@paramms/chat-widget 1.0.44 → 1.0.46

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/index.js CHANGED
@@ -1,63 +1,18 @@
1
- var Le = Object.defineProperty;
2
- var je = (t, e, i) => e in t ? Le(t, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : t[e] = i;
3
- var y = (t, e, i) => je(t, typeof e != "symbol" ? e + "" : e, i);
4
- import { p as Pe, r as Ae, a as Be } from "./codec.js";
1
+ var Be = Object.defineProperty;
2
+ var $e = (t, e, l) => e in t ? Be(t, e, { enumerable: !0, configurable: !0, writable: !0, value: l }) : t[e] = l;
3
+ var T = (t, e, l) => $e(t, typeof e != "symbol" ? e + "" : e, l);
4
+ import { l as Me, b as ge, p as Re, r as Ae, a as qe } from "./codec.js";
5
5
  import { h as st } from "./codec.js";
6
- import { P as $e, C as Me, b as Re } from "./outbox.js";
7
- import { e as rt } from "./outbox.js";
8
- import { E2ESession as qe, extractX3DHInit as Ne } from "./e2e.js";
9
- const xe = "http://www.w3.org/2000/svg", De = 8e3;
10
- class Oe {
11
- constructor() {
12
- y(this, "svg", null);
13
- y(this, "timers", /* @__PURE__ */ new Set());
14
- }
15
- /** Feed every server frame; the overlay reacts to annotation frames only. */
16
- apply(e) {
17
- var i;
18
- if (e.type === "annotation") this.draw(e.stroke);
19
- else if (e.type === "annotation_clear") this.clear();
20
- else if (e.type === "opened" && ((i = e.annotations) != null && i.length))
21
- for (const s of e.annotations) this.draw(s);
22
- }
23
- ensureSvg() {
24
- var i;
25
- if ((i = this.svg) != null && i.isConnected) return this.svg;
26
- const e = document.createElementNS(xe, "svg");
27
- return e.setAttribute("data-relay-annotations", ""), e.setAttribute("aria-hidden", "true"), e.setAttribute(
28
- "style",
29
- "position:fixed;inset:0;width:100vw;height:100vh;pointer-events:none;z-index:2147483000;"
30
- ), document.body.append(e), this.svg = e, e;
31
- }
32
- draw(e) {
33
- var b;
34
- if (typeof document > "u" || !((b = e.points) != null && b.length)) return;
35
- const i = this.ensureSvg(), s = window.innerWidth, a = window.innerHeight, c = document.createElementNS(xe, "polyline");
36
- c.setAttribute("points", e.points.map((l) => `${(l.x * s).toFixed(1)},${(l.y * a).toFixed(1)}`).join(" ")), c.setAttribute("fill", "none"), c.setAttribute("stroke", e.color || "#ff3b30"), c.setAttribute("stroke-width", String(e.width || 3)), c.setAttribute("stroke-linecap", "round"), c.setAttribute("stroke-linejoin", "round"), c.setAttribute("data-stroke-id", e.id), i.append(c);
37
- const w = setTimeout(() => {
38
- c.style.transition = "opacity 600ms", c.style.opacity = "0";
39
- const l = setTimeout(() => {
40
- c.remove(), this.timers.delete(l);
41
- }, 650);
42
- this.timers.add(l), this.timers.delete(w);
43
- }, De);
44
- this.timers.add(w);
45
- }
46
- clear() {
47
- var e;
48
- (e = this.svg) == null || e.replaceChildren();
49
- }
50
- destroy() {
51
- var e;
52
- for (const i of this.timers) clearTimeout(i);
53
- this.timers.clear(), (e = this.svg) == null || e.remove(), this.svg = null;
54
- }
55
- }
56
- const ge = "objectchat-widget-styles", He = ["👍", "❤️", "😂", "😮", "😢", "🙏"], _e = 400, Fe = '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M22 2 11 13M22 2l-7 20-4-9-9-4 20-7z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>', Ue = `
57
- .ocw { --ocw-accent:#4F63F5; --ocw-bg:#f3efe9; --ocw-card:#fff; --ocw-line:#ececec; --ocw-ink:#1c1b1a; --ocw-mut:#9b9690;
6
+ import { P as Ne, C as Oe, b as De } from "./outbox.js";
7
+ import { e as dt } from "./outbox.js";
8
+ import { E2ESession as He, extractX3DHInit as _e } from "./e2e.js";
9
+ const Ue = `
10
+ .ocw { ${Me("ocw")}
58
11
  position:relative;
59
12
  display:flex; flex-direction:column; height:100%; min-height:320px; background:var(--ocw-bg);
60
- font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif; color:var(--ocw-ink); overflow:hidden; }
13
+ font-family:var(--ocw-fb); color:var(--ocw-ink); overflow:hidden; }
14
+ @media (prefers-color-scheme: dark) { .ocw:not([data-theme="light"]) { ${ge("ocw")} } }
15
+ .ocw[data-theme="dark"] { ${ge("ocw")} }
61
16
  /* ── Responsive sizing ──────────────────────────────────────────────────────
62
17
  * Sizing is driven by the WIDGET'S OWN width (ResizeObserver toggles
63
18
  * .ocw-compact below 400px), not the viewport — so a widget embedded in a
@@ -79,38 +34,45 @@ const ge = "objectchat-widget-styles", He = ["👍", "❤️", "😂", "😮", "
79
34
  /* RTL support: when the host element has dir=rtl, flip layout direction */
80
35
  [dir="rtl"] .ocw-row.mine { flex-direction:row; }
81
36
  [dir="rtl"] .ocw-row.theirs { flex-direction:row-reverse; }
82
- [dir="rtl"] .mine .ocw-bubble { border-bottom-right-radius:18px; border-bottom-left-radius:6px; }
83
- [dir="rtl"] .theirs .ocw-bubble { border-bottom-left-radius:18px; border-bottom-right-radius:6px; }
37
+ [dir="rtl"] .mine .ocw-bubble { border-bottom-right-radius:18px; border-bottom-left-radius:4px; }
38
+ [dir="rtl"] .theirs .ocw-bubble { border-bottom-left-radius:18px; border-bottom-right-radius:4px; }
84
39
  [dir="rtl"] .ocw-input { flex-direction:row-reverse; }
85
40
  [dir="rtl"] .mine .ocw-meta { text-align:left; }
86
41
  .ocw-head { display:flex; align-items:center; gap:10px; padding:12px 14px; background:var(--ocw-card); border-bottom:1px solid var(--ocw-line); }
87
42
  .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; }
88
43
  .ocw-back:hover { background:var(--ocw-bg); }
