chatbotlite 0.5.2 → 0.6.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.
@@ -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;
@@ -1011,30 +1023,76 @@ function RequestPayment(props) {
1011
1023
  ] })
1012
1024
  ] });
1013
1025
  }
1014
- var BOLT = "\u26A1";
1015
1026
  var DEFAULT_PRIMARY = "#0f172a";
1016
1027
  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`;
1028
+ 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" }) });
1029
+ 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: [
1030
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "3", width: "6", height: "12", rx: "3" }),
1031
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 11a7 7 0 0 0 14 0M12 19v3" })
1032
+ ] });
1033
+ 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" }) });
1034
+ var SURFACE = "var(--cbl-bg)";
1035
+ var CHAT_BG = "var(--cbl-bg-chat)";
1036
+ var BUBBLE_BOT = "var(--cbl-bg-elevated)";
1037
+ var INPUT_BG = "var(--cbl-bg-sunken)";
1038
+ var BORDER = "var(--cbl-border)";
1039
+ var BORDER_LIGHT = "var(--cbl-border-light)";
1040
+ var TEXT_BODY = "var(--cbl-text)";
1041
+ var TEXT_MUTED = "var(--cbl-text-muted)";
1042
+ var TEXT_FAINT = "var(--cbl-text-faint)";
1043
+ var FONT_STACK = "var(--cbl-font)";
1037
1044
  var STYLE_TAG_ID = "chatbotlite-widget-styles";
1045
+ var TOKENS = `
1046
+ :where(.chatbotlite-root) {
1047
+ --cbl-bg: #FFFFFF;
1048
+ --cbl-bg-elevated: #FFFFFF;
1049
+ --cbl-bg-chat: #F7F8FA;
1050
+ --cbl-bg-sunken: #F1F3F5;
1051
+ --cbl-border: #E5E7EB;
1052
+ --cbl-border-strong: #D1D5DB;
1053
+ --cbl-border-light: rgba(15,23,42,0.06);
1054
+ --cbl-text: #0F172A;
1055
+ --cbl-text-muted: #64748B;
1056
+ --cbl-text-faint: #94A3B8;
1057
+ --cbl-success: #10B981;
1058
+ --cbl-danger: #EF4444;
1059
+ --cbl-font: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", system-ui, sans-serif;
1060
+ --cbl-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
1061
+ --cbl-ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
1062
+ --cbl-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
1063
+ --cbl-shadow-1: 0 1px 2px rgba(15,23,42,0.04);
1064
+ --cbl-shadow-2: 0 4px 12px rgba(15,23,42,0.06), 0 1px 2px rgba(15,23,42,0.04);
1065
+ --cbl-shadow-3: 0 10px 32px rgba(15,23,42,0.10), 0 2px 6px rgba(15,23,42,0.04);
1066
+ --cbl-shadow-4: 0 20px 48px rgba(15,23,42,0.18), 0 4px 12px rgba(15,23,42,0.08);
1067
+ }
1068
+ @media (prefers-color-scheme: dark) {
1069
+ :where(.chatbotlite-root[data-color-scheme="auto"]),
1070
+ :where(.chatbotlite-root[data-color-scheme="dark"]) {
1071
+ --cbl-bg: #16181D;
1072
+ --cbl-bg-elevated: #1F2228;
1073
+ --cbl-bg-chat: #0B0D10;
1074
+ --cbl-bg-sunken: #1F2228;
1075
+ --cbl-border: #24272E;
1076
+ --cbl-border-strong: #2E323A;
1077
+ --cbl-border-light: rgba(255,255,255,0.06);
1078
+ --cbl-text: #ECEDEE;
1079
+ --cbl-text-muted: #9BA1A6;
1080
+ --cbl-text-faint: #6B7177;
1081
+ }
1082
+ }
1083
+ :where(.chatbotlite-root[data-color-scheme="light"]) {
1084
+ --cbl-bg: #FFFFFF;
1085
+ --cbl-bg-elevated: #FFFFFF;
1086
+ --cbl-bg-chat: #F7F8FA;
1087
+ --cbl-bg-sunken: #F1F3F5;
1088
+ --cbl-border: #E5E7EB;
1089
+ --cbl-border-strong: #D1D5DB;
1090
+ --cbl-border-light: rgba(15,23,42,0.06);
1091
+ --cbl-text: #0F172A;
1092
+ --cbl-text-muted: #64748B;
1093
+ --cbl-text-faint: #94A3B8;
1094
+ }
1095
+ `;
1038
1096
  var KEYFRAMES = `
1039
1097
  @keyframes chatbotlite-pop { 0% { opacity: 0; transform: scale(0.6); } 100% { opacity: 1; transform: scale(1); } }
1040
1098
  @keyframes chatbotlite-slide { 0% { opacity: 0; transform: translateY(16px) scale(0.98); } 100% { opacity: 1; transform: translateY(0) scale(1); } }
@@ -1067,7 +1125,7 @@ function ensureStyles() {
1067
1125
  if (document.getElementById(STYLE_TAG_ID)) return;
1068
1126
  const style = document.createElement("style");
1069
1127
  style.id = STYLE_TAG_ID;
1070
- style.textContent = KEYFRAMES;
1128
+ style.textContent = TOKENS + KEYFRAMES;
1071
1129
  document.head.appendChild(style);
1072
1130
  }
