embeddedaichatux 2.2.0 → 2.3.0
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/EmbeddedChat.js +231 -160
- package/package.json +1 -1
package/EmbeddedChat.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
class EmbeddedChat {
|
|
2
2
|
static instanceCounter = 0;
|
|
3
3
|
|
|
4
4
|
constructor(containerDiv, chatId, options) {
|
|
@@ -7,22 +7,26 @@
|
|
|
7
7
|
|
|
8
8
|
if (!containerDiv) {
|
|
9
9
|
containerDiv = this.createChatContainer();
|
|
10
|
+
this.createdContainer = true;
|
|
11
|
+
} else {
|
|
12
|
+
this.createdContainer = false;
|
|
10
13
|
}
|
|
11
14
|
this.containerDiv = containerDiv;
|
|
12
15
|
this.chatId = chatId;
|
|
13
16
|
this.options = options || {};
|
|
14
17
|
this.isPreview = this.options.isPreview || false;
|
|
15
18
|
this.locale = options.locale || 'en';
|
|
16
|
-
|
|
19
|
+
|
|
17
20
|
this.serverUrl = this.options.serverUrl || 'https://app.bizdriver.ai/';
|
|
18
21
|
this.height = options.height || 600; // Default height
|
|
19
|
-
this.width = options.width ||
|
|
22
|
+
this.width = options.width || 400; // Default width
|
|
20
23
|
this.marginBottom = options.marginBottom || 0;
|
|
21
24
|
this.enableAnimation = options.enableAnimation !== false; // Default to true if not provided
|
|
22
|
-
this.
|
|
25
|
+
this.theme = options.theme || this.containerDiv.dataset.theme || 'Standard';
|
|
26
|
+
this.minimizedHeight = this.theme === 'MinimalInput' ? "75px" : "80px"; // Default heights for different themes
|
|
23
27
|
this.hasMeasuredSize = false;
|
|
24
28
|
this.mouseInsideChat = false;
|
|
25
|
-
|
|
29
|
+
|
|
26
30
|
this.conversationId = null;
|
|
27
31
|
this.userTokenProvider = options.userTokenProvider;
|
|
28
32
|
this.targetOrigin = "*";
|
|
@@ -33,7 +37,9 @@
|
|
|
33
37
|
this.position = this.options.position || this.containerDiv.dataset.position || 'fixed';
|
|
34
38
|
this.positionStyle = this.position === 'in-place' ?
|
|
35
39
|
`position: relative; width:100%; height:${this.height}px; ${transitionStyle}` :
|
|
36
|
-
|
|
40
|
+
(this.theme === 'MinimalInput' ?
|
|
41
|
+
`position: fixed; left: 0; right: 0; margin-left: auto; margin-right: auto; width: 100%; max-width: ${this.width}px; bottom: ${this.marginBottom}px; z-index: 100000; max-height: 90vh; ${transitionStyle}` :
|
|
42
|
+
`position: fixed; right: 1em; bottom: ${this.marginBottom}px; width: 100%; max-width: ${this.width}px; z-index: 100000; max-height: 90vh; ${transitionStyle}`);
|
|
37
43
|
this.mode = options.mode || 'Chat'; // default to 'chat'
|
|
38
44
|
this.minimizeOnScroll = false; // Default to false
|
|
39
45
|
if (this.mode === 'ContactForm' || this.mode === 'PartnerOffers') {
|
|
@@ -52,6 +58,13 @@
|
|
|
52
58
|
this.init();
|
|
53
59
|
}
|
|
54
60
|
|
|
61
|
+
queueDOMUpdate(fn) {
|
|
62
|
+
requestAnimationFrame(() => {
|
|
63
|
+
if (this.isDestroyed) return;
|
|
64
|
+
fn();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
55
68
|
isSafari() {
|
|
56
69
|
const ua = navigator.userAgent.toLowerCase();
|
|
57
70
|
return ua.indexOf('safari') != -1 && ua.indexOf('chrome') == -1;
|
|
@@ -89,17 +102,31 @@
|
|
|
89
102
|
}
|
|
90
103
|
|
|
91
104
|
async updateIframes() {
|
|
105
|
+
if (this.isDestroyed) return;
|
|
106
|
+
|
|
92
107
|
const cleanedServerUrl = this.serverUrl.endsWith('/')
|
|
93
108
|
? this.serverUrl.slice(0, -1)
|
|
94
109
|
: this.serverUrl;
|
|
95
110
|
const baseIframeUrl = `${cleanedServerUrl}/ChatUX/${this.chatId}`;
|
|
111
|
+
const transitionStyle = this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : '';
|
|
112
|
+
|
|
113
|
+
// Recalculate positionStyle conditionally in case theme changed dynamically
|
|
114
|
+
this.positionStyle = this.position === 'in-place' ?
|
|
115
|
+
`position: relative; width:100%; height:${this.height}px; ${transitionStyle}` :
|
|
116
|
+
(this.theme === 'MinimalInput' ?
|
|
117
|
+
`position: fixed; left: 0; right: 0; margin-left: auto; margin-right: auto; bottom: ${this.marginBottom}px; width: 95vw; max-width: ${this.width}px; z-index: 100000; max-height: 90vh; pointer-events: auto; ${transitionStyle}` :
|
|
118
|
+
`position: fixed; right: 1em; bottom: ${this.marginBottom}px; width: ${this.width}px; z-index: 100000; max-width:90vw; max-height: 90vh; pointer-events: auto; ${transitionStyle}`);
|
|
119
|
+
|
|
96
120
|
const minimizedPositionStyle = this.position === 'in-place' ?
|
|
97
|
-
`position: relative; width: 100%; height: ${this.minimizedHeight}; ${
|
|
98
|
-
|
|
121
|
+
`position: relative; width: 100%; height: ${this.minimizedHeight}; ${transitionStyle}` :
|
|
122
|
+
(this.theme === 'MinimalInput' ?
|
|
123
|
+
`position: fixed; left: 0; right: 0; margin-left: auto; margin-right: auto; bottom: ${this.marginBottom}px; width: 100vw; max-width: ${Math.min(300, this.width) + 40}px; height: ${this.minimizedHeight}; z-index: 100000; pointer-events: auto; ${transitionStyle}` :
|
|
124
|
+
`position: fixed; right: 0; bottom: ${this.marginBottom}px; width: 150px; height: ${this.minimizedHeight}; z-index: 100000; max-width: 95vw; pointer-events: auto; ${transitionStyle}`);
|
|
99
125
|
|
|
100
126
|
const params = {
|
|
101
127
|
isPreview: this.isPreview,
|
|
102
128
|
mode: this.mode,
|
|
129
|
+
theme: this.theme,
|
|
103
130
|
locale: this.locale,
|
|
104
131
|
conversationId: this.conversationId,
|
|
105
132
|
instanceId: this.instanceId,
|
|
@@ -138,17 +165,26 @@
|
|
|
138
165
|
if (this.iframe) {
|
|
139
166
|
await this.waitForIframeLoad(this.iframe);
|
|
140
167
|
}
|
|
168
|
+
if (this.isDestroyed) return;
|
|
141
169
|
|
|
142
170
|
this.addIframeEventListeners();
|
|
143
171
|
|
|
144
172
|
// Send auth to iframes after load
|
|
145
173
|
await this.postAuthToIframes();
|
|
174
|
+
if (this.isDestroyed) return;
|
|
146
175
|
|
|
147
|
-
//
|
|
176
|
+
// Restore ContactForm logic
|
|
148
177
|
if (this.mode === 'ContactForm' || this.mode === 'PartnerOffers') {
|
|
149
178
|
this.iframe.style.maxWidth = '100%';
|
|
150
179
|
this.iframe.style.display = 'block';
|
|
151
180
|
}
|
|
181
|
+
|
|
182
|
+
// Apply pointer-events to container if theme is MinimalInput to prevent blocking page
|
|
183
|
+
if (this.theme === 'MinimalInput' && this.position !== 'in-place') {
|
|
184
|
+
this.containerDiv.style.pointerEvents = 'none';
|
|
185
|
+
} else {
|
|
186
|
+
this.containerDiv.style.pointerEvents = 'auto'; // Reset for other themes
|
|
187
|
+
}
|
|
152
188
|
}
|
|
153
189
|
|
|
154
190
|
addIframeEventListeners() {
|
|
@@ -163,41 +199,40 @@
|
|
|
163
199
|
}
|
|
164
200
|
|
|
165
201
|
addWindowEventListeners() {
|
|
166
|
-
|
|
167
|
-
// Use a flag to ensure window listeners aren't duplicated for this specific instance if setMode is called (though it shouldn't be)
|
|
168
202
|
if (this.windowListenersAdded) return;
|
|
169
203
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
|
|
204
|
+
this.listeners = [
|
|
205
|
+
{ type: "message", fn: (e) => {
|
|
206
|
+
if (this.targetOrigin !== "*" && e.origin !== this.targetOrigin) return;
|
|
207
|
+
this.handleMessage(e);
|
|
208
|
+
}},
|
|
209
|
+
{ type: "scroll", fn: () => {
|
|
210
|
+
if (this.minimizeOnScroll && !this.mouseInsideChat) {
|
|
211
|
+
this.queueDOMUpdate(() => this.minimizeOnScrollAction());
|
|
212
|
+
}
|
|
213
|
+
}},
|
|
214
|
+
{ type: "resize", fn: () => this.queueDOMUpdate(() => this.postResizeMessage()) }
|
|
215
|
+
];
|
|
181
216
|
|
|
182
|
-
|
|
183
|
-
this.postResizeMessage();
|
|
184
|
-
};
|
|
217
|
+
this.listeners.forEach(l => window.addEventListener(l.type, l.fn));
|
|
185
218
|
|
|
219
|
+
const loadFn = () => this.queueDOMUpdate(() => this.postResizeMessage());
|
|
186
220
|
if (document.readyState === 'complete') {
|
|
187
|
-
|
|
221
|
+
loadFn();
|
|
188
222
|
} else {
|
|
189
|
-
|
|
223
|
+
this.listeners.push({ type: "load", fn: loadFn });
|
|
224
|
+
window.addEventListener("load", loadFn);
|
|
190
225
|
}
|
|
191
226
|
|
|
192
|
-
window.addEventListener("resize", handleResizeTrigger);
|
|
193
227
|
this.windowListenersAdded = true;
|
|
194
228
|
}
|
|
195
229
|
|
|
196
230
|
postResizeMessage() {
|
|
231
|
+
if (this.isDestroyed) return;
|
|
197
232
|
if (this.iframe?.contentWindow) {
|
|
198
233
|
this.iframe.contentWindow.postMessage({
|
|
199
234
|
message: "resize",
|
|
200
|
-
width: window.innerWidth,
|
|
235
|
+
width: window.innerWidth,
|
|
201
236
|
height: window.innerHeight,
|
|
202
237
|
instanceId: this.instanceId
|
|
203
238
|
}, this.targetOrigin);
|
|
@@ -205,11 +240,9 @@
|
|
|
205
240
|
}
|
|
206
241
|
|
|
207
242
|
handleMessage(e) {
|
|
208
|
-
// Only trust messages from our server (when targetOrigin is not "*")
|
|
209
243
|
if (this.targetOrigin !== "*" && e.origin !== this.targetOrigin) return;
|
|
210
244
|
|
|
211
245
|
if (typeof e.data !== "object") {
|
|
212
|
-
// Preserve original handling for string messages
|
|
213
246
|
if (typeof e.data === "string") {
|
|
214
247
|
if (e.data === "minimize") {
|
|
215
248
|
this.animateMinimize();
|
|
@@ -234,65 +267,76 @@
|
|
|
234
267
|
const targetChatId = (this.chatId || "").toString().toLowerCase();
|
|
235
268
|
const incomingInstanceId = data.instanceId;
|
|
236
269
|
|
|
237
|
-
// Priority 1: Handle instance-specific routing
|
|
238
270
|
if (incomingInstanceId && incomingInstanceId !== this.instanceId) return;
|
|
239
|
-
|
|
240
|
-
// Priority 2: Bail out if chatId doesn't match and is provided (legacy/fallback)
|
|
241
271
|
if (!incomingInstanceId && incomingChatId && targetChatId && incomingChatId !== targetChatId) return;
|
|
242
272
|
|
|
243
|
-
// Allow the iframe to request a fresh token
|
|
244
273
|
if (data.type === "requestAuth") {
|
|
245
274
|
this.postAuthToIframes();
|
|
246
275
|
return;
|
|
247
276
|
}
|
|
248
277
|
|
|
249
|
-
// Priority 1: Handle minimized size updates (CRITICAL: Bail out early and DO NOT pollute configuration)
|
|
250
278
|
if (msg === "updateMinimizedSize") {
|
|
251
|
-
// Support both new and legacy keys for compatibility with cached scripts
|
|
252
279
|
const h = data.minimizedHeight || data.height;
|
|
253
280
|
const w = data.minimizedWidth || data.width;
|
|
254
|
-
this.updateMinimizedSize(h, w);
|
|
281
|
+
this.queueDOMUpdate(() => this.updateMinimizedSize(h, w));
|
|
255
282
|
return;
|
|
256
283
|
}
|
|
257
284
|
|
|
258
|
-
|
|
285
|
+
if (msg === "collapseMinimalInput") {
|
|
286
|
+
this.queueDOMUpdate(() => {
|
|
287
|
+
if (this.minimizedIframe) {
|
|
288
|
+
Object.assign(this.minimizedIframe.style, {
|
|
289
|
+
width: '80px', height: '80px', left: 'auto', right: '0',
|
|
290
|
+
marginLeft: '0', marginRight: '0', pointerEvents: 'auto'
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
259
296
|
|
|
297
|
+
if (msg === "restoreMinimalInput") {
|
|
298
|
+
this.queueDOMUpdate(() => {
|
|
299
|
+
if (this.minimizedIframe) {
|
|
300
|
+
Object.assign(this.minimizedIframe.style, {
|
|
301
|
+
width: '100vw', maxWidth: `${Math.min(300, this.width) + 40}px`,
|
|
302
|
+
height: this.theme === 'MinimalInput' ? "75px" : this.minimizedHeight,
|
|
303
|
+
left: '0', right: '0', marginLeft: 'auto', marginRight: 'auto',
|
|
304
|
+
pointerEvents: 'auto'
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
if (this.theme === 'MinimalInput' && this.position !== 'in-place') {
|
|
308
|
+
this.containerDiv.style.pointerEvents = 'none';
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
const updates = {};
|
|
260
315
|
if (data.type === "setMinimizeOnScroll" || data.minimizeOnScroll !== undefined) {
|
|
261
316
|
const minimizeValue = data.type === "setMinimizeOnScroll" ? data.value : data.minimizeOnScroll;
|
|
262
317
|
this.minimizeOnScroll = minimizeValue === true || minimizeValue === "true";
|
|
263
318
|
}
|
|
264
319
|
|
|
265
|
-
if (data.locale)
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
if (data.
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if (data.height) {
|
|
272
|
-
updates.height = data.height;
|
|
273
|
-
}
|
|
274
|
-
if (data.marginBottom) {
|
|
275
|
-
updates.marginBottom = data.marginBottom;
|
|
276
|
-
}
|
|
277
|
-
if (data.scale) {
|
|
278
|
-
updates.scale = data.scale;
|
|
279
|
-
}
|
|
320
|
+
if (data.locale) updates.locale = data.locale;
|
|
321
|
+
if (data.width) updates.width = data.width;
|
|
322
|
+
if (data.height) updates.height = data.height;
|
|
323
|
+
if (data.marginBottom) updates.marginBottom = data.marginBottom;
|
|
324
|
+
if (data.scale) updates.scale = data.scale;
|
|
325
|
+
if (data.theme) updates.theme = data.theme;
|
|
280
326
|
|
|
281
|
-
// Apply iframe updates in one go
|
|
282
327
|
if (Object.keys(updates).length > 0) {
|
|
283
|
-
this.applyIframeUpdates(updates);
|
|
328
|
+
this.queueDOMUpdate(() => this.applyIframeUpdates(updates));
|
|
284
329
|
}
|
|
285
330
|
|
|
286
|
-
// Handle maximize/minimize/navigate
|
|
287
331
|
if (msg === "minimize") {
|
|
288
332
|
if (typeof this.options.onMinimize === 'function') {
|
|
289
333
|
this.options.onMinimize();
|
|
290
334
|
} else if (this.mode !== 'ContactForm' && this.mode !== 'PartnerOffers') {
|
|
291
|
-
this.animateMinimize();
|
|
335
|
+
this.queueDOMUpdate(() => this.animateMinimize());
|
|
292
336
|
}
|
|
293
337
|
} else if (msg === "show" || msg === "maximize") {
|
|
294
338
|
const animate = data.animate === true;
|
|
295
|
-
this.showMaximized(animate);
|
|
339
|
+
this.queueDOMUpdate(() => this.showMaximized(animate, data.initialMessage));
|
|
296
340
|
} else if (msg === "navigate" && data.url) {
|
|
297
341
|
window.location.href = data.url;
|
|
298
342
|
} else if (data.type === "switchToChat" || msg === "switchToChat") {
|
|
@@ -309,24 +353,24 @@
|
|
|
309
353
|
}
|
|
310
354
|
}
|
|
311
355
|
|
|
312
|
-
// Handle conversationId update
|
|
313
356
|
if (data.conversationId) {
|
|
314
357
|
this.setConversationId(data.conversationId);
|
|
315
358
|
}
|
|
316
359
|
}
|
|
317
360
|
|
|
318
361
|
animateMinimize() {
|
|
362
|
+
if (this.isDestroyed) return;
|
|
319
363
|
if (this.mode !== 'ContactForm' && this.mode !== 'PartnerOffers') {
|
|
320
364
|
this.iframe.style.height = this.minimizedHeight;
|
|
321
365
|
this.iframe.style.opacity = '0';
|
|
322
366
|
setTimeout(() => {
|
|
367
|
+
if (this.isDestroyed) return;
|
|
323
368
|
this.iframe.style.display = "none";
|
|
324
369
|
this.iframe.style.opacity = '1';
|
|
325
370
|
this.minimizedIframe.style.display = "block";
|
|
326
371
|
this.minimizedIframe.style.height = this.minimizedHeight;
|
|
327
372
|
this.minimizedIframe.style.opacity = '1';
|
|
328
373
|
|
|
329
|
-
// Request a height update after showing
|
|
330
374
|
if (this.minimizedIframe.contentWindow) {
|
|
331
375
|
this.minimizedIframe.contentWindow.postMessage({ message: "requestHeightUpdate", instanceId: this.instanceId }, this.targetOrigin);
|
|
332
376
|
}
|
|
@@ -335,11 +379,11 @@
|
|
|
335
379
|
}
|
|
336
380
|
|
|
337
381
|
updateMinimizedSize(contentHeight, contentWidth) {
|
|
382
|
+
if (this.isDestroyed) return;
|
|
338
383
|
if (this.mode === 'ContactForm' || this.mode === 'PartnerOffers') return;
|
|
339
384
|
|
|
340
385
|
this.hasMeasuredSize = true;
|
|
341
386
|
|
|
342
|
-
// Apply height update
|
|
343
387
|
if (contentHeight && contentHeight >= 10) {
|
|
344
388
|
const newHeight = `${contentHeight}px`;
|
|
345
389
|
this.minimizedHeight = newHeight;
|
|
@@ -348,9 +392,8 @@
|
|
|
348
392
|
}
|
|
349
393
|
}
|
|
350
394
|
|
|
351
|
-
// Apply width update
|
|
352
395
|
if (contentWidth && contentWidth >= 10) {
|
|
353
|
-
if (this.minimizedIframe) {
|
|
396
|
+
if (this.minimizedIframe && this.theme !== 'MinimalInput') {
|
|
354
397
|
this.minimizedIframe.style.width = `${contentWidth}px`;
|
|
355
398
|
}
|
|
356
399
|
}
|
|
@@ -358,97 +401,127 @@
|
|
|
358
401
|
|
|
359
402
|
animateMaximize() {
|
|
360
403
|
if (this.mode !== 'ContactForm' && this.mode !== 'PartnerOffers') {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
this.minimizedIframe.style.opacity = '0';
|
|
364
|
-
|
|
365
|
-
setTimeout(() => {
|
|
366
|
-
// Hide the minimized iframe
|
|
404
|
+
const onMinimizedAnimateEnd = () => {
|
|
405
|
+
this.minimizedIframe.removeEventListener("transitionend", onMinimizedAnimateEnd);
|
|
367
406
|
this.minimizedIframe.style.display = "none";
|
|
368
|
-
this.minimizedIframe.style.opacity = '1';
|
|
407
|
+
this.minimizedIframe.style.opacity = '1';
|
|
369
408
|
|
|
370
|
-
// Show and animate the main iframe
|
|
371
409
|
this.iframe.style.display = "block";
|
|
372
|
-
this.iframe.style.height = this.minimizedHeight;
|
|
373
|
-
this.iframe.style.opacity =
|
|
410
|
+
this.iframe.style.height = this.minimizedHeight;
|
|
411
|
+
this.iframe.style.opacity = "0";
|
|
374
412
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
413
|
+
this.iframe.offsetHeight;
|
|
414
|
+
|
|
415
|
+
this.iframe.style.height = `${this.height}px`;
|
|
416
|
+
this.iframe.style.opacity = "1";
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
if (this.enableAnimation) {
|
|
420
|
+
this.minimizedIframe.addEventListener("transitionend", onMinimizedAnimateEnd);
|
|
421
|
+
this.minimizedIframe.style.height = this.minimizedHeight;
|
|
422
|
+
this.minimizedIframe.style.opacity = "0";
|
|
423
|
+
|
|
424
|
+
// Notify iframe when maximize transition finishes to ensure final scroll-into-view
|
|
425
|
+
this.iframe.addEventListener("transitionend", (e) => {
|
|
426
|
+
if (e.propertyName === 'height' && this.iframe.style.display !== 'none') {
|
|
427
|
+
if (this.iframe.contentWindow) {
|
|
428
|
+
this.iframe.contentWindow.postMessage({ message: "maximizeComplete", instanceId: this.instanceId }, this.targetOrigin);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}, { once: true });
|
|
432
|
+
} else {
|
|
433
|
+
onMinimizedAnimateEnd();
|
|
434
|
+
}
|
|
381
435
|
}
|
|
382
436
|
}
|
|
383
437
|
|
|
384
|
-
applyIframeUpdates({ locale, width, height, marginBottom, scale } = {}) {
|
|
385
|
-
|
|
438
|
+
applyIframeUpdates({ locale, width, height, marginBottom, scale, theme } = {}) {
|
|
439
|
+
if (this.isDestroyed) return;
|
|
440
|
+
if (theme && typeof theme === 'string' && theme !== this.theme) {
|
|
441
|
+
this.theme = theme;
|
|
442
|
+
console.log(`Theme updated to: ${this.theme}`);
|
|
443
|
+
this.minimizedHeight = this.theme === 'MinimalInput' ? "75px" : "80px";
|
|
444
|
+
this.updateIframes();
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
386
448
|
if (locale && typeof locale === 'string' && locale !== this.locale) {
|
|
387
449
|
this.locale = locale;
|
|
388
450
|
console.log(`Locale stored locally: ${this.locale}`);
|
|
389
451
|
}
|
|
390
452
|
|
|
391
|
-
// Update width if provided and different
|
|
392
453
|
const parsedWidth = parseInt(width, 10);
|
|
393
454
|
if (!isNaN(parsedWidth) && parsedWidth > 0 && parsedWidth !== this.width) {
|
|
394
455
|
this.width = parsedWidth;
|
|
395
456
|
console.log(`Width updated to: ${this.width}px`);
|
|
396
457
|
|
|
397
|
-
// Apply width only if not in-place
|
|
398
458
|
if (this.position !== 'in-place') {
|
|
399
|
-
this.
|
|
400
|
-
|
|
401
|
-
this.
|
|
459
|
+
if (this.theme === 'MinimalInput') {
|
|
460
|
+
this.containerDiv.style.width = '100vw'; // Use 100vw but keep pointerEvents none
|
|
461
|
+
this.containerDiv.style.left = '0';
|
|
462
|
+
this.containerDiv.style.right = '0';
|
|
463
|
+
this.containerDiv.style.marginLeft = 'auto';
|
|
464
|
+
this.containerDiv.style.marginRight = 'auto';
|
|
465
|
+
this.containerDiv.style.pointerEvents = 'none'; // Prevent invisible area from blocking clicks
|
|
466
|
+
if (this.iframe) {
|
|
467
|
+
this.iframe.style.width = '95vw';
|
|
468
|
+
this.iframe.style.maxWidth = `${this.width}px`;
|
|
469
|
+
this.iframe.style.pointerEvents = 'auto';
|
|
470
|
+
this.iframe.style.left = '0';
|
|
471
|
+
this.iframe.style.right = '0';
|
|
472
|
+
this.iframe.style.margin = 'auto';
|
|
473
|
+
}
|
|
474
|
+
if (this.minimizedIframe) {
|
|
475
|
+
this.minimizedIframe.style.width = '100vw'; // Use 100vw to allow centering
|
|
476
|
+
this.minimizedIframe.style.maxWidth = `${Math.min(300, this.width) + 40}px`;
|
|
477
|
+
this.minimizedIframe.style.pointerEvents = 'auto';
|
|
478
|
+
this.minimizedIframe.style.left = '0';
|
|
479
|
+
this.minimizedIframe.style.right = '0';
|
|
480
|
+
this.minimizedIframe.style.margin = 'auto';
|
|
481
|
+
}
|
|
482
|
+
} else {
|
|
483
|
+
this.containerDiv.style.width = `${this.width}px`;
|
|
484
|
+
this.containerDiv.style.pointerEvents = 'auto'; // Ensure auto for other themes
|
|
485
|
+
if (this.iframe) this.iframe.style.width = `${this.width}px`;
|
|
402
486
|
}
|
|
403
487
|
} else {
|
|
404
488
|
this.containerDiv.style.width = '100%';
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
489
|
+
this.containerDiv.style.pointerEvents = 'auto';
|
|
490
|
+
if (this.iframe) this.iframe.style.width = '100%';
|
|
408
491
|
}
|
|
409
492
|
}
|
|
410
493
|
|
|
411
|
-
// Apply scale if provided
|
|
412
494
|
if (typeof scale === 'number' && scale > 0) {
|
|
413
495
|
this.applyScale(scale);
|
|
414
496
|
console.log(`Scale applied: ${scale}`);
|
|
415
497
|
}
|
|
416
498
|
|
|
417
|
-
// Handle height and marginBottom
|
|
418
499
|
let parsedHeight = parseInt(height, 10);
|
|
419
500
|
let parsedMarginBottom = parseInt(marginBottom, 10);
|
|
420
501
|
|
|
421
|
-
|
|
422
|
-
if (isNaN(parsedHeight) || parsedHeight <= 0) {
|
|
423
|
-
parsedHeight = this.height;
|
|
424
|
-
}
|
|
502
|
+
if (isNaN(parsedHeight) || parsedHeight <= 0) parsedHeight = this.height;
|
|
425
503
|
if (isNaN(parsedMarginBottom) || parsedMarginBottom < 0) {
|
|
426
504
|
parsedMarginBottom = (typeof this.marginBottom === 'number') ? this.marginBottom : 0;
|
|
427
505
|
}
|
|
428
506
|
|
|
429
|
-
// Clamp so that height + marginBottom doesn't exceed 90% of viewport
|
|
430
507
|
const viewportHeight = window.innerHeight;
|
|
431
508
|
let effectiveHeight = parsedHeight;
|
|
432
509
|
if (effectiveHeight + parsedMarginBottom > 0.9 * viewportHeight) {
|
|
433
510
|
effectiveHeight = Math.max(100, 0.9 * viewportHeight - parsedMarginBottom);
|
|
434
511
|
}
|
|
435
512
|
|
|
436
|
-
// Only apply if there's an actual change
|
|
437
513
|
if (parsedHeight !== this.height || parsedMarginBottom !== this.marginBottom) {
|
|
438
514
|
this.height = parsedHeight;
|
|
439
515
|
this.marginBottom = parsedMarginBottom;
|
|
440
516
|
|
|
441
|
-
// Only use the 30% estimate if we haven't received a real measurement yet
|
|
442
517
|
if (!this.hasMeasuredSize) {
|
|
443
|
-
this.minimizedHeight =
|
|
518
|
+
this.minimizedHeight = this.theme === 'MinimalInput' ? "75px" : "80px";
|
|
444
519
|
}
|
|
445
520
|
|
|
446
|
-
console.log(`Height updated to: ${this.height}px
|
|
521
|
+
console.log(`Height updated to: ${this.height}px, marginBottom: ${this.marginBottom}px`);
|
|
447
522
|
|
|
448
|
-
// Apply the updated height/marginBottom
|
|
449
523
|
if (this.mode !== 'ContactForm' && this.mode !== 'PartnerOffers') {
|
|
450
524
|
if (this.position === 'in-place') {
|
|
451
|
-
// "in-place" uses full width, sets containerDiv height
|
|
452
525
|
this.containerDiv.style.position = 'relative';
|
|
453
526
|
this.containerDiv.style.width = '100%';
|
|
454
527
|
this.containerDiv.style.height = `${effectiveHeight}px`;
|
|
@@ -467,8 +540,6 @@
|
|
|
467
540
|
this.minimizedIframe.style.right = 'unset';
|
|
468
541
|
}
|
|
469
542
|
} else {
|
|
470
|
-
// position: fixed (typical floating chat)
|
|
471
|
-
// Update bottom offset, main height
|
|
472
543
|
if (this.iframe) {
|
|
473
544
|
this.iframe.style.height = `${this.height}px`;
|
|
474
545
|
this.iframe.style.bottom = `${this.marginBottom}px`;
|
|
@@ -476,34 +547,38 @@
|
|
|
476
547
|
if (this.minimizedIframe) {
|
|
477
548
|
this.minimizedIframe.style.height = this.minimizedHeight;
|
|
478
549
|
this.minimizedIframe.style.bottom = `${this.marginBottom}px`;
|
|
550
|
+
if (this.theme === 'MinimalInput') {
|
|
551
|
+
this.minimizedIframe.style.width = '100vw';
|
|
552
|
+
this.minimizedIframe.style.maxWidth = `${Math.min(300, this.width) + 40}px`;
|
|
553
|
+
}
|
|
479
554
|
}
|
|
480
555
|
}
|
|
481
556
|
} else {
|
|
482
|
-
// ContactForm mode
|
|
483
557
|
this.containerDiv.style.height = `${this.height}px`;
|
|
484
|
-
if (this.iframe) {
|
|
485
|
-
this.iframe.style.height = `${this.height}px`;
|
|
486
|
-
}
|
|
558
|
+
if (this.iframe) this.iframe.style.height = `${this.height}px`;
|
|
487
559
|
}
|
|
488
560
|
}
|
|
489
561
|
}
|
|
490
562
|
|
|
491
|
-
showMaximized(animate = false) {
|
|
563
|
+
showMaximized(animate = false, initialMessage = null) {
|
|
564
|
+
if (this.isDestroyed) return;
|
|
492
565
|
const schedulePostMessage = () => {
|
|
493
566
|
if (this.iframe.contentWindow) {
|
|
494
567
|
this.iframe.contentWindow.postMessage({
|
|
495
568
|
message: "show",
|
|
496
569
|
sessionInfo: this.sessionInfo || null,
|
|
497
|
-
instanceId: this.instanceId
|
|
570
|
+
instanceId: this.instanceId,
|
|
571
|
+
initialMessage: initialMessage
|
|
498
572
|
}, this.targetOrigin);
|
|
499
573
|
} else {
|
|
500
|
-
// Schedule a single retry with a delay
|
|
501
574
|
setTimeout(() => {
|
|
575
|
+
if (this.isDestroyed) return;
|
|
502
576
|
if (this.iframe.contentWindow) {
|
|
503
577
|
this.iframe.contentWindow.postMessage({
|
|
504
578
|
message: "show",
|
|
505
579
|
sessionInfo: this.sessionInfo || null,
|
|
506
|
-
instanceId: this.instanceId
|
|
580
|
+
instanceId: this.instanceId,
|
|
581
|
+
initialMessage: initialMessage
|
|
507
582
|
}, this.targetOrigin);
|
|
508
583
|
} else {
|
|
509
584
|
console.warn("iframe contentWindow is not available.");
|
|
@@ -516,8 +591,7 @@
|
|
|
516
591
|
this.animateMaximize();
|
|
517
592
|
} else {
|
|
518
593
|
this.minimizedIframe.style.display = "none";
|
|
519
|
-
this.minimizedIframe.style.
|
|
520
|
-
this.minimizedIframe.style.opacity = ''; // Reset opacity to unset
|
|
594
|
+
this.minimizedIframe.style.opacity = '';
|
|
521
595
|
|
|
522
596
|
this.iframe.style.display = "block";
|
|
523
597
|
this.iframe.style.height = `${this.height}px`;
|
|
@@ -529,7 +603,8 @@
|
|
|
529
603
|
|
|
530
604
|
applyScale(scale) {
|
|
531
605
|
if (this.mode !== 'ContactForm' && this.mode !== 'PartnerOffers') {
|
|
532
|
-
|
|
606
|
+
let origin = this.position === 'in-place' ? 'top center' : 'bottom right';
|
|
607
|
+
if (this.theme === 'MinimalInput') origin = 'bottom center';
|
|
533
608
|
if (this.iframe) {
|
|
534
609
|
this.iframe.style.transform = `scale(${scale})`;
|
|
535
610
|
this.iframe.style.transformOrigin = origin;
|
|
@@ -542,16 +617,14 @@
|
|
|
542
617
|
}
|
|
543
618
|
|
|
544
619
|
minimizeOnScrollAction() {
|
|
620
|
+
if (this.isDestroyed) return;
|
|
545
621
|
if (this.mode !== 'ContactForm' && this.mode !== 'PartnerOffers' && this.iframe.style.display !== "none") {
|
|
546
622
|
this.animateMinimize();
|
|
547
623
|
}
|
|
548
624
|
}
|
|
549
625
|
|
|
550
626
|
setSessionInfo(sessionInfo) {
|
|
551
|
-
console.log('setSessionInfo called with sessionInfo:', sessionInfo);
|
|
552
627
|
this.sessionInfo = sessionInfo;
|
|
553
|
-
|
|
554
|
-
// Send session info immediately if the chat is already maximized
|
|
555
628
|
if (this.iframe?.contentWindow && this.iframe.style.display !== "none") {
|
|
556
629
|
this.iframe.contentWindow.postMessage({ type: 'setSessionInfo', sessionInfo: this.sessionInfo, instanceId: this.instanceId }, this.targetOrigin);
|
|
557
630
|
}
|
|
@@ -565,78 +638,56 @@
|
|
|
565
638
|
return chatContainer;
|
|
566
639
|
}
|
|
567
640
|
|
|
641
|
+
maximizeWithText(text) {
|
|
642
|
+
this.showMaximized(true, text);
|
|
643
|
+
}
|
|
644
|
+
|
|
568
645
|
buildIframeUrl(baseIframeUrl, params = {}) {
|
|
569
646
|
const urlParams = new URLSearchParams();
|
|
570
|
-
|
|
571
|
-
if (params.isPreview) {
|
|
572
|
-
urlParams.set('isPreview', 'true');
|
|
573
|
-
}
|
|
574
|
-
|
|
647
|
+
if (params.isPreview) urlParams.set('isPreview', 'true');
|
|
575
648
|
if (params.mode === 'ContactForm' || params.mode === 'PartnerOffers' || params.mode === 'Chat') {
|
|
576
649
|
urlParams.set('mode', params.mode);
|
|
577
650
|
}
|
|
578
|
-
|
|
579
|
-
if (params.
|
|
580
|
-
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
if (params.conversationId) {
|
|
584
|
-
urlParams.set('conversationId', params.conversationId);
|
|
585
|
-
}
|
|
651
|
+
if (params.locale) urlParams.set('locale', params.locale);
|
|
652
|
+
if (params.conversationId) urlParams.set('conversationId', params.conversationId);
|
|
653
|
+
if (params.instanceId) urlParams.set('instanceId', params.instanceId);
|
|
586
654
|
|
|
587
655
|
for (const [key, value] of Object.entries(params)) {
|
|
588
|
-
if (
|
|
656
|
+
if (!['mode', 'isPreview', 'conversationId', 'instanceId', 'userToken'].includes(key) && value !== null && value !== undefined) {
|
|
589
657
|
urlParams.set(key, value);
|
|
590
658
|
}
|
|
591
659
|
}
|
|
592
|
-
|
|
593
660
|
return `${baseIframeUrl}?${urlParams.toString()}`;
|
|
594
661
|
}
|
|
595
662
|
|
|
596
663
|
waitForIframeLoad(iframe, timeout = 10000) {
|
|
597
664
|
return new Promise((resolve) => {
|
|
598
|
-
// Set up a timeout to avoid waiting indefinitely
|
|
599
665
|
const timeoutId = setTimeout(() => {
|
|
600
666
|
console.warn('EmbeddedChat: Iframe load timeout, proceeding with initialization.');
|
|
601
667
|
resolve();
|
|
602
668
|
}, timeout);
|
|
603
669
|
|
|
604
|
-
// Add the load event listener
|
|
605
670
|
iframe.addEventListener('load', () => {
|
|
606
|
-
clearTimeout(timeoutId);
|
|
671
|
+
clearTimeout(timeoutId);
|
|
607
672
|
resolve();
|
|
608
|
-
}, { once: true });
|
|
673
|
+
}, { once: true });
|
|
609
674
|
});
|
|
610
675
|
}
|
|
611
676
|
|
|
612
677
|
async postAuthToIframes() {
|
|
613
|
-
|
|
614
|
-
if (typeof this.userTokenProvider !== 'function')
|
|
615
|
-
console.warn('[EmbeddedChat] No userTokenProvider function provided');
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
618
|
-
|
|
678
|
+
if (this.isDestroyed) return;
|
|
679
|
+
if (typeof this.userTokenProvider !== 'function') return;
|
|
619
680
|
try {
|
|
620
681
|
const userToken = await this.userTokenProvider();
|
|
621
|
-
|
|
622
|
-
if (!userToken) {
|
|
623
|
-
console.warn('[EmbeddedChat] userTokenProvider returned null/empty token');
|
|
624
|
-
return;
|
|
625
|
-
}
|
|
626
|
-
|
|
682
|
+
if (!userToken) return;
|
|
627
683
|
if (this.iframe?.contentWindow) {
|
|
628
|
-
console.log('[EmbeddedChat] Sending auth message to iframe with targetOrigin:', this.targetOrigin);
|
|
629
684
|
this.iframe.contentWindow.postMessage({
|
|
630
685
|
type: 'auth',
|
|
631
686
|
userToken: userToken,
|
|
632
687
|
chatId: this.chatId,
|
|
633
688
|
instanceId: this.instanceId
|
|
634
689
|
}, this.targetOrigin);
|
|
635
|
-
console.log('[EmbeddedChat] Auth message sent successfully');
|
|
636
|
-
} else {
|
|
637
|
-
console.error('[EmbeddedChat] iframe.contentWindow is not available');
|
|
638
690
|
}
|
|
639
|
-
// No longer send auth to minimizedIframe
|
|
640
691
|
} catch (err) {
|
|
641
692
|
console.error('[EmbeddedChat] Failed to get user token:', err);
|
|
642
693
|
}
|
|
@@ -647,9 +698,7 @@
|
|
|
647
698
|
|
|
648
699
|
console.log(`[EmbeddedChat] Setting mode to ${newMode}`, options);
|
|
649
700
|
this.mode = newMode;
|
|
650
|
-
if (options.chatId)
|
|
651
|
-
this.chatId = options.chatId;
|
|
652
|
-
}
|
|
701
|
+
if (options.chatId) this.chatId = options.chatId;
|
|
653
702
|
this.options = { ...this.options, ...options };
|
|
654
703
|
const transitionStyle = this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : '';
|
|
655
704
|
if (this.mode === 'ContactForm' || this.mode === 'PartnerOffers') {
|
|
@@ -659,7 +708,9 @@
|
|
|
659
708
|
} else {
|
|
660
709
|
this.positionStyle = this.position === 'in-place' ?
|
|
661
710
|
`position: relative; width:100%; height:${this.height}px; ${transitionStyle}` :
|
|
662
|
-
|
|
711
|
+
(this.theme === 'MinimalInput' ?
|
|
712
|
+
`position: fixed; left: 0; right: 0; margin-left: auto; margin-right: auto; bottom: ${this.marginBottom}px; width: ${this.width}px; z-index: 100000; max-width:90vw; max-height: 90vh; ${transitionStyle}` :
|
|
713
|
+
`position: fixed; right: 1em; bottom: ${this.marginBottom}px; width: ${this.width}px; z-index: 100000; max-width:90vw; max-height: 90vh; ${transitionStyle}`);
|
|
663
714
|
if (this.position === 'in-place') {
|
|
664
715
|
this.containerDiv.style.position = 'relative';
|
|
665
716
|
this.containerDiv.style.width = '100%';
|
|
@@ -668,6 +719,27 @@
|
|
|
668
719
|
}
|
|
669
720
|
this.updateIframes();
|
|
670
721
|
}
|
|
722
|
+
|
|
723
|
+
destroy() {
|
|
724
|
+
if (this.listeners) {
|
|
725
|
+
this.listeners.forEach(l => window.removeEventListener(l.type, l.fn));
|
|
726
|
+
this.listeners = null;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
this.windowListenersAdded = false;
|
|
730
|
+
this.isDestroyed = true;
|
|
731
|
+
|
|
732
|
+
if (this.containerDiv) {
|
|
733
|
+
if (this.createdContainer && this.containerDiv.parentNode) {
|
|
734
|
+
this.containerDiv.parentNode.removeChild(this.containerDiv);
|
|
735
|
+
} else if (!this.createdContainer) {
|
|
736
|
+
this.containerDiv.innerHTML = '';
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
this.iframe = null;
|
|
740
|
+
this.minimizedIframe = null;
|
|
741
|
+
this.containerDiv = null;
|
|
742
|
+
}
|
|
671
743
|
}
|
|
672
744
|
|
|
673
745
|
export function initEmbeddedChat(containerDiv, chatId, options) {
|
|
@@ -684,4 +756,3 @@ export function initOffers(options = {}) {
|
|
|
684
756
|
const mergedOptions = { ...options, mode: 'PartnerOffers', height: options.height || 500 };
|
|
685
757
|
return new EmbeddedChat(options.container, chatId, mergedOptions);
|
|
686
758
|
}
|
|
687
|
-
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "embeddedaichatux",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "A lightweight and customizable embedded AI chat UI component that seamlessly integrates into web applications, offering minimized and expanded views, with iframe-based content rendering.",
|
|
5
5
|
"main": "EmbeddedChat.js",
|
|
6
6
|
"scripts": {
|