@nextxai/sdk 0.1.2 → 0.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/CHANGELOG.md +6 -0
- package/dist/cjs/phone.d.ts +84 -0
- package/dist/cjs/phone.js +127 -0
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/phone.d.ts +84 -0
- package/dist/esm/phone.js +123 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +11 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
Theo [Semantic Versioning](https://semver.org/lang/vi/). Chính sách phiên bản: [VERSIONING.md](VERSIONING.md).
|
|
4
4
|
|
|
5
|
+
## 0.2.0 (2026-10-30)
|
|
6
|
+
|
|
7
|
+
### Thêm mới
|
|
8
|
+
|
|
9
|
+
- `@nextxai/sdk/phone` (chỉ Node): `NextXPhone` — nhúng softphone NextX vào phần mềm của bạn trên trình duyệt (`init`, `call`, `hangup`, `logout`, `destroy`, sự kiện `ready` · `auth-required` · `status` · `incoming` · `answered` · `ended` · `error`). Cùng mã với bản `<script src="https://developers.nextx.vn/phone/v1/phone.js">`.
|
|
10
|
+
|
|
5
11
|
## 0.1.2 (2026-10-30)
|
|
6
12
|
|
|
7
13
|
### Thêm mới
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NextX Phone — nhúng softphone NextX vào phần mềm của bạn (chạy trên trình duyệt).
|
|
3
|
+
*
|
|
4
|
+
* import { NextXPhone } from "@nextxai/sdk/phone";
|
|
5
|
+
* const phone = NextXPhone.init({ clientId: "app_…" });
|
|
6
|
+
* phone.on("incoming", (c) => openCustomer(c.from));
|
|
7
|
+
* phone.call("0901234567");
|
|
8
|
+
*
|
|
9
|
+
* Hoặc thẻ script: <script src="https://developers.nextx.vn/phone/v1/phone.js"></script> ⇒ `window.NextXPhone`.
|
|
10
|
+
*
|
|
11
|
+
* Softphone chạy trong iframe do NextX phục vụ; tổng đài viên đăng nhập NextX trong cửa sổ bật lên. Trang của bạn chỉ
|
|
12
|
+
* nhận sự kiện cuộc gọi — không bao giờ nhận token hay thông tin máy lẻ. Tên miền trang của bạn phải được khai trong
|
|
13
|
+
* developers.nextx.vn › Ứng dụng của tôi › Cài đặt › Softphone nhúng.
|
|
14
|
+
*/
|
|
15
|
+
export declare const PHONE_PROTOCOL = "nxphone/1";
|
|
16
|
+
export interface NextXPhoneOptions {
|
|
17
|
+
/** client_id của ứng dụng của bạn trên developers.nextx.vn. */
|
|
18
|
+
clientId: string;
|
|
19
|
+
/** Ngôn ngữ giao diện. Mặc định "vi". */
|
|
20
|
+
lang?: "vi" | "en";
|
|
21
|
+
/** Workspace NextX muốn đăng nhập (bỏ trống = workspace mặc định của tổng đài viên). */
|
|
22
|
+
workspaceId?: string;
|
|
23
|
+
/** Góc màn hình. Mặc định "bottom-right". */
|
|
24
|
+
position?: "bottom-right" | "bottom-left";
|
|
25
|
+
/** Khoảng cách tới mép (px). Mặc định 0. */
|
|
26
|
+
offset?: number;
|
|
27
|
+
/** Bắt số trong các phần tử có `data-nextx-call="<số>"` (bấm là gọi). Mặc định true. */
|
|
28
|
+
clickToDial?: boolean;
|
|
29
|
+
/** Ghi đè địa chỉ ứng dụng (vd sandbox: "https://app-dev.nextx.vn"). */
|
|
30
|
+
appUrl?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface PhoneCallEvent {
|
|
33
|
+
callId: string;
|
|
34
|
+
from?: string;
|
|
35
|
+
to?: string;
|
|
36
|
+
direction?: string;
|
|
37
|
+
status?: string;
|
|
38
|
+
talkSec?: number;
|
|
39
|
+
}
|
|
40
|
+
export interface PhoneEvents {
|
|
41
|
+
ready: {
|
|
42
|
+
loggedIn: boolean;
|
|
43
|
+
};
|
|
44
|
+
"auth-required": Record<string, never>;
|
|
45
|
+
status: {
|
|
46
|
+
registered: boolean;
|
|
47
|
+
extension?: string | null;
|
|
48
|
+
};
|
|
49
|
+
incoming: PhoneCallEvent;
|
|
50
|
+
answered: PhoneCallEvent;
|
|
51
|
+
ended: PhoneCallEvent;
|
|
52
|
+
error: {
|
|
53
|
+
code: string;
|
|
54
|
+
message?: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
type Handler<K extends keyof PhoneEvents> = (payload: PhoneEvents[K]) => void;
|
|
58
|
+
export declare class NextXPhone {
|
|
59
|
+
private readonly options;
|
|
60
|
+
private readonly iframe;
|
|
61
|
+
private readonly origin;
|
|
62
|
+
private readonly handlers;
|
|
63
|
+
private readonly queue;
|
|
64
|
+
private ready;
|
|
65
|
+
private readonly onMessage;
|
|
66
|
+
private readonly onClick;
|
|
67
|
+
private constructor();
|
|
68
|
+
/** Tạo và gắn NextX Phone vào trang. */
|
|
69
|
+
static init(options: NextXPhoneOptions): NextXPhone;
|
|
70
|
+
/** Nghe sự kiện. Trả hàm huỷ đăng ký. */
|
|
71
|
+
on<K extends keyof PhoneEvents>(event: K, handler: Handler<K>): () => void;
|
|
72
|
+
/** Gọi ra từ máy lẻ của tổng đài viên đang đăng nhập. */
|
|
73
|
+
call(number: string, opts?: {
|
|
74
|
+
contactRef?: string;
|
|
75
|
+
}): void;
|
|
76
|
+
/** Gác cuộc gọi đang diễn ra. */
|
|
77
|
+
hangup(): void;
|
|
78
|
+
/** Đăng xuất NextX trong khung softphone. */
|
|
79
|
+
logout(): void;
|
|
80
|
+
/** Gỡ softphone khỏi trang. */
|
|
81
|
+
destroy(): void;
|
|
82
|
+
private send;
|
|
83
|
+
}
|
|
84
|
+
export default NextXPhone;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/// <reference lib="dom" />
|
|
3
|
+
/**
|
|
4
|
+
* NextX Phone — nhúng softphone NextX vào phần mềm của bạn (chạy trên trình duyệt).
|
|
5
|
+
*
|
|
6
|
+
* import { NextXPhone } from "@nextxai/sdk/phone";
|
|
7
|
+
* const phone = NextXPhone.init({ clientId: "app_…" });
|
|
8
|
+
* phone.on("incoming", (c) => openCustomer(c.from));
|
|
9
|
+
* phone.call("0901234567");
|
|
10
|
+
*
|
|
11
|
+
* Hoặc thẻ script: <script src="https://developers.nextx.vn/phone/v1/phone.js"></script> ⇒ `window.NextXPhone`.
|
|
12
|
+
*
|
|
13
|
+
* Softphone chạy trong iframe do NextX phục vụ; tổng đài viên đăng nhập NextX trong cửa sổ bật lên. Trang của bạn chỉ
|
|
14
|
+
* nhận sự kiện cuộc gọi — không bao giờ nhận token hay thông tin máy lẻ. Tên miền trang của bạn phải được khai trong
|
|
15
|
+
* developers.nextx.vn › Ứng dụng của tôi › Cài đặt › Softphone nhúng.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.NextXPhone = exports.PHONE_PROTOCOL = void 0;
|
|
19
|
+
exports.PHONE_PROTOCOL = "nxphone/1";
|
|
20
|
+
const DEFAULT_APP_URL = "https://app.nextx.vn";
|
|
21
|
+
const INITIAL = { width: 96, height: 96 };
|
|
22
|
+
class NextXPhone {
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.options = options;
|
|
25
|
+
this.handlers = new Map();
|
|
26
|
+
this.queue = [];
|
|
27
|
+
this.ready = false;
|
|
28
|
+
if (!options?.clientId)
|
|
29
|
+
throw new Error("NextXPhone: thiếu clientId");
|
|
30
|
+
const appUrl = (options.appUrl ?? DEFAULT_APP_URL).replace(/\/+$/, "");
|
|
31
|
+
this.origin = new URL(appUrl).origin;
|
|
32
|
+
const q = new URLSearchParams({ client_id: options.clientId });
|
|
33
|
+
if (options.workspaceId)
|
|
34
|
+
q.set("workspace_id", options.workspaceId);
|
|
35
|
+
const f = document.createElement("iframe");
|
|
36
|
+
f.src = `${appUrl}/${options.lang ?? "vi"}/phone/embed?${q}`;
|
|
37
|
+
f.title = "NextX Phone";
|
|
38
|
+
f.allow = "microphone; autoplay";
|
|
39
|
+
f.setAttribute("allowtransparency", "true");
|
|
40
|
+
const side = options.position === "bottom-left" ? "left" : "right";
|
|
41
|
+
const off = `${options.offset ?? 0}px`;
|
|
42
|
+
Object.assign(f.style, {
|
|
43
|
+
position: "fixed",
|
|
44
|
+
bottom: off,
|
|
45
|
+
[side]: off,
|
|
46
|
+
width: `${INITIAL.width}px`,
|
|
47
|
+
height: `${INITIAL.height}px`,
|
|
48
|
+
border: "0",
|
|
49
|
+
background: "transparent",
|
|
50
|
+
colorScheme: "normal",
|
|
51
|
+
zIndex: "2147483000",
|
|
52
|
+
});
|
|
53
|
+
this.iframe = f;
|
|
54
|
+
this.onMessage = (e) => {
|
|
55
|
+
if (e.origin !== this.origin || e.source !== f.contentWindow)
|
|
56
|
+
return;
|
|
57
|
+
const msg = e.data;
|
|
58
|
+
if (!msg || msg.protocol !== exports.PHONE_PROTOCOL || !msg.event)
|
|
59
|
+
return;
|
|
60
|
+
const { type, ...payload } = msg.event;
|
|
61
|
+
if (type === "resize") {
|
|
62
|
+
const w = Math.max(64, Math.min(Number(payload.width) || INITIAL.width, window.innerWidth));
|
|
63
|
+
const h = Math.max(64, Math.min(Number(payload.height) || INITIAL.height, window.innerHeight));
|
|
64
|
+
f.style.width = `${w}px`;
|
|
65
|
+
f.style.height = `${h}px`;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (type === "ready" && !this.ready) {
|
|
69
|
+
this.ready = true;
|
|
70
|
+
for (const c of this.queue.splice(0))
|
|
71
|
+
this.send(c);
|
|
72
|
+
}
|
|
73
|
+
this.handlers.get(type)?.forEach((h) => h(payload));
|
|
74
|
+
};
|
|
75
|
+
this.onClick = (e) => {
|
|
76
|
+
const el = e.target?.closest?.("[data-nextx-call]");
|
|
77
|
+
const number = el?.getAttribute("data-nextx-call");
|
|
78
|
+
if (!number)
|
|
79
|
+
return;
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
this.call(number, { contactRef: el?.getAttribute("data-nextx-contact-ref") ?? undefined });
|
|
82
|
+
};
|
|
83
|
+
window.addEventListener("message", this.onMessage);
|
|
84
|
+
if (options.clickToDial !== false)
|
|
85
|
+
document.addEventListener("click", this.onClick);
|
|
86
|
+
(document.body ?? document.documentElement).appendChild(f);
|
|
87
|
+
}
|
|
88
|
+
/** Tạo và gắn NextX Phone vào trang. */
|
|
89
|
+
static init(options) {
|
|
90
|
+
return new NextXPhone(options);
|
|
91
|
+
}
|
|
92
|
+
/** Nghe sự kiện. Trả hàm huỷ đăng ký. */
|
|
93
|
+
on(event, handler) {
|
|
94
|
+
const set = this.handlers.get(event) ?? new Set();
|
|
95
|
+
set.add(handler);
|
|
96
|
+
this.handlers.set(event, set);
|
|
97
|
+
return () => set.delete(handler);
|
|
98
|
+
}
|
|
99
|
+
/** Gọi ra từ máy lẻ của tổng đài viên đang đăng nhập. */
|
|
100
|
+
call(number, opts = {}) {
|
|
101
|
+
this.send({ type: "call", number: String(number), contactRef: opts.contactRef });
|
|
102
|
+
}
|
|
103
|
+
/** Gác cuộc gọi đang diễn ra. */
|
|
104
|
+
hangup() {
|
|
105
|
+
this.send({ type: "hangup" });
|
|
106
|
+
}
|
|
107
|
+
/** Đăng xuất NextX trong khung softphone. */
|
|
108
|
+
logout() {
|
|
109
|
+
this.send({ type: "logout" });
|
|
110
|
+
}
|
|
111
|
+
/** Gỡ softphone khỏi trang. */
|
|
112
|
+
destroy() {
|
|
113
|
+
window.removeEventListener("message", this.onMessage);
|
|
114
|
+
document.removeEventListener("click", this.onClick);
|
|
115
|
+
this.iframe.remove();
|
|
116
|
+
this.handlers.clear();
|
|
117
|
+
}
|
|
118
|
+
send(command) {
|
|
119
|
+
if (!this.ready || !this.iframe.contentWindow) {
|
|
120
|
+
this.queue.push(command);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
this.iframe.contentWindow.postMessage({ protocol: exports.PHONE_PROTOCOL, command }, this.origin);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
exports.NextXPhone = NextXPhone;
|
|
127
|
+
exports.default = NextXPhone;
|
package/dist/cjs/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.2.0";
|
package/dist/cjs/version.js
CHANGED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NextX Phone — nhúng softphone NextX vào phần mềm của bạn (chạy trên trình duyệt).
|
|
3
|
+
*
|
|
4
|
+
* import { NextXPhone } from "@nextxai/sdk/phone";
|
|
5
|
+
* const phone = NextXPhone.init({ clientId: "app_…" });
|
|
6
|
+
* phone.on("incoming", (c) => openCustomer(c.from));
|
|
7
|
+
* phone.call("0901234567");
|
|
8
|
+
*
|
|
9
|
+
* Hoặc thẻ script: <script src="https://developers.nextx.vn/phone/v1/phone.js"></script> ⇒ `window.NextXPhone`.
|
|
10
|
+
*
|
|
11
|
+
* Softphone chạy trong iframe do NextX phục vụ; tổng đài viên đăng nhập NextX trong cửa sổ bật lên. Trang của bạn chỉ
|
|
12
|
+
* nhận sự kiện cuộc gọi — không bao giờ nhận token hay thông tin máy lẻ. Tên miền trang của bạn phải được khai trong
|
|
13
|
+
* developers.nextx.vn › Ứng dụng của tôi › Cài đặt › Softphone nhúng.
|
|
14
|
+
*/
|
|
15
|
+
export declare const PHONE_PROTOCOL = "nxphone/1";
|
|
16
|
+
export interface NextXPhoneOptions {
|
|
17
|
+
/** client_id của ứng dụng của bạn trên developers.nextx.vn. */
|
|
18
|
+
clientId: string;
|
|
19
|
+
/** Ngôn ngữ giao diện. Mặc định "vi". */
|
|
20
|
+
lang?: "vi" | "en";
|
|
21
|
+
/** Workspace NextX muốn đăng nhập (bỏ trống = workspace mặc định của tổng đài viên). */
|
|
22
|
+
workspaceId?: string;
|
|
23
|
+
/** Góc màn hình. Mặc định "bottom-right". */
|
|
24
|
+
position?: "bottom-right" | "bottom-left";
|
|
25
|
+
/** Khoảng cách tới mép (px). Mặc định 0. */
|
|
26
|
+
offset?: number;
|
|
27
|
+
/** Bắt số trong các phần tử có `data-nextx-call="<số>"` (bấm là gọi). Mặc định true. */
|
|
28
|
+
clickToDial?: boolean;
|
|
29
|
+
/** Ghi đè địa chỉ ứng dụng (vd sandbox: "https://app-dev.nextx.vn"). */
|
|
30
|
+
appUrl?: string;
|
|
31
|
+
}
|
|
32
|
+
export interface PhoneCallEvent {
|
|
33
|
+
callId: string;
|
|
34
|
+
from?: string;
|
|
35
|
+
to?: string;
|
|
36
|
+
direction?: string;
|
|
37
|
+
status?: string;
|
|
38
|
+
talkSec?: number;
|
|
39
|
+
}
|
|
40
|
+
export interface PhoneEvents {
|
|
41
|
+
ready: {
|
|
42
|
+
loggedIn: boolean;
|
|
43
|
+
};
|
|
44
|
+
"auth-required": Record<string, never>;
|
|
45
|
+
status: {
|
|
46
|
+
registered: boolean;
|
|
47
|
+
extension?: string | null;
|
|
48
|
+
};
|
|
49
|
+
incoming: PhoneCallEvent;
|
|
50
|
+
answered: PhoneCallEvent;
|
|
51
|
+
ended: PhoneCallEvent;
|
|
52
|
+
error: {
|
|
53
|
+
code: string;
|
|
54
|
+
message?: string;
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
type Handler<K extends keyof PhoneEvents> = (payload: PhoneEvents[K]) => void;
|
|
58
|
+
export declare class NextXPhone {
|
|
59
|
+
private readonly options;
|
|
60
|
+
private readonly iframe;
|
|
61
|
+
private readonly origin;
|
|
62
|
+
private readonly handlers;
|
|
63
|
+
private readonly queue;
|
|
64
|
+
private ready;
|
|
65
|
+
private readonly onMessage;
|
|
66
|
+
private readonly onClick;
|
|
67
|
+
private constructor();
|
|
68
|
+
/** Tạo và gắn NextX Phone vào trang. */
|
|
69
|
+
static init(options: NextXPhoneOptions): NextXPhone;
|
|
70
|
+
/** Nghe sự kiện. Trả hàm huỷ đăng ký. */
|
|
71
|
+
on<K extends keyof PhoneEvents>(event: K, handler: Handler<K>): () => void;
|
|
72
|
+
/** Gọi ra từ máy lẻ của tổng đài viên đang đăng nhập. */
|
|
73
|
+
call(number: string, opts?: {
|
|
74
|
+
contactRef?: string;
|
|
75
|
+
}): void;
|
|
76
|
+
/** Gác cuộc gọi đang diễn ra. */
|
|
77
|
+
hangup(): void;
|
|
78
|
+
/** Đăng xuất NextX trong khung softphone. */
|
|
79
|
+
logout(): void;
|
|
80
|
+
/** Gỡ softphone khỏi trang. */
|
|
81
|
+
destroy(): void;
|
|
82
|
+
private send;
|
|
83
|
+
}
|
|
84
|
+
export default NextXPhone;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
/**
|
|
3
|
+
* NextX Phone — nhúng softphone NextX vào phần mềm của bạn (chạy trên trình duyệt).
|
|
4
|
+
*
|
|
5
|
+
* import { NextXPhone } from "@nextxai/sdk/phone";
|
|
6
|
+
* const phone = NextXPhone.init({ clientId: "app_…" });
|
|
7
|
+
* phone.on("incoming", (c) => openCustomer(c.from));
|
|
8
|
+
* phone.call("0901234567");
|
|
9
|
+
*
|
|
10
|
+
* Hoặc thẻ script: <script src="https://developers.nextx.vn/phone/v1/phone.js"></script> ⇒ `window.NextXPhone`.
|
|
11
|
+
*
|
|
12
|
+
* Softphone chạy trong iframe do NextX phục vụ; tổng đài viên đăng nhập NextX trong cửa sổ bật lên. Trang của bạn chỉ
|
|
13
|
+
* nhận sự kiện cuộc gọi — không bao giờ nhận token hay thông tin máy lẻ. Tên miền trang của bạn phải được khai trong
|
|
14
|
+
* developers.nextx.vn › Ứng dụng của tôi › Cài đặt › Softphone nhúng.
|
|
15
|
+
*/
|
|
16
|
+
export const PHONE_PROTOCOL = "nxphone/1";
|
|
17
|
+
const DEFAULT_APP_URL = "https://app.nextx.vn";
|
|
18
|
+
const INITIAL = { width: 96, height: 96 };
|
|
19
|
+
export class NextXPhone {
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.options = options;
|
|
22
|
+
this.handlers = new Map();
|
|
23
|
+
this.queue = [];
|
|
24
|
+
this.ready = false;
|
|
25
|
+
if (!options?.clientId)
|
|
26
|
+
throw new Error("NextXPhone: thiếu clientId");
|
|
27
|
+
const appUrl = (options.appUrl ?? DEFAULT_APP_URL).replace(/\/+$/, "");
|
|
28
|
+
this.origin = new URL(appUrl).origin;
|
|
29
|
+
const q = new URLSearchParams({ client_id: options.clientId });
|
|
30
|
+
if (options.workspaceId)
|
|
31
|
+
q.set("workspace_id", options.workspaceId);
|
|
32
|
+
const f = document.createElement("iframe");
|
|
33
|
+
f.src = `${appUrl}/${options.lang ?? "vi"}/phone/embed?${q}`;
|
|
34
|
+
f.title = "NextX Phone";
|
|
35
|
+
f.allow = "microphone; autoplay";
|
|
36
|
+
f.setAttribute("allowtransparency", "true");
|
|
37
|
+
const side = options.position === "bottom-left" ? "left" : "right";
|
|
38
|
+
const off = `${options.offset ?? 0}px`;
|
|
39
|
+
Object.assign(f.style, {
|
|
40
|
+
position: "fixed",
|
|
41
|
+
bottom: off,
|
|
42
|
+
[side]: off,
|
|
43
|
+
width: `${INITIAL.width}px`,
|
|
44
|
+
height: `${INITIAL.height}px`,
|
|
45
|
+
border: "0",
|
|
46
|
+
background: "transparent",
|
|
47
|
+
colorScheme: "normal",
|
|
48
|
+
zIndex: "2147483000",
|
|
49
|
+
});
|
|
50
|
+
this.iframe = f;
|
|
51
|
+
this.onMessage = (e) => {
|
|
52
|
+
if (e.origin !== this.origin || e.source !== f.contentWindow)
|
|
53
|
+
return;
|
|
54
|
+
const msg = e.data;
|
|
55
|
+
if (!msg || msg.protocol !== PHONE_PROTOCOL || !msg.event)
|
|
56
|
+
return;
|
|
57
|
+
const { type, ...payload } = msg.event;
|
|
58
|
+
if (type === "resize") {
|
|
59
|
+
const w = Math.max(64, Math.min(Number(payload.width) || INITIAL.width, window.innerWidth));
|
|
60
|
+
const h = Math.max(64, Math.min(Number(payload.height) || INITIAL.height, window.innerHeight));
|
|
61
|
+
f.style.width = `${w}px`;
|
|
62
|
+
f.style.height = `${h}px`;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (type === "ready" && !this.ready) {
|
|
66
|
+
this.ready = true;
|
|
67
|
+
for (const c of this.queue.splice(0))
|
|
68
|
+
this.send(c);
|
|
69
|
+
}
|
|
70
|
+
this.handlers.get(type)?.forEach((h) => h(payload));
|
|
71
|
+
};
|
|
72
|
+
this.onClick = (e) => {
|
|
73
|
+
const el = e.target?.closest?.("[data-nextx-call]");
|
|
74
|
+
const number = el?.getAttribute("data-nextx-call");
|
|
75
|
+
if (!number)
|
|
76
|
+
return;
|
|
77
|
+
e.preventDefault();
|
|
78
|
+
this.call(number, { contactRef: el?.getAttribute("data-nextx-contact-ref") ?? undefined });
|
|
79
|
+
};
|
|
80
|
+
window.addEventListener("message", this.onMessage);
|
|
81
|
+
if (options.clickToDial !== false)
|
|
82
|
+
document.addEventListener("click", this.onClick);
|
|
83
|
+
(document.body ?? document.documentElement).appendChild(f);
|
|
84
|
+
}
|
|
85
|
+
/** Tạo và gắn NextX Phone vào trang. */
|
|
86
|
+
static init(options) {
|
|
87
|
+
return new NextXPhone(options);
|
|
88
|
+
}
|
|
89
|
+
/** Nghe sự kiện. Trả hàm huỷ đăng ký. */
|
|
90
|
+
on(event, handler) {
|
|
91
|
+
const set = this.handlers.get(event) ?? new Set();
|
|
92
|
+
set.add(handler);
|
|
93
|
+
this.handlers.set(event, set);
|
|
94
|
+
return () => set.delete(handler);
|
|
95
|
+
}
|
|
96
|
+
/** Gọi ra từ máy lẻ của tổng đài viên đang đăng nhập. */
|
|
97
|
+
call(number, opts = {}) {
|
|
98
|
+
this.send({ type: "call", number: String(number), contactRef: opts.contactRef });
|
|
99
|
+
}
|
|
100
|
+
/** Gác cuộc gọi đang diễn ra. */
|
|
101
|
+
hangup() {
|
|
102
|
+
this.send({ type: "hangup" });
|
|
103
|
+
}
|
|
104
|
+
/** Đăng xuất NextX trong khung softphone. */
|
|
105
|
+
logout() {
|
|
106
|
+
this.send({ type: "logout" });
|
|
107
|
+
}
|
|
108
|
+
/** Gỡ softphone khỏi trang. */
|
|
109
|
+
destroy() {
|
|
110
|
+
window.removeEventListener("message", this.onMessage);
|
|
111
|
+
document.removeEventListener("click", this.onClick);
|
|
112
|
+
this.iframe.remove();
|
|
113
|
+
this.handlers.clear();
|
|
114
|
+
}
|
|
115
|
+
send(command) {
|
|
116
|
+
if (!this.ready || !this.iframe.contentWindow) {
|
|
117
|
+
this.queue.push(command);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
this.iframe.contentWindow.postMessage({ protocol: PHONE_PROTOCOL, command }, this.origin);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export default NextXPhone;
|
package/dist/esm/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.2.0";
|
package/dist/esm/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "0.
|
|
1
|
+
export const VERSION = "0.2.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextxai/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Official Node.js and TypeScript client for the NextX API",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nextx",
|
|
@@ -35,6 +35,16 @@
|
|
|
35
35
|
"default": "./dist/cjs/index.js"
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
|
+
"./phone": {
|
|
39
|
+
"import": {
|
|
40
|
+
"types": "./dist/esm/phone.d.ts",
|
|
41
|
+
"default": "./dist/esm/phone.js"
|
|
42
|
+
},
|
|
43
|
+
"require": {
|
|
44
|
+
"types": "./dist/cjs/phone.d.ts",
|
|
45
|
+
"default": "./dist/cjs/phone.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
38
48
|
"./package.json": "./package.json"
|
|
39
49
|
},
|
|
40
50
|
"files": [
|