@wealthx/shadcn 1.1.0 → 1.2.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 (300) hide show
  1. package/.turbo/turbo-build.log +235 -154
  2. package/CHANGELOG.md +6 -0
  3. package/dist/{chunk-6OJF6XRN.mjs → chunk-24FUO7TD.mjs} +4 -8
  4. package/dist/{chunk-4AJ5HWHD.mjs → chunk-2I5S2AMY.mjs} +3 -3
  5. package/dist/chunk-2SF672SZ.mjs +161 -0
  6. package/dist/{chunk-GPRJQ24C.mjs → chunk-34NWQURD.mjs} +2 -2
  7. package/dist/{chunk-MQ72DIBH.mjs → chunk-3GF7OVTP.mjs} +14 -5
  8. package/dist/chunk-3WMX6KWS.mjs +245 -0
  9. package/dist/{chunk-PMKODV6M.mjs → chunk-462HMNO4.mjs} +6 -10
  10. package/dist/chunk-4CX4SBRO.mjs +153 -0
  11. package/dist/chunk-4MN6UQHG.mjs +443 -0
  12. package/dist/{chunk-GLW2UO6O.mjs → chunk-5QQVZTVZ.mjs} +82 -61
  13. package/dist/{chunk-BGP2N52Z.mjs → chunk-66MI7Q4B.mjs} +5 -5
  14. package/dist/chunk-6FCGKSZX.mjs +268 -0
  15. package/dist/{chunk-CGOKTPXU.mjs → chunk-6JQFUE5I.mjs} +20 -23
  16. package/dist/{chunk-Z3MK2KKZ.mjs → chunk-7DHU4VGG.mjs} +7 -3
  17. package/dist/{chunk-VZ2NR7L3.mjs → chunk-7PYJD5JI.mjs} +35 -27
  18. package/dist/{chunk-JU2RUWHF.mjs → chunk-7XJHLGUV.mjs} +1 -1
  19. package/dist/{chunk-BMFN37JH.mjs → chunk-7YAU5CY6.mjs} +1 -1
  20. package/dist/chunk-A56YQQHG.mjs +402 -0
  21. package/dist/chunk-AH52LG6N.mjs +315 -0
  22. package/dist/{chunk-SLWCCURD.mjs → chunk-CLIN5525.mjs} +8 -4
  23. package/dist/{chunk-3VQNJ235.mjs → chunk-CSDO6VBW.mjs} +7 -0
  24. package/dist/chunk-D4ILTPOG.mjs +293 -0
  25. package/dist/{chunk-HS7TFG7V.mjs → chunk-D6ID6M4V.mjs} +1 -1
  26. package/dist/chunk-DOH3EHX7.mjs +378 -0
  27. package/dist/{chunk-MJIEMGRD.mjs → chunk-EFRENWEJ.mjs} +9 -17
  28. package/dist/{chunk-YBXCIF5Q.mjs → chunk-ERGGHC2V.mjs} +36 -49
  29. package/dist/{chunk-OXQQNQZI.mjs → chunk-FEZKMUCF.mjs} +10 -1
  30. package/dist/{chunk-55CEW76V.mjs → chunk-FH6QVUVZ.mjs} +1 -1
  31. package/dist/chunk-FMAXJ2SI.mjs +71 -0
  32. package/dist/chunk-FZIXGLMV.mjs +173 -0
  33. package/dist/{chunk-DS2AMHN2.mjs → chunk-GYMYRIZP.mjs} +2 -2
  34. package/dist/{chunk-KQDD5MU3.mjs → chunk-H45TKD34.mjs} +5 -5
  35. package/dist/{chunk-BBJBJSXQ.mjs → chunk-J5UICVJS.mjs} +1 -1
  36. package/dist/{chunk-RL772EH7.mjs → chunk-JHJHG4GO.mjs} +4 -12
  37. package/dist/{chunk-RN67642N.mjs → chunk-KMCGSZTX.mjs} +47 -41
  38. package/dist/{chunk-FHNT55I5.mjs → chunk-KUDCQ4FI.mjs} +4 -4
  39. package/dist/chunk-LE6YFY6D.mjs +209 -0
  40. package/dist/{chunk-NLLKTU4B.mjs → chunk-LLVQKSU3.mjs} +21 -17
  41. package/dist/{chunk-KKHTJNMM.mjs → chunk-MARPPFOJ.mjs} +8 -4
  42. package/dist/{chunk-6AFMNC42.mjs → chunk-N2PT566P.mjs} +15 -11
  43. package/dist/chunk-NLCKVHWB.mjs +161 -0
  44. package/dist/{chunk-YN5SYTOO.mjs → chunk-NQPOYKAQ.mjs} +9 -5
  45. package/dist/{chunk-ZZV5JVNW.mjs → chunk-NSLMILBT.mjs} +3 -7
  46. package/dist/chunk-NXA3CZ7A.mjs +248 -0
  47. package/dist/chunk-OGOYQ7BG.mjs +150 -0
  48. package/dist/{chunk-3NQGYJEZ.mjs → chunk-P6AM5V7O.mjs} +10 -18
  49. package/dist/{chunk-CZ3BW5GL.mjs → chunk-P76HMUI6.mjs} +5 -11
  50. package/dist/chunk-PCPLO5HT.mjs +671 -0
  51. package/dist/chunk-PG6K5XEC.mjs +475 -0
  52. package/dist/{chunk-5JGQAAQV.mjs → chunk-PJHPSRYD.mjs} +84 -62
  53. package/dist/{chunk-DDPA2XXS.mjs → chunk-PMB3A7V3.mjs} +2 -2
  54. package/dist/chunk-PR6V5XKM.mjs +209 -0
  55. package/dist/{chunk-46OFHMQA.mjs → chunk-Q76O3RIQ.mjs} +10 -6
  56. package/dist/chunk-QVKWW6KE.mjs +272 -0
  57. package/dist/chunk-RGU7HOEC.mjs +140 -0
  58. package/dist/{chunk-JF4PHPD5.mjs → chunk-RGVKLTLH.mjs} +4 -4
  59. package/dist/{chunk-VG6UF6UT.mjs → chunk-RP3SQYA3.mjs} +2 -2
  60. package/dist/chunk-RRBS6D63.mjs +163 -0
  61. package/dist/{chunk-UEL4RD5P.mjs → chunk-SMQ3DG25.mjs} +80 -67
  62. package/dist/chunk-SPJ5KXW7.mjs +199 -0
  63. package/dist/chunk-SYOD63OZ.mjs +225 -0
  64. package/dist/chunk-UFYSFDER.mjs +42 -0
  65. package/dist/chunk-VACKZOMY.mjs +190 -0
  66. package/dist/chunk-VLQZANBF.mjs +42 -0
  67. package/dist/chunk-WA6O6EUR.mjs +1885 -0
  68. package/dist/{chunk-E3K6O4FZ.mjs → chunk-WAZD7NFU.mjs} +5 -2
  69. package/dist/chunk-WG6JGJXB.mjs +165 -0
  70. package/dist/{chunk-I64K754C.mjs → chunk-WNGWBVLV.mjs} +2 -2
  71. package/dist/{chunk-3U7SD3MS.mjs → chunk-WOEHFRGB.mjs} +3 -3
  72. package/dist/{chunk-DKZRJOMF.mjs → chunk-XIRTEFKH.mjs} +12 -12
  73. package/dist/chunk-Y6DWJSKZ.mjs +79 -0
  74. package/dist/chunk-YKPROFLB.mjs +161 -0
  75. package/dist/{chunk-CJ46PDXE.mjs → chunk-ZRO5JO3H.mjs} +106 -66
  76. package/dist/{chunk-VYMHBV6D.mjs → chunk-ZU4NV6RG.mjs} +5 -3
  77. package/dist/components/ui/accordion.js +40 -4
  78. package/dist/components/ui/accordion.mjs +2 -2
  79. package/dist/components/ui/add-column-modal.js +789 -0
  80. package/dist/components/ui/add-column-modal.mjs +17 -0
  81. package/dist/components/ui/add-lead-modal.js +647 -0
  82. package/dist/components/ui/add-lead-modal.mjs +16 -0
  83. package/dist/components/ui/ai-assistant-drawer.js +686 -0
  84. package/dist/components/ui/ai-assistant-drawer.mjs +16 -0
  85. package/dist/components/ui/alert-dialog.js +37 -5
  86. package/dist/components/ui/alert-dialog.mjs +4 -4
  87. package/dist/components/ui/alert.js +37 -11
  88. package/dist/components/ui/alert.mjs +2 -2
  89. package/dist/components/ui/avatar.js +36 -8
  90. package/dist/components/ui/avatar.mjs +2 -2
  91. package/dist/components/ui/backoffice-alert-history-chart.js +624 -0
  92. package/dist/components/ui/backoffice-alert-history-chart.mjs +16 -0
  93. package/dist/components/ui/backoffice-contact-history-chart.js +687 -0
  94. package/dist/components/ui/backoffice-contact-history-chart.mjs +16 -0
  95. package/dist/components/ui/badge.js +37 -2
  96. package/dist/components/ui/badge.mjs +2 -2
  97. package/dist/components/ui/borrowing-capacity-line-chart.js +639 -0
  98. package/dist/components/ui/borrowing-capacity-line-chart.mjs +16 -0
  99. package/dist/components/ui/button.js +35 -3
  100. package/dist/components/ui/button.mjs +2 -2
  101. package/dist/components/ui/calendar.js +43 -19
  102. package/dist/components/ui/calendar.mjs +3 -3
  103. package/dist/components/ui/card.js +40 -4
  104. package/dist/components/ui/card.mjs +2 -2
  105. package/dist/components/ui/cash-balance-line-chart.js +627 -0
  106. package/dist/components/ui/cash-balance-line-chart.mjs +16 -0
  107. package/dist/components/ui/cashflow-bar-chart.js +123 -69
  108. package/dist/components/ui/cashflow-bar-chart.mjs +8 -8
  109. package/dist/components/ui/checkbox.js +36 -5
  110. package/dist/components/ui/checkbox.mjs +2 -3
  111. package/dist/components/ui/chip.js +37 -2
  112. package/dist/components/ui/chip.mjs +3 -3
  113. package/dist/components/ui/combobox.js +68 -49
  114. package/dist/components/ui/combobox.mjs +2 -2
  115. package/dist/components/ui/data-table.js +160 -88
  116. package/dist/components/ui/data-table.mjs +10 -11
  117. package/dist/components/ui/date-picker.js +44 -20
  118. package/dist/components/ui/date-picker.mjs +6 -7
  119. package/dist/components/ui/dialog.js +44 -12
  120. package/dist/components/ui/dialog.mjs +4 -4
  121. package/dist/components/ui/drawer.js +46 -10
  122. package/dist/components/ui/drawer.mjs +3 -3
  123. package/dist/components/ui/dropdown-menu.js +40 -16
  124. package/dist/components/ui/dropdown-menu.mjs +3 -3
  125. package/dist/components/ui/empty.js +41 -5
  126. package/dist/components/ui/empty.mjs +2 -2
  127. package/dist/components/ui/expense-bar-chart.js +165 -66
  128. package/dist/components/ui/expense-bar-chart.mjs +8 -8
  129. package/dist/components/ui/field.js +53 -21
  130. package/dist/components/ui/field.mjs +4 -4
  131. package/dist/components/ui/financial-cards.js +1002 -0
  132. package/dist/components/ui/financial-cards.mjs +24 -0
  133. package/dist/components/ui/financial-drawers.js +637 -0
  134. package/dist/components/ui/financial-drawers.mjs +17 -0
  135. package/dist/components/ui/financial-primitives.js +218 -0
  136. package/dist/components/ui/financial-primitives.mjs +22 -0
  137. package/dist/components/ui/financial-sections.js +1422 -0
  138. package/dist/components/ui/financial-sections.mjs +30 -0
  139. package/dist/components/ui/form-primitives.js +682 -0
  140. package/dist/components/ui/form-primitives.mjs +19 -0
  141. package/dist/components/ui/income-bar-chart.js +163 -65
  142. package/dist/components/ui/income-bar-chart.mjs +8 -8
  143. package/dist/components/ui/input-group.js +43 -7
  144. package/dist/components/ui/input-group.mjs +5 -5
  145. package/dist/components/ui/input-otp.js +39 -3
  146. package/dist/components/ui/input-otp.mjs +2 -2
  147. package/dist/components/ui/input.js +34 -2
  148. package/dist/components/ui/input.mjs +2 -2
  149. package/dist/components/ui/kanban-column.js +1143 -0
  150. package/dist/components/ui/kanban-column.mjs +20 -0
  151. package/dist/components/ui/label.js +35 -7
  152. package/dist/components/ui/label.mjs +2 -2
  153. package/dist/components/ui/opportunity-card.js +960 -0
  154. package/dist/components/ui/opportunity-card.mjs +20 -0
  155. package/dist/components/ui/opportunity-edit-modals.js +3360 -0
  156. package/dist/components/ui/opportunity-edit-modals.mjs +37 -0
  157. package/dist/components/ui/opportunity-summary-tab.js +4365 -0
  158. package/dist/components/ui/opportunity-summary-tab.mjs +34 -0
  159. package/dist/components/ui/pagination.js +35 -3
  160. package/dist/components/ui/pagination.mjs +3 -3
  161. package/dist/components/ui/pipeline-alerts.js +103 -0
  162. package/dist/components/ui/pipeline-alerts.mjs +8 -0
  163. package/dist/components/ui/pipeline-board.js +1408 -0
  164. package/dist/components/ui/pipeline-board.mjs +24 -0
  165. package/dist/components/ui/pipeline-chart.js +216 -0
  166. package/dist/components/ui/pipeline-chart.mjs +10 -0
  167. package/dist/components/ui/pipeline-dialogs.js +1183 -0
  168. package/dist/components/ui/pipeline-dialogs.mjs +23 -0
  169. package/dist/components/ui/pipeline-primitives.js +300 -0
  170. package/dist/components/ui/pipeline-primitives.mjs +11 -0
  171. package/dist/components/ui/popover.js +45 -4
  172. package/dist/components/ui/popover.mjs +3 -3
  173. package/dist/components/ui/progress.js +33 -1
  174. package/dist/components/ui/progress.mjs +2 -2
  175. package/dist/components/ui/property-cashflow-doughnut-chart.js +523 -0
  176. package/dist/components/ui/property-cashflow-doughnut-chart.mjs +16 -0
  177. package/dist/components/ui/property-debt-equity-doughnut-chart.js +521 -0
  178. package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +16 -0
  179. package/dist/components/ui/property-mobile-estimate-line-chart.js +682 -0
  180. package/dist/components/ui/property-mobile-estimate-line-chart.mjs +16 -0
  181. package/dist/components/ui/radio-group.js +33 -1
  182. package/dist/components/ui/radio-group.mjs +2 -2
  183. package/dist/components/ui/select.js +66 -26
  184. package/dist/components/ui/select.mjs +3 -3
  185. package/dist/components/ui/separator.js +33 -1
  186. package/dist/components/ui/separator.mjs +2 -2
  187. package/dist/components/ui/sheet.js +37 -9
  188. package/dist/components/ui/sheet.mjs +3 -3
  189. package/dist/components/ui/skeleton.js +33 -1
  190. package/dist/components/ui/skeleton.mjs +2 -2
  191. package/dist/components/ui/slider.js +86 -102
  192. package/dist/components/ui/slider.mjs +2 -2
  193. package/dist/components/ui/spinner.js +33 -1
  194. package/dist/components/ui/spinner.mjs +2 -2
  195. package/dist/components/ui/stage-timeline.js +579 -0
  196. package/dist/components/ui/stage-timeline.mjs +15 -0
  197. package/dist/components/ui/switch.js +37 -4
  198. package/dist/components/ui/switch.mjs +2 -3
  199. package/dist/components/ui/table.js +37 -5
  200. package/dist/components/ui/table.mjs +2 -2
  201. package/dist/components/ui/tabs.js +36 -12
  202. package/dist/components/ui/tabs.mjs +2 -2
  203. package/dist/components/ui/textarea.js +34 -2
  204. package/dist/components/ui/textarea.mjs +2 -2
  205. package/dist/components/ui/toggle-group.js +35 -4
  206. package/dist/components/ui/toggle-group.mjs +3 -4
  207. package/dist/components/ui/toggle.js +35 -4
  208. package/dist/components/ui/toggle.mjs +2 -3
  209. package/dist/components/ui/tooltip.js +51 -22
  210. package/dist/components/ui/tooltip.mjs +3 -3
  211. package/dist/components/ui/transactions-expense-categories-doughnut-chart.js +528 -0
  212. package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +16 -0
  213. package/dist/components/ui/transactions-income-expense-bar-chart.js +76 -38
  214. package/dist/components/ui/transactions-income-expense-bar-chart.mjs +8 -8
  215. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.js +528 -0
  216. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +16 -0
  217. package/dist/index.js +11616 -3831
  218. package/dist/index.mjs +333 -161
  219. package/dist/lib/theme-provider.js +10 -1
  220. package/dist/lib/theme-provider.mjs +1 -1
  221. package/dist/lib/typography.js +8 -0
  222. package/dist/lib/typography.mjs +3 -1
  223. package/dist/lib/utils.js +33 -1
  224. package/dist/lib/utils.mjs +1 -1
  225. package/dist/styles.css +1 -1
  226. package/package.json +140 -5
  227. package/src/components/index.tsx +296 -42
  228. package/src/components/ui/accordion.tsx +6 -3
  229. package/src/components/ui/add-column-modal.tsx +339 -0
  230. package/src/components/ui/add-lead-modal.tsx +290 -0
  231. package/src/components/ui/ai-assistant-drawer.tsx +408 -0
  232. package/src/components/ui/alert-dialog.tsx +80 -54
  233. package/src/components/ui/alert.tsx +28 -28
  234. package/src/components/ui/avatar.tsx +30 -29
  235. package/src/components/ui/backoffice-alert-history-chart.tsx +260 -0
  236. package/src/components/ui/backoffice-contact-history-chart.tsx +325 -0
  237. package/src/components/ui/badge.tsx +17 -15
  238. package/src/components/ui/borrowing-capacity-line-chart.tsx +357 -0
  239. package/src/components/ui/button.tsx +30 -27
  240. package/src/components/ui/calendar.tsx +53 -67
  241. package/src/components/ui/card.tsx +27 -24
  242. package/src/components/ui/cash-balance-line-chart.tsx +302 -0
  243. package/src/components/ui/cashflow-bar-chart.tsx +104 -77
  244. package/src/components/ui/chart-shared.tsx +176 -15
  245. package/src/components/ui/checkbox.tsx +30 -26
  246. package/src/components/ui/combobox.tsx +78 -72
  247. package/src/components/ui/data-table.tsx +160 -99
  248. package/src/components/ui/date-picker.tsx +0 -2
  249. package/src/components/ui/dialog.tsx +70 -60
  250. package/src/components/ui/drawer.tsx +57 -48
  251. package/src/components/ui/dropdown-menu.tsx +90 -82
  252. package/src/components/ui/empty.tsx +31 -27
  253. package/src/components/ui/expense-bar-chart.tsx +83 -65
  254. package/src/components/ui/field.tsx +70 -62
  255. package/src/components/ui/financial-cards.tsx +830 -0
  256. package/src/components/ui/financial-drawers.tsx +339 -0
  257. package/src/components/ui/financial-primitives.tsx +331 -0
  258. package/src/components/ui/financial-sections.tsx +672 -0
  259. package/src/components/ui/form-primitives.tsx +536 -0
  260. package/src/components/ui/income-bar-chart.tsx +79 -60
  261. package/src/components/ui/input-group.tsx +41 -34
  262. package/src/components/ui/input-otp.tsx +29 -24
  263. package/src/components/ui/input.tsx +8 -8
  264. package/src/components/ui/kanban-column.tsx +333 -0
  265. package/src/components/ui/label.tsx +9 -12
  266. package/src/components/ui/opportunity-card.tsx +616 -0
  267. package/src/components/ui/opportunity-edit-modals.tsx +2528 -0
  268. package/src/components/ui/opportunity-summary-tab.tsx +579 -0
  269. package/src/components/ui/pipeline-alerts.tsx +74 -0
  270. package/src/components/ui/pipeline-board.tsx +268 -0
  271. package/src/components/ui/pipeline-chart.tsx +173 -0
  272. package/src/components/ui/pipeline-dialogs.tsx +303 -0
  273. package/src/components/ui/pipeline-primitives.tsx +108 -0
  274. package/src/components/ui/popover.tsx +41 -36
  275. package/src/components/ui/property-cashflow-doughnut-chart.tsx +188 -0
  276. package/src/components/ui/property-debt-equity-doughnut-chart.tsx +185 -0
  277. package/src/components/ui/property-mobile-estimate-line-chart.tsx +393 -0
  278. package/src/components/ui/select.tsx +65 -52
  279. package/src/components/ui/sheet.tsx +55 -52
  280. package/src/components/ui/slider.tsx +54 -77
  281. package/src/components/ui/stage-timeline.tsx +205 -0
  282. package/src/components/ui/switch.tsx +42 -29
  283. package/src/components/ui/table.tsx +28 -28
  284. package/src/components/ui/tabs.tsx +22 -28
  285. package/src/components/ui/textarea.tsx +8 -8
  286. package/src/components/ui/toggle-group.tsx +0 -2
  287. package/src/components/ui/toggle.tsx +13 -15
  288. package/src/components/ui/tooltip.tsx +30 -28
  289. package/src/components/ui/transactions-expense-categories-doughnut-chart.tsx +191 -0
  290. package/src/components/ui/transactions-income-expense-bar-chart.tsx +45 -38
  291. package/src/components/ui/transactions-liabilities-breakdown-doughnut-chart.tsx +191 -0
  292. package/src/lib/theme-provider.tsx +10 -0
  293. package/src/lib/typography.ts +9 -0
  294. package/src/lib/utils.ts +41 -3
  295. package/src/styles/globals.css +371 -124
  296. package/src/styles/styles-css.ts +1 -1
  297. package/tsup.config.ts +27 -0
  298. package/dist/chunk-3EQP72AW.mjs +0 -58
  299. package/dist/chunk-K74JRTJR.mjs +0 -105
  300. package/dist/chunk-V7CNWJT3.mjs +0 -10
