{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "select", "type": "registry:ui", "title": "Select", "description": "Modal-based option picker (wave 1; anchor popover later).", "registryDependencies": [ "https://raw.githubusercontent.com/truongnat/rnui/main/registry/dist/nativewind/utils.json", "https://raw.githubusercontent.com/truongnat/rnui/main/registry/dist/nativewind/text.json", "https://raw.githubusercontent.com/truongnat/rnui/main/registry/dist/nativewind/theme.json" ], "dependencies": [ "lucide-react-native" ], "files": [ { "path": "registry/shared/ui/select.tsx", "type": "registry:ui", "target": "components/ui/select.tsx", "content": "import { Check, ChevronDown } from 'lucide-react-native';\nimport { useContext, useState } from 'react';\nimport {\n Modal,\n Pressable,\n ScrollView,\n View,\n type PressableProps,\n} from 'react-native';\nimport { Text } from '@/components/ui/text';\nimport { cn, FormFieldContext, useIconColor, useThemeColor } from '@/lib/utils';\n\nexport interface SelectOption {\n label: string;\n value: string;\n}\n\nexport interface SelectProps extends Omit {\n options: SelectOption[];\n value?: string;\n onValueChange?: (value: string) => void;\n placeholder?: string;\n /** Mirrors shadcn `aria-invalid` — destructive trigger border. Auto-detected from FormField error. */\n invalid?: boolean;\n className?: string;\n triggerClassName?: string;\n}\n\n/** Modal-based select (wave 1). Anchor-positioned popover is a wave-2 upgrade. */\nexport function Select({\n options,\n value,\n onValueChange,\n placeholder = 'Select…',\n invalid,\n className,\n triggerClassName,\n disabled,\n style,\n ...props\n}: SelectProps) {\n const [open, setOpen] = useState(false);\n const iconColor = useIconColor();\n const colors = useThemeColor();\n const field = useContext(FormFieldContext);\n const isInvalid = invalid ?? !!field?.error;\n const selected = options.find((o) => o.value === value);\n\n return (\n \n setOpen(true)}\n className={cn(\n 'h-10 flex-row items-center justify-between rounded-md border border-input bg-background px-3 dark:bg-input/30',\n disabled && 'opacity-50',\n triggerClassName\n )}\n style={(state) => [\n { borderCurve: 'continuous' },\n isInvalid && { borderColor: colors.destructive },\n typeof style === 'function' ? style(state) : style,\n ]}\n {...props}\n >\n \n {selected?.label ?? placeholder}\n \n \n \n\n setOpen(false)}\n >\n setOpen(false)}\n accessibilityLabel=\"Close\"\n >\n e.stopPropagation()}\n >\n \n {options.map((opt) => {\n const active = opt.value === value;\n return (\n {\n onValueChange?.(opt.value);\n setOpen(false);\n }}\n className={cn(\n 'flex-row items-center justify-between rounded-md px-3 py-3'\n )}\n style={\n active ? { backgroundColor: colors.accent } : undefined\n }\n >\n \n {opt.label}\n \n {active && }\n \n );\n })}\n \n \n \n \n \n );\n}\n" } ] }