copilot-chat-widget 0.1.17 → 0.1.19
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/README.md +38 -45
- package/dist/chat-widget.min.js +3 -3
- package/dist/index.cjs +3 -3
- package/dist/index.mjs +43 -50
- package/package.json +1 -1
- package/src/index.d.ts +3 -4
- package/src/index.js +310 -326
- package/src/widget-runtime.js +101 -156
package/src/widget-runtime.js
CHANGED
|
@@ -11,22 +11,7 @@
|
|
|
11
11
|
const IFRAME_SIZE = 720;
|
|
12
12
|
const embeddingScript = document.currentScript;
|
|
13
13
|
|
|
14
|
-
const
|
|
15
|
-
if (!scriptEl?.src) return {};
|
|
16
|
-
try {
|
|
17
|
-
const url = new URL(scriptEl.src, window.location.href);
|
|
18
|
-
const params = {};
|
|
19
|
-
url.searchParams.forEach((value, key) => {
|
|
20
|
-
params[key] = value;
|
|
21
|
-
});
|
|
22
|
-
return params;
|
|
23
|
-
} catch (error) {
|
|
24
|
-
console.warn("[CopilotChat] Failed to parse script query params:", error);
|
|
25
|
-
return {};
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const ready = (fn) => {
|
|
14
|
+
const ready = (fn) => {
|
|
30
15
|
if (document.readyState === "complete" || document.readyState === "interactive") {
|
|
31
16
|
setTimeout(fn, 0);
|
|
32
17
|
} else {
|
|
@@ -57,47 +42,47 @@
|
|
|
57
42
|
|
|
58
43
|
return candidate || null;
|
|
59
44
|
};
|
|
60
|
-
|
|
61
|
-
const buildWidget = ({ iframeUrl, launcherIcon }) => {
|
|
62
|
-
const existingRoot = document.querySelector("[data-copilot-widget-root]");
|
|
63
|
-
if (existingRoot) {
|
|
64
|
-
existingRoot.remove();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const showCheckoutToast = (message) => {
|
|
68
|
-
const existingToast = document.querySelector("[data-copilot-checkout-toast]");
|
|
69
|
-
if (existingToast) {
|
|
70
|
-
existingToast.remove();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const toast = document.createElement("div");
|
|
74
|
-
toast.setAttribute("data-copilot-checkout-toast", "true");
|
|
75
|
-
toast.innerText = message;
|
|
76
|
-
|
|
77
|
-
Object.assign(toast.style, {
|
|
78
|
-
position: "fixed",
|
|
79
|
-
top: "20px",
|
|
80
|
-
left: "50%",
|
|
81
|
-
transform: "translateX(-50%)",
|
|
82
|
-
padding: "12px 16px",
|
|
83
|
-
background: "#0f172a",
|
|
84
|
-
color: "white",
|
|
85
|
-
borderRadius: "12px",
|
|
86
|
-
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
87
|
-
zIndex: 2147483647,
|
|
88
|
-
fontSize: "14px",
|
|
89
|
-
fontWeight: "600",
|
|
90
|
-
maxWidth: "420px",
|
|
91
|
-
lineHeight: "1.4",
|
|
92
|
-
textAlign: "center",
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
document.body.appendChild(toast);
|
|
96
|
-
|
|
97
|
-
setTimeout(() => {
|
|
98
|
-
toast.remove();
|
|
99
|
-
}, 4500);
|
|
100
|
-
};
|
|
45
|
+
|
|
46
|
+
const buildWidget = ({ iframeUrl, launcherIcon }) => {
|
|
47
|
+
const existingRoot = document.querySelector("[data-copilot-widget-root]");
|
|
48
|
+
if (existingRoot) {
|
|
49
|
+
existingRoot.remove();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const showCheckoutToast = (message) => {
|
|
53
|
+
const existingToast = document.querySelector("[data-copilot-checkout-toast]");
|
|
54
|
+
if (existingToast) {
|
|
55
|
+
existingToast.remove();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const toast = document.createElement("div");
|
|
59
|
+
toast.setAttribute("data-copilot-checkout-toast", "true");
|
|
60
|
+
toast.innerText = message;
|
|
61
|
+
|
|
62
|
+
Object.assign(toast.style, {
|
|
63
|
+
position: "fixed",
|
|
64
|
+
top: "20px",
|
|
65
|
+
left: "50%",
|
|
66
|
+
transform: "translateX(-50%)",
|
|
67
|
+
padding: "12px 16px",
|
|
68
|
+
background: "#0f172a",
|
|
69
|
+
color: "white",
|
|
70
|
+
borderRadius: "12px",
|
|
71
|
+
boxShadow: "0 8px 24px rgba(0,0,0,0.25)",
|
|
72
|
+
zIndex: 2147483647,
|
|
73
|
+
fontSize: "14px",
|
|
74
|
+
fontWeight: "600",
|
|
75
|
+
maxWidth: "420px",
|
|
76
|
+
lineHeight: "1.4",
|
|
77
|
+
textAlign: "center",
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
document.body.appendChild(toast);
|
|
81
|
+
|
|
82
|
+
setTimeout(() => {
|
|
83
|
+
toast.remove();
|
|
84
|
+
}, 4500);
|
|
85
|
+
};
|
|
101
86
|
|
|
102
87
|
// ---------- Shadow DOM container ----------
|
|
103
88
|
const containerHost = document.createElement("div");
|
|
@@ -256,42 +241,42 @@
|
|
|
256
241
|
btn.style.transform = "scale(1)";
|
|
257
242
|
};
|
|
258
243
|
|
|
259
|
-
const handleWidgetMessage = (event) => {
|
|
260
|
-
const { data, source } = event || {};
|
|
261
|
-
if (!data?.type) return;
|
|
262
|
-
|
|
263
|
-
if (data.type === "CART_CHECKOUT" && source === iframe.contentWindow) {
|
|
264
|
-
console.log("[CopilotChat] Received checkout payload from widget:", data);
|
|
265
|
-
showCheckoutToast("Checkout message received from chat widget. Check console for payload.");
|
|
266
|
-
return;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (data.type === "WIDGET_READY" && source === iframe.contentWindow) {
|
|
270
|
-
iframe.contentWindow.postMessage({ type: "INIT_WIDGET" }, "*");
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (data.type === "CHAT_CLOSED") {
|
|
275
|
-
closeChat();
|
|
276
|
-
}
|
|
277
|
-
};
|
|
278
|
-
|
|
279
|
-
btn.onclick = (event) => {
|
|
280
|
-
event.stopPropagation();
|
|
281
|
-
isOpen = !isOpen;
|
|
282
|
-
if (isOpen) {
|
|
283
|
-
container.style.display = "block";
|
|
284
|
-
arrow.style.display = "block";
|
|
285
|
-
requestAnimationFrame(() => {
|
|
286
|
-
container.style.opacity = "1";
|
|
287
|
-
container.style.transform = "scale(1) translateY(0)";
|
|
288
|
-
});
|
|
289
|
-
} else {
|
|
290
|
-
closeChat();
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
|
|
294
|
-
window.addEventListener("message", handleWidgetMessage);
|
|
244
|
+
const handleWidgetMessage = (event) => {
|
|
245
|
+
const { data, source } = event || {};
|
|
246
|
+
if (!data?.type) return;
|
|
247
|
+
|
|
248
|
+
if (data.type === "CART_CHECKOUT" && source === iframe.contentWindow) {
|
|
249
|
+
console.log("[CopilotChat] Received checkout payload from widget:", data);
|
|
250
|
+
showCheckoutToast("Checkout message received from chat widget. Check console for payload.");
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (data.type === "WIDGET_READY" && source === iframe.contentWindow) {
|
|
255
|
+
iframe.contentWindow.postMessage({ type: "INIT_WIDGET" }, "*");
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (data.type === "CHAT_CLOSED") {
|
|
260
|
+
closeChat();
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
btn.onclick = (event) => {
|
|
265
|
+
event.stopPropagation();
|
|
266
|
+
isOpen = !isOpen;
|
|
267
|
+
if (isOpen) {
|
|
268
|
+
container.style.display = "block";
|
|
269
|
+
arrow.style.display = "block";
|
|
270
|
+
requestAnimationFrame(() => {
|
|
271
|
+
container.style.opacity = "1";
|
|
272
|
+
container.style.transform = "scale(1) translateY(0)";
|
|
273
|
+
});
|
|
274
|
+
} else {
|
|
275
|
+
closeChat();
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
window.addEventListener("message", handleWidgetMessage);
|
|
295
280
|
|
|
296
281
|
document.addEventListener("click", (event) => {
|
|
297
282
|
const target = event.target;
|
|
@@ -322,75 +307,35 @@
|
|
|
322
307
|
console.error(`[CopilotChat] ${message}`);
|
|
323
308
|
};
|
|
324
309
|
|
|
325
|
-
const shouldAutoBootstrapFromScript = () => {
|
|
326
|
-
const scriptEl = resolveEmbeddingScript();
|
|
327
|
-
if (!scriptEl) return false;
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
const
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
if (fromConfig) return fromConfig;
|
|
344
|
-
|
|
345
|
-
try {
|
|
346
|
-
const stored = window.localStorage.getItem("copilotChatToken");
|
|
347
|
-
if (stored) return stored;
|
|
348
|
-
} catch (error) {
|
|
349
|
-
// ignore storage errors
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
if (typeof window !== "undefined" && typeof window.prompt === "function") {
|
|
353
|
-
const entered = window.prompt("Enter your Copilot Chat token:");
|
|
354
|
-
if (entered) {
|
|
355
|
-
try {
|
|
356
|
-
window.localStorage.setItem("copilotChatToken", entered);
|
|
357
|
-
} catch (error) {
|
|
358
|
-
// ignore storage errors
|
|
359
|
-
}
|
|
360
|
-
return entered;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
return null;
|
|
365
|
-
};
|
|
366
|
-
|
|
367
|
-
const token = resolveToken();
|
|
368
|
-
|
|
369
|
-
if (!token) {
|
|
370
|
-
handleError("Missing token (provide via init config, window.CopilotChatConfig.token, or data-token attribute).");
|
|
371
|
-
return null;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
const baseUrl =
|
|
375
|
-
config.baseUrl ||
|
|
376
|
-
globalConfig.baseUrl ||
|
|
377
|
-
datasetConfig.baseUrl ||
|
|
378
|
-
queryConfig.baseUrl ||
|
|
379
|
-
BUILD_BASE_URL ||
|
|
380
|
-
inferBaseUrlFromScript(scriptEl) ||
|
|
381
|
-
(typeof window !== "undefined" && window.location?.origin) ||
|
|
382
|
-
null;
|
|
310
|
+
const shouldAutoBootstrapFromScript = () => {
|
|
311
|
+
const scriptEl = resolveEmbeddingScript();
|
|
312
|
+
if (!scriptEl) return false;
|
|
313
|
+
const dataset = scriptEl.dataset || {};
|
|
314
|
+
return dataset.autoload !== "false";
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
const initCopilotChatWidget = async (config = {}) => {
|
|
318
|
+
const scriptEl = config.scriptEl || resolveEmbeddingScript();
|
|
319
|
+
const globalConfig = window.CopilotChatConfig || {};
|
|
320
|
+
|
|
321
|
+
const baseUrl =
|
|
322
|
+
config.baseUrl ||
|
|
323
|
+
globalConfig.baseUrl ||
|
|
324
|
+
BUILD_BASE_URL ||
|
|
325
|
+
inferBaseUrlFromScript(scriptEl) ||
|
|
326
|
+
(typeof window !== "undefined" && window.location?.origin) ||
|
|
327
|
+
null;
|
|
383
328
|
|
|
384
329
|
if (!baseUrl) {
|
|
385
330
|
handleError("Unable to resolve base URL from embedding script or window.location.");
|
|
386
331
|
return null;
|
|
387
332
|
}
|
|
388
333
|
|
|
389
|
-
try {
|
|
390
|
-
const response = await fetch(`${baseUrl}/api/chat-widget/config
|
|
391
|
-
credentials: "omit",
|
|
392
|
-
mode: "cors",
|
|
393
|
-
});
|
|
334
|
+
try {
|
|
335
|
+
const response = await fetch(`${baseUrl}/api/chat-widget/config`, {
|
|
336
|
+
credentials: "omit",
|
|
337
|
+
mode: "cors",
|
|
338
|
+
});
|
|
394
339
|
|
|
395
340
|
if (!response.ok) {
|
|
396
341
|
throw new Error(`Server responded with ${response.status}`);
|