1073
1131
  function ChatWidget(props) {
@@ -1220,7 +1278,12 @@ function ChatWidget(props) {
1220
1278
  body = JSON.stringify({ message: text, transcript: history, enabledTools });
1221
1279
  }
1222
1280
  const res = await fetch(props.endpoint, { method: "POST", headers, body });
1223
- if (!res.ok) throw new Error(`Endpoint ${res.status}: ${await res.text().catch(() => "")}`);
1281
+ if (!res.ok) {
1282
+ const raw = await res.text().catch(() => "");
1283
+ const looksLikeHtml = /^\s*<(!doctype|html|head|body)/i.test(raw);
1284
+ const snippet = looksLikeHtml ? "" : raw.slice(0, 120).replace(/\s+/g, " ").trim();
1285
+ throw new Error(`Server returned ${res.status}${snippet ? ` \u2014 ${snippet}` : ""}`);
1286
+ }
1224
1287
  const contentType = res.headers.get("Content-Type") ?? "";
1225
1288
  if (contentType.includes("text/event-stream") && res.body) {
1226
1289
  const reader = res.body.getReader();
@@ -1322,10 +1385,13 @@ function ChatWidget(props) {
1322
1385
  !open && /* @__PURE__ */ jsxRuntime.jsx(
1323
1386
  "button",
1324
1387
  {
1325
- className: "chatbotlite-launcher",
1388
+ className: "chatbotlite-root chatbotlite-launcher",
1389
+ "data-color-scheme": "auto",
1326
1390
  onClick: () => setOpen(true),
1327
1391
  "aria-label": "Open chat",
1328
1392
  style: {
1393
+ ["--cbl-primary"]: primary,
1394
+ ["--cbl-on-primary"]: onPrimary,
1329
1395
  position: "fixed",
1330
1396
  bottom: 20,
1331
1397
  ...launcherPos,
@@ -1356,9 +1422,13 @@ function ChatWidget(props) {
1356
1422
  open && /* @__PURE__ */ jsxRuntime.jsxs(
1357
1423
  "div",
1358
1424
  {
1425
+ className: "chatbotlite-root",
1426
+ "data-color-scheme": "auto",
1359
1427
  role: "dialog",
1360
1428
  "aria-label": "Chat",
1361
1429
  style: {
1430
+ ["--cbl-primary"]: primary,
1431
+ ["--cbl-on-primary"]: onPrimary,
1362
1432
  position: "fixed",
1363
1433
  bottom: 20,
1364
1434
  ...panelPos,
@@ -1629,9 +1699,9 @@ function ChatWidget(props) {
1629
1699
  maxWidth: 200
1630
1700
  },
1631
1701
  children: [
1632
- /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
1633
- "\u{1F4CE} ",
1634
- f.name
1702
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", color: TEXT_MUTED }, children: [
1703
+ /* @__PURE__ */ jsxRuntime.jsx(IconPaperclip, { size: 12 }),
1704
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis", color: TEXT_BODY }, children: f.name })
1635
1705
  ] }),
1636
1706
  /* @__PURE__ */ jsxRuntime.jsx(
1637
1707
  "button",
@@ -1691,8 +1761,8 @@ function ChatWidget(props) {
1691
1761
  background: "transparent",
1692
1762
  border: "none",
1693
1763
  cursor: sending || files.length >= maxFiles ? "default" : "pointer",
1694
- opacity: sending || files.length >= maxFiles ? 0.35 : 0.7,
1695
- fontSize: 18,
1764
+ opacity: sending || files.length >= maxFiles ? 0.35 : 0.75,
1765
+ color: TEXT_MUTED,
1696
1766
  lineHeight: 1,
1697
1767
  padding: 0,
1698
1768
  display: "flex",
@@ -1702,7 +1772,7 @@ function ChatWidget(props) {
1702
1772
  alignSelf: "center",
1703
1773
  transition: "opacity 120ms ease, background 120ms ease"
1704
1774
  },
1705
- children: "\u{1F4CE}"
1775
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconPaperclip, { size: 18 })
1706
1776
  }
1707
1777
  )
1708
1778
  ] }),
@@ -1721,8 +1791,7 @@ function ChatWidget(props) {
1721
1791
  color: voiceListening ? onPrimary : "inherit",
1722
1792
  border: "none",
1723
1793
  cursor: sending ? "default" : "pointer",
1724
- opacity: sending ? 0.35 : voiceListening ? 1 : 0.7,
1725
- fontSize: 16,
1794
+ opacity: sending ? 0.35 : voiceListening ? 1 : 0.75,
1726
1795
  lineHeight: 1,
1727
1796
  padding: 0,
1728
1797
  display: "flex",
@@ -1732,7 +1801,7 @@ function ChatWidget(props) {
1732
1801
  alignSelf: "center",
1733
1802
  transition: "opacity 120ms ease, background 120ms ease, color 120ms ease"
1734
1803
  },
1735
- children: "\u{1F399}\uFE0F"
1804
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconMic, { size: 16 })
1736
1805
  }
1737
1806
  ),
1738
1807
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1812,7 +1881,7 @@ function ChatWidget(props) {
1812
1881
  ]
1813
1882
  }
1814
1883
  ) }),
1815
- showBranding && /* @__PURE__ */ jsxRuntime.jsxs(
1884
+ showBranding && /* @__PURE__ */ jsxRuntime.jsx(
1816
1885
  "a",
1817
1886
  {
1818
1887
  className: "chatbotlite-brand",
@@ -1831,10 +1900,10 @@ function ChatWidget(props) {
1831
1900
  letterSpacing: "0.01em",
1832
1901
  transition: "color 120ms ease"
1833
1902
  },
1834
- children: [
1835
- BOLT,
1836
- " Powered by chatbotlite"
1837
- ]
1903
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 5 }, children: [
1904
+ /* @__PURE__ */ jsxRuntime.jsx(IconBolt, { size: 11 }),
1905
+ "Powered by chatbotlite"
1906
+ ] })
1838
1907
  }
1839
1908
  )
1840
1909
  ]