|
|
'use client'; import React from 'react'; import { createRadio } from '@gluestack-ui/radio'; import { Pressable, View, Platform, Text } from 'react-native'; import { tva } from '@gluestack-ui/nativewind-utils/tva'; import { withStyleContext, useStyleContext, } from '@gluestack-ui/nativewind-utils/withStyleContext'; import { cssInterop } from 'nativewind'; import type { VariantProps } from '@gluestack-ui/nativewind-utils'; import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon';
const SCOPE = 'Radio';
const UIRadio = createRadio({ Root: (Platform.OS === 'web' ? withStyleContext(View, SCOPE) : withStyleContext(Pressable, SCOPE)) as ReturnType< typeof withStyleContext<typeof Pressable> >, Group: View, Icon: UIIcon, Indicator: View, Label: Text, });
cssInterop(PrimitiveIcon, { className: { target: 'style', nativeStyleToProp: { height: true, width: true, fill: true, color: 'classNameColor', stroke: true, }, }, });
const radioStyle = tva({ base: 'group/radio flex-row justify-start items-center web:cursor-pointer data-[disabled=true]:web:cursor-not-allowed', variants: { size: { sm: 'gap-1.5', md: 'gap-2', lg: 'gap-2', }, }, });
const radioGroupStyle = tva({ base: 'gap-2', });
const radioIconStyle = tva({ base: 'rounded-full justify-center items-center text-primary-800 fill-primary-800',
parentVariants: { size: { sm: 'h-[9px] w-[9px]', md: 'h-3 w-3', lg: 'h-4 w-4', }, }, });
const radioIndicatorStyle = tva({ base: 'justify-center items-center bg-transparent border-outline-400 border-2 rounded-full data-[focus-visible=true]:web:outline-2 data-[focus-visible=true]:web:outline-primary-700 data-[focus-visible=true]:web:outline data-[checked=true]:border-primary-600 data-[checked=true]:bg-transparent data-[hover=true]:border-outline-500 data-[hover=true]:bg-transparent data-[hover=true]:data-[checked=true]:bg-transparent data-[hover=true]:data-[checked=true]:border-primary-700 data-[hover=true]:data-[invalid=true]:border-error-700 data-[hover=true]:data-[disabled=true]:opacity-40 data-[hover=true]:data-[disabled=true]:border-outline-400 data-[hover=true]:data-[disabled=true]:data-[invalid=true]:border-error-400 data-[active=true]:bg-transparent data-[active=true]:border-primary-800 data-[invalid=true]:border-error-700 data-[disabled=true]:opacity-40 data-[disabled=true]:data-[checked=true]:border-outline-400 data-[disabled=true]:data-[checked=true]:bg-transparent data-[disabled=true]:data-[invalid=true]:border-error-400', parentVariants: { size: { sm: 'h-4 w-4', md: 'h-5 w-5', lg: 'h-6 w-6', }, }, });
const radioLabelStyle = tva({ base: 'text-typography-600 data-[checked=true]:text-typography-900 data-[hover=true]:text-typography-900 data-[hover=true]:data-[disabled=true]:text-typography-600 data-[hover=true]:data-[disabled=true]:data-[checked=true]:text-typography-900 data-[active=true]:text-typography-900 data-[active=true]:data-[checked=true]:text-typography-900 data-[disabled=true]:opacity-40 web:select-none', parentVariants: { size: { '2xs': 'text-2xs', 'xs': 'text-xs', 'sm': 'text-sm', 'md': 'text-base', 'lg': 'text-lg', 'xl': 'text-xl', '2xl': 'text-2xl', '3xl': 'text-3xl', '4xl': 'text-4xl', '5xl': 'text-5xl', '6xl': 'text-6xl', }, }, });
type IRadioProps = Omit<React.ComponentProps<typeof UIRadio>, 'context'> & VariantProps<typeof radioStyle>; const Radio = React.forwardRef<React.ComponentRef<typeof UIRadio>, IRadioProps>( function Radio({ className, size = 'md', ...props }, ref) { return ( <UIRadio className={radioStyle({ class: className, size })} {...props} ref={ref} context={{ size }} /> ); } );
type IRadioGroupProps = React.ComponentProps<typeof UIRadio.Group> & VariantProps<typeof radioGroupStyle>; const RadioGroup = React.forwardRef< React.ComponentRef<typeof UIRadio.Group>, IRadioGroupProps >(function RadioGroup({ className, ...props }, ref) { return ( <UIRadio.Group className={radioGroupStyle({ class: className })} {...props} ref={ref} /> ); });
type IRadioIndicatorProps = React.ComponentProps<typeof UIRadio.Indicator> & VariantProps<typeof radioIndicatorStyle>; const RadioIndicator = React.forwardRef< React.ComponentRef<typeof UIRadio.Indicator>, IRadioIndicatorProps >(function RadioIndicator({ className, ...props }, ref) { const { size } = useStyleContext(SCOPE); return ( <UIRadio.Indicator className={radioIndicatorStyle({ parentVariants: { size }, class: className, })} ref={ref} {...props} /> ); });
type IRadioLabelProps = React.ComponentProps<typeof UIRadio.Label> & VariantProps<typeof radioIndicatorStyle>; const RadioLabel = React.forwardRef< React.ComponentRef<typeof UIRadio.Label>, IRadioLabelProps >(function RadioLabel({ className, ...props }, ref) { const { size } = useStyleContext(SCOPE); return ( <UIRadio.Label className={radioLabelStyle({ parentVariants: { size }, class: className, })} ref={ref} {...props} /> ); });
type IRadioIconProps = React.ComponentProps<typeof UIRadio.Icon> & VariantProps<typeof radioIconStyle> & { height?: number; width?: number; }; const RadioIcon = React.forwardRef< React.ComponentRef<typeof UIRadio.Icon>, IRadioIconProps >(function RadioIcon({ className, size, ...props }, ref) { const { size: parentSize } = useStyleContext(SCOPE);
if (typeof size === 'number') { return ( <UIRadio.Icon ref={ref} {...props} className={radioIconStyle({ class: className })} size={size} /> ); } else if ( (props.height !== undefined || props.width !== undefined) && size === undefined ) { return ( <UIRadio.Icon ref={ref} {...props} className={radioIconStyle({ class: className })} /> ); }
return ( <UIRadio.Icon {...props} className={radioIconStyle({ parentVariants: { size: parentSize, }, size, class: className, })} ref={ref} /> ); });
Radio.displayName = 'Radio'; RadioGroup.displayName = 'RadioGroup'; RadioIndicator.displayName = 'RadioIndicator'; RadioLabel.displayName = 'RadioLabel'; RadioIcon.displayName = 'RadioIcon';
export { Radio, RadioGroup, RadioIndicator, RadioLabel, RadioIcon };
|