lisichatbot 1.0.1 → 1.0.3
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 +111 -95
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -67,35 +67,43 @@ function disableNextButton() {
|
|
|
67
67
|
function addMessage(content, type = 'bot', isEditable = false, stepNumber = null) {
|
|
68
68
|
if (!elements.messages) return;
|
|
69
69
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
// Find the wrapper element directly by data-chat-element
|
|
71
|
+
const wrapperSelector = `[data-chat-element="${type}-message-wrapper"]`;
|
|
72
|
+
const existingWrapper = document.querySelector(wrapperSelector);
|
|
73
73
|
|
|
74
|
+
if (!existingWrapper) {
|
|
75
|
+
console.error(`Element with ${wrapperSelector} not found in HTML. Please add it to your HTML.`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Clone the existing wrapper
|
|
80
|
+
const clone = existingWrapper.cloneNode(true);
|
|
81
|
+
|
|
82
|
+
// Add step number if provided
|
|
74
83
|
if (stepNumber !== null) {
|
|
75
|
-
|
|
84
|
+
clone.setAttribute('data-chat-step', stepNumber);
|
|
76
85
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
onclick="editStep(${stepNumber})"
|
|
85
|
-
title="Edit this response">
|
|
86
|
-
✏️
|
|
87
|
-
</button>
|
|
88
|
-
`;
|
|
86
|
+
|
|
87
|
+
// Find text element in clone and set content
|
|
88
|
+
const textElement = clone.querySelector(`[data-chat-element="${type}-message-text"]`);
|
|
89
|
+
if (textElement) {
|
|
90
|
+
textElement.textContent = content;
|
|
91
|
+
} else {
|
|
92
|
+
console.error(`Element with data-chat-element="${type}-message-text" not found in wrapper`);
|
|
89
93
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
94
|
+
|
|
95
|
+
// Handle edit button for user messages
|
|
96
|
+
if (isEditable && type === 'user' && stepNumber !== null) {
|
|
97
|
+
const editButton = clone.querySelector('[data-chat-element="edit-button"]');
|
|
98
|
+
if (editButton) {
|
|
99
|
+
editButton.setAttribute('data-chat-step', stepNumber);
|
|
100
|
+
editButton.onclick = () => editStep(stepNumber);
|
|
101
|
+
editButton.style.display = 'inline-block';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Append to messages container
|
|
106
|
+
elements.messages.appendChild(clone);
|
|
99
107
|
scrollToBottom();
|
|
100
108
|
}
|
|
101
109
|
|
|
@@ -106,56 +114,63 @@ function addMessage(content, type = 'bot', isEditable = false, stepNumber = null
|
|
|
106
114
|
function renderOptions(options, field, isSingleSelect = true) {
|
|
107
115
|
if (!elements.messages) return;
|
|
108
116
|
|
|
109
|
-
const messageDiv = document.createElement('div');
|
|
110
|
-
messageDiv.className = 'cf-message cf-bot';
|
|
111
|
-
messageDiv.setAttribute('data-chat-message', 'bot');
|
|
112
|
-
|
|
113
117
|
// Determine input type attribute value
|
|
114
118
|
const inputTypeAttr = isSingleSelect ? 'single-select-input' : 'multi-select-input';
|
|
119
|
+
|
|
120
|
+
// Find existing option element in HTML by data-chat-element
|
|
121
|
+
const optionSelector = `[data-chat-element="${inputTypeAttr}"]`;
|
|
122
|
+
const existingOption = document.querySelector(optionSelector);
|
|
115
123
|
|
|
116
|
-
|
|
124
|
+
if (!existingOption) {
|
|
125
|
+
console.error(`Element with ${optionSelector} not found in HTML. Please add it to your HTML.`);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Create wrapper to hold all options
|
|
130
|
+
const optionsWrapper = document.createElement('div');
|
|
131
|
+
optionsWrapper.setAttribute('data-chat-element', 'options-wrapper');
|
|
132
|
+
|
|
133
|
+
// Clone and fill option element for each option
|
|
134
|
+
options.forEach((option, index) => {
|
|
117
135
|
const optionName = option.name || option;
|
|
118
136
|
const optionValue = option.value !== undefined ? option.value : option;
|
|
119
137
|
const valueStr = typeof optionValue === 'object' ?
|
|
120
138
|
JSON.stringify(optionValue) : String(optionValue);
|
|
121
139
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
`;
|
|
153
|
-
|
|
154
|
-
elements.messages.appendChild(messageDiv);
|
|
140
|
+
// Clone existing option element
|
|
141
|
+
const clone = existingOption.cloneNode(true);
|
|
142
|
+
|
|
143
|
+
// Set data attributes on container
|
|
144
|
+
clone.setAttribute('data-chat-element', inputTypeAttr);
|
|
145
|
+
clone.setAttribute('data-field', field);
|
|
146
|
+
clone.setAttribute('data-value', valueStr);
|
|
147
|
+
clone.setAttribute('data-name', optionName);
|
|
148
|
+
clone.setAttribute('data-index', index);
|
|
149
|
+
|
|
150
|
+
// Find and set input
|
|
151
|
+
const input = clone.querySelector('[data-chat-input-element="input"]');
|
|
152
|
+
if (input) {
|
|
153
|
+
input.setAttribute('data-chat-element', inputTypeAttr);
|
|
154
|
+
input.name = field;
|
|
155
|
+
input.value = valueStr;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Find and set text
|
|
159
|
+
const textElement = clone.querySelector('[data-chat-input-element="text"]');
|
|
160
|
+
if (textElement) {
|
|
161
|
+
textElement.textContent = optionName;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Append to wrapper
|
|
165
|
+
optionsWrapper.appendChild(clone);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Append wrapper to messages
|
|
169
|
+
elements.messages.appendChild(optionsWrapper);
|
|
155
170
|
scrollToBottom();
|
|
156
171
|
|
|
157
|
-
// Add click handlers
|
|
158
|
-
const optionElements =
|
|
172
|
+
// Add click handlers
|
|
173
|
+
const optionElements = optionsWrapper.querySelectorAll('[data-chat-input-element="container"]');
|
|
159
174
|
optionElements.forEach(el => {
|
|
160
175
|
el.onclick = () => handleOptionClick(el, field, isSingleSelect);
|
|
161
176
|
});
|
|
@@ -388,11 +403,13 @@ function handleCompletion() {
|
|
|
388
403
|
// INITIALIZATION
|
|
389
404
|
// =============================================================================
|
|
390
405
|
|
|
391
|
-
function init(
|
|
392
|
-
//
|
|
393
|
-
elements.container = document.
|
|
406
|
+
function init(flowName, flowConfig) {
|
|
407
|
+
// Find container by data-chat-element="chat-wrapper"
|
|
408
|
+
elements.container = document.querySelector('[data-chat-element="chat-wrapper"]');
|
|
409
|
+
|
|
394
410
|
if (!elements.container) {
|
|
395
|
-
console.error('Container not found
|
|
411
|
+
console.error('Container with data-chat-element="chat-wrapper" not found');
|
|
412
|
+
console.error('Please add <div data-chat-element="chat-wrapper"></div> to your HTML');
|
|
396
413
|
return null;
|
|
397
414
|
}
|
|
398
415
|
|
|
@@ -410,34 +427,32 @@ function init(containerId, flowConfig) {
|
|
|
410
427
|
chatState.history = [];
|
|
411
428
|
chatState.currentSelection = null;
|
|
412
429
|
|
|
413
|
-
//
|
|
414
|
-
elements.container.
|
|
415
|
-
|
|
416
|
-
<div class="cf-messages"
|
|
417
|
-
id="cfMessages"
|
|
418
|
-
data-chat-element="messages-container"></div>
|
|
419
|
-
<div class="cf-bottom"
|
|
420
|
-
data-chat-element="navigation-bottom">
|
|
421
|
-
<button id="cfNextBtn"
|
|
422
|
-
class="cf-next-btn"
|
|
423
|
-
data-chat-element="next-button"
|
|
424
|
-
style="opacity: 0.5; cursor: not-allowed;"
|
|
425
|
-
disabled>
|
|
426
|
-
Next →
|
|
427
|
-
</button>
|
|
428
|
-
</div>
|
|
429
|
-
</div>
|
|
430
|
-
`;
|
|
430
|
+
// Find existing elements (don't create new ones)
|
|
431
|
+
elements.messages = elements.container.querySelector('[data-chat-element="messages-container"]');
|
|
432
|
+
elements.nextBtn = elements.container.querySelector('[data-chat-element="next-button"]');
|
|
431
433
|
|
|
432
|
-
//
|
|
433
|
-
elements.messages
|
|
434
|
-
|
|
434
|
+
// Validate required elements exist
|
|
435
|
+
if (!elements.messages) {
|
|
436
|
+
console.error('messages-container not found. Please add <div data-chat-element="messages-container"></div>');
|
|
437
|
+
return null;
|
|
438
|
+
}
|
|
435
439
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
440
|
+
if (!elements.nextBtn) {
|
|
441
|
+
console.error('next-button not found. Please add <button data-chat-element="next-button"></button>');
|
|
442
|
+
return null;
|
|
439
443
|
}
|
|
440
444
|
|
|
445
|
+
// Clear ONLY messages container (not entire chat-wrapper)
|
|
446
|
+
elements.messages.innerHTML = '';
|
|
447
|
+
|
|
448
|
+
// Reset button state
|
|
449
|
+
elements.nextBtn.disabled = true;
|
|
450
|
+
elements.nextBtn.style.opacity = '0.5';
|
|
451
|
+
elements.nextBtn.style.cursor = 'not-allowed';
|
|
452
|
+
|
|
453
|
+
// Add event listener
|
|
454
|
+
elements.nextBtn.onclick = handleNext;
|
|
455
|
+
|
|
441
456
|
// Expose editStep globally for onclick handlers
|
|
442
457
|
if (typeof window !== 'undefined') {
|
|
443
458
|
window.editStep = editStep;
|
|
@@ -446,12 +461,13 @@ function init(containerId, flowConfig) {
|
|
|
446
461
|
// Start
|
|
447
462
|
showNextStep();
|
|
448
463
|
|
|
449
|
-
console.log(
|
|
464
|
+
console.log(`✅ Flow "${flowName}" initialized`);
|
|
450
465
|
|
|
451
466
|
return {
|
|
452
467
|
getState,
|
|
453
468
|
reset,
|
|
454
|
-
goToStep
|
|
469
|
+
goToStep,
|
|
470
|
+
editStep
|
|
455
471
|
};
|
|
456
472
|
}
|
|
457
473
|
|