89
- .ocw-avatar { width:34px; height:34px; border-radius:50%; background:#ffe9d6; display:flex; align-items:center; justify-content:center; font-size:17px; flex:none; }
44
+ .ocw-avatar { width:34px; height:34px; border-radius:50%; background:var(--ocw-tint); color:var(--ocw-accent); font-family:var(--ocw-fh); font-weight:600; display:flex; align-items:center; justify-content:center; font-size:13px; flex:none; }
90
45
  .ocw-head-main { flex:1; min-width:0; }
91
- .ocw-head-name { font-weight:700; font-size:15px; }
46
+ .ocw-head-name { font-family:var(--ocw-fh); font-weight:600; font-size:15px; }
92
47
  .ocw-head-meta { color:var(--ocw-mut); font-size:12px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
93
- .ocw-badge { font-size:12px; font-weight:600; color:#15803d; background:#e8f6ec; border-radius:999px; padding:3px 10px; }
94
- .ocw-e2e { font-size:11px; font-weight:700; color:#3730a3; background:#eef2ff; border-radius:999px; padding:3px 9px; align-items:center; }
95
- .ocw-menu { color:var(--ocw-mut); width:30px; height:30px; border-radius:50%; border:1px solid var(--ocw-line); background:#fff; cursor:pointer; }
48
+ .ocw-head-status { font-size:10.5px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
49
+ .ocw-head-status.online { color:#5cb37a; }
50
+ .ocw-head-status.away { color:#c98b2e; }
51
+ .ocw-msg-sender { font-size:10px; color:var(--ocw-mut); margin-bottom:2px; }
52
+ .ocw-resolved-note { text-align:center; font-size:10.5px; color:var(--ocw-mut); margin:6px 0 12px; }
53
+ .ocw-reopen { display:none; width:calc(100% - 32px); margin:0 16px 14px; height:40px; border:1.5px solid var(--ocw-accent); color:var(--ocw-accent); background:none; border-radius:20px; font:inherit; font-size:13.5px; font-weight:600; cursor:pointer; }
54
+ .ocw-reopen:hover { background:var(--ocw-tint); }
55
+ .ocw-badge { font-size:11px; font-weight:600; color:#2f8a52; background:#eafaf0; border-radius:20px; padding:5px 12px; }
56
+ .ocw-e2e { font-size:11px; font-weight:700; color:var(--ocw-accent); background:var(--ocw-tint); border-radius:20px; padding:5px 12px; align-items:center; }
57
+ .ocw-menu { color:var(--ocw-mut); width:30px; height:30px; border-radius:50%; border:1px solid var(--ocw-line); background:var(--ocw-card); cursor:pointer; }
96
58
  .ocw-chiprow { display:flex; gap:8px; padding:10px 12px; background:var(--ocw-card); border-bottom:1px solid var(--ocw-line); overflow-x:auto; }
97
- .ocw-chip { flex:none; display:flex; align-items:center; gap:6px; border:1px solid #e3ded7; background:#fff; border-radius:999px; padding:7px 13px; font-size:13px; font-weight:600; cursor:pointer; white-space:nowrap; }
59
+ .ocw-chip { flex:none; display:flex; align-items:center; gap:6px; border:none; background:var(--ocw-tint); color:var(--ocw-accent); border-radius:999px; padding:7px 13px; font-size:12px; font-weight:600; cursor:pointer; white-space:nowrap; }
98
60
  .ocw-chip:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
99
61
  .ocw-scroll { flex:1; min-height:0; overflow-y:auto; padding:16px 14px; display:flex; flex-direction:column; gap:10px; }
100
- .ocw-subject { background:var(--ocw-card); border:1px solid var(--ocw-line); border-radius:16px; padding:14px 16px; }
101
- .ocw-subject-title { font-weight:700; font-size:16px; margin-bottom:2px; }
102
- .ocw-subject-sub { color:var(--ocw-mut); font-size:13px; margin-bottom:10px; }
62
+ .ocw-subject { background:var(--ocw-tint); border:none; border-radius:16px; padding:10px 12px; }
63
+ .ocw-subject-title { font-family:var(--ocw-fh); font-weight:600; font-size:13px; margin-bottom:2px; }
64
+ .ocw-subject-sub { color:var(--ocw-mut); font-size:10.5px; margin-bottom:6px; }
103
65
  .ocw-tags { display:flex; flex-wrap:wrap; gap:6px; }
104
66
  .ocw-tag { font-size:12px; color:#5b554e; background:#efeae3; border-radius:8px; padding:4px 10px; }
105
67
  .ocw-row { display:flex; align-items:flex-end; gap:8px; max-width:86%; }
106
68
  .ocw-row.mine { align-self:flex-end; flex-direction:row-reverse; }
107
69
  .ocw-row.theirs { align-self:flex-start; }
108
- .ocw-dot { width:26px; height:26px; border-radius:50%; background:var(--ocw-accent); color:#fff; font-size:12px; font-weight:700; display:flex; align-items:center; justify-content:center; flex:none; }
109
- .ocw-bubble { padding:10px 14px; border-radius:18px; font-size:14.5px; line-height:1.4; word-wrap:break-word; }
110
- .theirs .ocw-bubble { background:#fff; border:1px solid var(--ocw-line); border-bottom-left-radius:6px; }
111
- .mine .ocw-bubble { background:var(--ocw-accent); color:#fff; border-bottom-right-radius:6px; }
70
+ .ocw-dot { width:26px; height:26px; border-radius:50%; background:var(--ocw-tint); color:var(--ocw-accent); font-size:12px; font-weight:700; display:flex; align-items:center; justify-content:center; flex:none; }
71
+ .ocw-bubble { padding:10px 14px; border-radius:18px; font-size:13.5px; line-height:1.45; word-wrap:break-word; max-width:80%; }
72
+ .theirs .ocw-bubble { background:var(--ocw-tint); border-bottom-left-radius:4px; }
73
+ .mine .ocw-bubble { background:var(--ocw-accent2); color:#fff; border-bottom-right-radius:4px; }
112
74
  .ocw-sys { align-self:center; color:var(--ocw-mut); font-size:12.5px; font-style:italic; text-align:center; max-width:90%; }
113
- .ocw-bot .ocw-bubble { background:#f0fdf4; border-color:#cdebd6; }
75
+ .ocw-bot .ocw-bubble { background:var(--ocw-tint); }
114
76
  .ocw-note .ocw-bubble { background:#fffbeb; border:1.5px dashed #f59e0b; color:#78350f; border-radius:12px !important; }
115
77
  .ocw-note .ocw-bubble::before { content:'🔒 Note — '; font-size:11px; font-weight:700; color:#b45309; display:block; margin-bottom:3px; letter-spacing:.3px; }
116
78
  .ocw-time { font-size:10.5px; color:var(--ocw-mut); margin-top:3px; }
@@ -121,20 +83,20 @@ const ge = "objectchat-widget-styles", He = ["👍", "❤️", "😂", "😮", "
121
83
  .ocw-deleted { font-style:italic; color:var(--ocw-mut); }
122
84
  .ocw-edited { font-size:10px; color:var(--ocw-mut); margin-left:4px; }
123
85
  .ocw-react { font-size:12px; margin-top:3px; display:flex; flex-wrap:wrap; gap:3px; }
124
- .ocw-react-pill { display:inline-flex; align-items:center; gap:3px; border:1px solid #e3ded7; border-radius:999px; padding:2px 7px; background:#fff; font-size:12px; cursor:pointer; }
86
+ .ocw-react-pill { display:inline-flex; align-items:center; gap:3px; border:1px solid var(--ocw-line); border-radius:999px; padding:2px 7px; background:var(--ocw-card); font-size:12px; cursor:pointer; }
125
87
  .ocw-react-pill:hover { border-color:var(--ocw-accent); }
126
88
  .ocw-react-pill.mine { border-color:var(--ocw-accent); background:#fff8f5; }
127
89
  .ocw-react-wrap { position:relative; }
128
90
  .ocw-react-wrap:not(:hover) .ocw-react-picker { display:none; }
129
- .ocw-react-picker { position:absolute; bottom:calc(100% + 4px); left:0; background:#fff; border:1px solid #e3ded7; border-radius:14px; padding:6px 8px; box-shadow:0 4px 16px rgba(0,0,0,.12); display:flex; gap:4px; z-index:10; white-space:nowrap; }
91
+ .ocw-react-picker { position:absolute; bottom:calc(100% + 4px); left:0; background:var(--ocw-card); border:1px solid var(--ocw-line); border-radius:14px; padding:6px 8px; box-shadow:0 4px 16px rgba(0,0,0,.12); display:flex; gap:4px; z-index:10; white-space:nowrap; }
130
92
  .ocw-react-picker button { background:none; border:none; font-size:16px; cursor:pointer; padding:2px; border-radius:6px; }
131
- .ocw-react-picker button:hover { background:#f3efe9; }
132
- .ocw-react-btn { background:none; border:1px solid #e3ded7; border-radius:999px; padding:2px 7px; font-size:12px; cursor:pointer; color:var(--ocw-mut); }
93
+ .ocw-react-picker button:hover { background:var(--ocw-bg); }
94
+ .ocw-react-btn { background:none; border:1px solid var(--ocw-line); border-radius:999px; padding:2px 7px; font-size:12px; cursor:pointer; color:var(--ocw-mut); }
133
95
  .ocw-react-btn:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
134
96
  .ocw-msg-menu { position:absolute; top:0; right:0; display:none; gap:3px; }
135
97
  .ocw-row.mine:hover .ocw-msg-menu { display:flex; }
136
98
  .ocw-row.theirs:hover .ocw-msg-menu { display:flex; left:0; right:auto; }
137
- .ocw-msg-menu button { background:#fff; border:1px solid #e3ded7; border-radius:6px; font-size:11px; padding:2px 6px; cursor:pointer; color:var(--ocw-mut); }
99
+ .ocw-msg-menu button { background:var(--ocw-card); border:1px solid var(--ocw-line); border-radius:6px; font-size:11px; padding:2px 6px; cursor:pointer; color:var(--ocw-mut); }
138
100
  .ocw-msg-menu button:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
139
101
  .ocw-msg-menu button.del:hover { border-color:#e74c3c; color:#e74c3c; }
140
102
  .ocw-bubble-wrap { position:relative; }
@@ -146,25 +108,32 @@ const ge = "objectchat-widget-styles", He = ["👍", "❤️", "😂", "😮", "
146
108
  .ocw-appt-desc { font-size:12px; color:var(--ocw-mut); margin-bottom:10px; white-space:pre-wrap; }
147
109
  .ocw-appt-links { display:flex; flex-direction:column; gap:6px; }
148
110
  .ocw-appt-btn { display:block; text-align:center; padding:8px 12px; border-radius:8px; font-size:13px; font-weight:600; text-decoration:none; background:var(--ocw-accent); color:#fff; }
149
- .ocw-appt-btn-sec { background:#fff; color:var(--ocw-accent); border:1px solid var(--ocw-accent); }
111
+ .ocw-appt-btn-sec { background:var(--ocw-card); color:var(--ocw-accent); border:1px solid var(--ocw-accent); }
150
112
  .ocw-conn-status { font-size:10px; color:var(--ocw-mut); margin-left:4px; }
151
113
  .ocw-conn-status.warn { color:#e67e22; }
152
114
  .ocw-conn-status.err { color:#c0392b; font-weight:600; }
153
- .ocw-load-more { display:block; width:100%; background:none; border:1px solid #e3ded7; border-radius:10px; padding:6px 0; font-size:12px; color:var(--ocw-mut); cursor:pointer; margin-bottom:8px; }
115
+ .ocw-load-more { display:block; width:100%; background:none; border:1px solid var(--ocw-line); border-radius:10px; padding:6px 0; font-size:12px; color:var(--ocw-mut); cursor:pointer; margin-bottom:8px; }
154
116
  .ocw-load-more:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
155
117
  .ocw-away { margin:0 14px 8px; padding:9px 12px; background:#fff8e6; border:1px solid #f0e2bd; border-radius:10px; font-size:12px; color:#7a5c17; display:flex; gap:7px; align-items:flex-start; line-height:1.45; }
118
+ .ocw button:focus-visible, .ocw textarea:focus-visible, .ocw a:focus-visible, .ocw [tabindex]:focus-visible { outline:2px solid var(--ocw-accent); outline-offset:2px; border-radius:8px; }
119
+ .ocw-sendbtn:active { transform:scale(.92); }
120
+ .ocw-quick button:active, .ocw-chip:active { transform:scale(.97); }
121
+ @media (prefers-color-scheme: dark) { .ocw:not([data-theme="light"]) .ocw-away { background:#3a3018; border-color:#5a4a1f; color:#e8d9a8; } .ocw:not([data-theme="light"]) .ocw-note .ocw-bubble { background:#332b12; border-color:#7a5c17; color:#f0e2bd; } .ocw:not([data-theme="light"]) .ocw-note .ocw-bubble::before { color:#e0c060; } }
122
+ .ocw[data-theme="dark"] .ocw-away { background:#3a3018; border-color:#5a4a1f; color:#e8d9a8; }
123
+ .ocw[data-theme="dark"] .ocw-note .ocw-bubble { background:#332b12; border-color:#7a5c17; color:#f0e2bd; }
124
+ .ocw[data-theme="dark"] .ocw-note .ocw-bubble::before { color:#e0c060; }
156
125
  .ocw-away-icon { flex:none; }
157
126
  /* Shared form styles (used by the pre-chat panel; named for the retired offline form). */
158
127
  .ocw-offline-form { display:flex; flex-direction:column; gap:8px; text-align:left; }
159
- .ocw-offline-input { border:1px solid #e3ded7; border-radius:10px; padding:10px 12px; font-size:13px; font-family:inherit; }
160
- .ocw-offline-input:focus { outline:none; border-color:var(--ocw-accent); }
161
- .ocw-offline-submit { background:var(--ocw-accent); color:#fff; border:none; border-radius:10px; padding:11px; font-size:14px; font-weight:600; cursor:pointer; }
162
- .ocw-prechat { margin:20px 14px; padding:20px; background:#fff; border:1px solid #e3ded7; border-radius:16px; }
163
- .ocw-prechat-title { font-weight:700; font-size:15px; margin-bottom:12px; }
164
- .ocw-prechat select { border:1px solid #e3ded7; border-radius:10px; padding:10px 12px; font:inherit; font-size:13px; background:#fff; }
128
+ .ocw-offline-input { border:none; background:var(--ocw-tint); border-radius:14px; padding:10px 12px; font-size:13px; font-family:inherit; color:var(--ocw-ink); }
129
+ .ocw-offline-input:focus { outline:none; box-shadow:inset 0 0 0 1.5px var(--ocw-accent); }
130
+ .ocw-offline-submit { background:var(--ocw-accent); color:var(--ocw-onaccent); border:none; border-radius:20px; padding:11px; font-family:var(--ocw-fh); font-size:13.5px; font-weight:600; cursor:pointer; box-shadow:var(--ocw-shadow); }
131
+ .ocw-prechat { margin:16px; padding:0; background:none; border:none; }
132
+ .ocw-prechat-title { font-family:var(--ocw-fh); font-weight:600; font-size:20px; margin-bottom:10px; }
133
+ .ocw-prechat select { border:none; border-radius:14px; padding:10px 12px; font:inherit; font-size:13px; background:var(--ocw-tint); color:var(--ocw-ink); }
165
134
  .ocw-prechat-cb { display:flex; align-items:center; gap:8px; font-size:13px; color:var(--ocw-ink); }
166
135
  .ocw-deflect { margin:0 14px 8px; display:flex; flex-direction:column; gap:6px; }
167
- .ocw-deflect-card { text-align:left; background:#fff; border:1px solid #e3ded7; border-radius:12px; padding:10px 12px; font:inherit; font-size:13px; cursor:pointer; }
136
+ .ocw-deflect-card { text-align:left; background:var(--ocw-card); border:1px solid var(--ocw-line); border-radius:12px; padding:10px 12px; font:inherit; font-size:13px; cursor:pointer; }
168
137
  .ocw-deflect-card:hover { border-color:var(--ocw-accent); }
169
138
  .ocw-deflect-q { font-weight:600; margin-bottom:2px; }
170
139
  .ocw-deflect-a { color:var(--ocw-mut); font-size:12.5px; display:none; white-space:pre-wrap; }
@@ -177,7 +146,7 @@ const ge = "objectchat-widget-styles", He = ["👍", "❤️", "😂", "😮", "
177
146
  .ocw-csat-done { font-size:12px; color:var(--ocw-mut); margin-top:6px; }
178
147
 
179
148
  .ocw-typing { min-height:22px; padding:0 16px 4px; display:flex; align-items:center; }
180
- .ocw-typing-bubble { display:none; align-items:center; gap:3px; background:#fff; border:1px solid var(--ocw-line); border-radius:14px; border-bottom-left-radius:4px; padding:7px 12px; }
149
+ .ocw-typing-bubble { display:none; align-items:center; gap:3px; background:var(--ocw-card); border:1px solid var(--ocw-line); border-radius:14px; border-bottom-left-radius:4px; padding:7px 12px; }
181
150
  .ocw-typing.active .ocw-typing-bubble { display:flex; }
182
151
  .ocw-typing-dot { width:6px; height:6px; border-radius:50%; background:var(--ocw-mut); animation:ocw-bounce 1.2s infinite ease-in-out; }
183
152
  .ocw-typing-dot:nth-child(2) { animation-delay:.2s; }
@@ -185,20 +154,20 @@ const ge = "objectchat-widget-styles", He = ["👍", "❤️", "😂", "😮", "
185
154
  @keyframes ocw-bounce { 0%,60%,100%{transform:translateY(0)} 30%{transform:translateY(-5px)} }
186
155
  .ocw-quick { display:flex; gap:8px; padding:8px 12px 6px; overflow-x:auto; scrollbar-width:none; flex-shrink:0; }
187
156
  .ocw-quick::-webkit-scrollbar { display:none; }
188
- .ocw-quick button { flex:none; border:1px solid #e3ded7; background:#fff; border-radius:999px; padding:7px 14px; font-size:13px; cursor:pointer; color:#444; white-space:nowrap; transition:border-color .12s,color .12s; }
189
- .ocw-quick button:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
157
+ .ocw-quick button { flex:none; border:none; background:var(--ocw-tint); border-radius:999px; padding:7px 14px; font-size:12px; font-weight:600; cursor:pointer; color:var(--ocw-accent); white-space:nowrap; transition:background .12s,color .12s; }
158
+ .ocw-quick button:hover { background:var(--ocw-accent); color:var(--ocw-onaccent); }
190
159
  .ocw-form-host:empty { display:none; }
191
160
  .ocw-form { margin:6px 12px 0; padding:12px; background:var(--ocw-card); border:1px solid var(--ocw-line); border-radius:14px; }
192
161
  .ocw-form-title { font-weight:700; font-size:14px; margin-bottom:8px; }
193
162
  .ocw-form-row { display:flex; flex-direction:column; gap:3px; margin-bottom:8px; }
194
163
  .ocw-form-lbl { font-size:12px; color:var(--ocw-mut); }
195
- .ocw-form-input { border:1px solid #e3ded7; border-radius:9px; padding:9px 11px; font:inherit; font-size:14px; outline:none; }
164
+ .ocw-form-input { border:1px solid var(--ocw-line); border-radius:9px; padding:9px 11px; font:inherit; font-size:14px; outline:none; }
196
165
  .ocw-form-input:focus { border-color:var(--ocw-accent); }
197
166
  .ocw-form-actions { display:flex; justify-content:flex-end; gap:8px; margin-top:4px; }
198
167
  .ocw-form-cancel { background:none; border:none; color:var(--ocw-mut); font-size:13px; cursor:pointer; padding:8px 10px; }
199
168
  .ocw-form-submit { background:var(--ocw-accent); color:#fff; border:none; border-radius:999px; padding:8px 18px; font-size:13px; font-weight:600; cursor:pointer; }
200
169
  .ocw-modal { position:absolute; inset:0; background:rgba(20,18,16,.42); display:flex; align-items:center; justify-content:center; z-index:50; }
201
- .ocw-modal-card { background:#fff; border-radius:16px; padding:20px; width:78%; max-width:300px; box-shadow:0 14px 44px rgba(0,0,0,.22); }
170
+ .ocw-modal-card { background:var(--ocw-card); border-radius:16px; padding:20px; width:78%; max-width:300px; box-shadow:0 14px 44px rgba(0,0,0,.22); }
202
171
  .ocw-modal-title { font-weight:700; font-size:16px; margin-bottom:6px; }
203
172
  .ocw-modal-body { color:var(--ocw-mut); font-size:14px; margin-bottom:16px; }
204
173
  .ocw-modal-actions { display:flex; justify-content:flex-end; gap:8px; }
@@ -210,55 +179,48 @@ const ge = "objectchat-widget-styles", He = ["👍", "❤️", "😂", "😮", "
210
179
  .ocw-footer a:hover { color:var(--ocw-accent); }
211
180
  .ocw-attach { background:none;border:none;cursor:pointer;font-size:18px;padding:4px 6px;opacity:.6;flex-none; }
212
181
  .ocw-attach:hover { opacity:1; }
213
- .ocw-input textarea { flex:1; min-width:0; resize:none; border:1px solid #e3ded7; border-radius:22px; padding:11px 16px; font:inherit; font-size:14px; line-height:1.4; background:#fff; outline:none; max-height:120px; overflow-y:auto; }
214
- .ocw-input textarea:focus { border-color:var(--ocw-accent); }
182
+ .ocw-input textarea { flex:1; min-width:0; resize:none; border:none; border-radius:20px; padding:11px 16px; font:inherit; font-size:14px; line-height:1.4; background:var(--ocw-tint); outline:none; max-height:120px; overflow-y:auto; }
183
+ .ocw-input textarea:focus { box-shadow:inset 0 0 0 1.5px var(--ocw-accent); }
215
184
  /* Send button auto-sizes to its label: the default is a fixed circle around an
216
185
  * inline SVG; a TEXT label (i18n.send: "Send", "보내기", "Enviar"…) switches to
217
186
  * .ocw-sendbtn-label — a pill whose width follows the text. A fixed 42px
218
187
  * circle with 18px type overflowed the moment anyone localized the label. */
219
- .ocw-sendbtn { min-width:42px; height:42px; border-radius:999px; border:none; background:var(--ocw-accent); color:#fff; font:inherit; font-size:14px; font-weight:600; cursor:pointer; flex:none; display:flex; align-items:center; justify-content:center; padding:0; transition:opacity .15s, transform .1s; }
188
+ .ocw-sendbtn { min-width:38px; height:38px; border-radius:999px; border:none; background:var(--ocw-accent2); color:#fff; font:inherit; font-size:14px; font-weight:600; cursor:pointer; flex:none; display:flex; align-items:center; justify-content:center; padding:0; transition:opacity .15s, transform .1s; }
220
189
  .ocw-sendbtn-label { padding:0 16px; white-space:nowrap; }
221
190
  .ocw-sendbtn svg { width:19px; height:19px; display:block; }
222
191
  .ocw-sendbtn:not(:disabled):hover { transform:scale(1.05); }
223
192
  .ocw-sendbtn:not(:disabled):active { transform:scale(.96); }
224
193
  .ocw-sendbtn:disabled { opacity:.5; cursor:default; }
225
194
  .ocw-sendbtn:focus-visible, .ocw-back:focus-visible, .ocw-chip:focus-visible { outline:2px solid var(--ocw-accent); outline-offset:2px; }
226
- .ocw-cobrowse-btn { display:none; }
227
- .ocw-cobrowse-btn.show { display:inline-flex; }
228
- .ocw-cobrowse-btn.on { color:var(--ocw-accent); border-color:var(--ocw-accent); }
229
- .ocw-cobrowse-canvas { position:absolute; inset:0; z-index:40; touch-action:none; display:none; }
230
- .ocw-cobrowse-canvas.active { display:block; cursor:crosshair; }
231
- .ocw-cobrowse-toolbar { position:absolute; top:8px; right:8px; z-index:41; display:none; gap:6px; background:rgba(255,255,255,.92); border-radius:999px; padding:5px 8px; box-shadow:0 2px 10px rgba(0,0,0,.12); }
232
- .ocw-cobrowse-toolbar.active { display:flex; align-items:center; }
233
- .ocw-cobrowse-swatch { width:18px; height:18px; border-radius:50%; border:2px solid transparent; cursor:pointer; padding:0; }
234
- .ocw-cobrowse-swatch.sel { border-color:#1c1b1a; }
235
- .ocw-cobrowse-clear { background:none; border:1px solid #e3ded7; border-radius:999px; font-size:11px; padding:3px 8px; cursor:pointer; color:var(--ocw-mut); }
236
- .ocw-cobrowse-clear:hover { border-color:#e74c3c; color:#e74c3c; }
237
- .ocw-cobrowse-hint { position:absolute; bottom:8px; left:8px; z-index:41; font-size:11px; color:var(--ocw-mut); background:rgba(255,255,255,.9); border-radius:8px; padding:3px 8px; display:none; }
238
- .ocw-cobrowse-hint.active { display:block; }
239
195
 
240
- .ocw-translate-btn { position:absolute; bottom:2px; right:-26px; background:#fff; border:1px solid #e3ded7; border-radius:50%; width:22px; height:22px; font-size:11px; cursor:pointer; color:var(--ocw-mut); display:flex; align-items:center; justify-content:center; opacity:0; transition:opacity .15s; padding:0; }
196
+ .ocw-translate-btn { position:absolute; bottom:2px; right:-26px; background:var(--ocw-card); border:1px solid var(--ocw-line); border-radius:50%; width:22px; height:22px; font-size:11px; cursor:pointer; color:var(--ocw-mut); display:flex; align-items:center; justify-content:center; opacity:0; transition:opacity .15s; padding:0; }
241
197
  .ocw-row.theirs .ocw-translate-btn { right:auto; left:-26px; }
242
198
  .ocw-bubble-wrap:hover .ocw-translate-btn { opacity:1; }
243
199
  .ocw-translated-tag { font-size:10px; color:var(--ocw-mut); margin-top:2px; }
244
- `;
245
- function We() {
246
- if (typeof document > "u" || document.getElementById(ge)) return;
200
+ `, ye = "objectchat-widget-styles", Fe = ["👍", "❤️", "😂", "😮", "😢", "🙏"], We = 400, Ge = '<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M22 2 11 13M22 2l-7 20-4-9-9-4 20-7z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>';
201
+ function Ke() {
202
+ if (typeof document > "u" || document.getElementById(ye)) return;
247
203
  const t = document.createElement("style");
248
- t.id = ge, t.textContent = Ue, document.head.appendChild(t);
204
+ t.id = ye, t.textContent = Ue, document.head.appendChild(t);
205
+ }
206
+ const ve = "ocw-webfont";
207
+ function Ve() {
208
+ if (typeof document > "u" || document.getElementById(ve)) return;
209
+ const t = document.createElement("link");
210
+ t.id = ve, t.rel = "stylesheet", t.href = "https://fonts.googleapis.com/css2?family=Baloo+2:wght@500;600;700&family=Nunito:wght@400;500;600;700&display=swap", document.head.appendChild(t);
249
211
  }
250
- function o(t, e, i) {
251
- const s = document.createElement(t);
252
- return e && (s.className = e), i !== void 0 && (s.textContent = i), s;
212
+ function n(t, e, l) {
213
+ const c = document.createElement(t);
214
+ return e && (c.className = e), l !== void 0 && (c.textContent = l), c;
253
215
  }
254
- function Ve(t) {
216
+ function Ye(t) {
255
217
  try {
256
218
  return new Date(t).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
257
219
  } catch {
258
220
  return "";
259
221
  }
260
222
  }
261
- function ie(t) {
223
+ function ae(t) {
262
224
  var e;
263
225
  switch (t.kind) {
264
226
  case "text":
@@ -275,115 +237,101 @@ function ie(t) {
275
237
  return `📅 ${t.title} — ${new Date(t.startIso).toLocaleString()}`;
276
238
  }
277
239
  }
278
- class Ke {
240
+ class Xe {
279
241
  /** Last seq the guest has seen per conversationId — used to compute unread badges. */
280
- constructor(e, i, s, a = {}) {
281
- y(this, "scroll");
282
- y(this, "chips");
283
- y(this, "typing");
284
- y(this, "quick");
285
- y(this, "formHost");
286
- y(this, "csatPanel");
287
- y(this, "awayNotice");
288
- y(this, "preChatPanel");
289
- y(this, "deflectPanel");
290
- y(this, "preChatBuilt", !1);
291
- y(this, "preChatDone", !1);
292
- y(this, "footer");
293
- y(this, "input");
294
- y(this, "subjectCard");
295
- y(this, "e2eBadge");
296
- y(this, "statusBadge");
297
- y(this, "headerName");
298
- y(this, "connStatus");
299
- y(this, "typingTimer", null);
300
- y(this, "csatSubmitted", !1);
301
- y(this, "sendBtn");
242
+ constructor(e, l, c, i = {}) {
243
+ T(this, "scroll");
244
+ T(this, "chips");
245
+ T(this, "typing");
246
+ T(this, "quick");
247
+ T(this, "formHost");
248
+ T(this, "csatPanel");
249
+ T(this, "awayNotice");
250
+ T(this, "headStatus");
251
+ T(this, "reopenBtn");
252
+ T(this, "preChatPanel");
253
+ T(this, "deflectPanel");
254
+ T(this, "preChatBuilt", !1);
255
+ T(this, "preChatDone", !1);
256
+ T(this, "footer");
257
+ T(this, "input");
258
+ T(this, "subjectCard");
259
+ T(this, "e2eBadge");
260
+ T(this, "statusBadge");
261
+ T(this, "headerName");
262
+ T(this, "connStatus");
263
+ T(this, "typingTimer", null);
264
+ T(this, "csatSubmitted", !1);
265
+ T(this, "sendBtn");
302
266
  /** Container-driven responsive sizing — toggles .ocw-compact (see CSS note). */
303
- y(this, "compactObserver", null);
304
- // ── Co-browsing (shared whiteboard) ─────────────────────────────────────
305
- y(this, "cobrowseBtn");
306
- y(this, "cobrowseCanvas");
307
- y(this, "cobrowseToolbar");
308
- y(this, "cobrowseHint");
309
- y(this, "cobrowseActive", !1);
310
- y(this, "cobrowseColor", "#f5713c");
311
- y(this, "lastAnnotationVersion", -1);
312
- y(this, "storeRef", null);
313
- y(this, "scrollCleanup", null);
267
+ T(this, "compactObserver", null);
268
+ T(this, "storeRef", null);
269
+ T(this, "cfgAccent2");
270
+ T(this, "scrollCleanup", null);
314
271
  // ── Live translation ──────────────────────────────────────────────────-
315
- y(this, "translationCache", /* @__PURE__ */ new Map());
316
- y(this, "showingTranslation", /* @__PURE__ */ new Set());
272
+ T(this, "translationCache", /* @__PURE__ */ new Map());
273
+ T(this, "showingTranslation", /* @__PURE__ */ new Set());
317
274
  /** Whether the subject card (server Subject entity, mount config fallback)
318
275
  * has been built — built once when data first arrives. */
319
- y(this, "subjectBuilt", !1);
320
- var k, I, P, C, R, A, N, V, T, $;
321
- this.root = e, this.me = i, this.h = s, this.cfg = a, We(), e.replaceChildren(), e.classList.add("ocw"), a.accent && e.style.setProperty("--ocw-accent", a.accent);
322
- const c = o("div", "ocw-head");
276
+ T(this, "subjectBuilt", !1);
277
+ var r, C, v, u, f, R, B, A, k, S, D;
278
+ this.root = e, this.me = l, this.h = c, this.cfg = i, Ke(), i.webfont !== !1 && Ve(), e.replaceChildren(), e.classList.add("ocw"), i.accent && e.style.setProperty("--ocw-accent", i.accent);
279
+ const x = i.accent2 ?? i.accent;
280
+ x && e.style.setProperty("--ocw-accent2", x), this.cfgAccent2 = i.accent2, i.theme && i.theme !== "auto" && (e.dataset.theme = i.theme);
281
+ const w = n("div", "ocw-head");
323
282
  if (this.h.onBack) {
324
- const g = o("button", "ocw-back", "‹");
325
- g.type = "button", g.setAttribute("aria-label", "Back"), g.addEventListener("click", () => this.h.onBack()), c.append(g);
283
+ const g = n("button", "ocw-back", "‹");
284
+ g.type = "button", g.setAttribute("aria-label", "Back"), g.addEventListener("click", () => this.h.onBack()), w.append(g);
326
285
  }
327
- const w = o("div", "ocw-avatar");
328
- if ((k = a.userInfo) != null && k.avatar) {
286
+ const y = n("div", "ocw-avatar");
287
+ if ((r = i.userInfo) != null && r.avatar) {
329
288
  const g = document.createElement("img");
330
- g.src = a.userInfo.avatar, g.alt = a.userInfo.name ?? "You", g.style.cssText = "width:100%;height:100%;border-radius:50%;object-fit:cover", w.append(g);
289
+ g.src = i.userInfo.avatar, g.alt = i.userInfo.name ?? "You", g.style.cssText = "width:100%;height:100%;border-radius:50%;object-fit:cover", y.append(g);
331
290
  } else
332
- w.textContent = (I = a.userInfo) != null && I.name ? a.userInfo.name[0].toUpperCase() : "🧑";
333
- c.append(w);
334
- const b = o("div", "ocw-head-main");
335
- this.headerName = o("div", "ocw-head-name", ((P = a.subject) == null ? void 0 : P.ownerLabel) ?? ((C = a.subject) == null ? void 0 : C.title) ?? ""), b.append(this.headerName), (R = a.subject) != null && R.subtitle && b.append(o("div", "ocw-head-meta", a.subject.subtitle)), c.append(b), this.statusBadge = o("span", "ocw-badge", ((A = a.subject) == null ? void 0 : A.status) ?? ""), (N = a.subject) != null && N.status || (this.statusBadge.style.display = "none"), c.append(this.statusBadge), this.e2eBadge = o("span", "ocw-e2e", "🔒 E2E"), this.e2eBadge.style.display = "none", c.append(this.e2eBadge), this.connStatus = o("span", "ocw-conn-status"), this.connStatus.style.display = "none", c.append(this.connStatus), this.cobrowseBtn = o("button", "ocw-menu ocw-cobrowse-btn", "🖍"), this.cobrowseBtn.title = "Shared whiteboard draw to point things out together", this.cobrowseBtn.addEventListener("click", () => {
336
- this.cobrowseActive = !this.cobrowseActive, this.updateCobrowseUI();
337
- }), c.append(this.cobrowseBtn), c.append(o("button", "ocw-menu", "⋯")), this.chips = o("div", "ocw-chiprow"), this.scroll = o("div", "ocw-scroll"), this.subjectCard = o("div", "ocw-subject"), this.typing = o("div", "ocw-typing");
338
- const l = o("div", "ocw-typing-bubble");
339
- l.append(o("div", "ocw-typing-dot"), o("div", "ocw-typing-dot"), o("div", "ocw-typing-dot")), this.typing.append(o("div", "ocw-dot", "🧑"), l), this.quick = o("div", "ocw-quick");
340
- for (const g of a.quickReplies ?? []) {
341
- const S = o("button", void 0, g);
342
- S.addEventListener("click", () => {
291
+ y.textContent = (C = i.userInfo) != null && C.name ? i.userInfo.name[0].toUpperCase() : "🧑";
292
+ w.append(y);
293
+ const p = n("div", "ocw-head-main");
294
+ this.headerName = n("div", "ocw-head-name", ((v = i.subject) == null ? void 0 : v.ownerLabel) ?? ((u = i.subject) == null ? void 0 : u.title) ?? ""), p.append(this.headerName), this.headStatus = n("div", "ocw-head-status"), this.headStatus.style.display = "none", p.append(this.headStatus), (f = i.subject) != null && f.subtitle && p.append(n("div", "ocw-head-meta", i.subject.subtitle)), w.append(p), this.statusBadge = n("span", "ocw-badge", ((R = i.subject) == null ? void 0 : R.status) ?? ""), (B = i.subject) != null && B.status || (this.statusBadge.style.display = "none"), w.append(this.statusBadge), this.e2eBadge = n("span", "ocw-e2e", "🔒 E2E"), this.e2eBadge.style.display = "none", w.append(this.e2eBadge), this.connStatus = n("span", "ocw-conn-status"), this.connStatus.style.display = "none", w.append(this.connStatus), w.append(n("button", "ocw-menu", "")), this.chips = n("div", "ocw-chiprow"), this.scroll = n("div", "ocw-scroll"), this.subjectCard = n("div", "ocw-subject"), this.typing = n("div", "ocw-typing");
295
+ const h = n("div", "ocw-typing-bubble");
296
+ h.append(n("div", "ocw-typing-dot"), n("div", "ocw-typing-dot"), n("div", "ocw-typing-dot")), this.typing.append(n("div", "ocw-dot", "🧑"), h), this.quick = n("div", "ocw-quick");
297
+ for (const g of i.quickReplies ?? []) {
298
+ const N = n("button", void 0, g);
299
+ N.addEventListener("click", () => {
343
300
  this.h.onSend(g), this.quick.style.display = "none";
344
- }), this.quick.append(S);
301
+ }), this.quick.append(N);
345
302
  }
346
- this.formHost = o("div", "ocw-form-host"), this.csatPanel = o("div", "ocw-csat"), this.csatPanel.style.display = "none", this.awayNotice = o("div", "ocw-away"), this.awayNotice.style.display = "none", this.preChatPanel = o("div", "ocw-prechat"), this.preChatPanel.style.display = "none", this.deflectPanel = o("div", "ocw-deflect"), this.deflectPanel.style.display = "none", this.input = o("textarea", void 0), this.input.rows = 1, this.input.placeholder = ((V = a.i18n) == null ? void 0 : V.placeholder) ?? "Message…";
347
- const h = o("button", "ocw-sendbtn");
348
- h.type = "button";
349
- const v = (T = a.i18n) == null ? void 0 : T.send;
350
- v ? (h.textContent = v, h.classList.add("ocw-sendbtn-label"), h.setAttribute("aria-label", v)) : (h.innerHTML = Fe, h.setAttribute("aria-label", "Send message")), h.disabled = !0, this.sendBtn = h, h.addEventListener("click", () => this.flushSend()), this.input.addEventListener("input", () => {
351
- var g, S;
352
- this.sendBtn.disabled = this.input.value.trim().length === 0, this.autoGrowInput(), this.storeRef && !this.storeRef.messages().some((q) => q.senderRole === "guest") ? (S = (g = this.h).onDeflectQuery) == null || S.call(g, this.input.value) : this.hideDeflection();
303
+ this.formHost = n("div", "ocw-form-host"), this.csatPanel = n("div", "ocw-csat"), this.csatPanel.style.display = "none", this.awayNotice = n("div", "ocw-away"), this.awayNotice.style.display = "none", this.preChatPanel = n("div", "ocw-prechat"), this.preChatPanel.style.display = "none", this.deflectPanel = n("div", "ocw-deflect"), this.deflectPanel.style.display = "none", this.input = n("textarea", void 0), this.input.rows = 1, this.input.placeholder = ((A = i.i18n) == null ? void 0 : A.placeholder) ?? "Message…";
304
+ const b = n("button", "ocw-sendbtn");
305
+ b.type = "button";
306
+ const a = (k = i.i18n) == null ? void 0 : k.send;
307
+ a ? (b.textContent = a, b.classList.add("ocw-sendbtn-label"), b.setAttribute("aria-label", a)) : (b.innerHTML = Ge, b.setAttribute("aria-label", "Send message")), b.disabled = !0, this.sendBtn = b, b.addEventListener("click", () => this.flushSend()), this.input.addEventListener("input", () => {
308
+ var g, N;
309
+ this.sendBtn.disabled = this.input.value.trim().length === 0, this.autoGrowInput(), this.storeRef && !this.storeRef.messages().some((H) => H.senderRole === "guest") ? (N = (g = this.h).onDeflectQuery) == null || N.call(g, this.input.value) : this.hideDeflection();
353
310
  }), this.input.addEventListener("keydown", (g) => {
354
311
  g.isComposing || g.keyCode === 229 || (g.key === "Enter" && !g.shiftKey ? (g.preventDefault(), this.flushSend()) : this.signalTyping());
355
312
  });
356
- const r = o("button", "ocw-attach", "📎");
357
- r.title = "Attach image or file";
358
- const u = document.createElement("input");
359
- u.type = "file", u.accept = "image/*,.pdf,.txt,.doc,.docx", u.style.display = "none", r.addEventListener("click", () => u.click()), u.addEventListener("change", () => {
313
+ const P = n("button", "ocw-attach", "📎");
314
+ P.title = "Attach image or file";
315
+ const I = document.createElement("input");
316
+ I.type = "file", I.accept = "image/*,.pdf,.txt,.doc,.docx", I.style.display = "none", P.addEventListener("click", () => I.click()), I.addEventListener("change", () => {
360
317
  var g;
361
- (g = u.files) != null && g[0] && this.h.onAttach && this.h.onAttach(u.files[0]), u.value = "";
318
+ (g = I.files) != null && g[0] && this.h.onAttach && this.h.onAttach(I.files[0]), I.value = "";
362
319
  });
363
- const d = o("div", "ocw-input");
364
- d.append(r, u, this.input, h);
365
- const E = o("div", "ocw-footer");
366
- (($ = a.i18n) == null ? void 0 : $.poweredBy) !== void 0 ? E.textContent = a.i18n.poweredBy : E.innerHTML = 'Powered by <a href="https://relay.paramms.com" target="_blank" rel="noopener">Relay</a>', this.footer = E, e.append(c, this.chips, this.scroll, this.typing, this.quick, this.formHost, this.csatPanel, this.preChatPanel, this.deflectPanel, this.awayNotice, d, this.footer), this.cobrowseCanvas = o("canvas", "ocw-cobrowse-canvas"), this.cobrowseToolbar = o("div", "ocw-cobrowse-toolbar");
367
- for (const g of ["#f5713c", "#1c1b1a", "#2563eb", "#16a34a", "#dc2626"]) {
368
- const S = o("button", "ocw-cobrowse-swatch");
369
- S.style.background = g, S.type = "button", g === this.cobrowseColor && S.classList.add("sel"), S.addEventListener("click", () => {
370
- this.cobrowseColor = g;
371
- for (const q of this.cobrowseToolbar.querySelectorAll(".ocw-cobrowse-swatch")) q.classList.remove("sel");
372
- S.classList.add("sel");
373
- }), this.cobrowseToolbar.append(S);
374
- }
375
- const m = o("button", "ocw-cobrowse-clear", "Clear");
376
- m.addEventListener("click", () => {
377
- var g, S;
378
- return (S = (g = this.h).onAnnotateClear) == null ? void 0 : S.call(g);
379
- }), this.cobrowseToolbar.append(m), this.cobrowseHint = o("div", "ocw-cobrowse-hint", "🖍 Draw to point things out — visible to both sides"), e.append(this.cobrowseCanvas, this.cobrowseToolbar, this.cobrowseHint), this.bindCobrowsePointerEvents();
380
- const f = (g) => {
381
- e.classList.toggle("ocw-compact", g > 0 && g < _e);
320
+ const M = n("div", "ocw-input");
321
+ M.append(P, I, this.input, b);
322
+ const j = n("div", "ocw-footer");
323
+ ((S = i.i18n) == null ? void 0 : S.poweredBy) !== void 0 ? j.textContent = i.i18n.poweredBy : j.innerHTML = 'Powered by <a href="https://relay.paramms.com" target="_blank" rel="noopener">Relay</a>', this.footer = j, this.reopenBtn = n("button", "ocw-reopen", ((D = this.cfg.i18n) == null ? void 0 : D.reopen) ?? "Reopen conversation"), this.reopenBtn.type = "button", this.reopenBtn.addEventListener("click", () => {
324
+ this.reopenBtn.style.display = "none";
325
+ const g = this.root.querySelector(".ocw-input textarea");
326
+ g == null || g.focus();
327
+ }), e.append(w, this.chips, this.scroll, this.typing, this.quick, this.formHost, this.csatPanel, this.preChatPanel, this.deflectPanel, this.awayNotice, M, this.reopenBtn, this.footer);
328
+ const d = (g) => {
329
+ e.classList.toggle("ocw-compact", g > 0 && g < We);
382
330
  };
383
- f(e.clientWidth), typeof ResizeObserver < "u" && (this.compactObserver = new ResizeObserver((g) => {
384
- var q;
385
- const S = ((q = g[0]) == null ? void 0 : q.contentRect.width) ?? e.clientWidth;
386
- f(S);
331
+ d(e.clientWidth), typeof ResizeObserver < "u" && (this.compactObserver = new ResizeObserver((g) => {
332
+ var H;
333
+ const N = ((H = g[0]) == null ? void 0 : H.contentRect.width) ?? e.clientWidth;
334
+ d(N);
387
335
  }), this.compactObserver.observe(e));
388
336
  }
389
337
  /** Returns the scroll container so history.ts can attach scroll listeners. */
@@ -392,13 +340,13 @@ class Ke {
392
340
  }
393
341
  /** Registers a cleanup fn removed on destroy() to prevent listener leaks. */
394
342
  setScrollCleanup(e) {
395
- var i;
396
- (i = this.scrollCleanup) == null || i.call(this), this.scrollCleanup = e;
343
+ var l;
344
+ (l = this.scrollCleanup) == null || l.call(this), this.scrollCleanup = e;
397
345
  }
398
346
  /** Call when the widget is unmounted. Disconnects scroll listeners and clears timers. */
399
347
  destroy() {
400
- var e, i;
401
- (e = this.scrollCleanup) == null || e.call(this), this.scrollCleanup = null, this.typingTimer && (clearTimeout(this.typingTimer), this.typingTimer = null), (i = this.compactObserver) == null || i.disconnect(), this.compactObserver = null;
348
+ var e, l;
349
+ (e = this.scrollCleanup) == null || e.call(this), this.scrollCleanup = null, this.typingTimer && (clearTimeout(this.typingTimer), this.typingTimer = null), (l = this.compactObserver) == null || l.disconnect(), this.compactObserver = null;
402
350
  }
403
351
  flushSend() {
404
352
  this.hideDeflection();
@@ -418,101 +366,109 @@ class Ke {
418
366
  this.h.onTyping(!0, e), this.typingTimer && clearTimeout(this.typingTimer), this.typingTimer = setTimeout(() => this.h.onTyping(!1), 2e3);
419
367
  }
420
368
  render(e) {
421
- var r, u, d, E, m;
422
- 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) {
423
- const f = (r = this.cfg.subject) == null ? void 0 : r.ownerLabel;
369
+ var I, M, j, d, r, C, v, u;
370
+ if (this.storeRef = e, e.accent && (this.root.style.setProperty("--ocw-accent", e.accent), this.root.style.setProperty("--ocw-accent2", this.cfgAccent2 ?? e.accent)), this.e2eBadge.style.display = e.e2e ? "inline-flex" : "none", this.buildSubjectCard(e), e.subject) {
371
+ const f = (I = this.cfg.subject) == null ? void 0 : I.ownerLabel;
424
372
  f && (this.headerName.textContent = f);
425
373
  }
426
374
  this.quick.style.display = e.messages().length === 0 ? "flex" : "none", this.chips.replaceChildren();
427
- const i = e.visibleActions();
428
- this.chips.style.display = i.length ? "flex" : "none";
429
- for (const f of i) this.chips.append(this.chipEl(f));
430
- const s = this.scroll.scrollHeight, a = this.scroll.scrollTop;
375
+ const l = e.visibleActions();
376
+ this.chips.style.display = l.length ? "flex" : "none";
377
+ for (const f of l) this.chips.append(this.chipEl(f));
378
+ const c = this.scroll.scrollHeight, i = this.scroll.scrollTop;
431
379
  if (this.scroll.replaceChildren(), this.subjectCard.childNodes.length && this.scroll.append(this.subjectCard), e.hasMoreHistory) {
432
- const f = o("div", "ocw-load-more");
380
+ const f = n("div", "ocw-load-more");
433
381
  f.textContent = "↑ Loading earlier messages…", f.style.pointerEvents = "none", this.scroll.append(f);
434
382
  }
435
- let c = 0;
436
- for (const f of e.messages())
437
- this.scroll.append(this.messageEl(f, e)), f.senderId !== this.me && f.seq > c && (c = f.seq);
438
- a > 20 ? this.scroll.scrollTop = this.scroll.scrollHeight - s + a : this.scroll.scrollTop = this.scroll.scrollHeight, c > 0 && this.h.onReadUpTo(c);
439
- const w = [...e.typing];
440
- this.typing.classList.toggle("active", w.length > 0);
441
- const b = this.typing.querySelector(".ocw-typing-bubble");
442
- b && b.setAttribute("aria-label", w.length ? "typing" : ""), this.footer.style.display = e.whiteLabel ? "none" : "block";
443
- const l = e.messages().some((f) => f.senderRole === "guest");
444
- if (!!((u = e.preChat) != null && u.enabled) && !this.preChatDone && !l && (e.preChat.showWhen !== "offline" || e.offline))
445
- this.preChatBuilt || this.buildPreChatPanel(e.preChat), this.preChatPanel.style.display = "block", this.awayNotice.style.display = "none", (d = this.root.querySelector(".ocw-input")) == null || d.style.setProperty("display", "none");
383
+ let x = 0, w = null;
384
+ for (const f of e.messages()) {
385
+ const R = f.senderRole !== "system" && f.senderId !== this.me && !f.internal && f.senderId !== w;
386
+ this.scroll.append(this.messageEl(f, e, R)), f.senderRole !== "system" && (w = f.senderId), f.senderId !== this.me && f.seq > x && (x = f.seq);
387
+ }
388
+ i > 20 ? this.scroll.scrollTop = this.scroll.scrollHeight - c + i : this.scroll.scrollTop = this.scroll.scrollHeight, x > 0 && this.h.onReadUpTo(x);
389
+ const y = [...e.typing];
390
+ this.typing.classList.toggle("active", y.length > 0);
391
+ const p = this.typing.querySelector(".ocw-typing-bubble");
392
+ p && p.setAttribute("aria-label", y.length ? "typing" : ""), this.footer.style.display = e.whiteLabel ? "none" : "block";
393
+ const h = e.messages().some((f) => f.senderRole === "guest");
394
+ if (!!((M = e.preChat) != null && M.enabled) && !this.preChatDone && !h && (e.preChat.showWhen !== "offline" || e.offline))
395
+ this.preChatBuilt || this.buildPreChatPanel(e.preChat), this.preChatPanel.style.display = "block", this.awayNotice.style.display = "none", (j = this.root.querySelector(".ocw-input")) == null || j.style.setProperty("display", "none");
446
396
  else {
447
397
  if (this.preChatPanel.style.display = "none", e.offline) {
448
- this.awayNotice.firstChild || this.awayNotice.append(o("span", "ocw-away-icon", "🌙"), o("span", "", ""));
398
+ this.awayNotice.firstChild || this.awayNotice.append(n("span", "ocw-away-icon", "🌙"), n("span", "", ""));
449
399
  const f = this.awayNotice.lastChild;
450
- f.textContent = e.offlineMessage || ((E = this.cfg.i18n) == null ? void 0 : E.offline) || "We're away right now — send your message and we'll reply as soon as we're back.", this.awayNotice.style.display = "flex";
400
+ f.textContent = e.offlineMessage || ((d = this.cfg.i18n) == null ? void 0 : d.offline) || "We're away right now — send your message and we'll reply as soon as we're back.", this.awayNotice.style.display = "flex";
451
401
  } else
452
402
  this.awayNotice.style.display = "none";
453
- (m = this.root.querySelector(".ocw-input")) == null || m.style.removeProperty("display");
403
+ (r = this.root.querySelector(".ocw-input")) == null || r.style.removeProperty("display");
454
404
  }
455
- const v = ["resolved", "closed", "sold", "issued", "checked_out"];
456
- 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");
405
+ const a = ["resolved", "closed", "sold", "issued", "checked_out"];
406
+ this.h.onCsat && !this.csatSubmitted && a.includes(e.state) && e.messages().length > 0 && (this.csatPanel.style.display === "none" && this.buildCsatPanel(), this.csatPanel.style.display = "block");
407
+ const P = a.includes(e.state);
408
+ if (e.offline ? (this.headStatus.textContent = `● ${e.offlineMessage || ((C = this.cfg.i18n) == null ? void 0 : C.away) || "Away"}`, this.headStatus.className = "ocw-head-status away", this.headStatus.style.display = "") : e.conversationId ? (this.headStatus.textContent = `● ${((v = this.cfg.i18n) == null ? void 0 : v.online) ?? "Online"}`, this.headStatus.className = "ocw-head-status online", this.headStatus.style.display = "") : this.headStatus.style.display = "none", P && e.messages().length > 0) {
409
+ const f = n("div", "ocw-resolved-note", `— ${((u = this.cfg.i18n) == null ? void 0 : u.resolved) ?? "Marked as resolved"} —`);
410
+ this.scroll.append(f), this.reopenBtn.style.display = "block";
411
+ } else
412
+ this.reopenBtn.style.display = "none";
457
413
  }
458
- setConnStatus(e, i) {
414
+ setConnStatus(e, l) {
459
415
  if (e === "open") {
460
416
  this.connStatus.style.display = "none";
461
417
  return;
462
418
  }
463
419
  this.connStatus.style.display = "";
464
- const s = e === "error";
465
- this.connStatus.className = `ocw-conn-status${s ? " err" : e === "reconnecting" ? " warn" : ""}`, this.connStatus.textContent = s ? `⚠ ${i ?? "Chat unavailable"}` : e === "reconnecting" ? i ?? "↻ reconnecting…" : "● connecting…";
420
+ const c = e === "error";
421
+ this.connStatus.className = `ocw-conn-status${c ? " err" : e === "reconnecting" ? " warn" : ""}`, this.connStatus.textContent = c ? `⚠ ${l ?? "Chat unavailable"}` : e === "reconnecting" ? l ?? "↻ reconnecting…" : "● connecting…";
466
422
  }
467
423
  buildPreChatPanel(e) {
468
- var l;
469
- this.preChatBuilt = !0, this.preChatPanel.replaceChildren(), this.preChatPanel.append(o("div", "ocw-prechat-title", e.title ?? "Before we start…"));
470
- const i = o("div", "ocw-offline-form"), s = {};
424
+ var p;
425
+ this.preChatBuilt = !0, this.preChatPanel.replaceChildren(), this.preChatPanel.append(n("div", "ocw-prechat-title", e.title ?? "Before we start…"));
426
+ const l = n("div", "ocw-offline-form"), c = {};
471
427
  for (const h of e.fields ?? ["name", "email"]) {
472
- const v = o("input", "ocw-offline-input");
473
- v.type = h === "email" ? "email" : h === "phone" ? "tel" : "text", v.placeholder = h === "name" ? "Your name" : h === "email" ? "Your email" : "Your phone number", s[h] = v, i.append(v);
428
+ const b = n("input", "ocw-offline-input");
429
+ b.type = h === "email" ? "email" : h === "phone" ? "tel" : "text", b.placeholder = h === "name" ? "Your name" : h === "email" ? "Your email" : "Your phone number", c[h] = b, l.append(b);
474
430
  }
475
- let a = null;
476
- if ((l = e.topics) != null && l.length) {
477
- a = o("select", void 0);
431
+ let i = null;
432
+ if ((p = e.topics) != null && p.length) {
433
+ i = n("select", void 0);
478
434
  const h = document.createElement("option");
479
- h.value = "", h.textContent = "What is this about?", a.append(h);
480
- for (const v of e.topics) {
481
- const r = document.createElement("option");
482
- r.value = v, r.textContent = v, a.append(r);
435
+ h.value = "", h.textContent = "What is this about?", i.append(h);
436
+ for (const b of e.topics) {
437
+ const a = document.createElement("option");
438
+ a.value = b, a.textContent = b, i.append(a);
483
439
  }
484
- i.append(a);
440
+ l.append(i);
485
441
  }
486
- let c = null, w = null;
442
+ let x = null, w = null;
487
443
  if (e.callbackOption) {
488
- const h = o("label", "ocw-prechat-cb");
489
- c = document.createElement("input"), c.type = "checkbox", h.append(c, document.createTextNode("📞 Request a call back")), i.append(h), s.phone || (w = o("input", "ocw-offline-input"), w.type = "tel", w.placeholder = "Phone number for the call", w.style.display = "none", c.addEventListener("change", () => w.style.setProperty("display", c.checked ? "block" : "none")), i.append(w));
444
+ const h = n("label", "ocw-prechat-cb");
445
+ x = document.createElement("input"), x.type = "checkbox", h.append(x, document.createTextNode("📞 Request a call back")), l.append(h), c.phone || (w = n("input", "ocw-offline-input"), w.type = "tel", w.placeholder = "Phone number for the call", w.style.display = "none", x.addEventListener("change", () => w.style.setProperty("display", x.checked ? "block" : "none")), l.append(w));
490
446
  }
491
- const b = o("button", "ocw-offline-submit", "Start chat");
492
- b.type = "button", b.addEventListener("click", () => {
493
- var u, d, E, m, f, k, I;
494
- const h = (u = s.email) == null ? void 0 : u.value.trim();
495
- if (s.email && (!h || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(h))) {
496
- s.email.focus();
447
+ const y = n("button", "ocw-offline-submit", "Start chat");
448
+ y.type = "button", y.addEventListener("click", () => {
449
+ var P, I, M, j, d, r, C;
450
+ const h = (P = c.email) == null ? void 0 : P.value.trim();
451
+ if (c.email && (!h || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(h))) {
452
+ c.email.focus();
497
453
  return;
498
454
  }
499
- const v = !!(c != null && c.checked), r = (((d = s.phone) == null ? void 0 : d.value) ?? (w == null ? void 0 : w.value) ?? "").trim();
500
- if (v && !r) {
501
- (E = s.phone ?? w) == null || E.focus();
455
+ const b = !!(x != null && x.checked), a = (((I = c.phone) == null ? void 0 : I.value) ?? (w == null ? void 0 : w.value) ?? "").trim();
456
+ if (b && !a) {
457
+ (M = c.phone ?? w) == null || M.focus();
502
458
  return;
503
459
  }
504
- if (a && ((m = e.topics) != null && m.length) && !a.value) {
505
- a.focus();
460
+ if (i && ((j = e.topics) != null && j.length) && !i.value) {
461
+ i.focus();
506
462
  return;
507
463
  }
508
- b.disabled = !0, this.completePreChat(), (I = (k = this.h).onPreChat) == null || I.call(k, {
509
- ...(f = s.name) != null && f.value.trim() ? { name: s.name.value.trim() } : {},
464
+ y.disabled = !0, this.completePreChat(), (C = (r = this.h).onPreChat) == null || C.call(r, {
465
+ ...(d = c.name) != null && d.value.trim() ? { name: c.name.value.trim() } : {},
510
466
  ...h ? { email: h } : {},
511
- ...r ? { phone: r } : {},
512
- ...a != null && a.value ? { topic: a.value } : {},
513
- ...v ? { callback: !0 } : {}
467
+ ...a ? { phone: a } : {},
468
+ ...i != null && i.value ? { topic: i.value } : {},
469
+ ...b ? { callback: !0 } : {}
514
470
  });
515
- }), i.append(b), this.preChatPanel.append(i);
471
+ }), l.append(y), this.preChatPanel.append(l);
516
472
  }
517
473
  /** Mark pre-chat complete (submitted now or in a previous session). */
518
474
  completePreChat() {
@@ -521,10 +477,10 @@ class Ke {
521
477
  /** KB deflection results ("was this your question?") above the composer. */
522
478
  showDeflection(e) {
523
479
  if (!e.length) return this.hideDeflection();
524
- this.deflectPanel.replaceChildren(), this.deflectPanel.append(o("div", "ocw-deflect-hint", "Instant answers — tap to expand"));
525
- for (const i of e.slice(0, 3)) {
526
- const s = o("button", "ocw-deflect-card");
527
- s.append(o("div", "ocw-deflect-q", i.title), o("div", "ocw-deflect-a", i.answer)), s.addEventListener("click", () => s.classList.toggle("open")), this.deflectPanel.append(s);
480
+ this.deflectPanel.replaceChildren(), this.deflectPanel.append(n("div", "ocw-deflect-hint", "Instant answers — tap to expand"));
481
+ for (const l of e.slice(0, 3)) {
482
+ const c = n("button", "ocw-deflect-card");
483
+ c.append(n("div", "ocw-deflect-q", l.title), n("div", "ocw-deflect-a", l.answer)), c.addEventListener("click", () => c.classList.toggle("open")), this.deflectPanel.append(c);
528
484
  }
529
485
  this.deflectPanel.style.display = "flex";
530
486
  }
@@ -532,264 +488,221 @@ class Ke {
532
488
  this.deflectPanel.style.display = "none", this.deflectPanel.replaceChildren();
533
489
  }
534
490
  buildCsatPanel() {
535
- this.csatPanel.replaceChildren(), this.csatPanel.append(o("div", "ocw-csat-title", "How did we do?"));
536
- const e = o("div", "ocw-csat-stars"), i = [];
537
- for (let s = 1; s <= 5; s++) {
538
- const a = o("button", "ocw-csat-star", "★");
539
- a.dataset.score = String(s), a.addEventListener("mouseenter", () => i.forEach((c, w) => c.classList.toggle("lit", w < s))), a.addEventListener("mouseleave", () => i.forEach((c) => c.classList.remove("lit"))), a.addEventListener("click", () => {
540
- var c, w;
541
- this.csatSubmitted = !0, this.csatPanel.replaceChildren(o("div", "ocw-csat-done", `Thanks for your ${s}★ rating!`)), (w = (c = this.h).onCsat) == null || w.call(c, s);
542
- }), i.push(a), e.append(a);
491
+ this.csatPanel.replaceChildren(), this.csatPanel.append(n("div", "ocw-csat-title", "How did we do?"));
492
+ const e = n("div", "ocw-csat-stars"), l = [];
493
+ for (let c = 1; c <= 5; c++) {
494
+ const i = n("button", "ocw-csat-star", "★");
495
+ i.dataset.score = String(c), i.addEventListener("mouseenter", () => l.forEach((x, w) => x.classList.toggle("lit", w < c))), i.addEventListener("mouseleave", () => l.forEach((x) => x.classList.remove("lit"))), i.addEventListener("click", () => {
496
+ var x, w;
497
+ this.csatSubmitted = !0, this.csatPanel.replaceChildren(n("div", "ocw-csat-done", `Thanks for your ${c}★ rating!`)), (w = (x = this.h).onCsat) == null || w.call(x, c);
498
+ }), l.push(i), e.append(i);
543
499
  }
544
500
  this.csatPanel.append(e);
545
501
  }
546
- // ── Co-browsing (shared whiteboard) ──────────────────────────────────────
547
- updateCobrowseUI() {
548
- this.cobrowseCanvas.classList.toggle("active", this.cobrowseActive), this.cobrowseToolbar.classList.toggle("active", this.cobrowseActive), this.cobrowseHint.classList.toggle("active", this.cobrowseActive), this.cobrowseBtn.classList.toggle("on", this.cobrowseActive), this.cobrowseActive && (this.resizeCobrowseCanvas(), this.redrawCobrowse());
549
- }
550
- resizeCobrowseCanvas() {
551
- this.cobrowseCanvas.width = this.root.clientWidth || 1, this.cobrowseCanvas.height = this.root.clientHeight || 1;
552
- }
553
- /** Draw a stroke whose points are normalized to 0..1, scaled to the current
554
- * canvas size — so strokes line up across different viewport sizes. */
555
- drawStroke(e) {
556
- const i = this.cobrowseCanvas.getContext("2d");
557
- if (!i || e.points.length < 2) return;
558
- const s = this.cobrowseCanvas.width, a = this.cobrowseCanvas.height;
559
- i.strokeStyle = e.color, i.lineWidth = Math.max(1, e.width * Math.min(s, a)), i.lineJoin = "round", i.lineCap = "round", i.beginPath(), i.moveTo(e.points[0].x * s, e.points[0].y * a);
560
- for (const c of e.points.slice(1)) i.lineTo(c.x * s, c.y * a);
561
- i.stroke();
562
- }
563
- redrawCobrowse() {
564
- var i;
565
- const e = this.cobrowseCanvas.getContext("2d");
566
- if (e) {
567
- e.clearRect(0, 0, this.cobrowseCanvas.width, this.cobrowseCanvas.height);
568
- for (const s of ((i = this.storeRef) == null ? void 0 : i.annotations) ?? []) this.drawStroke(s);
569
- }
570
- }
571
- bindCobrowsePointerEvents() {
572
- let e = !1, i = [];
573
- const s = (w) => {
574
- const b = this.cobrowseCanvas.getBoundingClientRect(), l = b.width > 0 ? (w.clientX - b.left) / b.width : 0, h = b.height > 0 ? (w.clientY - b.top) / b.height : 0;
575
- return { x: Math.min(1, Math.max(0, l)), y: Math.min(1, Math.max(0, h)) };
576
- }, a = 6e-3;
577
- this.cobrowseCanvas.addEventListener("pointerdown", (w) => {
578
- this.cobrowseActive && (e = !0, i = [s(w)], this.cobrowseCanvas.setPointerCapture(w.pointerId));
579
- }), this.cobrowseCanvas.addEventListener("pointermove", (w) => {
580
- e && (i.push(s(w)), this.redrawCobrowse(), this.drawStroke({ points: i, color: this.cobrowseColor, width: a }));
581
- });
582
- const c = (w) => {
583
- var b, l;
584
- if (e) {
585
- e = !1, i.length > 1 && ((l = (b = this.h).onAnnotate) == null || l.call(b, { id: `an_${Date.now()}_${Math.random().toString(36).slice(2)}`, points: i, color: this.cobrowseColor, width: a })), i = [];
586
- try {
587
- this.cobrowseCanvas.releasePointerCapture(w.pointerId);
588
- } catch {
589
- }
590
- }
591
- };
592
- this.cobrowseCanvas.addEventListener("pointerup", c), this.cobrowseCanvas.addEventListener("pointercancel", c);
593
- }
594
502
  buildSubjectCard(e) {
595
503
  if (this.subjectBuilt) return;
596
- const i = e.subject, s = this.cfg.subject, a = (i == null ? void 0 : i.title) ?? (s == null ? void 0 : s.title);
597
- if (!a) return;
598
- this.subjectBuilt = !0, this.subjectCard.replaceChildren(), this.subjectCard.append(o("div", "ocw-subject-title", a)), s != null && s.subtitle && this.subjectCard.append(o("div", "ocw-subject-sub", s.subtitle));
599
- const c = o("div", "ocw-tags");
600
- if (i) for (const [b, l] of Object.entries(i.fields)) c.append(o("span", "ocw-tag", `${b}: ${l}`));
601
- else for (const b of (s == null ? void 0 : s.tags) ?? []) c.append(o("span", "ocw-tag", b));
602
- c.childNodes.length && this.subjectCard.append(c);
603
- const w = (i == null ? void 0 : i.state) ?? (s == null ? void 0 : s.status);
504
+ const l = e.subject, c = this.cfg.subject, i = (l == null ? void 0 : l.title) ?? (c == null ? void 0 : c.title);
505
+ if (!i) return;
506
+ this.subjectBuilt = !0, this.subjectCard.replaceChildren(), this.subjectCard.append(n("div", "ocw-subject-title", i)), c != null && c.subtitle && this.subjectCard.append(n("div", "ocw-subject-sub", c.subtitle));
507
+ const x = n("div", "ocw-tags");
508
+ if (l) for (const [y, p] of Object.entries(l.fields)) x.append(n("span", "ocw-tag", `${y}: ${p}`));
509
+ else for (const y of (c == null ? void 0 : c.tags) ?? []) x.append(n("span", "ocw-tag", y));
510
+ x.childNodes.length && this.subjectCard.append(x);
511
+ const w = (l == null ? void 0 : l.state) ?? (c == null ? void 0 : c.status);
604
512
  w && (this.statusBadge.textContent = w, this.statusBadge.style.display = "inline-flex");
605
513
  }
606
514
  chipEl(e) {
607
- const i = o("button", "ocw-chip", e.icon ? `${e.icon} ${e.label}` : e.label);
608
- return i.dataset.actionId = e.id, i.addEventListener("click", async () => {
609
- var s;
610
- e.confirm && !await this.confirm(e.label) || ((s = e.input) != null && s.length ? this.openForm(e) : this.h.onInvoke(e.id));
611
- }), i;
515
+ const l = n("button", "ocw-chip", e.icon ? `${e.icon} ${e.label}` : e.label);
516
+ return l.dataset.actionId = e.id, l.addEventListener("click", async () => {
517
+ var c;
518
+ e.confirm && !await this.confirm(e.label) || ((c = e.input) != null && c.length ? this.openForm(e) : this.h.onInvoke(e.id));
519
+ }), l;
612
520
  }
613
521
  /** In-widget confirmation modal (replaces window.confirm). */
614
522
  confirm(e) {
615
- return new Promise((i) => {
616
- const s = o("div", "ocw-modal"), a = o("div", "ocw-modal-card");
617
- a.append(o("div", "ocw-modal-title", e)), a.append(o("div", "ocw-modal-body", `Confirm “${e}”?`));
618
- const c = o("div", "ocw-modal-actions"), w = o("button", "ocw-modal-cancel", "Cancel"), b = o("button", "ocw-modal-ok", "Confirm"), l = (h) => {
619
- s.remove(), i(h);
523
+ return new Promise((l) => {
524
+ const c = n("div", "ocw-modal"), i = n("div", "ocw-modal-card");
525
+ i.append(n("div", "ocw-modal-title", e)), i.append(n("div", "ocw-modal-body", `Confirm “${e}”?`));
526
+ const x = n("div", "ocw-modal-actions"), w = n("button", "ocw-modal-cancel", "Cancel"), y = n("button", "ocw-modal-ok", "Confirm"), p = (h) => {
527
+ c.remove(), l(h);
620
528
  };
621
- w.addEventListener("click", () => l(!1)), b.addEventListener("click", () => l(!0)), s.addEventListener("click", (h) => {
622
- h.target === s && l(!1);
623
- }), c.append(w, b), a.append(c), s.append(a), this.root.append(s), b.focus();
529
+ w.addEventListener("click", () => p(!1)), y.addEventListener("click", () => p(!0)), c.addEventListener("click", (h) => {
530
+ h.target === c && p(!1);
531
+ }), x.append(w, y), i.append(x), c.append(i), this.root.append(c), y.focus();
624
532
  });
625
533
  }
626
534
  /** Inline form for a form-effect action: typed inputs (date picker, number,
627
535
  * text) rendered above the composer — no browser prompts. */
628
536
  openForm(e) {
629
- var b, l;
537
+ var y, p;
630
538
  this.formHost.replaceChildren();
631
- const i = o("div", "ocw-form");
632
- i.append(o("div", "ocw-form-title", e.icon ? `${e.icon} ${e.label}` : e.label));
633
- const s = /* @__PURE__ */ new Map();
539
+ const l = n("div", "ocw-form");
540
+ l.append(n("div", "ocw-form-title", e.icon ? `${e.icon} ${e.label}` : e.label));
541
+ const c = /* @__PURE__ */ new Map();
634
542
  for (const h of e.input ?? []) {
635
- const v = o("label", "ocw-form-row");
636
- if (v.append(o("span", "ocw-form-lbl", h.label)), h.type === "select" && ((b = h.options) != null && b.length)) {
637
- const r = o("select", "ocw-form-input");
638
- h.required || r.append(o("option", void 0, "— select —"));
639
- for (const u of h.options) {
640
- const d = o("option");
641
- d.value = u, d.textContent = u, r.append(d);
543
+ const b = n("label", "ocw-form-row");
544
+ if (b.append(n("span", "ocw-form-lbl", h.label)), h.type === "select" && ((y = h.options) != null && y.length)) {
545
+ const a = n("select", "ocw-form-input");
546
+ h.required || a.append(n("option", void 0, "— select —"));
547
+ for (const P of h.options) {
548
+ const I = n("option");
549
+ I.value = P, I.textContent = P, a.append(I);
642
550
  }
643
- h.required && (r.required = !0), v.append(r), s.set(h.name, r);
551
+ h.required && (a.required = !0), b.append(a), c.set(h.name, a);
644
552
  } else {
645
- const r = o("input", "ocw-form-input");
646
- r.type = h.type === "number" ? "number" : h.type === "date" ? "datetime-local" : "text", h.required && (r.required = !0), v.append(r), s.set(h.name, r);
553
+ const a = n("input", "ocw-form-input");
554
+ a.type = h.type === "number" ? "number" : h.type === "date" ? "datetime-local" : "text", h.required && (a.required = !0), b.append(a), c.set(h.name, a);
647
555
  }
648
- i.append(v);
556
+ l.append(b);
649
557
  }
650
- const a = o("div", "ocw-form-actions"), c = o("button", "ocw-form-cancel", "Cancel"), w = o("button", "ocw-form-submit", "Send");
651
- c.addEventListener("click", () => this.formHost.replaceChildren()), w.addEventListener("click", () => {
558
+ const i = n("div", "ocw-form-actions"), x = n("button", "ocw-form-cancel", "Cancel"), w = n("button", "ocw-form-submit", "Send");
559
+ x.addEventListener("click", () => this.formHost.replaceChildren()), w.addEventListener("click", () => {
652
560
  const h = {};
653
- for (const [v, r] of s) {
654
- if (r.required && !r.value) {
655
- r.style.borderColor = "#e5484d";
561
+ for (const [b, a] of c) {
562
+ if (a.required && !a.value) {
563
+ a.style.borderColor = "#e5484d";
656
564
  return;
657
565
  }
658
- h[v] = r.type === "number" ? Number(r.value) : r.value;
566
+ h[b] = a.type === "number" ? Number(a.value) : a.value;
659
567
  }
660
568
  this.formHost.replaceChildren(), this.h.onInvoke(e.id, h);
661
- }), a.append(c, w), i.append(a), this.formHost.append(i), (l = s.values().next().value) == null || l.focus();
569
+ }), i.append(x, w), l.append(i), this.formHost.append(l), (p = c.values().next().value) == null || p.focus();
662
570
  }
663
- messageEl(e, i) {
664
- var r;
571
+ messageEl(e, l, c = !1) {
572
+ var P, I, M, j;
665
573
  if (e.senderRole === "system") {
666
- const u = o("div", "ocw-sys");
667
- return u.textContent = e.deletedAt ? "message deleted" : ie(e.content), u;
574
+ const d = n("div", "ocw-sys");
575
+ return d.textContent = e.deletedAt ? "message deleted" : ae(e.content), d;
576
+ }
577
+ const i = e.senderId === this.me, x = !!e.internal, w = n("div", `ocw-row ${x ? "ocw-note mine" : i ? "mine" : "theirs"} ${e.senderRole === "bot" ? "ocw-bot" : ""}`);
578
+ !i && !x && w.append(n("div", "ocw-dot", e.senderRole === "bot" ? "🤖" : "🧑"));
579
+ const y = n("div");
580
+ if (c) {
581
+ const d = e.senderRole === "bot" ? ((P = this.cfg.i18n) == null ? void 0 : P.aiAssistant) ?? "AI Assistant" : ((I = this.cfg.subject) == null ? void 0 : I.ownerLabel) ?? ((M = this.cfg.subject) == null ? void 0 : M.title) ?? "Support";
582
+ y.append(n("div", "ocw-msg-sender", d));
668
583
  }
669
- const s = e.senderId === this.me, a = !!e.internal, c = o("div", `ocw-row ${a ? "ocw-note mine" : s ? "mine" : "theirs"} ${e.senderRole === "bot" ? "ocw-bot" : ""}`);
670
- !s && !a && c.append(o("div", "ocw-dot", e.senderRole === "bot" ? "🤖" : "🧑"));
671
- const w = o("div"), b = o("div", "ocw-bubble-wrap");
584
+ const p = n("div", "ocw-bubble-wrap");
672
585
  if (e.replyToId) {
673
- const u = o("div", "ocw-reply-to", "↩ replying to a message");
674
- u.style.cssText = "font-size:11px;color:var(--ocw-mut);margin-bottom:2px;font-style:italic", w.append(u);
586
+ const d = n("div", "ocw-reply-to", "↩ replying to a message");
587
+ d.style.cssText = "font-size:11px;color:var(--ocw-mut);margin-bottom:2px;font-style:italic", y.append(d);
675
588
  }
676
- const l = o("div", "ocw-bubble");
677
- let h = null;
678
- if (e.deletedAt) l.append(o("span", "ocw-deleted", "message deleted"));
589
+ const h = n("div", "ocw-bubble");
590
+ let b = null;
591
+ if (e.deletedAt) h.append(n("span", "ocw-deleted", "message deleted"));
679
592
  else if (e.content.kind === "attachment") {
680
- const u = e.content;
681
- if ((r = u.mime) != null && r.startsWith("image/")) {
682
- const d = document.createElement("img");
683
- d.src = u.url, d.alt = u.name ?? "image", d.style.cssText = "max-width:220px;max-height:160px;border-radius:10px;display:block;cursor:pointer", d.addEventListener("click", () => window.open(u.url, "_blank")), l.append(d);
593
+ const d = e.content;
594
+ if ((j = d.mime) != null && j.startsWith("image/")) {
595
+ const r = document.createElement("img");
596
+ r.src = d.url, r.alt = d.name ?? "image", r.style.cssText = "max-width:220px;max-height:160px;border-radius:10px;display:block;cursor:pointer", r.addEventListener("click", () => window.open(d.url, "_blank")), h.append(r);
684
597
  } else {
685
- const d = document.createElement("a");
686
- d.href = u.url, d.target = "_blank", d.rel = "noopener", d.style.cssText = "display:flex;align-items:center;gap:8px;color:inherit;text-decoration:none", d.append(o("span", void 0, "📄"), o("span", void 0, u.name ?? "file")), l.append(d);
598
+ const r = document.createElement("a");
599
+ r.href = d.url, r.target = "_blank", r.rel = "noopener", r.style.cssText = "display:flex;align-items:center;gap:8px;color:inherit;text-decoration:none", r.append(n("span", void 0, "📄"), n("span", void 0, d.name ?? "file")), h.append(r);
687
600
  }
688
601
  } else if (e.content.kind === "appointment") {
689
- const u = e.content, d = o("div", "ocw-appt");
690
- d.append(o("div", "ocw-appt-title", `📅 ${u.title}`)), d.append(o("div", "ocw-appt-time", new Date(u.startIso).toLocaleString() + " – " + new Date(u.endIso).toLocaleTimeString())), u.location && d.append(o("div", "ocw-appt-loc", `📍 ${u.location}`)), u.description && d.append(o("div", "ocw-appt-desc", u.description));
691
- const E = o("div", "ocw-appt-links"), m = document.createElement("a");
692
- m.href = u.googleUrl, m.target = "_blank", m.rel = "noopener", m.className = "ocw-appt-btn", m.textContent = "📅 Add to Google Calendar";
693
- const f = document.createElement("a");
694
- f.href = u.icalUrl, f.download = `${u.title}.ics`, f.className = "ocw-appt-btn ocw-appt-btn-sec", f.textContent = "🍎 Apple / iCal", E.append(m, f), d.append(E), l.append(d);
602
+ const d = e.content, r = n("div", "ocw-appt");
603
+ r.append(n("div", "ocw-appt-title", `📅 ${d.title}`)), r.append(n("div", "ocw-appt-time", new Date(d.startIso).toLocaleString() + " – " + new Date(d.endIso).toLocaleTimeString())), d.location && r.append(n("div", "ocw-appt-loc", `📍 ${d.location}`)), d.description && r.append(n("div", "ocw-appt-desc", d.description));
604
+ const C = n("div", "ocw-appt-links"), v = document.createElement("a");
605
+ v.href = d.googleUrl, v.target = "_blank", v.rel = "noopener", v.className = "ocw-appt-btn", v.textContent = "📅 Add to Google Calendar";
606
+ const u = document.createElement("a");
607
+ u.href = d.icalUrl, u.download = `${d.title}.ics`, u.className = "ocw-appt-btn ocw-appt-btn-sec", u.textContent = "🍎 Apple / iCal", C.append(v, u), r.append(C), h.append(r);
695
608
  } else
696
- h = document.createTextNode(ie(e.content)), l.append(h), e.editedAt && l.append(o("span", "ocw-edited", "(edited)"));
697
- if (b.append(l), !s && !a && this.h.onTranslate && e.content.kind === "text" && !e.deletedAt && e.seq > 0 && h) {
698
- const u = e.content.text;
699
- if (u.trim()) {
700
- const d = o("button", "ocw-translate-btn", "🌐");
701
- d.type = "button", d.title = "Translate", d.addEventListener("click", (E) => {
702
- if (E.stopPropagation(), this.showingTranslation.has(e.id)) {
703
- this.showingTranslation.delete(e.id), h.textContent = u, d.textContent = "🌐", d.title = "Translate";
609
+ b = document.createTextNode(ae(e.content)), h.append(b), e.editedAt && h.append(n("span", "ocw-edited", "(edited)"));
610
+ if (p.append(h), !i && !x && this.h.onTranslate && e.content.kind === "text" && !e.deletedAt && e.seq > 0 && b) {
611
+ const d = e.content.text;
612
+ if (d.trim()) {
613
+ const r = n("button", "ocw-translate-btn", "🌐");
614
+ r.type = "button", r.title = "Translate", r.addEventListener("click", (C) => {
615
+ if (C.stopPropagation(), this.showingTranslation.has(e.id)) {
616
+ this.showingTranslation.delete(e.id), b.textContent = d, r.textContent = "🌐", r.title = "Translate";
704
617
  return;
705
618
  }
706
- const m = this.translationCache.get(e.id);
707
- if (m !== void 0) {
708
- this.showingTranslation.add(e.id), h.textContent = m, d.textContent = "↩", d.title = "Show original";
619
+ const v = this.translationCache.get(e.id);
620
+ if (v !== void 0) {
621
+ this.showingTranslation.add(e.id), b.textContent = v, r.textContent = "↩", r.title = "Show original";
709
622
  return;
710
623
  }
711
- d.textContent = "⏳", this.h.onTranslate(u).then((f) => {
712
- if (f === null) {
713
- d.textContent = "⚠️", d.title = "Translation unavailable", setTimeout(() => {
714
- d.textContent = "🌐", d.title = "Translate";
624
+ r.textContent = "⏳", this.h.onTranslate(d).then((u) => {
625
+ if (u === null) {
626
+ r.textContent = "⚠️", r.title = "Translation unavailable", setTimeout(() => {
627
+ r.textContent = "🌐", r.title = "Translate";
715
628
  }, 1500);
716
629
  return;
717
630
  }
718
- this.translationCache.set(e.id, f), this.showingTranslation.add(e.id), h.textContent = f, d.textContent = "↩", d.title = "Show original";
631
+ this.translationCache.set(e.id, u), this.showingTranslation.add(e.id), b.textContent = u, r.textContent = "↩", r.title = "Show original";
719
632
  });
720
- }), b.append(d);
633
+ }), p.append(r);
721
634
  }
722
635
  }
723
- if (s && !e.deletedAt && e.seq > 0 && (this.h.onEdit ?? this.h.onDelete)) {
724
- const u = o("div", "ocw-msg-menu");
636
+ if (i && !e.deletedAt && e.seq > 0 && (this.h.onEdit ?? this.h.onDelete)) {
637
+ const d = n("div", "ocw-msg-menu");
725
638
  if (this.h.onEdit) {
726
- const d = o("button", void 0, "✏️");
727
- d.title = "Edit", d.addEventListener("click", (E) => {
728
- E.stopPropagation();
729
- const m = ie(e.content), f = document.createElement("textarea");
730
- f.value = m, f.rows = Math.min(4, Math.ceil(m.length / 40) + 1), f.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";
731
- const k = o("button", "ocw-form-submit", "Save");
732
- k.style.cssText = "margin-top:6px;padding:5px 14px;font-size:13px";
733
- const I = o("button", "ocw-form-cancel", "Cancel");
734
- I.style.cssText = "margin-top:6px;padding:5px 10px;font-size:13px";
735
- const P = o("div");
736
- P.style.cssText = "display:flex;gap:6px;justify-content:flex-end", P.append(I, k);
737
- const C = o("div");
738
- C.append(f, P), l.replaceChildren(C), f.focus(), f.select();
739
- const R = () => l.replaceChildren(h ?? document.createTextNode(m));
740
- I.addEventListener("click", R), k.addEventListener("click", () => {
741
- const A = f.value.trim();
742
- A && A !== m && this.h.onEdit(e.id, A), R();
743
- }), f.addEventListener("keydown", (A) => {
744
- A.key === "Enter" && !A.shiftKey && (A.preventDefault(), k.click()), A.key === "Escape" && R();
639
+ const r = n("button", void 0, "✏️");
640
+ r.title = "Edit", r.addEventListener("click", (C) => {
641
+ C.stopPropagation();
642
+ const v = ae(e.content), u = document.createElement("textarea");
643
+ u.value = v, u.rows = Math.min(4, Math.ceil(v.length / 40) + 1), u.style.cssText = "width:100%;resize:vertical;border:1px solid var(--ocw-accent);border-radius:8px;padding:6px 10px;font:inherit;font-size:14px;background:var(--ocw-card);color:#1c1b1a;box-sizing:border-box";
644
+ const f = n("button", "ocw-form-submit", "Save");
645
+ f.style.cssText = "margin-top:6px;padding:5px 14px;font-size:13px";
646
+ const R = n("button", "ocw-form-cancel", "Cancel");
647
+ R.style.cssText = "margin-top:6px;padding:5px 10px;font-size:13px";
648
+ const B = n("div");
649
+ B.style.cssText = "display:flex;gap:6px;justify-content:flex-end", B.append(R, f);
650
+ const A = n("div");
651
+ A.append(u, B), h.replaceChildren(A), u.focus(), u.select();
652
+ const k = () => h.replaceChildren(b ?? document.createTextNode(v));
653
+ R.addEventListener("click", k), f.addEventListener("click", () => {
654
+ const S = u.value.trim();
655
+ S && S !== v && this.h.onEdit(e.id, S), k();
656
+ }), u.addEventListener("keydown", (S) => {
657
+ S.key === "Enter" && !S.shiftKey && (S.preventDefault(), f.click()), S.key === "Escape" && k();
745
658
  });
746
- }), u.append(d);
659
+ }), d.append(r);
747
660
  }
748
661
  if (this.h.onDelete) {
749
- const d = o("button", "del", "🗑");
750
- d.title = "Delete", d.addEventListener("click", (E) => {
751
- E.stopPropagation(), this.h.onDelete(e.id);
752
- }), u.append(d);
662
+ const r = n("button", "del", "🗑");
663
+ r.title = "Delete", r.addEventListener("click", (C) => {
664
+ C.stopPropagation(), this.h.onDelete(e.id);
665
+ }), d.append(r);
753
666
  }
754
- b.append(u);
667
+ p.append(d);
755
668
  }
756
- if (w.append(b), this.h.onReact && !e.deletedAt && e.seq > 0) {
757
- const u = o("div", "ocw-react-wrap"), d = o("div", "ocw-react");
669
+ if (y.append(p), this.h.onReact && !e.deletedAt && e.seq > 0) {
670
+ const d = n("div", "ocw-react-wrap"), r = n("div", "ocw-react");
758
671
  if (e.reactions && Object.keys(e.reactions).length)
759
- for (const [f, k] of Object.entries(e.reactions)) {
760
- const I = o("button", `ocw-react-pill${k.includes(this.me) ? " mine" : ""}`, `${f} ${k.length}`);
761
- I.addEventListener("click", () => {
762
- var P, C;
763
- return (C = (P = this.h).onReact) == null ? void 0 : C.call(P, e.id, f, k.includes(this.me));
764
- }), d.append(I);
672
+ for (const [u, f] of Object.entries(e.reactions)) {
673
+ const R = n("button", `ocw-react-pill${f.includes(this.me) ? " mine" : ""}`, `${u} ${f.length}`);
674
+ R.addEventListener("click", () => {
675
+ var B, A;
676
+ return (A = (B = this.h).onReact) == null ? void 0 : A.call(B, e.id, u, f.includes(this.me));
677
+ }), r.append(R);
765
678
  }
766
- const E = o("button", "ocw-react-btn", "+"), m = o("div", "ocw-react-picker");
767
- for (const f of He) {
768
- const k = o("button", void 0, f);
769
- k.addEventListener("click", (I) => {
770
- var C, R, A, N;
771
- I.stopPropagation();
772
- const P = (R = (C = e.reactions) == null ? void 0 : C[f]) == null ? void 0 : R.includes(this.me);
773
- (N = (A = this.h).onReact) == null || N.call(A, e.id, f, !!P), m.style.display = "none";
774
- }), m.append(k);
679
+ const C = n("button", "ocw-react-btn", "+"), v = n("div", "ocw-react-picker");
680
+ for (const u of Fe) {
681
+ const f = n("button", void 0, u);
682
+ f.addEventListener("click", (R) => {
683
+ var A, k, S, D;
684
+ R.stopPropagation();
685
+ const B = (k = (A = e.reactions) == null ? void 0 : A[u]) == null ? void 0 : k.includes(this.me);
686
+ (D = (S = this.h).onReact) == null || D.call(S, e.id, u, !!B), v.style.display = "none";
687
+ }), v.append(f);
775
688
  }
776
- m.style.display = "none", E.addEventListener("click", (f) => {
777
- f.stopPropagation();
778
- const k = m.style.display === "none";
779
- m.style.display = k ? "flex" : "none", k && document.addEventListener("click", () => {
780
- m.style.display = "none";
689
+ v.style.display = "none", C.addEventListener("click", (u) => {
690
+ u.stopPropagation();
691
+ const f = v.style.display === "none";
692
+ v.style.display = f ? "flex" : "none", f && document.addEventListener("click", () => {
693
+ v.style.display = "none";
781
694
  }, { once: !0 });
782
- }), d.append(E), u.append(d, m), w.append(u);
783
- } else e.reactions && Object.keys(e.reactions).length && w.append(o("div", "ocw-react", Object.entries(e.reactions).map(([u, d]) => `${u}${d.length}`).join(" ")));
784
- const v = o("div", "ocw-time ocw-meta", Ve(e.ts));
785
- if (s && e.status) {
786
- const u = o("span", `ocw-tick${e.status === "read" ? " read" : e.status === "delivered" ? " delivered" : ""}`, Ge(e.status));
787
- v.append(u);
695
+ }), r.append(C), d.append(r, v), y.append(d);
696
+ } else e.reactions && Object.keys(e.reactions).length && y.append(n("div", "ocw-react", Object.entries(e.reactions).map(([d, r]) => `${d}${r.length}`).join(" ")));
697
+ const a = n("div", "ocw-time ocw-meta", Ye(e.ts));
698
+ if (i && e.status) {
699
+ const d = n("span", `ocw-tick${e.status === "read" ? " read" : e.status === "delivered" ? " delivered" : ""}`, Qe(e.status));
700
+ a.append(d);
788
701
  }
789
- return s && e.seq > 0 && i.lastReadByOthers >= e.seq && v.append(o("span", "ocw-seen", " · Seen")), w.append(v), c.append(w), c;
702
+ return i && e.seq > 0 && l.lastReadByOthers >= e.seq && a.append(n("span", "ocw-seen", " · Seen")), y.append(a), w.append(y), w;
790
703
  }
791
704
  }
792
- function Ge(t) {
705
+ function Qe(t) {
793
706
  switch (t) {
794
707
  case "read":
795
708
  return "✓✓";
@@ -801,40 +714,40 @@ function Ge(t) {
801
714
  return "🕓";
802
715
  }
803
716
  }
804
- const O = /* @__PURE__ */ new WeakMap(), Q = /* @__PURE__ */ new Map();
805
- function me(t) {
717
+ const _ = /* @__PURE__ */ new WeakMap(), Z = /* @__PURE__ */ new Map();
718
+ function ke(t) {
806
719
  return `relay-launcher::${t.profileId}::${t.subjectId ?? ""}`;
807
720
  }
808
- let W = null;
809
- function Ye() {
810
- if (W && W.state !== "closed") return W;
721
+ let K = null;
722
+ function Je() {
723
+ if (K && K.state !== "closed") return K;
811
724
  try {
812
- return W = new AudioContext(), W;
725
+ return K = new AudioContext(), K;
813
726
  } catch {
814
727
  return null;
815
728
  }
816
729
  }
817
- function tt(t) {
730
+ function it(t) {
818
731
  var e;
819
- (e = O.get(t)) == null || e.close(), O.delete(t);
732
+ (e = _.get(t)) == null || e.close(), _.delete(t);
820
733
  }
821
- function ot(t) {
822
- var le, de, pe, he, ue;
823
- O.has(t.el) && (O.get(t.el).close(), O.delete(t.el)), t.launcher && ((le = Q.get(me(t))) == null || le.close());
824
- const e = Pe();
825
- let i, s = !1;
826
- const a = t.token ?? t.userId ?? e, c = a !== e ? e : void 0, { wsUrl: w, httpBase: b } = Ae(t.url, t.apiUrl);
827
- let l = new Me(a);
828
- const h = t.subjectId ? `${a}::${t.subjectId}` : a, v = new $e(h);
829
- let r, u = !1, d = null, E = null, m = null, f = null;
734
+ function at(t) {
735
+ var se, le, de, pe, he, ue, fe, we;
736
+ _.has(t.el) && (_.get(t.el).close(), _.delete(t.el)), t.launcher && ((se = Z.get(ke(t))) == null || se.close());
737
+ const e = Re();
738
+ let l, c = !1;
739
+ const i = t.token ?? t.userId ?? e, x = i !== e ? e : void 0, { wsUrl: w, httpBase: y } = Ae(t.url, t.apiUrl);
740
+ let p = new Oe(i);
741
+ const h = t.subjectId ? `${i}::${t.subjectId}` : i, b = new Ne(h);
742
+ let a, P = !1, I = null, M = null, j = null, d = null;
830
743
  !t.launcher && !t.el.style.height && t.el.clientHeight === 0 && (t.el.style.width = t.el.style.width || "100%", t.el.style.height = "600px");
831
- for (const n of v.load()) l.addOptimistic(n.clientMsgId, n.content);
832
- let k = null, I = null, P = 0, C = !t.launcher;
744
+ for (const o of b.load()) p.addOptimistic(o.clientMsgId, o.content);
745
+ let r = null, C = null, v = 0, u = !t.launcher;
833
746
  if (t.launcher) {
834
- const p = (t.position ?? "bottom-right").includes("right");
835
- k = document.createElement("div"), k.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`;
836
- const x = document.createElement("div"), j = typeof window < "u" && typeof window.matchMedia == "function" ? window.matchMedia("(max-width: 479px)") : null, F = (L) => {
837
- t.el.classList.toggle("ocw-fs", L), x.style.cssText = L ? [
747
+ const s = (t.position ?? "bottom-right").includes("right");
748
+ r = document.createElement("div"), r.style.cssText = `position:fixed;${s ? "right:20px" : "left:20px"};bottom:20px;z-index:9999;display:flex;flex-direction:column;align-items:${s ? "flex-end" : "flex-start"};gap:12px`;
749
+ const m = document.createElement("div"), L = typeof window < "u" && typeof window.matchMedia == "function" ? window.matchMedia("(max-width: 479px)") : null, W = (z) => {
750
+ t.el.classList.toggle("ocw-fs", z), m.style.cssText = z ? [
838
751
  "position:fixed",
839
752
  "inset:0",
840
753
  "width:100%",
@@ -851,268 +764,268 @@ function ot(t) {
851
764
  ].join(";") : [
852
765
  "width:min(380px, calc(100vw - 40px))",
853
766
  "height:min(600px, calc(100dvh - 108px))",
854
- "border-radius:16px",
767
+ "border-radius:28px",
855
768
  "overflow:hidden",
856
- "box-shadow:0 8px 40px rgba(0,0,0,.18)",
769
+ "box-shadow:0 12px 32px rgba(108,92,231,.14)",
857
770
  "display:none",
858
771
  "flex-direction:column",
859
772
  "background:#fff",
860
- "transform-origin:bottom " + (p ? "right" : "left"),
773
+ "transform-origin:bottom " + (s ? "right" : "left"),
861
774
  "transition:opacity .18s,transform .18s",
862
775
  "opacity:0",
863
776
  "transform:scale(.95)"
864
777
  ].join(";");
865
778
  };
866
- F((j == null ? void 0 : j.matches) ?? !1);
867
- const U = (L) => F(L.matches);
868
- j == null || j.addEventListener("change", U), d = j, E = U, t.el.style.cssText = "width:100%;height:100%;overflow:hidden", x.append(t.el);
869
- const G = '<svg viewBox="0 0 24 24" width="26" height="26" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>', Y = '<svg viewBox="0 0 24 24" width="22" height="22" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>', M = document.createElement("button");
870
- M.type = "button", M.style.cssText = [
779
+ W((L == null ? void 0 : L.matches) ?? !1);
780
+ const G = (z) => W(z.matches);
781
+ L == null || L.addEventListener("change", G), I = L, M = G, t.el.style.cssText = "width:100%;height:100%;overflow:hidden", m.append(t.el);
782
+ const Y = '<svg viewBox="0 0 24 24" width="26" height="26" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>', X = '<svg viewBox="0 0 24 24" width="22" height="22" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>', q = document.createElement("button");
783
+ q.type = "button", q.style.cssText = [
871
784
  "width:56px;height:56px;border-radius:50%",
872
- `background:${t.accent ?? "#4F63F5"}`,
785
+ `background:${t.accent ?? "#6c5ce7"}`,
873
786
  "color:#fff;border:none;cursor:pointer",
874
- "box-shadow:0 4px 16px rgba(0,0,0,.25)",
787
+ "box-shadow:0 12px 32px rgba(108,92,231,.14)",
875
788
  "position:relative;flex:none",
876
789
  "display:flex;align-items:center;justify-content:center",
877
790
  "transition:transform .15s"
878
- ].join(";"), M.onmouseenter = () => {
879
- M.style.transform = "scale(1.08)";
880
- }, M.onmouseleave = () => {
881
- M.style.transform = "scale(1)";
882
- }, I = document.createElement("span"), I.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";
883
- const X = () => {
884
- M.innerHTML = C ? Y : G, M.setAttribute("aria-label", C ? "Close chat" : "Open chat"), M.setAttribute("aria-expanded", String(C)), M.append(I);
791
+ ].join(";"), q.onmouseenter = () => {
792
+ q.style.transform = "scale(1.08)";
793
+ }, q.onmouseleave = () => {
794
+ q.style.transform = "scale(1)";
795
+ }, C = document.createElement("span"), C.style.cssText = "position:absolute;top:-4px;right:-4px;background:#4c6fff;color:#fff;border-radius:50%;width:20px;height:20px;font-size:11px;font-weight:700;display:none;align-items:center;justify-content:center";
796
+ const Q = () => {
797
+ q.innerHTML = u ? X : Y, q.setAttribute("aria-label", u ? "Close chat" : "Open chat"), q.setAttribute("aria-expanded", String(u)), q.append(C);
885
798
  };
886
- X(), k.append(x, M), document.body.append(k);
887
- const ee = `ocw-teaser-dismissed::${t.profileId}`, J = typeof t.launcherMessage == "string" ? { title: t.launcherMessage } : t.launcherMessage;
888
- let z = null;
889
- const Se = () => {
799
+ Q(), r.append(m, q), document.body.append(r);
800
+ const te = `ocw-teaser-dismissed::${t.profileId}`, J = typeof t.launcherMessage == "string" ? { title: t.launcherMessage } : t.launcherMessage;
801
+ let E = null;
802
+ const Le = () => {
890
803
  try {
891
- return sessionStorage.getItem(ee) === "1";
804
+ return sessionStorage.getItem(te) === "1";
892
805
  } catch {
893
806
  return !1;
894
807
  }
895
- }, ze = '<svg viewBox="0 0 24 24" width="15" height="15" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>', fe = () => {
896
- const L = J != null && J.title ? J : l.launcherMessage ?? void 0;
897
- if (!(!!(L != null && L.title) && !C && !Se())) {
898
- z && (z.remove(), z = null);
808
+ }, Pe = '<svg viewBox="0 0 24 24" width="15" height="15" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" fill="currentColor" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>', be = () => {
809
+ const z = J != null && J.title ? J : p.launcherMessage ?? void 0;
810
+ if (!(!!(z != null && z.title) && !u && !Le())) {
811
+ E && (E.remove(), E = null);
899
812
  return;
900
813
  }
901
- if (z) return;
902
- z = document.createElement("div"), z.setAttribute("role", "button"), z.setAttribute("tabindex", "0"), z.setAttribute("aria-label", L.title), z.style.cssText = [
814
+ if (E) return;
815
+ E = document.createElement("div"), E.setAttribute("role", "button"), E.setAttribute("tabindex", "0"), E.setAttribute("aria-label", z.title), E.style.cssText = [
903
816
  "max-width:280px",
904
817
  "background:#fff",
905
- "border-radius:14px",
906
- "box-shadow:0 6px 28px rgba(0,0,0,.16)",
818
+ "border-radius:16px",
819
+ "box-shadow:0 12px 32px rgba(108,92,231,.14)",
907
820
  "padding:14px 40px 14px 16px",
908
821
  "position:relative",
909
822
  "cursor:pointer",
910
823
  "font-family:inherit",
911
- `align-self:${p ? "flex-end" : "flex-start"}`,
824
+ `align-self:${s ? "flex-end" : "flex-start"}`,
912
825
  "animation:ocw-teaser-in .22s ease-out"
913
826
  ].join(";");
914
827
  const oe = document.createElement("div");
915
- if (oe.textContent = L.title, oe.style.cssText = "font-size:15px;font-weight:600;color:#111;line-height:1.35", z.append(oe), L.subtitle) {
916
- const D = document.createElement("div");
917
- D.style.cssText = "display:flex;align-items:center;gap:6px;margin-top:6px;font-size:13px;color:#6b7280";
918
- const ne = document.createElement("span");
919
- ne.innerHTML = ze, ne.style.cssText = `color:${t.accent ?? "#4F63F5"};display:inline-flex`;
920
- const be = document.createElement("span");
921
- be.textContent = L.subtitle, D.append(ne, be), z.append(D);
828
+ if (oe.textContent = z.title, oe.style.cssText = "font-size:15px;font-weight:600;color:#111;line-height:1.35", E.append(oe), z.subtitle) {
829
+ const O = document.createElement("div");
830
+ O.style.cssText = "display:flex;align-items:center;gap:6px;margin-top:6px;font-size:13px;color:#6b7280";
831
+ const ie = document.createElement("span");
832
+ ie.innerHTML = Pe, ie.style.cssText = `color:${t.accent ?? "#6c5ce7"};display:inline-flex`;
833
+ const me = document.createElement("span");
834
+ me.textContent = z.subtitle, O.append(ie, me), E.append(O);
922
835
  }
923
- const H = document.createElement("button");
924
- H.type = "button", H.setAttribute("aria-label", "Dismiss"), H.innerHTML = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18 6 6 18M6 6l12 12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>', H.style.cssText = "position:absolute;top:8px;right:8px;width:24px;height:24px;border:none;border-radius:50%;background:#f3f4f6;color:#6b7280;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0", H.addEventListener("click", (D) => {
925
- D.stopPropagation();
836
+ const U = document.createElement("button");
837
+ U.type = "button", U.setAttribute("aria-label", "Dismiss"), U.innerHTML = '<svg viewBox="0 0 24 24" width="14" height="14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18 6 6 18M6 6l12 12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"/></svg>', U.style.cssText = "position:absolute;top:8px;right:8px;width:24px;height:24px;border:none;border-radius:50%;background:#f3f4f6;color:#6b7280;cursor:pointer;display:flex;align-items:center;justify-content:center;padding:0", U.addEventListener("click", (O) => {
838
+ O.stopPropagation();
926
839
  try {
927
- sessionStorage.setItem(ee, "1");
840
+ sessionStorage.setItem(te, "1");
928
841
  } catch {
929
842
  }
930
- z && (z.remove(), z = null);
931
- }), z.append(H);
932
- const we = () => {
933
- C || (C = !0, te(!0), X(), P = 0, I && (I.style.display = "none"), z && (z.remove(), z = null));
843
+ E && (E.remove(), E = null);
844
+ }), E.append(U);
845
+ const xe = () => {
846
+ u || (u = !0, ne(!0), Q(), v = 0, C && (C.style.display = "none"), E && (E.remove(), E = null));
934
847
  };
935
- z.addEventListener("click", we), z.addEventListener("keydown", (D) => {
936
- (D.key === "Enter" || D.key === " ") && (D.preventDefault(), we());
937
- }), k.insertBefore(z, M);
848
+ E.addEventListener("click", xe), E.addEventListener("keydown", (O) => {
849
+ (O.key === "Enter" || O.key === " ") && (O.preventDefault(), xe());
850
+ }), r.insertBefore(E, q);
938
851
  };
939
852
  if (!document.getElementById("ocw-teaser-style")) {
940
- const L = document.createElement("style");
941
- L.id = "ocw-teaser-style", L.textContent = "@keyframes ocw-teaser-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}", document.head.append(L);
853
+ const z = document.createElement("style");
854
+ z.id = "ocw-teaser-style", z.textContent = "@keyframes ocw-teaser-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}", document.head.append(z);
942
855
  }
943
- f = fe, fe();
944
- const te = (L) => {
945
- L ? (x.style.display = "flex", requestAnimationFrame(() => {
946
- x.style.opacity = "1", x.style.transform = "scale(1)";
947
- })) : (x.style.opacity = "0", x.style.transform = "scale(.95)", setTimeout(() => {
948
- C || (x.style.display = "none");
856
+ d = be, be();
857
+ const ne = (z) => {
858
+ z ? (m.style.display = "flex", requestAnimationFrame(() => {
859
+ m.style.opacity = "1", m.style.transform = "scale(1)";
860
+ })) : (m.style.opacity = "0", m.style.transform = "scale(.95)", setTimeout(() => {
861
+ u || (m.style.display = "none");
949
862
  }, 180));
950
863
  };
951
- M.addEventListener("click", () => {
952
- if (C = !C, te(C), X(), C) {
953
- P = 0, I && (I.style.display = "none");
864
+ q.addEventListener("click", () => {
865
+ if (u = !u, ne(u), Q(), u) {
866
+ v = 0, C && (C.style.display = "none");
954
867
  try {
955
- sessionStorage.setItem(ee, "1");
868
+ sessionStorage.setItem(te, "1");
956
869
  } catch {
957
870
  }
958
871
  }
959
- f == null || f();
960
- }), m = (L) => {
961
- L.key === "Escape" && C && (C = !1, te(!1), X());
962
- }, document.addEventListener("keydown", m);
872
+ d == null || d();
873
+ }), j = (z) => {
874
+ z.key === "Escape" && u && (u = !1, ne(!1), Q());
875
+ }, document.addEventListener("keydown", j);
963
876
  }
964
- const R = () => {
965
- C || (P++, I && (I.textContent = String(P), I.style.display = "flex"));
966
- }, A = () => {
877
+ const f = () => {
878
+ u || (v++, C && (C.textContent = String(v), C.style.display = "flex"));
879
+ }, R = () => {
967
880
  try {
968
- const n = Ye();
969
- if (!n) return;
970
- n.state === "suspended" && n.resume().catch(() => {
881
+ const o = Je();
882
+ if (!o) return;
883
+ o.state === "suspended" && o.resume().catch(() => {
971
884
  });
972
- const p = n.createOscillator(), x = n.createGain();
973
- 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);
885
+ const s = o.createOscillator(), m = o.createGain();
886
+ s.connect(m), m.connect(o.destination), s.frequency.setValueAtTime(880, o.currentTime), s.frequency.exponentialRampToValueAtTime(440, o.currentTime + 0.15), m.gain.setValueAtTime(0.3, o.currentTime), m.gain.exponentialRampToValueAtTime(1e-3, o.currentTime + 0.3), s.start(), s.stop(o.currentTime + 0.3);
974
887
  } catch {
975
888
  }
976
- }, N = [], V = (n) => {
977
- for (; N.length; ) {
978
- const p = N.shift();
979
- v.add({ clientMsgId: p.clientMsgId, content: p.content, ts: Date.now() }), T.send({ type: "send", conversationId: n, clientMsgId: p.clientMsgId, content: p.content });
889
+ }, B = [], A = (o) => {
890
+ for (; B.length; ) {
891
+ const s = B.shift();
892
+ b.add({ clientMsgId: s.clientMsgId, content: s.content, ts: Date.now() }), k.send({ type: "send", conversationId: o, clientMsgId: s.clientMsgId, content: s.content });
980
893
  }
981
894
  };
982
- let T;
983
- const $ = new qe(`ocw-e2e-${t.profileId}`);
984
- let g = !1;
985
- const S = [], q = [];
986
- let se = !1;
987
- const Z = (n, p) => {
988
- $.sealText(p).then((x) => {
989
- r && T.send({ type: "send", conversationId: r, clientMsgId: n, content: x });
895
+ let k;
896
+ const S = new He(`ocw-e2e-${t.profileId}`);
897
+ let D = !1;
898
+ const g = [], N = [];
899
+ let H = !1;
900
+ const ee = (o, s) => {
901
+ S.sealText(s).then((m) => {
902
+ a && k.send({ type: "send", conversationId: a, clientMsgId: o, content: m });
990
903
  });
991
- }, ye = (n, p, x) => {
992
- $.sealText(p, x).then((j) => {
993
- r && T.send({ type: "send", conversationId: r, clientMsgId: n, content: j });
904
+ }, Ce = (o, s, m) => {
905
+ S.sealText(s, m).then((L) => {
906
+ a && k.send({ type: "send", conversationId: a, clientMsgId: o, content: L });
994
907
  });
995
- }, ve = () => {
996
- for (; S.length; ) {
997
- const n = S.shift();
998
- Z(n.clientMsgId, n.text);
908
+ }, Te = () => {
909
+ for (; g.length; ) {
910
+ const o = g.shift();
911
+ ee(o.clientMsgId, o.text);
999
912
  }
1000
- for (; q.length; ) {
1001
- const n = q.shift();
1002
- Z(n.clientMsgId, n.text);
913
+ for (; N.length; ) {
914
+ const o = N.shift();
915
+ ee(o.clientMsgId, o.text);
1003
916
  }
1004
- }, ke = (n) => {
1005
- T.send({ type: "fetchPrekey", targetUserId: n });
1006
- }, Ce = t.i18n ?? {}, Te = ["ar", "he", "fa", "ur"], Ee = typeof navigator < "u" ? (navigator.language ?? "").slice(0, 2).toLowerCase() : "";
1007
- Te.includes(Ee) && !t.el.dir && (t.el.dir = "rtl", t.el.style.fontFamily = t.el.style.fontFamily || "Tahoma,Arial,system-ui,sans-serif");
1008
- const ae = new Oe(), re = `oc_prechat_${t.profileId}_${a.slice(-8)}`, B = new Ke(t.el, a, {
1009
- onSend(n) {
1010
- const p = `cm_${Math.random().toString(36).slice(2)}`, x = { kind: "text", text: n };
1011
- l.addOptimistic(p, x), B.render(l), l.e2e ? $.ready ? Z(p, n) : se ? q.push({ clientMsgId: p, text: n }) : (S.push({ clientMsgId: p, text: n }), l.assignedAgentId && ke(l.assignedAgentId)) : r ? (v.add({ clientMsgId: p, content: x, ts: Date.now() }), T.send({ type: "send", conversationId: r, clientMsgId: p, content: x })) : N.push({ clientMsgId: p, content: x });
917
+ }, Ie = (o) => {
918
+ k.send({ type: "fetchPrekey", targetUserId: o });
919
+ }, Se = t.i18n ?? {}, Ee = ["ar", "he", "fa", "ur"], ze = typeof navigator < "u" ? (navigator.language ?? "").slice(0, 2).toLowerCase() : "";
920
+ Ee.includes(ze) && !t.el.dir && (t.el.dir = "rtl", t.el.style.fontFamily = t.el.style.fontFamily || "Tahoma,Arial,system-ui,sans-serif");
921
+ const re = `oc_prechat_${t.profileId}_${i.slice(-8)}`, $ = new Xe(t.el, i, {
922
+ onSend(o) {
923
+ const s = `cm_${Math.random().toString(36).slice(2)}`, m = { kind: "text", text: o };
924
+ p.addOptimistic(s, m), $.render(p), p.e2e ? S.ready ? ee(s, o) : H ? N.push({ clientMsgId: s, text: o }) : (g.push({ clientMsgId: s, text: o }), p.assignedAgentId && Ie(p.assignedAgentId)) : a ? (b.add({ clientMsgId: s, content: m, ts: Date.now() }), k.send({ type: "send", conversationId: a, clientMsgId: s, content: m })) : B.push({ clientMsgId: s, content: m });
1012
925
  },
1013
- async onAttach(n) {
1014
- if (!r) return;
1015
- const p = `${b}/upload?name=${encodeURIComponent(n.name)}`, x = `cm_${Math.random().toString(36).slice(2)}`;
1016
- l.addOptimistic(x, { kind: "text", text: `📎 Uploading ${n.name}…` }), B.render(l);
926
+ async onAttach(o) {
927
+ if (!a) return;
928
+ const s = `${y}/upload?name=${encodeURIComponent(o.name)}`, m = `cm_${Math.random().toString(36).slice(2)}`;
929
+ p.addOptimistic(m, { kind: "text", text: `📎 Uploading ${o.name}…` }), $.render(p);
1017
930
  try {
1018
- const j = await fetch(p, {
931
+ const L = await fetch(s, {
1019
932
  method: "POST",
1020
933
  // Use the resolved connection token (a signed JWT, an explicit userId,
1021
934
  // or the anonymous persistent uid) — NOT just opts.token. The server
1022
935
  // requires an Authorization header, and the verifier accepts an
1023
936
  // anonymous id as a guest; keying off opts.token alone meant anonymous
1024
937
  // visitors (the common case) sent no auth and every upload 401'd.
1025
- headers: { "content-type": n.type, authorization: `Bearer ${a}` },
1026
- body: n
938
+ headers: { "content-type": o.type, authorization: `Bearer ${i}` },
939
+ body: o
1027
940
  });
1028
- if (!j.ok) throw new Error(`Upload failed: ${j.status}`);
1029
- const { url: F, name: U, mime: G, size: Y } = await j.json();
1030
- l.addOptimistic(x, { kind: "attachment", url: F, name: U, mime: G, size: Y }), B.render(l), T.send({ type: "send", conversationId: r, clientMsgId: x, content: { kind: "attachment", url: F, name: U, mime: G, size: Y } });
1031
- } catch (j) {
1032
- l.addOptimistic(x, { kind: "text", text: `⚠️ Upload failed: ${j.message}` }), B.render(l);
941
+ if (!L.ok) throw new Error(`Upload failed: ${L.status}`);
942
+ const { url: W, name: G, mime: Y, size: X } = await L.json();
943
+ p.addOptimistic(m, { kind: "attachment", url: W, name: G, mime: Y, size: X }), $.render(p), k.send({ type: "send", conversationId: a, clientMsgId: m, content: { kind: "attachment", url: W, name: G, mime: Y, size: X } });
944
+ } catch (L) {
945
+ p.addOptimistic(m, { kind: "text", text: `⚠️ Upload failed: ${L.message}` }), $.render(p);
1033
946
  }
1034
947
  },
1035
- onInvoke(n, p) {
1036
- r && T.send({ type: "invoke", conversationId: r, actionId: n, clientInvokeId: `iv_${Math.random().toString(36).slice(2)}`, ...p ? { inputs: p } : {} });
948
+ onInvoke(o, s) {
949
+ a && k.send({ type: "invoke", conversationId: a, actionId: o, clientInvokeId: `iv_${Math.random().toString(36).slice(2)}`, ...s ? { inputs: s } : {} });
1037
950
  },
1038
- onTyping(n, p) {
1039
- r && T.send({ type: "typing", conversationId: r, isTyping: n, ...p ? { preview: p } : {} });
951
+ onTyping(o, s) {
952
+ a && k.send({ type: "typing", conversationId: a, isTyping: o, ...s ? { preview: s } : {} });
1040
953
  },
1041
- onPreChat(n) {
954
+ onPreChat(o) {
1042
955
  try {
1043
956
  localStorage.setItem(re, "1");
1044
957
  } catch {
1045
958
  }
1046
- T.send({
959
+ k.send({
1047
960
  type: "open",
1048
961
  profileId: t.profileId,
1049
962
  ...t.subjectId ? { subjectId: t.subjectId } : {},
1050
963
  userInfo: {
1051
- ...n.name ? { name: n.name } : {},
1052
- ...n.email ? { email: n.email } : {},
1053
- ...n.phone || n.topic ? { meta: {
1054
- ...n.phone ? { phone: n.phone } : {},
1055
- ...n.topic ? { topic: n.topic } : {}
964
+ ...o.name ? { name: o.name } : {},
965
+ ...o.email ? { email: o.email } : {},
966
+ ...o.phone || o.topic ? { meta: {
967
+ ...o.phone ? { phone: o.phone } : {},
968
+ ...o.topic ? { topic: o.topic } : {}
1056
969
  } } : {}
1057
970
  }
1058
971
  });
1059
- const p = n.callback ? `📞 Call-back requested${n.phone ? `: ${n.phone}` : ""}${n.topic ? ` — ${n.topic}` : ""}` : n.topic ? `Topic: ${n.topic}` : "";
1060
- p && r && !l.e2e && T.send({ type: "send", conversationId: r, clientMsgId: `pc_${Math.random().toString(36).slice(2, 12)}`, content: { kind: "text", text: p } });
972
+ const s = o.callback ? `📞 Call-back requested${o.phone ? `: ${o.phone}` : ""}${o.topic ? ` — ${o.topic}` : ""}` : o.topic ? `Topic: ${o.topic}` : "";
973
+ s && a && !p.e2e && k.send({ type: "send", conversationId: a, clientMsgId: `pc_${Math.random().toString(36).slice(2, 12)}`, content: { kind: "text", text: s } });
1061
974
  },
1062
- onDeflectQuery(n) {
1063
- if (s) return;
1064
- clearTimeout(i);
1065
- const p = n.trim();
1066
- if (p.length < 3) {
1067
- B.hideDeflection();
1068
- return;
975
+ ...((le = t.features) == null ? void 0 : le.deflection) !== !1 ? {
976
+ onDeflectQuery(o) {
977
+ if (c) return;
978
+ clearTimeout(l);
979
+ const s = o.trim();
980
+ if (s.length < 3) {
981
+ $.hideDeflection();
982
+ return;
983
+ }
984
+ l = setTimeout(() => {
985
+ fetch(`${y}/kb/search?profileId=${encodeURIComponent(t.profileId)}&q=${encodeURIComponent(s.slice(0, 200))}`).then((m) => m.ok ? m.json() : { articles: [] }).then((m) => $.showDeflection(m.articles ?? [])).catch(() => $.hideDeflection());
986
+ }, 350);
1069
987
  }
1070
- i = setTimeout(() => {
1071
- fetch(`${b}/kb/search?profileId=${encodeURIComponent(t.profileId)}&q=${encodeURIComponent(p.slice(0, 200))}`).then((x) => x.ok ? x.json() : { articles: [] }).then((x) => B.showDeflection(x.articles ?? [])).catch(() => B.hideDeflection());
1072
- }, 350);
1073
- },
1074
- onReadUpTo(n) {
1075
- r && T.send({ type: "read", conversationId: r, seq: n });
988
+ } : {},
989
+ onReadUpTo(o) {
990
+ a && k.send({ type: "read", conversationId: a, seq: o });
1076
991
  },
1077
992
  onLoadMore() {
1078
- if (!r || !l.e2e) return;
1079
- const n = l.messages()[0];
1080
- n && T.send({ type: "history", conversationId: r, beforeSeq: n.seq, limit: 20 });
993
+ if (!a || !p.e2e) return;
994
+ const o = p.messages()[0];
995
+ o && k.send({ type: "history", conversationId: a, beforeSeq: o.seq, limit: 20 });
1081
996
  },
1082
- onEdit(n, p) {
1083
- r && T.send({ type: "edit", conversationId: r, messageId: n, content: { kind: "text", text: p } });
997
+ onEdit(o, s) {
998
+ a && k.send({ type: "edit", conversationId: a, messageId: o, content: { kind: "text", text: s } });
1084
999
  },
1085
- onDelete(n) {
1086
- r && T.send({ type: "delete", conversationId: r, messageId: n });
1087
- },
1088
- onReact(n, p, x) {
1089
- r && T.send({ type: "react", conversationId: r, messageId: n, emoji: p, remove: x });
1090
- },
1091
- onCsat(n) {
1092
- r && fetch(`${b}/conversations/${r}/csat`, {
1093
- method: "POST",
1094
- headers: { "Content-Type": "application/json", Authorization: `Bearer ${a}` },
1095
- body: JSON.stringify({ score: n })
1096
- }).catch(() => {
1097
- });
1098
- },
1099
- onAnnotate(n) {
1100
- r && T.send({ type: "annotate", conversationId: r, stroke: n });
1101
- },
1102
- onAnnotateClear() {
1103
- r && T.send({ type: "annotate_clear", conversationId: r });
1000
+ onDelete(o) {
1001
+ a && k.send({ type: "delete", conversationId: a, messageId: o });
1104
1002
  },
1003
+ ...((de = t.features) == null ? void 0 : de.reactions) !== !1 ? {
1004
+ onReact(o, s, m) {
1005
+ a && k.send({ type: "react", conversationId: a, messageId: o, emoji: s, remove: m });
1006
+ }
1007
+ } : {},
1008
+ ...((pe = t.features) == null ? void 0 : pe.csat) !== !1 ? {
1009
+ onCsat(o) {
1010
+ a && fetch(`${y}/conversations/${a}/csat`, {
1011
+ method: "POST",
1012
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${i}` },
1013
+ body: JSON.stringify({ score: o })
1014
+ }).catch(() => {
1015
+ });
1016
+ }
1017
+ } : {},
1105
1018
  ...t.translateLang ? {
1106
- async onTranslate(n) {
1019
+ async onTranslate(o) {
1107
1020
  try {
1108
- const p = await fetch(`${b}/translate`, {
1021
+ const s = await fetch(`${y}/translate`, {
1109
1022
  method: "POST",
1110
- headers: { "content-type": "application/json", authorization: `Bearer ${a}` },
1111
- body: JSON.stringify({ text: n, targetLang: t.translateLang })
1023
+ headers: { "content-type": "application/json", authorization: `Bearer ${i}` },
1024
+ body: JSON.stringify({ text: o, targetLang: t.translateLang })
1112
1025
  });
1113
- if (!p.ok) return null;
1114
- const { translated: x } = await p.json();
1115
- return x;
1026
+ if (!s.ok) return null;
1027
+ const { translated: m } = await s.json();
1028
+ return m;
1116
1029
  } catch {
1117
1030
  return null;
1118
1031
  }
@@ -1123,11 +1036,14 @@ function ot(t) {
1123
1036
  ...t.subject ? { subject: t.subject } : {},
1124
1037
  ...t.quickReplies ? { quickReplies: t.quickReplies } : {},
1125
1038
  ...t.accent ? { accent: t.accent } : {},
1126
- ...(de = t.user) != null && de.name || (pe = t.user) != null && pe.avatar ? { userInfo: { ...t.user.name ? { name: t.user.name } : {}, ...t.user.avatar ? { avatar: t.user.avatar } : {} } } : {},
1127
- i18n: Ce
1039
+ ...t.accent2 ? { accent2: t.accent2 } : {},
1040
+ ...t.theme ? { theme: t.theme } : {},
1041
+ ...t.webfont === !1 ? { webfont: !1 } : {},
1042
+ ...(he = t.user) != null && he.name || (ue = t.user) != null && ue.avatar ? { userInfo: { ...t.user.name ? { name: t.user.name } : {}, ...t.user.avatar ? { avatar: t.user.avatar } : {} } } : {},
1043
+ i18n: Se
1128
1044
  });
1129
1045
  try {
1130
- localStorage.getItem(re) && B.completePreChat();
1046
+ localStorage.getItem(re) && $.completePreChat();
1131
1047
  } catch {
1132
1048
  }
1133
1049
  const ce = t.user && (t.user.name || t.user.email || t.user.avatar || t.user.meta) ? {
@@ -1135,90 +1051,90 @@ function ot(t) {
1135
1051
  ...t.user.email ? { email: t.user.email } : {},
1136
1052
  ...t.user.avatar ? { avatar: t.user.avatar } : {},
1137
1053
  ...t.user.meta ? { meta: t.user.meta } : {}
1138
- } : void 0, Ie = {
1054
+ } : void 0, je = {
1139
1055
  type: "open",
1140
1056
  profileId: t.profileId,
1141
1057
  // Direct conversations use the kind/peerId pair; the dm:… subject key is
1142
1058
  // server-derived and owner-keyed, so passing it as subjectId from the
1143
1059
  // NON-owner side would find-or-create a junk duplicate thread.
1144
1060
  ...t.kind === "direct" && t.peerId ? { kind: "direct", peerId: t.peerId } : t.subjectId ? { subjectId: t.subjectId } : {},
1145
- ...c ? { linkFrom: c } : {},
1061
+ ...x ? { linkFrom: x } : {},
1146
1062
  ...ce ? { userInfo: ce } : {},
1147
1063
  ...typeof location < "u" ? { pageUrl: location.href } : {},
1148
1064
  ...typeof document < "u" && document.title ? { pageTitle: document.title } : {},
1149
1065
  // Pass subject display info so the server can persist it to the Subject record.
1150
1066
  // This is how listingTitle and listingMeta get saved without a separate API call.
1151
- ...(he = t.subject) != null && he.title ? { subjectTitle: t.subject.title } : {},
1152
- ...(ue = t.subject) != null && ue.subtitle ? { subjectMeta: t.subject.subtitle } : {}
1067
+ ...(fe = t.subject) != null && fe.title ? { subjectTitle: t.subject.title } : {},
1068
+ ...(we = t.subject) != null && we.subtitle ? { subjectMeta: t.subject.subtitle } : {}
1153
1069
  };
1154
- T = new Re({
1070
+ k = new De({
1155
1071
  ...t.refreshToken ? { refreshToken: t.refreshToken } : {},
1156
1072
  url: w,
1157
- token: a,
1158
- open: Ie,
1159
- getCursor: () => l.highestSeq(),
1160
- onStatusChange: (n, p) => B.setConnStatus(n, p),
1161
- onFrame(n) {
1162
- if (ae.apply(n), n.type === "opened") {
1163
- if (r = n.conversation.id, !u) {
1164
- u = !0;
1165
- for (const p of v.load())
1166
- T.send({ type: "send", conversationId: r, clientMsgId: p.clientMsgId, content: p.content });
1073
+ token: i,
1074
+ open: je,
1075
+ getCursor: () => p.highestSeq(),
1076
+ onStatusChange: (o, s) => $.setConnStatus(o, s),
1077
+ onFrame(o) {
1078
+ if (o.type === "opened") {
1079
+ if (a = o.conversation.id, !P) {
1080
+ P = !0;
1081
+ for (const s of b.load())
1082
+ k.send({ type: "send", conversationId: a, clientMsgId: s.clientMsgId, content: s.content });
1167
1083
  }
1168
- Be(w, a, r, l, B, b), N.length && V(r);
1084
+ qe(w, i, a, p, $, y), B.length && A(a);
1169
1085
  }
1170
- if (n.type === "ack" && v.remove(n.clientMsgId), n.type === "prekeyBundle") {
1171
- n.bundle && (se = !0, $.x3dhSendTo(n.bundle).then((p) => {
1172
- const x = [...S.splice(0), ...q.splice(0)];
1173
- for (const j of x) ye(j.clientMsgId, j.text, p);
1174
- B.render(l);
1086
+ if (o.type === "ack" && b.remove(o.clientMsgId), o.type === "prekeyBundle") {
1087
+ o.bundle && (H = !0, S.x3dhSendTo(o.bundle).then((s) => {
1088
+ const m = [...g.splice(0), ...N.splice(0)];
1089
+ for (const L of m) Ce(L.clientMsgId, L.text, s);
1090
+ $.render(p);
1175
1091
  }));
1176
1092
  return;
1177
1093
  }
1178
- if (n.type === "message" && l.e2e) {
1179
- const p = Ne(n.message.content);
1180
- if (p && !$.ready) {
1181
- $.x3dhReceiveFrom(p.x3dhIK, p.x3dhEK, p.x3dhSPK).then(async () => {
1182
- await $.openFrame(n), l.apply(n), B.render(l);
1094
+ if (o.type === "message" && p.e2e) {
1095
+ const s = _e(o.message.content);
1096
+ if (s && !S.ready) {
1097
+ S.x3dhReceiveFrom(s.x3dhIK, s.x3dhEK, s.x3dhSPK, s.x3dhOTP).then(async () => {
1098
+ await S.openFrame(o), p.apply(o), $.render(p);
1183
1099
  });
1184
1100
  return;
1185
1101
  }
1186
1102
  }
1187
- if (n.type === "peerkey") {
1188
- $.onPeerKey(n.key).then(() => {
1189
- ve(), B.render(l);
1103
+ if (o.type === "peerkey") {
1104
+ S.onPeerKey(o.key).then(() => {
1105
+ Te(), $.render(p);
1190
1106
  });
1191
1107
  return;
1192
1108
  }
1193
1109
  (async () => {
1194
- if (l.e2e && await $.openFrame(n), l.apply(n), n.type === "manifest" && (f == null || f()), n.type === "message" && n.message.senderId !== a && !n.message.internal && (R(), A()), l.e2e && r && !g) {
1195
- g = !0;
1196
- const p = await $.initX3DH();
1197
- T.send({ type: "uploadPrekeys", ...p });
1198
- const x = await $.begin();
1199
- T.send({ type: "pubkey", conversationId: r, key: x });
1110
+ if (p.e2e && await S.openFrame(o), p.apply(o), o.type === "manifest" && (d == null || d()), o.type === "message" && o.message.senderId !== i && !o.message.internal && (f(), R()), p.e2e && a && !D) {
1111
+ D = !0;
1112
+ const s = await S.initX3DH();
1113
+ k.send({ type: "uploadPrekeys", ...s });
1114
+ const m = await S.begin();
1115
+ k.send({ type: "pubkey", conversationId: a, key: m });
1200
1116
  }
1201
- B.render(l);
1117
+ $.render(p);
1202
1118
  })();
1203
1119
  }
1204
- }), T.connect(), B.render(l);
1205
- const _ = t.launcher ? me(t) : null, K = { close: () => {
1206
- s = !0, clearTimeout(i), T.close(), k == null || k.remove(), B.destroy(), ae.destroy(), d && E && d.removeEventListener("change", E), m && (document.removeEventListener("keydown", m), m = null), O.delete(t.el), _ && Q.get(_) === K && Q.delete(_);
1120
+ }), k.connect(), $.render(p);
1121
+ const F = t.launcher ? ke(t) : null, V = { close: () => {
1122
+ c = !0, clearTimeout(l), k.close(), r == null || r.remove(), $.destroy(), I && M && I.removeEventListener("change", M), j && (document.removeEventListener("keydown", j), j = null), _.delete(t.el), F && Z.get(F) === V && Z.delete(F);
1207
1123
  } };
1208
- return O.set(t.el, K), _ && Q.set(_, K), K;
1124
+ return _.set(t.el, V), F && Z.set(F, V), V;
1209
1125
  }
1210
1126
  export {
1211
- Me as ChatStore,
1212
- Re as ConnectionManager,
1213
- qe as E2ESession,
1214
- $e as PersistentOutbox,
1215
- Ke as Renderer,
1216
- rt as asConversationId,
1217
- Ne as extractX3DHInit,
1127
+ Oe as ChatStore,
1128
+ De as ConnectionManager,
1129
+ He as E2ESession,
1130
+ Ne as PersistentOutbox,
1131
+ Xe as Renderer,
1132
+ dt as asConversationId,
1133
+ _e as extractX3DHInit,
1218
1134
  st as httpBaseFromWsUrl,
1219
- ot as mount,
1135
+ at as mount,
1220
1136
  Ae as resolveRelayUrls,
1221
- Be as restoreHistory,
1222
- tt as unmount
1137
+ qe as restoreHistory,
1138
+ it as unmount
1223
1139
  };
1224
1140
  //# sourceMappingURL=index.js.map