@wealthx/shadcn 1.0.2 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +235 -138
- package/CHANGELOG.md +12 -0
- package/README.md +82 -0
- package/dist/{chunk-6OJF6XRN.mjs → chunk-24FUO7TD.mjs} +4 -8
- package/dist/{chunk-4AJ5HWHD.mjs → chunk-2I5S2AMY.mjs} +3 -3
- package/dist/chunk-2SF672SZ.mjs +161 -0
- package/dist/{chunk-GPRJQ24C.mjs → chunk-34NWQURD.mjs} +2 -2
- package/dist/{chunk-MQ72DIBH.mjs → chunk-3GF7OVTP.mjs} +14 -5
- package/dist/chunk-3WMX6KWS.mjs +245 -0
- package/dist/{chunk-PMKODV6M.mjs → chunk-462HMNO4.mjs} +6 -10
- package/dist/chunk-4CX4SBRO.mjs +153 -0
- package/dist/chunk-4MN6UQHG.mjs +443 -0
- package/dist/chunk-5QQVZTVZ.mjs +233 -0
- package/dist/{chunk-BGP2N52Z.mjs → chunk-66MI7Q4B.mjs} +5 -5
- package/dist/chunk-6FCGKSZX.mjs +268 -0
- package/dist/{chunk-CGOKTPXU.mjs → chunk-6JQFUE5I.mjs} +20 -23
- package/dist/{chunk-Z3MK2KKZ.mjs → chunk-7DHU4VGG.mjs} +7 -3
- package/dist/{chunk-VZ2NR7L3.mjs → chunk-7PYJD5JI.mjs} +35 -27
- package/dist/{chunk-JU2RUWHF.mjs → chunk-7XJHLGUV.mjs} +1 -1
- package/dist/{chunk-BMFN37JH.mjs → chunk-7YAU5CY6.mjs} +1 -1
- package/dist/chunk-A56YQQHG.mjs +402 -0
- package/dist/chunk-AH52LG6N.mjs +315 -0
- package/dist/{chunk-SLWCCURD.mjs → chunk-CLIN5525.mjs} +8 -4
- package/dist/{chunk-3VQNJ235.mjs → chunk-CSDO6VBW.mjs} +7 -0
- package/dist/chunk-D4ILTPOG.mjs +293 -0
- package/dist/{chunk-HS7TFG7V.mjs → chunk-D6ID6M4V.mjs} +1 -1
- package/dist/chunk-DOH3EHX7.mjs +378 -0
- package/dist/{chunk-MJIEMGRD.mjs → chunk-EFRENWEJ.mjs} +9 -17
- package/dist/chunk-ERGGHC2V.mjs +185 -0
- package/dist/{chunk-OXQQNQZI.mjs → chunk-FEZKMUCF.mjs} +10 -1
- package/dist/{chunk-55CEW76V.mjs → chunk-FH6QVUVZ.mjs} +1 -1
- package/dist/chunk-FMAXJ2SI.mjs +71 -0
- package/dist/chunk-FZIXGLMV.mjs +173 -0
- package/dist/{chunk-DS2AMHN2.mjs → chunk-GYMYRIZP.mjs} +2 -2
- package/dist/{chunk-KQDD5MU3.mjs → chunk-H45TKD34.mjs} +5 -5
- package/dist/{chunk-BBJBJSXQ.mjs → chunk-J5UICVJS.mjs} +1 -1
- package/dist/{chunk-RL772EH7.mjs → chunk-JHJHG4GO.mjs} +4 -12
- package/dist/chunk-KMCGSZTX.mjs +177 -0
- package/dist/{chunk-FHNT55I5.mjs → chunk-KUDCQ4FI.mjs} +4 -4
- package/dist/chunk-LE6YFY6D.mjs +209 -0
- package/dist/{chunk-HUVTPUV2.mjs → chunk-LLVQKSU3.mjs} +23 -19
- package/dist/{chunk-KKHTJNMM.mjs → chunk-MARPPFOJ.mjs} +8 -4
- package/dist/{chunk-6AFMNC42.mjs → chunk-N2PT566P.mjs} +15 -11
- package/dist/chunk-NLCKVHWB.mjs +161 -0
- package/dist/{chunk-YN5SYTOO.mjs → chunk-NQPOYKAQ.mjs} +9 -5
- package/dist/{chunk-ZZV5JVNW.mjs → chunk-NSLMILBT.mjs} +3 -7
- package/dist/chunk-NXA3CZ7A.mjs +248 -0
- package/dist/chunk-OGOYQ7BG.mjs +150 -0
- package/dist/{chunk-3NQGYJEZ.mjs → chunk-P6AM5V7O.mjs} +10 -18
- package/dist/{chunk-CZ3BW5GL.mjs → chunk-P76HMUI6.mjs} +5 -11
- package/dist/chunk-PCPLO5HT.mjs +671 -0
- package/dist/chunk-PG6K5XEC.mjs +475 -0
- package/dist/chunk-PJHPSRYD.mjs +234 -0
- package/dist/{chunk-DDPA2XXS.mjs → chunk-PMB3A7V3.mjs} +2 -2
- package/dist/chunk-PR6V5XKM.mjs +209 -0
- package/dist/{chunk-46OFHMQA.mjs → chunk-Q76O3RIQ.mjs} +10 -6
- package/dist/chunk-QVKWW6KE.mjs +272 -0
- package/dist/chunk-RGU7HOEC.mjs +140 -0
- package/dist/{chunk-JF4PHPD5.mjs → chunk-RGVKLTLH.mjs} +4 -4
- package/dist/{chunk-VG6UF6UT.mjs → chunk-RP3SQYA3.mjs} +2 -2
- package/dist/chunk-RRBS6D63.mjs +163 -0
- package/dist/chunk-SMQ3DG25.mjs +285 -0
- package/dist/chunk-SPJ5KXW7.mjs +199 -0
- package/dist/chunk-SYOD63OZ.mjs +225 -0
- package/dist/chunk-UFYSFDER.mjs +42 -0
- package/dist/chunk-VACKZOMY.mjs +190 -0
- package/dist/chunk-VLQZANBF.mjs +42 -0
- package/dist/chunk-WA6O6EUR.mjs +1885 -0
- package/dist/{chunk-E3K6O4FZ.mjs → chunk-WAZD7NFU.mjs} +5 -2
- package/dist/chunk-WG6JGJXB.mjs +165 -0
- package/dist/{chunk-I64K754C.mjs → chunk-WNGWBVLV.mjs} +2 -2
- package/dist/{chunk-3U7SD3MS.mjs → chunk-WOEHFRGB.mjs} +3 -3
- package/dist/{chunk-DKZRJOMF.mjs → chunk-XIRTEFKH.mjs} +12 -12
- package/dist/chunk-Y6DWJSKZ.mjs +79 -0
- package/dist/chunk-YKPROFLB.mjs +161 -0
- package/dist/{chunk-K76E2TQU.mjs → chunk-ZRO5JO3H.mjs} +107 -67
- package/dist/{chunk-VYMHBV6D.mjs → chunk-ZU4NV6RG.mjs} +5 -3
- package/dist/components/ui/accordion.js +40 -4
- package/dist/components/ui/accordion.mjs +2 -2
- package/dist/components/ui/add-column-modal.js +789 -0
- package/dist/components/ui/add-column-modal.mjs +17 -0
- package/dist/components/ui/add-lead-modal.js +647 -0
- package/dist/components/ui/add-lead-modal.mjs +16 -0
- package/dist/components/ui/ai-assistant-drawer.js +686 -0
- package/dist/components/ui/ai-assistant-drawer.mjs +16 -0
- package/dist/components/ui/alert-dialog.js +37 -5
- package/dist/components/ui/alert-dialog.mjs +4 -4
- package/dist/components/ui/alert.js +37 -11
- package/dist/components/ui/alert.mjs +2 -2
- package/dist/components/ui/avatar.js +36 -8
- package/dist/components/ui/avatar.mjs +2 -2
- package/dist/components/ui/backoffice-alert-history-chart.js +624 -0
- package/dist/components/ui/backoffice-alert-history-chart.mjs +16 -0
- package/dist/components/ui/backoffice-contact-history-chart.js +687 -0
- package/dist/components/ui/backoffice-contact-history-chart.mjs +16 -0
- package/dist/components/ui/badge.js +37 -2
- package/dist/components/ui/badge.mjs +2 -2
- package/dist/components/ui/borrowing-capacity-line-chart.js +639 -0
- package/dist/components/ui/borrowing-capacity-line-chart.mjs +16 -0
- package/dist/components/ui/button.js +35 -3
- package/dist/components/ui/button.mjs +2 -2
- package/dist/components/ui/calendar.js +43 -19
- package/dist/components/ui/calendar.mjs +3 -3
- package/dist/components/ui/card.js +40 -4
- package/dist/components/ui/card.mjs +2 -2
- package/dist/components/ui/cash-balance-line-chart.js +627 -0
- package/dist/components/ui/cash-balance-line-chart.mjs +16 -0
- package/dist/components/ui/cashflow-bar-chart.js +650 -0
- package/dist/components/ui/cashflow-bar-chart.mjs +16 -0
- package/dist/components/ui/checkbox.js +36 -5
- package/dist/components/ui/checkbox.mjs +2 -3
- package/dist/components/ui/chip.js +37 -2
- package/dist/components/ui/chip.mjs +3 -3
- package/dist/components/ui/combobox.js +280 -0
- package/dist/components/ui/combobox.mjs +28 -0
- package/dist/components/ui/data-table.js +160 -88
- package/dist/components/ui/data-table.mjs +10 -11
- package/dist/components/ui/date-picker.js +44 -20
- package/dist/components/ui/date-picker.mjs +6 -7
- package/dist/components/ui/dialog.js +44 -12
- package/dist/components/ui/dialog.mjs +4 -4
- package/dist/components/ui/drawer.js +46 -10
- package/dist/components/ui/drawer.mjs +3 -3
- package/dist/components/ui/dropdown-menu.js +40 -16
- package/dist/components/ui/dropdown-menu.mjs +3 -3
- package/dist/components/ui/empty.js +41 -5
- package/dist/components/ui/empty.mjs +2 -2
- package/dist/components/ui/expense-bar-chart.js +642 -0
- package/dist/components/ui/expense-bar-chart.mjs +16 -0
- package/dist/components/ui/field.js +53 -21
- package/dist/components/ui/field.mjs +4 -4
- package/dist/components/ui/financial-cards.js +1002 -0
- package/dist/components/ui/financial-cards.mjs +24 -0
- package/dist/components/ui/financial-drawers.js +637 -0
- package/dist/components/ui/financial-drawers.mjs +17 -0
- package/dist/components/ui/financial-primitives.js +218 -0
- package/dist/components/ui/financial-primitives.mjs +22 -0
- package/dist/components/ui/financial-sections.js +1422 -0
- package/dist/components/ui/financial-sections.mjs +30 -0
- package/dist/components/ui/form-primitives.js +682 -0
- package/dist/components/ui/form-primitives.mjs +19 -0
- package/dist/components/ui/income-bar-chart.js +641 -0
- package/dist/components/ui/income-bar-chart.mjs +16 -0
- package/dist/components/ui/input-group.js +43 -7
- package/dist/components/ui/input-group.mjs +5 -5
- package/dist/components/ui/input-otp.js +39 -3
- package/dist/components/ui/input-otp.mjs +2 -2
- package/dist/components/ui/input.js +34 -2
- package/dist/components/ui/input.mjs +2 -2
- package/dist/components/ui/kanban-column.js +1143 -0
- package/dist/components/ui/kanban-column.mjs +20 -0
- package/dist/components/ui/label.js +35 -7
- package/dist/components/ui/label.mjs +2 -2
- package/dist/components/ui/opportunity-card.js +960 -0
- package/dist/components/ui/opportunity-card.mjs +20 -0
- package/dist/components/ui/opportunity-edit-modals.js +3360 -0
- package/dist/components/ui/opportunity-edit-modals.mjs +37 -0
- package/dist/components/ui/opportunity-summary-tab.js +4365 -0
- package/dist/components/ui/opportunity-summary-tab.mjs +34 -0
- package/dist/components/ui/pagination.js +35 -3
- package/dist/components/ui/pagination.mjs +3 -3
- package/dist/components/ui/pipeline-alerts.js +103 -0
- package/dist/components/ui/pipeline-alerts.mjs +8 -0
- package/dist/components/ui/pipeline-board.js +1408 -0
- package/dist/components/ui/pipeline-board.mjs +24 -0
- package/dist/components/ui/pipeline-chart.js +216 -0
- package/dist/components/ui/pipeline-chart.mjs +10 -0
- package/dist/components/ui/pipeline-dialogs.js +1183 -0
- package/dist/components/ui/pipeline-dialogs.mjs +23 -0
- package/dist/components/ui/pipeline-primitives.js +300 -0
- package/dist/components/ui/pipeline-primitives.mjs +11 -0
- package/dist/components/ui/popover.js +45 -4
- package/dist/components/ui/popover.mjs +3 -3
- package/dist/components/ui/progress.js +33 -1
- package/dist/components/ui/progress.mjs +2 -2
- package/dist/components/ui/property-cashflow-doughnut-chart.js +523 -0
- package/dist/components/ui/property-cashflow-doughnut-chart.mjs +16 -0
- package/dist/components/ui/property-debt-equity-doughnut-chart.js +521 -0
- package/dist/components/ui/property-debt-equity-doughnut-chart.mjs +16 -0
- package/dist/components/ui/property-mobile-estimate-line-chart.js +682 -0
- package/dist/components/ui/property-mobile-estimate-line-chart.mjs +16 -0
- package/dist/components/ui/radio-group.js +33 -1
- package/dist/components/ui/radio-group.mjs +2 -2
- package/dist/components/ui/select.js +66 -26
- package/dist/components/ui/select.mjs +3 -3
- package/dist/components/ui/separator.js +33 -1
- package/dist/components/ui/separator.mjs +2 -2
- package/dist/components/ui/sheet.js +37 -9
- package/dist/components/ui/sheet.mjs +3 -3
- package/dist/components/ui/skeleton.js +33 -1
- package/dist/components/ui/skeleton.mjs +2 -2
- package/dist/components/ui/slider.js +86 -102
- package/dist/components/ui/slider.mjs +2 -2
- package/dist/components/ui/spinner.js +33 -1
- package/dist/components/ui/spinner.mjs +2 -2
- package/dist/components/ui/stage-timeline.js +579 -0
- package/dist/components/ui/stage-timeline.mjs +15 -0
- package/dist/components/ui/switch.js +37 -4
- package/dist/components/ui/switch.mjs +2 -3
- package/dist/components/ui/table.js +37 -5
- package/dist/components/ui/table.mjs +2 -2
- package/dist/components/ui/tabs.js +36 -12
- package/dist/components/ui/tabs.mjs +2 -2
- package/dist/components/ui/textarea.js +34 -2
- package/dist/components/ui/textarea.mjs +2 -2
- package/dist/components/ui/toggle-group.js +35 -4
- package/dist/components/ui/toggle-group.mjs +3 -4
- package/dist/components/ui/toggle.js +35 -4
- package/dist/components/ui/toggle.mjs +2 -3
- package/dist/components/ui/tooltip.js +51 -22
- package/dist/components/ui/tooltip.mjs +3 -3
- package/dist/components/ui/transactions-expense-categories-doughnut-chart.js +528 -0
- package/dist/components/ui/transactions-expense-categories-doughnut-chart.mjs +16 -0
- package/dist/components/ui/transactions-income-expense-bar-chart.js +516 -0
- package/dist/components/ui/transactions-income-expense-bar-chart.mjs +16 -0
- package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.js +528 -0
- package/dist/components/ui/transactions-liabilities-breakdown-doughnut-chart.mjs +16 -0
- package/dist/index.js +11613 -2868
- package/dist/index.mjs +377 -164
- package/dist/lib/theme-provider.js +10 -1
- package/dist/lib/theme-provider.mjs +1 -1
- package/dist/lib/typography.js +8 -0
- package/dist/lib/typography.mjs +3 -1
- package/dist/lib/utils.js +33 -1
- package/dist/lib/utils.mjs +1 -1
- package/dist/styles.css +1 -1
- package/package.json +169 -6
- package/src/components/index.tsx +323 -13
- package/src/components/ui/accordion.tsx +6 -3
- package/src/components/ui/add-column-modal.tsx +339 -0
- package/src/components/ui/add-lead-modal.tsx +290 -0
- package/src/components/ui/ai-assistant-drawer.tsx +408 -0
- package/src/components/ui/alert-dialog.tsx +80 -54
- package/src/components/ui/alert.tsx +28 -28
- package/src/components/ui/avatar.tsx +30 -29
- package/src/components/ui/backoffice-alert-history-chart.tsx +260 -0
- package/src/components/ui/backoffice-contact-history-chart.tsx +325 -0
- package/src/components/ui/badge.tsx +17 -15
- package/src/components/ui/borrowing-capacity-line-chart.tsx +357 -0
- package/src/components/ui/button.tsx +30 -27
- package/src/components/ui/calendar.tsx +53 -67
- package/src/components/ui/card.tsx +27 -24
- package/src/components/ui/cash-balance-line-chart.tsx +302 -0
- package/src/components/ui/cashflow-bar-chart.tsx +363 -0
- package/src/components/ui/chart-shared.tsx +261 -0
- package/src/components/ui/checkbox.tsx +30 -26
- package/src/components/ui/combobox.tsx +223 -0
- package/src/components/ui/data-table.tsx +160 -99
- package/src/components/ui/date-picker.tsx +0 -2
- package/src/components/ui/dialog.tsx +70 -60
- package/src/components/ui/drawer.tsx +57 -48
- package/src/components/ui/dropdown-menu.tsx +90 -82
- package/src/components/ui/empty.tsx +31 -27
- package/src/components/ui/expense-bar-chart.tsx +296 -0
- package/src/components/ui/field.tsx +70 -62
- package/src/components/ui/financial-cards.tsx +830 -0
- package/src/components/ui/financial-drawers.tsx +339 -0
- package/src/components/ui/financial-primitives.tsx +331 -0
- package/src/components/ui/financial-sections.tsx +672 -0
- package/src/components/ui/form-primitives.tsx +536 -0
- package/src/components/ui/income-bar-chart.tsx +297 -0
- package/src/components/ui/input-group.tsx +41 -34
- package/src/components/ui/input-otp.tsx +29 -24
- package/src/components/ui/input.tsx +8 -8
- package/src/components/ui/kanban-column.tsx +333 -0
- package/src/components/ui/label.tsx +9 -12
- package/src/components/ui/opportunity-card.tsx +616 -0
- package/src/components/ui/opportunity-edit-modals.tsx +2528 -0
- package/src/components/ui/opportunity-summary-tab.tsx +579 -0
- package/src/components/ui/pipeline-alerts.tsx +74 -0
- package/src/components/ui/pipeline-board.tsx +268 -0
- package/src/components/ui/pipeline-chart.tsx +173 -0
- package/src/components/ui/pipeline-dialogs.tsx +303 -0
- package/src/components/ui/pipeline-primitives.tsx +108 -0
- package/src/components/ui/popover.tsx +41 -36
- package/src/components/ui/property-cashflow-doughnut-chart.tsx +188 -0
- package/src/components/ui/property-debt-equity-doughnut-chart.tsx +185 -0
- package/src/components/ui/property-mobile-estimate-line-chart.tsx +393 -0
- package/src/components/ui/select.tsx +65 -52
- package/src/components/ui/sheet.tsx +55 -52
- package/src/components/ui/slider.tsx +54 -77
- package/src/components/ui/stage-timeline.tsx +205 -0
- package/src/components/ui/switch.tsx +42 -29
- package/src/components/ui/table.tsx +28 -28
- package/src/components/ui/tabs.tsx +22 -28
- package/src/components/ui/textarea.tsx +8 -8
- package/src/components/ui/toggle-group.tsx +0 -2
- package/src/components/ui/toggle.tsx +13 -15
- package/src/components/ui/tooltip.tsx +30 -28
- package/src/components/ui/transactions-expense-categories-doughnut-chart.tsx +191 -0
- package/src/components/ui/transactions-income-expense-bar-chart.tsx +205 -0
- package/src/components/ui/transactions-liabilities-breakdown-doughnut-chart.tsx +191 -0
- package/src/lib/theme-provider.tsx +10 -0
- package/src/lib/typography.ts +9 -0
- package/src/lib/utils.ts +41 -3
- package/src/styles/globals.css +371 -124
- package/src/styles/styles-css.ts +1 -1
- package/tsup.config.ts +32 -0
- package/dist/chunk-K74JRTJR.mjs +0 -105
- package/dist/chunk-V7CNWJT3.mjs +0 -10
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities and sub-components for all shadcn chart components.
|
|
3
|
+
* Not part of the public package API — internal use only.
|
|
4
|
+
*/
|
|
5
|
+
import React from "react";
|
|
6
|
+
import { Button } from "./button";
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Types
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
export type ChartPeriod = 1 | 3 | 6 | 12;
|
|
13
|
+
export type ChartGranularity = "monthly" | "daily";
|
|
14
|
+
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// Period / slice config
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* How many data points to slice per period × granularity combination.
|
|
21
|
+
* monthly: slice by calendar month count.
|
|
22
|
+
* daily: slice by approximate day count (1M=30d, 3M=90d, 6M=180d, 12M=365d).
|
|
23
|
+
*/
|
|
24
|
+
export const CHART_SLICE_COUNT: Record<
|
|
25
|
+
ChartGranularity,
|
|
26
|
+
Record<ChartPeriod, number>
|
|
27
|
+
> = {
|
|
28
|
+
monthly: { 1: 1, 3: 3, 6: 6, 12: 12 },
|
|
29
|
+
daily: { 1: 30, 3: 90, 6: 180, 12: 365 },
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/** Period buttons shown per granularity. monthly hides 1M; daily shows all four. */
|
|
33
|
+
export const CHART_PERIODS: Record<ChartGranularity, ChartPeriod[]> = {
|
|
34
|
+
monthly: [3, 6, 12],
|
|
35
|
+
daily: [1, 3, 6, 12],
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Chart.js helpers
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
export function hexToRgba(hex: string, alpha: number): string {
|
|
43
|
+
const clean = hex.replace("#", "");
|
|
44
|
+
const full =
|
|
45
|
+
clean.length === 3
|
|
46
|
+
? clean
|
|
47
|
+
.split("")
|
|
48
|
+
.map((c) => c + c)
|
|
49
|
+
.join("")
|
|
50
|
+
: clean;
|
|
51
|
+
const r = parseInt(full.slice(0, 2), 16);
|
|
52
|
+
const g = parseInt(full.slice(2, 4), 16);
|
|
53
|
+
const b = parseInt(full.slice(4, 6), 16);
|
|
54
|
+
return `rgba(${r},${g},${b},${alpha})`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Opacity steps to derive distinct shades from a single brand color (up to 6 datasets). */
|
|
58
|
+
export const DATASET_ALPHAS = [1, 0.72, 0.52, 0.36, 0.24, 0.15];
|
|
59
|
+
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Fallback resolved colors for Chart.js canvas API.
|
|
62
|
+
// Chart.js requires actual hex/rgb strings — CSS variables cannot be used directly.
|
|
63
|
+
// All values match the :root defaults defined in globals.css.
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
|
|
66
|
+
/** Fallback for --primary (WealthX green) */
|
|
67
|
+
export const FALLBACK_PRIMARY = "#33FF99";
|
|
68
|
+
/** Fallback for --brand-secondary (WealthX dark navy) */
|
|
69
|
+
export const FALLBACK_SECONDARY = "#162029";
|
|
70
|
+
/** Fallback for --background (white) */
|
|
71
|
+
export const FALLBACK_BG = "#ffffff";
|
|
72
|
+
/** Fallback for --foreground (near-black) */
|
|
73
|
+
export const FALLBACK_FOREGROUND = "#040D13";
|
|
74
|
+
/** Fallback for --muted-foreground used as axis tick color */
|
|
75
|
+
export const FALLBACK_TICK = "#9EAAB5";
|
|
76
|
+
/** Fallback neutral grey for comparison / suburb lines */
|
|
77
|
+
export const FALLBACK_NEUTRAL = "#B9BCBF";
|
|
78
|
+
/** Fallback semi-transparent grid line color */
|
|
79
|
+
export const FALLBACK_GRID_COLOR = "rgba(0,0,0,0.06)";
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Semantic severity colors for alert / status charts.
|
|
83
|
+
* Match WealthX design tokens: --destructive, --warning, --success.
|
|
84
|
+
* Intentionally fixed — severity meaning must be recognisable regardless of tenant theme.
|
|
85
|
+
*/
|
|
86
|
+
export const SEVERITY_COLORS = {
|
|
87
|
+
high: "#F44336", // default --destructive oklch(0.643 0.215 28.8)
|
|
88
|
+
medium: "#FF9800", // default --warning oklch(0.77 0.174 64.1)
|
|
89
|
+
low: "#4CAF50", // default --success oklch(0.673 0.162 144.2)
|
|
90
|
+
} as const;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Format a dollar amount as an abbreviated string for chart axis ticks.
|
|
94
|
+
* e.g. 1_200_000 → "$1.2M", 580_000 → "$580K", -250_000 → "-$250K"
|
|
95
|
+
*/
|
|
96
|
+
export function formatAbbrev(value: number): string {
|
|
97
|
+
const abs = Math.abs(value);
|
|
98
|
+
const sign = value < 0 ? "-" : "";
|
|
99
|
+
if (abs >= 1_000_000_000)
|
|
100
|
+
return `${sign}$${(abs / 1_000_000_000).toFixed(1)}B`;
|
|
101
|
+
if (abs >= 1_000_000) return `${sign}$${(abs / 1_000_000).toFixed(1)}M`;
|
|
102
|
+
if (abs >= 1_000) return `${sign}$${(abs / 1_000).toFixed(0)}K`;
|
|
103
|
+
return `${sign}$${abs.toFixed(0)}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// ---------------------------------------------------------------------------
|
|
107
|
+
// Tooltip date format
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Format an ISO date string for the chart tooltip title.
|
|
112
|
+
* Daily granularity includes the day; monthly shows only month + year.
|
|
113
|
+
*/
|
|
114
|
+
export function formatTooltipDate(
|
|
115
|
+
iso: string,
|
|
116
|
+
granularity: ChartGranularity,
|
|
117
|
+
): string {
|
|
118
|
+
const d = new Date(iso);
|
|
119
|
+
return d.toLocaleDateString(
|
|
120
|
+
"en-US",
|
|
121
|
+
granularity === "daily"
|
|
122
|
+
? { month: "short", day: "numeric", year: "numeric" }
|
|
123
|
+
: { month: "short", year: "numeric" },
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
// Date / count formatters (shared across bar and doughnut charts)
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
|
|
131
|
+
/** Format an ISO date string as "Mon 'YY" for X-axis month labels. */
|
|
132
|
+
export function formatMonthLabel(iso: string): string {
|
|
133
|
+
return new Date(iso).toLocaleDateString("en-US", {
|
|
134
|
+
month: "short",
|
|
135
|
+
year: "2-digit",
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Format a raw integer count for axis ticks and tooltips. */
|
|
140
|
+
export function formatCount(n: number): string {
|
|
141
|
+
if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;
|
|
142
|
+
return String(Math.round(n));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// ---------------------------------------------------------------------------
|
|
146
|
+
// Sub-components
|
|
147
|
+
// ---------------------------------------------------------------------------
|
|
148
|
+
|
|
149
|
+
export function ChartLegendItem({
|
|
150
|
+
label,
|
|
151
|
+
color,
|
|
152
|
+
lineStyle,
|
|
153
|
+
}: {
|
|
154
|
+
label: string;
|
|
155
|
+
color: string;
|
|
156
|
+
/** When provided, renders a line indicator instead of a square swatch */
|
|
157
|
+
lineStyle?: "solid" | "dashed";
|
|
158
|
+
}) {
|
|
159
|
+
return (
|
|
160
|
+
<div className="flex items-center gap-1.5">
|
|
161
|
+
{lineStyle ? (
|
|
162
|
+
<svg
|
|
163
|
+
width="20"
|
|
164
|
+
height="10"
|
|
165
|
+
viewBox="0 0 20 10"
|
|
166
|
+
aria-hidden="true"
|
|
167
|
+
style={{ flexShrink: 0 }}
|
|
168
|
+
>
|
|
169
|
+
<line
|
|
170
|
+
x1="0"
|
|
171
|
+
y1="5"
|
|
172
|
+
x2="20"
|
|
173
|
+
y2="5"
|
|
174
|
+
stroke={color}
|
|
175
|
+
strokeWidth="2"
|
|
176
|
+
strokeLinecap="square"
|
|
177
|
+
strokeDasharray={lineStyle === "dashed" ? "5 3" : undefined}
|
|
178
|
+
/>
|
|
179
|
+
</svg>
|
|
180
|
+
) : (
|
|
181
|
+
<div
|
|
182
|
+
style={{
|
|
183
|
+
width: 10,
|
|
184
|
+
height: 10,
|
|
185
|
+
backgroundColor: color,
|
|
186
|
+
flexShrink: 0,
|
|
187
|
+
}}
|
|
188
|
+
/>
|
|
189
|
+
)}
|
|
190
|
+
<span className="text-[11px] text-muted-foreground leading-none">
|
|
191
|
+
{label}
|
|
192
|
+
</span>
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* One row in a doughnut chart legend — circle swatch, label, dollar value, percent.
|
|
199
|
+
* The label truncates when the container is constrained.
|
|
200
|
+
*/
|
|
201
|
+
export function DoughnutLegendRow({
|
|
202
|
+
label,
|
|
203
|
+
color,
|
|
204
|
+
value,
|
|
205
|
+
percent,
|
|
206
|
+
}: {
|
|
207
|
+
label: string;
|
|
208
|
+
color: string;
|
|
209
|
+
value: number;
|
|
210
|
+
percent: string;
|
|
211
|
+
}) {
|
|
212
|
+
return (
|
|
213
|
+
<div className="flex items-center justify-between gap-2">
|
|
214
|
+
<div className="flex items-center gap-1.5 min-w-0">
|
|
215
|
+
<div
|
|
216
|
+
style={{
|
|
217
|
+
width: 10,
|
|
218
|
+
height: 10,
|
|
219
|
+
borderRadius: "50%",
|
|
220
|
+
backgroundColor: color,
|
|
221
|
+
flexShrink: 0,
|
|
222
|
+
}}
|
|
223
|
+
/>
|
|
224
|
+
<span className="text-[11px] text-muted-foreground leading-none truncate">
|
|
225
|
+
{label}
|
|
226
|
+
</span>
|
|
227
|
+
</div>
|
|
228
|
+
<div className="flex items-center gap-2 shrink-0">
|
|
229
|
+
<span className="text-[11px] font-medium leading-none">
|
|
230
|
+
{formatAbbrev(value)}
|
|
231
|
+
</span>
|
|
232
|
+
<span className="text-[11px] text-muted-foreground leading-none w-10 text-right">
|
|
233
|
+
{percent}
|
|
234
|
+
</span>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export function ChartPeriodButton({
|
|
241
|
+
period,
|
|
242
|
+
active,
|
|
243
|
+
onClick,
|
|
244
|
+
unit = "M",
|
|
245
|
+
}: {
|
|
246
|
+
period: number;
|
|
247
|
+
active: boolean;
|
|
248
|
+
onClick: () => void;
|
|
249
|
+
unit?: string;
|
|
250
|
+
}) {
|
|
251
|
+
return (
|
|
252
|
+
<Button
|
|
253
|
+
variant={active ? "default" : "outline"}
|
|
254
|
+
size="xs"
|
|
255
|
+
onClick={onClick}
|
|
256
|
+
>
|
|
257
|
+
{period}
|
|
258
|
+
{unit}
|
|
259
|
+
</Button>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
|
|
6
|
-
import { cn } from "@/lib/utils"
|
|
1
|
+
import { type ReactElement, useState, type ComponentProps } from "react";
|
|
2
|
+
import { CheckIcon, MinusIcon } from "lucide-react";
|
|
3
|
+
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* Checkbox — shadcn/WealthX Design System
|
|
@@ -13,13 +11,13 @@ import { cn } from "@/lib/utils"
|
|
|
13
11
|
* White-label: checked/indeterminate use `primary` token → adapts to tenant color.
|
|
14
12
|
* Error+checked/indeterminate: stacked variant overrides primary with destructive (higher specificity).
|
|
15
13
|
*/
|
|
16
|
-
export type CheckboxProps = ComponentProps<typeof CheckboxPrimitive.Root
|
|
14
|
+
export type CheckboxProps = ComponentProps<typeof CheckboxPrimitive.Root>;
|
|
17
15
|
|
|
18
16
|
function Checkbox({ className, ...props }: CheckboxProps): ReactElement {
|
|
19
17
|
return (
|
|
20
18
|
<CheckboxPrimitive.Root
|
|
21
19
|
className={cn(
|
|
22
|
-
"peer group inline-flex size-4 shrink-0
|
|
20
|
+
"peer group inline-flex size-4 shrink-0 border border-input shadow-xs transition-all outline-none",
|
|
23
21
|
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
24
22
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
25
23
|
"aria-invalid:border-destructive aria-invalid:ring-destructive/20",
|
|
@@ -30,7 +28,7 @@ function Checkbox({ className, ...props }: CheckboxProps): ReactElement {
|
|
|
30
28
|
// Stacked (2 attr selectors) → wins over single-attr rules above
|
|
31
29
|
"aria-invalid:data-checked:border-destructive aria-invalid:data-checked:bg-destructive aria-invalid:data-checked:text-destructive-foreground",
|
|
32
30
|
"aria-invalid:data-indeterminate:border-destructive aria-invalid:data-indeterminate:bg-destructive aria-invalid:data-indeterminate:text-destructive-foreground",
|
|
33
|
-
className
|
|
31
|
+
className,
|
|
34
32
|
)}
|
|
35
33
|
data-slot="checkbox"
|
|
36
34
|
{...props}
|
|
@@ -43,7 +41,7 @@ function Checkbox({ className, ...props }: CheckboxProps): ReactElement {
|
|
|
43
41
|
<MinusIcon className="size-3.5 hidden group-data-indeterminate:block" />
|
|
44
42
|
</CheckboxPrimitive.Indicator>
|
|
45
43
|
</CheckboxPrimitive.Root>
|
|
46
|
-
)
|
|
44
|
+
);
|
|
47
45
|
}
|
|
48
46
|
|
|
49
47
|
/**
|
|
@@ -53,11 +51,13 @@ function Checkbox({ className, ...props }: CheckboxProps): ReactElement {
|
|
|
53
51
|
* Card background: primary/5 when checked/indeterminate; destructive/5 when error+checked.
|
|
54
52
|
* White-label: opacity modifier on primary token → adapts to tenant color.
|
|
55
53
|
*/
|
|
56
|
-
export type CheckboxCardProps = ComponentProps<
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
export type CheckboxCardProps = ComponentProps<
|
|
55
|
+
typeof CheckboxPrimitive.Root
|
|
56
|
+
> & {
|
|
57
|
+
label: string;
|
|
58
|
+
description?: string;
|
|
59
|
+
error?: boolean;
|
|
60
|
+
};
|
|
61
61
|
|
|
62
62
|
function CheckboxCard({
|
|
63
63
|
className,
|
|
@@ -71,11 +71,11 @@ function CheckboxCard({
|
|
|
71
71
|
...props
|
|
72
72
|
}: CheckboxCardProps): ReactElement {
|
|
73
73
|
const [internalChecked, setInternalChecked] = useState<boolean>(
|
|
74
|
-
Boolean(defaultChecked)
|
|
75
|
-
)
|
|
74
|
+
Boolean(defaultChecked),
|
|
75
|
+
);
|
|
76
76
|
|
|
77
|
-
const resolvedChecked = checked ?? internalChecked
|
|
78
|
-
const isTinted = resolvedChecked
|
|
77
|
+
const resolvedChecked = checked ?? internalChecked;
|
|
78
|
+
const isTinted = resolvedChecked;
|
|
79
79
|
|
|
80
80
|
return (
|
|
81
81
|
<label
|
|
@@ -85,7 +85,7 @@ function CheckboxCard({
|
|
|
85
85
|
? ["border-destructive", isTinted && "bg-destructive/5"]
|
|
86
86
|
: isTinted && "border-primary bg-primary/5",
|
|
87
87
|
disabled && "cursor-not-allowed opacity-50",
|
|
88
|
-
className
|
|
88
|
+
className,
|
|
89
89
|
)}
|
|
90
90
|
data-slot="checkbox-card"
|
|
91
91
|
>
|
|
@@ -95,17 +95,21 @@ function CheckboxCard({
|
|
|
95
95
|
className="mt-0.5"
|
|
96
96
|
disabled={disabled}
|
|
97
97
|
onCheckedChange={(value, event) => {
|
|
98
|
-
setInternalChecked(value as boolean)
|
|
99
|
-
onCheckedChange?.(value, event)
|
|
98
|
+
setInternalChecked(value as boolean);
|
|
99
|
+
onCheckedChange?.(value, event);
|
|
100
100
|
}}
|
|
101
101
|
{...props}
|
|
102
102
|
/>
|
|
103
103
|
<div className="flex flex-col gap-1">
|
|
104
|
-
<span className="text-
|
|
105
|
-
{description ?
|
|
104
|
+
<span className="text-label-medium leading-none">{label}</span>
|
|
105
|
+
{description ? (
|
|
106
|
+
<span className="text-body-small text-muted-foreground">
|
|
107
|
+
{description}
|
|
108
|
+
</span>
|
|
109
|
+
) : null}
|
|
106
110
|
</div>
|
|
107
111
|
</label>
|
|
108
|
-
)
|
|
112
|
+
);
|
|
109
113
|
}
|
|
110
114
|
|
|
111
|
-
export { Checkbox, CheckboxCard }
|
|
115
|
+
export { Checkbox, CheckboxCard };
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Combobox — WealthX Design System
|
|
3
|
+
* Base: @base-ui/react/combobox
|
|
4
|
+
* WealthX overrides: square corners (rounded-none), design token colors,
|
|
5
|
+
* consistent styling with Select component, built-in search filtering.
|
|
6
|
+
*/
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import { CheckIcon, ChevronDownIcon, SearchIcon } from "lucide-react";
|
|
9
|
+
import { Combobox as ComboboxPrimitive } from "@base-ui/react/combobox";
|
|
10
|
+
|
|
11
|
+
import { cn } from "@/lib/utils";
|
|
12
|
+
|
|
13
|
+
export type ComboboxProps<
|
|
14
|
+
Value = string,
|
|
15
|
+
Multiple extends boolean | undefined = false,
|
|
16
|
+
> = React.ComponentProps<typeof ComboboxPrimitive.Root<Value, Multiple>>;
|
|
17
|
+
|
|
18
|
+
function Combobox<Value, Multiple extends boolean | undefined = false>({
|
|
19
|
+
...props
|
|
20
|
+
}: React.ComponentProps<typeof ComboboxPrimitive.Root<Value, Multiple>>) {
|
|
21
|
+
return <ComboboxPrimitive.Root data-slot="combobox" {...props} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type ComboboxTriggerProps = React.ComponentProps<
|
|
25
|
+
typeof ComboboxPrimitive.Trigger
|
|
26
|
+
> & {
|
|
27
|
+
size?: "sm" | "default";
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function ComboboxTrigger({
|
|
31
|
+
className,
|
|
32
|
+
size = "default",
|
|
33
|
+
children,
|
|
34
|
+
...props
|
|
35
|
+
}: ComboboxTriggerProps) {
|
|
36
|
+
return (
|
|
37
|
+
<ComboboxPrimitive.Trigger
|
|
38
|
+
data-slot="combobox-trigger"
|
|
39
|
+
data-size={size}
|
|
40
|
+
className={cn(
|
|
41
|
+
"flex w-fit items-center justify-between gap-2 border border-input bg-transparent px-3 py-2 text-body-small whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/20 data-[popup-open]:border-primary data-[popup-open]:ring-[3px] data-[popup-open]:ring-primary/20 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:font-normal data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=combobox-value]:line-clamp-1 *:data-[slot=combobox-value]:flex *:data-[slot=combobox-value]:items-center *:data-[slot=combobox-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
42
|
+
className,
|
|
43
|
+
)}
|
|
44
|
+
{...props}
|
|
45
|
+
>
|
|
46
|
+
{children}
|
|
47
|
+
<ComboboxPrimitive.Icon className="transition-transform duration-200 data-[popup-open]:rotate-180">
|
|
48
|
+
<ChevronDownIcon className="size-4 opacity-50" />
|
|
49
|
+
</ComboboxPrimitive.Icon>
|
|
50
|
+
</ComboboxPrimitive.Trigger>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type ComboboxValueProps = React.ComponentProps<
|
|
55
|
+
typeof ComboboxPrimitive.Value
|
|
56
|
+
>;
|
|
57
|
+
|
|
58
|
+
function ComboboxValue({ ...props }: ComboboxValueProps) {
|
|
59
|
+
return <ComboboxPrimitive.Value data-slot="combobox-value" {...props} />;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type ComboboxInputProps = React.ComponentProps<
|
|
63
|
+
typeof ComboboxPrimitive.Input
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
function ComboboxInput({ className, ...props }: ComboboxInputProps) {
|
|
67
|
+
return (
|
|
68
|
+
<div
|
|
69
|
+
data-slot="combobox-input-wrapper"
|
|
70
|
+
className="flex items-center gap-2 border-b border-border px-3"
|
|
71
|
+
>
|
|
72
|
+
<SearchIcon className="size-4 shrink-0 text-muted-foreground" />
|
|
73
|
+
<ComboboxPrimitive.Input
|
|
74
|
+
data-slot="combobox-input"
|
|
75
|
+
className={cn(
|
|
76
|
+
"h-9 w-full min-w-0 bg-transparent py-1 text-body-small outline-none placeholder:font-normal placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
77
|
+
className,
|
|
78
|
+
)}
|
|
79
|
+
{...props}
|
|
80
|
+
/>
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type ComboboxContentProps = React.ComponentProps<
|
|
86
|
+
typeof ComboboxPrimitive.Popup
|
|
87
|
+
>;
|
|
88
|
+
|
|
89
|
+
function ComboboxContent({
|
|
90
|
+
className,
|
|
91
|
+
children,
|
|
92
|
+
...props
|
|
93
|
+
}: ComboboxContentProps) {
|
|
94
|
+
return (
|
|
95
|
+
<ComboboxPrimitive.Portal>
|
|
96
|
+
<ComboboxPrimitive.Positioner sideOffset={4} align="start">
|
|
97
|
+
<ComboboxPrimitive.Popup
|
|
98
|
+
data-slot="combobox-content"
|
|
99
|
+
className={cn(
|
|
100
|
+
"relative z-50 max-h-[var(--available-height)] min-w-[8rem] overflow-hidden border bg-popover text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[ending-style]:animate-out data-[ending-style]:fade-out-0 data-[ending-style]:zoom-out-95 data-[open]:animate-in data-[open]:fade-in-0 data-[open]:zoom-in-95",
|
|
101
|
+
className,
|
|
102
|
+
)}
|
|
103
|
+
{...props}
|
|
104
|
+
>
|
|
105
|
+
{children}
|
|
106
|
+
</ComboboxPrimitive.Popup>
|
|
107
|
+
</ComboboxPrimitive.Positioner>
|
|
108
|
+
</ComboboxPrimitive.Portal>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export type ComboboxListProps = React.ComponentProps<
|
|
113
|
+
typeof ComboboxPrimitive.List
|
|
114
|
+
>;
|
|
115
|
+
|
|
116
|
+
function ComboboxList({ className, ...props }: ComboboxListProps) {
|
|
117
|
+
return (
|
|
118
|
+
<ComboboxPrimitive.List
|
|
119
|
+
data-slot="combobox-list"
|
|
120
|
+
className={cn(
|
|
121
|
+
"max-h-[min(var(--available-height),18rem)] overflow-y-auto p-1",
|
|
122
|
+
className,
|
|
123
|
+
)}
|
|
124
|
+
{...props}
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export type ComboboxItemProps = React.ComponentProps<
|
|
130
|
+
typeof ComboboxPrimitive.Item
|
|
131
|
+
>;
|
|
132
|
+
|
|
133
|
+
function ComboboxItem({ className, children, ...props }: ComboboxItemProps) {
|
|
134
|
+
return (
|
|
135
|
+
<ComboboxPrimitive.Item
|
|
136
|
+
data-slot="combobox-item"
|
|
137
|
+
className={cn(
|
|
138
|
+
"relative flex w-full cursor-default items-center gap-2 py-1.5 pr-8 pl-2 text-body-small outline-hidden select-none data-highlighted:bg-primary/5 data-highlighted:text-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
139
|
+
className,
|
|
140
|
+
)}
|
|
141
|
+
{...props}
|
|
142
|
+
>
|
|
143
|
+
<span
|
|
144
|
+
data-slot="combobox-item-indicator"
|
|
145
|
+
className="absolute right-2 flex size-3.5 items-center justify-center"
|
|
146
|
+
>
|
|
147
|
+
<ComboboxPrimitive.ItemIndicator>
|
|
148
|
+
<CheckIcon className="size-4" />
|
|
149
|
+
</ComboboxPrimitive.ItemIndicator>
|
|
150
|
+
</span>
|
|
151
|
+
{children}
|
|
152
|
+
</ComboboxPrimitive.Item>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export type ComboboxEmptyProps = React.ComponentProps<
|
|
157
|
+
typeof ComboboxPrimitive.Empty
|
|
158
|
+
>;
|
|
159
|
+
|
|
160
|
+
function ComboboxEmpty({ className, ...props }: ComboboxEmptyProps) {
|
|
161
|
+
return (
|
|
162
|
+
<ComboboxPrimitive.Empty
|
|
163
|
+
data-slot="combobox-empty"
|
|
164
|
+
className={cn(
|
|
165
|
+
"text-body-small py-6 text-center text-muted-foreground empty:hidden",
|
|
166
|
+
className,
|
|
167
|
+
)}
|
|
168
|
+
{...props}
|
|
169
|
+
/>
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export type ComboboxGroupProps = React.ComponentProps<
|
|
174
|
+
typeof ComboboxPrimitive.Group
|
|
175
|
+
>;
|
|
176
|
+
|
|
177
|
+
function ComboboxGroup({ ...props }: ComboboxGroupProps) {
|
|
178
|
+
return <ComboboxPrimitive.Group data-slot="combobox-group" {...props} />;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export type ComboboxGroupLabelProps = React.ComponentProps<
|
|
182
|
+
typeof ComboboxPrimitive.GroupLabel
|
|
183
|
+
>;
|
|
184
|
+
|
|
185
|
+
function ComboboxGroupLabel({ className, ...props }: ComboboxGroupLabelProps) {
|
|
186
|
+
return (
|
|
187
|
+
<ComboboxPrimitive.GroupLabel
|
|
188
|
+
data-slot="combobox-group-label"
|
|
189
|
+
className={cn(
|
|
190
|
+
"text-label-small px-2 py-1.5 uppercase text-muted-foreground",
|
|
191
|
+
className,
|
|
192
|
+
)}
|
|
193
|
+
{...props}
|
|
194
|
+
/>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export type ComboboxSeparatorProps = React.ComponentProps<"div">;
|
|
199
|
+
|
|
200
|
+
function ComboboxSeparator({ className, ...props }: ComboboxSeparatorProps) {
|
|
201
|
+
return (
|
|
202
|
+
<div
|
|
203
|
+
role="separator"
|
|
204
|
+
data-slot="combobox-separator"
|
|
205
|
+
className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
|
|
206
|
+
{...props}
|
|
207
|
+
/>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export {
|
|
212
|
+
Combobox,
|
|
213
|
+
ComboboxTrigger,
|
|
214
|
+
ComboboxValue,
|
|
215
|
+
ComboboxInput,
|
|
216
|
+
ComboboxContent,
|
|
217
|
+
ComboboxList,
|
|
218
|
+
ComboboxItem,
|
|
219
|
+
ComboboxEmpty,
|
|
220
|
+
ComboboxGroup,
|
|
221
|
+
ComboboxGroupLabel,
|
|
222
|
+
ComboboxSeparator,
|
|
223
|
+
};
|