lisichatbot 1.8.7 → 1.8.9
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 +119 -30
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -18,13 +18,15 @@ let chatState = {
|
|
|
18
18
|
currentSelection: null,
|
|
19
19
|
returnToStep: null,
|
|
20
20
|
completed: false,
|
|
21
|
-
editPath: [] // ✅ NEW: Array of step names/numbers to edit in sequence
|
|
21
|
+
editPath: [], // ✅ NEW: Array of step names/numbers to edit in sequence
|
|
22
|
+
chatMode: 'create' // ✅ NEW: Track if in 'create' or 'edit' mode
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
let elements = {
|
|
25
26
|
container: null,
|
|
26
27
|
messages: null,
|
|
27
28
|
nextBtn: null,
|
|
29
|
+
cancelBtn: null, // ✅ NEW: Cancel button element
|
|
28
30
|
originalNextBtnText: null
|
|
29
31
|
};
|
|
30
32
|
|
|
@@ -32,6 +34,7 @@ let config = {
|
|
|
32
34
|
selectedBackground: '#667eea',
|
|
33
35
|
autoAdvanceDelay: 2000,
|
|
34
36
|
enableAnimations: true,
|
|
37
|
+
showCancelButton: false, // ✅ NEW: Control cancel button visibility
|
|
35
38
|
customRangeErrors: {
|
|
36
39
|
minRequired: 'Minimum value is required',
|
|
37
40
|
maxRequired: 'Maximum value is required',
|
|
@@ -1075,13 +1078,16 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
1075
1078
|
if (minInput) {
|
|
1076
1079
|
minInput.setAttribute('data-field', field);
|
|
1077
1080
|
minInput.setAttribute('data-input-type', 'min');
|
|
1078
|
-
minInput.type = 'number'
|
|
1079
|
-
minInput.
|
|
1080
|
-
minInput.
|
|
1081
|
-
minInput.
|
|
1081
|
+
minInput.type = 'text'; // Changed from 'number' to 'text' for locale formatting
|
|
1082
|
+
minInput.setAttribute('inputmode', 'numeric'); // Show numeric keyboard on mobile
|
|
1083
|
+
minInput.setAttribute('data-min', customConfig.min !== undefined ? customConfig.min : 0);
|
|
1084
|
+
minInput.setAttribute('data-max', customConfig.max !== undefined ? customConfig.max : 100);
|
|
1082
1085
|
|
|
1083
|
-
if (showMinMax) {
|
|
1084
|
-
|
|
1086
|
+
if (showMinMax && existingData[0] !== undefined) {
|
|
1087
|
+
const numValue = Number(existingData[0]);
|
|
1088
|
+
minInput.value = numValue.toLocaleString();
|
|
1089
|
+
minInput.setAttribute('data-raw-value', existingData[0]);
|
|
1090
|
+
console.log(` ✅ Pre-filled min: ${existingData[0]} (display: ${numValue.toLocaleString()})`);
|
|
1085
1091
|
}
|
|
1086
1092
|
}
|
|
1087
1093
|
|
|
@@ -1096,13 +1102,16 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
1096
1102
|
if (maxInput) {
|
|
1097
1103
|
maxInput.setAttribute('data-field', field);
|
|
1098
1104
|
maxInput.setAttribute('data-input-type', 'max');
|
|
1099
|
-
maxInput.type = 'number'
|
|
1100
|
-
maxInput.
|
|
1101
|
-
maxInput.
|
|
1102
|
-
maxInput.
|
|
1105
|
+
maxInput.type = 'text'; // Changed from 'number' to 'text' for locale formatting
|
|
1106
|
+
maxInput.setAttribute('inputmode', 'numeric'); // Show numeric keyboard on mobile
|
|
1107
|
+
maxInput.setAttribute('data-min', customConfig.min !== undefined ? customConfig.min : 0);
|
|
1108
|
+
maxInput.setAttribute('data-max', customConfig.max !== undefined ? customConfig.max : 100);
|
|
1103
1109
|
|
|
1104
|
-
if (showMinMax) {
|
|
1105
|
-
|
|
1110
|
+
if (showMinMax && existingData[1] !== undefined) {
|
|
1111
|
+
const numValue = Number(existingData[1]);
|
|
1112
|
+
maxInput.value = numValue.toLocaleString();
|
|
1113
|
+
maxInput.setAttribute('data-raw-value', existingData[1]);
|
|
1114
|
+
console.log(` ✅ Pre-filled max: ${existingData[1]} (display: ${numValue.toLocaleString()})`);
|
|
1106
1115
|
}
|
|
1107
1116
|
}
|
|
1108
1117
|
|
|
@@ -1137,8 +1146,8 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
1137
1146
|
|
|
1138
1147
|
if (minInput && maxInput) {
|
|
1139
1148
|
const updateVisualFeedback = () => {
|
|
1140
|
-
const minFilled = minInput.value.trim() !== '';
|
|
1141
|
-
const maxFilled = maxInput.value.trim() !== '';
|
|
1149
|
+
const minFilled = (minInput.getAttribute('data-raw-value') || minInput.value.trim()) !== '';
|
|
1150
|
+
const maxFilled = (maxInput.getAttribute('data-raw-value') || maxInput.value.trim()) !== '';
|
|
1142
1151
|
const anyFilled = minFilled || maxFilled;
|
|
1143
1152
|
|
|
1144
1153
|
const minTick = minClone.querySelector('[data-chat-input-element="tick-icon"]');
|
|
@@ -1163,20 +1172,40 @@ function renderMinMaxInputs(field, customConfig, existingData) {
|
|
|
1163
1172
|
console.log(' ✅ Applied visual feedback for pre-filled values');
|
|
1164
1173
|
}
|
|
1165
1174
|
|
|
1166
|
-
minInput.
|
|
1175
|
+
minInput.onchange = () => {
|
|
1167
1176
|
selectCustomOption(field);
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1177
|
+
// Remove non-numeric characters except minus sign at start
|
|
1178
|
+
let value = minInput.value.replace(/[^\d-]/g, '');
|
|
1179
|
+
if (value.indexOf('-') > 0) {
|
|
1180
|
+
value = value.replace(/-/g, '');
|
|
1181
|
+
}
|
|
1182
|
+
minInput.setAttribute('data-raw-value', value);
|
|
1183
|
+
|
|
1184
|
+
// Format with locale string if valid number
|
|
1185
|
+
if (value && value !== '' && !isNaN(value)) {
|
|
1186
|
+
const numValue = Number(value);
|
|
1187
|
+
minInput.value = numValue.toLocaleString();
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1171
1190
|
updateVisualFeedback();
|
|
1172
1191
|
validateMinMax(field, customConfig);
|
|
1173
1192
|
};
|
|
1174
1193
|
|
|
1175
|
-
maxInput.
|
|
1194
|
+
maxInput.onchange = () => {
|
|
1176
1195
|
selectCustomOption(field);
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1196
|
+
// Remove non-numeric characters except minus sign at start
|
|
1197
|
+
let value = maxInput.value.replace(/[^\d-]/g, '');
|
|
1198
|
+
if (value.indexOf('-') > 0) {
|
|
1199
|
+
value = value.replace(/-/g, '');
|
|
1200
|
+
}
|
|
1201
|
+
maxInput.setAttribute('data-raw-value', value);
|
|
1202
|
+
|
|
1203
|
+
// Format with locale string if valid number
|
|
1204
|
+
if (value && value !== '' && !isNaN(value)) {
|
|
1205
|
+
const numValue = Number(value);
|
|
1206
|
+
maxInput.value = numValue.toLocaleString();
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1180
1209
|
updateVisualFeedback();
|
|
1181
1210
|
validateMinMax(field, customConfig);
|
|
1182
1211
|
};
|
|
@@ -1328,10 +1357,12 @@ function handleCustomSelectClick(element, field, customConfig) {
|
|
|
1328
1357
|
|
|
1329
1358
|
if (minInput) {
|
|
1330
1359
|
minInput.value = '';
|
|
1360
|
+
minInput.removeAttribute('data-raw-value');
|
|
1331
1361
|
console.log(' 🧹 Cleared min input');
|
|
1332
1362
|
}
|
|
1333
1363
|
if (maxInput) {
|
|
1334
1364
|
maxInput.value = '';
|
|
1365
|
+
maxInput.removeAttribute('data-raw-value');
|
|
1335
1366
|
console.log(' 🧹 Cleared max input');
|
|
1336
1367
|
}
|
|
1337
1368
|
|
|
@@ -1401,17 +1432,20 @@ function validateMinMax(field, customConfig) {
|
|
|
1401
1432
|
return { valid: false, error: null };
|
|
1402
1433
|
}
|
|
1403
1434
|
|
|
1404
|
-
|
|
1405
|
-
const
|
|
1406
|
-
const
|
|
1407
|
-
const
|
|
1435
|
+
// Use data-raw-value for validation instead of formatted display value
|
|
1436
|
+
const minRawValue = minInput.getAttribute('data-raw-value') || '';
|
|
1437
|
+
const maxRawValue = maxInput.getAttribute('data-raw-value') || '';
|
|
1438
|
+
const minValue = parseFloat(minRawValue);
|
|
1439
|
+
const maxValue = parseFloat(maxRawValue);
|
|
1440
|
+
const minFilled = minRawValue.trim() !== '';
|
|
1441
|
+
const maxFilled = maxRawValue.trim() !== '';
|
|
1408
1442
|
|
|
1409
1443
|
const minConstraint = customConfig.min !== undefined ? customConfig.min : 0;
|
|
1410
1444
|
const maxConstraint = customConfig.max !== undefined ? customConfig.max : 100;
|
|
1411
1445
|
|
|
1412
1446
|
console.log(`📊 Input values:
|
|
1413
|
-
Min
|
|
1414
|
-
Max
|
|
1447
|
+
Min raw value: "${minRawValue}" (filled: ${minFilled}, parsed: ${minValue})
|
|
1448
|
+
Max raw value: "${maxRawValue}" (filled: ${maxFilled}, parsed: ${maxValue})`);
|
|
1415
1449
|
|
|
1416
1450
|
console.log(`📏 Constraints:
|
|
1417
1451
|
Min constraint: >= ${minConstraint}
|
|
@@ -2091,6 +2125,17 @@ async function handleNext() {
|
|
|
2091
2125
|
try {
|
|
2092
2126
|
disableNextButton();
|
|
2093
2127
|
|
|
2128
|
+
// ✅ NEW: Show loader and hide text when button is disabled
|
|
2129
|
+
const nextBtnText = elements.nextBtn.querySelector('[data-chat-element="next-button-text"]');
|
|
2130
|
+
const nextBtnLoader = elements.nextBtn.querySelector('[data-chat-element="next-button-loader"]');
|
|
2131
|
+
|
|
2132
|
+
if (nextBtnText) {
|
|
2133
|
+
nextBtnText.style.display = 'none';
|
|
2134
|
+
}
|
|
2135
|
+
if (nextBtnLoader) {
|
|
2136
|
+
nextBtnLoader.style.display = 'block';
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2094
2139
|
// ✅ NEW: Create showMessage helper function
|
|
2095
2140
|
const showMessage = (message) => {
|
|
2096
2141
|
console.log('💬 showMessage called:', message);
|
|
@@ -2105,6 +2150,14 @@ async function handleNext() {
|
|
|
2105
2150
|
showMessage // ✅ NEW: Third parameter
|
|
2106
2151
|
);
|
|
2107
2152
|
|
|
2153
|
+
// ✅ NEW: Hide loader and show text after onNext completes
|
|
2154
|
+
if (nextBtnText) {
|
|
2155
|
+
nextBtnText.style.display = '';
|
|
2156
|
+
}
|
|
2157
|
+
if (nextBtnLoader) {
|
|
2158
|
+
nextBtnLoader.style.display = 'none';
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2108
2161
|
// ✅ Still support showMessage in return object for backwards compatibility
|
|
2109
2162
|
if (result && typeof result === 'object' && result.showMessage) {
|
|
2110
2163
|
console.log('💬 onNext displaying message from return:', result.showMessage);
|
|
@@ -2355,6 +2408,18 @@ async function handleNext() {
|
|
|
2355
2408
|
} catch (error) {
|
|
2356
2409
|
console.error('Validation error:', error);
|
|
2357
2410
|
alert('An error occurred. Please try again.');
|
|
2411
|
+
|
|
2412
|
+
// ✅ NEW: Hide loader and show text on error
|
|
2413
|
+
const nextBtnText = elements.nextBtn.querySelector('[data-chat-element="next-button-text"]');
|
|
2414
|
+
const nextBtnLoader = elements.nextBtn.querySelector('[data-chat-element="next-button-loader"]');
|
|
2415
|
+
|
|
2416
|
+
if (nextBtnText) {
|
|
2417
|
+
nextBtnText.style.display = '';
|
|
2418
|
+
}
|
|
2419
|
+
if (nextBtnLoader) {
|
|
2420
|
+
nextBtnLoader.style.display = 'none';
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2358
2423
|
enableNextButton();
|
|
2359
2424
|
return;
|
|
2360
2425
|
}
|
|
@@ -3229,12 +3294,14 @@ function init(flowName, flowConfig, options = {}) {
|
|
|
3229
3294
|
hasEditData: Object.keys(editData).length > 0,
|
|
3230
3295
|
selectedBackground: config.selectedBackground,
|
|
3231
3296
|
autoAdvanceDelay: config.autoAdvanceDelay,
|
|
3297
|
+
showCancelButton: config.showCancelButton,
|
|
3232
3298
|
customRangeErrors: config.customRangeErrors
|
|
3233
3299
|
});
|
|
3234
3300
|
|
|
3235
3301
|
flowData = flowConfig;
|
|
3236
3302
|
|
|
3237
3303
|
chatState.step = 0;
|
|
3304
|
+
chatState.chatMode = mode; // ✅ NEW: Store mode in chatState as chatMode
|
|
3238
3305
|
|
|
3239
3306
|
// ✅ NEW: Merge initialData with editData for edit mode
|
|
3240
3307
|
if (mode === 'edit' && editData && Object.keys(editData).length > 0) {
|
|
@@ -3252,6 +3319,7 @@ function init(flowName, flowConfig, options = {}) {
|
|
|
3252
3319
|
|
|
3253
3320
|
elements.messages = elements.container.querySelector('[data-chat-element="messages-container"]');
|
|
3254
3321
|
elements.nextBtn = elements.container.querySelector('[data-chat-element="next-button"]');
|
|
3322
|
+
elements.cancelBtn = elements.container.querySelector('[data-chat-element="cancel-button"]');
|
|
3255
3323
|
|
|
3256
3324
|
if (!elements.messages) {
|
|
3257
3325
|
console.error('messages-container not found. Please add <div data-chat-element="messages-container"></div>');
|
|
@@ -3263,6 +3331,25 @@ function init(flowName, flowConfig, options = {}) {
|
|
|
3263
3331
|
return null;
|
|
3264
3332
|
}
|
|
3265
3333
|
|
|
3334
|
+
// ✅ NEW: Show/hide cancel button based on config
|
|
3335
|
+
if (elements.cancelBtn) {
|
|
3336
|
+
if (config.showCancelButton === true) {
|
|
3337
|
+
elements.cancelBtn.style.marginTop = '8px';
|
|
3338
|
+
elements.cancelBtn.style.display = '';
|
|
3339
|
+
console.log('✅ Cancel button found and shown (showCancelButton: true)');
|
|
3340
|
+
} else {
|
|
3341
|
+
elements.cancelBtn.style.display = 'none';
|
|
3342
|
+
console.log('🚫 Cancel button hidden (showCancelButton: false)');
|
|
3343
|
+
}
|
|
3344
|
+
} else {
|
|
3345
|
+
if (config.showCancelButton === true) {
|
|
3346
|
+
console.warn('⚠️ showCancelButton is true but cancel button element not found');
|
|
3347
|
+
console.warn(' Please add <button data-chat-element="cancel-button">Cancel</button> to your HTML');
|
|
3348
|
+
} else {
|
|
3349
|
+
console.log('ℹ️ Cancel button not found (optional, showCancelButton: false)');
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
|
|
3266
3353
|
const nextBtnTextElement = elements.nextBtn.querySelector('[data-chat-element="next-button-text"]');
|
|
3267
3354
|
if (nextBtnTextElement) {
|
|
3268
3355
|
elements.originalNextBtnText = nextBtnTextElement.textContent || nextBtnTextElement.innerText || 'Next';
|
|
@@ -3323,7 +3410,8 @@ function getState() {
|
|
|
3323
3410
|
return {
|
|
3324
3411
|
step: chatState.step,
|
|
3325
3412
|
data: { ...chatState.data },
|
|
3326
|
-
history: [...chatState.history]
|
|
3413
|
+
history: [...chatState.history],
|
|
3414
|
+
chatMode: chatState.chatMode // ✅ Include chatMode in state
|
|
3327
3415
|
};
|
|
3328
3416
|
}
|
|
3329
3417
|
|
|
@@ -3332,6 +3420,7 @@ function reset() {
|
|
|
3332
3420
|
chatState.data = flowData.initialData || {};
|
|
3333
3421
|
chatState.history = [];
|
|
3334
3422
|
chatState.currentSelection = null;
|
|
3423
|
+
chatState.chatMode = 'create'; // ✅ Reset to create mode
|
|
3335
3424
|
|
|
3336
3425
|
// ✅ Move back any injected elements before clearing
|
|
3337
3426
|
if (elements.messages) {
|