@lookalike/widget 1.1.0 โ†’ 1.2.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/dist/README.md CHANGED
@@ -73,8 +73,8 @@ A lightweight, self-contained widget for embedding Lookalike conversational AI a
73
73
 
74
74
  ## File Sizes
75
75
 
76
- - **Minified**: ~8KB
77
- - **Gzipped**: ~2KB (estimated)
76
+ - **Minified**: ~14KB
77
+ - **Gzipped**: ~4KB (estimated)
78
78
 
79
79
  ## License
80
80
 
@@ -8,9 +8,13 @@
8
8
  // Lookalike Widget - Standalone Embed Version
9
9
  // Self-contained widget for copy/paste embedding (no Wix dependencies)
10
10
  // Uses shadow DOM for complete encapsulation
11
+ // Version 1.2.0 - Debug Enhanced
11
12
 
13
+ const WIDGET_VERSION = '1.2.0';
12
14
  const DEFAULT_UUID = '019b4c51-7701-726a-8f59-e89a854682f3';
13
15
 
16
+ console.log(`๐Ÿš€ Lookalike Widget v${WIDGET_VERSION} loading...`);
17
+
14
18
  function getBaseUrl() {
15
19
  const hostname = window.location.hostname;
16
20
  if (hostname === 'localhost' || hostname === '127.0.0.1') {
@@ -36,10 +40,22 @@ class LookalikeWidget extends HTMLElement {
36
40
  this.currentIframe = null;
37
41
  this.shadow = null;
38
42
  this.messageHandler = null;
43
+ this.isInWixEmbed = false;
39
44
  }
40
45
 
41
46
  connectedCallback() {
42
- console.log('๐Ÿš€ Lookalike Widget initializing...');
47
+ console.log(`๐Ÿš€ Lookalike Widget v${WIDGET_VERSION} initializing...`);
48
+ console.log('๐Ÿ“Š Environment Info:', {
49
+ hostname: window.location.hostname,
50
+ href: window.location.href,
51
+ referrer: document.referrer,
52
+ userAgent: navigator.userAgent,
53
+ viewport: `${window.innerWidth}x${window.innerHeight}`,
54
+ inIframe: window !== window.parent
55
+ });
56
+
57
+ // Detect if we're in a Wix custom code embed (or similar constrained iframe)
58
+ this.detectWixEmbed();
43
59
 
44
60
  // Create shadow DOM for encapsulation
45
61
  this.shadow = this.attachShadow({ mode: 'closed' });
@@ -51,6 +67,53 @@ class LookalikeWidget extends HTMLElement {
51
67
  this.initLive();
52
68
  }
53
69
 
70
+ detectWixEmbed() {
71
+ console.log('๐Ÿ” Starting Wix embed detection...');
72
+
73
+ try {
74
+ // Check if we're in an iframe and can't access parent
75
+ const inIframe = window !== window.parent;
76
+ console.log('๐Ÿ“ฑ In iframe:', inIframe);
77
+
78
+ // Check for Wix-specific indicators
79
+ const wixHostname = window.location.hostname.includes('wix.com') || window.location.hostname.includes('wixsite.com');
80
+ const wixSearch = window.location.search.includes('wix');
81
+ const wixReferrer = document.referrer.includes('wix');
82
+ const smallDimensions = window.innerWidth < 500 || window.innerHeight < 300;
83
+
84
+ console.log('๐Ÿ” Wix Detection Results:', {
85
+ inIframe,
86
+ wixHostname,
87
+ wixSearch,
88
+ wixReferrer,
89
+ smallDimensions,
90
+ windowSize: `${window.innerWidth}x${window.innerHeight}`
91
+ });
92
+
93
+ const hasWixIndicators = wixHostname || wixSearch || wixReferrer || (inIframe && smallDimensions);
94
+
95
+ this.isInWixEmbed = inIframe && hasWixIndicators;
96
+
97
+ if (this.isInWixEmbed) {
98
+ console.log('โœ… Wix embed environment DETECTED - using full-screen overlay mode');
99
+ } else {
100
+ console.log('โŒ Standard environment detected - using normal positioning');
101
+ }
102
+
103
+ // Force Wix mode for testing if URL contains debug parameter
104
+ if (window.location.search.includes('force-wix-mode')) {
105
+ console.log('๐Ÿงช FORCE WIX MODE activated via URL parameter');
106
+ this.isInWixEmbed = true;
107
+ }
108
+
109
+ } catch (error) {
110
+ // If we can't access parent due to cross-origin, assume we're in an embed
111
+ console.log('โš ๏ธ Cross-origin iframe error:', error.message);
112
+ this.isInWixEmbed = true;
113
+ console.log('๐Ÿ”’ Cross-origin iframe detected - using full-screen overlay mode');
114
+ }
115
+ }
116
+
54
117
  loadConfiguration() {
55
118
  // Read configuration from HTML attributes
56
119
  if (this.hasAttribute('uuid')) {
@@ -117,7 +180,53 @@ class LookalikeWidget extends HTMLElement {
117
180
  initLive() {
118
181
  console.log('๐Ÿš€ Initializing live widget with config:', this.config);
119
182
 
120
- // Set host element positioning and initial size
183
+ if (this.isInWixEmbed) {
184
+ this.initWixEmbedMode();
185
+ } else {
186
+ this.initStandardMode();
187
+ }
188
+
189
+ this.injectShadowContent();
190
+ this.injectIframe();
191
+ }
192
+
193
+ initWixEmbedMode() {
194
+ console.log('๐Ÿ“ฑ Initializing Wix embed mode with full-screen overlay');
195
+
196
+ // Make the host element a full-screen transparent overlay
197
+ const overlayStyles = `
198
+ position: fixed;
199
+ top: 0;
200
+ left: 0;
201
+ width: 100vw;
202
+ height: 100vh;
203
+ border: 0;
204
+ z-index: 9999;
205
+ background: transparent;
206
+ pointer-events: none;
207
+ display: block;
208
+ `;
209
+
210
+ this.style.cssText = overlayStyles;
211
+
212
+ console.log('๐ŸŽจ Applied overlay styles:', overlayStyles);
213
+ console.log('๐Ÿ“ Host element computed styles:', {
214
+ position: getComputedStyle(this).position,
215
+ width: getComputedStyle(this).width,
216
+ height: getComputedStyle(this).height,
217
+ zIndex: getComputedStyle(this).zIndex,
218
+ pointerEvents: getComputedStyle(this).pointerEvents
219
+ });
220
+
221
+ // Add collapsed class initially
222
+ this.className = 'collapsed wix-embed';
223
+ console.log('๐Ÿท๏ธ Applied classes:', this.className);
224
+ }
225
+
226
+ initStandardMode() {
227
+ console.log('๐Ÿ’ป Initializing standard mode');
228
+
229
+ // Set host element positioning and initial size (original behavior)
121
230
  this.style.cssText = `
122
231
  position: fixed;
123
232
  bottom: 16px;
@@ -136,9 +245,6 @@ class LookalikeWidget extends HTMLElement {
136
245
 
137
246
  // Add collapsed class initially
138
247
  this.className = 'collapsed';
139
-
140
- this.injectShadowContent();
141
- this.injectIframe();
142
248
  }
143
249
 
144
250
  injectShadowContent() {
@@ -151,18 +257,60 @@ class LookalikeWidget extends HTMLElement {
151
257
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
152
258
  }
153
259
 
154
- :host(.collapsed) {
260
+ /* Standard mode styles */
261
+ :host(.collapsed:not(.wix-embed)) {
155
262
  height: 60px !important;
156
263
  max-height: 60px !important;
157
264
  }
158
265
 
159
- :host(.expanded) {
266
+ :host(.expanded:not(.wix-embed)) {
267
+ height: 520px;
268
+ max-height: calc(100vh - 32px);
269
+ }
270
+
271
+ /* Wix embed mode: container for positioned widget */
272
+ .wix-widget-container {
273
+ position: absolute;
274
+ bottom: 16px;
275
+ right: 16px;
276
+ width: 380px;
277
+ height: 60px;
278
+ max-width: calc(100vw - 32px);
279
+ border-radius: 16px;
280
+ box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
281
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
282
+ background: transparent;
283
+ pointer-events: auto;
284
+ }
285
+
286
+ /* Debug info overlay */
287
+ .debug-info {
288
+ position: absolute;
289
+ top: 10px;
290
+ left: 10px;
291
+ background: rgba(0, 0, 0, 0.8);
292
+ color: white;
293
+ padding: 8px;
294
+ border-radius: 4px;
295
+ font-size: 11px;
296
+ font-family: monospace;
297
+ z-index: 10000;
298
+ max-width: 300px;
299
+ pointer-events: none;
300
+ white-space: pre-line;
301
+ }
302
+
303
+ :host(.wix-embed.collapsed) .wix-widget-container {
304
+ height: 60px;
305
+ }
306
+
307
+ :host(.wix-embed.expanded) .wix-widget-container {
160
308
  height: 520px;
161
309
  max-height: calc(100vh - 32px);
162
310
  }
163
311
 
164
312
  @media (max-width: 639px) {
165
- :host(.expanded) {
313
+ :host(.expanded:not(.wix-embed)) {
166
314
  width: 100vw;
167
315
  height: 100vh;
168
316
  max-width: none;
@@ -173,13 +321,13 @@ class LookalikeWidget extends HTMLElement {
173
321
  box-shadow: none;
174
322
  }
175
323
 
176
- :host {
324
+ :host(:not(.wix-embed)) {
177
325
  width: calc(100vw - 16px);
178
326
  right: 8px;
179
327
  bottom: 8px;
180
328
  }
181
329
 
182
- :host(.collapsed) {
330
+ :host(.collapsed:not(.wix-embed)) {
183
331
  height: 60px !important;
184
332
  max-height: 60px !important;
185
333
  width: calc(100vw - 16px);
@@ -188,6 +336,33 @@ class LookalikeWidget extends HTMLElement {
188
336
  border-radius: 16px;
189
337
  box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
190
338
  }
339
+
340
+ /* Wix embed mobile styles */
341
+ :host(.wix-embed.expanded) .wix-widget-container {
342
+ width: 100vw;
343
+ height: 100vh;
344
+ max-width: none;
345
+ max-height: none;
346
+ bottom: 0;
347
+ right: 0;
348
+ border-radius: 0;
349
+ box-shadow: none;
350
+ }
351
+
352
+ .wix-widget-container {
353
+ width: calc(100vw - 16px);
354
+ right: 8px;
355
+ bottom: 8px;
356
+ }
357
+
358
+ :host(.wix-embed.collapsed) .wix-widget-container {
359
+ height: 60px !important;
360
+ width: calc(100vw - 16px);
361
+ right: 8px;
362
+ bottom: 8px;
363
+ border-radius: 16px;
364
+ box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
365
+ }
191
366
  }
192
367
 
193
368
  .loading {
@@ -254,17 +429,46 @@ class LookalikeWidget extends HTMLElement {
254
429
 
255
430
  this.shadow.appendChild(style);
256
431
 
432
+ // Add debug info if URL contains debug parameter
433
+ if (window.location.search.includes('debug') || window.location.search.includes('force-wix-mode')) {
434
+ this.addDebugInfo();
435
+ }
436
+
257
437
  // Create container for iframe
258
438
  const container = document.createElement('div');
259
- container.style.cssText = `
260
- width: 100%;
261
- height: 100%;
262
- border-radius: inherit;
263
- `;
439
+
440
+ if (this.isInWixEmbed) {
441
+ // In Wix embed mode, create a positioned container within the full-screen overlay
442
+ container.className = 'wix-widget-container';
443
+ } else {
444
+ // In standard mode, container fills the host element
445
+ container.style.cssText = `
446
+ width: 100%;
447
+ height: 100%;
448
+ border-radius: inherit;
449
+ `;
450
+ }
264
451
 
265
452
  this.shadow.appendChild(container);
266
453
  }
267
454
 
455
+ addDebugInfo() {
456
+ const debugDiv = document.createElement('div');
457
+ debugDiv.className = 'debug-info';
458
+
459
+ const info = `Lookalike Widget v${WIDGET_VERSION}
460
+ Mode: ${this.isInWixEmbed ? 'Wix Embed' : 'Standard'}
461
+ Viewport: ${window.innerWidth}x${window.innerHeight}
462
+ In iframe: ${window !== window.parent}
463
+ Hostname: ${window.location.hostname}
464
+ Classes: ${this.className}`;
465
+
466
+ debugDiv.textContent = info;
467
+ this.shadow.appendChild(debugDiv);
468
+
469
+ console.log('๐Ÿ› Debug info added to widget');
470
+ }
471
+
268
472
  buildIframeSrc() {
269
473
  if (!this.config.storyfileUuid) {
270
474
  console.error('โŒ No storyfile UUID configured');
@@ -296,11 +500,29 @@ class LookalikeWidget extends HTMLElement {
296
500
  }
297
501
 
298
502
  injectIframe() {
299
- const container = this.shadow.querySelector('div:last-child');
503
+ const containerSelector = this.isInWixEmbed ? '.wix-widget-container' : 'div:last-child';
504
+ const container = this.shadow.querySelector(containerSelector);
505
+
506
+ console.log('๐Ÿ–ผ๏ธ Injecting iframe into container:', containerSelector);
507
+ console.log('๐Ÿ“ฆ Container found:', !!container);
508
+
509
+ if (container) {
510
+ console.log('๐Ÿ“ Container rect:', container.getBoundingClientRect());
511
+ console.log('๐ŸŽจ Container computed styles:', {
512
+ position: getComputedStyle(container).position,
513
+ width: getComputedStyle(container).width,
514
+ height: getComputedStyle(container).height,
515
+ bottom: getComputedStyle(container).bottom,
516
+ right: getComputedStyle(container).right
517
+ });
518
+ }
300
519
 
301
520
  // Remove existing iframe if present
302
- const existingIframe = container.querySelector('iframe');
303
- if (existingIframe) existingIframe.remove();
521
+ const existingIframe = container?.querySelector('iframe');
522
+ if (existingIframe) {
523
+ console.log('๐Ÿ—‘๏ธ Removing existing iframe');
524
+ existingIframe.remove();
525
+ }
304
526
 
305
527
  const iframeSrc = this.buildIframeSrc();
306
528
  if (!iframeSrc) {
@@ -308,6 +530,8 @@ class LookalikeWidget extends HTMLElement {
308
530
  return;
309
531
  }
310
532
 
533
+ console.log('๐Ÿ”— Creating iframe with src:', iframeSrc);
534
+
311
535
  const iframe = document.createElement('iframe');
312
536
  iframe.className = 'loading';
313
537
  iframe.src = iframeSrc;
@@ -315,19 +539,22 @@ class LookalikeWidget extends HTMLElement {
315
539
  iframe.loading = 'lazy';
316
540
  iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-forms allow-popups allow-presentation');
317
541
 
318
- iframe.onerror = () => {
319
- console.error('โŒ Failed to load widget iframe');
542
+ iframe.onerror = (error) => {
543
+ console.error('โŒ Failed to load widget iframe:', error);
320
544
  this.showLoadingError(container);
321
545
  };
322
546
 
323
547
  iframe.onload = () => {
324
548
  console.log('โœ… Iframe loaded successfully');
549
+ console.log('๐Ÿ“ Iframe rect after load:', iframe.getBoundingClientRect());
325
550
  iframe.classList.remove('loading');
326
551
  };
327
552
 
328
553
  this.currentIframe = iframe;
329
554
  this.setupMessageHandling(iframe);
330
555
  container.appendChild(iframe);
556
+
557
+ console.log('๐ŸŽฏ Iframe injection complete');
331
558
  }
332
559
 
333
560
  setupMessageHandling(iframe) {
@@ -337,6 +564,8 @@ class LookalikeWidget extends HTMLElement {
337
564
  }
338
565
 
339
566
  this.messageHandler = (e) => {
567
+ console.log('๐Ÿ“จ Received message:', e.data, 'from:', e.origin);
568
+
340
569
  if (e.source !== iframe.contentWindow) return;
341
570
 
342
571
  if (e.data?.type === 'lookalike-widget-ready') {
@@ -348,7 +577,18 @@ class LookalikeWidget extends HTMLElement {
348
577
  if (ev.data?.type === 'lookalike-widget-resize') {
349
578
  const newClass = ev.data.collapsed ? 'collapsed' : 'expanded';
350
579
  console.log(`๐Ÿ“ Widget resize: ${this.className} โ†’ ${newClass}`);
351
- this.className = newClass;
580
+ console.log('๐Ÿ“ Before resize - Host element rect:', this.getBoundingClientRect());
581
+
582
+ this.className = this.isInWixEmbed ? `${newClass} wix-embed` : newClass;
583
+
584
+ // Log after resize
585
+ setTimeout(() => {
586
+ console.log('๐Ÿ“ After resize - Host element rect:', this.getBoundingClientRect());
587
+ const container = this.shadow.querySelector(this.isInWixEmbed ? '.wix-widget-container' : 'div:last-child');
588
+ if (container) {
589
+ console.log('๐Ÿ“ Widget container rect:', container.getBoundingClientRect());
590
+ }
591
+ }, 100);
352
592
  }
353
593
  };
354
594
 
@@ -361,6 +601,7 @@ class LookalikeWidget extends HTMLElement {
361
601
  };
362
602
 
363
603
  window.addEventListener('message', this.messageHandler);
604
+ console.log('๐Ÿ‘‚ Message handler installed');
364
605
  }
365
606
 
366
607
  showConfigurationError(container) {
@@ -5,4 +5,4 @@
5
5
  * Copy/paste embed widget for conversational AI avatars
6
6
  * Usage: <lookalike-widget uuid="your-uuid"></lookalike-widget>
7
7
  */
8
- const DEFAULT_UUID="019b4c51-7701-726a-8f59-e89a854682f3";function getBaseUrl(){const e=window.location.hostname;return"localhost"===e||"127.0.0.1"===e?(console.log("๐Ÿ  Local development detected"),"http://localhost:3000"):(console.log("๐ŸŒ Using production URL"),"https://lookalike.com")}const BASE_URL=getBaseUrl();class LookalikeWidget extends HTMLElement{constructor(){super(),this.config={storyfileUuid:null,primaryColor:"#2563eb",enableText:!0,enableVideo:!0,enableAudio:!0},this.currentIframe=null,this.shadow=null,this.messageHandler=null}connectedCallback(){console.log("๐Ÿš€ Lookalike Widget initializing..."),this.shadow=this.attachShadow({mode:"closed"}),this.loadConfiguration(),this.initLive()}loadConfiguration(){this.hasAttribute("uuid")&&(this.config.storyfileUuid=this.getAttribute("uuid")),this.hasAttribute("color")&&(this.config.primaryColor=this.getAttribute("color")),this.hasAttribute("text")&&(this.config.enableText="false"!==this.getAttribute("text")),this.hasAttribute("video")&&(this.config.enableVideo="false"!==this.getAttribute("video")),this.hasAttribute("audio")&&(this.config.enableAudio="false"!==this.getAttribute("audio")),this.config.storyfileUuid||(this.config.storyfileUuid=DEFAULT_UUID,console.log("๐Ÿ”ง Using default UUID:",DEFAULT_UUID)),console.log("๐Ÿ“ฅ Loaded config from attributes:",this.config)}static get observedAttributes(){return["uuid","color","text","video","audio"]}attributeChangedCallback(e,t,n){if(t!==n&&this.shadow){switch(console.log(`๐Ÿ”„ Attribute changed: ${e} = ${n}`),e){case"uuid":this.config.storyfileUuid=n;break;case"color":this.config.primaryColor=n;break;case"text":this.config.enableText="false"!==n;break;case"video":this.config.enableVideo="false"!==n;break;case"audio":this.config.enableAudio="false"!==n}console.log("๐Ÿ”„ Updated config after attribute change:",this.config),this.isConnected&&(this.shadow.innerHTML="",this.initLive())}}initLive(){console.log("๐Ÿš€ Initializing live widget with config:",this.config),this.style.cssText="\n position: fixed;\n bottom: 16px;\n right: 16px;\n width: 380px;\n height: 60px;\n max-width: calc(100vw - 32px);\n border: 0;\n border-radius: 16px;\n z-index: 9999;\n box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n background: transparent;\n display: block;\n ",this.className="collapsed",this.injectShadowContent(),this.injectIframe()}injectShadowContent(){const e=document.createElement("style");e.textContent="\n @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');\n \n :host {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n }\n\n :host(.collapsed) {\n height: 60px !important;\n max-height: 60px !important;\n }\n\n :host(.expanded) {\n height: 520px;\n max-height: calc(100vh - 32px);\n }\n\n @media (max-width: 639px) {\n :host(.expanded) {\n width: 100vw;\n height: 100vh;\n max-width: none;\n max-height: none;\n bottom: 0;\n right: 0;\n border-radius: 0;\n box-shadow: none;\n }\n \n :host {\n width: calc(100vw - 16px);\n right: 8px;\n bottom: 8px;\n }\n \n :host(.collapsed) {\n height: 60px !important;\n max-height: 60px !important;\n width: calc(100vw - 16px);\n right: 8px;\n bottom: 8px;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);\n }\n }\n \n .loading {\n background: #f3f4f6;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n border-radius: inherit;\n }\n \n .loading::after {\n content: 'Loading chat...';\n color: #6b7280;\n font-size: 14px;\n }\n\n .error-container {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n background: #f9fafb;\n border-radius: inherit;\n border: 2px dashed #d1d5db;\n color: #6b7280;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n padding: 20px;\n box-sizing: border-box;\n }\n\n .error-icon {\n font-size: 24px;\n margin-bottom: 8px;\n }\n\n .error-title {\n font-size: 14px;\n font-weight: 500;\n margin-bottom: 4px;\n }\n\n .error-message {\n font-size: 12px;\n }\n\n .error-uuid {\n font-size: 11px;\n margin-top: 8px;\n opacity: 0.7;\n }\n\n iframe {\n width: 100%;\n height: 100%;\n border: 0;\n border-radius: inherit;\n }\n ",this.shadow.appendChild(e);const t=document.createElement("div");t.style.cssText="\n width: 100%;\n height: 100%;\n border-radius: inherit;\n ",this.shadow.appendChild(t)}buildIframeSrc(){if(!this.config.storyfileUuid)return console.error("โŒ No storyfile UUID configured"),null;const e=new URL(`/${this.config.storyfileUuid}/chat`,BASE_URL);e.searchParams.set("embed",""),e.searchParams.set("variant","floating"),e.searchParams.set("anchor","bottom-right");const t=[];return this.config.enableText&&t.push("text"),this.config.enableAudio&&t.push("audio"),this.config.enableVideo&&t.push("video"),t.length>0&&t.length<3&&e.searchParams.set("modes",t.join(",")),this.config.primaryColor&&"#2563eb"!==this.config.primaryColor&&e.searchParams.set("theme",`primary:${this.config.primaryColor}`),console.log("๐Ÿ”— Built iframe URL:",e.toString()),e.toString()}injectIframe(){const e=this.shadow.querySelector("div:last-child"),t=e.querySelector("iframe");t&&t.remove();const n=this.buildIframeSrc();if(!n)return void this.showConfigurationError(e);const i=document.createElement("iframe");i.className="loading",i.src=n,i.allow="microphone; camera",i.loading="lazy",i.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups allow-presentation"),i.onerror=()=>{console.error("โŒ Failed to load widget iframe"),this.showLoadingError(e)},i.onload=()=>{console.log("โœ… Iframe loaded successfully"),i.classList.remove("loading")},this.currentIframe=i,this.setupMessageHandling(i),e.appendChild(i)}setupMessageHandling(e){this.messageHandler&&window.removeEventListener("message",this.messageHandler),this.messageHandler=t=>{if(t.source===e.contentWindow&&"lookalike-widget-ready"===t.data?.type){console.log("๐ŸŽ‰ Widget ready, setting up communication");const t=new MessageChannel;t.port1.onmessage=e=>{if(console.log("๐Ÿ“ Received resize message:",e.data),"lookalike-widget-resize"===e.data?.type){const t=e.data.collapsed?"collapsed":"expanded";console.log(`๐Ÿ“ Widget resize: ${this.className} โ†’ ${t}`),this.className=t}},e.contentWindow.postMessage({type:"lookalike-init-channel"},BASE_URL,[t.port2])}},window.addEventListener("message",this.messageHandler)}showConfigurationError(e){e.innerHTML='\n <div class="error-container">\n <div class="error-icon">โš ๏ธ</div>\n <div class="error-title">Configuration Error</div>\n <div class="error-message">No UUID configured. Please add a uuid attribute.</div>\n <div class="error-uuid">Expected: &lt;lookalike-widget uuid="your-uuid"&gt;</div>\n </div>\n '}showLoadingError(e){e.innerHTML=`\n <div class="error-container">\n <div class="error-icon">โš ๏ธ</div>\n <div class="error-title">Widget Loading Error</div>\n <div class="error-message">Check console for details</div>\n <div class="error-uuid">UUID: ${this.config.storyfileUuid}</div>\n </div>\n `}disconnectedCallback(){this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null)}}customElements.define("lookalike-widget",LookalikeWidget),"undefined"!=typeof module&&module.exports&&(module.exports=LookalikeWidget);
8
+ const WIDGET_VERSION="1.2.0",DEFAULT_UUID="019b4c51-7701-726a-8f59-e89a854682f3";function getBaseUrl(){const e=window.location.hostname;return"localhost"===e||"127.0.0.1"===e?(console.log("๐Ÿ  Local development detected"),"http://localhost:3000"):(console.log("๐ŸŒ Using production URL"),"https://lookalike.com")}console.log("๐Ÿš€ Lookalike Widget v1.2.0 loading...");const BASE_URL=getBaseUrl();class LookalikeWidget extends HTMLElement{constructor(){super(),this.config={storyfileUuid:null,primaryColor:"#2563eb",enableText:!0,enableVideo:!0,enableAudio:!0},this.currentIframe=null,this.shadow=null,this.messageHandler=null,this.isInWixEmbed=!1}connectedCallback(){console.log("๐Ÿš€ Lookalike Widget v1.2.0 initializing..."),console.log("๐Ÿ“Š Environment Info:",{hostname:window.location.hostname,href:window.location.href,referrer:document.referrer,userAgent:navigator.userAgent,viewport:`${window.innerWidth}x${window.innerHeight}`,inIframe:window!==window.parent}),this.detectWixEmbed(),this.shadow=this.attachShadow({mode:"closed"}),this.loadConfiguration(),this.initLive()}detectWixEmbed(){console.log("๐Ÿ” Starting Wix embed detection...");try{const e=window!==window.parent;console.log("๐Ÿ“ฑ In iframe:",e);const n=window.location.hostname.includes("wix.com")||window.location.hostname.includes("wixsite.com"),i=window.location.search.includes("wix"),t=document.referrer.includes("wix"),o=window.innerWidth<500||window.innerHeight<300;console.log("๐Ÿ” Wix Detection Results:",{inIframe:e,wixHostname:n,wixSearch:i,wixReferrer:t,smallDimensions:o,windowSize:`${window.innerWidth}x${window.innerHeight}`});const s=n||i||t||e&&o;this.isInWixEmbed=e&&s,this.isInWixEmbed?console.log("โœ… Wix embed environment DETECTED - using full-screen overlay mode"):console.log("โŒ Standard environment detected - using normal positioning"),window.location.search.includes("force-wix-mode")&&(console.log("๐Ÿงช FORCE WIX MODE activated via URL parameter"),this.isInWixEmbed=!0)}catch(e){console.log("โš ๏ธ Cross-origin iframe error:",e.message),this.isInWixEmbed=!0,console.log("๐Ÿ”’ Cross-origin iframe detected - using full-screen overlay mode")}}loadConfiguration(){this.hasAttribute("uuid")&&(this.config.storyfileUuid=this.getAttribute("uuid")),this.hasAttribute("color")&&(this.config.primaryColor=this.getAttribute("color")),this.hasAttribute("text")&&(this.config.enableText="false"!==this.getAttribute("text")),this.hasAttribute("video")&&(this.config.enableVideo="false"!==this.getAttribute("video")),this.hasAttribute("audio")&&(this.config.enableAudio="false"!==this.getAttribute("audio")),this.config.storyfileUuid||(this.config.storyfileUuid=DEFAULT_UUID,console.log("๐Ÿ”ง Using default UUID:",DEFAULT_UUID)),console.log("๐Ÿ“ฅ Loaded config from attributes:",this.config)}static get observedAttributes(){return["uuid","color","text","video","audio"]}attributeChangedCallback(e,n,i){if(n!==i&&this.shadow){switch(console.log(`๐Ÿ”„ Attribute changed: ${e} = ${i}`),e){case"uuid":this.config.storyfileUuid=i;break;case"color":this.config.primaryColor=i;break;case"text":this.config.enableText="false"!==i;break;case"video":this.config.enableVideo="false"!==i;break;case"audio":this.config.enableAudio="false"!==i}console.log("๐Ÿ”„ Updated config after attribute change:",this.config),this.isConnected&&(this.shadow.innerHTML="",this.initLive())}}initLive(){console.log("๐Ÿš€ Initializing live widget with config:",this.config),this.isInWixEmbed?this.initWixEmbedMode():this.initStandardMode(),this.injectShadowContent(),this.injectIframe()}initWixEmbedMode(){console.log("๐Ÿ“ฑ Initializing Wix embed mode with full-screen overlay");const e="\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n border: 0;\n z-index: 9999;\n background: transparent;\n pointer-events: none;\n display: block;\n ";this.style.cssText=e,console.log("๐ŸŽจ Applied overlay styles:",e),console.log("๐Ÿ“ Host element computed styles:",{position:getComputedStyle(this).position,width:getComputedStyle(this).width,height:getComputedStyle(this).height,zIndex:getComputedStyle(this).zIndex,pointerEvents:getComputedStyle(this).pointerEvents}),this.className="collapsed wix-embed",console.log("๐Ÿท๏ธ Applied classes:",this.className)}initStandardMode(){console.log("๐Ÿ’ป Initializing standard mode"),this.style.cssText="\n position: fixed;\n bottom: 16px;\n right: 16px;\n width: 380px;\n height: 60px;\n max-width: calc(100vw - 32px);\n border: 0;\n border-radius: 16px;\n z-index: 9999;\n box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n background: transparent;\n display: block;\n ",this.className="collapsed"}injectShadowContent(){const e=document.createElement("style");e.textContent="\n @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');\n \n :host {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n }\n\n /* Standard mode styles */\n :host(.collapsed:not(.wix-embed)) {\n height: 60px !important;\n max-height: 60px !important;\n }\n\n :host(.expanded:not(.wix-embed)) {\n height: 520px;\n max-height: calc(100vh - 32px);\n }\n\n /* Wix embed mode: container for positioned widget */\n .wix-widget-container {\n position: absolute;\n bottom: 16px;\n right: 16px;\n width: 380px;\n height: 60px;\n max-width: calc(100vw - 32px);\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);\n transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);\n background: transparent;\n pointer-events: auto;\n }\n\n /* Debug info overlay */\n .debug-info {\n position: absolute;\n top: 10px;\n left: 10px;\n background: rgba(0, 0, 0, 0.8);\n color: white;\n padding: 8px;\n border-radius: 4px;\n font-size: 11px;\n font-family: monospace;\n z-index: 10000;\n max-width: 300px;\n pointer-events: none;\n white-space: pre-line;\n }\n\n :host(.wix-embed.collapsed) .wix-widget-container {\n height: 60px;\n }\n\n :host(.wix-embed.expanded) .wix-widget-container {\n height: 520px;\n max-height: calc(100vh - 32px);\n }\n\n @media (max-width: 639px) {\n :host(.expanded:not(.wix-embed)) {\n width: 100vw;\n height: 100vh;\n max-width: none;\n max-height: none;\n bottom: 0;\n right: 0;\n border-radius: 0;\n box-shadow: none;\n }\n \n :host(:not(.wix-embed)) {\n width: calc(100vw - 16px);\n right: 8px;\n bottom: 8px;\n }\n \n :host(.collapsed:not(.wix-embed)) {\n height: 60px !important;\n max-height: 60px !important;\n width: calc(100vw - 16px);\n right: 8px;\n bottom: 8px;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);\n }\n\n /* Wix embed mobile styles */\n :host(.wix-embed.expanded) .wix-widget-container {\n width: 100vw;\n height: 100vh;\n max-width: none;\n max-height: none;\n bottom: 0;\n right: 0;\n border-radius: 0;\n box-shadow: none;\n }\n \n .wix-widget-container {\n width: calc(100vw - 16px);\n right: 8px;\n bottom: 8px;\n }\n \n :host(.wix-embed.collapsed) .wix-widget-container {\n height: 60px !important;\n width: calc(100vw - 16px);\n right: 8px;\n bottom: 8px;\n border-radius: 16px;\n box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);\n }\n }\n \n .loading {\n background: #f3f4f6;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n border-radius: inherit;\n }\n \n .loading::after {\n content: 'Loading chat...';\n color: #6b7280;\n font-size: 14px;\n }\n\n .error-container {\n width: 100%;\n height: 100%;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-direction: column;\n background: #f9fafb;\n border-radius: inherit;\n border: 2px dashed #d1d5db;\n color: #6b7280;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n padding: 20px;\n box-sizing: border-box;\n }\n\n .error-icon {\n font-size: 24px;\n margin-bottom: 8px;\n }\n\n .error-title {\n font-size: 14px;\n font-weight: 500;\n margin-bottom: 4px;\n }\n\n .error-message {\n font-size: 12px;\n }\n\n .error-uuid {\n font-size: 11px;\n margin-top: 8px;\n opacity: 0.7;\n }\n\n iframe {\n width: 100%;\n height: 100%;\n border: 0;\n border-radius: inherit;\n }\n ",this.shadow.appendChild(e),(window.location.search.includes("debug")||window.location.search.includes("force-wix-mode"))&&this.addDebugInfo();const n=document.createElement("div");this.isInWixEmbed?n.className="wix-widget-container":n.style.cssText="\n width: 100%;\n height: 100%;\n border-radius: inherit;\n ",this.shadow.appendChild(n)}addDebugInfo(){const e=document.createElement("div");e.className="debug-info";const n=`Lookalike Widget v1.2.0\nMode: ${this.isInWixEmbed?"Wix Embed":"Standard"}\nViewport: ${window.innerWidth}x${window.innerHeight}\nIn iframe: ${window!==window.parent}\nHostname: ${window.location.hostname}\nClasses: ${this.className}`;e.textContent=n,this.shadow.appendChild(e),console.log("๐Ÿ› Debug info added to widget")}buildIframeSrc(){if(!this.config.storyfileUuid)return console.error("โŒ No storyfile UUID configured"),null;const e=new URL(`/${this.config.storyfileUuid}/chat`,BASE_URL);e.searchParams.set("embed",""),e.searchParams.set("variant","floating"),e.searchParams.set("anchor","bottom-right");const n=[];return this.config.enableText&&n.push("text"),this.config.enableAudio&&n.push("audio"),this.config.enableVideo&&n.push("video"),n.length>0&&n.length<3&&e.searchParams.set("modes",n.join(",")),this.config.primaryColor&&"#2563eb"!==this.config.primaryColor&&e.searchParams.set("theme",`primary:${this.config.primaryColor}`),console.log("๐Ÿ”— Built iframe URL:",e.toString()),e.toString()}injectIframe(){const e=this.isInWixEmbed?".wix-widget-container":"div:last-child",n=this.shadow.querySelector(e);console.log("๐Ÿ–ผ๏ธ Injecting iframe into container:",e),console.log("๐Ÿ“ฆ Container found:",!!n),n&&(console.log("๐Ÿ“ Container rect:",n.getBoundingClientRect()),console.log("๐ŸŽจ Container computed styles:",{position:getComputedStyle(n).position,width:getComputedStyle(n).width,height:getComputedStyle(n).height,bottom:getComputedStyle(n).bottom,right:getComputedStyle(n).right}));const i=n?.querySelector("iframe");i&&(console.log("๐Ÿ—‘๏ธ Removing existing iframe"),i.remove());const t=this.buildIframeSrc();if(!t)return void this.showConfigurationError(n);console.log("๐Ÿ”— Creating iframe with src:",t);const o=document.createElement("iframe");o.className="loading",o.src=t,o.allow="microphone; camera",o.loading="lazy",o.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups allow-presentation"),o.onerror=e=>{console.error("โŒ Failed to load widget iframe:",e),this.showLoadingError(n)},o.onload=()=>{console.log("โœ… Iframe loaded successfully"),console.log("๐Ÿ“ Iframe rect after load:",o.getBoundingClientRect()),o.classList.remove("loading")},this.currentIframe=o,this.setupMessageHandling(o),n.appendChild(o),console.log("๐ŸŽฏ Iframe injection complete")}setupMessageHandling(e){this.messageHandler&&window.removeEventListener("message",this.messageHandler),this.messageHandler=n=>{if(console.log("๐Ÿ“จ Received message:",n.data,"from:",n.origin),n.source===e.contentWindow&&"lookalike-widget-ready"===n.data?.type){console.log("๐ŸŽ‰ Widget ready, setting up communication");const n=new MessageChannel;n.port1.onmessage=e=>{if(console.log("๐Ÿ“ Received resize message:",e.data),"lookalike-widget-resize"===e.data?.type){const n=e.data.collapsed?"collapsed":"expanded";console.log(`๐Ÿ“ Widget resize: ${this.className} โ†’ ${n}`),console.log("๐Ÿ“ Before resize - Host element rect:",this.getBoundingClientRect()),this.className=this.isInWixEmbed?`${n} wix-embed`:n,setTimeout(()=>{console.log("๐Ÿ“ After resize - Host element rect:",this.getBoundingClientRect());const e=this.shadow.querySelector(this.isInWixEmbed?".wix-widget-container":"div:last-child");e&&console.log("๐Ÿ“ Widget container rect:",e.getBoundingClientRect())},100)}},e.contentWindow.postMessage({type:"lookalike-init-channel"},BASE_URL,[n.port2])}},window.addEventListener("message",this.messageHandler),console.log("๐Ÿ‘‚ Message handler installed")}showConfigurationError(e){e.innerHTML='\n <div class="error-container">\n <div class="error-icon">โš ๏ธ</div>\n <div class="error-title">Configuration Error</div>\n <div class="error-message">No UUID configured. Please add a uuid attribute.</div>\n <div class="error-uuid">Expected: &lt;lookalike-widget uuid="your-uuid"&gt;</div>\n </div>\n '}showLoadingError(e){e.innerHTML=`\n <div class="error-container">\n <div class="error-icon">โš ๏ธ</div>\n <div class="error-title">Widget Loading Error</div>\n <div class="error-message">Check console for details</div>\n <div class="error-uuid">UUID: ${this.config.storyfileUuid}</div>\n </div>\n `}disconnectedCallback(){this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null)}}customElements.define("lookalike-widget",LookalikeWidget),"undefined"!=typeof module&&module.exports&&(module.exports=LookalikeWidget);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lookalike/widget",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Lookalike conversational AI widget for easy embedding",
5
5
  "main": "dist/lookalike-widget.js",
6
6
  "module": "dist/lookalike-widget.js",