{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "files": [
    {
      "content": "\"use client\";\n\nimport { useForm } from \"@tanstack/react-form\";\nimport { PlusIcon, XIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\nimport { z } from \"zod\";\nimport { Button } from \"~/registry/ui/button\";\nimport { Field } from \"~/registry/ui/field\";\nimport { Input } from \"~/registry/ui/input\";\nimport { TextField } from \"~/registry/ui/text-field\";\n\nconst MAX_EMAILS = 5;\n\nconst formSchema = z.object({\n  emails: z\n    .array(z.object({ address: z.email(\"Enter a valid email.\") }))\n    .min(1, \"Add at least one email address.\")\n    .max(MAX_EMAILS, `You can add up to ${MAX_EMAILS} email addresses.`),\n});\n\nexport function TanstackFormArrayDemo() {\n  const form = useForm({\n    defaultValues: {\n      emails: [{ address: \"\" }],\n    },\n    validators: {\n      onChange: formSchema,\n    },\n    onSubmit: ({ value }) => {\n      toast(JSON.stringify(value, null, 2));\n    },\n  });\n\n  return (\n    <form\n      className=\"flex w-full max-w-sm flex-col gap-4\"\n      onSubmit={(e) => {\n        e.preventDefault();\n        e.stopPropagation();\n        form.handleSubmit();\n      }}\n    >\n      <form.Field\n        children={(field) => (\n          <Field.Set>\n            <Field.Legend variant=\"label\">Email Addresses</Field.Legend>\n            <Field.Group>\n              {field.state.value.map((_, index) => (\n                <form.Field\n                  children={(subField) => {\n                    const isInvalid =\n                      subField.state.meta.isTouched &&\n                      !subField.state.meta.isValid;\n                    return (\n                      <Field.Root\n                        render={\n                          <TextField\n                            id={subField.name}\n                            isInvalid={isInvalid}\n                            name={subField.name}\n                            onBlur={subField.handleBlur}\n                            onChange={subField.handleChange}\n                            type=\"email\"\n                            value={subField.state.value}\n                          />\n                        }\n                      >\n                        <div className=\"flex items-center gap-2\">\n                          <Input\n                            className=\"flex-1\"\n                            placeholder=\"name@example.com\"\n                          />\n                          {field.state.value.length > 1 && (\n                            <Button\n                              aria-label={`Remove email ${index + 1}`}\n                              onPress={() => field.removeValue(index)}\n                              size=\"icon\"\n                              type=\"button\"\n                              variant=\"ghost\"\n                            >\n                              <XIcon />\n                            </Button>\n                          )}\n                        </div>\n                        <Field.Error errors={subField.state.meta.errors} />\n                      </Field.Root>\n                    );\n                  }}\n                  // biome-ignore lint/suspicious/noArrayIndexKey: index is stable for array fields\n                  key={index}\n                  name={`emails[${index}].address`}\n                />\n              ))}\n            </Field.Group>\n            <Button\n              isDisabled={field.state.value.length >= MAX_EMAILS}\n              onPress={() => field.pushValue({ address: \"\" })}\n              size=\"sm\"\n              type=\"button\"\n              variant=\"outline\"\n            >\n              <PlusIcon />\n              Add email\n            </Button>\n          </Field.Set>\n        )}\n        mode=\"array\"\n        name=\"emails\"\n      />\n      <form.Subscribe\n        selector={(state) => [state.canSubmit, state.isSubmitting]}\n        children={([canSubmit, isSubmitting]) => (\n          <Button isDisabled={!canSubmit} type=\"submit\">\n            {isSubmitting ? \"Submitting...\" : \"Submit\"}\n          </Button>\n        )}\n      />\n    </form>\n  );\n}\n",
      "path": "src/registry/examples/form/tanstack-form/tanstack-form-array-demo.tsx",
      "type": "registry:example"
    }
  ],
  "name": "tanstack-form-array-demo",
  "registryDependencies": [
    "@kanpeki/form"
  ],
  "type": "registry:example"
}