@mordn/chat-widget 0.1.4 → 0.2.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/dist/index.d.mts CHANGED
@@ -70,21 +70,36 @@ interface StarterPrompt {
70
70
  }
71
71
  interface ThemeConfig {
72
72
  /**
73
- * Theme mode
73
+ * Theme mode — drives the default token values (light vs dark).
74
74
  */
75
75
  mode?: 'light' | 'dark';
76
76
  /**
77
- * Primary color (hex)
77
+ * Primary accent color (any CSS color: hex, rgb, hsl, named).
78
+ * Maps to `--chat-primary` on the widget container at runtime.
78
79
  */
79
80
  primaryColor?: string;
80
81
  /**
81
- * Background color (hex)
82
+ * Background color (any CSS color).
83
+ * Maps to `--chat-background` on the widget container.
82
84
  */
83
85
  backgroundColor?: string;
84
86
  /**
85
- * Text color (hex)
87
+ * Body text color (any CSS color).
88
+ * Maps to `--chat-text` on the widget container.
86
89
  */
87
90
  textColor?: string;
91
+ /**
92
+ * Fine-grained CSS variable overrides. Keys must start with `--chat-`.
93
+ * Use this when the three high-level props above aren't enough — e.g. to
94
+ * theme the header glass, hover state, or surface tones independently.
95
+ *
96
+ * @example
97
+ * tokens: {
98
+ * '--chat-surface': '0 0% 96%', // HSL-triplet tokens
99
+ * '--chat-header-bg': 'rgba(0,0,0,0.7)', // direct color tokens
100
+ * }
101
+ */
102
+ tokens?: Record<`--chat-${string}`, string>;
88
103
  }
89
104
  interface FeatureConfig {
90
105
  /**
package/dist/index.d.ts CHANGED
@@ -70,21 +70,36 @@ interface StarterPrompt {
70
70
  }
71
71
  interface ThemeConfig {
72
72
  /**
73
- * Theme mode
73
+ * Theme mode — drives the default token values (light vs dark).
74
74
  */
75
75
  mode?: 'light' | 'dark';
76
76
  /**
77
- * Primary color (hex)
77
+ * Primary accent color (any CSS color: hex, rgb, hsl, named).
78
+ * Maps to `--chat-primary` on the widget container at runtime.
78
79
  */
79
80
  primaryColor?: string;
80
81
  /**
81
- * Background color (hex)
82
+ * Background color (any CSS color).
83
+ * Maps to `--chat-background` on the widget container.
82
84
  */
83
85
  backgroundColor?: string;
84
86
  /**
85
- * Text color (hex)
87
+ * Body text color (any CSS color).
88
+ * Maps to `--chat-text` on the widget container.
86
89
  */
87
90
  textColor?: string;
91
+ /**
92
+ * Fine-grained CSS variable overrides. Keys must start with `--chat-`.
93
+ * Use this when the three high-level props above aren't enough — e.g. to
94
+ * theme the header glass, hover state, or surface tones independently.
95
+ *
96
+ * @example
97
+ * tokens: {
98
+ * '--chat-surface': '0 0% 96%', // HSL-triplet tokens
99
+ * '--chat-header-bg': 'rgba(0,0,0,0.7)', // direct color tokens
100
+ * }
101
+ */
102
+ tokens?: Record<`--chat-${string}`, string>;
88
103
  }
