{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "form",
  "title": "Form Field (react-hook-form)",
  "description": "FormField: a react-hook-form Controller laid out with Field, with the id, label and ARIA wiring done for you.",
  "dependencies": [
    "react-hook-form@^7.89.0"
  ],
  "registryDependencies": [
    "@corsair-ui/field"
  ],
  "files": [
    {
      "path": "registry/default/ui/form.tsx",
      "content": "\"use client\";\n\nimport { useId, type ReactElement, type ReactNode } from \"react\";\nimport {\n  Controller,\n  type ControllerFieldState,\n  type ControllerProps,\n  type ControllerRenderProps,\n  type FieldPath,\n  type FieldValues,\n} from \"react-hook-form\";\n\nimport {\n  Field,\n  FieldContent,\n  FieldDescription,\n  FieldError,\n  FieldLabel,\n} from \"@/registry/default/ui/field\";\n\ntype FormControlProps<\n  TFieldValues extends FieldValues,\n  TName extends FieldPath<TFieldValues>,\n> = ControllerRenderProps<TFieldValues, TName> & {\n  id: string;\n  \"aria-invalid\": boolean;\n  \"aria-describedby\"?: string;\n};\n\ninterface FormFieldProps<\n  TFieldValues extends FieldValues,\n  TName extends FieldPath<TFieldValues>,\n> extends Omit<ControllerProps<TFieldValues, TName>, \"render\"> {\n  label?: ReactNode;\n  description?: ReactNode;\n  /** Horizontal puts the control before its label (checkboxes, switches). */\n  orientation?: \"vertical\" | \"horizontal\";\n  className?: string;\n  /**\n   * Render the control. Spread `field` on inputs; for Checkbox, Switch or\n   * Select map `field.value` / `field.onChange` to their own props.\n   */\n  render: (props: {\n    field: FormControlProps<TFieldValues, TName>;\n    fieldState: ControllerFieldState;\n  }) => ReactElement;\n}\n\n/**\n * A react-hook-form field laid out with Field. It generates the id, points the\n * label at it, and sets aria-invalid and aria-describedby on the control so\n * the description and error are announced with it.\n *\n * @example\n * <FormField\n *   control={form.control}\n *   name=\"email\"\n *   label=\"Email\"\n *   description=\"We only use it to reply to you.\"\n *   render={({ field }) => <Input type=\"email\" {...field} />}\n * />\n */\nfunction FormField<\n  TFieldValues extends FieldValues = FieldValues,\n  TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n  label,\n  description,\n  orientation = \"vertical\",\n  className,\n  render,\n  ...controller\n}: FormFieldProps<TFieldValues, TName>) {\n  const id = useId();\n  const descriptionId = `${id}-description`;\n  const errorId = `${id}-error`;\n\n  return (\n    <Controller\n      {...controller}\n      render={({ field, fieldState }) => {\n        const describedBy =\n          [description ? descriptionId : null, fieldState.invalid ? errorId : null]\n            .filter(Boolean)\n            .join(\" \") || undefined;\n\n        const control = render({\n          field: {\n            ...field,\n            id,\n            \"aria-invalid\": fieldState.invalid,\n            \"aria-describedby\": describedBy,\n          },\n          fieldState,\n        });\n        const labelNode = label ? <FieldLabel htmlFor={id}>{label}</FieldLabel> : null;\n        const descriptionNode = description ? (\n          <FieldDescription id={descriptionId}>{description}</FieldDescription>\n        ) : null;\n        const errorNode = <FieldError id={errorId} errors={[fieldState.error]} />;\n\n        return (\n          <Field\n            orientation={orientation}\n            data-invalid={fieldState.invalid || undefined}\n            data-disabled={field.disabled || undefined}\n            className={className}\n          >\n            {orientation === \"horizontal\" ? (\n              <>\n                {control}\n                <FieldContent>\n                  {labelNode}\n                  {descriptionNode}\n                  {errorNode}\n                </FieldContent>\n              </>\n            ) : (\n              <>\n                {labelNode}\n                {control}\n                {descriptionNode}\n                {errorNode}\n              </>\n            )}\n          </Field>\n        );\n      }}\n    />\n  );\n}\n\nexport { FormField, type FormControlProps, type FormFieldProps };\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}