@epicbagel/saas-kit 1.6.0 → 1.10.0

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 (81) hide show
  1. package/README.md +71 -1
  2. package/THIRD_PARTY_NOTICES.md +14 -0
  3. package/dist/chunk-2BSFYU22.cjs +71 -0
  4. package/dist/{chunk-GTVSRRE3.cjs → chunk-BGCNGYPL.cjs} +2 -2
  5. package/dist/{chunk-QTWJQQDH.cjs → chunk-FBVZRRA4.cjs} +6 -6
  6. package/dist/chunk-GJ7S3L6R.js +71 -0
  7. package/dist/{chunk-LKPM6DQP.cjs → chunk-HTCW6AEH.cjs} +51 -72
  8. package/dist/{chunk-F3B4M6DU.js → chunk-HTPPNW74.js} +1 -1
  9. package/dist/chunk-KUG4ONYC.js +127 -0
  10. package/dist/{chunk-TI57GAQP.js → chunk-KWV5KTOA.js} +48 -69
  11. package/dist/{chunk-JN6JOSZG.js → chunk-LQPJGZIE.js} +7 -7
  12. package/dist/chunk-M2ZNC3TK.js +316 -0
  13. package/dist/chunk-O6F3LVZY.cjs +316 -0
  14. package/dist/chunk-UW67GSZ4.cjs +127 -0
  15. package/dist/chunk-VBKJXNEL.js +157 -0
  16. package/dist/chunk-XB2D4NQK.cjs +157 -0
  17. package/dist/hooks/use-agent-audio-visualizer-bar.cjs +8 -0
  18. package/dist/hooks/use-agent-audio-visualizer-bar.d.cts +4 -0
  19. package/dist/hooks/use-agent-audio-visualizer-bar.d.ts +4 -0
  20. package/dist/hooks/use-agent-audio-visualizer-bar.js +8 -0
  21. package/dist/hooks/use-dictation.cjs +10 -0
  22. package/dist/hooks/use-dictation.d.cts +56 -0
  23. package/dist/hooks/use-dictation.d.ts +56 -0
  24. package/dist/hooks/use-dictation.js +10 -0
  25. package/dist/primitives/activity-feed.cjs +3 -3
  26. package/dist/primitives/activity-feed.js +4 -4
  27. package/dist/primitives/agent-audio-visualizer-bar.cjs +16 -0
  28. package/dist/primitives/agent-audio-visualizer-bar.d.cts +75 -0
  29. package/dist/primitives/agent-audio-visualizer-bar.d.ts +75 -0
  30. package/dist/primitives/agent-audio-visualizer-bar.js +16 -0
  31. package/dist/primitives/archive-confirmation-dialog.cjs +2 -2
  32. package/dist/primitives/archive-confirmation-dialog.js +3 -3
  33. package/dist/primitives/board-view.cjs +6 -6
  34. package/dist/primitives/board-view.js +5 -5
  35. package/dist/primitives/chat.cjs +127 -48
  36. package/dist/primitives/chat.d.cts +25 -3
  37. package/dist/primitives/chat.d.ts +25 -3
  38. package/dist/primitives/chat.js +122 -43
  39. package/dist/primitives/code-block.cjs +4 -4
  40. package/dist/primitives/code-block.js +3 -3
  41. package/dist/primitives/connection.cjs +6 -6
  42. package/dist/primitives/connection.js +7 -7
  43. package/dist/primitives/copy-button.cjs +3 -3
  44. package/dist/primitives/copy-button.js +2 -2
  45. package/dist/primitives/dictation-provider.cjs +8 -0
  46. package/dist/primitives/dictation-provider.d.cts +2 -0
  47. package/dist/primitives/dictation-provider.d.ts +2 -0
  48. package/dist/primitives/dictation-provider.js +8 -0
  49. package/dist/primitives/editable-list.cjs +1 -1
  50. package/dist/primitives/editable-list.js +1 -1
  51. package/dist/primitives/file-dropzone.cjs +3 -3
  52. package/dist/primitives/file-dropzone.js +2 -2
  53. package/dist/primitives/file-preview.cjs +6 -6
  54. package/dist/primitives/file-preview.js +5 -5
  55. package/dist/primitives/filter-bar.cjs +4 -4
  56. package/dist/primitives/filter-bar.js +3 -3
  57. package/dist/primitives/input-group.d.cts +1 -1
  58. package/dist/primitives/input-group.d.ts +1 -1
  59. package/dist/primitives/resource-list.cjs +6 -6
  60. package/dist/primitives/resource-list.js +5 -5
  61. package/dist/primitives/section.cjs +2 -2
  62. package/dist/primitives/section.js +3 -3
  63. package/dist/primitives/sheet.d.cts +1 -1
  64. package/dist/primitives/sheet.d.ts +1 -1
  65. package/dist/primitives/switch-field.cjs +2 -2
  66. package/dist/primitives/switch-field.js +3 -3
  67. package/dist/primitives/theme-selector.cjs +3 -3
  68. package/dist/primitives/theme-selector.js +4 -4
  69. package/dist/primitives/voice-dictation-button.cjs +3 -2
  70. package/dist/primitives/voice-dictation-button.js +2 -1
  71. package/dist/primitives/voice-session-controls.cjs +12 -0
  72. package/dist/primitives/voice-session-controls.d.cts +29 -0
  73. package/dist/primitives/voice-session-controls.d.ts +29 -0
  74. package/dist/primitives/voice-session-controls.js +12 -0
  75. package/package.json +51 -1
  76. package/dist/{chunk-HREEZUKL.js → chunk-DILYV4FI.js} +3 -3
  77. package/dist/{chunk-MU4F3DSW.cjs → chunk-FARCLWLU.cjs} +2 -2
  78. package/dist/{chunk-CRTH5GJ5.cjs → chunk-MW67PHAQ.cjs} +3 -3
  79. package/dist/{chunk-KNKV25WS.js → chunk-UFFHGKI7.js} +3 -3
  80. package/dist/{chunk-HBRVOGLA.js → chunk-WHDHUYS6.js} +3 -3
  81. package/dist/{chunk-Z3JJSNR5.cjs → chunk-ZLEM2SAU.cjs} +2 -2
