@adatechnology/conversations-ui 0.3.2 → 0.4.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.
@@ -64,6 +64,147 @@ function useConversationLocales() {
64
64
  return useContext(ConversationLocalesContext);
65
65
  }
66
66
 
67
+ // src/lib/phone.ts
68
+ function formatPhone(number) {
69
+ const digits = number.replace(/\D/g, "");
70
+ if (digits.length === 13) {
71
+ return `+${digits.slice(0, 2)} (${digits.slice(2, 4)}) ${digits.slice(4, 9)}-${digits.slice(9, 13)}`;
72
+ }
73
+ if (digits.length === 12) {
74
+ return `+${digits.slice(0, 2)} (${digits.slice(2, 4)}) ${digits.slice(4, 8)}-${digits.slice(8, 12)}`;
75
+ }
76
+ if (digits.length === 11) {
77
+ return `(${digits.slice(0, 2)}) ${digits.slice(2, 7)}-${digits.slice(7, 11)}`;
78
+ }
79
+ if (digits.length === 10) {
80
+ return `(${digits.slice(0, 2)}) ${digits.slice(2, 6)}-${digits.slice(6, 10)}`;
81
+ }
82
+ return number;
83
+ }
84
+ var COUNTRY_FLAG_BY_DIAL_CODE = {
85
+ "55": "\u{1F1E7}\u{1F1F7}",
86
+ "351": "\u{1F1F5}\u{1F1F9}",
87
+ "34": "\u{1F1EA}\u{1F1F8}",
88
+ "54": "\u{1F1E6}\u{1F1F7}",
89
+ "56": "\u{1F1E8}\u{1F1F1}",
90
+ "57": "\u{1F1E8}\u{1F1F4}",
91
+ "52": "\u{1F1F2}\u{1F1FD}",
92
+ "598": "\u{1F1FA}\u{1F1FE}",
93
+ "595": "\u{1F1F5}\u{1F1FE}",
94
+ "44": "\u{1F1EC}\u{1F1E7}",
95
+ "49": "\u{1F1E9}\u{1F1EA}",
96
+ "39": "\u{1F1EE}\u{1F1F9}",
97
+ "33": "\u{1F1EB}\u{1F1F7}"
98
+ };
99
+ function phoneCountryFlag(number) {
100
+ const digits = number.replace(/\D/g, "");
101
+ for (const length of [3, 2, 1]) {
102
+ const flag = COUNTRY_FLAG_BY_DIAL_CODE[digits.slice(0, length)];
103
+ if (flag) return flag;
104
+ }
105
+ return "";
106
+ }
107
+ function phoneInitials(number) {
108
+ const digits = number.replace(/\D/g, "");
109
+ return digits.slice(-2);
110
+ }
111
+
112
+ // src/conversationChannel.ts
113
+ var CONVERSATION_CHANNEL = {
114
+ WHATSAPP: "whatsapp",
115
+ MESSENGER: "messenger",
116
+ INSTAGRAM: "instagram",
117
+ WEBCHAT: "webchat",
118
+ EMAIL: "email"
119
+ };
120
+ var DEFAULT_CONVERSATION_CHANNEL = CONVERSATION_CHANNEL.WHATSAPP;
121
+ var REOPEN_MECHANISM = {
122
+ TEMPLATE: "template",
123
+ TAG: "tag",
124
+ NONE: "none"
125
+ };
126
+ var HANDLE_KIND = {
127
+ PHONE: "phone",
128
+ USERNAME: "username",
129
+ SESSION: "session",
130
+ EMAIL: "email"
131
+ };
132
+ var CHANNEL_CAPABILITIES = {
133
+ [CONVERSATION_CHANNEL.WHATSAPP]: {
134
+ label: "WhatsApp",
135
+ icon: "\u{1F4AC}",
136
+ reopenMechanism: REOPEN_MECHANISM.TEMPLATE,
137
+ handleKind: HANDLE_KIND.PHONE
138
+ },
139
+ [CONVERSATION_CHANNEL.MESSENGER]: {
140
+ // Messenger também tem 24h, mas reabre com message tag — não com template aprovado.
141
+ label: "Messenger",
142
+ icon: "\u{1F4E8}",
143
+ reopenMechanism: REOPEN_MECHANISM.TAG,
144
+ handleKind: HANDLE_KIND.USERNAME
145
+ },
146
+ [CONVERSATION_CHANNEL.INSTAGRAM]: {
147
+ label: "Instagram",
148
+ icon: "\u{1F4F7}",
149
+ reopenMechanism: REOPEN_MECHANISM.TAG,
150
+ handleKind: HANDLE_KIND.USERNAME
151
+ },
152
+ [CONVERSATION_CHANNEL.WEBCHAT]: {
153
+ // Chat próprio: sem intermediário, sem janela. Bloquear o composer aqui seria inventar limite.
154
+ label: "Chat do site",
155
+ icon: "\u{1F310}",
156
+ reopenMechanism: REOPEN_MECHANISM.NONE,
157
+ handleKind: HANDLE_KIND.SESSION
158
+ },
159
+ [CONVERSATION_CHANNEL.EMAIL]: {
160
+ // RF10: e-mail entra no vocabulário; ele não reabre por template nem por tag — é só resposta.
161
+ label: "E-mail",
162
+ icon: "\u2709\uFE0F",
163
+ reopenMechanism: REOPEN_MECHANISM.NONE,
164
+ handleKind: HANDLE_KIND.EMAIL
165
+ }
166
+ };
167
+ function capabilitiesOf(channel) {
168
+ return CHANNEL_CAPABILITIES[channel ?? DEFAULT_CONVERSATION_CHANNEL];
169
+ }
170
+ var CHANNEL_FILTER_ALL = "all";
171
+ function channelFiltersFor(conversations) {
172
+ const present = new Set(
173
+ conversations.map((conversation) => conversation.channel ?? DEFAULT_CONVERSATION_CHANNEL)
174
+ );
175
+ if (present.size < 2) return [];
176
+ const ordered = Object.keys(CHANNEL_CAPABILITIES).filter((channel) => present.has(channel));
177
+ return [
178
+ { value: CHANNEL_FILTER_ALL, label: "Todos" },
179
+ ...ordered.map((channel) => ({ value: channel, label: CHANNEL_CAPABILITIES[channel].label }))
180
+ ];
181
+ }
182
+ function formatContactHandle(params) {
183
+ const { handleKind } = capabilitiesOf(params.channel);
184
+ if (handleKind === HANDLE_KIND.PHONE) return formatPhone(params.handle);
185
+ if (handleKind === HANDLE_KIND.USERNAME) return params.handle.startsWith("@") ? params.handle : `@${params.handle}`;
186
+ if (handleKind === HANDLE_KIND.EMAIL) return params.handle;
187
+ return `Visitante ${params.handle.slice(-6)}`;
188
+ }
189
+ function contactFlag(params) {
190
+ return capabilitiesOf(params.channel).handleKind === HANDLE_KIND.PHONE ? phoneCountryFlag(params.handle) : "";
191
+ }
192
+
193
+ // src/channelCapability.ts
194
+ import {
195
+ CHANNEL_CAPABILITIES as CORE_CHANNEL_CAPABILITIES,
196
+ CONVERSATION_CHANNEL as CORE_CONVERSATION_CHANNEL
197
+ } from "@adatechnology/conversation-contracts";
198
+ var CORE_CHANNELS = CORE_CONVERSATION_CHANNEL;
199
+ function isCoreChannel(channel) {
200
+ return CORE_CHANNELS.includes(channel);
201
+ }
202
+ var META_ONLY_CHANNEL_CAPABILITY = CORE_CHANNEL_CAPABILITIES.whatsapp;
203
+ function channelCapabilityFor(channel) {
204
+ const resolved = channel ?? DEFAULT_CONVERSATION_CHANNEL;
205
+ return isCoreChannel(resolved) ? CORE_CHANNEL_CAPABILITIES[resolved] : META_ONLY_CHANNEL_CAPABILITY;
206
+ }
207
+
67
208
  // src/StatusTicks.tsx
