lisichatbot 1.6.8 → 1.7.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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +137 -31
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisichatbot",
3
- "version": "1.6.8",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.js",
6
6
  "exports": {
package/src/index.js CHANGED
@@ -17,7 +17,8 @@ let chatState = {
17
17
  history: [],
18
18
  currentSelection: null,
19
19
  returnToStep: null,
20
- completed: false
20
+ completed: false,
21
+ editPath: [] // ✅ NEW: Array of step names/numbers to edit in sequence
21
22
  };
22
23
 
23
24
  let elements = {
@@ -229,14 +230,24 @@ function updateEditIcons() {
229
230
  return;
230
231
  }
231
232
 
232
- if (hasInput && stepNumber < chatState.step && isLatest) {
233
+ // ✅ NEW: Check if edit icon should be forced to show (even without input)
234
+ const forceShowEdit = stepData && stepData.showEditIcon === true;
235
+
236
+ if ((hasInput || forceShowEdit) && stepNumber < chatState.step && isLatest) {
233
237
  editIcon.onclick = (e) => {
234
238
  e.stopPropagation();
235
239
  e.preventDefault();
236
240
  console.log(`\n🖱️ EDIT ICON CLICKED (from updateEditIcons) - Step ${stepNumber}`);
237
241
  console.log(` Current step: ${chatState.step}`);
238
- console.log(` Calling editStep(${stepNumber})...`);
239
- editStep(stepNumber);
242
+
243
+ // ✅ NEW: Check if this step has an editSteps path
244
+ if (stepData.editSteps && Array.isArray(stepData.editSteps) && stepData.editSteps.length > 0) {
245
+ console.log(` 🛤️ Step has editSteps path:`, stepData.editSteps);
246
+ startEditPath(stepData.editSteps);
247
+ } else {
248
+ console.log(` Calling editStep(${stepNumber})...`);
249
+ editStep(stepNumber);
250
+ }
240
251
  };
241
252
  editIcon.setAttribute('data-chat-step', stepNumber);
242
253
  editIcon.style.setProperty('display', 'flex', 'important');
@@ -2365,19 +2376,42 @@ async function handleNext() {
2365
2376
  await showNextStep();
2366
2377
  return;
2367
2378
  } else {
2368
- // Reached or passed target, clear returnToStep and go to target
2369
- console.log(` ⏭️ Reached target, returning to step ${targetStep}`);
2370
- chatState.returnToStep = null;
2371
- chatState.step = targetStep;
2372
-
2373
- const allRangeWrappers = document.querySelectorAll('[data-chat-element="range-wrapper"]');
2374
- allRangeWrappers.forEach(wrapper => {
2375
- wrapper.style.display = 'none';
2376
- });
2377
-
2378
- updateEditIcons();
2379
- await showNextStep();
2380
- return;
2379
+ // Reached or passed target
2380
+ console.log(` ⏭️ Reached target step`);
2381
+
2382
+ // NEW: Check if there are more steps in the edit path
2383
+ if (chatState.editPath && chatState.editPath.length > 0) {
2384
+ const nextEditStep = chatState.editPath.shift();
2385
+ console.log(` 🛤️ Edit path continues - going to step ${nextEditStep}`);
2386
+ console.log(` 🛤️ Remaining edit path:`, chatState.editPath);
2387
+
2388
+ // Keep returnToStep for when edit path completes
2389
+ chatState.step = nextEditStep;
2390
+
2391
+ const allRangeWrappers = document.querySelectorAll('[data-chat-element="range-wrapper"]');
2392
+ allRangeWrappers.forEach(wrapper => {
2393
+ wrapper.style.display = 'none';
2394
+ });
2395
+
2396
+ updateEditIcons();
2397
+ await showNextStep();
2398
+ return;
2399
+ } else {
2400
+ // No more edit path, return to saved step
2401
+ console.log(` ✅ Edit complete - returning to step ${targetStep}`);
2402
+ chatState.returnToStep = null;
2403
+ chatState.editPath = []; // Clear any remaining path
2404
+ chatState.step = targetStep;
2405
+
2406
+ const allRangeWrappers = document.querySelectorAll('[data-chat-element="range-wrapper"]');
2407
+ allRangeWrappers.forEach(wrapper => {
2408
+ wrapper.style.display = 'none';
2409
+ });
2410
+
2411
+ updateEditIcons();
2412
+ await showNextStep();
2413
+ return;
2414
+ }
2381
2415
  }
2382
2416
  }
2383
2417
 
@@ -2424,6 +2458,16 @@ function findNextAccessibleStep(currentStep) {
2424
2458
  async function showNextStep() {
2425
2459
  const nextStep = flowData.flow[chatState.step];
2426
2460
 
2461
+ // ✅ NEW: Clean up any previously injected elements (from addElements)
2462
+ // BUT: If this step has addElements, we'll re-inject them below
2463
+ if (elements.messages) {
2464
+ const injectedElements = elements.messages.querySelectorAll('[data-chat-injected="true"]');
2465
+ if (injectedElements.length > 0) {
2466
+ console.log(` 🧹 Removing ${injectedElements.length} previously injected element(s)`);
2467
+ injectedElements.forEach(el => el.remove());
2468
+ }
2469
+ }
2470
+
2427
2471
  // ✅ NEW: Check if step should be displayed based on condition
2428
2472
  if (nextStep.shouldDisplay) {
2429
2473
  let shouldShow = false;
@@ -2793,6 +2837,9 @@ async function showNextStep() {
2793
2837
  // Make it visible (in case it was hidden)
2794
2838
  clonedElement.style.display = '';
2795
2839
 
2840
+ // ✅ Mark as injected for cleanup
2841
+ clonedElement.setAttribute('data-chat-injected', 'true');
2842
+
2796
2843
  // Add to messages container
2797
2844
  elements.messages.appendChild(clonedElement);
2798
2845
 
@@ -2888,20 +2935,29 @@ async function showNextStep() {
2888
2935
  // If hasPreFill, renderOptions already handled it
2889
2936
  }
2890
2937
  } else {
2891
- const delay = nextStep.autoAdvanceDelay !== undefined ? nextStep.autoAdvanceDelay : config.autoAdvanceDelay;
2892
- console.log(` ⏱️ Auto-advance delay: ${delay}ms ${nextStep.autoAdvanceDelay !== undefined ? '(step-level)' : '(global)'}`);
2938
+ // FIXED: Only auto-advance if explicitly enabled OR if step has autoAdvance
2939
+ const shouldAutoAdvance = nextStep.autoAdvance === true;
2893
2940
 
2894
- setTimeout(() => {
2895
- // NEW: Find next accessible step
2896
- chatState.step = findNextAccessibleStep(chatState.step);
2897
- updateEditIcons();
2941
+ if (shouldAutoAdvance) {
2942
+ const delay = nextStep.autoAdvanceDelay !== undefined ? nextStep.autoAdvanceDelay : config.autoAdvanceDelay;
2943
+ console.log(` ⏱️ Auto-advance delay: ${delay}ms ${nextStep.autoAdvanceDelay !== undefined ? '(step-level)' : '(global)'}`);
2898
2944
 
2899
- if (chatState.step < flowData.flow.length) {
2900
- showNextStep();
2901
- } else {
2902
- handleCompletion();
2903
- }
2904
- }, delay);
2945
+ setTimeout(() => {
2946
+ // ✅ NEW: Find next accessible step
2947
+ chatState.step = findNextAccessibleStep(chatState.step);
2948
+ updateEditIcons();
2949
+
2950
+ if (chatState.step < flowData.flow.length) {
2951
+ showNextStep();
2952
+ } else {
2953
+ handleCompletion();
2954
+ }
2955
+ }, delay);
2956
+ } else {
2957
+ // ✅ No input and no auto-advance - just enable Next button
2958
+ enableNextButton();
2959
+ console.log(' 🔓 No input field - Next button enabled for manual progression');
2960
+ }
2905
2961
  }
2906
2962
 
2907
2963
  const showNextButton = nextStep.nextButtonDisplay !== false;
@@ -3081,6 +3137,7 @@ function init(flowName, flowConfig, options = {}) {
3081
3137
 
3082
3138
  if (typeof window !== 'undefined') {
3083
3139
  window.editStep = editStep;
3140
+ window.startEditPath = startEditPath; // ✅ NEW: Export to window
3084
3141
  }
3085
3142
 
3086
3143
  showNextStep();
@@ -3091,7 +3148,8 @@ function init(flowName, flowConfig, options = {}) {
3091
3148
  getState,
3092
3149
  reset,
3093
3150
  goToStep,
3094
- editStep
3151
+ editStep,
3152
+ startEditPath // ✅ NEW: Export from init
3095
3153
  };
3096
3154
  }
3097
3155
 
@@ -3141,6 +3199,53 @@ function goToStep(stepNumber) {
3141
3199
  showNextStep();
3142
3200
  }
3143
3201
 
3202
+ // ✅ NEW: Start editing through a path of steps
3203
+ function startEditPath(stepNamesOrNumbers) {
3204
+ console.log(`\n🛤️ startEditPath() called with:`, stepNamesOrNumbers);
3205
+
3206
+ if (!Array.isArray(stepNamesOrNumbers) || stepNamesOrNumbers.length === 0) {
3207
+ console.error('editPath must be a non-empty array');
3208
+ return;
3209
+ }
3210
+
3211
+ // Convert step names to step numbers
3212
+ const stepNumbers = stepNamesOrNumbers.map(nameOrNumber => {
3213
+ if (typeof nameOrNumber === 'number') {
3214
+ return nameOrNumber;
3215
+ } else if (typeof nameOrNumber === 'string') {
3216
+ // Find step by name
3217
+ const stepIndex = flowData.flow.findIndex(step => step.name === nameOrNumber);
3218
+ if (stepIndex === -1) {
3219
+ console.error(`Step with name "${nameOrNumber}" not found`);
3220
+ return null;
3221
+ }
3222
+ return stepIndex;
3223
+ }
3224
+ return null;
3225
+ }).filter(num => num !== null);
3226
+
3227
+ if (stepNumbers.length === 0) {
3228
+ console.error('No valid steps found in editPath');
3229
+ return;
3230
+ }
3231
+
3232
+ console.log(` ✅ Resolved to step numbers:`, stepNumbers);
3233
+
3234
+ // Save current step as return point
3235
+ chatState.returnToStep = chatState.step;
3236
+ console.log(` 💾 Saved return step: ${chatState.returnToStep}`);
3237
+
3238
+ // Save the edit path (remaining steps to edit)
3239
+ chatState.editPath = [...stepNumbers];
3240
+ console.log(` 🛤️ Edit path set:`, chatState.editPath);
3241
+
3242
+ // Start editing the first step in the path
3243
+ const firstStep = chatState.editPath.shift();
3244
+ console.log(` 🎯 Starting with step ${firstStep}`);
3245
+
3246
+ editStep(firstStep);
3247
+ }
3248
+
3144
3249
  function editStep(stepNumber) {
3145
3250
  console.log(`\n📝 editStep() called with stepNumber: ${stepNumber}`);
3146
3251
  console.log(` Current step before edit: ${chatState.step}`);
@@ -3282,5 +3387,6 @@ module.exports = {
3282
3387
  reset,
3283
3388
  goToStep,
3284
3389
  editStep,
3285
- displayMessage // ✅ NEW: Export helper function
3390
+ displayMessage,
3391
+ startEditPath // ✅ NEW: Export edit path function
3286
3392
  };