forked from mrzachnugent/react-native-reusables
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathradio-group.tsx
130 lines (119 loc) · 3.03 KB
/
radio-group.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import React from 'react';
import { GestureResponderEvent, Pressable, View } from 'react-native';
import { cn } from '~/lib/utils';
import { Label } from './label';
interface RadioGroupProps {
defaultValue?: string;
onValueChange?: (val: string) => void;
disabled?: boolean;
}
interface RadioGroupContext {
value: string;
setValue: React.Dispatch<React.SetStateAction<string>>;
onValueChange?: (val: string) => void;
disabled: boolean;
}
const RadioGroupContext = React.createContext({} as RadioGroupContext);
const RadioGroup = React.forwardRef<
React.ElementRef<typeof View>,
React.ComponentPropsWithoutRef<typeof View> & RadioGroupProps
>(
(
{ defaultValue = '', onValueChange, className, disabled = false, ...props },
ref
) => {
const [value, setValue] = React.useState(defaultValue);
return (
<RadioGroupContext.Provider
value={{
value,
setValue,
disabled,
onValueChange,
}}
>
<View
role='radiogroup'
ref={ref}
className={cn('gap-2', className)}
{...props}
/>
</RadioGroupContext.Provider>
);
}
);
RadioGroup.displayName = 'RadioGroup';
function useRadioGroupContext() {
const context = React.useContext(RadioGroupContext);
if (!context) {
throw new Error(
'RadioGroup compound components cannot be rendered outside the RadioGroup component'
);
}
return context;
}
const RadioGroupItem = React.forwardRef<
React.ElementRef<typeof Pressable>,
Omit<React.ComponentPropsWithoutRef<typeof Pressable>, 'disabled'> & {
name: string;
labelClass?: string;
buttonClass?: string;
innerButtonClass?: string;
children?: string;
}
>(
(
{
className,
name,
labelClass,
buttonClass,
innerButtonClass,
onPress,
children,
...props
},
ref
) => {
const { value, setValue, disabled, onValueChange } = useRadioGroupContext();
function handleOnPress(ev: GestureResponderEvent) {
setValue(name);
onValueChange?.(name);
onPress?.(ev);
}
return (
<View className={cn('flex-row gap-3 items-center', className)}>
<Pressable
disabled={disabled}
onPress={handleOnPress}
className={cn(
'h-6 w-6 border-primary [borderWidth:1.5] rounded-full items-center justify-center',
buttonClass
)}
aria-labelledby={name}
accessibilityState={{ selected: value === name }}
role='radio'
{...props}
>
{value === name && (
<View
ref={ref}
className={cn(
'h-3 w-3 bg-primary rounded-full',
innerButtonClass
)}
/>
)}
</Pressable>
<Label
onPress={handleOnPress}
className={cn('text-xl', labelClass)}
nativeID={name}
>
{children}
</Label>
</View>
);
}
);
export { RadioGroup, RadioGroupItem };