@adatechnology/conversations-ui 0.1.0-rc.20 → 0.1.0-rc.21

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.
@@ -28,6 +28,19 @@ var DEFAULT_LOCALES = {
28
28
  untitledDocument: "Documento",
29
29
  downloadFile: "Baixar"
30
30
  },
31
+ transcription: {
32
+ label: "Transcri\xE7\xE3o",
33
+ copy: "Copiar",
34
+ copied: "Copiado!",
35
+ transcribe: "Transcrever \xE1udio",
36
+ transcribing: "Transcrevendo...",
37
+ retry: "Transcrever novamente",
38
+ failed: "Falha ao transcrever \u2014 tentar novamente",
39
+ empty: "Sem fala detectada",
40
+ unsupported: "Formato de \xE1udio n\xE3o suportado para transcri\xE7\xE3o",
41
+ showMore: "ver transcri\xE7\xE3o completa",
42
+ showLess: "ver menos"
43
+ },
31
44
  selection: {
32
45
  select: "Selecionar"
33
46
  },
@@ -40,6 +53,7 @@ var ConversationLocalesContext = createContext(DEFAULT_LOCALES);
40
53
  function ConversationLocalesProvider({ children, locales }) {
41
54
  const merged = {
42
55
  bubble: { ...DEFAULT_LOCALES.bubble, ...locales?.bubble },
56
+ transcription: { ...DEFAULT_LOCALES.transcription, ...locales?.transcription },
43
57
  selection: { ...DEFAULT_LOCALES.selection, ...locales?.selection },
44
58
  dateDivider: { ...DEFAULT_LOCALES.dateDivider, ...locales?.dateDivider }
45
59
  };
@@ -166,36 +180,183 @@ function AudioPlayer({ src, isMine = false }) {
166
180
  ] });
167
181
  }
168
182
 
183
+ // src/AudioTranscription.tsx
184
+ import { useCallback, useState as useState2 } from "react";
185
+ import { Check, Copy, FileText, Loader2, RefreshCw } from "lucide-react";
186
+
187
+ // src/lib/cn.ts
188
+ import { clsx } from "clsx";
189
+ import { twMerge } from "tailwind-merge";
190
+ function cn(...inputs) {
191
+ return twMerge(clsx(inputs));
192
+ }
193
+
194
+ // src/AudioTranscription.tsx
195
+ import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
196
+ var COPIED_FEEDBACK_MS = 2e3;
197
+ var COLLAPSE_ABOVE_CHARS = 320;
198
+ var COLLAPSED_LINE_CLAMP = 4;
199
+ function AudioTranscription({ transcription, onTranscribe, isMine = false }) {
200
+ const { transcription: locales } = useConversationLocales();
201
+ const [hasCopied, setHasCopied] = useState2(false);
202
+ const [isTranscribing, setIsTranscribing] = useState2(false);
203
+ const [hasRequestFailed, setHasRequestFailed] = useState2(false);
204
+ const [justTranscribed, setJustTranscribed] = useState2();
205
+ const [isExpanded, setIsExpanded] = useState2(false);
206
+ const effective = justTranscribed ?? transcription;
207
+ const text = effective?.text?.trim() ?? "";
208
+ const status = effective?.status;
209
+ const isLong = text.length > COLLAPSE_ABOVE_CHARS;
210
+ const isTruncated = isLong && !isExpanded;
211
+ const isDone = status === "done";
212
+ const hasText = isDone && text.length > 0;
213
+ const isSilent = isDone && text.length === 0;
214
+ const handleCopy = useCallback(async () => {
215
+ if (!text) return;
216
+ try {
217
+ await navigator.clipboard.writeText(text);
218
+ setHasCopied(true);
219
+ setTimeout(() => setHasCopied(false), COPIED_FEEDBACK_MS);
220
+ } catch {
221
+ }
222
+ }, [text]);
223
+ const handleTranscribe = useCallback(async () => {
224
+ if (!onTranscribe || isTranscribing) return;
225
+ setIsTranscribing(true);
226
+ setHasRequestFailed(false);
227
+ try {
228
+ const result = await onTranscribe();
229
+ if (result) setJustTranscribed(result);
230
+ } catch {
231
+ setHasRequestFailed(true);
232
+ } finally {
233
+ setIsTranscribing(false);
234
+ }
235
+ }, [onTranscribe, isTranscribing]);
236
+ const dividerClass = isMine ? "border-black/10 dark:border-white/10" : "border-black/10 dark:border-white/10";
237
+ if (!status && !onTranscribe) return null;
238
+ if (!status || status === "pending" || status === "failed") {
239
+ return /* @__PURE__ */ jsx4("div", { className: `mt-1.5 border-t pt-1.5 ${dividerClass}`, children: /* @__PURE__ */ jsx4(
240
+ TranscribeButton,
241
+ {
242
+ label: resolveActionLabel({ status, hasRequestFailed, isTranscribing, locales }),
243
+ isBusy: isTranscribing,
244
+ onClick: handleTranscribe,
245
+ isDisabled: !onTranscribe
246
+ }
247
+ ) });
248
+ }
249
+ if (status === "unsupported") {
250
+ return /* @__PURE__ */ jsx4("div", { className: `mt-1.5 border-t pt-1.5 ${dividerClass}`, children: /* @__PURE__ */ jsx4("p", { className: "text-xs italic text-gray-500 dark:text-gray-400", children: locales.unsupported }) });
251
+ }
252
+ return /* @__PURE__ */ jsxs3("div", { className: `mt-1.5 border-t pt-1.5 ${dividerClass}`, children: [
253
+ /* @__PURE__ */ jsxs3("div", { className: "mb-0.5 flex items-center gap-1.5", children: [
254
+ /* @__PURE__ */ jsx4(FileText, { size: 11, className: "flex-shrink-0 text-gray-500 dark:text-gray-400", "aria-hidden": true }),
255
+ /* @__PURE__ */ jsx4("span", { className: "text-[11px] font-medium uppercase tracking-wide text-gray-500 dark:text-gray-400", children: locales.label }),
256
+ hasText && /* @__PURE__ */ jsx4(
257
+ "button",
258
+ {
259
+ onClick: handleCopy,
260
+ title: locales.copy,
261
+ "aria-label": hasCopied ? locales.copied : locales.copy,
262
+ className: "ml-auto flex flex-shrink-0 items-center gap-1 rounded px-1.5 py-0.5 text-[11px] text-gray-500 transition-colors hover:bg-black/5 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-white/10 dark:hover:text-gray-200",
263
+ children: hasCopied ? /* @__PURE__ */ jsxs3(Fragment, { children: [
264
+ /* @__PURE__ */ jsx4(Check, { size: 11, "aria-hidden": true }),
265
+ /* @__PURE__ */ jsx4("span", { children: locales.copied })
266
+ ] }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
267
+ /* @__PURE__ */ jsx4(Copy, { size: 11, "aria-hidden": true }),
268
+ /* @__PURE__ */ jsx4("span", { children: locales.copy })
269
+ ] })
270
+ }
271
+ )
272
+ ] }),
273
+ isSilent ? /* @__PURE__ */ jsx4("p", { className: "text-xs italic text-gray-500 dark:text-gray-400", children: locales.empty }) : /* @__PURE__ */ jsxs3(Fragment, { children: [
274
+ /* @__PURE__ */ jsx4(
275
+ "p",
276
+ {
277
+ className: cn(
278
+ "select-all whitespace-pre-wrap break-words text-[13px] leading-[18px] text-gray-700 dark:text-gray-200",
279
+ isTruncated && "overflow-hidden"
280
+ ),
281
+ style: isTruncated ? {
282
+ display: "-webkit-box",
283
+ WebkitBoxOrient: "vertical",
284
+ WebkitLineClamp: COLLAPSED_LINE_CLAMP
285
+ } : void 0,
286
+ children: text
287
+ }
288
+ ),
289
+ isLong && /* @__PURE__ */ jsx4(
290
+ "button",
291
+ {
292
+ onClick: () => setIsExpanded((current) => !current),
293
+ className: "mt-1 text-[11px] font-medium text-gray-500 underline decoration-dotted hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200",
294
+ children: isExpanded ? locales.showLess : locales.showMore
295
+ }
296
+ )
297
+ ] }),
298
+ onTranscribe && /* @__PURE__ */ jsxs3(
299
+ "button",
300
+ {
301
+ onClick: handleTranscribe,
302
+ disabled: isTranscribing,
303
+ className: "mt-1 flex items-center gap-1 text-[11px] text-gray-400 opacity-0 transition-opacity hover:text-gray-600 focus:opacity-100 group-hover:opacity-100 disabled:opacity-50 dark:text-gray-500 dark:hover:text-gray-300",
304
+ children: [
305
+ isTranscribing ? /* @__PURE__ */ jsx4(Loader2, { size: 10, className: "animate-spin", "aria-hidden": true }) : /* @__PURE__ */ jsx4(RefreshCw, { size: 10, "aria-hidden": true }),
306
+ /* @__PURE__ */ jsx4("span", { children: isTranscribing ? locales.transcribing : locales.retry })
307
+ ]
308
+ }
309
+ )
310
+ ] });
311
+ }
312
+ function resolveActionLabel(params) {
313
+ if (params.isTranscribing) return params.locales.transcribing;
314
+ if (params.hasRequestFailed) return params.locales.retry;
315
+ if (params.status === "pending") return params.locales.transcribing;
316
+ if (params.status === "failed") return params.locales.failed;
317
+ return params.locales.transcribe;
318
+ }
319
+ function TranscribeButton({
320
+ label,
321
+ isBusy,
322
+ isDisabled,
323
+ onClick
324
+ }) {
325
+ return /* @__PURE__ */ jsxs3(
326
+ "button",
327
+ {
328
+ onClick,
329
+ disabled: isBusy || isDisabled,
330
+ className: "flex items-center gap-1.5 rounded px-1.5 py-0.5 text-[11px] text-gray-500 transition-colors hover:bg-black/5 hover:text-gray-700 disabled:opacity-60 dark:text-gray-400 dark:hover:bg-white/10 dark:hover:text-gray-200",
331
+ children: [
332
+ isBusy ? /* @__PURE__ */ jsx4(Loader2, { size: 11, className: "animate-spin", "aria-hidden": true }) : /* @__PURE__ */ jsx4(FileText, { size: 11, "aria-hidden": true }),
333
+ /* @__PURE__ */ jsx4("span", { children: label })
334
+ ]
335
+ }
336
+ );
337
+ }
338
+
169
339
  // src/FileIcon.tsx
170
340
  import {
171
341
  FileArchive,
172
342
  FileAudio,
173
343
  FileImage,
174
344
  FileSpreadsheet,
175
- FileText,
345
+ FileText as FileText2,
176
346
  FileVideo,
177
347
  File as FileGeneric,
178
348
  Presentation
179
349
  } from "lucide-react";
180
-
181
- // src/lib/cn.ts
182
- import { clsx } from "clsx";
183
- import { twMerge } from "tailwind-merge";
184
- function cn(...inputs) {
185
- return twMerge(clsx(inputs));
186
- }
187
-
188
- // src/FileIcon.tsx
189
- import { jsx as jsx4 } from "react/jsx-runtime";
350
+ import { jsx as jsx5 } from "react/jsx-runtime";
190
351
  var IMAGE_STYLE = { Icon: FileImage, colorClass: "text-violet-500" };
191
352
  var VIDEO_STYLE = { Icon: FileVideo, colorClass: "text-fuchsia-500" };
192
353
  var AUDIO_STYLE = { Icon: FileAudio, colorClass: "text-amber-500" };
193
354
  var SHEET_STYLE = { Icon: FileSpreadsheet, colorClass: "text-green-600" };
194
- var WORD_STYLE = { Icon: FileText, colorClass: "text-blue-500" };
355
+ var WORD_STYLE = { Icon: FileText2, colorClass: "text-blue-500" };
195
356
  var SLIDES_STYLE = { Icon: Presentation, colorClass: "text-orange-600" };
