copilot-chat-widget 0.1.7 → 0.1.9
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 +68 -78
- package/dist/chat-widget.min.js +3 -3
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +5 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,35 +1,31 @@
|
|
|
1
|
-
# Copilot Chat Widget (NPM)
|
|
2
|
-
|
|
3
|
-
Widget chat Copilot
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
```jsx
|
|
30
|
-
import { useEffect } from "react";
|
|
31
|
-
import { loadCopilotChatWidget } from "copilot-chat-widget";
|
|
32
|
-
|
|
1
|
+
# Copilot Chat Widget (NPM)
|
|
2
|
+
|
|
3
|
+
Widget chat Copilot có thể nhúng theo hai cách:
|
|
4
|
+
1. Qua NPM (khuyến nghị cho SPA/Next.js/React/Vue).
|
|
5
|
+
2. Qua thẻ `<script>` (tương thích ngược, không cần build).
|
|
6
|
+
|
|
7
|
+
## Cài đặt
|
|
8
|
+
```bash
|
|
9
|
+
npm install copilot-chat-widget
|
|
10
|
+
# hoặc
|
|
11
|
+
yarn add copilot-chat-widget
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Sử dụng với NPM (import)
|
|
15
|
+
```js
|
|
16
|
+
import { loadCopilotChatWidget } from "copilot-chat-widget";
|
|
17
|
+
|
|
18
|
+
loadCopilotChatWidget({ token: "YOUR_WIDGET_TOKEN" });
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Hàm này sẽ gắn script `chat-widget.min.js` (IIFE) vào trang, đọc `token` từ options (hoặc `window.CopilotChatConfig` nếu bạn set trước).
|
|
22
|
+
- Nếu backend widget không cùng origin với web hiện tại, truyền thêm `baseUrl: "https://your-backend-domain"` để gọi đúng API. Nếu không truyền, widget sẽ dùng giá trị build-time `WIDGET_BASE_URL` (đọc từ `.env` khi build), sau đó mới fallback sang origin của script/trang.
|
|
23
|
+
|
|
24
|
+
### React/Next.js
|
|
25
|
+
```jsx
|
|
26
|
+
import { useEffect } from "react";
|
|
27
|
+
import { loadCopilotChatWidget } from "copilot-chat-widget";
|
|
28
|
+
|
|
33
29
|
export default function Page() {
|
|
34
30
|
useEffect(() => {
|
|
35
31
|
loadCopilotChatWidget({
|
|
@@ -37,49 +33,43 @@ export default function Page() {
|
|
|
37
33
|
baseUrl: process.env.NEXT_PUBLIC_WIDGET_BASE_URL // nếu backend khác origin; nếu không, sẽ dùng giá trị build-time hoặc origin hiện tại
|
|
38
34
|
});
|
|
39
35
|
}, []);
|
|
40
|
-
|
|
41
|
-
return <main>Your page content</main>;
|
|
42
|
-
}
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
##
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
data-
|
|
51
|
-
></script>
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
- `data-
|
|
55
|
-
- `data-
|
|
56
|
-
|
|
57
|
-
## API
|
|
58
|
-
|
|
59
|
-
- `
|
|
60
|
-
- `
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
window.CopilotChat.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
```bash
|
|
82
|
-
npm publish --access public
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
Neu muon doi ten package cho phu hop scope cong ty, sua truong `name` trong `webui/widget/package.json` truoc khi publish.
|
|
36
|
+
|
|
37
|
+
return <main>Your page content</main>;
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Sử dụng qua thẻ `<script>` (giữ hành vi cũ)
|
|
42
|
+
```html
|
|
43
|
+
<script
|
|
44
|
+
src="https://cdn.example.com/chat-widget.min.js"
|
|
45
|
+
data-token="YOUR_WIDGET_TOKEN"
|
|
46
|
+
data-base-url="https://your-backend-domain" <!-- tùy chọn nếu khác origin -->
|
|
47
|
+
></script>
|
|
48
|
+
```
|
|
49
|
+
- `data-token`: bắt buộc.
|
|
50
|
+
- `data-autoload="false"`: nếu muốn chèn script nhưng tự gọi `window.CopilotChat.init()` sau.
|
|
51
|
+
- `data-base-url`: override host backend nếu khác origin hoặc bạn không build sẵn `WIDGET_BASE_URL`.
|
|
52
|
+
|
|
53
|
+
## API cấu hình
|
|
54
|
+
- `token` (string, bắt buộc): mã token widget.
|
|
55
|
+
- `autoload` (boolean): đặt `false` nếu muốn tự gọi `window.CopilotChat.load()`.
|
|
56
|
+
- `baseUrl` (string): host/backend cung cấp API `/api/chat-widget/config`. Cần khi web embed khác origin; nếu không truyền sẽ dùng `WIDGET_BASE_URL` build-time rồi fallback origin.
|
|
57
|
+
|
|
58
|
+
Khi script đã load, có thể gọi:
|
|
59
|
+
```js
|
|
60
|
+
window.CopilotChat.open(); // mở widget
|
|
61
|
+
window.CopilotChat.close(); // đóng widget
|
|
62
|
+
window.CopilotChat.load(); // khởi tạo lại nếu autoload=false
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Build và publish package
|
|
66
|
+
```bash
|
|
67
|
+
cd webui/widget
|
|
68
|
+
npm install
|
|
69
|
+
WIDGET_BASE_URL=https://your-backend-domain npm run build # gắn default baseUrl vào bundle
|
|
70
|
+
```
|
|
71
|
+
Sau khi kiểm tra output trong `webui/widget/dist`, có thể publish lên NPM:
|
|
72
|
+
```bash
|
|
73
|
+
npm publish --access public
|
|
74
|
+
```
|
|
75
|
+
Nếu muốn đổi tên package cho phù hợp scope công ty, sửa trường `name` trong `webui/widget/package.json` trước khi publish.
|
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
|
|
1
|
+
(function(){"use strict";(()=>{if(typeof window>"u"||typeof document>"u"||window.__copilotWidgetLoaded)return;window.__copilotWidgetLoaded=!0;const v="http://localhost:3005",m=64,f=720,C=document.currentScript,y=t=>{if(!t?.src)return{};try{const i=new URL(t.src,window.location.href),o={};return i.searchParams.forEach((a,s)=>{o[s]=a}),o}catch(i){return console.warn("[CopilotChat] Failed to parse script query params:",i),{}}},S=t=>{document.readyState==="complete"||document.readyState==="interactive"?setTimeout(t,0):document.addEventListener("DOMContentLoaded",t)},x=()=>C||Array.from(document.querySelectorAll("script")).reverse().find(o=>o.dataset?.token||o.src&&o.src.includes("chat-widget"))||null,U=({iframeUrl:t,launcherIcon:i})=>{const o=document.querySelector("[data-copilot-widget-root]");o&&o.remove();const a=document.createElement("div");a.setAttribute("data-copilot-widget-root","true");const s=a.attachShadow({mode:"open"});document.body.appendChild(a);const e=document.createElement("button");e.type="button",e.setAttribute("aria-label","Open Copilot chat"),e.innerHTML=`
|
|
2
2
|
<img
|
|
3
|
-
src="${
|
|
3
|
+
src="${i}"
|
|
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:`${m}px`,height:`${m}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
|
|
7
|
+
`,Object.assign(e.style,{position:"fixed",bottom:"24px",right:"24px",width:`${m}px`,height:`${m}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 n=document.createElement("div");n.setAttribute("data-copilot-widget-root","true"),Object.assign(n.style,{display:"none",position:"fixed",bottom:`${m+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 r=document.createElement("div"),l=document.createElement("div"),g=document.createElement("div");Object.assign(r.style,{position:"absolute",bottom:"-14px",right:"28px",width:"30px",height:"20px",pointerEvents:"none",display:"none",zIndex:"1"}),Object.assign(l.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(g.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"}),r.appendChild(l),r.appendChild(g);const d=document.createElement("div");Object.assign(d.style,{width:`${f}px`,maxWidth:"calc(100vw - 48px)",height:`${Math.min(f,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"}),s.appendChild(d);const c=document.createElement("iframe");c.src=t,c.title="Copilot chat widget",c.allow="clipboard-read; clipboard-write; microphone; camera; display-capture",c.setAttribute("scrolling","no"),Object.assign(c.style,{width:"100%",height:"100%",border:"none",display:"block",background:"transparent",overflow:"hidden"}),s.appendChild(d),d.appendChild(c),n.appendChild(r),n.appendChild(d),document.body.appendChild(e),document.body.appendChild(n);let p=!1;const u=()=>{p&&(p=!1,n.style.opacity="0",n.style.transform="scale(0.8) translateY(20px)",r.style.display="none",setTimeout(()=>{n.style.display="none"},250),e.style.transform="scale(1)")};e.onclick=h=>{h.stopPropagation(),p=!p,p?(n.style.display="block",r.style.display="block",requestAnimationFrame(()=>{n.style.opacity="1",n.style.transform="scale(1) translateY(0)"})):u()},window.addEventListener("message",h=>{h?.data?.type==="CHAT_CLOSED"&&u()}),document.addEventListener("click",h=>{const b=h.target;b&&p&&!n.contains(b)&&b!==e&&u()});const w={close:u,open:()=>{p||e.click()}};return window.CopilotChat=window.CopilotChat||{},window.CopilotChat.close=w.close,window.CopilotChat.open=w.open,window.CopilotChat.controls=w,w},k=t=>{console.error(`[CopilotChat] ${t}`)},I=()=>{const t=x();if(!t)return!1;const i=y(t),o=t.dataset||{},a=o.token||i.token,s=typeof window<"u"&&window.CopilotChatConfig&&window.CopilotChatConfig.token;return(a||s)&&o.autoload!=="false"},E=async(t={})=>{const i=t.scriptEl||x(),o=window.CopilotChatConfig||{},a=i?.dataset||{},s=y(i),e=t.token||o.token||a.token||s.token;if(!e)return k("Missing token (provide via init config, window.CopilotChatConfig.token, or data-token attribute)."),null;const n=t.baseUrl||o.baseUrl||a.baseUrl||s.baseUrl||v;try{const r=await fetch(`${n}/api/chat-widget/config?token=${encodeURIComponent(e)}`,{credentials:"omit",mode:"cors"});if(!r.ok)throw new Error(`Server responded with ${r.status}`);const l=await r.json();if(!l?.iframeUrl||!l?.launcherIcon)throw new Error("Received incomplete widget configuration from server.");return window.CopilotChat=window.CopilotChat||{},window.CopilotChat.init=(d={})=>{const c={iframeUrl:d.iframeUrl||l.iframeUrl,launcherIcon:d.launcherIcon||l.launcherIcon};return U(c)},window.CopilotChat.init(t)}catch(r){return k(r instanceof Error?r.message:"Unknown error during widget bootstrap."),null}};I()&&S(()=>{E()}),window.CopilotChat=window.CopilotChat||{},window.CopilotChat.load=E})()})();
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var n=typeof document<"u"?document.currentScript:null;const r="http://localhost:3005";function l(d={}){if(typeof window>"u"||typeof document>"u")return null;const{token:a,autoload:i,baseUrl:t=r}=d;window.CopilotChatConfig={...window.CopilotChatConfig,...d,baseUrl:t||window.CopilotChatConfig?.baseUrl||void 0};const o=document.getElementById("copilot-chat-widget-loader");if(o)return a&&(o.dataset.token=a),t&&(o.dataset.baseUrl=t),i===!1&&(o.dataset.autoload="false"),o;const e=document.createElement("script");return e.id="copilot-chat-widget-loader",e.src=new URL("./chat-widget.min.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:n&&n.tagName.toUpperCase()==="SCRIPT"&&n.src||new URL("index.cjs",document.baseURI).href).href,e.async=!0,a&&(e.dataset.token=a),t&&(e.dataset.baseUrl=t),i===!1&&(e.dataset.autoload="false"),document.body.appendChild(e),e}exports.default=l;exports.loadCopilotChatWidget=l;
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
const n = "http://localhost:3005";
|
|
2
|
+
function l(i = {}) {
|
|
2
3
|
if (typeof window > "u" || typeof document > "u")
|
|
3
4
|
return null;
|
|
4
|
-
const { token: a, autoload: d, baseUrl: e =
|
|
5
|
+
const { token: a, autoload: d, baseUrl: e = n } = i;
|
|
5
6
|
window.CopilotChatConfig = {
|
|
6
7
|
...window.CopilotChatConfig,
|
|
7
8
|
...i,
|
|
@@ -14,6 +15,6 @@ function n(i = {}) {
|
|
|
14
15
|
return t.id = "copilot-chat-widget-loader", t.src = new URL("./chat-widget.min.js", import.meta.url).href, t.async = !0, a && (t.dataset.token = a), e && (t.dataset.baseUrl = e), d === !1 && (t.dataset.autoload = "false"), document.body.appendChild(t), t;
|
|
15
16
|
}
|
|
16
17
|
export {
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
l as default,
|
|
19
|
+
l as loadCopilotChatWidget
|
|
19
20
|
};
|