@epicbagel/saas-kit 1.20.0 → 1.21.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.
@@ -1,1227 +1,46 @@
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";
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});"use client";
2
2
  "use client";
3
3
 
4
4
 
5
5
 
6
6
 
7
- var _chunk2BTDBZYNcjs = require('../chunk-2BTDBZYN.cjs');
8
7
 
9
-
10
- var _chunkPH2TV7XIcjs = require('../chunk-PH2TV7XI.cjs');
11
-
12
-
13
- var _chunkYMI3X2YLcjs = require('../chunk-YMI3X2YL.cjs');
14
-
15
-
16
-
17
- var _chunkM4V7OJNFcjs = require('../chunk-M4V7OJNF.cjs');
18
-
19
-
20
-
21
- var _chunkB765DSRGcjs = require('../chunk-B765DSRG.cjs');
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
- var _chunk23IETCLVcjs = require('../chunk-23IETCLV.cjs');
8
+ var _chunk4YJ6DGPLcjs = require('../chunk-4YJ6DGPL.cjs');
9
+ require('../chunk-2BTDBZYN.cjs');
10
+ require('../chunk-PH2TV7XI.cjs');
11
+ require('../chunk-YMI3X2YL.cjs');
12
+ require('../chunk-M4V7OJNF.cjs');
13
+ require('../chunk-B765DSRG.cjs');
14
+ require('../chunk-23IETCLV.cjs');
30
15
  require('../chunk-DMPSKGFM.cjs');
31
-
32
-
33
-
34
-
35
-
36
- var _chunkNWDPH2Z7cjs = require('../chunk-NWDPH2Z7.cjs');
16
+ require('../chunk-NWDPH2Z7.cjs');
37
17
  require('../chunk-Z2H4LJVG.cjs');
38
-
39
-
40
-
41
-
42
- var _chunk7LDJAXRXcjs = require('../chunk-7LDJAXRX.cjs');
18
+ require('../chunk-7LDJAXRX.cjs');
43
19
  require('../chunk-2HV2KKOE.cjs');
44
-
45
-
46
-
47
- var _chunkZLEM2SAUcjs = require('../chunk-ZLEM2SAU.cjs');
48
-
49
-
50
- var _chunkKENBU3NVcjs = require('../chunk-KENBU3NV.cjs');
20
+ require('../chunk-ZLEM2SAU.cjs');
21
+ require('../chunk-KENBU3NV.cjs');
51
22
  require('../chunk-ELPV44S6.cjs');
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
- var _chunk2BHI5ZWJcjs = require('../chunk-2BHI5ZWJ.cjs');
60
-
61
-
62
-
63
-
64
-
65
- var _chunkZAITUDYDcjs = require('../chunk-ZAITUDYD.cjs');
23
+ require('../chunk-2BHI5ZWJ.cjs');
24
+ require('../chunk-ZAITUDYD.cjs');
66
25
  require('../chunk-U2NES7VR.cjs');
67
-
68
-
69
-
70
- var _chunkV4YWTRLDcjs = require('../chunk-V4YWTRLD.cjs');
26
+ require('../chunk-V4YWTRLD.cjs');
71
27
  require('../chunk-373W6VAD.cjs');
72
28
  require('../chunk-W5HPHEE7.cjs');
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
- var _chunkFYRQFEU4cjs = require('../chunk-FYRQFEU4.cjs');
84
-
85
-
86
- var _chunk2KFZQJH5cjs = require('../chunk-2KFZQJH5.cjs');
29
+ require('../chunk-FYRQFEU4.cjs');
30
+ require('../chunk-2KFZQJH5.cjs');
87
31
  require('../chunk-PQUSJEXL.cjs');
88
32
  require('../chunk-WABCLRBR.cjs');
89
33
  require('../chunk-NKWHDI4C.cjs');
90
-
91
-
92
- var _chunkJDEXZGIYcjs = require('../chunk-JDEXZGIY.cjs');
93
-
94
-
95
- var _chunkKWLSBTB2cjs = require('../chunk-KWLSBTB2.cjs');
34
+ require('../chunk-JDEXZGIY.cjs');
35
+ require('../chunk-KWLSBTB2.cjs');
96
36
  require('../chunk-2BSFYU22.cjs');
97
-
98
-
99
- var _chunk4LXN6GLZcjs = require('../chunk-4LXN6GLZ.cjs');
37
+ require('../chunk-4LXN6GLZ.cjs');
100
38
  require('../chunk-7Q4EFCUI.cjs');
