@wealthx/shadcn 1.5.37 → 1.5.38

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 (34) hide show
  1. package/.turbo/turbo-build.log +99 -93
  2. package/CHANGELOG.md +6 -0
  3. package/dist/{chunk-734FOOJC.mjs → chunk-B5PSUONN.mjs} +25 -58
  4. package/dist/chunk-EFHPSKVF.mjs +192 -0
  5. package/dist/{chunk-NB3ZL36B.mjs → chunk-MZI77ZMX.mjs} +17 -2
  6. package/dist/chunk-R7M657QL.mjs +587 -0
  7. package/dist/{chunk-DIH2NZZ3.mjs → chunk-RRROLESJ.mjs} +33 -23
  8. package/dist/components/ui/ai-assistant-drawer.js +269 -121
  9. package/dist/components/ui/ai-assistant-drawer.mjs +2 -1
  10. package/dist/components/ui/ai-conversations/index.js +474 -286
  11. package/dist/components/ui/ai-conversations/index.mjs +2 -1
  12. package/dist/components/ui/chat-input-area.js +429 -0
  13. package/dist/components/ui/chat-input-area.mjs +11 -0
  14. package/dist/components/ui/page-top-bar.js +182 -5
  15. package/dist/components/ui/page-top-bar.mjs +3 -1
  16. package/dist/components/ui/support-agent/index.js +1131 -0
  17. package/dist/components/ui/support-agent/index.mjs +27 -0
  18. package/dist/index.js +4760 -4027
  19. package/dist/index.mjs +54 -36
  20. package/dist/styles.css +1 -1
  21. package/package.json +11 -1
  22. package/src/components/index.tsx +24 -0
  23. package/src/components/ui/ai-assistant-drawer.tsx +24 -51
  24. package/src/components/ui/ai-conversations/index.tsx +16 -8
  25. package/src/components/ui/ai-conversations/thread.tsx +38 -27
  26. package/src/components/ui/chat-input-area.tsx +244 -0
  27. package/src/components/ui/page-top-bar.tsx +31 -5
  28. package/src/components/ui/support-agent/index.tsx +25 -0
  29. package/src/components/ui/support-agent/support-agent-fab.tsx +116 -0
  30. package/src/components/ui/support-agent/support-agent-panel.tsx +498 -0
  31. package/src/components/ui/support-agent/support-agent-primitives.tsx +354 -0
  32. package/src/styles/globals.css +1 -0
  33. package/src/styles/styles-css.ts +1 -1
  34. package/tsup.config.ts +2 -0
@@ -62,8 +62,8 @@ __export(ai_assistant_drawer_exports, {
62
62
  AiAssistantDrawer: () => AiAssistantDrawer
63
63
  });
64
64
  module.exports = __toCommonJS(ai_assistant_drawer_exports);
65
- var React3 = __toESM(require("react"));
66
- var import_lucide_react4 = require("lucide-react");
65
+ var React4 = __toESM(require("react"));
66
+ var import_lucide_react5 = require("lucide-react");
67
67
 
68
68
  // src/lib/utils.ts
69
69
  var import_clsx = require("clsx");
@@ -367,10 +367,208 @@ function Badge(_a) {
367
367
  );
368
368
  }
369
369
 
370
- // src/components/ui/spinner.tsx
371
- var import_class_variance_authority3 = require("class-variance-authority");
370
+ // src/components/ui/chat-input-area.tsx
371
+ var React3 = __toESM(require("react"));
372
372
  var import_lucide_react3 = require("lucide-react");
373
+
374
+ // src/components/ui/textarea.tsx
373
375
  var import_jsx_runtime5 = require("react/jsx-runtime");
