@mordn/chat-widget 0.1.3 → 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.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,15 +2001,15 @@ 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)"
2008
+ borderColor: "var(--chat-border-soft)",
2009
+ backgroundColor: "var(--chat-overlay)"
2010
2010
  }, children: /* @__PURE__ */ jsxs12("div", { className: "relative", children: [
2011
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"
2012
+ color: "hsl(var(--chat-text-muted))"
2013
2013
  }, strokeWidth: 2 }),
2014
2014
  /* @__PURE__ */ jsx20(
2015
2015
  "input",
@@ -2020,29 +2020,29 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2020
2020
  onChange: (e) => setSearchQuery(e.target.value),
2021
2021
  className: "w-full h-7 pl-8 pr-2.5 text-[13px] rounded-lg focus:outline-none transition-all",
2022
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"
2023
+ backgroundColor: "hsl(var(--chat-surface-deep))",
2024
+ border: `1px solid ${"var(--chat-border-medium)"}`,
2025
+ color: "hsl(var(--chat-text))"
2026
2026
  }
2027
2027
  }
2028
2028
  )
2029
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: [
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: "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
2031
  /* @__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" })
2032
+ backgroundColor: "hsl(var(--chat-surface))"
2033
+ }, children: /* @__PURE__ */ jsx20(MessageSquareIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2034
+ /* @__PURE__ */ jsx20("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Conversations" }),
2035
+ /* @__PURE__ */ jsx20("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Start a new chat to begin" })
2036
2036
  ] }) : groupedConversations.length === 0 ? /* @__PURE__ */ jsxs12("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
2037
2037
  /* @__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" })
2038
+ backgroundColor: "hsl(var(--chat-surface))"
2039
+ }, children: /* @__PURE__ */ jsx20(SearchIcon, { className: "h-5 w-5", style: { color: "hsl(var(--chat-text-subtle))" }, strokeWidth: 2 }) }),
2040
+ /* @__PURE__ */ jsx20("p", { className: "text-[13px] font-medium mb-0.5", style: { color: "hsl(var(--chat-text))" }, children: "No Results" }),
2041
+ /* @__PURE__ */ jsx20("p", { className: "text-[12px]", style: { color: "hsl(var(--chat-text-muted))" }, children: "Try a different search" })
2042
2042
  ] }) : /* @__PURE__ */ jsx20("div", { className: "py-0.5", children: groupedConversations.map(([groupName, groupConversations]) => /* @__PURE__ */ jsxs12("div", { className: "mb-0.5", children: [
2043
2043
  /* @__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 }) }),
2044
+ backgroundColor: "var(--chat-header-bg-strong)"
2045
+ }, children: /* @__PURE__ */ jsx20("h3", { className: "text-[10px] font-semibold uppercase tracking-wide", style: { color: "hsl(var(--chat-text-muted))" }, children: groupName }) }),
2046
2046
  /* @__PURE__ */ jsx20("div", { className: "px-1 space-y-0.5", children: groupConversations.map((conversation) => {
2047
2047
  const isActiveConversation = activeTabId === conversation.id;
2048
2048
  return /* @__PURE__ */ jsx20(
@@ -2050,11 +2050,11 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2050
2050
  {
2051
2051
  className: "w-full px-2 py-1 rounded-md transition-all duration-150 text-left group relative",
2052
2052
  style: {
2053
- backgroundColor: isActiveConversation ? themeMode === "dark" ? "#333333" : "#f5f5f5" : "transparent"
2053
+ backgroundColor: isActiveConversation ? "hsl(var(--chat-surface))" : "transparent"
2054
2054
  },
2055
2055
  onMouseEnter: (e) => {
2056
2056
  if (!isActiveConversation) {
2057
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "rgba(51,51,51,0.5)" : "rgba(245,245,245,0.5)";
2057
+ e.currentTarget.style.backgroundColor = "var(--chat-hover-bg)";
2058
2058
  }
2059
2059
  },
2060
2060
  onMouseLeave: (e) => {
@@ -2066,14 +2066,14 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2066
2066
  children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1.5", children: [
2067
2067
  /* @__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
2068
  fontWeight: isActiveConversation ? 500 : 400,
2069
- color: isActiveConversation ? themeMode === "dark" ? "#e5e5e5" : "#171717" : themeMode === "dark" ? "#cccccc" : "#404040"
2069
+ color: isActiveConversation ? "hsl(var(--chat-text))" : "hsl(var(--chat-text-strong))"
2070
2070
  }, children: conversation.title }) }),
2071
2071
  /* @__PURE__ */ jsx20(
2072
2072
  ChevronRightIcon2,
2073
2073
  {
2074
2074
  className: "h-3 w-3 transition-all duration-150 flex-shrink-0",
2075
2075
  style: {
2076
- color: themeMode === "dark" ? "#666666" : "#a3a3a3",
2076
+ color: "hsl(var(--chat-text-subtle))",
2077
2077
  opacity: isActiveConversation ? 1 : 0
2078
2078
  },
2079
2079
  strokeWidth: 2
@@ -2093,14 +2093,14 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2093
2093
  onClick: onClose,
2094
2094
  className: "flex items-center justify-center w-7 h-7 rounded-lg transition-all duration-150",
2095
2095
  style: {
2096
- color: themeMode === "dark" ? "#999999" : "#737373"
2096
+ color: "hsl(var(--chat-text-muted))"
2097
2097
  },
2098
2098
  onMouseEnter: (e) => {
2099
- e.currentTarget.style.color = themeMode === "dark" ? "#e5e5e5" : "#171717";
2100
- e.currentTarget.style.backgroundColor = themeMode === "dark" ? "#444444" : "#f5f5f5";
2099
+ e.currentTarget.style.color = "hsl(var(--chat-text))";
2100
+ e.currentTarget.style.backgroundColor = "hsl(var(--chat-surface))";
2101
2101
  },
2102
2102
  onMouseLeave: (e) => {
2103
- e.currentTarget.style.color = themeMode === "dark" ? "#999999" : "#737373";
2103
+ e.currentTarget.style.color = "hsl(var(--chat-text-muted))";
2104
2104
  e.currentTarget.style.backgroundColor = "transparent";
2105
2105
  },
2106
2106
  title: "Close Chat",
@@ -2139,7 +2139,7 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2139
2139
  )
2140
2140
  ] }),
2141
2141
  /* @__PURE__ */ jsxs12(PromptInputToolbar, { children: [
2142
- /* @__PURE__ */ jsx20(PromptInputTools, { children: config?.features?.fileUpload !== false && /* @__PURE__ */ jsx20(AttachButton, {}) }),
2142
+ /* @__PURE__ */ jsx20(PromptInputTools, { children: config?.features?.fileUpload === true && /* @__PURE__ */ jsx20(AttachButton, {}) }),
2143
2143
  /* @__PURE__ */ jsx20(PromptInputSubmit, { disabled: !input, status })
2144
2144
  ] })
2145
2145
  ] })
@@ -2151,6 +2151,43 @@ function ChatInterface({ id, initialMessages, config, onClose } = {}) {
2151
2151
 
2152
2152
  // src/ChatWidget.tsx
2153
2153
  import { MessageCircle } from "lucide-react";
2154
+
2155
+ // src/utils/color.ts
2156
+ function toHslTripletIfHex(value) {
2157
+ const trimmed = value.trim();
2158
+ const hexMatch = /^#?([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.exec(trimmed);
2159
+ if (!hexMatch) return value;
2160
+ let hex = hexMatch[1];
2161
+ if (hex.length === 3) {
2162
+ hex = hex.split("").map((c) => c + c).join("");
2163
+ }
2164
+ const r = parseInt(hex.substring(0, 2), 16) / 255;
2165
+ const g = parseInt(hex.substring(2, 4), 16) / 255;
2166
+ const b = parseInt(hex.substring(4, 6), 16) / 255;
2167
+ const max = Math.max(r, g, b);
2168
+ const min = Math.min(r, g, b);
2169
+ const l = (max + min) / 2;
2170
+ let h = 0;
2171
+ let s = 0;
2172
+ if (max !== min) {
2173
+ const d = max - min;
2174
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
2175
+ switch (max) {
2176
+ case r:
2177
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
2178
+ break;
2179
+ case g:
2180
+ h = ((b - r) / d + 2) / 6;
2181
+ break;
2182
+ case b:
2183
+ h = ((r - g) / d + 4) / 6;
2184
+ break;
2185
+ }
2186
+ }
2187
+ return `${Math.round(h * 360)} ${Math.round(s * 100)}% ${Math.round(l * 100)}%`;
2188
+ }
2189
+
2190
+ // src/ChatWidget.tsx
2154
2191
  import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
2155
2192
  function ChatWidget({
2156
2193
  userId,
@@ -2176,8 +2213,20 @@ function ChatWidget({
2176
2213
  if (display?.width) {
2177
2214
  styles["--chat-widget-width"] = display.width;
2178
2215
  }
2216
+ if (theme?.primaryColor) {
2217
+ styles["--chat-primary"] = toHslTripletIfHex(theme.primaryColor);
2218
+ }
2219
+ if (theme?.backgroundColor) {
2220
+ styles["--chat-background"] = toHslTripletIfHex(theme.backgroundColor);
2221
+ }
2222
+ if (theme?.textColor) {
2223
+ styles["--chat-text"] = toHslTripletIfHex(theme.textColor);
2224
+ }
2225
+ if (theme?.tokens) {
2226
+ Object.assign(styles, theme.tokens);
2227
+ }
2179
2228
  return styles;
2180
- }, [display?.width]);
2229
+ }, [display?.width, theme?.primaryColor, theme?.backgroundColor, theme?.textColor, theme?.tokens]);
2181
2230
  const handleMouseDown = useCallback4((e) => {
2182
2231
  if (!resizable) return;
2183
2232
  e.preventDefault();