@traky-app/ui 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 (131) hide show
  1. package/README.md +30 -2
  2. package/package.json +26 -4
  3. package/registry/registry.json +6 -0
  4. package/registry/traky/hooks/use-mobile.ts +19 -0
  5. package/registry/traky/json/accordion.json +18 -0
  6. package/registry/traky/json/alert-dialog.json +20 -0
  7. package/registry/traky/json/alert.json +17 -0
  8. package/registry/traky/json/animated-beam.json +14 -0
  9. package/registry/traky/json/animated-list.json +14 -0
  10. package/registry/traky/json/avatar.json +17 -0
  11. package/registry/traky/json/badge.json +18 -0
  12. package/registry/traky/json/bento-grid.json +20 -0
  13. package/registry/traky/json/breadcrumb.json +18 -0
  14. package/registry/traky/json/bubble.json +18 -0
  15. package/registry/traky/json/button-group.json +21 -0
  16. package/registry/traky/json/button.json +18 -0
  17. package/registry/traky/json/calendar.json +21 -0
  18. package/registry/traky/json/card.json +14 -0
  19. package/registry/traky/json/carousel.json +21 -0
  20. package/registry/traky/json/chart.json +17 -0
  21. package/registry/traky/json/checkbox.json +18 -0
  22. package/registry/traky/json/checkpoint.json +22 -0
  23. package/registry/traky/json/code-block.json +21 -0
  24. package/registry/traky/json/collapsible.json +17 -0
  25. package/registry/traky/json/command.json +22 -0
  26. package/registry/traky/json/context-menu.json +18 -0
  27. package/registry/traky/json/dialog.json +18 -0
  28. package/registry/traky/json/drawer.json +17 -0
  29. package/registry/traky/json/dropdown-menu.json +18 -0
  30. package/registry/traky/json/empty.json +17 -0
  31. package/registry/traky/json/field.json +21 -0
  32. package/registry/traky/json/globe.json +17 -0
  33. package/registry/traky/json/hook-use-mobile.json +14 -0
  34. package/registry/traky/json/hover-card.json +17 -0
  35. package/registry/traky/json/input-group.json +22 -0
  36. package/registry/traky/json/input-otp.json +18 -0
  37. package/registry/traky/json/input.json +17 -0
  38. package/registry/traky/json/item.json +21 -0
  39. package/registry/traky/json/kbd.json +14 -0
  40. package/registry/traky/json/label.json +17 -0
  41. package/registry/traky/json/lib-disable-input-autofill.json +14 -0
  42. package/registry/traky/json/lib-sidebar-persistence.json +14 -0
  43. package/registry/traky/json/lib-utils.json +18 -0
  44. package/registry/traky/json/map.json +19 -0
  45. package/registry/traky/json/marker.json +18 -0
  46. package/registry/traky/json/marquee.json +14 -0
  47. package/registry/traky/json/message.json +14 -0
  48. package/registry/traky/json/navigation-menu.json +19 -0
  49. package/registry/traky/json/number-ticker.json +14 -0
  50. package/registry/traky/json/pagination.json +20 -0
  51. package/registry/traky/json/popover.json +17 -0
  52. package/registry/traky/json/progress.json +17 -0
  53. package/registry/traky/json/select.json +18 -0
  54. package/registry/traky/json/separator.json +17 -0
  55. package/registry/traky/json/sheet.json +18 -0
  56. package/registry/traky/json/sidebar.json +29 -0
  57. package/registry/traky/json/skeleton.json +14 -0
  58. package/registry/traky/json/sonner.json +18 -0
  59. package/registry/traky/json/spinner.json +17 -0
  60. package/registry/traky/json/switch.json +17 -0
  61. package/registry/traky/json/table.json +14 -0
  62. package/registry/traky/json/tabs.json +17 -0
  63. package/registry/traky/json/textarea.json +17 -0
  64. package/registry/traky/json/toggle-group.json +21 -0
  65. package/registry/traky/json/toggle.json +18 -0
  66. package/registry/traky/json/tooltip.json +17 -0
  67. package/registry/traky/json/trace.json +20 -0
  68. package/registry/traky/lib/disable-input-autofill.ts +23 -0
  69. package/registry/traky/lib/sidebar-persistence.ts +76 -0
  70. package/registry/traky/lib/utils.ts +6 -0
  71. package/registry/traky/registry.json +637 -0
  72. package/registry/traky/ui/accordion.tsx +65 -0
  73. package/registry/traky/ui/alert-dialog.tsx +163 -0
  74. package/registry/traky/ui/alert.tsx +66 -0
  75. package/registry/traky/ui/animated-beam.tsx +185 -0
  76. package/registry/traky/ui/animated-list.tsx +71 -0
  77. package/registry/traky/ui/avatar.tsx +53 -0
  78. package/registry/traky/ui/badge.tsx +46 -0
  79. package/registry/traky/ui/bento-grid.tsx +109 -0
  80. package/registry/traky/ui/breadcrumb.tsx +108 -0
  81. package/registry/traky/ui/bubble.tsx +125 -0
  82. package/registry/traky/ui/button-group.tsx +83 -0
  83. package/registry/traky/ui/button.tsx +64 -0
  84. package/registry/traky/ui/calendar.tsx +213 -0
  85. package/registry/traky/ui/card.tsx +92 -0
  86. package/registry/traky/ui/carousel.tsx +240 -0
  87. package/registry/traky/ui/chart.tsx +380 -0
  88. package/registry/traky/ui/checkbox.tsx +31 -0
  89. package/registry/traky/ui/checkpoint.tsx +94 -0
  90. package/registry/traky/ui/code-block.tsx +232 -0
  91. package/registry/traky/ui/collapsible.tsx +33 -0
  92. package/registry/traky/ui/command.tsx +190 -0
  93. package/registry/traky/ui/context-menu.tsx +251 -0
  94. package/registry/traky/ui/dialog.tsx +142 -0
  95. package/registry/traky/ui/drawer.tsx +135 -0
  96. package/registry/traky/ui/dropdown-menu.tsx +256 -0
  97. package/registry/traky/ui/empty.tsx +104 -0
  98. package/registry/traky/ui/field.tsx +248 -0
  99. package/registry/traky/ui/globe.tsx +234 -0
  100. package/registry/traky/ui/hover-card.tsx +44 -0
  101. package/registry/traky/ui/input-group.tsx +170 -0
  102. package/registry/traky/ui/input-otp.tsx +77 -0
  103. package/registry/traky/ui/input.tsx +24 -0
  104. package/registry/traky/ui/item.tsx +193 -0
  105. package/registry/traky/ui/kbd.tsx +28 -0
  106. package/registry/traky/ui/label.tsx +24 -0
  107. package/registry/traky/ui/map.tsx +2226 -0
  108. package/registry/traky/ui/marker.tsx +69 -0
  109. package/registry/traky/ui/marquee.tsx +74 -0
  110. package/registry/traky/ui/message.tsx +92 -0
  111. package/registry/traky/ui/navigation-menu.tsx +169 -0
  112. package/registry/traky/ui/number-ticker.tsx +90 -0
  113. package/registry/traky/ui/pagination.tsx +122 -0
  114. package/registry/traky/ui/popover.tsx +48 -0
  115. package/registry/traky/ui/progress.tsx +31 -0
  116. package/registry/traky/ui/select.tsx +193 -0
  117. package/registry/traky/ui/separator.tsx +28 -0
  118. package/registry/traky/ui/sheet.tsx +143 -0
  119. package/registry/traky/ui/sidebar.tsx +764 -0
  120. package/registry/traky/ui/skeleton.tsx +13 -0
  121. package/registry/traky/ui/sonner.tsx +71 -0
  122. package/registry/traky/ui/spinner.tsx +15 -0
  123. package/registry/traky/ui/switch.tsx +41 -0
  124. package/registry/traky/ui/table.tsx +116 -0
  125. package/registry/traky/ui/tabs.tsx +66 -0
  126. package/registry/traky/ui/textarea.tsx +20 -0
  127. package/registry/traky/ui/toggle-group.tsx +83 -0
  128. package/registry/traky/ui/toggle.tsx +47 -0
  129. package/registry/traky/ui/tooltip.tsx +61 -0
  130. package/registry/traky/ui/trace.tsx +165 -0
  131. package/schema/components.json +24 -0
