{
  "title": "Form Input",
  "description": "A form input component with validation and error handling.",
  "name": "form-input",
  "dependencies": [
    "@tanstack/react-form"
  ],
  "registryDependencies": [
    "field",
    "input"
  ],
  "type": "registry:component",
  "files": [
    {
      "path": "components/ui/forms/form-input.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 { Input } from \"@/components/ui/input\";\n\nexport type FormInputProps<TForm extends AnyFormApi> = Omit<ComponentProps<\"input\">, \"name\" | \"form\" | \"prefix\"> & {\n    label?: ReactNode;\n    form: TForm;\n    name: DeepKeys<GetFormData<TForm>>;\n    prefix?: ReactNode;\n    suffix?: ReactNode;\n};\n\nexport const FormInput = <TForm extends AnyFormApi>({\n    label,\n    form,\n    name,\n    className,\n    prefix,\n    suffix,\n    ...rest\n}: FormInputProps<TForm>) => {\n    const field = useField({\n        form,\n        name,\n    });\n\n    const errors = field.state.meta.errors[0];\n\n    const error = typeof errors === \"object\" ? errors.message : errors;\n\n    return (\n        <Field data-invalid={error != undefined} className=\"gap-1.5\">\n            {label && <FieldLabel htmlFor={field.name}>{label}</FieldLabel>}\n            <div className=\"relative\">\n                {prefix && <div className=\"absolute inset-s-3 top-1/2 -translate-y-1/2\">{prefix}</div>}\n                <Input\n                    id={field.name}\n                    className={cn({ \"ps-10\": prefix, \"pe-10\": suffix }, className)}\n                    name={field.name}\n                    value={field.state.value ?? \"\"}\n                    onBlur={field.handleBlur}\n                    onChange={(e) => {\n                        const val = e.target.value;\n                        field.handleChange(rest.type === \"number\" ? Number(val) : val);\n                    }}\n                    aria-invalid={error != undefined}\n                    {...rest}\n                />\n                {suffix && <div className=\"absolute inset-e-3 top-1/2 -translate-y-1/2\">{suffix}</div>}\n            </div>\n            <FormError form={form} name={name} className=\"mt-0.5\" />\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 form input component with validation and error handling. Relies on @tanstack/react-form, field, input. Optimal for building reusable interface elements and user input flows.",
    "tags": [
      "component",
      "form"
    ]
  }
}