@wealthx/shadcn 1.5.6 → 1.5.8
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.
- package/.turbo/turbo-build.log +177 -171
- package/CHANGELOG.md +12 -0
- package/dist/{chunk-XHGISOX5.mjs → chunk-33VT74R4.mjs} +1 -1
- package/dist/{chunk-M4LTX3MH.mjs → chunk-3C4DZTGA.mjs} +1 -1
- package/dist/{chunk-ODO6BUOF.mjs → chunk-3CGM3QXQ.mjs} +3 -5
- package/dist/{chunk-QBPNYXTI.mjs → chunk-3NJPNSJG.mjs} +1 -1
- package/dist/{chunk-6SR4K5T5.mjs → chunk-3S6KVFF5.mjs} +1 -1
- package/dist/{chunk-7KT5HPYM.mjs → chunk-3VZ6CYY2.mjs} +1 -1
- package/dist/chunk-3Z75IKFO.mjs +34 -0
- package/dist/{chunk-DFL5CV75.mjs → chunk-4BHDDLWK.mjs} +2 -2
- package/dist/{chunk-KLJLDNCA.mjs → chunk-4LLTZ45R.mjs} +1 -1
- package/dist/{chunk-RAKBWNQH.mjs → chunk-54MTIKNC.mjs} +27 -66
- package/dist/{chunk-JTG5R5YV.mjs → chunk-54TRNCID.mjs} +287 -61
- package/dist/{chunk-KCKYGQVQ.mjs → chunk-5DAQU3B6.mjs} +1 -1
- package/dist/{chunk-CKPEFZNH.mjs → chunk-5LZZYODG.mjs} +2 -2
- package/dist/{chunk-2A53WPEC.mjs → chunk-5YVJSKFH.mjs} +2 -2
- package/dist/{chunk-JUBUN65Q.mjs → chunk-5YWUGE6F.mjs} +1 -1
- package/dist/chunk-65PZNG4Y.mjs +129 -0
- package/dist/{chunk-K7WSRWOU.mjs → chunk-6LWCFAB4.mjs} +1 -1
- package/dist/{chunk-Q5SGEIJV.mjs → chunk-6MDNL5I2.mjs} +3 -3
- package/dist/{chunk-AUEUTZIC.mjs → chunk-6U4NQGVM.mjs} +3 -3
- package/dist/{chunk-V4CUTCHS.mjs → chunk-77L3UPBW.mjs} +1 -1
- package/dist/{chunk-CW32WTZU.mjs → chunk-7UIL5UN3.mjs} +1 -1
- package/dist/{chunk-2LLFNGJZ.mjs → chunk-AANINK2B.mjs} +3 -3
- package/dist/{chunk-UEREFDAE.mjs → chunk-AZGLSIHF.mjs} +1 -1
- package/dist/{chunk-XN37434W.mjs → chunk-B3CTBLIY.mjs} +2 -2
- package/dist/{chunk-XTWAJWCQ.mjs → chunk-BAONSY54.mjs} +1 -1
- package/dist/{chunk-XIY5DJXI.mjs → chunk-BXL74CM2.mjs} +1 -1
- package/dist/{chunk-OYBIUEGE.mjs → chunk-BZGFW6L7.mjs} +1 -1
- package/dist/chunk-CEEVYRQA.mjs +61 -0
- package/dist/{chunk-BD3DWDT4.mjs → chunk-CEYEK3TI.mjs} +1 -1
- package/dist/{chunk-I3UDLWQ7.mjs → chunk-D3HKFRQO.mjs} +1 -1
- package/dist/{chunk-3AREQTZU.mjs → chunk-DCKT635J.mjs} +1 -1
- package/dist/{chunk-VLELWBEW.mjs → chunk-E2BNCA6L.mjs} +1 -1
- package/dist/{chunk-QRVEI6J3.mjs → chunk-E5EDZQ5J.mjs} +1 -3
- package/dist/{chunk-QHJDGB54.mjs → chunk-EAKRTKHJ.mjs} +2 -2
- package/dist/{chunk-Q35PNFJ7.mjs → chunk-FBNEIYSE.mjs} +1 -1
- package/dist/{chunk-KB7MZMED.mjs → chunk-FGMDBJCF.mjs} +1 -1
- package/dist/{chunk-S4CTM3UE.mjs → chunk-FRCTOAKZ.mjs} +35 -4
- package/dist/{chunk-K7TWMLLW.mjs → chunk-FW4U543X.mjs} +4 -4
- package/dist/{chunk-PGR53HMH.mjs → chunk-G2W754UJ.mjs} +1 -1
- package/dist/{chunk-46Q4335I.mjs → chunk-GS47ZSSA.mjs} +12 -22
- package/dist/{chunk-AHKHVBWR.mjs → chunk-GYWOD2YI.mjs} +1 -1
- package/dist/{chunk-HNDTLT5X.mjs → chunk-H5DTKPJ2.mjs} +1 -1
- package/dist/{chunk-C6SWS7OW.mjs → chunk-HB5BKRMH.mjs} +1 -1
- package/dist/{chunk-WUA546RX.mjs → chunk-IFSQWDRN.mjs} +1 -1
- package/dist/{chunk-KAD26MCC.mjs → chunk-IRZWYTGV.mjs} +1 -1
- package/dist/{chunk-AL6GOL2Y.mjs → chunk-IW33VLL5.mjs} +1 -1
- package/dist/{chunk-A6ER36CW.mjs → chunk-JGBV3XMQ.mjs} +1 -1
- package/dist/{chunk-Y6UM3VTN.mjs → chunk-JUMEIPII.mjs} +1 -1
- package/dist/{chunk-VFH632TB.mjs → chunk-K4WDPVFY.mjs} +3 -3
- package/dist/{chunk-PV3Y7QGK.mjs → chunk-LHWJQNLG.mjs} +3 -3
- package/dist/{chunk-NCUH54IZ.mjs → chunk-LI2CTS5O.mjs} +1 -1
- package/dist/{chunk-F24U4QQQ.mjs → chunk-LPVXO3TD.mjs} +1 -1
- package/dist/{chunk-VJ3GC7W3.mjs → chunk-MNMSHB2J.mjs} +5 -5
- package/dist/{chunk-J5NW5NCT.mjs → chunk-NCMV3LTP.mjs} +1 -1
- package/dist/{chunk-IXR4BQSQ.mjs → chunk-O5CP6VP6.mjs} +3 -3
- package/dist/{chunk-TGVXRD53.mjs → chunk-OZ2R6ERP.mjs} +1 -1
- package/dist/{chunk-D447W45Z.mjs → chunk-PCULNQWA.mjs} +42 -50
- package/dist/{chunk-CDVG7SFT.mjs → chunk-PGJRZHN7.mjs} +1 -1
- package/dist/{chunk-IKDTOCSY.mjs → chunk-RSEVIQEO.mjs} +1 -1
- package/dist/{chunk-GNER6MCO.mjs → chunk-SSUK6C2K.mjs} +1 -1
- package/dist/{chunk-6TX73WG7.mjs → chunk-TCE5L44O.mjs} +3 -2
- package/dist/{chunk-OECGKCVF.mjs → chunk-TLLD5IU6.mjs} +1 -1
- package/dist/{chunk-BFB3UH7V.mjs → chunk-TRM3KIHT.mjs} +2 -2
- package/dist/{chunk-TLYSVRSK.mjs → chunk-TUC2BNUR.mjs} +3 -3
- package/dist/{chunk-HXU5JGLQ.mjs → chunk-UBHBIWIA.mjs} +3 -3
- package/dist/{chunk-TXUBGKB7.mjs → chunk-UJMVXREM.mjs} +2 -2
- package/dist/{chunk-TAX3KL66.mjs → chunk-USOVLDGS.mjs} +1 -1
- package/dist/{chunk-HF4FUBCY.mjs → chunk-UTCW5YUX.mjs} +1 -1
- package/dist/{chunk-OL65UQHQ.mjs → chunk-UYRHYJPX.mjs} +27 -61
- package/dist/{chunk-BDESHD25.mjs → chunk-VLVEZHFE.mjs} +1 -1
- package/dist/{chunk-EUYPMDQG.mjs → chunk-VWZS32ZQ.mjs} +1 -1
- package/dist/{chunk-HROG643K.mjs → chunk-W5QJ57PU.mjs} +1 -1
- package/dist/{chunk-F4O2YPXJ.mjs → chunk-WHIW6KOB.mjs} +1 -1
- package/dist/{chunk-TOIVHWNC.mjs → chunk-WWIWRNBK.mjs} +1 -1
- package/dist/{chunk-2QNOPXMQ.mjs → chunk-XMP24PWA.mjs} +1 -1
- package/dist/{chunk-HO6S3ECM.mjs → chunk-XUCDPAVI.mjs} +2 -2
- package/dist/{chunk-EW72FINW.mjs → chunk-XVZGXPIX.mjs} +1 -1
- package/dist/{chunk-WDTXHLYM.mjs → chunk-XYSRRDBH.mjs} +17 -11
- package/dist/{chunk-QAX6HCUH.mjs → chunk-ZAXZBOWI.mjs} +1 -1
- package/dist/{chunk-E3PQDBYI.mjs → chunk-ZFKAYRFQ.mjs} +1 -1
- package/dist/components/ui/about-you-form.mjs +6 -6
- package/dist/components/ui/add-column-modal.js +56 -227
- package/dist/components/ui/add-column-modal.mjs +4 -5
- package/dist/components/ui/add-lead-modal.mjs +6 -6
- package/dist/components/ui/ai-assistant-drawer.mjs +4 -4
- package/dist/components/ui/ai-builder.mjs +4 -4
- package/dist/components/ui/ai-conversations.js +278 -58
- package/dist/components/ui/ai-conversations.mjs +6 -6
- package/dist/components/ui/alert-dialog.mjs +3 -3
- package/dist/components/ui/appointment-action-dialogs.mjs +7 -7
- package/dist/components/ui/appointment-availability-settings.js +1 -1
- package/dist/components/ui/appointment-availability-settings.mjs +9 -9
- package/dist/components/ui/appointment-book-dialog.js +11 -21
- package/dist/components/ui/appointment-book-dialog.mjs +7 -7
- package/dist/components/ui/appointment-calendar-view.mjs +2 -2
- package/dist/components/ui/appointment-detail-sheet.mjs +9 -9
- package/dist/components/ui/appointment-upcoming-card.mjs +6 -6
- package/dist/components/ui/assets-liabilities-side-card.mjs +3 -3
- package/dist/components/ui/backoffice-alert-history-chart.mjs +3 -3
- package/dist/components/ui/backoffice-alert-matching-chart.mjs +3 -3
- package/dist/components/ui/backoffice-alerts-chart.mjs +3 -3
- package/dist/components/ui/backoffice-connections-chart.mjs +3 -3
- package/dist/components/ui/backoffice-contact-history-chart.mjs +3 -3
- package/dist/components/ui/backoffice-contact-matching-chart.mjs +3 -3
- package/dist/components/ui/backoffice-signup-steps.mjs +9 -9
- package/dist/components/ui/bank-statement-generate-dialog.mjs +9 -9
- package/dist/components/ui/bank-statement-pdf-viewer.mjs +4 -4
- package/dist/components/ui/borrowing-capacity-card.mjs +3 -3
- package/dist/components/ui/borrowing-capacity-line-chart.mjs +3 -3
- package/dist/components/ui/calculator-section.mjs +4 -4
- package/dist/components/ui/calendar.mjs +2 -2
- package/dist/components/ui/cash-balance-line-chart.mjs +3 -3
- package/dist/components/ui/cashflow-bar-chart.mjs +3 -3
- package/dist/components/ui/category-edit-dialog.mjs +4 -4
- package/dist/components/ui/color-picker.mjs +4 -4
- package/dist/components/ui/contact-alert-dialog/index.mjs +5 -5
- package/dist/components/ui/create-contact-modal.mjs +5 -5
- package/dist/components/ui/csv-import-modal.mjs +4 -4
- package/dist/components/ui/dashboard-transactions-table.mjs +5 -5
- package/dist/components/ui/data-table.mjs +6 -6
- package/dist/components/ui/date-picker.mjs +6 -6
- package/dist/components/ui/delete-contact-component.mjs +4 -4
- package/dist/components/ui/dialog.mjs +3 -3
- package/dist/components/ui/document-checklist-template.mjs +4 -4
- package/dist/components/ui/drawer.mjs +3 -3
- package/dist/components/ui/dropdown-menu.mjs +3 -3
- package/dist/components/ui/dynamic-tabs.mjs +3 -3
- package/dist/components/ui/editable-money-item.mjs +4 -4
- package/dist/components/ui/expense-bar-chart.mjs +3 -3
- package/dist/components/ui/expense-work-details.mjs +4 -4
- package/dist/components/ui/file-preview-dialog.mjs +6 -6
- package/dist/components/ui/financial-cards.mjs +2 -2
- package/dist/components/ui/financial-drawers.mjs +4 -4
- package/dist/components/ui/financial-sections.mjs +3 -3
- package/dist/components/ui/frontend-signup-steps.mjs +7 -7
- package/dist/components/ui/income-bar-chart.mjs +3 -3
- package/dist/components/ui/income-work-details.mjs +4 -4
- package/dist/components/ui/integration-card.js +326 -0
- package/dist/components/ui/integration-card.mjs +11 -0
- package/dist/components/ui/kanban-column.js +151 -243
- package/dist/components/ui/kanban-column.mjs +6 -7
- package/dist/components/ui/loan-application-cards.mjs +1 -1
- package/dist/components/ui/money-item-with-color-indicator.mjs +4 -4
- package/dist/components/ui/onboarding-layout.js +65 -4
- package/dist/components/ui/onboarding-layout.mjs +6 -4
- package/dist/components/ui/opportunity-card.js +126 -216
- package/dist/components/ui/opportunity-card.mjs +5 -6
- package/dist/components/ui/opportunity-edit-modals.mjs +9 -9
- package/dist/components/ui/opportunity-summary-tab.mjs +11 -11
- package/dist/components/ui/pagination.mjs +4 -4
- package/dist/components/ui/password-strength-tooltip.mjs +4 -4
- package/dist/components/ui/pipeline-board.js +167 -261
- package/dist/components/ui/pipeline-board.mjs +7 -8
- package/dist/components/ui/pipeline-chart.js +128 -55
- package/dist/components/ui/pipeline-chart.mjs +4 -3
- package/dist/components/ui/pipeline-dialogs.mjs +9 -9
- package/dist/components/ui/popover.mjs +3 -3
- package/dist/components/ui/property-cashflow-doughnut-chart.mjs +3 -3
- package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +3 -3
- package/dist/components/ui/property-mobile-estimate-line-chart.mjs +3 -3
- package/dist/components/ui/property-report-dialog.mjs +4 -4
- package/dist/components/ui/resource-center.mjs +4 -4
- package/dist/components/ui/review-alerts-dialog.mjs +4 -4
- package/dist/components/ui/savings-goal-modal.mjs +7 -7
- package/dist/components/ui/scenario-drawer.mjs +3 -3
- package/dist/components/ui/scenario-item.mjs +4 -4
- package/dist/components/ui/scenario-list.mjs +4 -4
- package/dist/components/ui/select.mjs +3 -3
- package/dist/components/ui/selectable-card.js +163 -0
- package/dist/components/ui/selectable-card.mjs +9 -0
- package/dist/components/ui/share-details-dialog.mjs +4 -4
- package/dist/components/ui/sheet.mjs +3 -3
- package/dist/components/ui/sidebar-nav.mjs +4 -4
- package/dist/components/ui/signup-form-primitives.mjs +6 -6
- package/dist/components/ui/signup-shell.js +3 -2
- package/dist/components/ui/signup-shell.mjs +2 -2
- package/dist/components/ui/stepper.js +3 -2
- package/dist/components/ui/stepper.mjs +1 -1
- package/dist/components/ui/tooltip.mjs +3 -3
- package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +3 -3
- package/dist/components/ui/transactions-income-expense-bar-chart.mjs +3 -3
- package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +3 -3
- package/dist/index.js +2144 -1875
- package/dist/index.mjs +105 -95
- package/dist/lib/colors.js +36 -3
- package/dist/lib/colors.mjs +5 -1
- package/dist/lib/theme-provider.js +60 -13
- package/dist/lib/theme-provider.mjs +2 -2
- package/dist/styles.css +1 -1
- package/package.json +11 -1
- package/src/components/index.tsx +13 -1
- package/src/components/ui/add-column-modal.tsx +9 -58
- package/src/components/ui/ai-conversations.tsx +308 -42
- package/src/components/ui/appointment-availability-settings.tsx +1 -1
- package/src/components/ui/appointment-book-dialog.tsx +25 -48
- package/src/components/ui/integration-card.tsx +88 -0
- package/src/components/ui/kanban-column.tsx +0 -7
- package/src/components/ui/onboarding-layout.tsx +102 -1
- package/src/components/ui/opportunity-card.tsx +5 -53
- package/src/components/ui/pipeline-board.tsx +0 -3
- package/src/components/ui/pipeline-chart.tsx +47 -53
- package/src/components/ui/selectable-card.tsx +37 -0
- package/src/components/ui/stepper.tsx +3 -2
- package/src/lib/colors.ts +73 -5
- package/src/lib/format-date.ts +6 -6
- package/src/lib/theme-provider.tsx +13 -8
- package/src/styles/globals.css +37 -9
- package/src/styles/styles-css.ts +1 -1
- package/tsup.config.ts +2 -0
- package/dist/chunk-2P7HP7LR.mjs +0 -68
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { RadioGroupItem } from "./radio-group";
|
|
3
|
+
import { cn } from "../../lib/utils";
|
|
4
|
+
|
|
5
|
+
export interface SelectableCardProps {
|
|
6
|
+
/** The value passed to the parent RadioGroup */
|
|
7
|
+
value: string;
|
|
8
|
+
/** Whether this card is currently selected */
|
|
9
|
+
selected?: boolean;
|
|
10
|
+
/** Content rendered inside the card */
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A card-shaped radio option. Place inside a RadioGroup.
|
|
17
|
+
* Hides the RadioGroupItem visually so the entire card acts as the selector.
|
|
18
|
+
*/
|
|
19
|
+
export function SelectableCard({
|
|
20
|
+
value,
|
|
21
|
+
selected = false,
|
|
22
|
+
children,
|
|
23
|
+
className,
|
|
24
|
+
}: SelectableCardProps) {
|
|
25
|
+
return (
|
|
26
|
+
<label
|
|
27
|
+
className={cn(
|
|
28
|
+
"flex cursor-pointer flex-col items-center justify-center gap-3 border border-border p-6 text-center transition-colors hover:border-primary/50",
|
|
29
|
+
selected && "border-primary bg-primary/5",
|
|
30
|
+
className,
|
|
31
|
+
)}
|
|
32
|
+
>
|
|
33
|
+
<RadioGroupItem value={value} className="sr-only" />
|
|
34
|
+
{children}
|
|
35
|
+
</label>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -279,7 +279,8 @@ function StepLabel({
|
|
|
279
279
|
>
|
|
280
280
|
<span
|
|
281
281
|
className={cn(
|
|
282
|
-
"
|
|
282
|
+
orientation === "vertical" && "flex h-8 items-center",
|
|
283
|
+
"text-label-small transition-colors",
|
|
283
284
|
(isActive || isCompleted) && !error && "text-foreground",
|
|
284
285
|
!isActive && !isCompleted && !error && "text-muted-foreground",
|
|
285
286
|
error && "text-destructive",
|
|
@@ -290,7 +291,7 @@ function StepLabel({
|
|
|
290
291
|
{subtext && (
|
|
291
292
|
<span
|
|
292
293
|
className={cn(
|
|
293
|
-
"mt-0.5 text-
|
|
294
|
+
"mt-0.5 text-caption",
|
|
294
295
|
error ? "text-destructive" : "text-muted-foreground",
|
|
295
296
|
)}
|
|
296
297
|
>
|
package/src/lib/colors.ts
CHANGED
|
@@ -57,8 +57,18 @@ export function colorMixSwatch(color: string, fillOpacity = 0.15): string {
|
|
|
57
57
|
return `color-mix(in srgb, ${color} ${percent}%, transparent)`;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
/**
|
|
61
|
-
export
|
|
60
|
+
/** Parsed OKLCH components as numbers (not a CSS string). */
|
|
61
|
+
export interface OklchComponents {
|
|
62
|
+
/** Lightness: 0 (black) – 1 (white) */
|
|
63
|
+
L: number;
|
|
64
|
+
/** Chroma: 0 (grey) – ~0.4 (max saturation) */
|
|
65
|
+
C: number;
|
|
66
|
+
/** Hue angle in degrees: 0–360 */
|
|
67
|
+
H: number;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Convert hex to individual OKLCH components. */
|
|
71
|
+
export function hexToOklchComponents(hex: string): OklchComponents {
|
|
62
72
|
const [r, g, b] = hexToRgb(hex);
|
|
63
73
|
const rl = linearizeSrgb(r);
|
|
64
74
|
const gl = linearizeSrgb(g);
|
|
@@ -77,10 +87,68 @@ export function hexToOklch(hex: string): string {
|
|
|
77
87
|
const a = 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_;
|
|
78
88
|
const bv = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_;
|
|
79
89
|
|
|
80
|
-
// OKLab → OKLch
|
|
81
90
|
const C = Math.sqrt(a * a + bv * bv);
|
|
82
|
-
const
|
|
91
|
+
const H = ((Math.atan2(bv, a) * 180) / Math.PI + 360) % 360;
|
|
92
|
+
|
|
93
|
+
return { L, C, H };
|
|
94
|
+
}
|
|
83
95
|
|
|
96
|
+
/** Convert hex to oklch() CSS string */
|
|
97
|
+
export function hexToOklch(hex: string): string {
|
|
98
|
+
const { L, C, H } = hexToOklchComponents(hex);
|
|
84
99
|
if (C < 0.001) return `oklch(${L.toFixed(3)} 0 0)`;
|
|
85
|
-
return `oklch(${L.toFixed(3)} ${C.toFixed(3)} ${
|
|
100
|
+
return `oklch(${L.toFixed(3)} ${C.toFixed(3)} ${H.toFixed(1)})`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Tailwind-style lightness stops for an 11-step shade scale (50–950).
|
|
105
|
+
* The hue and a scaled chroma from the base color fill in the rest.
|
|
106
|
+
*
|
|
107
|
+
* Lightness values mirror Tailwind v4's perceptual curve so shades look
|
|
108
|
+
* consistent with standard Tailwind palettes across all tenant hues.
|
|
109
|
+
*/
|
|
110
|
+
const SHADE_LIGHTNESS: ReadonlyArray<[number, number]> = [
|
|
111
|
+
[50, 0.971],
|
|
112
|
+
[100, 0.944],
|
|
113
|
+
[200, 0.887],
|
|
114
|
+
[300, 0.808],
|
|
115
|
+
[400, 0.72],
|
|
116
|
+
[500, 0.646],
|
|
117
|
+
[600, 0.57],
|
|
118
|
+
[700, 0.48],
|
|
119
|
+
[800, 0.39],
|
|
120
|
+
[900, 0.31],
|
|
121
|
+
[950, 0.24],
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Generate an 11-step Tailwind-style primary shade palette from a hex color.
|
|
126
|
+
*
|
|
127
|
+
* Returns CSS-variable key/value pairs ready to be spread into an inline
|
|
128
|
+
* style object or injected via ThemeProvider:
|
|
129
|
+
*
|
|
130
|
+
* ```ts
|
|
131
|
+
* { "--primary-50": "oklch(0.971 0.104 163.0)", "--primary-100": "...", … }
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* Each shade keeps the hue of the base color and linearly scales chroma down
|
|
135
|
+
* for very light (≥ 0.87) and very dark (≤ 0.35) stops to stay in-gamut.
|
|
136
|
+
*/
|
|
137
|
+
export function generatePrimaryShades(hex: string): Record<string, string> {
|
|
138
|
+
const { L: baseL, C: baseC, H } = hexToOklchComponents(hex);
|
|
139
|
+
|
|
140
|
+
return Object.fromEntries(
|
|
141
|
+
SHADE_LIGHTNESS.map(([shade, targetL]) => {
|
|
142
|
+
// Reduce chroma for stops far from the base lightness to stay in-gamut.
|
|
143
|
+
// Stops very close to white (>0.9) or black (<0.3) get ~10% of base chroma.
|
|
144
|
+
const distance = Math.abs(targetL - baseL);
|
|
145
|
+
const chromaScale = Math.max(0.1, 1 - distance * 1.5);
|
|
146
|
+
const C = +(baseC * chromaScale).toFixed(3);
|
|
147
|
+
const value =
|
|
148
|
+
C < 0.001
|
|
149
|
+
? `oklch(${targetL.toFixed(3)} 0 0)`
|
|
150
|
+
: `oklch(${targetL.toFixed(3)} ${C} ${H.toFixed(1)})`;
|
|
151
|
+
return [`--primary-${shade}`, value];
|
|
152
|
+
}),
|
|
153
|
+
);
|
|
86
154
|
}
|
package/src/lib/format-date.ts
CHANGED
|
@@ -50,21 +50,21 @@ export function formatDateWithWeekday(iso: string): string {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
* Format a Date or ISO string as
|
|
54
|
-
*
|
|
53
|
+
* Format a Date or ISO string as a long human-readable string: "Wednesday, 15 January 2026".
|
|
54
|
+
* Used for booking confirmations and summary displays.
|
|
55
55
|
*/
|
|
56
56
|
export function formatDateLong(date: Date | string): string {
|
|
57
|
-
const d = typeof date === "string" ? safeParse(date) : date;
|
|
58
57
|
try {
|
|
59
|
-
|
|
58
|
+
const d = typeof date === "string" ? safeParse(date) : date;
|
|
59
|
+
return format(d, "EEEE, d MMMM yyyy");
|
|
60
60
|
} catch {
|
|
61
|
-
return
|
|
61
|
+
return String(date);
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
/**
|
|
66
66
|
* Format a Date or ISO string as an uppercase short weekday: "MON", "TUE", etc.
|
|
67
|
-
*
|
|
67
|
+
* Used for calendar day headers.
|
|
68
68
|
*/
|
|
69
69
|
export function formatWeekdayShort(date: Date | string): string {
|
|
70
70
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import React, { createContext, useContext, useMemo } from "react";
|
|
4
|
-
import { hexToOklch, getContrastText } from "./colors";
|
|
4
|
+
import { hexToOklch, getContrastText, generatePrimaryShades } from "./colors";
|
|
5
5
|
|
|
6
6
|
export interface ThemeProviderProps {
|
|
7
7
|
children: React.ReactNode;
|
|
@@ -94,13 +94,18 @@ export function ThemeProvider({
|
|
|
94
94
|
"--theme-primary": primary,
|
|
95
95
|
"--theme-secondary": secondary,
|
|
96
96
|
|
|
97
|
-
//
|
|
98
|
-
// Defined here
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
97
|
+
// Primary shade palette (50–950) — Tailwind-style, tenant-adaptive.
|
|
98
|
+
// Defined here so they react to tenant theme switches.
|
|
99
|
+
// Referenced as var(--primary-50) … var(--primary-950) in components.
|
|
100
|
+
...generatePrimaryShades(primary),
|
|
101
|
+
|
|
102
|
+
// Pipeline stage palette — maps stage slots to primary shades.
|
|
103
|
+
// stage-1 = darkest visible, stage-5 = lightest visible on white bg.
|
|
104
|
+
"--color-stage-1": `var(--primary-600)`,
|
|
105
|
+
"--color-stage-2": `var(--primary-400)`,
|
|
106
|
+
"--color-stage-3": `var(--primary-300)`,
|
|
107
|
+
"--color-stage-4": `var(--primary-200)`,
|
|
108
|
+
"--color-stage-5": `var(--primary-100)`,
|
|
104
109
|
// WCAG-computed contrast text for any primary-shaded background
|
|
105
110
|
"--color-stage-fg": primaryFgOklch,
|
|
106
111
|
};
|
package/src/styles/globals.css
CHANGED
|
@@ -57,6 +57,19 @@
|
|
|
57
57
|
--color-popover-foreground: var(--popover-foreground);
|
|
58
58
|
--color-primary: var(--primary);
|
|
59
59
|
--color-primary-foreground: var(--primary-foreground);
|
|
60
|
+
|
|
61
|
+
/* Primary shade palette — generated by ThemeProvider, fallbacks here for static CSS */
|
|
62
|
+
--color-primary-50: var(--primary-50);
|
|
63
|
+
--color-primary-100: var(--primary-100);
|
|
64
|
+
--color-primary-200: var(--primary-200);
|
|
65
|
+
--color-primary-300: var(--primary-300);
|
|
66
|
+
--color-primary-400: var(--primary-400);
|
|
67
|
+
--color-primary-500: var(--primary-500);
|
|
68
|
+
--color-primary-600: var(--primary-600);
|
|
69
|
+
--color-primary-700: var(--primary-700);
|
|
70
|
+
--color-primary-800: var(--primary-800);
|
|
71
|
+
--color-primary-900: var(--primary-900);
|
|
72
|
+
--color-primary-950: var(--primary-950);
|
|
60
73
|
--color-secondary: var(--secondary);
|
|
61
74
|
--color-secondary-foreground: var(--secondary-foreground);
|
|
62
75
|
--color-muted: var(--muted);
|
|
@@ -97,14 +110,14 @@
|
|
|
97
110
|
--color-info-text: var(--info-text);
|
|
98
111
|
--color-destructive-text: var(--destructive-text);
|
|
99
112
|
|
|
100
|
-
/* === Pipeline stage palette —
|
|
101
|
-
/* Real values are injected by ThemeProvider via useThemeVars() / inline style.
|
|
102
|
-
/* Do NOT use these :root fallbacks for production — they won't react to tenant
|
|
103
|
-
--color-stage-1:
|
|
104
|
-
--color-stage-2:
|
|
105
|
-
--color-stage-3:
|
|
106
|
-
--color-stage-4:
|
|
107
|
-
--color-stage-5:
|
|
113
|
+
/* === Pipeline stage palette — maps to primary shades, defined in ThemeProvider === */
|
|
114
|
+
/* Real values are injected by ThemeProvider via useThemeVars() / inline style. */
|
|
115
|
+
/* Do NOT use these :root fallbacks for production — they won't react to tenant. */
|
|
116
|
+
--color-stage-1: var(--primary-600);
|
|
117
|
+
--color-stage-2: var(--primary-400);
|
|
118
|
+
--color-stage-3: var(--primary-300);
|
|
119
|
+
--color-stage-4: var(--primary-200);
|
|
120
|
+
--color-stage-5: var(--primary-100);
|
|
108
121
|
/* Auto foreground for stage-colored backgrounds (WCAG contrast of primary) */
|
|
109
122
|
--color-stage-fg: var(--primary-foreground);
|
|
110
123
|
|
|
@@ -439,8 +452,23 @@
|
|
|
439
452
|
|
|
440
453
|
/* Primary — TENANT-DRIVEN (white-label)
|
|
441
454
|
* Default: WealthX green #33FF99
|
|
442
|
-
* Override at runtime via ThemeProvider for each tenant
|
|
455
|
+
* Override at runtime via ThemeProvider for each tenant.
|
|
456
|
+
* Shade palette (50–950) generated by generatePrimaryShades() in ThemeProvider. */
|
|
443
457
|
--primary: oklch(0.894 0.208 163); /* #33FF99 — palette/primary/main */
|
|
458
|
+
|
|
459
|
+
/* Primary shade palette — static fallbacks for WealthX default green.
|
|
460
|
+
* ThemeProvider overrides these at runtime for each tenant. */
|
|
461
|
+
--primary-50: oklch(0.971 0.021 163);
|
|
462
|
+
--primary-100: oklch(0.944 0.042 163);
|
|
463
|
+
--primary-200: oklch(0.887 0.083 163);
|
|
464
|
+
--primary-300: oklch(0.808 0.125 163);
|
|
465
|
+
--primary-400: oklch(0.72 0.156 163);
|
|
466
|
+
--primary-500: oklch(0.646 0.156 163);
|
|
467
|
+
--primary-600: oklch(0.57 0.146 163);
|
|
468
|
+
--primary-700: oklch(0.48 0.125 163);
|
|
469
|
+
--primary-800: oklch(0.39 0.104 163);
|
|
470
|
+
--primary-900: oklch(0.31 0.073 163);
|
|
471
|
+
--primary-950: oklch(0.24 0.052 163);
|
|
444
472
|
--primary-foreground: oklch(
|
|
445
473
|
0.152 0.02 235
|
|
446
474
|
); /* #040D13 — contrastText for bright primary (button text readability) */
|