@adatechnology/conversations-ui 0.1.0-rc.9 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. package/dist/ConversationSimulatorPanel--5fIzXWY.d.ts +804 -0
  2. package/dist/{chunk-G5BM3VBP.js → chunk-BJNRLLDO.js} +1248 -282
  3. package/dist/chunk-DKPXKQGC.js +110 -0
  4. package/dist/{chunk-2AYDBWNE.js → chunk-WCBDXZ3X.js} +13 -3
  5. package/dist/flows/index.d.ts +422 -5
  6. package/dist/flows/index.js +2502 -676
  7. package/dist/index.d.ts +919 -17
  8. package/dist/index.js +3676 -675
  9. package/dist/preview/index.d.ts +62 -105
  10. package/dist/preview/index.js +162 -284
  11. package/dist/styles.css +893 -0
  12. package/package.json +9 -8
  13. package/src/AudioPlayer.tsx +8 -0
  14. package/src/AudioRecorderButton.test.tsx +30 -0
  15. package/src/AudioRecorderButton.tsx +248 -0
  16. package/src/AudioTranscription.test.tsx +115 -0
  17. package/src/AudioTranscription.tsx +252 -0
  18. package/src/Avatar.tsx +1 -1
  19. package/src/ConversationContextPanel.tsx +218 -44
  20. package/src/ConversationDocumentsPanel.tsx +11 -6
  21. package/src/ConversationHeader.test.tsx +66 -0
  22. package/src/ConversationHeader.tsx +147 -47
  23. package/src/ConversationListItem.tsx +8 -6
  24. package/src/ConversationLocalesProvider.tsx +28 -0
  25. package/src/ConversationRow.tsx +53 -7
  26. package/src/DarkModeToggle.test.tsx +76 -0
  27. package/src/DarkModeToggle.tsx +92 -0
  28. package/src/DocumentsLibrary.tsx +67 -7
  29. package/src/EmojiPicker.tsx +2 -1
  30. package/src/InteractiveMessage.tsx +3 -0
  31. package/src/Lightbox.tsx +1 -1
  32. package/src/MediaRenderer.tsx +88 -15
  33. package/src/MessageBubble.test.tsx +41 -0
  34. package/src/MessageBubble.tsx +47 -5
  35. package/src/MessageComposer.test.tsx +35 -0
  36. package/src/MessageComposer.tsx +122 -17
  37. package/src/MessageText.tsx +2 -1
  38. package/src/MessageTimestamp.tsx +2 -1
  39. package/src/RichMessageComposer.test.tsx +113 -0
  40. package/src/RichMessageComposer.tsx +551 -0
  41. package/src/SimpleEmojiPicker.tsx +5 -3
  42. package/src/StatusTicks.tsx +1 -1
  43. package/src/Toast.tsx +4 -0
  44. package/src/Tooltip.test.ts +42 -0
  45. package/src/Tooltip.tsx +167 -0
  46. package/src/Wallpaper.tsx +27 -13
  47. package/src/WhatsAppMessageEditor.tsx +10 -7
  48. package/src/WindowExpiredNotice.tsx +12 -4
  49. package/src/{preview/audioRecorderFormat.test.ts → audioRecorderFormat.test.ts} +1 -1
  50. package/src/buildOutput.test.ts +79 -0
  51. package/src/composer.constant.ts +33 -0
  52. package/src/conversationTranscript.test.ts +57 -0
  53. package/src/conversationTranscript.ts +29 -4
  54. package/src/conversationWindow.ts +7 -5
  55. package/src/documentTypeLabel.test.ts +57 -0
  56. package/src/documents/DocumentsWorkspace.tsx +550 -0
  57. package/src/documents/index.ts +8 -0
  58. package/src/documents/labels.ts +92 -0
  59. package/src/flows/FlowConnectionEdge.tsx +104 -0
  60. package/src/flows/FlowGroupHeader.tsx +12 -2
  61. package/src/flows/FlowLegend.tsx +125 -0
  62. package/src/flows/FlowMapCanvas.tsx +15 -12
  63. package/src/flows/FlowMapNode.tsx +4 -1
  64. package/src/flows/FlowNodeCard.tsx +219 -34
  65. package/src/flows/FlowNodePanel.tsx +153 -39
  66. package/src/flows/FlowPalette.tsx +156 -70
  67. package/src/flows/FlowPortalNode.tsx +1 -1
  68. package/src/flows/FlowWhatsAppPreview.tsx +14 -3
  69. package/src/flows/FlowsWorkspace.tsx +1255 -0
  70. package/src/flows/flowCanvasModel.test.ts +456 -0
  71. package/src/flows/flowCanvasModel.ts +378 -0
  72. package/src/flows/flowEditorOps.test.ts +276 -0
  73. package/src/flows/flowEditorOps.ts +202 -0
  74. package/src/flows/flowGraph.ts +78 -53
  75. package/src/flows/flowMenuPlacement.test.ts +130 -0
  76. package/src/flows/flowMenuPlacement.ts +86 -0
  77. package/src/flows/index.ts +51 -2
  78. package/src/flows/labels.ts +180 -0
  79. package/src/flows/workspaceContract.test.ts +126 -0
  80. package/src/hooks/useContainerWidth.ts +35 -0
  81. package/src/hooks/useConversationRealtime.ts +10 -8
  82. package/src/hooks/useScrollToLatestMessage.ts +127 -0
  83. package/src/hooks/useUrlFilterState.ts +107 -0
  84. package/src/icon.constant.ts +12 -0
  85. package/src/index.ts +100 -0
  86. package/src/lib/composer-formatting.test.ts +78 -0
  87. package/src/lib/composer-formatting.ts +145 -0
  88. package/src/lib/whatsapp-formatting.test.tsx +37 -0
  89. package/src/lib/whatsapp-formatting.tsx +28 -3
  90. package/src/listing/index.tsx +202 -0
  91. package/src/pagination.constant.ts +10 -0
  92. package/src/preview/ConversationPreview.tsx +84 -45
  93. package/src/preview/ConversationSimulatorClient.ts +143 -0
  94. package/src/preview/ConversationSimulatorPanel.test.tsx +55 -0
  95. package/src/preview/ConversationSimulatorPanel.tsx +131 -0
  96. package/src/preview/createPreviewBridgeClient.test.ts +92 -0
  97. package/src/preview/createPreviewBridgeClient.ts +124 -0
  98. package/src/preview/createPreviewMediaUploader.ts +82 -0
  99. package/src/preview/createPreviewWebhookClient.test.ts +96 -0
  100. package/src/preview/createPreviewWebhookClient.ts +99 -3
  101. package/src/preview/index.ts +36 -2
  102. package/src/preview/previewMediaUploader.test.ts +61 -0
  103. package/src/providers/ConversationsProvider.tsx +8 -6
  104. package/src/providers/types.ts +59 -2
  105. package/src/quickReply.test.ts +58 -0
  106. package/src/replyLatency.test.ts +71 -0
  107. package/src/replyLatency.ts +57 -0
  108. package/src/settings/MessagesWorkspace.tsx +571 -0
  109. package/src/settings/TopicsForm.tsx +2 -0
  110. package/src/settings/TranscriptionSettingsForm.test.tsx +81 -0
  111. package/src/settings/TranscriptionSettingsForm.tsx +190 -0
  112. package/src/settings/WelcomeFarewellForm.tsx +1 -0
  113. package/src/settings/WhatsAppCreateTemplateForm.tsx +1 -0
  114. package/src/settings/WhatsAppTemplateSettingsForm.tsx +5 -2
  115. package/src/settings/WhatsAppTemplatesSettings.test.tsx +61 -0
  116. package/src/settings/WhatsAppTemplatesSettings.tsx +22 -2
  117. package/src/styles.css +858 -0
  118. package/src/theme.ts +13 -0
  119. package/src/types.ts +26 -0
  120. package/src/workspace/BulkTemplateModal.tsx +132 -0
  121. package/src/workspace/ConversationPane.tsx +432 -0
  122. package/src/workspace/ConversationsInboxList.tsx +194 -0
  123. package/src/workspace/ConversationsWorkspace.tsx +423 -0
  124. package/src/workspace/index.ts +17 -0
  125. package/src/workspace/labels.test.ts +17 -0
  126. package/src/workspace/labels.ts +85 -0
  127. package/src/workspace/useConversationsInbox.ts +332 -0
  128. package/dist/types-B5C1DLu1.d.ts +0 -365
  129. package/src/preview/AudioRecorderButton.tsx +0 -117
