@locdo.tech/botiq-chat-sdk 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sdk/index.js +1 -1
- package/dist/sdk/{npm-DbbHOVFV.js → npm-CjQcAuJy.js} +973 -291
- package/dist/sdk/react.js +1 -1
- package/dist/sdk/vue.js +1 -1
- package/package.json +2 -2
|
@@ -90,23 +90,24 @@ async function f(e, r) {
|
|
|
90
90
|
} catch {
|
|
91
91
|
return n;
|
|
92
92
|
}
|
|
93
|
-
let o = typeof a.name == "string" && a.name.length > 0 ? a.name : n.name, s = a.widgetLanguage === "en" ? "en" : "vi", c = Array.isArray(a.pageActions) ? a.pageActions : void 0, u = typeof a.contactInfo == "string" ? a.contactInfo : void 0, f = a.proactive && typeof a.proactive == "object" ? a.proactive : void 0, p = a.status === "offline" ? "offline" : a.status === "online" ? "online" : void 0
|
|
93
|
+
let o = typeof a.name == "string" && a.name.length > 0 ? a.name : n.name, s = a.widgetLanguage === "en" ? "en" : "vi", c = Array.isArray(a.pageActions) ? a.pageActions : void 0, u = typeof a.contactInfo == "string" ? a.contactInfo : void 0, f = a.proactive && typeof a.proactive == "object" ? a.proactive : void 0, p = a.status === "offline" ? "offline" : a.status === "online" ? "online" : void 0, m = a.imageInput === !0 ? !0 : void 0, h = a.richMessages === !0 ? !0 : void 0, g = {
|
|
94
|
+
...c ? { pageActions: c } : {},
|
|
95
|
+
...u ? { contactInfo: u } : {},
|
|
96
|
+
...f ? { proactive: f } : {},
|
|
97
|
+
...p ? { status: p } : {},
|
|
98
|
+
...m ? { imageInput: m } : {},
|
|
99
|
+
...h ? { richMessages: h } : {}
|
|
100
|
+
};
|
|
94
101
|
return !a.design?.colors || !a.design?.layout || !a.design?.content || !l(a.design) ? {
|
|
95
102
|
name: o,
|
|
96
103
|
design: t,
|
|
97
104
|
widgetLanguage: s,
|
|
98
|
-
...
|
|
99
|
-
...u ? { contactInfo: u } : {},
|
|
100
|
-
...f ? { proactive: f } : {},
|
|
101
|
-
...p ? { status: p } : {}
|
|
105
|
+
...g
|
|
102
106
|
} : {
|
|
103
107
|
name: o,
|
|
104
108
|
design: a.design,
|
|
105
109
|
widgetLanguage: s,
|
|
106
|
-
...
|
|
107
|
-
...u ? { contactInfo: u } : {},
|
|
108
|
-
...f ? { proactive: f } : {},
|
|
109
|
-
...p ? { status: p } : {}
|
|
110
|
+
...g
|
|
110
111
|
};
|
|
111
112
|
}
|
|
112
113
|
function p(t) {
|
|
@@ -223,7 +224,7 @@ var T = /^[a-z][a-z0-9_]{2,40}$/, E = new Set([
|
|
|
223
224
|
}();
|
|
224
225
|
//#endregion
|
|
225
226
|
//#region src/core/api.ts
|
|
226
|
-
async function
|
|
227
|
+
async function O(e, t, n) {
|
|
227
228
|
try {
|
|
228
229
|
let r = new URLSearchParams({ visitorId: n }), i = await fetch(`${e}/widget/conversations?${r.toString()}`, {
|
|
229
230
|
method: "GET",
|
|
@@ -240,9 +241,51 @@ async function ee(e, t, n) {
|
|
|
240
241
|
return [];
|
|
241
242
|
}
|
|
242
243
|
}
|
|
243
|
-
async function
|
|
244
|
+
async function k(e, t, n, r, i) {
|
|
245
|
+
let a = i?.imageUploadError ?? "Image upload failed. Please try again.";
|
|
246
|
+
try {
|
|
247
|
+
let o = new FormData(), s = n.type === "image/webp" ? ".webp" : ".jpg";
|
|
248
|
+
o.append("file", n, `image${s}`);
|
|
249
|
+
let c = await fetch(`${e}/widget/upload`, {
|
|
250
|
+
method: "POST",
|
|
251
|
+
headers: {
|
|
252
|
+
"X-Api-Key": t,
|
|
253
|
+
...r ? { "X-Visitor-Id": r } : {}
|
|
254
|
+
},
|
|
255
|
+
referrerPolicy: "no-referrer-when-downgrade",
|
|
256
|
+
body: o
|
|
257
|
+
});
|
|
258
|
+
if (!c.ok) return c.status === 403 ? {
|
|
259
|
+
ok: !1,
|
|
260
|
+
error: i?.imageUploadPlanError ?? a
|
|
261
|
+
} : c.status === 413 ? {
|
|
262
|
+
ok: !1,
|
|
263
|
+
error: i?.imageUploadTooLarge ?? a
|
|
264
|
+
} : c.status === 429 ? {
|
|
265
|
+
ok: !1,
|
|
266
|
+
error: i?.imageUploadRateLimit ?? a
|
|
267
|
+
} : {
|
|
268
|
+
ok: !1,
|
|
269
|
+
error: a
|
|
270
|
+
};
|
|
271
|
+
let l = await c.json();
|
|
272
|
+
return l.url ? {
|
|
273
|
+
ok: !0,
|
|
274
|
+
url: l.url
|
|
275
|
+
} : {
|
|
276
|
+
ok: !1,
|
|
277
|
+
error: a
|
|
278
|
+
};
|
|
279
|
+
} catch {
|
|
280
|
+
return {
|
|
281
|
+
ok: !1,
|
|
282
|
+
error: a
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
async function A(e, t, n, r, i, a, o, s) {
|
|
244
287
|
try {
|
|
245
|
-
let
|
|
288
|
+
let c = D.getDefinitions(), l = await fetch(`${e}/widget/chat`, {
|
|
246
289
|
method: "POST",
|
|
247
290
|
headers: {
|
|
248
291
|
"Content-Type": "application/json",
|
|
@@ -254,26 +297,28 @@ async function te(e, t, n, r, i, a, o) {
|
|
|
254
297
|
sessionId: n,
|
|
255
298
|
message: r,
|
|
256
299
|
history: i,
|
|
257
|
-
...
|
|
300
|
+
...c.length > 0 ? { availableActions: c } : {},
|
|
301
|
+
...s?.length ? { attachments: s } : {}
|
|
258
302
|
})
|
|
259
303
|
});
|
|
260
|
-
if (!
|
|
304
|
+
if (!l.ok) return l.status === 401 ? {
|
|
261
305
|
reply: a.errorAuth,
|
|
262
306
|
error: !0
|
|
263
|
-
} :
|
|
307
|
+
} : l.status === 403 ? {
|
|
264
308
|
reply: a.errorForbidden,
|
|
265
309
|
error: !0
|
|
266
|
-
} :
|
|
310
|
+
} : l.status === 429 ? {
|
|
267
311
|
reply: a.errorQuota,
|
|
268
312
|
error: !0
|
|
269
313
|
} : {
|
|
270
314
|
reply: a.errorGeneric,
|
|
271
315
|
error: !0
|
|
272
316
|
};
|
|
273
|
-
let
|
|
317
|
+
let u = await l.json(), d = Array.isArray(u.blocks) && u.blocks.length > 0 ? u.blocks : void 0;
|
|
274
318
|
return {
|
|
275
|
-
reply:
|
|
276
|
-
pageAction:
|
|
319
|
+
reply: u.reply || a.errorMessage,
|
|
320
|
+
pageAction: u.pageAction,
|
|
321
|
+
blocks: d
|
|
277
322
|
};
|
|
278
323
|
} catch {
|
|
279
324
|
return {
|
|
@@ -282,16 +327,16 @@ async function te(e, t, n, r, i, a, o) {
|
|
|
282
327
|
};
|
|
283
328
|
}
|
|
284
329
|
}
|
|
285
|
-
var
|
|
330
|
+
var j = {
|
|
286
331
|
messages: [],
|
|
287
332
|
hasMore: !1
|
|
288
333
|
};
|
|
289
|
-
function
|
|
334
|
+
function M(e) {
|
|
290
335
|
if (!e || typeof e != "object") return !1;
|
|
291
336
|
let t = e;
|
|
292
337
|
return typeof t.id == "string" && (t.role === "user" || t.role === "assistant") && typeof t.content == "string";
|
|
293
338
|
}
|
|
294
|
-
async function
|
|
339
|
+
async function N(e, t, n, r, i, a) {
|
|
295
340
|
try {
|
|
296
341
|
let o = new URLSearchParams({
|
|
297
342
|
sessionId: n,
|
|
@@ -306,26 +351,112 @@ async function A(e, t, n, r, i, a) {
|
|
|
306
351
|
},
|
|
307
352
|
referrerPolicy: "no-referrer-when-downgrade"
|
|
308
353
|
});
|
|
309
|
-
if (!s.ok) return
|
|
354
|
+
if (!s.ok) return j;
|
|
310
355
|
let c = await s.json();
|
|
311
356
|
return {
|
|
312
|
-
messages: Array.isArray(c.messages) ? c.messages.filter(
|
|
357
|
+
messages: Array.isArray(c.messages) ? c.messages.filter(M) : [],
|
|
313
358
|
hasMore: c.hasMore === !0,
|
|
314
359
|
escalated: c.escalated === !0
|
|
315
360
|
};
|
|
316
361
|
} catch {
|
|
317
|
-
return
|
|
362
|
+
return j;
|
|
318
363
|
}
|
|
319
364
|
}
|
|
320
|
-
function
|
|
321
|
-
return
|
|
365
|
+
function P(e, t, n, r, i) {
|
|
366
|
+
return N(e, t, n, void 0, r, i);
|
|
322
367
|
}
|
|
323
|
-
function
|
|
324
|
-
return
|
|
368
|
+
function ee(e, t, n, r, i, a) {
|
|
369
|
+
return N(e, t, n, r, i, a);
|
|
370
|
+
}
|
|
371
|
+
//#endregion
|
|
372
|
+
//#region src/core/stream.ts
|
|
373
|
+
async function te(e) {
|
|
374
|
+
if (typeof ReadableStream > "u") return A(e.apiUrl, e.apiKey, e.sessionId, e.message, e.history, e.strings, e.visitorId, e.attachments);
|
|
375
|
+
let t = D.getDefinitions(), n = {
|
|
376
|
+
sessionId: e.sessionId,
|
|
377
|
+
message: e.message,
|
|
378
|
+
history: e.history,
|
|
379
|
+
...t.length ? { availableActions: t } : {},
|
|
380
|
+
...e.visitorId ? { visitorId: e.visitorId } : {},
|
|
381
|
+
...e.attachments?.length ? { attachments: e.attachments } : {}
|
|
382
|
+
}, r;
|
|
383
|
+
try {
|
|
384
|
+
r = await fetch(`${e.apiUrl}/widget/chat/stream`, {
|
|
385
|
+
method: "POST",
|
|
386
|
+
headers: {
|
|
387
|
+
"Content-Type": "application/json",
|
|
388
|
+
"X-Api-Key": e.apiKey,
|
|
389
|
+
...e.visitorId ? { "X-Visitor-Id": e.visitorId } : {}
|
|
390
|
+
},
|
|
391
|
+
referrerPolicy: "no-referrer-when-downgrade",
|
|
392
|
+
body: JSON.stringify(n)
|
|
393
|
+
});
|
|
394
|
+
} catch {
|
|
395
|
+
return A(e.apiUrl, e.apiKey, e.sessionId, e.message, e.history, e.strings, e.visitorId, e.attachments);
|
|
396
|
+
}
|
|
397
|
+
if (!r.ok) return r.status === 401 ? {
|
|
398
|
+
reply: e.strings.errorAuth,
|
|
399
|
+
error: !0
|
|
400
|
+
} : r.status === 403 ? {
|
|
401
|
+
reply: e.strings.errorForbidden,
|
|
402
|
+
error: !0
|
|
403
|
+
} : r.status === 429 ? {
|
|
404
|
+
reply: e.strings.errorQuota,
|
|
405
|
+
error: !0
|
|
406
|
+
} : A(e.apiUrl, e.apiKey, e.sessionId, e.message, e.history, e.strings, e.visitorId, e.attachments);
|
|
407
|
+
if (!r.body) return {
|
|
408
|
+
reply: e.strings.errorMessage,
|
|
409
|
+
error: !0
|
|
410
|
+
};
|
|
411
|
+
try {
|
|
412
|
+
return await ne(r.body, e);
|
|
413
|
+
} catch {
|
|
414
|
+
return {
|
|
415
|
+
reply: e.strings.errorMessage,
|
|
416
|
+
error: !0
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
async function ne(e, t) {
|
|
421
|
+
let n = e.getReader(), r = new TextDecoder(), i = "", a = "", o = null;
|
|
422
|
+
outer: for (;;) {
|
|
423
|
+
let { done: e, value: s } = await n.read();
|
|
424
|
+
if (e) break;
|
|
425
|
+
i += r.decode(s, { stream: !0 });
|
|
426
|
+
let c = i.split("\n");
|
|
427
|
+
i = c.pop() ?? "";
|
|
428
|
+
for (let e of c) {
|
|
429
|
+
if (!e.startsWith("data: ")) continue;
|
|
430
|
+
let n = e.slice(6).trim();
|
|
431
|
+
if (!n) continue;
|
|
432
|
+
let r;
|
|
433
|
+
try {
|
|
434
|
+
r = JSON.parse(n);
|
|
435
|
+
} catch {
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
if (r.type === "token") {
|
|
439
|
+
let e = String(r.delta ?? "");
|
|
440
|
+
e && (a += e, t.onToken(e));
|
|
441
|
+
} else if (r.type === "done") {
|
|
442
|
+
o = r;
|
|
443
|
+
break outer;
|
|
444
|
+
} else if (r.type === "error") return {
|
|
445
|
+
reply: t.strings.errorMessage,
|
|
446
|
+
error: !0
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (!o) throw Error("SSE stream ended without done event");
|
|
451
|
+
return {
|
|
452
|
+
reply: a || t.strings.errorMessage,
|
|
453
|
+
pageAction: o.pageAction,
|
|
454
|
+
blocks: o.blocks
|
|
455
|
+
};
|
|
325
456
|
}
|
|
326
457
|
//#endregion
|
|
327
458
|
//#region src/core/state.ts
|
|
328
|
-
var
|
|
459
|
+
var F = {
|
|
329
460
|
messages: [],
|
|
330
461
|
isLoading: !1,
|
|
331
462
|
isOpen: !1,
|
|
@@ -334,26 +465,107 @@ var M = {
|
|
|
334
465
|
unreadCount: 0,
|
|
335
466
|
conversations: [],
|
|
336
467
|
currentSessionId: "",
|
|
337
|
-
escalated: !1
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
468
|
+
escalated: !1,
|
|
469
|
+
pendingAttachment: null,
|
|
470
|
+
isUploading: !1,
|
|
471
|
+
uploadError: null
|
|
472
|
+
}, I = /* @__PURE__ */ new Set();
|
|
473
|
+
function L() {
|
|
474
|
+
return F;
|
|
341
475
|
}
|
|
342
|
-
function
|
|
343
|
-
Object.assign(
|
|
476
|
+
function R(e) {
|
|
477
|
+
Object.assign(F, e);
|
|
344
478
|
let t = {
|
|
345
|
-
...
|
|
346
|
-
messages: [...
|
|
347
|
-
conversations: [...
|
|
479
|
+
...F,
|
|
480
|
+
messages: [...F.messages],
|
|
481
|
+
conversations: [...F.conversations]
|
|
348
482
|
};
|
|
349
|
-
|
|
483
|
+
I.forEach((e) => e(t));
|
|
350
484
|
}
|
|
351
485
|
function re(e) {
|
|
352
|
-
return
|
|
486
|
+
return I.add(e), () => I.delete(e);
|
|
487
|
+
}
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region src/core/upload.ts
|
|
490
|
+
var z = new Set([
|
|
491
|
+
"image/jpeg",
|
|
492
|
+
"image/png",
|
|
493
|
+
"image/webp"
|
|
494
|
+
]), B = 25 * 1024 * 1024, ie = 5 * 1024 * 1024, V = 1600, ae = .85, oe = .65;
|
|
495
|
+
function se(e) {
|
|
496
|
+
return z.has(e);
|
|
497
|
+
}
|
|
498
|
+
function ce(e) {
|
|
499
|
+
return se(e.type) ? e.size > B ? {
|
|
500
|
+
ok: !1,
|
|
501
|
+
error: "Image too large (max 25 MB before compression)."
|
|
502
|
+
} : { ok: !0 } : {
|
|
503
|
+
ok: !1,
|
|
504
|
+
error: "Unsupported image type. Please use JPEG, PNG, or WebP."
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
function le(e, t) {
|
|
508
|
+
let n = Math.max(e, t);
|
|
509
|
+
if (n <= V) return {
|
|
510
|
+
width: e,
|
|
511
|
+
height: t
|
|
512
|
+
};
|
|
513
|
+
let r = V / n;
|
|
514
|
+
return {
|
|
515
|
+
width: Math.floor(e * r),
|
|
516
|
+
height: Math.floor(t * r)
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
function ue(e) {
|
|
520
|
+
let t = ce(e);
|
|
521
|
+
return t.ok ? new Promise((t, n) => {
|
|
522
|
+
let r = new Image(), i = URL.createObjectURL(e);
|
|
523
|
+
r.onload = () => {
|
|
524
|
+
URL.revokeObjectURL(i);
|
|
525
|
+
let { width: a, height: o } = le(r.naturalWidth, r.naturalHeight), s = document.createElement("canvas");
|
|
526
|
+
s.width = a, s.height = o;
|
|
527
|
+
let c = s.getContext("2d");
|
|
528
|
+
if (!c) {
|
|
529
|
+
n(/* @__PURE__ */ Error("Canvas 2D context not available"));
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
c.drawImage(r, 0, 0, a, o);
|
|
533
|
+
let l = e.type === "image/webp" ? "image/webp" : "image/jpeg";
|
|
534
|
+
s.toBlob((e) => {
|
|
535
|
+
if (!e) {
|
|
536
|
+
n(/* @__PURE__ */ Error("Canvas toBlob returned null"));
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
if (e.size <= ie) {
|
|
540
|
+
t({
|
|
541
|
+
blob: e,
|
|
542
|
+
mimeType: l
|
|
543
|
+
});
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
s.toBlob((e) => {
|
|
547
|
+
if (!e) {
|
|
548
|
+
n(/* @__PURE__ */ Error("Canvas toBlob (fallback quality) returned null"));
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
if (e.size > ie) {
|
|
552
|
+
n(/* @__PURE__ */ Error("Image too large after compression (> 5 MB). Try a smaller image."));
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
t({
|
|
556
|
+
blob: e,
|
|
557
|
+
mimeType: l
|
|
558
|
+
});
|
|
559
|
+
}, l, oe);
|
|
560
|
+
}, l, ae);
|
|
561
|
+
}, r.onerror = () => {
|
|
562
|
+
URL.revokeObjectURL(i), n(/* @__PURE__ */ Error("Failed to load image"));
|
|
563
|
+
}, r.src = i;
|
|
564
|
+
}) : Promise.reject(Error(t.error));
|
|
353
565
|
}
|
|
354
566
|
//#endregion
|
|
355
567
|
//#region src/core/styles.ts
|
|
356
|
-
var
|
|
568
|
+
var de = {
|
|
357
569
|
inter: {
|
|
358
570
|
url: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap",
|
|
359
571
|
family: "'Inter', system-ui, -apple-system, sans-serif"
|
|
@@ -375,21 +587,21 @@ var I = {
|
|
|
375
587
|
family: "'Playfair Display', Georgia, serif"
|
|
376
588
|
}
|
|
377
589
|
};
|
|
378
|
-
function
|
|
590
|
+
function H(e, t) {
|
|
379
591
|
if (!t) return e;
|
|
380
592
|
let n = t.angle ?? 135;
|
|
381
593
|
return t.type === "linear" ? `linear-gradient(${n}deg, ${t.from}, ${t.to})` : `radial-gradient(circle, ${t.from}, ${t.to})`;
|
|
382
594
|
}
|
|
383
|
-
function
|
|
595
|
+
function fe(e) {
|
|
384
596
|
return e.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\\[0-9a-fA-F]{1,6}\s?/g, "x").replace(/@import\b[^;]*;?/gi, "").replace(/url\s*\(\s*["']?\s*(?!data:)[^)]*["']?\s*\)/gi, "url(\"\")").replace(/expression\s*\(/gi, "expression_(").replace(/javascript\s*:/gi, "blocked:").replace(/-moz-binding\s*:/gi, "").replace(/\bbehavior\s*:/gi, "");
|
|
385
597
|
}
|
|
386
|
-
function
|
|
598
|
+
function pe(e) {
|
|
387
599
|
let t = e?.bubbleOpen ?? "none", n = e?.typingIndicator ?? "dots-bounce";
|
|
388
600
|
return [t === "fade" ? "@keyframes biq-open-fade { from { opacity: 0; } to { opacity: 1; } }\n.chat-window.open { animation: biq-open-fade .22s ease forwards; }" : t === "slide-up" ? "@keyframes biq-open-slide { from { opacity: 0; transform: scale(1) translateY(20px); } to { opacity: 1; transform: scale(1) translateY(0); } }\n.chat-window.open { animation: biq-open-slide .25s cubic-bezier(.22,1,.36,1) forwards; }" : t === "bounce" ? "@keyframes biq-open-bounce { 0% { opacity: 0; transform: scale(.85) translateY(8px); } 60% { transform: scale(1.03) translateY(-3px); } 100% { opacity: 1; transform: scale(1) translateY(0); } }\n.chat-window.open { animation: biq-open-bounce .35s cubic-bezier(.34,1.56,.64,1) forwards; }" : "", n === "dots-pulse" ? "@keyframes biq-pulse { 0%, 100% { opacity: 0.3; transform: scale(1); } 50% { opacity: 1; transform: scale(1.3); } }\n.typing span { animation: biq-pulse 1.2s infinite ease-in-out; }" : n === "bar" ? ".typing { gap: 3px; align-items: flex-end; }\n.typing span { width: 3px; height: 14px; border-radius: 2px; animation: biq-bar 1s infinite ease-in-out; }\n.typing span:nth-child(1) { animation-delay: 0s; }\n.typing span:nth-child(2) { animation-delay: .15s; height: 20px; }\n.typing span:nth-child(3) { animation-delay: .3s; }\n@keyframes biq-bar { 0%, 100% { transform: scaleY(.4); opacity: .5; } 50% { transform: scaleY(1); opacity: 1; } }" : ""].filter(Boolean).join("\n");
|
|
389
601
|
}
|
|
390
|
-
var
|
|
391
|
-
function
|
|
392
|
-
let { colors: t, layout: n, font: r, gradient: i, animation: a, customCSS: o, whiteLabel: s } = e, c =
|
|
602
|
+
var me = "\n/* ── Rich Blocks ─────────────────────────── */\n.biq-blocks {\n margin-top: 8px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n max-width: 100%;\n}\n\n/* ── Shared button style ─────────────────── */\n.biq-btn {\n display: inline-block;\n padding: 7px 14px;\n border-radius: 18px;\n font: inherit;\n font-size: 13px;\n font-weight: 500;\n cursor: pointer;\n transition: filter .15s, opacity .15s;\n text-decoration: none;\n border: 1.5px solid #F97316;\n background: transparent;\n color: #F97316;\n line-height: 1.3;\n white-space: nowrap;\n}\n.biq-btn:hover { filter: brightness(1.15); }\n.biq-btn--send { background: #F97316; color: #fff; }\n.biq-btn--send:hover { filter: brightness(0.9); }\n.biq-btn--url { background: transparent; color: #F97316; }\n.biq-btn--page_action { border-style: dashed; }\n\n/* ── Card ────────────────────────────────── */\n.biq-card {\n background: #1A1A1A;\n border: 1px solid #2D2D2D;\n border-radius: 12px;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n min-width: 0;\n text-decoration: none;\n color: inherit;\n transition: border-color .15s;\n}\n.biq-card--link:hover { border-color: #F97316; }\n\n.biq-card-img {\n width: 100%;\n max-height: 160px;\n object-fit: cover;\n display: block;\n}\n\n.biq-card-title {\n font-size: 14px;\n font-weight: 600;\n color: #fff;\n padding: 10px 12px 2px;\n line-height: 1.3;\n}\n\n.biq-card-subtitle {\n font-size: 12px;\n color: #9CA3AF;\n padding: 0 12px 6px;\n line-height: 1.4;\n}\n\n.biq-card-price {\n font-size: 14px;\n font-weight: 600;\n color: #F97316;\n padding: 4px 12px 8px;\n}\n\n.biq-card-btns {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n padding: 0 10px 10px;\n}\n\n/* ── Carousel ────────────────────────────── */\n.biq-carousel {\n display: flex;\n flex-direction: row;\n gap: 10px;\n overflow-x: auto;\n padding-bottom: 4px;\n scrollbar-width: thin;\n scrollbar-color: #2D2D2D transparent;\n /* Snap cards into position on scroll */\n scroll-snap-type: x mandatory;\n}\n.biq-carousel::-webkit-scrollbar { height: 4px; }\n.biq-carousel::-webkit-scrollbar-track { background: transparent; }\n.biq-carousel::-webkit-scrollbar-thumb { background: #2D2D2D; border-radius: 2px; }\n\n.biq-carousel .biq-card {\n flex: 0 0 200px;\n scroll-snap-align: start;\n max-width: 200px;\n}\n\n/* ── Quick Replies ───────────────────────── */\n.biq-quick-replies {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 4px;\n}\n\n.biq-qr-pill {\n padding: 5px 14px;\n border-radius: 20px;\n border: 1.5px solid #F97316;\n background: transparent;\n color: #F97316;\n font: inherit;\n font-size: 13px;\n cursor: pointer;\n transition: background .15s, color .15s;\n white-space: nowrap;\n}\n.biq-qr-pill:hover { background: #F97316; color: #fff; }\n\n/* ── Buttons block ───────────────────────── */\n.biq-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n margin-top: 4px;\n}\n", he = "\n.botiq-confirm-overlay { position:absolute; inset:0; background:rgba(0,0,0,.7);\n display:flex; align-items:center; justify-content:center; z-index:999; }\n.botiq-confirm-dialog { background:#1A1A1A; border:1px solid #2D2D2D; border-radius:12px;\n padding:16px; max-width:320px; color:#fff; font-size:14px; }\n.botiq-confirm-header { font-weight:600; margin-bottom:8px; }\n.botiq-confirm-reason { color:#9CA3AF; margin-bottom:8px; }\n.botiq-confirm-params { background:#0a0a0a; padding:8px; border-radius:6px; font-size:12px;\n max-height:120px; overflow:auto; white-space:pre-wrap; }\n.botiq-confirm-actions { display:flex; gap:8px; margin-top:12px; }\n.botiq-confirm-yes { flex:1; padding:8px 12px; border-radius:6px; border:none;\n background:#F97316; color:#fff; cursor:pointer; }\n.botiq-confirm-yes[data-risk=\"high\"] { background:#DC2626; }\n.botiq-confirm-no { flex:1; padding:8px 12px; border-radius:6px; background:transparent;\n border:1px solid #2D2D2D; color:#fff; cursor:pointer; }\n.botiq-confirm-countdown { margin-top:8px; font-size:12px; color:#9CA3AF; }\n";
|
|
603
|
+
function ge(e) {
|
|
604
|
+
let { colors: t, layout: n, font: r, gradient: i, animation: a, customCSS: o, whiteLabel: s } = e, c = de[r] ?? de.inter, l = n.buttonShape === "square" ? "14px" : "50%", u = n.position === "bottom-left" ? "right: auto; left: 24px;" : "right: 24px;", d = n.position === "bottom-left" ? "bottom left" : "bottom right", f = n.position === "bottom-left" ? "right: auto; left: 0;" : "right: 0;", p = n.fillHeight ? `min(${n.height}px, calc(100dvh - 48px))` : `${n.height}px`, m = H(t.primary, i), h = H(t.header, i), g = H(t.userBubble, i), _ = t.primary.length === 4 ? "#" + t.primary[1].repeat(2) + t.primary[2].repeat(2) + t.primary[3].repeat(2) : t.primary, v = s ? ".botiq-badge { display: none !important; }" : "";
|
|
393
605
|
return `
|
|
394
606
|
@import url('${c.url}');
|
|
395
607
|
|
|
@@ -407,6 +619,7 @@ function oe(e) {
|
|
|
407
619
|
--color-bg: ${t.background};
|
|
408
620
|
--color-text: ${t.text};
|
|
409
621
|
--color-input-bg: ${t.inputBackground};
|
|
622
|
+
--hover-bg: ${_}1A;
|
|
410
623
|
--gray-50: #1A1A1A;
|
|
411
624
|
--gray-100: #222222;
|
|
412
625
|
--gray-200: #2D2D2D;
|
|
@@ -564,12 +777,17 @@ function oe(e) {
|
|
|
564
777
|
border: none;
|
|
565
778
|
color: var(--gray-400);
|
|
566
779
|
font: inherit;
|
|
567
|
-
font-size:
|
|
568
|
-
padding: 10px;
|
|
780
|
+
font-size: 11px;
|
|
781
|
+
padding: 8px 10px 10px;
|
|
569
782
|
cursor: pointer;
|
|
570
783
|
transition: color .15s;
|
|
784
|
+
display: flex;
|
|
785
|
+
flex-direction: column;
|
|
786
|
+
align-items: center;
|
|
787
|
+
gap: 3px;
|
|
571
788
|
}
|
|
572
789
|
|
|
790
|
+
.nav-btn svg { width: 18px; height: 18px; fill: currentColor; }
|
|
573
791
|
.nav-btn:hover { color: var(--color-text); }
|
|
574
792
|
.nav-btn.active { color: var(--color-primary); }
|
|
575
793
|
|
|
@@ -577,10 +795,11 @@ function oe(e) {
|
|
|
577
795
|
.msg-list { flex: 1; overflow-y: auto; }
|
|
578
796
|
|
|
579
797
|
.msg-list-item {
|
|
580
|
-
display:
|
|
798
|
+
display: flex;
|
|
799
|
+
align-items: flex-start;
|
|
800
|
+
gap: 10px;
|
|
581
801
|
width: 100%;
|
|
582
802
|
text-align: left;
|
|
583
|
-
gap: 2px;
|
|
584
803
|
padding: 12px 16px;
|
|
585
804
|
background: transparent;
|
|
586
805
|
border: none;
|
|
@@ -589,7 +808,27 @@ function oe(e) {
|
|
|
589
808
|
font: inherit;
|
|
590
809
|
}
|
|
591
810
|
|
|
592
|
-
.msg-list-item:hover { background: var(--
|
|
811
|
+
.msg-list-item:hover { background: var(--hover-bg); }
|
|
812
|
+
|
|
813
|
+
.msg-list-avatar {
|
|
814
|
+
flex-shrink: 0;
|
|
815
|
+
width: 36px;
|
|
816
|
+
height: 36px;
|
|
817
|
+
border-radius: 50%;
|
|
818
|
+
overflow: hidden;
|
|
819
|
+
background: var(--color-primary);
|
|
820
|
+
display: flex;
|
|
821
|
+
align-items: center;
|
|
822
|
+
justify-content: center;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
.msg-list-body {
|
|
826
|
+
flex: 1;
|
|
827
|
+
min-width: 0;
|
|
828
|
+
display: flex;
|
|
829
|
+
flex-direction: column;
|
|
830
|
+
gap: 2px;
|
|
831
|
+
}
|
|
593
832
|
|
|
594
833
|
.msg-list-title {
|
|
595
834
|
color: var(--color-text);
|
|
@@ -607,7 +846,7 @@ function oe(e) {
|
|
|
607
846
|
|
|
608
847
|
.msg-list-time { color: var(--gray-400); font-size: 10px; }
|
|
609
848
|
|
|
610
|
-
.msg-list-badge { color:
|
|
849
|
+
.msg-list-badge { color: var(--color-primary); font-size: 10px; }
|
|
611
850
|
|
|
612
851
|
.msg-list-empty {
|
|
613
852
|
padding: 24px;
|
|
@@ -630,33 +869,124 @@ function oe(e) {
|
|
|
630
869
|
|
|
631
870
|
.msg-list-new:hover { background: var(--color-primary); color: #fff; }
|
|
632
871
|
|
|
633
|
-
/* ── Home panel
|
|
634
|
-
.home-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
872
|
+
/* ── Home panel hero banner ─────────────── */
|
|
873
|
+
.home-hero {
|
|
874
|
+
background: var(--color-primary);
|
|
875
|
+
padding: 22px 18px 20px;
|
|
876
|
+
flex-shrink: 0;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
.home-hero-row {
|
|
880
|
+
display: flex;
|
|
881
|
+
align-items: center;
|
|
882
|
+
gap: 12px;
|
|
883
|
+
margin-bottom: 14px;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.home-hero-avatar {
|
|
887
|
+
width: 48px;
|
|
888
|
+
height: 48px;
|
|
889
|
+
border-radius: 50%;
|
|
890
|
+
overflow: hidden;
|
|
891
|
+
flex-shrink: 0;
|
|
892
|
+
background: rgba(255,255,255,.2);
|
|
639
893
|
}
|
|
640
894
|
|
|
895
|
+
.home-hero-name {
|
|
896
|
+
font-weight: 700;
|
|
897
|
+
font-size: 15px;
|
|
898
|
+
color: #fff;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
.home-hero-status {
|
|
902
|
+
font-size: 12px;
|
|
903
|
+
color: rgba(255,255,255,.8);
|
|
904
|
+
margin-top: 2px;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
.home-hero-greeting {
|
|
908
|
+
font-size: 15px;
|
|
909
|
+
line-height: 1.5;
|
|
910
|
+
color: rgba(255,255,255,.92);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
/* ── Home panel CTA ─────────────────────── */
|
|
641
914
|
.home-start {
|
|
642
|
-
margin:
|
|
915
|
+
margin: 14px 18px;
|
|
643
916
|
padding: 14px;
|
|
644
917
|
border-radius: 12px;
|
|
645
|
-
border:
|
|
646
|
-
background:
|
|
647
|
-
color: var(--color-
|
|
648
|
-
text-align:
|
|
918
|
+
border: 1.5px solid var(--color-primary);
|
|
919
|
+
background: transparent;
|
|
920
|
+
color: var(--color-primary);
|
|
921
|
+
text-align: center;
|
|
649
922
|
cursor: pointer;
|
|
650
923
|
font: inherit;
|
|
651
924
|
font-size: 14px;
|
|
652
|
-
|
|
925
|
+
font-weight: 600;
|
|
926
|
+
width: calc(100% - 36px);
|
|
927
|
+
transition: background .15s, color .15s;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
.home-start:hover { background: var(--color-primary); color: #fff; }
|
|
931
|
+
|
|
932
|
+
/* ── Home recent conversations ──────────────── */
|
|
933
|
+
.home-recent-label {
|
|
934
|
+
margin: 16px 18px 6px;
|
|
935
|
+
font-size: 11px;
|
|
936
|
+
font-weight: 600;
|
|
937
|
+
text-transform: uppercase;
|
|
938
|
+
letter-spacing: .06em;
|
|
939
|
+
color: var(--gray-400);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
.home-recent-item {
|
|
943
|
+
display: flex;
|
|
944
|
+
align-items: center;
|
|
945
|
+
gap: 10px;
|
|
946
|
+
width: 100%;
|
|
947
|
+
padding: 10px 18px;
|
|
948
|
+
background: transparent;
|
|
949
|
+
border: none;
|
|
950
|
+
border-bottom: 1px solid var(--gray-100);
|
|
951
|
+
cursor: pointer;
|
|
952
|
+
font: inherit;
|
|
953
|
+
text-align: left;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
.home-recent-item:hover { background: var(--hover-bg); }
|
|
957
|
+
|
|
958
|
+
.home-recent-avatar {
|
|
959
|
+
flex-shrink: 0;
|
|
960
|
+
width: 32px;
|
|
961
|
+
height: 32px;
|
|
962
|
+
border-radius: 50%;
|
|
963
|
+
overflow: hidden;
|
|
964
|
+
background: var(--color-primary);
|
|
965
|
+
display: flex;
|
|
966
|
+
align-items: center;
|
|
967
|
+
justify-content: center;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
.home-recent-body { flex: 1; min-width: 0; }
|
|
971
|
+
|
|
972
|
+
.home-recent-title {
|
|
973
|
+
color: var(--color-text);
|
|
974
|
+
font-size: 13px;
|
|
975
|
+
font-weight: 500;
|
|
976
|
+
white-space: nowrap;
|
|
977
|
+
overflow: hidden;
|
|
978
|
+
text-overflow: ellipsis;
|
|
653
979
|
}
|
|
654
980
|
|
|
655
|
-
.home-
|
|
981
|
+
.home-recent-preview {
|
|
982
|
+
color: var(--gray-400);
|
|
983
|
+
font-size: 12px;
|
|
984
|
+
white-space: nowrap;
|
|
985
|
+
overflow: hidden;
|
|
986
|
+
text-overflow: ellipsis;
|
|
987
|
+
}
|
|
656
988
|
|
|
657
|
-
.home-
|
|
658
|
-
.home-status--online { color: #16A34A; }
|
|
659
|
-
.home-status--offline { color: var(--gray-400); }
|
|
989
|
+
.home-recent-time { color: var(--gray-400); font-size: 10px; flex-shrink: 0; }
|
|
660
990
|
|
|
661
991
|
/* ── Messages ───────────────────────────── */
|
|
662
992
|
.messages {
|
|
@@ -910,9 +1240,11 @@ function oe(e) {
|
|
|
910
1240
|
color: var(--color-text);
|
|
911
1241
|
opacity: 0.4;
|
|
912
1242
|
text-decoration: none;
|
|
913
|
-
|
|
1243
|
+
padding: 5px 0 7px;
|
|
914
1244
|
letter-spacing: 0.02em;
|
|
915
1245
|
transition: opacity .15s;
|
|
1246
|
+
background: var(--color-bg);
|
|
1247
|
+
border-top: 1px solid var(--gray-100);
|
|
916
1248
|
}
|
|
917
1249
|
.botiq-badge:hover { opacity: 0.85; }
|
|
918
1250
|
.botiq-badge-name { font-weight: 600; color: var(--color-primary); }
|
|
@@ -957,6 +1289,72 @@ function oe(e) {
|
|
|
957
1289
|
.send-btn:disabled { background: var(--gray-200); cursor: not-allowed; filter: none; }
|
|
958
1290
|
.send-btn svg { width: 18px; height: 18px; fill: #fff; }
|
|
959
1291
|
|
|
1292
|
+
/* ── Attach Button ──────────────────────── */
|
|
1293
|
+
.attach-btn {
|
|
1294
|
+
width: 34px; height: 38px;
|
|
1295
|
+
background: transparent; border: none; cursor: pointer;
|
|
1296
|
+
color: var(--gray-400); flex-shrink: 0;
|
|
1297
|
+
display: flex; align-items: center; justify-content: center;
|
|
1298
|
+
border-radius: 8px; transition: color .15s, background .15s;
|
|
1299
|
+
}
|
|
1300
|
+
.attach-btn:hover { color: var(--color-primary); background: rgba(249,115,22,.08); }
|
|
1301
|
+
.attach-btn svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
|
|
1302
|
+
|
|
1303
|
+
/* ── Attach Preview Slot ────────────────── */
|
|
1304
|
+
.attach-preview-slot {
|
|
1305
|
+
margin-bottom: 6px;
|
|
1306
|
+
}
|
|
1307
|
+
|
|
1308
|
+
.attach-preview {
|
|
1309
|
+
display: flex;
|
|
1310
|
+
align-items: center;
|
|
1311
|
+
gap: 8px;
|
|
1312
|
+
padding: 6px 8px;
|
|
1313
|
+
background: var(--gray-50);
|
|
1314
|
+
border: 1px solid var(--gray-200);
|
|
1315
|
+
border-radius: 10px;
|
|
1316
|
+
position: relative;
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
.attach-preview-img {
|
|
1320
|
+
width: 48px;
|
|
1321
|
+
height: 48px;
|
|
1322
|
+
object-fit: cover;
|
|
1323
|
+
border-radius: 6px;
|
|
1324
|
+
flex-shrink: 0;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
.attach-preview-img--uploading {
|
|
1328
|
+
opacity: 0.5;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
.attach-preview-status {
|
|
1332
|
+
font-size: 12px;
|
|
1333
|
+
color: var(--gray-400);
|
|
1334
|
+
flex: 1;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
.attach-preview-error {
|
|
1338
|
+
font-size: 12px;
|
|
1339
|
+
color: #DC2626;
|
|
1340
|
+
flex: 1;
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
.attach-preview-remove {
|
|
1344
|
+
width: 22px; height: 22px;
|
|
1345
|
+
border-radius: 50%;
|
|
1346
|
+
background: var(--gray-200);
|
|
1347
|
+
border: none;
|
|
1348
|
+
cursor: pointer;
|
|
1349
|
+
color: var(--color-text);
|
|
1350
|
+
font-size: 14px;
|
|
1351
|
+
line-height: 1;
|
|
1352
|
+
display: flex; align-items: center; justify-content: center;
|
|
1353
|
+
flex-shrink: 0;
|
|
1354
|
+
transition: background .15s;
|
|
1355
|
+
}
|
|
1356
|
+
.attach-preview-remove:hover { background: #DC2626; color: #fff; }
|
|
1357
|
+
|
|
960
1358
|
.emoji-btn {
|
|
961
1359
|
width: 34px; height: 38px;
|
|
962
1360
|
background: transparent; border: none; cursor: pointer;
|
|
@@ -977,10 +1375,11 @@ function oe(e) {
|
|
|
977
1375
|
}
|
|
978
1376
|
.emoji-item:hover { background: var(--gray-100); }
|
|
979
1377
|
|
|
980
|
-
${
|
|
981
|
-
${
|
|
982
|
-
${o ?
|
|
983
|
-
${
|
|
1378
|
+
${v}
|
|
1379
|
+
${pe(a)}
|
|
1380
|
+
${o ? fe(o) : ""}
|
|
1381
|
+
${he}
|
|
1382
|
+
${me}
|
|
984
1383
|
@media (max-width: 480px) {
|
|
985
1384
|
:host { bottom: 0; right: 0; left: 0; }
|
|
986
1385
|
.chat-window {
|
|
@@ -997,18 +1396,18 @@ ${ae}
|
|
|
997
1396
|
}
|
|
998
1397
|
//#endregion
|
|
999
1398
|
//#region src/core/timeago.ts
|
|
1000
|
-
function
|
|
1399
|
+
function U(e) {
|
|
1001
1400
|
return String(e).padStart(2, "0");
|
|
1002
1401
|
}
|
|
1003
|
-
function
|
|
1402
|
+
function W(e, t, n) {
|
|
1004
1403
|
let r = Math.max(0, Math.floor((t - e) / 1e3));
|
|
1005
1404
|
if (r < 60) return n === "vi" ? "vừa xong" : "just now";
|
|
1006
1405
|
let i = Math.floor(r / 60);
|
|
1007
1406
|
if (i < 60) return n === "vi" ? `${i} phút` : `${i} min`;
|
|
1008
1407
|
let a = new Date(e);
|
|
1009
|
-
return `${
|
|
1408
|
+
return `${U(a.getHours())}:${U(a.getMinutes())}`;
|
|
1010
1409
|
}
|
|
1011
|
-
function
|
|
1410
|
+
function _e(e, t, n) {
|
|
1012
1411
|
let r = (e) => {
|
|
1013
1412
|
let t = new Date(e);
|
|
1014
1413
|
return new Date(t.getFullYear(), t.getMonth(), t.getDate()).getTime();
|
|
@@ -1016,85 +1415,111 @@ function se(e, t, n) {
|
|
|
1016
1415
|
if (i <= 0) return n === "vi" ? "Hôm nay" : "Today";
|
|
1017
1416
|
if (i === 1) return n === "vi" ? "Hôm qua" : "Yesterday";
|
|
1018
1417
|
let a = new Date(e);
|
|
1019
|
-
return `${
|
|
1418
|
+
return `${U(a.getDate())}/${U(a.getMonth() + 1)}/${a.getFullYear()}`;
|
|
1020
1419
|
}
|
|
1021
1420
|
//#endregion
|
|
1022
1421
|
//#region src/core/views.ts
|
|
1023
|
-
function
|
|
1422
|
+
function G(e) {
|
|
1024
1423
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
1025
1424
|
}
|
|
1026
|
-
function
|
|
1027
|
-
let
|
|
1028
|
-
return e.length === 0 ? `<div class="msg-list-empty">${
|
|
1029
|
-
let
|
|
1030
|
-
return `<button class="msg-list-item" type="button" data-session="${
|
|
1031
|
-
|
|
1032
|
-
<
|
|
1033
|
-
|
|
1425
|
+
function ve(e, t, n, r = "") {
|
|
1426
|
+
let i = `<button class="msg-list-new" type="button">+ ${G(t.newConversation)}</button>`;
|
|
1427
|
+
return e.length === 0 ? `<div class="msg-list-empty">${G(t.noConversations)}</div>${i}` : `<div class="msg-list">${e.map((e) => {
|
|
1428
|
+
let i = e.lastMessageAt ? Date.parse(e.lastMessageAt) : n, a = Number.isFinite(i) ? W(i, n, "vi") : "", o = e.escalated ? `<span class="msg-list-badge">${G(t.waitingForHuman)}</span>` : "";
|
|
1429
|
+
return `<button class="msg-list-item" type="button" data-session="${G(e.sessionId)}">
|
|
1430
|
+
${r ? `<div class="msg-list-avatar">${r}</div>` : ""}
|
|
1431
|
+
<div class="msg-list-body">
|
|
1432
|
+
<span class="msg-list-title">${G(e.title)}</span>
|
|
1433
|
+
<span class="msg-list-preview">${G(e.preview)}</span>
|
|
1434
|
+
<span class="msg-list-time">${G(a)}</span>${o}
|
|
1435
|
+
</div>
|
|
1034
1436
|
</button>`;
|
|
1035
|
-
}).join("")}</div>${
|
|
1036
|
-
}
|
|
1037
|
-
function
|
|
1038
|
-
let
|
|
1437
|
+
}).join("")}</div>${i}`;
|
|
1438
|
+
}
|
|
1439
|
+
function ye(e, t, n = [], r = "", i = Date.now()) {
|
|
1440
|
+
let a = e.status === "offline" ? t.statusPaused : t.statusOnline, o = G(e.design.content.greeting || t.homeGreeting), s = "";
|
|
1441
|
+
if (n.length > 0) {
|
|
1442
|
+
let e = n.slice(0, 3).map((e) => {
|
|
1443
|
+
let t = e.lastMessageAt ? Date.parse(e.lastMessageAt) : i, n = Number.isFinite(t) ? W(t, i, "vi") : "";
|
|
1444
|
+
return `<button class="home-recent-item" type="button" data-session="${G(e.sessionId)}">
|
|
1445
|
+
${r ? `<div class="home-recent-avatar">${r}</div>` : ""}
|
|
1446
|
+
<div class="home-recent-body">
|
|
1447
|
+
<div class="home-recent-title">${G(e.title)}</div>
|
|
1448
|
+
<div class="home-recent-preview">${G(e.preview)}</div>
|
|
1449
|
+
</div>
|
|
1450
|
+
<span class="home-recent-time">${G(n)}</span>
|
|
1451
|
+
</button>`;
|
|
1452
|
+
}).join("");
|
|
1453
|
+
s = `<div class="home-recent-label">${G(t.recentMessages)}</div>${e}`;
|
|
1454
|
+
}
|
|
1039
1455
|
return `
|
|
1040
|
-
<div class="home-
|
|
1041
|
-
|
|
1042
|
-
|
|
1456
|
+
<div class="home-hero">
|
|
1457
|
+
<div class="home-hero-row">
|
|
1458
|
+
${r ? `<div class="home-hero-avatar">${r}</div>` : ""}
|
|
1459
|
+
<div>
|
|
1460
|
+
<div class="home-hero-name">${G(e.name)}</div>
|
|
1461
|
+
<div class="home-hero-status">● ${G(a)}</div>
|
|
1462
|
+
</div>
|
|
1463
|
+
</div>
|
|
1464
|
+
<div class="home-hero-greeting">${o}</div>
|
|
1465
|
+
</div>
|
|
1466
|
+
<button class="home-start" type="button">${G(t.startConversation)}</button>
|
|
1467
|
+
${s}
|
|
1043
1468
|
`;
|
|
1044
1469
|
}
|
|
1045
1470
|
//#endregion
|
|
1046
1471
|
//#region src/core/assets.ts
|
|
1047
|
-
var
|
|
1472
|
+
var be = "data:image/png;base64,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";
|
|
1048
1473
|
//#endregion
|
|
1049
1474
|
//#region src/core/history-pager.ts
|
|
1050
|
-
function
|
|
1475
|
+
function K() {
|
|
1051
1476
|
return {
|
|
1052
1477
|
oldestCursor: null,
|
|
1053
1478
|
hasMore: !1,
|
|
1054
1479
|
cursorReady: !1
|
|
1055
1480
|
};
|
|
1056
1481
|
}
|
|
1057
|
-
function
|
|
1482
|
+
function xe(e) {
|
|
1058
1483
|
return {
|
|
1059
1484
|
oldestCursor: e.messages[0]?.id ?? null,
|
|
1060
1485
|
hasMore: e.hasMore,
|
|
1061
1486
|
cursorReady: e.messages.length > 0
|
|
1062
1487
|
};
|
|
1063
1488
|
}
|
|
1064
|
-
function
|
|
1489
|
+
function Se(e, t) {
|
|
1065
1490
|
return {
|
|
1066
1491
|
oldestCursor: t.messages[0]?.id ?? e.oldestCursor,
|
|
1067
1492
|
hasMore: t.hasMore,
|
|
1068
1493
|
cursorReady: e.cursorReady
|
|
1069
1494
|
};
|
|
1070
1495
|
}
|
|
1071
|
-
function
|
|
1496
|
+
function Ce(e, t) {
|
|
1072
1497
|
return e.cursorReady && e.hasMore && !t && e.oldestCursor !== null;
|
|
1073
1498
|
}
|
|
1074
|
-
function
|
|
1499
|
+
function we(e, t, n) {
|
|
1075
1500
|
return e + (n - t);
|
|
1076
1501
|
}
|
|
1077
1502
|
//#endregion
|
|
1078
1503
|
//#region src/core/confirm-dialog.ts
|
|
1079
|
-
function
|
|
1504
|
+
function q(e) {
|
|
1080
1505
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1081
1506
|
}
|
|
1082
|
-
function
|
|
1507
|
+
function Te(e, t) {
|
|
1083
1508
|
let n = t.labels?.confirm ?? "Đồng ý", r = t.labels?.cancel ?? "Huỷ", i = t.labels?.countdownPrefix ?? "Tự động xác nhận sau ", a = t.labels?.countdownSuffix ?? "s…";
|
|
1084
1509
|
return new Promise((o) => {
|
|
1085
1510
|
let s = document.createElement("div");
|
|
1086
1511
|
s.className = "botiq-confirm-overlay", s.innerHTML = `
|
|
1087
1512
|
<div class="botiq-confirm-dialog" role="dialog" aria-modal="true">
|
|
1088
|
-
<div class="botiq-confirm-header">${
|
|
1513
|
+
<div class="botiq-confirm-header">${q(t.title)}</div>
|
|
1089
1514
|
<div class="botiq-confirm-body">
|
|
1090
|
-
<div class="botiq-confirm-reason">${
|
|
1091
|
-
<pre class="botiq-confirm-params">${
|
|
1515
|
+
<div class="botiq-confirm-reason">${q(t.reason)}</div>
|
|
1516
|
+
<pre class="botiq-confirm-params">${q(t.paramsDisplay)}</pre>
|
|
1092
1517
|
</div>
|
|
1093
1518
|
<div class="botiq-confirm-actions">
|
|
1094
|
-
<button class="botiq-confirm-yes" data-risk="${t.riskLevel}" type="button">${
|
|
1095
|
-
<button class="botiq-confirm-no" type="button">${
|
|
1519
|
+
<button class="botiq-confirm-yes" data-risk="${t.riskLevel}" type="button">${q(n)}</button>
|
|
1520
|
+
<button class="botiq-confirm-no" type="button">${q(r)}</button>
|
|
1096
1521
|
</div>
|
|
1097
|
-
${t.autoConfirmAfterSec ? `<div class="botiq-confirm-countdown">${
|
|
1522
|
+
${t.autoConfirmAfterSec ? `<div class="botiq-confirm-countdown">${q(i)}<span class="botiq-confirm-secs">${t.autoConfirmAfterSec}</span>${q(a)}</div>` : ""}
|
|
1098
1523
|
</div>`, e.appendChild(s);
|
|
1099
1524
|
let c = !1, l = null, u = (t) => {
|
|
1100
1525
|
c || (c = !0, l && clearInterval(l), e.removeChild(s), o(t));
|
|
@@ -1109,15 +1534,15 @@ function me(e, t) {
|
|
|
1109
1534
|
}
|
|
1110
1535
|
//#endregion
|
|
1111
1536
|
//#region src/core/emoji.ts
|
|
1112
|
-
function
|
|
1537
|
+
function Ee(e, t) {
|
|
1113
1538
|
let n = e.selectionStart ?? e.value.length, r = e.selectionEnd ?? e.value.length;
|
|
1114
1539
|
e.value = e.value.slice(0, n) + t + e.value.slice(r), e.selectionStart = e.selectionEnd = n + t.length, e.dispatchEvent(new Event("input", { bubbles: !0 }));
|
|
1115
1540
|
}
|
|
1116
|
-
var
|
|
1117
|
-
async function
|
|
1118
|
-
return
|
|
1541
|
+
var J = null;
|
|
1542
|
+
async function De() {
|
|
1543
|
+
return J || (J = (await import("./emoji-data-DWiYsBZI.js")).EMOJIS, J);
|
|
1119
1544
|
}
|
|
1120
|
-
function
|
|
1545
|
+
function Oe(e) {
|
|
1121
1546
|
let t = document.createElement("button");
|
|
1122
1547
|
t.type = "button", t.className = "emoji-btn", t.setAttribute("aria-label", "Emoji"), t.textContent = "🙂";
|
|
1123
1548
|
let n = document.createElement("div");
|
|
@@ -1125,7 +1550,7 @@ function _e(e) {
|
|
|
1125
1550
|
let r = !1;
|
|
1126
1551
|
return t.addEventListener("click", async () => {
|
|
1127
1552
|
if (!r) {
|
|
1128
|
-
let t = await
|
|
1553
|
+
let t = await De();
|
|
1129
1554
|
for (let r of t) {
|
|
1130
1555
|
let t = document.createElement("button");
|
|
1131
1556
|
t.type = "button", t.className = "emoji-item", t.textContent = r, t.addEventListener("click", () => {
|
|
@@ -1141,45 +1566,95 @@ function _e(e) {
|
|
|
1141
1566
|
};
|
|
1142
1567
|
}
|
|
1143
1568
|
//#endregion
|
|
1569
|
+
//#region src/core/blocks-renderer.ts
|
|
1570
|
+
function Y(e) {
|
|
1571
|
+
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1572
|
+
}
|
|
1573
|
+
function X(e) {
|
|
1574
|
+
return /^https?:\/\//i.test(e) ? e : "";
|
|
1575
|
+
}
|
|
1576
|
+
function ke(e) {
|
|
1577
|
+
let t = Y(e.label), n = Y(e.value), r = Y(e.action);
|
|
1578
|
+
if (e.action === "url") {
|
|
1579
|
+
let n = X(e.value);
|
|
1580
|
+
return n ? `<a class="biq-btn biq-btn--url" href="${Y(n)}" target="_blank" rel="noopener noreferrer">${t}</a>` : "";
|
|
1581
|
+
}
|
|
1582
|
+
return `<button class="biq-btn biq-btn--${r}" type="button" data-action="${r}" data-value="${n}">${t}</button>`;
|
|
1583
|
+
}
|
|
1584
|
+
function Ae(e) {
|
|
1585
|
+
let t = `${e.imageUrl ? (() => {
|
|
1586
|
+
let t = X(e.imageUrl);
|
|
1587
|
+
return t ? `<img class="biq-card-img" src="${Y(t)}" alt="" loading="lazy" />` : "";
|
|
1588
|
+
})() : ""}${`<div class="biq-card-title">${Y(e.title)}</div>`}${e.subtitle ? `<div class="biq-card-subtitle">${Y(e.subtitle)}</div>` : ""}${e.price ? `<div class="biq-card-price">${Y(e.price)}</div>` : ""}${e.buttons && e.buttons.length > 0 ? `<div class="biq-card-btns">${e.buttons.map(ke).join("")}</div>` : ""}`;
|
|
1589
|
+
if (e.url) {
|
|
1590
|
+
let n = X(e.url);
|
|
1591
|
+
if (n) return `<a class="biq-card biq-card--link" href="${Y(n)}" target="_blank" rel="noopener noreferrer">${t}</a>`;
|
|
1592
|
+
}
|
|
1593
|
+
return `<div class="biq-card">${t}</div>`;
|
|
1594
|
+
}
|
|
1595
|
+
function je(e) {
|
|
1596
|
+
return `<div class="biq-carousel">${e.cards.map(Ae).join("")}</div>`;
|
|
1597
|
+
}
|
|
1598
|
+
function Me(e) {
|
|
1599
|
+
return `<div class="biq-quick-replies">${e.replies.map((e) => {
|
|
1600
|
+
let t = Y(e.label);
|
|
1601
|
+
return `<button class="biq-qr-pill" type="button" data-qr="1" data-value="${Y(e.value)}">${t}</button>`;
|
|
1602
|
+
}).join("")}</div>`;
|
|
1603
|
+
}
|
|
1604
|
+
function Ne(e) {
|
|
1605
|
+
return `<div class="biq-buttons">${e.buttons.map(ke).join("")}</div>`;
|
|
1606
|
+
}
|
|
1607
|
+
function Pe(e) {
|
|
1608
|
+
return !e || e.length === 0 ? "" : e.map((e) => {
|
|
1609
|
+
switch (e.type) {
|
|
1610
|
+
case "card": return Ae(e);
|
|
1611
|
+
case "carousel": return je(e);
|
|
1612
|
+
case "quick_replies": return Me(e);
|
|
1613
|
+
case "buttons": return Ne(e);
|
|
1614
|
+
default: return "";
|
|
1615
|
+
}
|
|
1616
|
+
}).join("");
|
|
1617
|
+
}
|
|
1618
|
+
//#endregion
|
|
1144
1619
|
//#region src/core/ui.ts
|
|
1145
|
-
var
|
|
1146
|
-
function
|
|
1147
|
-
if (!e || e.type === "icon") return
|
|
1148
|
-
if (e.type === "emoji") return `<span style="font-size:22px;line-height:1;display:flex;align-items:center;justify-content:center;width:100%;height:100%">${
|
|
1620
|
+
var Fe = "https://bot-q-frontend.vercel.app/", Ie = "<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M20 2H4a2 2 0 00-2 2v18l4-4h14a2 2 0 002-2V4a2 2 0 00-2-2z\"/>\n</svg>", Le = "<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/>\n</svg>", Re = `<img src="${be}" alt="" style="width:100%;height:100%;object-fit:cover;border-radius:50%" />`, ze = "<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M2.01 21L23 12 2.01 3 2 10l15 2-15 2z\"/>\n</svg>", Be = "<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M20 2H4a2 2 0 00-2 2v18l4-4h14a2 2 0 002-2V4a2 2 0 00-2-2zm-2 10H6v-2h12v2zm0-3H6V7h12v2z\"/>\n</svg>", Ve = "<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48\"/>\n</svg>", He = "<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z\"/></svg>", Ue = "<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M20 2H4c-1.1 0-2 .9-2 2v18l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2z\"/></svg>";
|
|
1621
|
+
function We(e) {
|
|
1622
|
+
if (!e || e.type === "icon") return Re;
|
|
1623
|
+
if (e.type === "emoji") return `<span style="font-size:22px;line-height:1;display:flex;align-items:center;justify-content:center;width:100%;height:100%">${Z(e.value)}</span>`;
|
|
1149
1624
|
if (e.type === "initials") {
|
|
1150
1625
|
let t = e.bgColor ?? "#F97316";
|
|
1151
|
-
return `<div style="width:100%;height:100%;border-radius:50%;background:${/^#[0-9A-Fa-f]{3,6}$/.test(t) ? t : "#F97316"};display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;color:#fff">${
|
|
1626
|
+
return `<div style="width:100%;height:100%;border-radius:50%;background:${/^#[0-9A-Fa-f]{3,6}$/.test(t) ? t : "#F97316"};display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:700;color:#fff">${Z(e.value.slice(0, 2).toUpperCase())}</div>`;
|
|
1152
1627
|
}
|
|
1153
|
-
return e.type === "image" ? `<img src="${
|
|
1628
|
+
return e.type === "image" ? `<img src="${Z(e.value)}" style="width:100%;height:100%;object-fit:cover;border-radius:50%" alt="" />` : Re;
|
|
1154
1629
|
}
|
|
1155
|
-
function
|
|
1630
|
+
function Z(e) {
|
|
1156
1631
|
return e.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1157
1632
|
}
|
|
1158
|
-
function
|
|
1633
|
+
function Q(e) {
|
|
1159
1634
|
let t = [];
|
|
1160
1635
|
return e = e.replace(/`([^`]+)`/g, (e, n) => (t.push(`<code>${n}</code>`), `\x00CODE${t.length - 1}\x00`)), e = e.replace(/\*\*\*(.+?)\*\*\*/g, "<strong><em>$1</em></strong>"), e = e.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>"), e = e.replace(/(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)/g, "<em>$1</em>"), e = e.replace(/~~(.+?)~~/g, "<del>$1</del>"), e = e.replace(/__(.+?)__/g, "<strong>$1</strong>"), e = e.replace(/(^|\s)_(?!_)(.+?)_(?!_)(?=\s|$)/g, "$1<em>$2</em>"), e = e.replace(/\[([^\]]+)\]\(([^()]*(?:\([^()]*\))*[^()]*)\)/g, (e, t, n) => /^https?:\/\//.test(n) ? `<a href="${n}" target="_blank" rel="noopener noreferrer">${t}</a>` : t), e = e.replace(/\x00CODE(\d+)\x00/g, (e, n) => t[Number(n)]), e;
|
|
1161
1636
|
}
|
|
1162
|
-
function
|
|
1637
|
+
function Ge(e) {
|
|
1163
1638
|
return /^\|[\s\-:|]+\|$/.test(e);
|
|
1164
1639
|
}
|
|
1165
|
-
function
|
|
1640
|
+
function Ke(e) {
|
|
1166
1641
|
return e.replace(/^\|/, "").replace(/\|$/, "").split("|").map((e) => e.trim());
|
|
1167
1642
|
}
|
|
1168
|
-
function
|
|
1169
|
-
return e ? `<div class="handoff-banner">⏳ ${
|
|
1643
|
+
function qe(e, t) {
|
|
1644
|
+
return e ? `<div class="handoff-banner">⏳ ${Z(t.waitingForHuman)}</div>` : "";
|
|
1170
1645
|
}
|
|
1171
|
-
function
|
|
1646
|
+
function Je(e) {
|
|
1172
1647
|
return e <= 0 ? "" : `<span class="unread-badge">${e > 9 ? "9+" : String(e)}</span>`;
|
|
1173
1648
|
}
|
|
1174
|
-
function
|
|
1175
|
-
let t =
|
|
1649
|
+
function Ye(e) {
|
|
1650
|
+
let t = Z(e).replace(/\x00/g, "").split("\n"), n = [], r = 0;
|
|
1176
1651
|
for (; r < t.length;) {
|
|
1177
1652
|
let e = t[r].trim();
|
|
1178
1653
|
if (e.startsWith("|") && e.endsWith("|")) {
|
|
1179
1654
|
let e = [];
|
|
1180
1655
|
for (; r < t.length && t[r].trim().startsWith("|") && t[r].trim().endsWith("|");) e.push(t[r].trim()), r++;
|
|
1181
|
-
let i = e.findIndex(
|
|
1182
|
-
a.length > 0 && (s += "<thead>" + a.map((e) => "<tr>" +
|
|
1656
|
+
let i = e.findIndex(Ge), a = i > 0 ? e.slice(0, i) : [], o = i >= 0 ? e.slice(i + 1) : e, s = "<table>";
|
|
1657
|
+
a.length > 0 && (s += "<thead>" + a.map((e) => "<tr>" + Ke(e).map((e) => `<th>${Q(e)}</th>`).join("") + "</tr>").join("") + "</thead>"), o.length > 0 && (s += "<tbody>" + o.map((e) => "<tr>" + Ke(e).map((e) => `<td>${Q(e)}</td>`).join("") + "</tr>").join("") + "</tbody>"), s += "</table>", n.push(s);
|
|
1183
1658
|
continue;
|
|
1184
1659
|
}
|
|
1185
1660
|
if (/^-{3,}$/.test(e)) {
|
|
@@ -1189,67 +1664,67 @@ function De(e) {
|
|
|
1189
1664
|
let i = e.match(/^(#{1,6})\s+(.*)$/);
|
|
1190
1665
|
if (i) {
|
|
1191
1666
|
let e = i[1].length;
|
|
1192
|
-
n.push(`<h${e}>${
|
|
1667
|
+
n.push(`<h${e}>${Q(i[2])}</h${e}>`), r++;
|
|
1193
1668
|
continue;
|
|
1194
1669
|
}
|
|
1195
1670
|
if (/^[-*]\s/.test(e)) {
|
|
1196
1671
|
let e = [];
|
|
1197
1672
|
for (; r < t.length && /^\s*[-*]\s/.test(t[r]);) e.push(t[r].trim().replace(/^[-*]\s+/, "")), r++;
|
|
1198
|
-
n.push("<ul>" + e.map((e) => `<li>${
|
|
1673
|
+
n.push("<ul>" + e.map((e) => `<li>${Q(e)}</li>`).join("") + "</ul>");
|
|
1199
1674
|
continue;
|
|
1200
1675
|
}
|
|
1201
1676
|
if (/^\d+\.\s/.test(e)) {
|
|
1202
1677
|
let e = [];
|
|
1203
1678
|
for (; r < t.length && /^\s*\d+\.\s/.test(t[r]);) e.push(t[r].trim().replace(/^\d+\.\s+/, "")), r++;
|
|
1204
|
-
n.push("<ol>" + e.map((e) => `<li>${
|
|
1679
|
+
n.push("<ol>" + e.map((e) => `<li>${Q(e)}</li>`).join("") + "</ol>");
|
|
1205
1680
|
continue;
|
|
1206
1681
|
}
|
|
1207
1682
|
if (e === "") {
|
|
1208
1683
|
n.push("<br>"), r++;
|
|
1209
1684
|
continue;
|
|
1210
1685
|
}
|
|
1211
|
-
n.push(
|
|
1686
|
+
n.push(Q(e)), n.push("<br>"), r++;
|
|
1212
1687
|
}
|
|
1213
1688
|
for (; n.length > 0 && n[n.length - 1] === "<br>";) n.pop();
|
|
1214
1689
|
return n.join("");
|
|
1215
1690
|
}
|
|
1216
|
-
function
|
|
1217
|
-
let { strings: n, content: r, botName: i, lang: a, now: o, contactInfo: s } = t;
|
|
1691
|
+
function Xe(e, t) {
|
|
1692
|
+
let { strings: n, content: r, botName: i, lang: a, now: o, contactInfo: s, richMessages: c } = t;
|
|
1218
1693
|
if (e.messages.length === 0 && !e.isLoading) {
|
|
1219
|
-
let e = r.suggestionChips.length > 0 ? `<div class="chips">${r.suggestionChips.map((e) => `<button class="chip">${
|
|
1694
|
+
let e = r.suggestionChips.length > 0 ? `<div class="chips">${r.suggestionChips.map((e) => `<button class="chip">${Z(e)}</button>`).join("")}</div>` : "";
|
|
1220
1695
|
return `
|
|
1221
1696
|
<div class="empty-state">
|
|
1222
|
-
${
|
|
1223
|
-
<span class="greeting">${
|
|
1697
|
+
${Be}
|
|
1698
|
+
<span class="greeting">${Z(r.greeting || n.defaultGreeting)}</span>
|
|
1224
1699
|
${e}
|
|
1225
1700
|
</div>
|
|
1226
1701
|
`;
|
|
1227
1702
|
}
|
|
1228
|
-
let
|
|
1229
|
-
let t = e.ts ?? o, r =
|
|
1230
|
-
|
|
1231
|
-
let
|
|
1232
|
-
return `${
|
|
1233
|
-
}).join(""),
|
|
1234
|
-
return
|
|
1235
|
-
}
|
|
1236
|
-
function
|
|
1237
|
-
let { name: i, design: a } = t, o, s, c, l, u, d, f, p, m, h, g, _, { content:
|
|
1238
|
-
function
|
|
1703
|
+
let l = "", u = e.messages.map((e) => {
|
|
1704
|
+
let t = e.ts ?? o, r = _e(t, o, a), u = r === l ? "" : `<div class="day-sep"><span>${Z(r)}</span></div>`;
|
|
1705
|
+
l = r;
|
|
1706
|
+
let d = e.role === "assistant" ? Ye(e.content) : Z(e.content), f = e.role === "assistant" && !e.error ? `<div class="msg-meta">${Z(i)} · ${Z(W(t, o, a))}</div>` : "", p = e.error ? `<button class="retry-btn" type="button">↻ ${Z(n.retry)}</button>` : "", m = e.error && s ? `<div class="msg-contact">${Z(s)}</div>` : "", h = c && e.role === "assistant" && !e.error && e.blocks && e.blocks.length > 0 ? `<div class="biq-blocks">${Pe(e.blocks)}</div>` : "";
|
|
1707
|
+
return `${u}<div class="${`message ${e.role}${e.error ? " error" : ""}`}"><div class="message-bubble">${d}</div>${p}${m}${f}${h}</div>`;
|
|
1708
|
+
}).join(""), d = e.loadingOlder ? "<div class=\"typing\"><span></span><span></span><span></span></div>" : "", f = e.isLoading ? "<div class=\"typing\"><span></span><span></span><span></span></div>" : "";
|
|
1709
|
+
return d + u + f;
|
|
1710
|
+
}
|
|
1711
|
+
function Ze(e, t, n, r) {
|
|
1712
|
+
let { name: i, design: a } = t, o, s, c, l, u, d, f, p, m, h, g, _, v = null, y = null, b = null, { content: x } = a, S = t.imageInput === !0, C = We(a.avatar), w = null;
|
|
1713
|
+
function T(e) {
|
|
1239
1714
|
e.setAttribute("data-position", a.layout.position), o = e.attachShadow({ mode: "closed" });
|
|
1240
|
-
let
|
|
1241
|
-
|
|
1242
|
-
<span class="icon-chat">${
|
|
1243
|
-
<span class="icon-close">${
|
|
1715
|
+
let w = document.createElement("style");
|
|
1716
|
+
w.textContent = ge(a), o.appendChild(w), s = document.createElement("button"), s.className = "bubble", s.setAttribute("aria-label", n.ariaOpenChat), s.innerHTML = `
|
|
1717
|
+
<span class="icon-chat">${Ie}</span>
|
|
1718
|
+
<span class="icon-close">${Le}</span>
|
|
1244
1719
|
<span class="unread-badge-slot"></span>
|
|
1245
1720
|
`, s.addEventListener("click", () => r.onToggle()), o.appendChild(s), c = document.createElement("div"), c.className = "chat-window", c.setAttribute("role", "dialog"), c.setAttribute("aria-label", `${i} chat`), c.innerHTML = `
|
|
1246
1721
|
<div class="chat-header">
|
|
1247
|
-
<div class="avatar">${
|
|
1722
|
+
<div class="avatar">${We(a.avatar)}</div>
|
|
1248
1723
|
<div class="header-text">
|
|
1249
|
-
<span class="bot-name">${
|
|
1250
|
-
<span class="bot-status">${
|
|
1724
|
+
<span class="bot-name">${Z(i)}</span>
|
|
1725
|
+
<span class="bot-status">${Z(t.status === "offline" ? n.statusPaused : n.statusOnline)}</span>
|
|
1251
1726
|
</div>
|
|
1252
|
-
<button class="close-btn" aria-label="${
|
|
1727
|
+
<button class="close-btn" aria-label="${Z(n.ariaCloseChat)}">×</button>
|
|
1253
1728
|
</div>
|
|
1254
1729
|
<div class="chat-body">
|
|
1255
1730
|
<div class="panel panel-home"></div>
|
|
@@ -1258,29 +1733,31 @@ function ke(e, t, n, r) {
|
|
|
1258
1733
|
<div class="messages" id="messages-container" role="log" aria-live="polite" aria-atomic="false"></div>
|
|
1259
1734
|
<div class="handoff-slot"></div>
|
|
1260
1735
|
<div class="chat-footer">
|
|
1736
|
+
<div class="attach-preview-slot"></div>
|
|
1261
1737
|
<div class="input-row">
|
|
1738
|
+
${S ? `<button class="attach-btn" type="button" aria-label="${Z(n.imageAttach)}">${Ve}</button>` : ""}
|
|
1262
1739
|
<textarea
|
|
1263
1740
|
class="input"
|
|
1264
|
-
placeholder="${
|
|
1741
|
+
placeholder="${Z(x.placeholder || n.inputPlaceholder)}"
|
|
1265
1742
|
rows="1"
|
|
1266
1743
|
maxlength="2000"
|
|
1267
1744
|
aria-label="Message input"
|
|
1268
1745
|
></textarea>
|
|
1269
|
-
<button class="send-btn" aria-label="${
|
|
1270
|
-
${
|
|
1746
|
+
<button class="send-btn" aria-label="${Z(n.ariaSendMessage)}">
|
|
1747
|
+
${ze}
|
|
1271
1748
|
</button>
|
|
1272
1749
|
</div>
|
|
1273
|
-
<a class="botiq-badge" href="${ve}" target="_blank" rel="noopener noreferrer">
|
|
1274
|
-
${q(n.poweredBy)} <span class="botiq-badge-name">BotIQ</span>
|
|
1275
|
-
</a>
|
|
1276
1750
|
</div>
|
|
1277
1751
|
</div>
|
|
1278
1752
|
</div>
|
|
1279
1753
|
<div class="bottom-nav">
|
|
1280
|
-
<button class="nav-btn" data-view="home"
|
|
1281
|
-
<button class="nav-btn" data-view="messages"
|
|
1754
|
+
<button class="nav-btn" data-view="home">${He}<span>${Z(n.navHome)}</span></button>
|
|
1755
|
+
<button class="nav-btn" data-view="messages">${Ue}<span>${Z(n.navMessages)}</span></button>
|
|
1282
1756
|
</div>
|
|
1283
|
-
|
|
1757
|
+
<a class="botiq-badge" href="${Fe}" target="_blank" rel="noopener noreferrer">
|
|
1758
|
+
${Z(n.poweredBy)} <span class="botiq-badge-name">BotIQ</span>
|
|
1759
|
+
</a>
|
|
1760
|
+
`, c.querySelector(".close-btn").addEventListener("click", () => r.onToggle()), l = c.querySelector(".panel-home"), u = c.querySelector(".panel-messages"), d = c.querySelector(".panel-conversation"), l.innerHTML = ye(t, n, [], C), l.querySelector(".home-start")?.addEventListener("click", () => {
|
|
1284
1761
|
r.onNewConversation();
|
|
1285
1762
|
}), f = c.querySelector(".nav-btn[data-view=\"home\"]"), p = c.querySelector(".nav-btn[data-view=\"messages\"]"), c.querySelectorAll(".nav-btn").forEach((e) => {
|
|
1286
1763
|
e.addEventListener("click", () => {
|
|
@@ -1288,44 +1765,105 @@ function ke(e, t, n, r) {
|
|
|
1288
1765
|
r.onNavigate(t);
|
|
1289
1766
|
});
|
|
1290
1767
|
}), m = c.querySelector("#messages-container"), h = c.querySelector(".handoff-slot");
|
|
1291
|
-
let
|
|
1768
|
+
let T = null;
|
|
1292
1769
|
m.addEventListener("scroll", () => {
|
|
1293
|
-
m.scrollTop <= 48 && !
|
|
1294
|
-
|
|
1770
|
+
m.scrollTop <= 48 && !T && (T = setTimeout(() => {
|
|
1771
|
+
T = null;
|
|
1295
1772
|
}, 150), r.onScrollTop());
|
|
1296
1773
|
}), g = c.querySelector(".input"), _ = c.querySelector(".send-btn"), g.addEventListener("input", () => {
|
|
1297
1774
|
g.style.height = "auto", g.style.height = Math.min(g.scrollHeight, 100) + "px";
|
|
1298
1775
|
}), g.addEventListener("keydown", (e) => {
|
|
1299
|
-
e.key === "Enter" && !e.shiftKey && (e.preventDefault(),
|
|
1300
|
-
}), _.addEventListener("click",
|
|
1301
|
-
let
|
|
1302
|
-
|
|
1776
|
+
e.key === "Enter" && !e.shiftKey && (e.preventDefault(), E());
|
|
1777
|
+
}), _.addEventListener("click", E);
|
|
1778
|
+
let D = c.querySelector(".input-row"), { button: O, panel: k } = Oe((e) => {
|
|
1779
|
+
Ee(g, e), g.focus();
|
|
1303
1780
|
});
|
|
1304
|
-
|
|
1781
|
+
D.insertBefore(O, _), c.querySelector(".chat-footer").appendChild(k), y = c.querySelector(".attach-preview-slot"), S && (v = c.querySelector(".attach-btn"), v && (b = document.createElement("input"), b.type = "file", b.accept = "image/jpeg,image/png,image/webp", b.style.display = "none", b.setAttribute("aria-hidden", "true"), o.appendChild(b), v.addEventListener("click", () => {
|
|
1782
|
+
b?.click();
|
|
1783
|
+
}), b.addEventListener("change", () => {
|
|
1784
|
+
let e = b?.files?.[0];
|
|
1785
|
+
e && r.onAttachImage && (r.onAttachImage(e), b && (b.value = ""));
|
|
1786
|
+
}))), o.appendChild(c);
|
|
1305
1787
|
}
|
|
1306
|
-
function
|
|
1788
|
+
function E() {
|
|
1307
1789
|
let e = g.value.trim();
|
|
1308
|
-
!e || _.disabled || (g.value = "", g.style.height = "auto", r.onSend(e));
|
|
1790
|
+
!e && !y?.querySelector(".attach-preview") || _.disabled || (g.value = "", g.style.height = "auto", r.onSend(e));
|
|
1309
1791
|
}
|
|
1310
|
-
function
|
|
1792
|
+
function D(e) {
|
|
1311
1793
|
let a = m.scrollHeight - m.scrollTop - m.clientHeight < 80, o = m.scrollTop, s = m.scrollHeight;
|
|
1312
|
-
m.innerHTML =
|
|
1794
|
+
m.innerHTML = Xe(e, {
|
|
1313
1795
|
strings: n,
|
|
1314
|
-
content:
|
|
1796
|
+
content: x,
|
|
1315
1797
|
botName: i,
|
|
1316
1798
|
lang: t.widgetLanguage,
|
|
1317
1799
|
now: Date.now(),
|
|
1318
|
-
contactInfo: t.contactInfo
|
|
1800
|
+
contactInfo: t.contactInfo,
|
|
1801
|
+
richMessages: t.richMessages
|
|
1319
1802
|
}), m.querySelectorAll(".chip").forEach((e) => {
|
|
1320
1803
|
e.addEventListener("click", () => r.onSend(e.textContent ?? ""));
|
|
1321
1804
|
}), m.querySelectorAll(".retry-btn").forEach((e) => {
|
|
1322
1805
|
e.addEventListener("click", () => r.onRetry());
|
|
1323
|
-
}),
|
|
1806
|
+
}), m.querySelectorAll(".biq-btn[data-action=\"send\"]").forEach((e) => {
|
|
1807
|
+
e.addEventListener("click", () => {
|
|
1808
|
+
let t = e.dataset.value ?? "";
|
|
1809
|
+
if (t) {
|
|
1810
|
+
r.onSend(t);
|
|
1811
|
+
let n = e.closest(".biq-blocks");
|
|
1812
|
+
n && (n.style.pointerEvents = "none", n.style.opacity = "0.5");
|
|
1813
|
+
}
|
|
1814
|
+
});
|
|
1815
|
+
}), m.querySelectorAll(".biq-btn[data-action=\"page_action\"]").forEach((e) => {
|
|
1816
|
+
e.addEventListener("click", () => {
|
|
1817
|
+
let t = e.dataset.value ?? "";
|
|
1818
|
+
if (t && r.onBlockPageAction) {
|
|
1819
|
+
let n = e.closest(".biq-blocks");
|
|
1820
|
+
n && (n.style.pointerEvents = "none", n.style.opacity = "0.5"), r.onBlockPageAction(t);
|
|
1821
|
+
}
|
|
1822
|
+
});
|
|
1823
|
+
}), m.querySelectorAll(".biq-qr-pill[data-qr=\"1\"]").forEach((e) => {
|
|
1824
|
+
e.addEventListener("click", () => {
|
|
1825
|
+
let t = e.dataset.value ?? "";
|
|
1826
|
+
if (t) {
|
|
1827
|
+
r.onSend(t);
|
|
1828
|
+
let n = e.closest(".biq-quick-replies");
|
|
1829
|
+
n && (n.style.display = "none");
|
|
1830
|
+
}
|
|
1831
|
+
});
|
|
1832
|
+
}), a ? m.scrollTop = m.scrollHeight : m.scrollTop = we(o, s, m.scrollHeight);
|
|
1324
1833
|
}
|
|
1325
|
-
function
|
|
1834
|
+
function O(e) {
|
|
1326
1835
|
e.isOpen ? (c.classList.add("open"), s.classList.add("open"), s.setAttribute("aria-label", n.ariaCloseChat), e.view === "conversation" && requestAnimationFrame(() => g.focus())) : (c.classList.remove("open"), s.classList.remove("open"), s.setAttribute("aria-label", n.ariaOpenChat));
|
|
1327
|
-
let
|
|
1328
|
-
|
|
1836
|
+
let i = s.querySelector(".unread-badge-slot");
|
|
1837
|
+
if (i && (i.innerHTML = Je(e.unreadCount)), _.disabled = e.isLoading || e.isUploading, y && S) if (e.pendingAttachment) {
|
|
1838
|
+
let t = e.pendingAttachment, i = e.isUploading, a = e.uploadError;
|
|
1839
|
+
y.innerHTML = `
|
|
1840
|
+
<div class="attach-preview">
|
|
1841
|
+
<img
|
|
1842
|
+
src="${Z(t.previewUrl)}"
|
|
1843
|
+
alt="Preview"
|
|
1844
|
+
class="attach-preview-img${i ? " attach-preview-img--uploading" : ""}"
|
|
1845
|
+
/>
|
|
1846
|
+
${i ? `<span class="attach-preview-status">${Z(n.imageUploading)}</span>` : ""}
|
|
1847
|
+
${a ? `<span class="attach-preview-error">${Z(a)}</span>` : ""}
|
|
1848
|
+
${i ? "" : `<button class="attach-preview-remove" type="button" aria-label="${Z(n.imageRemove)}">×</button>`}
|
|
1849
|
+
</div>
|
|
1850
|
+
`, y.querySelector(".attach-preview-remove")?.addEventListener("click", () => {
|
|
1851
|
+
r.onRemoveAttachment?.();
|
|
1852
|
+
});
|
|
1853
|
+
} else y.innerHTML = "";
|
|
1854
|
+
if (c.dataset.view = e.view, l.classList.toggle("active", e.view === "home"), u.classList.toggle("active", e.view === "messages"), d.classList.toggle("active", e.view === "conversation"), f.classList.toggle("active", e.view === "home"), p.classList.toggle("active", e.view === "messages"), e.view === "home" && e.conversations !== w) {
|
|
1855
|
+
w = e.conversations;
|
|
1856
|
+
let i = Date.now();
|
|
1857
|
+
l.innerHTML = ye(t, n, e.conversations, C, i), l.querySelector(".home-start")?.addEventListener("click", () => {
|
|
1858
|
+
r.onNewConversation();
|
|
1859
|
+
}), l.querySelectorAll(".home-recent-item").forEach((e) => {
|
|
1860
|
+
e.addEventListener("click", () => {
|
|
1861
|
+
let t = e.dataset.session;
|
|
1862
|
+
t && r.onOpenConversation(t);
|
|
1863
|
+
});
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
e.view === "conversation" && (D(e), h.innerHTML = qe(e.escalated, n)), e.view === "messages" && (u.innerHTML = ve(e.conversations, n, Date.now(), C), u.querySelectorAll(".msg-list-item").forEach((e) => {
|
|
1329
1867
|
e.addEventListener("click", () => {
|
|
1330
1868
|
let t = e.dataset.session;
|
|
1331
1869
|
t && r.onOpenConversation(t);
|
|
@@ -1334,8 +1872,8 @@ function ke(e, t, n, r) {
|
|
|
1334
1872
|
r.onNewConversation();
|
|
1335
1873
|
}));
|
|
1336
1874
|
}
|
|
1337
|
-
function
|
|
1338
|
-
return
|
|
1875
|
+
function k(e) {
|
|
1876
|
+
return Te(o, {
|
|
1339
1877
|
...e,
|
|
1340
1878
|
labels: {
|
|
1341
1879
|
confirm: n.confirmYes,
|
|
@@ -1346,14 +1884,14 @@ function ke(e, t, n, r) {
|
|
|
1346
1884
|
});
|
|
1347
1885
|
}
|
|
1348
1886
|
return {
|
|
1349
|
-
mount:
|
|
1350
|
-
update:
|
|
1351
|
-
confirmAction:
|
|
1887
|
+
mount: T,
|
|
1888
|
+
update: O,
|
|
1889
|
+
confirmAction: k
|
|
1352
1890
|
};
|
|
1353
1891
|
}
|
|
1354
1892
|
//#endregion
|
|
1355
1893
|
//#region src/i18n/vi.ts
|
|
1356
|
-
var
|
|
1894
|
+
var Qe = {
|
|
1357
1895
|
statusOnline: "Trực tuyến",
|
|
1358
1896
|
statusPaused: "Tạm ngừng",
|
|
1359
1897
|
navHome: "Trang chủ",
|
|
@@ -1385,8 +1923,16 @@ var Ae = {
|
|
|
1385
1923
|
confirmNo: "Huỷ",
|
|
1386
1924
|
confirmCountdownPrefix: "Tự động xác nhận sau ",
|
|
1387
1925
|
confirmCountdownSuffix: "s…",
|
|
1388
|
-
retry: "Thử lại"
|
|
1389
|
-
|
|
1926
|
+
retry: "Thử lại",
|
|
1927
|
+
recentMessages: "Tin nhắn gần đây",
|
|
1928
|
+
imageAttach: "Đính kèm ảnh",
|
|
1929
|
+
imageRemove: "Xóa ảnh",
|
|
1930
|
+
imageUploading: "Đang tải ảnh…",
|
|
1931
|
+
imageUploadPlanError: "Gói hiện tại không hỗ trợ gửi ảnh.",
|
|
1932
|
+
imageUploadTooLarge: "Ảnh quá lớn (tối đa 5 MB sau khi nén).",
|
|
1933
|
+
imageUploadRateLimit: "Gửi quá nhanh. Vui lòng thử lại.",
|
|
1934
|
+
imageUploadError: "Tải ảnh thất bại. Vui lòng thử lại."
|
|
1935
|
+
}, $e = {
|
|
1390
1936
|
statusOnline: "Online",
|
|
1391
1937
|
statusPaused: "Paused",
|
|
1392
1938
|
navHome: "Home",
|
|
@@ -1418,24 +1964,32 @@ var Ae = {
|
|
|
1418
1964
|
confirmNo: "Cancel",
|
|
1419
1965
|
confirmCountdownPrefix: "Auto-confirming in ",
|
|
1420
1966
|
confirmCountdownSuffix: "s…",
|
|
1421
|
-
retry: "Retry"
|
|
1967
|
+
retry: "Retry",
|
|
1968
|
+
recentMessages: "Recent messages",
|
|
1969
|
+
imageAttach: "Attach image",
|
|
1970
|
+
imageRemove: "Remove image",
|
|
1971
|
+
imageUploading: "Uploading image…",
|
|
1972
|
+
imageUploadPlanError: "Your plan does not support image sending.",
|
|
1973
|
+
imageUploadTooLarge: "Image too large (max 5 MB after compression).",
|
|
1974
|
+
imageUploadRateLimit: "Too many requests. Please try again.",
|
|
1975
|
+
imageUploadError: "Image upload failed. Please try again."
|
|
1422
1976
|
};
|
|
1423
1977
|
//#endregion
|
|
1424
1978
|
//#region src/i18n/index.ts
|
|
1425
|
-
function
|
|
1426
|
-
return e === "en" ?
|
|
1979
|
+
function et(e) {
|
|
1980
|
+
return e === "en" ? $e : Qe;
|
|
1427
1981
|
}
|
|
1428
1982
|
//#endregion
|
|
1429
1983
|
//#region src/core/declarative-executor.ts
|
|
1430
|
-
var
|
|
1431
|
-
function
|
|
1984
|
+
var tt = /^[a-zA-Z0-9_-]*$/;
|
|
1985
|
+
function nt(e, t) {
|
|
1432
1986
|
return e.replace(/\{([a-zA-Z][a-zA-Z0-9_]*)\}/g, (e, n) => {
|
|
1433
1987
|
let r = t[n], i = r == null ? "" : String(r);
|
|
1434
|
-
if (!
|
|
1988
|
+
if (!tt.test(i)) throw Error(`Unsafe param value for "${n}"`);
|
|
1435
1989
|
return i;
|
|
1436
1990
|
});
|
|
1437
1991
|
}
|
|
1438
|
-
function
|
|
1992
|
+
function rt(e, t) {
|
|
1439
1993
|
let n = typeof location < "u" ? location.origin : "https://placeholder.local", r, i;
|
|
1440
1994
|
try {
|
|
1441
1995
|
r = new URL(e, n), i = new URL(t.replace(/\{[a-zA-Z][a-zA-Z0-9_]*\}/g, "x"), n);
|
|
@@ -1445,10 +1999,10 @@ function Me(e, t) {
|
|
|
1445
1999
|
if (!/^https?:$/.test(r.protocol)) throw Error("Navigation must be http(s)");
|
|
1446
2000
|
if (r.origin !== i.origin) throw Error("Navigation origin not allowed");
|
|
1447
2001
|
}
|
|
1448
|
-
async function
|
|
2002
|
+
async function it(e, t) {
|
|
1449
2003
|
let n = e.config;
|
|
1450
2004
|
if (e.operation === "click") {
|
|
1451
|
-
let e =
|
|
2005
|
+
let e = nt(String(n.selectorTemplate ?? ""), t), r = document.querySelector(e);
|
|
1452
2006
|
if (!r) throw Error(`No element for selector: ${e}`);
|
|
1453
2007
|
r.click();
|
|
1454
2008
|
return;
|
|
@@ -1463,15 +2017,15 @@ async function Ne(e, t) {
|
|
|
1463
2017
|
return;
|
|
1464
2018
|
}
|
|
1465
2019
|
if (e.operation === "navigate") {
|
|
1466
|
-
let e = String(n.urlTemplate ?? ""), r =
|
|
1467
|
-
|
|
2020
|
+
let e = String(n.urlTemplate ?? ""), r = nt(e, t);
|
|
2021
|
+
rt(r, e), location.assign(r);
|
|
1468
2022
|
return;
|
|
1469
2023
|
}
|
|
1470
2024
|
throw Error(`Unknown operation: ${String(e.operation)}`);
|
|
1471
2025
|
}
|
|
1472
2026
|
//#endregion
|
|
1473
2027
|
//#region src/core/page-action-executor.ts
|
|
1474
|
-
async function
|
|
2028
|
+
async function at(e, t) {
|
|
1475
2029
|
let n = t.registry.get(e.actionName);
|
|
1476
2030
|
if (!n) return {
|
|
1477
2031
|
status: "unknown",
|
|
@@ -1496,26 +2050,26 @@ async function Pe(e, t) {
|
|
|
1496
2050
|
//#endregion
|
|
1497
2051
|
//#region src/builds/npm/index.ts
|
|
1498
2052
|
var $ = 10;
|
|
1499
|
-
function
|
|
1500
|
-
if (D.setDeclarativeRunner(
|
|
2053
|
+
function ot(e) {
|
|
2054
|
+
if (D.setDeclarativeRunner(it), typeof window < "u" && (window.botiq = window.botiq ?? {}, window.botiq.registerActions = (e) => D.register(e)), !e.apiKey) return console.warn("[BotIQ] apiKey is required"), () => void 0;
|
|
1501
2055
|
let t = p(e);
|
|
1502
2056
|
y();
|
|
1503
2057
|
let n = t.apiKey.slice(-16), r = C(), i = b(n), a = x(n, i);
|
|
1504
|
-
|
|
2058
|
+
R({
|
|
1505
2059
|
messages: a,
|
|
1506
2060
|
view: "home",
|
|
1507
2061
|
currentSessionId: i
|
|
1508
2062
|
});
|
|
1509
|
-
let o =
|
|
2063
|
+
let o = K(), s = document.createElement("div");
|
|
1510
2064
|
document.body.appendChild(s);
|
|
1511
|
-
let c = () => void 0, l = !1, u =
|
|
1512
|
-
function
|
|
1513
|
-
|
|
1514
|
-
if (
|
|
1515
|
-
let e = await
|
|
1516
|
-
e.messages.length > 0 &&
|
|
2065
|
+
let c = () => void 0, l = !1, u = et(void 0), d = null, m = null, h = null, g = null;
|
|
2066
|
+
function _() {
|
|
2067
|
+
g ||= setTimeout(async () => {
|
|
2068
|
+
if (g = null, !(!L().escalated || !L().isOpen)) try {
|
|
2069
|
+
let e = await P(t.apiUrl, t.apiKey, L().currentSessionId, $, r);
|
|
2070
|
+
e.messages.length > 0 && R({ messages: e.messages.map(M) }), R({ escalated: e.escalated === !0 });
|
|
1517
2071
|
} catch {} finally {
|
|
1518
|
-
|
|
2072
|
+
L().escalated && L().isOpen && _();
|
|
1519
2073
|
}
|
|
1520
2074
|
}, 1e4);
|
|
1521
2075
|
}
|
|
@@ -1525,94 +2079,132 @@ function Fe(e) {
|
|
|
1525
2079
|
console.warn("[BotIQ] Widget not authorised on this origin — skipped mount"), s.remove();
|
|
1526
2080
|
return;
|
|
1527
2081
|
}
|
|
1528
|
-
u =
|
|
1529
|
-
let n =
|
|
1530
|
-
onSend:
|
|
1531
|
-
onToggle:
|
|
1532
|
-
onScrollTop:
|
|
1533
|
-
onRetry:
|
|
1534
|
-
onNavigate:
|
|
1535
|
-
onOpenConversation:
|
|
1536
|
-
onNewConversation:
|
|
2082
|
+
h = e, u = et(e.widgetLanguage), e.pageActions?.length && D.seed(e.pageActions);
|
|
2083
|
+
let n = Ze(t, e, u, {
|
|
2084
|
+
onSend: ae,
|
|
2085
|
+
onToggle: le,
|
|
2086
|
+
onScrollTop: ne,
|
|
2087
|
+
onRetry: oe,
|
|
2088
|
+
onNavigate: E,
|
|
2089
|
+
onOpenConversation: j,
|
|
2090
|
+
onNewConversation: A,
|
|
2091
|
+
onAttachImage: ie,
|
|
2092
|
+
onRemoveAttachment: V,
|
|
2093
|
+
onBlockPageAction: se
|
|
1537
2094
|
});
|
|
1538
|
-
d = n, n.mount(s), c = re((e) => n.update(e)), n.update(
|
|
1539
|
-
if (
|
|
1540
|
-
let t =
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
2095
|
+
d = n, n.mount(s), c = re((e) => n.update(e)), n.update(L()), e.proactive?.enabled && (m = setTimeout(() => {
|
|
2096
|
+
if (L().isOpen) return;
|
|
2097
|
+
let t = w();
|
|
2098
|
+
R({
|
|
2099
|
+
messages: [{
|
|
2100
|
+
role: "assistant",
|
|
2101
|
+
content: e.proactive.message,
|
|
2102
|
+
ts: Date.now()
|
|
2103
|
+
}],
|
|
1547
2104
|
view: "conversation",
|
|
1548
|
-
|
|
2105
|
+
currentSessionId: t,
|
|
2106
|
+
unreadCount: L().unreadCount + 1
|
|
1549
2107
|
});
|
|
1550
|
-
}, e.proactive.delayMs ?? 8e3)), a.length > 0 &&
|
|
2108
|
+
}, e.proactive.delayMs ?? 8e3)), a.length > 0 && N(i);
|
|
1551
2109
|
});
|
|
1552
|
-
|
|
1553
|
-
|
|
2110
|
+
let v = !1;
|
|
2111
|
+
async function T() {
|
|
2112
|
+
if (!v) {
|
|
2113
|
+
v = !0;
|
|
2114
|
+
try {
|
|
2115
|
+
R({ conversations: await O(t.apiUrl, t.apiKey, r) });
|
|
2116
|
+
} finally {
|
|
2117
|
+
v = !1;
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
1554
2120
|
}
|
|
1555
|
-
function
|
|
1556
|
-
|
|
2121
|
+
function E(e) {
|
|
2122
|
+
R({ view: e }), (e === "home" || e === "messages") && T();
|
|
1557
2123
|
}
|
|
1558
|
-
function
|
|
1559
|
-
|
|
2124
|
+
function A() {
|
|
2125
|
+
R({
|
|
1560
2126
|
view: "conversation",
|
|
1561
2127
|
currentSessionId: w(),
|
|
1562
2128
|
messages: [],
|
|
1563
2129
|
escalated: !1
|
|
1564
|
-
}), o =
|
|
2130
|
+
}), o = K();
|
|
1565
2131
|
}
|
|
1566
|
-
function
|
|
1567
|
-
|
|
2132
|
+
function j(e) {
|
|
2133
|
+
R({
|
|
1568
2134
|
view: "conversation",
|
|
1569
2135
|
currentSessionId: e,
|
|
1570
2136
|
messages: x(n, e)
|
|
1571
|
-
}), o =
|
|
2137
|
+
}), o = K(), N(e);
|
|
1572
2138
|
}
|
|
1573
|
-
function
|
|
2139
|
+
function M(e) {
|
|
1574
2140
|
let t = Date.parse(e.createdAt);
|
|
1575
2141
|
return {
|
|
1576
2142
|
role: e.role,
|
|
1577
2143
|
content: e.content,
|
|
1578
|
-
...Number.isFinite(t) ? { ts: t } : {}
|
|
2144
|
+
...Number.isFinite(t) ? { ts: t } : {},
|
|
2145
|
+
...h?.richMessages && e.blocks?.length ? { blocks: e.blocks } : {}
|
|
1579
2146
|
};
|
|
1580
2147
|
}
|
|
1581
|
-
async function
|
|
1582
|
-
let n = await
|
|
1583
|
-
n.messages.length > 0 && (o =
|
|
2148
|
+
async function N(e) {
|
|
2149
|
+
let n = await P(t.apiUrl, t.apiKey, e, $, r);
|
|
2150
|
+
L().currentSessionId === e && (n.messages.length > 0 && (o = xe(n), R({ messages: n.messages.map(M) })), R({ escalated: n.escalated === !0 }), L().escalated && _());
|
|
1584
2151
|
}
|
|
1585
|
-
async function
|
|
1586
|
-
if (
|
|
1587
|
-
|
|
2152
|
+
async function ne() {
|
|
2153
|
+
if (Ce(o, L().loadingOlder)) {
|
|
2154
|
+
R({ loadingOlder: !0 });
|
|
1588
2155
|
try {
|
|
1589
|
-
let e =
|
|
1590
|
-
n.messages.length > 0 &&
|
|
2156
|
+
let e = L().currentSessionId, n = await ee(t.apiUrl, t.apiKey, e, o.oldestCursor, $);
|
|
2157
|
+
n.messages.length > 0 && R({ messages: [...n.messages.map(M), ...L().messages] }), o = Se(o, n);
|
|
1591
2158
|
} finally {
|
|
1592
|
-
|
|
2159
|
+
R({ loadingOlder: !1 });
|
|
1593
2160
|
}
|
|
1594
2161
|
}
|
|
1595
2162
|
}
|
|
1596
|
-
let
|
|
1597
|
-
async function
|
|
1598
|
-
let
|
|
1599
|
-
|
|
2163
|
+
let F = "", I = null, z = null;
|
|
2164
|
+
async function B(e, i, a) {
|
|
2165
|
+
let o = L().currentSessionId, s = x(n, o).length === 0 && L().messages.filter((e) => e.role === "user").length === 1;
|
|
2166
|
+
R({ isLoading: !0 });
|
|
1600
2167
|
try {
|
|
1601
|
-
let
|
|
2168
|
+
let c = i && a ? [{
|
|
2169
|
+
url: i,
|
|
2170
|
+
mimeType: a
|
|
2171
|
+
}] : void 0, l = await te({
|
|
2172
|
+
apiUrl: t.apiUrl,
|
|
2173
|
+
apiKey: t.apiKey,
|
|
2174
|
+
sessionId: o,
|
|
2175
|
+
message: e,
|
|
2176
|
+
history: L().messages.filter((e) => !e.error && !e.streaming),
|
|
2177
|
+
strings: u,
|
|
2178
|
+
visitorId: r,
|
|
2179
|
+
attachments: c,
|
|
2180
|
+
onToken(e) {
|
|
2181
|
+
let t = L().messages, n = t[t.length - 1];
|
|
2182
|
+
n?.role === "assistant" && n.streaming ? R({ messages: [...t.slice(0, -1), {
|
|
2183
|
+
...n,
|
|
2184
|
+
content: n.content + e
|
|
2185
|
+
}] }) : R({ messages: [...t, {
|
|
2186
|
+
role: "assistant",
|
|
2187
|
+
content: e,
|
|
2188
|
+
ts: Date.now(),
|
|
2189
|
+
streaming: !0
|
|
2190
|
+
}] });
|
|
2191
|
+
}
|
|
2192
|
+
}), f = L().messages.filter((e) => !e.streaming), p = {
|
|
1602
2193
|
role: "assistant",
|
|
1603
|
-
content:
|
|
2194
|
+
content: l.reply,
|
|
1604
2195
|
ts: Date.now(),
|
|
1605
|
-
...
|
|
2196
|
+
...l.error ? { error: !0 } : {},
|
|
2197
|
+
...h?.richMessages && l.blocks?.length ? { blocks: l.blocks } : {}
|
|
1606
2198
|
};
|
|
1607
|
-
if (
|
|
1608
|
-
messages: [...
|
|
2199
|
+
if (R({
|
|
2200
|
+
messages: [...f, p],
|
|
1609
2201
|
isLoading: !1
|
|
1610
|
-
}),
|
|
1611
|
-
|
|
1612
|
-
}), !
|
|
2202
|
+
}), l.error || S(n, o, [p]), !l.error && s && T(), l.error || P(t.apiUrl, t.apiKey, o, $, r).then((e) => {
|
|
2203
|
+
R({ escalated: e.escalated === !0 }), L().escalated && _();
|
|
2204
|
+
}), !l.error && l.pageAction && d) {
|
|
1613
2205
|
let e = d;
|
|
1614
2206
|
try {
|
|
1615
|
-
let t = await
|
|
2207
|
+
let t = await at(l.pageAction, {
|
|
1616
2208
|
registry: D,
|
|
1617
2209
|
confirm: (t) => e.confirmAction(t)
|
|
1618
2210
|
});
|
|
@@ -1622,7 +2214,7 @@ function Fe(e) {
|
|
|
1622
2214
|
content: t.status === "executed" ? u.actionDone : t.status === "cancelled" ? u.actionCancelled : t.status === "unknown" ? `⚠ ${t.message ?? u.actionUnavailable}` : `⚠ ${t.message ?? u.actionError}`,
|
|
1623
2215
|
ts: Date.now()
|
|
1624
2216
|
};
|
|
1625
|
-
|
|
2217
|
+
R({ messages: [...L().messages, r] }), S(n, o, [r]);
|
|
1626
2218
|
} catch {
|
|
1627
2219
|
if (!d) return;
|
|
1628
2220
|
let e = {
|
|
@@ -1630,38 +2222,128 @@ function Fe(e) {
|
|
|
1630
2222
|
content: u.actionError,
|
|
1631
2223
|
ts: Date.now()
|
|
1632
2224
|
};
|
|
1633
|
-
|
|
2225
|
+
R({ messages: [...L().messages, e] }), S(n, o, [e]);
|
|
1634
2226
|
}
|
|
1635
2227
|
}
|
|
1636
2228
|
} catch {
|
|
1637
|
-
|
|
2229
|
+
R({ isLoading: !1 });
|
|
1638
2230
|
}
|
|
1639
2231
|
}
|
|
1640
|
-
async function
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
2232
|
+
async function ie(e) {
|
|
2233
|
+
let t = ce(e);
|
|
2234
|
+
if (!t.ok) {
|
|
2235
|
+
R({ uploadError: t.error });
|
|
2236
|
+
return;
|
|
2237
|
+
}
|
|
2238
|
+
R({ uploadError: null });
|
|
2239
|
+
try {
|
|
2240
|
+
let { blob: t, mimeType: n } = await ue(e), r = L().pendingAttachment;
|
|
2241
|
+
r && URL.revokeObjectURL(r.previewUrl), R({
|
|
2242
|
+
pendingAttachment: {
|
|
2243
|
+
blob: t,
|
|
2244
|
+
previewUrl: URL.createObjectURL(t),
|
|
2245
|
+
mimeType: n
|
|
2246
|
+
},
|
|
2247
|
+
uploadError: null
|
|
2248
|
+
});
|
|
2249
|
+
} catch {
|
|
2250
|
+
R({ uploadError: u.imageUploadError });
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
function V() {
|
|
2254
|
+
let e = L().pendingAttachment;
|
|
2255
|
+
e && URL.revokeObjectURL(e.previewUrl), R({
|
|
2256
|
+
pendingAttachment: null,
|
|
2257
|
+
uploadError: null
|
|
2258
|
+
});
|
|
2259
|
+
}
|
|
2260
|
+
async function ae(e) {
|
|
2261
|
+
if (L().isLoading || L().isUploading) return;
|
|
2262
|
+
let i = L().pendingAttachment;
|
|
2263
|
+
if (!e && !i) return;
|
|
2264
|
+
R({ uploadError: null }), F = e, I = null, z = null;
|
|
2265
|
+
let a = L().currentSessionId, o = {
|
|
1644
2266
|
role: "user",
|
|
1645
2267
|
content: e,
|
|
1646
2268
|
ts: Date.now()
|
|
1647
2269
|
};
|
|
1648
|
-
|
|
2270
|
+
if (R({ messages: [...L().messages, o] }), S(n, a, [o]), i) {
|
|
2271
|
+
R({
|
|
2272
|
+
isUploading: !0,
|
|
2273
|
+
uploadError: null
|
|
2274
|
+
});
|
|
2275
|
+
let e = await k(t.apiUrl, t.apiKey, i.blob, r, u);
|
|
2276
|
+
if (R({ isUploading: !1 }), !e.ok) {
|
|
2277
|
+
R({ uploadError: e.error });
|
|
2278
|
+
let t = L().messages;
|
|
2279
|
+
R({ messages: t.slice(0, -1) });
|
|
2280
|
+
return;
|
|
2281
|
+
}
|
|
2282
|
+
I = e.url, z = i.mimeType, URL.revokeObjectURL(i.previewUrl), R({
|
|
2283
|
+
pendingAttachment: null,
|
|
2284
|
+
uploadError: null
|
|
2285
|
+
});
|
|
2286
|
+
}
|
|
2287
|
+
await B(e, I ?? void 0, z ?? void 0);
|
|
2288
|
+
}
|
|
2289
|
+
function oe() {
|
|
2290
|
+
if (L().isLoading || !F) return;
|
|
2291
|
+
let e = L().messages;
|
|
2292
|
+
R({ messages: e.length > 0 && e[e.length - 1].error ? e.slice(0, -1) : e }), B(F, I ?? void 0, z ?? void 0);
|
|
1649
2293
|
}
|
|
1650
|
-
function
|
|
1651
|
-
if (
|
|
1652
|
-
|
|
1653
|
-
|
|
2294
|
+
async function se(e) {
|
|
2295
|
+
if (!d) return;
|
|
2296
|
+
if (!D.has(e)) {
|
|
2297
|
+
let e = {
|
|
2298
|
+
role: "assistant",
|
|
2299
|
+
content: `⚠ ${u.actionUnavailable}`,
|
|
2300
|
+
ts: Date.now()
|
|
2301
|
+
};
|
|
2302
|
+
R({ messages: [...L().messages, e] });
|
|
2303
|
+
return;
|
|
2304
|
+
}
|
|
2305
|
+
let t = d;
|
|
2306
|
+
try {
|
|
2307
|
+
let n = await at({
|
|
2308
|
+
actionName: e,
|
|
2309
|
+
params: {},
|
|
2310
|
+
reason: ""
|
|
2311
|
+
}, {
|
|
2312
|
+
registry: D,
|
|
2313
|
+
confirm: (e) => t.confirmAction(e)
|
|
2314
|
+
});
|
|
2315
|
+
if (!d) return;
|
|
2316
|
+
let r = {
|
|
2317
|
+
role: "assistant",
|
|
2318
|
+
content: n.status === "executed" ? u.actionDone : n.status === "cancelled" ? u.actionCancelled : n.status === "unknown" ? `⚠ ${n.message ?? u.actionUnavailable}` : `⚠ ${n.message ?? u.actionError}`,
|
|
2319
|
+
ts: Date.now()
|
|
2320
|
+
};
|
|
2321
|
+
R({ messages: [...L().messages, r] });
|
|
2322
|
+
} catch {
|
|
2323
|
+
if (!d) return;
|
|
2324
|
+
let e = {
|
|
2325
|
+
role: "assistant",
|
|
2326
|
+
content: u.actionError,
|
|
2327
|
+
ts: Date.now()
|
|
2328
|
+
};
|
|
2329
|
+
R({ messages: [...L().messages, e] });
|
|
2330
|
+
}
|
|
1654
2331
|
}
|
|
1655
|
-
function
|
|
1656
|
-
let e = !
|
|
1657
|
-
|
|
2332
|
+
function le() {
|
|
2333
|
+
let e = !L().isOpen, t = L().view;
|
|
2334
|
+
R({
|
|
1658
2335
|
isOpen: e,
|
|
1659
2336
|
...e ? { unreadCount: 0 } : {}
|
|
1660
|
-
});
|
|
2337
|
+
}), e && t === "home" && T();
|
|
1661
2338
|
}
|
|
1662
2339
|
return () => {
|
|
1663
|
-
l = !0, d = null, c(), m && clearTimeout(m),
|
|
2340
|
+
l = !0, d = null, c(), m && clearTimeout(m), g &&= (clearTimeout(g), null);
|
|
2341
|
+
let e = L().pendingAttachment;
|
|
2342
|
+
e && URL.revokeObjectURL(e.previewUrl), R({
|
|
2343
|
+
pendingAttachment: null,
|
|
2344
|
+
uploadError: null
|
|
2345
|
+
}), s.remove();
|
|
1664
2346
|
};
|
|
1665
2347
|
}
|
|
1666
2348
|
//#endregion
|
|
1667
|
-
export {
|
|
2349
|
+
export { ot as t };
|