lisichatbot 1.0.2 → 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +101 -81
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisichatbot",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "type": "module",
5
5
  "main": "./src/index.js",
6
6
  "exports": {
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
- const messageDiv = document.createElement('div');
71
- messageDiv.className = `cf-message cf-${type}`;
72
- messageDiv.setAttribute('data-chat-element', `${type}-message-wrapper`);
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
- messageDiv.setAttribute('data-chat-step', stepNumber);
84
+ clone.setAttribute('data-chat-step', stepNumber);
76
85
  }
77
-
78
- let editIcon = '';
79
- if (isEditable && type === 'user') {
80
- editIcon = `
81
- <button class="cf-edit-icon"
82
- data-chat-element="edit-button"
83
- data-chat-step="${stepNumber}"
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
- messageDiv.innerHTML = `
92
- <div class="cf-message-content" data-chat-element="${type}-message-text">
93
- ${content}
94
- </div>
95
- ${editIcon}
96
- `;
97
-
98
- elements.messages.appendChild(messageDiv);
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
- const optionsHtml = options.map((option, index) => {
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
- return `
123
- <label class="cf-option ${isSingleSelect ? 'cf-single' : 'cf-multi'}"
124
- data-chat-input-element="container"
125
- data-chat-element="${inputTypeAttr}"
126
- data-field="${field}"
127
- data-value='${valueStr}'
128
- data-name="${optionName}"
129
- data-index="${index}">
130
-
131
- <div class="cf-tick"
132
- data-chat-input-element="tick-icon"
133
- style="display: none;">✓</div>
134
-
135
- <input type="${isSingleSelect ? 'radio' : 'checkbox'}"
136
- name="${field}"
137
- value="${valueStr}"
138
- data-chat-input-element="input"
139
- data-chat-element="${inputTypeAttr}"
140
- style="display: none;">
141
-
142
- <span class="cf-option-text"
143
- data-chat-input-element="text">${optionName}</span>
144
- </label>
145
- `;
146
- }).join('');
147
-
148
- messageDiv.innerHTML = `
149
- <div class="cf-message-content" data-chat-element="bot-message-text">
150
- <div class="cf-options" data-chat-element="options-wrapper">${optionsHtml}</div>
151
- </div>
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 using custom attribute selector
158
- const optionElements = messageDiv.querySelectorAll('[data-chat-input-element="container"]');
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
  });
@@ -412,27 +427,32 @@ function init(flowName, flowConfig) {
412
427
  chatState.history = [];
413
428
  chatState.currentSelection = null;
414
429
 
415
- // Clear existing content and create structure
416
- elements.container.innerHTML = `
417
- <div data-chat-element="messages-container"></div>
418
- <div data-chat-element="navigation-bottom">
419
- <button data-chat-element="next-button"
420
- style="opacity: 0.5; cursor: not-allowed;"
421
- disabled>
422
- Next →
423
- </button>
424
- </div>
425
- `;
426
-
427
- // Get elements by data-chat-element
430
+ // Find existing elements (don't create new ones)
428
431
  elements.messages = elements.container.querySelector('[data-chat-element="messages-container"]');
429
432
  elements.nextBtn = elements.container.querySelector('[data-chat-element="next-button"]');
430
433
 
431
- // Add event listener
432
- if (elements.nextBtn) {
433
- elements.nextBtn.onclick = handleNext;
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
+ }
439
+
440
+ if (!elements.nextBtn) {
441
+ console.error('next-button not found. Please add <button data-chat-element="next-button"></button>');
442
+ return null;
434
443
  }
435
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
+
436
456
  // Expose editStep globally for onclick handlers
437
457
  if (typeof window !== 'undefined') {
438
458
  window.editStep = editStep;