@adatechnology/conversations-ui 0.1.0-rc.26 → 0.1.0-rc.27
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/chunk-DXPSPUWF.js +110 -0
- package/dist/{chunk-TV4OQRGH.js → chunk-UZJBYD5O.js} +123 -45
- package/dist/{chunk-2AYDBWNE.js → chunk-WCBDXZ3X.js} +13 -3
- package/dist/flows/index.d.ts +2 -0
- package/dist/flows/index.js +61 -18
- package/dist/index.d.ts +37 -10
- package/dist/index.js +694 -297
- package/dist/preview/index.js +3 -3
- package/dist/styles.css +119 -6
- package/package.json +1 -1
- package/src/AudioPlayer.tsx +8 -0
- package/src/AudioRecorderButton.test.tsx +3 -3
- package/src/AudioRecorderButton.tsx +3 -3
- package/src/AudioTranscription.tsx +4 -1
- package/src/Avatar.tsx +1 -1
- package/src/ConversationContextPanel.tsx +2 -2
- package/src/ConversationDocumentsPanel.tsx +11 -6
- package/src/ConversationHeader.test.tsx +66 -0
- package/src/ConversationHeader.tsx +147 -47
- package/src/ConversationListItem.tsx +3 -2
- package/src/ConversationRow.tsx +31 -7
- package/src/DocumentsLibrary.tsx +9 -4
- package/src/EmojiPicker.tsx +2 -1
- package/src/InteractiveMessage.tsx +3 -0
- package/src/Lightbox.tsx +1 -1
- package/src/MediaRenderer.tsx +2 -0
- package/src/MessageBubble.test.tsx +41 -0
- package/src/MessageBubble.tsx +27 -8
- package/src/MessageComposer.tsx +11 -8
- package/src/RichMessageComposer.test.tsx +42 -12
- package/src/RichMessageComposer.tsx +216 -45
- package/src/SimpleEmojiPicker.tsx +5 -3
- package/src/StatusTicks.tsx +1 -1
- package/src/Toast.tsx +4 -0
- package/src/Tooltip.test.ts +42 -0
- package/src/Tooltip.tsx +164 -0
- package/src/WhatsAppMessageEditor.tsx +4 -4
- package/src/WindowExpiredNotice.tsx +12 -4
- package/src/composer.constant.ts +33 -0
- package/src/conversationWindow.ts +7 -5
- package/src/documents/DocumentsWorkspace.tsx +10 -6
- package/src/flows/FlowGroupHeader.tsx +2 -2
- package/src/flows/FlowMapNode.tsx +2 -1
- package/src/flows/FlowNodeCard.tsx +3 -3
- package/src/flows/FlowNodePanel.tsx +6 -5
- package/src/flows/FlowPalette.tsx +7 -1
- package/src/flows/FlowPortalNode.tsx +1 -1
- package/src/flows/FlowsWorkspace.tsx +13 -4
- package/src/flows/labels.ts +4 -0
- package/src/hooks/useContainerWidth.ts +35 -0
- package/src/hooks/useConversationRealtime.ts +10 -8
- package/src/icon.constant.ts +12 -0
- package/src/index.ts +1 -0
- package/src/lib/composer-formatting.test.ts +78 -0
- package/src/lib/composer-formatting.ts +145 -0
- package/src/lib/whatsapp-formatting.test.tsx +37 -0
- package/src/lib/whatsapp-formatting.tsx +28 -3
- package/src/listing/index.tsx +5 -1
- package/src/pagination.constant.ts +10 -0
- package/src/preview/ConversationSimulatorPanel.tsx +1 -1
- package/src/providers/ConversationsProvider.tsx +8 -6
- package/src/settings/MessagesWorkspace.tsx +3 -0
- package/src/settings/TopicsForm.tsx +2 -0
- package/src/settings/TranscriptionSettingsForm.test.tsx +1 -1
- package/src/settings/TranscriptionSettingsForm.tsx +1 -0
- package/src/settings/WelcomeFarewellForm.tsx +1 -0
- package/src/settings/WhatsAppCreateTemplateForm.tsx +1 -0
- package/src/settings/WhatsAppTemplateSettingsForm.tsx +5 -2
- package/src/settings/WhatsAppTemplatesSettings.tsx +2 -0
- package/src/styles.css +100 -4
- package/src/workspace/BulkTemplateModal.tsx +4 -2
- package/src/workspace/ConversationPane.tsx +49 -19
- package/src/workspace/ConversationsInboxList.tsx +17 -8
- package/src/workspace/ConversationsWorkspace.tsx +24 -16
- package/src/workspace/useConversationsInbox.ts +5 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseWhatsAppFormatting,
|
|
3
3
|
useIsDarkTheme
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WCBDXZ3X.js";
|
|
5
5
|
|
|
6
6
|
// src/ConversationLocalesProvider.tsx
|
|
7
7
|
import { createContext, useContext } from "react";
|
|
@@ -89,7 +89,7 @@ function Ticks({ double }) {
|
|
|
89
89
|
}
|
|
90
90
|
function StatusTicks({ status, title }) {
|
|
91
91
|
const colorClass = STATUS_COLOR_CLASS[status] ?? STATUS_COLOR_CLASS.sent;
|
|
92
|
-
return /* @__PURE__ */ jsx2("span", { className: `cursor-help leading-none flex items-center ${colorClass}`, title, children: status === "failed" ? /* @__PURE__ */ jsx2(AlertTriangle, { size: 11 }) : /* @__PURE__ */ jsx2(Ticks, { double: status !== "sent" }) });
|
|
92
|
+
return /* @__PURE__ */ jsx2("span", { className: `cursor-help leading-none flex items-center ${colorClass}`, "data-cv-tooltip": title, children: status === "failed" ? /* @__PURE__ */ jsx2(AlertTriangle, { size: 11 }) : /* @__PURE__ */ jsx2(Ticks, { double: status !== "sent" }) });
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// src/AudioPlayer.tsx
|
|
@@ -100,6 +100,10 @@ var BARS = Array.from({ length: 30 }, (_, i) => {
|
|
|
100
100
|
const heights = [3, 5, 8, 12, 7, 10, 14, 9, 6, 11, 15, 8, 4, 13, 7, 10, 6, 12, 9, 5, 14, 8, 11, 6, 13, 7, 10, 5, 9, 4];
|
|
101
101
|
return heights[i % heights.length];
|
|
102
102
|
});
|
|
103
|
+
var AUDIO_PLAYER_LABELS = {
|
|
104
|
+
play: "Reproduzir",
|
|
105
|
+
pause: "Pausar"
|
|
106
|
+
};
|
|
103
107
|
function fmt(sec) {
|
|
104
108
|
if (!isFinite(sec)) return "0:00";
|
|
105
109
|
const m = Math.floor(sec / 60);
|
|
@@ -161,6 +165,8 @@ function AudioPlayer({ src, isMine = false }) {
|
|
|
161
165
|
/* @__PURE__ */ jsx3(
|
|
162
166
|
"button",
|
|
163
167
|
{
|
|
168
|
+
"data-cv-tooltip": playing ? AUDIO_PLAYER_LABELS.pause : AUDIO_PLAYER_LABELS.play,
|
|
169
|
+
"aria-label": playing ? AUDIO_PLAYER_LABELS.pause : AUDIO_PLAYER_LABELS.play,
|
|
164
170
|
onClick: toggle,
|
|
165
171
|
className: `flex-shrink-0 w-9 h-9 rounded-full flex items-center justify-center transition-colors ${playBtn}`,
|
|
166
172
|
children: playing ? /* @__PURE__ */ jsx3(Pause, { size: 16 }) : /* @__PURE__ */ jsx3(Play, { size: 16, className: "translate-x-0.5" })
|
|
@@ -257,7 +263,7 @@ function AudioTranscription({ transcription, onTranscribe, isMine = false }) {
|
|
|
257
263
|
"button",
|
|
258
264
|
{
|
|
259
265
|
onClick: handleCopy,
|
|
260
|
-
|
|
266
|
+
"data-cv-tooltip": locales.copy,
|
|
261
267
|
"aria-label": hasCopied ? locales.copied : locales.copy,
|
|
262
268
|
className: "ml-auto flex flex-shrink-0 items-center gap-1 rounded px-1.5 py-0.5 text-[11px] text-gray-500 transition-colors hover:bg-black/5 hover:text-gray-700 dark:text-gray-400 dark:hover:bg-white/10 dark:hover:text-gray-200",
|
|
263
269
|
children: hasCopied ? /* @__PURE__ */ jsxs3(Fragment, { children: [
|
|
@@ -289,6 +295,8 @@ function AudioTranscription({ transcription, onTranscribe, isMine = false }) {
|
|
|
289
295
|
isLong && /* @__PURE__ */ jsx4(
|
|
290
296
|
"button",
|
|
291
297
|
{
|
|
298
|
+
"data-cv-tooltip": isExpanded ? locales.showLess : locales.showMore,
|
|
299
|
+
"aria-label": isExpanded ? locales.showLess : locales.showMore,
|
|
292
300
|
onClick: () => setIsExpanded((current) => !current),
|
|
293
301
|
className: "mt-1 text-[11px] font-medium text-gray-500 underline decoration-dotted hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200",
|
|
294
302
|
children: isExpanded ? locales.showLess : locales.showMore
|
|
@@ -298,6 +306,8 @@ function AudioTranscription({ transcription, onTranscribe, isMine = false }) {
|
|
|
298
306
|
onTranscribe && /* @__PURE__ */ jsxs3(
|
|
299
307
|
"button",
|
|
300
308
|
{
|
|
309
|
+
"data-cv-tooltip": isTranscribing ? locales.transcribing : locales.retry,
|
|
310
|
+
"aria-label": isTranscribing ? locales.transcribing : locales.retry,
|
|
301
311
|
onClick: handleTranscribe,
|
|
302
312
|
disabled: isTranscribing,
|
|
303
313
|
className: "mt-1 flex items-center gap-1 text-[11px] text-gray-400 opacity-0 transition-opacity hover:text-gray-600 focus:opacity-100 group-hover:opacity-100 disabled:opacity-50 dark:text-gray-500 dark:hover:text-gray-300",
|
|
@@ -325,6 +335,8 @@ function TranscribeButton({
|
|
|
325
335
|
return /* @__PURE__ */ jsxs3(
|
|
326
336
|
"button",
|
|
327
337
|
{
|
|
338
|
+
"data-cv-tooltip": label,
|
|
339
|
+
"aria-label": label,
|
|
328
340
|
onClick,
|
|
329
341
|
disabled: isBusy || isDisabled,
|
|
330
342
|
className: "flex items-center gap-1.5 rounded px-1.5 py-0.5 text-[11px] text-gray-500 transition-colors hover:bg-black/5 hover:text-gray-700 disabled:opacity-60 dark:text-gray-400 dark:hover:bg-white/10 dark:hover:text-gray-200",
|
|
@@ -492,6 +504,8 @@ function MediaRenderer({
|
|
|
492
504
|
return /* @__PURE__ */ jsxs4(
|
|
493
505
|
"button",
|
|
494
506
|
{
|
|
507
|
+
"data-cv-tooltip": label,
|
|
508
|
+
"aria-label": label,
|
|
495
509
|
onClick: lazy.load,
|
|
496
510
|
disabled: lazy.loading,
|
|
497
511
|
className: "flex min-w-[180px] items-center gap-2 rounded-lg bg-black/5 px-2 py-1.5 text-left transition-colors hover:bg-black/10 disabled:opacity-60 dark:bg-white/10 dark:hover:bg-white/15",
|
|
@@ -584,6 +598,7 @@ function MediaRenderer({
|
|
|
584
598
|
] }) }) : canLazyLoad ? /* @__PURE__ */ jsx6(
|
|
585
599
|
"button",
|
|
586
600
|
{
|
|
601
|
+
"data-cv-tooltip": bubble.downloadFile,
|
|
587
602
|
onClick: lazy.load,
|
|
588
603
|
disabled: lazy.loading,
|
|
589
604
|
className: "w-8 h-8 flex items-center justify-center rounded-full bg-gray-200 hover:bg-gray-300 flex-shrink-0 transition-colors disabled:opacity-50",
|
|
@@ -615,7 +630,7 @@ function Lightbox({ imageUrl, caption, onClose, labels }) {
|
|
|
615
630
|
return /* @__PURE__ */ jsx7("div", { className: "fixed inset-0 z-50 bg-black/85 flex items-center justify-center p-4", onClick: onClose, children: /* @__PURE__ */ jsxs5("div", { className: "max-w-[90vw] max-h-[90vh] flex flex-col items-center", onClick: (e) => e.stopPropagation(), children: [
|
|
616
631
|
/* @__PURE__ */ jsx7("img", { src: imageUrl, alt: caption ?? imageAltLabel, className: "max-w-full max-h-[80vh] object-contain rounded-lg" }),
|
|
617
632
|
caption && /* @__PURE__ */ jsx7("p", { className: "text-white text-sm mt-3 text-center", children: caption }),
|
|
618
|
-
/* @__PURE__ */ jsx7("button", { onClick: onClose, className: "mt-4 px-4 py-2 bg-white/20 text-white rounded-lg hover:bg-white/30 transition-colors", children: closeLabel })
|
|
633
|
+
/* @__PURE__ */ jsx7("button", { "data-cv-tooltip": closeLabel, "aria-label": closeLabel, onClick: onClose, className: "mt-4 px-4 py-2 bg-white/20 text-white rounded-lg hover:bg-white/30 transition-colors", children: closeLabel })
|
|
619
634
|
] }) });
|
|
620
635
|
}
|
|
621
636
|
|
|
@@ -655,6 +670,8 @@ function InteractiveMessage({ payload, onSelect, labels, className }) {
|
|
|
655
670
|
buttons.length > 0 ? /* @__PURE__ */ jsx8("div", { className: "mt-1 flex flex-col gap-1 border-t border-gray-200 pt-1 dark:border-gray-700", children: buttons.map((button) => /* @__PURE__ */ jsx8(
|
|
656
671
|
"button",
|
|
657
672
|
{
|
|
673
|
+
"data-cv-tooltip": button.title,
|
|
674
|
+
"aria-label": button.title,
|
|
658
675
|
type: "button",
|
|
659
676
|
disabled: !isInteractable,
|
|
660
677
|
onClick: () => onSelect?.({ kind: "button", option: button }),
|
|
@@ -667,6 +684,8 @@ function InteractiveMessage({ payload, onSelect, labels, className }) {
|
|
|
667
684
|
/* @__PURE__ */ jsxs6(
|
|
668
685
|
"button",
|
|
669
686
|
{
|
|
687
|
+
"data-cv-tooltip": payload.action?.button ?? openListLabel,
|
|
688
|
+
"aria-label": payload.action?.button ?? openListLabel,
|
|
670
689
|
type: "button",
|
|
671
690
|
onClick: () => setIsListOpen((open) => !open),
|
|
672
691
|
"aria-expanded": isListOpen,
|
|
@@ -682,6 +701,8 @@ function InteractiveMessage({ payload, onSelect, labels, className }) {
|
|
|
682
701
|
(section.rows ?? []).map((row) => /* @__PURE__ */ jsxs6(
|
|
683
702
|
"button",
|
|
684
703
|
{
|
|
704
|
+
"data-cv-tooltip": row.title,
|
|
705
|
+
"aria-label": row.title,
|
|
685
706
|
type: "button",
|
|
686
707
|
disabled: !isInteractable,
|
|
687
708
|
onClick: () => onSelect?.({ kind: "list", option: row }),
|
|
@@ -711,7 +732,7 @@ function createMediaUrlResolver(api) {
|
|
|
711
732
|
}
|
|
712
733
|
|
|
713
734
|
// src/providers/ConversationsProvider.tsx
|
|
714
|
-
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
735
|
+
import { createContext as createContext2, useContext as useContext2, useMemo } from "react";
|
|
715
736
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
716
737
|
var ConversationsContext = createContext2(null);
|
|
717
738
|
function ConversationsProvider({
|
|
@@ -719,14 +740,15 @@ function ConversationsProvider({
|
|
|
719
740
|
sse,
|
|
720
741
|
children
|
|
721
742
|
}) {
|
|
722
|
-
|
|
743
|
+
const value = useMemo(() => ({ api, sse }), [api, sse]);
|
|
744
|
+
return /* @__PURE__ */ jsx9(ConversationsContext.Provider, { value, children });
|
|
723
745
|
}
|
|
724
746
|
function useConversations() {
|
|
725
747
|
return useContext2(ConversationsContext);
|
|
726
748
|
}
|
|
727
749
|
|
|
728
750
|
// src/MessageBubble.tsx
|
|
729
|
-
import { useMemo, useState as useState5 } from "react";
|
|
751
|
+
import { useMemo as useMemo2, useState as useState5 } from "react";
|
|
730
752
|
import { Check as Check2 } from "lucide-react";
|
|
731
753
|
import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
732
754
|
var BUBBLE_COLOR = {
|
|
@@ -751,11 +773,11 @@ function MessageBubble({
|
|
|
751
773
|
const { bubble, selection } = useConversationLocales();
|
|
752
774
|
const [lightboxSrc, setLightboxSrc] = useState5(null);
|
|
753
775
|
const context = useConversations();
|
|
754
|
-
const resolveMediaUrl =
|
|
776
|
+
const resolveMediaUrl = useMemo2(
|
|
755
777
|
() => onResolveMediaUrl ?? (context?.api ? createMediaUrlResolver(context.api) : void 0),
|
|
756
778
|
[onResolveMediaUrl, context?.api]
|
|
757
779
|
);
|
|
758
|
-
const requestTranscription =
|
|
780
|
+
const requestTranscription = useMemo2(() => {
|
|
759
781
|
const transcribe = onTranscribeAudio ?? context?.api?.transcribeAudio?.bind(context.api);
|
|
760
782
|
if (!transcribe) return void 0;
|
|
761
783
|
return () => transcribe(message.id);
|
|
@@ -765,6 +787,10 @@ function MessageBubble({
|
|
|
765
787
|
const isMedia = MEDIA_TYPES.has(message.type);
|
|
766
788
|
const isTemplate = message.type === "template";
|
|
767
789
|
const isInteractive = message.type === "interactive";
|
|
790
|
+
const mediaCaption = isMedia ? [message.caption, message.content].find((text) => {
|
|
791
|
+
const trimmed = text?.trim();
|
|
792
|
+
return trimmed && trimmed !== message.filename;
|
|
793
|
+
}) : void 0;
|
|
768
794
|
const displayName = message.sender === "agent" && senderName ? senderName : bubble[message.sender] ?? message.sender;
|
|
769
795
|
const tooltipText = message.status === "read" && message.readAt ? `${bubble.readAt}${formatDateTime(message.readAt)}` : message.status === "failed" ? bubble.windowExpired : void 0;
|
|
770
796
|
const tailCornerClass = isFirstInGroup ? isMine ? "rounded-tr-md" : "rounded-tl-md" : "";
|
|
@@ -775,7 +801,8 @@ function MessageBubble({
|
|
|
775
801
|
e.stopPropagation();
|
|
776
802
|
onToggleSelect?.();
|
|
777
803
|
},
|
|
778
|
-
|
|
804
|
+
"data-cv-tooltip": selection.select,
|
|
805
|
+
"aria-label": selection.select,
|
|
779
806
|
className: `
|
|
780
807
|
flex-shrink-0 self-end mb-1 w-5 h-5 rounded-full border-2 flex items-center justify-center transition-all
|
|
781
808
|
${isSelected ? "bg-teal-600 border-teal-600" : "bg-white/80 dark:bg-black/40 border-black/20 dark:border-white/30"}
|
|
@@ -813,22 +840,25 @@ function MessageBubble({
|
|
|
813
840
|
"div",
|
|
814
841
|
{
|
|
815
842
|
className: "mb-1 inline-flex items-center gap-1 rounded-full bg-amber-100 px-2 py-0.5 text-xs font-medium text-amber-800 dark:bg-amber-950/60 dark:text-amber-300",
|
|
816
|
-
|
|
843
|
+
"data-cv-tooltip": message.moderation.terms.length > 0 ? message.moderation.terms.join(", ") : void 0,
|
|
817
844
|
children: [
|
|
818
845
|
/* @__PURE__ */ jsx10("span", { "aria-hidden": true, children: "\u26A0\uFE0F" }),
|
|
819
846
|
/* @__PURE__ */ jsx10("span", { children: bubble.moderationFlagged })
|
|
820
847
|
]
|
|
821
848
|
}
|
|
822
849
|
),
|
|
823
|
-
isMedia ? /* @__PURE__ */
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
850
|
+
isMedia ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
|
|
851
|
+
/* @__PURE__ */ jsx10(
|
|
852
|
+
MediaRenderer,
|
|
853
|
+
{
|
|
854
|
+
message,
|
|
855
|
+
onLightbox: setLightboxSrc,
|
|
856
|
+
onResolveUrl: resolveMediaUrl,
|
|
857
|
+
...requestTranscription ? { onTranscribeAudio: requestTranscription } : {}
|
|
858
|
+
}
|
|
859
|
+
),
|
|
860
|
+
mediaCaption ? /* @__PURE__ */ jsx10("div", { className: "mt-1 text-sm text-gray-900 dark:text-gray-100 whitespace-pre-wrap break-words leading-[19px]", children: parseWhatsAppFormatting(mediaCaption) }) : null
|
|
861
|
+
] }) : isInteractive && message.payload ? (
|
|
832
862
|
// O texto da mensagem interativa mora dentro do payload (`body.text`), e `content` guarda
|
|
833
863
|
// só uma cópia achatada para busca — renderizar `content` aqui duplicaria o corpo.
|
|
834
864
|
/* @__PURE__ */ jsx10(InteractiveMessage, { payload: message.payload, onSelect: onInteractiveSelect })
|
|
@@ -1046,7 +1076,7 @@ function searchEmojis(query) {
|
|
|
1046
1076
|
}
|
|
1047
1077
|
|
|
1048
1078
|
// src/EmojiPicker.tsx
|
|
1049
|
-
import { useState as useState6, useCallback as useCallback2, useMemo as
|
|
1079
|
+
import { useState as useState6, useCallback as useCallback2, useMemo as useMemo3 } from "react";
|
|
1050
1080
|
import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1051
1081
|
var DEFAULT_EMOJI_PICKER_LABELS = {
|
|
1052
1082
|
search: "Buscar emoji",
|
|
@@ -1064,7 +1094,7 @@ var EmojiPicker = ({ onSelect, labels, className = "" }) => {
|
|
|
1064
1094
|
[onSelect]
|
|
1065
1095
|
);
|
|
1066
1096
|
const isSearching = query.trim().length > 0;
|
|
1067
|
-
const visibleEntries =
|
|
1097
|
+
const visibleEntries = useMemo3(
|
|
1068
1098
|
() => isSearching ? searchEmojis(query) : EMOJI_CATEGORIES[activeCategory].entries,
|
|
1069
1099
|
[isSearching, query, activeCategory]
|
|
1070
1100
|
);
|
|
@@ -1083,6 +1113,8 @@ var EmojiPicker = ({ onSelect, labels, className = "" }) => {
|
|
|
1083
1113
|
isSearching ? null : /* @__PURE__ */ jsx12("div", { className: "flex border-b border-gray-200 overflow-x-auto", children: EMOJI_CATEGORIES.map((category, index) => /* @__PURE__ */ jsxs8(
|
|
1084
1114
|
"button",
|
|
1085
1115
|
{
|
|
1116
|
+
"data-cv-tooltip": category.name,
|
|
1117
|
+
"aria-label": category.name,
|
|
1086
1118
|
onClick: () => setActiveCategory(index),
|
|
1087
1119
|
className: `px-3 py-2 text-xs font-medium whitespace-nowrap border-b-2 transition-colors ${activeCategory === index ? "border-blue-500 text-blue-600" : "border-transparent text-gray-500 hover:text-gray-700"}`,
|
|
1088
1120
|
children: [
|
|
@@ -1099,7 +1131,7 @@ var EmojiPicker = ({ onSelect, labels, className = "" }) => {
|
|
|
1099
1131
|
onClick: () => handleSelect(entry.emoji),
|
|
1100
1132
|
className: "w-8 h-8 flex items-center justify-center text-lg hover:bg-gray-100 rounded transition-colors cursor-pointer",
|
|
1101
1133
|
"aria-label": entry.emoji,
|
|
1102
|
-
|
|
1134
|
+
"data-cv-tooltip": entry.keywords[0],
|
|
1103
1135
|
children: entry.emoji
|
|
1104
1136
|
},
|
|
1105
1137
|
entry.emoji
|
|
@@ -1221,7 +1253,7 @@ function AudioRecorderButton({
|
|
|
1221
1253
|
{
|
|
1222
1254
|
type: "button",
|
|
1223
1255
|
onClick: discard,
|
|
1224
|
-
|
|
1256
|
+
"data-cv-tooltip": labelOf("discard"),
|
|
1225
1257
|
"aria-label": labelOf("discard"),
|
|
1226
1258
|
className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full text-gray-500 transition-colors hover:bg-gray-100 hover:text-red-500 dark:hover:bg-gray-700",
|
|
1227
1259
|
children: /* @__PURE__ */ jsxs9("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
|
|
@@ -1235,7 +1267,7 @@ function AudioRecorderButton({
|
|
|
1235
1267
|
{
|
|
1236
1268
|
type: "button",
|
|
1237
1269
|
onClick: confirm,
|
|
1238
|
-
|
|
1270
|
+
"data-cv-tooltip": labelOf("send"),
|
|
1239
1271
|
"aria-label": labelOf("send"),
|
|
1240
1272
|
className: "flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-full bg-emerald-500 text-white transition-colors hover:bg-emerald-600",
|
|
1241
1273
|
children: /* @__PURE__ */ jsx13("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx13("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) })
|
|
@@ -1250,7 +1282,7 @@ function AudioRecorderButton({
|
|
|
1250
1282
|
type: "button",
|
|
1251
1283
|
disabled: disabled || pending !== void 0,
|
|
1252
1284
|
onClick: () => isRecording ? stop() : void start(),
|
|
1253
|
-
|
|
1285
|
+
"data-cv-tooltip": toggleLabel,
|
|
1254
1286
|
"aria-label": toggleLabel,
|
|
1255
1287
|
"aria-pressed": isRecording,
|
|
1256
1288
|
className: `flex h-10 w-10 items-center justify-center rounded-full transition-colors disabled:opacity-50 ${isRecording ? "animate-pulse bg-red-500 text-white ring-4 ring-red-500/30 hover:bg-red-600" : "text-gray-500 hover:bg-gray-200 dark:hover:bg-gray-700"}`,
|
|
@@ -1267,6 +1299,17 @@ function AudioRecorderButton({
|
|
|
1267
1299
|
|
|
1268
1300
|
// src/MessageComposer.tsx
|
|
1269
1301
|
import { useState as useState8, useRef as useRef3, useCallback as useCallback4 } from "react";
|
|
1302
|
+
|
|
1303
|
+
// src/composer.constant.ts
|
|
1304
|
+
var COMPOSER_BAR_CLASS = "cv-composer-bar";
|
|
1305
|
+
var COMPOSER_TOOL_BUTTON_CLASS = "flex h-9 w-9 flex-shrink-0 items-center justify-center rounded-full transition-colors hover:bg-teal-50 hover:text-teal-600 dark:hover:bg-teal-900/30 dark:hover:text-teal-400";
|
|
1306
|
+
var COMPOSER_TOOL_BUTTON_ACTIVE_CLASS = "bg-teal-50 text-teal-600 dark:bg-teal-900/40 dark:text-teal-400";
|
|
1307
|
+
var COMPOSER_TOOL_BUTTON_IDLE_CLASS = "text-gray-400 dark:text-gray-500";
|
|
1308
|
+
var COMPOSER_MONOSPACE_CLASS = "bg-black/5 dark:bg-white/10 rounded px-0.5 font-mono text-sm";
|
|
1309
|
+
var COMPOSER_COMPACT_WIDTH = 480;
|
|
1310
|
+
var QUICK_REPLY_PILL_CLASS = "whitespace-nowrap rounded-full border border-gray-200 bg-white px-3 py-1.5 text-xs text-gray-600 shadow-sm transition-colors hover:border-teal-200 hover:bg-teal-50 hover:text-teal-700 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:border-teal-800 dark:hover:bg-teal-950/40 dark:hover:text-teal-400";
|
|
1311
|
+
|
|
1312
|
+
// src/MessageComposer.tsx
|
|
1270
1313
|
import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1271
1314
|
function applyQuickReplyVariables(template, variables = {}) {
|
|
1272
1315
|
return template.replace(/\{\{\s*([\w.]+)\s*\}\}/g, (_, chave) => variables[chave] ?? "");
|
|
@@ -1277,7 +1320,8 @@ function resolveQuickReply(quickReply, variables = {}) {
|
|
|
1277
1320
|
var DEFAULT_MESSAGE_COMPOSER_LABELS = {
|
|
1278
1321
|
emoji: "Emoji",
|
|
1279
1322
|
attach: "Anexar",
|
|
1280
|
-
send: "Enviar"
|
|
1323
|
+
send: "Enviar",
|
|
1324
|
+
removeAttachment: "Remover anexo"
|
|
1281
1325
|
};
|
|
1282
1326
|
var DEFAULT_ACCEPTED_FILE_TYPES = [
|
|
1283
1327
|
"image/jpeg,image/png,image/webp",
|
|
@@ -1309,6 +1353,7 @@ var MessageComposer = ({
|
|
|
1309
1353
|
const emojiLabel = labels?.emoji ?? DEFAULT_MESSAGE_COMPOSER_LABELS.emoji;
|
|
1310
1354
|
const attachLabel = labels?.attach ?? DEFAULT_MESSAGE_COMPOSER_LABELS.attach;
|
|
1311
1355
|
const sendLabel = labels?.send ?? DEFAULT_MESSAGE_COMPOSER_LABELS.send;
|
|
1356
|
+
const removeAttachmentLabel = labels?.removeAttachment ?? DEFAULT_MESSAGE_COMPOSER_LABELS.removeAttachment;
|
|
1312
1357
|
const [internalText, setInternalText] = useState8("");
|
|
1313
1358
|
const [showEmoji, setShowEmoji] = useState8(false);
|
|
1314
1359
|
const [attachments, setAttachments] = useState8([]);
|
|
@@ -1406,7 +1451,7 @@ var MessageComposer = ({
|
|
|
1406
1451
|
/* A barra é a superfície (cinza, largura cheia, sem raio) e o campo dentro é que arredonda —
|
|
1407
1452
|
ordem do WhatsApp. Invertido, o pill arredondado ia até a borda da tela e os cantos
|
|
1408
1453
|
descobriam o fundo branco da página, que lia como defeito. */
|
|
1409
|
-
/* @__PURE__ */ jsxs10("div", { className: cn(
|
|
1454
|
+
/* @__PURE__ */ jsxs10("div", { className: cn(COMPOSER_BAR_CLASS, className), children: [
|
|
1410
1455
|
quickReplies && quickReplies.length > 0 && /* @__PURE__ */ jsx14(
|
|
1411
1456
|
"div",
|
|
1412
1457
|
{
|
|
@@ -1417,15 +1462,14 @@ var MessageComposer = ({
|
|
|
1417
1462
|
children: quickReplies.map((quickReply) => /* @__PURE__ */ jsx14(
|
|
1418
1463
|
"button",
|
|
1419
1464
|
{
|
|
1465
|
+
"data-cv-tooltip": quickReply.label,
|
|
1466
|
+
"aria-label": quickReply.label,
|
|
1420
1467
|
type: "button",
|
|
1421
1468
|
onClick: () => {
|
|
1422
1469
|
setText(resolveQuickReply(quickReply, quickReplyVariables));
|
|
1423
1470
|
textareaRef.current?.focus();
|
|
1424
1471
|
},
|
|
1425
|
-
className: cn(
|
|
1426
|
-
"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",
|
|
1427
|
-
classNames?.quickReply
|
|
1428
|
-
),
|
|
1472
|
+
className: cn(QUICK_REPLY_PILL_CLASS, classNames?.quickReply),
|
|
1429
1473
|
children: quickReply.label
|
|
1430
1474
|
},
|
|
1431
1475
|
quickReply.key
|
|
@@ -1437,11 +1481,11 @@ var MessageComposer = ({
|
|
|
1437
1481
|
/* @__PURE__ */ jsx14("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
1438
1482
|
/* @__PURE__ */ jsx14("polyline", { points: "14 2 14 8 20 8" })
|
|
1439
1483
|
] }) }),
|
|
1440
|
-
/* @__PURE__ */ jsx14("button", { onClick: () => removeAttachment(i), className: "absolute -top-2 -right-2 w-5 h-5 bg-gray-600 text-white rounded-full flex items-center justify-center hover:bg-gray-800 text-xs", children: "\u2715" })
|
|
1484
|
+
/* @__PURE__ */ jsx14("button", { "data-cv-tooltip": removeAttachmentLabel, "aria-label": removeAttachmentLabel, onClick: () => removeAttachment(i), className: "absolute -top-2 -right-2 w-5 h-5 bg-gray-600 text-white rounded-full flex items-center justify-center hover:bg-gray-800 text-xs", children: "\u2715" })
|
|
1441
1485
|
] }, i)) }),
|
|
1442
1486
|
/* @__PURE__ */ jsxs10("div", { className: cn("flex items-end gap-1.5 rounded-xl bg-white px-3 py-2", classNames?.field), children: [
|
|
1443
1487
|
showEmojiButton && /* @__PURE__ */ jsxs10("div", { className: "relative flex-shrink-0", children: [
|
|
1444
|
-
/* @__PURE__ */ jsx14("button", { onClick: () => setShowEmoji((v) => !v), className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 transition-colors", "aria-label": emojiLabel, children: /* @__PURE__ */ jsxs10("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1488
|
+
/* @__PURE__ */ jsx14("button", { "data-cv-tooltip": emojiLabel, onClick: () => setShowEmoji((v) => !v), className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 transition-colors", "aria-label": emojiLabel, children: /* @__PURE__ */ jsxs10("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: [
|
|
1445
1489
|
/* @__PURE__ */ jsx14("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1446
1490
|
/* @__PURE__ */ jsx14("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }),
|
|
1447
1491
|
/* @__PURE__ */ jsx14("circle", { cx: "9", cy: "9", r: "0.5", fill: "currentColor" }),
|
|
@@ -1468,11 +1512,12 @@ var MessageComposer = ({
|
|
|
1468
1512
|
),
|
|
1469
1513
|
showAttachButton && /* @__PURE__ */ jsxs10(Fragment3, { children: [
|
|
1470
1514
|
/* @__PURE__ */ jsx14("input", { ref: fileInputRef, type: "file", multiple: true, accept: acceptedFileTypes, onChange: handleFileChange, className: "hidden" }),
|
|
1471
|
-
/* @__PURE__ */ jsx14("button", { onClick: () => fileInputRef.current?.click(), className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 flex-shrink-0 transition-colors", "aria-label": attachLabel, children: /* @__PURE__ */ jsx14("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx14("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })
|
|
1515
|
+
/* @__PURE__ */ jsx14("button", { "data-cv-tooltip": attachLabel, onClick: () => fileInputRef.current?.click(), className: "w-9 h-9 flex items-center justify-center rounded-full text-gray-500 hover:bg-gray-200 flex-shrink-0 transition-colors", "aria-label": attachLabel, children: /* @__PURE__ */ jsx14("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx14("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) }) })
|
|
1472
1516
|
] }),
|
|
1473
1517
|
!canSend && effectiveIdleAction ? /* @__PURE__ */ jsx14("div", { className: "flex-shrink-0", children: effectiveIdleAction }) : /* @__PURE__ */ jsx14(
|
|
1474
1518
|
"button",
|
|
1475
1519
|
{
|
|
1520
|
+
"data-cv-tooltip": sendLabel,
|
|
1476
1521
|
onClick: sendMessage,
|
|
1477
1522
|
disabled: !canSend || disabled,
|
|
1478
1523
|
className: `w-10 h-10 flex items-center justify-center rounded-full flex-shrink-0 transition-all ${canSend && !disabled ? "bg-[#00a884] text-white hover:bg-[#06cf9c] shadow-sm" : "bg-gray-200 text-gray-400 cursor-not-allowed"}`,
|
|
@@ -1613,6 +1658,16 @@ function useConversationDocuments(conversationId, params) {
|
|
|
1613
1658
|
// src/ConversationDocumentsPanel.tsx
|
|
1614
1659
|
import { useState as useState10 } from "react";
|
|
1615
1660
|
import { ArrowUpDown, Bot, Download, Eye, Users } from "lucide-react";
|
|
1661
|
+
|
|
1662
|
+
// src/pagination.constant.ts
|
|
1663
|
+
var PAGINATION_LABELS = {
|
|
1664
|
+
first: "Primeira p\xE1gina",
|
|
1665
|
+
previous: "P\xE1gina anterior",
|
|
1666
|
+
next: "Pr\xF3xima p\xE1gina",
|
|
1667
|
+
last: "\xDAltima p\xE1gina"
|
|
1668
|
+
};
|
|
1669
|
+
|
|
1670
|
+
// src/ConversationDocumentsPanel.tsx
|
|
1616
1671
|
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1617
1672
|
var DOCUMENT_SOURCE_FILTER = {
|
|
1618
1673
|
ALL: "all",
|
|
@@ -1740,6 +1795,8 @@ function ConversationDocumentsPanel({
|
|
|
1740
1795
|
/* @__PURE__ */ jsxs11(
|
|
1741
1796
|
"button",
|
|
1742
1797
|
{
|
|
1798
|
+
"data-cv-tooltip": sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest,
|
|
1799
|
+
"aria-label": sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest,
|
|
1743
1800
|
type: "button",
|
|
1744
1801
|
onClick: () => applyFilter(() => setSortDirection(sortDirection === "desc" ? "asc" : "desc")),
|
|
1745
1802
|
className: cn("cv-header-action inline-flex items-center gap-1", classNames?.sortButton),
|
|
@@ -1752,6 +1809,8 @@ function ConversationDocumentsPanel({
|
|
|
1752
1809
|
hasFilters ? /* @__PURE__ */ jsx16(
|
|
1753
1810
|
"button",
|
|
1754
1811
|
{
|
|
1812
|
+
"data-cv-tooltip": labels.clearFilters,
|
|
1813
|
+
"aria-label": labels.clearFilters,
|
|
1755
1814
|
type: "button",
|
|
1756
1815
|
onClick: () => applyFilter(() => {
|
|
1757
1816
|
setSearch("");
|
|
@@ -1779,7 +1838,7 @@ function ConversationDocumentsPanel({
|
|
|
1779
1838
|
),
|
|
1780
1839
|
labels.selectAll
|
|
1781
1840
|
] }),
|
|
1782
|
-
selectedIds.length > 0 ? /* @__PURE__ */ jsx16("button", { type: "button", onClick: () => void handleDownloadSelected(), className: "cv-header-action", children: labels.downloadSelected(selectedIds.length) }) : null,
|
|
1841
|
+
selectedIds.length > 0 ? /* @__PURE__ */ jsx16("button", { "data-cv-tooltip": labels.downloadSelected(selectedIds.length), "aria-label": labels.downloadSelected(selectedIds.length), type: "button", onClick: () => void handleDownloadSelected(), className: "cv-header-action", children: labels.downloadSelected(selectedIds.length) }) : null,
|
|
1783
1842
|
archiveError ? /* @__PURE__ */ jsx16("span", { role: "alert", className: "text-red-600 dark:text-red-400", children: labels.archiveFailed }) : null
|
|
1784
1843
|
] }) : null,
|
|
1785
1844
|
/* @__PURE__ */ jsx16("ul", { className: cn("space-y-2", classNames?.list), children: documents.map((document2) => {
|
|
@@ -1824,7 +1883,7 @@ function ConversationDocumentsPanel({
|
|
|
1824
1883
|
"div",
|
|
1825
1884
|
{
|
|
1826
1885
|
className: cn("truncate text-sm font-medium", classNames?.filename),
|
|
1827
|
-
|
|
1886
|
+
"data-cv-tooltip": document2.filename,
|
|
1828
1887
|
children: document2.filename
|
|
1829
1888
|
}
|
|
1830
1889
|
),
|
|
@@ -1841,7 +1900,7 @@ function ConversationDocumentsPanel({
|
|
|
1841
1900
|
{
|
|
1842
1901
|
type: "button",
|
|
1843
1902
|
onClick: () => void handleOpen(document2.id, "inline"),
|
|
1844
|
-
|
|
1903
|
+
"data-cv-tooltip": labels.view,
|
|
1845
1904
|
"aria-label": `${labels.view}: ${document2.filename}`,
|
|
1846
1905
|
className: cn("cv-header-icon", classNames?.viewButton),
|
|
1847
1906
|
children: /* @__PURE__ */ jsx16(Eye, { size: 14 })
|
|
@@ -1852,7 +1911,7 @@ function ConversationDocumentsPanel({
|
|
|
1852
1911
|
{
|
|
1853
1912
|
type: "button",
|
|
1854
1913
|
onClick: () => void handleOpen(document2.id, "attachment"),
|
|
1855
|
-
|
|
1914
|
+
"data-cv-tooltip": labels.download,
|
|
1856
1915
|
"aria-label": `${labels.download}: ${document2.filename}`,
|
|
1857
1916
|
className: cn("cv-header-icon", classNames?.downloadButton),
|
|
1858
1917
|
children: /* @__PURE__ */ jsx16(Download, { size: 14 })
|
|
@@ -1880,7 +1939,8 @@ function ConversationDocumentsPanel({
|
|
|
1880
1939
|
type: "button",
|
|
1881
1940
|
onClick: () => setPage(page - 1),
|
|
1882
1941
|
disabled: page <= 1,
|
|
1883
|
-
"aria-label":
|
|
1942
|
+
"aria-label": PAGINATION_LABELS.previous,
|
|
1943
|
+
"data-cv-tooltip": PAGINATION_LABELS.previous,
|
|
1884
1944
|
className: "cv-header-icon disabled:opacity-40",
|
|
1885
1945
|
children: "\u2039"
|
|
1886
1946
|
}
|
|
@@ -1892,7 +1952,8 @@ function ConversationDocumentsPanel({
|
|
|
1892
1952
|
type: "button",
|
|
1893
1953
|
onClick: () => setPage(page + 1),
|
|
1894
1954
|
disabled: page >= lastPage,
|
|
1895
|
-
"aria-label":
|
|
1955
|
+
"aria-label": PAGINATION_LABELS.next,
|
|
1956
|
+
"data-cv-tooltip": PAGINATION_LABELS.next,
|
|
1896
1957
|
className: "cv-header-icon disabled:opacity-40",
|
|
1897
1958
|
children: "\u203A"
|
|
1898
1959
|
}
|
|
@@ -2013,6 +2074,8 @@ function DocumentsLibrary({
|
|
|
2013
2074
|
/* @__PURE__ */ jsxs12(
|
|
2014
2075
|
"button",
|
|
2015
2076
|
{
|
|
2077
|
+
"data-cv-tooltip": sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest,
|
|
2078
|
+
"aria-label": sortDirection === "desc" ? labels.sortMostRecent : labels.sortOldest,
|
|
2016
2079
|
type: "button",
|
|
2017
2080
|
onClick: () => applyFilter(() => setSortDirection(sortDirection === "desc" ? "asc" : "desc")),
|
|
2018
2081
|
className: cn("cv-header-action inline-flex items-center gap-1", classNames?.sortButton),
|
|
@@ -2025,6 +2088,8 @@ function DocumentsLibrary({
|
|
|
2025
2088
|
hasFilters ? /* @__PURE__ */ jsx17(
|
|
2026
2089
|
"button",
|
|
2027
2090
|
{
|
|
2091
|
+
"data-cv-tooltip": labels.clearFilters,
|
|
2092
|
+
"aria-label": labels.clearFilters,
|
|
2028
2093
|
type: "button",
|
|
2029
2094
|
onClick: () => applyFilter(() => {
|
|
2030
2095
|
setSearch("");
|
|
@@ -2053,7 +2118,7 @@ function DocumentsLibrary({
|
|
|
2053
2118
|
/* @__PURE__ */ jsxs12("div", { className: "flex min-w-0 flex-1 items-center gap-3", children: [
|
|
2054
2119
|
/* @__PURE__ */ jsx17(FileIcon, { filename: document2.filename, mimeType: document2.mimeType }),
|
|
2055
2120
|
/* @__PURE__ */ jsxs12("div", { className: "min-w-0 flex-1", children: [
|
|
2056
|
-
/* @__PURE__ */ jsx17("div", { className: cn("truncate text-sm font-medium", classNames?.filename),
|
|
2121
|
+
/* @__PURE__ */ jsx17("div", { className: cn("truncate text-sm font-medium", classNames?.filename), "data-cv-tooltip": document2.filename, children: document2.filename }),
|
|
2057
2122
|
/* @__PURE__ */ jsxs12("div", { className: cn("flex flex-wrap items-center gap-x-2 text-xs text-gray-500", classNames?.meta), children: [
|
|
2058
2123
|
/* @__PURE__ */ jsxs12("span", { className: "inline-flex items-center gap-1", children: [
|
|
2059
2124
|
/* @__PURE__ */ jsx17(SourceIcon, { size: 11 }),
|
|
@@ -2071,7 +2136,8 @@ function DocumentsLibrary({
|
|
|
2071
2136
|
{
|
|
2072
2137
|
type: "button",
|
|
2073
2138
|
onClick: () => onOpenConversation(document2.conversationId),
|
|
2074
|
-
|
|
2139
|
+
"data-cv-tooltip": labels.openConversation,
|
|
2140
|
+
"aria-label": labels.openConversation,
|
|
2075
2141
|
className: cn("cv-header-action inline-flex shrink-0 items-center gap-1", classNames?.conversationLink),
|
|
2076
2142
|
children: [
|
|
2077
2143
|
/* @__PURE__ */ jsx17(MessageSquare, { size: 12 }),
|
|
@@ -2085,7 +2151,7 @@ function DocumentsLibrary({
|
|
|
2085
2151
|
{
|
|
2086
2152
|
type: "button",
|
|
2087
2153
|
onClick: () => void handleOpen(document2.id, "inline"),
|
|
2088
|
-
|
|
2154
|
+
"data-cv-tooltip": labels.view,
|
|
2089
2155
|
"aria-label": `${labels.view}: ${document2.filename}`,
|
|
2090
2156
|
className: "cv-header-icon",
|
|
2091
2157
|
children: /* @__PURE__ */ jsx17(Eye2, { size: 14 })
|
|
@@ -2096,7 +2162,7 @@ function DocumentsLibrary({
|
|
|
2096
2162
|
{
|
|
2097
2163
|
type: "button",
|
|
2098
2164
|
onClick: () => void handleOpen(document2.id, "attachment"),
|
|
2099
|
-
|
|
2165
|
+
"data-cv-tooltip": labels.download,
|
|
2100
2166
|
"aria-label": `${labels.download}: ${document2.filename}`,
|
|
2101
2167
|
className: "cv-header-icon",
|
|
2102
2168
|
children: /* @__PURE__ */ jsx17(Download2, { size: 14 })
|
|
@@ -2114,6 +2180,8 @@ function DocumentsLibrary({
|
|
|
2114
2180
|
/* @__PURE__ */ jsx17(
|
|
2115
2181
|
"button",
|
|
2116
2182
|
{
|
|
2183
|
+
"data-cv-tooltip": PAGINATION_LABELS.previous,
|
|
2184
|
+
"aria-label": PAGINATION_LABELS.previous,
|
|
2117
2185
|
type: "button",
|
|
2118
2186
|
onClick: () => setPage(page - 1),
|
|
2119
2187
|
disabled: page <= 1,
|
|
@@ -2125,6 +2193,8 @@ function DocumentsLibrary({
|
|
|
2125
2193
|
/* @__PURE__ */ jsx17(
|
|
2126
2194
|
"button",
|
|
2127
2195
|
{
|
|
2196
|
+
"data-cv-tooltip": PAGINATION_LABELS.next,
|
|
2197
|
+
"aria-label": PAGINATION_LABELS.next,
|
|
2128
2198
|
type: "button",
|
|
2129
2199
|
onClick: () => setPage(page + 1),
|
|
2130
2200
|
disabled: page >= lastPage,
|
|
@@ -2166,6 +2236,13 @@ export {
|
|
|
2166
2236
|
DEFAULT_AUDIO_RECORDER_BUTTON_LABELS,
|
|
2167
2237
|
DEFAULT_MAX_RECORDING_MILLISECONDS,
|
|
2168
2238
|
AudioRecorderButton,
|
|
2239
|
+
COMPOSER_BAR_CLASS,
|
|
2240
|
+
COMPOSER_TOOL_BUTTON_CLASS,
|
|
2241
|
+
COMPOSER_TOOL_BUTTON_ACTIVE_CLASS,
|
|
2242
|
+
COMPOSER_TOOL_BUTTON_IDLE_CLASS,
|
|
2243
|
+
COMPOSER_MONOSPACE_CLASS,
|
|
2244
|
+
COMPOSER_COMPACT_WIDTH,
|
|
2245
|
+
QUICK_REPLY_PILL_CLASS,
|
|
2169
2246
|
applyQuickReplyVariables,
|
|
2170
2247
|
resolveQuickReply,
|
|
2171
2248
|
DEFAULT_MESSAGE_COMPOSER_LABELS,
|
|
@@ -2179,6 +2256,7 @@ export {
|
|
|
2179
2256
|
conversationsOf,
|
|
2180
2257
|
totalOf,
|
|
2181
2258
|
useConversationDocuments,
|
|
2259
|
+
PAGINATION_LABELS,
|
|
2182
2260
|
DOCUMENT_SOURCE_FILTER,
|
|
2183
2261
|
DEFAULT_CONVERSATION_DOCUMENTS_LABELS,
|
|
2184
2262
|
ConversationDocumentsPanel,
|
|
@@ -69,9 +69,12 @@ function parseInlineTokens(text) {
|
|
|
69
69
|
if (remaining) result.push({ type: "text", content: remaining });
|
|
70
70
|
break;
|
|
71
71
|
}
|
|
72
|
-
if (nextSpecial
|
|
73
|
-
result.push({ type: "text", content: remaining.slice(0,
|
|
72
|
+
if (nextSpecial === 0) {
|
|
73
|
+
result.push({ type: "text", content: remaining.slice(0, 1) });
|
|
74
|
+
remaining = remaining.slice(1);
|
|
75
|
+
continue;
|
|
74
76
|
}
|
|
77
|
+
result.push({ type: "text", content: remaining.slice(0, nextSpecial) });
|
|
75
78
|
remaining = remaining.slice(nextSpecial);
|
|
76
79
|
}
|
|
77
80
|
return result;
|
|
@@ -103,6 +106,9 @@ function unescapeHtml(text) {
|
|
|
103
106
|
}
|
|
104
107
|
var CODE_TOKEN_MARK = String.fromCharCode(57344);
|
|
105
108
|
var CODE_TOKEN_REGEX = new RegExp(`${CODE_TOKEN_MARK}(\\d+)${CODE_TOKEN_MARK}`, "g");
|
|
109
|
+
var ZERO_WIDTH_SPACE = String.fromCharCode(8203);
|
|
110
|
+
var EMPTY_CODE_REGEX = new RegExp(`<code[^>]*>[${ZERO_WIDTH_SPACE}\\s]*</code>`, "gi");
|
|
111
|
+
var ZERO_WIDTH_SPACE_REGEX = new RegExp(ZERO_WIDTH_SPACE, "g");
|
|
106
112
|
function waToHTML(text) {
|
|
107
113
|
if (!text) return "";
|
|
108
114
|
const codeTokens = [];
|
|
@@ -117,7 +123,7 @@ function waToHTML(text) {
|
|
|
117
123
|
let html = escapeHtml(working);
|
|
118
124
|
html = html.replace(/\*([^*\n]+)\*/g, "<strong>$1</strong>");
|
|
119
125
|
html = html.replace(/_([^_\n]+)_/g, "<em>$1</em>");
|
|
120
|
-
html = html.replace(/~([^~\n]+)~/g, "<
|
|
126
|
+
html = html.replace(/~([^~\n]+)~/g, "<s>$1</s>");
|
|
121
127
|
html = html.replace(/\n/g, "<br>");
|
|
122
128
|
html = html.replace(CODE_TOKEN_REGEX, (_match, indexStr) => {
|
|
123
129
|
const token = codeTokens[Number(indexStr)];
|
|
@@ -132,6 +138,7 @@ function waToHTML(text) {
|
|
|
132
138
|
function htmlToWA(html) {
|
|
133
139
|
if (!html) return "";
|
|
134
140
|
let text = html;
|
|
141
|
+
text = text.replace(EMPTY_CODE_REGEX, "");
|
|
135
142
|
text = text.replace(/<code data-wa="block"[^>]*>([\s\S]*?)<\/code>/gi, (_match, inner) => `\`\`\`${unescapeHtml(inner.replace(/<br\s*\/?>/gi, "\n"))}\`\`\``);
|
|
136
143
|
text = text.replace(/<code data-wa="inline"[^>]*>([\s\S]*?)<\/code>/gi, (_match, inner) => `\`${unescapeHtml(inner)}\``);
|
|
137
144
|
text = text.replace(/<br\s*\/?>/gi, "\n").replace(/<div>/gi, "\n").replace(/<\/div>/gi, "").replace(/<\/p>/gi, "\n").replace(/<p[^>]*>/gi, "");
|
|
@@ -141,9 +148,11 @@ function htmlToWA(html) {
|
|
|
141
148
|
text = text.replace(/<i>(.*?)<\/i>/gi, "_$1_");
|
|
142
149
|
text = text.replace(/<del>(.*?)<\/del>/gi, "~$1~");
|
|
143
150
|
text = text.replace(/<s>(.*?)<\/s>/gi, "~$1~");
|
|
151
|
+
text = text.replace(/<strike>(.*?)<\/strike>/gi, "~$1~");
|
|
144
152
|
text = text.replace(/<code[^>]*>(.*?)<\/code>/gi, "`$1`");
|
|
145
153
|
text = text.replace(/<[^>]+>/g, "");
|
|
146
154
|
text = unescapeHtml(text);
|
|
155
|
+
text = text.replace(ZERO_WIDTH_SPACE_REGEX, "");
|
|
147
156
|
return text.trim();
|
|
148
157
|
}
|
|
149
158
|
function waToHTMLInline(text) {
|
|
@@ -205,6 +214,7 @@ function useDarkMode() {
|
|
|
205
214
|
|
|
206
215
|
export {
|
|
207
216
|
parseWhatsAppFormatting,
|
|
217
|
+
ZERO_WIDTH_SPACE,
|
|
208
218
|
waToHTML,
|
|
209
219
|
htmlToWA,
|
|
210
220
|
waToHTMLInline,
|