ihms-ds 0.0.0-stage → 1.0.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 (82) hide show
  1. package/README.md +25 -2
  2. package/package.json +23 -4
  3. package/r/accordion.json +25 -0
  4. package/r/alert-dialog.json +25 -0
  5. package/r/alert.json +24 -0
  6. package/r/all.json +87 -0
  7. package/r/app-shell.json +27 -0
  8. package/r/aspect-ratio.json +23 -0
  9. package/r/attachment.json +26 -0
  10. package/r/avatar.json +24 -0
  11. package/r/badge.json +25 -0
  12. package/r/breadcrumb.json +25 -0
  13. package/r/bubble.json +25 -0
  14. package/r/button-group.json +26 -0
  15. package/r/button.json +25 -0
  16. package/r/calendar.json +26 -0
  17. package/r/card.json +23 -0
  18. package/r/carousel.json +26 -0
  19. package/r/chart.json +24 -0
  20. package/r/checkbox.json +25 -0
  21. package/r/collapsible.json +23 -0
  22. package/r/combobox.json +27 -0
  23. package/r/command.json +26 -0
  24. package/r/context-menu.json +25 -0
  25. package/r/copy-button.json +24 -0
  26. package/r/dialog.json +26 -0
  27. package/r/direction.json +23 -0
  28. package/r/drawer.json +24 -0
  29. package/r/dropdown-menu.json +25 -0
  30. package/r/empty.json +24 -0
  31. package/r/field.json +26 -0
  32. package/r/form.json +26 -0
  33. package/r/hover-card.json +24 -0
  34. package/r/input-group.json +27 -0
  35. package/r/input-otp.json +25 -0
  36. package/r/input.json +23 -0
  37. package/r/item.json +26 -0
  38. package/r/kbd.json +23 -0
  39. package/r/label.json +24 -0
  40. package/r/login-form.json +29 -0
  41. package/r/marker.json +25 -0
  42. package/r/menubar.json +25 -0
  43. package/r/message-scroller.json +26 -0
  44. package/r/message.json +23 -0
  45. package/r/money-input.json +22 -0
  46. package/r/money.json +18 -0
  47. package/r/native-select.json +24 -0
  48. package/r/navigation-menu.json +26 -0
  49. package/r/page-header.json +23 -0
  50. package/r/pagination.json +25 -0
  51. package/r/phone-input.json +25 -0
  52. package/r/phone.json +18 -0
  53. package/r/pix-copy.json +29 -0
  54. package/r/pix.json +18 -0
  55. package/r/popover.json +24 -0
  56. package/r/progress.json +24 -0
  57. package/r/radio-group.json +25 -0
  58. package/r/registry.json +1947 -0
  59. package/r/resizable.json +25 -0
  60. package/r/scroll-area.json +24 -0
  61. package/r/select.json +25 -0
  62. package/r/separator.json +24 -0
  63. package/r/sheet.json +25 -0
  64. package/r/sidebar.json +33 -0
  65. package/r/skeleton.json +23 -0
  66. package/r/slider.json +24 -0
  67. package/r/sonner.json +25 -0
  68. package/r/spinner.json +24 -0
  69. package/r/stat-card.json +24 -0
  70. package/r/switch.json +24 -0
  71. package/r/table.json +23 -0
  72. package/r/tabs.json +25 -0
  73. package/r/textarea.json +23 -0
  74. package/r/theme-toggle.json +25 -0
  75. package/r/theme.json +129 -0
  76. package/r/timeline.json +24 -0
  77. package/r/toggle-group.json +26 -0
  78. package/r/toggle.json +25 -0
  79. package/r/tooltip.json +24 -0
  80. package/r/use-mobile.json +18 -0
  81. package/r/whatsapp-button.json +25 -0
  82. package/r/whatsapp.json +18 -0
