create-lexy 0.3.1 → 0.4.0

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.
Files changed (61) hide show
  1. package/assets/r/accordion.json +1 -1
  2. package/assets/r/alert-dialog.json +1 -1
  3. package/assets/r/app-accordion.json +1 -1
  4. package/assets/r/app-dialog.json +1 -1
  5. package/assets/r/app-header-bar.json +1 -1
  6. package/assets/r/app-sidebar.json +1 -1
  7. package/assets/r/avatar.json +1 -1
  8. package/assets/r/badge.json +1 -1
  9. package/assets/r/breadcrumb.json +1 -1
  10. package/assets/r/button-group.json +1 -1
  11. package/assets/r/button.json +1 -1
  12. package/assets/r/calendar.json +1 -1
  13. package/assets/r/card.json +1 -1
  14. package/assets/r/chart.json +1 -1
  15. package/assets/r/checkbox.json +1 -1
  16. package/assets/r/combobox.json +1 -1
  17. package/assets/r/command.json +1 -1
  18. package/assets/r/confirmacion.json +1 -1
  19. package/assets/r/counter-badge.json +1 -1
  20. package/assets/r/crm-app-layout.json +1 -1
  21. package/assets/r/crm-desk.json +1 -1
  22. package/assets/r/crm-detalle-caso.json +1 -1
  23. package/assets/r/date-picker.json +1 -1
  24. package/assets/r/dialog.json +1 -1
  25. package/assets/r/dropdown-menu.json +1 -1
  26. package/assets/r/empty.json +1 -1
  27. package/assets/r/feature-card.json +1 -1
  28. package/assets/r/form.json +1 -1
  29. package/assets/r/header-bar.json +1 -1
  30. package/assets/r/intake-wizard.json +1 -1
  31. package/assets/r/label.json +1 -1
  32. package/assets/r/login.json +1 -1
  33. package/assets/r/logo.json +1 -1
  34. package/assets/r/menubar.json +1 -1
  35. package/assets/r/navigation-menu.json +1 -1
  36. package/assets/r/pagination.json +1 -1
  37. package/assets/r/popover.json +1 -1
  38. package/assets/r/profile-card.json +1 -1
  39. package/assets/r/progress.json +1 -1
  40. package/assets/r/radio-group.json +1 -1
  41. package/assets/r/scroll-area.json +1 -1
  42. package/assets/r/searchbox.json +1 -1
  43. package/assets/r/select.json +1 -1
  44. package/assets/r/separator.json +1 -1
  45. package/assets/r/sheet.json +1 -1
  46. package/assets/r/sidebar.json +1 -1
  47. package/assets/r/skeleton.json +1 -1
  48. package/assets/r/slider.json +1 -1
  49. package/assets/r/snippet.json +1 -1
  50. package/assets/r/spinner.json +1 -1
  51. package/assets/r/status-dot.json +1 -1
  52. package/assets/r/switch.json +1 -1
  53. package/assets/r/table.json +1 -1
  54. package/assets/r/tabs.json +1 -1
  55. package/assets/r/tag.json +1 -1
  56. package/assets/r/textarea.json +1 -1
  57. package/assets/r/toaster.json +1 -1
  58. package/assets/r/tooltip.json +1 -1
  59. package/assets/r/tree.json +1 -1
  60. package/dist/index.js +113 -46
  61. package/package.json +1 -1
@@ -13,7 +13,7 @@
13
13
  "path": "components/base/Command.tsx",
14
14
  "type": "registry:ui",
15
15
  "target": "components/base/Command.tsx",
16
- "content": "import * as React from \"react\";\nimport { Command as CommandPrimitive } from \"cmdk\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst Command = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive\n ref={ref}\n className={cn(\n \"flex h-full w-full flex-col overflow-hidden rounded bg-popover text-popover-foreground\",\n className,\n )}\n {...props}\n />\n));\nCommand.displayName = CommandPrimitive.displayName;\n\nconst CommandInput = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Input>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>\n>(({ className, ...props }, ref) => (\n <div className='flex items-center border-b border-border px-3' cmdk-input-wrapper=''>\n <svg\n className='mr-2 h-4 w-4 shrink-0 opacity-50'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'>\n <circle cx='11' cy='11' r='8' />\n <path d='m21 21-4.3-4.3' />\n </svg>\n <CommandPrimitive.Input\n ref={ref}\n className={cn(\n \"flex h-10 w-full rounded bg-transparent py-3 text-sm text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n </div>\n));\nCommandInput.displayName = CommandPrimitive.Input.displayName;\n\nconst CommandList = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.List\n ref={ref}\n className={cn(\"max-h-75 overflow-y-auto overflow-x-hidden\", className)}\n {...props}\n />\n));\nCommandList.displayName = CommandPrimitive.List.displayName;\n\nconst CommandEmpty = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Empty>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>\n>((props, ref) => (\n <CommandPrimitive.Empty\n ref={ref}\n className='py-6 text-center text-sm text-muted-foreground'\n {...props}\n />\n));\nCommandEmpty.displayName = CommandPrimitive.Empty.displayName;\n\nconst CommandGroup = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Group\n ref={ref}\n className={cn(\n \"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground\",\n className,\n )}\n {...props}\n />\n));\nCommandGroup.displayName = CommandPrimitive.Group.displayName;\n\nconst CommandSeparator = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 h-px bg-border\", className)}\n {...props}\n />\n));\nCommandSeparator.displayName = CommandPrimitive.Separator.displayName;\n\nconst CommandItem = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center gap-2 rounded px-2 py-1.5 text-sm text-foreground outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-primary/15 data-[selected=true]:text-primary data-[disabled=true]:opacity-50\",\n className,\n )}\n {...props}\n />\n));\nCommandItem.displayName = CommandPrimitive.Item.displayName;\n\nconst CommandShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => (\n <span\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className,\n )}\n {...props}\n />\n);\nCommandShortcut.displayName = \"CommandShortcut\";\n\nexport {\n Command,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandShortcut,\n CommandSeparator,\n};\n"
16
+ "content": "import { Command as CommandPrimitive } from \"cmdk\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst Command = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive\n ref={ref}\n className={cn(\n \"flex h-full w-full flex-col overflow-hidden rounded bg-popover text-popover-foreground\",\n className,\n )}\n {...props}\n />\n));\nCommand.displayName = CommandPrimitive.displayName;\n\nconst CommandInput = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Input>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>\n>(({ className, ...props }, ref) => (\n <div className=\"flex items-center border-b border-border px-3\" cmdk-input-wrapper=\"\">\n <svg\n className=\"mr-2 h-4 w-4 shrink-0 opacity-50\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\n <path d=\"m21 21-4.3-4.3\" />\n </svg>\n <CommandPrimitive.Input\n ref={ref}\n className={cn(\n \"flex h-10 w-full rounded bg-transparent py-3 text-sm text-foreground outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50\",\n className,\n )}\n {...props}\n />\n </div>\n));\nCommandInput.displayName = CommandPrimitive.Input.displayName;\n\nconst CommandList = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.List\n ref={ref}\n className={cn(\"max-h-75 overflow-y-auto overflow-x-hidden\", className)}\n {...props}\n />\n));\nCommandList.displayName = CommandPrimitive.List.displayName;\n\nconst CommandEmpty = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Empty>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>\n>((props, ref) => (\n <CommandPrimitive.Empty\n ref={ref}\n className=\"py-6 text-center text-sm text-muted-foreground\"\n {...props}\n />\n));\nCommandEmpty.displayName = CommandPrimitive.Empty.displayName;\n\nconst CommandGroup = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Group\n ref={ref}\n className={cn(\n \"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground\",\n className,\n )}\n {...props}\n />\n));\nCommandGroup.displayName = CommandPrimitive.Group.displayName;\n\nconst CommandSeparator = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 h-px bg-border\", className)}\n {...props}\n />\n));\nCommandSeparator.displayName = CommandPrimitive.Separator.displayName;\n\nconst CommandItem = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center gap-2 rounded px-2 py-1.5 text-sm text-foreground outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-primary/15 data-[selected=true]:text-primary data-[disabled=true]:opacity-50\",\n className,\n )}\n {...props}\n />\n));\nCommandItem.displayName = CommandPrimitive.Item.displayName;\n\nconst CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (\n <span\n className={cn(\"ml-auto text-xs tracking-widest text-muted-foreground\", className)}\n {...props}\n />\n);\nCommandShortcut.displayName = \"CommandShortcut\";\n\nexport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut,\n};\n"
17
17
  },
18
18
  {
19
19
  "path": "components/base/Command.md",
@@ -15,7 +15,7 @@
15
15
  "path": "views/EnvioConfirmado.tsx",
16
16
  "type": "registry:file",
17
17
  "target": "views/EnvioConfirmado.tsx",
18
- "content": "import { CheckCircle2 } from \"lucide-react\";\nimport { Button } from \"@/components/base/Button\";\n\n// Receta cliente — confirmación / éxito: celebra breve, di qué pasa ahora y\n// dónde seguir. Ver confirmacion.md.\n\nexport function EnvioConfirmado() {\n return (\n <main className='mx-auto flex min-h-[60vh] w-full max-w-md flex-col items-center justify-center px-4 text-center'>\n <span className='mb-4 flex size-12 items-center justify-center rounded-full bg-success/10'>\n <CheckCircle2 className='size-6 text-success' aria-hidden />\n </span>\n <h1 className='text-2xl font-bold text-foreground'>\n ¡Enviamos tus documentos!\n </h1>\n <p className='mt-2 text-base text-muted-foreground'>\n El equipo legal los está revisando. Podrás seguir su estado en la pestaña\n «Enviados» y te avisaremos si falta algo.\n </p>\n <Button className='mt-6'>Volver al inicio</Button>\n </main>\n );\n}\n"
18
+ "content": "import { CheckCircle2 } from \"lucide-react\";\n\nimport { Button } from \"@/components/base/Button\";\n\n// Receta cliente — confirmación / éxito: celebra breve, di qué pasa ahora y\n// dónde seguir. Ver confirmacion.md.\n\nexport function EnvioConfirmado() {\n return (\n <main className=\"mx-auto flex min-h-[60vh] w-full max-w-md flex-col items-center justify-center px-4 text-center\">\n <span className=\"mb-4 flex size-12 items-center justify-center rounded-full bg-success/10\">\n <CheckCircle2 className=\"size-6 text-success\" aria-hidden />\n </span>\n <h1 className=\"text-2xl font-bold text-foreground\">¡Enviamos tus documentos!</h1>\n <p className=\"mt-2 text-base text-muted-foreground\">\n El equipo legal los está revisando. Podrás seguir su estado en la pestaña «Enviados» y te\n avisaremos si falta algo.\n </p>\n <Button className=\"mt-6\">Volver al inicio</Button>\n </main>\n );\n}\n"
19
19
  },
