@spilki/widget 0.1.1 → 0.1.2
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 +29 -25
- package/dist/bootstrap.es.js +60 -62
- package/dist/bootstrap.es.js.map +1 -1
- package/dist/bootstrap.umd.js +2 -2
- package/dist/bootstrap.umd.js.map +1 -1
- package/dist/core/state.d.ts +1 -2
- package/dist/core/state.d.ts.map +1 -1
- package/dist/core/transport.d.ts +0 -1
- package/dist/core/transport.d.ts.map +1 -1
- package/dist/core/utils.d.ts +4 -4
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +0 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/widget.es.js +64 -66
- package/dist/widget.es.js.map +1 -1
- package/dist/widget.umd.js +2 -2
- package/dist/widget.umd.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@spilki/widget)
|
|
4
4
|
[](#size-budget)
|
|
5
5
|
|
|
6
|
-
Embeddable chat widget that connects your website visitors with the Spilki assistant backend via a secure Web Widget
|
|
6
|
+
Embeddable chat widget that connects your website visitors with the Spilki assistant backend via a secure Web Widget
|
|
7
|
+
channel.
|
|
7
8
|
|
|
8
9
|
## Features
|
|
9
10
|
|
|
@@ -24,40 +25,38 @@ npm install @spilki/widget
|
|
|
24
25
|
### CDN (UMD)
|
|
25
26
|
|
|
26
27
|
```html
|
|
28
|
+
|
|
27
29
|
<script src="https://cdn.jsdelivr.net/npm/@spilki/widget/dist/widget.umd.js"
|
|
28
30
|
data-org="ori-bar"
|
|
29
|
-
data-assistant="main-bot"
|
|
30
31
|
data-token="<your-jwt>"></script>
|
|
31
32
|
```
|
|
32
33
|
|
|
33
34
|
### ESM
|
|
34
35
|
|
|
35
36
|
```ts
|
|
36
|
-
import {
|
|
37
|
+
import {initSpilkiWidget} from "@spilki/widget";
|
|
37
38
|
|
|
38
39
|
initSpilkiWidget({
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
token: "<your-jwt>"
|
|
40
|
+
org: "ori-bar",
|
|
41
|
+
token: "<your-jwt>"
|
|
42
42
|
});
|
|
43
43
|
```
|
|
44
44
|
|
|
45
45
|
## Options
|
|
46
46
|
|
|
47
|
-
| Option
|
|
48
|
-
|
|
49
|
-
| `org`
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `hooks` | `Partial<WidgetHooks>?` | – | Telemetry callbacks for open/close/message/error/transport change. |
|
|
47
|
+
| Option | Type | Default | Description |
|
|
48
|
+
|----------------------|-----------------------------------|---------------------------|-----------------------------------------------------------------------------------------|
|
|
49
|
+
| `org` | `string` | – | Spilki organisation identifier. |
|
|
50
|
+
| `token` | `string?` | – | Signed JWT obtained from the admin UI or backend. |
|
|
51
|
+
| `apiBase` | `string?` | `https://api.spilki.ai` | Override API endpoint (useful for staging/local). |
|
|
52
|
+
| `position` | `"bottom-right" \| "bottom-left"` | `"bottom-right"` | Corner to anchor the bubble + panel. |
|
|
53
|
+
| `theme` | `"auto" \| "light" \| "dark"` | `"auto"` | Force light/dark or respect OS preference. |
|
|
54
|
+
| `color` | `string?` | `#6366f1` | Accent color for bubble + primary CTA. |
|
|
55
|
+
| `welcome` | `string?` | "Hi! I'm your assistant." | Greeting shown when no conversation exists. |
|
|
56
|
+
| `persist` | `boolean?` | `true` | Persist session + history in localStorage. |
|
|
57
|
+
| `allowedOriginsHint` | `string[]?` | – | List of origins expected to be in JWT allowlist. Logs warnings during misconfiguration. |
|
|
58
|
+
| `i18n` | `Partial<WidgetI18n>?` | – | Override UI strings (welcome, placeholder, sendLabel, typing, offline, title). |
|
|
59
|
+
| `hooks` | `Partial<WidgetHooks>?` | – | Telemetry callbacks for open/close/message/error/transport change. |
|
|
61
60
|
|
|
62
61
|
## Security
|
|
63
62
|
|
|
@@ -66,13 +65,16 @@ The widget never stores credentials. Provide a short-lived JWT (HS256) issued se
|
|
|
66
65
|
```json
|
|
67
66
|
{
|
|
68
67
|
"organisation_id": "ori-bar",
|
|
69
|
-
"
|
|
70
|
-
|
|
68
|
+
"allowed_origins": [
|
|
69
|
+
"https://yourdomain.com"
|
|
70
|
+
],
|
|
71
71
|
"exp": 1760000000
|
|
72
72
|
}
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
During `POST /widget/
|
|
75
|
+
During `POST /widget/session` the widget sends `Origin` and the JWT for verification. Expired tokens are rejected
|
|
76
|
+
client-side before any network call. Rotate tokens frequently and limit the allowed origins array to trusted domains
|
|
77
|
+
only.
|
|
76
78
|
|
|
77
79
|
See [`apps/mock-server/openapi.yaml`](../apps/mock-server/openapi.yaml) for the full handshake specification.
|
|
78
80
|
|
|
@@ -92,8 +94,10 @@ pnpm install
|
|
|
92
94
|
pnpm -w dev # runs mock server + demo site
|
|
93
95
|
```
|
|
94
96
|
|
|
95
|
-
Open [http://localhost:5174](http://localhost:5174) and use **Issue token** to obtain a development JWT. Messages are
|
|
97
|
+
Open [http://localhost:5174](http://localhost:5174) and use **Issue token** to obtain a development JWT. Messages are
|
|
98
|
+
relayed via websocket by default; stop the websocket server to see SSE fallback.
|
|
96
99
|
|
|
97
100
|
## Publishing
|
|
98
101
|
|
|
99
|
-
The GitHub Actions workflow publishes on tags that match `v*`. Ensure `NPM_TOKEN` is configured in the repository
|
|
102
|
+
The GitHub Actions workflow publishes on tags that match `v*`. Ensure `NPM_TOKEN` is configured in the repository
|
|
103
|
+
secrets before tagging `v0.1.2` or later.
|
package/dist/bootstrap.es.js
CHANGED
|
@@ -58,16 +58,16 @@ function A(r) {
|
|
|
58
58
|
destroy() {
|
|
59
59
|
e.remove();
|
|
60
60
|
},
|
|
61
|
-
setOpen(
|
|
62
|
-
s.setAttribute("aria-expanded", String(
|
|
61
|
+
setOpen(n) {
|
|
62
|
+
s.setAttribute("aria-expanded", String(n));
|
|
63
63
|
}
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
-
const
|
|
67
|
-
class
|
|
66
|
+
const C = ':host{--spilki-bg-light: #ffffff;--spilki-bg-dark: #0f172a;--spilki-text-light: #0f172a;--spilki-text-dark: #f8fafc;--spilki-border-light: rgba(15, 23, 42, .1);--spilki-border-dark: rgba(148, 163, 184, .25);--spilki-shadow: 0 10px 40px rgba(15, 23, 42, .2);--spilki-radius: 16px;--spilki-font: "Inter", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;color:inherit;font-family:var(--spilki-font)}.wrapper{width:100%;height:100%;display:flex;flex-direction:column;background:var(--spilki-surface);color:var(--spilki-text);border-radius:var(--spilki-radius);box-shadow:var(--spilki-shadow);border:1px solid var(--spilki-border);overflow:hidden}header{display:flex;align-items:center;justify-content:space-between;padding:.75rem 1rem;background:var(--spilki-surface);border-bottom:1px solid var(--spilki-border)}header h1{font-size:1rem;margin:0;display:flex;align-items:center;gap:.5rem}header button.close{border:none;background:transparent;color:inherit;font-size:1.25rem;cursor:pointer}header .status-dot{width:10px;height:10px;border-radius:999px;background:var(--spilki-accent)}.messages{flex:1;overflow-y:auto;padding:1rem;display:flex;flex-direction:column;gap:.5rem}.message{display:flex;flex-direction:column;gap:.25rem;max-width:85%;line-height:1.4;word-wrap:break-word;overflow-wrap:anywhere;white-space:pre-wrap}.message.user{align-self:flex-end;text-align:right}.message .bubble{padding:.6rem .8rem;border-radius:1rem;background:#6366f126}.message.user .bubble{background:var(--spilki-accent);color:#fff}.message.bot .bubble{background:#94a3b826}.input-area{display:flex;align-items:flex-end;gap:.5rem;padding:.75rem 1rem;border-top:1px solid var(--spilki-border)}.input-area textarea{flex:1;resize:none;min-height:2.5rem;max-height:6rem;border-radius:.75rem;border:1px solid var(--spilki-border);padding:.6rem .75rem;font-family:inherit;font-size:.95rem;background:var(--spilki-surface);color:var(--spilki-text)}.input-area button{border:none;border-radius:999px;padding:.6rem 1.1rem;background:var(--spilki-accent);color:#fff;font-weight:600;cursor:pointer}.typing{font-size:.75rem;color:#94a3b8e6;padding:0 1rem .75rem}.offline{font-size:.8rem;padding:0 1rem;color:#f97316}:host([data-theme="dark"]){--spilki-surface: var(--spilki-bg-dark);--spilki-text: var(--spilki-text-dark);--spilki-border: var(--spilki-border-dark)}:host([data-theme="light"]){--spilki-surface: var(--spilki-bg-light);--spilki-text: var(--spilki-text-light);--spilki-border: var(--spilki-border-light)}:host([data-theme="dark"]) .message .bubble{background:#94a3b81f}:host([data-theme="dark"]) .message.bot .bubble{background:#6366f126}:host([data-theme="dark"]) .input-area textarea{background:#0f172ad9}.messages::-webkit-scrollbar,.input-area textarea::-webkit-scrollbar{width:6px}.messages::-webkit-scrollbar-track,.input-area textarea::-webkit-scrollbar-track{background:transparent}.messages::-webkit-scrollbar-thumb,.input-area textarea::-webkit-scrollbar-thumb{background:#94a3b84d;border-radius:999px}.messages::-webkit-scrollbar-thumb:hover,.input-area textarea::-webkit-scrollbar-thumb:hover{background:#94a3b880}:host([data-theme="dark"]) .messages::-webkit-scrollbar-thumb,:host([data-theme="dark"]) .input-area textarea::-webkit-scrollbar-thumb{background:#fff3}:host([data-theme="dark"]) .messages::-webkit-scrollbar-thumb:hover,:host([data-theme="dark"]) .input-area textarea::-webkit-scrollbar-thumb:hover{background:#ffffff59}.messages{scroll-behavior:smooth}';
|
|
67
|
+
class W {
|
|
68
68
|
constructor(e) {
|
|
69
69
|
this.options = e, this.focusable = [], this.open = !1, this.host = document.createElement("div"), this.host.setAttribute("part", "panel-root"), this.host.style.position = "fixed", this.host.style.bottom = "96px", this.host.style[e.position === "bottom-right" ? "right" : "left"] = "24px", this.host.style.width = "360px", this.host.style.maxWidth = "calc(100vw - 32px)", this.host.style.height = "520px", this.host.style.display = "none", this.host.style.zIndex = "2147483001", this.shadow = this.host.attachShadow({ mode: "open" }), this.shadow.innerHTML = `
|
|
70
|
-
<style>${
|
|
70
|
+
<style>${C}</style>
|
|
71
71
|
<div class="wrapper" role="dialog" aria-modal="true" aria-label="${e.i18n.title}">
|
|
72
72
|
<header>
|
|
73
73
|
<h1><span class="status-dot" aria-hidden="true"></span>${e.i18n.title}</h1>
|
|
@@ -149,7 +149,7 @@ class C {
|
|
|
149
149
|
e.shiftKey && i === t ? (e.preventDefault(), s.focus()) : !e.shiftKey && i === s && (e.preventDefault(), t.focus());
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
-
const
|
|
152
|
+
const $ = "https://api.spilki.ai", g = {
|
|
153
153
|
welcome: "Hi! I'm your assistant.",
|
|
154
154
|
placeholder: "Type a message…",
|
|
155
155
|
sendLabel: "Send",
|
|
@@ -157,7 +157,7 @@ const W = "https://api.spilki.ai", g = {
|
|
|
157
157
|
offline: "Unable to connect. Please try again later.",
|
|
158
158
|
title: "Spilki Assistant"
|
|
159
159
|
}, p = {
|
|
160
|
-
apiBase:
|
|
160
|
+
apiBase: $,
|
|
161
161
|
position: "bottom-right",
|
|
162
162
|
theme: "auto",
|
|
163
163
|
color: "#6366f1",
|
|
@@ -166,7 +166,7 @@ const W = "https://api.spilki.ai", g = {
|
|
|
166
166
|
i18n: g
|
|
167
167
|
};
|
|
168
168
|
function B(r) {
|
|
169
|
-
var t, s, i,
|
|
169
|
+
var t, s, i, n, l, a, h;
|
|
170
170
|
const e = { ...g, ...(t = r.i18n) != null ? t : {} };
|
|
171
171
|
return {
|
|
172
172
|
...p,
|
|
@@ -174,7 +174,7 @@ function B(r) {
|
|
|
174
174
|
apiBase: (s = r.apiBase) != null ? s : p.apiBase,
|
|
175
175
|
i18n: e,
|
|
176
176
|
welcome: (i = r.welcome) != null ? i : e.welcome,
|
|
177
|
-
position: (
|
|
177
|
+
position: (n = r.position) != null ? n : p.position,
|
|
178
178
|
theme: (l = r.theme) != null ? l : p.theme,
|
|
179
179
|
color: (a = r.color) != null ? a : p.color,
|
|
180
180
|
persist: (h = r.persist) != null ? h : p.persist
|
|
@@ -215,9 +215,8 @@ class U {
|
|
|
215
215
|
async connect() {
|
|
216
216
|
var l, a;
|
|
217
217
|
this.stopped = !1;
|
|
218
|
-
const e = `${this.options.apiBase.replace(/\/$/, "")}/widget/
|
|
218
|
+
const e = `${this.options.apiBase.replace(/\/$/, "")}/widget/session`, t = (a = (l = this.sessionId) != null ? l : this.options.sessionId) != null ? a : void 0, s = {
|
|
219
219
|
organisationId: this.options.org,
|
|
220
|
-
assistantId: this.options.assistant,
|
|
221
220
|
sessionId: t,
|
|
222
221
|
userAgent: typeof navigator != "undefined" ? navigator.userAgent : "",
|
|
223
222
|
referrer: typeof document != "undefined" ? document.referrer : "",
|
|
@@ -232,13 +231,13 @@ class U {
|
|
|
232
231
|
});
|
|
233
232
|
if (!i.ok)
|
|
234
233
|
throw new Error(`SpilkiWidget: connect failed (${i.status})`);
|
|
235
|
-
const
|
|
236
|
-
return this.sessionId =
|
|
234
|
+
const n = await i.json();
|
|
235
|
+
return this.sessionId = n.sessionId, this.options.sessionId = n.sessionId, this.backoff = d, await this.startTransport(n), n;
|
|
237
236
|
}
|
|
238
237
|
async send(e) {
|
|
239
|
-
var
|
|
238
|
+
var n, l;
|
|
240
239
|
const t = {
|
|
241
|
-
sessionId: (l = (
|
|
240
|
+
sessionId: (l = (n = this.sessionId) != null ? n : this.options.sessionId) != null ? l : "",
|
|
242
241
|
text: e
|
|
243
242
|
};
|
|
244
243
|
if (!t.sessionId)
|
|
@@ -284,7 +283,7 @@ class U {
|
|
|
284
283
|
return;
|
|
285
284
|
}
|
|
286
285
|
this.currentKind = "ws", this.handlers.onOpen("ws"), this.backoff = d, t();
|
|
287
|
-
}), i.addEventListener("message", (
|
|
286
|
+
}), i.addEventListener("message", (n) => this.handleIncoming(n.data)), i.addEventListener("close", () => {
|
|
288
287
|
this.stopped || this.retryFallback("ws");
|
|
289
288
|
}), i.addEventListener("error", () => {
|
|
290
289
|
this.handlers.onError(new Error("SpilkiWidget: websocket error")), i.readyState !== WebSocket.OPEN && s(new Error("WebSocket failed"));
|
|
@@ -302,15 +301,15 @@ class U {
|
|
|
302
301
|
}
|
|
303
302
|
const i = new EventSource(e);
|
|
304
303
|
this.sse = i;
|
|
305
|
-
let
|
|
304
|
+
let n = !1;
|
|
306
305
|
i.addEventListener("open", () => {
|
|
307
|
-
if (
|
|
306
|
+
if (n = !0, this.stopped) {
|
|
308
307
|
i.close();
|
|
309
308
|
return;
|
|
310
309
|
}
|
|
311
310
|
this.currentKind = "sse", this.handlers.onOpen("sse"), this.backoff = d, t();
|
|
312
311
|
}), i.addEventListener("message", (l) => this.handleIncoming(l.data)), i.addEventListener("error", () => {
|
|
313
|
-
if (!
|
|
312
|
+
if (!n) {
|
|
314
313
|
s(new Error("SSE failed"));
|
|
315
314
|
return;
|
|
316
315
|
}
|
|
@@ -326,7 +325,7 @@ class U {
|
|
|
326
325
|
const s = await fetch(e);
|
|
327
326
|
if (!s.ok) throw new Error(`Poll failed ${s.status}`);
|
|
328
327
|
const i = await s.json();
|
|
329
|
-
u(i).forEach((
|
|
328
|
+
u(i).forEach((n) => this.handlers.onMessage(n)), this.backoff = d;
|
|
330
329
|
} catch (s) {
|
|
331
330
|
this.handlers.onError(s), this.backoff = Math.min(this.backoff * 1.5, v);
|
|
332
331
|
} finally {
|
|
@@ -369,13 +368,13 @@ class U {
|
|
|
369
368
|
}
|
|
370
369
|
const f = 30;
|
|
371
370
|
class N {
|
|
372
|
-
constructor(e, t
|
|
373
|
-
this.org = e, this.
|
|
371
|
+
constructor(e, t) {
|
|
372
|
+
this.org = e, this.listeners = /* @__PURE__ */ new Set(), this.state = {
|
|
374
373
|
isOpen: !1,
|
|
375
374
|
isTyping: !1,
|
|
376
375
|
isConnected: !1,
|
|
377
376
|
messages: []
|
|
378
|
-
}, this.historyKey = `spilki-history:${e}
|
|
377
|
+
}, this.historyKey = `spilki-history:${e}`, this.sessionKey = `spilki-session:${e}`, this.tokenKey = `spilki-token:${e}`, this.persist = t.persist, this.state.messages = this.loadMessages();
|
|
379
378
|
}
|
|
380
379
|
get snapshot() {
|
|
381
380
|
return { ...this.state, messages: [...this.state.messages] };
|
|
@@ -522,14 +521,14 @@ const H = {
|
|
|
522
521
|
onTransportChange() {
|
|
523
522
|
}
|
|
524
523
|
};
|
|
525
|
-
async function q(r, e) {
|
|
526
|
-
const
|
|
524
|
+
async function q(r, e, t) {
|
|
525
|
+
const s = `${r.replace(/\/$/, "")}/widget/install`, i = await fetch(s, {
|
|
527
526
|
method: "POST",
|
|
528
527
|
headers: { "Content-Type": "application/json", Origin: window.location.origin },
|
|
529
|
-
body: JSON.stringify({ token: e })
|
|
528
|
+
body: JSON.stringify({ token: e, organisationId: t })
|
|
530
529
|
});
|
|
531
|
-
if (!
|
|
532
|
-
return (await
|
|
530
|
+
if (!i.ok) throw new Error(`SpilkiWidget: install failed (${i.status})`);
|
|
531
|
+
return (await i.json()).accessToken;
|
|
533
532
|
}
|
|
534
533
|
async function J(r, e) {
|
|
535
534
|
const t = `${r.replace(/\/$/, "")}/widget/refresh`, s = await fetch(t, {
|
|
@@ -541,16 +540,17 @@ async function J(r, e) {
|
|
|
541
540
|
}
|
|
542
541
|
function E(r) {
|
|
543
542
|
var k, w, y, S;
|
|
544
|
-
if (!r.org
|
|
545
|
-
throw new Error("SpilkiWidget: org
|
|
543
|
+
if (!r.org)
|
|
544
|
+
throw new Error("SpilkiWidget: org is required");
|
|
546
545
|
const e = B(r);
|
|
547
546
|
P(e.allowedOriginsHint);
|
|
548
|
-
const t = { ...H, ...(k = e.hooks) != null ? k : {} }, s = new N(e.org,
|
|
547
|
+
const t = { ...H, ...(k = e.hooks) != null ? k : {} }, s = new N(e.org, { persist: e.persist });
|
|
549
548
|
let i = (w = s.accessToken) != null ? w : void 0;
|
|
550
|
-
const
|
|
549
|
+
const n = async () => {
|
|
551
550
|
if (!i) {
|
|
552
551
|
if (!r.installationToken) throw new Error("SpilkiWidget: missing installationToken");
|
|
553
|
-
|
|
552
|
+
if (!r.org) throw new Error("SpilkiWidget: missing org");
|
|
553
|
+
i = await q(e.apiBase, r.installationToken, r.org), s.persistAccessToken(i);
|
|
554
554
|
return;
|
|
555
555
|
}
|
|
556
556
|
z(i) && (i = await J(e.apiBase, i), s.persistAccessToken(i));
|
|
@@ -560,7 +560,7 @@ function E(r) {
|
|
|
560
560
|
onClick: () => {
|
|
561
561
|
s.snapshot.isOpen ? (s.close(), t.onClose()) : (s.open(), t.onOpen());
|
|
562
562
|
}
|
|
563
|
-
}), a = new
|
|
563
|
+
}), a = new W({
|
|
564
564
|
color: e.color,
|
|
565
565
|
theme: x(e.theme),
|
|
566
566
|
position: (S = e.position) != null ? S : "bottom-right",
|
|
@@ -568,9 +568,9 @@ function E(r) {
|
|
|
568
568
|
onClose: () => {
|
|
569
569
|
s.close(), t.onClose();
|
|
570
570
|
},
|
|
571
|
-
onSend: (
|
|
572
|
-
const c = s.addMessage({ author: "user", text:
|
|
573
|
-
a.appendMessage(c),
|
|
571
|
+
onSend: (o) => {
|
|
572
|
+
const c = s.addMessage({ author: "user", text: o });
|
|
573
|
+
a.appendMessage(c), n().then(() => h.send(o)).catch((O) => {
|
|
574
574
|
t.onError(O), s.setConnected(!1), a.setOffline(!0);
|
|
575
575
|
});
|
|
576
576
|
}
|
|
@@ -579,48 +579,47 @@ function E(r) {
|
|
|
579
579
|
apiBase: e.apiBase,
|
|
580
580
|
accessToken: i,
|
|
581
581
|
org: e.org,
|
|
582
|
-
assistant: e.assistant,
|
|
583
582
|
sessionId: s.sessionId
|
|
584
583
|
},
|
|
585
584
|
{
|
|
586
|
-
onOpen(
|
|
587
|
-
m.transport =
|
|
585
|
+
onOpen(o) {
|
|
586
|
+
m.transport = o, t.onTransportChange(o), s.setConnected(!0), a.setOffline(!1);
|
|
588
587
|
},
|
|
589
|
-
onMessage(
|
|
590
|
-
const c = s.addMessage(
|
|
588
|
+
onMessage(o) {
|
|
589
|
+
const c = s.addMessage(o);
|
|
591
590
|
a.appendMessage(c), t.onMessage(c);
|
|
592
591
|
},
|
|
593
|
-
onTyping(
|
|
594
|
-
s.setTyping(
|
|
592
|
+
onTyping(o) {
|
|
593
|
+
s.setTyping(o);
|
|
595
594
|
},
|
|
596
|
-
onError(
|
|
597
|
-
t.onError(
|
|
595
|
+
onError(o) {
|
|
596
|
+
t.onError(o), s.setConnected(!1), s.snapshot.isOpen && a.setOffline(!0);
|
|
598
597
|
}
|
|
599
598
|
}
|
|
600
599
|
);
|
|
601
600
|
l.mount(), a.mount();
|
|
602
601
|
const b = s.snapshot.messages;
|
|
603
602
|
if (b.length === 0 && e.welcome) {
|
|
604
|
-
const
|
|
603
|
+
const o = {
|
|
605
604
|
id: "welcome",
|
|
606
605
|
author: "bot",
|
|
607
606
|
text: e.welcome,
|
|
608
607
|
ts: Date.now()
|
|
609
608
|
};
|
|
610
|
-
s.addMessage(
|
|
609
|
+
s.addMessage(o), a.appendMessage(o);
|
|
611
610
|
} else
|
|
612
611
|
a.updateMessages(b);
|
|
613
612
|
const I = s.subscribe(() => {
|
|
614
|
-
const
|
|
615
|
-
l.setOpen(
|
|
613
|
+
const o = s.snapshot;
|
|
614
|
+
l.setOpen(o.isOpen), a.setTyping(o.isTyping), a.setOffline(!o.isConnected), a.updateTheme(x(e.theme)), o.isOpen ? a.show() : a.hide();
|
|
616
615
|
});
|
|
617
|
-
|
|
618
|
-
() => h.connect().then((
|
|
616
|
+
n().then(
|
|
617
|
+
() => h.connect().then((o) => {
|
|
619
618
|
var c;
|
|
620
|
-
e.persist && s.persistSession(
|
|
619
|
+
e.persist && s.persistSession(o.sessionId), s.setConnected(!0), t.onTransportChange((c = h.kind) != null ? c : "ws");
|
|
621
620
|
})
|
|
622
|
-
).catch((
|
|
623
|
-
t.onError(
|
|
621
|
+
).catch((o) => {
|
|
622
|
+
t.onError(o), s.setConnected(!1), a.setOffline(!0);
|
|
624
623
|
});
|
|
625
624
|
const m = {
|
|
626
625
|
transport: null,
|
|
@@ -637,24 +636,23 @@ function E(r) {
|
|
|
637
636
|
return m;
|
|
638
637
|
}
|
|
639
638
|
function T() {
|
|
640
|
-
var
|
|
639
|
+
var s, i;
|
|
641
640
|
if (typeof document == "undefined") return;
|
|
642
641
|
const r = document.currentScript;
|
|
643
642
|
if (!r) return;
|
|
644
643
|
const e = r.dataset;
|
|
645
644
|
if (e.autoinit === "false") return;
|
|
646
|
-
const t = e.org
|
|
647
|
-
if (!t
|
|
648
|
-
console.error("SpilkiWidget: data-org and
|
|
645
|
+
const t = e.org;
|
|
646
|
+
if (!t) {
|
|
647
|
+
console.error("SpilkiWidget: data-org and is required for auto init");
|
|
649
648
|
return;
|
|
650
649
|
}
|
|
651
650
|
E({
|
|
652
651
|
org: t,
|
|
653
|
-
assistant: s,
|
|
654
652
|
installationToken: e.installationToken,
|
|
655
653
|
apiBase: e.apiBase,
|
|
656
|
-
position: (
|
|
657
|
-
theme: (
|
|
654
|
+
position: (s = e.position) != null ? s : void 0,
|
|
655
|
+
theme: (i = e.theme) != null ? i : void 0
|
|
658
656
|
});
|
|
659
657
|
}
|
|
660
658
|
if (typeof window != "undefined") {
|