196
- var TEXT_STYLE = { Icon: FileText, colorClass: "text-gray-500" };
357
+ var TEXT_STYLE = { Icon: FileText2, colorClass: "text-gray-500" };
197
358
  var EXTENSION_STYLE = {
198
- pdf: { Icon: FileText, colorClass: "text-red-500" },
359
+ pdf: { Icon: FileText2, colorClass: "text-red-500" },
199
360
  doc: WORD_STYLE,
200
361
  docx: WORD_STYLE,
201
362
  xls: SHEET_STYLE,
@@ -242,7 +403,7 @@ function FileIcon({ filename, mimeType, size = 20, className }) {
242
403
  const extension = resolveFileIconExtension(filename, mimeType);
243
404
  const style = EXTENSION_STYLE[extension] ?? { Icon: FileGeneric, colorClass: "text-gray-500" };
244
405
  const { Icon, colorClass } = style;
245
- return /* @__PURE__ */ jsx4(Icon, { size, className: cn(colorClass, className) });
406
+ return /* @__PURE__ */ jsx5(Icon, { size, className: cn(colorClass, className) });
246
407
  }
247
408
 
248
409
  // src/lib/format.ts
@@ -274,8 +435,8 @@ function formatFileSize(bytes) {
274
435
  }
275
436
 
276
437
  // src/MediaRenderer.tsx
277
- import { useState as useState2 } from "react";
278
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
438
+ import { useState as useState3 } from "react";
439
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
279
440
  function documentTypeLabel(filename, mimeType) {
280
441
  const extension = filename?.split(".").pop();
281
442
  if (extension && extension.length <= 5 && extension !== filename) return extension.toUpperCase();
@@ -296,9 +457,9 @@ function hasLazyRef(message) {
296
457
  return Boolean(message.uploadId || message.mediaId);
297
458
  }
298
459
  function useLazyMediaUrl(message, onResolveUrl) {
299
- const [url, setUrl] = useState2(null);
300
- const [loading, setLoading] = useState2(false);
301
- const [error, setError] = useState2(false);
460
+ const [url, setUrl] = useState3(null);
461
+ const [loading, setLoading] = useState3(false);
462
+ const [error, setError] = useState3(false);
302
463
  const load = async () => {
303
464
  if (url || loading || !onResolveUrl) return;
304
465
  setLoading(true);
@@ -315,22 +476,28 @@ function useLazyMediaUrl(message, onResolveUrl) {
315
476
  };
316
477
  return { url, loading, error, load };
317
478
  }
318
- function MediaRenderer({ message, onLightbox, onResolveUrl, className }) {
479
+ function MediaRenderer({
480
+ message,
481
+ onLightbox,
482
+ onResolveUrl,
483
+ onTranscribeAudio,
484
+ className
485
+ }) {
319
486
  const { bubble } = useConversationLocales();
320
487
  const eagerSrc = resolveMediaSource(message);
321
488
  const lazy = useLazyMediaUrl(message, onResolveUrl);
322
489
  const src = eagerSrc ?? lazy.url;
323
490
  const canLazyLoad = !eagerSrc && hasLazyRef(message) && Boolean(onResolveUrl);
324
491
  function LazyMediaButton({ icon, label }) {
325
- return /* @__PURE__ */ jsxs3(
492
+ return /* @__PURE__ */ jsxs4(
326
493
  "button",
327
494
  {
328
495
  onClick: lazy.load,
329
496
  disabled: lazy.loading,
330
497
  className: "flex min-w-[180px] items-center gap-2 rounded-lg bg-black/5 px-2 py-1.5 text-left transition-colors hover:bg-black/10 disabled:opacity-60 dark:bg-white/10 dark:hover:bg-white/15",
331
498
  children: [
332
- /* @__PURE__ */ jsx5("span", { className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full bg-gray-600 text-white", children: icon }),
333
- /* @__PURE__ */ jsx5("span", { className: "truncate text-xs text-gray-600 dark:text-gray-300", children: label })
499
+ /* @__PURE__ */ jsx6("span", { className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full bg-gray-600 text-white", children: icon }),
500
+ /* @__PURE__ */ jsx6("span", { className: "truncate text-xs text-gray-600 dark:text-gray-300", children: label })
334
501
  ]
335
502
  }
336
503
  );
@@ -339,82 +506,96 @@ function MediaRenderer({ message, onLightbox, onResolveUrl, className }) {
339
506
  case "image":
340
507
  case "sticker": {
341
508
  if (!src && canLazyLoad) {
342
- return /* @__PURE__ */ jsx5(
509
+ return /* @__PURE__ */ jsx6(
343
510
  LazyMediaButton,
344
511
  {
345
- icon: /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
346
- /* @__PURE__ */ jsx5("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
347
- /* @__PURE__ */ jsx5("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
348
- /* @__PURE__ */ jsx5("polyline", { points: "21 15 16 10 5 21" })
512
+ icon: /* @__PURE__ */ jsxs4("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
513
+ /* @__PURE__ */ jsx6("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
514
+ /* @__PURE__ */ jsx6("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
515
+ /* @__PURE__ */ jsx6("polyline", { points: "21 15 16 10 5 21" })
349
516
  ] }),
350
517
  label: lazy.loading ? bubble.mediaLoading : lazy.error ? bubble.mediaRetry : bubble.viewImage
351
518
  }
352
519
  );
353
520
  }
354
- return /* @__PURE__ */ jsx5("div", { className: "min-w-[200px]", children: src ? /* @__PURE__ */ jsx5("img", { src, alt: message.caption ?? bubble.imageAlt, className: "w-full max-h-80 object-cover cursor-pointer hover:opacity-90 transition-opacity", onClick: () => onLightbox(src), loading: "lazy" }) : /* @__PURE__ */ jsx5("div", { className: "w-full h-40 bg-gray-200 flex items-center justify-center text-gray-400", children: /* @__PURE__ */ jsxs3("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
355
- /* @__PURE__ */ jsx5("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
356
- /* @__PURE__ */ jsx5("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
357
- /* @__PURE__ */ jsx5("polyline", { points: "21 15 16 10 5 21" })
521
+ return /* @__PURE__ */ jsx6("div", { className: "min-w-[200px]", children: src ? /* @__PURE__ */ jsx6("img", { src, alt: message.caption ?? bubble.imageAlt, className: "w-full max-h-80 object-cover cursor-pointer hover:opacity-90 transition-opacity", onClick: () => onLightbox(src), loading: "lazy" }) : /* @__PURE__ */ jsx6("div", { className: "w-full h-40 bg-gray-200 flex items-center justify-center text-gray-400", children: /* @__PURE__ */ jsxs4("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
522
+ /* @__PURE__ */ jsx6("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
523
+ /* @__PURE__ */ jsx6("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
524
+ /* @__PURE__ */ jsx6("polyline", { points: "21 15 16 10 5 21" })
358
525
  ] }) }) });
359
526
  }
360
527
  case "video": {
361
528
  if (!src && canLazyLoad) {
362
- return /* @__PURE__ */ jsx5(
529
+ return /* @__PURE__ */ jsx6(
363
530
  LazyMediaButton,
364
531
  {
365
- icon: /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
366
- /* @__PURE__ */ jsx5("polygon", { points: "23 7 16 12 23 17 23 7" }),
367
- /* @__PURE__ */ jsx5("rect", { x: "1", y: "5", width: "15", height: "14", rx: "2", ry: "2" })
532
+ icon: /* @__PURE__ */ jsxs4("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
533
+ /* @__PURE__ */ jsx6("polygon", { points: "23 7 16 12 23 17 23 7" }),
534
+ /* @__PURE__ */ jsx6("rect", { x: "1", y: "5", width: "15", height: "14", rx: "2", ry: "2" })
368
535
  ] }),
369
536
  label: lazy.loading ? bubble.mediaLoading : lazy.error ? bubble.mediaRetry : bubble.viewVideo
370
537
  }
371
538
  );
372
539
  }
373
- return /* @__PURE__ */ jsx5("div", { className: "min-w-[200px]", children: src ? /* @__PURE__ */ jsx5("video", { src, className: "w-full max-h-80 rounded-lg", controls: true, preload: "metadata", children: /* @__PURE__ */ jsx5("track", { kind: "captions" }) }) : /* @__PURE__ */ jsx5("div", { className: "w-full h-32 bg-gray-200 rounded-lg flex items-center justify-center text-gray-400", children: /* @__PURE__ */ jsxs3("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
374
- /* @__PURE__ */ jsx5("polygon", { points: "23 7 16 12 23 17 23 7" }),
375
- /* @__PURE__ */ jsx5("rect", { x: "1", y: "5", width: "15", height: "14", rx: "2", ry: "2" })
540
+ return /* @__PURE__ */ jsx6("div", { className: "min-w-[200px]", children: src ? /* @__PURE__ */ jsx6("video", { src, className: "w-full max-h-80 rounded-lg", controls: true, preload: "metadata", children: /* @__PURE__ */ jsx6("track", { kind: "captions" }) }) : /* @__PURE__ */ jsx6("div", { className: "w-full h-32 bg-gray-200 rounded-lg flex items-center justify-center text-gray-400", children: /* @__PURE__ */ jsxs4("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
541
+ /* @__PURE__ */ jsx6("polygon", { points: "23 7 16 12 23 17 23 7" }),
542
+ /* @__PURE__ */ jsx6("rect", { x: "1", y: "5", width: "15", height: "14", rx: "2", ry: "2" })
376
543
  ] }) }) });
377
544
  }
378
545
  case "audio": {
546
+ const transcriptionBlock = /* @__PURE__ */ jsx6(
547
+ AudioTranscription,
548
+ {
549
+ transcription: message.transcription,
550
+ isMine: message.direction === "outbound",
551
+ ...onTranscribeAudio ? { onTranscribe: onTranscribeAudio } : {}
552
+ }
553
+ );
379
554
  if (!src && canLazyLoad) {
380
- return /* @__PURE__ */ jsx5(
381
- LazyMediaButton,
382
- {
383
- icon: /* @__PURE__ */ jsx5("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", className: "translate-x-0.5", children: /* @__PURE__ */ jsx5("polygon", { points: "5 3 19 12 5 21 5 3" }) }),
384
- label: lazy.loading ? bubble.mediaLoading : lazy.error ? bubble.mediaRetry : bubble.listenAudio
385
- }
386
- );
555
+ return /* @__PURE__ */ jsxs4("div", { className: "min-w-[200px]", children: [
556
+ /* @__PURE__ */ jsx6(
557
+ LazyMediaButton,
558
+ {
559
+ icon: /* @__PURE__ */ jsx6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", className: "translate-x-0.5", children: /* @__PURE__ */ jsx6("polygon", { points: "5 3 19 12 5 21 5 3" }) }),
560
+ label: lazy.loading ? bubble.mediaLoading : lazy.error ? bubble.mediaRetry : bubble.listenAudio
561
+ }
562
+ ),
563
+ transcriptionBlock
564
+ ] });
387
565
  }
388
- return /* @__PURE__ */ jsx5("div", { className: "min-w-[200px]", children: src ? /* @__PURE__ */ jsx5(AudioPlayer, { src, isMine: message.direction === "outbound" }) : /* @__PURE__ */ jsx5("div", { className: "h-12 bg-gray-200 rounded-lg flex items-center justify-center text-gray-400 text-xs", children: bubble.mediaUnavailable }) });
566
+ return /* @__PURE__ */ jsxs4("div", { className: "min-w-[200px]", children: [
567
+ src ? /* @__PURE__ */ jsx6(AudioPlayer, { src, isMine: message.direction === "outbound" }) : /* @__PURE__ */ jsx6("div", { className: "h-12 bg-gray-200 rounded-lg flex items-center justify-center text-gray-400 text-xs", children: bubble.mediaUnavailable }),
568
+ transcriptionBlock
569
+ ] });
389
570
  }
390
571
  case "document": {
391
572
  const typeLabel = documentTypeLabel(message.filename, message.mimeType);
392
573
  const sizeLabel = message.sizeBytes ? formatFileSize(message.sizeBytes) : null;
393
- return /* @__PURE__ */ jsxs3("div", { className: cn("flex items-center gap-3 min-w-[200px]", className), children: [
394
- /* @__PURE__ */ jsx5("div", { className: "w-10 h-10 bg-gray-200 rounded-lg flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx5(FileIcon, { filename: message.filename, mimeType: message.mimeType }) }),
395
- /* @__PURE__ */ jsxs3("div", { className: "flex-1 min-w-0", children: [
396
- /* @__PURE__ */ jsx5("p", { className: "text-sm font-medium truncate", children: message.filename ?? bubble.untitledDocument }),
397
- /* @__PURE__ */ jsx5("p", { className: "truncate text-xs text-gray-500", children: sizeLabel ? `${typeLabel} \xB7 ${sizeLabel}` : typeLabel })
574
+ return /* @__PURE__ */ jsxs4("div", { className: cn("flex items-center gap-3 min-w-[200px]", className), children: [
575
+ /* @__PURE__ */ jsx6("div", { className: "w-10 h-10 bg-gray-200 rounded-lg flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx6(FileIcon, { filename: message.filename, mimeType: message.mimeType }) }),
576
+ /* @__PURE__ */ jsxs4("div", { className: "flex-1 min-w-0", children: [
577
+ /* @__PURE__ */ jsx6("p", { className: "text-sm font-medium truncate", children: message.filename ?? bubble.untitledDocument }),
578
+ /* @__PURE__ */ jsx6("p", { className: "truncate text-xs text-gray-500", children: sizeLabel ? `${typeLabel} \xB7 ${sizeLabel}` : typeLabel })
398
579
  ] }),
399
- src ? /* @__PURE__ */ jsx5("a", { href: src, download: message.filename, className: "w-8 h-8 flex items-center justify-center rounded-full bg-gray-200 hover:bg-gray-300 flex-shrink-0 transition-colors", "aria-label": bubble.downloadFile, children: /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", className: "text-gray-600", children: [
400
- /* @__PURE__ */ jsx5("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
401
- /* @__PURE__ */ jsx5("polyline", { points: "7 10 12 15 17 10" }),
402
- /* @__PURE__ */ jsx5("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
403
- ] }) }) : canLazyLoad ? /* @__PURE__ */ jsx5(
580
+ src ? /* @__PURE__ */ jsx6("a", { href: src, download: message.filename, className: "w-8 h-8 flex items-center justify-center rounded-full bg-gray-200 hover:bg-gray-300 flex-shrink-0 transition-colors", "aria-label": bubble.downloadFile, children: /* @__PURE__ */ jsxs4("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", className: "text-gray-600", children: [
581
+ /* @__PURE__ */ jsx6("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
582
+ /* @__PURE__ */ jsx6("polyline", { points: "7 10 12 15 17 10" }),
583
+ /* @__PURE__ */ jsx6("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
584
+ ] }) }) : canLazyLoad ? /* @__PURE__ */ jsx6(
404
585
  "button",
405
586
  {
406
587
  onClick: lazy.load,
407
588
  disabled: lazy.loading,
408
589
  className: "w-8 h-8 flex items-center justify-center rounded-full bg-gray-200 hover:bg-gray-300 flex-shrink-0 transition-colors disabled:opacity-50",
409
590
  "aria-label": bubble.downloadFile,
410
- children: /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", className: "text-gray-600", children: [
411
- /* @__PURE__ */ jsx5("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
412
- /* @__PURE__ */ jsx5("polyline", { points: "7 10 12 15 17 10" }),
413
- /* @__PURE__ */ jsx5("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
591
+ children: /* @__PURE__ */ jsxs4("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", className: "text-gray-600", children: [
592
+ /* @__PURE__ */ jsx6("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
593
+ /* @__PURE__ */ jsx6("polyline", { points: "7 10 12 15 17 10" }),
594
+ /* @__PURE__ */ jsx6("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
414
595
  ] })
415
596
  }
416
597
  ) : null,
417
- lazy.error && /* @__PURE__ */ jsx5("span", { className: "text-xs text-red-500 flex-shrink-0", children: bubble.mediaError })
598
+ lazy.error && /* @__PURE__ */ jsx6("span", { className: "text-xs text-red-500 flex-shrink-0", children: bubble.mediaError })
418
599
  ] });
419
600
  }
420
601
  default:
@@ -423,7 +604,7 @@ function MediaRenderer({ message, onLightbox, onResolveUrl, className }) {
423
604
  }
424
605
 
425
606
  // src/Lightbox.tsx
426
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
607
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
427
608
  var DEFAULT_LIGHTBOX_LABELS = {
428
609
  imageAlt: "Imagem",
429
610
  close: "Fechar"
@@ -431,16 +612,16 @@ var DEFAULT_LIGHTBOX_LABELS = {
431
612
  function Lightbox({ imageUrl, caption, onClose, labels }) {
432
613
  const imageAltLabel = labels?.imageAlt ?? DEFAULT_LIGHTBOX_LABELS.imageAlt;
433
614
  const closeLabel = labels?.close ?? DEFAULT_LIGHTBOX_LABELS.close;
434
- return /* @__PURE__ */ jsx6("div", { className: "fixed inset-0 z-50 bg-black/85 flex items-center justify-center p-4", onClick: onClose, children: /* @__PURE__ */ jsxs4("div", { className: "max-w-[90vw] max-h-[90vh] flex flex-col items-center", onClick: (e) => e.stopPropagation(), children: [
435
- /* @__PURE__ */ jsx6("img", { src: imageUrl, alt: caption ?? imageAltLabel, className: "max-w-full max-h-[80vh] object-contain rounded-lg" }),
436
- caption && /* @__PURE__ */ jsx6("p", { className: "text-white text-sm mt-3 text-center", children: caption }),
437
- /* @__PURE__ */ jsx6("button", { onClick: onClose, className: "mt-4 px-4 py-2 bg-white/20 text-white rounded-lg hover:bg-white/30 transition-colors", children: closeLabel })
615
+ return /* @__PURE__ */ jsx7("div", { className: "fixed inset-0 z-50 bg-black/85 flex items-center justify-center p-4", onClick: onClose, children: /* @__PURE__ */ jsxs5("div", { className: "max-w-[90vw] max-h-[90vh] flex flex-col items-center", onClick: (e) => e.stopPropagation(), children: [
616
+ /* @__PURE__ */ jsx7("img", { src: imageUrl, alt: caption ?? imageAltLabel, className: "max-w-full max-h-[80vh] object-contain rounded-lg" }),
617
+ caption && /* @__PURE__ */ jsx7("p", { className: "text-white text-sm mt-3 text-center", children: caption }),
618
+ /* @__PURE__ */ jsx7("button", { onClick: onClose, className: "mt-4 px-4 py-2 bg-white/20 text-white rounded-lg hover:bg-white/30 transition-colors", children: closeLabel })
438
619
  ] }) });
439
620
  }
440
621
 
441
622
  // src/InteractiveMessage.tsx
442
- import { useState as useState3 } from "react";
443
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
623
+ import { useState as useState4 } from "react";
624
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
444
625
  var FORMATTING_CLASSES = "[&_strong]:font-bold [&_em]:italic [&_del]:line-through";
445
626
  var DEFAULT_INTERACTIVE_MESSAGE_LABELS = {
446
627
  openList: "Ver op\xE7\xF5es"
@@ -453,14 +634,14 @@ function collectButtons(payload) {
453
634
  }
454
635
  function InteractiveMessage({ payload, onSelect, labels, className }) {
455
636
  const openListLabel = labels?.openList ?? DEFAULT_INTERACTIVE_MESSAGE_LABELS.openList;
456
- const [isListOpen, setIsListOpen] = useState3(false);
637
+ const [isListOpen, setIsListOpen] = useState4(false);
457
638
  const buttons = collectButtons(payload);
458
639
  const sections = payload.action?.sections ?? [];
459
640
  const hasRows = collectRows(payload).length > 0;
460
641
  const isInteractable = onSelect !== void 0;
461
- return /* @__PURE__ */ jsxs5("div", { className: cn("flex flex-col gap-1", className), children: [
462
- payload.header?.text ? /* @__PURE__ */ jsx7("p", { className: cn("text-sm font-semibold text-gray-900 dark:text-gray-100", FORMATTING_CLASSES), children: parseWhatsAppFormatting(payload.header.text) }) : null,
463
- payload.body?.text ? /* @__PURE__ */ jsx7(
642
+ return /* @__PURE__ */ jsxs6("div", { className: cn("flex flex-col gap-1", className), children: [
643
+ payload.header?.text ? /* @__PURE__ */ jsx8("p", { className: cn("text-sm font-semibold text-gray-900 dark:text-gray-100", FORMATTING_CLASSES), children: parseWhatsAppFormatting(payload.header.text) }) : null,
644
+ payload.body?.text ? /* @__PURE__ */ jsx8(
464
645
  "p",
465
646
  {
466
647
  className: cn(
@@ -470,8 +651,8 @@ function InteractiveMessage({ payload, onSelect, labels, className }) {
470
651
  children: parseWhatsAppFormatting(payload.body.text)
471
652
  }
472
653
  ) : null,
473
- payload.footer?.text ? /* @__PURE__ */ jsx7("p", { className: cn("text-xs text-gray-500 dark:text-gray-400", FORMATTING_CLASSES), children: parseWhatsAppFormatting(payload.footer.text) }) : null,
474
- buttons.length > 0 ? /* @__PURE__ */ jsx7("div", { className: "mt-1 flex flex-col gap-1 border-t border-gray-200 pt-1 dark:border-gray-700", children: buttons.map((button) => /* @__PURE__ */ jsx7(
654
+ payload.footer?.text ? /* @__PURE__ */ jsx8("p", { className: cn("text-xs text-gray-500 dark:text-gray-400", FORMATTING_CLASSES), children: parseWhatsAppFormatting(payload.footer.text) }) : null,
655
+ buttons.length > 0 ? /* @__PURE__ */ jsx8("div", { className: "mt-1 flex flex-col gap-1 border-t border-gray-200 pt-1 dark:border-gray-700", children: buttons.map((button) => /* @__PURE__ */ jsx8(
475
656
  "button",
476
657
  {
477
658
  type: "button",
@@ -482,8 +663,8 @@ function InteractiveMessage({ payload, onSelect, labels, className }) {
482
663
  },
483
664
  button.id
484
665
  )) }) : null,
485
- hasRows ? /* @__PURE__ */ jsxs5("div", { className: "mt-1 border-t border-gray-200 pt-1 dark:border-gray-700", children: [
486
- /* @__PURE__ */ jsxs5(
666
+ hasRows ? /* @__PURE__ */ jsxs6("div", { className: "mt-1 border-t border-gray-200 pt-1 dark:border-gray-700", children: [
667
+ /* @__PURE__ */ jsxs6(
487
668
  "button",
488
669
  {
489
670
  type: "button",
@@ -496,9 +677,9 @@ function InteractiveMessage({ payload, onSelect, labels, className }) {
496
677
  ]
497
678
  }
498
679
  ),
499
- isListOpen ? /* @__PURE__ */ jsx7("div", { className: "mt-1 flex flex-col gap-1", children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs5("div", { className: "flex flex-col", children: [
500
- section.title ? /* @__PURE__ */ jsx7("p", { className: "px-3 py-1 text-xs font-semibold uppercase text-gray-500 dark:text-gray-400", children: section.title }) : null,
501
- (section.rows ?? []).map((row) => /* @__PURE__ */ jsxs5(
680
+ isListOpen ? /* @__PURE__ */ jsx8("div", { className: "mt-1 flex flex-col gap-1", children: sections.map((section, sectionIndex) => /* @__PURE__ */ jsxs6("div", { className: "flex flex-col", children: [
681
+ section.title ? /* @__PURE__ */ jsx8("p", { className: "px-3 py-1 text-xs font-semibold uppercase text-gray-500 dark:text-gray-400", children: section.title }) : null,
682
+ (section.rows ?? []).map((row) => /* @__PURE__ */ jsxs6(
502
683
  "button",
503
684
  {
504
685
  type: "button",
@@ -506,8 +687,8 @@ function InteractiveMessage({ payload, onSelect, labels, className }) {
506
687
  onClick: () => onSelect?.({ kind: "list", option: row }),
507
688
  className: "rounded-md px-3 py-1.5 text-left text-sm text-gray-900 transition-colors enabled:hover:bg-gray-100 disabled:cursor-default dark:text-gray-100 dark:enabled:hover:bg-gray-700",
508
689
  children: [
509
- /* @__PURE__ */ jsx7("span", { className: "block", children: row.title }),
510
- row.description ? /* @__PURE__ */ jsx7("span", { className: "block text-xs text-gray-500 dark:text-gray-400", children: row.description }) : null
690
+ /* @__PURE__ */ jsx8("span", { className: "block", children: row.title }),
691
+ row.description ? /* @__PURE__ */ jsx8("span", { className: "block text-xs text-gray-500 dark:text-gray-400", children: row.description }) : null
511
692
  ]
512
693
  },
513
694
  row.id
@@ -531,23 +712,23 @@ function createMediaUrlResolver(api) {
531
712
 
532
713
  // src/providers/ConversationsProvider.tsx
533
714
  import { createContext as createContext2, useContext as useContext2 } from "react";
534
- import { jsx as jsx8 } from "react/jsx-runtime";
715
+ import { jsx as jsx9 } from "react/jsx-runtime";
535
716
  var ConversationsContext = createContext2(null);
536
717
  function ConversationsProvider({
537
718
  api,
538
719
  sse,
539
720
  children
540
721
  }) {
541
- return /* @__PURE__ */ jsx8(ConversationsContext.Provider, { value: { api, sse }, children });
722
+ return /* @__PURE__ */ jsx9(ConversationsContext.Provider, { value: { api, sse }, children });
542
723
  }
543
724
  function useConversations() {
544
725
  return useContext2(ConversationsContext);
545
726
  }
546
727
 
547
728
  // src/MessageBubble.tsx
548
- import { useMemo, useState as useState4 } from "react";
549
- import { Check } from "lucide-react";
550
- import { Fragment, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
729
+ import { useMemo, useState as useState5 } from "react";
730
+ import { Check as Check2 } from "lucide-react";
731
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
551
732
  var BUBBLE_COLOR = {
552
733
  agent: "bg-[#d9fdd3] dark:bg-[#005c4b]",
553
734
  bot: "bg-[#d7f0ec] dark:bg-[#0a3d3a]",
@@ -564,15 +745,21 @@ function MessageBubble({
564
745
  onToggleSelect,
565
746
  onResolveMediaUrl,
566
747
  onInteractiveSelect,
748
+ onTranscribeAudio,
567
749
  className
568
750
  }) {
569
751
  const { bubble, selection } = useConversationLocales();
570
- const [lightboxSrc, setLightboxSrc] = useState4(null);
752
+ const [lightboxSrc, setLightboxSrc] = useState5(null);
571
753
  const context = useConversations();
572
754
  const resolveMediaUrl = useMemo(
573
755
  () => onResolveMediaUrl ?? (context?.api ? createMediaUrlResolver(context.api) : void 0),
574
756
  [onResolveMediaUrl, context?.api]
575
757
  );
758
+ const requestTranscription = useMemo(() => {
759
+ const transcribe = onTranscribeAudio ?? context?.api?.transcribeAudio?.bind(context.api);
760
+ if (!transcribe) return void 0;
761
+ return () => transcribe(message.id);
762
+ }, [onTranscribeAudio, context?.api, message.id]);
576
763
  const bubbleColor = BUBBLE_COLOR[message.sender] ?? BUBBLE_COLOR.customer;
577
764
  const hasError = message.status === "failed";
578
765
  const isMedia = MEDIA_TYPES.has(message.type);
@@ -581,7 +768,7 @@ function MessageBubble({
581
768
  const displayName = message.sender === "agent" && senderName ? senderName : bubble[message.sender] ?? message.sender;
582
769
  const tooltipText = message.status === "read" && message.readAt ? `${bubble.readAt}${formatDateTime(message.readAt)}` : message.status === "failed" ? bubble.windowExpired : void 0;
583
770
  const tailCornerClass = isFirstInGroup ? isMine ? "rounded-tr-md" : "rounded-tl-md" : "";
584
- const checkbox = /* @__PURE__ */ jsx9(
771
+ const checkbox = /* @__PURE__ */ jsx10(
585
772
  "button",
586
773
  {
587
774
  onClick: (e) => {
@@ -594,10 +781,10 @@ function MessageBubble({
594
781
  ${isSelected ? "bg-teal-600 border-teal-600" : "bg-white/80 dark:bg-black/40 border-black/20 dark:border-white/30"}
595
782
  ${isSelecting ? "opacity-100" : "opacity-0 group-hover:opacity-100"}
596
783
  `,
597
- children: isSelected && /* @__PURE__ */ jsx9(Check, { size: 12, className: "text-white", strokeWidth: 3 })
784
+ children: isSelected && /* @__PURE__ */ jsx10(Check2, { size: 12, className: "text-white", strokeWidth: 3 })
598
785
  }
599
786
  );
600
- return /* @__PURE__ */ jsxs6(
787
+ return /* @__PURE__ */ jsxs7(
601
788
  "div",
602
789
  {
603
790
  className: cn(
@@ -608,7 +795,7 @@ function MessageBubble({
608
795
  ),
609
796
  children: [
610
797
  isMine && checkbox,
611
- /* @__PURE__ */ jsxs6(
798
+ /* @__PURE__ */ jsxs7(
612
799
  "div",
613
800
  {
614
801
  onClick: isSelecting ? onToggleSelect : void 0,
@@ -621,48 +808,57 @@ function MessageBubble({
621
808
  relative
622
809
  `,
623
810
  children: [
624
- isMine && isFirstInGroup && (message.sender === "bot" || message.sender === "agent" && senderName) && /* @__PURE__ */ jsx9("div", { className: "text-xs font-semibold mb-0.5 text-teal-700 dark:text-teal-400", children: displayName }),
625
- message.moderation?.isOffensive && /* @__PURE__ */ jsxs6(
811
+ isMine && isFirstInGroup && (message.sender === "bot" || message.sender === "agent" && senderName) && /* @__PURE__ */ jsx10("div", { className: "text-xs font-semibold mb-0.5 text-teal-700 dark:text-teal-400", children: displayName }),
812
+ message.moderation?.isOffensive && /* @__PURE__ */ jsxs7(
626
813
  "div",
627
814
  {
628
815
  className: "mb-1 inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-800 dark:bg-amber-950/60 dark:text-amber-300",
629
816
  title: message.moderation.terms.length > 0 ? message.moderation.terms.join(", ") : void 0,
630
817
  children: [
631
- /* @__PURE__ */ jsx9("span", { "aria-hidden": true, children: "\u26A0\uFE0F" }),
632
- /* @__PURE__ */ jsx9("span", { children: bubble.moderationFlagged })
818
+ /* @__PURE__ */ jsx10("span", { "aria-hidden": true, children: "\u26A0\uFE0F" }),
819
+ /* @__PURE__ */ jsx10("span", { children: bubble.moderationFlagged })
633
820
  ]
634
821
  }
635
822
  ),
636
- isMedia ? /* @__PURE__ */ jsx9(MediaRenderer, { message, onLightbox: setLightboxSrc, onResolveUrl: resolveMediaUrl }) : isInteractive && message.payload ? (
823
+ isMedia ? /* @__PURE__ */ jsx10(
824
+ MediaRenderer,
825
+ {
826
+ message,
827
+ onLightbox: setLightboxSrc,
828
+ onResolveUrl: resolveMediaUrl,
829
+ ...requestTranscription ? { onTranscribeAudio: requestTranscription } : {}
830
+ }
831
+ ) : isInteractive && message.payload ? (
637
832
  // O texto da mensagem interativa mora dentro do payload (`body.text`), e `content` guarda
638
833
  // só uma cópia achatada para busca — renderizar `content` aqui duplicaria o corpo.
639
- /* @__PURE__ */ jsx9(InteractiveMessage, { payload: message.payload, onSelect: onInteractiveSelect })
640
- ) : /* @__PURE__ */ jsxs6(Fragment, { children: [
641
- isTemplate && /* @__PURE__ */ jsxs6("p", { className: "text-xs text-gray-500 dark:text-gray-400 flex items-center gap-1 mb-0.5", children: [
642
- /* @__PURE__ */ jsx9("span", { children: "\u{1F4E8}" }),
643
- /* @__PURE__ */ jsxs6("span", { className: "font-medium", children: [
834
+ /* @__PURE__ */ jsx10(InteractiveMessage, { payload: message.payload, onSelect: onInteractiveSelect })
835
+ ) : /* @__PURE__ */ jsxs7(Fragment2, { children: [
836
+ isTemplate && /* @__PURE__ */ jsxs7("p", { className: "text-xs text-gray-500 dark:text-gray-400 flex items-center gap-1 mb-0.5", children: [
837
+ /* @__PURE__ */ jsx10("span", { children: "\u{1F4E8}" }),
838
+ /* @__PURE__ */ jsxs7("span", { className: "font-medium", children: [
644
839
  bubble.templateLabel,
645
840
  message.templateName ? ` \u2014 ${message.templateName}` : ""
646
841
  ] })
647
842
  ] }),
648
- /* @__PURE__ */ jsx9("div", { className: "text-sm text-gray-900 dark:text-gray-100 whitespace-pre-wrap break-words leading-[19px]", children: parseWhatsAppFormatting(message.content ?? "") })
843
+ /* @__PURE__ */ jsx10("div", { className: "text-sm text-gray-900 dark:text-gray-100 whitespace-pre-wrap break-words leading-[19px]", children: parseWhatsAppFormatting(message.content ?? "") })
649
844
  ] }),
650
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-end gap-1 mt-0.5 select-none", children: [
651
- /* @__PURE__ */ jsx9("span", { className: "text-xs text-black/40 dark:text-white/40 font-medium", children: formatTimestamp(message.timestamp) }),
652
- isMine && message.status && /* @__PURE__ */ jsx9(StatusTicks, { status: message.status, title: tooltipText })
845
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-end gap-1 mt-0.5 select-none", children: [
846
+ /* @__PURE__ */ jsx10("span", { className: "text-xs text-black/40 dark:text-white/40 font-medium", children: formatTimestamp(message.timestamp) }),
847
+ isMine && message.status && /* @__PURE__ */ jsx10(StatusTicks, { status: message.status, title: tooltipText })
653
848
  ] })
654
849
  ]
655
850
  }
656
851
  ),
657
852
  !isMine && checkbox,
658
- lightboxSrc && /* @__PURE__ */ jsx9(Lightbox, { imageUrl: lightboxSrc, onClose: () => setLightboxSrc(null) })
853
+ lightboxSrc && /* @__PURE__ */ jsx10(Lightbox, { imageUrl: lightboxSrc, onClose: () => setLightboxSrc(null) })
659
854
  ]
660
855
  }
661
856
  );
662
857
  }
663
858
 
664
859
  // src/Wallpaper.tsx
665
- import { jsx as jsx10 } from "react/jsx-runtime";
860
+ import { forwardRef } from "react";
861
+ import { jsx as jsx11 } from "react/jsx-runtime";
666
862
  function doodlePattern(strokeColor, opacity) {
667
863
  const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'><g fill='none' stroke='${strokeColor}' stroke-width='1.2' opacity='${opacity}'><circle cx='15' cy='15' r='3'/><path d='M40 10 q5 8 0 16 q-5 -8 0 -16z'/><circle cx='70' cy='28' r='2'/><path d='M18 55 l6 6 m-6 0 l6 -6'/><circle cx='55' cy='68' r='2.5'/><path d='M85 58 q6 6 0 12 q-6 -6 0 -12z'/><circle cx='8' cy='85' r='2'/><path d='M65 90 l5 5 m-5 0 l5 -5'/></g></svg>`;
668
864
  return `url("data:image/svg+xml,${encodeURIComponent(svg)}")`;
@@ -679,17 +875,21 @@ var DARK_WALLPAPER = {
679
875
  backgroundRepeat: "repeat",
680
876
  backgroundSize: "100px 100px"
681
877
  };
682
- function ConversationWallpaper({ children, className, style }) {
683
- const isDark = useIsDarkTheme();
684
- return /* @__PURE__ */ jsx10(
685
- "div",
686
- {
687
- className: cn("cv-wallpaper", className),
688
- style: { ...isDark ? DARK_WALLPAPER : LIGHT_WALLPAPER, ...style },
689
- children
690
- }
691
- );
692
- }
878
+ var ConversationWallpaper = forwardRef(
879
+ function ConversationWallpaper2({ children, className, style, onScroll }, ref) {
880
+ const isDark = useIsDarkTheme();
881
+ return /* @__PURE__ */ jsx11(
882
+ "div",
883
+ {
884
+ ref,
885
+ onScroll,
886
+ className: cn("cv-wallpaper", className),
887
+ style: { ...isDark ? DARK_WALLPAPER : LIGHT_WALLPAPER, ...style },
888
+ children
889
+ }
890
+ );
891
+ }
892
+ );
693
893
 
694
894
  // src/emojiCatalog.ts
695
895
  var EMOJI_CATEGORIES = [
@@ -846,8 +1046,8 @@ function searchEmojis(query) {
846
1046
  }
847
1047
 
848
1048
  // src/EmojiPicker.tsx
849
- import { useState as useState5, useCallback, useMemo as useMemo2 } from "react";
850
- import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
1049
+ import { useState as useState6, useCallback as useCallback2, useMemo as useMemo2 } from "react";
1050
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
851
1051
  var DEFAULT_EMOJI_PICKER_LABELS = {
852
1052
  search: "Buscar emoji",
853
1053
  noResults: "Nenhum emoji encontrado"
@@ -855,9 +1055,9 @@ var DEFAULT_EMOJI_PICKER_LABELS = {
855
1055
  var EmojiPicker = ({ onSelect, labels, className = "" }) => {
856
1056
  const searchLabel = labels?.search ?? DEFAULT_EMOJI_PICKER_LABELS.search;
857
1057
  const noResultsLabel = labels?.noResults ?? DEFAULT_EMOJI_PICKER_LABELS.noResults;
858
- const [activeCategory, setActiveCategory] = useState5(0);
859
- const [query, setQuery] = useState5("");
860
- const handleSelect = useCallback(
1058
+ const [activeCategory, setActiveCategory] = useState6(0);
1059
+ const [query, setQuery] = useState6("");
1060
+ const handleSelect = useCallback2(
861
1061
  (emoji) => {
862
1062
  onSelect(emoji);
863
1063
  },
@@ -868,8 +1068,8 @@ var EmojiPicker = ({ onSelect, labels, className = "" }) => {
868
1068
  () => isSearching ? searchEmojis(query) : EMOJI_CATEGORIES[activeCategory].entries,
869
1069
  [isSearching, query, activeCategory]
870
1070
  );
871
- return /* @__PURE__ */ jsxs7("div", { className: `bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden ${className}`, children: [
872
- /* @__PURE__ */ jsx11("div", { className: "p-2 border-b border-gray-200", children: /* @__PURE__ */ jsx11(
1071
+ return /* @__PURE__ */ jsxs8("div", { className: `bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden ${className}`, children: [
1072
+ /* @__PURE__ */ jsx12("div", { className: "p-2 border-b border-gray-200", children: /* @__PURE__ */ jsx12(
873
1073
  "input",
874
1074
  {
875
1075
  type: "search",
@@ -880,7 +1080,7 @@ var EmojiPicker = ({ onSelect, labels, className = "" }) => {
880
1080
  className: "w-full rounded-md border border-gray-200 px-2 py-1.5 text-sm outline-none focus:border-blue-500"
881
1081
  }
882
1082
  ) }),
883
- isSearching ? null : /* @__PURE__ */ jsx11("div", { className: "flex border-b border-gray-200 overflow-x-auto", children: EMOJI_CATEGORIES.map((category, index) => /* @__PURE__ */ jsxs7(
1083
+ isSearching ? null : /* @__PURE__ */ jsx12("div", { className: "flex border-b border-gray-200 overflow-x-auto", children: EMOJI_CATEGORIES.map((category, index) => /* @__PURE__ */ jsxs8(
884
1084
  "button",
885
1085
  {
886
1086
  onClick: () => setActiveCategory(index),
@@ -893,7 +1093,7 @@ var EmojiPicker = ({ onSelect, labels, className = "" }) => {
893
1093
  },
894
1094
  category.name
895
1095
  )) }),
896
- visibleEntries.length === 0 ? /* @__PURE__ */ jsx11("p", { className: "px-3 py-6 text-center text-sm text-gray-500", children: noResultsLabel }) : /* @__PURE__ */ jsx11("div", { className: "grid grid-cols-10 gap-0.5 p-2 max-h-[240px] overflow-y-auto", children: visibleEntries.map((entry) => /* @__PURE__ */ jsx11(
1096
+ visibleEntries.length === 0 ? /* @__PURE__ */ jsx12("p", { className: "px-3 py-6 text-center text-sm text-gray-500", children: noResultsLabel }) : /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-10 gap-0.5 p-2 max-h-[240px] overflow-y-auto", children: visibleEntries.map((entry) => /* @__PURE__ */ jsx12(
897
1097
  "button",
898
1098
  {
899
1099
  onClick: () => handleSelect(entry.emoji),
@@ -907,9 +1107,167 @@ var EmojiPicker = ({ onSelect, labels, className = "" }) => {
907
1107
  ] });
908
1108
  };
909
1109
 
1110
+ // src/AudioRecorderButton.tsx
1111
+ import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef2, useState as useState7 } from "react";
1112
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1113
+ var DEFAULT_AUDIO_RECORDER_BUTTON_LABELS = {
1114
+ start: "Gravar \xE1udio",
1115
+ stop: "Parar grava\xE7\xE3o",
1116
+ unsupported: "Este navegador n\xE3o grava \xE1udio.",
1117
+ denied: "Sem permiss\xE3o para usar o microfone.",
1118
+ review: "Ou\xE7a antes de enviar",
1119
+ send: "Enviar \xE1udio",
1120
+ discard: "Descartar \xE1udio",
1121
+ empty: "Nada foi captado pelo microfone."
1122
+ };
1123
+ var DEFAULT_MAX_RECORDING_MILLISECONDS = 5 * 60 * 1e3;
1124
+ var RECORDING_FORMATS = [
1125
+ { mimeType: "audio/ogg;codecs=opus", uploadMimeType: "audio/ogg", extension: "ogg" },
1126
+ { mimeType: "audio/mp4", uploadMimeType: "audio/mp4", extension: "m4a" },
1127
+ { mimeType: "audio/webm", uploadMimeType: "audio/webm", extension: "webm" }
1128
+ ];
1129
+ function resolveRecordingFormat() {
1130
+ if (typeof MediaRecorder === "undefined") return void 0;
1131
+ if (typeof MediaRecorder.isTypeSupported !== "function") return RECORDING_FORMATS[0];
1132
+ return RECORDING_FORMATS.find((format) => MediaRecorder.isTypeSupported(format.mimeType));
1133
+ }
1134
+ function AudioRecorderButton({
1135
+ onRecorded,
1136
+ onFailure,
1137
+ onRecordingChange,
1138
+ reviewBeforeSend = true,
1139
+ maxDurationMilliseconds = DEFAULT_MAX_RECORDING_MILLISECONDS,
1140
+ labels,
1141
+ disabled
1142
+ }) {
1143
+ const labelOf = (key) => labels?.[key] ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS[key];
1144
+ const [isRecording, setIsRecording] = useState7(false);
1145
+ const [pending, setPending] = useState7(void 0);
1146
+ const recorderRef = useRef2(null);
1147
+ const autoStopRef = useRef2(void 0);
1148
+ const discard = useCallback3(() => {
1149
+ setPending((current) => {
1150
+ if (current) URL.revokeObjectURL(current.objectURL);
1151
+ return void 0;
1152
+ });
1153
+ }, []);
1154
+ useEffect2(() => discard, [discard]);
1155
+ const confirm = useCallback3(() => {
1156
+ if (!pending) return;
1157
+ void onRecorded(pending.file);
1158
+ discard();
1159
+ }, [discard, onRecorded, pending]);
1160
+ const stop = useCallback3(() => {
1161
+ recorderRef.current?.stop();
1162
+ }, []);
1163
+ const start = useCallback3(async () => {
1164
+ const format = resolveRecordingFormat();
1165
+ if (!format || !navigator.mediaDevices?.getUserMedia) {
1166
+ onFailure?.(labels?.unsupported ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS.unsupported);
1167
+ return;
1168
+ }
1169
+ try {
1170
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
1171
+ const recorder = new MediaRecorder(stream, { mimeType: format.mimeType });
1172
+ const chunks = [];
1173
+ recorder.addEventListener("dataavailable", (event) => {
1174
+ if (event.data.size > 0) chunks.push(event.data);
1175
+ });
1176
+ recorder.addEventListener("stop", () => {
1177
+ stream.getTracks().forEach((track) => track.stop());
1178
+ clearTimeout(autoStopRef.current);
1179
+ setIsRecording(false);
1180
+ onRecordingChange?.(false);
1181
+ recorderRef.current = null;
1182
+ const blob = new Blob(chunks, { type: format.uploadMimeType });
1183
+ const file = new File([blob], `audio-${Date.now()}.${format.extension}`, {
1184
+ type: format.uploadMimeType
1185
+ });
1186
+ if (blob.size === 0) {
1187
+ onFailure?.(labelOf("empty"));
1188
+ return;
1189
+ }
1190
+ if (!reviewBeforeSend) {
1191
+ void onRecorded(file);
1192
+ return;
1193
+ }
1194
+ setPending({ file, objectURL: URL.createObjectURL(blob) });
1195
+ });
1196
+ recorderRef.current = recorder;
1197
+ recorder.start();
1198
+ autoStopRef.current = setTimeout(() => recorder.stop(), maxDurationMilliseconds);
1199
+ setIsRecording(true);
1200
+ onRecordingChange?.(true);
1201
+ } catch {
1202
+ onFailure?.(labels?.denied ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS.denied);
1203
+ }
1204
+ }, [maxDurationMilliseconds, onFailure, onRecorded, onRecordingChange, reviewBeforeSend]);
1205
+ const toggleLabel = isRecording ? labelOf("stop") : labelOf("start");
1206
+ return (
1207
+ /* O painel de revisão flutua sobre o botão em vez de ocupar espaço na barra: o microfone mora
1208
+ na caixa do botão de enviar, e empurrar o composer para cima a cada gravação faria a
1209
+ conversa saltar. */
1210
+ /* @__PURE__ */ jsxs9("div", { className: "relative flex-shrink-0", children: [
1211
+ pending && /* @__PURE__ */ jsxs9(
1212
+ "div",
1213
+ {
1214
+ role: "group",
1215
+ "aria-label": labelOf("review"),
1216
+ className: "absolute bottom-full right-0 z-20 mb-2 flex w-[calc(100vw-2rem)] max-w-[20rem] flex-wrap items-center justify-end gap-2 rounded-xl border border-gray-200 bg-white p-2 shadow-lg dark:border-gray-700 dark:bg-gray-800",
1217
+ children: [
1218
+ /* @__PURE__ */ jsx13("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx13(AudioPlayer, { src: pending.objectURL }) }),
1219
+ /* @__PURE__ */ jsx13(
1220
+ "button",
1221
+ {
1222
+ type: "button",
1223
+ onClick: discard,
1224
+ title: labelOf("discard"),
1225
+ "aria-label": labelOf("discard"),
1226
+ className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full text-gray-500 transition-colors hover:bg-gray-100 hover:text-red-500 dark:hover:bg-gray-700",
1227
+ children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
1228
+ /* @__PURE__ */ jsx13("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1229
+ /* @__PURE__ */ jsx13("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1230
+ ] })
1231
+ }
1232
+ ),
1233
+ /* @__PURE__ */ jsx13(
1234
+ "button",
1235
+ {
1236
+ type: "button",
1237
+ onClick: confirm,
1238
+ title: labelOf("send"),
1239
+ "aria-label": labelOf("send"),
1240
+ className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-emerald-500 text-white transition-colors hover:bg-emerald-600",
1241
+ children: /* @__PURE__ */ jsx13("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx13("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) })
1242
+ }
1243
+ )
1244
+ ]
1245
+ }
1246
+ ),
1247
+ /* @__PURE__ */ jsx13(
1248
+ "button",
1249
+ {
1250
+ type: "button",
1251
+ disabled: disabled || pending !== void 0,
1252
+ onClick: () => isRecording ? stop() : void start(),
1253
+ title: toggleLabel,
1254
+ "aria-label": toggleLabel,
1255
+ "aria-pressed": isRecording,
1256
+ className: `flex h-10 w-10 items-center justify-center rounded-full transition-colors disabled:opacity-50 ${isRecording ? "animate-pulse bg-red-500 text-white ring-4 ring-red-500/30 hover:bg-red-600" : "text-gray-500 hover:bg-gray-200 dark:hover:bg-gray-700"}`,
1257
+ children: isRecording ? /* @__PURE__ */ jsx13("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx13("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) }) : /* @__PURE__ */ jsxs9("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
1258
+ /* @__PURE__ */ jsx13("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z" }),
1259
+ /* @__PURE__ */ jsx13("path", { d: "M19 11a7 7 0 0 1-14 0" }),
1260
+ /* @__PURE__ */ jsx13("line", { x1: "12", y1: "18", x2: "12", y2: "22" })
1261
+ ] })
1262
+ }
1263
+ )
1264
+ ] })
1265
+ );
1266
+ }
1267
+
910
1268
  // src/MessageComposer.tsx
911
- import { useState as useState6, useRef as useRef2, useCallback as useCallback2 } from "react";
912
- import { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1269
+ import { useState as useState8, useRef as useRef3, useCallback as useCallback4 } from "react";
1270
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
913
1271
  function applyQuickReplyVariables(template, variables = {}) {
914
1272
  return template.replace(/\{\{\s*([\w.]+)\s*\}\}/g, (_, chave) => variables[chave] ?? "");
915
1273
  }
@@ -951,14 +1309,14 @@ var MessageComposer = ({
951
1309
  const emojiLabel = labels?.emoji ?? DEFAULT_MESSAGE_COMPOSER_LABELS.emoji;
952
1310
  const attachLabel = labels?.attach ?? DEFAULT_MESSAGE_COMPOSER_LABELS.attach;
953
1311
  const sendLabel = labels?.send ?? DEFAULT_MESSAGE_COMPOSER_LABELS.send;
954
- const [internalText, setInternalText] = useState6("");
955
- const [showEmoji, setShowEmoji] = useState6(false);
956
- const [attachments, setAttachments] = useState6([]);
957
- const textareaRef = useRef2(null);
958
- const fileInputRef = useRef2(null);
1312
+ const [internalText, setInternalText] = useState8("");
1313
+ const [showEmoji, setShowEmoji] = useState8(false);
1314
+ const [attachments, setAttachments] = useState8([]);
1315
+ const textareaRef = useRef3(null);
1316
+ const fileInputRef = useRef3(null);
959
1317
  const isControlled = externalValue !== void 0;
960
1318
  const text = isControlled ? externalValue : internalText;
961
- const setText = useCallback2((newText) => {
1319
+ const setText = useCallback4((newText) => {
962
1320
  if (isControlled) {
963
1321
  externalOnChange?.(newText);
964
1322
  } else {
@@ -967,7 +1325,7 @@ var MessageComposer = ({
967
1325
  }, [isControlled, externalOnChange]);
968
1326
  const showEmojiButton = features?.emoji !== false;
969
1327
  const showAttachButton = features?.documents !== false;
970
- const sendMessage = useCallback2(() => {
1328
+ const sendMessage = useCallback4(() => {
971
1329
  const trimmed = text.trim();
972
1330
  if (!trimmed && attachments.length === 0) return;
973
1331
  if (trimmed) onSend(trimmed);
@@ -980,19 +1338,19 @@ var MessageComposer = ({
980
1338
  setShowEmoji(false);
981
1339
  if (textareaRef.current) textareaRef.current.style.height = "auto";
982
1340
  }, [text, attachments, onSend, onAttach, isControlled]);
983
- const handleKeyDown = useCallback2((e) => {
1341
+ const handleKeyDown = useCallback4((e) => {
984
1342
  if (e.key === "Enter" && !e.shiftKey) {
985
1343
  e.preventDefault();
986
1344
  if (!disabled) sendMessage();
987
1345
  }
988
1346
  }, [sendMessage, disabled]);
989
- const handleInput = useCallback2(() => {
1347
+ const handleInput = useCallback4(() => {
990
1348
  const ta = textareaRef.current;
991
1349
  if (!ta) return;
992
1350
  ta.style.height = "auto";
993
1351
  ta.style.height = `${Math.min(ta.scrollHeight, 100)}px`;
994
1352
  }, []);
995
- const handleEmojiSelect = useCallback2((emoji) => {
1353
+ const handleEmojiSelect = useCallback4((emoji) => {
996
1354
  const ta = textareaRef.current;
997
1355
  if (!ta) {
998
1356
  setText(text + emoji);
@@ -1008,7 +1366,7 @@ var MessageComposer = ({
1008
1366
  handleInput();
1009
1367
  });
1010
1368
  }, [text, setText, handleInput]);
1011
- const handleFileChange = useCallback2((e) => {
1369
+ const handleFileChange = useCallback4((e) => {
1012
1370
  const files = e.target.files;
1013
1371
  if (!files) return;
1014
1372
  const previews = [];
@@ -1019,7 +1377,7 @@ var MessageComposer = ({
1019
1377
  setAttachments((prev) => [...prev, ...previews]);
1020
1378
  if (fileInputRef.current) fileInputRef.current.value = "";
1021
1379
  }, []);
1022
- const removeAttachment = useCallback2((index) => {
1380
+ const removeAttachment = useCallback4((index) => {
1023
1381
  setAttachments((prev) => {
1024
1382
  const next = [...prev];
1025
1383
  if (next[index].previewUrl) URL.revokeObjectURL(next[index].previewUrl);
@@ -1027,7 +1385,7 @@ var MessageComposer = ({
1027
1385
  return next;
1028
1386
  });
1029
1387
  }, []);
1030
- const insertFormatting = useCallback2((marker) => {
1388
+ const insertFormatting = useCallback4((marker) => {
1031
1389
  const ta = textareaRef.current;
1032
1390
  if (!ta) return;
1033
1391
  const start = ta.selectionStart;
@@ -1041,21 +1399,22 @@ var MessageComposer = ({
1041
1399
  });
1042
1400
  }
1043
1401
  }, [text, setText]);
1402
+ const effectiveIdleAction = idleAction ?? (onAttach ? /* @__PURE__ */ jsx14(AudioRecorderButton, { onRecorded: (file) => onAttach(file) }) : void 0);
1044
1403
  const canSend = text.trim().length > 0 || attachments.length > 0;
1045
1404
  const remaining = maxLength ? maxLength - text.length : null;
1046
1405
  return (
1047
1406
  /* A barra é a superfície (cinza, largura cheia, sem raio) e o campo dentro é que arredonda —
1048
1407
  ordem do WhatsApp. Invertido, o pill arredondado ia até a borda da tela e os cantos
1049
1408
  descobriam o fundo branco da página, que lia como defeito. */
1050
- /* @__PURE__ */ jsxs8("div", { className: cn("bg-[#f0f2f5] px-2 py-2", className), children: [
1051
- quickReplies && quickReplies.length > 0 && /* @__PURE__ */ jsx12(
1409
+ /* @__PURE__ */ jsxs10("div", { className: cn("bg-[#f0f2f5] px-2 py-2", className), children: [
1410
+ quickReplies && quickReplies.length > 0 && /* @__PURE__ */ jsx14(
1052
1411
  "div",
1053
1412
  {
1054
1413
  className: cn(
1055
1414
  "mb-2 flex flex-nowrap gap-1 overflow-x-auto px-1 sm:flex-wrap sm:overflow-x-visible [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
1056
1415
  classNames?.quickReplies
1057
1416
  ),
1058
- children: quickReplies.map((quickReply) => /* @__PURE__ */ jsx12(
1417
+ children: quickReplies.map((quickReply) => /* @__PURE__ */ jsx14(
1059
1418
  "button",
1060
1419
  {
1061
1420
  type: "button",
@@ -1073,24 +1432,24 @@ var MessageComposer = ({
1073
1432
  ))
1074
1433
  }
1075
1434
  ),
1076
- attachments.length > 0 && /* @__PURE__ */ jsx12("div", { className: "flex gap-2 px-1 pb-2 overflow-x-auto", children: attachments.map((a, i) => /* @__PURE__ */ jsxs8("div", { className: "relative flex-shrink-0", children: [
1077
- a.previewUrl ? /* @__PURE__ */ jsx12("img", { src: a.previewUrl, alt: "", className: "w-16 h-16 object-cover rounded-lg border border-gray-200" }) : /* @__PURE__ */ jsx12("div", { className: "w-16 h-16 bg-gray-100 rounded-lg border border-gray-200 flex items-center justify-center", children: /* @__PURE__ */ jsxs8("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#9ca3af", strokeWidth: "1.5", children: [
1078
- /* @__PURE__ */ jsx12("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1079
- /* @__PURE__ */ jsx12("polyline", { points: "14 2 14 8 20 8" })
1435
+ attachments.length > 0 && /* @__PURE__ */ jsx14("div", { className: "flex gap-2 px-1 pb-2 overflow-x-auto", children: attachments.map((a, i) => /* @__PURE__ */ jsxs10("div", { className: "relative flex-shrink-0", children: [
1436
+ a.previewUrl ? /* @__PURE__ */ jsx14("img", { src: a.previewUrl, alt: "", className: "w-16 h-16 object-cover rounded-lg border border-gray-200" }) : /* @__PURE__ */ jsx14("div", { className: "w-16 h-16 bg-gray-100 rounded-lg border border-gray-200 flex items-center justify-center", children: /* @__PURE__ */ jsxs10("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#9ca3af", strokeWidth: "1.5", children: [
1437
+ /* @__PURE__ */ jsx14("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1438
+ /* @__PURE__ */ jsx14("polyline", { points: "14 2 14 8 20 8" })
1080
1439
  ] }) }),
1081
- /* @__PURE__ */ jsx12("button", { onClick: () => removeAttachment(i), className: "absolute -top-2 -right-2 w-5 h-5 bg-gray-600 text-white rounded-full flex items-center justify-center hover:bg-gray-800 text-xs", children: "\u2715" })
1440
+ /* @__PURE__ */ jsx14("button", { onClick: () => removeAttachment(i), className: "absolute -top-2 -right-2 w-5 h-5 bg-gray-600 text-white rounded-full flex items-center justify-center hover:bg-gray-800 text-xs", children: "\u2715" })
1082
1441
  ] }, i)) }),
1083
- /* @__PURE__ */ jsxs8("div", { className: cn("flex items-end gap-1.5 rounded-xl bg-white px-3 py-2", classNames?.field), children: [
1084
- showEmojiButton && /* @__PURE__ */ jsxs8("div", { className: "relative flex-shrink-0", children: [
1085
- /* @__PURE__ */ jsx12("button", { onClick: () => setShowEmoji((v) => !v), className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 transition-colors", "aria-label": emojiLabel, children: /* @__PURE__ */ jsxs8("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1086
- /* @__PURE__ */ jsx12("circle", { cx: "12", cy: "12", r: "10" }),
1087
- /* @__PURE__ */ jsx12("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }),
1088
- /* @__PURE__ */ jsx12("circle", { cx: "9", cy: "9", r: "0.5", fill: "currentColor" }),
1089
- /* @__PURE__ */ jsx12("circle", { cx: "15", cy: "9", r: "0.5", fill: "currentColor" })
1442
+ /* @__PURE__ */ jsxs10("div", { className: cn("flex items-end gap-1.5 rounded-xl bg-white px-3 py-2", classNames?.field), children: [
1443
+ showEmojiButton && /* @__PURE__ */ jsxs10("div", { className: "relative flex-shrink-0", children: [
1444
+ /* @__PURE__ */ jsx14("button", { onClick: () => setShowEmoji((v) => !v), className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 transition-colors", "aria-label": emojiLabel, children: /* @__PURE__ */ jsxs10("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1445
+ /* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "10" }),
1446
+ /* @__PURE__ */ jsx14("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }),
1447
+ /* @__PURE__ */ jsx14("circle", { cx: "9", cy: "9", r: "0.5", fill: "currentColor" }),
1448
+ /* @__PURE__ */ jsx14("circle", { cx: "15", cy: "9", r: "0.5", fill: "currentColor" })
1090
1449
  ] }) }),
1091
- showEmoji && /* @__PURE__ */ jsx12("div", { className: "absolute bottom-full left-0 mb-2 z-10", children: /* @__PURE__ */ jsx12(EmojiPicker, { onSelect: handleEmojiSelect }) })
1450
+ showEmoji && /* @__PURE__ */ jsx14("div", { className: "absolute bottom-full left-0 mb-2 z-10", children: /* @__PURE__ */ jsx14(EmojiPicker, { onSelect: handleEmojiSelect }) })
1092
1451
  ] }),
1093
- /* @__PURE__ */ jsx12(
1452
+ /* @__PURE__ */ jsx14(
1094
1453
  "textarea",
1095
1454
  {
1096
1455
  ref: textareaRef,
@@ -1107,189 +1466,31 @@ var MessageComposer = ({
1107
1466
  style: { fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" }
1108
1467
  }
1109
1468
  ),
1110
- showAttachButton && /* @__PURE__ */ jsxs8(Fragment2, { children: [
1111
- /* @__PURE__ */ jsx12("input", { ref: fileInputRef, type: "file", multiple: true, accept: acceptedFileTypes, onChange: handleFileChange, className: "hidden" }),
1112
- /* @__PURE__ */ jsx12("button", { onClick: () => fileInputRef.current?.click(), className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 flex-shrink-0 transition-colors", "aria-label": attachLabel, children: /* @__PURE__ */ jsx12("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx12("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })
1469
+ showAttachButton && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1470
+ /* @__PURE__ */ jsx14("input", { ref: fileInputRef, type: "file", multiple: true, accept: acceptedFileTypes, onChange: handleFileChange, className: "hidden" }),
1471
+ /* @__PURE__ */ jsx14("button", { onClick: () => fileInputRef.current?.click(), className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 flex-shrink-0 transition-colors", "aria-label": attachLabel, children: /* @__PURE__ */ jsx14("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx14("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })
1113
1472
  ] }),
1114
- !canSend && idleAction ? /* @__PURE__ */ jsx12("div", { className: "flex-shrink-0", children: idleAction }) : /* @__PURE__ */ jsx12(
1473
+ !canSend && effectiveIdleAction ? /* @__PURE__ */ jsx14("div", { className: "flex-shrink-0", children: effectiveIdleAction }) : /* @__PURE__ */ jsx14(
1115
1474
  "button",
1116
1475
  {
1117
1476
  onClick: sendMessage,
1118
1477
  disabled: !canSend || disabled,
1119
1478
  className: `w-10 h-10 flex items-center justify-center rounded-full flex-shrink-0 transition-all ${canSend && !disabled ? "bg-[#00a884] text-white hover:bg-[#06cf9c] shadow-sm" : "bg-gray-200 text-gray-400 cursor-not-allowed"}`,
1120
1479
  "aria-label": sendLabel,
1121
- children: /* @__PURE__ */ jsx12("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx12("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) })
1480
+ children: /* @__PURE__ */ jsx14("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx14("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) })
1122
1481
  }
1123
1482
  )
1124
1483
  ] }),
1125
- remaining !== null && /* @__PURE__ */ jsx12("div", { className: "flex justify-end mt-1 pr-1", children: /* @__PURE__ */ jsx12("span", { className: `text-xs ${remaining < 20 ? "text-red-500" : "text-gray-400"}`, children: remaining }) })
1484
+ remaining !== null && /* @__PURE__ */ jsx14("div", { className: "flex justify-end mt-1 pr-1", children: /* @__PURE__ */ jsx14("span", { className: `text-xs ${remaining < 20 ? "text-red-500" : "text-gray-400"}`, children: remaining }) })
1126
1485
  ] })
1127
1486
  );
1128
1487
  };
1129
1488
 
1130
- // src/AudioRecorderButton.tsx
1131
- import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef3, useState as useState7 } from "react";
1132
- import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1133
- var DEFAULT_AUDIO_RECORDER_BUTTON_LABELS = {
1134
- start: "Gravar \xE1udio",
1135
- stop: "Parar grava\xE7\xE3o",
1136
- unsupported: "Este navegador n\xE3o grava \xE1udio.",
1137
- denied: "Sem permiss\xE3o para usar o microfone.",
1138
- review: "Ou\xE7a antes de enviar",
1139
- send: "Enviar \xE1udio",
1140
- discard: "Descartar \xE1udio",
1141
- empty: "Nada foi captado pelo microfone."
1142
- };
1143
- var DEFAULT_MAX_RECORDING_MILLISECONDS = 5 * 60 * 1e3;
1144
- var RECORDING_FORMATS = [
1145
- { mimeType: "audio/ogg;codecs=opus", uploadMimeType: "audio/ogg", extension: "ogg" },
1146
- { mimeType: "audio/mp4", uploadMimeType: "audio/mp4", extension: "m4a" },
1147
- { mimeType: "audio/webm", uploadMimeType: "audio/webm", extension: "webm" }
1148
- ];
1149
- function resolveRecordingFormat() {
1150
- if (typeof MediaRecorder === "undefined") return void 0;
1151
- if (typeof MediaRecorder.isTypeSupported !== "function") return RECORDING_FORMATS[0];
1152
- return RECORDING_FORMATS.find((format) => MediaRecorder.isTypeSupported(format.mimeType));
1153
- }
1154
- function AudioRecorderButton({
1155
- onRecorded,
1156
- onFailure,
1157
- onRecordingChange,
1158
- reviewBeforeSend = true,
1159
- maxDurationMilliseconds = DEFAULT_MAX_RECORDING_MILLISECONDS,
1160
- labels,
1161
- disabled
1162
- }) {
1163
- const labelOf = (key) => labels?.[key] ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS[key];
1164
- const [isRecording, setIsRecording] = useState7(false);
1165
- const [pending, setPending] = useState7(void 0);
1166
- const recorderRef = useRef3(null);
1167
- const autoStopRef = useRef3(void 0);
1168
- const discard = useCallback3(() => {
1169
- setPending((current) => {
1170
- if (current) URL.revokeObjectURL(current.objectURL);
1171
- return void 0;
1172
- });
1173
- }, []);
1174
- useEffect2(() => discard, [discard]);
1175
- const confirm = useCallback3(() => {
1176
- if (!pending) return;
1177
- void onRecorded(pending.file);
1178
- discard();
1179
- }, [discard, onRecorded, pending]);
1180
- const stop = useCallback3(() => {
1181
- recorderRef.current?.stop();
1182
- }, []);
1183
- const start = useCallback3(async () => {
1184
- const format = resolveRecordingFormat();
1185
- if (!format || !navigator.mediaDevices?.getUserMedia) {
1186
- onFailure?.(labels?.unsupported ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS.unsupported);
1187
- return;
1188
- }
1189
- try {
1190
- const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
1191
- const recorder = new MediaRecorder(stream, { mimeType: format.mimeType });
1192
- const chunks = [];
1193
- recorder.addEventListener("dataavailable", (event) => {
1194
- if (event.data.size > 0) chunks.push(event.data);
1195
- });
1196
- recorder.addEventListener("stop", () => {
1197
- stream.getTracks().forEach((track) => track.stop());
1198
- clearTimeout(autoStopRef.current);
1199
- setIsRecording(false);
1200
- onRecordingChange?.(false);
1201
- recorderRef.current = null;
1202
- const blob = new Blob(chunks, { type: format.uploadMimeType });
1203
- const file = new File([blob], `audio-${Date.now()}.${format.extension}`, {
1204
- type: format.uploadMimeType
1205
- });
1206
- if (blob.size === 0) {
1207
- onFailure?.(labelOf("empty"));
1208
- return;
1209
- }
1210
- if (!reviewBeforeSend) {
1211
- void onRecorded(file);
1212
- return;
1213
- }
1214
- setPending({ file, objectURL: URL.createObjectURL(blob) });
1215
- });
1216
- recorderRef.current = recorder;
1217
- recorder.start();
1218
- autoStopRef.current = setTimeout(() => recorder.stop(), maxDurationMilliseconds);
1219
- setIsRecording(true);
1220
- onRecordingChange?.(true);
1221
- } catch {
1222
- onFailure?.(labels?.denied ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS.denied);
1223
- }
1224
- }, [maxDurationMilliseconds, onFailure, onRecorded, onRecordingChange, reviewBeforeSend]);
1225
- const toggleLabel = isRecording ? labelOf("stop") : labelOf("start");
1226
- return (
1227
- /* O painel de revisão flutua sobre o botão em vez de ocupar espaço na barra: o microfone mora
1228
- na caixa do botão de enviar, e empurrar o composer para cima a cada gravação faria a
1229
- conversa saltar. */
1230
- /* @__PURE__ */ jsxs9("div", { className: "relative flex-shrink-0", children: [
1231
- pending && /* @__PURE__ */ jsxs9(
1232
- "div",
1233
- {
1234
- role: "group",
1235
- "aria-label": labelOf("review"),
1236
- className: "absolute bottom-full right-0 z-20 mb-2 flex w-[calc(100vw-2rem)] max-w-[20rem] flex-wrap items-center justify-end gap-2 rounded-xl border border-gray-200 bg-white p-2 shadow-lg dark:border-gray-700 dark:bg-gray-800",
1237
- children: [
1238
- /* @__PURE__ */ jsx13("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx13(AudioPlayer, { src: pending.objectURL }) }),
1239
- /* @__PURE__ */ jsx13(
1240
- "button",
1241
- {
1242
- type: "button",
1243
- onClick: discard,
1244
- title: labelOf("discard"),
1245
- "aria-label": labelOf("discard"),
1246
- className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full text-gray-500 transition-colors hover:bg-gray-100 hover:text-red-500 dark:hover:bg-gray-700",
1247
- children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
1248
- /* @__PURE__ */ jsx13("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1249
- /* @__PURE__ */ jsx13("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1250
- ] })
1251
- }
1252
- ),
1253
- /* @__PURE__ */ jsx13(
1254
- "button",
1255
- {
1256
- type: "button",
1257
- onClick: confirm,
1258
- title: labelOf("send"),
1259
- "aria-label": labelOf("send"),
1260
- className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-emerald-500 text-white transition-colors hover:bg-emerald-600",
1261
- children: /* @__PURE__ */ jsx13("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx13("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) })
1262
- }
1263
- )
1264
- ]
1265
- }
1266
- ),
1267
- /* @__PURE__ */ jsx13(
1268
- "button",
1269
- {
1270
- type: "button",
1271
- disabled: disabled || pending !== void 0,
1272
- onClick: () => isRecording ? stop() : void start(),
1273
- title: toggleLabel,
1274
- "aria-label": toggleLabel,
1275
- "aria-pressed": isRecording,
1276
- className: `flex h-10 w-10 items-center justify-center rounded-full transition-colors disabled:opacity-50 ${isRecording ? "animate-pulse bg-red-500 text-white ring-4 ring-red-500/30 hover:bg-red-600" : "text-gray-500 hover:bg-gray-200 dark:hover:bg-gray-700"}`,
1277
- children: isRecording ? /* @__PURE__ */ jsx13("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx13("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) }) : /* @__PURE__ */ jsxs9("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
1278
- /* @__PURE__ */ jsx13("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z" }),
1279
- /* @__PURE__ */ jsx13("path", { d: "M19 11a7 7 0 0 1-14 0" }),
1280
- /* @__PURE__ */ jsx13("line", { x1: "12", y1: "18", x2: "12", y2: "22" })
1281
- ] })
1282
- }
1283
- )
1284
- ] })
1285
- );
1286
- }
1287
-
1288
1489
  // src/DateDivider.tsx
1289
- import { jsx as jsx14 } from "react/jsx-runtime";
1490
+ import { jsx as jsx15 } from "react/jsx-runtime";
1290
1491
  function DateDivider({ iso, className, classNames }) {
1291
1492
  const { dateDivider } = useConversationLocales();
1292
- return /* @__PURE__ */ jsx14("div", { className: cn("flex justify-center sticky top-0 z-10 my-2 pointer-events-none", classNames?.root, className), children: /* @__PURE__ */ jsx14(
1493
+ return /* @__PURE__ */ jsx15("div", { className: cn("flex justify-center sticky top-0 z-10 my-2 pointer-events-none", classNames?.root, className), children: /* @__PURE__ */ jsx15(
1293
1494
  "span",
1294
1495
  {
1295
1496
  className: cn(
@@ -1356,13 +1557,13 @@ function phoneInitials(number) {
1356
1557
  }
1357
1558
 
1358
1559
  // src/hooks/useAsyncResource.ts
1359
- import { useCallback as useCallback4, useEffect as useEffect3, useRef as useRef4, useState as useState8 } from "react";
1560
+ import { useCallback as useCallback5, useEffect as useEffect3, useRef as useRef4, useState as useState9 } from "react";
1360
1561
  function useAsyncResource(fetcher, deps) {
1361
- const [data, setData] = useState8(void 0);
1362
- const [loading, setLoading] = useState8(false);
1363
- const [error, setError] = useState8(void 0);
1562
+ const [data, setData] = useState9(void 0);
1563
+ const [loading, setLoading] = useState9(false);
1564
+ const [error, setError] = useState9(void 0);
1364
1565
  const requestIdRef = useRef4(0);
1365
- const load = useCallback4(async () => {
1566
+ const load = useCallback5(async () => {
1366
1567
  const requestId = ++requestIdRef.current;
1367
1568
  setLoading(true);
1368
1569
  setError(void 0);
@@ -1410,9 +1611,9 @@ function useConversationDocuments(conversationId, params) {
1410
1611
  }
1411
1612
 
1412
1613
  // src/ConversationDocumentsPanel.tsx
1413
- import { useState as useState9 } from "react";
1614
+ import { useState as useState10 } from "react";
1414
1615
  import { ArrowUpDown, Bot, Download, Eye, Users } from "lucide-react";
1415
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
1616
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
1416
1617
  var DOCUMENT_SOURCE_FILTER = {
1417
1618
  ALL: "all",
1418
1619
  CUSTOMER: "customer",
@@ -1452,12 +1653,12 @@ function ConversationDocumentsPanel({
1452
1653
  }) {
1453
1654
  const labels = { ...DEFAULT_CONVERSATION_DOCUMENTS_LABELS, ...labelsOverride };
1454
1655
  const context = useConversations();
1455
- const [search, setSearch] = useState9("");
1456
- const [sourceFilter, setSourceFilter] = useState9(DOCUMENT_SOURCE_FILTER.ALL);
1457
- const [sortDirection, setSortDirection] = useState9("desc");
1458
- const [page, setPage] = useState9(1);
1459
- const [selectedIds, setSelectedIds] = useState9([]);
1460
- const [archiveError, setArchiveError] = useState9(false);
1656
+ const [search, setSearch] = useState10("");
1657
+ const [sourceFilter, setSourceFilter] = useState10(DOCUMENT_SOURCE_FILTER.ALL);
1658
+ const [sortDirection, setSortDirection] = useState10("desc");
1659
+ const [page, setPage] = useState10(1);
1660
+ const [selectedIds, setSelectedIds] = useState10([]);
1661
+ const [archiveError, setArchiveError] = useState10(false);
1461
1662
  const hasFilters = search !== "" || sourceFilter !== DOCUMENT_SOURCE_FILTER.ALL || sortDirection !== "desc";
1462
1663
  const { documents, total, loading, error } = useConversationDocuments(open ? conversationId : void 0, {
1463
1664
  search,
@@ -1508,10 +1709,10 @@ function ConversationDocumentsPanel({
1508
1709
  }
1509
1710
  }
1510
1711
  if (!open) return null;
1511
- return /* @__PURE__ */ jsx15("div", { className: cn("border-b", classNames?.root, className), children: /* @__PURE__ */ jsxs10("section", { className: cn("px-4 py-3", classNames?.body), children: [
1512
- /* @__PURE__ */ jsx15("p", { className: cn("mb-2 text-sm font-medium", classNames?.title), children: labels.title }),
1513
- /* @__PURE__ */ jsxs10("div", { className: cn("mb-2 flex flex-wrap items-center gap-2 border-b pb-2", classNames?.filters), children: [
1514
- /* @__PURE__ */ jsx15(
1712
+ return /* @__PURE__ */ jsx16("div", { className: cn("border-b", classNames?.root, className), children: /* @__PURE__ */ jsxs11("section", { className: cn("px-4 py-3", classNames?.body), children: [
1713
+ /* @__PURE__ */ jsx16("p", { className: cn("mb-2 text-sm font-medium", classNames?.title), children: labels.title }),
1714
+ /* @__PURE__ */ jsxs11("div", { className: cn("mb-2 flex flex-wrap items-center gap-2 border-b pb-2", classNames?.filters), children: [
1715
+ /* @__PURE__ */ jsx16(
1515
1716
  "input",
1516
1717
  {
1517
1718
  type: "search",
@@ -1522,7 +1723,7 @@ function ConversationDocumentsPanel({
1522
1723
  className: cn("w-full rounded-md border px-3 py-2 text-sm sm:w-52", classNames?.search)
1523
1724
  }
1524
1725
  ),
1525
- /* @__PURE__ */ jsxs10(
1726
+ /* @__PURE__ */ jsxs11(
1526
1727
  "select",
1527
1728
  {
1528
1729
  value: sourceFilter,
@@ -1530,25 +1731,25 @@ function ConversationDocumentsPanel({
1530
1731
  "aria-label": labels.sourceFilterAll,
1531
1732
  className: cn("w-full rounded-md border px-2 py-2 text-sm sm:w-36", classNames?.sourceSelect),
1532
1733
  children: [
1533
- /* @__PURE__ */ jsx15("option", { value: DOCUMENT_SOURCE_FILTER.ALL, children: labels.sourceFilterAll }),
1534
- /* @__PURE__ */ jsx15("option", { value: DOCUMENT_SOURCE_FILTER.CUSTOMER, children: labels.sourceFilterCustomer }),
1535
- /* @__PURE__ */ jsx15("option", { value: DOCUMENT_SOURCE_FILTER.TEAM, children: labels.sourceFilterTeam })
1734
+ /* @__PURE__ */ jsx16("option", { value: DOCUMENT_SOURCE_FILTER.ALL, children: labels.sourceFilterAll }),
1735
+ /* @__PURE__ */ jsx16("option", { value: DOCUMENT_SOURCE_FILTER.CUSTOMER, children: labels.sourceFilterCustomer }),
1736
+ /* @__PURE__ */ jsx16("option", { value: DOCUMENT_SOURCE_FILTER.TEAM, children: labels.sourceFilterTeam })
1536
1737
  ]
1537
1738
  }
1538
1739
  ),
1539
- /* @__PURE__ */ jsxs10(
1740
+ /* @__PURE__ */ jsxs11(
1540
1741
  "button",
1541
1742
  {
1542
1743
  type: "button",
1543
1744
  onClick: () => applyFilter(() => setSortDirection(sortDirection === "desc" ? "asc" : "desc")),
1544
1745
  className: cn("cv-header-action inline-flex items-center gap-1", classNames?.sortButton),
1545
1746
  children: [
1546
- /* @__PURE__ */ jsx15(ArrowUpDown, { size: 14 }),
1747
+ /* @__PURE__ */ jsx16(ArrowUpDown, { size: 14 }),
1547
1748
  sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest
1548
1749
  ]
1549
1750
  }
1550
1751
  ),
1551
- hasFilters ? /* @__PURE__ */ jsx15(
1752
+ hasFilters ? /* @__PURE__ */ jsx16(
1552
1753
  "button",
1553
1754
  {
1554
1755
  type: "button",
@@ -1562,12 +1763,12 @@ function ConversationDocumentsPanel({
1562
1763
  }
1563
1764
  ) : null
1564
1765
  ] }),
1565
- loading ? /* @__PURE__ */ jsx15("p", { className: cn("text-xs text-gray-500", classNames?.status), children: labels.loading }) : null,
1566
- error ? /* @__PURE__ */ jsx15("p", { role: "alert", className: cn("text-xs text-red-600 dark:text-red-400", classNames?.status), children: labels.failure }) : null,
1567
- !loading && !error && documents.length === 0 ? /* @__PURE__ */ jsx15("p", { className: cn("text-xs text-gray-500", classNames?.status), children: hasFilters ? labels.noResults : labels.empty }) : null,
1568
- canArchive && documents.length > 0 ? /* @__PURE__ */ jsxs10("div", { className: cn("mb-2 flex flex-wrap items-center gap-3 text-xs", classNames?.selectionBar), children: [
1569
- /* @__PURE__ */ jsxs10("label", { className: "inline-flex items-center gap-1.5", children: [
1570
- /* @__PURE__ */ jsx15(
1766
+ loading ? /* @__PURE__ */ jsx16("p", { className: cn("text-xs text-gray-500", classNames?.status), children: labels.loading }) : null,
1767
+ error ? /* @__PURE__ */ jsx16("p", { role: "alert", className: cn("text-xs text-red-600 dark:text-red-400", classNames?.status), children: labels.failure }) : null,
1768
+ !loading && !error && documents.length === 0 ? /* @__PURE__ */ jsx16("p", { className: cn("text-xs text-gray-500", classNames?.status), children: hasFilters ? labels.noResults : labels.empty }) : null,
1769
+ canArchive && documents.length > 0 ? /* @__PURE__ */ jsxs11("div", { className: cn("mb-2 flex flex-wrap items-center gap-3 text-xs", classNames?.selectionBar), children: [
1770
+ /* @__PURE__ */ jsxs11("label", { className: "inline-flex items-center gap-1.5", children: [
1771
+ /* @__PURE__ */ jsx16(
1571
1772
  "input",
1572
1773
  {
1573
1774
  type: "checkbox",
@@ -1578,13 +1779,13 @@ function ConversationDocumentsPanel({
1578
1779
  ),
1579
1780
  labels.selectAll
1580
1781
  ] }),
1581
- selectedIds.length > 0 ? /* @__PURE__ */ jsx15("button", { type: "button", onClick: () => void handleDownloadSelected(), className: "cv-header-action", children: labels.downloadSelected(selectedIds.length) }) : null,
1582
- archiveError ? /* @__PURE__ */ jsx15("span", { role: "alert", className: "text-red-600 dark:text-red-400", children: labels.archiveFailed }) : null
1782
+ selectedIds.length > 0 ? /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => void handleDownloadSelected(), className: "cv-header-action", children: labels.downloadSelected(selectedIds.length) }) : null,
1783
+ archiveError ? /* @__PURE__ */ jsx16("span", { role: "alert", className: "text-red-600 dark:text-red-400", children: labels.archiveFailed }) : null
1583
1784
  ] }) : null,
1584
- /* @__PURE__ */ jsx15("ul", { className: cn("space-y-2", classNames?.list), children: documents.map((document2) => {
1785
+ /* @__PURE__ */ jsx16("ul", { className: cn("space-y-2", classNames?.list), children: documents.map((document2) => {
1585
1786
  const isFromCustomer = !TEAM_SOURCES.has(document2.source);
1586
1787
  const SourceIcon = isFromCustomer ? Users : Bot;
1587
- return /* @__PURE__ */ jsxs10(
1788
+ return /* @__PURE__ */ jsxs11(
1588
1789
  "li",
1589
1790
  {
1590
1791
  className: cn(
@@ -1592,8 +1793,8 @@ function ConversationDocumentsPanel({
1592
1793
  classNames?.item
1593
1794
  ),
1594
1795
  children: [
1595
- /* @__PURE__ */ jsxs10("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
1596
- canArchive ? /* @__PURE__ */ jsx15(
1796
+ /* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
1797
+ canArchive ? /* @__PURE__ */ jsx16(
1597
1798
  "input",
1598
1799
  {
1599
1800
  type: "checkbox",
@@ -1603,9 +1804,9 @@ function ConversationDocumentsPanel({
1603
1804
  className: cn("shrink-0", classNames?.checkbox)
1604
1805
  }
1605
1806
  ) : null,
1606
- /* @__PURE__ */ jsx15(FileIcon, { filename: document2.filename, mimeType: document2.mimeType }),
1607
- /* @__PURE__ */ jsxs10("div", { className: "min-w-0 flex-1", children: [
1608
- /* @__PURE__ */ jsxs10(
1807
+ /* @__PURE__ */ jsx16(FileIcon, { filename: document2.filename, mimeType: document2.mimeType }),
1808
+ /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
1809
+ /* @__PURE__ */ jsxs11(
1609
1810
  "div",
1610
1811
  {
1611
1812
  className: cn(
@@ -1614,12 +1815,12 @@ function ConversationDocumentsPanel({
1614
1815
  classNames?.sourceBadge
1615
1816
  ),
1616
1817
  children: [
1617
- /* @__PURE__ */ jsx15(SourceIcon, { size: 11 }),
1818
+ /* @__PURE__ */ jsx16(SourceIcon, { size: 11 }),
1618
1819
  isFromCustomer ? labels.sourceFilterCustomer : labels.sourceFilterTeam
1619
1820
  ]
1620
1821
  }
1621
1822
  ),
1622
- /* @__PURE__ */ jsx15(
1823
+ /* @__PURE__ */ jsx16(
1623
1824
  "div",
1624
1825
  {
1625
1826
  className: cn("truncate text-sm font-medium", classNames?.filename),
@@ -1627,15 +1828,15 @@ function ConversationDocumentsPanel({
1627
1828
  children: document2.filename
1628
1829
  }
1629
1830
  ),
1630
- /* @__PURE__ */ jsxs10("div", { className: cn("text-xs text-gray-500 dark:text-gray-400", classNames?.meta), children: [
1831
+ /* @__PURE__ */ jsxs11("div", { className: cn("text-xs text-gray-500 dark:text-gray-400", classNames?.meta), children: [
1631
1832
  formatDateTime(document2.linkedAt),
1632
1833
  " \xB7 ",
1633
1834
  formatFileSize(document2.sizeBytes)
1634
1835
  ] })
1635
1836
  ] })
1636
1837
  ] }),
1637
- /* @__PURE__ */ jsxs10("div", { className: "flex shrink-0 gap-1", children: [
1638
- /* @__PURE__ */ jsx15(
1838
+ /* @__PURE__ */ jsxs11("div", { className: "flex shrink-0 gap-1", children: [
1839
+ /* @__PURE__ */ jsx16(
1639
1840
  "button",
1640
1841
  {
1641
1842
  type: "button",
@@ -1643,10 +1844,10 @@ function ConversationDocumentsPanel({
1643
1844
  title: labels.view,
1644
1845
  "aria-label": `${labels.view}: ${document2.filename}`,
1645
1846
  className: cn("cv-header-icon", classNames?.viewButton),
1646
- children: /* @__PURE__ */ jsx15(Eye, { size: 14 })
1847
+ children: /* @__PURE__ */ jsx16(Eye, { size: 14 })
1647
1848
  }
1648
1849
  ),
1649
- /* @__PURE__ */ jsx15(
1850
+ /* @__PURE__ */ jsx16(
1650
1851
  "button",
1651
1852
  {
1652
1853
  type: "button",
@@ -1654,7 +1855,7 @@ function ConversationDocumentsPanel({
1654
1855
  title: labels.download,
1655
1856
  "aria-label": `${labels.download}: ${document2.filename}`,
1656
1857
  className: cn("cv-header-icon", classNames?.downloadButton),
1657
- children: /* @__PURE__ */ jsx15(Download, { size: 14 })
1858
+ children: /* @__PURE__ */ jsx16(Download, { size: 14 })
1658
1859
  }
1659
1860
  )
1660
1861
  ] })
@@ -1663,7 +1864,7 @@ function ConversationDocumentsPanel({
1663
1864
  document2.id
1664
1865
  );
1665
1866
  }) }),
1666
- total > perPage ? /* @__PURE__ */ jsxs10(
1867
+ total > perPage ? /* @__PURE__ */ jsxs11(
1667
1868
  "div",
1668
1869
  {
1669
1870
  className: cn(
@@ -1671,9 +1872,9 @@ function ConversationDocumentsPanel({
1671
1872
  classNames?.pagination
1672
1873
  ),
1673
1874
  children: [
1674
- /* @__PURE__ */ jsx15("span", { className: "text-gray-400", children: labels.total(total) }),
1675
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
1676
- /* @__PURE__ */ jsx15(
1875
+ /* @__PURE__ */ jsx16("span", { className: "text-gray-400", children: labels.total(total) }),
1876
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
1877
+ /* @__PURE__ */ jsx16(
1677
1878
  "button",
1678
1879
  {
1679
1880
  type: "button",
@@ -1684,8 +1885,8 @@ function ConversationDocumentsPanel({
1684
1885
  children: "\u2039"
1685
1886
  }
1686
1887
  ),
1687
- /* @__PURE__ */ jsx15("span", { className: "text-gray-500", children: labels.page(page, lastPage) }),
1688
- /* @__PURE__ */ jsx15(
1888
+ /* @__PURE__ */ jsx16("span", { className: "text-gray-500", children: labels.page(page, lastPage) }),
1889
+ /* @__PURE__ */ jsx16(
1689
1890
  "button",
1690
1891
  {
1691
1892
  type: "button",
@@ -1704,9 +1905,9 @@ function ConversationDocumentsPanel({
1704
1905
  }
1705
1906
 
1706
1907
  // src/DocumentsLibrary.tsx
1707
- import { useEffect as useEffect4, useState as useState10 } from "react";
1908
+ import { useEffect as useEffect4, useState as useState11 } from "react";
1708
1909
  import { ArrowUpDown as ArrowUpDown2, Bot as Bot2, Download as Download2, Eye as Eye2, MessageSquare, Users as Users2 } from "lucide-react";
1709
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
1910
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
1710
1911
  var DEFAULT_DOCUMENTS_LIBRARY_LABELS = {
1711
1912
  title: "Documentos",
1712
1913
  searchPlaceholder: "Buscar por nome do arquivo ou telefone",
@@ -1737,14 +1938,14 @@ function DocumentsLibrary({
1737
1938
  }) {
1738
1939
  const labels = { ...DEFAULT_DOCUMENTS_LIBRARY_LABELS, ...labelsOverride };
1739
1940
  const context = useConversations();
1740
- const [search, setSearch] = useState10("");
1741
- const [sourceFilter, setSourceFilter] = useState10(DOCUMENT_SOURCE_FILTER.ALL);
1742
- const [sortDirection, setSortDirection] = useState10("desc");
1743
- const [page, setPage] = useState10(1);
1744
- const [documents, setDocuments] = useState10([]);
1745
- const [total, setTotal] = useState10(0);
1746
- const [loading, setLoading] = useState10(false);
1747
- const [failed, setFailed] = useState10(false);
1941
+ const [search, setSearch] = useState11("");
1942
+ const [sourceFilter, setSourceFilter] = useState11(DOCUMENT_SOURCE_FILTER.ALL);
1943
+ const [sortDirection, setSortDirection] = useState11("desc");
1944
+ const [page, setPage] = useState11(1);
1945
+ const [documents, setDocuments] = useState11([]);
1946
+ const [total, setTotal] = useState11(0);
1947
+ const [loading, setLoading] = useState11(false);
1948
+ const [failed, setFailed] = useState11(false);
1748
1949
  const hasFilters = search !== "" || sourceFilter !== DOCUMENT_SOURCE_FILTER.ALL || sortDirection !== "desc";
1749
1950
  const lastPage = Math.max(1, Math.ceil(total / perPage));
1750
1951
  const fetchAll = context?.api.getAllDocuments;
@@ -1781,10 +1982,10 @@ function DocumentsLibrary({
1781
1982
  if (url) window.open(url, "_blank", "noopener,noreferrer");
1782
1983
  }
1783
1984
  if (!fetchAll) return null;
1784
- return /* @__PURE__ */ jsxs11("div", { className: cn("space-y-3", classNames?.root, className), children: [
1785
- /* @__PURE__ */ jsx16("h2", { className: cn("text-lg font-semibold", classNames?.title), children: labels.title }),
1786
- /* @__PURE__ */ jsxs11("div", { className: cn("flex flex-wrap items-center gap-2", classNames?.filters), children: [
1787
- /* @__PURE__ */ jsx16(
1985
+ return /* @__PURE__ */ jsxs12("div", { className: cn("space-y-3", classNames?.root, className), children: [
1986
+ /* @__PURE__ */ jsx17("h2", { className: cn("text-lg font-semibold", classNames?.title), children: labels.title }),
1987
+ /* @__PURE__ */ jsxs12("div", { className: cn("flex flex-wrap items-center gap-2", classNames?.filters), children: [
1988
+ /* @__PURE__ */ jsx17(
1788
1989
  "input",
1789
1990
  {
1790
1991
  type: "search",
@@ -1795,7 +1996,7 @@ function DocumentsLibrary({
1795
1996
  className: cn("w-full rounded-md border px-3 py-2 text-sm sm:w-64", classNames?.search)
1796
1997
  }
1797
1998
  ),
1798
- /* @__PURE__ */ jsxs11(
1999
+ /* @__PURE__ */ jsxs12(
1799
2000
  "select",
1800
2001
  {
1801
2002
  value: sourceFilter,
@@ -1803,25 +2004,25 @@ function DocumentsLibrary({
1803
2004
  "aria-label": labels.sourceFilterAll,
1804
2005
  className: cn("w-full rounded-md border px-2 py-2 text-sm sm:w-40", classNames?.sourceSelect),
1805
2006
  children: [
1806
- /* @__PURE__ */ jsx16("option", { value: DOCUMENT_SOURCE_FILTER.ALL, children: labels.sourceFilterAll }),
1807
- /* @__PURE__ */ jsx16("option", { value: DOCUMENT_SOURCE_FILTER.CUSTOMER, children: labels.sourceFilterCustomer }),
1808
- /* @__PURE__ */ jsx16("option", { value: DOCUMENT_SOURCE_FILTER.TEAM, children: labels.sourceFilterTeam })
2007
+ /* @__PURE__ */ jsx17("option", { value: DOCUMENT_SOURCE_FILTER.ALL, children: labels.sourceFilterAll }),
2008
+ /* @__PURE__ */ jsx17("option", { value: DOCUMENT_SOURCE_FILTER.CUSTOMER, children: labels.sourceFilterCustomer }),
2009
+ /* @__PURE__ */ jsx17("option", { value: DOCUMENT_SOURCE_FILTER.TEAM, children: labels.sourceFilterTeam })
1809
2010
  ]
1810
2011
  }
1811
2012
  ),
1812
- /* @__PURE__ */ jsxs11(
2013
+ /* @__PURE__ */ jsxs12(
1813
2014
  "button",
1814
2015
  {
1815
2016
  type: "button",
1816
2017
  onClick: () => applyFilter(() => setSortDirection(sortDirection === "desc" ? "asc" : "desc")),
1817
2018
  className: cn("cv-header-action inline-flex items-center gap-1", classNames?.sortButton),
1818
2019
  children: [
1819
- /* @__PURE__ */ jsx16(ArrowUpDown2, { size: 14 }),
2020
+ /* @__PURE__ */ jsx17(ArrowUpDown2, { size: 14 }),
1820
2021
  sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest
1821
2022
  ]
1822
2023
  }
1823
2024
  ),
1824
- hasFilters ? /* @__PURE__ */ jsx16(
2025
+ hasFilters ? /* @__PURE__ */ jsx17(
1825
2026
  "button",
1826
2027
  {
1827
2028
  type: "button",
@@ -1835,13 +2036,13 @@ function DocumentsLibrary({
1835
2036
  }
1836
2037
  ) : null
1837
2038
  ] }),
1838
- loading ? /* @__PURE__ */ jsx16("p", { className: cn("text-sm text-gray-500", classNames?.status), children: labels.loading }) : null,
1839
- failed ? /* @__PURE__ */ jsx16("p", { role: "alert", className: cn("text-sm text-red-600 dark:text-red-400", classNames?.status), children: labels.failure }) : null,
1840
- !loading && !failed && documents.length === 0 ? /* @__PURE__ */ jsx16("p", { className: cn("text-sm text-gray-500", classNames?.status), children: hasFilters ? labels.noResults : labels.empty }) : null,
1841
- /* @__PURE__ */ jsx16("ul", { className: cn("space-y-2", classNames?.list), children: documents.map((document2) => {
2039
+ loading ? /* @__PURE__ */ jsx17("p", { className: cn("text-sm text-gray-500", classNames?.status), children: labels.loading }) : null,
2040
+ failed ? /* @__PURE__ */ jsx17("p", { role: "alert", className: cn("text-sm text-red-600 dark:text-red-400", classNames?.status), children: labels.failure }) : null,
2041
+ !loading && !failed && documents.length === 0 ? /* @__PURE__ */ jsx17("p", { className: cn("text-sm text-gray-500", classNames?.status), children: hasFilters ? labels.noResults : labels.empty }) : null,
2042
+ /* @__PURE__ */ jsx17("ul", { className: cn("space-y-2", classNames?.list), children: documents.map((document2) => {
1842
2043
  const isFromCustomer = !TEAM_SOURCES2.has(document2.source);
1843
2044
  const SourceIcon = isFromCustomer ? Users2 : Bot2;
1844
- return /* @__PURE__ */ jsxs11(
2045
+ return /* @__PURE__ */ jsxs12(
1845
2046
  "li",
1846
2047
  {
1847
2048
  className: cn(
@@ -1849,23 +2050,23 @@ function DocumentsLibrary({
1849
2050
  classNames?.item
1850
2051
  ),
1851
2052
  children: [
1852
- /* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
1853
- /* @__PURE__ */ jsx16(FileIcon, { filename: document2.filename, mimeType: document2.mimeType }),
1854
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
1855
- /* @__PURE__ */ jsx16("div", { className: cn("truncate text-sm font-medium", classNames?.filename), title: document2.filename, children: document2.filename }),
1856
- /* @__PURE__ */ jsxs11("div", { className: cn("flex flex-wrap items-center gap-x-2 text-xs text-gray-500", classNames?.meta), children: [
1857
- /* @__PURE__ */ jsxs11("span", { className: "inline-flex items-center gap-1", children: [
1858
- /* @__PURE__ */ jsx16(SourceIcon, { size: 11 }),
2053
+ /* @__PURE__ */ jsxs12("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
2054
+ /* @__PURE__ */ jsx17(FileIcon, { filename: document2.filename, mimeType: document2.mimeType }),
2055
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
2056
+ /* @__PURE__ */ jsx17("div", { className: cn("truncate text-sm font-medium", classNames?.filename), title: document2.filename, children: document2.filename }),
2057
+ /* @__PURE__ */ jsxs12("div", { className: cn("flex flex-wrap items-center gap-x-2 text-xs text-gray-500", classNames?.meta), children: [
2058
+ /* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1", children: [
2059
+ /* @__PURE__ */ jsx17(SourceIcon, { size: 11 }),
1859
2060
  isFromCustomer ? labels.sourceFilterCustomer : labels.sourceFilterTeam
1860
2061
  ] }),
1861
- /* @__PURE__ */ jsx16("span", { children: "\xB7" }),
1862
- /* @__PURE__ */ jsx16("span", { children: formatDateTime(document2.linkedAt) }),
1863
- /* @__PURE__ */ jsx16("span", { children: "\xB7" }),
1864
- /* @__PURE__ */ jsx16("span", { children: formatFileSize(document2.sizeBytes) })
2062
+ /* @__PURE__ */ jsx17("span", { children: "\xB7" }),
2063
+ /* @__PURE__ */ jsx17("span", { children: formatDateTime(document2.linkedAt) }),
2064
+ /* @__PURE__ */ jsx17("span", { children: "\xB7" }),
2065
+ /* @__PURE__ */ jsx17("span", { children: formatFileSize(document2.sizeBytes) })
1865
2066
  ] })
1866
2067
  ] })
1867
2068
  ] }),
1868
- onOpenConversation ? /* @__PURE__ */ jsxs11(
2069
+ onOpenConversation ? /* @__PURE__ */ jsxs12(
1869
2070
  "button",
1870
2071
  {
1871
2072
  type: "button",
@@ -1873,13 +2074,13 @@ function DocumentsLibrary({
1873
2074
  title: labels.openConversation,
1874
2075
  className: cn("cv-header-action inline-flex shrink-0 items-center gap-1", classNames?.conversationLink),
1875
2076
  children: [
1876
- /* @__PURE__ */ jsx16(MessageSquare, { size: 12 }),
2077
+ /* @__PURE__ */ jsx17(MessageSquare, { size: 12 }),
1877
2078
  formatPhone(document2.conversationId)
1878
2079
  ]
1879
2080
  }
1880
- ) : /* @__PURE__ */ jsx16("span", { className: cn("shrink-0 text-xs text-gray-500", classNames?.conversationLink), children: formatPhone(document2.conversationId) }),
1881
- /* @__PURE__ */ jsxs11("div", { className: "flex shrink-0 gap-1", children: [
1882
- /* @__PURE__ */ jsx16(
2081
+ ) : /* @__PURE__ */ jsx17("span", { className: cn("shrink-0 text-xs text-gray-500", classNames?.conversationLink), children: formatPhone(document2.conversationId) }),
2082
+ /* @__PURE__ */ jsxs12("div", { className: "flex shrink-0 gap-1", children: [
2083
+ /* @__PURE__ */ jsx17(
1883
2084
  "button",
1884
2085
  {
1885
2086
  type: "button",
@@ -1887,10 +2088,10 @@ function DocumentsLibrary({
1887
2088
  title: labels.view,
1888
2089
  "aria-label": `${labels.view}: ${document2.filename}`,
1889
2090
  className: "cv-header-icon",
1890
- children: /* @__PURE__ */ jsx16(Eye2, { size: 14 })
2091
+ children: /* @__PURE__ */ jsx17(Eye2, { size: 14 })
1891
2092
  }
1892
2093
  ),
1893
- /* @__PURE__ */ jsx16(
2094
+ /* @__PURE__ */ jsx17(
1894
2095
  "button",
1895
2096
  {
1896
2097
  type: "button",
@@ -1898,7 +2099,7 @@ function DocumentsLibrary({
1898
2099
  title: labels.download,
1899
2100
  "aria-label": `${labels.download}: ${document2.filename}`,
1900
2101
  className: "cv-header-icon",
1901
- children: /* @__PURE__ */ jsx16(Download2, { size: 14 })
2102
+ children: /* @__PURE__ */ jsx17(Download2, { size: 14 })
1902
2103
  }
1903
2104
  )
1904
2105
  ] })
@@ -1907,10 +2108,10 @@ function DocumentsLibrary({
1907
2108
  `${document2.conversationId}:${document2.id}`
1908
2109
  );
1909
2110
  }) }),
1910
- total > perPage ? /* @__PURE__ */ jsxs11("div", { className: cn("flex items-center justify-between border-t pt-2 text-xs dark:border-gray-700", classNames?.pagination), children: [
1911
- /* @__PURE__ */ jsx16("span", { className: "text-gray-400", children: labels.total(total) }),
1912
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
1913
- /* @__PURE__ */ jsx16(
2111
+ total > perPage ? /* @__PURE__ */ jsxs12("div", { className: cn("flex items-center justify-between border-t pt-2 text-xs dark:border-gray-700", classNames?.pagination), children: [
2112
+ /* @__PURE__ */ jsx17("span", { className: "text-gray-400", children: labels.total(total) }),
2113
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
2114
+ /* @__PURE__ */ jsx17(
1914
2115
  "button",
1915
2116
  {
1916
2117
  type: "button",
@@ -1920,8 +2121,8 @@ function DocumentsLibrary({
1920
2121
  children: "\u2039"
1921
2122
  }
1922
2123
  ),
1923
- /* @__PURE__ */ jsx16("span", { className: "text-gray-500", children: labels.page(page, lastPage) }),
1924
- /* @__PURE__ */ jsx16(
2124
+ /* @__PURE__ */ jsx17("span", { className: "text-gray-500", children: labels.page(page, lastPage) }),
2125
+ /* @__PURE__ */ jsx17(
1925
2126
  "button",
1926
2127
  {
1927
2128
  type: "button",
@@ -1942,6 +2143,7 @@ export {
1942
2143
  StatusTicks,
1943
2144
  AudioPlayer,
1944
2145
  cn,
2146
+ AudioTranscription,
1945
2147
  FileIcon,
1946
2148
  formatTimestamp,
1947
2149
  formatDateTime,
@@ -1961,14 +2163,14 @@ export {
1961
2163
  searchEmojis,
1962
2164
  DEFAULT_EMOJI_PICKER_LABELS,
1963
2165
  EmojiPicker,
2166
+ DEFAULT_AUDIO_RECORDER_BUTTON_LABELS,
2167
+ DEFAULT_MAX_RECORDING_MILLISECONDS,
2168
+ AudioRecorderButton,
1964
2169
  applyQuickReplyVariables,
1965
2170
  resolveQuickReply,
1966
2171
  DEFAULT_MESSAGE_COMPOSER_LABELS,
1967
2172
  DEFAULT_ACCEPTED_FILE_TYPES,
1968
2173
  MessageComposer,
1969
- DEFAULT_AUDIO_RECORDER_BUTTON_LABELS,
1970
- DEFAULT_MAX_RECORDING_MILLISECONDS,
1971
- AudioRecorderButton,
1972
2174
  DateDivider,
1973
2175
  formatPhone,
1974
2176
  phoneCountryFlag,