@@ -0,0 +1,110 @@
1
+ // src/Tooltip.tsx
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { createPortal } from "react-dom";
4
+ import { jsx } from "react/jsx-runtime";
5
+ var TOOLTIP_ATTRIBUTE = "data-cv-tooltip";
6
+ var TOOLTIP_DELAY_MS = 120;
7
+ var TOOLTIP_GAP_PX = 8;
8
+ var TOOLTIP_EDGE_PX = 72;
9
+ function tooltipPositionOf({ targetRect, viewportWidth }) {
10
+ const placement = targetRect.top < TOOLTIP_EDGE_PX ? "bottom" : "top";
11
+ const centerX = targetRect.left + targetRect.width / 2;
12
+ return {
13
+ left: Math.min(Math.max(centerX, TOOLTIP_EDGE_PX), viewportWidth - TOOLTIP_EDGE_PX),
14
+ top: placement === "top" ? targetRect.top - TOOLTIP_GAP_PX : targetRect.bottom + TOOLTIP_GAP_PX,
15
+ placement
16
+ };
17
+ }
18
+ function tooltipStateFor(target, text) {
19
+ const position = tooltipPositionOf({
20
+ targetRect: target.getBoundingClientRect(),
21
+ viewportWidth: window.innerWidth
22
+ });
23
+ return { text, ...position };
24
+ }
25
+ var layerOwner;
26
+ function TooltipLayer() {
27
+ const identity = useRef({});
28
+ const [isOwner, setIsOwner] = useState(false);
29
+ const [tooltip, setTooltip] = useState(void 0);
30
+ useEffect(() => {
31
+ const owned = identity.current;
32
+ if (layerOwner && layerOwner !== owned) return void 0;
33
+ layerOwner = owned;
34
+ setIsOwner(true);
35
+ return () => {
36
+ if (layerOwner === owned) layerOwner = void 0;
37
+ };
38
+ }, []);
39
+ useEffect(() => {
40
+ if (!isOwner) return void 0;
41
+ let timer;
42
+ function cancelPending() {
43
+ if (timer) clearTimeout(timer);
44
+ timer = void 0;
45
+ }
46
+ function hide() {
47
+ cancelPending();
48
+ setTooltip(void 0);
49
+ }
50
+ function handleEnter(event) {
51
+ const origin = event.target;
52
+ if (!(origin instanceof Element)) return;
53
+ const target = origin.closest(`[${TOOLTIP_ATTRIBUTE}]`);
54
+ if (!target) {
55
+ hide();
56
+ return;
57
+ }
58
+ const text = target.getAttribute(TOOLTIP_ATTRIBUTE);
59
+ if (!text) {
60
+ hide();
61
+ return;
62
+ }
63
+ cancelPending();
64
+ timer = setTimeout(() => setTooltip(tooltipStateFor(target, text)), TOOLTIP_DELAY_MS);
65
+ }
66
+ function handleLeaveWindow(event) {
67
+ if (!event.relatedTarget) hide();
68
+ }
69
+ function handleKeyDown(event) {
70
+ if (event.key === "Escape") hide();
71
+ }
72
+ document.addEventListener("pointerover", handleEnter);
73
+ document.addEventListener("pointerout", handleLeaveWindow);
74
+ document.addEventListener("focusin", handleEnter);
75
+ document.addEventListener("pointerdown", hide);
76
+ document.addEventListener("focusout", hide);
77
+ document.addEventListener("keydown", handleKeyDown);
78
+ window.addEventListener("scroll", hide, true);
79
+ window.addEventListener("resize", hide);
80
+ return () => {
81
+ cancelPending();
82
+ document.removeEventListener("pointerover", handleEnter);
83
+ document.removeEventListener("pointerout", handleLeaveWindow);
84
+ document.removeEventListener("focusin", handleEnter);
85
+ document.removeEventListener("pointerdown", hide);
86
+ document.removeEventListener("focusout", hide);
87
+ document.removeEventListener("keydown", handleKeyDown);
88
+ window.removeEventListener("scroll", hide, true);
89
+ window.removeEventListener("resize", hide);
90
+ };
91
+ }, [isOwner]);
92
+ if (!tooltip) return null;
93
+ return createPortal(
94
+ /* @__PURE__ */ jsx(
95
+ "div",
96
+ {
97
+ role: "tooltip",
98
+ className: `cv-tooltip cv-tooltip--${tooltip.placement}`,
99
+ style: { left: tooltip.left, top: tooltip.top },
100
+ children: tooltip.text
101
+ }
102
+ ),
103
+ document.body
104
+ );
105
+ }
106
+
107
+ export {
108
+ TOOLTIP_ATTRIBUTE,
109
+ TooltipLayer
110
+ };
@@ -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 > 0) {
73
- result.push({ type: "text", content: remaining.slice(0, nextSpecial) });
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, "<del>$1</del>");
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,