@adatechnology/conversations-ui 0.1.0-rc.11 → 0.1.0-rc.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +77 -1
- package/dist/index.js +689 -434
- package/package.json +1 -1
- package/src/RichMessageComposer.test.tsx +83 -0
- package/src/RichMessageComposer.tsx +379 -0
- package/src/index.ts +9 -0
package/dist/index.js
CHANGED
|
@@ -51,128 +51,14 @@ import {
|
|
|
51
51
|
waToHTMLInline
|
|
52
52
|
} from "./chunk-2AYDBWNE.js";
|
|
53
53
|
|
|
54
|
-
// src/
|
|
55
|
-
import { useRef } from "react";
|
|
56
|
-
import { Bold, Italic, Strikethrough } from "lucide-react";
|
|
57
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
58
|
-
var DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS = {
|
|
59
|
-
bold: "Negrito",
|
|
60
|
-
boldHint: "Negrito (*texto*)",
|
|
61
|
-
italic: "It\xE1lico",
|
|
62
|
-
italicHint: "It\xE1lico (_texto_)",
|
|
63
|
-
strikethrough: "Tachado",
|
|
64
|
-
strikethroughHint: "Tachado (~texto~)",
|
|
65
|
-
insertPlaceholder: (token) => `Inserir ${token}`
|
|
66
|
-
};
|
|
67
|
-
var INLINE_TOKEN = /(\*[^*\n]+\*|_[^_\n]+_|~[^~\n]+~|`[^`\n]+`|\{[a-zA-Z_]+\})/g;
|
|
68
|
-
function renderLine(line, lineKey) {
|
|
69
|
-
const nodes = [];
|
|
70
|
-
let lastIndex = 0;
|
|
71
|
-
let match;
|
|
72
|
-
let tokenIndex = 0;
|
|
73
|
-
INLINE_TOKEN.lastIndex = 0;
|
|
74
|
-
while ((match = INLINE_TOKEN.exec(line)) !== null) {
|
|
75
|
-
if (match.index > lastIndex) nodes.push(line.slice(lastIndex, match.index));
|
|
76
|
-
const token = match[0];
|
|
77
|
-
const key = `${lineKey}-${tokenIndex++}`;
|
|
78
|
-
if (token.startsWith("*")) nodes.push(/* @__PURE__ */ jsx("strong", { children: token.slice(1, -1) }, key));
|
|
79
|
-
else if (token.startsWith("_")) nodes.push(/* @__PURE__ */ jsx("em", { children: token.slice(1, -1) }, key));
|
|
80
|
-
else if (token.startsWith("~")) nodes.push(/* @__PURE__ */ jsx("s", { children: token.slice(1, -1) }, key));
|
|
81
|
-
else if (token.startsWith("`")) nodes.push(/* @__PURE__ */ jsx("code", { className: "font-mono text-[0.85em]", children: token.slice(1, -1) }, key));
|
|
82
|
-
else nodes.push(/* @__PURE__ */ jsx("span", { className: "rounded bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 px-1", children: token }, key));
|
|
83
|
-
lastIndex = INLINE_TOKEN.lastIndex;
|
|
84
|
-
}
|
|
85
|
-
if (lastIndex < line.length) nodes.push(line.slice(lastIndex));
|
|
86
|
-
return nodes;
|
|
87
|
-
}
|
|
88
|
-
function renderWhatsApp(text) {
|
|
89
|
-
const lines = text.split("\n");
|
|
90
|
-
return lines.map((line, index) => /* @__PURE__ */ jsxs("span", { children: [
|
|
91
|
-
renderLine(line, `ln-${index}`),
|
|
92
|
-
index < lines.length - 1 ? /* @__PURE__ */ jsx("br", {}) : null
|
|
93
|
-
] }, `ln-${index}`));
|
|
94
|
-
}
|
|
95
|
-
function WhatsAppMessageEditor({
|
|
96
|
-
value,
|
|
97
|
-
onChange,
|
|
98
|
-
placeholder,
|
|
99
|
-
placeholders = [],
|
|
100
|
-
rows = 4,
|
|
101
|
-
previewLabel = "Pr\xE9via (como aparece no WhatsApp)",
|
|
102
|
-
emptyPreviewText = "Sua mensagem aparecer\xE1 aqui\u2026",
|
|
103
|
-
labels
|
|
104
|
-
}) {
|
|
105
|
-
const editorLabels = { ...DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS, ...labels };
|
|
106
|
-
const textareaRef = useRef(null);
|
|
107
|
-
function wrapSelection(marker) {
|
|
108
|
-
const textarea = textareaRef.current;
|
|
109
|
-
if (!textarea) return;
|
|
110
|
-
const start = textarea.selectionStart;
|
|
111
|
-
const end = textarea.selectionEnd;
|
|
112
|
-
const selected = value.slice(start, end) || "texto";
|
|
113
|
-
const next = value.slice(0, start) + marker + selected + marker + value.slice(end);
|
|
114
|
-
onChange(next);
|
|
115
|
-
requestAnimationFrame(() => {
|
|
116
|
-
textarea.focus();
|
|
117
|
-
textarea.setSelectionRange(start + marker.length, start + marker.length + selected.length);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
function insertAtCursor(snippet) {
|
|
121
|
-
const textarea = textareaRef.current;
|
|
122
|
-
if (!textarea) return;
|
|
123
|
-
const start = textarea.selectionStart;
|
|
124
|
-
const end = textarea.selectionEnd;
|
|
125
|
-
const next = value.slice(0, start) + snippet + value.slice(end);
|
|
126
|
-
onChange(next);
|
|
127
|
-
requestAnimationFrame(() => {
|
|
128
|
-
textarea.focus();
|
|
129
|
-
const caret = start + snippet.length;
|
|
130
|
-
textarea.setSelectionRange(caret, caret);
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
const toolbarButtonClass = "inline-flex items-center justify-center h-8 w-8 rounded-lg border border-gray-200 dark:border-gray-600 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors";
|
|
134
|
-
return /* @__PURE__ */ jsxs("div", { children: [
|
|
135
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1.5 mb-2", children: [
|
|
136
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => wrapSelection("*"), className: toolbarButtonClass, title: editorLabels.boldHint, "aria-label": editorLabels.bold, children: /* @__PURE__ */ jsx(Bold, { size: 15 }) }),
|
|
137
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => wrapSelection("_"), className: toolbarButtonClass, title: editorLabels.italicHint, "aria-label": editorLabels.italic, children: /* @__PURE__ */ jsx(Italic, { size: 15 }) }),
|
|
138
|
-
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => wrapSelection("~"), className: toolbarButtonClass, title: editorLabels.strikethroughHint, "aria-label": editorLabels.strikethrough, children: /* @__PURE__ */ jsx(Strikethrough, { size: 15 }) }),
|
|
139
|
-
placeholders.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
140
|
-
/* @__PURE__ */ jsx("span", { className: "mx-1 h-5 w-px bg-gray-200 dark:bg-gray-600" }),
|
|
141
|
-
placeholders.map((token) => /* @__PURE__ */ jsx(
|
|
142
|
-
"button",
|
|
143
|
-
{
|
|
144
|
-
type: "button",
|
|
145
|
-
onClick: () => insertAtCursor(token),
|
|
146
|
-
className: "inline-flex items-center h-8 px-2 rounded-lg border border-gray-200 dark:border-gray-600 text-xs text-blue-600 dark:text-blue-300 hover:bg-blue-50 dark:hover:bg-blue-900/40 transition-colors",
|
|
147
|
-
title: editorLabels.insertPlaceholder(token),
|
|
148
|
-
children: token
|
|
149
|
-
},
|
|
150
|
-
token
|
|
151
|
-
))
|
|
152
|
-
] })
|
|
153
|
-
] }),
|
|
154
|
-
/* @__PURE__ */ jsx(
|
|
155
|
-
"textarea",
|
|
156
|
-
{
|
|
157
|
-
ref: textareaRef,
|
|
158
|
-
value,
|
|
159
|
-
onChange: (event) => onChange(event.target.value),
|
|
160
|
-
placeholder,
|
|
161
|
-
rows,
|
|
162
|
-
className: "w-full border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all placeholder:text-gray-400 dark:placeholder:text-gray-500 resize-y"
|
|
163
|
-
}
|
|
164
|
-
),
|
|
165
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-2", children: [
|
|
166
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 dark:text-gray-400 mb-1", children: previewLabel }),
|
|
167
|
-
/* @__PURE__ */ jsx("div", { className: "rounded-xl bg-[#e5ded8] dark:bg-gray-900 p-3", children: /* @__PURE__ */ jsx("div", { className: "inline-block max-w-full rounded-lg rounded-tl-none bg-white dark:bg-gray-800 shadow-sm px-3 py-2 text-sm text-gray-800 dark:text-gray-100 whitespace-pre-wrap break-words", children: value.trim() ? renderWhatsApp(value) : /* @__PURE__ */ jsx("span", { className: "text-gray-400 dark:text-gray-500", children: emptyPreviewText }) }) })
|
|
168
|
-
] })
|
|
169
|
-
] });
|
|
170
|
-
}
|
|
54
|
+
// src/RichMessageComposer.tsx
|
|
55
|
+
import { forwardRef, useCallback, useEffect as useEffect2, useImperativeHandle, useRef as useRef2, useState as useState2 } from "react";
|
|
56
|
+
import { Bold, Italic, Strikethrough, Code, Paperclip, SendHorizonal, Braces } from "lucide-react";
|
|
171
57
|
|
|
172
58
|
// src/SimpleEmojiPicker.tsx
|
|
173
|
-
import { useEffect, useRef
|
|
59
|
+
import { useEffect, useRef, useState } from "react";
|
|
174
60
|
import { Smile } from "lucide-react";
|
|
175
|
-
import { jsx
|
|
61
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
176
62
|
var EMOJIS = [
|
|
177
63
|
"\u{1F600}",
|
|
178
64
|
"\u{1F602}",
|
|
@@ -257,7 +143,7 @@ var EMOJIS = [
|
|
|
257
143
|
];
|
|
258
144
|
function SimpleEmojiPicker({ onSelect, label = "Emojis", pickerWidth = "280px", pickerMaxHeight = "220px" }) {
|
|
259
145
|
const [open, setOpen] = useState(false);
|
|
260
|
-
const containerRef =
|
|
146
|
+
const containerRef = useRef(null);
|
|
261
147
|
useEffect(() => {
|
|
262
148
|
if (!open) return;
|
|
263
149
|
const handleClickOutside = (e) => {
|
|
@@ -268,23 +154,23 @@ function SimpleEmojiPicker({ onSelect, label = "Emojis", pickerWidth = "280px",
|
|
|
268
154
|
document.addEventListener("mousedown", handleClickOutside);
|
|
269
155
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
270
156
|
}, [open]);
|
|
271
|
-
return /* @__PURE__ */
|
|
272
|
-
/* @__PURE__ */
|
|
157
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative flex-shrink-0", children: [
|
|
158
|
+
/* @__PURE__ */ jsx(
|
|
273
159
|
"button",
|
|
274
160
|
{
|
|
275
161
|
type: "button",
|
|
276
162
|
onClick: () => setOpen((v) => !v),
|
|
277
163
|
className: "w-7 h-7 flex items-center justify-center rounded-lg text-gray-400 dark:text-gray-500 hover:text-teal-600 dark:hover:text-teal-400 hover:bg-teal-50 dark:hover:bg-teal-900/30 transition-colors",
|
|
278
164
|
title: label,
|
|
279
|
-
children: /* @__PURE__ */
|
|
165
|
+
children: /* @__PURE__ */ jsx(Smile, { size: 15 })
|
|
280
166
|
}
|
|
281
167
|
),
|
|
282
|
-
open && /* @__PURE__ */
|
|
168
|
+
open && /* @__PURE__ */ jsx("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-xl shadow-xl p-2 z-50", children: /* @__PURE__ */ jsx(
|
|
283
169
|
"div",
|
|
284
170
|
{
|
|
285
171
|
className: "grid grid-cols-10 gap-0.5 overflow-y-auto",
|
|
286
172
|
style: { width: pickerWidth, maxHeight: pickerMaxHeight },
|
|
287
|
-
children: EMOJIS.map((emoji) => /* @__PURE__ */
|
|
173
|
+
children: EMOJIS.map((emoji) => /* @__PURE__ */ jsx(
|
|
288
174
|
"button",
|
|
289
175
|
{
|
|
290
176
|
type: "button",
|
|
@@ -302,8 +188,374 @@ function SimpleEmojiPicker({ onSelect, label = "Emojis", pickerWidth = "280px",
|
|
|
302
188
|
] });
|
|
303
189
|
}
|
|
304
190
|
|
|
191
|
+
// src/RichMessageComposer.tsx
|
|
192
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
193
|
+
var RICH_COMPOSER_ACTION = {
|
|
194
|
+
BOLD: "bold",
|
|
195
|
+
ITALIC: "italic",
|
|
196
|
+
STRIKETHROUGH: "strikethrough",
|
|
197
|
+
MONOSPACE: "monospace",
|
|
198
|
+
EMOJI: "emoji",
|
|
199
|
+
ATTACH: "attach",
|
|
200
|
+
VARIABLES: "variables"
|
|
201
|
+
};
|
|
202
|
+
var DEFAULT_RICH_COMPOSER_TOOLTIPS = {
|
|
203
|
+
bold: "Negrito",
|
|
204
|
+
italic: "It\xE1lico",
|
|
205
|
+
strikethrough: "Tachado",
|
|
206
|
+
monospace: "Monoespa\xE7ado",
|
|
207
|
+
emoji: "Emojis",
|
|
208
|
+
attach: "Anexar arquivo",
|
|
209
|
+
send: "Enviar",
|
|
210
|
+
variables: "Vari\xE1veis dispon\xEDveis"
|
|
211
|
+
};
|
|
212
|
+
var FORMATTING_ELEMENT = {
|
|
213
|
+
bold: "strong",
|
|
214
|
+
italic: "em",
|
|
215
|
+
strikethrough: "del",
|
|
216
|
+
monospace: "code"
|
|
217
|
+
};
|
|
218
|
+
var MONOSPACE_CLASS = "bg-black/5 dark:bg-white/10 rounded px-0.5 font-mono text-sm";
|
|
219
|
+
var RichMessageComposer = forwardRef(function RichMessageComposer2({
|
|
220
|
+
value,
|
|
221
|
+
onChange,
|
|
222
|
+
onSend,
|
|
223
|
+
onAttachFiles,
|
|
224
|
+
quickReplies,
|
|
225
|
+
variables,
|
|
226
|
+
toolbar,
|
|
227
|
+
tooltips,
|
|
228
|
+
placeholder,
|
|
229
|
+
disabled = false,
|
|
230
|
+
isSending = false,
|
|
231
|
+
idleAction,
|
|
232
|
+
attachmentsPreview,
|
|
233
|
+
acceptedFileTypes = DEFAULT_ACCEPTED_FILE_TYPES,
|
|
234
|
+
className
|
|
235
|
+
}, ref) {
|
|
236
|
+
const editorRef = useRef2(null);
|
|
237
|
+
const fileInputRef = useRef2(null);
|
|
238
|
+
const variablesRef = useRef2(null);
|
|
239
|
+
const [isVariablesOpen, setIsVariablesOpen] = useState2(false);
|
|
240
|
+
useEffect2(() => {
|
|
241
|
+
if (!isVariablesOpen) return;
|
|
242
|
+
const closeOnOutsideClick = (event) => {
|
|
243
|
+
if (!variablesRef.current?.contains(event.target)) setIsVariablesOpen(false);
|
|
244
|
+
};
|
|
245
|
+
document.addEventListener("mousedown", closeOnOutsideClick);
|
|
246
|
+
return () => document.removeEventListener("mousedown", closeOnOutsideClick);
|
|
247
|
+
}, [isVariablesOpen]);
|
|
248
|
+
const tooltipOf = (action) => tooltips?.[action] ?? DEFAULT_RICH_COMPOSER_TOOLTIPS[action];
|
|
249
|
+
const shows = (action) => toolbar?.[action] !== false;
|
|
250
|
+
const replaceContent = useCallback((text) => {
|
|
251
|
+
const editor = editorRef.current;
|
|
252
|
+
if (!editor) return;
|
|
253
|
+
editor.innerHTML = waToHTML(text);
|
|
254
|
+
onChange(htmlToWA(editor.innerHTML));
|
|
255
|
+
editor.focus();
|
|
256
|
+
}, [onChange]);
|
|
257
|
+
useImperativeHandle(ref, () => ({
|
|
258
|
+
setContent: replaceContent,
|
|
259
|
+
clear: () => {
|
|
260
|
+
const editor = editorRef.current;
|
|
261
|
+
if (!editor) return;
|
|
262
|
+
editor.innerHTML = "";
|
|
263
|
+
onChange("");
|
|
264
|
+
},
|
|
265
|
+
focus: () => editorRef.current?.focus()
|
|
266
|
+
}), [onChange, replaceContent]);
|
|
267
|
+
const currentRange = useCallback(() => {
|
|
268
|
+
const editor = editorRef.current;
|
|
269
|
+
if (!editor) return void 0;
|
|
270
|
+
editor.focus();
|
|
271
|
+
const selection = window.getSelection();
|
|
272
|
+
if (!selection?.rangeCount || !editor.contains(selection.anchorNode)) return void 0;
|
|
273
|
+
return selection.getRangeAt(0);
|
|
274
|
+
}, []);
|
|
275
|
+
const commitRange = useCallback((range, node) => {
|
|
276
|
+
const selection = window.getSelection();
|
|
277
|
+
range.setStartAfter(node);
|
|
278
|
+
range.collapse(true);
|
|
279
|
+
selection?.removeAllRanges();
|
|
280
|
+
selection?.addRange(range);
|
|
281
|
+
onChange(htmlToWA(editorRef.current?.innerHTML ?? ""));
|
|
282
|
+
}, [onChange]);
|
|
283
|
+
const insertAtCursor = useCallback((fragment) => {
|
|
284
|
+
const range = currentRange();
|
|
285
|
+
if (!range) return;
|
|
286
|
+
range.deleteContents();
|
|
287
|
+
const textNode = document.createTextNode(fragment);
|
|
288
|
+
range.insertNode(textNode);
|
|
289
|
+
commitRange(range, textNode);
|
|
290
|
+
}, [commitRange, currentRange]);
|
|
291
|
+
const wrapSelection = useCallback((action) => {
|
|
292
|
+
const range = currentRange();
|
|
293
|
+
const selectedText = range?.toString();
|
|
294
|
+
if (!range || !selectedText) return;
|
|
295
|
+
range.deleteContents();
|
|
296
|
+
const wrapper = document.createElement(FORMATTING_ELEMENT[action]);
|
|
297
|
+
if (action === "monospace") wrapper.className = MONOSPACE_CLASS;
|
|
298
|
+
wrapper.textContent = selectedText;
|
|
299
|
+
range.insertNode(wrapper);
|
|
300
|
+
commitRange(range, wrapper);
|
|
301
|
+
}, [commitRange, currentRange]);
|
|
302
|
+
const handleInput = useCallback((event) => {
|
|
303
|
+
onChange(htmlToWA(event.currentTarget.innerHTML));
|
|
304
|
+
}, [onChange]);
|
|
305
|
+
const handleKeyDown = useCallback((event) => {
|
|
306
|
+
if (event.key === "Enter" && !event.shiftKey) {
|
|
307
|
+
event.preventDefault();
|
|
308
|
+
if (!disabled) onSend();
|
|
309
|
+
}
|
|
310
|
+
}, [disabled, onSend]);
|
|
311
|
+
const handleFileChange = useCallback((event) => {
|
|
312
|
+
if (event.target.files?.length) onAttachFiles?.(event.target.files);
|
|
313
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
314
|
+
}, [onAttachFiles]);
|
|
315
|
+
const canSend = value.trim().length > 0;
|
|
316
|
+
return /* @__PURE__ */ jsxs2("div", { className: cn("flex flex-col", className), children: [
|
|
317
|
+
attachmentsPreview,
|
|
318
|
+
quickReplies?.length ? (
|
|
319
|
+
/* Uma linha rolável no celular, quebrando em várias no desktop: empilhar os chips no
|
|
320
|
+
celular come a altura da conversa, que é o que o operador precisa ver. */
|
|
321
|
+
/* @__PURE__ */ jsx2("div", { className: "mb-2 flex flex-nowrap gap-1 overflow-x-auto sm:flex-wrap sm:overflow-x-visible [scrollbar-width:none] [&::-webkit-scrollbar]:hidden", children: quickReplies.map((quickReply) => /* @__PURE__ */ jsx2(
|
|
322
|
+
"button",
|
|
323
|
+
{
|
|
324
|
+
type: "button",
|
|
325
|
+
title: quickReply.tooltip,
|
|
326
|
+
onClick: () => replaceContent(quickReply.text),
|
|
327
|
+
className: "whitespace-nowrap rounded-full border border-gray-200 bg-white px-2 py-1 text-xs text-gray-600 transition-colors hover:border-teal-200 hover:bg-teal-50 hover:text-teal-700 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:border-teal-800 dark:hover:bg-teal-950/40 dark:hover:text-teal-400",
|
|
328
|
+
children: quickReply.label
|
|
329
|
+
},
|
|
330
|
+
quickReply.id
|
|
331
|
+
)) })
|
|
332
|
+
) : null,
|
|
333
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex flex-wrap items-end gap-2", children: [
|
|
334
|
+
/* @__PURE__ */ jsx2("div", { className: "mb-0.5 hidden items-center gap-0.5 sm:flex", children: [
|
|
335
|
+
[RICH_COMPOSER_ACTION.BOLD, Bold],
|
|
336
|
+
[RICH_COMPOSER_ACTION.ITALIC, Italic],
|
|
337
|
+
[RICH_COMPOSER_ACTION.STRIKETHROUGH, Strikethrough],
|
|
338
|
+
[RICH_COMPOSER_ACTION.MONOSPACE, Code]
|
|
339
|
+
].filter(([action]) => shows(action)).map(([action, Icon]) => /* @__PURE__ */ jsx2(
|
|
340
|
+
"button",
|
|
341
|
+
{
|
|
342
|
+
type: "button",
|
|
343
|
+
onClick: () => wrapSelection(action),
|
|
344
|
+
title: tooltipOf(action),
|
|
345
|
+
"aria-label": tooltipOf(action),
|
|
346
|
+
className: "flex h-7 w-7 flex-shrink-0 items-center justify-center rounded-lg text-gray-400 transition-colors hover:bg-teal-50 hover:text-teal-600 dark:text-gray-500 dark:hover:bg-teal-900/30 dark:hover:text-teal-400",
|
|
347
|
+
children: /* @__PURE__ */ jsx2(Icon, { size: 15 })
|
|
348
|
+
},
|
|
349
|
+
action
|
|
350
|
+
)) }),
|
|
351
|
+
shows(RICH_COMPOSER_ACTION.EMOJI) ? /* @__PURE__ */ jsx2(SimpleEmojiPicker, { onSelect: insertAtCursor, label: tooltipOf("emoji") }) : null,
|
|
352
|
+
variables?.length && shows(RICH_COMPOSER_ACTION.VARIABLES) ? /* @__PURE__ */ jsxs2("div", { ref: variablesRef, className: "relative", children: [
|
|
353
|
+
/* @__PURE__ */ jsx2(
|
|
354
|
+
"button",
|
|
355
|
+
{
|
|
356
|
+
type: "button",
|
|
357
|
+
onClick: () => setIsVariablesOpen((open) => !open),
|
|
358
|
+
title: tooltipOf("variables"),
|
|
359
|
+
"aria-label": tooltipOf("variables"),
|
|
360
|
+
"aria-expanded": isVariablesOpen,
|
|
361
|
+
className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full text-gray-400 transition-colors hover:bg-teal-50 hover:text-teal-600 dark:text-gray-500 dark:hover:bg-teal-900/30 dark:hover:text-teal-400",
|
|
362
|
+
children: /* @__PURE__ */ jsx2(Braces, { size: 18 })
|
|
363
|
+
}
|
|
364
|
+
),
|
|
365
|
+
isVariablesOpen ? /* @__PURE__ */ jsx2("div", { className: "absolute bottom-full left-0 z-20 mb-2 max-h-56 w-64 overflow-y-auto rounded-xl border border-gray-200 bg-white py-1 shadow-lg dark:border-gray-700 dark:bg-gray-800", children: variables.map((variable) => /* @__PURE__ */ jsxs2(
|
|
366
|
+
"button",
|
|
367
|
+
{
|
|
368
|
+
type: "button",
|
|
369
|
+
title: variable.tooltip ?? variable.value,
|
|
370
|
+
onClick: () => {
|
|
371
|
+
insertAtCursor(variable.value);
|
|
372
|
+
setIsVariablesOpen(false);
|
|
373
|
+
},
|
|
374
|
+
className: "flex w-full flex-col items-start px-3 py-1.5 text-left hover:bg-teal-50 dark:hover:bg-teal-950/40",
|
|
375
|
+
children: [
|
|
376
|
+
/* @__PURE__ */ jsx2("span", { className: "text-sm text-gray-800 dark:text-gray-100", children: variable.label }),
|
|
377
|
+
/* @__PURE__ */ jsx2("span", { className: "font-mono text-xs text-gray-400 dark:text-gray-500", children: variable.value })
|
|
378
|
+
]
|
|
379
|
+
},
|
|
380
|
+
variable.id
|
|
381
|
+
)) }) : null
|
|
382
|
+
] }) : null,
|
|
383
|
+
onAttachFiles && shows(RICH_COMPOSER_ACTION.ATTACH) ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
384
|
+
/* @__PURE__ */ jsx2(
|
|
385
|
+
"input",
|
|
386
|
+
{
|
|
387
|
+
ref: fileInputRef,
|
|
388
|
+
type: "file",
|
|
389
|
+
multiple: true,
|
|
390
|
+
accept: acceptedFileTypes,
|
|
391
|
+
onChange: handleFileChange,
|
|
392
|
+
className: "hidden"
|
|
393
|
+
}
|
|
394
|
+
),
|
|
395
|
+
/* @__PURE__ */ jsx2(
|
|
396
|
+
"button",
|
|
397
|
+
{
|
|
398
|
+
type: "button",
|
|
399
|
+
onClick: () => fileInputRef.current?.click(),
|
|
400
|
+
title: tooltipOf("attach"),
|
|
401
|
+
"aria-label": tooltipOf("attach"),
|
|
402
|
+
className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full text-gray-400 transition-colors hover:bg-teal-50 hover:text-teal-600 dark:text-gray-500 dark:hover:bg-teal-900/30 dark:hover:text-teal-400",
|
|
403
|
+
children: /* @__PURE__ */ jsx2(Paperclip, { size: 18 })
|
|
404
|
+
}
|
|
405
|
+
)
|
|
406
|
+
] }) : null,
|
|
407
|
+
/* @__PURE__ */ jsx2(
|
|
408
|
+
"div",
|
|
409
|
+
{
|
|
410
|
+
ref: editorRef,
|
|
411
|
+
contentEditable: !disabled,
|
|
412
|
+
suppressContentEditableWarning: true,
|
|
413
|
+
role: "textbox",
|
|
414
|
+
"aria-multiline": "true",
|
|
415
|
+
"aria-label": placeholder,
|
|
416
|
+
"data-placeholder": placeholder,
|
|
417
|
+
onInput: handleInput,
|
|
418
|
+
onKeyDown: handleKeyDown,
|
|
419
|
+
style: { minHeight: "36px", maxHeight: "120px" },
|
|
420
|
+
className: "flex-1 min-w-[180px] overflow-y-auto rounded-2xl border border-gray-200 bg-gray-50 px-4 py-2 text-sm text-gray-800 transition-all focus:border-transparent focus:outline-none focus:ring-2 focus:ring-teal-300 dark:border-gray-700 dark:bg-gray-700 dark:text-gray-100 empty:before:content-[attr(data-placeholder)] empty:before:text-gray-400 dark:empty:before:text-gray-500 before:pointer-events-none [&_strong]:font-semibold [&_em]:italic [&_del]:line-through [&_code]:rounded [&_code]:bg-black/5 [&_code]:px-0.5 [&_code]:font-mono [&_code]:text-sm dark:[&_code]:bg-white/10"
|
|
421
|
+
}
|
|
422
|
+
),
|
|
423
|
+
!canSend && idleAction ? /* @__PURE__ */ jsx2("div", { className: "flex-shrink-0", children: idleAction }) : /* @__PURE__ */ jsx2(
|
|
424
|
+
"button",
|
|
425
|
+
{
|
|
426
|
+
type: "button",
|
|
427
|
+
onClick: onSend,
|
|
428
|
+
disabled: disabled || isSending || !canSend,
|
|
429
|
+
title: tooltipOf("send"),
|
|
430
|
+
"aria-label": tooltipOf("send"),
|
|
431
|
+
className: "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full bg-teal-600 text-white transition-colors hover:bg-teal-700 disabled:cursor-not-allowed disabled:opacity-40",
|
|
432
|
+
children: isSending ? /* @__PURE__ */ jsx2("span", { className: "text-xs", children: "\u23F3" }) : /* @__PURE__ */ jsx2(SendHorizonal, { size: 16 })
|
|
433
|
+
}
|
|
434
|
+
)
|
|
435
|
+
] })
|
|
436
|
+
] });
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
// src/WhatsAppMessageEditor.tsx
|
|
440
|
+
import { useRef as useRef3 } from "react";
|
|
441
|
+
import { Bold as Bold2, Italic as Italic2, Strikethrough as Strikethrough2 } from "lucide-react";
|
|
442
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
443
|
+
var DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS = {
|
|
444
|
+
bold: "Negrito",
|
|
445
|
+
boldHint: "Negrito (*texto*)",
|
|
446
|
+
italic: "It\xE1lico",
|
|
447
|
+
italicHint: "It\xE1lico (_texto_)",
|
|
448
|
+
strikethrough: "Tachado",
|
|
449
|
+
strikethroughHint: "Tachado (~texto~)",
|
|
450
|
+
insertPlaceholder: (token) => `Inserir ${token}`
|
|
451
|
+
};
|
|
452
|
+
var INLINE_TOKEN = /(\*[^*\n]+\*|_[^_\n]+_|~[^~\n]+~|`[^`\n]+`|\{[a-zA-Z_]+\})/g;
|
|
453
|
+
function renderLine(line, lineKey) {
|
|
454
|
+
const nodes = [];
|
|
455
|
+
let lastIndex = 0;
|
|
456
|
+
let match;
|
|
457
|
+
let tokenIndex = 0;
|
|
458
|
+
INLINE_TOKEN.lastIndex = 0;
|
|
459
|
+
while ((match = INLINE_TOKEN.exec(line)) !== null) {
|
|
460
|
+
if (match.index > lastIndex) nodes.push(line.slice(lastIndex, match.index));
|
|
461
|
+
const token = match[0];
|
|
462
|
+
const key = `${lineKey}-${tokenIndex++}`;
|
|
463
|
+
if (token.startsWith("*")) nodes.push(/* @__PURE__ */ jsx3("strong", { children: token.slice(1, -1) }, key));
|
|
464
|
+
else if (token.startsWith("_")) nodes.push(/* @__PURE__ */ jsx3("em", { children: token.slice(1, -1) }, key));
|
|
465
|
+
else if (token.startsWith("~")) nodes.push(/* @__PURE__ */ jsx3("s", { children: token.slice(1, -1) }, key));
|
|
466
|
+
else if (token.startsWith("`")) nodes.push(/* @__PURE__ */ jsx3("code", { className: "font-mono text-[0.85em]", children: token.slice(1, -1) }, key));
|
|
467
|
+
else nodes.push(/* @__PURE__ */ jsx3("span", { className: "rounded bg-blue-100 dark:bg-blue-900/50 text-blue-700 dark:text-blue-300 px-1", children: token }, key));
|
|
468
|
+
lastIndex = INLINE_TOKEN.lastIndex;
|
|
469
|
+
}
|
|
470
|
+
if (lastIndex < line.length) nodes.push(line.slice(lastIndex));
|
|
471
|
+
return nodes;
|
|
472
|
+
}
|
|
473
|
+
function renderWhatsApp(text) {
|
|
474
|
+
const lines = text.split("\n");
|
|
475
|
+
return lines.map((line, index) => /* @__PURE__ */ jsxs3("span", { children: [
|
|
476
|
+
renderLine(line, `ln-${index}`),
|
|
477
|
+
index < lines.length - 1 ? /* @__PURE__ */ jsx3("br", {}) : null
|
|
478
|
+
] }, `ln-${index}`));
|
|
479
|
+
}
|
|
480
|
+
function WhatsAppMessageEditor({
|
|
481
|
+
value,
|
|
482
|
+
onChange,
|
|
483
|
+
placeholder,
|
|
484
|
+
placeholders = [],
|
|
485
|
+
rows = 4,
|
|
486
|
+
previewLabel = "Pr\xE9via (como aparece no WhatsApp)",
|
|
487
|
+
emptyPreviewText = "Sua mensagem aparecer\xE1 aqui\u2026",
|
|
488
|
+
labels
|
|
489
|
+
}) {
|
|
490
|
+
const editorLabels = { ...DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS, ...labels };
|
|
491
|
+
const textareaRef = useRef3(null);
|
|
492
|
+
function wrapSelection(marker) {
|
|
493
|
+
const textarea = textareaRef.current;
|
|
494
|
+
if (!textarea) return;
|
|
495
|
+
const start = textarea.selectionStart;
|
|
496
|
+
const end = textarea.selectionEnd;
|
|
497
|
+
const selected = value.slice(start, end) || "texto";
|
|
498
|
+
const next = value.slice(0, start) + marker + selected + marker + value.slice(end);
|
|
499
|
+
onChange(next);
|
|
500
|
+
requestAnimationFrame(() => {
|
|
501
|
+
textarea.focus();
|
|
502
|
+
textarea.setSelectionRange(start + marker.length, start + marker.length + selected.length);
|
|
503
|
+
});
|
|
504
|
+
}
|
|
505
|
+
function insertAtCursor(snippet) {
|
|
506
|
+
const textarea = textareaRef.current;
|
|
507
|
+
if (!textarea) return;
|
|
508
|
+
const start = textarea.selectionStart;
|
|
509
|
+
const end = textarea.selectionEnd;
|
|
510
|
+
const next = value.slice(0, start) + snippet + value.slice(end);
|
|
511
|
+
onChange(next);
|
|
512
|
+
requestAnimationFrame(() => {
|
|
513
|
+
textarea.focus();
|
|
514
|
+
const caret = start + snippet.length;
|
|
515
|
+
textarea.setSelectionRange(caret, caret);
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
const toolbarButtonClass = "inline-flex items-center justify-center h-8 w-8 rounded-lg border border-gray-200 dark:border-gray-600 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors";
|
|
519
|
+
return /* @__PURE__ */ jsxs3("div", { children: [
|
|
520
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-1.5 mb-2", children: [
|
|
521
|
+
/* @__PURE__ */ jsx3("button", { type: "button", onClick: () => wrapSelection("*"), className: toolbarButtonClass, title: editorLabels.boldHint, "aria-label": editorLabels.bold, children: /* @__PURE__ */ jsx3(Bold2, { size: 15 }) }),
|
|
522
|
+
/* @__PURE__ */ jsx3("button", { type: "button", onClick: () => wrapSelection("_"), className: toolbarButtonClass, title: editorLabels.italicHint, "aria-label": editorLabels.italic, children: /* @__PURE__ */ jsx3(Italic2, { size: 15 }) }),
|
|
523
|
+
/* @__PURE__ */ jsx3("button", { type: "button", onClick: () => wrapSelection("~"), className: toolbarButtonClass, title: editorLabels.strikethroughHint, "aria-label": editorLabels.strikethrough, children: /* @__PURE__ */ jsx3(Strikethrough2, { size: 15 }) }),
|
|
524
|
+
placeholders.length > 0 && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
525
|
+
/* @__PURE__ */ jsx3("span", { className: "mx-1 h-5 w-px bg-gray-200 dark:bg-gray-600" }),
|
|
526
|
+
placeholders.map((token) => /* @__PURE__ */ jsx3(
|
|
527
|
+
"button",
|
|
528
|
+
{
|
|
529
|
+
type: "button",
|
|
530
|
+
onClick: () => insertAtCursor(token),
|
|
531
|
+
className: "inline-flex items-center h-8 px-2 rounded-lg border border-gray-200 dark:border-gray-600 text-xs text-blue-600 dark:text-blue-300 hover:bg-blue-50 dark:hover:bg-blue-900/40 transition-colors",
|
|
532
|
+
title: editorLabels.insertPlaceholder(token),
|
|
533
|
+
children: token
|
|
534
|
+
},
|
|
535
|
+
token
|
|
536
|
+
))
|
|
537
|
+
] })
|
|
538
|
+
] }),
|
|
539
|
+
/* @__PURE__ */ jsx3(
|
|
540
|
+
"textarea",
|
|
541
|
+
{
|
|
542
|
+
ref: textareaRef,
|
|
543
|
+
value,
|
|
544
|
+
onChange: (event) => onChange(event.target.value),
|
|
545
|
+
placeholder,
|
|
546
|
+
rows,
|
|
547
|
+
className: "w-full border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all placeholder:text-gray-400 dark:placeholder:text-gray-500 resize-y"
|
|
548
|
+
}
|
|
549
|
+
),
|
|
550
|
+
/* @__PURE__ */ jsxs3("div", { className: "mt-2", children: [
|
|
551
|
+
/* @__PURE__ */ jsx3("p", { className: "text-xs text-gray-500 dark:text-gray-400 mb-1", children: previewLabel }),
|
|
552
|
+
/* @__PURE__ */ jsx3("div", { className: "rounded-xl bg-[#e5ded8] dark:bg-gray-900 p-3", children: /* @__PURE__ */ jsx3("div", { className: "inline-block max-w-full rounded-lg rounded-tl-none bg-white dark:bg-gray-800 shadow-sm px-3 py-2 text-sm text-gray-800 dark:text-gray-100 whitespace-pre-wrap break-words", children: value.trim() ? renderWhatsApp(value) : /* @__PURE__ */ jsx3("span", { className: "text-gray-400 dark:text-gray-500", children: emptyPreviewText }) }) })
|
|
553
|
+
] })
|
|
554
|
+
] });
|
|
555
|
+
}
|
|
556
|
+
|
|
305
557
|
// src/Avatar.tsx
|
|
306
|
-
import { jsx as
|
|
558
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
307
559
|
var DEFAULT_AVATAR_LABELS = {
|
|
308
560
|
unnamedContact: "Contato sem nome"
|
|
309
561
|
};
|
|
@@ -336,7 +588,7 @@ function Avatar({ name, avatarUrl, size = "md", className = "", labels }) {
|
|
|
336
588
|
const sizeClass = sizeClasses[size];
|
|
337
589
|
const unnamedContactLabel = labels?.unnamedContact ?? DEFAULT_AVATAR_LABELS.unnamedContact;
|
|
338
590
|
if (avatarUrl) {
|
|
339
|
-
return /* @__PURE__ */
|
|
591
|
+
return /* @__PURE__ */ jsx4(
|
|
340
592
|
"img",
|
|
341
593
|
{
|
|
342
594
|
src: avatarUrl,
|
|
@@ -347,17 +599,17 @@ function Avatar({ name, avatarUrl, size = "md", className = "", labels }) {
|
|
|
347
599
|
}
|
|
348
600
|
const bgColor = getBgColor(name);
|
|
349
601
|
if (!name) {
|
|
350
|
-
return /* @__PURE__ */
|
|
602
|
+
return /* @__PURE__ */ jsx4(
|
|
351
603
|
"div",
|
|
352
604
|
{
|
|
353
605
|
className: `${sizeClass} ${bgColor} rounded-full flex items-center justify-center text-white flex-shrink-0 ${className}`,
|
|
354
606
|
role: "img",
|
|
355
607
|
"aria-label": unnamedContactLabel,
|
|
356
|
-
children: /* @__PURE__ */
|
|
608
|
+
children: /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 24 24", fill: "currentColor", className: "h-[60%] w-[60%]", "aria-hidden": true, children: /* @__PURE__ */ jsx4("path", { d: "M12 12a5 5 0 1 0 0-10 5 5 0 0 0 0 10Zm0 2c-4.42 0-8 2.24-8 5v1h16v-1c0-2.76-3.58-5-8-5Z" }) })
|
|
357
609
|
}
|
|
358
610
|
);
|
|
359
611
|
}
|
|
360
|
-
return /* @__PURE__ */
|
|
612
|
+
return /* @__PURE__ */ jsx4(
|
|
361
613
|
"div",
|
|
362
614
|
{
|
|
363
615
|
className: `${sizeClass} ${bgColor} rounded-full flex items-center justify-center text-white font-semibold flex-shrink-0 ${className}`,
|
|
@@ -450,7 +702,7 @@ function contactFlag(params) {
|
|
|
450
702
|
}
|
|
451
703
|
|
|
452
704
|
// src/ConversationListItem.tsx
|
|
453
|
-
import { jsx as
|
|
705
|
+
import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
454
706
|
var DEFAULT_CONVERSATION_LIST_ITEM_LABELS = {
|
|
455
707
|
expiredWindow: "Janela expirada",
|
|
456
708
|
warningWindow: "Janela pr\xF3xima do fim"
|
|
@@ -533,7 +785,7 @@ var ConversationListItem = ({
|
|
|
533
785
|
onClick?.();
|
|
534
786
|
onSelect?.(conversation.id);
|
|
535
787
|
};
|
|
536
|
-
return /* @__PURE__ */
|
|
788
|
+
return /* @__PURE__ */ jsxs4(
|
|
537
789
|
"button",
|
|
538
790
|
{
|
|
539
791
|
onClick: handleClick,
|
|
@@ -542,34 +794,34 @@ var ConversationListItem = ({
|
|
|
542
794
|
backgroundColor: isActive && highlightActive ? "#f0f2f5" : "transparent"
|
|
543
795
|
},
|
|
544
796
|
children: [
|
|
545
|
-
/* @__PURE__ */
|
|
546
|
-
/* @__PURE__ */
|
|
547
|
-
conversation.waitingHuman && /* @__PURE__ */
|
|
797
|
+
/* @__PURE__ */ jsxs4("div", { className: "relative flex-shrink-0", children: [
|
|
798
|
+
/* @__PURE__ */ jsx5(Avatar, { name: conversation.clientName, size: "lg" }),
|
|
799
|
+
conversation.waitingHuman && /* @__PURE__ */ jsx5("div", { className: "absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 bg-amber-400 rounded-full border-2 border-white" })
|
|
548
800
|
] }),
|
|
549
|
-
/* @__PURE__ */
|
|
550
|
-
/* @__PURE__ */
|
|
551
|
-
/* @__PURE__ */
|
|
552
|
-
!conversation.clientName && flag ? /* @__PURE__ */
|
|
553
|
-
/* @__PURE__ */
|
|
554
|
-
windowStatus && windowStatus.label === "expired" && /* @__PURE__ */
|
|
555
|
-
windowStatus && windowStatus.label === "warning" && /* @__PURE__ */
|
|
801
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex-1 min-w-0", children: [
|
|
802
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between gap-2", children: [
|
|
803
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5 min-w-0", children: [
|
|
804
|
+
!conversation.clientName && flag ? /* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: flag }) : null,
|
|
805
|
+
/* @__PURE__ */ jsx5("span", { className: "text-[16px] text-[#111b21] truncate", children: name }),
|
|
806
|
+
windowStatus && windowStatus.label === "expired" && /* @__PURE__ */ jsx5("span", { className: "w-2 h-2 rounded-full bg-red-500 flex-shrink-0", title: expiredWindowLabel }),
|
|
807
|
+
windowStatus && windowStatus.label === "warning" && /* @__PURE__ */ jsx5("span", { className: "w-2 h-2 rounded-full bg-orange-500 flex-shrink-0", title: warningWindowLabel })
|
|
556
808
|
] }),
|
|
557
|
-
timestamp && /* @__PURE__ */
|
|
809
|
+
timestamp && /* @__PURE__ */ jsx5("span", { className: "text-xs text-[#667781] flex-shrink-0", children: timestamp })
|
|
558
810
|
] }),
|
|
559
|
-
conversation.clientName ? /* @__PURE__ */
|
|
560
|
-
flag ? /* @__PURE__ */
|
|
561
|
-
/* @__PURE__ */
|
|
811
|
+
conversation.clientName ? /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1 text-xs text-[#667781]", children: [
|
|
812
|
+
flag ? /* @__PURE__ */ jsx5("span", { "aria-hidden": true, children: flag }) : null,
|
|
813
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: displayHandle })
|
|
562
814
|
] }) : null,
|
|
563
|
-
/* @__PURE__ */
|
|
564
|
-
/* @__PURE__ */
|
|
565
|
-
preview.icon && /* @__PURE__ */
|
|
815
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between mt-0.5", children: [
|
|
816
|
+
/* @__PURE__ */ jsxs4("span", { className: "text-sm text-[#667781] truncate max-w-[180px]", children: [
|
|
817
|
+
preview.icon && /* @__PURE__ */ jsx5("span", { className: "mr-1", children: preview.icon }),
|
|
566
818
|
preview.preview || "Sem mensagens"
|
|
567
819
|
] }),
|
|
568
|
-
conversation.unread > 0 && /* @__PURE__ */
|
|
820
|
+
conversation.unread > 0 && /* @__PURE__ */ jsx5("span", { className: "bg-[#25d366] text-white text-xs font-semibold rounded-full min-w-[20px] h-5 px-1.5 flex items-center justify-center flex-shrink-0 ml-2", children: conversation.unread > 99 ? "99+" : conversation.unread })
|
|
569
821
|
] }),
|
|
570
|
-
/* @__PURE__ */
|
|
571
|
-
conversation.mode === "human" && /* @__PURE__ */
|
|
572
|
-
conversation.mode === "bot" && conversation.waitingHuman && /* @__PURE__ */
|
|
822
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5 mt-1", children: [
|
|
823
|
+
conversation.mode === "human" && /* @__PURE__ */ jsx5("span", { className: "text-[10px] px-1.5 py-0.5 rounded font-medium bg-purple-100 text-purple-700", children: "Humano" }),
|
|
824
|
+
conversation.mode === "bot" && conversation.waitingHuman && /* @__PURE__ */ jsx5("span", { className: "text-[10px] px-1.5 py-0.5 rounded font-medium bg-amber-100 text-amber-700", children: "Aguardando" })
|
|
573
825
|
] })
|
|
574
826
|
] })
|
|
575
827
|
]
|
|
@@ -578,8 +830,8 @@ var ConversationListItem = ({
|
|
|
578
830
|
};
|
|
579
831
|
|
|
580
832
|
// src/Toast.tsx
|
|
581
|
-
import { createContext, useContext, useState as
|
|
582
|
-
import { jsx as
|
|
833
|
+
import { createContext, useContext, useState as useState3, useCallback as useCallback2, useEffect as useEffect3 } from "react";
|
|
834
|
+
import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
583
835
|
var ToastContext = createContext(null);
|
|
584
836
|
var nextId = 0;
|
|
585
837
|
var singletonShow = null;
|
|
@@ -596,34 +848,34 @@ var typeStyles = {
|
|
|
596
848
|
info: "bg-blue-600"
|
|
597
849
|
};
|
|
598
850
|
var typeIcons = {
|
|
599
|
-
success: /* @__PURE__ */
|
|
600
|
-
error: /* @__PURE__ */
|
|
601
|
-
/* @__PURE__ */
|
|
602
|
-
/* @__PURE__ */
|
|
851
|
+
success: /* @__PURE__ */ jsx6("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx6("polyline", { points: "20 6 9 17 4 12" }) }),
|
|
852
|
+
error: /* @__PURE__ */ jsxs5("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
853
|
+
/* @__PURE__ */ jsx6("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
854
|
+
/* @__PURE__ */ jsx6("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
603
855
|
] }),
|
|
604
|
-
info: /* @__PURE__ */
|
|
605
|
-
/* @__PURE__ */
|
|
606
|
-
/* @__PURE__ */
|
|
607
|
-
/* @__PURE__ */
|
|
856
|
+
info: /* @__PURE__ */ jsxs5("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
857
|
+
/* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "10" }),
|
|
858
|
+
/* @__PURE__ */ jsx6("line", { x1: "12", y1: "16", x2: "12", y2: "12" }),
|
|
859
|
+
/* @__PURE__ */ jsx6("line", { x1: "12", y1: "8", x2: "12.01", y2: "8" })
|
|
608
860
|
] })
|
|
609
861
|
};
|
|
610
862
|
function ToastItemComponent({ item, onRemove }) {
|
|
611
|
-
const [exiting, setExiting] =
|
|
612
|
-
|
|
863
|
+
const [exiting, setExiting] = useState3(false);
|
|
864
|
+
useEffect3(() => {
|
|
613
865
|
const timer = setTimeout(() => {
|
|
614
866
|
setExiting(true);
|
|
615
867
|
setTimeout(() => onRemove(item.id), 300);
|
|
616
868
|
}, 5e3);
|
|
617
869
|
return () => clearTimeout(timer);
|
|
618
870
|
}, [item.id, onRemove]);
|
|
619
|
-
return /* @__PURE__ */
|
|
871
|
+
return /* @__PURE__ */ jsxs5(
|
|
620
872
|
"div",
|
|
621
873
|
{
|
|
622
874
|
className: `flex items-center gap-2 px-4 py-3 rounded-lg shadow-lg text-white text-sm min-w-[280px] max-w-[400px] ${typeStyles[item.type]} ${exiting ? "animate-slide-out" : "animate-slide-in"}`,
|
|
623
875
|
children: [
|
|
624
|
-
/* @__PURE__ */
|
|
625
|
-
/* @__PURE__ */
|
|
626
|
-
/* @__PURE__ */
|
|
876
|
+
/* @__PURE__ */ jsx6("span", { className: "flex-shrink-0", children: typeIcons[item.type] }),
|
|
877
|
+
/* @__PURE__ */ jsx6("span", { className: "flex-1", children: item.message }),
|
|
878
|
+
/* @__PURE__ */ jsx6(
|
|
627
879
|
"button",
|
|
628
880
|
{
|
|
629
881
|
onClick: () => {
|
|
@@ -631,9 +883,9 @@ function ToastItemComponent({ item, onRemove }) {
|
|
|
631
883
|
setTimeout(() => onRemove(item.id), 300);
|
|
632
884
|
},
|
|
633
885
|
className: "flex-shrink-0 opacity-70 hover:opacity-100 transition-opacity",
|
|
634
|
-
children: /* @__PURE__ */
|
|
635
|
-
/* @__PURE__ */
|
|
636
|
-
/* @__PURE__ */
|
|
886
|
+
children: /* @__PURE__ */ jsxs5("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
887
|
+
/* @__PURE__ */ jsx6("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
888
|
+
/* @__PURE__ */ jsx6("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
637
889
|
] })
|
|
638
890
|
}
|
|
639
891
|
)
|
|
@@ -642,24 +894,24 @@ function ToastItemComponent({ item, onRemove }) {
|
|
|
642
894
|
);
|
|
643
895
|
}
|
|
644
896
|
function ToastProvider({ children }) {
|
|
645
|
-
const [items, setItems] =
|
|
646
|
-
const show =
|
|
897
|
+
const [items, setItems] = useState3([]);
|
|
898
|
+
const show = useCallback2((type, message) => {
|
|
647
899
|
const id = ++nextId;
|
|
648
900
|
setItems((prev) => [...prev, { id, type, message }]);
|
|
649
901
|
}, []);
|
|
650
|
-
const remove =
|
|
902
|
+
const remove = useCallback2((id) => {
|
|
651
903
|
setItems((prev) => prev.filter((item) => item.id !== id));
|
|
652
904
|
}, []);
|
|
653
|
-
|
|
905
|
+
useEffect3(() => {
|
|
654
906
|
singletonShow = show;
|
|
655
907
|
return () => {
|
|
656
908
|
singletonShow = null;
|
|
657
909
|
};
|
|
658
910
|
}, [show]);
|
|
659
|
-
return /* @__PURE__ */
|
|
911
|
+
return /* @__PURE__ */ jsxs5(ToastContext.Provider, { value: { show }, children: [
|
|
660
912
|
children,
|
|
661
|
-
/* @__PURE__ */
|
|
662
|
-
/* @__PURE__ */
|
|
913
|
+
/* @__PURE__ */ jsx6("div", { className: "fixed top-4 right-4 z-[100] flex flex-col gap-2", children: items.map((item) => /* @__PURE__ */ jsx6(ToastItemComponent, { item, onRemove: remove }, item.id)) }),
|
|
914
|
+
/* @__PURE__ */ jsx6("style", { children: `
|
|
663
915
|
@keyframes slide-in {
|
|
664
916
|
from { transform: translateX(100%); opacity: 0; }
|
|
665
917
|
to { transform: translateX(0); opacity: 1; }
|
|
@@ -682,11 +934,11 @@ function useToast() {
|
|
|
682
934
|
}
|
|
683
935
|
|
|
684
936
|
// src/MessageText.tsx
|
|
685
|
-
import { useCallback as
|
|
686
|
-
import { jsx as
|
|
937
|
+
import { useCallback as useCallback3, useState as useState4 } from "react";
|
|
938
|
+
import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
687
939
|
function MessageText({ message }) {
|
|
688
|
-
const [copied, setCopied] =
|
|
689
|
-
const handleCopy =
|
|
940
|
+
const [copied, setCopied] = useState4(false);
|
|
941
|
+
const handleCopy = useCallback3(async () => {
|
|
690
942
|
if (!message.content) return;
|
|
691
943
|
try {
|
|
692
944
|
await navigator.clipboard.writeText(message.content);
|
|
@@ -696,35 +948,35 @@ function MessageText({ message }) {
|
|
|
696
948
|
}
|
|
697
949
|
}, [message.content]);
|
|
698
950
|
if (message.type === "template")
|
|
699
|
-
return /* @__PURE__ */
|
|
700
|
-
return /* @__PURE__ */
|
|
951
|
+
return /* @__PURE__ */ jsx7("p", { className: "text-sm italic text-[#667781]", children: message.content ?? "Template message" });
|
|
952
|
+
return /* @__PURE__ */ jsxs6(
|
|
701
953
|
"div",
|
|
702
954
|
{
|
|
703
955
|
onClick: handleCopy,
|
|
704
956
|
className: "text-[14.2px] leading-[19px] whitespace-pre-wrap break-words select-all [&_strong]:font-bold [&_em]:italic [&_del]:line-through",
|
|
705
957
|
children: [
|
|
706
|
-
/* @__PURE__ */
|
|
707
|
-
copied && /* @__PURE__ */
|
|
958
|
+
/* @__PURE__ */ jsx7("span", { children: parseWhatsAppFormatting(message.content ?? "") }),
|
|
959
|
+
copied && /* @__PURE__ */ jsx7("span", { className: "absolute top-0 right-0 -translate-y-full bg-[#3b4a54] text-white text-[11px] px-1.5 py-0.5 rounded shadow-lg", children: "Copiado!" })
|
|
708
960
|
]
|
|
709
961
|
}
|
|
710
962
|
);
|
|
711
963
|
}
|
|
712
964
|
|
|
713
965
|
// src/MessageTimestamp.tsx
|
|
714
|
-
import { jsx as
|
|
966
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
715
967
|
function MessageTimestamp({ timestamp, status, isOutbound }) {
|
|
716
|
-
return /* @__PURE__ */
|
|
717
|
-
/* @__PURE__ */
|
|
718
|
-
isOutbound && status && /* @__PURE__ */
|
|
968
|
+
return /* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-end gap-[3px]", children: [
|
|
969
|
+
/* @__PURE__ */ jsx8("span", { className: "text-[11px] text-[#667781] leading-[15px] select-none", children: timestamp }),
|
|
970
|
+
isOutbound && status && /* @__PURE__ */ jsx8("span", { className: "flex items-center -mr-[2px]", children: /* @__PURE__ */ jsx8(StatusTicks, { status }) })
|
|
719
971
|
] });
|
|
720
972
|
}
|
|
721
973
|
|
|
722
974
|
// src/MessageTail.tsx
|
|
723
|
-
import { jsx as
|
|
975
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
724
976
|
function MessageTail({ isOutbound }) {
|
|
725
977
|
if (isOutbound)
|
|
726
|
-
return /* @__PURE__ */
|
|
727
|
-
return /* @__PURE__ */
|
|
978
|
+
return /* @__PURE__ */ jsx9("svg", { className: "absolute top-0 -right-[5px] w-[5px] h-[11px]", viewBox: "0 0 5 11", fill: "#d9fdd3", children: /* @__PURE__ */ jsx9("path", { d: "M5 0H0v11c1.5-2 4.5-2 5-4V0z" }) });
|
|
979
|
+
return /* @__PURE__ */ jsx9("svg", { className: "absolute top-0 -left-[5px] w-[5px] h-[11px]", viewBox: "0 0 5 11", fill: "white", children: /* @__PURE__ */ jsx9("path", { d: "M0 0h5v11C3.5 9 .5 9 0 7V0z" }) });
|
|
728
980
|
}
|
|
729
981
|
|
|
730
982
|
// src/conversationWindow.ts
|
|
@@ -769,7 +1021,7 @@ function formatStalledFor(lastAt, now) {
|
|
|
769
1021
|
}
|
|
770
1022
|
|
|
771
1023
|
// src/ChannelIcon.tsx
|
|
772
|
-
import { Fragment as
|
|
1024
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
773
1025
|
var CHANNEL_BRAND_COLOR = {
|
|
774
1026
|
[CONVERSATION_CHANNEL.WHATSAPP]: "#25D366",
|
|
775
1027
|
[CONVERSATION_CHANNEL.MESSENGER]: "#0084FF",
|
|
@@ -779,9 +1031,9 @@ var CHANNEL_BRAND_COLOR = {
|
|
|
779
1031
|
function Glyph({ channel }) {
|
|
780
1032
|
const color = CHANNEL_BRAND_COLOR[channel];
|
|
781
1033
|
if (channel === CONVERSATION_CHANNEL.WHATSAPP) {
|
|
782
|
-
return /* @__PURE__ */
|
|
783
|
-
/* @__PURE__ */
|
|
784
|
-
/* @__PURE__ */
|
|
1034
|
+
return /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
1035
|
+
/* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "11", fill: color }),
|
|
1036
|
+
/* @__PURE__ */ jsx10(
|
|
785
1037
|
"path",
|
|
786
1038
|
{
|
|
787
1039
|
d: "M8.6 7.2c.3-.1.7 0 .9.3l1 1.6c.2.3.1.7-.1.9l-.7.7c.6 1.3 1.6 2.3 2.9 2.9l.7-.7c.2-.2.6-.3.9-.1l1.6 1c.3.2.4.6.3.9-.4 1-1.4 1.6-2.4 1.4-3-.5-5.4-2.9-5.9-5.9-.2-1 .4-2 1.4-2.4Z",
|
|
@@ -791,28 +1043,28 @@ function Glyph({ channel }) {
|
|
|
791
1043
|
] });
|
|
792
1044
|
}
|
|
793
1045
|
if (channel === CONVERSATION_CHANNEL.MESSENGER) {
|
|
794
|
-
return /* @__PURE__ */
|
|
795
|
-
/* @__PURE__ */
|
|
796
|
-
/* @__PURE__ */
|
|
1046
|
+
return /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
1047
|
+
/* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "11", fill: color }),
|
|
1048
|
+
/* @__PURE__ */ jsx10("path", { d: "M6.5 15.5 11 10.8l2.4 2.4L17.5 9l-4.6 4.9-2.4-2.4-4 4Z", fill: "#fff", stroke: "#fff", strokeWidth: "1.4", strokeLinejoin: "round" })
|
|
797
1049
|
] });
|
|
798
1050
|
}
|
|
799
1051
|
if (channel === CONVERSATION_CHANNEL.INSTAGRAM) {
|
|
800
|
-
return /* @__PURE__ */
|
|
801
|
-
/* @__PURE__ */
|
|
802
|
-
/* @__PURE__ */
|
|
803
|
-
/* @__PURE__ */
|
|
804
|
-
/* @__PURE__ */
|
|
1052
|
+
return /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
1053
|
+
/* @__PURE__ */ jsx10("rect", { x: "2", y: "2", width: "20", height: "20", rx: "6", fill: color }),
|
|
1054
|
+
/* @__PURE__ */ jsx10("rect", { x: "6.5", y: "6.5", width: "11", height: "11", rx: "3.5", fill: "none", stroke: "#fff", strokeWidth: "1.6" }),
|
|
1055
|
+
/* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "2.6", fill: "none", stroke: "#fff", strokeWidth: "1.6" }),
|
|
1056
|
+
/* @__PURE__ */ jsx10("circle", { cx: "16.4", cy: "7.6", r: "1", fill: "#fff" })
|
|
805
1057
|
] });
|
|
806
1058
|
}
|
|
807
|
-
return /* @__PURE__ */
|
|
808
|
-
/* @__PURE__ */
|
|
809
|
-
/* @__PURE__ */
|
|
1059
|
+
return /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
1060
|
+
/* @__PURE__ */ jsx10("circle", { cx: "12", cy: "12", r: "11", fill: color }),
|
|
1061
|
+
/* @__PURE__ */ jsx10("path", { d: "M6.5 8.5h11v7h-5.5L8.5 18v-2.5h-2v-7Z", fill: "#fff" })
|
|
810
1062
|
] });
|
|
811
1063
|
}
|
|
812
1064
|
function ChannelIcon({ channel, size = 14, className = "" }) {
|
|
813
1065
|
const resolved = channel ?? CONVERSATION_CHANNEL.WHATSAPP;
|
|
814
1066
|
const { label } = capabilitiesOf(resolved);
|
|
815
|
-
return /* @__PURE__ */
|
|
1067
|
+
return /* @__PURE__ */ jsx10(
|
|
816
1068
|
"svg",
|
|
817
1069
|
{
|
|
818
1070
|
viewBox: "0 0 24 24",
|
|
@@ -821,13 +1073,13 @@ function ChannelIcon({ channel, size = 14, className = "" }) {
|
|
|
821
1073
|
className: `inline-block shrink-0 ${className}`.trim(),
|
|
822
1074
|
role: "img",
|
|
823
1075
|
"aria-label": label,
|
|
824
|
-
children: /* @__PURE__ */
|
|
1076
|
+
children: /* @__PURE__ */ jsx10(Glyph, { channel: resolved })
|
|
825
1077
|
}
|
|
826
1078
|
);
|
|
827
1079
|
}
|
|
828
1080
|
|
|
829
1081
|
// src/ConversationRow.tsx
|
|
830
|
-
import { jsx as
|
|
1082
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
831
1083
|
var WINDOW_TITLE = {
|
|
832
1084
|
[CONVERSATION_WINDOW.ALL]: "",
|
|
833
1085
|
[CONVERSATION_WINDOW.FRESH]: "Janela de 24h aberta (menos de 12h)",
|
|
@@ -860,8 +1112,8 @@ function ConversationRow({
|
|
|
860
1112
|
const stalledMs = now - new Date(conversation.lastAt).getTime();
|
|
861
1113
|
const isStalled = stalledMs > STALLED_THRESHOLD_MS;
|
|
862
1114
|
const isWaiting = conversation.mode === "bot" && conversation.waitingHuman;
|
|
863
|
-
return /* @__PURE__ */
|
|
864
|
-
/* @__PURE__ */
|
|
1115
|
+
return /* @__PURE__ */ jsxs9("div", { className: cn("cv-row flex border-b", active && "cv-row--active", classNames?.root, className), children: [
|
|
1116
|
+
/* @__PURE__ */ jsx11(
|
|
865
1117
|
"span",
|
|
866
1118
|
{
|
|
867
1119
|
className: cn("w-1 shrink-0", WINDOW_BAR_CLASS[window2], classNames?.windowBar),
|
|
@@ -869,9 +1121,9 @@ function ConversationRow({
|
|
|
869
1121
|
"aria-label": WINDOW_TITLE[window2]
|
|
870
1122
|
}
|
|
871
1123
|
),
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
/* @__PURE__ */
|
|
874
|
-
/* @__PURE__ */
|
|
1124
|
+
/* @__PURE__ */ jsxs9("div", { className: "min-w-0 flex-1", children: [
|
|
1125
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-2 px-2 pt-2", children: [
|
|
1126
|
+
/* @__PURE__ */ jsx11(
|
|
875
1127
|
"input",
|
|
876
1128
|
{
|
|
877
1129
|
type: "checkbox",
|
|
@@ -881,7 +1133,7 @@ function ConversationRow({
|
|
|
881
1133
|
className: "mt-3"
|
|
882
1134
|
}
|
|
883
1135
|
),
|
|
884
|
-
/* @__PURE__ */
|
|
1136
|
+
/* @__PURE__ */ jsx11("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx11(
|
|
885
1137
|
ConversationListItem,
|
|
886
1138
|
{
|
|
887
1139
|
conversation,
|
|
@@ -892,28 +1144,28 @@ function ConversationRow({
|
|
|
892
1144
|
}
|
|
893
1145
|
) })
|
|
894
1146
|
] }),
|
|
895
|
-
/* @__PURE__ */
|
|
896
|
-
/* @__PURE__ */
|
|
897
|
-
/* @__PURE__ */
|
|
1147
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex flex-wrap items-center gap-1.5 px-4 pb-2 pl-8", children: [
|
|
1148
|
+
/* @__PURE__ */ jsxs9("span", { className: "cv-pill", children: [
|
|
1149
|
+
/* @__PURE__ */ jsx11(ChannelIcon, { channel: conversation.channel }),
|
|
898
1150
|
" ",
|
|
899
1151
|
capabilities.label
|
|
900
1152
|
] }),
|
|
901
|
-
conversation.mode === "human" ? /* @__PURE__ */
|
|
902
|
-
isWaiting ? /* @__PURE__ */
|
|
903
|
-
!isWaiting && conversation.mode === "bot" ? /* @__PURE__ */
|
|
904
|
-
isStalled ? /* @__PURE__ */
|
|
1153
|
+
conversation.mode === "human" ? /* @__PURE__ */ jsx11("span", { className: "cv-pill cv-pill--success", children: "\u{1F9D1}\u200D\u{1F4BC} em atendimento" }) : null,
|
|
1154
|
+
isWaiting ? /* @__PURE__ */ jsx11("span", { className: "cv-pill cv-pill--warning", children: "\u23F3 aguardando atendimento" }) : null,
|
|
1155
|
+
!isWaiting && conversation.mode === "bot" ? /* @__PURE__ */ jsx11("span", { className: "cv-pill", children: "\u{1F916} bot ativo" }) : null,
|
|
1156
|
+
isStalled ? /* @__PURE__ */ jsxs9("span", { className: "cv-pill cv-pill--danger", children: [
|
|
905
1157
|
"\u23F1\uFE0F parada h\xE1 ",
|
|
906
1158
|
formatStalledFor(conversation.lastAt, now)
|
|
907
1159
|
] }) : null,
|
|
908
|
-
isWaiting ? /* @__PURE__ */
|
|
1160
|
+
isWaiting ? /* @__PURE__ */ jsx11("button", { type: "button", onClick: onTakeover, disabled: busy, className: "cv-header-action", children: "\u25B6\uFE0F Continuar Atendimento" }) : null
|
|
909
1161
|
] })
|
|
910
1162
|
] })
|
|
911
1163
|
] });
|
|
912
1164
|
}
|
|
913
1165
|
|
|
914
1166
|
// src/ConversationHeader.tsx
|
|
915
|
-
import { useState as
|
|
916
|
-
import { jsx as
|
|
1167
|
+
import { useState as useState5 } from "react";
|
|
1168
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
917
1169
|
var DEFAULT_CONVERSATION_HEADER_LABELS = {
|
|
918
1170
|
botMode: "\u{1F916} atendimento autom\xE1tico",
|
|
919
1171
|
humanMode: "\u{1F9D1}\u200D\u{1F4BC} atendimento humano",
|
|
@@ -946,7 +1198,7 @@ function ConversationHeader({
|
|
|
946
1198
|
const displayHandle = formatContactHandle({ handle, channel: conversation.channel });
|
|
947
1199
|
const flag = contactFlag({ handle, channel: conversation.channel });
|
|
948
1200
|
const capabilities = capabilitiesOf(conversation.channel);
|
|
949
|
-
const [menuOpen, setMenuOpen] =
|
|
1201
|
+
const [menuOpen, setMenuOpen] = useState5(false);
|
|
950
1202
|
const utilities = [
|
|
951
1203
|
onOpenDocuments ? { key: "documents", icon: "\u{1F4C4}", label: labels.documents, run: onOpenDocuments, active: documentsOpen } : void 0,
|
|
952
1204
|
onDownload ? { key: "download", icon: "\u2B07\uFE0F", label: labels.download, run: onDownload, active: false } : void 0,
|
|
@@ -968,7 +1220,7 @@ function ConversationHeader({
|
|
|
968
1220
|
})),
|
|
969
1221
|
...actions
|
|
970
1222
|
];
|
|
971
|
-
return /* @__PURE__ */
|
|
1223
|
+
return /* @__PURE__ */ jsxs10(
|
|
972
1224
|
"header",
|
|
973
1225
|
{
|
|
974
1226
|
className: cn(
|
|
@@ -977,26 +1229,26 @@ function ConversationHeader({
|
|
|
977
1229
|
className
|
|
978
1230
|
),
|
|
979
1231
|
children: [
|
|
980
|
-
/* @__PURE__ */
|
|
981
|
-
onBack ? /* @__PURE__ */
|
|
982
|
-
/* @__PURE__ */
|
|
983
|
-
/* @__PURE__ */
|
|
984
|
-
/* @__PURE__ */
|
|
985
|
-
/* @__PURE__ */
|
|
1232
|
+
/* @__PURE__ */ jsxs10("div", { className: cn("flex min-w-0 flex-1 items-center gap-3", classNames?.identity), children: [
|
|
1233
|
+
onBack ? /* @__PURE__ */ jsx12("button", { type: "button", onClick: onBack, className: "cv-back cv-touch", "aria-label": labels.back, title: labels.back, children: "\u2190" }) : null,
|
|
1234
|
+
/* @__PURE__ */ jsx12(Avatar, { name: conversation.clientName, size: "md" }),
|
|
1235
|
+
/* @__PURE__ */ jsxs10("div", { className: "min-w-0", children: [
|
|
1236
|
+
/* @__PURE__ */ jsx12("p", { className: cn("truncate font-medium", classNames?.name), children: conversation.clientName ?? displayHandle }),
|
|
1237
|
+
/* @__PURE__ */ jsxs10("p", { className: cn("truncate text-xs text-gray-500", classNames?.meta), children: [
|
|
986
1238
|
flag ? `${flag} ` : "",
|
|
987
1239
|
displayHandle,
|
|
988
|
-
/* @__PURE__ */
|
|
989
|
-
/* @__PURE__ */
|
|
990
|
-
/* @__PURE__ */
|
|
1240
|
+
/* @__PURE__ */ jsxs10("span", { className: "ml-2 inline-flex items-center gap-1", children: [
|
|
1241
|
+
/* @__PURE__ */ jsx12(ChannelIcon, { channel: conversation.channel }),
|
|
1242
|
+
/* @__PURE__ */ jsx12("span", { className: "cv-only-wide", children: capabilities.label })
|
|
991
1243
|
] }),
|
|
992
|
-
/* @__PURE__ */
|
|
993
|
-
/* @__PURE__ */
|
|
1244
|
+
/* @__PURE__ */ jsx12("span", { className: "ml-2 cv-only-wide", children: isHuman ? labels.humanMode : labels.botMode }),
|
|
1245
|
+
/* @__PURE__ */ jsx12("span", { className: "ml-1 cv-only-narrow", title: isHuman ? labels.humanMode : labels.botMode, children: isHuman ? "\u{1F9D1}\u200D\u{1F4BC}" : "\u{1F916}" })
|
|
994
1246
|
] })
|
|
995
1247
|
] })
|
|
996
1248
|
] }),
|
|
997
|
-
/* @__PURE__ */
|
|
998
|
-
/* @__PURE__ */
|
|
999
|
-
utilities.map((utility) => /* @__PURE__ */
|
|
1249
|
+
/* @__PURE__ */ jsxs10("div", { className: cn("flex shrink-0 items-center gap-2", classNames?.actions), children: [
|
|
1250
|
+
/* @__PURE__ */ jsxs10("div", { className: cn("hidden items-center gap-2 lg:flex", classNames?.desktopActions), children: [
|
|
1251
|
+
utilities.map((utility) => /* @__PURE__ */ jsx12(
|
|
1000
1252
|
"button",
|
|
1001
1253
|
{
|
|
1002
1254
|
type: "button",
|
|
@@ -1010,7 +1262,7 @@ function ConversationHeader({
|
|
|
1010
1262
|
},
|
|
1011
1263
|
utility.key
|
|
1012
1264
|
)),
|
|
1013
|
-
actions.map((action) => /* @__PURE__ */
|
|
1265
|
+
actions.map((action) => /* @__PURE__ */ jsx12(
|
|
1014
1266
|
"button",
|
|
1015
1267
|
{
|
|
1016
1268
|
type: "button",
|
|
@@ -1022,8 +1274,8 @@ function ConversationHeader({
|
|
|
1022
1274
|
action.key
|
|
1023
1275
|
))
|
|
1024
1276
|
] }),
|
|
1025
|
-
menuItems.length > 0 ? /* @__PURE__ */
|
|
1026
|
-
/* @__PURE__ */
|
|
1277
|
+
menuItems.length > 0 ? /* @__PURE__ */ jsxs10("div", { className: cn("cv-menu lg:hidden", classNames?.mobileMenu), children: [
|
|
1278
|
+
/* @__PURE__ */ jsx12(
|
|
1027
1279
|
"button",
|
|
1028
1280
|
{
|
|
1029
1281
|
type: "button",
|
|
@@ -1035,7 +1287,7 @@ function ConversationHeader({
|
|
|
1035
1287
|
children: "\u22EE"
|
|
1036
1288
|
}
|
|
1037
1289
|
),
|
|
1038
|
-
menuOpen ? /* @__PURE__ */
|
|
1290
|
+
menuOpen ? /* @__PURE__ */ jsx12("div", { className: "cv-menu-panel", role: "menu", children: menuItems.map((item) => /* @__PURE__ */ jsx12(
|
|
1039
1291
|
"button",
|
|
1040
1292
|
{
|
|
1041
1293
|
type: "button",
|
|
@@ -1058,16 +1310,16 @@ function ConversationHeader({
|
|
|
1058
1310
|
}
|
|
1059
1311
|
|
|
1060
1312
|
// src/ConversationContextPanel.tsx
|
|
1061
|
-
import { useState as
|
|
1313
|
+
import { useState as useState7 } from "react";
|
|
1062
1314
|
|
|
1063
1315
|
// src/useIsNarrow.ts
|
|
1064
|
-
import { useEffect as
|
|
1316
|
+
import { useEffect as useEffect4, useState as useState6 } from "react";
|
|
1065
1317
|
var NARROW_MAX_WIDTH_PX = 1023;
|
|
1066
1318
|
function useIsNarrow() {
|
|
1067
|
-
const [isNarrow, setIsNarrow] =
|
|
1319
|
+
const [isNarrow, setIsNarrow] = useState6(
|
|
1068
1320
|
() => typeof window !== "undefined" && window.matchMedia(`(max-width: ${NARROW_MAX_WIDTH_PX}px)`).matches
|
|
1069
1321
|
);
|
|
1070
|
-
|
|
1322
|
+
useEffect4(() => {
|
|
1071
1323
|
const query = window.matchMedia(`(max-width: ${NARROW_MAX_WIDTH_PX}px)`);
|
|
1072
1324
|
const handleChange = (event) => setIsNarrow(event.matches);
|
|
1073
1325
|
query.addEventListener("change", handleChange);
|
|
@@ -1078,7 +1330,7 @@ function useIsNarrow() {
|
|
|
1078
1330
|
}
|
|
1079
1331
|
|
|
1080
1332
|
// src/ConversationContextPanel.tsx
|
|
1081
|
-
import { jsx as
|
|
1333
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1082
1334
|
var DEFAULT_CONVERSATION_CONTEXT_LABELS = {
|
|
1083
1335
|
title: "\u{1F4CB} Suas Sele\xE7\xF5es",
|
|
1084
1336
|
empty: "Nada coletado ainda nesta conversa."
|
|
@@ -1092,10 +1344,10 @@ function ConversationContextPanel({
|
|
|
1092
1344
|
const labels = { ...DEFAULT_CONVERSATION_CONTEXT_LABELS, ...labelsOverride };
|
|
1093
1345
|
const filled = entries.filter((entry) => Boolean(entry.value));
|
|
1094
1346
|
const isNarrow = useIsNarrow();
|
|
1095
|
-
const [manualOpen, setManualOpen] =
|
|
1347
|
+
const [manualOpen, setManualOpen] = useState7(void 0);
|
|
1096
1348
|
const open = manualOpen ?? (!isNarrow && filled.length > 0);
|
|
1097
|
-
return /* @__PURE__ */
|
|
1098
|
-
/* @__PURE__ */
|
|
1349
|
+
return /* @__PURE__ */ jsxs11("section", { className: cn("border-b", classNames?.root, className), children: [
|
|
1350
|
+
/* @__PURE__ */ jsxs11(
|
|
1099
1351
|
"button",
|
|
1100
1352
|
{
|
|
1101
1353
|
type: "button",
|
|
@@ -1103,9 +1355,9 @@ function ConversationContextPanel({
|
|
|
1103
1355
|
"aria-expanded": open,
|
|
1104
1356
|
className: cn("flex w-full items-center gap-2 px-4 py-3 text-left text-sm font-medium", classNames?.toggle),
|
|
1105
1357
|
children: [
|
|
1106
|
-
/* @__PURE__ */
|
|
1107
|
-
/* @__PURE__ */
|
|
1108
|
-
/* @__PURE__ */
|
|
1358
|
+
/* @__PURE__ */ jsx13("span", { "aria-hidden": true, className: "text-xs", children: open ? "\u25BE" : "\u25B8" }),
|
|
1359
|
+
/* @__PURE__ */ jsx13("span", { children: labels.title }),
|
|
1360
|
+
/* @__PURE__ */ jsxs11("span", { className: cn("rounded-full bg-gray-200 px-2 text-xs dark:bg-gray-700", classNames?.counter), children: [
|
|
1109
1361
|
filled.length,
|
|
1110
1362
|
"/",
|
|
1111
1363
|
entries.length
|
|
@@ -1113,12 +1365,12 @@ function ConversationContextPanel({
|
|
|
1113
1365
|
]
|
|
1114
1366
|
}
|
|
1115
1367
|
),
|
|
1116
|
-
open ? /* @__PURE__ */
|
|
1117
|
-
/* @__PURE__ */
|
|
1368
|
+
open ? /* @__PURE__ */ jsx13("div", { className: cn("px-4 pb-3", classNames?.body), children: entries.length === 0 ? /* @__PURE__ */ jsx13("p", { className: "text-xs text-gray-500", children: labels.empty }) : /* @__PURE__ */ jsx13("dl", { className: "grid grid-cols-2 gap-2 text-xs", children: entries.map((entry) => /* @__PURE__ */ jsxs11("div", { className: "min-w-0", children: [
|
|
1369
|
+
/* @__PURE__ */ jsxs11("dt", { className: "truncate text-gray-500", children: [
|
|
1118
1370
|
entry.icon ? `${entry.icon} ` : "",
|
|
1119
1371
|
entry.label
|
|
1120
1372
|
] }),
|
|
1121
|
-
/* @__PURE__ */
|
|
1373
|
+
/* @__PURE__ */ jsx13("dd", { className: "truncate font-medium", children: entry.value ? /* @__PURE__ */ jsxs11("span", { className: "text-green-700 dark:text-green-400", children: [
|
|
1122
1374
|
"\u2713 ",
|
|
1123
1375
|
entry.value
|
|
1124
1376
|
] }) : "\u2014" })
|
|
@@ -1127,7 +1379,7 @@ function ConversationContextPanel({
|
|
|
1127
1379
|
}
|
|
1128
1380
|
|
|
1129
1381
|
// src/WindowExpiredNotice.tsx
|
|
1130
|
-
import { jsx as
|
|
1382
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1131
1383
|
var DEFAULT_WINDOW_EXPIRED_LABELS = {
|
|
1132
1384
|
title: "\u23F0 Janela de 24h expirada \u2014 o WhatsApp n\xE3o aceita mensagens livres.",
|
|
1133
1385
|
description: "Envie uma mensagem de template para reabrir a conversa com o cliente.",
|
|
@@ -1140,10 +1392,10 @@ function WindowExpiredNotice({
|
|
|
1140
1392
|
className
|
|
1141
1393
|
}) {
|
|
1142
1394
|
const labels = { ...DEFAULT_WINDOW_EXPIRED_LABELS, ...labelsOverride };
|
|
1143
|
-
return /* @__PURE__ */
|
|
1144
|
-
/* @__PURE__ */
|
|
1145
|
-
/* @__PURE__ */
|
|
1146
|
-
onSendTemplate ? /* @__PURE__ */
|
|
1395
|
+
return /* @__PURE__ */ jsxs12("div", { role: "status", className: cn("border-t bg-yellow-50 px-4 py-3 text-sm dark:bg-yellow-950", className), children: [
|
|
1396
|
+
/* @__PURE__ */ jsx14("p", { className: "font-medium text-yellow-900 dark:text-yellow-200", children: labels.title }),
|
|
1397
|
+
/* @__PURE__ */ jsx14("p", { className: "text-yellow-800 dark:text-yellow-300", children: labels.description }),
|
|
1398
|
+
onSendTemplate ? /* @__PURE__ */ jsx14("button", { type: "button", onClick: onSendTemplate, disabled, className: "cv-header-action mt-2", children: labels.sendTemplate }) : null
|
|
1147
1399
|
] });
|
|
1148
1400
|
}
|
|
1149
1401
|
function isWindowBlocking(window2) {
|
|
@@ -1186,7 +1438,7 @@ function downloadTextFile(filename, content) {
|
|
|
1186
1438
|
}
|
|
1187
1439
|
|
|
1188
1440
|
// src/useWaitingNotifications.ts
|
|
1189
|
-
import { useState as
|
|
1441
|
+
import { useState as useState8, useEffect as useEffect5, useRef as useRef4, useCallback as useCallback4 } from "react";
|
|
1190
1442
|
var DEFAULT_POLL_INTERVAL_MS = 1e4;
|
|
1191
1443
|
var DEFAULT_LIMIT = 50;
|
|
1192
1444
|
var DEFAULT_LABELS = {
|
|
@@ -1195,17 +1447,17 @@ var DEFAULT_LABELS = {
|
|
|
1195
1447
|
};
|
|
1196
1448
|
function useWaitingNotifications(params) {
|
|
1197
1449
|
const conversationsContext = useConversations();
|
|
1198
|
-
const [conversations, setConversations] =
|
|
1199
|
-
const previousUnreadMap =
|
|
1200
|
-
const notifiedIds =
|
|
1201
|
-
const isPollingRef =
|
|
1450
|
+
const [conversations, setConversations] = useState8([]);
|
|
1451
|
+
const previousUnreadMap = useRef4(/* @__PURE__ */ new Map());
|
|
1452
|
+
const notifiedIds = useRef4(/* @__PURE__ */ new Set());
|
|
1453
|
+
const isPollingRef = useRef4(false);
|
|
1202
1454
|
const isEnabled = params?.enabled ?? true;
|
|
1203
1455
|
const intervalMs = params?.intervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
1204
1456
|
const icon = params?.icon;
|
|
1205
1457
|
const listParams = params?.params;
|
|
1206
1458
|
const labelTitle = params?.labels?.title ?? DEFAULT_LABELS.title;
|
|
1207
1459
|
const labelBody = params?.labels?.body ?? DEFAULT_LABELS.body;
|
|
1208
|
-
const refresh =
|
|
1460
|
+
const refresh = useCallback4(async () => {
|
|
1209
1461
|
if (!conversationsContext || isPollingRef.current) return;
|
|
1210
1462
|
isPollingRef.current = true;
|
|
1211
1463
|
try {
|
|
@@ -1230,7 +1482,7 @@ function useWaitingNotifications(params) {
|
|
|
1230
1482
|
isPollingRef.current = false;
|
|
1231
1483
|
}
|
|
1232
1484
|
}, [conversationsContext, listParams, icon, labelTitle, labelBody]);
|
|
1233
|
-
|
|
1485
|
+
useEffect5(() => {
|
|
1234
1486
|
if (!isEnabled) return;
|
|
1235
1487
|
if (typeof window !== "undefined" && "Notification" in window && Notification.permission === "default") {
|
|
1236
1488
|
Notification.requestPermission();
|
|
@@ -1245,7 +1497,7 @@ function useWaitingNotifications(params) {
|
|
|
1245
1497
|
|
|
1246
1498
|
// src/settings/WhatsAppTemplateSettingsForm.tsx
|
|
1247
1499
|
import { Plus, RefreshCw, Save, Trash2 } from "lucide-react";
|
|
1248
|
-
import { jsx as
|
|
1500
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1249
1501
|
var DEFAULT_LABELS2 = {
|
|
1250
1502
|
sectionTitle: "WhatsApp",
|
|
1251
1503
|
sectionDescription: "Template usado para reabrir a janela de 24h com o cliente.",
|
|
@@ -1304,16 +1556,16 @@ function WhatsAppTemplateSettingsForm({
|
|
|
1304
1556
|
}
|
|
1305
1557
|
onVariablesChange([...variables, token]);
|
|
1306
1558
|
}
|
|
1307
|
-
return /* @__PURE__ */
|
|
1308
|
-
/* @__PURE__ */
|
|
1309
|
-
/* @__PURE__ */
|
|
1310
|
-
/* @__PURE__ */
|
|
1559
|
+
return /* @__PURE__ */ jsxs13("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
|
|
1560
|
+
/* @__PURE__ */ jsxs13("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: [
|
|
1561
|
+
/* @__PURE__ */ jsx15("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: labels.sectionTitle }),
|
|
1562
|
+
/* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: labels.sectionDescription })
|
|
1311
1563
|
] }),
|
|
1312
|
-
/* @__PURE__ */
|
|
1313
|
-
/* @__PURE__ */
|
|
1314
|
-
/* @__PURE__ */
|
|
1315
|
-
/* @__PURE__ */
|
|
1316
|
-
/* @__PURE__ */
|
|
1564
|
+
/* @__PURE__ */ jsxs13("form", { onSubmit: onSave, className: "p-6 space-y-4", children: [
|
|
1565
|
+
/* @__PURE__ */ jsxs13("div", { children: [
|
|
1566
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between mb-1.5", children: [
|
|
1567
|
+
/* @__PURE__ */ jsx15("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.templateLabel }),
|
|
1568
|
+
/* @__PURE__ */ jsxs13(
|
|
1317
1569
|
"button",
|
|
1318
1570
|
{
|
|
1319
1571
|
type: "button",
|
|
@@ -1321,31 +1573,31 @@ function WhatsAppTemplateSettingsForm({
|
|
|
1321
1573
|
disabled: loadingTemplates,
|
|
1322
1574
|
className: "flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400 hover:underline disabled:opacity-50",
|
|
1323
1575
|
children: [
|
|
1324
|
-
/* @__PURE__ */
|
|
1576
|
+
/* @__PURE__ */ jsx15(RefreshCw, { size: 11, className: loadingTemplates ? "animate-spin" : "" }),
|
|
1325
1577
|
labels.refreshList
|
|
1326
1578
|
]
|
|
1327
1579
|
}
|
|
1328
1580
|
)
|
|
1329
1581
|
] }),
|
|
1330
|
-
templatesError && /* @__PURE__ */
|
|
1582
|
+
templatesError && /* @__PURE__ */ jsxs13("div", { className: "mb-2 rounded-lg bg-amber-50 dark:bg-amber-950/40 border border-amber-200 dark:border-amber-800 px-3 py-2 text-xs text-amber-700 dark:text-amber-400", children: [
|
|
1331
1583
|
labels.errorLoading,
|
|
1332
|
-
/* @__PURE__ */
|
|
1333
|
-
/* @__PURE__ */
|
|
1584
|
+
/* @__PURE__ */ jsx15("br", {}),
|
|
1585
|
+
/* @__PURE__ */ jsxs13("span", { className: "text-gray-500 dark:text-gray-400 mt-0.5 block", children: [
|
|
1334
1586
|
labels.currentNameSaved,
|
|
1335
1587
|
" ",
|
|
1336
|
-
/* @__PURE__ */
|
|
1588
|
+
/* @__PURE__ */ jsx15("strong", { children: selectedTemplateName || "\u2014" })
|
|
1337
1589
|
] })
|
|
1338
1590
|
] }),
|
|
1339
|
-
loadingTemplates && /* @__PURE__ */
|
|
1340
|
-
!loadingTemplates && !templatesError && /* @__PURE__ */
|
|
1591
|
+
loadingTemplates && /* @__PURE__ */ jsx15("div", { className: "h-10 rounded-xl bg-gray-100 dark:bg-gray-700 animate-pulse" }),
|
|
1592
|
+
!loadingTemplates && !templatesError && /* @__PURE__ */ jsxs13(
|
|
1341
1593
|
"select",
|
|
1342
1594
|
{
|
|
1343
1595
|
value: selectedTemplateName,
|
|
1344
1596
|
onChange: (e) => handleSelect(e.target.value),
|
|
1345
1597
|
className: "w-full border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all",
|
|
1346
1598
|
children: [
|
|
1347
|
-
/* @__PURE__ */
|
|
1348
|
-
templates.map((template) => /* @__PURE__ */
|
|
1599
|
+
/* @__PURE__ */ jsx15("option", { value: "", children: labels.selectPlaceholder }),
|
|
1600
|
+
templates.map((template) => /* @__PURE__ */ jsxs13("option", { value: template.name, disabled: template.status !== "APPROVED", children: [
|
|
1349
1601
|
template.displayName,
|
|
1350
1602
|
" \xB7 ",
|
|
1351
1603
|
template.shortId,
|
|
@@ -1357,27 +1609,27 @@ function WhatsAppTemplateSettingsForm({
|
|
|
1357
1609
|
]
|
|
1358
1610
|
}
|
|
1359
1611
|
),
|
|
1360
|
-
selected?.bodyText && /* @__PURE__ */
|
|
1612
|
+
selected?.bodyText && /* @__PURE__ */ jsx15("div", { className: "mt-2 rounded-lg bg-gray-50 dark:bg-gray-700/50 border border-gray-200 dark:border-gray-600 px-3 py-2 text-xs text-gray-600 dark:text-gray-300 whitespace-pre-wrap", children: selected.bodyText })
|
|
1361
1613
|
] }),
|
|
1362
|
-
/* @__PURE__ */
|
|
1363
|
-
/* @__PURE__ */
|
|
1364
|
-
/* @__PURE__ */
|
|
1365
|
-
/* @__PURE__ */
|
|
1614
|
+
/* @__PURE__ */ jsxs13("div", { children: [
|
|
1615
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between mb-1.5", children: [
|
|
1616
|
+
/* @__PURE__ */ jsx15("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.variablesLabel }),
|
|
1617
|
+
/* @__PURE__ */ jsxs13(
|
|
1366
1618
|
"button",
|
|
1367
1619
|
{
|
|
1368
1620
|
type: "button",
|
|
1369
1621
|
onClick: () => onVariablesChange([...variables, ""]),
|
|
1370
1622
|
className: "flex items-center gap-1 text-xs text-blue-600 dark:text-blue-400 hover:underline",
|
|
1371
1623
|
children: [
|
|
1372
|
-
/* @__PURE__ */
|
|
1624
|
+
/* @__PURE__ */ jsx15(Plus, { size: 12 }),
|
|
1373
1625
|
labels.addVariable
|
|
1374
1626
|
]
|
|
1375
1627
|
}
|
|
1376
1628
|
)
|
|
1377
1629
|
] }),
|
|
1378
|
-
availableVariables.length > 0 && /* @__PURE__ */
|
|
1379
|
-
/* @__PURE__ */
|
|
1380
|
-
/* @__PURE__ */
|
|
1630
|
+
availableVariables.length > 0 && /* @__PURE__ */ jsxs13("div", { className: "mb-3 rounded-lg border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700/40 p-2.5", children: [
|
|
1631
|
+
/* @__PURE__ */ jsx15("p", { className: "text-xs font-medium text-gray-600 dark:text-gray-300 mb-1.5", children: labels.variablesAvailableTitle }),
|
|
1632
|
+
/* @__PURE__ */ jsx15("div", { className: "flex flex-wrap gap-1.5", children: availableVariables.map((available) => /* @__PURE__ */ jsxs13(
|
|
1381
1633
|
"button",
|
|
1382
1634
|
{
|
|
1383
1635
|
type: "button",
|
|
@@ -1385,8 +1637,8 @@ function WhatsAppTemplateSettingsForm({
|
|
|
1385
1637
|
title: `Inserir ${available.token}`,
|
|
1386
1638
|
className: "inline-flex items-center gap-1 rounded-md border border-gray-200 dark:border-gray-600 bg-white dark:bg-gray-800 px-2 py-1 text-xs hover:border-blue-400 dark:hover:border-blue-500 transition-colors",
|
|
1387
1639
|
children: [
|
|
1388
|
-
/* @__PURE__ */
|
|
1389
|
-
/* @__PURE__ */
|
|
1640
|
+
/* @__PURE__ */ jsx15("code", { className: "text-blue-600 dark:text-blue-300", children: available.token }),
|
|
1641
|
+
/* @__PURE__ */ jsxs13("span", { className: "text-gray-400 dark:text-gray-500", children: [
|
|
1390
1642
|
"\xB7 ",
|
|
1391
1643
|
available.label
|
|
1392
1644
|
] })
|
|
@@ -1394,13 +1646,13 @@ function WhatsAppTemplateSettingsForm({
|
|
|
1394
1646
|
},
|
|
1395
1647
|
available.token
|
|
1396
1648
|
)) }),
|
|
1397
|
-
/* @__PURE__ */
|
|
1649
|
+
/* @__PURE__ */ jsx15("p", { className: "mt-1.5 text-[11px] text-gray-400 dark:text-gray-500", children: labels.variablesAvailableHint })
|
|
1398
1650
|
] }),
|
|
1399
|
-
/* @__PURE__ */
|
|
1400
|
-
variables.length === 0 && /* @__PURE__ */
|
|
1401
|
-
/* @__PURE__ */
|
|
1402
|
-
/* @__PURE__ */
|
|
1403
|
-
/* @__PURE__ */
|
|
1651
|
+
/* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-400 dark:text-gray-500 mb-2", children: labels.variablesMappingHint }),
|
|
1652
|
+
variables.length === 0 && /* @__PURE__ */ jsx15("p", { className: "text-xs text-gray-400 dark:text-gray-500 italic", children: labels.noVariables }),
|
|
1653
|
+
/* @__PURE__ */ jsx15("div", { className: "space-y-2", children: variables.map((variable, index) => /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
|
|
1654
|
+
/* @__PURE__ */ jsx15("span", { className: "text-xs text-gray-400 dark:text-gray-500 w-6 text-right flex-shrink-0", children: `{{${index + 1}}}` }),
|
|
1655
|
+
/* @__PURE__ */ jsx15(
|
|
1404
1656
|
"input",
|
|
1405
1657
|
{
|
|
1406
1658
|
type: "text",
|
|
@@ -1410,27 +1662,27 @@ function WhatsAppTemplateSettingsForm({
|
|
|
1410
1662
|
className: "flex-1 border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-lg px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all placeholder:text-gray-400 dark:placeholder:text-gray-500"
|
|
1411
1663
|
}
|
|
1412
1664
|
),
|
|
1413
|
-
/* @__PURE__ */
|
|
1665
|
+
/* @__PURE__ */ jsx15(
|
|
1414
1666
|
"button",
|
|
1415
1667
|
{
|
|
1416
1668
|
type: "button",
|
|
1417
1669
|
onClick: () => removeVariable(index),
|
|
1418
1670
|
className: "text-gray-400 hover:text-red-500 dark:hover:text-red-400 transition-colors flex-shrink-0",
|
|
1419
1671
|
title: labels.removeVariable,
|
|
1420
|
-
children: /* @__PURE__ */
|
|
1672
|
+
children: /* @__PURE__ */ jsx15(Trash2, { size: 14 })
|
|
1421
1673
|
}
|
|
1422
1674
|
)
|
|
1423
1675
|
] }, index)) })
|
|
1424
1676
|
] }),
|
|
1425
|
-
saveSuccess && /* @__PURE__ */
|
|
1426
|
-
/* @__PURE__ */
|
|
1677
|
+
saveSuccess && /* @__PURE__ */ jsx15("div", { className: "bg-green-50 dark:bg-green-950/40 border border-green-200 dark:border-green-800 rounded-xl px-4 py-3 text-sm text-green-700 dark:text-green-400", children: labels.saveSuccess }),
|
|
1678
|
+
/* @__PURE__ */ jsx15("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs13(
|
|
1427
1679
|
"button",
|
|
1428
1680
|
{
|
|
1429
1681
|
type: "submit",
|
|
1430
1682
|
disabled: saving || !selectedTemplateName.trim(),
|
|
1431
1683
|
className: "flex items-center gap-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-semibold px-5 py-2.5 rounded-xl transition-colors text-sm",
|
|
1432
1684
|
children: [
|
|
1433
|
-
saving ? /* @__PURE__ */
|
|
1685
|
+
saving ? /* @__PURE__ */ jsx15("span", { className: "w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" }) : /* @__PURE__ */ jsx15(Save, { size: 14 }),
|
|
1434
1686
|
saving ? labels.saving : labels.save
|
|
1435
1687
|
]
|
|
1436
1688
|
}
|
|
@@ -1440,8 +1692,8 @@ function WhatsAppTemplateSettingsForm({
|
|
|
1440
1692
|
}
|
|
1441
1693
|
|
|
1442
1694
|
// src/settings/WhatsAppCreateTemplateForm.tsx
|
|
1443
|
-
import { SendHorizonal } from "lucide-react";
|
|
1444
|
-
import { jsx as
|
|
1695
|
+
import { SendHorizonal as SendHorizonal2 } from "lucide-react";
|
|
1696
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1445
1697
|
var DEFAULT_LABELS3 = {
|
|
1446
1698
|
sectionTitle: "Criar novo template",
|
|
1447
1699
|
sectionDescription: "Envia um template para aprova\xE7\xE3o da Meta.",
|
|
@@ -1498,16 +1750,16 @@ function WhatsAppCreateTemplateForm({
|
|
|
1498
1750
|
function set(key, next) {
|
|
1499
1751
|
onChange({ ...value, [key]: next });
|
|
1500
1752
|
}
|
|
1501
|
-
return /* @__PURE__ */
|
|
1502
|
-
/* @__PURE__ */
|
|
1503
|
-
/* @__PURE__ */
|
|
1504
|
-
/* @__PURE__ */
|
|
1753
|
+
return /* @__PURE__ */ jsxs14("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
|
|
1754
|
+
/* @__PURE__ */ jsxs14("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: [
|
|
1755
|
+
/* @__PURE__ */ jsx16("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: labels.sectionTitle }),
|
|
1756
|
+
/* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: labels.sectionDescription })
|
|
1505
1757
|
] }),
|
|
1506
|
-
/* @__PURE__ */
|
|
1507
|
-
/* @__PURE__ */
|
|
1508
|
-
/* @__PURE__ */
|
|
1509
|
-
/* @__PURE__ */
|
|
1510
|
-
/* @__PURE__ */
|
|
1758
|
+
/* @__PURE__ */ jsxs14("form", { onSubmit, className: "p-6 space-y-4", children: [
|
|
1759
|
+
/* @__PURE__ */ jsxs14("div", { children: [
|
|
1760
|
+
/* @__PURE__ */ jsx16("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.nameLabel }),
|
|
1761
|
+
/* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.nameHint }),
|
|
1762
|
+
/* @__PURE__ */ jsx16(
|
|
1511
1763
|
"input",
|
|
1512
1764
|
{
|
|
1513
1765
|
type: "text",
|
|
@@ -1519,56 +1771,56 @@ function WhatsAppCreateTemplateForm({
|
|
|
1519
1771
|
}
|
|
1520
1772
|
)
|
|
1521
1773
|
] }),
|
|
1522
|
-
/* @__PURE__ */
|
|
1523
|
-
/* @__PURE__ */
|
|
1524
|
-
/* @__PURE__ */
|
|
1525
|
-
/* @__PURE__ */
|
|
1774
|
+
/* @__PURE__ */ jsxs14("div", { className: "grid grid-cols-2 gap-3", children: [
|
|
1775
|
+
/* @__PURE__ */ jsxs14("div", { children: [
|
|
1776
|
+
/* @__PURE__ */ jsx16("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.categoryLabel }),
|
|
1777
|
+
/* @__PURE__ */ jsxs14(
|
|
1526
1778
|
"select",
|
|
1527
1779
|
{
|
|
1528
1780
|
value: value.category,
|
|
1529
1781
|
onChange: (e) => set("category", e.target.value),
|
|
1530
1782
|
className: "w-full border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all",
|
|
1531
1783
|
children: [
|
|
1532
|
-
/* @__PURE__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
1784
|
+
/* @__PURE__ */ jsx16("option", { value: "UTILITY", children: "UTILITY (Transacional)" }),
|
|
1785
|
+
/* @__PURE__ */ jsx16("option", { value: "MARKETING", children: "MARKETING (Promocional)" })
|
|
1534
1786
|
]
|
|
1535
1787
|
}
|
|
1536
1788
|
)
|
|
1537
1789
|
] }),
|
|
1538
|
-
/* @__PURE__ */
|
|
1539
|
-
/* @__PURE__ */
|
|
1540
|
-
/* @__PURE__ */
|
|
1790
|
+
/* @__PURE__ */ jsxs14("div", { children: [
|
|
1791
|
+
/* @__PURE__ */ jsx16("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.languageLabel }),
|
|
1792
|
+
/* @__PURE__ */ jsxs14(
|
|
1541
1793
|
"select",
|
|
1542
1794
|
{
|
|
1543
1795
|
value: value.language,
|
|
1544
1796
|
onChange: (e) => set("language", e.target.value),
|
|
1545
1797
|
className: "w-full border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 focus:border-transparent transition-all",
|
|
1546
1798
|
children: [
|
|
1547
|
-
/* @__PURE__ */
|
|
1548
|
-
/* @__PURE__ */
|
|
1549
|
-
/* @__PURE__ */
|
|
1799
|
+
/* @__PURE__ */ jsx16("option", { value: "pt_BR", children: "Portugu\xEAs (Brasil)" }),
|
|
1800
|
+
/* @__PURE__ */ jsx16("option", { value: "en_US", children: "Ingl\xEAs (EUA)" }),
|
|
1801
|
+
/* @__PURE__ */ jsx16("option", { value: "es_ES", children: "Espanhol" })
|
|
1550
1802
|
]
|
|
1551
1803
|
}
|
|
1552
1804
|
)
|
|
1553
1805
|
] })
|
|
1554
1806
|
] }),
|
|
1555
|
-
/* @__PURE__ */
|
|
1556
|
-
/* @__PURE__ */
|
|
1557
|
-
/* @__PURE__ */
|
|
1558
|
-
/* @__PURE__ */
|
|
1559
|
-
/* @__PURE__ */
|
|
1807
|
+
/* @__PURE__ */ jsxs14("div", { children: [
|
|
1808
|
+
/* @__PURE__ */ jsx16("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.headerLabel }),
|
|
1809
|
+
/* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.headerHint }),
|
|
1810
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex gap-2", children: [
|
|
1811
|
+
/* @__PURE__ */ jsxs14(
|
|
1560
1812
|
"select",
|
|
1561
1813
|
{
|
|
1562
1814
|
value: value.headerType,
|
|
1563
1815
|
onChange: (e) => set("headerType", e.target.value),
|
|
1564
1816
|
className: "border border-gray-200 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100 rounded-xl px-3 py-2.5 text-sm focus:outline-none focus:ring-2 focus:ring-blue-400 transition-all",
|
|
1565
1817
|
children: [
|
|
1566
|
-
/* @__PURE__ */
|
|
1567
|
-
/* @__PURE__ */
|
|
1818
|
+
/* @__PURE__ */ jsx16("option", { value: "NONE", children: labels.headerNone }),
|
|
1819
|
+
/* @__PURE__ */ jsx16("option", { value: "TEXT", children: labels.headerText })
|
|
1568
1820
|
]
|
|
1569
1821
|
}
|
|
1570
1822
|
),
|
|
1571
|
-
value.headerType === "TEXT" && /* @__PURE__ */
|
|
1823
|
+
value.headerType === "TEXT" && /* @__PURE__ */ jsx16(
|
|
1572
1824
|
"input",
|
|
1573
1825
|
{
|
|
1574
1826
|
type: "text",
|
|
@@ -1581,10 +1833,10 @@ function WhatsAppCreateTemplateForm({
|
|
|
1581
1833
|
)
|
|
1582
1834
|
] })
|
|
1583
1835
|
] }),
|
|
1584
|
-
/* @__PURE__ */
|
|
1585
|
-
/* @__PURE__ */
|
|
1586
|
-
/* @__PURE__ */
|
|
1587
|
-
/* @__PURE__ */
|
|
1836
|
+
/* @__PURE__ */ jsxs14("div", { children: [
|
|
1837
|
+
/* @__PURE__ */ jsx16("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.bodyLabel }),
|
|
1838
|
+
/* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.bodyHint }),
|
|
1839
|
+
/* @__PURE__ */ jsx16(
|
|
1588
1840
|
"textarea",
|
|
1589
1841
|
{
|
|
1590
1842
|
value: value.bodyText,
|
|
@@ -1595,26 +1847,26 @@ function WhatsAppCreateTemplateForm({
|
|
|
1595
1847
|
required: true
|
|
1596
1848
|
}
|
|
1597
1849
|
),
|
|
1598
|
-
detectedVariables.length > 0 && /* @__PURE__ */
|
|
1599
|
-
/* @__PURE__ */
|
|
1600
|
-
/* @__PURE__ */
|
|
1601
|
-
/* @__PURE__ */
|
|
1602
|
-
/* @__PURE__ */
|
|
1850
|
+
detectedVariables.length > 0 && /* @__PURE__ */ jsxs14("div", { className: "mt-2 rounded-lg bg-gray-50 dark:bg-gray-700/50 border border-gray-200 dark:border-gray-600 px-3 py-2", children: [
|
|
1851
|
+
/* @__PURE__ */ jsx16("p", { className: "font-medium text-gray-500 dark:text-gray-400 mb-1.5 uppercase tracking-wide text-xs", children: labels.detectedVariables }),
|
|
1852
|
+
/* @__PURE__ */ jsx16("div", { className: "flex flex-wrap gap-2", children: detectedVariables.map((num) => /* @__PURE__ */ jsxs14("span", { className: "inline-flex items-center gap-1 text-xs", children: [
|
|
1853
|
+
/* @__PURE__ */ jsx16("code", { className: "bg-blue-100 dark:bg-blue-900/40 text-blue-700 dark:text-blue-300 px-1.5 py-0.5 rounded font-mono", children: `{{${num}}}` }),
|
|
1854
|
+
/* @__PURE__ */ jsxs14("span", { className: "text-gray-400 dark:text-gray-500", children: [
|
|
1603
1855
|
"= ",
|
|
1604
1856
|
variableExamples[Number(num) - 1] ?? labels.variableLabel(Number(num))
|
|
1605
1857
|
] })
|
|
1606
1858
|
] }, num)) }),
|
|
1607
|
-
/* @__PURE__ */
|
|
1859
|
+
/* @__PURE__ */ jsxs14("p", { className: "text-gray-400 dark:text-gray-500 mt-1.5 text-xs", children: [
|
|
1608
1860
|
labels.configureHintPrefix,
|
|
1609
|
-
/* @__PURE__ */
|
|
1861
|
+
/* @__PURE__ */ jsx16("strong", { children: labels.configureHintLink }),
|
|
1610
1862
|
labels.configureHintSuffix
|
|
1611
1863
|
] })
|
|
1612
1864
|
] })
|
|
1613
1865
|
] }),
|
|
1614
|
-
/* @__PURE__ */
|
|
1615
|
-
/* @__PURE__ */
|
|
1616
|
-
/* @__PURE__ */
|
|
1617
|
-
/* @__PURE__ */
|
|
1866
|
+
/* @__PURE__ */ jsxs14("div", { children: [
|
|
1867
|
+
/* @__PURE__ */ jsx16("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: labels.footerLabel }),
|
|
1868
|
+
/* @__PURE__ */ jsx16("p", { className: "text-xs text-gray-400 mb-1.5", children: labels.footerHint }),
|
|
1869
|
+
/* @__PURE__ */ jsx16(
|
|
1618
1870
|
"input",
|
|
1619
1871
|
{
|
|
1620
1872
|
type: "text",
|
|
@@ -1626,48 +1878,48 @@ function WhatsAppCreateTemplateForm({
|
|
|
1626
1878
|
}
|
|
1627
1879
|
)
|
|
1628
1880
|
] }),
|
|
1629
|
-
/* @__PURE__ */
|
|
1630
|
-
/* @__PURE__ */
|
|
1631
|
-
/* @__PURE__ */
|
|
1632
|
-
/* @__PURE__ */
|
|
1633
|
-
/* @__PURE__ */
|
|
1634
|
-
/* @__PURE__ */
|
|
1635
|
-
/* @__PURE__ */
|
|
1636
|
-
/* @__PURE__ */
|
|
1881
|
+
/* @__PURE__ */ jsxs14("div", { children: [
|
|
1882
|
+
/* @__PURE__ */ jsx16("label", { className: "text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 block", children: labels.previewLabel }),
|
|
1883
|
+
/* @__PURE__ */ jsxs14("div", { className: "rounded-2xl bg-[#e5ddd5] dark:bg-[#1a1a2e] border border-gray-300 dark:border-gray-600 overflow-hidden shadow-inner", children: [
|
|
1884
|
+
/* @__PURE__ */ jsxs14("div", { className: "bg-[#075e54] px-4 py-2.5 flex items-center gap-2", children: [
|
|
1885
|
+
/* @__PURE__ */ jsx16("div", { className: "w-8 h-8 rounded-full bg-white/20 flex items-center justify-center text-white text-xs font-bold", children: previewCompanyName.slice(0, 2).toUpperCase() }),
|
|
1886
|
+
/* @__PURE__ */ jsxs14("div", { children: [
|
|
1887
|
+
/* @__PURE__ */ jsx16("p", { className: "text-white text-xs font-semibold leading-tight", children: previewCompanyName }),
|
|
1888
|
+
/* @__PURE__ */ jsx16("p", { className: "text-white/60 text-xs", children: labels.previewOnline })
|
|
1637
1889
|
] })
|
|
1638
1890
|
] }),
|
|
1639
|
-
/* @__PURE__ */
|
|
1640
|
-
/* @__PURE__ */
|
|
1641
|
-
/* @__PURE__ */
|
|
1642
|
-
/* @__PURE__ */
|
|
1891
|
+
/* @__PURE__ */ jsxs14("div", { className: "px-3 py-4 space-y-3", style: { minHeight: "120px" }, children: [
|
|
1892
|
+
/* @__PURE__ */ jsx16("div", { className: "flex justify-start", style: { maxWidth: "85%" }, children: /* @__PURE__ */ jsxs14("div", { className: "bg-white dark:bg-gray-700 rounded-lg rounded-tl-none px-3 py-2 shadow-sm", children: [
|
|
1893
|
+
/* @__PURE__ */ jsx16("p", { className: "text-gray-500 dark:text-gray-400 leading-tight text-sm", children: labels.previewDescription }),
|
|
1894
|
+
/* @__PURE__ */ jsx16("p", { className: "text-gray-400 dark:text-gray-500 mt-1 text-right text-[9px]", children: "12:00" })
|
|
1643
1895
|
] }) }),
|
|
1644
|
-
/* @__PURE__ */
|
|
1645
|
-
value.headerType === "TEXT" && value.headerText && /* @__PURE__ */
|
|
1646
|
-
/* @__PURE__ */
|
|
1647
|
-
value.footerText && /* @__PURE__ */
|
|
1648
|
-
/* @__PURE__ */
|
|
1896
|
+
/* @__PURE__ */ jsx16("div", { className: "flex justify-end ml-auto", style: { maxWidth: "85%" }, children: /* @__PURE__ */ jsxs14("div", { className: "bg-[#dcf8c6] dark:bg-[#1b5e20] rounded-lg rounded-tr-none px-3 py-2 shadow-sm", children: [
|
|
1897
|
+
value.headerType === "TEXT" && value.headerText && /* @__PURE__ */ jsx16("p", { className: "text-xs font-bold text-gray-700 dark:text-gray-200 mb-1", children: fillPreviewTokens(value.headerText) || labels.previewHeaderFallback }),
|
|
1898
|
+
/* @__PURE__ */ jsx16("p", { className: "text-sm text-gray-800 dark:text-gray-100 leading-relaxed", children: value.bodyText ? fillPreviewTokens(value.bodyText) : /* @__PURE__ */ jsx16("span", { className: "text-gray-400 italic", children: labels.previewBodyPlaceholder }) }),
|
|
1899
|
+
value.footerText && /* @__PURE__ */ jsx16("p", { className: "text-gray-400 dark:text-gray-400 mt-1 text-xs", children: value.footerText }),
|
|
1900
|
+
/* @__PURE__ */ jsx16("p", { className: "text-gray-400 dark:text-gray-400 mt-1 text-right text-[9px]", children: "12:01 \u2713" })
|
|
1649
1901
|
] }) })
|
|
1650
1902
|
] })
|
|
1651
1903
|
] })
|
|
1652
1904
|
] }),
|
|
1653
|
-
result && /* @__PURE__ */
|
|
1905
|
+
result && /* @__PURE__ */ jsxs14(
|
|
1654
1906
|
"div",
|
|
1655
1907
|
{
|
|
1656
1908
|
className: `rounded-xl px-4 py-3 text-sm ${result.ok ? "bg-green-50 dark:bg-green-950/40 border border-green-200 dark:border-green-800 text-green-700 dark:text-green-400" : "bg-red-50 dark:bg-red-950/40 border border-red-200 dark:border-red-800 text-red-700 dark:text-red-400"}`,
|
|
1657
1909
|
children: [
|
|
1658
1910
|
result.message,
|
|
1659
|
-
result.ok && result.status && /* @__PURE__ */
|
|
1911
|
+
result.ok && result.status && /* @__PURE__ */ jsx16("p", { className: "text-xs mt-1 opacity-75", children: labels.successStatus(result.status) })
|
|
1660
1912
|
]
|
|
1661
1913
|
}
|
|
1662
1914
|
),
|
|
1663
|
-
/* @__PURE__ */
|
|
1915
|
+
/* @__PURE__ */ jsx16("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs14(
|
|
1664
1916
|
"button",
|
|
1665
1917
|
{
|
|
1666
1918
|
type: "submit",
|
|
1667
1919
|
disabled: submitting || !value.name || !value.bodyText,
|
|
1668
1920
|
className: "flex items-center gap-2 bg-emerald-600 hover:bg-emerald-700 disabled:bg-emerald-400 text-white font-semibold px-5 py-2.5 rounded-xl transition-colors text-sm",
|
|
1669
1921
|
children: [
|
|
1670
|
-
submitting ? /* @__PURE__ */
|
|
1922
|
+
submitting ? /* @__PURE__ */ jsx16("span", { className: "w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" }) : /* @__PURE__ */ jsx16(SendHorizonal2, { size: 14 }),
|
|
1671
1923
|
submitting ? labels.sending : labels.sendForApproval
|
|
1672
1924
|
]
|
|
1673
1925
|
}
|
|
@@ -1678,7 +1930,7 @@ function WhatsAppCreateTemplateForm({
|
|
|
1678
1930
|
|
|
1679
1931
|
// src/settings/WelcomeFarewellForm.tsx
|
|
1680
1932
|
import { LogOut, Mail, Save as Save2 } from "lucide-react";
|
|
1681
|
-
import { jsx as
|
|
1933
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1682
1934
|
var DEFAULT_LABELS4 = {
|
|
1683
1935
|
sectionTitle: "Boas-vindas e encerramento",
|
|
1684
1936
|
welcomeMessage: "Mensagem de boas-vindas",
|
|
@@ -1706,15 +1958,15 @@ function WelcomeFarewellForm({
|
|
|
1706
1958
|
labels: labelsOverride
|
|
1707
1959
|
}) {
|
|
1708
1960
|
const labels = { ...DEFAULT_LABELS4, ...labelsOverride };
|
|
1709
|
-
return /* @__PURE__ */
|
|
1710
|
-
/* @__PURE__ */
|
|
1711
|
-
/* @__PURE__ */
|
|
1712
|
-
/* @__PURE__ */
|
|
1713
|
-
/* @__PURE__ */
|
|
1714
|
-
/* @__PURE__ */
|
|
1961
|
+
return /* @__PURE__ */ jsxs15("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
|
|
1962
|
+
/* @__PURE__ */ jsx17("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: /* @__PURE__ */ jsx17("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: labels.sectionTitle }) }),
|
|
1963
|
+
/* @__PURE__ */ jsxs15("form", { onSubmit: onSave, className: "p-6 space-y-5", children: [
|
|
1964
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
1965
|
+
/* @__PURE__ */ jsxs15("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5 flex items-center gap-1.5", children: [
|
|
1966
|
+
/* @__PURE__ */ jsx17(Mail, { size: 13, className: "text-blue-600 dark:text-blue-400" }),
|
|
1715
1967
|
labels.welcomeMessage
|
|
1716
1968
|
] }),
|
|
1717
|
-
/* @__PURE__ */
|
|
1969
|
+
/* @__PURE__ */ jsx17(
|
|
1718
1970
|
WhatsAppMessageEditor,
|
|
1719
1971
|
{
|
|
1720
1972
|
value: welcomeMessage,
|
|
@@ -1723,14 +1975,14 @@ function WelcomeFarewellForm({
|
|
|
1723
1975
|
placeholders: welcomePlaceholders
|
|
1724
1976
|
}
|
|
1725
1977
|
),
|
|
1726
|
-
/* @__PURE__ */
|
|
1978
|
+
/* @__PURE__ */ jsx17("p", { className: "mt-1.5 text-xs text-gray-500 dark:text-gray-400", children: labels.welcomeMessageHint })
|
|
1727
1979
|
] }),
|
|
1728
|
-
/* @__PURE__ */
|
|
1729
|
-
/* @__PURE__ */
|
|
1730
|
-
/* @__PURE__ */
|
|
1980
|
+
/* @__PURE__ */ jsxs15("div", { children: [
|
|
1981
|
+
/* @__PURE__ */ jsxs15("label", { className: "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5 flex items-center gap-1.5", children: [
|
|
1982
|
+
/* @__PURE__ */ jsx17(LogOut, { size: 13, className: "text-blue-600 dark:text-blue-400" }),
|
|
1731
1983
|
labels.farewellMessage
|
|
1732
1984
|
] }),
|
|
1733
|
-
/* @__PURE__ */
|
|
1985
|
+
/* @__PURE__ */ jsx17(
|
|
1734
1986
|
WhatsAppMessageEditor,
|
|
1735
1987
|
{
|
|
1736
1988
|
value: farewellMessage,
|
|
@@ -1739,17 +1991,17 @@ function WelcomeFarewellForm({
|
|
|
1739
1991
|
placeholders: farewellPlaceholders
|
|
1740
1992
|
}
|
|
1741
1993
|
),
|
|
1742
|
-
/* @__PURE__ */
|
|
1994
|
+
/* @__PURE__ */ jsx17("p", { className: "mt-1.5 text-xs text-gray-500 dark:text-gray-400", children: labels.farewellMessageHint })
|
|
1743
1995
|
] }),
|
|
1744
|
-
saveSuccess && /* @__PURE__ */
|
|
1745
|
-
/* @__PURE__ */
|
|
1996
|
+
saveSuccess && /* @__PURE__ */ jsx17("div", { className: "bg-green-50 dark:bg-green-950/40 border border-green-200 dark:border-green-800 rounded-xl px-4 py-3 text-sm text-green-700 dark:text-green-400", children: labels.saveSuccess }),
|
|
1997
|
+
/* @__PURE__ */ jsx17("div", { className: "flex justify-end", children: /* @__PURE__ */ jsxs15(
|
|
1746
1998
|
"button",
|
|
1747
1999
|
{
|
|
1748
2000
|
type: "submit",
|
|
1749
2001
|
disabled: saving,
|
|
1750
2002
|
className: "flex items-center gap-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white font-semibold px-5 py-2.5 rounded-xl transition-colors text-sm",
|
|
1751
2003
|
children: [
|
|
1752
|
-
saving ? /* @__PURE__ */
|
|
2004
|
+
saving ? /* @__PURE__ */ jsx17("span", { className: "w-4 h-4 border-2 border-white/40 border-t-white rounded-full animate-spin" }) : /* @__PURE__ */ jsx17(Save2, { size: 14 }),
|
|
1753
2005
|
saving ? labels.saving : labels.save
|
|
1754
2006
|
]
|
|
1755
2007
|
}
|
|
@@ -1759,8 +2011,8 @@ function WelcomeFarewellForm({
|
|
|
1759
2011
|
}
|
|
1760
2012
|
|
|
1761
2013
|
// src/settings/WhatsAppTemplatesSettings.tsx
|
|
1762
|
-
import { useState as
|
|
1763
|
-
import { jsx as
|
|
2014
|
+
import { useState as useState9 } from "react";
|
|
2015
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1764
2016
|
var TEMPLATE_SETTINGS_TAB = {
|
|
1765
2017
|
SELECT: "select",
|
|
1766
2018
|
CREATE: "create"
|
|
@@ -1775,10 +2027,10 @@ function WhatsAppTemplatesSettings({
|
|
|
1775
2027
|
...settingsProps
|
|
1776
2028
|
}) {
|
|
1777
2029
|
const labels = { ...DEFAULT_TEMPLATES_SETTINGS_LABELS, ...labelsOverride };
|
|
1778
|
-
const [tab, setTab] =
|
|
1779
|
-
return /* @__PURE__ */
|
|
1780
|
-
/* @__PURE__ */
|
|
1781
|
-
/* @__PURE__ */
|
|
2030
|
+
const [tab, setTab] = useState9(TEMPLATE_SETTINGS_TAB.SELECT);
|
|
2031
|
+
return /* @__PURE__ */ jsxs16("div", { className: "space-y-4", children: [
|
|
2032
|
+
/* @__PURE__ */ jsxs16("nav", { className: "flex gap-1 border-b", role: "tablist", children: [
|
|
2033
|
+
/* @__PURE__ */ jsx18(
|
|
1782
2034
|
"button",
|
|
1783
2035
|
{
|
|
1784
2036
|
type: "button",
|
|
@@ -1789,7 +2041,7 @@ function WhatsAppTemplatesSettings({
|
|
|
1789
2041
|
children: labels.selectTab
|
|
1790
2042
|
}
|
|
1791
2043
|
),
|
|
1792
|
-
create ? /* @__PURE__ */
|
|
2044
|
+
create ? /* @__PURE__ */ jsx18(
|
|
1793
2045
|
"button",
|
|
1794
2046
|
{
|
|
1795
2047
|
type: "button",
|
|
@@ -1801,13 +2053,13 @@ function WhatsAppTemplatesSettings({
|
|
|
1801
2053
|
}
|
|
1802
2054
|
) : null
|
|
1803
2055
|
] }),
|
|
1804
|
-
tab === TEMPLATE_SETTINGS_TAB.SELECT ? /* @__PURE__ */
|
|
2056
|
+
tab === TEMPLATE_SETTINGS_TAB.SELECT ? /* @__PURE__ */ jsx18(WhatsAppTemplateSettingsForm, { ...settingsProps }) : create ? /* @__PURE__ */ jsx18(WhatsAppCreateTemplateForm, { ...create }) : null
|
|
1805
2057
|
] });
|
|
1806
2058
|
}
|
|
1807
2059
|
|
|
1808
2060
|
// src/settings/TopicsForm.tsx
|
|
1809
2061
|
import { Megaphone, Save as Save3 } from "lucide-react";
|
|
1810
|
-
import { jsx as
|
|
2062
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1811
2063
|
var DEFAULT_LABELS5 = {
|
|
1812
2064
|
sectionTitle: "T\xF3picos intermedi\xE1rios",
|
|
1813
2065
|
sectionDescription: "Mensagens autom\xE1ticas para assuntos espec\xEDficos, disparadas quando o cliente demonstra interesse.",
|
|
@@ -1825,19 +2077,19 @@ function TopicsForm({
|
|
|
1825
2077
|
labels: labelsOverride
|
|
1826
2078
|
}) {
|
|
1827
2079
|
const labels = { ...DEFAULT_LABELS5, ...labelsOverride };
|
|
1828
|
-
return /* @__PURE__ */
|
|
1829
|
-
/* @__PURE__ */
|
|
1830
|
-
/* @__PURE__ */
|
|
1831
|
-
/* @__PURE__ */
|
|
2080
|
+
return /* @__PURE__ */ jsxs17("section", { className: "bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 overflow-hidden", children: [
|
|
2081
|
+
/* @__PURE__ */ jsxs17("div", { className: "px-6 py-4 border-b border-gray-100 dark:border-gray-700", children: [
|
|
2082
|
+
/* @__PURE__ */ jsxs17("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100 flex items-center gap-2", children: [
|
|
2083
|
+
/* @__PURE__ */ jsx19(Megaphone, { size: 16, className: "text-orange-600 dark:text-orange-400" }),
|
|
1832
2084
|
labels.sectionTitle
|
|
1833
2085
|
] }),
|
|
1834
|
-
/* @__PURE__ */
|
|
2086
|
+
/* @__PURE__ */ jsx19("p", { className: "text-xs text-gray-500 dark:text-gray-400 mt-1", children: labels.sectionDescription })
|
|
1835
2087
|
] }),
|
|
1836
|
-
/* @__PURE__ */
|
|
1837
|
-
topics.map((topic) => /* @__PURE__ */
|
|
1838
|
-
/* @__PURE__ */
|
|
1839
|
-
/* @__PURE__ */
|
|
1840
|
-
/* @__PURE__ */
|
|
2088
|
+
/* @__PURE__ */ jsxs17("form", { onSubmit: onSave, className: "p-6 space-y-6", children: [
|
|
2089
|
+
topics.map((topic) => /* @__PURE__ */ jsxs17("div", { className: "space-y-2", children: [
|
|
2090
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-start gap-4", children: [
|
|
2091
|
+
/* @__PURE__ */ jsx19("div", { className: "flex-1", children: /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: topic.label }) }),
|
|
2092
|
+
/* @__PURE__ */ jsx19(
|
|
1841
2093
|
"button",
|
|
1842
2094
|
{
|
|
1843
2095
|
type: "button",
|
|
@@ -1845,7 +2097,7 @@ function TopicsForm({
|
|
|
1845
2097
|
className: `relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${topic.enabled ? "bg-blue-600 dark:bg-blue-500" : "bg-gray-200 dark:bg-gray-700"}`,
|
|
1846
2098
|
role: "switch",
|
|
1847
2099
|
"aria-checked": topic.enabled,
|
|
1848
|
-
children: /* @__PURE__ */
|
|
2100
|
+
children: /* @__PURE__ */ jsx19(
|
|
1849
2101
|
"span",
|
|
1850
2102
|
{
|
|
1851
2103
|
className: `pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${topic.enabled ? "translate-x-5" : "translate-x-0"}`
|
|
@@ -1854,7 +2106,7 @@ function TopicsForm({
|
|
|
1854
2106
|
}
|
|
1855
2107
|
)
|
|
1856
2108
|
] }),
|
|
1857
|
-
/* @__PURE__ */
|
|
2109
|
+
/* @__PURE__ */ jsx19(
|
|
1858
2110
|
"textarea",
|
|
1859
2111
|
{
|
|
1860
2112
|
value: topic.message,
|
|
@@ -1866,27 +2118,27 @@ function TopicsForm({
|
|
|
1866
2118
|
}
|
|
1867
2119
|
)
|
|
1868
2120
|
] }, topic.key)),
|
|
1869
|
-
/* @__PURE__ */
|
|
1870
|
-
/* @__PURE__ */
|
|
2121
|
+
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-3", children: [
|
|
2122
|
+
/* @__PURE__ */ jsxs17(
|
|
1871
2123
|
"button",
|
|
1872
2124
|
{
|
|
1873
2125
|
type: "submit",
|
|
1874
2126
|
disabled: saving,
|
|
1875
2127
|
className: "inline-flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:opacity-50",
|
|
1876
2128
|
children: [
|
|
1877
|
-
/* @__PURE__ */
|
|
2129
|
+
/* @__PURE__ */ jsx19(Save3, { size: 14 }),
|
|
1878
2130
|
labels.saveButton
|
|
1879
2131
|
]
|
|
1880
2132
|
}
|
|
1881
2133
|
),
|
|
1882
|
-
saveSuccess && /* @__PURE__ */
|
|
2134
|
+
saveSuccess && /* @__PURE__ */ jsx19("span", { className: "text-sm text-green-600 dark:text-green-400", children: labels.saveSuccess })
|
|
1883
2135
|
] })
|
|
1884
2136
|
] })
|
|
1885
2137
|
] });
|
|
1886
2138
|
}
|
|
1887
2139
|
|
|
1888
2140
|
// src/hooks/useConversationMessages.ts
|
|
1889
|
-
import { useCallback as
|
|
2141
|
+
import { useCallback as useCallback5 } from "react";
|
|
1890
2142
|
function useConversationMessages(conversationId, params) {
|
|
1891
2143
|
const context = useConversations();
|
|
1892
2144
|
if (!context) {
|
|
@@ -1897,7 +2149,7 @@ function useConversationMessages(conversationId, params) {
|
|
|
1897
2149
|
() => api.fetchMessages(conversationId, params),
|
|
1898
2150
|
[conversationId, params?.limit, params?.before]
|
|
1899
2151
|
);
|
|
1900
|
-
const sendMessage =
|
|
2152
|
+
const sendMessage = useCallback5(
|
|
1901
2153
|
async (text) => {
|
|
1902
2154
|
const message = await api.sendMessage(conversationId, text);
|
|
1903
2155
|
await refetch();
|
|
@@ -1905,7 +2157,7 @@ function useConversationMessages(conversationId, params) {
|
|
|
1905
2157
|
},
|
|
1906
2158
|
[api, conversationId, refetch]
|
|
1907
2159
|
);
|
|
1908
|
-
const sendMedia =
|
|
2160
|
+
const sendMedia = useCallback5(
|
|
1909
2161
|
async (mediaData) => {
|
|
1910
2162
|
const message = await api.sendMedia(conversationId, mediaData);
|
|
1911
2163
|
await refetch();
|
|
@@ -1913,14 +2165,14 @@ function useConversationMessages(conversationId, params) {
|
|
|
1913
2165
|
},
|
|
1914
2166
|
[api, conversationId, refetch]
|
|
1915
2167
|
);
|
|
1916
|
-
const sendTemplate =
|
|
2168
|
+
const sendTemplate = useCallback5(
|
|
1917
2169
|
async (templateData) => {
|
|
1918
2170
|
await api.sendTemplate(conversationId, templateData);
|
|
1919
2171
|
await refetch();
|
|
1920
2172
|
},
|
|
1921
2173
|
[api, conversationId, refetch]
|
|
1922
2174
|
);
|
|
1923
|
-
const markRead =
|
|
2175
|
+
const markRead = useCallback5(() => api.markRead(conversationId), [api, conversationId]);
|
|
1924
2176
|
return { messages: data ?? [], loading, error, refetch, sendMessage, sendMedia, sendTemplate, markRead };
|
|
1925
2177
|
}
|
|
1926
2178
|
|
|
@@ -1954,12 +2206,12 @@ function useConversationContext(conversationId) {
|
|
|
1954
2206
|
}
|
|
1955
2207
|
|
|
1956
2208
|
// src/hooks/useConversationRealtime.ts
|
|
1957
|
-
import { useEffect as
|
|
2209
|
+
import { useEffect as useEffect6, useRef as useRef5 } from "react";
|
|
1958
2210
|
function useConversationRealtime(conversationId, onEvent) {
|
|
1959
2211
|
const context = useConversations();
|
|
1960
|
-
const onEventRef =
|
|
2212
|
+
const onEventRef = useRef5(onEvent);
|
|
1961
2213
|
onEventRef.current = onEvent;
|
|
1962
|
-
|
|
2214
|
+
useEffect6(() => {
|
|
1963
2215
|
if (!context || !conversationId) return;
|
|
1964
2216
|
const source = context.sse.connectConversationStream(conversationId);
|
|
1965
2217
|
const handler = (event) => onEventRef.current(event);
|
|
@@ -1972,9 +2224,9 @@ function useConversationRealtime(conversationId, onEvent) {
|
|
|
1972
2224
|
}
|
|
1973
2225
|
function useGlobalRealtime(onEvent) {
|
|
1974
2226
|
const context = useConversations();
|
|
1975
|
-
const onEventRef =
|
|
2227
|
+
const onEventRef = useRef5(onEvent);
|
|
1976
2228
|
onEventRef.current = onEvent;
|
|
1977
|
-
|
|
2229
|
+
useEffect6(() => {
|
|
1978
2230
|
if (!context) return;
|
|
1979
2231
|
const source = context.sse.connectGlobalStream();
|
|
1980
2232
|
const handler = (event) => onEventRef.current(event);
|
|
@@ -2046,6 +2298,7 @@ export {
|
|
|
2046
2298
|
DEFAULT_INTERACTIVE_MESSAGE_LABELS,
|
|
2047
2299
|
DEFAULT_LIGHTBOX_LABELS,
|
|
2048
2300
|
DEFAULT_MESSAGE_COMPOSER_LABELS,
|
|
2301
|
+
DEFAULT_RICH_COMPOSER_TOOLTIPS,
|
|
2049
2302
|
DEFAULT_TEMPLATES_SETTINGS_LABELS,
|
|
2050
2303
|
DEFAULT_WHATSAPP_MESSAGE_EDITOR_LABELS,
|
|
2051
2304
|
DEFAULT_WINDOW_EXPIRED_LABELS,
|
|
@@ -2066,6 +2319,8 @@ export {
|
|
|
2066
2319
|
MessageTimestamp,
|
|
2067
2320
|
NARROW_MAX_WIDTH_PX,
|
|
2068
2321
|
REOPEN_MECHANISM,
|
|
2322
|
+
RICH_COMPOSER_ACTION,
|
|
2323
|
+
RichMessageComposer,
|
|
2069
2324
|
SimpleEmojiPicker,
|
|
2070
2325
|
StatusTicks,
|
|
2071
2326
|
TEMPLATE_SETTINGS_TAB,
|