@adatechnology/conversations-ui 0.2.0 → 0.3.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.
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  TOOLTIP_ATTRIBUTE,
3
- TooltipLayer
4
- } from "./chunk-DKPXKQGC.js";
3
+ TooltipLayer,
4
+ WhatsAppMessagePreview
5
+ } from "./chunk-HMCOTZAX.js";
5
6
  import {
6
7
  AudioPlayer,
7
8
  AudioRecorderButton,
@@ -52,7 +53,6 @@ import {
52
53
  applyQuickReplyVariables,
53
54
  capabilitiesOf,
54
55
  channelFiltersFor,
55
- cn,
56
56
  contactFlag,
57
57
  conversationsOf,
58
58
  createMediaUrlResolver,
@@ -76,16 +76,17 @@ import {
76
76
  useConversationLocales,
77
77
  useConversations,
78
78
  useQuickRepliesPicker
79
- } from "./chunk-NHQDQJL2.js";
79
+ } from "./chunk-L4OE4ORQ.js";
80
80
  import {
81
81
  ZERO_WIDTH_SPACE,
82
+ cn,
82
83
  htmlToWA,
83
84
  parseWhatsAppFormatting,
84
85
  useDarkMode,
85
86
  useIsDarkTheme,
86
87
  waToHTML,
87
88
  waToHTMLInline
88
- } from "./chunk-WCBDXZ3X.js";
89
+ } from "./chunk-PJNR6UMN.js";
89
90
 
90
91
  // src/RichMessageComposer.tsx
