@paramms/chat-widget 0.1.0 → 1.0.1

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.
Files changed (51) hide show
  1. package/README.md +138 -12
  2. package/dist/connection.d.ts +48 -0
  3. package/dist/crypto.d.ts +69 -0
  4. package/dist/e2e.d.ts +75 -0
  5. package/dist/history.d.ts +14 -0
  6. package/dist/index.d.ts +60 -0
  7. package/dist/index.js +2638 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/outbox.d.ts +20 -0
  10. package/dist/protocol/actions.d.ts +98 -0
  11. package/dist/protocol/codec.d.ts +12 -0
  12. package/dist/protocol/entities.d.ts +109 -0
  13. package/dist/protocol/frames.d.ts +248 -0
  14. package/dist/protocol/ids.d.ts +22 -0
  15. package/dist/protocol/index.d.ts +5 -0
  16. package/dist/react.d.ts +124 -0
  17. package/dist/react.js +143 -0
  18. package/dist/react.js.map +1 -0
  19. package/dist/renderer.d.ts +163 -0
  20. package/dist/store.d.ts +48 -0
  21. package/package.json +31 -2
  22. package/build-preview.js +0 -136
  23. package/index.html +0 -37
  24. package/src/__tests__/chatlist.test.ts +0 -133
  25. package/src/__tests__/connection.test.ts +0 -163
  26. package/src/__tests__/crypto.test.ts +0 -28
  27. package/src/__tests__/history.test.ts +0 -91
  28. package/src/__tests__/ime.test.ts +0 -93
  29. package/src/__tests__/render.test.ts +0 -58
  30. package/src/__tests__/render_new.test.ts +0 -441
  31. package/src/__tests__/store.test.ts +0 -86
  32. package/src/__tests__/x3dh.test.ts +0 -204
  33. package/src/connection.ts +0 -133
  34. package/src/crypto.ts +0 -252
  35. package/src/e2e.ts +0 -161
  36. package/src/history.ts +0 -43
  37. package/src/index.ts +0 -380
  38. package/src/outbox.ts +0 -58
  39. package/src/protocol/actions.ts +0 -114
  40. package/src/protocol/codec.ts +0 -35
  41. package/src/protocol/entities.ts +0 -104
  42. package/src/protocol/frames.ts +0 -86
  43. package/src/protocol/ids.ts +0 -27
  44. package/src/protocol/index.ts +0 -5
  45. package/src/react.tsx +0 -37
  46. package/src/renderer.ts +0 -906
  47. package/src/store.ts +0 -207
  48. package/tsconfig.json +0 -33
  49. package/vercel.json +0 -22
  50. package/vite.config.ts +0 -26
  51. package/vitest.config.ts +0 -2
