@inploi/plugin-chatbot 3.10.1 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cdn/index.js +12 -12
- package/dist/{job-application-content-89f9de3b.js → chatbot-body-04c70e40.js} +341 -265
- package/dist/{job-application-content-e3943b85.cjs → chatbot-body-a6d50df4.cjs} +352 -276
- package/dist/chatbot.api.d.ts +2441 -13
- package/dist/chatbot.d.ts +25 -5
- package/dist/chatbot.idb.d.ts +15 -7
- package/dist/chatbot.utils.d.ts +9 -6
- package/dist/{index-8dc9cfab.cjs → index-413f4efe.cjs} +2175 -1912
- package/dist/{index-30bbcd8c.js → index-ec980c39.js} +2194 -1931
- package/dist/index.dev.d.ts +1 -0
- package/dist/interpreter.d.ts +5 -2
- package/dist/plugin-chatbot.cjs +1 -1
- package/dist/plugin-chatbot.js +2 -2
- package/dist/progress.d.ts +11 -0
- package/dist/progress.test.d.ts +1 -0
- package/package.json +8 -6
- package/dist/chatbot.state.d.ts +0 -92
|
@@ -1,31 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const index = require("./index-
|
|
3
|
+
const index = require("./index-413f4efe.cjs");
|
|
4
4
|
require("@inploi/sdk");
|
|
5
|
-
const kbToReadableSize = (kb) => index.N(kb).with(index._.number.lte(1e3), () => `${Math.round(kb)}KB`).with(index._.number.lt(1e3 * 10), () => `${(kb / 1e3).toFixed(1)}MB`).otherwise(() => `${Math.round(kb / 1e3)}MB`);
|
|
6
|
-
const getHeadOrThrow = (nodes) => {
|
|
7
|
-
const head = nodes.find((n2) => n2.isHead);
|
|
8
|
-
if (!head)
|
|
9
|
-
throw new Error("No head node found");
|
|
10
|
-
return head;
|
|
11
|
-
};
|
|
12
|
-
const getApplicationSubmissionsPayload = (submissions) => {
|
|
13
|
-
const payload = Object.entries(submissions).reduce((acc, [key, submission]) => {
|
|
14
|
-
acc[key] = submission.value;
|
|
15
|
-
return acc;
|
|
16
|
-
}, {});
|
|
17
|
-
return payload;
|
|
18
|
-
};
|
|
19
|
-
const isSubmissionOfType = (type) => (submission) => {
|
|
20
|
-
if (!submission)
|
|
21
|
-
return false;
|
|
22
|
-
return submission.type === type;
|
|
23
|
-
};
|
|
24
|
-
class AbortedError extends Error {
|
|
25
|
-
constructor() {
|
|
26
|
-
super("Aborted");
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
5
|
const followNodes = ({
|
|
30
6
|
node,
|
|
31
7
|
nodes,
|
|
@@ -77,7 +53,7 @@ const createFlowInterpreter = ({
|
|
|
77
53
|
onFlowEnd,
|
|
78
54
|
onInterpret
|
|
79
55
|
}) => {
|
|
80
|
-
|
|
56
|
+
let controller = new AbortController();
|
|
81
57
|
const interpretNode = async (node, prevNode) => {
|
|
82
58
|
const submissions = getSubmissions();
|
|
83
59
|
onInterpret == null ? void 0 : onInterpret(node, prevNode);
|
|
@@ -112,16 +88,37 @@ const createFlowInterpreter = ({
|
|
|
112
88
|
end: () => onFlowEnd == null ? void 0 : onFlowEnd(node)
|
|
113
89
|
});
|
|
114
90
|
} catch (e) {
|
|
115
|
-
if (e instanceof AbortedError)
|
|
91
|
+
if (e instanceof index.AbortedError)
|
|
116
92
|
return;
|
|
117
93
|
throw e;
|
|
118
94
|
}
|
|
119
95
|
};
|
|
120
96
|
return {
|
|
121
97
|
interpret: async (startFromNodeId) => {
|
|
122
|
-
const startNode = flow.find((node) => node.id === startFromNodeId) ?? getHeadOrThrow(flow);
|
|
98
|
+
const startNode = flow.find((node) => node.id === startFromNodeId) ?? index.getHeadOrThrow(flow);
|
|
123
99
|
return interpretNode(startNode);
|
|
124
100
|
},
|
|
101
|
+
undo: (nodeHistory) => {
|
|
102
|
+
let removed = 1;
|
|
103
|
+
const formerLastNode = flow.find((n2) => n2.id === nodeHistory[nodeHistory.length - 1]);
|
|
104
|
+
for (let i2 = nodeHistory.length - 2; i2 > 0; i2--) {
|
|
105
|
+
const nodeId = nodeHistory[i2];
|
|
106
|
+
const node = flow.find((n2) => n2.id === nodeId);
|
|
107
|
+
if (!node)
|
|
108
|
+
break;
|
|
109
|
+
removed++;
|
|
110
|
+
if (node.type.startsWith("question-"))
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
controller.abort();
|
|
114
|
+
controller = new AbortController();
|
|
115
|
+
const newStartNode = flow.find((node) => node.id === nodeHistory[nodeHistory.length - removed]);
|
|
116
|
+
index.invariant(newStartNode, "Undo failed: new start node not found");
|
|
117
|
+
interpretNode(newStartNode, formerLastNode);
|
|
118
|
+
return {
|
|
119
|
+
removed
|
|
120
|
+
};
|
|
121
|
+
},
|
|
125
122
|
abort: () => {
|
|
126
123
|
controller.abort();
|
|
127
124
|
}
|
|
@@ -200,22 +197,17 @@ async function interpretSubmitNode({
|
|
|
200
197
|
analytics
|
|
201
198
|
}) {
|
|
202
199
|
await chat.userInput({
|
|
203
|
-
type: "
|
|
200
|
+
type: "submit",
|
|
204
201
|
key: void 0,
|
|
205
202
|
config: {
|
|
206
|
-
|
|
207
|
-
label: "Submit my application",
|
|
208
|
-
value: "submit"
|
|
209
|
-
}],
|
|
210
|
-
maxSelected: 1,
|
|
211
|
-
minSelected: 1
|
|
203
|
+
label: "Submit my application"
|
|
212
204
|
}
|
|
213
205
|
});
|
|
214
206
|
const logApplyComplete = () => {
|
|
215
|
-
const contextJobId = typeof context.
|
|
216
|
-
const contextFlowId = typeof context.
|
|
217
|
-
|
|
218
|
-
|
|
207
|
+
const contextJobId = typeof context.job_id === "string" ? context.job_id : void 0;
|
|
208
|
+
const contextFlowId = typeof context.flow_id === "string" ? context.flow_id : void 0;
|
|
209
|
+
if (!contextJobId || !contextFlowId)
|
|
210
|
+
return;
|
|
219
211
|
if (contextJobId) {
|
|
220
212
|
analytics.log({
|
|
221
213
|
event: "APPLY_COMPLETE",
|
|
@@ -243,7 +235,7 @@ async function interpretSubmitNode({
|
|
|
243
235
|
integration_id: node.data.integrationId,
|
|
244
236
|
anonymous_id,
|
|
245
237
|
session_id,
|
|
246
|
-
submissions:
|
|
238
|
+
submissions: index.getFlowSubmissionsPayload(submissions || {})
|
|
247
239
|
})
|
|
248
240
|
}).catch((e) => e);
|
|
249
241
|
await index.N(response).with({
|
|
@@ -781,7 +773,7 @@ const interpolateString = (str, context) => {
|
|
|
781
773
|
case "file":
|
|
782
774
|
if (!submission.value)
|
|
783
775
|
return "no files";
|
|
784
|
-
return submission.value.map((file) => `${file.name} (${kbToReadableSize(file.sizeKb)})`).join(", ");
|
|
776
|
+
return submission.value.map((file) => `${file.name} (${index.kbToReadableSize(file.sizeKb)})`).join(", ");
|
|
785
777
|
case "multiple-choice":
|
|
786
778
|
return submission.value.join(", ");
|
|
787
779
|
default:
|
|
@@ -814,6 +806,96 @@ const SendButton = ({
|
|
|
814
806
|
})]
|
|
815
807
|
})
|
|
816
808
|
});
|
|
809
|
+
const TYPING_SPEED_MS_PER_CHARACTER = 25;
|
|
810
|
+
const scrollToEndFn$ = index.a({
|
|
811
|
+
instant: () => {
|
|
812
|
+
},
|
|
813
|
+
smooth: () => {
|
|
814
|
+
}
|
|
815
|
+
});
|
|
816
|
+
const chatStore = {
|
|
817
|
+
onSubmitSuccessFn$: index.a(() => {
|
|
818
|
+
}),
|
|
819
|
+
isBotTyping$: index.a(false),
|
|
820
|
+
scrollToEnd: {
|
|
821
|
+
instant: () => scrollToEndFn$.value.instant(),
|
|
822
|
+
smooth: () => scrollToEndFn$.value.smooth()
|
|
823
|
+
}
|
|
824
|
+
};
|
|
825
|
+
const useChatService = () => {
|
|
826
|
+
const chatRef = index._$1(null);
|
|
827
|
+
index.y(() => {
|
|
828
|
+
scrollToEndFn$.value = {
|
|
829
|
+
instant: () => {
|
|
830
|
+
var _a;
|
|
831
|
+
return (_a = chatRef.current) == null ? void 0 : _a.scrollTo({
|
|
832
|
+
top: chatRef.current.scrollHeight,
|
|
833
|
+
behavior: "instant"
|
|
834
|
+
});
|
|
835
|
+
},
|
|
836
|
+
smooth: () => {
|
|
837
|
+
if (!chatRef.current)
|
|
838
|
+
return;
|
|
839
|
+
if (chatRef.current.scrollHeight - chatRef.current.scrollTop <= chatRef.current.clientHeight * 1.5) {
|
|
840
|
+
chatRef.current.scrollTo({
|
|
841
|
+
top: chatRef.current.scrollHeight,
|
|
842
|
+
behavior: "smooth"
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
};
|
|
847
|
+
}, [chatRef]);
|
|
848
|
+
const chatService = index.F(() => ({
|
|
849
|
+
send: async ({
|
|
850
|
+
message,
|
|
851
|
+
signal: signal2,
|
|
852
|
+
groupId
|
|
853
|
+
}) => {
|
|
854
|
+
await index.N(message).with({
|
|
855
|
+
author: "bot",
|
|
856
|
+
type: "text"
|
|
857
|
+
}, async (message2) => {
|
|
858
|
+
if (signal2 == null ? void 0 : signal2.aborted)
|
|
859
|
+
throw new index.AbortedError();
|
|
860
|
+
chatStore.isBotTyping$.value = true;
|
|
861
|
+
const typingTime = Math.min(Math.max(20, message2.text.length), 100) * TYPING_SPEED_MS_PER_CHARACTER;
|
|
862
|
+
await new Promise((resolve) => {
|
|
863
|
+
return setTimeout(resolve, typingTime, {
|
|
864
|
+
signal: signal2
|
|
865
|
+
});
|
|
866
|
+
});
|
|
867
|
+
chatStore.isBotTyping$.value = false;
|
|
868
|
+
}).otherwise(async () => void 0);
|
|
869
|
+
if (signal2 == null ? void 0 : signal2.aborted)
|
|
870
|
+
throw new index.AbortedError();
|
|
871
|
+
index.store.addMessage(message, groupId);
|
|
872
|
+
},
|
|
873
|
+
input: async ({
|
|
874
|
+
input,
|
|
875
|
+
signal: signal2
|
|
876
|
+
}) => {
|
|
877
|
+
if (signal2 == null ? void 0 : signal2.aborted)
|
|
878
|
+
throw new index.AbortedError();
|
|
879
|
+
index.store.setInput(input);
|
|
880
|
+
return await new Promise((resolve) => {
|
|
881
|
+
const submitFunction = (submission) => {
|
|
882
|
+
if (signal2 == null ? void 0 : signal2.aborted)
|
|
883
|
+
throw new index.AbortedError();
|
|
884
|
+
index.store.setInput(void 0);
|
|
885
|
+
if (input.key) {
|
|
886
|
+
index.store.setSubmission(input.key, submission);
|
|
887
|
+
}
|
|
888
|
+
resolve(submission);
|
|
889
|
+
};
|
|
890
|
+
chatStore.onSubmitSuccessFn$.value = submitFunction;
|
|
891
|
+
});
|
|
892
|
+
}
|
|
893
|
+
}), []);
|
|
894
|
+
return {
|
|
895
|
+
chatRef,
|
|
896
|
+
chatService
|
|
897
|
+
};
|
|
898
|
+
};
|
|
817
899
|
const SkipButton = ({
|
|
818
900
|
class: className,
|
|
819
901
|
...props
|
|
@@ -954,7 +1036,7 @@ const toBase64 = (file) => new Promise((resolve, reject) => {
|
|
|
954
1036
|
reader.onerror = reject;
|
|
955
1037
|
});
|
|
956
1038
|
const addFileSizesKb = (files) => files.reduce((acc, cur) => acc + cur.sizeKb, 0);
|
|
957
|
-
const isFileSubmission = isSubmissionOfType("file");
|
|
1039
|
+
const isFileSubmission = index.isSubmissionOfType("file");
|
|
958
1040
|
const FILENAMES_TO_SHOW_QTY = 3;
|
|
959
1041
|
const FileThumbnail = ({
|
|
960
1042
|
file,
|
|
@@ -978,7 +1060,7 @@ const FileThumbnail = ({
|
|
|
978
1060
|
}), index.o("p", {
|
|
979
1061
|
"aria-label": "File size",
|
|
980
1062
|
class: "text-accent-11",
|
|
981
|
-
children: kbToReadableSize(file.sizeKb)
|
|
1063
|
+
children: index.kbToReadableSize(file.sizeKb)
|
|
982
1064
|
})]
|
|
983
1065
|
});
|
|
984
1066
|
};
|
|
@@ -1008,7 +1090,7 @@ const ChatInputFile = ({
|
|
|
1008
1090
|
onHeightChange
|
|
1009
1091
|
}) => {
|
|
1010
1092
|
var _a;
|
|
1011
|
-
const submission = (_a = index.
|
|
1093
|
+
const submission = (_a = index.store.current$.value.flow) == null ? void 0 : _a.data.submissions[input.key];
|
|
1012
1094
|
const [files, setFiles] = index.h(isFileSubmission(submission) && submission.value !== null ? submission.value : []);
|
|
1013
1095
|
const [error, setError] = index.h();
|
|
1014
1096
|
const hiddenFileCount = files.length - FILENAMES_TO_SHOW_QTY;
|
|
@@ -1037,7 +1119,7 @@ const ChatInputFile = ({
|
|
|
1037
1119
|
if (input.config.fileSizeLimitKib && totalSize > input.config.fileSizeLimitKib) {
|
|
1038
1120
|
return setError({
|
|
1039
1121
|
type: "max",
|
|
1040
|
-
message: `File size exceeds limit of ${kbToReadableSize(input.config.fileSizeLimitKib)}`
|
|
1122
|
+
message: `File size exceeds limit of ${index.kbToReadableSize(input.config.fileSizeLimitKib)}`
|
|
1041
1123
|
});
|
|
1042
1124
|
}
|
|
1043
1125
|
if (input.config.allowMultiple === false && files.length > 1)
|
|
@@ -1073,7 +1155,7 @@ const ChatInputFile = ({
|
|
|
1073
1155
|
}) : null]
|
|
1074
1156
|
}), index.o("p", {
|
|
1075
1157
|
class: "text-neutral-11 text-xs",
|
|
1076
|
-
children: [kbToReadableSize(totalSize), " ", files.length > 1 ? "total" : ""]
|
|
1158
|
+
children: [index.kbToReadableSize(totalSize), " ", files.length > 1 ? "total" : ""]
|
|
1077
1159
|
})]
|
|
1078
1160
|
}) : index.o("div", {
|
|
1079
1161
|
class: "flex flex-col justify-center gap-4 pb-6 pt-5",
|
|
@@ -1097,7 +1179,7 @@ const ChatInputFile = ({
|
|
|
1097
1179
|
children: [input.config.allowMultiple ? "Select files" : "Select a file", " to upload"]
|
|
1098
1180
|
}), input.config.fileSizeLimitKib ? index.o("p", {
|
|
1099
1181
|
class: "text-neutral-10 text-xs",
|
|
1100
|
-
children: ["(max ", kbToReadableSize(input.config.fileSizeLimitKib), ")"]
|
|
1182
|
+
children: ["(max ", index.kbToReadableSize(input.config.fileSizeLimitKib), ")"]
|
|
1101
1183
|
}) : null]
|
|
1102
1184
|
}), index.o("aside", {
|
|
1103
1185
|
class: "flex flex-col items-center gap-2",
|
|
@@ -2629,7 +2711,7 @@ const submitIfSingleChecked = (form) => {
|
|
|
2629
2711
|
bubbles: true
|
|
2630
2712
|
}));
|
|
2631
2713
|
};
|
|
2632
|
-
const isMultipleChoiceSubmission = isSubmissionOfType("multiple-choice");
|
|
2714
|
+
const isMultipleChoiceSubmission = index.isSubmissionOfType("multiple-choice");
|
|
2633
2715
|
const getResolver$1 = (config) => {
|
|
2634
2716
|
const length = {
|
|
2635
2717
|
min: config.minSelected ?? 0,
|
|
@@ -2645,7 +2727,8 @@ const ChatInputMultipleChoice = ({
|
|
|
2645
2727
|
onHeightChange
|
|
2646
2728
|
}) => {
|
|
2647
2729
|
var _a, _b;
|
|
2648
|
-
const submission = input.key ? (_a = index.
|
|
2730
|
+
const submission = input.key ? (_a = index.store.current$.value.flow) == null ? void 0 : _a.data.submissions[input.key] : void 0;
|
|
2731
|
+
const isSingleChoice = (input.config.minSelected === 1 || input.config.minSelected === void 0) && input.config.maxSelected === 1;
|
|
2649
2732
|
const {
|
|
2650
2733
|
register,
|
|
2651
2734
|
handleSubmit,
|
|
@@ -2654,12 +2737,11 @@ const ChatInputMultipleChoice = ({
|
|
|
2654
2737
|
}
|
|
2655
2738
|
} = useForm({
|
|
2656
2739
|
defaultValues: {
|
|
2657
|
-
checked: isMultipleChoiceSubmission(submission) ? Object.fromEntries(submission.value.map((key) => [key, true])) : {}
|
|
2740
|
+
checked: isSingleChoice ? {} : isMultipleChoiceSubmission(submission) ? Object.fromEntries(submission.value.map((key) => [key, true])) : {}
|
|
2658
2741
|
},
|
|
2659
2742
|
resolver: getResolver$1(input.config)
|
|
2660
2743
|
});
|
|
2661
2744
|
const focusRef = useFocusOnMount();
|
|
2662
|
-
const isSingleChoice = (input.config.minSelected === 1 || input.config.minSelected === void 0) && input.config.maxSelected === 1;
|
|
2663
2745
|
return index.o("form", {
|
|
2664
2746
|
noValidate: true,
|
|
2665
2747
|
class: "flex flex-col gap-1 pr-2.5",
|
|
@@ -2724,6 +2806,41 @@ const ChatInputMultipleChoice = ({
|
|
|
2724
2806
|
})]
|
|
2725
2807
|
});
|
|
2726
2808
|
};
|
|
2809
|
+
const ChatInputSubmit = ({
|
|
2810
|
+
input,
|
|
2811
|
+
onSubmitSuccess
|
|
2812
|
+
}) => {
|
|
2813
|
+
return index.o("div", {
|
|
2814
|
+
class: "flex flex-col items-center py-3",
|
|
2815
|
+
children: index.o("button", {
|
|
2816
|
+
class: "bg-accent-9 hover:bg-accent-10 active:bg-submit-bg-active hover:border-accent-10 active:border-submit-bg-active border-accent-9 ring-accent-6 focus-visible:outline-accent-8 ring-offset-neutral-1 group flex cursor-pointer rounded-full border border-solid px-5 py-3 pr-4 text-white shadow-[inset_0px_-6px_2px_-1px_oklch(100_0_0/.45),inset_0px_1px_1px_oklch(100_0_0/.3)] outline-none ring-1 ring-offset-[1.5px] transition-all duration-300 focus-visible:outline-2 active:shadow-[inset_0px_0px_2px_-1px_oklch(100_0_0/.45),inset_0px_3px_1px_.5px_oklch(0_0_0/.08)] active:ring-2 active:ring-offset-2",
|
|
2817
|
+
name: input.key,
|
|
2818
|
+
onClick: () => {
|
|
2819
|
+
onSubmitSuccess(null);
|
|
2820
|
+
},
|
|
2821
|
+
children: index.o("span", {
|
|
2822
|
+
class: "relative bottom-[2px] top-[-2px] flex items-center gap-1.5 transition-all duration-300 group-active:bottom-0 group-active:top-0",
|
|
2823
|
+
children: [index.o("span", {
|
|
2824
|
+
class: "inline-flex items-center text-sm font-medium",
|
|
2825
|
+
children: input.config.label
|
|
2826
|
+
}), index.o("svg", {
|
|
2827
|
+
stroke: "currentColor",
|
|
2828
|
+
"stroke-width": "1.5",
|
|
2829
|
+
width: "16",
|
|
2830
|
+
height: "16",
|
|
2831
|
+
viewBox: "0 0 16 16",
|
|
2832
|
+
fill: "none",
|
|
2833
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2834
|
+
children: [index.o("path", {
|
|
2835
|
+
d: "M4 8L8 4L12 8"
|
|
2836
|
+
}), index.o("path", {
|
|
2837
|
+
d: "M8 4V13"
|
|
2838
|
+
})]
|
|
2839
|
+
})]
|
|
2840
|
+
})
|
|
2841
|
+
})
|
|
2842
|
+
});
|
|
2843
|
+
};
|
|
2727
2844
|
const errors = {
|
|
2728
2845
|
empty: "Please enter some text",
|
|
2729
2846
|
email: "That doesn’t look like a valid email address",
|
|
@@ -2751,7 +2868,7 @@ const inputFormatToProps = {
|
|
|
2751
2868
|
formNoValidate: true
|
|
2752
2869
|
}
|
|
2753
2870
|
};
|
|
2754
|
-
const isTextSubmission = isSubmissionOfType("text");
|
|
2871
|
+
const isTextSubmission = index.isSubmissionOfType("text");
|
|
2755
2872
|
const getResolver = (config) => i(index.object({
|
|
2756
2873
|
text: {
|
|
2757
2874
|
email: index.string(errors.email, [index.email(errors.email)]),
|
|
@@ -2766,7 +2883,7 @@ const ChatInputText = ({
|
|
|
2766
2883
|
onHeightChange
|
|
2767
2884
|
}) => {
|
|
2768
2885
|
var _a;
|
|
2769
|
-
const submission = input.key ? (_a = index.
|
|
2886
|
+
const submission = input.key ? (_a = index.store.current$.value.flow) == null ? void 0 : _a.data.submissions[input.key] : void 0;
|
|
2770
2887
|
const defaultValue = input.config.defaultValue;
|
|
2771
2888
|
const {
|
|
2772
2889
|
register,
|
|
@@ -2832,22 +2949,19 @@ const ChatInputText = ({
|
|
|
2832
2949
|
})
|
|
2833
2950
|
});
|
|
2834
2951
|
};
|
|
2835
|
-
const ChatInput = ({
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
input
|
|
2839
|
-
}) => {
|
|
2952
|
+
const ChatInput = () => {
|
|
2953
|
+
var _a;
|
|
2954
|
+
const input = (_a = index.store.current$.value.flow) == null ? void 0 : _a.data.currentInput;
|
|
2840
2955
|
const inputWrapperRef = index._$1(null);
|
|
2841
2956
|
const updateHeight = index.T(() => {
|
|
2842
2957
|
if (inputWrapperRef.current) {
|
|
2843
|
-
index.inputHeight
|
|
2958
|
+
index.store.inputHeight$.value = inputWrapperRef.current.getBoundingClientRect().height;
|
|
2844
2959
|
}
|
|
2845
2960
|
}, []);
|
|
2846
2961
|
index.p(() => {
|
|
2847
2962
|
updateHeight();
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
const handleSubmitSuccess = (type) => (value) => onSubmit({
|
|
2963
|
+
}, [input == null ? void 0 : input.type, updateHeight]);
|
|
2964
|
+
const handleSubmitSuccess = (type) => (value) => chatStore.onSubmitSuccessFn$.value({
|
|
2851
2965
|
type,
|
|
2852
2966
|
value
|
|
2853
2967
|
});
|
|
@@ -2856,18 +2970,19 @@ const ChatInput = ({
|
|
|
2856
2970
|
height: 0
|
|
2857
2971
|
},
|
|
2858
2972
|
animate: {
|
|
2859
|
-
height: index.inputHeight
|
|
2973
|
+
height: index.store.inputHeight$.value
|
|
2860
2974
|
},
|
|
2861
2975
|
exit: {
|
|
2862
2976
|
height: 0,
|
|
2863
2977
|
opacity: 0
|
|
2864
2978
|
},
|
|
2979
|
+
onAnimationStart: chatStore.scrollToEnd.smooth,
|
|
2980
|
+
onAnimationComplete: chatStore.scrollToEnd.smooth,
|
|
2865
2981
|
class: "bg-statusbar absolute bottom-0 w-full overflow-hidden rounded-b-3xl backdrop-blur-md backdrop-saturate-150",
|
|
2866
2982
|
children: index.o("div", {
|
|
2867
2983
|
ref: inputWrapperRef,
|
|
2868
2984
|
class: "border-divider border-t",
|
|
2869
2985
|
children: index.N({
|
|
2870
|
-
application: index.application,
|
|
2871
2986
|
input,
|
|
2872
2987
|
onHeightChange: updateHeight
|
|
2873
2988
|
}).with({
|
|
@@ -2912,6 +3027,13 @@ const ChatInput = ({
|
|
|
2912
3027
|
}, (props) => index.o(ChatInputFile, {
|
|
2913
3028
|
onSubmitSuccess: handleSubmitSuccess(props.input.type),
|
|
2914
3029
|
...props
|
|
3030
|
+
})).with({
|
|
3031
|
+
input: {
|
|
3032
|
+
type: "submit"
|
|
3033
|
+
}
|
|
3034
|
+
}, (props) => index.o(ChatInputSubmit, {
|
|
3035
|
+
onSubmitSuccess: handleSubmitSuccess(props.input.type),
|
|
3036
|
+
...props
|
|
2915
3037
|
})).exhaustive()
|
|
2916
3038
|
})
|
|
2917
3039
|
});
|
|
@@ -2960,7 +3082,7 @@ const cva = (base, config) => {
|
|
|
2960
3082
|
return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className);
|
|
2961
3083
|
};
|
|
2962
3084
|
};
|
|
2963
|
-
const chatBubbleVariants = cva("max-w-[min(100%,24rem)] [text-wrap:pretty] leading-snug flex-shrink min-w-[2rem] py-2 px-3 rounded-[18px] min-h-[36px] break-words", {
|
|
3085
|
+
const chatBubbleVariants = cva("max-w-[min(100%,24rem)] [text-wrap:pretty] leading-snug flex-shrink min-w-[2rem] py-2 px-3 rounded-[18px] min-h-[36px] break-words relative", {
|
|
2964
3086
|
variants: {
|
|
2965
3087
|
side: {
|
|
2966
3088
|
left: "bg-bubble-weak-bg text-neutral-12 shadow-surface-sm outline outline-1 outline-bubble-weak rounded-bl-md",
|
|
@@ -3020,18 +3142,24 @@ const TypingIndicator = ({
|
|
|
3020
3142
|
className,
|
|
3021
3143
|
...props
|
|
3022
3144
|
}) => {
|
|
3145
|
+
index.p(() => {
|
|
3146
|
+
chatStore.scrollToEnd.smooth();
|
|
3147
|
+
});
|
|
3023
3148
|
return index.o("div", {
|
|
3024
|
-
"aria-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3149
|
+
"aria-hidden": true,
|
|
3150
|
+
children: chatStore.isBotTyping$.value === true ? index.o("div", {
|
|
3151
|
+
"aria-label": "Typing…",
|
|
3152
|
+
class: index.clsx("flex gap-1 p-4", className),
|
|
3153
|
+
...props,
|
|
3154
|
+
children: Array.from({
|
|
3155
|
+
length: 3
|
|
3156
|
+
}, (_, i2) => index.o("div", {
|
|
3157
|
+
class: "bg-accent-9 h-1.5 w-1.5 animate-bounce rounded-full",
|
|
3158
|
+
style: {
|
|
3159
|
+
animationDelay: `${-i2 * 200}ms`
|
|
3160
|
+
}
|
|
3161
|
+
}))
|
|
3162
|
+
}) : void 0
|
|
3035
3163
|
});
|
|
3036
3164
|
};
|
|
3037
3165
|
const authorToSide = {
|
|
@@ -3049,213 +3177,131 @@ const systemMessageStyle = cva("w-full select-none py-2 text-wrap-balance text-c
|
|
|
3049
3177
|
}
|
|
3050
3178
|
});
|
|
3051
3179
|
const Conversation = ({
|
|
3052
|
-
|
|
3053
|
-
isBotTyping
|
|
3180
|
+
lastSentMessageFooter
|
|
3054
3181
|
}) => {
|
|
3182
|
+
var _a;
|
|
3183
|
+
const messages = ((_a = index.store.current$.value.flow) == null ? void 0 : _a.data.messages) ?? [];
|
|
3184
|
+
index.p(() => {
|
|
3185
|
+
chatStore.scrollToEnd.smooth();
|
|
3186
|
+
}, [messages.length]);
|
|
3055
3187
|
return index.o("ol", {
|
|
3056
3188
|
"aria-label": "Chat messages",
|
|
3057
3189
|
class: "flex flex-col justify-end gap-2 p-2 pt-[calc(var(--header-height)+1rem)]",
|
|
3058
3190
|
children: [index.o(index.AnimatePresence, {
|
|
3059
3191
|
initial: false,
|
|
3060
|
-
children: messages.map((message, i2) =>
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3192
|
+
children: messages.map((message, i2) => {
|
|
3193
|
+
return index.o(index.k, {
|
|
3194
|
+
children: index.o("li", {
|
|
3195
|
+
class: "flex",
|
|
3196
|
+
children: index.N(message).with({
|
|
3197
|
+
type: "system"
|
|
3198
|
+
}, (message2) => index.o("p", {
|
|
3199
|
+
class: systemMessageStyle({
|
|
3200
|
+
variant: message2.variant
|
|
3201
|
+
}),
|
|
3202
|
+
children: message2.text
|
|
3203
|
+
})).with({
|
|
3204
|
+
type: "text",
|
|
3205
|
+
author: index._.union("bot", "user")
|
|
3206
|
+
}, (message2) => {
|
|
3207
|
+
const isLastSentMessage = message2.author === "user" && !messages.slice(i2 + 1).some((m) => m.type === "text" && m.author === "user");
|
|
3208
|
+
return index.o(ChatBubble, {
|
|
3209
|
+
side: authorToSide[message2.author],
|
|
3210
|
+
children: [message2.text, isLastSentMessage ? lastSentMessageFooter : null]
|
|
3211
|
+
}, i2);
|
|
3212
|
+
}).with({
|
|
3213
|
+
type: "link"
|
|
3214
|
+
}, (message2) => {
|
|
3215
|
+
return index.o("div", {
|
|
3216
|
+
class: "bg-accent-3 flex w-full items-center justify-center overflow-hidden rounded-xl px-2 py-2",
|
|
3217
|
+
children: index.o("a", {
|
|
3218
|
+
class: "bg-lowest shadow-surface-sm ring-accent-6 hover:ring-accent-8 active:bg-accent-2 active:text-accent-10 text-accent-9 focus-visible:ring-accent-7/50 text-wrap-balance flex items-center gap-1.5 rounded-full py-2 pl-4 pr-2.5 text-center no-underline ring-1 transition-all focus:outline-none focus-visible:ring-4 focus-visible:ring-offset-2",
|
|
3219
|
+
target: "_blank",
|
|
3220
|
+
href: message2.href,
|
|
3221
|
+
children: [message2.text, index.o("svg", {
|
|
3222
|
+
class: "flex-none",
|
|
3223
|
+
width: "15",
|
|
3224
|
+
height: "15",
|
|
3225
|
+
viewBox: "0 0 15 15",
|
|
3226
|
+
fill: "none",
|
|
3227
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3228
|
+
children: index.o("path", {
|
|
3229
|
+
d: "M3.64645 11.3536C3.45118 11.1583 3.45118 10.8417 3.64645 10.6465L10.2929 4L6 4C5.72386 4 5.5 3.77614 5.5 3.5C5.5 3.22386 5.72386 3 6 3L11.5 3C11.6326 3 11.7598 3.05268 11.8536 3.14645C11.9473 3.24022 12 3.36739 12 3.5L12 9.00001C12 9.27615 11.7761 9.50001 11.5 9.50001C11.2239 9.50001 11 9.27615 11 9.00001V4.70711L4.35355 11.3536C4.15829 11.5488 3.84171 11.5488 3.64645 11.3536Z",
|
|
3230
|
+
fill: "currentColor",
|
|
3231
|
+
"fill-rule": "evenodd",
|
|
3232
|
+
"clip-rule": "evenodd"
|
|
3233
|
+
})
|
|
3234
|
+
})]
|
|
3098
3235
|
})
|
|
3099
|
-
})
|
|
3100
|
-
})
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
}
|
|
3119
|
-
})
|
|
3120
|
-
})
|
|
3121
|
-
}
|
|
3122
|
-
}), index.o(
|
|
3123
|
-
"aria-hidden": true,
|
|
3124
|
-
children: isBotTyping && index.o(TypingIndicator, {})
|
|
3125
|
-
})]
|
|
3236
|
+
});
|
|
3237
|
+
}).with({
|
|
3238
|
+
type: "image"
|
|
3239
|
+
}, (image) => index.o("img", {
|
|
3240
|
+
class: "shadow-surface-md w-full max-w-[min(100%,24rem)] rounded-2xl",
|
|
3241
|
+
src: image.url,
|
|
3242
|
+
style: {
|
|
3243
|
+
aspectRatio: image.width / image.height
|
|
3244
|
+
}
|
|
3245
|
+
})).with({
|
|
3246
|
+
type: "file"
|
|
3247
|
+
}, (file) => {
|
|
3248
|
+
return index.o(FileThumbnail, {
|
|
3249
|
+
class: file.author === "bot" ? "" : "ml-auto",
|
|
3250
|
+
file: {
|
|
3251
|
+
name: file.fileName,
|
|
3252
|
+
sizeKb: file.fileSizeKb
|
|
3253
|
+
}
|
|
3254
|
+
});
|
|
3255
|
+
}).exhaustive()
|
|
3256
|
+
})
|
|
3257
|
+
}, i2);
|
|
3258
|
+
})
|
|
3259
|
+
}), index.o(TypingIndicator, {}, "typing")]
|
|
3126
3260
|
});
|
|
3127
3261
|
};
|
|
3128
|
-
const
|
|
3129
|
-
const useChatService = () => {
|
|
3130
|
-
const chatRef = index._$1(null);
|
|
3131
|
-
const [isBotTyping, setIsBotTyping] = index.h(false);
|
|
3132
|
-
const [onSubmitSuccessFn, setOnSubmitSuccessFn] = index.h(() => () => {
|
|
3133
|
-
});
|
|
3134
|
-
const scrollToEnd = index.F(() => (options2) => {
|
|
3135
|
-
var _a;
|
|
3136
|
-
return (_a = chatRef.current) == null ? void 0 : _a.scrollTo({
|
|
3137
|
-
top: chatRef.current.scrollHeight,
|
|
3138
|
-
...options2
|
|
3139
|
-
});
|
|
3140
|
-
}, [chatRef]);
|
|
3141
|
-
const chatService = index.F(() => ({
|
|
3142
|
-
send: async ({
|
|
3143
|
-
message,
|
|
3144
|
-
signal,
|
|
3145
|
-
groupId
|
|
3146
|
-
}) => {
|
|
3147
|
-
await index.N(message).with({
|
|
3148
|
-
author: "bot",
|
|
3149
|
-
type: "text"
|
|
3150
|
-
}, async (message2) => {
|
|
3151
|
-
if (signal == null ? void 0 : signal.aborted)
|
|
3152
|
-
throw new AbortedError();
|
|
3153
|
-
setIsBotTyping(true);
|
|
3154
|
-
const typingTime = Math.min(Math.max(20, message2.text.length), 100) * TYPING_SPEED_MS_PER_CHARACTER;
|
|
3155
|
-
await new Promise((resolve) => {
|
|
3156
|
-
return setTimeout(resolve, typingTime, {
|
|
3157
|
-
signal
|
|
3158
|
-
});
|
|
3159
|
-
});
|
|
3160
|
-
setIsBotTyping(false);
|
|
3161
|
-
}).otherwise(async () => void 0);
|
|
3162
|
-
if (signal == null ? void 0 : signal.aborted)
|
|
3163
|
-
throw new AbortedError();
|
|
3164
|
-
index.application.addMessage(message, groupId);
|
|
3165
|
-
},
|
|
3166
|
-
input: async ({
|
|
3167
|
-
input,
|
|
3168
|
-
signal
|
|
3169
|
-
}) => {
|
|
3170
|
-
if (signal == null ? void 0 : signal.aborted)
|
|
3171
|
-
throw new AbortedError();
|
|
3172
|
-
index.application.setInput(input);
|
|
3173
|
-
return await new Promise((resolve) => {
|
|
3174
|
-
const submitFunction = (submission) => {
|
|
3175
|
-
if (signal == null ? void 0 : signal.aborted)
|
|
3176
|
-
throw new AbortedError();
|
|
3177
|
-
index.application.setInput(void 0);
|
|
3178
|
-
if (input.key) {
|
|
3179
|
-
index.application.setSubmission;
|
|
3180
|
-
index.application.setSubmission(input.key, submission);
|
|
3181
|
-
}
|
|
3182
|
-
resolve(submission);
|
|
3183
|
-
};
|
|
3184
|
-
setOnSubmitSuccessFn(() => submitFunction);
|
|
3185
|
-
});
|
|
3186
|
-
}
|
|
3187
|
-
}), []);
|
|
3188
|
-
return {
|
|
3189
|
-
chatRef,
|
|
3190
|
-
chatService,
|
|
3191
|
-
isBotTyping,
|
|
3192
|
-
onSubmitSuccessFn,
|
|
3193
|
-
scrollToEnd
|
|
3194
|
-
};
|
|
3195
|
-
};
|
|
3196
|
-
const JobApplicationContent = ({
|
|
3197
|
-
currentApplication,
|
|
3262
|
+
const ChatbotBody = ({
|
|
3198
3263
|
logger,
|
|
3199
3264
|
apiClient,
|
|
3200
3265
|
analytics
|
|
3201
3266
|
}) => {
|
|
3267
|
+
const {
|
|
3268
|
+
flow
|
|
3269
|
+
} = index.store.current$.value;
|
|
3270
|
+
index.invariant(flow, "Flow is required to exist to show chatbot body");
|
|
3271
|
+
const view = index.store.viewState$.value;
|
|
3202
3272
|
const {
|
|
3203
3273
|
chatRef,
|
|
3204
|
-
chatService
|
|
3205
|
-
isBotTyping,
|
|
3206
|
-
onSubmitSuccessFn,
|
|
3207
|
-
scrollToEnd
|
|
3274
|
+
chatService
|
|
3208
3275
|
} = useChatService();
|
|
3209
|
-
const
|
|
3210
|
-
const flow = currentApplication.flow;
|
|
3211
|
-
const job = currentApplication.job;
|
|
3276
|
+
const [undoFn, setUndoFn] = index.h();
|
|
3212
3277
|
index.y(() => {
|
|
3213
3278
|
if (view === "maximised")
|
|
3214
|
-
scrollToEnd(
|
|
3215
|
-
|
|
3216
|
-
});
|
|
3217
|
-
}, [scrollToEnd, view]);
|
|
3218
|
-
index.p(() => {
|
|
3219
|
-
scrollToEnd({
|
|
3220
|
-
behavior: "smooth"
|
|
3221
|
-
});
|
|
3222
|
-
}, [currentApplication.data.messages, scrollToEnd]);
|
|
3279
|
+
chatStore.scrollToEnd.instant();
|
|
3280
|
+
}, [view]);
|
|
3223
3281
|
index.y(() => {
|
|
3224
3282
|
const {
|
|
3225
3283
|
state,
|
|
3226
|
-
|
|
3227
|
-
} = index.
|
|
3284
|
+
flow: currentApplication
|
|
3285
|
+
} = index.store.current$.peek();
|
|
3228
3286
|
if (state !== "loaded")
|
|
3229
3287
|
throw new Error(index.ERROR_MESSAGES.invalid_state);
|
|
3230
|
-
let fromNodeId =
|
|
3231
|
-
scrollToEnd(
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
index.application.setInput(void 0);
|
|
3235
|
-
if (currentApplication2.data.isFinished)
|
|
3288
|
+
let fromNodeId = currentApplication.data.nodeHistory.at(-1);
|
|
3289
|
+
chatStore.scrollToEnd.instant();
|
|
3290
|
+
index.store.setInput(void 0);
|
|
3291
|
+
if (currentApplication.data.isFinished)
|
|
3236
3292
|
return;
|
|
3237
|
-
if (fromNodeId ===
|
|
3238
|
-
fromNodeId = getHeadOrThrow(flow.nodes).id;
|
|
3239
|
-
index.
|
|
3240
|
-
analytics.log({
|
|
3241
|
-
event: "APPLY_START",
|
|
3242
|
-
attributionKey: `job_${job.id}`,
|
|
3243
|
-
properties: {
|
|
3244
|
-
job_id: job.id,
|
|
3245
|
-
flow_id: flow.id
|
|
3246
|
-
}
|
|
3247
|
-
});
|
|
3293
|
+
if (fromNodeId === void 0) {
|
|
3294
|
+
fromNodeId = index.getHeadOrThrow(flow.nodes).id;
|
|
3295
|
+
index.store.setCurrentNodeId(fromNodeId);
|
|
3248
3296
|
} else {
|
|
3249
|
-
index.
|
|
3297
|
+
index.store.removeMessagesSentByNodeIds([fromNodeId]);
|
|
3250
3298
|
}
|
|
3251
3299
|
const {
|
|
3252
3300
|
interpret: interpret2,
|
|
3253
|
-
abort
|
|
3301
|
+
abort,
|
|
3302
|
+
undo
|
|
3254
3303
|
} = createFlowInterpreter({
|
|
3255
|
-
context:
|
|
3256
|
-
jobId: job.id,
|
|
3257
|
-
flowId: flow.id
|
|
3258
|
-
},
|
|
3304
|
+
context: flow.context,
|
|
3259
3305
|
analytics,
|
|
3260
3306
|
apiClient,
|
|
3261
3307
|
logger,
|
|
@@ -3264,57 +3310,87 @@ const JobApplicationContent = ({
|
|
|
3264
3310
|
// We need to get fresh submissions, that’s why we call `peek` here.
|
|
3265
3311
|
getSubmissions: () => {
|
|
3266
3312
|
var _a;
|
|
3267
|
-
return (_a = index.
|
|
3313
|
+
return (_a = index.store.current$.peek().flow) == null ? void 0 : _a.data.submissions;
|
|
3268
3314
|
},
|
|
3269
3315
|
onInterpret: (node, prevNode) => {
|
|
3270
|
-
const currentState = index.
|
|
3316
|
+
const currentState = index.store.current$.peek().flow;
|
|
3271
3317
|
index.invariant(currentState);
|
|
3272
3318
|
if (prevNode) {
|
|
3273
3319
|
currentState.data.sequence = currentState.data.sequence + 1;
|
|
3274
3320
|
analytics.log({
|
|
3275
3321
|
event: "FLOW_NODE",
|
|
3276
|
-
attributionKey: `job_${job.id}`,
|
|
3277
3322
|
properties: {
|
|
3278
3323
|
flow_id: flow.id,
|
|
3279
3324
|
flow_version: flow.version,
|
|
3280
|
-
job_id: job.id,
|
|
3281
3325
|
from_node_id: prevNode.id,
|
|
3282
3326
|
to_node_id: node.id,
|
|
3283
3327
|
sequence: currentState.data.sequence,
|
|
3284
3328
|
flow_session_id: currentState.data.flowSessionId
|
|
3285
|
-
}
|
|
3329
|
+
},
|
|
3330
|
+
customProperties: flow.context
|
|
3286
3331
|
});
|
|
3287
3332
|
}
|
|
3288
|
-
index.
|
|
3333
|
+
index.store.setCurrentNodeId(node.id);
|
|
3289
3334
|
},
|
|
3290
3335
|
onFlowEnd: async () => {
|
|
3291
|
-
index.
|
|
3336
|
+
index.store.markAsFinished();
|
|
3292
3337
|
}
|
|
3293
3338
|
});
|
|
3339
|
+
setUndoFn(() => undo);
|
|
3294
3340
|
interpret2(fromNodeId);
|
|
3295
3341
|
return abort;
|
|
3296
|
-
}, [analytics, apiClient, chatService, logger,
|
|
3342
|
+
}, [analytics, apiClient, chatService, logger, flow]);
|
|
3297
3343
|
return index.o(index.k, {
|
|
3298
3344
|
children: [index.o("div", {
|
|
3299
3345
|
ref: chatRef,
|
|
3300
|
-
className: "hide-scrollbars relative flex max-w-full flex-grow flex-col overflow-y-scroll",
|
|
3346
|
+
className: "hide-scrollbars relative flex w-full max-w-full flex-grow flex-col overflow-y-scroll",
|
|
3301
3347
|
style: {
|
|
3302
3348
|
WebkitOverflowScrolling: "touch",
|
|
3303
|
-
paddingBottom: index.inputHeight
|
|
3349
|
+
paddingBottom: index.store.inputHeight$.value
|
|
3304
3350
|
},
|
|
3305
|
-
children: index.o(
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
messages: currentApplication.data.messages
|
|
3351
|
+
children: index.o(Conversation, {
|
|
3352
|
+
lastSentMessageFooter: flow.data.isFinished || !undoFn ? null : index.o(UndoButton, {
|
|
3353
|
+
undoFn
|
|
3309
3354
|
})
|
|
3310
3355
|
})
|
|
3311
|
-
}), index.o(ChatInput, {
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3356
|
+
}), index.o(ChatInput, {})]
|
|
3357
|
+
});
|
|
3358
|
+
};
|
|
3359
|
+
const getNodeKeys = (node) => {
|
|
3360
|
+
if ("key" in node.data && node.data.key)
|
|
3361
|
+
return [node.data.key];
|
|
3362
|
+
if ("keys" in node.data)
|
|
3363
|
+
return Object.values(node.data.keys).filter((key) => typeof key === "string");
|
|
3364
|
+
return [];
|
|
3365
|
+
};
|
|
3366
|
+
const UndoButton = ({
|
|
3367
|
+
undoFn
|
|
3368
|
+
}) => {
|
|
3369
|
+
return index.o("div", {
|
|
3370
|
+
class: "absolute bottom-0 right-0 flex w-full translate-y-full justify-end",
|
|
3371
|
+
children: index.o("button", {
|
|
3372
|
+
class: "fr touch-hitbox text-neutral-9 hover:text-neutral-12 rounded-full p-1 text-right text-xs transition-all",
|
|
3373
|
+
onClick: async () => {
|
|
3374
|
+
const {
|
|
3375
|
+
flow
|
|
3376
|
+
} = index.store.current$.peek();
|
|
3377
|
+
index.invariant(flow);
|
|
3378
|
+
const {
|
|
3379
|
+
removed
|
|
3380
|
+
} = undoFn(flow.data.nodeHistory);
|
|
3381
|
+
const removedNodeIds = flow.data.nodeHistory.splice(-removed);
|
|
3382
|
+
if (removedNodeIds.length === 0)
|
|
3383
|
+
return;
|
|
3384
|
+
index.store.removeMessagesSentByNodeIds(removedNodeIds);
|
|
3385
|
+
index.store.setInput(void 0);
|
|
3386
|
+
removedNodeIds.pop();
|
|
3387
|
+
removedNodeIds.map((nodeId) => flow.nodes.find((node) => node.id === nodeId)).filter(Boolean).flatMap(getNodeKeys).forEach((key) => delete flow.data.submissions[key]);
|
|
3388
|
+
index.store.current$.value = {
|
|
3389
|
+
...index.store.current$.value
|
|
3390
|
+
};
|
|
3391
|
+
},
|
|
3392
|
+
children: "Undo"
|
|
3393
|
+
})
|
|
3318
3394
|
});
|
|
3319
3395
|
};
|
|
3320
|
-
exports.
|
|
3396
|
+
exports.ChatbotBody = ChatbotBody;
|