@wealthx/shadcn 1.5.39 → 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 +118 -118
- 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-R7M657QL.mjs → chunk-GIQGZFP6.mjs} +138 -46
- 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 +233 -45
- package/dist/components/ui/support-agent/index.mjs +2 -2
- package/dist/index.js +3521 -3330
- 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 +170 -48
- 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
|
|
@@ -17,6 +17,11 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
cn
|
|
19
19
|
} from "./chunk-AFML43VJ.mjs";
|
|
20
|
+
import {
|
|
21
|
+
__objRest,
|
|
22
|
+
__spreadProps,
|
|
23
|
+
__spreadValues
|
|
24
|
+
} from "./chunk-WNQUEZJF.mjs";
|
|
20
25
|
|
|
21
26
|
// src/components/ui/support-agent/support-agent-primitives.tsx
|
|
22
27
|
import * as React from "react";
|
|
@@ -285,6 +290,9 @@ function SupportAgentFAB({
|
|
|
285
290
|
|
|
286
291
|
// src/components/ui/support-agent/support-agent-panel.tsx
|
|
287
292
|
import * as React2 from "react";
|
|
293
|
+
import ReactMarkdown from "react-markdown";
|
|
294
|
+
import rehypeRaw from "rehype-raw";
|
|
295
|
+
import rehypeSanitize, { defaultSchema } from "rehype-sanitize";
|
|
288
296
|
import { Bot, ChevronLeft, ChevronRight, SquarePen, X as X2 } from "lucide-react";
|
|
289
297
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
290
298
|
function SupportTypingIndicator() {
|
|
@@ -306,6 +314,21 @@ function SupportTypingIndicator() {
|
|
|
306
314
|
}
|
|
307
315
|
);
|
|
308
316
|
}
|
|
317
|
+
function StreamingStatus({ label }) {
|
|
318
|
+
if (!label) return /* @__PURE__ */ jsx3(SupportTypingIndicator, {});
|
|
319
|
+
return /* @__PURE__ */ jsxs3(
|
|
320
|
+
"span",
|
|
321
|
+
{
|
|
322
|
+
className: "flex items-center gap-1.5 text-sm text-muted-foreground",
|
|
323
|
+
role: "status",
|
|
324
|
+
"aria-label": `${label}\u2026`,
|
|
325
|
+
children: [
|
|
326
|
+
/* @__PURE__ */ jsx3("span", { children: label }),
|
|
327
|
+
/* @__PURE__ */ jsx3(SupportTypingIndicator, {})
|
|
328
|
+
]
|
|
329
|
+
}
|
|
330
|
+
);
|
|
331
|
+
}
|
|
309
332
|
function MessageBubble({ message }) {
|
|
310
333
|
const isUser = message.role === "user";
|
|
311
334
|
const isEmpty = !message.content.trim();
|
|
@@ -328,7 +351,19 @@ function MessageBubble({ message }) {
|
|
|
328
351
|
"data-slot": "support-message-bubble",
|
|
329
352
|
"data-role": message.role,
|
|
330
353
|
children: [
|
|
331
|
-
isEmpty && message.isStreaming ? /* @__PURE__ */ jsx3(
|
|
354
|
+
isEmpty && message.isStreaming ? /* @__PURE__ */ jsx3(StreamingStatus, { label: message.streamingLabel }) : isUser ? /* @__PURE__ */ jsx3("span", { className: "whitespace-pre-wrap break-words leading-relaxed", children: message.content }) : /* @__PURE__ */ jsx3("div", { className: "break-words text-sm leading-relaxed [&_a]:text-primary [&_a]:underline [&_p]:m-0 [&_p:not(:last-child)]:mb-2 [&_ul]:my-1 [&_ul]:list-disc [&_ul]:pl-4 [&_ol]:my-1 [&_ol]:list-decimal [&_ol]:pl-4 [&_li]:mb-0.5", children: /* @__PURE__ */ jsx3(
|
|
355
|
+
ReactMarkdown,
|
|
356
|
+
{
|
|
357
|
+
rehypePlugins: [rehypeRaw, [rehypeSanitize, defaultSchema]],
|
|
358
|
+
components: {
|
|
359
|
+
a: (_a) => {
|
|
360
|
+
var _b = _a, { node } = _b, props = __objRest(_b, ["node"]);
|
|
361
|
+
return /* @__PURE__ */ jsx3("a", __spreadProps(__spreadValues({}, props), { target: "_blank", rel: "noopener noreferrer" }));
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
children: message.content
|
|
365
|
+
}
|
|
366
|
+
) }),
|
|
332
367
|
message.isErrored && /* @__PURE__ */ jsx3("p", { className: "mt-1 text-xs opacity-70", children: "Failed to send. Please try again." })
|
|
333
368
|
]
|
|
334
369
|
}
|
|
@@ -361,6 +396,49 @@ function RichContentRenderer({ richContent }) {
|
|
|
361
396
|
}
|
|
362
397
|
return null;
|
|
363
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
|
+
}
|
|
364
442
|
function SupportAgentPanel({
|
|
365
443
|
open,
|
|
366
444
|
onClose,
|
|
@@ -382,9 +460,13 @@ function SupportAgentPanel({
|
|
|
382
460
|
}) {
|
|
383
461
|
var _a;
|
|
384
462
|
const [inputValue, setInputValue] = React2.useState("");
|
|
463
|
+
const [showAllConversations, setShowAllConversations] = React2.useState(false);
|
|
385
464
|
const messagesEndRef = React2.useRef(null);
|
|
386
465
|
const hasMessages = messages.length > 0;
|
|
387
466
|
const isChatMode = hasMessages && !!conversationTitle;
|
|
467
|
+
React2.useEffect(() => {
|
|
468
|
+
if (!open) setShowAllConversations(false);
|
|
469
|
+
}, [open]);
|
|
388
470
|
React2.useEffect(() => {
|
|
389
471
|
if (!messagesEndRef.current) return;
|
|
390
472
|
messagesEndRef.current.scrollIntoView({
|
|
@@ -406,6 +488,17 @@ function SupportAgentPanel({
|
|
|
406
488
|
[onSendMessage]
|
|
407
489
|
);
|
|
408
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]);
|
|
409
502
|
return /* @__PURE__ */ jsx3(Sheet, { open, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs3(
|
|
410
503
|
SheetContent,
|
|
411
504
|
{
|
|
@@ -418,38 +511,45 @@ function SupportAgentPanel({
|
|
|
418
511
|
"data-slot": "support-agent-panel",
|
|
419
512
|
children: [
|
|
420
513
|
/* @__PURE__ */ jsxs3("div", { className: "shrink-0 border-b border-border px-3 py-2.5", children: [
|
|
421
|
-
|
|
422
|
-
/*
|
|
514
|
+
showAllConversations ? (
|
|
515
|
+
/* All-conversations mode: [←] All conversations [✕] */
|
|
423
516
|
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
|
|
424
|
-
|
|
517
|
+
/* @__PURE__ */ jsxs3(
|
|
425
518
|
Button,
|
|
426
519
|
{
|
|
427
520
|
variant: "ghost",
|
|
428
521
|
size: "icon",
|
|
429
522
|
className: "size-7 shrink-0",
|
|
430
|
-
onClick:
|
|
431
|
-
title: "Back
|
|
523
|
+
onClick: () => setShowAllConversations(false),
|
|
524
|
+
title: "Back",
|
|
432
525
|
children: [
|
|
433
526
|
/* @__PURE__ */ jsx3(ChevronLeft, { className: "size-3.5" }),
|
|
434
527
|
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Back" })
|
|
435
528
|
]
|
|
436
529
|
}
|
|
437
530
|
),
|
|
438
|
-
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate px-1 text-sm font-medium text-foreground", children:
|
|
439
|
-
/* @__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(
|
|
440
538
|
Button,
|
|
441
539
|
{
|
|
442
540
|
variant: "ghost",
|
|
443
541
|
size: "icon",
|
|
444
542
|
className: "size-7 shrink-0",
|
|
445
|
-
onClick:
|
|
446
|
-
title: "
|
|
543
|
+
onClick: onBack,
|
|
544
|
+
title: "Back to conversations",
|
|
447
545
|
children: [
|
|
448
|
-
/* @__PURE__ */ jsx3(
|
|
449
|
-
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "
|
|
546
|
+
/* @__PURE__ */ jsx3(ChevronLeft, { className: "size-3.5" }),
|
|
547
|
+
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Back" })
|
|
450
548
|
]
|
|
451
549
|
}
|
|
452
|
-
)
|
|
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 })
|
|
453
553
|
] })
|
|
454
554
|
) : (
|
|
455
555
|
/* Home mode: [Bot icon] Support Assistant [✕] */
|
|
@@ -464,23 +564,10 @@ function SupportAgentPanel({
|
|
|
464
564
|
) }),
|
|
465
565
|
/* @__PURE__ */ jsx3("span", { className: "text-sm font-semibold text-foreground", children: "Support Assistant" })
|
|
466
566
|
] }),
|
|
467
|
-
/* @__PURE__ */
|
|
468
|
-
Button,
|
|
469
|
-
{
|
|
470
|
-
variant: "ghost",
|
|
471
|
-
size: "icon",
|
|
472
|
-
className: "size-7",
|
|
473
|
-
onClick: onClose,
|
|
474
|
-
title: "Close",
|
|
475
|
-
children: [
|
|
476
|
-
/* @__PURE__ */ jsx3(X2, { className: "size-3.5" }),
|
|
477
|
-
/* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Close" })
|
|
478
|
-
]
|
|
479
|
-
}
|
|
480
|
-
)
|
|
567
|
+
/* @__PURE__ */ jsx3(CloseButton, { onClick: onClose })
|
|
481
568
|
] })
|
|
482
569
|
),
|
|
483
|
-
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 }) })
|
|
484
571
|
] }),
|
|
485
572
|
/* @__PURE__ */ jsx3("div", { className: "flex flex-1 flex-col overflow-y-auto", children: isLoading ? (
|
|
486
573
|
/* Loading state */
|
|
@@ -488,6 +575,20 @@ function SupportAgentPanel({
|
|
|
488
575
|
/* @__PURE__ */ jsx3(Spinner, { size: "lg", className: "text-muted-foreground" }),
|
|
489
576
|
/* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: "Loading\u2026" })
|
|
490
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." }) })
|
|
491
592
|
) : !hasMessages ? (
|
|
492
593
|
/* Home state — Rovo pattern: New Chat CTA + Recents + Suggested */
|
|
493
594
|
/* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-5 p-4", children: [
|
|
@@ -506,31 +607,21 @@ function SupportAgentPanel({
|
|
|
506
607
|
),
|
|
507
608
|
hasRecents && /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-1", children: [
|
|
508
609
|
/* @__PURE__ */ jsx3("p", { className: "px-1 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Recents" }),
|
|
509
|
-
/* @__PURE__ */ jsx3("div", { className: "flex flex-col", children:
|
|
510
|
-
|
|
610
|
+
/* @__PURE__ */ jsx3("div", { className: "flex flex-col", children: recentsPreview.map((conv) => /* @__PURE__ */ jsx3(
|
|
611
|
+
ConversationRow,
|
|
511
612
|
{
|
|
512
|
-
|
|
613
|
+
conv,
|
|
513
614
|
onClick: () => onOpenConversation == null ? void 0 : onOpenConversation(conv.id),
|
|
514
|
-
className: "
|
|
515
|
-
children: [
|
|
516
|
-
/* @__PURE__ */ jsx3("span", { className: "flex-1 truncate", children: conv.title }),
|
|
517
|
-
/* @__PURE__ */ jsx3(
|
|
518
|
-
ChevronRight,
|
|
519
|
-
{
|
|
520
|
-
className: "size-3.5 shrink-0 text-muted-foreground",
|
|
521
|
-
"aria-hidden": "true"
|
|
522
|
-
}
|
|
523
|
-
)
|
|
524
|
-
]
|
|
615
|
+
className: "px-1 py-2.5"
|
|
525
616
|
},
|
|
526
617
|
conv.id
|
|
527
618
|
)) }),
|
|
528
|
-
|
|
619
|
+
/* @__PURE__ */ jsxs3(
|
|
529
620
|
Button,
|
|
530
621
|
{
|
|
531
622
|
variant: "ghost",
|
|
532
623
|
size: "sm",
|
|
533
|
-
onClick:
|
|
624
|
+
onClick: handleViewAll,
|
|
534
625
|
className: "h-auto w-fit gap-0.5 px-1 py-1 text-xs text-muted-foreground hover:bg-transparent hover:text-foreground",
|
|
535
626
|
children: [
|
|
536
627
|
"View all conversations",
|
|
@@ -569,7 +660,8 @@ function SupportAgentPanel({
|
|
|
569
660
|
onAttachFile,
|
|
570
661
|
onAttachImage,
|
|
571
662
|
disabled: isLoading || isStreaming,
|
|
572
|
-
placeholder: "Ask anything\u2026"
|
|
663
|
+
placeholder: "Ask anything\u2026",
|
|
664
|
+
showMarkdownToolbar: true
|
|
573
665
|
}
|
|
574
666
|
) })
|
|
575
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";
|