376
+ function Textarea(_a) {
377
+ var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
378
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
379
+ "textarea",
380
+ __spreadValues({
381
+ className: cn(
382
+ // WealthX: removed shadow-xs (flat panels), added font-sans
383
+ "flex field-sizing-content min-h-16 w-full border border-input bg-transparent px-3 py-2 text-body-medium font-sans transition-[color,box-shadow] outline-none placeholder:font-normal placeholder:text-muted-foreground focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/20 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
384
+ className
385
+ ),
386
+ "data-slot": "textarea"
387
+ }, props)
388
+ );
389
+ }
390
+
391
+ // src/components/ui/chat-input-area.tsx
392
+ var import_jsx_runtime6 = require("react/jsx-runtime");
393
+ var DEFAULT_HINT = "Enter to send \xB7 Shift+Enter for new line";
394
+ function ChatInputArea({
395
+ value,
396
+ onChange,
397
+ onSend,
398
+ onAttachFile,
399
+ onAttachImage,
400
+ disabled = false,
401
+ placeholder = "Type your message\u2026",
402
+ hint = DEFAULT_HINT,
403
+ maxHeight = 160,
404
+ autoFocus = false,
405
+ className
406
+ }) {
407
+ const textareaRef = React3.useRef(null);
408
+ const fileInputRef = React3.useRef(null);
409
+ const imageInputRef = React3.useRef(null);
410
+ React3.useEffect(() => {
411
+ if (autoFocus) {
412
+ setTimeout(() => {
413
+ var _a;
414
+ return (_a = textareaRef.current) == null ? void 0 : _a.focus();
415
+ }, 50);
416
+ }
417
+ }, [autoFocus]);
418
+ const handleSend = React3.useCallback(() => {
419
+ const text = value.trim();
420
+ if (!text || disabled) return;
421
+ onSend(text);
422
+ if (textareaRef.current) {
423
+ textareaRef.current.style.height = "auto";
424
+ }
425
+ }, [value, disabled, onSend]);
426
+ const handleKeyDown = React3.useCallback(
427
+ (e) => {
428
+ if (e.key === "Enter" && !e.shiftKey) {
429
+ e.preventDefault();
430
+ handleSend();
431
+ }
432
+ },
433
+ [handleSend]
434
+ );
435
+ const handleTextareaChange = React3.useCallback(
436
+ (e) => {
437
+ onChange(e.target.value);
438
+ const el = e.target;
439
+ el.style.height = "auto";
440
+ el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;
441
+ },
442
+ [onChange, maxHeight]
443
+ );
444
+ const handleFileChange = React3.useCallback(
445
+ (e) => {
446
+ var _a;
447
+ if ((_a = e.target.files) == null ? void 0 : _a.length) {
448
+ onAttachFile == null ? void 0 : onAttachFile(e.target.files);
449
+ e.target.value = "";
450
+ }
451
+ },
452
+ [onAttachFile]
453
+ );
454
+ const handleImageChange = React3.useCallback(
455
+ (e) => {
456
+ var _a;
457
+ if ((_a = e.target.files) == null ? void 0 : _a.length) {
458
+ onAttachImage == null ? void 0 : onAttachImage(e.target.files);
459
+ e.target.value = "";
460
+ }
461
+ },
462
+ [onAttachImage]
463
+ );
464
+ const showFileButton = typeof onAttachFile === "function";
465
+ const showImageButton = typeof onAttachImage === "function";
466
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
467
+ "div",
468
+ {
469
+ "data-slot": "chat-input-area",
470
+ className: cn("flex flex-col gap-1.5", className),
471
+ children: [
472
+ /* @__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: [
473
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
474
+ Textarea,
475
+ {
476
+ ref: textareaRef,
477
+ value,
478
+ onChange: handleTextareaChange,
479
+ onKeyDown: handleKeyDown,
480
+ placeholder,
481
+ disabled,
482
+ rows: 3,
483
+ className: "resize-none text-sm border-0 shadow-none focus-visible:ring-0 px-3 pt-3 pb-1 min-h-[72px]",
484
+ "aria-label": placeholder
485
+ }
486
+ ),
487
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between px-2 pb-2", children: [
488
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-0.5", children: [
489
+ showFileButton && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
490
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
491
+ Button,
492
+ {
493
+ variant: "ghost",
494
+ size: "icon-sm",
495
+ type: "button",
496
+ title: "Attach file",
497
+ "aria-label": "Attach file",
498
+ disabled,
499
+ onClick: () => {
500
+ var _a;
501
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
502
+ },
503
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.Paperclip, { className: "size-3.5", "aria-hidden": "true" })
504
+ }
505
+ ),
506
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
507
+ "input",
508
+ {
509
+ ref: fileInputRef,
510
+ type: "file",
511
+ multiple: true,
512
+ className: "sr-only",
513
+ tabIndex: -1,
514
+ onChange: handleFileChange
515
+ }
516
+ )
517
+ ] }),
518
+ showImageButton && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
519
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
520
+ Button,
521
+ {
522
+ variant: "ghost",
523
+ size: "icon-sm",
524
+ type: "button",
525
+ title: "Upload image",
526
+ "aria-label": "Upload image",
527
+ disabled,
528
+ onClick: () => {
529
+ var _a;
530
+ return (_a = imageInputRef.current) == null ? void 0 : _a.click();
531
+ },
532
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.ImagePlus, { className: "size-3.5", "aria-hidden": "true" })
533
+ }
534
+ ),
535
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
536
+ "input",
537
+ {
538
+ ref: imageInputRef,
539
+ type: "file",
540
+ multiple: true,
541
+ accept: "image/*",
542
+ className: "sr-only",
543
+ tabIndex: -1,
544
+ onChange: handleImageChange
545
+ }
546
+ )
547
+ ] })
548
+ ] }),
549
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
550
+ Button,
551
+ {
552
+ size: "icon-sm",
553
+ type: "button",
554
+ "aria-label": "Send message",
555
+ disabled: !value.trim() || disabled,
556
+ onClick: handleSend,
557
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react3.Send, { className: "size-3.5", "aria-hidden": "true" })
558
+ }
559
+ )
560
+ ] })
561
+ ] }),
562
+ hint !== false && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-xs text-muted-foreground", children: hint })
563
+ ]
564
+ }
565
+ );
566
+ }
567
+
568
+ // src/components/ui/spinner.tsx
569
+ var import_class_variance_authority3 = require("class-variance-authority");
570
+ var import_lucide_react4 = require("lucide-react");
571
+ var import_jsx_runtime7 = require("react/jsx-runtime");
374
572
  var spinnerVariants = (0, import_class_variance_authority3.cva)("animate-spin shrink-0", {
375
573
  variants: {
376
574
  size: {
@@ -386,8 +584,8 @@ var spinnerVariants = (0, import_class_variance_authority3.cva)("animate-spin sh
386
584
  });
387
585
  function Spinner(_a) {
388
586
  var _b = _a, { className, size } = _b, props = __objRest(_b, ["className", "size"]);
389
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
390
- import_lucide_react3.LoaderCircle,
587
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
588
+ import_lucide_react4.LoaderCircle,
391
589
  __spreadValues({
392
590
  "aria-hidden": "true",
393
591
  className: cn(spinnerVariants({ size }), className),
@@ -396,27 +594,10 @@ function Spinner(_a) {
396
594
  );
397
595
  }
398
596
 
399
- // src/components/ui/textarea.tsx
400
- var import_jsx_runtime6 = require("react/jsx-runtime");
401
- function Textarea(_a) {
402
- var _b = _a, { className } = _b, props = __objRest(_b, ["className"]);
403
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
404
- "textarea",
405
- __spreadValues({
406
- className: cn(
407
- // WealthX: removed shadow-xs (flat panels), added font-sans
408
- "flex field-sizing-content min-h-16 w-full border border-input bg-transparent px-3 py-2 text-body-medium font-sans transition-[color,box-shadow] outline-none placeholder:font-normal placeholder:text-muted-foreground focus-visible:border-primary focus-visible:ring-[3px] focus-visible:ring-primary/20 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
409
- className
410
- ),
411
- "data-slot": "textarea"
412
- }, props)
413
- );
414
- }
415
-
416
597
  // src/components/ui/ai-assistant-drawer.tsx
417
- var import_jsx_runtime7 = require("react/jsx-runtime");
598
+ var import_jsx_runtime8 = require("react/jsx-runtime");
418
599
  function AiTypingIndicator() {
419
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "flex items-center gap-1 py-1", "aria-label": "AI is thinking", children: [0, 150, 300].map((delay) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
600
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "flex items-center gap-1 py-1", "aria-label": "AI is thinking", children: [0, 150, 300].map((delay) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
420
601
  "span",
421
602
  {
422
603
  className: "size-1.5 rounded-full bg-current animate-bounce",
@@ -429,11 +610,11 @@ function AiTypingIndicator() {
429
610
  function AiChatBubble({ message }) {
430
611
  const isUser = message.role === "user";
431
612
  const isEmpty = !message.content.trim();
432
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
613
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
433
614
  "div",
434
615
  {
435
616
  className: cn("flex w-full", isUser ? "justify-end" : "justify-start"),
436
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
617
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
437
618
  "div",
438
619
  {
439
620
  className: cn(
@@ -442,8 +623,8 @@ function AiChatBubble({ message }) {
442
623
  message.isErrored && "bg-destructive/10 text-destructive"
443
624
  ),
444
625
  children: [
445
- isEmpty && message.isStreaming ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AiTypingIndicator, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "whitespace-pre-wrap break-words leading-relaxed", children: message.content }),
446
- message.isErrored && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mt-1 text-xs opacity-70", children: "Failed to send. Please try again." })
626
+ isEmpty && message.isStreaming ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AiTypingIndicator, {}) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "whitespace-pre-wrap break-words leading-relaxed", children: message.content }),
627
+ message.isErrored && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "mt-1 text-xs opacity-70", children: "Failed to send. Please try again." })
447
628
  ]
448
629
  }
449
630
  )
@@ -454,7 +635,7 @@ function AiTaskCard({
454
635
  suggestion,
455
636
  onSelect
456
637
  }) {
457
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
638
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
458
639
  Button,
459
640
  {
460
641
  type: "button",
@@ -462,8 +643,8 @@ function AiTaskCard({
462
643
  onClick: () => onSelect(suggestion.title),
463
644
  className: "h-auto w-full flex-col items-start gap-1 border border-border bg-background p-3 text-left hover:bg-muted/50",
464
645
  children: [
465
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-sm font-medium text-foreground", children: suggestion.title }),
466
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-xs text-muted-foreground", children: suggestion.description })
646
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm font-medium text-foreground", children: suggestion.title }),
647
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-xs text-muted-foreground", children: suggestion.description })
467
648
  ]
468
649
  }
469
650
  );
@@ -499,47 +680,34 @@ function AiAssistantDrawer({
499
680
  isStreaming = false,
500
681
  isLoading = false,
501
682
  onSendMessage,
683
+ onAttachFile,
684
+ onAttachImage,
502
685
  onReset,
503
686
  className
504
687
  }) {
505
688
  var _a;
506
- const [inputValue, setInputValue] = React3.useState("");
507
- const messagesEndRef = React3.useRef(null);
508
- const textareaRef = React3.useRef(null);
689
+ const [inputValue, setInputValue] = React4.useState("");
690
+ const messagesEndRef = React4.useRef(null);
509
691
  const suggestions = taskSuggestions != null ? taskSuggestions : DEFAULT_SUGGESTIONS;
510
692
  const hasMessages = messages.length > 0;
511
- const canSend = inputValue.trim().length > 0 && !isStreaming && !isLoading;
512
- React3.useEffect(() => {
693
+ React4.useEffect(() => {
513
694
  if (!messagesEndRef.current) return;
514
695
  messagesEndRef.current.scrollIntoView({
515
696
  behavior: "smooth",
516
697
  block: "nearest"
517
698
  });
518
699
  }, [messages.length]);
519
- React3.useEffect(() => {
520
- const el = textareaRef.current;
521
- if (!el) return;
522
- el.style.height = "auto";
523
- el.style.height = `${Math.min(el.scrollHeight, 120)}px`;
524
- }, [inputValue]);
525
- const handleSend = React3.useCallback(() => {
526
- const text = inputValue.trim();
527
- if (!text || !canSend) return;
528
- onSendMessage == null ? void 0 : onSendMessage(text);
529
- setInputValue("");
530
- }, [inputValue, canSend, onSendMessage]);
531
- const handleKeyDown = (e) => {
532
- if (e.key === "Enter" && !e.shiftKey) {
533
- e.preventDefault();
534
- handleSend();
535
- }
536
- };
700
+ const handleSend = React4.useCallback(
701
+ (text) => {
702
+ onSendMessage == null ? void 0 : onSendMessage(text);
703
+ setInputValue("");
704
+ },
705
+ [onSendMessage]
706
+ );
537
707
  const handleSuggestionSelect = (text) => {
538
- var _a2;
539
708
  setInputValue(text);
540
- (_a2 = textareaRef.current) == null ? void 0 : _a2.focus();
541
709
  };
542
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Sheet, { open, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
710
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Sheet, { open, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
543
711
  SheetContent,
544
712
  {
545
713
  side: "right",
@@ -547,16 +715,16 @@ function AiAssistantDrawer({
547
715
  className: cn("w-[480px] max-w-full gap-0 p-0", className),
548
716
  "data-slot": "ai-assistant-drawer",
549
717
  children: [
550
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between border-b border-border px-4 py-3", children: [
551
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-3", children: [
552
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-full bg-primary", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react4.Bot, { className: "size-4 text-primary-foreground" }) }),
553
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col", children: [
554
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-sm font-semibold text-foreground", children: "AI Assistant" }),
555
- opportunityName && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-xs text-muted-foreground", children: opportunityName })
718
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between border-b border-border px-4 py-3", children: [
719
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-3", children: [
720
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "flex size-8 shrink-0 items-center justify-center rounded-full bg-primary", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.Bot, { className: "size-4 text-primary-foreground" }) }),
721
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col", children: [
722
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-sm font-semibold text-foreground", children: "AI Assistant" }),
723
+ opportunityName && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-xs text-muted-foreground", children: opportunityName })
556
724
  ] })
557
725
  ] }),
558
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-1", children: [
559
- onReset && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
726
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-1", children: [
727
+ onReset && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
560
728
  Button,
561
729
  {
562
730
  variant: "ghost",
@@ -566,12 +734,12 @@ function AiAssistantDrawer({
566
734
  title: "Reset conversation",
567
735
  disabled: isLoading,
568
736
  children: [
569
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react4.RotateCcw, { className: "size-4" }),
570
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "sr-only", children: "Reset conversation" })
737
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.RotateCcw, { className: "size-4" }),
738
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "sr-only", children: "Reset conversation" })
571
739
  ]
572
740
  }
573
741
  ),
574
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
742
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
575
743
  Button,
576
744
  {
577
745
  variant: "ghost",
@@ -580,25 +748,25 @@ function AiAssistantDrawer({
580
748
  onClick: onClose,
581
749
  title: "Close",
582
750
  children: [
583
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react4.X, { className: "size-4" }),
584
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "sr-only", children: "Close" })
751
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.X, { className: "size-4" }),
752
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "sr-only", children: "Close" })
585
753
  ]
586
754
  }
587
755
  )
588
756
  ] })
589
757
  ] }),
590
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-1 flex-col overflow-y-auto", children: isLoading ? (
758
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex flex-1 flex-col overflow-y-auto", children: isLoading ? (
591
759
  /* Loading state */
592
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex flex-1 items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col items-center gap-3", children: [
593
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Spinner, { size: "lg", className: "text-muted-foreground" }),
594
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-sm text-muted-foreground", children: "Initialising\u2026" })
760
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex flex-1 items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col items-center gap-3", children: [
761
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Spinner, { size: "lg", className: "text-muted-foreground" }),
762
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-sm text-muted-foreground", children: "Initialising\u2026" })
595
763
  ] }) })
