@mbao01/common 0.8.0 → 0.9.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 (276) hide show
  1. package/dist/types/components/ActivityFeed/ActivityFeed.d.ts +6 -0
  2. package/dist/types/components/ActivityFeed/constants.d.ts +6 -0
  3. package/dist/types/components/ActivityFeed/index.d.ts +2 -0
  4. package/dist/types/components/ActivityFeed/types.d.ts +21 -0
  5. package/dist/types/components/Amount/Amount.d.ts +6 -0
  6. package/dist/types/components/Amount/index.d.ts +2 -0
  7. package/dist/types/components/Amount/types.d.ts +19 -0
  8. package/dist/types/components/AnimatedCounter/AnimatedCounter.d.ts +6 -0
  9. package/dist/types/components/AnimatedCounter/index.d.ts +2 -0
  10. package/dist/types/components/AnimatedCounter/types.d.ts +13 -0
  11. package/dist/types/components/AnimatedGroup/AnimatedGroup.d.ts +6 -0
  12. package/dist/types/components/AnimatedGroup/index.d.ts +2 -0
  13. package/dist/types/components/AnimatedGroup/types.d.ts +22 -0
  14. package/dist/types/components/AnimatedList/AnimatedList.d.ts +6 -0
  15. package/dist/types/components/AnimatedList/index.d.ts +2 -0
  16. package/dist/types/components/AnimatedList/types.d.ts +13 -0
  17. package/dist/types/components/BorderBeam/BorderBeam.d.ts +6 -0
  18. package/dist/types/components/BorderBeam/index.d.ts +2 -0
  19. package/dist/types/components/BorderBeam/types.d.ts +13 -0
  20. package/dist/types/components/Box/Box.d.ts +4 -0
  21. package/dist/types/components/Box/constants.d.ts +4 -0
  22. package/dist/types/components/CalendarHeatmap/CalendarHeatmap.d.ts +6 -0
  23. package/dist/types/components/CalendarHeatmap/index.d.ts +2 -0
  24. package/dist/types/components/CalendarHeatmap/types.d.ts +25 -0
  25. package/dist/types/components/Chart/components/ChartLegend.d.ts +1 -2
  26. package/dist/types/components/Chart/stories/args/index.d.ts +1 -1
  27. package/dist/types/components/Chart/stories/examples/AreaChart.d.ts +6 -0
  28. package/dist/types/components/Chart/stories/examples/BarChart.d.ts +11 -0
  29. package/dist/types/components/Chart/stories/examples/LineChart.d.ts +10 -0
  30. package/dist/types/components/Chart/stories/examples/PieChart.d.ts +5 -0
  31. package/dist/types/components/Chart/stories/examples/RadialChart.d.ts +5 -0
  32. package/dist/types/components/Chart/types.d.ts +1 -1
  33. package/dist/types/components/CircularProgress/CircularProgress.d.ts +6 -0
  34. package/dist/types/components/CircularProgress/constants.d.ts +5 -0
  35. package/dist/types/components/CircularProgress/index.d.ts +2 -0
  36. package/dist/types/components/CircularProgress/types.d.ts +17 -0
  37. package/dist/types/components/ComparisonBar/ComparisonBar.d.ts +6 -0
  38. package/dist/types/components/ComparisonBar/constants.d.ts +4 -0
  39. package/dist/types/components/ComparisonBar/index.d.ts +2 -0
  40. package/dist/types/components/ComparisonBar/types.d.ts +21 -0
  41. package/dist/types/components/Confetti/Confetti.d.ts +6 -0
  42. package/dist/types/components/Confetti/index.d.ts +2 -0
  43. package/dist/types/components/Confetti/types.d.ts +19 -0
  44. package/dist/types/components/CountdownTimer/CountdownTimer.d.ts +6 -0
  45. package/dist/types/components/CountdownTimer/index.d.ts +2 -0
  46. package/dist/types/components/CountdownTimer/types.d.ts +13 -0
  47. package/dist/types/components/DataList/DataList.d.ts +6 -0
  48. package/dist/types/components/DataList/constants.d.ts +12 -0
  49. package/dist/types/components/DataList/index.d.ts +2 -0
  50. package/dist/types/components/DataList/types.d.ts +15 -0
  51. package/dist/types/components/DatePicker/DateRangePresetPicker.d.ts +2 -0
  52. package/dist/types/components/DatePicker/index.d.ts +1 -0
  53. package/dist/types/components/DatePicker/types.d.ts +19 -0
  54. package/dist/types/components/Description/Description.d.ts +2 -1
  55. package/dist/types/components/Description/DescriptionGroup.d.ts +6 -0
  56. package/dist/types/components/Description/constants.d.ts +23 -0
  57. package/dist/types/components/Description/index.d.ts +2 -0
  58. package/dist/types/components/Description/types.d.ts +28 -3
  59. package/dist/types/components/Form/DatetimeInput/DatetimeInput.d.ts +1 -1
  60. package/dist/types/components/GlowCard/GlowCard.d.ts +6 -0
  61. package/dist/types/components/GlowCard/index.d.ts +2 -0
  62. package/dist/types/components/GlowCard/types.d.ts +8 -0
  63. package/dist/types/components/GradientText/GradientText.d.ts +6 -0
  64. package/dist/types/components/GradientText/index.d.ts +2 -0
  65. package/dist/types/components/GradientText/types.d.ts +14 -0
  66. package/dist/types/components/Greeting/Greeting.d.ts +6 -0
  67. package/dist/types/components/Greeting/index.d.ts +2 -0
  68. package/dist/types/components/Greeting/types.d.ts +9 -0
  69. package/dist/types/components/KPICard/KPICard.d.ts +6 -0
  70. package/dist/types/components/KPICard/index.d.ts +2 -0
  71. package/dist/types/components/KPICard/types.d.ts +21 -0
  72. package/dist/types/components/Marquee/Marquee.d.ts +6 -0
  73. package/dist/types/components/Marquee/index.d.ts +2 -0
  74. package/dist/types/components/Marquee/types.d.ts +12 -0
  75. package/dist/types/components/Meteors/Meteors.d.ts +6 -0
  76. package/dist/types/components/Meteors/index.d.ts +2 -0
  77. package/dist/types/components/Meteors/types.d.ts +5 -0
  78. package/dist/types/components/MiniAreaChart/MiniAreaChart.d.ts +6 -0
  79. package/dist/types/components/MiniAreaChart/index.d.ts +2 -0
  80. package/dist/types/components/MiniAreaChart/types.d.ts +10 -0
  81. package/dist/types/components/MiniBarChart/MiniBarChart.d.ts +6 -0
  82. package/dist/types/components/MiniBarChart/index.d.ts +2 -0
  83. package/dist/types/components/MiniBarChart/types.d.ts +15 -0
  84. package/dist/types/components/MiniDonutChart/MiniDonutChart.d.ts +6 -0
  85. package/dist/types/components/MiniDonutChart/index.d.ts +2 -0
  86. package/dist/types/components/MiniDonutChart/types.d.ts +15 -0
  87. package/dist/types/components/MiniStackedBar/MiniStackedBar.d.ts +6 -0
  88. package/dist/types/components/MiniStackedBar/index.d.ts +2 -0
  89. package/dist/types/components/MiniStackedBar/types.d.ts +13 -0
  90. package/dist/types/components/NumberTicker/NumberTicker.d.ts +6 -0
  91. package/dist/types/components/NumberTicker/index.d.ts +2 -0
  92. package/dist/types/components/NumberTicker/types.d.ts +11 -0
  93. package/dist/types/components/Pulse/Pulse.d.ts +6 -0
  94. package/dist/types/components/Pulse/constants.d.ts +10 -0
  95. package/dist/types/components/Pulse/index.d.ts +2 -0
  96. package/dist/types/components/Pulse/types.d.ts +11 -0
  97. package/dist/types/components/Resizable/Resizable.d.ts +1 -1
  98. package/dist/types/components/ShinyButton/ShinyButton.d.ts +6 -0
  99. package/dist/types/components/ShinyButton/index.d.ts +2 -0
  100. package/dist/types/components/ShinyButton/types.d.ts +4 -0
  101. package/dist/types/components/Sparkline/Sparkline.d.ts +6 -0
  102. package/dist/types/components/Sparkline/index.d.ts +2 -0
  103. package/dist/types/components/Sparkline/types.d.ts +17 -0
  104. package/dist/types/components/SpotlightCard/SpotlightCard.d.ts +6 -0
  105. package/dist/types/components/SpotlightCard/index.d.ts +2 -0
  106. package/dist/types/components/SpotlightCard/types.d.ts +7 -0
  107. package/dist/types/components/StatCard/StatCard.d.ts +6 -0
  108. package/dist/types/components/StatCard/index.d.ts +2 -0
  109. package/dist/types/components/StatCard/types.d.ts +15 -0
  110. package/dist/types/components/TextShimmer/TextShimmer.d.ts +6 -0
  111. package/dist/types/components/TextShimmer/index.d.ts +2 -0
  112. package/dist/types/components/TextShimmer/types.d.ts +7 -0
  113. package/dist/types/components/TrendBadge/TrendBadge.d.ts +6 -0
  114. package/dist/types/components/TrendBadge/constants.d.ts +7 -0
  115. package/dist/types/components/TrendBadge/index.d.ts +2 -0
  116. package/dist/types/components/TrendBadge/types.d.ts +15 -0
  117. package/dist/types/components/WidgetShell/WidgetShell.d.ts +6 -0
  118. package/dist/types/components/WidgetShell/index.d.ts +2 -0
  119. package/dist/types/components/WidgetShell/types.d.ts +20 -0
  120. package/dist/types/index.d.ts +33 -0
  121. package/package.json +58 -58
  122. package/src/components/Accordion/constants.ts +1 -1
  123. package/src/components/ActivityFeed/ActivityFeed.tsx +51 -0
  124. package/src/components/ActivityFeed/constants.ts +19 -0
  125. package/src/components/ActivityFeed/index.ts +2 -0
  126. package/src/components/ActivityFeed/types.ts +23 -0
  127. package/src/components/Alert/constants.ts +1 -1
  128. package/src/components/AlertDialog/constants.ts +1 -1
  129. package/src/components/Amount/Amount.tsx +50 -0
  130. package/src/components/Amount/index.ts +2 -0
  131. package/src/components/Amount/types.ts +20 -0
  132. package/src/components/AnimatedCounter/AnimatedCounter.tsx +68 -0
  133. package/src/components/AnimatedCounter/index.ts +2 -0
  134. package/src/components/AnimatedCounter/types.ts +14 -0
  135. package/src/components/AnimatedGroup/AnimatedGroup.tsx +97 -0
  136. package/src/components/AnimatedGroup/index.ts +2 -0
  137. package/src/components/AnimatedGroup/types.ts +21 -0
  138. package/src/components/AnimatedList/AnimatedList.tsx +42 -0
  139. package/src/components/AnimatedList/index.ts +2 -0
  140. package/src/components/AnimatedList/types.ts +15 -0
  141. package/src/components/Badge/constants.ts +1 -1
  142. package/src/components/Banner/constants.ts +1 -1
  143. package/src/components/BorderBeam/BorderBeam.tsx +41 -0
  144. package/src/components/BorderBeam/index.ts +2 -0
  145. package/src/components/BorderBeam/types.ts +14 -0
  146. package/src/components/Box/Box.tsx +8 -2
  147. package/src/components/Box/constants.ts +35 -0
  148. package/src/components/Button/constants.ts +66 -63
  149. package/src/components/CalendarHeatmap/CalendarHeatmap.tsx +141 -0
  150. package/src/components/CalendarHeatmap/index.ts +2 -0
  151. package/src/components/CalendarHeatmap/types.ts +27 -0
  152. package/src/components/Card/constants.ts +24 -21
  153. package/src/components/Carousel/constants.ts +2 -2
  154. package/src/components/Chart/components/ChartTooltip.tsx +1 -1
  155. package/src/components/Chart/stories/args/index.ts +2 -1
  156. package/src/components/Chart/stories/examples/AreaChart.tsx +55 -0
  157. package/src/components/Chart/stories/examples/BarChart.tsx +104 -6
  158. package/src/components/Chart/stories/examples/LineChart.tsx +111 -0
  159. package/src/components/Chart/stories/examples/PieChart.tsx +55 -0
  160. package/src/components/Chart/stories/examples/RadialChart.tsx +65 -0
  161. package/src/components/Chart/types.ts +1 -1
  162. package/src/components/CircularProgress/CircularProgress.tsx +46 -0
  163. package/src/components/CircularProgress/constants.ts +32 -0
  164. package/src/components/CircularProgress/index.ts +2 -0
  165. package/src/components/CircularProgress/types.ts +18 -0
  166. package/src/components/Command/constants.ts +1 -1
  167. package/src/components/ComparisonBar/ComparisonBar.tsx +65 -0
  168. package/src/components/ComparisonBar/constants.ts +23 -0
  169. package/src/components/ComparisonBar/index.ts +2 -0
  170. package/src/components/ComparisonBar/types.ts +23 -0
  171. package/src/components/Confetti/Confetti.tsx +82 -0
  172. package/src/components/Confetti/index.ts +2 -0
  173. package/src/components/Confetti/types.ts +20 -0
  174. package/src/components/CountdownTimer/CountdownTimer.tsx +91 -0
  175. package/src/components/CountdownTimer/index.ts +2 -0
  176. package/src/components/CountdownTimer/types.ts +14 -0
  177. package/src/components/DataList/DataList.tsx +32 -0
  178. package/src/components/DataList/constants.ts +47 -0
  179. package/src/components/DataList/index.ts +2 -0
  180. package/src/components/DataList/types.ts +17 -0
  181. package/src/components/DatePicker/DateRangePresetPicker.tsx +122 -0
  182. package/src/components/DatePicker/index.ts +1 -0
  183. package/src/components/DatePicker/types.ts +22 -0
  184. package/src/components/Description/Description.tsx +67 -5
  185. package/src/components/Description/DescriptionGroup.tsx +39 -0
  186. package/src/components/Description/constants.ts +128 -0
  187. package/src/components/Description/index.ts +10 -0
  188. package/src/components/Description/types.ts +31 -3
  189. package/src/components/Dialog/constants.ts +2 -2
  190. package/src/components/Dock/constants.ts +2 -2
  191. package/src/components/Drawer/constants.ts +2 -2
  192. package/src/components/Form/Checkbox/constants.ts +1 -1
  193. package/src/components/Form/DatetimeInput/constants.ts +1 -1
  194. package/src/components/Form/Input/constants.ts +1 -1
  195. package/src/components/Form/MultiSelect/constants.ts +1 -1
  196. package/src/components/Form/NativeSelect/constants.ts +1 -1
  197. package/src/components/Form/Radio/constants.ts +1 -1
  198. package/src/components/Form/Select/constants.ts +1 -1
  199. package/src/components/Form/Slider/constants.ts +1 -1
  200. package/src/components/Form/Switch/constants.ts +1 -1
  201. package/src/components/Form/Textarea/constants.ts +1 -1
  202. package/src/components/GlowCard/GlowCard.tsx +46 -0
  203. package/src/components/GlowCard/index.ts +2 -0
  204. package/src/components/GlowCard/types.ts +9 -0
  205. package/src/components/GradientText/GradientText.tsx +36 -0
  206. package/src/components/GradientText/index.ts +2 -0
  207. package/src/components/GradientText/types.ts +15 -0
  208. package/src/components/Greeting/Greeting.tsx +46 -0
  209. package/src/components/Greeting/index.ts +2 -0
  210. package/src/components/Greeting/types.ts +10 -0
  211. package/src/components/KPICard/KPICard.tsx +85 -0
  212. package/src/components/KPICard/index.ts +2 -0
  213. package/src/components/KPICard/types.ts +22 -0
  214. package/src/components/Marquee/Marquee.tsx +45 -0
  215. package/src/components/Marquee/index.ts +2 -0
  216. package/src/components/Marquee/types.ts +13 -0
  217. package/src/components/Menu/Menubar/constants.ts +2 -2
  218. package/src/components/Menu/NavigationMenu/constants.ts +2 -2
  219. package/src/components/Meteors/Meteors.tsx +38 -0
  220. package/src/components/Meteors/index.ts +2 -0
  221. package/src/components/Meteors/types.ts +6 -0
  222. package/src/components/MiniAreaChart/MiniAreaChart.tsx +68 -0
  223. package/src/components/MiniAreaChart/index.ts +2 -0
  224. package/src/components/MiniAreaChart/types.ts +11 -0
  225. package/src/components/MiniBarChart/MiniBarChart.tsx +49 -0
  226. package/src/components/MiniBarChart/index.ts +2 -0
  227. package/src/components/MiniBarChart/types.ts +16 -0
  228. package/src/components/MiniDonutChart/MiniDonutChart.tsx +87 -0
  229. package/src/components/MiniDonutChart/index.ts +2 -0
  230. package/src/components/MiniDonutChart/types.ts +17 -0
  231. package/src/components/MiniStackedBar/MiniStackedBar.tsx +61 -0
  232. package/src/components/MiniStackedBar/index.ts +2 -0
  233. package/src/components/MiniStackedBar/types.ts +15 -0
  234. package/src/components/NumberTicker/NumberTicker.tsx +58 -0
  235. package/src/components/NumberTicker/index.ts +2 -0
  236. package/src/components/NumberTicker/types.ts +12 -0
  237. package/src/components/Pagination/constants.ts +2 -2
  238. package/src/components/Progress/constants.ts +1 -1
  239. package/src/components/Pulse/Pulse.tsx +26 -0
  240. package/src/components/Pulse/constants.ts +55 -0
  241. package/src/components/Pulse/index.ts +2 -0
  242. package/src/components/Pulse/types.ts +12 -0
  243. package/src/components/Resizable/constants.ts +1 -1
  244. package/src/components/Sheet/constants.ts +1 -1
  245. package/src/components/ShinyButton/ShinyButton.tsx +57 -0
  246. package/src/components/ShinyButton/index.ts +2 -0
  247. package/src/components/ShinyButton/types.ts +8 -0
  248. package/src/components/Skeleton/constants.ts +1 -1
  249. package/src/components/Sonner/constants.ts +1 -1
  250. package/src/components/Sparkline/Sparkline.tsx +108 -0
  251. package/src/components/Sparkline/index.ts +2 -0
  252. package/src/components/Sparkline/types.ts +18 -0
  253. package/src/components/SpotlightCard/SpotlightCard.tsx +56 -0
  254. package/src/components/SpotlightCard/index.ts +2 -0
  255. package/src/components/SpotlightCard/types.ts +8 -0
  256. package/src/components/Stat/constants.ts +1 -1
  257. package/src/components/StatCard/StatCard.tsx +59 -0
  258. package/src/components/StatCard/index.ts +2 -0
  259. package/src/components/StatCard/types.ts +16 -0
  260. package/src/components/Tabs/constants.ts +1 -1
  261. package/src/components/TextShimmer/TextShimmer.tsx +34 -0
  262. package/src/components/TextShimmer/index.ts +2 -0
  263. package/src/components/TextShimmer/types.ts +8 -0
  264. package/src/components/Timeline/constants.ts +1 -1
  265. package/src/components/Toggle/constants.ts +1 -1
  266. package/src/components/Tooltip/constants.ts +1 -1
  267. package/src/components/TrendBadge/TrendBadge.tsx +40 -0
  268. package/src/components/TrendBadge/constants.ts +38 -0
  269. package/src/components/TrendBadge/index.ts +2 -0
  270. package/src/components/TrendBadge/types.ts +16 -0
  271. package/src/components/WidgetShell/WidgetShell.tsx +101 -0
  272. package/src/components/WidgetShell/index.ts +2 -0
  273. package/src/components/WidgetShell/types.ts +22 -0
  274. package/src/index.ts +35 -0
  275. package/src/stylesheets/tailwind.css +210 -0
  276. package/src/utilities/getSubpaths/getSubpaths.ts +1 -2
