{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "form",
  "title": "Form",
  "description": "The core Form component for BuzzForm v2.",
  "dependencies": [
    "@buildnbuzz/form-core",
    "@buildnbuzz/form-react",
    "@tanstack/form-core",
    "@tanstack/react-form"
  ],
  "registryDependencies": [
    "button"
  ],
  "files": [
    {
      "path": "registry/shadcn/form.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport {\n  Form as HeadlessForm,\n  RenderFields,\n  FormConfigContext,\n  useForm,\n  type FieldFormApi,\n  type UseFormOptionsWithSchema,\n  type FormRegistries,\n  FormProvider,\n  mergeRegistries,\n} from \"@buildnbuzz/form-react\";\nimport type {\n  CoreField,\n  FormSchema,\n  ValidationRun,\n} from \"@buildnbuzz/form-react\";\nimport { Button } from \"@/components/ui/button\";\nimport { cn } from \"@/lib/utils\";\n\n// --- Context ---\n\ninterface FormContextValue {\n  form: FieldFormApi;\n  schema?: FormSchema;\n  formId: string;\n  derivedValidationMode?: ValidationRun;\n  registries?: FormRegistries;\n}\n\nconst FormContext = React.createContext<FormContextValue | null>(null);\n\nfunction useFormContext(): FormContextValue {\n  const ctx = React.useContext(FormContext);\n  if (!ctx) throw new Error(\"Must be used within <Form>\");\n  return ctx;\n}\n\n// --- Types ---\n\ntype FormActionsConfig = {\n  /** Label for the submit button. Defaults to \"Submit\". */\n  submitLabel?: string;\n  /** Props forwarded to the submit button. */\n  submitProps?: Omit<FormSubmitProps, \"children\">;\n  /** Alignment of the actions row. Defaults to \"end\". */\n  align?: FormActionsProps[\"align\"];\n  /** Whether to show a reset button. Defaults to false. */\n  showReset?: boolean;\n  /** Label for the reset button. Defaults to \"Reset\". */\n  resetLabel?: string;\n  /** Props forwarded to the reset button. */\n  resetProps?: Omit<FormResetProps, \"children\">;\n};\n\ntype FormOwnProps = {\n  /** Unified runtime registries (fields, validators, resolvers, fns). */\n  registries?: FormRegistries;\n  children?: React.ReactNode;\n  actions?: FormActionsConfig;\n};\n\ntype FormWithInstance = FormOwnProps & {\n  form: FieldFormApi;\n  schema?: FormSchema;\n  derivedValidationMode?: ValidationRun;\n};\n\ntype FormWithSchema<TSchema extends FormSchema = FormSchema> = FormOwnProps &\n  UseFormOptionsWithSchema<TSchema> & {\n    form?: never;\n  };\n\ntype FormProps<TSchema extends FormSchema = FormSchema> =\n  | FormWithInstance\n  | FormWithSchema<TSchema>;\n\n// --- Form ---\n\nfunction Form<TSchema extends FormSchema = FormSchema>(\n  props: FormProps<TSchema>,\n) {\n  const config = React.useContext(FormConfigContext);\n  const globalRegistries = config?.registries;\n  // Check fields registry exists either on the prop or globally.\n  // Merging happens inside the headless layer (renderer / field / use-form).\n  const hasFieldRegistry =\n    (props.registries?.fields ?? globalRegistries?.fields) !== undefined;\n\n  const derivedValidationMode =\n    (props as FormWithInstance).derivedValidationMode ??\n    (props as FormWithSchema<TSchema>).derivedValidationMode ??\n    config?.derivedValidationMode;\n  const formId = React.useId();\n\n  if (!hasFieldRegistry) {\n    throw new Error(\n      \"No field component registry found. Pass `registries.fields` to <Form> or wrap with <FormProvider>.\",\n    );\n  }\n\n  if (\"form\" in props && props.form) {\n    const mergedRegistries = mergeRegistries(\n      config?.registries,\n      props.registries,\n    );\n    return (\n      <FormContext.Provider\n        value={{\n          form: props.form,\n          schema: props.schema,\n          formId,\n          derivedValidationMode,\n          registries: mergedRegistries,\n        }}\n      >\n        <FormProvider\n          registries={mergedRegistries}\n          derivedValidationMode={derivedValidationMode}\n        >\n          {props.children}\n        </FormProvider>\n      </FormContext.Provider>\n    );\n  }\n\n  return (\n    <FormInner\n      {...(props as FormWithSchema<TSchema>)}\n      derivedValidationMode={derivedValidationMode}\n      formId={formId}\n    />\n  );\n}\nfunction FormInner<TSchema extends FormSchema = FormSchema>({\n  formId,\n  children,\n  schema,\n  actions,\n  defaultValues,\n  onSubmit,\n  registries,\n  contextData,\n  derivedValidationMode,\n  ...tanstackOpts\n}: FormWithSchema<TSchema> & {\n  formId: string;\n  derivedValidationMode?: ValidationRun;\n}) {\n  const config = React.useContext(FormConfigContext);\n  if (process.env.NODE_ENV === \"development\" && children && actions) {\n    console.warn(\n      \"<Form>: `actions` prop is ignored when children are provided.\",\n    );\n  }\n\n  const {\n    submitLabel = \"Submit\",\n    submitProps,\n    align = \"end\",\n    showReset = false,\n    resetLabel = \"Reset\",\n    resetProps,\n  } = actions ?? {};\n\n  const form = useForm<TSchema>({\n    schema: schema as TSchema,\n    defaultValues,\n    onSubmit,\n    registries,\n    contextData,\n    derivedValidationMode,\n    ...tanstackOpts,\n  } as UseFormOptionsWithSchema<TSchema>);\n\n  const mergedRegistries = React.useMemo(\n    () => mergeRegistries(config?.registries, registries),\n    [config?.registries, registries],\n  );\n\n  return (\n    <FormContext.Provider\n      value={{\n        form,\n        schema,\n        formId,\n        derivedValidationMode,\n        registries: mergedRegistries,\n      }}\n    >\n      <FormProvider\n        registries={mergedRegistries}\n        derivedValidationMode={derivedValidationMode}\n      >\n        {children ?? (\n          <FormContent>\n            <FormFields />\n            <FormActions align={align}>\n              {showReset && <FormReset {...resetProps}>{resetLabel}</FormReset>}\n              <FormSubmit {...submitProps}>{submitLabel}</FormSubmit>\n            </FormActions>\n          </FormContent>\n        )}\n      </FormProvider>\n    </FormContext.Provider>\n  );\n}\n\n// --- FormContent ---\n\ntype FormContentProps = Omit<React.ComponentProps<\"form\">, \"onSubmit\"> & {\n  autoRender?: boolean;\n  as?: React.ElementType;\n};\n\nfunction FormContent({\n  className,\n  autoRender,\n  as,\n  children,\n  ...props\n}: FormContentProps) {\n  const { form, formId, derivedValidationMode, registries } = useFormContext();\n\n  return (\n    <HeadlessForm\n      id={formId}\n      as={as}\n      form={form}\n      registries={registries}\n      derivedValidationMode={derivedValidationMode}\n      className={cn(\"flex flex-col gap-4\", className)}\n      {...props}\n    >\n      {autoRender ? (\n        <>\n          <FormFields />\n          {children}\n        </>\n      ) : (\n        children\n      )}\n    </HeadlessForm>\n  );\n}\n\n// --- FormFields ---\n\ntype FormFieldsProps = {\n  className?: string;\n};\n\nfunction FormFields({ className }: FormFieldsProps) {\n  const { form, schema, derivedValidationMode, registries } = useFormContext();\n  const fields = (schema?.fields ?? []) as readonly CoreField[];\n\n  return (\n    <div className={cn(\"flex flex-col gap-4\", className)}>\n      <RenderFields\n        fields={fields}\n        form={form}\n        registries={registries}\n        derivedValidationMode={derivedValidationMode}\n      />\n    </div>\n  );\n}\n\n// --- FormActions ---\n\ntype FormActionsProps = React.ComponentProps<\"div\"> & {\n  align?: \"start\" | \"center\" | \"end\" | \"between\";\n};\n\nfunction FormActions({ className, align = \"end\", ...props }: FormActionsProps) {\n  return (\n    <div\n      data-slot=\"form-actions\"\n      className={cn(\n        \"flex gap-2\",\n        align === \"start\" && \"justify-start\",\n        align === \"center\" && \"justify-center\",\n        align === \"end\" && \"justify-end\",\n        align === \"between\" && \"justify-between\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\n// --- FormSubmit ---\n\ntype FormSubmitProps = Omit<\n  React.ComponentProps<typeof Button>,\n  \"type\" | \"form\"\n> & {\n  submittingText?: React.ReactNode;\n};\n\nfunction FormSubmit({\n  children,\n  submittingText = \"Submitting...\",\n  disabled,\n  ...props\n}: FormSubmitProps) {\n  const { form, formId } = useFormContext();\n  return (\n    <form.Subscribe\n      selector={(s) => ({\n        canSubmit: s.canSubmit,\n        isSubmitting: s.isSubmitting,\n      })}\n    >\n      {({ canSubmit, isSubmitting }) => (\n        <Button\n          type=\"submit\"\n          form={formId}\n          disabled={disabled || !canSubmit || isSubmitting}\n          {...props}\n        >\n          {isSubmitting ? submittingText : (children ?? \"Submit\")}\n        </Button>\n      )}\n    </form.Subscribe>\n  );\n}\n\n// --- FormReset ---\n\ntype FormResetProps = Omit<\n  React.ComponentProps<typeof Button>,\n  \"type\" | \"onClick\"\n> & {\n  disabled?: boolean;\n};\n\nfunction FormReset({\n  children,\n  disabled,\n  variant = \"outline\",\n  ...props\n}: FormResetProps) {\n  const { form } = useFormContext();\n  return (\n    <form.Subscribe\n      selector={(s) => ({ isSubmitting: s.isSubmitting, isDirty: s.isDirty })}\n    >\n      {({ isSubmitting, isDirty }) => (\n        <Button\n          type=\"button\"\n          variant={variant}\n          disabled={disabled || isSubmitting || !isDirty}\n          onClick={() => form.reset()}\n          {...props}\n        >\n          {children ?? \"Reset\"}\n        </Button>\n      )}\n    </form.Subscribe>\n  );\n}\n\n// --- FormMessage ---\n\nfunction FormMessage({\n  className,\n  children,\n  ...props\n}: React.ComponentProps<\"div\">) {\n  const { form } = useFormContext();\n  return (\n    <form.Subscribe selector={(s) => s.errors}>\n      {(errors) => {\n        const rootError = errors[0];\n        const message =\n          children ??\n          (typeof rootError === \"string\" || React.isValidElement(rootError)\n            ? (rootError as React.ReactNode)\n            : null);\n        if (!message) return null;\n        return (\n          <div\n            role=\"alert\"\n            data-slot=\"form-message\"\n            className={cn(\n              \"rounded-md bg-destructive/10 px-3 py-2 text-sm text-destructive\",\n              className,\n            )}\n            {...props}\n          >\n            {message}\n          </div>\n        );\n      }}\n    </form.Subscribe>\n  );\n}\n\n// --- Exports ---\n\nexport {\n  Form,\n  FormContent,\n  FormFields,\n  FormActions,\n  FormSubmit,\n  FormReset,\n  FormMessage,\n  useFormContext,\n  type FormProps,\n  type FormContentProps,\n  type FormActionsProps,\n  type FormSubmitProps,\n  type FormResetProps,\n};\n",
      "type": "registry:component",
      "target": "components/buzzform/form.tsx"
    }
  ],
  "type": "registry:ui"
}