@wealthx/shadcn 1.2.2 → 1.3.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 (229) hide show
  1. package/.turbo/turbo-build.log +200 -156
  2. package/CHANGELOG.md +22 -0
  3. package/dist/{chunk-4Y6R4WEC.mjs → chunk-2A5RRQGG.mjs} +9 -22
  4. package/dist/{chunk-TS2ZX2VS.mjs → chunk-2UM72RJ7.mjs} +11 -15
  5. package/dist/{chunk-A56YQQHG.mjs → chunk-3NCUZIFP.mjs} +2 -2
  6. package/dist/chunk-3OYFOX3X.mjs +79 -0
  7. package/dist/{chunk-RP3SQYA3.mjs → chunk-3TTACBDP.mjs} +9 -4
  8. package/dist/chunk-4GAWMKMI.mjs +710 -0
  9. package/dist/{chunk-VGSESELX.mjs → chunk-5FQIKDKP.mjs} +5 -5
  10. package/dist/{chunk-K3JYD4IU.mjs → chunk-5IS7G74I.mjs} +11 -4
  11. package/dist/chunk-6AW4KJHE.mjs +235 -0
  12. package/dist/chunk-6CR5N2JW.mjs +302 -0
  13. package/dist/{chunk-XIRTEFKH.mjs → chunk-6DZEXFNB.mjs} +36 -8
  14. package/dist/chunk-6O6KD7CE.mjs +271 -0
  15. package/dist/chunk-7PV3IWCN.mjs +33 -0
  16. package/dist/{chunk-SPJ5KXW7.mjs → chunk-7S5AESZO.mjs} +5 -5
  17. package/dist/{chunk-RYCLWMZ7.mjs → chunk-ABFDMHOR.mjs} +9 -7
  18. package/dist/{chunk-SWGT756Z.mjs → chunk-AMQZRHEZ.mjs} +10 -4
  19. package/dist/{chunk-WAZD7NFU.mjs → chunk-BKNFWEH2.mjs} +6 -6
  20. package/dist/{chunk-CLIN5525.mjs → chunk-C7CQJNMR.mjs} +1 -1
  21. package/dist/{chunk-D4ILTPOG.mjs → chunk-CFMQP5QS.mjs} +5 -4
  22. package/dist/{chunk-VPBN3WOO.mjs → chunk-DGHAXJBN.mjs} +9 -7
  23. package/dist/chunk-DOEO3CDL.mjs +27 -0
  24. package/dist/{chunk-5MEWU56Z.mjs → chunk-DUJTAXMH.mjs} +11 -6
  25. package/dist/{chunk-GGM2UYGG.mjs → chunk-EBXQWIYG.mjs} +10 -4
  26. package/dist/chunk-EWRB4PAD.mjs +468 -0
  27. package/dist/{chunk-ZSHYDDRB.mjs → chunk-FAKPBKLT.mjs} +6 -2
  28. package/dist/chunk-FNQXOAYJ.mjs +169 -0
  29. package/dist/{chunk-A6AAWBPF.mjs → chunk-GHC7LLUX.mjs} +13 -4
  30. package/dist/chunk-HBZLGDIN.mjs +507 -0
  31. package/dist/{chunk-SIZMLSRU.mjs → chunk-HISNT2MG.mjs} +8 -6
  32. package/dist/{chunk-CGH4DRNG.mjs → chunk-HVY6KCCF.mjs} +10 -7
  33. package/dist/chunk-I3RZS7V2.mjs +136 -0
  34. package/dist/chunk-IAE3F7DR.mjs +1962 -0
  35. package/dist/{chunk-UT4KJR7V.mjs → chunk-IHMFS7NZ.mjs} +35 -74
  36. package/dist/{chunk-PCPLO5HT.mjs → chunk-IOJRDS6V.mjs} +96 -14
  37. package/dist/{chunk-LHYCMLVA.mjs → chunk-JKGDCQTZ.mjs} +11 -4
  38. package/dist/{chunk-H45TKD34.mjs → chunk-JMHR3YGZ.mjs} +1 -1
  39. package/dist/{chunk-4MN6UQHG.mjs → chunk-K5A5L6T2.mjs} +17 -39
  40. package/dist/chunk-LV35NGVG.mjs +272 -0
  41. package/dist/{chunk-FZIXGLMV.mjs → chunk-M3FV7LOK.mjs} +5 -12
  42. package/dist/{chunk-FMAXJ2SI.mjs → chunk-MBON7YRJ.mjs} +1 -1
  43. package/dist/chunk-MIZQHHUO.mjs +441 -0
  44. package/dist/chunk-MN5NYQCL.mjs +29 -0
  45. package/dist/chunk-NL3ZO62D.mjs +31 -0
  46. package/dist/{chunk-Q76O3RIQ.mjs → chunk-NMOI6CQD.mjs} +1 -1
  47. package/dist/{chunk-P6AM5V7O.mjs → chunk-OODBHKG7.mjs} +1 -1
  48. package/dist/chunk-PBL4OQV2.mjs +283 -0
  49. package/dist/{chunk-Y4QFWRNR.mjs → chunk-PU4YZQXV.mjs} +17 -18
  50. package/dist/chunk-QMY3AZJH.mjs +80 -0
  51. package/dist/{chunk-BL3DXM2X.mjs → chunk-QZ4RE6NA.mjs} +11 -4
  52. package/dist/{chunk-VACKZOMY.mjs → chunk-R3VSPKNP.mjs} +3 -3
  53. package/dist/{chunk-OPNQAVVH.mjs → chunk-RJI6GKVF.mjs} +8 -6
  54. package/dist/{chunk-WG6JGJXB.mjs → chunk-T4BJLT57.mjs} +1 -1
  55. package/dist/chunk-UMTOX62O.mjs +415 -0
  56. package/dist/{chunk-7MMXNK3C.mjs → chunk-VLARHE5V.mjs} +8 -6
  57. package/dist/{chunk-2I5S2AMY.mjs → chunk-XREGSKX3.mjs} +2 -2
  58. package/dist/{chunk-JNQORUPP.mjs → chunk-YJG55G2H.mjs} +14 -11
  59. package/dist/{chunk-ZRSDX6OW.mjs → chunk-ZC45IGZO.mjs} +33 -30
  60. package/dist/components/ui/add-column-modal.js +42 -14
  61. package/dist/components/ui/add-column-modal.mjs +5 -5
  62. package/dist/components/ui/add-lead-modal.js +42 -11
  63. package/dist/components/ui/add-lead-modal.mjs +3 -3
  64. package/dist/components/ui/advisor-card.js +497 -0
  65. package/dist/components/ui/advisor-card.mjs +13 -0
  66. package/dist/components/ui/ai-assistant-drawer.js +11 -10
  67. package/dist/components/ui/ai-assistant-drawer.mjs +3 -3
  68. package/dist/components/ui/alert-dialog.js +2 -2
  69. package/dist/components/ui/alert-dialog.mjs +2 -2
  70. package/dist/components/ui/appointment-action-dialogs.js +1160 -0
  71. package/dist/components/ui/appointment-action-dialogs.mjs +23 -0
  72. package/dist/components/ui/appointment-availability-settings.js +1590 -0
  73. package/dist/components/ui/appointment-availability-settings.mjs +23 -0
  74. package/dist/components/ui/appointment-book-dialog.js +1744 -0
  75. package/dist/components/ui/appointment-book-dialog.mjs +27 -0
  76. package/dist/components/ui/appointment-calendar-view.js +833 -0
  77. package/dist/components/ui/appointment-calendar-view.mjs +14 -0
  78. package/dist/components/ui/appointment-detail-sheet.js +1517 -0
  79. package/dist/components/ui/appointment-detail-sheet.mjs +24 -0
  80. package/dist/components/ui/appointment-gmail-connect.js +467 -0
  81. package/dist/components/ui/appointment-gmail-connect.mjs +14 -0
  82. package/dist/components/ui/appointment-mini-card.js +345 -0
  83. package/dist/components/ui/appointment-mini-card.mjs +11 -0
  84. package/dist/components/ui/appointment-time-slot-picker.js +311 -0
  85. package/dist/components/ui/appointment-time-slot-picker.mjs +13 -0
  86. package/dist/components/ui/appointment-upcoming-card.js +1268 -0
  87. package/dist/components/ui/appointment-upcoming-card.mjs +21 -0
  88. package/dist/components/ui/backoffice-alert-history-chart.js +11 -5
  89. package/dist/components/ui/backoffice-alert-history-chart.mjs +5 -4
  90. package/dist/components/ui/backoffice-alerts-chart.js +786 -0
  91. package/dist/components/ui/backoffice-alerts-chart.mjs +19 -0
  92. package/dist/components/ui/backoffice-connections-chart.js +817 -0
  93. package/dist/components/ui/backoffice-connections-chart.mjs +19 -0
  94. package/dist/components/ui/backoffice-contact-history-chart.js +11 -5
  95. package/dist/components/ui/backoffice-contact-history-chart.mjs +5 -4
  96. package/dist/components/ui/badge.js +6 -6
  97. package/dist/components/ui/badge.mjs +1 -1
  98. package/dist/components/ui/borrowing-capacity-line-chart.js +30 -21
  99. package/dist/components/ui/borrowing-capacity-line-chart.mjs +5 -4
  100. package/dist/components/ui/button.js +2 -2
  101. package/dist/components/ui/button.mjs +1 -1
  102. package/dist/components/ui/calendar.js +2 -2
  103. package/dist/components/ui/calendar.mjs +2 -2
  104. package/dist/components/ui/card.js +1 -1
  105. package/dist/components/ui/card.mjs +1 -1
  106. package/dist/components/ui/cash-balance-line-chart.js +31 -23
  107. package/dist/components/ui/cash-balance-line-chart.mjs +5 -4
  108. package/dist/components/ui/cashflow-bar-chart.js +12 -5
  109. package/dist/components/ui/cashflow-bar-chart.mjs +5 -4
  110. package/dist/components/ui/chip.js +97 -18
  111. package/dist/components/ui/chip.mjs +3 -2
  112. package/dist/components/ui/color-picker.js +158 -28
  113. package/dist/components/ui/color-picker.mjs +3 -1
  114. package/dist/components/ui/data-table.js +140 -119
  115. package/dist/components/ui/data-table.mjs +3 -2
  116. package/dist/components/ui/date-picker.js +48 -27
  117. package/dist/components/ui/date-picker.mjs +4 -3
  118. package/dist/components/ui/dialog.js +37 -9
  119. package/dist/components/ui/dialog.mjs +2 -2
  120. package/dist/components/ui/expense-bar-chart.js +12 -5
  121. package/dist/components/ui/expense-bar-chart.mjs +5 -4
  122. package/dist/components/ui/field.mjs +2 -2
  123. package/dist/components/ui/financial-cards.js +322 -155
  124. package/dist/components/ui/financial-cards.mjs +5 -3
  125. package/dist/components/ui/financial-drawers.js +2 -2
  126. package/dist/components/ui/financial-drawers.mjs +3 -3
  127. package/dist/components/ui/financial-sections.js +14 -10
  128. package/dist/components/ui/financial-sections.mjs +6 -5
  129. package/dist/components/ui/income-bar-chart.js +12 -5
  130. package/dist/components/ui/income-bar-chart.mjs +5 -4
  131. package/dist/components/ui/input-group.js +2 -2
  132. package/dist/components/ui/input-group.mjs +2 -2
  133. package/dist/components/ui/kanban-column.js +52 -44
  134. package/dist/components/ui/kanban-column.mjs +7 -5
  135. package/dist/components/ui/opportunity-card.js +52 -44
  136. package/dist/components/ui/opportunity-card.mjs +6 -4
  137. package/dist/components/ui/opportunity-edit-modals.js +1367 -1263
  138. package/dist/components/ui/opportunity-edit-modals.mjs +8 -8
  139. package/dist/components/ui/opportunity-summary-tab.js +2744 -2157
  140. package/dist/components/ui/opportunity-summary-tab.mjs +14 -14
  141. package/dist/components/ui/page-header.js +92 -0
  142. package/dist/components/ui/page-header.mjs +8 -0
  143. package/dist/components/ui/page-top-bar.js +88 -0
  144. package/dist/components/ui/page-top-bar.mjs +8 -0
  145. package/dist/components/ui/pagination.js +303 -19
  146. package/dist/components/ui/pagination.mjs +11 -4
  147. package/dist/components/ui/pipeline-board.js +205 -191
  148. package/dist/components/ui/pipeline-board.mjs +9 -7
  149. package/dist/components/ui/pipeline-dialogs.js +114 -65
  150. package/dist/components/ui/pipeline-dialogs.mjs +7 -6
  151. package/dist/components/ui/pipeline-primitives.js +6 -6
  152. package/dist/components/ui/pipeline-primitives.mjs +2 -2
  153. package/dist/components/ui/property-cashflow-doughnut-chart.js +14 -12
  154. package/dist/components/ui/property-cashflow-doughnut-chart.mjs +5 -4
  155. package/dist/components/ui/property-debt-equity-doughnut-chart.js +14 -12
  156. package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +5 -4
  157. package/dist/components/ui/property-mobile-estimate-line-chart.js +16 -14
  158. package/dist/components/ui/property-mobile-estimate-line-chart.mjs +5 -4
  159. package/dist/components/ui/sidebar-nav.js +234 -95
  160. package/dist/components/ui/sidebar-nav.mjs +4 -1
  161. package/dist/components/ui/stage-timeline.js +6 -6
  162. package/dist/components/ui/stage-timeline.mjs +3 -3
  163. package/dist/components/ui/transactions-expense-categories-doughnut-chart.js +18 -16
  164. package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +5 -4
  165. package/dist/components/ui/transactions-income-expense-bar-chart.js +28 -12
  166. package/dist/components/ui/transactions-income-expense-bar-chart.mjs +5 -4
  167. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.js +18 -16
  168. package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +5 -4
  169. package/dist/index.js +12899 -9343
  170. package/dist/index.mjs +256 -190
  171. package/dist/styles.css +1 -1
  172. package/package.json +71 -1
  173. package/src/components/index.tsx +114 -9
  174. package/src/components/ui/add-column-modal.tsx +7 -7
  175. package/src/components/ui/add-lead-modal.tsx +6 -3
  176. package/src/components/ui/advisor-card.tsx +227 -0
  177. package/src/components/ui/ai-assistant-drawer.tsx +4 -3
  178. package/src/components/ui/appointment-action-dialogs.tsx +297 -0
  179. package/src/components/ui/appointment-availability-settings.tsx +645 -0
  180. package/src/components/ui/appointment-book-dialog.tsx +618 -0
  181. package/src/components/ui/appointment-calendar-view.tsx +510 -0
  182. package/src/components/ui/appointment-detail-sheet.tsx +415 -0
  183. package/src/components/ui/appointment-gmail-connect.tsx +188 -0
  184. package/src/components/ui/appointment-mini-card.tsx +104 -0
  185. package/src/components/ui/appointment-time-slot-picker.tsx +123 -0
  186. package/src/components/ui/appointment-upcoming-card.tsx +635 -0
  187. package/src/components/ui/backoffice-alert-history-chart.tsx +10 -2
  188. package/src/components/ui/backoffice-alerts-chart.tsx +312 -0
  189. package/src/components/ui/backoffice-connections-chart.tsx +339 -0
  190. package/src/components/ui/backoffice-contact-history-chart.tsx +10 -2
  191. package/src/components/ui/badge.tsx +12 -6
  192. package/src/components/ui/borrowing-capacity-line-chart.tsx +4 -11
  193. package/src/components/ui/button.tsx +2 -2
  194. package/src/components/ui/card.tsx +1 -1
  195. package/src/components/ui/cash-balance-line-chart.tsx +4 -23
  196. package/src/components/ui/cashflow-bar-chart.tsx +9 -2
  197. package/src/components/ui/chart-shared.tsx +4 -11
  198. package/src/components/ui/chip.tsx +23 -19
  199. package/src/components/ui/color-picker.tsx +4 -2
  200. package/src/components/ui/data-table.tsx +28 -74
  201. package/src/components/ui/date-picker.tsx +42 -37
  202. package/src/components/ui/dialog.tsx +72 -6
  203. package/src/components/ui/expense-bar-chart.tsx +11 -2
  204. package/src/components/ui/financial-cards.tsx +99 -10
  205. package/src/components/ui/income-bar-chart.tsx +11 -2
  206. package/src/components/ui/opportunity-card.tsx +10 -39
  207. package/src/components/ui/opportunity-edit-modals.tsx +98 -36
  208. package/src/components/ui/opportunity-summary-tab.tsx +548 -232
  209. package/src/components/ui/page-header.tsx +57 -0
  210. package/src/components/ui/page-top-bar.tsx +48 -0
  211. package/src/components/ui/pagination.tsx +171 -22
  212. package/src/components/ui/pipeline-board.tsx +12 -5
  213. package/src/components/ui/property-cashflow-doughnut-chart.tsx +3 -1
  214. package/src/components/ui/property-debt-equity-doughnut-chart.tsx +3 -1
  215. package/src/components/ui/property-mobile-estimate-line-chart.tsx +3 -1
  216. package/src/components/ui/sidebar-nav.tsx +36 -37
  217. package/src/components/ui/transactions-expense-categories-doughnut-chart.tsx +3 -1
  218. package/src/components/ui/transactions-income-expense-bar-chart.tsx +12 -9
  219. package/src/components/ui/transactions-liabilities-breakdown-doughnut-chart.tsx +3 -1
  220. package/src/lib/format-currency.ts +44 -0
  221. package/src/lib/format-date.ts +50 -0
  222. package/src/lib/opportunity-constants.ts +12 -0
  223. package/src/styles/globals.css +17 -15
  224. package/src/styles/styles-css.ts +1 -1
  225. package/tsup.config.ts +14 -0
  226. package/dist/chunk-S4QRUQNW.mjs +0 -475
  227. package/dist/chunk-URGMJAE3.mjs +0 -1885
  228. package/dist/chunk-WNGWBVLV.mjs +0 -148
  229. package/dist/{chunk-LLVQKSU3.mjs → chunk-GD4BJDJR.mjs} +3 -3
