@wealthx/shadcn 1.4.1 → 1.5.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 (430) hide show
  1. package/.turbo/turbo-build.log +360 -180
  2. package/CHANGELOG.md +6 -0
  3. package/dist/chunk-2A53WPEC.mjs +182 -0
  4. package/dist/{chunk-SIVYAI3M.mjs → chunk-2LLFNGJZ.mjs} +15 -15
  5. package/dist/chunk-2QNOPXMQ.mjs +360 -0
  6. package/dist/{chunk-K5QV4TT6.mjs → chunk-2WCIORP7.mjs} +29 -4
  7. package/dist/{chunk-5NF6T2RS.mjs → chunk-3AREQTZU.mjs} +8 -8
  8. package/dist/{chunk-2EM2FRU6.mjs → chunk-3WGFIFP6.mjs} +5 -5
  9. package/dist/{chunk-K4KOD3KR.mjs → chunk-42NEC57Y.mjs} +44 -25
  10. package/dist/{chunk-FL6DZFJK.mjs → chunk-46Q4335I.mjs} +121 -39
  11. package/dist/chunk-4DO3WM7V.mjs +48 -0
  12. package/dist/chunk-5FHBC6DY.mjs +68 -0
  13. package/dist/chunk-5SAYZ4CI.mjs +40 -0
  14. package/dist/chunk-5WMFKQZ6.mjs +180 -0
  15. package/dist/chunk-623YVI5O.mjs +43 -0
  16. package/dist/{chunk-SFH2NJEJ.mjs → chunk-6OSULDEO.mjs} +3 -3
  17. package/dist/{chunk-UALR6JGV.mjs → chunk-6SR4K5T5.mjs} +1 -1
  18. package/dist/{chunk-D2NSIIXG.mjs → chunk-7KT5HPYM.mjs} +11 -11
  19. package/dist/chunk-A6ER36CW.mjs +456 -0
  20. package/dist/{chunk-QX7IFQSF.mjs → chunk-AHKHVBWR.mjs} +4 -4
  21. package/dist/chunk-AHSCWXYJ.mjs +113 -0
  22. package/dist/{chunk-7GWRPXHD.mjs → chunk-AL6GOL2Y.mjs} +1 -1
  23. package/dist/{chunk-OIKBW2QD.mjs → chunk-AUEUTZIC.mjs} +13 -13
  24. package/dist/{chunk-FYPSTTEJ.mjs → chunk-B7DD3ODQ.mjs} +1 -1
  25. package/dist/{chunk-TLAWKTSA.mjs → chunk-BD3DWDT4.mjs} +3 -3
  26. package/dist/{chunk-S2FKV4M5.mjs → chunk-BDESHD25.mjs} +4 -4
  27. package/dist/{chunk-OKTJFDPN.mjs → chunk-BFB3UH7V.mjs} +2 -2
  28. package/dist/{chunk-DGNHGNYH.mjs → chunk-C6SWS7OW.mjs} +1 -1
  29. package/dist/chunk-CDVG7SFT.mjs +271 -0
  30. package/dist/chunk-CUSHAIUL.mjs +109 -0
  31. package/dist/{chunk-QXKGOMUX.mjs → chunk-CW32WTZU.mjs} +4 -4
  32. package/dist/{chunk-SET2ANTY.mjs → chunk-D447W45Z.mjs} +3 -3
  33. package/dist/{chunk-RCAOCHWA.mjs → chunk-DFL5CV75.mjs} +18 -18
  34. package/dist/chunk-DYSVJ473.mjs +162 -0
  35. package/dist/chunk-E3PQDBYI.mjs +288 -0
  36. package/dist/chunk-EMYBNPIA.mjs +83 -0
  37. package/dist/chunk-EUYPMDQG.mjs +348 -0
  38. package/dist/{chunk-XYPW2XA5.mjs → chunk-EW72FINW.mjs} +11 -11
  39. package/dist/chunk-F24U4QQQ.mjs +234 -0
  40. package/dist/{chunk-VB5M6OZQ.mjs → chunk-F4O2YPXJ.mjs} +1 -1
  41. package/dist/chunk-FFXTQTB4.mjs +84 -0
  42. package/dist/{chunk-ZOWL2L5J.mjs → chunk-FYUSF5KO.mjs} +5 -1
  43. package/dist/{chunk-FTPBQVQ6.mjs → chunk-GNER6MCO.mjs} +1 -1
  44. package/dist/{chunk-2D3HQPFN.mjs → chunk-HF4FUBCY.mjs} +5 -5
  45. package/dist/{chunk-RSUIPKGX.mjs → chunk-HNDTLT5X.mjs} +1 -1
  46. package/dist/{chunk-N6Q5IPKT.mjs → chunk-HO6S3ECM.mjs} +46 -18
  47. package/dist/{chunk-L4NSRQ3T.mjs → chunk-HROG643K.mjs} +1 -1
  48. package/dist/chunk-I2EKKSEF.mjs +148 -0
  49. package/dist/{chunk-QTRSCVQ3.mjs → chunk-I3UDLWQ7.mjs} +1 -1
  50. package/dist/{chunk-AE7MASLF.mjs → chunk-IQGKOT7A.mjs} +9 -6
  51. package/dist/chunk-IXR4BQSQ.mjs +290 -0
  52. package/dist/{chunk-4MM7LHM5.mjs → chunk-J5NW5NCT.mjs} +1 -1
  53. package/dist/{chunk-OLKMCXAR.mjs → chunk-JTG5R5YV.mjs} +24 -24
  54. package/dist/chunk-JUBUN65Q.mjs +106 -0
  55. package/dist/chunk-K7TWMLLW.mjs +520 -0
  56. package/dist/{chunk-BOW7U26Y.mjs → chunk-K7WSRWOU.mjs} +4 -4
  57. package/dist/{chunk-NTYQWVLI.mjs → chunk-KAD26MCC.mjs} +1 -1
  58. package/dist/{chunk-KCWNDYPZ.mjs → chunk-KB7MZMED.mjs} +4 -4
  59. package/dist/chunk-KCKYGQVQ.mjs +61 -0
  60. package/dist/{chunk-VY5NEUP7.mjs → chunk-KLJLDNCA.mjs} +1 -1
  61. package/dist/chunk-LLAGF6BA.mjs +49 -0
  62. package/dist/{chunk-G27TSQLQ.mjs → chunk-M4LTX3MH.mjs} +1 -1
  63. package/dist/{chunk-YIZHS72Z.mjs → chunk-MHHA7QGO.mjs} +94 -54
  64. package/dist/{chunk-P2N2PEFY.mjs → chunk-NCUH54IZ.mjs} +4 -4
  65. package/dist/{chunk-PNRUH7JY.mjs → chunk-OECGKCVF.mjs} +5 -5
  66. package/dist/{chunk-YE67AALL.mjs → chunk-OL65UQHQ.mjs} +10 -10
  67. package/dist/{chunk-LQULK2E3.mjs → chunk-OYBIUEGE.mjs} +1 -1
  68. package/dist/{chunk-LR6LHDP3.mjs → chunk-PGR53HMH.mjs} +7 -7
  69. package/dist/chunk-PUJ42INK.mjs +141 -0
  70. package/dist/{chunk-M4VYX2PV.mjs → chunk-PV3Y7QGK.mjs} +2 -2
  71. package/dist/{chunk-UJZ4UHWI.mjs → chunk-PV7PNA6K.mjs} +4 -4
  72. package/dist/{chunk-6HIOM2HL.mjs → chunk-Q35PNFJ7.mjs} +1 -1
  73. package/dist/{chunk-JZY6TNIS.mjs → chunk-Q5SGEIJV.mjs} +27 -27
  74. package/dist/{chunk-ZFCDYW6N.mjs → chunk-QAX6HCUH.mjs} +1 -1
  75. package/dist/chunk-QHJDGB54.mjs +135 -0
  76. package/dist/chunk-QQSOZQOC.mjs +27 -0
  77. package/dist/chunk-RUX3OLVZ.mjs +59 -0
  78. package/dist/{chunk-QOJ2DQD6.mjs → chunk-S4CTM3UE.mjs} +5 -0
  79. package/dist/{chunk-ZEDMKQK2.mjs → chunk-TAX3KL66.mjs} +1 -1
  80. package/dist/chunk-TC43SMIN.mjs +133 -0
  81. package/dist/chunk-TGVXRD53.mjs +174 -0
  82. package/dist/{chunk-K5VHK7CM.mjs → chunk-TLYSVRSK.mjs} +12 -12
  83. package/dist/{chunk-YCWLFG27.mjs → chunk-TOIVHWNC.mjs} +1 -1
  84. package/dist/chunk-TXUBGKB7.mjs +160 -0
  85. package/dist/chunk-UEREFDAE.mjs +75 -0
  86. package/dist/chunk-UTCQN6XU.mjs +123 -0
  87. package/dist/{chunk-37AE3OM5.mjs → chunk-V4CUTCHS.mjs} +4 -4
  88. package/dist/{chunk-THVO2N47.mjs → chunk-VFH632TB.mjs} +9 -9
  89. package/dist/{chunk-3ERBUVHC.mjs → chunk-VJ3GC7W3.mjs} +95 -49
  90. package/dist/{chunk-V6XGXYCJ.mjs → chunk-VLELWBEW.mjs} +4 -4
  91. package/dist/{chunk-FEZKMUCF.mjs → chunk-WDTXHLYM.mjs} +1 -1
  92. package/dist/chunk-WUA546RX.mjs +129 -0
  93. package/dist/chunk-XHGISOX5.mjs +257 -0
  94. package/dist/chunk-XIY5DJXI.mjs +168 -0
  95. package/dist/{chunk-TOWTPLRC.mjs → chunk-XN37434W.mjs} +8 -8
  96. package/dist/{chunk-KLTACJ2G.mjs → chunk-XTWAJWCQ.mjs} +1 -1
  97. package/dist/chunk-Y24TXIFJ.mjs +518 -0
  98. package/dist/{chunk-DMXYRCHM.mjs → chunk-Y6UM3VTN.mjs} +4 -4
  99. package/dist/components/ui/about-you-form.js +1120 -0
  100. package/dist/components/ui/about-you-form.mjs +323 -0
  101. package/dist/components/ui/account-list-carousel.js +304 -0
  102. package/dist/components/ui/account-list-carousel.mjs +11 -0
  103. package/dist/components/ui/add-column-modal.js +1 -1
  104. package/dist/components/ui/add-column-modal.mjs +6 -6
  105. package/dist/components/ui/add-lead-modal.js +2 -2
  106. package/dist/components/ui/add-lead-modal.mjs +6 -6
  107. package/dist/components/ui/advisor-card.mjs +2 -2
  108. package/dist/components/ui/agent-evaluation-toast.js +299 -0
  109. package/dist/components/ui/agent-evaluation-toast.mjs +12 -0
  110. package/dist/components/ui/ai-assistant-drawer.mjs +5 -5
  111. package/dist/components/ui/ai-builder.js +3 -3
  112. package/dist/components/ui/ai-builder.mjs +5 -5
  113. package/dist/components/ui/ai-conversations.js +2 -2
  114. package/dist/components/ui/ai-conversations.mjs +11 -11
  115. package/dist/components/ui/alert-dialog.mjs +3 -3
  116. package/dist/components/ui/applicant-document-checklist.js +346 -0
  117. package/dist/components/ui/applicant-document-checklist.mjs +10 -0
  118. package/dist/components/ui/applicant-expenses-section.js +455 -0
  119. package/dist/components/ui/applicant-expenses-section.mjs +220 -0
  120. package/dist/components/ui/applicant-navigation-bar.js +309 -0
  121. package/dist/components/ui/applicant-navigation-bar.mjs +87 -0
  122. package/dist/components/ui/applicant-switcher.js +268 -0
  123. package/dist/components/ui/applicant-switcher.mjs +46 -0
  124. package/dist/components/ui/application-mobile-layout.js +88 -0
  125. package/dist/components/ui/application-mobile-layout.mjs +8 -0
  126. package/dist/components/ui/appointment-action-dialogs.js +1 -1
  127. package/dist/components/ui/appointment-action-dialogs.mjs +10 -10
  128. package/dist/components/ui/appointment-availability-settings.js +78 -31
  129. package/dist/components/ui/appointment-availability-settings.mjs +12 -10
  130. package/dist/components/ui/appointment-book-dialog.js +137 -58
  131. package/dist/components/ui/appointment-book-dialog.mjs +14 -14
  132. package/dist/components/ui/appointment-calendar-view.js +1 -1
  133. package/dist/components/ui/appointment-calendar-view.mjs +4 -4
  134. package/dist/components/ui/appointment-detail-sheet.js +38 -11
  135. package/dist/components/ui/appointment-detail-sheet.mjs +13 -13
  136. package/dist/components/ui/appointment-gmail-connect.mjs +2 -2
  137. package/dist/components/ui/appointment-time-slot-picker.mjs +2 -2
  138. package/dist/components/ui/appointment-upcoming-card.js +1 -1
  139. package/dist/components/ui/appointment-upcoming-card.mjs +10 -10
  140. package/dist/components/ui/asset-accordion.js +506 -0
  141. package/dist/components/ui/asset-accordion.mjs +202 -0
  142. package/dist/components/ui/assets-liabilities-side-card.js +328 -0
  143. package/dist/components/ui/assets-liabilities-side-card.mjs +127 -0
  144. package/dist/components/ui/auth-page-layout.js +3 -3
  145. package/dist/components/ui/auth-page-layout.mjs +1 -1
  146. package/dist/components/ui/backoffice-alert-history-chart.mjs +4 -4
  147. package/dist/components/ui/backoffice-alert-matching-chart.js +786 -0
  148. package/dist/components/ui/backoffice-alert-matching-chart.mjs +19 -0
  149. package/dist/components/ui/backoffice-alerts-chart.mjs +4 -4
  150. package/dist/components/ui/backoffice-connections-chart.mjs +4 -4
  151. package/dist/components/ui/backoffice-contact-history-chart.mjs +4 -4
  152. package/dist/components/ui/backoffice-contact-matching-chart.js +803 -0
  153. package/dist/components/ui/backoffice-contact-matching-chart.mjs +19 -0
  154. package/dist/components/ui/backoffice-signup-steps.js +1673 -0
  155. package/dist/components/ui/backoffice-signup-steps.mjs +36 -0
  156. package/dist/components/ui/bank-statement-document-table.js +467 -0
  157. package/dist/components/ui/bank-statement-document-table.mjs +12 -0
  158. package/dist/components/ui/bank-statement-generate-dialog.js +1517 -0
  159. package/dist/components/ui/bank-statement-generate-dialog.mjs +27 -0
  160. package/dist/components/ui/bank-statement-pdf-viewer.js +525 -0
  161. package/dist/components/ui/bank-statement-pdf-viewer.mjs +14 -0
  162. package/dist/components/ui/banking-accounts-connect.js +336 -0
  163. package/dist/components/ui/banking-accounts-connect.mjs +114 -0
  164. package/dist/components/ui/borrowing-capacity-atoms.js +382 -0
  165. package/dist/components/ui/borrowing-capacity-atoms.mjs +17 -0
  166. package/dist/components/ui/borrowing-capacity-card.js +835 -0
  167. package/dist/components/ui/borrowing-capacity-card.mjs +89 -0
  168. package/dist/components/ui/borrowing-capacity-line-chart.mjs +4 -4
  169. package/dist/components/ui/broker-info-panel.js +281 -0
  170. package/dist/components/ui/broker-info-panel.mjs +59 -0
  171. package/dist/components/ui/calculator-input-item.js +101 -0
  172. package/dist/components/ui/calculator-input-item.mjs +8 -0
  173. package/dist/components/ui/calculator-section.js +743 -0
  174. package/dist/components/ui/calculator-section.mjs +220 -0
  175. package/dist/components/ui/calendar.mjs +2 -2
  176. package/dist/components/ui/cash-balance-line-chart.mjs +5 -5
  177. package/dist/components/ui/cashflow-bar-chart.mjs +4 -4
  178. package/dist/components/ui/category-edit-dialog.js +737 -0
  179. package/dist/components/ui/category-edit-dialog.mjs +16 -0
  180. package/dist/components/ui/chat-widget.mjs +3 -3
  181. package/dist/components/ui/color-picker.mjs +4 -4
  182. package/dist/components/ui/connect-bank-step.js +511 -0
  183. package/dist/components/ui/connect-bank-step.mjs +287 -0
  184. package/dist/components/ui/contact-alert-dialog.js +1405 -0
  185. package/dist/components/ui/contact-alert-dialog.mjs +27 -0
  186. package/dist/components/ui/create-contact-modal.js +1028 -0
  187. package/dist/components/ui/create-contact-modal.mjs +21 -0
  188. package/dist/components/ui/csv-import-modal.js +583 -0
  189. package/dist/components/ui/csv-import-modal.mjs +14 -0
  190. package/dist/components/ui/currency-input.js +439 -0
  191. package/dist/components/ui/currency-input.mjs +13 -0
  192. package/dist/components/ui/dashboard-expense-categories.js +355 -0
  193. package/dist/components/ui/dashboard-expense-categories.mjs +186 -0
  194. package/dist/components/ui/dashboard-transactions-table.js +1083 -0
  195. package/dist/components/ui/dashboard-transactions-table.mjs +177 -0
  196. package/dist/components/ui/data-table.mjs +6 -6
  197. package/dist/components/ui/date-picker.mjs +6 -6
  198. package/dist/components/ui/debt-accordion.js +523 -0
  199. package/dist/components/ui/debt-accordion.mjs +219 -0
  200. package/dist/components/ui/delete-contact-component.js +479 -0
  201. package/dist/components/ui/delete-contact-component.mjs +14 -0
  202. package/dist/components/ui/dialog.js +1 -1
  203. package/dist/components/ui/dialog.mjs +3 -3
  204. package/dist/components/ui/document-checklist-template.mjs +4 -4
  205. package/dist/components/ui/drawer.mjs +3 -3
  206. package/dist/components/ui/dropdown-menu.mjs +3 -3
  207. package/dist/components/ui/dynamic-tabs.js +274 -0
  208. package/dist/components/ui/dynamic-tabs.mjs +116 -0
  209. package/dist/components/ui/editable-money-item.js +306 -0
  210. package/dist/components/ui/editable-money-item.mjs +12 -0
  211. package/dist/components/ui/expense-bar-chart.mjs +4 -4
  212. package/dist/components/ui/expense-detail-item.js +506 -0
  213. package/dist/components/ui/expense-detail-item.mjs +15 -0
  214. package/dist/components/ui/expense-work-details.js +1259 -0
  215. package/dist/components/ui/expense-work-details.mjs +175 -0
  216. package/dist/components/ui/field.mjs +2 -2
  217. package/dist/components/ui/file-preview-dialog.js +704 -0
  218. package/dist/components/ui/file-preview-dialog.mjs +17 -0
  219. package/dist/components/ui/financial-cards.mjs +2 -2
  220. package/dist/components/ui/financial-drawers.js +1 -1
  221. package/dist/components/ui/financial-drawers.mjs +5 -5
  222. package/dist/components/ui/financial-sections.mjs +4 -4
  223. package/dist/components/ui/form-primitives.mjs +2 -2
  224. package/dist/components/ui/frontend-signup-steps.js +1239 -0
  225. package/dist/components/ui/frontend-signup-steps.mjs +38 -0
  226. package/dist/components/ui/income-bar-chart.mjs +4 -4
  227. package/dist/components/ui/income-sources-card.js +269 -0
  228. package/dist/components/ui/income-sources-card.mjs +100 -0
  229. package/dist/components/ui/income-summary-component.js +361 -0
  230. package/dist/components/ui/income-summary-component.mjs +84 -0
  231. package/dist/components/ui/income-work-details.js +1663 -0
  232. package/dist/components/ui/income-work-details.mjs +28 -0
  233. package/dist/components/ui/incoming-outgoings-card.js +218 -0
  234. package/dist/components/ui/incoming-outgoings-card.mjs +82 -0
  235. package/dist/components/ui/interest-rate-input.js +442 -0
  236. package/dist/components/ui/interest-rate-input.mjs +90 -0
  237. package/dist/components/ui/interest-rate-section.js +337 -0
  238. package/dist/components/ui/interest-rate-section.mjs +84 -0
  239. package/dist/components/ui/interest-rate-used.js +202 -0
  240. package/dist/components/ui/interest-rate-used.mjs +62 -0
  241. package/dist/components/ui/kanban-column.js +338 -160
  242. package/dist/components/ui/kanban-column.mjs +13 -11
  243. package/dist/components/ui/loan-applicant-information.js +336 -0
  244. package/dist/components/ui/loan-applicant-information.mjs +59 -0
  245. package/dist/components/ui/loan-applicant-invite.js +319 -0
  246. package/dist/components/ui/loan-applicant-invite.mjs +68 -0
  247. package/dist/components/ui/loan-application-badge.js +236 -0
  248. package/dist/components/ui/loan-application-badge.mjs +10 -0
  249. package/dist/components/ui/loan-application-cards.js +356 -0
  250. package/dist/components/ui/loan-application-cards.mjs +110 -0
  251. package/dist/components/ui/loan-entry-shell.js +104 -0
  252. package/dist/components/ui/loan-entry-shell.mjs +8 -0
  253. package/dist/components/ui/loan-financials.js +410 -0
  254. package/dist/components/ui/loan-financials.mjs +76 -0
  255. package/dist/components/ui/loan-option-card.js +102 -0
  256. package/dist/components/ui/loan-option-card.mjs +41 -0
  257. package/dist/components/ui/loan-option-group.js +288 -0
  258. package/dist/components/ui/loan-option-group.mjs +10 -0
  259. package/dist/components/ui/loan-steps.js +1121 -0
  260. package/dist/components/ui/loan-steps.mjs +509 -0
  261. package/dist/components/ui/loan-wizard-shell.js +452 -0
  262. package/dist/components/ui/loan-wizard-shell.mjs +11 -0
  263. package/dist/components/ui/money-input-with-slider.js +210 -0
  264. package/dist/components/ui/money-input-with-slider.mjs +10 -0
  265. package/dist/components/ui/money-item-with-color-indicator.js +314 -0
  266. package/dist/components/ui/money-item-with-color-indicator.mjs +20 -0
  267. package/dist/components/ui/opportunity-card.js +235 -97
  268. package/dist/components/ui/opportunity-card.mjs +11 -9
  269. package/dist/components/ui/opportunity-edit-modals.js +1 -1
  270. package/dist/components/ui/opportunity-edit-modals.mjs +15 -15
  271. package/dist/components/ui/opportunity-summary-tab.js +1 -1
  272. package/dist/components/ui/opportunity-summary-tab.mjs +19 -19
  273. package/dist/components/ui/pagination.mjs +4 -4
  274. package/dist/components/ui/password-strength-tooltip.mjs +4 -4
  275. package/dist/components/ui/pipeline-board.js +358 -176
  276. package/dist/components/ui/pipeline-board.mjs +16 -14
  277. package/dist/components/ui/pipeline-chart.mjs +3 -3
  278. package/dist/components/ui/pipeline-dialogs.js +1 -1
  279. package/dist/components/ui/pipeline-dialogs.mjs +9 -9
  280. package/dist/components/ui/pipeline-primitives.js +75 -8
  281. package/dist/components/ui/pipeline-primitives.mjs +3 -2
  282. package/dist/components/ui/popover.mjs +3 -3
  283. package/dist/components/ui/property-asset-card.js +428 -0
  284. package/dist/components/ui/property-asset-card.mjs +156 -0
  285. package/dist/components/ui/property-cashflow-doughnut-chart.mjs +4 -4
  286. package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +4 -4
  287. package/dist/components/ui/property-list-carousel.js +295 -0
  288. package/dist/components/ui/property-list-carousel.mjs +11 -0
  289. package/dist/components/ui/property-mobile-estimate-line-chart.mjs +4 -4
  290. package/dist/components/ui/property-report-dialog.js +1148 -0
  291. package/dist/components/ui/property-report-dialog.mjs +25 -0
  292. package/dist/components/ui/resource-center.js +748 -0
  293. package/dist/components/ui/resource-center.mjs +24 -0
  294. package/dist/components/ui/review-alerts-dialog.js +569 -0
  295. package/dist/components/ui/review-alerts-dialog.mjs +15 -0
  296. package/dist/components/ui/savings-goal-modal.js +1148 -0
  297. package/dist/components/ui/savings-goal-modal.mjs +160 -0
  298. package/dist/components/ui/scenario-drawer.js +791 -0
  299. package/dist/components/ui/scenario-drawer.mjs +294 -0
  300. package/dist/components/ui/scenario-item.js +256 -0
  301. package/dist/components/ui/scenario-item.mjs +11 -0
  302. package/dist/components/ui/scenario-list.js +507 -0
  303. package/dist/components/ui/scenario-list.mjs +100 -0
  304. package/dist/components/ui/select.mjs +3 -3
  305. package/dist/components/ui/share-details-dialog.js +636 -0
  306. package/dist/components/ui/share-details-dialog.mjs +19 -0
  307. package/dist/components/ui/sheet.mjs +3 -3
  308. package/dist/components/ui/sidebar-nav.mjs +5 -5
  309. package/dist/components/ui/signup-form-primitives.js +770 -0
  310. package/dist/components/ui/signup-form-primitives.mjs +25 -0
  311. package/dist/components/ui/signup-shell.js +338 -0
  312. package/dist/components/ui/signup-shell.mjs +13 -0
  313. package/dist/components/ui/stage-timeline.js +103 -33
  314. package/dist/components/ui/stage-timeline.mjs +5 -4
  315. package/dist/components/ui/submission-confirmation-card.js +284 -0
  316. package/dist/components/ui/submission-confirmation-card.mjs +62 -0
  317. package/dist/components/ui/tooltip.mjs +3 -3
  318. package/dist/components/ui/top-three-product.js +374 -0
  319. package/dist/components/ui/top-three-product.mjs +129 -0
  320. package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +4 -4
  321. package/dist/components/ui/transactions-income-expense-bar-chart.mjs +5 -5
  322. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +4 -4
  323. package/dist/components/ui/transactions-summary-block.js +95 -0
  324. package/dist/components/ui/transactions-summary-block.mjs +34 -0
  325. package/dist/components/ui/two-fa-setup-form.mjs +3 -3
  326. package/dist/index.js +9430 -4573
  327. package/dist/index.mjs +404 -251
  328. package/dist/lib/colors.js +6 -0
  329. package/dist/lib/colors.mjs +3 -1
  330. package/dist/lib/theme-provider.mjs +2 -2
  331. package/dist/styles.css +1 -1
  332. package/package.json +366 -2
  333. package/src/components/index.tsx +223 -0
  334. package/src/components/ui/about-you-form.tsx +397 -0
  335. package/src/components/ui/account-list-carousel.tsx +87 -0
  336. package/src/components/ui/add-lead-modal.tsx +1 -1
  337. package/src/components/ui/agent-evaluation-toast.tsx +191 -0
  338. package/src/components/ui/ai-builder.tsx +3 -5
  339. package/src/components/ui/ai-conversations.tsx +1 -1
  340. package/src/components/ui/applicant-document-checklist.tsx +175 -0
  341. package/src/components/ui/applicant-expenses-section.tsx +260 -0
  342. package/src/components/ui/applicant-navigation-bar.tsx +104 -0
  343. package/src/components/ui/applicant-switcher.tsx +54 -0
  344. package/src/components/ui/application-mobile-layout.tsx +34 -0
  345. package/src/components/ui/appointment-availability-settings.tsx +115 -23
  346. package/src/components/ui/appointment-book-dialog.tsx +406 -259
  347. package/src/components/ui/appointment-calendar-view.tsx +4 -1
  348. package/src/components/ui/appointment-detail-sheet.tsx +59 -24
  349. package/src/components/ui/appointment-time-slot-picker.tsx +5 -1
  350. package/src/components/ui/asset-accordion.tsx +241 -0
  351. package/src/components/ui/assets-liabilities-side-card.tsx +157 -0
  352. package/src/components/ui/auth-page-layout.tsx +3 -3
  353. package/src/components/ui/backoffice-alert-matching-chart.tsx +320 -0
  354. package/src/components/ui/backoffice-contact-matching-chart.tsx +341 -0
  355. package/src/components/ui/backoffice-signup-steps.tsx +615 -0
  356. package/src/components/ui/bank-statement-document-table.tsx +222 -0
  357. package/src/components/ui/bank-statement-generate-dialog.tsx +435 -0
  358. package/src/components/ui/bank-statement-pdf-viewer.tsx +241 -0
  359. package/src/components/ui/banking-accounts-connect.tsx +187 -0
  360. package/src/components/ui/borrowing-capacity-atoms.tsx +228 -0
  361. package/src/components/ui/borrowing-capacity-card.tsx +155 -0
  362. package/src/components/ui/broker-info-panel.tsx +94 -0
  363. package/src/components/ui/calculator-input-item.tsx +49 -0
  364. package/src/components/ui/calculator-section.tsx +275 -0
  365. package/src/components/ui/category-edit-dialog.tsx +300 -0
  366. package/src/components/ui/connect-bank-step.tsx +379 -0
  367. package/src/components/ui/contact-alert-dialog.tsx +710 -0
  368. package/src/components/ui/create-contact-modal.tsx +237 -0
  369. package/src/components/ui/csv-import-modal.tsx +153 -0
  370. package/src/components/ui/currency-input.tsx +104 -0
  371. package/src/components/ui/dashboard-expense-categories.tsx +262 -0
  372. package/src/components/ui/dashboard-transactions-table.tsx +241 -0
  373. package/src/components/ui/debt-accordion.tsx +254 -0
  374. package/src/components/ui/delete-contact-component.tsx +87 -0
  375. package/src/components/ui/dialog.tsx +2 -2
  376. package/src/components/ui/dynamic-tabs.tsx +149 -0
  377. package/src/components/ui/editable-money-item.tsx +176 -0
  378. package/src/components/ui/expense-detail-item.tsx +216 -0
  379. package/src/components/ui/expense-work-details.tsx +229 -0
  380. package/src/components/ui/file-preview-dialog.tsx +292 -0
  381. package/src/components/ui/financial-drawers.tsx +1 -1
  382. package/src/components/ui/frontend-signup-steps.tsx +548 -0
  383. package/src/components/ui/income-sources-card.tsx +143 -0
  384. package/src/components/ui/income-summary-component.tsx +120 -0
  385. package/src/components/ui/income-work-details.tsx +429 -0
  386. package/src/components/ui/incoming-outgoings-card.tsx +111 -0
  387. package/src/components/ui/interest-rate-input.tsx +111 -0
  388. package/src/components/ui/interest-rate-section.tsx +158 -0
  389. package/src/components/ui/interest-rate-used.tsx +82 -0
  390. package/src/components/ui/kanban-column.tsx +53 -2
  391. package/src/components/ui/loan-applicant-information.tsx +64 -0
  392. package/src/components/ui/loan-applicant-invite.tsx +67 -0
  393. package/src/components/ui/loan-application-badge.tsx +70 -0
  394. package/src/components/ui/loan-application-cards.tsx +152 -0
  395. package/src/components/ui/loan-entry-shell.tsx +86 -0
  396. package/src/components/ui/loan-financials.tsx +77 -0
  397. package/src/components/ui/loan-option-card.tsx +62 -0
  398. package/src/components/ui/loan-option-group.tsx +106 -0
  399. package/src/components/ui/loan-steps.tsx +630 -0
  400. package/src/components/ui/loan-wizard-shell.tsx +235 -0
  401. package/src/components/ui/money-input-with-slider.tsx +77 -0
  402. package/src/components/ui/money-item-with-color-indicator.tsx +30 -0
  403. package/src/components/ui/opportunity-card.tsx +46 -18
  404. package/src/components/ui/pipeline-board.tsx +13 -0
  405. package/src/components/ui/pipeline-primitives.tsx +28 -0
  406. package/src/components/ui/property-asset-card.tsx +221 -0
  407. package/src/components/ui/property-list-carousel.tsx +73 -0
  408. package/src/components/ui/property-report-dialog.tsx +355 -0
  409. package/src/components/ui/resource-center.tsx +539 -0
  410. package/src/components/ui/review-alerts-dialog.tsx +163 -0
  411. package/src/components/ui/savings-goal-modal.tsx +169 -0
  412. package/src/components/ui/scenario-drawer.tsx +358 -0
  413. package/src/components/ui/scenario-item.tsx +141 -0
  414. package/src/components/ui/scenario-list.tsx +150 -0
  415. package/src/components/ui/share-details-dialog.tsx +238 -0
  416. package/src/components/ui/signup-form-primitives.tsx +212 -0
  417. package/src/components/ui/signup-shell.tsx +180 -0
  418. package/src/components/ui/stage-timeline.tsx +11 -0
  419. package/src/components/ui/submission-confirmation-card.tsx +68 -0
  420. package/src/components/ui/top-three-product.tsx +207 -0
  421. package/src/components/ui/transactions-summary-block.tsx +59 -0
  422. package/src/lib/colors.ts +12 -0
  423. package/src/lib/format-date.ts +2 -2
  424. package/src/styles/styles-css.ts +1 -1
  425. package/tsup.config.ts +77 -1
  426. package/dist/{chunk-5VOTTIXF.mjs → chunk-FRT3S72S.mjs} +3 -3
  427. package/dist/{chunk-7BTFGCFC.mjs → chunk-MUV4EGDW.mjs} +3 -3
  428. package/dist/{chunk-57ZXILTS.mjs → chunk-MXP2RX2V.mjs} +3 -3
  429. package/dist/{chunk-ZKWXDQDG.mjs → chunk-VCDGLN25.mjs} +3 -3
  430. package/dist/{chunk-FLL633WS.mjs → chunk-ZXEUBBHJ.mjs} +3 -3
