lisichatbot 1.2.5 → 1.2.6
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 +170 -33
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -145,7 +145,7 @@ function addMessage(content, type = 'bot', hasInput = false, stepNumber = null)
|
|
|
145
145
|
console.log(` Calling editStep(${stepNumber})...`);
|
|
146
146
|
editStep(stepNumber);
|
|
147
147
|
};
|
|
148
|
-
editIcon.style.setProperty('display', '
|
|
148
|
+
editIcon.style.setProperty('display', 'flex', 'important');
|
|
149
149
|
editIcon.style.setProperty('margin-left', '8px', 'important');
|
|
150
150
|
editIcon.style.setProperty('cursor', 'pointer', 'important');
|
|
151
151
|
console.log(` ✏️ Edit icon SHOWN (step ${stepNumber} is latest previous step with input)`);
|
|
@@ -184,7 +184,7 @@ function addMessage(content, type = 'bot', hasInput = false, stepNumber = null)
|
|
|
184
184
|
|
|
185
185
|
// Only show if has input AND it's a previous step AND it's latest instance
|
|
186
186
|
if (hasInput && stepNumber !== null && stepNumber < chatState.step && isLatest) {
|
|
187
|
-
editIconAfterAppend.style.setProperty('display', '
|
|
187
|
+
editIconAfterAppend.style.setProperty('display', 'flex', 'important');
|
|
188
188
|
|
|
189
189
|
// Debug: Check spacing
|
|
190
190
|
setTimeout(() => {
|
|
@@ -238,7 +238,7 @@ function updateEditIcons() {
|
|
|
238
238
|
editStep(stepNumber);
|
|
239
239
|
};
|
|
240
240
|
editIcon.setAttribute('data-chat-step', stepNumber);
|
|
241
|
-
editIcon.style.setProperty('display', '
|
|
241
|
+
editIcon.style.setProperty('display', 'flex', 'important');
|
|
242
242
|
editIcon.style.setProperty('cursor', 'pointer', 'important');
|
|
243
243
|
editIcon.style.setProperty('margin-left', '8px', 'important');
|
|
244
244
|
console.log(` ✏️ Step ${stepNumber}: Icon SHOWN (latest previous step)`);
|
|
@@ -648,6 +648,7 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
648
648
|
const rangeWrapper = document.createElement('div');
|
|
649
649
|
rangeWrapper.setAttribute('data-chat-element', 'range-wrapper');
|
|
650
650
|
rangeWrapper.setAttribute('data-field', field);
|
|
651
|
+
rangeWrapper.style.marginBottom = '16px'; // Add space below wrapper
|
|
651
652
|
|
|
652
653
|
// Check if should show min/max (custom option selected)
|
|
653
654
|
// Data is stored as array [min, max]
|
|
@@ -660,6 +661,7 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
660
661
|
// Clone and setup min input
|
|
661
662
|
const minClone = minTemplate.cloneNode(true);
|
|
662
663
|
minClone.style.display = '';
|
|
664
|
+
minClone.style.marginRight = '12px'; // Add space between inputs
|
|
663
665
|
minClone.setAttribute('data-field', field);
|
|
664
666
|
|
|
665
667
|
const minInput = minClone.querySelector('[data-chat-input-element="input"]');
|
|
@@ -712,14 +714,48 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
712
714
|
|
|
713
715
|
elements.messages.appendChild(rangeWrapper);
|
|
714
716
|
|
|
715
|
-
// Add
|
|
716
|
-
if (minInput) {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
717
|
+
// Add handlers for both inputs
|
|
718
|
+
if (minInput && maxInput) {
|
|
719
|
+
const updateVisualFeedback = () => {
|
|
720
|
+
const minFilled = minInput.value.trim() !== '';
|
|
721
|
+
const maxFilled = maxInput.value.trim() !== '';
|
|
722
|
+
const anyFilled = minFilled || maxFilled;
|
|
723
|
+
|
|
724
|
+
// Get tick icons
|
|
725
|
+
const minTick = minClone.querySelector('[data-chat-input-element="tick-icon"]');
|
|
726
|
+
const maxTick = maxClone.querySelector('[data-chat-input-element="tick-icon"]');
|
|
727
|
+
|
|
728
|
+
// Update background and tick for BOTH inputs
|
|
729
|
+
if (anyFilled) {
|
|
730
|
+
minClone.style.backgroundColor = config.selectedBackground;
|
|
731
|
+
maxClone.style.backgroundColor = config.selectedBackground;
|
|
732
|
+
if (minTick) minTick.style.display = 'block';
|
|
733
|
+
if (maxTick) maxTick.style.display = 'block';
|
|
734
|
+
} else {
|
|
735
|
+
minClone.style.backgroundColor = 'transparent';
|
|
736
|
+
maxClone.style.backgroundColor = 'transparent';
|
|
737
|
+
if (minTick) minTick.style.display = 'none';
|
|
738
|
+
if (maxTick) maxTick.style.display = 'none';
|
|
739
|
+
}
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
minInput.onfocus = () => {
|
|
743
|
+
selectCustomOption(field);
|
|
744
|
+
updateVisualFeedback();
|
|
745
|
+
};
|
|
746
|
+
minInput.oninput = () => {
|
|
747
|
+
updateVisualFeedback();
|
|
748
|
+
validateMinMax(field, customConfig);
|
|
749
|
+
};
|
|
750
|
+
|
|
751
|
+
maxInput.onfocus = () => {
|
|
752
|
+
selectCustomOption(field);
|
|
753
|
+
updateVisualFeedback();
|
|
754
|
+
};
|
|
755
|
+
maxInput.oninput = () => {
|
|
756
|
+
updateVisualFeedback();
|
|
757
|
+
validateMinMax(field, customConfig);
|
|
758
|
+
};
|
|
723
759
|
}
|
|
724
760
|
}
|
|
725
761
|
|
|
@@ -783,10 +819,39 @@ function handleCustomSelectClick(element, field, customConfig) {
|
|
|
783
819
|
chatState.currentSelection = null;
|
|
784
820
|
console.log(' ℹ️ Custom selected - waiting for min/max input');
|
|
785
821
|
} else {
|
|
786
|
-
// Hide min/max inputs
|
|
822
|
+
// Hide min/max inputs and clear them
|
|
787
823
|
const rangeWrapper = document.querySelector(`[data-chat-element="range-wrapper"][data-field="${field}"]`);
|
|
788
824
|
if (rangeWrapper) {
|
|
789
825
|
rangeWrapper.style.display = 'none';
|
|
826
|
+
|
|
827
|
+
// Clear input values
|
|
828
|
+
const minInput = rangeWrapper.querySelector('[data-input-type="min"] [data-chat-input-element="input"]');
|
|
829
|
+
const maxInput = rangeWrapper.querySelector('[data-input-type="max"] [data-chat-input-element="input"]');
|
|
830
|
+
|
|
831
|
+
if (minInput) minInput.value = '';
|
|
832
|
+
if (maxInput) maxInput.value = '';
|
|
833
|
+
|
|
834
|
+
// Reset visual feedback (background and ticks)
|
|
835
|
+
const minContainer = rangeWrapper.querySelector('[data-chat-element="single-select-custom-min"]');
|
|
836
|
+
const maxContainer = rangeWrapper.querySelector('[data-chat-element="single-select-custom-max"]');
|
|
837
|
+
|
|
838
|
+
if (minContainer) {
|
|
839
|
+
minContainer.style.backgroundColor = 'transparent';
|
|
840
|
+
const minTick = minContainer.querySelector('[data-chat-input-element="tick-icon"]');
|
|
841
|
+
if (minTick) minTick.style.display = 'none';
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
if (maxContainer) {
|
|
845
|
+
maxContainer.style.backgroundColor = 'transparent';
|
|
846
|
+
const maxTick = maxContainer.querySelector('[data-chat-input-element="tick-icon"]');
|
|
847
|
+
if (maxTick) maxTick.style.display = 'none';
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// Hide error message
|
|
851
|
+
const errorDiv = rangeWrapper.querySelector('[data-chat-element="range-error"]');
|
|
852
|
+
if (errorDiv) errorDiv.style.display = 'none';
|
|
853
|
+
|
|
854
|
+
console.log(' 🧹 Min/max inputs cleared and hidden');
|
|
790
855
|
}
|
|
791
856
|
|
|
792
857
|
// Parse and save regular value
|
|
@@ -809,7 +874,7 @@ function validateMinMax(field, customConfig) {
|
|
|
809
874
|
const maxInput = document.querySelector(`[data-field="${field}"][data-input-type="max"] [data-chat-input-element="input"]`);
|
|
810
875
|
const errorDiv = document.querySelector(`[data-chat-element="range-error"][data-field="${field}"]`);
|
|
811
876
|
|
|
812
|
-
if (!minInput || !maxInput) return false;
|
|
877
|
+
if (!minInput || !maxInput) return { valid: false, error: null };
|
|
813
878
|
|
|
814
879
|
const minValue = parseFloat(minInput.value);
|
|
815
880
|
const maxValue = parseFloat(maxInput.value);
|
|
@@ -819,66 +884,85 @@ function validateMinMax(field, customConfig) {
|
|
|
819
884
|
const minConstraint = customConfig.min !== undefined ? customConfig.min : 0;
|
|
820
885
|
const maxConstraint = customConfig.max !== undefined ? customConfig.max : 100;
|
|
821
886
|
|
|
822
|
-
// Helper to show error
|
|
823
|
-
const
|
|
887
|
+
// Helper to show error in div
|
|
888
|
+
const showErrorDiv = (message) => {
|
|
824
889
|
if (errorDiv) {
|
|
825
890
|
errorDiv.textContent = message;
|
|
826
891
|
errorDiv.style.display = 'block';
|
|
827
892
|
}
|
|
828
|
-
console.log(' ❌ Validation error:', message);
|
|
829
|
-
disableNextButton();
|
|
830
|
-
return false;
|
|
831
893
|
};
|
|
832
894
|
|
|
833
|
-
// Helper to hide error
|
|
834
|
-
const
|
|
895
|
+
// Helper to hide error div
|
|
896
|
+
const hideErrorDiv = () => {
|
|
835
897
|
if (errorDiv) {
|
|
836
898
|
errorDiv.style.display = 'none';
|
|
837
899
|
}
|
|
838
900
|
};
|
|
839
901
|
|
|
840
|
-
// Validation rules
|
|
902
|
+
// Validation rules - return error message if invalid
|
|
841
903
|
|
|
842
904
|
// 1. Check if only one is filled
|
|
843
905
|
if (minFilled && !maxFilled) {
|
|
844
|
-
|
|
906
|
+
const error = config.customRangeErrors.maxRequired;
|
|
907
|
+
showErrorDiv(error);
|
|
908
|
+
console.log(' ❌ Validation error:', error);
|
|
909
|
+
disableNextButton();
|
|
910
|
+
return { valid: false, error };
|
|
845
911
|
}
|
|
846
912
|
|
|
847
913
|
if (!minFilled && maxFilled) {
|
|
848
|
-
|
|
914
|
+
const error = config.customRangeErrors.minRequired;
|
|
915
|
+
showErrorDiv(error);
|
|
916
|
+
console.log(' ❌ Validation error:', error);
|
|
917
|
+
disableNextButton();
|
|
918
|
+
return { valid: false, error };
|
|
849
919
|
}
|
|
850
920
|
|
|
851
921
|
// 2. Check if both are empty
|
|
852
922
|
if (!minFilled && !maxFilled) {
|
|
853
|
-
|
|
923
|
+
hideErrorDiv();
|
|
854
924
|
disableNextButton();
|
|
855
|
-
return false;
|
|
925
|
+
return { valid: false, error: null };
|
|
856
926
|
}
|
|
857
927
|
|
|
858
928
|
// 3. Check if values are valid numbers
|
|
859
929
|
if (isNaN(minValue) || isNaN(maxValue)) {
|
|
860
|
-
|
|
930
|
+
const error = config.customRangeErrors.bothRequired;
|
|
931
|
+
showErrorDiv(error);
|
|
932
|
+
console.log(' ❌ Validation error:', error);
|
|
933
|
+
disableNextButton();
|
|
934
|
+
return { valid: false, error };
|
|
861
935
|
}
|
|
862
936
|
|
|
863
937
|
// 4. Check min constraint
|
|
864
938
|
if (minValue < minConstraint) {
|
|
865
|
-
const
|
|
866
|
-
|
|
939
|
+
const error = config.customRangeErrors.minBelowConstraint.replace('{min}', minConstraint);
|
|
940
|
+
showErrorDiv(error);
|
|
941
|
+
console.log(' ❌ Validation error:', error);
|
|
942
|
+
disableNextButton();
|
|
943
|
+
return { valid: false, error };
|
|
867
944
|
}
|
|
868
945
|
|
|
869
946
|
// 5. Check max constraint
|
|
870
947
|
if (maxValue > maxConstraint) {
|
|
871
|
-
const
|
|
872
|
-
|
|
948
|
+
const error = config.customRangeErrors.maxAboveConstraint.replace('{max}', maxConstraint);
|
|
949
|
+
showErrorDiv(error);
|
|
950
|
+
console.log(' ❌ Validation error:', error);
|
|
951
|
+
disableNextButton();
|
|
952
|
+
return { valid: false, error };
|
|
873
953
|
}
|
|
874
954
|
|
|
875
955
|
// 6. Check min < max
|
|
876
956
|
if (minValue >= maxValue) {
|
|
877
|
-
|
|
957
|
+
const error = config.customRangeErrors.minGreaterThanMax;
|
|
958
|
+
showErrorDiv(error);
|
|
959
|
+
console.log(' ❌ Validation error:', error);
|
|
960
|
+
disableNextButton();
|
|
961
|
+
return { valid: false, error };
|
|
878
962
|
}
|
|
879
963
|
|
|
880
964
|
// All valid! Hide error and save data as array
|
|
881
|
-
|
|
965
|
+
hideErrorDiv();
|
|
882
966
|
|
|
883
967
|
// Store as array [min, max]
|
|
884
968
|
chatState.data[field] = [minValue, maxValue];
|
|
@@ -890,7 +974,7 @@ function validateMinMax(field, customConfig) {
|
|
|
890
974
|
|
|
891
975
|
console.log(' ✅ Range valid - stored as array:', [minValue, maxValue]);
|
|
892
976
|
enableNextButton();
|
|
893
|
-
return true;
|
|
977
|
+
return { valid: true, error: null };
|
|
894
978
|
}
|
|
895
979
|
|
|
896
980
|
// =============================================================================
|
|
@@ -1106,6 +1190,45 @@ async function handleNext() {
|
|
|
1106
1190
|
return;
|
|
1107
1191
|
}
|
|
1108
1192
|
|
|
1193
|
+
// VALIDATION: Check for single-select-custom validation before proceeding
|
|
1194
|
+
if (currentStep.inputType === 'single-select-custom' && currentStep.input) {
|
|
1195
|
+
const field = currentStep.input.field;
|
|
1196
|
+
const customConfig = currentStep.input.custom;
|
|
1197
|
+
|
|
1198
|
+
// Check if custom range was selected (data is array)
|
|
1199
|
+
const selectedValue = chatState.data[field];
|
|
1200
|
+
const isCustomRange = Array.isArray(selectedValue);
|
|
1201
|
+
|
|
1202
|
+
if (isCustomRange && customConfig) {
|
|
1203
|
+
// Validate the custom range
|
|
1204
|
+
const validation = validateMinMax(field, customConfig);
|
|
1205
|
+
|
|
1206
|
+
if (!validation.valid && validation.error) {
|
|
1207
|
+
// Show error as bot message
|
|
1208
|
+
console.log(' ⚠️ Validation failed, showing error message');
|
|
1209
|
+
|
|
1210
|
+
// Hide current inputs (options and range wrapper)
|
|
1211
|
+
const optionsWrapper = document.querySelector('[data-chat-element="options-wrapper"]');
|
|
1212
|
+
if (optionsWrapper) {
|
|
1213
|
+
optionsWrapper.style.display = 'none';
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
const rangeWrapper = document.querySelector(`[data-chat-element="range-wrapper"][data-field="${field}"]`);
|
|
1217
|
+
if (rangeWrapper) {
|
|
1218
|
+
rangeWrapper.style.display = 'none';
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
// Add error message as bot message
|
|
1222
|
+
addMessage(validation.error, 'bot', false, null);
|
|
1223
|
+
|
|
1224
|
+
// Re-display the same step with fresh inputs
|
|
1225
|
+
await showNextStep();
|
|
1226
|
+
|
|
1227
|
+
return; // Stop here, don't proceed
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1109
1232
|
// Call onNext validation if exists
|
|
1110
1233
|
if (currentStep.onNext) {
|
|
1111
1234
|
try {
|
|
@@ -1155,6 +1278,13 @@ async function handleNext() {
|
|
|
1155
1278
|
chatState.step = targetStep;
|
|
1156
1279
|
console.log(` ✅ Jumped to step ${targetStep}`);
|
|
1157
1280
|
|
|
1281
|
+
// Hide all range-wrappers
|
|
1282
|
+
const allRangeWrappers = document.querySelectorAll('[data-chat-element="range-wrapper"]');
|
|
1283
|
+
allRangeWrappers.forEach(wrapper => {
|
|
1284
|
+
wrapper.style.display = 'none';
|
|
1285
|
+
});
|
|
1286
|
+
console.log(' 🙈 Hidden all range-wrappers');
|
|
1287
|
+
|
|
1158
1288
|
// Update edit icons for the new position
|
|
1159
1289
|
updateEditIcons();
|
|
1160
1290
|
|
|
@@ -1169,6 +1299,13 @@ async function handleNext() {
|
|
|
1169
1299
|
// Normal flow: Move to next step
|
|
1170
1300
|
chatState.step++;
|
|
1171
1301
|
|
|
1302
|
+
// Hide all range-wrappers (custom min/max inputs)
|
|
1303
|
+
const allRangeWrappers = document.querySelectorAll('[data-chat-element="range-wrapper"]');
|
|
1304
|
+
allRangeWrappers.forEach(wrapper => {
|
|
1305
|
+
wrapper.style.display = 'none';
|
|
1306
|
+
});
|
|
1307
|
+
console.log(' 🙈 Hidden all range-wrappers');
|
|
1308
|
+
|
|
1172
1309
|
// Update edit icons for all previous steps
|
|
1173
1310
|
updateEditIcons();
|
|
1174
1311
|
|