{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "form-tanstack",
  "type": "registry:ui",
  "title": "Form",
  "description": "Renders a form built with Tanstack Form.",
  "dependencies": [
    "@base-ui/react",
    "@tanstack/react-form"
  ],
  "registryDependencies": [
    "@basecn/label"
  ],
  "files": [
    {
      "path": "src/registry/components/ui/form-tanstack.tsx",
      "content": "\"use client\";\n\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { createFormHookContexts, createFormHook } from \"@tanstack/react-form\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Label } from \"@/registry/components/ui/label\";\n\nconst { fieldContext, formContext, useFieldContext } = createFormHookContexts();\n\nconst { useAppForm } = createFormHook({\n  fieldComponents: {\n    Label: FieldLabel,\n    Control: FieldControl,\n    Description: FieldDescription,\n    Message: FieldMessage,\n  },\n  formComponents: {\n    Item: FormItem,\n  },\n  fieldContext,\n  formContext,\n});\n\nconst useFormField = () => {\n  const itemContext = React.useContext(FormItemContext);\n  const fieldContext = useFieldContext();\n\n  if (!fieldContext) {\n    throw new Error(\"useFormField should be used within <field.Container>\");\n  }\n\n  const { id } = itemContext;\n\n  return {\n    id,\n    name: fieldContext.name,\n    formItemId: `${id}-form-item`,\n    formDescriptionId: `${id}-form-item-description`,\n    formMessageId: `${id}-form-item-message`,\n    ...fieldContext.state.meta,\n  };\n};\n\ntype FormItemContextValue = {\n  id: string;\n};\n\nconst FormItemContext = React.createContext<FormItemContextValue>(\n  {} as FormItemContextValue\n);\n\nfunction FormItem({ className, ...props }: React.ComponentProps<\"div\">) {\n  const id = React.useId();\n\n  return (\n    <FormItemContext.Provider value={{ id }}>\n      <div\n        data-slot=\"form-item\"\n        className={cn(\"grid gap-2\", className)}\n        {...props}\n      />\n    </FormItemContext.Provider>\n  );\n}\n\nfunction FieldLabel({\n  className,\n  ...props\n}: React.ComponentProps<typeof Label>) {\n  const { formItemId, isValid } = useFormField();\n\n  return (\n    <Label\n      data-slot=\"field-label\"\n      data-error={!isValid}\n      className={cn(\"data-[error=true]:text-destructive\", className)}\n      htmlFor={formItemId}\n      {...props}\n    />\n  );\n}\n\nfunction FieldControl({\n  children = <div />,\n}: {\n  children?: useRender.RenderProp;\n}) {\n  const { formItemId, isValid, formDescriptionId, formMessageId } =\n    useFormField();\n\n  return useRender({\n    render: children,\n    props: {\n      \"data-slot\": \"field-control\",\n      id: formItemId,\n      \"aria-describedby\": isValid\n        ? `${formDescriptionId}`\n        : `${formDescriptionId} ${formMessageId}`,\n      \"aria-invalid\": !isValid,\n    },\n  });\n}\n\nfunction FieldDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n  const { formDescriptionId } = useFormField();\n\n  return (\n    <p\n      data-slot=\"field-description\"\n      id={formDescriptionId}\n      className={cn(\"text-muted-foreground text-sm\", className)}\n      {...props}\n    />\n  );\n}\n\nfunction FieldMessage({ className, ...props }: React.ComponentProps<\"p\">) {\n  const { formMessageId, isValid, errors } = useFormField();\n\n  if (props.children) return props.children;\n\n  const body = isValid\n    ? props.children\n    : String(errors.map((error) => error.message).join(\", \") ?? \"\");\n\n  if (!body) return null;\n\n  return (\n    <p\n      data-slot=\"field-message\"\n      id={formMessageId}\n      className={cn(\"text-destructive text-sm\", className)}\n      {...props}\n    >\n      {body}\n    </p>\n  );\n}\n\nexport { useAppForm };\n",
      "type": "registry:ui"
    }
  ]
}