{
  "name": "form",
  "layer": "base",
  "type": "component",
  "title": "Form",
  "description": "",
  "files": [
    {
      "path": "components/base/form/form.tsx",
      "target": "components/base/form/form.tsx",
      "type": "component",
      "content": "\"use client\";\n\nimport type { ComponentPropsWithRef } from \"react\";\nimport { Form as AriaForm } from \"react-aria-components\";\n\nexport const Form = (props: ComponentPropsWithRef<typeof AriaForm>) => {\n    return <AriaForm {...props} />;\n};\n\nForm.displayName = \"Form\";\n",
      "dependencies": [
        "react",
        "react-aria-components"
      ]
    },
    {
      "path": "components/base/form/hook-form.tsx",
      "target": "components/base/form/hook-form.tsx",
      "type": "component",
      "content": "\"use client\";\n\nimport type { ComponentPropsWithoutRef, ReactNode } from \"react\";\nimport { createContext, useContext, useId } from \"react\";\nimport { Form as AriaForm } from \"react-aria-components\";\nimport type { Control, FieldPath, FieldValues, UseControllerReturn, UseFormReturn } from \"react-hook-form\";\nimport { FormProvider, useController, useFormContext } from \"react-hook-form\";\n\ninterface FormProps<TFieldValues extends FieldValues = FieldValues> extends ComponentPropsWithoutRef<typeof AriaForm> {\n    form: UseFormReturn<TFieldValues>;\n    children: ReactNode;\n}\n\ninterface FormFieldProps<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> {\n    name: TName;\n    control: Control<TFieldValues>;\n    children: ReactNode | ((control: UseControllerReturn<TFieldValues, TName>) => ReactNode);\n}\n\ninterface FormFieldContextValues<TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>> {\n    id: string;\n    name: TName;\n    control?: UseControllerReturn<TFieldValues, TName>;\n}\n\nconst FormFieldContext = createContext<FormFieldContextValues>({} as FormFieldContextValues);\n\nexport const useFormFieldContext = () => {\n    const context = useContext(FormFieldContext);\n    const { getFieldState, formState } = useFormContext();\n    const fieldState = getFieldState(context.name, formState);\n\n    if (!context) {\n        throw new Error(\"The 'useFormContext' hook must be used within a '<FormField />'\");\n    }\n\n    return { ...context, ...fieldState };\n};\n\nexport const HookForm = <TFieldValues extends FieldValues = FieldValues>({ form, ...props }: FormProps<TFieldValues>) => {\n    return (\n        <FormProvider {...form}>\n            <AriaForm {...props} />\n        </FormProvider>\n    );\n};\n\nHookForm.displayName = \"HookForm\";\n\nexport const FormField = <TFieldValues extends FieldValues = FieldValues, TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>>({\n    children,\n    ...props\n}: FormFieldProps<TFieldValues, TName>) => {\n    const id = \"form-item-\" + useId();\n    const control = useController(props);\n    const withValidationBehavior = {\n        ...control,\n        field: {\n            ...control.field,\n            validationBehavior: \"aria\",\n        },\n    };\n\n    return (\n        <FormFieldContext.Provider\n            value={{\n                id,\n                name: props.name,\n                control: control as UseControllerReturn<FieldValues, TName>,\n            }}\n        >\n            {children && (typeof children === \"function\" ? children(withValidationBehavior) : children)}\n        </FormFieldContext.Provider>\n    );\n};\n\nFormField.displayName = \"FormField\";\n",
      "dependencies": [
        "react",
        "react-aria-components",
        "react-hook-form"
      ]
    }
  ],
  "registryDependencies": [],
  "optionalRegistryDependencies": [],
  "dependencies": [
    "react",
    "react-aria-components",
    "react-hook-form"
  ],
  "cssVars": [],
  "examples": [],
  "intent": "Group form fields into a single submit/validation boundary.",
  "avoid_when": [
    "laying out read-only key/value content (use a plain list or table)"
  ],
  "composes_with": [
    "input",
    "checkbox",
    "radio-buttons",
    "select",
    "textarea",
    "buttons"
  ],
  "a11y_contract": [
    "built on React Aria Form: surfaces native and custom field validation errors and associates them with their fields automatically"
  ],
  "requires_data": [
    "form field children; the hook-form variant additionally requires a react-hook-form `UseFormReturn` instance"
  ],
  "changelog": [
    {
      "version": "0.3.0",
      "changes": [
        "Adds six new component groups. Under `base/`: `HoverCard` (a rich hover/focus-triggered preview built on `Popover`, for things a plain `Tooltip` can't hold, like a profile card with a Follow button), `Menubar` (an application-style `File`/`Edit`/`View` menu bar built on React Aria's `Toolbar` plus the same `Menu`/`MenuTrigger` primitives `Dropdown` uses, with hover-switching between open menus, submenus, and checkbox/radio items), `NumberInput` (a `NumberField`-based numeric input with stacked or inline increment/decrement buttons and `formatOptions` for currency/percent/unit display), and `TagInput` (type-to-add tags on Enter/comma, paste-splits- on-commas, `maxTags`, a `validate` callback, and `isReadOnly`). Under `application/`: `Stepper` (a controlled multi-step form wizard — distinct from the purely decorative `ProgressSteps` — with `canAdvance` validation, linear and non-linear navigation, and horizontal/vertical layouts) and `Timeline` (vertical, alternating and horizontal status timelines with `completed`/`current`/`upcoming` coloring)."
      ]
    },
    {
      "version": "0.2.0",
      "changes": [
        "Adds six new primitives requested in the DrivenSellers feedback pass (docs/spec/feedback/2026-09-11-agent-feedback-map.md item 2.18, DrivenSellers §4): `Skeleton`/`SkeletonText` for loading placeholders, `DescriptionList` for term/details key-value content, a free-form `Popover` built on React Aria's `DialogTrigger`/`Popover`/`Dialog` that never binds its width to the trigger, `ConfirmDialog` (composed from the existing `modals` parts) for a controlled \"are you sure?\" prompt with an async `onConfirm` and a loading state, tone-tinted `Callout` for inline tips and notices, and a standalone `ToggleChip` built on React Aria's `ToggleButton`, colored from the badge palette."
      ]
    }
  ],
  "platforms": [
    "react",
    "next"
  ]
}
