@mordn/chat-widget 0.1.4 → 0.2.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/index.mjs CHANGED
@@ -178,7 +178,7 @@ function Textarea({ className, ...props }) {
178
178
  {
179
179
  "data-slot": "textarea",
180
180
  className: cn(
181
- "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",
181
+ "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",
182
182
  className
183
183
  ),
184
184
  ...props
@@ -1900,20 +1900,20 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
1900
1900
  ),
1901
1901
  children: [
1902
1902
  /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2 px-3 py-2 border-b backdrop-blur-sm relative z-20", style: {
1903
- borderColor: themeMode === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.08)",
1904
- backgroundColor: themeMode === "dark" ? "rgba(37,37,37,0.8)" : "rgba(255,255,255,0.8)"
1903
+ borderColor: "var(--chat-border-soft)",
1904
+ backgroundColor: "var(--chat-header-bg)"
1905
1905
  }, children: [
1906
1906
  /* @__PURE__ */ jsx20("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__ */ jsxs12(
1907
1907
  "div",
1908
1908
  {
1909
1909
  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",
1910
1910
  style: {
1911
- backgroundColor: tab.isActive ? themeMode === "dark" ? "#444444" : "#f5f5f5" : "transparent",
1912
- color: tab.isActive ? themeMode === "dark" ? "#e5e5e5" : "#171717" : themeMode === "dark" ? "#999999" : "#737373"
1911
+ backgroundColor: tab.isActive ? "hsl(var(--chat-surface))" : "transparent",
1912
+ color: tab.isActive ? "hsl(var(--chat-text))" : "hsl(var(--chat-text-muted))"
1913
1913
  },
1914
1914
  onMouseEnter: (e) => {
1915
1915
  if (!tab.isActive) {
1916
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "rgba(68,68,68,0.5)" : "rgba(245,245,245,0.5)";
1916
+ e.currentTarget.style.backgroundColor = "var(--chat-hover-bg)";
1917
1917
  }
1918
1918
  },
1919
1919
  onMouseLeave: (e) => {
@@ -1940,7 +1940,7 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
1940
1940
  },
1941
1941
  onMouseEnter: (e) => {
1942
1942
  e.currentTarget.style.opacity = "1";
1943
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "#555555" : "#e5e5e5";
1943
+ e.currentTarget.style.backgroundColor = "hsl(var(--chat-surface-hover))";
1944
1944
  },
1945
1945
  onMouseLeave: (e) => {
1946
1946
  e.currentTarget.style.opacity = tab.isActive ? "0.6" : "0";
@@ -1960,14 +1960,14 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
1960
1960
  onClick: createNewTab,
1961
1961
  className: "flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150",
1962
1962
  style: {
1963
- color: themeMode === "dark" ? "#999999" : "#737373"
1963
+ color: "hsl(var(--chat-text-muted))"
1964
1964
  },
1965
1965
  onMouseEnter: (e) => {
1966
- e.currentTarget.style.color = themeMode === "dark" ? "#e5e5e5" : "#171717";
1967
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "#444444" : "#f5f5f5";
1966
+ e.currentTarget.style.color = "hsl(var(--chat-text))";
1967
+ e.currentTarget.style.backgroundColor = "hsl(var(--chat-surface))";
1968
1968
  },
1969
1969
  onMouseLeave: (e) => {
1970
- e.currentTarget.style.color = themeMode === "dark" ? "#999999" : "#737373";
1970
+ e.currentTarget.style.color = "hsl(var(--chat-text-muted))";
1971
1971
  e.currentTarget.style.backgroundColor = "transparent";
1972
1972
  },
1973
1973
  title: "New Chat",
@@ -1981,18 +1981,18 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
1981
1981
  onClick: () => setShowHistory(!showHistory),
1982
1982
  className: "flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150",
1983
1983
  style: {
1984
- color: showHistory ? themeMode === "dark" ? "#e5e5e5" : "#171717" : themeMode === "dark" ? "#999999" : "#737373",
1985
- backgroundColor: showHistory ? themeMode === "dark" ? "#444444" : "#f5f5f5" : "transparent"
1984
+ color: showHistory ? "hsl(var(--chat-text))" : "hsl(var(--chat-text-muted))",
1985
+ backgroundColor: showHistory ? "hsl(var(--chat-surface))" : "transparent"
1986
1986
  },
1987
1987
  onMouseEnter: (e) => {
1988
1988
  if (!showHistory) {
1989
- e.currentTarget.style.color = themeMode === "dark" ? "#e5e5e5" : "#171717";
1990
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "#444444" : "#f5f5f5";
1989
+ e.currentTarget.style.color = "hsl(var(--chat-text))";
1990
+ e.currentTarget.style.backgroundColor = "hsl(var(--chat-surface))";
1991
1991
  }
1992
1992
  },
1993
1993
  onMouseLeave: (e) => {
1994
1994
  if (!showHistory) {
1995
- e.currentTarget.style.color = themeMode === "dark" ? "#999999" : "#737373";
1995
+ e.currentTarget.style.color = "hsl(var(--chat-text-muted))";
1996
1996
  e.currentTarget.style.backgroundColor = "transparent";
1997
1997
  }
1998
1998
  },
@@ -2001,48 +2001,43 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2001
2001
  }
2002
2002
  ),
2003
2003
  showHistory && /* @__PURE__ */ jsxs12("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: {
2004
- backgroundColor: themeMode === "dark" ? "#252525" : "#ffffff",
2005
- border: `1px solid ${themeMode === "dark" ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.1)"}`
2004
+ backgroundColor: "hsl(var(--chat-background))",
2005
+ border: `1px solid ${"var(--chat-border-medium)"}`
2006
2006
  }, children: [
2007
2007
  /* @__PURE__ */ jsx20("div", { className: "p-2.5 border-b", style: {
2008
- borderColor: themeMode === "dark" ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.08)",
2009
- backgroundColor: themeMode === "dark" ? "rgba(0,0,0,0.2)" : "rgba(0,0,0,0.02)"
2010
- }, children: /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
2011
- /* @__PURE__ */ jsx20(SearchIcon, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5", style: {
2012
- color: themeMode === "dark" ? "#666666" : "#999999"
2013
- }, strokeWidth: 2 }),
2014
- /* @__PURE__ */ jsx20(
2015
- "input",
2016
- {
2017
- type: "text",
2018
- placeholder: "Search",
2019
- value: searchQuery,
2020
- onChange: (e) => setSearchQuery(e.target.value),
2021
- className: "w-full h-7 pl-8 pr-2.5 text-[13px] rounded-lg focus:outline-none transition-all",
2022
- style: {
2023
- backgroundColor: themeMode === "dark" ? "#1a1a1a" : "#ffffff",
2024
- border: `1px solid ${themeMode === "dark" ? "rgba(255,255,255,0.1)" : "rgba(0,0,0,0.1)"}`,
2025
- color: themeMode === "dark" ? "#e5e5e5" : "#171717"
2026
- }
2008
+ borderColor: "var(--chat-border-soft)",
2009
+ backgroundColor: "var(--chat-overlay)"
2010
+ }, children: /* @__PURE__ */ jsx20("div", { className: "relative", children: /* @__PURE__ */ jsx20(
2011
+ "input",
2012
+ {
2013
+ type: "text",
2014
+ placeholder: "Search",
2015
+ value: searchQuery,
2016
+ onChange: (e) => setSearchQuery(e.target.value),
2017
+ className: "w-full h-7 px-2.5 text-[13px] rounded-lg focus:outline-none transition-all",
2018
+ style: {
2019
+ backgroundColor: "hsl(var(--chat-surface-deep))",
2020
+ border: `1px solid ${"var(--chat-border-medium)"}`,
2021
+ color: "hsl(var(--chat-text))"
2027
2022
  }
2028
- )
2029
- ] }) }),
2030
- /* @__PURE__ */ jsx20("div", { className: "max-h-[300px] overflow-y-auto ai-assistant-scrollbar", children: loadingHistory ? /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx20("div", { className: "text-[13px]", style: { color: themeMode === "dark" ? "#999999" : "#737373" }, children: "Loading..." }) }) : conversations.length === 0 ? /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2023
+ }
2024
+ ) }) }),
2025
+ /* @__PURE__ */ jsx20("div", { className: "max-h-[300px] overflow-y-auto ai-assistant-scrollbar", children: loadingHistory ? /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx20("div", { className: "text-[13px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Loading..." }) }) : conversations.length === 0 ? /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2031
2026
  /* @__PURE__ */ jsx20("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mb-3", style: {
2032
- backgroundColor: themeMode === "dark" ? "#333333" : "#f5f5f5"
2033
- }, children: /* @__PURE__ */ jsx20(MessageSquareIcon, { className: "h-5 w-5", style: { color: themeMode === "dark" ? "#666666" : "#a3a3a3" }, strokeWidth: 2 }) }),
2034
- /* @__PURE__ */ jsx20("p", { className: "text-[13px] font-medium mb-0.5", style: { color: themeMode === "dark" ? "#e5e5e5" : "#171717" }, children: "No Conversations" }),
2035
- /* @__PURE__ */ jsx20("p", { className: "text-[12px]", style: { color: themeMode === "dark" ? "#999999" : "#737373" }, children: "Start a new chat to begin" })
2027
+ backgroundColor: "hsl(var(--chat-surface))"
2028
+ }, children: /* @__PURE__ */ jsx20(MessageSquareIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2029
+ /* @__PURE__ */ jsx20("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Conversations" }),
2030
+ /* @__PURE__ */ jsx20("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Start a new chat to begin" })
2036
2031
  ] }) : groupedConversations.length === 0 ? /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2037
