{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "address-form", "title": "Address Form", "description": "A validated shipping/billing address form (react-hook-form + zod) that emits a normalized Address.", "dependencies": [ "react-hook-form", "zod", "@hookform/resolvers" ], "registryDependencies": [ "https://lumo-www.vercel.app/r/lib.json" ], "files": [ { "path": "packages/core/src/components/lumo/address-form.tsx", "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { useForm, type SubmitHandler } from \"react-hook-form\"\r\nimport { zodResolver } from \"@hookform/resolvers/zod\"\r\nimport { z } from \"zod\"\r\nimport type { Address } from \"@/lib/lumo/types\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nconst addressSchema = z.object({\r\n firstName: z.string().min(1, \"Required\"),\r\n lastName: z.string().min(1, \"Required\"),\r\n line1: z.string().min(1, \"Required\"),\r\n line2: z.string().optional(),\r\n city: z.string().min(1, \"Required\"),\r\n region: z.string().optional(),\r\n postalCode: z.string().min(1, \"Required\"),\r\n country: z.string().min(2, \"Use a 2-letter country code\"),\r\n phone: z.string().optional(),\r\n})\r\n\r\nexport type AddressFormValues = z.infer\r\n\r\nconst inputClass =\r\n \"h-10 w-full rounded-md border border-input bg-background px-3 text-sm transition-colors placeholder:text-muted-foreground/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\r\n\r\nfunction Field({\r\n label,\r\n error,\r\n children,\r\n className,\r\n}: {\r\n label: string\r\n error?: string\r\n children: React.ReactElement\r\n className?: string\r\n}) {\r\n const id = React.useId()\r\n return (\r\n
\r\n \r\n {React.cloneElement(children, { id, \"aria-invalid\": error ? true : undefined } as Record)}\r\n {error && {error}}\r\n
\r\n )\r\n}\r\n\r\nexport interface AddressFormProps {\r\n defaultValues?: Partial
\r\n onSubmit?: (address: Address) => void\r\n submitLabel?: string\r\n className?: string\r\n}\r\n\r\nexport function AddressForm({ defaultValues, onSubmit, submitLabel = \"Continue\", className }: AddressFormProps) {\r\n const {\r\n register,\r\n handleSubmit,\r\n formState: { errors, isSubmitting },\r\n } = useForm({\r\n resolver: zodResolver(addressSchema),\r\n defaultValues: defaultValues as AddressFormValues,\r\n })\r\n\r\n const submit: SubmitHandler = (values) => onSubmit?.(values as Address)\r\n\r\n return (\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n \r\n \r\n \r\n {submitLabel}\r\n \r\n \r\n )\r\n}\r\n", "type": "registry:ui", "target": "components/lumo/address-form.tsx" } ], "type": "registry:ui" }