@customerhero/js 2.2.0 → 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 +128 -3
- package/dist/index.d.cts +154 -1
- package/dist/index.d.ts +154 -1
- package/dist/index.js +122 -3
- 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
|
|
@@ -1014,7 +1042,14 @@ function startTriggersRuntime(options) {
|
|
|
1014
1042
|
}
|
|
1015
1043
|
|
|
1016
1044
|
// src/client.ts
|
|
1045
|
+
function clampInt(value, min, max, fallback) {
|
|
1046
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
1047
|
+
return Math.max(min, Math.min(max, Math.trunc(value)));
|
|
1048
|
+
}
|
|
1017
1049
|
function resolveConfig(userConfig, fetched) {
|
|
1050
|
+
const launcherUser = userConfig.launcher ?? {};
|
|
1051
|
+
const launcherFetched = fetched?.launcher ?? {};
|
|
1052
|
+
const offsetUser = userConfig.offset ?? {};
|
|
1018
1053
|
return {
|
|
1019
1054
|
chatbotId: userConfig.chatbotId,
|
|
1020
1055
|
apiBase: userConfig.apiBase ?? DEFAULTS.apiBase,
|
|
@@ -1027,7 +1062,32 @@ function resolveConfig(userConfig, fetched) {
|
|
|
1027
1062
|
title: userConfig.title ?? fetched?.title ?? DEFAULTS.title,
|
|
1028
1063
|
avatarUrl: userConfig.avatarUrl ?? fetched?.avatarUrl,
|
|
1029
1064
|
suggestedMessages: userConfig.suggestedMessages ?? fetched?.suggestedMessages ?? [],
|
|
1030
|
-
stringOverrides: fetched?.stringOverrides
|
|
1065
|
+
stringOverrides: fetched?.stringOverrides,
|
|
1066
|
+
// Appearance pack. Color palette + size + corner style + launcher all
|
|
1067
|
+
// come from the server widget_config (with host-side override). The
|
|
1068
|
+
// *runtime* knobs — colorScheme, offset, zIndex — are host-only because
|
|
1069
|
+
// they depend on the page the widget is embedded in, not the chatbot.
|
|
1070
|
+
primaryColorDark: userConfig.primaryColorDark ?? fetched?.primaryColorDark,
|
|
1071
|
+
backgroundColorDark: userConfig.backgroundColorDark ?? fetched?.backgroundColorDark,
|
|
1072
|
+
textColorDark: userConfig.textColorDark ?? fetched?.textColorDark,
|
|
1073
|
+
size: userConfig.size ?? fetched?.size ?? DEFAULTS.size,
|
|
1074
|
+
cornerStyle: userConfig.cornerStyle ?? fetched?.cornerStyle ?? DEFAULTS.cornerStyle,
|
|
1075
|
+
launcher: {
|
|
1076
|
+
iconUrl: launcherUser.iconUrl ?? launcherFetched.iconUrl,
|
|
1077
|
+
label: launcherUser.label ?? launcherFetched.label,
|
|
1078
|
+
showOnlineDot: launcherUser.showOnlineDot ?? launcherFetched.showOnlineDot ?? false
|
|
1079
|
+
},
|
|
1080
|
+
colorScheme: userConfig.colorScheme ?? DEFAULTS.colorScheme,
|
|
1081
|
+
offset: {
|
|
1082
|
+
bottom: clampInt(offsetUser.bottom, 0, 1e3, DEFAULTS.offsetBottom),
|
|
1083
|
+
side: clampInt(offsetUser.side, 0, 1e3, DEFAULTS.offsetSide)
|
|
1084
|
+
},
|
|
1085
|
+
zIndex: clampInt(userConfig.zIndex, 0, 2e9, DEFAULTS.zIndex),
|
|
1086
|
+
// Defaults to true — the widget shows the attach button unless the
|
|
1087
|
+
// chatbot explicitly opts out via widget_config or the host passes
|
|
1088
|
+
// allowAttachments=false. Server still enforces the same flag at the
|
|
1089
|
+
// upload endpoint either way.
|
|
1090
|
+
allowAttachments: userConfig.allowAttachments ?? fetched?.allowAttachments ?? true
|
|
1031
1091
|
};
|
|
1032
1092
|
}
|
|
1033
1093
|
function sanitizeIncidentBanner(input) {
|
|
@@ -1117,9 +1177,40 @@ var CustomerHeroChat = class {
|
|
|
1117
1177
|
pendingTriggerId: null,
|
|
1118
1178
|
pendingPrefill: null,
|
|
1119
1179
|
incidentBanner: null,
|
|
1120
|
-
incidentBannerDismissed: false
|
|
1180
|
+
incidentBannerDismissed: false,
|
|
1181
|
+
readOnly: false
|
|
1121
1182
|
};
|
|
1122
1183
|
}
|
|
1184
|
+
/**
|
|
1185
|
+
* Mark the config as loaded and put the client into read-only preview
|
|
1186
|
+
* mode without hitting the API. Used by `@customerhero/react/preview` to
|
|
1187
|
+
* render the widget against a host-supplied config (the dashboard preview
|
|
1188
|
+
* pane). Public API consumers should not call this.
|
|
1189
|
+
*
|
|
1190
|
+
* Pass a config to re-resolve and update the rendered colors/size/launcher
|
|
1191
|
+
* in place. Callers should reuse the same client instance across config
|
|
1192
|
+
* changes so the open animation only fires once.
|
|
1193
|
+
*
|
|
1194
|
+
* @internal
|
|
1195
|
+
*/
|
|
1196
|
+
__seedForPreview(config, extras) {
|
|
1197
|
+
const resolved = config ? resolveConfig(config) : this.state.config;
|
|
1198
|
+
if (config) this.userConfig = config;
|
|
1199
|
+
const seededMessages = resolved.welcomeMessage ? [{ role: "bot", content: resolved.welcomeMessage }] : [];
|
|
1200
|
+
const sanitizedBanner = extras && "banner" in extras ? sanitizeIncidentBanner(extras.banner ?? null) : this.state.incidentBanner;
|
|
1201
|
+
this.setState({
|
|
1202
|
+
config: resolved,
|
|
1203
|
+
configLoaded: true,
|
|
1204
|
+
configError: null,
|
|
1205
|
+
readOnly: true,
|
|
1206
|
+
isOpen: true,
|
|
1207
|
+
messages: seededMessages,
|
|
1208
|
+
incidentBanner: sanitizedBanner,
|
|
1209
|
+
// Reset the dismissed flag so toggling the banner on in the dashboard
|
|
1210
|
+
// re-renders it after a previous preview-side dismiss.
|
|
1211
|
+
incidentBannerDismissed: false
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1123
1214
|
// ── Proactive engagement state ─────────────────────────────────────
|
|
1124
1215
|
triggersRuntime = null;
|
|
1125
1216
|
preChatFormSubmitted = false;
|
|
@@ -1265,6 +1356,7 @@ var CustomerHeroChat = class {
|
|
|
1265
1356
|
}
|
|
1266
1357
|
}
|
|
1267
1358
|
async sendMessage(message, options) {
|
|
1359
|
+
if (this.state.readOnly) return;
|
|
1268
1360
|
const trimmed = message.trim();
|
|
1269
1361
|
const attachmentTokens = options?.attachmentTokens ?? [];
|
|
1270
1362
|
if (!trimmed || this.state.isLoading) return;
|
|
@@ -1817,6 +1909,33 @@ function pickExtension(mime) {
|
|
|
1817
1909
|
return "jpg";
|
|
1818
1910
|
}
|
|
1819
1911
|
|
|
1912
|
+
// src/theme.ts
|
|
1913
|
+
function resolveScheme(colorScheme, prefersDark) {
|
|
1914
|
+
if (colorScheme === "dark") return "dark";
|
|
1915
|
+
if (colorScheme === "light") return "light";
|
|
1916
|
+
return prefersDark ? "dark" : "light";
|
|
1917
|
+
}
|
|
1918
|
+
function effectiveColors(config, scheme) {
|
|
1919
|
+
if (scheme === "dark") {
|
|
1920
|
+
return {
|
|
1921
|
+
primary: config.primaryColorDark ?? DEFAULTS.primaryColorDark,
|
|
1922
|
+
background: config.backgroundColorDark ?? DEFAULTS.backgroundColorDark,
|
|
1923
|
+
text: config.textColorDark ?? DEFAULTS.textColorDark
|
|
1924
|
+
};
|
|
1925
|
+
}
|
|
1926
|
+
return {
|
|
1927
|
+
primary: config.primaryColor,
|
|
1928
|
+
background: config.backgroundColor,
|
|
1929
|
+
text: config.textColor
|
|
1930
|
+
};
|
|
1931
|
+
}
|
|
1932
|
+
function sizePreset(size) {
|
|
1933
|
+
return SIZE_PRESETS[size];
|
|
1934
|
+
}
|
|
1935
|
+
function panelRadius(cornerStyle) {
|
|
1936
|
+
return CORNER_RADIUS[cornerStyle];
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1820
1939
|
// src/screenshot.ts
|
|
1821
1940
|
var ScreenshotCancelled = class extends Error {
|
|
1822
1941
|
constructor(message = "Screenshot cancelled") {
|
|
@@ -1951,8 +2070,10 @@ async function canvasToBlob(canvas, quality) {
|
|
|
1951
2070
|
}
|
|
1952
2071
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1953
2072
|
0 && (module.exports = {
|
|
2073
|
+
CORNER_RADIUS,
|
|
1954
2074
|
CustomerHeroChat,
|
|
1955
2075
|
DEFAULTS,
|
|
2076
|
+
SIZE_PRESETS,
|
|
1956
2077
|
SUPPORTED_LOCALES,
|
|
1957
2078
|
ScreenshotCancelled,
|
|
1958
2079
|
ScreenshotUnavailable,
|
|
@@ -1960,9 +2081,13 @@ async function canvasToBlob(canvas, quality) {
|
|
|
1960
2081
|
captureScreenshot,
|
|
1961
2082
|
createTranslator,
|
|
1962
2083
|
detectLocale,
|
|
2084
|
+
effectiveColors,
|
|
1963
2085
|
evaluate,
|
|
1964
2086
|
isRtlLocale,
|
|
2087
|
+
panelRadius,
|
|
1965
2088
|
pickFire,
|
|
1966
2089
|
resolveLocale,
|
|
2090
|
+
resolveScheme,
|
|
2091
|
+
sizePreset,
|
|
1967
2092
|
startTriggersRuntime
|
|
1968
2093
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -35,6 +35,52 @@ interface CustomerHeroChatConfig {
|
|
|
35
35
|
locale?: string;
|
|
36
36
|
/** Predefined quick-reply options shown before the user sends a message */
|
|
37
37
|
suggestedMessages?: string[];
|
|
38
|
+
/**
|
|
39
|
+
* Color scheme. `auto` follows the visitor's OS preference; `light` and
|
|
40
|
+
* `dark` force a fixed palette. Defaults to `light` when unset.
|
|
41
|
+
*/
|
|
42
|
+
colorScheme?: "auto" | "light" | "dark";
|
|
43
|
+
/** Primary color used in dark mode. Only honoured when the effective
|
|
44
|
+
* scheme resolves to dark; never auto-derived from `primaryColor`. */
|
|
45
|
+
primaryColorDark?: string;
|
|
46
|
+
/** Background color used in dark mode. Only honoured when the effective
|
|
47
|
+
* scheme resolves to dark; never auto-derived from `backgroundColor`. */
|
|
48
|
+
backgroundColorDark?: string;
|
|
49
|
+
/** Text color used in dark mode. Only honoured when the effective scheme
|
|
50
|
+
* resolves to dark; never auto-derived from `textColor`. */
|
|
51
|
+
textColorDark?: string;
|
|
52
|
+
/** Widget size preset. Affects launcher diameter, panel dimensions, and
|
|
53
|
+
* base font size. Defaults to `default`. */
|
|
54
|
+
size?: "compact" | "default" | "large";
|
|
55
|
+
/** Corner radius preset for the chat panel. `soft` ~ small radius,
|
|
56
|
+
* `rounded` ~ medium (default), `square` ~ 0. */
|
|
57
|
+
cornerStyle?: "soft" | "rounded" | "square";
|
|
58
|
+
/** Launcher (floating bubble) customization. Each field is optional. */
|
|
59
|
+
launcher?: {
|
|
60
|
+
/** Custom launcher icon URL. Replaces the default chat-bubble glyph. */
|
|
61
|
+
iconUrl?: string;
|
|
62
|
+
/** Optional CTA label shown next to the launcher (turns the bubble into
|
|
63
|
+
* a pill). Max 60 characters. */
|
|
64
|
+
label?: string;
|
|
65
|
+
/** When true, render a small green dot on the launcher to advertise
|
|
66
|
+
* agent availability. The host site is responsible for keeping
|
|
67
|
+
* business-hours state in sync; the SDK only renders the dot. */
|
|
68
|
+
showOnlineDot?: boolean;
|
|
69
|
+
};
|
|
70
|
+
/** Pixel offsets so the widget can sit above sticky cookie bars or chat
|
|
71
|
+
* CTAs. Each axis defaults to 20 px when unset. Clamped to 0–1000. */
|
|
72
|
+
offset?: {
|
|
73
|
+
bottom?: number;
|
|
74
|
+
side?: number;
|
|
75
|
+
};
|
|
76
|
+
/** Z-index override for sites whose overlays clip the widget. Defaults
|
|
77
|
+
* to 99999. Capped at 2_000_000_000. */
|
|
78
|
+
zIndex?: number;
|
|
79
|
+
/** When false, the input's attach button is hidden so visitors can't
|
|
80
|
+
* even attempt an upload (the server enforces the same flag). Defaults
|
|
81
|
+
* to true. Per-chatbot, sourced from the public widget config endpoint
|
|
82
|
+
* but overrideable on the host. */
|
|
83
|
+
allowAttachments?: boolean;
|
|
38
84
|
}
|
|
39
85
|
|
|
40
86
|
interface ResolvedConfig {
|
|
@@ -51,6 +97,23 @@ interface ResolvedConfig {
|
|
|
51
97
|
suggestedMessages: string[];
|
|
52
98
|
/** Per-chatbot overrides for any translation key, optionally per-locale. */
|
|
53
99
|
stringOverrides?: StringOverrides;
|
|
100
|
+
colorScheme: "auto" | "light" | "dark";
|
|
101
|
+
primaryColorDark?: string;
|
|
102
|
+
backgroundColorDark?: string;
|
|
103
|
+
textColorDark?: string;
|
|
104
|
+
size: "compact" | "default" | "large";
|
|
105
|
+
cornerStyle: "soft" | "rounded" | "square";
|
|
106
|
+
launcher: {
|
|
107
|
+
iconUrl?: string;
|
|
108
|
+
label?: string;
|
|
109
|
+
showOnlineDot: boolean;
|
|
110
|
+
};
|
|
111
|
+
offset: {
|
|
112
|
+
bottom: number;
|
|
113
|
+
side: number;
|
|
114
|
+
};
|
|
115
|
+
zIndex: number;
|
|
116
|
+
allowAttachments: boolean;
|
|
54
117
|
}
|
|
55
118
|
interface MessageSource {
|
|
56
119
|
index: number;
|
|
@@ -303,6 +366,10 @@ interface ChatState {
|
|
|
303
366
|
/** True when the visitor has dismissed the active banner this session.
|
|
304
367
|
* Reset whenever a new banner (different content) lands. */
|
|
305
368
|
incidentBannerDismissed: boolean;
|
|
369
|
+
/** When true, the chat input is disabled and `sendMessage` is a no-op.
|
|
370
|
+
* Used by the dashboard preview (and any other host that wants a
|
|
371
|
+
* visual-only render). Public API consumers should not set this. */
|
|
372
|
+
readOnly: boolean;
|
|
306
373
|
}
|
|
307
374
|
|
|
308
375
|
type Listener = (state: ChatState) => void;
|
|
@@ -314,6 +381,21 @@ declare class CustomerHeroChat {
|
|
|
314
381
|
private identityData;
|
|
315
382
|
t: TranslateFn;
|
|
316
383
|
constructor(config: CustomerHeroChatConfig);
|
|
384
|
+
/**
|
|
385
|
+
* Mark the config as loaded and put the client into read-only preview
|
|
386
|
+
* mode without hitting the API. Used by `@customerhero/react/preview` to
|
|
387
|
+
* render the widget against a host-supplied config (the dashboard preview
|
|
388
|
+
* pane). Public API consumers should not call this.
|
|
389
|
+
*
|
|
390
|
+
* Pass a config to re-resolve and update the rendered colors/size/launcher
|
|
391
|
+
* in place. Callers should reuse the same client instance across config
|
|
392
|
+
* changes so the open animation only fires once.
|
|
393
|
+
*
|
|
394
|
+
* @internal
|
|
395
|
+
*/
|
|
396
|
+
__seedForPreview(config?: CustomerHeroChatConfig, extras?: {
|
|
397
|
+
banner?: IncidentBanner | null;
|
|
398
|
+
}): void;
|
|
317
399
|
private triggersRuntime;
|
|
318
400
|
private preChatFormSubmitted;
|
|
319
401
|
private readStoredConsent;
|
|
@@ -400,7 +482,78 @@ declare const DEFAULTS: {
|
|
|
400
482
|
placeholderText: string;
|
|
401
483
|
welcomeMessage: string;
|
|
402
484
|
title: string;
|
|
485
|
+
colorScheme: "auto" | "light" | "dark";
|
|
486
|
+
primaryColorDark: string;
|
|
487
|
+
backgroundColorDark: string;
|
|
488
|
+
textColorDark: string;
|
|
489
|
+
size: "compact" | "default" | "large";
|
|
490
|
+
cornerStyle: "soft" | "rounded" | "square";
|
|
491
|
+
offsetBottom: number;
|
|
492
|
+
offsetSide: number;
|
|
493
|
+
zIndex: number;
|
|
494
|
+
};
|
|
495
|
+
declare const SIZE_PRESETS: {
|
|
496
|
+
readonly compact: {
|
|
497
|
+
readonly bubble: 48;
|
|
498
|
+
readonly width: 320;
|
|
499
|
+
readonly height: 480;
|
|
500
|
+
readonly fontSize: 13;
|
|
501
|
+
};
|
|
502
|
+
readonly default: {
|
|
503
|
+
readonly bubble: 56;
|
|
504
|
+
readonly width: 380;
|
|
505
|
+
readonly height: 520;
|
|
506
|
+
readonly fontSize: 14;
|
|
507
|
+
};
|
|
508
|
+
readonly large: {
|
|
509
|
+
readonly bubble: 64;
|
|
510
|
+
readonly width: 440;
|
|
511
|
+
readonly height: 600;
|
|
512
|
+
readonly fontSize: 15;
|
|
513
|
+
};
|
|
514
|
+
};
|
|
515
|
+
declare const CORNER_RADIUS: {
|
|
516
|
+
readonly soft: 8;
|
|
517
|
+
readonly rounded: 16;
|
|
518
|
+
readonly square: 0;
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
type EffectiveScheme = "light" | "dark";
|
|
522
|
+
/**
|
|
523
|
+
* Resolve the configured `colorScheme` against the visitor's OS preference.
|
|
524
|
+
* `prefersDark` is the live value of `matchMedia("(prefers-color-scheme: dark)")`
|
|
525
|
+
* (or `false` when not running in a browser). Kept as a pure function so the
|
|
526
|
+
* caller subscribes once and re-renders.
|
|
527
|
+
*/
|
|
528
|
+
declare function resolveScheme(colorScheme: ResolvedConfig["colorScheme"], prefersDark: boolean): EffectiveScheme;
|
|
529
|
+
/**
|
|
530
|
+
* Pick the colors that should drive the widget render right now. When the
|
|
531
|
+
* effective scheme is dark and a dark color is configured, use it; otherwise
|
|
532
|
+
* fall back to the light color (so half-configured dark mode still ships
|
|
533
|
+
* something readable rather than a white panel with white text).
|
|
534
|
+
*/
|
|
535
|
+
declare function effectiveColors(config: ResolvedConfig, scheme: EffectiveScheme): {
|
|
536
|
+
primary: string;
|
|
537
|
+
background: string;
|
|
538
|
+
text: string;
|
|
539
|
+
};
|
|
540
|
+
declare function sizePreset(size: ResolvedConfig["size"]): {
|
|
541
|
+
readonly bubble: 48;
|
|
542
|
+
readonly width: 320;
|
|
543
|
+
readonly height: 480;
|
|
544
|
+
readonly fontSize: 13;
|
|
545
|
+
} | {
|
|
546
|
+
readonly bubble: 56;
|
|
547
|
+
readonly width: 380;
|
|
548
|
+
readonly height: 520;
|
|
549
|
+
readonly fontSize: 14;
|
|
550
|
+
} | {
|
|
551
|
+
readonly bubble: 64;
|
|
552
|
+
readonly width: 440;
|
|
553
|
+
readonly height: 600;
|
|
554
|
+
readonly fontSize: 15;
|
|
403
555
|
};
|
|
556
|
+
declare function panelRadius(cornerStyle: ResolvedConfig["cornerStyle"]): 0 | 8 | 16;
|
|
404
557
|
|
|
405
558
|
declare class ScreenshotCancelled extends Error {
|
|
406
559
|
constructor(message?: string);
|
|
@@ -464,4 +617,4 @@ interface StartTriggersRuntimeOptions {
|
|
|
464
617
|
}
|
|
465
618
|
declare function startTriggersRuntime(options: StartTriggersRuntimeOptions): TriggersRuntimeHandle;
|
|
466
619
|
|
|
467
|
-
export { type ActionConfirmationBlock, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type IdentifyPayload, type IdentityData, type IncidentBanner, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, evaluate, isRtlLocale, pickFire, resolveLocale, startTriggersRuntime };
|
|
620
|
+
export { type ActionConfirmationBlock, CORNER_RADIUS, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type EffectiveScheme, type IdentifyPayload, type IdentityData, type IncidentBanner, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SIZE_PRESETS, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, effectiveColors, evaluate, isRtlLocale, panelRadius, pickFire, resolveLocale, resolveScheme, sizePreset, startTriggersRuntime };
|
package/dist/index.d.ts
CHANGED
|
@@ -35,6 +35,52 @@ interface CustomerHeroChatConfig {
|
|
|
35
35
|
locale?: string;
|
|
36
36
|
/** Predefined quick-reply options shown before the user sends a message */
|
|
37
37
|
suggestedMessages?: string[];
|
|
38
|
+
/**
|
|
39
|
+
* Color scheme. `auto` follows the visitor's OS preference; `light` and
|
|
40
|
+
* `dark` force a fixed palette. Defaults to `light` when unset.
|
|
41
|
+
*/
|
|
42
|
+
colorScheme?: "auto" | "light" | "dark";
|
|
43
|
+
/** Primary color used in dark mode. Only honoured when the effective
|
|
44
|
+
* scheme resolves to dark; never auto-derived from `primaryColor`. */
|
|
45
|
+
primaryColorDark?: string;
|
|
46
|
+
/** Background color used in dark mode. Only honoured when the effective
|
|
47
|
+
* scheme resolves to dark; never auto-derived from `backgroundColor`. */
|
|
48
|
+
backgroundColorDark?: string;
|
|
49
|
+
/** Text color used in dark mode. Only honoured when the effective scheme
|
|
50
|
+
* resolves to dark; never auto-derived from `textColor`. */
|
|
51
|
+
textColorDark?: string;
|
|
52
|
+
/** Widget size preset. Affects launcher diameter, panel dimensions, and
|
|
53
|
+
* base font size. Defaults to `default`. */
|
|
54
|
+
size?: "compact" | "default" | "large";
|
|
55
|
+
/** Corner radius preset for the chat panel. `soft` ~ small radius,
|
|
56
|
+
* `rounded` ~ medium (default), `square` ~ 0. */
|
|
57
|
+
cornerStyle?: "soft" | "rounded" | "square";
|
|
58
|
+
/** Launcher (floating bubble) customization. Each field is optional. */
|
|
59
|
+
launcher?: {
|
|
60
|
+
/** Custom launcher icon URL. Replaces the default chat-bubble glyph. */
|
|
61
|
+
iconUrl?: string;
|
|
62
|
+
/** Optional CTA label shown next to the launcher (turns the bubble into
|
|
63
|
+
* a pill). Max 60 characters. */
|
|
64
|
+
label?: string;
|
|
65
|
+
/** When true, render a small green dot on the launcher to advertise
|
|
66
|
+
* agent availability. The host site is responsible for keeping
|
|
67
|
+
* business-hours state in sync; the SDK only renders the dot. */
|
|
68
|
+
showOnlineDot?: boolean;
|
|
69
|
+
};
|
|
70
|
+
/** Pixel offsets so the widget can sit above sticky cookie bars or chat
|
|
71
|
+
* CTAs. Each axis defaults to 20 px when unset. Clamped to 0–1000. */
|
|
72
|
+
offset?: {
|
|
73
|
+
bottom?: number;
|
|
74
|
+
side?: number;
|
|
75
|
+
};
|
|
76
|
+
/** Z-index override for sites whose overlays clip the widget. Defaults
|
|
77
|
+
* to 99999. Capped at 2_000_000_000. */
|
|
78
|
+
zIndex?: number;
|
|
79
|
+
/** When false, the input's attach button is hidden so visitors can't
|
|
80
|
+
* even attempt an upload (the server enforces the same flag). Defaults
|
|
81
|
+
* to true. Per-chatbot, sourced from the public widget config endpoint
|
|
82
|
+
* but overrideable on the host. */
|
|
83
|
+
allowAttachments?: boolean;
|
|
38
84
|
}
|
|
39
85
|
|
|
40
86
|
interface ResolvedConfig {
|
|
@@ -51,6 +97,23 @@ interface ResolvedConfig {
|
|
|
51
97
|
suggestedMessages: string[];
|
|
52
98
|
/** Per-chatbot overrides for any translation key, optionally per-locale. */
|
|
53
99
|
stringOverrides?: StringOverrides;
|
|
100
|
+
colorScheme: "auto" | "light" | "dark";
|
|
101
|
+
primaryColorDark?: string;
|
|
102
|
+
backgroundColorDark?: string;
|
|
103
|
+
textColorDark?: string;
|
|
104
|
+
size: "compact" | "default" | "large";
|
|
105
|
+
cornerStyle: "soft" | "rounded" | "square";
|
|
106
|
+
launcher: {
|
|
107
|
+
iconUrl?: string;
|
|
108
|
+
label?: string;
|
|
109
|
+
showOnlineDot: boolean;
|
|
110
|
+
};
|
|
111
|
+
offset: {
|
|
112
|
+
bottom: number;
|
|
113
|
+
side: number;
|
|
114
|
+
};
|
|
115
|
+
zIndex: number;
|
|
116
|
+
allowAttachments: boolean;
|
|
54
117
|
}
|
|
55
118
|
interface MessageSource {
|
|
56
119
|
index: number;
|
|
@@ -303,6 +366,10 @@ interface ChatState {
|
|
|
303
366
|
/** True when the visitor has dismissed the active banner this session.
|
|
304
367
|
* Reset whenever a new banner (different content) lands. */
|
|
305
368
|
incidentBannerDismissed: boolean;
|
|
369
|
+
/** When true, the chat input is disabled and `sendMessage` is a no-op.
|
|
370
|
+
* Used by the dashboard preview (and any other host that wants a
|
|
371
|
+
* visual-only render). Public API consumers should not set this. */
|
|
372
|
+
readOnly: boolean;
|
|
306
373
|
}
|
|
307
374
|
|
|
308
375
|
type Listener = (state: ChatState) => void;
|
|
@@ -314,6 +381,21 @@ declare class CustomerHeroChat {
|
|
|
314
381
|
private identityData;
|
|
315
382
|
t: TranslateFn;
|
|
316
383
|
constructor(config: CustomerHeroChatConfig);
|
|
384
|
+
/**
|
|
385
|
+
* Mark the config as loaded and put the client into read-only preview
|
|
386
|
+
* mode without hitting the API. Used by `@customerhero/react/preview` to
|
|
387
|
+
* render the widget against a host-supplied config (the dashboard preview
|
|
388
|
+
* pane). Public API consumers should not call this.
|
|
389
|
+
*
|
|
390
|
+
* Pass a config to re-resolve and update the rendered colors/size/launcher
|
|
391
|
+
* in place. Callers should reuse the same client instance across config
|
|
392
|
+
* changes so the open animation only fires once.
|
|
393
|
+
*
|
|
394
|
+
* @internal
|
|
395
|
+
*/
|
|
396
|
+
__seedForPreview(config?: CustomerHeroChatConfig, extras?: {
|
|
397
|
+
banner?: IncidentBanner | null;
|
|
398
|
+
}): void;
|
|
317
399
|
private triggersRuntime;
|
|
318
400
|
private preChatFormSubmitted;
|
|
319
401
|
private readStoredConsent;
|
|
@@ -400,7 +482,78 @@ declare const DEFAULTS: {
|
|
|
400
482
|
placeholderText: string;
|
|
401
483
|
welcomeMessage: string;
|
|
402
484
|
title: string;
|
|
485
|
+
colorScheme: "auto" | "light" | "dark";
|
|
486
|
+
primaryColorDark: string;
|
|
487
|
+
backgroundColorDark: string;
|
|
488
|
+
textColorDark: string;
|
|
489
|
+
size: "compact" | "default" | "large";
|
|
490
|
+
cornerStyle: "soft" | "rounded" | "square";
|
|
491
|
+
offsetBottom: number;
|
|
492
|
+
offsetSide: number;
|
|
493
|
+
zIndex: number;
|
|
494
|
+
};
|
|
495
|
+
declare const SIZE_PRESETS: {
|
|
496
|
+
readonly compact: {
|
|
497
|
+
readonly bubble: 48;
|
|
498
|
+
readonly width: 320;
|
|
499
|
+
readonly height: 480;
|
|
500
|
+
readonly fontSize: 13;
|
|
501
|
+
};
|
|
502
|
+
readonly default: {
|
|
503
|
+
readonly bubble: 56;
|
|
504
|
+
readonly width: 380;
|
|
505
|
+
readonly height: 520;
|
|
506
|
+
readonly fontSize: 14;
|
|
507
|
+
};
|
|
508
|
+
readonly large: {
|
|
509
|
+
readonly bubble: 64;
|
|
510
|
+
readonly width: 440;
|
|
511
|
+
readonly height: 600;
|
|
512
|
+
readonly fontSize: 15;
|
|
513
|
+
};
|
|
514
|
+
};
|
|
515
|
+
declare const CORNER_RADIUS: {
|
|
516
|
+
readonly soft: 8;
|
|
517
|
+
readonly rounded: 16;
|
|
518
|
+
readonly square: 0;
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
type EffectiveScheme = "light" | "dark";
|
|
522
|
+
/**
|
|
523
|
+
* Resolve the configured `colorScheme` against the visitor's OS preference.
|
|
524
|
+
* `prefersDark` is the live value of `matchMedia("(prefers-color-scheme: dark)")`
|
|
525
|
+
* (or `false` when not running in a browser). Kept as a pure function so the
|
|
526
|
+
* caller subscribes once and re-renders.
|
|
527
|
+
*/
|
|
528
|
+
declare function resolveScheme(colorScheme: ResolvedConfig["colorScheme"], prefersDark: boolean): EffectiveScheme;
|
|
529
|
+
/**
|
|
530
|
+
* Pick the colors that should drive the widget render right now. When the
|
|
531
|
+
* effective scheme is dark and a dark color is configured, use it; otherwise
|
|
532
|
+
* fall back to the light color (so half-configured dark mode still ships
|
|
533
|
+
* something readable rather than a white panel with white text).
|
|
534
|
+
*/
|
|
535
|
+
declare function effectiveColors(config: ResolvedConfig, scheme: EffectiveScheme): {
|
|
536
|
+
primary: string;
|
|
537
|
+
background: string;
|
|
538
|
+
text: string;
|
|
539
|
+
};
|
|
540
|
+
declare function sizePreset(size: ResolvedConfig["size"]): {
|
|
541
|
+
readonly bubble: 48;
|
|
542
|
+
readonly width: 320;
|
|
543
|
+
readonly height: 480;
|
|
544
|
+
readonly fontSize: 13;
|
|
545
|
+
} | {
|
|
546
|
+
readonly bubble: 56;
|
|
547
|
+
readonly width: 380;
|
|
548
|
+
readonly height: 520;
|
|
549
|
+
readonly fontSize: 14;
|
|
550
|
+
} | {
|
|
551
|
+
readonly bubble: 64;
|
|
552
|
+
readonly width: 440;
|
|
553
|
+
readonly height: 600;
|
|
554
|
+
readonly fontSize: 15;
|
|
403
555
|
};
|
|
556
|
+
declare function panelRadius(cornerStyle: ResolvedConfig["cornerStyle"]): 0 | 8 | 16;
|
|
404
557
|
|
|
405
558
|
declare class ScreenshotCancelled extends Error {
|
|
406
559
|
constructor(message?: string);
|
|
@@ -464,4 +617,4 @@ interface StartTriggersRuntimeOptions {
|
|
|
464
617
|
}
|
|
465
618
|
declare function startTriggersRuntime(options: StartTriggersRuntimeOptions): TriggersRuntimeHandle;
|
|
466
619
|
|
|
467
|
-
export { type ActionConfirmationBlock, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type IdentifyPayload, type IdentityData, type IncidentBanner, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, evaluate, isRtlLocale, pickFire, resolveLocale, startTriggersRuntime };
|
|
620
|
+
export { type ActionConfirmationBlock, CORNER_RADIUS, type ChatMessage, type ChatState, type ConsentSettings, CustomerHeroChat, type CustomerHeroChatConfig, DEFAULTS, type EffectiveScheme, type IdentifyPayload, type IdentityData, type IncidentBanner, type MessageBlock, type MessageRating, type MessageSource, type MessageStatus, type PreChatField, type PreChatFieldKind, type PreChatFormConfig, type PreChatSubmission, type QuickRepliesBlock, type ResolvedConfig, SIZE_PRESETS, SUPPORTED_LOCALES, ScreenshotCancelled, ScreenshotUnavailable, type StringOverrides, type SupportedLocale, type TranslateFn, type TranslationKey, type Translations, type TriggerAction, type TriggerConditionLeaf, type TriggerConditionNode, type TriggerDefinition, type TriggerFrequency, type TriggersRuntimeHandle, type VisitorContext, canCaptureScreenshot, captureScreenshot, createTranslator, detectLocale, effectiveColors, evaluate, isRtlLocale, panelRadius, pickFire, resolveLocale, resolveScheme, sizePreset, startTriggersRuntime };
|
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
|
|
@@ -975,7 +997,14 @@ function startTriggersRuntime(options) {
|
|
|
975
997
|
}
|
|
976
998
|
|
|
977
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
|
+
}
|
|
978
1004
|
function resolveConfig(userConfig, fetched) {
|
|
1005
|
+
const launcherUser = userConfig.launcher ?? {};
|
|
1006
|
+
const launcherFetched = fetched?.launcher ?? {};
|
|
1007
|
+
const offsetUser = userConfig.offset ?? {};
|
|
979
1008
|
return {
|
|
980
1009
|
chatbotId: userConfig.chatbotId,
|
|
981
1010
|
apiBase: userConfig.apiBase ?? DEFAULTS.apiBase,
|
|
@@ -988,7 +1017,32 @@ function resolveConfig(userConfig, fetched) {
|
|
|
988
1017
|
title: userConfig.title ?? fetched?.title ?? DEFAULTS.title,
|
|
989
1018
|
avatarUrl: userConfig.avatarUrl ?? fetched?.avatarUrl,
|
|
990
1019
|
suggestedMessages: userConfig.suggestedMessages ?? fetched?.suggestedMessages ?? [],
|
|
991
|
-
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
|
|
992
1046
|
};
|
|
993
1047
|
}
|
|
994
1048
|
function sanitizeIncidentBanner(input) {
|
|
@@ -1078,9 +1132,40 @@ var CustomerHeroChat = class {
|
|
|
1078
1132
|
pendingTriggerId: null,
|
|
1079
1133
|
pendingPrefill: null,
|
|
1080
1134
|
incidentBanner: null,
|
|
1081
|
-
incidentBannerDismissed: false
|
|
1135
|
+
incidentBannerDismissed: false,
|
|
1136
|
+
readOnly: false
|
|
1082
1137
|
};
|
|
1083
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
|
+
}
|
|
1084
1169
|
// ── Proactive engagement state ─────────────────────────────────────
|
|
1085
1170
|
triggersRuntime = null;
|
|
1086
1171
|
preChatFormSubmitted = false;
|
|
@@ -1226,6 +1311,7 @@ var CustomerHeroChat = class {
|
|
|
1226
1311
|
}
|
|
1227
1312
|
}
|
|
1228
1313
|
async sendMessage(message, options) {
|
|
1314
|
+
if (this.state.readOnly) return;
|
|
1229
1315
|
const trimmed = message.trim();
|
|
1230
1316
|
const attachmentTokens = options?.attachmentTokens ?? [];
|
|
1231
1317
|
if (!trimmed || this.state.isLoading) return;
|
|
@@ -1778,6 +1864,33 @@ function pickExtension(mime) {
|
|
|
1778
1864
|
return "jpg";
|
|
1779
1865
|
}
|
|
1780
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
|
+
|
|
1781
1894
|
// src/screenshot.ts
|
|
1782
1895
|
var ScreenshotCancelled = class extends Error {
|
|
1783
1896
|
constructor(message = "Screenshot cancelled") {
|
|
@@ -1911,8 +2024,10 @@ async function canvasToBlob(canvas, quality) {
|
|
|
1911
2024
|
});
|
|
1912
2025
|
}
|
|
1913
2026
|
export {
|
|
2027
|
+
CORNER_RADIUS,
|
|
1914
2028
|
CustomerHeroChat,
|
|
1915
2029
|
DEFAULTS,
|
|
2030
|
+
SIZE_PRESETS,
|
|
1916
2031
|
SUPPORTED_LOCALES,
|
|
1917
2032
|
ScreenshotCancelled,
|
|
1918
2033
|
ScreenshotUnavailable,
|
|
@@ -1920,9 +2035,13 @@ export {
|
|
|
1920
2035
|
captureScreenshot,
|
|
1921
2036
|
createTranslator,
|
|
1922
2037
|
detectLocale,
|
|
2038
|
+
effectiveColors,
|
|
1923
2039
|
evaluate,
|
|
1924
2040
|
isRtlLocale,
|
|
2041
|
+
panelRadius,
|
|
1925
2042
|
pickFire,
|
|
1926
2043
|
resolveLocale,
|
|
2044
|
+
resolveScheme,
|
|
2045
|
+
sizePreset,
|
|
1927
2046
|
startTriggersRuntime
|
|
1928
2047
|
};
|