@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.
- package/dist/{ConversationSimulatorPanel-DmV8uaFE.d.ts → ConversationSimulatorPanel-DnXElfY8.d.ts} +87 -73
- package/dist/{chunk-L4OE4ORQ.js → chunk-4P5KMWOI.js} +219 -161
- package/dist/index.d.ts +44 -6
- package/dist/index.js +16 -5
- package/dist/preview/index.d.ts +2 -2
- package/dist/preview/index.js +1 -1
- package/package.json +3 -2
- package/src/AudioRecorderButton.test.tsx +18 -0
- package/src/AudioRecorderButton.tsx +17 -2
- package/src/ChannelIcon.tsx +11 -0
- package/src/MessageBubble.test.tsx +33 -0
- package/src/MessageBubble.tsx +18 -5
- package/src/MessageComposer.test.tsx +39 -1
- package/src/MessageComposer.tsx +66 -15
- package/src/channelCapability.test.ts +47 -0
- package/src/channelCapability.ts +37 -0
- package/src/conversationChannel.ts +19 -10
- package/src/conversationWindow.ts +7 -5
- package/src/index.ts +5 -1
- package/src/preview/ConversationSimulatorPanel.tsx +4 -0
- package/src/workspace/ConversationPane.tsx +2 -0
|
@@ -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 =
|
|
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 &&
|
|
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 =
|
|
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(
|
|
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__ */
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
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
|
-
|
|
2144
|
+
disabled: !attachmentsAllowed,
|
|
2145
|
+
"data-cv-tooltip": attachmentsAllowed ? attachLabel : attachDisabledHintLabel,
|
|
1971
2146
|
onClick: () => fileInputRef.current?.click(),
|
|
1972
|
-
|
|
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
|
|
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-
|
|
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 `
|
|
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 };
|