@@ -0,0 +1,82 @@
1
+ "use client";
2
+
3
+ import { useEffect, useMemo, useState } from "react";
4
+ import type { ConfettiProps } from "./types";
5
+
6
+ const DEFAULT_COLORS = [
7
+ "oklch(0.7 0.25 250)",
8
+ "oklch(0.7 0.2 330)",
9
+ "oklch(0.75 0.2 150)",
10
+ "oklch(0.8 0.15 60)",
11
+ "oklch(0.7 0.25 25)",
12
+ "oklch(0.7 0.15 200)",
13
+ ];
14
+
15
+ const Confetti = ({
16
+ active = false,
17
+ count = 50,
18
+ duration = 3,
19
+ colors = DEFAULT_COLORS,
20
+ }: ConfettiProps) => {
21
+ const [visible, setVisible] = useState(false);
22
+
23
+ useEffect(() => {
24
+ if (active) {
25
+ setVisible(true);
26
+ const timer = setTimeout(() => setVisible(false), duration * 1000);
27
+ return () => clearTimeout(timer);
28
+ }
29
+ setVisible(false);
30
+ }, [active, duration]);
31
+
32
+ const pieces = useMemo(
33
+ () =>
34
+ Array.from({ length: count }, (_, i) => ({
35
+ id: i,
36
+ x: Math.random() * 100,
37
+ delay: Math.random() * 0.5,
38
+ duration: duration * 0.6 + Math.random() * duration * 0.4,
39
+ color: colors[i % colors.length],
40
+ size: 4 + Math.random() * 6,
41
+ rotation: Math.random() * 360,
42
+ })),
43
+ [count, duration, colors]
44
+ );
45
+
46
+ if (!visible) return null;
47
+
48
+ return (
49
+ <div className="pointer-events-none fixed inset-0 z-[100] overflow-hidden" aria-hidden="true">
50
+ {pieces.map((piece) => (
51
+ <div
52
+ key={piece.id}
53
+ className="absolute animate-confetti"
54
+ style={{
55
+ left: `${piece.x}%`,
56
+ top: "-5%",
57
+ width: piece.size,
58
+ height: piece.size * 0.6,
59
+ backgroundColor: piece.color,
60
+ borderRadius: "1px",
61
+ transform: `rotate(${piece.rotation}deg)`,
62
+ animationDelay: `${piece.delay}s`,
63
+ animationDuration: `${piece.duration}s`,
64
+ }}
65
+ />
66
+ ))}
67
+ <style>{`
68
+ @keyframes confetti-fall {
69
+ 0% { transform: translateY(0) rotate(0deg); opacity: 1; }
70
+ 100% { transform: translateY(100vh) rotate(720deg); opacity: 0; }
71
+ }
72
+ .animate-confetti {
73
+ animation: confetti-fall var(--tw-duration, 3s) cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
74
+ }
75
+ `}</style>
76
+ </div>
77
+ );
78
+ };
79
+
80
+ Confetti.displayName = "Confetti";
81
+
82
+ export { Confetti };
@@ -0,0 +1,2 @@
1
+ export { Confetti } from "./Confetti";
2
+ export type { ConfettiProps } from "./types";
@@ -0,0 +1,20 @@
1
+ export type ConfettiPiece = {
2
+ id: number;
3
+ x: number;
4
+ delay: number;
5
+ duration: number;
6
+ color: string;
7
+ size: number;
8
+ rotation: number;
9
+ };
10
+
11
+ export type ConfettiProps = {
12
+ /** Whether to show confetti */
13
+ active?: boolean;
14
+ /** Number of confetti pieces */
15
+ count?: number;
16
+ /** Duration in seconds */
17
+ duration?: number;
18
+ /** Custom colors */
19
+ colors?: string[];
20
+ };
@@ -0,0 +1,91 @@
1
+ "use client";
2
+
3
+ import { useCallback, useEffect, useState } from "react";
4
+ import type { CountdownTimerProps } from "./types";
5
+ import { cn } from "../../utilities";
6
+
7
+ type TimeLeft = { days: number; hours: number; minutes: number; seconds: number };
8
+
9
+ const unitClasses = {
10
+ sm: "text-[10px]",
11
+ md: "text-xs",
12
+ lg: "text-sm",
13
+ } as const;
14
+
15
+ const Unit = ({ value, unit, size }: { value: number; unit: string; size: "sm" | "md" | "lg" }) => (
16
+ <div className="flex flex-col items-center">
17
+ <span className="font-bold tabular-nums">{String(value).padStart(2, "0")}</span>
18
+ <span className={cn("text-base-content/50 uppercase tracking-wider", unitClasses[size])}>
19
+ {unit}
20
+ </span>
21
+ </div>
22
+ );
23
+
24
+ const Separator = () => <span className="self-start font-bold text-base-content/30 pt-0.5">:</span>;
25
+
26
+ const CountdownTimer = ({
27
+ targetDate,
28
+ className,
29
+ label,
30
+ onComplete,
31
+ showSeconds = true,
32
+ size = "md",
33
+ ...props
34
+ }: CountdownTimerProps) => {
35
+ const calcTimeLeft = useCallback((): TimeLeft => {
36
+ const diff = Math.max(0, targetDate.getTime() - Date.now());
37
+ return {
38
+ days: Math.floor(diff / (1000 * 60 * 60 * 24)),
39
+ hours: Math.floor((diff / (1000 * 60 * 60)) % 24),
40
+ minutes: Math.floor((diff / (1000 * 60)) % 60),
41
+ seconds: Math.floor((diff / 1000) % 60),
42
+ };
43
+ }, [targetDate]);
44
+
45
+ const [timeLeft, setTimeLeft] = useState<TimeLeft>(calcTimeLeft);
46
+
47
+ useEffect(() => {
48
+ const timer = setInterval(() => {
49
+ const tl = calcTimeLeft();
50
+ setTimeLeft(tl);
51
+ if (tl.days === 0 && tl.hours === 0 && tl.minutes === 0 && tl.seconds === 0) {
52
+ clearInterval(timer);
53
+ onComplete?.();
54
+ }
55
+ }, 1000);
56
+ return () => clearInterval(timer);
57
+ }, [calcTimeLeft, onComplete]);
58
+
59
+ const sizeClasses = {
60
+ sm: "text-lg gap-1",
61
+ md: "text-2xl gap-2",
62
+ lg: "text-4xl gap-3",
63
+ };
64
+
65
+ return (
66
+ <div className={cn("flex flex-col items-center gap-1", className)} {...props}>
67
+ {label && <span className="text-sm text-base-content/60">{label}</span>}
68
+ <div className={cn("flex items-center", sizeClasses[size])}>
69
+ {timeLeft.days > 0 && (
70
+ <>
71
+ <Unit size={size} value={timeLeft.days} unit="days" />
72
+ <Separator />
73
+ </>
74
+ )}
75
+ <Unit size={size} value={timeLeft.hours} unit="hrs" />
76
+ <Separator />
77
+ <Unit size={size} value={timeLeft.minutes} unit="min" />
78
+ {showSeconds && (
79
+ <>
80
+ <Separator />
81
+ <Unit size={size} value={timeLeft.seconds} unit="sec" />
82
+ </>
83
+ )}
84
+ </div>
85
+ </div>
86
+ );
87
+ };
88
+
89
+ CountdownTimer.displayName = "CountdownTimer";
90
+
91
+ export { CountdownTimer };
@@ -0,0 +1,2 @@
1
+ export { CountdownTimer } from "./CountdownTimer";
2
+ export type { CountdownTimerProps } from "./types";
@@ -0,0 +1,14 @@
1
+ import type { HTMLAttributes } from "react";
2
+
3
+ export type CountdownTimerProps = Omit<HTMLAttributes<HTMLDivElement>, "children"> & {
4
+ /** Target date/time to count down to */
5
+ targetDate: Date;
6
+ /** Label to show above the timer */
7
+ label?: string;
8
+ /** Callback when countdown reaches zero */
9
+ onComplete?: () => void;
10
+ /** Whether to show seconds */
11
+ showSeconds?: boolean;
12
+ /** Size variant */
13
+ size?: "sm" | "md" | "lg";
14
+ };
@@ -0,0 +1,32 @@
1
+ import { cn } from "../../utilities";
2
+ import {
3
+ getDataListClasses,
4
+ getDataListItemClasses,
5
+ getDataListLabelClasses,
6
+ getDataListValueClasses,
7
+ } from "./constants";
8
+ import type { DataListProps } from "./types";
9
+
10
+ const DataList = ({
11
+ items,
12
+ className,
13
+ size = "md",
14
+ dividers = true,
15
+ horizontal = false,
16
+ ...props
17
+ }: DataListProps) => {
18
+ return (
19
+ <dl className={cn(getDataListClasses({ horizontal }), className)} {...props}>
20
+ {items.map((item, index) => (
21
+ <div key={index} className={getDataListItemClasses({ size, dividers, horizontal })}>
22
+ <dt className={getDataListLabelClasses()}>{item.label}</dt>
23
+ <dd className={getDataListValueClasses({ horizontal })}>{item.value}</dd>
24
+ </div>
25
+ ))}
26
+ </dl>
27
+ );
28
+ };
29
+
30
+ DataList.displayName = "DataList";
31
+
32
+ export { DataList };
@@ -0,0 +1,47 @@
1
+ import { cva } from "../../libs";
2
+ import { createVariants } from "../../utilities";
3
+
4
+ export const getDataListClasses = cva("", {
5
+ variants: createVariants({
6
+ horizontal: {
7
+ true: "flex flex-wrap gap-x-6 gap-y-2",
8
+ false: "flex flex-col",
9
+ },
10
+ }),
11
+ defaultVariants: {
12
+ horizontal: false,
13
+ },
14
+ });
15
+
16
+ export const getDataListItemClasses = cva(
17
+ "flex justify-between gap-4 transition-colors duration-150",
18
+ {
19
+ variants: createVariants({
20
+ size: {
21
+ sm: "py-1.5 text-xs",
22
+ md: "py-2.5 text-sm",
23
+ lg: "py-3 text-base",
24
+ },
25
+ dividers: {
26
+ true: "border-b border-base-200 last:border-0",
27
+ },
28
+ horizontal: {
29
+ true: "flex-col gap-0.5",
30
+ },
31
+ }),
32
+ defaultVariants: {
33
+ size: "md",
34
+ dividers: true,
35
+ },
36
+ }
37
+ );
38
+
39
+ export const getDataListLabelClasses = cva("text-base-content/60 shrink-0");
40
+
41
+ export const getDataListValueClasses = cva("font-medium text-right tabular-nums", {
42
+ variants: createVariants({
43
+ horizontal: {
44
+ true: "text-left",
45
+ },
46
+ }),
47
+ });
@@ -0,0 +1,2 @@
1
+ export { DataList } from "./DataList";
2
+ export type { DataListProps, DataListItem } from "./types";
@@ -0,0 +1,17 @@
1
+ import type { HTMLAttributes, ReactNode } from "react";
2
+
3
+ export type DataListItem = {
4
+ label: ReactNode;
5
+ value: ReactNode;
6
+ };
7
+
8
+ export type DataListProps = Omit<HTMLAttributes<HTMLDListElement>, "children"> & {
9
+ /** Key-value items to display */
10
+ items: DataListItem[];
11
+ /** Size variant */
12
+ size?: "sm" | "md" | "lg";
13
+ /** Whether to show dividers between items */
14
+ dividers?: boolean;
15
+ /** Whether to show items in a horizontal layout */
16
+ horizontal?: boolean;
17
+ };
@@ -0,0 +1,122 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { type DateRange } from "react-day-picker";
5
+ import { format, subDays, startOfMonth, startOfYear } from "date-fns";
6
+ import { CalendarDaysIcon } from "lucide-react";
7
+ import { cn } from "../../utilities";
8
+ import { Button } from "../Button";
9
+ import { Calendar } from "../Calendar";
10
+ import { Popover } from "../Popover";
11
+ import { type DateRangePresetPickerProps, type DateRangePreset } from "./types";
12
+
13
+ const DEFAULT_PRESETS: DateRangePreset[] = [
14
+ { label: "Today", range: () => ({ from: new Date(), to: new Date() }) },
15
+ { label: "Last 7 days", range: () => ({ from: subDays(new Date(), 7), to: new Date() }) },
16
+ { label: "Last 30 days", range: () => ({ from: subDays(new Date(), 30), to: new Date() }) },
17
+ { label: "Last 90 days", range: () => ({ from: subDays(new Date(), 90), to: new Date() }) },
18
+ { label: "This month", range: () => ({ from: startOfMonth(new Date()), to: new Date() }) },
19
+ { label: "This year", range: () => ({ from: startOfYear(new Date()), to: new Date() }) },
20
+ ];
21
+
22
+ export const DateRangePresetPicker = ({
23
+ name,
24
+ size,
25
+ wide,
26
+ label,
27
+ outline,
28
+ variant,
29
+ disabled,
30
+ disabledDates,
31
+ defaultRange,
32
+ presets = DEFAULT_PRESETS,
33
+ onRangeChange,
34
+ getRangeValue = (range) => ({
35
+ from: range?.from?.toUTCString(),
36
+ to: range?.to?.toUTCString(),
37
+ }),
38
+ getRangeLabel = (range) =>
39
+ range?.from
40
+ ? range.to
41
+ ? `${format(range.from, "LLL dd, y")} - ${format(range.to, "LLL dd, y")}`
42
+ : format(range.from, "LLL dd, y")
43
+ : undefined,
44
+ triggerClassName,
45
+ ...props
46
+ }: DateRangePresetPickerProps) => {
47
+ const [range, setRange] = useState<DateRange | undefined>(defaultRange);
48
+ const [activePreset, setActivePreset] = useState<string | null>(null);
49
+
50
+ const handlePresetClick = (preset: DateRangePreset) => {
51
+ const newRange = preset.range();
52
+ setRange(newRange);
53
+ setActivePreset(preset.label);
54
+ onRangeChange?.(newRange, preset.label);
55
+ };
56
+
57
+ const handleCalendarSelect = (newRange: DateRange | undefined) => {
58
+ setRange(newRange);
59
+ setActivePreset(null);
60
+ onRangeChange?.(newRange, undefined);
61
+ };
62
+
63
+ const rangeLabel = getRangeLabel(range);
64
+ const rangeValue = getRangeValue(range);
65
+
66
+ return (
67
+ <Popover>
68
+ {name && (
69
+ <>
70
+ <input hidden className="hidden" aria-hidden="true" name={`${name}.from`} defaultValue={rangeValue.from} />
71
+ <input hidden className="hidden" aria-hidden="true" name={`${name}.to`} defaultValue={rangeValue.to} />
72
+ </>
73
+ )}
74
+ <Popover.Trigger asChild>
75
+ <Button
76
+ name={name}
77
+ size={size}
78
+ wide={wide}
79
+ outline={outline}
80
+ variant={variant}
81
+ disabled={disabled}
82
+ className={cn("justify-start flex-nowrap", !range && "font-normal", triggerClassName)}
83
+ >
84
+ <span className="text-left text-ellipsis overflow-hidden text-nowrap">
85
+ {activePreset ?? rangeLabel ?? label ?? "Select period"}
86
+ </span>
87
+ <CalendarDaysIcon className="ml-auto h-4 w-4 opacity-50" />
88
+ </Button>
89
+ </Popover.Trigger>
90
+ <Popover.Content className="w-auto p-0" align="start">
91
+ <div className="flex">
92
+ <div className="flex flex-col border-r p-2 gap-0.5">
93
+ {presets.map((preset) => (
94
+ <button
95
+ key={preset.label}
96
+ type="button"
97
+ onClick={() => handlePresetClick(preset)}
98
+ className={cn(
99
+ "rounded-md px-3 py-1.5 text-left text-sm transition-colors duration-150 hover:bg-base-200",
100
+ activePreset === preset.label && "bg-primary text-primary-content hover:bg-primary"
101
+ )}
102
+ >
103
+ {preset.label}
104
+ </button>
105
+ ))}
106
+ </div>
107
+ <div className="p-2">
108
+ <Calendar
109
+ autoFocus
110
+ mode="range"
111
+ selected={range}
112
+ disabled={disabledDates}
113
+ onSelect={handleCalendarSelect}
114
+ captionLayout="label"
115
+ {...props}
116
+ />
117
+ </div>
118
+ </div>
119
+ </Popover.Content>
120
+ </Popover>
121
+ );
122
+ };
@@ -1,3 +1,4 @@
1
1
  export { DatePicker } from "./DatePicker";