@@ -2,12 +2,15 @@
2
2
  "use client";
3
3
 
4
4
 
5
+ var _chunkUW67GSZ4cjs = require('../chunk-UW67GSZ4.cjs');
6
+
7
+
5
8
 
6
9
 
7
10
  var _chunk2BTDBZYNcjs = require('../chunk-2BTDBZYN.cjs');
8
11
 
9
12
 
10
- var _chunkLKPM6DQPcjs = require('../chunk-LKPM6DQP.cjs');
13
+ var _chunkHTCW6AEHcjs = require('../chunk-HTCW6AEH.cjs');
11
14
 
12
15
 
13
16
 
@@ -15,21 +18,21 @@ var _chunkM4V7OJNFcjs = require('../chunk-M4V7OJNF.cjs');
15
18
 
16
19
 
17
20
 
21
+ var _chunkB765DSRGcjs = require('../chunk-B765DSRG.cjs');
18
22
 
19
23
 
20
24
 
21
25
 
22
- var _chunk5VMKDVB6cjs = require('../chunk-5VMKDVB6.cjs');
23
26
 
24
27
 
25
28
 
29
+ var _chunk5VMKDVB6cjs = require('../chunk-5VMKDVB6.cjs');
26
30
 
27
31
 
28
- var _chunkNWDPH2Z7cjs = require('../chunk-NWDPH2Z7.cjs');
29
32
 
30
33
 
31
34
 
32
- var _chunkB765DSRGcjs = require('../chunk-B765DSRG.cjs');
35
+ var _chunkNWDPH2Z7cjs = require('../chunk-NWDPH2Z7.cjs');
33
36
 
34
37
 
35
38
 
@@ -39,7 +42,7 @@ require('../chunk-2HV2KKOE.cjs');
39
42
 
40
43
 
41
44
 
42
- var _chunkZ3JJSNR5cjs = require('../chunk-Z3JJSNR5.cjs');
45
+ var _chunkZLEM2SAUcjs = require('../chunk-ZLEM2SAU.cjs');
43
46
 
44
47
 
45
48
  var _chunkKENBU3NVcjs = require('../chunk-KENBU3NV.cjs');
@@ -50,6 +53,7 @@ require('../chunk-ELPV44S6.cjs');
50
53
 
51
54
 
52
55
  var _chunkZAITUDYDcjs = require('../chunk-ZAITUDYD.cjs');