89
104
  interface FeatureConfig {
90
105
  /**
package/dist/index.js CHANGED
@@ -227,7 +227,7 @@ function Textarea({ className, ...props }) {
227
227
  {
228
228
  "data-slot": "textarea",
229
229
  className: cn(
230
- "border-input placeholder:text-muted-foreground focus-visible:border-ring aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base transition-colors outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
230
+ "border-input placeholder:text-muted-foreground focus-visible:border-ring aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-[14px] transition-colors outline-none disabled:cursor-not-allowed disabled:opacity-50",
231
231
  className
232
232
  ),
233
233
  ...props
@@ -1920,20 +1920,20 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
1920
1920
  ),
1921
1921
  children: [
1922
1922
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-2 px-3 py-2 border-b backdrop-blur-sm relative z-20", style: {
1923
- borderColor: themeMode === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.08)",
1924
- backgroundColor: themeMode === "dark" ? "rgba(37,37,37,0.8)" : "rgba(255,255,255,0.8)"
1923
+ borderColor: "var(--chat-border-soft)",
1924
+ backgroundColor: "var(--chat-header-bg)"
1925
1925
  }, children: [
1926
1926
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex items-center gap-1 flex-1 min-w-0 overflow-x-auto scrollbar-hide py-0.5 scroll-smooth", children: tabs.map((tab, index) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
1927
1927
  "div",
1928
1928
  {
1929
1929
  className: "relative flex items-center gap-1.5 px-3 py-1.5 rounded-lg cursor-pointer transition-all duration-150 group flex-shrink-0 min-w-0",
1930
1930
  style: {
1931
- backgroundColor: tab.isActive ? themeMode === "dark" ? "#444444" : "#f5f5f5" : "transparent",
1932
- color: tab.isActive ? themeMode === "dark" ? "#e5e5e5" : "#171717" : themeMode === "dark" ? "#999999" : "#737373"
1931
+ backgroundColor: tab.isActive ? "hsl(var(--chat-surface))" : "transparent",
1932
+ color: tab.isActive ? "hsl(var(--chat-text))" : "hsl(var(--chat-text-muted))"
1933
1933
  },
1934
1934
  onMouseEnter: (e) => {
1935
1935
  if (!tab.isActive) {
1936
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "rgba(68,68,68,0.5)" : "rgba(245,245,245,0.5)";
1936
+ e.currentTarget.style.backgroundColor = "var(--chat-hover-bg)";
1937
1937
  }
1938
1938
  },
1939
1939
  onMouseLeave: (e) => {
@@ -1960,7 +1960,7 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
1960
1960
  },
1961
1961
  onMouseEnter: (e) => {
1962
1962
  e.currentTarget.style.opacity = "1";
1963
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "#555555" : "#e5e5e5";
1963
+ e.currentTarget.style.backgroundColor = "hsl(var(--chat-surface-hover))";
1964
1964
  },
1965
1965
  onMouseLeave: (e) => {
1966
1966
  e.currentTarget.style.opacity = tab.isActive ? "0.6" : "0";
@@ -1980,14 +1980,14 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
1980
1980
  onClick: createNewTab,
1981
1981
  className: "flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150",
1982
1982
  style: {
1983
- color: themeMode === "dark" ? "#999999" : "#737373"
1983
+ color: "hsl(var(--chat-text-muted))"
1984
1984
  },
1985
1985
  onMouseEnter: (e) => {
1986
- e.currentTarget.style.color = themeMode === "dark" ? "#e5e5e5" : "#171717";
1987
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "#444444" : "#f5f5f5";
1986
+ e.currentTarget.style.color = "hsl(var(--chat-text))";
1987
+ e.currentTarget.style.backgroundColor = "hsl(var(--chat-surface))";
1988
1988
  },
1989
1989
  onMouseLeave: (e) => {
1990
- e.currentTarget.style.color = themeMode === "dark" ? "#999999" : "#737373";
1990
+ e.currentTarget.style.color = "hsl(var(--chat-text-muted))";
1991
1991
  e.currentTarget.style.backgroundColor = "transparent";
1992
1992
  },
1993
1993
  title: "New Chat",
@@ -2001,18 +2001,18 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2001
2001
  onClick: () => setShowHistory(!showHistory),
2002
2002
  className: "flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150",
2003
2003
  style: {
2004
- color: showHistory ? themeMode === "dark" ? "#e5e5e5" : "#171717" : themeMode === "dark" ? "#999999" : "#737373",
2005
- backgroundColor: showHistory ? themeMode === "dark" ? "#444444" : "#f5f5f5" : "transparent"
2004
+ color: showHistory ? "hsl(var(--chat-text))" : "hsl(var(--chat-text-muted))",
2005
+ backgroundColor: showHistory ? "hsl(var(--chat-surface))" : "transparent"
2006
2006
  },
2007
2007
  onMouseEnter: (e) => {
2008
2008
  if (!showHistory) {
2009
- e.currentTarget.style.color = themeMode === "dark" ? "#e5e5e5" : "#171717";
2010
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "#444444" : "#f5f5f5";
2009
+ e.currentTarget.style.color = "hsl(var(--chat-text))";
2010
+ e.currentTarget.style.backgroundColor = "hsl(var(--chat-surface))";
2011
2011
  }
2012
2012
  },
2013
2013
  onMouseLeave: (e) => {
2014
2014
  if (!showHistory) {
2015
- e.currentTarget.style.color = themeMode === "dark" ? "#999999" : "#737373";
2015
+ e.currentTarget.style.color = "hsl(var(--chat-text-muted))";
2016
2016
  e.currentTarget.style.backgroundColor = "transparent";
2017
2017
  }
2018
2018
  },
@@ -2021,15 +2021,15 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2021
2021
  }
2022
2022
  ),
2023
2023
  showHistory && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "absolute right-0 top-full mt-1.5 w-72 rounded-xl shadow-[0_4px_24px_rgba(0,0,0,0.08)] dark:shadow-[0_4px_24px_rgba(0,0,0,0.3)] z-50 animate-in fade-in slide-in-from-top-1 duration-150 overflow-hidden", style: {
2024
- backgroundColor: themeMode === "dark" ? "#252525" : "#ffffff",
2025
- border: `1px solid ${themeMode === "dark" ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.1)"}`
2024
+ backgroundColor: "hsl(var(--chat-background))",
2025
+ border: `1px solid ${"var(--chat-border-medium)"}`
2026
2026
  }, children: [
2027
2027
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "p-2.5 border-b", style: {
2028
- borderColor: themeMode === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.08)",
2029
- backgroundColor: themeMode === "dark" ? "rgba(0,0,0,0.2)" : "rgba(0,0,0,0.02)"
2028
+ borderColor: "var(--chat-border-soft)",
2029
+ backgroundColor: "var(--chat-overlay)"
2030
2030
  }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "relative", children: [
2031
2031
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.SearchIcon, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5", style: {
2032
- color: themeMode === "dark" ? "#666666" : "#999999"
2032
+ color: "hsl(var(--chat-text-muted))"
2033
2033
  }, strokeWidth: 2 }),
2034
2034
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2035
2035
  "input",
@@ -2040,29 +2040,29 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2040
2040
  onChange: (e) => setSearchQuery(e.target.value),
2041
2041
  className: "w-full h-7 pl-8 pr-2.5 text-[13px] rounded-lg focus:outline-none transition-all",
2042
2042
  style: {
2043
- backgroundColor: themeMode === "dark" ? "#1a1a1a" : "#ffffff",
2044
- border: `1px solid ${themeMode === "dark" ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.1)"}`,
2045
- color: themeMode === "dark" ? "#e5e5e5" : "#171717"
2043
+ backgroundColor: "hsl(var(--chat-surface-deep))",
2044
+ border: `1px solid ${"var(--chat-border-medium)"}`,
2045
+ color: "hsl(var(--chat-text))"
2046
2046
  }
2047
2047
  }
2048
2048
  )
2049
2049
  ] }) }),
2050
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "max-h-[300px] overflow-y-auto ai-assistant-scrollbar", children: loadingHistory ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-[13px]", style: { color: themeMode === "dark" ? "#999999" : "#737373" }, children: "Loading..." }) }) : conversations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2050
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "max-h-[300px] overflow-y-auto ai-assistant-scrollbar", children: loadingHistory ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "text-[13px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Loading..." }) }) : conversations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2051
2051
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mb-3", style: {
2052
- backgroundColor: themeMode === "dark" ? "#333333" : "#f5f5f5"
2053
- }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.MessageSquareIcon, { className: "h-5 w-5", style: { color: themeMode === "dark" ? "#666666" : "#a3a3a3" }, strokeWidth: 2 }) }),
2054
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: themeMode === "dark" ? "#e5e5e5" : "#171717" }, children: "No Conversations" }),
2055
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[12px]", style: { color: themeMode === "dark" ? "#999999" : "#737373" }, children: "Start a new chat to begin" })
2052
+ backgroundColor: "hsl(var(--chat-surface))"
2053
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.MessageSquareIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2054
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Conversations" }),
2055
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Start a new chat to begin" })
2056
2056
  ] }) : groupedConversations.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2057
2057
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mb-3", style: {
2058
- backgroundColor: themeMode === "dark" ? "#333333" : "#f5f5f5"
2059
- }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.SearchIcon, { className: "h-5 w-5", style: { color: themeMode === "dark" ? "#666666" : "#a3a3a3" }, strokeWidth: 2 }) }),
2060
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: themeMode === "dark" ? "#e5e5e5" : "#171717" }, children: "No Results" }),
2061
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[12px]", style: { color: themeMode === "dark" ? "#999999" : "#737373" }, children: "Try a different search" })
2058
+ backgroundColor: "hsl(var(--chat-surface))"
2059
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react10.SearchIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2060
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Results" }),
2061
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Try a different search" })
2062
2062
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "py-0.5", children: groupedConversations.map(([groupName, groupConversations]) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "mb-0.5", children: [
2063
2063
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "px-2.5 py-1 sticky top-0 backdrop-blur-sm z-10", style: {
2064
- backgroundColor: themeMode === "dark" ? "rgba(37,37,37,0.95)" : "rgba(255,255,255,0.95)"
2065
- }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "text-[10px] font-semibold uppercase tracking-wide", style: { color: themeMode === "dark" ? "#999999" : "#737373" }, children: groupName }) }),
2064
+ backgroundColor: "var(--chat-header-bg-strong)"
2065
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "text-[10px] font-semibold uppercase tracking-wide", style: { color: "hsl(var(--chat-text-muted))" }, children: groupName }) }),
2066
2066
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "px-1 space-y-0.5", children: groupConversations.map((conversation) => {
2067
2067
  const isActiveConversation = activeTabId === conversation.id;
2068
2068
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
@@ -2070,11 +2070,11 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2070
2070
  {
2071
2071
  className: "w-full px-2 py-1 rounded-md transition-all duration-150 text-left group relative",
2072
2072
  style: {
2073
- backgroundColor: isActiveConversation ? themeMode === "dark" ? "#333333" : "#f5f5f5" : "transparent"
2073
+ backgroundColor: isActiveConversation ? "hsl(var(--chat-surface))" : "transparent"
2074
2074
  },
2075
2075
  onMouseEnter: (e) => {
2076
2076
  if (!isActiveConversation) {
2077
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "rgba(51,51,51,0.5)" : "rgba(245,245,245,0.5)";
2077
+ e.currentTarget.style.backgroundColor = "var(--chat-hover-bg)";
2078
2078
  }
2079
2079
  },
2080
2080
  onMouseLeave: (e) => {
@@ -2086,14 +2086,14 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2086
2086
  children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2087
2087
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "text-[12px] line-clamp-1 transition-colors leading-tight", style: {
2088
2088
  fontWeight: isActiveConversation ? 500 : 400,
2089
- color: isActiveConversation ? themeMode === "dark" ? "#e5e5e5" : "#171717" : themeMode === "dark" ? "#cccccc" : "#404040"
2089
+ color: isActiveConversation ? "hsl(var(--chat-text))" : "hsl(var(--chat-text-strong))"
2090
2090
  }, children: conversation.title }) }),
2091
2091
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2092
2092
  import_lucide_react10.ChevronRightIcon,
2093
2093
  {
2094
2094
  className: "h-3 w-3 transition-all duration-150 flex-shrink-0",
2095
2095
  style: {
2096
- color: themeMode === "dark" ? "#666666" : "#a3a3a3",
2096
+ color: "hsl(var(--chat-text-subtle))",
2097
2097
  opacity: isActiveConversation ? 1 : 0
2098
2098
  },
2099
2099
  strokeWidth: 2
@@ -2113,14 +2113,14 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2113
2113
  onClick: onClose,
2114
2114
  className: "flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150",
2115
2115
  style: {
2116
- color: themeMode === "dark" ? "#999999" : "#737373"
2116
+ color: "hsl(var(--chat-text-muted))"
2117
2117
  },
2118
2118
  onMouseEnter: (e) => {
2119
- e.currentTarget.style.color = themeMode === "dark" ? "#e5e5e5" : "#171717";
2120
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "#444444" : "#f5f5f5";
2119
+ e.currentTarget.style.color = "hsl(var(--chat-text))";
2120
+ e.currentTarget.style.backgroundColor = "hsl(var(--chat-surface))";
2121
2121
  },
2122
2122
  onMouseLeave: (e) => {
2123
- e.currentTarget.style.color = themeMode === "dark" ? "#999999" : "#737373";
2123
+ e.currentTarget.style.color = "hsl(var(--chat-text-muted))";
2124
2124
  e.currentTarget.style.backgroundColor = "transparent";
2125
2125
  },
2126
2126
  title: "Close Chat",
@@ -2171,6 +2171,43 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2171
2171
 
2172
2172
  // src/ChatWidget.tsx
2173
2173
  var import_lucide_react11 = require("lucide-react");
2174
+
2175
+ // src/utils/color.ts
2176
+ function toHslTripletIfHex(value) {
2177
+ const trimmed = value.trim();
2178
+ const hexMatch = /^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.exec(trimmed);
2179
+ if (!hexMatch) return value;
2180
+ let hex = hexMatch[1];
2181
+ if (hex.length === 3) {
2182
+ hex = hex.split("").map((c) => c + c).join("");
2183
+ }
2184
+ const r = parseInt(hex.substring(0, 2), 16) / 255;
2185
+ const g = parseInt(hex.substring(2, 4), 16) / 255;
2186
+ const b = parseInt(hex.substring(4, 6), 16) / 255;
2187
+ const max = Math.max(r, g, b);
2188
+ const min = Math.min(r, g, b);
2189
+ const l = (max + min) / 2;
2190
+ let h = 0;
2191
+ let s = 0;
2192
+ if (max !== min) {
2193
+ const d = max - min;
2194
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
2195
+ switch (max) {
2196
+ case r:
2197
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
2198
+ break;
2199
+ case g:
2200
+ h = ((b - r) / d + 2) / 6;
2201
+ break;
2202
+ case b:
2203
+ h = ((r - g) / d + 4) / 6;
2204
+ break;
2205
+ }
2206
+ }
2207
+ return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
2208
+ }
2209
+
2210
+ // src/ChatWidget.tsx
2174
2211
  var import_jsx_runtime21 = require("react/jsx-runtime");
2175
2212
  function ChatWidget({
2176
2213
  userId,
@@ -2196,8 +2233,20 @@ function ChatWidget({
2196
2233
  if (display?.width) {
2197
2234
  styles["--chat-widget-width"] = display.width;
2198
2235
  }
2236
+ if (theme?.primaryColor) {
2237
+ styles["--chat-primary"] = toHslTripletIfHex(theme.primaryColor);
2238
+ }
2239
+ if (theme?.backgroundColor) {
2240
+ styles["--chat-background"] = toHslTripletIfHex(theme.backgroundColor);
2241
+ }
2242
+ if (theme?.textColor) {
2243
+ styles["--chat-text"] = toHslTripletIfHex(theme.textColor);
2244
+ }
2245
+ if (theme?.tokens) {
2246
+ Object.assign(styles, theme.tokens);
2247
+ }
2199
2248
  return styles;
2200
- }, [display?.width]);
2249
+ }, [display?.width, theme?.primaryColor, theme?.backgroundColor, theme?.textColor, theme?.tokens]);
2201
2250
  const handleMouseDown = (0, import_react12.useCallback)((e) => {
2202
2251
  if (!resizable) return;
2203
2252
  e.preventDefault();