2
2
  export { DateRangePicker } from "./DateRangePicker";
3
+ export { DateRangePresetPicker } from "./DateRangePresetPicker";
3
4
  export { MultipleDatesPicker } from "./MultipleDatesPicker";
@@ -33,6 +33,28 @@ export type DateRangePickerProps = BaseDatePickerProps &
33
33
  getRangeLabel?: (range: DateRange | undefined) => string | React.JSX.Element | undefined;
34
34
  };
35
35
 
36
+ export type DateRangePreset = {
37
+ /** Display label for the preset */
38
+ label: string;
39
+ /** Function that returns the date range for this preset */
40
+ range: () => DateRange;
41
+ };
42
+
43
+ export type DateRangePresetPickerProps = BaseDatePickerProps &
44
+ Omit<PropsRange, "mode" | "disabled"> & {
45
+ defaultRange?: DateRange;
46
+ disabledDates?: PropsRange["disabled"];
47
+ /** Preset period options. Defaults to Today, Last 7/30/90 days, This month, This year */
48
+ presets?: DateRangePreset[];
49
+ /** Called when range changes, with optional preset label */
50
+ onRangeChange?: (range: DateRange | undefined, presetLabel?: string) => void;
51
+ getRangeValue?: (range: DateRange | undefined) => {
52
+ from: string | undefined;
53
+ to: string | undefined;
54
+ };
55
+ getRangeLabel?: (range: DateRange | undefined) => string | undefined;
56
+ };
57
+
36
58
  export type MultipleDatesPickerProps = BaseDatePickerProps &
