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