@@ -16,13 +16,20 @@ import { Card, CardContent, CardHeader, CardTitle } from "./card";
16
16
  import { Empty, EmptyDescription } from "./empty";
17
17
  import { Spinner } from "./spinner";
18
18
  import { cn } from "@/lib/utils";
19
+ import { formatCurrency } from "@/lib/format-currency";
19
20
  import {
20
21
  FALLBACK_TICK,
21
22
  FALLBACK_PRIMARY,
22
23
  FALLBACK_SECONDARY,
23
24
  } from "./chart-shared";
24
25
 
25
- ChartJS.register(CategoryScale, LinearScale, BarController, BarElement, Tooltip);
26
+ ChartJS.register(
27
+ CategoryScale,
28
+ LinearScale,
29
+ BarController,
30
+ BarElement,
31
+ Tooltip,
32
+ );
26
33
 
27
34
  // ---------------------------------------------------------------------------
28
35
  // Constants
@@ -32,12 +39,6 @@ ChartJS.register(CategoryScale, LinearScale, BarController, BarElement, Tooltip)
32
39
  // Helpers
33
40
  // ---------------------------------------------------------------------------
34
41
 
35
- function formatDollar(value: number): string {
36
- return `$${value.toLocaleString(undefined, {
37
- minimumFractionDigits: 2,
38
- maximumFractionDigits: 2,
39
- })}`;
40
- }
41
42
 
