-
Notifications
You must be signed in to change notification settings - Fork 52
/
RadioGroup.tsx
90 lines (80 loc) · 2.34 KB
/
RadioGroup.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
import { Circle, CircleDot } from 'lucide-react-native';
import { createContext, useContext, useState } from 'react';
import { Text, TouchableOpacity, useColorScheme } from 'react-native';
import { cn } from '../lib/utils';
import { theme } from '../styles/theme';
interface RadioGroupContextType {
value: string;
setValue: (value: string) => void;
}
const RadioGroupContext = createContext<RadioGroupContextType | undefined>(
undefined
);
interface RadioGroupProps {
defaultValue: string;
children: React.ReactNode;
}
function RadioGroup({ defaultValue, children }: RadioGroupProps) {
const [value, setValue] = useState<string>(defaultValue);
return (
<RadioGroupContext.Provider value={{ value, setValue }}>
{children}
</RadioGroupContext.Provider>
);
}
interface RadioGroupItemProps
extends React.ComponentPropsWithoutRef<typeof TouchableOpacity> {
value: string;
label?: string;
labelClasses?: string;
}
function RadioGroupItem({
value,
className,
label,
labelClasses,
...props
}: RadioGroupItemProps) {
const context = useContext(RadioGroupContext);
if (!context) {
throw new Error('RadioGroupItem must be used within a RadioGroup');
}
const { value: selectedValue, setValue } = context;
const colorScheme = useColorScheme();
const currentTheme = colorScheme === 'dark' ? theme.dark : theme.light;
return (
<TouchableOpacity
onPress={() => setValue(value)}
className={cn('flex flex-row items-center gap-2', className)}
{...props}
>
{selectedValue === value ? (
<CircleDot color={currentTheme.foreground} />
) : (
<Circle color={currentTheme.foreground} />
)}
{label && (
<Text className={cn('text-primary', labelClasses)}>{label}</Text>
)}
</TouchableOpacity>
);
}
interface RadioGroupLabelProps
extends React.ComponentPropsWithoutRef<typeof TouchableOpacity> {
value: string;
}
function RadioGroupLabel({ value, className, ...props }: RadioGroupLabelProps) {
const context = useContext(RadioGroupContext);
if (!context) {
throw new Error('RadioGroupLabel must be used within a RadioGroup');
}
const { setValue } = context;
return (
<TouchableOpacity
className={className}
onPress={() => setValue(value)}
{...props}
/>
);
}
export { RadioGroup, RadioGroupItem, RadioGroupLabel };