@wealthx/shadcn 1.0.2 → 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 -138
  2. package/CHANGELOG.md +12 -0
  3. package/README.md +82 -0
  4. package/dist/{chunk-6OJF6XRN.mjs → chunk-24FUO7TD.mjs} +4 -8
  5. package/dist/{chunk-4AJ5HWHD.mjs → chunk-2I5S2AMY.mjs} +3 -3
  6. package/dist/chunk-2SF672SZ.mjs +161 -0
  7. package/dist/{chunk-GPRJQ24C.mjs → chunk-34NWQURD.mjs} +2 -2
  8. package/dist/{chunk-MQ72DIBH.mjs → chunk-3GF7OVTP.mjs} +14 -5
  9. package/dist/chunk-3WMX6KWS.mjs +245 -0
  10. package/dist/{chunk-PMKODV6M.mjs → chunk-462HMNO4.mjs} +6 -10
  11. package/dist/chunk-4CX4SBRO.mjs +153 -0
  12. package/dist/chunk-4MN6UQHG.mjs +443 -0
  13. package/dist/chunk-5QQVZTVZ.mjs +233 -0
  14. package/dist/{chunk-BGP2N52Z.mjs → chunk-66MI7Q4B.mjs} +5 -5
  15. package/dist/chunk-6FCGKSZX.mjs +268 -0
  16. package/dist/{chunk-CGOKTPXU.mjs → chunk-6JQFUE5I.mjs} +20 -23
  17. package/dist/{chunk-Z3MK2KKZ.mjs → chunk-7DHU4VGG.mjs} +7 -3
  18. package/dist/{chunk-VZ2NR7L3.mjs → chunk-7PYJD5JI.mjs} +35 -27
  19. package/dist/{chunk-JU2RUWHF.mjs → chunk-7XJHLGUV.mjs} +1 -1
  20. package/dist/{chunk-BMFN37JH.mjs → chunk-7YAU5CY6.mjs} +1 -1
  21. package/dist/chunk-A56YQQHG.mjs +402 -0
  22. package/dist/chunk-AH52LG6N.mjs +315 -0
  23. package/dist/{chunk-SLWCCURD.mjs → chunk-CLIN5525.mjs} +8 -4
  24. package/dist/{chunk-3VQNJ235.mjs → chunk-CSDO6VBW.mjs} +7 -0
  25. package/dist/chunk-D4ILTPOG.mjs +293 -0
  26. package/dist/{chunk-HS7TFG7V.mjs → chunk-D6ID6M4V.mjs} +1 -1
  27. package/dist/chunk-DOH3EHX7.mjs +378 -0
  28. package/dist/{chunk-MJIEMGRD.mjs → chunk-EFRENWEJ.mjs} +9 -17
  29. package/dist/chunk-ERGGHC2V.mjs +185 -0
  30. package/dist/{chunk-OXQQNQZI.mjs → chunk-FEZKMUCF.mjs} +10 -1
  31. package/dist/{chunk-55CEW76V.mjs → chunk-FH6QVUVZ.mjs} +1 -1
  32. package/dist/chunk-FMAXJ2SI.mjs +71 -0
  33. package/dist/chunk-FZIXGLMV.mjs +173 -0
  34. package/dist/{chunk-DS2AMHN2.mjs → chunk-GYMYRIZP.mjs} +2 -2
  35. package/dist/{chunk-KQDD5MU3.mjs → chunk-H45TKD34.mjs} +5 -5
  36. package/dist/{chunk-BBJBJSXQ.mjs → chunk-J5UICVJS.mjs} +1 -1
  37. package/dist/{chunk-RL772EH7.mjs → chunk-JHJHG4GO.mjs} +4 -12
  38. package/dist/chunk-KMCGSZTX.mjs +177 -0
  39. package/dist/{chunk-FHNT55I5.mjs → chunk-KUDCQ4FI.mjs} +4 -4
  40. package/dist/chunk-LE6YFY6D.mjs +209 -0
  41. package/dist/{chunk-HUVTPUV2.mjs → chunk-LLVQKSU3.mjs} +23 -19
  42. package/dist/{chunk-KKHTJNMM.mjs → chunk-MARPPFOJ.mjs} +8 -4
  43. package/dist/{chunk-6AFMNC42.mjs → chunk-N2PT566P.mjs} +15 -11
  44. package/dist/chunk-NLCKVHWB.mjs +161 -0
  45. package/dist/{chunk-YN5SYTOO.mjs → chunk-NQPOYKAQ.mjs} +9 -5
  46. package/dist/{chunk-ZZV5JVNW.mjs → chunk-NSLMILBT.mjs} +3 -7
  47. package/dist/chunk-NXA3CZ7A.mjs +248 -0
  48. package/dist/chunk-OGOYQ7BG.mjs +150 -0
  49. package/dist/{chunk-3NQGYJEZ.mjs → chunk-P6AM5V7O.mjs} +10 -18
  50. package/dist/{chunk-CZ3BW5GL.mjs → chunk-P76HMUI6.mjs} +5 -11
  51. package/dist/chunk-PCPLO5HT.mjs +671 -0
  52. package/dist/chunk-PG6K5XEC.mjs +475 -0
  53. package/dist/chunk-PJHPSRYD.mjs +234 -0
  54. package/dist/{chunk-DDPA2XXS.mjs → chunk-PMB3A7V3.mjs} +2 -2
  55. package/dist/chunk-PR6V5XKM.mjs +209 -0
  56. package/dist/{chunk-46OFHMQA.mjs → chunk-Q76O3RIQ.mjs} +10 -6
  57. package/dist/chunk-QVKWW6KE.mjs +272 -0
  58. package/dist/chunk-RGU7HOEC.mjs +140 -0
  59. package/dist/{chunk-JF4PHPD5.mjs → chunk-RGVKLTLH.mjs} +4 -4
  60. package/dist/{chunk-VG6UF6UT.mjs → chunk-RP3SQYA3.mjs} +2 -2
  61. package/dist/chunk-RRBS6D63.mjs +163 -0
  62. package/dist/chunk-SMQ3DG25.mjs +285 -0
  63. package/dist/chunk-SPJ5KXW7.mjs +199 -0
  64. package/dist/chunk-SYOD63OZ.mjs +225 -0
  65. package/dist/chunk-UFYSFDER.mjs +42 -0
  66. package/dist/chunk-VACKZOMY.mjs +190 -0
  67. package/dist/chunk-VLQZANBF.mjs +42 -0
  68. package/dist/chunk-WA6O6EUR.mjs +1885 -0
  69. package/dist/{chunk-E3K6O4FZ.mjs → chunk-WAZD7NFU.mjs} +5 -2
  70. package/dist/chunk-WG6JGJXB.mjs +165 -0
  71. package/dist/{chunk-I64K754C.mjs → chunk-WNGWBVLV.mjs} +2 -2
  72. package/dist/{chunk-3U7SD3MS.mjs → chunk-WOEHFRGB.mjs} +3 -3
  73. package/dist/{chunk-DKZRJOMF.mjs → chunk-XIRTEFKH.mjs} +12 -12
  74. package/dist/chunk-Y6DWJSKZ.mjs +79 -0
  75. package/dist/chunk-YKPROFLB.mjs +161 -0
  76. package/dist/{chunk-K76E2TQU.mjs → chunk-ZRO5JO3H.mjs} +107 -67
  77. package/dist/{chunk-VYMHBV6D.mjs → chunk-ZU4NV6RG.mjs} +5 -3
  78. package/dist/components/ui/accordion.js +40 -4
  79. package/dist/components/ui/accordion.mjs +2 -2
  80. package/dist/components/ui/add-column-modal.js +789 -0
  81. package/dist/components/ui/add-column-modal.mjs +17 -0
  82. package/dist/components/ui/add-lead-modal.js +647 -0
  83. package/dist/components/ui/add-lead-modal.mjs +16 -0
  84. package/dist/components/ui/ai-assistant-drawer.js +686 -0
  85. package/dist/components/ui/ai-assistant-drawer.mjs +16 -0
  86. package/dist/components/ui/alert-dialog.js +37 -5
  87. package/dist/components/ui/alert-dialog.mjs +4 -4
  88. package/dist/components/ui/alert.js +37 -11
  89. package/dist/components/ui/alert.mjs +2 -2
  90. package/dist/components/ui/avatar.js +36 -8
  91. package/dist/components/ui/avatar.mjs +2 -2
  92. package/dist/components/ui/backoffice-alert-history-chart.js +624 -0
  93. package/dist/components/ui/backoffice-alert-history-chart.mjs +16 -0
  94. package/dist/components/ui/backoffice-contact-history-chart.js +687 -0
  95. package/dist/components/ui/backoffice-contact-history-chart.mjs +16 -0
  96. package/dist/components/ui/badge.js +37 -2
  97. package/dist/components/ui/badge.mjs +2 -2
  98. package/dist/components/ui/borrowing-capacity-line-chart.js +639 -0
  99. package/dist/components/ui/borrowing-capacity-line-chart.mjs +16 -0
  100. package/dist/components/ui/button.js +35 -3
  101. package/dist/components/ui/button.mjs +2 -2
  102. package/dist/components/ui/calendar.js +43 -19
  103. package/dist/components/ui/calendar.mjs +3 -3
  104. package/dist/components/ui/card.js +40 -4
  105. package/dist/components/ui/card.mjs +2 -2
  106. package/dist/components/ui/cash-balance-line-chart.js +627 -0
  107. package/dist/components/ui/cash-balance-line-chart.mjs +16 -0
  108. package/dist/components/ui/cashflow-bar-chart.js +650 -0
  109. package/dist/components/ui/cashflow-bar-chart.mjs +16 -0
  110. package/dist/components/ui/checkbox.js +36 -5
  111. package/dist/components/ui/checkbox.mjs +2 -3
  112. package/dist/components/ui/chip.js +37 -2
  113. package/dist/components/ui/chip.mjs +3 -3
  114. package/dist/components/ui/combobox.js +280 -0
  115. package/dist/components/ui/combobox.mjs +28 -0
  116. package/dist/components/ui/data-table.js +160 -88
  117. package/dist/components/ui/data-table.mjs +10 -11
  118. package/dist/components/ui/date-picker.js +44 -20
  119. package/dist/components/ui/date-picker.mjs +6 -7
  120. package/dist/components/ui/dialog.js +44 -12
  121. package/dist/components/ui/dialog.mjs +4 -4
  122. package/dist/components/ui/drawer.js +46 -10
  123. package/dist/components/ui/drawer.mjs +3 -3
  124. package/dist/components/ui/dropdown-menu.js +40 -16
  125. package/dist/components/ui/dropdown-menu.mjs +3 -3
  126. package/dist/components/ui/empty.js +41 -5
  127. package/dist/components/ui/empty.mjs +2 -2
  128. package/dist/components/ui/expense-bar-chart.js +642 -0
  129. package/dist/components/ui/expense-bar-chart.mjs +16 -0
  130. package/dist/components/ui/field.js +53 -21
  131. package/dist/components/ui/field.mjs +4 -4
  132. package/dist/components/ui/financial-cards.js +1002 -0
  133. package/dist/components/ui/financial-cards.mjs +24 -0
  134. package/dist/components/ui/financial-drawers.js +637 -0
  135. package/dist/components/ui/financial-drawers.mjs +17 -0
  136. package/dist/components/ui/financial-primitives.js +218 -0
  137. package/dist/components/ui/financial-primitives.mjs +22 -0
  138. package/dist/components/ui/financial-sections.js +1422 -0
  139. package/dist/components/ui/financial-sections.mjs +30 -0
  140. package/dist/components/ui/form-primitives.js +682 -0
  141. package/dist/components/ui/form-primitives.mjs +19 -0
  142. package/dist/components/ui/income-bar-chart.js +641 -0
  143. package/dist/components/ui/income-bar-chart.mjs +16 -0
  144. package/dist/components/ui/input-group.js +43 -7
  145. package/dist/components/ui/input-group.mjs +5 -5
  146. package/dist/components/ui/input-otp.js +39 -3
  147. package/dist/components/ui/input-otp.mjs +2 -2
  148. package/dist/components/ui/input.js +34 -2
  149. package/dist/components/ui/input.mjs +2 -2
  150. package/dist/components/ui/kanban-column.js +1143 -0
  151. package/dist/components/ui/kanban-column.mjs +20 -0
  152. package/dist/components/ui/label.js +35 -7
  153. package/dist/components/ui/label.mjs +2 -2
  154. package/dist/components/ui/opportunity-card.js +960 -0
  155. package/dist/components/ui/opportunity-card.mjs +20 -0
  156. package/dist/components/ui/opportunity-edit-modals.js +3360 -0
  157. package/dist/components/ui/opportunity-edit-modals.mjs +37 -0
  158. package/dist/components/ui/opportunity-summary-tab.js +4365 -0
  159. package/dist/components/ui/opportunity-summary-tab.mjs +34 -0
  160. package/dist/components/ui/pagination.js +35 -3
  161. package/dist/components/ui/pagination.mjs +3 -3
  162. package/dist/components/ui/pipeline-alerts.js +103 -0
  163. package/dist/components/ui/pipeline-alerts.mjs +8 -0
  164. package/dist/components/ui/pipeline-board.js +1408 -0
  165. package/dist/components/ui/pipeline-board.mjs +24 -0
  166. package/dist/components/ui/pipeline-chart.js +216 -0
  167. package/dist/components/ui/pipeline-chart.mjs +10 -0
  168. package/dist/components/ui/pipeline-dialogs.js +1183 -0
  169. package/dist/components/ui/pipeline-dialogs.mjs +23 -0
  170. package/dist/components/ui/pipeline-primitives.js +300 -0
  171. package/dist/components/ui/pipeline-primitives.mjs +11 -0
  172. package/dist/components/ui/popover.js +45 -4
  173. package/dist/components/ui/popover.mjs +3 -3
  174. package/dist/components/ui/progress.js +33 -1
  175. package/dist/components/ui/progress.mjs +2 -2
  176. package/dist/components/ui/property-cashflow-doughnut-chart.js +523 -0
  177. package/dist/components/ui/property-cashflow-doughnut-chart.mjs +16 -0
  178. package/dist/components/ui/property-debt-equity-doughnut-chart.js +521 -0
  179. package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +16 -0
  180. package/dist/components/ui/property-mobile-estimate-line-chart.js +682 -0
  181. package/dist/components/ui/property-mobile-estimate-line-chart.mjs +16 -0
  182. package/dist/components/ui/radio-group.js +33 -1
  183. package/dist/components/ui/radio-group.mjs +2 -2
  184. package/dist/components/ui/select.js +66 -26
  185. package/dist/components/ui/select.mjs +3 -3
  186. package/dist/components/ui/separator.js +33 -1
  187. package/dist/components/ui/separator.mjs +2 -2
  188. package/dist/components/ui/sheet.js +37 -9
  189. package/dist/components/ui/sheet.mjs +3 -3
  190. package/dist/components/ui/skeleton.js +33 -1
  191. package/dist/components/ui/skeleton.mjs +2 -2
  192. package/dist/components/ui/slider.js +86 -102
  193. package/dist/components/ui/slider.mjs +2 -2
  194. package/dist/components/ui/spinner.js +33 -1
  195. package/dist/components/ui/spinner.mjs +2 -2
  196. package/dist/components/ui/stage-timeline.js +579 -0
  197. package/dist/components/ui/stage-timeline.mjs +15 -0
  198. package/dist/components/ui/switch.js +37 -4
  199. package/dist/components/ui/switch.mjs +2 -3
  200. package/dist/components/ui/table.js +37 -5
  201. package/dist/components/ui/table.mjs +2 -2
  202. package/dist/components/ui/tabs.js +36 -12
  203. package/dist/components/ui/tabs.mjs +2 -2
  204. package/dist/components/ui/textarea.js +34 -2
  205. package/dist/components/ui/textarea.mjs +2 -2
  206. package/dist/components/ui/toggle-group.js +35 -4
  207. package/dist/components/ui/toggle-group.mjs +3 -4
  208. package/dist/components/ui/toggle.js +35 -4
  209. package/dist/components/ui/toggle.mjs +2 -3
  210. package/dist/components/ui/tooltip.js +51 -22
  211. package/dist/components/ui/tooltip.mjs +3 -3
  212. package/dist/components/ui/transactions-expense-categories-doughnut-chart.js +528 -0
  213. package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +16 -0
  214. package/dist/components/ui/transactions-income-expense-bar-chart.js +516 -0
  215. package/dist/components/ui/transactions-income-expense-bar-chart.mjs +16 -0
  216. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.js +528 -0
  217. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +16 -0
  218. package/dist/index.js +11613 -2868
  219. package/dist/index.mjs +377 -164
  220. package/dist/lib/theme-provider.js +10 -1
  221. package/dist/lib/theme-provider.mjs +1 -1
  222. package/dist/lib/typography.js +8 -0
  223. package/dist/lib/typography.mjs +3 -1
  224. package/dist/lib/utils.js +33 -1
  225. package/dist/lib/utils.mjs +1 -1
  226. package/dist/styles.css +1 -1
  227. package/package.json +169 -6
  228. package/src/components/index.tsx +323 -13
  229. package/src/components/ui/accordion.tsx +6 -3
  230. package/src/components/ui/add-column-modal.tsx +339 -0
  231. package/src/components/ui/add-lead-modal.tsx +290 -0
  232. package/src/components/ui/ai-assistant-drawer.tsx +408 -0
  233. package/src/components/ui/alert-dialog.tsx +80 -54
  234. package/src/components/ui/alert.tsx +28 -28
  235. package/src/components/ui/avatar.tsx +30 -29
  236. package/src/components/ui/backoffice-alert-history-chart.tsx +260 -0
  237. package/src/components/ui/backoffice-contact-history-chart.tsx +325 -0
  238. package/src/components/ui/badge.tsx +17 -15
  239. package/src/components/ui/borrowing-capacity-line-chart.tsx +357 -0
  240. package/src/components/ui/button.tsx +30 -27
  241. package/src/components/ui/calendar.tsx +53 -67
  242. package/src/components/ui/card.tsx +27 -24
  243. package/src/components/ui/cash-balance-line-chart.tsx +302 -0
  244. package/src/components/ui/cashflow-bar-chart.tsx +363 -0
  245. package/src/components/ui/chart-shared.tsx +261 -0
  246. package/src/components/ui/checkbox.tsx +30 -26
  247. package/src/components/ui/combobox.tsx +223 -0
  248. package/src/components/ui/data-table.tsx +160 -99
  249. package/src/components/ui/date-picker.tsx +0 -2
  250. package/src/components/ui/dialog.tsx +70 -60
  251. package/src/components/ui/drawer.tsx +57 -48
  252. package/src/components/ui/dropdown-menu.tsx +90 -82
  253. package/src/components/ui/empty.tsx +31 -27
  254. package/src/components/ui/expense-bar-chart.tsx +296 -0
  255. package/src/components/ui/field.tsx +70 -62
  256. package/src/components/ui/financial-cards.tsx +830 -0
  257. package/src/components/ui/financial-drawers.tsx +339 -0
  258. package/src/components/ui/financial-primitives.tsx +331 -0
  259. package/src/components/ui/financial-sections.tsx +672 -0
  260. package/src/components/ui/form-primitives.tsx +536 -0
  261. package/src/components/ui/income-bar-chart.tsx +297 -0
  262. package/src/components/ui/input-group.tsx +41 -34
  263. package/src/components/ui/input-otp.tsx +29 -24
  264. package/src/components/ui/input.tsx +8 -8
  265. package/src/components/ui/kanban-column.tsx +333 -0
  266. package/src/components/ui/label.tsx +9 -12
  267. package/src/components/ui/opportunity-card.tsx +616 -0
  268. package/src/components/ui/opportunity-edit-modals.tsx +2528 -0
  269. package/src/components/ui/opportunity-summary-tab.tsx +579 -0
  270. package/src/components/ui/pipeline-alerts.tsx +74 -0
  271. package/src/components/ui/pipeline-board.tsx +268 -0
  272. package/src/components/ui/pipeline-chart.tsx +173 -0
  273. package/src/components/ui/pipeline-dialogs.tsx +303 -0
  274. package/src/components/ui/pipeline-primitives.tsx +108 -0
  275. package/src/components/ui/popover.tsx +41 -36
  276. package/src/components/ui/property-cashflow-doughnut-chart.tsx +188 -0
  277. package/src/components/ui/property-debt-equity-doughnut-chart.tsx +185 -0
  278. package/src/components/ui/property-mobile-estimate-line-chart.tsx +393 -0
  279. package/src/components/ui/select.tsx +65 -52
  280. package/src/components/ui/sheet.tsx +55 -52
  281. package/src/components/ui/slider.tsx +54 -77
  282. package/src/components/ui/stage-timeline.tsx +205 -0
  283. package/src/components/ui/switch.tsx +42 -29
  284. package/src/components/ui/table.tsx +28 -28
  285. package/src/components/ui/tabs.tsx +22 -28
  286. package/src/components/ui/textarea.tsx +8 -8
  287. package/src/components/ui/toggle-group.tsx +0 -2
  288. package/src/components/ui/toggle.tsx +13 -15
  289. package/src/components/ui/tooltip.tsx +30 -28
  290. package/src/components/ui/transactions-expense-categories-doughnut-chart.tsx +191 -0
  291. package/src/components/ui/transactions-income-expense-bar-chart.tsx +205 -0
  292. package/src/components/ui/transactions-liabilities-breakdown-doughnut-chart.tsx +191 -0
  293. package/src/lib/theme-provider.tsx +10 -0
  294. package/src/lib/typography.ts +9 -0
  295. package/src/lib/utils.ts +41 -3
  296. package/src/styles/globals.css +371 -124
  297. package/src/styles/styles-css.ts +1 -1
  298. package/tsup.config.ts +32 -0
  299. package/dist/chunk-K74JRTJR.mjs +0 -105
  300. package/dist/chunk-V7CNWJT3.mjs +0 -10
