@adatechnology/conversations-ui 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/{ConversationSimulatorPanel--5fIzXWY.d.ts → ConversationSimulatorPanel-ikgmlciE.d.ts} +103 -1
  2. package/dist/{chunk-BJNRLLDO.js → chunk-NHQDQJL2.js} +769 -244
  3. package/dist/index.d.ts +304 -9
  4. package/dist/index.js +2166 -509
  5. package/dist/preview/index.d.ts +2 -2
  6. package/dist/preview/index.js +147 -1
  7. package/dist/styles.css +135 -0
  8. package/package.json +2 -2
  9. package/src/MessageComposer.test.tsx +14 -0
  10. package/src/MessageComposer.tsx +327 -73
  11. package/src/RichMessageComposer.test.tsx +22 -4
  12. package/src/RichMessageComposer.tsx +674 -370
  13. package/src/index.ts +28 -1
  14. package/src/preview/createMockConversationsApi.ts +184 -0
  15. package/src/providers/types.ts +34 -0
  16. package/src/quickReplies/AttachmentsFormSection.tsx +160 -0
  17. package/src/quickReplies/QuickRepliesPicker.test.tsx +114 -0
  18. package/src/quickReplies/QuickRepliesPicker.tsx +188 -0
  19. package/src/quickReplies/QuickRepliesWorkspace.test.tsx +32 -0
  20. package/src/quickReplies/QuickRepliesWorkspace.tsx +395 -0
  21. package/src/quickReplies/createUploadQueue.test.ts +106 -0
  22. package/src/quickReplies/createUploadQueue.ts +69 -0
  23. package/src/quickReplies/index.ts +5 -0
  24. package/src/quickReplies/labels.ts +124 -0
  25. package/src/quickReplies/quickReply.types.ts +74 -0
  26. package/src/quickReplies/quickReplyAttachmentUpload.test.ts +76 -0
  27. package/src/quickReplies/quickReplyAttachmentUpload.ts +81 -0
  28. package/src/quickReplies/quickReplyAttachments.test.ts +396 -0
  29. package/src/quickReplies/quickReplyAttachments.ts +289 -0
  30. package/src/quickReplies/quickReplySearch.test.ts +88 -0
  31. package/src/quickReplies/quickReplySearch.ts +104 -0
  32. package/src/quickReplies/quickReplyShortcut.test.ts +38 -0
  33. package/src/quickReplies/quickReplyShortcut.ts +46 -0
  34. package/src/quickReplies/resolveConversationVariables.test.ts +63 -0
  35. package/src/quickReplies/resolveConversationVariables.ts +41 -0
  36. package/src/quickReplies/useQuickRepliesPicker.test.ts +20 -0
  37. package/src/quickReplies/useQuickRepliesPicker.ts +121 -0
  38. package/src/quickReplies/useQuickRepliesWorkspace.test.ts +222 -0
  39. package/src/quickReplies/useQuickRepliesWorkspace.ts +426 -0
  40. package/src/quickReplies/useQuickReplyAttachmentUploads.ts +159 -0
  41. package/src/styles.css +87 -0
  42. package/src/workspace/ConversationPane.tsx +137 -73
  43. package/src/workspace/ConversationsWorkspace.tsx +16 -1
  44. package/src/workspace/QueuedAttachmentsList.test.ts +27 -0
  45. package/src/workspace/QueuedAttachmentsList.tsx +198 -0
  46. package/src/workspace/index.ts +1 -0
  47. package/src/workspace/labels.ts +14 -0
  48. package/src/workspace/useComposerAttachmentRetry.ts +155 -0
  49. package/src/workspace/useComposerQueue.ts +220 -0
