@customerhero/js 2.2.0 → 2.4.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/README.md +19 -0
- package/dist/index.cjs +221 -21
- package/dist/index.d.cts +181 -2
- package/dist/index.d.ts +181 -2
- package/dist/index.js +215 -21
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -56,6 +56,25 @@ chat.identify({
|
|
|
56
56
|
| `locale` | `string` | Widget locale (e.g. `"en"`, `"es"`). Auto-detected from browser if omitted. |
|
|
57
57
|
| `suggestedMessages` | `string[]` | Quick-reply options shown before the first message. |
|
|
58
58
|
|
|
59
|
+
### Appearance
|
|
60
|
+
|
|
61
|
+
| Option | Type | Description |
|
|
62
|
+
| ------------------------ | ----------------------------------- | --------------------------------------------------------------------------------- |
|
|
63
|
+
| `colorScheme` | `"auto" \| "light" \| "dark"` | `auto` follows the visitor's OS preference. Defaults to `light`. |
|
|
64
|
+
| `primaryColorDark` | `string` | Primary color used in dark mode. Only honoured when the effective scheme is dark. |
|
|
65
|
+
| `backgroundColorDark` | `string` | Background color used in dark mode. |
|
|
66
|
+
| `textColorDark` | `string` | Text color used in dark mode. |
|
|
67
|
+
| `size` | `"compact" \| "default" \| "large"` | Launcher diameter, panel dimensions, and base font size. |
|
|
68
|
+
| `cornerStyle` | `"soft" \| "rounded" \| "square"` | Panel border-radius preset. |
|
|
69
|
+
| `launcher.iconUrl` | `string` | Custom launcher icon URL (replaces the default chat-bubble glyph). |
|
|
70
|
+
| `launcher.label` | `string` | CTA label next to the launcher (turns the bubble into a pill). Max 60 chars. |
|
|
71
|
+
| `launcher.showOnlineDot` | `boolean` | Show a small green dot on the launcher when agents are available. |
|
|
72
|
+
| `offset.bottom` | `number` | Pixel offset from the bottom edge. 0–1000. Defaults to 20. |
|
|
73
|
+
| `offset.side` | `number` | Pixel offset from the side (mirrors `position`). 0–1000. Defaults to 20. |
|
|
74
|
+
| `zIndex` | `number` | Z-index override. Defaults to 99999. Capped at 2 000 000 000. |
|
|
75
|
+
|
|
76
|
+
Dark colors are never auto-derived from `primaryColor`/`backgroundColor`/`textColor` — set them explicitly when enabling dark or auto modes.
|
|
77
|
+
|
|
59
78
|
## License
|
|
60
79
|
|
|
61
80
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -20,8 +20,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
CORNER_RADIUS: () => CORNER_RADIUS,
|
|
23
24
|
CustomerHeroChat: () => CustomerHeroChat,
|
|
24
25
|
DEFAULTS: () => DEFAULTS,
|
|
26
|
+
SIZE_PRESETS: () => SIZE_PRESETS,
|
|
25
27
|
SUPPORTED_LOCALES: () => SUPPORTED_LOCALES,
|
|
26
28
|
ScreenshotCancelled: () => ScreenshotCancelled,
|
|
27
29
|
ScreenshotUnavailable: () => ScreenshotUnavailable,
|
|
@@ -29,10 +31,14 @@ __export(index_exports, {
|
|
|
29
31
|
captureScreenshot: () => captureScreenshot,
|
|
30
32
|
createTranslator: () => createTranslator,
|
|
31
33
|
detectLocale: () => detectLocale,
|
|
34
|
+
effectiveColors: () => effectiveColors,
|
|
32
35
|
evaluate: () => evaluate,
|
|
33
36
|
isRtlLocale: () => isRtlLocale,
|
|
37
|
+
panelRadius: () => panelRadius,
|
|
34
38
|
pickFire: () => pickFire,
|
|
35
39
|
resolveLocale: () => resolveLocale,
|
|
40
|
+
resolveScheme: () => resolveScheme,
|
|
41
|
+
sizePreset: () => sizePreset,
|
|
36
42
|
startTriggersRuntime: () => startTriggersRuntime
|
|
37
43
|
});
|
|
38
44
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -46,7 +52,29 @@ var DEFAULTS = {
|
|
|
46
52
|
position: "bottom-right",
|
|
47
53
|
placeholderText: "Type your message...",
|
|
48
54
|
welcomeMessage: "Hi! How can I help you today?",
|
|
49
|
-
title: "CustomerHero"
|
|
55
|
+
title: "CustomerHero",
|
|
56
|
+
// Appearance pack (B1–B6) defaults.
|
|
57
|
+
colorScheme: "light",
|
|
58
|
+
// Dark fallbacks used when the effective scheme is dark and no per-chatbot
|
|
59
|
+
// dark color is configured. Operators can — and should — override these.
|
|
60
|
+
primaryColorDark: "#A78BFA",
|
|
61
|
+
backgroundColorDark: "#0F172A",
|
|
62
|
+
textColorDark: "#E5E7EB",
|
|
63
|
+
size: "default",
|
|
64
|
+
cornerStyle: "rounded",
|
|
65
|
+
offsetBottom: 20,
|
|
66
|
+
offsetSide: 20,
|
|
67
|
+
zIndex: 99999
|
|
68
|
+
};
|
|
69
|
+
var SIZE_PRESETS = {
|
|
70
|
+
compact: { bubble: 48, width: 320, height: 480, fontSize: 13 },
|
|
71
|
+
default: { bubble: 56, width: 380, height: 520, fontSize: 14 },
|
|
72
|
+
large: { bubble: 64, width: 440, height: 600, fontSize: 15 }
|
|
73
|
+
};
|
|
74
|
+
var CORNER_RADIUS = {
|
|
75
|
+
soft: 8,
|
|
76
|
+
rounded: 16,
|
|
77
|
+
square: 0
|
|
50
78
|
};
|
|
51
79
|
|
|
52
80
|
// src/i18n/locales/en.ts
|
|
@@ -77,7 +105,10 @@ var en = {
|
|
|
77
105
|
drop_files_here: "Drop files here",
|
|
78
106
|
incident_dismiss: "Dismiss",
|
|
79
107
|
incident_default_link_label: "Learn more",
|
|
80
|
-
attachment_unsupported_type: "Unsupported file type"
|
|
108
|
+
attachment_unsupported_type: "Unsupported file type",
|
|
109
|
+
attachment_open: "Open attachment",
|
|
110
|
+
attachment_image_alt: "Image attachment",
|
|
111
|
+
attachment_location: "Shared location"
|
|
81
112
|
};
|
|
82
113
|
|
|
83
114
|
// src/i18n/locales/es.ts
|
|
@@ -108,7 +139,10 @@ var es = {
|
|
|
108
139
|
drop_files_here: "Suelta los archivos aqu\xED",
|
|
109
140
|
incident_dismiss: "Descartar",
|
|
110
141
|
incident_default_link_label: "M\xE1s informaci\xF3n",
|
|
111
|
-
attachment_unsupported_type: "Tipo de archivo no admitido"
|
|
142
|
+
attachment_unsupported_type: "Tipo de archivo no admitido",
|
|
143
|
+
attachment_open: "Abrir adjunto",
|
|
144
|
+
attachment_image_alt: "Imagen adjunta",
|
|
145
|
+
attachment_location: "Ubicaci\xF3n compartida"
|
|
112
146
|
};
|
|
113
147
|
|
|
114
148
|
// src/i18n/locales/pt-BR.ts
|
|
@@ -139,7 +173,10 @@ var ptBR = {
|
|
|
139
173
|
drop_files_here: "Solte os arquivos aqui",
|
|
140
174
|
incident_dismiss: "Dispensar",
|
|
141
175
|
incident_default_link_label: "Saiba mais",
|
|
142
|
-
attachment_unsupported_type: "Tipo de arquivo n\xE3o suportado"
|
|
176
|
+
attachment_unsupported_type: "Tipo de arquivo n\xE3o suportado",
|
|
177
|
+
attachment_open: "Abrir anexo",
|
|
178
|
+
attachment_image_alt: "Imagem anexada",
|
|
179
|
+
attachment_location: "Localiza\xE7\xE3o compartilhada"
|
|
143
180
|
};
|
|
144
181
|
|
|
145
182
|
// src/i18n/locales/pt-PT.ts
|
|
@@ -170,7 +207,10 @@ var ptPT = {
|
|
|
170
207
|
drop_files_here: "Largue os ficheiros aqui",
|
|
171
208
|
incident_dismiss: "Dispensar",
|
|
172
209
|
incident_default_link_label: "Saiba mais",
|
|
173
|
-
attachment_unsupported_type: "Tipo de ficheiro n\xE3o suportado"
|
|
210
|
+
attachment_unsupported_type: "Tipo de ficheiro n\xE3o suportado",
|
|
211
|
+
attachment_open: "Abrir anexo",
|
|
212
|
+
attachment_image_alt: "Imagem anexa",
|
|
213
|
+
attachment_location: "Localiza\xE7\xE3o partilhada"
|
|
174
214
|
};
|
|
175
215
|
|
|
176
216
|
// src/i18n/locales/fr.ts
|
|
@@ -201,7 +241,10 @@ var fr = {
|
|
|
201
241
|
drop_files_here: "D\xE9posez les fichiers ici",
|
|
202
242
|
incident_dismiss: "Ignorer",
|
|
203
243
|
incident_default_link_label: "En savoir plus",
|
|
204
|
-
attachment_unsupported_type: "Type de fichier non pris en charge"
|
|
244
|
+
attachment_unsupported_type: "Type de fichier non pris en charge",
|
|
245
|
+
attachment_open: "Ouvrir la pi\xE8ce jointe",
|
|
246
|
+
attachment_image_alt: "Pi\xE8ce jointe (image)",
|
|
247
|
+
attachment_location: "Position partag\xE9e"
|
|
205
248
|
};
|
|
206
249
|
|
|
207
250
|
// src/i18n/locales/de.ts
|
|
@@ -232,7 +275,10 @@ var de = {
|
|
|
232
275
|
drop_files_here: "Dateien hier ablegen",
|
|
233
276
|
incident_dismiss: "Schlie\xDFen",
|
|
234
277
|
incident_default_link_label: "Mehr erfahren",
|
|
235
|
-
attachment_unsupported_type: "Dateityp nicht unterst\xFCtzt"
|
|
278
|
+
attachment_unsupported_type: "Dateityp nicht unterst\xFCtzt",
|
|
279
|
+
attachment_open: "Anhang \xF6ffnen",
|
|
280
|
+
attachment_image_alt: "Bildanhang",
|
|
281
|
+
attachment_location: "Geteilter Standort"
|
|
236
282
|
};
|
|
237
283
|
|
|
238
284
|
// src/i18n/locales/it.ts
|
|
@@ -263,7 +309,10 @@ var it = {
|
|
|
263
309
|
drop_files_here: "Trascina qui i file",
|
|
264
310
|
incident_dismiss: "Chiudi",
|
|
265
311
|
incident_default_link_label: "Scopri di pi\xF9",
|
|
266
|
-
attachment_unsupported_type: "Tipo di file non supportato"
|
|
312
|
+
attachment_unsupported_type: "Tipo di file non supportato",
|
|
313
|
+
attachment_open: "Apri allegato",
|
|
314
|
+
attachment_image_alt: "Allegato immagine",
|
|
315
|
+
attachment_location: "Posizione condivisa"
|
|
267
316
|
};
|
|
268
317
|
|
|
269
318
|
// src/i18n/locales/nl.ts
|
|
@@ -294,7 +343,10 @@ var nl = {
|
|
|
294
343
|
drop_files_here: "Sleep bestanden hier",
|
|
295
344
|
incident_dismiss: "Sluiten",
|
|
296
345
|
incident_default_link_label: "Meer informatie",
|
|
297
|
-
attachment_unsupported_type: "Bestandstype niet ondersteund"
|
|
346
|
+
attachment_unsupported_type: "Bestandstype niet ondersteund",
|
|
347
|
+
attachment_open: "Bijlage openen",
|
|
348
|
+
attachment_image_alt: "Afbeeldingsbijlage",
|
|
349
|
+
attachment_location: "Gedeelde locatie"
|
|
298
350
|
};
|
|
299
351
|
|
|
300
352
|
// src/i18n/locales/pl.ts
|
|
@@ -325,7 +377,10 @@ var pl = {
|
|
|
325
377
|
drop_files_here: "Upu\u015B\u0107 pliki tutaj",
|
|
326
378
|
incident_dismiss: "Zamknij",
|
|
327
379
|
incident_default_link_label: "Dowiedz si\u0119 wi\u0119cej",
|
|
328
|
-
attachment_unsupported_type: "Nieobs\u0142ugiwany typ pliku"
|
|
380
|
+
attachment_unsupported_type: "Nieobs\u0142ugiwany typ pliku",
|
|
381
|
+
attachment_open: "Otw\xF3rz za\u0142\u0105cznik",
|
|
382
|
+
attachment_image_alt: "Za\u0142\u0105cznik obrazu",
|
|
383
|
+
attachment_location: "Udost\u0119pniona lokalizacja"
|
|
329
384
|
};
|
|
330
385
|
|
|
331
386
|
// src/i18n/locales/tr.ts
|
|
@@ -356,7 +411,10 @@ var tr = {
|
|
|
356
411
|
drop_files_here: "Dosyalar\u0131 buraya b\u0131rak",
|
|
357
412
|
incident_dismiss: "Kapat",
|
|
358
413
|
incident_default_link_label: "Daha fazla bilgi",
|
|
359
|
-
attachment_unsupported_type: "Desteklenmeyen dosya t\xFCr\xFC"
|
|
414
|
+
attachment_unsupported_type: "Desteklenmeyen dosya t\xFCr\xFC",
|
|
415
|
+
attachment_open: "Eki a\xE7",
|
|
416
|
+
attachment_image_alt: "Resim eki",
|
|
417
|
+
attachment_location: "Payla\u015F\u0131lan konum"
|
|
360
418
|
};
|
|
361
419
|
|
|
362
420
|
// src/i18n/locales/ar.ts
|
|
@@ -387,7 +445,10 @@ var ar = {
|
|
|
387
445
|
drop_files_here: "\u0623\u0641\u0644\u062A \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0647\u0646\u0627",
|
|
388
446
|
incident_dismiss: "\u0625\u063A\u0644\u0627\u0642",
|
|
389
447
|
incident_default_link_label: "\u0627\u0639\u0631\u0641 \u0627\u0644\u0645\u0632\u064A\u062F",
|
|
390
|
-
attachment_unsupported_type: "\u0646\u0648\u0639 \u0627\u0644\u0645\u0644\u0641 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645"
|
|
448
|
+
attachment_unsupported_type: "\u0646\u0648\u0639 \u0627\u0644\u0645\u0644\u0641 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645",
|
|
449
|
+
attachment_open: "\u0641\u062A\u062D \u0627\u0644\u0645\u0631\u0641\u0642",
|
|
450
|
+
attachment_image_alt: "\u0635\u0648\u0631\u0629 \u0645\u0631\u0641\u0642\u0629",
|
|
451
|
+
attachment_location: "\u0645\u0648\u0642\u0639 \u0645\u0634\u062A\u0631\u0643"
|
|
391
452
|
};
|
|
392
453
|
|
|
393
454
|
// src/i18n/locales/ja.ts
|
|
@@ -418,7 +479,10 @@ var ja = {
|
|
|
418
479
|
drop_files_here: "\u30D5\u30A1\u30A4\u30EB\u3092\u3053\u3053\u306B\u30C9\u30ED\u30C3\u30D7",
|
|
419
480
|
incident_dismiss: "\u9589\u3058\u308B",
|
|
420
481
|
incident_default_link_label: "\u8A73\u7D30\u3092\u898B\u308B",
|
|
421
|
-
attachment_unsupported_type: "\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F"
|
|
482
|
+
attachment_unsupported_type: "\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F",
|
|
483
|
+
attachment_open: "\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB\u3092\u958B\u304F",
|
|
484
|
+
attachment_image_alt: "\u753B\u50CF\u306E\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB",
|
|
485
|
+
attachment_location: "\u5171\u6709\u3055\u308C\u305F\u4F4D\u7F6E\u60C5\u5831"
|
|
422
486
|
};
|
|
423
487
|
|
|
424
488
|
// src/i18n/locales/ko.ts
|
|
@@ -449,7 +513,10 @@ var ko = {
|
|
|
449
513
|
drop_files_here: "\uD30C\uC77C\uC744 \uC5EC\uAE30\uC5D0 \uB193\uAE30",
|
|
450
514
|
incident_dismiss: "\uB2EB\uAE30",
|
|
451
515
|
incident_default_link_label: "\uC790\uC138\uD788 \uC54C\uC544\uBCF4\uAE30",
|
|
452
|
-
attachment_unsupported_type: "\uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD"
|
|
516
|
+
attachment_unsupported_type: "\uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD",
|
|
517
|
+
attachment_open: "\uCCA8\uBD80 \uD30C\uC77C \uC5F4\uAE30",
|
|
518
|
+
attachment_image_alt: "\uC774\uBBF8\uC9C0 \uCCA8\uBD80 \uD30C\uC77C",
|
|
519
|
+
attachment_location: "\uACF5\uC720\uB41C \uC704\uCE58"
|
|
453
520
|
};
|
|
454
521
|
|
|
455
522
|
// src/i18n/locales/zh-CN.ts
|
|
@@ -480,7 +547,10 @@ var zhCN = {
|
|
|
480
547
|
drop_files_here: "\u5C06\u6587\u4EF6\u62D6\u653E\u5230\u6B64\u5904",
|
|
481
548
|
incident_dismiss: "\u5173\u95ED",
|
|
482
549
|
incident_default_link_label: "\u4E86\u89E3\u66F4\u591A",
|
|
483
|
-
attachment_unsupported_type: "\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B"
|
|
550
|
+
attachment_unsupported_type: "\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B",
|
|
551
|
+
attachment_open: "\u6253\u5F00\u9644\u4EF6",
|
|
552
|
+
attachment_image_alt: "\u56FE\u7247\u9644\u4EF6",
|
|
553
|
+
attachment_location: "\u5171\u4EAB\u7684\u4F4D\u7F6E"
|
|
484
554
|
};
|
|
485
555
|
|
|
486
556
|
// src/i18n/locales/zh-TW.ts
|
|
@@ -511,7 +581,10 @@ var zhTW = {
|
|
|
511
581
|
drop_files_here: "\u5C07\u6A94\u6848\u62D6\u653E\u5230\u6B64\u8655",
|
|
512
582
|
incident_dismiss: "\u95DC\u9589",
|
|
513
583
|
incident_default_link_label: "\u77AD\u89E3\u66F4\u591A",
|
|
514
|
-
attachment_unsupported_type: "\u4E0D\u652F\u63F4\u7684\u6A94\u6848\u985E\u578B"
|
|
584
|
+
attachment_unsupported_type: "\u4E0D\u652F\u63F4\u7684\u6A94\u6848\u985E\u578B",
|
|
585
|
+
attachment_open: "\u958B\u555F\u9644\u4EF6",
|
|
586
|
+
attachment_image_alt: "\u5716\u7247\u9644\u4EF6",
|
|
587
|
+
attachment_location: "\u5171\u4EAB\u7684\u4F4D\u7F6E"
|
|
515
588
|
};
|
|
516
589
|
|
|
517
590
|
// src/i18n/index.ts
|
|
@@ -1014,7 +1087,14 @@ function startTriggersRuntime(options) {
|
|
|
1014
1087
|
}
|
|
1015
1088
|
|
|
1016
1089
|
// src/client.ts
|
|
1090
|
+
function clampInt(value, min, max, fallback) {
|
|
1091
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
1092
|
+
return Math.max(min, Math.min(max, Math.trunc(value)));
|
|
1093
|
+
}
|
|
1017
1094
|
function resolveConfig(userConfig, fetched) {
|
|
1095
|
+
const launcherUser = userConfig.launcher ?? {};
|
|
1096
|
+
const launcherFetched = fetched?.launcher ?? {};
|
|
1097
|
+
const offsetUser = userConfig.offset ?? {};
|
|
1018
1098
|
return {
|
|
1019
1099
|
chatbotId: userConfig.chatbotId,
|
|
1020
1100
|
apiBase: userConfig.apiBase ?? DEFAULTS.apiBase,
|
|
@@ -1027,7 +1107,32 @@ function resolveConfig(userConfig, fetched) {
|
|
|
1027
1107
|
title: userConfig.title ?? fetched?.title ?? DEFAULTS.title,
|
|
1028
1108
|
avatarUrl: userConfig.avatarUrl ?? fetched?.avatarUrl,
|
|
1029
1109
|
suggestedMessages: userConfig.suggestedMessages ?? fetched?.suggestedMessages ?? [],
|
|
1030
|
-
stringOverrides: fetched?.stringOverrides
|
|
1110
|
+
stringOverrides: fetched?.stringOverrides,
|
|
1111
|
+
// Appearance pack. Color palette + size + corner style + launcher all
|
|
1112
|
+
// come from the server widget_config (with host-side override). The
|
|
1113
|
+
// *runtime* knobs — colorScheme, offset, zIndex — are host-only because
|
|
1114
|
+
// they depend on the page the widget is embedded in, not the chatbot.
|
|
1115
|
+
primaryColorDark: userConfig.primaryColorDark ?? fetched?.primaryColorDark,
|
|
1116
|
+
backgroundColorDark: userConfig.backgroundColorDark ?? fetched?.backgroundColorDark,
|
|
1117
|
+
textColorDark: userConfig.textColorDark ?? fetched?.textColorDark,
|
|
1118
|
+
size: userConfig.size ?? fetched?.size ?? DEFAULTS.size,
|
|
1119
|
+
cornerStyle: userConfig.cornerStyle ?? fetched?.cornerStyle ?? DEFAULTS.cornerStyle,
|
|
1120
|
+
launcher: {
|
|
1121
|
+
iconUrl: launcherUser.iconUrl ?? launcherFetched.iconUrl,
|
|
1122
|
+
label: launcherUser.label ?? launcherFetched.label,
|
|
1123
|
+
showOnlineDot: launcherUser.showOnlineDot ?? launcherFetched.showOnlineDot ?? false
|
|
1124
|
+
},
|
|
1125
|
+
colorScheme: userConfig.colorScheme ?? DEFAULTS.colorScheme,
|
|
1126
|
+
offset: {
|
|
1127
|
+
bottom: clampInt(offsetUser.bottom, 0, 1e3, DEFAULTS.offsetBottom),
|
|
1128
|
+
side: clampInt(offsetUser.side, 0, 1e3, DEFAULTS.offsetSide)
|
|
1129
|
+
},
|
|
1130
|
+
zIndex: clampInt(userConfig.zIndex, 0, 2e9, DEFAULTS.zIndex),
|
|
1131
|
+
// Defaults to true — the widget shows the attach button unless the
|
|
1132
|
+
// chatbot explicitly opts out via widget_config or the host passes
|
|
1133
|
+
// allowAttachments=false. Server still enforces the same flag at the
|
|
1134
|
+
// upload endpoint either way.
|
|
1135
|
+
allowAttachments: userConfig.allowAttachments ?? fetched?.allowAttachments ?? true
|
|
1031
1136
|
};
|
|
1032
1137
|
}
|
|
1033
1138
|
function sanitizeIncidentBanner(input) {
|
|
@@ -1117,9 +1222,40 @@ var CustomerHeroChat = class {
|
|
|
1117
1222
|
pendingTriggerId: null,
|
|
1118
1223
|
pendingPrefill: null,
|
|
1119
1224
|
incidentBanner: null,
|
|
1120
|
-
incidentBannerDismissed: false
|
|
1225
|
+
incidentBannerDismissed: false,
|
|
1226
|
+
readOnly: false
|
|
1121
1227
|
};
|
|
1122
1228
|
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Mark the config as loaded and put the client into read-only preview
|
|
1231
|
+
* mode without hitting the API. Used by `@customerhero/react/preview` to
|
|
1232
|
+
* render the widget against a host-supplied config (the dashboard preview
|
|
1233
|
+
* pane). Public API consumers should not call this.
|
|
1234
|
+
*
|
|
1235
|
+
* Pass a config to re-resolve and update the rendered colors/size/launcher
|
|
1236
|
+
* in place. Callers should reuse the same client instance across config
|
|
1237
|
+
* changes so the open animation only fires once.
|
|
1238
|
+
*
|
|
1239
|
+
* @internal
|
|
1240
|
+
*/
|
|
1241
|
+
__seedForPreview(config, extras) {
|
|
1242
|
+
const resolved = config ? resolveConfig(config) : this.state.config;
|
|
1243
|
+
if (config) this.userConfig = config;
|
|
1244
|
+
const seededMessages = resolved.welcomeMessage ? [{ role: "bot", content: resolved.welcomeMessage }] : [];
|
|
1245
|
+
const sanitizedBanner = extras && "banner" in extras ? sanitizeIncidentBanner(extras.banner ?? null) : this.state.incidentBanner;
|
|
1246
|
+
this.setState({
|
|
1247
|
+
config: resolved,
|
|
1248
|
+
configLoaded: true,
|
|
1249
|
+
configError: null,
|
|
1250
|
+
readOnly: true,
|
|
1251
|
+
isOpen: true,
|
|
1252
|
+
messages: seededMessages,
|
|
1253
|
+
incidentBanner: sanitizedBanner,
|
|
1254
|
+
// Reset the dismissed flag so toggling the banner on in the dashboard
|
|
1255
|
+
// re-renders it after a previous preview-side dismiss.
|
|
1256
|
+
incidentBannerDismissed: false
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1123
1259
|
// ── Proactive engagement state ─────────────────────────────────────
|
|
1124
1260
|
triggersRuntime = null;
|
|
1125
1261
|
preChatFormSubmitted = false;
|
|
@@ -1228,12 +1364,15 @@ var CustomerHeroChat = class {
|
|
|
1228
1364
|
const { chatbotId, apiBase } = this.state.config;
|
|
1229
1365
|
const { conversationId } = this.state;
|
|
1230
1366
|
if (!conversationId) return;
|
|
1367
|
+
const readToken = this.storage?.getItem(`ch_conv_token_${chatbotId}`);
|
|
1368
|
+
const messagesUrl = `${apiBase}/api/chat/${chatbotId}/messages/${conversationId}`;
|
|
1231
1369
|
try {
|
|
1232
1370
|
const response = await fetch(
|
|
1233
|
-
`${
|
|
1371
|
+
readToken ? `${messagesUrl}?t=${encodeURIComponent(readToken)}` : messagesUrl
|
|
1234
1372
|
);
|
|
1235
1373
|
if (!response.ok) {
|
|
1236
1374
|
this.storage?.removeItem(`ch_conv_${chatbotId}`);
|
|
1375
|
+
this.storage?.removeItem(`ch_conv_token_${chatbotId}`);
|
|
1237
1376
|
this.setState({ conversationId: null });
|
|
1238
1377
|
return;
|
|
1239
1378
|
}
|
|
@@ -1245,7 +1384,8 @@ var CustomerHeroChat = class {
|
|
|
1245
1384
|
content: m.content,
|
|
1246
1385
|
...m.sources ? { sources: m.sources } : {},
|
|
1247
1386
|
...m.blocks ? { blocks: m.blocks } : {},
|
|
1248
|
-
...m.suggestions ? { suggestions: m.suggestions } : {}
|
|
1387
|
+
...m.suggestions ? { suggestions: m.suggestions } : {},
|
|
1388
|
+
...m.attachments?.length ? { attachments: m.attachments } : {}
|
|
1249
1389
|
}));
|
|
1250
1390
|
const lastBotIndex = findLastIndex(
|
|
1251
1391
|
messages,
|
|
@@ -1265,6 +1405,7 @@ var CustomerHeroChat = class {
|
|
|
1265
1405
|
}
|
|
1266
1406
|
}
|
|
1267
1407
|
async sendMessage(message, options) {
|
|
1408
|
+
if (this.state.readOnly) return;
|
|
1268
1409
|
const trimmed = message.trim();
|
|
1269
1410
|
const attachmentTokens = options?.attachmentTokens ?? [];
|
|
1270
1411
|
if (!trimmed || this.state.isLoading) return;
|
|
@@ -1348,6 +1489,16 @@ var CustomerHeroChat = class {
|
|
|
1348
1489
|
}
|
|
1349
1490
|
break;
|
|
1350
1491
|
}
|
|
1492
|
+
case "read-token": {
|
|
1493
|
+
const tok = safeParse(evt.data);
|
|
1494
|
+
if (tok?.readToken) {
|
|
1495
|
+
this.storage?.setItem(
|
|
1496
|
+
`ch_conv_token_${chatbotId}`,
|
|
1497
|
+
tok.readToken
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
break;
|
|
1501
|
+
}
|
|
1351
1502
|
case "token": {
|
|
1352
1503
|
const tok = safeParse(evt.data);
|
|
1353
1504
|
const text = tok?.text ?? "";
|
|
@@ -1460,6 +1611,9 @@ var CustomerHeroChat = class {
|
|
|
1460
1611
|
await this.loadHistory();
|
|
1461
1612
|
return;
|
|
1462
1613
|
}
|
|
1614
|
+
const decisionBlock = this.state.messages[targetIndex].blocks?.find(
|
|
1615
|
+
(b) => b.type === "action_confirmation" && b.pendingToolCallId === pendingId
|
|
1616
|
+
);
|
|
1463
1617
|
const messages = this.state.messages.slice();
|
|
1464
1618
|
const original = messages[targetIndex];
|
|
1465
1619
|
messages[targetIndex] = {
|
|
@@ -1468,7 +1622,8 @@ var CustomerHeroChat = class {
|
|
|
1468
1622
|
};
|
|
1469
1623
|
this.setState({ messages, error: null });
|
|
1470
1624
|
const { chatbotId, apiBase } = this.state.config;
|
|
1471
|
-
const
|
|
1625
|
+
const href = decision === "approve" ? decisionBlock?.approveHref : decisionBlock?.cancelHref;
|
|
1626
|
+
const url = href ? `${apiBase}${href}` : `${apiBase}/api/chat/${chatbotId}/tool-calls/${pendingId}/decision`;
|
|
1472
1627
|
try {
|
|
1473
1628
|
const response = await fetch(url, {
|
|
1474
1629
|
method: "POST",
|
|
@@ -1500,6 +1655,16 @@ var CustomerHeroChat = class {
|
|
|
1500
1655
|
}
|
|
1501
1656
|
break;
|
|
1502
1657
|
}
|
|
1658
|
+
case "read-token": {
|
|
1659
|
+
const tok = safeParse(evt.data);
|
|
1660
|
+
if (tok?.readToken) {
|
|
1661
|
+
this.storage?.setItem(
|
|
1662
|
+
`ch_conv_token_${chatbotId}`,
|
|
1663
|
+
tok.readToken
|
|
1664
|
+
);
|
|
1665
|
+
}
|
|
1666
|
+
break;
|
|
1667
|
+
}
|
|
1503
1668
|
case "token": {
|
|
1504
1669
|
const tok = safeParse(evt.data);
|
|
1505
1670
|
const text = tok?.text ?? "";
|
|
@@ -1606,6 +1771,7 @@ var CustomerHeroChat = class {
|
|
|
1606
1771
|
reset() {
|
|
1607
1772
|
const { chatbotId, welcomeMessage } = this.state.config;
|
|
1608
1773
|
this.storage?.removeItem(`ch_conv_${chatbotId}`);
|
|
1774
|
+
this.storage?.removeItem(`ch_conv_token_${chatbotId}`);
|
|
1609
1775
|
this.setState({
|
|
1610
1776
|
messages: welcomeMessage ? [{ role: "bot", content: welcomeMessage }] : [],
|
|
1611
1777
|
conversationId: null,
|
|
@@ -1773,6 +1939,7 @@ var CustomerHeroChat = class {
|
|
|
1773
1939
|
};
|
|
1774
1940
|
const { chatbotId, welcomeMessage } = this.state.config;
|
|
1775
1941
|
this.storage?.removeItem(`ch_conv_${chatbotId}`);
|
|
1942
|
+
this.storage?.removeItem(`ch_conv_token_${chatbotId}`);
|
|
1776
1943
|
this.setState({
|
|
1777
1944
|
messages: welcomeMessage ? [{ role: "bot", content: welcomeMessage }] : [],
|
|
1778
1945
|
conversationId: null,
|
|
@@ -1817,6 +1984,33 @@ function pickExtension(mime) {
|
|
|
1817
1984
|
return "jpg";
|
|
1818
1985
|
}
|
|
1819
1986
|
|
|
1987
|
+
// src/theme.ts
|
|
1988
|
+
function resolveScheme(colorScheme, prefersDark) {
|
|
1989
|
+
if (colorScheme === "dark") return "dark";
|
|
1990
|
+
if (colorScheme === "light") return "light";
|
|
1991
|
+
return prefersDark ? "dark" : "light";
|
|
1992
|
+
}
|
|
1993
|
+
function effectiveColors(config, scheme) {
|
|
1994
|
+
if (scheme === "dark") {
|
|
1995
|
+
return {
|
|
1996
|
+
primary: config.primaryColorDark ?? DEFAULTS.primaryColorDark,
|
|
1997
|
+
background: config.backgroundColorDark ?? DEFAULTS.backgroundColorDark,
|
|
1998
|
+
text: config.textColorDark ?? DEFAULTS.textColorDark
|
|
1999
|
+
};
|
|
2000
|
+
}
|
|
2001
|
+
return {
|
|
2002
|
+
primary: config.primaryColor,
|
|
2003
|
+
background: config.backgroundColor,
|
|
2004
|
+
text: config.textColor
|
|
2005
|
+
};
|
|
2006
|
+
}
|
|
2007
|
+
function sizePreset(size) {
|
|
2008
|
+
return SIZE_PRESETS[size];
|
|
2009
|
+
}
|
|
2010
|
+
function panelRadius(cornerStyle) {
|
|
2011
|
+
return CORNER_RADIUS[cornerStyle];
|
|
2012
|
+
}
|
|
2013
|
+
|
|
1820
2014
|
// src/screenshot.ts
|
|
1821
2015
|
var ScreenshotCancelled = class extends Error {
|
|
1822
2016
|
constructor(message = "Screenshot cancelled") {
|
|
@@ -1951,8 +2145,10 @@ async function canvasToBlob(canvas, quality) {
|
|
|
1951
2145
|
}
|
|
1952
2146
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1953
2147
|
0 && (module.exports = {
|
|
2148
|
+
CORNER_RADIUS,
|
|
1954
2149
|
CustomerHeroChat,
|
|
1955
2150
|
DEFAULTS,
|
|
2151
|
+
SIZE_PRESETS,
|
|
1956
2152
|
SUPPORTED_LOCALES,
|
|
1957
2153
|
ScreenshotCancelled,
|
|
1958
2154
|
ScreenshotUnavailable,
|
|
@@ -1960,9 +2156,13 @@ async function canvasToBlob(canvas, quality) {
|
|
|
1960
2156
|
captureScreenshot,
|
|
1961
2157
|
createTranslator,
|
|
1962
2158
|
detectLocale,
|
|
2159
|
+
effectiveColors,
|
|
1963
2160
|
evaluate,
|
|
1964
2161
|
isRtlLocale,
|
|
2162
|
+
panelRadius,
|
|
1965
2163
|
pickFire,
|
|
1966
2164
|
resolveLocale,
|
|
2165
|
+
resolveScheme,
|
|
2166
|
+
sizePreset,
|
|
1967
2167
|
startTriggersRuntime
|
|
1968
2168
|
});
|