56
+ require('../chunk-U2NES7VR.cjs');
53
57
 
54
58
 
55
59
 
@@ -67,17 +71,22 @@ require('../chunk-W5HPHEE7.cjs');
67
71
 
68
72
 
69
73
  var _chunkFYRQFEU4cjs = require('../chunk-FYRQFEU4.cjs');
70
- require('../chunk-U2NES7VR.cjs');
71
74
 
72
75
 
73
76
  var _chunk2KFZQJH5cjs = require('../chunk-2KFZQJH5.cjs');
74
77
  require('../chunk-PQUSJEXL.cjs');
78
+ require('../chunk-XB2D4NQK.cjs');
75
79
 
76
80
 
77
81
  var _chunkJDEXZGIYcjs = require('../chunk-JDEXZGIY.cjs');
78
82
 
79
83
 
84
+ var _chunkKWLSBTB2cjs = require('../chunk-KWLSBTB2.cjs');
85
+ require('../chunk-2BSFYU22.cjs');
86
+
87
+
80
88
  var _chunk4LXN6GLZcjs = require('../chunk-4LXN6GLZ.cjs');
89
+ require('../chunk-O6F3LVZY.cjs');
81
90
 
82
91
 
83
92
  var _chunkR35FT53Gcjs = require('../chunk-R35FT53G.cjs');
@@ -85,9 +94,6 @@ var _chunkR35FT53Gcjs = require('../chunk-R35FT53G.cjs');
85
94
 
86
95
  var _chunkH2UFRLLNcjs = require('../chunk-H2UFRLLN.cjs');
87
96
 
88
-
89
- var _chunkKWLSBTB2cjs = require('../chunk-KWLSBTB2.cjs');
90
-
91
97
  // src/primitives/chat.tsx
92
98
 
93
99
 
@@ -372,6 +378,7 @@ function ChatInput({
372
378
  size = "md",
373
379
  uploadingLabel,
374
380
  voice = true,
381
+ voiceSession,
375
382
  voiceTitle,
376
383
  voiceLang,
377
384
  submitLabel,
@@ -397,6 +404,7 @@ function ChatInput({
397
404
  const isDisabled = pending || disabled;
398
405
  const attachmentsReady = attachments.length > 0 && attachments.every((item) => item.state !== "uploading");
399
406
  const canSubmit = !isDisabled && (Boolean(value.trim()) || attachmentsReady);
407
+ const liveVoiceActive = voiceSession && voiceSession.state !== "disconnected" && voiceSession.state !== "error";
400
408
  const submit = () => {
401
409
  const trimmed = value.trim();
402
410
  if (!trimmed && !attachmentsReady || isDisabled) return;
@@ -457,6 +465,7 @@ function ChatInput({
457
465
  className
458
466
  ),
459
467
  children: [
468
+ liveVoiceActive && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk7LDJAXRXcjs.InputGroupAddon, { align: "block-start", className: "w-full border-b border-border", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUW67GSZ4cjs.VoiceSessionControls, { ...voiceSession }) }),
460
469
  attachments.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
461
470
  ChatAttachmentList,
462
471
  {
@@ -523,12 +532,21 @@ function ChatInput({
523
532
  addFilesLabel
524
533
  ] }) })
525
534
  ] }),
535
+ helperText ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
536
+ "span",
537
+ {
538
+ "data-slot": "chat-input-helper",
539
+ className: _chunkKWLSBTB2cjs.cn.call(void 0, "min-w-0 flex-1 truncate px-1 text-center text-xs font-normal text-muted-foreground sm:px-2 sm:text-sm", compact && "hidden"),
540
+ children: helperText
541
+ }
542
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: compact ? "hidden" : "flex-1" }),
526
543
  voice && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
