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.
@@ -5,6 +5,18 @@ var jsxRuntime = require('react/jsx-runtime');
5
5
 
6
6
  // src/react/ChatWidget.tsx
7
7
 
8
+ // src/react/color.ts
9
+ function luminance(hex) {
10
+ const m = hex.replace("#", "");
11
+ const norm = m.length === 3 ? m.split("").map((c) => c + c).join("") : m;
12
+ if (norm.length !== 6 || !/^[0-9a-fA-F]{6}$/.test(norm)) return 0;
13
+ const r = parseInt(norm.slice(0, 2), 16) / 255;
14
+ const g = parseInt(norm.slice(2, 4), 16) / 255;
15
+ const b = parseInt(norm.slice(4, 6), 16) / 255;
16
+ const toLinear = (c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
17
+ return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
18
+ }
19
+
8
20
  // src/core/tools.ts
9
21
  var MARKER_RE = /\[SKILL:(\w+)((?:\s+\w+=(?:"[^"]*"|[\w./@*+,:-]+))*)\s*\]/g;
10
22
  var ARG_RE = /(\w+)=("([^"]*)"|([\w./@*+,:-]+))/g;
@@ -57,9 +69,11 @@ function buildToolsPromptAddendum(enabledTools) {
57
69
  }
58
70
 
59
71
  // src/core/prompts.ts
60
- function buildSystemPrompt(knowledge, enabledTools = []) {
61
- const toolsAddendum = buildToolsPromptAddendum(enabledTools);
62
- return [
72
+ function buildSystemPrompt(knowledge, optionsOrEnabledTools = []) {
73
+ const opts = Array.isArray(optionsOrEnabledTools) ? { enabledTools: optionsOrEnabledTools } : optionsOrEnabledTools;
74
+ const toolsAddendum = buildToolsPromptAddendum(opts.enabledTools ?? []);
75
+ const extras = opts.extraInstructions?.trim();
76
+ const parts = [
63
77
  "You are an AI assistant on a business website. Use ONLY the knowledge below to answer.",
64
78
  "",
65
79
  "## Business knowledge",
@@ -71,9 +85,16 @@ function buildSystemPrompt(knowledge, enabledTools = []) {
71
85
  "- For anything not covered in the knowledge above, say the owner will follow up \u2014 do NOT guess.",
72
86
  '- 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."',
73
87
  `- If wrong number or asked to stop, say: "Sorry about that. We won't text again."`,
74
- "- Match the caller's language automatically.",
75
- toolsAddendum
76
- ].filter(Boolean).join("\n");
88
+ "- Match the caller's language automatically."
89
+ ];
90
+ if (extras) {
91
+ parts.push("", "## Additional instructions", extras);
92
+ }
93
+ if (toolsAddendum) {
94
+ parts.push(toolsAddendum);
95
+ }
96
+ const defaultPrompt = parts.join("\n");
97
+ return opts.systemPromptTransform ? opts.systemPromptTransform(defaultPrompt) : defaultPrompt;
77
98
  }
78
99
 
79
100
  // src/core/guards.ts
@@ -197,6 +218,8 @@ var ChatBot = class {
197
218
  cachedSystemPrompt;
198
219
  guards;
199
220
  knowledge;
221
+ extraInstructions;
222
+ systemPromptTransform;
200
223
  constructor(init) {
201
224
  if (!init.knowledge || typeof init.knowledge !== "string" || init.knowledge.trim().length === 0) {
202
225
  throw new Error("chatbotlite: knowledge is required (a non-empty markdown string).");
@@ -206,14 +229,23 @@ var ChatBot = class {
206
229
  this.steps = resolveChain(init.providers);
207
230
  this.fetcher = init.options?.fetch ?? globalThis.fetch.bind(globalThis);
208
231
  this.timeoutMs = init.options?.timeoutMs ?? 3e4;
209
- this.cachedSystemPrompt = buildSystemPrompt(init.knowledge);
232
+ this.extraInstructions = init.extraInstructions;
233
+ this.systemPromptTransform = init.systemPromptTransform;
234
+ this.cachedSystemPrompt = buildSystemPrompt(init.knowledge, {
235
+ extraInstructions: this.extraInstructions,
236
+ systemPromptTransform: this.systemPromptTransform
237
+ });
210
238
  this.guards = init.guards ?? {};
211
239
  }
212
240
  /** Build system prompt for given opts — uses cached if no enabledTools, else rebuilds. */
213
241
  resolveSystemPrompt(opts) {
214
242
  if (opts.systemPrompt) return opts.systemPrompt;
215
243
  if (opts.enabledTools && opts.enabledTools.length > 0) {
216
- return buildSystemPrompt(this.knowledge, opts.enabledTools);
244
+ return buildSystemPrompt(this.knowledge, {
245
+ enabledTools: opts.enabledTools,
246
+ extraInstructions: this.extraInstructions,
247
+ systemPromptTransform: this.systemPromptTransform
248
+ });
217
249
  }
218
250
  return this.cachedSystemPrompt;
219
251
  }
@@ -883,7 +915,7 @@ function RequestPayment(props) {
883
915
  surface,
884
916
  textBody,
885
917
  textMuted,
886
- showInterac = true,
918
+ showInterac = false,
887
919
  stripeLink,
888
920
  onPick,
889
921
  submitting = false,
@@ -999,8 +1031,12 @@ function RequestPayment(props) {
999
1031
  display: "flex",
1000
1032
  alignItems: "center",
1001
1033
  justifyContent: "center",
1002
- flexShrink: 0
1003
- }, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#635BFF", fontSize: 14, fontWeight: 700 }, children: "\u{1F4B3}" }) }),
1034
+ flexShrink: 0,
1035
+ color: "#635BFF"
1036
+ }, children: /* @__PURE__ */ jsxRuntime.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: [
1037
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "5", width: "20", height: "14", rx: "2.5" }),
1038
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "2", y1: "10", x2: "22", y2: "10" })
1039
+ ] }) }),
1004
1040
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
1005
1041
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: 13, fontWeight: 600, color: textBody }, children: "Pay by card" }),
1006
1042
  /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "2px 0 0", fontSize: 11, color: textMuted }, children: "Visa \xB7 Mastercard \xB7 Amex" })
