embeddedaichatux 2.0.0 → 2.1.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/EmbeddedChat.js +120 -80
- package/package.json +1 -1
package/EmbeddedChat.js
CHANGED
|
@@ -14,17 +14,13 @@
|
|
|
14
14
|
this.width = options.width || 320; // Default width
|
|
15
15
|
this.marginBottom = options.marginBottom || 0;
|
|
16
16
|
this.enableAnimation = options.enableAnimation !== false; // Default to true if not provided
|
|
17
|
-
this.minimizedHeight =
|
|
17
|
+
this.minimizedHeight = "180px"; // Sensible default instead of 30% calculation
|
|
18
|
+
this.hasMeasuredSize = false;
|
|
18
19
|
this.mouseInsideChat = false;
|
|
19
20
|
this.hasRefreshed = false; // Flag to prevent endless loop
|
|
20
21
|
this.conversationId = null;
|
|
21
22
|
this.userTokenProvider = options.userTokenProvider;
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
this.targetOrigin = new URL(this.serverUrl).origin;
|
|
25
|
-
} catch {
|
|
26
|
-
this.targetOrigin = "*";
|
|
27
|
-
}
|
|
23
|
+
this.targetOrigin = "*";
|
|
28
24
|
|
|
29
25
|
// Determine transition styles
|
|
30
26
|
const transitionStyle = this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : '';
|
|
@@ -46,7 +42,7 @@
|
|
|
46
42
|
}
|
|
47
43
|
|
|
48
44
|
isSafari() {
|
|
49
|
-
|
|
45
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
50
46
|
return ua.indexOf('safari') != -1 && ua.indexOf('chrome') == -1;
|
|
51
47
|
}
|
|
52
48
|
|
|
@@ -88,7 +84,7 @@
|
|
|
88
84
|
const baseIframeUrl = `${cleanedServerUrl}/ChatUX/${this.chatId}`;
|
|
89
85
|
const minimizedPositionStyle = `
|
|
90
86
|
position: fixed; right: 0; bottom: 0;
|
|
91
|
-
width:
|
|
87
|
+
width: 150px;
|
|
92
88
|
height: ${this.minimizedHeight};
|
|
93
89
|
z-index: 100000;
|
|
94
90
|
${this.enableAnimation ? 'transition: height 0.3s ease, opacity 0.3s ease;' : ''}
|
|
@@ -120,13 +116,14 @@
|
|
|
120
116
|
|
|
121
117
|
// inject and capture references
|
|
122
118
|
this.containerDiv.innerHTML = iframeHtml;
|
|
123
|
-
this.iframe = this.containerDiv.querySelector(
|
|
124
|
-
this.minimizedIframe = this.containerDiv.querySelector(
|
|
119
|
+
this.iframe = this.containerDiv.querySelector("#embedded-chat");
|
|
120
|
+
this.minimizedIframe = this.containerDiv.querySelector("#embedded-chat-minimized");
|
|
125
121
|
|
|
126
|
-
//
|
|
127
|
-
|
|
122
|
+
// Wait for main iframe to load
|
|
123
|
+
if (this.iframe) {
|
|
124
|
+
await this.waitForIframeLoad(this.iframe);
|
|
125
|
+
}
|
|
128
126
|
|
|
129
|
-
// now that this.iframe & this.minimizedIframe exist, hook up events
|
|
130
127
|
this.addEventListeners();
|
|
131
128
|
|
|
132
129
|
// Send auth to iframes after load
|
|
@@ -181,6 +178,21 @@
|
|
|
181
178
|
}
|
|
182
179
|
|
|
183
180
|
handleMessage(e) {
|
|
181
|
+
// Only trust messages from our server (when targetOrigin is not "*")
|
|
182
|
+
if (this.targetOrigin !== "*" && e.origin !== this.targetOrigin) return;
|
|
183
|
+
|
|
184
|
+
if (typeof e.data !== "object") {
|
|
185
|
+
// Preserve original handling for string messages
|
|
186
|
+
if (typeof e.data === "string") {
|
|
187
|
+
if (e.data === "minimize") {
|
|
188
|
+
this.animateMinimize();
|
|
189
|
+
} else if (e.data === "show" || e.data === "maximize") {
|
|
190
|
+
this.showMaximized();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
184
196
|
console.log('[EmbeddedChat] Received message:', {
|
|
185
197
|
origin: e.origin,
|
|
186
198
|
type: e.data?.type,
|
|
@@ -189,68 +201,72 @@
|
|
|
189
201
|
data: e.data
|
|
190
202
|
});
|
|
191
203
|
|
|
204
|
+
const data = e.data;
|
|
205
|
+
const msg = (data.message || data.type || "").toString();
|
|
206
|
+
const incomingChatId = (data.chatId || "").toString().toLowerCase();
|
|
207
|
+
const targetChatId = (this.chatId || "").toString().toLowerCase();
|
|
208
|
+
|
|
209
|
+
// Bail out if chatId doesn't match and is provided
|
|
210
|
+
if (incomingChatId && targetChatId && incomingChatId !== targetChatId) return;
|
|
211
|
+
|
|
192
212
|
// Allow the iframe to request a fresh token
|
|
193
|
-
if (
|
|
194
|
-
console.log('[EmbeddedChat] Received requestAuth message, calling postAuthToIframes');
|
|
213
|
+
if (data.type === "requestAuth") {
|
|
195
214
|
this.postAuthToIframes();
|
|
196
215
|
return;
|
|
197
216
|
}
|
|
198
217
|
|
|
199
|
-
|
|
200
|
-
|
|
218
|
+
// Priority 1: Handle minimized size updates (CRITICAL: Bail out early and DO NOT pollute configuration)
|
|
219
|
+
if (msg === "updateMinimizedSize") {
|
|
220
|
+
// Support both new and legacy keys for compatibility with cached scripts
|
|
221
|
+
const h = data.minimizedHeight || data.height;
|
|
222
|
+
const w = data.minimizedWidth || data.width;
|
|
223
|
+
this.updateMinimizedSize(h, w);
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
201
226
|
|
|
202
|
-
|
|
203
|
-
const minimizeValue = e.data.type === "setMinimizeOnScroll" ? e.data.value : e.data.minimizeOnScroll;
|
|
204
|
-
this.minimizeOnScroll = minimizeValue === true || minimizeValue === "true";
|
|
205
|
-
}
|
|
227
|
+
const updates = {};
|
|
206
228
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
updates.width = e.data.width;
|
|
212
|
-
}
|
|
213
|
-
if (e.data.height) {
|
|
214
|
-
updates.height = e.data.height;
|
|
215
|
-
}
|
|
216
|
-
if (e.data.marginBottom) {
|
|
217
|
-
updates.marginBottom = e.data.marginBottom;
|
|
218
|
-
}
|
|
219
|
-
if (e.data.scale) {
|
|
220
|
-
updates.scale = e.data.scale;
|
|
221
|
-
}
|
|
229
|
+
if (data.type === "setMinimizeOnScroll" || data.minimizeOnScroll !== undefined) {
|
|
230
|
+
const minimizeValue = data.type === "setMinimizeOnScroll" ? data.value : data.minimizeOnScroll;
|
|
231
|
+
this.minimizeOnScroll = minimizeValue === true || minimizeValue === "true";
|
|
232
|
+
}
|
|
222
233
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
234
|
+
if (data.locale) {
|
|
235
|
+
updates.locale = data.locale;
|
|
236
|
+
}
|
|
237
|
+
if (data.width) {
|
|
238
|
+
updates.width = data.width;
|
|
239
|
+
}
|
|
240
|
+
if (data.height) {
|
|
241
|
+
updates.height = data.height;
|
|
242
|
+
}
|
|
243
|
+
if (data.marginBottom) {
|
|
244
|
+
updates.marginBottom = data.marginBottom;
|
|
245
|
+
}
|
|
246
|
+
if (data.scale) {
|
|
247
|
+
updates.scale = data.scale;
|
|
248
|
+
}
|
|
227
249
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
this.animateMinimize();
|
|
233
|
-
}
|
|
234
|
-
} else if (e.data.message === "show" || e.data.message === "maximize") {
|
|
235
|
-
const animate = e.data.animate === true;
|
|
236
|
-
this.showMaximized(animate);
|
|
237
|
-
} else if (e.data.message === "navigate" && e.data.url) {
|
|
238
|
-
// Handle the navigate message
|
|
239
|
-
window.location.href = e.data.url;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
250
|
+
// Apply iframe updates in one go
|
|
251
|
+
if (Object.keys(updates).length > 0) {
|
|
252
|
+
this.applyIframeUpdates(updates);
|
|
253
|
+
}
|
|
242
254
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
} else if (typeof e.data === "string") {
|
|
248
|
-
// Preserve original handling for string messages
|
|
249
|
-
if (e.data === "minimize") {
|
|
255
|
+
// Handle maximize/minimize/navigate
|
|
256
|
+
if (msg === "minimize") {
|
|
257
|
+
if (this.mode !== 'ContactForm') {
|
|
250
258
|
this.animateMinimize();
|
|
251
|
-
} else if (e.data === "show" || e.data === "maximize") {
|
|
252
|
-
this.showMaximized();
|
|
253
259
|
}
|
|
260
|
+
} else if (msg === "show" || msg === "maximize") {
|
|
261
|
+
const animate = data.animate === true;
|
|
262
|
+
this.showMaximized(animate);
|
|
263
|
+
} else if (msg === "navigate" && data.url) {
|
|
264
|
+
window.location.href = data.url;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Handle conversationId update
|
|
268
|
+
if (data.conversationId) {
|
|
269
|
+
this.setConversationId(data.conversationId);
|
|
254
270
|
}
|
|
255
271
|
}
|
|
256
272
|
|
|
@@ -264,10 +280,37 @@
|
|
|
264
280
|
this.minimizedIframe.style.display = "block";
|
|
265
281
|
this.minimizedIframe.style.height = this.minimizedHeight;
|
|
266
282
|
this.minimizedIframe.style.opacity = '1';
|
|
283
|
+
|
|
284
|
+
// Request a height update after showing
|
|
285
|
+
if (this.minimizedIframe.contentWindow) {
|
|
286
|
+
this.minimizedIframe.contentWindow.postMessage({ message: "requestHeightUpdate" }, this.targetOrigin);
|
|
287
|
+
}
|
|
267
288
|
}, this.enableAnimation ? 300 : 0);
|
|
268
289
|
}
|
|
269
290
|
}
|
|
270
291
|
|
|
292
|
+
updateMinimizedSize(contentHeight, contentWidth) {
|
|
293
|
+
if (this.mode === 'ContactForm') return;
|
|
294
|
+
|
|
295
|
+
this.hasMeasuredSize = true;
|
|
296
|
+
|
|
297
|
+
// Apply height update
|
|
298
|
+
if (contentHeight && contentHeight >= 10) {
|
|
299
|
+
const newHeight = `${contentHeight}px`;
|
|
300
|
+
this.minimizedHeight = newHeight;
|
|
301
|
+
if (this.minimizedIframe) {
|
|
302
|
+
this.minimizedIframe.style.height = newHeight;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Apply width update
|
|
307
|
+
if (contentWidth && contentWidth >= 10) {
|
|
308
|
+
if (this.minimizedIframe) {
|
|
309
|
+
this.minimizedIframe.style.width = `${contentWidth}px`;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
271
314
|
animateMaximize() {
|
|
272
315
|
if (this.mode !== 'ContactForm') {
|
|
273
316
|
// Start the animation for minimizing iframe
|
|
@@ -303,7 +346,7 @@
|
|
|
303
346
|
// Update width if provided and different
|
|
304
347
|
const parsedWidth = parseInt(width, 10);
|
|
305
348
|
if (!isNaN(parsedWidth) && parsedWidth > 0 && parsedWidth !== this.width) {
|
|
306
|
-
this.width =
|
|
349
|
+
this.width = parsedWidth;
|
|
307
350
|
console.log(`Width updated to: ${this.width}px`);
|
|
308
351
|
|
|
309
352
|
// Apply width to container
|
|
@@ -313,11 +356,6 @@
|
|
|
313
356
|
if (this.iframe) {
|
|
314
357
|
this.iframe.style.width = `${this.width}px`;
|
|
315
358
|
}
|
|
316
|
-
|
|
317
|
-
// Apply width to the minimized iframe
|
|
318
|
-
if (this.minimizedIframe) {
|
|
319
|
-
this.minimizedIframe.style.width = `${this.width}px`;
|
|
320
|
-
}
|
|
321
359
|
}
|
|
322
360
|
|
|
323
361
|
// Apply scale if provided
|
|
@@ -347,25 +385,30 @@
|
|
|
347
385
|
|
|
348
386
|
// Clamp so that height + marginBottom doesn't exceed 90% of viewport
|
|
349
387
|
const viewportHeight = window.innerHeight;
|
|
350
|
-
|
|
351
|
-
|
|
388
|
+
let effectiveHeight = parsedHeight;
|
|
389
|
+
if (effectiveHeight + parsedMarginBottom > 0.9 * viewportHeight) {
|
|
390
|
+
effectiveHeight = Math.max(100, 0.9 * viewportHeight - parsedMarginBottom);
|
|
352
391
|
}
|
|
353
392
|
|
|
354
393
|
// Only apply if there's an actual change
|
|
355
394
|
if (parsedHeight !== this.height || parsedMarginBottom !== this.marginBottom) {
|
|
356
395
|
this.height = parsedHeight;
|
|
357
396
|
this.marginBottom = parsedMarginBottom;
|
|
358
|
-
this.minimizedHeight = `${this.height * 0.3}px`;
|
|
359
397
|
|
|
360
|
-
|
|
398
|
+
// Only use the 30% estimate if we haven't received a real measurement yet
|
|
399
|
+
if (!this.hasMeasuredSize) {
|
|
400
|
+
this.minimizedHeight = `${this.height * 0.3}px`;
|
|
401
|
+
}
|
|
361
402
|
|
|
362
|
-
|
|
403
|
+
console.log(`Height updated to: ${this.height}px (clamped to ${effectiveHeight}px for display), marginBottom: ${this.marginBottom}px`);
|
|
404
|
+
|
|
405
|
+
// Apply the updated height/marginBottom
|
|
363
406
|
if (this.mode !== 'ContactForm') {
|
|
364
407
|
if (this.containerDiv.dataset.position === 'in-place') {
|
|
365
408
|
// "in-place" uses full width, sets containerDiv height
|
|
366
|
-
this.containerDiv.style.height = `${
|
|
409
|
+
this.containerDiv.style.height = `${effectiveHeight}px`;
|
|
367
410
|
if (this.iframe) {
|
|
368
|
-
this.iframe.style.height = `${
|
|
411
|
+
this.iframe.style.height = `${effectiveHeight}px`;
|
|
369
412
|
}
|
|
370
413
|
if (this.minimizedIframe) {
|
|
371
414
|
this.minimizedIframe.style.height = this.minimizedHeight;
|
|
@@ -519,7 +562,6 @@
|
|
|
519
562
|
}
|
|
520
563
|
|
|
521
564
|
try {
|
|
522
|
-
console.log('[EmbeddedChat] Calling userTokenProvider...');
|
|
523
565
|
const userToken = await this.userTokenProvider();
|
|
524
566
|
|
|
525
567
|
if (!userToken) {
|
|
@@ -527,8 +569,6 @@
|
|
|
527
569
|
return;
|
|
528
570
|
}
|
|
529
571
|
|
|
530
|
-
console.log('[EmbeddedChat] Got user token, length:', userToken?.length || 0);
|
|
531
|
-
|
|
532
572
|
if (this.iframe?.contentWindow) {
|
|
533
573
|
console.log('[EmbeddedChat] Sending auth message to iframe with targetOrigin:', this.targetOrigin);
|
|
534
574
|
this.iframe.contentWindow.postMessage({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "embeddedaichatux",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
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": {
|