91
92
  import {
@@ -122,6 +123,12 @@ var FORMATTING_ACTION = {
122
123
  STRIKETHROUGH: "strikethrough",
123
124
  MONOSPACE: "monospace"
124
125
  };
126
+ var WHATSAPP_MARKER_BY_ACTION = {
127
+ [FORMATTING_ACTION.BOLD]: "*",
128
+ [FORMATTING_ACTION.ITALIC]: "_",
129
+ [FORMATTING_ACTION.STRIKETHROUGH]: "~",
130
+ [FORMATTING_ACTION.MONOSPACE]: "```"
131
+ };
125
132
  var EXEC_COMMAND_BY_ACTION = {
126
133
  [FORMATTING_ACTION.BOLD]: "bold",
127
134
  [FORMATTING_ACTION.ITALIC]: "italic",
@@ -611,7 +618,7 @@ var RichMessageComposer = forwardRef(
611
618
  document.addEventListener("mousedown", handleOutsideClick);
612
619
  return () => document.removeEventListener("mousedown", handleOutsideClick);
613
620
  }, [isQuickRepliesOpen, quickRepliesMode, closeQuickRepliesAndRefocus]);
614
- const wrapSelection = useCallback(
621
+ const wrapSelection2 = useCallback(
615
622
  (action) => {
616
623
  const range = currentRange();
617
624
  const selectedText = range?.toString();
@@ -638,17 +645,17 @@ var RichMessageComposer = forwardRef(
638
645
  } else if (code) {
639
646
  unwrapMonospace(code);
640
647
  } else {
641
- wrapSelection(action);
648
+ wrapSelection2(action);
642
649
  }
643
650
  emitChange(editor.innerHTML);
644
651
  refreshActiveFormatting();
645
652
  return;
646
653
  }
647
654
  if (toggleFormattingCommand(action)) emitChange(editor.innerHTML);
648
- else wrapSelection(action);
655
+ else wrapSelection2(action);
649
656
  refreshActiveFormatting();
650
657
  },
651
- [currentRange, emitChange, refreshActiveFormatting, wrapSelection]
658
+ [currentRange, emitChange, refreshActiveFormatting, wrapSelection2]
652
659
  );
653
660
  const handleInput = useCallback(
654
661
  (event) => {
@@ -928,7 +935,7 @@ function WhatsAppMessageEditor({
928
935
  }) {
929
936
  const editorLabels = { ...DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS, ...labels };
930
937
  const textareaRef = useRef3(null);
931
- function wrapSelection(marker) {
938
+ function wrapSelection2(marker) {
932
939
  const textarea = textareaRef.current;
933
940
  if (!textarea) return;
934
941
  const start = textarea.selectionStart;
@@ -957,9 +964,9 @@ function WhatsAppMessageEditor({
957
964
  const toolbarButtonClass = "inline-flex items-center justify-center h-8 w-8 rounded-lg border border-gray-200 dark:border-gray-600 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors";
958
965
  return /* @__PURE__ */ jsxs3("div", { children: [
959
966
  /* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-1.5 mb-2", children: [
960
- /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => wrapSelection("*"), className: toolbarButtonClass, "data-cv-tooltip": editorLabels.boldHint, "aria-label": editorLabels.bold, children: /* @__PURE__ */ jsx3(Bold2, { size: 15 }) }),
961
- /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => wrapSelection("_"), className: toolbarButtonClass, "data-cv-tooltip": editorLabels.italicHint, "aria-label": editorLabels.italic, children: /* @__PURE__ */ jsx3(Italic2, { size: 15 }) }),
962
- /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => wrapSelection("~"), className: toolbarButtonClass, "data-cv-tooltip": editorLabels.strikethroughHint, "aria-label": editorLabels.strikethrough, children: /* @__PURE__ */ jsx3(Strikethrough2, { size: 15 }) }),
967
+ /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => wrapSelection2("*"), className: toolbarButtonClass, "data-cv-tooltip": editorLabels.boldHint, "aria-label": editorLabels.bold, children: /* @__PURE__ */ jsx3(Bold2, { size: 15 }) }),
968
+ /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => wrapSelection2("_"), className: toolbarButtonClass, "data-cv-tooltip": editorLabels.italicHint, "aria-label": editorLabels.italic, children: /* @__PURE__ */ jsx3(Italic2, { size: 15 }) }),
969
+ /* @__PURE__ */ jsx3("button", { type: "button", onClick: () => wrapSelection2("~"), className: toolbarButtonClass, "data-cv-tooltip": editorLabels.strikethroughHint, "aria-label": editorLabels.strikethrough, children: /* @__PURE__ */ jsx3(Strikethrough2, { size: 15 }) }),
963
970
  placeholders.length > 0 && /* @__PURE__ */ jsxs3(Fragment2, { children: [
964
971
  /* @__PURE__ */ jsx3("span", { className: "mx-1 h-5 w-px bg-gray-200 dark:bg-gray-600" }),
965
972
  placeholders.map((token) => /* @__PURE__ */ jsx3(
@@ -1328,7 +1335,7 @@ function MessageText({ message }) {
1328
1335
  onClick: handleCopy,
1329
1336
  className: "text-[14.2px] leading-[19px] whitespace-pre-wrap break-words select-all [&_strong]:font-bold [&_em]:italic [&_del]:line-through",
1330
1337
  children: [
1331
- /* @__PURE__ */ jsx7("span", { children: parseWhatsAppFormatting(message.content ?? "") }),
1338
+ /* @__PURE__ */ jsx7("div", { children: parseWhatsAppFormatting(message.content ?? "") }),
1332
1339
  copied && /* @__PURE__ */ jsx7("span", { className: "absolute top-0 right-0 -translate-y-full bg-[#3b4a54] text-white text-[11px] px-1.5 py-0.5 rounded shadow-lg", children: "Copiado!" })
1333
1340
  ]
1334
1341
  }
@@ -4256,6 +4263,16 @@ function sameUploadIds(a, b) {
4256
4263
  if (a.length !== b.length) return false;
4257
4264
  return a.every((id, index) => id === b[index]);
4258
4265
  }
4266
+ function hasSentEveryStoredUpload(storedUploadIds, sentAttachmentKeys) {
4267
+ if (storedUploadIds.length === 0) return true;
4268
+ const sentKeys = new Set(sentAttachmentKeys);
4269
+ return storedUploadIds.every((uploadId) => sentKeys.has(uploadId));
4270
+ }
4271
+ function shouldResetRetryKey(params) {
4272
+ const { current, attempted, sentAttachmentKeys, uploadId } = params;
4273
+ if (!sentAttachmentKeys.includes(uploadId)) return false;
4274
+ return current === attempted;
4275
+ }
4259
4276
  function attachmentSendStatusOf(status) {
4260
4277
  if (status === "sent") return "sent";
4261
4278
  if (status === "skipped") return "skipped";
@@ -4331,6 +4348,7 @@ async function sendQueuedMessage(params) {
4331
4348
 
4332
4349
  // src/quickReplies/QuickRepliesWorkspace.tsx
4333
4350
  import { useEffect as useEffect13, useId as useId2, useRef as useRef11, useState as useState18 } from "react";
4351
+ import { Pencil as Pencil2, Plus as Plus2, Trash2 as Trash23 } from "lucide-react";
4334
4352
 
4335
4353
  // src/quickReplies/useQuickRepliesWorkspace.ts
4336
4354
  import { useCallback as useCallback10, useEffect as useEffect12, useState as useState17 } from "react";
@@ -4759,10 +4777,208 @@ function useQuickRepliesWorkspace({
4759
4777
  };
4760
4778
  }
4761
4779
 
4780
+ // src/quickReplies/quickReplyFormatting.ts
4781
+ var LEADING_WHITESPACE = /^\s*/;
4782
+ var TRAILING_WHITESPACE = /\s*$/;
4783
+ function isWrappedBy(core, marker) {
4784
+ return core.length >= marker.length * 2 && core.startsWith(marker) && core.endsWith(marker);
4785
+ }
4786
+ function toggleLine({ line, marker, shouldUnwrap }) {
4787
+ if (!line.trim()) return line;
4788
+ const leading = LEADING_WHITESPACE.exec(line)?.[0] ?? "";
4789
+ const trailing = TRAILING_WHITESPACE.exec(line)?.[0] ?? "";
4790
+ const core = line.slice(leading.length, line.length - trailing.length);
4791
+ const toggled = shouldUnwrap ? core.slice(marker.length, core.length - marker.length) : marker + core + marker;
4792
+ return leading + toggled + trailing;
4793
+ }
4794
+ function wrapLines({ text, start, end, marker }) {
4795
+ const lines = text.slice(start, end).split("\n");
4796
+ const shouldUnwrap = lines.filter((line) => line.trim()).every((line) => isWrappedBy(line.trim(), marker));
4797
+ const replaced = lines.map((line) => toggleLine({ line, marker, shouldUnwrap })).join("\n");
4798
+ return {
4799
+ text: text.slice(0, start) + replaced + text.slice(end),
4800
+ selectionStart: start,
4801
+ selectionEnd: start + replaced.length
4802
+ };
4803
+ }
4804
+ function wrapSelection({ text, start, end, marker }) {
4805
+ const selected = text.slice(start, end);
4806
+ if (!selected.trim()) {
4807
+ return {
4808
+ text: text.slice(0, start) + marker + selected + marker + text.slice(end),
4809
+ selectionStart: start + marker.length,
4810
+ selectionEnd: end + marker.length
4811
+ };
4812
+ }
4813
+ if (selected.includes("\n")) return wrapLines({ text, start, end, marker });
4814
+ const coreStart = start + (LEADING_WHITESPACE.exec(selected)?.[0].length ?? 0);
4815
+ const coreEnd = end - (TRAILING_WHITESPACE.exec(selected)?.[0].length ?? 0);
4816
+ const core = text.slice(coreStart, coreEnd);
4817
+ const before = text.slice(0, coreStart);
4818
+ const after = text.slice(coreEnd);
4819
+ const size = marker.length;
4820
+ if (isWrappedBy(core, marker)) {
4821
+ const unwrapped = core.slice(size, core.length - size);
4822
+ return { text: before + unwrapped + after, selectionStart: coreStart, selectionEnd: coreStart + unwrapped.length };
4823
+ }
4824
+ if (before.endsWith(marker) && after.startsWith(marker)) {
4825
+ return {
4826
+ text: before.slice(0, before.length - size) + core + after.slice(size),
4827
+ selectionStart: coreStart - size,
4828
+ selectionEnd: coreEnd - size
4829
+ };
4830
+ }
4831
+ return {
4832
+ text: before + marker + core + marker + after,
4833
+ selectionStart: coreStart + size,
4834
+ selectionEnd: coreEnd + size
4835
+ };
4836
+ }
4837
+ var QUICK_REPLY_FORMATTING_ACTION = {
4838
+ ...FORMATTING_ACTION,
4839
+ INLINE_CODE: "inlineCode",
4840
+ BULLETED_LIST: "bulletedList",
4841
+ NUMBERED_LIST: "numberedList",
4842
+ QUOTE: "quote"
4843
+ };
4844
+ var LINE_PREFIX_PATTERN = {
4845
+ [QUICK_REPLY_FORMATTING_ACTION.BULLETED_LIST]: /^[-*] /,
4846
+ [QUICK_REPLY_FORMATTING_ACTION.NUMBERED_LIST]: /^\d+\. /,
4847
+ [QUICK_REPLY_FORMATTING_ACTION.QUOTE]: /^> /
4848
+ };
4849
+ var INLINE_MARKER_BY_ACTION = {
4850
+ ...WHATSAPP_MARKER_BY_ACTION,
4851
+ [QUICK_REPLY_FORMATTING_ACTION.INLINE_CODE]: "`"
4852
+ };
4853
+ function isLinePrefixAction(action) {
4854
+ return action in LINE_PREFIX_PATTERN;
4855
+ }
4856
+ function prefixFor(action, position) {
4857
+ if (action === QUICK_REPLY_FORMATTING_ACTION.NUMBERED_LIST) return `${position}. `;
4858
+ return action === QUICK_REPLY_FORMATTING_ACTION.QUOTE ? "> " : "- ";
4859
+ }
4860
+ function toggleLinePrefix({ text, start, end, action }) {
4861
+ const lineStart = start === 0 ? 0 : text.lastIndexOf("\n", start - 1) + 1;
4862
+ const searchFrom = end > start && text[end - 1] === "\n" ? end - 1 : end;
4863
+ const nextBreak = text.indexOf("\n", searchFrom);
4864
+ const lineEnd = nextBreak === -1 ? text.length : nextBreak;
4865
+ const original = text.slice(lineStart, lineEnd);
4866
+ const lines = original.split("\n");
4867
+ const pattern = LINE_PREFIX_PATTERN[action];
4868
+ const filledLines = lines.filter((line) => line.trim());
4869
+ const shouldRemove = filledLines.length > 0 && filledLines.every((line) => pattern.test(line));
4870
+ let position = 0;
4871
+ const replaced = lines.map((line) => {
4872
+ if (shouldRemove) return line.replace(pattern, "");
4873
+ if (!line.trim() && lines.length > 1) return line;
4874
+ position += 1;
4875
+ return prefixFor(action, position) + line.replace(pattern, "");
4876
+ }).join("\n");
4877
+ const nextText = text.slice(0, lineStart) + replaced + text.slice(lineEnd);
4878
+ if (start === end) {
4879
+ const caret = Math.max(lineStart, start + replaced.length - original.length);
4880
+ return { text: nextText, selectionStart: caret, selectionEnd: caret };
4881
+ }
4882
+ return { text: nextText, selectionStart: lineStart, selectionEnd: lineStart + replaced.length };
4883
+ }
4884
+ function computeFormattingEdit({
4885
+ text,
4886
+ selectionStart,
4887
+ selectionEnd,
4888
+ action,
4889
+ maximumLength
4890
+ }) {
4891
+ const edit = isLinePrefixAction(action) ? toggleLinePrefix({ text, start: selectionStart, end: selectionEnd, action }) : wrapSelection({ text, start: selectionStart, end: selectionEnd, marker: INLINE_MARKER_BY_ACTION[action] ?? "" });
4892
+ return edit.text.length > maximumLength ? void 0 : edit;
4893
+ }
4894
+ var SHORTCUT_ACTION_BY_KEY = {
4895
+ b: FORMATTING_ACTION.BOLD,
4896
+ i: FORMATTING_ACTION.ITALIC
4897
+ };
4898
+ var FORMATTING_SHORTCUT_HINT = {
4899
+ [FORMATTING_ACTION.BOLD]: "Ctrl/\u2318+B",
4900
+ [FORMATTING_ACTION.ITALIC]: "Ctrl/\u2318+I"
4901
+ };
4902
+ function formattingActionForShortcut(event) {
4903
+ if (event.isComposing || event.shiftKey || event.altKey) return void 0;
4904
+ if (!(event.ctrlKey || event.metaKey)) return void 0;
4905
+ return SHORTCUT_ACTION_BY_KEY[event.key.toLowerCase()];
4906
+ }
4907
+ function changedRange(previous, next) {
4908
+ let prefix = 0;
4909
+ const shortest = Math.min(previous.length, next.length);
4910
+ while (prefix < shortest && previous[prefix] === next[prefix]) prefix += 1;
4911
+ let suffix = 0;
4912
+ while (suffix < shortest - prefix && previous[previous.length - 1 - suffix] === next[next.length - 1 - suffix]) {
4913
+ suffix += 1;
4914
+ }
4915
+ return { start: prefix, end: previous.length - suffix, insertedText: next.slice(prefix, next.length - suffix) };
4916
+ }
4917
+
4918
+ // src/quickReplies/QuickReplyFormattingToolbar.tsx
4919
+ import { Bold as Bold3, Code as Code2, Italic as Italic3, List, ListOrdered, Quote, SquareCode, Strikethrough as Strikethrough3 } from "lucide-react";
4920
+ import { jsx as jsx25 } from "react/jsx-runtime";
4921
+ function QuickReplyFormattingToolbar({ labels, onFormat }) {
4922
+ const buttons = [
4923
+ { action: QUICK_REPLY_FORMATTING_ACTION.BOLD, label: labels.formatBold, Icon: Bold3 },
4924
+ { action: QUICK_REPLY_FORMATTING_ACTION.ITALIC, label: labels.formatItalic, Icon: Italic3 },
4925
+ { action: QUICK_REPLY_FORMATTING_ACTION.STRIKETHROUGH, label: labels.formatStrikethrough, Icon: Strikethrough3 },
4926
+ { action: QUICK_REPLY_FORMATTING_ACTION.MONOSPACE, label: labels.formatMonospace, Icon: SquareCode },
4927
+ { action: QUICK_REPLY_FORMATTING_ACTION.INLINE_CODE, label: labels.formatInlineCode, Icon: Code2 },
4928
+ { action: QUICK_REPLY_FORMATTING_ACTION.BULLETED_LIST, label: labels.formatBulletedList, Icon: List },
4929
+ { action: QUICK_REPLY_FORMATTING_ACTION.NUMBERED_LIST, label: labels.formatNumberedList, Icon: ListOrdered },
4930
+ { action: QUICK_REPLY_FORMATTING_ACTION.QUOTE, label: labels.formatQuote, Icon: Quote }
4931
+ ];
4932
+ return /* @__PURE__ */ jsx25("div", { role: "toolbar", "aria-label": labels.formattingToolbar, className: "flex flex-wrap gap-1", children: buttons.map(({ action, label, Icon }) => /* @__PURE__ */ jsx25(
4933
+ "button",
4934
+ {
4935
+ type: "button",
4936
+ "aria-label": label,
4937
+ title: FORMATTING_SHORTCUT_HINT[action] ? `${label} (${FORMATTING_SHORTCUT_HINT[action]})` : label,
4938
+ onMouseDown: (event) => event.preventDefault(),
4939
+ onClick: () => onFormat(action),
4940
+ className: cn(COMPOSER_TOOL_BUTTON_CLASS, COMPOSER_TOOL_BUTTON_IDLE_CLASS),
4941
+ children: /* @__PURE__ */ jsx25(Icon, { size: 16, "aria-hidden": "true" })
4942
+ },
4943
+ action
4944
+ )) });
4945
+ }
4946
+
4947
+ // src/quickReplies/QuickReplyWhatsAppPreview.tsx
4948
+ import { Paperclip as Paperclip2 } from "lucide-react";
4949
+ import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
4950
+ function resolvePreviewVariables(body, variables = []) {
4951
+ return variables.reduce(
4952
+ (resolved, variable) => variable.marker ? resolved.split(variable.marker).join(variable.value || variable.label) : resolved,
4953
+ body
4954
+ );
4955
+ }
4956
+ function QuickReplyWhatsAppPreview({ body, variables, attachments, labels }) {
4957
+ const resolvedBody = resolvePreviewVariables(body, variables);
4958
+ const hasAttachments = (attachments?.length ?? 0) > 0;
4959
+ return /* @__PURE__ */ jsxs23("section", { "aria-label": labels.previewTitle, className: "space-y-1", children: [
4960
+ /* @__PURE__ */ jsx26("h3", { className: "text-sm font-medium", children: labels.previewTitle }),
4961
+ /* @__PURE__ */ jsxs23(WhatsAppMessagePreview, { children: [
4962
+ hasAttachments ? /* @__PURE__ */ jsx26("ul", { className: "mb-1.5 flex flex-wrap gap-1 whitespace-normal", children: attachments?.map((attachment) => /* @__PURE__ */ jsxs23(
4963
+ "li",
4964
+ {
4965
+ className: "inline-flex max-w-full items-center gap-1 rounded-md bg-black/5 px-1.5 py-0.5 text-xs dark:bg-white/10",
4966
+ children: [
4967
+ /* @__PURE__ */ jsx26(Paperclip2, { size: 12, "aria-hidden": "true", className: "shrink-0" }),
4968
+ /* @__PURE__ */ jsx26("span", { className: "truncate", children: attachment.filename })
4969
+ ]
4970
+ },
4971
+ attachment.uploadId
4972
+ )) }) : null,
4973
+ resolvedBody ? parseWhatsAppFormatting(resolvedBody) : /* @__PURE__ */ jsx26("span", { className: "italic text-gray-400", children: labels.previewEmptyBody })
4974
+ ] })
4975
+ ] });
4976
+ }
4977
+
4762
4978
  // src/quickReplies/AttachmentsFormSection.tsx
4763
4979
  import { useRef as useRef10 } from "react";
4764
- import { Paperclip as Paperclip2, X as X4 } from "lucide-react";
4765
- import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
4980
+ import { Paperclip as Paperclip3, X as X4 } from "lucide-react";
4981
+ import { Fragment as Fragment7, jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
4766
4982
  function AttachmentsFormSection({
4767
4983
  labels: text,
4768
4984
  attachments,
@@ -4776,18 +4992,18 @@ function AttachmentsFormSection({
4776
4992
  onDismissRejections
4777
4993
  }) {
4778
4994
  const attachmentFileInputRef = useRef10(null);
4779
- return /* @__PURE__ */ jsxs23("div", { className: "space-y-2", children: [
4780
- /* @__PURE__ */ jsx25("span", { className: "block text-sm font-medium", children: text.attachmentsTitle }),
4781
- attachments.length === 0 && pendingUploads.length === 0 ? /* @__PURE__ */ jsx25("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: text.attachmentsEmpty }) : /* @__PURE__ */ jsxs23("ul", { className: "space-y-1", children: [
4782
- attachments.map((attachment, index) => /* @__PURE__ */ jsxs23(
4995
+ return /* @__PURE__ */ jsxs24("div", { className: "space-y-2", children: [
4996
+ /* @__PURE__ */ jsx27("span", { className: "block text-sm font-medium", children: text.attachmentsTitle }),
4997
+ attachments.length === 0 && pendingUploads.length === 0 ? /* @__PURE__ */ jsx27("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: text.attachmentsEmpty }) : /* @__PURE__ */ jsxs24("ul", { className: "space-y-1", children: [
4998
+ attachments.map((attachment, index) => /* @__PURE__ */ jsxs24(
4783
4999
  "li",
4784
5000
  {
4785
5001
  className: "flex items-center gap-2 rounded-md border border-gray-200 px-2 py-1.5 text-xs dark:border-gray-700",
4786
5002
  children: [
4787
- /* @__PURE__ */ jsx25(Paperclip2, { "aria-hidden": "true", className: "h-3.5 w-3.5 flex-none text-gray-400" }),
4788
- /* @__PURE__ */ jsx25("span", { className: "min-w-0 flex-1 truncate", children: attachment.filename }),
4789
- /* @__PURE__ */ jsx25("span", { className: "flex-none text-gray-400", children: formatFileSize(attachment.sizeBytes) }),
4790
- /* @__PURE__ */ jsx25(
5003
+ /* @__PURE__ */ jsx27(Paperclip3, { "aria-hidden": "true", className: "h-3.5 w-3.5 flex-none text-gray-400" }),
5004
+ /* @__PURE__ */ jsx27("span", { className: "min-w-0 flex-1 truncate", children: attachment.filename }),
5005
+ /* @__PURE__ */ jsx27("span", { className: "flex-none text-gray-400", children: formatFileSize(attachment.sizeBytes) }),
5006
+ /* @__PURE__ */ jsx27(
4791
5007
  "button",
4792
5008
  {
4793
5009
  type: "button",
@@ -4798,7 +5014,7 @@ function AttachmentsFormSection({
4798
5014
  children: "\u2191"
4799
5015
  }
4800
5016
  ),
4801
- /* @__PURE__ */ jsx25(
5017
+ /* @__PURE__ */ jsx27(
4802
5018
  "button",
4803
5019
  {
4804
5020
  type: "button",
@@ -4809,32 +5025,32 @@ function AttachmentsFormSection({
4809
5025
  children: "\u2193"
4810
5026
  }
4811
5027
  ),
4812
- /* @__PURE__ */ jsx25(
5028
+ /* @__PURE__ */ jsx27(
4813
5029
  "button",
4814
5030
  {
4815
5031
  type: "button",
4816
5032
  "aria-label": text.attachmentRemove,
4817
5033
  onClick: () => onRemoveAttachment(attachment.uploadId),
4818
5034
  className: "flex-none text-red-600 dark:text-red-400",
4819
- children: /* @__PURE__ */ jsx25(X4, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
5035
+ children: /* @__PURE__ */ jsx27(X4, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
4820
5036
  }
4821
5037
  )
4822
5038
  ]
4823
5039
  },
4824
5040
  attachment.uploadId
4825
5041
  )),
4826
- pendingUploads.map((pending) => /* @__PURE__ */ jsxs23(
5042
+ pendingUploads.map((pending) => /* @__PURE__ */ jsxs24(
4827
5043
  "li",
4828
5044
  {
4829
5045
  className: "flex items-center gap-2 rounded-md border border-gray-200 px-2 py-1.5 text-xs dark:border-gray-700",
4830
5046
  "aria-busy": pending.status === "uploading",
4831
5047
  "aria-live": "polite",
4832
5048
  children: [
4833
- /* @__PURE__ */ jsx25(Paperclip2, { "aria-hidden": "true", className: "h-3.5 w-3.5 flex-none text-gray-400" }),
4834
- /* @__PURE__ */ jsx25("span", { className: "min-w-0 flex-1 truncate", children: pending.file.name }),
4835
- pending.status === "uploading" ? /* @__PURE__ */ jsx25("span", { className: "flex-none text-gray-500 dark:text-gray-400", children: text.attachmentUploading(Math.round(pending.progress * 100)) }) : /* @__PURE__ */ jsxs23(Fragment7, { children: [
4836
- /* @__PURE__ */ jsx25("span", { role: "alert", className: "flex-none text-red-600 dark:text-red-400", children: pending.error }),
4837
- /* @__PURE__ */ jsx25(
5049
+ /* @__PURE__ */ jsx27(Paperclip3, { "aria-hidden": "true", className: "h-3.5 w-3.5 flex-none text-gray-400" }),
5050
+ /* @__PURE__ */ jsx27("span", { className: "min-w-0 flex-1 truncate", children: pending.file.name }),
5051
+ pending.status === "uploading" ? /* @__PURE__ */ jsx27("span", { className: "flex-none text-gray-500 dark:text-gray-400", children: text.attachmentUploading(Math.round(pending.progress * 100)) }) : /* @__PURE__ */ jsxs24(Fragment7, { children: [
5052
+ /* @__PURE__ */ jsx27("span", { role: "alert", className: "flex-none text-red-600 dark:text-red-400", children: pending.error }),
5053
+ /* @__PURE__ */ jsx27(
4838
5054
  "button",
4839
5055
  {
4840
5056
  type: "button",
@@ -4844,14 +5060,14 @@ function AttachmentsFormSection({
4844
5060
  }
4845
5061
  )
4846
5062
  ] }),
4847
- /* @__PURE__ */ jsx25(
5063
+ /* @__PURE__ */ jsx27(
4848
5064
  "button",
4849
5065
  {
4850
5066
  type: "button",
4851
5067
  "aria-label": text.attachmentCancel,
4852
5068
  onClick: () => onCancelUpload(pending.localId),
4853
5069
  className: "flex-none text-gray-400",
4854
- children: /* @__PURE__ */ jsx25(X4, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
5070
+ children: /* @__PURE__ */ jsx27(X4, { "aria-hidden": "true", className: "h-3.5 w-3.5" })
4855
5071
  }
4856
5072
  )
4857
5073
  ]
@@ -4859,11 +5075,11 @@ function AttachmentsFormSection({
4859
5075
  pending.localId
4860
5076
  ))
4861
5077
  ] }),
4862
- attachmentRejections.length > 0 ? /* @__PURE__ */ jsxs23("div", { role: "alert", className: "space-y-0.5 text-xs text-red-600 dark:text-red-400", children: [
4863
- attachmentRejections.map((rejection, index) => /* @__PURE__ */ jsx25("p", { children: rejection.reason === "limit" ? text.attachmentLimitReached : text.attachmentTooLarge(rejection.file.name) }, index)),
4864
- /* @__PURE__ */ jsx25("button", { type: "button", onClick: onDismissRejections, className: "hover:underline", children: text.cancel })
5078
+ attachmentRejections.length > 0 ? /* @__PURE__ */ jsxs24("div", { role: "alert", className: "space-y-0.5 text-xs text-red-600 dark:text-red-400", children: [
5079
+ attachmentRejections.map((rejection, index) => /* @__PURE__ */ jsx27("p", { children: rejection.reason === "limit" ? text.attachmentLimitReached : text.attachmentTooLarge(rejection.file.name) }, index)),
5080
+ /* @__PURE__ */ jsx27("button", { type: "button", onClick: onDismissRejections, className: "hover:underline", children: text.cancel })
4865
5081
  ] }) : null,
4866
- /* @__PURE__ */ jsx25(
5082
+ /* @__PURE__ */ jsx27(
4867
5083
  "input",
4868
5084
  {
4869
5085
  ref: attachmentFileInputRef,
@@ -4876,7 +5092,7 @@ function AttachmentsFormSection({
4876
5092
  }
4877
5093
  }
4878
5094
  ),
4879
- /* @__PURE__ */ jsx25(
5095
+ /* @__PURE__ */ jsx27(
4880
5096
  "button",
4881
5097
  {
4882
5098
  type: "button",
@@ -4889,8 +5105,19 @@ function AttachmentsFormSection({
4889
5105
  }
4890
5106
 
4891
5107
  // src/quickReplies/QuickRepliesWorkspace.tsx
4892
- import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
5108
+ import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
4893
5109
  var TABLE_SKELETON_ROWS = 3;
5110
+ function replaceWithNativeUndo(field, previous, next) {
5111
+ if (!canExecuteFormattingCommand()) return false;
5112
+ const range = changedRange(previous, next);
5113
+ field.focus();
5114
+ field.setSelectionRange(range.start, range.end);
5115
+ try {
5116
+ return range.insertedText ? document.execCommand("insertText", false, range.insertedText) : document.execCommand("delete");
5117
+ } catch {
5118
+ return false;
5119
+ }
5120
+ }
4894
5121
  function QuickRepliesWorkspace({
4895
5122
  api,
4896
5123
  variables,
@@ -4962,14 +5189,46 @@ function QuickRepliesWorkspace({
4962
5189
  field.setSelectionRange(caret, caret);
4963
5190
  });
4964
5191
  };
4965
- return /* @__PURE__ */ jsxs24("div", { className: cn("space-y-4", className), children: [
4966
- /* @__PURE__ */ jsxs24("header", { className: "space-y-0.5", children: [
4967
- /* @__PURE__ */ jsx26("h2", { className: "text-lg font-semibold", children: text.title }),
4968
- /* @__PURE__ */ jsx26("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: text.subtitle(quickReplies.length) })
5192
+ const applyFormatting = (action) => {
5193
+ const field = bodyFieldRef.current;
5194
+ if (!field || !editing) return;
5195
+ const next = computeFormattingEdit({
5196
+ text: editing.body,
5197
+ selectionStart: field.selectionStart,
5198
+ selectionEnd: field.selectionEnd,
5199
+ action,
5200
+ maximumLength: BODY_MAX_LENGTH
5201
+ });
5202
+ if (!next) return;
5203
+ if (!replaceWithNativeUndo(field, editing.body, next.text) || field.value !== next.text) {
5204
+ updateField("body", next.text);
5205
+ }
5206
+ requestAnimationFrame(() => {
5207
+ field.focus();
5208
+ field.setSelectionRange(next.selectionStart, next.selectionEnd);
5209
+ });
5210
+ };
5211
+ const handleBodyKeyDown = (event) => {
5212
+ const action = formattingActionForShortcut({
5213
+ key: event.key,
5214
+ ctrlKey: event.ctrlKey,
5215
+ metaKey: event.metaKey,
5216
+ shiftKey: event.shiftKey,
5217
+ altKey: event.altKey,
5218
+ isComposing: event.nativeEvent.isComposing
5219
+ });
5220
+ if (!action) return;
5221
+ event.preventDefault();
5222
+ applyFormatting(action);
5223
+ };
5224
+ return /* @__PURE__ */ jsxs25("div", { className: cn("space-y-4", className), children: [
5225
+ /* @__PURE__ */ jsxs25("header", { className: "space-y-0.5", children: [
5226
+ /* @__PURE__ */ jsx28("h2", { className: "text-lg font-semibold", children: text.title }),
5227
+ /* @__PURE__ */ jsx28("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: text.subtitle(quickReplies.length) })
4969
5228
  ] }),
4970
- readOnly ? /* @__PURE__ */ jsx26("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: text.readOnlyNotice }) : null,
4971
- /* @__PURE__ */ jsxs24("div", { className: "flex flex-wrap items-center gap-2", children: [
4972
- /* @__PURE__ */ jsx26(
5229
+ readOnly ? /* @__PURE__ */ jsx28("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: text.readOnlyNotice }) : null,
5230
+ /* @__PURE__ */ jsxs25("div", { className: "flex flex-wrap items-center gap-2", children: [
5231
+ /* @__PURE__ */ jsx28(
4973
5232
  "input",
4974
5233
  {
4975
5234
  type: "search",
@@ -4980,158 +5239,176 @@ function QuickRepliesWorkspace({
4980
5239
  className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-900 sm:w-64"
4981
5240
  }
4982
5241
  ),
4983
- !readOnly ? /* @__PURE__ */ jsx26(
5242
+ !readOnly ? /* @__PURE__ */ jsxs25(
4984
5243
  "button",
4985
5244
  {
4986
5245
  type: "button",
4987
5246
  onClick: startCreate,
4988
- className: "cv-header-action ml-auto inline-flex items-center gap-1",
4989
- children: text.create
5247
+ className: "cv-header-action cv-header-action--primary ml-auto inline-flex items-center gap-1",
5248
+ children: [
5249
+ /* @__PURE__ */ jsx28(Plus2, { size: 14, "aria-hidden": "true" }),
5250
+ text.create
5251
+ ]
4990
5252
  }
4991
5253
  ) : null
4992
5254
  ] }),
4993
- isLoading ? /* @__PURE__ */ jsx26("span", { className: "sr-only", "aria-live": "polite", children: text.loading }) : null,
4994
- loadError ? /* @__PURE__ */ jsx26("p", { role: "alert", className: "text-sm text-red-600 dark:text-red-400", children: loadError || text.failure }) : null,
4995
- editing ? /* @__PURE__ */ jsxs24(
5255
+ isLoading ? /* @__PURE__ */ jsx28("span", { className: "sr-only", "aria-live": "polite", children: text.loading }) : null,
5256
+ loadError ? /* @__PURE__ */ jsx28("p", { role: "alert", className: "text-sm text-red-600 dark:text-red-400", children: loadError || text.failure }) : null,
5257
+ editing ? /* @__PURE__ */ jsxs25(
4996
5258
  "form",
4997
5259
  {
4998
- className: "space-y-3 rounded-lg border border-gray-200 p-4 dark:border-gray-700",
5260
+ className: "grid gap-4 rounded-lg border border-gray-200 p-4 dark:border-gray-700 lg:grid-cols-[minmax(0,1fr)_minmax(0,22rem)]",
4999
5261
  onSubmit: (event) => {
5000
5262
  event.preventDefault();
5001
5263
  void submit();
5002
5264
  },
5003
5265
  children: [
5004
- /* @__PURE__ */ jsxs24("div", { className: "space-y-1", children: [
5005
- /* @__PURE__ */ jsx26("label", { className: "block text-sm font-medium", htmlFor: titleFieldId, children: text.fieldTitle }),
5006
- /* @__PURE__ */ jsx26(
5007
- "input",
5008
- {
5009
- id: titleFieldId,
5010
- type: "text",
5011
- maxLength: 40,
5012
- value: editing.title,
5013
- onChange: (event) => updateField("title", event.target.value),
5014
- "aria-invalid": Boolean(fieldErrors.title),
5015
- "aria-describedby": fieldErrors.title ? `${titleFieldId}-error` : void 0,
5016
- className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-900"
5017
- }
5018
- ),
5019
- fieldErrors.title ? /* @__PURE__ */ jsx26("p", { id: `${titleFieldId}-error`, role: "alert", className: "text-xs text-red-600 dark:text-red-400", children: fieldErrors.title }) : null
5020
- ] }),
5021
- /* @__PURE__ */ jsxs24("div", { className: "space-y-1", children: [
5022
- /* @__PURE__ */ jsx26("label", { className: "block text-sm font-medium", htmlFor: shortcutFieldId, children: text.fieldShortcut }),
5023
- /* @__PURE__ */ jsx26(
5024
- "input",
5025
- {
5026
- id: shortcutFieldId,
5027
- type: "text",
5028
- maxLength: 20,
5029
- value: editing.shortcut,
5030
- onChange: (event) => updateField("shortcut", event.target.value),
5031
- "aria-invalid": Boolean(fieldErrors.shortcut),
5032
- "aria-describedby": fieldErrors.shortcut ? `${shortcutFieldId}-error` : `${shortcutFieldId}-hint`,
5033
- className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm font-mono dark:border-gray-700 dark:bg-gray-900"
5034
- }
5035
- ),
5036
- fieldErrors.shortcut ? /* @__PURE__ */ jsx26("p", { id: `${shortcutFieldId}-error`, role: "alert", className: "text-xs text-red-600 dark:text-red-400", children: fieldErrors.shortcut }) : /* @__PURE__ */ jsx26("p", { id: `${shortcutFieldId}-hint`, className: "text-xs text-gray-400", children: text.fieldShortcutHint })
5037
- ] }),
5038
- /* @__PURE__ */ jsxs24("div", { className: "space-y-1", children: [
5039
- /* @__PURE__ */ jsx26("label", { className: "block text-sm font-medium", htmlFor: bodyFieldId, children: text.fieldBody }),
5040
- /* @__PURE__ */ jsx26(
5041
- "textarea",
5266
+ /* @__PURE__ */ jsxs25("div", { className: "space-y-3", children: [
5267
+ /* @__PURE__ */ jsxs25("div", { className: "space-y-1", children: [
5268
+ /* @__PURE__ */ jsx28("label", { className: "block text-sm font-medium", htmlFor: titleFieldId, children: text.fieldTitle }),
5269
+ /* @__PURE__ */ jsx28(
5270
+ "input",
5271
+ {
5272
+ id: titleFieldId,
5273
+ type: "text",
5274
+ maxLength: 40,
5275
+ value: editing.title,
5276
+ onChange: (event) => updateField("title", event.target.value),
5277
+ "aria-invalid": Boolean(fieldErrors.title),
5278
+ "aria-describedby": fieldErrors.title ? `${titleFieldId}-error` : void 0,
5279
+ className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-900"
5280
+ }
5281
+ ),
5282
+ fieldErrors.title ? /* @__PURE__ */ jsx28("p", { id: `${titleFieldId}-error`, role: "alert", className: "text-xs text-red-600 dark:text-red-400", children: fieldErrors.title }) : null
5283
+ ] }),
5284
+ /* @__PURE__ */ jsxs25("div", { className: "space-y-1", children: [
5285
+ /* @__PURE__ */ jsx28("label", { className: "block text-sm font-medium", htmlFor: shortcutFieldId, children: text.fieldShortcut }),
5286
+ /* @__PURE__ */ jsx28(
5287
+ "input",
5288
+ {
5289
+ id: shortcutFieldId,
5290
+ type: "text",
5291
+ maxLength: 20,
5292
+ value: editing.shortcut,
5293
+ onChange: (event) => updateField("shortcut", event.target.value),
5294
+ "aria-invalid": Boolean(fieldErrors.shortcut),
5295
+ "aria-describedby": fieldErrors.shortcut ? `${shortcutFieldId}-error` : `${shortcutFieldId}-hint`,
5296
+ className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm font-mono dark:border-gray-700 dark:bg-gray-900"
5297
+ }
5298
+ ),
5299
+ fieldErrors.shortcut ? /* @__PURE__ */ jsx28("p", { id: `${shortcutFieldId}-error`, role: "alert", className: "text-xs text-red-600 dark:text-red-400", children: fieldErrors.shortcut }) : /* @__PURE__ */ jsx28("p", { id: `${shortcutFieldId}-hint`, className: "text-xs text-gray-400", children: text.fieldShortcutHint })
5300
+ ] }),
5301
+ /* @__PURE__ */ jsxs25("div", { className: "space-y-1", children: [
5302
+ /* @__PURE__ */ jsx28("label", { className: "block text-sm font-medium", htmlFor: bodyFieldId, children: text.fieldBody }),
5303
+ /* @__PURE__ */ jsx28(QuickReplyFormattingToolbar, { labels: text, onFormat: applyFormatting }),
5304
+ /* @__PURE__ */ jsx28(
5305
+ "textarea",
5306
+ {
5307
+ id: bodyFieldId,
5308
+ ref: bodyFieldRef,
5309
+ maxLength: BODY_MAX_LENGTH,
5310
+ rows: 4,
5311
+ value: editing.body,
5312
+ onChange: (event) => updateField("body", event.target.value),
5313
+ onKeyDown: handleBodyKeyDown,
5314
+ "aria-invalid": Boolean(fieldErrors.body),
5315
+ "aria-describedby": fieldErrors.body ? `${bodyFieldId}-error` : void 0,
5316
+ className: "w-full resize-none rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-900"
5317
+ }
5318
+ ),
5319
+ fieldErrors.body ? /* @__PURE__ */ jsx28("p", { id: `${bodyFieldId}-error`, role: "alert", className: "text-xs text-red-600 dark:text-red-400", children: fieldErrors.body }) : null,
5320
+ variables && variables.length > 0 ? /* @__PURE__ */ jsx28("div", { className: "flex flex-wrap gap-1 pt-1", children: variables.map((variable) => /* @__PURE__ */ jsx28(
5321
+ "button",
5322
+ {
5323
+ type: "button",
5324
+ onClick: () => insertVariableAtCursor(variable.marker),
5325
+ "aria-label": `${text.insertVariable}: ${variable.label}`,
5326
+ className: "rounded-full border border-gray-200 px-2 py-0.5 text-xs text-gray-600 hover:bg-gray-100 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800",
5327
+ children: variable.label
5328
+ },
5329
+ variable.id
5330
+ )) }) : null
5331
+ ] }),
5332
+ hasAttachmentsCapability ? /* @__PURE__ */ jsx28(
5333
+ AttachmentsFormSection,
5042
5334
  {
5043
- id: bodyFieldId,
5044
- ref: bodyFieldRef,
5045
- maxLength: 1e3,
5046
- rows: 4,
5047
- value: editing.body,
5048
- onChange: (event) => updateField("body", event.target.value),
5049
- "aria-invalid": Boolean(fieldErrors.body),
5050
- "aria-describedby": fieldErrors.body ? `${bodyFieldId}-error` : void 0,
5051
- className: "w-full resize-none rounded-md border border-gray-300 px-3 py-2 text-sm dark:border-gray-700 dark:bg-gray-900"
5335
+ labels: text,
5336
+ attachments: editing.attachments,
5337
+ pendingUploads,
5338
+ attachmentRejections,
5339
+ onAddFiles: addAttachmentFiles,
5340
+ onRetryUpload: retryAttachmentUpload,
5341
+ onCancelUpload: cancelAttachmentUpload,
5342
+ onRemoveAttachment: removeAttachment,
5343
+ onMoveAttachment: moveAttachmentAt,
5344
+ onDismissRejections: dismissAttachmentRejections
5052
5345
  }
5053
- ),
5054
- fieldErrors.body ? /* @__PURE__ */ jsx26("p", { id: `${bodyFieldId}-error`, role: "alert", className: "text-xs text-red-600 dark:text-red-400", children: fieldErrors.body }) : null,
5055
- variables && variables.length > 0 ? /* @__PURE__ */ jsx26("div", { className: "flex flex-wrap gap-1 pt-1", children: variables.map((variable) => /* @__PURE__ */ jsx26(
5056
- "button",
5057
- {
5058
- type: "button",
5059
- onClick: () => insertVariableAtCursor(variable.marker),
5060
- "aria-label": `${text.insertVariable}: ${variable.label}`,
5061
- className: "rounded-full border border-gray-200 px-2 py-0.5 text-xs text-gray-600 hover:bg-gray-100 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800",
5062
- children: variable.label
5063
- },
5064
- variable.id
5065
- )) }) : null
5346
+ ) : null,
5347
+ saveError ? /* @__PURE__ */ jsx28("p", { role: "alert", className: "text-sm text-red-600 dark:text-red-400", children: saveError }) : null,
5348
+ /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2", children: [
5349
+ /* @__PURE__ */ jsx28(
5350
+ "button",
5351
+ {
5352
+ type: "submit",
5353
+ disabled: isSaving || hasPendingUploads,
5354
+ "aria-busy": isSaving,
5355
+ title: hasPendingUploads ? text.saveBlockedUploading : void 0,
5356
+ className: "cv-header-action inline-flex items-center gap-1 disabled:opacity-40",
5357
+ children: isSaving ? text.saving : hasPendingUploads ? text.saveBlockedUploading : text.save
5358
+ }
5359
+ ),
5360
+ /* @__PURE__ */ jsx28("button", { type: "button", onClick: cancelEdit, className: "text-sm text-gray-500 hover:underline", children: text.cancel })
5361
+ ] })
5066
5362
  ] }),
5067
- hasAttachmentsCapability ? /* @__PURE__ */ jsx26(
5068
- AttachmentsFormSection,
5363
+ /* @__PURE__ */ jsx28(
5364
+ QuickReplyWhatsAppPreview,
5069
5365
  {
5070
- labels: text,
5366
+ body: editing.body,
5367
+ ...variables ? { variables } : {},
5071
5368
  attachments: editing.attachments,
5072
- pendingUploads,
5073
- attachmentRejections,
5074
- onAddFiles: addAttachmentFiles,
5075
- onRetryUpload: retryAttachmentUpload,
5076
- onCancelUpload: cancelAttachmentUpload,
5077
- onRemoveAttachment: removeAttachment,
5078
- onMoveAttachment: moveAttachmentAt,
5079
- onDismissRejections: dismissAttachmentRejections
5369
+ labels: text
5080
5370
  }
5081
- ) : null,
5082
- saveError ? /* @__PURE__ */ jsx26("p", { role: "alert", className: "text-sm text-red-600 dark:text-red-400", children: saveError }) : null,
5083
- /* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-2", children: [
5084
- /* @__PURE__ */ jsx26(
5085
- "button",
5086
- {
5087
- type: "submit",
5088
- disabled: isSaving || hasPendingUploads,
5089
- "aria-busy": isSaving,
5090
- title: hasPendingUploads ? text.saveBlockedUploading : void 0,
5091
- className: "cv-header-action inline-flex items-center gap-1 disabled:opacity-40",
5092
- children: isSaving ? text.saving : hasPendingUploads ? text.saveBlockedUploading : text.save
5093
- }
5094
- ),
5095
- /* @__PURE__ */ jsx26("button", { type: "button", onClick: cancelEdit, className: "text-sm text-gray-500 hover:underline", children: text.cancel })
5096
- ] })
5371
+ )
5097
5372
  ]
5098
5373
  }
5099
5374
  ) : null,
5100
- /* @__PURE__ */ jsx26("div", { className: "cv-table-card", children: /* @__PURE__ */ jsxs24("table", { className: "cv-table", children: [
5101
- /* @__PURE__ */ jsx26("thead", { children: /* @__PURE__ */ jsxs24("tr", { children: [
5102
- /* @__PURE__ */ jsx26("th", { scope: "col", className: "px-3 py-2 text-left text-xs font-medium", children: text.columnTitle }),
5103
- /* @__PURE__ */ jsx26("th", { scope: "col", className: "px-3 py-2 text-left text-xs font-medium", children: text.columnShortcut }),
5104
- /* @__PURE__ */ jsx26("th", { scope: "col", className: "hidden px-3 py-2 text-left text-xs font-medium sm:table-cell", children: text.columnBody }),
5105
- !readOnly ? /* @__PURE__ */ jsx26("th", { scope: "col", className: "px-3 py-2 text-left text-xs font-medium", children: text.columnActions }) : null
5375
+ /* @__PURE__ */ jsx28("div", { className: "cv-table-card", children: /* @__PURE__ */ jsxs25("table", { className: "cv-table", children: [
5376
+ /* @__PURE__ */ jsx28("thead", { children: /* @__PURE__ */ jsxs25("tr", { children: [
5377
+ /* @__PURE__ */ jsx28("th", { scope: "col", className: "px-3 py-2 text-left text-xs font-medium", children: text.columnTitle }),
5378
+ /* @__PURE__ */ jsx28("th", { scope: "col", className: "px-3 py-2 text-left text-xs font-medium", children: text.columnShortcut }),
5379
+ /* @__PURE__ */ jsx28("th", { scope: "col", className: "hidden px-3 py-2 text-left text-xs font-medium sm:table-cell", children: text.columnBody }),
5380
+ !readOnly ? /* @__PURE__ */ jsx28("th", { scope: "col", className: "px-3 py-2 text-left text-xs font-medium", children: text.columnActions }) : null
5106
5381
  ] }) }),
5107
- /* @__PURE__ */ jsxs24("tbody", { children: [
5108
- isLoading ? Array.from({ length: TABLE_SKELETON_ROWS }).map((_, index) => /* @__PURE__ */ jsxs24("tr", { "aria-hidden": "true", children: [
5109
- /* @__PURE__ */ jsx26("td", { className: "px-3 py-3", children: /* @__PURE__ */ jsx26("span", { className: "cv-skeleton-line cv-skeleton-line--title block" }) }),
5110
- /* @__PURE__ */ jsx26("td", { className: "px-3 py-3", children: /* @__PURE__ */ jsx26("span", { className: "cv-skeleton-line cv-skeleton-line--shortcut block" }) }),
5111
- /* @__PURE__ */ jsx26("td", { className: "hidden px-3 py-3 sm:table-cell", children: /* @__PURE__ */ jsx26("span", { className: "cv-skeleton-line cv-skeleton-line--body block" }) }),
5112
- !readOnly ? /* @__PURE__ */ jsx26("td", { className: "px-3 py-3" }) : null
5113
- ] }, index)) : filtered.length === 0 ? /* @__PURE__ */ jsx26("tr", { children: /* @__PURE__ */ jsx26("td", { colSpan: 4, className: "px-3 py-4 text-center text-sm text-gray-500 dark:text-gray-400", children: search.trim() ? text.noResults : text.empty }) }) : null,
5114
- !isLoading && filtered.map((quickReply) => /* @__PURE__ */ jsxs24("tr", { className: cn(deletingId === quickReply.id ? "cv-row-departing" : void 0), children: [
5115
- /* @__PURE__ */ jsx26("td", { className: "px-3 py-2 font-medium", children: quickReply.title }),
5116
- /* @__PURE__ */ jsxs24("td", { className: "px-3 py-2 font-mono text-xs text-gray-500", children: [
5382
+ /* @__PURE__ */ jsxs25("tbody", { children: [
5383
+ isLoading ? Array.from({ length: TABLE_SKELETON_ROWS }).map((_, index) => /* @__PURE__ */ jsxs25("tr", { "aria-hidden": "true", children: [
5384
+ /* @__PURE__ */ jsx28("td", { className: "px-3 py-3", children: /* @__PURE__ */ jsx28("span", { className: "cv-skeleton-line cv-skeleton-line--title block" }) }),
5385
+ /* @__PURE__ */ jsx28("td", { className: "px-3 py-3", children: /* @__PURE__ */ jsx28("span", { className: "cv-skeleton-line cv-skeleton-line--shortcut block" }) }),
5386
+ /* @__PURE__ */ jsx28("td", { className: "hidden px-3 py-3 sm:table-cell", children: /* @__PURE__ */ jsx28("span", { className: "cv-skeleton-line cv-skeleton-line--body block" }) }),
5387
+ !readOnly ? /* @__PURE__ */ jsx28("td", { className: "px-3 py-3" }) : null
5388
+ ] }, index)) : filtered.length === 0 ? /* @__PURE__ */ jsx28("tr", { children: /* @__PURE__ */ jsx28("td", { colSpan: 4, className: "px-3 py-4 text-center text-sm text-gray-500 dark:text-gray-400", children: search.trim() ? text.noResults : text.empty }) }) : null,
5389
+ !isLoading && filtered.map((quickReply) => /* @__PURE__ */ jsxs25("tr", { className: cn(deletingId === quickReply.id ? "cv-row-departing" : void 0), children: [
5390
+ /* @__PURE__ */ jsx28("td", { className: "px-3 py-2 font-medium", children: quickReply.title }),
5391
+ /* @__PURE__ */ jsxs25("td", { className: "px-3 py-2 font-mono text-xs text-gray-500", children: [
5117
5392
  "/",
5118
5393
  quickReply.shortcut
5119
5394
  ] }),
5120
- /* @__PURE__ */ jsx26("td", { className: "hidden max-w-sm truncate px-3 py-2 text-gray-500 sm:table-cell", children: quickReply.body }),
5121
- !readOnly ? /* @__PURE__ */ jsxs24("td", { className: "flex gap-2 px-3 py-2", children: [
5122
- canEdit ? /* @__PURE__ */ jsx26(
5395
+ /* @__PURE__ */ jsx28("td", { className: "hidden max-w-sm truncate px-3 py-2 text-gray-500 sm:table-cell", children: quickReply.body }),
5396
+ !readOnly ? /* @__PURE__ */ jsx28("td", { className: "px-3 py-2", children: /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-1", children: [
5397
+ canEdit ? /* @__PURE__ */ jsx28(
5123
5398
  "button",
5124
5399
  {
5125
5400
  type: "button",
5126
5401
  onClick: () => startEdit(quickReply),
5127
- className: "text-xs text-blue-600 hover:underline dark:text-blue-400",
5128
- children: text.edit
5402
+ "data-cv-tooltip": text.edit,
5403
+ "aria-label": `${text.edit}: ${quickReply.title}`,
5404
+ className: "cv-header-icon",
5405
+ children: /* @__PURE__ */ jsx28(Pencil2, { size: 14, "aria-hidden": "true" })
5129
5406
  }
5130
5407
  ) : null,
5131
5408
  canDelete ? confirmingDeleteId === quickReply.id ? (
5132
5409
  // Linha de confirmação inline em vez de `window.confirm`: trava a aba
5133
5410
  // inteira e não segue os tokens visuais do pacote (`web.md` §14).
5134
- /* @__PURE__ */ jsxs24(
5411
+ /* @__PURE__ */ jsxs25(
5135
5412
  "span",
5136
5413
  {
5137
5414
  role: "group",
@@ -5140,7 +5417,7 @@ function QuickRepliesWorkspace({
5140
5417
  className: "flex items-center gap-2 text-xs",
5141
5418
  children: [
5142
5419
  text.removeConfirm(quickReply.title),
5143
- /* @__PURE__ */ jsx26(
5420
+ /* @__PURE__ */ jsxs25(
5144
5421
  "button",
5145
5422
  {
5146
5423
  ref: confirmButtonRef,
@@ -5149,23 +5426,26 @@ function QuickRepliesWorkspace({
5149
5426
  setConfirmingDeleteId(null);
5150
5427
  void remove(quickReply.id);
5151
5428
  },
5152
- className: "font-medium text-red-600 hover:underline dark:text-red-400",
5153
- children: text.remove
5429
+ className: "cv-header-action cv-header-action--danger inline-flex items-center gap-1",
5430
+ children: [
5431
+ /* @__PURE__ */ jsx28(Trash23, { size: 12, "aria-hidden": "true" }),
5432
+ text.remove
5433
+ ]
5154
5434
  }
5155
5435
  ),
5156
- /* @__PURE__ */ jsx26(
5436
+ /* @__PURE__ */ jsx28(
5157
5437
  "button",
5158
5438
  {
5159
5439
  type: "button",
5160
5440
  onClick: () => cancelDeleteConfirm(quickReply.id),
5161
- className: "text-gray-500 hover:underline dark:text-gray-400",
5441
+ className: "cv-header-action",
5162
5442
  children: text.cancel
5163
5443
  }
5164
5444
  )
5165
5445
  ]
5166
5446
  }
5167
5447
  )
5168
- ) : /* @__PURE__ */ jsx26(
5448
+ ) : /* @__PURE__ */ jsx28(
5169
5449
  "button",
5170
5450
  {
5171
5451
  ref: (node) => {
@@ -5175,11 +5455,13 @@ function QuickRepliesWorkspace({
5175
5455
  disabled: deletingId === quickReply.id,
5176
5456
  "aria-busy": deletingId === quickReply.id,
5177
5457
  onClick: () => setConfirmingDeleteId(quickReply.id),
5178
- className: "text-xs text-red-600 hover:underline disabled:opacity-50 dark:text-red-400",
5179
- children: deletingId === quickReply.id ? text.deleting : text.remove
5458
+ "data-cv-tooltip": deletingId === quickReply.id ? text.deleting : text.remove,
5459
+ "aria-label": `${deletingId === quickReply.id ? text.deleting : text.remove}: ${quickReply.title}`,
5460
+ className: "cv-header-icon disabled:opacity-40",
5461
+ children: /* @__PURE__ */ jsx28(Trash23, { size: 14, "aria-hidden": "true", className: "text-red-500" })
5180
5462
  }
5181
5463
  ) : null
5182
- ] }) : null
5464
+ ] }) }) : null
5183
5465
  ] }, quickReply.id))
5184
5466
  ] })
5185
5467
  ] }) })
@@ -5192,7 +5474,7 @@ import { Check as Check2, CheckCheck, FlaskConical, Hourglass as Hourglass2, Mai
5192
5474
 
5193
5475
  // src/workspace/BulkTemplateModal.tsx
5194
5476
  import { useEffect as useEffect14, useMemo as useMemo4, useState as useState19 } from "react";
5195
- import { jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
5477
+ import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
5196
5478
  function BulkTemplateModal({
5197
5479
  labels,
5198
5480
  expiredCount,
@@ -5223,15 +5505,15 @@ function BulkTemplateModal({
5223
5505
  if (!term) return templates;
5224
5506
  return templates.filter((template) => template.name.toLowerCase().includes(term));
5225
5507
  }, [templates, search]);
5226
- return /* @__PURE__ */ jsx27("div", { className: "cv-workspace-modal", role: "dialog", "aria-modal": "true", "aria-label": labels.templateModalTitle, children: /* @__PURE__ */ jsxs25("div", { className: "cv-workspace-modal__box", children: [
5227
- /* @__PURE__ */ jsxs25("header", { className: "cv-workspace-modal__header", children: [
5228
- /* @__PURE__ */ jsxs25("div", { children: [
5229
- /* @__PURE__ */ jsx27("h3", { children: labels.templateModalTitle }),
5230
- /* @__PURE__ */ jsx27("p", { children: labels.templateModalAvailable(templates.length) })
5508
+ return /* @__PURE__ */ jsx29("div", { className: "cv-workspace-modal", role: "dialog", "aria-modal": "true", "aria-label": labels.templateModalTitle, children: /* @__PURE__ */ jsxs26("div", { className: "cv-workspace-modal__box", children: [
5509
+ /* @__PURE__ */ jsxs26("header", { className: "cv-workspace-modal__header", children: [
5510
+ /* @__PURE__ */ jsxs26("div", { children: [
5511
+ /* @__PURE__ */ jsx29("h3", { children: labels.templateModalTitle }),
5512
+ /* @__PURE__ */ jsx29("p", { children: labels.templateModalAvailable(templates.length) })
5231
5513
  ] }),
5232
- /* @__PURE__ */ jsx27("button", { "data-cv-tooltip": labels.templateModalCancel, type: "button", onClick: onClose, "aria-label": labels.templateModalCancel, children: "\u2715" })
5514
+ /* @__PURE__ */ jsx29("button", { "data-cv-tooltip": labels.templateModalCancel, type: "button", onClick: onClose, "aria-label": labels.templateModalCancel, children: "\u2715" })
5233
5515
  ] }),
5234
- /* @__PURE__ */ jsx27("div", { className: "cv-workspace-modal__search", children: /* @__PURE__ */ jsx27(
5516
+ /* @__PURE__ */ jsx29("div", { className: "cv-workspace-modal__search", children: /* @__PURE__ */ jsx29(
5235
5517
  "input",
5236
5518
  {
5237
5519
  type: "search",
@@ -5241,9 +5523,9 @@ function BulkTemplateModal({
5241
5523
  autoFocus: true
5242
5524
  }
5243
5525
  ) }),
5244
- /* @__PURE__ */ jsxs25("div", { className: "cv-workspace-modal__list", children: [
5245
- filtered.length === 0 ? /* @__PURE__ */ jsx27("p", { className: "cv-workspace-empty", children: labels.templateModalEmpty }) : null,
5246
- filtered.map((template) => /* @__PURE__ */ jsxs25(
5526
+ /* @__PURE__ */ jsxs26("div", { className: "cv-workspace-modal__list", children: [
5527
+ filtered.length === 0 ? /* @__PURE__ */ jsx29("p", { className: "cv-workspace-empty", children: labels.templateModalEmpty }) : null,
5528
+ filtered.map((template) => /* @__PURE__ */ jsxs26(
5247
5529
  "button",
5248
5530
  {
5249
5531
  "data-cv-tooltip": template.name,
@@ -5253,8 +5535,8 @@ function BulkTemplateModal({
5253
5535
  "aria-pressed": template.name === selected,
5254
5536
  className: `cv-workspace-modal__item${template.name === selected ? " cv-workspace-modal__item--on" : ""}`,
5255
5537
  children: [
5256
- /* @__PURE__ */ jsx27("span", { className: "cv-workspace-modal__item-name", children: template.name }),
5257
- /* @__PURE__ */ jsxs25("span", { className: "cv-workspace-modal__item-meta", children: [
5538
+ /* @__PURE__ */ jsx29("span", { className: "cv-workspace-modal__item-name", children: template.name }),
5539
+ /* @__PURE__ */ jsxs26("span", { className: "cv-workspace-modal__item-meta", children: [
5258
5540
  template.language,
5259
5541
  template.category ? ` \xB7 ${template.category.toLowerCase()}` : ""
5260
5542
  ] })
@@ -5263,10 +5545,10 @@ function BulkTemplateModal({
5263
5545
  template.name
5264
5546
  ))
5265
5547
  ] }),
5266
- expiredCount === 0 ? /* @__PURE__ */ jsx27("p", { className: "cv-workspace-modal__warning", children: labels.templateModalNoneExpired }) : null,
5267
- /* @__PURE__ */ jsxs25("footer", { className: "cv-workspace-modal__footer", children: [
5268
- /* @__PURE__ */ jsx27("button", { "data-cv-tooltip": labels.templateModalCancel, "aria-label": labels.templateModalCancel, type: "button", onClick: onClose, children: labels.templateModalCancel }),
5269
- /* @__PURE__ */ jsx27(
5548
+ expiredCount === 0 ? /* @__PURE__ */ jsx29("p", { className: "cv-workspace-modal__warning", children: labels.templateModalNoneExpired }) : null,
5549
+ /* @__PURE__ */ jsxs26("footer", { className: "cv-workspace-modal__footer", children: [
5550
+ /* @__PURE__ */ jsx29("button", { "data-cv-tooltip": labels.templateModalCancel, "aria-label": labels.templateModalCancel, type: "button", onClick: onClose, children: labels.templateModalCancel }),
5551
+ /* @__PURE__ */ jsx29(
5270
5552
  "button",
5271
5553
  {
5272
5554
  "data-cv-tooltip": sending ? labels.templateModalSending : labels.templateModalSend(expiredCount),
@@ -5304,7 +5586,7 @@ function resolveConversationVariables({
5304
5586
 
5305
5587
  // src/workspace/QueuedAttachmentsList.tsx
5306
5588
  import { useEffect as useEffect15, useRef as useRef12, useState as useState20 } from "react";
5307
- import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
5589
+ import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
5308
5590
  function nameOf(item) {
5309
5591
  return item.kind === "local" ? item.file.name : item.filename;
5310
5592
  }
@@ -5339,7 +5621,7 @@ function AttachmentThumbnail({
5339
5621
  };
5340
5622
  }, [isImage, uploadId, getThumbnailUrl]);
5341
5623
  if (!isImage) return null;
5342
- return /* @__PURE__ */ jsx28("span", { className: "cv-attachment-item__thumbnail", "aria-hidden": "true", children: url ? /* @__PURE__ */ jsx28("img", { src: url, alt: "" }) : null });
5624
+ return /* @__PURE__ */ jsx30("span", { className: "cv-attachment-item__thumbnail", "aria-hidden": "true", children: url ? /* @__PURE__ */ jsx30("img", { src: url, alt: "" }) : null });
5343
5625
  }
5344
5626
  function departedItemsOf(previouslyRendered, items) {
5345
5627
  const currentKeys = new Set(items.map(attachmentKey));
@@ -5386,25 +5668,25 @@ function QueuedAttachmentsList({
5386
5668
  if (status === "skipped") return labels.skipped;
5387
5669
  return labels.waiting;
5388
5670
  };
5389
- return /* @__PURE__ */ jsx28("ul", { className: "cv-workspace-attachments", "aria-busy": busy, "aria-live": "polite", children: rendered.map((item) => {
5671
+ return /* @__PURE__ */ jsx30("ul", { className: "cv-workspace-attachments", "aria-busy": busy, "aria-live": "polite", children: rendered.map((item) => {
5390
5672
  const key = attachmentKey(item);
5391
5673
  const status = statusOf2(key);
5392
5674
  const isDeparting = departingKeys.has(key);
5393
- return /* @__PURE__ */ jsxs26(
5675
+ return /* @__PURE__ */ jsxs27(
5394
5676
  "li",
5395
5677
  {
5396
5678
  className: `cv-attachment-item cv-attachment-item--${status}${isDeparting ? " cv-attachment-item--departing" : ""}`,
5397
5679
  children: [
5398
- /* @__PURE__ */ jsx28(AttachmentThumbnail, { item, getThumbnailUrl }),
5399
- /* @__PURE__ */ jsxs26("span", { className: "cv-attachment-item__info", children: [
5400
- /* @__PURE__ */ jsx28("span", { className: "cv-attachment-item__name", children: nameOf(item) }),
5401
- /* @__PURE__ */ jsxs26("span", { className: "cv-attachment-item__meta", children: [
5680
+ /* @__PURE__ */ jsx30(AttachmentThumbnail, { item, getThumbnailUrl }),
5681
+ /* @__PURE__ */ jsxs27("span", { className: "cv-attachment-item__info", children: [
5682
+ /* @__PURE__ */ jsx30("span", { className: "cv-attachment-item__name", children: nameOf(item) }),
5683
+ /* @__PURE__ */ jsxs27("span", { className: "cv-attachment-item__meta", children: [
5402
5684
  formatFileSize(sizeOf(item)),
5403
5685
  " \xB7 ",
5404
5686
  statusLabelOf(status)
5405
5687
  ] })
5406
5688
  ] }),
5407
- (status === "failed" || status === "skipped") && onRetry ? /* @__PURE__ */ jsx28(
5689
+ (status === "failed" || status === "skipped") && onRetry ? /* @__PURE__ */ jsx30(
5408
5690
  "button",
5409
5691
  {
5410
5692
  type: "button",
@@ -5415,7 +5697,7 @@ function QueuedAttachmentsList({
5415
5697
  children: labels.retry
5416
5698
  }
5417
5699
  ) : null,
5418
- /* @__PURE__ */ jsx28(
5700
+ /* @__PURE__ */ jsx30(
5419
5701
  "button",
5420
5702
  {
5421
5703
  "data-cv-tooltip": labels.remove,
@@ -5497,6 +5779,14 @@ function useComposerAttachmentRetry(params) {
5497
5779
  if (isSameConversation()) setAttachmentStatus((current) => ({ ...current, [statusKey]: status }));
5498
5780
  }
5499
5781
  });
5782
+ if (shouldResetRetryKey({
5783
+ current: retryIdempotencyKeyRef.current,
5784
+ attempted: idempotencyState,
5785
+ sentAttachmentKeys: result.sentAttachmentKeys,
5786
+ uploadId: item.uploadId
5787
+ })) {
5788
+ retryIdempotencyKeyRef.current = void 0;
5789
+ }
5500
5790
  setQueue(
5501
5791
  (current) => resolveRetryOutcome({
5502
5792
  conversationIdAtRetry,
@@ -5621,15 +5911,14 @@ function useComposerQueue(params) {
5621
5911
  if (!isSameConversation()) return;
5622
5912
  if (!result.textSent) return;
5623
5913
  const sentKeys = new Set(result.sentAttachmentKeys);
5624
- let queueEmptyAfterSend = false;
5625
- setQueue((current) => {
5626
- const next = current.filter((item) => !sentKeys.has(attachmentKey(item)));
5627
- queueEmptyAfterSend = next.length === 0;
5914
+ setQueue((current) => current.filter((item) => !sentKeys.has(attachmentKey(item))));
5915
+ setAttachmentStatus((current) => {
5916
+ const next = { ...current };
5917
+ for (const key of sentKeys) delete next[key];
5628
5918
  return next;
5629
5919
  });
5630
- if (queueEmptyAfterSend) {
5920
+ if (idempotencyKeyRef.current === idempotencyState && hasSentEveryStoredUpload(idempotencyState.uploadIds, result.sentAttachmentKeys)) {
5631
5921
  idempotencyKeyRef.current = void 0;
5632
- setAttachmentStatus({});
5633
5922
  }
5634
5923
  if (draft.trim()) setDraft("");
5635
5924
  await refetch();
@@ -5670,7 +5959,7 @@ function useComposerQueue(params) {
5670
5959
  }
5671
5960
 
5672
5961
  // src/workspace/ConversationPane.tsx
5673
- import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
5962
+ import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
5674
5963
  function ConversationPane({
5675
5964
  conversation,
5676
5965
  now,
@@ -5823,8 +6112,8 @@ function ConversationPane({
5823
6112
  }
5824
6113
  } : void 0;
5825
6114
  const botOwnsConversation = Boolean(requireTakeoverToReply) && conversation.mode !== "human";
5826
- return /* @__PURE__ */ jsxs27("div", { className: "cv-workspace-pane", children: [
5827
- /* @__PURE__ */ jsx29(
6115
+ return /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-pane", children: [
6116
+ /* @__PURE__ */ jsx31(
5828
6117
  ConversationHeader,
5829
6118
  {
5830
6119
  conversation,
@@ -5839,10 +6128,10 @@ function ConversationPane({
5839
6128
  ...extraUtilities ? { extraUtilities } : {}
5840
6129
  }
5841
6130
  ),
5842
- contextEntries && contextEntries.length > 0 || flowLabel ? /* @__PURE__ */ jsx29(ConversationContextPanel, { entries: contextEntries ?? [], ...flowLabel ? { flowLabel } : {} }) : null,
5843
- /* @__PURE__ */ jsx29(ConversationDocumentsPanel, { conversationId: conversation.id, open: documentsOpen }),
6131
+ contextEntries && contextEntries.length > 0 || flowLabel ? /* @__PURE__ */ jsx31(ConversationContextPanel, { entries: contextEntries ?? [], ...flowLabel ? { flowLabel } : {} }) : null,
6132
+ /* @__PURE__ */ jsx31(ConversationDocumentsPanel, { conversationId: conversation.id, open: documentsOpen }),
5844
6133
  renderAboveTranscript?.(conversation, conversationContext),
5845
- /* @__PURE__ */ jsx29(
6134
+ /* @__PURE__ */ jsx31(
5846
6135
  ConversationWallpaper,
5847
6136
  {
5848
6137
  ref: scroll.containerRef,
@@ -5851,9 +6140,9 @@ function ConversationPane({
5851
6140
  children: messages.map((message, index) => {
5852
6141
  const previous = index > 0 ? messages[index - 1] : void 0;
5853
6142
  const startsNewDay = !previous || new Date(message.timestamp).toDateString() !== new Date(previous.timestamp).toDateString();
5854
- return /* @__PURE__ */ jsxs27("div", { children: [
5855
- startsNewDay ? /* @__PURE__ */ jsx29(DateDivider, { iso: message.timestamp }) : null,
5856
- /* @__PURE__ */ jsx29(
6143
+ return /* @__PURE__ */ jsxs28("div", { children: [
6144
+ startsNewDay ? /* @__PURE__ */ jsx31(DateDivider, { iso: message.timestamp }) : null,
6145
+ /* @__PURE__ */ jsx31(
5857
6146
  MessageBubble,
5858
6147
  {
5859
6148
  message,
@@ -5870,10 +6159,10 @@ function ConversationPane({
5870
6159
  })
5871
6160
  }
5872
6161
  ),
5873
- messageSelection && selectedMessageIds.size > 0 ? /* @__PURE__ */ jsxs27("div", { className: "cv-workspace-selection", children: [
5874
- /* @__PURE__ */ jsx29("span", { children: labels.messagesSelected(selectedMessageIds.size) }),
5875
- /* @__PURE__ */ jsxs27("div", { className: "cv-workspace-selection__actions", children: [
5876
- /* @__PURE__ */ jsx29(
6162
+ messageSelection && selectedMessageIds.size > 0 ? /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-selection", children: [
6163
+ /* @__PURE__ */ jsx31("span", { children: labels.messagesSelected(selectedMessageIds.size) }),
6164
+ /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-selection__actions", children: [
6165
+ /* @__PURE__ */ jsx31(
5877
6166
  "button",
5878
6167
  {
5879
6168
  "data-cv-tooltip": labels.bulkClear,
@@ -5883,7 +6172,7 @@ function ConversationPane({
5883
6172
  children: labels.bulkClear
5884
6173
  }
5885
6174
  ),
5886
- /* @__PURE__ */ jsx29(
6175
+ /* @__PURE__ */ jsx31(
5887
6176
  "button",
5888
6177
  {
5889
6178
  "data-cv-tooltip": labels.copySelected,
@@ -5895,11 +6184,11 @@ function ConversationPane({
5895
6184
  )
5896
6185
  ] })
5897
6186
  ] }) : null,
5898
- sendFailure ? /* @__PURE__ */ jsx29("p", { role: "alert", className: "cv-workspace-alert", children: sendFailure }) : null,
5899
- blocked ? /* @__PURE__ */ jsx29(WindowExpiredNotice, { disabled: busy, onSendTemplate: () => void handleSendTemplate() }) : botOwnsConversation ? (
6187
+ sendFailure ? /* @__PURE__ */ jsx31("p", { role: "alert", className: "cv-workspace-alert", children: sendFailure }) : null,
6188
+ blocked ? /* @__PURE__ */ jsx31(WindowExpiredNotice, { disabled: busy, onSendTemplate: () => void handleSendTemplate() }) : botOwnsConversation ? (
5900
6189
  // Responder com a conversa no bot atropelaria o fluxo automático no meio de uma pergunta.
5901
- /* @__PURE__ */ jsx29("p", { className: "cv-workspace-notice", children: labels.takeoverToReply })
5902
- ) : composer === "rich" ? /* @__PURE__ */ jsx29(
6190
+ /* @__PURE__ */ jsx31("p", { className: "cv-workspace-notice", children: labels.takeoverToReply })
6191
+ ) : composer === "rich" ? /* @__PURE__ */ jsx31(
5903
6192
  RichMessageComposer,
5904
6193
  {
5905
6194
  value: draft,
@@ -5920,7 +6209,7 @@ function ConversationPane({
5920
6209
  isSending: busy || isSendingDraft,
5921
6210
  hasQueuedAttachments: queue.length > 0,
5922
6211
  ...onRecordAudio ? {
5923
- idleAction: /* @__PURE__ */ jsx29(
6212
+ idleAction: /* @__PURE__ */ jsx31(
5924
6213
  AudioRecorderButton,
5925
6214
  {
5926
6215
  onRecorded: (file) => void runSend(() => onRecordAudio(file), labels.recordFailure),
@@ -5929,7 +6218,7 @@ function ConversationPane({
5929
6218
  )
5930
6219
  } : {},
5931
6220
  ...queue.length > 0 ? {
5932
- attachmentsPreview: /* @__PURE__ */ jsx29(
6221
+ attachmentsPreview: /* @__PURE__ */ jsx31(
5933
6222
  QueuedAttachmentsList,
5934
6223
  {
5935
6224
  items: queue,
@@ -5955,7 +6244,7 @@ function ConversationPane({
5955
6244
  ...composerVariables ? { variables: [...composerVariables] } : {},
5956
6245
  ...savedQuickReplies ? { savedQuickReplies } : {}
5957
6246
  }
5958
- ) : /* @__PURE__ */ jsx29(
6247
+ ) : /* @__PURE__ */ jsx31(
5959
6248
  MessageComposer,
5960
6249
  {
5961
6250
  value: draft,
@@ -5972,7 +6261,7 @@ function ConversationPane({
5972
6261
  }
5973
6262
 
5974
6263
  // src/workspace/ConversationsInboxList.tsx
5975
- import { jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
6264
+ import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
5976
6265
  function ConversationsInboxList({
5977
6266
  inbox,
5978
6267
  labels,
@@ -5983,13 +6272,13 @@ function ConversationsInboxList({
5983
6272
  onSendTemplateToSelected
5984
6273
  }) {
5985
6274
  const hasSelection = inbox.selectedIds.size > 0;
5986
- return /* @__PURE__ */ jsxs28("aside", { className, children: [
5987
- hasSelection ? /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-bulk", children: [
5988
- /* @__PURE__ */ jsx30("span", { className: "cv-workspace-bulk__count", children: labels.bulkSelected(inbox.selectedIds.size) }),
5989
- /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-bulk__actions", children: [
5990
- /* @__PURE__ */ jsx30("button", { "data-cv-tooltip": labels.bulkClear, "aria-label": labels.bulkClear, type: "button", onClick: inbox.clearBulkSelection, children: labels.bulkClear }),
5991
- onSendTemplateToSelected ? /* @__PURE__ */ jsx30("button", { "data-cv-tooltip": labels.bulkTemplate, "aria-label": labels.bulkTemplate, type: "button", onClick: onSendTemplateToSelected, disabled: inbox.busy, children: labels.bulkTemplate }) : null,
5992
- inbox.canFinalize ? /* @__PURE__ */ jsx30(
6275
+ return /* @__PURE__ */ jsxs29("aside", { className, children: [
6276
+ hasSelection ? /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-bulk", children: [
6277
+ /* @__PURE__ */ jsx32("span", { className: "cv-workspace-bulk__count", children: labels.bulkSelected(inbox.selectedIds.size) }),
6278
+ /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-bulk__actions", children: [
6279
+ /* @__PURE__ */ jsx32("button", { "data-cv-tooltip": labels.bulkClear, "aria-label": labels.bulkClear, type: "button", onClick: inbox.clearBulkSelection, children: labels.bulkClear }),
6280
+ onSendTemplateToSelected ? /* @__PURE__ */ jsx32("button", { "data-cv-tooltip": labels.bulkTemplate, "aria-label": labels.bulkTemplate, type: "button", onClick: onSendTemplateToSelected, disabled: inbox.busy, children: labels.bulkTemplate }) : null,
6281
+ inbox.canFinalize ? /* @__PURE__ */ jsx32(
5993
6282
  "button",
5994
6283
  {
5995
6284
  "data-cv-tooltip": labels.bulkFinalize,
@@ -6007,8 +6296,8 @@ function ConversationsInboxList({
6007
6296
  renderBulkActions?.(inbox)
6008
6297
  ] })
6009
6298
  ] }) : null,
6010
- /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-filters", children: [
6011
- /* @__PURE__ */ jsx30(
6299
+ /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-filters", children: [
6300
+ /* @__PURE__ */ jsx32(
6012
6301
  "input",
6013
6302
  {
6014
6303
  type: "search",
@@ -6018,9 +6307,9 @@ function ConversationsInboxList({
6018
6307
  className: "cv-workspace-search"
6019
6308
  }
6020
6309
  ),
6021
- /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-chips", children: [
6022
- /* @__PURE__ */ jsx30("span", { className: "cv-workspace-chips__legend", children: labels.windowLegend }),
6023
- WINDOW_FILTERS.map((filter) => /* @__PURE__ */ jsx30(
6310
+ /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-chips", children: [
6311
+ /* @__PURE__ */ jsx32("span", { className: "cv-workspace-chips__legend", children: labels.windowLegend }),
6312
+ WINDOW_FILTERS.map((filter) => /* @__PURE__ */ jsx32(
6024
6313
  "button",
6025
6314
  {
6026
6315
  type: "button",
@@ -6038,9 +6327,9 @@ function ConversationsInboxList({
6038
6327
  filter.value
6039
6328
  ))
6040
6329
  ] }),
6041
- inbox.channelFilters.length > 0 ? /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-chips", children: [
6042
- /* @__PURE__ */ jsx30("span", { className: "cv-workspace-chips__legend", children: labels.channelLegend }),
6043
- inbox.channelFilters.map((filter) => /* @__PURE__ */ jsxs28(
6330
+ inbox.channelFilters.length > 0 ? /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-chips", children: [
6331
+ /* @__PURE__ */ jsx32("span", { className: "cv-workspace-chips__legend", children: labels.channelLegend }),
6332
+ inbox.channelFilters.map((filter) => /* @__PURE__ */ jsxs29(
6044
6333
  "button",
6045
6334
  {
6046
6335
  "data-cv-tooltip": filter.label,
@@ -6050,7 +6339,7 @@ function ConversationsInboxList({
6050
6339
  "aria-pressed": inbox.channelFilter === filter.value,
6051
6340
  className: `cv-workspace-chip${inbox.channelFilter === filter.value ? " cv-workspace-chip--on" : ""}`,
6052
6341
  children: [
6053
- filter.value === CHANNEL_FILTER_ALL ? null : /* @__PURE__ */ jsx30(ChannelIcon, { channel: filter.value }),
6342
+ filter.value === CHANNEL_FILTER_ALL ? null : /* @__PURE__ */ jsx32(ChannelIcon, { channel: filter.value }),
6054
6343
  filter.label
6055
6344
  ]
6056
6345
  },
@@ -6058,14 +6347,14 @@ function ConversationsInboxList({
6058
6347
  ))
6059
6348
  ] }) : null,
6060
6349
  renderFilters?.(inbox),
6061
- /* @__PURE__ */ jsxs28("label", { className: "cv-workspace-selectall", children: [
6062
- /* @__PURE__ */ jsx30("input", { type: "checkbox", checked: inbox.allOnPageSelected, onChange: inbox.toggleSelectAllOnPage }),
6350
+ /* @__PURE__ */ jsxs29("label", { className: "cv-workspace-selectall", children: [
6351
+ /* @__PURE__ */ jsx32("input", { type: "checkbox", checked: inbox.allOnPageSelected, onChange: inbox.toggleSelectAllOnPage }),
6063
6352
  labels.selectAll
6064
6353
  ] })
6065
6354
  ] }),
6066
- /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-rows", children: [
6355
+ /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-rows", children: [
6067
6356
  inbox.pageConversations.map(
6068
- (conversation) => renderRow ? /* @__PURE__ */ jsx30("div", { children: renderRow(conversation) }, conversation.id) : /* @__PURE__ */ jsx30(
6357
+ (conversation) => renderRow ? /* @__PURE__ */ jsx32("div", { children: renderRow(conversation) }, conversation.id) : /* @__PURE__ */ jsx32(
6069
6358
  ConversationRow,
6070
6359
  {
6071
6360
  conversation,
@@ -6080,13 +6369,13 @@ function ConversationsInboxList({
6080
6369
  conversation.id
6081
6370
  )
6082
6371
  ),
6083
- !inbox.loading && inbox.filteredCount === 0 ? /* @__PURE__ */ jsx30("p", { className: "cv-workspace-empty", children: labels.emptyList }) : null
6372
+ !inbox.loading && inbox.filteredCount === 0 ? /* @__PURE__ */ jsx32("p", { className: "cv-workspace-empty", children: labels.emptyList }) : null
6084
6373
  ] }),
6085
- /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-pager", children: [
6086
- /* @__PURE__ */ jsx30("span", { children: labels.rangeOf(inbox.firstOnPage, inbox.lastOnPage, inbox.filteredCount) }),
6087
- /* @__PURE__ */ jsxs28("div", { className: "cv-workspace-pager__buttons", children: [
6088
- /* @__PURE__ */ jsx30("button", { type: "button", onClick: () => inbox.goToPage(1), disabled: inbox.page === 1, "aria-label": PAGINATION_LABELS.first, "data-cv-tooltip": PAGINATION_LABELS.first, children: "\xAB" }),
6089
- /* @__PURE__ */ jsx30(
6374
+ /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-pager", children: [
6375
+ /* @__PURE__ */ jsx32("span", { children: labels.rangeOf(inbox.firstOnPage, inbox.lastOnPage, inbox.filteredCount) }),
6376
+ /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-pager__buttons", children: [
6377
+ /* @__PURE__ */ jsx32("button", { type: "button", onClick: () => inbox.goToPage(1), disabled: inbox.page === 1, "aria-label": PAGINATION_LABELS.first, "data-cv-tooltip": PAGINATION_LABELS.first, children: "\xAB" }),
6378
+ /* @__PURE__ */ jsx32(
6090
6379
  "button",
6091
6380
  {
6092
6381
  type: "button",
@@ -6097,8 +6386,8 @@ function ConversationsInboxList({
6097
6386
  children: "\u2039"
6098
6387
  }
6099
6388
  ),
6100
- /* @__PURE__ */ jsx30("span", { children: labels.pageOf(inbox.page, inbox.pageCount) }),
6101
- /* @__PURE__ */ jsx30(
6389
+ /* @__PURE__ */ jsx32("span", { children: labels.pageOf(inbox.page, inbox.pageCount) }),
6390
+ /* @__PURE__ */ jsx32(
6102
6391
  "button",
6103
6392
  {
6104
6393
  type: "button",
@@ -6109,7 +6398,7 @@ function ConversationsInboxList({
6109
6398
  children: "\u203A"
6110
6399
  }
6111
6400
  ),
6112
- /* @__PURE__ */ jsx30(
6401
+ /* @__PURE__ */ jsx32(
6113
6402
  "button",
6114
6403
  {
6115
6404
  type: "button",
@@ -6355,7 +6644,7 @@ function useConversationsInbox(params = {}) {
6355
6644
  }
6356
6645
 
6357
6646
  // src/workspace/ConversationsWorkspace.tsx
6358
- import { Fragment as Fragment8, jsx as jsx31, jsxs as jsxs29 } from "react/jsx-runtime";
6647
+ import { Fragment as Fragment8, jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
6359
6648
  function ConversationsWorkspace({
6360
6649
  labels: labelsOverride,
6361
6650
  filters,
@@ -6431,50 +6720,50 @@ function ConversationsWorkspace({
6431
6720
  ...fromProduct,
6432
6721
  {
6433
6722
  key: "simulator",
6434
- icon: simulator?.icon ?? /* @__PURE__ */ jsx31(FlaskConical, { size: ICON_SIZE_ACTION }),
6723
+ icon: simulator?.icon ?? /* @__PURE__ */ jsx33(FlaskConical, { size: ICON_SIZE_ACTION }),
6435
6724
  label: simulator?.label ?? "Simular cliente",
6436
6725
  active: simulatorOpen,
6437
6726
  run: () => setSimulatorOpen((open) => !open)
6438
6727
  }
6439
6728
  ];
6440
6729
  }, [selected, extraUtilitiesFor, simulatorEnabled, simulator, simulatorOpen]);
6441
- return /* @__PURE__ */ jsxs29("div", { className: `cv-workspace${className ? ` ${className}` : ""}`, children: [
6442
- /* @__PURE__ */ jsx31(TooltipLayer, {}),
6443
- /* @__PURE__ */ jsxs29("header", { className: "cv-workspace-header", children: [
6444
- /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-header__titles", children: [
6445
- /* @__PURE__ */ jsx31("h1", { children: labels.title }),
6446
- /* @__PURE__ */ jsxs29("p", { children: [
6447
- /* @__PURE__ */ jsxs29("span", { "data-cv-tooltip": labels.conversations, className: "cv-stat", children: [
6448
- /* @__PURE__ */ jsx31(MessagesSquare, { size: ICON_SIZE_INLINE, "aria-hidden": "true" }),
6730
+ return /* @__PURE__ */ jsxs30("div", { className: `cv-workspace${className ? ` ${className}` : ""}`, children: [
6731
+ /* @__PURE__ */ jsx33(TooltipLayer, {}),
6732
+ /* @__PURE__ */ jsxs30("header", { className: "cv-workspace-header", children: [
6733
+ /* @__PURE__ */ jsxs30("div", { className: "cv-workspace-header__titles", children: [
6734
+ /* @__PURE__ */ jsx33("h1", { children: labels.title }),
6735
+ /* @__PURE__ */ jsxs30("p", { children: [
6736
+ /* @__PURE__ */ jsxs30("span", { "data-cv-tooltip": labels.conversations, className: "cv-stat", children: [
6737
+ /* @__PURE__ */ jsx33(MessagesSquare, { size: ICON_SIZE_INLINE, "aria-hidden": "true" }),
6449
6738
  " ",
6450
6739
  inbox.totalCount,
6451
- /* @__PURE__ */ jsxs29("span", { className: "cv-only-wide", children: [
6740
+ /* @__PURE__ */ jsxs30("span", { className: "cv-only-wide", children: [
6452
6741
  " ",
6453
6742
  labels.conversations
6454
6743
  ] })
6455
6744
  ] }),
6456
- /* @__PURE__ */ jsxs29("span", { "data-cv-tooltip": labels.waiting, className: "cv-stat cv-workspace-header__waiting", children: [
6457
- /* @__PURE__ */ jsx31(Hourglass2, { size: ICON_SIZE_INLINE, "aria-hidden": "true" }),
6745
+ /* @__PURE__ */ jsxs30("span", { "data-cv-tooltip": labels.waiting, className: "cv-stat cv-workspace-header__waiting", children: [
6746
+ /* @__PURE__ */ jsx33(Hourglass2, { size: ICON_SIZE_INLINE, "aria-hidden": "true" }),
6458
6747
  " ",
6459
6748
  inbox.waitingCount,
6460
- /* @__PURE__ */ jsxs29("span", { className: "cv-only-wide", children: [
6749
+ /* @__PURE__ */ jsxs30("span", { className: "cv-only-wide", children: [
6461
6750
  " ",
6462
6751
  labels.waiting
6463
6752
  ] })
6464
6753
  ] }),
6465
- /* @__PURE__ */ jsxs29("span", { "data-cv-tooltip": labels.unread, className: "cv-stat", children: [
6466
- /* @__PURE__ */ jsx31(Mail2, { size: ICON_SIZE_INLINE, "aria-hidden": "true" }),
6754
+ /* @__PURE__ */ jsxs30("span", { "data-cv-tooltip": labels.unread, className: "cv-stat", children: [
6755
+ /* @__PURE__ */ jsx33(Mail2, { size: ICON_SIZE_INLINE, "aria-hidden": "true" }),
6467
6756
  " ",
6468
6757
  inbox.unreadCount,
6469
- /* @__PURE__ */ jsxs29("span", { className: "cv-only-wide", children: [
6758
+ /* @__PURE__ */ jsxs30("span", { className: "cv-only-wide", children: [
6470
6759
  " ",
6471
6760
  labels.unread
6472
6761
  ] })
6473
6762
  ] })
6474
6763
  ] })
6475
6764
  ] }),
6476
- /* @__PURE__ */ jsxs29("div", { className: "cv-workspace-header__actions", children: [
6477
- /* @__PURE__ */ jsxs29(
6765
+ /* @__PURE__ */ jsxs30("div", { className: "cv-workspace-header__actions", children: [
6766
+ /* @__PURE__ */ jsxs30(
6478
6767
  "button",
6479
6768
  {
6480
6769
  type: "button",
@@ -6484,12 +6773,12 @@ function ConversationsWorkspace({
6484
6773
  "aria-label": labels.waitingOnly,
6485
6774
  className: inbox.waitingOnly ? "cv-workspace-toggle cv-workspace-toggle--on" : "cv-workspace-toggle",
6486
6775
  children: [
6487
- /* @__PURE__ */ jsx31(Hourglass2, { size: ICON_SIZE_ACTION, "aria-hidden": "true" }),
6488
- /* @__PURE__ */ jsx31("span", { className: "cv-only-wide", children: labels.waitingOnly })
6776
+ /* @__PURE__ */ jsx33(Hourglass2, { size: ICON_SIZE_ACTION, "aria-hidden": "true" }),
6777
+ /* @__PURE__ */ jsx33("span", { className: "cv-only-wide", children: labels.waitingOnly })
6489
6778
  ]
6490
6779
  }
6491
6780
  ),
6492
- /* @__PURE__ */ jsxs29(
6781
+ /* @__PURE__ */ jsxs30(
6493
6782
  "button",
6494
6783
  {
6495
6784
  type: "button",
@@ -6499,9 +6788,9 @@ function ConversationsWorkspace({
6499
6788
  "aria-label": labels.markSelectedAsRead,
6500
6789
  className: "cv-workspace-toggle",
6501
6790
  children: [
6502
- /* @__PURE__ */ jsx31(Check2, { size: ICON_SIZE_ACTION, "aria-hidden": "true" }),
6503
- /* @__PURE__ */ jsx31("span", { className: "cv-only-wide", children: labels.markSelectedAsRead }),
6504
- inbox.selectedIds.size > 0 ? /* @__PURE__ */ jsxs29("span", { children: [
6791
+ /* @__PURE__ */ jsx33(Check2, { size: ICON_SIZE_ACTION, "aria-hidden": "true" }),
6792
+ /* @__PURE__ */ jsx33("span", { className: "cv-only-wide", children: labels.markSelectedAsRead }),
6793
+ inbox.selectedIds.size > 0 ? /* @__PURE__ */ jsxs30("span", { children: [
6505
6794
  "(",
6506
6795
  inbox.selectedIds.size,
6507
6796
  ")"
@@ -6509,7 +6798,7 @@ function ConversationsWorkspace({
6509
6798
  ]
6510
6799
  }
6511
6800
  ),
6512
- inbox.canMarkAllRead && inbox.unreadCount > 0 ? /* @__PURE__ */ jsxs29(
6801
+ inbox.canMarkAllRead && inbox.unreadCount > 0 ? /* @__PURE__ */ jsxs30(
6513
6802
  "button",
6514
6803
  {
6515
6804
  type: "button",
@@ -6519,28 +6808,28 @@ function ConversationsWorkspace({
6519
6808
  "aria-label": labels.markAllAsRead,
6520
6809
  className: "cv-workspace-toggle",
6521
6810
  children: [
6522
- /* @__PURE__ */ jsx31(CheckCheck, { size: ICON_SIZE_ACTION, "aria-hidden": "true" }),
6523
- /* @__PURE__ */ jsx31("span", { className: "cv-only-wide", children: labels.markAllAsRead })
6811
+ /* @__PURE__ */ jsx33(CheckCheck, { size: ICON_SIZE_ACTION, "aria-hidden": "true" }),
6812
+ /* @__PURE__ */ jsx33("span", { className: "cv-only-wide", children: labels.markAllAsRead })
6524
6813
  ]
6525
6814
  }
6526
6815
  ) : null,
6527
6816
  renderHeaderActions?.(inbox)
6528
6817
  ] })
6529
6818
  ] }),
6530
- inbox.loadFailure ? /* @__PURE__ */ jsxs29("p", { role: "alert", className: "cv-workspace-failure", children: [
6819
+ inbox.loadFailure ? /* @__PURE__ */ jsxs30("p", { role: "alert", className: "cv-workspace-failure", children: [
6531
6820
  inbox.loadFailure,
6532
- signInHref ? /* @__PURE__ */ jsxs29(Fragment8, { children: [
6821
+ signInHref ? /* @__PURE__ */ jsxs30(Fragment8, { children: [
6533
6822
  " ",
6534
- /* @__PURE__ */ jsx31("a", { href: signInHref, className: "cv-workspace-failure__link", children: labels.signIn })
6823
+ /* @__PURE__ */ jsx33("a", { href: signInHref, className: "cv-workspace-failure__link", children: labels.signIn })
6535
6824
  ] }) : null
6536
6825
  ] }) : null,
6537
- /* @__PURE__ */ jsxs29(
6826
+ /* @__PURE__ */ jsxs30(
6538
6827
  "div",
6539
6828
  {
6540
6829
  className: `cv-workspace-grid${showSimulator ? " cv-workspace-grid--with-simulator" : ""}`,
6541
6830
  "data-detail": selected ? "open" : "closed",
6542
6831
  children: [
6543
- /* @__PURE__ */ jsx31(
6832
+ /* @__PURE__ */ jsx33(
6544
6833
  ConversationsInboxList,
6545
6834
  {
6546
6835
  inbox,
@@ -6552,7 +6841,7 @@ function ConversationsWorkspace({
6552
6841
  ...onSendTemplateToSelected ? { onSendTemplateToSelected: () => onSendTemplateToSelected(inbox) } : inbox.canListTemplates ? { onSendTemplateToSelected: () => setTemplateModalOpen(true) } : {}
6553
6842
  }
6554
6843
  ),
6555
- /* @__PURE__ */ jsx31("section", { className: "cv-workspace-detail", children: selected ? /* @__PURE__ */ jsx31(
6844
+ /* @__PURE__ */ jsx33("section", { className: "cv-workspace-detail", children: selected ? /* @__PURE__ */ jsx33(
6556
6845
  ConversationPane,
6557
6846
  {
6558
6847
  conversation: selected,
@@ -6582,14 +6871,14 @@ function ConversationsWorkspace({
6582
6871
  ...renderAboveTranscript ? { renderAboveTranscript } : {},
6583
6872
  ...onAttach ? { onAttach: (file) => onAttach(selected, file) } : {}
6584
6873
  }
6585
- ) : /* @__PURE__ */ jsx31("p", { className: "cv-workspace-empty", children: labels.emptyDetail }) }),
6874
+ ) : /* @__PURE__ */ jsx33("p", { className: "cv-workspace-empty", children: labels.emptyDetail }) }),
6586
6875
  showSimulator && selected ? (
6587
6876
  // `min-height:0` junto do `min-width:0`: sem isso a linha do grid cresce com o conteúdo do
6588
6877
  // painel, o scroll interno nunca ativa e quem rola passa a ser a página inteira.
6589
- /* @__PURE__ */ jsx31("div", { className: "cv-workspace-simulator", children: simulator?.render ? simulator.render({ conversationId: selected.id, channel, close: () => setSimulatorOpen(false) }) : simulatorClient && conversations ? (
6878
+ /* @__PURE__ */ jsx33("div", { className: "cv-workspace-simulator", children: simulator?.render ? simulator.render({ conversationId: selected.id, channel, close: () => setSimulatorOpen(false) }) : simulatorClient && conversations ? (
6590
6879
  // `key` pela conversa: trocar de contato sem remontar deixaria o transcript e o campo
6591
6880
  // de texto do contato anterior na tela.
6592
- /* @__PURE__ */ jsx31(
6881
+ /* @__PURE__ */ jsx33(
6593
6882
  ConversationSimulatorPanel,
6594
6883
  {
6595
6884
  client: simulatorClient,
@@ -6610,7 +6899,7 @@ function ConversationsWorkspace({
6610
6899
  ]
6611
6900
  }
6612
6901
  ),
6613
- templateModalOpen ? /* @__PURE__ */ jsx31(
6902
+ templateModalOpen ? /* @__PURE__ */ jsx33(
6614
6903
  BulkTemplateModal,
6615
6904
  {
6616
6905
  labels,
@@ -6712,10 +7001,12 @@ export {
6712
7001
  TooltipLayer,
6713
7002
  TopicsForm,
6714
7003
  TranscriptionSettingsForm,
7004
+ WHATSAPP_MARKER_BY_ACTION,
6715
7005
  WINDOW_FILTERS,
6716
7006
  WelcomeFarewellForm,
6717
7007
  WhatsAppCreateTemplateForm,
6718
7008
  WhatsAppMessageEditor,
7009
+ WhatsAppMessagePreview,
6719
7010
  WhatsAppTemplateSettingsForm,
6720
7011
  WhatsAppTemplatesSettings,
6721
7012
  WindowExpiredNotice,