20
20
  {
21
21
  "path": "views/confirmacion.md",
@@ -13,7 +13,7 @@
13
13
  "path": "components/base/CounterBadge.tsx",
14
14
  "type": "registry:ui",
15
15
  "target": "components/base/CounterBadge.tsx",
16
- "content": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nfunction formatCount(children: React.ReactNode, max?: number): React.ReactNode {\n if (max == null) return children;\n const n =\n typeof children === \"number\"\n ? children\n : typeof children === \"string\" && /^\\d+$/.test(children.trim())\n ? Number.parseInt(children, 10)\n : null;\n if (n == null || n <= max) return children;\n return `${max}+`;\n}\n\nconst counterBadgeVariants = cva(\n \"inline-flex select-none items-center justify-center rounded-full bg-primary font-semibold tabular-nums text-primary-foreground\",\n {\n variants: {\n size: {\n sm: \"h-4 min-w-4 px-1 text-xs leading-none\",\n md: \"h-5 min-w-5 px-1.5 text-xs leading-none\",\n lg: \"h-6 min-w-6 px-1.5 text-xs/[1]\",\n },\n },\n defaultVariants: { size: \"md\" },\n },\n);\n\nexport interface CounterBadgeProps\n extends React.HTMLAttributes<HTMLSpanElement>,\n VariantProps<typeof counterBadgeVariants> {\n /** Tope numérico (ej. 99 → \"99+\"). */\n max?: number;\n}\n\nconst CounterBadge = React.forwardRef<HTMLSpanElement, CounterBadgeProps>(\n ({ size, max, className, children, ...props }, ref) => (\n <span\n ref={ref}\n className={cn(counterBadgeVariants({ size }), className)}\n {...props}>\n {formatCount(children, max)}\n </span>\n ),\n);\nCounterBadge.displayName = \"CounterBadge\";\n\nexport { CounterBadge, counterBadgeVariants };\n"
16
+ "content": "import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nfunction formatCount(children: React.ReactNode, max?: number): React.ReactNode {\n if (max == null) return children;\n const n =\n typeof children === \"number\"\n ? children\n : typeof children === \"string\" && /^\\d+$/.test(children.trim())\n ? Number.parseInt(children, 10)\n : null;\n if (n == null || n <= max) return children;\n return `${max}+`;\n}\n\nconst counterBadgeVariants = cva(\n \"inline-flex select-none items-center justify-center rounded-full bg-primary font-semibold tabular-nums text-primary-foreground\",\n {\n variants: {\n size: {\n sm: \"h-4 min-w-4 px-1 text-xs leading-none\",\n md: \"h-5 min-w-5 px-1.5 text-xs leading-none\",\n lg: \"h-6 min-w-6 px-1.5 text-xs/[1]\",\n },\n },\n defaultVariants: { size: \"md\" },\n },\n);\n\nexport interface CounterBadgeProps\n extends React.HTMLAttributes<HTMLSpanElement>, VariantProps<typeof counterBadgeVariants> {\n /** Tope numérico (ej. 99 → \"99+\"). */\n max?: number;\n}\n\nconst CounterBadge = React.forwardRef<HTMLSpanElement, CounterBadgeProps>(\n ({ size, max, className, children, ...props }, ref) => (\n <span ref={ref} className={cn(counterBadgeVariants({ size }), className)} {...props}>\n {formatCount(children, max)}\n </span>\n ),\n);\nCounterBadge.displayName = \"CounterBadge\";\n\nexport { CounterBadge, counterBadgeVariants };\n"
17
17
  },
18
18
  {
19
19
  "path": "components/base/CounterBadge.md",
@@ -17,7 +17,7 @@
17
17
  "path": "views/AppLayout.tsx",
18
18
  "type": "registry:file",
19
19
  "target": "views/AppLayout.tsx",
20
- "content": "import * as React from \"react\";\nimport { FolderKanban, Inbox, Settings } from \"lucide-react\";\nimport { AppSidebar } from \"@/components/base/AppSidebar\";\nimport { Logo } from \"@/components/base/Logo\";\nimport { SidebarInset, SidebarProvider } from \"@/components/base/Sidebar\";\n\n// Receta CRM — layout de aplicación: navegación lateral colapsable data-driven\n// y área de trabajo. Las vistas del desk y el detalle viven dentro de\n// SidebarInset. Ver crm-app-layout.md.\n\nexport function AppLayout({ children }: { children: React.ReactNode }) {\n return (\n <SidebarProvider>\n <AppSidebar\n logo={<Logo layout='horizontal' />}\n groups={[\n {\n label: \"Trabajo\",\n items: [\n { title: \"Casos\", icon: FolderKanban, url: \"/casos\", isActive: true },\n { title: \"Bandeja\", icon: Inbox, url: \"/bandeja\" },\n ],\n },\n {\n label: \"Sistema\",\n items: [{ title: \"Configuración\", icon: Settings, url: \"/config\" }],\n },\n ]}\n />\n <SidebarInset>{children}</SidebarInset>\n </SidebarProvider>\n );\n}\n"
20
+ "content": "import { FolderKanban, Inbox, Settings } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { AppSidebar } from \"@/components/base/AppSidebar\";\nimport { Logo } from \"@/components/base/Logo\";\nimport { SidebarInset, SidebarProvider } from \"@/components/base/Sidebar\";\n\n// Receta CRM — layout de aplicación: navegación lateral colapsable data-driven\n// y área de trabajo. Las vistas del desk y el detalle viven dentro de\n// SidebarInset. Ver crm-app-layout.md.\n\nexport function AppLayout({ children }: { children: React.ReactNode }) {\n return (\n <SidebarProvider>\n <AppSidebar\n logo={<Logo layout=\"horizontal\" />}\n groups={[\n {\n label: \"Trabajo\",\n items: [\n { title: \"Casos\", icon: FolderKanban, url: \"/casos\", isActive: true },\n { title: \"Bandeja\", icon: Inbox, url: \"/bandeja\" },\n ],\n },\n {\n label: \"Sistema\",\n items: [{ title: \"Configuración\", icon: Settings, url: \"/config\" }],\n },\n ]}\n />\n <SidebarInset>{children}</SidebarInset>\n </SidebarProvider>\n );\n}\n"
21
21
  },
22
22
  {
23
23
  "path": "views/crm-app-layout.md",
@@ -19,7 +19,7 @@
19
19
  "path": "views/CasosDesk.tsx",
20
20
  "type": "registry:file",
21
21
  "target": "views/CasosDesk.tsx",
22
- "content": "import { Plus } from \"lucide-react\";\nimport { Button } from \"@/components/base/Button\";\nimport { Input } from \"@/components/base/Input\";\nimport { Pagination, PaginationContent, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from \"@/components/base/Pagination\";\nimport { StatusDot } from \"@/components/base/StatusDot\";\nimport { Table } from \"@/components/base/Table\";\n\n// Receta CRM — desk con tabla y acciones: ancho completo, toolbar con búsqueda\n// y acción primaria, tabla densa con estado por fila, paginación al pie.\n// Ver crm-desk.md.\n\nexport function CasosDesk() {\n return (\n <main className='w-full p-4'>\n <header className='mb-4 flex items-center justify-between gap-4'>\n <div>\n <h1 className='text-xl font-semibold text-foreground'>Casos</h1>\n <p className='text-sm text-muted-foreground'>24 activos · 3 vencen hoy</p>\n </div>\n <div className='flex items-center gap-2'>\n <Input className='h-9 w-64' placeholder='Buscar por cliente o RUT' aria-label='Buscar casos' />\n <Button size='sm'>\n <Plus /> Nuevo caso\n </Button>\n </div>\n </header>\n\n <Table columns='2fr 1.5fr 1fr 1fr' stickyHeader>\n <Table.Header>\n <Table.Cell>Cliente</Table.Cell>\n <Table.Cell>Materia</Table.Cell>\n <Table.Cell>Estado</Table.Cell>\n <Table.Cell>Plazo</Table.Cell>\n </Table.Header>\n <Table.Content>\n <Table.Row onClick={() => {}}>\n <Table.Cell className='font-medium'>María Pérez</Table.Cell>\n <Table.Cell>Despido</Table.Cell>\n <Table.Cell><StatusDot tone='warning'>En revisión</StatusDot></Table.Cell>\n <Table.Cell className='text-warning'>Vence hoy</Table.Cell>\n </Table.Row>\n <Table.Row onClick={() => {}}>\n <Table.Cell className='font-medium'>Juan Soto</Table.Cell>\n <Table.Cell>Deuda</Table.Cell>\n <Table.Cell><StatusDot tone='success'>Al día</StatusDot></Table.Cell>\n <Table.Cell className='text-muted-foreground'>12 días</Table.Cell>\n </Table.Row>\n </Table.Content>\n </Table>\n\n <footer className='mt-4 flex items-center justify-between'>\n <p className='text-sm text-muted-foreground'>Mostrando 1–20 de 64 casos</p>\n <Pagination className='mx-0 w-auto justify-end'>\n <PaginationContent>\n <PaginationItem><PaginationPrevious href='#' /></PaginationItem>\n <PaginationItem><PaginationLink href='#' isActive>1</PaginationLink></PaginationItem>\n <PaginationItem><PaginationLink href='#'>2</PaginationLink></PaginationItem>\n <PaginationItem><PaginationLink href='#'>3</PaginationLink></PaginationItem>\n <PaginationItem><PaginationNext href='#' /></PaginationItem>\n </PaginationContent>\n </Pagination>\n </footer>\n </main>\n );\n}\n"
22
+ "content": "import { Plus } from \"lucide-react\";\n\nimport { Button } from \"@/components/base/Button\";\nimport { Input } from \"@/components/base/Input\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n} from \"@/components/base/Pagination\";\nimport { StatusDot } from \"@/components/base/StatusDot\";\nimport { Table } from \"@/components/base/Table\";\n\n// Receta CRM — desk con tabla y acciones: ancho completo, toolbar con búsqueda\n// y acción primaria, tabla densa con estado por fila, paginación al pie.\n// Ver crm-desk.md.\n\nexport function CasosDesk() {\n return (\n <main className=\"w-full p-4\">\n <header className=\"mb-4 flex items-center justify-between gap-4\">\n <div>\n <h1 className=\"text-xl font-semibold text-foreground\">Casos</h1>\n <p className=\"text-sm text-muted-foreground\">24 activos · 3 vencen hoy</p>\n </div>\n <div className=\"flex items-center gap-2\">\n <Input\n className=\"h-9 w-64\"\n placeholder=\"Buscar por cliente o RUT\"\n aria-label=\"Buscar casos\"\n />\n <Button size=\"sm\">\n <Plus /> Nuevo caso\n </Button>\n </div>\n </header>\n\n <Table columns=\"2fr 1.5fr 1fr 1fr\" stickyHeader>\n <Table.Header>\n <Table.Cell>Cliente</Table.Cell>\n <Table.Cell>Materia</Table.Cell>\n <Table.Cell>Estado</Table.Cell>\n <Table.Cell>Plazo</Table.Cell>\n </Table.Header>\n <Table.Content>\n <Table.Row onClick={() => {}}>\n <Table.Cell className=\"font-medium\">María Pérez</Table.Cell>\n <Table.Cell>Despido</Table.Cell>\n <Table.Cell>\n <StatusDot tone=\"warning\">En revisión</StatusDot>\n </Table.Cell>\n <Table.Cell className=\"text-warning\">Vence hoy</Table.Cell>\n </Table.Row>\n <Table.Row onClick={() => {}}>\n <Table.Cell className=\"font-medium\">Juan Soto</Table.Cell>\n <Table.Cell>Deuda</Table.Cell>\n <Table.Cell>\n <StatusDot tone=\"success\">Al día</StatusDot>\n </Table.Cell>\n <Table.Cell className=\"text-muted-foreground\">12 días</Table.Cell>\n </Table.Row>\n </Table.Content>\n </Table>\n\n <footer className=\"mt-4 flex items-center justify-between\">\n <p className=\"text-sm text-muted-foreground\">Mostrando 1–20 de 64 casos</p>\n <Pagination className=\"mx-0 w-auto justify-end\">\n <PaginationContent>\n <PaginationItem>\n <PaginationPrevious href=\"#\" />\n </PaginationItem>\n <PaginationItem>\n <PaginationLink href=\"#\" isActive>\n 1\n </PaginationLink>\n </PaginationItem>\n <PaginationItem>\n <PaginationLink href=\"#\">2</PaginationLink>\n </PaginationItem>\n <PaginationItem>\n <PaginationLink href=\"#\">3</PaginationLink>\n </PaginationItem>\n <PaginationItem>\n <PaginationNext href=\"#\" />\n </PaginationItem>\n </PaginationContent>\n </Pagination>\n </footer>\n </main>\n );\n}\n"
23
23
  },
24
24
  {
25
25
  "path": "views/crm-desk.md",
@@ -16,7 +16,7 @@
16
16
  "path": "views/CasoDetalle.tsx",
17
17
  "type": "registry:file",
18
18
  "target": "views/CasoDetalle.tsx",
19
- "content": "import { Button } from \"@/components/base/Button\";\nimport { Separator } from \"@/components/base/Separator\";\nimport { Tag } from \"@/components/base/Tag\";\nimport { Tabs, TabsList, TabsTrigger, TabsContent } from \"@/components/base/Tabs\";\n\n// Receta CRM — detalle de caso (master-detail): contexto a la izquierda,\n// trabajo al centro, acciones a la mano. Ver crm-detalle-caso.md.\n\nexport function CasoDetalle() {\n return (\n <main className='flex w-full gap-4 p-4'>\n <aside className='w-72 shrink-0 space-y-4'>\n <div>\n <h1 className='text-lg font-semibold text-foreground'>María Pérez</h1>\n <p className='text-sm text-muted-foreground'>Caso #1042 · Despido</p>\n </div>\n <Tag tone='warning'>En revisión</Tag>\n <Separator />\n <dl className='space-y-2 text-sm'>\n <div className='flex justify-between'>\n <dt className='text-muted-foreground'>Abogado</dt>\n <dd className='text-foreground'>C. Rivera</dd>\n </div>\n <div className='flex justify-between'>\n <dt className='text-muted-foreground'>Plazo</dt>\n <dd className='text-warning'>Vence hoy</dd>\n </div>\n </dl>\n </aside>\n\n <section className='min-w-0 flex-1'>\n <div className='mb-3 flex items-center justify-between'>\n <h2 className='text-base font-semibold text-foreground'>Gestiones</h2>\n <Button size='sm'>Nueva gestión</Button>\n </div>\n <Tabs defaultValue='actividad'>\n <TabsList>\n <TabsTrigger value='actividad'>Actividad</TabsTrigger>\n <TabsTrigger value='documentos'>Documentos</TabsTrigger>\n <TabsTrigger value='notas'>Notas</TabsTrigger>\n </TabsList>\n <TabsContent value='actividad'>{/* timeline */}</TabsContent>\n <TabsContent value='documentos'>{/* lista */}</TabsContent>\n <TabsContent value='notas'>{/* notas */}</TabsContent>\n </Tabs>\n </section>\n </main>\n );\n}\n"
19
+ "content": "import { Button } from \"@/components/base/Button\";\nimport { Separator } from \"@/components/base/Separator\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"@/components/base/Tabs\";\nimport { Tag } from \"@/components/base/Tag\";\n\n// Receta CRM — detalle de caso (master-detail): contexto a la izquierda,\n// trabajo al centro, acciones a la mano. Ver crm-detalle-caso.md.\n\nexport function CasoDetalle() {\n return (\n <main className=\"flex w-full gap-4 p-4\">\n <aside className=\"w-72 shrink-0 space-y-4\">\n <div>\n <h1 className=\"text-lg font-semibold text-foreground\">María Pérez</h1>\n <p className=\"text-sm text-muted-foreground\">Caso #1042 · Despido</p>\n </div>\n <Tag tone=\"warning\">En revisión</Tag>\n <Separator />\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <dt className=\"text-muted-foreground\">Abogado</dt>\n <dd className=\"text-foreground\">C. Rivera</dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-muted-foreground\">Plazo</dt>\n <dd className=\"text-warning\">Vence hoy</dd>\n </div>\n </dl>\n </aside>\n\n <section className=\"min-w-0 flex-1\">\n <div className=\"mb-3 flex items-center justify-between\">\n <h2 className=\"text-base font-semibold text-foreground\">Gestiones</h2>\n <Button size=\"sm\">Nueva gestión</Button>\n </div>\n <Tabs defaultValue=\"actividad\">\n <TabsList>\n <TabsTrigger value=\"actividad\">Actividad</TabsTrigger>\n <TabsTrigger value=\"documentos\">Documentos</TabsTrigger>\n <TabsTrigger value=\"notas\">Notas</TabsTrigger>\n </TabsList>\n <TabsContent value=\"actividad\">{/* timeline */}</TabsContent>\n <TabsContent value=\"documentos\">{/* lista */}</TabsContent>\n <TabsContent value=\"notas\">{/* notas */}</TabsContent>\n </Tabs>\n </section>\n </main>\n );\n}\n"
20
20
  },
21
21
  {
22
22
  "path": "views/crm-detalle-caso.md",
@@ -18,7 +18,7 @@
18
18
  "path": "components/base/DatePicker.tsx",
19
19
  "type": "registry:ui",
20
20
  "target": "components/base/DatePicker.tsx",
21
- "content": "import * as React from \"react\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { es } from \"react-day-picker/locale\";\nimport type { Locale } from \"react-day-picker\";\n\nimport { cn } from \"@/lib/utils/cn\";\nimport { Button } from \"./Button\";\nimport { Calendar } from \"./Calendar\";\nimport { Popover, PopoverTrigger, PopoverContent } from \"./Popover\";\n\nfunction formatDate(date: Date, localeCode?: string) {\n return date.toLocaleDateString(localeCode, {\n day: \"numeric\",\n month: \"long\",\n year: \"numeric\",\n });\n}\n\n/**\n * Wrapper ergonómico sobre la receta compuesta Popover + Button + Calendar.\n * Si necesitas variar la estructura (rango, dos meses, footer, otro trigger),\n * compón las piezas directamente — ver \"Receta compuesta\" en DatePicker.md.\n */\nexport interface DatePickerProps\n extends Omit<\n React.ComponentPropsWithoutRef<typeof Button>,\n \"value\" | \"defaultValue\" | \"onChange\"\n > {\n /** Fecha seleccionada (modo controlado: pásala junto a `onChange`). */\n value?: Date;\n /** Fecha inicial en modo no controlado. */\n defaultValue?: Date;\n /** Callback de selección (activa el modo controlado). */\n onChange?: (date: Date | undefined) => void;\n placeholder?: string;\n captionLayout?: React.ComponentProps<typeof Calendar>[\"captionLayout\"];\n locale?: Partial<Locale>;\n align?: React.ComponentProps<typeof PopoverContent>[\"align\"];\n}\n\nconst DatePicker = React.forwardRef<HTMLButtonElement, DatePickerProps>(\n function DatePicker(\n {\n value,\n defaultValue,\n onChange,\n placeholder = \"Selecciona una fecha\",\n captionLayout = \"label\",\n locale = es,\n align = \"start\",\n className,\n ...props\n },\n ref,\n ) {\n const [open, setOpen] = React.useState(false);\n const [internal, setInternal] = React.useState<Date | undefined>(\n defaultValue,\n );\n\n // Controlado si se provee `onChange`; si no, mantenemos estado interno.\n const selected = onChange ? value : internal;\n\n const handleSelect = (date: Date | undefined) => {\n if (onChange) onChange(date);\n else setInternal(date);\n setOpen(false);\n };\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n ref={ref}\n type=\"button\"\n variant=\"outline\"\n data-empty={!selected}\n className={cn(\n \"w-65 justify-start text-left font-normal data-[empty=true]:text-muted-foreground\",\n className,\n )}\n {...props}\n >\n <CalendarIcon />\n {selected ? formatDate(selected, locale?.code) : placeholder}\n </Button>\n </PopoverTrigger>\n {/* El panel toma el ancho del trigger (igual que Combobox); el calendario\n (248px natural) se centra dentro. */}\n <PopoverContent\n className=\"flex w-[var(--radix-popover-trigger-width)] justify-center p-0\"\n align={align}\n >\n <Calendar\n mode=\"single\"\n selected={selected}\n onSelect={handleSelect}\n captionLayout={captionLayout}\n locale={locale}\n autoFocus\n />\n </PopoverContent>\n </Popover>\n );\n },\n);\nDatePicker.displayName = \"DatePicker\";\n\nexport { DatePicker };\n"
21
+ "content": "/* eslint-disable jsx-a11y/no-autofocus -- el foco entra al calendario al abrir el popover (patrón diálogo) */\nimport { CalendarIcon } from \"lucide-react\";\nimport * as React from \"react\";\nimport type { Locale } from \"react-day-picker\";\nimport { es } from \"react-day-picker/locale\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nimport { Button } from \"./Button\";\nimport { Calendar } from \"./Calendar\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"./Popover\";\n\nfunction formatDate(date: Date, localeCode?: string) {\n return date.toLocaleDateString(localeCode, {\n day: \"numeric\",\n month: \"long\",\n year: \"numeric\",\n });\n}\n\n/**\n * Wrapper ergonómico sobre la receta compuesta Popover + Button + Calendar.\n * Si necesitas variar la estructura (rango, dos meses, footer, otro trigger),\n * compón las piezas directamente — ver \"Receta compuesta\" en DatePicker.md.\n */\nexport interface DatePickerProps extends Omit<\n React.ComponentPropsWithoutRef<typeof Button>,\n \"value\" | \"defaultValue\" | \"onChange\"\n> {\n /** Fecha seleccionada (modo controlado: pásala junto a `onChange`). */\n value?: Date;\n /** Fecha inicial en modo no controlado. */\n defaultValue?: Date;\n /** Callback de selección (activa el modo controlado). */\n onChange?: (date: Date | undefined) => void;\n placeholder?: string;\n captionLayout?: React.ComponentProps<typeof Calendar>[\"captionLayout\"];\n locale?: Partial<Locale>;\n align?: React.ComponentProps<typeof PopoverContent>[\"align\"];\n}\n\nconst DatePicker = React.forwardRef<HTMLButtonElement, DatePickerProps>(function DatePicker(\n {\n value,\n defaultValue,\n onChange,\n placeholder = \"Selecciona una fecha\",\n captionLayout = \"label\",\n locale = es,\n align = \"start\",\n className,\n ...props\n },\n ref,\n) {\n const [open, setOpen] = React.useState(false);\n const [internal, setInternal] = React.useState<Date | undefined>(defaultValue);\n\n // Controlado si se provee `onChange`; si no, mantenemos estado interno.\n const selected = onChange ? value : internal;\n\n const handleSelect = (date: Date | undefined) => {\n if (onChange) onChange(date);\n else setInternal(date);\n setOpen(false);\n };\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <Button\n ref={ref}\n type=\"button\"\n variant=\"outline\"\n data-empty={!selected}\n className={cn(\n \"w-65 justify-start text-left font-normal data-[empty=true]:text-muted-foreground\",\n className,\n )}\n {...props}\n >\n <CalendarIcon />\n {selected ? formatDate(selected, locale?.code) : placeholder}\n </Button>\n </PopoverTrigger>\n {/* El panel toma el ancho del trigger (igual que Combobox); el calendario\n (248px natural) se centra dentro. */}\n <PopoverContent\n className=\"flex w-[var(--radix-popover-trigger-width)] justify-center p-0\"\n align={align}\n >\n <Calendar\n mode=\"single\"\n selected={selected}\n onSelect={handleSelect}\n captionLayout={captionLayout}\n locale={locale}\n autoFocus\n />\n </PopoverContent>\n </Popover>\n );\n});\nDatePicker.displayName = \"DatePicker\";\n\nexport { DatePicker };\n"
22
22
  },
23
23
  {
24
24
  "path": "components/base/DatePicker.md",
@@ -13,7 +13,7 @@
13
13
  "path": "components/base/Dialog.tsx",
14
14
  "type": "registry:ui",
15
15
  "target": "components/base/Dialog.tsx",
16
- "content": "import * as React from \"react\";\nimport * as DialogPrimitive from \"@radix-ui/react-dialog\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst Dialog = DialogPrimitive.Root;\nconst DialogTrigger = DialogPrimitive.Trigger;\nconst DialogPortal = DialogPrimitive.Portal;\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-lg\",\n className,\n )}\n {...props}>\n {children}\n {/* Sin X de cierre: se cierra con Escape, click en el overlay o una\n acción explícita (DialogClose / botón Cancelar de AppDialog). */}\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nconst DialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nDialogFooter.displayName = \"DialogFooter\";\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\n \"text-lg font-semibold leading-none tracking-tight text-foreground\",\n className,\n )}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogPortal,\n DialogOverlay,\n DialogClose,\n DialogTrigger,\n DialogContent,\n DialogHeader,\n DialogFooter,\n DialogTitle,\n DialogDescription,\n};\n"
16
+ "content": "import * as DialogPrimitive from \"@radix-ui/react-dialog\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst Dialog = DialogPrimitive.Root;\nconst DialogTrigger = DialogPrimitive.Trigger;\nconst DialogPortal = DialogPrimitive.Portal;\nconst DialogClose = DialogPrimitive.Close;\n\nconst DialogOverlay = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Overlay\n ref={ref}\n className={cn(\n \"fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n />\n));\nDialogOverlay.displayName = DialogPrimitive.Overlay.displayName;\n\nconst DialogContent = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <DialogPortal>\n <DialogOverlay />\n <DialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-lg\",\n className,\n )}\n {...props}\n >\n {children}\n {/* Sin X de cierre: se cierra con Escape, click en el overlay o una\n acción explícita (DialogClose / botón Cancelar de AppDialog). */}\n </DialogPrimitive.Content>\n </DialogPortal>\n));\nDialogContent.displayName = DialogPrimitive.Content.displayName;\n\nconst DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn(\"flex flex-col space-y-2 text-center sm:text-left\", className)} {...props} />\n);\nDialogHeader.displayName = \"DialogHeader\";\n\nconst DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\", className)}\n {...props}\n />\n);\nDialogFooter.displayName = \"DialogFooter\";\n\nconst DialogTitle = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold leading-none tracking-tight text-foreground\", className)}\n {...props}\n />\n));\nDialogTitle.displayName = DialogPrimitive.Title.displayName;\n\nconst DialogDescription = React.forwardRef<\n React.ElementRef<typeof DialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <DialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nDialogDescription.displayName = DialogPrimitive.Description.displayName;\n\nexport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogOverlay,\n DialogPortal,\n DialogTitle,\n DialogTrigger,\n};\n"
17
17
  },
18
18
  {
19
19
  "path": "components/base/Dialog.md",
@@ -13,7 +13,7 @@
13
13
  "path": "components/base/DropdownMenu.tsx",
14
14
  "type": "registry:ui",
15
15
  "target": "components/base/DropdownMenu.tsx",
16
- "content": "import * as React from \"react\";\nimport * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst ChevronRightIcon = () => (\n <svg\n className='ml-auto h-4 w-4'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'>\n <path d='m9 18 6-6-6-6' />\n </svg>\n);\n\nconst CheckIcon = () => (\n <svg\n className='h-4 w-4'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'>\n <path d='M20 6 9 17l-5-5' />\n </svg>\n);\n\nconst DotIcon = () => (\n <svg className='h-2 w-2 fill-current' viewBox='0 0 24 24'>\n <circle cx='12' cy='12' r='12' />\n </svg>\n);\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-pointer select-none items-center rounded px-2 py-1.5 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[state=open]:bg-primary/15 data-[state=open]:text-primary\",\n inset && \"pl-8\",\n className,\n )}\n {...props}>\n {children}\n <ChevronRightIcon />\n </DropdownMenuPrimitive.SubTrigger>\n));\nDropdownMenuSubTrigger.displayName =\n DropdownMenuPrimitive.SubTrigger.displayName;\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-32 overflow-hidden rounded border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuSubContent.displayName =\n DropdownMenuPrimitive.SubContent.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 min-w-32 overflow-hidden rounded border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center gap-2 rounded px-2 py-1.5 text-sm outline-none transition-colors focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n checked={checked}\n {...props}>\n <span className='absolute left-2 flex h-3.5 w-3.5 items-center justify-center'>\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName =\n DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}>\n <span className='absolute left-2 flex h-3.5 w-3.5 items-center justify-center'>\n <DropdownMenuPrimitive.ItemIndicator>\n <DotIcon />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\n \"px-2 py-1.5 text-sm font-semibold text-foreground\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => (\n <span\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className,\n )}\n {...props}\n />\n);\nDropdownMenuShortcut.displayName = \"DropdownMenuShortcut\";\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuGroup,\n DropdownMenuPortal,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuRadioGroup,\n};\n"
16
+ "content": "import * as DropdownMenuPrimitive from \"@radix-ui/react-dropdown-menu\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst DropdownMenu = DropdownMenuPrimitive.Root;\nconst DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;\nconst DropdownMenuGroup = DropdownMenuPrimitive.Group;\nconst DropdownMenuPortal = DropdownMenuPrimitive.Portal;\nconst DropdownMenuSub = DropdownMenuPrimitive.Sub;\nconst DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;\n\nconst ChevronRightIcon = () => (\n <svg\n className=\"ml-auto h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n);\n\nconst CheckIcon = () => (\n <svg\n className=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n);\n\nconst DotIcon = () => (\n <svg className=\"h-2 w-2 fill-current\" viewBox=\"0 0 24 24\">\n <circle cx=\"12\" cy=\"12\" r=\"12\" />\n </svg>\n);\n\nconst DropdownMenuSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-pointer select-none items-center rounded px-2 py-1.5 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[state=open]:bg-primary/15 data-[state=open]:text-primary\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon />\n </DropdownMenuPrimitive.SubTrigger>\n));\nDropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;\n\nconst DropdownMenuSubContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-32 overflow-hidden rounded border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;\n\nconst DropdownMenuContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 min-w-32 overflow-hidden rounded border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n className,\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n));\nDropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;\n\nconst DropdownMenuItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center gap-2 rounded px-2 py-1.5 text-sm outline-none transition-colors focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nDropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;\n\nconst DropdownMenuCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <CheckIcon />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n));\nDropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;\n\nconst DropdownMenuRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <DotIcon />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n));\nDropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;\n\nconst DropdownMenuLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\"px-2 py-1.5 text-sm font-semibold text-foreground\", inset && \"pl-8\", className)}\n {...props}\n />\n));\nDropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;\n\nconst DropdownMenuSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n));\nDropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;\n\nconst DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (\n <span\n className={cn(\"ml-auto text-xs tracking-widest text-muted-foreground\", className)}\n {...props}\n />\n);\nDropdownMenuShortcut.displayName = \"DropdownMenuShortcut\";\n\nexport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n};\n"
17
17
  },
18
18
  {
19
19
  "path": "components/base/DropdownMenu.md",
@@ -13,7 +13,7 @@
13
13
  "path": "components/base/Empty.tsx",
14
14
  "type": "registry:ui",
15
15
  "target": "components/base/Empty.tsx",
16
- "content": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nfunction Empty({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty\"\n className={cn(\n \"flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-lg border-dashed p-12 text-center text-balance\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-header\"\n className={cn(\"flex max-w-sm flex-col items-center gap-2\", className)}\n {...props}\n />\n );\n}\n\nconst emptyMediaVariants = cva(\n \"mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n icon: \"flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-6\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n);\n\nfunction EmptyMedia({\n className,\n variant = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof emptyMediaVariants>) {\n return (\n <div\n data-slot=\"empty-icon\"\n data-variant={variant}\n className={cn(emptyMediaVariants({ variant, className }))}\n {...props}\n />\n );\n}\n\nfunction EmptyTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-title\"\n className={cn(\n \"font-sans text-lg font-medium tracking-tight\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <div\n data-slot=\"empty-description\"\n className={cn(\n \"text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-content\"\n className={cn(\n \"flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport {\n Empty,\n EmptyHeader,\n EmptyTitle,\n EmptyDescription,\n EmptyContent,\n EmptyMedia,\n emptyMediaVariants,\n};\n"
16
+ "content": "import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nfunction Empty({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty\"\n className={cn(\n \"flex w-full min-w-0 flex-1 flex-col items-center justify-center gap-4 rounded-lg border-dashed p-12 text-center text-balance\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-header\"\n className={cn(\"flex max-w-sm flex-col items-center gap-2\", className)}\n {...props}\n />\n );\n}\n\nconst emptyMediaVariants = cva(\n \"mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n icon: \"flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-6\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nfunction EmptyMedia({\n className,\n variant = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof emptyMediaVariants>) {\n return (\n <div\n data-slot=\"empty-icon\"\n data-variant={variant}\n className={cn(emptyMediaVariants({ variant, className }))}\n {...props}\n />\n );\n}\n\nfunction EmptyTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-title\"\n className={cn(\"font-sans text-lg font-medium tracking-tight\", className)}\n {...props}\n />\n );\n}\n\nfunction EmptyDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <div\n data-slot=\"empty-description\"\n className={cn(\n \"text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction EmptyContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-content\"\n className={cn(\n \"flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport {\n Empty,\n EmptyContent,\n EmptyDescription,\n EmptyHeader,\n EmptyMedia,\n emptyMediaVariants,\n EmptyTitle,\n};\n"
17
17
  },
18
18
  {
19
19
  "path": "components/base/Empty.md",
@@ -11,7 +11,7 @@
11
11
  "path": "components/base/FeatureCard.tsx",
12
12
  "type": "registry:ui",
13
13
  "target": "components/base/FeatureCard.tsx",
14
- "content": "import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nexport interface FeatureCardProps\n extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n title: React.ReactNode;\n description?: React.ReactNode;\n /** Icono (cualquier nodo: SVG, lucide, etc.). */\n icon?: React.ReactNode;\n /** Si se define, renderiza como <a> con afordancia de hover/foco. */\n href?: string;\n target?: string;\n rel?: string;\n}\n\nconst cardClassName = (interactive: boolean) =>\n cn(\n \"group flex w-full flex-col gap-4 rounded-lg border border-border bg-background p-6 transition-[border-color,box-shadow] duration-150\",\n interactive &&\n \"cursor-pointer hover:border-primary/40 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n );\n\nfunction FeatureCardContent({\n title,\n description,\n icon,\n interactive,\n}: {\n title: React.ReactNode;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n interactive: boolean;\n}) {\n return (\n <>\n {(icon || interactive) && (\n <div className='flex items-start justify-between gap-3'>\n {icon ? (\n <span\n className='inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-accent text-primary [&>svg]:h-4 [&>svg]:w-4'\n aria-hidden>\n {icon}\n </span>\n ) : (\n <span className='min-w-0 flex-1' />\n )}\n {interactive && (\n <svg\n className='h-4 w-4 shrink-0 text-muted-foreground transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:text-foreground'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden>\n <path d='M7 7h10v10M7 17 17 7' />\n </svg>\n )}\n </div>\n )}\n <div className='flex flex-col gap-1'>\n <h3 className='text-sm font-medium text-foreground'>{title}</h3>\n {description != null && description !== \"\" && (\n <p className='text-xs leading-relaxed text-muted-foreground'>\n {description}\n </p>\n )}\n </div>\n </>\n );\n}\n\nexport const FeatureCard = React.forwardRef<HTMLElement, FeatureCardProps>(\n function FeatureCard(\n { title, description, icon, href, target, rel, className, ...props },\n ref,\n ) {\n const interactive = href != null && href !== \"\";\n const classes = cn(cardClassName(interactive), className);\n\n if (interactive) {\n const resolvedRel =\n rel ?? (target === \"_blank\" ? \"noopener noreferrer\" : undefined);\n return (\n <a\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={resolvedRel}\n className={classes}\n {...(props as React.AnchorHTMLAttributes<HTMLAnchorElement>)}>\n <FeatureCardContent\n title={title}\n description={description}\n icon={icon}\n interactive\n />\n </a>\n );\n }\n\n return (\n <article\n ref={ref as React.Ref<HTMLElement>}\n className={classes}\n {...(props as React.HTMLAttributes<HTMLElement>)}>\n <FeatureCardContent\n title={title}\n description={description}\n icon={icon}\n interactive={false}\n />\n </article>\n );\n },\n);\n"
14
+ "content": "import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nexport interface FeatureCardProps extends Omit<React.HTMLAttributes<HTMLElement>, \"title\"> {\n title: React.ReactNode;\n description?: React.ReactNode;\n /** Icono (cualquier nodo: SVG, lucide, etc.). */\n icon?: React.ReactNode;\n /** Si se define, renderiza como <a> con afordancia de hover/foco. */\n href?: string;\n target?: string;\n rel?: string;\n}\n\nconst cardClassName = (interactive: boolean) =>\n cn(\n \"group flex w-full flex-col gap-4 rounded-lg border border-border bg-background p-6 transition-[border-color,box-shadow] duration-150\",\n interactive &&\n \"cursor-pointer hover:border-primary/40 hover:shadow-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\",\n );\n\nfunction FeatureCardContent({\n title,\n description,\n icon,\n interactive,\n}: {\n title: React.ReactNode;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n interactive: boolean;\n}) {\n return (\n <>\n {(icon || interactive) && (\n <div className=\"flex items-start justify-between gap-3\">\n {icon ? (\n <span\n className=\"inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-md bg-accent text-primary [&>svg]:h-4 [&>svg]:w-4\"\n aria-hidden\n >\n {icon}\n </span>\n ) : (\n <span className=\"min-w-0 flex-1\" />\n )}\n {interactive && (\n <svg\n className=\"h-4 w-4 shrink-0 text-muted-foreground transition-transform group-hover:-translate-y-0.5 group-hover:translate-x-0.5 group-hover:text-foreground\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden\n >\n <path d=\"M7 7h10v10M7 17 17 7\" />\n </svg>\n )}\n </div>\n )}\n <div className=\"flex flex-col gap-1\">\n <h3 className=\"text-sm font-medium text-foreground\">{title}</h3>\n {description != null && description !== \"\" && (\n <p className=\"text-xs leading-relaxed text-muted-foreground\">{description}</p>\n )}\n </div>\n </>\n );\n}\n\nexport const FeatureCard = React.forwardRef<HTMLElement, FeatureCardProps>(function FeatureCard(\n { title, description, icon, href, target, rel, className, ...props },\n ref,\n) {\n const interactive = href != null && href !== \"\";\n const classes = cn(cardClassName(interactive), className);\n\n if (interactive) {\n const resolvedRel = rel ?? (target === \"_blank\" ? \"noopener noreferrer\" : undefined);\n return (\n <a\n ref={ref as React.Ref<HTMLAnchorElement>}\n href={href}\n target={target}\n rel={resolvedRel}\n className={classes}\n {...(props as React.AnchorHTMLAttributes<HTMLAnchorElement>)}\n >\n <FeatureCardContent title={title} description={description} icon={icon} interactive />\n </a>\n );\n }\n\n return (\n <article\n ref={ref as React.Ref<HTMLElement>}\n className={classes}\n {...(props as React.HTMLAttributes<HTMLElement>)}\n >\n <FeatureCardContent title={title} description={description} icon={icon} interactive={false} />\n </article>\n );\n});\n"
15
15
  },
16
16
  {
17
17
  "path": "components/base/FeatureCard.md",
@@ -18,7 +18,7 @@
18
18
  "path": "components/base/Form.tsx",
19
19
  "type": "registry:ui",
20
20
  "target": "components/base/Form.tsx",
21
- "content": "import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport {\n Controller,\n FormProvider,\n useFormContext,\n useFormState,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n} from \"react-hook-form\";\n\nimport { cn } from \"@/lib/utils/cn\";\nimport { Label } from \"./Label\";\n\n// Patrón shadcn sobre react-hook-form: Form provee el contexto, FormField\n// registra el campo (Controller) y FormItem/FormLabel/FormControl cablean\n// ids y aria-* automáticamente. Validación con zod vía\n// zodResolver(@hookform/resolvers) — `add form` instala ambas deps.\n\nconst Form = FormProvider;\n\ninterface FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> {\n name: TName;\n}\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>(\n {} as FormFieldContextValue,\n);\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n ...props\n}: ControllerProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\nconst useFormField = () => {\n const fieldContext = React.useContext(FormFieldContext);\n const itemContext = React.useContext(FormItemContext);\n const { getFieldState } = useFormContext();\n const formState = useFormState({ name: fieldContext.name });\n const fieldState = getFieldState(fieldContext.name, formState);\n\n if (!fieldContext) {\n throw new Error(\"useFormField debe usarse dentro de <FormField>\");\n }\n\n const { id } = itemContext;\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n };\n};\n\ninterface FormItemContextValue {\n id: string;\n}\n\nconst FormItemContext = React.createContext<FormItemContextValue>(\n {} as FormItemContextValue,\n);\n\nconst FormItem = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => {\n const id = React.useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div ref={ref} className={cn(\"grid gap-2\", className)} {...props} />\n </FormItemContext.Provider>\n );\n});\nFormItem.displayName = \"FormItem\";\n\nconst FormLabel = React.forwardRef<\n React.ElementRef<typeof Label>,\n React.ComponentPropsWithoutRef<typeof Label>\n>(({ className, ...props }, ref) => {\n const { error, formItemId } = useFormField();\n\n return (\n <Label\n ref={ref}\n className={cn(error && \"text-destructive\", className)}\n htmlFor={formItemId}\n {...props}\n />\n );\n});\nFormLabel.displayName = \"FormLabel\";\n\nconst FormControl = React.forwardRef<\n React.ElementRef<typeof Slot>,\n React.ComponentPropsWithoutRef<typeof Slot>\n>(({ ...props }, ref) => {\n const { error, formItemId, formDescriptionId, formMessageId } =\n useFormField();\n\n return (\n <Slot\n ref={ref}\n id={formItemId}\n aria-describedby={\n !error\n ? `${formDescriptionId}`\n : `${formDescriptionId} ${formMessageId}`\n }\n aria-invalid={!!error}\n {...props}\n />\n );\n});\nFormControl.displayName = \"FormControl\";\n\nconst FormDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => {\n const { formDescriptionId } = useFormField();\n\n return (\n <p\n ref={ref}\n id={formDescriptionId}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n );\n});\nFormDescription.displayName = \"FormDescription\";\n\nconst FormMessage = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message ?? \"\") : children;\n\n if (!body) {\n return null;\n }\n\n return (\n <p\n ref={ref}\n id={formMessageId}\n className={cn(\"text-sm text-destructive\", className)}\n {...props}\n >\n {body}\n </p>\n );\n});\nFormMessage.displayName = \"FormMessage\";\n\nexport {\n useFormField,\n Form,\n FormItem,\n FormLabel,\n FormControl,\n FormDescription,\n FormMessage,\n FormField,\n};\n"
21
+ "content": "import { Slot } from \"@radix-ui/react-slot\";\nimport * as React from \"react\";\nimport {\n Controller,\n type ControllerProps,\n type FieldPath,\n type FieldValues,\n FormProvider,\n useFormContext,\n useFormState,\n} from \"react-hook-form\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nimport { Label } from \"./Label\";\n\n// Patrón shadcn sobre react-hook-form: Form provee el contexto, FormField\n// registra el campo (Controller) y FormItem/FormLabel/FormControl cablean\n// ids y aria-* automáticamente. Validación con zod vía\n// zodResolver(@hookform/resolvers) — `add form` instala ambas deps.\n\nconst Form = FormProvider;\n\ninterface FormFieldContextValue<\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n> {\n name: TName;\n}\n\nconst FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);\n\nconst FormField = <\n TFieldValues extends FieldValues = FieldValues,\n TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,\n>({\n ...props\n}: ControllerProps<TFieldValues, TName>) => {\n return (\n <FormFieldContext.Provider value={{ name: props.name }}>\n <Controller {...props} />\n </FormFieldContext.Provider>\n );\n};\n\nconst useFormField = () => {\n const fieldContext = React.useContext(FormFieldContext);\n const itemContext = React.useContext(FormItemContext);\n const { getFieldState } = useFormContext();\n const formState = useFormState({ name: fieldContext.name });\n const fieldState = getFieldState(fieldContext.name, formState);\n\n if (!fieldContext) {\n throw new Error(\"useFormField debe usarse dentro de <FormField>\");\n }\n\n const { id } = itemContext;\n\n return {\n id,\n name: fieldContext.name,\n formItemId: `${id}-form-item`,\n formDescriptionId: `${id}-form-item-description`,\n formMessageId: `${id}-form-item-message`,\n ...fieldState,\n };\n};\n\ninterface FormItemContextValue {\n id: string;\n}\n\nconst FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);\n\nconst FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => {\n const id = React.useId();\n\n return (\n <FormItemContext.Provider value={{ id }}>\n <div ref={ref} className={cn(\"grid gap-2\", className)} {...props} />\n </FormItemContext.Provider>\n );\n },\n);\nFormItem.displayName = \"FormItem\";\n\nconst FormLabel = React.forwardRef<\n React.ElementRef<typeof Label>,\n React.ComponentPropsWithoutRef<typeof Label>\n>(({ className, ...props }, ref) => {\n const { error, formItemId } = useFormField();\n\n return (\n <Label\n ref={ref}\n className={cn(error && \"text-destructive\", className)}\n htmlFor={formItemId}\n {...props}\n />\n );\n});\nFormLabel.displayName = \"FormLabel\";\n\nconst FormControl = React.forwardRef<\n React.ElementRef<typeof Slot>,\n React.ComponentPropsWithoutRef<typeof Slot>\n>(({ ...props }, ref) => {\n const { error, formItemId, formDescriptionId, formMessageId } = useFormField();\n\n return (\n <Slot\n ref={ref}\n id={formItemId}\n aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}\n aria-invalid={!!error}\n {...props}\n />\n );\n});\nFormControl.displayName = \"FormControl\";\n\nconst FormDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => {\n const { formDescriptionId } = useFormField();\n\n return (\n <p\n ref={ref}\n id={formDescriptionId}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n );\n});\nFormDescription.displayName = \"FormDescription\";\n\nconst FormMessage = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, children, ...props }, ref) => {\n const { error, formMessageId } = useFormField();\n const body = error ? String(error?.message ?? \"\") : children;\n\n if (!body) {\n return null;\n }\n\n return (\n <p\n ref={ref}\n id={formMessageId}\n className={cn(\"text-sm text-destructive\", className)}\n {...props}\n >\n {body}\n </p>\n );\n});\nFormMessage.displayName = \"FormMessage\";\n\nexport {\n Form,\n FormControl,\n FormDescription,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n useFormField,\n};\n"
22
22
  },
23
23
  {
24
24
  "path": "components/base/Form.md",
@@ -15,7 +15,7 @@
15
15
  "path": "components/base/HeaderBar.tsx",
16
16
  "type": "registry:ui",
17
17
  "target": "components/base/HeaderBar.tsx",
18
- "content": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils/cn\";\nimport { Logo } from \"./Logo\";\n\n// `brand-navy` = navy/ink de marca Lexy (mismo del wordmark oscuro), definido\n// en el theme como --color-brand-navy.\nconst headerVariants = cva(\n \"flex h-16 w-full shrink-0 items-center justify-between gap-6\",\n {\n variants: {\n surface: {\n default: \"bg-background text-foreground\",\n transparent: \"bg-transparent text-foreground\",\n navy: \"bg-brand-navy text-white\",\n },\n bordered: { true: \"border-b\", false: \"\" },\n padding: {\n page: \"px-4 md:px-6 lg:px-8\",\n none: \"px-0\",\n },\n sticky: { true: \"sticky top-0 z-50\", false: \"\" },\n },\n compoundVariants: [\n { surface: \"default\", bordered: true, class: \"border-border\" },\n { surface: \"transparent\", bordered: true, class: \"border-border\" },\n { surface: \"navy\", bordered: true, class: \"border-white/15\" },\n ],\n defaultVariants: {\n surface: \"default\",\n bordered: true,\n padding: \"page\",\n sticky: false,\n },\n },\n);\n\nexport interface HeaderBarProps\n extends React.HTMLAttributes<HTMLElement>,\n VariantProps<typeof headerVariants> {\n /** Acciones alineadas a la derecha (botones, avatar, menús). */\n actions?: React.ReactNode;\n /** Sobrescribe el área de marca (por defecto, el `Logo`). */\n brand?: React.ReactNode;\n}\n\nexport const HeaderBar = React.forwardRef<HTMLElement, HeaderBarProps>(\n function HeaderBar(\n { surface = \"default\", bordered, padding, sticky, actions, brand, className, ...props },\n ref,\n ) {\n const logoSurface = surface === \"navy\" ? \"dark\" : \"light\";\n\n return (\n <header\n ref={ref}\n className={cn(\n headerVariants({ surface, bordered, padding, sticky }),\n className,\n )}\n {...props}>\n <div className='flex min-w-0 items-center gap-6'>\n {brand ?? <Logo surface={logoSurface} />}\n </div>\n {actions != null && (\n <div className='flex shrink-0 items-center gap-2'>{actions}</div>\n )}\n </header>\n );\n },\n);\n\nHeaderBar.displayName = \"HeaderBar\";\n\nexport { headerVariants };\n"
18
+ "content": "import { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nimport { Logo } from \"./Logo\";\n\n// `brand-navy` = navy/ink de marca Lexy (mismo del wordmark oscuro), definido\n// en el theme como --color-brand-navy.\nconst headerVariants = cva(\"flex h-16 w-full shrink-0 items-center justify-between gap-6\", {\n variants: {\n surface: {\n default: \"bg-background text-foreground\",\n transparent: \"bg-transparent text-foreground\",\n navy: \"bg-brand-navy text-white\",\n },\n bordered: { true: \"border-b\", false: \"\" },\n padding: {\n page: \"px-4 md:px-6 lg:px-8\",\n none: \"px-0\",\n },\n sticky: { true: \"sticky top-0 z-50\", false: \"\" },\n },\n compoundVariants: [\n { surface: \"default\", bordered: true, class: \"border-border\" },\n { surface: \"transparent\", bordered: true, class: \"border-border\" },\n { surface: \"navy\", bordered: true, class: \"border-white/15\" },\n ],\n defaultVariants: {\n surface: \"default\",\n bordered: true,\n padding: \"page\",\n sticky: false,\n },\n});\n\nexport interface HeaderBarProps\n extends React.HTMLAttributes<HTMLElement>, VariantProps<typeof headerVariants> {\n /** Acciones alineadas a la derecha (botones, avatar, menús). */\n actions?: React.ReactNode;\n /** Sobrescribe el área de marca (por defecto, el `Logo`). */\n brand?: React.ReactNode;\n}\n\nexport const HeaderBar = React.forwardRef<HTMLElement, HeaderBarProps>(function HeaderBar(\n { surface = \"default\", bordered, padding, sticky, actions, brand, className, ...props },\n ref,\n) {\n const logoSurface = surface === \"navy\" ? \"dark\" : \"light\";\n\n return (\n <header\n ref={ref}\n className={cn(headerVariants({ surface, bordered, padding, sticky }), className)}\n {...props}\n >\n <div className=\"flex min-w-0 items-center gap-6\">\n {brand ?? <Logo surface={logoSurface} />}\n </div>\n {actions != null && <div className=\"flex shrink-0 items-center gap-2\">{actions}</div>}\n </header>\n );\n});\n\nHeaderBar.displayName = \"HeaderBar\";\n\nexport { headerVariants };\n"
19
19
  },
20
20
  {
21
21
  "path": "components/base/HeaderBar.md",
@@ -16,7 +16,7 @@
16
16
  "path": "views/IntakeDatosPersonales.tsx",
17
17
  "type": "registry:file",
18
18
  "target": "views/IntakeDatosPersonales.tsx",
19
- "content": "import { Button } from \"@/components/base/Button\";\nimport { Input } from \"@/components/base/Input\";\nimport { Label } from \"@/components/base/Label\";\nimport { Progress } from \"@/components/base/Progress\";\n\n// Receta cliente — intake / ficha web (paso de wizard): un paso enfocado,\n// columna angosta, calma, CTA al final. Ver intake-wizard.md.\n\nexport function IntakeDatosPersonales() {\n return (\n <main className='mx-auto w-full max-w-xl px-4 py-10'>\n <div className='mb-8'>\n <p className='mb-2 text-sm text-muted-foreground'>Paso 2 de 4</p>\n <Progress value={50} aria-label='Avance del formulario' />\n </div>\n\n <header className='mb-6'>\n <h1 className='text-2xl font-bold text-foreground'>Cuéntanos tus datos</h1>\n <p className='mt-2 text-base text-muted-foreground'>\n Usaremos esta información para preparar la primera revisión de tu caso.\n </p>\n </header>\n\n <form className='space-y-5'>\n <fieldset className='space-y-5 border-0 p-0'>\n <legend className='sr-only'>Datos personales</legend>\n\n <div className='space-y-2'>\n <Label htmlFor='nombre'>Nombre completo</Label>\n <Input id='nombre' name='nombre' placeholder='Escribe tu nombre' />\n </div>\n\n <div className='space-y-2'>\n <Label htmlFor='correo'>Correo</Label>\n <Input id='correo' name='correo' type='email' placeholder='tu@correo.cl' />\n <p className='text-xs text-muted-foreground'>\n Te escribiremos solo para avanzar con tu caso.\n </p>\n </div>\n </fieldset>\n\n <div className='flex items-center justify-between pt-2'>\n <Button type='button' variant='ghost'>Volver</Button>\n <Button type='submit'>Guardar y continuar</Button>\n </div>\n </form>\n </main>\n );\n}\n"
19
+ "content": "import { Button } from \"@/components/base/Button\";\nimport { Input } from \"@/components/base/Input\";\nimport { Label } from \"@/components/base/Label\";\nimport { Progress } from \"@/components/base/Progress\";\n\n// Receta cliente — intake / ficha web (paso de wizard): un paso enfocado,\n// columna angosta, calma, CTA al final. Ver intake-wizard.md.\n\nexport function IntakeDatosPersonales() {\n return (\n <main className=\"mx-auto w-full max-w-xl px-4 py-10\">\n <div className=\"mb-8\">\n <p className=\"mb-2 text-sm text-muted-foreground\">Paso 2 de 4</p>\n <Progress value={50} aria-label=\"Avance del formulario\" />\n </div>\n\n <header className=\"mb-6\">\n <h1 className=\"text-2xl font-bold text-foreground\">Cuéntanos tus datos</h1>\n <p className=\"mt-2 text-base text-muted-foreground\">\n Usaremos esta información para preparar la primera revisión de tu caso.\n </p>\n </header>\n\n <form className=\"space-y-5\">\n <fieldset className=\"space-y-5 border-0 p-0\">\n <legend className=\"sr-only\">Datos personales</legend>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"nombre\">Nombre completo</Label>\n <Input id=\"nombre\" name=\"nombre\" placeholder=\"Escribe tu nombre\" />\n </div>\n\n <div className=\"space-y-2\">\n <Label htmlFor=\"correo\">Correo</Label>\n <Input id=\"correo\" name=\"correo\" type=\"email\" placeholder=\"tu@correo.cl\" />\n <p className=\"text-xs text-muted-foreground\">\n Te escribiremos solo para avanzar con tu caso.\n </p>\n </div>\n </fieldset>\n\n <div className=\"flex items-center justify-between pt-2\">\n <Button type=\"button\" variant=\"ghost\">\n Volver\n </Button>\n <Button type=\"submit\">Guardar y continuar</Button>\n </div>\n </form>\n </main>\n );\n}\n"
20
20
  },
21
21
  {
22
22
  "path": "views/intake-wizard.md",
@@ -14,7 +14,7 @@
14
14
  "path": "components/base/Label.tsx",
15
15
  "type": "registry:ui",
16
16
  "target": "components/base/Label.tsx",
17
- "content": "import * as React from \"react\";\nimport * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst labelVariants = cva(\n \"text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants> & {\n required?: boolean;\n }\n>(({ className, required, children, ...props }, ref) => (\n <LabelPrimitive.Root\n ref={ref}\n className={cn(labelVariants(), className)}\n {...props}\n >\n {children}\n {required && (\n <span aria-hidden=\"true\" className=\"ml-0.5 text-destructive\">\n *\n </span>\n )}\n </LabelPrimitive.Root>\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label, labelVariants };\n"
17
+ "content": "import * as LabelPrimitive from \"@radix-ui/react-label\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst labelVariants = cva(\n \"text-sm font-medium leading-none text-foreground peer-disabled:cursor-not-allowed peer-disabled:opacity-70\",\n);\n\nconst Label = React.forwardRef<\n React.ElementRef<typeof LabelPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &\n VariantProps<typeof labelVariants> & {\n required?: boolean;\n }\n>(({ className, required, children, ...props }, ref) => (\n <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props}>\n {children}\n {required && (\n <span aria-hidden=\"true\" className=\"ml-0.5 text-destructive\">\n *\n </span>\n )}\n </LabelPrimitive.Root>\n));\nLabel.displayName = LabelPrimitive.Root.displayName;\n\nexport { Label, labelVariants };\n"
18
18
  },
19
19
  {
20
20
  "path": "components/base/Label.md",
@@ -16,7 +16,7 @@
16
16
  "path": "views/Login.tsx",
17
17
  "type": "registry:file",
18
18
  "target": "views/Login.tsx",
19
- "content": "import { Button } from \"@/components/base/Button\";\nimport { Card, CardHeader, CardTitle, CardDescription, CardContent } from \"@/components/base/Card\";\nimport { Input } from \"@/components/base/Input\";\nimport { Label } from \"@/components/base/Label\";\n\n// Receta cliente — acceso (login): una sola tarea, foco único, ayuda\n// contextual breve. Para CRM, ver la variante en login.md. Ver login.md.\n\nexport function Login() {\n return (\n <main className='flex min-h-screen items-center justify-center bg-background px-4'>\n <Card className='w-full max-w-sm'>\n <CardHeader>\n <CardTitle>Ingresa a Lexy</CardTitle>\n <CardDescription>Te acompañamos con tu caso desde aquí.</CardDescription>\n </CardHeader>\n <CardContent>\n <form className='space-y-4'>\n <div className='space-y-2'>\n <Label htmlFor='email'>Correo</Label>\n <Input id='email' type='email' placeholder='tu@correo.cl' />\n </div>\n <div className='space-y-2'>\n <Label htmlFor='pass'>Contraseña</Label>\n <Input id='pass' type='password' placeholder='Ingresa tu contraseña' />\n </div>\n <Button type='submit' className='w-full'>Entrar</Button>\n </form>\n </CardContent>\n </Card>\n </main>\n );\n}\n"
19
+ "content": "import { Button } from \"@/components/base/Button\";\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from \"@/components/base/Card\";\nimport { Input } from \"@/components/base/Input\";\nimport { Label } from \"@/components/base/Label\";\n\n// Receta cliente — acceso (login): una sola tarea, foco único, ayuda\n// contextual breve. Para CRM, ver la variante en login.md. Ver login.md.\n\nexport function Login() {\n return (\n <main className=\"flex min-h-screen items-center justify-center bg-background px-4\">\n <Card className=\"w-full max-w-sm\">\n <CardHeader>\n <CardTitle>Ingresa a Lexy</CardTitle>\n <CardDescription>Te acompañamos con tu caso desde aquí.</CardDescription>\n </CardHeader>\n <CardContent>\n <form className=\"space-y-4\">\n <div className=\"space-y-2\">\n <Label htmlFor=\"email\">Correo</Label>\n <Input id=\"email\" type=\"email\" placeholder=\"tu@correo.cl\" />\n </div>\n <div className=\"space-y-2\">\n <Label htmlFor=\"pass\">Contraseña</Label>\n <Input id=\"pass\" type=\"password\" placeholder=\"Ingresa tu contraseña\" />\n </div>\n <Button type=\"submit\" className=\"w-full\">\n Entrar\n </Button>\n </form>\n </CardContent>\n </Card>\n </main>\n );\n}\n"
20
20
  },
21
21
  {
22
22
  "path": "views/login.md",
@@ -11,7 +11,7 @@
11
11
  "path": "components/base/Logo.tsx",
12
12
  "type": "registry:ui",
13
13
  "target": "components/base/Logo.tsx",
14
- "content": "import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nimport lexyDarkHorizontal from \"./assets/logo/lexy-dark-horizontal.svg\";\nimport lexyDarkHorizontalSlogan from \"./assets/logo/lexy-dark-horizontal-slogan.svg\";\nimport lexyDarkVertical from \"./assets/logo/lexy-dark-vertical.svg\";\nimport lexyDarkVerticalSlogan from \"./assets/logo/lexy-dark-vertical-slogan.svg\";\nimport lexyDarkIsotipe from \"./assets/logo/lexy-dark-isotipe.svg\";\nimport lexyLightHorizontal from \"./assets/logo/lexy-light-horizontal.svg\";\nimport lexyLightHorizontalSlogan from \"./assets/logo/lexy-light-horizontal-slogan.svg\";\nimport lexyLightVertical from \"./assets/logo/lexy-light-vertical.svg\";\nimport lexyLightVerticalSlogan from \"./assets/logo/lexy-light-vertical-slogan.svg\";\nimport lexyLightIsotipe from \"./assets/logo/lexy-light-isotipe.svg\";\nimport saludDarkV1 from \"./assets/logo/lexysalud-dark-v1.svg\";\nimport saludDarkV2 from \"./assets/logo/lexysalud-dark-v2.svg\";\nimport saludLightV1 from \"./assets/logo/lexysalud-light-v1.svg\";\nimport saludLightV2 from \"./assets/logo/lexysalud-light-v2.svg\";\nimport deudorDarkV1 from \"./assets/logo/lexydeudor-dark-v1.svg\";\nimport deudorDarkV2 from \"./assets/logo/lexydeudor-dark-v2.svg\";\nimport deudorLightV1 from \"./assets/logo/lexydeudor-light-v1.svg\";\nimport deudorLightV2 from \"./assets/logo/lexydeudor-light-v2.svg\";\n\nexport type LogoBrand = \"lexy\" | \"salud\" | \"deudor\";\n/**\n * Color del fondo sobre el que va el logo:\n * - `light` (fondo claro) → logo OSCURO (navy). ← por defecto\n * - `dark` (fondo oscuro) → logo CLARO (blanco).\n */\nexport type LogoSurface = \"light\" | \"dark\";\nexport type LogoLayout = \"horizontal\" | \"vertical\" | \"isotipe\";\nexport type LogoVersion = \"v1\" | \"v2\";\n\n// Clave del mapa = el `surface` (fondo). El archivo `*-light-*` trae arte oscuro\n// (para fondo claro) y `*-dark-*` trae arte claro (para fondo oscuro).\nconst lexyMap = {\n light: {\n horizontal: { false: lexyLightHorizontal, true: lexyLightHorizontalSlogan },\n vertical: { false: lexyLightVertical, true: lexyLightVerticalSlogan },\n isotipe: { false: lexyLightIsotipe, true: lexyLightIsotipe },\n },\n dark: {\n horizontal: { false: lexyDarkHorizontal, true: lexyDarkHorizontalSlogan },\n vertical: { false: lexyDarkVertical, true: lexyDarkVerticalSlogan },\n isotipe: { false: lexyDarkIsotipe, true: lexyDarkIsotipe },\n },\n} as const;\n\nconst subBrandMap = {\n salud: {\n light: { v1: saludLightV1, v2: saludLightV2 },\n dark: { v1: saludDarkV1, v2: saludDarkV2 },\n },\n deudor: {\n light: { v1: deudorLightV1, v2: deudorLightV2 },\n dark: { v1: deudorDarkV1, v2: deudorDarkV2 },\n },\n} as const;\n\nexport interface LogoProps\n extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, \"src\"> {\n brand?: LogoBrand;\n /** Fondo sobre el que va el logo. `light` (def.) = logo oscuro; `dark` = logo claro. */\n surface?: LogoSurface;\n /** Solo Lexy. */\n layout?: LogoLayout;\n /** Solo Lexy. */\n slogan?: boolean;\n /** Solo sub-marcas (salud / deudor). */\n version?: LogoVersion;\n}\n\nexport const Logo = React.forwardRef<HTMLImageElement, LogoProps>(function Logo(\n {\n brand = \"lexy\",\n surface = \"light\",\n layout = \"horizontal\",\n slogan = false,\n version = \"v1\",\n alt,\n className,\n draggable = false,\n ...props\n },\n ref,\n) {\n let src: string;\n let label: string;\n\n if (brand === \"lexy\") {\n src = lexyMap[surface][layout][slogan ? \"true\" : \"false\"];\n label = \"Lexy\";\n } else {\n src = subBrandMap[brand][surface][version];\n label = brand === \"salud\" ? \"Lexy Salud\" : \"Lexy Deudor\";\n }\n\n return (\n <img\n ref={ref}\n src={src}\n alt={alt ?? label}\n draggable={draggable}\n className={cn(\"block h-8 w-auto max-w-full select-none\", className)}\n {...props}\n />\n );\n});\n\nLogo.displayName = \"Logo\";\n"
14
+ "content": "import * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nimport lexyDarkHorizontal from \"./assets/logo/lexy-dark-horizontal.svg\";\nimport lexyDarkHorizontalSlogan from \"./assets/logo/lexy-dark-horizontal-slogan.svg\";\nimport lexyDarkIsotipe from \"./assets/logo/lexy-dark-isotipe.svg\";\nimport lexyDarkVertical from \"./assets/logo/lexy-dark-vertical.svg\";\nimport lexyDarkVerticalSlogan from \"./assets/logo/lexy-dark-vertical-slogan.svg\";\nimport lexyLightHorizontal from \"./assets/logo/lexy-light-horizontal.svg\";\nimport lexyLightHorizontalSlogan from \"./assets/logo/lexy-light-horizontal-slogan.svg\";\nimport lexyLightIsotipe from \"./assets/logo/lexy-light-isotipe.svg\";\nimport lexyLightVertical from \"./assets/logo/lexy-light-vertical.svg\";\nimport lexyLightVerticalSlogan from \"./assets/logo/lexy-light-vertical-slogan.svg\";\nimport deudorDarkV1 from \"./assets/logo/lexydeudor-dark-v1.svg\";\nimport deudorDarkV2 from \"./assets/logo/lexydeudor-dark-v2.svg\";\nimport deudorLightV1 from \"./assets/logo/lexydeudor-light-v1.svg\";\nimport deudorLightV2 from \"./assets/logo/lexydeudor-light-v2.svg\";\nimport saludDarkV1 from \"./assets/logo/lexysalud-dark-v1.svg\";\nimport saludDarkV2 from \"./assets/logo/lexysalud-dark-v2.svg\";\nimport saludLightV1 from \"./assets/logo/lexysalud-light-v1.svg\";\nimport saludLightV2 from \"./assets/logo/lexysalud-light-v2.svg\";\n\nexport type LogoBrand = \"lexy\" | \"salud\" | \"deudor\";\n/**\n * Color del fondo sobre el que va el logo:\n * - `light` (fondo claro) → logo OSCURO (navy). ← por defecto\n * - `dark` (fondo oscuro) → logo CLARO (blanco).\n */\nexport type LogoSurface = \"light\" | \"dark\";\nexport type LogoLayout = \"horizontal\" | \"vertical\" | \"isotipe\";\nexport type LogoVersion = \"v1\" | \"v2\";\n\n// Clave del mapa = el `surface` (fondo). El archivo `*-light-*` trae arte oscuro\n// (para fondo claro) y `*-dark-*` trae arte claro (para fondo oscuro).\nconst lexyMap = {\n light: {\n horizontal: { false: lexyLightHorizontal, true: lexyLightHorizontalSlogan },\n vertical: { false: lexyLightVertical, true: lexyLightVerticalSlogan },\n isotipe: { false: lexyLightIsotipe, true: lexyLightIsotipe },\n },\n dark: {\n horizontal: { false: lexyDarkHorizontal, true: lexyDarkHorizontalSlogan },\n vertical: { false: lexyDarkVertical, true: lexyDarkVerticalSlogan },\n isotipe: { false: lexyDarkIsotipe, true: lexyDarkIsotipe },\n },\n} as const;\n\nconst subBrandMap = {\n salud: {\n light: { v1: saludLightV1, v2: saludLightV2 },\n dark: { v1: saludDarkV1, v2: saludDarkV2 },\n },\n deudor: {\n light: { v1: deudorLightV1, v2: deudorLightV2 },\n dark: { v1: deudorDarkV1, v2: deudorDarkV2 },\n },\n} as const;\n\nexport interface LogoProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, \"src\"> {\n brand?: LogoBrand;\n /** Fondo sobre el que va el logo. `light` (def.) = logo oscuro; `dark` = logo claro. */\n surface?: LogoSurface;\n /** Solo Lexy. */\n layout?: LogoLayout;\n /** Solo Lexy. */\n slogan?: boolean;\n /** Solo sub-marcas (salud / deudor). */\n version?: LogoVersion;\n}\n\nexport const Logo = React.forwardRef<HTMLImageElement, LogoProps>(function Logo(\n {\n brand = \"lexy\",\n surface = \"light\",\n layout = \"horizontal\",\n slogan = false,\n version = \"v1\",\n alt,\n className,\n draggable = false,\n ...props\n },\n ref,\n) {\n let src: string;\n let label: string;\n\n if (brand === \"lexy\") {\n src = lexyMap[surface][layout][slogan ? \"true\" : \"false\"];\n label = \"Lexy\";\n } else {\n src = subBrandMap[brand][surface][version];\n label = brand === \"salud\" ? \"Lexy Salud\" : \"Lexy Deudor\";\n }\n\n return (\n <img\n ref={ref}\n src={src}\n alt={alt ?? label}\n draggable={draggable}\n className={cn(\"block h-8 w-auto max-w-full select-none\", className)}\n {...props}\n />\n );\n});\n\nLogo.displayName = \"Logo\";\n"
15
15
  },
16
16
  {
17
17
  "path": "components/base/Logo.md",
@@ -13,7 +13,7 @@
13
13
  "path": "components/base/Menubar.tsx",
14
14
  "type": "registry:ui",
15
15
  "target": "components/base/Menubar.tsx",
16
- "content": "import * as React from \"react\";\nimport * as MenubarPrimitive from \"@radix-ui/react-menubar\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst MenubarMenu = MenubarPrimitive.Menu;\nconst MenubarGroup = MenubarPrimitive.Group;\nconst MenubarPortal = MenubarPrimitive.Portal;\nconst MenubarSub = MenubarPrimitive.Sub;\nconst MenubarRadioGroup = MenubarPrimitive.RadioGroup;\n\nconst ChevronRightIcon = () => (\n <svg\n className='ml-auto h-4 w-4'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'>\n <path d='m9 18 6-6-6-6' />\n </svg>\n);\n\nconst CheckIcon = () => (\n <svg\n className='h-4 w-4'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'>\n <path d='M20 6 9 17l-5-5' />\n </svg>\n);\n\nconst DotIcon = () => (\n <svg className='h-2 w-2 fill-current' viewBox='0 0 24 24'>\n <circle cx='12' cy='12' r='12' />\n </svg>\n);\n\nconst Menubar = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Root\n ref={ref}\n className={cn(\n \"flex h-10 items-center gap-1 rounded border border-border bg-background p-1\",\n className,\n )}\n {...props}\n />\n));\nMenubar.displayName = MenubarPrimitive.Root.displayName;\n\nconst MenubarTrigger = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex cursor-pointer select-none items-center rounded px-3 py-1.5 text-sm font-medium text-foreground outline-none focus:bg-primary/15 focus:text-primary data-[state=open]:bg-primary/15 data-[state=open]:text-primary\",\n className,\n )}\n {...props}\n />\n));\nMenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;\n\nconst MenubarSubTrigger = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <MenubarPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-pointer select-none items-center rounded px-2 py-1.5 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[state=open]:bg-primary/15 data-[state=open]:text-primary\",\n inset && \"pl-8\",\n className,\n )}\n {...props}>\n {children}\n <ChevronRightIcon />\n </MenubarPrimitive.SubTrigger>\n));\nMenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;\n\nconst MenubarSubContent = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-32 overflow-hidden rounded border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n className,\n )}\n {...props}\n />\n));\nMenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;\n\nconst MenubarContent = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>\n>(\n (\n { className, align = \"start\", alignOffset = -4, sideOffset = 8, ...props },\n ref,\n ) => (\n <MenubarPortal>\n <MenubarPrimitive.Content\n ref={ref}\n align={align}\n alignOffset={alignOffset}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 min-w-48 overflow-hidden rounded border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n className,\n )}\n {...props}\n />\n </MenubarPortal>\n ),\n);\nMenubarContent.displayName = MenubarPrimitive.Content.displayName;\n\nconst MenubarItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded px-2 py-1.5 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nMenubarItem.displayName = MenubarPrimitive.Item.displayName;\n\nconst MenubarCheckboxItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <MenubarPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n checked={checked}\n {...props}>\n <span className='absolute left-2 flex h-3.5 w-3.5 items-center justify-center'>\n <MenubarPrimitive.ItemIndicator>\n <CheckIcon />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n));\nMenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;\n\nconst MenubarRadioItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <MenubarPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}>\n <span className='absolute left-2 flex h-3.5 w-3.5 items-center justify-center'>\n <MenubarPrimitive.ItemIndicator>\n <DotIcon />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.RadioItem>\n));\nMenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;\n\nconst MenubarLabel = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Label\n ref={ref}\n className={cn(\n \"px-2 py-1.5 text-sm font-semibold text-foreground\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nMenubarLabel.displayName = MenubarPrimitive.Label.displayName;\n\nconst MenubarSeparator = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n));\nMenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;\n\nconst MenubarShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => (\n <span\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground\",\n className,\n )}\n {...props}\n />\n);\nMenubarShortcut.displayName = \"MenubarShortcut\";\n\nexport {\n Menubar,\n MenubarMenu,\n MenubarTrigger,\n MenubarContent,\n MenubarItem,\n MenubarSeparator,\n MenubarLabel,\n MenubarCheckboxItem,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarPortal,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarGroup,\n MenubarSub,\n MenubarShortcut,\n};\n"
16
+ "content": "import * as MenubarPrimitive from \"@radix-ui/react-menubar\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst MenubarMenu = MenubarPrimitive.Menu;\nconst MenubarGroup = MenubarPrimitive.Group;\nconst MenubarPortal = MenubarPrimitive.Portal;\nconst MenubarSub = MenubarPrimitive.Sub;\nconst MenubarRadioGroup = MenubarPrimitive.RadioGroup;\n\nconst ChevronRightIcon = () => (\n <svg\n className=\"ml-auto h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n);\n\nconst CheckIcon = () => (\n <svg\n className=\"h-4 w-4\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M20 6 9 17l-5-5\" />\n </svg>\n);\n\nconst DotIcon = () => (\n <svg className=\"h-2 w-2 fill-current\" viewBox=\"0 0 24 24\">\n <circle cx=\"12\" cy=\"12\" r=\"12\" />\n </svg>\n);\n\nconst Menubar = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Root\n ref={ref}\n className={cn(\n \"flex h-10 items-center gap-1 rounded border border-border bg-background p-1\",\n className,\n )}\n {...props}\n />\n));\nMenubar.displayName = MenubarPrimitive.Root.displayName;\n\nconst MenubarTrigger = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex cursor-pointer select-none items-center rounded px-3 py-1.5 text-sm font-medium text-foreground outline-none focus:bg-primary/15 focus:text-primary data-[state=open]:bg-primary/15 data-[state=open]:text-primary\",\n className,\n )}\n {...props}\n />\n));\nMenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;\n\nconst MenubarSubTrigger = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {\n inset?: boolean;\n }\n>(({ className, inset, children, ...props }, ref) => (\n <MenubarPrimitive.SubTrigger\n ref={ref}\n className={cn(\n \"flex cursor-pointer select-none items-center rounded px-2 py-1.5 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[state=open]:bg-primary/15 data-[state=open]:text-primary\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronRightIcon />\n </MenubarPrimitive.SubTrigger>\n));\nMenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;\n\nconst MenubarSubContent = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.SubContent\n ref={ref}\n className={cn(\n \"z-50 min-w-32 overflow-hidden rounded border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n className,\n )}\n {...props}\n />\n));\nMenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;\n\nconst MenubarContent = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>\n>(({ className, align = \"start\", alignOffset = -4, sideOffset = 8, ...props }, ref) => (\n <MenubarPortal>\n <MenubarPrimitive.Content\n ref={ref}\n align={align}\n alignOffset={alignOffset}\n sideOffset={sideOffset}\n className={cn(\n \"z-50 min-w-48 overflow-hidden rounded border border-border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95\",\n className,\n )}\n {...props}\n />\n </MenubarPortal>\n));\nMenubarContent.displayName = MenubarPrimitive.Content.displayName;\n\nconst MenubarItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Item\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded px-2 py-1.5 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n inset && \"pl-8\",\n className,\n )}\n {...props}\n />\n));\nMenubarItem.displayName = MenubarPrimitive.Item.displayName;\n\nconst MenubarCheckboxItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <MenubarPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <CheckIcon />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.CheckboxItem>\n));\nMenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;\n\nconst MenubarRadioItem = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <MenubarPrimitive.RadioItem\n ref={ref}\n className={cn(\n \"relative flex cursor-pointer select-none items-center rounded py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-primary/15 focus:text-primary data-[disabled]:pointer-events-none data-[disabled]:opacity-50\",\n className,\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <MenubarPrimitive.ItemIndicator>\n <DotIcon />\n </MenubarPrimitive.ItemIndicator>\n </span>\n {children}\n </MenubarPrimitive.RadioItem>\n));\nMenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;\n\nconst MenubarLabel = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {\n inset?: boolean;\n }\n>(({ className, inset, ...props }, ref) => (\n <MenubarPrimitive.Label\n ref={ref}\n className={cn(\"px-2 py-1.5 text-sm font-semibold text-foreground\", inset && \"pl-8\", className)}\n {...props}\n />\n));\nMenubarLabel.displayName = MenubarPrimitive.Label.displayName;\n\nconst MenubarSeparator = React.forwardRef<\n React.ElementRef<typeof MenubarPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <MenubarPrimitive.Separator\n ref={ref}\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n));\nMenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;\n\nconst MenubarShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => (\n <span\n className={cn(\"ml-auto text-xs tracking-widest text-muted-foreground\", className)}\n {...props}\n />\n);\nMenubarShortcut.displayName = \"MenubarShortcut\";\n\nexport {\n Menubar,\n MenubarCheckboxItem,\n MenubarContent,\n MenubarGroup,\n MenubarItem,\n MenubarLabel,\n MenubarMenu,\n MenubarPortal,\n MenubarRadioGroup,\n MenubarRadioItem,\n MenubarSeparator,\n MenubarShortcut,\n MenubarSub,\n MenubarSubContent,\n MenubarSubTrigger,\n MenubarTrigger,\n};\n"
17
17
  },
18
18
  {
19
19
  "path": "components/base/Menubar.md",
@@ -14,7 +14,7 @@
14
14
  "path": "components/base/NavigationMenu.tsx",
15
15
  "type": "registry:ui",
16
16
  "target": "components/base/NavigationMenu.tsx",
17
- "content": "import * as React from \"react\";\nimport * as NavigationMenuPrimitive from \"@radix-ui/react-navigation-menu\";\nimport { cva } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst NavigationMenu = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>\n>(({ className, children, ...props }, ref) => (\n <NavigationMenuPrimitive.Root\n ref={ref}\n className={cn(\n \"relative z-10 flex max-w-max flex-1 items-center justify-center\",\n className,\n )}\n {...props}>\n {children}\n <NavigationMenuViewport />\n </NavigationMenuPrimitive.Root>\n));\nNavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;\n\nconst NavigationMenuList = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>\n>(({ className, ...props }, ref) => (\n <NavigationMenuPrimitive.List\n ref={ref}\n className={cn(\n \"group flex flex-1 list-none items-center justify-center gap-1\",\n className,\n )}\n {...props}\n />\n));\nNavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;\n\nconst NavigationMenuItem = NavigationMenuPrimitive.Item;\n\nconst navigationMenuTriggerStyle = cva(\n \"group inline-flex h-10 w-max cursor-pointer items-center justify-center rounded bg-background px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-primary/15 hover:text-primary focus:bg-primary/15 focus:text-primary focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-secondary data-[state=open]:bg-secondary\",\n);\n\nconst NavigationMenuTrigger = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>\n>(({ className, children, onPointerMove, onPointerLeave, ...props }, ref) => (\n <NavigationMenuPrimitive.Trigger\n ref={ref}\n className={cn(navigationMenuTriggerStyle(), \"group\", className)}\n // Desactiva la apertura por hover para evitar el conflicto hover/click de\n // Radix (el menú se cerraba al reabrirlo tras un click). Queda controlado\n // por click y teclado. Radix omite su handler si el evento está prevenido.\n onPointerMove={(event) => {\n event.preventDefault();\n onPointerMove?.(event);\n }}\n onPointerLeave={(event) => {\n event.preventDefault();\n onPointerLeave?.(event);\n }}\n {...props}>\n {children}{\" \"}\n <svg\n className='relative top-px ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180'\n viewBox='0 0 24 24'\n fill='none'\n stroke='currentColor'\n strokeWidth='2'\n strokeLinecap='round'\n strokeLinejoin='round'\n aria-hidden='true'>\n <path d='m6 9 6 6 6-6' />\n </svg>\n </NavigationMenuPrimitive.Trigger>\n));\nNavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;\n\nconst NavigationMenuContent = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <NavigationMenuPrimitive.Content\n ref={ref}\n className={cn(\n \"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out md:absolute md:w-auto\",\n className,\n )}\n {...props}\n />\n));\nNavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;\n\nconst NavigationMenuLink = NavigationMenuPrimitive.Link;\n\nconst NavigationMenuViewport = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>\n>(({ className, ...props }, ref) => (\n <div className={cn(\"absolute left-0 top-full flex justify-center\")}>\n <NavigationMenuPrimitive.Viewport\n ref={ref}\n className={cn(\n \"origin-top-center relative mt-2 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded border border-border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]\",\n className,\n )}\n {...props}\n />\n </div>\n));\nNavigationMenuViewport.displayName =\n NavigationMenuPrimitive.Viewport.displayName;\n\nconst NavigationMenuIndicator = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>\n>(({ className, ...props }, ref) => (\n <NavigationMenuPrimitive.Indicator\n ref={ref}\n className={cn(\n \"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in\",\n className,\n )}\n {...props}>\n <div className='relative top-[60%] h-2 w-2 rotate-45 rounded-tl bg-border shadow-md' />\n </NavigationMenuPrimitive.Indicator>\n));\nNavigationMenuIndicator.displayName =\n NavigationMenuPrimitive.Indicator.displayName;\n\nexport {\n navigationMenuTriggerStyle,\n NavigationMenu,\n NavigationMenuList,\n NavigationMenuItem,\n NavigationMenuContent,\n NavigationMenuTrigger,\n NavigationMenuLink,\n NavigationMenuIndicator,\n NavigationMenuViewport,\n};\n"
17
+ "content": "import * as NavigationMenuPrimitive from \"@radix-ui/react-navigation-menu\";\nimport { cva } from \"class-variance-authority\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nconst NavigationMenu = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>\n>(({ className, children, ...props }, ref) => (\n <NavigationMenuPrimitive.Root\n ref={ref}\n className={cn(\"relative z-10 flex max-w-max flex-1 items-center justify-center\", className)}\n {...props}\n >\n {children}\n <NavigationMenuViewport />\n </NavigationMenuPrimitive.Root>\n));\nNavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;\n\nconst NavigationMenuList = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>\n>(({ className, ...props }, ref) => (\n <NavigationMenuPrimitive.List\n ref={ref}\n className={cn(\"group flex flex-1 list-none items-center justify-center gap-1\", className)}\n {...props}\n />\n));\nNavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;\n\nconst NavigationMenuItem = NavigationMenuPrimitive.Item;\n\nconst navigationMenuTriggerStyle = cva(\n \"group inline-flex h-10 w-max cursor-pointer items-center justify-center rounded bg-background px-4 py-2 text-sm font-medium text-foreground transition-colors hover:bg-primary/15 hover:text-primary focus:bg-primary/15 focus:text-primary focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-secondary data-[state=open]:bg-secondary\",\n);\n\nconst NavigationMenuTrigger = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>\n>(({ className, children, onPointerMove, onPointerLeave, ...props }, ref) => (\n <NavigationMenuPrimitive.Trigger\n ref={ref}\n className={cn(navigationMenuTriggerStyle(), \"group\", className)}\n // Desactiva la apertura por hover para evitar el conflicto hover/click de\n // Radix (el menú se cerraba al reabrirlo tras un click). Queda controlado\n // por click y teclado. Radix omite su handler si el evento está prevenido.\n onPointerMove={(event) => {\n event.preventDefault();\n onPointerMove?.(event);\n }}\n onPointerLeave={(event) => {\n event.preventDefault();\n onPointerLeave?.(event);\n }}\n {...props}\n >\n {children}{\" \"}\n <svg\n className=\"relative top-px ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n </NavigationMenuPrimitive.Trigger>\n));\nNavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;\n\nconst NavigationMenuContent = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <NavigationMenuPrimitive.Content\n ref={ref}\n className={cn(\n \"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out md:absolute md:w-auto\",\n className,\n )}\n {...props}\n />\n));\nNavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;\n\nconst NavigationMenuLink = NavigationMenuPrimitive.Link;\n\nconst NavigationMenuViewport = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>\n>(({ className, ...props }, ref) => (\n <div className={cn(\"absolute left-0 top-full flex justify-center\")}>\n <NavigationMenuPrimitive.Viewport\n ref={ref}\n className={cn(\n \"origin-top-center relative mt-2 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded border border-border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]\",\n className,\n )}\n {...props}\n />\n </div>\n));\nNavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName;\n\nconst NavigationMenuIndicator = React.forwardRef<\n React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,\n React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>\n>(({ className, ...props }, ref) => (\n <NavigationMenuPrimitive.Indicator\n ref={ref}\n className={cn(\n \"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in\",\n className,\n )}\n {...props}\n >\n <div className=\"relative top-[60%] h-2 w-2 rotate-45 rounded-tl bg-border shadow-md\" />\n </NavigationMenuPrimitive.Indicator>\n));\nNavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName;\n\nexport {\n NavigationMenu,\n NavigationMenuContent,\n NavigationMenuIndicator,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n NavigationMenuTrigger,\n navigationMenuTriggerStyle,\n NavigationMenuViewport,\n};\n"
18
18
  },
19
19
  {
20
20
  "path": "components/base/NavigationMenu.md",
@@ -16,7 +16,7 @@
16
16
  "path": "components/base/Pagination.tsx",
17
17
  "type": "registry:ui",
18
18
  "target": "components/base/Pagination.tsx",
19
- "content": "import * as React from \"react\";\n\nimport { type VariantProps } from \"class-variance-authority\";\nimport { cn } from \"@/lib/utils/cn\";\nimport { buttonVariants } from \"./Button\";\nimport { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon } from \"lucide-react\";\n\nfunction Pagination({ className, ...props }: React.ComponentProps<\"nav\">) {\n return (\n <nav\n role=\"navigation\"\n aria-label=\"pagination\"\n data-slot=\"pagination\"\n className={cn(\"mx-auto flex w-full justify-center\", className)}\n {...props}\n />\n );\n}\n\nfunction PaginationContent({\n className,\n ...props\n}: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"pagination-content\"\n className={cn(\"flex items-center gap-1\", className)}\n {...props}\n />\n );\n}\n\nfunction PaginationItem({ ...props }: React.ComponentProps<\"li\">) {\n return <li data-slot=\"pagination-item\" {...props} />;\n}\n\ntype PaginationLinkProps = {\n isActive?: boolean;\n} & Pick<VariantProps<typeof buttonVariants>, \"size\"> &\n Omit<React.ComponentProps<\"a\">, \"size\">;\n\nfunction PaginationLink({\n className,\n isActive,\n size = \"icon\",\n ...props\n}: PaginationLinkProps) {\n return (\n <a\n aria-current={isActive ? \"page\" : undefined}\n data-slot=\"pagination-link\"\n data-active={isActive}\n className={cn(\n buttonVariants({\n variant: isActive ? \"outline\" : \"ghost\",\n size,\n }),\n \"cursor-pointer\",\n className\n )}\n {...props}\n />\n );\n}\n\nfunction PaginationPrevious({\n className,\n text = \"Anterior\",\n ...props\n}: React.ComponentProps<typeof PaginationLink> & { text?: string }) {\n return (\n <PaginationLink\n aria-label=\"Ir a la página anterior\"\n size=\"default\"\n className={cn(\"pl-2!\", className)}\n {...props}\n >\n <ChevronLeftIcon data-icon=\"inline-start\" className=\"cn-rtl-flip\" />\n <span className=\"hidden sm:block\">{text}</span>\n </PaginationLink>\n );\n}\n\nfunction PaginationNext({\n className,\n text = \"Siguiente\",\n ...props\n}: React.ComponentProps<typeof PaginationLink> & { text?: string }) {\n return (\n <PaginationLink\n aria-label=\"Ir a la página siguiente\"\n size=\"default\"\n className={cn(\"pr-2!\", className)}\n {...props}\n >\n <span className=\"hidden sm:block\">{text}</span>\n <ChevronRightIcon data-icon=\"inline-end\" className=\"cn-rtl-flip\" />\n </PaginationLink>\n );\n}\n\nfunction PaginationEllipsis({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n aria-hidden\n data-slot=\"pagination-ellipsis\"\n className={cn(\n \"flex size-9 items-center justify-center [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <MoreHorizontalIcon />\n <span className=\"sr-only\">Más páginas</span>\n </span>\n );\n}\n\nexport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n};\n"
19
+ "content": "import { type VariantProps } from \"class-variance-authority\";\nimport { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils/cn\";\n\nimport { buttonVariants } from \"./Button\";\n\nfunction Pagination({ className, ...props }: React.ComponentProps<\"nav\">) {\n return (\n <nav\n role=\"navigation\"\n aria-label=\"pagination\"\n data-slot=\"pagination\"\n className={cn(\"mx-auto flex w-full justify-center\", className)}\n {...props}\n />\n );\n}\n\nfunction PaginationContent({ className, ...props }: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"pagination-content\"\n className={cn(\"flex items-center gap-1\", className)}\n {...props}\n />\n );\n}\n\nfunction PaginationItem({ ...props }: React.ComponentProps<\"li\">) {\n return <li data-slot=\"pagination-item\" {...props} />;\n}\n\ntype PaginationLinkProps = {\n isActive?: boolean;\n} & Pick<VariantProps<typeof buttonVariants>, \"size\"> &\n Omit<React.ComponentProps<\"a\">, \"size\">;\n\nfunction PaginationLink({ className, isActive, size = \"icon\", ...props }: PaginationLinkProps) {\n return (\n // eslint-disable-next-line jsx-a11y/anchor-has-content -- el contenido llega por {...props} (componente genérico de enlace)\n <a\n aria-current={isActive ? \"page\" : undefined}\n data-slot=\"pagination-link\"\n data-active={isActive}\n className={cn(\n buttonVariants({\n variant: isActive ? \"outline\" : \"ghost\",\n size,\n }),\n \"cursor-pointer\",\n className,\n )}\n {...props}\n />\n );\n}\n\nfunction PaginationPrevious({\n className,\n text = \"Anterior\",\n ...props\n}: React.ComponentProps<typeof PaginationLink> & { text?: string }) {\n return (\n <PaginationLink\n aria-label=\"Ir a la página anterior\"\n size=\"default\"\n className={cn(\"pl-2!\", className)}\n {...props}\n >\n <ChevronLeftIcon data-icon=\"inline-start\" className=\"cn-rtl-flip\" />\n <span className=\"hidden sm:block\">{text}</span>\n </PaginationLink>\n );\n}\n\nfunction PaginationNext({\n className,\n text = \"Siguiente\",\n ...props\n}: React.ComponentProps<typeof PaginationLink> & { text?: string }) {\n return (\n <PaginationLink\n aria-label=\"Ir a la página siguiente\"\n size=\"default\"\n className={cn(\"pr-2!\", className)}\n {...props}\n >\n <span className=\"hidden sm:block\">{text}</span>\n <ChevronRightIcon data-icon=\"inline-end\" className=\"cn-rtl-flip\" />\n </PaginationLink>\n );\n}\n\nfunction PaginationEllipsis({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n aria-hidden\n data-slot=\"pagination-ellipsis\"\n className={cn(\n \"flex size-9 items-center justify-center [&_svg:not([class*='size-'])]:size-4\",\n className,\n )}\n {...props}\n >\n <MoreHorizontalIcon />\n <span className=\"sr-only\">Más páginas</span>\n </span>\n );\n}\n\nexport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n};\n"
20
20
  },
21
21
  {
22
22
  "path": "components/base/Pagination.md",