import type { DCloneHTMLElement } from '../../utils/types';
import type { DFormControl } from '../form';
import { isUndefined } from 'lodash';
import { checkNodeExist, getClassName } from '@react-devui/utils';
import { useGeneralContext, useDValue } from '../../hooks';
import { registerComponentMate } from '../../utils';
import { DBaseInput } from '../_base-input';
import { useFormControl } from '../form';
import { useComponentConfig, usePrefixConfig } from '../root';
import { DCheckboxGroup } from './CheckboxGroup';
import { DCheckboxGroupRenderer } from './CheckboxGroupRenderer';
export interface DCheckboxProps extends React.HTMLAttributes<HTMLElement> {
dRef?: {
input?: React.ForwardedRef<HTMLInputElement>;
};
dFormControl?: DFormControl;
dModel?: boolean;
dDisabled?: boolean;
dIndeterminate?: boolean;
dInputRender?: DCloneHTMLElement<React.InputHTMLAttributes<HTMLInputElement>>;
onModelChange?: (checked: boolean) => void;
}
const { COMPONENT_NAME } = registerComponentMate({ COMPONENT_NAME: 'DCheckbox' as const });
export const DCheckbox: {
(props: DCheckboxProps): JSX.Element | null;
Group: typeof DCheckboxGroup;
GroupRenderer: typeof DCheckboxGroupRenderer;
} = (props) => {
const {
children,
dRef,
dFormControl,
dModel,
dDisabled = false,
dIndeterminate = false,
dInputRender,
onModelChange,
...restProps
} = useComponentConfig(COMPONENT_NAME, props);
const dPrefix = usePrefixConfig();
const { gDisabled } = useGeneralContext();
const formControlInject = useFormControl(dFormControl);
const [checked, changeChecked] = useDValue<boolean | undefined, boolean>(
false,
dIndeterminate ? false : dModel,
onModelChange,
undefined,
formControlInject
);
const disabled = dDisabled || gDisabled || dFormControl?.control.disabled;
return (
<label
{...restProps}
className={getClassName(restProps.className, `${dPrefix}checkbox`, {
'is-indeterminate': dIndeterminate,
'is-checked': checked,
'is-disabled': disabled,
})}
>
<div className={`${dPrefix}checkbox__state-container-wrapper`}>
<div className={`${dPrefix}checkbox__state-container`}>
<DBaseInput dFormControl={dFormControl} dLabelFor>
{({ render: renderBaseInput }) => {
const input = renderBaseInput(
<input
ref={dRef?.input}
className={`${dPrefix}checkbox__input`}
type="checkbox"
disabled={disabled}
aria-checked={dIndeterminate ? 'mixed' : checked}
onChange={() => {
changeChecked(!checked);
}}
/>
);
return isUndefined(dInputRender) ? input : dInputRender(input);
}}
</DBaseInput>
{dIndeterminate ? (
<div className={`${dPrefix}checkbox__indeterminate`}></div>
) : (
checked && <div className={`${dPrefix}checkbox__tick`}></div>
)}
</div>
</div>
{checkNodeExist(children) && <div className={`${dPrefix}checkbox__label`}>{children}</div>}
</label>
);
};
DCheckbox.Group = DCheckboxGroup;
DCheckbox.GroupRenderer = DCheckboxGroupRenderer;