@@ -0,0 +1,303 @@
1
+ import * as React from "react";
2
+ import { addDays, startOfDay, format } from "date-fns";
3
+ import { cn } from "@/lib/utils";
4
+ import {
5
+ Dialog,
6
+ DialogContent,
7
+ DialogDescription,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ DialogFooter,
11
+ } from "@/components/ui/dialog";
12
+ import { Button } from "@/components/ui/button";
13
+ import {
14
+ Select,
15
+ SelectContent,
16
+ SelectItem,
17
+ SelectTrigger,
18
+ SelectValue,
19
+ } from "@/components/ui/select";
20
+ import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
21
+ import { DatePicker } from "@/components/ui/date-picker";
22
+
23
+ /**
24
+ * Pipeline Dialogs — WealthX DS (L4)
25
+ *
26
+ * Small, focused dialogs for Pipeline / Loan CRM actions:
27
+ * - DeleteOpportunityDialog — confirm card deletion
28
+ * - ChangePriorityDialog — select priority (Auto / Low / Medium / High)
29
+ * - PutOnHoldDialog — choose a hold-until date (preset or custom)
30
+ *
31
+ * All dialogs are fully controlled (`open` + `onOpenChange`).
32
+ * The `loading` prop disables actions and prevents accidental close.
33
+ */
34
+
35
+ // ---------------------------------------------------------------------------
36
+ // DeleteOpportunityDialog
37
+ // ---------------------------------------------------------------------------
38
+
39
+ export interface DeleteOpportunityDialogProps {
40
+ open: boolean;
41
+ /** Disables buttons and prevents close while an async op is in-flight. */
42
+ loading?: boolean;
43
+ onOpenChange: (open: boolean) => void;
44
+ onConfirm: () => void;
45
+ className?: string;
46
+ }
47
+
48
+ export function DeleteOpportunityDialog({
49
+ open,
50
+ loading = false,
51
+ onOpenChange,
52
+ onConfirm,
53
+ className,
54
+ }: DeleteOpportunityDialogProps) {
55
+ return (
56
+ <Dialog open={open} onOpenChange={loading ? undefined : onOpenChange}>
57
+ <DialogContent
58
+ showCloseButton={!loading}
59
+ className={cn("max-w-sm", className)}
60
+ >
61
+ <DialogHeader>
62
+ <DialogTitle>Want to delete this card?</DialogTitle>
63
+ <DialogDescription>
64
+ Doing so will also remove all associated loan applications and
65
+ tasks. This action cannot be undone.
66
+ </DialogDescription>
67
+ </DialogHeader>
68
+ <DialogFooter>
69
+ <Button
70
+ variant="outline"
71
+ onClick={() => onOpenChange(false)}
72
+ disabled={loading}
73
+ >
74
+ Cancel
75
+ </Button>
76
+ <Button variant="destructive" onClick={onConfirm} disabled={loading}>
77
+ {loading ? "Deleting…" : "Delete"}
78
+ </Button>
79
+ </DialogFooter>
80
+ </DialogContent>
81
+ </Dialog>
82
+ );
83
+ }
84
+
85
+ // ---------------------------------------------------------------------------
86
+ // ChangePriorityDialog
87
+ // ---------------------------------------------------------------------------
88
+
89
+ export type PrioritySelection = "auto" | "low" | "medium" | "high";
90
+
91
+ const PRIORITY_OPTIONS: {
92
+ value: PrioritySelection;
93
+ label: string;
94
+ color: string;
95
+ }[] = [
96
+ { value: "auto", label: "Auto", color: "var(--color-muted-foreground)" },
97
+ { value: "low", label: "Low", color: "var(--color-success)" },
98
+ { value: "medium", label: "Medium", color: "var(--color-warning)" },
99
+ { value: "high", label: "High", color: "var(--color-destructive)" },
100
+ ];
101
+
102
+ export interface ChangePriorityDialogProps {
103
+ open: boolean;
104
+ value: PrioritySelection;
105
+ loading?: boolean;
106
+ onOpenChange: (open: boolean) => void;
107
+ onSave: () => void;
108
+ onSelectionChange: (value: PrioritySelection) => void;
109
+ className?: string;
110
+ }
111
+
112
+ export function ChangePriorityDialog({
113
+ open,
114
+ value,
115
+ loading = false,
116
+ onOpenChange,
117
+ onSave,
118
+ onSelectionChange,
119
+ className,
120
+ }: ChangePriorityDialogProps) {
121
+ return (
122
+ <Dialog open={open} onOpenChange={loading ? undefined : onOpenChange}>
123
+ <DialogContent className={cn("max-w-sm", className)}>
124
+ <DialogHeader>
125
+ <DialogTitle>Change priority</DialogTitle>
126
+ </DialogHeader>
127
+ <Select
128
+ value={value}
129
+ onValueChange={(v) => onSelectionChange(v as PrioritySelection)}
130
+ >
131
+ <SelectTrigger className="w-full">
132
+ {(() => {
133
+ const opt = PRIORITY_OPTIONS.find((o) => o.value === value);
134
+ return opt ? (
135
+ <span className="flex items-center gap-2">
136
+ <span
137
+ className="inline-block size-2 shrink-0 rounded-full"
138
+ style={{ backgroundColor: opt.color }}
139
+ aria-hidden="true"
140
+ />
141
+ {opt.label}
142
+ </span>
143
+ ) : null;
144
+ })()}
145
+ </SelectTrigger>
146
+ <SelectContent>
147
+ {PRIORITY_OPTIONS.map((opt) => (
148
+ <SelectItem key={opt.value} value={opt.value}>
149
+ <span className="flex items-center gap-2">
150
+ <span
151
+ className="inline-block size-2 shrink-0 rounded-full"
152
+ style={{ backgroundColor: opt.color }}
153
+ aria-hidden="true"
154
+ />
155
+ {opt.label}
156
+ </span>
157
+ </SelectItem>
158
+ ))}
159
+ </SelectContent>
160
+ </Select>
161
+ <DialogFooter>
162
+ <Button
163
+ variant="outline"
164
+ onClick={() => onOpenChange(false)}
165
+ disabled={loading}
166
+ >
167
+ Cancel
168
+ </Button>
169
+ <Button onClick={onSave} disabled={loading}>
170
+ {loading ? "Saving…" : "Save"}
171
+ </Button>
172
+ </DialogFooter>
173
+ </DialogContent>
174
+ </Dialog>
175
+ );
176
+ }
177
+
178
+ // ---------------------------------------------------------------------------
179
+ // PutOnHoldDialog
180
+ // ---------------------------------------------------------------------------
181
+
182
+ export type HoldDuration = "90" | "180" | "360" | "custom";
183
+
184
+ const HOLD_OPTIONS: { value: HoldDuration; label: string }[] = [
185
+ { value: "90", label: "90 Days" },
186
+ { value: "180", label: "180 Days" },
187
+ { value: "360", label: "360 Days" },
188
+ { value: "custom", label: "Custom" },
189
+ ];
190
+
191
+ export interface PutOnHoldDialogProps {
192
+ open: boolean;
193
+ loading?: boolean;
194
+ onOpenChange: (open: boolean) => void;
195
+ /** Called with an ISO date string (yyyy-MM-dd) when the user saves. */
196
+ onSave: (isoDate: string) => void;
197
+ className?: string;
198
+ }
199
+
200
+ export function PutOnHoldDialog({
201
+ open,
202
+ loading = false,
203
+ onOpenChange,
204
+ onSave,
205
+ className,
206
+ }: PutOnHoldDialogProps) {
207
+ const [duration, setDuration] = React.useState<HoldDuration>("90");
208
+ const [customDate, setCustomDate] = React.useState<Date | undefined>();
209
+ const today = React.useMemo(() => startOfDay(new Date()), []);
210
+
211
+ const resolvedDate = React.useMemo<Date | undefined>(() => {
212
+ if (duration === "custom") return customDate;
213
+ return addDays(today, parseInt(duration, 10));
214
+ }, [duration, customDate, today]);
215
+
216
+ const isValid = resolvedDate !== undefined && resolvedDate >= today;
217
+
218
+ function handleSave() {
219
+ if (!resolvedDate) return;
220
+ onSave(format(resolvedDate, "yyyy-MM-dd"));
221
+ }
222
+
223
+ // Reset when dialog opens
224
+ React.useEffect(() => {
225
+ if (open) {
226
+ setDuration("90");
227
+ setCustomDate(undefined);
228
+ }
229
+ }, [open]);
230
+
231
+ return (
232
+ <Dialog open={open} onOpenChange={loading ? undefined : onOpenChange}>
233
+ <DialogContent className={cn("max-w-sm", className)}>
234
+ <DialogHeader>
235
+ <DialogTitle>Hold and Hide Until Later Date</DialogTitle>
236
+ </DialogHeader>
237
+ <div className="flex flex-col gap-4">
238
+ <ToggleGroup
239
+ type="single"
240
+ variant="outline"
241
+ size="sm"
242
+ value={[duration]}
243
+ onValueChange={(v) => {
244
+ if (v.length) setDuration(v[0] as HoldDuration);
245
+ }}
246
+ className="w-full"
247
+ >
248
+ {HOLD_OPTIONS.map((opt) => (
249
+ <ToggleGroupItem
250
+ key={opt.value}
251
+ value={opt.value}
252
+ className="flex-1"
253
+ >
254
+ {opt.label}
255
+ </ToggleGroupItem>
256
+ ))}
257
+ </ToggleGroup>
258
+
259
+ {/* Fixed-height row — same h-9 in all tab states to prevent layout jump */}
260
+ {duration === "custom" ? (
261
+ <DatePicker
262
+ value={customDate}
263
+ onChange={setCustomDate}
264
+ placeholder="Pick a date"
265
+ calendarProps={{ disabled: { before: today } }}
266
+ />
267
+ ) : (
268
+ resolvedDate && (
269
+ <div className="flex h-9 items-center border border-input bg-muted/30 px-3 text-sm text-muted-foreground">
270
+ Hold until:{" "}
271
+ <span className="ml-1 font-medium text-foreground">
272
+ {format(resolvedDate, "dd MMM yyyy")}
273
+ </span>
274
+ </div>
275
+ )
276
+ )}
277
+
278
+ {/* For custom: show resolved date below the picker once selected */}
279
+ {duration === "custom" && customDate && (
280
+ <p className="text-sm text-muted-foreground">
281
+ Hold until:{" "}
282
+ <span className="font-medium text-foreground">
283
+ {format(customDate, "dd MMM yyyy")}
284
+ </span>
285
+ </p>
286
+ )}
287
+ </div>
288
+ <DialogFooter>
289
+ <Button
290
+ variant="outline"
291
+ onClick={() => onOpenChange(false)}
292
+ disabled={loading}
293
+ >
294
+ Cancel
295
+ </Button>
296
+ <Button onClick={handleSave} disabled={loading || !isValid}>
297
+ {loading ? "Saving…" : "Save"}
298
+ </Button>
299
+ </DialogFooter>
300
+ </DialogContent>
301
+ </Dialog>
302
+ );
303
+ }
@@ -0,0 +1,108 @@
1
+ import { cn } from "@/lib/utils";
2
+ import { Badge } from "@/components/ui/badge";
3
+ import { Checkbox } from "@/components/ui/checkbox";
4
+
5
+ /**
6
+ * Pipeline domain primitives — WealthX DS
7
+ *
8
+ * Complex domain-specific atoms for the Pipeline / Loan CRM feature
9
+ * that cannot be expressed as simple use-cases of existing primitives.
10
+ *
11
+ * Simple patterns (priority dot, days chip, loan type badge, progress bar)
12
+ * are documented as use-cases in their respective base component stories
13
+ * (Badge, Chip, Progress) — not exported as separate components.
14
+ *
15
+ * Layer: L2 Domain Primitive
16
+ */
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // TaskCheckItem
20
+ // ---------------------------------------------------------------------------
21
+
22
+ export interface TaskCheckItemProps {
23
+ /** Task display title. */
24
+ title: string;
25
+ /** Whether the task has been completed. */
26
+ completed: boolean;
27
+ /** Name of the AI agent assigned to this task, if any. */
28
+ aiAgentName?: string | null;
29
+ /** Called when the checkbox is toggled. */
30
+ onToggle?: () => void;
31
+ /** Disables interaction (e.g. while saving). */
32
+ disabled?: boolean;
33
+ /**
34
+ * Text size for the task title.
35
+ * - "xs" (default) — 12px, for compact card usage
36
+ * - "sm" — 14px, for standalone / drawer usage
37
+ */
38
+ size?: "xs" | "sm";
39
+ className?: string;
40
+ }
41
+
42
+ /**
43
+ * A single task row with a checkbox, title (strikethrough when done),
44
+ * and an optional AI agent chip.
45
+ *
46
+ * Used in two contexts:
47
+ * - `OpportunityCard` (kanban card) — default `size="xs"` (12px), compact
48
+ * - `StageTimeline` (drawer Tasks tab) — `size="sm"` (14px), standalone
49
+ *
50
+ * Data source: `Opportunity.tasks[]` from `loan-crm.ts`
51
+ * - `completed` ← `task.completedTaskId !== null`
52
+ * - `aiAgentName` ← `task.aiAgentName`
53
+ */
54
+ export function TaskCheckItem({
55
+ title,
56
+ completed,
57
+ aiAgentName,
58
+ onToggle,
59
+ disabled = false,
60
+ size = "xs",
61
+ className,
62
+ }: TaskCheckItemProps) {
63
+ return (
64
+ <div
65
+ className={cn(
66
+ "flex cursor-pointer items-start gap-2 py-1.5",
67
+ disabled && "pointer-events-none opacity-60",
68
+ className,
69
+ )}
70
+ onClick={() => onToggle?.()}
71
+ data-slot="task-check-item"
72
+ >
73
+ {/*
74
+ * Wrapper span stops click propagation so the outer div's onClick doesn't
75
+ * double-fire when the user clicks the Checkbox button directly.
76
+ * (Radix Checkbox renders as <button> — clicking it fires onCheckedChange,
77
+ * then the event would bubble to the div and call onToggle a second time.)
78
+ */}
79
+ <span onClick={(e) => e.stopPropagation()} className="mt-0.5 shrink-0">
80
+ <Checkbox
81
+ checked={completed}
82
+ onCheckedChange={() => onToggle?.()}
83
+ disabled={disabled}
84
+ />
85
+ </span>
86
+ <span className="flex min-w-0 flex-1 flex-col gap-0.5">
87
+ <span
88
+ className={cn(
89
+ "leading-snug text-foreground",
90
+ size === "sm" ? "text-sm" : "text-xs",
91
+ completed && "text-muted-foreground line-through",
92
+ )}
93
+ >
94
+ {title}
95
+ </span>
96
+ {aiAgentName && (
97
+ <Badge variant="secondary" className="gap-1 text-[10px]">
98
+ <span
99
+ className="size-1.5 rounded-full bg-primary"
100
+ aria-hidden="true"
101
+ />
102
+ {aiAgentName}
103
+ </Badge>
104
+ )}
105
+ </span>
106
+ </div>
107
+ );
108
+ }
@@ -1,29 +1,29 @@
1
- import { type ReactElement } from "react"
2
- import * as React from "react"
3
- import { Popover as PopoverPrimitive } from "@base-ui/react/popover"
4
- import { cn } from "@/lib/utils"
5
- import { useThemeVars } from "@/lib/theme-provider"
1
+ import { type ReactElement } from "react";
2
+ import * as React from "react";
3
+ import { Popover as PopoverPrimitive } from "@base-ui/react/popover";
4
+ import { cn } from "@/lib/utils";
5
+ import { useThemeVars } from "@/lib/theme-provider";
6
6
 
