lisichatbot 2.0.8 → 2.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.
- package/package.json +1 -1
- package/src/index.js +245 -40
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -19,7 +19,11 @@ let chatState = {
|
|
|
19
19
|
returnToStep: null,
|
|
20
20
|
completed: false,
|
|
21
21
|
editPath: [], // ✅ NEW: Array of step names/numbers to edit in sequence
|
|
22
|
-
chatMode: 'create' // ✅ NEW: Track if in 'create' or 'edit' mode
|
|
22
|
+
chatMode: 'create', // ✅ NEW: Track if in 'create' or 'edit' mode
|
|
23
|
+
editSteps: null, // ✅ Array of step indices to walk through in edit-steps mode
|
|
24
|
+
editStepsIndex: 0, // ✅ Current position within editSteps array
|
|
25
|
+
onEditComplete: null, // ✅ Callback when editSteps flow finishes
|
|
26
|
+
editFinalButtonText: null // ✅ Button text for the last step in editSteps
|
|
23
27
|
};
|
|
24
28
|
|
|
25
29
|
let elements = {
|
|
@@ -197,45 +201,74 @@ function updateEditIcons() {
|
|
|
197
201
|
const allBotMessages = elements.messages.querySelectorAll('[data-chat-element="bot-message-wrapper"]');
|
|
198
202
|
|
|
199
203
|
console.log(`\n🔄 Updating edit icons - Current step: ${chatState.step}, Completed: ${chatState.completed}`);
|
|
200
|
-
|
|
204
|
+
|
|
201
205
|
allBotMessages.forEach(wrapper => {
|
|
202
206
|
const stepNumber = parseInt(wrapper.getAttribute('data-chat-step'));
|
|
203
207
|
const editIcon = wrapper.querySelector('[data-chat-element="bot-edit-icon"]');
|
|
204
208
|
const isLatest = wrapper.hasAttribute('data-chat-latest');
|
|
205
|
-
|
|
209
|
+
|
|
206
210
|
if (editIcon && !isNaN(stepNumber)) {
|
|
207
211
|
const stepData = flowData.flow[stepNumber];
|
|
208
212
|
const hasInput = stepData && !!stepData.input;
|
|
209
|
-
|
|
213
|
+
|
|
210
214
|
// ✅ NEW: Check if edit is disabled for this step
|
|
211
215
|
if (stepData && stepData.disableEdit === true) {
|
|
212
216
|
editIcon.style.setProperty('display', 'none', 'important');
|
|
213
217
|
console.log(` 🚫 Step ${stepNumber}: Icon HIDDEN (edit disabled)`);
|
|
214
218
|
return;
|
|
215
219
|
}
|
|
216
|
-
|
|
220
|
+
|
|
217
221
|
// ✅ FIX: In edit mode, keep edit icons visible even after completion
|
|
218
222
|
if (chatState.completed && chatState.chatMode !== 'edit') {
|
|
219
223
|
editIcon.style.setProperty('display', 'none', 'important');
|
|
220
224
|
console.log(` 🏁 Step ${stepNumber}: Icon HIDDEN (flow completed in create mode)`);
|
|
221
225
|
return;
|
|
222
226
|
}
|
|
223
|
-
|
|
227
|
+
|
|
224
228
|
// ✅ NEW: Check if edit icon should be forced to show (even without input)
|
|
225
229
|
const forceShowEdit = stepData && stepData.showEditIcon === true;
|
|
226
|
-
|
|
230
|
+
|
|
227
231
|
// ✅ FIX: In edit mode, show edit icons for all completed steps (not just previous)
|
|
228
232
|
const shouldShowInEditMode = chatState.chatMode === 'edit' && chatState.completed && isLatest;
|
|
229
233
|
const shouldShowNormally = stepNumber < chatState.step && isLatest;
|
|
230
|
-
|
|
231
|
-
|
|
234
|
+
// ✅ In editSteps mode, show edit icons for steps already visited in the editSteps list
|
|
235
|
+
const shouldShowInEditSteps = chatState.editSteps && chatState.editSteps.length > 0 &&
|
|
236
|
+
chatState.editSteps.includes(stepNumber) &&
|
|
237
|
+
chatState.editSteps.indexOf(stepNumber) < chatState.editStepsIndex && isLatest;
|
|
238
|
+
|
|
239
|
+
if ((hasInput || forceShowEdit) && (shouldShowInEditMode || shouldShowNormally || shouldShowInEditSteps)) {
|
|
232
240
|
editIcon.onclick = (e) => {
|
|
233
241
|
e.stopPropagation();
|
|
234
242
|
e.preventDefault();
|
|
235
243
|
console.log(`\n🖱️ EDIT ICON CLICKED (from updateEditIcons) - Step ${stepNumber}`);
|
|
236
244
|
console.log(` Current step: ${chatState.step}`);
|
|
237
|
-
|
|
238
|
-
// ✅
|
|
245
|
+
|
|
246
|
+
// ✅ In editSteps mode, go back to that step within the editSteps flow
|
|
247
|
+
if (chatState.editSteps && chatState.editSteps.length > 0) {
|
|
248
|
+
const editStepIdx = chatState.editSteps.indexOf(stepNumber);
|
|
249
|
+
if (editStepIdx !== -1) {
|
|
250
|
+
console.log(` 🛤️ editSteps: jumping back to editSteps[${editStepIdx}] (step ${stepNumber})`);
|
|
251
|
+
chatState.editStepsIndex = editStepIdx;
|
|
252
|
+
chatState.step = stepNumber;
|
|
253
|
+
chatState.currentSelection = null;
|
|
254
|
+
|
|
255
|
+
// Remove history from this editStep onward
|
|
256
|
+
const stepsToRemove = chatState.editSteps.slice(editStepIdx);
|
|
257
|
+
chatState.history = chatState.history.filter(h => !stepsToRemove.includes(h.step));
|
|
258
|
+
|
|
259
|
+
// Set prefill override
|
|
260
|
+
const targetStepData = flowData.flow[stepNumber];
|
|
261
|
+
if (targetStepData?.input?.field && chatState.data[targetStepData.input.field] !== undefined) {
|
|
262
|
+
chatState.prefillOverrideFields = [targetStepData.input.field];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
disableNextButton();
|
|
266
|
+
showNextStep();
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// ✅ Check if this step has an editSteps path (normal mode)
|
|
239
272
|
if (stepData.editSteps && Array.isArray(stepData.editSteps) && stepData.editSteps.length > 0) {
|
|
240
273
|
console.log(` 🛤️ Step has editSteps path:`, stepData.editSteps);
|
|
241
274
|
startEditPath(stepData.editSteps);
|
|
@@ -320,8 +353,9 @@ function renderMultiSelectDropdown(options, field) {
|
|
|
320
353
|
// ✅ NEW: Check if prefill is disabled for this step
|
|
321
354
|
const currentStep = flowData.flow[chatState.step];
|
|
322
355
|
const hasOverride = chatState.prefillOverrideFields && chatState.prefillOverrideFields.includes(field);
|
|
323
|
-
const
|
|
324
|
-
|
|
356
|
+
const isEditing = (chatState.returnToStep !== null && chatState.returnToStep !== undefined) || (chatState.editSteps && chatState.editSteps.length > 0);
|
|
357
|
+
const disablePrefill = currentStep?.disableInputValuePrefill === true && !hasOverride && !isEditing;
|
|
358
|
+
|
|
325
359
|
const existingData = disablePrefill ? [] : (chatState.data[field] || []);
|
|
326
360
|
const selectedValues = new Set(existingData);
|
|
327
361
|
|
|
@@ -621,14 +655,15 @@ function renderOptions(options, field, isSingleSelect = true) {
|
|
|
621
655
|
// ✅ NEW: Check if prefill is disabled for this step
|
|
622
656
|
const currentStep = flowData.flow[chatState.step];
|
|
623
657
|
const hasOverride = chatState.prefillOverrideFields && chatState.prefillOverrideFields.includes(field);
|
|
624
|
-
const
|
|
625
|
-
|
|
658
|
+
const isEditing = (chatState.returnToStep !== null && chatState.returnToStep !== undefined) || (chatState.editSteps && chatState.editSteps.length > 0);
|
|
659
|
+
const disablePrefill = currentStep?.disableInputValuePrefill === true && !hasOverride && !isEditing;
|
|
660
|
+
|
|
626
661
|
const existingData = disablePrefill ? (isSingleSelect ? null : []) : chatState.data[field];
|
|
627
|
-
|
|
662
|
+
|
|
628
663
|
if (disablePrefill) {
|
|
629
664
|
console.log(`⏭️ Pre-fill disabled for ${field} - starting fresh`);
|
|
630
665
|
} else {
|
|
631
|
-
if (hasOverride) {
|
|
666
|
+
if (hasOverride || isEditing) {
|
|
632
667
|
console.log(` 🔓 Pre-fill override active for ${field}:`, existingData);
|
|
633
668
|
} else {
|
|
634
669
|
console.log(`📝 Pre-filling ${field}:`, existingData);
|
|
@@ -761,14 +796,15 @@ function renderColorOptions(options, field) {
|
|
|
761
796
|
// ✅ NEW: Check if prefill is disabled for this step
|
|
762
797
|
const currentStep = flowData.flow[chatState.step];
|
|
763
798
|
const hasOverride = chatState.prefillOverrideFields && chatState.prefillOverrideFields.includes(field);
|
|
764
|
-
const
|
|
765
|
-
|
|
799
|
+
const isEditing = (chatState.returnToStep !== null && chatState.returnToStep !== undefined) || (chatState.editSteps && chatState.editSteps.length > 0);
|
|
800
|
+
const disablePrefill = currentStep?.disableInputValuePrefill === true && !hasOverride && !isEditing;
|
|
801
|
+
|
|
766
802
|
const existingData = disablePrefill ? [] : chatState.data[field];
|
|
767
|
-
|
|
803
|
+
|
|
768
804
|
if (disablePrefill) {
|
|
769
805
|
console.log(`⏭️ Pre-fill disabled for ${field} (color) - starting fresh`);
|
|
770
806
|
} else {
|
|
771
|
-
if (hasOverride) {
|
|
807
|
+
if (hasOverride || isEditing) {
|
|
772
808
|
console.log(` 🔓 Pre-fill override active for ${field} (color):`, existingData);
|
|
773
809
|
} else {
|
|
774
810
|
console.log(`📝 Pre-filling ${field} (color):`, existingData);
|
|
@@ -898,12 +934,14 @@ function renderCustomSelectOptions(options, field, customConfig) {
|
|
|
898
934
|
// ✅ NEW: Check if prefill is disabled for this step
|
|
899
935
|
const currentStep = flowData.flow[chatState.step];
|
|
900
936
|
const hasOverride = chatState.prefillOverrideFields && chatState.prefillOverrideFields.includes(field);
|
|
901
|
-
const
|
|
902
|
-
|
|
937
|
+
const isEditing = (chatState.returnToStep !== null && chatState.returnToStep !== undefined) || (chatState.editSteps && chatState.editSteps.length > 0);
|
|
938
|
+
const disablePrefill = currentStep?.disableInputValuePrefill === true && !hasOverride && !isEditing;
|
|
939
|
+
|
|
903
940
|
console.log(`\n🔍 === PREFILL DEBUG for field: ${field} ===`);
|
|
904
941
|
console.log(` disableInputValuePrefill:`, currentStep?.disableInputValuePrefill);
|
|
905
942
|
console.log(` prefillOverrideFields:`, chatState.prefillOverrideFields);
|
|
906
943
|
console.log(` hasOverride:`, hasOverride);
|
|
944
|
+
console.log(` isEditing:`, isEditing);
|
|
907
945
|
console.log(` disablePrefill:`, disablePrefill);
|
|
908
946
|
console.log(` chatState.data[${field}]:`, chatState.data[field]);
|
|
909
947
|
|
|
@@ -1076,7 +1114,7 @@ function renderCustomSelectOptions(options, field, customConfig) {
|
|
|
1076
1114
|
// ✅ FIX: Enable Next button if option is pre-selected
|
|
1077
1115
|
if (hasPreselectedOption) {
|
|
1078
1116
|
// Set currentSelection
|
|
1079
|
-
const isCustomSelected = Array.isArray(existingData) && existingData.length === 2;
|
|
1117
|
+
const isCustomSelected = Array.isArray(existingData) && existingData.length === 2 && !hasMatchingNormalOption;
|
|
1080
1118
|
|
|
1081
1119
|
if (isCustomSelected) {
|
|
1082
1120
|
// Custom range selected - currentSelection will be set by validateMinMax
|
|
@@ -1687,8 +1725,9 @@ function renderTextInput(field, inputType = 'text', inputConfig = {}) {
|
|
|
1687
1725
|
// ✅ NEW: Check if prefill is disabled for this step
|
|
1688
1726
|
const currentStep = flowData.flow[chatState.step];
|
|
1689
1727
|
const hasOverride = chatState.prefillOverrideFields && chatState.prefillOverrideFields.includes(field);
|
|
1690
|
-
const
|
|
1691
|
-
|
|
1728
|
+
const isEditing = (chatState.returnToStep !== null && chatState.returnToStep !== undefined) || (chatState.editSteps && chatState.editSteps.length > 0);
|
|
1729
|
+
const disablePrefill = currentStep?.disableInputValuePrefill === true && !hasOverride && !isEditing;
|
|
1730
|
+
|
|
1692
1731
|
const existingValue = disablePrefill ? null : chatState.data[field];
|
|
1693
1732
|
|
|
1694
1733
|
if (disablePrefill) {
|
|
@@ -2535,6 +2574,89 @@ async function handleNext() {
|
|
|
2535
2574
|
chatState.currentSelection = null;
|
|
2536
2575
|
disableNextButton();
|
|
2537
2576
|
|
|
2577
|
+
// ✅ Edit-steps mode: jump to next step in the list or finish
|
|
2578
|
+
if (chatState.editSteps && chatState.editSteps.length > 0) {
|
|
2579
|
+
const currentEditIndex = chatState.editStepsIndex;
|
|
2580
|
+
const nextEditIndex = currentEditIndex + 1;
|
|
2581
|
+
|
|
2582
|
+
if (nextEditIndex < chatState.editSteps.length) {
|
|
2583
|
+
// More steps to edit
|
|
2584
|
+
chatState.editStepsIndex = nextEditIndex;
|
|
2585
|
+
const nextStepIndex = chatState.editSteps[nextEditIndex];
|
|
2586
|
+
console.log(`\n🛤️ Edit-steps: moving to step ${nextEditIndex + 1}/${chatState.editSteps.length} (flow index ${nextStepIndex})`);
|
|
2587
|
+
|
|
2588
|
+
chatState.step = nextStepIndex;
|
|
2589
|
+
|
|
2590
|
+
// Set prefillOverrideFields for the next step
|
|
2591
|
+
const targetStep = flowData.flow[nextStepIndex];
|
|
2592
|
+
if (targetStep?.input?.field && chatState.data[targetStep.input.field] !== undefined) {
|
|
2593
|
+
chatState.prefillOverrideFields = [targetStep.input.field];
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
const allRangeWrappers = document.querySelectorAll('[data-chat-element="range-wrapper"]');
|
|
2597
|
+
allRangeWrappers.forEach(wrapper => {
|
|
2598
|
+
wrapper.style.display = 'none';
|
|
2599
|
+
});
|
|
2600
|
+
|
|
2601
|
+
updateEditIcons();
|
|
2602
|
+
await showNextStep();
|
|
2603
|
+
scrollToBottom();
|
|
2604
|
+
return;
|
|
2605
|
+
} else {
|
|
2606
|
+
// All edit steps done - call onEditComplete
|
|
2607
|
+
console.log(`\n✅ Edit-steps complete! All ${chatState.editSteps.length} steps finished.`);
|
|
2608
|
+
|
|
2609
|
+
const dataCopy = { ...chatState.data };
|
|
2610
|
+
const historyCopy = [...chatState.history];
|
|
2611
|
+
const callback = chatState.onEditComplete;
|
|
2612
|
+
|
|
2613
|
+
// Clean up edit-steps state
|
|
2614
|
+
chatState.editSteps = null;
|
|
2615
|
+
chatState.editStepsIndex = 0;
|
|
2616
|
+
chatState.onEditComplete = null;
|
|
2617
|
+
chatState.editFinalButtonText = null;
|
|
2618
|
+
chatState.completed = true;
|
|
2619
|
+
|
|
2620
|
+
// Hide inputs and next button
|
|
2621
|
+
const allRangeWrappers = document.querySelectorAll('[data-chat-element="range-wrapper"]');
|
|
2622
|
+
allRangeWrappers.forEach(wrapper => { wrapper.style.display = 'none'; });
|
|
2623
|
+
|
|
2624
|
+
const previousInputs = elements.messages.querySelectorAll(
|
|
2625
|
+
'[data-chat-element="options-wrapper"], ' +
|
|
2626
|
+
'[data-chat-element="text-input"]:not([style*="display: none"]), ' +
|
|
2627
|
+
'[data-chat-element="number-input"]:not([style*="display: none"]), ' +
|
|
2628
|
+
'[data-chat-element="multi-select-dropdown"]:not([style*="display: none"])'
|
|
2629
|
+
);
|
|
2630
|
+
previousInputs.forEach(input => { input.style.display = 'none'; });
|
|
2631
|
+
|
|
2632
|
+
if (elements.nextBtn) {
|
|
2633
|
+
elements.nextBtn.style.display = 'none';
|
|
2634
|
+
}
|
|
2635
|
+
|
|
2636
|
+
updateEditIcons();
|
|
2637
|
+
|
|
2638
|
+
// Dispatch event
|
|
2639
|
+
if (typeof window !== 'undefined') {
|
|
2640
|
+
const event = new CustomEvent('conversationalFlowEditStepsComplete', {
|
|
2641
|
+
detail: { data: dataCopy, history: historyCopy }
|
|
2642
|
+
});
|
|
2643
|
+
window.dispatchEvent(event);
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
// Call onEditComplete callback with updated data
|
|
2647
|
+
if (callback) {
|
|
2648
|
+
console.log('📞 Calling onEditComplete with data:', dataCopy);
|
|
2649
|
+
try {
|
|
2650
|
+
callback(dataCopy);
|
|
2651
|
+
} catch (error) {
|
|
2652
|
+
console.error('Error in onEditComplete callback:', error);
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2656
|
+
return;
|
|
2657
|
+
}
|
|
2658
|
+
}
|
|
2659
|
+
|
|
2538
2660
|
if (chatState.returnToStep !== null) {
|
|
2539
2661
|
const targetStep = chatState.returnToStep;
|
|
2540
2662
|
console.log(`\n🔙 Returning to saved step ${targetStep} (edited step complete)`);
|
|
@@ -2642,7 +2764,12 @@ async function handleNext() {
|
|
|
2642
2764
|
});
|
|
2643
2765
|
|
|
2644
2766
|
updateEditIcons();
|
|
2645
|
-
|
|
2767
|
+
|
|
2768
|
+
if (chatState.step >= flowData.flow.length) {
|
|
2769
|
+
handleCompletion();
|
|
2770
|
+
} else {
|
|
2771
|
+
await showNextStep();
|
|
2772
|
+
}
|
|
2646
2773
|
return;
|
|
2647
2774
|
}
|
|
2648
2775
|
}
|
|
@@ -2689,6 +2816,12 @@ function findNextAccessibleStep(currentStep) {
|
|
|
2689
2816
|
}
|
|
2690
2817
|
|
|
2691
2818
|
async function showNextStep() {
|
|
2819
|
+
// ✅ FIX: Bounds check - if step is out of range, trigger completion
|
|
2820
|
+
if (chatState.step >= flowData.flow.length) {
|
|
2821
|
+
handleCompletion();
|
|
2822
|
+
return;
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2692
2825
|
const nextStep = flowData.flow[chatState.step];
|
|
2693
2826
|
|
|
2694
2827
|
// ✅ NEW: Clean up any previously injected elements (from addElements)
|
|
@@ -2723,7 +2856,12 @@ async function showNextStep() {
|
|
|
2723
2856
|
}
|
|
2724
2857
|
|
|
2725
2858
|
// ✅ NEW: Check if step should be displayed based on condition
|
|
2726
|
-
|
|
2859
|
+
// ✅ Skip shouldDisplay check entirely if this step is explicitly in editSteps
|
|
2860
|
+
const isInEditSteps = chatState.editSteps && chatState.editSteps.includes(chatState.step);
|
|
2861
|
+
if (isInEditSteps) {
|
|
2862
|
+
console.log(` 🔓 Step ${chatState.step} is in editSteps - overriding shouldDisplay, always showing`);
|
|
2863
|
+
}
|
|
2864
|
+
if (nextStep.shouldDisplay && !isInEditSteps) {
|
|
2727
2865
|
let shouldShow = false;
|
|
2728
2866
|
|
|
2729
2867
|
if (typeof nextStep.shouldDisplay === 'function') {
|
|
@@ -2745,13 +2883,31 @@ async function showNextStep() {
|
|
|
2745
2883
|
|
|
2746
2884
|
if (!shouldShow) {
|
|
2747
2885
|
console.log(` ⏭️ Skipping step ${chatState.step} (shouldDisplay returned false)`);
|
|
2886
|
+
|
|
2887
|
+
// ✅ In editSteps mode, skip to the next step in the editSteps list
|
|
2888
|
+
if (chatState.editSteps && chatState.editSteps.length > 0) {
|
|
2889
|
+
const nextEditIndex = chatState.editStepsIndex + 1;
|
|
2890
|
+
if (nextEditIndex < chatState.editSteps.length) {
|
|
2891
|
+
chatState.editStepsIndex = nextEditIndex;
|
|
2892
|
+
chatState.step = chatState.editSteps[nextEditIndex];
|
|
2893
|
+
console.log(` 🛤️ editSteps: skipping to next edit step ${chatState.step}`);
|
|
2894
|
+
await showNextStep();
|
|
2895
|
+
return;
|
|
2896
|
+
} else {
|
|
2897
|
+
// All remaining edit steps should be skipped - trigger edit completion
|
|
2898
|
+
console.log(` 🛤️ editSteps: no more steps - completing`);
|
|
2899
|
+
handleCompletion();
|
|
2900
|
+
return;
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2748
2904
|
chatState.step++;
|
|
2749
|
-
|
|
2905
|
+
|
|
2750
2906
|
if (chatState.step >= flowData.flow.length) {
|
|
2751
2907
|
handleCompletion();
|
|
2752
2908
|
return;
|
|
2753
2909
|
}
|
|
2754
|
-
|
|
2910
|
+
|
|
2755
2911
|
// Recursively check next step
|
|
2756
2912
|
await showNextStep();
|
|
2757
2913
|
return;
|
|
@@ -3331,12 +3487,20 @@ async function showNextStep() {
|
|
|
3331
3487
|
|
|
3332
3488
|
if (elements.nextBtn) {
|
|
3333
3489
|
const nextBtnTextElement = elements.nextBtn.querySelector('[data-chat-element="next-button-text"]');
|
|
3334
|
-
|
|
3490
|
+
|
|
3335
3491
|
if (nextBtnTextElement) {
|
|
3336
|
-
// ✅ Priority: step-level > global config > original
|
|
3492
|
+
// ✅ Priority: editFinalButtonText (last edit step) > step-level > global config > original
|
|
3337
3493
|
let buttonText;
|
|
3338
|
-
|
|
3339
|
-
if
|
|
3494
|
+
|
|
3495
|
+
// Check if this is the last step in editSteps mode
|
|
3496
|
+
const isLastEditStep = chatState.editSteps &&
|
|
3497
|
+
chatState.editStepsIndex === chatState.editSteps.length - 1 &&
|
|
3498
|
+
chatState.editFinalButtonText;
|
|
3499
|
+
|
|
3500
|
+
if (isLastEditStep) {
|
|
3501
|
+
buttonText = chatState.editFinalButtonText;
|
|
3502
|
+
console.log(` 📝 Next button text: "${buttonText}" (editFinalButtonText - last edit step)`);
|
|
3503
|
+
} else if (nextStep.nextButtonText) {
|
|
3340
3504
|
// Step-level override takes highest priority
|
|
3341
3505
|
buttonText = nextStep.nextButtonText;
|
|
3342
3506
|
console.log(` 📝 Next button text: "${buttonText}" (step-level)`);
|
|
@@ -3349,7 +3513,7 @@ async function showNextStep() {
|
|
|
3349
3513
|
buttonText = elements.originalNextBtnText;
|
|
3350
3514
|
console.log(` 📝 Next button text: "${buttonText}" (original)`);
|
|
3351
3515
|
}
|
|
3352
|
-
|
|
3516
|
+
|
|
3353
3517
|
nextBtnTextElement.textContent = buttonText;
|
|
3354
3518
|
} else if (nextStep.nextButtonText || config.nextButtonText) {
|
|
3355
3519
|
console.warn(` ⚠️ nextButtonText specified but next-button-text element not found`);
|
|
@@ -3422,16 +3586,16 @@ function handleCompletion() {
|
|
|
3422
3586
|
|
|
3423
3587
|
if (typeof window !== 'undefined') {
|
|
3424
3588
|
const event = new CustomEvent('conversationalFlowComplete', {
|
|
3425
|
-
detail: {
|
|
3426
|
-
data: chatState.data,
|
|
3427
|
-
history: chatState.history
|
|
3589
|
+
detail: {
|
|
3590
|
+
data: { ...chatState.data },
|
|
3591
|
+
history: [...chatState.history]
|
|
3428
3592
|
}
|
|
3429
3593
|
});
|
|
3430
3594
|
window.dispatchEvent(event);
|
|
3431
3595
|
}
|
|
3432
3596
|
|
|
3433
3597
|
if (flowData.onComplete && typeof flowData.onComplete === 'function') {
|
|
3434
|
-
flowData.onComplete(chatState.data);
|
|
3598
|
+
flowData.onComplete({ ...chatState.data });
|
|
3435
3599
|
}
|
|
3436
3600
|
}
|
|
3437
3601
|
|
|
@@ -3497,6 +3661,43 @@ function init(flowName, flowConfig, options = {}) {
|
|
|
3497
3661
|
chatState.history = [];
|
|
3498
3662
|
chatState.currentSelection = null;
|
|
3499
3663
|
|
|
3664
|
+
// ✅ NEW: Edit-steps mode - only walk through specific steps by name
|
|
3665
|
+
if (options.editSteps && Array.isArray(options.editSteps) && options.editSteps.length > 0) {
|
|
3666
|
+
// Resolve step names to indices
|
|
3667
|
+
const resolvedSteps = [];
|
|
3668
|
+
options.editSteps.forEach(stepName => {
|
|
3669
|
+
const index = flowConfig.flow.findIndex(s => s.name === stepName);
|
|
3670
|
+
if (index !== -1) {
|
|
3671
|
+
resolvedSteps.push(index);
|
|
3672
|
+
console.log(` 🔍 editSteps: "${stepName}" → step index ${index}`);
|
|
3673
|
+
} else {
|
|
3674
|
+
console.warn(` ⚠️ editSteps: step name "${stepName}" not found in flow`);
|
|
3675
|
+
}
|
|
3676
|
+
});
|
|
3677
|
+
|
|
3678
|
+
if (resolvedSteps.length > 0) {
|
|
3679
|
+
chatState.editSteps = resolvedSteps;
|
|
3680
|
+
chatState.editStepsIndex = 0;
|
|
3681
|
+
chatState.onEditComplete = typeof options.onEditComplete === 'function' ? options.onEditComplete : null;
|
|
3682
|
+
chatState.editFinalButtonText = options.editFinalButtonText || null;
|
|
3683
|
+
chatState.step = resolvedSteps[0]; // Start at the first edit step
|
|
3684
|
+
console.log(`🛤️ Edit-steps mode: ${resolvedSteps.length} steps to edit`, resolvedSteps);
|
|
3685
|
+
console.log(` onEditComplete: ${chatState.onEditComplete ? 'provided' : 'not provided'}`);
|
|
3686
|
+
console.log(` editFinalButtonText: ${chatState.editFinalButtonText || 'not set'}`);
|
|
3687
|
+
} else {
|
|
3688
|
+
console.warn('⚠️ editSteps provided but no valid step names found - using normal flow');
|
|
3689
|
+
chatState.editSteps = null;
|
|
3690
|
+
chatState.editStepsIndex = 0;
|
|
3691
|
+
chatState.onEditComplete = null;
|
|
3692
|
+
chatState.editFinalButtonText = null;
|
|
3693
|
+
}
|
|
3694
|
+
} else {
|
|
3695
|
+
chatState.editSteps = null;
|
|
3696
|
+
chatState.editStepsIndex = 0;
|
|
3697
|
+
chatState.onEditComplete = null;
|
|
3698
|
+
chatState.editFinalButtonText = null;
|
|
3699
|
+
}
|
|
3700
|
+
|
|
3500
3701
|
elements.messages = elements.container.querySelector('[data-chat-element="messages-container"]');
|
|
3501
3702
|
elements.nextBtn = elements.container.querySelector('[data-chat-element="next-button"]');
|
|
3502
3703
|
elements.cancelBtn = elements.container.querySelector('[data-chat-element="cancel-button"]');
|
|
@@ -3600,7 +3801,11 @@ function reset() {
|
|
|
3600
3801
|
chatState.history = [];
|
|
3601
3802
|
chatState.currentSelection = null;
|
|
3602
3803
|
chatState.chatMode = 'create'; // ✅ Reset to create mode
|
|
3603
|
-
|
|
3804
|
+
chatState.editSteps = null;
|
|
3805
|
+
chatState.editStepsIndex = 0;
|
|
3806
|
+
chatState.onEditComplete = null;
|
|
3807
|
+
chatState.editFinalButtonText = null;
|
|
3808
|
+
|
|
3604
3809
|
// ✅ Move back any injected elements before clearing
|
|
3605
3810
|
if (elements.messages) {
|
|
3606
3811
|
const injectedElements = elements.messages.querySelectorAll('[data-chat-injected="true"]');
|