@skipphq/desk-web 0.3.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/LICENSE +21 -0
- package/README.md +152 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +254 -0
- package/dist/types.d.ts +52 -0
- package/dist/types.js +2 -0
- package/package.json +44 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Skipp
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS IN CONTRACT OFFICERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# @skipphq/desk-web
|
|
2
|
+
|
|
3
|
+
Official JavaScript / TypeScript Web SDK for the **Skipp Desk** customer support chat widget.
|
|
4
|
+
|
|
5
|
+
Easily integrate live chat, support tickets, and identity verification into React, Vue, Next.js, or plain HTML websites.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 📦 Installation
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @skipphq/desk-web
|
|
13
|
+
# or
|
|
14
|
+
yarn add @skipphq/desk-web
|
|
15
|
+
# or
|
|
16
|
+
pnpm add @skipphq/desk-web
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 🚀 Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. React / Next.js / Single Page Apps
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { SkippDesk } from '@skipphq/desk-web';
|
|
27
|
+
import { useEffect } from 'react';
|
|
28
|
+
|
|
29
|
+
export function SupportWidget() {
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
// Initialize Skipp Desk
|
|
32
|
+
SkippDesk.init({
|
|
33
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
34
|
+
// Optional pre-authenticated backend JWT identity token
|
|
35
|
+
identityToken: userJwtToken,
|
|
36
|
+
user: {
|
|
37
|
+
name: 'Timi Adesina',
|
|
38
|
+
email: 'adesinatim@gmail.com',
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Listen to events
|
|
43
|
+
const unsub = SkippDesk.on('unread-count-change', (count) => {
|
|
44
|
+
console.log('Unread messages:', count);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
return () => unsub();
|
|
48
|
+
}, []);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<button onClick={() => SkippDesk.open()}>
|
|
52
|
+
Need help? Chat with us
|
|
53
|
+
</button>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### 2. HTML Module Import
|
|
61
|
+
|
|
62
|
+
```html
|
|
63
|
+
<script type="module">
|
|
64
|
+
import { SkippDesk } from 'https://cdn.jsdelivr.net/npm/@skipphq/desk-web/+esm';
|
|
65
|
+
|
|
66
|
+
SkippDesk.init({
|
|
67
|
+
workspaceId: 'YOUR_WORKSPACE_ID',
|
|
68
|
+
user: { name: 'Alex' },
|
|
69
|
+
});
|
|
70
|
+
</script>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### 3. Standalone Script Tag (Alternative Embed)
|
|
76
|
+
|
|
77
|
+
If you prefer not to use an NPM package or ESM import, you can embed the widget directly using a single `<script>` tag:
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<!-- Embedded Widget Script -->
|
|
81
|
+
<script
|
|
82
|
+
src="https://cdn.skipp.cx/widget.js"
|
|
83
|
+
data-workspace-id="YOUR_WORKSPACE_ID"
|
|
84
|
+
data-position="right"
|
|
85
|
+
data-brand-color="#25282d">
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<!-- Optional: Control widget via global window.SkippDesk -->
|
|
89
|
+
<script>
|
|
90
|
+
window.addEventListener('DOMContentLoaded', () => {
|
|
91
|
+
// Open widget
|
|
92
|
+
window.SkippDesk.open();
|
|
93
|
+
|
|
94
|
+
// Set logged-in user JWT identity token
|
|
95
|
+
window.SkippDesk.setIdentityToken('USER_JWT_TOKEN');
|
|
96
|
+
});
|
|
97
|
+
</script>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Both methods support identical runtime controls (`open`, `close`, `toggle`, `setIdentityToken`, `logout`).
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 📖 API Reference
|
|
105
|
+
|
|
106
|
+
### `SkippDesk.init(config)`
|
|
107
|
+
Initialize the widget on the page.
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
SkippDesk.init({
|
|
111
|
+
workspaceId: string; // Required Workspace ID
|
|
112
|
+
identityToken?: string; // Optional backend-signed JWT token
|
|
113
|
+
apiBaseUrl?: string; // Custom API endpoint override
|
|
114
|
+
position?: 'left' | 'right'; // Position of launcher button
|
|
115
|
+
brandColor?: string; // Brand color override (#176b57)
|
|
116
|
+
welcomeMessage?: string; // Custom greeting message
|
|
117
|
+
user?: {
|
|
118
|
+
name?: string;
|
|
119
|
+
email?: string;
|
|
120
|
+
phone?: string;
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Methods
|
|
126
|
+
|
|
127
|
+
| Method | Description |
|
|
128
|
+
| :--- | :--- |
|
|
129
|
+
| `SkippDesk.open()` | Open the chat widget |
|
|
130
|
+
| `SkippDesk.close()` | Minimize the chat widget |
|
|
131
|
+
| `SkippDesk.toggle()` | Toggle open/closed state |
|
|
132
|
+
| `SkippDesk.show()` | Show launcher button if hidden |
|
|
133
|
+
| `SkippDesk.hide()` | Hide launcher button |
|
|
134
|
+
| `SkippDesk.setUser(user)` | Identify or update logged-in user details |
|
|
135
|
+
| `SkippDesk.setIdentityToken(token)` | Set/update JWT pre-auth token dynamically |
|
|
136
|
+
| `SkippDesk.logout()` | Clear session and log out customer |
|
|
137
|
+
| `SkippDesk.on(event, callback)` | Subscribe to events (`'ready'`, `'open'`, `'close'`, `'unread-count-change'`) |
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 🛡️ Pre-Authenticated Customer Identity
|
|
142
|
+
|
|
143
|
+
For seamless cross-device continuity without requiring users to fill out contact forms:
|
|
144
|
+
|
|
145
|
+
1. Generate a JWT identity token on your backend signed with your Workspace identity secret.
|
|
146
|
+
2. Pass `identityToken` during `init()` or call `SkippDesk.setIdentityToken(jwtToken)` upon user login.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## 📄 License
|
|
151
|
+
|
|
152
|
+
MIT © [Skipp](https://skipp.cx)
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { SkippDeskConfig, SkippDeskEvent, SkippDeskEventListener, SkippDeskPosition, SkippDeskUser } from "./types.js";
|
|
2
|
+
export type { SkippDeskConfig, SkippDeskEvent, SkippDeskEventListener, SkippDeskPosition, SkippDeskUser, };
|
|
3
|
+
declare class SkippDeskSDK {
|
|
4
|
+
private config;
|
|
5
|
+
private listeners;
|
|
6
|
+
private ready;
|
|
7
|
+
private messageHandlerAttached;
|
|
8
|
+
/**
|
|
9
|
+
* Initialize Skipp Desk on the page with workspace and identity settings.
|
|
10
|
+
*/
|
|
11
|
+
init(config: SkippDeskConfig): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Open the chat widget.
|
|
14
|
+
*/
|
|
15
|
+
open(): void;
|
|
16
|
+
/**
|
|
17
|
+
* Close/minimize the chat widget.
|
|
18
|
+
*/
|
|
19
|
+
close(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Toggle open/close state of the chat widget.
|
|
22
|
+
*/
|
|
23
|
+
toggle(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Show the launcher button if hidden.
|
|
26
|
+
*/
|
|
27
|
+
show(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Hide the launcher button.
|
|
30
|
+
*/
|
|
31
|
+
hide(): void;
|
|
32
|
+
/**
|
|
33
|
+
* Set or update backend-signed JWT identity token dynamically.
|
|
34
|
+
*/
|
|
35
|
+
setIdentityToken(token: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Identify or update logged-in customer info dynamically.
|
|
38
|
+
*/
|
|
39
|
+
setUser(user: SkippDeskUser): void;
|
|
40
|
+
/**
|
|
41
|
+
* Log out the current user and clear visitor session state.
|
|
42
|
+
*/
|
|
43
|
+
logout(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Reset visitor session and clear local widget state.
|
|
46
|
+
*/
|
|
47
|
+
reset(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Subscribe to widget lifecycle events.
|
|
50
|
+
*/
|
|
51
|
+
on(event: SkippDeskEvent, callback: SkippDeskEventListener): () => void;
|
|
52
|
+
/**
|
|
53
|
+
* Unsubscribe from widget lifecycle events.
|
|
54
|
+
*/
|
|
55
|
+
off(event: SkippDeskEvent, callback: SkippDeskEventListener): void;
|
|
56
|
+
/**
|
|
57
|
+
* Check whether Skipp Desk is initialized and ready.
|
|
58
|
+
*/
|
|
59
|
+
isReady(): boolean;
|
|
60
|
+
private emit;
|
|
61
|
+
private dispatchCommand;
|
|
62
|
+
private ensureMessageHandler;
|
|
63
|
+
private injectScript;
|
|
64
|
+
}
|
|
65
|
+
export declare const SkippDesk: SkippDeskSDK;
|
|
66
|
+
export default SkippDesk;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SkippDesk = void 0;
|
|
4
|
+
const DEFAULT_WIDGET_URL = "https://cdn.skipp.cx/widget.js";
|
|
5
|
+
const DEFAULT_API_BASE_URL = "https://api.zirrodesk.com";
|
|
6
|
+
const WIDGET_SCRIPT_ID = "skipp-desk-widget-script";
|
|
7
|
+
class SkippDeskSDK {
|
|
8
|
+
config = null;
|
|
9
|
+
listeners = new Map();
|
|
10
|
+
ready = false;
|
|
11
|
+
messageHandlerAttached = false;
|
|
12
|
+
/**
|
|
13
|
+
* Initialize Skipp Desk on the page with workspace and identity settings.
|
|
14
|
+
*/
|
|
15
|
+
async init(config) {
|
|
16
|
+
if (!config.workspaceId) {
|
|
17
|
+
throw new Error("SkippDesk.init requires a valid workspaceId.");
|
|
18
|
+
}
|
|
19
|
+
this.config = {
|
|
20
|
+
...config,
|
|
21
|
+
apiBaseUrl: (config.apiBaseUrl || DEFAULT_API_BASE_URL).replace(/\/$/, ""),
|
|
22
|
+
widgetUrl: config.widgetUrl || DEFAULT_WIDGET_URL,
|
|
23
|
+
};
|
|
24
|
+
// Store pre-authenticated identity token if provided
|
|
25
|
+
if (this.config.identityToken && typeof window !== "undefined") {
|
|
26
|
+
try {
|
|
27
|
+
window.localStorage.setItem(`skipp-widget-identity-token:${this.config.workspaceId}`, this.config.identityToken);
|
|
28
|
+
window.localStorage.setItem(`zirro-desk-widget-identity-token:${this.config.workspaceId}`, this.config.identityToken);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Ignore localStorage restrictions
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Attach window message listener for widget events
|
|
35
|
+
this.ensureMessageHandler();
|
|
36
|
+
// Inject widget script if not present
|
|
37
|
+
await this.injectScript();
|
|
38
|
+
// Notify listeners if widget is ready
|
|
39
|
+
if (this.ready) {
|
|
40
|
+
this.emit("ready", { workspaceId: this.config.workspaceId });
|
|
41
|
+
}
|
|
42
|
+
if (config.user) {
|
|
43
|
+
this.setUser(config.user);
|
|
44
|
+
}
|
|
45
|
+
if (config.autoOpen) {
|
|
46
|
+
this.open();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Open the chat widget.
|
|
51
|
+
*/
|
|
52
|
+
open() {
|
|
53
|
+
this.dispatchCommand("open");
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Close/minimize the chat widget.
|
|
57
|
+
*/
|
|
58
|
+
close() {
|
|
59
|
+
this.dispatchCommand("close");
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Toggle open/close state of the chat widget.
|
|
63
|
+
*/
|
|
64
|
+
toggle() {
|
|
65
|
+
this.dispatchCommand("toggle");
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Show the launcher button if hidden.
|
|
69
|
+
*/
|
|
70
|
+
show() {
|
|
71
|
+
this.dispatchCommand("show");
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Hide the launcher button.
|
|
75
|
+
*/
|
|
76
|
+
hide() {
|
|
77
|
+
this.dispatchCommand("hide");
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Set or update backend-signed JWT identity token dynamically.
|
|
81
|
+
*/
|
|
82
|
+
setIdentityToken(token) {
|
|
83
|
+
if (!this.config)
|
|
84
|
+
return;
|
|
85
|
+
try {
|
|
86
|
+
window.localStorage.setItem(`skipp-widget-identity-token:${this.config.workspaceId}`, token);
|
|
87
|
+
window.localStorage.setItem(`zirro-desk-widget-identity-token:${this.config.workspaceId}`, token);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
// Ignore
|
|
91
|
+
}
|
|
92
|
+
this.dispatchCommand("setIdentityToken", { token });
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Identify or update logged-in customer info dynamically.
|
|
96
|
+
*/
|
|
97
|
+
setUser(user) {
|
|
98
|
+
if (!this.config)
|
|
99
|
+
return;
|
|
100
|
+
this.dispatchCommand("setUser", user);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Log out the current user and clear visitor session state.
|
|
104
|
+
*/
|
|
105
|
+
async logout() {
|
|
106
|
+
await this.reset();
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Reset visitor session and clear local widget state.
|
|
110
|
+
*/
|
|
111
|
+
async reset() {
|
|
112
|
+
if (this.config && typeof window !== "undefined") {
|
|
113
|
+
try {
|
|
114
|
+
window.localStorage.removeItem(`skipp-widget-identity-token:${this.config.workspaceId}`);
|
|
115
|
+
window.localStorage.removeItem(`zirro-desk-widget-identity-token:${this.config.workspaceId}`);
|
|
116
|
+
window.localStorage.removeItem(`zirro-desk-widget-visitor-token:${this.config.workspaceId}`);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Ignore
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
this.dispatchCommand("logout");
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Subscribe to widget lifecycle events.
|
|
126
|
+
*/
|
|
127
|
+
on(event, callback) {
|
|
128
|
+
if (!this.listeners.has(event)) {
|
|
129
|
+
this.listeners.set(event, new Set());
|
|
130
|
+
}
|
|
131
|
+
this.listeners.get(event).add(callback);
|
|
132
|
+
return () => this.off(event, callback);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Unsubscribe from widget lifecycle events.
|
|
136
|
+
*/
|
|
137
|
+
off(event, callback) {
|
|
138
|
+
const callbacks = this.listeners.get(event);
|
|
139
|
+
if (callbacks) {
|
|
140
|
+
callbacks.delete(callback);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Check whether Skipp Desk is initialized and ready.
|
|
145
|
+
*/
|
|
146
|
+
isReady() {
|
|
147
|
+
return this.ready;
|
|
148
|
+
}
|
|
149
|
+
// Private helpers
|
|
150
|
+
emit(event, data) {
|
|
151
|
+
const callbacks = this.listeners.get(event);
|
|
152
|
+
if (callbacks) {
|
|
153
|
+
callbacks.forEach((cb) => {
|
|
154
|
+
try {
|
|
155
|
+
cb(data);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
console.error(`[SkippDesk] Error in '${event}' event listener:`, err);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
dispatchCommand(action, data = {}) {
|
|
164
|
+
if (typeof window === "undefined")
|
|
165
|
+
return;
|
|
166
|
+
// Call window.SkippDesk if exposed by widget.js
|
|
167
|
+
const globalSkipp = window.SkippDesk;
|
|
168
|
+
if (globalSkipp && typeof globalSkipp[action] === "function") {
|
|
169
|
+
globalSkipp[action](data);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
// Fallback: postMessage to iframe or window
|
|
173
|
+
const messagePayload = {
|
|
174
|
+
source: "skipp-desk-sdk",
|
|
175
|
+
action,
|
|
176
|
+
workspaceId: this.config?.workspaceId,
|
|
177
|
+
...data,
|
|
178
|
+
};
|
|
179
|
+
window.postMessage(messagePayload, "*");
|
|
180
|
+
}
|
|
181
|
+
ensureMessageHandler() {
|
|
182
|
+
if (this.messageHandlerAttached || typeof window === "undefined")
|
|
183
|
+
return;
|
|
184
|
+
window.addEventListener("message", (event) => {
|
|
185
|
+
if (!event.data)
|
|
186
|
+
return;
|
|
187
|
+
let payload = event.data;
|
|
188
|
+
if (typeof payload === "string") {
|
|
189
|
+
try {
|
|
190
|
+
payload = JSON.parse(payload);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (payload.source !== "skipp-desk" && payload.source !== "zirro-desk")
|
|
197
|
+
return;
|
|
198
|
+
switch (payload.type) {
|
|
199
|
+
case "ready":
|
|
200
|
+
this.ready = true;
|
|
201
|
+
this.emit("ready", payload);
|
|
202
|
+
break;
|
|
203
|
+
case "open":
|
|
204
|
+
this.emit("open");
|
|
205
|
+
break;
|
|
206
|
+
case "close":
|
|
207
|
+
this.emit("close");
|
|
208
|
+
break;
|
|
209
|
+
case "unread_count_change":
|
|
210
|
+
case "unread-count-change":
|
|
211
|
+
this.emit("unread-count-change", payload.unreadCount ?? payload.count ?? 0);
|
|
212
|
+
break;
|
|
213
|
+
case "ticket_created":
|
|
214
|
+
case "ticket-created":
|
|
215
|
+
this.emit("ticket-created", payload);
|
|
216
|
+
break;
|
|
217
|
+
case "error":
|
|
218
|
+
this.emit("error", new Error(payload.message || "Skipp Desk Widget Error"));
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
this.messageHandlerAttached = true;
|
|
223
|
+
}
|
|
224
|
+
injectScript() {
|
|
225
|
+
if (typeof document === "undefined" || !this.config)
|
|
226
|
+
return Promise.resolve();
|
|
227
|
+
if (document.getElementById(WIDGET_SCRIPT_ID)) {
|
|
228
|
+
return Promise.resolve();
|
|
229
|
+
}
|
|
230
|
+
return new Promise((resolve, reject) => {
|
|
231
|
+
const script = document.createElement("script");
|
|
232
|
+
script.id = WIDGET_SCRIPT_ID;
|
|
233
|
+
script.async = true;
|
|
234
|
+
script.src = this.config.widgetUrl || DEFAULT_WIDGET_URL;
|
|
235
|
+
script.dataset.workspaceId = this.config.workspaceId;
|
|
236
|
+
script.dataset.apiBaseUrl = this.config.apiBaseUrl;
|
|
237
|
+
if (this.config.position) {
|
|
238
|
+
script.dataset.position = this.config.position;
|
|
239
|
+
}
|
|
240
|
+
script.onload = () => {
|
|
241
|
+
this.ready = true;
|
|
242
|
+
resolve();
|
|
243
|
+
};
|
|
244
|
+
script.onerror = (err) => {
|
|
245
|
+
const error = new Error(`Failed to load Skipp Desk widget script from ${script.src}`);
|
|
246
|
+
this.emit("error", error);
|
|
247
|
+
reject(error);
|
|
248
|
+
};
|
|
249
|
+
document.head.appendChild(script);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
exports.SkippDesk = new SkippDeskSDK();
|
|
254
|
+
exports.default = exports.SkippDesk;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export type SkippDeskPosition = "left" | "right";
|
|
2
|
+
export type SkippDeskUser = {
|
|
3
|
+
id?: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
email?: string;
|
|
6
|
+
phone?: string;
|
|
7
|
+
};
|
|
8
|
+
export type SkippDeskConfig = {
|
|
9
|
+
/**
|
|
10
|
+
* Your Skipp Desk Workspace ID (Required)
|
|
11
|
+
*/
|
|
12
|
+
workspaceId: string;
|
|
13
|
+
/**
|
|
14
|
+
* Base URL for the Skipp Desk API (Defaults to production API if omitted)
|
|
15
|
+
*/
|
|
16
|
+
apiBaseUrl?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Hosted URL of the widget script (Defaults to https://cdn.skipp.cx/widget.js if omitted)
|
|
19
|
+
*/
|
|
20
|
+
widgetUrl?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Pre-authenticated JWT identity token issued by your backend
|
|
23
|
+
*/
|
|
24
|
+
identityToken?: string;
|
|
25
|
+
/**
|
|
26
|
+
* User identity information
|
|
27
|
+
*/
|
|
28
|
+
user?: SkippDeskUser;
|
|
29
|
+
/**
|
|
30
|
+
* Position of the chat widget button
|
|
31
|
+
*/
|
|
32
|
+
position?: SkippDeskPosition;
|
|
33
|
+
/**
|
|
34
|
+
* Primary brand color override (hex format)
|
|
35
|
+
*/
|
|
36
|
+
brandColor?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Custom welcome message override
|
|
39
|
+
*/
|
|
40
|
+
welcomeMessage?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Auto-open widget after initialization
|
|
43
|
+
*/
|
|
44
|
+
autoOpen?: boolean;
|
|
45
|
+
};
|
|
46
|
+
export type SkippDeskEvent = "ready" | "open" | "close" | "unread-count-change" | "ticket-created" | "error";
|
|
47
|
+
export type SkippDeskEventListener = (data?: Record<string, unknown> | number | string | Error) => void;
|
|
48
|
+
export type SkippDeskCommand = ["init", SkippDeskConfig] | ["open"] | ["close"] | ["toggle"] | ["show"] | ["hide"] | ["setIdentityToken", string] | ["setUser", SkippDeskUser] | ["logout"] | ["reset"] | ["on", SkippDeskEvent, SkippDeskEventListener] | ["off", SkippDeskEvent, SkippDeskEventListener];
|
|
49
|
+
export interface SkippDeskGlobalQueue {
|
|
50
|
+
q?: SkippDeskCommand[];
|
|
51
|
+
(...args: SkippDeskCommand): void;
|
|
52
|
+
}
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skipphq/desk-web",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Web SDK for Skipp Desk support widget",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"module": "dist/index.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc -p tsconfig.json",
|
|
22
|
+
"test": "npm run build && node --test tests/*.test.cjs",
|
|
23
|
+
"prepack": "npm run build",
|
|
24
|
+
"publish:check": "npm pack --dry-run"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://www.npmjs.com/package/@skipphq/desk-web",
|
|
27
|
+
"keywords": [
|
|
28
|
+
"skipp",
|
|
29
|
+
"skipp-desk",
|
|
30
|
+
"customer-support",
|
|
31
|
+
"help-desk",
|
|
32
|
+
"chat-widget",
|
|
33
|
+
"web-sdk",
|
|
34
|
+
"typescript"
|
|
35
|
+
],
|
|
36
|
+
"sideEffects": false,
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"typescript": "~5.9.3"
|
|
42
|
+
},
|
|
43
|
+
"license": "MIT"
|
|
44
|
+
}
|