@customerhero/js 2.1.1 → 2.3.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 +238 -5
- package/dist/index.d.cts +181 -2
- package/dist/index.d.ts +181 -2
- package/dist/index.js +232 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,7 +7,29 @@ var DEFAULTS = {
|
|
|
7
7
|
position: "bottom-right",
|
|
8
8
|
placeholderText: "Type your message...",
|
|
9
9
|
welcomeMessage: "Hi! How can I help you today?",
|
|
10
|
-
title: "CustomerHero"
|
|
10
|
+
title: "CustomerHero",
|
|
11
|
+
// Appearance pack (B1–B6) defaults.
|
|
12
|
+
colorScheme: "light",
|
|
13
|
+
// Dark fallbacks used when the effective scheme is dark and no per-chatbot
|
|
14
|
+
// dark color is configured. Operators can — and should — override these.
|
|
15
|
+
primaryColorDark: "#A78BFA",
|
|
16
|
+
backgroundColorDark: "#0F172A",
|
|
17
|
+
textColorDark: "#E5E7EB",
|
|
18
|
+
size: "default",
|
|
19
|
+
cornerStyle: "rounded",
|
|
20
|
+
offsetBottom: 20,
|
|
21
|
+
offsetSide: 20,
|
|
22
|
+
zIndex: 99999
|
|
23
|
+
};
|
|
24
|
+
var SIZE_PRESETS = {
|
|
25
|
+
compact: { bubble: 48, width: 320, height: 480, fontSize: 13 },
|
|
26
|
+
default: { bubble: 56, width: 380, height: 520, fontSize: 14 },
|
|
27
|
+
large: { bubble: 64, width: 440, height: 600, fontSize: 15 }
|
|
28
|
+
};
|
|
29
|
+
var CORNER_RADIUS = {
|
|
30
|
+
soft: 8,
|
|
31
|
+
rounded: 16,
|
|
32
|
+
square: 0
|
|
11
33
|
};
|
|
12
34
|
|
|
13
35
|
// src/i18n/locales/en.ts
|
|
@@ -36,6 +58,8 @@ var en = {
|
|
|
36
58
|
attach_menu_open: "Add attachment",
|
|
37
59
|
attach_photo: "Choose file",
|
|
38
60
|
drop_files_here: "Drop files here",
|
|
61
|
+
incident_dismiss: "Dismiss",
|
|
62
|
+
incident_default_link_label: "Learn more",
|
|
39
63
|
attachment_unsupported_type: "Unsupported file type"
|
|
40
64
|
};
|
|
41
65
|
|
|
@@ -65,6 +89,8 @@ var es = {
|
|
|
65
89
|
attach_menu_open: "A\xF1adir adjunto",
|
|
66
90
|
attach_photo: "Elegir archivo",
|
|
67
91
|
drop_files_here: "Suelta los archivos aqu\xED",
|
|
92
|
+
incident_dismiss: "Descartar",
|
|
93
|
+
incident_default_link_label: "M\xE1s informaci\xF3n",
|
|
68
94
|
attachment_unsupported_type: "Tipo de archivo no admitido"
|
|
69
95
|
};
|
|
70
96
|
|
|
@@ -94,6 +120,8 @@ var ptBR = {
|
|
|
94
120
|
attach_menu_open: "Adicionar anexo",
|
|
95
121
|
attach_photo: "Escolher arquivo",
|
|
96
122
|
drop_files_here: "Solte os arquivos aqui",
|
|
123
|
+
incident_dismiss: "Dispensar",
|
|
124
|
+
incident_default_link_label: "Saiba mais",
|
|
97
125
|
attachment_unsupported_type: "Tipo de arquivo n\xE3o suportado"
|
|
98
126
|
};
|
|
99
127
|
|
|
@@ -123,6 +151,8 @@ var ptPT = {
|
|
|
123
151
|
attach_menu_open: "Adicionar anexo",
|
|
124
152
|
attach_photo: "Escolher ficheiro",
|
|
125
153
|
drop_files_here: "Largue os ficheiros aqui",
|
|
154
|
+
incident_dismiss: "Dispensar",
|
|
155
|
+
incident_default_link_label: "Saiba mais",
|
|
126
156
|
attachment_unsupported_type: "Tipo de ficheiro n\xE3o suportado"
|
|
127
157
|
};
|
|
128
158
|
|
|
@@ -152,6 +182,8 @@ var fr = {
|
|
|
152
182
|
attach_menu_open: "Ajouter une pi\xE8ce jointe",
|
|
153
183
|
attach_photo: "Choisir un fichier",
|
|
154
184
|
drop_files_here: "D\xE9posez les fichiers ici",
|
|
185
|
+
incident_dismiss: "Ignorer",
|
|
186
|
+
incident_default_link_label: "En savoir plus",
|
|
155
187
|
attachment_unsupported_type: "Type de fichier non pris en charge"
|
|
156
188
|
};
|
|
157
189
|
|
|
@@ -181,6 +213,8 @@ var de = {
|
|
|
181
213
|
attach_menu_open: "Anhang hinzuf\xFCgen",
|
|
182
214
|
attach_photo: "Datei ausw\xE4hlen",
|
|
183
215
|
drop_files_here: "Dateien hier ablegen",
|
|
216
|
+
incident_dismiss: "Schlie\xDFen",
|
|
217
|
+
incident_default_link_label: "Mehr erfahren",
|
|
184
218
|
attachment_unsupported_type: "Dateityp nicht unterst\xFCtzt"
|
|
185
219
|
};
|
|
186
220
|
|
|
@@ -210,6 +244,8 @@ var it = {
|
|
|
210
244
|
attach_menu_open: "Aggiungi allegato",
|
|
211
245
|
attach_photo: "Scegli file",
|
|
212
246
|
drop_files_here: "Trascina qui i file",
|
|
247
|
+
incident_dismiss: "Chiudi",
|
|
248
|
+
incident_default_link_label: "Scopri di pi\xF9",
|
|
213
249
|
attachment_unsupported_type: "Tipo di file non supportato"
|
|
214
250
|
};
|
|
215
251
|
|
|
@@ -239,6 +275,8 @@ var nl = {
|
|
|
239
275
|
attach_menu_open: "Bijlage toevoegen",
|
|
240
276
|
attach_photo: "Bestand kiezen",
|
|
241
277
|
drop_files_here: "Sleep bestanden hier",
|
|
278
|
+
incident_dismiss: "Sluiten",
|
|
279
|
+
incident_default_link_label: "Meer informatie",
|
|
242
280
|
attachment_unsupported_type: "Bestandstype niet ondersteund"
|
|
243
281
|
};
|
|
244
282
|
|
|
@@ -268,6 +306,8 @@ var pl = {
|
|
|
268
306
|
attach_menu_open: "Dodaj za\u0142\u0105cznik",
|
|
269
307
|
attach_photo: "Wybierz plik",
|
|
270
308
|
drop_files_here: "Upu\u015B\u0107 pliki tutaj",
|
|
309
|
+
incident_dismiss: "Zamknij",
|
|
310
|
+
incident_default_link_label: "Dowiedz si\u0119 wi\u0119cej",
|
|
271
311
|
attachment_unsupported_type: "Nieobs\u0142ugiwany typ pliku"
|
|
272
312
|
};
|
|
273
313
|
|
|
@@ -297,6 +337,8 @@ var tr = {
|
|
|
297
337
|
attach_menu_open: "Ek ekle",
|
|
298
338
|
attach_photo: "Dosya se\xE7",
|
|
299
339
|
drop_files_here: "Dosyalar\u0131 buraya b\u0131rak",
|
|
340
|
+
incident_dismiss: "Kapat",
|
|
341
|
+
incident_default_link_label: "Daha fazla bilgi",
|
|
300
342
|
attachment_unsupported_type: "Desteklenmeyen dosya t\xFCr\xFC"
|
|
301
343
|
};
|
|
302
344
|
|
|
@@ -326,6 +368,8 @@ var ar = {
|
|
|
326
368
|
attach_menu_open: "\u0625\u0636\u0627\u0641\u0629 \u0645\u0631\u0641\u0642",
|
|
327
369
|
attach_photo: "\u0627\u062E\u062A\u0631 \u0645\u0644\u0641\u064B\u0627",
|
|
328
370
|
drop_files_here: "\u0623\u0641\u0644\u062A \u0627\u0644\u0645\u0644\u0641\u0627\u062A \u0647\u0646\u0627",
|
|
371
|
+
incident_dismiss: "\u0625\u063A\u0644\u0627\u0642",
|
|
372
|
+
incident_default_link_label: "\u0627\u0639\u0631\u0641 \u0627\u0644\u0645\u0632\u064A\u062F",
|
|
329
373
|
attachment_unsupported_type: "\u0646\u0648\u0639 \u0627\u0644\u0645\u0644\u0641 \u063A\u064A\u0631 \u0645\u062F\u0639\u0648\u0645"
|
|
330
374
|
};
|
|
331
375
|
|
|
@@ -355,6 +399,8 @@ var ja = {
|
|
|
355
399
|
attach_menu_open: "\u6DFB\u4ED8\u30D5\u30A1\u30A4\u30EB\u3092\u8FFD\u52A0",
|
|
356
400
|
attach_photo: "\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E",
|
|
357
401
|
drop_files_here: "\u30D5\u30A1\u30A4\u30EB\u3092\u3053\u3053\u306B\u30C9\u30ED\u30C3\u30D7",
|
|
402
|
+
incident_dismiss: "\u9589\u3058\u308B",
|
|
403
|
+
incident_default_link_label: "\u8A73\u7D30\u3092\u898B\u308B",
|
|
358
404
|
attachment_unsupported_type: "\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u5F62\u5F0F"
|
|
359
405
|
};
|
|
360
406
|
|
|
@@ -384,6 +430,8 @@ var ko = {
|
|
|
384
430
|
attach_menu_open: "\uCCA8\uBD80 \uD30C\uC77C \uCD94\uAC00",
|
|
385
431
|
attach_photo: "\uD30C\uC77C \uC120\uD0DD",
|
|
386
432
|
drop_files_here: "\uD30C\uC77C\uC744 \uC5EC\uAE30\uC5D0 \uB193\uAE30",
|
|
433
|
+
incident_dismiss: "\uB2EB\uAE30",
|
|
434
|
+
incident_default_link_label: "\uC790\uC138\uD788 \uC54C\uC544\uBCF4\uAE30",
|
|
387
435
|
attachment_unsupported_type: "\uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 \uD30C\uC77C \uD615\uC2DD"
|
|
388
436
|
};
|
|
389
437
|
|
|
@@ -413,6 +461,8 @@ var zhCN = {
|
|
|
413
461
|
attach_menu_open: "\u6DFB\u52A0\u9644\u4EF6",
|
|
414
462
|
attach_photo: "\u9009\u62E9\u6587\u4EF6",
|
|
415
463
|
drop_files_here: "\u5C06\u6587\u4EF6\u62D6\u653E\u5230\u6B64\u5904",
|
|
464
|
+
incident_dismiss: "\u5173\u95ED",
|
|
465
|
+
incident_default_link_label: "\u4E86\u89E3\u66F4\u591A",
|
|
416
466
|
attachment_unsupported_type: "\u4E0D\u652F\u6301\u7684\u6587\u4EF6\u7C7B\u578B"
|
|
417
467
|
};
|
|
418
468
|
|
|
@@ -442,6 +492,8 @@ var zhTW = {
|
|
|
442
492
|
attach_menu_open: "\u65B0\u589E\u9644\u4EF6",
|
|
443
493
|
attach_photo: "\u9078\u64C7\u6A94\u6848",
|
|
444
494
|
drop_files_here: "\u5C07\u6A94\u6848\u62D6\u653E\u5230\u6B64\u8655",
|
|
495
|
+
incident_dismiss: "\u95DC\u9589",
|
|
496
|
+
incident_default_link_label: "\u77AD\u89E3\u66F4\u591A",
|
|
445
497
|
attachment_unsupported_type: "\u4E0D\u652F\u63F4\u7684\u6A94\u6848\u985E\u578B"
|
|
446
498
|
};
|
|
447
499
|
|
|
@@ -945,7 +997,14 @@ function startTriggersRuntime(options) {
|
|
|
945
997
|
}
|
|
946
998
|
|
|
947
999
|
// src/client.ts
|
|
1000
|
+
function clampInt(value, min, max, fallback) {
|
|
1001
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
1002
|
+
return Math.max(min, Math.min(max, Math.trunc(value)));
|
|
1003
|
+
}
|
|
948
1004
|
function resolveConfig(userConfig, fetched) {
|
|
1005
|
+
const launcherUser = userConfig.launcher ?? {};
|
|
1006
|
+
const launcherFetched = fetched?.launcher ?? {};
|
|
1007
|
+
const offsetUser = userConfig.offset ?? {};
|
|
949
1008
|
return {
|
|
950
1009
|
chatbotId: userConfig.chatbotId,
|
|
951
1010
|
apiBase: userConfig.apiBase ?? DEFAULTS.apiBase,
|
|
@@ -958,12 +1017,78 @@ function resolveConfig(userConfig, fetched) {
|
|
|
958
1017
|
title: userConfig.title ?? fetched?.title ?? DEFAULTS.title,
|
|
959
1018
|
avatarUrl: userConfig.avatarUrl ?? fetched?.avatarUrl,
|
|
960
1019
|
suggestedMessages: userConfig.suggestedMessages ?? fetched?.suggestedMessages ?? [],
|
|
961
|
-
stringOverrides: fetched?.stringOverrides
|
|
1020
|
+
stringOverrides: fetched?.stringOverrides,
|
|
1021
|
+
// Appearance pack. Color palette + size + corner style + launcher all
|
|
1022
|
+
// come from the server widget_config (with host-side override). The
|
|
1023
|
+
// *runtime* knobs — colorScheme, offset, zIndex — are host-only because
|
|
1024
|
+
// they depend on the page the widget is embedded in, not the chatbot.
|
|
1025
|
+
primaryColorDark: userConfig.primaryColorDark ?? fetched?.primaryColorDark,
|
|
1026
|
+
backgroundColorDark: userConfig.backgroundColorDark ?? fetched?.backgroundColorDark,
|
|
1027
|
+
textColorDark: userConfig.textColorDark ?? fetched?.textColorDark,
|
|
1028
|
+
size: userConfig.size ?? fetched?.size ?? DEFAULTS.size,
|
|
1029
|
+
cornerStyle: userConfig.cornerStyle ?? fetched?.cornerStyle ?? DEFAULTS.cornerStyle,
|
|
1030
|
+
launcher: {
|
|
1031
|
+
iconUrl: launcherUser.iconUrl ?? launcherFetched.iconUrl,
|
|
1032
|
+
label: launcherUser.label ?? launcherFetched.label,
|
|
1033
|
+
showOnlineDot: launcherUser.showOnlineDot ?? launcherFetched.showOnlineDot ?? false
|
|
1034
|
+
},
|
|
1035
|
+
colorScheme: userConfig.colorScheme ?? DEFAULTS.colorScheme,
|
|
1036
|
+
offset: {
|
|
1037
|
+
bottom: clampInt(offsetUser.bottom, 0, 1e3, DEFAULTS.offsetBottom),
|
|
1038
|
+
side: clampInt(offsetUser.side, 0, 1e3, DEFAULTS.offsetSide)
|
|
1039
|
+
},
|
|
1040
|
+
zIndex: clampInt(userConfig.zIndex, 0, 2e9, DEFAULTS.zIndex),
|
|
1041
|
+
// Defaults to true — the widget shows the attach button unless the
|
|
1042
|
+
// chatbot explicitly opts out via widget_config or the host passes
|
|
1043
|
+
// allowAttachments=false. Server still enforces the same flag at the
|
|
1044
|
+
// upload endpoint either way.
|
|
1045
|
+
allowAttachments: userConfig.allowAttachments ?? fetched?.allowAttachments ?? true
|
|
962
1046
|
};
|
|
963
1047
|
}
|
|
1048
|
+
function sanitizeIncidentBanner(input) {
|
|
1049
|
+
if (!input || typeof input !== "object") return null;
|
|
1050
|
+
const raw = input;
|
|
1051
|
+
const sev = raw.severity;
|
|
1052
|
+
if (sev !== "info" && sev !== "warning" && sev !== "outage") return null;
|
|
1053
|
+
if (typeof raw.title !== "string" || raw.title.length === 0) return null;
|
|
1054
|
+
if (typeof raw.expiresAt === "string") {
|
|
1055
|
+
const t = Date.parse(raw.expiresAt);
|
|
1056
|
+
if (!Number.isNaN(t) && t <= Date.now()) return null;
|
|
1057
|
+
}
|
|
1058
|
+
const out = { severity: sev, title: raw.title };
|
|
1059
|
+
if (typeof raw.body === "string") out.body = raw.body;
|
|
1060
|
+
if (typeof raw.eta === "string") out.eta = raw.eta;
|
|
1061
|
+
if (raw.link && typeof raw.link === "object") {
|
|
1062
|
+
const link = raw.link;
|
|
1063
|
+
if (typeof link.url === "string") {
|
|
1064
|
+
out.link = { url: link.url };
|
|
1065
|
+
if (typeof link.label === "string") out.link.label = link.label;
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
if (typeof raw.expiresAt === "string") out.expiresAt = raw.expiresAt;
|
|
1069
|
+
return out;
|
|
1070
|
+
}
|
|
1071
|
+
function bannerKey(banner) {
|
|
1072
|
+
if (!banner) return null;
|
|
1073
|
+
return JSON.stringify([
|
|
1074
|
+
banner.severity,
|
|
1075
|
+
banner.title,
|
|
1076
|
+
banner.body ?? "",
|
|
1077
|
+
banner.eta ?? "",
|
|
1078
|
+
banner.link?.url ?? "",
|
|
1079
|
+
banner.link?.label ?? "",
|
|
1080
|
+
banner.expiresAt ?? ""
|
|
1081
|
+
]);
|
|
1082
|
+
}
|
|
964
1083
|
function getStorage() {
|
|
965
1084
|
try {
|
|
966
|
-
|
|
1085
|
+
if (typeof window !== "undefined" && window.localStorage)
|
|
1086
|
+
return window.localStorage;
|
|
1087
|
+
if (typeof globalThis !== "undefined") {
|
|
1088
|
+
const ls = globalThis.localStorage;
|
|
1089
|
+
if (ls) return ls;
|
|
1090
|
+
}
|
|
1091
|
+
return null;
|
|
967
1092
|
} catch {
|
|
968
1093
|
return null;
|
|
969
1094
|
}
|
|
@@ -1005,9 +1130,42 @@ var CustomerHeroChat = class {
|
|
|
1005
1130
|
preChatSubmission: null,
|
|
1006
1131
|
consent: this.readStoredConsent(),
|
|
1007
1132
|
pendingTriggerId: null,
|
|
1008
|
-
pendingPrefill: null
|
|
1133
|
+
pendingPrefill: null,
|
|
1134
|
+
incidentBanner: null,
|
|
1135
|
+
incidentBannerDismissed: false,
|
|
1136
|
+
readOnly: false
|
|
1009
1137
|
};
|
|
1010
1138
|
}
|
|
1139
|
+
/**
|
|
1140
|
+
* Mark the config as loaded and put the client into read-only preview
|
|
1141
|
+
* mode without hitting the API. Used by `@customerhero/react/preview` to
|
|
1142
|
+
* render the widget against a host-supplied config (the dashboard preview
|
|
1143
|
+
* pane). Public API consumers should not call this.
|
|
1144
|
+
*
|
|
1145
|
+
* Pass a config to re-resolve and update the rendered colors/size/launcher
|
|
1146
|
+
* in place. Callers should reuse the same client instance across config
|
|
1147
|
+
* changes so the open animation only fires once.
|
|
1148
|
+
*
|
|
1149
|
+
* @internal
|
|
1150
|
+
*/
|
|
1151
|
+
__seedForPreview(config, extras) {
|
|
1152
|
+
const resolved = config ? resolveConfig(config) : this.state.config;
|
|
1153
|
+
if (config) this.userConfig = config;
|
|
1154
|
+
const seededMessages = resolved.welcomeMessage ? [{ role: "bot", content: resolved.welcomeMessage }] : [];
|
|
1155
|
+
const sanitizedBanner = extras && "banner" in extras ? sanitizeIncidentBanner(extras.banner ?? null) : this.state.incidentBanner;
|
|
1156
|
+
this.setState({
|
|
1157
|
+
config: resolved,
|
|
1158
|
+
configLoaded: true,
|
|
1159
|
+
configError: null,
|
|
1160
|
+
readOnly: true,
|
|
1161
|
+
isOpen: true,
|
|
1162
|
+
messages: seededMessages,
|
|
1163
|
+
incidentBanner: sanitizedBanner,
|
|
1164
|
+
// Reset the dismissed flag so toggling the banner on in the dashboard
|
|
1165
|
+
// re-renders it after a previous preview-side dismiss.
|
|
1166
|
+
incidentBannerDismissed: false
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1011
1169
|
// ── Proactive engagement state ─────────────────────────────────────
|
|
1012
1170
|
triggersRuntime = null;
|
|
1013
1171
|
preChatFormSubmitted = false;
|
|
@@ -1084,11 +1242,18 @@ var CustomerHeroChat = class {
|
|
|
1084
1242
|
const resolved = resolveConfig(this.userConfig, fetched);
|
|
1085
1243
|
const triggers = Array.isArray(fetched.triggers) ? fetched.triggers : [];
|
|
1086
1244
|
const preChatForm = fetched.preChatForm ?? null;
|
|
1245
|
+
const incidentBanner = sanitizeIncidentBanner(fetched.incidentBanner);
|
|
1246
|
+
const prevBannerKey = bannerKey(this.state.incidentBanner);
|
|
1247
|
+
const nextBannerKey = bannerKey(incidentBanner);
|
|
1248
|
+
const dismissedFromStorage = nextBannerKey && nextBannerKey === this.readStoredBannerDismissal();
|
|
1249
|
+
const incidentBannerDismissed = nextBannerKey === prevBannerKey ? this.state.incidentBannerDismissed || !!dismissedFromStorage : !!dismissedFromStorage;
|
|
1087
1250
|
this.setState({
|
|
1088
1251
|
config: resolved,
|
|
1089
1252
|
configLoaded: true,
|
|
1090
1253
|
triggers,
|
|
1091
|
-
preChatForm
|
|
1254
|
+
preChatForm,
|
|
1255
|
+
incidentBanner,
|
|
1256
|
+
incidentBannerDismissed
|
|
1092
1257
|
});
|
|
1093
1258
|
if (resolved.stringOverrides) this.rebuildTranslator();
|
|
1094
1259
|
this.startTriggersRuntimeIfPossible();
|
|
@@ -1146,6 +1311,7 @@ var CustomerHeroChat = class {
|
|
|
1146
1311
|
}
|
|
1147
1312
|
}
|
|
1148
1313
|
async sendMessage(message, options) {
|
|
1314
|
+
if (this.state.readOnly) return;
|
|
1149
1315
|
const trimmed = message.trim();
|
|
1150
1316
|
const attachmentTokens = options?.attachmentTokens ?? [];
|
|
1151
1317
|
if (!trimmed || this.state.isLoading) return;
|
|
@@ -1513,6 +1679,34 @@ var CustomerHeroChat = class {
|
|
|
1513
1679
|
setTraits(traits) {
|
|
1514
1680
|
this.triggersRuntime?.setTraits(traits);
|
|
1515
1681
|
}
|
|
1682
|
+
/** Hide the active incident banner for this visitor. Persisted in
|
|
1683
|
+
* localStorage so a refresh keeps it dismissed; resets automatically
|
|
1684
|
+
* when the operator changes the banner content. No-op when no banner
|
|
1685
|
+
* is showing. */
|
|
1686
|
+
dismissIncidentBanner() {
|
|
1687
|
+
const key = bannerKey(this.state.incidentBanner);
|
|
1688
|
+
if (!key) return;
|
|
1689
|
+
this.writeStoredBannerDismissal(key);
|
|
1690
|
+
this.setState({ incidentBannerDismissed: true });
|
|
1691
|
+
}
|
|
1692
|
+
readStoredBannerDismissal() {
|
|
1693
|
+
try {
|
|
1694
|
+
return this.storage?.getItem(
|
|
1695
|
+
`ch_incident_dismissed_${this.userConfig.chatbotId}`
|
|
1696
|
+
) ?? null;
|
|
1697
|
+
} catch {
|
|
1698
|
+
return null;
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
writeStoredBannerDismissal(key) {
|
|
1702
|
+
try {
|
|
1703
|
+
this.storage?.setItem(
|
|
1704
|
+
`ch_incident_dismissed_${this.userConfig.chatbotId}`,
|
|
1705
|
+
key
|
|
1706
|
+
);
|
|
1707
|
+
} catch {
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1516
1710
|
/** Submit pre-chat form answers. Synthesizes a customer record server-side
|
|
1517
1711
|
* on the next sendMessage. Resumes any pending message that was deferred
|
|
1518
1712
|
* while the form was open. */
|
|
@@ -1670,6 +1864,33 @@ function pickExtension(mime) {
|
|
|
1670
1864
|
return "jpg";
|
|
1671
1865
|
}
|
|
1672
1866
|
|
|
1867
|
+
// src/theme.ts
|
|
1868
|
+
function resolveScheme(colorScheme, prefersDark) {
|
|
1869
|
+
if (colorScheme === "dark") return "dark";
|
|
1870
|
+
if (colorScheme === "light") return "light";
|
|
1871
|
+
return prefersDark ? "dark" : "light";
|
|
1872
|
+
}
|
|
1873
|
+
function effectiveColors(config, scheme) {
|
|
1874
|
+
if (scheme === "dark") {
|
|
1875
|
+
return {
|
|
1876
|
+
primary: config.primaryColorDark ?? DEFAULTS.primaryColorDark,
|
|
1877
|
+
background: config.backgroundColorDark ?? DEFAULTS.backgroundColorDark,
|
|
1878
|
+
text: config.textColorDark ?? DEFAULTS.textColorDark
|
|
1879
|
+
};
|
|
1880
|
+
}
|
|
1881
|
+
return {
|
|
1882
|
+
primary: config.primaryColor,
|
|
1883
|
+
background: config.backgroundColor,
|
|
1884
|
+
text: config.textColor
|
|
1885
|
+
};
|
|
1886
|
+
}
|
|
1887
|
+
function sizePreset(size) {
|
|
1888
|
+
return SIZE_PRESETS[size];
|
|
1889
|
+
}
|
|
1890
|
+
function panelRadius(cornerStyle) {
|
|
1891
|
+
return CORNER_RADIUS[cornerStyle];
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1673
1894
|
// src/screenshot.ts
|
|
1674
1895
|
var ScreenshotCancelled = class extends Error {
|
|
1675
1896
|
constructor(message = "Screenshot cancelled") {
|
|
@@ -1803,8 +2024,10 @@ async function canvasToBlob(canvas, quality) {
|
|
|
1803
2024
|
});
|
|
1804
2025
|
}
|
|
1805
2026
|
export {
|
|
2027
|
+
CORNER_RADIUS,
|
|
1806
2028
|
CustomerHeroChat,
|
|
1807
2029
|
DEFAULTS,
|
|
2030
|
+
SIZE_PRESETS,
|
|
1808
2031
|
SUPPORTED_LOCALES,
|
|
1809
2032
|
ScreenshotCancelled,
|
|
1810
2033
|
ScreenshotUnavailable,
|
|
@@ -1812,9 +2035,13 @@ export {
|
|
|
1812
2035
|
captureScreenshot,
|
|
1813
2036
|
createTranslator,
|
|
1814
2037
|
detectLocale,
|
|
2038
|
+
effectiveColors,
|
|
1815
2039
|
evaluate,
|
|
1816
2040
|
isRtlLocale,
|
|
2041
|
+
panelRadius,
|
|
1817
2042
|
pickFire,
|
|
1818
2043
|
resolveLocale,
|
|
2044
|
+
resolveScheme,
|
|
2045
|
+
sizePreset,
|
|
1819
2046
|
startTriggersRuntime
|
|
1820
2047
|
};
|