2032
  /* @__PURE__ */ jsx20("div", { className: "w-12 h-12 rounded-full flex items-center justify-center mb-3", style: {
2038
- backgroundColor: themeMode === "dark" ? "#333333" : "#f5f5f5"
2039
- }, children: /* @__PURE__ */ jsx20(SearchIcon, { className: "h-5 w-5", style: { color: themeMode === "dark" ? "#666666" : "#a3a3a3" }, strokeWidth: 2 }) }),
2040
- /* @__PURE__ */ jsx20("p", { className: "text-[13px] font-medium mb-0.5", style: { color: themeMode === "dark" ? "#e5e5e5" : "#171717" }, children: "No Results" }),
2041
- /* @__PURE__ */ jsx20("p", { className: "text-[12px]", style: { color: themeMode === "dark" ? "#999999" : "#737373" }, children: "Try a different search" })
2033
+ backgroundColor: "hsl(var(--chat-surface))"
2034
+ }, children: /* @__PURE__ */ jsx20(SearchIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2035
+ /* @__PURE__ */ jsx20("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Results" }),
2036
+ /* @__PURE__ */ jsx20("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Try a different search" })
2042
2037
  ] }) : /* @__PURE__ */ jsx20("div", { className: "py-0.5", children: groupedConversations.map(([groupName, groupConversations]) => /* @__PURE__ */ jsxs12("div", { className: "mb-0.5", children: [
2043
2038
  /* @__PURE__ */ jsx20("div", { className: "px-2.5 py-1 sticky top-0 backdrop-blur-sm z-10", style: {
2044
- backgroundColor: themeMode === "dark" ? "rgba(37,37,37,0.95)" : "rgba(255,255,255,0.95)"
2045
- }, children: /* @__PURE__ */ jsx20("h3", { className: "text-[10px] font-semibold uppercase tracking-wide", style: { color: themeMode === "dark" ? "#999999" : "#737373" }, children: groupName }) }),
2039
+ backgroundColor: "var(--chat-header-bg-strong)"
2040
+ }, children: /* @__PURE__ */ jsx20("h3", { className: "text-[10px] font-semibold uppercase tracking-wide", style: { color: "hsl(var(--chat-text-muted))" }, children: groupName }) }),
2046
2041
  /* @__PURE__ */ jsx20("div", { className: "px-1 space-y-0.5", children: groupConversations.map((conversation) => {
2047
2042
  const isActiveConversation = activeTabId === conversation.id;
2048
2043
  return /* @__PURE__ */ jsx20(
@@ -2050,11 +2045,11 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2050
2045
  {
2051
2046
  className: "w-full px-2 py-1 rounded-md transition-all duration-150 text-left group relative",
2052
2047
  style: {
2053
- backgroundColor: isActiveConversation ? themeMode === "dark" ? "#333333" : "#f5f5f5" : "transparent"
2048
+ backgroundColor: isActiveConversation ? "hsl(var(--chat-surface))" : "transparent"
2054
2049
  },
2055
2050
  onMouseEnter: (e) => {
2056
2051
  if (!isActiveConversation) {
2057
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "rgba(51,51,51,0.5)" : "rgba(245,245,245,0.5)";
2052
+ e.currentTarget.style.backgroundColor = "var(--chat-hover-bg)";
2058
2053
  }
2059
2054
  },
2060
2055
  onMouseLeave: (e) => {
@@ -2066,14 +2061,14 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2066
2061
  children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5", children: [
2067
2062
  /* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx20("p", { className: "text-[12px] line-clamp-1 transition-colors leading-tight", style: {
2068
2063
  fontWeight: isActiveConversation ? 500 : 400,
2069
- color: isActiveConversation ? themeMode === "dark" ? "#e5e5e5" : "#171717" : themeMode === "dark" ? "#cccccc" : "#404040"
2064
+ color: isActiveConversation ? "hsl(var(--chat-text))" : "hsl(var(--chat-text-strong))"
2070
2065
  }, children: conversation.title }) }),
2071
2066
  /* @__PURE__ */ jsx20(
2072
2067
  ChevronRightIcon2,
2073
2068
  {
2074
2069
  className: "h-3 w-3 transition-all duration-150 flex-shrink-0",
2075
2070
  style: {
2076
- color: themeMode === "dark" ? "#666666" : "#a3a3a3",
2071
+ color: "hsl(var(--chat-text-subtle))",
2077
2072
  opacity: isActiveConversation ? 1 : 0
2078
2073
  },
2079
2074
  strokeWidth: 2
@@ -2093,14 +2088,14 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2093
2088
  onClick: onClose,
2094
2089
  className: "flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150",
2095
2090
  style: {
2096
- color: themeMode === "dark" ? "#999999" : "#737373"
2091
+ color: "hsl(var(--chat-text-muted))"
2097
2092
  },
2098
2093
  onMouseEnter: (e) => {
2099
- e.currentTarget.style.color = themeMode === "dark" ? "#e5e5e5" : "#171717";
2100
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "#444444" : "#f5f5f5";
2094
+ e.currentTarget.style.color = "hsl(var(--chat-text))";
2095
+ e.currentTarget.style.backgroundColor = "hsl(var(--chat-surface))";
2101
2096
  },
2102
2097
  onMouseLeave: (e) => {
2103
- e.currentTarget.style.color = themeMode === "dark" ? "#999999" : "#737373";
2098
+ e.currentTarget.style.color = "hsl(var(--chat-text-muted))";
2104
2099
  e.currentTarget.style.backgroundColor = "transparent";
2105
2100
  },
2106
2101
  title: "Close Chat",
@@ -2151,6 +2146,43 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2151
2146
 
2152
2147
  // src/ChatWidget.tsx
2153
2148
  import { MessageCircle } from "lucide-react";
2149
+
2150
+ // src/utils/color.ts
2151
+ function toHslTripletIfHex(value) {
2152
+ const trimmed = value.trim();
2153
+ const hexMatch = /^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.exec(trimmed);
2154
+ if (!hexMatch) return value;
2155
+ let hex = hexMatch[1];
2156
+ if (hex.length === 3) {
2157
+ hex = hex.split("").map((c) => c + c).join("");
2158
+ }
2159
+ const r = parseInt(hex.substring(0, 2), 16) / 255;
2160
+ const g = parseInt(hex.substring(2, 4), 16) / 255;
2161
+ const b = parseInt(hex.substring(4, 6), 16) / 255;
2162
+ const max = Math.max(r, g, b);
2163
+ const min = Math.min(r, g, b);
2164
+ const l = (max + min) / 2;
2165
+ let h = 0;
2166
+ let s = 0;
2167
+ if (max !== min) {
2168
+ const d = max - min;
2169
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
2170
+ switch (max) {
2171
+ case r:
2172
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
2173
+ break;
2174
+ case g:
2175
+ h = ((b - r) / d + 2) / 6;
2176
+ break;
2177
+ case b:
2178
+ h = ((r - g) / d + 4) / 6;
2179
+ break;
2180
+ }
2181
+ }
2182
+ return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
2183
+ }
2184
+
2185
+ // src/ChatWidget.tsx
2154
2186
  import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
2155
2187
  function ChatWidget({
2156
2188
  userId,
@@ -2176,8 +2208,20 @@ function ChatWidget({
2176
2208
  if (display?.width) {
2177
2209
  styles["--chat-widget-width"] = display.width;
2178
2210
  }
2211
+ if (theme?.primaryColor) {
2212
+ styles["--chat-primary"] = toHslTripletIfHex(theme.primaryColor);
2213
+ }
2214
+ if (theme?.backgroundColor) {
2215
+ styles["--chat-background"] = toHslTripletIfHex(theme.backgroundColor);
2216
+ }
2217
+ if (theme?.textColor) {
2218
+ styles["--chat-text"] = toHslTripletIfHex(theme.textColor);
2219
+ }
2220
+ if (theme?.tokens) {
2221
+ Object.assign(styles, theme.tokens);
2222
+ }
2179
2223
  return styles;
2180
- }, [display?.width]);
2224
+ }, [display?.width, theme?.primaryColor, theme?.backgroundColor, theme?.textColor, theme?.tokens]);
2181
2225
  const handleMouseDown = useCallback4((e) => {
2182
2226
  if (!resizable) return;
2183
2227
  e.preventDefault();