@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,241 @@
1
+ import { useEffect, useMemo, useRef, useState } from "react";
2
+ import { ChevronLeft, ChevronRight, Download, X } from "lucide-react";
3
+ import { cn } from "@/lib/utils";
4
+ import { Button } from "@/components/ui/button";
5
+ import { Dialog, DialogContent } from "@/components/ui/dialog";
6
+ import { Spinner } from "@/components/ui/spinner";
7
+
8
+ /**
9
+ * BankStatementPDFViewer — WealthX DS (L4 Template)
10
+ *
11
+ * Full-viewport dialog for viewing a bank statement PDF.
12
+ * Supports paging through multiple accounts using prev / next navigation.
13
+ *
14
+ * PDF rendering:
15
+ * - Embeds the blob via `URL.createObjectURL(pdfBlob) + "#toolbar=0"` in an
16
+ * `<iframe>` so the browser's native PDF plugin renders it without toolbar.
17
+ * - Object URL is revoked automatically when the blob changes.
18
+ *
19
+ * Typical usage in the Bank Statement tab:
20
+ * 1. User clicks a document name in `BankStatementDocumentTable`.
21
+ * 2. Consumer fetches the PDF blob for each linked account.
22
+ * 3. `BankStatementPDFViewer` is mounted with `open={true}`.
23
+ * 4. User pages through accounts with ‹ / ›; download icon triggers a direct
24
+ * browser download of the current blob.
25
+ *
26
+ * Layer: L4 Template
27
+ */
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Types
31
+ // ---------------------------------------------------------------------------
32
+
33
+ export interface BankStatementViewerAccount {
34
+ id: string;
35
+ /** Account display name (e.g. "Everyday Savings"). */
36
+ name?: string;
37
+ /** Institution name fallback (e.g. "CommBank"). */
38
+ institutionName?: string;
39
+ }
40
+
41
+ export interface BankStatementPDFViewerProps {
42
+ open: boolean;
43
+ onClose: () => void;
44
+ /** Raw PDF blob for the currently viewed document. `null` shows an empty state. */
45
+ pdfBlob: Blob | null;
46
+ /** Filename used for the browser download, e.g. "CommBank_James_90days.pdf". */
47
+ pdfFilename?: string;
48
+ /** All accounts linked to this statement (for prev/next navigation). */
49
+ accounts: BankStatementViewerAccount[];
50
+ /** Zero-based index of the currently viewed account. */
51
+ currentAccountIndex: number;
52
+ /** Called when the user clicks ‹ / › to navigate between accounts. */
53
+ onAccountChange: (index: number) => void;
54
+ className?: string;
55
+ }
56
+
57
+ // ---------------------------------------------------------------------------
58
+ // BankStatementPDFViewer
59
+ // ---------------------------------------------------------------------------
60
+
61
+ export function BankStatementPDFViewer({
62
+ open,
63
+ onClose,
64
+ pdfBlob,
65
+ pdfFilename,
66
+ accounts,
67
+ currentAccountIndex,
68
+ onAccountChange,
69
+ className,
70
+ }: BankStatementPDFViewerProps) {
71
+ const [loading, setLoading] = useState(true);
72
+ const [error, setError] = useState<string | null>(null);
73
+ const previousUrlRef = useRef<string | null>(null);
74
+
75
+ // Create an object URL from the blob (memoised; revoked when blob changes)
76
+ const pdfUrl = useMemo(() => {
77
+ if (!pdfBlob) return null;
78
+ return `${URL.createObjectURL(pdfBlob)}#toolbar=0`;
79
+ }, [pdfBlob]);
80
+
81
+ // Revoke the previous URL when the blob changes to avoid memory leaks
82
+ useEffect(() => {
83
+ return () => {
84
+ if (pdfUrl) {
85
+ // Strip the #toolbar=0 fragment before revoking
86
+ URL.revokeObjectURL(pdfUrl.split("#")[0]);
87
+ }
88
+ };
89
+ }, [pdfUrl]);
90
+
91
+ // Reset loading state when the URL (blob or account) changes
92
+ useEffect(() => {
93
+ if (!pdfUrl) {
94
+ setLoading(false);
95
+ return;
96
+ }
97
+
98
+ if (previousUrlRef.current !== pdfUrl) {
99
+ previousUrlRef.current = pdfUrl;
100
+ setLoading(true);
101
+ setError(null);
102
+ }
103
+
104
+ // Fallback: hide spinner after 2 s even if onLoad never fires (e.g. Firefox)
105
+ const timer = setTimeout(() => setLoading(false), 2000);
106
+ return () => clearTimeout(timer);
107
+ }, [pdfUrl, currentAccountIndex]);
108
+
109
+ // ── Navigation ────────────────────────────────────────────────────────────
110
+
111
+ const canGoPrev = currentAccountIndex > 0;
112
+ const canGoNext = currentAccountIndex < accounts.length - 1;
113
+
114
+ const currentAccount = accounts[currentAccountIndex];
115
+ const accountLabel =
116
+ currentAccount?.name ?? currentAccount?.institutionName ?? "Account";
117
+
118
+ // ── Download ──────────────────────────────────────────────────────────────
119
+
120
+ const handleDownload = () => {
121
+ if (!pdfBlob) return;
122
+ const filename = pdfFilename ?? "bank-statement.pdf";
123
+ const url = URL.createObjectURL(pdfBlob);
124
+ const anchor = document.createElement("a");
125
+ anchor.href = url;
126
+ anchor.download = filename;
127
+ document.body.appendChild(anchor);
128
+ anchor.click();
129
+ document.body.removeChild(anchor);
130
+ URL.revokeObjectURL(url);
131
+ };
132
+
133
+ // ── Render ────────────────────────────────────────────────────────────────
134
+
135
+ return (
136
+ <Dialog open={open} onOpenChange={(o) => !o && onClose()}>
137
+ <DialogContent
138
+ showCloseButton={false}
139
+ className={cn(
140
+ "flex h-[95vh] max-h-[95vh] w-[95vw] max-w-[95vw] flex-col gap-0 p-0",
141
+ className,
142
+ )}
143
+ data-slot="bank-statement-pdf-viewer"
144
+ >
145
+ {/* Navigation bar */}
146
+ <div className="flex shrink-0 items-center justify-between border-b border-border px-3 py-2">
147
+ <div className="flex items-center gap-2">
148
+ <Button
149
+ variant="ghost"
150
+ size="icon-sm"
151
+ aria-label="Previous account"
152
+ onClick={() => onAccountChange(currentAccountIndex - 1)}
153
+ disabled={!canGoPrev}
154
+ >
155
+ <ChevronLeft className="size-4" />
156
+ </Button>
157
+
158
+ <span className="text-body-medium tabular-nums">
159
+ Account {currentAccountIndex + 1} of {accounts.length}
160
+ </span>
161
+
162
+ <Button
163
+ variant="ghost"
164
+ size="icon-sm"
165
+ aria-label="Next account"
166
+ onClick={() => onAccountChange(currentAccountIndex + 1)}
167
+ disabled={!canGoNext}
168
+ >
169
+ <ChevronRight className="size-4" />
170
+ </Button>
171
+
172
+ <span className="ml-2 text-body-medium text-muted-foreground">
173
+ {accountLabel}
174
+ </span>
175
+ </div>
176
+
177
+ <div className="flex items-center gap-1">
178
+ <Button
179
+ variant="ghost"
180
+ size="icon-sm"
181
+ aria-label="Download PDF"
182
+ onClick={handleDownload}
183
+ disabled={!pdfBlob}
184
+ >
185
+ <Download className="size-4" />
186
+ </Button>
187
+ <Button
188
+ variant="ghost"
189
+ size="icon-sm"
190
+ aria-label="Close viewer"
191
+ onClick={onClose}
192
+ >
193
+ <X className="size-4" />
194
+ </Button>
195
+ </div>
196
+ </div>
197
+
198
+ {/* PDF area */}
199
+ <div className="relative flex flex-1 items-start justify-center overflow-auto bg-muted">
200
+ {!pdfBlob ? (
201
+ <div className="flex h-full w-full items-center justify-center">
202
+ <p className="text-body-medium text-muted-foreground">
203
+ No PDF document available
204
+ </p>
205
+ </div>
206
+ ) : (
207
+ <>
208
+ {loading && (
209
+ <div className="absolute left-1/2 top-1/2 z-10 flex -translate-x-1/2 -translate-y-1/2 flex-col items-center gap-2">
210
+ <Spinner />
211
+ <p className="text-body-medium text-muted-foreground">
212
+ Loading PDF…
213
+ </p>
214
+ </div>
215
+ )}
216
+
217
+ {error && !loading && (
218
+ <div className="absolute left-1/2 top-1/2 z-10 -translate-x-1/2 -translate-y-1/2">
219
+ <p className="text-body-medium text-destructive">{error}</p>
220
+ </div>
221
+ )}
222
+
223
+ <iframe
224
+ key={pdfUrl ?? "no-url"}
225
+ src={pdfUrl ?? undefined}
226
+ className="min-h-full w-full max-w-[1000px] border-none transition-opacity duration-300"
227
+ style={{ opacity: loading ? 0 : 1 }}
228
+ title="Bank Statement PDF"
229
+ onLoad={() => setLoading(false)}
230
+ onError={() => {
231
+ setLoading(false);
232
+ setError("Failed to load PDF");
233
+ }}
234
+ />
235
+ </>
236
+ )}
237
+ </div>
238
+ </DialogContent>
239
+ </Dialog>
240
+ );
241
+ }
@@ -0,0 +1,187 @@
1
+ import * as React from "react";
2
+ import { cn } from "@/lib/utils";
3
+ import { Button } from "@/components/ui/button";
4
+
5
+ // ─── Types ────────────────────────────────────────────────────────────────────
6
+
7
+ export type BankAccountItem = {
8
+ id: string;
9
+ name: string;
10
+ balance?: string;
11
+ institutionName?: string;
12
+ institutionLogoUrl?: string;
13
+ };
14
+
15
+ export type BankAccountCategory =
16
+ | "banking"
17
+ | "home-loan"
18
+ | "credit-card"
19
+ | "personal-loan";
20
+
21
+ export type BankAccountsByCategory = Partial<
22
+ Record<BankAccountCategory, BankAccountItem[]>
23
+ >;
24
+
25
+ export type BankingAccountsConnectApplicant = {
26
+ name: string;
27
+ email?: string;
28
+ };
29
+
30
+ export type BankingAccountsConnectProps = {
31
+ applicant: BankingAccountsConnectApplicant;
32
+ /** Connected accounts grouped by category. All accounts are flattened and shown in a single grid. */
33
+ accountsByCategory?: BankAccountsByCategory;
34
+ /** Called when the "Connect Your Bank +" tile is clicked. */
35
+ onConnectBank?: () => void;
36
+ onNext?: () => void;
37
+ onPrev?: () => void;
38
+ /** Hide the built-in Previous/Next navigation row — use when the parent wizard shell provides navigation. */
39
+ hideNavigation?: boolean;
40
+ className?: string;
41
+ };
42
+
43
+ // ─── Component ────────────────────────────────────────────────────────────────
44
+
45
+ /**
46
+ * BankingAccountsConnect — shown on the Connections tab when the applicant
47
+ * already has at least one bank account connected.
48
+ *
49
+ * Renders all connected accounts as horizontal card tiles plus a
50
+ * "Connect Your Bank +" tile to add more. Layout mirrors the bank-selection
51
+ * grid in ConnectBankStep.
52
+ *
53
+ * Figma: WealthX-Backoffice---Mobile-App — node 19308:53046 (Connection section)
54
+ */
55
+ export function BankingAccountsConnect({
56
+ accountsByCategory = {},
57
+ onConnectBank,
58
+ onNext,
59
+ onPrev,
60
+ hideNavigation = false,
61
+ className,
62
+ }: BankingAccountsConnectProps) {
63
+ // Flatten all category accounts into a single list for display
64
+ const allAccounts = ([] as BankAccountItem[]).concat(
65
+ ...Object.values(accountsByCategory),
66
+ );
67
+
68
+ return (
69
+ <div className={cn("flex flex-col gap-6 font-sans", className)}>
70
+ {/* Heading with left accent bar */}
71
+ <div className="border-l-4 border-primary pl-3">
72
+ <h2 className="text-h3 text-foreground">
73
+ Connect Available Banking Information
74
+ </h2>
75
+ <p className="mt-1 text-body-small text-muted-foreground">
76
+ This will help auto populate your application form and remove the need
77
+ to upload bank statements.
78
+ </p>
79
+ </div>
80
+
81
+ {/* Connected accounts grid */}
82
+ <div className="flex flex-col gap-3">
83
+ <h3 className="text-label-large text-foreground">
84
+ Your Connected Accounts
85
+ </h3>
86
+
87
+ {/* 3-column tile grid — same border-collapse trick as ConnectBankStep */}
88
+ <div className="grid grid-cols-3 border-l border-t border-border">
89
+ {allAccounts.map((account: BankAccountItem) => (
90
+ <div
91
+ key={account.id}
92
+ className="flex h-[82px] items-center gap-3 border-b border-r border-border bg-background p-3"
93
+ >
94
+ {/* Institution logo or abbreviation */}
95
+ {account.institutionLogoUrl ? (
96
+ <img
97
+ src={account.institutionLogoUrl}
98
+ alt={account.institutionName ?? ""}
99
+ className="size-[50px] shrink-0 object-contain"
100
+ />
101
+ ) : (
102
+ <div className="flex size-[50px] shrink-0 items-center justify-center bg-muted text-caption text-muted-foreground">
103
+ {account.institutionName?.[0] ?? "?"}
104
+ </div>
105
+ )}
106
+
107
+ {/* Account name + balance */}
108
+ <div className="flex min-w-0 flex-col">
109
+ <span className="truncate text-body-small text-foreground">
110
+ {account.name}
111
+ </span>
112
+ {account.balance && (
113
+ <span className="text-label-small text-foreground">
114
+ {account.balance}
115
+ </span>
116
+ )}
117
+ </div>
118
+ </div>
119
+ ))}
120
+
121
+ {/* "Connect Your Bank +" tile */}
122
+ <button
123
+ type="button"
124
+ onClick={onConnectBank}
125
+ className="flex h-[82px] items-center justify-center gap-1.5 border-b border-r border-border bg-background p-3 transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring"
126
+ >
127
+ <span className="text-body-small font-bold text-foreground">
128
+ Connect Your Bank +
129
+ </span>
130
+ </button>
131
+ </div>
132
+ </div>
133
+
134
+ {/* Navigation — hidden when the parent wizard shell owns navigation */}
135
+ {!hideNavigation && (
136
+ <div className="flex items-center justify-between border-t border-border pt-4">
137
+ <Button variant="outline" onClick={onPrev}>
138
+ <ChevronLeftIcon className="mr-1 size-4" />
139
+ Previous
140
+ </Button>
141
+ <Button onClick={onNext}>
142
+ Next
143
+ <ChevronRightIcon className="ml-1 size-4" />
144
+ </Button>
145
+ </div>
146
+ )}
147
+ </div>
148
+ );
149
+ }
150
+
151
+ // ─── Icons ────────────────────────────────────────────────────────────────────
152
+
153
+ function ChevronLeftIcon({ className }: { className?: string }) {
154
+ return (
155
+ <svg
156
+ xmlns="http://www.w3.org/2000/svg"
157
+ viewBox="0 0 24 24"
158
+ fill="none"
159
+ stroke="currentColor"
160
+ strokeWidth={2}
161
+ strokeLinecap="round"
162
+ strokeLinejoin="round"
163
+ className={className}
164
+ aria-hidden="true"
165
+ >
166
+ <path d="m15 18-6-6 6-6" />
167
+ </svg>
168
+ );
169
+ }
170
+
171
+ function ChevronRightIcon({ className }: { className?: string }) {
172
+ return (
173
+ <svg
174
+ xmlns="http://www.w3.org/2000/svg"
175
+ viewBox="0 0 24 24"
176
+ fill="none"
177
+ stroke="currentColor"
178
+ strokeWidth={2}
179
+ strokeLinecap="round"
180
+ strokeLinejoin="round"
181
+ className={className}
182
+ aria-hidden="true"
183
+ >
184
+ <path d="m9 18 6-6-6-6" />
185
+ </svg>
186
+ );
187
+ }
@@ -0,0 +1,228 @@
1
+ import React from "react";
2
+ import { TrendingUp, TrendingDown, Minus, Plus } from "lucide-react";
3
+ import { cn } from "@/lib/utils";
4
+ import { formatCurrencyAbbrev } from "@/lib/format-currency";
5
+ import { Button } from "./button";
6
+
7
+ // ─── BorrowCapacityItem ───────────────────────────────────────────────────────
8
+ /**
9
+ * Displays a single borrowing capacity result field.
10
+ * Shows a muted label, optional sub-label, and the formatted value below.
11
+ *
12
+ * Used inside scenario detail cards on the Borrowing Capacity page.
13
+ */
14
+
15
+ export interface BorrowCapacityItemProps {
16
+ /** Label above the value (e.g. "Purchase Price") */
17
+ title?: string;
18
+ /** Optional secondary descriptor below the title */
19
+ subTitle?: string;
20
+ /** Pre-formatted value string to display (e.g. "$500,000") */
21
+ value?: string;
22
+ className?: string;
23
+ }
24
+
25
+ export function BorrowCapacityItem({
26
+ title,
27
+ subTitle,
28
+ value,
29
+ className,
30
+ }: BorrowCapacityItemProps) {
31
+ if (!title && !value) {
32
+ return <div className={cn("min-h-[52px]", className)} aria-hidden />;
33
+ }
34
+
35
+ return (
36
+ <div className={cn("flex flex-col gap-1", className)}>
37
+ {title && (
38
+ <span className="block min-h-[2.5rem] text-sm text-muted-foreground">
39
+ {title}
40
+ </span>
41
+ )}
42
+ {value && (
43
+ <span className="text-lg font-semibold text-foreground">{value}</span>
44
+ )}
45
+ {subTitle && (
46
+ <span className="text-sm italic text-muted-foreground/70">
47
+ {subTitle}
48
+ </span>
49
+ )}
50
+ </div>
51
+ );
52
+ }
53
+
54
+ // ─── StatisticItem ────────────────────────────────────────────────────────────
55
+ /**
56
+ * Shows a financial trend statistic over a lookback period.
57
+ * Displays a heading ("Last N months"), the absolute dollar change,
58
+ * and the percentage change with a direction icon.
59
+ *
60
+ * Trend colors: positive → primary, flat/negative → muted.
61
+ *
62
+ * Used in the statistics summary row of the Borrowing Capacity page.
63
+ */
64
+
65
+ export interface StatisticItemProps {
66
+ /** Number of months to look back (default: 3) */
67
+ loopBackMonths?: number;
68
+ /** Absolute dollar amount of change */
69
+ amountChange?: number;
70
+ /** Percentage change — positive = up, negative = down, 0 = flat */
71
+ amountChangePercentage?: number;
72
+ className?: string;
73
+ }
74
+
75
+ export function StatisticItem({
76
+ loopBackMonths = 3,
77
+ amountChange = 0,
78
+ amountChangePercentage = 0,
79
+ className,
80
+ }: StatisticItemProps) {
81
+ const isPositive = amountChangePercentage > 0;
82
+ const isNegative = amountChangePercentage < 0;
83
+ const TrendIcon = isPositive ? TrendingUp : isNegative ? TrendingDown : Minus;
84
+ const trendClassName = isPositive ? "text-primary" : "text-muted-foreground";
85
+ const amountPrefix = isPositive ? "+" : isNegative ? "−" : "";
86
+
87
+ return (
88
+ <div
89
+ className={cn(
90
+ "flex flex-col justify-center gap-2 border border-border p-3",
91
+ className,
92
+ )}
93
+ >
94
+ <span className="text-sm text-muted-foreground">
95
+ Last {loopBackMonths} month{loopBackMonths !== 1 ? "s" : ""}
96
+ </span>
97
+ <div className="flex items-center justify-between gap-2">
98
+ <span className="text-xl font-semibold tabular-nums text-foreground">
99
+ {amountPrefix}
100
+ {formatCurrencyAbbrev(Math.abs(amountChange), 2)}
101
+ </span>
102
+ <span
103
+ className={cn(
104
+ "flex items-center gap-1 text-sm font-medium tabular-nums",
105
+ trendClassName,
106
+ )}
107
+ >
108
+ <TrendIcon size={14} className="shrink-0" />
109
+ {Math.abs(amountChangePercentage).toFixed(1)}%
110
+ </span>
111
+ </div>
112
+ </div>
113
+ );
114
+ }
115
+
116
+ // ─── LoanToValueRatio ─────────────────────────────────────────────────────────
117
+ /**
118
+ * Displays a Loan-to-Value Ratio (LVR) as a percentage with a color-coded
119
+ * risk indicator and an optional equity/debt breakdown bar.
120
+ *
121
+ * Risk tiers:
122
+ * ≤ 60% → green (safe)
123
+ * 61–80% → warning (moderate)
124
+ * > 80% → destructive (high)
125
+ *
126
+ * Used in the LVR settings panel of the Borrowing Capacity page.
127
+ */
128
+
129
+ export interface LoanToValueRatioProps {
130
+ /** LVR as a whole number percentage (0–100) */
131
+ lvr: number;
132
+ /** Optional debt amount — shown below the bar when provided */
133
+ debtAmount?: number;
134
+ /** Optional equity amount — shown below the bar when provided */
135
+ equityAmount?: number;
136
+ className?: string;
137
+ }
138
+
139
+ // Thresholds match major Australian lender risk bands
140
+ const LVR_TIER_STYLES = {
141
+ safe: { text: "text-success", bar: "bg-success" },
142
+ moderate: { text: "text-warning", bar: "bg-warning" },
143
+ high: { text: "text-destructive", bar: "bg-destructive" },
144
+ } as const;
145
+
146
+ export function LoanToValueRatio({
147
+ lvr,
148
+ debtAmount,
149
+ equityAmount,
150
+ className,
151
+ }: LoanToValueRatioProps) {
152
+ const clamped = Math.min(100, Math.max(0, lvr));
153
+ const tier = clamped <= 60 ? "safe" : clamped <= 80 ? "moderate" : "high";
154
+ const { text: lvrTextColor, bar: lvrBarColor } = LVR_TIER_STYLES[tier];
155
+
156
+ return (
157
+ <div className={cn("flex flex-col items-center gap-2", className)}>
158
+ <div className="flex flex-col items-center leading-none">
159
+ <span className={cn("text-3xl font-bold tabular-nums", lvrTextColor)}>
160
+ {clamped.toFixed(0)}%
161
+ </span>
162
+ <span className="mt-1 text-sm font-semibold uppercase tracking-widest text-muted-foreground">
163
+ LVR
164
+ </span>
165
+ </div>
166
+
167
+ {/* Debt-vs-equity bar */}
168
+ <div className="h-1.5 w-full overflow-hidden bg-muted" aria-hidden>
169
+ <div
170
+ className={cn("h-full transition-all", lvrBarColor)}
171
+ style={{ width: `${clamped}%` }}
172
+ />
173
+ </div>
174
+
175
+ {(debtAmount !== undefined || equityAmount !== undefined) && (
176
+ <div className="flex w-full items-center justify-between text-sm text-muted-foreground">
177
+ {debtAmount !== undefined && (
178
+ <span>Debt {formatCurrencyAbbrev(debtAmount, 1)}</span>
179
+ )}
180
+ {equityAmount !== undefined && (
181
+ <span>Equity {formatCurrencyAbbrev(equityAmount, 1)}</span>
182
+ )}
183
+ </div>
184
+ )}
185
+ </div>
186
+ );
187
+ }
188
+
189
+ // ─── AddScenarioButton ────────────────────────────────────────────────────────
190
+ /**
191
+ * A dashed-border CTA button for adding a new borrowing scenario.
192
+ * Renders as a full-width <button> with a label and Plus icon.
193
+ * Supports a disabled state that removes interactivity.
194
+ *
195
+ * Used on the Borrowing Capacity page to open the "add / compare scenario" flow.
196
+ */
197
+
198
+ export interface AddScenarioButtonProps {
199
+ /** Button label (default: "Compare Loan Options") */
200
+ title?: string;
201
+ /** Disables the button */
202
+ disabled?: boolean;
203
+ /** Click handler */
204
+ onClick?: () => void;
205
+ className?: string;
206
+ }
207
+
208
+ export function AddScenarioButton({
209
+ title = "Compare Loan Options",
210
+ disabled = false,
211
+ onClick,
212
+ className,
213
+ }: AddScenarioButtonProps) {
214
+ return (
215
+ <Button
216
+ variant="outline-secondary"
217
+ disabled={disabled}
218
+ onClick={onClick}
219
+ className={cn(
220
+ "w-full justify-between border-dashed text-base",
221
+ className,
222
+ )}
223
+ >
224
+ <span>{title}</span>
225
+ <Plus size={18} className="shrink-0" />
226
+ </Button>
227
+ );
228
+ }