{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "form-tanstack-story",
  "title": "Form (TanStack Form) Story",
  "author": "Lloyd Richards <lloyd.d.richards@gmail.com>",
  "description": "Interactive Storybook stories demonstrating form usage with TanStack Form",
  "dependencies": [
    "@tanstack/react-form",
    "zod"
  ],
  "registryDependencies": [
    "button",
    "field",
    "input"
  ],
  "files": [
    {
      "path": "registry/ui/form-story/form-tanstack-base.stories.tsx",
      "content": "import type { Meta, StoryObj } from \"@storybook/nextjs-vite\";\nimport { useForm as useTanstackForm } from \"@tanstack/react-form\";\nimport type { ComponentProps } from \"react\";\nimport { action } from \"storybook/actions\";\nimport { expect, userEvent } from \"storybook/test\";\nimport * as z from \"zod\";\n\nimport { Button } from \"@/components/ui/button\";\nimport {\n  Field,\n  FieldDescription,\n  FieldError,\n  FieldGroup,\n  FieldLabel,\n} from \"@/components/ui/field\";\nimport { Input } from \"@/components/ui/input\";\n\nconst formSchema = z.object({\n  username: z.string().min(6, {\n    message: \"Username must be at least 6 characters.\",\n  }),\n});\n\ntype ProfileFormValues = z.infer<typeof formSchema>;\n\nfunction TanStackFormProfileForm(props: ComponentProps<\"form\">) {\n  const form = useTanstackForm({\n    defaultValues: {\n      username: \"\",\n    },\n    validators: {\n      onSubmit: formSchema,\n    },\n    onSubmit: async ({ value }) => {\n      action(\"onSubmit\")(value as ProfileFormValues);\n    },\n  });\n\n  return (\n    <form\n      onSubmit={(event) => {\n        event.preventDefault();\n        form.handleSubmit();\n      }}\n      className=\"space-y-8\"\n      {...props}\n    >\n      <FieldGroup>\n        <form.Field name=\"username\">\n          {(field) => {\n            const isInvalid =\n              field.state.meta.isTouched && !field.state.meta.isValid;\n            return (\n              <Field data-invalid={isInvalid}>\n                <FieldLabel htmlFor=\"form-tanstack-username\">\n                  Username\n                </FieldLabel>\n                <Input\n                  id=\"form-tanstack-username\"\n                  name={field.name}\n                  placeholder=\"username\"\n                  value={field.state.value}\n                  onBlur={field.handleBlur}\n                  onChange={(event) => field.handleChange(event.target.value)}\n                  aria-invalid={isInvalid}\n                />\n                <FieldDescription>\n                  This is your public display name.\n                </FieldDescription>\n                {isInvalid && (\n                  <FieldError\n                    errors={field.state.meta.errors.map((error) =>\n                      typeof error === \"string\" ? { message: error } : error,\n                    )}\n                  />\n                )}\n              </Field>\n            );\n          }}\n        </form.Field>\n      </FieldGroup>\n      <Button type=\"submit\">Submit</Button>\n    </form>\n  );\n}\n\n/**\n * Building forms with TanStack Form and Zod.\n */\nconst meta: Meta<typeof TanStackFormProfileForm> = {\n  title: \"ui/base/Form (TanStack Form)\",\n  component: TanStackFormProfileForm,\n  tags: [\"autodocs\"],\n  argTypes: {},\n} satisfies Meta<typeof TanStackFormProfileForm>;\n\nexport default meta;\n\ntype Story = StoryObj<typeof meta>;\n\n/**\n * The default form of the form.\n */\nexport const Default: Story = {};\n\nexport const ShouldSucceedWhenValidInput: Story = {\n  name: \"when typing a valid username, should not show an error message\",\n  tags: [\"!dev\", \"!autodocs\"],\n  play: async ({ canvas, step }) => {\n    await step(\"Type a valid username\", async () => {\n      await userEvent.type(\n        await canvas.findByRole(\"textbox\", { name: /username/i }),\n        \"mockuser\",\n      );\n    });\n\n    await step(\"Click the submit button\", async () => {\n      await userEvent.click(\n        await canvas.findByRole(\"button\", { name: /submit/i }),\n      );\n      expect(\n        await canvas.queryByText(/username must be at least 6 characters/i, {\n          exact: true,\n        }),\n      ).toBeNull();\n    });\n  },\n};\n\nexport const ShouldShowErrorWhenInvalidInput: Story = {\n  name: \"when typing a short username, should show an error message\",\n  tags: [\"!dev\", \"!autodocs\"],\n  play: async ({ canvas, step }) => {\n    await step(\"Type a short username\", async () => {\n      await userEvent.type(\n        await canvas.findByRole(\"textbox\", { name: /username/i }),\n        \"fail\",\n      );\n    });\n\n    await step(\"Click the submit button\", async () => {\n      await userEvent.click(\n        await canvas.findByRole(\"button\", { name: /submit/i }),\n      );\n      expect(\n        await canvas.queryByText(/username must be at least 6 characters/i, {\n          exact: true,\n        }),\n      ).toBeVisible();\n    });\n  },\n};\n",
      "type": "registry:component"
    }
  ],
  "categories": [
    "ui",
    "storybook",
    "form",
    "validation"
  ],
  "type": "registry:component"
}