@adatechnology/conversations-ui 0.1.0-rc.2 → 0.1.0-rc.21
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-ZDURDZTM.js → chunk-2AYDBWNE.js} +14 -0
- package/dist/chunk-TV4OQRGH.js +2187 -0
- package/dist/flows/index.d.ts +14 -2
- package/dist/flows/index.js +117 -39
- package/dist/index.d.ts +862 -136
- package/dist/index.js +1746 -1124
- package/dist/preview/index.d.ts +470 -0
- package/dist/preview/index.js +1329 -0
- package/dist/styles.css +228 -0
- package/dist/types-C6A_9edv.d.ts +456 -0
- package/package.json +10 -3
- package/src/AudioRecorderButton.test.tsx +30 -0
- package/src/AudioRecorderButton.tsx +248 -0
- package/src/AudioTranscription.test.tsx +115 -0
- package/src/AudioTranscription.tsx +249 -0
- package/src/Avatar.tsx +30 -4
- package/src/ChannelIcon.tsx +87 -0
- package/src/ConversationContextPanel.tsx +280 -0
- package/src/ConversationDocumentsPanel.tsx +425 -0
- package/src/ConversationHeader.tsx +257 -0
- package/src/ConversationListItem.tsx +54 -7
- package/src/ConversationLocalesProvider.tsx +44 -0
- package/src/ConversationRow.tsx +137 -0
- package/src/DateDivider.tsx +16 -3
- package/src/DocumentsLibrary.tsx +322 -0
- package/src/EmojiPicker.tsx +69 -55
- package/src/FileIcon.test.ts +83 -0
- package/src/FileIcon.tsx +88 -11
- package/src/InteractiveMessage.test.tsx +41 -0
- package/src/InteractiveMessage.tsx +143 -0
- package/src/Lightbox.tsx +18 -3
- package/src/MediaRenderer.tsx +96 -22
- package/src/MessageBubble.tsx +77 -5
- package/src/MessageComposer.test.tsx +35 -0
- package/src/MessageComposer.tsx +165 -19
- package/src/RichMessageComposer.test.tsx +83 -0
- package/src/RichMessageComposer.tsx +380 -0
- package/src/Wallpaper.test.tsx +21 -0
- package/src/Wallpaper.tsx +69 -7
- package/src/WhatsAppMessageEditor.tsx +28 -4
- package/src/WindowExpiredNotice.tsx +57 -0
- package/src/audioRecorderFormat.test.ts +67 -0
- package/src/conversationChannel.test.ts +53 -0
- package/src/conversationChannel.ts +146 -0
- package/src/conversationTranscript.test.ts +122 -0
- package/src/conversationTranscript.ts +89 -0
- package/src/conversationWindow.test.ts +90 -0
- package/src/conversationWindow.ts +78 -0
- package/src/documentTypeLabel.test.ts +57 -0
- package/src/emojiCatalog.test.ts +35 -0
- package/src/emojiCatalog.ts +189 -0
- package/src/flows/FlowGroupHeader.tsx +12 -2
- package/src/flows/FlowMapCanvas.tsx +17 -14
- package/src/flows/FlowMapNode.tsx +3 -1
- package/src/flows/FlowNodeCard.tsx +22 -4
- package/src/flows/FlowNodePanel.tsx +132 -35
- package/src/flows/FlowPalette.tsx +6 -2
- package/src/flows/FlowWhatsAppPreview.tsx +14 -3
- package/src/flows/flowGraph.ts +5 -5
- package/src/flows/labels.ts +5 -0
- package/src/hooks/useConversationActions.ts +56 -0
- package/src/hooks/useConversationDocuments.ts +15 -9
- package/src/hooks/useConversationList.ts +15 -9
- package/src/hooks/useConversationMessages.ts +2 -2
- package/src/hooks/useScrollToLatestMessage.ts +127 -0
- package/src/index.ts +140 -16
- package/src/lib/cn.test.ts +29 -0
- package/src/lib/cn.ts +15 -0
- package/src/lib/createMediaUrlResolver.ts +33 -0
- package/src/lib/paginated.test.ts +33 -0
- package/src/lib/paginated.ts +26 -0
- package/src/lib/phone.ts +34 -0
- package/src/preview/ConversationPreview.tsx +334 -0
- package/src/preview/MediaTypesPreview.tsx +87 -0
- package/src/preview/conversationPreviewFailures.test.ts +64 -0
- package/src/preview/createMockConversationsApi.ts +271 -0
- package/src/preview/createMockSSEProvider.ts +40 -0
- package/src/preview/createPreviewBridgeClient.test.ts +92 -0
- package/src/preview/createPreviewBridgeClient.ts +124 -0
- package/src/preview/createPreviewMediaUploader.ts +82 -0
- package/src/preview/createPreviewWebhookClient.test.ts +194 -0
- package/src/preview/createPreviewWebhookClient.ts +222 -0
- package/src/preview/index.ts +67 -0
- package/src/preview/mediaTypeOf.test.ts +15 -0
- package/src/preview/mockDocumentsSearch.test.ts +57 -0
- package/src/preview/mockEventSource.ts +53 -0
- package/src/preview/preview.test.ts +177 -0
- package/src/preview/previewFileSamples.test.ts +151 -0
- package/src/preview/previewFileSamples.ts +74 -0
- package/src/preview/previewFixtures.ts +440 -0
- package/src/preview/previewMediaSource.test.ts +62 -0
- package/src/preview/previewMediaSource.ts +91 -0
- package/src/preview/previewMediaUploader.test.ts +61 -0
- package/src/preview/previewStore.ts +193 -0
- package/src/preview/startPreviewScript.ts +60 -0
- package/src/providers/types.ts +175 -12
- package/src/quickReply.test.ts +58 -0
- package/src/settings/TranscriptionSettingsForm.test.tsx +81 -0
- package/src/settings/TranscriptionSettingsForm.tsx +189 -0
- package/src/settings/WhatsAppCreateTemplateForm.tsx +3 -1
- package/src/settings/WhatsAppTemplatesSettings.tsx +106 -0
- package/src/styles.css +173 -0
- package/src/types.ts +72 -1
- package/src/useDarkMode.ts +26 -0
- package/src/useIsNarrow.ts +29 -0
- package/src/useWaitingNotifications.ts +74 -29
package/dist/flows/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
import { NodeProps } from '@xyflow/react';
|
|
3
4
|
import { LucideIcon } from 'lucide-react';
|
|
4
5
|
import { FlowConditionOperator, FlowGraphData, FlowNodeData, FlowNodeType, FlowQuestionType, FlowActionKind } from '@adatechnology/meta-whatsapp-contracts';
|
|
@@ -9,6 +10,7 @@ declare const BUILT_IN_ACTION_KINDS: {
|
|
|
9
10
|
readonly HANDOFF: "handoff";
|
|
10
11
|
readonly RATE_LIMITED_HANDOFF: "rate_limited_handoff";
|
|
11
12
|
readonly SEND_PRODUCT_LIST: "send_product_list";
|
|
13
|
+
readonly SEND_MEDIA: "send_media";
|
|
12
14
|
};
|
|
13
15
|
declare const CROSS_FLOW_PREFIX = "flow:";
|
|
14
16
|
declare const isCrossFlowTarget: (target: string) => boolean;
|
|
@@ -109,6 +111,8 @@ interface FlowEditorLabels {
|
|
|
109
111
|
conditionTrue: string;
|
|
110
112
|
conditionFalse: string;
|
|
111
113
|
conditionVariableMissing: string;
|
|
114
|
+
media: string;
|
|
115
|
+
mediaUnavailable: string;
|
|
112
116
|
};
|
|
113
117
|
palette: {
|
|
114
118
|
title: string;
|
|
@@ -233,14 +237,22 @@ interface FlowNodePanelProps {
|
|
|
233
237
|
onChange: (updated: FlowNodeData) => void;
|
|
234
238
|
onDelete: (nodeId: string) => void;
|
|
235
239
|
labels?: Partial<FlowEditorLabels>;
|
|
240
|
+
/**
|
|
241
|
+
* Seletor de arquivos do nó `send_media`, renderizado no lugar da mensagem direta.
|
|
242
|
+
*
|
|
243
|
+
* Slot, e não uma lista de arquivos por prop, porque a biblioteca é do host: upload, permissão e
|
|
244
|
+
* URL assinada são dele, e o painel não tem como buscar nada. Ausente, o nó continua editável —
|
|
245
|
+
* só não dá para anexar por aqui.
|
|
246
|
+
*/
|
|
247
|
+
renderMediaPicker?: (node: FlowNodeData) => ReactNode;
|
|
236
248
|
}
|
|
237
|
-
declare function FlowNodePanel({ graph, node, issues, otherFlows, onClose, onChange, onDelete, labels: labelsOverride, }: FlowNodePanelProps): react.JSX.Element;
|
|
249
|
+
declare function FlowNodePanel({ graph, node, issues, otherFlows, onClose, onChange, onDelete, labels: labelsOverride, renderMediaPicker, }: FlowNodePanelProps): react.JSX.Element;
|
|
238
250
|
|
|
239
251
|
interface FlowWhatsAppPreviewProps {
|
|
240
252
|
body: string;
|
|
241
253
|
options?: [string, string][];
|
|
242
254
|
labels?: FlowEditorLabels['nodePanel'];
|
|
243
255
|
}
|
|
244
|
-
declare function FlowWhatsAppPreview({ body, options, labels }: FlowWhatsAppPreviewProps): react.JSX.Element;
|
|
256
|
+
declare function FlowWhatsAppPreview({ body, options, labels, }: FlowWhatsAppPreviewProps): react.JSX.Element;
|
|
245
257
|
|
|
246
258
|
export { BUILT_IN_ACTION_KINDS, CONDITION_OPERATORS, CROSS_FLOW_PREFIX, type CollectionChain, DEFAULT_FLOW_EDITOR_LABELS, type FlowEditorLabels, FlowGroupFrame, type FlowGroupFrameData, FlowGroupHeader, type FlowGroupHeaderData, FlowMapCanvas, type FlowMapCanvasProps, FlowMapNode, type FlowMapNodeData, FlowNodeCard, type FlowNodeCardData, FlowNodePanel, type FlowNodePanelProps, FlowPalette, type FlowPaletteActionOption, type FlowPaletteProps, FlowPortalNode, type FlowPortalNodeData, FlowWhatsAppPreview, type FlowWhatsAppPreviewProps, type GraphIssue, NODE_CARD_WIDTH, type NewNodeSpec, WHATSAPP_LIMITS, computeAutoLayout, computeFlowMapLayout, crossFlowKey, crossFlowTargetsOf, estimateNodeHeight, findCollectionChains, flowGroupFrameNodeTypes, flowGroupHeaderNodeTypes, flowMapNodeTypes, flowNodeTypes, flowPortalNodeTypes, isCrossFlowTarget, mergeFlowEditorLabels, nodeLabel, rendersAsButtons, slugifyNodeId, targetsOf, validateGraph };
|
package/dist/flows/index.js
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import {
|
|
2
2
|
parseWhatsAppFormatting,
|
|
3
|
-
|
|
4
|
-
} from "../chunk-
|
|
3
|
+
useIsDarkTheme
|
|
4
|
+
} from "../chunk-2AYDBWNE.js";
|
|
5
5
|
|
|
6
6
|
// src/flows/FlowNodeCard.tsx
|
|
7
7
|
import { Handle, Position } from "@xyflow/react";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
MessageCircleQuestion,
|
|
10
|
+
GitBranch,
|
|
11
|
+
Zap,
|
|
12
|
+
ListTree,
|
|
13
|
+
Diamond,
|
|
14
|
+
AlertTriangle,
|
|
15
|
+
AlertCircle,
|
|
16
|
+
Headset,
|
|
17
|
+
Clock3,
|
|
18
|
+
ShoppingBag
|
|
19
|
+
} from "lucide-react";
|
|
9
20
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
21
|
var NODE_TYPE_COLOR = {
|
|
11
22
|
question: "border-blue-300 bg-blue-50 dark:bg-blue-950/40 dark:border-blue-800",
|
|
@@ -57,7 +68,13 @@ function sourceRows(node, labels) {
|
|
|
57
68
|
}
|
|
58
69
|
function SourceRow({ label, isDefault, handleId }) {
|
|
59
70
|
return /* @__PURE__ */ jsxs("div", { className: "relative flex items-center gap-1.5 rounded-md border border-gray-200 dark:border-gray-600 bg-white/70 dark:bg-gray-900/40 px-2 py-1 pr-3", children: [
|
|
60
|
-
/* @__PURE__ */ jsx(
|
|
71
|
+
/* @__PURE__ */ jsx(
|
|
72
|
+
"span",
|
|
73
|
+
{
|
|
74
|
+
className: `text-xs truncate flex-1 ${isDefault ? "italic text-gray-400 dark:text-gray-500" : "text-gray-700 dark:text-gray-200"}`,
|
|
75
|
+
children: label
|
|
76
|
+
}
|
|
77
|
+
),
|
|
61
78
|
/* @__PURE__ */ jsx(
|
|
62
79
|
Handle,
|
|
63
80
|
{
|
|
@@ -132,7 +149,8 @@ var DEFAULT_FLOW_EDITOR_LABELS = {
|
|
|
132
149
|
actionKindLabels: {
|
|
133
150
|
handoff: "Encaminhar para atendimento",
|
|
134
151
|
rate_limited_handoff: "Encaminhar (limite de simula\xE7\xF5es atingido)",
|
|
135
|
-
send_product_list: "Enviar cat\xE1logo de produtos"
|
|
152
|
+
send_product_list: "Enviar cat\xE1logo de produtos",
|
|
153
|
+
send_media: "Enviar arquivos da biblioteca"
|
|
136
154
|
},
|
|
137
155
|
conditionOperatorLabels: {
|
|
138
156
|
">": "maior que",
|
|
@@ -187,7 +205,9 @@ var DEFAULT_FLOW_EDITOR_LABELS = {
|
|
|
187
205
|
conditionValue: "Valor de compara\xE7\xE3o",
|
|
188
206
|
conditionTrue: "Se verdadeiro \u2192",
|
|
189
207
|
conditionFalse: "Se falso \u2192",
|
|
190
|
-
conditionVariableMissing: "Se a vari\xE1vel ainda n\xE3o foi coletada \u2192"
|
|
208
|
+
conditionVariableMissing: "Se a vari\xE1vel ainda n\xE3o foi coletada \u2192",
|
|
209
|
+
media: "Arquivos enviados neste ponto",
|
|
210
|
+
mediaUnavailable: "A biblioteca de arquivos n\xE3o est\xE1 dispon\xEDvel neste painel."
|
|
191
211
|
},
|
|
192
212
|
palette: {
|
|
193
213
|
title: "Adicionar ao fluxo",
|
|
@@ -266,12 +286,9 @@ import { ReactFlow, Background, Controls, MarkerType } from "@xyflow/react";
|
|
|
266
286
|
import "@xyflow/react/dist/style.css";
|
|
267
287
|
|
|
268
288
|
// src/flows/flowGraph.ts
|
|
289
|
+
import { FLOW_ACTION_KIND } from "@adatechnology/meta-whatsapp-contracts";
|
|
269
290
|
var CONDITION_OPERATORS = [">", ">=", "<", "<=", "==", "!=", "contains"];
|
|
270
|
-
var BUILT_IN_ACTION_KINDS =
|
|
271
|
-
HANDOFF: "handoff",
|
|
272
|
-
RATE_LIMITED_HANDOFF: "rate_limited_handoff",
|
|
273
|
-
SEND_PRODUCT_LIST: "send_product_list"
|
|
274
|
-
};
|
|
291
|
+
var BUILT_IN_ACTION_KINDS = FLOW_ACTION_KIND;
|
|
275
292
|
var CROSS_FLOW_PREFIX = "flow:";
|
|
276
293
|
var isCrossFlowTarget = (target) => target.startsWith(CROSS_FLOW_PREFIX);
|
|
277
294
|
var crossFlowKey = (target) => target.slice(CROSS_FLOW_PREFIX.length);
|
|
@@ -524,21 +541,23 @@ var BACKGROUND_COLOR_LIGHT = "#cbd5e1";
|
|
|
524
541
|
var BACKGROUND_COLOR_DARK = "#334155";
|
|
525
542
|
function FlowMapCanvas({ graphs, rootKey, onOpenFlow, labels: labelsOverride }) {
|
|
526
543
|
const labels = { ...DEFAULT_FLOW_EDITOR_LABELS, ...labelsOverride };
|
|
527
|
-
const
|
|
544
|
+
const isDark = useIsDarkTheme();
|
|
528
545
|
const positions = useMemo(() => computeFlowMapLayout(graphs, rootKey), [graphs, rootKey]);
|
|
529
546
|
const nodes = useMemo(
|
|
530
|
-
() => Object.values(graphs).map(
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
547
|
+
() => Object.values(graphs).map(
|
|
548
|
+
(g) => ({
|
|
549
|
+
id: g.key,
|
|
550
|
+
type: "flowMapNode",
|
|
551
|
+
position: positions[g.key] ?? { x: 0, y: 0 },
|
|
552
|
+
data: {
|
|
553
|
+
label: g.label,
|
|
554
|
+
nodeCount: Object.keys(g.nodes).length,
|
|
555
|
+
isRoot: g.key === rootKey,
|
|
556
|
+
labels,
|
|
557
|
+
onOpen: () => onOpenFlow(g.key)
|
|
558
|
+
}
|
|
559
|
+
})
|
|
560
|
+
),
|
|
542
561
|
[graphs, positions, rootKey, onOpenFlow, labels]
|
|
543
562
|
);
|
|
544
563
|
const edges = useMemo(() => {
|
|
@@ -590,8 +609,26 @@ function FlowGroupHeader({ data }) {
|
|
|
590
609
|
const { label, labels = DEFAULT_FLOW_EDITOR_LABELS, onFocus, onClose } = data;
|
|
591
610
|
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2 rounded-full border border-cyan-300 dark:border-cyan-700 bg-cyan-50 dark:bg-cyan-950/50 px-3 py-1 text-xs font-medium text-cyan-800 dark:text-cyan-200 shadow-sm whitespace-nowrap", children: [
|
|
592
611
|
/* @__PURE__ */ jsx5("span", { children: label }),
|
|
593
|
-
/* @__PURE__ */ jsx5(
|
|
594
|
-
|
|
612
|
+
/* @__PURE__ */ jsx5(
|
|
613
|
+
"button",
|
|
614
|
+
{
|
|
615
|
+
type: "button",
|
|
616
|
+
onClick: onFocus,
|
|
617
|
+
title: labels.flowGroup.focus,
|
|
618
|
+
className: "hover:text-blue-600 dark:hover:text-blue-400",
|
|
619
|
+
children: /* @__PURE__ */ jsx5(Maximize22, { size: 12 })
|
|
620
|
+
}
|
|
621
|
+
),
|
|
622
|
+
/* @__PURE__ */ jsx5(
|
|
623
|
+
"button",
|
|
624
|
+
{
|
|
625
|
+
type: "button",
|
|
626
|
+
onClick: onClose,
|
|
627
|
+
title: labels.flowGroup.close,
|
|
628
|
+
className: "hover:text-red-600 dark:hover:text-red-400",
|
|
629
|
+
children: /* @__PURE__ */ jsx5(X, { size: 12 })
|
|
630
|
+
}
|
|
631
|
+
)
|
|
595
632
|
] });
|
|
596
633
|
}
|
|
597
634
|
var flowGroupHeaderNodeTypes = { flowGroupHeader: FlowGroupHeader };
|
|
@@ -753,7 +790,11 @@ import { Plus as Plus2, Trash2, Save, X as X2, AlertTriangle as AlertTriangle2,
|
|
|
753
790
|
// src/flows/FlowWhatsAppPreview.tsx
|
|
754
791
|
import { List } from "lucide-react";
|
|
755
792
|
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
756
|
-
function FlowWhatsAppPreview({
|
|
793
|
+
function FlowWhatsAppPreview({
|
|
794
|
+
body,
|
|
795
|
+
options,
|
|
796
|
+
labels = DEFAULT_FLOW_EDITOR_LABELS.nodePanel
|
|
797
|
+
}) {
|
|
757
798
|
if (!body && (!options || options.length === 0)) {
|
|
758
799
|
return /* @__PURE__ */ jsx8("p", { className: "text-xs text-gray-400 dark:text-gray-500 italic px-1", children: labels.previewPlaceholder });
|
|
759
800
|
}
|
|
@@ -769,7 +810,14 @@ function FlowWhatsAppPreview({ body, options, labels = DEFAULT_FLOW_EDITOR_LABEL
|
|
|
769
810
|
labels.previewListButton
|
|
770
811
|
] }) })
|
|
771
812
|
] }),
|
|
772
|
-
hasOptions && usesButtons && /* @__PURE__ */ jsx8("div", { className: "mt-1 space-y-1", children: options.map(([id, label]) => /* @__PURE__ */ jsx8(
|
|
813
|
+
hasOptions && usesButtons && /* @__PURE__ */ jsx8("div", { className: "mt-1 space-y-1", children: options.map(([id, label]) => /* @__PURE__ */ jsx8(
|
|
814
|
+
"div",
|
|
815
|
+
{
|
|
816
|
+
className: "rounded-lg bg-white dark:bg-gray-700 py-1.5 text-center text-sm font-medium text-cyan-600 dark:text-cyan-400 shadow-sm",
|
|
817
|
+
children: label || /* @__PURE__ */ jsx8("span", { className: "italic text-gray-400", children: labels.previewEmptyOption })
|
|
818
|
+
},
|
|
819
|
+
id
|
|
820
|
+
)) }),
|
|
773
821
|
hasOptions && !usesButtons && /* @__PURE__ */ jsx8("div", { className: "mt-1.5 rounded-lg bg-white dark:bg-gray-700 shadow-sm divide-y divide-gray-100 dark:divide-gray-600 overflow-hidden", children: options.slice(0, WHATSAPP_LIMITS.MAX_LIST_ROWS).map(([id, label]) => /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 px-3 py-1.5 text-sm text-gray-800 dark:text-gray-100", children: [
|
|
774
822
|
/* @__PURE__ */ jsx8("span", { className: "h-3.5 w-3.5 rounded-full border border-gray-300 dark:border-gray-500 shrink-0" }),
|
|
775
823
|
label || /* @__PURE__ */ jsx8("span", { className: "italic text-gray-400", children: labels.previewEmptyOption })
|
|
@@ -831,17 +879,23 @@ function FlowNodePanel({
|
|
|
831
879
|
onClose,
|
|
832
880
|
onChange,
|
|
833
881
|
onDelete,
|
|
834
|
-
labels: labelsOverride
|
|
882
|
+
labels: labelsOverride,
|
|
883
|
+
renderMediaPicker
|
|
835
884
|
}) {
|
|
836
885
|
const labels = { ...DEFAULT_FLOW_EDITOR_LABELS, ...labelsOverride };
|
|
837
886
|
const [draft, setDraft] = useState2(node);
|
|
838
887
|
const otherNodeIds = Object.keys(graph.nodes).filter((id) => id !== node.id);
|
|
839
888
|
const isFixedLogic = draft.type === "entrada_choice";
|
|
840
889
|
const isAction = draft.type === "action";
|
|
890
|
+
const isSendMedia = isAction && draft.actionKind === BUILT_IN_ACTION_KINDS.SEND_MEDIA;
|
|
841
891
|
const isCondition = draft.type === "condition";
|
|
842
892
|
const isStart = graph.startNodeId === node.id;
|
|
843
893
|
const nodeIssues = issues.filter((i) => i.nodeId === node.id);
|
|
844
|
-
const knownContextKeys = [
|
|
894
|
+
const knownContextKeys = [
|
|
895
|
+
...new Set(
|
|
896
|
+
Object.values(graph.nodes).map((n) => n.contextKey).filter((key) => !!key)
|
|
897
|
+
)
|
|
898
|
+
];
|
|
845
899
|
const conditionAnswerIds = isCondition ? ["true", "false"] : (draft.options ?? []).map(([id]) => id);
|
|
846
900
|
function updateNextString(value) {
|
|
847
901
|
setDraft((prev) => ({ ...prev, next: value }));
|
|
@@ -868,7 +922,10 @@ function FlowNodePanel({
|
|
|
868
922
|
});
|
|
869
923
|
}
|
|
870
924
|
function addOption() {
|
|
871
|
-
setDraft((prev) => ({
|
|
925
|
+
setDraft((prev) => ({
|
|
926
|
+
...prev,
|
|
927
|
+
options: [...prev.options ?? [], [String((prev.options?.length ?? 0) + 1), "Nova op\xE7\xE3o"]]
|
|
928
|
+
}));
|
|
872
929
|
}
|
|
873
930
|
function removeOption(index) {
|
|
874
931
|
setDraft((prev) => ({ ...prev, options: (prev.options ?? []).filter((_, i) => i !== index) }));
|
|
@@ -891,7 +948,14 @@ function FlowNodePanel({
|
|
|
891
948
|
isCondition && /* @__PURE__ */ jsx9("p", { className: "text-xs text-cyan-700 dark:text-cyan-400 bg-cyan-50 dark:bg-cyan-950/30 rounded-lg p-2", children: labels.nodePanel.conditionNotice }),
|
|
892
949
|
draft.contextKey && /* @__PURE__ */ jsxs8("div", { children: [
|
|
893
950
|
/* @__PURE__ */ jsx9("label", { className: "text-xs font-medium text-gray-500 dark:text-gray-400", children: labels.nodePanel.contextKey }),
|
|
894
|
-
/* @__PURE__ */ jsx9(
|
|
951
|
+
/* @__PURE__ */ jsx9(
|
|
952
|
+
"input",
|
|
953
|
+
{
|
|
954
|
+
value: draft.contextKey,
|
|
955
|
+
disabled: true,
|
|
956
|
+
className: "w-full mt-1 rounded-xl border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900 px-3 py-2.5 text-sm text-gray-500"
|
|
957
|
+
}
|
|
958
|
+
)
|
|
895
959
|
] }),
|
|
896
960
|
!isFixedLogic && !isAction && !isCondition && /* @__PURE__ */ jsxs8("div", { children: [
|
|
897
961
|
/* @__PURE__ */ jsx9("label", { className: "text-xs font-medium text-gray-500 dark:text-gray-400", children: labels.nodePanel.questionType }),
|
|
@@ -935,7 +999,10 @@ function FlowNodePanel({
|
|
|
935
999
|
"select",
|
|
936
1000
|
{
|
|
937
1001
|
value: draft.conditionOperator ?? ">",
|
|
938
|
-
onChange: (e) => setDraft((prev) => ({
|
|
1002
|
+
onChange: (e) => setDraft((prev) => ({
|
|
1003
|
+
...prev,
|
|
1004
|
+
conditionOperator: e.target.value
|
|
1005
|
+
})),
|
|
939
1006
|
className: `w-full mt-1 ${SELECT_CLASSNAME}`,
|
|
940
1007
|
children: CONDITION_OPERATORS.map((operator) => /* @__PURE__ */ jsx9("option", { value: operator, children: labels.conditionOperatorLabels[operator] ?? operator }, operator))
|
|
941
1008
|
}
|
|
@@ -963,7 +1030,11 @@ function FlowNodePanel({
|
|
|
963
1030
|
labels
|
|
964
1031
|
}
|
|
965
1032
|
),
|
|
966
|
-
|
|
1033
|
+
isSendMedia && /* @__PURE__ */ jsxs8("div", { children: [
|
|
1034
|
+
/* @__PURE__ */ jsx9("label", { className: "text-xs font-medium text-gray-500 dark:text-gray-400", children: labels.nodePanel.media }),
|
|
1035
|
+
/* @__PURE__ */ jsx9("div", { className: "mt-1", children: renderMediaPicker?.(node) ?? /* @__PURE__ */ jsx9("p", { className: "text-xs text-gray-400", children: labels.nodePanel.mediaUnavailable }) })
|
|
1036
|
+
] }),
|
|
1037
|
+
isAction && draft.actionKind !== "send_product_list" && !isSendMedia && /* @__PURE__ */ jsx9(
|
|
967
1038
|
WhatsAppTextField,
|
|
968
1039
|
{
|
|
969
1040
|
label: labels.nodePanel.directMessage,
|
|
@@ -1053,11 +1124,18 @@ function FlowNodePanel({
|
|
|
1053
1124
|
] })
|
|
1054
1125
|
] }),
|
|
1055
1126
|
/* @__PURE__ */ jsxs8("div", { className: "p-4 border-t border-gray-100 dark:border-gray-700 flex gap-2", children: [
|
|
1056
|
-
/* @__PURE__ */ jsxs8(
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1127
|
+
/* @__PURE__ */ jsxs8(
|
|
1128
|
+
"button",
|
|
1129
|
+
{
|
|
1130
|
+
onClick: () => onChange(draft),
|
|
1131
|
+
className: "flex-1 inline-flex items-center justify-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700",
|
|
1132
|
+
children: [
|
|
1133
|
+
/* @__PURE__ */ jsx9(Save, { size: 14 }),
|
|
1134
|
+
" ",
|
|
1135
|
+
labels.nodePanel.save
|
|
1136
|
+
]
|
|
1137
|
+
}
|
|
1138
|
+
),
|
|
1061
1139
|
!isStart && /* @__PURE__ */ jsx9(
|
|
1062
1140
|
"button",
|
|
1063
1141
|
{
|