37
59
  Omit<PropsMulti, "mode"> & {
38
60
  defaultDates?: Date[];
@@ -1,19 +1,81 @@
1
- import type { DescriptionDetailProps, DescriptionProps, DescriptionTermProps } from "./types";
1
+ import { createContext, useContext } from "react";
2
2
  import { cn } from "../../utilities";
3
+ import {
4
+ getDescriptionClasses,
5
+ getDescriptionDetailClasses,
6
+ getDescriptionPairClasses,
7
+ getDescriptionTermClasses,
8
+ } from "./constants";
9
+ import type {
10
+ DescriptionDetailProps,
11
+ DescriptionLayout,
12
+ DescriptionProps,
13
+ DescriptionSize,
14
+ DescriptionTermProps,
15
+ } from "./types";
3
16
 
4
- const Description = (props: DescriptionProps) => {
5
- return <dl {...props} />;
17
+ type DescriptionContextValue = {
18
+ size: DescriptionSize;
19
+ layout: DescriptionLayout;
20
+ dividers: boolean;
21
+ striped: boolean;
22
+ };
23
+
24
+ const DescriptionContext = createContext<DescriptionContextValue>({
25
+ size: "md",
26
+ layout: "vertical",
27
+ dividers: false,
28
+ striped: false,
29
+ });
30
+
31
+ const useDescriptionContext = () => useContext(DescriptionContext);
32
+
33
+ const Description = ({
34
+ className,
35
+ variant = "default",
36
+ layout = "vertical",
37
+ size = "md",
38
+ dividers = false,
39
+ striped = false,
40
+ ...props
41
+ }: DescriptionProps) => {
42
+ return (
43
+ <DescriptionContext.Provider value={{ size, layout, dividers, striped }}>
44
+ <dl
45
+ className={cn(getDescriptionClasses({ variant, layout, size }), className)}
46
+ {...props}
47
+ />
48
+ </DescriptionContext.Provider>
49
+ );
6
50
  };
7
51
 
8
52
  const DescriptionTerm = ({ className, ...props }: DescriptionTermProps) => {
9
- return <dt className={cn("py-2 text-sm font-semibold", className)} {...props} />;
53
+ const { size, layout } = useDescriptionContext();
54
+ return (
55
+ <dt className={cn(getDescriptionTermClasses({ size, layout }), className)} {...props} />
56
+ );
10
57
  };
11
58
 
12
59
  const DescriptionDetail = ({ className, ...props }: DescriptionDetailProps) => {
13
- return <dd className={cn("text-base not-last:mb-1", className)} {...props} />;
60
+ const { size, layout, dividers } = useDescriptionContext();
61
+ return (
62
+ <dd
63
+ className={cn(getDescriptionDetailClasses({ size, layout, dividers }), className)}
64
+ {...props}
65
+ />
66
+ );
67
+ };
68
+
69
+ const DescriptionPair = ({
70
+ className,
71
+ ...props
72
+ }: React.HTMLAttributes<HTMLDivElement>) => {
73
+ const { layout, striped } = useDescriptionContext();
74
+ return <div className={cn(getDescriptionPairClasses({ layout, striped }), className)} {...props} />;
14
75
  };
15
76
 
16
77
  Description.Term = DescriptionTerm;
17
78
  Description.Detail = DescriptionDetail;
79
+ Description.Pair = DescriptionPair;
18
80
 
19
81
  export { Description };
@@ -0,0 +1,39 @@
1
+ import { cn } from "../../utilities";
2
+ import { getDescriptionGroupClasses, getDescriptionGroupItemClasses } from "./constants";
3
+ import type { DescriptionGroupProps } from "./types";
4
+
5
+ const DescriptionGroup = ({
6
+ className,
7
+ children,
8
+ direction = "column",
9
+ dividers = false,
10
+ title,
11
+ description,
12
+ ...props
13
+ }: DescriptionGroupProps) => {
14
+ return (
15
+ <div className={cn("flex flex-col", className)} {...props}>
16
+ {(title || description) && (
17
+ <div className="mb-4">
18
+ {title && <h3 className="text-base font-semibold text-base-content">{title}</h3>}
19
+ {description && (
20
+ <p className="mt-0.5 text-sm text-base-content/60">{description}</p>
21
+ )}
22
+ </div>
23
+ )}
24
+ <div className={getDescriptionGroupClasses({ direction, dividers })}>
25
+ {Array.isArray(children)
26
+ ? children.map((child, i) => (
27
+ <div key={i} className={getDescriptionGroupItemClasses()}>
28
+ {child}
29
+ </div>
30
+ ))
31
+ : children}
32
+ </div>
33
+ </div>
34
+ );
35
+ };
36
+
37
+ DescriptionGroup.displayName = "DescriptionGroup";
38
+
39
+ export { DescriptionGroup };