package/dist/index.js ADDED
@@ -0,0 +1,2638 @@
1
+ var Se = Object.defineProperty;
2
+ var Ce = (s, e, t) => e in s ? Se(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
3
+ var a = (s, e, t) => Ce(s, typeof e != "symbol" ? e + "" : e, t);
4
+ const Dt = (s) => s;
5
+ function Ie(s) {
6
+ const e = s.length;
7
+ let t = 0, n = 0;
8
+ for (; n < e; ) {
9
+ let i = s.charCodeAt(n++);
10
+ if (i & 4294967168)
11
+ if (!(i & 4294965248))
12
+ t += 2;
13
+ else {
14
+ if (i >= 55296 && i <= 56319 && n < e) {
15
+ const o = s.charCodeAt(n);
16
+ (o & 64512) === 56320 && (++n, i = ((i & 1023) << 10) + (o & 1023) + 65536);
17
+ }
18
+ i & 4294901760 ? t += 4 : t += 3;
19
+ }
20
+ else {
21
+ t++;
22
+ continue;
23
+ }
24
+ }
25
+ return t;
26
+ }
27
+ function Ee(s, e, t) {
28
+ const n = s.length;
29
+ let i = t, o = 0;
30
+ for (; o < n; ) {
31
+ let r = s.charCodeAt(o++);
32
+ if (r & 4294967168)
33
+ if (!(r & 4294965248))
34
+ e[i++] = r >> 6 & 31 | 192;
35
+ else {
36
+ if (r >= 55296 && r <= 56319 && o < n) {
37
+ const d = s.charCodeAt(o);
38
+ (d & 64512) === 56320 && (++o, r = ((r & 1023) << 10) + (d & 1023) + 65536);
39
+ }
40
+ r & 4294901760 ? (e[i++] = r >> 18 & 7 | 240, e[i++] = r >> 12 & 63 | 128, e[i++] = r >> 6 & 63 | 128) : (e[i++] = r >> 12 & 15 | 224, e[i++] = r >> 6 & 63 | 128);
41
+ }
42
+ else {
43
+ e[i++] = r;
44
+ continue;
45
+ }
46
+ e[i++] = r & 63 | 128;
47
+ }
48
+ }
49
+ const Ue = new TextEncoder(), Te = 50;
50
+ function Be(s, e, t) {
51
+ Ue.encodeInto(s, e.subarray(t));
52
+ }
53
+ function Ae(s, e, t) {
54
+ s.length > Te ? Be(s, e, t) : Ee(s, e, t);
55
+ }
56
+ const Pe = 4096;
57
+ function pe(s, e, t) {
58
+ let n = e;
59
+ const i = n + t, o = [];
60
+ let r = "";
61
+ for (; n < i; ) {
62
+ const d = s[n++];
63
+ if (!(d & 128))
64
+ o.push(d);
65
+ else if ((d & 224) === 192) {
66
+ const u = s[n++] & 63;
67
+ o.push((d & 31) << 6 | u);
68
+ } else if ((d & 240) === 224) {
69
+ const u = s[n++] & 63, w = s[n++] & 63;
70
+ o.push((d & 31) << 12 | u << 6 | w);
71
+ } else if ((d & 248) === 240) {
72
+ const u = s[n++] & 63, w = s[n++] & 63, y = s[n++] & 63;
73
+ let x = (d & 7) << 18 | u << 12 | w << 6 | y;
74
+ x > 65535 && (x -= 65536, o.push(x >>> 10 & 1023 | 55296), x = 56320 | x & 1023), o.push(x);
75
+ } else
76
+ o.push(d);
77
+ o.length >= Pe && (r += String.fromCharCode(...o), o.length = 0);
78
+ }
79
+ return o.length > 0 && (r += String.fromCharCode(...o)), r;
80
+ }
81
+ const Ke = new TextDecoder(), Le = 200;
82
+ function ze(s, e, t) {
83
+ const n = s.subarray(e, e + t);
84
+ return Ke.decode(n);
85
+ }
86
+ function Me(s, e, t) {
87
+ return t > Le ? ze(s, e, t) : pe(s, e, t);
88
+ }
89
+ class X {
90
+ constructor(e, t) {
91
+ a(this, "type");
92
+ a(this, "data");
93
+ this.type = e, this.data = t;
94
+ }
95
+ }
96
+ class U extends Error {
97
+ constructor(e) {
98
+ super(e);
99
+ const t = Object.create(U.prototype);
100
+ Object.setPrototypeOf(this, t), Object.defineProperty(this, "name", {
101
+ configurable: !0,
102
+ enumerable: !1,
103
+ value: U.name
104
+ });
105
+ }
106
+ }
107
+ const F = 4294967295;
108
+ function $e(s, e, t) {
109
+ const n = t / 4294967296, i = t;
110
+ s.setUint32(e, n), s.setUint32(e + 4, i);
111
+ }
112
+ function fe(s, e, t) {
113
+ const n = Math.floor(t / 4294967296), i = t;
114
+ s.setUint32(e, n), s.setUint32(e + 4, i);
115
+ }
116
+ function ue(s, e) {
117
+ const t = s.getInt32(e), n = s.getUint32(e + 4);
118
+ return t * 4294967296 + n;
119
+ }
120
+ function _e(s, e) {
121
+ const t = s.getUint32(e), n = s.getUint32(e + 4);
122
+ return t * 4294967296 + n;
123
+ }
124
+ const De = -1, qe = 4294967296 - 1, Re = 17179869184 - 1;
125
+ function He({ sec: s, nsec: e }) {
126
+ if (s >= 0 && e >= 0 && s <= Re)
127
+ if (e === 0 && s <= qe) {
128
+ const t = new Uint8Array(4);
129
+ return new DataView(t.buffer).setUint32(0, s), t;
130
+ } else {
131
+ const t = s / 4294967296, n = s & 4294967295, i = new Uint8Array(8), o = new DataView(i.buffer);
132
+ return o.setUint32(0, e << 2 | t & 3), o.setUint32(4, n), i;
133
+ }
134
+ else {
135
+ const t = new Uint8Array(12), n = new DataView(t.buffer);
136
+ return n.setUint32(0, e), fe(n, 4, s), t;
137
+ }
138
+ }
139
+ function Fe(s) {
140
+ const e = s.getTime(), t = Math.floor(e / 1e3), n = (e - t * 1e3) * 1e6, i = Math.floor(n / 1e9);
141
+ return {
142
+ sec: t + i,
143
+ nsec: n - i * 1e9
144
+ };
145
+ }
146
+ function je(s) {
147
+ if (s instanceof Date) {
148
+ const e = Fe(s);
149
+ return He(e);
150
+ } else
151
+ return null;
152
+ }
153
+ function Oe(s) {
154
+ const e = new DataView(s.buffer, s.byteOffset, s.byteLength);
155
+ switch (s.byteLength) {
156
+ case 4:
157
+ return { sec: e.getUint32(0), nsec: 0 };
158
+ case 8: {
159
+ const t = e.getUint32(0), n = e.getUint32(4), i = (t & 3) * 4294967296 + n, o = t >>> 2;
160
+ return { sec: i, nsec: o };
161
+ }
162
+ case 12: {
163
+ const t = ue(e, 4), n = e.getUint32(0);
164
+ return { sec: t, nsec: n };
165
+ }
166
+ default:
167
+ throw new U(`Unrecognized data size for timestamp (expected 4, 8, or 12): ${s.length}`);
168
+ }
169
+ }
170
+ function Ne(s) {
171
+ const e = Oe(s);
172
+ return new Date(e.sec * 1e3 + e.nsec / 1e6);
173
+ }
174
+ const We = {
175
+ type: De,
176
+ encode: je,
177
+ decode: Ne
178
+ }, G = class G {
179
+ constructor() {
180
+ // ensures ExtensionCodecType<X> matches ExtensionCodec<X>
181
+ // this will make type errors a lot more clear
182
+ // eslint-disable-next-line @typescript-eslint/naming-convention
183
+ a(this, "__brand");
184
+ // built-in extensions
185
+ a(this, "builtInEncoders", []);
186
+ a(this, "builtInDecoders", []);
187
+ // custom extensions
188
+ a(this, "encoders", []);
189
+ a(this, "decoders", []);
190
+ this.register(We);
191
+ }
192
+ register({ type: e, encode: t, decode: n }) {
193
+ if (e >= 0)
194
+ this.encoders[e] = t, this.decoders[e] = n;
195
+ else {
196
+ const i = -1 - e;
197
+ this.builtInEncoders[i] = t, this.builtInDecoders[i] = n;
198
+ }
199
+ }
200
+ tryToEncode(e, t) {
201
+ for (let n = 0; n < this.builtInEncoders.length; n++) {
202
+ const i = this.builtInEncoders[n];
203
+ if (i != null) {
204
+ const o = i(e, t);
205
+ if (o != null) {
206
+ const r = -1 - n;
207
+ return new X(r, o);
208
+ }
209
+ }
210
+ }
211
+ for (let n = 0; n < this.encoders.length; n++) {
212
+ const i = this.encoders[n];
213
+ if (i != null) {
214
+ const o = i(e, t);
215
+ if (o != null) {
216
+ const r = n;
217
+ return new X(r, o);
218
+ }
219
+ }
220
+ }
221
+ return e instanceof X ? e : null;
222
+ }
223
+ decode(e, t, n) {
224
+ const i = t < 0 ? this.builtInDecoders[-1 - t] : this.decoders[t];
225
+ return i ? i(e, t, n) : new X(t, e);
226
+ }
227
+ };
228
+ a(G, "defaultCodec", new G());
229
+ let Y = G;
230
+ function Ve(s) {
231
+ return s instanceof ArrayBuffer || typeof SharedArrayBuffer < "u" && s instanceof SharedArrayBuffer;
232
+ }
233
+ function ee(s) {
234
+ return s instanceof Uint8Array ? s : ArrayBuffer.isView(s) ? new Uint8Array(s.buffer, s.byteOffset, s.byteLength) : Ve(s) ? new Uint8Array(s) : Uint8Array.from(s);
235
+ }
236
+ const Xe = 100, Ye = 2048;
237
+ class ne {
238
+ constructor(e) {
239
+ a(this, "extensionCodec");
240
+ a(this, "context");
241
+ a(this, "useBigInt64");
242
+ a(this, "maxDepth");
243
+ a(this, "initialBufferSize");
244
+ a(this, "sortKeys");
245
+ a(this, "forceFloat32");
246
+ a(this, "ignoreUndefined");
247
+ a(this, "forceIntegerToFloat");
248
+ a(this, "pos");
249
+ a(this, "view");
250
+ a(this, "bytes");
251
+ a(this, "entered", !1);
252
+ this.extensionCodec = (e == null ? void 0 : e.extensionCodec) ?? Y.defaultCodec, this.context = e == null ? void 0 : e.context, this.useBigInt64 = (e == null ? void 0 : e.useBigInt64) ?? !1, this.maxDepth = (e == null ? void 0 : e.maxDepth) ?? Xe, this.initialBufferSize = (e == null ? void 0 : e.initialBufferSize) ?? Ye, this.sortKeys = (e == null ? void 0 : e.sortKeys) ?? !1, this.forceFloat32 = (e == null ? void 0 : e.forceFloat32) ?? !1, this.ignoreUndefined = (e == null ? void 0 : e.ignoreUndefined) ?? !1, this.forceIntegerToFloat = (e == null ? void 0 : e.forceIntegerToFloat) ?? !1, this.pos = 0, this.view = new DataView(new ArrayBuffer(this.initialBufferSize)), this.bytes = new Uint8Array(this.view.buffer);
253
+ }
254
+ clone() {
255
+ return new ne({
256
+ extensionCodec: this.extensionCodec,
257
+ context: this.context,
258
+ useBigInt64: this.useBigInt64,
259
+ maxDepth: this.maxDepth,
260
+ initialBufferSize: this.initialBufferSize,
261
+ sortKeys: this.sortKeys,
262
+ forceFloat32: this.forceFloat32,
263
+ ignoreUndefined: this.ignoreUndefined,
264
+ forceIntegerToFloat: this.forceIntegerToFloat
265
+ });
266
+ }
267
+ reinitializeState() {
268
+ this.pos = 0;
269
+ }
270
+ /**
271
+ * This is almost equivalent to {@link Encoder#encode}, but it returns an reference of the encoder's internal buffer and thus much faster than {@link Encoder#encode}.
272
+ *
273
+ * @returns Encodes the object and returns a shared reference the encoder's internal buffer.
274
+ */
275
+ encodeSharedRef(e) {
276
+ if (this.entered)
277
+ return this.clone().encodeSharedRef(e);
278
+ try {
279
+ return this.entered = !0, this.reinitializeState(), this.doEncode(e, 1), this.bytes.subarray(0, this.pos);
280
+ } finally {
281
+ this.entered = !1;
282
+ }
283
+ }
284
+ /**
285
+ * @returns Encodes the object and returns a copy of the encoder's internal buffer.
286
+ */
287
+ encode(e) {
288
+ if (this.entered)
289
+ return this.clone().encode(e);
290
+ try {
291
+ return this.entered = !0, this.reinitializeState(), this.doEncode(e, 1), this.bytes.slice(0, this.pos);
292
+ } finally {
293
+ this.entered = !1;
294
+ }
295
+ }
296
+ doEncode(e, t) {
297
+ if (t > this.maxDepth)
298
+ throw new Error(`Too deep objects in depth ${t}`);
299
+ e == null ? this.encodeNil() : typeof e == "boolean" ? this.encodeBoolean(e) : typeof e == "number" ? this.forceIntegerToFloat ? this.encodeNumberAsFloat(e) : this.encodeNumber(e) : typeof e == "string" ? this.encodeString(e) : this.useBigInt64 && typeof e == "bigint" ? this.encodeBigInt64(e) : this.encodeObject(e, t);
300
+ }
301
+ ensureBufferSizeToWrite(e) {
302
+ const t = this.pos + e;
303
+ this.view.byteLength < t && this.resizeBuffer(t * 2);
304
+ }
305
+ resizeBuffer(e) {
306
+ const t = new ArrayBuffer(e), n = new Uint8Array(t), i = new DataView(t);
307
+ n.set(this.bytes), this.view = i, this.bytes = n;
308
+ }
309
+ encodeNil() {
310
+ this.writeU8(192);
311
+ }
312
+ encodeBoolean(e) {
313
+ e === !1 ? this.writeU8(194) : this.writeU8(195);
314
+ }
315
+ encodeNumber(e) {
316
+ !this.forceIntegerToFloat && Number.isSafeInteger(e) ? e >= 0 ? e < 128 ? this.writeU8(e) : e < 256 ? (this.writeU8(204), this.writeU8(e)) : e < 65536 ? (this.writeU8(205), this.writeU16(e)) : e < 4294967296 ? (this.writeU8(206), this.writeU32(e)) : this.useBigInt64 ? this.encodeNumberAsFloat(e) : (this.writeU8(207), this.writeU64(e)) : e >= -32 ? this.writeU8(224 | e + 32) : e >= -128 ? (this.writeU8(208), this.writeI8(e)) : e >= -32768 ? (this.writeU8(209), this.writeI16(e)) : e >= -2147483648 ? (this.writeU8(210), this.writeI32(e)) : this.useBigInt64 ? this.encodeNumberAsFloat(e) : (this.writeU8(211), this.writeI64(e)) : this.encodeNumberAsFloat(e);
317
+ }
318
+ encodeNumberAsFloat(e) {
319
+ this.forceFloat32 ? (this.writeU8(202), this.writeF32(e)) : (this.writeU8(203), this.writeF64(e));
320
+ }
321
+ encodeBigInt64(e) {
322
+ e >= BigInt(0) ? (this.writeU8(207), this.writeBigUint64(e)) : (this.writeU8(211), this.writeBigInt64(e));
323
+ }
324
+ writeStringHeader(e) {
325
+ if (e < 32)
326
+ this.writeU8(160 + e);
327
+ else if (e < 256)
328
+ this.writeU8(217), this.writeU8(e);
329
+ else if (e < 65536)
330
+ this.writeU8(218), this.writeU16(e);
331
+ else if (e < 4294967296)
332
+ this.writeU8(219), this.writeU32(e);
333
+ else
334
+ throw new Error(`Too long string: ${e} bytes in UTF-8`);
335
+ }
336
+ encodeString(e) {
337
+ const n = Ie(e);
338
+ this.ensureBufferSizeToWrite(5 + n), this.writeStringHeader(n), Ae(e, this.bytes, this.pos), this.pos += n;
339
+ }
340
+ encodeObject(e, t) {
341
+ const n = this.extensionCodec.tryToEncode(e, this.context);
342
+ if (n != null)
343
+ this.encodeExtension(n);
344
+ else if (Array.isArray(e))
345
+ this.encodeArray(e, t);
346
+ else if (ArrayBuffer.isView(e))
347
+ this.encodeBinary(e);
348
+ else if (typeof e == "object")
349
+ this.encodeMap(e, t);
350
+ else
351
+ throw new Error(`Unrecognized object: ${Object.prototype.toString.apply(e)}`);
352
+ }
353
+ encodeBinary(e) {
354
+ const t = e.byteLength;
355
+ if (t < 256)
356
+ this.writeU8(196), this.writeU8(t);
357
+ else if (t < 65536)
358
+ this.writeU8(197), this.writeU16(t);
359
+ else if (t < 4294967296)
360
+ this.writeU8(198), this.writeU32(t);
361
+ else
362
+ throw new Error(`Too large binary: ${t}`);
363
+ const n = ee(e);
364
+ this.writeU8a(n);
365
+ }
366
+ encodeArray(e, t) {
367
+ const n = e.length;
368
+ if (n < 16)
369
+ this.writeU8(144 + n);
370
+ else if (n < 65536)
371
+ this.writeU8(220), this.writeU16(n);
372
+ else if (n < 4294967296)
373
+ this.writeU8(221), this.writeU32(n);
374
+ else
375
+ throw new Error(`Too large array: ${n}`);
376
+ for (const i of e)
377
+ this.doEncode(i, t + 1);
378
+ }
379
+ countWithoutUndefined(e, t) {
380
+ let n = 0;
381
+ for (const i of t)
382
+ e[i] !== void 0 && n++;
383
+ return n;
384
+ }
385
+ encodeMap(e, t) {
386
+ const n = Object.keys(e);
387
+ this.sortKeys && n.sort();
388
+ const i = this.ignoreUndefined ? this.countWithoutUndefined(e, n) : n.length;
389
+ if (i < 16)
390
+ this.writeU8(128 + i);
391
+ else if (i < 65536)
392
+ this.writeU8(222), this.writeU16(i);
393
+ else if (i < 4294967296)
394
+ this.writeU8(223), this.writeU32(i);
395
+ else
396
+ throw new Error(`Too large map object: ${i}`);
397
+ for (const o of n) {
398
+ const r = e[o];
399
+ this.ignoreUndefined && r === void 0 || (this.encodeString(o), this.doEncode(r, t + 1));
400
+ }
401
+ }
402
+ encodeExtension(e) {
403
+ if (typeof e.data == "function") {
404
+ const n = e.data(this.pos + 6), i = n.length;
405
+ if (i >= 4294967296)
406
+ throw new Error(`Too large extension object: ${i}`);
407
+ this.writeU8(201), this.writeU32(i), this.writeI8(e.type), this.writeU8a(n);
408
+ return;
409
+ }
410
+ const t = e.data.length;
411
+ if (t === 1)
412
+ this.writeU8(212);
413
+ else if (t === 2)
414
+ this.writeU8(213);
415
+ else if (t === 4)
416
+ this.writeU8(214);
417
+ else if (t === 8)
418
+ this.writeU8(215);
419
+ else if (t === 16)
420
+ this.writeU8(216);
421
+ else if (t < 256)
422
+ this.writeU8(199), this.writeU8(t);
423
+ else if (t < 65536)
424
+ this.writeU8(200), this.writeU16(t);
425
+ else if (t < 4294967296)
426
+ this.writeU8(201), this.writeU32(t);
427
+ else
428
+ throw new Error(`Too large extension object: ${t}`);
429
+ this.writeI8(e.type), this.writeU8a(e.data);
430
+ }
431
+ writeU8(e) {
432
+ this.ensureBufferSizeToWrite(1), this.view.setUint8(this.pos, e), this.pos++;
433
+ }
434
+ writeU8a(e) {
435
+ const t = e.length;
436
+ this.ensureBufferSizeToWrite(t), this.bytes.set(e, this.pos), this.pos += t;
437
+ }
438
+ writeI8(e) {
439
+ this.ensureBufferSizeToWrite(1), this.view.setInt8(this.pos, e), this.pos++;
440
+ }
441
+ writeU16(e) {
442
+ this.ensureBufferSizeToWrite(2), this.view.setUint16(this.pos, e), this.pos += 2;
443
+ }
444
+ writeI16(e) {
445
+ this.ensureBufferSizeToWrite(2), this.view.setInt16(this.pos, e), this.pos += 2;
446
+ }
447
+ writeU32(e) {
448
+ this.ensureBufferSizeToWrite(4), this.view.setUint32(this.pos, e), this.pos += 4;
449
+ }
450
+ writeI32(e) {
451
+ this.ensureBufferSizeToWrite(4), this.view.setInt32(this.pos, e), this.pos += 4;
452
+ }
453
+ writeF32(e) {
454
+ this.ensureBufferSizeToWrite(4), this.view.setFloat32(this.pos, e), this.pos += 4;
455
+ }
456
+ writeF64(e) {
457
+ this.ensureBufferSizeToWrite(8), this.view.setFloat64(this.pos, e), this.pos += 8;
458
+ }
459
+ writeU64(e) {
460
+ this.ensureBufferSizeToWrite(8), $e(this.view, this.pos, e), this.pos += 8;
461
+ }
462
+ writeI64(e) {
463
+ this.ensureBufferSizeToWrite(8), fe(this.view, this.pos, e), this.pos += 8;
464
+ }
465
+ writeBigUint64(e) {
466
+ this.ensureBufferSizeToWrite(8), this.view.setBigUint64(this.pos, e), this.pos += 8;
467
+ }
468
+ writeBigInt64(e) {
469
+ this.ensureBufferSizeToWrite(8), this.view.setBigInt64(this.pos, e), this.pos += 8;
470
+ }
471
+ }
472
+ function Je(s, e) {
473
+ return new ne(e).encodeSharedRef(s);
474
+ }
475
+ function Z(s) {
476
+ return `${s < 0 ? "-" : ""}0x${Math.abs(s).toString(16).padStart(2, "0")}`;
477
+ }
478
+ const Ge = 16, Ze = 16;
479
+ class Qe {
480
+ constructor(e = Ge, t = Ze) {
481
+ a(this, "hit", 0);
482
+ a(this, "miss", 0);
483
+ a(this, "caches");
484
+ a(this, "maxKeyLength");
485
+ a(this, "maxLengthPerKey");
486
+ this.maxKeyLength = e, this.maxLengthPerKey = t, this.caches = [];
487
+ for (let n = 0; n < this.maxKeyLength; n++)
488
+ this.caches.push([]);
489
+ }
490
+ canBeCached(e) {
491
+ return e > 0 && e <= this.maxKeyLength;
492
+ }
493
+ find(e, t, n) {
494
+ const i = this.caches[n - 1];
495
+ e: for (const o of i) {
496
+ const r = o.bytes;
497
+ for (let d = 0; d < n; d++)
498
+ if (r[d] !== e[t + d])
499
+ continue e;
500
+ return o.str;
501
+ }
502
+ return null;
503
+ }
504
+ store(e, t) {
505
+ const n = this.caches[e.length - 1], i = { bytes: e, str: t };
506
+ n.length >= this.maxLengthPerKey ? n[Math.random() * n.length | 0] = i : n.push(i);
507
+ }
508
+ decode(e, t, n) {
509
+ const i = this.find(e, t, n);
510
+ if (i != null)
511
+ return this.hit++, i;
512
+ this.miss++;
513
+ const o = pe(e, t, n), r = Uint8Array.prototype.slice.call(e, t, t + n);
514
+ return this.store(r, o), o;
515
+ }
516
+ }
517
+ const te = "array", O = "map_key", we = "map_value", et = (s) => {
518
+ if (typeof s == "string" || typeof s == "number")
519
+ return s;
520
+ throw new U("The type of key must be string or number but " + typeof s);
521
+ };
522
+ class tt {
523
+ constructor() {
524
+ a(this, "stack", []);
525
+ a(this, "stackHeadPosition", -1);
526
+ }
527
+ get length() {
528
+ return this.stackHeadPosition + 1;
529
+ }
530
+ top() {
531
+ return this.stack[this.stackHeadPosition];
532
+ }
533
+ pushArrayState(e) {
534
+ const t = this.getUninitializedStateFromPool();
535
+ t.type = te, t.position = 0, t.size = e, t.array = new Array(e);
536
+ }
537
+ pushMapState(e) {
538
+ const t = this.getUninitializedStateFromPool();
539
+ t.type = O, t.readCount = 0, t.size = e, t.map = {};
540
+ }
541
+ getUninitializedStateFromPool() {
542
+ if (this.stackHeadPosition++, this.stackHeadPosition === this.stack.length) {
543
+ const e = {
544
+ type: void 0,
545
+ size: 0,
546
+ array: void 0,
547
+ position: 0,
548
+ readCount: 0,
549
+ map: void 0,
550
+ key: null
551
+ };
552
+ this.stack.push(e);
553
+ }
554
+ return this.stack[this.stackHeadPosition];
555
+ }
556
+ release(e) {
557
+ if (this.stack[this.stackHeadPosition] !== e)
558
+ throw new Error("Invalid stack state. Released state is not on top of the stack.");
559
+ if (e.type === te) {
560
+ const n = e;
561
+ n.size = 0, n.array = void 0, n.position = 0, n.type = void 0;
562
+ }
563
+ if (e.type === O || e.type === we) {
564
+ const n = e;
565
+ n.size = 0, n.map = void 0, n.readCount = 0, n.type = void 0;
566
+ }
567
+ this.stackHeadPosition--;
568
+ }
569
+ reset() {
570
+ this.stack.length = 0, this.stackHeadPosition = -1;
571
+ }
572
+ }
573
+ const j = -1, se = new DataView(new ArrayBuffer(0)), it = new Uint8Array(se.buffer);
574
+ try {
575
+ se.getInt8(0);
576
+ } catch (s) {
577
+ if (!(s instanceof RangeError))
578
+ throw new Error("This module is not supported in the current JavaScript engine because DataView does not throw RangeError on out-of-bounds access");
579
+ }
580
+ const re = new RangeError("Insufficient data"), nt = new Qe();
581
+ class oe {
582
+ constructor(e) {
583
+ a(this, "extensionCodec");
584
+ a(this, "context");
585
+ a(this, "useBigInt64");
586
+ a(this, "rawStrings");
587
+ a(this, "maxStrLength");
588
+ a(this, "maxBinLength");
589
+ a(this, "maxArrayLength");
590
+ a(this, "maxMapLength");
591
+ a(this, "maxExtLength");
592
+ a(this, "keyDecoder");
593
+ a(this, "mapKeyConverter");
594
+ a(this, "totalPos", 0);
595
+ a(this, "pos", 0);
596
+ a(this, "view", se);
597
+ a(this, "bytes", it);
598
+ a(this, "headByte", j);
599
+ a(this, "stack", new tt());
600
+ a(this, "entered", !1);
601
+ this.extensionCodec = (e == null ? void 0 : e.extensionCodec) ?? Y.defaultCodec, this.context = e == null ? void 0 : e.context, this.useBigInt64 = (e == null ? void 0 : e.useBigInt64) ?? !1, this.rawStrings = (e == null ? void 0 : e.rawStrings) ?? !1, this.maxStrLength = (e == null ? void 0 : e.maxStrLength) ?? F, this.maxBinLength = (e == null ? void 0 : e.maxBinLength) ?? F, this.maxArrayLength = (e == null ? void 0 : e.maxArrayLength) ?? F, this.maxMapLength = (e == null ? void 0 : e.maxMapLength) ?? F, this.maxExtLength = (e == null ? void 0 : e.maxExtLength) ?? F, this.keyDecoder = (e == null ? void 0 : e.keyDecoder) !== void 0 ? e.keyDecoder : nt, this.mapKeyConverter = (e == null ? void 0 : e.mapKeyConverter) ?? et;
602
+ }
603
+ clone() {
604
+ return new oe({
605
+ extensionCodec: this.extensionCodec,
606
+ context: this.context,
607
+ useBigInt64: this.useBigInt64,
608
+ rawStrings: this.rawStrings,
609
+ maxStrLength: this.maxStrLength,
610
+ maxBinLength: this.maxBinLength,
611
+ maxArrayLength: this.maxArrayLength,
612
+ maxMapLength: this.maxMapLength,
613
+ maxExtLength: this.maxExtLength,
614
+ keyDecoder: this.keyDecoder
615
+ });
616
+ }
617
+ reinitializeState() {
618
+ this.totalPos = 0, this.headByte = j, this.stack.reset();
619
+ }
620
+ setBuffer(e) {
621
+ const t = ee(e);
622
+ this.bytes = t, this.view = new DataView(t.buffer, t.byteOffset, t.byteLength), this.pos = 0;
623
+ }
624
+ appendBuffer(e) {
625
+ if (this.headByte === j && !this.hasRemaining(1))
626
+ this.setBuffer(e);
627
+ else {
628
+ const t = this.bytes.subarray(this.pos), n = ee(e), i = new Uint8Array(t.length + n.length);
629
+ i.set(t), i.set(n, t.length), this.setBuffer(i);
630
+ }
631
+ }
632
+ hasRemaining(e) {
633
+ return this.view.byteLength - this.pos >= e;
634
+ }
635
+ createExtraByteError(e) {
636
+ const { view: t, pos: n } = this;
637
+ return new RangeError(`Extra ${t.byteLength - n} of ${t.byteLength} byte(s) found at buffer[${e}]`);
638
+ }
639
+ /**
640
+ * @throws {@link DecodeError}
641
+ * @throws {@link RangeError}
642
+ */
643
+ decode(e) {
644
+ if (this.entered)
645
+ return this.clone().decode(e);
646
+ try {
647
+ this.entered = !0, this.reinitializeState(), this.setBuffer(e);
648
+ const t = this.doDecodeSync();
649
+ if (this.hasRemaining(1))
650
+ throw this.createExtraByteError(this.pos);
651
+ return t;
652
+ } finally {
653
+ this.entered = !1;
654
+ }
655
+ }
656
+ *decodeMulti(e) {
657
+ if (this.entered) {
658
+ yield* this.clone().decodeMulti(e);
659
+ return;
660
+ }
661
+ try {
662
+ for (this.entered = !0, this.reinitializeState(), this.setBuffer(e); this.hasRemaining(1); )
663
+ yield this.doDecodeSync();
664
+ } finally {
665
+ this.entered = !1;
666
+ }
667
+ }
668
+ async decodeAsync(e) {
669
+ if (this.entered)
670
+ return this.clone().decodeAsync(e);
671
+ try {
672
+ this.entered = !0;
673
+ let t = !1, n;
674
+ for await (const d of e) {
675
+ if (t)
676
+ throw this.entered = !1, this.createExtraByteError(this.totalPos);
677
+ this.appendBuffer(d);
678
+ try {
679
+ n = this.doDecodeSync(), t = !0;
680
+ } catch (u) {
681
+ if (!(u instanceof RangeError))
682
+ throw u;
683
+ }
684
+ this.totalPos += this.pos;
685
+ }
686
+ if (t) {
687
+ if (this.hasRemaining(1))
688
+ throw this.createExtraByteError(this.totalPos);
689
+ return n;
690
+ }
691
+ const { headByte: i, pos: o, totalPos: r } = this;
692
+ throw new RangeError(`Insufficient data in parsing ${Z(i)} at ${r} (${o} in the current buffer)`);
693
+ } finally {
694
+ this.entered = !1;
695
+ }
696
+ }
697
+ decodeArrayStream(e) {
698
+ return this.decodeMultiAsync(e, !0);
699
+ }
700
+ decodeStream(e) {
701
+ return this.decodeMultiAsync(e, !1);
702
+ }
703
+ async *decodeMultiAsync(e, t) {
704
+ if (this.entered) {
705
+ yield* this.clone().decodeMultiAsync(e, t);
706
+ return;
707
+ }
708
+ try {
709
+ this.entered = !0;
710
+ let n = t, i = -1;
711
+ for await (const o of e) {
712
+ if (t && i === 0)
713
+ throw this.createExtraByteError(this.totalPos);
714
+ this.appendBuffer(o), n && (i = this.readArraySize(), n = !1, this.complete());
715
+ try {
716
+ for (; yield this.doDecodeSync(), --i !== 0; )
717
+ ;
718
+ } catch (r) {
719
+ if (!(r instanceof RangeError))
720
+ throw r;
721
+ }
722
+ this.totalPos += this.pos;
723
+ }
724
+ } finally {
725
+ this.entered = !1;
726
+ }
727
+ }
728
+ doDecodeSync() {
729
+ e: for (; ; ) {
730
+ const e = this.readHeadByte();
731
+ let t;
732
+ if (e >= 224)
733
+ t = e - 256;
734
+ else if (e < 192)
735
+ if (e < 128)
736
+ t = e;
737
+ else if (e < 144) {
738
+ const i = e - 128;
739
+ if (i !== 0) {
740
+ this.pushMapState(i), this.complete();
741
+ continue e;
742
+ } else
743
+ t = {};
744
+ } else if (e < 160) {
745
+ const i = e - 144;
746
+ if (i !== 0) {
747
+ this.pushArrayState(i), this.complete();
748
+ continue e;
749
+ } else
750
+ t = [];
751
+ } else {
752
+ const i = e - 160;
753
+ t = this.decodeString(i, 0);
754
+ }
755
+ else if (e === 192)
756
+ t = null;
757
+ else if (e === 194)
758
+ t = !1;
759
+ else if (e === 195)
760
+ t = !0;
761
+ else if (e === 202)
762
+ t = this.readF32();
763
+ else if (e === 203)
764
+ t = this.readF64();
765
+ else if (e === 204)
766
+ t = this.readU8();
767
+ else if (e === 205)
768
+ t = this.readU16();
769
+ else if (e === 206)
770
+ t = this.readU32();
771
+ else if (e === 207)
772
+ this.useBigInt64 ? t = this.readU64AsBigInt() : t = this.readU64();
773
+ else if (e === 208)
774
+ t = this.readI8();
775
+ else if (e === 209)
776
+ t = this.readI16();
777
+ else if (e === 210)
778
+ t = this.readI32();
779
+ else if (e === 211)
780
+ this.useBigInt64 ? t = this.readI64AsBigInt() : t = this.readI64();
781
+ else if (e === 217) {
782
+ const i = this.lookU8();
783
+ t = this.decodeString(i, 1);
784
+ } else if (e === 218) {
785
+ const i = this.lookU16();
786
+ t = this.decodeString(i, 2);
787
+ } else if (e === 219) {
788
+ const i = this.lookU32();
789
+ t = this.decodeString(i, 4);
790
+ } else if (e === 220) {
791
+ const i = this.readU16();
792
+ if (i !== 0) {
793
+ this.pushArrayState(i), this.complete();
794
+ continue e;
795
+ } else
796
+ t = [];
797
+ } else if (e === 221) {
798
+ const i = this.readU32();
799
+ if (i !== 0) {
800
+ this.pushArrayState(i), this.complete();
801
+ continue e;
802
+ } else
803
+ t = [];
804
+ } else if (e === 222) {
805
+ const i = this.readU16();
806
+ if (i !== 0) {
807
+ this.pushMapState(i), this.complete();
808
+ continue e;
809
+ } else
810
+ t = {};
811
+ } else if (e === 223) {
812
+ const i = this.readU32();
813
+ if (i !== 0) {
814
+ this.pushMapState(i), this.complete();
815
+ continue e;
816
+ } else
817
+ t = {};
818
+ } else if (e === 196) {
819
+ const i = this.lookU8();
820
+ t = this.decodeBinary(i, 1);
821
+ } else if (e === 197) {
822
+ const i = this.lookU16();
823
+ t = this.decodeBinary(i, 2);
824
+ } else if (e === 198) {
825
+ const i = this.lookU32();
826
+ t = this.decodeBinary(i, 4);
827
+ } else if (e === 212)
828
+ t = this.decodeExtension(1, 0);
829
+ else if (e === 213)
830
+ t = this.decodeExtension(2, 0);
831
+ else if (e === 214)
832
+ t = this.decodeExtension(4, 0);
833
+ else if (e === 215)
834
+ t = this.decodeExtension(8, 0);
835
+ else if (e === 216)
836
+ t = this.decodeExtension(16, 0);
837
+ else if (e === 199) {
838
+ const i = this.lookU8();
839
+ t = this.decodeExtension(i, 1);
840
+ } else if (e === 200) {
841
+ const i = this.lookU16();
842
+ t = this.decodeExtension(i, 2);
843
+ } else if (e === 201) {
844
+ const i = this.lookU32();
845
+ t = this.decodeExtension(i, 4);
846
+ } else
847
+ throw new U(`Unrecognized type byte: ${Z(e)}`);
848
+ this.complete();
849
+ const n = this.stack;
850
+ for (; n.length > 0; ) {
851
+ const i = n.top();
852
+ if (i.type === te)
853
+ if (i.array[i.position] = t, i.position++, i.position === i.size)
854
+ t = i.array, n.release(i);
855
+ else
856
+ continue e;
857
+ else if (i.type === O) {
858
+ if (t === "__proto__")
859
+ throw new U("The key __proto__ is not allowed");
860
+ i.key = this.mapKeyConverter(t), i.type = we;
861
+ continue e;
862
+ } else if (i.map[i.key] = t, i.readCount++, i.readCount === i.size)
863
+ t = i.map, n.release(i);
864
+ else {
865
+ i.key = null, i.type = O;
866
+ continue e;
867
+ }
868
+ }
869
+ return t;
870
+ }
871
+ }
872
+ readHeadByte() {
873
+ return this.headByte === j && (this.headByte = this.readU8()), this.headByte;
874
+ }
875
+ complete() {
876
+ this.headByte = j;
877
+ }
878
+ readArraySize() {
879
+ const e = this.readHeadByte();
880
+ switch (e) {
881
+ case 220:
882
+ return this.readU16();
883
+ case 221:
884
+ return this.readU32();
885
+ default: {
886
+ if (e < 160)
887
+ return e - 144;
888
+ throw new U(`Unrecognized array type byte: ${Z(e)}`);
889
+ }
890
+ }
891
+ }
892
+ pushMapState(e) {
893
+ if (e > this.maxMapLength)
894
+ throw new U(`Max length exceeded: map length (${e}) > maxMapLengthLength (${this.maxMapLength})`);
895
+ this.stack.pushMapState(e);
896
+ }
897
+ pushArrayState(e) {
898
+ if (e > this.maxArrayLength)
899
+ throw new U(`Max length exceeded: array length (${e}) > maxArrayLength (${this.maxArrayLength})`);
900
+ this.stack.pushArrayState(e);
901
+ }
902
+ decodeString(e, t) {
903
+ return !this.rawStrings || this.stateIsMapKey() ? this.decodeUtf8String(e, t) : this.decodeBinary(e, t);
904
+ }
905
+ /**
906
+ * @throws {@link RangeError}
907
+ */
908
+ decodeUtf8String(e, t) {
909
+ var o;
910
+ if (e > this.maxStrLength)
911
+ throw new U(`Max length exceeded: UTF-8 byte length (${e}) > maxStrLength (${this.maxStrLength})`);
912
+ if (this.bytes.byteLength < this.pos + t + e)
913
+ throw re;
914
+ const n = this.pos + t;
915
+ let i;
916
+ return this.stateIsMapKey() && ((o = this.keyDecoder) != null && o.canBeCached(e)) ? i = this.keyDecoder.decode(this.bytes, n, e) : i = Me(this.bytes, n, e), this.pos += t + e, i;
917
+ }
918
+ stateIsMapKey() {
919
+ return this.stack.length > 0 ? this.stack.top().type === O : !1;
920
+ }
921
+ /**
922
+ * @throws {@link RangeError}
923
+ */
924
+ decodeBinary(e, t) {
925
+ if (e > this.maxBinLength)
926
+ throw new U(`Max length exceeded: bin length (${e}) > maxBinLength (${this.maxBinLength})`);
927
+ if (!this.hasRemaining(e + t))
928
+ throw re;
929
+ const n = this.pos + t, i = this.bytes.subarray(n, n + e);
930
+ return this.pos += t + e, i;
931
+ }
932
+ decodeExtension(e, t) {
933
+ if (e > this.maxExtLength)
934
+ throw new U(`Max length exceeded: ext length (${e}) > maxExtLength (${this.maxExtLength})`);
935
+ const n = this.view.getInt8(this.pos + t), i = this.decodeBinary(
936
+ e,
937
+ t + 1
938
+ /* extType */
939
+ );
940
+ return this.extensionCodec.decode(i, n, this.context);
941
+ }
942
+ lookU8() {
943
+ return this.view.getUint8(this.pos);
944
+ }
945
+ lookU16() {
946
+ return this.view.getUint16(this.pos);
947
+ }
948
+ lookU32() {
949
+ return this.view.getUint32(this.pos);
950
+ }
951
+ readU8() {
952
+ const e = this.view.getUint8(this.pos);
953
+ return this.pos++, e;
954
+ }
955
+ readI8() {
956
+ const e = this.view.getInt8(this.pos);
957
+ return this.pos++, e;
958
+ }
959
+ readU16() {
960
+ const e = this.view.getUint16(this.pos);
961
+ return this.pos += 2, e;
962
+ }
963
+ readI16() {
964
+ const e = this.view.getInt16(this.pos);
965
+ return this.pos += 2, e;
966
+ }
967
+ readU32() {
968
+ const e = this.view.getUint32(this.pos);
969
+ return this.pos += 4, e;
970
+ }
971
+ readI32() {
972
+ const e = this.view.getInt32(this.pos);
973
+ return this.pos += 4, e;
974
+ }
975
+ readU64() {
976
+ const e = _e(this.view, this.pos);
977
+ return this.pos += 8, e;
978
+ }
979
+ readI64() {
980
+ const e = ue(this.view, this.pos);
981
+ return this.pos += 8, e;
982
+ }
983
+ readU64AsBigInt() {
984
+ const e = this.view.getBigUint64(this.pos);
985
+ return this.pos += 8, e;
986
+ }
987
+ readI64AsBigInt() {
988
+ const e = this.view.getBigInt64(this.pos);
989
+ return this.pos += 8, e;
990
+ }
991
+ readF32() {
992
+ const e = this.view.getFloat32(this.pos);
993
+ return this.pos += 4, e;
994
+ }
995
+ readF64() {
996
+ const e = this.view.getFloat64(this.pos);
997
+ return this.pos += 8, e;
998
+ }
999
+ }
1000
+ function st(s, e) {
1001
+ return new oe(e).decode(s);
1002
+ }
1003
+ const ot = /* @__PURE__ */ new Set([
1004
+ "auth",
1005
+ "open",
1006
+ "send",
1007
+ "sync",
1008
+ "history",
1009
+ "read",
1010
+ "typing",
1011
+ "react",
1012
+ "edit",
1013
+ "delete",
1014
+ "invoke",
1015
+ "pubkey",
1016
+ "ping",
1017
+ "annotate",
1018
+ "annotate_clear"
1019
+ ]);
1020
+ function rt(s) {
1021
+ return ot.has(s.type);
1022
+ }
1023
+ function at(s) {
1024
+ return Je(s);
1025
+ }
1026
+ function ct(s) {
1027
+ let e;
1028
+ try {
1029
+ e = st(s);
1030
+ } catch {
1031
+ return null;
1032
+ }
1033
+ return typeof e != "object" || e === null || typeof e.type != "string" ? null : e;
1034
+ }
1035
+ class dt {
1036
+ constructor(e) {
1037
+ a(this, "conversationId");
1038
+ a(this, "state", "");
1039
+ a(this, "version", 0);
1040
+ a(this, "hasMoreHistory", !1);
1041
+ a(this, "lastReadByOthers", 0);
1042
+ a(this, "assignedAgentId");
1043
+ a(this, "accent");
1044
+ a(this, "subject");
1045
+ a(this, "name");
1046
+ a(this, "e2e", !1);
1047
+ a(this, "offline", !1);
1048
+ a(this, "offlineMessage", "");
1049
+ a(this, "whiteLabel", !1);
1050
+ a(this, "typing", /* @__PURE__ */ new Set());
1051
+ a(this, "online", /* @__PURE__ */ new Set());
1052
+ /** Co-browsing: shared whiteboard strokes for this conversation. */
1053
+ a(this, "annotations", []);
1054
+ /** Bumped on any annotation change so the renderer can cheaply detect updates. */
1055
+ a(this, "annotationVersion", 0);
1056
+ /** Live sentiment of the guest's latest message (agent-side only). */
1057
+ a(this, "sentiment");
1058
+ a(this, "sentimentScore");
1059
+ a(this, "actions", []);
1060
+ a(this, "byId", /* @__PURE__ */ new Map());
1061
+ a(this, "keyByClient", /* @__PURE__ */ new Map());
1062
+ a(this, "_maxSeq", 0);
1063
+ a(this, "_sorted", null);
1064
+ this.me = e;
1065
+ }
1066
+ messages() {
1067
+ return this._sorted || (this._sorted = [...this.byId.values()].sort((e, t) => {
1068
+ const n = e.status === "pending", i = t.status === "pending";
1069
+ return n !== i ? n ? 1 : -1 : n && i ? e.ts - t.ts : e.seq - t.seq;
1070
+ })), this._sorted;
1071
+ }
1072
+ visibleActions() {
1073
+ return this.actions.filter((e) => !e.availableInStates || e.availableInStates.includes(this.state));
1074
+ }
1075
+ highestSeq() {
1076
+ return this._maxSeq;
1077
+ }
1078
+ addOptimistic(e, t) {
1079
+ const n = {
1080
+ id: e,
1081
+ conversationId: this.conversationId,
1082
+ seq: 0,
1083
+ senderId: this.me,
1084
+ senderRole: "guest",
1085
+ content: t,
1086
+ ts: Date.now(),
1087
+ clientMsgId: e,
1088
+ status: "pending"
1089
+ };
1090
+ return this.byId.set(e, n), this.keyByClient.set(e, e), this._sorted = null, n;
1091
+ }
1092
+ apply(e) {
1093
+ var t;
1094
+ switch (e.type) {
1095
+ case "opened":
1096
+ this.conversationId = e.conversation.id, this.state = e.conversation.state, e.subject && (this.subject = e.subject), e.annotations && (this.annotations = e.annotations, this.annotationVersion++);
1097
+ return;
1098
+ case "manifest":
1099
+ this.actions = e.actions, this.version = e.version, e.name && (this.name = e.name), (t = e.theme) != null && t.accent && (this.accent = e.theme.accent), e.e2e && (this.e2e = !0), e.offline && (this.offline = !0), e.offlineMessage && (this.offlineMessage = e.offlineMessage), e.whiteLabel && (this.whiteLabel = !0);
1100
+ return;
1101
+ case "message":
1102
+ this.upsert({ ...e.message });
1103
+ return;
1104
+ case "ack": {
1105
+ const n = this.keyByClient.get(e.clientMsgId), i = n ? this.byId.get(n) : void 0;
1106
+ if (i && n) {
1107
+ this.byId.delete(n);
1108
+ const o = { ...i, id: e.messageId, seq: e.seq, ts: e.ts, status: "sent" };
1109
+ this.byId.set(e.messageId, o), this.keyByClient.set(e.clientMsgId, e.messageId), e.seq > this._maxSeq && (this._maxSeq = e.seq);
1110
+ }
1111
+ this._sorted = null;
1112
+ return;
1113
+ }
1114
+ case "delivered":
1115
+ this.markOwnStatus(e.seq, "delivered");
1116
+ return;
1117
+ case "read":
1118
+ e.by !== this.me && (this.lastReadByOthers = Math.max(this.lastReadByOthers, e.seq), this.markOwnStatus(e.seq, "read"));
1119
+ return;
1120
+ case "sync":
1121
+ for (const n of e.messages) this.upsert({ ...n });
1122
+ return;
1123
+ case "history":
1124
+ for (const n of e.messages) this.upsert({ ...n });
1125
+ this.hasMoreHistory = e.hasMore;
1126
+ return;
1127
+ case "typing":
1128
+ e.userId !== this.me && (e.isTyping ? this.typing.add(e.userId) : this.typing.delete(e.userId));
1129
+ return;
1130
+ case "reaction": {
1131
+ const n = this.byId.get(e.messageId);
1132
+ if (!n) return;
1133
+ const i = { ...n.reactions ?? {} }, o = (i[e.emoji] ?? []).filter((r) => r !== e.by);
1134
+ e.removed || o.push(e.by), o.length ? i[e.emoji] = o : delete i[e.emoji], this.byId.set(e.messageId, { ...n, reactions: i }), this._sorted = null;
1135
+ return;
1136
+ }
1137
+ case "edited": {
1138
+ const n = this.byId.get(e.messageId);
1139
+ n && (this.byId.set(e.messageId, { ...n, content: e.content, editedAt: e.editedAt }), this._sorted = null);
1140
+ return;
1141
+ }
1142
+ case "deleted": {
1143
+ const n = this.byId.get(e.messageId);
1144
+ n && (this.byId.set(e.messageId, { ...n, deletedAt: e.ts }), this._sorted = null);
1145
+ return;
1146
+ }
1147
+ case "state":
1148
+ this.state = e.state;
1149
+ return;
1150
+ case "assigned":
1151
+ this.assignedAgentId = e.agentId ?? void 0;
1152
+ return;
1153
+ case "presence":
1154
+ e.status === "online" ? this.online.add(e.userId) : this.online.delete(e.userId);
1155
+ return;
1156
+ case "subjectState":
1157
+ case "invoked":
1158
+ case "authed":
1159
+ case "error":
1160
+ case "pong":
1161
+ return;
1162
+ case "annotation":
1163
+ this.annotations = [...this.annotations, e.stroke], this.annotationVersion++;
1164
+ return;
1165
+ case "annotation_clear":
1166
+ this.annotations = [], this.annotationVersion++;
1167
+ return;
1168
+ case "sentiment":
1169
+ this.sentiment = e.label, this.sentimentScore = e.score;
1170
+ return;
1171
+ default:
1172
+ return;
1173
+ }
1174
+ }
1175
+ upsert(e) {
1176
+ const t = this.byId.get(e.id);
1177
+ this.byId.set(e.id, t ? { ...t, ...e } : e), e.seq > this._maxSeq && (this._maxSeq = e.seq), this._sorted = null;
1178
+ }
1179
+ markOwnStatus(e, t) {
1180
+ for (const [n, i] of this.byId)
1181
+ i.senderId === this.me && i.seq > 0 && i.seq <= e && ae(t) > ae(i.status) && (this.byId.set(n, { ...i, status: t }), this._sorted = null);
1182
+ }
1183
+ }
1184
+ function ae(s) {
1185
+ switch (s) {
1186
+ case "read":
1187
+ return 3;
1188
+ case "delivered":
1189
+ return 2;
1190
+ case "sent":
1191
+ return 1;
1192
+ default:
1193
+ return 0;
1194
+ }
1195
+ }
1196
+ class lt {
1197
+ constructor(e) {
1198
+ a(this, "socket", null);
1199
+ a(this, "state", "idle");
1200
+ a(this, "authed", !1);
1201
+ a(this, "attempt", 0);
1202
+ a(this, "outbox", []);
1203
+ a(this, "stopped", !1);
1204
+ a(this, "timer", null);
1205
+ this.opts = e;
1206
+ }
1207
+ connect() {
1208
+ var n, i;
1209
+ if (this.state === "connecting" || this.state === "open") return;
1210
+ this.stopped = !1, this.state = "connecting", this.authed = !1, (i = (n = this.opts).onStatusChange) == null || i.call(n, this.attempt > 0 ? "reconnecting" : "connecting");
1211
+ const t = (this.opts.socketFactory ?? ht)(this.opts.url);
1212
+ t.binaryType = "arraybuffer", this.socket = t, t.onopen = () => {
1213
+ this.raw({ type: "auth", token: this.opts.token });
1214
+ }, t.onmessage = (o) => {
1215
+ const r = ct(new Uint8Array(o.data));
1216
+ !r || rt(r) || this.handle(r);
1217
+ }, t.onclose = () => this.onClosed(), t.onerror = () => {
1218
+ try {
1219
+ t.close();
1220
+ } catch {
1221
+ }
1222
+ };
1223
+ }
1224
+ /** Queue a frame; sent immediately if open, else flushed on (re)connect.
1225
+ * The outbox is bounded so a prolonged outage can't grow memory without limit
1226
+ * — oldest queued frames are dropped past the cap. */
1227
+ send(e) {
1228
+ if (this.state === "open" && this.authed) {
1229
+ this.raw(e);
1230
+ return;
1231
+ }
1232
+ const t = this.opts.maxOutbox ?? 1e3;
1233
+ this.outbox.length >= t && (this.outbox = this.outbox.slice(this.outbox.length - (t >> 1))), this.outbox.push(e);
1234
+ }
1235
+ close() {
1236
+ var e;
1237
+ this.stopped = !0, this.timer && clearTimeout(this.timer), this.state = "closed";
1238
+ try {
1239
+ (e = this.socket) == null || e.close();
1240
+ } catch {
1241
+ }
1242
+ }
1243
+ handle(e) {
1244
+ var t, n;
1245
+ e.type === "authed" && (this.attempt = 0, this.state = "open", this.authed = !0, (n = (t = this.opts).onStatusChange) == null || n.call(t, "open"), this.raw(this.opts.open), this.flush()), e.type === "opened" && this.raw({ type: "sync", conversationId: e.conversation.id, sinceSeq: this.opts.getCursor() }), this.opts.onFrame(e);
1246
+ }
1247
+ flush() {
1248
+ const e = this.outbox;
1249
+ this.outbox = [];
1250
+ for (const t of e) this.raw(t);
1251
+ }
1252
+ raw(e) {
1253
+ var t;
1254
+ try {
1255
+ (t = this.socket) == null || t.send(at(e));
1256
+ } catch {
1257
+ this.outbox.push(e);
1258
+ }
1259
+ }
1260
+ onClosed() {
1261
+ if (this.authed = !1, this.socket = null, this.stopped) {
1262
+ this.state = "closed";
1263
+ return;
1264
+ }
1265
+ this.state = "idle";
1266
+ const e = this.opts.backoffBaseMs ?? 500, t = this.opts.backoffMaxMs ?? 15e3, n = Math.min(t, e * 2 ** this.attempt) * (0.5 + Math.random() * 0.5);
1267
+ this.attempt++, this.timer = setTimeout(() => this.connect(), n);
1268
+ }
1269
+ }
1270
+ function ht(s) {
1271
+ return new WebSocket(s);
1272
+ }
1273
+ const ce = 200, pt = 7 * 864e5;
1274
+ class ft {
1275
+ constructor(e) {
1276
+ a(this, "key");
1277
+ this.key = `ocw_outbox_${e}`;
1278
+ }
1279
+ /** All pending items, oldest first, with stale (>7d) entries dropped. */
1280
+ load() {
1281
+ try {
1282
+ const e = localStorage.getItem(this.key);
1283
+ if (!e) return [];
1284
+ const t = JSON.parse(e), n = Date.now() - pt, i = t.filter((o) => o.ts >= n);
1285
+ return i.length !== t.length && this.save(i), i;
1286
+ } catch {
1287
+ return [];
1288
+ }
1289
+ }
1290
+ add(e) {
1291
+ try {
1292
+ const t = this.load();
1293
+ t.push(e), this.save(t.length > ce ? t.slice(t.length - ce) : t);
1294
+ } catch {
1295
+ }
1296
+ }
1297
+ /** Remove an item once it's been acknowledged by the server. */
1298
+ remove(e) {
1299
+ try {
1300
+ const t = this.load().filter((n) => n.clientMsgId !== e);
1301
+ this.save(t);
1302
+ } catch {
1303
+ }
1304
+ }
1305
+ save(e) {
1306
+ try {
1307
+ localStorage.setItem(this.key, JSON.stringify(e));
1308
+ } catch {
1309
+ }
1310
+ }
1311
+ }
1312
+ const I = () => globalThis.crypto.subtle;
1313
+ function J(s) {
1314
+ const e = s instanceof Uint8Array ? s : new Uint8Array(s);
1315
+ let t = "";
1316
+ for (const n of e) t += String.fromCharCode(n);
1317
+ return btoa(t);
1318
+ }
1319
+ function ie(s) {
1320
+ const e = atob(s), t = new ArrayBuffer(e.length), n = new Uint8Array(t);
1321
+ for (let i = 0; i < e.length; i++) n[i] = e.charCodeAt(i);
1322
+ return n;
1323
+ }
1324
+ async function N() {
1325
+ const s = await I().generateKey({ name: "ECDH", namedCurve: "P-256" }, !0, ["deriveKey", "deriveBits"]);
1326
+ return { publicKey: s.publicKey, privateKey: s.privateKey };
1327
+ }
1328
+ async function M(s) {
1329
+ return J(await I().exportKey("raw", s));
1330
+ }
1331
+ async function H(s) {
1332
+ return I().importKey("raw", ie(s), { name: "ECDH", namedCurve: "P-256" }, !1, []);
1333
+ }
1334
+ async function ut(s, e) {
1335
+ const t = await H(e);
1336
+ return I().deriveKey(
1337
+ { name: "ECDH", public: t },
1338
+ s,
1339
+ { name: "AES-GCM", length: 256 },
1340
+ !1,
1341
+ ["encrypt", "decrypt"]
1342
+ );
1343
+ }
1344
+ async function wt(s, e) {
1345
+ const t = globalThis.crypto.getRandomValues(new Uint8Array(12)), n = new TextEncoder().encode(e), i = await I().encrypt({ name: "AES-GCM", iv: t }, s, n);
1346
+ return { ct: J(i), iv: J(t) };
1347
+ }
1348
+ async function xt(s, e, t) {
1349
+ const n = await I().decrypt({ name: "AES-GCM", iv: ie(t) }, s, ie(e));
1350
+ return new TextDecoder().decode(n);
1351
+ }
1352
+ async function gt(s) {
1353
+ var t, n;
1354
+ try {
1355
+ const i = (t = globalThis.localStorage) == null ? void 0 : t.getItem(s);
1356
+ if (i) {
1357
+ const { pub: o, priv: r } = JSON.parse(i), d = await I().importKey("jwk", o, { name: "ECDH", namedCurve: "P-256" }, !0, []), u = await I().importKey("jwk", r, { name: "ECDH", namedCurve: "P-256" }, !0, ["deriveKey", "deriveBits"]);
1358
+ return { publicKey: d, privateKey: u };
1359
+ }
1360
+ } catch {
1361
+ }
1362
+ const e = await N();
1363
+ try {
1364
+ const i = await I().exportKey("jwk", e.publicKey), o = await I().exportKey("jwk", e.privateKey);
1365
+ (n = globalThis.localStorage) == null || n.setItem(s, JSON.stringify({ pub: i, priv: o }));
1366
+ } catch {
1367
+ }
1368
+ return e;
1369
+ }
1370
+ async function yt(s, e) {
1371
+ const t = await I().exportKey("raw", e), n = await I().sign({ name: "ECDSA", hash: "SHA-256" }, s, t);
1372
+ return J(n);
1373
+ }
1374
+ async function bt() {
1375
+ const s = await N(), e = await I().generateKey({ name: "ECDSA", namedCurve: "P-256" }, !0, ["sign", "verify"]);
1376
+ return {
1377
+ ecdhKP: s,
1378
+ ecdsaKP: { publicKey: e.publicKey, privateKey: e.privateKey },
1379
+ publicKeyB64: await M(s.publicKey),
1380
+ sigPublicKeyB64: await M(e.publicKey)
1381
+ };
1382
+ }
1383
+ async function de(s) {
1384
+ var t, n;
1385
+ try {
1386
+ const i = (t = globalThis.localStorage) == null ? void 0 : t.getItem(`${s}-identity`);
1387
+ if (i) {
1388
+ const o = JSON.parse(i), r = await I().importKey("jwk", o.ecdhPub, { name: "ECDH", namedCurve: "P-256" }, !0, []), d = await I().importKey("jwk", o.ecdhPriv, { name: "ECDH", namedCurve: "P-256" }, !0, ["deriveKey", "deriveBits"]), u = await I().importKey("jwk", o.ecdsaPub, { name: "ECDSA", namedCurve: "P-256" }, !0, ["verify"]), w = await I().importKey("jwk", o.ecdsaPriv, { name: "ECDSA", namedCurve: "P-256" }, !0, ["sign"]);
1389
+ return {
1390
+ ecdhKP: { publicKey: r, privateKey: d },
1391
+ ecdsaKP: { publicKey: u, privateKey: w },
1392
+ publicKeyB64: await M(r),
1393
+ sigPublicKeyB64: await M(u)
1394
+ };
1395
+ }
1396
+ } catch {
1397
+ }
1398
+ const e = await bt();
1399
+ try {
1400
+ const i = await I().exportKey("jwk", e.ecdhKP.publicKey), o = await I().exportKey("jwk", e.ecdhKP.privateKey), r = await I().exportKey("jwk", e.ecdsaKP.publicKey), d = await I().exportKey("jwk", e.ecdsaKP.privateKey);
1401
+ (n = globalThis.localStorage) == null || n.setItem(`${s}-identity`, JSON.stringify({ ecdhPub: i, ecdhPriv: o, ecdsaPub: r, ecdsaPriv: d }));
1402
+ } catch {
1403
+ }
1404
+ return e;
1405
+ }
1406
+ async function mt(s, e) {
1407
+ const t = await N(), n = await M(t.publicKey), i = await H(e.identityKey), o = await H(e.signedPrekey), r = e.oneTimePrekey ? await H(e.oneTimePrekey) : null, d = await z(s.privateKey, o), u = await z(t.privateKey, i), w = await z(t.privateKey, o), y = r ? await z(t.privateKey, r) : null, x = xe(d, u, w, ...y ? [y] : []);
1408
+ return { sharedKey: await ge(x), ephemeralPublicKey: n };
1409
+ }
1410
+ async function vt(s, e, t, n, i) {
1411
+ const o = await H(t), r = await H(n), d = await z(e.privateKey, o), u = await z(s.privateKey, r), w = await z(e.privateKey, r), y = i ? await z(i.privateKey, r) : null, x = xe(d, u, w, ...y ? [y] : []);
1412
+ return ge(x);
1413
+ }
1414
+ async function z(s, e) {
1415
+ return I().deriveBits({ name: "ECDH", public: e }, s, 256);
1416
+ }
1417
+ function xe(...s) {
1418
+ const e = s.reduce((i, o) => i + o.byteLength, 0), t = new Uint8Array(e);
1419
+ let n = 0;
1420
+ for (const i of s)
1421
+ t.set(new Uint8Array(i), n), n += i.byteLength;
1422
+ return t.buffer;
1423
+ }
1424
+ async function ge(s) {
1425
+ const e = await I().importKey("raw", s, "HKDF", !1, ["deriveKey"]);
1426
+ return I().deriveKey(
1427
+ { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(32), info: new TextEncoder().encode("ObjectChat X3DH v1") },
1428
+ e,
1429
+ { name: "AES-GCM", length: 256 },
1430
+ !1,
1431
+ ["encrypt", "decrypt"]
1432
+ );
1433
+ }
1434
+ const kt = 20;
1435
+ class St {
1436
+ constructor(e) {
1437
+ // Live ECDH mode state
1438
+ a(this, "kp");
1439
+ a(this, "shared");
1440
+ // X3DH async mode state
1441
+ a(this, "identityKP");
1442
+ a(this, "signedPreKP");
1443
+ a(this, "signedPrekeyId");
1444
+ a(this, "otpKeys", []);
1445
+ // one-time prekeys awaiting matching
1446
+ a(this, "x3dhShared");
1447
+ // Queued init messages arriving before we could derive (shouldn't happen, but safe)
1448
+ a(this, "pendingX3DH");
1449
+ this.storageKey = e;
1450
+ }
1451
+ get ready() {
1452
+ return !!(this.shared ?? this.x3dhShared);
1453
+ }
1454
+ /** Live ECDH mode: Generate/restore our keypair and return our public key to publish. */
1455
+ async begin() {
1456
+ return this.kp = await gt(this.storageKey), M(this.kp.publicKey);
1457
+ }
1458
+ /** Live ECDH mode: A peer published their key — derive the shared secret. */
1459
+ async onPeerKey(e) {
1460
+ this.kp && (this.shared = await ut(this.kp.privateKey, e));
1461
+ }
1462
+ // ── X3DH async mode ────────────────────────────────────────────────────────
1463
+ /** X3DH: Generate identity key, signed prekey, and OTP prekeys.
1464
+ * Returns the upload frame payload the caller should send to the server. */
1465
+ async initX3DH() {
1466
+ this.identityKP = await de(this.storageKey), this.signedPreKP = await N(), this.signedPrekeyId = `spk-${Date.now()}-${Math.random().toString(36).slice(2)}`;
1467
+ for (let i = 0; i < kt; i++) this.otpKeys.push(await N());
1468
+ const e = await M(this.signedPreKP.publicKey), t = await yt(this.identityKP.ecdsaKP.privateKey, this.signedPreKP.publicKey), n = await Promise.all(this.otpKeys.map((i) => M(i.publicKey)));
1469
+ return {
1470
+ identityKey: this.identityKP.publicKeyB64,
1471
+ signedPrekey: e,
1472
+ signedPrekeyId: this.signedPrekeyId,
1473
+ signature: t,
1474
+ oneTimePrekeys: n
1475
+ };
1476
+ }
1477
+ /** X3DH sender: given a recipient's prekey bundle, derive the shared key and
1478
+ * return the init message fields to embed in the first encrypted message. */
1479
+ async x3dhSendTo(e) {
1480
+ this.identityKP || (this.identityKP = await de(this.storageKey));
1481
+ const { sharedKey: t, ephemeralPublicKey: n } = await mt(this.identityKP.ecdhKP, e);
1482
+ return this.x3dhShared = t, { ephemeralKey: n, spkId: e.signedPrekeyId, usedOTP: !!e.oneTimePrekey, senderIK: this.identityKP.publicKeyB64 };
1483
+ }
1484
+ /** X3DH recipient: given an init message's sender IK + EK + SPK ID, derive the shared key. */
1485
+ async x3dhReceiveFrom(e, t, n) {
1486
+ if (!this.identityKP || !this.signedPreKP) {
1487
+ this.pendingX3DH = { senderIK: e, ephemeralKey: t, spkId: n };
1488
+ return;
1489
+ }
1490
+ const i = this.otpKeys.shift();
1491
+ this.x3dhShared = await vt(this.identityKP.ecdhKP, this.signedPreKP, e, t, i);
1492
+ }
1493
+ /** Flush pending X3DH derivation after initX3DH() completes. */
1494
+ async flushPendingX3DH() {
1495
+ if (!this.pendingX3DH) return;
1496
+ const { senderIK: e, ephemeralKey: t, spkId: n } = this.pendingX3DH;
1497
+ this.pendingX3DH = void 0, await this.x3dhReceiveFrom(e, t, n);
1498
+ }
1499
+ /** Encrypt outgoing text into a wire content object. For X3DH init messages,
1500
+ * the caller should pass x3dhInit fields to embed in the content. */
1501
+ async sealText(e, t) {
1502
+ const n = this.x3dhShared ?? this.shared;
1503
+ if (!n) throw new Error("secure channel not ready");
1504
+ const { ct: i, iv: o } = await wt(n, e);
1505
+ return {
1506
+ kind: "text",
1507
+ text: i,
1508
+ enc: !0,
1509
+ iv: o,
1510
+ ...t ? { x3dhEK: t.ephemeralKey, x3dhSPK: t.spkId, x3dhIK: t.senderIK } : {}
1511
+ };
1512
+ }
1513
+ /** Decrypt one content object if it is encrypted (otherwise pass through). */
1514
+ async openContent(e) {
1515
+ if (e.kind !== "text" || !e.enc || !e.iv) return e;
1516
+ const t = this.x3dhShared ?? this.shared;
1517
+ if (!t) return { kind: "text", text: "🔒 encrypted" };
1518
+ try {
1519
+ return { kind: "text", text: await xt(t, e.text, e.iv) };
1520
+ } catch {
1521
+ return { kind: "text", text: "🔒 unable to decrypt" };
1522
+ }
1523
+ }
1524
+ /** Decrypt any encrypted message content carried by an incoming frame, in place. */
1525
+ async openFrame(e) {
1526
+ if (e.type === "message") e.message.content = await this.openContent(e.message.content);
1527
+ else if (e.type === "sync")
1528
+ for (const t of e.messages) t.content = await this.openContent(t.content);
1529
+ }
1530
+ }
1531
+ function Ct(s) {
1532
+ if (s.kind !== "text" || !s.enc) return null;
1533
+ const e = s;
1534
+ return !e.x3dhEK || !e.x3dhSPK || !e.x3dhIK ? null : { x3dhEK: e.x3dhEK, x3dhSPK: e.x3dhSPK, x3dhIK: e.x3dhIK };
1535
+ }
1536
+ const le = "objectchat-widget-styles", It = ["👍", "❤️", "😂", "😮", "😢", "🙏"], Et = `
1537
+ .ocw { --ocw-accent:#f5713c; --ocw-bg:#f3efe9; --ocw-card:#fff; --ocw-line:#ececec; --ocw-ink:#1c1b1a; --ocw-mut:#9b9690;
1538
+ position:relative;
1539
+ display:flex; flex-direction:column; height:100%; min-height:320px; background:var(--ocw-bg);
1540
+ font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',system-ui,sans-serif; color:var(--ocw-ink); overflow:hidden; }
1541
+ @media (max-width:480px) {
1542
+ .ocw { min-height:100dvh; border-radius:0 !important; }
1543
+ .ocw-bubble { font-size:15px; }
1544
+ .ocw-input textarea { font-size:16px; } /* prevent iOS zoom on focus */
1545
+ .ocw-chip { padding:9px 14px; font-size:14px; }
1546
+ .ocw-modal-card { width:90%; }
1547
+ .ocw-row { max-width:94%; }
1548
+ }
1549
+ /* RTL support: when the host element has dir=rtl, flip layout direction */
1550
+ [dir="rtl"] .ocw-row.mine { flex-direction:row; }
1551
+ [dir="rtl"] .ocw-row.theirs { flex-direction:row-reverse; }
1552
+ [dir="rtl"] .mine .ocw-bubble { border-bottom-right-radius:18px; border-bottom-left-radius:6px; }
1553
+ [dir="rtl"] .theirs .ocw-bubble { border-bottom-left-radius:18px; border-bottom-right-radius:6px; }
1554
+ [dir="rtl"] .ocw-input { flex-direction:row-reverse; }
1555
+ [dir="rtl"] .mine .ocw-meta { text-align:left; }
1556
+ .ocw-head { display:flex; align-items:center; gap:10px; padding:12px 14px; background:var(--ocw-card); border-bottom:1px solid var(--ocw-line); }
1557
+ .ocw-avatar { width:34px; height:34px; border-radius:50%; background:#ffe9d6; display:flex; align-items:center; justify-content:center; font-size:17px; flex:none; }
1558
+ .ocw-head-main { flex:1; min-width:0; }
1559
+ .ocw-head-name { font-weight:700; font-size:15px; }
1560
+ .ocw-head-meta { color:var(--ocw-mut); font-size:12px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
1561
+ .ocw-badge { font-size:12px; font-weight:600; color:#15803d; background:#e8f6ec; border-radius:999px; padding:3px 10px; }
1562
+ .ocw-e2e { font-size:11px; font-weight:700; color:#3730a3; background:#eef2ff; border-radius:999px; padding:3px 9px; align-items:center; }
1563
+ .ocw-menu { color:var(--ocw-mut); width:30px; height:30px; border-radius:50%; border:1px solid var(--ocw-line); background:#fff; cursor:pointer; }
1564
+ .ocw-chiprow { display:flex; gap:8px; padding:10px 12px; background:var(--ocw-card); border-bottom:1px solid var(--ocw-line); overflow-x:auto; }
1565
+ .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; }
1566
+ .ocw-chip:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
1567
+ .ocw-scroll { flex:1; min-height:0; overflow-y:auto; padding:16px 14px; display:flex; flex-direction:column; gap:10px; }
1568
+ .ocw-subject { background:var(--ocw-card); border:1px solid var(--ocw-line); border-radius:16px; padding:14px 16px; }
1569
+ .ocw-subject-title { font-weight:700; font-size:16px; margin-bottom:2px; }
1570
+ .ocw-subject-sub { color:var(--ocw-mut); font-size:13px; margin-bottom:10px; }
1571
+ .ocw-tags { display:flex; flex-wrap:wrap; gap:6px; }
1572
+ .ocw-tag { font-size:12px; color:#5b554e; background:#efeae3; border-radius:8px; padding:4px 10px; }
1573
+ .ocw-row { display:flex; align-items:flex-end; gap:8px; max-width:86%; }
1574
+ .ocw-row.mine { align-self:flex-end; flex-direction:row-reverse; }
1575
+ .ocw-row.theirs { align-self:flex-start; }
1576
+ .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; }
1577
+ .ocw-bubble { padding:10px 14px; border-radius:18px; font-size:14.5px; line-height:1.4; word-wrap:break-word; }
1578
+ .theirs .ocw-bubble { background:#fff; border:1px solid var(--ocw-line); border-bottom-left-radius:6px; }
1579
+ .mine .ocw-bubble { background:var(--ocw-accent); color:#fff; border-bottom-right-radius:6px; }
1580
+ .ocw-sys { align-self:center; color:var(--ocw-mut); font-size:12.5px; font-style:italic; text-align:center; max-width:90%; }
1581
+ .ocw-bot .ocw-bubble { background:#f0fdf4; border-color:#cdebd6; }
1582
+ .ocw-note .ocw-bubble { background:#fffbeb; border:1.5px dashed #f59e0b; color:#78350f; border-radius:12px !important; }
1583
+ .ocw-note .ocw-bubble::before { content:'🔒 Note — '; font-size:11px; font-weight:700; color:#b45309; display:block; margin-bottom:3px; letter-spacing:.3px; }
1584
+ .ocw-time { font-size:10.5px; color:var(--ocw-mut); margin-top:3px; }
1585
+ .mine .ocw-meta { text-align:right; }
1586
+ .ocw-tick { margin-left:4px; font-size:11px; color:var(--ocw-mut); }
1587
+ .ocw-tick.read { color:#3b82f6; }
1588
+ .ocw-tick.delivered { color:var(--ocw-mut); }
1589
+ .ocw-deleted { font-style:italic; color:var(--ocw-mut); }
1590
+ .ocw-edited { font-size:10px; color:var(--ocw-mut); margin-left:4px; }
1591
+ .ocw-react { font-size:12px; margin-top:3px; display:flex; flex-wrap:wrap; gap:3px; }
1592
+ .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; }
1593
+ .ocw-react-pill:hover { border-color:var(--ocw-accent); }
1594
+ .ocw-react-pill.mine { border-color:var(--ocw-accent); background:#fff8f5; }
1595
+ .ocw-react-add { display:none; position:absolute; bottom:100%; left:0; margin-bottom:4px; 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; }
1596
+ .ocw-react-wrap { position:relative; }
1597
+ .ocw-react-wrap:not(:hover) .ocw-react-picker { display:none; }
1598
+ .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; }
1599
+ .ocw-react-picker button { background:none; border:none; font-size:16px; cursor:pointer; padding:2px; border-radius:6px; }
1600
+ .ocw-react-picker button:hover { background:#f3efe9; }
1601
+ .ocw-react-btn { background:none; border:1px solid #e3ded7; border-radius:999px; padding:2px 7px; font-size:12px; cursor:pointer; color:var(--ocw-mut); }
1602
+ .ocw-react-btn:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
1603
+ .ocw-msg-menu { position:absolute; top:0; right:0; display:none; gap:3px; }
1604
+ .ocw-row.mine:hover .ocw-msg-menu { display:flex; }
1605
+ .ocw-row.theirs:hover .ocw-msg-menu { display:flex; left:0; right:auto; }
1606
+ .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); }
1607
+ .ocw-msg-menu button:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
1608
+ .ocw-msg-menu button.del:hover { border-color:#e74c3c; color:#e74c3c; }
1609
+ .ocw-bubble-wrap { position:relative; }
1610
+ .ocw-seen { font-size:10.5px; color:var(--ocw-mut); }
1611
+ .ocw-appt { background:#f0f7ff; border:1px solid #c7deff; border-radius:12px; padding:12px 14px; max-width:260px; }
1612
+ .ocw-appt-title { font-weight:700; font-size:14px; margin-bottom:4px; }
1613
+ .ocw-appt-time { font-size:12px; color:#1d4ed8; margin-bottom:4px; }
1614
+ .ocw-appt-loc { font-size:12px; color:var(--ocw-mut); margin-bottom:4px; }
1615
+ .ocw-appt-desc { font-size:12px; color:var(--ocw-mut); margin-bottom:10px; white-space:pre-wrap; }
1616
+ .ocw-appt-links { display:flex; flex-direction:column; gap:6px; }
1617
+ .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; }
1618
+ .ocw-appt-btn-sec { background:#fff; color:var(--ocw-accent); border:1px solid var(--ocw-accent); }
1619
+ .ocw-conn-status { font-size:10px; color:var(--ocw-mut); margin-left:4px; }
1620
+ .ocw-conn-status.warn { color:#e67e22; }
1621
+ .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; }
1622
+ .ocw-load-more:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
1623
+ .ocw-offline { margin:20px 14px; padding:20px; background:#fff; border:1px solid #e3ded7; border-radius:16px; text-align:center; }
1624
+ .ocw-offline-icon { font-size:32px; margin-bottom:8px; }
1625
+ .ocw-offline-title { font-weight:700; font-size:16px; margin-bottom:6px; }
1626
+ .ocw-offline-msg { font-size:13px; color:var(--ocw-mut); margin-bottom:16px; }
1627
+ .ocw-offline-form { display:flex; flex-direction:column; gap:8px; text-align:left; }
1628
+ .ocw-offline-input { border:1px solid #e3ded7; border-radius:10px; padding:10px 12px; font-size:13px; font-family:inherit; }
1629
+ .ocw-offline-input:focus { outline:none; border-color:var(--ocw-accent); }
1630
+ .ocw-offline-submit { background:var(--ocw-accent); color:#fff; border:none; border-radius:10px; padding:11px; font-size:14px; font-weight:600; cursor:pointer; }
1631
+ .ocw-offline-thanks { font-size:14px; color:#15803d; font-weight:600; }
1632
+ .ocw-csat-title { font-size:13px; font-weight:600; margin-bottom:8px; }
1633
+ .ocw-csat-stars { display:flex; gap:6px; }
1634
+ .ocw-csat-star { background:none; border:none; font-size:22px; cursor:pointer; padding:2px; opacity:.4; transition:opacity .15s; }
1635
+ .ocw-csat-star:hover, .ocw-csat-star.lit { opacity:1; }
1636
+ .ocw-csat-done { font-size:12px; color:var(--ocw-mut); margin-top:6px; }
1637
+
1638
+ .ocw-typing { min-height:22px; padding:0 16px 4px; display:flex; align-items:center; }
1639
+ .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; }
1640
+ .ocw-typing.active .ocw-typing-bubble { display:flex; }
1641
+ .ocw-typing-dot { width:6px; height:6px; border-radius:50%; background:var(--ocw-mut); animation:ocw-bounce 1.2s infinite ease-in-out; }
1642
+ .ocw-typing-dot:nth-child(2) { animation-delay:.2s; }
1643
+ .ocw-typing-dot:nth-child(3) { animation-delay:.4s; }
1644
+ @keyframes ocw-bounce { 0%,60%,100%{transform:translateY(0)} 30%{transform:translateY(-5px)} }
1645
+ .ocw-quick { display:flex; gap:8px; padding:8px 12px 0; overflow-x:auto; }
1646
+ .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; }
1647
+ .ocw-quick button:hover { border-color:var(--ocw-accent); color:var(--ocw-accent); }
1648
+ .ocw-form-host:empty { display:none; }
1649
+ .ocw-form { margin:6px 12px 0; padding:12px; background:var(--ocw-card); border:1px solid var(--ocw-line); border-radius:14px; }
1650
+ .ocw-form-title { font-weight:700; font-size:14px; margin-bottom:8px; }
1651
+ .ocw-form-row { display:flex; flex-direction:column; gap:3px; margin-bottom:8px; }
1652
+ .ocw-form-lbl { font-size:12px; color:var(--ocw-mut); }
1653
+ .ocw-form-input { border:1px solid #e3ded7; border-radius:9px; padding:9px 11px; font:inherit; font-size:14px; outline:none; }
1654
+ .ocw-form-input:focus { border-color:var(--ocw-accent); }
1655
+ .ocw-form-actions { display:flex; justify-content:flex-end; gap:8px; margin-top:4px; }
1656
+ .ocw-form-cancel { background:none; border:none; color:var(--ocw-mut); font-size:13px; cursor:pointer; padding:8px 10px; }
1657
+ .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; }
1658
+ .ocw-modal { position:absolute; inset:0; background:rgba(20,18,16,.42); display:flex; align-items:center; justify-content:center; z-index:50; }
1659
+ .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); }
1660
+ .ocw-modal-title { font-weight:700; font-size:16px; margin-bottom:6px; }
1661
+ .ocw-modal-body { color:var(--ocw-mut); font-size:14px; margin-bottom:16px; }
1662
+ .ocw-modal-actions { display:flex; justify-content:flex-end; gap:8px; }
1663
+ .ocw-modal-cancel { background:none; border:none; color:var(--ocw-mut); font-size:14px; cursor:pointer; padding:9px 12px; }
1664
+ .ocw-modal-ok { background:var(--ocw-accent); color:#fff; border:none; border-radius:999px; padding:9px 20px; font-size:14px; font-weight:600; cursor:pointer; }
1665
+ .ocw-input { display:flex; align-items:center; gap:10px; padding:12px; }
1666
+ .ocw-footer { text-align:center; font-size:11px; color:var(--ocw-mut); padding:6px 0 8px; }
1667
+ .ocw-footer a { color:var(--ocw-mut); text-decoration:none; font-weight:600; }
1668
+ .ocw-footer a:hover { color:var(--ocw-accent); }
1669
+ .ocw-attach { background:none;border:none;cursor:pointer;font-size:18px;padding:4px 6px;opacity:.6;flex-none; }
1670
+ .ocw-attach:hover { opacity:1; }
1671
+ .ocw-input textarea { flex:1; resize:none; border:1px solid #e3ded7; border-radius:22px; padding:11px 16px; font:inherit; font-size:14px; background:#fff; outline:none; max-height:96px; }
1672
+ .ocw-input textarea:focus { border-color:var(--ocw-accent); }
1673
+ .ocw-sendbtn { width:42px; height:42px; border-radius:50%; border:none; background:var(--ocw-accent); color:#fff; font-size:18px; cursor:pointer; flex:none; display:flex; align-items:center; justify-content:center; }
1674
+ .ocw-sendbtn:disabled { opacity:.5; cursor:default; }
1675
+ .ocw-cobrowse-btn { display:none; }
1676
+ .ocw-cobrowse-btn.show { display:inline-flex; }
1677
+ .ocw-cobrowse-btn.on { color:var(--ocw-accent); border-color:var(--ocw-accent); }
1678
+ .ocw-cobrowse-canvas { position:absolute; inset:0; z-index:40; touch-action:none; display:none; }
1679
+ .ocw-cobrowse-canvas.active { display:block; cursor:crosshair; }
1680
+ .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); }
1681
+ .ocw-cobrowse-toolbar.active { display:flex; align-items:center; }
1682
+ .ocw-cobrowse-swatch { width:18px; height:18px; border-radius:50%; border:2px solid transparent; cursor:pointer; padding:0; }
1683
+ .ocw-cobrowse-swatch.sel { border-color:#1c1b1a; }
1684
+ .ocw-cobrowse-clear { background:none; border:1px solid #e3ded7; border-radius:999px; font-size:11px; padding:3px 8px; cursor:pointer; color:var(--ocw-mut); }
1685
+ .ocw-cobrowse-clear:hover { border-color:#e74c3c; color:#e74c3c; }
1686
+ .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; }
1687
+ .ocw-cobrowse-hint.active { display:block; }
1688
+ /* ── Chat-app mode (showChatList=true): WhatsApp-style two-screen navigation ── */
1689
+ /* Screen A: conversation list — full widget, like WhatsApp's home screen */
1690
+ .ocw-screen { position:absolute; inset:0; display:flex; flex-direction:column; background:var(--ocw-bg); transition:transform .22s cubic-bezier(.4,0,.2,1); will-change:transform; }
1691
+ .ocw-screen-list { transform:translateX(0); z-index:10; }
1692
+ .ocw-screen-chat { transform:translateX(100%); z-index:20; background:var(--ocw-card); }
1693
+ .ocw-screen-list.hidden { transform:translateX(-30%); }
1694
+ .ocw-screen-chat.visible { transform:translateX(0); }
1695
+ /* List header */
1696
+ .ocw-cl-head { display:flex; align-items:center; padding:14px 16px 10px; background:var(--ocw-card); border-bottom:1px solid var(--ocw-line); gap:8px; }
1697
+ .ocw-cl-title { flex:1; font-size:17px; font-weight:700; color:var(--ocw-ink); }
1698
+ .ocw-cl-new { width:34px; height:34px; border-radius:50%; border:none; background:var(--ocw-accent); color:#fff; font-size:20px; cursor:pointer; display:flex; align-items:center; justify-content:center; flex:none; }
1699
+ /* Search bar */
1700
+ .ocw-cl-search-wrap { padding:8px 12px; background:var(--ocw-card); }
1701
+ .ocw-cl-search { width:100%; box-sizing:border-box; border:none; background:var(--ocw-bg); border-radius:20px; padding:8px 14px; font:inherit; font-size:14px; color:var(--ocw-ink); outline:none; }
1702
+ /* Section dividers: read / unread */
1703
+ .ocw-cl-section { padding:4px 16px 4px; font-size:11px; font-weight:700; color:var(--ocw-mut); letter-spacing:.5px; text-transform:uppercase; background:var(--ocw-bg); }
1704
+ /* Conversation row */
1705
+ .ocw-cl-row { display:flex; align-items:center; gap:12px; padding:10px 16px; background:var(--ocw-card); border:none; width:100%; text-align:left; cursor:pointer; border-bottom:1px solid var(--ocw-line); transition:background .1s; }
1706
+ .ocw-cl-row:hover, .ocw-cl-row:active { background:#faf8f6; }
1707
+ .ocw-cl-row.unread { background:var(--ocw-card); }
1708
+ /* Avatar circle with initial */
1709
+ .ocw-cl-av { width:46px; height:46px; border-radius:50%; background:var(--ocw-accent); color:#fff; font-size:18px; font-weight:700; display:flex; align-items:center; justify-content:center; flex:none; position:relative; }
1710
+ .ocw-cl-av img { width:100%; height:100%; border-radius:50%; object-fit:cover; }
1711
+ /* Status dot on avatar: green=open, grey=resolved */
1712
+ .ocw-cl-status { position:absolute; bottom:1px; right:1px; width:12px; height:12px; border-radius:50%; border:2px solid var(--ocw-card); background:#9b9690; }
1713
+ .ocw-cl-status.open { background:#22c55e; }
1714
+ .ocw-cl-status.waiting { background:#f59e0b; }
1715
+ /* Row content */
1716
+ .ocw-cl-body { flex:1; min-width:0; }
1717
+ .ocw-cl-name { font-size:15px; font-weight:600; color:var(--ocw-ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-bottom:2px; }
1718
+ .ocw-cl-row.unread .ocw-cl-name { font-weight:700; }
1719
+ .ocw-cl-preview { font-size:13px; color:var(--ocw-mut); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
1720
+ .ocw-cl-row.unread .ocw-cl-preview { color:var(--ocw-ink); }
1721
+ /* Right side: time + unread badge */
1722
+ .ocw-cl-right { display:flex; flex-direction:column; align-items:flex-end; gap:4px; flex:none; }
1723
+ .ocw-cl-time { font-size:11px; color:var(--ocw-mut); }
1724
+ .ocw-cl-row.unread .ocw-cl-time { color:var(--ocw-accent); font-weight:600; }
1725
+ .ocw-cl-badge { background:var(--ocw-accent); color:#fff; border-radius:999px; font-size:11px; font-weight:700; min-width:20px; height:20px; padding:0 5px; display:flex; align-items:center; justify-content:center; }
1726
+ .ocw-cl-body-scroll { flex:1; overflow-y:auto; }
1727
+ /* Chat screen back button */
1728
+ .ocw-chat-back { background:none; border:none; cursor:pointer; font-size:22px; color:var(--ocw-ink); padding:2px 6px 2px 0; line-height:1; display:none; }
1729
+ .ocw-chat-back.show { display:block; }
1730
+ .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; }
1731
+ .ocw-row.theirs .ocw-translate-btn { right:auto; left:-26px; }
1732
+ .ocw-bubble-wrap:hover .ocw-translate-btn { opacity:1; }
1733
+ .ocw-translated-tag { font-size:10px; color:var(--ocw-mut); margin-top:2px; }
1734
+ `;
1735
+ function Ut() {
1736
+ if (typeof document > "u" || document.getElementById(le)) return;
1737
+ const s = document.createElement("style");
1738
+ s.id = le, s.textContent = Et, document.head.appendChild(s);
1739
+ }
1740
+ function c(s, e, t) {
1741
+ const n = document.createElement(s);
1742
+ return e && (n.className = e), t !== void 0 && (n.textContent = t), n;
1743
+ }
1744
+ function Tt(s) {
1745
+ try {
1746
+ return new Date(s).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
1747
+ } catch {
1748
+ return "";
1749
+ }
1750
+ }
1751
+ function Bt(s) {
1752
+ const e = Math.floor((Date.now() - s) / 1e3);
1753
+ return e < 60 ? "now" : e < 3600 ? `${Math.floor(e / 60)}m` : e < 86400 ? `${Math.floor(e / 3600)}h` : `${Math.floor(e / 86400)}d`;
1754
+ }
1755
+ function Q(s) {
1756
+ var e;
1757
+ switch (s.kind) {
1758
+ case "text":
1759
+ return s.text;
1760
+ case "system":
1761
+ return typeof ((e = s.data) == null ? void 0 : e.message) == "string" ? String(s.data.message) : s.event;
1762
+ case "card":
1763
+ return [s.title, s.body].filter(Boolean).join(" — ");
1764
+ case "attachment":
1765
+ return s.name ?? s.url;
1766
+ case "form":
1767
+ return s.prompt;
1768
+ case "appointment":
1769
+ return `📅 ${s.title} — ${new Date(s.startIso).toLocaleString()}`;
1770
+ }
1771
+ }
1772
+ class At {
1773
+ constructor(e, t, n, i = {}) {
1774
+ a(this, "scroll");
1775
+ a(this, "chips");
1776
+ a(this, "typing");
1777
+ a(this, "quick");
1778
+ a(this, "formHost");
1779
+ a(this, "csatPanel");
1780
+ a(this, "offlinePanel");
1781
+ a(this, "footer");
1782
+ a(this, "input");
1783
+ a(this, "subjectCard");
1784
+ a(this, "e2eBadge");
1785
+ a(this, "statusBadge");
1786
+ a(this, "headerName");
1787
+ a(this, "connStatus");
1788
+ a(this, "typingTimer", null);
1789
+ a(this, "csatSubmitted", !1);
1790
+ // ── Co-browsing (shared whiteboard) ─────────────────────────────────────
1791
+ a(this, "cobrowseBtn");
1792
+ a(this, "cobrowseCanvas");
1793
+ a(this, "cobrowseToolbar");
1794
+ a(this, "cobrowseHint");
1795
+ a(this, "cobrowseActive", !1);
1796
+ a(this, "cobrowseColor", "#f5713c");
1797
+ a(this, "lastAnnotationVersion", -1);
1798
+ a(this, "storeRef", null);
1799
+ a(this, "scrollCleanup", null);
1800
+ // ── Live translation ──────────────────────────────────────────────────-
1801
+ a(this, "translationCache", /* @__PURE__ */ new Map());
1802
+ a(this, "showingTranslation", /* @__PURE__ */ new Set());
1803
+ // ── Chat-app two-screen navigation ──────────────────────────────────────────
1804
+ a(this, "listScreen", null);
1805
+ a(this, "chatScreen", null);
1806
+ a(this, "listBody", null);
1807
+ a(this, "listSearch", null);
1808
+ a(this, "backBtn", null);
1809
+ a(this, "activeChatId", null);
1810
+ a(this, "inChatScreen", !1);
1811
+ a(this, "allEntries", []);
1812
+ /** Last seq the guest has seen per conversationId — used to compute unread badges. */
1813
+ a(this, "seenSeq", /* @__PURE__ */ new Map());
1814
+ a(this, "seenSeqKey", "");
1815
+ /** Fetch the list and re-render it. Called on mount and after switching chats. */
1816
+ a(this, "destroyed", !1);
1817
+ a(this, "subjectBuilt", !1);
1818
+ var k, b, E, B, T, A, $, _, D, W;
1819
+ this.root = e, this.me = t, this.h = n, this.cfg = i, Ut(), e.classList.add("ocw"), i.accent && e.style.setProperty("--ocw-accent", i.accent);
1820
+ const o = c("div", "ocw-head"), r = c("div", "ocw-avatar");
1821
+ if ((k = i.userInfo) != null && k.avatar) {
1822
+ const S = document.createElement("img");
1823
+ S.src = i.userInfo.avatar, S.alt = i.userInfo.name ?? "You", S.style.cssText = "width:100%;height:100%;border-radius:50%;object-fit:cover", r.append(S);
1824
+ } else
1825
+ r.textContent = (b = i.userInfo) != null && b.name ? i.userInfo.name[0].toUpperCase() : "🧑";
1826
+ o.append(r);
1827
+ const d = c("div", "ocw-head-main");
1828
+ this.headerName = c("div", "ocw-head-name", ((E = i.subject) == null ? void 0 : E.ownerLabel) ?? ((B = i.subject) == null ? void 0 : B.title) ?? ""), d.append(this.headerName), (T = i.subject) != null && T.subtitle && d.append(c("div", "ocw-head-meta", i.subject.subtitle)), o.append(d), this.statusBadge = c("span", "ocw-badge", ((A = i.subject) == null ? void 0 : A.status) ?? ""), ($ = i.subject) != null && $.status || (this.statusBadge.style.display = "none"), o.append(this.statusBadge), this.e2eBadge = c("span", "ocw-e2e", "🔒 E2E"), this.e2eBadge.style.display = "none", o.append(this.e2eBadge), this.connStatus = c("span", "ocw-conn-status"), this.connStatus.style.display = "none", o.append(this.connStatus), this.cobrowseBtn = c("button", "ocw-menu ocw-cobrowse-btn", "🖍"), this.cobrowseBtn.title = "Shared whiteboard — draw to point things out together", this.cobrowseBtn.addEventListener("click", () => {
1829
+ this.cobrowseActive = !this.cobrowseActive, this.updateCobrowseUI();
1830
+ }), o.append(this.cobrowseBtn), this.h.onListChats && (this.backBtn = c("button", "ocw-chat-back", "←"), this.backBtn.addEventListener("click", () => this.showListScreen()), o.prepend(this.backBtn)), o.append(c("button", "ocw-menu", "⋯")), this.chips = c("div", "ocw-chiprow"), this.scroll = c("div", "ocw-scroll"), this.subjectCard = c("div", "ocw-subject"), this.typing = c("div", "ocw-typing");
1831
+ const u = c("div", "ocw-typing-bubble");
1832
+ u.append(c("div", "ocw-typing-dot"), c("div", "ocw-typing-dot"), c("div", "ocw-typing-dot")), this.typing.append(c("div", "ocw-dot", "🧑"), u), this.quick = c("div", "ocw-quick");
1833
+ for (const S of i.quickReplies ?? []) {
1834
+ const m = c("button", void 0, S);
1835
+ m.addEventListener("click", () => this.h.onSend(S)), this.quick.append(m);
1836
+ }
1837
+ this.formHost = c("div", "ocw-form-host"), this.csatPanel = c("div", "ocw-csat"), this.csatPanel.style.display = "none", this.offlinePanel = c("div", "ocw-offline"), this.offlinePanel.style.display = "none", this.input = c("textarea", void 0), this.input.rows = 1, this.input.placeholder = "Message…";
1838
+ const w = c("button", "ocw-sendbtn", ((_ = i.i18n) == null ? void 0 : _.send) ?? "➤");
1839
+ w.addEventListener("click", () => this.flushSend()), this.input.addEventListener("keydown", (S) => {
1840
+ S.isComposing || S.keyCode === 229 || (S.key === "Enter" && !S.shiftKey ? (S.preventDefault(), this.flushSend()) : this.signalTyping());
1841
+ });
1842
+ const y = c("button", "ocw-attach", "📎");
1843
+ y.title = "Attach image or file";
1844
+ const x = document.createElement("input");
1845
+ x.type = "file", x.accept = "image/*,.pdf,.txt,.doc,.docx", x.style.display = "none", y.addEventListener("click", () => x.click()), x.addEventListener("change", () => {
1846
+ var S;
1847
+ (S = x.files) != null && S[0] && this.h.onAttach && this.h.onAttach(x.files[0]), x.value = "";
1848
+ });
1849
+ const p = c("div", "ocw-input");
1850
+ p.append(y, x, this.input, w);
1851
+ const h = c("div", "ocw-footer");
1852
+ if (h.innerHTML = ((D = i.i18n) == null ? void 0 : D.poweredBy) !== void 0 ? i.i18n.poweredBy : 'Powered by <a href="https://relay.paramms.com" target="_blank" rel="noopener">Relay</a>', this.footer = h, this.h.onListChats) {
1853
+ const S = c("div", "ocw-screen ocw-screen-list"), m = c("div", "ocw-cl-head");
1854
+ m.append(c("span", "ocw-cl-title", "Messages"));
1855
+ const q = c("button", "ocw-cl-new", "+");
1856
+ q.title = "New conversation", q.addEventListener("click", () => {
1857
+ var f, g;
1858
+ (g = (f = this.h).onSwitchChat) == null || g.call(f, { id: "__new__", state: "open", updatedAt: Date.now() });
1859
+ }), m.append(q);
1860
+ const V = c("div", "ocw-cl-search-wrap"), P = c("input", "ocw-cl-search");
1861
+ P.placeholder = "🔍 Search", P.type = "search", P.addEventListener("input", () => this.renderListRows(this.allEntries, P.value.trim().toLowerCase())), V.append(P);
1862
+ const R = c("div", "ocw-cl-body-scroll");
1863
+ R.append(c("div", "ocw-cl-section", "Loading…")), S.append(m, V, R), e.append(S), this.listScreen = S, this.listBody = R, this.listSearch = P;
1864
+ const l = c("div", "ocw-screen ocw-screen-chat");
1865
+ l.append(o, this.chips, this.scroll, this.typing, this.quick, this.formHost, this.csatPanel, this.offlinePanel, p, this.footer), e.append(l), this.chatScreen = l, i.startOnChat ? (this.inChatScreen = !0, this.listScreen.classList.add("hidden"), this.chatScreen.classList.add("visible"), (W = this.backBtn) == null || W.classList.add("show")) : this.inChatScreen = !1, this.refreshList();
1866
+ } else
1867
+ e.append(o, this.chips, this.scroll, this.typing, this.quick, this.formHost, this.csatPanel, this.offlinePanel, p, this.footer);
1868
+ this.cobrowseCanvas = c("canvas", "ocw-cobrowse-canvas"), this.cobrowseToolbar = c("div", "ocw-cobrowse-toolbar");
1869
+ for (const S of ["#f5713c", "#1c1b1a", "#2563eb", "#16a34a", "#dc2626"]) {
1870
+ const m = c("button", "ocw-cobrowse-swatch");
1871
+ m.style.background = S, m.type = "button", S === this.cobrowseColor && m.classList.add("sel"), m.addEventListener("click", () => {
1872
+ this.cobrowseColor = S;
1873
+ for (const q of this.cobrowseToolbar.querySelectorAll(".ocw-cobrowse-swatch")) q.classList.remove("sel");
1874
+ m.classList.add("sel");
1875
+ }), this.cobrowseToolbar.append(m);
1876
+ }
1877
+ const v = c("button", "ocw-cobrowse-clear", "Clear");
1878
+ v.addEventListener("click", () => {
1879
+ var S, m;
1880
+ return (m = (S = this.h).onAnnotateClear) == null ? void 0 : m.call(S);
1881
+ }), this.cobrowseToolbar.append(v), this.cobrowseHint = c("div", "ocw-cobrowse-hint", "🖍 Draw to point things out — visible to both sides"), e.append(this.cobrowseCanvas, this.cobrowseToolbar, this.cobrowseHint), this.bindCobrowsePointerEvents();
1882
+ }
1883
+ /** Returns the scroll container so history.ts can attach scroll listeners. */
1884
+ getScrollEl() {
1885
+ return this.scroll;
1886
+ }
1887
+ /** Registers a cleanup fn removed on destroy() to prevent listener leaks. */
1888
+ setScrollCleanup(e) {
1889
+ var t;
1890
+ (t = this.scrollCleanup) == null || t.call(this), this.scrollCleanup = e;
1891
+ }
1892
+ /** Load seenSeq from localStorage (keyed by userId+profileId). */
1893
+ initSeenSeq(e) {
1894
+ this.seenSeqKey = e;
1895
+ try {
1896
+ const t = localStorage.getItem(`ocw_seen_${e}`);
1897
+ if (t) {
1898
+ const n = JSON.parse(t);
1899
+ for (const [i, o] of Object.entries(n)) this.seenSeq.set(i, o);
1900
+ }
1901
+ } catch {
1902
+ }
1903
+ }
1904
+ setSeenSeq(e, t) {
1905
+ if (this.seenSeq.set(e, Math.max(this.seenSeq.get(e) ?? 0, t)), this.seenSeqKey)
1906
+ try {
1907
+ const n = {};
1908
+ for (const [i, o] of this.seenSeq) n[i] = o;
1909
+ localStorage.setItem(`ocw_seen_${this.seenSeqKey}`, JSON.stringify(n));
1910
+ } catch {
1911
+ }
1912
+ }
1913
+ /** Call when the widget is unmounted. Disconnects scroll listeners and
1914
+ * prevents in-flight fetches from writing to dead DOM. */
1915
+ destroy() {
1916
+ var e;
1917
+ this.destroyed = !0, (e = this.scrollCleanup) == null || e.call(this), this.scrollCleanup = null;
1918
+ }
1919
+ refreshList() {
1920
+ var e, t;
1921
+ !this.listBody || this.destroyed || (t = (e = this.h).onListChats) == null || t.call(e).then((n) => {
1922
+ var i;
1923
+ this.destroyed || (this.allEntries = n, this.renderListRows(n, ((i = this.listSearch) == null ? void 0 : i.value.trim().toLowerCase()) ?? ""));
1924
+ }).catch(() => {
1925
+ var n;
1926
+ this.destroyed || (n = this.listBody) == null || n.replaceChildren(c("div", "ocw-cl-section", "Could not load conversations."));
1927
+ });
1928
+ }
1929
+ /** Render list rows, optionally filtered by search query. */
1930
+ renderListRows(e, t) {
1931
+ if (!this.listBody) return;
1932
+ const n = t ? e.filter((r) => (r.subjectTitle ?? "General enquiry").toLowerCase().includes(t) || r.state.includes(t)) : e;
1933
+ if (!n.length) {
1934
+ this.listBody.replaceChildren(c("div", "ocw-cl-section", t ? "No results." : "No conversations yet."));
1935
+ return;
1936
+ }
1937
+ const i = n.filter((r) => this.isUnread(r)).sort((r, d) => d.updatedAt - r.updatedAt), o = n.filter((r) => !this.isUnread(r)).sort((r, d) => d.updatedAt - r.updatedAt);
1938
+ if (this.listBody.replaceChildren(), i.length) {
1939
+ this.listBody.append(c("div", "ocw-cl-section", `Unread (${i.length})`));
1940
+ for (const r of i) this.listBody.append(this.buildRow(r));
1941
+ }
1942
+ if (o.length) {
1943
+ this.listBody.append(c("div", "ocw-cl-section", i.length ? "Read" : "All conversations"));
1944
+ for (const r of o) this.listBody.append(this.buildRow(r));
1945
+ }
1946
+ }
1947
+ isUnread(e) {
1948
+ return e.id === this.activeChatId ? !1 : (e.lastSeq ?? 0) > (this.seenSeq.get(e.id) ?? 0);
1949
+ }
1950
+ /** Build a single WhatsApp-style conversation row. */
1951
+ buildRow(e) {
1952
+ var v;
1953
+ const t = this.seenSeq.get(e.id) ?? 0, n = e.lastSeq ?? 0, i = this.isUnread(e) ? Math.max(1, n - t) : 0, o = e.subjectTitle ?? "General enquiry", r = ((v = o[0]) == null ? void 0 : v.toUpperCase()) ?? "?", d = c("button", `ocw-cl-row${i > 0 ? " unread" : ""}`), u = c("div", "ocw-cl-av", r), w = c("div", "ocw-cl-status");
1954
+ e.state === "open" ? w.classList.add("open") : e.state === "awaiting_staff" && w.classList.add("waiting"), u.append(w), d.append(u);
1955
+ const y = c("div", "ocw-cl-body");
1956
+ y.append(c("div", "ocw-cl-name", o));
1957
+ const x = {
1958
+ open: "Conversation open",
1959
+ awaiting_staff: "Waiting for reply…",
1960
+ resolved: "Conversation resolved ✓",
1961
+ closed: "Conversation closed"
1962
+ }, p = e.lastMessage ?? x[e.state] ?? e.state;
1963
+ y.append(c("div", "ocw-cl-preview", p)), d.append(y);
1964
+ const h = c("div", "ocw-cl-right");
1965
+ return h.append(c("div", "ocw-cl-time", Bt(e.updatedAt))), i > 0 && h.append(c("div", "ocw-cl-badge", String(i > 99 ? "99+" : i))), d.append(h), d.addEventListener("click", () => {
1966
+ var k, b;
1967
+ n > 0 && this.seenSeq.set(e.id, n), this.activeChatId = e.id, this.showChatScreen(), (b = (k = this.h).onSwitchChat) == null || b.call(k, e);
1968
+ }), d;
1969
+ }
1970
+ /** Returns true when the chat screen is visible (not the list). */
1971
+ isInChatScreen() {
1972
+ return this.inChatScreen;
1973
+ }
1974
+ /** Navigate to the chat screen (slide list left, slide chat in from right). */
1975
+ showChatScreen() {
1976
+ var e, t, n;
1977
+ this.inChatScreen || (this.inChatScreen = !0, (e = this.listScreen) == null || e.classList.add("hidden"), (t = this.chatScreen) == null || t.classList.add("visible"), (n = this.backBtn) == null || n.classList.add("show"));
1978
+ }
1979
+ /** Navigate back to the list screen. */
1980
+ showListScreen() {
1981
+ var e, t, n;
1982
+ this.inChatScreen && (this.inChatScreen = !1, (e = this.listScreen) == null || e.classList.remove("hidden"), (t = this.chatScreen) == null || t.classList.remove("visible"), (n = this.backBtn) == null || n.classList.remove("show"), this.refreshList());
1983
+ }
1984
+ flushSend() {
1985
+ const e = this.input.value.trim();
1986
+ e && (this.input.value = "", this.h.onTyping(!1), this.h.onSend(e));
1987
+ }
1988
+ signalTyping() {
1989
+ this.h.onTyping(!0), this.typingTimer && clearTimeout(this.typingTimer), this.typingTimer = setTimeout(() => this.h.onTyping(!1), 2e3);
1990
+ }
1991
+ render(e) {
1992
+ var w, y, x;
1993
+ 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) {
1994
+ const p = (w = this.cfg.subject) == null ? void 0 : w.ownerLabel;
1995
+ p && (this.headerName.textContent = p);
1996
+ }
1997
+ this.chips.replaceChildren();
1998
+ const t = e.visibleActions();
1999
+ this.chips.style.display = t.length ? "flex" : "none";
2000
+ for (const p of t) this.chips.append(this.chipEl(p));
2001
+ const n = this.scroll.scrollHeight, i = this.scroll.scrollTop;
2002
+ if (this.scroll.replaceChildren(), this.subjectCard.childNodes.length && this.scroll.append(this.subjectCard), e.hasMoreHistory) {
2003
+ const p = c("div", "ocw-load-more");
2004
+ p.textContent = "↑ Loading earlier messages…", p.style.pointerEvents = "none", this.scroll.append(p);
2005
+ }
2006
+ let o = 0;
2007
+ for (const p of e.messages())
2008
+ this.scroll.append(this.messageEl(p, e)), p.senderId !== this.me && p.seq > o && (o = p.seq);
2009
+ i > 20 ? this.scroll.scrollTop = this.scroll.scrollHeight - n + i : this.scroll.scrollTop = this.scroll.scrollHeight, o > 0 && this.h.onReadUpTo(o);
2010
+ const r = [...e.typing];
2011
+ this.typing.classList.toggle("active", r.length > 0);
2012
+ const d = this.typing.querySelector(".ocw-typing-bubble");
2013
+ d && d.setAttribute("aria-label", r.length ? "typing" : ""), this.footer.style.display = e.whiteLabel ? "none" : "block", e.offline ? (this.offlinePanel.style.display === "none" && this.buildOfflinePanel(e.offlineMessage), this.offlinePanel.style.display = "block", (y = this.root.querySelector(".ocw-input")) == null || y.style.setProperty("display", "none")) : (this.offlinePanel.style.display = "none", (x = this.root.querySelector(".ocw-input")) == null || x.style.removeProperty("display"));
2014
+ const u = ["resolved", "closed", "sold", "issued", "checked_out"];
2015
+ this.h.onCsat && !this.csatSubmitted && u.includes(e.state) && e.messages().length > 0 && (this.csatPanel.style.display === "none" && this.buildCsatPanel(), this.csatPanel.style.display = "block");
2016
+ }
2017
+ setConnStatus(e) {
2018
+ if (e === "open") {
2019
+ this.connStatus.style.display = "none";
2020
+ return;
2021
+ }
2022
+ this.connStatus.style.display = "", this.connStatus.className = `ocw-conn-status${e === "reconnecting" ? " warn" : ""}`, this.connStatus.textContent = e === "reconnecting" ? "↻ reconnecting…" : "● connecting…";
2023
+ }
2024
+ buildOfflinePanel(e) {
2025
+ var d;
2026
+ this.offlinePanel.replaceChildren(), this.offlinePanel.append(c("div", "ocw-offline-icon", "🌙")), this.offlinePanel.append(c("div", "ocw-offline-title", ((d = this.cfg.i18n) == null ? void 0 : d.offline) ?? "We're offline right now")), this.offlinePanel.append(c("div", "ocw-offline-msg", e || "Leave your details and we'll get back to you soon."));
2027
+ const t = c("div", "ocw-offline-form"), n = c("input", "ocw-offline-input");
2028
+ n.placeholder = "Your name", n.type = "text";
2029
+ const i = c("input", "ocw-offline-input");
2030
+ i.placeholder = "Your email", i.type = "email";
2031
+ const o = c("textarea", "ocw-offline-input");
2032
+ o.placeholder = "Your message", o.rows = 3;
2033
+ const r = c("button", "ocw-offline-submit", "Send message");
2034
+ r.addEventListener("click", () => {
2035
+ !i.value.trim() || !o.value.trim() || (this.h.onSend(`[Offline form]
2036
+ Name: ${n.value || "Anonymous"}
2037
+ Email: ${i.value}
2038
+ Message: ${o.value}`), this.offlinePanel.replaceChildren(c("div", "ocw-offline-thanks", "✓ Message sent! We'll reply to your email.")));
2039
+ }), t.append(n, i, o, r), this.offlinePanel.append(t);
2040
+ }
2041
+ buildCsatPanel() {
2042
+ this.csatPanel.replaceChildren(), this.csatPanel.append(c("div", "ocw-csat-title", "How did we do?"));
2043
+ const e = c("div", "ocw-csat-stars"), t = [];
2044
+ for (let n = 1; n <= 5; n++) {
2045
+ const i = c("button", "ocw-csat-star", "★");
2046
+ i.dataset.score = String(n), i.addEventListener("mouseenter", () => t.forEach((o, r) => o.classList.toggle("lit", r < n))), i.addEventListener("mouseleave", () => t.forEach((o) => o.classList.remove("lit"))), i.addEventListener("click", () => {
2047
+ var o, r;
2048
+ this.csatSubmitted = !0, this.csatPanel.replaceChildren(c("div", "ocw-csat-done", `Thanks for your ${n}★ rating!`)), (r = (o = this.h).onCsat) == null || r.call(o, n);
2049
+ }), t.push(i), e.append(i);
2050
+ }
2051
+ this.csatPanel.append(e);
2052
+ }
2053
+ /** Subject card from the server's Subject entity (per chatroom), with the
2054
+ * mount config as a fallback. Built once when data first arrives. */
2055
+ // ── Co-browsing (shared whiteboard) ──────────────────────────────────────
2056
+ updateCobrowseUI() {
2057
+ 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());
2058
+ }
2059
+ resizeCobrowseCanvas() {
2060
+ this.cobrowseCanvas.width = this.root.clientWidth || 1, this.cobrowseCanvas.height = this.root.clientHeight || 1;
2061
+ }
2062
+ /** Draw a stroke whose points are normalized to 0..1, scaled to the current
2063
+ * canvas size — so strokes line up across different viewport sizes. */
2064
+ drawStroke(e) {
2065
+ const t = this.cobrowseCanvas.getContext("2d");
2066
+ if (!t || e.points.length < 2) return;
2067
+ const n = this.cobrowseCanvas.width, i = this.cobrowseCanvas.height;
2068
+ t.strokeStyle = e.color, t.lineWidth = Math.max(1, e.width * Math.min(n, i)), t.lineJoin = "round", t.lineCap = "round", t.beginPath(), t.moveTo(e.points[0].x * n, e.points[0].y * i);
2069
+ for (const o of e.points.slice(1)) t.lineTo(o.x * n, o.y * i);
2070
+ t.stroke();
2071
+ }
2072
+ redrawCobrowse() {
2073
+ var t;
2074
+ const e = this.cobrowseCanvas.getContext("2d");
2075
+ if (e) {
2076
+ e.clearRect(0, 0, this.cobrowseCanvas.width, this.cobrowseCanvas.height);
2077
+ for (const n of ((t = this.storeRef) == null ? void 0 : t.annotations) ?? []) this.drawStroke(n);
2078
+ }
2079
+ }
2080
+ bindCobrowsePointerEvents() {
2081
+ let e = !1, t = [];
2082
+ const n = (r) => {
2083
+ const d = this.cobrowseCanvas.getBoundingClientRect(), u = d.width > 0 ? (r.clientX - d.left) / d.width : 0, w = d.height > 0 ? (r.clientY - d.top) / d.height : 0;
2084
+ return { x: Math.min(1, Math.max(0, u)), y: Math.min(1, Math.max(0, w)) };
2085
+ }, i = 6e-3;
2086
+ this.cobrowseCanvas.addEventListener("pointerdown", (r) => {
2087
+ this.cobrowseActive && (e = !0, t = [n(r)], this.cobrowseCanvas.setPointerCapture(r.pointerId));
2088
+ }), this.cobrowseCanvas.addEventListener("pointermove", (r) => {
2089
+ e && (t.push(n(r)), this.redrawCobrowse(), this.drawStroke({ points: t, color: this.cobrowseColor, width: i }));
2090
+ });
2091
+ const o = (r) => {
2092
+ var d, u;
2093
+ if (e) {
2094
+ e = !1, t.length > 1 && ((u = (d = this.h).onAnnotate) == null || u.call(d, { id: `an_${Date.now()}_${Math.random().toString(36).slice(2)}`, points: t, color: this.cobrowseColor, width: i })), t = [];
2095
+ try {
2096
+ this.cobrowseCanvas.releasePointerCapture(r.pointerId);
2097
+ } catch {
2098
+ }
2099
+ }
2100
+ };
2101
+ this.cobrowseCanvas.addEventListener("pointerup", o), this.cobrowseCanvas.addEventListener("pointercancel", o);
2102
+ }
2103
+ buildSubjectCard(e) {
2104
+ if (this.subjectBuilt) return;
2105
+ const t = e.subject, n = this.cfg.subject, i = (t == null ? void 0 : t.title) ?? (n == null ? void 0 : n.title);
2106
+ if (!i) return;
2107
+ this.subjectBuilt = !0, this.subjectCard.replaceChildren(), this.subjectCard.append(c("div", "ocw-subject-title", i)), n != null && n.subtitle && this.subjectCard.append(c("div", "ocw-subject-sub", n.subtitle));
2108
+ const o = c("div", "ocw-tags");
2109
+ if (t) for (const [d, u] of Object.entries(t.fields)) o.append(c("span", "ocw-tag", `${d}: ${u}`));
2110
+ else for (const d of (n == null ? void 0 : n.tags) ?? []) o.append(c("span", "ocw-tag", d));
2111
+ o.childNodes.length && this.subjectCard.append(o);
2112
+ const r = (t == null ? void 0 : t.state) ?? (n == null ? void 0 : n.status);
2113
+ r && (this.statusBadge.textContent = r, this.statusBadge.style.display = "inline-flex");
2114
+ }
2115
+ chipEl(e) {
2116
+ const t = c("button", "ocw-chip", e.icon ? `${e.icon} ${e.label}` : e.label);
2117
+ return t.dataset.actionId = e.id, t.addEventListener("click", async () => {
2118
+ var n;
2119
+ e.confirm && !await this.confirm(e.label) || ((n = e.input) != null && n.length ? this.openForm(e) : this.h.onInvoke(e.id));
2120
+ }), t;
2121
+ }
2122
+ /** In-widget confirmation modal (replaces window.confirm). */
2123
+ confirm(e) {
2124
+ return new Promise((t) => {
2125
+ const n = c("div", "ocw-modal"), i = c("div", "ocw-modal-card");
2126
+ i.append(c("div", "ocw-modal-title", e)), i.append(c("div", "ocw-modal-body", `Confirm “${e}”?`));
2127
+ const o = c("div", "ocw-modal-actions"), r = c("button", "ocw-modal-cancel", "Cancel"), d = c("button", "ocw-modal-ok", "Confirm"), u = (w) => {
2128
+ n.remove(), t(w);
2129
+ };
2130
+ r.addEventListener("click", () => u(!1)), d.addEventListener("click", () => u(!0)), n.addEventListener("click", (w) => {
2131
+ w.target === n && u(!1);
2132
+ }), o.append(r, d), i.append(o), n.append(i), this.root.append(n), d.focus();
2133
+ });
2134
+ }
2135
+ /** Inline form for a form-effect action: typed inputs (date picker, number,
2136
+ * text) rendered above the composer — no browser prompts. */
2137
+ openForm(e) {
2138
+ var d, u;
2139
+ this.formHost.replaceChildren();
2140
+ const t = c("div", "ocw-form");
2141
+ t.append(c("div", "ocw-form-title", e.icon ? `${e.icon} ${e.label}` : e.label));
2142
+ const n = /* @__PURE__ */ new Map();
2143
+ for (const w of e.input ?? []) {
2144
+ const y = c("label", "ocw-form-row");
2145
+ if (y.append(c("span", "ocw-form-lbl", w.label)), w.type === "select" && ((d = w.options) != null && d.length)) {
2146
+ const x = c("select", "ocw-form-input");
2147
+ w.required || x.append(c("option", void 0, "— select —"));
2148
+ for (const p of w.options) {
2149
+ const h = c("option");
2150
+ h.value = p, h.textContent = p, x.append(h);
2151
+ }
2152
+ w.required && (x.required = !0), y.append(x), n.set(w.name, x);
2153
+ } else {
2154
+ const x = c("input", "ocw-form-input");
2155
+ x.type = w.type === "number" ? "number" : w.type === "date" ? "datetime-local" : "text", w.required && (x.required = !0), y.append(x), n.set(w.name, x);
2156
+ }
2157
+ t.append(y);
2158
+ }
2159
+ const i = c("div", "ocw-form-actions"), o = c("button", "ocw-form-cancel", "Cancel"), r = c("button", "ocw-form-submit", "Send");
2160
+ o.addEventListener("click", () => this.formHost.replaceChildren()), r.addEventListener("click", () => {
2161
+ const w = {};
2162
+ for (const [y, x] of n) {
2163
+ if (x.required && !x.value) {
2164
+ x.style.borderColor = "#e5484d";
2165
+ return;
2166
+ }
2167
+ w[y] = x.type === "number" ? Number(x.value) : x.value;
2168
+ }
2169
+ this.formHost.replaceChildren(), this.h.onInvoke(e.id, w);
2170
+ }), i.append(o, r), t.append(i), this.formHost.append(t), (u = n.values().next().value) == null || u.focus();
2171
+ }
2172
+ messageEl(e, t) {
2173
+ var x;
2174
+ if (e.senderRole === "system") {
2175
+ const p = c("div", "ocw-sys");
2176
+ return p.textContent = e.deletedAt ? "message deleted" : Q(e.content), p;
2177
+ }
2178
+ const n = e.senderId === this.me, i = !!e.internal, o = c("div", `ocw-row ${i ? "ocw-note mine" : n ? "mine" : "theirs"} ${e.senderRole === "bot" ? "ocw-bot" : ""}`);
2179
+ !n && !i && o.append(c("div", "ocw-dot", e.senderRole === "bot" ? "🤖" : "🧑"));
2180
+ const r = c("div"), d = c("div", "ocw-bubble-wrap");
2181
+ if (e.replyToId) {
2182
+ const p = c("div", "ocw-reply-to", "↩ replying to a message");
2183
+ p.style.cssText = "font-size:11px;color:var(--ocw-mut);margin-bottom:2px;font-style:italic", r.append(p);
2184
+ }
2185
+ const u = c("div", "ocw-bubble");
2186
+ let w = null;
2187
+ if (e.deletedAt) u.append(c("span", "ocw-deleted", "message deleted"));
2188
+ else if (e.content.kind === "attachment") {
2189
+ const p = e.content;
2190
+ if ((x = p.mime) != null && x.startsWith("image/")) {
2191
+ const h = document.createElement("img");
2192
+ h.src = p.url, h.alt = p.name ?? "image", h.style.cssText = "max-width:220px;max-height:160px;border-radius:10px;display:block;cursor:pointer", h.addEventListener("click", () => window.open(p.url, "_blank")), u.append(h);
2193
+ } else {
2194
+ const h = document.createElement("a");
2195
+ h.href = p.url, h.target = "_blank", h.rel = "noopener", h.style.cssText = "display:flex;align-items:center;gap:8px;color:inherit;text-decoration:none", h.append(c("span", void 0, "📄"), c("span", void 0, p.name ?? "file")), u.append(h);
2196
+ }
2197
+ } else if (e.content.kind === "appointment") {
2198
+ const p = e.content, h = c("div", "ocw-appt");
2199
+ h.append(c("div", "ocw-appt-title", `📅 ${p.title}`)), h.append(c("div", "ocw-appt-time", new Date(p.startIso).toLocaleString() + " – " + new Date(p.endIso).toLocaleTimeString())), p.location && h.append(c("div", "ocw-appt-loc", `📍 ${p.location}`)), p.description && h.append(c("div", "ocw-appt-desc", p.description));
2200
+ const v = c("div", "ocw-appt-links"), k = document.createElement("a");
2201
+ k.href = p.googleUrl, k.target = "_blank", k.rel = "noopener", k.className = "ocw-appt-btn", k.textContent = "📅 Add to Google Calendar";
2202
+ const b = document.createElement("a");
2203
+ b.href = p.icalUrl, b.download = `${p.title}.ics`, b.className = "ocw-appt-btn ocw-appt-btn-sec", b.textContent = "🍎 Apple / iCal", v.append(k, b), h.append(v), u.append(h);
2204
+ } else
2205
+ w = document.createTextNode(Q(e.content)), u.append(w), e.editedAt && u.append(c("span", "ocw-edited", "(edited)"));
2206
+ if (d.append(u), !n && !i && this.h.onTranslate && e.content.kind === "text" && !e.deletedAt && e.seq > 0 && w) {
2207
+ const p = e.content.text;
2208
+ if (p.trim()) {
2209
+ const h = c("button", "ocw-translate-btn", "🌐");
2210
+ h.type = "button", h.title = "Translate", h.addEventListener("click", (v) => {
2211
+ if (v.stopPropagation(), this.showingTranslation.has(e.id)) {
2212
+ this.showingTranslation.delete(e.id), w.textContent = p, h.textContent = "🌐", h.title = "Translate";
2213
+ return;
2214
+ }
2215
+ const k = this.translationCache.get(e.id);
2216
+ if (k !== void 0) {
2217
+ this.showingTranslation.add(e.id), w.textContent = k, h.textContent = "↩", h.title = "Show original";
2218
+ return;
2219
+ }
2220
+ h.textContent = "⏳", this.h.onTranslate(p).then((b) => {
2221
+ if (b === null) {
2222
+ h.textContent = "⚠️", h.title = "Translation unavailable", setTimeout(() => {
2223
+ h.textContent = "🌐", h.title = "Translate";
2224
+ }, 1500);
2225
+ return;
2226
+ }
2227
+ this.translationCache.set(e.id, b), this.showingTranslation.add(e.id), w.textContent = b, h.textContent = "↩", h.title = "Show original";
2228
+ });
2229
+ }), d.append(h);
2230
+ }
2231
+ }
2232
+ if (n && !e.deletedAt && e.seq > 0 && (this.h.onEdit ?? this.h.onDelete)) {
2233
+ const p = c("div", "ocw-msg-menu");
2234
+ if (this.h.onEdit) {
2235
+ const h = c("button", void 0, "✏️");
2236
+ h.title = "Edit", h.addEventListener("click", (v) => {
2237
+ v.stopPropagation();
2238
+ const k = Q(e.content), b = prompt("Edit message:", k);
2239
+ b !== null && b.trim() && b !== k && this.h.onEdit(e.id, b.trim());
2240
+ }), p.append(h);
2241
+ }
2242
+ if (this.h.onDelete) {
2243
+ const h = c("button", "del", "🗑");
2244
+ h.title = "Delete", h.addEventListener("click", (v) => {
2245
+ v.stopPropagation(), this.h.onDelete(e.id);
2246
+ }), p.append(h);
2247
+ }
2248
+ d.append(p);
2249
+ }
2250
+ if (r.append(d), this.h.onReact && !e.deletedAt && e.seq > 0) {
2251
+ const p = c("div", "ocw-react-wrap"), h = c("div", "ocw-react");
2252
+ if (e.reactions && Object.keys(e.reactions).length)
2253
+ for (const [b, E] of Object.entries(e.reactions)) {
2254
+ const B = c("button", `ocw-react-pill${E.includes(this.me) ? " mine" : ""}`, `${b} ${E.length}`);
2255
+ B.addEventListener("click", () => {
2256
+ var T, A;
2257
+ return (A = (T = this.h).onReact) == null ? void 0 : A.call(T, e.id, b, E.includes(this.me));
2258
+ }), h.append(B);
2259
+ }
2260
+ const v = c("button", "ocw-react-btn", "+"), k = c("div", "ocw-react-picker");
2261
+ for (const b of It) {
2262
+ const E = c("button", void 0, b);
2263
+ E.addEventListener("click", (B) => {
2264
+ var A, $, _, D;
2265
+ B.stopPropagation();
2266
+ const T = ($ = (A = e.reactions) == null ? void 0 : A[b]) == null ? void 0 : $.includes(this.me);
2267
+ (D = (_ = this.h).onReact) == null || D.call(_, e.id, b, !!T), k.style.display = "none";
2268
+ }), k.append(E);
2269
+ }
2270
+ k.style.display = "none", v.addEventListener("click", (b) => {
2271
+ b.stopPropagation(), k.style.display = k.style.display === "none" ? "flex" : "none";
2272
+ }), document.addEventListener("click", () => {
2273
+ k.style.display = "none";
2274
+ }, { once: !0 }), h.append(v), p.append(h, k), r.append(p);
2275
+ } else e.reactions && Object.keys(e.reactions).length && r.append(c("div", "ocw-react", Object.entries(e.reactions).map(([p, h]) => `${p}${h.length}`).join(" ")));
2276
+ const y = c("div", "ocw-time ocw-meta", Tt(e.ts));
2277
+ if (n && e.status) {
2278
+ const p = c("span", `ocw-tick${e.status === "read" ? " read" : e.status === "delivered" ? " delivered" : ""}`, Pt(e.status));
2279
+ y.append(p);
2280
+ }
2281
+ return n && e.seq > 0 && t.lastReadByOthers >= e.seq && y.append(c("span", "ocw-seen", " · Seen")), r.append(y), o.append(r), o;
2282
+ }
2283
+ }
2284
+ function Pt(s) {
2285
+ switch (s) {
2286
+ case "read":
2287
+ return "✓✓";
2288
+ case "delivered":
2289
+ return "✓✓";
2290
+ case "sent":
2291
+ return "✓";
2292
+ default:
2293
+ return "🕓";
2294
+ }
2295
+ }
2296
+ const Kt = 20;
2297
+ function ye(s) {
2298
+ return s.replace(/^ws/, "http").replace(/\/ws\/?$/, "");
2299
+ }
2300
+ function Lt(s, e, t, n) {
2301
+ const i = `beforeSeq=${t}&limit=${n}`;
2302
+ return [
2303
+ `${s}/conversations/${e}/messages?${i}`,
2304
+ `${s}/conversations/${e}/history?${i}`
2305
+ ];
2306
+ }
2307
+ async function he(s, e, t, n, i = Kt) {
2308
+ for (const o of Lt(s, e, n, i))
2309
+ try {
2310
+ const r = await fetch(o, { headers: { authorization: `Bearer ${t}` } });
2311
+ if (!r.ok) continue;
2312
+ const d = await r.json();
2313
+ return { messages: d.messages ?? [], hasMore: d.hasMore ?? !1 };
2314
+ } catch {
2315
+ }
2316
+ return null;
2317
+ }
2318
+ async function zt(s, e, t, n, i) {
2319
+ const o = ye(s), r = await he(o, t, e, Number.MAX_SAFE_INTEGER);
2320
+ if (!r || (r.messages.length ? (n.apply({ type: "sync", conversationId: t, messages: r.messages }), n.apply({ type: "history", conversationId: t, messages: [], hasMore: r.hasMore }), i.render(n)) : n.apply({ type: "history", conversationId: t, messages: [], hasMore: !1 }), !r.hasMore)) return;
2321
+ let d = !1;
2322
+ const u = async () => {
2323
+ if (d || !n.hasMoreHistory) return;
2324
+ d = !0;
2325
+ const p = n.messages()[0];
2326
+ if (!p) {
2327
+ d = !1;
2328
+ return;
2329
+ }
2330
+ const h = await he(o, t, e, p.seq);
2331
+ h && (n.apply({ type: "history", conversationId: t, messages: h.messages, hasMore: h.hasMore }), i.render(n)), d = !1;
2332
+ }, w = i.getScrollEl();
2333
+ if (!w) return;
2334
+ let y = !1;
2335
+ setTimeout(() => {
2336
+ y = !0;
2337
+ }, 300);
2338
+ const x = () => {
2339
+ y && w.scrollTop < 80 && n.hasMoreHistory && !d && u();
2340
+ };
2341
+ w.addEventListener("scroll", x, { passive: !0 }), i.setScrollCleanup(() => w.removeEventListener("scroll", x));
2342
+ }
2343
+ function Mt() {
2344
+ const s = "oc_uid";
2345
+ try {
2346
+ const e = localStorage.getItem(s);
2347
+ if (e) return e;
2348
+ const t = `g_${Math.random().toString(36).slice(2)}${Date.now().toString(36)}`;
2349
+ return localStorage.setItem(s, t), t;
2350
+ } catch {
2351
+ return `g_${Math.random().toString(36).slice(2)}`;
2352
+ }
2353
+ }
2354
+ function $t(s) {
2355
+ var P, R;
2356
+ const e = s.token ?? Mt(), t = new dt(e), n = new ft(e);
2357
+ let i, o = !1, r = null;
2358
+ !s.launcher && !s.el.style.height && s.el.clientHeight === 0 && (s.el.style.width = s.el.style.width || "100%", s.el.style.height = "600px");
2359
+ for (const l of n.load()) t.addOptimistic(l.clientMsgId, l.content);
2360
+ let d = null, u = null, w = 0, y = !s.launcher;
2361
+ if (s.launcher) {
2362
+ const f = (s.position ?? "bottom-right").includes("right");
2363
+ d = document.createElement("div"), d.style.cssText = `position:fixed;${f ? "right:20px" : "left:20px"};bottom:20px;z-index:9999;display:flex;flex-direction:column;align-items:${f ? "flex-end" : "flex-start"};gap:12px`;
2364
+ const g = document.createElement("div");
2365
+ g.style.cssText = [
2366
+ "width:380px",
2367
+ "height:600px",
2368
+ "border-radius:16px",
2369
+ "overflow:hidden",
2370
+ "box-shadow:0 8px 40px rgba(0,0,0,.18)",
2371
+ "display:none",
2372
+ // hidden until bubble clicked
2373
+ "flex-direction:column",
2374
+ "background:#fff",
2375
+ "transform-origin:bottom " + (f ? "right" : "left"),
2376
+ "transition:opacity .18s,transform .18s",
2377
+ "opacity:0",
2378
+ "transform:scale(.95)"
2379
+ ].join(";"), s.el.style.cssText = "width:100%;height:100%;overflow:hidden", g.append(s.el);
2380
+ const C = document.createElement("button");
2381
+ C.style.cssText = [
2382
+ "width:56px;height:56px;border-radius:50%",
2383
+ `background:${s.accent ?? "#4F63F5"}`,
2384
+ "color:#fff;border:none;font-size:24px;cursor:pointer",
2385
+ "box-shadow:0 4px 16px rgba(0,0,0,.25)",
2386
+ "position:relative;flex:none",
2387
+ "transition:transform .15s"
2388
+ ].join(";"), C.textContent = "💬", C.onmouseenter = () => {
2389
+ C.style.transform = "scale(1.08)";
2390
+ }, C.onmouseleave = () => {
2391
+ C.style.transform = "scale(1)";
2392
+ }, u = document.createElement("span"), u.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", C.append(u), d.append(g, C), document.body.append(d);
2393
+ const L = (K) => {
2394
+ K ? (g.style.display = "flex", requestAnimationFrame(() => {
2395
+ g.style.opacity = "1", g.style.transform = "scale(1)";
2396
+ })) : (g.style.opacity = "0", g.style.transform = "scale(.95)", setTimeout(() => {
2397
+ y || (g.style.display = "none");
2398
+ }, 180));
2399
+ };
2400
+ C.addEventListener("click", () => {
2401
+ y = !y, L(y), C.textContent = y ? "✕" : "💬", C.append(u), y && (w = 0, u && (u.style.display = "none"));
2402
+ }), document.addEventListener("keydown", (K) => {
2403
+ K.key === "Escape" && y && (y = !1, L(!1), C.textContent = "💬", C.append(u));
2404
+ });
2405
+ }
2406
+ const x = () => {
2407
+ y || (w++, u && (u.textContent = String(w), u.style.display = "flex"));
2408
+ }, p = () => {
2409
+ try {
2410
+ const l = new AudioContext(), f = l.createOscillator(), g = l.createGain();
2411
+ f.connect(g), g.connect(l.destination), f.frequency.setValueAtTime(880, l.currentTime), f.frequency.exponentialRampToValueAtTime(440, l.currentTime + 0.15), g.gain.setValueAtTime(0.3, l.currentTime), g.gain.exponentialRampToValueAtTime(1e-3, l.currentTime + 0.3), f.start(), f.stop(l.currentTime + 0.3);
2412
+ } catch {
2413
+ }
2414
+ };
2415
+ let h;
2416
+ const v = new St(`ocw-e2e-${s.profileId}`);
2417
+ let k = !1;
2418
+ const b = [], E = [];
2419
+ let B = !1;
2420
+ const T = (l, f) => {
2421
+ v.sealText(f).then((g) => {
2422
+ i && h.send({ type: "send", conversationId: i, clientMsgId: l, content: g });
2423
+ });
2424
+ }, A = (l, f, g) => {
2425
+ v.sealText(f, g).then((C) => {
2426
+ i && h.send({ type: "send", conversationId: i, clientMsgId: l, content: C });
2427
+ });
2428
+ }, $ = () => {
2429
+ for (; b.length; ) {
2430
+ const l = b.shift();
2431
+ T(l.clientMsgId, l.text);
2432
+ }
2433
+ for (; E.length; ) {
2434
+ const l = E.shift();
2435
+ T(l.clientMsgId, l.text);
2436
+ }
2437
+ }, _ = (l) => {
2438
+ h.send({ type: "fetchPrekey", targetUserId: l });
2439
+ }, D = s.i18n ?? {}, W = ["ar", "he", "fa", "ur"], S = typeof navigator < "u" ? (navigator.language ?? "").slice(0, 2).toLowerCase() : "";
2440
+ W.includes(S) && !s.el.dir && (s.el.dir = "rtl", s.el.style.fontFamily = s.el.style.fontFamily || "Tahoma,Arial,system-ui,sans-serif");
2441
+ const m = new At(s.el, e, {
2442
+ onSend(l) {
2443
+ if (!i) return;
2444
+ const f = `cm_${Math.random().toString(36).slice(2)}`;
2445
+ t.addOptimistic(f, { kind: "text", text: l }), m.render(t), t.e2e ? v.ready ? T(f, l) : B ? E.push({ clientMsgId: f, text: l }) : (b.push({ clientMsgId: f, text: l }), t.assignedAgentId && _(t.assignedAgentId)) : (n.add({ clientMsgId: f, content: { kind: "text", text: l }, ts: Date.now() }), h.send({ type: "send", conversationId: i, clientMsgId: f, content: { kind: "text", text: l } }));
2446
+ },
2447
+ async onAttach(l) {
2448
+ if (!i) return;
2449
+ const C = `${s.url.replace(/^ws/, "http").replace(/\/ws$/, "")}/upload?name=${encodeURIComponent(l.name)}`, L = `cm_${Math.random().toString(36).slice(2)}`;
2450
+ t.addOptimistic(L, { kind: "text", text: `📎 Uploading ${l.name}…` }), m.render(t);
2451
+ try {
2452
+ const K = await fetch(C, {
2453
+ method: "POST",
2454
+ headers: { "content-type": l.type, ...s.token ? { authorization: `Bearer ${s.token}` } : {} },
2455
+ body: l
2456
+ });
2457
+ if (!K.ok) throw new Error(`Upload failed: ${K.status}`);
2458
+ const { url: be, name: me, mime: ve, size: ke } = await K.json();
2459
+ h.send({ type: "send", conversationId: i, clientMsgId: L, content: { kind: "attachment", url: be, name: me, mime: ve, size: ke } });
2460
+ } catch (K) {
2461
+ t.addOptimistic(L, { kind: "text", text: `⚠️ Upload failed: ${K.message}` }), m.render(t);
2462
+ }
2463
+ },
2464
+ onInvoke(l, f) {
2465
+ i && h.send({ type: "invoke", conversationId: i, actionId: l, clientInvokeId: `iv_${Math.random().toString(36).slice(2)}`, ...f ? { inputs: f } : {} });
2466
+ },
2467
+ onTyping(l) {
2468
+ i && h.send({ type: "typing", conversationId: i, isTyping: l });
2469
+ },
2470
+ onReadUpTo(l) {
2471
+ i && h.send({ type: "read", conversationId: i, seq: l });
2472
+ },
2473
+ onLoadMore() {
2474
+ if (!i || !t.e2e) return;
2475
+ const l = t.messages()[0];
2476
+ l && h.send({ type: "history", conversationId: i, beforeSeq: l.seq, limit: 20 });
2477
+ },
2478
+ onEdit(l, f) {
2479
+ i && h.send({ type: "edit", conversationId: i, messageId: l, content: { kind: "text", text: f } });
2480
+ },
2481
+ onDelete(l) {
2482
+ i && h.send({ type: "delete", conversationId: i, messageId: l });
2483
+ },
2484
+ onReact(l, f, g) {
2485
+ i && h.send({ type: "react", conversationId: i, messageId: l, emoji: f, remove: g });
2486
+ },
2487
+ onCsat(l) {
2488
+ if (!i) return;
2489
+ const f = s.url.replace(/^ws/, "http").replace(/\/+$/, "").replace(/:\d+$/, (g) => g);
2490
+ fetch(`${f}/conversations/${i}/csat`, {
2491
+ method: "POST",
2492
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${e}` },
2493
+ body: JSON.stringify({ score: l })
2494
+ }).catch(() => {
2495
+ });
2496
+ },
2497
+ onAnnotate(l) {
2498
+ i && h.send({ type: "annotate", conversationId: i, stroke: l });
2499
+ },
2500
+ onAnnotateClear() {
2501
+ i && h.send({ type: "annotate_clear", conversationId: i });
2502
+ },
2503
+ ...s.translateLang ? {
2504
+ async onTranslate(l) {
2505
+ const f = s.url.replace(/^ws/, "http").replace(/\/+$/, "");
2506
+ try {
2507
+ const g = await fetch(`${f}/translate`, {
2508
+ method: "POST",
2509
+ headers: { "content-type": "application/json", authorization: `Bearer ${e}` },
2510
+ body: JSON.stringify({ text: l, targetLang: s.translateLang })
2511
+ });
2512
+ if (!g.ok) return null;
2513
+ const { translated: C } = await g.json();
2514
+ return C;
2515
+ } catch {
2516
+ return null;
2517
+ }
2518
+ }
2519
+ } : {},
2520
+ ...s.showChatList ? {
2521
+ async onListChats() {
2522
+ const l = ye(s.url);
2523
+ try {
2524
+ const f = await fetch(`${l}/conversations/mine?profileId=${encodeURIComponent(s.profileId)}`, {
2525
+ headers: { authorization: `Bearer ${e}` }
2526
+ });
2527
+ return f.ok ? (await f.json()).conversations ?? [] : [];
2528
+ } catch {
2529
+ return [];
2530
+ }
2531
+ },
2532
+ onSwitchChat(l) {
2533
+ if (!l.id || l.id === "__new__") return;
2534
+ r == null || r.close(), s.el.replaceChildren();
2535
+ const { subjectId: f, token: g, ...C } = s;
2536
+ r = $t({
2537
+ ...C,
2538
+ token: e,
2539
+ // always the resolved identity, never undefined
2540
+ ...l.subjectId ? { subjectId: l.subjectId } : {},
2541
+ showChatList: !0
2542
+ });
2543
+ }
2544
+ } : {}
2545
+ }, {
2546
+ ...s.subject ? { subject: s.subject } : {},
2547
+ ...s.quickReplies ? { quickReplies: s.quickReplies } : {},
2548
+ ...s.accent ? { accent: s.accent } : {},
2549
+ ...(P = s.user) != null && P.name || (R = s.user) != null && R.avatar ? { userInfo: { ...s.user.name ? { name: s.user.name } : {}, ...s.user.avatar ? { avatar: s.user.avatar } : {} } } : {},
2550
+ i18n: D,
2551
+ // Start directly on chat screen when a specific conversation is known upfront
2552
+ ...s.showChatList && s.subjectId ? { startOnChat: !0 } : {}
2553
+ }), q = {
2554
+ type: "open",
2555
+ profileId: s.profileId,
2556
+ ...s.subjectId ? { subjectId: s.subjectId } : {},
2557
+ // Auto-capture the page context so agents know where the guest is browsing.
2558
+ // This is pure display metadata — it never affects identity or access.
2559
+ ...typeof location < "u" ? { pageUrl: location.href } : {},
2560
+ ...typeof document < "u" && document.title ? { pageTitle: document.title } : {}
2561
+ }, V = (l) => {
2562
+ const f = s.user;
2563
+ if (!f || !f.name && !f.email && !f.avatar && !f.meta) return;
2564
+ const g = [];
2565
+ if (f.name && g.push(`Name: ${f.name}`), f.email && g.push(`Email: ${f.email}`), f.avatar && g.push(`Avatar: ${f.avatar}`), f.meta) for (const [C, L] of Object.entries(f.meta)) g.push(`${C}: ${L}`);
2566
+ h.send({ type: "note", conversationId: l, clientMsgId: `ui_${Date.now()}`, text: `[User info]
2567
+ ${g.join(`
2568
+ `)}` });
2569
+ };
2570
+ return h = new lt({
2571
+ url: s.url,
2572
+ token: e,
2573
+ open: q,
2574
+ getCursor: () => t.highestSeq(),
2575
+ onStatusChange: (l) => m.setConnStatus(l),
2576
+ onFrame(l) {
2577
+ if (l.type === "opened") {
2578
+ const f = i === void 0;
2579
+ if (i = l.conversation.id, !o) {
2580
+ o = !0;
2581
+ for (const g of n.load())
2582
+ h.send({ type: "send", conversationId: i, clientMsgId: g.clientMsgId, content: g.content });
2583
+ }
2584
+ f && (zt(s.url, e, i, t, m), l.conversation.lastSeq === 0 && V(i), s.showChatList && s.subjectId && m.showChatScreen());
2585
+ }
2586
+ if (l.type === "ack" && n.remove(l.clientMsgId), l.type === "prekeyBundle") {
2587
+ l.bundle && (B = !0, v.x3dhSendTo(l.bundle).then((f) => {
2588
+ const g = [...b.splice(0), ...E.splice(0)];
2589
+ for (const C of g) A(C.clientMsgId, C.text, f);
2590
+ m.render(t);
2591
+ }));
2592
+ return;
2593
+ }
2594
+ if (l.type === "message" && t.e2e) {
2595
+ const f = Ct(l.message.content);
2596
+ if (f && !v.ready) {
2597
+ v.x3dhReceiveFrom(f.x3dhIK, f.x3dhEK, f.x3dhSPK).then(async () => {
2598
+ await v.openFrame(l), t.apply(l), m.render(t);
2599
+ });
2600
+ return;
2601
+ }
2602
+ }
2603
+ if (l.type === "peerkey") {
2604
+ v.onPeerKey(l.key).then(() => {
2605
+ $(), m.render(t);
2606
+ });
2607
+ return;
2608
+ }
2609
+ (async () => {
2610
+ if (t.e2e && await v.openFrame(l), t.apply(l), l.type === "message" && l.message.senderId !== e && !l.message.internal && (s.showChatList && m.isInChatScreen() || x(), p()), t.e2e && i && !k) {
2611
+ k = !0;
2612
+ const f = await v.initX3DH();
2613
+ h.send({ type: "uploadPrekeys", ...f });
2614
+ const g = await v.begin();
2615
+ h.send({ type: "pubkey", conversationId: i, key: g });
2616
+ }
2617
+ m.render(t), i && m.setSeenSeq(i, t.highestSeq());
2618
+ })();
2619
+ }
2620
+ }), s.showChatList && m.initSeenSeq(`${s.profileId}_${e.slice(-8)}`), s.showChatList && !s.subjectId ? (r = { close: () => {
2621
+ d == null || d.remove(), m.destroy();
2622
+ } }, r) : (h.connect(), m.render(t), r = { close: () => {
2623
+ h.close(), d == null || d.remove(), m.destroy();
2624
+ } }, r);
2625
+ }
2626
+ export {
2627
+ dt as ChatStore,
2628
+ lt as ConnectionManager,
2629
+ St as E2ESession,
2630
+ ft as PersistentOutbox,
2631
+ At as Renderer,
2632
+ Dt as asConversationId,
2633
+ Ct as extractX3DHInit,
2634
+ ye as httpBaseFromWsUrl,
2635
+ $t as mount,
2636
+ zt as restoreHistory
2637
+ };
2638
+ //# sourceMappingURL=index.js.map