import * as React from 'react'; import classNames from 'classnames'; import { Flex } from '../Flex'; import { IconCheck, IconIndeterminate } from '../Icon/internal'; import { Input } from '../Input'; import { Text } from '../Text'; import { VisuallyHidden } from '../VisuallyHidden'; import { BaseCheckboxProps, CheckboxProps } from '../types/checkbox'; import { ForwardRefPrimitive, Primitive } from '../types/view'; import { getTestId } from '../utils/getTestId'; import { useStableId } from '../utils/useStableId'; import { useCheckbox } from './useCheckbox'; import { ComponentClassNames } from '../shared/constants'; import { splitPrimitiveProps } from '../utils/splitPrimitiveProps'; import { classNameModifierByFlag } from '../shared/utils'; const CheckboxPrimitive: Primitive = ( { checked, className, defaultChecked, hasError, isDisabled, isIndeterminate, label, labelHidden, labelPosition, onChange: onChangeProp, testId, inputStyles, ..._rest }, ref ) => { const { styleProps, rest } = splitPrimitiveProps(_rest); // controlled way should always override uncontrolled way const initialChecked = checked !== undefined ? checked : defaultChecked; const { dataChecked, dataFocus, onBlur, onChange, onFocus, setDataChecked } = useCheckbox(initialChecked, onChangeProp); React.useEffect(() => { const isControlled = checked !== undefined; if (isControlled && checked !== dataChecked) { setDataChecked(checked); } }, [checked, dataChecked, setDataChecked]); const dataId = useStableId(); React.useEffect(() => { const input = document.querySelector(`[data-id="${dataId}"]`); if (input && typeof isIndeterminate === 'boolean') { // HTMLInputElement does not have an `indeterminate` attribute (input as HTMLInputElement & { indeterminate: boolean }).indeterminate = isIndeterminate; } }, [dataId, isIndeterminate]); const buttonTestId = getTestId(testId, ComponentClassNames.CheckboxButton); const iconTestId = getTestId(testId, ComponentClassNames.CheckboxIcon); const labelTestId = getTestId(testId, ComponentClassNames.CheckboxLabel); const flexClasses = classNames( ComponentClassNames.CheckboxButton, classNameModifierByFlag( ComponentClassNames.CheckboxButton, 'disabled', isDisabled ), classNameModifierByFlag( ComponentClassNames.CheckboxButton, 'error', hasError ), classNameModifierByFlag( ComponentClassNames.CheckboxButton, 'focused', dataFocus ) ); const iconClasses = classNames( ComponentClassNames.CheckboxIcon, classNameModifierByFlag( ComponentClassNames.CheckboxIcon, 'checked', dataChecked ), classNameModifierByFlag( ComponentClassNames.CheckboxIcon, 'disabled', isDisabled ) ); const renderedIcon = React.useMemo( () => isIndeterminate ? ( ) : ( ), [dataChecked, iconClasses, iconTestId, isDisabled, isIndeterminate] ); return ( {label && ( {label} )} ); }; export const Checkbox: ForwardRefPrimitive = React.forwardRef(CheckboxPrimitive); Checkbox.displayName = 'Checkbox';