@@ -1,7 +1,7 @@
1
- import { type ReactElement } from "react"
2
- import * as React from "react"
3
- import { cva, type VariantProps } from "class-variance-authority"
4
- import { cn } from "@/lib/utils"
1
+ import { type ReactElement } from "react";
2
+ import * as React from "react";
3
+ import { cva, type VariantProps } from "class-variance-authority";
4
+ import { cn } from "@/lib/utils";
5
5
 
6
6
  /**
7
7
  * Alert — WealthX Design System
@@ -11,30 +11,30 @@ import { cn } from "@/lib/utils"
11
11
  * WealthX overrides: sharp corners (no rounded-lg), added warning/success/info variants
12
12
  */
13
13
  const alertVariants = cva(
14
- "relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
14
+ "relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 border px-4 py-3 text-body-small has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
15
15
  {
16
16
  variants: {
17
17
  variant: {
18
- default: "border-border bg-card text-card-foreground",
19
- destructive: "border-destructive/40 bg-destructive/10 text-destructive *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-destructive",
20
- warning: "border-warning/40 bg-warning/10 text-warning *:data-[slot=alert-description]:text-warning/90 [&>svg]:text-warning",
21
- success: "border-success/40 bg-success/10 text-success *:data-[slot=alert-description]:text-success/90 [&>svg]:text-success",
22
- info: "border-info/40 bg-info/10 text-info *:data-[slot=alert-description]:text-info/90 [&>svg]:text-info",
18
+ default: "border-border bg-card text-card-foreground",
19
+ destructive:
20
+ "border-destructive/40 bg-destructive/10 text-destructive *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-destructive",
21
+ warning:
22
+ "border-warning/40 bg-warning/10 text-warning *:data-[slot=alert-description]:text-warning/90 [&>svg]:text-warning",
23
+ success:
24
+ "border-success/40 bg-success/10 text-success *:data-[slot=alert-description]:text-success/90 [&>svg]:text-success",
25
+ info: "border-info/40 bg-info/10 text-info *:data-[slot=alert-description]:text-info/90 [&>svg]:text-info",
23
26
  },
24
27
  },
25
28
  defaultVariants: {
26
29
  variant: "default",
27
30
  },
28
- }
29
- )
31
+ },
32
+ );
30
33
 
