Files
zeekay 16c4453cc1 feat: sync with upstream shadcn/ui (through [email protected])
Squash merge of shadcn-ui/ui main branch into hanzo/ui, bringing in:
- [email protected] through [email protected] releases
- New apps/v4 directory structure
- Registry system improvements and MCP server
- Framework support (Vue, Svelte, React Native)
- New templates (vite-app, monorepo-next, laravel)
- Zod 4 compatibility (scoped override for zod@>4)
- Test fixture corrections for alias resolution

All 867 merge conflicts resolved preserving Hanzo customizations.
1020/1020 shadcn tests pass.
2026-02-09 10:44:26 -08:00

74 lines
5.7 KiB
JSON

{
"name": "app-01",
"type": "registry:block",
"description": "A simple task app.",
"dependencies": [
"swr"
],
"registryDependencies": [
"card",
"input",
"button",
"skeleton",
"label"
],
"files": [
{
"path": "blocks/app-01/page.tsx",
"content": "import { AddTaskForm } from \"@/registry/new-york/blocks/app-01/components/add-task-form\"\nimport { TasksList } from \"@/registry/new-york/blocks/app-01/components/tasks-list\"\nimport {\n Card,\n CardContent,\n CardFooter,\n CardHeader,\n CardTitle,\n} from \"@/registry/new-york/ui/card\"\n\nexport default function AppPage() {\n return (\n <div className=\"h-screen flex flex-col items-center justify-center\">\n <Card className=\"w-full max-w-md\">\n <CardHeader>\n <CardTitle>Add Task</CardTitle>\n </CardHeader>\n <CardContent>\n <TasksList />\n </CardContent>\n <CardFooter>\n <AddTaskForm />\n </CardFooter>\n </Card>\n </div>\n )\n}\n",
"type": "registry:page",
"target": "app/page.tsx"
},
{
"path": "blocks/app-01/api/tasks/route.ts",
"content": "import { NextResponse } from \"next/server\"\n\nimport { API_URL } from \"@/registry/new-york/blocks/app-01/lib/constants\"\n\nexport async function GET() {\n const response = await fetch(API_URL)\n const data = await response.json()\n return NextResponse.json(data)\n}\n",
"type": "registry:page",
"target": "app/api/tasks/route.ts"
},
{
"path": "blocks/app-01/components/add-task-form.tsx",
"content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { Label } from \"@/registry/default/ui/label\"\nimport { SubmitButton } from \"@/registry/new-york/blocks/app-01/components/submit-button\"\nimport { useTasks } from \"@/registry/new-york/blocks/app-01/hooks/use-tasks\"\nimport { saveTask } from \"@/registry/new-york/blocks/app-01/lib/actions\"\nimport { Input } from \"@/registry/new-york/ui/input\"\n\nexport function AddTaskForm() {\n const { mutate } = useTasks()\n const formRef = React.useRef<HTMLFormElement>(null)\n\n return (\n <form\n action={async (formData) => {\n await saveTask(formData)\n void mutate()\n formRef.current?.reset()\n }}\n className=\"w-full\"\n ref={formRef}\n >\n <div className=\"flex flex-col gap-2\">\n <Label htmlFor=\"name\" className=\"sr-only\">\n Task Name\n </Label>\n <Input\n type=\"text\"\n name=\"name\"\n required\n autoComplete=\"off\"\n placeholder=\"Remember the milk\"\n />\n <SubmitButton className=\"w-full\">Add Task</SubmitButton>\n </div>\n </form>\n )\n}\n",
"type": "registry:component",
"target": ""
},
{
"path": "blocks/app-01/components/submit-button.tsx",
"content": "\"use client\"\n\nimport { Loader2 } from \"lucide-react\"\nimport { useFormStatus } from \"react-dom\"\n\nimport { Button } from \"@/registry/new-york/ui/button\"\n\nexport function SubmitButton({\n children,\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { pending } = useFormStatus()\n\n return (\n <Button type=\"submit\" disabled={pending} {...props}>\n {pending && <Loader2 className=\"animate-spin\" />}\n {children}\n </Button>\n )\n}\n",
"type": "registry:component",
"target": ""
},
{
"path": "blocks/app-01/components/tasks-list.tsx",
"content": "\"use client\"\n\nimport { useTasks } from \"@/registry/new-york/blocks/app-01/hooks/use-tasks\"\nimport { Skeleton } from \"@/registry/new-york/ui/skeleton\"\n\nexport function TasksList() {\n const { tasks, isLoading } = useTasks()\n\n if (isLoading)\n return (\n <div className=\"grid gap-2\">\n {Array.from({ length: 5 }).map((_, index) => (\n <Skeleton className=\"h-5 w-full\" key={index} />\n ))}\n </div>\n )\n\n return (\n <div className=\"grid gap-2\">\n {tasks.map((task, index) => (\n <div key={index} className=\"h-5 text-sm\">\n {task}\n </div>\n ))}\n </div>\n )\n}\n",
"type": "registry:component",
"target": ""
},
{
"path": "blocks/app-01/hooks/use-tasks.ts",
"content": "\"use client\"\n\nimport useSWR from \"swr\"\n\nimport { API_URL } from \"@/registry/new-york/blocks/app-01/lib/constants\"\n\nexport function useTasks() {\n const { data, isLoading, mutate } = useSWR<{ tasks: string[] }>(\n \"/api/tasks\",\n async () => {\n const response = await fetch(API_URL)\n return response.json()\n }\n )\n\n return { tasks: data?.tasks || [], isLoading, mutate }\n}\n",
"type": "registry:hook",
"target": ""
},
{
"path": "blocks/app-01/lib/constants.ts",
"content": "export const API_URL = \"https://api.npoint.io/40ac2c2a67c912fa2120\"\n",
"type": "registry:lib",
"target": ""
},
{
"path": "blocks/app-01/lib/actions.ts",
"content": "\"use server\"\n\nimport { API_URL } from \"@/registry/new-york/blocks/app-01/lib/constants\"\n\nexport async function saveTask(formData: FormData) {\n const name = formData.get(\"name\")\n\n // Get current tasks\n const response = await fetch(API_URL)\n const data = await response.json()\n const tasks = data.tasks || []\n\n // Add new task to array\n tasks.push(name)\n\n // Save updated tasks array\n await fetch(API_URL, {\n method: \"POST\",\n body: JSON.stringify({ tasks }),\n })\n\n return { success: true }\n}\n",
"type": "registry:lib",
"target": ""
}
],
"cssVars": {
"light": {
"primary": "224.3 76.3% 48%",
"primary-foreground": "0 0% 100%"
}
},
"categories": [
"apps"
]
}