@wealthx/shadcn 1.5.40 → 1.5.41
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 +84 -84
- package/CHANGELOG.md +6 -0
- package/dist/{chunk-MGIDYXOP.mjs → chunk-DWNLBUDC.mjs} +459 -67
- package/dist/{chunk-EFHPSKVF.mjs → chunk-EGM4DARZ.mjs} +110 -1
- package/dist/{chunk-STN5QIWN.mjs → chunk-GIQGZFP6.mjs} +102 -45
- package/dist/{chunk-B5PSUONN.mjs → chunk-TF5TOVIM.mjs} +1 -1
- package/dist/{chunk-RRROLESJ.mjs → chunk-XHZONBL4.mjs} +1 -1
- package/dist/components/ui/ai-assistant-drawer.js +101 -0
- package/dist/components/ui/ai-assistant-drawer.mjs +2 -2
- package/dist/components/ui/ai-conversations/index.js +101 -0
- package/dist/components/ui/ai-conversations/index.mjs +2 -2
- package/dist/components/ui/chat-input-area.js +101 -0
- package/dist/components/ui/chat-input-area.mjs +1 -1
- package/dist/components/ui/policy-ai/index.js +818 -261
- package/dist/components/ui/policy-ai/index.mjs +11 -2
- package/dist/components/ui/support-agent/index.js +202 -44
- package/dist/components/ui/support-agent/index.mjs +2 -2
- package/dist/index.js +3490 -3329
- package/dist/index.mjs +5 -5
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/src/components/ui/chat-input-area.tsx +181 -2
- package/src/components/ui/policy-ai/index.tsx +12 -0
- package/src/components/ui/policy-ai/policy-ai-context-sidebar.tsx +231 -0
- package/src/components/ui/policy-ai/policy-ai-history-panel.tsx +175 -0
- package/src/components/ui/policy-ai/policy-ai-page.tsx +243 -0
- package/src/components/ui/policy-ai/policy-ai-panel.tsx +64 -57
- package/src/components/ui/policy-ai/policy-ai-responses.tsx +8 -12
- package/src/components/ui/support-agent/support-agent-panel.tsx +124 -46
- package/src/styles/styles-css.ts +1 -1
|
@@ -10,9 +10,109 @@ import {
|
|
|
10
10
|
|
|
11
11
|
// src/components/ui/chat-input-area.tsx
|
|
12
12
|
import * as React from "react";
|
|
13
|
-
import {
|
|
13
|
+
import { flushSync } from "react-dom";
|
|
14
|
+
import {
|
|
15
|
+
Bold,
|
|
16
|
+
Code,
|
|
17
|
+
Code2,
|
|
18
|
+
ImagePlus,
|
|
19
|
+
Italic,
|
|
20
|
+
Paperclip,
|
|
21
|
+
Send
|
|
22
|
+
} from "lucide-react";
|
|
14
23
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
15
24
|
var DEFAULT_HINT = "Enter to send \xB7 Shift+Enter for new line";
|
|
25
|
+
var TOOLBAR_ITEMS = [
|
|
26
|
+
{
|
|
27
|
+
type: "button",
|
|
28
|
+
icon: Bold,
|
|
29
|
+
label: "Bold",
|
|
30
|
+
title: "Bold (Ctrl+B)",
|
|
31
|
+
before: "**",
|
|
32
|
+
after: "**",
|
|
33
|
+
placeholder: "bold text"
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: "button",
|
|
37
|
+
icon: Italic,
|
|
38
|
+
label: "Italic",
|
|
39
|
+
title: "Italic (Ctrl+I)",
|
|
40
|
+
before: "*",
|
|
41
|
+
after: "*",
|
|
42
|
+
placeholder: "italic text"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: "button",
|
|
46
|
+
icon: Code,
|
|
47
|
+
label: "Inline code",
|
|
48
|
+
title: "Inline code",
|
|
49
|
+
before: "`",
|
|
50
|
+
after: "`",
|
|
51
|
+
placeholder: "code"
|
|
52
|
+
},
|
|
53
|
+
{ type: "divider" },
|
|
54
|
+
{
|
|
55
|
+
type: "button",
|
|
56
|
+
icon: Code2,
|
|
57
|
+
label: "Code block",
|
|
58
|
+
title: "Code block",
|
|
59
|
+
before: "```\n",
|
|
60
|
+
after: "\n```",
|
|
61
|
+
placeholder: "code block"
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
function applyMarkdown(textarea, before, after, placeholder, onChange) {
|
|
65
|
+
const start = textarea.selectionStart;
|
|
66
|
+
const end = textarea.selectionEnd;
|
|
67
|
+
const selected = textarea.value.slice(start, end);
|
|
68
|
+
const insertion = selected || placeholder;
|
|
69
|
+
const next = textarea.value.slice(0, start) + before + insertion + after + textarea.value.slice(end);
|
|
70
|
+
const newStart = start + before.length;
|
|
71
|
+
const newEnd = newStart + insertion.length;
|
|
72
|
+
flushSync(() => onChange(next));
|
|
73
|
+
textarea.focus();
|
|
74
|
+
textarea.setSelectionRange(newStart, newEnd);
|
|
75
|
+
}
|
|
76
|
+
var MarkdownToolbar = React.memo(function MarkdownToolbar2({
|
|
77
|
+
textareaRef,
|
|
78
|
+
onChange,
|
|
79
|
+
disabled
|
|
80
|
+
}) {
|
|
81
|
+
const handleFormat = React.useCallback(
|
|
82
|
+
(e) => {
|
|
83
|
+
if (!textareaRef.current) return;
|
|
84
|
+
const { before, after, placeholder } = e.currentTarget.dataset;
|
|
85
|
+
applyMarkdown(textareaRef.current, before, after, placeholder, onChange);
|
|
86
|
+
},
|
|
87
|
+
[textareaRef, onChange]
|
|
88
|
+
);
|
|
89
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0.5 border-b border-border px-2 py-1", children: TOOLBAR_ITEMS.map(
|
|
90
|
+
(item, i) => item.type === "divider" ? /* @__PURE__ */ jsx(
|
|
91
|
+
"span",
|
|
92
|
+
{
|
|
93
|
+
className: "mx-0.5 h-3.5 w-px bg-border",
|
|
94
|
+
"aria-hidden": "true"
|
|
95
|
+
},
|
|
96
|
+
i
|
|
97
|
+
) : /* @__PURE__ */ jsx(
|
|
98
|
+
Button,
|
|
99
|
+
{
|
|
100
|
+
variant: "ghost",
|
|
101
|
+
size: "icon-sm",
|
|
102
|
+
type: "button",
|
|
103
|
+
title: item.title,
|
|
104
|
+
"aria-label": item.label,
|
|
105
|
+
disabled,
|
|
106
|
+
"data-before": item.before,
|
|
107
|
+
"data-after": item.after,
|
|
108
|
+
"data-placeholder": item.placeholder,
|
|
109
|
+
onClick: handleFormat,
|
|
110
|
+
children: /* @__PURE__ */ jsx(item.icon, { className: "size-3.5", "aria-hidden": "true" })
|
|
111
|
+
},
|
|
112
|
+
item.label
|
|
113
|
+
)
|
|
114
|
+
) });
|
|
115
|
+
});
|
|
16
116
|
function ChatInputArea({
|
|
17
117
|
value,
|
|
18
118
|
onChange,
|
|
@@ -24,6 +124,7 @@ function ChatInputArea({
|
|
|
24
124
|
hint = DEFAULT_HINT,
|
|
25
125
|
maxHeight = 160,
|
|
26
126
|
autoFocus = false,
|
|
127
|
+
showMarkdownToolbar = false,
|
|
27
128
|
className
|
|
28
129
|
}) {
|
|
29
130
|
const textareaRef = React.useRef(null);
|
|
@@ -92,6 +193,14 @@ function ChatInputArea({
|
|
|
92
193
|
className: cn("flex flex-col gap-1.5", className),
|
|
93
194
|
children: [
|
|
94
195
|
/* @__PURE__ */ jsxs("div", { className: "border border-border bg-background flex flex-col focus-within:ring-1 focus-within:ring-ring", children: [
|
|
196
|
+
showMarkdownToolbar && /* @__PURE__ */ jsx(
|
|
197
|
+
MarkdownToolbar,
|
|
198
|
+
{
|
|
199
|
+
textareaRef,
|
|
200
|
+
onChange,
|
|
201
|
+
disabled
|
|
202
|
+
}
|
|
203
|
+
),
|
|
95
204
|
/* @__PURE__ */ jsx(
|
|
96
205
|
Textarea,
|
|
97
206
|
{
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-GTAVSBDO.mjs";
|
|
4
4
|
import {
|
|
5
5
|
ChatInputArea
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-EGM4DARZ.mjs";
|
|
7
7
|
import {
|
|
8
8
|
Sheet,
|
|
9
9
|
SheetContent
|
|
@@ -396,6 +396,49 @@ function RichContentRenderer({ richContent }) {
|
|
|
396
396
|
}
|
|
397
397
|
return null;
|
|
398
398
|
}
|
|
399
|
+
function CloseButton({ onClick }) {
|
|
400
|
+
return /* @__PURE__ */ jsxs3(
|
|
401
|
+
Button,
|
|
402
|
+
{
|
|
403
|
+
variant: "ghost",
|
|
404
|
+
size: "icon",
|
|
405
|
+
className: "size-7 shrink-0",
|
|
406
|
+
onClick,
|
|
407
|
+
title: "Close",
|
|
408
|
+
children: [
|
|
409
|
+
/* @__PURE__ */ jsx3(X2, { className: "size-3.5" }),
|
|
410
|
+
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Close" })
|
|
411
|
+
]
|
|
412
|
+
}
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
function ConversationRow({
|
|
416
|
+
conv,
|
|
417
|
+
onClick,
|
|
418
|
+
className
|
|
419
|
+
}) {
|
|
420
|
+
return /* @__PURE__ */ jsxs3(
|
|
421
|
+
"button",
|
|
422
|
+
{
|
|
423
|
+
type: "button",
|
|
424
|
+
onClick,
|
|
425
|
+
className: cn(
|
|
426
|
+
"flex w-full items-center justify-between gap-2 text-left text-sm text-foreground hover:bg-muted/50",
|
|
427
|
+
className
|
|
428
|
+
),
|
|
429
|
+
children: [
|
|
430
|
+
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate", children: conv.title }),
|
|
431
|
+
/* @__PURE__ */ jsx3(
|
|
432
|
+
ChevronRight,
|
|
433
|
+
{
|
|
434
|
+
className: "size-3.5 shrink-0 text-muted-foreground",
|
|
435
|
+
"aria-hidden": "true"
|
|
436
|
+
}
|
|
437
|
+
)
|
|
438
|
+
]
|
|
439
|
+
}
|
|
440
|
+
);
|
|
441
|
+
}
|
|
399
442
|
function SupportAgentPanel({
|
|
400
443
|
open,
|
|
401
444
|
onClose,
|
|
@@ -417,9 +460,13 @@ function SupportAgentPanel({
|
|
|
417
460
|
}) {
|
|
418
461
|
var _a;
|
|
419
462
|
const [inputValue, setInputValue] = React2.useState("");
|
|
463
|
+
const [showAllConversations, setShowAllConversations] = React2.useState(false);
|
|
420
464
|
const messagesEndRef = React2.useRef(null);
|
|
421
465
|
const hasMessages = messages.length > 0;
|
|
422
466
|
const isChatMode = hasMessages && !!conversationTitle;
|
|
467
|
+
React2.useEffect(() => {
|
|
468
|
+
if (!open) setShowAllConversations(false);
|
|
469
|
+
}, [open]);
|
|
423
470
|
React2.useEffect(() => {
|
|
424
471
|
if (!messagesEndRef.current) return;
|
|
425
472
|
messagesEndRef.current.scrollIntoView({
|
|
@@ -441,6 +488,17 @@ function SupportAgentPanel({
|
|
|
441
488
|
[onSendMessage]
|
|
442
489
|
);
|
|
443
490
|
const hasRecents = !!(recentConversations == null ? void 0 : recentConversations.length);
|
|
491
|
+
const recentsPreview = React2.useMemo(
|
|
492
|
+
() => {
|
|
493
|
+
var _a2;
|
|
494
|
+
return (_a2 = recentConversations == null ? void 0 : recentConversations.slice(0, 3)) != null ? _a2 : [];
|
|
495
|
+
},
|
|
496
|
+
[recentConversations]
|
|
497
|
+
);
|
|
498
|
+
const handleViewAll = React2.useCallback(() => {
|
|
499
|
+
setShowAllConversations(true);
|
|
500
|
+
onViewAllConversations == null ? void 0 : onViewAllConversations();
|
|
501
|
+
}, [onViewAllConversations]);
|
|
444
502
|
return /* @__PURE__ */ jsx3(Sheet, { open, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs3(
|
|
445
503
|
SheetContent,
|
|
446
504
|
{
|
|
@@ -453,38 +511,45 @@ function SupportAgentPanel({
|
|
|
453
511
|
"data-slot": "support-agent-panel",
|
|
454
512
|
children: [
|
|
455
513
|
/* @__PURE__ */ jsxs3("div", { className: "shrink-0 border-b border-border px-3 py-2.5", children: [
|
|
456
|
-
|
|
457
|
-
/*
|
|
514
|
+
showAllConversations ? (
|
|
515
|
+
/* All-conversations mode: [←] All conversations [✕] */
|
|
458
516
|
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
|
|
459
|
-
|
|
517
|
+
/* @__PURE__ */ jsxs3(
|
|
460
518
|
Button,
|
|
461
519
|
{
|
|
462
520
|
variant: "ghost",
|
|
463
521
|
size: "icon",
|
|
464
522
|
className: "size-7 shrink-0",
|
|
465
|
-
onClick:
|
|
466
|
-
title: "Back
|
|
523
|
+
onClick: () => setShowAllConversations(false),
|
|
524
|
+
title: "Back",
|
|
467
525
|
children: [
|
|
468
526
|
/* @__PURE__ */ jsx3(ChevronLeft, { className: "size-3.5" }),
|
|
469
527
|
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Back" })
|
|
470
528
|
]
|
|
471
529
|
}
|
|
472
530
|
),
|
|
473
|
-
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children:
|
|
474
|
-
/* @__PURE__ */
|
|
531
|
+
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children: "All conversations" }),
|
|
532
|
+
/* @__PURE__ */ jsx3(CloseButton, { onClick: onClose })
|
|
533
|
+
] })
|
|
534
|
+
) : isChatMode ? (
|
|
535
|
+
/* Chat mode: [←] Conversation title [✕] */
|
|
536
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
|
|
537
|
+
onBack && /* @__PURE__ */ jsxs3(
|
|
475
538
|
Button,
|
|
476
539
|
{
|
|
477
540
|
variant: "ghost",
|
|
478
541
|
size: "icon",
|
|
479
542
|
className: "size-7 shrink-0",
|
|
480
|
-
onClick:
|
|
481
|
-
title: "
|
|
543
|
+
onClick: onBack,
|
|
544
|
+
title: "Back to conversations",
|
|
482
545
|
children: [
|
|
483
|
-
/* @__PURE__ */ jsx3(
|
|
484
|
-
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "
|
|
546
|
+
/* @__PURE__ */ jsx3(ChevronLeft, { className: "size-3.5" }),
|
|
547
|
+
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Back" })
|
|
485
548
|
]
|
|
486
549
|
}
|
|
487
|
-
)
|
|
550
|
+
),
|
|
551
|
+
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children: conversationTitle }),
|
|
552
|
+
/* @__PURE__ */ jsx3(CloseButton, { onClick: onClose })
|
|
488
553
|
] })
|
|
489
554
|
) : (
|
|
490
555
|
/* Home mode: [Bot icon] Support Assistant [✕] */
|
|
@@ -499,23 +564,10 @@ function SupportAgentPanel({
|
|
|
499
564
|
) }),
|
|
500
565
|
/* @__PURE__ */ jsx3("span", { className: "text-sm font-semibold text-foreground", children: "Support Assistant" })
|
|
501
566
|
] }),
|
|
502
|
-
/* @__PURE__ */
|
|
503
|
-
Button,
|
|
504
|
-
{
|
|
505
|
-
variant: "ghost",
|
|
506
|
-
size: "icon",
|
|
507
|
-
className: "size-7",
|
|
508
|
-
onClick: onClose,
|
|
509
|
-
title: "Close",
|
|
510
|
-
children: [
|
|
511
|
-
/* @__PURE__ */ jsx3(X2, { className: "size-3.5" }),
|
|
512
|
-
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Close" })
|
|
513
|
-
]
|
|
514
|
-
}
|
|
515
|
-
)
|
|
567
|
+
/* @__PURE__ */ jsx3(CloseButton, { onClick: onClose })
|
|
516
568
|
] })
|
|
517
569
|
),
|
|
518
|
-
context && /* @__PURE__ */ jsx3("div", { className: "mt-2", children: /* @__PURE__ */ jsx3(SupportContextChip, { context }) })
|
|
570
|
+
context && !showAllConversations && /* @__PURE__ */ jsx3("div", { className: "mt-2", children: /* @__PURE__ */ jsx3(SupportContextChip, { context }) })
|
|
519
571
|
] }),
|
|
520
572
|
/* @__PURE__ */ jsx3("div", { className: "flex flex-1 flex-col overflow-y-auto", children: isLoading ? (
|
|
521
573
|
/* Loading state */
|
|
@@ -523,6 +575,20 @@ function SupportAgentPanel({
|
|
|
523
575
|
/* @__PURE__ */ jsx3(Spinner, { size: "lg", className: "text-muted-foreground" }),
|
|
524
576
|
/* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: "Loading\u2026" })
|
|
525
577
|
] }) })
|
|
578
|
+
) : showAllConversations ? (
|
|
579
|
+
/* All conversations — full scrollable list (Jira Rovo pattern) */
|
|
580
|
+
/* @__PURE__ */ jsx3("div", { className: "flex flex-col", children: (recentConversations == null ? void 0 : recentConversations.length) ? recentConversations.map((conv) => /* @__PURE__ */ jsx3(
|
|
581
|
+
ConversationRow,
|
|
582
|
+
{
|
|
583
|
+
conv,
|
|
584
|
+
onClick: () => {
|
|
585
|
+
setShowAllConversations(false);
|
|
586
|
+
onOpenConversation == null ? void 0 : onOpenConversation(conv.id);
|
|
587
|
+
},
|
|
588
|
+
className: "border-b border-border px-4 py-3"
|
|
589
|
+
},
|
|
590
|
+
conv.id
|
|
591
|
+
)) : /* @__PURE__ */ jsx3("p", { className: "p-4 text-sm text-muted-foreground", children: "No conversations yet." }) })
|
|
526
592
|
) : !hasMessages ? (
|
|
527
593
|
/* Home state — Rovo pattern: New Chat CTA + Recents + Suggested */
|
|
528
594
|
/* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-5 p-4", children: [
|
|
@@ -541,31 +607,21 @@ function SupportAgentPanel({
|
|
|
541
607
|
),
|
|
542
608
|
hasRecents && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-1", children: [
|
|
543
609
|
/* @__PURE__ */ jsx3("p", { className: "px-1 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Recents" }),
|
|
544
|
-
/* @__PURE__ */ jsx3("div", { className: "flex flex-col", children:
|
|
545
|
-
|
|
610
|
+
/* @__PURE__ */ jsx3("div", { className: "flex flex-col", children: recentsPreview.map((conv) => /* @__PURE__ */ jsx3(
|
|
611
|
+
ConversationRow,
|
|
546
612
|
{
|
|
547
|
-
|
|
613
|
+
conv,
|
|
548
614
|
onClick: () => onOpenConversation == null ? void 0 : onOpenConversation(conv.id),
|
|
549
|
-
className: "
|
|
550
|
-
children: [
|
|
551
|
-
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate", children: conv.title }),
|
|
552
|
-
/* @__PURE__ */ jsx3(
|
|
553
|
-
ChevronRight,
|
|
554
|
-
{
|
|
555
|
-
className: "size-3.5 shrink-0 text-muted-foreground",
|
|
556
|
-
"aria-hidden": "true"
|
|
557
|
-
}
|
|
558
|
-
)
|
|
559
|
-
]
|
|
615
|
+
className: "px-1 py-2.5"
|
|
560
616
|
},
|
|
561
617
|
conv.id
|
|
562
618
|
)) }),
|
|
563
|
-
|
|
619
|
+
/* @__PURE__ */ jsxs3(
|
|
564
620
|
Button,
|
|
565
621
|
{
|
|
566
622
|
variant: "ghost",
|
|
567
623
|
size: "sm",
|
|
568
|
-
onClick:
|
|
624
|
+
onClick: handleViewAll,
|
|
569
625
|
className: "h-auto w-fit gap-0.5 px-1 py-1 text-xs text-muted-foreground hover:bg-transparent hover:text-foreground",
|
|
570
626
|
children: [
|
|
571
627
|
"View all conversations",
|
|
@@ -604,7 +660,8 @@ function SupportAgentPanel({
|
|
|
604
660
|
onAttachFile,
|
|
605
661
|
onAttachImage,
|
|
606
662
|
disabled: isLoading || isStreaming,
|
|
607
|
-
placeholder: "Ask anything\u2026"
|
|
663
|
+
placeholder: "Ask anything\u2026",
|
|
664
|
+
showMarkdownToolbar: true
|
|
608
665
|
}
|
|
609
666
|
) })
|
|
610
667
|
]
|
|
@@ -369,6 +369,7 @@ function Badge(_a) {
|
|
|
369
369
|
|
|
370
370
|
// src/components/ui/chat-input-area.tsx
|
|
371
371
|
var React3 = __toESM(require("react"));
|
|
372
|
+
var import_react_dom = require("react-dom");
|
|
372
373
|
var import_lucide_react3 = require("lucide-react");
|
|
373
374
|
|
|
374
375
|
// src/components/ui/textarea.tsx
|
|
@@ -391,6 +392,97 @@ function Textarea(_a) {
|
|
|
391
392
|
// src/components/ui/chat-input-area.tsx
|
|
392
393
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
393
394
|
var DEFAULT_HINT = "Enter to send \xB7 Shift+Enter for new line";
|
|
395
|
+
var TOOLBAR_ITEMS = [
|
|
396
|
+
{
|
|
397
|
+
type: "button",
|
|
398
|
+
icon: import_lucide_react3.Bold,
|
|
399
|
+
label: "Bold",
|
|
400
|
+
title: "Bold (Ctrl+B)",
|
|
401
|
+
before: "**",
|
|
402
|
+
after: "**",
|
|
403
|
+
placeholder: "bold text"
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
type: "button",
|
|
407
|
+
icon: import_lucide_react3.Italic,
|
|
408
|
+
label: "Italic",
|
|
409
|
+
title: "Italic (Ctrl+I)",
|
|
410
|
+
before: "*",
|
|
411
|
+
after: "*",
|
|
412
|
+
placeholder: "italic text"
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
type: "button",
|
|
416
|
+
icon: import_lucide_react3.Code,
|
|
417
|
+
label: "Inline code",
|
|
418
|
+
title: "Inline code",
|
|
419
|
+
before: "`",
|
|
420
|
+
after: "`",
|
|
421
|
+
placeholder: "code"
|
|
422
|
+
},
|
|
423
|
+
{ type: "divider" },
|
|
424
|
+
{
|
|
425
|
+
type: "button",
|
|
426
|
+
icon: import_lucide_react3.Code2,
|
|
427
|
+
label: "Code block",
|
|
428
|
+
title: "Code block",
|
|
429
|
+
before: "```\n",
|
|
430
|
+
after: "\n```",
|
|
431
|
+
placeholder: "code block"
|
|
432
|
+
}
|
|
433
|
+
];
|
|
434
|
+
function applyMarkdown(textarea, before, after, placeholder, onChange) {
|
|
435
|
+
const start = textarea.selectionStart;
|
|
436
|
+
const end = textarea.selectionEnd;
|
|
437
|
+
const selected = textarea.value.slice(start, end);
|
|
438
|
+
const insertion = selected || placeholder;
|
|
439
|
+
const next = textarea.value.slice(0, start) + before + insertion + after + textarea.value.slice(end);
|
|
440
|
+
const newStart = start + before.length;
|
|
441
|
+
const newEnd = newStart + insertion.length;
|
|
442
|
+
(0, import_react_dom.flushSync)(() => onChange(next));
|
|
443
|
+
textarea.focus();
|
|
444
|
+
textarea.setSelectionRange(newStart, newEnd);
|
|
445
|
+
}
|
|
446
|
+
var MarkdownToolbar = React3.memo(function MarkdownToolbar2({
|
|
447
|
+
textareaRef,
|
|
448
|
+
onChange,
|
|
449
|
+
disabled
|
|
450
|
+
}) {
|
|
451
|
+
const handleFormat = React3.useCallback(
|
|
452
|
+
(e) => {
|
|
453
|
+
if (!textareaRef.current) return;
|
|
454
|
+
const { before, after, placeholder } = e.currentTarget.dataset;
|
|
455
|
+
applyMarkdown(textareaRef.current, before, after, placeholder, onChange);
|
|
456
|
+
},
|
|
457
|
+
[textareaRef, onChange]
|
|
458
|
+
);
|
|
459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex items-center gap-0.5 border-b border-border px-2 py-1", children: TOOLBAR_ITEMS.map(
|
|
460
|
+
(item, i) => item.type === "divider" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
461
|
+
"span",
|
|
462
|
+
{
|
|
463
|
+
className: "mx-0.5 h-3.5 w-px bg-border",
|
|
464
|
+
"aria-hidden": "true"
|
|
465
|
+
},
|
|
466
|
+
i
|
|
467
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
468
|
+
Button,
|
|
469
|
+
{
|
|
470
|
+
variant: "ghost",
|
|
471
|
+
size: "icon-sm",
|
|
472
|
+
type: "button",
|
|
473
|
+
title: item.title,
|
|
474
|
+
"aria-label": item.label,
|
|
475
|
+
disabled,
|
|
476
|
+
"data-before": item.before,
|
|
477
|
+
"data-after": item.after,
|
|
478
|
+
"data-placeholder": item.placeholder,
|
|
479
|
+
onClick: handleFormat,
|
|
480
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(item.icon, { className: "size-3.5", "aria-hidden": "true" })
|
|
481
|
+
},
|
|
482
|
+
item.label
|
|
483
|
+
)
|
|
484
|
+
) });
|
|
485
|
+
});
|
|
394
486
|
function ChatInputArea({
|
|
395
487
|
value,
|
|
396
488
|
onChange,
|
|
@@ -402,6 +494,7 @@ function ChatInputArea({
|
|
|
402
494
|
hint = DEFAULT_HINT,
|
|
403
495
|
maxHeight = 160,
|
|
404
496
|
autoFocus = false,
|
|
497
|
+
showMarkdownToolbar = false,
|
|
405
498
|
className
|
|
406
499
|
}) {
|
|
407
500
|
const textareaRef = React3.useRef(null);
|
|
@@ -470,6 +563,14 @@ function ChatInputArea({
|
|
|
470
563
|
className: cn("flex flex-col gap-1.5", className),
|
|
471
564
|
children: [
|
|
472
565
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "border border-border bg-background flex flex-col focus-within:ring-1 focus-within:ring-ring", children: [
|
|
566
|
+
showMarkdownToolbar && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
567
|
+
MarkdownToolbar,
|
|
568
|
+
{
|
|
569
|
+
textareaRef,
|
|
570
|
+
onChange,
|
|
571
|
+
disabled
|
|
572
|
+
}
|
|
573
|
+
),
|
|
473
574
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
474
575
|
Textarea,
|
|
475
576
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AiAssistantDrawer
|
|
3
|
-
} from "../../chunk-
|
|
4
|
-
import "../../chunk-
|
|
3
|
+
} from "../../chunk-TF5TOVIM.mjs";
|
|
4
|
+
import "../../chunk-EGM4DARZ.mjs";
|
|
5
5
|
import "../../chunk-H3PTREG6.mjs";
|
|
6
6
|
import "../../chunk-BS75ICOO.mjs";
|
|
7
7
|
import "../../chunk-JVMXMFBB.mjs";
|
|
@@ -1196,6 +1196,7 @@ function Separator(_a2) {
|
|
|
1196
1196
|
|
|
1197
1197
|
// src/components/ui/chat-input-area.tsx
|
|
1198
1198
|
var React5 = __toESM(require("react"));
|
|
1199
|
+
var import_react_dom = require("react-dom");
|
|
1199
1200
|
var import_lucide_react5 = require("lucide-react");
|
|
1200
1201
|
|
|
1201
1202
|
// src/components/ui/textarea.tsx
|
|
@@ -1218,6 +1219,97 @@ function Textarea(_a2) {
|
|
|
1218
1219
|
// src/components/ui/chat-input-area.tsx
|
|
1219
1220
|
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1220
1221
|
var DEFAULT_HINT = "Enter to send \xB7 Shift+Enter for new line";
|
|
1222
|
+
var TOOLBAR_ITEMS = [
|
|
1223
|
+
{
|
|
1224
|
+
type: "button",
|
|
1225
|
+
icon: import_lucide_react5.Bold,
|
|
1226
|
+
label: "Bold",
|
|
1227
|
+
title: "Bold (Ctrl+B)",
|
|
1228
|
+
before: "**",
|
|
1229
|
+
after: "**",
|
|
1230
|
+
placeholder: "bold text"
|
|
1231
|
+
},
|
|
1232
|
+
{
|
|
1233
|
+
type: "button",
|
|
1234
|
+
icon: import_lucide_react5.Italic,
|
|
1235
|
+
label: "Italic",
|
|
1236
|
+
title: "Italic (Ctrl+I)",
|
|
1237
|
+
before: "*",
|
|
1238
|
+
after: "*",
|
|
1239
|
+
placeholder: "italic text"
|
|
1240
|
+
},
|
|
1241
|
+
{
|
|
1242
|
+
type: "button",
|
|
1243
|
+
icon: import_lucide_react5.Code,
|
|
1244
|
+
label: "Inline code",
|
|
1245
|
+
title: "Inline code",
|
|
1246
|
+
before: "`",
|
|
1247
|
+
after: "`",
|
|
1248
|
+
placeholder: "code"
|
|
1249
|
+
},
|
|
1250
|
+
{ type: "divider" },
|
|
1251
|
+
{
|
|
1252
|
+
type: "button",
|
|
1253
|
+
icon: import_lucide_react5.Code2,
|
|
1254
|
+
label: "Code block",
|
|
1255
|
+
title: "Code block",
|
|
1256
|
+
before: "```\n",
|
|
1257
|
+
after: "\n```",
|
|
1258
|
+
placeholder: "code block"
|
|
1259
|
+
}
|
|
1260
|
+
];
|
|
1261
|
+
function applyMarkdown(textarea, before, after, placeholder, onChange) {
|
|
1262
|
+
const start = textarea.selectionStart;
|
|
1263
|
+
const end = textarea.selectionEnd;
|
|
1264
|
+
const selected = textarea.value.slice(start, end);
|
|
1265
|
+
const insertion = selected || placeholder;
|
|
1266
|
+
const next = textarea.value.slice(0, start) + before + insertion + after + textarea.value.slice(end);
|
|
1267
|
+
const newStart = start + before.length;
|
|
1268
|
+
const newEnd = newStart + insertion.length;
|
|
1269
|
+
(0, import_react_dom.flushSync)(() => onChange(next));
|
|
1270
|
+
textarea.focus();
|
|
1271
|
+
textarea.setSelectionRange(newStart, newEnd);
|
|
1272
|
+
}
|
|
1273
|
+
var MarkdownToolbar = React5.memo(function MarkdownToolbar2({
|
|
1274
|
+
textareaRef,
|
|
1275
|
+
onChange,
|
|
1276
|
+
disabled
|
|
1277
|
+
}) {
|
|
1278
|
+
const handleFormat = React5.useCallback(
|
|
1279
|
+
(e) => {
|
|
1280
|
+
if (!textareaRef.current) return;
|
|
1281
|
+
const { before, after, placeholder } = e.currentTarget.dataset;
|
|
1282
|
+
applyMarkdown(textareaRef.current, before, after, placeholder, onChange);
|
|
1283
|
+
},
|
|
1284
|
+
[textareaRef, onChange]
|
|
1285
|
+
);
|
|
1286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex items-center gap-0.5 border-b border-border px-2 py-1", children: TOOLBAR_ITEMS.map(
|
|
1287
|
+
(item, i) => item.type === "divider" ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1288
|
+
"span",
|
|
1289
|
+
{
|
|
1290
|
+
className: "mx-0.5 h-3.5 w-px bg-border",
|
|
1291
|
+
"aria-hidden": "true"
|
|
1292
|
+
},
|
|
1293
|
+
i
|
|
1294
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1295
|
+
Button,
|
|
1296
|
+
{
|
|
1297
|
+
variant: "ghost",
|
|
1298
|
+
size: "icon-sm",
|
|
1299
|
+
type: "button",
|
|
1300
|
+
title: item.title,
|
|
1301
|
+
"aria-label": item.label,
|
|
1302
|
+
disabled,
|
|
1303
|
+
"data-before": item.before,
|
|
1304
|
+
"data-after": item.after,
|
|
1305
|
+
"data-placeholder": item.placeholder,
|
|
1306
|
+
onClick: handleFormat,
|
|
1307
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(item.icon, { className: "size-3.5", "aria-hidden": "true" })
|
|
1308
|
+
},
|
|
1309
|
+
item.label
|
|
1310
|
+
)
|
|
1311
|
+
) });
|
|
1312
|
+
});
|
|
1221
1313
|
function ChatInputArea({
|
|
1222
1314
|
value,
|
|
1223
1315
|
onChange,
|
|
@@ -1229,6 +1321,7 @@ function ChatInputArea({
|
|
|
1229
1321
|
hint = DEFAULT_HINT,
|
|
1230
1322
|
maxHeight = 160,
|
|
1231
1323
|
autoFocus = false,
|
|
1324
|
+
showMarkdownToolbar = false,
|
|
1232
1325
|
className
|
|
1233
1326
|
}) {
|
|
1234
1327
|
const textareaRef = React5.useRef(null);
|
|
@@ -1297,6 +1390,14 @@ function ChatInputArea({
|
|
|
1297
1390
|
className: cn("flex flex-col gap-1.5", className),
|
|
1298
1391
|
children: [
|
|
1299
1392
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "border border-border bg-background flex flex-col focus-within:ring-1 focus-within:ring-ring", children: [
|
|
1393
|
+
showMarkdownToolbar && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1394
|
+
MarkdownToolbar,
|
|
1395
|
+
{
|
|
1396
|
+
textareaRef,
|
|
1397
|
+
onChange,
|
|
1398
|
+
disabled
|
|
1399
|
+
}
|
|
1400
|
+
),
|
|
1300
1401
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1301
1402
|
Textarea,
|
|
1302
1403
|
{
|
|
@@ -9,14 +9,14 @@ import {
|
|
|
9
9
|
ConversationStatusChip,
|
|
10
10
|
ConversationsPage,
|
|
11
11
|
LeadInfoPanel
|
|
12
|
-
} from "../../../chunk-
|
|
12
|
+
} from "../../../chunk-XHZONBL4.mjs";
|
|
13
13
|
import "../../../chunk-3S6KVFF5.mjs";
|
|
14
14
|
import "../../../chunk-WE4YKBDE.mjs";
|
|
15
15
|
import "../../../chunk-T5FRVEJQ.mjs";
|
|
16
16
|
import "../../../chunk-H5DTKPJ2.mjs";
|
|
17
17
|
import "../../../chunk-H6NQTIF4.mjs";
|
|
18
18
|
import "../../../chunk-2GIYVERS.mjs";
|
|
19
|
-
import "../../../chunk-
|
|
19
|
+
import "../../../chunk-EGM4DARZ.mjs";
|
|
20
20
|
import "../../../chunk-BS75ICOO.mjs";
|
|
21
21
|
import "../../../chunk-X6RC5UWB.mjs";
|
|
22
22
|
import "../../../chunk-F3CU6KEI.mjs";
|