@object-ui/components 0.3.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 (295) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/LICENSE +21 -0
  3. package/README.md +170 -0
  4. package/dist/index.css +1 -0
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.js +46186 -0
  7. package/dist/index.umd.cjs +92 -0
  8. package/dist/src/hooks/use-mobile.d.ts +1 -0
  9. package/dist/src/index.d.ts +2 -0
  10. package/dist/src/index.test.d.ts +1 -0
  11. package/dist/src/lib/utils.d.ts +4 -0
  12. package/dist/src/new-components.test.d.ts +1 -0
  13. package/dist/src/renderers/basic/div.d.ts +1 -0
  14. package/dist/src/renderers/basic/html.d.ts +1 -0
  15. package/dist/src/renderers/basic/icon.d.ts +1 -0
  16. package/dist/src/renderers/basic/image.d.ts +1 -0
  17. package/dist/src/renderers/basic/index.d.ts +0 -0
  18. package/dist/src/renderers/basic/separator.d.ts +1 -0
  19. package/dist/src/renderers/basic/span.d.ts +1 -0
  20. package/dist/src/renderers/basic/text.d.ts +1 -0
  21. package/dist/src/renderers/complex/__tests__/data-table.test.d.ts +0 -0
  22. package/dist/src/renderers/complex/calendar-view.d.ts +1 -0
  23. package/dist/src/renderers/complex/carousel.d.ts +1 -0
  24. package/dist/src/renderers/complex/chatbot.d.ts +1 -0
  25. package/dist/src/renderers/complex/chatbot.test.d.ts +1 -0
  26. package/dist/src/renderers/complex/data-table.d.ts +1 -0
  27. package/dist/src/renderers/complex/filter-builder.d.ts +1 -0
  28. package/dist/src/renderers/complex/index.d.ts +0 -0
  29. package/dist/src/renderers/complex/resizable.d.ts +1 -0
  30. package/dist/src/renderers/complex/scroll-area.d.ts +1 -0
  31. package/dist/src/renderers/complex/table.d.ts +1 -0
  32. package/dist/src/renderers/complex/timeline.d.ts +1 -0
  33. package/dist/src/renderers/data-display/alert.d.ts +1 -0
  34. package/dist/src/renderers/data-display/avatar.d.ts +1 -0
  35. package/dist/src/renderers/data-display/badge.d.ts +1 -0
  36. package/dist/src/renderers/data-display/index.d.ts +0 -0
  37. package/dist/src/renderers/data-display/list.d.ts +1 -0
  38. package/dist/src/renderers/data-display/statistic.d.ts +1 -0
  39. package/dist/src/renderers/data-display/tree-view.d.ts +1 -0
  40. package/dist/src/renderers/disclosure/accordion.d.ts +1 -0
  41. package/dist/src/renderers/disclosure/collapsible.d.ts +1 -0
  42. package/dist/src/renderers/disclosure/index.d.ts +0 -0
  43. package/dist/src/renderers/feedback/index.d.ts +0 -0
  44. package/dist/src/renderers/feedback/loading.d.ts +1 -0
  45. package/dist/src/renderers/feedback/progress.d.ts +1 -0
  46. package/dist/src/renderers/feedback/skeleton.d.ts +1 -0
  47. package/dist/src/renderers/feedback/toaster.d.ts +1 -0
  48. package/dist/src/renderers/form/button.d.ts +1 -0
  49. package/dist/src/renderers/form/calendar.d.ts +1 -0
  50. package/dist/src/renderers/form/checkbox.d.ts +1 -0
  51. package/dist/src/renderers/form/date-picker.d.ts +1 -0
  52. package/dist/src/renderers/form/file-upload.d.ts +1 -0
  53. package/dist/src/renderers/form/form.d.ts +1 -0
  54. package/dist/src/renderers/form/index.d.ts +0 -0
  55. package/dist/src/renderers/form/input-otp.d.ts +1 -0
  56. package/dist/src/renderers/form/input.d.ts +1 -0
  57. package/dist/src/renderers/form/label.d.ts +1 -0
  58. package/dist/src/renderers/form/radio-group.d.ts +1 -0
  59. package/dist/src/renderers/form/select.d.ts +1 -0
  60. package/dist/src/renderers/form/slider.d.ts +1 -0
  61. package/dist/src/renderers/form/switch.d.ts +1 -0
  62. package/dist/src/renderers/form/textarea.d.ts +1 -0
  63. package/dist/src/renderers/form/toggle.d.ts +1 -0
  64. package/dist/src/renderers/index.d.ts +0 -0
  65. package/dist/src/renderers/layout/card.d.ts +1 -0
  66. package/dist/src/renderers/layout/container.d.ts +1 -0
  67. package/dist/src/renderers/layout/flex.d.ts +1 -0
  68. package/dist/src/renderers/layout/grid.d.ts +1 -0
  69. package/dist/src/renderers/layout/index.d.ts +0 -0
  70. package/dist/src/renderers/layout/page.d.ts +7 -0
  71. package/dist/src/renderers/layout/semantic.d.ts +1 -0
  72. package/dist/src/renderers/layout/stack.d.ts +1 -0
  73. package/dist/src/renderers/layout/tabs.d.ts +1 -0
  74. package/dist/src/renderers/navigation/header-bar.d.ts +1 -0
  75. package/dist/src/renderers/navigation/index.d.ts +0 -0
  76. package/dist/src/renderers/navigation/sidebar.d.ts +1 -0
  77. package/dist/src/renderers/overlay/alert-dialog.d.ts +1 -0
  78. package/dist/src/renderers/overlay/context-menu.d.ts +1 -0
  79. package/dist/src/renderers/overlay/dialog.d.ts +1 -0
  80. package/dist/src/renderers/overlay/drawer.d.ts +1 -0
  81. package/dist/src/renderers/overlay/dropdown-menu.d.ts +1 -0
  82. package/dist/src/renderers/overlay/hover-card.d.ts +1 -0
  83. package/dist/src/renderers/overlay/index.d.ts +0 -0
  84. package/dist/src/renderers/overlay/popover.d.ts +1 -0
  85. package/dist/src/renderers/overlay/sheet.d.ts +1 -0
  86. package/dist/src/renderers/overlay/tooltip.d.ts +1 -0
  87. package/dist/src/ui/accordion.d.ts +7 -0
  88. package/dist/src/ui/alert-dialog.d.ts +14 -0
  89. package/dist/src/ui/alert.d.ts +9 -0
  90. package/dist/src/ui/aspect-ratio.d.ts +3 -0
  91. package/dist/src/ui/avatar.d.ts +6 -0
  92. package/dist/src/ui/badge.d.ts +9 -0
  93. package/dist/src/ui/breadcrumb.d.ts +11 -0
  94. package/dist/src/ui/button-group.d.ts +11 -0
  95. package/dist/src/ui/button.d.ts +13 -0
  96. package/dist/src/ui/calendar-view.d.ts +21 -0
  97. package/dist/src/ui/calendar.d.ts +8 -0
  98. package/dist/src/ui/card.d.ts +9 -0
  99. package/dist/src/ui/carousel.d.ts +19 -0
  100. package/dist/src/ui/chatbot.d.ts +36 -0
  101. package/dist/src/ui/checkbox.d.ts +4 -0
  102. package/dist/src/ui/collapsible.d.ts +5 -0
  103. package/dist/src/ui/command.d.ts +18 -0
  104. package/dist/src/ui/context-menu.d.ts +25 -0
  105. package/dist/src/ui/dialog.d.ts +15 -0
  106. package/dist/src/ui/drawer.d.ts +13 -0
  107. package/dist/src/ui/dropdown-menu.d.ts +25 -0
  108. package/dist/src/ui/empty.d.ts +11 -0
  109. package/dist/src/ui/field.d.ts +24 -0
  110. package/dist/src/ui/filter-builder.d.ts +31 -0
  111. package/dist/src/ui/form.d.ts +24 -0
  112. package/dist/src/ui/hover-card.d.ts +6 -0
  113. package/dist/src/ui/index.d.ts +56 -0
  114. package/dist/src/ui/input-group.d.ts +16 -0
  115. package/dist/src/ui/input-otp.d.ts +11 -0
  116. package/dist/src/ui/input.d.ts +3 -0
  117. package/dist/src/ui/item.d.ts +23 -0
  118. package/dist/src/ui/kbd.d.ts +3 -0
  119. package/dist/src/ui/label.d.ts +4 -0
  120. package/dist/src/ui/menubar.d.ts +26 -0
  121. package/dist/src/ui/navigation-menu.d.ts +14 -0
  122. package/dist/src/ui/pagination.d.ts +13 -0
  123. package/dist/src/ui/popover.d.ts +7 -0
  124. package/dist/src/ui/progress.d.ts +4 -0
  125. package/dist/src/ui/radio-group.d.ts +5 -0
  126. package/dist/src/ui/resizable.d.ts +10 -0
  127. package/dist/src/ui/scroll-area.d.ts +5 -0
  128. package/dist/src/ui/select.d.ts +15 -0
  129. package/dist/src/ui/separator.d.ts +4 -0
  130. package/dist/src/ui/sheet.d.ts +13 -0
  131. package/dist/src/ui/sidebar.d.ts +69 -0
  132. package/dist/src/ui/skeleton.d.ts +2 -0
  133. package/dist/src/ui/slider.d.ts +4 -0
  134. package/dist/src/ui/sonner.d.ts +3 -0
  135. package/dist/src/ui/spinner.d.ts +3 -0
  136. package/dist/src/ui/switch.d.ts +4 -0
  137. package/dist/src/ui/table.d.ts +10 -0
  138. package/dist/src/ui/tabs.d.ts +7 -0
  139. package/dist/src/ui/textarea.d.ts +3 -0
  140. package/dist/src/ui/timeline.d.ts +25 -0
  141. package/dist/src/ui/toggle-group.d.ts +9 -0
  142. package/dist/src/ui/toggle.d.ts +9 -0
  143. package/dist/src/ui/tooltip.d.ts +7 -0
  144. package/docs/FilterBuilder.md +268 -0
  145. package/metadata/Chart.component.yml +30 -0
  146. package/metadata/FilterBuilder.component.yml +39 -0
  147. package/metadata/GridLayout.component.yml +27 -0
  148. package/metadata/Menu.component.yml +31 -0
  149. package/metadata/ObjectForm.component.yml +34 -0
  150. package/metadata/ObjectTable.component.yml +41 -0
  151. package/metadata/Page.component.yml +24 -0
  152. package/package.json +87 -0
  153. package/postcss.config.js +6 -0
  154. package/src/hooks/use-mobile.tsx +19 -0
  155. package/src/index.css +76 -0
  156. package/src/index.test.ts +7 -0
  157. package/src/index.ts +10 -0
  158. package/src/lib/utils.tsx +27 -0
  159. package/src/new-components.test.ts +74 -0
  160. package/src/renderers/basic/div.tsx +41 -0
  161. package/src/renderers/basic/html.tsx +34 -0
  162. package/src/renderers/basic/icon.tsx +25 -0
  163. package/src/renderers/basic/image.tsx +37 -0
  164. package/src/renderers/basic/index.ts +7 -0
  165. package/src/renderers/basic/separator.tsx +48 -0
  166. package/src/renderers/basic/span.tsx +44 -0
  167. package/src/renderers/basic/text.tsx +42 -0
  168. package/src/renderers/complex/README-KANBAN.md +208 -0
  169. package/src/renderers/complex/TIMELINE.md +353 -0
  170. package/src/renderers/complex/__tests__/data-table.test.ts +52 -0
  171. package/src/renderers/complex/calendar-view.tsx +219 -0
  172. package/src/renderers/complex/carousel.tsx +60 -0
  173. package/src/renderers/complex/chatbot.test.ts +44 -0
  174. package/src/renderers/complex/chatbot.tsx +185 -0
  175. package/src/renderers/complex/data-table.tsx +650 -0
  176. package/src/renderers/complex/filter-builder.tsx +68 -0
  177. package/src/renderers/complex/index.ts +10 -0
  178. package/src/renderers/complex/resizable.tsx +54 -0
  179. package/src/renderers/complex/scroll-area.tsx +32 -0
  180. package/src/renderers/complex/table.tsx +86 -0
  181. package/src/renderers/complex/timeline.tsx +466 -0
  182. package/src/renderers/data-display/alert.tsx +37 -0
  183. package/src/renderers/data-display/avatar.tsx +29 -0
  184. package/src/renderers/data-display/badge.tsx +46 -0
  185. package/src/renderers/data-display/index.ts +6 -0
  186. package/src/renderers/data-display/list.tsx +95 -0
  187. package/src/renderers/data-display/statistic.tsx +98 -0
  188. package/src/renderers/data-display/tree-view.tsx +180 -0
  189. package/src/renderers/disclosure/accordion.tsx +60 -0
  190. package/src/renderers/disclosure/collapsible.tsx +44 -0
  191. package/src/renderers/disclosure/index.ts +2 -0
  192. package/src/renderers/feedback/index.ts +4 -0
  193. package/src/renderers/feedback/loading.tsx +69 -0
  194. package/src/renderers/feedback/progress.tsx +20 -0
  195. package/src/renderers/feedback/skeleton.tsx +22 -0
  196. package/src/renderers/feedback/toaster.tsx +26 -0
  197. package/src/renderers/form/button.tsx +61 -0
  198. package/src/renderers/form/calendar.tsx +25 -0
  199. package/src/renderers/form/checkbox.tsx +41 -0
  200. package/src/renderers/form/date-picker.tsx +75 -0
  201. package/src/renderers/form/file-upload.tsx +175 -0
  202. package/src/renderers/form/form.tsx +417 -0
  203. package/src/renderers/form/index.ts +16 -0
  204. package/src/renderers/form/input-otp.tsx +31 -0
  205. package/src/renderers/form/input.tsx +79 -0
  206. package/src/renderers/form/label.tsx +36 -0
  207. package/src/renderers/form/radio-group.tsx +54 -0
  208. package/src/renderers/form/select.tsx +66 -0
  209. package/src/renderers/form/slider.tsx +45 -0
  210. package/src/renderers/form/switch.tsx +39 -0
  211. package/src/renderers/form/textarea.tsx +45 -0
  212. package/src/renderers/form/toggle.tsx +76 -0
  213. package/src/renderers/index.ts +9 -0
  214. package/src/renderers/layout/card.tsx +69 -0
  215. package/src/renderers/layout/container.tsx +113 -0
  216. package/src/renderers/layout/flex.tsx +123 -0
  217. package/src/renderers/layout/grid.tsx +155 -0
  218. package/src/renderers/layout/index.ts +10 -0
  219. package/src/renderers/layout/page.tsx +82 -0
  220. package/src/renderers/layout/semantic.tsx +39 -0
  221. package/src/renderers/layout/stack.tsx +123 -0
  222. package/src/renderers/layout/tabs.tsx +63 -0
  223. package/src/renderers/navigation/header-bar.tsx +50 -0
  224. package/src/renderers/navigation/index.ts +2 -0
  225. package/src/renderers/navigation/sidebar.tsx +189 -0
  226. package/src/renderers/overlay/alert-dialog.tsx +63 -0
  227. package/src/renderers/overlay/context-menu.tsx +91 -0
  228. package/src/renderers/overlay/dialog.tsx +68 -0
  229. package/src/renderers/overlay/drawer.tsx +68 -0
  230. package/src/renderers/overlay/dropdown-menu.tsx +90 -0
  231. package/src/renderers/overlay/hover-card.tsx +46 -0
  232. package/src/renderers/overlay/index.ts +9 -0
  233. package/src/renderers/overlay/popover.tsx +47 -0
  234. package/src/renderers/overlay/sheet.tsx +68 -0
  235. package/src/renderers/overlay/tooltip.tsx +58 -0
  236. package/src/ui/accordion.tsx +64 -0
  237. package/src/ui/alert-dialog.tsx +155 -0
  238. package/src/ui/alert.tsx +78 -0
  239. package/src/ui/aspect-ratio.tsx +11 -0
  240. package/src/ui/avatar.tsx +51 -0
  241. package/src/ui/badge.tsx +46 -0
  242. package/src/ui/breadcrumb.tsx +109 -0
  243. package/src/ui/button-group.tsx +83 -0
  244. package/src/ui/button.tsx +65 -0
  245. package/src/ui/calendar-view.tsx +503 -0
  246. package/src/ui/calendar.tsx +237 -0
  247. package/src/ui/card.tsx +138 -0
  248. package/src/ui/carousel.tsx +239 -0
  249. package/src/ui/chatbot.tsx +240 -0
  250. package/src/ui/checkbox.tsx +32 -0
  251. package/src/ui/collapsible.tsx +31 -0
  252. package/src/ui/command.tsx +182 -0
  253. package/src/ui/context-menu.tsx +247 -0
  254. package/src/ui/dialog.tsx +141 -0
  255. package/src/ui/drawer.tsx +135 -0
  256. package/src/ui/dropdown-menu.tsx +254 -0
  257. package/src/ui/empty.tsx +104 -0
  258. package/src/ui/field.tsx +246 -0
  259. package/src/ui/filter-builder.tsx +359 -0
  260. package/src/ui/form.tsx +167 -0
  261. package/src/ui/hover-card.tsx +44 -0
  262. package/src/ui/index.ts +56 -0
  263. package/src/ui/input-group.tsx +170 -0
  264. package/src/ui/input-otp.tsx +81 -0
  265. package/src/ui/input.tsx +24 -0
  266. package/src/ui/item.tsx +193 -0
  267. package/src/ui/kbd.tsx +28 -0
  268. package/src/ui/label.tsx +24 -0
  269. package/src/ui/menubar.tsx +274 -0
  270. package/src/ui/navigation-menu.tsx +168 -0
  271. package/src/ui/pagination.tsx +127 -0
  272. package/src/ui/popover.tsx +48 -0
  273. package/src/ui/progress.tsx +41 -0
  274. package/src/ui/radio-group.tsx +45 -0
  275. package/src/ui/resizable.tsx +55 -0
  276. package/src/ui/scroll-area.tsx +58 -0
  277. package/src/ui/select.tsx +188 -0
  278. package/src/ui/separator.tsx +31 -0
  279. package/src/ui/sheet.tsx +137 -0
  280. package/src/ui/sidebar.tsx +726 -0
  281. package/src/ui/skeleton.tsx +20 -0
  282. package/src/ui/slider.tsx +63 -0
  283. package/src/ui/sonner.tsx +43 -0
  284. package/src/ui/spinner.tsx +38 -0
  285. package/src/ui/switch.tsx +31 -0
  286. package/src/ui/table.tsx +120 -0
  287. package/src/ui/tabs.tsx +86 -0
  288. package/src/ui/textarea.tsx +18 -0
  289. package/src/ui/timeline.tsx +266 -0
  290. package/src/ui/toggle-group.tsx +87 -0
  291. package/src/ui/toggle.tsx +50 -0
  292. package/src/ui/tooltip.tsx +61 -0
  293. package/tailwind.config.js +75 -0
  294. package/tsconfig.json +18 -0
  295. package/vite.config.ts +44 -0
