import React, { memo, forwardRef } from 'react';
//@ts-ignore
import stableHash from 'stable-hash';
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 { useHasResponsiveProps } from '../../../hooks/useHasResponsiveProps';
import { extractInObject, stylingProps } from '../../../theme/tools/utils';
import { combineContextAndProps } from '../../../utils';
import SizedIcon from './SizedIcon';
import { Stack } from '../Stack';
import { wrapStringChild } from '../../../utils/wrapStringChild';
const Checkbox = (
{
wrapperRef,
isHovered: isHoveredProp,
isFocusVisible: isFocusVisibleProp,
...props
}: ICheckboxProps,
ref: any
) => {
const formControlContext = useFormControlContext();
const {
isInvalid,
isReadOnly,
isIndeterminate,
...combinedProps
} = combineContextAndProps(formControlContext, props);
const checkboxGroupContext = React.useContext(CheckboxGroupContext);
const state = useToggleState({
...props,
defaultSelected: props.defaultIsChecked,
isSelected: props.isChecked,
});
const _ref = React.useRef();
const mergedRef = mergeRefs([ref, _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: groupItemInputProps } = checkboxGroupContext
? // eslint-disable-next-line react-hooks/rules-of-hooks
useCheckboxGroupItem(
{
...combinedProps,
'aria-label': combinedProps.accessibilityLabel,
'value': combinedProps.value,
},
checkboxGroupContext.state,
//@ts-ignore
mergedRef
)
: // eslint-disable-next-line react-hooks/rules-of-hooks
useCheckbox(
{
...combinedProps,
'aria-label': combinedProps.accessibilityLabel,
},
state,
//@ts-ignore
mergedRef
);
// eslint-disable-next-line react-hooks/exhaustive-deps
const inputProps = React.useMemo(() => groupItemInputProps, [
groupItemInputProps.checked,
groupItemInputProps.disabled,
groupItemInputProps,
]);
const contextCombinedProps = React.useMemo(() => {
return { ...checkboxGroupContext, ...combinedProps };
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [stableHash(combinedProps)]);
return (
);
};
const CheckboxComponent = React.memo(
({
wrapperRef,
inputProps,
combinedProps,
isInvalid,
isReadOnly,
isIndeterminate,
mergedRef,
isHovered: isHoveredProp,
isFocusVisible: isFocusVisibleProp,
}: any) => {
const _ref = React.useRef();
const { isHovered } = useHover({}, _ref);
const { checked: isChecked, disabled: isDisabled } = inputProps;
const { focusProps, isFocusVisible } = useFocusRing();
const {
icon,
_interactionBox,
_icon,
_stack,
_text,
...resolvedProps
} = usePropsResolution('Checkbox', combinedProps, {
isInvalid,
isReadOnly,
isFocusVisible: isFocusVisibleProp || isFocusVisible,
isDisabled,
isIndeterminate,
isChecked,
isHovered: isHovered || isHoveredProp,
});
const [layoutProps, nonLayoutProps] = extractInObject(resolvedProps, [
...stylingProps.margin,
...stylingProps.layout,
...stylingProps.flexbox,
...stylingProps.position,
'_text',
]);
const component = React.useMemo(() => {
return (
{/* Interaction Box */}
{/* Checkbox */}
{/* {iconResolver()} */}
{/* Label */}
{/* {resolvedProps?.children} */}
{wrapStringChild(resolvedProps?.children, _text)}
);
}, [
_icon,
_stack,
_text,
_interactionBox,
icon,
isChecked,
nonLayoutProps,
layoutProps,
resolvedProps?.children,
]);
const mergedWrapperRef = React.useMemo(
() => mergeRefs([wrapperRef, _ref]),
[wrapperRef]
);
//TODO: refactor for responsive prop
if (useHasResponsiveProps(resolvedProps)) {
return null;
}
return (
{/* */}
{component}
);
}
);
export default memo(forwardRef(Checkbox));