lisichatbot 1.2.9 β 1.3.1
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 +195 -33
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -656,6 +656,13 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
656
656
|
return;
|
|
657
657
|
}
|
|
658
658
|
|
|
659
|
+
// Remove existing rangeWrapper if it exists (for edit flow)
|
|
660
|
+
const existingRangeWrapper = elements.messages.querySelector(`[data-chat-element="range-wrapper"][data-field="${field}"]`);
|
|
661
|
+
if (existingRangeWrapper) {
|
|
662
|
+
console.log(' ποΈ Removing existing rangeWrapper for re-render');
|
|
663
|
+
existingRangeWrapper.remove();
|
|
664
|
+
}
|
|
665
|
+
|
|
659
666
|
// Create wrapper for min/max
|
|
660
667
|
const rangeWrapper = document.createElement('div');
|
|
661
668
|
rangeWrapper.setAttribute('data-chat-element', 'range-wrapper');
|
|
@@ -690,7 +697,7 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
690
697
|
minInput.min = customConfig.min !== undefined ? customConfig.min : 0;
|
|
691
698
|
minInput.max = customConfig.max !== undefined ? customConfig.max : 100;
|
|
692
699
|
minInput.value = showMinMax && existingData[0] !== undefined ? existingData[0] : '';
|
|
693
|
-
|
|
700
|
+
// Removed placeholder
|
|
694
701
|
|
|
695
702
|
if (showMinMax) {
|
|
696
703
|
console.log(` β
Pre-filled min: ${existingData[0]}`);
|
|
@@ -713,7 +720,7 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
713
720
|
maxInput.min = customConfig.min !== undefined ? customConfig.min : 0;
|
|
714
721
|
maxInput.max = customConfig.max !== undefined ? customConfig.max : 100;
|
|
715
722
|
maxInput.value = showMinMax && existingData[1] !== undefined ? existingData[1] : '';
|
|
716
|
-
|
|
723
|
+
// Removed placeholder
|
|
717
724
|
|
|
718
725
|
if (showMinMax) {
|
|
719
726
|
console.log(` β
Pre-filled max: ${existingData[1]}`);
|
|
@@ -760,6 +767,14 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
760
767
|
}
|
|
761
768
|
};
|
|
762
769
|
|
|
770
|
+
// Apply visual feedback immediately if pre-filled
|
|
771
|
+
if (showMinMax) {
|
|
772
|
+
updateVisualFeedback();
|
|
773
|
+
// Also run validation to set currentSelection
|
|
774
|
+
validateMinMax(field, customConfig);
|
|
775
|
+
console.log(' β
Applied visual feedback for pre-filled values');
|
|
776
|
+
}
|
|
777
|
+
|
|
763
778
|
minInput.onfocus = () => {
|
|
764
779
|
selectCustomOption(field);
|
|
765
780
|
updateVisualFeedback();
|
|
@@ -832,8 +847,16 @@ function handleCustomSelectClick(element, field, customConfig) {
|
|
|
832
847
|
if (isCustom) {
|
|
833
848
|
// Show min/max inputs
|
|
834
849
|
const rangeWrapper = document.querySelector(`[data-chat-element="range-wrapper"][data-field="${field}"]`);
|
|
850
|
+
console.log(' π¦ Looking for rangeWrapper:', `[data-chat-element="range-wrapper"][data-field="${field}"]`);
|
|
851
|
+
console.log(' π¦ Found rangeWrapper:', rangeWrapper);
|
|
852
|
+
|
|
835
853
|
if (rangeWrapper) {
|
|
854
|
+
console.log(' π¦ Current display:', rangeWrapper.style.display);
|
|
836
855
|
rangeWrapper.style.display = 'flex'; // Keep flex!
|
|
856
|
+
console.log(' β
Set rangeWrapper display to flex');
|
|
857
|
+
console.log(' π¦ New display:', rangeWrapper.style.display);
|
|
858
|
+
} else {
|
|
859
|
+
console.log(' β rangeWrapper not found!');
|
|
837
860
|
}
|
|
838
861
|
|
|
839
862
|
// Don't save data yet - wait for validation
|
|
@@ -845,12 +868,18 @@ function handleCustomSelectClick(element, field, customConfig) {
|
|
|
845
868
|
if (rangeWrapper) {
|
|
846
869
|
rangeWrapper.style.display = 'none';
|
|
847
870
|
|
|
848
|
-
// Clear input values
|
|
849
|
-
const minInput =
|
|
850
|
-
const maxInput =
|
|
871
|
+
// Clear input values - fixed selectors
|
|
872
|
+
const minInput = document.querySelector(`[data-field="${field}"][data-input-type="min"][data-chat-input-element="input"]`);
|
|
873
|
+
const maxInput = document.querySelector(`[data-field="${field}"][data-input-type="max"][data-chat-input-element="input"]`);
|
|
851
874
|
|
|
852
|
-
if (minInput)
|
|
853
|
-
|
|
875
|
+
if (minInput) {
|
|
876
|
+
minInput.value = '';
|
|
877
|
+
console.log(' π§Ή Cleared min input');
|
|
878
|
+
}
|
|
879
|
+
if (maxInput) {
|
|
880
|
+
maxInput.value = '';
|
|
881
|
+
console.log(' π§Ή Cleared max input');
|
|
882
|
+
}
|
|
854
883
|
|
|
855
884
|
// Reset visual feedback (background and ticks)
|
|
856
885
|
const minContainer = rangeWrapper.querySelector('[data-chat-element="single-select-custom-min"]');
|
|
@@ -1019,15 +1048,35 @@ function validateMinMax(field, customConfig) {
|
|
|
1019
1048
|
|
|
1020
1049
|
// Store as array [min, max]
|
|
1021
1050
|
chatState.data[field] = [minValue, maxValue];
|
|
1051
|
+
|
|
1052
|
+
// Get the current step's input config for formatting
|
|
1053
|
+
const currentStep = flowData.flow[chatState.step];
|
|
1054
|
+
const inputConfig = currentStep?.input || {};
|
|
1055
|
+
const valueType = inputConfig.selectedInputValueType;
|
|
1056
|
+
const prefix = inputConfig.selectedInputPrefix || '';
|
|
1057
|
+
const suffix = inputConfig.selectedInputSuffix || '';
|
|
1058
|
+
|
|
1059
|
+
// Format display name
|
|
1060
|
+
let displayName = `${minValue}-${maxValue}`;
|
|
1061
|
+
if (valueType === 'arrayRange') {
|
|
1062
|
+
const formattedMin = minValue.toLocaleString();
|
|
1063
|
+
const formattedMax = maxValue.toLocaleString();
|
|
1064
|
+
displayName = `${formattedMin} - ${formattedMax}`;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// Add prefix and suffix with spaces
|
|
1068
|
+
if (prefix) displayName = `${prefix} ${displayName}`;
|
|
1069
|
+
if (suffix) displayName = `${displayName} ${suffix}`;
|
|
1070
|
+
|
|
1022
1071
|
chatState.currentSelection = {
|
|
1023
1072
|
field,
|
|
1024
1073
|
value: [minValue, maxValue],
|
|
1025
|
-
name:
|
|
1074
|
+
name: displayName
|
|
1026
1075
|
};
|
|
1027
1076
|
|
|
1028
1077
|
console.log(`β
β
β
ALL VALIDATION PASSED!`);
|
|
1029
1078
|
console.log(`πΎ Data saved: chatState.data.${field} = [${minValue}, ${maxValue}]`);
|
|
1030
|
-
console.log(`πΎ
|
|
1079
|
+
console.log(`πΎ Display name: "${displayName}"`);
|
|
1031
1080
|
console.log(`π’ Next button: ENABLED\n`);
|
|
1032
1081
|
|
|
1033
1082
|
enableNextButton();
|
|
@@ -1038,7 +1087,7 @@ function validateMinMax(field, customConfig) {
|
|
|
1038
1087
|
// TEXT/NUMBER INPUT RENDERING
|
|
1039
1088
|
// =============================================================================
|
|
1040
1089
|
|
|
1041
|
-
function renderTextInput(field, inputType = 'text') {
|
|
1090
|
+
function renderTextInput(field, inputType = 'text', inputConfig = {}) {
|
|
1042
1091
|
if (!elements.messages) return;
|
|
1043
1092
|
|
|
1044
1093
|
// Determine input type attribute value
|
|
@@ -1056,6 +1105,17 @@ function renderTextInput(field, inputType = 'text') {
|
|
|
1056
1105
|
// Get existing data for this field (for pre-filling when editing)
|
|
1057
1106
|
const existingValue = chatState.data[field];
|
|
1058
1107
|
console.log(`π Pre-filling ${field}:`, existingValue);
|
|
1108
|
+
|
|
1109
|
+
// Check if validation should be applied (only if input has min/max defined)
|
|
1110
|
+
const hasValidation = inputType === 'number' &&
|
|
1111
|
+
(inputConfig.min !== undefined || inputConfig.max !== undefined);
|
|
1112
|
+
|
|
1113
|
+
if (hasValidation) {
|
|
1114
|
+
console.log(` π Validation enabled for ${field}:`, {
|
|
1115
|
+
min: inputConfig.min,
|
|
1116
|
+
max: inputConfig.max
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1059
1119
|
|
|
1060
1120
|
// Clone existing input element
|
|
1061
1121
|
const clone = existingInput.cloneNode(true);
|
|
@@ -1072,17 +1132,46 @@ function renderTextInput(field, inputType = 'text') {
|
|
|
1072
1132
|
inputElement.setAttribute('data-field', field);
|
|
1073
1133
|
inputElement.name = field;
|
|
1074
1134
|
|
|
1135
|
+
// Set min/max attributes if validation enabled
|
|
1136
|
+
if (hasValidation) {
|
|
1137
|
+
if (inputConfig.min !== undefined) {
|
|
1138
|
+
inputElement.min = inputConfig.min;
|
|
1139
|
+
}
|
|
1140
|
+
if (inputConfig.max !== undefined) {
|
|
1141
|
+
inputElement.max = inputConfig.max;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1075
1145
|
// Pre-fill value if it exists
|
|
1076
1146
|
if (existingValue !== undefined && existingValue !== null) {
|
|
1077
1147
|
inputElement.value = existingValue;
|
|
1078
1148
|
console.log(` β
Pre-filled with: ${existingValue}`);
|
|
1149
|
+
|
|
1150
|
+
// If validation enabled, validate the pre-filled value
|
|
1151
|
+
if (hasValidation) {
|
|
1152
|
+
const value = parseFloat(existingValue);
|
|
1153
|
+
const min = inputConfig.min;
|
|
1154
|
+
const max = inputConfig.max;
|
|
1155
|
+
|
|
1156
|
+
let isValid = !isNaN(value);
|
|
1157
|
+
if (isValid && min !== undefined && value < min) isValid = false;
|
|
1158
|
+
if (isValid && max !== undefined && value > max) isValid = false;
|
|
1159
|
+
|
|
1160
|
+
if (isValid) {
|
|
1161
|
+
enableNextButton();
|
|
1162
|
+
console.log(` β
Pre-filled value is valid: ${value}`);
|
|
1163
|
+
} else {
|
|
1164
|
+
disableNextButton();
|
|
1165
|
+
console.log(` β Pre-filled value is invalid: ${value}`);
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1079
1168
|
} else {
|
|
1080
1169
|
inputElement.value = '';
|
|
1081
1170
|
}
|
|
1082
1171
|
|
|
1083
1172
|
inputElement.type = inputType === 'number' ? 'number' : 'text';
|
|
1084
1173
|
|
|
1085
|
-
// Add input event
|
|
1174
|
+
// Add input event handler
|
|
1086
1175
|
inputElement.oninput = (e) => {
|
|
1087
1176
|
const value = inputType === 'number' ? parseFloat(e.target.value) : e.target.value;
|
|
1088
1177
|
|
|
@@ -1090,11 +1179,36 @@ function renderTextInput(field, inputType = 'text') {
|
|
|
1090
1179
|
chatState.data[field] = value;
|
|
1091
1180
|
chatState.currentSelection = { field, value, name: value };
|
|
1092
1181
|
|
|
1093
|
-
//
|
|
1094
|
-
if (
|
|
1095
|
-
|
|
1182
|
+
// Apply validation ONLY if min/max defined at input level
|
|
1183
|
+
if (hasValidation) {
|
|
1184
|
+
const min = inputConfig.min;
|
|
1185
|
+
const max = inputConfig.max;
|
|
1186
|
+
|
|
1187
|
+
// Check if value is valid
|
|
1188
|
+
let isValid = true;
|
|
1189
|
+
let errorMessage = '';
|
|
1190
|
+
|
|
1191
|
+
if (value === '' || isNaN(value)) {
|
|
1192
|
+
isValid = false;
|
|
1193
|
+
errorMessage = 'Please enter a valid number';
|
|
1194
|
+
} else if (min !== undefined && value < min) {
|
|
1195
|
+
isValid = false;
|
|
1196
|
+
errorMessage = `Value must be at least ${min}`;
|
|
1197
|
+
} else if (max !== undefined && value > max) {
|
|
1198
|
+
isValid = false;
|
|
1199
|
+
errorMessage = `Value must be at most ${max}`;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
if (isValid) {
|
|
1203
|
+
enableNextButton();
|
|
1204
|
+
console.log(` β
Number input valid: ${value}`);
|
|
1205
|
+
} else {
|
|
1206
|
+
disableNextButton();
|
|
1207
|
+
console.log(` β Number input invalid: ${errorMessage}`);
|
|
1208
|
+
}
|
|
1096
1209
|
} else {
|
|
1097
|
-
|
|
1210
|
+
// No validation - just log
|
|
1211
|
+
console.log(` π Input updated: ${value} (no validation)`);
|
|
1098
1212
|
}
|
|
1099
1213
|
};
|
|
1100
1214
|
}
|
|
@@ -1330,14 +1444,34 @@ async function handleNext() {
|
|
|
1330
1444
|
|
|
1331
1445
|
// Add user message (only if selection was made)
|
|
1332
1446
|
if (chatState.currentSelection) {
|
|
1333
|
-
|
|
1447
|
+
// Get the step's input config
|
|
1448
|
+
const inputConfig = currentStep.input || {};
|
|
1449
|
+
const valueType = inputConfig.selectedInputValueType;
|
|
1450
|
+
const prefix = inputConfig.selectedInputPrefix || '';
|
|
1451
|
+
const suffix = inputConfig.selectedInputSuffix || '';
|
|
1452
|
+
|
|
1453
|
+
let displayName = chatState.currentSelection.name;
|
|
1454
|
+
|
|
1455
|
+
// Format based on valueType
|
|
1456
|
+
if (valueType === 'arrayRange' && Array.isArray(chatState.currentSelection.value)) {
|
|
1457
|
+
const [min, max] = chatState.currentSelection.value;
|
|
1458
|
+
const formattedMin = min.toLocaleString();
|
|
1459
|
+
const formattedMax = max.toLocaleString();
|
|
1460
|
+
displayName = `${formattedMin} - ${formattedMax}`;
|
|
1461
|
+
}
|
|
1462
|
+
|
|
1463
|
+
// Add prefix and suffix with spaces
|
|
1464
|
+
if (prefix) displayName = `${prefix} ${displayName}`;
|
|
1465
|
+
if (suffix) displayName = `${displayName} ${suffix}`;
|
|
1466
|
+
|
|
1467
|
+
addMessage(displayName, 'user', false, chatState.step);
|
|
1334
1468
|
|
|
1335
1469
|
// Save to history
|
|
1336
1470
|
chatState.history.push({
|
|
1337
1471
|
step: chatState.step,
|
|
1338
1472
|
field: chatState.currentSelection.field,
|
|
1339
1473
|
value: chatState.currentSelection.value,
|
|
1340
|
-
name:
|
|
1474
|
+
name: displayName
|
|
1341
1475
|
});
|
|
1342
1476
|
}
|
|
1343
1477
|
|
|
@@ -1437,13 +1571,21 @@ async function showNextStep() {
|
|
|
1437
1571
|
|
|
1438
1572
|
if (inputType === 'text' || inputType === 'number') {
|
|
1439
1573
|
// Render text or number input
|
|
1440
|
-
renderTextInput(nextStep.input.field, inputType);
|
|
1574
|
+
renderTextInput(nextStep.input.field, inputType, nextStep.input);
|
|
1441
1575
|
|
|
1442
|
-
//
|
|
1443
|
-
|
|
1576
|
+
// Check if validation is enabled (number input with min/max defined)
|
|
1577
|
+
const hasValidation = inputType === 'number' &&
|
|
1578
|
+
(nextStep.input.min !== undefined || nextStep.input.max !== undefined);
|
|
1579
|
+
|
|
1580
|
+
// Initial Next button state
|
|
1581
|
+
if (inputRequired || hasValidation) {
|
|
1582
|
+
// Disable if input is required OR has validation rules
|
|
1444
1583
|
disableNextButton();
|
|
1584
|
+
console.log(' π Next button disabled initially (input required or validation enabled)');
|
|
1445
1585
|
} else {
|
|
1586
|
+
// Enable if optional and no validation
|
|
1446
1587
|
enableNextButton();
|
|
1588
|
+
console.log(' π Next button enabled (optional input, no validation)');
|
|
1447
1589
|
}
|
|
1448
1590
|
} else if (inputType === 'multi-select-color') {
|
|
1449
1591
|
// Render color options with color blocks
|
|
@@ -1478,19 +1620,39 @@ async function showNextStep() {
|
|
|
1478
1620
|
}
|
|
1479
1621
|
}
|
|
1480
1622
|
} else {
|
|
1481
|
-
//
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
//
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1623
|
+
// No input
|
|
1624
|
+
const shouldAutoAdvance = nextStep.nextButtonDisplay !== false;
|
|
1625
|
+
|
|
1626
|
+
if (shouldAutoAdvance) {
|
|
1627
|
+
// Auto-advance for steps without input (default behavior)
|
|
1628
|
+
setTimeout(() => {
|
|
1629
|
+
chatState.step++;
|
|
1630
|
+
|
|
1631
|
+
// Update edit icons after auto-advance
|
|
1632
|
+
updateEditIcons();
|
|
1633
|
+
|
|
1634
|
+
if (chatState.step < flowData.flow.length) {
|
|
1635
|
+
showNextStep();
|
|
1636
|
+
} else {
|
|
1637
|
+
handleCompletion();
|
|
1638
|
+
}
|
|
1639
|
+
}, config.autoAdvanceDelay);
|
|
1640
|
+
} else {
|
|
1641
|
+
// Don't auto-advance if nextButtonDisplay is explicitly false
|
|
1642
|
+
console.log(' βΈοΈ Not auto-advancing (nextButtonDisplay: false)');
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1646
|
+
// Handle nextButtonDisplay - default is true
|
|
1647
|
+
const showNextButton = nextStep.nextButtonDisplay !== false;
|
|
1648
|
+
if (elements.nextBtn) {
|
|
1649
|
+
if (showNextButton) {
|
|
1650
|
+
elements.nextBtn.style.display = '';
|
|
1651
|
+
console.log(' ποΈ Next button shown (nextButtonDisplay: true or undefined)');
|
|
1652
|
+
} else {
|
|
1653
|
+
elements.nextBtn.style.display = 'none';
|
|
1654
|
+
console.log(' π Next button hidden (nextButtonDisplay: false)');
|
|
1655
|
+
}
|
|
1494
1656
|
}
|
|
1495
1657
|
|
|
1496
1658
|
// Always update edit icons at the end to ensure correct state
|