596
764
  ) : !hasMessages ? (
597
765
  /* Empty / welcome state */
598
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-6 p-4", children: [
599
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-3 border border-border bg-muted/30 p-4", children: [
600
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(Badge, { variant: "outline", className: "w-fit gap-1.5", children: [
601
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
766
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col gap-6 p-4", children: [
767
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col gap-3 border border-border bg-muted/30 p-4", children: [
768
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Badge, { variant: "outline", className: "w-fit gap-1.5", children: [
769
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
602
770
  "span",
603
771
  {
604
772
  className: "size-1.5 rounded-full bg-primary",
@@ -607,12 +775,12 @@ function AiAssistantDrawer({
607
775
  ),
608
776
  "AI Chat for Brokers"
609
777
  ] }),
610
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-sm text-muted-foreground", children: "A safe and secure way to chat about insights that run your business and utilise AI. All chats stay within your environment, all closed off and compliant." }),
611
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex gap-2", children: [
778
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-sm text-muted-foreground", children: "A safe and secure way to chat about insights that run your business and utilise AI. All chats stay within your environment, all closed off and compliant." }),
779
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex gap-2", children: [
612
780
  { emoji: "\u{1F916}", label: "Smart" },
613
781
  { emoji: "\u26A1", label: "Fast" },
614
782
  { emoji: "\u{1F512}", label: "Secure" }
615
- ].map(({ emoji, label }) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
783
+ ].map(({ emoji, label }) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
616
784
  "span",
617
785
  {
618
786
  className: "border border-border px-2.5 py-1 text-xs text-foreground",
@@ -625,9 +793,9 @@ function AiAssistantDrawer({
625
793
  label
626
794
  )) })
627
795
  ] }),
628
- suggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-2", children: [
629
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-xs font-medium text-muted-foreground", children: "Suggested tasks" }),
630
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "grid grid-cols-2 gap-2", children: suggestions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
796
+ suggestions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col gap-2", children: [
797
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-xs font-medium text-muted-foreground", children: "Suggested tasks" }),
798
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "grid grid-cols-2 gap-2", children: suggestions.map((s) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
631
799
  AiTaskCard,
632
800
  {
633
801
  suggestion: s,
@@ -639,44 +807,24 @@ function AiAssistantDrawer({
639
807
  ] })
640
808
  ) : (
641
809
  /* Message list */
642
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
643
- messages.map((msg) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AiChatBubble, { message: msg }, msg.id)),
644
- isStreaming && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) === "user" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-muted px-3 py-2 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(AiTypingIndicator, {}) }) }),
645
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref: messagesEndRef })
810
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex flex-col gap-3 p-4", children: [
811
+ messages.map((msg) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AiChatBubble, { message: msg }, msg.id)),
812
+ isStreaming && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) === "user" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex justify-start", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "bg-muted px-3 py-2 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(AiTypingIndicator, {}) }) }),
813
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: messagesEndRef })
646
814
  ] })
