copilot-chat-widget 0.1.27 → 0.1.28
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/chat-widget.min.js +2 -2
- package/package.json +1 -1
- package/src/widget-runtime.js +58 -18
package/dist/chat-widget.min.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
(function(){"use strict";(()=>{if(typeof window>"u"||typeof document>"u"||window.__copilotWidgetLoaded)return;window.__copilotWidgetLoaded=!0;const T="http://localhost:3000",b=64,
|
|
1
|
+
(function(){"use strict";(()=>{if(typeof window>"u"||typeof document>"u"||window.__copilotWidgetLoaded)return;window.__copilotWidgetLoaded=!0;const T="http://localhost:3000",b=64,x=720,y=document.currentScript,k=t=>{if(!t?.src)return{};try{const s=new URL(t.src,window.location.href),n={};return s.searchParams.forEach((l,c)=>{n[c]=l}),n}catch(s){return console.warn("[CopilotChat] Failed to parse script query params:",s),{}}},I=t=>{document.readyState==="complete"||document.readyState==="interactive"?setTimeout(t,0):document.addEventListener("DOMContentLoaded",t)},E=()=>y||Array.from(document.querySelectorAll("script")).reverse().find(n=>n.dataset?.token||n.src&&n.src.includes("chat-widget"))||null,U=({iframeUrl:t,launcherIcon:s})=>{const n=document.querySelector("[data-copilot-widget-root]");n&&n.remove();const l=w=>{const a=document.querySelector("[data-copilot-checkout-toast]");a&&a.remove();const h=document.createElement("div");h.setAttribute("data-copilot-checkout-toast","true"),h.innerText=w,Object.assign(h.style,{position:"fixed",top:"20px",left:"50%",transform:"translateX(-50%)",padding:"12px 16px",background:"#0f172a",color:"white",borderRadius:"12px",boxShadow:"0 8px 24px rgba(0,0,0,0.25)",zIndex:2147483647,fontSize:"14px",fontWeight:"600",maxWidth:"420px",lineHeight:"1.4",textAlign:"center"}),document.body.appendChild(h),setTimeout(()=>{h.remove()},4500)},c=document.createElement("div");c.setAttribute("data-copilot-widget-root","true");const C=c.attachShadow({mode:"open"});document.body.appendChild(c);const e=document.createElement("button");e.type="button",e.setAttribute("aria-label","Open Copilot chat"),e.innerHTML=`
|
|
2
2
|
<img
|
|
3
3
|
src="${s}"
|
|
4
4
|
alt="Copilot chat launcher"
|
|
5
5
|
style="width: 38px; height: 38px; object-fit: contain; border-radius: 50%; pointer-events: none;"
|
|
6
6
|
/>
|
|
7
|
-
`,Object.assign(e.style,{position:"fixed",bottom:"24px",right:"24px",width:`${b}px`,height:`${b}px`,borderRadius:"50%",border:"none",background:"linear-gradient(135deg, #0078ff, #00c6ff)",color:"white",cursor:"pointer",zIndex:999998,display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 6px 14px rgba(0,0,0,0.25)",transition:"all 0.25s ease"}),e.onmouseover=()=>{e.style.transform="scale(1.12)",e.style.boxShadow="0 10px 25px rgba(0,0,0,0.3)"},e.onmouseout=()=>{e.style.transform="scale(1)",e.style.boxShadow="0 6px 14px rgba(0,0,0,0.25)"};const i=document.createElement("div");i.setAttribute("data-copilot-widget-root","true"),Object.assign(i.style,{display:"none",position:"fixed",bottom:`${b+36}px`,right:"24px",zIndex:"999999",transformOrigin:"bottom right",transform:"scale(0.8) translateY(20px)",opacity:"0",transition:"all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)"});const o=document.createElement("div"),r=document.createElement("div"),m=document.createElement("div");Object.assign(o.style,{position:"absolute",bottom:"-14px",right:"28px",width:"30px",height:"20px",pointerEvents:"none",display:"none",zIndex:"1"}),Object.assign(r.style,{position:"absolute",bottom:"0",left:"0",right:"0",margin:"0 auto",width:"0",height:"0",borderLeft:"15px solid transparent",borderRight:"15px solid transparent",borderTop:"15px solid rgba(15,23,42,0.1)"}),Object.assign(m.style,{position:"absolute",bottom:"2px",left:"0",right:"0",margin:"0 auto",width:"0",height:"0",borderLeft:"13px solid transparent",borderRight:"13px solid transparent",borderTop:"13px solid white",boxShadow:"0 6px 16px rgba(15,23,42,0.12)",borderRadius:"2px"}),o.appendChild(r),o.appendChild(m);const p=document.createElement("div");Object.assign(p.style,{width:`${
|
|
7
|
+
`,Object.assign(e.style,{position:"fixed",bottom:"24px",right:"24px",width:`${b}px`,height:`${b}px`,borderRadius:"50%",border:"none",background:"linear-gradient(135deg, #0078ff, #00c6ff)",color:"white",cursor:"pointer",zIndex:999998,display:"flex",alignItems:"center",justifyContent:"center",boxShadow:"0 6px 14px rgba(0,0,0,0.25)",transition:"all 0.25s ease"}),e.onmouseover=()=>{e.style.transform="scale(1.12)",e.style.boxShadow="0 10px 25px rgba(0,0,0,0.3)"},e.onmouseout=()=>{e.style.transform="scale(1)",e.style.boxShadow="0 6px 14px rgba(0,0,0,0.25)"};const i=document.createElement("div");i.setAttribute("data-copilot-widget-root","true"),Object.assign(i.style,{display:"none",position:"fixed",bottom:`${b+36}px`,right:"24px",zIndex:"999999",transformOrigin:"bottom right",transform:"scale(0.8) translateY(20px)",opacity:"0",transition:"all 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55)"});const o=document.createElement("div"),r=document.createElement("div"),m=document.createElement("div");Object.assign(o.style,{position:"absolute",bottom:"-14px",right:"28px",width:"30px",height:"20px",pointerEvents:"none",display:"none",zIndex:"1"}),Object.assign(r.style,{position:"absolute",bottom:"0",left:"0",right:"0",margin:"0 auto",width:"0",height:"0",borderLeft:"15px solid transparent",borderRight:"15px solid transparent",borderTop:"15px solid rgba(15,23,42,0.1)"}),Object.assign(m.style,{position:"absolute",bottom:"2px",left:"0",right:"0",margin:"0 auto",width:"0",height:"0",borderLeft:"13px solid transparent",borderRight:"13px solid transparent",borderTop:"13px solid white",boxShadow:"0 6px 16px rgba(15,23,42,0.12)",borderRadius:"2px"}),o.appendChild(r),o.appendChild(m);const p=document.createElement("div");Object.assign(p.style,{width:`${x}px`,maxWidth:"calc(100vw - 48px)",height:`${Math.min(x,Math.max(320,window.innerHeight-140))}px`,maxHeight:"calc(100vh - 150px)",borderRadius:"20px",background:"white",border:"1px solid rgba(15,23,42,0.12)",boxShadow:"0 18px 45px rgba(15,23,42,0.16)",overflow:"hidden"}),C.appendChild(p);const d=document.createElement("iframe");d.src=t,d.title="Copilot chat widget",d.allow="clipboard-read; clipboard-write; microphone; camera; display-capture",d.setAttribute("scrolling","no"),Object.assign(d.style,{width:"100%",height:"100%",border:"none",display:"block",background:"transparent",overflow:"hidden"}),C.appendChild(p),p.appendChild(d),i.appendChild(o),i.appendChild(p),document.body.appendChild(e),document.body.appendChild(i);let u=!1;const f=()=>{u&&(u=!1,i.style.opacity="0",i.style.transform="scale(0.8) translateY(20px)",o.style.display="none",setTimeout(()=>{i.style.display="none"},250),e.style.transform="scale(1)")},O=w=>{const{data:a,source:h}=w||{};if(a?.type){if(a.type==="CART_CHECKOUT"&&h===d.contentWindow){console.log("[CopilotChat] Received checkout payload from widget:",a),l("Data:");return}if(a.type==="WIDGET_READY"&&h===d.contentWindow){d.contentWindow.postMessage({type:"INIT_WIDGET"},"*");return}a.type==="CHAT_CLOSED"&&f()}};e.onclick=w=>{w.stopPropagation(),u=!u,u?(i.style.display="block",o.style.display="block",requestAnimationFrame(()=>{i.style.opacity="1",i.style.transform="scale(1) translateY(0)"})):f()},window.addEventListener("message",O),document.addEventListener("click",w=>{const a=w.target;a&&u&&!i.contains(a)&&a!==e&&f()});const g={close:f,open:()=>{u||e.click()}};return window.CopilotChat=window.CopilotChat||{},window.CopilotChat.close=g.close,window.CopilotChat.open=g.open,window.CopilotChat.controls=g,g},v=t=>{console.error(`[CopilotChat] ${t}`)},A=()=>{const t=E();if(!t)return!1;const s=k(t),n=t.dataset||{},l=n.token||s.token,c=typeof window<"u"&&window.CopilotChatConfig&&window.CopilotChatConfig.token;return(l||c)&&n.autoload!=="false"},S=async(t={})=>{const s=t.scriptEl||E(),n=window.CopilotChatConfig||{},l=s?.dataset||{},c=k(s),e=(()=>{const o=t.token||n.token||l.token||c.token;if(o)return o;try{const r=window.localStorage.getItem("copilotChatToken");if(r)return r}catch{}if(typeof window<"u"&&typeof window.prompt=="function"){const r=window.prompt("Enter your Copilot Chat token:");if(r){try{window.localStorage.setItem("copilotChatToken",r)}catch{}return r}}return null})();if(!e)return v("Missing token (provide via init config, window.CopilotChatConfig.token, or data-token attribute)."),null;const i=t.baseUrl||n.baseUrl||l.baseUrl||c.baseUrl||T;try{const o=await fetch(`${i}/api/chat-widget/config?token=${encodeURIComponent(e)}`,{credentials:"omit",mode:"cors"});if(!o.ok)throw new Error(`Server responded with ${o.status}`);const r=await o.json();if(!r?.iframeUrl||!r?.launcherIcon)throw new Error("Received incomplete widget configuration from server.");return window.CopilotChat=window.CopilotChat||{},window.CopilotChat.init=(p={})=>{const d={iframeUrl:p.iframeUrl||r.iframeUrl,launcherIcon:p.launcherIcon||r.launcherIcon};return U(d)},window.CopilotChat.init(t)}catch(o){return v(o instanceof Error?o.message:"Unknown error during widget bootstrap."),null}};A()&&I(()=>{S()}),window.CopilotChat=window.CopilotChat||{},window.CopilotChat.load=S})()})();
|
package/package.json
CHANGED
package/src/widget-runtime.js
CHANGED
|
@@ -27,7 +27,10 @@
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
const ready = (fn) => {
|
|
30
|
-
if (
|
|
30
|
+
if (
|
|
31
|
+
document.readyState === "complete" ||
|
|
32
|
+
document.readyState === "interactive"
|
|
33
|
+
) {
|
|
31
34
|
setTimeout(fn, 0);
|
|
32
35
|
} else {
|
|
33
36
|
document.addEventListener("DOMContentLoaded", fn);
|
|
@@ -40,7 +43,10 @@
|
|
|
40
43
|
const srcUrl = new URL(scriptEl.src, window.location.href);
|
|
41
44
|
return `${srcUrl.protocol}//${srcUrl.host}`;
|
|
42
45
|
} catch (error) {
|
|
43
|
-
console.warn(
|
|
46
|
+
console.warn(
|
|
47
|
+
"[CopilotChat] Unable to infer base URL from script source.",
|
|
48
|
+
error
|
|
49
|
+
);
|
|
44
50
|
return null;
|
|
45
51
|
}
|
|
46
52
|
};
|
|
@@ -53,7 +59,11 @@
|
|
|
53
59
|
const scripts = Array.from(document.querySelectorAll("script"));
|
|
54
60
|
const candidate = scripts
|
|
55
61
|
.reverse()
|
|
56
|
-
.find(
|
|
62
|
+
.find(
|
|
63
|
+
(script) =>
|
|
64
|
+
script.dataset?.token ||
|
|
65
|
+
(script.src && script.src.includes("chat-widget"))
|
|
66
|
+
);
|
|
57
67
|
|
|
58
68
|
return candidate || null;
|
|
59
69
|
};
|
|
@@ -65,7 +75,9 @@
|
|
|
65
75
|
}
|
|
66
76
|
|
|
67
77
|
const showCheckoutToast = (message) => {
|
|
68
|
-
const existingToast = document.querySelector(
|
|
78
|
+
const existingToast = document.querySelector(
|
|
79
|
+
"[data-copilot-checkout-toast]"
|
|
80
|
+
);
|
|
69
81
|
if (existingToast) {
|
|
70
82
|
existingToast.remove();
|
|
71
83
|
}
|
|
@@ -223,7 +235,8 @@
|
|
|
223
235
|
const iframe = document.createElement("iframe");
|
|
224
236
|
iframe.src = iframeUrl;
|
|
225
237
|
iframe.title = "Copilot chat widget";
|
|
226
|
-
iframe.allow =
|
|
238
|
+
iframe.allow =
|
|
239
|
+
"clipboard-read; clipboard-write; microphone; camera; display-capture";
|
|
227
240
|
iframe.setAttribute("scrolling", "no");
|
|
228
241
|
Object.assign(iframe.style, {
|
|
229
242
|
width: "100%",
|
|
@@ -261,8 +274,12 @@
|
|
|
261
274
|
if (!data?.type) return;
|
|
262
275
|
|
|
263
276
|
if (data.type === "CART_CHECKOUT" && source === iframe.contentWindow) {
|
|
264
|
-
console.log(
|
|
265
|
-
|
|
277
|
+
console.log(
|
|
278
|
+
"[CopilotChat] Received checkout payload from widget:",
|
|
279
|
+
data
|
|
280
|
+
);
|
|
281
|
+
showCheckoutToast("Data:", data);
|
|
282
|
+
|
|
266
283
|
return;
|
|
267
284
|
}
|
|
268
285
|
|
|
@@ -328,7 +345,10 @@
|
|
|
328
345
|
const queryConfig = readQueryConfig(scriptEl);
|
|
329
346
|
const dataset = scriptEl.dataset || {};
|
|
330
347
|
const hasTokenHint = dataset.token || queryConfig.token;
|
|
331
|
-
const hasGlobalToken =
|
|
348
|
+
const hasGlobalToken =
|
|
349
|
+
typeof window !== "undefined" &&
|
|
350
|
+
window.CopilotChatConfig &&
|
|
351
|
+
window.CopilotChatConfig.token;
|
|
332
352
|
return (hasTokenHint || hasGlobalToken) && dataset.autoload !== "false";
|
|
333
353
|
};
|
|
334
354
|
|
|
@@ -339,7 +359,11 @@
|
|
|
339
359
|
const queryConfig = readQueryConfig(scriptEl);
|
|
340
360
|
|
|
341
361
|
const resolveToken = () => {
|
|
342
|
-
const fromConfig =
|
|
362
|
+
const fromConfig =
|
|
363
|
+
config.token ||
|
|
364
|
+
globalConfig.token ||
|
|
365
|
+
datasetConfig.token ||
|
|
366
|
+
queryConfig.token;
|
|
343
367
|
if (fromConfig) return fromConfig;
|
|
344
368
|
|
|
345
369
|
try {
|
|
@@ -349,7 +373,10 @@
|
|
|
349
373
|
// ignore storage errors
|
|
350
374
|
}
|
|
351
375
|
|
|
352
|
-
if (
|
|
376
|
+
if (
|
|
377
|
+
typeof window !== "undefined" &&
|
|
378
|
+
typeof window.prompt === "function"
|
|
379
|
+
) {
|
|
353
380
|
const entered = window.prompt("Enter your Copilot Chat token:");
|
|
354
381
|
if (entered) {
|
|
355
382
|
try {
|
|
@@ -367,7 +394,9 @@
|
|
|
367
394
|
const token = resolveToken();
|
|
368
395
|
|
|
369
396
|
if (!token) {
|
|
370
|
-
handleError(
|
|
397
|
+
handleError(
|
|
398
|
+
"Missing token (provide via init config, window.CopilotChatConfig.token, or data-token attribute)."
|
|
399
|
+
);
|
|
371
400
|
return null;
|
|
372
401
|
}
|
|
373
402
|
|
|
@@ -382,15 +411,20 @@
|
|
|
382
411
|
null;
|
|
383
412
|
|
|
384
413
|
if (!baseUrl) {
|
|
385
|
-
handleError(
|
|
414
|
+
handleError(
|
|
415
|
+
"Unable to resolve base URL from embedding script or window.location."
|
|
416
|
+
);
|
|
386
417
|
return null;
|
|
387
418
|
}
|
|
388
419
|
|
|
389
420
|
try {
|
|
390
|
-
const response = await fetch(
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
421
|
+
const response = await fetch(
|
|
422
|
+
`${baseUrl}/api/chat-widget/config?token=${encodeURIComponent(token)}`,
|
|
423
|
+
{
|
|
424
|
+
credentials: "omit",
|
|
425
|
+
mode: "cors",
|
|
426
|
+
}
|
|
427
|
+
);
|
|
394
428
|
|
|
395
429
|
if (!response.ok) {
|
|
396
430
|
throw new Error(`Server responded with ${response.status}`);
|
|
@@ -398,7 +432,9 @@
|
|
|
398
432
|
|
|
399
433
|
const remoteConfig = await response.json();
|
|
400
434
|
if (!remoteConfig?.iframeUrl || !remoteConfig?.launcherIcon) {
|
|
401
|
-
throw new Error(
|
|
435
|
+
throw new Error(
|
|
436
|
+
"Received incomplete widget configuration from server."
|
|
437
|
+
);
|
|
402
438
|
}
|
|
403
439
|
|
|
404
440
|
window.CopilotChat = window.CopilotChat || {};
|
|
@@ -414,7 +450,11 @@
|
|
|
414
450
|
const controls = window.CopilotChat.init(config);
|
|
415
451
|
return controls;
|
|
416
452
|
} catch (error) {
|
|
417
|
-
handleError(
|
|
453
|
+
handleError(
|
|
454
|
+
error instanceof Error
|
|
455
|
+
? error.message
|
|
456
|
+
: "Unknown error during widget bootstrap."
|
|
457
|
+
);
|
|
418
458
|
return null;
|
|
419
459
|
}
|
|
420
460
|
};
|