101
-
102
-
103
- var _chunkR35FT53Gcjs = require('../chunk-R35FT53G.cjs');
104
-
105
-
106
- var _chunkH2UFRLLNcjs = require('../chunk-H2UFRLLN.cjs');
107
-
108
- // src/primitives/chat.tsx
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
- var _react = require('react');
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
- var _lucidereact = require('lucide-react');
133
- var _jsxruntime = require('react/jsx-runtime');
134
- function offersActions(message) {
135
- if (message.status) return false;
136
- return _nullishCoalesce(message.actions, () => ( message.role === "assistant"));
137
- }
138
- function useArrivingUserTurnId(messages) {
139
- const seen = _react.useRef.call(void 0, null);
140
- seen.current ??= new Set(messages.map((m) => m.id));
141
- _react.useEffect.call(void 0, () => {
142
- seen.current = new Set(messages.map((m) => m.id));
143
- }, [messages]);
144
- for (let i = messages.length - 1; i >= 0; i--) {
145
- const message = messages[i];
146
- if (message.role === "user" && message.status !== "running") {
147
- return seen.current.has(message.id) ? void 0 : message.id;
148
- }
149
- }
150
- return void 0;
151
- }
152
- function timelineMarkers(messages, now) {
153
- let previous = null;
154
- return messages.map((message) => {
155
- if (message.status === "running") return null;
156
- const relativeTime = _chunkH2UFRLLNcjs.formatRelativeLong.call(void 0, message.createdAt, now);
157
- const opens = relativeTime && relativeTime !== previous ? relativeTime : null;
158
- previous = relativeTime;
159
- return opens;
160
- });
161
- }
162
- function TimelineMarker({ label }) {
163
- 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 }) });
164
- }
165
- function ChatRunningLine({
166
- label,
167
- align = "start",
168
- workspace
169
- }) {
170
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNWDPH2Z7cjs.Message, { align, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNWDPH2Z7cjs.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: label }) }) }) }) });
171
- }
172
- var ChatThread = _react.forwardRef.call(void 0,
173
- function ChatThread2({
174
- messages,
175
- pending = false,
176
- pendingLabel = "Thinking\u2026",
177
- scrollButtonLabel = "Scroll to latest message",
178
- uploadingLabel,
179
- maxHeight = "46vh",
180
- appearance = "bubbles",
181
- footer,
182
- markdownComponents,
183
- onOpenAttachment,
184
- attachmentAction = "open",
185
- messageActions,
186
- className
187
- }, ref) {
188
- const markers = timelineMarkers(messages, /* @__PURE__ */ new Date());
189
- const anchorId = useArrivingUserTurnId(messages);
190
- const workspace = appearance === "workspace";
191
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk23IETCLVcjs.MessageScrollerProvider, { autoScroll: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
192
- _chunk23IETCLVcjs.MessageScroller,
193
- {
194
- ref,
195
- style: { maxHeight },
196
- className: _chunkKWLSBTB2cjs.cn.call(void 0, "min-h-0", className),
197
- children: [
198
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk23IETCLVcjs.MessageScrollerViewport, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
199
- _chunk23IETCLVcjs.MessageScrollerContent,
200
- {
201
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
202
- workspace ? "mx-auto w-full max-w-3xl gap-10 px-4 py-6 md:px-6 md:py-8" : "gap-2.5 px-px py-px"
203
- ),
204
- children: [
205
- messages.map((m, index) => {
206
- const isUser = m.role === "user";
207
- if (m.status === "running") {
208
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk23IETCLVcjs.MessageScrollerItem, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
209
- ChatRunningLine,
210
- {
211
- label: m.text || pendingLabel,
212
- align: isUser ? "end" : "start",
213
- workspace
214
- }
215
- ) }, m.id);
216
- }
217
- const isFullWidth = m.width === "full";
218
- const marker = markers[index];
219
- const actions = messageActions && offersActions(m) ? messageActions(m) : null;
220
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
221
- _chunk23IETCLVcjs.MessageScrollerItem,
222
- {
223
- messageId: m.id,
224
- scrollAnchor: m.id === anchorId,
225
- className: _chunkKWLSBTB2cjs.cn.call(void 0, "flex flex-col", workspace ? "gap-5" : "gap-3"),
226
- children: [
227
- marker ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TimelineMarker, { label: marker }) : null,
228
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNWDPH2Z7cjs.Message, { align: isUser ? "end" : "start", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkNWDPH2Z7cjs.MessageContent, { children: [
229
- (m.content || m.text) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
230
- _chunkV4YWTRLDcjs.Bubble,
231
- {
232
- variant: workspace ? isUser ? "muted" : "ghost" : isUser ? "default" : "muted",
233
- align: isUser ? "end" : "start",
234
- className: isFullWidth ? "w-full" : void 0,
235
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
236
- _chunkV4YWTRLDcjs.BubbleContent,
237
- {
238
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
239
- isFullWidth && "w-full",
240
- 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"
241
- ),
242
- children: _nullishCoalesce(m.content, () => ( (m.text ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkKENBU3NVcjs.LazyMarkdown, { size: workspace ? "base" : "sm", components: markdownComponents, children: m.text }) : null)))
243
- }
244
- )
245
- }
246
- ),
247
- m.attachments && m.attachments.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
248
- ChatAttachmentList,
249
- {
250
- attachments: m.attachments,
251
- onOpen: onOpenAttachment,
252
- openAction: attachmentAction,
253
- uploadingLabel,
254
- className: "px-0 pt-0"
255
- }
256
- ),
257
- actions != null && actions !== false ? (
258
- // Unboxed workspace turns pull the row out by the
259
- // button's inset, so the first icon lines up with
260
- // the text above it.
261
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
262
- _chunkNWDPH2Z7cjs.MessageActions,
263
- {
264
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
265
- workspace && (isUser ? "-me-2 pointer-coarse:-me-3.5" : "-ms-2 pointer-coarse:-ms-3.5")
266
- ),
267
- children: actions
268
- }
269
- )
270
- ) : null
271
- ] }) })
272
- ]
273
- },
274
- m.id
275
- );
276
- }),
277
- pending && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk23IETCLVcjs.MessageScrollerItem, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatRunningLine, { label: pendingLabel, workspace }) }),
278
- footer && // Always painted: content-visibility:auto would contain the
279
- // footer's paint and layout, clipping a ring or shadow at its
280
- // edge and re-parenting anything fixed inside it.
281
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk23IETCLVcjs.MessageScrollerItem, { className: "[content-visibility:visible]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNWDPH2Z7cjs.Message, { align: "start", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNWDPH2Z7cjs.MessageContent, { children: footer }) }) })
282
- ]
283
- }
284
- ) }),
285
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk23IETCLVcjs.MessageScrollerButton, { variant: "outline", className: "rounded-full shadow-sm", children: [
286
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowDown, { className: "h-4 w-4" }),
287
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: scrollButtonLabel })
288
- ] })
289
- ]
290
- }
291
- ) });
292
- }
293
- );
294
- function ChatCopyAction({
295
- message,
296
- label = "Copy",
297
- copiedLabel = "Copied",
298
- onCopy,
299
- resetAfter = 2e3
300
- }) {
301
- const { copied, copy } = _chunk4LXN6GLZcjs.useCopyToClipboard.call(void 0, { resetAfter });
302
- const text = message.text;
303
- if (!text) return null;
304
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
305
- _chunkNWDPH2Z7cjs.MessageAction,
306
- {
307
- tooltip: copied ? copiedLabel : label,
308
- "data-copied": copied || void 0,
309
- onClick: async () => {
310
- const ok = await copy(text);
311
- _optionalChain([onCopy, 'optionalCall', _ => _(ok)]);
312
- },
313
- children: copied ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Check, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Copy, {})
314
- }
315
- );
316
- }
317
- function formatFileSize(size) {
318
- if (size === void 0) return "File";
319
- if (size < 1024) return `${size} B`;
320
- if (size < 1048576) return `${Math.round(size / 1024)} KB`;
321
- return `${(size / 1048576).toFixed(1)} MB`;
322
- }
323
- var ATTACHMENT_ACTIONS = {
324
- open: { verb: "Open", icon: _lucidereact.ArrowUpRight },
325
- download: { verb: "Download", icon: _lucidereact.Download }
326
- };
327
- var COMPOSER_SIZES = {
328
- sm: { minHeight: "min-h-12", rows: 2 },
329
- md: { minHeight: "min-h-[4.5rem]", rows: 2 },
330
- lg: { minHeight: "min-h-32", rows: 3 }
331
- };
332
- function ChatAttachmentList({
333
- attachments,
334
- onRemove,
335
- onOpen,
336
- openAction = "open",
337
- uploadingLabel = "Uploading\u2026",
338
- className
339
- }) {
340
- const { verb, icon: ActionIcon } = ATTACHMENT_ACTIONS[openAction];
341
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFYRQFEU4cjs.AttachmentGroup, { className: _chunkKWLSBTB2cjs.cn.call(void 0, "gap-2 px-3 pt-3", className), children: attachments.map((attachment) => {
342
- const state = _nullishCoalesce(attachment.state, () => ( "done"));
343
- const opens = Boolean(onOpen) && state === "done";
344
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
345
- _chunkFYRQFEU4cjs.Attachment,
346
- {
347
- state,
348
- size: "sm",
349
- className: "min-w-[12rem] rounded-xl p-2",
350
- children: [
351
- opens && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
352
- _chunkFYRQFEU4cjs.AttachmentTrigger,
353
- {
354
- "aria-label": `${verb} ${attachment.name}`,
355
- title: `${verb} ${attachment.name}`,
356
- onClick: () => _optionalChain([onOpen, 'optionalCall', _2 => _2(attachment)]),
357
- className: "rounded-xl focus-visible:ring-2 focus-visible:ring-ring/50"
358
- }
359
- ),
360
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFYRQFEU4cjs.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" }) }),
361
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkFYRQFEU4cjs.AttachmentContent, { className: "px-2", children: [
362
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFYRQFEU4cjs.AttachmentTitle, { className: "text-xs font-medium", children: attachment.name }),
363
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFYRQFEU4cjs.AttachmentDescription, { className: "text-[11px]", children: state === "uploading" ? uploadingLabel : opens ? `${formatFileSize(attachment.size)} \xB7 ${verb}` : formatFileSize(attachment.size) })
364
- ] }),
365
- onRemove ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFYRQFEU4cjs.AttachmentActions, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
366
- _chunkFYRQFEU4cjs.AttachmentAction,
367
- {
368
- type: "button",
369
- "aria-label": `Remove ${attachment.name}`,
370
- onClick: () => onRemove(attachment),
371
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.X, { className: "h-3.5 w-3.5" })
372
- }
373
- ) }) : opens ? (
374
- // The trigger covers the whole file; the icon only says what it does.
375
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFYRQFEU4cjs.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" }) })
376
- ) : null
377
- ]
378
- },
379
- attachment.id
380
- );
381
- }) });
382
- }
383
- function ChatInput({
384
- value,
385
- onChange,
386
- onSend,
387
- pending = false,
388
- disabled = false,
389
- placeholder = "Type your message\u2026",
390
- size = "md",
391
- uploadingLabel,
392
- voice = true,
393
- voiceSession,
394
- voiceTitle,
395
- voiceLang,
396
- submitLabel,
397
- autoFocus = false,
398
- className,
399
- inputRef,
400
- attachments = [],
401
- onFilesSelected,
402
- onRemoveAttachment,
403
- accept,
404
- multiple = true,
405
- addFilesLabel = "Add files",
406
- appearance = "default",
407
- compactOnBlur = false,
408
- header,
409
- helperText,
410
- privacyNote
411
- }) {
412
- const internalRef = _react.useRef.call(void 0, null);
413
- const ref = _nullishCoalesce(inputRef, () => ( internalRef));
414
- const fileInputRef = _react.useRef.call(void 0, null);
415
- const [editing, setEditing] = _react.useState.call(void 0, false);
416
- const focusVersion = _react.useRef.call(void 0, 0);
417
- const isDisabled = pending || disabled;
418
- const hasText = Boolean(value.trim());
419
- const attachmentsReady = attachments.length > 0 && attachments.every((item) => item.state !== "uploading");
420
- const canSubmit = !isDisabled && (hasText || attachmentsReady);
421
- const liveVoiceActive = voiceSession && voiceSession.state !== "disconnected" && voiceSession.state !== "error";
422
- const submit = () => {
423
- const trimmed = value.trim();
424
- if (!trimmed && !attachmentsReady || isDisabled) return;
425
- onSend(trimmed, attachments);
426
- };
427
- const spacious = appearance === "spacious";
428
- const composerSize = COMPOSER_SIZES[size];
429
- const compact = compactOnBlur && !editing && value.length === 0 && attachments.length === 0;
430
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-slot": "chat-input-container", className: "w-full", children: [
431
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
432
- "form",
433
- {
434
- "data-slot": "chat-input",
435
- "data-appearance": appearance,
436
- "data-compact": compact || void 0,
437
- className: "w-full",
438
- onFocusCapture: (event) => {
439
- focusVersion.current += 1;
440
- if (event.nativeEvent.target === ref.current) setEditing(true);
441
- },
442
- onBlurCapture: (event) => {
443
- if (event.currentTarget.contains(event.relatedTarget)) return;
444
- const form = event.currentTarget;
445
- const blurredAt = ++focusVersion.current;
446
- queueMicrotask(() => {
447
- if (form.isConnected && focusVersion.current === blurredAt) setEditing(false);
448
- });
449
- },
450
- onSubmit: (event) => {
451
- if (event.target !== event.currentTarget) return;
452
- event.preventDefault();
453
- submit();
454
- },
455
- children: [
456
- onFilesSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
457
- "input",
458
- {
459
- ref: fileInputRef,
460
- type: "file",
461
- accept,
462
- multiple,
463
- hidden: true,
464
- onChange: (event) => {
465
- const files = Array.from(_nullishCoalesce(event.currentTarget.files, () => ( [])));
466
- if (files.length > 0) void onFilesSelected(files);
467
- event.currentTarget.value = "";
468
- }
469
- }
470
- ),
471
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
472
- _chunk7LDJAXRXcjs.InputGroup,
473
- {
474
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
475
- // Opaque in both modes: the input group's own dark:bg-input/30
476
- // would let the thread show through the composer.
477
- "overflow-hidden bg-background dark:bg-background",
478
- spacious ? "rounded-3xl" : "rounded-lg",
479
- className
480
- ),
481
- children: [
482
- header && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
483
- _chunk7LDJAXRXcjs.InputGroupAddon,
484
- {
485
- align: "block-start",
486
- className: "w-full cursor-default border-b border-border bg-muted/50 p-0 [.border-b]:pb-0",
487
- onClick: () => {
488
- },
489
- children: header
490
- }
491
- ),
492
- liveVoiceActive && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk7LDJAXRXcjs.InputGroupAddon, { align: "block-start", className: "w-full cursor-default border-b border-border p-0 [.border-b]:pb-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYMI3X2YLcjs.VoiceSessionControls, { ...voiceSession }) }),
493
- attachments.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
494
- ChatAttachmentList,
495
- {
496
- attachments,
497
- onRemove: onRemoveAttachment,
498
- uploadingLabel,
499
- className: "w-full"
500
- }
501
- ),
502
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
503
- _chunk7LDJAXRXcjs.InputGroupTextarea,
504
- {
505
- ref,
506
- value,
507
- onChange: (e) => onChange(e.target.value),
508
- onKeyDown: (e) => {
509
- if (e.key !== "Enter" || e.shiftKey) return;
510
- if (e.nativeEvent.isComposing || e.keyCode === 229) return;
511
- e.preventDefault();
512
- submit();
513
- },
514
- placeholder,
515
- rows: compact ? 1 : composerSize.rows,
516
- disabled: isDisabled,
517
- autoFocus,
518
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
519
- compact ? "min-h-[44px] max-h-24 min-w-0" : composerSize.minHeight,
520
- // Grows with the text, then scrolls rather than pushing the thread away.
521
- "leading-relaxed disabled:opacity-70 placeholder:text-sm",
522
- !compact && "max-h-48",
523
- compact ? "px-4 py-2" : spacious ? "px-6 pb-2 pt-6" : "px-4 py-3.5"
524
- )
525
- }
526
- ),
527
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
528
- _chunk7LDJAXRXcjs.InputGroupAddon,
529
- {
530
- align: "block-end",
531
- "data-slot": "chat-input-actions",
532
- onClick: (event) => {
533
- if (!event.currentTarget.contains(event.target)) return;
534
- if (!event.target.closest("button")) _optionalChain([ref, 'access', _3 => _3.current, 'optionalAccess', _4 => _4.focus, 'call', _5 => _5()]);
535
- },
536
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
537
- compact ? "gap-1 px-2 pb-2 pt-0" : "gap-2",
538
- !compact && (spacious ? "px-5 pb-5 pt-1" : "border-t border-border px-3 py-2.5")
539
- ),
540
- children: [
541
- onFilesSelected && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkZAITUDYDcjs.DropdownMenu, { children: [
542
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkZAITUDYDcjs.DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
543
- _chunkJDEXZGIYcjs.Button,
544
- {
545
- type: "button",
546
- size: spacious && !compact ? "icon-lg" : "icon",
547
- variant: "ghost",
548
- "aria-label": "Add to conversation",
549
- className: compactOnBlur ? "min-h-[44px] min-w-[44px] shrink-0" : void 0,
550
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Plus, { className: _chunkKWLSBTB2cjs.cn.call(void 0, spacious && "h-5 w-5") })
551
- }
552
- ) }),
553
- /* @__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', _6 => _6.current, 'optionalAccess', _7 => _7.click, 'call', _8 => _8()]), children: [
554
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.Paperclip, { className: "h-4 w-4" }),
555
- addFilesLabel
556
- ] }) })
557
- ] }),
558
- helperText ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
559
- "span",
560
- {
561
- "data-slot": "chat-input-helper",
562
- 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"),
563
- children: helperText
564
- }
565
- ) : null,
566
- (!helperText || compact) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1" }),
567
- voice && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
568
- _chunkPH2TV7XIcjs.VoiceDictationButton,
569
- {
570
- size: "icon",
571
- title: voiceTitle,
572
- lang: voiceLang,
573
- disabled: Boolean(isDisabled || liveVoiceActive),
574
- onCommit: (text) => onSend(text),
575
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
576
- spacious && "border-transparent bg-transparent shadow-none hover:bg-muted",
577
- spacious && !compact && "h-12 w-12",
578
- compactOnBlur && "min-h-[44px] min-w-[44px] shrink-0"
579
- )
580
- }
581
- ),
582
- voiceSession && !liveVoiceActive && !hasText && attachments.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYMI3X2YLcjs.VoiceSessionControls, { ...voiceSession, disabled: voiceSession.disabled || isDisabled }) : submitLabel ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
583
- _chunkJDEXZGIYcjs.Button,
584
- {
585
- type: "submit",
586
- disabled: !canSubmit,
587
- "data-chat-action": "submit",
588
- className: _chunkKWLSBTB2cjs.cn.call(void 0, spacious && "rounded-xl", compactOnBlur && "min-h-[44px] min-w-[44px] shrink-0"),
589
- children: [
590
- submitLabel,
591
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowRight, { className: "ml-2 h-4 w-4" })
592
- ]
593
- }
594
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
595
- _chunkJDEXZGIYcjs.Button,
596
- {
597
- type: "submit",
598
- size: !voiceSession && spacious && !compact ? "icon-lg" : "icon",
599
- shape: voiceSession ? "circle" : void 0,
600
- disabled: !canSubmit,
601
- "aria-label": "Send",
602
- "data-chat-action": "submit",
603
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
604
- spacious && !voiceSession && "rounded-xl",
605
- (voiceSession || compactOnBlur) && "min-h-[44px] min-w-[44px] shrink-0"
606
- ),
607
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowUp, { className: _chunkKWLSBTB2cjs.cn.call(void 0, spacious && "h-5 w-5") })
608
- }
609
- )
610
- ]
611
- }
612
- )
613
- ]
614
- }
615
- )
616
- ]
617
- }
618
- ),
619
- privacyNote ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
620
- "div",
621
- {
622
- "data-slot": "chat-input-privacy",
623
- className: "mt-3 flex items-center justify-center gap-2 px-4 text-center text-xs text-muted-foreground sm:text-sm",
624
- children: [
625
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.LockKeyhole, { "aria-hidden": true, className: "h-4 w-4 shrink-0" }),
626
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: privacyNote })
627
- ]
628
- }
629
- ) : null
630
- ] });
631
- }
632
- function VoiceHero({
633
- onSubmit,
634
- voice,
635
- voiceSession,
636
- voiceTitle,
637
- voiceLang,
638
- onSwitchToText,
639
- label,
640
- switchLabel
641
- }) {
642
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-5 py-6", children: [
643
- voiceSession ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
644
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkYMI3X2YLcjs.VoiceSessionControls, { ...voiceSession, size: "hero" }),
645
- voice && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
646
- _chunkPH2TV7XIcjs.VoiceDictationButton,
647
- {
648
- size: "icon",
649
- title: voiceTitle,
650
- lang: voiceLang,
651
- onCommit: onSubmit,
652
- disabled: Boolean(voiceSession.disabled || voiceSession.state !== "disconnected" && voiceSession.state !== "error")
653
- }
654
- )
655
- ] }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
656
- _chunkPH2TV7XIcjs.VoiceDictationButton,
657
- {
658
- size: "lg",
659
- title: voiceTitle,
660
- lang: voiceLang,
661
- onCommit: onSubmit,
662
- className: "h-24 w-24 rounded-full p-0 shadow-lg transition-transform hover:scale-105 active:scale-95 [&_svg]:size-7"
663
- }
664
- ),
665
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-1.5", children: [
666
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-base font-medium text-foreground", children: label }),
667
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
668
- "button",
669
- {
670
- type: "button",
671
- onClick: onSwitchToText,
672
- className: "text-xs text-muted-foreground hover:text-foreground transition-colors underline underline-offset-4 decoration-muted-foreground/40",
673
- children: switchLabel
674
- }
675
- )
676
- ] })
677
- ] });
678
- }
679
- var EXAMPLE_PROMPT_LAYOUTS = {
680
- chips: "wrap",
681
- row: "row",
682
- cards: "grid"
683
- };
684
- function ChatSuggestions({
685
- slot,
686
- items,
687
- onSelect,
688
- label,
689
- showLabel = true,
690
- variant = "chips",
691
- disabled = false,
692
- className
693
- }) {
694
- const labelId = _react.useId.call(void 0, );
695
- if (items.length === 0) return null;
696
- const cards = variant === "cards";
697
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-slot": slot, "data-variant": variant, className, children: [
698
- 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 }),
699
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
700
- _chunkM4V7OJNFcjs.Suggestions,
701
- {
702
- role: "group",
703
- "aria-labelledby": showLabel ? labelId : void 0,
704
- "aria-label": showLabel ? void 0 : label,
705
- layout: EXAMPLE_PROMPT_LAYOUTS[variant],
706
- children: items.map((item) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
707
- _chunkM4V7OJNFcjs.Suggestion,
708
- {
709
- suggestion: item,
710
- onClick: onSelect,
711
- disabled,
712
- className: cards ? "h-auto min-h-12 px-3 py-2.5 text-xs" : void 0
713
- },
714
- item
715
- ))
716
- }
717
- )
718
- ] });
719
- }
720
- function MobileReplySuggestions({
721
- items,
722
- onSelect,
723
- label,
724
- moreLabel,
725
- closeLabel,
726
- disabled
727
- }) {
728
- const [open, setOpen] = _react.useState.call(void 0, false);
729
- const triggerRef = _react.useRef.call(void 0, null);
730
- const closeRef = _react.useRef.call(void 0, null);
731
- _react.useEffect.call(void 0, () => {
732
- if (disabled) setOpen(false);
733
- }, [disabled]);
734
- const select = (item) => {
735
- if (disabled) return;
736
- setOpen(false);
737
- onSelect(item);
738
- };
739
- const primary = items[0];
740
- if (primary === void 0) return null;
741
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk2BHI5ZWJcjs.Drawer, { open, onOpenChange: setOpen, shouldScaleBackground: false, repositionInputs: false, children: [
742
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
743
- "div",
744
- {
745
- "data-slot": "chat-replies",
746
- "data-variant": "compact",
747
- role: "group",
748
- "aria-label": label,
749
- className: "flex w-full min-w-0 items-center text-foreground",
750
- children: [
751
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
752
- _chunkJDEXZGIYcjs.Button,
753
- {
754
- type: "button",
755
- variant: "ghost",
756
- size: "bare",
757
- disabled,
758
- className: "h-[44px] min-h-[44px] min-w-0 flex-1 justify-start gap-2 px-3 text-left focus-visible:-ring-offset-2",
759
- onClick: () => select(primary),
760
- children: [
761
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowUpRight, { "aria-hidden": "true" }),
762
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "min-w-0 truncate", children: primary })
763
- ]
764
- }
765
- ),
766
- items.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BHI5ZWJcjs.DrawerTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
767
- _chunkJDEXZGIYcjs.Button,
768
- {
769
- ref: triggerRef,
770
- type: "button",
771
- variant: "ghost",
772
- size: "bare",
773
- disabled,
774
- className: "h-[44px] min-h-[44px] shrink-0 gap-1 px-3 text-muted-foreground focus-visible:-ring-offset-2",
775
- children: [
776
- moreLabel(items.length - 1),
777
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ChevronUp, { "aria-hidden": "true" })
778
- ]
779
- }
780
- ) })
781
- ]
782
- }
783
- ),
784
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
785
- _chunk2BHI5ZWJcjs.DrawerContent,
786
- {
787
- "aria-describedby": void 0,
788
- className: "max-h-[min(85dvh,40rem)] overflow-hidden pb-[env(safe-area-inset-bottom)]",
789
- onOpenAutoFocus: (event) => {
790
- event.preventDefault();
791
- _optionalChain([closeRef, 'access', _9 => _9.current, 'optionalAccess', _10 => _10.focus, 'call', _11 => _11({ preventScroll: true })]);
792
- },
793
- onCloseAutoFocus: (event) => {
794
- event.preventDefault();
795
- if (_optionalChain([triggerRef, 'access', _12 => _12.current, 'optionalAccess', _13 => _13.isConnected]) && !triggerRef.current.disabled) {
796
- triggerRef.current.focus({ preventScroll: true });
797
- }
798
- },
799
- children: [
800
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk2BHI5ZWJcjs.DrawerHeader, { align: "start", className: "flex shrink-0 items-center justify-between gap-3 border-b px-4 py-2", children: [
801
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BHI5ZWJcjs.DrawerTitle, { className: "min-w-0 break-words leading-snug", children: label }),
802
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk2BHI5ZWJcjs.DrawerClose, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
803
- _chunkJDEXZGIYcjs.Button,
804
- {
805
- ref: closeRef,
806
- type: "button",
807
- variant: "ghost",
808
- size: "icon",
809
- "aria-label": closeLabel,
810
- className: "h-[44px] w-[44px] shrink-0",
811
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.X, { "aria-hidden": "true" })
812
- }
813
- ) })
814
- ] }),
815
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-0 overflow-y-auto overscroll-contain", role: "group", "aria-label": label, children: items.map((item) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
816
- _chunkJDEXZGIYcjs.Button,
817
- {
818
- type: "button",
819
- variant: "ghost",
820
- size: "bare",
821
- disabled,
822
- "data-slot": "chat-reply-option",
823
- className: "min-h-[56px] w-full justify-between gap-4 rounded-none border-b px-4 py-4 text-left text-base font-normal whitespace-normal last:border-b-0 focus-visible:-ring-offset-2",
824
- onClick: () => select(item),
825
- children: [
826
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "min-w-0 break-words", children: item }),
827
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowUpRight, { "aria-hidden": "true" })
828
- ]
829
- },
830
- item
831
- )) })
832
- ]
833
- }
834
- )
835
- ] });
836
- }
837
- function ExamplePromptsLoading({ label, className }) {
838
- const list = Array.isArray(label) ? label : [label];
839
- const [idx, setIdx] = _react.useState.call(void 0, 0);
840
- _react.useEffect.call(void 0, () => {
841
- if (list.length <= 1) return;
842
- const id = setInterval(() => setIdx((i) => (i + 1) % list.length), 1800);
843
- return () => clearInterval(id);
844
- }, [list.length]);
845
- 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: [
846
- /* @__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) }) }),
847
- /* @__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,
848
- "span",
849
- {
850
- className: "h-11 shrink-0 rounded-md bg-muted animate-pulse",
851
- style: {
852
- width: `${w * 4}px`,
853
- animationDelay: `${i * 120}ms`
854
- }
855
- },
856
- i
857
- )) })
858
- ] });
859
- }
860
- function ChatError({ children, className }) {
861
- 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 });
862
- }
863
- var Chat = _react.forwardRef.call(void 0, function Chat2({
864
- messages,
865
- onSend,
866
- onSendError,
867
- pending = false,
868
- pendingLabel,
869
- emptyPendingContent,
870
- error = null,
871
- emptyTitle,
872
- emptySubtitle,
873
- examplePrompts = [],
874
- examplePromptsLabel = "Try",
875
- examplePromptsVariant = "chips",
876
- examplePromptsLoading = false,
877
- examplePromptsLoadingLabel = "Loading suggestions\u2026",
878
- replySuggestions = [],
879
- replySuggestionsLabel = "Suggested replies",
880
- mobileCompactSuggestions = false,
881
- replySuggestionsMoreLabel = (count) => `+${count} more`,
882
- replySuggestionsCloseLabel = "Close suggested replies",
883
- compactEmptyState = false,
884
- defaultMode,
885
- placeholder = "Type your message\u2026",
886
- activePlaceholder = "Reply\u2026",
887
- submitLabel,
888
- attachments = [],
889
- onFilesSelected,
890
- onRemoveAttachment,
891
- attachmentAccept,
892
- addFilesLabel,
893
- uploadingLabel,
894
- composerAppearance = "default",
895
- mobileCompactComposer = false,
896
- composerHelperText,
897
- composerPrivacyNote,
898
- emptyFileDropzone = false,
899
- emptyFileDropzoneLabel = "Drop files here, or choose them",
900
- emptyFileDropzoneDescription,
901
- fileDrop = "conversation",
902
- fileDropLabel,
903
- fileDropDescription,
904
- voice = true,
905
- voiceSession,
906
- voiceTitle,
907
- activeVoiceTitle,
908
- voiceLang,
909
- voiceHeroLabel = "Tap to speak",
910
- voiceHeroSwitchLabel = "or type instead",
911
- threadMaxHeight = "46vh",
912
- scrollButtonLabel,
913
- emptyAlign = "start",
914
- emptyIcon,
915
- emptyFooter,
916
- layout = "embedded",
917
- threadFooter,
918
- markdownComponents,
919
- onOpenAttachment,
920
- attachmentAction,
921
- messageActions,
922
- className
923
- }, ref) {
924
- const isMobile = _chunkR35FT53Gcjs.useIsMobile.call(void 0, );
925
- const [input, setInput] = _react.useState.call(void 0, "");
926
- const inputRef = _react.useRef.call(void 0, null);
927
- const conversationStarted = messages.length > 0;
928
- const [userMode, setUserMode] = _react.useState.call(void 0, null);
929
- const mode = !voice && !voiceSession ? "text" : _nullishCoalesce(_nullishCoalesce(userMode, () => ( defaultMode)), () => ( (isMobile ? "voice" : "text")));
930
- const reportSendError = _react.useCallback.call(void 0,
931
- (cause) => {
932
- if (onSendError) onSendError(cause);
933
- else if (typeof globalThis.reportError === "function") globalThis.reportError(cause);
934
- else console.error(cause);
935
- },
936
- [onSendError]
937
- );
938
- const send = _react.useCallback.call(void 0,
939
- async (text, sentAttachments = attachments) => {
940
- const trimmed = text.trim();
941
- if (!trimmed && sentAttachments.length === 0 || pending) return;
942
- setInput("");
943
- try {
944
- await onSend(trimmed, sentAttachments);
945
- } catch (cause) {
946
- if (trimmed) {
947
- setInput((current) => current ? current : trimmed);
948
- if (mode === "voice") setUserMode("text");
949
- }
950
- reportSendError(cause);
951
- }
952
- window.setTimeout(() => _optionalChain([inputRef, 'access', _14 => _14.current, 'optionalAccess', _15 => _15.focus, 'call', _16 => _16()]), 0);
953
- },
954
- [attachments, mode, onSend, pending, reportSendError]
955
- );
956
- const sendSuggestion = _react.useCallback.call(void 0,
957
- async (text, focusInput = true) => {
958
- const trimmed = text.trim();
959
- if (!trimmed || pending) return;
960
- try {
961
- await onSend(trimmed, []);
962
- } catch (cause) {
963
- reportSendError(cause);
964
- }
965
- if (focusInput) window.setTimeout(() => _optionalChain([inputRef, 'access', _17 => _17.current, 'optionalAccess', _18 => _18.focus, 'call', _19 => _19()]), 0);
966
- },
967
- [onSend, pending, reportSendError]
968
- );
969
- _react.useImperativeHandle.call(void 0,
970
- ref,
971
- () => ({
972
- focusInput: () => _optionalChain([inputRef, 'access', _20 => _20.current, 'optionalAccess', _21 => _21.focus, 'call', _22 => _22()]),
973
- clearInput: () => setInput("")
974
- }),
975
- []
976
- );
977
- const dropFiles = _react.useCallback.call(void 0,
978
- (files) => {
979
- if (!conversationStarted && mode === "voice") setUserMode("text");
980
- return _optionalChain([onFilesSelected, 'optionalCall', _23 => _23(files)]);
981
- },
982
- [conversationStarted, mode, onFilesSelected]
983
- );
984
- const application = layout === "application";
985
- const workspace = layout === "workspace";
986
- const compactSuggestions = mobileCompactSuggestions && isMobile;
987
- const showEmptyFileDropzone = emptyFileDropzone && Boolean(onFilesSelected) && attachments.length === 0;
988
- const liveVoiceActive = voiceSession && voiceSession.state !== "disconnected" && voiceSession.state !== "error";
989
- const showEmptyPending = !conversationStarted && pending && Boolean(emptyPendingContent) && !liveVoiceActive;
990
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
991
- _chunkZLEM2SAUcjs.FileDropArea,
992
- {
993
- "data-slot": "chat",
994
- "data-layout": layout,
995
- onFiles: onFilesSelected ? dropFiles : void 0,
996
- disabled: fileDrop === false || showEmptyPending,
997
- scope: fileDrop === "page" ? "page" : "area",
998
- label: fileDropLabel,
999
- description: fileDropDescription,
1000
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
1001
- "w-full",
1002
- application && "flex min-h-[calc(100svh-4rem)] flex-1 flex-col md:block md:min-h-0",
1003
- workspace && "flex h-full min-h-0 flex-1 flex-col overflow-hidden",
1004
- className
1005
- ),
1006
- children: showEmptyPending ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1007
- "div",
1008
- {
1009
- "data-slot": "chat-empty-pending",
1010
- className: "flex min-h-0 flex-1 items-center justify-center px-4 py-8",
1011
- children: emptyPendingContent
1012
- }
1013
- ) : !conversationStarted ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1014
- "div",
1015
- {
1016
- "data-slot": "chat-empty",
1017
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
1018
- emptyAlign === "center" && "mx-auto flex w-full max-w-3xl flex-col items-center text-center",
1019
- application && "min-h-0 max-w-none flex-1 md:max-w-3xl",
1020
- workspace && "min-h-0 max-w-none flex-1 overflow-y-auto overscroll-contain px-4 pb-20"
1021
- ),
1022
- children: [
1023
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1024
- "div",
1025
- {
1026
- "data-slot": "chat-empty-intro",
1027
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
1028
- application && "flex flex-1 flex-col items-center justify-center px-6 py-8 md:contents",
1029
- workspace && "mt-auto w-full flex-none px-0 py-0"
1030
- ),
1031
- children: [
1032
- !compactEmptyState && emptyIcon && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "chat-empty-icon", className: "mb-4", children: emptyIcon }),
1033
- 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 }),
1034
- emptySubtitle && !compactEmptyState && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1035
- "p",
1036
- {
1037
- "data-slot": "chat-empty-subtitle",
1038
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
1039
- "text-base text-muted-foreground leading-relaxed mb-6 max-w-md",
1040
- emptyAlign === "center" && "mx-auto"
1041
- ),
1042
- children: emptySubtitle
1043
- }
1044
- )
1045
- ]
1046
- }
1047
- ),
1048
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1049
- _chunk2KFZQJH5cjs.ActionDock,
1050
- {
1051
- shrink: false,
1052
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
1053
- application && "px-4 py-3 md:border-0 md:bg-transparent md:p-0 md:backdrop-blur-none md:supports-backdrop-filter:bg-transparent",
1054
- !application && "border-0 bg-transparent p-0 backdrop-blur-none",
1055
- workspace && "mb-auto mt-2 w-full max-w-3xl border-0 bg-transparent p-0 backdrop-blur-none supports-[backdrop-filter]:bg-transparent"
1056
- ),
1057
- children: [
1058
- showEmptyFileDropzone && onFilesSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1059
- _chunkZLEM2SAUcjs.FileDropzone,
1060
- {
1061
- multiple: true,
1062
- onFiles: onFilesSelected,
1063
- accept: attachmentAccept,
1064
- label: emptyFileDropzoneLabel,
1065
- description: emptyFileDropzoneDescription,
1066
- icon: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.FileText, {}),
1067
- className: "mb-4 rounded-lg bg-muted/20 py-8"
1068
- }
1069
- ),
1070
- mode === "voice" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1071
- VoiceHero,
1072
- {
1073
- onSubmit: (text) => void send(text),
1074
- voice,
1075
- voiceSession: voiceSession ? { ...voiceSession, disabled: voiceSession.disabled || pending } : void 0,
1076
- voiceTitle,
1077
- voiceLang,
1078
- label: voiceHeroLabel,
1079
- switchLabel: voiceHeroSwitchLabel,
1080
- onSwitchToText: () => setUserMode("text")
1081
- }
1082
- ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1083
- ChatInput,
1084
- {
1085
- value: input,
1086
- onChange: setInput,
1087
- onSend: (text) => void send(text),
1088
- pending,
1089
- placeholder,
1090
- size: showEmptyFileDropzone || application && isMobile ? "md" : "lg",
1091
- voice,
1092
- voiceSession,
1093
- voiceTitle,
1094
- voiceLang,
1095
- submitLabel,
1096
- autoFocus: !isMobile,
1097
- inputRef,
1098
- attachments,
1099
- onFilesSelected,
1100
- onRemoveAttachment,
1101
- accept: attachmentAccept,
1102
- addFilesLabel,
1103
- uploadingLabel,
1104
- appearance: composerAppearance,
1105
- helperText: composerHelperText,
1106
- privacyNote: composerPrivacyNote,
1107
- className: workspace ? "rounded-3xl shadow-sm" : void 0
1108
- }
1109
- ),
1110
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatError, { children: error }),
1111
- !pending && examplePromptsLoading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ExamplePromptsLoading, { label: examplePromptsLoadingLabel }),
1112
- !pending && !examplePromptsLoading && examplePrompts.length > 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1113
- ChatSuggestions,
1114
- {
1115
- slot: "chat-examples",
1116
- items: examplePrompts,
1117
- onSelect: (prompt) => void sendSuggestion(prompt),
1118
- label: examplePromptsLabel,
1119
- variant: examplePromptsVariant,
1120
- className: examplePromptsVariant === "cards" ? "mt-4" : "mt-3"
1121
- }
1122
- ),
1123
- emptyFooter && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { "data-slot": "chat-empty-footer", className: "mt-5", children: emptyFooter })
1124
- ]
1125
- }
1126
- )
1127
- ]
1128
- }
1129
- ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
1130
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1131
- ChatThread,
1132
- {
1133
- messages,
1134
- pending,
1135
- pendingLabel,
1136
- scrollButtonLabel,
1137
- uploadingLabel,
1138
- maxHeight: workspace || application && isMobile ? "none" : threadMaxHeight,
1139
- appearance: workspace ? "workspace" : "bubbles",
1140
- footer: threadFooter,
1141
- markdownComponents,
1142
- onOpenAttachment,
1143
- attachmentAction,
1144
- messageActions,
1145
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
1146
- "mb-3",
1147
- application && "min-h-0 flex-1 px-4 py-4 md:px-0 md:py-0",
1148
- workspace && "mb-0 min-h-0 flex-1"
1149
- )
1150
- }
1151
- ),
1152
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
1153
- _chunk2KFZQJH5cjs.ActionDock,
1154
- {
1155
- shrink: false,
1156
- className: _chunkKWLSBTB2cjs.cn.call(void 0,
1157
- "pt-3",
1158
- application && "px-4 py-3 md:bg-transparent md:px-0 md:pb-0 md:backdrop-blur-none md:supports-backdrop-filter:bg-transparent",
1159
- 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",
1160
- workspace && mobileCompactComposer && "max-md:pb-[max(0.75rem,env(safe-area-inset-bottom))] max-md:pt-3"
1161
- ),
1162
- children: [
1163
- !compactSuggestions && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1164
- ChatSuggestions,
1165
- {
1166
- slot: "chat-replies",
1167
- items: replySuggestions,
1168
- onSelect: (reply) => void sendSuggestion(reply),
1169
- label: replySuggestionsLabel,
1170
- showLabel: false,
1171
- disabled: pending,
1172
- className: _chunkKWLSBTB2cjs.cn.call(void 0, "mb-3", workspace && "mx-auto max-w-3xl")
1173
- }
1174
- ),
1175
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1176
- ChatInput,
1177
- {
1178
- header: compactSuggestions && replySuggestions.length > 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
1179
- MobileReplySuggestions,
1180
- {
1181
- items: replySuggestions,
1182
- onSelect: (reply) => void sendSuggestion(reply, false),
1183
- label: replySuggestionsLabel,
1184
- moreLabel: replySuggestionsMoreLabel,
1185
- closeLabel: replySuggestionsCloseLabel,
1186
- disabled: pending
1187
- },
1188
- JSON.stringify([_optionalChain([messages, 'access', _24 => _24.at, 'call', _25 => _25(-1), 'optionalAccess', _26 => _26.id]), replySuggestions])
1189
- ) : void 0,
1190
- value: input,
1191
- onChange: setInput,
1192
- onSend: (text) => void send(text),
1193
- pending,
1194
- placeholder: activePlaceholder,
1195
- size: composerAppearance === "spacious" ? "lg" : "sm",
1196
- voice,
1197
- voiceSession,
1198
- voiceTitle: _nullishCoalesce(activeVoiceTitle, () => ( voiceTitle)),
1199
- voiceLang,
1200
- inputRef,
1201
- attachments,
1202
- onFilesSelected,
1203
- onRemoveAttachment,
1204
- accept: attachmentAccept,
1205
- addFilesLabel,
1206
- uploadingLabel,
1207
- appearance: composerAppearance,
1208
- compactOnBlur: mobileCompactComposer && isMobile,
1209
- helperText: composerHelperText,
1210
- privacyNote: composerPrivacyNote,
1211
- className: workspace ? "mx-auto max-w-3xl rounded-3xl shadow-sm" : void 0
1212
- }
1213
- ),
1214
- error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatError, { className: workspace ? "mx-auto max-w-3xl px-2" : void 0, children: error })
1215
- ]
1216
- }
1217
- )
1218
- ] })
1219
- }
1220
- );
1221
- });
39
+ require('../chunk-R35FT53G.cjs');
40
+ require('../chunk-H2UFRLLN.cjs');
1222
41
 
1223
42
 
1224
43
 
1225
44
 
1226
45
 
1227
- exports.Chat = Chat; exports.ChatCopyAction = ChatCopyAction; exports.ChatInput = ChatInput; exports.ChatThread = ChatThread;
46
+ exports.Chat = _chunk4YJ6DGPLcjs.Chat; exports.ChatCopyAction = _chunk4YJ6DGPLcjs.ChatCopyAction; exports.ChatInput = _chunk4YJ6DGPLcjs.ChatInput; exports.ChatThread = _chunk4YJ6DGPLcjs.ChatThread;