chatbotlite 0.5.2 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.cjs +28 -8
- package/dist/client/index.cjs.map +1 -1
- package/dist/client/index.d.cts +15 -0
- package/dist/client/index.d.ts +15 -0
- package/dist/client/index.js +28 -8
- package/dist/client/index.js.map +1 -1
- package/dist/core/index.cjs +15 -6
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +26 -5
- package/dist/core/index.d.ts +26 -5
- package/dist/core/index.js +15 -6
- package/dist/core/index.js.map +1 -1
- package/dist/embed.global.js +71 -21
- package/dist/embed.global.js.map +1 -1
- package/dist/index.cjs +28 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +28 -8
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +242 -83
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +13 -0
- package/dist/react/index.d.ts +13 -0
- package/dist/react/index.js +243 -84
- package/dist/react/index.js.map +1 -1
- package/package.json +11 -2
package/dist/react/index.d.cts
CHANGED
|
@@ -95,6 +95,19 @@ interface ChatWidgetDirectProps extends ChatWidgetCommonProps {
|
|
|
95
95
|
knowledge: Knowledge;
|
|
96
96
|
/** Provider chain + API keys. */
|
|
97
97
|
providers: ProviderConfig;
|
|
98
|
+
/**
|
|
99
|
+
* Append per-vertical behaviour tweaks to the default system prompt
|
|
100
|
+
* (tone, escalation rules, "don't quote price too early", etc.).
|
|
101
|
+
* Only used in direct (client-side) mode — in endpoint mode the server
|
|
102
|
+
* controls the prompt.
|
|
103
|
+
*/
|
|
104
|
+
extraInstructions?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Power-user hook to modify our default scaffolding inline.
|
|
107
|
+
* Receives the assembled default prompt, returns a transformed string.
|
|
108
|
+
* Direct mode only.
|
|
109
|
+
*/
|
|
110
|
+
systemPromptTransform?: (defaultPrompt: string) => string;
|
|
98
111
|
endpoint?: never;
|
|
99
112
|
}
|
|
100
113
|
interface ChatWidgetEndpointProps extends ChatWidgetCommonProps {
|
package/dist/react/index.d.ts
CHANGED
|
@@ -95,6 +95,19 @@ interface ChatWidgetDirectProps extends ChatWidgetCommonProps {
|
|
|
95
95
|
knowledge: Knowledge;
|
|
96
96
|
/** Provider chain + API keys. */
|
|
97
97
|
providers: ProviderConfig;
|
|
98
|
+
/**
|
|
99
|
+
* Append per-vertical behaviour tweaks to the default system prompt
|
|
100
|
+
* (tone, escalation rules, "don't quote price too early", etc.).
|
|
101
|
+
* Only used in direct (client-side) mode — in endpoint mode the server
|
|
102
|
+
* controls the prompt.
|
|
103
|
+
*/
|
|
104
|
+
extraInstructions?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Power-user hook to modify our default scaffolding inline.
|
|
107
|
+
* Receives the assembled default prompt, returns a transformed string.
|
|
108
|
+
* Direct mode only.
|
|
109
|
+
*/
|
|
110
|
+
systemPromptTransform?: (defaultPrompt: string) => string;
|
|
98
111
|
endpoint?: never;
|
|
99
112
|
}
|
|
100
113
|
interface ChatWidgetEndpointProps extends ChatWidgetCommonProps {
|
package/dist/react/index.js
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
import { useState,
|
|
1
|
+
import { useState, useEffect, useRef, useMemo } from 'react';
|
|
2
2
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
3
3
|
|
|
4
4
|
// src/react/ChatWidget.tsx
|
|
5
5
|
|
|
6
|
+
// src/react/color.ts
|
|
7
|
+
function luminance(hex) {
|
|
8
|
+
const m = hex.replace("#", "");
|
|
9
|
+
const norm = m.length === 3 ? m.split("").map((c) => c + c).join("") : m;
|
|
10
|
+
if (norm.length !== 6 || !/^[0-9a-fA-F]{6}$/.test(norm)) return 0;
|
|
11
|
+
const r = parseInt(norm.slice(0, 2), 16) / 255;
|
|
12
|
+
const g = parseInt(norm.slice(2, 4), 16) / 255;
|
|
13
|
+
const b = parseInt(norm.slice(4, 6), 16) / 255;
|
|
14
|
+
const toLinear = (c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
15
|
+
return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
|
|
16
|
+
}
|
|
17
|
+
|
|
6
18
|
// src/core/tools.ts
|
|
7
19
|
var MARKER_RE = /\[SKILL:(\w+)((?:\s+\w+=(?:"[^"]*"|[\w./@*+,:-]+))*)\s*\]/g;
|
|
8
20
|
var ARG_RE = /(\w+)=("([^"]*)"|([\w./@*+,:-]+))/g;
|
|
@@ -55,9 +67,11 @@ function buildToolsPromptAddendum(enabledTools) {
|
|
|
55
67
|
}
|
|
56
68
|
|
|
57
69
|
// src/core/prompts.ts
|
|
58
|
-
function buildSystemPrompt(knowledge,
|
|
59
|
-
const
|
|
60
|
-
|
|
70
|
+
function buildSystemPrompt(knowledge, optionsOrEnabledTools = []) {
|
|
71
|
+
const opts = Array.isArray(optionsOrEnabledTools) ? { enabledTools: optionsOrEnabledTools } : optionsOrEnabledTools;
|
|
72
|
+
const toolsAddendum = buildToolsPromptAddendum(opts.enabledTools ?? []);
|
|
73
|
+
const extras = opts.extraInstructions?.trim();
|
|
74
|
+
const parts = [
|
|
61
75
|
"You are an AI assistant on a business website. Use ONLY the knowledge below to answer.",
|
|
62
76
|
"",
|
|
63
77
|
"## Business knowledge",
|
|
@@ -69,9 +83,16 @@ function buildSystemPrompt(knowledge, enabledTools = []) {
|
|
|
69
83
|
"- For anything not covered in the knowledge above, say the owner will follow up \u2014 do NOT guess.",
|
|
70
84
|
'- If the caller is clearly a vendor/sales pitch, say: "This does not look like a customer service request, so we will not continue this thread."',
|
|
71
85
|
`- If wrong number or asked to stop, say: "Sorry about that. We won't text again."`,
|
|
72
|
-
"- Match the caller's language automatically."
|
|
73
|
-
|
|
74
|
-
|
|
86
|
+
"- Match the caller's language automatically."
|
|
87
|
+
];
|
|
88
|
+
if (extras) {
|
|
89
|
+
parts.push("", "## Additional instructions", extras);
|
|
90
|
+
}
|
|
91
|
+
if (toolsAddendum) {
|
|
92
|
+
parts.push(toolsAddendum);
|
|
93
|
+
}
|
|
94
|
+
const defaultPrompt = parts.join("\n");
|
|
95
|
+
return opts.systemPromptTransform ? opts.systemPromptTransform(defaultPrompt) : defaultPrompt;
|
|
75
96
|
}
|
|
76
97
|
|
|
77
98
|
// src/core/guards.ts
|
|
@@ -195,6 +216,8 @@ var ChatBot = class {
|
|
|
195
216
|
cachedSystemPrompt;
|
|
196
217
|
guards;
|
|
197
218
|
knowledge;
|
|
219
|
+
extraInstructions;
|
|
220
|
+
systemPromptTransform;
|
|
198
221
|
constructor(init) {
|
|
199
222
|
if (!init.knowledge || typeof init.knowledge !== "string" || init.knowledge.trim().length === 0) {
|
|
200
223
|
throw new Error("chatbotlite: knowledge is required (a non-empty markdown string).");
|
|
@@ -204,14 +227,23 @@ var ChatBot = class {
|
|
|
204
227
|
this.steps = resolveChain(init.providers);
|
|
205
228
|
this.fetcher = init.options?.fetch ?? globalThis.fetch.bind(globalThis);
|
|
206
229
|
this.timeoutMs = init.options?.timeoutMs ?? 3e4;
|
|
207
|
-
this.
|
|
230
|
+
this.extraInstructions = init.extraInstructions;
|
|
231
|
+
this.systemPromptTransform = init.systemPromptTransform;
|
|
232
|
+
this.cachedSystemPrompt = buildSystemPrompt(init.knowledge, {
|
|
233
|
+
extraInstructions: this.extraInstructions,
|
|
234
|
+
systemPromptTransform: this.systemPromptTransform
|
|
235
|
+
});
|
|
208
236
|
this.guards = init.guards ?? {};
|
|
209
237
|
}
|
|
210
238
|
/** Build system prompt for given opts — uses cached if no enabledTools, else rebuilds. */
|
|
211
239
|
resolveSystemPrompt(opts) {
|
|
212
240
|
if (opts.systemPrompt) return opts.systemPrompt;
|
|
213
241
|
if (opts.enabledTools && opts.enabledTools.length > 0) {
|
|
214
|
-
return buildSystemPrompt(this.knowledge,
|
|
242
|
+
return buildSystemPrompt(this.knowledge, {
|
|
243
|
+
enabledTools: opts.enabledTools,
|
|
244
|
+
extraInstructions: this.extraInstructions,
|
|
245
|
+
systemPromptTransform: this.systemPromptTransform
|
|
246
|
+
});
|
|
215
247
|
}
|
|
216
248
|
return this.cachedSystemPrompt;
|
|
217
249
|
}
|
|
@@ -881,7 +913,7 @@ function RequestPayment(props) {
|
|
|
881
913
|
surface,
|
|
882
914
|
textBody,
|
|
883
915
|
textMuted,
|
|
884
|
-
showInterac =
|
|
916
|
+
showInterac = false,
|
|
885
917
|
stripeLink,
|
|
886
918
|
onPick,
|
|
887
919
|
submitting = false,
|
|
@@ -997,8 +1029,12 @@ function RequestPayment(props) {
|
|
|
997
1029
|
display: "flex",
|
|
998
1030
|
alignItems: "center",
|
|
999
1031
|
justifyContent: "center",
|
|
1000
|
-
flexShrink: 0
|
|
1001
|
-
|
|
1032
|
+
flexShrink: 0,
|
|
1033
|
+
color: "#635BFF"
|
|
1034
|
+
}, children: /* @__PURE__ */ jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1035
|
+
/* @__PURE__ */ jsx("rect", { x: "2", y: "5", width: "20", height: "14", rx: "2.5" }),
|
|
1036
|
+
/* @__PURE__ */ jsx("line", { x1: "2", y1: "10", x2: "22", y2: "10" })
|
|
1037
|
+
] }) }),
|
|
1002
1038
|
/* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1003
1039
|
/* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: 13, fontWeight: 600, color: textBody }, children: "Pay by card" }),
|
|
1004
1040
|
/* @__PURE__ */ jsx("p", { style: { margin: "2px 0 0", fontSize: 11, color: textMuted }, children: "Visa \xB7 Mastercard \xB7 Amex" })
|
|
@@ -1009,30 +1045,76 @@ function RequestPayment(props) {
|
|
|
1009
1045
|
] })
|
|
1010
1046
|
] });
|
|
1011
1047
|
}
|
|
1012
|
-
var BOLT = "\u26A1";
|
|
1013
1048
|
var DEFAULT_PRIMARY = "#0f172a";
|
|
1014
1049
|
var DEFAULT_ON_PRIMARY = "#ffffff";
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
var
|
|
1026
|
-
var
|
|
1027
|
-
var
|
|
1028
|
-
var
|
|
1029
|
-
var
|
|
1030
|
-
var
|
|
1031
|
-
var TEXT_BODY = "#0f172a";
|
|
1032
|
-
var TEXT_MUTED = "#64748b";
|
|
1033
|
-
var TEXT_FAINT = "#94a3b8";
|
|
1034
|
-
var FONT_STACK = `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif`;
|
|
1050
|
+
var IconPaperclip = ({ size = 18 }) => /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
|
|
1051
|
+
var IconMic = ({ size = 16 }) => /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1052
|
+
/* @__PURE__ */ jsx("rect", { x: "9", y: "3", width: "6", height: "12", rx: "3" }),
|
|
1053
|
+
/* @__PURE__ */ jsx("path", { d: "M5 11a7 7 0 0 0 14 0M12 19v3" })
|
|
1054
|
+
] });
|
|
1055
|
+
var IconBolt = ({ size = 11 }) => /* @__PURE__ */ jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", style: { verticalAlign: "-1px" }, children: /* @__PURE__ */ jsx("path", { d: "M13 2L4 14h7l-1 8 9-12h-7l1-8z" }) });
|
|
1056
|
+
var SURFACE = "var(--cbl-bg)";
|
|
1057
|
+
var CHAT_BG = "var(--cbl-bg-chat)";
|
|
1058
|
+
var BUBBLE_BOT = "var(--cbl-bg-elevated)";
|
|
1059
|
+
var INPUT_BG = "var(--cbl-bg-sunken)";
|
|
1060
|
+
var BORDER = "var(--cbl-border)";
|
|
1061
|
+
var BORDER_LIGHT = "var(--cbl-border-light)";
|
|
1062
|
+
var TEXT_BODY = "var(--cbl-text)";
|
|
1063
|
+
var TEXT_MUTED = "var(--cbl-text-muted)";
|
|
1064
|
+
var TEXT_FAINT = "var(--cbl-text-faint)";
|
|
1065
|
+
var FONT_STACK = "var(--cbl-font)";
|
|
1035
1066
|
var STYLE_TAG_ID = "chatbotlite-widget-styles";
|
|
1067
|
+
var TOKENS = `
|
|
1068
|
+
:where(.chatbotlite-root) {
|
|
1069
|
+
--cbl-bg: #FFFFFF;
|
|
1070
|
+
--cbl-bg-elevated: #FFFFFF;
|
|
1071
|
+
--cbl-bg-chat: #F7F8FA;
|
|
1072
|
+
--cbl-bg-sunken: #F1F3F5;
|
|
1073
|
+
--cbl-border: #E5E7EB;
|
|
1074
|
+
--cbl-border-strong: #D1D5DB;
|
|
1075
|
+
--cbl-border-light: rgba(15,23,42,0.06);
|
|
1076
|
+
--cbl-text: #0F172A;
|
|
1077
|
+
--cbl-text-muted: #64748B;
|
|
1078
|
+
--cbl-text-faint: #94A3B8;
|
|
1079
|
+
--cbl-success: #10B981;
|
|
1080
|
+
--cbl-danger: #EF4444;
|
|
1081
|
+
--cbl-font: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", system-ui, sans-serif;
|
|
1082
|
+
--cbl-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
|
1083
|
+
--cbl-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
1084
|
+
--cbl-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
|
1085
|
+
--cbl-shadow-1: 0 1px 2px rgba(15,23,42,0.04);
|
|
1086
|
+
--cbl-shadow-2: 0 4px 12px rgba(15,23,42,0.06), 0 1px 2px rgba(15,23,42,0.04);
|
|
1087
|
+
--cbl-shadow-3: 0 10px 32px rgba(15,23,42,0.10), 0 2px 6px rgba(15,23,42,0.04);
|
|
1088
|
+
--cbl-shadow-4: 0 20px 48px rgba(15,23,42,0.18), 0 4px 12px rgba(15,23,42,0.08);
|
|
1089
|
+
}
|
|
1090
|
+
@media (prefers-color-scheme: dark) {
|
|
1091
|
+
:where(.chatbotlite-root[data-color-scheme="auto"]),
|
|
1092
|
+
:where(.chatbotlite-root[data-color-scheme="dark"]) {
|
|
1093
|
+
--cbl-bg: #16181D;
|
|
1094
|
+
--cbl-bg-elevated: #1F2228;
|
|
1095
|
+
--cbl-bg-chat: #0B0D10;
|
|
1096
|
+
--cbl-bg-sunken: #1F2228;
|
|
1097
|
+
--cbl-border: #24272E;
|
|
1098
|
+
--cbl-border-strong: #2E323A;
|
|
1099
|
+
--cbl-border-light: rgba(255,255,255,0.06);
|
|
1100
|
+
--cbl-text: #ECEDEE;
|
|
1101
|
+
--cbl-text-muted: #9BA1A6;
|
|
1102
|
+
--cbl-text-faint: #6B7177;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
:where(.chatbotlite-root[data-color-scheme="light"]) {
|
|
1106
|
+
--cbl-bg: #FFFFFF;
|
|
1107
|
+
--cbl-bg-elevated: #FFFFFF;
|
|
1108
|
+
--cbl-bg-chat: #F7F8FA;
|
|
1109
|
+
--cbl-bg-sunken: #F1F3F5;
|
|
1110
|
+
--cbl-border: #E5E7EB;
|
|
1111
|
+
--cbl-border-strong: #D1D5DB;
|
|
1112
|
+
--cbl-border-light: rgba(15,23,42,0.06);
|
|
1113
|
+
--cbl-text: #0F172A;
|
|
1114
|
+
--cbl-text-muted: #64748B;
|
|
1115
|
+
--cbl-text-faint: #94A3B8;
|
|
1116
|
+
}
|
|
1117
|
+
`;
|
|
1036
1118
|
var KEYFRAMES = `
|
|
1037
1119
|
@keyframes chatbotlite-pop { 0% { opacity: 0; transform: scale(0.6); } 100% { opacity: 1; transform: scale(1); } }
|
|
1038
1120
|
@keyframes chatbotlite-slide { 0% { opacity: 0; transform: translateY(16px) scale(0.98); } 100% { opacity: 1; transform: translateY(0) scale(1); } }
|
|
@@ -1065,7 +1147,7 @@ function ensureStyles() {
|
|
|
1065
1147
|
if (document.getElementById(STYLE_TAG_ID)) return;
|
|
1066
1148
|
const style = document.createElement("style");
|
|
1067
1149
|
style.id = STYLE_TAG_ID;
|
|
1068
|
-
style.textContent = KEYFRAMES;
|
|
1150
|
+
style.textContent = TOKENS + KEYFRAMES;
|
|
1069
1151
|
document.head.appendChild(style);
|
|
1070
1152
|
}
|
|
1071
1153
|
function ChatWidget(props) {
|
|
@@ -1093,6 +1175,33 @@ function ChatWidget(props) {
|
|
|
1093
1175
|
const voiceLang = voiceCfg?.lang ?? "en-US";
|
|
1094
1176
|
const speechSupported = typeof window !== "undefined" && (Boolean(window.SpeechRecognition) || Boolean(window.webkitSpeechRecognition));
|
|
1095
1177
|
const [open, setOpen] = useState(false);
|
|
1178
|
+
const [expanded, setExpanded] = useState(() => {
|
|
1179
|
+
if (typeof window === "undefined") return false;
|
|
1180
|
+
try {
|
|
1181
|
+
return window.localStorage.getItem("cbl-panel-size") === "expanded";
|
|
1182
|
+
} catch {
|
|
1183
|
+
return false;
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
const [isMobile, setIsMobile] = useState(
|
|
1187
|
+
() => typeof window === "undefined" ? false : window.innerWidth < 640
|
|
1188
|
+
);
|
|
1189
|
+
useEffect(() => {
|
|
1190
|
+
if (typeof window === "undefined") return;
|
|
1191
|
+
const onResize = () => setIsMobile(window.innerWidth < 640);
|
|
1192
|
+
window.addEventListener("resize", onResize);
|
|
1193
|
+
return () => window.removeEventListener("resize", onResize);
|
|
1194
|
+
}, []);
|
|
1195
|
+
function toggleExpanded() {
|
|
1196
|
+
setExpanded((prev) => {
|
|
1197
|
+
const next = !prev;
|
|
1198
|
+
try {
|
|
1199
|
+
window.localStorage.setItem("cbl-panel-size", next ? "expanded" : "compact");
|
|
1200
|
+
} catch {
|
|
1201
|
+
}
|
|
1202
|
+
return next;
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
1096
1205
|
const [messages, setMessages] = useState([
|
|
1097
1206
|
{ id: "g0", role: "assistant", content: resolvedGreeting, ts: Date.now() }
|
|
1098
1207
|
]);
|
|
@@ -1185,11 +1294,17 @@ function ChatWidget(props) {
|
|
|
1185
1294
|
useEffect(() => {
|
|
1186
1295
|
ensureStyles();
|
|
1187
1296
|
}, []);
|
|
1297
|
+
const directProps = isEndpointMode ? null : props;
|
|
1188
1298
|
const bot = useMemo(() => {
|
|
1189
|
-
if (
|
|
1190
|
-
if (!
|
|
1191
|
-
return new ChatBot({
|
|
1192
|
-
|
|
1299
|
+
if (!directProps) return null;
|
|
1300
|
+
if (!directProps.knowledge || !directProps.providers) return null;
|
|
1301
|
+
return new ChatBot({
|
|
1302
|
+
knowledge: directProps.knowledge,
|
|
1303
|
+
providers: directProps.providers,
|
|
1304
|
+
...directProps.extraInstructions ? { extraInstructions: directProps.extraInstructions } : {},
|
|
1305
|
+
...directProps.systemPromptTransform ? { systemPromptTransform: directProps.systemPromptTransform } : {}
|
|
1306
|
+
});
|
|
1307
|
+
}, [directProps]);
|
|
1193
1308
|
useEffect(() => {
|
|
1194
1309
|
if (scrollRef.current) {
|
|
1195
1310
|
scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
|
|
@@ -1218,7 +1333,12 @@ function ChatWidget(props) {
|
|
|
1218
1333
|
body = JSON.stringify({ message: text, transcript: history, enabledTools });
|
|
1219
1334
|
}
|
|
1220
1335
|
const res = await fetch(props.endpoint, { method: "POST", headers, body });
|
|
1221
|
-
if (!res.ok)
|
|
1336
|
+
if (!res.ok) {
|
|
1337
|
+
const raw = await res.text().catch(() => "");
|
|
1338
|
+
const looksLikeHtml = /^\s*<(!doctype|html|head|body)/i.test(raw);
|
|
1339
|
+
const snippet = looksLikeHtml ? "" : raw.slice(0, 120).replace(/\s+/g, " ").trim();
|
|
1340
|
+
throw new Error(`Server returned ${res.status}${snippet ? ` \u2014 ${snippet}` : ""}`);
|
|
1341
|
+
}
|
|
1222
1342
|
const contentType = res.headers.get("Content-Type") ?? "";
|
|
1223
1343
|
if (contentType.includes("text/event-stream") && res.body) {
|
|
1224
1344
|
const reader = res.body.getReader();
|
|
@@ -1320,10 +1440,13 @@ function ChatWidget(props) {
|
|
|
1320
1440
|
!open && /* @__PURE__ */ jsx(
|
|
1321
1441
|
"button",
|
|
1322
1442
|
{
|
|
1323
|
-
className: "chatbotlite-launcher",
|
|
1443
|
+
className: "chatbotlite-root chatbotlite-launcher",
|
|
1444
|
+
"data-color-scheme": "auto",
|
|
1324
1445
|
onClick: () => setOpen(true),
|
|
1325
1446
|
"aria-label": "Open chat",
|
|
1326
1447
|
style: {
|
|
1448
|
+
["--cbl-primary"]: primary,
|
|
1449
|
+
["--cbl-on-primary"]: onPrimary,
|
|
1327
1450
|
position: "fixed",
|
|
1328
1451
|
bottom: 20,
|
|
1329
1452
|
...launcherPos,
|
|
@@ -1354,16 +1477,20 @@ function ChatWidget(props) {
|
|
|
1354
1477
|
open && /* @__PURE__ */ jsxs(
|
|
1355
1478
|
"div",
|
|
1356
1479
|
{
|
|
1480
|
+
className: "chatbotlite-root",
|
|
1481
|
+
"data-color-scheme": "auto",
|
|
1357
1482
|
role: "dialog",
|
|
1358
1483
|
"aria-label": "Chat",
|
|
1359
1484
|
style: {
|
|
1485
|
+
["--cbl-primary"]: primary,
|
|
1486
|
+
["--cbl-on-primary"]: onPrimary,
|
|
1360
1487
|
position: "fixed",
|
|
1361
|
-
bottom: 20,
|
|
1362
|
-
...panelPos,
|
|
1363
|
-
width: 380,
|
|
1364
|
-
maxWidth: "calc(100vw - 40px)",
|
|
1365
|
-
height: 580,
|
|
1366
|
-
maxHeight: "calc(100vh - 40px)",
|
|
1488
|
+
bottom: isMobile ? 0 : 20,
|
|
1489
|
+
...isMobile ? { left: 0, right: 0 } : panelPos,
|
|
1490
|
+
width: isMobile ? "100vw" : expanded ? 720 : 380,
|
|
1491
|
+
maxWidth: isMobile ? "100vw" : "calc(100vw - 40px)",
|
|
1492
|
+
height: isMobile ? "100vh" : expanded ? 800 : 580,
|
|
1493
|
+
maxHeight: isMobile ? "100vh" : "calc(100vh - 40px)",
|
|
1367
1494
|
background: SURFACE,
|
|
1368
1495
|
color: TEXT_BODY,
|
|
1369
1496
|
borderRadius: 20,
|
|
@@ -1421,30 +1548,63 @@ function ChatWidget(props) {
|
|
|
1421
1548
|
(subtitle || sending) && /* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: TEXT_MUTED, marginTop: 2, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: subtitle ?? (sending ? "typing\u2026" : "") })
|
|
1422
1549
|
] })
|
|
1423
1550
|
] }),
|
|
1424
|
-
/* @__PURE__ */
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1551
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 2, flexShrink: 0 }, children: [
|
|
1552
|
+
!isMobile && /* @__PURE__ */ jsx(
|
|
1553
|
+
"button",
|
|
1554
|
+
{
|
|
1555
|
+
className: "chatbotlite-resize",
|
|
1556
|
+
onClick: toggleExpanded,
|
|
1557
|
+
"aria-label": expanded ? "Compact view" : "Expand view",
|
|
1558
|
+
title: expanded ? "Compact view" : "Expand view",
|
|
1559
|
+
style: {
|
|
1560
|
+
background: "transparent",
|
|
1561
|
+
border: "none",
|
|
1562
|
+
color: TEXT_MUTED,
|
|
1563
|
+
width: 32,
|
|
1564
|
+
height: 32,
|
|
1565
|
+
borderRadius: 10,
|
|
1566
|
+
cursor: "pointer",
|
|
1567
|
+
display: "flex",
|
|
1568
|
+
alignItems: "center",
|
|
1569
|
+
justifyContent: "center"
|
|
1570
|
+
},
|
|
1571
|
+
children: expanded ? /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1572
|
+
/* @__PURE__ */ jsx("polyline", { points: "9 4 4 4 4 9" }),
|
|
1573
|
+
/* @__PURE__ */ jsx("polyline", { points: "15 4 20 4 20 9" }),
|
|
1574
|
+
/* @__PURE__ */ jsx("polyline", { points: "4 15 4 20 9 20" }),
|
|
1575
|
+
/* @__PURE__ */ jsx("polyline", { points: "20 15 20 20 15 20" })
|
|
1576
|
+
] }) : /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.75, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1577
|
+
/* @__PURE__ */ jsx("polyline", { points: "3 9 3 3 9 3" }),
|
|
1578
|
+
/* @__PURE__ */ jsx("polyline", { points: "21 9 21 3 15 3" }),
|
|
1579
|
+
/* @__PURE__ */ jsx("polyline", { points: "3 15 3 21 9 21" }),
|
|
1580
|
+
/* @__PURE__ */ jsx("polyline", { points: "21 15 21 21 15 21" })
|
|
1581
|
+
] })
|
|
1582
|
+
}
|
|
1583
|
+
),
|
|
1584
|
+
/* @__PURE__ */ jsx(
|
|
1585
|
+
"button",
|
|
1586
|
+
{
|
|
1587
|
+
className: "chatbotlite-close",
|
|
1588
|
+
onClick: () => setOpen(false),
|
|
1589
|
+
"aria-label": "Close chat",
|
|
1590
|
+
style: {
|
|
1591
|
+
background: "transparent",
|
|
1592
|
+
border: "none",
|
|
1593
|
+
color: TEXT_MUTED,
|
|
1594
|
+
width: 32,
|
|
1595
|
+
height: 32,
|
|
1596
|
+
borderRadius: 10,
|
|
1597
|
+
fontSize: 22,
|
|
1598
|
+
lineHeight: 1,
|
|
1599
|
+
cursor: "pointer",
|
|
1600
|
+
display: "flex",
|
|
1601
|
+
alignItems: "center",
|
|
1602
|
+
justifyContent: "center"
|
|
1603
|
+
},
|
|
1604
|
+
children: "\xD7"
|
|
1605
|
+
}
|
|
1606
|
+
)
|
|
1607
|
+
] })
|
|
1448
1608
|
] }),
|
|
1449
1609
|
/* @__PURE__ */ jsxs(
|
|
1450
1610
|
"div",
|
|
@@ -1627,9 +1787,9 @@ function ChatWidget(props) {
|
|
|
1627
1787
|
maxWidth: 200
|
|
1628
1788
|
},
|
|
1629
1789
|
children: [
|
|
1630
|
-
/* @__PURE__ */ jsxs("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
|
|
1631
|
-
|
|
1632
|
-
f.name
|
|
1790
|
+
/* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: TEXT_MUTED }, children: [
|
|
1791
|
+
/* @__PURE__ */ jsx(IconPaperclip, { size: 12 }),
|
|
1792
|
+
/* @__PURE__ */ jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis", color: TEXT_BODY }, children: f.name })
|
|
1633
1793
|
] }),
|
|
1634
1794
|
/* @__PURE__ */ jsx(
|
|
1635
1795
|
"button",
|
|
@@ -1689,8 +1849,8 @@ function ChatWidget(props) {
|
|
|
1689
1849
|
background: "transparent",
|
|
1690
1850
|
border: "none",
|
|
1691
1851
|
cursor: sending || files.length >= maxFiles ? "default" : "pointer",
|
|
1692
|
-
opacity: sending || files.length >= maxFiles ? 0.35 : 0.
|
|
1693
|
-
|
|
1852
|
+
opacity: sending || files.length >= maxFiles ? 0.35 : 0.75,
|
|
1853
|
+
color: TEXT_MUTED,
|
|
1694
1854
|
lineHeight: 1,
|
|
1695
1855
|
padding: 0,
|
|
1696
1856
|
display: "flex",
|
|
@@ -1700,7 +1860,7 @@ function ChatWidget(props) {
|
|
|
1700
1860
|
alignSelf: "center",
|
|
1701
1861
|
transition: "opacity 120ms ease, background 120ms ease"
|
|
1702
1862
|
},
|
|
1703
|
-
children:
|
|
1863
|
+
children: /* @__PURE__ */ jsx(IconPaperclip, { size: 18 })
|
|
1704
1864
|
}
|
|
1705
1865
|
)
|
|
1706
1866
|
] }),
|
|
@@ -1719,8 +1879,7 @@ function ChatWidget(props) {
|
|
|
1719
1879
|
color: voiceListening ? onPrimary : "inherit",
|
|
1720
1880
|
border: "none",
|
|
1721
1881
|
cursor: sending ? "default" : "pointer",
|
|
1722
|
-
opacity: sending ? 0.35 : voiceListening ? 1 : 0.
|
|
1723
|
-
fontSize: 16,
|
|
1882
|
+
opacity: sending ? 0.35 : voiceListening ? 1 : 0.75,
|
|
1724
1883
|
lineHeight: 1,
|
|
1725
1884
|
padding: 0,
|
|
1726
1885
|
display: "flex",
|
|
@@ -1730,7 +1889,7 @@ function ChatWidget(props) {
|
|
|
1730
1889
|
alignSelf: "center",
|
|
1731
1890
|
transition: "opacity 120ms ease, background 120ms ease, color 120ms ease"
|
|
1732
1891
|
},
|
|
1733
|
-
children:
|
|
1892
|
+
children: /* @__PURE__ */ jsx(IconMic, { size: 16 })
|
|
1734
1893
|
}
|
|
1735
1894
|
),
|
|
1736
1895
|
/* @__PURE__ */ jsx(
|
|
@@ -1810,7 +1969,7 @@ function ChatWidget(props) {
|
|
|
1810
1969
|
]
|
|
1811
1970
|
}
|
|
1812
1971
|
) }),
|
|
1813
|
-
showBranding && /* @__PURE__ */
|
|
1972
|
+
showBranding && /* @__PURE__ */ jsx(
|
|
1814
1973
|
"a",
|
|
1815
1974
|
{
|
|
1816
1975
|
className: "chatbotlite-brand",
|
|
@@ -1829,10 +1988,10 @@ function ChatWidget(props) {
|
|
|
1829
1988
|
letterSpacing: "0.01em",
|
|
1830
1989
|
transition: "color 120ms ease"
|
|
1831
1990
|
},
|
|
1832
|
-
children: [
|
|
1833
|
-
|
|
1834
|
-
"
|
|
1835
|
-
]
|
|
1991
|
+
children: /* @__PURE__ */ jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 5 }, children: [
|
|
1992
|
+
/* @__PURE__ */ jsx(IconBolt, { size: 11 }),
|
|
1993
|
+
"Powered by chatbotlite"
|
|
1994
|
+
] })
|
|
1836
1995
|
}
|
|
1837
1996
|
)
|
|
1838
1997
|
]
|