import React, { memo, forwardRef } from 'react';
//@ts-ignore
import stableHash from 'stable-hash';
import Box from '../Box';
import { Stack } from '../Stack';
import { Center } from '../../composites/Center';
import { usePropsResolution } from '../../../hooks/useThemeProps';
import { wrapStringChild } from '../../../utils/wrapStringChild';
import type { IRadioProps } from './types';
import { mergeRefs } from './../../../utils';
import { useHover } from '@react-native-aria/interactions';
import { useRadio } from '@react-native-aria/radio';
import { VisuallyHidden } from '@react-aria/visually-hidden';
import { RadioContext } from './RadioGroup';
import { useFocusRing } from '@react-native-aria/focus';
import { CircleIcon } from '../Icon/Icons';
import { useHasResponsiveProps } from '../../../hooks/useHasResponsiveProps';
import { combineContextAndProps, isEmptyObj } from '../../../utils';
import { useFormControlContext } from '../../composites/FormControl';
const RadioComponent = memo(
forwardRef(
(
{
icon,
inputProps,
combinedProps,
children,
wrapperRef,
isHovered: isHoveredProp,
isPressed: isPressedProp,
isFocused: isFocusedProp,
isFocusVisible: isFocusVisibleProp,
...props
}: any,
ref: any
) => {
const { isInvalid, isReadOnly, isIndeterminate } = combinedProps;
const { disabled: isDisabled, checked: isChecked } = inputProps;
const _ref = React.useRef(null);
const { isHovered } = useHover({}, _ref);
const mergedRefs = mergeRefs([_ref, wrapperRef]);
const { focusProps, isFocusVisible } = useFocusRing();
const [isFocused, setFocused] = React.useState(isFocusedProp);
const [isPressed, setPressed] = React.useState(isPressedProp);
const handleFocus = () => {
setFocused(true);
};
const handleBlur = () => {
isFocusedProp ? setFocused(true) : setFocused(false);
};
const handlePressIn = () => {
setPressed(true);
};
const handlePressOut = () => {
isPressedProp ? setPressed(true) : setPressed(false);
};
const {
_interactionBox,
_icon,
_stack,
_text,
...resolvedProps
} = usePropsResolution('Radio', combinedProps, {
isInvalid,
isReadOnly,
isFocusVisible: isFocusVisibleProp || isFocused || isFocusVisible,
isDisabled,
isIndeterminate,
isChecked,
isHovered: isHoveredProp || isHovered,
isPressed,
isFocused,
});
// only calling below function when icon exist.
const sizedIcon = () =>
//@ts-ignore
React.cloneElement(icon, {
..._icon,
});
const component = (
{/* Interaction Box */}
{/* Radio */}
{icon && sizedIcon && isChecked ? (
sizedIcon()
) : (
)}
{wrapStringChild(children, _text)}
);
//TODO: refactor for responsive prop
if (useHasResponsiveProps(props)) {
return null;
}
return (
{component}
);
}
)
);
const Radio = (
{
icon,
children,
wrapperRef,
isHovered: isHoveredProp,
isPressed,
isFocused: isFocusedProp,
isFocusVisible: isFocusVisibleProp,
...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
);
//@ts-ignore
// 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));