@@ -1011,30 +1047,76 @@ function RequestPayment(props) {
1011
1047
  ] })
1012
1048
  ] });
1013
1049
  }
1014
- var BOLT = "\u26A1";
1015
1050
  var DEFAULT_PRIMARY = "#0f172a";
1016
1051
  var DEFAULT_ON_PRIMARY = "#ffffff";
1017
- function luminance(hex) {
1018
- const m = hex.replace("#", "");
1019
- const norm = m.length === 3 ? m.split("").map((c) => c + c).join("") : m;
1020
- if (norm.length !== 6) return 0;
1021
- const r = parseInt(norm.slice(0, 2), 16) / 255;
1022
- const g = parseInt(norm.slice(2, 4), 16) / 255;
1023
- const b = parseInt(norm.slice(4, 6), 16) / 255;
1024
- const toLinear = (c) => c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
1025
- return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
1026
- }
1027
- var SURFACE = "#ffffff";
1028
- var CHAT_BG = "#f5f1eb";
1029
- var BUBBLE_BOT = "#ffffff";
1030
- var INPUT_BG = "#f1f3f5";
1031
- var BORDER = "#e5e7eb";
1032
- var BORDER_LIGHT = "rgba(15,23,42,0.06)";
1033
- var TEXT_BODY = "#0f172a";
1034
- var TEXT_MUTED = "#64748b";
1035
- var TEXT_FAINT = "#94a3b8";
1036
- var FONT_STACK = `-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif`;
1052
+ var IconPaperclip = ({ size = 18 }) => /* @__PURE__ */ jsxRuntime.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__ */ jsxRuntime.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" }) });
1053
+ var IconMic = ({ size = 16 }) => /* @__PURE__ */ jsxRuntime.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: [
1054
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "3", width: "6", height: "12", rx: "3" }),
1055
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 11a7 7 0 0 0 14 0M12 19v3" })
1056
+ ] });
1057
+ var IconBolt = ({ size = 11 }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", style: { verticalAlign: "-1px" }, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13 2L4 14h7l-1 8 9-12h-7l1-8z" }) });
1058
+ var SURFACE = "var(--cbl-bg)";
1059
+ var CHAT_BG = "var(--cbl-bg-chat)";
1060
+ var BUBBLE_BOT = "var(--cbl-bg-elevated)";
1061
+ var INPUT_BG = "var(--cbl-bg-sunken)";
1062
+ var BORDER = "var(--cbl-border)";
1063
+ var BORDER_LIGHT = "var(--cbl-border-light)";
1064
+ var TEXT_BODY = "var(--cbl-text)";
1065
+ var TEXT_MUTED = "var(--cbl-text-muted)";
1066
+ var TEXT_FAINT = "var(--cbl-text-faint)";
1067
+ var FONT_STACK = "var(--cbl-font)";
1037
1068
  var STYLE_TAG_ID = "chatbotlite-widget-styles";