68
209
  import { AlertTriangle } from "lucide-react";
69
210
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
@@ -757,8 +898,11 @@ function MessageBubble({
757
898
  onResolveMediaUrl,
758
899
  onInteractiveSelect,
759
900
  onTranscribeAudio,
901
+ channel,
760
902
  className
761
903
  }) {
904
+ const confirmsRead = channelCapabilityFor(channel).confirmsRead;
905
+ const displayStatus = message.status === "read" && !confirmsRead ? "delivered" : message.status;
762
906
  const { bubble, selection } = useConversationLocales();
763
907
  const [lightboxSrc, setLightboxSrc] = useState5(null);
764
908
  const context = useConversations();
@@ -781,7 +925,7 @@ function MessageBubble({
781
925
  return trimmed && trimmed !== message.filename;
782
926
  }) : void 0;
783
927
  const displayName = message.sender === "agent" && senderName ? senderName : bubble[message.sender] ?? message.sender;
784
- const tooltipText = message.status === "read" && message.readAt ? `${bubble.readAt}${formatDateTime(message.readAt)}` : message.status === "failed" ? bubble.windowExpired : void 0;
928
+ const tooltipText = displayStatus === "read" && message.readAt ? `${bubble.readAt}${formatDateTime(message.readAt)}` : displayStatus === "failed" ? bubble.windowExpired : void 0;
785
929
  const tailCornerClass = isFirstInGroup ? isMine ? "rounded-tr-md" : "rounded-tl-md" : "";
786
930
  const checkbox = /* @__PURE__ */ jsx10(
787
931
  "button",
@@ -863,7 +1007,7 @@ function MessageBubble({
863
1007
  ] }),
864
1008
  /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-end gap-1 mt-0.5 select-none", children: [
865
1009
  /* @__PURE__ */ jsx10("span", { className: "text-xs text-black/40 dark:text-white/40 font-medium", children: formatTimestamp(message.timestamp) }),
866
- isMine && message.status && /* @__PURE__ */ jsx10(StatusTicks, { status: message.status, title: tooltipText })
1010
+ isMine && displayStatus && /* @__PURE__ */ jsx10(StatusTicks, { status: displayStatus, title: tooltipText })
867
1011
  ] })
868
1012
  ]
869
1013
  }
@@ -1129,7 +1273,7 @@ var EmojiPicker = ({ onSelect, labels, className = "" }) => {
1129
1273
  };
1130
1274
 
1131
1275
  // src/AudioRecorderButton.tsx
1132
- import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef2, useState as useState7 } from "react";
1276
+ import { useCallback as useCallback3, useEffect as useEffect2, useId, useRef as useRef2, useState as useState7 } from "react";
1133
1277
  import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1134
1278
  var DEFAULT_AUDIO_RECORDER_BUTTON_LABELS = {
1135
1279
  start: "Gravar \xE1udio",
@@ -1159,9 +1303,12 @@ function AudioRecorderButton({
1159
1303
  reviewBeforeSend = true,
1160
1304
  maxDurationMilliseconds = DEFAULT_MAX_RECORDING_MILLISECONDS,
1161
1305
  labels,
1162
- disabled
1306
+ disabled,
1307
+ disabledHint
1163
1308
  }) {
1164
1309
  const labelOf = (key) => labels?.[key] ?? DEFAULT_AUDIO_RECORDER_BUTTON_LABELS[key];
1310
+ const disabledHintId = useId();
1311
+ const showDisabledHint = Boolean(disabled && disabledHint);
1165
1312
  const [isRecording, setIsRecording] = useState7(false);
1166
1313
  const [pending, setPending] = useState7(void 0);
1167
1314
  const recorderRef = useRef2(null);
@@ -1271,8 +1418,9 @@ function AudioRecorderButton({
1271
1418
  type: "button",
1272
1419
  disabled: disabled || pending !== void 0,
1273
1420
  onClick: () => isRecording ? stop() : void start(),
1274
- "data-cv-tooltip": toggleLabel,
1421
+ "data-cv-tooltip": showDisabledHint ? disabledHint : toggleLabel,
1275
1422
  "aria-label": toggleLabel,
1423
+ "aria-describedby": showDisabledHint ? disabledHintId : void 0,
1276
1424
  "aria-pressed": isRecording,
1277
1425
  className: `flex h-10 w-10 items-center justify-center rounded-full transition-colors disabled:opacity-50 ${isRecording ? "animate-pulse bg-red-500 text-white ring-4 ring-red-500/30 hover:bg-red-600" : "text-gray-500 hover:bg-gray-200 dark:hover:bg-gray-700"}`,
1278
1426
  children: isRecording ? /* @__PURE__ */ jsx13("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx13("rect", { x: "6", y: "6", width: "12", height: "12", rx: "2" }) }) : /* @__PURE__ */ jsxs9("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
@@ -1281,7 +1429,8 @@ function AudioRecorderButton({
1281
1429
  /* @__PURE__ */ jsx13("line", { x1: "12", y1: "18", x2: "12", y2: "22" })
1282
1430
  ] })
1283
1431
  }
1284
- )
1432
+ ),
1433
+ showDisabledHint && /* @__PURE__ */ jsx13("span", { id: disabledHintId, className: "sr-only", children: disabledHint })
1285
1434
  ] })
1286
1435
  );
1287
1436
  }
@@ -1292,7 +1441,7 @@ import {
1292
1441
  useRef as useRef5,
1293
1442
  useCallback as useCallback5,
1294
1443
  useEffect as useEffect5,
1295
- useId
1444
+ useId as useId2
1296
1445
  } from "react";
1297
1446
 
1298
1447
  // src/composer.constant.ts
@@ -1602,7 +1751,10 @@ var DEFAULT_MESSAGE_COMPOSER_LABELS = {
1602
1751
  attach: "Anexar",
1603
1752
  send: "Enviar",
1604
1753
  removeAttachment: "Remover anexo",
1605
- quickReplies: "Mensagens prontas"
1754
+ quickReplies: "Mensagens prontas",
1755
+ attachDisabledHint: "Este canal n\xE3o aceita anexo.",
1756
+ audioDisabledHint: "Este canal n\xE3o grava \xE1udio.",
1757
+ quickRepliesDisabledHint: "Este canal n\xE3o aceita mensagem pronta."
1606
1758
  };
