create-huenei-frontend 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create-huenei-frontend.js +2 -0
- package/dist/index.js +99 -0
- package/dist/templates/clean/.cursor/skills/architecture/SKILL.md +26 -0
- package/dist/templates/clean/.cursor/skills/components-shadcn/SKILL.md +23 -0
- package/dist/templates/clean/.cursor/skills/daisyui/SKILL.md +98 -0
- package/dist/templates/clean/.cursor/skills/routing/SKILL.md +32 -0
- package/dist/templates/clean/.cursor/skills/testing/SKILL.md +55 -0
- package/dist/templates/clean/.cursor/skills/tooling-and-scripts/SKILL.md +24 -0
- package/dist/templates/clean/.cursor/skills/ui-and-styling/SKILL.md +32 -0
- package/dist/templates/clean/.cursor/skills/vibe-and-ia/SKILL.md +23 -0
- package/dist/templates/clean/.prettierrc +6 -0
- package/dist/templates/clean/.tanstack/tmp/c28007bb-2319511cf318e28129c8d8eb723db5fd +9 -0
- package/dist/templates/clean/.tanstack/tmp/c28007bb-bcef89e9e4593777e1c15ec4b4f32eea +9 -0
- package/dist/templates/clean/.vscode/extensions.json +7 -0
- package/dist/templates/clean/README.md +75 -0
- package/dist/templates/clean/components.json +22 -0
- package/dist/templates/clean/eslint.config.js +31 -0
- package/dist/templates/clean/index.html +13 -0
- package/dist/templates/clean/package.json +62 -0
- package/dist/templates/clean/pnpm-lock.yaml +4487 -0
- package/dist/templates/clean/pnpm-workspace.yaml +2 -0
- package/dist/templates/clean/src/assets/react.svg +1 -0
- package/dist/templates/clean/src/components/ui/badge.tsx +37 -0
- package/dist/templates/clean/src/components/ui/breadcrumb.tsx +106 -0
- package/dist/templates/clean/src/components/ui/button.tsx +58 -0
- package/dist/templates/clean/src/components/ui/card.tsx +72 -0
- package/dist/templates/clean/src/components/ui/form.tsx +165 -0
- package/dist/templates/clean/src/components/ui/input.tsx +22 -0
- package/dist/templates/clean/src/components/ui/label.tsx +24 -0
- package/dist/templates/clean/src/components/ui/password-input.tsx +41 -0
- package/dist/templates/clean/src/components/ui/separator.tsx +28 -0
- package/dist/templates/clean/src/components/ui/tabs.tsx +62 -0
- package/dist/templates/clean/src/components/ui/textarea.tsx +21 -0
- package/dist/templates/clean/src/index.css +104 -0
- package/dist/templates/clean/src/lib/queryClient.ts +11 -0
- package/dist/templates/clean/src/lib/utils.ts +6 -0
- package/dist/templates/clean/src/main.tsx +33 -0
- package/dist/templates/clean/src/routeTree.gen.ts +77 -0
- package/dist/templates/clean/src/router.tsx +13 -0
- package/dist/templates/clean/src/routes/__root.tsx +82 -0
- package/dist/templates/clean/src/routes/index.tsx +187 -0
- package/dist/templates/clean/src/routes/otra-ruta.tsx +319 -0
- package/dist/templates/clean/src/test/setup.ts +1 -0
- package/dist/templates/clean/tsconfig.app.json +34 -0
- package/dist/templates/clean/tsconfig.json +10 -0
- package/dist/templates/clean/tsconfig.node.json +26 -0
- package/dist/templates/clean/vite.config.ts +22 -0
- package/dist/templates/clean/vitest.config.ts +9 -0
- package/dist/templates/help/.cursor/skills/architecture/SKILL.md +26 -0
- package/dist/templates/help/.cursor/skills/components-shadcn/SKILL.md +23 -0
- package/dist/templates/help/.cursor/skills/daisyui/SKILL.md +98 -0
- package/dist/templates/help/.cursor/skills/routing/SKILL.md +32 -0
- package/dist/templates/help/.cursor/skills/testing/SKILL.md +55 -0
- package/dist/templates/help/.cursor/skills/tooling-and-scripts/SKILL.md +24 -0
- package/dist/templates/help/.cursor/skills/ui-and-styling/SKILL.md +32 -0
- package/dist/templates/help/.cursor/skills/vibe-and-ia/SKILL.md +23 -0
- package/dist/templates/help/.prettierrc +6 -0
- package/dist/templates/help/.tanstack/tmp/c28007bb-2319511cf318e28129c8d8eb723db5fd +9 -0
- package/dist/templates/help/.tanstack/tmp/c28007bb-bcef89e9e4593777e1c15ec4b4f32eea +9 -0
- package/dist/templates/help/.vscode/extensions.json +7 -0
- package/dist/templates/help/README.md +75 -0
- package/dist/templates/help/components.json +22 -0
- package/dist/templates/help/eslint.config.js +31 -0
- package/dist/templates/help/index.html +13 -0
- package/dist/templates/help/package.json +62 -0
- package/dist/templates/help/pnpm-lock.yaml +4487 -0
- package/dist/templates/help/pnpm-workspace.yaml +2 -0
- package/dist/templates/help/src/assets/react.svg +1 -0
- package/dist/templates/help/src/components/documentacion/entorno.tsx +99 -0
- package/dist/templates/help/src/components/documentacion/estructura.tsx +100 -0
- package/dist/templates/help/src/components/documentacion/figma-mcp.tsx +200 -0
- package/dist/templates/help/src/components/documentacion/inicio.tsx +69 -0
- package/dist/templates/help/src/components/documentacion/instalacion.tsx +72 -0
- package/dist/templates/help/src/components/documentacion/personalizacion.tsx +163 -0
- package/dist/templates/help/src/components/documentacion/rutas.tsx +138 -0
- package/dist/templates/help/src/components/documentacion/stack.tsx +401 -0
- package/dist/templates/help/src/components/ui/badge.tsx +37 -0
- package/dist/templates/help/src/components/ui/breadcrumb.tsx +106 -0
- package/dist/templates/help/src/components/ui/button.tsx +58 -0
- package/dist/templates/help/src/components/ui/card.tsx +72 -0
- package/dist/templates/help/src/components/ui/form.tsx +165 -0
- package/dist/templates/help/src/components/ui/input.tsx +22 -0
- package/dist/templates/help/src/components/ui/label.tsx +24 -0
- package/dist/templates/help/src/components/ui/password-input.tsx +41 -0
- package/dist/templates/help/src/components/ui/separator.tsx +28 -0
- package/dist/templates/help/src/components/ui/tabs.tsx +62 -0
- package/dist/templates/help/src/components/ui/textarea.tsx +21 -0
- package/dist/templates/help/src/data/proyectos.json +56 -0
- package/dist/templates/help/src/index.css +104 -0
- package/dist/templates/help/src/lib/queryClient.ts +11 -0
- package/dist/templates/help/src/lib/utils.ts +6 -0
- package/dist/templates/help/src/main.tsx +33 -0
- package/dist/templates/help/src/routeTree.gen.ts +241 -0
- package/dist/templates/help/src/router.tsx +13 -0
- package/dist/templates/help/src/routes/__root.tsx +92 -0
- package/dist/templates/help/src/routes/auth/iniciar-sesion.tsx +139 -0
- package/dist/templates/help/src/routes/auth/registro.tsx +205 -0
- package/dist/templates/help/src/routes/contacto.tsx +60 -0
- package/dist/templates/help/src/routes/dashbord.tsx +9 -0
- package/dist/templates/help/src/routes/documentacion.tsx +80 -0
- package/dist/templates/help/src/routes/index.test.tsx +42 -0
- package/dist/templates/help/src/routes/index.tsx +211 -0
- package/dist/templates/help/src/routes/perfil.tsx +9 -0
- package/dist/templates/help/src/routes/proyectos.$proyectoId.tsx +156 -0
- package/dist/templates/help/src/routes/proyectos.tsx +93 -0
- package/dist/templates/help/src/test/setup.ts +1 -0
- package/dist/templates/help/tsconfig.app.json +34 -0
- package/dist/templates/help/tsconfig.json +10 -0
- package/dist/templates/help/tsconfig.node.json +26 -0
- package/dist/templates/help/vite.config.ts +22 -0
- package/dist/templates/help/vitest.config.ts +9 -0
- package/dist/test-cli.js +48 -0
- package/package.json +25 -0
- package/templates/clean/.cursor/skills/architecture/SKILL.md +26 -0
- package/templates/clean/.cursor/skills/components-shadcn/SKILL.md +23 -0
- package/templates/clean/.cursor/skills/daisyui/SKILL.md +98 -0
- package/templates/clean/.cursor/skills/routing/SKILL.md +32 -0
- package/templates/clean/.cursor/skills/testing/SKILL.md +55 -0
- package/templates/clean/.cursor/skills/tooling-and-scripts/SKILL.md +24 -0
- package/templates/clean/.cursor/skills/ui-and-styling/SKILL.md +32 -0
- package/templates/clean/.cursor/skills/vibe-and-ia/SKILL.md +23 -0
- package/templates/clean/.prettierrc +6 -0
- package/templates/clean/.tanstack/tmp/c28007bb-2319511cf318e28129c8d8eb723db5fd +9 -0
- package/templates/clean/.tanstack/tmp/c28007bb-bcef89e9e4593777e1c15ec4b4f32eea +9 -0
- package/templates/clean/.vscode/extensions.json +7 -0
- package/templates/clean/README.md +75 -0
- package/templates/clean/components.json +22 -0
- package/templates/clean/eslint.config.js +31 -0
- package/templates/clean/index.html +13 -0
- package/templates/clean/package.json +62 -0
- package/templates/clean/pnpm-lock.yaml +4487 -0
- package/templates/clean/pnpm-workspace.yaml +2 -0
- package/templates/clean/src/assets/react.svg +1 -0
- package/templates/clean/src/components/ui/badge.tsx +37 -0
- package/templates/clean/src/components/ui/breadcrumb.tsx +106 -0
- package/templates/clean/src/components/ui/button.tsx +58 -0
- package/templates/clean/src/components/ui/card.tsx +72 -0
- package/templates/clean/src/components/ui/form.tsx +165 -0
- package/templates/clean/src/components/ui/input.tsx +22 -0
- package/templates/clean/src/components/ui/label.tsx +24 -0
- package/templates/clean/src/components/ui/password-input.tsx +41 -0
- package/templates/clean/src/components/ui/separator.tsx +28 -0
- package/templates/clean/src/components/ui/tabs.tsx +62 -0
- package/templates/clean/src/components/ui/textarea.tsx +21 -0
- package/templates/clean/src/index.css +104 -0
- package/templates/clean/src/lib/queryClient.ts +11 -0
- package/templates/clean/src/lib/utils.ts +6 -0
- package/templates/clean/src/main.tsx +33 -0
- package/templates/clean/src/routeTree.gen.ts +77 -0
- package/templates/clean/src/router.tsx +13 -0
- package/templates/clean/src/routes/__root.tsx +82 -0
- package/templates/clean/src/routes/index.tsx +187 -0
- package/templates/clean/src/routes/otra-ruta.tsx +319 -0
- package/templates/clean/src/test/setup.ts +1 -0
- package/templates/clean/tsconfig.app.json +34 -0
- package/templates/clean/tsconfig.json +10 -0
- package/templates/clean/tsconfig.node.json +26 -0
- package/templates/clean/vite.config.ts +22 -0
- package/templates/clean/vitest.config.ts +9 -0
- package/templates/help/.cursor/skills/architecture/SKILL.md +26 -0
- package/templates/help/.cursor/skills/components-shadcn/SKILL.md +23 -0
- package/templates/help/.cursor/skills/daisyui/SKILL.md +98 -0
- package/templates/help/.cursor/skills/routing/SKILL.md +32 -0
- package/templates/help/.cursor/skills/testing/SKILL.md +55 -0
- package/templates/help/.cursor/skills/tooling-and-scripts/SKILL.md +24 -0
- package/templates/help/.cursor/skills/ui-and-styling/SKILL.md +32 -0
- package/templates/help/.cursor/skills/vibe-and-ia/SKILL.md +23 -0
- package/templates/help/.prettierrc +6 -0
- package/templates/help/.tanstack/tmp/c28007bb-2319511cf318e28129c8d8eb723db5fd +9 -0
- package/templates/help/.tanstack/tmp/c28007bb-bcef89e9e4593777e1c15ec4b4f32eea +9 -0
- package/templates/help/.vscode/extensions.json +7 -0
- package/templates/help/README.md +75 -0
- package/templates/help/components.json +22 -0
- package/templates/help/eslint.config.js +31 -0
- package/templates/help/index.html +13 -0
- package/templates/help/package.json +62 -0
- package/templates/help/pnpm-lock.yaml +4487 -0
- package/templates/help/pnpm-workspace.yaml +2 -0
- package/templates/help/src/assets/react.svg +1 -0
- package/templates/help/src/components/documentacion/entorno.tsx +99 -0
- package/templates/help/src/components/documentacion/estructura.tsx +100 -0
- package/templates/help/src/components/documentacion/figma-mcp.tsx +200 -0
- package/templates/help/src/components/documentacion/inicio.tsx +69 -0
- package/templates/help/src/components/documentacion/instalacion.tsx +72 -0
- package/templates/help/src/components/documentacion/personalizacion.tsx +163 -0
- package/templates/help/src/components/documentacion/rutas.tsx +138 -0
- package/templates/help/src/components/documentacion/stack.tsx +401 -0
- package/templates/help/src/components/ui/badge.tsx +37 -0
- package/templates/help/src/components/ui/breadcrumb.tsx +106 -0
- package/templates/help/src/components/ui/button.tsx +58 -0
- package/templates/help/src/components/ui/card.tsx +72 -0
- package/templates/help/src/components/ui/form.tsx +165 -0
- package/templates/help/src/components/ui/input.tsx +22 -0
- package/templates/help/src/components/ui/label.tsx +24 -0
- package/templates/help/src/components/ui/password-input.tsx +41 -0
- package/templates/help/src/components/ui/separator.tsx +28 -0
- package/templates/help/src/components/ui/tabs.tsx +62 -0
- package/templates/help/src/components/ui/textarea.tsx +21 -0
- package/templates/help/src/data/proyectos.json +56 -0
- package/templates/help/src/index.css +104 -0
- package/templates/help/src/lib/queryClient.ts +11 -0
- package/templates/help/src/lib/utils.ts +6 -0
- package/templates/help/src/main.tsx +33 -0
- package/templates/help/src/routeTree.gen.ts +241 -0
- package/templates/help/src/router.tsx +13 -0
- package/templates/help/src/routes/__root.tsx +92 -0
- package/templates/help/src/routes/auth/iniciar-sesion.tsx +139 -0
- package/templates/help/src/routes/auth/registro.tsx +205 -0
- package/templates/help/src/routes/contacto.tsx +60 -0
- package/templates/help/src/routes/dashbord.tsx +9 -0
- package/templates/help/src/routes/documentacion.tsx +80 -0
- package/templates/help/src/routes/index.test.tsx +42 -0
- package/templates/help/src/routes/index.tsx +211 -0
- package/templates/help/src/routes/perfil.tsx +9 -0
- package/templates/help/src/routes/proyectos.$proyectoId.tsx +156 -0
- package/templates/help/src/routes/proyectos.tsx +93 -0
- package/templates/help/src/test/setup.ts +1 -0
- package/templates/help/tsconfig.app.json +34 -0
- package/templates/help/tsconfig.json +10 -0
- package/templates/help/tsconfig.node.json +26 -0
- package/templates/help/vite.config.ts +22 -0
- package/templates/help/vitest.config.ts +9 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
|
2
|
+
import { Badge } from "@/components/ui/badge";
|
|
3
|
+
import { Separator } from "@/components/ui/separator";
|
|
4
|
+
import { Zap, Code, FileText, Database, Palette } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
export function StackTab() {
|
|
7
|
+
return (
|
|
8
|
+
<>
|
|
9
|
+
<Card>
|
|
10
|
+
<CardHeader>
|
|
11
|
+
<CardTitle>Índice del Stack Tecnológico</CardTitle>
|
|
12
|
+
</CardHeader>
|
|
13
|
+
<CardContent>
|
|
14
|
+
<div className="p-4 bg-slate-50 dark:bg-slate-800 rounded-lg border border-slate-200 dark:border-slate-700">
|
|
15
|
+
<ul className="space-y-2 text-sm">
|
|
16
|
+
<li>
|
|
17
|
+
<a href="#stack-vite" className="text-blue-600 hover:underline">
|
|
18
|
+
Vite
|
|
19
|
+
</a>
|
|
20
|
+
</li>
|
|
21
|
+
<li>
|
|
22
|
+
<a href="#stack-react" className="text-blue-600 hover:underline">
|
|
23
|
+
React 19 + TypeScript
|
|
24
|
+
</a>
|
|
25
|
+
</li>
|
|
26
|
+
<li>
|
|
27
|
+
<a href="#stack-zod" className="text-blue-600 hover:underline">
|
|
28
|
+
Zod - Validación de Esquemas
|
|
29
|
+
</a>
|
|
30
|
+
</li>
|
|
31
|
+
<li>
|
|
32
|
+
<a href="#stack-query" className="text-blue-600 hover:underline">
|
|
33
|
+
TanStack Query
|
|
34
|
+
</a>
|
|
35
|
+
</li>
|
|
36
|
+
<li>
|
|
37
|
+
<a href="#stack-router" className="text-blue-600 hover:underline">
|
|
38
|
+
TanStack Router
|
|
39
|
+
</a>
|
|
40
|
+
</li>
|
|
41
|
+
<li>
|
|
42
|
+
<a href="#stack-tailwind" className="text-blue-600 hover:underline">
|
|
43
|
+
Tailwind CSS v4
|
|
44
|
+
</a>
|
|
45
|
+
</li>
|
|
46
|
+
<li>
|
|
47
|
+
<a href="#stack-shadcn" className="text-blue-600 hover:underline">
|
|
48
|
+
shadcn/ui
|
|
49
|
+
</a>
|
|
50
|
+
</li>
|
|
51
|
+
</ul>
|
|
52
|
+
</div>
|
|
53
|
+
</CardContent>
|
|
54
|
+
</Card>
|
|
55
|
+
{/* Vite */}
|
|
56
|
+
<Card id="stack-vite">
|
|
57
|
+
<CardHeader>
|
|
58
|
+
<div className="flex items-center gap-2">
|
|
59
|
+
<Zap className="h-5 w-5" />
|
|
60
|
+
<CardTitle>Vite</CardTitle>
|
|
61
|
+
</div>
|
|
62
|
+
<CardDescription>Build tool ultra-rápido para desarrollo y producción.</CardDescription>
|
|
63
|
+
</CardHeader>
|
|
64
|
+
<CardContent className="space-y-4">
|
|
65
|
+
<div>
|
|
66
|
+
<h3 className="text-lg font-semibold mb-2">Características</h3>
|
|
67
|
+
<ul className="list-disc list-inside space-y-2 text-slate-600">
|
|
68
|
+
<li>HMR (Hot Module Replacement) instantáneo</li>
|
|
69
|
+
<li>Build optimizado con rolldown</li>
|
|
70
|
+
<li>
|
|
71
|
+
Configuración en <code className="bg-slate-100 px-1 rounded">vite.config.ts</code>
|
|
72
|
+
</li>
|
|
73
|
+
</ul>
|
|
74
|
+
</div>
|
|
75
|
+
<Separator />
|
|
76
|
+
<div>
|
|
77
|
+
<h3 className="text-lg font-semibold mb-2">Scripts disponibles</h3>
|
|
78
|
+
<div className="bg-slate-100 rounded-lg p-4 font-mono text-sm space-y-2">
|
|
79
|
+
<div>
|
|
80
|
+
<code>pnpm dev</code> - Servidor de desarrollo
|
|
81
|
+
</div>
|
|
82
|
+
<div>
|
|
83
|
+
<code>pnpm build</code> - Build para producción
|
|
84
|
+
</div>
|
|
85
|
+
<div>
|
|
86
|
+
<code>pnpm preview</code> - Preview del build
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</CardContent>
|
|
91
|
+
</Card>
|
|
92
|
+
|
|
93
|
+
{/* React + TypeScript */}
|
|
94
|
+
<Card id="stack-react">
|
|
95
|
+
<CardHeader>
|
|
96
|
+
<div className="flex items-center gap-2">
|
|
97
|
+
<Code className="h-5 w-5" />
|
|
98
|
+
<CardTitle>React 19 + TypeScript</CardTitle>
|
|
99
|
+
</div>
|
|
100
|
+
<CardDescription>Framework y lenguaje base del proyecto.</CardDescription>
|
|
101
|
+
</CardHeader>
|
|
102
|
+
<CardContent className="space-y-4">
|
|
103
|
+
<div>
|
|
104
|
+
<h3 className="text-lg font-semibold mb-2">Características</h3>
|
|
105
|
+
<ul className="list-disc list-inside space-y-2 text-slate-600">
|
|
106
|
+
<li>React 19 con todas sus mejoras</li>
|
|
107
|
+
<li>TypeScript estricto para type safety</li>
|
|
108
|
+
<li>React Compiler habilitado para optimizaciones automáticas</li>
|
|
109
|
+
<li>StrictMode activado por defecto</li>
|
|
110
|
+
</ul>
|
|
111
|
+
</div>
|
|
112
|
+
<Separator />
|
|
113
|
+
<div>
|
|
114
|
+
<h3 className="text-lg font-semibold mb-2">Configuración</h3>
|
|
115
|
+
<ul className="list-disc list-inside space-y-2 text-slate-600">
|
|
116
|
+
<li>
|
|
117
|
+
<code className="bg-slate-100 px-1 rounded">tsconfig.json</code> - Configuración
|
|
118
|
+
principal
|
|
119
|
+
</li>
|
|
120
|
+
<li>
|
|
121
|
+
<code className="bg-slate-100 px-1 rounded">tsconfig.app.json</code> - Configuración
|
|
122
|
+
de la app
|
|
123
|
+
</li>
|
|
124
|
+
<li>
|
|
125
|
+
Alias <code className="bg-slate-100 px-1 rounded">@/</code> configurado para imports
|
|
126
|
+
</li>
|
|
127
|
+
</ul>
|
|
128
|
+
</div>
|
|
129
|
+
</CardContent>
|
|
130
|
+
</Card>
|
|
131
|
+
|
|
132
|
+
{/* Zod */}
|
|
133
|
+
<Card id="stack-zod">
|
|
134
|
+
<CardHeader>
|
|
135
|
+
<div className="flex items-center gap-2">
|
|
136
|
+
<FileText className="h-5 w-5" />
|
|
137
|
+
<CardTitle>Zod - Validación de Esquemas</CardTitle>
|
|
138
|
+
</div>
|
|
139
|
+
<CardDescription>
|
|
140
|
+
Validación de datos y tipos con TypeScript-first schema validation.
|
|
141
|
+
</CardDescription>
|
|
142
|
+
</CardHeader>
|
|
143
|
+
<CardContent className="space-y-4">
|
|
144
|
+
<div>
|
|
145
|
+
<h3 className="text-lg font-semibold mb-2">Uso con React Hook Form</h3>
|
|
146
|
+
<p className="text-slate-600 mb-3">
|
|
147
|
+
Zod se integra perfectamente con React Hook Form usando{" "}
|
|
148
|
+
<code className="bg-slate-100 px-1 rounded">@hookform/resolvers</code>:
|
|
149
|
+
</p>
|
|
150
|
+
<div className="bg-slate-100 rounded-lg p-4 font-mono text-sm">
|
|
151
|
+
<pre className="text-xs">
|
|
152
|
+
{`import { useForm } from "react-hook-form";
|
|
153
|
+
import { standardSchemaResolver } from "@hookform/resolvers/standard-schema";
|
|
154
|
+
import * as z from "zod";
|
|
155
|
+
|
|
156
|
+
const schema = z.object({
|
|
157
|
+
email: z.string().email("El email no es válido"),
|
|
158
|
+
password: z.string().min(6, "Mínimo 6 caracteres"),
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
type FormValues = z.infer<typeof schema>;
|
|
162
|
+
|
|
163
|
+
const form = useForm<FormValues>({
|
|
164
|
+
resolver: standardSchemaResolver(schema),
|
|
165
|
+
});`}
|
|
166
|
+
</pre>
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
<Separator />
|
|
170
|
+
<div>
|
|
171
|
+
<h3 className="text-lg font-semibold mb-2">Ventajas</h3>
|
|
172
|
+
<ul className="list-disc list-inside space-y-2 text-slate-600">
|
|
173
|
+
<li>Type safety end-to-end</li>
|
|
174
|
+
<li>Validación en runtime y compile-time</li>
|
|
175
|
+
<li>Mensajes de error personalizables</li>
|
|
176
|
+
<li>Inferencia automática de tipos TypeScript</li>
|
|
177
|
+
</ul>
|
|
178
|
+
</div>
|
|
179
|
+
</CardContent>
|
|
180
|
+
</Card>
|
|
181
|
+
|
|
182
|
+
{/* TanStack Query */}
|
|
183
|
+
<Card id="stack-query">
|
|
184
|
+
<CardHeader>
|
|
185
|
+
<div className="flex items-center gap-2">
|
|
186
|
+
<Database className="h-5 w-5" />
|
|
187
|
+
<CardTitle>TanStack Query</CardTitle>
|
|
188
|
+
</div>
|
|
189
|
+
<CardDescription>
|
|
190
|
+
Manejo de estado del servidor, caché y sincronización de datos.
|
|
191
|
+
</CardDescription>
|
|
192
|
+
</CardHeader>
|
|
193
|
+
<CardContent className="space-y-4">
|
|
194
|
+
<div>
|
|
195
|
+
<h3 className="text-lg font-semibold mb-2">Configuración</h3>
|
|
196
|
+
<p className="text-slate-600 mb-3">
|
|
197
|
+
El QueryClient está configurado en{" "}
|
|
198
|
+
<code className="bg-slate-100 px-1 rounded">src/lib/queryClient.ts</code>:
|
|
199
|
+
</p>
|
|
200
|
+
<div className="bg-slate-100 rounded-lg p-4 font-mono text-sm">
|
|
201
|
+
<pre className="text-xs">
|
|
202
|
+
{`export const queryClient = new QueryClient({
|
|
203
|
+
defaultOptions: {
|
|
204
|
+
queries: {
|
|
205
|
+
staleTime: 60_000, // 1 minuto
|
|
206
|
+
retry: 1,
|
|
207
|
+
refetchOnWindowFocus: false,
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
});`}
|
|
211
|
+
</pre>
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
<Separator />
|
|
215
|
+
<div>
|
|
216
|
+
<h3 className="text-lg font-semibold mb-2">Ejemplo de uso</h3>
|
|
217
|
+
<div className="bg-slate-100 rounded-lg p-4 font-mono text-sm">
|
|
218
|
+
<pre className="text-xs">
|
|
219
|
+
{`import { useQuery } from '@tanstack/react-query';
|
|
220
|
+
|
|
221
|
+
function MyComponent() {
|
|
222
|
+
const { data, isLoading, error } = useQuery({
|
|
223
|
+
queryKey: ['users'],
|
|
224
|
+
queryFn: async () => {
|
|
225
|
+
const res = await fetch('/api/users');
|
|
226
|
+
return res.json();
|
|
227
|
+
},
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
if (isLoading) return <div>Loading...</div>;
|
|
231
|
+
if (error) return <div>Error: {error.message}</div>;
|
|
232
|
+
|
|
233
|
+
return <div>{/* Render data */}</div>;
|
|
234
|
+
}`}
|
|
235
|
+
</pre>
|
|
236
|
+
</div>
|
|
237
|
+
</div>
|
|
238
|
+
<Separator />
|
|
239
|
+
<div>
|
|
240
|
+
<h3 className="text-lg font-semibold mb-2">DevTools</h3>
|
|
241
|
+
<p className="text-slate-600">
|
|
242
|
+
TanStack Query DevTools está disponible en desarrollo para inspeccionar queries, caché
|
|
243
|
+
y estado.
|
|
244
|
+
</p>
|
|
245
|
+
</div>
|
|
246
|
+
</CardContent>
|
|
247
|
+
</Card>
|
|
248
|
+
|
|
249
|
+
{/* TanStack Router */}
|
|
250
|
+
<Card id="stack-router">
|
|
251
|
+
<CardHeader>
|
|
252
|
+
<div className="flex items-center gap-2">
|
|
253
|
+
<Zap className="h-5 w-5" />
|
|
254
|
+
<CardTitle>TanStack Router</CardTitle>
|
|
255
|
+
</div>
|
|
256
|
+
<CardDescription>Enrutamiento type-safe y file-based routing.</CardDescription>
|
|
257
|
+
</CardHeader>
|
|
258
|
+
<CardContent className="space-y-4">
|
|
259
|
+
<div>
|
|
260
|
+
<h3 className="text-lg font-semibold mb-2">File-based Routing</h3>
|
|
261
|
+
<p className="text-slate-600 mb-3">
|
|
262
|
+
Las rutas se generan automáticamente desde la estructura de archivos en{" "}
|
|
263
|
+
<code className="bg-slate-100 px-1 rounded">src/routes/</code>:
|
|
264
|
+
</p>
|
|
265
|
+
<ul className="list-disc list-inside space-y-2 text-slate-600">
|
|
266
|
+
<li>
|
|
267
|
+
<code className="bg-slate-100 px-1 rounded">index.tsx</code> → <code>/</code>
|
|
268
|
+
</li>
|
|
269
|
+
<li>
|
|
270
|
+
<code className="bg-slate-100 px-1 rounded">proyectos.tsx</code> →{" "}
|
|
271
|
+
<code>/proyectos</code>
|
|
272
|
+
</li>
|
|
273
|
+
<li>
|
|
274
|
+
<code className="bg-slate-100 px-1 rounded">proyectos.$proyectoId.tsx</code> →{" "}
|
|
275
|
+
<code>/proyectos/:proyectoId</code>
|
|
276
|
+
</li>
|
|
277
|
+
</ul>
|
|
278
|
+
</div>
|
|
279
|
+
<Separator />
|
|
280
|
+
<div>
|
|
281
|
+
<h3 className="text-lg font-semibold mb-2">Características</h3>
|
|
282
|
+
<ul className="list-disc list-inside space-y-2 text-slate-600">
|
|
283
|
+
<li>Type-safe routing con autocompletado</li>
|
|
284
|
+
<li>
|
|
285
|
+
Preload automático con{" "}
|
|
286
|
+
<code className="bg-slate-100 px-1 rounded">defaultPreload: 'intent'</code>
|
|
287
|
+
</li>
|
|
288
|
+
<li>Code splitting automático</li>
|
|
289
|
+
<li>Router DevTools para debugging</li>
|
|
290
|
+
</ul>
|
|
291
|
+
</div>
|
|
292
|
+
</CardContent>
|
|
293
|
+
</Card>
|
|
294
|
+
|
|
295
|
+
{/* Tailwind CSS */}
|
|
296
|
+
<Card id="stack-tailwind">
|
|
297
|
+
<CardHeader>
|
|
298
|
+
<div className="flex items-center gap-2">
|
|
299
|
+
<Palette className="h-5 w-5" />
|
|
300
|
+
<CardTitle>Tailwind CSS v4</CardTitle>
|
|
301
|
+
</div>
|
|
302
|
+
<CardDescription>Framework CSS utility-first con configuración moderna.</CardDescription>
|
|
303
|
+
</CardHeader>
|
|
304
|
+
<CardContent className="space-y-4">
|
|
305
|
+
<div>
|
|
306
|
+
<h3 className="text-lg font-semibold mb-2">Configuración</h3>
|
|
307
|
+
<p className="text-slate-600 mb-3">
|
|
308
|
+
Tailwind CSS v4 se configura directamente en el archivo CSS usando{" "}
|
|
309
|
+
<code className="bg-slate-100 px-1 rounded">@theme</code>:
|
|
310
|
+
</p>
|
|
311
|
+
<ul className="list-disc list-inside space-y-2 text-slate-600">
|
|
312
|
+
<li>
|
|
313
|
+
Plugin Vite: <code className="bg-slate-100 px-1 rounded">@tailwindcss/vite</code>
|
|
314
|
+
</li>
|
|
315
|
+
<li>
|
|
316
|
+
Configuración en <code className="bg-slate-100 px-1 rounded">src/index.css</code>
|
|
317
|
+
</li>
|
|
318
|
+
<li>No usar estilos inline</li>
|
|
319
|
+
<li>Mobile-first approach</li>
|
|
320
|
+
</ul>
|
|
321
|
+
</div>
|
|
322
|
+
<Separator />
|
|
323
|
+
<div>
|
|
324
|
+
<h3 className="text-lg font-semibold mb-2">Reglas importantes</h3>
|
|
325
|
+
<ul className="list-disc list-inside space-y-2 text-slate-600">
|
|
326
|
+
<li>Figma define layout, spacing y jerarquía</li>
|
|
327
|
+
<li>
|
|
328
|
+
Priorizar <code className="bg-slate-100 px-1 rounded">gap</code> sobre{" "}
|
|
329
|
+
<code className="bg-slate-100 px-1 rounded">margin</code>
|
|
330
|
+
</li>
|
|
331
|
+
<li>Usar tokens definidos, no valores arbitrarios</li>
|
|
332
|
+
<li>Mantener consistencia visual</li>
|
|
333
|
+
</ul>
|
|
334
|
+
</div>
|
|
335
|
+
</CardContent>
|
|
336
|
+
</Card>
|
|
337
|
+
|
|
338
|
+
{/* shadcn/ui */}
|
|
339
|
+
<Card id="stack-shadcn">
|
|
340
|
+
<CardHeader>
|
|
341
|
+
<div className="flex items-center gap-2">
|
|
342
|
+
<Code className="h-5 w-5" />
|
|
343
|
+
<CardTitle>shadcn/ui</CardTitle>
|
|
344
|
+
</div>
|
|
345
|
+
<CardDescription>
|
|
346
|
+
Componentes UI reutilizables construidos con Radix UI y Tailwind CSS.
|
|
347
|
+
</CardDescription>
|
|
348
|
+
</CardHeader>
|
|
349
|
+
<CardContent className="space-y-4">
|
|
350
|
+
<div>
|
|
351
|
+
<h3 className="text-lg font-semibold mb-3">Componentes instalados</h3>
|
|
352
|
+
<div className="flex flex-wrap gap-2">
|
|
353
|
+
<Badge>Card</Badge>
|
|
354
|
+
<Badge>Button</Badge>
|
|
355
|
+
<Badge>Badge</Badge>
|
|
356
|
+
<Badge>Input</Badge>
|
|
357
|
+
<Badge>PasswordInput</Badge>
|
|
358
|
+
<Badge>Textarea</Badge>
|
|
359
|
+
<Badge>Label</Badge>
|
|
360
|
+
<Badge>Form</Badge>
|
|
361
|
+
<Badge>Breadcrumb</Badge>
|
|
362
|
+
<Badge>Separator</Badge>
|
|
363
|
+
<Badge>Tabs</Badge>
|
|
364
|
+
</div>
|
|
365
|
+
</div>
|
|
366
|
+
<Separator />
|
|
367
|
+
<div>
|
|
368
|
+
<h3 className="text-lg font-semibold mb-2">Reglas de uso</h3>
|
|
369
|
+
<ul className="list-disc list-inside space-y-2 text-slate-600">
|
|
370
|
+
<li>
|
|
371
|
+
Importar desde <code className="bg-slate-100 px-1 rounded">@/components/ui</code>
|
|
372
|
+
</li>
|
|
373
|
+
<li>No modificar componentes base</li>
|
|
374
|
+
<li>Extender solo vía composición</li>
|
|
375
|
+
<li>Componentes UI sin lógica de negocio</li>
|
|
376
|
+
</ul>
|
|
377
|
+
</div>
|
|
378
|
+
<Separator />
|
|
379
|
+
<div>
|
|
380
|
+
<h3 className="text-lg font-semibold mb-2">Instalar nuevos componentes</h3>
|
|
381
|
+
<div className="bg-slate-100 rounded-lg p-4 font-mono text-sm mb-2">
|
|
382
|
+
<code>pnpm dlx shadcn@latest add [nombre-componente]</code>
|
|
383
|
+
</div>
|
|
384
|
+
<p className="text-sm text-slate-600">
|
|
385
|
+
Visita{" "}
|
|
386
|
+
<a
|
|
387
|
+
href="https://ui.shadcn.com/docs/components"
|
|
388
|
+
target="_blank"
|
|
389
|
+
rel="noopener noreferrer"
|
|
390
|
+
className="text-blue-600 hover:underline"
|
|
391
|
+
>
|
|
392
|
+
la documentación oficial
|
|
393
|
+
</a>{" "}
|
|
394
|
+
para ver todos los componentes disponibles.
|
|
395
|
+
</p>
|
|
396
|
+
</div>
|
|
397
|
+
</CardContent>
|
|
398
|
+
</Card>
|
|
399
|
+
</>
|
|
400
|
+
);
|
|
401
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
const badgeVariants = cva(
|
|
8
|
+
"badge inline-flex items-center justify-center px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none transition-colors overflow-hidden",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "badge-primary",
|
|
13
|
+
secondary: "badge-secondary",
|
|
14
|
+
destructive: "badge-error",
|
|
15
|
+
outline: "badge-outline",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
defaultVariants: {
|
|
19
|
+
variant: "default",
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
function Badge({
|
|
25
|
+
className,
|
|
26
|
+
variant,
|
|
27
|
+
asChild = false,
|
|
28
|
+
...props
|
|
29
|
+
}: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
|
30
|
+
const Comp = asChild ? Slot : "span";
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Comp data-slot="badge" className={cn(badgeVariants({ variant }), className)} {...props} />
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export { Badge, badgeVariants };
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { ChevronRight, MoreHorizontal } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
function Breadcrumb({ className, ...props }: React.ComponentProps<"nav">) {
|
|
8
|
+
return (
|
|
9
|
+
<nav
|
|
10
|
+
aria-label="breadcrumb"
|
|
11
|
+
data-slot="breadcrumb"
|
|
12
|
+
className={cn("breadcrumbs text-sm", className)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function BreadcrumbList({ className, ...props }: React.ComponentProps<"ol">) {
|
|
19
|
+
return (
|
|
20
|
+
<ol
|
|
21
|
+
data-slot="breadcrumb-list"
|
|
22
|
+
className={cn("flex flex-wrap items-center gap-1.5 wrap-break-words sm:gap-2.5", className)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function BreadcrumbItem({ className, ...props }: React.ComponentProps<"li">) {
|
|
29
|
+
return (
|
|
30
|
+
<li
|
|
31
|
+
data-slot="breadcrumb-item"
|
|
32
|
+
className={cn("inline-flex items-center gap-1.5", className)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function BreadcrumbLink({
|
|
39
|
+
asChild,
|
|
40
|
+
className,
|
|
41
|
+
...props
|
|
42
|
+
}: React.ComponentProps<"a"> & {
|
|
43
|
+
asChild?: boolean;
|
|
44
|
+
}) {
|
|
45
|
+
const Comp = asChild ? Slot : "a";
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Comp
|
|
49
|
+
data-slot="breadcrumb-link"
|
|
50
|
+
className={cn("hover:text-base-content transition-colors", className)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function BreadcrumbPage({ className, ...props }: React.ComponentProps<"span">) {
|
|
57
|
+
return (
|
|
58
|
+
<span
|
|
59
|
+
data-slot="breadcrumb-page"
|
|
60
|
+
role="link"
|
|
61
|
+
aria-disabled="true"
|
|
62
|
+
aria-current="page"
|
|
63
|
+
className={cn("text-base-content font-normal", className)}
|
|
64
|
+
{...props}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function BreadcrumbSeparator({ children, className, ...props }: React.ComponentProps<"li">) {
|
|
70
|
+
return (
|
|
71
|
+
<li
|
|
72
|
+
data-slot="breadcrumb-separator"
|
|
73
|
+
role="presentation"
|
|
74
|
+
aria-hidden="true"
|
|
75
|
+
className={cn("[&>svg]:size-3.5", className)}
|
|
76
|
+
{...props}
|
|
77
|
+
>
|
|
78
|
+
{children ?? <ChevronRight />}
|
|
79
|
+
</li>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function BreadcrumbEllipsis({ className, ...props }: React.ComponentProps<"span">) {
|
|
84
|
+
return (
|
|
85
|
+
<span
|
|
86
|
+
data-slot="breadcrumb-ellipsis"
|
|
87
|
+
role="presentation"
|
|
88
|
+
aria-hidden="true"
|
|
89
|
+
className={cn("flex size-9 items-center justify-center", className)}
|
|
90
|
+
{...props}
|
|
91
|
+
>
|
|
92
|
+
<MoreHorizontal className="size-4" />
|
|
93
|
+
<span className="sr-only">More</span>
|
|
94
|
+
</span>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export {
|
|
99
|
+
Breadcrumb,
|
|
100
|
+
BreadcrumbList,
|
|
101
|
+
BreadcrumbItem,
|
|
102
|
+
BreadcrumbLink,
|
|
103
|
+
BreadcrumbPage,
|
|
104
|
+
BreadcrumbSeparator,
|
|
105
|
+
BreadcrumbEllipsis,
|
|
106
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot"
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils"
|
|
6
|
+
|
|
7
|
+
const buttonVariants = cva(
|
|
8
|
+
"btn inline-flex items-center justify-center gap-2 whitespace-nowrap [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none disabled:pointer-events-none disabled:opacity-50",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "btn-primary",
|
|
13
|
+
destructive: "btn-error",
|
|
14
|
+
outline: "btn-outline btn-primary",
|
|
15
|
+
secondary: "btn-secondary",
|
|
16
|
+
ghost: "btn-ghost",
|
|
17
|
+
link: "btn-link",
|
|
18
|
+
},
|
|
19
|
+
size: {
|
|
20
|
+
default: "btn-md",
|
|
21
|
+
sm: "btn-sm",
|
|
22
|
+
lg: "btn-lg",
|
|
23
|
+
icon: "btn-square",
|
|
24
|
+
"icon-sm": "btn-square btn-sm",
|
|
25
|
+
"icon-lg": "btn-square btn-lg",
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
defaultVariants: {
|
|
29
|
+
variant: "default",
|
|
30
|
+
size: "default",
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
function Button({
|
|
36
|
+
className,
|
|
37
|
+
variant = "default",
|
|
38
|
+
size = "default",
|
|
39
|
+
asChild = false,
|
|
40
|
+
...props
|
|
41
|
+
}: React.ComponentProps<"button"> &
|
|
42
|
+
VariantProps<typeof buttonVariants> & {
|
|
43
|
+
asChild?: boolean
|
|
44
|
+
}) {
|
|
45
|
+
const Comp = asChild ? Slot : "button"
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Comp
|
|
49
|
+
data-slot="button"
|
|
50
|
+
data-variant={variant}
|
|
51
|
+
data-size={size}
|
|
52
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export { Button, buttonVariants }
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
function Card({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="card"
|
|
9
|
+
className={cn("card bg-base-100 shadow-sm border border-base-300 px-4 py-6", className)}
|
|
10
|
+
{...props}
|
|
11
|
+
/>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
16
|
+
return (
|
|
17
|
+
<div
|
|
18
|
+
data-slot="card-header"
|
|
19
|
+
className={cn(
|
|
20
|
+
"card-header @container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
21
|
+
className
|
|
22
|
+
)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function CardTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
29
|
+
return (
|
|
30
|
+
<div
|
|
31
|
+
data-slot="card-title"
|
|
32
|
+
className={cn("card-title leading-none font-semibold", className)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function CardDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
39
|
+
return (
|
|
40
|
+
<div
|
|
41
|
+
data-slot="card-description"
|
|
42
|
+
className={cn("text-base-content/70 text-sm", className)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function CardAction({ className, ...props }: React.ComponentProps<"div">) {
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
data-slot="card-action"
|
|
52
|
+
className={cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className)}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function CardContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
59
|
+
return <div data-slot="card-content" className={cn("card-body px-6", className)} {...props} />;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
63
|
+
return (
|
|
64
|
+
<div
|
|
65
|
+
data-slot="card-footer"
|
|
66
|
+
className={cn("card-actions flex items-center px-6 [.border-t]:pt-6", className)}
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };
|