import { CSSProperties, ReactNode, useContext, useState, useEffect, } from 'react' import classNames from 'classnames' import { CheckboxGroup, CheckboxGroupContext } from './CheckboxGroup' import { CommonComponentProps } from '../../utils/types' import { Icon } from '../icon/Icon' import './Checkbox.scss' export * from './CheckboxGroup' export interface CheckboxProps extends CommonComponentProps { className?: string style?: CSSProperties children?: ReactNode checked?: boolean defaultChecked?: boolean value?: any disabled?: boolean size?: string type?: 'square' | 'circle' icon?: (checked: boolean) => ReactNode checkedColor?: string onChange?: (checked: boolean, value: any) => any onClick?: () => any } const typeIconMap = { square: ['square', 'check-square-fill'], circle: ['circle', 'check-circle-fill'], } export function Checkbox(props: CheckboxProps) { const { className, children, checked, defaultChecked, value = '', disabled = false, size, type = 'square', onChange, onClick, icon, checkedColor, ...restProps } = props const context = useContext(CheckboxGroupContext) const [innerChecked, setInnerChecked] = useState( checked ?? defaultChecked ?? false ) // 受控 useEffect(() => { if (checked != null) { setInnerChecked(checked) } }, [checked]) const isChecked = context ? context.value.includes(value) : innerChecked === true const toggle = () => { if (context) { const groupValue = isChecked ? context.value.filter((item) => item !== value) : context.value.concat(value) onChange?.(!isChecked, value) context.onChange(groupValue) } else { // 非受控 if (checked == null) { setInnerChecked(!innerChecked) } onChange?.(!innerChecked, value) } } const handleCheckboxClick = () => { if (!disabled) { toggle() } onClick?.() } const iconStyle = { fontSize: size, color: isChecked ? checkedColor : '', } const checkboxClass = classNames( 's-checkbox', { 's-checkbox-checked': isChecked, 's-checkbox-disabled': disabled, }, className ) return (
{icon ? ( icon(isChecked) ) : ( )}
{children &&
{children}
}
) } Checkbox.Group = CheckboxGroup export default Checkbox