@epicbagel/saas-kit 1.0.0 → 1.2.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 (120) hide show
  1. package/README.md +72 -3
  2. package/THIRD_PARTY_NOTICES.md +230 -7
  3. package/dist/chunk-2AU7ZRGX.cjs +96 -0
  4. package/dist/chunk-2BTDBZYN.cjs +154 -0
  5. package/dist/chunk-2HV2KKOE.cjs +38 -0
  6. package/dist/chunk-2KFZQJH5.cjs +29 -0
  7. package/dist/chunk-32Q4XOTU.cjs +204 -0
  8. package/dist/chunk-42RTTHND.js +29 -0
  9. package/dist/chunk-6FC65AZQ.js +38 -0
  10. package/dist/chunk-B765DSRG.cjs +66 -0
  11. package/dist/chunk-ELPV44S6.cjs +44 -0
  12. package/dist/chunk-EOUO3ORO.cjs +244 -0
  13. package/dist/chunk-EZCKWTH7.js +204 -0
  14. package/dist/chunk-F366BHWH.js +116 -0
  15. package/dist/chunk-GFG2R5BZ.js +132 -0
  16. package/dist/chunk-HAC32ALJ.js +244 -0
  17. package/dist/chunk-INNGGLMZ.js +44 -0
  18. package/dist/chunk-IW4ZIXXG.js +66 -0
  19. package/dist/chunk-JZOBIPFC.js +96 -0
  20. package/dist/chunk-KADJ56AH.cjs +416 -0
  21. package/dist/chunk-KENBU3NV.cjs +27 -0
  22. package/dist/chunk-M7FYGAGO.js +416 -0
  23. package/dist/chunk-MHYAVXOE.js +159 -0
  24. package/dist/chunk-RIWLAMME.cjs +159 -0
  25. package/dist/chunk-SUB4BAYE.cjs +73 -0
  26. package/dist/chunk-THWIJG5C.js +73 -0
  27. package/dist/chunk-V4YWTRLD.cjs +116 -0
  28. package/dist/chunk-VY5U4VGV.js +27 -0
  29. package/dist/chunk-XABXUP6L.cjs +132 -0
  30. package/dist/chunk-Z45YKVAM.js +154 -0
  31. package/dist/primitives/action-dock.cjs +8 -0
  32. package/dist/primitives/action-dock.d.cts +10 -0
  33. package/dist/primitives/action-dock.d.ts +10 -0
  34. package/dist/primitives/action-dock.js +8 -0
  35. package/dist/primitives/attachment.cjs +25 -203
  36. package/dist/primitives/attachment.d.cts +1 -1
  37. package/dist/primitives/attachment.d.ts +1 -1
  38. package/dist/primitives/attachment.js +12 -190
  39. package/dist/primitives/badge.d.cts +1 -1
  40. package/dist/primitives/badge.d.ts +1 -1
  41. package/dist/primitives/board-view.cjs +3 -3
  42. package/dist/primitives/board-view.js +2 -2
  43. package/dist/primitives/bubble.cjs +14 -0
  44. package/dist/primitives/bubble.d.cts +21 -0
  45. package/dist/primitives/bubble.d.ts +21 -0
  46. package/dist/primitives/bubble.js +14 -0
  47. package/dist/primitives/button.d.cts +3 -3
  48. package/dist/primitives/button.d.ts +3 -3
  49. package/dist/primitives/chat.cjs +881 -0
  50. package/dist/primitives/chat.d.cts +345 -0
  51. package/dist/primitives/chat.d.ts +345 -0
  52. package/dist/primitives/chat.js +881 -0
  53. package/dist/primitives/connection.cjs +6 -6
  54. package/dist/primitives/connection.js +7 -7
  55. package/dist/primitives/file-dropzone.cjs +7 -107
  56. package/dist/primitives/file-dropzone.d.cts +66 -3
  57. package/dist/primitives/file-dropzone.d.ts +66 -3
  58. package/dist/primitives/file-dropzone.js +13 -113
  59. package/dist/primitives/input-group.cjs +21 -0
  60. package/dist/primitives/input-group.d.cts +20 -0
  61. package/dist/primitives/input-group.d.ts +20 -0
  62. package/dist/primitives/input-group.js +21 -0
  63. package/dist/primitives/item.cjs +197 -0
  64. package/dist/primitives/item.d.cts +28 -0
  65. package/dist/primitives/item.d.ts +28 -0
  66. package/dist/primitives/item.js +197 -0
  67. package/dist/primitives/lazy-markdown.cjs +10 -0
  68. package/dist/primitives/lazy-markdown.d.cts +20 -0
  69. package/dist/primitives/lazy-markdown.d.ts +20 -0
  70. package/dist/primitives/lazy-markdown.js +10 -0
  71. package/dist/primitives/markdown.cjs +17 -0
  72. package/dist/primitives/markdown.d.cts +32 -0
  73. package/dist/primitives/markdown.d.ts +32 -0
  74. package/dist/primitives/markdown.js +17 -0
  75. package/dist/primitives/marker.cjs +14 -0
  76. package/dist/primitives/marker.d.cts +15 -0
  77. package/dist/primitives/marker.d.ts +15 -0
  78. package/dist/primitives/marker.js +14 -0
  79. package/dist/primitives/message-scroller.cjs +26 -0
  80. package/dist/primitives/message-scroller.d.cts +16 -0
  81. package/dist/primitives/message-scroller.d.ts +16 -0
  82. package/dist/primitives/message-scroller.js +26 -0
  83. package/dist/primitives/message.cjs +7 -84
  84. package/dist/primitives/message.js +8 -85
  85. package/dist/primitives/resource-list.cjs +3 -3
  86. package/dist/primitives/resource-list.js +2 -2
  87. package/dist/primitives/rich-text.cjs +3 -38
  88. package/dist/primitives/rich-text.js +3 -38
  89. package/dist/primitives/section-header.d.cts +1 -1
  90. package/dist/primitives/section-header.d.ts +1 -1
  91. package/dist/primitives/spinner.cjs +23 -0
  92. package/dist/primitives/spinner.d.cts +6 -0
  93. package/dist/primitives/spinner.d.ts +6 -0
  94. package/dist/primitives/spinner.js +23 -0
  95. package/dist/primitives/suggestion.cjs +11 -0
  96. package/dist/primitives/suggestion.d.cts +19 -0
  97. package/dist/primitives/suggestion.d.ts +19 -0
  98. package/dist/primitives/suggestion.js +11 -0
  99. package/dist/primitives/switch-field.cjs +2 -2
  100. package/dist/primitives/switch-field.js +3 -3
  101. package/dist/primitives/textarea.cjs +4 -33
  102. package/dist/primitives/textarea.js +3 -32
  103. package/dist/primitives/toggle-group.d.cts +2 -2
  104. package/dist/primitives/toggle-group.d.ts +2 -2
  105. package/dist/primitives/toggle.d.cts +2 -2
  106. package/dist/primitives/toggle.d.ts +2 -2
  107. package/dist/primitives/trace.cjs +23 -0
  108. package/dist/primitives/trace.d.cts +22 -0
  109. package/dist/primitives/trace.d.ts +22 -0
  110. package/dist/primitives/trace.js +23 -0
  111. package/dist/primitives/voice-dictation-button.cjs +5 -239
  112. package/dist/primitives/voice-dictation-button.js +4 -238
  113. package/package.json +125 -2
  114. package/src/styles/components/bubble.css +81 -0
  115. package/src/styles/components/marker.css +27 -0
  116. package/src/styles/components/message-scroller.css +11 -0
  117. package/src/styles/components.css +3 -0
  118. package/src/styles/utilities.css +3 -2
  119. package/dist/{chunk-UGF2K6NR.js → chunk-HRLP4BHJ.js} +6 -6
  120. package/dist/{chunk-RWWOFWLP.cjs → chunk-IH3COANJ.cjs} +3 -3
