import React, { memo, forwardRef } from 'react'; //@ts-ignore import stableHash from 'stable-hash'; import { Pressable, IPressableProps } from '../Pressable'; import { Center } from '../../composites/Center'; import Box from '../Box'; import { Stack } from '../Stack'; import { usePropsResolution } from '../../../hooks/useThemeProps'; import { wrapStringChild } from '../../../utils/wrapStringChild'; import type { IRadioProps } from './types'; import { useRadio } from '@react-native-aria/radio'; import { RadioContext } from './RadioGroup'; import { mergeRefs } from '../../../utils'; import { CircleIcon } from '../Icon/Icons'; import { useHasResponsiveProps } from '../../../hooks/useHasResponsiveProps'; import { composeEventHandlers, combineContextAndProps, isEmptyObj, } from '../../../utils'; import { extractInObject, stylingProps } from '../../../theme/tools/utils'; import { useHover, useFocus, useIsPressed, } from '../../primitives/Pressable/Pressable'; import { useFormControlContext } from '../../composites/FormControl'; const RadioComponent = memo( forwardRef( ( { icon, inputProps, combinedProps, size, children, wrapperRef, isHovered: isHoveredProp, isPressed: isPressedProp, isFocused: isFocusedProp, }: any, ref: any ) => { const { isInvalid, isReadOnly, isIndeterminate } = combinedProps; const { hoverProps, isHovered } = useHover(); const { pressableProps, isPressed } = useIsPressed(); const { focusProps, isFocused } = useFocus(); const { disabled: isDisabled, checked: isChecked } = inputProps; const { onPressIn, onPressOut, onHoverIn, onHoverOut, onFocus, onBlur, _interactionBox, _icon, _stack, _text, ...resolvedProps } = usePropsResolution( 'Radio', { ...combinedProps, size, }, { isInvalid, isReadOnly, isDisabled, isIndeterminate, isChecked, isHovered: isHoveredProp || isHovered, isPressed: isPressedProp || isPressed, isFocused: isFocusedProp || isFocused, } ); const [, cleanInputProps] = extractInObject(inputProps, [ ...stylingProps.margin, ...stylingProps.layout, ...stylingProps.flexbox, ...stylingProps.position, ...stylingProps.background, ...stylingProps.padding, ...stylingProps.border, '_text', ]); // only calling below function when icon exist. const sizedIcon = () => //@ts-ignore React.cloneElement(icon, { ..._icon, }); return (
{/* Interaction Wrapper */} {/* radio */}
{icon && sizedIcon && isChecked ? ( sizedIcon() ) : ( )}
{/* Label */} {wrapStringChild(children, _text)}
); } ) ); const Radio = ( { icon, children, size, wrapperRef, isHovered: isHoveredProp, isPressed: isPressedProp, isFocused: isFocusedProp, ...props }: IRadioProps, ref: any ) => { const formControlContext = useFormControlContext(); const contextState = React.useContext(RadioContext); const combinedProps = combineContextAndProps( { ...formControlContext, ...contextState }, props ); const inputRef = React.useRef(null); const radioState = useRadio( { ...combinedProps, 'aria-label': props.accessibilityLabel, children }, contextState.state ?? {}, inputRef ); // eslint-disable-next-line react-hooks/exhaustive-deps const inputProps = React.useMemo(() => radioState.inputProps, [ radioState.inputProps.checked, radioState.inputProps.disabled, ]); const contextCombinedProps = React.useMemo(() => { return { ...combinedProps }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [stableHash(combinedProps)]); //TODO: refactor for responsive prop if (useHasResponsiveProps(props)) { return null; } if (isEmptyObj(contextState)) { console.error('Error: Radio must be wrapped inside a Radio.Group'); return <>; } return ( ); }; export default memo(forwardRef(Radio));