527
- _chunkLKPM6DQPcjs.VoiceDictationButton,
544
+ _chunkHTCW6AEHcjs.VoiceDictationButton,
528
545
  {
529
546
  size: "icon",
530
547
  title: voiceTitle,
531
548
  lang: voiceLang,
549
+ disabled: Boolean(isDisabled || liveVoiceActive),
532
550
  onCommit: (text) => onSend(text),
533
551
  className: _chunkKWLSBTB2cjs.cn.call(void 0,
534
552
  spacious && "border-transparent bg-transparent shadow-none hover:bg-muted",
@@ -537,14 +555,7 @@ function ChatInput({
537
555
  )
538
556
  }
539
557
  ),
540
- helperText ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
541
- "span",
542
- {
543
- "data-slot": "chat-input-helper",
544
- className: _chunkKWLSBTB2cjs.cn.call(void 0, "min-w-0 flex-1 truncate px-1 text-center text-xs font-normal text-muted-foreground sm:px-2 sm:text-sm", compact && "hidden"),
545
- children: helperText
546
- }
547
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: compact ? "hidden" : "flex-1" }),
558
+ voiceSession && !liveVoiceActive && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUW67GSZ4cjs.VoiceSessionControls, { ...voiceSession, disabled: voiceSession.disabled || isDisabled }),
548
559
  submitLabel ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
549
560
  _chunkJDEXZGIYcjs.Button,
550
561
  {
@@ -593,6 +604,8 @@ function ChatInput({
593
604
  }
594
605
  function VoiceHero({
595
606
  onSubmit,
607
+ voice,
608
+ voiceSession,
596
609
  voiceTitle,
597
610
  voiceLang,
598
611
  onSwitchToText,
@@ -600,8 +613,20 @@ function VoiceHero({
600
613
  switchLabel
601
614
  }) {
602
615
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-5 py-6", children: [
603
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
604
- _chunkLKPM6DQPcjs.VoiceDictationButton,
616
+ voiceSession ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
617
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkUW67GSZ4cjs.VoiceSessionControls, { ...voiceSession, size: "hero" }),
618
+ voice && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
619
+ _chunkHTCW6AEHcjs.VoiceDictationButton,
620
+ {
621
+ size: "icon",
622
+ title: voiceTitle,
623
+ lang: voiceLang,
624
+ onCommit: onSubmit,
625
+ disabled: Boolean(voiceSession.disabled || voiceSession.state !== "disconnected" && voiceSession.state !== "error")
626
+ }
627
+ )
628
+ ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
629
+ _chunkHTCW6AEHcjs.VoiceDictationButton,
605
630
  {
606
631
  size: "lg",
607
632
  title: voiceTitle,
@@ -629,27 +654,40 @@ var EXAMPLE_PROMPT_LAYOUTS = {
629
654
  row: "row",
630
655
  cards: "grid"
631
656
  };
632
- function ExamplePrompts({
633
- prompts,
657
+ function ChatSuggestions({
658
+ slot,
659
+ items,
634
660
  onSelect,
635
- label = "Try",
661
+ label,
662
+ showLabel = true,
636
663
  variant = "chips",
664
+ disabled = false,
637
665
  className
638
666
  }) {
639
667
  const labelId = _react.useId.call(void 0, );
640
- if (prompts.length === 0) return null;
668
+ if (items.length === 0) return null;
641
669
  const cards = variant === "cards";
642
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-slot": "chat-examples", "data-variant": variant, className: _chunkKWLSBTB2cjs.cn.call(void 0, cards ? "mt-4" : "mt-3", className), children: [
643
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { id: labelId, "data-slot": "chat-examples-label", className: "mb-2 text-left text-xs text-muted-foreground", children: label }),
644
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkM4V7OJNFcjs.Suggestions, { role: "group", "aria-labelledby": labelId, layout: EXAMPLE_PROMPT_LAYOUTS[variant], children: prompts.map((prompt) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
645
- _chunkM4V7OJNFcjs.Suggestion,
670
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-slot": slot, "data-variant": variant, className, children: [
671
+ showLabel && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { id: labelId, "data-slot": `${slot}-label`, className: "mb-2 text-left text-xs text-muted-foreground", children: label }),
672
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
673
+ _chunkM4V7OJNFcjs.Suggestions,
646
674
  {
647
- suggestion: prompt,
648
- onClick: onSelect,
649
- className: cards ? "h-auto min-h-12 px-3 py-2.5 text-xs" : void 0
650
- },
651
- prompt
652
- )) })
675
+ role: "group",
676
+ "aria-labelledby": showLabel ? labelId : void 0,
677
+ "aria-label": showLabel ? void 0 : label,
678
+ layout: EXAMPLE_PROMPT_LAYOUTS[variant],
679
+ children: items.map((item) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
680
+ _chunkM4V7OJNFcjs.Suggestion,
681
+ {
682
+ suggestion: item,
683
+ onClick: onSelect,
684
+ disabled,
685
+ className: cards ? "h-auto min-h-12 px-3 py-2.5 text-xs" : void 0
686
+ },
687
+ item
688
+ ))
689
+ }
690
+ )
653
691
  ] });
