@lookalike/widget 1.1.0 → 1.2.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/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**: ~11KB
77
+ - **Gzipped**: ~3KB (estimated)
78
78
 
79
79
  ## License
80
80
 
@@ -36,11 +36,15 @@ class LookalikeWidget extends HTMLElement {
36
36
  this.currentIframe = null;
37
37
  this.shadow = null;
38
38
  this.messageHandler = null;
39
+ this.isInWixEmbed = false;
39
40
  }
40
41
 
41
42
  connectedCallback() {
42
43
  console.log('🚀 Lookalike Widget initializing...');
43
44
 
45
+ // Detect if we're in a Wix custom code embed (or similar constrained iframe)
46
+ this.detectWixEmbed();
47
+
44
48
  // Create shadow DOM for encapsulation
45
49
  this.shadow = this.attachShadow({ mode: 'closed' });
46
50
 
@@ -51,6 +55,34 @@ class LookalikeWidget extends HTMLElement {
51
55
  this.initLive();
52
56
  }
53
57
 
58
+ detectWixEmbed() {
59
+ try {
60
+ // Check if we're in an iframe and can't access parent
61
+ const inIframe = window !== window.parent;
62
+
63
+ // Check for Wix-specific indicators
64
+ const hasWixIndicators =
65
+ window.location.hostname.includes('wix.com') ||
66
+ window.location.hostname.includes('wixsite.com') ||
67
+ window.location.search.includes('wix') ||
68
+ document.referrer.includes('wix') ||
69
+ (inIframe && (
70
+ window.innerWidth < 500 || // Typical small embed size
71
+ window.innerHeight < 300
72
+ ));
73
+
74
+ this.isInWixEmbed = inIframe && hasWixIndicators;
75
+
76
+ if (this.isInWixEmbed) {
77
+ console.log('🔍 Detected Wix embed environment - using full-screen overlay mode');
78
+ }
79
+ } catch (error) {
80
+ // If we can't access parent due to cross-origin, assume we're in an embed
81
+ this.isInWixEmbed = true;
82
+ console.log('🔍 Cross-origin iframe detected - using full-screen overlay mode');
83
+ }
84
+ }
85
+
54
86
  loadConfiguration() {
55
87
  // Read configuration from HTML attributes
56
88
  if (this.hasAttribute('uuid')) {
@@ -117,7 +149,41 @@ class LookalikeWidget extends HTMLElement {
117
149
  initLive() {
118
150
  console.log('🚀 Initializing live widget with config:', this.config);
119
151
 
120
- // Set host element positioning and initial size
152
+ if (this.isInWixEmbed) {
153
+ this.initWixEmbedMode();
154
+ } else {
155
+ this.initStandardMode();
156
+ }
157
+
158
+ this.injectShadowContent();
159
+ this.injectIframe();
160
+ }
161
+
162
+ initWixEmbedMode() {
163
+ console.log('📱 Initializing Wix embed mode with full-screen overlay');
164
+
165
+ // Make the host element a full-screen transparent overlay
166
+ this.style.cssText = `
167
+ position: fixed;
168
+ top: 0;
169
+ left: 0;
170
+ width: 100vw;
171
+ height: 100vh;
172
+ border: 0;
173
+ z-index: 9999;
174
+ background: transparent;
175
+ pointer-events: none;
176
+ display: block;
177
+ `;
178
+
179
+ // Add collapsed class initially
180
+ this.className = 'collapsed wix-embed';
181
+ }
182
+
183
+ initStandardMode() {
184
+ console.log('💻 Initializing standard mode');
185
+
186
+ // Set host element positioning and initial size (original behavior)
121
187
  this.style.cssText = `
122
188
  position: fixed;
123
189
  bottom: 16px;
@@ -136,9 +202,6 @@ class LookalikeWidget extends HTMLElement {
136
202
 
137
203
  // Add collapsed class initially
138
204
  this.className = 'collapsed';
139
-
140
- this.injectShadowContent();
141
- this.injectIframe();
142
205
  }
143
206
 
144
207
  injectShadowContent() {
@@ -151,18 +214,43 @@ class LookalikeWidget extends HTMLElement {
151
214
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
152
215
  }
153
216
 
154
- :host(.collapsed) {
217
+ /* Standard mode styles */
218
+ :host(.collapsed:not(.wix-embed)) {
155
219
  height: 60px !important;
156
220
  max-height: 60px !important;
157
221
  }
158
222
 
159
- :host(.expanded) {
223
+ :host(.expanded:not(.wix-embed)) {
224
+ height: 520px;
225
+ max-height: calc(100vh - 32px);
226
+ }
227
+
228
+ /* Wix embed mode: container for positioned widget */
229
+ .wix-widget-container {
230
+ position: absolute;
231
+ bottom: 16px;
232
+ right: 16px;
233
+ width: 380px;
234
+ height: 60px;
235
+ max-width: calc(100vw - 32px);
236
+ border-radius: 16px;
237
+ box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
238
+ transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
239
+ background: transparent;
240
+ pointer-events: auto;
241
+ }
242
+
243
+ :host(.wix-embed.collapsed) .wix-widget-container {
244
+ height: 60px;
245
+ }
246
+
247
+ :host(.wix-embed.expanded) .wix-widget-container {
160
248
  height: 520px;
161
249
  max-height: calc(100vh - 32px);
162
250
  }
163
251
 
164
252
  @media (max-width: 639px) {
165
- :host(.expanded) {
253
+ :host(.expanded:not(.wix-embed)) {
166
254
  width: 100vw;
167
255
  height: 100vh;
168
256
  max-width: none;
@@ -173,13 +261,13 @@ class LookalikeWidget extends HTMLElement {
173
261
  box-shadow: none;
174
262
  }
175
263
 
176
- :host {
264
+ :host(:not(.wix-embed)) {
177
265
  width: calc(100vw - 16px);
178
266
  right: 8px;
179
267
  bottom: 8px;
180
268
  }
181
269
 
182
- :host(.collapsed) {
270
+ :host(.collapsed:not(.wix-embed)) {
183
271
  height: 60px !important;
184
272
  max-height: 60px !important;
185
273
  width: calc(100vw - 16px);
@@ -188,6 +276,33 @@ class LookalikeWidget extends HTMLElement {
188
276
  border-radius: 16px;
189
277
  box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
190
278
  }
279
+
280
+ /* Wix embed mobile styles */
281
+ :host(.wix-embed.expanded) .wix-widget-container {
282
+ width: 100vw;
283
+ height: 100vh;
284
+ max-width: none;
285
+ max-height: none;
286
+ bottom: 0;
287
+ right: 0;
288
+ border-radius: 0;
289
+ box-shadow: none;
290
+ }
291
+
292
+ .wix-widget-container {
293
+ width: calc(100vw - 16px);
294
+ right: 8px;
295
+ bottom: 8px;
296
+ }
297
+
298
+ :host(.wix-embed.collapsed) .wix-widget-container {
299
+ height: 60px !important;
300
+ width: calc(100vw - 16px);
301
+ right: 8px;
302
+ bottom: 8px;
303
+ border-radius: 16px;
304
+ box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25);
305
+ }
191
306
  }
192
307
 
193
308
  .loading {
@@ -256,11 +371,18 @@ class LookalikeWidget extends HTMLElement {
256
371
 
257
372
  // Create container for iframe
258
373
  const container = document.createElement('div');
259
- container.style.cssText = `
260
- width: 100%;
261
- height: 100%;
262
- border-radius: inherit;
263
- `;
374
+
375
+ if (this.isInWixEmbed) {
376
+ // In Wix embed mode, create a positioned container within the full-screen overlay
377
+ container.className = 'wix-widget-container';
378
+ } else {
379
+ // In standard mode, container fills the host element
380
+ container.style.cssText = `
381
+ width: 100%;
382
+ height: 100%;
383
+ border-radius: inherit;
384
+ `;
385
+ }
264
386
 
265
387
  this.shadow.appendChild(container);
266
388
  }
@@ -296,7 +418,7 @@ class LookalikeWidget extends HTMLElement {
296
418
  }
297
419
 
298
420
  injectIframe() {
299
- const container = this.shadow.querySelector('div:last-child');
421
+ const container = this.shadow.querySelector(this.isInWixEmbed ? '.wix-widget-container' : 'div:last-child');
300
422
 
301
423
  // Remove existing iframe if present
302
424
  const existingIframe = container.querySelector('iframe');
@@ -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 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,this.isInWixEmbed=!1}connectedCallback(){console.log("🚀 Lookalike Widget initializing..."),this.detectWixEmbed(),this.shadow=this.attachShadow({mode:"closed"}),this.loadConfiguration(),this.initLive()}detectWixEmbed(){try{const e=window!==window.parent,n=window.location.hostname.includes("wix.com")||window.location.hostname.includes("wixsite.com")||window.location.search.includes("wix")||document.referrer.includes("wix")||e&&(window.innerWidth<500||window.innerHeight<300);this.isInWixEmbed=e&&n,this.isInWixEmbed&&console.log("🔍 Detected Wix embed environment - using full-screen overlay mode")}catch(e){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"),this.style.cssText="\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.className="collapsed wix-embed"}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 :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);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)}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.shadow.querySelector(this.isInWixEmbed?".wix-widget-container":"div:last-child"),n=e.querySelector("iframe");n&&n.remove();const i=this.buildIframeSrc();if(!i)return void this.showConfigurationError(e);const t=document.createElement("iframe");t.className="loading",t.src=i,t.allow="microphone; camera",t.loading="lazy",t.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms allow-popups allow-presentation"),t.onerror=()=>{console.error("❌ Failed to load widget iframe"),this.showLoadingError(e)},t.onload=()=>{console.log("✅ Iframe loaded successfully"),t.classList.remove("loading")},this.currentIframe=t,this.setupMessageHandling(t),e.appendChild(t)}setupMessageHandling(e){this.messageHandler&&window.removeEventListener("message",this.messageHandler),this.messageHandler=n=>{if(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}`),this.className=n}},e.contentWindow.postMessage({type:"lookalike-init-channel"},BASE_URL,[n.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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lookalike/widget",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Lookalike conversational AI widget for easy embedding",
5
5
  "main": "dist/lookalike-widget.js",
6
6
  "module": "dist/lookalike-widget.js",