{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "form-field",
  "type": "registry:ui",
  "title": "Form field",
  "description": "A control with its words: label, description and an error that grows open from under the control on the settle spring; invalid and disabled reach every control inside. Fieldset groups fields under a legend.",
  "dependencies": [
    "@base-ui/react@^1.8.0"
  ],
  "registryDependencies": [
    "https://metalui.dev/r/tokens.json"
  ],
  "files": [
    {
      "path": "packages/metalui/src/components/form-field/form-field.tsx",
      "type": "registry:ui",
      "target": "components/metalui/form-field/form-field.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { Field as BaseField } from '@base-ui/react/field';\nimport { Fieldset as BaseFieldset } from '@base-ui/react/fieldset';\nimport { Form as BaseForm } from '@base-ui/react/form';\n\n/* ─────────────────────────────────────────────────────────\n * FORM FIELD and FIELDSET, a control with its words, on Base UI Field and Fieldset\n *\n *   label        above the control (ui type, ink); tied to it, so clicking it focuses the control\n *   description  below (meta type, ink3); read with the control by assistive tech\n *   error        below, when the value is not accepted (meta type, red): its row grows open on\n *                the settle spring as it fades in, so the layout below moves rather than jumps;\n *                it leaves on the release spring\n *   states       invalid and disabled on the field reach every control inside (Field, Textarea,\n *                Select, Combobox, Number field, Radio group, Checkbox group), which draw their own\n *                invalid ring and disabled look\n *   fieldset     groups fields (or a radio or checkbox group) under a legend\n *   form         validates every field on submit, moves focus to the first one not accepted, and\n *                takes a server's errors by field name\n * Reduce Motion: the error's row snaps; the fade stays.\n * Slots: FormField.Root, FormField.Label, FormField.Description, FormField.Error; Fieldset.Root, Fieldset.Legend; Form.\n * ───────────────────────────────────────────────────────── */\n\nconst ROOT = 'mu-form-field grid gap-form-field-gap';\nconst LABEL = 'mu-form-field-label type-ui text-ink w-max data-disabled:opacity-field-state-disabled';\nconst DESCRIPTION = 'mu-form-field-description m-0 type-meta text-ink3';\nconst ERROR = 'mu-form-field-error type-meta text-form-field-error-ink form-field-error';\nconst FIELDSET = 'mu-fieldset grid gap-form-field-fieldset-gap m-0 p-0 border-0 min-w-0 data-disabled:opacity-field-state-disabled';\nconst FORM = 'mu-form grid gap-form-field-form-gap';\nconst LEGEND = 'mu-fieldset-legend type-label engraved form-field-legend';\n\nexport type FormFieldRootProps = Omit<BaseField.Root.Props, 'className'> & { className?: string };\n\nfunction Root({ className, ...props }: FormFieldRootProps) {\n  return <BaseField.Root className={className ? `${ROOT} ${className}` : ROOT} {...props} />;\n}\n\nfunction Label({ className, ...props }: BaseField.Label.Props & { className?: string }) {\n  return <BaseField.Label className={className ? `${LABEL} ${className}` : LABEL} {...props} />;\n}\n\nfunction Description({ className, ...props }: BaseField.Description.Props & { className?: string }) {\n  return <BaseField.Description className={className ? `${DESCRIPTION} ${className}` : DESCRIPTION} {...props} />;\n}\n\n/**\n * Why the value is not accepted. Shown while the field is invalid (or, with `match`, for one validity\n * rule). Without children it says the validation message: what `validate` returned, or the browser's.\n */\nfunction Error({ className, children, ...props }: BaseField.Error.Props & { className?: string }) {\n  return (\n    <BaseField.Error className={className ? `${ERROR} ${className}` : ERROR} {...props}>\n      {/* One inner row: the error's grid grows it open. */}\n      <span>{children ?? <BaseField.Validity>{(v) => v.errors.join(' ') || v.error}</BaseField.Validity>}</span>\n    </BaseField.Error>\n  );\n}\n\nexport const FormField = Object.assign(Root, { Label, Description, Error, Root });\n\nfunction FieldsetRoot({ className, ...props }: BaseFieldset.Root.Props & { className?: string }) {\n  return <BaseFieldset.Root className={className ? `${FIELDSET} ${className}` : FIELDSET} {...props} />;\n}\n\nfunction Legend({ className, ...props }: BaseFieldset.Legend.Props & { className?: string }) {\n  return <BaseFieldset.Legend className={className ? `${LEGEND} ${className}` : LEGEND} {...props} />;\n}\n\nexport const Fieldset = Object.assign(FieldsetRoot, { Legend, Root: FieldsetRoot });\n\nexport type FormProps<Values extends Record<string, unknown> = Record<string, unknown>> = Omit<BaseForm.Props<Values>, 'className'> & { className?: string };\n\n/** A form of fields: validates them all on submit and focuses the first one not accepted. */\nexport function Form<Values extends Record<string, unknown> = Record<string, unknown>>({ className, ...props }: FormProps<Values>) {\n  return <BaseForm<Values> className={className ? `${FORM} ${className}` : FORM} {...props} />;\n}\n"
    }
  ],
  "docs": "Agent guide: https://metalui.dev/r/form-field.md. SwiftUI: MetalFormField in the MetalUI Swift package."
}
