@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,408 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Bot, RotateCcw, Send, X } from "lucide-react";
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
import { Sheet, SheetContent } from "@/components/ui/sheet";
|
|
5
|
+
import { Button } from "@/components/ui/button";
|
|
6
|
+
import { Badge } from "@/components/ui/badge";
|
|
7
|
+
import { Spinner } from "@/components/ui/spinner";
|
|
8
|
+
import { Textarea } from "@/components/ui/textarea";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* AiAssistantDrawer — WealthX DS (L5 Drawer)
|
|
12
|
+
*
|
|
13
|
+
* Right-side panel that provides an AI conversation interface for a specific
|
|
14
|
+
* opportunity/deal. Used in the Pipeline board via the "Launch Assistant" button
|
|
15
|
+
* on OpportunityCard.
|
|
16
|
+
*
|
|
17
|
+
* Layout:
|
|
18
|
+
* • Header — bot icon + title + reload + close
|
|
19
|
+
* • Content — empty state (task suggestions) or chat message list
|
|
20
|
+
* • Footer — textarea input + send button
|
|
21
|
+
*
|
|
22
|
+
* Pure display component: all message state and API calls are managed by the
|
|
23
|
+
* consuming page. The drawer only handles local `inputValue` state.
|
|
24
|
+
*
|
|
25
|
+
* Data source: `ai-chat.ts` / `conversation.ts` hooks in the backoffice
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Types
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
export interface AiChatMessage {
|
|
33
|
+
id: string;
|
|
34
|
+
role: "user" | "assistant";
|
|
35
|
+
content: string;
|
|
36
|
+
/** True while the assistant response is still streaming in. */
|
|
37
|
+
isStreaming?: boolean;
|
|
38
|
+
/** True if the message failed to send or receive. */
|
|
39
|
+
isErrored?: boolean;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface AiTaskSuggestion {
|
|
43
|
+
id: string;
|
|
44
|
+
/** Short label shown as the suggestion title. */
|
|
45
|
+
title: string;
|
|
46
|
+
/** Supporting description shown below the title. */
|
|
47
|
+
description: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface AiAssistantDrawerProps {
|
|
51
|
+
open: boolean;
|
|
52
|
+
onClose: () => void;
|
|
53
|
+
/** Opportunity or contact name shown in the header subtitle. */
|
|
54
|
+
opportunityName?: string;
|
|
55
|
+
/**
|
|
56
|
+
* Suggested tasks shown in the empty state.
|
|
57
|
+
* Typically the opportunity's incomplete tasks.
|
|
58
|
+
* Clicking a suggestion pre-fills the input.
|
|
59
|
+
*/
|
|
60
|
+
taskSuggestions?: AiTaskSuggestion[];
|
|
61
|
+
/** Chat message history. Empty array = show empty/welcome state. */
|
|
62
|
+
messages?: AiChatMessage[];
|
|
63
|
+
/** True while the assistant is generating a response. */
|
|
64
|
+
isStreaming?: boolean;
|
|
65
|
+
/** True while initial data is loading (shows full-panel spinner). */
|
|
66
|
+
isLoading?: boolean;
|
|
67
|
+
/** Called when the user submits a message. Input is cleared after this fires. */
|
|
68
|
+
onSendMessage?: (text: string) => void;
|
|
69
|
+
/** Called when the user clicks the reload/reset button. */
|
|
70
|
+
onReset?: () => void;
|
|
71
|
+
className?: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Typing indicator (three bouncing dots)
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
|
|
78
|
+
function AiTypingIndicator() {
|
|
79
|
+
return (
|
|
80
|
+
<span className="flex items-center gap-1 py-1" aria-label="AI is thinking">
|
|
81
|
+
{[0, 150, 300].map((delay) => (
|
|
82
|
+
<span
|
|
83
|
+
key={delay}
|
|
84
|
+
className="size-1.5 rounded-full bg-current animate-bounce"
|
|
85
|
+
style={{ animationDelay: `${delay}ms` }}
|
|
86
|
+
aria-hidden="true"
|
|
87
|
+
/>
|
|
88
|
+
))}
|
|
89
|
+
</span>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
// Chat message bubble
|
|
95
|
+
// ---------------------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
function AiChatBubble({ message }: { message: AiChatMessage }) {
|
|
98
|
+
const isUser = message.role === "user";
|
|
99
|
+
const isEmpty = !message.content.trim();
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<div
|
|
103
|
+
className={cn("flex w-full", isUser ? "justify-end" : "justify-start")}
|
|
104
|
+
>
|
|
105
|
+
<div
|
|
106
|
+
className={cn(
|
|
107
|
+
"max-w-[85%] px-3 py-2 text-sm",
|
|
108
|
+
isUser
|
|
109
|
+
? "bg-primary text-primary-foreground"
|
|
110
|
+
: "bg-muted text-foreground",
|
|
111
|
+
message.isErrored && "bg-destructive/10 text-destructive",
|
|
112
|
+
)}
|
|
113
|
+
>
|
|
114
|
+
{/* Content or streaming indicators */}
|
|
115
|
+
{isEmpty && message.isStreaming ? (
|
|
116
|
+
<AiTypingIndicator />
|
|
117
|
+
) : (
|
|
118
|
+
<span className="whitespace-pre-wrap break-words leading-relaxed">
|
|
119
|
+
{message.content}
|
|
120
|
+
</span>
|
|
121
|
+
)}
|
|
122
|
+
{message.isErrored && (
|
|
123
|
+
<p className="mt-1 text-xs opacity-70">
|
|
124
|
+
Failed to send. Please try again.
|
|
125
|
+
</p>
|
|
126
|
+
)}
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
// Task suggestion card
|
|
134
|
+
// ---------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
function AiTaskCard({
|
|
137
|
+
suggestion,
|
|
138
|
+
onSelect,
|
|
139
|
+
}: {
|
|
140
|
+
suggestion: AiTaskSuggestion;
|
|
141
|
+
onSelect: (text: string) => void;
|
|
142
|
+
}) {
|
|
143
|
+
return (
|
|
144
|
+
<button
|
|
145
|
+
type="button"
|
|
146
|
+
onClick={() => onSelect(suggestion.title)}
|
|
147
|
+
className="flex flex-col gap-1 border border-border bg-background p-3 text-left transition-colors hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
148
|
+
>
|
|
149
|
+
<span className="text-sm font-medium text-foreground">
|
|
150
|
+
{suggestion.title}
|
|
151
|
+
</span>
|
|
152
|
+
<span className="text-xs text-muted-foreground">
|
|
153
|
+
{suggestion.description}
|
|
154
|
+
</span>
|
|
155
|
+
</button>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// AiAssistantDrawer
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
|
|
163
|
+
const DEFAULT_SUGGESTIONS: AiTaskSuggestion[] = [
|
|
164
|
+
{
|
|
165
|
+
id: "s1",
|
|
166
|
+
title: "Update pricing strategy",
|
|
167
|
+
description: "Review and adjust pricing based on market trends",
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: "s2",
|
|
171
|
+
title: "Enhance marketing outreach",
|
|
172
|
+
description: "Develop new campaigns to increase customer engagement",
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
id: "s3",
|
|
176
|
+
title: "Optimise social media strategy",
|
|
177
|
+
description: "Analyse performance and adjust content for better visibility",
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
id: "s4",
|
|
181
|
+
title: "Implement customer feedback loops",
|
|
182
|
+
description: "Create mechanisms to collect and act on customer insights",
|
|
183
|
+
},
|
|
184
|
+
];
|
|
185
|
+
|
|
186
|
+
export function AiAssistantDrawer({
|
|
187
|
+
open,
|
|
188
|
+
onClose,
|
|
189
|
+
opportunityName,
|
|
190
|
+
taskSuggestions,
|
|
191
|
+
messages = [],
|
|
192
|
+
isStreaming = false,
|
|
193
|
+
isLoading = false,
|
|
194
|
+
onSendMessage,
|
|
195
|
+
onReset,
|
|
196
|
+
className,
|
|
197
|
+
}: AiAssistantDrawerProps) {
|
|
198
|
+
const [inputValue, setInputValue] = React.useState("");
|
|
199
|
+
const messagesEndRef = React.useRef<HTMLDivElement>(null);
|
|
200
|
+
const textareaRef = React.useRef<HTMLTextAreaElement>(null);
|
|
201
|
+
|
|
202
|
+
const suggestions = taskSuggestions ?? DEFAULT_SUGGESTIONS;
|
|
203
|
+
const hasMessages = messages.length > 0;
|
|
204
|
+
const canSend = inputValue.trim().length > 0 && !isStreaming && !isLoading;
|
|
205
|
+
|
|
206
|
+
// Auto-scroll to latest message
|
|
207
|
+
React.useEffect(() => {
|
|
208
|
+
if (!messagesEndRef.current) return;
|
|
209
|
+
messagesEndRef.current.scrollIntoView({
|
|
210
|
+
behavior: "smooth",
|
|
211
|
+
block: "nearest",
|
|
212
|
+
});
|
|
213
|
+
}, [messages.length]);
|
|
214
|
+
|
|
215
|
+
// Auto-resize textarea on value change
|
|
216
|
+
React.useEffect(() => {
|
|
217
|
+
const el = textareaRef.current;
|
|
218
|
+
if (!el) return;
|
|
219
|
+
el.style.height = "auto";
|
|
220
|
+
el.style.height = `${Math.min(el.scrollHeight, 120)}px`;
|
|
221
|
+
}, [inputValue]);
|
|
222
|
+
|
|
223
|
+
const handleSend = React.useCallback(() => {
|
|
224
|
+
const text = inputValue.trim();
|
|
225
|
+
if (!text || !canSend) return;
|
|
226
|
+
onSendMessage?.(text);
|
|
227
|
+
setInputValue("");
|
|
228
|
+
}, [inputValue, canSend, onSendMessage]);
|
|
229
|
+
|
|
230
|
+
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
|
|
231
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
232
|
+
e.preventDefault();
|
|
233
|
+
handleSend();
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const handleSuggestionSelect = (text: string) => {
|
|
238
|
+
setInputValue(text);
|
|
239
|
+
textareaRef.current?.focus();
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
return (
|
|
243
|
+
<Sheet open={open} onOpenChange={(o) => !o && onClose()}>
|
|
244
|
+
<SheetContent
|
|
245
|
+
side="right"
|
|
246
|
+
showCloseButton={false}
|
|
247
|
+
className={cn("w-[480px] max-w-full gap-0 p-0", className)}
|
|
248
|
+
data-slot="ai-assistant-drawer"
|
|
249
|
+
>
|
|
250
|
+
{/* Header */}
|
|
251
|
+
<div className="flex items-center justify-between border-b border-border px-4 py-3">
|
|
252
|
+
<div className="flex items-center gap-3">
|
|
253
|
+
<span className="flex size-8 shrink-0 items-center justify-center rounded-full bg-primary">
|
|
254
|
+
<Bot className="size-4 text-primary-foreground" />
|
|
255
|
+
</span>
|
|
256
|
+
<div className="flex flex-col">
|
|
257
|
+
<span className="text-sm font-semibold text-foreground">
|
|
258
|
+
AI Assistant
|
|
259
|
+
</span>
|
|
260
|
+
{opportunityName && (
|
|
261
|
+
<span className="text-xs text-muted-foreground">
|
|
262
|
+
{opportunityName}
|
|
263
|
+
</span>
|
|
264
|
+
)}
|
|
265
|
+
</div>
|
|
266
|
+
</div>
|
|
267
|
+
<div className="flex items-center gap-1">
|
|
268
|
+
{onReset && (
|
|
269
|
+
<Button
|
|
270
|
+
variant="ghost"
|
|
271
|
+
size="icon"
|
|
272
|
+
className="size-8"
|
|
273
|
+
onClick={onReset}
|
|
274
|
+
title="Reset conversation"
|
|
275
|
+
disabled={isLoading}
|
|
276
|
+
>
|
|
277
|
+
<RotateCcw className="size-4" />
|
|
278
|
+
<span className="sr-only">Reset conversation</span>
|
|
279
|
+
</Button>
|
|
280
|
+
)}
|
|
281
|
+
<Button
|
|
282
|
+
variant="ghost"
|
|
283
|
+
size="icon"
|
|
284
|
+
className="size-8"
|
|
285
|
+
onClick={onClose}
|
|
286
|
+
title="Close"
|
|
287
|
+
>
|
|
288
|
+
<X className="size-4" />
|
|
289
|
+
<span className="sr-only">Close</span>
|
|
290
|
+
</Button>
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
|
|
294
|
+
{/* Content */}
|
|
295
|
+
<div className="flex flex-1 flex-col overflow-y-auto">
|
|
296
|
+
{isLoading ? (
|
|
297
|
+
/* Loading state */
|
|
298
|
+
<div className="flex flex-1 items-center justify-center py-20">
|
|
299
|
+
<div className="flex flex-col items-center gap-3">
|
|
300
|
+
<Spinner size="lg" className="text-muted-foreground" />
|
|
301
|
+
<p className="text-sm text-muted-foreground">Initialising…</p>
|
|
302
|
+
</div>
|
|
303
|
+
</div>
|
|
304
|
+
) : !hasMessages ? (
|
|
305
|
+
/* Empty / welcome state */
|
|
306
|
+
<div className="flex flex-col gap-6 p-4">
|
|
307
|
+
{/* Hero card */}
|
|
308
|
+
<div className="flex flex-col gap-3 border border-border bg-muted/30 p-4">
|
|
309
|
+
<Badge variant="outline" className="w-fit gap-1.5">
|
|
310
|
+
<span
|
|
311
|
+
className="size-1.5 rounded-full bg-primary"
|
|
312
|
+
aria-hidden="true"
|
|
313
|
+
/>
|
|
314
|
+
AI Chat for Brokers
|
|
315
|
+
</Badge>
|
|
316
|
+
<p className="text-sm text-muted-foreground">
|
|
317
|
+
A safe and secure way to chat about insights that run your
|
|
318
|
+
business and utilise AI. All chats stay within your
|
|
319
|
+
environment, all closed off and compliant.
|
|
320
|
+
</p>
|
|
321
|
+
<div className="flex gap-2">
|
|
322
|
+
{(
|
|
323
|
+
[
|
|
324
|
+
{ emoji: "🤖", label: "Smart" },
|
|
325
|
+
{ emoji: "⚡", label: "Fast" },
|
|
326
|
+
{ emoji: "🔒", label: "Secure" },
|
|
327
|
+
] as const
|
|
328
|
+
).map(({ emoji, label }) => (
|
|
329
|
+
<span
|
|
330
|
+
key={label}
|
|
331
|
+
className="border border-border px-2.5 py-1 text-xs text-foreground"
|
|
332
|
+
>
|
|
333
|
+
{emoji} {label}
|
|
334
|
+
</span>
|
|
335
|
+
))}
|
|
336
|
+
</div>
|
|
337
|
+
</div>
|
|
338
|
+
|
|
339
|
+
{/* Task suggestions */}
|
|
340
|
+
{suggestions.length > 0 && (
|
|
341
|
+
<div className="flex flex-col gap-2">
|
|
342
|
+
<p className="text-xs font-medium text-muted-foreground">
|
|
343
|
+
Suggested tasks
|
|
344
|
+
</p>
|
|
345
|
+
<div className="grid grid-cols-2 gap-2">
|
|
346
|
+
{suggestions.map((s) => (
|
|
347
|
+
<AiTaskCard
|
|
348
|
+
key={s.id}
|
|
349
|
+
suggestion={s}
|
|
350
|
+
onSelect={handleSuggestionSelect}
|
|
351
|
+
/>
|
|
352
|
+
))}
|
|
353
|
+
</div>
|
|
354
|
+
</div>
|
|
355
|
+
)}
|
|
356
|
+
</div>
|
|
357
|
+
) : (
|
|
358
|
+
/* Message list */
|
|
359
|
+
<div className="flex flex-col gap-3 p-4">
|
|
360
|
+
{messages.map((msg) => (
|
|
361
|
+
<AiChatBubble key={msg.id} message={msg} />
|
|
362
|
+
))}
|
|
363
|
+
{/* Streaming indicator when last message is user's */}
|
|
364
|
+
{isStreaming &&
|
|
365
|
+
messages[messages.length - 1]?.role === "user" && (
|
|
366
|
+
<div className="flex justify-start">
|
|
367
|
+
<div className="bg-muted px-3 py-2 text-muted-foreground">
|
|
368
|
+
<AiTypingIndicator />
|
|
369
|
+
</div>
|
|
370
|
+
</div>
|
|
371
|
+
)}
|
|
372
|
+
<div ref={messagesEndRef} />
|
|
373
|
+
</div>
|
|
374
|
+
)}
|
|
375
|
+
</div>
|
|
376
|
+
|
|
377
|
+
{/* Footer — input bar */}
|
|
378
|
+
<div className="border-t border-border p-3">
|
|
379
|
+
<div className="flex items-end gap-2">
|
|
380
|
+
<Textarea
|
|
381
|
+
ref={textareaRef}
|
|
382
|
+
value={inputValue}
|
|
383
|
+
onChange={(e) => setInputValue(e.target.value)}
|
|
384
|
+
onKeyDown={handleKeyDown}
|
|
385
|
+
placeholder="Ask me anything… (Enter to send, Shift+Enter for new line)"
|
|
386
|
+
rows={1}
|
|
387
|
+
disabled={isLoading}
|
|
388
|
+
className="min-h-0 flex-1 resize-none overflow-hidden py-2 text-sm"
|
|
389
|
+
/>
|
|
390
|
+
<Button
|
|
391
|
+
size="icon"
|
|
392
|
+
onClick={handleSend}
|
|
393
|
+
disabled={!canSend}
|
|
394
|
+
className="shrink-0"
|
|
395
|
+
title="Send"
|
|
396
|
+
>
|
|
397
|
+
<Send className="size-4" />
|
|
398
|
+
<span className="sr-only">Send message</span>
|
|
399
|
+
</Button>
|
|
400
|
+
</div>
|
|
401
|
+
<p className="mt-1.5 text-[10px] text-muted-foreground">
|
|
402
|
+
Enter to send · Shift+Enter for new line
|
|
403
|
+
</p>
|
|
404
|
+
</div>
|
|
405
|
+
</SheetContent>
|
|
406
|
+
</Sheet>
|
|
407
|
+
);
|
|
408
|
+
}
|
|
@@ -8,42 +8,46 @@
|
|
|
8
8
|
* - AlertDialogFooter: always row, right-aligned; `border-t border-border pt-4` separator
|
|
9
9
|
* - AlertDialogMedia: borderless icon slot — `size-10` default, `size-8` sm
|
|
10
10
|
*/
|
|
11
|
-
import { type ReactElement } from "react"
|
|
12
|
-
import * as React from "react"
|
|
13
|
-
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog"
|
|
14
|
-
import { cn } from "@/lib/utils"
|
|
15
|
-
import { useThemeVars } from "@/lib/theme-provider"
|
|
16
|
-
import { buttonVariants } from "@/components/ui/button"
|
|
11
|
+
import { type ReactElement } from "react";
|
|
12
|
+
import * as React from "react";
|
|
13
|
+
import { AlertDialog as AlertDialogPrimitive } from "@base-ui/react/alert-dialog";
|
|
14
|
+
import { cn } from "@/lib/utils";
|
|
15
|
+
import { useThemeVars } from "@/lib/theme-provider";
|
|
16
|
+
import { buttonVariants } from "@/components/ui/button";
|
|
17
17
|
|
|
18
|
-
export type AlertDialogProps = React.ComponentProps<
|
|
18
|
+
export type AlertDialogProps = React.ComponentProps<
|
|
19
|
+
typeof AlertDialogPrimitive.Root
|
|
20
|
+
>;
|
|
19
21
|
|
|
20
|
-
function AlertDialog({
|
|
21
|
-
...props
|
|
22
|
-
}: AlertDialogProps): ReactElement {
|
|
23
|
-
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />
|
|
22
|
+
function AlertDialog({ ...props }: AlertDialogProps): ReactElement {
|
|
23
|
+
return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export type AlertDialogTriggerProps = React.ComponentProps<
|
|
26
|
+
export type AlertDialogTriggerProps = React.ComponentProps<
|
|
27
|
+
typeof AlertDialogPrimitive.Trigger
|
|
28
|
+
>;
|
|
27
29
|
|
|
28
30
|
function AlertDialogTrigger({
|
|
29
31
|
...props
|
|
30
32
|
}: AlertDialogTriggerProps): ReactElement {
|
|
31
33
|
return (
|
|
32
34
|
<AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
|
|
33
|
-
)
|
|
35
|
+
);
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
export type AlertDialogPortalProps = React.ComponentProps<
|
|
38
|
+
export type AlertDialogPortalProps = React.ComponentProps<
|
|
39
|
+
typeof AlertDialogPrimitive.Portal
|
|
40
|
+
>;
|
|
37
41
|
|
|
38
|
-
function AlertDialogPortal({
|
|
39
|
-
...props
|
|
40
|
-
}: AlertDialogPortalProps): ReactElement {
|
|
42
|
+
function AlertDialogPortal({ ...props }: AlertDialogPortalProps): ReactElement {
|
|
41
43
|
return (
|
|
42
44
|
<AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
|
|
43
|
-
)
|
|
45
|
+
);
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
export type AlertDialogOverlayProps = React.ComponentProps<
|
|
48
|
+
export type AlertDialogOverlayProps = React.ComponentProps<
|
|
49
|
+
typeof AlertDialogPrimitive.Backdrop
|
|
50
|
+
>;
|
|
47
51
|
|
|
48
52
|
function AlertDialogOverlay({
|
|
49
53
|
className,
|
|
@@ -54,17 +58,19 @@ function AlertDialogOverlay({
|
|
|
54
58
|
className={cn(
|
|
55
59
|
// WealthX: foreground/50 scrim — matches Figma foreground token at 50% opacity
|
|
56
60
|
"fixed inset-0 z-50 bg-foreground/50 data-ending-style:animate-out data-ending-style:fade-out-0 data-ending-style:fill-mode-forwards data-open:animate-in data-open:fade-in-0",
|
|
57
|
-
className
|
|
61
|
+
className,
|
|
58
62
|
)}
|
|
59
63
|
data-slot="alert-dialog-overlay"
|
|
60
64
|
{...props}
|
|
61
65
|
/>
|
|
62
|
-
)
|
|
66
|
+
);
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
export type AlertDialogContentProps = React.ComponentProps<
|
|
66
|
-
|
|
67
|
-
|
|
69
|
+
export type AlertDialogContentProps = React.ComponentProps<
|
|
70
|
+
typeof AlertDialogPrimitive.Popup
|
|
71
|
+
> & {
|
|
72
|
+
size?: "default" | "sm";
|
|
73
|
+
};
|
|
68
74
|
|
|
69
75
|
function AlertDialogContent({
|
|
70
76
|
className,
|
|
@@ -80,7 +86,7 @@ function AlertDialogContent({
|
|
|
80
86
|
className={cn(
|
|
81
87
|
// WealthX: removed rounded-lg (sharp corners), shadow-lg (flat panels)
|
|
82
88
|
"group/alert-dialog-content fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 duration-200 data-[size=sm]:max-w-xs data-ending-style:animate-out data-ending-style:fade-out-0 data-ending-style:zoom-out-95 data-ending-style:fill-mode-forwards data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[size=default]:sm:max-w-lg",
|
|
83
|
-
className
|
|
89
|
+
className,
|
|
84
90
|
)}
|
|
85
91
|
data-size={size}
|
|
86
92
|
data-slot="alert-dialog-content"
|
|
@@ -88,10 +94,10 @@ function AlertDialogContent({
|
|
|
88
94
|
{...props}
|
|
89
95
|
/>
|
|
90
96
|
</AlertDialogPortal>
|
|
91
|
-
)
|
|
97
|
+
);
|
|
92
98
|
}
|
|
93
99
|
|
|
94
|
-
export type AlertDialogHeaderProps = React.ComponentProps<"div"
|
|
100
|
+
export type AlertDialogHeaderProps = React.ComponentProps<"div">;
|
|
95
101
|
|
|
96
102
|
function AlertDialogHeader({
|
|
97
103
|
className,
|
|
@@ -101,15 +107,15 @@ function AlertDialogHeader({
|
|
|
101
107
|
<div
|
|
102
108
|
className={cn(
|
|
103
109
|
"grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
|
|
104
|
-
className
|
|
110
|
+
className,
|
|
105
111
|
)}
|
|
106
112
|
data-slot="alert-dialog-header"
|
|
107
113
|
{...props}
|
|
108
114
|
/>
|
|
109
|
-
)
|
|
115
|
+
);
|
|
110
116
|
}
|
|
111
117
|
|
|
112
|
-
export type AlertDialogFooterProps = React.ComponentProps<"div"
|
|
118
|
+
export type AlertDialogFooterProps = React.ComponentProps<"div">;
|
|
113
119
|
|
|
114
120
|
function AlertDialogFooter({
|
|
115
121
|
className,
|
|
@@ -120,15 +126,17 @@ function AlertDialogFooter({
|
|
|
120
126
|
className={cn(
|
|
121
127
|
// WealthX: always row, right-aligned, separator above footer (matches Figma)
|
|
122
128
|
"flex flex-row justify-end gap-2 border-t border-border pt-4",
|
|
123
|
-
className
|
|
129
|
+
className,
|
|
124
130
|
)}
|
|
125
131
|
data-slot="alert-dialog-footer"
|
|
126
132
|
{...props}
|
|
127
133
|
/>
|
|
128
|
-
)
|
|
134
|
+
);
|
|
129
135
|
}
|
|
130
136
|
|
|
131
|
-
export type AlertDialogTitleProps = React.ComponentProps<
|
|
137
|
+
export type AlertDialogTitleProps = React.ComponentProps<
|
|
138
|
+
typeof AlertDialogPrimitive.Title
|
|
139
|
+
>;
|
|
132
140
|
|
|
133
141
|
function AlertDialogTitle({
|
|
134
142
|
className,
|
|
@@ -137,16 +145,18 @@ function AlertDialogTitle({
|
|
|
137
145
|
return (
|
|
138
146
|
<AlertDialogPrimitive.Title
|
|
139
147
|
className={cn(
|
|
140
|
-
"text-
|
|
141
|
-
className
|
|
148
|
+
"text-h5 sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
|
|
149
|
+
className,
|
|
142
150
|
)}
|
|
143
151
|
data-slot="alert-dialog-title"
|
|
144
152
|
{...props}
|
|
145
153
|
/>
|
|
146
|
-
)
|
|
154
|
+
);
|
|
147
155
|
}
|
|
148
156
|
|
|
149
|
-
export type AlertDialogDescriptionProps = React.ComponentProps<
|
|
157
|
+
export type AlertDialogDescriptionProps = React.ComponentProps<
|
|
158
|
+
typeof AlertDialogPrimitive.Description
|
|
159
|
+
>;
|
|
150
160
|
|
|
151
161
|
function AlertDialogDescription({
|
|
152
162
|
className,
|
|
@@ -155,16 +165,16 @@ function AlertDialogDescription({
|
|
|
155
165
|
return (
|
|
156
166
|
<AlertDialogPrimitive.Description
|
|
157
167
|
className={cn(
|
|
158
|
-
"text-
|
|
159
|
-
className
|
|
168
|
+
"text-body-small text-muted-foreground sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
|
|
169
|
+
className,
|
|
160
170
|
)}
|
|
161
171
|
data-slot="alert-dialog-description"
|
|
162
172
|
{...props}
|
|
163
173
|
/>
|
|
164
|
-
)
|
|
174
|
+
);
|
|
165
175
|
}
|
|
166
176
|
|
|
167
|
-
export type AlertDialogMediaProps = React.ComponentProps<"div"
|
|
177
|
+
export type AlertDialogMediaProps = React.ComponentProps<"div">;
|
|
168
178
|
|
|
169
179
|
function AlertDialogMedia({
|
|
170
180
|
className,
|
|
@@ -175,18 +185,26 @@ function AlertDialogMedia({
|
|
|
175
185
|
className={cn(
|
|
176
186
|
// WealthX: borderless icon slot — size-10 default, size-8 sm
|
|
177
187
|
"mb-2 inline-flex size-10 items-center justify-center group-data-[size=sm]/alert-dialog-content:size-8 sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-5",
|
|
178
|
-
className
|
|
188
|
+
className,
|
|
179
189
|
)}
|
|
180
190
|
data-slot="alert-dialog-media"
|
|
181
191
|
{...props}
|
|
182
192
|
/>
|
|
183
|
-
)
|
|
193
|
+
);
|
|
184
194
|
}
|
|
185
195
|
|
|
186
|
-
export type AlertDialogActionProps = React.ComponentProps<
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
196
|
+
export type AlertDialogActionProps = React.ComponentProps<
|
|
197
|
+
typeof AlertDialogPrimitive.Close
|
|
198
|
+
> & {
|
|
199
|
+
variant?:
|
|
200
|
+
| "default"
|
|
201
|
+
| "destructive"
|
|
202
|
+
| "outline"
|
|
203
|
+
| "secondary"
|
|
204
|
+
| "ghost"
|
|
205
|
+
| "link";
|
|
206
|
+
size?: "default" | "sm" | "lg" | "xs" | "icon";
|
|
207
|
+
};
|
|
190
208
|
|
|
191
209
|
function AlertDialogAction({
|
|
192
210
|
className,
|
|
@@ -200,13 +218,21 @@ function AlertDialogAction({
|
|
|
200
218
|
data-slot="alert-dialog-action"
|
|
201
219
|
{...props}
|
|
202
220
|
/>
|
|
203
|
-
)
|
|
221
|
+
);
|
|
204
222
|
}
|
|
205
223
|
|
|
206
|
-
export type AlertDialogCancelProps = React.ComponentProps<
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
224
|
+
export type AlertDialogCancelProps = React.ComponentProps<
|
|
225
|
+
typeof AlertDialogPrimitive.Close
|
|
226
|
+
> & {
|
|
227
|
+
variant?:
|
|
228
|
+
| "default"
|
|
229
|
+
| "destructive"
|
|
230
|
+
| "outline"
|
|
231
|
+
| "secondary"
|
|
232
|
+
| "ghost"
|
|
233
|
+
| "link";
|
|
234
|
+
size?: "default" | "sm" | "lg" | "xs" | "icon";
|
|
235
|
+
};
|
|
210
236
|
|
|
211
237
|
function AlertDialogCancel({
|
|
212
238
|
className,
|
|
@@ -220,7 +246,7 @@ function AlertDialogCancel({
|
|
|
220
246
|
data-slot="alert-dialog-cancel"
|
|
221
247
|
{...props}
|
|
222
248
|
/>
|
|
223
|
-
)
|
|
249
|
+
);
|
|
224
250
|
}
|
|
225
251
|
|
|
226
252
|
export {
|
|
@@ -236,4 +262,4 @@ export {
|
|
|
236
262
|
AlertDialogPortal,
|
|
237
263
|
AlertDialogTitle,
|
|
238
264
|
AlertDialogTrigger,
|
|
239
|
-
}
|
|
265
|
+
};
|