1607
1759
  var DEFAULT_ACCEPTED_FILE_TYPES = [
1608
1760
  "image/jpeg,image/png,image/webp",
@@ -1623,6 +1775,7 @@ var MessageComposer = ({
1623
1775
  quickReplyVariables,
1624
1776
  savedQuickReplies,
1625
1777
  features,
1778
+ channel,
1626
1779
  placeholder = "Digite uma mensagem...",
1627
1780
  maxLength,
1628
1781
  disabled = false,
@@ -1637,12 +1790,21 @@ var MessageComposer = ({
1637
1790
  const sendLabel = labels?.send ?? DEFAULT_MESSAGE_COMPOSER_LABELS.send;
1638
1791
  const removeAttachmentLabel = labels?.removeAttachment ?? DEFAULT_MESSAGE_COMPOSER_LABELS.removeAttachment;
1639
1792
  const quickRepliesLabel = labels?.quickReplies ?? DEFAULT_MESSAGE_COMPOSER_LABELS.quickReplies;
1793
+ const attachDisabledHintLabel = labels?.attachDisabledHint ?? DEFAULT_MESSAGE_COMPOSER_LABELS.attachDisabledHint;
1794
+ const audioDisabledHintLabel = labels?.audioDisabledHint ?? DEFAULT_MESSAGE_COMPOSER_LABELS.audioDisabledHint;
1795
+ const quickRepliesDisabledHintLabel = labels?.quickRepliesDisabledHint ?? DEFAULT_MESSAGE_COMPOSER_LABELS.quickRepliesDisabledHint;
1796
+ const capability = channelCapabilityFor(channel);
1797
+ const attachmentsAllowed = capability.attachments.accepted;
1798
+ const audioRecordingAllowed = capability.audio.records;
1799
+ const quickRepliesAllowed = capability.quickReplies;
1800
+ const attachHintId = useId2();
1801
+ const quickRepliesHintId = useId2();
1640
1802
  const [internalText, setInternalText] = useState9("");
1641
1803
  const [showEmoji, setShowEmoji] = useState9(false);
1642
1804
  const [attachments, setAttachments] = useState9([]);
1643
1805
  const textareaRef = useRef5(null);
1644
1806
  const fileInputRef = useRef5(null);
1645
- const quickRepliesListboxId = useId();
1807
+ const quickRepliesListboxId = useId2();
1646
1808
  const [isQuickRepliesOpen, setIsQuickRepliesOpen] = useState9(false);
1647
1809
  const [quickRepliesTerm, setQuickRepliesTerm] = useState9("");
1648
1810
  const [shortcutStart, setShortcutStart] = useState9(null);
@@ -1823,7 +1985,14 @@ var MessageComposer = ({
1823
1985
  return next;
1824
1986
  });
1825
1987
  }, []);
1826
- const effectiveIdleAction = idleAction ?? (onAttach ? /* @__PURE__ */ jsx15(AudioRecorderButton, { onRecorded: (file) => onAttach(file) }) : void 0);
1988
+ const effectiveIdleAction = idleAction ?? (onAttach ? /* @__PURE__ */ jsx15(
1989
+ AudioRecorderButton,
1990
+ {
1991
+ onRecorded: (file) => onAttach(file),
1992
+ disabled: !audioRecordingAllowed,
1993
+ disabledHint: audioRecordingAllowed ? void 0 : audioDisabledHintLabel
1994
+ }
1995
+ ) : void 0);
1827
1996
  const canSend = text.trim().length > 0 || attachments.length > 0;
1828
1997
  const remaining = maxLength ? maxLength - text.length : null;
1829
1998
  return (
@@ -1940,18 +2109,23 @@ var MessageComposer = ({
1940
2109
  quickRepliesMode
1941
2110
  ) })
1942
2111
  ] }),
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" }) })
1953
- }
1954
- ),
2112
+ showQuickRepliesButton && /* @__PURE__ */ jsxs11(Fragment3, { children: [
2113
+ /* @__PURE__ */ jsx15(
2114
+ "button",
2115
+ {
2116
+ ref: quickRepliesTriggerRef,
2117
+ type: "button",
2118
+ disabled: !quickRepliesAllowed,
2119
+ "data-cv-tooltip": quickRepliesAllowed ? quickRepliesLabel : quickRepliesDisabledHintLabel,
2120
+ "aria-label": quickRepliesLabel,
2121
+ "aria-describedby": quickRepliesAllowed ? void 0 : quickRepliesHintId,
2122
+ onClick: openQuickRepliesViaButton,
2123
+ className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 flex-shrink-0 transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent",
2124
+ 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" }) })
2125
+ }
2126
+ ),
2127
+ !quickRepliesAllowed && /* @__PURE__ */ jsx15("span", { id: quickRepliesHintId, className: "sr-only", children: quickRepliesDisabledHintLabel })
2128
+ ] }),
1955
2129
  showAttachButton && /* @__PURE__ */ jsxs11(Fragment3, { children: [
1956
2130
  /* @__PURE__ */ jsx15(
1957
2131
  "input",
@@ -1967,13 +2141,16 @@ var MessageComposer = ({
1967
2141
  /* @__PURE__ */ jsx15(
1968
2142
  "button",
1969
2143
  {
1970
- "data-cv-tooltip": attachLabel,
2144
+ disabled: !attachmentsAllowed,
2145
+ "data-cv-tooltip": attachmentsAllowed ? attachLabel : attachDisabledHintLabel,
1971
2146
  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",
2147
+ "aria-describedby": attachmentsAllowed ? void 0 : attachHintId,
2148
+ className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 flex-shrink-0 transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-transparent",
1973
2149
  "aria-label": attachLabel,
1974
2150
  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
2151
  }
1976
- )
2152
+ ),
2153
+ !attachmentsAllowed && /* @__PURE__ */ jsx15("span", { id: attachHintId, className: "sr-only", children: attachDisabledHintLabel })
1977
2154
  ] }),
1978
2155
  !canSend && effectiveIdleAction ? /* @__PURE__ */ jsx15("div", { className: "flex-shrink-0", children: effectiveIdleAction }) : /* @__PURE__ */ jsx15(
1979
2156
  "button",
@@ -2073,130 +2250,6 @@ function formatDividerLabel(iso, dateDivider) {
2073
2250
  return date.toLocaleDateString("pt-BR", { day: "2-digit", month: "long", year: "numeric" });
2074
2251
  }
2075
2252
 
2076
- // src/lib/phone.ts
2077
- function formatPhone(number) {
2078
- const digits = number.replace(/\D/g, "");
2079
- if (digits.length === 13) {
2080
- return `+${digits.slice(0, 2)} (${digits.slice(2, 4)}) ${digits.slice(4, 9)}-${digits.slice(9, 13)}`;
2081
- }
2082
- if (digits.length === 12) {
2083
- return `+${digits.slice(0, 2)} (${digits.slice(2, 4)}) ${digits.slice(4, 8)}-${digits.slice(8, 12)}`;
2084
- }
2085
- if (digits.length === 11) {
2086
- return `(${digits.slice(0, 2)}) ${digits.slice(2, 7)}-${digits.slice(7, 11)}`;
2087
- }
2088
- if (digits.length === 10) {
2089
- return `(${digits.slice(0, 2)}) ${digits.slice(2, 6)}-${digits.slice(6, 10)}`;
2090
- }
2091
- return number;
2092
- }
2093
- var COUNTRY_FLAG_BY_DIAL_CODE = {
2094
- "55": "\u{1F1E7}\u{1F1F7}",
2095
- "351": "\u{1F1F5}\u{1F1F9}",
2096
- "34": "\u{1F1EA}\u{1F1F8}",
2097
- "54": "\u{1F1E6}\u{1F1F7}",
2098
- "56": "\u{1F1E8}\u{1F1F1}",
2099
- "57": "\u{1F1E8}\u{1F1F4}",
2100
- "52": "\u{1F1F2}\u{1F1FD}",
2101
- "598": "\u{1F1FA}\u{1F1FE}",
2102
- "595": "\u{1F1F5}\u{1F1FE}",
2103
- "44": "\u{1F1EC}\u{1F1E7}",
2104
- "49": "\u{1F1E9}\u{1F1EA}",
2105
- "39": "\u{1F1EE}\u{1F1F9}",
2106
- "33": "\u{1F1EB}\u{1F1F7}"
2107
- };
2108
- function phoneCountryFlag(number) {
2109
- const digits = number.replace(/\D/g, "");
2110
- for (const length of [3, 2, 1]) {
2111
- const flag = COUNTRY_FLAG_BY_DIAL_CODE[digits.slice(0, length)];
2112
- if (flag) return flag;
2113
- }
2114
- return "";
2115
- }
2116
- function phoneInitials(number) {
2117
- const digits = number.replace(/\D/g, "");
2118
- return digits.slice(-2);
2119
- }
2120
-
2121
- // src/conversationChannel.ts
2122
- var CONVERSATION_CHANNEL = {
2123
- WHATSAPP: "whatsapp",
2124
- MESSENGER: "messenger",
2125
- INSTAGRAM: "instagram",
2126
- WEBCHAT: "webchat"
2127
- };
2128
- var DEFAULT_CONVERSATION_CHANNEL = CONVERSATION_CHANNEL.WHATSAPP;
2129
- var REOPEN_MECHANISM = {
2130
- TEMPLATE: "template",
2131
- TAG: "tag",
2132
- NONE: "none"
2133
- };
2134
- var HANDLE_KIND = {
2135
- PHONE: "phone",
2136
- USERNAME: "username",
2137
- SESSION: "session"
2138
- };
2139
- var CHANNEL_CAPABILITIES = {
2140
- [CONVERSATION_CHANNEL.WHATSAPP]: {
2141
- label: "WhatsApp",
2142
- icon: "\u{1F4AC}",
2143
- hasSessionWindow: true,
2144
- windowHours: 24,
2145
- reopenMechanism: REOPEN_MECHANISM.TEMPLATE,
2146
- handleKind: HANDLE_KIND.PHONE
2147
- },
2148
- [CONVERSATION_CHANNEL.MESSENGER]: {
2149
- // Messenger também tem 24h, mas reabre com message tag — não com template aprovado.
2150
- label: "Messenger",
2151
- icon: "\u{1F4E8}",
2152
- hasSessionWindow: true,
2153
- windowHours: 24,
2154
- reopenMechanism: REOPEN_MECHANISM.TAG,
2155
- handleKind: HANDLE_KIND.USERNAME
2156
- },
2157
- [CONVERSATION_CHANNEL.INSTAGRAM]: {
2158
- label: "Instagram",
2159
- icon: "\u{1F4F7}",
2160
- hasSessionWindow: true,
2161
- windowHours: 24,
2162
- reopenMechanism: REOPEN_MECHANISM.TAG,
2163
- handleKind: HANDLE_KIND.USERNAME
2164
- },
2165
- [CONVERSATION_CHANNEL.WEBCHAT]: {
2166
- // Chat próprio: sem intermediário, sem janela. Bloquear o composer aqui seria inventar limite.
2167
- label: "Chat do site",
2168
- icon: "\u{1F310}",
2169
- hasSessionWindow: false,
2170
- windowHours: 0,
2171
- reopenMechanism: REOPEN_MECHANISM.NONE,
2172
- handleKind: HANDLE_KIND.SESSION
2173
- }
2174
- };
2175
- function capabilitiesOf(channel) {
2176
- return CHANNEL_CAPABILITIES[channel ?? DEFAULT_CONVERSATION_CHANNEL];
2177
- }
2178
- var CHANNEL_FILTER_ALL = "all";
2179
- function channelFiltersFor(conversations) {
2180
- const present = new Set(
2181
- conversations.map((conversation) => conversation.channel ?? DEFAULT_CONVERSATION_CHANNEL)
2182
- );
2183
- if (present.size < 2) return [];
2184
- const ordered = Object.keys(CHANNEL_CAPABILITIES).filter((channel) => present.has(channel));
2185
- return [
2186
- { value: CHANNEL_FILTER_ALL, label: "Todos" },
2187
- ...ordered.map((channel) => ({ value: channel, label: CHANNEL_CAPABILITIES[channel].label }))
2188
- ];
2189
- }
2190
- function formatContactHandle(params) {
2191
- const { handleKind } = capabilitiesOf(params.channel);
2192
- if (handleKind === HANDLE_KIND.PHONE) return formatPhone(params.handle);
2193
- if (handleKind === HANDLE_KIND.USERNAME) return params.handle.startsWith("@") ? params.handle : `@${params.handle}`;
2194
- return `Visitante ${params.handle.slice(-6)}`;
2195
- }
2196
- function contactFlag(params) {
2197
- return capabilitiesOf(params.channel).handleKind === HANDLE_KIND.PHONE ? phoneCountryFlag(params.handle) : "";
2198
- }
2199
-
2200
2253
  // src/hooks/useAsyncResource.ts
2201
2254
  import { useCallback as useCallback6, useEffect as useEffect6, useRef as useRef6, useState as useState10 } from "react";
2202
2255
  function useAsyncResource(fetcher, deps) {
@@ -3113,6 +3166,10 @@ var SIMULATOR_PANEL_CHANNEL_WORDING = {
3113
3166
  [CONVERSATION_CHANNEL.WEBCHAT]: {
3114
3167
  destinationHint: "entrega na API do chat do site",
3115
3168
  placeholder: "Escreva como o visitante\u2026"
3169
+ },
3170
+ [CONVERSATION_CHANNEL.EMAIL]: {
3171
+ destinationHint: "entrega na caixa de entrada do contratante",
3172
+ placeholder: "Escreva como quem respondeu o e-mail\u2026"
3116
3173
  }
3117
3174
  };
3118
3175
  function simulatorPanelLabelsOf(channel) {
@@ -3150,6 +3207,19 @@ function ConversationSimulatorPanel({
3150
3207
  export {
3151
3208
  ConversationLocalesProvider,
3152
3209
  useConversationLocales,
3210
+ formatPhone,
3211
+ phoneInitials,
3212
+ CONVERSATION_CHANNEL,
3213
+ DEFAULT_CONVERSATION_CHANNEL,
3214
+ REOPEN_MECHANISM,
3215
+ HANDLE_KIND,
3216
+ CHANNEL_CAPABILITIES,
3217
+ capabilitiesOf,
3218
+ CHANNEL_FILTER_ALL,
3219
+ channelFiltersFor,
3220
+ formatContactHandle,
3221
+ contactFlag,
3222
+ channelCapabilityFor,
3153
3223
  StatusTicks,
3154
3224
  AudioPlayer,
3155
3225
  AudioTranscription,
@@ -3197,18 +3267,6 @@ export {
3197
3267
  DEFAULT_ACCEPTED_FILE_TYPES,
3198
3268
  MessageComposer,
3199
3269
  DateDivider,
3200
- formatPhone,
3201
- phoneInitials,
3202
- CONVERSATION_CHANNEL,
3203
- DEFAULT_CONVERSATION_CHANNEL,
3204
- REOPEN_MECHANISM,
3205
- HANDLE_KIND,
3206
- CHANNEL_CAPABILITIES,
3207
- capabilitiesOf,
3208
- CHANNEL_FILTER_ALL,
3209
- channelFiltersFor,
3210
- formatContactHandle,
3211
- contactFlag,
3212
3270
  useAsyncResource,
3213
3271
  conversationsOf,
3214
3272
  totalOf,
package/dist/index.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import * as react from 'react';
2
2
  import react__default, { ReactNode, CSSProperties, UIEvent, FormEvent, RefObject, KeyboardEvent } from 'react';
3
- import { M as MessagePayload, R as ResolveMediaUrl, U as InteractiveSelection, V as MessageTranscription, W as InteractivePayload, X as ConversationsFeatures, Y as QuickReply$1, C as ConversationSummary, Z as ConversationChannel, L as ListConversationsParams, b as ConversationsApi, S as SSEProvider, _ as TranscriptionMode, $ as ListDocumentsParams, d as ConversationDocument, a0 as ConversationTemplate, a1 as QueuedAttachment, a2 as QuickReplyInput, a3 as QuickReplyAttachment, a4 as ConversationVariable, a5 as ChannelFilter, a6 as ChannelFilterOption, k as ConversationSimulatorClient, m as ConversationSimulatorPanelLabels, P as PreviewUploadedMedia } from './ConversationSimulatorPanel-DmV8uaFE.js';
4
- export { A as AudioRecorderButton, g as AudioRecorderButtonLabels, h as AudioRecorderButtonProps, a7 as CHANNEL_CAPABILITIES, a8 as CHANNEL_FILTER_ALL, a9 as CONVERSATION_CHANNEL, aa as ChannelCapabilities, ab as CompanyDocument, ac as CompanyDocumentPage, ad as ConversationDocumentPage, a as ConversationEventSource, c as ConversationPage, ae as ConversationsTheme, af as ConversationsUIConfig, D as DEFAULT_AUDIO_RECORDER_BUTTON_LABELS, ag as DEFAULT_CONVERSATION_CHANNEL, ah as DEFAULT_MAX_RECORDING_MILLISECONDS, ai as FormatContactHandleParams, aj as HANDLE_KIND, ak as HandleKind, al as InteractiveOption, am as InteractiveSection, an as MediaRenderer, ao as MediaRendererProps, ap as QUICK_REPLY_ATTACHMENT_LIMIT, aq as REOPEN_MECHANISM, ar as ReopenMechanism, y as SendSimulatorMediaParams, z as SimulatorMediaKind, as as StoredAttachmentSendResult, at as TranscriptionStatus, au as capabilitiesOf, av as channelFiltersFor, aw as contactFlag, ax as formatContactHandle } from './ConversationSimulatorPanel-DmV8uaFE.js';
3
+ import { M as MessagePayload, R as ResolveMediaUrl, U as InteractiveSelection, V as MessageTranscription, W as ConversationChannel, X as InteractivePayload, Y as ConversationsFeatures, Z as QuickReply$1, C as ConversationSummary, L as ListConversationsParams, b as ConversationsApi, S as SSEProvider, _ as TranscriptionMode, $ as ListDocumentsParams, d as ConversationDocument, a0 as ConversationTemplate, a1 as QueuedAttachment, a2 as QuickReplyInput, a3 as QuickReplyAttachment, a4 as ConversationVariable, a5 as ChannelFilter, a6 as ChannelFilterOption, k as ConversationSimulatorClient, m as ConversationSimulatorPanelLabels, P as PreviewUploadedMedia } from './ConversationSimulatorPanel-DnXElfY8.js';
4
+ export { A as AudioRecorderButton, g as AudioRecorderButtonLabels, h as AudioRecorderButtonProps, a7 as CHANNEL_CAPABILITIES, a8 as CHANNEL_FILTER_ALL, a9 as CONVERSATION_CHANNEL, aa as ChannelCapabilities, ab as CompanyDocument, ac as CompanyDocumentPage, ad as ConversationDocumentPage, a as ConversationEventSource, c as ConversationPage, ae as ConversationsTheme, af as ConversationsUIConfig, D as DEFAULT_AUDIO_RECORDER_BUTTON_LABELS, ag as DEFAULT_CONVERSATION_CHANNEL, ah as DEFAULT_MAX_RECORDING_MILLISECONDS, ai as FormatContactHandleParams, aj as HANDLE_KIND, ak as HandleKind, al as InteractiveOption, am as InteractiveSection, an as MediaRenderer, ao as MediaRendererProps, ap as QUICK_REPLY_ATTACHMENT_LIMIT, aq as REOPEN_MECHANISM, ar as ReopenMechanism, y as SendSimulatorMediaParams, z as SimulatorMediaKind, as as StoredAttachmentSendResult, at as TranscriptionStatus, au as capabilitiesOf, av as channelFiltersFor, aw as contactFlag, ax as formatContactHandle } from './ConversationSimulatorPanel-DnXElfY8.js';
5
+ import { ChannelCapability } from '@adatechnology/conversation-contracts';
6
+ export { ChannelCapability } from '@adatechnology/conversation-contracts';
5
7
  import '@adatechnology/meta-whatsapp-contracts/testing';
6
8
 
7
9
  interface MessageBubbleProps {
@@ -28,9 +30,15 @@ interface MessageBubbleProps {
28
30
  * o que já veio pronto do backend.
29
31
  */
30
32
  onTranscribeAudio?: (messageId: string) => Promise<MessageTranscription | void>;
33
+ /**
34
+ * Canal da conversa (RF10, D4). Ausente = `whatsapp`, o comportamento de antes desta mudança.
35
+ * E-mail não confirma leitura (CA04): o selo de lida nunca aparece nesse canal, mesmo que o
36
+ * status chegue como `read` por algum caminho antigo — a tela não finge o que o canal não sabe.
37
+ */
38
+ channel?: ConversationChannel;
31
39
  className?: string;
32
40
  }
33
- declare function MessageBubble({ message, isMine, senderName, isFirstInGroup, isSelecting, isSelected, onToggleSelect, onResolveMediaUrl, onInteractiveSelect, onTranscribeAudio, className, }: MessageBubbleProps): react.JSX.Element;
41
+ declare function MessageBubble({ message, isMine, senderName, isFirstInGroup, isSelecting, isSelected, onToggleSelect, onResolveMediaUrl, onInteractiveSelect, onTranscribeAudio, channel, className, }: MessageBubbleProps): react.JSX.Element;
34
42
 
35
43
  interface InteractiveMessageLabels {
36
44
  /** Fallback do rótulo do botão que abre a lista, quando o payload não traz um. */
@@ -294,6 +302,12 @@ interface MessageComposerLabels {
294
302
  send: string;
295
303
  removeAttachment: string;
296
304
  quickReplies: string;
305
+ /** RF10, D3: por que o anexo está desabilitado no canal atual. */
306
+ attachDisabledHint: string;
307
+ /** RF10, D3: por que o microfone está desabilitado no canal atual. */
308
+ audioDisabledHint: string;
309
+ /** RF10, D3: por que a mensagem pronta está desabilitada no canal atual. */
310
+ quickRepliesDisabledHint: string;
297
311
  }
298
312
  declare const DEFAULT_MESSAGE_COMPOSER_LABELS: MessageComposerLabels;
299
313
  /**
@@ -324,6 +338,12 @@ interface MessageComposerProps {
324
338
  value?: string;
325
339
  onChange?: (value: string) => void;
326
340
  features?: ConversationsFeatures;
341
+ /**
342
+ * Canal da conversa (RF10, D3). Ausente = `whatsapp`, o comportamento de antes desta mudança.
343
+ * Decide o que aparece desabilitado com dica: anexo, microfone e mensagem pronta que o canal não
344
+ * suporta nunca somem sem explicação — ficam visíveis e desabilitados.
345
+ */
346
+ channel?: ConversationChannel;
327
347
  placeholder?: string;
328
348
  maxLength?: number;
329
349
  disabled?: boolean;
@@ -355,7 +375,7 @@ interface MessageComposerClassNames {
355
375
  * Produto com regra própria passa `acceptedFileTypes`.
356
376
  */
357
377
  declare const DEFAULT_ACCEPTED_FILE_TYPES: string;
358
- declare const MessageComposer: ({ onSend, onAttach, value: externalValue, onChange: externalOnChange, quickReplies, quickReplyVariables, savedQuickReplies, features, placeholder, maxLength, disabled, acceptedFileTypes, idleAction, className, classNames, labels, }: MessageComposerProps) => react.JSX.Element;
378
+ declare const MessageComposer: ({ onSend, onAttach, value: externalValue, onChange: externalOnChange, quickReplies, quickReplyVariables, savedQuickReplies, features, channel, placeholder, maxLength, disabled, acceptedFileTypes, idleAction, className, classNames, labels, }: MessageComposerProps) => react.JSX.Element;
359
379
 
360
380
  /** Cada ação que a barra sabe oferecer. `toolbar` decide quais delas aparecem. */
361
381
  declare const RICH_COMPOSER_ACTION: {
@@ -625,7 +645,8 @@ declare function MessageTail({ isOutbound }: MessageTailProps): react.JSX.Elemen
625
645
  /**
626
646
  * Janela de sessão: o intervalo em que o canal aceita mensagem livre do atendente. No WhatsApp são
627
647
  * 24h desde o último contato do cliente; fora dela só template. Cada canal tem a sua regra — e há
628
- * canal sem janela nenhuma — então a política vem de `capabilitiesOf`, não de constante fixa.
648
+ * canal sem janela nenhuma — então a política vem de `channelCapabilityFor` (RF10), não de
649
+ * constante fixa.
629
650
  *
630
651
  * Mora no SDK porque é regra de plataforma, não de produto: todo projeto que usa este pacote
631
652
  * precisa dela para saber o que o atendente ainda consegue fazer.
@@ -715,6 +736,23 @@ declare function replyLatencyOf(params: ReplyLatencyParams): ReplyLatency | null
715
736
  /** Só o que passou do combinado merece alerta — é o corte que a lista usa para destacar. */
716
737
  declare function isReplyOverdue(latency: ReplyLatency | null): boolean;
717
738
 
739
+ /**
740
+ * Capacidade **comportamental** do canal (RF10, D3): confirma leitura, tem janela de sessão (e de
741
+ * quantas horas), aceita anexo e de que tamanho, aceita áudio, aceita resposta rápida, precisa de
742
+ * transporte próprio. Vem de `@adatechnology/conversation-contracts`, nunca redeclarada aqui — é a
743
+ * "duas verdades sobre capacidade de canal" que o plano da spec 211 lista como risco.
744
+ *
745
+ * `messenger` e `instagram` são os dois canais que esta UI já servia antes do núcleo de conversa
746
+ * existir, e que o contrato não conhece (ele nasceu do que a spec 183 exercitava: `email`,
747
+ * `whatsapp`, `app`, `portal`, `webchat`). Convivência decidida aqui: o vocabulário de canal desta
748
+ * UI (`conversationChannel.ts`) é a união dos dois, e a capacidade comportamental de Messenger e
749
+ * Instagram cai no fallback do WhatsApp — o outro canal da Meta, com a mesma janela de 24h, a mesma
750
+ * confirmação de leitura e o mesmo anexo/áudio. Não é aproximação arbitrária: as três plataformas
751
+ * (WhatsApp, Messenger, Instagram) compartilham a política de sessão de 24h da Meta.
752
+ */
753
+
754
+ declare function channelCapabilityFor(channel: ConversationChannel | undefined): ChannelCapability;
755
+
718
756
  type ConversationRowClassNames = {
719
757
  root: string;
720
758
  windowBar: string;
@@ -2260,4 +2298,4 @@ type QueuedAttachmentsListProps = {
2260
2298
  };
2261
2299
  declare function QueuedAttachmentsList({ items, statusOf, onRemove, onRetry, retryingKeys, getThumbnailUrl, labels, busy, }: QueuedAttachmentsListProps): react.JSX.Element | null;
2262
2300
 
2263
- export { type AsyncResourceState, type AttachmentFileRejection, AudioPlayer, type AudioPlayerProps, AudioTranscription, type AudioTranscriptionProps, Avatar, type AvatarLabels, type AvatarProps, type BotMessages, type BuildTranscriptTextParams, BulkActionBar, type BulkActionBarProps, CHANNEL_BRAND_COLOR, CONVERSATIONS_PER_PAGE, CONVERSATION_WINDOW, ChannelFilter, ChannelFilterOption, ChannelIcon, type ChannelIconProps, ConversationChannel, type ConversationContextEntry, ConversationContextPanel, type ConversationContextPanelClassNames, type ConversationContextPanelLabels, type ConversationContextPanelProps, type ConversationContextStatus, ConversationDocument, ConversationDocumentsPanel, type ConversationDocumentsPanelClassNames, type ConversationDocumentsPanelLabels, type ConversationDocumentsPanelProps, ConversationHeader, type ConversationHeaderClassNames, type ConversationHeaderLabels, type ConversationHeaderProps, type ConversationHeaderUtility, ConversationListItem, type ConversationListItemLabels, type ConversationListItemProps, type ConversationLocales, ConversationLocalesProvider, type ConversationLocalesProviderProps, ConversationPane, type ConversationPaneProps, type ConversationRealtimeHandler, ConversationRow, type ConversationRowClassNames, type ConversationRowProps, ConversationSimulatorClient, ConversationSummary, ConversationTemplate, ConversationVariable, ConversationWallpaper, type ConversationWallpaperProps, type ConversationWindow, ConversationsApi, ConversationsFeatures, ConversationsInboxList, type ConversationsInboxListProps, ConversationsProvider, ConversationsWorkspace, type ConversationsWorkspaceLabels, type ConversationsWorkspaceProps, type ConversationsWorkspaceSimulator, DEFAULT_ACCEPTED_FILE_TYPES, DEFAULT_AVATAR_LABELS, DEFAULT_CONVERSATIONS_WORKSPACE_LABELS, DEFAULT_CONVERSATION_CONTEXT_LABELS, DEFAULT_CONVERSATION_DOCUMENTS_LABELS, DEFAULT_CONVERSATION_HEADER_LABELS, DEFAULT_CONVERSATION_LIST_ITEM_LABELS, DEFAULT_DARK_MODE_TOGGLE_LABELS, DEFAULT_DOCUMENTS_LIBRARY_LABELS, DEFAULT_DOCUMENTS_WORKSPACE_LABELS, DEFAULT_EMOJI_PICKER_LABELS, DEFAULT_INTERACTIVE_MESSAGE_LABELS, DEFAULT_LIGHTBOX_LABELS, DEFAULT_MAX_ATTACHMENT_SIZE_BYTES, DEFAULT_MESSAGE_COMPOSER_LABELS, DEFAULT_QUICK_REPLIES_PICKER_LABELS, DEFAULT_QUICK_REPLIES_WORKSPACE_LABELS, DEFAULT_RICH_COMPOSER_TOOLTIPS, DEFAULT_TEMPLATES_SETTINGS_LABELS, DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS, DEFAULT_WINDOW_EXPIRED_LABELS, DOCUMENT_SOURCE_FILTER, DarkModeToggle, type DarkModeToggleLabels, type DarkModeToggleProps, DateDivider, type DateDividerClassNames, type DateDividerProps, type DocumentSourceFilter, type DocumentsFiltersContext, DocumentsLibrary, type DocumentsLibraryClassNames, type DocumentsLibraryLabels, type DocumentsLibraryProps, DocumentsWorkspace, type DocumentsWorkspaceClassNames, type DocumentsWorkspaceLabels, type DocumentsWorkspaceProps, EMOJI_CATEGORIES, type EmojiCategory, type EmojiEntry, EmojiPicker, type EmojiPickerLabels, type EmojiPickerProps, FileIcon, type FileIconProps, type FilterOption, type FilterQuickRepliesParams, InteractiveMessage, type InteractiveMessageLabels, type InteractiveMessageProps, InteractivePayload, InteractiveSelection, Lightbox, type LightboxLabels, type LightboxProps, ListConversationsParams, ListDocumentsParams, ListingPagination, type ListingPaginationProps, type MatchSegment, type MaxAttachmentSizeBytes, MessageBubble, type MessageBubbleProps, MessageComposer, type MessageComposerClassNames, type MessageComposerLabels, type MessageComposerProps, MessagePayload, MessageTail, MessageText, type MessageTextProps, MessageTimestamp, MessageTranscription, MessagesWorkspace, type MessagesWorkspaceApi, type MessagesWorkspaceLabels, type MessagesWorkspaceProps, type MessagesWorkspaceTemplateRole, MultiSelectFilter, type MultiSelectFilterProps, NARROW_MAX_WIDTH_PX, type OutgoingItems, QueuedAttachment, QueuedAttachmentsList, QuickRepliesPicker, type QuickRepliesPickerLabels, type QuickRepliesPickerProps, QuickRepliesWorkspace, type QuickRepliesWorkspaceLabels, type QuickRepliesWorkspaceProps, type QuickReply, QuickReplyAttachment, QuickReplyInput, REPLY_LATENCY, REPLY_LATENCY_CRITICAL_HOURS, REPLY_LATENCY_LATE_HOURS, RICH_COMPOSER_ACTION, type ReplyLatency, type ReplyLatencyParams, ResolveMediaUrl, type RichComposerAction, type RichComposerQuickReply, type RichComposerTooltips, type RichComposerVariable, RichMessageComposer, type RichMessageComposerHandle, type RichMessageComposerProps, SSEProvider, QuickReply$1 as SavedQuickReply, SimpleEmojiPicker, type SimpleEmojiPickerProps, type SimulatorTransportFactory, type SimulatorTransportParams, type SortDirection, SortableHead, type SortableHeadProps, StatusTicks, type StatusTicksProps, TEMPLATE_SETTINGS_TAB, TOOLTIP_ATTRIBUTE, type TemplateSettings, type TemplateSettingsTab, ToastProvider, TooltipLayer, type TopicItem, TopicsForm, type TopicsFormLabels, type TopicsFormProps, TranscriptionMode, type TranscriptionSettings, TranscriptionSettingsForm, type TranscriptionSettingsFormLabels, type TranscriptionSettingsFormProps, type UrlStateOptions, type UseConversationActionsResult, type UseConversationContextResult, type UseConversationDocumentsParams, type UseConversationDocumentsResult, type UseConversationListParams, type UseConversationListResult, type UseConversationMessagesResult, type UseConversationsInboxParams, type UseConversationsInboxResult, type UseInboxActionsResult, type UseScrollToLatestMessageParams, type UseScrollToLatestMessageResult, type UseWaitingNotificationsLabels, type UseWaitingNotificationsParams, type UseWaitingNotificationsResult, type ValidateAttachmentFilesResult, WHATSAPP_MARKER_BY_ACTION, WINDOW_FILTERS, WelcomeFarewellForm, type WelcomeFarewellFormLabels, type WelcomeFarewellFormProps, WhatsAppCreateTemplateForm, type WhatsAppCreateTemplateFormLabels, type WhatsAppCreateTemplateFormProps, type WhatsAppCreateTemplateResult, type WhatsAppCreateTemplateState, WhatsAppMessageEditor, type WhatsAppMessageEditorLabels, type WhatsAppMessageEditorProps, WhatsAppMessagePreview, type WhatsAppMessagePreviewProps, type WhatsAppTemplateHeaderType, WhatsAppTemplateSettingsForm, type WhatsAppTemplateSettingsFormLabels, type WhatsAppTemplateSettingsFormProps, type WhatsAppTemplateSummary, type WhatsAppTemplateVariableSuggestion, WhatsAppTemplatesSettings, type WhatsAppTemplatesSettingsLabels, type WhatsAppTemplatesSettingsProps, WindowExpiredNotice, type WindowExpiredNoticeLabels, type WindowExpiredNoticeProps, type WindowOfParams, applyQuickReplyVariables, buildTranscriptFilename, buildTranscriptText, createMediaUrlResolver, downloadTextFile, filterQuickReplies, formatDateTime, formatFileSize, formatPhone, formatStalledFor, formatTimestamp, highlightMatch, htmlToWA, isReplyOverdue, isSameDay, isWindowBlocking, normalizeForSearch, parseWhatsAppFormatting, phoneInitials, queuedAttachmentsFromQuickReply, replyLatencyOf, resolveMaxAttachmentSizeBytes, resolveQuickReply, searchEmojis, toast, useConversationActions, useConversationContext, useConversationDocuments, useConversationList, useConversationLocales, useConversationMessages, useConversationRealtime, useConversations, useConversationsInbox, useDarkMode, useDebouncedValue, useGlobalRealtime, useInboxActions, useIsDarkTheme, useIsNarrow, useScrollToLatestMessage, useToast, useUrlArrayState, useUrlNumberState, useUrlStringState, useWaitingNotifications, waToHTML, waToHTMLInline, windowOf };
2301
+ export { type AsyncResourceState, type AttachmentFileRejection, AudioPlayer, type AudioPlayerProps, AudioTranscription, type AudioTranscriptionProps, Avatar, type AvatarLabels, type AvatarProps, type BotMessages, type BuildTranscriptTextParams, BulkActionBar, type BulkActionBarProps, CHANNEL_BRAND_COLOR, CONVERSATIONS_PER_PAGE, CONVERSATION_WINDOW, ChannelFilter, ChannelFilterOption, ChannelIcon, type ChannelIconProps, ConversationChannel, type ConversationContextEntry, ConversationContextPanel, type ConversationContextPanelClassNames, type ConversationContextPanelLabels, type ConversationContextPanelProps, type ConversationContextStatus, ConversationDocument, ConversationDocumentsPanel, type ConversationDocumentsPanelClassNames, type ConversationDocumentsPanelLabels, type ConversationDocumentsPanelProps, ConversationHeader, type ConversationHeaderClassNames, type ConversationHeaderLabels, type ConversationHeaderProps, type ConversationHeaderUtility, ConversationListItem, type ConversationListItemLabels, type ConversationListItemProps, type ConversationLocales, ConversationLocalesProvider, type ConversationLocalesProviderProps, ConversationPane, type ConversationPaneProps, type ConversationRealtimeHandler, ConversationRow, type ConversationRowClassNames, type ConversationRowProps, ConversationSimulatorClient, ConversationSummary, ConversationTemplate, ConversationVariable, ConversationWallpaper, type ConversationWallpaperProps, type ConversationWindow, ConversationsApi, ConversationsFeatures, ConversationsInboxList, type ConversationsInboxListProps, ConversationsProvider, ConversationsWorkspace, type ConversationsWorkspaceLabels, type ConversationsWorkspaceProps, type ConversationsWorkspaceSimulator, DEFAULT_ACCEPTED_FILE_TYPES, DEFAULT_AVATAR_LABELS, DEFAULT_CONVERSATIONS_WORKSPACE_LABELS, DEFAULT_CONVERSATION_CONTEXT_LABELS, DEFAULT_CONVERSATION_DOCUMENTS_LABELS, DEFAULT_CONVERSATION_HEADER_LABELS, DEFAULT_CONVERSATION_LIST_ITEM_LABELS, DEFAULT_DARK_MODE_TOGGLE_LABELS, DEFAULT_DOCUMENTS_LIBRARY_LABELS, DEFAULT_DOCUMENTS_WORKSPACE_LABELS, DEFAULT_EMOJI_PICKER_LABELS, DEFAULT_INTERACTIVE_MESSAGE_LABELS, DEFAULT_LIGHTBOX_LABELS, DEFAULT_MAX_ATTACHMENT_SIZE_BYTES, DEFAULT_MESSAGE_COMPOSER_LABELS, DEFAULT_QUICK_REPLIES_PICKER_LABELS, DEFAULT_QUICK_REPLIES_WORKSPACE_LABELS, DEFAULT_RICH_COMPOSER_TOOLTIPS, DEFAULT_TEMPLATES_SETTINGS_LABELS, DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS, DEFAULT_WINDOW_EXPIRED_LABELS, DOCUMENT_SOURCE_FILTER, DarkModeToggle, type DarkModeToggleLabels, type DarkModeToggleProps, DateDivider, type DateDividerClassNames, type DateDividerProps, type DocumentSourceFilter, type DocumentsFiltersContext, DocumentsLibrary, type DocumentsLibraryClassNames, type DocumentsLibraryLabels, type DocumentsLibraryProps, DocumentsWorkspace, type DocumentsWorkspaceClassNames, type DocumentsWorkspaceLabels, type DocumentsWorkspaceProps, EMOJI_CATEGORIES, type EmojiCategory, type EmojiEntry, EmojiPicker, type EmojiPickerLabels, type EmojiPickerProps, FileIcon, type FileIconProps, type FilterOption, type FilterQuickRepliesParams, InteractiveMessage, type InteractiveMessageLabels, type InteractiveMessageProps, InteractivePayload, InteractiveSelection, Lightbox, type LightboxLabels, type LightboxProps, ListConversationsParams, ListDocumentsParams, ListingPagination, type ListingPaginationProps, type MatchSegment, type MaxAttachmentSizeBytes, MessageBubble, type MessageBubbleProps, MessageComposer, type MessageComposerClassNames, type MessageComposerLabels, type MessageComposerProps, MessagePayload, MessageTail, MessageText, type MessageTextProps, MessageTimestamp, MessageTranscription, MessagesWorkspace, type MessagesWorkspaceApi, type MessagesWorkspaceLabels, type MessagesWorkspaceProps, type MessagesWorkspaceTemplateRole, MultiSelectFilter, type MultiSelectFilterProps, NARROW_MAX_WIDTH_PX, type OutgoingItems, QueuedAttachment, QueuedAttachmentsList, QuickRepliesPicker, type QuickRepliesPickerLabels, type QuickRepliesPickerProps, QuickRepliesWorkspace, type QuickRepliesWorkspaceLabels, type QuickRepliesWorkspaceProps, type QuickReply, QuickReplyAttachment, QuickReplyInput, REPLY_LATENCY, REPLY_LATENCY_CRITICAL_HOURS, REPLY_LATENCY_LATE_HOURS, RICH_COMPOSER_ACTION, type ReplyLatency, type ReplyLatencyParams, ResolveMediaUrl, type RichComposerAction, type RichComposerQuickReply, type RichComposerTooltips, type RichComposerVariable, RichMessageComposer, type RichMessageComposerHandle, type RichMessageComposerProps, SSEProvider, QuickReply$1 as SavedQuickReply, SimpleEmojiPicker, type SimpleEmojiPickerProps, type SimulatorTransportFactory, type SimulatorTransportParams, type SortDirection, SortableHead, type SortableHeadProps, StatusTicks, type StatusTicksProps, TEMPLATE_SETTINGS_TAB, TOOLTIP_ATTRIBUTE, type TemplateSettings, type TemplateSettingsTab, ToastProvider, TooltipLayer, type TopicItem, TopicsForm, type TopicsFormLabels, type TopicsFormProps, TranscriptionMode, type TranscriptionSettings, TranscriptionSettingsForm, type TranscriptionSettingsFormLabels, type TranscriptionSettingsFormProps, type UrlStateOptions, type UseConversationActionsResult, type UseConversationContextResult, type UseConversationDocumentsParams, type UseConversationDocumentsResult, type UseConversationListParams, type UseConversationListResult, type UseConversationMessagesResult, type UseConversationsInboxParams, type UseConversationsInboxResult, type UseInboxActionsResult, type UseScrollToLatestMessageParams, type UseScrollToLatestMessageResult, type UseWaitingNotificationsLabels, type UseWaitingNotificationsParams, type UseWaitingNotificationsResult, type ValidateAttachmentFilesResult, WHATSAPP_MARKER_BY_ACTION, WINDOW_FILTERS, WelcomeFarewellForm, type WelcomeFarewellFormLabels, type WelcomeFarewellFormProps, WhatsAppCreateTemplateForm, type WhatsAppCreateTemplateFormLabels, type WhatsAppCreateTemplateFormProps, type WhatsAppCreateTemplateResult, type WhatsAppCreateTemplateState, WhatsAppMessageEditor, type WhatsAppMessageEditorLabels, type WhatsAppMessageEditorProps, WhatsAppMessagePreview, type WhatsAppMessagePreviewProps, type WhatsAppTemplateHeaderType, WhatsAppTemplateSettingsForm, type WhatsAppTemplateSettingsFormLabels, type WhatsAppTemplateSettingsFormProps, type WhatsAppTemplateSummary, type WhatsAppTemplateVariableSuggestion, WhatsAppTemplatesSettings, type WhatsAppTemplatesSettingsLabels, type WhatsAppTemplatesSettingsProps, WindowExpiredNotice, type WindowExpiredNoticeLabels, type WindowExpiredNoticeProps, type WindowOfParams, applyQuickReplyVariables, buildTranscriptFilename, buildTranscriptText, channelCapabilityFor, createMediaUrlResolver, downloadTextFile, filterQuickReplies, formatDateTime, formatFileSize, formatPhone, formatStalledFor, formatTimestamp, highlightMatch, htmlToWA, isReplyOverdue, isSameDay, isWindowBlocking, normalizeForSearch, parseWhatsAppFormatting, phoneInitials, queuedAttachmentsFromQuickReply, replyLatencyOf, resolveMaxAttachmentSizeBytes, resolveQuickReply, searchEmojis, toast, useConversationActions, useConversationContext, useConversationDocuments, useConversationList, useConversationLocales, useConversationMessages, useConversationRealtime, useConversations, useConversationsInbox, useDarkMode, useDebouncedValue, useGlobalRealtime, useInboxActions, useIsDarkTheme, useIsNarrow, useScrollToLatestMessage, useToast, useUrlArrayState, useUrlNumberState, useUrlStringState, useWaitingNotifications, waToHTML, waToHTMLInline, windowOf };