654
692
  }
655
693
  function ExamplePromptsLoading({ label, className }) {
@@ -693,6 +731,8 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
693
731
  examplePromptsVariant = "chips",
694
732
  examplePromptsLoading = false,
695
733
  examplePromptsLoadingLabel = "Loading suggestions\u2026",
734
+ replySuggestions = [],
735
+ replySuggestionsLabel = "Suggested replies",
696
736
  compactEmptyState = false,
697
737
  defaultMode,
698
738
  placeholder = "Type your message\u2026",
@@ -715,6 +755,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
715
755
  fileDropLabel,
716
756
  fileDropDescription,
717
757
  voice = true,
758
+ voiceSession,
718
759
  voiceTitle,
719
760
  activeVoiceTitle,
720
761
  voiceLang,
@@ -738,7 +779,15 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
738
779
  const inputRef = _react.useRef.call(void 0, null);
739
780
  const conversationStarted = messages.length > 0;
740
781
  const [userMode, setUserMode] = _react.useState.call(void 0, null);
741
- const mode = _nullishCoalesce(_nullishCoalesce(userMode, () => ( defaultMode)), () => ( (isMobile ? "voice" : "text")));
782
+ const mode = !voice && !voiceSession ? "text" : _nullishCoalesce(_nullishCoalesce(userMode, () => ( defaultMode)), () => ( (isMobile ? "voice" : "text")));
783
+ const reportSendError = _react.useCallback.call(void 0,
784
+ (cause) => {
785
+ if (onSendError) onSendError(cause);
786
+ else if (typeof globalThis.reportError === "function") globalThis.reportError(cause);
787
+ else console.error(cause);
788
+ },
789
+ [onSendError]
790
+ );
742
791
  const send = _react.useCallback.call(void 0,
743
792
  async (text, sentAttachments = attachments) => {
744
793
  const trimmed = text.trim();
@@ -751,18 +800,29 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
751
800
  setInput((current) => current ? current : trimmed);
752
801
  if (mode === "voice") setUserMode("text");
753
802
  }
754
- if (onSendError) onSendError(cause);
755
- else if (typeof globalThis.reportError === "function") globalThis.reportError(cause);
756
- else console.error(cause);
803
+ reportSendError(cause);
757
804
  }
758
805
  window.setTimeout(() => _optionalChain([inputRef, 'access', _9 => _9.current, 'optionalAccess', _10 => _10.focus, 'call', _11 => _11()]), 0);
759
806
  },
760
- [attachments, mode, onSend, onSendError, pending]
807
+ [attachments, mode, onSend, pending, reportSendError]
808
+ );
809
+ const sendSuggestion = _react.useCallback.call(void 0,
810
+ async (text) => {
811
+ const trimmed = text.trim();
812
+ if (!trimmed || pending) return;
813
+ try {
814
+ await onSend(trimmed, []);
815
+ } catch (cause) {
816
+ reportSendError(cause);
817
+ }
818
+ window.setTimeout(() => _optionalChain([inputRef, 'access', _12 => _12.current, 'optionalAccess', _13 => _13.focus, 'call', _14 => _14()]), 0);
819
+ },
820
+ [onSend, pending, reportSendError]
761
821
  );
