import cx from 'classnames'; import { useCallback, useContext, useRef } from 'react'; import getWidth from '../utils/getWidth'; import GroupContext, { ICheckboxContext } from './GroupContext'; import { DisabledContext, IDisabledContext } from '../disabled'; import CheckboxGroup from './Group'; export interface ICheckboxEventTarget extends ICheckboxProps { type: 'checkbox'; checked: boolean; } export interface ICheckboxEvent { target: ICheckboxEventTarget; preventDefault(): void; stopPropagation(): void; } export interface ICheckboxProps { checked?: boolean; value?: Value; disabled?: boolean; readOnly?: boolean; indeterminate?: boolean; onChange?: (e: ICheckboxEvent) => void; className?: string; style?: React.CSSProperties; labelStyle?: React.CSSProperties; width?: number; children?: React.ReactNode; onMouseEnter?: React.MouseEventHandler; onMouseLeave?: React.MouseEventHandler; } function getDisabled( disabledCtx: IDisabledContext, groupCtx: ICheckboxContext | null, props: ICheckboxProps ) { if (typeof props.disabled === 'boolean') { return props.disabled; } if (groupCtx) { return groupCtx.disabled; } return disabledCtx.value; } function getReadOnly( groupCtx: ICheckboxContext | null, props: ICheckboxProps ) { if (typeof props.readOnly === 'boolean') { return props.readOnly; } if (groupCtx) { return groupCtx.readOnly; } return false; } export function Checkbox(props: ICheckboxProps) { const disabledCtx = useContext(DisabledContext); const groupCtx = useContext(GroupContext); const propsRef = useRef(props); propsRef.current = props; const ctxOnChange = groupCtx && groupCtx.onChange; const onChange: React.ChangeEventHandler = useCallback( evt => { const { value, onChange } = propsRef.current; if (ctxOnChange) { ctxOnChange(value); return; } else if (onChange) { const e: ICheckboxEvent = Object.create(evt); e.target = { ...propsRef.current, type: 'checkbox', checked: evt.target.checked, }; onChange(e); } }, [ctxOnChange] ); const { checked: _3, className, style, disabled: _1, readOnly: _2, children, indeterminate, width, // value可以是任意类型,不要写到dom上去 value, labelStyle, onMouseEnter, onMouseLeave, ...others } = props; const readOnly = getReadOnly(groupCtx, props); const disabled = getDisabled(disabledCtx, groupCtx, props); let checked: boolean; if (groupCtx) { const { value, isValueEqual } = groupCtx; checked = value.findIndex(it => isValueEqual(it, props.value)) !== -1; } else { checked = !!props.checked; } return ( ); } Checkbox.Group = CheckboxGroup; export default Checkbox;