@spilki/widget 1.0.37 → 1.0.38

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/dist/widget.es.js CHANGED
@@ -74,13 +74,13 @@ const Y = `
74
74
  <span class="badge" hidden aria-hidden="true">0</span>
75
75
  </button>
76
76
  `;
77
- function G(o) {
77
+ function G(r) {
78
78
  const e = document.createElement("div");
79
- e.setAttribute("part", "bubble-root"), e.setAttribute("data-position", o.position), e.style.setProperty("--spilki-accent", o.color);
79
+ e.setAttribute("part", "bubble-root"), e.setAttribute("data-position", r.position), e.style.setProperty("--spilki-accent", r.color);
80
80
  const t = e.attachShadow({ mode: "open" });
81
81
  t.innerHTML = Y;
82
82
  const s = t.querySelector("button"), i = t.querySelector(".badge");
83
- return s.addEventListener("click", () => o.onClick()), {
83
+ return s.addEventListener("click", () => r.onClick()), {
84
84
  element: e,
85
85
  mount() {
86
86
  document.body.appendChild(e);
@@ -92,12 +92,12 @@ function G(o) {
92
92
  s.setAttribute("aria-expanded", String(a)), s.setAttribute("aria-label", a ? "Close chat" : "Open chat");
93
93
  },
94
94
  setBadge(a) {
95
- const r = Math.max(0, a), l = s.getAttribute("aria-expanded") === "true";
96
- if (r === 0) {
95
+ const n = Math.max(0, a), l = s.getAttribute("aria-expanded") === "true";
96
+ if (n === 0) {
97
97
  i.toggleAttribute("hidden", !0), i.textContent = "0", l || s.setAttribute("aria-label", "Open chat");
98
98
  return;
99
99
  }
100
- i.toggleAttribute("hidden", !1), i.textContent = r > 99 ? "99+" : String(r), l || s.setAttribute("aria-label", `Open chat, ${r} unread`);
100
+ i.toggleAttribute("hidden", !1), i.textContent = n > 99 ? "99+" : String(n), l || s.setAttribute("aria-label", `Open chat, ${n} unread`);
101
101
  },
102
102
  setDimmed(a) {
103
103
  e.toggleAttribute("data-dimmed", a);
@@ -110,7 +110,7 @@ function G(o) {
110
110
  }
111
111
  };
112
112
  }
113
- const V = "https://api.spilki.app", M = {
113
+ const V = "https://api.spilki.app", P = {
114
114
  welcome: "Hi! I'm your assistant.",
115
115
  placeholder: "Type a message…",
116
116
  sendLabel: "Send",
@@ -125,53 +125,53 @@ const V = "https://api.spilki.app", M = {
125
125
  position: "bottom-right",
126
126
  theme: "auto",
127
127
  color: "#6366f1",
128
- welcome: M.welcome,
128
+ welcome: P.welcome,
129
129
  persist: !0,
130
130
  sound: !0,
131
- i18n: M
131
+ i18n: P
132
132
  };
133
- function J(o) {
134
- var t, s, i, n, a, r, l, p;
135
- const e = { ...M, ...(t = o.i18n) != null ? t : {} };
133
+ function J(r) {
134
+ var t, s, i, o, a, n, l, p;
135
+ const e = { ...P, ...(t = r.i18n) != null ? t : {} };
136
136
  return {
137
137
  ...w,
138
- ...o,
139
- apiBase: (s = o.apiBase) != null ? s : w.apiBase,
138
+ ...r,
139
+ apiBase: (s = r.apiBase) != null ? s : w.apiBase,
140
140
  i18n: e,
141
- welcome: (i = o.welcome) != null ? i : e.welcome,
142
- position: (n = o.position) != null ? n : w.position,
143
- theme: (a = o.theme) != null ? a : w.theme,
144
- color: (r = o.color) != null ? r : w.color,
145
- persist: (l = o.persist) != null ? l : w.persist,
146
- sound: (p = o.sound) != null ? p : w.sound
141
+ welcome: (i = r.welcome) != null ? i : e.welcome,
142
+ position: (o = r.position) != null ? o : w.position,
143
+ theme: (a = r.theme) != null ? a : w.theme,
144
+ color: (n = r.color) != null ? n : w.color,
145
+ persist: (l = r.persist) != null ? l : w.persist,
146
+ sound: (p = r.sound) != null ? p : w.sound
147
147
  };
148
148
  }
149
- function X(o = "msg") {
150
- return typeof crypto != "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${o}-${Math.random().toString(16).slice(2)}`;
149
+ function X(r = "msg") {
150
+ return typeof crypto != "undefined" && crypto.randomUUID ? crypto.randomUUID() : `${r}-${Math.random().toString(16).slice(2)}`;
151
151
  }
152
152
  function Z() {
153
- var o, e;
154
- return (e = (o = window.matchMedia) == null ? void 0 : o.call(window, "(prefers-color-scheme: dark)").matches) != null ? e : !1;
153
+ var r, e;
154
+ return (e = (r = window.matchMedia) == null ? void 0 : r.call(window, "(prefers-color-scheme: dark)").matches) != null ? e : !1;
155
155
  }
156
- function R(o) {
157
- return o === "light" || o === "dark" ? o : Z() ? "dark" : "light";
156
+ function $(r) {
157
+ return r === "light" || r === "dark" ? r : Z() ? "dark" : "light";
158
158
  }
159
- function A(o, e = 30) {
160
- return o.slice(-e);
159
+ function A(r, e = 30) {
160
+ return r.slice(-e);
161
161
  }
162
- function Q(o) {
163
- if (!o || o.length === 0) return;
162
+ function Q(r) {
163
+ if (!r || r.length === 0) return;
164
164
  const e = window.location.origin;
165
- o.includes(e) || console.warn(
166
- `SpilkiWidget: current origin ${e} not in allowedOriginsHint: ${o.join(", ")}`
165
+ r.includes(e) || console.warn(
166
+ `SpilkiWidget: current origin ${e} not in allowedOriginsHint: ${r.join(", ")}`
167
167
  );
168
168
  }
169
169
  const ee = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
170
- function te(o) {
171
- const e = new Date(o), t = /* @__PURE__ */ new Date(), s = (l) => String(l).padStart(2, "0"), i = `${s(e.getHours())}:${s(e.getMinutes())}`, n = new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime(), a = n - 864e5, r = new Date(e.getFullYear(), e.getMonth(), e.getDate()).getTime();
172
- return r === n ? `Today at ${i}` : r === a ? `Yesterday at ${i}` : `${ee[e.getMonth()]} ${e.getDate()}, ${i}`;
170
+ function te(r) {
171
+ const e = new Date(r), t = /* @__PURE__ */ new Date(), s = (l) => String(l).padStart(2, "0"), i = `${s(e.getHours())}:${s(e.getMinutes())}`, o = new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime(), a = o - 864e5, n = new Date(e.getFullYear(), e.getMonth(), e.getDate()).getTime();
172
+ return n === o ? `Today at ${i}` : n === a ? `Yesterday at ${i}` : `${ee[e.getMonth()]} ${e.getDate()}, ${i}`;
173
173
  }
174
- const se = ':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-muted-light: #64748b;--spilki-muted-dark: #94a3b8;--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{position:relative;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 button.close:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px;border-radius:4px}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:.75rem;scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.3) transparent;scroll-behavior:smooth}.message{display:flex;flex-direction:column;gap:.15rem;max-width:85%;width:fit-content;line-height:1.4;word-wrap:break-word;overflow-wrap:anywhere;white-space:pre-wrap}.message.user{align-self:flex-end;align-items:flex-end}.message .bubble{padding:.6rem .8rem;border-radius:1rem;background:#6366f126}.message.user .bubble{background:var(--spilki-accent);color:#fff}.message.bot .bubble{background:#94a3b826}.msg-time{font-size:.7rem;color:var(--spilki-muted);margin-top:2px}.date-separator{display:flex;align-items:center;gap:.5rem;padding:.4rem 0;font-size:.72rem;color:var(--spilki-muted);white-space:nowrap}.date-separator:before,.date-separator:after{content:"";flex:1;height:1px;background:var(--spilki-border)}.scroll-bottom{position:absolute;right:1rem;bottom:88px;width:38px;height:38px;border:none;border-radius:999px;background:var(--spilki-accent);color:#fff;box-shadow:0 8px 20px #0f172a40;cursor:pointer;opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity .18s ease,transform .18s ease;z-index:3}.scroll-bottom.visible{opacity:1;pointer-events:auto;transform:translateY(0)}.scroll-arrow{font-size:.8rem;line-height:1}.scroll-count{position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;border-radius:999px;background:#ef4444;color:#fff;font-size:10px;line-height:16px;text-align:center;padding:0 4px}.suggested-replies{display:flex;flex-wrap:wrap;gap:.4rem;padding:.5rem 1rem;border-top:1px solid var(--spilki-border)}.suggested-chip{border:1px solid var(--spilki-accent);background:transparent;color:var(--spilki-accent);border-radius:999px;padding:.35rem .75rem;font-size:.8rem;font-family:inherit;cursor:pointer;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background .15s,color .15s}.suggested-chip:hover{background:var(--spilki-accent);color:#fff}.suggested-chip:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px}.input-area{padding:.5rem .75rem}.input-wrap{display:flex;align-items:center;border:1px solid var(--spilki-border);border-radius:1.5rem;background:transparent;padding-left:0}.input-area textarea{flex:1;resize:none;min-height:2.4rem;max-height:6rem;border:0;border-radius:0;outline:0;background:transparent;box-shadow:none;-webkit-box-shadow:none;-webkit-appearance:none;appearance:none;padding:.55rem 0 .55rem 1rem;font-family:inherit;font-size:.95rem;color:var(--spilki-text);scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.3) transparent}.input-actions{display:flex;align-items:center;gap:.25rem;padding:.25rem .35rem;flex-shrink:0}.input-actions button{width:32px;height:32px;display:grid;place-items:center;border:none;border-radius:50%;cursor:pointer;padding:0;transition:opacity .15s}.emoji-btn{background:#6366f126;color:var(--spilki-accent)}.emoji-btn:hover{background:#6366f140}.emoji-btn:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:1px}.send-btn{background:var(--spilki-accent);color:#fff}.send-btn:hover{opacity:.85}.send-btn:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px}.emoji-picker{position:absolute;right:1rem;bottom:80px;width:240px;max-height:180px;overflow-y:auto;display:none;grid-template-columns:repeat(10,minmax(0,1fr));gap:.25rem;padding:.5rem;background:var(--spilki-surface);border:1px solid var(--spilki-border);border-radius:12px;box-shadow:0 14px 30px #0f172a40;z-index:4}.emoji-option{width:100%;aspect-ratio:1;border:none;border-radius:8px;background:transparent;font-size:1rem;cursor:pointer}.emoji-option:hover,.emoji-option:focus-visible{background:#94a3b833}.typing{font-size:.75rem;color:var(--spilki-muted);padding:0 1rem .75rem}.typing:after{content:"";animation:dots 1.2s steps(4,end) infinite}@keyframes dots{0%{content:""}25%{content:"."}50%{content:".."}75%{content:"..."}}.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);--spilki-muted: var(--spilki-muted-dark)}:host([data-theme="dark"]) .messages,:host([data-theme="dark"]) .input-area textarea,:host([data-theme="dark"]) .emoji-picker{scrollbar-color:rgba(255,255,255,.2) transparent}:host([data-theme="light"]){--spilki-surface: var(--spilki-bg-light);--spilki-text: var(--spilki-text-light);--spilki-border: var(--spilki-border-light);--spilki-muted: var(--spilki-muted-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:transparent}.messages::-webkit-scrollbar,.input-area textarea::-webkit-scrollbar,.emoji-picker::-webkit-scrollbar{width:6px}.messages::-webkit-scrollbar-track,.input-area textarea::-webkit-scrollbar-track,.emoji-picker::-webkit-scrollbar-track{background:transparent}.messages::-webkit-scrollbar-thumb,.input-area textarea::-webkit-scrollbar-thumb,.emoji-picker::-webkit-scrollbar-thumb{background:#94a3b84d;border-radius:999px}.messages::-webkit-scrollbar-thumb:hover,.input-area textarea::-webkit-scrollbar-thumb:hover,.emoji-picker::-webkit-scrollbar-thumb:hover{background:#94a3b880}:host([data-theme="dark"]) .messages::-webkit-scrollbar-thumb,:host([data-theme="dark"]) .input-area textarea::-webkit-scrollbar-thumb,:host([data-theme="dark"]) .emoji-picker::-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,:host([data-theme="dark"]) .emoji-picker::-webkit-scrollbar-thumb:hover{background:#ffffff59}.conversation-separator{display:flex;align-items:center;gap:.5rem;padding:.5rem 0;cursor:pointer;user-select:none;font-size:.7rem;color:var(--spilki-muted);white-space:nowrap}.conversation-separator:before,.conversation-separator:after{content:"";flex:1;height:1px;background:var(--spilki-border)}.conversation-separator:hover{color:var(--spilki-text)}.conversation-separator:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px;border-radius:4px}.conversation-history{display:none;flex-direction:column;gap:.5rem}.conversation-history.expanded{display:flex}', $ = 24 * 60 * 60 * 1e3, ie = 2 * 60 * 1e3, oe = 200, ne = [
174
+ const se = ':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-muted-light: #64748b;--spilki-muted-dark: #94a3b8;--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{position:relative;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 button.close:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px;border-radius:4px}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:.75rem;scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.3) transparent;scroll-behavior:smooth}.message{display:flex;flex-direction:column;gap:.15rem;max-width:85%;width:fit-content;line-height:1.4;word-wrap:break-word;overflow-wrap:anywhere;white-space:pre-wrap}.message.user{align-self:flex-end;align-items:flex-end}.message .bubble{padding:.6rem .8rem;border-radius:1rem;background:#6366f126}.message.user .bubble{background:var(--spilki-accent);color:#fff}.message.bot .bubble{background:#94a3b826}.msg-time{font-size:.7rem;color:var(--spilki-muted);margin-top:2px}.date-separator{display:flex;align-items:center;gap:.5rem;padding:.4rem 0;font-size:.72rem;color:var(--spilki-muted);white-space:nowrap}.date-separator:before,.date-separator:after{content:"";flex:1;height:1px;background:var(--spilki-border)}.scroll-bottom{position:absolute;right:1rem;bottom:88px;width:38px;height:38px;border:none;border-radius:999px;background:var(--spilki-accent);color:#fff;box-shadow:0 8px 20px #0f172a40;cursor:pointer;opacity:0;pointer-events:none;transform:translateY(4px);transition:opacity .18s ease,transform .18s ease;z-index:3}.scroll-bottom.visible{opacity:1;pointer-events:auto;transform:translateY(0)}.scroll-arrow{font-size:.8rem;line-height:1}.scroll-count{position:absolute;top:-5px;right:-5px;min-width:16px;height:16px;border-radius:999px;background:#ef4444;color:#fff;font-size:10px;line-height:16px;text-align:center;padding:0 4px}.suggested-replies{display:flex;flex-wrap:wrap;gap:.4rem;padding:.5rem 1rem;border-top:1px solid var(--spilki-border)}.suggested-chip{border:1px solid var(--spilki-accent);background:transparent;color:var(--spilki-accent);border-radius:999px;padding:.35rem .75rem;font-size:.8rem;font-family:inherit;cursor:pointer;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;transition:background .15s,color .15s}.suggested-chip:hover{background:var(--spilki-accent);color:#fff}.suggested-chip:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px}.input-area{padding:.5rem .75rem}.input-wrap{display:flex;align-items:center;border:1px solid var(--spilki-border);border-radius:1.5rem;background:transparent;padding-left:0}.input-area textarea{flex:1;resize:none;min-height:2.4rem;max-height:6rem;border:0;border-radius:0;outline:0;background:transparent;box-shadow:none;-webkit-box-shadow:none;-webkit-appearance:none;appearance:none;padding:.55rem 0 .55rem 1rem;font-family:inherit;font-size:.95rem;color:var(--spilki-text);scrollbar-width:thin;scrollbar-color:rgba(148,163,184,.3) transparent}.input-actions{display:flex;align-items:center;gap:.25rem;padding:.25rem .35rem;flex-shrink:0}.input-actions button{width:32px;height:32px;display:grid;place-items:center;border:none;border-radius:50%;cursor:pointer;padding:0;transition:opacity .15s}.emoji-btn{background:#6366f126;color:var(--spilki-accent)}.emoji-btn:hover{background:#6366f140}.emoji-btn:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:1px}.send-btn{background:var(--spilki-accent);color:#fff}.send-btn:hover{opacity:.85}.send-btn:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px}.emoji-picker{position:absolute;right:1rem;bottom:80px;width:240px;max-height:180px;overflow-y:auto;display:none;grid-template-columns:repeat(10,minmax(0,1fr));gap:.25rem;padding:.5rem;background:var(--spilki-surface);border:1px solid var(--spilki-border);border-radius:12px;box-shadow:0 14px 30px #0f172a40;z-index:4}.emoji-option{width:100%;aspect-ratio:1;border:none;border-radius:8px;background:transparent;font-size:1rem;cursor:pointer}.emoji-option:hover,.emoji-option:focus-visible{background:#94a3b833}.typing{font-size:.75rem;color:var(--spilki-muted);padding:0 1rem .75rem}.typing:after{content:"";animation:dots 1.2s steps(4,end) infinite}@keyframes dots{0%{content:""}25%{content:"."}50%{content:".."}75%{content:"..."}}.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);--spilki-muted: var(--spilki-muted-dark)}:host([data-theme="dark"]) .messages,:host([data-theme="dark"]) .input-area textarea,:host([data-theme="dark"]) .emoji-picker{scrollbar-color:rgba(255,255,255,.2) transparent}:host([data-theme="light"]){--spilki-surface: var(--spilki-bg-light);--spilki-text: var(--spilki-text-light);--spilki-border: var(--spilki-border-light);--spilki-muted: var(--spilki-muted-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:transparent}.messages::-webkit-scrollbar,.input-area textarea::-webkit-scrollbar,.emoji-picker::-webkit-scrollbar{width:6px}.messages::-webkit-scrollbar-track,.input-area textarea::-webkit-scrollbar-track,.emoji-picker::-webkit-scrollbar-track{background:transparent}.messages::-webkit-scrollbar-thumb,.input-area textarea::-webkit-scrollbar-thumb,.emoji-picker::-webkit-scrollbar-thumb{background:#94a3b84d;border-radius:999px}.messages::-webkit-scrollbar-thumb:hover,.input-area textarea::-webkit-scrollbar-thumb:hover,.emoji-picker::-webkit-scrollbar-thumb:hover{background:#94a3b880}:host([data-theme="dark"]) .messages::-webkit-scrollbar-thumb,:host([data-theme="dark"]) .input-area textarea::-webkit-scrollbar-thumb,:host([data-theme="dark"]) .emoji-picker::-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,:host([data-theme="dark"]) .emoji-picker::-webkit-scrollbar-thumb:hover{background:#ffffff59}.conversation-separator{display:flex;align-items:center;gap:.5rem;padding:.5rem 0;cursor:pointer;user-select:none;font-size:.7rem;color:var(--spilki-muted);white-space:nowrap}.conversation-separator:before,.conversation-separator:after{content:"";flex:1;height:1px;background:var(--spilki-border)}.conversation-separator:hover{color:var(--spilki-text)}.conversation-separator:focus-visible{outline:2px solid var(--spilki-accent);outline-offset:2px;border-radius:4px}.conversation-history{display:none;flex-direction:column;gap:.5rem}.conversation-history.expanded{display:flex}', N = 24 * 60 * 60 * 1e3, ie = 2 * 60 * 1e3, re = 200, oe = [
175
175
  "😀",
176
176
  "😂",
177
177
  "🤣",
@@ -223,10 +223,10 @@ const se = ':host{--spilki-bg-light: #ffffff;--spilki-bg-dark: #0f172a;--spilki-
223
223
  "☕",
224
224
  "🍕"
225
225
  ];
226
- function S(o) {
227
- return o.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
226
+ function S(r) {
227
+ return r.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
228
228
  }
229
- class re {
229
+ class ne {
230
230
  constructor(e) {
231
231
  this.options = e, this.relativeTimeFormat = new Intl.RelativeTimeFormat(void 0, {
232
232
  numeric: "auto"
@@ -241,7 +241,7 @@ class re {
241
241
  day: "numeric",
242
242
  year: "numeric"
243
243
  }), this.renderedMessages = [], this.focusable = [], this.seenIds = /* @__PURE__ */ new Set(), this.lastTimelineMessage = null, this.scrollUnreadCount = 0, this.emojiPickerOpen = !1, 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" });
244
- const t = S(e.i18n.title), s = S(e.i18n.typing), i = S(e.i18n.offline), n = S(e.i18n.placeholder), a = S(e.i18n.sendLabel);
244
+ const t = S(e.i18n.title), s = S(e.i18n.typing), i = S(e.i18n.offline), o = S(e.i18n.placeholder), a = S(e.i18n.sendLabel);
245
245
  this.shadow.innerHTML = `
246
246
  <style>${se}</style>
247
247
  <div class="wrapper" role="dialog" aria-modal="true" aria-label="${t}">
@@ -260,7 +260,7 @@ class re {
260
260
  <div class="emoji-picker" aria-label="Emoji picker"></div>
261
261
  <div class="input-area">
262
262
  <div class="input-wrap">
263
- <textarea rows="1" placeholder="${n}" aria-label="${n}"></textarea>
263
+ <textarea rows="1" placeholder="${o}" aria-label="${o}"></textarea>
264
264
  <div class="input-actions">
265
265
  <button class="emoji-btn" type="button" aria-label="Insert emoji">
266
266
  <svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">
@@ -279,18 +279,18 @@ class re {
279
279
  </div>
280
280
  </div>
281
281
  </div>
282
- `, this.host.dataset.theme = e.theme, this.host.style.setProperty("--spilki-accent", e.color), this.messagesEl = this.shadow.querySelector(".messages"), this.typingEl = this.shadow.querySelector(".typing"), this.input = this.shadow.querySelector("textarea"), this.offlineEl = this.shadow.querySelector(".offline"), this.sendButton = this.shadow.querySelector(".send-btn"), this.emojiButton = this.shadow.querySelector(".emoji-btn"), this.emojiPickerEl = this.shadow.querySelector(".emoji-picker"), this.scrollBottomButton = this.shadow.querySelector(".scroll-bottom"), this.scrollBottomCountEl = this.shadow.querySelector(".scroll-count"), this.closeButton = this.shadow.querySelector("header .close"), this.suggestedRepliesEl = this.shadow.querySelector(".suggested-replies"), this.handleCloseClick = () => this.options.onClose(), this.handleSendClick = () => this.send(), this.handleInputKeydown = (r) => {
283
- if (r.key === "Enter" && !r.shiftKey)
284
- r.preventDefault(), this.send();
285
- else if (r.key === "Escape") {
282
+ `, this.host.dataset.theme = e.theme, this.host.style.setProperty("--spilki-accent", e.color), this.messagesEl = this.shadow.querySelector(".messages"), this.typingEl = this.shadow.querySelector(".typing"), this.input = this.shadow.querySelector("textarea"), this.offlineEl = this.shadow.querySelector(".offline"), this.sendButton = this.shadow.querySelector(".send-btn"), this.emojiButton = this.shadow.querySelector(".emoji-btn"), this.emojiPickerEl = this.shadow.querySelector(".emoji-picker"), this.scrollBottomButton = this.shadow.querySelector(".scroll-bottom"), this.scrollBottomCountEl = this.shadow.querySelector(".scroll-count"), this.closeButton = this.shadow.querySelector("header .close"), this.suggestedRepliesEl = this.shadow.querySelector(".suggested-replies"), this.handleCloseClick = () => this.options.onClose(), this.handleSendClick = () => this.send(), this.handleInputKeydown = (n) => {
283
+ if (n.key === "Enter" && !n.shiftKey)
284
+ n.preventDefault(), this.send();
285
+ else if (n.key === "Escape") {
286
286
  if (this.emojiPickerOpen) {
287
- r.stopPropagation(), this.closeEmojiPicker();
287
+ n.stopPropagation(), this.closeEmojiPicker();
288
288
  return;
289
289
  }
290
290
  this.options.onClose();
291
291
  }
292
- }, this.handleShadowKeydown = (r) => {
293
- const l = r;
292
+ }, this.handleShadowKeydown = (n) => {
293
+ const l = n;
294
294
  if (l.key === "Escape") {
295
295
  if (this.emojiPickerOpen) {
296
296
  l.preventDefault(), this.closeEmojiPicker();
@@ -303,9 +303,9 @@ class re {
303
303
  this.scrollToBottom(), this.resetScrollUnreadCount();
304
304
  }, this.handleEmojiClick = () => {
305
305
  this.toggleEmojiPicker();
306
- }, this.handleDocumentPointerDown = (r) => {
306
+ }, this.handleDocumentPointerDown = (n) => {
307
307
  if (!this.emojiPickerOpen) return;
308
- const l = r.composedPath();
308
+ const l = n.composedPath();
309
309
  l.includes(this.emojiPickerEl) || l.includes(this.emojiButton) || this.closeEmojiPicker();
310
310
  }, this.closeButton.addEventListener("click", this.handleCloseClick), this.sendButton.addEventListener("click", this.handleSendClick), this.emojiButton.addEventListener("click", this.handleEmojiClick), this.scrollBottomButton.addEventListener("click", this.handleScrollBottomClick), this.input.addEventListener("keydown", this.handleInputKeydown), this.messagesEl.addEventListener("scroll", this.handleMessagesScroll), this.shadow.addEventListener("keydown", this.handleShadowKeydown), this.shadow.addEventListener("focusin", this.handleFocusin), document.addEventListener("pointerdown", this.handleDocumentPointerDown, !0), this.renderEmojiPicker(), this.updateScrollBottomState(), this.collectFocusable();
311
311
  }
@@ -343,8 +343,8 @@ class re {
343
343
  renderWithConversations(e, t) {
344
344
  this.messagesEl.innerHTML = "", this.seenIds.clear(), this.renderedMessages.length = 0, this.lastTimelineMessage = null;
345
345
  for (const s of e) {
346
- s.messages.forEach((r) => this.seenIds.add(r.id));
347
- const i = this.createHistoryContainer(s.messages), n = s.messages[s.messages.length - 1].ts, a = this.createSeparatorElement(n, i);
346
+ s.messages.forEach((n) => this.seenIds.add(n.id));
347
+ const i = this.createHistoryContainer(s.messages), o = s.messages[s.messages.length - 1].ts, a = this.createSeparatorElement(o, i);
348
348
  this.messagesEl.appendChild(i), this.messagesEl.appendChild(a);
349
349
  }
350
350
  t.forEach((s) => {
@@ -412,14 +412,14 @@ class re {
412
412
  const s = document.createElement("div");
413
413
  s.className = "conversation-separator", s.setAttribute("role", "button"), s.setAttribute("tabindex", "0"), s.setAttribute("aria-expanded", "false"), s.setAttribute("aria-label", "Show previous conversation"), s.textContent = te(e);
414
414
  const i = () => {
415
- const n = t.classList.toggle("expanded");
416
- s.setAttribute("aria-expanded", String(n)), s.setAttribute(
415
+ const o = t.classList.toggle("expanded");
416
+ s.setAttribute("aria-expanded", String(o)), s.setAttribute(
417
417
  "aria-label",
418
- n ? "Hide previous conversation" : "Show previous conversation"
418
+ o ? "Hide previous conversation" : "Show previous conversation"
419
419
  );
420
420
  };
421
- return s.addEventListener("click", i), s.addEventListener("keydown", (n) => {
422
- const a = n;
421
+ return s.addEventListener("click", i), s.addEventListener("keydown", (o) => {
422
+ const a = o;
423
423
  (a.key === "Enter" || a.key === " ") && (a.preventDefault(), i());
424
424
  }), s;
425
425
  }
@@ -429,8 +429,8 @@ class re {
429
429
  let s = null;
430
430
  return e.forEach((i) => {
431
431
  this.appendDateSeparatorIfNeeded(s, i, t);
432
- const { item: n } = this.createMessageElement(i);
433
- t.appendChild(n), s = i;
432
+ const { item: o } = this.createMessageElement(i);
433
+ t.appendChild(o), s = i;
434
434
  }), t;
435
435
  }
436
436
  appendTimelineMessage(e) {
@@ -452,18 +452,18 @@ class re {
452
452
  }
453
453
  formatMessageTimestamp(e) {
454
454
  const s = Date.now() - e;
455
- if (s < $) {
455
+ if (s < N) {
456
456
  const i = Math.max(1, Math.round(s / 6e4));
457
457
  if (i < 60)
458
458
  return this.relativeTimeFormat.format(-i, "minute");
459
- const n = Math.max(1, Math.round(i / 60));
460
- return this.relativeTimeFormat.format(-n, "hour");
459
+ const o = Math.max(1, Math.round(i / 60));
460
+ return this.relativeTimeFormat.format(-o, "hour");
461
461
  }
462
462
  return this.absoluteTimeFormat.format(new Date(e));
463
463
  }
464
464
  formatDateSeparator(e) {
465
465
  const t = new Date(e), s = this.startOfDay(Date.now()), i = this.startOfDay(e);
466
- return i === s ? "Today" : i === s - $ ? "Yesterday" : this.dateSeparatorFormat.format(t);
466
+ return i === s ? "Today" : i === s - N ? "Yesterday" : this.dateSeparatorFormat.format(t);
467
467
  }
468
468
  isSameDay(e, t) {
469
469
  return this.startOfDay(e) === this.startOfDay(t);
@@ -473,7 +473,7 @@ class re {
473
473
  return new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime();
474
474
  }
475
475
  isScrolledUp() {
476
- return this.distanceFromBottom() > oe;
476
+ return this.distanceFromBottom() > re;
477
477
  }
478
478
  distanceFromBottom() {
479
479
  return this.messagesEl.scrollHeight - this.messagesEl.scrollTop - this.messagesEl.clientHeight;
@@ -520,7 +520,7 @@ class re {
520
520
  this.emojiPickerOpen && (this.emojiPickerOpen = !1, this.emojiPickerEl.style.display = "none", this.emojiButton.setAttribute("aria-expanded", "false"), this.collectFocusable());
521
521
  }
522
522
  renderEmojiPicker() {
523
- this.emojiPickerEl.replaceChildren(), ne.forEach((e) => {
523
+ this.emojiPickerEl.replaceChildren(), oe.forEach((e) => {
524
524
  const t = document.createElement("button");
525
525
  t.type = "button", t.className = "emoji-option", t.textContent = e, t.setAttribute("aria-label", `Insert ${e}`), t.addEventListener("click", () => {
526
526
  this.insertEmojiAtCursor(e), this.closeEmojiPicker();
@@ -528,11 +528,11 @@ class re {
528
528
  });
529
529
  }
530
530
  insertEmojiAtCursor(e) {
531
- var a, r;
532
- const t = this.input.value, s = (a = this.input.selectionStart) != null ? a : t.length, i = (r = this.input.selectionEnd) != null ? r : t.length;
531
+ var a, n;
532
+ const t = this.input.value, s = (a = this.input.selectionStart) != null ? a : t.length, i = (n = this.input.selectionEnd) != null ? n : t.length;
533
533
  this.input.value = `${t.slice(0, s)}${e}${t.slice(i)}`;
534
- const n = s + e.length;
535
- this.input.setSelectionRange(n, n), this.input.dispatchEvent(new Event("input", { bubbles: !0 })), this.input.focus();
534
+ const o = s + e.length;
535
+ this.input.setSelectionRange(o, o), this.input.dispatchEvent(new Event("input", { bubbles: !0 })), this.input.focus();
536
536
  }
537
537
  collectFocusable() {
538
538
  const e = this.shadow.querySelectorAll(
@@ -548,63 +548,57 @@ class re {
548
548
  e.shiftKey && i === t ? (e.preventDefault(), s.focus()) : !e.shiftKey && i === s && (e.preventDefault(), t.focus());
549
549
  }
550
550
  }
551
- function ae(o) {
552
- if (!(o instanceof HTMLElement) || o.hasAttribute("disabled") || o.getAttribute("aria-disabled") === "true" || o.hasAttribute("inert"))
551
+ function ae(r) {
552
+ if (!(r instanceof HTMLElement) || r.hasAttribute("disabled") || r.getAttribute("aria-disabled") === "true" || r.hasAttribute("inert"))
553
553
  return !1;
554
- const e = getComputedStyle(o);
554
+ const e = getComputedStyle(r);
555
555
  if (e.display === "none" || e.visibility === "hidden" || e.pointerEvents === "none")
556
556
  return !1;
557
- const t = o.tagName;
558
- if (t === "BUTTON" || t === "SELECT" || t === "TEXTAREA" || t === "A" && o.hasAttribute("href") || t === "INPUT" && o.type !== "hidden" || t === "IFRAME") return !0;
559
- const s = o.getAttribute("role");
560
- if (s === "button" || s === "link" || o.getAttribute("contenteditable") === "true") return !0;
561
- const i = o.getAttribute("tabindex");
557
+ const t = r.tagName;
558
+ if (t === "BUTTON" || t === "SELECT" || t === "TEXTAREA" || t === "A" && r.hasAttribute("href") || t === "INPUT" && r.type !== "hidden" || t === "IFRAME") return !0;
559
+ const s = r.getAttribute("role");
560
+ if (s === "button" || s === "link" || r.getAttribute("contenteditable") === "true") return !0;
561
+ const i = r.getAttribute("tabindex");
562
562
  return i !== null && i !== "-1";
563
563
  }
564
- function K(o, e, t) {
565
- const s = document.elementsFromPoint(o, e);
564
+ function K(r, e, t) {
565
+ const s = document.elementsFromPoint(r, e);
566
566
  for (const i of s) {
567
567
  if (t.has(i)) continue;
568
- let n = !1;
568
+ let o = !1;
569
569
  for (const a of t)
570
570
  if (a.contains(i)) {
571
- n = !0;
571
+ o = !0;
572
572
  break;
573
573
  }
574
- if (!n && ae(i))
574
+ if (!o && ae(i))
575
575
  return !0;
576
576
  }
577
577
  return !1;
578
578
  }
579
- function N(o, e) {
580
- const t = [
581
- [o.x + o.width / 2, o.y + o.height / 2],
582
- [o.x + o.width / 2, o.y + 4],
583
- [o.x + o.width / 2, o.y + o.height - 4],
584
- [o.x + 4, o.y + o.height / 2],
585
- [o.x + o.width - 4, o.y + o.height / 2]
586
- ];
587
- for (const [s, i] of t)
588
- if (K(s, i, e)) return !0;
579
+ function O(r, e) {
580
+ for (let s = r.x + 4; s <= r.x + r.width - 4; s += 8)
581
+ for (let i = r.y + 4; i <= r.y + r.height - 4; i += 8)
582
+ if (K(s, i, e)) return !0;
589
583
  return !1;
590
584
  }
591
585
  function F() {
592
- var o, e;
593
- return (e = (o = window.matchMedia) == null ? void 0 : o.call(window, "(pointer: coarse)").matches) != null ? e : !1;
586
+ var r, e;
587
+ return (e = (r = window.matchMedia) == null ? void 0 : r.call(window, "(pointer: coarse)").matches) != null ? e : !1;
594
588
  }
595
- function le(o) {
596
- return o === "bottom-right" ? "bottom-left" : "bottom-right";
589
+ function le(r) {
590
+ return r === "bottom-right" ? "bottom-left" : "bottom-right";
597
591
  }
598
592
  class ce {
599
593
  constructor(e) {
600
- this.rafId = 0, this.pendingX = 0, this.pendingY = 0, this.pendingUpdate = !1, this.passthrough = !1, this.cachedRect = null, this.bubble = e.bubble, this.widgetHosts = e.widgetHosts, this.currentPosition = e.position, this.handlePointerMove = (t) => this.onPointerMove(t), this.handlePointerUp = () => this.exitPassthrough(), this.handleScroll = () => this.onLayoutChange(), this.handleResize = () => this.onLayoutChange(), window.addEventListener("scroll", this.handleScroll, { passive: !0 }), window.addEventListener("resize", this.handleResize, { passive: !0 }), F() ? this.scheduleAutoDockCheck() : (document.addEventListener("pointermove", this.handlePointerMove, {
594
+ this.rafId = 0, this.pendingX = 0, this.pendingY = 0, this.pendingUpdate = !1, this.passthrough = !1, this.overlapping = !1, this.cachedRect = null, this.recheckTimer = 0, this.bubble = e.bubble, this.widgetHosts = e.widgetHosts, this.currentPosition = e.position, this.handlePointerMove = (t) => this.onPointerMove(t), this.handlePointerUp = () => this.exitPassthrough(), this.handleScroll = () => this.onLayoutChange(), this.handleResize = () => this.onLayoutChange(), window.addEventListener("scroll", this.handleScroll, { passive: !0 }), window.addEventListener("resize", this.handleResize, { passive: !0 }), F() ? this.scheduleAutoDockCheck() : (document.addEventListener("pointermove", this.handlePointerMove, {
601
595
  passive: !0
602
596
  }), document.addEventListener("pointerup", this.handlePointerUp, {
603
597
  passive: !0
604
- })), requestAnimationFrame(() => this.onLayoutChange());
598
+ })), requestAnimationFrame(() => this.onLayoutChange()), this.recheckTimer = window.setInterval(() => this.onLayoutChange(), 2e3);
605
599
  }
606
600
  destroy() {
607
- document.removeEventListener("pointermove", this.handlePointerMove), document.removeEventListener("pointerup", this.handlePointerUp), window.removeEventListener("scroll", this.handleScroll), window.removeEventListener("resize", this.handleResize), this.rafId && cancelAnimationFrame(this.rafId), this.exitPassthrough();
601
+ document.removeEventListener("pointermove", this.handlePointerMove), document.removeEventListener("pointerup", this.handlePointerUp), window.removeEventListener("scroll", this.handleScroll), window.removeEventListener("resize", this.handleResize), this.rafId && cancelAnimationFrame(this.rafId), this.recheckTimer && clearInterval(this.recheckTimer), this.exitPassthrough();
608
602
  }
609
603
  onPointerMove(e) {
610
604
  this.pendingX = e.clientX, this.pendingY = e.clientY, this.pendingUpdate || (this.pendingUpdate = !0, this.rafId = requestAnimationFrame(() => this.tick()));
@@ -616,16 +610,16 @@ class ce {
616
610
  this.passthrough && this.exitPassthrough();
617
611
  return;
618
612
  }
619
- const n = this.bubble.element, a = n.style.pointerEvents;
620
- n.style.pointerEvents = "none";
621
- const r = K(t, s, this.widgetHosts);
622
- n.style.pointerEvents = a, r && !this.passthrough ? this.enterPassthrough() : !r && this.passthrough && this.exitPassthrough();
613
+ const o = this.bubble.element, a = o.style.pointerEvents;
614
+ o.style.pointerEvents = "none";
615
+ const n = K(t, s, this.widgetHosts);
616
+ o.style.pointerEvents = a, n && !this.passthrough ? this.enterPassthrough() : !n && this.passthrough && this.exitPassthrough();
623
617
  }
624
618
  enterPassthrough() {
625
619
  this.passthrough = !0, this.bubble.setDimmed(!0), this.bubble.setPassthrough(!0);
626
620
  }
627
621
  exitPassthrough() {
628
- this.passthrough && (this.passthrough = !1, this.bubble.setDimmed(!1), this.bubble.setPassthrough(!1));
622
+ this.passthrough && (this.passthrough = !1, this.bubble.setPassthrough(!1), this.bubble.setDimmed(this.overlapping));
629
623
  }
630
624
  scheduleAutoDockCheck() {
631
625
  requestAnimationFrame(() => this.autoDockIfNeeded());
@@ -634,21 +628,27 @@ class ce {
634
628
  this.invalidateRect();
635
629
  const e = this.getBubbleRect(), t = this.bubble.element, s = t.style.pointerEvents;
636
630
  t.style.pointerEvents = "none";
637
- const i = N(e, this.widgetHosts);
631
+ const i = O(e, this.widgetHosts);
638
632
  if (t.style.pointerEvents = s, !i) return;
639
- const n = le(this.currentPosition);
640
- this.currentPosition = n, this.bubble.setPosition(n), this.invalidateRect(), requestAnimationFrame(() => {
641
- const a = this.getBubbleRect(), r = this.bubble.element, l = r.style.pointerEvents;
642
- r.style.pointerEvents = "none";
643
- const p = N(
633
+ const o = le(this.currentPosition);
634
+ this.currentPosition = o, this.bubble.setPosition(o), this.invalidateRect(), requestAnimationFrame(() => {
635
+ const a = this.getBubbleRect(), n = this.bubble.element, l = n.style.pointerEvents;
636
+ n.style.pointerEvents = "none";
637
+ const p = O(
644
638
  a,
645
639
  this.widgetHosts
646
640
  );
647
- r.style.pointerEvents = l, p && this.bubble.setDimmed(!0);
641
+ n.style.pointerEvents = l, p && this.bubble.setDimmed(!0);
648
642
  });
649
643
  }
650
644
  onLayoutChange() {
651
- this.invalidateRect(), F() && this.autoDockIfNeeded();
645
+ this.invalidateRect(), F() ? this.autoDockIfNeeded() : this.checkOverlapState();
646
+ }
647
+ checkOverlapState() {
648
+ const e = this.getBubbleRect(), t = this.bubble.element, s = t.style.pointerEvents;
649
+ t.style.pointerEvents = "none";
650
+ const i = O(e, this.widgetHosts);
651
+ t.style.pointerEvents = s, i !== this.overlapping && (this.overlapping = i, this.bubble.setDimmed(i));
652
652
  }
653
653
  getBubbleRect() {
654
654
  return this.cachedRect || (this.cachedRect = this.bubble.element.getBoundingClientRect()), this.cachedRect;
@@ -669,8 +669,8 @@ class he {
669
669
  const t = {};
670
670
  for (const [s, i] of Object.entries(e))
671
671
  if (typeof i == "string") {
672
- const n = i.trim();
673
- n && (t[s] = n);
672
+ const o = i.trim();
673
+ o && (t[s] = o);
674
674
  }
675
675
  this.user = t, this.sessionId && this.sendIdentify().catch(
676
676
  (s) => this.handlers.onError(s)
@@ -709,9 +709,9 @@ class he {
709
709
  }
710
710
  }
711
711
  async doConnect() {
712
- var a, r;
712
+ var a, n;
713
713
  this.stopped = !1;
714
- const e = `${this.options.apiBase.replace(/\/$/, "")}/widget/session`, t = (r = (a = this.sessionId) != null ? a : this.options.sessionId) != null ? r : void 0, s = {
714
+ const e = `${this.options.apiBase.replace(/\/$/, "")}/widget/session`, t = (n = (a = this.sessionId) != null ? a : this.options.sessionId) != null ? n : void 0, s = {
715
715
  organisationId: this.options.org,
716
716
  sessionId: t,
717
717
  userAgent: typeof navigator != "undefined" ? navigator.userAgent : "",
@@ -728,13 +728,13 @@ class he {
728
728
  });
729
729
  if (!i.ok)
730
730
  throw new Error(`SpilkiWidget: connect failed (${i.status})`);
731
- const n = await i.json();
732
- return this.sessionId = n.sessionId, this.options.sessionId = n.sessionId, this.backoff = v, await this.startTransport(n), n;
731
+ const o = await i.json();
732
+ return this.sessionId = o.sessionId, this.options.sessionId = o.sessionId, this.backoff = v, await this.startTransport(o), o;
733
733
  }
734
734
  async send(e, t) {
735
- var a, r, l;
735
+ var a, n, l;
736
736
  const s = {
737
- sessionId: (r = (a = this.sessionId) != null ? a : this.options.sessionId) != null ? r : "",
737
+ sessionId: (n = (a = this.sessionId) != null ? a : this.options.sessionId) != null ? n : "",
738
738
  text: e,
739
739
  ...t ? { messageId: t } : {},
740
740
  ...(l = this.user) != null && l.userId ? { userId: this.user.userId } : {}
@@ -745,7 +745,7 @@ class he {
745
745
  this.ws.send(JSON.stringify({ type: "message", payload: s }));
746
746
  return;
747
747
  }
748
- const i = `${this.options.apiBase.replace(/\/$/, "")}/widget/message`, n = await fetch(i, {
748
+ const i = `${this.options.apiBase.replace(/\/$/, "")}/widget/message`, o = await fetch(i, {
749
749
  method: "POST",
750
750
  headers: {
751
751
  "Content-Type": "application/json",
@@ -753,8 +753,8 @@ class he {
753
753
  },
754
754
  body: JSON.stringify(s)
755
755
  });
756
- if (!n.ok)
757
- throw new Error(`SpilkiWidget: send failed (${n.status})`);
756
+ if (!o.ok)
757
+ throw new Error(`SpilkiWidget: send failed (${o.status})`);
758
758
  }
759
759
  // #1: accept resetBackoff param; #8 #9: clear retryTimer
760
760
  stop(e = !0) {
@@ -784,7 +784,7 @@ class he {
784
784
  return;
785
785
  }
786
786
  this.currentKind = "ws", this.handlers.onOpen("ws"), this.backoff = v, t();
787
- }, this.wsOnMessage = (n) => this.handleIncoming(n.data), this.wsOnClose = () => {
787
+ }, this.wsOnMessage = (o) => this.handleIncoming(o.data), this.wsOnClose = () => {
788
788
  this.stopped || this.retryFallback("ws");
789
789
  }, this.wsOnError = () => {
790
790
  this.handlers.onError(new Error("SpilkiWidget: websocket error")), i.readyState !== WebSocket.OPEN && s(new Error("WebSocket failed"));
@@ -804,8 +804,8 @@ class he {
804
804
  "X-Authorization": `Bearer ${this.options.accessToken}`
805
805
  },
806
806
  signal: i.signal
807
- }).then((n) => {
808
- if (!n.ok || !n.body) {
807
+ }).then((o) => {
808
+ if (!o.ok || !o.body) {
809
809
  s(new Error("SSE failed"));
810
810
  return;
811
811
  }
@@ -814,7 +814,7 @@ class he {
814
814
  return;
815
815
  }
816
816
  this.currentKind = "sse", this.handlers.onOpen("sse"), this.backoff = v, t();
817
- const a = n.body.getReader(), r = new TextDecoder();
817
+ const a = o.body.getReader(), n = new TextDecoder();
818
818
  let l = "";
819
819
  const p = () => {
820
820
  a.read().then(({ done: u, value: h }) => {
@@ -823,7 +823,7 @@ class he {
823
823
  this.stopped || (this.handlers.onError(new Error("SpilkiWidget: SSE stream ended")), this.retryFallback("sse"));
824
824
  return;
825
825
  }
826
- l += r.decode(h, { stream: !0 });
826
+ l += n.decode(h, { stream: !0 });
827
827
  const d = l.split(`
828
828
 
829
829
  `);
@@ -838,8 +838,8 @@ class he {
838
838
  });
839
839
  };
840
840
  p();
841
- }).catch((n) => {
842
- i.signal.aborted || s(n);
841
+ }).catch((o) => {
842
+ i.signal.aborted || s(o);
843
843
  });
844
844
  });
845
845
  }
@@ -856,7 +856,7 @@ class he {
856
856
  });
857
857
  if (!s.ok) throw new Error(`Poll failed ${s.status}`);
858
858
  const i = await s.json();
859
- A(i).forEach((n) => this.handlers.onMessage(n)), this.backoff = v;
859
+ A(i).forEach((o) => this.handlers.onMessage(o)), this.backoff = v;
860
860
  } catch (s) {
861
861
  this.handlers.onError(s), this.backoff = Math.min(this.backoff * 1.5, W);
862
862
  } finally {
@@ -894,12 +894,12 @@ class he {
894
894
  }
895
895
  }
896
896
  const de = /* @__PURE__ */ new Set(["TYPING", "THINKING", "SEARCHING", "EXECUTING_TOOL"]);
897
- function ue(o) {
898
- if (typeof o != "object" || o === null) return !1;
899
- const e = o;
897
+ function ue(r) {
898
+ if (typeof r != "object" || r === null) return !1;
899
+ const e = r;
900
900
  return de.has(e.eventType);
901
901
  }
902
- const H = 30 * 60 * 1e3, pe = 3e4, O = 30;
902
+ const H = 30 * 60 * 1e3, pe = 3e4, M = 30;
903
903
  class ge {
904
904
  constructor(e, t) {
905
905
  this.org = e, this.listeners = /* @__PURE__ */ new Set(), this.activityTimer = null, this.state = {
@@ -948,10 +948,10 @@ class ge {
948
948
  author: e.author,
949
949
  text: e.text
950
950
  };
951
- return this.state.messages.some((n) => n.id === t.id) ? null : (this.state.messages = A([...this.state.messages, t], O), this.resetAgentActivity(), this.persistMessages(), this.touchActivity(), this.emit(), t);
951
+ return this.state.messages.some((o) => o.id === t.id) ? null : (this.state.messages = A([...this.state.messages, t], M), this.resetAgentActivity(), this.persistMessages(), this.touchActivity(), this.emit(), t);
952
952
  }
953
953
  setMessages(e) {
954
- this.state.messages = A(e, O), this.persistMessages(), this.emit();
954
+ this.state.messages = A(e, M), this.persistMessages(), this.emit();
955
955
  }
956
956
  clearMessages() {
957
957
  this.state.messages = [], this.persistMessages(), this.emit();
@@ -1071,14 +1071,14 @@ class ge {
1071
1071
  const e = localStorage.getItem(this.historyKey);
1072
1072
  if (!e) return [];
1073
1073
  const t = JSON.parse(e);
1074
- return Array.isArray(t) ? A(t, O) : [];
1074
+ return Array.isArray(t) ? A(t, M) : [];
1075
1075
  } catch (e) {
1076
1076
  return console.error("SpilkiWidget: unable to load messages", e), [];
1077
1077
  }
1078
1078
  }
1079
1079
  }
1080
- function me(o) {
1081
- const e = o.replace(/-/g, "+").replace(/_/g, "/"), t = e.padEnd(e.length + (4 - e.length % 4) % 4, "=");
1080
+ function me(r) {
1081
+ const e = r.replace(/-/g, "+").replace(/_/g, "/"), t = e.padEnd(e.length + (4 - e.length % 4) % 4, "=");
1082
1082
  if (typeof atob == "function")
1083
1083
  return decodeURIComponent(
1084
1084
  Array.prototype.map.call(atob(t), (i) => `%${`00${i.charCodeAt(0).toString(16)}`.slice(-2)}`).join("")
@@ -1088,9 +1088,9 @@ function me(o) {
1088
1088
  return s.from(t, "base64").toString("utf8");
1089
1089
  throw new Error("SpilkiWidget: no base64 decoder available");
1090
1090
  }
1091
- function fe(o) {
1092
- if (!o) return null;
1093
- const e = o.split(".");
1091
+ function fe(r) {
1092
+ if (!r) return null;
1093
+ const e = r.split(".");
1094
1094
  if (e.length < 2) return null;
1095
1095
  try {
1096
1096
  const t = me(e[1]);
@@ -1099,8 +1099,8 @@ function fe(o) {
1099
1099
  return console.error("SpilkiWidget: unable to parse JWT", t), null;
1100
1100
  }
1101
1101
  }
1102
- function be(o) {
1103
- const e = fe(o);
1102
+ function be(r) {
1103
+ const e = fe(r);
1104
1104
  if (!(e != null && e.exp) || typeof e.exp != "number") return !0;
1105
1105
  const t = Math.floor(Date.now() / 1e3);
1106
1106
  return e.exp < t + 60;
@@ -1117,8 +1117,8 @@ const ke = {
1117
1117
  onTransportChange() {
1118
1118
  }
1119
1119
  };
1120
- async function ye(o, e, t) {
1121
- const s = `${o.replace(/\/$/, "")}/widget/install`, i = await fetch(s, {
1120
+ async function ye(r, e, t) {
1121
+ const s = `${r.replace(/\/$/, "")}/widget/install`, i = await fetch(s, {
1122
1122
  method: "POST",
1123
1123
  headers: { "Content-Type": "application/json", Origin: window.location.origin },
1124
1124
  body: JSON.stringify({ token: e, organisationId: t })
@@ -1126,103 +1126,103 @@ async function ye(o, e, t) {
1126
1126
  if (!i.ok) throw new Error(`SpilkiWidget: install failed (${i.status})`);
1127
1127
  return (await i.json()).accessToken;
1128
1128
  }
1129
- async function we(o, e) {
1130
- const t = `${o.replace(/\/$/, "")}/widget/refresh`, s = await fetch(t, {
1129
+ async function we(r, e) {
1130
+ const t = `${r.replace(/\/$/, "")}/widget/refresh`, s = await fetch(t, {
1131
1131
  method: "POST",
1132
1132
  headers: { "X-Authorization": `Bearer ${e}`, Origin: window.location.origin }
1133
1133
  });
1134
1134
  if (!s.ok) throw new Error(`SpilkiWidget: refresh failed (${s.status})`);
1135
1135
  return (await s.json()).accessToken;
1136
1136
  }
1137
- function ve(o) {
1137
+ function ve(r) {
1138
1138
  let e = !1, t = null;
1139
1139
  const s = [], i = () => {
1140
- var r;
1141
- if (!o) return null;
1140
+ var n;
1141
+ if (!r) return null;
1142
1142
  if (t) return t;
1143
1143
  try {
1144
- const l = (r = window.AudioContext) != null ? r : window.webkitAudioContext;
1144
+ const l = (n = window.AudioContext) != null ? n : window.webkitAudioContext;
1145
1145
  if (!l) return null;
1146
1146
  t = new l();
1147
1147
  } catch {
1148
1148
  return null;
1149
1149
  }
1150
1150
  return t;
1151
- }, n = () => {
1151
+ }, o = () => {
1152
1152
  e = !0;
1153
1153
  try {
1154
- const r = i();
1155
- (r == null ? void 0 : r.state) === "suspended" && r.resume().catch(() => {
1154
+ const n = i();
1155
+ (n == null ? void 0 : n.state) === "suspended" && n.resume().catch(() => {
1156
1156
  });
1157
1157
  } catch {
1158
1158
  }
1159
- }, a = (r) => {
1159
+ }, a = (n) => {
1160
1160
  const l = () => {
1161
- n(), window.removeEventListener(r, l, !0);
1161
+ o(), window.removeEventListener(n, l, !0);
1162
1162
  };
1163
- s.push({ type: r, listener: l }), window.addEventListener(r, l, { capture: !0, passive: !0 });
1163
+ s.push({ type: n, listener: l }), window.addEventListener(n, l, { capture: !0, passive: !0 });
1164
1164
  };
1165
1165
  return a("pointerdown"), a("keydown"), {
1166
- markUserInteraction: n,
1166
+ markUserInteraction: o,
1167
1167
  play() {
1168
- if (!o || !e) return;
1169
- const r = i();
1170
- if (!r || r.state !== "running") return;
1171
- const l = r.createGain();
1172
- l.gain.value = 0.15, l.connect(r.destination);
1168
+ if (!r || !e) return;
1169
+ const n = i();
1170
+ if (!n || n.state !== "running") return;
1171
+ const l = n.createGain();
1172
+ l.gain.value = 0.15, l.connect(n.destination);
1173
1173
  const p = (h, d, y) => {
1174
- const f = r.createOscillator(), g = r.createGain();
1174
+ const f = n.createOscillator(), g = n.createGain();
1175
1175
  f.type = "sine", f.frequency.setValueAtTime(h, d), g.gain.setValueAtTime(1e-4, d), g.gain.exponentialRampToValueAtTime(1, d + 0.012), g.gain.exponentialRampToValueAtTime(1e-4, d + y), f.connect(g), g.connect(l), f.start(d), f.stop(d + y + 0.02);
1176
- }, u = r.currentTime;
1176
+ }, u = n.currentTime;
1177
1177
  p(880, u, 0.08), p(1175, u + 0.09, 0.08);
1178
1178
  },
1179
1179
  destroy() {
1180
- s.forEach(({ type: r, listener: l }) => {
1181
- window.removeEventListener(r, l, !0);
1180
+ s.forEach(({ type: n, listener: l }) => {
1181
+ window.removeEventListener(n, l, !0);
1182
1182
  }), s.length = 0, t && t.close().catch(() => {
1183
1183
  }), t = null;
1184
1184
  }
1185
1185
  };
1186
1186
  }
1187
- function z(o) {
1188
- var B, L, D, j, U;
1189
- if (!o.org)
1187
+ function z(r) {
1188
+ var L, D, j, U, R;
1189
+ if (!r.org)
1190
1190
  throw new Error("SpilkiWidget: org is required");
1191
- const e = J(o);
1191
+ const e = J(r);
1192
1192
  Q(e.allowedOriginsHint);
1193
- const t = { ...ke, ...(B = e.hooks) != null ? B : {} }, s = new ge(e.org, { persist: e.persist }), i = ve(e.sound);
1194
- let n = (L = s.accessToken) != null ? L : void 0, a = null;
1195
- const r = () => {
1193
+ const t = { ...ke, ...(L = e.hooks) != null ? L : {} }, s = new ge(e.org, { persist: e.persist }), i = ve(e.sound);
1194
+ let o = (D = s.accessToken) != null ? D : void 0, a = null;
1195
+ const n = () => {
1196
1196
  u.setBadge(s.countUnread());
1197
1197
  }, l = () => {
1198
1198
  s.markRead(), u.setBadge(0);
1199
1199
  }, p = async () => a || (a = (async () => {
1200
1200
  try {
1201
- if (n && be(n))
1201
+ if (o && be(o))
1202
1202
  try {
1203
- n = await we(e.apiBase, n), s.persistAccessToken(n), d.setAccessToken(n);
1203
+ o = await we(e.apiBase, o), s.persistAccessToken(o), d.setAccessToken(o);
1204
1204
  return;
1205
1205
  } catch {
1206
- n = void 0, s.clearAccessToken();
1206
+ o = void 0, s.clearAccessToken();
1207
1207
  }
1208
- if (!n) {
1209
- if (!o.installationToken) throw new Error("SpilkiWidget: missing installationToken");
1210
- if (!o.org) throw new Error("SpilkiWidget: missing org");
1211
- n = await ye(e.apiBase, o.installationToken, o.org), s.persistAccessToken(n), d.setAccessToken(n);
1208
+ if (!o) {
1209
+ if (!r.installationToken) throw new Error("SpilkiWidget: missing installationToken");
1210
+ if (!r.org) throw new Error("SpilkiWidget: missing org");
1211
+ o = await ye(e.apiBase, r.installationToken, r.org), s.persistAccessToken(o), d.setAccessToken(o);
1212
1212
  }
1213
1213
  } finally {
1214
1214
  a = null;
1215
1215
  }
1216
1216
  })(), a), u = G({
1217
1217
  color: e.color,
1218
- position: (D = e.position) != null ? D : "bottom-right",
1218
+ position: (j = e.position) != null ? j : "bottom-right",
1219
1219
  onClick: () => {
1220
1220
  s.snapshot.isOpen ? (s.close(), t.onClose()) : (i.markUserInteraction(), s.open(), l(), t.onOpen());
1221
1221
  }
1222
- }), h = new re({
1222
+ }), h = new ne({
1223
1223
  color: e.color,
1224
- theme: R(e.theme),
1225
- position: (j = e.position) != null ? j : "bottom-right",
1224
+ theme: $(e.theme),
1225
+ position: (U = e.position) != null ? U : "bottom-right",
1226
1226
  i18n: e.i18n,
1227
1227
  onClose: () => {
1228
1228
  s.close(), t.onClose();
@@ -1236,7 +1236,7 @@ function z(o) {
1236
1236
  }), d = new he(
1237
1237
  {
1238
1238
  apiBase: e.apiBase,
1239
- accessToken: n,
1239
+ accessToken: o,
1240
1240
  org: e.org,
1241
1241
  sessionId: s.sessionId
1242
1242
  },
@@ -1246,7 +1246,7 @@ function z(o) {
1246
1246
  },
1247
1247
  onMessage(c) {
1248
1248
  const m = c.suggestedReplies, k = s.addMessage(c);
1249
- k && (h.appendMessage(k), k.author === "bot" && m && m.length > 0 && h.setSuggestedReplies(m), !s.snapshot.isOpen && k.author === "bot" && (r(), i.play()), t.onMessage(k));
1249
+ k && (h.appendMessage(k), k.author === "bot" && m && m.length > 0 && h.setSuggestedReplies(m), !s.snapshot.isOpen && k.author === "bot" && (n(), i.play()), t.onMessage(k));
1250
1250
  },
1251
1251
  onTyping() {
1252
1252
  s.handleAgentEvent("TYPING");
@@ -1260,11 +1260,11 @@ function z(o) {
1260
1260
  }
1261
1261
  );
1262
1262
  u.mount(), h.mount();
1263
- const y = (U = e.position) != null ? U : "bottom-right", f = /* @__PURE__ */ new Set([u.element, h.element]), g = new ce({
1263
+ const y = (R = e.position) != null ? R : "bottom-right", f = /* @__PURE__ */ new Set([u.element, h.element]), g = new ce({
1264
1264
  bubble: u,
1265
1265
  widgetHosts: f,
1266
1266
  position: y
1267
- }), T = s.snapshot.messages, P = s.isSessionExpired(), x = s.getConversationGroups();
1267
+ }), T = s.snapshot.messages, B = s.isSessionExpired(), x = s.getConversationGroups();
1268
1268
  if (T.length === 0 && e.welcome) {
1269
1269
  const c = {
1270
1270
  id: "welcome",
@@ -1273,11 +1273,11 @@ function z(o) {
1273
1273
  ts: Date.now()
1274
1274
  };
1275
1275
  s.addMessage(c), h.appendMessage(c);
1276
- } else P && T.length > 0 ? h.renderWithConversations(x, []) : x.length > 1 ? h.renderWithConversations(x.slice(0, -1), x[x.length - 1].messages) : h.updateMessages(T);
1276
+ } else B && T.length > 0 ? h.renderWithConversations(x, []) : x.length > 1 ? h.renderWithConversations(x.slice(0, -1), x[x.length - 1].messages) : h.updateMessages(T);
1277
1277
  let C = !1;
1278
1278
  const _ = s.subscribe(() => {
1279
1279
  const c = s.snapshot;
1280
- if (u.setOpen(c.isOpen), h.setAgentActivity(c.agentActivity, e.i18n), h.setOffline(!c.isConnected), h.updateTheme(R(e.theme)), c.isOpen) {
1280
+ if (u.setOpen(c.isOpen), h.setAgentActivity(c.agentActivity, e.i18n), h.setOffline(!c.isConnected), h.updateTheme($(e.theme)), c.isOpen) {
1281
1281
  if (!C) {
1282
1282
  const b = s.countUnread() > 0, m = s.lastReadTs;
1283
1283
  l(), b && h.scrollToFirstUnread(m);
@@ -1285,8 +1285,8 @@ function z(o) {
1285
1285
  C = !0, h.show();
1286
1286
  } else
1287
1287
  C = !1, h.hide();
1288
- }), q = T.length === 0 || P;
1289
- r(), p().then(
1288
+ }), q = T.length === 0 || B;
1289
+ n(), p().then(
1290
1290
  () => d.connect().then((c) => {
1291
1291
  var m, k;
1292
1292
  e.persist && s.persistSession(c.sessionId), s.setConnected(!0), t.onTransportChange((m = d.kind) != null ? m : "ws");
@@ -1316,9 +1316,9 @@ function z(o) {
1316
1316
  function Ee() {
1317
1317
  var s, i;
1318
1318
  if (typeof document == "undefined") return;
1319
- const o = document.currentScript;
1320
- if (!o) return;
1321
- const e = o.dataset;
1319
+ const r = document.currentScript;
1320
+ if (!r) return;
1321
+ const e = r.dataset;
1322
1322
  if (e.autoinit === "false") return;
1323
1323
  const t = e.org;
1324
1324
  if (!t) {
@@ -1334,8 +1334,8 @@ function Ee() {
1334
1334
  });
1335
1335
  }
1336
1336
  let E = null;
1337
- typeof window != "undefined" && (window.SpilkiWidget = window.SpilkiWidget || {}, window.SpilkiWidget.init = (o) => (E = z(o), E), window.SpilkiWidget.identify = (o) => {
1338
- E ? E.identify(o) : console.warn("SpilkiWidget: call init() before identify()");
1337
+ typeof window != "undefined" && (window.SpilkiWidget = window.SpilkiWidget || {}, window.SpilkiWidget.init = (r) => (E = z(r), E), window.SpilkiWidget.identify = (r) => {
1338
+ E ? E.identify(r) : console.warn("SpilkiWidget: call init() before identify()");
1339
1339
  });
1340
1340
  Ee();
1341
1341
  export {