@wealthx/shadcn 1.5.40 → 1.5.42
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 +103 -103
- package/CHANGELOG.md +12 -0
- package/dist/{chunk-MGIDYXOP.mjs → chunk-DWNLBUDC.mjs} +459 -67
- package/dist/{chunk-EFHPSKVF.mjs → chunk-EGM4DARZ.mjs} +110 -1
- package/dist/{chunk-B5PSUONN.mjs → chunk-TF5TOVIM.mjs} +1 -1
- package/dist/{chunk-STN5QIWN.mjs → chunk-THOHFAW2.mjs} +119 -46
- 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 +218 -44
- package/dist/components/ui/support-agent/index.mjs +2 -2
- package/dist/index.js +3506 -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 +153 -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
|
|
@@ -294,7 +294,7 @@ import ReactMarkdown from "react-markdown";
|
|
|
294
294
|
import rehypeRaw from "rehype-raw";
|
|
295
295
|
import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
|
|
296
296
|
import { Bot, ChevronLeft, ChevronRight, SquarePen, X as X2 } from "lucide-react";
|
|
297
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
297
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
298
298
|
function SupportTypingIndicator() {
|
|
299
299
|
return /* @__PURE__ */ jsx3(
|
|
300
300
|
"span",
|
|
@@ -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,
|
|
@@ -413,13 +456,20 @@ function SupportAgentPanel({
|
|
|
413
456
|
onBack,
|
|
414
457
|
onOpenConversation,
|
|
415
458
|
onViewAllConversations,
|
|
459
|
+
hasMoreConversations = false,
|
|
460
|
+
onLoadMoreConversations,
|
|
461
|
+
isLoadingMoreConversations = false,
|
|
416
462
|
className
|
|
417
463
|
}) {
|
|
418
464
|
var _a;
|
|
419
465
|
const [inputValue, setInputValue] = React2.useState("");
|
|
466
|
+
const [showAllConversations, setShowAllConversations] = React2.useState(false);
|
|
420
467
|
const messagesEndRef = React2.useRef(null);
|
|
421
468
|
const hasMessages = messages.length > 0;
|
|
422
469
|
const isChatMode = hasMessages && !!conversationTitle;
|
|
470
|
+
React2.useEffect(() => {
|
|
471
|
+
if (!open) setShowAllConversations(false);
|
|
472
|
+
}, [open]);
|
|
423
473
|
React2.useEffect(() => {
|
|
424
474
|
if (!messagesEndRef.current) return;
|
|
425
475
|
messagesEndRef.current.scrollIntoView({
|
|
@@ -441,6 +491,17 @@ function SupportAgentPanel({
|
|
|
441
491
|
[onSendMessage]
|
|
442
492
|
);
|
|
443
493
|
const hasRecents = !!(recentConversations == null ? void 0 : recentConversations.length);
|
|
494
|
+
const recentsPreview = React2.useMemo(
|
|
495
|
+
() => {
|
|
496
|
+
var _a2;
|
|
497
|
+
return (_a2 = recentConversations == null ? void 0 : recentConversations.slice(0, 3)) != null ? _a2 : [];
|
|
498
|
+
},
|
|
499
|
+
[recentConversations]
|
|
500
|
+
);
|
|
501
|
+
const handleViewAll = React2.useCallback(() => {
|
|
502
|
+
setShowAllConversations(true);
|
|
503
|
+
onViewAllConversations == null ? void 0 : onViewAllConversations();
|
|
504
|
+
}, [onViewAllConversations]);
|
|
444
505
|
return /* @__PURE__ */ jsx3(Sheet, { open, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs3(
|
|
445
506
|
SheetContent,
|
|
446
507
|
{
|
|
@@ -453,38 +514,45 @@ function SupportAgentPanel({
|
|
|
453
514
|
"data-slot": "support-agent-panel",
|
|
454
515
|
children: [
|
|
455
516
|
/* @__PURE__ */ jsxs3("div", { className: "shrink-0 border-b border-border px-3 py-2.5", children: [
|
|
456
|
-
|
|
457
|
-
/*
|
|
517
|
+
showAllConversations ? (
|
|
518
|
+
/* All-conversations mode: [←] All conversations [✕] */
|
|
458
519
|
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
|
|
459
|
-
|
|
520
|
+
/* @__PURE__ */ jsxs3(
|
|
460
521
|
Button,
|
|
461
522
|
{
|
|
462
523
|
variant: "ghost",
|
|
463
524
|
size: "icon",
|
|
464
525
|
className: "size-7 shrink-0",
|
|
465
|
-
onClick:
|
|
466
|
-
title: "Back
|
|
526
|
+
onClick: () => setShowAllConversations(false),
|
|
527
|
+
title: "Back",
|
|
467
528
|
children: [
|
|
468
529
|
/* @__PURE__ */ jsx3(ChevronLeft, { className: "size-3.5" }),
|
|
469
530
|
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Back" })
|
|
470
531
|
]
|
|
471
532
|
}
|
|
472
533
|
),
|
|
473
|
-
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children:
|
|
474
|
-
/* @__PURE__ */
|
|
534
|
+
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children: "All conversations" }),
|
|
535
|
+
/* @__PURE__ */ jsx3(CloseButton, { onClick: onClose })
|
|
536
|
+
] })
|
|
537
|
+
) : isChatMode ? (
|
|
538
|
+
/* Chat mode: [←] Conversation title [✕] */
|
|
539
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
|
|
540
|
+
onBack && /* @__PURE__ */ jsxs3(
|
|
475
541
|
Button,
|
|
476
542
|
{
|
|
477
543
|
variant: "ghost",
|
|
478
544
|
size: "icon",
|
|
479
545
|
className: "size-7 shrink-0",
|
|
480
|
-
onClick:
|
|
481
|
-
title: "
|
|
546
|
+
onClick: onBack,
|
|
547
|
+
title: "Back to conversations",
|
|
482
548
|
children: [
|
|
483
|
-
/* @__PURE__ */ jsx3(
|
|
484
|
-
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "
|
|
549
|
+
/* @__PURE__ */ jsx3(ChevronLeft, { className: "size-3.5" }),
|
|
550
|
+
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Back" })
|
|
485
551
|
]
|
|
486
552
|
}
|
|
487
|
-
)
|
|
553
|
+
),
|
|
554
|
+
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children: conversationTitle }),
|
|
555
|
+
/* @__PURE__ */ jsx3(CloseButton, { onClick: onClose })
|
|
488
556
|
] })
|
|
489
557
|
) : (
|
|
490
558
|
/* Home mode: [Bot icon] Support Assistant [✕] */
|
|
@@ -499,23 +567,10 @@ function SupportAgentPanel({
|
|
|
499
567
|
) }),
|
|
500
568
|
/* @__PURE__ */ jsx3("span", { className: "text-sm font-semibold text-foreground", children: "Support Assistant" })
|
|
501
569
|
] }),
|
|
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
|
-
)
|
|
570
|
+
/* @__PURE__ */ jsx3(CloseButton, { onClick: onClose })
|
|
516
571
|
] })
|
|
517
572
|
),
|
|
518
|
-
context && /* @__PURE__ */ jsx3("div", { className: "mt-2", children: /* @__PURE__ */ jsx3(SupportContextChip, { context }) })
|
|
573
|
+
context && !showAllConversations && /* @__PURE__ */ jsx3("div", { className: "mt-2", children: /* @__PURE__ */ jsx3(SupportContextChip, { context }) })
|
|
519
574
|
] }),
|
|
520
575
|
/* @__PURE__ */ jsx3("div", { className: "flex flex-1 flex-col overflow-y-auto", children: isLoading ? (
|
|
521
576
|
/* Loading state */
|
|
@@ -523,6 +578,33 @@ function SupportAgentPanel({
|
|
|
523
578
|
/* @__PURE__ */ jsx3(Spinner, { size: "lg", className: "text-muted-foreground" }),
|
|
524
579
|
/* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: "Loading\u2026" })
|
|
525
580
|
] }) })
|
|
581
|
+
) : showAllConversations ? (
|
|
582
|
+
/* All conversations — full scrollable list (Jira Rovo pattern) */
|
|
583
|
+
/* @__PURE__ */ jsx3("div", { className: "flex flex-col", children: (recentConversations == null ? void 0 : recentConversations.length) ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
584
|
+
recentConversations.map((conv) => /* @__PURE__ */ jsx3(
|
|
585
|
+
ConversationRow,
|
|
586
|
+
{
|
|
587
|
+
conv,
|
|
588
|
+
onClick: () => {
|
|
589
|
+
setShowAllConversations(false);
|
|
590
|
+
onOpenConversation == null ? void 0 : onOpenConversation(conv.id);
|
|
591
|
+
},
|
|
592
|
+
className: "border-b border-border px-4 py-3"
|
|
593
|
+
},
|
|
594
|
+
conv.id
|
|
595
|
+
)),
|
|
596
|
+
hasMoreConversations && /* @__PURE__ */ jsx3("div", { className: "border-t border-border p-3", children: /* @__PURE__ */ jsx3(
|
|
597
|
+
Button,
|
|
598
|
+
{
|
|
599
|
+
variant: "outline",
|
|
600
|
+
size: "sm",
|
|
601
|
+
className: "w-full",
|
|
602
|
+
disabled: isLoadingMoreConversations,
|
|
603
|
+
onClick: onLoadMoreConversations,
|
|
604
|
+
children: isLoadingMoreConversations ? "Loading..." : "Load more"
|
|
605
|
+
}
|
|
606
|
+
) })
|
|
607
|
+
] }) : /* @__PURE__ */ jsx3("p", { className: "p-4 text-sm text-muted-foreground", children: "No conversations yet." }) })
|
|
526
608
|
) : !hasMessages ? (
|
|
527
609
|
/* Home state — Rovo pattern: New Chat CTA + Recents + Suggested */
|
|
528
610
|
/* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-5 p-4", children: [
|
|
@@ -541,31 +623,21 @@ function SupportAgentPanel({
|
|
|
541
623
|
),
|
|
542
624
|
hasRecents && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-1", children: [
|
|
543
625
|
/* @__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
|
-
|
|
626
|
+
/* @__PURE__ */ jsx3("div", { className: "flex flex-col", children: recentsPreview.map((conv) => /* @__PURE__ */ jsx3(
|
|
627
|
+
ConversationRow,
|
|
546
628
|
{
|
|
547
|
-
|
|
629
|
+
conv,
|
|
548
630
|
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
|
-
]
|
|
631
|
+
className: "px-1 py-2.5"
|
|
560
632
|
},
|
|
561
633
|
conv.id
|
|
562
634
|
)) }),
|
|
563
|
-
|
|
635
|
+
/* @__PURE__ */ jsxs3(
|
|
564
636
|
Button,
|
|
565
637
|
{
|
|
566
638
|
variant: "ghost",
|
|
567
639
|
size: "sm",
|
|
568
|
-
onClick:
|
|
640
|
+
onClick: handleViewAll,
|
|
569
641
|
className: "h-auto w-fit gap-0.5 px-1 py-1 text-xs text-muted-foreground hover:bg-transparent hover:text-foreground",
|
|
570
642
|
children: [
|
|
571
643
|
"View all conversations",
|
|
@@ -604,7 +676,8 @@ function SupportAgentPanel({
|
|
|
604
676
|
onAttachFile,
|
|
605
677
|
onAttachImage,
|
|
606
678
|
disabled: isLoading || isStreaming,
|
|
607
|
-
placeholder: "Ask anything\u2026"
|
|
679
|
+
placeholder: "Ask anything\u2026",
|
|
680
|
+
showMarkdownToolbar: true
|
|
608
681
|
}
|
|
609
682
|
) })
|
|
610
683
|
]
|
|
@@ -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
|
{
|