@@ -1298,7 +1298,13 @@ function AudioRecorderButton({
1298
1298
  }
1299
1299
 
1300
1300
  // src/MessageComposer.tsx
1301
- import { useState as useState8, useRef as useRef3, useCallback as useCallback4 } from "react";
1301
+ import {
1302
+ useState as useState9,
1303
+ useRef as useRef5,
1304
+ useCallback as useCallback5,
1305
+ useEffect as useEffect5,
1306
+ useId
1307
+ } from "react";
1302
1308
 
1303
1309
  // src/composer.constant.ts
1304
1310
  var COMPOSER_BAR_CLASS = "cv-composer-bar";
@@ -1309,8 +1315,282 @@ var COMPOSER_MONOSPACE_CLASS = "bg-black/5 dark:bg-white/10 rounded px-0.5 font-
1309
1315
  var COMPOSER_COMPACT_WIDTH = 480;
1310
1316
  var QUICK_REPLY_PILL_CLASS = "whitespace-nowrap rounded-full border border-gray-200 bg-white px-3 py-1.5 text-xs text-gray-600 shadow-sm transition-colors hover:border-teal-200 hover:bg-teal-50 hover:text-teal-700 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:border-teal-800 dark:hover:bg-teal-950/40 dark:hover:text-teal-400";
1311
1317
 
1318
+ // src/quickReplies/QuickRepliesPicker.tsx
1319
+ import { useEffect as useEffect3, useRef as useRef3 } from "react";
1320
+ import { Paperclip } from "lucide-react";
1321
+
1322
+ // src/quickReplies/labels.ts
1323
+ var DEFAULT_QUICK_REPLIES_PICKER_LABELS = {
1324
+ loading: "Carregando mensagens prontas\u2026",
1325
+ error: "N\xE3o foi poss\xEDvel carregar as mensagens prontas.",
1326
+ empty: "Nenhuma mensagem pronta cadastrada ainda.",
1327
+ noResults: "Nenhuma mensagem encontrada.",
1328
+ attachmentsCount: (count) => `${count} ${count === 1 ? "anexo" : "anexos"}`,
1329
+ attachmentsUnavailable: "Este produto n\xE3o envia os anexos desta mensagem \u2014 s\xF3 o texto entra."
1330
+ };
1331
+ var DEFAULT_QUICK_REPLIES_WORKSPACE_LABELS = {
1332
+ title: "Mensagens prontas",
1333
+ subtitle: (total) => `${total} ${total === 1 ? "mensagem cadastrada" : "mensagens cadastradas"}`,
1334
+ searchPlaceholder: "Buscar por t\xEDtulo, atalho ou texto",
1335
+ loading: "Carregando mensagens prontas\u2026",
1336
+ failure: "N\xE3o foi poss\xEDvel carregar as mensagens prontas.",
1337
+ empty: "Nenhuma mensagem pronta cadastrada ainda.",
1338
+ noResults: "Nenhuma mensagem encontrada para a busca.",
1339
+ create: "Nova mensagem",
1340
+ edit: "Editar",
1341
+ remove: "Excluir",
1342
+ removeConfirm: (title) => `Excluir a mensagem "${title}"?`,
1343
+ save: "Salvar",
1344
+ cancel: "Cancelar",
1345
+ columnTitle: "T\xEDtulo",
1346
+ columnShortcut: "Atalho",
1347
+ columnBody: "Texto",
1348
+ columnActions: "A\xE7\xF5es",
1349
+ fieldTitle: "T\xEDtulo",
1350
+ fieldTitleInvalid: "Digite um t\xEDtulo de at\xE9 40 caracteres.",
1351
+ fieldShortcut: "Atalho",
1352
+ fieldShortcutHint: "Letras min\xFAsculas, n\xFAmeros e h\xEDfen, sem espa\xE7o nem acento.",
1353
+ fieldShortcutInvalid: "Atalho inv\xE1lido \u2014 s\xF3 letras min\xFAsculas, n\xFAmeros e h\xEDfen, at\xE9 20 caracteres.",
1354
+ fieldBody: "Texto",
1355
+ fieldBodyInvalid: "Digite um texto de at\xE9 1000 caracteres.",
1356
+ insertVariable: "Inserir vari\xE1vel",
1357
+ shortcutTaken: "Esse atalho j\xE1 est\xE1 em uso \u2014 escolha outro.",
1358
+ readOnlyNotice: "Voc\xEA s\xF3 pode consultar as mensagens prontas.",
1359
+ saveError: "N\xE3o foi poss\xEDvel salvar a mensagem.",
1360
+ saveUnavailable: "Salvar mensagens prontas n\xE3o est\xE1 dispon\xEDvel.",
1361
+ saving: "Salvando\u2026",
1362
+ deleting: "Excluindo\u2026",
1363
+ attachmentsTitle: "Anexos",
1364
+ attachmentsAdd: "Adicionar anexo",
1365
+ attachmentsEmpty: "Nenhum anexo \u2014 at\xE9 10 arquivos.",
1366
+ attachmentUploading: (percent) => `Enviando\u2026 ${percent}%`,
1367
+ attachmentProcessing: "Processando\u2026",
1368
+ attachmentRetry: "Tentar de novo",
1369
+ attachmentRemove: "Remover anexo",
1370
+ attachmentCancel: "Cancelar envio",
1371
+ attachmentMoveUp: "Mover para cima",
1372
+ attachmentMoveDown: "Mover para baixo",
1373
+ attachmentLimitReached: "Limite de 10 anexos por mensagem.",
1374
+ attachmentTooLarge: (filename) => `${filename}: excede o tamanho m\xE1ximo para o tipo de arquivo.`,
1375
+ saveBlockedUploading: "Aguardando o envio dos anexos\u2026"
1376
+ };
1377
+
1378
+ // src/quickReplies/QuickRepliesPicker.tsx
1379
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
1380
+ var LOADING_SKELETON_ROWS = 4;
1381
+ function QuickRepliesPicker({
1382
+ id,
1383
+ items,
1384
+ search,
1385
+ highlightedIndex,
1386
+ isLoading,
1387
+ hasError,
1388
+ onHover,
1389
+ onSelect,
1390
+ labels,
1391
+ className,
1392
+ ownSearch,
1393
+ variables,
1394
+ hasAttachmentsCapability
1395
+ }) {
1396
+ const text = { ...DEFAULT_QUICK_REPLIES_PICKER_LABELS, ...labels };
1397
+ const searchInputRef = useRef3(null);
1398
+ useEffect3(() => {
1399
+ if (ownSearch) searchInputRef.current?.focus();
1400
+ }, []);
1401
+ const activeOptionId = items.length > 0 ? `${id}-option-${highlightedIndex}` : void 0;
1402
+ return /* @__PURE__ */ jsxs10("div", { className, children: [
1403
+ ownSearch ? /* @__PURE__ */ jsx14(
1404
+ "input",
1405
+ {
1406
+ ref: searchInputRef,
1407
+ type: "text",
1408
+ role: "combobox",
1409
+ "aria-expanded": "true",
1410
+ "aria-controls": id,
1411
+ "aria-activedescendant": activeOptionId,
1412
+ value: ownSearch.value,
1413
+ onChange: (event) => ownSearch.onChange(event.target.value),
1414
+ onKeyDown: ownSearch.onKeyDown,
1415
+ placeholder: ownSearch.label,
1416
+ "aria-label": ownSearch.label,
1417
+ className: "mb-1 w-72 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm outline-none focus:border-gray-400 dark:border-gray-700 dark:bg-gray-900"
1418
+ }
1419
+ ) : null,
1420
+ /* @__PURE__ */ jsxs10(
1421
+ "ul",
1422
+ {
1423
+ role: "listbox",
1424
+ id,
1425
+ className: "max-h-64 w-72 overflow-y-auto rounded-lg border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-700 dark:bg-gray-900",
1426
+ children: [
1427
+ isLoading ? /* @__PURE__ */ jsxs10("li", { "aria-busy": "true", "aria-live": "polite", children: [
1428
+ /* @__PURE__ */ jsx14("span", { className: "sr-only", children: text.loading }),
1429
+ Array.from({ length: LOADING_SKELETON_ROWS }).map((_, index) => /* @__PURE__ */ jsxs10("span", { className: "flex flex-col gap-1 px-3 py-2", children: [
1430
+ /* @__PURE__ */ jsx14("span", { className: "cv-skeleton-line", style: { width: "60%", height: "0.75rem" } }),
1431
+ /* @__PURE__ */ jsx14("span", { className: "cv-skeleton-line", style: { width: "85%", height: "0.625rem" } })
1432
+ ] }, index))
1433
+ ] }) : null,
1434
+ !isLoading && hasError ? /* @__PURE__ */ jsx14("li", { role: "alert", className: "px-3 py-2 text-sm text-red-600 dark:text-red-400", children: text.error }) : null,
1435
+ !isLoading && !hasError && items.length === 0 ? /* @__PURE__ */ jsx14("li", { className: "px-3 py-2 text-sm text-gray-500 dark:text-gray-400", children: search.trim() ? text.noResults : text.empty }) : null,
1436
+ !isLoading && !hasError ? items.map((quickReply, index) => {
1437
+ const resolvedBody = applyQuickReplyVariables(quickReply.body, variables);
1438
+ return /* @__PURE__ */ jsxs10(
1439
+ "li",
1440
+ {
1441
+ id: `${id}-option-${index}`,
1442
+ role: "option",
1443
+ "aria-selected": index === highlightedIndex,
1444
+ className: cn(
1445
+ "flex cursor-pointer flex-col gap-0.5 px-3 py-2 text-sm",
1446
+ index === highlightedIndex ? "bg-gray-100 dark:bg-gray-800" : void 0
1447
+ ),
1448
+ onMouseEnter: () => onHover(index),
1449
+ onMouseDown: (event) => {
1450
+ event.preventDefault();
1451
+ onSelect(quickReply);
1452
+ },
1453
+ children: [
1454
+ /* @__PURE__ */ jsxs10("span", { className: "flex items-center gap-2", children: [
1455
+ /* @__PURE__ */ jsxs10("span", { className: "font-mono text-xs text-gray-400", children: [
1456
+ "/",
1457
+ quickReply.shortcut
1458
+ ] }),
1459
+ /* @__PURE__ */ jsx14("span", { className: "truncate font-medium", children: highlightMatch(quickReply.title, search).map(
1460
+ (segment, segmentIndex) => segment.isMatch ? /* @__PURE__ */ jsx14("mark", { className: "rounded-sm bg-yellow-200 dark:bg-yellow-700/60", children: segment.text }, segmentIndex) : /* @__PURE__ */ jsx14("span", { children: segment.text }, segmentIndex)
1461
+ ) }),
1462
+ quickReply.attachments && quickReply.attachments.length > 0 ? /* @__PURE__ */ jsxs10(
1463
+ "span",
1464
+ {
1465
+ className: cn(
1466
+ "flex flex-none items-center gap-0.5 text-xs",
1467
+ hasAttachmentsCapability ? "text-gray-500 dark:text-gray-400" : "text-amber-600 dark:text-amber-400"
1468
+ ),
1469
+ title: hasAttachmentsCapability ? void 0 : text.attachmentsUnavailable,
1470
+ children: [
1471
+ /* @__PURE__ */ jsx14(Paperclip, { "aria-hidden": "true", className: "h-3 w-3" }),
1472
+ text.attachmentsCount(quickReply.attachments.length)
1473
+ ]
1474
+ }
1475
+ ) : null
1476
+ ] }),
1477
+ quickReply.attachments && quickReply.attachments.length > 0 && !hasAttachmentsCapability ? /* @__PURE__ */ jsx14("span", { className: "text-xs text-amber-600 dark:text-amber-400", children: text.attachmentsUnavailable }) : null,
1478
+ /* @__PURE__ */ jsx14("span", { className: "truncate text-xs text-gray-500 dark:text-gray-400", children: highlightMatch(resolvedBody, search).map(
1479
+ (segment, segmentIndex) => segment.isMatch ? /* @__PURE__ */ jsx14("mark", { className: "rounded-sm bg-yellow-200 dark:bg-yellow-700/60", children: segment.text }, segmentIndex) : /* @__PURE__ */ jsx14("span", { children: segment.text }, segmentIndex)
1480
+ ) })
1481
+ ]
1482
+ },
1483
+ quickReply.id
1484
+ );
1485
+ }) : null
1486
+ ]
1487
+ }
1488
+ )
1489
+ ] });
1490
+ }
1491
+
1492
+ // src/quickReplies/useQuickRepliesPicker.ts
1493
+ import { useCallback as useCallback4, useEffect as useEffect4, useRef as useRef4, useState as useState8 } from "react";
1494
+ function nextHighlightedIndex(current, length, delta) {
1495
+ if (length === 0) return 0;
1496
+ return (current + delta + length) % length;
1497
+ }
1498
+ function useQuickRepliesPicker({
1499
+ isOpen,
1500
+ search,
1501
+ listQuickReplies,
1502
+ quickReplyVariables,
1503
+ onSelect,
1504
+ onClose
1505
+ }) {
1506
+ const cacheRef = useRef4(void 0);
1507
+ const requestIdRef = useRef4(0);
1508
+ const [items, setItems] = useState8([]);
1509
+ const [isLoading, setIsLoading] = useState8(false);
1510
+ const [hasError, setHasError] = useState8(false);
1511
+ const [highlightedIndex, setHighlightedIndex] = useState8(0);
1512
+ const load = useCallback4(() => {
1513
+ if (!listQuickReplies) return;
1514
+ const requestId = ++requestIdRef.current;
1515
+ setIsLoading(true);
1516
+ setHasError(false);
1517
+ listQuickReplies().then((result) => {
1518
+ if (requestIdRef.current !== requestId) return;
1519
+ cacheRef.current = result;
1520
+ setItems(result);
1521
+ setIsLoading(false);
1522
+ }).catch(() => {
1523
+ if (requestIdRef.current !== requestId) return;
1524
+ setHasError(true);
1525
+ setIsLoading(false);
1526
+ });
1527
+ }, [listQuickReplies]);
1528
+ useEffect4(() => {
1529
+ if (!isOpen || !listQuickReplies) return;
1530
+ if (cacheRef.current) {
1531
+ setItems(cacheRef.current);
1532
+ return;
1533
+ }
1534
+ load();
1535
+ }, [isOpen, listQuickReplies, load]);
1536
+ const refetch = useCallback4(() => {
1537
+ cacheRef.current = void 0;
1538
+ load();
1539
+ }, [load]);
1540
+ const filtered = filterQuickReplies({ quickReplies: items, search, variables: quickReplyVariables });
1541
+ useEffect4(() => {
1542
+ setHighlightedIndex(0);
1543
+ }, [search, filtered.length]);
1544
+ const handleKeyDown = useCallback4(
1545
+ (event) => {
1546
+ if (event.key === "ArrowDown") {
1547
+ event.preventDefault();
1548
+ setHighlightedIndex((index) => nextHighlightedIndex(index, filtered.length, 1));
1549
+ return;
1550
+ }
1551
+ if (event.key === "ArrowUp") {
1552
+ event.preventDefault();
1553
+ setHighlightedIndex((index) => nextHighlightedIndex(index, filtered.length, -1));
1554
+ return;
1555
+ }
1556
+ if (event.key === "Enter") {
1557
+ const selected = filtered[highlightedIndex];
1558
+ if (!selected) return;
1559
+ event.preventDefault();
1560
+ onSelect(selected);
1561
+ return;
1562
+ }
1563
+ if (event.key === "Escape") {
1564
+ event.preventDefault();
1565
+ onClose();
1566
+ }
1567
+ },
1568
+ [filtered, highlightedIndex, onSelect, onClose]
1569
+ );
1570
+ return { items: filtered, isLoading, hasError, highlightedIndex, setHighlightedIndex, handleKeyDown, refetch };
1571
+ }
1572
+
1573
+ // src/quickReplies/quickReplyShortcut.ts
1574
+ var QUICK_REPLY_SHORTCUT_PATTERN = /(?:^|\s)\/([a-z0-9-]*)$/i;
1575
+ function detectQuickReplyShortcut(text) {
1576
+ const match = QUICK_REPLY_SHORTCUT_PATTERN.exec(text);
1577
+ if (!match) return void 0;
1578
+ return { start: match.index + (match[0].startsWith("/") ? 0 : 1), term: match[1] ?? "" };
1579
+ }
1580
+ function replaceQuickReplyShortcut({
1581
+ text,
1582
+ start,
1583
+ caret,
1584
+ replacement
1585
+ }) {
1586
+ return {
1587
+ text: text.slice(0, start) + replacement + text.slice(caret),
1588
+ caret: start + replacement.length
1589
+ };
1590
+ }
1591
+
1312
1592
  // src/MessageComposer.tsx
1313
- import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
1593
+ import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1314
1594
  function applyQuickReplyVariables(template, variables = {}) {
1315
1595
  return template.replace(/\{\{\s*([\w.]+)\s*\}\}/g, (_, chave) => variables[chave] ?? "");
1316
1596
  }
@@ -1321,7 +1601,8 @@ var DEFAULT_MESSAGE_COMPOSER_LABELS = {
1321
1601
  emoji: "Emoji",
1322
1602
  attach: "Anexar",
1323
1603
  send: "Enviar",
1324
- removeAttachment: "Remover anexo"
1604
+ removeAttachment: "Remover anexo",
1605
+ quickReplies: "Mensagens prontas"
1325
1606
  };
1326
1607
  var DEFAULT_ACCEPTED_FILE_TYPES = [
1327
1608
  "image/jpeg,image/png,image/webp",
@@ -1340,6 +1621,7 @@ var MessageComposer = ({
1340
1621
  onChange: externalOnChange,
1341
1622
  quickReplies,
1342
1623
  quickReplyVariables,
1624
+ savedQuickReplies,
1343
1625
  features,
1344
1626
  placeholder = "Digite uma mensagem...",
1345
1627
  maxLength,
@@ -1354,23 +1636,124 @@ var MessageComposer = ({
1354
1636
  const attachLabel = labels?.attach ?? DEFAULT_MESSAGE_COMPOSER_LABELS.attach;
1355
1637
  const sendLabel = labels?.send ?? DEFAULT_MESSAGE_COMPOSER_LABELS.send;
1356
1638
  const removeAttachmentLabel = labels?.removeAttachment ?? DEFAULT_MESSAGE_COMPOSER_LABELS.removeAttachment;
1357
- const [internalText, setInternalText] = useState8("");
1358
- const [showEmoji, setShowEmoji] = useState8(false);
1359
- const [attachments, setAttachments] = useState8([]);
1360
- const textareaRef = useRef3(null);
1361
- const fileInputRef = useRef3(null);
1639
+ const quickRepliesLabel = labels?.quickReplies ?? DEFAULT_MESSAGE_COMPOSER_LABELS.quickReplies;
1640
+ const [internalText, setInternalText] = useState9("");
1641
+ const [showEmoji, setShowEmoji] = useState9(false);
1642
+ const [attachments, setAttachments] = useState9([]);
1643
+ const textareaRef = useRef5(null);
1644
+ const fileInputRef = useRef5(null);
1645
+ const quickRepliesListboxId = useId();
1646
+ const [isQuickRepliesOpen, setIsQuickRepliesOpen] = useState9(false);
1647
+ const [quickRepliesTerm, setQuickRepliesTerm] = useState9("");
1648
+ const [shortcutStart, setShortcutStart] = useState9(null);
1649
+ const [quickRepliesMode, setQuickRepliesMode] = useState9("shortcut");
1650
+ const [caretPosition, setCaretPosition] = useState9(0);
1651
+ const quickRepliesPopoverRef = useRef5(null);
1652
+ const quickRepliesTriggerRef = useRef5(null);
1362
1653
  const isControlled = externalValue !== void 0;
1363
1654
  const text = isControlled ? externalValue : internalText;
1364
- const setText = useCallback4((newText) => {
1365
- if (isControlled) {
1366
- externalOnChange?.(newText);
1367
- } else {
1368
- setInternalText(newText);
1369
- }
1370
- }, [isControlled, externalOnChange]);
1655
+ const setText = useCallback5(
1656
+ (newText) => {
1657
+ if (isControlled) {
1658
+ externalOnChange?.(newText);
1659
+ } else {
1660
+ setInternalText(newText);
1661
+ }
1662
+ },
1663
+ [isControlled, externalOnChange]
1664
+ );
1371
1665
  const showEmojiButton = features?.emoji !== false;
1372
1666
  const showAttachButton = features?.documents !== false;
1373
- const sendMessage = useCallback4(() => {
1667
+ const showQuickRepliesButton = Boolean(savedQuickReplies);
1668
+ useEffect5(() => {
1669
+ if (!showQuickRepliesButton || quickRepliesMode === "button") return;
1670
+ const match = detectQuickReplyShortcut(text.slice(0, caretPosition));
1671
+ setIsQuickRepliesOpen(Boolean(match));
1672
+ setQuickRepliesTerm(match?.term ?? "");
1673
+ setShortcutStart(match?.start ?? null);
1674
+ }, [text, caretPosition, showQuickRepliesButton, quickRepliesMode]);
1675
+ useEffect5(() => {
1676
+ if (!showQuickRepliesButton) setIsQuickRepliesOpen(false);
1677
+ }, [showQuickRepliesButton]);
1678
+ const closeQuickReplies = useCallback5(() => {
1679
+ setIsQuickRepliesOpen(false);
1680
+ setShortcutStart(null);
1681
+ setQuickRepliesTerm("");
1682
+ setQuickRepliesMode("shortcut");
1683
+ }, []);
1684
+ const closeQuickRepliesAndRefocus = useCallback5(() => {
1685
+ closeQuickReplies();
1686
+ textareaRef.current?.focus();
1687
+ }, [closeQuickReplies]);
1688
+ const trackCaret = useCallback5((event) => {
1689
+ setCaretPosition(event.currentTarget.selectionStart);
1690
+ }, []);
1691
+ const insertSavedQuickReply = useCallback5(
1692
+ (quickReply) => {
1693
+ savedQuickReplies?.onSelect?.(quickReply);
1694
+ const ta = textareaRef.current;
1695
+ if (!ta) return;
1696
+ const resolvedBody = applyQuickReplyVariables(quickReply.body, savedQuickReplies?.variables);
1697
+ if (quickRepliesMode === "button") {
1698
+ const start = ta.selectionStart;
1699
+ const end = ta.selectionEnd;
1700
+ const newText2 = text.slice(0, start) + resolvedBody + text.slice(end);
1701
+ setText(newText2);
1702
+ closeQuickReplies();
1703
+ requestAnimationFrame(() => {
1704
+ ta.focus();
1705
+ const caret2 = start + resolvedBody.length;
1706
+ ta.setSelectionRange(caret2, caret2);
1707
+ });
1708
+ return;
1709
+ }
1710
+ if (shortcutStart === null) return;
1711
+ const shortcutEnd = shortcutStart + 1 + quickRepliesTerm.length;
1712
+ const { text: newText, caret } = replaceQuickReplyShortcut({
1713
+ text,
1714
+ start: shortcutStart,
1715
+ caret: shortcutEnd,
1716
+ replacement: resolvedBody
1717
+ });
1718
+ setText(newText);
1719
+ closeQuickReplies();
1720
+ requestAnimationFrame(() => {
1721
+ ta.focus();
1722
+ ta.setSelectionRange(caret, caret);
1723
+ });
1724
+ },
1725
+ [text, setText, shortcutStart, quickRepliesTerm, quickRepliesMode, savedQuickReplies, closeQuickReplies]
1726
+ );
1727
+ const quickRepliesPicker = useQuickRepliesPicker({
1728
+ isOpen: isQuickRepliesOpen,
1729
+ search: quickRepliesTerm,
1730
+ listQuickReplies: savedQuickReplies?.listQuickReplies,
1731
+ quickReplyVariables: savedQuickReplies?.variables,
1732
+ onSelect: insertSavedQuickReply,
1733
+ onClose: closeQuickRepliesAndRefocus
1734
+ });
1735
+ const openQuickRepliesViaButton = useCallback5(() => {
1736
+ if (isQuickRepliesOpen && quickRepliesMode === "button") {
1737
+ closeQuickRepliesAndRefocus();
1738
+ return;
1739
+ }
1740
+ setQuickRepliesMode("button");
1741
+ setQuickRepliesTerm("");
1742
+ setShortcutStart(null);
1743
+ setIsQuickRepliesOpen(true);
1744
+ }, [isQuickRepliesOpen, quickRepliesMode, closeQuickRepliesAndRefocus]);
1745
+ useEffect5(() => {
1746
+ if (!isQuickRepliesOpen || quickRepliesMode !== "button") return;
1747
+ const handleOutsideClick = (event) => {
1748
+ const target = event.target;
1749
+ if (quickRepliesPopoverRef.current?.contains(target)) return;
1750
+ if (quickRepliesTriggerRef.current?.contains(target)) return;
1751
+ closeQuickRepliesAndRefocus();
1752
+ };
1753
+ document.addEventListener("mousedown", handleOutsideClick);
1754
+ return () => document.removeEventListener("mousedown", handleOutsideClick);
1755
+ }, [isQuickRepliesOpen, quickRepliesMode, closeQuickRepliesAndRefocus]);
1756
+ const sendMessage = useCallback5(() => {
1374
1757
  const trimmed = text.trim();
1375
1758
  if (!trimmed && attachments.length === 0) return;
1376
1759
  if (trimmed) onSend(trimmed);
@@ -1383,35 +1766,45 @@ var MessageComposer = ({
1383
1766
  setShowEmoji(false);
1384
1767
  if (textareaRef.current) textareaRef.current.style.height = "auto";
1385
1768
  }, [text, attachments, onSend, onAttach, isControlled]);
1386
- const handleKeyDown = useCallback4((e) => {
1387
- if (e.key === "Enter" && !e.shiftKey) {
1388
- e.preventDefault();
1389
- if (!disabled) sendMessage();
1390
- }
1391
- }, [sendMessage, disabled]);
1392
- const handleInput = useCallback4(() => {
1769
+ const handleKeyDown = useCallback5(
1770
+ (e) => {
1771
+ if (isQuickRepliesOpen && quickRepliesMode === "shortcut") {
1772
+ quickRepliesPicker.handleKeyDown(e);
1773
+ return;
1774
+ }
1775
+ if (e.key === "Enter" && !e.shiftKey) {
1776
+ e.preventDefault();
1777
+ if (!disabled) sendMessage();
1778
+ }
1779
+ },
1780
+ [sendMessage, disabled, isQuickRepliesOpen, quickRepliesMode, quickRepliesPicker]
1781
+ );
1782
+ const handleInput = useCallback5(() => {
1393
1783
  const ta = textareaRef.current;
1394
1784
  if (!ta) return;
1395
1785
  ta.style.height = "auto";
1396
1786
  ta.style.height = `${Math.min(ta.scrollHeight, 100)}px`;
1397
1787
  }, []);
1398
- const handleEmojiSelect = useCallback4((emoji) => {
1399
- const ta = textareaRef.current;
1400
- if (!ta) {
1401
- setText(text + emoji);
1402
- return;
1403
- }
1404
- const start = ta.selectionStart;
1405
- const end = ta.selectionEnd;
1406
- const newText = text.slice(0, start) + emoji + text.slice(end);
1407
- setText(newText);
1408
- requestAnimationFrame(() => {
1409
- ta.focus();
1410
- ta.setSelectionRange(start + emoji.length, start + emoji.length);
1411
- handleInput();
1412
- });
1413
- }, [text, setText, handleInput]);
1414
- const handleFileChange = useCallback4((e) => {
1788
+ const handleEmojiSelect = useCallback5(
1789
+ (emoji) => {
1790
+ const ta = textareaRef.current;
1791
+ if (!ta) {
1792
+ setText(text + emoji);
1793
+ return;
1794
+ }
1795
+ const start = ta.selectionStart;
1796
+ const end = ta.selectionEnd;
1797
+ const newText = text.slice(0, start) + emoji + text.slice(end);
1798
+ setText(newText);
1799
+ requestAnimationFrame(() => {
1800
+ ta.focus();
1801
+ ta.setSelectionRange(start + emoji.length, start + emoji.length);
1802
+ handleInput();
1803
+ });
1804
+ },
1805
+ [text, setText, handleInput]
1806
+ );
1807
+ const handleFileChange = useCallback5((e) => {
1415
1808
  const files = e.target.files;
1416
1809
  if (!files) return;
1417
1810
  const previews = [];
@@ -1422,7 +1815,7 @@ var MessageComposer = ({
1422
1815
  setAttachments((prev) => [...prev, ...previews]);
1423
1816
  if (fileInputRef.current) fileInputRef.current.value = "";
1424
1817
  }, []);
1425
- const removeAttachment = useCallback4((index) => {
1818
+ const removeAttachment = useCallback5((index) => {
1426
1819
  setAttachments((prev) => {
1427
1820
  const next = [...prev];
1428
1821
  if (next[index].previewUrl) URL.revokeObjectURL(next[index].previewUrl);
@@ -1430,36 +1823,22 @@ var MessageComposer = ({
1430
1823
  return next;
1431
1824
  });
1432
1825
  }, []);
1433
- const insertFormatting = useCallback4((marker) => {
1434
- const ta = textareaRef.current;
1435
- if (!ta) return;
1436
- const start = ta.selectionStart;
1437
- const end = ta.selectionEnd;
1438
- const sel = text.slice(start, end);
1439
- if (sel) {
1440
- setText(text.slice(0, start) + marker + sel + marker + text.slice(end));
1441
- requestAnimationFrame(() => {
1442
- ta.focus();
1443
- ta.setSelectionRange(start + marker.length + sel.length + marker.length, start + marker.length + sel.length + marker.length);
1444
- });
1445
- }
1446
- }, [text, setText]);
1447
- const effectiveIdleAction = idleAction ?? (onAttach ? /* @__PURE__ */ jsx14(AudioRecorderButton, { onRecorded: (file) => onAttach(file) }) : void 0);
1826
+ const effectiveIdleAction = idleAction ?? (onAttach ? /* @__PURE__ */ jsx15(AudioRecorderButton, { onRecorded: (file) => onAttach(file) }) : void 0);
1448
1827
  const canSend = text.trim().length > 0 || attachments.length > 0;
1449
1828
  const remaining = maxLength ? maxLength - text.length : null;
1450
1829
  return (
1451
1830
  /* A barra é a superfície (cinza, largura cheia, sem raio) e o campo dentro é que arredonda —
1452
1831
  ordem do WhatsApp. Invertido, o pill arredondado ia até a borda da tela e os cantos
1453
1832
  descobriam o fundo branco da página, que lia como defeito. */
1454
- /* @__PURE__ */ jsxs10("div", { className: cn(COMPOSER_BAR_CLASS, className), children: [
1455
- quickReplies && quickReplies.length > 0 && /* @__PURE__ */ jsx14(
1833
+ /* @__PURE__ */ jsxs11("div", { className: cn(COMPOSER_BAR_CLASS, className), children: [
1834
+ quickReplies && quickReplies.length > 0 && /* @__PURE__ */ jsx15(
1456
1835
  "div",
1457
1836
  {
1458
1837
  className: cn(
1459
1838
  "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",
1460
1839
  classNames?.quickReplies
1461
1840
  ),
1462
- children: quickReplies.map((quickReply) => /* @__PURE__ */ jsx14(
1841
+ children: quickReplies.map((quickReply) => /* @__PURE__ */ jsx15(
1463
1842
  "button",
1464
1843
  {
1465
1844
  "data-cv-tooltip": quickReply.label,
@@ -1476,45 +1855,127 @@ var MessageComposer = ({
1476
1855
  ))
1477
1856
  }
1478
1857
  ),
1479
- 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: [
1480
- 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: [
1481
- /* @__PURE__ */ jsx14("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1482
- /* @__PURE__ */ jsx14("polyline", { points: "14 2 14 8 20 8" })
1858
+ attachments.length > 0 && /* @__PURE__ */ jsx15("div", { className: "flex gap-2 px-1 pb-2 overflow-x-auto", children: attachments.map((a, i) => /* @__PURE__ */ jsxs11("div", { className: "relative flex-shrink-0", children: [
1859
+ a.previewUrl ? /* @__PURE__ */ jsx15("img", { src: a.previewUrl, alt: "", className: "w-16 h-16 object-cover rounded-lg border border-gray-200" }) : /* @__PURE__ */ jsx15("div", { className: "w-16 h-16 bg-gray-100 rounded-lg border border-gray-200 flex items-center justify-center", children: /* @__PURE__ */ jsxs11("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#9ca3af", strokeWidth: "1.5", children: [
1860
+ /* @__PURE__ */ jsx15("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1861
+ /* @__PURE__ */ jsx15("polyline", { points: "14 2 14 8 20 8" })
1483
1862
  ] }) }),
1484
- /* @__PURE__ */ jsx14("button", { "data-cv-tooltip": removeAttachmentLabel, "aria-label": removeAttachmentLabel, 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" })
1863
+ /* @__PURE__ */ jsx15(
1864
+ "button",
1865
+ {
1866
+ "data-cv-tooltip": removeAttachmentLabel,
1867
+ "aria-label": removeAttachmentLabel,
1868
+ onClick: () => removeAttachment(i),
1869
+ 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",
1870
+ children: "\u2715"
1871
+ }
1872
+ )
1485
1873
  ] }, i)) }),
1486
- /* @__PURE__ */ jsxs10("div", { className: cn("flex items-end gap-1.5 rounded-xl bg-white px-3 py-2", classNames?.field), children: [
1487
- showEmojiButton && /* @__PURE__ */ jsxs10("div", { className: "relative flex-shrink-0", children: [
1488
- /* @__PURE__ */ jsx14("button", { "data-cv-tooltip": emojiLabel, 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: [
1489
- /* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "10" }),
1490
- /* @__PURE__ */ jsx14("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }),
1491
- /* @__PURE__ */ jsx14("circle", { cx: "9", cy: "9", r: "0.5", fill: "currentColor" }),
1492
- /* @__PURE__ */ jsx14("circle", { cx: "15", cy: "9", r: "0.5", fill: "currentColor" })
1493
- ] }) }),
1494
- showEmoji && /* @__PURE__ */ jsx14("div", { className: "absolute bottom-full left-0 mb-2 z-10", children: /* @__PURE__ */ jsx14(EmojiPicker, { onSelect: handleEmojiSelect }) })
1874
+ /* @__PURE__ */ jsxs11("div", { className: cn("flex items-end gap-1.5 rounded-xl bg-white px-3 py-2", classNames?.field), children: [
1875
+ showEmojiButton && /* @__PURE__ */ jsxs11("div", { className: "relative flex-shrink-0", children: [
1876
+ /* @__PURE__ */ jsx15(
1877
+ "button",
1878
+ {
1879
+ "data-cv-tooltip": emojiLabel,
1880
+ onClick: () => setShowEmoji((v) => !v),
1881
+ className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 transition-colors",
1882
+ "aria-label": emojiLabel,
1883
+ children: /* @__PURE__ */ jsxs11("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
1884
+ /* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "10" }),
1885
+ /* @__PURE__ */ jsx15("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }),
1886
+ /* @__PURE__ */ jsx15("circle", { cx: "9", cy: "9", r: "0.5", fill: "currentColor" }),
1887
+ /* @__PURE__ */ jsx15("circle", { cx: "15", cy: "9", r: "0.5", fill: "currentColor" })
1888
+ ] })
1889
+ }
1890
+ ),
1891
+ showEmoji && /* @__PURE__ */ jsx15("div", { className: "absolute bottom-full left-0 mb-2 z-10", children: /* @__PURE__ */ jsx15(EmojiPicker, { onSelect: handleEmojiSelect }) })
1495
1892
  ] }),
1496
- /* @__PURE__ */ jsx14(
1497
- "textarea",
1498
- {
1499
- ref: textareaRef,
1500
- value: text,
1501
- onChange: (e) => {
1502
- setText(e.target.value);
1503
- handleInput();
1893
+ /* @__PURE__ */ jsxs11("div", { className: "relative flex-1", children: [
1894
+ /* @__PURE__ */ jsx15(
1895
+ "textarea",
1896
+ {
1897
+ ref: textareaRef,
1898
+ value: text,
1899
+ onChange: (e) => {
1900
+ setText(e.target.value);
1901
+ setCaretPosition(e.target.selectionStart);
1902
+ handleInput();
1903
+ },
1904
+ onKeyDown: handleKeyDown,
1905
+ onKeyUp: trackCaret,
1906
+ onClick: trackCaret,
1907
+ onSelect: trackCaret,
1908
+ placeholder,
1909
+ rows: 1,
1910
+ disabled,
1911
+ role: showQuickRepliesButton ? "combobox" : void 0,
1912
+ "aria-expanded": showQuickRepliesButton ? isQuickRepliesOpen : void 0,
1913
+ "aria-controls": showQuickRepliesButton ? quickRepliesListboxId : void 0,
1914
+ "aria-activedescendant": isQuickRepliesOpen && quickRepliesMode === "shortcut" ? `${quickRepliesListboxId}-option-${quickRepliesPicker.highlightedIndex}` : void 0,
1915
+ className: "w-full resize-none bg-transparent text-[15px] text-[#3b4a54] placeholder-[#8696a0] outline-none py-1.5 max-h-[100px] leading-relaxed",
1916
+ style: { fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" }
1917
+ }
1918
+ ),
1919
+ isQuickRepliesOpen && /* @__PURE__ */ jsx15("div", { ref: quickRepliesPopoverRef, className: "absolute bottom-full left-0 mb-2 z-10", children: /* @__PURE__ */ jsx15(
1920
+ QuickRepliesPicker,
1921
+ {
1922
+ id: quickRepliesListboxId,
1923
+ items: quickRepliesPicker.items,
1924
+ search: quickRepliesTerm,
1925
+ highlightedIndex: quickRepliesPicker.highlightedIndex,
1926
+ isLoading: quickRepliesPicker.isLoading,
1927
+ hasError: quickRepliesPicker.hasError,
1928
+ onHover: quickRepliesPicker.setHighlightedIndex,
1929
+ onSelect: insertSavedQuickReply,
1930
+ labels: savedQuickReplies?.labels,
1931
+ variables: savedQuickReplies?.variables,
1932
+ hasAttachmentsCapability: savedQuickReplies?.hasAttachmentsCapability,
1933
+ ownSearch: quickRepliesMode === "button" ? {
1934
+ value: quickRepliesTerm,
1935
+ onChange: setQuickRepliesTerm,
1936
+ onKeyDown: quickRepliesPicker.handleKeyDown,
1937
+ label: quickRepliesLabel
1938
+ } : void 0
1504
1939
  },
1505
- onKeyDown: handleKeyDown,
1506
- placeholder,
1507
- rows: 1,
1508
- disabled,
1509
- className: "flex-1 resize-none bg-transparent text-[15px] text-[#3b4a54] placeholder-[#8696a0] outline-none py-1.5 max-h-[100px] leading-relaxed",
1510
- style: { fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif" }
1940
+ quickRepliesMode
1941
+ ) })
1942
+ ] }),
1943
+ showQuickRepliesButton && /* @__PURE__ */ jsx15(
1944
+ "button",
1945
+ {
1946
+ ref: quickRepliesTriggerRef,
1947
+ type: "button",
1948
+ "data-cv-tooltip": quickRepliesLabel,
1949
+ "aria-label": quickRepliesLabel,
1950
+ onClick: openQuickRepliesViaButton,
1951
+ className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 flex-shrink-0 transition-colors",
1952
+ children: /* @__PURE__ */ jsx15("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx15("polygon", { points: "13 2 3 14 12 14 11 22 21 10 12 10 13 2" }) })
1511
1953
  }
1512
1954
  ),
1513
- showAttachButton && /* @__PURE__ */ jsxs10(Fragment3, { children: [
1514
- /* @__PURE__ */ jsx14("input", { ref: fileInputRef, type: "file", multiple: true, accept: acceptedFileTypes, onChange: handleFileChange, className: "hidden" }),
1515
- /* @__PURE__ */ jsx14("button", { "data-cv-tooltip": attachLabel, 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" }) }) })
1955
+ showAttachButton && /* @__PURE__ */ jsxs11(Fragment3, { children: [
1956
+ /* @__PURE__ */ jsx15(
1957
+ "input",
1958
+ {
1959
+ ref: fileInputRef,
1960
+ type: "file",
1961
+ multiple: true,
1962
+ accept: acceptedFileTypes,
1963
+ onChange: handleFileChange,
1964
+ className: "hidden"
1965
+ }
1966
+ ),
1967
+ /* @__PURE__ */ jsx15(
1968
+ "button",
1969
+ {
1970
+ "data-cv-tooltip": attachLabel,
1971
+ onClick: () => fileInputRef.current?.click(),
1972
+ className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 flex-shrink-0 transition-colors",
1973
+ "aria-label": attachLabel,
1974
+ children: /* @__PURE__ */ jsx15("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx15("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" }) })
1975
+ }
1976
+ )
1516
1977
  ] }),
1517
- !canSend && effectiveIdleAction ? /* @__PURE__ */ jsx14("div", { className: "flex-shrink-0", children: effectiveIdleAction }) : /* @__PURE__ */ jsx14(
1978
+ !canSend && effectiveIdleAction ? /* @__PURE__ */ jsx15("div", { className: "flex-shrink-0", children: effectiveIdleAction }) : /* @__PURE__ */ jsx15(
1518
1979
  "button",
1519
1980
  {
1520
1981
  "data-cv-tooltip": sendLabel,
@@ -1522,20 +1983,76 @@ var MessageComposer = ({
1522
1983
  disabled: !canSend || disabled,
1523
1984
  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"}`,
1524
1985
  "aria-label": sendLabel,
1525
- 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" }) })
1986
+ children: /* @__PURE__ */ jsx15("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx15("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) })
1526
1987
  }
1527
1988
  )
1528
1989
  ] }),
1529
- 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 }) })
1990
+ remaining !== null && /* @__PURE__ */ jsx15("div", { className: "flex justify-end mt-1 pr-1", children: /* @__PURE__ */ jsx15("span", { className: `text-xs ${remaining < 20 ? "text-red-500" : "text-gray-400"}`, children: remaining }) })
1530
1991
  ] })
1531
1992
  );
1532
1993
  };
1533
1994
 
1995
+ // src/quickReplies/quickReplySearch.ts
1996
+ var DIACRITIC_PATTERN = /[\u0300-\u036f]/g;
1997
+ function normalizeForSearchWithMap(value) {
1998
+ let normalized = "";
1999
+ const originalIndexOf = [];
2000
+ let originalCursor = 0;
2001
+ for (const char of value) {
2002
+ const piece = char.normalize("NFD").replace(DIACRITIC_PATTERN, "").toLowerCase();
2003
+ for (let i = 0; i < piece.length; i++) originalIndexOf.push(originalCursor);
2004
+ normalized += piece;
2005
+ originalCursor += char.length;
2006
+ }
2007
+ return { normalized, originalIndexOf };
2008
+ }
2009
+ function normalizeForSearch(value) {
2010
+ return normalizeForSearchWithMap(value).normalized;
2011
+ }
2012
+ function filterQuickReplies({
2013
+ quickReplies,
2014
+ search,
2015
+ variables
2016
+ }) {
2017
+ const term = normalizeForSearch(search.trim());
2018
+ if (!term) return quickReplies;
2019
+ return quickReplies.filter((quickReply) => {
2020
+ const body = applyQuickReplyVariables(quickReply.body, variables);
2021
+ return normalizeForSearch(quickReply.title).includes(term) || normalizeForSearch(quickReply.shortcut).includes(term) || normalizeForSearch(body).includes(term);
2022
+ });
2023
+ }
2024
+ function highlightMatch(text, search) {
2025
+ const term = search.trim();
2026
+ if (!term) return [{ text, isMatch: false }];
2027
+ const { normalized: normalizedText, originalIndexOf } = normalizeForSearchWithMap(text);
2028
+ const normalizedTerm = normalizeForSearch(term);
2029
+ if (!normalizedTerm) return [{ text, isMatch: false }];
2030
+ const originalIndexAt = (normalizedIndex) => normalizedIndex < originalIndexOf.length ? originalIndexOf[normalizedIndex] : text.length;
2031
+ const segments = [];
2032
+ let normalizedCursor = 0;
2033
+ let originalCursor = 0;
2034
+ while (normalizedCursor < normalizedText.length) {
2035
+ const matchIndex = normalizedText.indexOf(normalizedTerm, normalizedCursor);
2036
+ if (matchIndex === -1) break;
2037
+ const matchOriginalStart = originalIndexAt(matchIndex);
2038
+ if (matchOriginalStart > originalCursor) {
2039
+ segments.push({ text: text.slice(originalCursor, matchOriginalStart), isMatch: false });
2040
+ }
2041
+ const matchNormalizedEnd = matchIndex + normalizedTerm.length;
2042
+ const matchOriginalEnd = originalIndexAt(matchNormalizedEnd);
2043
+ segments.push({ text: text.slice(matchOriginalStart, matchOriginalEnd), isMatch: true });
2044
+ normalizedCursor = matchNormalizedEnd;
2045
+ originalCursor = matchOriginalEnd;
2046
+ }
2047
+ if (originalCursor < text.length) segments.push({ text: text.slice(originalCursor), isMatch: false });
2048
+ return segments;
2049
+ }
2050
+
1534
2051
  // src/DateDivider.tsx
1535
- import { jsx as jsx15 } from "react/jsx-runtime";
2052
+ import { jsx as jsx16 } from "react/jsx-runtime";
1536
2053
  function DateDivider({ iso, className, classNames }) {
1537
2054
  const { dateDivider } = useConversationLocales();
1538
- 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(
2055
+ return /* @__PURE__ */ jsx16("div", { className: cn("flex justify-center sticky top-0 z-10 my-2 pointer-events-none", classNames?.root, className), children: /* @__PURE__ */ jsx16(
1539
2056
  "span",
1540
2057
  {
1541
2058
  className: cn(
@@ -1681,13 +2198,13 @@ function contactFlag(params) {
1681
2198
  }
1682
2199
 
1683
2200
  // src/hooks/useAsyncResource.ts
1684
- import { useCallback as useCallback5, useEffect as useEffect3, useRef as useRef4, useState as useState9 } from "react";
2201
+ import { useCallback as useCallback6, useEffect as useEffect6, useRef as useRef6, useState as useState10 } from "react";
1685
2202
  function useAsyncResource(fetcher, deps) {
1686
- const [data, setData] = useState9(void 0);
1687
- const [loading, setLoading] = useState9(false);
1688
- const [error, setError] = useState9(void 0);
1689
- const requestIdRef = useRef4(0);
1690
- const load = useCallback5(async () => {
2203
+ const [data, setData] = useState10(void 0);
2204
+ const [loading, setLoading] = useState10(false);
2205
+ const [error, setError] = useState10(void 0);
2206
+ const requestIdRef = useRef6(0);
2207
+ const load = useCallback6(async () => {
1691
2208
  const requestId = ++requestIdRef.current;
1692
2209
  setLoading(true);
1693
2210
  setError(void 0);
@@ -1700,7 +2217,7 @@ function useAsyncResource(fetcher, deps) {
1700
2217
  if (requestId === requestIdRef.current) setLoading(false);
1701
2218
  }
1702
2219
  }, deps);
1703
- useEffect3(() => {
2220
+ useEffect6(() => {
1704
2221
  load();
1705
2222
  }, [load]);
1706
2223
  return { data, loading, error, refetch: load };
@@ -1735,7 +2252,7 @@ function useConversationDocuments(conversationId, params) {
1735
2252
  }
1736
2253
 
1737
2254
  // src/ConversationDocumentsPanel.tsx
1738
- import { useState as useState10 } from "react";
2255
+ import { useState as useState11 } from "react";
1739
2256
  import { ArrowUpDown, Bot, Download, Eye, Users } from "lucide-react";
1740
2257
 
1741
2258
  // src/pagination.constant.ts
@@ -1747,7 +2264,7 @@ var PAGINATION_LABELS = {
1747
2264
  };
1748
2265
 
1749
2266
  // src/ConversationDocumentsPanel.tsx
1750
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
2267
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
1751
2268
  var DOCUMENT_SOURCE_FILTER = {
1752
2269
  ALL: "all",
1753
2270
  CUSTOMER: "customer",
@@ -1787,12 +2304,12 @@ function ConversationDocumentsPanel({
1787
2304
  }) {
1788
2305
  const labels = { ...DEFAULT_CONVERSATION_DOCUMENTS_LABELS, ...labelsOverride };
1789
2306
  const context = useConversations();
1790
- const [search, setSearch] = useState10("");
1791
- const [sourceFilter, setSourceFilter] = useState10(DOCUMENT_SOURCE_FILTER.ALL);
1792
- const [sortDirection, setSortDirection] = useState10("desc");
1793
- const [page, setPage] = useState10(1);
1794
- const [selectedIds, setSelectedIds] = useState10([]);
1795
- const [archiveError, setArchiveError] = useState10(false);
2307
+ const [search, setSearch] = useState11("");
2308
+ const [sourceFilter, setSourceFilter] = useState11(DOCUMENT_SOURCE_FILTER.ALL);
2309
+ const [sortDirection, setSortDirection] = useState11("desc");
2310
+ const [page, setPage] = useState11(1);
2311
+ const [selectedIds, setSelectedIds] = useState11([]);
2312
+ const [archiveError, setArchiveError] = useState11(false);
1796
2313
  const hasFilters = search !== "" || sourceFilter !== DOCUMENT_SOURCE_FILTER.ALL || sortDirection !== "desc";
1797
2314
  const { documents, total, loading, error } = useConversationDocuments(open ? conversationId : void 0, {
1798
2315
  search,
@@ -1843,10 +2360,10 @@ function ConversationDocumentsPanel({
1843
2360
  }
1844
2361
  }
1845
2362
  if (!open) return null;
1846
- return /* @__PURE__ */ jsx16("div", { className: cn("border-b", classNames?.root, className), children: /* @__PURE__ */ jsxs11("section", { className: cn("px-4 py-3", classNames?.body), children: [
1847
- /* @__PURE__ */ jsx16("p", { className: cn("mb-2 text-sm font-medium", classNames?.title), children: labels.title }),
1848
- /* @__PURE__ */ jsxs11("div", { className: cn("mb-2 flex flex-wrap items-center gap-2 border-b pb-2", classNames?.filters), children: [
1849
- /* @__PURE__ */ jsx16(
2363
+ return /* @__PURE__ */ jsx17("div", { className: cn("border-b", classNames?.root, className), children: /* @__PURE__ */ jsxs12("section", { className: cn("px-4 py-3", classNames?.body), children: [
2364
+ /* @__PURE__ */ jsx17("p", { className: cn("mb-2 text-sm font-medium", classNames?.title), children: labels.title }),
2365
+ /* @__PURE__ */ jsxs12("div", { className: cn("mb-2 flex flex-wrap items-center gap-2 border-b pb-2", classNames?.filters), children: [
2366
+ /* @__PURE__ */ jsx17(
1850
2367
  "input",
1851
2368
  {
1852
2369
  type: "search",
@@ -1857,7 +2374,7 @@ function ConversationDocumentsPanel({
1857
2374
  className: cn("w-full rounded-md border px-3 py-2 text-sm sm:w-52", classNames?.search)
1858
2375
  }
1859
2376
  ),
1860
- /* @__PURE__ */ jsxs11(
2377
+ /* @__PURE__ */ jsxs12(
1861
2378
  "select",
1862
2379
  {
1863
2380
  value: sourceFilter,
@@ -1865,13 +2382,13 @@ function ConversationDocumentsPanel({
1865
2382
  "aria-label": labels.sourceFilterAll,
1866
2383
  className: cn("w-full rounded-md border px-2 py-2 text-sm sm:w-36", classNames?.sourceSelect),
1867
2384
  children: [
1868
- /* @__PURE__ */ jsx16("option", { value: DOCUMENT_SOURCE_FILTER.ALL, children: labels.sourceFilterAll }),
1869
- /* @__PURE__ */ jsx16("option", { value: DOCUMENT_SOURCE_FILTER.CUSTOMER, children: labels.sourceFilterCustomer }),
1870
- /* @__PURE__ */ jsx16("option", { value: DOCUMENT_SOURCE_FILTER.TEAM, children: labels.sourceFilterTeam })
2385
+ /* @__PURE__ */ jsx17("option", { value: DOCUMENT_SOURCE_FILTER.ALL, children: labels.sourceFilterAll }),
2386
+ /* @__PURE__ */ jsx17("option", { value: DOCUMENT_SOURCE_FILTER.CUSTOMER, children: labels.sourceFilterCustomer }),
2387
+ /* @__PURE__ */ jsx17("option", { value: DOCUMENT_SOURCE_FILTER.TEAM, children: labels.sourceFilterTeam })
1871
2388
  ]
1872
2389
  }
1873
2390
  ),
1874
- /* @__PURE__ */ jsxs11(
2391
+ /* @__PURE__ */ jsxs12(
1875
2392
  "button",
1876
2393
  {
1877
2394
  "data-cv-tooltip": sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest,
@@ -1880,12 +2397,12 @@ function ConversationDocumentsPanel({
1880
2397
  onClick: () => applyFilter(() => setSortDirection(sortDirection === "desc" ? "asc" : "desc")),
1881
2398
  className: cn("cv-header-action inline-flex items-center gap-1", classNames?.sortButton),
1882
2399
  children: [
1883
- /* @__PURE__ */ jsx16(ArrowUpDown, { size: 14 }),
2400
+ /* @__PURE__ */ jsx17(ArrowUpDown, { size: 14 }),
1884
2401
  sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest
1885
2402
  ]
1886
2403
  }
1887
2404
  ),
1888
- hasFilters ? /* @__PURE__ */ jsx16(
2405
+ hasFilters ? /* @__PURE__ */ jsx17(
1889
2406
  "button",
1890
2407
  {
1891
2408
  "data-cv-tooltip": labels.clearFilters,
@@ -1901,12 +2418,12 @@ function ConversationDocumentsPanel({
1901
2418
  }
1902
2419
  ) : null
1903
2420
  ] }),
1904
- loading ? /* @__PURE__ */ jsx16("p", { className: cn("text-xs text-gray-500", classNames?.status), children: labels.loading }) : null,
1905
- error ? /* @__PURE__ */ jsx16("p", { role: "alert", className: cn("text-xs text-red-600 dark:text-red-400", classNames?.status), children: labels.failure }) : null,
1906
- !loading && !error && documents.length === 0 ? /* @__PURE__ */ jsx16("p", { className: cn("text-xs text-gray-500", classNames?.status), children: hasFilters ? labels.noResults : labels.empty }) : null,
1907
- canArchive && documents.length > 0 ? /* @__PURE__ */ jsxs11("div", { className: cn("mb-2 flex flex-wrap items-center gap-3 text-xs", classNames?.selectionBar), children: [
1908
- /* @__PURE__ */ jsxs11("label", { className: "inline-flex items-center gap-1.5", children: [
1909
- /* @__PURE__ */ jsx16(
2421
+ loading ? /* @__PURE__ */ jsx17("p", { className: cn("text-xs text-gray-500", classNames?.status), children: labels.loading }) : null,
2422
+ error ? /* @__PURE__ */ jsx17("p", { role: "alert", className: cn("text-xs text-red-600 dark:text-red-400", classNames?.status), children: labels.failure }) : null,
2423
+ !loading && !error && documents.length === 0 ? /* @__PURE__ */ jsx17("p", { className: cn("text-xs text-gray-500", classNames?.status), children: hasFilters ? labels.noResults : labels.empty }) : null,
2424
+ canArchive && documents.length > 0 ? /* @__PURE__ */ jsxs12("div", { className: cn("mb-2 flex flex-wrap items-center gap-3 text-xs", classNames?.selectionBar), children: [
2425
+ /* @__PURE__ */ jsxs12("label", { className: "inline-flex items-center gap-1.5", children: [
2426
+ /* @__PURE__ */ jsx17(
1910
2427
  "input",
1911
2428
  {
1912
2429
  type: "checkbox",
@@ -1917,13 +2434,13 @@ function ConversationDocumentsPanel({
1917
2434
  ),
1918
2435
  labels.selectAll
1919
2436
  ] }),
1920
- selectedIds.length > 0 ? /* @__PURE__ */ jsx16("button", { "data-cv-tooltip": labels.downloadSelected(selectedIds.length), "aria-label": labels.downloadSelected(selectedIds.length), type: "button", onClick: () => void handleDownloadSelected(), className: "cv-header-action", children: labels.downloadSelected(selectedIds.length) }) : null,
1921
- archiveError ? /* @__PURE__ */ jsx16("span", { role: "alert", className: "text-red-600 dark:text-red-400", children: labels.archiveFailed }) : null
2437
+ selectedIds.length > 0 ? /* @__PURE__ */ jsx17("button", { "data-cv-tooltip": labels.downloadSelected(selectedIds.length), "aria-label": labels.downloadSelected(selectedIds.length), type: "button", onClick: () => void handleDownloadSelected(), className: "cv-header-action", children: labels.downloadSelected(selectedIds.length) }) : null,
2438
+ archiveError ? /* @__PURE__ */ jsx17("span", { role: "alert", className: "text-red-600 dark:text-red-400", children: labels.archiveFailed }) : null
1922
2439
  ] }) : null,
1923
- /* @__PURE__ */ jsx16("ul", { className: cn("space-y-2", classNames?.list), children: documents.map((document2) => {
2440
+ /* @__PURE__ */ jsx17("ul", { className: cn("space-y-2", classNames?.list), children: documents.map((document2) => {
1924
2441
  const isFromCustomer = !TEAM_SOURCES.has(document2.source);
1925
2442
  const SourceIcon = isFromCustomer ? Users : Bot;
1926
- return /* @__PURE__ */ jsxs11(
2443
+ return /* @__PURE__ */ jsxs12(
1927
2444
  "li",
1928
2445
  {
1929
2446
  className: cn(
@@ -1931,8 +2448,8 @@ function ConversationDocumentsPanel({
1931
2448
  classNames?.item
1932
2449
  ),
1933
2450
  children: [
1934
- /* @__PURE__ */ jsxs11("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
1935
- canArchive ? /* @__PURE__ */ jsx16(
2451
+ /* @__PURE__ */ jsxs12("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
2452
+ canArchive ? /* @__PURE__ */ jsx17(
1936
2453
  "input",
1937
2454
  {
1938
2455
  type: "checkbox",
@@ -1942,9 +2459,9 @@ function ConversationDocumentsPanel({
1942
2459
  className: cn("shrink-0", classNames?.checkbox)
1943
2460
  }
1944
2461
  ) : null,
1945
- /* @__PURE__ */ jsx16(FileIcon, { filename: document2.filename, mimeType: document2.mimeType }),
1946
- /* @__PURE__ */ jsxs11("div", { className: "min-w-0 flex-1", children: [
1947
- /* @__PURE__ */ jsxs11(
2462
+ /* @__PURE__ */ jsx17(FileIcon, { filename: document2.filename, mimeType: document2.mimeType }),
2463
+ /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
2464
+ /* @__PURE__ */ jsxs12(
1948
2465
  "div",
1949
2466
  {
1950
2467
  className: cn(
@@ -1953,12 +2470,12 @@ function ConversationDocumentsPanel({
1953
2470
  classNames?.sourceBadge
1954
2471
  ),
1955
2472
  children: [
1956
- /* @__PURE__ */ jsx16(SourceIcon, { size: 11 }),
2473
+ /* @__PURE__ */ jsx17(SourceIcon, { size: 11 }),
1957
2474
  isFromCustomer ? labels.sourceFilterCustomer : labels.sourceFilterTeam
1958
2475
  ]
1959
2476
  }
1960
2477
  ),
1961
- /* @__PURE__ */ jsx16(
2478
+ /* @__PURE__ */ jsx17(
1962
2479
  "div",
1963
2480
  {
1964
2481
  className: cn("truncate text-sm font-medium", classNames?.filename),
@@ -1966,15 +2483,15 @@ function ConversationDocumentsPanel({
1966
2483
  children: document2.filename
1967
2484
  }
1968
2485
  ),
1969
- /* @__PURE__ */ jsxs11("div", { className: cn("text-xs text-gray-500 dark:text-gray-400", classNames?.meta), children: [
2486
+ /* @__PURE__ */ jsxs12("div", { className: cn("text-xs text-gray-500 dark:text-gray-400", classNames?.meta), children: [
1970
2487
  formatDateTime(document2.linkedAt),
1971
2488
  " \xB7 ",
1972
2489
  formatFileSize(document2.sizeBytes)
1973
2490
  ] })
1974
2491
  ] })
1975
2492
  ] }),
1976
- /* @__PURE__ */ jsxs11("div", { className: "flex shrink-0 gap-1", children: [
1977
- /* @__PURE__ */ jsx16(
2493
+ /* @__PURE__ */ jsxs12("div", { className: "flex shrink-0 gap-1", children: [
2494
+ /* @__PURE__ */ jsx17(
1978
2495
  "button",
1979
2496
  {
1980
2497
  type: "button",
@@ -1982,10 +2499,10 @@ function ConversationDocumentsPanel({
1982
2499
  "data-cv-tooltip": labels.view,
1983
2500
  "aria-label": `${labels.view}: ${document2.filename}`,
1984
2501
  className: cn("cv-header-icon", classNames?.viewButton),
1985
- children: /* @__PURE__ */ jsx16(Eye, { size: 14 })
2502
+ children: /* @__PURE__ */ jsx17(Eye, { size: 14 })
1986
2503
  }
1987
2504
  ),
1988
- /* @__PURE__ */ jsx16(
2505
+ /* @__PURE__ */ jsx17(
1989
2506
  "button",
1990
2507
  {
1991
2508
  type: "button",
@@ -1993,7 +2510,7 @@ function ConversationDocumentsPanel({
1993
2510
  "data-cv-tooltip": labels.download,
1994
2511
  "aria-label": `${labels.download}: ${document2.filename}`,
1995
2512
  className: cn("cv-header-icon", classNames?.downloadButton),
1996
- children: /* @__PURE__ */ jsx16(Download, { size: 14 })
2513
+ children: /* @__PURE__ */ jsx17(Download, { size: 14 })
1997
2514
  }
1998
2515
  )
1999
2516
  ] })
@@ -2002,7 +2519,7 @@ function ConversationDocumentsPanel({
2002
2519
  document2.id
2003
2520
  );
2004
2521
  }) }),
2005
- total > perPage ? /* @__PURE__ */ jsxs11(
2522
+ total > perPage ? /* @__PURE__ */ jsxs12(
2006
2523
  "div",
2007
2524
  {
2008
2525
  className: cn(
@@ -2010,9 +2527,9 @@ function ConversationDocumentsPanel({
2010
2527
  classNames?.pagination
2011
2528
  ),
2012
2529
  children: [
2013
- /* @__PURE__ */ jsx16("span", { className: "text-gray-400", children: labels.total(total) }),
2014
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
2015
- /* @__PURE__ */ jsx16(
2530
+ /* @__PURE__ */ jsx17("span", { className: "text-gray-400", children: labels.total(total) }),
2531
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
2532
+ /* @__PURE__ */ jsx17(
2016
2533
  "button",
2017
2534
  {
2018
2535
  type: "button",
@@ -2024,8 +2541,8 @@ function ConversationDocumentsPanel({
2024
2541
  children: "\u2039"
2025
2542
  }
2026
2543
  ),
2027
- /* @__PURE__ */ jsx16("span", { className: "text-gray-500", children: labels.page(page, lastPage) }),
2028
- /* @__PURE__ */ jsx16(
2544
+ /* @__PURE__ */ jsx17("span", { className: "text-gray-500", children: labels.page(page, lastPage) }),
2545
+ /* @__PURE__ */ jsx17(
2029
2546
  "button",
2030
2547
  {
2031
2548
  type: "button",
@@ -2045,9 +2562,9 @@ function ConversationDocumentsPanel({
2045
2562
  }
2046
2563
 
2047
2564
  // src/DocumentsLibrary.tsx
2048
- import { useEffect as useEffect4, useRef as useRef5, useState as useState11 } from "react";
2565
+ import { useEffect as useEffect7, useRef as useRef7, useState as useState12 } from "react";
2049
2566
  import { ArrowUpDown as ArrowUpDown2, Bot as Bot2, Download as Download2, Eye as Eye2, MessageSquare, Upload, Users as Users2 } from "lucide-react";
2050
- import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
2567
+ import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2051
2568
  var DEFAULT_DOCUMENTS_LIBRARY_LABELS = {
2052
2569
  title: "Documentos",
2053
2570
  searchPlaceholder: "Buscar por nome do arquivo ou telefone",
@@ -2080,23 +2597,23 @@ function DocumentsLibrary({
2080
2597
  }) {
2081
2598
  const labels = { ...DEFAULT_DOCUMENTS_LIBRARY_LABELS, ...labelsOverride };
2082
2599
  const context = useConversations();
2083
- const [search, setSearch] = useState11("");
2084
- const [sourceFilter, setSourceFilter] = useState11(DOCUMENT_SOURCE_FILTER.ALL);
2085
- const [sortDirection, setSortDirection] = useState11("desc");
2086
- const [page, setPage] = useState11(1);
2087
- const [documents, setDocuments] = useState11([]);
2088
- const [total, setTotal] = useState11(0);
2089
- const [loading, setLoading] = useState11(false);
2090
- const [failed, setFailed] = useState11(false);
2091
- const [uploading, setUploading] = useState11(false);
2092
- const [uploadFailed, setUploadFailed] = useState11(false);
2093
- const [reloadToken, setReloadToken] = useState11(0);
2094
- const fileInputRef = useRef5(null);
2600
+ const [search, setSearch] = useState12("");
2601
+ const [sourceFilter, setSourceFilter] = useState12(DOCUMENT_SOURCE_FILTER.ALL);
2602
+ const [sortDirection, setSortDirection] = useState12("desc");
2603
+ const [page, setPage] = useState12(1);
2604
+ const [documents, setDocuments] = useState12([]);
2605
+ const [total, setTotal] = useState12(0);
2606
+ const [loading, setLoading] = useState12(false);
2607
+ const [failed, setFailed] = useState12(false);
2608
+ const [uploading, setUploading] = useState12(false);
2609
+ const [uploadFailed, setUploadFailed] = useState12(false);
2610
+ const [reloadToken, setReloadToken] = useState12(0);
2611
+ const fileInputRef = useRef7(null);
2095
2612
  const hasFilters = search !== "" || sourceFilter !== DOCUMENT_SOURCE_FILTER.ALL || sortDirection !== "desc";
2096
2613
  const lastPage = Math.max(1, Math.ceil(total / perPage));
2097
2614
  const fetchAll = context?.api.getAllDocuments;
2098
2615
  const uploadDocument = context?.api.uploadDocument;
2099
- useEffect4(() => {
2616
+ useEffect7(() => {
2100
2617
  if (!fetchAll) return;
2101
2618
  let active = true;
2102
2619
  setLoading(true);
@@ -2142,10 +2659,10 @@ function DocumentsLibrary({
2142
2659
  }
2143
2660
  }
2144
2661
  if (!fetchAll) return null;
2145
- return /* @__PURE__ */ jsxs12("div", { className: cn("space-y-3", classNames?.root, className), children: [
2146
- /* @__PURE__ */ jsx17("h2", { className: cn("text-lg font-semibold", classNames?.title), children: labels.title }),
2147
- /* @__PURE__ */ jsxs12("div", { className: cn("flex flex-wrap items-center gap-2", classNames?.filters), children: [
2148
- /* @__PURE__ */ jsx17(
2662
+ return /* @__PURE__ */ jsxs13("div", { className: cn("space-y-3", classNames?.root, className), children: [
2663
+ /* @__PURE__ */ jsx18("h2", { className: cn("text-lg font-semibold", classNames?.title), children: labels.title }),
2664
+ /* @__PURE__ */ jsxs13("div", { className: cn("flex flex-wrap items-center gap-2", classNames?.filters), children: [
2665
+ /* @__PURE__ */ jsx18(
2149
2666
  "input",
2150
2667
  {
2151
2668
  type: "search",
@@ -2156,7 +2673,7 @@ function DocumentsLibrary({
2156
2673
  className: cn("w-full rounded-md border px-3 py-2 text-sm sm:w-64", classNames?.search)
2157
2674
  }
2158
2675
  ),
2159
- /* @__PURE__ */ jsxs12(
2676
+ /* @__PURE__ */ jsxs13(
2160
2677
  "select",
2161
2678
  {
2162
2679
  value: sourceFilter,
@@ -2164,13 +2681,13 @@ function DocumentsLibrary({
2164
2681
  "aria-label": labels.sourceFilterAll,
2165
2682
  className: cn("w-full rounded-md border px-2 py-2 text-sm sm:w-40", classNames?.sourceSelect),
2166
2683
  children: [
2167
- /* @__PURE__ */ jsx17("option", { value: DOCUMENT_SOURCE_FILTER.ALL, children: labels.sourceFilterAll }),
2168
- /* @__PURE__ */ jsx17("option", { value: DOCUMENT_SOURCE_FILTER.CUSTOMER, children: labels.sourceFilterCustomer }),
2169
- /* @__PURE__ */ jsx17("option", { value: DOCUMENT_SOURCE_FILTER.TEAM, children: labels.sourceFilterTeam })
2684
+ /* @__PURE__ */ jsx18("option", { value: DOCUMENT_SOURCE_FILTER.ALL, children: labels.sourceFilterAll }),
2685
+ /* @__PURE__ */ jsx18("option", { value: DOCUMENT_SOURCE_FILTER.CUSTOMER, children: labels.sourceFilterCustomer }),
2686
+ /* @__PURE__ */ jsx18("option", { value: DOCUMENT_SOURCE_FILTER.TEAM, children: labels.sourceFilterTeam })
2170
2687
  ]
2171
2688
  }
2172
2689
  ),
2173
- /* @__PURE__ */ jsxs12(
2690
+ /* @__PURE__ */ jsxs13(
2174
2691
  "button",
2175
2692
  {
2176
2693
  "data-cv-tooltip": sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest,
@@ -2179,12 +2696,12 @@ function DocumentsLibrary({
2179
2696
  onClick: () => applyFilter(() => setSortDirection(sortDirection === "desc" ? "asc" : "desc")),
2180
2697
  className: cn("cv-header-action inline-flex items-center gap-1", classNames?.sortButton),
2181
2698
  children: [
2182
- /* @__PURE__ */ jsx17(ArrowUpDown2, { size: 14 }),
2699
+ /* @__PURE__ */ jsx18(ArrowUpDown2, { size: 14 }),
2183
2700
  sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest
2184
2701
  ]
2185
2702
  }
2186
2703
  ),
2187
- hasFilters ? /* @__PURE__ */ jsx17(
2704
+ hasFilters ? /* @__PURE__ */ jsx18(
2188
2705
  "button",
2189
2706
  {
2190
2707
  "data-cv-tooltip": labels.clearFilters,
@@ -2199,8 +2716,8 @@ function DocumentsLibrary({
2199
2716
  children: labels.clearFilters
2200
2717
  }
2201
2718
  ) : null,
2202
- uploadDocument ? /* @__PURE__ */ jsxs12(Fragment4, { children: [
2203
- /* @__PURE__ */ jsx17(
2719
+ uploadDocument ? /* @__PURE__ */ jsxs13(Fragment4, { children: [
2720
+ /* @__PURE__ */ jsx18(
2204
2721
  "input",
2205
2722
  {
2206
2723
  ref: fileInputRef,
@@ -2213,7 +2730,7 @@ function DocumentsLibrary({
2213
2730
  }
2214
2731
  }
2215
2732
  ),
2216
- /* @__PURE__ */ jsxs12(
2733
+ /* @__PURE__ */ jsxs13(
2217
2734
  "button",
2218
2735
  {
2219
2736
  "data-cv-tooltip": labels.upload,
@@ -2223,21 +2740,21 @@ function DocumentsLibrary({
2223
2740
  disabled: uploading,
2224
2741
  className: "cv-header-action ml-auto inline-flex items-center gap-1 disabled:opacity-40",
2225
2742
  children: [
2226
- /* @__PURE__ */ jsx17(Upload, { size: 14, "aria-hidden": "true" }),
2743
+ /* @__PURE__ */ jsx18(Upload, { size: 14, "aria-hidden": "true" }),
2227
2744
  labels.upload
2228
2745
  ]
2229
2746
  }
2230
2747
  )
2231
2748
  ] }) : null
2232
2749
  ] }),
2233
- loading ? /* @__PURE__ */ jsx17("p", { className: cn("text-sm text-gray-500", classNames?.status), children: labels.loading }) : null,
2234
- failed ? /* @__PURE__ */ jsx17("p", { role: "alert", className: cn("text-sm text-red-600 dark:text-red-400", classNames?.status), children: labels.failure }) : null,
2235
- uploadFailed ? /* @__PURE__ */ jsx17("p", { role: "alert", className: cn("text-sm text-red-600 dark:text-red-400", classNames?.status), children: labels.uploadError }) : null,
2236
- !loading && !failed && documents.length === 0 ? /* @__PURE__ */ jsx17("p", { className: cn("text-sm text-gray-500", classNames?.status), children: hasFilters ? labels.noResults : labels.empty }) : null,
2237
- /* @__PURE__ */ jsx17("ul", { className: cn("space-y-2", classNames?.list), children: documents.map((document2) => {
2750
+ loading ? /* @__PURE__ */ jsx18("p", { className: cn("text-sm text-gray-500", classNames?.status), children: labels.loading }) : null,
2751
+ failed ? /* @__PURE__ */ jsx18("p", { role: "alert", className: cn("text-sm text-red-600 dark:text-red-400", classNames?.status), children: labels.failure }) : null,
2752
+ uploadFailed ? /* @__PURE__ */ jsx18("p", { role: "alert", className: cn("text-sm text-red-600 dark:text-red-400", classNames?.status), children: labels.uploadError }) : null,
2753
+ !loading && !failed && documents.length === 0 ? /* @__PURE__ */ jsx18("p", { className: cn("text-sm text-gray-500", classNames?.status), children: hasFilters ? labels.noResults : labels.empty }) : null,
2754
+ /* @__PURE__ */ jsx18("ul", { className: cn("space-y-2", classNames?.list), children: documents.map((document2) => {
2238
2755
  const isFromCustomer = !TEAM_SOURCES2.has(document2.source);
2239
2756
  const SourceIcon = isFromCustomer ? Users2 : Bot2;
2240
- return /* @__PURE__ */ jsxs12(
2757
+ return /* @__PURE__ */ jsxs13(
2241
2758
  "li",
2242
2759
  {
2243
2760
  className: cn(
@@ -2245,23 +2762,23 @@ function DocumentsLibrary({
2245
2762
  classNames?.item
2246
2763
  ),
2247
2764
  children: [
2248
- /* @__PURE__ */ jsxs12("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
2249
- /* @__PURE__ */ jsx17(FileIcon, { filename: document2.filename, mimeType: document2.mimeType }),
2250
- /* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
2251
- /* @__PURE__ */ jsx17("div", { className: cn("truncate text-sm font-medium", classNames?.filename), "data-cv-tooltip": document2.filename, children: document2.filename }),
2252
- /* @__PURE__ */ jsxs12("div", { className: cn("flex flex-wrap items-center gap-x-2 text-xs text-gray-500", classNames?.meta), children: [
2253
- /* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1", children: [
2254
- /* @__PURE__ */ jsx17(SourceIcon, { size: 11 }),
2765
+ /* @__PURE__ */ jsxs13("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
2766
+ /* @__PURE__ */ jsx18(FileIcon, { filename: document2.filename, mimeType: document2.mimeType }),
2767
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
2768
+ /* @__PURE__ */ jsx18("div", { className: cn("truncate text-sm font-medium", classNames?.filename), "data-cv-tooltip": document2.filename, children: document2.filename }),
2769
+ /* @__PURE__ */ jsxs13("div", { className: cn("flex flex-wrap items-center gap-x-2 text-xs text-gray-500", classNames?.meta), children: [
2770
+ /* @__PURE__ */ jsxs13("span", { className: "inline-flex items-center gap-1", children: [
2771
+ /* @__PURE__ */ jsx18(SourceIcon, { size: 11 }),
2255
2772
  isFromCustomer ? labels.sourceFilterCustomer : labels.sourceFilterTeam
2256
2773
  ] }),
2257
- /* @__PURE__ */ jsx17("span", { children: "\xB7" }),
2258
- /* @__PURE__ */ jsx17("span", { children: formatDateTime(document2.linkedAt) }),
2259
- /* @__PURE__ */ jsx17("span", { children: "\xB7" }),
2260
- /* @__PURE__ */ jsx17("span", { children: formatFileSize(document2.sizeBytes) })
2774
+ /* @__PURE__ */ jsx18("span", { children: "\xB7" }),
2775
+ /* @__PURE__ */ jsx18("span", { children: formatDateTime(document2.linkedAt) }),
2776
+ /* @__PURE__ */ jsx18("span", { children: "\xB7" }),
2777
+ /* @__PURE__ */ jsx18("span", { children: formatFileSize(document2.sizeBytes) })
2261
2778
  ] })
2262
2779
  ] })
2263
2780
  ] }),
2264
- onOpenConversation ? /* @__PURE__ */ jsxs12(
2781
+ onOpenConversation ? /* @__PURE__ */ jsxs13(
2265
2782
  "button",
2266
2783
  {
2267
2784
  type: "button",
@@ -2270,13 +2787,13 @@ function DocumentsLibrary({
2270
2787
  "aria-label": labels.openConversation,
2271
2788
  className: cn("cv-header-action inline-flex shrink-0 items-center gap-1", classNames?.conversationLink),
2272
2789
  children: [
2273
- /* @__PURE__ */ jsx17(MessageSquare, { size: 12 }),
2790
+ /* @__PURE__ */ jsx18(MessageSquare, { size: 12 }),
2274
2791
  formatPhone(document2.conversationId)
2275
2792
  ]
2276
2793
  }
2277
- ) : /* @__PURE__ */ jsx17("span", { className: cn("shrink-0 text-xs text-gray-500", classNames?.conversationLink), children: formatPhone(document2.conversationId) }),
2278
- /* @__PURE__ */ jsxs12("div", { className: "flex shrink-0 gap-1", children: [
2279
- /* @__PURE__ */ jsx17(
2794
+ ) : /* @__PURE__ */ jsx18("span", { className: cn("shrink-0 text-xs text-gray-500", classNames?.conversationLink), children: formatPhone(document2.conversationId) }),
2795
+ /* @__PURE__ */ jsxs13("div", { className: "flex shrink-0 gap-1", children: [
2796
+ /* @__PURE__ */ jsx18(
2280
2797
  "button",
2281
2798
  {
2282
2799
  type: "button",
@@ -2284,10 +2801,10 @@ function DocumentsLibrary({
2284
2801
  "data-cv-tooltip": labels.view,
2285
2802
  "aria-label": `${labels.view}: ${document2.filename}`,
2286
2803
  className: "cv-header-icon",
2287
- children: /* @__PURE__ */ jsx17(Eye2, { size: 14 })
2804
+ children: /* @__PURE__ */ jsx18(Eye2, { size: 14 })
2288
2805
  }
2289
2806
  ),
2290
- /* @__PURE__ */ jsx17(
2807
+ /* @__PURE__ */ jsx18(
2291
2808
  "button",
2292
2809
  {
2293
2810
  type: "button",
@@ -2295,7 +2812,7 @@ function DocumentsLibrary({
2295
2812
  "data-cv-tooltip": labels.download,
2296
2813
  "aria-label": `${labels.download}: ${document2.filename}`,
2297
2814
  className: "cv-header-icon",
2298
- children: /* @__PURE__ */ jsx17(Download2, { size: 14 })
2815
+ children: /* @__PURE__ */ jsx18(Download2, { size: 14 })
2299
2816
  }
2300
2817
  )
2301
2818
  ] })
@@ -2304,10 +2821,10 @@ function DocumentsLibrary({
2304
2821
  `${document2.conversationId}:${document2.id}`
2305
2822
  );
2306
2823
  }) }),
2307
- 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: [
2308
- /* @__PURE__ */ jsx17("span", { className: "text-gray-400", children: labels.total(total) }),
2309
- /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
2310
- /* @__PURE__ */ jsx17(
2824
+ total > perPage ? /* @__PURE__ */ jsxs13("div", { className: cn("flex items-center justify-between border-t pt-2 text-xs dark:border-gray-700", classNames?.pagination), children: [
2825
+ /* @__PURE__ */ jsx18("span", { className: "text-gray-400", children: labels.total(total) }),
2826
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
2827
+ /* @__PURE__ */ jsx18(
2311
2828
  "button",
2312
2829
  {
2313
2830
  "data-cv-tooltip": PAGINATION_LABELS.previous,
@@ -2319,8 +2836,8 @@ function DocumentsLibrary({
2319
2836
  children: "\u2039"
2320
2837
  }
2321
2838
  ),
2322
- /* @__PURE__ */ jsx17("span", { className: "text-gray-500", children: labels.page(page, lastPage) }),
2323
- /* @__PURE__ */ jsx17(
2839
+ /* @__PURE__ */ jsx18("span", { className: "text-gray-500", children: labels.page(page, lastPage) }),
2840
+ /* @__PURE__ */ jsx18(
2324
2841
  "button",
2325
2842
  {
2326
2843
  "data-cv-tooltip": PAGINATION_LABELS.next,
@@ -2384,8 +2901,8 @@ function toConversationSimulatorClient({
2384
2901
  }
2385
2902
 
2386
2903
  // src/preview/ConversationPreview.tsx
2387
- import { useCallback as useCallback6, useEffect as useEffect5, useMemo as useMemo4, useRef as useRef6, useState as useState12 } from "react";
2388
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2904
+ import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo4, useRef as useRef8, useState as useState13 } from "react";
2905
+ import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
2389
2906
  function mediaTypeOf(mimeType) {
2390
2907
  return mediaKindOf(mimeType);
2391
2908
  }
@@ -2429,19 +2946,19 @@ function ConversationPreview({
2429
2946
  pollIntervalMs,
2430
2947
  uploadMedia
2431
2948
  }) {
2432
- const [messages, setMessages] = useState12([]);
2433
- const [failure, setFailure] = useState12(void 0);
2434
- const [loadFailure, setLoadFailure] = useState12(void 0);
2435
- const [isRecording, setIsRecording] = useState12(false);
2436
- const [pendingLocal, setPendingLocal] = useState12([]);
2437
- const loadMessagesRef = useRef6(loadMessages);
2438
- const bottomRef = useRef6(null);
2949
+ const [messages, setMessages] = useState13([]);
2950
+ const [failure, setFailure] = useState13(void 0);
2951
+ const [loadFailure, setLoadFailure] = useState13(void 0);
2952
+ const [isRecording, setIsRecording] = useState13(false);
2953
+ const [pendingLocal, setPendingLocal] = useState13([]);
2954
+ const loadMessagesRef = useRef8(loadMessages);
2955
+ const bottomRef = useRef8(null);
2439
2956
  loadMessagesRef.current = loadMessages;
2440
2957
  const simulator = useMemo4(
2441
2958
  () => isConversationSimulatorClient(client) ? client : toConversationSimulatorClient({ client, ...uploadMedia ? { uploadMedia } : {} }),
2442
2959
  [client, uploadMedia]
2443
2960
  );
2444
- const refresh = useCallback6(async () => {
2961
+ const refresh = useCallback7(async () => {
2445
2962
  try {
2446
2963
  const loaded = await loadMessagesRef.current(conversationId);
2447
2964
  setMessages(loaded);
@@ -2456,10 +2973,10 @@ function ConversationPreview({
2456
2973
  setLoadFailure(describeLoadFailure(error));
2457
2974
  }
2458
2975
  }, [conversationId]);
2459
- useEffect5(() => {
2976
+ useEffect8(() => {
2460
2977
  void refresh();
2461
2978
  }, [refresh]);
2462
- useEffect5(() => {
2979
+ useEffect8(() => {
2463
2980
  const source = sse.connectConversationStream(conversationId);
2464
2981
  const handler = () => {
2465
2982
  void refresh();
@@ -2470,12 +2987,12 @@ function ConversationPreview({
2470
2987
  source.close();
2471
2988
  };
2472
2989
  }, [sse, conversationId, refresh]);
2473
- useEffect5(() => {
2990
+ useEffect8(() => {
2474
2991
  if (!pollIntervalMs) return;
2475
2992
  const timer = setInterval(() => void refresh(), pollIntervalMs);
2476
2993
  return () => clearInterval(timer);
2477
2994
  }, [pollIntervalMs, refresh]);
2478
- useEffect5(() => {
2995
+ useEffect8(() => {
2479
2996
  bottomRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" });
2480
2997
  }, [messages]);
2481
2998
  const rendered = useMemo4(() => decorate([...messages, ...pendingLocal]), [messages, pendingLocal]);
@@ -2535,11 +3052,11 @@ function ConversationPreview({
2535
3052
  setFailure(error instanceof Error ? error.message : "Falha ao enviar o arquivo.");
2536
3053
  }
2537
3054
  }
2538
- return /* @__PURE__ */ jsxs13("div", { className: "flex h-full min-h-0 flex-col", children: [
2539
- /* @__PURE__ */ jsxs13(ConversationWallpaper, { className: "flex-1 min-h-0 overflow-y-auto px-4 py-3", children: [
2540
- rendered.map(({ message, isFirstInGroup, showDateDivider }) => /* @__PURE__ */ jsxs13("div", { children: [
2541
- showDateDivider ? /* @__PURE__ */ jsx18(DateDivider, { iso: message.timestamp }) : null,
2542
- /* @__PURE__ */ jsx18(
3055
+ return /* @__PURE__ */ jsxs14("div", { className: "flex h-full min-h-0 flex-col", children: [
3056
+ /* @__PURE__ */ jsxs14(ConversationWallpaper, { className: "flex-1 min-h-0 overflow-y-auto px-4 py-3", children: [
3057
+ rendered.map(({ message, isFirstInGroup, showDateDivider }) => /* @__PURE__ */ jsxs14("div", { children: [
3058
+ showDateDivider ? /* @__PURE__ */ jsx19(DateDivider, { iso: message.timestamp }) : null,
3059
+ /* @__PURE__ */ jsx19(
2543
3060
  MessageBubble,
2544
3061
  {
2545
3062
  message,
@@ -2549,17 +3066,17 @@ function ConversationPreview({
2549
3066
  }
2550
3067
  )
2551
3068
  ] }, message.id)),
2552
- /* @__PURE__ */ jsx18("div", { ref: bottomRef })
3069
+ /* @__PURE__ */ jsx19("div", { ref: bottomRef })
2553
3070
  ] }),
2554
- failure ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "px-4 py-2 text-sm text-red-600 dark:text-red-400", children: failure }) : null,
2555
- loadFailure ? /* @__PURE__ */ jsx18("p", { role: "status", className: "px-4 py-2 text-sm text-amber-700 dark:text-amber-400", children: loadFailure }) : null,
2556
- /* @__PURE__ */ jsx18(
3071
+ failure ? /* @__PURE__ */ jsx19("p", { role: "alert", className: "px-4 py-2 text-sm text-red-600 dark:text-red-400", children: failure }) : null,
3072
+ loadFailure ? /* @__PURE__ */ jsx19("p", { role: "status", className: "px-4 py-2 text-sm text-amber-700 dark:text-amber-400", children: loadFailure }) : null,
3073
+ /* @__PURE__ */ jsx19(
2557
3074
  MessageComposer,
2558
3075
  {
2559
3076
  onSend: (text) => void handleSend(text),
2560
3077
  onAttach: canAttachFile ? (file) => void handleAttach(file) : void 0,
2561
3078
  placeholder: isRecording ? "Gravando\u2026 toque no quadrado para ouvir" : placeholder ?? "Escreva como o cliente\u2026",
2562
- idleAction: canRecordAudio ? /* @__PURE__ */ jsx18(
3079
+ idleAction: canRecordAudio ? /* @__PURE__ */ jsx19(
2563
3080
  AudioRecorderButton,
2564
3081
  {
2565
3082
  onRecorded: (file) => void handleAttach(file),
@@ -2573,7 +3090,7 @@ function ConversationPreview({
2573
3090
  }
2574
3091
 
2575
3092
  // src/preview/ConversationSimulatorPanel.tsx
2576
- import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
3093
+ import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
2577
3094
  var DEFAULT_CONVERSATION_SIMULATOR_PANEL_LABELS = {
2578
3095
  title: "Simulador do cliente",
2579
3096
  destinationHint: "entrega no webhook real",
@@ -2615,18 +3132,18 @@ function ConversationSimulatorPanel({
2615
3132
  }) {
2616
3133
  const text = { ...simulatorPanelLabelsOf(channel), ...labels };
2617
3134
  const subtitle = [displayHandle ?? displayNumber ?? previewProps.conversationId, text.destinationHint].join(" \xB7 ");
2618
- return /* @__PURE__ */ jsxs14("aside", { className: "cv-simulator-panel", "aria-label": text.title, children: [
2619
- /* @__PURE__ */ jsxs14("header", { className: "cv-simulator-panel__header", children: [
2620
- /* @__PURE__ */ jsxs14("div", { className: "cv-simulator-panel__heading", children: [
2621
- /* @__PURE__ */ jsx19("h2", { className: "cv-simulator-panel__title", children: text.title }),
2622
- /* @__PURE__ */ jsx19("p", { className: "cv-simulator-panel__subtitle", children: subtitle })
3135
+ return /* @__PURE__ */ jsxs15("aside", { className: "cv-simulator-panel", "aria-label": text.title, children: [
3136
+ /* @__PURE__ */ jsxs15("header", { className: "cv-simulator-panel__header", children: [
3137
+ /* @__PURE__ */ jsxs15("div", { className: "cv-simulator-panel__heading", children: [
3138
+ /* @__PURE__ */ jsx20("h2", { className: "cv-simulator-panel__title", children: text.title }),
3139
+ /* @__PURE__ */ jsx20("p", { className: "cv-simulator-panel__subtitle", children: subtitle })
2623
3140
  ] }),
2624
- /* @__PURE__ */ jsxs14("div", { className: "cv-simulator-panel__actions", children: [
3141
+ /* @__PURE__ */ jsxs15("div", { className: "cv-simulator-panel__actions", children: [
2625
3142
  headerActions,
2626
- /* @__PURE__ */ jsx19("button", { type: "button", onClick: onClose, "data-cv-tooltip": text.close, "aria-label": text.close, className: "cv-simulator-panel__close", children: /* @__PURE__ */ jsx19("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: /* @__PURE__ */ jsx19("path", { d: "M18 6 6 18M6 6l12 12" }) }) })
3143
+ /* @__PURE__ */ jsx20("button", { type: "button", onClick: onClose, "data-cv-tooltip": text.close, "aria-label": text.close, className: "cv-simulator-panel__close", children: /* @__PURE__ */ jsx20("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: /* @__PURE__ */ jsx20("path", { d: "M18 6 6 18M6 6l12 12" }) }) })
2627
3144
  ] })
2628
3145
  ] }),
2629
- /* @__PURE__ */ jsx19("div", { className: "cv-simulator-panel__body", children: /* @__PURE__ */ jsx19(ConversationPreview, { ...previewProps, placeholder: text.placeholder }) })
3146
+ /* @__PURE__ */ jsx20("div", { className: "cv-simulator-panel__body", children: /* @__PURE__ */ jsx20(ConversationPreview, { ...previewProps, placeholder: text.placeholder }) })
2630
3147
  ] });
2631
3148
  }
2632
3149
 
@@ -2667,6 +3184,14 @@ export {
2667
3184
  COMPOSER_MONOSPACE_CLASS,
2668
3185
  COMPOSER_COMPACT_WIDTH,
2669
3186
  QUICK_REPLY_PILL_CLASS,
3187
+ normalizeForSearch,
3188
+ filterQuickReplies,
3189
+ highlightMatch,
3190
+ DEFAULT_QUICK_REPLIES_PICKER_LABELS,
3191
+ DEFAULT_QUICK_REPLIES_WORKSPACE_LABELS,
3192
+ QuickRepliesPicker,
3193
+ useQuickRepliesPicker,
3194
+ detectQuickReplyShortcut,
2670
3195
  applyQuickReplyVariables,
2671
3196
  resolveQuickReply,
2672
3197
  DEFAULT_MESSAGE_COMPOSER_LABELS,