@@ -0,0 +1,237 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import {
5
+ ChevronDownIcon,
6
+ ChevronLeftIcon,
7
+ ChevronRightIcon,
8
+ } from "lucide-react"
9
+ import {
10
+ DayPicker,
11
+ getDefaultClassNames,
12
+ type DayButton,
13
+ } from "react-day-picker"
14
+
15
+ import { cn } from "../lib/utils"
16
+ import { Button, buttonVariants } from "./button"
17
+
18
+ function Calendar({
19
+ className,
20
+ classNames,
21
+ showOutsideDays = true,
22
+ captionLayout = "label",
23
+ buttonVariant = "ghost",
24
+ formatters,
25
+ components,
26
+ ...props
27
+ }: React.ComponentProps<typeof DayPicker> & {
28
+ buttonVariant?: React.ComponentProps<typeof Button>["variant"]
29
+ }) {
30
+ const defaultClassNames = getDefaultClassNames()
31
+
32
+ return (
33
+ <DayPicker
34
+ showOutsideDays={showOutsideDays}
35
+ className={cn(
36
+ "bg-[#0a0a0b] bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))] from-violet-900/20 via-slate-950/80 to-black backdrop-blur-3xl border border-violet-500/20 shadow-[0_0_50px_-12px_rgba(124,58,237,0.25)] rounded-xl group/calendar p-4 [--cell-size:--spacing(9)]",
37
+ "before:absolute before:inset-0 before:rounded-xl before:bg-[url('https://grainy-gradients.vercel.app/noise.svg')] before:opacity-10 before:pointer-events-none",
38
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
39
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
40
+ className
41
+ )}
42
+ captionLayout={captionLayout}
43
+ formatters={{
44
+ formatMonthDropdown: (date) =>
45
+ date.toLocaleString("default", { month: "short" }),
46
+ ...formatters,
47
+ }}
48
+ classNames={{
49
+ root: cn("w-fit relative overflow-hidden", defaultClassNames.root),
50
+ months: cn(
51
+ "flex gap-4 flex-col md:flex-row relative z-10",
52
+ defaultClassNames.months
53
+ ),
54
+ month: cn("flex flex-col w-full gap-4", defaultClassNames.month),
55
+ nav: cn(
56
+ "flex items-center gap-1 w-full absolute top-0 inset-x-0 justify-between px-1",
57
+ defaultClassNames.nav
58
+ ),
59
+ button_previous: cn(
60
+ buttonVariants({ variant: "outline", size: "icon-sm" }),
61
+ "z-20 bg-slate-900/80 border-violet-800/50 text-violet-400 hover:bg-violet-900/40 hover:text-violet-100 hover:border-violet-500 hover:shadow-[0_0_15px_rgba(139,92,246,0.5)] transition-all duration-300 rounded-full",
62
+ defaultClassNames.button_previous
63
+ ),
64
+ button_next: cn(
65
+ buttonVariants({ variant: "outline", size: "icon-sm" }),
66
+ "z-20 bg-slate-900/80 border-violet-800/50 text-violet-400 hover:bg-violet-900/40 hover:text-violet-100 hover:border-violet-500 hover:shadow-[0_0_15px_rgba(139,92,246,0.5)] transition-all duration-300 rounded-full",
67
+ defaultClassNames.button_next
68
+ ),
69
+ month_caption: cn(
70
+ "flex items-center justify-center h-(--cell-size) w-full px-(--cell-size) text-transparent bg-clip-text bg-linear-to-r from-violet-200 via-cyan-200 to-violet-200 font-bold tracking-[0.2em] relative uppercase text-lg",
71
+ defaultClassNames.month_caption
72
+ ),
73
+ dropdowns: cn(
74
+ "w-full flex items-center text-sm font-medium justify-center h-(--cell-size) gap-1.5",
75
+ defaultClassNames.dropdowns
76
+ ),
77
+ dropdown_root: cn(
78
+ "relative has-focus:border-violet-500 border border-violet-900/50 shadow-xs has-focus:ring-violet-500/30 has-focus:ring-[2px] rounded-md bg-slate-950 text-violet-200",
79
+ defaultClassNames.dropdown_root
80
+ ),
81
+ dropdown: cn(
82
+ "absolute bg-slate-950 inset-0 opacity-0",
83
+ defaultClassNames.dropdown
84
+ ),
85
+ caption_label: cn(
86
+ "select-none font-medium",
87
+ captionLayout === "label"
88
+ ? "text-sm"
89
+ : "rounded-md pl-2 pr-1 flex items-center gap-1 text-sm h-8 [&>svg]:text-muted-foreground [&>svg]:size-3.5",
90
+ defaultClassNames.caption_label
91
+ ),
92
+ table: "w-full border-collapse",
93
+ weekdays: cn("flex my-2", defaultClassNames.weekdays),
94
+ weekday: cn(
95
+ "text-violet-500/70 rounded-md flex-1 font-mono text-[0.65rem] uppercase tracking-widest select-none pb-2",
96
+ defaultClassNames.weekday
97
+ ),
98
+ week: cn("flex w-full mt-1", defaultClassNames.week),
99
+ week_number_header: cn(
100
+ "select-none w-(--cell-size)",
101
+ defaultClassNames.week_number_header
102
+ ),
103
+ week_number: cn(
104
+ "text-[0.8rem] select-none text-muted-foreground",
105
+ defaultClassNames.week_number
106
+ ),
107
+ day: cn(
108
+ "relative w-full h-full p-0 text-center group/day aspect-square select-none",
109
+ defaultClassNames.day
110
+ ),
111
+ range_start: cn(
112
+ "rounded-l-full bg-violet-900/20",
113
+ defaultClassNames.range_start
114
+ ),
115
+ range_middle: cn("rounded-none bg-violet-900/10", defaultClassNames.range_middle),
116
+ range_end: cn("rounded-r-full bg-violet-900/20", defaultClassNames.range_end),
117
+ today: cn(
118
+ "text-cyan-400 font-bold", // Styling handled in DayButton mostly
119
+ defaultClassNames.today
120
+ ),
121
+ outside: cn(
122
+ "text-slate-800 opacity-30 aria-selected:text-slate-800",
123
+ defaultClassNames.outside
124
+ ),
125
+ disabled: cn(
126
+ "text-slate-800 opacity-20",
127
+ defaultClassNames.disabled
128
+ ),
129
+ hidden: cn("invisible", defaultClassNames.hidden),
130
+ ...classNames,
131
+ }}
132
+ components={{
133
+ Root: ({ className, rootRef, ...props }) => {
134
+ return (
135
+ <div
136
+ data-slot="calendar"
137
+ ref={rootRef}
138
+ className={cn(className)}
139
+ {...props}
140
+ />
141
+ )
142
+ },
143
+ Chevron: ({ className, orientation, ...props }) => {
144
+ if (orientation === "left") {
145
+ return (
146
+ <ChevronLeftIcon className={cn("size-4", className)} {...props} />
147
+ )
148
+ }
149
+
150
+ if (orientation === "right") {
151
+ return (
152
+ <ChevronRightIcon
153
+ className={cn("size-4", className)}
154
+ {...props}
155
+ />
156
+ )
157
+ }
158
+
159
+ return (
160
+ <ChevronDownIcon className={cn("size-4", className)} {...props} />
161
+ )
162
+ },
163
+ DayButton: CalendarDayButton,
164
+ WeekNumber: ({ children, ...props }) => {
165
+ return (
166
+ <td {...props}>
167
+ <div className="flex size-(--cell-size) items-center justify-center text-center">
168
+ {children}
169
+ </div>
170
+ </td>
171
+ )
172
+ },
173
+ ...components,
174
+ }}
175
+ {...props}
176
+ />
177
+ )
178
+ }
179
+
180
+ function CalendarDayButton({
181
+ className,
182
+ day,
183
+ modifiers,
184
+ ...props
185
+ }: React.ComponentProps<typeof DayButton>) {
186
+ const defaultClassNames = getDefaultClassNames()
187
+
188
+ const ref = React.useRef<HTMLButtonElement>(null)
189
+ React.useEffect(() => {
190
+ if (modifiers.focused) ref.current?.focus()
191
+ }, [modifiers.focused])
192
+
193
+ return (
194
+ <Button
195
+ ref={ref}
196
+ variant="ghost"
197
+ size="icon"
198
+ data-day={day.date.toLocaleDateString()}
199
+ data-selected-single={
200
+ modifiers.selected &&
201
+ !modifiers.range_start &&
202
+ !modifiers.range_end &&
203
+ !modifiers.range_middle
204
+ }
205
+ data-range-start={modifiers.range_start}
206
+ data-range-end={modifiers.range_end}
207
+ data-range-middle={modifiers.range_middle}
208
+ className={cn(
209
+ "data-[selected-single=true]:bg-violet-600 data-[selected-single=true]:text-white data-[selected-single=true]:shadow-[0_0_20px_rgba(124,58,237,0.8)] data-[selected-single=true]:border-violet-400 data-[selected-single=true]:scale-110 data-[selected-single=true]:z-10",
210
+
211
+ "data-[range-middle=true]:bg-transparent data-[range-middle=true]:text-violet-200",
212
+
213
+ "data-[range-start=true]:bg-violet-600 data-[range-start=true]:text-white data-[range-start=true]:shadow-[0_0_15px_rgba(124,58,237,0.5)] data-[range-start=true]:z-10",
214
+
215
+ "data-[range-end=true]:bg-violet-600 data-[range-end=true]:text-white data-[range-end=true]:shadow-[0_0_15px_rgba(124,58,237,0.5)] data-[range-end=true]:z-10",
216
+
217
+ // Today state (Current Timeline)
218
+ "data-[today=true]:border data-[today=true]:border-cyan-500/50 data-[today=true]:text-cyan-300 data-[today=true]:shadow-[0_0_10px_rgba(6,182,212,0.3)]",
219
+
220
+ // Base hover & focus
221
+ "group-data-[focused=true]/day:border-violet-400 group-data-[focused=true]/day:ring-violet-500/50",
222
+ "hover:bg-violet-900/30 hover:text-white hover:scale-125 hover:z-20 hover:shadow-[0_0_15px_rgba(139,92,246,0.5)] transition-all duration-300",
223
+
224
+ "bg-transparent flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal rounded-full",
225
+
226
+ "group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[2px]",
227
+
228
+ "text-violet-300/80 [&>span]:text-xs [&>span]:opacity-70",
229
+ defaultClassNames.day,
230
+ className
231
+ )}
232
+ {...props}
233
+ />
234
+ )
235
+ }
236
+
237
+ export { Calendar, CalendarDayButton }
@@ -0,0 +1,138 @@
1
+ import * as React from "react"
2
+
3
+ import { cn } from "../lib/utils"
4
+
5
+ const Card = React.forwardRef<
6
+ HTMLDivElement,
7
+ React.ComponentProps<"div">
8
+ >(({ className, ...props }, ref) => {
9
+ return (
10
+ <div
11
+ ref={ref}
12
+ data-slot="card"
13
+ className={cn(
14
+ "bg-card/90 dark:bg-card/40 backdrop-blur-md text-card-foreground flex flex-col gap-6 rounded-xl border border-cyan-500/20 py-6 shadow-[0_0_30px_-10px_rgba(6,182,212,0.15)] transition-all duration-300 hover:shadow-[0_0_40px_-10px_rgba(6,182,212,0.3)] hover:border-cyan-500/40 relative overflow-hidden",
15
+ className
16
+ )}
17
+ {...props}
18
+ >
19
+ {/* Decorative corner accents */}
20
+ <div className="absolute top-0 left-0 w-2 h-2 border-t border-l border-cyan-500/50 rounded-tl-sm" />
21
+ <div className="absolute top-0 right-0 w-2 h-2 border-t border-r border-cyan-500/50 rounded-tr-sm" />
22
+ <div className="absolute bottom-0 left-0 w-2 h-2 border-b border-l border-cyan-500/50 rounded-bl-sm" />
23
+ <div className="absolute bottom-0 right-0 w-2 h-2 border-b border-r border-cyan-500/50 rounded-br-sm" />
24
+
25
+ {/* Content */}
26
+ <div className="relative z-10 flex flex-col gap-6 h-full">
27
+ {props.children}
28
+ </div>
29
+ </div>
30
+ )
31
+ })
32
+ Card.displayName = "Card"
33
+
34
+ const CardHeader = React.forwardRef<
35
+ HTMLDivElement,
36
+ React.ComponentProps<"div">
37
+ >(({ className, ...props }, ref) => {
38
+ return (
39
+ <div
40
+ ref={ref}
41
+ data-slot="card-header"
42
+ className={cn(
43
+ "@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",
44
+ className
45
+ )}
46
+ {...props}
47
+ />
48
+ )
49
+ })
50
+ CardHeader.displayName = "CardHeader"
51
+
52
+ const CardTitle = React.forwardRef<
53
+ HTMLDivElement,
54
+ React.ComponentProps<"div">
55
+ >(({ className, ...props }, ref) => {
56
+ return (
57
+ <div
58
+ ref={ref}
59
+ data-slot="card-title"
60
+ className={cn("leading-none font-semibold", className)}
61
+ {...props}
62
+ />
63
+ )
64
+ })
65
+ CardTitle.displayName = "CardTitle"
66
+
67
+ const CardDescription = React.forwardRef<
68
+ HTMLDivElement,
69
+ React.ComponentProps<"div">
70
+ >(({ className, ...props }, ref) => {
71
+ return (
72
+ <div
73
+ ref={ref}
74
+ data-slot="card-description"
75
+ className={cn("text-muted-foreground text-sm", className)}
76
+ {...props}
77
+ />
78
+ )
79
+ })
80
+ CardDescription.displayName = "CardDescription"
81
+
82
+ const CardAction = React.forwardRef<
83
+ HTMLDivElement,
84
+ React.ComponentProps<"div">
85
+ >(({ className, ...props }, ref) => {
86
+ return (
87
+ <div
88
+ ref={ref}
89
+ data-slot="card-action"
90
+ className={cn(
91
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
92
+ className
93
+ )}
94
+ {...props}
95
+ />
96
+ )
97
+ })
98
+ CardAction.displayName = "CardAction"
99
+
100
+ const CardContent = React.forwardRef<
101
+ HTMLDivElement,
102
+ React.ComponentProps<"div">
103
+ >(({ className, ...props }, ref) => {
104
+ return (
105
+ <div
106
+ ref={ref}
107
+ data-slot="card-content"
108
+ className={cn("px-6", className)}
109
+ {...props}
110
+ />
111
+ )
112
+ })
113
+ CardContent.displayName = "CardContent"
114
+
115
+ const CardFooter = React.forwardRef<
116
+ HTMLDivElement,
117
+ React.ComponentProps<"div">
118
+ >(({ className, ...props }, ref) => {
119
+ return (
120
+ <div
121
+ ref={ref}
122
+ data-slot="card-footer"
123
+ className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
124
+ {...props}
125
+ />
126
+ )
127
+ })
128
+ CardFooter.displayName = "CardFooter"
129
+
130
+ export {
131
+ Card,
132
+ CardHeader,
133
+ CardFooter,
134
+ CardTitle,
135
+ CardAction,
136
+ CardDescription,
137
+ CardContent,
138
+ }
@@ -0,0 +1,239 @@
1
+ import * as React from "react"
2
+ import useEmblaCarousel, {
3
+ type UseEmblaCarouselType,
4
+ } from "embla-carousel-react"
5
+ import { ArrowLeft, ArrowRight } from "lucide-react"
6
+
7
+ import { cn } from "../lib/utils"
8
+ import { Button } from "./button"
9
+
10
+ type CarouselApi = UseEmblaCarouselType[1]
11
+ type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
12
+ type CarouselOptions = UseCarouselParameters[0]
13
+ type CarouselPlugin = UseCarouselParameters[1]
14
+
15
+ type CarouselProps = {
16
+ opts?: CarouselOptions
17
+ plugins?: CarouselPlugin
18
+ orientation?: "horizontal" | "vertical"
19
+ setApi?: (api: CarouselApi) => void
20
+ }
21
+
22
+ type CarouselContextProps = {
23
+ carouselRef: ReturnType<typeof useEmblaCarousel>[0]
24
+ api: ReturnType<typeof useEmblaCarousel>[1]
25
+ scrollPrev: () => void
26
+ scrollNext: () => void
27
+ canScrollPrev: boolean
28
+ canScrollNext: boolean
29
+ } & CarouselProps
30
+
31
+ const CarouselContext = React.createContext<CarouselContextProps | null>(null)
32
+
33
+ function useCarousel() {
34
+ const context = React.useContext(CarouselContext)
35
+
36
+ if (!context) {
37
+ throw new Error("useCarousel must be used within a <Carousel />")
38
+ }
39
+
40
+ return context
41
+ }
42
+
43
+ function Carousel({
44
+ orientation = "horizontal",
45
+ opts,
46
+ setApi,
47
+ plugins,
48
+ className,
49
+ children,
50
+ ...props
51
+ }: React.ComponentProps<"div"> & CarouselProps) {
52
+ const [carouselRef, api] = useEmblaCarousel(
53
+ {
54
+ ...opts,
55
+ axis: orientation === "horizontal" ? "x" : "y",
56
+ },
57
+ plugins
58
+ )
59
+ const [canScrollPrev, setCanScrollPrev] = React.useState(false)
60
+ const [canScrollNext, setCanScrollNext] = React.useState(false)
61
+
62
+ const onSelect = React.useCallback((api: CarouselApi) => {
63
+ if (!api) return
64
+ setCanScrollPrev(api.canScrollPrev())
65
+ setCanScrollNext(api.canScrollNext())
66
+ }, [])
67
+
68
+ const scrollPrev = React.useCallback(() => {
69
+ api?.scrollPrev()
70
+ }, [api])
71
+
72
+ const scrollNext = React.useCallback(() => {
73
+ api?.scrollNext()
74
+ }, [api])
75
+
76
+ const handleKeyDown = React.useCallback(
77
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
78
+ if (event.key === "ArrowLeft") {
79
+ event.preventDefault()
80
+ scrollPrev()
81
+ } else if (event.key === "ArrowRight") {
82
+ event.preventDefault()
83
+ scrollNext()
84
+ }
85
+ },
86
+ [scrollPrev, scrollNext]
87
+ )
88
+
89
+ React.useEffect(() => {
90
+ if (!api || !setApi) return
91
+ setApi(api)
92
+ }, [api, setApi])
93
+
94
+ React.useEffect(() => {
95
+ if (!api) return
96
+ onSelect(api)
97
+ api.on("reInit", onSelect)
98
+ api.on("select", onSelect)
99
+
100
+ return () => {
101
+ api?.off("select", onSelect)
102
+ }
103
+ }, [api, onSelect])
104
+
105
+ return (
106
+ <CarouselContext.Provider
107
+ value={{
108
+ carouselRef,
109
+ api: api,
110
+ opts,
111
+ orientation:
112
+ orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
113
+ scrollPrev,
114
+ scrollNext,
115
+ canScrollPrev,
116
+ canScrollNext,
117
+ }}
118
+ >
119
+ <div
120
+ onKeyDownCapture={handleKeyDown}
121
+ className={cn("relative", className)}
122
+ role="region"
123
+ aria-roledescription="carousel"
124
+ data-slot="carousel"
125
+ {...props}
126
+ >
127
+ {children}
128
+ </div>
129
+ </CarouselContext.Provider>
130
+ )
131
+ }
132
+
133
+ function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {
134
+ const { carouselRef, orientation } = useCarousel()
135
+
136
+ return (
137
+ <div
138
+ ref={carouselRef}
139
+ className="overflow-hidden"
140
+ data-slot="carousel-content"
141
+ >
142
+ <div
143
+ className={cn(
144
+ "flex",
145
+ orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
146
+ className
147
+ )}
148
+ {...props}
149
+ />
150
+ </div>
151
+ )
152
+ }
153
+
154
+ function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {
155
+ const { orientation } = useCarousel()
156
+
157
+ return (
158
+ <div
159
+ role="group"
160
+ aria-roledescription="slide"
161
+ data-slot="carousel-item"
162
+ className={cn(
163
+ "min-w-0 shrink-0 grow-0 basis-full",
164
+ orientation === "horizontal" ? "pl-4" : "pt-4",
165
+ className
166
+ )}
167
+ {...props}
168
+ />
169
+ )
170
+ }
171
+
172
+ function CarouselPrevious({
173
+ className,
174
+ variant = "outline",
175
+ size = "icon",
176
+ ...props
177
+ }: React.ComponentProps<typeof Button>) {
178
+ const { orientation, scrollPrev, canScrollPrev } = useCarousel()
179
+
180
+ return (
181
+ <Button
182
+ data-slot="carousel-previous"
183
+ variant={variant}
184
+ size={size}
185
+ className={cn(
186
+ "absolute size-8 rounded-full",
187
+ orientation === "horizontal"
188
+ ? "top-1/2 -left-12 -translate-y-1/2"
189
+ : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
190
+ className
191
+ )}
192
+ disabled={!canScrollPrev}
193
+ onClick={scrollPrev}
194
+ {...props}
195
+ >
196
+ <ArrowLeft />
197
+ <span className="sr-only">Previous slide</span>
198
+ </Button>
199
+ )
200
+ }
201
+
202
+ function CarouselNext({
203
+ className,
204
+ variant = "outline",
205
+ size = "icon",
206
+ ...props
207
+ }: React.ComponentProps<typeof Button>) {
208
+ const { orientation, scrollNext, canScrollNext } = useCarousel()
209
+
210
+ return (
211
+ <Button
212
+ data-slot="carousel-next"
213
+ variant={variant}
214
+ size={size}
215
+ className={cn(
216
+ "absolute size-8 rounded-full",
217
+ orientation === "horizontal"
218
+ ? "top-1/2 -right-12 -translate-y-1/2"
219
+ : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
220
+ className
221
+ )}
222
+ disabled={!canScrollNext}
223
+ onClick={scrollNext}
224
+ {...props}
225
+ >
226
+ <ArrowRight />
227
+ <span className="sr-only">Next slide</span>
228
+ </Button>
229
+ )
230
+ }
231
+
232
+ export {
233
+ type CarouselApi,
234
+ Carousel,
235
+ CarouselContent,
236
+ CarouselItem,
237
+ CarouselPrevious,
238
+ CarouselNext,
239
+ }