package/README.md CHANGED
@@ -1,3 +1,31 @@
1
- # Temporary Holding Version
1
+ # @traky-app/ui
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 oficial de componentes Traky (copy-paste, estilo shadcn, **sin** depender de `ui.shadcn.com`).
4
+
5
+ ## Estructura
6
+
7
+ ```
8
+ packages/ui/
9
+ ├── registry/traky/
10
+ │ ├── ui/ # fuente .tsx (59+ componentes)
11
+ │ ├── lib/ # utils, sidebar-persistence, …
12
+ │ ├── hooks/ # use-mobile, …
13
+ │ ├── json/ # ítems generados (*.json)
14
+ │ └── registry.json # índice
15
+ ├── schema/components.json # plantilla components.json
16
+ └── scripts/build-registry.mjs
17
+ ```
18
+
19
+ ## Generar JSON del registro
20
+
21
+ Tras editar fuentes en `registry/traky/ui/`:
22
+
23
+ ```bash
24
+ pnpm --filter @traky-app/ui registry:build
25
+ ```
26
+
27
+ Commitea `registry/traky/json/` para que funcione la URL raw de GitHub.
28
+
29
+ ## Consumir desde app-traky
30
+
31
+ Ver `@traky-app/cli` y [REGISTRY.md](../../REGISTRY.md) en la raíz del monorepo.
package/package.json CHANGED
@@ -1,6 +1,28 @@
1
1
  {
2
2
  "name": "@traky-app/ui",
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 Traky UI — componentes copy-paste (sin depender del registro shadcn)",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "files": [
8
+ "registry",
9
+ "schema",
10
+ "README.md"
11
+ ],
12
+ "exports": {
13
+ "./registry/*": "./registry/*",
14
+ "./schema/components.json": "./schema/components.json"
15
+ },
16
+ "scripts": {
17
+ "registry:build": "node ./scripts/build-registry.mjs",
18
+ "prepack": "pnpm registry:build"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "https://github.com/traky-app/traky-ui.git",
23
+ "directory": "packages/ui"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ }
28
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry.json",
3
+ "name": "traky",
4
+ "homepage": "https://traky.app",
5
+ "items": []
6
+ }
@@ -0,0 +1,19 @@
1
+ import * as React from "react"
2
+
3
+ const MOBILE_BREAKPOINT = 768
4
+
5
+ export function useIsMobile() {
6
+ const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
7
+
8
+ React.useEffect(() => {
9
+ const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
10
+ const onChange = () => {
11
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
12
+ }
13
+ mql.addEventListener("change", onChange)
14
+ setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
15
+ return () => mql.removeEventListener("change", onChange)
16
+ }, [])
17
+
18
+ return !!isMobile
19
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "accordion",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@radix-ui/react-accordion",
8
+ "@tabler/icons-react"
9
+ ],
10
+ "files": [
11
+ {
12
+ "path": "ui/accordion.tsx",
13
+ "content": "\"use client\"\n\nimport { IconChevronDown } from \"@tabler/icons-react\";\nimport * as React from \"react\"\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\"\nimport { cn } from \"@/lib/utils\"\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 \"focus-visible:border-ring focus-visible:ring-ring/50 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:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180\",\n className\n )}\n {...props}\n >\n {children}\n <IconChevronDown className=\"text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 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=\"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm\"\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",
14
+ "type": "registry:ui",
15
+ "target": ""
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "alert-dialog",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@radix-ui/react-alert-dialog"
8
+ ],
9
+ "registryDependencies": [
10
+ "button"
11
+ ],
12
+ "files": [
13
+ {
14
+ "path": "ui/alert-dialog.tsx",
15
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\"\n\nimport { cn } from \"@/lib/utils\"\nimport { buttonVariants } 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 \"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50\",\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\" | \"lg\"\n}) {\n return (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n data-slot=\"alert-dialog-content\"\n className={cn(\n \"bg-background 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 fixed top-[50%] left-[50%] z-50 w-full translate-x-[-50%] translate-y-[-50%] rounded-lg border shadow-lg duration-200\",\n size === \"lg\"\n ? \"flex max-h-[92dvh] max-w-[calc(100%-1.25rem)] flex-col gap-0 overflow-hidden p-0 sm:max-w-5xl\"\n : \"grid max-w-[calc(100%-2rem)] gap-4 p-6 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(\"flex flex-col gap-2 text-center sm:text-left\", className)}\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 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(\"text-lg font-semibold\", className)}\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-muted-foreground text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogAction({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Action>) {\n return (\n <AlertDialogPrimitive.Action\n className={cn(buttonVariants(), className)}\n {...props}\n />\n )\n}\n\nfunction AlertDialogCancel({\n className,\n ...props\n}: React.ComponentProps<typeof AlertDialogPrimitive.Cancel>) {\n return (\n <AlertDialogPrimitive.Cancel\n className={cn(buttonVariants({ variant: \"outline\" }), className)}\n {...props}\n />\n )\n}\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n}\n",
16
+ "type": "registry:ui",
17
+ "target": ""
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "alert",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "class-variance-authority"
8
+ ],
9
+ "files": [
10
+ {
11
+ "path": "ui/alert.tsx",
12
+ "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>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 \"text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90\",\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 \"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Alert, AlertTitle, AlertDescription }\n",
13
+ "type": "registry:ui",
14
+ "target": ""
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "animated-beam",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "files": [
7
+ {
8
+ "path": "ui/animated-beam.tsx",
9
+ "content": "\"use client\"\n\nimport { RefObject, useEffect, useId, useState } from \"react\"\nimport { motion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface AnimatedBeamProps {\n className?: string\n containerRef: RefObject<HTMLElement | null> // Container ref\n fromRef: RefObject<HTMLElement | null>\n toRef: RefObject<HTMLElement | null>\n curvature?: number\n reverse?: boolean\n pathColor?: string\n pathWidth?: number\n pathOpacity?: number\n gradientStartColor?: string\n gradientStopColor?: string\n delay?: number\n duration?: number\n startXOffset?: number\n startYOffset?: number\n endXOffset?: number\n endYOffset?: number\n}\n\nexport const AnimatedBeam: React.FC<AnimatedBeamProps> = ({\n className,\n containerRef,\n fromRef,\n toRef,\n curvature = 0,\n reverse = false, // Include the reverse prop\n duration = Math.random() * 3 + 4,\n delay = 0,\n pathColor = \"gray\",\n pathWidth = 2,\n pathOpacity = 0.2,\n gradientStartColor = \"#ffaa40\",\n gradientStopColor = \"#9c40ff\",\n startXOffset = 0,\n startYOffset = 0,\n endXOffset = 0,\n endYOffset = 0,\n}) => {\n const id = useId()\n const [pathD, setPathD] = useState(\"\")\n const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 })\n\n // Calculate the gradient coordinates based on the reverse prop\n const gradientCoordinates = reverse\n ? {\n x1: [\"90%\", \"-10%\"],\n x2: [\"100%\", \"0%\"],\n y1: [\"0%\", \"0%\"],\n y2: [\"0%\", \"0%\"],\n }\n : {\n x1: [\"10%\", \"110%\"],\n x2: [\"0%\", \"100%\"],\n y1: [\"0%\", \"0%\"],\n y2: [\"0%\", \"0%\"],\n }\n\n useEffect(() => {\n const updatePath = () => {\n if (containerRef.current && fromRef.current && toRef.current) {\n const containerRect = containerRef.current.getBoundingClientRect()\n const rectA = fromRef.current.getBoundingClientRect()\n const rectB = toRef.current.getBoundingClientRect()\n\n const svgWidth = containerRect.width\n const svgHeight = containerRect.height\n setSvgDimensions({ width: svgWidth, height: svgHeight })\n\n const startX =\n rectA.left - containerRect.left + rectA.width / 2 + startXOffset\n const startY =\n rectA.top - containerRect.top + rectA.height / 2 + startYOffset\n const endX =\n rectB.left - containerRect.left + rectB.width / 2 + endXOffset\n const endY =\n rectB.top - containerRect.top + rectB.height / 2 + endYOffset\n\n const controlY = startY - curvature\n const d = `M ${startX},${startY} Q ${\n (startX + endX) / 2\n },${controlY} ${endX},${endY}`\n setPathD(d)\n }\n }\n\n // Initialize ResizeObserver\n const resizeObserver = new ResizeObserver(() => {\n updatePath()\n })\n\n // Observe the container element\n if (containerRef.current) {\n resizeObserver.observe(containerRef.current)\n }\n\n // Call the updatePath initially to set the initial path\n updatePath()\n\n // Clean up the observer on component unmount\n return () => {\n resizeObserver.disconnect()\n }\n }, [\n containerRef,\n fromRef,\n toRef,\n curvature,\n startXOffset,\n startYOffset,\n endXOffset,\n endYOffset,\n ])\n\n return (\n <svg\n fill=\"none\"\n width={svgDimensions.width}\n height={svgDimensions.height}\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn(\n \"pointer-events-none absolute top-0 left-0 transform-gpu stroke-2\",\n className\n )}\n viewBox={`0 0 ${svgDimensions.width} ${svgDimensions.height}`}\n >\n <path\n d={pathD}\n stroke={pathColor}\n strokeWidth={pathWidth}\n strokeOpacity={pathOpacity}\n strokeLinecap=\"round\"\n />\n <path\n d={pathD}\n strokeWidth={pathWidth}\n stroke={`url(#${id})`}\n strokeOpacity=\"1\"\n strokeLinecap=\"round\"\n />\n <defs>\n <motion.linearGradient\n className=\"transform-gpu\"\n id={id}\n gradientUnits={\"userSpaceOnUse\"}\n initial={{\n x1: \"0%\",\n x2: \"0%\",\n y1: \"0%\",\n y2: \"0%\",\n }}\n animate={{\n x1: gradientCoordinates.x1,\n x2: gradientCoordinates.x2,\n y1: gradientCoordinates.y1,\n y2: gradientCoordinates.y2,\n }}\n transition={{\n delay,\n duration,\n ease: [0.16, 1, 0.3, 1], // https://easings.net/#easeOutExpo\n repeat: Infinity,\n repeatDelay: 0,\n }}\n >\n <stop stopColor={gradientStartColor} stopOpacity=\"0\"></stop>\n <stop stopColor={gradientStartColor}></stop>\n <stop offset=\"32.5%\" stopColor={gradientStopColor}></stop>\n <stop\n offset=\"100%\"\n stopColor={gradientStopColor}\n stopOpacity=\"0\"\n ></stop>\n </motion.linearGradient>\n </defs>\n </svg>\n )\n}\n",
10
+ "type": "registry:ui",
11
+ "target": ""
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "animated-list",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "files": [
7
+ {
8
+ "path": "ui/animated-list.tsx",
9
+ "content": "\"use client\"\n\nimport React, {\n ComponentPropsWithoutRef,\n useEffect,\n useMemo,\n useState,\n} from \"react\"\nimport { AnimatePresence, motion, MotionProps } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport function AnimatedListItem({ children }: { children: React.ReactNode }) {\n const animations: MotionProps = {\n initial: { scale: 0, opacity: 0 },\n animate: { scale: 1, opacity: 1, originY: 0 },\n exit: { scale: 0, opacity: 0 },\n transition: { type: \"spring\", stiffness: 350, damping: 40 },\n }\n\n return (\n <motion.div {...animations} layout className=\"mx-auto w-full\">\n {children}\n </motion.div>\n )\n}\n\nexport interface AnimatedListProps extends ComponentPropsWithoutRef<\"div\"> {\n children: React.ReactNode\n delay?: number\n}\n\nexport const AnimatedList = React.memo(\n ({ children, className, delay = 1000, ...props }: AnimatedListProps) => {\n const [index, setIndex] = useState(0)\n const childrenArray = useMemo(\n () => React.Children.toArray(children),\n [children]\n )\n\n useEffect(() => {\n const timeout = setTimeout(() => {\n setIndex((prevIndex) => (prevIndex + 1) % childrenArray.length)\n }, delay)\n\n return () => clearTimeout(timeout)\n }, [index, delay, childrenArray.length])\n\n const itemsToShow = useMemo(() => {\n const result = childrenArray.slice(0, index + 1).reverse()\n return result\n }, [index, childrenArray])\n\n return (\n <div\n className={cn(`flex flex-col items-center gap-4`, className)}\n {...props}\n >\n <AnimatePresence>\n {itemsToShow.map((item) => (\n <AnimatedListItem key={(item as React.ReactElement).key}>\n {item}\n </AnimatedListItem>\n ))}\n </AnimatePresence>\n </div>\n )\n }\n)\n\nAnimatedList.displayName = \"AnimatedList\"\n",
10
+ "type": "registry:ui",
11
+ "target": ""
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "avatar",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@radix-ui/react-avatar"
8
+ ],
9
+ "files": [
10
+ {
11
+ "path": "ui/avatar.tsx",
12
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as AvatarPrimitive from \"@radix-ui/react-avatar\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Avatar({\n className,\n ...props\n}: React.ComponentProps<typeof AvatarPrimitive.Root>) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n className={cn(\n \"relative flex size-8 shrink-0 overflow-hidden rounded-full\",\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 \"bg-muted flex size-full items-center justify-center rounded-full\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Avatar, AvatarImage, AvatarFallback }\n",
13
+ "type": "registry:ui",
14
+ "target": ""
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "badge",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@radix-ui/react-slot",
8
+ "class-variance-authority"
9
+ ],
10
+ "files": [
11
+ {
12
+ "path": "ui/badge.tsx",
13
+ "content": "import * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden\",\n {\n variants: {\n variant: {\n default:\n \"border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"border-transparent bg-destructive text-destructive-foreground [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60\",\n outline:\n \"text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant,\n asChild = false,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & { asChild?: boolean }) {\n const Comp = asChild ? Slot : \"span\"\n\n return (\n <Comp\n data-slot=\"badge\"\n className={cn(badgeVariants({ variant }), className)}\n {...props}\n />\n )\n}\n\nexport { Badge, badgeVariants }\n",
14
+ "type": "registry:ui",
15
+ "target": ""
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "bento-grid",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@tabler/icons-react"
8
+ ],
9
+ "registryDependencies": [
10
+ "button"
11
+ ],
12
+ "files": [
13
+ {
14
+ "path": "ui/bento-grid.tsx",
15
+ "content": "import { ComponentPropsWithoutRef, ReactNode } from \"react\"\nimport { IconArrowRight } from \"@tabler/icons-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\n\ninterface BentoGridProps extends ComponentPropsWithoutRef<\"div\"> {\n children: ReactNode\n className?: string\n}\n\ninterface BentoCardProps extends ComponentPropsWithoutRef<\"div\"> {\n name: string\n className: string\n background: ReactNode\n Icon: React.ElementType\n description: string\n href: string\n cta: string\n}\n\nconst BentoGrid = ({ children, className, ...props }: BentoGridProps) => {\n return (\n <div\n className={cn(\n \"grid w-full auto-rows-[22rem] grid-cols-3 gap-4\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\n\nconst BentoCard = ({\n name,\n className,\n background,\n Icon,\n description,\n href,\n cta,\n ...props\n}: BentoCardProps) => (\n <div\n key={name}\n className={cn(\n \"group relative col-span-3 flex flex-col justify-between overflow-hidden rounded-xl\",\n // light styles\n \"bg-background [box-shadow:0_0_0_1px_rgba(0,0,0,.03),0_2px_4px_rgba(0,0,0,.05),0_12px_24px_rgba(0,0,0,.05)]\",\n // dark styles\n \"dark:bg-background transform-gpu dark:[box-shadow:0_-20px_80px_-20px_#ffffff1f_inset] dark:[border:1px_solid_rgba(255,255,255,.1)]\",\n className\n )}\n {...props}\n >\n <div>{background}</div>\n <div className=\"p-4\">\n <div className=\"pointer-events-none z-10 flex transform-gpu flex-col gap-1 transition-all duration-300 lg:group-hover:-translate-y-10\">\n <Icon className=\"h-12 w-12 origin-left transform-gpu text-neutral-700 transition-all duration-300 ease-in-out group-hover:scale-75\" />\n <h3 className=\"text-xl font-semibold text-neutral-700 dark:text-neutral-300\">\n {name}\n </h3>\n <p className=\"max-w-lg text-neutral-400\">{description}</p>\n </div>\n\n <div\n className={cn(\n \"pointer-events-none flex w-full translate-y-0 transform-gpu flex-row items-center transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100 lg:hidden\"\n )}\n >\n <Button\n variant=\"link\"\n asChild\n size=\"sm\"\n className=\"pointer-events-auto p-0\"\n >\n <a href={href}>\n {cta}\n <IconArrowRight className=\"ms-2 size-4 rtl:rotate-180\" />\n </a>\n </Button>\n </div>\n </div>\n\n <div\n className={cn(\n \"pointer-events-none absolute bottom-0 hidden w-full translate-y-10 transform-gpu flex-row items-center p-4 opacity-0 transition-all duration-300 group-hover:translate-y-0 group-hover:opacity-100 lg:flex\"\n )}\n >\n <Button\n variant=\"link\"\n asChild\n size=\"sm\"\n className=\"pointer-events-auto p-0\"\n >\n <a href={href}>\n {cta}\n <IconArrowRight className=\"ms-2 size-4 rtl:rotate-180\" />\n </a>\n </Button>\n </div>\n\n <div className=\"pointer-events-none absolute inset-0 transform-gpu transition-all duration-300 group-hover:bg-black/[.03] group-hover:dark:bg-neutral-800/10\" />\n </div>\n)\n\nexport { BentoCard, BentoGrid }\n",
16
+ "type": "registry:ui",
17
+ "target": ""
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "breadcrumb",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@radix-ui/react-slot",
8
+ "@tabler/icons-react"
9
+ ],
10
+ "files": [
11
+ {
12
+ "path": "ui/breadcrumb.tsx",
13
+ "content": "import { IconChevronRight, IconDots } from \"@tabler/icons-react\";\nimport * as React from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cn } from \"@/lib/utils\"\n\nfunction Breadcrumb({ ...props }: React.ComponentProps<\"nav\">) {\n return <nav aria-label=\"breadcrumb\" 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 \"text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words 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 : \"a\"\n\n return (\n <Comp\n data-slot=\"breadcrumb-link\"\n className={cn(\"hover:text-foreground transition-colors\", 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(\"text-foreground font-normal\", 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 ?? <IconChevronRight />}\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 <IconDots className=\"size-4\" />\n <span className=\"sr-only\">More</span>\n </span>\n )\n}\n\nexport {\n Breadcrumb,\n BreadcrumbList,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbPage,\n BreadcrumbSeparator,\n BreadcrumbEllipsis,\n}\n",
14
+ "type": "registry:ui",
15
+ "target": ""
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "bubble",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "class-variance-authority",
8
+ "radix-ui"
9
+ ],
10
+ "files": [
11
+ {
12
+ "path": "ui/bubble.tsx",
13
+ "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\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",
14
+ "type": "registry:ui",
15
+ "target": ""
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "button-group",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "class-variance-authority",
8
+ "radix-ui"
9
+ ],
10
+ "registryDependencies": [
11
+ "separator"
12
+ ],
13
+ "files": [
14
+ {
15
+ "path": "ui/button-group.tsx",
16
+ "content": "import { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\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",
17
+ "type": "registry:ui",
18
+ "target": ""
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "button",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "class-variance-authority",
8
+ "radix-ui"
9
+ ],
10
+ "files": [
11
+ {
12
+ "path": "ui/button.tsx",
13
+ "content": "import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { Slot } from \"radix-ui\"\n\nimport { cn } from \"@/lib/utils\"\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 },\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",
14
+ "type": "registry:ui",
15
+ "target": ""
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "calendar",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@tabler/icons-react",
8
+ "react-day-picker"
9
+ ],
10
+ "registryDependencies": [
11
+ "button"
12
+ ],
13
+ "files": [
14
+ {
15
+ "path": "ui/calendar.tsx",
16
+ "content": "\"use client\"\n\nimport { IconChevronDown, IconChevronLeft, IconChevronRight } from \"@tabler/icons-react\";\nimport * as React from \"react\"\nimport { DayButton, DayPicker, getDefaultClassNames } from \"react-day-picker\"\n\nimport { cn } from \"@/lib/utils\"\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 \"bg-background group/calendar 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 \"flex gap-4 flex-col md:flex-row relative\",\n defaultClassNames.months\n ),\n month: cn(\"flex flex-col w-full gap-4\", defaultClassNames.month),\n nav: cn(\n \"flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between\",\n defaultClassNames.nav\n ),\n button_previous: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n defaultClassNames.button_previous\n ),\n button_next: cn(\n buttonVariants({ variant: buttonVariant }),\n \"size-(--cell-size) aria-disabled:opacity-50 p-0 select-none\",\n defaultClassNames.button_next\n ),\n month_caption: cn(\n \"flex items-center justify-center h-(--cell-size) w-full px-(--cell-size)\",\n defaultClassNames.month_caption\n ),\n dropdowns: cn(\n \"w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5\",\n defaultClassNames.dropdowns\n ),\n dropdown_root: cn(\n \"relative has-focus:border-ring border border-input shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] rounded-md\",\n defaultClassNames.dropdown_root\n ),\n dropdown: cn(\n \"absolute bg-popover inset-0 opacity-0\",\n defaultClassNames.dropdown\n ),\n caption_label: cn(\n \"select-none font-medium\",\n captionLayout === \"label\"\n ? \"text-sm\"\n : \"rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5\",\n defaultClassNames.caption_label\n ),\n // react-day-picker v10: `table` sigue en runtime; tipos desactualizados\n table: \"w-full border-collapse\" as string,\n weekdays: cn(\"flex\", defaultClassNames.weekdays),\n weekday: cn(\n \"text-muted-foreground rounded-md flex-1 font-normal text-[0.8rem] select-none\",\n defaultClassNames.weekday\n ),\n week: cn(\"flex w-full mt-2\", defaultClassNames.week),\n week_number_header: cn(\n \"select-none w-(--cell-size)\",\n defaultClassNames.week_number_header\n ),\n week_number: cn(\n \"text-[0.8rem] select-none text-muted-foreground\",\n defaultClassNames.week_number\n ),\n day: cn(\n \"relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none\",\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 \"bg-accent text-accent-foreground rounded-md 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 } as React.ComponentProps<typeof DayPicker>[\"classNames\"]}\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 <IconChevronLeft className={cn(\"size-4\", className)} {...props} />\n )\n }\n\n if (orientation === \"right\") {\n return (\n <IconChevronRight\n className={cn(\"size-4\", className)}\n {...props}\n />\n )\n }\n\n return (\n <IconChevronDown 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 \"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 dark:hover:text-accent-foreground 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:ring-[3px] data-[range-end=true]:rounded-md data-[range-end=true]:rounded-r-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md data-[range-start=true]:rounded-l-md [&>span]:text-xs [&>span]:opacity-70\",\n defaultClassNames.day,\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Calendar, CalendarDayButton }\n",
17
+ "type": "registry:ui",
18
+ "target": ""
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "card",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "files": [
7
+ {
8
+ "path": "ui/card.tsx",
9
+ "content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 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-muted-foreground text-sm\", 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",
10
+ "type": "registry:ui",
11
+ "target": ""
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "carousel",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@tabler/icons-react",
8
+ "embla-carousel-react"
9
+ ],
10
+ "registryDependencies": [
11
+ "button"
12
+ ],
13
+ "files": [
14
+ {
15
+ "path": "ui/carousel.tsx",
16
+ "content": "\"use client\"\n\nimport { IconArrowLeft, IconArrowRight } from \"@tabler/icons-react\";\nimport * as React from \"react\"\nimport useEmblaCarousel, {\n type UseEmblaCarouselType,\n} from \"embla-carousel-react\"\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/components/ui/button\"\n\ntype CarouselApi = UseEmblaCarouselType[1]\ntype UseCarouselParameters = Parameters<typeof useEmblaCarousel>\ntype CarouselOptions = UseCarouselParameters[0]\ntype CarouselPlugin = UseCarouselParameters[1]\n\ntype CarouselProps = {\n opts?: CarouselOptions\n plugins?: CarouselPlugin\n orientation?: \"horizontal\" | \"vertical\"\n setApi?: (api: CarouselApi) => void\n}\n\ntype CarouselContextProps = {\n carouselRef: ReturnType<typeof useEmblaCarousel>[0]\n api: ReturnType<typeof useEmblaCarousel>[1]\n scrollPrev: () => void\n scrollNext: () => void\n canScrollPrev: boolean\n canScrollNext: boolean\n} & CarouselProps\n\nconst CarouselContext = React.createContext<CarouselContextProps | null>(null)\n\nfunction useCarousel() {\n const context = React.useContext(CarouselContext)\n\n if (!context) {\n throw new Error(\"useCarousel must be used within a <Carousel />\")\n }\n\n return context\n}\n\nfunction Carousel({\n orientation = \"horizontal\",\n opts,\n setApi,\n plugins,\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & CarouselProps) {\n const [carouselRef, api] = useEmblaCarousel(\n {\n ...opts,\n axis: orientation === \"horizontal\" ? \"x\" : \"y\",\n },\n plugins\n )\n const [canScrollPrev, setCanScrollPrev] = React.useState(false)\n const [canScrollNext, setCanScrollNext] = React.useState(false)\n\n const onSelect = React.useCallback((api: CarouselApi) => {\n if (!api) return\n setCanScrollPrev(api.canScrollPrev())\n setCanScrollNext(api.canScrollNext())\n }, [])\n\n const scrollPrev = React.useCallback(() => {\n api?.scrollPrev()\n }, [api])\n\n const scrollNext = React.useCallback(() => {\n api?.scrollNext()\n }, [api])\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (event.key === \"IconArrowLeft\") {\n event.preventDefault()\n scrollPrev()\n } else if (event.key === \"IconArrowRight\") {\n event.preventDefault()\n scrollNext()\n }\n },\n [scrollPrev, scrollNext]\n )\n\n React.useEffect(() => {\n if (!api || !setApi) return\n setApi(api)\n }, [api, setApi])\n\n React.useEffect(() => {\n if (!api) return\n onSelect(api)\n api.on(\"reInit\", onSelect)\n api.on(\"select\", onSelect)\n\n return () => {\n api?.off(\"select\", onSelect)\n }\n }, [api, onSelect])\n\n return (\n <CarouselContext.Provider\n value={{\n carouselRef,\n api: api,\n opts,\n orientation:\n orientation || (opts?.axis === \"y\" ? \"vertical\" : \"horizontal\"),\n scrollPrev,\n scrollNext,\n canScrollPrev,\n canScrollNext,\n }}\n >\n <div\n onKeyDownCapture={handleKeyDown}\n className={cn(\"relative\", className)}\n role=\"region\"\n aria-roledescription=\"carousel\"\n data-slot=\"carousel\"\n {...props}\n >\n {children}\n </div>\n </CarouselContext.Provider>\n )\n}\n\nfunction CarouselContent({ className, ...props }: React.ComponentProps<\"div\">) {\n const { carouselRef, orientation } = useCarousel()\n\n return (\n <div\n ref={carouselRef}\n className=\"overflow-hidden\"\n data-slot=\"carousel-content\"\n >\n <div\n className={cn(\n \"flex\",\n orientation === \"horizontal\" ? \"-ml-4\" : \"-mt-4 flex-col\",\n className\n )}\n {...props}\n />\n </div>\n )\n}\n\nfunction CarouselItem({ className, ...props }: React.ComponentProps<\"div\">) {\n const { orientation } = useCarousel()\n\n return (\n <div\n role=\"group\"\n aria-roledescription=\"slide\"\n data-slot=\"carousel-item\"\n className={cn(\n \"min-w-0 shrink-0 grow-0 basis-full\",\n orientation === \"horizontal\" ? \"pl-4\" : \"pt-4\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CarouselPrevious({\n className,\n variant = \"outline\",\n size = \"icon\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollPrev, canScrollPrev } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-previous\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -left-12 -translate-y-1/2\"\n : \"-top-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollPrev}\n onClick={scrollPrev}\n {...props}\n >\n <IconArrowLeft />\n <span className=\"sr-only\">Previous slide</span>\n </Button>\n )\n}\n\nfunction CarouselNext({\n className,\n variant = \"outline\",\n size = \"icon\",\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { orientation, scrollNext, canScrollNext } = useCarousel()\n\n return (\n <Button\n data-slot=\"carousel-next\"\n variant={variant}\n size={size}\n className={cn(\n \"absolute size-8 rounded-full\",\n orientation === \"horizontal\"\n ? \"top-1/2 -right-12 -translate-y-1/2\"\n : \"-bottom-12 left-1/2 -translate-x-1/2 rotate-90\",\n className\n )}\n disabled={!canScrollNext}\n onClick={scrollNext}\n {...props}\n >\n <IconArrowRight />\n <span className=\"sr-only\">Next slide</span>\n </Button>\n )\n}\n\nexport {\n type CarouselApi,\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselPrevious,\n CarouselNext,\n}\n",
17
+ "type": "registry:ui",
18
+ "target": ""
19
+ }
20
+ ]
21
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "chart",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "recharts"
8
+ ],
9
+ "files": [
10
+ {
11
+ "path": "ui/chart.tsx",
12
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as RechartsPrimitive from \"recharts\"\nimport type {\n TooltipContentProps,\n TooltipPayloadEntry,\n LegendPayload,\n} from \"recharts\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Format: { THEME_NAME: CSS_SELECTOR }\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record<keyof typeof THEMES, string> }\n )\n}\n\ntype ChartContextProps = {\n config: ChartConfig\n}\n\nconst ChartContext = React.createContext<ChartContextProps | null>(null)\n\nfunction useChart() {\n const context = React.useContext(ChartContext)\n\n if (!context) {\n throw new Error(\"useChart must be used within a <ChartContainer />\")\n }\n\n return context\n}\n\n/** Color de la serie definido en el config. La leyenda y el tooltip usan el mismo token que el trazo. */\nfunction seriesColor(config: ChartConfig, key: string, fallback?: string) {\n if (key in config && config[key]?.color) {\n return `var(--color-${key})`\n }\n return fallback\n}\n\nfunction ChartContainer({\n id,\n className,\n children,\n config,\n ...props\n}: React.ComponentProps<\"div\"> & {\n config: ChartConfig\n children: React.ComponentProps<\n typeof RechartsPrimitive.ResponsiveContainer\n >[\"children\"]\n}) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n\n return (\n <ChartContext.Provider value={{ config }}>\n <div\n data-slot=\"chart\"\n data-chart={chartId}\n className={cn(\n \"[&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border flex aspect-video justify-center text-xs [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-hidden [&_.recharts-sector]:outline-hidden [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-surface]:outline-hidden\",\n className\n )}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <RechartsPrimitive.ResponsiveContainer\n width=\"100%\"\n height=\"100%\"\n minWidth={0}\n debounce={50}\n >\n {children}\n </RechartsPrimitive.ResponsiveContainer>\n </div>\n </ChartContext.Provider>\n )\n}\n\nconst ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {\n const colorConfig = Object.entries(config).filter(\n ([, config]) => config.theme || config.color\n )\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n <style\n dangerouslySetInnerHTML={{\n __html: Object.entries(THEMES)\n .map(\n ([theme, prefix]) => `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, itemConfig]) => {\n const color =\n itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||\n itemConfig.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nconst ChartTooltip = RechartsPrimitive.Tooltip\n\nfunction ChartTooltipContent({\n active,\n payload,\n className,\n indicator = \"dot\",\n hideLabel = false,\n hideIndicator = false,\n label,\n labelFormatter,\n labelClassName,\n formatter,\n color,\n nameKey,\n labelKey,\n}: Partial<TooltipContentProps> &\n React.ComponentProps<\"div\"> & {\n hideLabel?: boolean\n hideIndicator?: boolean\n indicator?: \"line\" | \"dot\" | \"dashed\"\n nameKey?: string\n labelKey?: string\n }) {\n const { config } = useChart()\n\n const tooltipLabel = React.useMemo(() => {\n if (hideLabel || !payload?.length) {\n return null\n }\n\n const [item] = payload\n const key = `${labelKey || item?.dataKey || item?.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const value =\n !labelKey && typeof label === \"string\"\n ? config[label as keyof typeof config]?.label || label\n : itemConfig?.label\n\n if (labelFormatter) {\n return (\n <div className={cn(\"font-medium\", labelClassName)}>\n {labelFormatter(value, payload)}\n </div>\n )\n }\n\n if (!value) {\n return null\n }\n\n return <div className={cn(\"font-medium\", labelClassName)}>{value}</div>\n }, [\n label,\n labelFormatter,\n payload,\n hideLabel,\n labelClassName,\n config,\n labelKey,\n ])\n\n if (!active || !payload?.length) {\n return null\n }\n\n const nestLabel = payload.length === 1 && indicator !== \"dot\"\n\n return (\n <div\n className={cn(\n \"border-border/50 bg-background grid min-w-[8rem] items-start gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs shadow-xl\",\n className\n )}\n >\n {!nestLabel ? tooltipLabel : null}\n <div className=\"grid gap-1.5\">\n {payload\n .filter((item: TooltipPayloadEntry) => item.type !== \"none\")\n .map((item: TooltipPayloadEntry, index: number) => {\n const key = `${item.dataKey || nameKey || item.name || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n const indicatorColor =\n color || seriesColor(config, key, item.color || item.payload?.fill)\n\n return (\n <div\n key={\n item.graphicalItemId ??\n `row-${index}-${String(item.name ?? item.dataKey ?? \"\")}`\n }\n className={cn(\n \"[&>svg]:text-muted-foreground flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5\",\n indicator === \"dot\" && \"items-center\"\n )}\n >\n {formatter && item?.value !== undefined && item.name ? (\n formatter(item.value, item.name, item, index, item.payload)\n ) : (\n <>\n {itemConfig?.icon ? (\n <itemConfig.icon />\n ) : (\n !hideIndicator && (\n <div\n className={cn(\n \"shrink-0 rounded-[2px] border-(--color-border) bg-(--color-bg)\",\n {\n \"h-2.5 w-2.5\": indicator === \"dot\",\n \"w-1\": indicator === \"line\",\n \"w-0 border-[1.5px] border-dashed bg-transparent\":\n indicator === \"dashed\",\n \"my-0.5\": nestLabel && indicator === \"dashed\",\n }\n )}\n style={\n {\n \"--color-bg\": indicatorColor,\n \"--color-border\": indicatorColor,\n } as React.CSSProperties\n }\n />\n )\n )}\n <div\n className={cn(\n \"flex flex-1 justify-between leading-none\",\n nestLabel ? \"items-end\" : \"items-center\"\n )}\n >\n <div className=\"grid gap-1.5\">\n {nestLabel ? tooltipLabel : null}\n <span className=\"text-muted-foreground\">\n {itemConfig?.label || item.name}\n </span>\n </div>\n {item.value && (\n <span className=\"text-foreground font-mono font-medium tabular-nums\">\n {item.value.toLocaleString()}\n </span>\n )}\n </div>\n </>\n )}\n </div>\n )\n })}\n </div>\n </div>\n )\n}\n\nconst ChartLegend = RechartsPrimitive.Legend\n\nfunction ChartLegendContent({\n className,\n hideIcon = false,\n payload,\n verticalAlign = \"bottom\",\n nameKey,\n}: React.ComponentProps<\"div\"> & {\n payload?: ReadonlyArray<LegendPayload>\n verticalAlign?: \"top\" | \"bottom\";\n hideIcon?: boolean\n nameKey?: string\n}) {\n const { config } = useChart()\n\n if (!payload?.length) {\n return null\n }\n\n return (\n <div\n className={cn(\n \"flex items-center justify-center gap-4\",\n verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\n className\n )}\n >\n {payload\n .filter((item: LegendPayload) => item.type !== \"none\")\n .map((item: LegendPayload) => {\n const key = `${nameKey || item.dataKey || \"value\"}`\n const itemConfig = getPayloadConfigFromPayload(config, item, key)\n\n return (\n <div\n key={item.value}\n className={cn(\n \"[&>svg]:text-muted-foreground flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n <itemConfig.icon />\n ) : (\n <div\n className=\"h-2 w-2 shrink-0 rounded-[2px]\"\n style={{\n backgroundColor: seriesColor(config, key, item.color),\n }}\n />\n )}\n {itemConfig?.label}\n </div>\n )\n })}\n </div>\n )\n}\n\n// Helper to extract item config from a payload.\nfunction getPayloadConfigFromPayload(\n config: ChartConfig,\n payload: unknown,\n key: string\n) {\n if (typeof payload !== \"object\" || payload === null) {\n return undefined\n }\n\n const payloadPayload =\n \"payload\" in payload &&\n typeof payload.payload === \"object\" &&\n payload.payload !== null\n ? payload.payload\n : undefined\n\n let configLabelKey: string = key\n\n if (\n key in payload &&\n typeof payload[key as keyof typeof payload] === \"string\"\n ) {\n configLabelKey = payload[key as keyof typeof payload] as string\n } else if (\n payloadPayload &&\n key in payloadPayload &&\n typeof payloadPayload[key as keyof typeof payloadPayload] === \"string\"\n ) {\n configLabelKey = payloadPayload[\n key as keyof typeof payloadPayload\n ] as string\n }\n\n return configLabelKey in config\n ? config[configLabelKey]\n : config[key as keyof typeof config]\n}\n\nexport {\n ChartContainer,\n ChartTooltip,\n ChartTooltipContent,\n ChartLegend,\n ChartLegendContent,\n ChartStyle,\n}\n",
13
+ "type": "registry:ui",
14
+ "target": ""
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "checkbox",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@radix-ui/react-checkbox",
8
+ "@tabler/icons-react"
9
+ ],
10
+ "files": [
11
+ {
12
+ "path": "ui/checkbox.tsx",
13
+ "content": "\"use client\"\n\nimport { IconCheck } from \"@tabler/icons-react\";\nimport * as React from \"react\"\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\"\nimport { cn } from \"@/lib/utils\"\n\nfunction Checkbox({\n className,\n ...props\n}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {\n return (\n <CheckboxPrimitive.Root\n data-slot=\"checkbox\"\n className={cn(\n \"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50\",\n className\n )}\n {...props}\n >\n <CheckboxPrimitive.Indicator\n data-slot=\"checkbox-indicator\"\n className=\"grid place-content-center text-current transition-none\"\n >\n <IconCheck className=\"size-3.5\" />\n </CheckboxPrimitive.Indicator>\n </CheckboxPrimitive.Root>\n )\n}\n\nexport { Checkbox }\n",
14
+ "type": "registry:ui",
15
+ "target": ""
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "$schema": "https://ui.shadcn.com/schema/registry-item.json",
3
+ "name": "checkpoint",
4
+ "type": "registry:ui",
5
+ "author": "Traky (https://traky.app)",
6
+ "dependencies": [
7
+ "@tabler/icons-react"
8
+ ],
9
+ "registryDependencies": [
10
+ "button",
11
+ "marker",
12
+ "tooltip"
13
+ ],
14
+ "files": [
15
+ {
16
+ "path": "ui/checkpoint.tsx",
17
+ "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { IconBookmark } from \"@tabler/icons-react\"\n\nimport { Button } from \"@/components/ui/button\"\nimport { Marker, MarkerContent, MarkerIcon } from \"@/components/ui/marker\"\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\"\nimport { cn } from \"@/lib/utils\"\n\n/**\n * Checkpoint (AI Element): punto de restauración en un hilo.\n * Compuesto con Marker + Button — https://ui.shadcn.com/docs/ai-elements/base/checkpoint\n */\nfunction Checkpoint({\n className,\n ...props\n}: React.ComponentProps<typeof Marker>) {\n return (\n <Marker\n data-slot=\"checkpoint\"\n variant=\"separator\"\n className={cn(className)}\n {...props}\n />\n )\n}\n\nfunction CheckpointIcon({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof MarkerIcon>) {\n return (\n <MarkerIcon data-slot=\"checkpoint-icon\" className={className} {...props}>\n {children ?? <IconBookmark />}\n </MarkerIcon>\n )\n}\n\nfunction CheckpointTrigger({\n className,\n children = \"Restore\",\n tooltip,\n ...props\n}: React.ComponentProps<typeof Button> & {\n tooltip?: string\n}) {\n const button = (\n <Button\n data-slot=\"checkpoint-trigger\"\n type=\"button\"\n size=\"xs\"\n variant=\"outline\"\n className={cn(className)}\n {...props}\n >\n {children}\n </Button>\n )\n\n if (!tooltip) {\n return button\n }\n\n return (\n <TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent>{tooltip}</TooltipContent>\n </Tooltip>\n </TooltipProvider>\n )\n}\n\nfunction CheckpointContent({\n className,\n ...props\n}: React.ComponentProps<typeof MarkerContent>) {\n return (\n <MarkerContent\n data-slot=\"checkpoint-content\"\n className={cn(\"inline-flex items-center gap-2\", className)}\n {...props}\n />\n )\n}\n\nexport { Checkpoint, CheckpointIcon, CheckpointContent, CheckpointTrigger }\n",
18
+ "type": "registry:ui",
19
+ "target": ""
20
+ }
21
+ ]
22
+ }