@paramms/chat-widget 1.0.35 โ†’ 1.0.37

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/hooks.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useState as d, useEffect as R, useRef as $, useSyncExternalStore as w, useMemo as h } from "react";
2
2
  import { RelayClient as C } from "./core.js";
3
- import { r as b, p as U } from "./uid.js";
3
+ import { r as b, p as U } from "./codec.js";
4
4
  function T(e) {
5
5
  var c;
6
6
  const l = `${e.url}|${e.token ?? ""}|${e.profileId}|${e.subjectId ?? ""}|${e.kind ?? ""}|${e.peerId ?? ""}`, o = $(null);
package/dist/index.d.ts CHANGED
@@ -47,6 +47,10 @@ export interface MountOptions {
47
47
  subject?: WidgetConfig['subject'];
48
48
  quickReplies?: string[];
49
49
  accent?: string;
50
+ /** Stack navigation: when set, the chatroom header shows a back chevron that
51
+ * calls this. Used by `<ChatApp>` so tapping a conversation opens the room and
52
+ * the back arrow returns to the list โ€” native-app style. */
53
+ onBack?: () => void;
50
54
  /** If set, shows a ๐ŸŒ translate button on incoming messages that translates
51
55
  * them into this language (ISO code or language name) via the server's
52
56
  * /translate endpoint. Omit to disable the feature. */
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  var pe = Object.defineProperty;
2
2
  var he = (o, e, i) => e in o ? pe(o, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : o[e] = i;
3
3
  var y = (o, e, i) => he(o, typeof e != "symbol" ? e + "" : e, i);
4
- import { p as fe, r as ue, a as we } from "./uid.js";
5
- import { h as Me } from "./uid.js";
4
+ import { p as fe, r as ue, a as we } from "./codec.js";
5
+ import { h as Me } from "./codec.js";
6
6
  import { P as be, C as xe, b as ge } from "./outbox.js";
7
7
  import { e as He } from "./outbox.js";
8
8
  import { E2ESession as me, extractX3DHInit as ye } from "./e2e.js";
@@ -74,6 +74,8 @@ const oe = "objectchat-widget-styles", Ce = ["๐Ÿ‘", "โค๏ธ", "๐Ÿ˜‚", "๐Ÿ˜ฎ", "
74
74
  [dir="rtl"] .ocw-input { flex-direction:row-reverse; }
75
75
  [dir="rtl"] .mine .ocw-meta { text-align:left; }
76
76
  .ocw-head { display:flex; align-items:center; gap:10px; padding:12px 14px; background:var(--ocw-card); border-bottom:1px solid var(--ocw-line); }
77
+ .ocw-back { flex:none; width:30px; height:30px; margin:-2px -2px -2px -4px; border:none; background:none; color:var(--ocw-ink); font-size:26px; line-height:1; cursor:pointer; border-radius:50%; display:flex; align-items:center; justify-content:center; }
78
+ .ocw-back:hover { background:var(--ocw-bg); }
77
79
  .ocw-avatar { width:34px; height:34px; border-radius:50%; background:#ffe9d6; display:flex; align-items:center; justify-content:center; font-size:17px; flex:none; }
78
80
  .ocw-head-main { flex:1; min-width:0; }
79
81
  .ocw-head-name { font-weight:700; font-size:15px; }
@@ -294,58 +296,63 @@ class Ee {
294
296
  y(this, "translationCache", /* @__PURE__ */ new Map());
295
297
  y(this, "showingTranslation", /* @__PURE__ */ new Set());
296
298
  y(this, "subjectBuilt", !1);
297
- var g, h, I, T, $, A, z, P, k;
299
+ var m, h, I, T, $, A, P, z, k;
298
300
  this.root = e, this.me = i, this.h = s, this.cfg = a, Ie(), e.replaceChildren(), e.classList.add("ocw"), a.accent && e.style.setProperty("--ocw-accent", a.accent);
299
- const c = t("div", "ocw-head"), f = t("div", "ocw-avatar");
300
- if ((g = a.userInfo) != null && g.avatar) {
301
- const m = document.createElement("img");
302
- m.src = a.userInfo.avatar, m.alt = a.userInfo.name ?? "You", m.style.cssText = "width:100%;height:100%;border-radius:50%;object-fit:cover", f.append(m);
301
+ const c = t("div", "ocw-head");
302
+ if (this.h.onBack) {
303
+ const x = t("button", "ocw-back", "โ€น");
304
+ x.type = "button", x.setAttribute("aria-label", "Back"), x.addEventListener("click", () => this.h.onBack()), c.append(x);
305
+ }
306
+ const f = t("div", "ocw-avatar");
307
+ if ((m = a.userInfo) != null && m.avatar) {
308
+ const x = document.createElement("img");
309
+ x.src = a.userInfo.avatar, x.alt = a.userInfo.name ?? "You", x.style.cssText = "width:100%;height:100%;border-radius:50%;object-fit:cover", f.append(x);
303
310
  } else
304
311
  f.textContent = (h = a.userInfo) != null && h.name ? a.userInfo.name[0].toUpperCase() : "๐Ÿง‘";
305
312
  c.append(f);
306
313
  const b = t("div", "ocw-head-main");
307
- this.headerName = t("div", "ocw-head-name", ((I = a.subject) == null ? void 0 : I.ownerLabel) ?? ((T = a.subject) == null ? void 0 : T.title) ?? ""), b.append(this.headerName), ($ = a.subject) != null && $.subtitle && b.append(t("div", "ocw-head-meta", a.subject.subtitle)), c.append(b), this.statusBadge = t("span", "ocw-badge", ((A = a.subject) == null ? void 0 : A.status) ?? ""), (z = a.subject) != null && z.status || (this.statusBadge.style.display = "none"), c.append(this.statusBadge), this.e2eBadge = t("span", "ocw-e2e", "๐Ÿ”’ E2E"), this.e2eBadge.style.display = "none", c.append(this.e2eBadge), this.connStatus = t("span", "ocw-conn-status"), this.connStatus.style.display = "none", c.append(this.connStatus), this.cobrowseBtn = t("button", "ocw-menu ocw-cobrowse-btn", "๐Ÿ–"), this.cobrowseBtn.title = "Shared whiteboard โ€” draw to point things out together", this.cobrowseBtn.addEventListener("click", () => {
314
+ this.headerName = t("div", "ocw-head-name", ((I = a.subject) == null ? void 0 : I.ownerLabel) ?? ((T = a.subject) == null ? void 0 : T.title) ?? ""), b.append(this.headerName), ($ = a.subject) != null && $.subtitle && b.append(t("div", "ocw-head-meta", a.subject.subtitle)), c.append(b), this.statusBadge = t("span", "ocw-badge", ((A = a.subject) == null ? void 0 : A.status) ?? ""), (P = a.subject) != null && P.status || (this.statusBadge.style.display = "none"), c.append(this.statusBadge), this.e2eBadge = t("span", "ocw-e2e", "๐Ÿ”’ E2E"), this.e2eBadge.style.display = "none", c.append(this.e2eBadge), this.connStatus = t("span", "ocw-conn-status"), this.connStatus.style.display = "none", c.append(this.connStatus), this.cobrowseBtn = t("button", "ocw-menu ocw-cobrowse-btn", "๐Ÿ–"), this.cobrowseBtn.title = "Shared whiteboard โ€” draw to point things out together", this.cobrowseBtn.addEventListener("click", () => {
308
315
  this.cobrowseActive = !this.cobrowseActive, this.updateCobrowseUI();
309
316
  }), c.append(this.cobrowseBtn), c.append(t("button", "ocw-menu", "โ‹ฏ")), this.chips = t("div", "ocw-chiprow"), this.scroll = t("div", "ocw-scroll"), this.subjectCard = t("div", "ocw-subject"), this.typing = t("div", "ocw-typing");
310
317
  const d = t("div", "ocw-typing-bubble");
311
318
  d.append(t("div", "ocw-typing-dot"), t("div", "ocw-typing-dot"), t("div", "ocw-typing-dot")), this.typing.append(t("div", "ocw-dot", "๐Ÿง‘"), d), this.quick = t("div", "ocw-quick");
312
- for (const m of a.quickReplies ?? []) {
313
- const S = t("button", void 0, m);
319
+ for (const x of a.quickReplies ?? []) {
320
+ const S = t("button", void 0, x);
314
321
  S.addEventListener("click", () => {
315
- this.h.onSend(m), this.quick.style.display = "none";
322
+ this.h.onSend(x), this.quick.style.display = "none";
316
323
  }), this.quick.append(S);
317
324
  }
318
325
  this.formHost = t("div", "ocw-form-host"), this.csatPanel = t("div", "ocw-csat"), this.csatPanel.style.display = "none", this.offlinePanel = t("div", "ocw-offline"), this.offlinePanel.style.display = "none", this.preChatPanel = t("div", "ocw-prechat"), this.preChatPanel.style.display = "none", this.deflectPanel = t("div", "ocw-deflect"), this.deflectPanel.style.display = "none", this.input = t("textarea", void 0), this.input.rows = 1, this.input.placeholder = "Messageโ€ฆ";
319
- const w = t("button", "ocw-sendbtn", ((P = a.i18n) == null ? void 0 : P.send) ?? "โžค");
326
+ const w = t("button", "ocw-sendbtn", ((z = a.i18n) == null ? void 0 : z.send) ?? "โžค");
320
327
  w.addEventListener("click", () => this.flushSend()), this.input.addEventListener("input", () => {
321
- var m, S;
322
- this.storeRef && !this.storeRef.messages().some((B) => B.senderRole === "guest") ? (S = (m = this.h).onDeflectQuery) == null || S.call(m, this.input.value) : this.hideDeflection();
323
- }), this.input.addEventListener("keydown", (m) => {
324
- m.isComposing || m.keyCode === 229 || (m.key === "Enter" && !m.shiftKey ? (m.preventDefault(), this.flushSend()) : this.signalTyping());
328
+ var x, S;
329
+ this.storeRef && !this.storeRef.messages().some((B) => B.senderRole === "guest") ? (S = (x = this.h).onDeflectQuery) == null || S.call(x, this.input.value) : this.hideDeflection();
330
+ }), this.input.addEventListener("keydown", (x) => {
331
+ x.isComposing || x.keyCode === 229 || (x.key === "Enter" && !x.shiftKey ? (x.preventDefault(), this.flushSend()) : this.signalTyping());
325
332
  });
326
333
  const v = t("button", "ocw-attach", "๐Ÿ“Ž");
327
334
  v.title = "Attach image or file";
328
335
  const r = document.createElement("input");
329
336
  r.type = "file", r.accept = "image/*,.pdf,.txt,.doc,.docx", r.style.display = "none", v.addEventListener("click", () => r.click()), r.addEventListener("change", () => {
330
- var m;
331
- (m = r.files) != null && m[0] && this.h.onAttach && this.h.onAttach(r.files[0]), r.value = "";
337
+ var x;
338
+ (x = r.files) != null && x[0] && this.h.onAttach && this.h.onAttach(r.files[0]), r.value = "";
332
339
  });
333
340
  const u = t("div", "ocw-input");
334
341
  u.append(v, r, this.input, w);
335
342
  const l = t("div", "ocw-footer");
336
343
  ((k = a.i18n) == null ? void 0 : k.poweredBy) !== void 0 ? l.textContent = a.i18n.poweredBy : l.innerHTML = 'Powered by <a href="https://relay.paramms.com" target="_blank" rel="noopener">Relay</a>', this.footer = l, e.append(c, this.chips, this.scroll, this.typing, this.quick, this.formHost, this.csatPanel, this.offlinePanel, this.preChatPanel, this.deflectPanel, u, this.footer), this.cobrowseCanvas = t("canvas", "ocw-cobrowse-canvas"), this.cobrowseToolbar = t("div", "ocw-cobrowse-toolbar");
337
- for (const m of ["#f5713c", "#1c1b1a", "#2563eb", "#16a34a", "#dc2626"]) {
344
+ for (const x of ["#f5713c", "#1c1b1a", "#2563eb", "#16a34a", "#dc2626"]) {
338
345
  const S = t("button", "ocw-cobrowse-swatch");
339
- S.style.background = m, S.type = "button", m === this.cobrowseColor && S.classList.add("sel"), S.addEventListener("click", () => {
340
- this.cobrowseColor = m;
346
+ S.style.background = x, S.type = "button", x === this.cobrowseColor && S.classList.add("sel"), S.addEventListener("click", () => {
347
+ this.cobrowseColor = x;
341
348
  for (const B of this.cobrowseToolbar.querySelectorAll(".ocw-cobrowse-swatch")) B.classList.remove("sel");
342
349
  S.classList.add("sel");
343
350
  }), this.cobrowseToolbar.append(S);
344
351
  }
345
352
  const C = t("button", "ocw-cobrowse-clear", "Clear");
346
353
  C.addEventListener("click", () => {
347
- var m, S;
348
- return (S = (m = this.h).onAnnotateClear) == null ? void 0 : S.call(m);
354
+ var x, S;
355
+ return (S = (x = this.h).onAnnotateClear) == null ? void 0 : S.call(x);
349
356
  }), this.cobrowseToolbar.append(C), this.cobrowseHint = t("div", "ocw-cobrowse-hint", "๐Ÿ– Draw to point things out โ€” visible to both sides"), e.append(this.cobrowseCanvas, this.cobrowseToolbar, this.cobrowseHint), this.bindCobrowsePointerEvents();
350
357
  }
351
358
  /** Returns the scroll container so history.ts can attach scroll listeners. */
@@ -377,7 +384,7 @@ class Ee {
377
384
  this.h.onTyping(!0, e), this.typingTimer && clearTimeout(this.typingTimer), this.typingTimer = setTimeout(() => this.h.onTyping(!1), 2e3);
378
385
  }
379
386
  render(e) {
380
- var r, u, l, C, g;
387
+ var r, u, l, C, m;
381
388
  if (this.storeRef = e, this.cobrowseBtn.classList.toggle("show", !!e.subject), !e.subject && this.cobrowseActive && (this.cobrowseActive = !1, this.updateCobrowseUI()), this.cobrowseActive && e.annotationVersion !== this.lastAnnotationVersion && (this.lastAnnotationVersion = e.annotationVersion, this.resizeCobrowseCanvas(), this.redrawCobrowse()), e.accent && this.root.style.setProperty("--ocw-accent", e.accent), this.e2eBadge.style.display = e.e2e ? "inline-flex" : "none", this.buildSubjectCard(e), e.subject) {
382
389
  const h = (r = this.cfg.subject) == null ? void 0 : r.ownerLabel;
383
390
  h && (this.headerName.textContent = h);
@@ -400,7 +407,7 @@ class Ee {
400
407
  const b = this.typing.querySelector(".ocw-typing-bubble");
401
408
  b && b.setAttribute("aria-label", f.length ? "typing" : ""), this.footer.style.display = e.whiteLabel ? "none" : "block";
402
409
  const d = e.messages().some((h) => h.senderRole === "guest");
403
- !!((u = e.preChat) != null && u.enabled) && !this.preChatDone && !d && (e.preChat.showWhen !== "offline" || e.offline) ? (this.preChatBuilt || this.buildPreChatPanel(e.preChat), this.preChatPanel.style.display = "block", this.offlinePanel.style.display = "none", (l = this.root.querySelector(".ocw-input")) == null || l.style.setProperty("display", "none")) : (this.preChatPanel.style.display = "none", e.offline ? (this.offlinePanel.style.display === "none" && this.buildOfflinePanel(e.offlineMessage), this.offlinePanel.style.display = "block", (C = this.root.querySelector(".ocw-input")) == null || C.style.setProperty("display", "none")) : (this.offlinePanel.style.display = "none", (g = this.root.querySelector(".ocw-input")) == null || g.style.removeProperty("display")));
410
+ !!((u = e.preChat) != null && u.enabled) && !this.preChatDone && !d && (e.preChat.showWhen !== "offline" || e.offline) ? (this.preChatBuilt || this.buildPreChatPanel(e.preChat), this.preChatPanel.style.display = "block", this.offlinePanel.style.display = "none", (l = this.root.querySelector(".ocw-input")) == null || l.style.setProperty("display", "none")) : (this.preChatPanel.style.display = "none", e.offline ? (this.offlinePanel.style.display === "none" && this.buildOfflinePanel(e.offlineMessage), this.offlinePanel.style.display = "block", (C = this.root.querySelector(".ocw-input")) == null || C.style.setProperty("display", "none")) : (this.offlinePanel.style.display = "none", (m = this.root.querySelector(".ocw-input")) == null || m.style.removeProperty("display")));
404
411
  const v = ["resolved", "closed", "sold", "issued", "checked_out"];
405
412
  this.h.onCsat && !this.csatSubmitted && v.includes(e.state) && e.messages().length > 0 && (this.csatPanel.style.display === "none" && this.buildCsatPanel(), this.csatPanel.style.display = "block");
406
413
  }
@@ -456,7 +463,7 @@ Message: ${c.value}`), this.offlinePanel.replaceChildren(t("div", "ocw-offline-t
456
463
  }
457
464
  const b = t("button", "ocw-offline-submit", "Start chat");
458
465
  b.addEventListener("click", () => {
459
- var u, l, C, g, h, I, T;
466
+ var u, l, C, m, h, I, T;
460
467
  const w = (u = s.email) == null ? void 0 : u.value.trim();
461
468
  if (s.email && (!w || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(w))) {
462
469
  s.email.focus();
@@ -467,7 +474,7 @@ Message: ${c.value}`), this.offlinePanel.replaceChildren(t("div", "ocw-offline-t
467
474
  (C = s.phone ?? f) == null || C.focus();
468
475
  return;
469
476
  }
470
- if (a && ((g = e.topics) != null && g.length) && !a.value) {
477
+ if (a && ((m = e.topics) != null && m.length) && !a.value) {
471
478
  a.focus();
472
479
  return;
473
480
  }
@@ -656,10 +663,10 @@ Message: ${c.value}`), this.offlinePanel.replaceChildren(t("div", "ocw-offline-t
656
663
  } else if (e.content.kind === "appointment") {
657
664
  const u = e.content, l = t("div", "ocw-appt");
658
665
  l.append(t("div", "ocw-appt-title", `๐Ÿ“… ${u.title}`)), l.append(t("div", "ocw-appt-time", new Date(u.startIso).toLocaleString() + " โ€“ " + new Date(u.endIso).toLocaleTimeString())), u.location && l.append(t("div", "ocw-appt-loc", `๐Ÿ“ ${u.location}`)), u.description && l.append(t("div", "ocw-appt-desc", u.description));
659
- const C = t("div", "ocw-appt-links"), g = document.createElement("a");
660
- g.href = u.googleUrl, g.target = "_blank", g.rel = "noopener", g.className = "ocw-appt-btn", g.textContent = "๐Ÿ“… Add to Google Calendar";
666
+ const C = t("div", "ocw-appt-links"), m = document.createElement("a");
667
+ m.href = u.googleUrl, m.target = "_blank", m.rel = "noopener", m.className = "ocw-appt-btn", m.textContent = "๐Ÿ“… Add to Google Calendar";
661
668
  const h = document.createElement("a");
662
- h.href = u.icalUrl, h.download = `${u.title}.ics`, h.className = "ocw-appt-btn ocw-appt-btn-sec", h.textContent = "๐ŸŽ Apple / iCal", C.append(g, h), l.append(C), d.append(l);
669
+ h.href = u.icalUrl, h.download = `${u.title}.ics`, h.className = "ocw-appt-btn ocw-appt-btn-sec", h.textContent = "๐ŸŽ Apple / iCal", C.append(m, h), l.append(C), d.append(l);
663
670
  } else
664
671
  w = document.createTextNode(W(e.content)), d.append(w), e.editedAt && d.append(t("span", "ocw-edited", "(edited)"));
665
672
  if (b.append(d), !s && !a && this.h.onTranslate && e.content.kind === "text" && !e.deletedAt && e.seq > 0 && w) {
@@ -671,9 +678,9 @@ Message: ${c.value}`), this.offlinePanel.replaceChildren(t("div", "ocw-offline-t
671
678
  this.showingTranslation.delete(e.id), w.textContent = u, l.textContent = "๐ŸŒ", l.title = "Translate";
672
679
  return;
673
680
  }
674
- const g = this.translationCache.get(e.id);
675
- if (g !== void 0) {
676
- this.showingTranslation.add(e.id), w.textContent = g, l.textContent = "โ†ฉ", l.title = "Show original";
681
+ const m = this.translationCache.get(e.id);
682
+ if (m !== void 0) {
683
+ this.showingTranslation.add(e.id), w.textContent = m, l.textContent = "โ†ฉ", l.title = "Show original";
677
684
  return;
678
685
  }
679
686
  l.textContent = "โณ", this.h.onTranslate(u).then((h) => {
@@ -694,8 +701,8 @@ Message: ${c.value}`), this.offlinePanel.replaceChildren(t("div", "ocw-offline-t
694
701
  const l = t("button", void 0, "โœ๏ธ");
695
702
  l.title = "Edit", l.addEventListener("click", (C) => {
696
703
  C.stopPropagation();
697
- const g = W(e.content), h = document.createElement("textarea");
698
- h.value = g, h.rows = Math.min(4, Math.ceil(g.length / 40) + 1), h.style.cssText = "width:100%;resize:vertical;border:1px solid var(--ocw-accent);border-radius:8px;padding:6px 10px;font:inherit;font-size:14px;background:#fff;color:#1c1b1a;box-sizing:border-box";
704
+ const m = W(e.content), h = document.createElement("textarea");
705
+ h.value = m, h.rows = Math.min(4, Math.ceil(m.length / 40) + 1), h.style.cssText = "width:100%;resize:vertical;border:1px solid var(--ocw-accent);border-radius:8px;padding:6px 10px;font:inherit;font-size:14px;background:#fff;color:#1c1b1a;box-sizing:border-box";
699
706
  const I = t("button", "ocw-form-submit", "Save");
700
707
  I.style.cssText = "margin-top:6px;padding:5px 14px;font-size:13px";
701
708
  const T = t("button", "ocw-form-cancel", "Cancel");
@@ -704,12 +711,12 @@ Message: ${c.value}`), this.offlinePanel.replaceChildren(t("div", "ocw-offline-t
704
711
  $.style.cssText = "display:flex;gap:6px;justify-content:flex-end", $.append(T, I);
705
712
  const A = t("div");
706
713
  A.append(h, $), d.replaceChildren(A), h.focus(), h.select();
707
- const z = () => d.replaceChildren(w ?? document.createTextNode(g));
708
- T.addEventListener("click", z), I.addEventListener("click", () => {
709
- const P = h.value.trim();
710
- P && P !== g && this.h.onEdit(e.id, P), z();
711
- }), h.addEventListener("keydown", (P) => {
712
- P.key === "Enter" && !P.shiftKey && (P.preventDefault(), I.click()), P.key === "Escape" && z();
714
+ const P = () => d.replaceChildren(w ?? document.createTextNode(m));
715
+ T.addEventListener("click", P), I.addEventListener("click", () => {
716
+ const z = h.value.trim();
717
+ z && z !== m && this.h.onEdit(e.id, z), P();
718
+ }), h.addEventListener("keydown", (z) => {
719
+ z.key === "Enter" && !z.shiftKey && (z.preventDefault(), I.click()), z.key === "Escape" && P();
713
720
  });
714
721
  }), u.append(l);
715
722
  }
@@ -731,31 +738,31 @@ Message: ${c.value}`), this.offlinePanel.replaceChildren(t("div", "ocw-offline-t
731
738
  return (A = ($ = this.h).onReact) == null ? void 0 : A.call($, e.id, h, I.includes(this.me));
732
739
  }), l.append(T);
733
740
  }
734
- const C = t("button", "ocw-react-btn", "๏ผ‹"), g = t("div", "ocw-react-picker");
741
+ const C = t("button", "ocw-react-btn", "๏ผ‹"), m = t("div", "ocw-react-picker");
735
742
  for (const h of Ce) {
736
743
  const I = t("button", void 0, h);
737
744
  I.addEventListener("click", (T) => {
738
- var A, z, P, k;
745
+ var A, P, z, k;
739
746
  T.stopPropagation();
740
- const $ = (z = (A = e.reactions) == null ? void 0 : A[h]) == null ? void 0 : z.includes(this.me);
741
- (k = (P = this.h).onReact) == null || k.call(P, e.id, h, !!$), g.style.display = "none";
742
- }), g.append(I);
747
+ const $ = (P = (A = e.reactions) == null ? void 0 : A[h]) == null ? void 0 : P.includes(this.me);
748
+ (k = (z = this.h).onReact) == null || k.call(z, e.id, h, !!$), m.style.display = "none";
749
+ }), m.append(I);
743
750
  }
744
- g.style.display = "none", C.addEventListener("click", (h) => {
745
- h.stopPropagation(), g.style.display = g.style.display === "none" ? "flex" : "none";
751
+ m.style.display = "none", C.addEventListener("click", (h) => {
752
+ h.stopPropagation(), m.style.display = m.style.display === "none" ? "flex" : "none";
746
753
  }), document.addEventListener("click", () => {
747
- g.style.display = "none";
748
- }, { once: !0 }), l.append(C), u.append(l, g), f.append(u);
754
+ m.style.display = "none";
755
+ }, { once: !0 }), l.append(C), u.append(l, m), f.append(u);
749
756
  } else e.reactions && Object.keys(e.reactions).length && f.append(t("div", "ocw-react", Object.entries(e.reactions).map(([u, l]) => `${u}${l.length}`).join(" ")));
750
757
  const v = t("div", "ocw-time ocw-meta", Se(e.ts));
751
758
  if (s && e.status) {
752
- const u = t("span", `ocw-tick${e.status === "read" ? " read" : e.status === "delivered" ? " delivered" : ""}`, Pe(e.status));
759
+ const u = t("span", `ocw-tick${e.status === "read" ? " read" : e.status === "delivered" ? " delivered" : ""}`, ze(e.status));
753
760
  v.append(u);
754
761
  }
755
762
  return s && e.seq > 0 && i.lastReadByOthers >= e.seq && v.append(t("span", "ocw-seen", " ยท Seen")), f.append(v), c.append(f), c;
756
763
  }
757
764
  }
758
- function Pe(o) {
765
+ function ze(o) {
759
766
  switch (o) {
760
767
  case "read":
761
768
  return "โœ“โœ“";
@@ -786,12 +793,12 @@ function Be(o) {
786
793
  let r, u = !1, l = null, C = null;
787
794
  !o.launcher && !o.el.style.height && o.el.clientHeight === 0 && (o.el.style.width = o.el.style.width || "100%", o.el.style.height = "600px");
788
795
  for (const n of v.load()) d.addOptimistic(n.clientMsgId, n.content);
789
- let g = null, h = null, I = 0, T = !o.launcher;
796
+ let m = null, h = null, I = 0, T = !o.launcher;
790
797
  if (o.launcher) {
791
798
  const p = (o.position ?? "bottom-right").includes("right");
792
- g = document.createElement("div"), g.style.cssText = `position:fixed;${p ? "right:20px" : "left:20px"};bottom:20px;z-index:9999;display:flex;flex-direction:column;align-items:${p ? "flex-end" : "flex-start"};gap:12px`;
793
- const x = document.createElement("div"), E = typeof window < "u" ? window.matchMedia("(max-width: 479px)") : null, O = (q) => {
794
- x.style.cssText = q ? [
799
+ m = document.createElement("div"), m.style.cssText = `position:fixed;${p ? "right:20px" : "left:20px"};bottom:20px;z-index:9999;display:flex;flex-direction:column;align-items:${p ? "flex-end" : "flex-start"};gap:12px`;
800
+ const g = document.createElement("div"), E = typeof window < "u" ? window.matchMedia("(max-width: 479px)") : null, O = (q) => {
801
+ g.style.cssText = q ? [
795
802
  "position:fixed",
796
803
  "inset:0",
797
804
  "width:100%",
@@ -822,7 +829,7 @@ function Be(o) {
822
829
  };
823
830
  O((E == null ? void 0 : E.matches) ?? !1);
824
831
  const N = (q) => O(q.matches);
825
- E == null || E.addEventListener("change", N), l = E, C = N, o.el.style.cssText = "width:100%;height:100%;overflow:hidden", x.append(o.el);
832
+ E == null || E.addEventListener("change", N), l = E, C = N, o.el.style.cssText = "width:100%;height:100%;overflow:hidden", g.append(o.el);
826
833
  const L = document.createElement("button");
827
834
  L.style.cssText = [
828
835
  "width:56px;height:56px;border-radius:50%",
@@ -835,12 +842,12 @@ function Be(o) {
835
842
  L.style.transform = "scale(1.08)";
836
843
  }, L.onmouseleave = () => {
837
844
  L.style.transform = "scale(1)";
838
- }, h = document.createElement("span"), h.style.cssText = "position:absolute;top:-4px;right:-4px;background:#ef4444;color:#fff;border-radius:50%;width:20px;height:20px;font-size:11px;font-weight:700;display:none;align-items:center;justify-content:center", L.append(h), g.append(x, L), document.body.append(g);
845
+ }, h = document.createElement("span"), h.style.cssText = "position:absolute;top:-4px;right:-4px;background:#ef4444;color:#fff;border-radius:50%;width:20px;height:20px;font-size:11px;font-weight:700;display:none;align-items:center;justify-content:center", L.append(h), m.append(g, L), document.body.append(m);
839
846
  const _ = (q) => {
840
- q ? (x.style.display = "flex", requestAnimationFrame(() => {
841
- x.style.opacity = "1", x.style.transform = "scale(1)";
842
- })) : (x.style.opacity = "0", x.style.transform = "scale(.95)", setTimeout(() => {
843
- T || (x.style.display = "none");
847
+ q ? (g.style.display = "flex", requestAnimationFrame(() => {
848
+ g.style.opacity = "1", g.style.transform = "scale(1)";
849
+ })) : (g.style.opacity = "0", g.style.transform = "scale(.95)", setTimeout(() => {
850
+ T || (g.style.display = "none");
844
851
  }, 180));
845
852
  };
846
853
  L.addEventListener("click", () => {
@@ -853,27 +860,27 @@ function Be(o) {
853
860
  T || (I++, h && (h.textContent = String(I), h.style.display = "flex"));
854
861
  }, A = () => {
855
862
  try {
856
- const n = new AudioContext(), p = n.createOscillator(), x = n.createGain();
857
- p.connect(x), x.connect(n.destination), p.frequency.setValueAtTime(880, n.currentTime), p.frequency.exponentialRampToValueAtTime(440, n.currentTime + 0.15), x.gain.setValueAtTime(0.3, n.currentTime), x.gain.exponentialRampToValueAtTime(1e-3, n.currentTime + 0.3), p.start(), p.stop(n.currentTime + 0.3);
863
+ const n = new AudioContext(), p = n.createOscillator(), g = n.createGain();
864
+ p.connect(g), g.connect(n.destination), p.frequency.setValueAtTime(880, n.currentTime), p.frequency.exponentialRampToValueAtTime(440, n.currentTime + 0.15), g.gain.setValueAtTime(0.3, n.currentTime), g.gain.exponentialRampToValueAtTime(1e-3, n.currentTime + 0.3), p.start(), p.stop(n.currentTime + 0.3);
858
865
  } catch {
859
866
  }
860
- }, z = [], P = (n) => {
861
- for (; z.length; ) {
862
- const p = z.shift();
867
+ }, P = [], z = (n) => {
868
+ for (; P.length; ) {
869
+ const p = P.shift();
863
870
  v.add({ clientMsgId: p.clientMsgId, content: p.content, ts: Date.now() }), k.send({ type: "send", conversationId: n, clientMsgId: p.clientMsgId, content: p.content });
864
871
  }
865
872
  };
866
873
  let k;
867
- const m = new me(`ocw-e2e-${o.profileId}`);
874
+ const x = new me(`ocw-e2e-${o.profileId}`);
868
875
  let S = !1;
869
876
  const B = [], D = [];
870
877
  let Y = !1;
871
878
  const F = (n, p) => {
872
- m.sealText(p).then((x) => {
873
- r && k.send({ type: "send", conversationId: r, clientMsgId: n, content: x });
879
+ x.sealText(p).then((g) => {
880
+ r && k.send({ type: "send", conversationId: r, clientMsgId: n, content: g });
874
881
  });
875
- }, ie = (n, p, x) => {
876
- m.sealText(p, x).then((E) => {
882
+ }, ie = (n, p, g) => {
883
+ x.sealText(p, g).then((E) => {
877
884
  r && k.send({ type: "send", conversationId: r, clientMsgId: n, content: E });
878
885
  });
879
886
  }, se = () => {
@@ -891,24 +898,29 @@ function Be(o) {
891
898
  ce.includes(le) && !o.el.dir && (o.el.dir = "rtl", o.el.style.fontFamily = o.el.style.fontFamily || "Tahoma,Arial,system-ui,sans-serif");
892
899
  const K = new ke(), V = `oc_prechat_${o.profileId}_${a.slice(-8)}`, j = new Ee(o.el, a, {
893
900
  onSend(n) {
894
- const p = `cm_${Math.random().toString(36).slice(2)}`, x = { kind: "text", text: n };
895
- d.addOptimistic(p, x), j.render(d), d.e2e ? m.ready ? F(p, n) : Y ? D.push({ clientMsgId: p, text: n }) : (B.push({ clientMsgId: p, text: n }), d.assignedAgentId && ae(d.assignedAgentId)) : r ? (v.add({ clientMsgId: p, content: x, ts: Date.now() }), k.send({ type: "send", conversationId: r, clientMsgId: p, content: x })) : z.push({ clientMsgId: p, content: x });
901
+ const p = `cm_${Math.random().toString(36).slice(2)}`, g = { kind: "text", text: n };
902
+ d.addOptimistic(p, g), j.render(d), d.e2e ? x.ready ? F(p, n) : Y ? D.push({ clientMsgId: p, text: n }) : (B.push({ clientMsgId: p, text: n }), d.assignedAgentId && ae(d.assignedAgentId)) : r ? (v.add({ clientMsgId: p, content: g, ts: Date.now() }), k.send({ type: "send", conversationId: r, clientMsgId: p, content: g })) : P.push({ clientMsgId: p, content: g });
896
903
  },
897
904
  async onAttach(n) {
898
905
  if (!r) return;
899
- const p = `${b}/upload?name=${encodeURIComponent(n.name)}`, x = `cm_${Math.random().toString(36).slice(2)}`;
900
- d.addOptimistic(x, { kind: "text", text: `๐Ÿ“Ž Uploading ${n.name}โ€ฆ` }), j.render(d);
906
+ const p = `${b}/upload?name=${encodeURIComponent(n.name)}`, g = `cm_${Math.random().toString(36).slice(2)}`;
907
+ d.addOptimistic(g, { kind: "text", text: `๐Ÿ“Ž Uploading ${n.name}โ€ฆ` }), j.render(d);
901
908
  try {
902
909
  const E = await fetch(p, {
903
910
  method: "POST",
904
- headers: { "content-type": n.type, ...o.token ? { authorization: `Bearer ${o.token}` } : {} },
911
+ // Use the resolved connection token (a signed JWT, an explicit userId,
912
+ // or the anonymous persistent uid) โ€” NOT just opts.token. The server
913
+ // requires an Authorization header, and the verifier accepts an
914
+ // anonymous id as a guest; keying off opts.token alone meant anonymous
915
+ // visitors (the common case) sent no auth and every upload 401'd.
916
+ headers: { "content-type": n.type, authorization: `Bearer ${a}` },
905
917
  body: n
906
918
  });
907
919
  if (!E.ok) throw new Error(`Upload failed: ${E.status}`);
908
920
  const { url: O, name: N, mime: L, size: _ } = await E.json();
909
- k.send({ type: "send", conversationId: r, clientMsgId: x, content: { kind: "attachment", url: O, name: N, mime: L, size: _ } });
921
+ k.send({ type: "send", conversationId: r, clientMsgId: g, content: { kind: "attachment", url: O, name: N, mime: L, size: _ } });
910
922
  } catch (E) {
911
- d.addOptimistic(x, { kind: "text", text: `โš ๏ธ Upload failed: ${E.message}` }), j.render(d);
923
+ d.addOptimistic(g, { kind: "text", text: `โš ๏ธ Upload failed: ${E.message}` }), j.render(d);
912
924
  }
913
925
  },
914
926
  onInvoke(n, p) {
@@ -947,7 +959,7 @@ function Be(o) {
947
959
  return;
948
960
  }
949
961
  i = setTimeout(() => {
950
- fetch(`${b}/kb/search?profileId=${encodeURIComponent(o.profileId)}&q=${encodeURIComponent(p.slice(0, 200))}`).then((x) => x.ok ? x.json() : { articles: [] }).then((x) => j.showDeflection(x.articles ?? [])).catch(() => j.hideDeflection());
962
+ fetch(`${b}/kb/search?profileId=${encodeURIComponent(o.profileId)}&q=${encodeURIComponent(p.slice(0, 200))}`).then((g) => g.ok ? g.json() : { articles: [] }).then((g) => j.showDeflection(g.articles ?? [])).catch(() => j.hideDeflection());
951
963
  }, 350);
952
964
  },
953
965
  onReadUpTo(n) {
@@ -964,8 +976,8 @@ function Be(o) {
964
976
  onDelete(n) {
965
977
  r && k.send({ type: "delete", conversationId: r, messageId: n });
966
978
  },
967
- onReact(n, p, x) {
968
- r && k.send({ type: "react", conversationId: r, messageId: n, emoji: p, remove: x });
979
+ onReact(n, p, g) {
980
+ r && k.send({ type: "react", conversationId: r, messageId: n, emoji: p, remove: g });
969
981
  },
970
982
  onCsat(n) {
971
983
  r && fetch(`${b}/conversations/${r}/csat`, {
@@ -990,13 +1002,14 @@ function Be(o) {
990
1002
  body: JSON.stringify({ text: n, targetLang: o.translateLang })
991
1003
  });
992
1004
  if (!p.ok) return null;
993
- const { translated: x } = await p.json();
994
- return x;
1005
+ const { translated: g } = await p.json();
1006
+ return g;
995
1007
  } catch {
996
1008
  return null;
997
1009
  }
998
1010
  }
999
- } : {}
1011
+ } : {},
1012
+ ...o.onBack ? { onBack: o.onBack } : {}
1000
1013
  }, {
1001
1014
  ...o.subject ? { subject: o.subject } : {},
1002
1015
  ...o.quickReplies ? { quickReplies: o.quickReplies } : {},
@@ -1043,45 +1056,45 @@ function Be(o) {
1043
1056
  for (const p of v.load())
1044
1057
  k.send({ type: "send", conversationId: r, clientMsgId: p.clientMsgId, content: p.content });
1045
1058
  }
1046
- we(f, a, r, d, j, b), z.length && P(r);
1059
+ we(f, a, r, d, j, b), P.length && z(r);
1047
1060
  }
1048
1061
  if (n.type === "ack" && v.remove(n.clientMsgId), n.type === "prekeyBundle") {
1049
- n.bundle && (Y = !0, m.x3dhSendTo(n.bundle).then((p) => {
1050
- const x = [...B.splice(0), ...D.splice(0)];
1051
- for (const E of x) ie(E.clientMsgId, E.text, p);
1062
+ n.bundle && (Y = !0, x.x3dhSendTo(n.bundle).then((p) => {
1063
+ const g = [...B.splice(0), ...D.splice(0)];
1064
+ for (const E of g) ie(E.clientMsgId, E.text, p);
1052
1065
  j.render(d);
1053
1066
  }));
1054
1067
  return;
1055
1068
  }
1056
1069
  if (n.type === "message" && d.e2e) {
1057
1070
  const p = ye(n.message.content);
1058
- if (p && !m.ready) {
1059
- m.x3dhReceiveFrom(p.x3dhIK, p.x3dhEK, p.x3dhSPK).then(async () => {
1060
- await m.openFrame(n), d.apply(n), j.render(d);
1071
+ if (p && !x.ready) {
1072
+ x.x3dhReceiveFrom(p.x3dhIK, p.x3dhEK, p.x3dhSPK).then(async () => {
1073
+ await x.openFrame(n), d.apply(n), j.render(d);
1061
1074
  });
1062
1075
  return;
1063
1076
  }
1064
1077
  }
1065
1078
  if (n.type === "peerkey") {
1066
- m.onPeerKey(n.key).then(() => {
1079
+ x.onPeerKey(n.key).then(() => {
1067
1080
  se(), j.render(d);
1068
1081
  });
1069
1082
  return;
1070
1083
  }
1071
1084
  (async () => {
1072
- if (d.e2e && await m.openFrame(n), d.apply(n), n.type === "message" && n.message.senderId !== a && !n.message.internal && ($(), A()), d.e2e && r && !S) {
1085
+ if (d.e2e && await x.openFrame(n), d.apply(n), n.type === "message" && n.message.senderId !== a && !n.message.internal && ($(), A()), d.e2e && r && !S) {
1073
1086
  S = !0;
1074
- const p = await m.initX3DH();
1087
+ const p = await x.initX3DH();
1075
1088
  k.send({ type: "uploadPrekeys", ...p });
1076
- const x = await m.begin();
1077
- k.send({ type: "pubkey", conversationId: r, key: x });
1089
+ const g = await x.begin();
1090
+ k.send({ type: "pubkey", conversationId: r, key: g });
1078
1091
  }
1079
1092
  j.render(d);
1080
1093
  })();
1081
1094
  }
1082
1095
  }), k.connect(), j.render(d);
1083
1096
  const M = o.launcher ? ne(o) : null, H = { close: () => {
1084
- s = !0, clearTimeout(i), k.close(), g == null || g.remove(), j.destroy(), K.destroy(), l && C && l.removeEventListener("change", C), R.delete(o.el), M && U.get(M) === H && U.delete(M);
1097
+ s = !0, clearTimeout(i), k.close(), m == null || m.remove(), j.destroy(), K.destroy(), l && C && l.removeEventListener("change", C), R.delete(o.el), M && U.get(M) === H && U.delete(M);
1085
1098
  } };
1086
1099
  return R.set(o.el, H), M && U.set(M, H), H;
1087
1100
  }