@lunar-kit/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +5 -0
- package/dist/index.js +14 -0
- package/package.json +31 -0
- package/src/components/ui/accordion.tsx +334 -0
- package/src/components/ui/avatar.tsx +326 -0
- package/src/components/ui/badge.tsx +84 -0
- package/src/components/ui/banner.tsx +151 -0
- package/src/components/ui/bottom-sheet.tsx +579 -0
- package/src/components/ui/button.tsx +142 -0
- package/src/components/ui/calendar.tsx +502 -0
- package/src/components/ui/card.tsx +163 -0
- package/src/components/ui/checkbox.tsx +129 -0
- package/src/components/ui/date-picker.tsx +190 -0
- package/src/components/ui/date-range-picker.tsx +262 -0
- package/src/components/ui/dialog.tsx +204 -0
- package/src/components/ui/form.tsx +139 -0
- package/src/components/ui/input.tsx +107 -0
- package/src/components/ui/radio-group.tsx +123 -0
- package/src/components/ui/radio.tsx +109 -0
- package/src/components/ui/select-sheet.tsx +814 -0
- package/src/components/ui/select.tsx +547 -0
- package/src/components/ui/tabs.tsx +254 -0
- package/src/components/ui/text.tsx +229 -0
- package/src/components/ui/textarea.tsx +77 -0
- package/src/components/v0/accordion.tsx +199 -0
- package/src/components/v1/accordion.tsx +234 -0
- package/src/components/v1/avatar.tsx +259 -0
- package/src/components/v1/bottom-sheet.tsx +1090 -0
- package/src/components/v1/button.tsx +61 -0
- package/src/components/v1/calendar.tsx +498 -0
- package/src/components/v1/card.tsx +86 -0
- package/src/components/v1/checkbox.tsx +46 -0
- package/src/components/v1/date-picker.tsx +135 -0
- package/src/components/v1/date-range-picker.tsx +218 -0
- package/src/components/v1/dialog.tsx +211 -0
- package/src/components/v1/radio-group.tsx +76 -0
- package/src/components/v1/select.tsx +217 -0
- package/src/components/v1/tabs.tsx +253 -0
- package/src/registry/ui/accordion.json +30 -0
- package/src/registry/ui/avatar.json +41 -0
- package/src/registry/ui/badge.json +26 -0
- package/src/registry/ui/banner.json +27 -0
- package/src/registry/ui/bottom-sheet.json +29 -0
- package/src/registry/ui/button.json +24 -0
- package/src/registry/ui/calendar.json +29 -0
- package/src/registry/ui/card.json +25 -0
- package/src/registry/ui/checkbox.json +25 -0
- package/src/registry/ui/date-picker.json +30 -0
- package/src/registry/ui/date-range-picker.json +33 -0
- package/src/registry/ui/dialog.json +25 -0
- package/src/registry/ui/form.json +27 -0
- package/src/registry/ui/input.json +22 -0
- package/src/registry/ui/radio-group.json +26 -0
- package/src/registry/ui/radio.json +23 -0
- package/src/registry/ui/select-sheet.json +29 -0
- package/src/registry/ui/select.json +26 -0
- package/src/registry/ui/tabs.json +29 -0
- package/src/registry/ui/text.json +22 -0
- package/src/registry/ui/textarea.json +24 -0
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
// components/ui/select.tsx
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Pressable, ScrollView, View } from 'react-native';
|
|
4
|
+
import { cn } from '@/lib/utils';
|
|
5
|
+
import { Text } from './text';
|
|
6
|
+
import { Dialog, DialogContent } from './dialog';
|
|
7
|
+
import { useThemeColors } from '@/hooks/useThemeColors';
|
|
8
|
+
import { ChevronDown, Check } from 'lucide-react-native';
|
|
9
|
+
|
|
10
|
+
interface SelectOption {
|
|
11
|
+
label: string;
|
|
12
|
+
value: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface SelectProps {
|
|
16
|
+
value?: string;
|
|
17
|
+
onValueChange?: (value: string) => void;
|
|
18
|
+
children: React.ReactNode;
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface SelectTriggerProps {
|
|
23
|
+
className?: string;
|
|
24
|
+
containerClassName?: string;
|
|
25
|
+
children?: React.ReactNode;
|
|
26
|
+
size?: 'sm' | 'md' | 'lg';
|
|
27
|
+
variant?: 'outline' | 'underline';
|
|
28
|
+
prefix?: React.ReactNode;
|
|
29
|
+
suffix?: React.ReactNode;
|
|
30
|
+
error?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface SelectValueProps {
|
|
34
|
+
placeholder?: string;
|
|
35
|
+
className?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface SelectContentProps {
|
|
39
|
+
className?: string;
|
|
40
|
+
children: React.ReactNode;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface SelectItemProps {
|
|
44
|
+
value: string;
|
|
45
|
+
label: string;
|
|
46
|
+
className?: string;
|
|
47
|
+
disabled?: boolean;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface SelectGroupProps {
|
|
51
|
+
className?: string;
|
|
52
|
+
children: React.ReactNode;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
interface SelectLabelProps {
|
|
56
|
+
className?: string;
|
|
57
|
+
children: React.ReactNode;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface SelectSeparatorProps {
|
|
61
|
+
className?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const SelectContext = React.createContext<{
|
|
65
|
+
value?: string;
|
|
66
|
+
onValueChange?: (value: string) => void;
|
|
67
|
+
open: boolean;
|
|
68
|
+
setOpen: (open: boolean) => void;
|
|
69
|
+
disabled?: boolean;
|
|
70
|
+
options: Map<string, string>;
|
|
71
|
+
registerOption: (value: string, label: string) => void;
|
|
72
|
+
} | null>(null);
|
|
73
|
+
|
|
74
|
+
function useSelect() {
|
|
75
|
+
const context = React.useContext(SelectContext);
|
|
76
|
+
if (!context) {
|
|
77
|
+
throw new Error('Select components must be used within Select');
|
|
78
|
+
}
|
|
79
|
+
return context;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function Select({ value, onValueChange, children, disabled = false }: SelectProps) {
|
|
83
|
+
const [open, setOpen] = React.useState(false);
|
|
84
|
+
const [options] = React.useState(() => new Map<string, string>());
|
|
85
|
+
|
|
86
|
+
const registerOption = React.useCallback((val: string, label: string) => {
|
|
87
|
+
options.set(val, label);
|
|
88
|
+
}, [options]);
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<SelectContext.Provider
|
|
92
|
+
value={{
|
|
93
|
+
value,
|
|
94
|
+
onValueChange,
|
|
95
|
+
open,
|
|
96
|
+
setOpen: (val) => !disabled && setOpen(val),
|
|
97
|
+
disabled,
|
|
98
|
+
options,
|
|
99
|
+
registerOption,
|
|
100
|
+
}}
|
|
101
|
+
>
|
|
102
|
+
<Dialog open={open} onOpenChange={setOpen}>
|
|
103
|
+
{children}
|
|
104
|
+
</Dialog>
|
|
105
|
+
</SelectContext.Provider>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function SelectTrigger({
|
|
110
|
+
className,
|
|
111
|
+
containerClassName,
|
|
112
|
+
children,
|
|
113
|
+
size = 'md',
|
|
114
|
+
variant = 'outline',
|
|
115
|
+
prefix,
|
|
116
|
+
suffix,
|
|
117
|
+
error = false,
|
|
118
|
+
}: SelectTriggerProps) {
|
|
119
|
+
const { setOpen, disabled, value, options } = useSelect();
|
|
120
|
+
const { colors } = useThemeColors();
|
|
121
|
+
const isOutline = variant === 'outline';
|
|
122
|
+
|
|
123
|
+
const sizeStyles = {
|
|
124
|
+
sm: 'web:h-9 h-10',
|
|
125
|
+
md: 'web:h-10 h-11',
|
|
126
|
+
lg: 'web:h-12 h-13',
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const displayValue = value ? options.get(value) : null;
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<View className={cn('w-full', containerClassName)}>
|
|
133
|
+
<Pressable
|
|
134
|
+
onPress={() => setOpen(true)}
|
|
135
|
+
disabled={disabled}
|
|
136
|
+
className={cn(
|
|
137
|
+
'flex-row items-center bg-background',
|
|
138
|
+
isOutline && `${sizeStyles[size]} border rounded-lg px-3`,
|
|
139
|
+
!isOutline && `${sizeStyles[size]} border-b`,
|
|
140
|
+
error ? 'border-destructive' : 'border-input',
|
|
141
|
+
'focus:border-ring',
|
|
142
|
+
disabled && 'opacity-50',
|
|
143
|
+
className
|
|
144
|
+
)}
|
|
145
|
+
>
|
|
146
|
+
{prefix && <View className="mr-3">{prefix}</View>}
|
|
147
|
+
|
|
148
|
+
<View className="flex-1 flex-row items-center justify-between gap-2">
|
|
149
|
+
<Text
|
|
150
|
+
size="md"
|
|
151
|
+
className={cn(
|
|
152
|
+
'flex-1',
|
|
153
|
+
displayValue ? 'text-foreground' : 'text-muted-foreground'
|
|
154
|
+
)}
|
|
155
|
+
>
|
|
156
|
+
{displayValue || children}
|
|
157
|
+
</Text>
|
|
158
|
+
|
|
159
|
+
<ChevronDown size={16} color={colors.mutedForeground} />
|
|
160
|
+
</View>
|
|
161
|
+
|
|
162
|
+
{suffix && <View className="ml-3">{suffix}</View>}
|
|
163
|
+
</Pressable>
|
|
164
|
+
|
|
165
|
+
{error && (
|
|
166
|
+
<Text size="sm" className="text-destructive mt-2">
|
|
167
|
+
{error}
|
|
168
|
+
</Text>
|
|
169
|
+
)}
|
|
170
|
+
</View>
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function SelectValue({ placeholder = 'Select...', className }: SelectValueProps) {
|
|
175
|
+
const { value, options } = useSelect();
|
|
176
|
+
const displayValue = value ? options.get(value) : null;
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<Text
|
|
180
|
+
size="sm"
|
|
181
|
+
className={cn(
|
|
182
|
+
'flex-1',
|
|
183
|
+
displayValue ? 'text-foreground' : 'text-muted-foreground',
|
|
184
|
+
className
|
|
185
|
+
)}
|
|
186
|
+
>
|
|
187
|
+
{displayValue || placeholder}
|
|
188
|
+
</Text>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export function SelectContent({ className, children }: SelectContentProps) {
|
|
193
|
+
return (
|
|
194
|
+
<DialogContent className={cn('p-0 max-h-96', className)}>
|
|
195
|
+
<ScrollView
|
|
196
|
+
showsVerticalScrollIndicator={false}
|
|
197
|
+
bounces={false}
|
|
198
|
+
className="max-h-96"
|
|
199
|
+
>
|
|
200
|
+
<View className="py-1">{children}</View>
|
|
201
|
+
</ScrollView>
|
|
202
|
+
</DialogContent>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function SelectItem({ value, label, className, disabled = false }: SelectItemProps) {
|
|
207
|
+
const { value: selectedValue, onValueChange, setOpen, registerOption } = useSelect();
|
|
208
|
+
const { colors } = useThemeColors();
|
|
209
|
+
const isSelected = selectedValue === value;
|
|
210
|
+
|
|
211
|
+
React.useEffect(() => {
|
|
212
|
+
registerOption(value, label);
|
|
213
|
+
}, [value, label, registerOption]);
|
|
214
|
+
|
|
215
|
+
const handleSelect = () => {
|
|
216
|
+
if (disabled) return;
|
|
217
|
+
onValueChange?.(value);
|
|
218
|
+
setOpen(false);
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
return (
|
|
222
|
+
<Pressable
|
|
223
|
+
onPress={handleSelect}
|
|
224
|
+
disabled={disabled}
|
|
225
|
+
className={cn(
|
|
226
|
+
'flex-row items-center justify-between px-4 py-3 border-b border-border active:bg-accent',
|
|
227
|
+
isSelected && 'bg-accent',
|
|
228
|
+
disabled && 'opacity-50',
|
|
229
|
+
className
|
|
230
|
+
)}
|
|
231
|
+
>
|
|
232
|
+
<Text
|
|
233
|
+
size="sm"
|
|
234
|
+
variant={'body'}
|
|
235
|
+
className={cn(
|
|
236
|
+
'flex-1',
|
|
237
|
+
isSelected ? 'text-accent-foreground' : 'text-foreground'
|
|
238
|
+
)}
|
|
239
|
+
>
|
|
240
|
+
{label}
|
|
241
|
+
</Text>
|
|
242
|
+
|
|
243
|
+
{isSelected && (
|
|
244
|
+
<Check size={16} color={colors.primary} className="ml-2" />
|
|
245
|
+
)}
|
|
246
|
+
</Pressable>
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export function SelectGroup({ className, children }: SelectGroupProps) {
|
|
251
|
+
return <View className={cn('py-1', className)}>{children}</View>;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export function SelectLabel({ className, children }: SelectLabelProps) {
|
|
255
|
+
return (
|
|
256
|
+
<View className={cn('px-4 py-2', className)}>
|
|
257
|
+
<Text size="sm" variant="body" className="uppercase tracking-wide text-muted-foreground">
|
|
258
|
+
{children}
|
|
259
|
+
</Text>
|
|
260
|
+
</View>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export function SelectSeparator({ className }: SelectSeparatorProps) {
|
|
265
|
+
return <View className={cn('h-px bg-border my-1 mx-2', className)} />;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export type { SelectOption };
|
|
269
|
+
|
|
270
|
+
// // components/ui/select.tsx
|
|
271
|
+
// import * as React from 'react';
|
|
272
|
+
// import { Pressable, ScrollView, View } from 'react-native';
|
|
273
|
+
// import { cn } from '@/lib/utils';
|
|
274
|
+
// import { Text } from './text';
|
|
275
|
+
// import { Dialog, DialogContent } from './dialog';
|
|
276
|
+
// import { useThemeColors } from '@/hooks/useThemeColors';
|
|
277
|
+
// import { ChevronDown, Check } from 'lucide-react-native';
|
|
278
|
+
|
|
279
|
+
// interface SelectOption {
|
|
280
|
+
// label: string;
|
|
281
|
+
// value: string;
|
|
282
|
+
// }
|
|
283
|
+
|
|
284
|
+
// interface SelectProps {
|
|
285
|
+
// value?: string;
|
|
286
|
+
// onValueChange?: (value: string) => void;
|
|
287
|
+
// children: React.ReactNode;
|
|
288
|
+
// disabled?: boolean;
|
|
289
|
+
// }
|
|
290
|
+
|
|
291
|
+
// interface SelectTriggerProps {
|
|
292
|
+
// className?: string;
|
|
293
|
+
// containerClassName?: string;
|
|
294
|
+
// children?: React.ReactNode;
|
|
295
|
+
// size?: 'sm' | 'md' | 'lg';
|
|
296
|
+
// variant?: 'outline' | 'underline';
|
|
297
|
+
// prefix?: React.ReactNode;
|
|
298
|
+
// suffix?: React.ReactNode;
|
|
299
|
+
// error?: boolean;
|
|
300
|
+
// }
|
|
301
|
+
|
|
302
|
+
// interface SelectValueProps {
|
|
303
|
+
// placeholder?: string;
|
|
304
|
+
// className?: string;
|
|
305
|
+
// }
|
|
306
|
+
|
|
307
|
+
// interface SelectContentProps {
|
|
308
|
+
// className?: string;
|
|
309
|
+
// children: React.ReactNode;
|
|
310
|
+
// }
|
|
311
|
+
|
|
312
|
+
// interface SelectItemProps {
|
|
313
|
+
// value: string;
|
|
314
|
+
// label: string;
|
|
315
|
+
// className?: string;
|
|
316
|
+
// disabled?: boolean;
|
|
317
|
+
// }
|
|
318
|
+
|
|
319
|
+
// interface SelectGroupProps {
|
|
320
|
+
// className?: string;
|
|
321
|
+
// children: React.ReactNode;
|
|
322
|
+
// }
|
|
323
|
+
|
|
324
|
+
// interface SelectLabelProps {
|
|
325
|
+
// className?: string;
|
|
326
|
+
// children: React.ReactNode;
|
|
327
|
+
// }
|
|
328
|
+
|
|
329
|
+
// interface SelectSeparatorProps {
|
|
330
|
+
// className?: string;
|
|
331
|
+
// }
|
|
332
|
+
|
|
333
|
+
// const SelectContext = React.createContext<{
|
|
334
|
+
// value?: string;
|
|
335
|
+
// onValueChange?: (value: string) => void;
|
|
336
|
+
// open: boolean;
|
|
337
|
+
// setOpen: (open: boolean) => void;
|
|
338
|
+
// disabled?: boolean;
|
|
339
|
+
// options: Map<string, string>;
|
|
340
|
+
// registerOption: (value: string, label: string) => void;
|
|
341
|
+
// } | null>(null);
|
|
342
|
+
|
|
343
|
+
// function useSelect() {
|
|
344
|
+
// const context = React.useContext(SelectContext);
|
|
345
|
+
// if (!context) {
|
|
346
|
+
// throw new Error('Select components must be used within Select');
|
|
347
|
+
// }
|
|
348
|
+
// return context;
|
|
349
|
+
// }
|
|
350
|
+
|
|
351
|
+
// export function Select({ value, onValueChange, children, disabled = false }: SelectProps) {
|
|
352
|
+
// const [open, setOpen] = React.useState(false);
|
|
353
|
+
// const [options] = React.useState(() => new Map<string, string>());
|
|
354
|
+
|
|
355
|
+
// const registerOption = React.useCallback((val: string, label: string) => {
|
|
356
|
+
// options.set(val, label);
|
|
357
|
+
// }, [options]);
|
|
358
|
+
|
|
359
|
+
// return (
|
|
360
|
+
// <SelectContext.Provider
|
|
361
|
+
// value={{
|
|
362
|
+
// value,
|
|
363
|
+
// onValueChange,
|
|
364
|
+
// open,
|
|
365
|
+
// setOpen: (val) => !disabled && setOpen(val),
|
|
366
|
+
// disabled,
|
|
367
|
+
// options,
|
|
368
|
+
// registerOption,
|
|
369
|
+
// }}
|
|
370
|
+
// >
|
|
371
|
+
// <Dialog open={open} onOpenChange={setOpen}>
|
|
372
|
+
// {children}
|
|
373
|
+
// </Dialog>
|
|
374
|
+
// </SelectContext.Provider>
|
|
375
|
+
// );
|
|
376
|
+
// }
|
|
377
|
+
|
|
378
|
+
// export function SelectTrigger({
|
|
379
|
+
// className,
|
|
380
|
+
// containerClassName,
|
|
381
|
+
// children,
|
|
382
|
+
// size = 'md',
|
|
383
|
+
// variant = 'outline',
|
|
384
|
+
// prefix,
|
|
385
|
+
// suffix,
|
|
386
|
+
// error = false,
|
|
387
|
+
// }: SelectTriggerProps) {
|
|
388
|
+
// const { setOpen, disabled, value, options } = useSelect();
|
|
389
|
+
// const { colors } = useThemeColors();
|
|
390
|
+
// const [isFocused, setIsFocused] = React.useState(false);
|
|
391
|
+
// const isOutline = variant === 'outline';
|
|
392
|
+
|
|
393
|
+
// const sizeStyles = {
|
|
394
|
+
// sm: 'web:h-9 h-10',
|
|
395
|
+
// md: 'web:h-10 h-11',
|
|
396
|
+
// lg: 'web:h-12 h-13',
|
|
397
|
+
// };
|
|
398
|
+
|
|
399
|
+
// const displayValue = value ? options.get(value) : null;
|
|
400
|
+
|
|
401
|
+
// return (
|
|
402
|
+
// <View className={cn('w-full', containerClassName)}>
|
|
403
|
+
// <View
|
|
404
|
+
// className={cn(
|
|
405
|
+
// 'flex-row items-center bg-background',
|
|
406
|
+
// isOutline && `${sizeStyles[size]} border rounded-lg px-3`,
|
|
407
|
+
// !isOutline && `${sizeStyles[size]} border-b`,
|
|
408
|
+
// isOutline && !error && !isFocused && 'border-input',
|
|
409
|
+
// isOutline && !error && isFocused && 'border-ring',
|
|
410
|
+
// isOutline && error && 'border-destructive',
|
|
411
|
+
// !isOutline && !error && !isFocused && 'border-input',
|
|
412
|
+
// !isOutline && !error && isFocused && 'border-ring',
|
|
413
|
+
// !isOutline && error && 'border-destructive',
|
|
414
|
+
// disabled && 'opacity-50',
|
|
415
|
+
// className
|
|
416
|
+
// )}
|
|
417
|
+
// >
|
|
418
|
+
// {prefix && <View className="mr-3">{prefix}</View>}
|
|
419
|
+
|
|
420
|
+
// <Pressable
|
|
421
|
+
// onPress={() => {
|
|
422
|
+
// setIsFocused(true);
|
|
423
|
+
// setOpen(true);
|
|
424
|
+
// }}
|
|
425
|
+
// disabled={disabled}
|
|
426
|
+
// className="flex-1 flex-row items-center justify-between gap-2"
|
|
427
|
+
// >
|
|
428
|
+
// <Text
|
|
429
|
+
// size="md"
|
|
430
|
+
// className={cn(
|
|
431
|
+
// 'flex-1',
|
|
432
|
+
// displayValue ? 'text-foreground' : 'text-muted-foreground'
|
|
433
|
+
// )}
|
|
434
|
+
// >
|
|
435
|
+
// {displayValue || children}
|
|
436
|
+
// </Text>
|
|
437
|
+
|
|
438
|
+
// <ChevronDown size={16} color={colors.mutedForeground} />
|
|
439
|
+
// </Pressable>
|
|
440
|
+
|
|
441
|
+
// {suffix && <View className="ml-3">{suffix}</View>}
|
|
442
|
+
// </View>
|
|
443
|
+
|
|
444
|
+
// {error && (
|
|
445
|
+
// <Text size="sm" className="text-destructive mt-2">
|
|
446
|
+
// {error}
|
|
447
|
+
// </Text>
|
|
448
|
+
// )}
|
|
449
|
+
// </View>
|
|
450
|
+
// );
|
|
451
|
+
// }
|
|
452
|
+
|
|
453
|
+
// export function SelectValue({ placeholder = 'Select...', className }: SelectValueProps) {
|
|
454
|
+
// const { value, options } = useSelect();
|
|
455
|
+
// const displayValue = value ? options.get(value) : null;
|
|
456
|
+
|
|
457
|
+
// return (
|
|
458
|
+
// <Text
|
|
459
|
+
// size="sm"
|
|
460
|
+
// className={cn(
|
|
461
|
+
// 'flex-1',
|
|
462
|
+
// displayValue ? 'text-foreground' : 'text-muted-foreground',
|
|
463
|
+
// className
|
|
464
|
+
// )}
|
|
465
|
+
// >
|
|
466
|
+
// {displayValue || placeholder}
|
|
467
|
+
// </Text>
|
|
468
|
+
// );
|
|
469
|
+
// }
|
|
470
|
+
|
|
471
|
+
// export function SelectContent({ className, children }: SelectContentProps) {
|
|
472
|
+
// return (
|
|
473
|
+
// <DialogContent className={cn('p-0 max-h-96', className)}>
|
|
474
|
+
// <ScrollView
|
|
475
|
+
// showsVerticalScrollIndicator={false}
|
|
476
|
+
// bounces={false}
|
|
477
|
+
// className="max-h-96"
|
|
478
|
+
// >
|
|
479
|
+
// <View className="py-1">{children}</View>
|
|
480
|
+
// </ScrollView>
|
|
481
|
+
// </DialogContent>
|
|
482
|
+
// );
|
|
483
|
+
// }
|
|
484
|
+
|
|
485
|
+
// export function SelectItem({ value, label, className, disabled = false }: SelectItemProps) {
|
|
486
|
+
// const { value: selectedValue, onValueChange, setOpen, registerOption } = useSelect();
|
|
487
|
+
// const { colors } = useThemeColors();
|
|
488
|
+
// const isSelected = selectedValue === value;
|
|
489
|
+
|
|
490
|
+
// React.useEffect(() => {
|
|
491
|
+
// registerOption(value, label);
|
|
492
|
+
// }, [value, label, registerOption]);
|
|
493
|
+
|
|
494
|
+
// const handleSelect = () => {
|
|
495
|
+
// if (disabled) return;
|
|
496
|
+
// onValueChange?.(value);
|
|
497
|
+
// setOpen(false);
|
|
498
|
+
// };
|
|
499
|
+
|
|
500
|
+
// return (
|
|
501
|
+
// <Pressable
|
|
502
|
+
// onPress={handleSelect}
|
|
503
|
+
// disabled={disabled}
|
|
504
|
+
// className={cn(
|
|
505
|
+
// 'flex-row items-center justify-between px-4 py-3 border-b border-border active:bg-accent',
|
|
506
|
+
// isSelected && 'bg-accent',
|
|
507
|
+
// disabled && 'opacity-50',
|
|
508
|
+
// className
|
|
509
|
+
// )}
|
|
510
|
+
// >
|
|
511
|
+
// <Text
|
|
512
|
+
// size="sm"
|
|
513
|
+
// variant={'body'}
|
|
514
|
+
// className={cn(
|
|
515
|
+
// 'flex-1',
|
|
516
|
+
// isSelected ? 'text-accent-foreground' : 'text-foreground'
|
|
517
|
+
// )}
|
|
518
|
+
// >
|
|
519
|
+
// {label}
|
|
520
|
+
// </Text>
|
|
521
|
+
|
|
522
|
+
// {isSelected && (
|
|
523
|
+
// <Check size={16} color={colors.primary} className="ml-2" />
|
|
524
|
+
// )}
|
|
525
|
+
// </Pressable>
|
|
526
|
+
// );
|
|
527
|
+
// }
|
|
528
|
+
|
|
529
|
+
// export function SelectGroup({ className, children }: SelectGroupProps) {
|
|
530
|
+
// return <View className={cn('py-1', className)}>{children}</View>;
|
|
531
|
+
// }
|
|
532
|
+
|
|
533
|
+
// export function SelectLabel({ className, children }: SelectLabelProps) {
|
|
534
|
+
// return (
|
|
535
|
+
// <View className={cn('px-4 py-2', className)}>
|
|
536
|
+
// <Text size="sm" variant='title' className="uppercase tracking-wide text-muted-foreground">
|
|
537
|
+
// {children}
|
|
538
|
+
// </Text>
|
|
539
|
+
// </View>
|
|
540
|
+
// );
|
|
541
|
+
// }
|
|
542
|
+
|
|
543
|
+
// export function SelectSeparator({ className }: SelectSeparatorProps) {
|
|
544
|
+
// return <View className={cn('h-px bg-border my-1 mx-2', className)} />;
|
|
545
|
+
// }
|
|
546
|
+
|
|
547
|
+
// export type { SelectOption };
|