7
- export type PopoverProps = React.ComponentProps<typeof PopoverPrimitive.Root>
7
+ export type PopoverProps = React.ComponentProps<typeof PopoverPrimitive.Root>;
8
8
 
9
- function Popover({
10
- ...props
11
- }: PopoverProps): ReactElement {
12
- return <PopoverPrimitive.Root data-slot="popover" {...props} />
9
+ function Popover({ ...props }: PopoverProps): ReactElement {
10
+ return <PopoverPrimitive.Root data-slot="popover" {...props} />;
13
11
  }
14
12
 
15
- export type PopoverTriggerProps = React.ComponentProps<typeof PopoverPrimitive.Trigger>
13
+ export type PopoverTriggerProps = React.ComponentProps<
14
+ typeof PopoverPrimitive.Trigger
15
+ >;
16
16
 
17
- function PopoverTrigger({
18
- ...props
19
- }: PopoverTriggerProps): ReactElement {
20
- return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
17
+ function PopoverTrigger({ ...props }: PopoverTriggerProps): ReactElement {
18
+ return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
21
19
  }
22
20
 
23
- export type PopoverContentProps = React.ComponentProps<typeof PopoverPrimitive.Popup> & {
24
- align?: "start" | "center" | "end"
25
- sideOffset?: number
26
- }
21
+ export type PopoverContentProps = React.ComponentProps<
22
+ typeof PopoverPrimitive.Popup
23
+ > & {
24
+ align?: "start" | "center" | "end";
25
+ sideOffset?: number;
26
+ };
27
27
 
28
28
  function PopoverContent({
29
29
  className,
@@ -36,13 +36,14 @@ function PopoverContent({
36
36
  return (
37
37
  <PopoverPrimitive.Portal>
38
38
  <PopoverPrimitive.Positioner
39
+ className="z-[200]"
39
40
  align={align}
40
41
  sideOffset={sideOffset}
41
42
  >
42
43
  <PopoverPrimitive.Popup
43
44
  className={cn(
44
45
  "z-50 w-72 border border-border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-ending-style:animate-out data-ending-style:fade-out-0 data-ending-style:zoom-out-95 data-ending-style:fill-mode-forwards data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95",
45
- className
46
+ className,
46
47
  )}
47
48
  data-slot="popover-content"
48
49
  style={{ ...themeVars, ...style } as React.CSSProperties}
@@ -50,32 +51,36 @@ function PopoverContent({
50
51
  />
51
52
  </PopoverPrimitive.Positioner>
52
53
  </PopoverPrimitive.Portal>
53
- )
54
+ );
54
55
  }
55
56
 
56
- export type PopoverAnchorProps = React.ComponentProps<"div">
57
+ export type PopoverAnchorProps = React.ComponentProps<"div">;
57
58
 
58
- function PopoverAnchor({
59
- ...props
60
- }: PopoverAnchorProps): ReactElement {
61
- return <div data-slot="popover-anchor" {...props} />
59
+ function PopoverAnchor({ ...props }: PopoverAnchorProps): ReactElement {
60
+ return <div data-slot="popover-anchor" {...props} />;
62
61
  }
63
62
 
64
- export type PopoverHeaderProps = React.ComponentProps<"div">
63
+ export type PopoverHeaderProps = React.ComponentProps<"div">;
65
64
 
66
- function PopoverHeader({ className, ...props }: PopoverHeaderProps): ReactElement {
65
+ function PopoverHeader({
66
+ className,
67
+ ...props
68
+ }: PopoverHeaderProps): ReactElement {
67
69
  return (
68
70
  <div
69
- className={cn("flex flex-col gap-1 text-sm", className)}
71
+ className={cn("flex flex-col gap-1 text-body-small", className)}
70
72
  data-slot="popover-header"
71
73
  {...props}
72
74
  />
73
- )
75
+ );
74
76
  }
75
77
 
76
- export type PopoverTitleProps = React.ComponentProps<"h2">
78
+ export type PopoverTitleProps = React.ComponentProps<"h2">;
77
79
 
78
- function PopoverTitle({ className, ...props }: PopoverTitleProps): ReactElement {
80
+ function PopoverTitle({
81
+ className,
82
+ ...props
83
+ }: PopoverTitleProps): ReactElement {
79
84
  return (
80
85
  // eslint-disable-next-line jsx-a11y/heading-has-content -- children passed via props spread
81
86
  <h2
@@ -83,10 +88,10 @@ function PopoverTitle({ className, ...props }: PopoverTitleProps): ReactElement
83
88
  data-slot="popover-title"
84
89
  {...props}
85
90
  />
86
- )
91
+ );
87
92
  }
88
93
 
89
- export type PopoverDescriptionProps = React.ComponentProps<"p">
94
+ export type PopoverDescriptionProps = React.ComponentProps<"p">;
90
95
 
91
96
  function PopoverDescription({
92
97
  className,
@@ -98,7 +103,7 @@ function PopoverDescription({
98
103
  data-slot="popover-description"
99
104
  {...props}
100
105
  />
101
- )
106
+ );
102
107
  }
103
108
 
104
109
  export {
@@ -109,4 +114,4 @@ export {
109
114
  PopoverHeader,
110
115
  PopoverTitle,
111
116
  PopoverDescription,
112
- }
117
+ };