762
822
  _react.useImperativeHandle.call(void 0,
763
823
  ref,
764
824
  () => ({
765
- focusInput: () => _optionalChain([inputRef, 'access', _12 => _12.current, 'optionalAccess', _13 => _13.focus, 'call', _14 => _14()]),
825
+ focusInput: () => _optionalChain([inputRef, 'access', _15 => _15.current, 'optionalAccess', _16 => _16.focus, 'call', _17 => _17()]),
766
826
  clearInput: () => setInput("")
767
827
  }),
768
828
  []
@@ -770,16 +830,17 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
770
830
  const dropFiles = _react.useCallback.call(void 0,
771
831
  (files) => {
772
832
  if (!conversationStarted && mode === "voice") setUserMode("text");
773
- return _optionalChain([onFilesSelected, 'optionalCall', _15 => _15(files)]);
833
+ return _optionalChain([onFilesSelected, 'optionalCall', _18 => _18(files)]);
774
834
  },
775
835
  [conversationStarted, mode, onFilesSelected]
776
836
  );
777
837
  const application = layout === "application";
778
838
  const workspace = layout === "workspace";
779
839
  const showEmptyFileDropzone = emptyFileDropzone && Boolean(onFilesSelected) && attachments.length === 0;
780
- const showEmptyPending = !conversationStarted && pending && Boolean(emptyPendingContent);
840
+ const liveVoiceActive = voiceSession && voiceSession.state !== "disconnected" && voiceSession.state !== "error";
841
+ const showEmptyPending = !conversationStarted && pending && Boolean(emptyPendingContent) && !liveVoiceActive;
781
842
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
782
- _chunkZ3JJSNR5cjs.FileDropArea,
843
+ _chunkZLEM2SAUcjs.FileDropArea,
783
844
  {
784
845
  "data-slot": "chat",
785
846
  "data-layout": layout,
@@ -847,7 +908,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
847
908
  ),
848
909
  children: [
849
910
  showEmptyFileDropzone && onFilesSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
850
- _chunkZ3JJSNR5cjs.FileDropzone,
911
+ _chunkZLEM2SAUcjs.FileDropzone,
851
912
  {
852
913
  multiple: true,
853
914
  onFiles: onFilesSelected,
@@ -862,6 +923,8 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
862
923
  VoiceHero,
863
924
  {
864
925
  onSubmit: (text) => void send(text),
926
+ voice,
927
+ voiceSession: voiceSession ? { ...voiceSession, disabled: voiceSession.disabled || pending } : void 0,
865
928
  voiceTitle,
866
929
  voiceLang,
867
930
  label: voiceHeroLabel,
@@ -878,6 +941,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
878
941
  placeholder,
879
942
  size: showEmptyFileDropzone || application && isMobile ? "md" : "lg",
880
943
  voice,
944
+ voiceSession,
881
945
  voiceTitle,
882
946
  voiceLang,
883
947
  submitLabel,
@@ -898,12 +962,14 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
898
962
  error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatError, { children: error }),
899
963
  !pending && examplePromptsLoading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ExamplePromptsLoading, { label: examplePromptsLoadingLabel }),
900
964
  !pending && !examplePromptsLoading && examplePrompts.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
901
- ExamplePrompts,
965
+ ChatSuggestions,
902
966
  {
903
- prompts: examplePrompts,
904
- onSelect: (p) => void send(p),
967
+ slot: "chat-examples",
968
+ items: examplePrompts,
969
+ onSelect: (prompt) => void sendSuggestion(prompt),
905
970
  label: examplePromptsLabel,
906
- variant: examplePromptsVariant
971
+ variant: examplePromptsVariant,
972
+ className: examplePromptsVariant === "cards" ? "mt-4" : "mt-3"
907
973
  }
908
974
  ),
909
975
  emptyFooter && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "chat-empty-footer", className: "mt-5", children: emptyFooter })
@@ -946,6 +1012,18 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
946
1012
  workspace && mobileCompactComposer && "max-md:pb-[max(0.75rem,env(safe-area-inset-bottom))] max-md:pt-3"
947
1013
  ),
948
1014
  children: [
1015
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1016
+ ChatSuggestions,
1017
+ {
1018
+ slot: "chat-replies",
1019
+ items: replySuggestions,
1020
+ onSelect: (reply) => void sendSuggestion(reply),
1021
+ label: replySuggestionsLabel,
1022
+ showLabel: false,
1023
+ disabled: pending,
1024
+ className: _chunkKWLSBTB2cjs.cn.call(void 0, "mb-3", workspace && "mx-auto max-w-3xl")
1025
+ }
1026
+ ),
949
1027
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
950
1028
  ChatInput,
