import React, { useContext, memo, forwardRef } from 'react'; import { mergeRefs } from './../../../utils'; import { usePropsResolution } from '../../../hooks/useThemeProps'; import { Center } from '../../composites/Center'; import { useFormControlContext } from '../../composites/FormControl'; import Box from '../Box'; import type { ICheckboxProps } from './types'; import { useToggleState } from '@react-stately/toggle'; import { VisuallyHidden } from '@react-aria/visually-hidden'; import { CheckboxGroupContext } from './CheckboxGroup'; import { useHover } from '@react-native-aria/interactions'; import { useCheckbox, useCheckboxGroupItem } from '@react-native-aria/checkbox'; import { useFocusRing } from '@react-native-aria/focus'; import { CheckIcon } from '../Icon/Icons'; const Checkbox = ( { children, icon, wrapperRef, ...props }: ICheckboxProps, ref: any ) => { const formControlContext = useFormControlContext(); const checkboxGroupContext = React.useContext(CheckboxGroupContext); const { _interactionBox: { _hover: _iterationBoxHover, _focus: _iterationBoxFocus, _disabled: _iterationBoxDisabled, ..._interactionBox }, _checkbox: { _checked: _checkboxChecked, _disabled: _checkboxDisabled, _invalid: _checkboxInvalid, ..._checkbox }, _icon, isInvalid, ...themedProps } = usePropsResolution('Checkbox', { ...checkboxGroupContext, ...formControlContext, ...props, }); const _ref = React.useRef(); const mergedRef = mergeRefs([ref, _ref]); const state = useToggleState({ ...props, defaultSelected: props.defaultIsChecked, isSelected: props.isChecked, }); const groupState = useContext(CheckboxGroupContext); const { isHovered } = useHover({}, _ref); // Swap hooks depending on whether this checkbox is inside a CheckboxGroup. // This is a bit unorthodox. Typically, hooks cannot be called in a conditional, // but since the checkbox won't move in and out of a group, it should be safe. const { inputProps } = groupState ? // eslint-disable-next-line react-hooks/rules-of-hooks useCheckboxGroupItem( { ...themedProps, 'aria-label': themedProps.accessibilityLabel, 'value': themedProps.value, }, groupState.state, //@ts-ignore mergedRef ) : // eslint-disable-next-line react-hooks/rules-of-hooks useCheckbox( { ...themedProps, 'aria-label': themedProps.accessibilityLabel }, state, //@ts-ignore mergedRef ); const { checked, disabled } = inputProps; const sizedIcon = icon ? () => React.cloneElement( icon, { ..._icon, }, icon.props.children ) : null; const { focusProps, isFocusVisible } = useFocusRing(); const component = (
{/* Interaction Box */} {/* Checkbox */}
{icon && sizedIcon && checked ? ( sizedIcon() ) : ( )}
{children}
); return ( {component} ); }; export default memo(forwardRef(Checkbox));