Files
zeekay 05fc512820 feat: sync upstream shadcn/ui — [email protected], v4 app, font system, chart improvements
Upstream sync from shadcn-ui/ui (1686 commits since last merge base).

Key changes:
- packages/shadcn upgraded to 4.1.0 (CLI font transformers, scaffold from github, chart colors)
- apps/v4 replaces apps/www as the primary docs/registry app
- Font system: 25+ heading font registries, font markers utility, @supports override
- Chart improvements: recharts v3 compat, radial chart fixes
- templates/ updated with monorepo variants (astro, vite, react-router, start)
- skills/shadcn AI skill definitions added
- deprecated/ removed (auth, auth-firebase, cli, www)

Preserved Hanzo-only paths: app/, pkg/, demo/, docs/, template/next/
2026-03-24 19:04:31 -07:00

211 lines
6.7 KiB
TypeScript

/* eslint-disable react/no-children-prop */
"use client"
import { useForm } from "@tanstack/react-form"
import { toast } from "sonner"
import * as z from "zod"
import { Button } from "@/registry/new-york-v4/ui/button"
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/registry/new-york-v4/ui/card"
import { Checkbox } from "@/registry/new-york-v4/ui/checkbox"
import {
Field,
FieldDescription,
FieldError,
FieldGroup,
FieldLabel,
FieldLegend,
FieldSeparator,
FieldSet,
} from "@/registry/new-york-v4/ui/field"
const tasks = [
{
id: "push",
label: "Push notifications",
},
{
id: "email",
label: "Email notifications",
},
] as const
const formSchema = z.object({
responses: z.boolean(),
tasks: z
.array(z.string())
.min(1, "Please select at least one notification type.")
.refine(
(value) => value.every((task) => tasks.some((t) => t.id === task)),
{
message: "Invalid notification type selected.",
}
),
})
export default function FormTanstackCheckbox() {
const form = useForm({
defaultValues: {
responses: true,
tasks: [] as string[],
},
validators: {
onSubmit: formSchema,
},
onSubmit: async ({ value }) => {
toast("You submitted the following values:", {
description: (
<pre className="mt-2 w-[320px] overflow-x-auto rounded-md bg-code p-4 text-code-foreground">
<code>{JSON.stringify(value, null, 2)}</code>
</pre>
),
position: "bottom-right",
classNames: {
content: "flex flex-col gap-2",
},
style: {
"--border-radius": "calc(var(--radius) + 4px)",
} as React.CSSProperties,
})
},
})
return (
<Card className="w-full sm:max-w-md">
<CardHeader>
<CardTitle>Notifications</CardTitle>
<CardDescription>Manage your notification preferences.</CardDescription>
</CardHeader>
<CardContent>
<form
id="form-tanstack-checkbox"
onSubmit={(e) => {
e.preventDefault()
form.handleSubmit()
}}
>
<FieldGroup>
<form.Field
name="responses"
children={(field) => {
const isInvalid =
field.state.meta.isTouched && !field.state.meta.isValid
return (
<div>
<FieldSet>
<FieldLegend variant="label">Responses</FieldLegend>
<FieldDescription>
Get notified for requests that take time, like research
or image generation.
</FieldDescription>
<FieldGroup data-slot="checkbox-group">
<Field
orientation="horizontal"
data-invalid={isInvalid}
>
<Checkbox
id="form-tanstack-checkbox-responses"
name={field.name}
checked={field.state.value}
onCheckedChange={(checked) =>
field.handleChange(checked === true)
}
disabled
/>
<FieldLabel
htmlFor="form-tanstack-checkbox-responses"
className="font-normal"
>
Push notifications
</FieldLabel>
</Field>
</FieldGroup>
</FieldSet>
{isInvalid && (
<FieldError errors={field.state.meta.errors} />
)}
</div>
)
}}
/>
<FieldSeparator />
<form.Field
name="tasks"
mode="array"
children={(field) => {
const isInvalid =
field.state.meta.isTouched && !field.state.meta.isValid
return (
<FieldGroup>
<FieldSet data-invalid={isInvalid}>
<FieldLegend variant="label">Tasks</FieldLegend>
<FieldDescription>
Get notified when tasks you&apos;ve created have
updates.
</FieldDescription>
<FieldGroup data-slot="checkbox-group">
{tasks.map((task) => (
<Field
key={task.id}
orientation="horizontal"
data-invalid={isInvalid}
>
<Checkbox
id={`form-tanstack-checkbox-${task.id}`}
name={field.name}
aria-invalid={isInvalid}
checked={field.state.value.includes(task.id)}
onCheckedChange={(checked) => {
if (checked) {
field.pushValue(task.id)
} else {
const index = field.state.value.indexOf(
task.id
)
if (index > -1) {
field.removeValue(index)
}
}
}}
/>
<FieldLabel
htmlFor={`form-tanstack-checkbox-${task.id}`}
className="font-normal"
>
{task.label}
</FieldLabel>
</Field>
))}
</FieldGroup>
</FieldSet>
{isInvalid && (
<FieldError errors={field.state.meta.errors} />
)}
</FieldGroup>
)
}}
/>
</FieldGroup>
</form>
</CardContent>
<CardFooter>
<Field orientation="horizontal">
<Button type="button" variant="outline" onClick={() => form.reset()}>
Reset
</Button>
<Button type="submit" form="form-tanstack-checkbox">
Save
</Button>
</Field>
</CardFooter>
</Card>
)
}