42
43
  // ---------------------------------------------------------------------------
43
44
  // Types
@@ -110,7 +111,7 @@ export function TransactionsIncomeExpenseBarChart({
110
111
  color: FALLBACK_SECONDARY,
111
112
  textAlign: "left",
112
113
  // Returns array for multi-line: dollar value on line 1, blank on line 2
113
- formatter: (v: number) => [formatDollar(v), ""],
114
+ formatter: (v: number) => [formatCurrency(v, { decimals: 2 }), ""],
114
115
  },
115
116
  name: {
116
117
  anchor: "end",
@@ -173,7 +174,9 @@ export function TransactionsIncomeExpenseBarChart({
173
174
  style={{ maxWidth: width, fontFamily }}
174
175
  >
175
176
  <CardHeader className="px-3 sm:px-6">
176
- <CardTitle className="text-sm sm:text-base">{title}</CardTitle>
177
+ <CardTitle className="text-xs font-semibold uppercase tracking-wide">
178
+ {title}
179
+ </CardTitle>
177
180
  </CardHeader>
178
181
 
179
182
  <CardContent className="px-3 sm:px-6">
@@ -129,7 +129,9 @@ export function TransactionsLiabilitiesBreakdownChart({
129
129
  style={{ maxWidth: width, fontFamily }}
130
130
  >
131
131
  <CardHeader className="px-3 sm:px-6">
132
- <CardTitle className="text-sm sm:text-base">{title}</CardTitle>
132
+ <CardTitle className="text-xs font-semibold uppercase tracking-wide">
133
+ {title}
134
+ </CardTitle>
133
135
  </CardHeader>
134
136
 
135
137
  <CardContent className="px-3 sm:px-6">
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Currency formatting utilities for the WealthX design system.
3
+ * All formatters default to AUD (en-AU locale).
4
+ */
5
+
6
+ /**
7
+ * Format a number as AUD currency using Intl.NumberFormat.
8
+ *
9
+ * @param value The numeric value to format.
10
+ * @param options Optional formatting overrides.
11
+ * @param options.decimals Decimal places (default: 0).
12
+ * @param options.showSign Prefix with +/− for positive/negative (default: false).
13
+ */
14
+ export function formatCurrency(
15
+ value: number,
16
+ options?: { decimals?: number; showSign?: boolean },
17
+ ): string {
18
+ const { decimals = 0, showSign = false } = options ?? {};
19
+ const abs = Math.abs(value);
20
+ const formatted = new Intl.NumberFormat("en-AU", {
21
+ style: "currency",
22
+ currency: "AUD",
23
+ minimumFractionDigits: decimals,
24
+ maximumFractionDigits: decimals,
25
+ }).format(abs);
26
+ if (!showSign) return value < 0 ? `-${formatted}` : formatted;
27
+ if (value > 0) return `+${formatted}`;
28
+ if (value < 0) return `-${formatted}`;
29
+ return formatted;
30
+ }
31
+
32
+ /**
33
+ * Abbreviated currency: $1.2B, $3.5M, $580K, $42.
34
+ * Used primarily for chart axis ticks.
35
+ */
36
+ export function formatCurrencyAbbrev(value: number): string {
37
+ const abs = Math.abs(value);
38
+ const sign = value < 0 ? "-" : "";
39
+ if (abs >= 1_000_000_000)
40
+ return `${sign}$${(abs / 1_000_000_000).toFixed(1)}B`;
41
+ if (abs >= 1_000_000) return `${sign}$${(abs / 1_000_000).toFixed(1)}M`;
42
+ if (abs >= 1_000) return `${sign}$${(abs / 1_000).toFixed(0)}K`;
43
+ return `${sign}$${abs.toFixed(0)}`;
44
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Date formatting utilities for the WealthX design system.
3
+ * Uses date-fns for consistent, locale-independent formatting.
4
+ */
5
+ import { format, parseISO } from "date-fns";
6
+
7
+ /**
8
+ * Parse an ISO date string safely, handling both full ISO and date-only strings.
9
+ * Date-only strings ("2026-01-15") are parsed via parseISO to avoid timezone shifts.
10
+ */
11
+ function safeParse(iso: string): Date {
12
+ return parseISO(iso);
13
+ }
14
+
15
+ /**
16
+ * Format an ISO date string as "15 Jan 2026".
17
+ * Returns "—" for falsy input, raw string on parse failure.
18
+ */
19
+ export function formatDateShort(iso?: string): string {
20
+ if (!iso) return "—";
21
+ try {
22
+ return format(safeParse(iso), "dd MMM yyyy");
23
+ } catch {
24
+ return iso;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Format an ISO date string as "15 Jan" (day + month only).
30
+ * Returns raw string on parse failure.
31
+ */
32
+ export function formatDateDayMonth(iso: string): string {
33
+ try {
34
+ return format(safeParse(iso), "dd MMM");
35
+ } catch {
36
+ return iso;
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Format an ISO date string with weekday: "Wed, 15 Jan 2026".
42
+ * Returns raw string on parse failure.
43
+ */
44
+ export function formatDateWithWeekday(iso: string): string {
45
+ try {
46
+ return format(safeParse(iso), "EEE, dd MMM yyyy");
47
+ } catch {
48
+ return iso;
49
+ }
50
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Shared constants for the opportunity / loan pipeline domain.
3
+ */
4
+
5
+ /** Asset types that represent real property (map to PropertyCard). */
6
+ export const PROPERTY_ASSET_TYPES = new Set([
7
+ "Primary Residence",
8
+ "Investment Property",
9
+ "Holiday Home",
10
+ "Commercial Property",
11
+ "Rural Property",
12
+ ]);
@@ -11,7 +11,7 @@
11
11
  * (e.g. when packages/shadcn is outside the Vite root apps/docs).
12
12
  * These cover all state-dependent classes used in Checkbox, Button, etc.
13
13
  */
14
- @source inline("h-2 h-10 h-12 h-16 h-20 h-24 h-28 h-32 h-36 h-40 h-44 h-48 size-10 size-12 size-14 size-16 rounded-full w-4/5 shrink-0 bg-muted transition-all flex-wrap gap-x-4 gap-y-1.5 mt-3");
14
+ @source inline("h-2 h-10 h-12 h-16 h-20 h-24 h-28 h-32 h-36 h-40 h-44 h-48 size-10 size-12 size-14 size-16 rounded-full w-4/5 shrink-0 bg-muted transition-all flex-wrap gap-x-4 gap-y-1.5 mt-3 text-success-text text-warning-text text-destructive-text text-info-text");
15
15
 
16
16
  @source inline("has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 border-border border-destructive/40 bg-destructive/10 border-warning/40 bg-warning/10 text-warning border-success/40 bg-success/10 text-success border-info/40 bg-info/10 text-info *:data-[slot=alert-description]:text-warning/90 *:data-[slot=alert-description]:text-success/90 *:data-[slot=alert-description]:text-info/90 *:data-[slot=alert-description]:text-destructive/90 [&>svg]:text-destructive [&>svg]:text-warning [&>svg]:text-success [&>svg]:text-info");
17
17
 
@@ -19,7 +19,7 @@
19
19
 
20
20
  /* Toggle / ToggleGroup pressed-state safelist — data-pressed is set by @base-ui/react/toggle */
21
21
  @source inline("data-pressed:bg-primary/10 data-pressed:inset-ring data-pressed:inset-ring-primary data-pressed:text-foreground data-pressed:hover:bg-primary/10 data-pressed:hover:text-foreground");
22
- @source inline("bg-foreground/50 hover:bg-foreground/5 focus:ring-border focus:ring-2 focus:ring-offset-0 fixed inset-0 translate-x-[-50%] translate-y-[-50%] max-w-[calc(100%-2rem)] sm:max-w-lg border-t pt-4 justify-end gap-1.5");
22
+ @source inline("bg-foreground/50 hover:bg-foreground/5 focus:ring-border focus:ring-2 focus:ring-offset-0 fixed inset-0 translate-x-[-50%] translate-y-[-50%] max-w-[calc(100%-2rem)] sm:max-w-sm sm:max-w-md sm:max-w-lg sm:max-w-xl sm:max-w-2xl sm:max-w-3xl sm:max-w-4xl sm:max-w-full border-t pt-4 justify-end gap-1.5 aria-expanded:border-ring aria-expanded:ring-2 aria-expanded:ring-ring/20");
23
23
 
24
24
  @source inline("data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20");
25
25
 
@@ -462,7 +462,9 @@
462
462
  --accent-foreground: oklch(0.152 0.02 235); /* #040D13 */
463
463
 
464
464
  /* Destructive — error state */
465
- --destructive: oklch(0.643 0.215 28.8); /* #F44336 — palette/error/main */
465
+ --destructive: oklch(
466
+ 0.48 0.215 28
467
+ ); /* #C62828 — darkened for 4.5:1 with white */
466
468
  --destructive-foreground: oklch(1 0 0); /* #FFFFFF — light text on red */
467
469
 
468
470
  /* Borders */
@@ -472,25 +474,25 @@
472
474
  0.894 0.208 163
473
475
  ); /* #33FF99 — primary (focus ring uses brand color) */
474
476
 
475
- /* WealthX custom: state colors */
476
- --warning: oklch(0.77 0.174 64.1); /* #FF9800 palette/warning/main */
477
+ /* WealthX custom: state colors
478
+ * Base colors are darkened to achieve ≥4.5:1 contrast with white foreground.
479
+ * *-text tokens are for colored text on light/white surfaces (not affected). */
480
+ --warning: oklch(0.565 0.18 67); /* #B45309 — darkened for 4.5:1 with white */
477
481
  --warning-foreground: oklch(1 0 0); /* #FFFFFF */
478
482
  --warning-text: oklch(
479
483
  0.44 0.14 58
480
- ); /* ~#7A5200 — darkened for text on light bg (4.5:1 on white) */
481
- --success: oklch(0.673 0.162 144.2); /* #4CAF50 — palette/success/main */
484
+ ); /* ~#7A5200 — colored text on light bg (4.5:1 on white) */
485
+ --success: oklch(
486
+ 0.485 0.145 145
487
+ ); /* #2E7D32 — darkened for 4.5:1 with white */
482
488
  --success-foreground: oklch(1 0 0); /* #FFFFFF */
483
- --success-text: oklch(
484
- 0.4 0.12 145
485
- ); /* ~#1B5E20 — darkened for text on light bg */
486
- --info: oklch(0.658 0.169 248.8); /* #2196F3 — palette/info/main */
489
+ --success-text: oklch(0.4 0.12 145); /* ~#1B5E20 — colored text on light bg */
490
+ --info: oklch(0.465 0.19 252); /* #1565C0 — darkened for 4.5:1 with white */
487
491
  --info-foreground: oklch(1 0 0); /* #FFFFFF */
488
- --info-text: oklch(
489
- 0.4 0.13 250
490
- ); /* ~#0D47A1 — darkened for text on light bg */
492
+ --info-text: oklch(0.4 0.13 250); /* ~#0D47A1 — colored text on light bg */
491
493
  --destructive-text: oklch(
492
494
  0.44 0.2 28.8
493
- ); /* ~#8B0000 — darkened for text on light bg */
495
+ ); /* ~#8B0000 — colored text on light bg */
494
496
 
495
497
  /* Chart series — WealthX Charts collection */
496
498
  --chart-1: oklch(0.59 0.217 261.8); /* #2B72FB — series/blue */