// components/ui/select.tsx import * as React from 'react'; import { Pressable, ScrollView, View } from 'react-native'; import { cn } from '@/lib/utils'; import { Text } from './text'; import { Dialog, DialogContent } from './dialog'; import { useThemeColors } from '@/hooks/useThemeColors'; import { ChevronDown, Check } from 'lucide-react-native'; interface SelectOption { label: string; value: string; } interface SelectProps { value?: string; onValueChange?: (value: string) => void; children: React.ReactNode; disabled?: boolean; } interface SelectTriggerProps { className?: string; containerClassName?: string; children?: React.ReactNode; size?: 'sm' | 'md' | 'lg'; variant?: 'outline' | 'underline'; prefix?: React.ReactNode; suffix?: React.ReactNode; error?: boolean; } interface SelectValueProps { placeholder?: string; className?: string; } interface SelectContentProps { className?: string; children: React.ReactNode; } interface SelectItemProps { value: string; label: string; className?: string; disabled?: boolean; } interface SelectGroupProps { className?: string; children: React.ReactNode; } interface SelectLabelProps { className?: string; children: React.ReactNode; } interface SelectSeparatorProps { className?: string; } const SelectContext = React.createContext<{ value?: string; onValueChange?: (value: string) => void; open: boolean; setOpen: (open: boolean) => void; disabled?: boolean; options: Map; registerOption: (value: string, label: string) => void; } | null>(null); function useSelect() { const context = React.useContext(SelectContext); if (!context) { throw new Error('Select components must be used within Select'); } return context; } export function Select({ value, onValueChange, children, disabled = false }: SelectProps) { const [open, setOpen] = React.useState(false); const [options] = React.useState(() => new Map()); const registerOption = React.useCallback((val: string, label: string) => { options.set(val, label); }, [options]); return ( !disabled && setOpen(val), disabled, options, registerOption, }} > {children} ); } export function SelectTrigger({ className, containerClassName, children, size = 'md', variant = 'outline', prefix, suffix, error = false, }: SelectTriggerProps) { const { setOpen, disabled, value, options } = useSelect(); const { colors } = useThemeColors(); const isOutline = variant === 'outline'; const sizeStyles = { sm: 'web:h-9 h-10', md: 'web:h-10 h-11', lg: 'web:h-12 h-13', }; const displayValue = value ? options.get(value) : null; return ( setOpen(true)} disabled={disabled} className={cn( 'flex-row items-center bg-background', isOutline && `${sizeStyles[size]} border rounded-lg px-3`, !isOutline && `${sizeStyles[size]} border-b`, error ? 'border-destructive' : 'border-input', 'focus:border-ring', disabled && 'opacity-50', className )} > {prefix && {prefix}} {displayValue || children} {suffix && {suffix}} {error && ( {error} )} ); } export function SelectValue({ placeholder = 'Select...', className }: SelectValueProps) { const { value, options } = useSelect(); const displayValue = value ? options.get(value) : null; return ( {displayValue || placeholder} ); } export function SelectContent({ className, children }: SelectContentProps) { return ( {children} ); } export function SelectItem({ value, label, className, disabled = false }: SelectItemProps) { const { value: selectedValue, onValueChange, setOpen, registerOption } = useSelect(); const { colors } = useThemeColors(); const isSelected = selectedValue === value; React.useEffect(() => { registerOption(value, label); }, [value, label, registerOption]); const handleSelect = () => { if (disabled) return; onValueChange?.(value); setOpen(false); }; return ( {label} {isSelected && ( )} ); } export function SelectGroup({ className, children }: SelectGroupProps) { return {children}; } export function SelectLabel({ className, children }: SelectLabelProps) { return ( {children} ); } export function SelectSeparator({ className }: SelectSeparatorProps) { return ; } export type { SelectOption };