@@ -0,0 +1,169 @@
1
+ import React, { useState } from "react";
2
+ import { differenceInDays } from "date-fns";
3
+ import { cn } from "@/lib/utils";
4
+ import { formatCurrency } from "@/lib/format-currency";
5
+ import {
6
+ Dialog,
7
+ DialogContent,
8
+ DialogHeader,
9
+ DialogTitle,
10
+ DialogFooter,
11
+ } from "./dialog";
12
+ import { Button } from "./button";
13
+ import { DatePicker } from "./date-picker";
14
+ import { ToggleGroup, ToggleGroupItem } from "./toggle-group";
15
+ import { MoneyInputWithSlider } from "./money-input-with-slider";
16
+
17
+ type GoalPeriod = "90d" | "180d" | "360d" | "custom";
18
+
19
+ const PERIOD_OPTIONS: { id: GoalPeriod; label: string; days: number }[] = [
20
+ { id: "90d", label: "90 Days", days: 90 },
21
+ { id: "180d", label: "180 Days", days: 180 },
22
+ { id: "360d", label: "360 Days", days: 360 },
23
+ { id: "custom", label: "Custom", days: 0 },
24
+ ];
25
+
26
+ const PERIOD_DAYS: Partial<Record<GoalPeriod, number>> = Object.fromEntries(
27
+ PERIOD_OPTIONS.map((p) => [p.id, p.days]),
28
+ );
29
+
30
+ function SummaryRow({ label, value }: { label: string; value: number }) {
31
+ return (
32
+ <div className="flex items-center justify-between">
33
+ <span className="text-sm text-foreground">{label}</span>
34
+ <span className="text-sm font-semibold tabular-nums text-foreground">
35
+ {formatCurrency(value)}
36
+ </span>
37
+ </div>
38
+ );
39
+ }
40
+
41
+ export interface SavingsGoalModalProps {
42
+ open: boolean;
43
+ onOpenChange: (open: boolean) => void;
44
+ /** Current monthly savings trend (pre-calculated) in dollars */
45
+ currentMonthlyTrend?: number;
46
+ /** Initial goal amount in dollars */
47
+ defaultGoalAmount?: number;
48
+ /** Called when user confirms the goal */
49
+ onSave?: (goalAmount: number, periodDays: number) => void;
50
+ className?: string;
51
+ }
52
+
53
+ export function SavingsGoalModal({
54
+ open,
55
+ onOpenChange,
56
+ currentMonthlyTrend = 0,
57
+ defaultGoalAmount = 0,
58
+ onSave,
59
+ className,
60
+ }: SavingsGoalModalProps) {
61
+ const [goalAmount, setGoalAmount] = useState(defaultGoalAmount);
62
+ const [selectedPeriod, setSelectedPeriod] = useState<GoalPeriod>("90d");
63
+ const [customStart, setCustomStart] = useState<Date | undefined>(undefined);
64
+ const [customEnd, setCustomEnd] = useState<Date | undefined>(undefined);
65
+
66
+ const isCustom = selectedPeriod === "custom";
67
+ const today = new Date();
68
+
69
+ const periodDays = isCustom
70
+ ? customStart && customEnd && customEnd > customStart
71
+ ? differenceInDays(customEnd, customStart)
72
+ : 0
73
+ : (PERIOD_DAYS[selectedPeriod] ?? 90);
74
+
75
+ const monthlyTarget =
76
+ periodDays > 0 ? Math.round((goalAmount / periodDays) * 30) : 0;
77
+
78
+ const canSave = goalAmount > 0 && (!isCustom || periodDays > 0);
79
+
80
+ const handleSave = () => {
81
+ onSave?.(goalAmount, periodDays);
82
+ onOpenChange(false);
83
+ };
84
+
85
+ return (
86
+ <Dialog open={open} onOpenChange={onOpenChange}>
87
+ <DialogContent className={cn("max-w-sm top-8 translate-y-0", className)}>
88
+ <DialogHeader>
89
+ <DialogTitle>Savings Target Setter</DialogTitle>
90
+ </DialogHeader>
91
+
92
+ <div className="flex flex-col gap-6 py-2">
93
+ <MoneyInputWithSlider
94
+ label="Savings Goal"
95
+ value={goalAmount}
96
+ min={0}
97
+ max={200_000}
98
+ step={500}
99
+ onChange={setGoalAmount}
100
+ />
101
+
102
+ <div className="flex flex-col gap-3">
103
+ <p className="text-sm font-medium text-foreground">End Goal Date</p>
104
+ <ToggleGroup
105
+ type="single"
106
+ variant="outline"
107
+ size="sm"
108
+ className="w-full"
109
+ value={[selectedPeriod]}
110
+ onValueChange={(values) => {
111
+ const next = values[0] as GoalPeriod | undefined;
112
+ if (next) setSelectedPeriod(next);
113
+ }}
114
+ >
115
+ {PERIOD_OPTIONS.map((option) => (
116
+ <ToggleGroupItem
117
+ key={option.id}
118
+ value={option.id}
119
+ className="flex-1"
120
+ >
121
+ {option.label}
122
+ </ToggleGroupItem>
123
+ ))}
124
+ </ToggleGroup>
125
+
126
+ {isCustom && (
127
+ <div className="grid grid-cols-2 gap-2">
128
+ <div className="flex flex-col gap-1">
129
+ <p className="text-xs text-muted-foreground">Start Date</p>
130
+ <DatePicker
131
+ value={customStart}
132
+ onChange={setCustomStart}
133
+ placeholder="Start date"
134
+ calendarProps={{ disabled: { before: today } }}
135
+ />
136
+ </div>
137
+ <div className="flex flex-col gap-1">
138
+ <p className="text-xs text-muted-foreground">End Date</p>
139
+ <DatePicker
140
+ value={customEnd}
141
+ onChange={setCustomEnd}
142
+ placeholder="End date"
143
+ calendarProps={{
144
+ disabled: { before: customStart ?? today },
145
+ }}
146
+ />
147
+ </div>
148
+ </div>
149
+ )}
150
+ </div>
151
+
152
+ <div className="flex flex-col gap-3 border-t border-border pt-4">
153
+ <SummaryRow label="Monthly Savings Target" value={monthlyTarget} />
154
+ <SummaryRow label="Current Trend" value={currentMonthlyTrend} />
155
+ </div>
156
+ </div>
157
+
158
+ <DialogFooter>
159
+ <Button variant="ghost" onClick={() => onOpenChange(false)}>
160
+ Cancel
161
+ </Button>
162
+ <Button onClick={handleSave} disabled={!canSave}>
163
+ Set Now
164
+ </Button>
165
+ </DialogFooter>
166
+ </DialogContent>
167
+ </Dialog>
168
+ );
169
+ }
@@ -0,0 +1,358 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { Pencil, X } from "lucide-react";
3
+ import { cn } from "@/lib/utils";
4
+ import { Button } from "./button";
5
+ import { Input } from "./input";
6
+ import { MoneyInputWithSlider } from "./money-input-with-slider";
7
+ import { Toggle } from "./toggle";
8
+ import { Sheet, SheetContent, SheetTitle } from "./sheet";
9
+
10
+ /**
11
+ * Mobile bottom-sheet organism for creating or editing a borrowing scenario.
12
+ *
13
+ * Sections (top-to-bottom):
14
+ * - Header: editable scenario name + close button
15
+ * - Content (scrollable):
16
+ * - Objective selector (Buy a Home / Buy an Investment / Refinance)
17
+ * - Applicants selector (1 / 2)
18
+ * - Dependants selector (0 – 3)
19
+ * - MoneyInputWithSlider fields (income, expenses, debt, desired loan)
20
+ * - Footer: Cancel + Create/Update Scenario buttons
21
+ *
22
+ * On mobile the sheet fills the viewport width. On larger screens it is
23
+ * capped at max-w-2xl and the slider fields flow in a 2-column grid so
24
+ * the drawer does not stretch the page layout.
25
+ */
26
+
27
+ // ─── Types ────────────────────────────────────────────────────────────────────
28
+
29
+ export type ScenarioObjective = "buy-home" | "buy-investment" | "refinance";
30
+
31
+ export interface ScenarioDrawerValues {
32
+ name: string;
33
+ objective: ScenarioObjective;
34
+ /** 1 = sole applicant, 2 = two applicants */
35
+ applicants: 1 | 2;
36
+ /** Number of dependants (0–3) */
37
+ dependants: number;
38
+ /** Main applicant after-tax monthly income in dollars */
39
+ mainApplicantMonthlyIncome: number;
40
+ /** Main applicant monthly rental income in dollars */
41
+ mainApplicantMonthlyRentalIncome: number;
42
+ /** Co-applicant after-tax monthly income in dollars (applicants = 2 only) */
43
+ coApplicantMonthlyIncome: number;
44
+ /** Co-applicant monthly rental income in dollars (applicants = 2 only) */
45
+ coApplicantMonthlyRentalIncome: number;
46
+ /** Combined essential expenses per month in dollars */
47
+ monthlyExpense: number;
48
+ /** Combined debt repayments per month in dollars */
49
+ monthlyDebtRepayment: number;
50
+ /** Estimated rental income (buy-investment objective only) */
51
+ estimatedRentalIncome: number;
52
+ /** Target loan amount in dollars */
53
+ desiredLoanAmount: number;
54
+ }
55
+
56
+ export interface ScenarioDrawerProps {
57
+ open: boolean;
58
+ onOpenChange: (open: boolean) => void;
59
+ /** Initial field values — re-applied whenever the drawer opens */
60
+ defaultValues?: Partial<ScenarioDrawerValues>;
61
+ /** true = show "Update Scenario" footer button, false = "Create Scenario" */
62
+ isEditMode?: boolean;
63
+ /** Called with the final values when the user clicks Save */
64
+ onSave: (values: ScenarioDrawerValues) => void;
65
+ /** Called when the user clicks Cancel or the close button */
66
+ onCancel?: () => void;
67
+ className?: string;
68
+ }
69
+
70
+ // ─── Constants ────────────────────────────────────────────────────────────────
71
+
72
+ const DEFAULT_VALUES: ScenarioDrawerValues = {
73
+ name: "New Scenario",
74
+ objective: "buy-home",
75
+ applicants: 1,
76
+ dependants: 0,
77
+ mainApplicantMonthlyIncome: 0,
78
+ mainApplicantMonthlyRentalIncome: 0,
79
+ coApplicantMonthlyIncome: 0,
80
+ coApplicantMonthlyRentalIncome: 0,
81
+ monthlyExpense: 0,
82
+ monthlyDebtRepayment: 0,
83
+ estimatedRentalIncome: 0,
84
+ desiredLoanAmount: 750_000,
85
+ };
86
+
87
+ const OBJECTIVE_OPTIONS: { value: ScenarioObjective; label: string }[] = [
88
+ { value: "buy-home", label: "Buy a Home or Move" },
89
+ { value: "buy-investment", label: "Buy an Investment" },
90
+ { value: "refinance", label: "Refinance My Loan" },
91
+ ];
92
+
93
+ const APPLICANT_OPTIONS: { value: 1 | 2; label: string }[] = [
94
+ { value: 1, label: "Just Me" },
95
+ { value: 2, label: "Me + One" },
96
+ ];
97
+
98
+ const DEPENDANT_OPTIONS: { value: number; label: string }[] = [
99
+ { value: 0, label: "None" },
100
+ { value: 1, label: "1" },
101
+ { value: 2, label: "2" },
102
+ { value: 3, label: "3" },
103
+ ];
104
+
105
+ // ─── Internal sub-components ──────────────────────────────────────────────────
106
+
107
+ /**
108
+ * Horizontally connected row of Toggle buttons acting as a single-select group.
109
+ * Uses the WealthX `Toggle` variant="outline" so the pressed state renders
110
+ * with `bg-primary/10 + inset-ring-primary` per the DS token.
111
+ */
112
+ function OptionGroup<T extends string | number>({
113
+ label,
114
+ options,
115
+ value,
116
+ onChange,
117
+ }: {
118
+ label: string;
119
+ options: { value: T; label: string }[];
120
+ value: T;
121
+ onChange: (v: T) => void;
122
+ }) {
123
+ return (
124
+ <div className="flex flex-col gap-2">
125
+ <span className="text-sm font-medium text-foreground">{label}</span>
126
+ <div className="flex">
127
+ {options.map((opt, idx) => (
128
+ <Toggle
129
+ key={String(opt.value)}
130
+ variant="outline"
131
+ pressed={opt.value === value}
132
+ onPressedChange={(on) => {
133
+ if (on) onChange(opt.value);
134
+ }}
135
+ className={cn(
136
+ "flex-1 px-3 py-2 text-sm",
137
+ // Connect buttons: collapse shared borders
138
+ idx > 0 && "border-l-0",
139
+ )}
140
+ >
141
+ {opt.label}
142
+ </Toggle>
143
+ ))}
144
+ </div>
145
+ </div>
146
+ );
147
+ }
148
+
149
+ // ─── Main component ───────────────────────────────────────────────────────────
150
+
151
+ export function ScenarioDrawer({
152
+ open,
153
+ onOpenChange,
154
+ defaultValues,
155
+ isEditMode = false,
156
+ onSave,
157
+ onCancel,
158
+ className,
159
+ }: ScenarioDrawerProps) {
160
+ const [values, setValues] = useState<ScenarioDrawerValues>({
161
+ ...DEFAULT_VALUES,
162
+ ...defaultValues,
163
+ });
164
+ const [editingName, setEditingName] = useState(false);
165
+
166
+ // Re-seed internal state whenever the drawer opens with new defaultValues
167
+ useEffect(() => {
168
+ if (open) {
169
+ setValues({ ...DEFAULT_VALUES, ...defaultValues });
170
+ }
171
+ }, [open]); // intentional: only react to open changing, not defaultValues
172
+
173
+ const set = <K extends keyof ScenarioDrawerValues>(
174
+ key: K,
175
+ value: ScenarioDrawerValues[K],
176
+ ) => setValues((prev) => ({ ...prev, [key]: value }));
177
+
178
+ const handleCancel = () => {
179
+ onCancel?.();
180
+ onOpenChange(false);
181
+ };
182
+
183
+ const handleSave = () => {
184
+ onSave(values);
185
+ onOpenChange(false);
186
+ };
187
+
188
+ const isTwoApplicants = values.applicants === 2;
189
+ const isInvestment = values.objective === "buy-investment";
190
+ const expenseLabel = isTwoApplicants ? "Combined" : "Estimated";
191
+
192
+ return (
193
+ <Sheet open={open} onOpenChange={onOpenChange}>
194
+ {/*
195
+ * showCloseButton={false}: disable the Sheet's built-in absolute close
196
+ * button — the drawer renders its own X in the header row.
197
+ */}
198
+ <SheetContent
199
+ side="bottom"
200
+ showCloseButton={false}
201
+ className={cn("flex max-h-[90dvh] flex-col gap-0 p-0", className)}
202
+ >
203
+ {/* ── Header ─────────────────────────────────────────────────────── */}
204
+ <div className="flex items-center justify-between border-b border-border px-4 py-3">
205
+ <SheetTitle className="sr-only">
206
+ {isEditMode ? "Edit Scenario" : "Create Scenario"}
207
+ </SheetTitle>
208
+
209
+ {editingName ? (
210
+ <Input
211
+ autoFocus
212
+ value={values.name}
213
+ onChange={(e) => set("name", e.target.value)}
214
+ onBlur={() => setEditingName(false)}
215
+ onKeyDown={(e) => e.key === "Enter" && setEditingName(false)}
216
+ className="h-8 text-base font-semibold"
217
+ />
218
+ ) : (
219
+ <button
220
+ type="button"
221
+ onClick={() => setEditingName(true)}
222
+ className="flex items-center gap-2 text-base font-semibold text-foreground hover:opacity-70"
223
+ >
224
+ {values.name}
225
+ <Pencil size={14} className="shrink-0 text-muted-foreground" />
226
+ </button>
227
+ )}
228
+
229
+ <button
230
+ type="button"
231
+ onClick={handleCancel}
232
+ aria-label="Close"
233
+ className="ml-3 shrink-0 p-1 text-muted-foreground transition-colors hover:text-foreground"
234
+ >
235
+ <X size={18} />
236
+ </button>
237
+ </div>
238
+
239
+ {/* ── Scrollable content ──────────────────────────────────────────── */}
240
+ <div className="flex-1 overflow-y-auto px-4 py-4">
241
+ <div className="flex flex-col gap-6">
242
+ {/* Selectors */}
243
+ <OptionGroup
244
+ label="Objective"
245
+ options={OBJECTIVE_OPTIONS}
246
+ value={values.objective}
247
+ onChange={(v) => set("objective", v)}
248
+ />
249
+ <OptionGroup
250
+ label="Applicants"
251
+ options={APPLICANT_OPTIONS}
252
+ value={values.applicants}
253
+ onChange={(v) => set("applicants", v)}
254
+ />
255
+ <OptionGroup
256
+ label="Dependants"
257
+ options={DEPENDANT_OPTIONS}
258
+ value={values.dependants}
259
+ onChange={(v) => set("dependants", v)}
260
+ />
261
+
262
+ {/* Income sliders — 2-col grid on md+ */}
263
+ <div className="grid grid-cols-1 gap-5 md:grid-cols-2">
264
+ <MoneyInputWithSlider
265
+ label="Main Applicant Monthly Income"
266
+ value={values.mainApplicantMonthlyIncome}
267
+ min={0}
268
+ max={30_000}
269
+ step={100}
270
+ onChange={(v) => set("mainApplicantMonthlyIncome", v)}
271
+ />
272
+ <MoneyInputWithSlider
273
+ label="Main Applicant Rental Income"
274
+ value={values.mainApplicantMonthlyRentalIncome}
275
+ min={0}
276
+ max={30_000}
277
+ step={100}
278
+ onChange={(v) => set("mainApplicantMonthlyRentalIncome", v)}
279
+ />
280
+ {isTwoApplicants && (
281
+ <>
282
+ <MoneyInputWithSlider
283
+ label="Co-Applicant Monthly Income"
284
+ value={values.coApplicantMonthlyIncome}
285
+ min={0}
286
+ max={30_000}
287
+ step={100}
288
+ onChange={(v) => set("coApplicantMonthlyIncome", v)}
289
+ />
290
+ <MoneyInputWithSlider
291
+ label="Co-Applicant Rental Income"
292
+ value={values.coApplicantMonthlyRentalIncome}
293
+ min={0}
294
+ max={30_000}
295
+ step={100}
296
+ onChange={(v) => set("coApplicantMonthlyRentalIncome", v)}
297
+ />
298
+ </>
299
+ )}
300
+ </div>
301
+
302
+ {/* Expense sliders — 2-col grid on md+ */}
303
+ <div className="grid grid-cols-1 gap-5 md:grid-cols-2">
304
+ <MoneyInputWithSlider
305
+ label={`${expenseLabel} Essential Expenses PM`}
306
+ value={values.monthlyExpense}
307
+ min={0}
308
+ max={15_000}
309
+ step={100}
310
+ onChange={(v) => set("monthlyExpense", v)}
311
+ />
312
+ <MoneyInputWithSlider
313
+ label={`${expenseLabel} Debt Repayment PM`}
314
+ value={values.monthlyDebtRepayment}
315
+ min={0}
316
+ max={15_000}
317
+ step={100}
318
+ onChange={(v) => set("monthlyDebtRepayment", v)}
319
+ />
320
+ {isInvestment && (
321
+ <MoneyInputWithSlider
322
+ label="Estimated Rental Income PM"
323
+ value={values.estimatedRentalIncome}
324
+ min={0}
325
+ max={30_000}
326
+ step={100}
327
+ onChange={(v) => set("estimatedRentalIncome", v)}
328
+ />
329
+ )}
330
+ </div>
331
+
332
+ {/* Desired Loan Amount */}
333
+ <div className="border-t border-border pt-4">
334
+ <MoneyInputWithSlider
335
+ label="Desired Loan Amount"
336
+ value={values.desiredLoanAmount}
337
+ min={50_000}
338
+ max={2_000_000}
339
+ step={5_000}
340
+ onChange={(v) => set("desiredLoanAmount", v)}
341
+ />
342
+ </div>
343
+ </div>
344
+ </div>
345
+
346
+ {/* ── Footer ──────────────────────────────────────────────────────── */}
347
+ <div className="flex gap-3 border-t border-border px-4 py-3">
348
+ <Button variant="outline" className="flex-1" onClick={handleCancel}>
349
+ Cancel
350
+ </Button>
351
+ <Button className="flex-1" onClick={handleSave}>
352
+ {isEditMode ? "Update Scenario" : "Create Scenario"}
353
+ </Button>
354
+ </div>
355
+ </SheetContent>
356
+ </Sheet>
357
+ );
358
+ }
@@ -0,0 +1,141 @@
1
+ import React from "react";
2
+ import { GripVertical, MoreVertical } from "lucide-react";
3
+ import { cn } from "@/lib/utils";
4
+ import {
5
+ DropdownMenu,
6
+ DropdownMenuContent,
7
+ DropdownMenuItem,
8
+ DropdownMenuTrigger,
9
+ } from "./dropdown-menu";
10
+
11
+ /**
12
+ * A selectable scenario card used in the Borrowing Capacity left sidebar.
13
+ *
14
+ * Displays a scenario name and description. Supports selected state (right
15
+ * border accent), an optional drag handle for reordering, and an optional
16
+ * kebab menu with "Update Scenario" and "Delete Scenario" options.
17
+ */
18
+
19
+ export interface ScenarioItemProps {
20
+ /** Scenario display name (e.g. "Default Scenario") */
21
+ name: string;
22
+ /** Secondary descriptor (e.g. "Owner Occupier") */
23
+ description?: string;
24
+ /** Highlights the item with a left border accent */
25
+ isSelected?: boolean;
26
+ /** Shows the drag grip handle and marks the root as draggable */
27
+ isDraggable?: boolean;
28
+ /** Visual drag-over highlight (consumer-controlled) */
29
+ isDragOver?: boolean;
30
+ /** Click handler — typically selects this scenario */
31
+ onSelect?: () => void;
32
+ /** Called when "Update Scenario" is clicked in the kebab menu */
33
+ onEdit?: () => void;
34
+ /** Called when "Delete Scenario" is clicked in the kebab menu */
35
+ onDelete?: () => void;
36
+ /** HTML5 drag events forwarded from parent (ScenarioList) */
37
+ onDragStart?: (e: React.DragEvent<HTMLDivElement>) => void;
38
+ onDragOver?: (e: React.DragEvent<HTMLDivElement>) => void;
39
+ onDragLeave?: (e: React.DragEvent<HTMLDivElement>) => void;
40
+ onDrop?: (e: React.DragEvent<HTMLDivElement>) => void;
41
+ onDragEnd?: (e: React.DragEvent<HTMLDivElement>) => void;
42
+ className?: string;
43
+ }
44
+
45
+ export function ScenarioItem({
46
+ name,
47
+ description,
48
+ isSelected = false,
49
+ isDraggable = false,
50
+ isDragOver = false,
51
+ onSelect,
52
+ onEdit,
53
+ onDelete,
54
+ onDragStart,
55
+ onDragOver,
56
+ onDragLeave,
57
+ onDrop,
58
+ onDragEnd,
59
+ className,
60
+ }: ScenarioItemProps) {
61
+ return (
62
+ <div
63
+ role="button"
64
+ tabIndex={0}
65
+ draggable={isDraggable}
66
+ onClick={onSelect}
67
+ onKeyDown={(e) => {
68
+ if (e.key === "Enter" || e.key === " ") onSelect?.();
69
+ }}
70
+ onDragStart={onDragStart}
71
+ onDragOver={onDragOver}
72
+ onDragLeave={onDragLeave}
73
+ onDrop={onDrop}
74
+ onDragEnd={onDragEnd}
75
+ className={cn(
76
+ "flex cursor-pointer items-center gap-2 border border-border bg-background px-3 py-3 transition-colors hover:bg-muted/50",
77
+ isSelected && "border-r-2 border-r-primary bg-primary/5",
78
+ isDragOver && "bg-primary/10",
79
+ className,
80
+ )}
81
+ >
82
+ {isDraggable && (
83
+ <span
84
+ aria-hidden
85
+ className="shrink-0 cursor-grab text-muted-foreground active:cursor-grabbing"
86
+ >
87
+ <GripVertical size={16} />
88
+ </span>
89
+ )}
90
+
91
+ <div className="min-w-0 flex-1">
92
+ <p className="truncate text-base font-semibold text-foreground">
93
+ {name}
94
+ </p>
95
+ {description && (
96
+ <p className="mt-0.5 truncate text-sm text-muted-foreground">
97
+ {description}
98
+ </p>
99
+ )}
100
+ </div>
101
+
102
+ {(onEdit || onDelete) && (
103
+ <DropdownMenu>
104
+ <DropdownMenuTrigger asChild>
105
+ <button
106
+ type="button"
107
+ aria-label="Scenario options"
108
+ onClick={(e) => e.stopPropagation()}
109
+ className="shrink-0 p-1 text-muted-foreground transition-colors hover:text-foreground"
110
+ >
111
+ <MoreVertical size={16} />
112
+ </button>
113
+ </DropdownMenuTrigger>
114
+ <DropdownMenuContent align="end">
115
+ {onEdit && (
116
+ <DropdownMenuItem
117
+ onClick={(e) => {
118
+ e.stopPropagation();
119
+ onEdit();
120
+ }}
121
+ >
122
+ Update Scenario
123
+ </DropdownMenuItem>
124
+ )}
125
+ {onDelete && (
126
+ <DropdownMenuItem
127
+ onClick={(e) => {
128
+ e.stopPropagation();
129
+ onDelete();
130
+ }}
131
+ className="text-destructive focus:text-destructive"
132
+ >
133
+ Delete Scenario
134
+ </DropdownMenuItem>
135
+ )}
136
+ </DropdownMenuContent>
137
+ </DropdownMenu>
138
+ )}
139
+ </div>
140
+ );
141
+ }