UNPKG

@gluestack-ui/checkbox

Version:

A universal headless Checkbox component for React Native, Next.js & React

86 lines (85 loc) 4.69 kB
import React, { forwardRef, useContext } from 'react'; import { CheckboxProvider } from './CheckboxProvider'; import { useFocusRing } from '@react-native-aria/focus'; import { useHover } from '@react-native-aria/interactions'; import { useToggleState } from '@react-stately/toggle'; import { useCheckbox, useCheckboxGroupItem } from '@react-native-aria/checkbox'; import { CheckboxGroupContext } from './CheckboxGroup'; import { combineContextAndProps, mergeRefs, stableHash, } from '@gluestack-ui/utils'; import { useFormControlContext } from '@gluestack-ui/form-control'; import { VisuallyHidden } from '@react-aria/visually-hidden'; export const Checkbox = (StyledCheckbox) => forwardRef(({ children, ...props }, ref) => { const { isHovered: isHoveredProp, isFocusVisible: isFocusVisibleProp, isChecked: isCheckedProp, isDisabled: isDisabledProp, isInvalid: isInvalidProp, isReadOnly: isReadOnlyProp, isIndeterminate: isIndeterminateProp, isFocused, isPressed, } = props; const formControlContext = useFormControlContext(); const { isInvalid, isReadOnly, isIndeterminate, ...combinedProps } = combineContextAndProps(formControlContext, props); const checkboxGroupContext = useContext(CheckboxGroupContext); const state = useToggleState({ ...combinedProps, defaultSelected: props.defaultIsChecked, isSelected: isCheckedProp, }); //aria-state-hook const _ref = React.useRef(null); const { isHovered } = useHover({}, _ref); const { focusProps, isFocusVisible } = useFocusRing(); const ariaLabel = combinedProps['aria-label'] || combinedProps.value || 'Checkbox'; const mergedRef = mergeRefs([ref, _ref]); const { inputProps: groupItemInputProps } = checkboxGroupContext ? // eslint-disable-next-line react-hooks/rules-of-hooks useCheckboxGroupItem({ ...combinedProps, 'aria-label': ariaLabel, 'value': combinedProps.value, }, checkboxGroupContext.state, //@ts-ignore mergedRef) : // eslint-disable-next-line react-hooks/rules-of-hooks useCheckbox({ ...combinedProps, 'aria-label': ariaLabel, }, state, //@ts-ignore mergedRef); const inputProps = React.useMemo(() => groupItemInputProps, // eslint-disable-next-line react-hooks/exhaustive-deps [ groupItemInputProps.checked, groupItemInputProps.disabled, groupItemInputProps, ]); const contextCombinedProps = React.useMemo(() => { return { ...checkboxGroupContext, ...combinedProps }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [stableHash(combinedProps)]); const { checked: isChecked, disabled: isDisabled } = inputProps; return (<StyledCheckbox {...contextCombinedProps} role="label" // remove in future, role="label" is not supported in react-native-web, PR is open accessibilityRole="label" ref={mergedRef} states={{ checked: isChecked || isCheckedProp, disabled: isDisabled || isDisabledProp, hover: isHovered || isHoveredProp, invalid: isInvalid || isInvalidProp, readonly: isReadOnly || isReadOnlyProp, active: isPressed, focus: isFocused, indeterminate: isIndeterminate || isIndeterminateProp, focusVisible: isFocusVisible || isFocusVisibleProp, }} dataSet={{ checked: isChecked || isCheckedProp ? 'true' : 'false', disabled: isDisabled || isDisabledProp ? 'true' : 'false', hover: isHovered || isHoveredProp ? 'true' : 'false', invalid: isInvalid || isInvalidProp ? 'true' : 'false', readonly: isReadOnly || isReadOnlyProp ? 'true' : 'false', active: isPressed ? 'true' : 'false', focus: isFocused ? 'true' : 'false', indeterminate: isIndeterminate || isIndeterminateProp ? 'true' : 'false', focusVisible: isFocusVisible || isFocusVisibleProp ? 'true' : 'false', }}> <CheckboxProvider isChecked={isChecked || isCheckedProp} isDisabled={isDisabled || isDisabledProp} isFocusVisible={isFocusVisible || isFocusVisibleProp} isHovered={isHovered || isHoveredProp} isInvalid={isInvalid || isInvalidProp} isReadOnly={isReadOnly || isReadOnlyProp} isIndeterminate={isIndeterminate || isIndeterminateProp} isPressed={isPressed}> <VisuallyHidden> <input {...inputProps} {...focusProps} ref={mergedRef}/> </VisuallyHidden> {children} </CheckboxProvider> </StyledCheckbox>); });