{
  "title": "Form Select",
  "description": "A select input field with options and validation.",
  "name": "form-select",
  "dependencies": [
    "@tanstack/react-form"
  ],
  "registryDependencies": [
    "field",
    "select"
  ],
  "type": "registry:component",
  "files": [
    {
      "path": "components/ui/forms/form-select.tsx",
      "type": "registry:component",
      "content": "import { type AnyFormApi, type DeepKeys, useField } from \"@tanstack/react-form\";\nimport type { ComponentProps, ReactNode } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport { Field, FieldLabel } from \"@/components/ui/field\";\nimport { FormError } from \"@/components/ui/forms/form-error\";\nimport { type GetFormData } from \"@/components/ui/forms/helpers\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\n\nexport type FormSelectProps<TForm extends AnyFormApi> = Omit<\n    ComponentProps<typeof SelectTrigger>,\n    \"name\" | \"form\" | \"prefix\"\n> & {\n    label?: ReactNode;\n    form: TForm;\n    name: DeepKeys<GetFormData<TForm>>;\n    options: { label: string; value: string }[];\n    placeholder?: string;\n    containerClassName?: string;\n    prefix?: ReactNode;\n};\n\nexport const FormSelect = <TForm extends AnyFormApi>({\n    label,\n    form,\n    name,\n    options,\n    placeholder,\n    className,\n    containerClassName,\n    prefix,\n    ...rest\n}: FormSelectProps<TForm>) => {\n    const field = useField({\n        form,\n        name,\n    });\n\n    const errors = field.state.meta.errors[0];\n    const error = typeof errors === \"object\" ? errors.message : errors;\n\n    return (\n        <Field data-invalid={error != undefined} className={cn(\"gap-1.5\", containerClassName)}>\n            {label && <FieldLabel htmlFor={field.name}>{label}</FieldLabel>}\n            <Select name={field.name} value={field.state.value as string} onValueChange={field.handleChange}>\n                <SelectTrigger\n                    id={field.name}\n                    className={cn(\"relative\", className)}\n                    aria-invalid={error != undefined}\n                    onBlur={field.handleBlur}\n                    {...rest}>\n                    {prefix && <div className=\"absolute inset-s-3 top-1/2 -translate-y-1/2\">{prefix}</div>}\n                    <SelectValue className={cn({ \"ps-7\": prefix })} placeholder={placeholder} />\n                </SelectTrigger>\n                <SelectContent>\n                    {options.map((option) => (\n                        <SelectItem key={option.value} value={option.value}>\n                            {option.label}\n                        </SelectItem>\n                    ))}\n                </SelectContent>\n            </Select>\n            <FormError form={form} name={name} />\n        </Field>\n    );\n};\n"
    },
    {
      "path": "components/ui/forms/form-error.tsx",
      "type": "registry:ui",
      "content": "import { type AnyFormApi, type DeepKeys, useField } from \"@tanstack/react-form\";\nimport type { InputHTMLAttributes } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport { type GetFormData } from \"@/components/ui/forms/helpers\";\n\nexport type FormErrorProps<TForm extends AnyFormApi> = Omit<\n    InputHTMLAttributes<HTMLParagraphElement>,\n    \"name\" | \"form\"\n> & {\n    form: TForm;\n    name: DeepKeys<GetFormData<TForm>>;\n};\n\nexport const FormError = <TForm extends AnyFormApi>({ form, name = \"\", className, ...rest }: FormErrorProps<TForm>) => {\n    const field = useField({\n        form,\n        name,\n    });\n\n    const errors = field.state.meta.errors[0];\n    const error = typeof errors === \"object\" ? errors.message : errors;\n\n    return (\n        <>\n            {error && (\n                <p {...rest} className={cn(\"text-destructive text-sm\", className)}>\n                    {error}\n                </p>\n            )}\n        </>\n    );\n};\n"
    },
    {
      "path": "components/ui/forms/helpers.ts",
      "type": "registry:ui",
      "content": "import { type AnyFormApi, type DeepKeys, type FormApi } from \"@tanstack/react-form\";\n\nexport type GetFormData<TForm> =\n    TForm extends FormApi<infer TData, any, any, any, any, any, any, any, any, any, any, any> ? TData : never;\n\nexport const setFieldError = <TForm extends AnyFormApi>(\n    form: TForm,\n    field: DeepKeys<GetFormData<TForm>>,\n    error: string,\n) => {\n    form.setFieldMeta(field, (prev) => ({\n        ...prev,\n        errorMap: {\n            ...prev.errorMap,\n            onSubmit: error,\n        },\n    }));\n};\n\nexport const clearFormErrors = <TForm extends AnyFormApi>(form: TForm) => {\n    form.setErrorMap({ onDynamic: { fields: {} } });\n};\n"
    }
  ],
  "mcp": {
    "description": "Provides refined UI interactions and accessible controls. A select input field with options and validation. Relies on @tanstack/react-form, field, select. Optimal for building reusable interface elements and user input flows.",
    "tags": [
      "component",
      "form"
    ]
  }
}