31
- export type AlertProps = React.ComponentProps<"div"> & VariantProps<typeof alertVariants>
34
+ export type AlertProps = React.ComponentProps<"div"> &
35
+ VariantProps<typeof alertVariants>;
32
36
 
33
- function Alert({
34
- className,
35
- variant,
36
- ...props
37
- }: AlertProps): ReactElement {
37
+ function Alert({ className, variant, ...props }: AlertProps): ReactElement {
38
38
  return (
39
39
  <div
40
40
  className={cn(alertVariants({ variant }), className)}
@@ -42,25 +42,25 @@ function Alert({
42
42
  role="alert"
43
43
  {...props}
44
44
  />
45
- )
45
+ );
46
46
  }
47
47
 
48
- export type AlertTitleProps = React.ComponentProps<"div">
48
+ export type AlertTitleProps = React.ComponentProps<"div">;
49
49
 
50
50
  function AlertTitle({ className, ...props }: AlertTitleProps): ReactElement {
51
51
  return (
52
52
  <div
53
53
  className={cn(
54
- "col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
55
- className
54
+ "col-start-2 line-clamp-1 min-h-4 text-label-medium",
55
+ className,
56
56
  )}
57
57
  data-slot="alert-title"
58
58
  {...props}
59
59
  />
60
- )
60
+ );
61
61
  }
62
62
 
63
- export type AlertDescriptionProps = React.ComponentProps<"div">
63
+ export type AlertDescriptionProps = React.ComponentProps<"div">;
64
64
 
65
65
  function AlertDescription({
66
66
  className,
@@ -69,13 +69,13 @@ function AlertDescription({
69
69
  return (
70
70
  <div
71
71
  className={cn(
72
- "col-start-2 grid justify-items-start gap-1 text-sm text-muted-foreground [&_p]:leading-relaxed",
73
- className
72
+ "col-start-2 grid justify-items-start gap-1 text-body-small text-muted-foreground [&_p]:leading-relaxed",
73
+ className,
74
74
  )}
75
75
  data-slot="alert-description"
76
76
  {...props}
77
77
  />
78
- )
78
+ );
79
79
  }
80
80
 
81
- export { Alert, AlertTitle, AlertDescription }
81
+ export { Alert, AlertTitle, AlertDescription };
@@ -1,7 +1,7 @@
1
- import { type ReactElement } from "react"
2
- import * as React from "react"
3
- import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar"
4
- import { cn } from "@/lib/utils"
1
+ import { type ReactElement } from "react";
2
+ import * as React from "react";
3
+ import { Avatar as AvatarPrimitive } from "@base-ui/react/avatar";
4
+ import { cn } from "@/lib/utils";
5
5
 
6
6
  /**
7
7
  * Avatar — shadcn/WealthX
@@ -15,8 +15,8 @@ import { cn } from "@/lib/utils"
15
15
  */
16
16
 
17
17
  export type AvatarProps = React.ComponentProps<typeof AvatarPrimitive.Root> & {
18
- size?: "default" | "sm" | "lg"
19
- }
18
+ size?: "default" | "sm" | "lg";
19
+ };
20
20
 
21
21
  function Avatar({
22
22
  className,
@@ -27,31 +27,32 @@ function Avatar({
27
27
  <AvatarPrimitive.Root
28
28
  className={cn(
29
29
  "group/avatar relative flex size-8 shrink-0 rounded-full select-none data-[size=lg]:size-10 data-[size=sm]:size-6",
30
- className
30
+ className,
31
31
  )}
32
32
  data-size={size}
33
33
  data-slot="avatar"
34
34
  {...props}
35
35
  />
36
- )
36
+ );
37
37
  }
38
38
 
39
- export type AvatarImageProps = React.ComponentProps<typeof AvatarPrimitive.Image>
39
+ export type AvatarImageProps = React.ComponentProps<
40
+ typeof AvatarPrimitive.Image
41
+ >;
40
42
 
41
- function AvatarImage({
42
- className,
43
- ...props
44
- }: AvatarImageProps): ReactElement {
43
+ function AvatarImage({ className, ...props }: AvatarImageProps): ReactElement {
45
44
  return (
46
45
  <AvatarPrimitive.Image
47
46
  className={cn("aspect-square size-full rounded-full", className)}
48
47
  data-slot="avatar-image"
49
48
  {...props}
50
49
  />
51
- )
50
+ );
52
51
  }
53
52
 
54
- export type AvatarFallbackProps = React.ComponentProps<typeof AvatarPrimitive.Fallback>
53
+ export type AvatarFallbackProps = React.ComponentProps<
54
+ typeof AvatarPrimitive.Fallback
55
+ >;
55
56
 
56
57
  function AvatarFallback({
57
58
  className,
@@ -60,16 +61,16 @@ function AvatarFallback({
60
61
  return (
61
62
  <AvatarPrimitive.Fallback
62
63
  className={cn(
63
- "flex size-full items-center justify-center rounded-full overflow-hidden bg-muted text-sm font-sans text-muted-foreground group-data-[size=sm]/avatar:text-xs",
64
- className
64
+ "flex size-full items-center justify-center rounded-full overflow-hidden bg-muted text-body-small font-sans text-muted-foreground group-data-[size=sm]/avatar:text-caption",
65
+ className,
65
66
  )}
66
67
  data-slot="avatar-fallback"
67
68
  {...props}
68
69
  />
69
- )
70
+ );
70
71
  }
71
72
 
72
- export type AvatarBadgeProps = React.ComponentProps<"span">
73
+ export type AvatarBadgeProps = React.ComponentProps<"span">;
73
74
 
74
75
  function AvatarBadge({ className, ...props }: AvatarBadgeProps): ReactElement {
75
76
  return (
@@ -79,30 +80,30 @@ function AvatarBadge({ className, ...props }: AvatarBadgeProps): ReactElement {
79
80
  "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
80
81
  "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
81
82
  "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
82
- className
83
+ className,
83
84
  )}
84
85
  data-slot="avatar-badge"
85
86
  {...props}
86
87
  />
87
- )
88
+ );
88
89
  }
89
90
 
90
- export type AvatarGroupProps = React.ComponentProps<"div">
91
+ export type AvatarGroupProps = React.ComponentProps<"div">;
91
92
 
92
93
  function AvatarGroup({ className, ...props }: AvatarGroupProps): ReactElement {
93
94
  return (
94
95
  <div
95
96
  className={cn(
96
97
  "group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
97
- className
98
+ className,
98
99
  )}
99
100
  data-slot="avatar-group"
100
101
  {...props}
101
102
  />
102
- )
103
+ );
103
104
  }
104
105
 
105
- export type AvatarGroupCountProps = React.ComponentProps<"div">
106
+ export type AvatarGroupCountProps = React.ComponentProps<"div">;
106
107
 
107
108
  function AvatarGroupCount({
108
109
  className,
@@ -111,13 +112,13 @@ function AvatarGroupCount({
111
112
  return (
112
113
  <div
113
114
  className={cn(
114
- "relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
115
- className
115
+ "relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-body-small text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
116
+ className,
116
117
  )}
117
118
  data-slot="avatar-group-count"
118
119
  {...props}
119
120
  />
120
- )
121
+ );
121
122
  }
122
123
 
123
124
  export {
@@ -127,4 +128,4 @@ export {
127
128
  AvatarBadge,
128
129
  AvatarGroup,
129
130
  AvatarGroupCount,
130
- }
131
+ };
@@ -0,0 +1,260 @@
1
+ import React, { useMemo, useState } from "react";
2
+ import {
3
+ Chart as ChartJS,
4
+ CategoryScale,
5
+ LinearScale,
6
+ BarElement,
7
+ Tooltip,
8
+ type ChartOptions,
9
+ type ChartData,
10
+ } from "chart.js";
11
+ import { Chart } from "react-chartjs-2";
12
+ import { useThemeVars } from "@/lib/theme-provider";
13
+ import { Card, CardContent, CardHeader, CardTitle, CardAction } from "./card";
14
+ import { Empty, EmptyDescription } from "./empty";
15
+ import { Skeleton } from "./skeleton";
16
+ import { cn } from "@/lib/utils";
17
+ import {
18
+ FALLBACK_TICK,
19
+ SEVERITY_COLORS,
20
+ formatTooltipDate,
21
+ formatMonthLabel,
22
+ formatCount,
23
+ ChartLegendItem,
24
+ ChartPeriodButton,
25
+ } from "./chart-shared";
26
+
27
+ ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip);
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Types
31
+ // ---------------------------------------------------------------------------
32
+
33
+ export interface AlertHistoryDataPoint {
34
+ /** ISO date string e.g. "2024-01-01" */
35
+ date: string;
36
+ /** Count of high-severity alerts */
37
+ high: number;
38
+ /** Count of medium-severity alerts */
39
+ medium: number;
40
+ /** Count of low-severity alerts */
41
+ low: number;
42
+ }
43
+
44
+ export type AlertHistoryPeriod = 3 | 6 | 12;
45
+
46
+ export interface BackofficeAlertHistoryChartProps {
47
+ chartData?: AlertHistoryDataPoint[] | null;
48
+ title?: string;
49
+ /** Show or hide the chart legend */
50
+ showLegend?: boolean;
51
+ /** Legend placement relative to the chart */
52
+ legendPosition?: "top" | "bottom";
53
+ /** Show or hide X axis labels */
54
+ showXAxis?: boolean;
55
+ /** Show or hide Y axis labels */
56
+ showYAxis?: boolean;
57
+ /** Default period selector value */
58
+ defaultPeriod?: AlertHistoryPeriod;
59
+ /** Chart canvas height in pixels */
60
+ height?: number;
61
+ /** Card max-width in pixels or CSS string */
62
+ width?: number | string;
63
+ className?: string;
64
+ /** Show skeleton loading state instead of the chart */
65
+ isLoading?: boolean;
66
+ }
67
+
68
+ // ---------------------------------------------------------------------------
69
+ // Constants
70
+ // ---------------------------------------------------------------------------
71
+
72
+ const ALERT_PERIODS: AlertHistoryPeriod[] = [3, 6, 12];
73
+ const SLICE_COUNT: Record<AlertHistoryPeriod, number> = { 3: 3, 6: 6, 12: 12 };
74
+
75
+ // ---------------------------------------------------------------------------
76
+ // Legend
77
+ // ---------------------------------------------------------------------------
78
+
79
+ function ChartLegend() {
80
+ return (
81
+ <div className="flex flex-wrap gap-x-3 gap-y-1.5 pb-2">
82
+ <ChartLegendItem label="High" color={SEVERITY_COLORS.high} />
83
+ <ChartLegendItem label="Medium" color={SEVERITY_COLORS.medium} />
84
+ <ChartLegendItem label="Low" color={SEVERITY_COLORS.low} />
85
+ </div>
86
+ );
87
+ }
88
+
89
+ // ---------------------------------------------------------------------------
90
+ // Component
91
+ // ---------------------------------------------------------------------------
92
+
93
+ export function BackofficeAlertHistoryChart({
94
+ chartData,
95
+ title = "Alert History",
96
+ showLegend = true,
97
+ legendPosition = "top",
98
+ showXAxis = true,
99
+ showYAxis = false,
100
+ defaultPeriod = 6,
101
+ height = 200,
102
+ width = "100%",
103
+ className,
104
+ isLoading = false,
105
+ }: BackofficeAlertHistoryChartProps) {
106
+ const [period, setPeriod] = useState<AlertHistoryPeriod>(defaultPeriod);
107
+
108
+ const themeVars = useThemeVars();
109
+ const fontFamily: string =
110
+ (themeVars["--font-sans"] as string | undefined) || "Figtree, sans-serif";
111
+
112
+ const sliced = useMemo<AlertHistoryDataPoint[] | null>(() => {
113
+ if (!chartData?.length) return null;
114
+ const count = Math.min(SLICE_COUNT[period], chartData.length);
115
+ return chartData.slice(chartData.length - count);
116
+ }, [chartData, period]);
117
+
118
+ const labels = useMemo(
119
+ () => sliced?.map((p) => formatMonthLabel(p.date)) ?? [],
120
+ [sliced],
121
+ );
122
+
123
+ const data = useMemo<ChartData<"bar">>(() => {
124
+ if (!sliced) return { labels: [], datasets: [] };
125
+ return {
126
+ labels,
127
+ datasets: [
128
+ {
129
+ label: "High",
130
+ data: sliced.map((p) => p.high),
131
+ backgroundColor: SEVERITY_COLORS.high,
132
+ borderWidth: 0,
133
+ stack: "alerts",
134
+ },
135
+ {
136
+ label: "Medium",
137
+ data: sliced.map((p) => p.medium),
138
+ backgroundColor: SEVERITY_COLORS.medium,
139
+ borderWidth: 0,
140
+ stack: "alerts",
141
+ },
142
+ {
143
+ label: "Low",
144
+ data: sliced.map((p) => p.low),
145
+ backgroundColor: SEVERITY_COLORS.low,
146
+ borderWidth: 0,
147
+ stack: "alerts",
148
+ },
149
+ ],
150
+ };
151
+ }, [sliced, labels]);
152
+
153
+ const options = useMemo<ChartOptions<"bar">>(
154
+ () => ({
155
+ responsive: true,
156
+ maintainAspectRatio: false,
157
+ animation: { duration: 600, easing: "easeOutQuart" },
158
+ layout: { padding: 0 },
159
+ plugins: {
160
+ legend: { display: false },
161
+ tooltip: {
162
+ mode: "index",
163
+ intersect: false,
164
+ padding: 12,
165
+ cornerRadius: 0,
166
+ titleFont: { size: 11, weight: 600 },
167
+ bodyFont: { size: 12, weight: 500 },
168
+ callbacks: {
169
+ title: (tooltipItems) => {
170
+ const idx = tooltipItems[0]?.dataIndex;
171
+ if (idx != null && sliced?.[idx]?.date) {
172
+ return formatTooltipDate(sliced[idx].date, "monthly");
173
+ }
174
+ return tooltipItems[0]?.label ?? "";
175
+ },
176
+ label: (ctx) => {
177
+ const val = ctx.raw as number;
178
+ if (val === 0) return;
179
+ return ` ${ctx.dataset.label}: ${formatCount(val)}`;
180
+ },
181
+ },
182
+ },
183
+ },
184
+ scales: {
185
+ x: {
186
+ stacked: true,
187
+ display: showXAxis,
188
+ grid: { display: false },
189
+ border: { display: false },
190
+ ticks: {
191
+ maxRotation: 0,
192
+ minRotation: 0,
193
+ color: FALLBACK_TICK,
194
+ font: { size: 10 },
195
+ },
196
+ },
197
+ y: {
198
+ stacked: true,
199
+ display: showYAxis,
200
+ grid: { display: false },
201
+ border: { display: false },
202
+ ticks: {
203
+ padding: 8,
204
+ maxTicksLimit: 5,
205
+ color: FALLBACK_TICK,
206
+ font: { size: 10 },
207
+ callback: (v) => formatCount(Number(v)),
208
+ },
209
+ },
210
+ },
211
+ }),
212
+ [showXAxis, showYAxis, sliced],
213
+ );
214
+
215
+ return (
216
+ <Card
217
+ className={cn("w-full py-4 sm:py-6 gap-2", className)}
218
+ style={{ maxWidth: width, fontFamily }}
219
+ >
220
+ <CardHeader className="px-3 sm:px-6">
221
+ <CardTitle className="text-sm sm:text-base">{title}</CardTitle>
222
+ <CardAction>
223
+ <div className="flex gap-0.5 sm:gap-1">
224
+ {ALERT_PERIODS.map((p) => (
225
+ <ChartPeriodButton
226
+ key={p}
227
+ period={p}
228
+ active={period === p}
229
+ onClick={() => setPeriod(p)}
230
+ />
231
+ ))}
232
+ </div>
233
+ </CardAction>
234
+ </CardHeader>
235
+
236
+ <CardContent className="px-3 sm:px-6">
237
+ {isLoading ? (
238
+ <Skeleton style={{ height, width: "100%" }} />
239
+ ) : !sliced ? (
240
+ <Empty className="flex-none p-4" style={{ height }}>
241
+ <EmptyDescription>No data available</EmptyDescription>
242
+ </Empty>
243
+ ) : (
244
+ <div className="flex flex-col gap-2">
245
+ {showLegend && legendPosition === "top" && <ChartLegend />}
246
+ <div style={{ height, width: "100%", position: "relative" }}>
247
+ <Chart
248
+ type="bar"
249
+ data={data}
250
+ options={options}
251
+ aria-label={title}
252
+ />
253
+ </div>
254
+ {showLegend && legendPosition === "bottom" && <ChartLegend />}
255
+ </div>
256
+ )}
257
+ </CardContent>
258
+ </Card>
259
+ );
260
+ }