647
815
  ) }),
648
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "border-t border-border p-3", children: [
649
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-end gap-2", children: [
650
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
651
- Textarea,
652
- {
653
- ref: textareaRef,
654
- value: inputValue,
655
- onChange: (e) => setInputValue(e.target.value),
656
- onKeyDown: handleKeyDown,
657
- placeholder: "Ask me anything\u2026 (Enter to send, Shift+Enter for new line)",
658
- rows: 1,
659
- disabled: isLoading,
660
- className: "min-h-0 flex-1 resize-none overflow-hidden py-2 text-sm"
661
- }
662
- ),
663
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
664
- Button,
665
- {
666
- size: "icon",
667
- onClick: handleSend,
668
- disabled: !canSend,
669
- className: "shrink-0",
670
- title: "Send",
671
- children: [
672
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react4.Send, { className: "size-4" }),
673
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "sr-only", children: "Send message" })
674
- ]
675
- }
676
- )
677
- ] }),
678
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mt-1.5 text-[10px] text-muted-foreground", children: "Enter to send \xB7 Shift+Enter for new line" })
679
- ] })
816
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "border-t border-border p-3", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
817
+ ChatInputArea,
818
+ {
819
+ value: inputValue,
820
+ onChange: setInputValue,
821
+ onSend: handleSend,
822
+ onAttachFile,
823
+ onAttachImage,
824
+ disabled: isLoading || isStreaming,
825
+ placeholder: "Ask me anything\u2026"
826
+ }
827
+ ) })
680
828
  ]
681
829
  }
682
830
  ) });
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  AiAssistantDrawer
3
- } from "../../chunk-734FOOJC.mjs";
3
+ } from "../../chunk-B5PSUONN.mjs";
4
+ import "../../chunk-EFHPSKVF.mjs";
4
5
  import "../../chunk-H3PTREG6.mjs";
5
6
  import "../../chunk-BS75ICOO.mjs";
6
7
  import "../../chunk-JVMXMFBB.mjs";