951
1029
  {
@@ -956,6 +1034,7 @@ var Chat = _react.forwardRef.call(void 0, function Chat2({
956
1034
  placeholder: activePlaceholder,
957
1035
  size: composerAppearance === "spacious" ? "lg" : "sm",
958
1036
  voice,
1037
+ voiceSession,
959
1038
  voiceTitle: _nullishCoalesce(activeVoiceTitle, () => ( voiceTitle)),
960
1039
  voiceLang,
961
1040
  inputRef,
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React$1 from 'react';
3
3
  import { ReactNode } from 'react';
4
+ import { VoiceSessionControlsProps } from './voice-session-controls.cjs';
4
5
  import { MarkdownComponents } from './markdown.cjs';
5
6
  import 'react-markdown';
6
7
  import './rich-text.cjs';
@@ -153,6 +154,8 @@ interface ChatInputProps {
153
154
  uploadingLabel?: string;
154
155
  /** Show the inline voice dictation button. Defaults to true. */
155
156
  voice?: boolean;
157
+ /** A separate live voice control alongside dictation. The host owns its transport and lifecycle. */
158
+ voiceSession?: VoiceSessionControlsProps;
156
159
  /** Title shown inside the voice overlay. */
157
160
  voiceTitle?: string;
158
161
  /** Language tag for voice dictation. */
@@ -210,7 +213,7 @@ interface ChatInputProps {
210
213
  * `<Chat>` instead of composing `<ChatInput>` directly if you want
211
214
  * device-aware default modes.
212
215
  */
213
- declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, helperText, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
216
+ declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceSession, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, helperText, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
214
217
  interface ChatProps {
215
218
  /** Conversation messages. */
216
219
  messages: ChatMessage[];
@@ -249,7 +252,10 @@ interface ChatProps {
249
252
  emptyTitle?: ReactNode;
250
253
  /** Subheadline shown under the headline. */
251
254
  emptySubtitle?: ReactNode;
252
- /** Optional list of suggested starter prompts. Click → sends. */
255
+ /**
256
+ * Optional list of suggested starter prompts, under the empty-state
257
+ * composer. Picking one sends it as `replySuggestions` do.
258
+ */
253
259
  examplePrompts?: ReadonlyArray<string>;
254
260
  /** Label above the example prompts. Defaults to "Try". */
255
261
  examplePromptsLabel?: string;
@@ -303,6 +309,19 @@ interface ChatProps {
303
309
  addFilesLabel?: string;
304
310
  /** Shown on a file, staged or on a message, while it is still uploading. Defaults to "Uploading…". */
305
311
  uploadingLabel?: string;
312
+ /**
313
+ * Replies the conversation offers next, such as the choices the latest
314
+ * assistant turn asked for. Once the conversation has started they show
315
+ * at the composer, directly above the input and at its width, as the same
316
+ * suggestion chips as `examplePrompts`, wrapping onto as many lines as
317
+ * they need. Picking one sends only its words: the draft and any staged
318
+ * files stay in the composer, and a failed send is reported
319
+ * (`onSendError`) without touching them. Disabled while `pending`. Pass
320
+ * none (the default) to show none; drop them once they no longer apply.
321
+ */
322
+ replySuggestions?: ReadonlyArray<string>;
323
+ /** The reply suggestions' accessible name. Defaults to "Suggested replies". */
324
+ replySuggestionsLabel?: string;
306
325
  /** Visual treatment for both empty and active text composers. */
307
326
  composerAppearance?: ChatInputProps["appearance"];
308
327
  /**
@@ -338,6 +357,8 @@ interface ChatProps {
338
357
  fileDropDescription?: ReactNode;
339
358
  /** Enable voice dictation. Defaults to true. */
340
359
  voice?: boolean;
360
+ /** Controlled live voice UI, used instead of browser dictation when provided. */
361
+ voiceSession?: VoiceSessionControlsProps;
341
362
  /** Title shown inside the voice overlay. */
342
363
  voiceTitle?: string;
343
364
  /** Title shown inside the voice overlay in the active state. */
@@ -406,7 +427,8 @@ interface ChatHandle {
406
427
  * - Optional example prompts render as suggestions below the input.
407
428
  *
408
429
  * **Active state** (messages exist) — always the compact text input;
409
- * the mic stays as an accessory icon.
430
+ * the mic stays as an accessory icon. Optional reply suggestions render as
431
+ * the same suggestions, directly above the input.
410
432
  *
411
433
  * **Files** — with `onFilesSelected`, the composer's menu picks files and a
412
434
  * file dragged anywhere on the conversation can be dropped (`fileDrop`);
@@ -1,6 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React$1 from 'react';
3
3
  import { ReactNode } from 'react';
4
+ import { VoiceSessionControlsProps } from './voice-session-controls.js';
4
5
  import { MarkdownComponents } from './markdown.js';
5
6
  import 'react-markdown';
6
7
  import './rich-text.js';
@@ -153,6 +154,8 @@ interface ChatInputProps {
153
154
  uploadingLabel?: string;
154
155
  /** Show the inline voice dictation button. Defaults to true. */
155
156
  voice?: boolean;
157
+ /** A separate live voice control alongside dictation. The host owns its transport and lifecycle. */
158
+ voiceSession?: VoiceSessionControlsProps;
156
159
  /** Title shown inside the voice overlay. */
157
160
  voiceTitle?: string;
158
161
  /** Language tag for voice dictation. */
@@ -210,7 +213,7 @@ interface ChatInputProps {
210
213
  * `<Chat>` instead of composing `<ChatInput>` directly if you want
211
214
  * device-aware default modes.
212
215
  */
213
- declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, helperText, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
216
+ declare function ChatInput({ value, onChange, onSend, pending, disabled, placeholder, size, uploadingLabel, voice, voiceSession, voiceTitle, voiceLang, submitLabel, autoFocus, className, inputRef, attachments, onFilesSelected, onRemoveAttachment, accept, multiple, addFilesLabel, appearance, compactOnBlur, helperText, privacyNote, }: ChatInputProps): react_jsx_runtime.JSX.Element;
214
217
  interface ChatProps {
215
218
  /** Conversation messages. */
216
219
  messages: ChatMessage[];
@@ -249,7 +252,10 @@ interface ChatProps {
249
252
  emptyTitle?: ReactNode;
250
253
  /** Subheadline shown under the headline. */
251
254
  emptySubtitle?: ReactNode;
252
- /** Optional list of suggested starter prompts. Click → sends. */
255
+ /**
256
+ * Optional list of suggested starter prompts, under the empty-state
257
+ * composer. Picking one sends it as `replySuggestions` do.
258
+ */
253
259
  examplePrompts?: ReadonlyArray<string>;
254
260
  /** Label above the example prompts. Defaults to "Try". */
255
261
  examplePromptsLabel?: string;
@@ -303,6 +309,19 @@ interface ChatProps {
303
309
  addFilesLabel?: string;
304
310
  /** Shown on a file, staged or on a message, while it is still uploading. Defaults to "Uploading…". */
305
311
  uploadingLabel?: string;
312
+ /**
313
+ * Replies the conversation offers next, such as the choices the latest
314
+ * assistant turn asked for. Once the conversation has started they show
315
+ * at the composer, directly above the input and at its width, as the same
316
+ * suggestion chips as `examplePrompts`, wrapping onto as many lines as
317
+ * they need. Picking one sends only its words: the draft and any staged
318
+ * files stay in the composer, and a failed send is reported
319
+ * (`onSendError`) without touching them. Disabled while `pending`. Pass
320
+ * none (the default) to show none; drop them once they no longer apply.
321
+ */
322
+ replySuggestions?: ReadonlyArray<string>;
323
+ /** The reply suggestions' accessible name. Defaults to "Suggested replies". */
324
+ replySuggestionsLabel?: string;
306
325
  /** Visual treatment for both empty and active text composers. */
307
326
  composerAppearance?: ChatInputProps["appearance"];
308
327
  /**
@@ -338,6 +357,8 @@ interface ChatProps {
338
357
  fileDropDescription?: ReactNode;
339
358
  /** Enable voice dictation. Defaults to true. */
340
359
  voice?: boolean;
360
+ /** Controlled live voice UI, used instead of browser dictation when provided. */
361
+ voiceSession?: VoiceSessionControlsProps;
341
362
  /** Title shown inside the voice overlay. */
342
363
  voiceTitle?: string;
343
364
  /** Title shown inside the voice overlay in the active state. */
@@ -406,7 +427,8 @@ interface ChatHandle {
406
427
  * - Optional example prompts render as suggestions below the input.
407
428
  *
408
429
  * **Active state** (messages exist) — always the compact text input;
409
- * the mic stays as an accessory icon.
430
+ * the mic stays as an accessory icon. Optional reply suggestions render as
431
+ * the same suggestions, directly above the input.
410
432
  *
411
433
  * **Files** — with `onFilesSelected`, the composer's menu picks files and a
412
434
  * file dragged anywhere on the conversation can be dropped (`fileDrop`);