@@ -0,0 +1,881 @@
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }"use client";
2
+ "use client";
3
+
4
+
5
+
6
+
7
+ var _chunk2BTDBZYNcjs = require('../chunk-2BTDBZYN.cjs');
8
+
9
+
10
+ var _chunkEOUO3OROcjs = require('../chunk-EOUO3ORO.cjs');
11
+
12
+
13
+
14
+ var _chunkSUB4BAYEcjs = require('../chunk-SUB4BAYE.cjs');
15
+
16
+
17
+
18
+ var _chunkB765DSRGcjs = require('../chunk-B765DSRG.cjs');
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+ var _chunkXABXUP6Lcjs = require('../chunk-XABXUP6L.cjs');
27
+
28
+
29
+
30
+ var _chunk2AU7ZRGXcjs = require('../chunk-2AU7ZRGX.cjs');
31
+
32
+
33
+
34
+
35
+ var _chunkRIWLAMMEcjs = require('../chunk-RIWLAMME.cjs');
36
+ require('../chunk-2HV2KKOE.cjs');
37
+
38
+
39
+ var _chunkKENBU3NVcjs = require('../chunk-KENBU3NV.cjs');
40
+ require('../chunk-ELPV44S6.cjs');
41
+
42
+
43
+
44
+ var _chunkKADJ56AHcjs = require('../chunk-KADJ56AH.cjs');
45
+
46
+
47
+
48
+
49
+
50
+ var _chunkZAITUDYDcjs = require('../chunk-ZAITUDYD.cjs');
51
+
52
+
53
+
54
+ var _chunkV4YWTRLDcjs = require('../chunk-V4YWTRLD.cjs');
55
+ require('../chunk-373W6VAD.cjs');
56
+ require('../chunk-W5HPHEE7.cjs');
57
+
58
+
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+ var _chunk32Q4XOTUcjs = require('../chunk-32Q4XOTU.cjs');
68
+ require('../chunk-U2NES7VR.cjs');
69
+
70
+
71
+ var _chunk2KFZQJH5cjs = require('../chunk-2KFZQJH5.cjs');
72
+ require('../chunk-PQUSJEXL.cjs');
73
+
74
+
75
+ var _chunkL4DH72UFcjs = require('../chunk-L4DH72UF.cjs');
76
+
77
+
78
+ var _chunkR35FT53Gcjs = require('../chunk-R35FT53G.cjs');
79
+
80
+
81
+ var _chunkH2UFRLLNcjs = require('../chunk-H2UFRLLN.cjs');
82
+
83
+
84
+ var _chunkKWLSBTB2cjs = require('../chunk-KWLSBTB2.cjs');
85
+
86
+ // src/primitives/chat.tsx
87
+
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+ var _react = require('react');
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+ var _lucidereact = require('lucide-react');
108
+ var _jsxruntime = require('react/jsx-runtime');
109
+ function useArrivingUserTurnId(messages) {
110
+ const seen = _react.useRef.call(void 0, null);
111
+ seen.current ??= new Set(messages.map((m) => m.id));
112
+ _react.useEffect.call(void 0, () => {
113
+ seen.current = new Set(messages.map((m) => m.id));
114
+ }, [messages]);
115
+ for (let i = messages.length - 1; i >= 0; i--) {
116
+ const message = messages[i];
117
+ if (message.role === "user") return seen.current.has(message.id) ? void 0 : message.id;
118
+ }
119
+ return void 0;
120
+ }
121
+ function TimelineMarker({ label }) {
122
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkB765DSRGcjs.Marker, { variant: "separator", role: "separator", "aria-label": label, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkB765DSRGcjs.MarkerContent, { children: label }) });
123
+ }
124
+ var ChatThread = _react.forwardRef.call(void 0,
125
+ function ChatThread2({
126
+ messages,
127
+ pending = false,
128
+ pendingLabel = "Thinking\u2026",
129
+ scrollButtonLabel = "Scroll to latest message",
130
+ uploadingLabel,
131
+ maxHeight = "46vh",
132
+ appearance = "bubbles",
133
+ footer,
134
+ markdownComponents,
135
+ onOpenAttachment,
136
+ attachmentAction = "open",
137
+ className
138
+ }, ref) {
139
+ const timelineNow = /* @__PURE__ */ new Date();
140
+ const anchorId = useArrivingUserTurnId(messages);
141
+ const workspace = appearance === "workspace";
142
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerProvider, { autoScroll: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
143
+ _chunkXABXUP6Lcjs.MessageScroller,
144
+ {
145
+ ref,
146
+ style: { maxHeight },
147
+ className: _chunkKWLSBTB2cjs.cn.call(void 0, "min-h-0", className),
148
+ children: [
149
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerViewport, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
150
+ _chunkXABXUP6Lcjs.MessageScrollerContent,
151
+ {
152
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
153
+ workspace ? "mx-auto w-full max-w-3xl gap-7 px-4 py-6 md:px-6 md:py-8" : "gap-2.5 px-px py-px"
154
+ ),
155
+ children: [
156
+ messages.map((m, index) => {
157
+ const isUser = m.role === "user";
158
+ const isFullWidth = m.width === "full";
159
+ const relativeTime = _chunkH2UFRLLNcjs.formatRelativeLong.call(void 0, m.createdAt, timelineNow);
160
+ const previousRelativeTime = _chunkH2UFRLLNcjs.formatRelativeLong.call(void 0, _optionalChain([messages, 'access', _ => _[index - 1], 'optionalAccess', _2 => _2.createdAt]), timelineNow);
161
+ const startsTimelineSection = relativeTime && relativeTime !== previousRelativeTime;
162
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
163
+ _chunkXABXUP6Lcjs.MessageScrollerItem,
164
+ {
165
+ messageId: m.id,
166
+ scrollAnchor: m.id === anchorId,
167
+ className: "flex flex-col gap-3",
168
+ children: [
169
+ startsTimelineSection ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TimelineMarker, { label: relativeTime }) : null,
170
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2AU7ZRGXcjs.Message, { align: isUser ? "end" : "start", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk2AU7ZRGXcjs.MessageContent, { children: [
171
+ (m.content || m.text) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
172
+ _chunkV4YWTRLDcjs.Bubble,
173
+ {
174
+ variant: workspace ? isUser ? "muted" : "ghost" : isUser ? "default" : "muted",
175
+ align: isUser ? "end" : "start",
176
+ className: isFullWidth ? "w-full" : void 0,
177
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
178
+ _chunkV4YWTRLDcjs.BubbleContent,
179
+ {
180
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
181
+ isFullWidth && "w-full",
182
+ workspace ? isUser ? "rounded-2xl px-4 py-2.5 text-[15px] leading-7" : "px-0 py-0 text-[15px] leading-7" : "px-3.5 py-2 text-sm leading-relaxed"
183
+ ),
184
+ children: _nullishCoalesce(m.content, () => ( (m.text ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkKENBU3NVcjs.LazyMarkdown, { size: workspace ? "base" : "sm", components: markdownComponents, children: m.text }) : null)))
185
+ }
186
+ )
187
+ }
188
+ ),
189
+ m.attachments && m.attachments.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
190
+ ChatAttachmentList,
191
+ {
192
+ attachments: m.attachments,
193
+ onOpen: onOpenAttachment,
194
+ openAction: attachmentAction,
195
+ uploadingLabel,
196
+ className: "px-0 pt-0"
197
+ }
198
+ )
199
+ ] }) })
200
+ ]
201
+ },
202
+ m.id
203
+ );
204
+ }),
205
+ pending && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerItem, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2AU7ZRGXcjs.Message, { align: "start", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2AU7ZRGXcjs.MessageContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BTDBZYNcjs.Trace, { className: workspace ? void 0 : "px-3.5 py-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BTDBZYNcjs.TraceLine, { status: "running", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BTDBZYNcjs.TraceTitle, { children: pendingLabel }) }) }) }) }) }),
206
+ footer && // Always painted: content-visibility:auto would contain the
207
+ // footer's paint and layout, clipping a ring or shadow at its
208
+ // edge and re-parenting anything fixed inside it.
209
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerItem, { className: "[content-visibility:visible]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2AU7ZRGXcjs.Message, { align: "start", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2AU7ZRGXcjs.MessageContent, { children: footer }) }) })
210
+ ]
211
+ }
212
+ ) }),
213
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkXABXUP6Lcjs.MessageScrollerButton, { variant: "outline", className: "rounded-full shadow-sm", children: [
214
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowDown, { className: "h-4 w-4" }),
215
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: scrollButtonLabel })
216
+ ] })
217
+ ]
218
+ }
219
+ ) });
220
+ }
221
+ );
222
+ function formatFileSize(size) {
223
+ if (size === void 0) return "File";
224
+ if (size < 1024) return `${size} B`;
225
+ if (size < 1048576) return `${Math.round(size / 1024)} KB`;
226
+ return `${(size / 1048576).toFixed(1)} MB`;
227
+ }
228
+ var ATTACHMENT_ACTIONS = {
229
+ open: { verb: "Open", icon: _lucidereact.ArrowUpRight },
230
+ download: { verb: "Download", icon: _lucidereact.Download }
231
+ };
232
+ var COMPOSER_SIZES = {
233
+ sm: { minHeight: "min-h-12", rows: 2 },
234
+ md: { minHeight: "min-h-[4.5rem]", rows: 2 },
235
+ lg: { minHeight: "min-h-32", rows: 3 }
236
+ };
237
+ function ChatAttachmentList({
238
+ attachments,
239
+ onRemove,
240
+ onOpen,
241
+ openAction = "open",
242
+ uploadingLabel = "Uploading\u2026",
243
+ className
244
+ }) {
245
+ const { verb, icon: ActionIcon } = ATTACHMENT_ACTIONS[openAction];
246
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk32Q4XOTUcjs.AttachmentGroup, { className: _chunkKWLSBTB2cjs.cn.call(void 0, "gap-2 px-3 pt-3", className), children: attachments.map((attachment) => {
247
+ const state = _nullishCoalesce(attachment.state, () => ( "done"));
248
+ const opens = Boolean(onOpen) && state === "done";
249
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
250
+ _chunk32Q4XOTUcjs.Attachment,
251
+ {
252
+ state,
253
+ size: "sm",
254
+ className: "min-w-[12rem] rounded-xl p-2",
255
+ children: [
256
+ opens && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
257
+ _chunk32Q4XOTUcjs.AttachmentTrigger,
258
+ {
259
+ "aria-label": `${verb} ${attachment.name}`,
260
+ title: `${verb} ${attachment.name}`,
261
+ onClick: () => _optionalChain([onOpen, 'optionalCall', _3 => _3(attachment)]),
262
+ className: "rounded-xl focus-visible:ring-2 focus-visible:ring-ring/50"
263
+ }
264
+ ),
265
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk32Q4XOTUcjs.AttachmentMedia, { variant: "icon", className: "h-9 w-9 rounded-lg bg-muted", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.FileText, { className: "h-4 w-4" }) }),
266
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk32Q4XOTUcjs.AttachmentContent, { className: "px-2", children: [
267
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk32Q4XOTUcjs.AttachmentTitle, { className: "text-xs font-medium", children: attachment.name }),
268
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk32Q4XOTUcjs.AttachmentDescription, { className: "text-[11px]", children: state === "uploading" ? uploadingLabel : opens ? `${formatFileSize(attachment.size)} \xB7 ${verb}` : formatFileSize(attachment.size) })
269
+ ] }),
270
+ onRemove ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk32Q4XOTUcjs.AttachmentActions, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
271
+ _chunk32Q4XOTUcjs.AttachmentAction,
272
+ {
273
+ type: "button",
274
+ "aria-label": `Remove ${attachment.name}`,
275
+ onClick: () => onRemove(attachment),
276
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.X, { className: "h-3.5 w-3.5" })
277
+ }
278
+ ) }) : opens ? (
279
+ // The trigger covers the whole file; the icon only says what it does.
280
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk32Q4XOTUcjs.AttachmentActions, { "aria-hidden": true, className: "pointer-events-none pr-1 text-muted-foreground", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ActionIcon, { className: "h-4 w-4" }) })
281
+ ) : null
282
+ ]
283
+ },
284
+ attachment.id
285
+ );
286
+ }) });
287
+ }
288
+ function ChatInput({
289
+ value,
290
+ onChange,
291
+ onSend,
292
+ pending = false,
293
+ disabled = false,
294
+ placeholder = "Type your message\u2026",
295
+ size = "md",
296
+ uploadingLabel,
297
+ voice = true,
298
+ voiceTitle,
299
+ voiceLang,
300
+ submitLabel,
301
+ autoFocus = false,
302
+ className,
303
+ inputRef,
304
+ attachments = [],
305
+ onFilesSelected,
306
+ onRemoveAttachment,
307
+ accept,
308
+ multiple = true,
309
+ addFilesLabel = "Add files",
310
+ appearance = "default",
311
+ helperText,
312
+ privacyNote
313
+ }) {
314
+ const internalRef = _react.useRef.call(void 0, null);
315
+ const ref = _nullishCoalesce(inputRef, () => ( internalRef));
316
+ const fileInputRef = _react.useRef.call(void 0, null);
317
+ const isDisabled = pending || disabled;
318
+ const attachmentsReady = attachments.length > 0 && attachments.every((item) => item.state !== "uploading");
319
+ const canSubmit = !isDisabled && (Boolean(value.trim()) || attachmentsReady);
320
+ const submit = () => {
321
+ const trimmed = value.trim();
322
+ if (!trimmed && !attachmentsReady || isDisabled) return;
323
+ onSend(trimmed, attachments);
324
+ };
325
+ const spacious = appearance === "spacious";
326
+ const composerSize = COMPOSER_SIZES[size];
327
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-slot": "chat-input-container", className: "w-full", children: [
328
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
329
+ "form",
330
+ {
331
+ "data-slot": "chat-input",
332
+ "data-appearance": appearance,
333
+ className: "w-full",
334
+ onSubmit: (event) => {
335
+ if (event.target !== event.currentTarget) return;
336
+ event.preventDefault();
337
+ submit();
338
+ },
339
+ children: [
340
+ onFilesSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
341
+ "input",
342
+ {
343
+ ref: fileInputRef,
344
+ type: "file",
345
+ accept,
346
+ multiple,
347
+ hidden: true,
348
+ onChange: (event) => {
349
+ const files = Array.from(_nullishCoalesce(event.currentTarget.files, () => ( [])));
350
+ if (files.length > 0) void onFilesSelected(files);
351
+ event.currentTarget.value = "";
352
+ }
353
+ }
354
+ ),
355
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
356
+ _chunkRIWLAMMEcjs.InputGroup,
357
+ {
358
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
359
+ // Opaque in both modes: the input group's own dark:bg-input/30
360
+ // would let the thread show through the composer.
361
+ "overflow-hidden bg-background dark:bg-background",
362
+ spacious ? "rounded-3xl" : "rounded-lg",
363
+ className
364
+ ),
365
+ children: [
366
+ attachments.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
367
+ ChatAttachmentList,
368
+ {
369
+ attachments,
370
+ onRemove: onRemoveAttachment,
371
+ uploadingLabel,
372
+ className: "w-full"
373
+ }
374
+ ),
375
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
376
+ _chunkRIWLAMMEcjs.InputGroupTextarea,
377
+ {
378
+ ref,
379
+ value,
380
+ onChange: (e) => onChange(e.target.value),
381
+ onKeyDown: (e) => {
382
+ if (e.key !== "Enter" || e.shiftKey) return;
383
+ if (e.nativeEvent.isComposing || e.keyCode === 229) return;
384
+ e.preventDefault();
385
+ submit();
386
+ },
387
+ placeholder,
388
+ rows: composerSize.rows,
389
+ disabled: isDisabled,
390
+ autoFocus,
391
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
392
+ composerSize.minHeight,
393
+ // Grows with the text, then scrolls rather than pushing the thread away.
394
+ "max-h-48 leading-relaxed disabled:opacity-70 placeholder:text-sm",
395
+ spacious ? "px-6 pb-2 pt-6" : "px-4 py-3.5"
396
+ )
397
+ }
398
+ ),
399
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
400
+ _chunkRIWLAMMEcjs.InputGroupAddon,
401
+ {
402
+ align: "block-end",
403
+ "data-slot": "chat-input-actions",
404
+ onClick: (event) => {
405
+ if (!event.currentTarget.contains(event.target)) return;
406
+ if (!event.target.closest("button")) _optionalChain([ref, 'access', _4 => _4.current, 'optionalAccess', _5 => _5.focus, 'call', _6 => _6()]);
407
+ },
408
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
409
+ "gap-2",
410
+ spacious ? "px-5 pb-5 pt-1" : "border-t border-border px-3 py-2.5"
411
+ ),
412
+ children: [
413
+ onFilesSelected && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenu, { children: [
414
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
415
+ _chunkL4DH72UFcjs.Button,
416
+ {
417
+ type: "button",
418
+ size: spacious ? "icon-lg" : "icon",
419
+ variant: "ghost",
420
+ "aria-label": "Add to conversation",
421
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Plus, { className: _chunkKWLSBTB2cjs.cn.call(void 0, spacious && "h-5 w-5") })
422
+ }
423
+ ) }),
424
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuContent, { align: "start", side: "top", className: "min-w-52", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenuItem, { onSelect: () => _optionalChain([fileInputRef, 'access', _7 => _7.current, 'optionalAccess', _8 => _8.click, 'call', _9 => _9()]), children: [
425
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Paperclip, { className: "h-4 w-4" }),
426
+ addFilesLabel
427
+ ] }) })
428
+ ] }),
429
+ voice && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
430
+ _chunkEOUO3OROcjs.VoiceDictationButton,
431
+ {
432
+ size: "icon",
433
+ title: voiceTitle,
434
+ lang: voiceLang,
435
+ onCommit: (text) => onSend(text),
436
+ className: spacious ? "h-12 w-12 border-transparent bg-transparent shadow-none hover:bg-muted" : void 0
437
+ }
438
+ ),
439
+ helperText ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
440
+ "span",
441
+ {
442
+ "data-slot": "chat-input-helper",
443
+ className: "min-w-0 flex-1 truncate px-1 text-center text-xs font-normal text-muted-foreground sm:px-2 sm:text-sm",
444
+ children: helperText
445
+ }
446
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1" }),
447
+ submitLabel ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
448
+ _chunkL4DH72UFcjs.Button,
449
+ {
450
+ type: "submit",
451
+ disabled: !canSubmit,
452
+ "data-chat-action": "submit",
453
+ className: spacious ? "rounded-xl" : void 0,
454
+ children: [
455
+ submitLabel,
456
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowRight, { className: "ml-2 h-4 w-4" })
457
+ ]
458
+ }
459
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
460
+ _chunkL4DH72UFcjs.Button,
461
+ {
462
+ type: "submit",
463
+ size: spacious ? "icon-lg" : "icon",
464
+ disabled: !canSubmit,
465
+ "aria-label": "Send",
466
+ "data-chat-action": "submit",
467
+ className: spacious ? "rounded-xl" : void 0,
468
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowUp, { className: _chunkKWLSBTB2cjs.cn.call(void 0, spacious && "h-5 w-5") })
469
+ }
470
+ )
471
+ ]
472
+ }
473
+ )
474
+ ]
475
+ }
476
+ )
477
+ ]
478
+ }
479
+ ),
480
+ privacyNote ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
481
+ "div",
482
+ {
483
+ "data-slot": "chat-input-privacy",
484
+ className: "mt-3 flex items-center justify-center gap-2 px-4 text-center text-xs text-muted-foreground sm:text-sm",
485
+ children: [
486
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.LockKeyhole, { "aria-hidden": true, className: "h-4 w-4 shrink-0" }),
487
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: privacyNote })
488
+ ]
489
+ }
490
+ ) : null
491
+ ] });
492
+ }
493
+ function VoiceHero({
494
+ onSubmit,
495
+ voiceTitle,
496
+ voiceLang,
497
+ onSwitchToText,
498
+ label,
499
+ switchLabel
500
+ }) {
501
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-5 py-6", children: [
502
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
503
+ _chunkEOUO3OROcjs.VoiceDictationButton,
504
+ {
505
+ size: "lg",
506
+ title: voiceTitle,
507
+ lang: voiceLang,
508
+ onCommit: onSubmit,
509
+ className: "h-24 w-24 rounded-full p-0 shadow-lg transition-transform hover:scale-105 active:scale-95 [&_svg]:size-7"
510
+ }
511
+ ),
512
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-1.5", children: [
513
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-base font-medium text-foreground", children: label }),
514
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
515
+ "button",
516
+ {
517
+ type: "button",
518
+ onClick: onSwitchToText,
519
+ className: "text-xs text-muted-foreground hover:text-foreground transition-colors underline underline-offset-4 decoration-muted-foreground/40",
520
+ children: switchLabel
521
+ }
522
+ )
523
+ ] })
524
+ ] });
525
+ }
526
+ var EXAMPLE_PROMPT_LAYOUTS = {
527
+ chips: "wrap",
528
+ row: "row",
529
+ cards: "grid"
530
+ };
531
+ function ExamplePrompts({
532
+ prompts,
533
+ onSelect,
534
+ label = "Try",
535
+ variant = "chips",
536
+ className
537
+ }) {
538
+ const labelId = _react.useId.call(void 0, );
539
+ if (prompts.length === 0) return null;
540
+ const cards = variant === "cards";
541
+ 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: [
542
+ /* @__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 }),
543
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSUB4BAYEcjs.Suggestions, { role: "group", "aria-labelledby": labelId, layout: EXAMPLE_PROMPT_LAYOUTS[variant], children: prompts.map((prompt) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
544
+ _chunkSUB4BAYEcjs.Suggestion,
545
+ {
546
+ suggestion: prompt,
547
+ onClick: onSelect,
548
+ className: cards ? "h-auto min-h-12 px-3 py-2.5 text-xs" : void 0
549
+ },
550
+ prompt
551
+ )) })
552
+ ] });
553
+ }
554
+ function ExamplePromptsLoading({ label, className }) {
555
+ const list = Array.isArray(label) ? label : [label];
556
+ const [idx, setIdx] = _react.useState.call(void 0, 0);
557
+ _react.useEffect.call(void 0, () => {
558
+ if (list.length <= 1) return;
559
+ const id = setInterval(() => setIdx((i) => (i + 1) % list.length), 1800);
560
+ return () => clearInterval(id);
561
+ }, [list.length]);
562
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-slot": "chat-examples", "data-state": "loading", "aria-busy": "true", className: _chunkKWLSBTB2cjs.cn.call(void 0, "mt-3", className), children: [
563
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BTDBZYNcjs.Trace, { className: "mb-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BTDBZYNcjs.TraceLine, { status: "running", className: "text-xs", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BTDBZYNcjs.TraceTitle, { className: "animate-in fade-in duration-500", children: list[idx] }, idx) }) }),
564
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "aria-hidden": true, className: "flex gap-2 overflow-hidden", children: [36, 44, 28, 40].map((w, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
565
+ "span",
566
+ {
567
+ className: "h-11 shrink-0 rounded-md bg-muted animate-pulse",
568
+ style: {
569
+ width: `${w * 4}px`,
570
+ animationDelay: `${i * 120}ms`
571
+ }
572
+ },
573
+ i
574
+ )) })
575
+ ] });
576
+ }
577
+ function ChatError({ children, className }) {
578
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { "data-slot": "chat-error", role: "alert", className: _chunkKWLSBTB2cjs.cn.call(void 0, "mt-2 text-xs text-destructive", className), children });
579
+ }
580
+ var Chat = _react.forwardRef.call(void 0, function Chat2({
581
+ messages,
582
+ onSend,
583
+ onSendError,
584
+ pending = false,
585
+ pendingLabel,
586
+ emptyPendingContent,
587
+ error = null,
588
+ emptyTitle,
589
+ emptySubtitle,
590
+ examplePrompts = [],
591
+ examplePromptsLabel = "Try",
592
+ examplePromptsVariant = "chips",
593
+ examplePromptsLoading = false,
594
+ examplePromptsLoadingLabel = "Loading suggestions\u2026",
595
+ compactEmptyState = false,
596
+ defaultMode,
597
+ placeholder = "Type your message\u2026",
598
+ activePlaceholder = "Reply\u2026",
599
+ submitLabel,
600
+ attachments = [],
601
+ onFilesSelected,
602
+ onRemoveAttachment,
603
+ attachmentAccept,
604
+ addFilesLabel,
605
+ uploadingLabel,
606
+ composerAppearance = "default",
607
+ composerHelperText,
608
+ composerPrivacyNote,
609
+ emptyFileDropzone = false,
610
+ emptyFileDropzoneLabel = "Drop files here, or choose them",
611
+ emptyFileDropzoneDescription,
612
+ fileDrop = "conversation",
613
+ fileDropLabel,
614
+ fileDropDescription,
615
+ voice = true,
616
+ voiceTitle,
617
+ activeVoiceTitle,
618
+ voiceLang,
619
+ voiceHeroLabel = "Tap to speak",
620
+ voiceHeroSwitchLabel = "or type instead",
621
+ threadMaxHeight = "46vh",
622
+ scrollButtonLabel,
623
+ emptyAlign = "start",
624
+ emptyIcon,
625
+ emptyFooter,
626
+ layout = "embedded",
627
+ threadFooter,
628
+ markdownComponents,
629
+ onOpenAttachment,
630
+ attachmentAction,
631
+ className
632
+ }, ref) {
633
+ const isMobile = _chunkR35FT53Gcjs.useIsMobile.call(void 0, );
634
+ const [input, setInput] = _react.useState.call(void 0, "");
635
+ const inputRef = _react.useRef.call(void 0, null);
636
+ const conversationStarted = messages.length > 0;
637
+ const [userMode, setUserMode] = _react.useState.call(void 0, null);
638
+ const mode = _nullishCoalesce(_nullishCoalesce(userMode, () => ( defaultMode)), () => ( (isMobile ? "voice" : "text")));
639
+ const send = _react.useCallback.call(void 0,
640
+ async (text, sentAttachments = attachments) => {
641
+ const trimmed = text.trim();
642
+ if (!trimmed && sentAttachments.length === 0 || pending) return;
643
+ setInput("");
644
+ try {
645
+ await onSend(trimmed, sentAttachments);
646
+ } catch (cause) {
647
+ if (trimmed) {
648
+ setInput((current) => current ? current : trimmed);
649
+ if (mode === "voice") setUserMode("text");
650
+ }
651
+ if (onSendError) onSendError(cause);
652
+ else if (typeof globalThis.reportError === "function") globalThis.reportError(cause);
653
+ else console.error(cause);
654
+ }
655
+ window.setTimeout(() => _optionalChain([inputRef, 'access', _10 => _10.current, 'optionalAccess', _11 => _11.focus, 'call', _12 => _12()]), 0);
656
+ },
657
+ [attachments, mode, onSend, onSendError, pending]
658
+ );
659
+ _react.useImperativeHandle.call(void 0,
660
+ ref,
661
+ () => ({
662
+ focusInput: () => _optionalChain([inputRef, 'access', _13 => _13.current, 'optionalAccess', _14 => _14.focus, 'call', _15 => _15()]),
663
+ clearInput: () => setInput("")
664
+ }),
665
+ []
666
+ );
667
+ const dropFiles = _react.useCallback.call(void 0,
668
+ (files) => {
669
+ if (!conversationStarted && mode === "voice") setUserMode("text");
670
+ return _optionalChain([onFilesSelected, 'optionalCall', _16 => _16(files)]);
671
+ },
672
+ [conversationStarted, mode, onFilesSelected]
673
+ );
674
+ const application = layout === "application";
675
+ const workspace = layout === "workspace";
676
+ const showEmptyFileDropzone = emptyFileDropzone && Boolean(onFilesSelected) && attachments.length === 0;
677
+ const showEmptyPending = !conversationStarted && pending && Boolean(emptyPendingContent);
678
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
679
+ _chunkKADJ56AHcjs.FileDropArea,
680
+ {
681
+ "data-slot": "chat",
682
+ "data-layout": layout,
683
+ onFiles: onFilesSelected ? dropFiles : void 0,
684
+ disabled: fileDrop === false || showEmptyPending,
685
+ scope: fileDrop === "page" ? "page" : "area",
686
+ label: fileDropLabel,
687
+ description: fileDropDescription,
688
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
689
+ "w-full",
690
+ application && "flex min-h-[calc(100svh-4rem)] flex-1 flex-col md:block md:min-h-0",
691
+ workspace && "flex h-full min-h-0 flex-1 flex-col overflow-hidden",
692
+ className
693
+ ),
694
+ children: showEmptyPending ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
695
+ "div",
696
+ {
697
+ "data-slot": "chat-empty-pending",
698
+ className: "flex min-h-0 flex-1 items-center justify-center px-4 py-8",
699
+ children: emptyPendingContent
700
+ }
701
+ ) : !conversationStarted ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
702
+ "div",
703
+ {
704
+ "data-slot": "chat-empty",
705
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
706
+ emptyAlign === "center" && "mx-auto flex w-full max-w-3xl flex-col items-center text-center",
707
+ application && "min-h-0 max-w-none flex-1 md:max-w-3xl",
708
+ workspace && "min-h-0 max-w-none flex-1 overflow-y-auto overscroll-contain px-4 pb-20"
709
+ ),
710
+ children: [
711
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
712
+ "div",
713
+ {
714
+ "data-slot": "chat-empty-intro",
715
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
716
+ application && "flex flex-1 flex-col items-center justify-center px-6 py-8 md:contents",
717
+ workspace && "mt-auto w-full flex-none px-0 py-0"
718
+ ),
719
+ children: [
720
+ !compactEmptyState && emptyIcon && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "chat-empty-icon", className: "mb-4", children: emptyIcon }),
721
+ emptyTitle && !compactEmptyState && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { "data-slot": "chat-empty-title", className: "text-3xl md:text-4xl font-medium tracking-tight leading-[1.1] mt-2 mb-3", children: emptyTitle }),
722
+ emptySubtitle && !compactEmptyState && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
723
+ "p",
724
+ {
725
+ "data-slot": "chat-empty-subtitle",
726
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
727
+ "text-base text-muted-foreground leading-relaxed mb-6 max-w-md",
728
+ emptyAlign === "center" && "mx-auto"
729
+ ),
730
+ children: emptySubtitle
731
+ }
732
+ )
733
+ ]
734
+ }
735
+ ),
736
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
737
+ _chunk2KFZQJH5cjs.ActionDock,
738
+ {
739
+ shrink: false,
740
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
741
+ application && "px-4 py-3 md:border-0 md:bg-transparent md:p-0 md:backdrop-blur-none md:supports-backdrop-filter:bg-transparent",
742
+ !application && "border-0 bg-transparent p-0 backdrop-blur-none",
743
+ workspace && "mb-auto mt-2 w-full max-w-3xl border-0 bg-transparent p-0 backdrop-blur-none supports-[backdrop-filter]:bg-transparent"
744
+ ),
745
+ children: [
746
+ showEmptyFileDropzone && onFilesSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
747
+ _chunkKADJ56AHcjs.FileDropzone,
748
+ {
749
+ multiple: true,
750
+ onFiles: onFilesSelected,
751
+ accept: attachmentAccept,
752
+ label: emptyFileDropzoneLabel,
753
+ description: emptyFileDropzoneDescription,
754
+ icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.FileText, {}),
755
+ className: "mb-4 rounded-lg bg-muted/20 py-8"
756
+ }
757
+ ),
758
+ mode === "voice" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
759
+ VoiceHero,
760
+ {
761
+ onSubmit: (text) => void send(text),
762
+ voiceTitle,
763
+ voiceLang,
764
+ label: voiceHeroLabel,
765
+ switchLabel: voiceHeroSwitchLabel,
766
+ onSwitchToText: () => setUserMode("text")
767
+ }
768
+ ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
769
+ ChatInput,
770
+ {
771
+ value: input,
772
+ onChange: setInput,
773
+ onSend: (text) => void send(text),
774
+ pending,
775
+ placeholder,
776
+ size: showEmptyFileDropzone || application && isMobile ? "md" : "lg",
777
+ voice,
778
+ voiceTitle,
779
+ voiceLang,
780
+ submitLabel,
781
+ autoFocus: !isMobile,
782
+ inputRef,
783
+ attachments,
784
+ onFilesSelected,
785
+ onRemoveAttachment,
786
+ accept: attachmentAccept,
787
+ addFilesLabel,
788
+ uploadingLabel,
789
+ appearance: composerAppearance,
790
+ helperText: composerHelperText,
791
+ privacyNote: composerPrivacyNote,
792
+ className: workspace ? "rounded-3xl shadow-sm" : void 0
793
+ }
794
+ ),
795
+ error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatError, { children: error }),
796
+ !pending && examplePromptsLoading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ExamplePromptsLoading, { label: examplePromptsLoadingLabel }),
797
+ !pending && !examplePromptsLoading && examplePrompts.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
798
+ ExamplePrompts,
799
+ {
800
+ prompts: examplePrompts,
801
+ onSelect: (p) => void send(p),
802
+ label: examplePromptsLabel,
803
+ variant: examplePromptsVariant
804
+ }
805
+ ),
806
+ emptyFooter && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "chat-empty-footer", className: "mt-5", children: emptyFooter })
807
+ ]
808
+ }
809
+ )
810
+ ]
811
+ }
812
+ ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
813
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
814
+ ChatThread,
815
+ {
816
+ messages,
817
+ pending,
818
+ pendingLabel,
819
+ scrollButtonLabel,
820
+ uploadingLabel,
821
+ maxHeight: workspace || application && isMobile ? "none" : threadMaxHeight,
822
+ appearance: workspace ? "workspace" : "bubbles",
823
+ footer: threadFooter,
824
+ markdownComponents,
825
+ onOpenAttachment,
826
+ attachmentAction,
827
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
828
+ "mb-3",
829
+ application && "min-h-0 flex-1 px-4 py-4 md:px-0 md:py-0",
830
+ workspace && "mb-0 min-h-0 flex-1"
831
+ )
832
+ }
833
+ ),
834
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
835
+ _chunk2KFZQJH5cjs.ActionDock,
836
+ {
837
+ shrink: false,
838
+ className: _chunkKWLSBTB2cjs.cn.call(void 0,
839
+ "pt-3",
840
+ application && "px-4 py-3 md:bg-transparent md:px-0 md:pb-0 md:backdrop-blur-none md:supports-backdrop-filter:bg-transparent",
841
+ workspace && "border-0 bg-gradient-to-t from-background via-background to-transparent px-4 pb-[max(1.25rem,env(safe-area-inset-bottom))] pt-8 backdrop-blur-none supports-[backdrop-filter]:bg-gradient-to-t"
842
+ ),
843
+ children: [
844
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
845
+ ChatInput,
846
+ {
847
+ value: input,
848
+ onChange: setInput,
849
+ onSend: (text) => void send(text),
850
+ pending,
851
+ placeholder: activePlaceholder,
852
+ size: composerAppearance === "spacious" ? "lg" : "sm",
853
+ voice,
854
+ voiceTitle: _nullishCoalesce(activeVoiceTitle, () => ( voiceTitle)),
855
+ voiceLang,
856
+ inputRef,
857
+ attachments,
858
+ onFilesSelected,
859
+ onRemoveAttachment,
860
+ accept: attachmentAccept,
861
+ addFilesLabel,
862
+ uploadingLabel,
863
+ appearance: composerAppearance,
864
+ helperText: composerHelperText,
865
+ privacyNote: composerPrivacyNote,
866
+ className: workspace ? "mx-auto max-w-3xl rounded-3xl shadow-sm" : void 0
867
+ }
868
+ ),
869
+ error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatError, { className: workspace ? "mx-auto max-w-3xl px-2" : void 0, children: error })
870
+ ]
871
+ }
872
+ )
873
+ ] })
874
+ }
875
+ );
876
+ });
877
+
878
+
879
+
880
+
881
+ exports.Chat = Chat; exports.ChatInput = ChatInput; exports.ChatThread = ChatThread;