@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.
Files changed (30) hide show
  1. package/.turbo/turbo-build.log +84 -84
  2. package/CHANGELOG.md +6 -0
  3. package/dist/{chunk-MGIDYXOP.mjs → chunk-DWNLBUDC.mjs} +459 -67
  4. package/dist/{chunk-EFHPSKVF.mjs → chunk-EGM4DARZ.mjs} +110 -1
  5. package/dist/{chunk-STN5QIWN.mjs → chunk-GIQGZFP6.mjs} +102 -45
  6. package/dist/{chunk-B5PSUONN.mjs → chunk-TF5TOVIM.mjs} +1 -1
  7. package/dist/{chunk-RRROLESJ.mjs → chunk-XHZONBL4.mjs} +1 -1
  8. package/dist/components/ui/ai-assistant-drawer.js +101 -0
  9. package/dist/components/ui/ai-assistant-drawer.mjs +2 -2
  10. package/dist/components/ui/ai-conversations/index.js +101 -0
  11. package/dist/components/ui/ai-conversations/index.mjs +2 -2
  12. package/dist/components/ui/chat-input-area.js +101 -0
  13. package/dist/components/ui/chat-input-area.mjs +1 -1
  14. package/dist/components/ui/policy-ai/index.js +818 -261
  15. package/dist/components/ui/policy-ai/index.mjs +11 -2
  16. package/dist/components/ui/support-agent/index.js +202 -44
  17. package/dist/components/ui/support-agent/index.mjs +2 -2
  18. package/dist/index.js +3490 -3329
  19. package/dist/index.mjs +5 -5
  20. package/dist/styles.css +1 -1
  21. package/package.json +1 -1
  22. package/src/components/ui/chat-input-area.tsx +181 -2
  23. package/src/components/ui/policy-ai/index.tsx +12 -0
  24. package/src/components/ui/policy-ai/policy-ai-context-sidebar.tsx +231 -0
  25. package/src/components/ui/policy-ai/policy-ai-history-panel.tsx +175 -0
  26. package/src/components/ui/policy-ai/policy-ai-page.tsx +243 -0
  27. package/src/components/ui/policy-ai/policy-ai-panel.tsx +64 -57
  28. package/src/components/ui/policy-ai/policy-ai-responses.tsx +8 -12
  29. package/src/components/ui/support-agent/support-agent-panel.tsx +124 -46
  30. 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 { ImagePlus, Paperclip, Send } from "lucide-react";
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-EFHPSKVF.mjs";
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
- isChatMode ? (
457
- /* Chat mode: [←] Conversation title [✕] */
514
+ showAllConversations ? (
515
+ /* All-conversations mode: [←] All conversations [✕] */
458
516
  /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-1", children: [
459
- onBack && /* @__PURE__ */ jsxs3(
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: onBack,
466
- title: "Back to conversations",
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: conversationTitle }),
474
- /* @__PURE__ */ jsxs3(
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: onClose,
481
- title: "Close",
543
+ onClick: onBack,
544
+ title: "Back to conversations",
482
545
  children: [
483
- /* @__PURE__ */ jsx3(X2, { className: "size-3.5" }),
484
- /* @__PURE__ */ jsx3("span", { className: "sr-only", children: "Close" })
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__ */ jsxs3(
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: recentConversations.map((conv) => /* @__PURE__ */ jsxs3(
545
- "button",
610
+ /* @__PURE__ */ jsx3("div", { className: "flex flex-col", children: recentsPreview.map((conv) => /* @__PURE__ */ jsx3(
611
+ ConversationRow,
546
612
  {
547
- type: "button",
613
+ conv,
548
614
  onClick: () => onOpenConversation == null ? void 0 : onOpenConversation(conv.id),
549
- className: "flex w-full items-center justify-between gap-2 px-1 py-2.5 text-left text-sm text-foreground hover:bg-muted/50",
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
- onViewAllConversations && /* @__PURE__ */ jsxs3(
619
+ /* @__PURE__ */ jsxs3(
564
620
  Button,
565
621
  {
566
622
  variant: "ghost",
567
623
  size: "sm",
568
- onClick: onViewAllConversations,
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
  ]
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ChatInputArea
3
- } from "./chunk-EFHPSKVF.mjs";
3
+ } from "./chunk-EGM4DARZ.mjs";
4
4
  import {
5
5
  Sheet,
6
6
  SheetContent
@@ -33,7 +33,7 @@ import {
33
33
  } from "./chunk-2GIYVERS.mjs";
34
34
  import {
35
35
  ChatInputArea
36
- } from "./chunk-EFHPSKVF.mjs";
36
+ } from "./chunk-EGM4DARZ.mjs";
37
37
  import {
38
38
  Textarea
39
39
  } from "./chunk-BS75ICOO.mjs";
@@ -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-B5PSUONN.mjs";
4
- import "../../chunk-EFHPSKVF.mjs";
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-RRROLESJ.mjs";
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-EFHPSKVF.mjs";
19
+ import "../../../chunk-EGM4DARZ.mjs";
20
20
  import "../../../chunk-BS75ICOO.mjs";
21
21
  import "../../../chunk-X6RC5UWB.mjs";
22
22
  import "../../../chunk-F3CU6KEI.mjs";