package/README.md CHANGED
@@ -1,3 +1,26 @@
1
- # Temporary Holding Version
1
+ # ihms-ds
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Registro do [shadcn](https://ui.shadcn.com) do design system **ihms**: os componentes do shadcn/ui (base Radix) customizados, neutros e em português, mais peças para produtos brasileiros (valor em reais, telefone, Pix, WhatsApp).
4
+
5
+ Este pacote **não é importado no código**. Ele só guarda os arquivos do registro, que o shadcn baixa pelo jsDelivr e **copia para o seu projeto**, onde o código fica editável.
6
+
7
+ ## Usar
8
+
9
+ No `components.json` do projeto (Next.js, Tailwind 4, shadcn na base Radix):
10
+
11
+ ```json
12
+ {
13
+ "registries": {
14
+ "@ihms": "https://cdn.jsdelivr.net/npm/ihms-ds@1/r/{name}.json"
15
+ }
16
+ }
17
+ ```
18
+
19
+ ```bash
20
+ npx shadcn add @ihms/button @ihms/money-input # o tema vem junto
21
+ npx shadcn add @ihms/all # tudo
22
+ ```
23
+
24
+ Para dar cor ao projeto, troque `--primary` no `globals.css` dele.
25
+
26
+ Documentação e código-fonte: [github.com/igorhms/design-system](https://github.com/igorhms/design-system).
package/package.json CHANGED
@@ -1,6 +1,25 @@
1
1
  {
2
2
  "name": "ihms-ds",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "Registro do shadcn do design system ihms: componentes shadcn/ui customizados em português, com peças para produtos brasileiros. Instale com npx shadcn add @ihms/<item>.",
5
+ "keywords": [
6
+ "shadcn",
7
+ "shadcn-registry",
8
+ "design-system",
9
+ "radix",
10
+ "tailwindcss",
11
+ "react",
12
+ "pt-br"
13
+ ],
14
+ "homepage": "https://github.com/igorhms/design-system",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/igorhms/design-system.git"
18
+ },
19
+ "author": "Igor Machado",
20
+ "license": "MIT",
21
+ "files": [
22
+ "r",
23
+ "README.md"
24
+ ]
25
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "accordion",
4
+ "title": "Accordion",
5
+ "description": "Seções que abrem e fecham, uma de cada vez ou várias.",
6
+ "dependencies": [
7
+ "cn@^0.5.0",
8
+ "lucide-react@^1.49.0",
9
+ "radix-ui@^1.8.1"
10
+ ],
11
+ "registryDependencies": [
12
+ "@ihms/theme"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "src/components/ui/accordion.tsx",
17
+ "content": "/**\n * @categoria Exibição\n * @descricao Seções que abrem e fecham, uma de cada vez ou várias.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cn } from \"cn\"\nimport { ChevronDownIcon } from \"lucide-react\"\nimport { Accordion as AccordionPrimitive } from \"radix-ui\"\n\nfunction Accordion({\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Root>) {\n return <AccordionPrimitive.Root data-slot=\"accordion\" {...props} />\n}\n\nfunction AccordionItem({\n className,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Item>) {\n return (\n <AccordionPrimitive.Item\n data-slot=\"accordion-item\"\n className={cn(\"border-b last:border-b-0\", className)}\n {...props}\n />\n )\n}\n\nfunction AccordionTrigger({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {\n return (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n data-slot=\"accordion-trigger\"\n className={cn(\n \"flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180\",\n className\n )}\n {...props}\n >\n {children}\n <ChevronDownIcon className=\"pointer-events-none size-4 shrink-0 translate-y-0.5 text-muted-foreground transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n )\n}\n\nfunction AccordionContent({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof AccordionPrimitive.Content>) {\n return (\n <AccordionPrimitive.Content\n data-slot=\"accordion-content\"\n className=\"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pt-0 pb-4\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n )\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent }\n",
18
+ "type": "registry:ui"
19
+ }
20
+ ],
21
+ "categories": [
22
+ "Exibição"
23
+ ],
24
+ "type": "registry:ui"
25
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "alert-dialog",
4
+ "title": "Alert Dialog",
5
+ "description": "Confirmação antes de uma ação que não dá para desfazer.",
6
+ "dependencies": [
7
+ "cn@^0.5.0",
8
+ "radix-ui@^1.8.1"
9
+ ],
10
+ "registryDependencies": [
11
+ "@ihms/theme",
12
+ "@ihms/button"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "src/components/ui/alert-dialog.tsx",
17
+ "content": "\"use client\"\n\n/**\n * @categoria Sobreposição\n * @descricao Confirmação antes de uma ação que não dá para desfazer.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cn } from \"cn\"\nimport { AlertDialog as AlertDialogPrimitive } from \"radix-ui\"\n\nimport { Button } from \"@/components/ui/button\"\n\nfunction AlertDialog({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {\n return <AlertDialogPrimitive.Root data-slot=\"alert-dialog\" {...props} />\n}\n\nfunction AlertDialogTrigger({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {\n return (\n <AlertDialogPrimitive.Trigger data-slot=\"alert-dialog-trigger\" {...props} />\n )\n}\n\nfunction AlertDialogPortal({\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {\n return (\n <AlertDialogPrimitive.Portal data-slot=\"alert-dialog-portal\" {...props} />\n )\n}\n\nfunction AlertDialogOverlay({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {\n return (\n <AlertDialogPrimitive.Overlay\n data-slot=\"alert-dialog-overlay\"\n className={cn(\n \"fixed inset-0 z-50 bg-black/50 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogContent({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Content> & {\n size?: \"default\" | \"sm\"\n}) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n data-slot=\"alert-dialog-content\"\n data-size={size}\n className={cn(\n \"group/alert-dialog-content fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 data-[size=sm]:max-w-xs data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[size=default]:sm:max-w-lg\",\n className\n )}\n {...props}\n />\n </AlertDialogPortal>\n )\n}\n\nfunction AlertDialogHeader({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-header\"\n className={cn(\n \"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogFooter({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-footer\"\n className={cn(\n \"flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogTitle({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {\n return (\n <AlertDialogPrimitive.Title\n data-slot=\"alert-dialog-title\"\n className={cn(\n \"text-lg font-semibold sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogDescription({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {\n return (\n <AlertDialogPrimitive.Description\n data-slot=\"alert-dialog-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogMedia({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-dialog-media\"\n className={cn(\n \"mb-2 inline-flex size-16 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-8\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDialogAction({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Action> &\n Pick<React.ComponentProps<typeof Button>, \"variant\" | \"size\">) {\n return (\n <Button variant={variant} size={size} asChild>\n <AlertDialogPrimitive.Action\n data-slot=\"alert-dialog-action\"\n className={cn(className)}\n {...props}\n />\n </Button>\n )\n}\n\nfunction AlertDialogCancel({\n className,\n variant = \"outline\",\n size = \"default\",\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> &\n Pick<React.ComponentProps<typeof Button>, \"variant\" | \"size\">) {\n return (\n <Button variant={variant} size={size} asChild>\n <AlertDialogPrimitive.Cancel\n data-slot=\"alert-dialog-cancel\"\n className={cn(className)}\n {...props}\n />\n </Button>\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogMedia,\n AlertDialogOverlay,\n AlertDialogPortal,\n AlertDialogTitle,\n AlertDialogTrigger,\n}\n",
18
+ "type": "registry:ui"
19
+ }
20
+ ],
21
+ "categories": [
22
+ "Sobreposição"
23
+ ],
24
+ "type": "registry:ui"
25
+ }
package/r/alert.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "alert",
4
+ "title": "Alert",
5
+ "description": "Aviso dentro da página, com tons de informação, sucesso, atenção e erro.",
6
+ "dependencies": [
7
+ "class-variance-authority@^0.7.1",
8
+ "cn@^0.5.0"
9
+ ],
10
+ "registryDependencies": [
11
+ "@ihms/theme"
12
+ ],
13
+ "files": [
14
+ {
15
+ "path": "src/components/ui/alert.tsx",
16
+ "content": "/**\n * @categoria Feedback\n * @descricao Aviso dentro da página, com tons de informação, sucesso, atenção e erro.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"cn\"\n\nconst alertVariants = cva(\n \"relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current\",\n {\n variants: {\n variant: {\n default: \"bg-card text-card-foreground\",\n destructive:\n \"bg-card text-destructive *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-current\",\n success:\n \"border-success/30 bg-success/8 text-success *:data-[slot=alert-description]:text-foreground/80\",\n warning:\n \"border-warning/35 bg-warning/10 text-warning *:data-[slot=alert-description]:text-foreground/80\",\n info: \"border-info/30 bg-info/8 text-info *:data-[slot=alert-description]:text-foreground/80\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Alert({\n className,\n variant,\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof alertVariants>) {\n return (\n <div\n data-slot=\"alert\"\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction AlertTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-title\"\n className={cn(\n \"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AlertDescription({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"alert-description\"\n className={cn(\n \"col-start-2 grid justify-items-start gap-1 text-sm text-muted-foreground [&_p]:leading-relaxed\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Alert, AlertTitle, AlertDescription }\n",
17
+ "type": "registry:ui"
18
+ }
19
+ ],
20
+ "categories": [
21
+ "Feedback"
22
+ ],
23
+ "type": "registry:ui"
24
+ }
package/r/all.json ADDED
@@ -0,0 +1,87 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "all",
4
+ "title": "Tudo",
5
+ "description": "Tema, todos os componentes, blocos e funções.",
6
+ "registryDependencies": [
7
+ "@ihms/theme",
8
+ "@ihms/accordion",
9
+ "@ihms/alert-dialog",
10
+ "@ihms/alert",
11
+ "@ihms/aspect-ratio",
12
+ "@ihms/attachment",
13
+ "@ihms/avatar",
14
+ "@ihms/badge",
15
+ "@ihms/breadcrumb",
16
+ "@ihms/bubble",
17
+ "@ihms/button-group",
18
+ "@ihms/button",
19
+ "@ihms/calendar",
20
+ "@ihms/card",
21
+ "@ihms/carousel",
22
+ "@ihms/chart",
23
+ "@ihms/checkbox",
24
+ "@ihms/collapsible",
25
+ "@ihms/combobox",
26
+ "@ihms/command",
27
+ "@ihms/context-menu",
28
+ "@ihms/copy-button",
29
+ "@ihms/dialog",
30
+ "@ihms/direction",
31
+ "@ihms/drawer",
32
+ "@ihms/dropdown-menu",
33
+ "@ihms/empty",
34
+ "@ihms/field",
35
+ "@ihms/form",
36
+ "@ihms/hover-card",
37
+ "@ihms/input-group",
38
+ "@ihms/input-otp",
39
+ "@ihms/input",
40
+ "@ihms/item",
41
+ "@ihms/kbd",
42
+ "@ihms/label",
43
+ "@ihms/marker",
44
+ "@ihms/menubar",
45
+ "@ihms/message-scroller",
46
+ "@ihms/message",
47
+ "@ihms/money-input",
48
+ "@ihms/native-select",
49
+ "@ihms/navigation-menu",
50
+ "@ihms/page-header",
51
+ "@ihms/pagination",
52
+ "@ihms/phone-input",
53
+ "@ihms/pix-copy",
54
+ "@ihms/popover",
55
+ "@ihms/progress",
56
+ "@ihms/radio-group",
57
+ "@ihms/resizable",
58
+ "@ihms/scroll-area",
59
+ "@ihms/select",
60
+ "@ihms/separator",
61
+ "@ihms/sheet",
62
+ "@ihms/sidebar",
63
+ "@ihms/skeleton",
64
+ "@ihms/slider",
65
+ "@ihms/sonner",
66
+ "@ihms/spinner",
67
+ "@ihms/stat-card",
68
+ "@ihms/switch",
69
+ "@ihms/table",
70
+ "@ihms/tabs",
71
+ "@ihms/textarea",
72
+ "@ihms/theme-toggle",
73
+ "@ihms/timeline",
74
+ "@ihms/toggle-group",
75
+ "@ihms/toggle",
76
+ "@ihms/tooltip",
77
+ "@ihms/whatsapp-button",
78
+ "@ihms/app-shell",
79
+ "@ihms/login-form",
80
+ "@ihms/money",
81
+ "@ihms/phone",
82
+ "@ihms/pix",
83
+ "@ihms/whatsapp",
84
+ "@ihms/use-mobile"
85
+ ],
86
+ "type": "registry:item"
87
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "app-shell",
4
+ "title": "App Shell",
5
+ "description": "Casca do app: menu lateral recolhível, topo e conteúdo.",
6
+ "dependencies": [
7
+ "lucide-react@^1.49.0"
8
+ ],
9
+ "registryDependencies": [
10
+ "@ihms/theme",
11
+ "@ihms/avatar",
12
+ "@ihms/dropdown-menu",
13
+ "@ihms/separator",
14
+ "@ihms/sidebar"
15
+ ],
16
+ "files": [
17
+ {
18
+ "path": "src/components/blocks/app-shell.tsx",
19
+ "content": "\"use client\"\n\n/**\n * @categoria Blocos\n * @descricao Casca do app: menu lateral recolhível, topo e conteúdo.\n */\nimport * as React from \"react\"\nimport { ChevronsUpDown, LogOut } from \"lucide-react\"\nimport { Avatar, AvatarFallback } from \"@/components/ui/avatar\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\"\nimport { Separator } from \"@/components/ui/separator\"\nimport {\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarGroup,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarInset,\n SidebarMenu,\n SidebarMenuBadge,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarProvider,\n SidebarRail,\n SidebarTrigger,\n} from \"@/components/ui/sidebar\"\n\nexport type AppShellNavItem = {\n title: string\n href: string\n icon?: React.ComponentType<{ className?: string }>\n isActive?: boolean\n /** Contador à direita do item (pendências, mensagens novas). */\n badge?: React.ReactNode\n}\n\nexport type AppShellNavGroup = { label?: string; items: AppShellNavItem[] }\n\ntype AppShellProps = {\n /** Marca no topo do menu: logo e nome do produto ou do estabelecimento. */\n brand: React.ReactNode\n nav: AppShellNavGroup[]\n user?: { name: string; detail?: string; onSignOut?: () => void }\n /** Conteúdo do topo, ao lado do botão do menu: breadcrumb, busca, ações. */\n header?: React.ReactNode\n children: React.ReactNode\n}\n\n/**\n * Casca do app: menu lateral recolhível (vira gaveta no celular), topo fixo e área de conteúdo.\n * Os links são <a>; num projeto Next, troque por <Link> de \"next/link\" aqui mesmo, no arquivo copiado.\n */\nexport function AppShell({\n brand,\n nav,\n user,\n header,\n children,\n}: AppShellProps) {\n return (\n <SidebarProvider>\n <Sidebar collapsible=\"icon\">\n <SidebarHeader className=\"h-14 justify-center border-b border-sidebar-border px-3\">\n {brand}\n </SidebarHeader>\n <SidebarContent>\n {nav.map((group, i) => (\n <SidebarGroup key={group.label ?? i}>\n {group.label && (\n <SidebarGroupLabel>{group.label}</SidebarGroupLabel>\n )}\n <SidebarGroupContent>\n <SidebarMenu>\n {group.items.map((item) => (\n <SidebarMenuItem key={item.href}>\n <SidebarMenuButton\n asChild\n isActive={item.isActive}\n tooltip={item.title}\n >\n <a\n href={item.href}\n aria-current={item.isActive ? \"page\" : undefined}\n >\n {item.icon && <item.icon />}\n <span>{item.title}</span>\n </a>\n </SidebarMenuButton>\n {item.badge != null && (\n <SidebarMenuBadge className=\"tnum\">\n {item.badge}\n </SidebarMenuBadge>\n )}\n </SidebarMenuItem>\n ))}\n </SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n ))}\n </SidebarContent>\n {user && (\n <SidebarFooter className=\"border-t border-sidebar-border\">\n <SidebarMenu>\n <SidebarMenuItem>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton\n size=\"lg\"\n className=\"data-[state=open]:bg-sidebar-accent\"\n >\n <Avatar className=\"size-8 rounded-md\">\n <AvatarFallback className=\"rounded-md text-xs font-semibold\">\n {initials(user.name)}\n </AvatarFallback>\n </Avatar>\n <span className=\"grid flex-1 text-left leading-tight\">\n <span className=\"truncate text-sm font-medium\">\n {user.name}\n </span>\n {user.detail && (\n <span className=\"truncate text-xs text-muted-foreground\">\n {user.detail}\n </span>\n )}\n </span>\n <ChevronsUpDown className=\"ml-auto size-4\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent\n side=\"top\"\n align=\"start\"\n className=\"w-(--radix-dropdown-menu-trigger-width) min-w-52\"\n >\n <DropdownMenuLabel className=\"font-normal\">\n <span className=\"block text-sm font-medium\">\n {user.name}\n </span>\n {user.detail && (\n <span className=\"block text-xs text-muted-foreground\">\n {user.detail}\n </span>\n )}\n </DropdownMenuLabel>\n {user.onSignOut && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem onSelect={user.onSignOut}>\n <LogOut />\n Sair\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </SidebarMenuItem>\n </SidebarMenu>\n </SidebarFooter>\n )}\n <SidebarRail />\n </Sidebar>\n <SidebarInset>\n <header className=\"sticky top-0 z-10 flex h-14 shrink-0 items-center gap-2 border-b bg-background/95 px-4 backdrop-blur supports-[backdrop-filter]:bg-background/80\">\n <SidebarTrigger className=\"-ml-1\" />\n {header && (\n <>\n <Separator\n orientation=\"vertical\"\n className=\"mr-1 data-[orientation=vertical]:h-4\"\n />\n <div className=\"flex min-w-0 flex-1 items-center gap-2\">\n {header}\n </div>\n </>\n )}\n </header>\n <div className=\"flex-1 p-4 md:p-6\">{children}</div>\n </SidebarInset>\n </SidebarProvider>\n )\n}\n\nfunction initials(name: string) {\n const parts = name.trim().split(/\\s+/)\n return (\n (parts[0]?.[0] ?? \"\") + (parts.length > 1 ? parts[parts.length - 1][0] : \"\")\n ).toUpperCase()\n}\n",
20
+ "type": "registry:component"
21
+ }
22
+ ],
23
+ "categories": [
24
+ "Blocos"
25
+ ],
26
+ "type": "registry:block"
27
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "aspect-ratio",
4
+ "title": "Aspect Ratio",
5
+ "description": "Mantém a proporção de imagens e vídeos.",
6
+ "dependencies": [
7
+ "radix-ui@^1.8.1"
8
+ ],
9
+ "registryDependencies": [
10
+ "@ihms/theme"
11
+ ],
12
+ "files": [
13
+ {
14
+ "path": "src/components/ui/aspect-ratio.tsx",
15
+ "content": "\"use client\"\n\n/**\n * @categoria Layout\n * @descricao Mantém a proporção de imagens e vídeos.\n * @shadcn\n */\nimport { AspectRatio as AspectRatioPrimitive } from \"radix-ui\"\n\nfunction AspectRatio({\n ...props\n}: React.ComponentProps<typeof AspectRatioPrimitive.Root>) {\n return <AspectRatioPrimitive.Root data-slot=\"aspect-ratio\" {...props} />\n}\n\nexport { AspectRatio }\n",
16
+ "type": "registry:ui"
17
+ }
18
+ ],
19
+ "categories": [
20
+ "Layout"
21
+ ],
22
+ "type": "registry:ui"
23
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "attachment",
4
+ "title": "Attachment",
5
+ "description": "Arquivo anexado, com estado de envio, erro e ações.",
6
+ "dependencies": [
7
+ "class-variance-authority@^0.7.1",
8
+ "cn@^0.5.0",
9
+ "radix-ui@^1.8.1"
10
+ ],
11
+ "registryDependencies": [
12
+ "@ihms/theme",
13
+ "@ihms/button"
14
+ ],
15
+ "files": [
16
+ {
17
+ "path": "src/components/ui/attachment.tsx",
18
+ "content": "/**\n * @categoria Conversa\n * @descricao Arquivo anexado, com estado de envio, erro e ações.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"cn\"\nimport { Slot } from \"radix-ui\"\n\nimport { Button } from \"@/components/ui/button\"\n\nconst attachmentVariants = cva(\n \"group/attachment relative flex w-fit max-w-full min-w-0 shrink-0 flex-wrap rounded-xl border bg-card text-card-foreground transition-colors focus-within:ring-1 focus-within:ring-ring/50 has-[>a,>button]:hover:bg-muted/50 data-[state=error]:border-destructive/30 data-[state=idle]:border-dashed\",\n {\n variants: {\n size: {\n default:\n \"gap-2 text-sm has-data-[slot=attachment-content]:px-2.5 has-data-[slot=attachment-content]:py-2 has-data-[slot=attachment-media]:p-2\",\n sm: \"gap-2.5 text-xs has-data-[slot=attachment-content]:px-2 has-data-[slot=attachment-content]:py-1.5 has-data-[slot=attachment-media]:p-1.5\",\n xs: \"gap-1.5 rounded-lg text-xs has-data-[slot=attachment-content]:px-1.5 has-data-[slot=attachment-content]:py-1 has-data-[slot=attachment-media]:p-1\",\n },\n orientation: {\n horizontal: \"min-w-40 items-center\",\n vertical: \"w-24 flex-col has-data-[slot=attachment-content]:w-30\",\n },\n },\n }\n)\n\nfunction Attachment({\n className,\n state = \"done\",\n size = \"default\",\n orientation = \"horizontal\",\n ...props\n}: React.ComponentProps<\"div\"> &\n VariantProps<typeof attachmentVariants> & {\n state?: \"idle\" | \"uploading\" | \"processing\" | \"error\" | \"done\"\n }) {\n return (\n <div\n data-slot=\"attachment\"\n data-state={state}\n data-size={size}\n data-orientation={orientation}\n className={cn(attachmentVariants({ size, orientation }), className)}\n {...props}\n />\n )\n}\n\nconst attachmentMediaVariants = cva(\n \"relative flex aspect-square w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted text-foreground group-data-[orientation=vertical]/attachment:w-full group-data-[size=sm]/attachment:w-8 group-data-[size=xs]/attachment:w-7 group-data-[size=xs]/attachment:rounded-md group-data-[state=error]/attachment:bg-destructive/10 group-data-[state=error]/attachment:text-destructive group-data-[orientation=vertical]/attachment:*:data-[slot=spinner]:size-6! [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 group-data-[orientation=vertical]/attachment:[&_svg:not([class*='size-'])]:size-6 group-data-[size=xs]/attachment:[&_svg:not([class*='size-'])]:size-3.5\",\n {\n variants: {\n variant: {\n icon: \"\",\n image:\n \"opacity-60 group-data-[state=done]/attachment:opacity-100 group-data-[state=idle]/attachment:opacity-100 *:[img]:aspect-square *:[img]:w-full *:[img]:object-cover\",\n },\n },\n defaultVariants: {\n variant: \"icon\",\n },\n }\n)\n\nfunction AttachmentMedia({\n className,\n variant = \"icon\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof attachmentMediaVariants>) {\n return (\n <div\n data-slot=\"attachment-media\"\n data-variant={variant}\n className={cn(attachmentMediaVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction AttachmentContent({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"attachment-content\"\n className={cn(\n \"max-w-full min-w-0 flex-1 leading-tight group-data-[orientation=vertical]/attachment:px-1\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AttachmentTitle({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"attachment-title\"\n className={cn(\n \"group-data-[state=processing]/attachment:shimmer group-data-[state=uploading]/attachment:shimmer block max-w-full min-w-0 truncate font-medium\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AttachmentDescription({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"attachment-description\"\n className={cn(\n \"mt-0.5 block min-w-0 truncate text-xs text-muted-foreground group-data-[state=error]/attachment:text-destructive\",\n \"max-w-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AttachmentActions({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"attachment-actions\"\n className={cn(\n \"relative z-20 flex shrink-0 items-center group-data-[orientation=vertical]/attachment:absolute group-data-[orientation=vertical]/attachment:top-3 group-data-[orientation=vertical]/attachment:right-3 group-data-[orientation=vertical]/attachment:gap-1\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AttachmentAction({\n className,\n variant,\n size = \"icon-xs\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n return (\n <Button\n data-slot=\"attachment-action\"\n variant={variant ?? \"ghost\"}\n size={size}\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction AttachmentTrigger({\n className,\n asChild = false,\n type,\n ...props\n}: React.ComponentProps<\"button\"> & {\n asChild?: boolean\n}) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"attachment-trigger\"\n type={asChild ? undefined : (type ?? \"button\")}\n className={cn(\"absolute inset-0 z-10 outline-none\", className)}\n {...props}\n />\n )\n}\n\nfunction AttachmentGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"attachment-group\"\n className={cn(\n \"scroll-fade-x flex min-w-0 snap-x snap-mandatory scroll-px-1 scrollbar-none gap-3 overflow-x-auto overscroll-x-contain py-1 *:data-[slot=attachment]:flex-none *:data-[slot=attachment]:snap-start\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Attachment,\n AttachmentGroup,\n AttachmentMedia,\n AttachmentContent,\n AttachmentTitle,\n AttachmentDescription,\n AttachmentActions,\n AttachmentAction,\n AttachmentTrigger,\n}\n",
19
+ "type": "registry:ui"
20
+ }
21
+ ],
22
+ "categories": [
23
+ "Conversa"
24
+ ],
25
+ "type": "registry:ui"
26
+ }
package/r/avatar.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "avatar",
4
+ "title": "Avatar",
5
+ "description": "Foto ou iniciais de uma pessoa, sozinha ou em grupo.",
6
+ "dependencies": [
7
+ "cn@^0.5.0",
8
+ "radix-ui@^1.8.1"
9
+ ],
10
+ "registryDependencies": [
11
+ "@ihms/theme"
12
+ ],
13
+ "files": [
14
+ {
15
+ "path": "src/components/ui/avatar.tsx",
16
+ "content": "/**\n * @categoria Exibição\n * @descricao Foto ou iniciais de uma pessoa, sozinha ou em grupo.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cn } from \"cn\"\nimport { Avatar as AvatarPrimitive } from \"radix-ui\"\n\nfunction Avatar({\n className,\n size = \"default\",\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root> & {\n size?: \"default\" | \"sm\" | \"lg\"\n}) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n data-size={size}\n className={cn(\n \"group/avatar relative flex size-8 shrink-0 overflow-hidden rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Image>) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\"aspect-square size-full\", className)}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarBadge({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"avatar-badge\"\n className={cn(\n \"absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground ring-2 ring-background select-none\",\n \"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden\",\n \"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2\",\n \"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"avatar-group\"\n className={cn(\n \"group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarGroupCount({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"avatar-group-count\"\n className={cn(\n \"relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Avatar,\n AvatarImage,\n AvatarFallback,\n AvatarBadge,\n AvatarGroup,\n AvatarGroupCount,\n}\n",
17
+ "type": "registry:ui"
18
+ }
19
+ ],
20
+ "categories": [
21
+ "Exibição"
22
+ ],
23
+ "type": "registry:ui"
24
+ }
package/r/badge.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "badge",
4
+ "title": "Badge",
5
+ "description": "Selo curto para status e contagens.",
6
+ "dependencies": [
7
+ "class-variance-authority@^0.7.1",
8
+ "cn@^0.5.0",
9
+ "radix-ui@^1.8.1"
10
+ ],
11
+ "registryDependencies": [
12
+ "@ihms/theme"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "src/components/ui/badge.tsx",
17
+ "content": "/**\n * @categoria Exibição\n * @descricao Selo curto para status e contagens.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"cn\"\nimport { Slot } from \"radix-ui\"\n\nconst badgeVariants = cva(\n \"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-md border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90\",\n outline:\n \"border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n ghost: \"[a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 [a&]:hover:underline\",\n // Tons de status: fundo suave e texto na cor do status, legíveis nos dois temas.\n neutral: \"border-border bg-muted text-muted-foreground\",\n success: \"bg-success/12 text-success\",\n warning: \"bg-warning/14 text-warning\",\n info: \"bg-info/12 text-info\",\n danger: \"bg-destructive/12 text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot.Root : \"span\"\n\n return (\n <Comp\n data-slot=\"badge\"\n data-variant={variant}\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport { Badge, badgeVariants }\n",
18
+ "type": "registry:ui"
19
+ }
20
+ ],
21
+ "categories": [
22
+ "Exibição"
23
+ ],
24
+ "type": "registry:ui"
25
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "breadcrumb",
4
+ "title": "Breadcrumb",
5
+ "description": "Caminho até a página atual.",
6
+ "dependencies": [
7
+ "cn@^0.5.0",
8
+ "lucide-react@^1.49.0",
9
+ "radix-ui@^1.8.1"
10
+ ],
11
+ "registryDependencies": [
12
+ "@ihms/theme"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "src/components/ui/breadcrumb.tsx",
17
+ "content": "/**\n * @categoria Navegação\n * @descricao Caminho até a página atual.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cn } from \"cn\"\nimport { ChevronRight, MoreHorizontal } from \"lucide-react\"\nimport { Slot } from \"radix-ui\"\n\nfunction Breadcrumb({ ...props }: React.ComponentProps<\"nav\">) {\n return <nav aria-label=\"Caminho\" data-slot=\"breadcrumb\" {...props} />\n}\n\nfunction BreadcrumbList({ className, ...props }: React.ComponentProps<\"ol\">) {\n return (\n <ol\n data-slot=\"breadcrumb-list\"\n className={cn(\n \"flex flex-wrap items-center gap-1.5 text-sm break-words text-muted-foreground sm:gap-2.5\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-item\"\n className={cn(\"inline-flex items-center gap-1.5\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbLink({\n asChild,\n className,\n ...props\n}: React.ComponentProps<\"a\"> & {\n asChild?: boolean\n}) {\n const Comp = asChild ? Slot.Root : \"a\"\n\n return (\n <Comp\n data-slot=\"breadcrumb-link\"\n className={cn(\"transition-colors hover:text-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbPage({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-page\"\n role=\"link\"\n aria-disabled=\"true\"\n aria-current=\"page\"\n className={cn(\"font-normal text-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction BreadcrumbSeparator({\n children,\n className,\n ...props\n}: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"breadcrumb-separator\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"[&>svg]:size-3.5\", className)}\n {...props}\n >\n {children ?? <ChevronRight />}\n </li>\n )\n}\n\nfunction BreadcrumbEllipsis({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"breadcrumb-ellipsis\"\n role=\"presentation\"\n aria-hidden=\"true\"\n className={cn(\"flex size-9 items-center justify-center\", className)}\n {...props}\n >\n <MoreHorizontal className=\"size-4\" />\n <span className=\"sr-only\">Mais</span>\n </span>\n )\n}\n\nexport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n}\n",
18
+ "type": "registry:ui"
19
+ }
20
+ ],
21
+ "categories": [
22
+ "Navegação"
23
+ ],
24
+ "type": "registry:ui"
25
+ }
package/r/bubble.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "bubble",
4
+ "title": "Bubble",
5
+ "description": "Balão de mensagem de uma conversa.",
6
+ "dependencies": [
7
+ "class-variance-authority@^0.7.1",
8
+ "cn@^0.5.0",
9
+ "radix-ui@^1.8.1"
10
+ ],
11
+ "registryDependencies": [
12
+ "@ihms/theme"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "src/components/ui/bubble.tsx",
17
+ "content": "/**\n * @categoria Conversa\n * @descricao Balão de mensagem de uma conversa.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"cn\"\nimport { Slot } from \"radix-ui\"\n\nfunction BubbleGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"bubble-group\"\n className={cn(\"flex min-w-0 flex-col gap-2\", className)}\n {...props}\n />\n )\n}\n\nconst bubbleVariants = cva(\n \"group/bubble relative flex w-fit max-w-[80%] min-w-0 flex-col gap-1 group-data-[align=end]/message:self-end data-[align=end]:self-end data-[variant=ghost]:max-w-full\",\n {\n variants: {\n variant: {\n default:\n \"*:data-[slot=bubble-content]:bg-primary *:data-[slot=bubble-content]:text-primary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-primary/80\",\n secondary:\n \"*:data-[slot=bubble-content]:bg-secondary *:data-[slot=bubble-content]:text-secondary-foreground [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]\",\n muted:\n \"*:data-[slot=bubble-content]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[color-mix(in_oklch,var(--muted),var(--foreground)_5%)]\",\n tinted:\n \"*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.93_calc(c*0.4)_h)] *:data-[slot=bubble-content]:text-foreground dark:*:data-[slot=bubble-content]:bg-[oklch(from_var(--primary)_0.3_calc(c*0.4)_h)] [&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.88_calc(c*0.5)_h)] dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-[oklch(from_var(--primary)_0.35_calc(c*0.5)_h)]\",\n outline:\n \"*:data-[slot=bubble-content]:border-border *:data-[slot=bubble-content]:bg-background [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-input/30\",\n ghost:\n \"border-none *:data-[slot=bubble-content]:rounded-none *:data-[slot=bubble-content]:bg-transparent *:data-[slot=bubble-content]:p-0 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted [&>[data-slot=bubble-content]:is(button,a):hover]:text-foreground dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-muted/50\",\n destructive:\n \"*:data-[slot=bubble-content]:bg-destructive/10 *:data-[slot=bubble-content]:text-destructive dark:*:data-[slot=bubble-content]:bg-destructive/20 [&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/20 dark:[&>[data-slot=bubble-content]:is(button,a):hover]:bg-destructive/30\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Bubble({\n variant = \"default\",\n align = \"start\",\n className,\n ...props\n}: React.ComponentProps<\"div\"> &\n VariantProps<typeof bubbleVariants> & {\n align?: \"start\" | \"end\"\n }) {\n return (\n <div\n data-slot=\"bubble\"\n data-variant={variant}\n data-align={align}\n className={cn(bubbleVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nfunction BubbleContent({\n asChild = false,\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n asChild?: boolean\n}) {\n const Comp = asChild ? Slot.Root : \"div\"\n\n return (\n <Comp\n data-slot=\"bubble-content\"\n className={cn(\n \"w-fit max-w-full min-w-0 overflow-hidden rounded-xl border border-transparent px-3 py-2 text-sm leading-relaxed wrap-break-word group-data-[align=end]/bubble:self-end [button]:text-left [button,a]:transition-colors [button,a]:outline-none [button,a]:focus-visible:border-ring [button,a]:focus-visible:ring-3 [button,a]:focus-visible:ring-ring/50\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst bubbleReactionsVariants = cva(\n \"absolute z-10 flex w-fit shrink-0 items-center justify-center gap-1 rounded-full bg-muted px-1.5 py-0.5 text-sm ring-3 ring-card has-[button]:p-0\",\n {\n variants: {\n side: {\n top: \"top-0 -translate-y-3/4\",\n bottom: \"bottom-0 translate-y-3/4\",\n },\n align: {\n start: \"left-3\",\n end: \"right-3\",\n },\n },\n defaultVariants: {\n side: \"bottom\",\n align: \"end\",\n },\n }\n)\n\nfunction BubbleReactions({\n side = \"bottom\",\n align = \"end\",\n className,\n ...props\n}: React.ComponentProps<\"div\"> & {\n align?: \"start\" | \"end\"\n side?: \"top\" | \"bottom\"\n}) {\n return (\n <div\n data-slot=\"bubble-reactions\"\n data-align={align}\n data-side={side}\n className={cn(bubbleReactionsVariants({ side, align }), className)}\n {...props}\n />\n )\n}\n\nexport { BubbleGroup, Bubble, BubbleContent, BubbleReactions }\n",
18
+ "type": "registry:ui"
19
+ }
20
+ ],
21
+ "categories": [
22
+ "Conversa"
23
+ ],
24
+ "type": "registry:ui"
25
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "button-group",
4
+ "title": "Button Group",
5
+ "description": "Botões e campos encostados, como um controle só.",
6
+ "dependencies": [
7
+ "class-variance-authority@^0.7.1",
8
+ "cn@^0.5.0",
9
+ "radix-ui@^1.8.1"
10
+ ],
11
+ "registryDependencies": [
12
+ "@ihms/theme",
13
+ "@ihms/separator"
14
+ ],
15
+ "files": [
16
+ {
17
+ "path": "src/components/ui/button-group.tsx",
18
+ "content": "/**\n * @categoria Ações\n * @descricao Botões e campos encostados, como um controle só.\n * @shadcn\n */\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"cn\"\nimport { Slot } from \"radix-ui\"\n\nimport { Separator } from \"@/components/ui/separator\"\n\nconst buttonGroupVariants = cva(\n \"flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1\",\n {\n variants: {\n orientation: {\n horizontal:\n \"[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none\",\n vertical:\n \"flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none\",\n },\n },\n defaultVariants: {\n orientation: \"horizontal\",\n },\n }\n)\n\nfunction ButtonGroup({\n className,\n orientation,\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof buttonGroupVariants>) {\n return (\n <div\n role=\"group\"\n data-slot=\"button-group\"\n data-orientation={orientation}\n className={cn(buttonGroupVariants({ orientation }), className)}\n {...props}\n />\n )\n}\n\nfunction ButtonGroupText({\n className,\n asChild = false,\n ...props\n}: React.ComponentProps<\"div\"> & {\n asChild?: boolean\n}) {\n const Comp = asChild ? Slot.Root : \"div\"\n\n return (\n <Comp\n className={cn(\n \"flex items-center gap-2 rounded-md border bg-muted px-4 text-sm font-medium shadow-xs [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction ButtonGroupSeparator({\n className,\n orientation = \"vertical\",\n ...props\n}: React.ComponentProps<typeof Separator>) {\n return (\n <Separator\n data-slot=\"button-group-separator\"\n orientation={orientation}\n className={cn(\n \"relative m-0! self-stretch bg-input data-[orientation=vertical]:h-auto\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n ButtonGroup,\n ButtonGroupSeparator,\n ButtonGroupText,\n buttonGroupVariants,\n}\n",
19
+ "type": "registry:ui"
20
+ }
21
+ ],
22
+ "categories": [
23
+ "Ações"
24
+ ],
25
+ "type": "registry:ui"
26
+ }
package/r/button.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "button",
4
+ "title": "Button",
5
+ "description": "Botão de ação, com variantes e tamanhos para toque.",
6
+ "dependencies": [
7
+ "class-variance-authority@^0.7.1",
8
+ "cn@^0.5.0",
9
+ "radix-ui@^1.8.1"
10
+ ],
11
+ "registryDependencies": [
12
+ "@ihms/theme"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "src/components/ui/button.tsx",
17
+ "content": "/**\n * @categoria Ações\n * @descricao Botão de ação, com variantes e tamanhos para toque.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { cn } from \"cn\"\nimport { Slot } from \"radix-ui\"\n\nconst buttonVariants = cva(\n \"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n xs: \"h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 rounded-md [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n // Alvo de toque de 44px, para telas usadas de pé, no balcão ou no celular.\n touch: \"h-11 gap-2 px-4 text-[15px] has-[>svg]:px-3.5\",\n // Ação principal de uma tela operacional (o botão grande do funcionário).\n xl: \"h-12 gap-2 rounded-lg px-6 text-base font-semibold has-[>svg]:px-5 [&_svg:not([class*='size-'])]:size-5\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n asChild = false,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n asChild?: boolean\n }) {\n const Comp = asChild ? Slot.Root : \"button\"\n\n return (\n <Comp\n data-slot=\"button\"\n data-variant={variant}\n data-size={size}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n",
18
+ "type": "registry:ui"
19
+ }
20
+ ],
21
+ "categories": [
22
+ "Ações"
23
+ ],
24
+ "type": "registry:ui"
25
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "calendar",
4
+ "title": "Calendar",
5
+ "description": "Calendário para escolher data ou período.",
6
+ "dependencies": [
7
+ "cn@^0.5.0",
8
+ "lucide-react@^1.49.0",
9
+ "react-day-picker@^10.0.2"
10
+ ],
11
+ "registryDependencies": [
12
+ "@ihms/theme",
13
+ "@ihms/button"
14
+ ],
15
+ "files": [
16
+ {
17
+ "path": "src/components/ui/calendar.tsx",
18
+ "content": "/**\n * @categoria Formulário\n * @descricao Calendário para escolher data ou período.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cn } from \"cn\"\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from \"lucide-react\"\nimport {\n DayPicker,\n getDefaultClassNames,\n type DayButton,\n} from \"react-day-picker\"\n\nimport { Button, buttonVariants } from \"@/components/ui/button\"\n\nfunction Calendar({\n className,\n classNames,\n showOutsideDays = true,\n captionLayout = \"label\",\n buttonVariant = \"ghost\",\n formatters,\n components,\n ...props\n}: React.ComponentProps<typeof DayPicker> & {\n buttonVariant?: React.ComponentProps<typeof Button>[\"variant\"]\n}) {\n const defaultClassNames = getDefaultClassNames()\n\n return (\n <DayPicker\n showOutsideDays={showOutsideDays}\n className={cn(\n \"group/calendar bg-background p-3 [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent\",\n String.raw`rtl:**:[.rdp-button\\_next>svg]:rotate-180`,\n String.raw`rtl:**:[.rdp-button\\_previous>svg]:rotate-180`,\n className\n )}\n captionLayout={captionLayout}\n formatters={{\n formatMonthDropdown: (date) =>\n date.toLocaleString(\"default\", { month: \"short\" }),\n ...formatters,\n }}\n classNames={{\n root: cn(\"w-fit\", defaultClassNames.root),\n months: cn(\n \"relative flex flex-col gap-4 md:flex-row\",\n defaultClassNames.months\n ),\n month: cn(\"flex w-full flex-col gap-4\", defaultClassNames.month),\n nav: cn(\n \"absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1\",\n defaultClassNames.nav\n ),\n button_previous: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) p-0 select-none aria-disabled:opacity-50\",\n defaultClassNames.button_previous\n ),\n button_next: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) p-0 select-none aria-disabled:opacity-50\",\n defaultClassNames.button_next\n ),\n month_caption: cn(\n \"flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)\",\n defaultClassNames.month_caption\n ),\n dropdowns: cn(\n \"flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium\",\n defaultClassNames.dropdowns\n ),\n dropdown_root: cn(\n \"relative rounded-md border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50\",\n defaultClassNames.dropdown_root\n ),\n dropdown: cn(\n \"absolute inset-0 bg-popover opacity-0\",\n defaultClassNames.dropdown\n ),\n caption_label: cn(\n \"font-medium select-none\",\n captionLayout === \"label\"\n ? \"text-sm\"\n : \"flex h-8 items-center gap-1 rounded-md pr-1 pl-2 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground\",\n defaultClassNames.caption_label\n ),\n month_grid: cn(\"w-full border-collapse\", defaultClassNames.month_grid),\n weekdays: cn(\"flex\", defaultClassNames.weekdays),\n weekday: cn(\n \"flex-1 rounded-md text-[0.8rem] font-normal text-muted-foreground select-none\",\n defaultClassNames.weekday\n ),\n week: cn(\"mt-2 flex w-full\", defaultClassNames.week),\n week_number_header: cn(\n \"w-(--cell-size) select-none\",\n defaultClassNames.week_number_header\n ),\n week_number: cn(\n \"text-[0.8rem] text-muted-foreground select-none\",\n defaultClassNames.week_number\n ),\n day: cn(\n \"group/day relative aspect-square h-full w-full p-0 text-center select-none [&:last-child[data-selected=true]_button]:rounded-r-md\",\n props.showWeekNumber\n ? \"[&:nth-child(2)[data-selected=true]_button]:rounded-l-md\"\n : \"[&:first-child[data-selected=true]_button]:rounded-l-md\",\n defaultClassNames.day\n ),\n range_start: cn(\n \"rounded-l-md bg-accent\",\n defaultClassNames.range_start\n ),\n range_middle: cn(\"rounded-none\", defaultClassNames.range_middle),\n range_end: cn(\"rounded-r-md bg-accent\", defaultClassNames.range_end),\n today: cn(\n \"rounded-md bg-accent text-accent-foreground data-[selected=true]:rounded-none\",\n defaultClassNames.today\n ),\n outside: cn(\n \"text-muted-foreground aria-selected:text-muted-foreground\",\n defaultClassNames.outside\n ),\n disabled: cn(\n \"text-muted-foreground opacity-50\",\n defaultClassNames.disabled\n ),\n hidden: cn(\"invisible\", defaultClassNames.hidden),\n ...classNames,\n }}\n components={{\n Root: ({ className, rootRef, ...props }) => {\n return (\n <div\n data-slot=\"calendar\"\n ref={rootRef}\n className={cn(className)}\n {...props}\n />\n )\n },\n Chevron: ({ className, orientation, ...props }) => {\n if (orientation === \"left\") {\n return (\n <ChevronLeftIcon className={cn(\"size-4\", className)} {...props} />\n )\n }\n\n if (orientation === \"right\") {\n return (\n <ChevronRightIcon\n className={cn(\"size-4\", className)}\n {...props}\n />\n )\n }\n\n return (\n <ChevronDownIcon className={cn(\"size-4\", className)} {...props} />\n )\n },\n DayButton: CalendarDayButton,\n WeekNumber: ({ children, ...props }) => {\n return (\n <td {...props}>\n <div className=\"flex size-(--cell-size) items-center justify-center text-center\">\n {children}\n </div>\n </td>\n )\n },\n ...components,\n }}\n {...props}\n />\n )\n}\n\nfunction CalendarDayButton({\n className,\n day,\n modifiers,\n ...props\n}: React.ComponentProps<typeof DayButton>) {\n const defaultClassNames = getDefaultClassNames()\n\n const ref = React.useRef<HTMLButtonElement>(null)\n React.useEffect(() => {\n if (modifiers.focused) ref.current?.focus()\n }, [modifiers.focused])\n\n return (\n <Button\n ref={ref}\n variant=\"ghost\"\n size=\"icon\"\n data-day={day.date.toLocaleDateString()}\n data-selected-single={\n modifiers.selected &&\n !modifiers.range_start &&\n !modifiers.range_end &&\n !modifiers.range_middle\n }\n data-range-start={modifiers.range_start}\n data-range-end={modifiers.range_end}\n data-range-middle={modifiers.range_middle}\n className={cn(\n \"flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70\",\n defaultClassNames.day,\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Calendar, CalendarDayButton }\n",
19
+ "type": "registry:ui"
20
+ }
21
+ ],
22
+ "categories": [
23
+ "Formulário"
24
+ ],
25
+ "type": "registry:ui"
26
+ }
package/r/card.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "card",
4
+ "title": "Card",
5
+ "description": "Bloco com cabeçalho, conteúdo e rodapé.",
6
+ "dependencies": [
7
+ "cn@^0.5.0"
8
+ ],
9
+ "registryDependencies": [
10
+ "@ihms/theme"
11
+ ],
12
+ "files": [
13
+ {
14
+ "path": "src/components/ui/card.tsx",
15
+ "content": "/**\n * @categoria Exibição\n * @descricao Bloco com cabeçalho, conteúdo e rodapé.\n * @shadcn\n */\nimport * as React from \"react\"\nimport { cn } from \"cn\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-sm\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6 [.border-t]:pt-6\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n",
16
+ "type": "registry:ui"
17
+ }
18
+ ],
19
+ "categories": [
20
+ "Exibição"
21
+ ],
22
+ "type": "registry:ui"
23
+ }