1069
+ var TOKENS = `
1070
+ :where(.chatbotlite-root) {
1071
+ --cbl-bg: #FFFFFF;
1072
+ --cbl-bg-elevated: #FFFFFF;
1073
+ --cbl-bg-chat: #F7F8FA;
1074
+ --cbl-bg-sunken: #F1F3F5;
1075
+ --cbl-border: #E5E7EB;
1076
+ --cbl-border-strong: #D1D5DB;
1077
+ --cbl-border-light: rgba(15,23,42,0.06);
1078
+ --cbl-text: #0F172A;
1079
+ --cbl-text-muted: #64748B;
1080
+ --cbl-text-faint: #94A3B8;
1081
+ --cbl-success: #10B981;
1082
+ --cbl-danger: #EF4444;
1083
+ --cbl-font: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", system-ui, sans-serif;
1084
+ --cbl-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
1085
+ --cbl-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
1086
+ --cbl-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
1087
+ --cbl-shadow-1: 0 1px 2px rgba(15,23,42,0.04);
1088
+ --cbl-shadow-2: 0 4px 12px rgba(15,23,42,0.06), 0 1px 2px rgba(15,23,42,0.04);
1089
+ --cbl-shadow-3: 0 10px 32px rgba(15,23,42,0.10), 0 2px 6px rgba(15,23,42,0.04);
1090
+ --cbl-shadow-4: 0 20px 48px rgba(15,23,42,0.18), 0 4px 12px rgba(15,23,42,0.08);
1091
+ }
1092
+ @media (prefers-color-scheme: dark) {
1093
+ :where(.chatbotlite-root[data-color-scheme="auto"]),
1094
+ :where(.chatbotlite-root[data-color-scheme="dark"]) {
1095
+ --cbl-bg: #16181D;
1096
+ --cbl-bg-elevated: #1F2228;
1097
+ --cbl-bg-chat: #0B0D10;
1098
+ --cbl-bg-sunken: #1F2228;
1099
+ --cbl-border: #24272E;
1100
+ --cbl-border-strong: #2E323A;
1101
+ --cbl-border-light: rgba(255,255,255,0.06);
1102
+ --cbl-text: #ECEDEE;
1103
+ --cbl-text-muted: #9BA1A6;
1104
+ --cbl-text-faint: #6B7177;
1105
+ }
1106
+ }
1107
+ :where(.chatbotlite-root[data-color-scheme="light"]) {
1108
+ --cbl-bg: #FFFFFF;
1109
+ --cbl-bg-elevated: #FFFFFF;
1110
+ --cbl-bg-chat: #F7F8FA;
1111
+ --cbl-bg-sunken: #F1F3F5;
1112
+ --cbl-border: #E5E7EB;
1113
+ --cbl-border-strong: #D1D5DB;
1114
+ --cbl-border-light: rgba(15,23,42,0.06);
1115
+ --cbl-text: #0F172A;
1116
+ --cbl-text-muted: #64748B;
1117
+ --cbl-text-faint: #94A3B8;
1118
+ }
1119
+ `;
1038
1120
  var KEYFRAMES = `
1039
1121
  @keyframes chatbotlite-pop { 0% { opacity: 0; transform: scale(0.6); } 100% { opacity: 1; transform: scale(1); } }
1040
1122
  @keyframes chatbotlite-slide { 0% { opacity: 0; transform: translateY(16px) scale(0.98); } 100% { opacity: 1; transform: translateY(0) scale(1); } }
@@ -1067,7 +1149,7 @@ function ensureStyles() {
1067
1149
  if (document.getElementById(STYLE_TAG_ID)) return;
1068
1150
  const style = document.createElement("style");
1069
1151
  style.id = STYLE_TAG_ID;
1070
- style.textContent = KEYFRAMES;
1152
+ style.textContent = TOKENS + KEYFRAMES;
1071
1153
  document.head.appendChild(style);
1072
1154
  }
1073
1155
  function ChatWidget(props) {
@@ -1095,6 +1177,33 @@ function ChatWidget(props) {
1095
1177
  const voiceLang = voiceCfg?.lang ?? "en-US";
1096
1178
  const speechSupported = typeof window !== "undefined" && (Boolean(window.SpeechRecognition) || Boolean(window.webkitSpeechRecognition));
1097
1179
  const [open, setOpen] = react.useState(false);
1180
+ const [expanded, setExpanded] = react.useState(() => {
1181
+ if (typeof window === "undefined") return false;
1182
+ try {
1183
+ return window.localStorage.getItem("cbl-panel-size") === "expanded";
1184
+ } catch {
1185
+ return false;
1186
+ }
1187
+ });
1188
+ const [isMobile, setIsMobile] = react.useState(
1189
+ () => typeof window === "undefined" ? false : window.innerWidth < 640
1190
+ );
1191
+ react.useEffect(() => {
1192
+ if (typeof window === "undefined") return;
1193
+ const onResize = () => setIsMobile(window.innerWidth < 640);
1194
+ window.addEventListener("resize", onResize);
1195
+ return () => window.removeEventListener("resize", onResize);
1196
+ }, []);
1197
+ function toggleExpanded() {
1198
+ setExpanded((prev) => {
1199
+ const next = !prev;
1200
+ try {
1201
+ window.localStorage.setItem("cbl-panel-size", next ? "expanded" : "compact");
1202
+ } catch {
1203
+ }
1204
+ return next;
1205
+ });
1206
+ }
1098
1207
  const [messages, setMessages] = react.useState([
1099
1208
  { id: "g0", role: "assistant", content: resolvedGreeting, ts: Date.now() }
1100
1209
  ]);
@@ -1187,11 +1296,17 @@ function ChatWidget(props) {
1187
1296
  react.useEffect(() => {
1188
1297
  ensureStyles();
1189
1298
  }, []);
1299
+ const directProps = isEndpointMode ? null : props;
1190
1300
  const bot = react.useMemo(() => {
1191
- if (isEndpointMode) return null;
1192
- if (!props.knowledge || !props.providers) return null;
1193
- return new ChatBot({ knowledge: props.knowledge, providers: props.providers });
1194
- }, [isEndpointMode, props.knowledge, props.providers]);
1301
+ if (!directProps) return null;
1302
+ if (!directProps.knowledge || !directProps.providers) return null;
1303
+ return new ChatBot({
1304
+ knowledge: directProps.knowledge,
1305
+ providers: directProps.providers,
1306
+ ...directProps.extraInstructions ? { extraInstructions: directProps.extraInstructions } : {},
1307
+ ...directProps.systemPromptTransform ? { systemPromptTransform: directProps.systemPromptTransform } : {}
1308
+ });
1309
+ }, [directProps]);
1195
1310
  react.useEffect(() => {
1196
1311
  if (scrollRef.current) {
1197
1312
  scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
@@ -1220,7 +1335,12 @@ function ChatWidget(props) {
1220
1335
  body = JSON.stringify({ message: text, transcript: history, enabledTools });
1221
1336
  }
1222
1337
  const res = await fetch(props.endpoint, { method: "POST", headers, body });
1223
- if (!res.ok) throw new Error(`Endpoint ${res.status}: ${await res.text().catch(() => "")}`);
1338
+ if (!res.ok) {
1339
+ const raw = await res.text().catch(() => "");
1340
+ const looksLikeHtml = /^\s*<(!doctype|html|head|body)/i.test(raw);
1341
+ const snippet = looksLikeHtml ? "" : raw.slice(0, 120).replace(/\s+/g, " ").trim();
1342
+ throw new Error(`Server returned ${res.status}${snippet ? ` \u2014 ${snippet}` : ""}`);
1343
+ }
1224
1344
  const contentType = res.headers.get("Content-Type") ?? "";
1225
1345
  if (contentType.includes("text/event-stream") && res.body) {
1226
1346
  const reader = res.body.getReader();
@@ -1322,10 +1442,13 @@ function ChatWidget(props) {
1322
1442
  !open && /* @__PURE__ */ jsxRuntime.jsx(
1323
1443
  "button",
1324
1444
  {
1325
- className: "chatbotlite-launcher",
1445
+ className: "chatbotlite-root chatbotlite-launcher",
1446
+ "data-color-scheme": "auto",
1326
1447
  onClick: () => setOpen(true),
1327
1448
  "aria-label": "Open chat",
1328
1449
  style: {
1450
+ ["--cbl-primary"]: primary,
1451
+ ["--cbl-on-primary"]: onPrimary,
1329
1452
  position: "fixed",
1330
1453
  bottom: 20,
1331
1454
  ...launcherPos,
@@ -1356,16 +1479,20 @@ function ChatWidget(props) {
1356
1479
  open && /* @__PURE__ */ jsxRuntime.jsxs(
1357
1480
  "div",
1358
1481
  {
1482
+ className: "chatbotlite-root",
1483
+ "data-color-scheme": "auto",
1359
1484
  role: "dialog",
1360
1485
  "aria-label": "Chat",
1361
1486
  style: {
1487
+ ["--cbl-primary"]: primary,
1488
+ ["--cbl-on-primary"]: onPrimary,
1362
1489
  position: "fixed",
1363
- bottom: 20,
1364
- ...panelPos,
1365
- width: 380,
1366
- maxWidth: "calc(100vw - 40px)",
1367
- height: 580,
1368
- maxHeight: "calc(100vh - 40px)",
1490
+ bottom: isMobile ? 0 : 20,
1491
+ ...isMobile ? { left: 0, right: 0 } : panelPos,
1492
+ width: isMobile ? "100vw" : expanded ? 720 : 380,
1493
+ maxWidth: isMobile ? "100vw" : "calc(100vw - 40px)",
1494
+ height: isMobile ? "100vh" : expanded ? 800 : 580,
1495
+ maxHeight: isMobile ? "100vh" : "calc(100vh - 40px)",
1369
1496
  background: SURFACE,
1370
1497
  color: TEXT_BODY,
1371
1498
  borderRadius: 20,
@@ -1423,30 +1550,63 @@ function ChatWidget(props) {
1423
1550
  (subtitle || sending) && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: TEXT_MUTED, marginTop: 2, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: subtitle ?? (sending ? "typing\u2026" : "") })
1424
1551
  ] })
1425
1552
  ] }),
1426
- /* @__PURE__ */ jsxRuntime.jsx(
1427
- "button",
1428
- {
1429
- className: "chatbotlite-close",
1430
- onClick: () => setOpen(false),
1431
- "aria-label": "Close chat",
1432
- style: {
1433
- background: "transparent",
1434
- border: "none",
1435
- color: TEXT_MUTED,
1436
- width: 32,
1437
- height: 32,
1438
- borderRadius: 10,
1439
- fontSize: 22,
1440
- lineHeight: 1,
1441
- cursor: "pointer",
1442
- display: "flex",
1443
- alignItems: "center",
1444
- justifyContent: "center",
1445
- flexShrink: 0
1446
- },
1447
- children: "\xD7"
1448
- }
1449
- )
1553
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 2, flexShrink: 0 }, children: [
1554
+ !isMobile && /* @__PURE__ */ jsxRuntime.jsx(
1555
+ "button",
1556
+ {
1557
+ className: "chatbotlite-resize",
1558
+ onClick: toggleExpanded,
1559
+ "aria-label": expanded ? "Compact view" : "Expand view",
1560
+ title: expanded ? "Compact view" : "Expand view",
1561
+ style: {
1562
+ background: "transparent",
1563
+ border: "none",
1564
+ color: TEXT_MUTED,
1565
+ width: 32,
1566
+ height: 32,
1567
+ borderRadius: 10,
1568
+ cursor: "pointer",
1569
+ display: "flex",
1570
+ alignItems: "center",
1571
+ justifyContent: "center"
1572
+ },
1573
+ children: expanded ? /* @__PURE__ */ jsxRuntime.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: [
1574
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 4 4 4 4 9" }),
1575
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 4 20 4 20 9" }),
1576
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "4 15 4 20 9 20" }),
1577
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 15 20 20 15 20" })
1578
+ ] }) : /* @__PURE__ */ jsxRuntime.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: [
1579
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "3 9 3 3 9 3" }),
1580
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "21 9 21 3 15 3" }),
1581
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "3 15 3 21 9 21" }),
1582
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "21 15 21 21 15 21" })
1583
+ ] })
1584
+ }
1585
+ ),
1586
+ /* @__PURE__ */ jsxRuntime.jsx(
1587
+ "button",
1588
+ {
1589
+ className: "chatbotlite-close",
1590
+ onClick: () => setOpen(false),
1591
+ "aria-label": "Close chat",
1592
+ style: {
1593
+ background: "transparent",
1594
+ border: "none",
1595
+ color: TEXT_MUTED,
1596
+ width: 32,
1597
+ height: 32,
1598
+ borderRadius: 10,
1599
+ fontSize: 22,
1600
+ lineHeight: 1,
1601
+ cursor: "pointer",
1602
+ display: "flex",
1603
+ alignItems: "center",
1604
+ justifyContent: "center"
1605
+ },
1606
+ children: "\xD7"
1607
+ }
1608
+ )
1609
+ ] })
1450
1610
  ] }),
1451
1611
  /* @__PURE__ */ jsxRuntime.jsxs(
1452
1612
  "div",
@@ -1629,9 +1789,9 @@ function ChatWidget(props) {
1629
1789
  maxWidth: 200
1630
1790
  },
1631
1791
  children: [
1632
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
1633
- "\u{1F4CE} ",
1634
- f.name
1792
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: TEXT_MUTED }, children: [
1793
+ /* @__PURE__ */ jsxRuntime.jsx(IconPaperclip, { size: 12 }),
1794
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis", color: TEXT_BODY }, children: f.name })
1635
1795
  ] }),
1636
1796
  /* @__PURE__ */ jsxRuntime.jsx(
1637
1797
  "button",
@@ -1691,8 +1851,8 @@ function ChatWidget(props) {
1691
1851
  background: "transparent",
1692
1852
  border: "none",
1693
1853
  cursor: sending || files.length >= maxFiles ? "default" : "pointer",
1694
- opacity: sending || files.length >= maxFiles ? 0.35 : 0.7,
1695
- fontSize: 18,
1854
+ opacity: sending || files.length >= maxFiles ? 0.35 : 0.75,
1855
+ color: TEXT_MUTED,
1696
1856
  lineHeight: 1,
1697
1857
  padding: 0,
1698
1858
  display: "flex",
@@ -1702,7 +1862,7 @@ function ChatWidget(props) {
1702
1862
  alignSelf: "center",
1703
1863
  transition: "opacity 120ms ease, background 120ms ease"
1704
1864
  },
1705
- children: "\u{1F4CE}"
1865
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconPaperclip, { size: 18 })
1706
1866
  }
1707
1867
  )
1708
1868
  ] }),
@@ -1721,8 +1881,7 @@ function ChatWidget(props) {
1721
1881
  color: voiceListening ? onPrimary : "inherit",
1722
1882
  border: "none",
1723
1883
  cursor: sending ? "default" : "pointer",
1724
- opacity: sending ? 0.35 : voiceListening ? 1 : 0.7,
1725
- fontSize: 16,
1884
+ opacity: sending ? 0.35 : voiceListening ? 1 : 0.75,
1726
1885
  lineHeight: 1,
1727
1886
  padding: 0,
1728
1887
  display: "flex",
@@ -1732,7 +1891,7 @@ function ChatWidget(props) {
1732
1891
  alignSelf: "center",
1733
1892
  transition: "opacity 120ms ease, background 120ms ease, color 120ms ease"
1734
1893
  },
1735
- children: "\u{1F399}\uFE0F"
1894
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconMic, { size: 16 })
1736
1895
  }
1737
1896
  ),
1738
1897
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1812,7 +1971,7 @@ function ChatWidget(props) {
1812
1971
  ]
1813
1972
  }
1814
1973
  ) }),
1815
- showBranding && /* @__PURE__ */ jsxRuntime.jsxs(
1974
+ showBranding && /* @__PURE__ */ jsxRuntime.jsx(
1816
1975
  "a",
1817
1976
  {
1818
1977
  className: "chatbotlite-brand",
@@ -1831,10 +1990,10 @@ function ChatWidget(props) {
1831
1990
  letterSpacing: "0.01em",
1832
1991
  transition: "color 120ms ease"
1833
1992
  },
1834
- children: [
1835
- BOLT,
1836
- " Powered by chatbotlite"
1837
- ]
1993
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 5 }, children: [
1994
+ /* @__PURE__ */ jsxRuntime.jsx(IconBolt, { size: 11 }),
1995
+ "Powered by chatbotlite"
1996
+ ] })
1838
1997
  }
1839
1998
  )
1840
1999
  ]