@akropolys/kiku 1.6.8 → 1.6.10

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
@@ -1157,6 +1157,7 @@ var ArrowUpIcon2 = () => /* @__PURE__ */ jsxs6("svg", { width: "18", height: "18
1157
1157
  /* @__PURE__ */ jsx7("path", { d: "m5 12 7-7 7 7" }),
1158
1158
  /* @__PURE__ */ jsx7("path", { d: "M12 19V5" })
1159
1159
  ] });
1160
+ var StopIcon = () => /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx7("rect", { x: "5", y: "5", width: "14", height: "14", rx: "2" }) });
1160
1161
  var CloseIcon = () => /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
1161
1162
  /* @__PURE__ */ jsx7("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1162
1163
  /* @__PURE__ */ jsx7("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
@@ -1167,7 +1168,6 @@ var HistoryIcon = () => /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16"
1167
1168
  /* @__PURE__ */ jsx7("path", { d: "M3 3v5h5" }),
1168
1169
  /* @__PURE__ */ jsx7("path", { d: "M12 7v5l4 2" })
1169
1170
  ] });
1170
- var NewChatIcon = () => /* @__PURE__ */ jsx7("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: "M12 5v14M5 12h14" }) });
1171
1171
  var BookmarkIcon = () => /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: "M19 21 12 16l-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" }) });
1172
1172
  var TrashIcon = () => /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1173
1173
  /* @__PURE__ */ jsx7("path", { d: "M3 6h18" }),
@@ -1193,8 +1193,6 @@ var DEFAULT_CHIPS = [
1193
1193
  "Noise-cancelling headphones",
1194
1194
  "Best laptop for students"
1195
1195
  ];
1196
- var SESSIONS_KEY = "akropolys_chat_sessions";
1197
- var MAX_SESSIONS = 20;
1198
1196
  function parseAtKiku(raw) {
1199
1197
  const trimmed = raw.trim();
1200
1198
  if (!/^@kiku\b/i.test(trimmed)) return null;
@@ -1347,33 +1345,7 @@ function AtPickerMenu({ onSelect, onDismiss }) {
1347
1345
  }
1348
1346
  );
1349
1347
  }
1350
- function loadSessions() {
1351
- try {
1352
- if (typeof window === "undefined") return [];
1353
- const raw = localStorage.getItem(SESSIONS_KEY);
1354
- return raw ? JSON.parse(raw) : [];
1355
- } catch {
1356
- return [];
1357
- }
1358
- }
1359
- function saveSessions(sessions) {
1360
- try {
1361
- if (typeof window === "undefined") return;
1362
- localStorage.setItem(SESSIONS_KEY, JSON.stringify(sessions.slice(0, MAX_SESSIONS)));
1363
- } catch {
1364
- }
1365
- }
1366
- function relativeTime(ts) {
1367
- const diff = Date.now() - ts;
1368
- const mins = Math.floor(diff / 6e4);
1369
- if (mins < 1) return "just now";
1370
- if (mins < 60) return `${mins}m ago`;
1371
- const hrs = Math.floor(mins / 60);
1372
- if (hrs < 24) return `${hrs}h ago`;
1373
- const days = Math.floor(hrs / 24);
1374
- return `${days}d ago`;
1375
- }
1376
- function SourcesCarousel({ sources, defaultCurrency, onSelectSource, referencedIds = [] }) {
1348
+ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, onImageClick, referencedIds = [] }) {
1377
1349
  const client = useAkropolysContext3();
1378
1350
  const isProperty = client?.vertical === "property";
1379
1351
  const railRef = useRef5(null);
@@ -1412,7 +1384,18 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, referencedI
1412
1384
  onClick: () => onSelectSource?.(src),
1413
1385
  children: [
1414
1386
  src.image ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-imgwrap", style: { position: "relative" }, children: [
1415
- /* @__PURE__ */ jsx7("img", { src: src.image, alt: src.name, loading: "lazy" }),
1387
+ /* @__PURE__ */ jsx7(
1388
+ "img",
1389
+ {
1390
+ src: src.image,
1391
+ alt: src.name,
1392
+ loading: "lazy",
1393
+ onClick: onImageClick ? (e) => {
1394
+ e.stopPropagation();
1395
+ onImageClick(src.image);
1396
+ } : void 0
1397
+ }
1398
+ ),
1416
1399
  isReferenced && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", children: /* @__PURE__ */ jsx7(SparkleIcon2, { size: 10 }) }),
1417
1400
  isProperty && /* @__PURE__ */ jsx7("div", { style: {
1418
1401
  position: "absolute",
@@ -1685,7 +1668,7 @@ function ChatModal({
1685
1668
  visionCategoryHint
1686
1669
  }) {
1687
1670
  const client = useAkropolysContext3();
1688
- const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, reset, referencedIds } = useKiku2();
1671
+ const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, stop, reset, referencedIds } = useKiku2();
1689
1672
  const [input, setInput] = useState5("");
1690
1673
  const [attachments, setAttachments] = useState5([]);
1691
1674
  const imageInputRef = useRef5(null);
@@ -1760,6 +1743,7 @@ function ChatModal({
1760
1743
  const activeTitle = title === "Shopping Assistant" && isProperty ? "Property Assistant" : title;
1761
1744
  const activePlaceholder = placeholder === "Ask me anything \u2014 gifts, budget, use case\u2026" && isProperty ? "Ask me anything \u2014 location, budget, bedrooms\u2026" : placeholder;
1762
1745
  const [selectedProduct, setSelectedProduct] = useState5(null);
1746
+ const [lightboxSrc, setLightboxSrc] = useState5(null);
1763
1747
  const bottomRef = useRef5(null);
1764
1748
  const textareaRef = useRef5(null);
1765
1749
  const [keyInput, setKeyInput] = useState5("");
@@ -1769,9 +1753,6 @@ function ChatModal({
1769
1753
  const [minting, setMinting] = useState5(false);
1770
1754
  const [showKikuPicker, setShowKikuPicker] = useState5(false);
1771
1755
  const [showAtPicker, setShowAtPicker] = useState5(false);
1772
- const [sessions, setSessions] = useState5(() => loadSessions());
1773
- const [sidebarOpen, setSidebarOpen] = useState5(false);
1774
- const [replayMessages, setReplayMessages] = useState5(null);
1775
1756
  useEffect3(() => {
1776
1757
  if (!lastAction) return;
1777
1758
  if (lastAction.type === "request_kiku_key") {
@@ -1828,40 +1809,43 @@ function ChatModal({
1828
1809
  }
1829
1810
  };
1830
1811
  const msgsContainerRef = useRef5(null);
1812
+ const messageRefs = useRef5([]);
1831
1813
  useEffect3(() => {
1832
1814
  const container = msgsContainerRef.current;
1833
1815
  if (!container) return;
1816
+ const lastMsg = messages[messages.length - 1];
1817
+ if (lastMsg?.role === "user") {
1818
+ messageRefs.current[messages.length - 1]?.scrollIntoView({ behavior: "smooth", block: "start" });
1819
+ return;
1820
+ }
1834
1821
  const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
1835
1822
  if (distanceFromBottom < 120) {
1836
1823
  bottomRef.current?.scrollIntoView({ behavior: "smooth" });
1837
1824
  }
1838
1825
  }, [messages, loading, selectedProduct]);
1826
+ useEffect3(() => {
1827
+ const prev = document.body.style.overflow;
1828
+ document.body.style.overflow = "hidden";
1829
+ return () => {
1830
+ document.body.style.overflow = prev;
1831
+ };
1832
+ }, []);
1839
1833
  useEffect3(() => {
1840
1834
  const h = (e) => {
1841
- if (e.key === "Escape") onClose();
1835
+ if (e.key !== "Escape") return;
1836
+ if (lightboxSrc) {
1837
+ setLightboxSrc(null);
1838
+ return;
1839
+ }
1840
+ onClose();
1842
1841
  };
1843
1842
  document.addEventListener("keydown", h);
1844
1843
  return () => document.removeEventListener("keydown", h);
1845
- }, []);
1846
- const saveCurrentSession = useCallback2(() => {
1847
- if (messages.length < 2) return;
1848
- const firstUser = messages.find((m) => m.role === "user");
1849
- const session = {
1850
- id: `session_${Date.now()}`,
1851
- title: firstUser ? firstUser.content.slice(0, 60) : "Chat session",
1852
- messages,
1853
- ts: Date.now()
1854
- };
1855
- const updated = [session, ...sessions].slice(0, MAX_SESSIONS);
1856
- setSessions(updated);
1857
- saveSessions(updated);
1858
- }, [messages, sessions]);
1844
+ }, [lightboxSrc, onClose]);
1859
1845
  const handleReset = useCallback2(() => {
1860
- saveCurrentSession();
1861
1846
  reset();
1862
- setReplayMessages(null);
1863
1847
  setKeyPhase("idle");
1864
- }, [reset, saveCurrentSession]);
1848
+ }, [reset]);
1865
1849
  const handleSourceClick = (src) => {
1866
1850
  setSelectedProduct(src);
1867
1851
  onSelectSource?.(src);
@@ -1874,7 +1858,6 @@ function ChatModal({
1874
1858
  const kiku = parseAtKiku(raw);
1875
1859
  const q = kiku ? kiku.cleanQuery : raw;
1876
1860
  const resolvedForcedIntent = forcedIntent ?? kiku?.intent;
1877
- setReplayMessages(null);
1878
1861
  setSelectedProduct(null);
1879
1862
  setShowKikuPicker(false);
1880
1863
  setShowAtPicker(false);
@@ -1899,7 +1882,6 @@ function ChatModal({
1899
1882
  const display = `@kiku capture${name ? " " + name : ""}`;
1900
1883
  const q = name || "capture current page";
1901
1884
  setInput("");
1902
- setReplayMessages(null);
1903
1885
  setSelectedProduct(null);
1904
1886
  const toSend = attachments;
1905
1887
  setAttachments([]);
@@ -1916,7 +1898,6 @@ function ChatModal({
1916
1898
  const names = products.map((p) => p.name).filter(Boolean).join(", ");
1917
1899
  const display = `@kiku capture all (${products.length} items)`;
1918
1900
  setInput("");
1919
- setReplayMessages(null);
1920
1901
  setSelectedProduct(null);
1921
1902
  setAttachments([]);
1922
1903
  send(names || "capture all", display, void 0, "capture_all", targets);
@@ -1924,7 +1905,6 @@ function ChatModal({
1924
1905
  const handleKikuViewHistory = useCallback2(() => {
1925
1906
  const display = "@kiku what have you saved?";
1926
1907
  setInput("");
1927
- setReplayMessages(null);
1928
1908
  setSelectedProduct(null);
1929
1909
  setAttachments([]);
1930
1910
  send("show my saved items", display, void 0, "view_history");
@@ -1932,7 +1912,6 @@ function ChatModal({
1932
1912
  const handleKikuDelete = useCallback2(() => {
1933
1913
  const display = "@kiku delete this";
1934
1914
  setInput("");
1935
- setReplayMessages(null);
1936
1915
  setSelectedProduct(null);
1937
1916
  setAttachments([]);
1938
1917
  send("delete this", display, void 0, "delete");
@@ -1978,17 +1957,7 @@ function ChatModal({
1978
1957
  return () => clearTimeout(timer);
1979
1958
  }, [voiceState]);
1980
1959
  const blurVal = typeof backdropBlur === "number" ? `${backdropBlur}px` : backdropBlur ?? "20px";
1981
- const displayMessages = replayMessages ?? messages;
1982
- const loadSession = (session) => {
1983
- setReplayMessages(session.messages);
1984
- setSidebarOpen(false);
1985
- };
1986
- const deleteSession = (id, e) => {
1987
- e.stopPropagation();
1988
- const updated = sessions.filter((s) => s.id !== id);
1989
- setSessions(updated);
1990
- saveSessions(updated);
1991
- };
1960
+ const displayMessages = messages;
1992
1961
  return /* @__PURE__ */ jsx7(
1993
1962
  "div",
1994
1963
  {
@@ -2001,326 +1970,298 @@ function ChatModal({
2001
1970
  ...backdropColor ? { background: backdropColor } : {},
2002
1971
  ...customStyles
2003
1972
  },
2004
- children: /* @__PURE__ */ jsxs6("div", { className: cn("hsk-cb-panel hsk-cb-panel--with-sidebar", classNames.panel), onClick: (e) => e.stopPropagation(), children: [
2005
- /* @__PURE__ */ jsxs6("div", { className: cn("hsk-cb-sidebar", sidebarOpen && "hsk-cb-sidebar--open"), children: [
2006
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-sidebar-header", children: [
2007
- /* @__PURE__ */ jsx7("span", { className: "hsk-cb-sidebar-title", children: "History" }),
2008
- /* @__PURE__ */ jsxs6(
2009
- "button",
2010
- {
2011
- className: "hsk-cb-sidebar-new",
2012
- onClick: handleReset,
2013
- title: "New chat",
2014
- children: [
2015
- /* @__PURE__ */ jsx7(NewChatIcon, {}),
2016
- /* @__PURE__ */ jsx7("span", { children: "New chat" })
2017
- ]
2018
- }
2019
- )
2020
- ] }),
2021
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-sidebar-list", children: sessions.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-sidebar-empty", children: [
2022
- /* @__PURE__ */ jsx7(HistoryIcon, {}),
2023
- /* @__PURE__ */ jsx7("span", { children: "No history yet" })
2024
- ] }) : sessions.map((session) => /* @__PURE__ */ jsxs6(
2025
- "div",
2026
- {
2027
- className: cn(
2028
- "hsk-cb-sidebar-session",
2029
- replayMessages === session.messages && "hsk-cb-sidebar-session--active"
2030
- ),
2031
- onClick: () => loadSession(session),
2032
- children: [
2033
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-sidebar-session-title", children: session.title }),
2034
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-sidebar-session-meta", children: relativeTime(session.ts) }),
2035
- /* @__PURE__ */ jsx7(
2036
- "button",
2037
- {
2038
- className: "hsk-cb-sidebar-session-del",
2039
- onClick: (e) => deleteSession(session.id, e),
2040
- title: "Delete",
2041
- children: "\xD7"
2042
- }
2043
- )
2044
- ]
2045
- },
2046
- session.id
2047
- )) })
2048
- ] }),
2049
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-main", children: [
2050
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-topbar", children: [
2051
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-topbar-left", children: [
2052
- /* @__PURE__ */ jsx7(
2053
- "button",
2054
- {
2055
- className: cn("hsk-cb-sidebar-toggle", sidebarOpen && "hsk-cb-sidebar-toggle--active"),
2056
- onClick: (e) => {
2057
- e.stopPropagation();
2058
- setSidebarOpen((v) => !v);
2059
- },
2060
- "aria-label": "Toggle history",
2061
- children: /* @__PURE__ */ jsx7(HistoryIcon, {})
2062
- }
2063
- ),
2064
- /* @__PURE__ */ jsx7("span", { className: "hsk-cb-topbar-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2065
- /* @__PURE__ */ jsx7("div", { children: /* @__PURE__ */ jsx7("div", { className: "hsk-cb-topbar-title", children: activeTitle }) })
1973
+ children: /* @__PURE__ */ jsxs6(
1974
+ "div",
1975
+ {
1976
+ className: cn("hsk-cb-panel", classNames.panel),
1977
+ onClick: (e) => {
1978
+ e.stopPropagation();
1979
+ const target = e.target;
1980
+ if (target.tagName === "IMG" && (target.classList.contains("hsk-markdown-img") || target.classList.contains("hsk-cb-user-img-thumb"))) {
1981
+ const src = target.src;
1982
+ if (src) setLightboxSrc(src);
1983
+ }
1984
+ },
1985
+ children: [
1986
+ lightboxSrc && /* @__PURE__ */ jsxs6("div", { className: "hsk-lightbox", onClick: () => setLightboxSrc(null), children: [
1987
+ /* @__PURE__ */ jsx7("button", { className: "hsk-lightbox-close", onClick: () => setLightboxSrc(null), "aria-label": "Close image", children: /* @__PURE__ */ jsx7(CloseIcon, {}) }),
1988
+ /* @__PURE__ */ jsx7("img", { src: lightboxSrc, alt: "", className: "hsk-lightbox-img", onClick: (e) => e.stopPropagation() })
2066
1989
  ] }),
2067
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-topbar-actions", children: [
2068
- replayMessages ? /* @__PURE__ */ jsx7("button", { className: "hsk-cb-topbar-btn", onClick: () => {
2069
- setReplayMessages(null);
2070
- }, children: "\u2190 Live chat" }) : messages.length > 0 && /* @__PURE__ */ jsx7("button", { className: "hsk-cb-topbar-btn", onClick: handleReset, children: "Clear chat" }),
2071
- /* @__PURE__ */ jsx7("button", { className: "hsk-cb-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx7(CloseIcon, {}) })
2072
- ] })
2073
- ] }),
2074
- replayMessages && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-replay-banner", children: [
2075
- /* @__PURE__ */ jsx7(HistoryIcon, {}),
2076
- /* @__PURE__ */ jsx7("span", { children: "You're viewing a past conversation." }),
2077
- /* @__PURE__ */ jsx7("button", { onClick: () => setReplayMessages(null), children: "Back to chat \u2192" })
2078
- ] }),
2079
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-msgs", ref: msgsContainerRef, children: [
2080
- displayMessages.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-empty", children: [
2081
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-empty-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2082
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-empty-title", children: "Find exactly what you need" }),
2083
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-chips", children: activeChips.map((chip) => /* @__PURE__ */ jsx7(
2084
- "button",
2085
- {
2086
- className: "hsk-cb-chip",
2087
- onClick: () => handleSend(chip),
2088
- children: chip
2089
- },
2090
- chip
2091
- )) })
2092
- ] }) : displayMessages.map((msg, idx) => {
2093
- const isLast = idx === displayMessages.length - 1 && !replayMessages;
2094
- const isUser = msg.role === "user";
2095
- const displayContent = !isUser && isLast && lastIntent === "compare" && sources.length >= 2 && !replayMessages ? stripMarkdownTables(msg.content) : msg.content;
2096
- return /* @__PURE__ */ jsx7("div", { className: "hsk-cb-msg-group", children: isUser ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-user-msg", children: [
2097
- msg.images && msg.images.length > 0 && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-user-imgs", children: msg.images.map((img, i) => /* @__PURE__ */ jsx7("img", { src: img, alt: `attachment ${i + 1}`, className: "hsk-cb-user-img-thumb" }, i)) }),
2098
- msg.content && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-user-bubble", children: [
2099
- /^@kiku\b/i.test(msg.content) && /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-badge", children: "@kiku" }),
2100
- msg.content
1990
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-main", children: [
1991
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-topbar", children: [
1992
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-topbar-left", children: [
1993
+ /* @__PURE__ */ jsx7("span", { className: "hsk-cb-topbar-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
1994
+ /* @__PURE__ */ jsx7("div", { children: /* @__PURE__ */ jsx7("div", { className: "hsk-cb-topbar-title", children: activeTitle }) })
1995
+ ] }),
1996
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-topbar-actions", children: [
1997
+ messages.length > 0 && /* @__PURE__ */ jsx7("button", { className: "hsk-cb-topbar-btn", onClick: handleReset, children: "Clear chat" }),
1998
+ /* @__PURE__ */ jsx7("button", { className: "hsk-cb-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx7(CloseIcon, {}) })
2101
1999
  ] })
2102
- ] }) : /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-msg", children: [
2103
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2104
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-body", children: [
2105
- (() => {
2106
- const { thinking, content, isComplete } = parseThinking(displayContent);
2107
- return /* @__PURE__ */ jsxs6(Fragment3, { children: [
2108
- thinking && /* @__PURE__ */ jsx7(ThinkingBlock, { text: thinking, isComplete }),
2109
- content && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-text", children: [
2110
- renderMarkdown(content),
2111
- isLast && streaming && /* @__PURE__ */ jsx7("span", { style: { display: "inline-block", width: "0.5em", height: "1.05em", marginLeft: "2px", verticalAlign: "text-bottom", background: "currentColor", opacity: 0.55, borderRadius: "1px" } })
2112
- ] })
2113
- ] });
2114
- })(),
2115
- isLast && lastIntent === "compare" && sources.length >= 2 && !replayMessages && /* @__PURE__ */ jsx7(ComparisonMatrix, { sources, defaultCurrency }),
2116
- isLast && referencedIds.length > 0 && lastIntent !== "compare" && lastAction?.type !== "request_kiku_key" && lastAction?.type !== "capture" && lastAction?.type !== "delete" && lastAction?.type !== "view_history" && /* @__PURE__ */ jsx7(
2117
- SourcesCarousel,
2118
- {
2119
- sources,
2120
- defaultCurrency,
2121
- onSelectSource: handleSourceClick,
2122
- referencedIds
2123
- }
2124
- ),
2125
- isLast && !loading && lastAction?.url && /* @__PURE__ */ jsx7("div", { className: "hsk-action-pills", children: /* @__PURE__ */ jsxs6("a", { className: "hsk-action-pill", href: lastAction.url, children: [
2126
- String(lastAction.type || "continue").replace(/_/g, " "),
2127
- " \u2192"
2128
- ] }) }),
2129
- isLast && !loading && !replayMessages && /* @__PURE__ */ jsx7(
2130
- SmartContextPills,
2000
+ ] }),
2001
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-msgs", ref: msgsContainerRef, children: [
2002
+ displayMessages.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-empty", children: [
2003
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-empty-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2004
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-empty-title", children: "Find exactly what you need" }),
2005
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-chips", children: activeChips.map((chip) => /* @__PURE__ */ jsx7(
2006
+ "button",
2131
2007
  {
2132
- intent: lastIntent,
2133
- sources: sources.filter((s) => s.id && referencedIds.includes(s.id)),
2134
- onSend: handleSend,
2135
- loading
2136
- }
2137
- )
2138
- ] })
2139
- ] }) }, idx);
2140
- }),
2141
- selectedProduct && loading && /* @__PURE__ */ jsxs6(
2142
- "div",
2143
- {
2144
- className: "hsk-cb-selected-product",
2145
- onClick: () => selectedProduct.url && window.open(selectedProduct.url, "_blank"),
2146
- children: [
2147
- selectedProduct.image && /* @__PURE__ */ jsx7("img", { className: "hsk-cb-selected-img", src: selectedProduct.image, alt: selectedProduct.name }),
2148
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-selected-info", children: [
2149
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-selected-name", children: selectedProduct.name }),
2150
- selectedProduct.price && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-selected-price", children: [
2151
- selectedProduct.currency ?? defaultCurrency,
2152
- " ",
2153
- parseFloat(String(selectedProduct.price ?? "").replace(/[^0-9.]/g, "") || "0").toLocaleString()
2008
+ className: "hsk-cb-chip",
2009
+ onClick: () => handleSend(chip),
2010
+ children: chip
2011
+ },
2012
+ chip
2013
+ )) })
2014
+ ] }) : displayMessages.map((msg, idx) => {
2015
+ const isLast = idx === displayMessages.length - 1;
2016
+ const isUser = msg.role === "user";
2017
+ const displayContent = !isUser && isLast && lastIntent === "compare" && sources.length >= 2 ? stripMarkdownTables(msg.content) : msg.content;
2018
+ return /* @__PURE__ */ jsx7("div", { className: "hsk-cb-msg-group", ref: (el) => {
2019
+ messageRefs.current[idx] = el;
2020
+ }, children: isUser ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-user-msg", children: [
2021
+ msg.images && msg.images.length > 0 && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-user-imgs", children: msg.images.map((img, i) => /* @__PURE__ */ jsx7("img", { src: img, alt: `attachment ${i + 1}`, className: "hsk-cb-user-img-thumb" }, i)) }),
2022
+ msg.content && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-user-bubble", children: [
2023
+ /^@kiku\b/i.test(msg.content) && /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-badge", children: "@kiku" }),
2024
+ msg.content
2154
2025
  ] })
2155
- ] })
2156
- ]
2157
- }
2158
- ),
2159
- loading && !streaming && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-typing-row", style: { display: "flex", alignItems: "flex-start", gap: "10px" }, children: [
2160
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center", marginTop: "4px" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2161
- /* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
2162
- /* @__PURE__ */ jsx7("style", { children: `
2026
+ ] }) : /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-msg", children: [
2027
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2028
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-body", children: [
2029
+ (() => {
2030
+ const { thinking, content, isComplete } = parseThinking(displayContent);
2031
+ return /* @__PURE__ */ jsxs6(Fragment3, { children: [
2032
+ thinking && /* @__PURE__ */ jsx7(ThinkingBlock, { text: thinking, isComplete }),
2033
+ content && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-text", children: [
2034
+ renderMarkdown(content),
2035
+ isLast && streaming && /* @__PURE__ */ jsx7("span", { style: { display: "inline-block", width: "0.5em", height: "1.05em", marginLeft: "2px", verticalAlign: "text-bottom", background: "currentColor", opacity: 0.55, borderRadius: "1px" } })
2036
+ ] })
2037
+ ] });
2038
+ })(),
2039
+ isLast && lastIntent === "compare" && sources.length >= 2 && /* @__PURE__ */ jsx7(ComparisonMatrix, { sources, defaultCurrency }),
2040
+ (() => {
2041
+ const msgReferencedIds = isLast ? referencedIds : msg.referencedIds ?? [];
2042
+ const msgSources = isLast ? sources : msg.sources ?? [];
2043
+ const showCarousel = msgReferencedIds.length > 0 && (isLast ? lastIntent !== "compare" : msg.intent !== "compare") && lastAction?.type !== "request_kiku_key" && lastAction?.type !== "capture" && lastAction?.type !== "delete" && lastAction?.type !== "view_history";
2044
+ return showCarousel && /* @__PURE__ */ jsx7(
2045
+ SourcesCarousel,
2046
+ {
2047
+ sources: msgSources,
2048
+ defaultCurrency,
2049
+ onSelectSource: handleSourceClick,
2050
+ onImageClick: setLightboxSrc,
2051
+ referencedIds: msgReferencedIds
2052
+ }
2053
+ );
2054
+ })(),
2055
+ isLast && !loading && lastAction?.url && /* @__PURE__ */ jsx7("div", { className: "hsk-action-pills", children: /* @__PURE__ */ jsxs6("a", { className: "hsk-action-pill", href: lastAction.url, children: [
2056
+ String(lastAction.type || "continue").replace(/_/g, " "),
2057
+ " \u2192"
2058
+ ] }) }),
2059
+ isLast && !loading && /* @__PURE__ */ jsx7(
2060
+ SmartContextPills,
2061
+ {
2062
+ intent: lastIntent,
2063
+ sources: sources.filter((s) => s.id && referencedIds.includes(s.id)),
2064
+ onSend: handleSend,
2065
+ loading
2066
+ }
2067
+ )
2068
+ ] })
2069
+ ] }) }, idx);
2070
+ }),
2071
+ selectedProduct && loading && /* @__PURE__ */ jsxs6(
2072
+ "div",
2073
+ {
2074
+ className: "hsk-cb-selected-product",
2075
+ onClick: () => selectedProduct.url && window.open(selectedProduct.url, "_blank"),
2076
+ children: [
2077
+ selectedProduct.image && /* @__PURE__ */ jsx7("img", { className: "hsk-cb-selected-img", src: selectedProduct.image, alt: selectedProduct.name }),
2078
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-selected-info", children: [
2079
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-selected-name", children: selectedProduct.name }),
2080
+ selectedProduct.price && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-selected-price", children: [
2081
+ selectedProduct.currency ?? defaultCurrency,
2082
+ " ",
2083
+ parseFloat(String(selectedProduct.price ?? "").replace(/[^0-9.]/g, "") || "0").toLocaleString()
2084
+ ] })
2085
+ ] })
2086
+ ]
2087
+ }
2088
+ ),
2089
+ loading && !streaming && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-typing-row", style: { display: "flex", alignItems: "flex-start", gap: "10px" }, children: [
2090
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center", marginTop: "4px" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2091
+ /* @__PURE__ */ jsxs6("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
2092
+ /* @__PURE__ */ jsx7("style", { children: `
2163
2093
  @keyframes hsk-pulse {
2164
2094
  0%, 100% { opacity: 0.6; }
2165
2095
  50% { opacity: 1; }
2166
2096
  }
2167
2097
  ` }),
2168
- /* @__PURE__ */ jsx7("div", { style: { fontSize: "0.85rem", color: "#6b7280", fontStyle: "italic", animation: "hsk-pulse 1.5s infinite ease-in-out" }, children: "Thinking\u2026" }),
2169
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-typing", style: { margin: 0, alignSelf: "flex-start" }, children: [
2170
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-dot" }),
2171
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-dot" }),
2172
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-dot" })
2173
- ] })
2174
- ] })
2175
- ] }),
2176
- error && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-error", children: getFriendlyError(error) }),
2177
- !replayMessages && keyPhase === "prompt_key" && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-msg", children: [
2178
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2179
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-phone-form", children: [
2180
- /* @__PURE__ */ jsx7("label", { className: "hsk-cb-phone-label", children: "Paste your kiku key \u2014 or create one" }),
2181
- /* @__PURE__ */ jsx7(
2182
- "input",
2098
+ /* @__PURE__ */ jsx7("div", { style: { fontSize: "0.85rem", color: "#6b7280", fontStyle: "italic", animation: "hsk-pulse 1.5s infinite ease-in-out" }, children: "Thinking\u2026" }),
2099
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-typing", style: { margin: 0, alignSelf: "flex-start" }, children: [
2100
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-dot" }),
2101
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-dot" }),
2102
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-dot" })
2103
+ ] })
2104
+ ] })
2105
+ ] }),
2106
+ error && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-error", children: getFriendlyError(error) }),
2107
+ keyPhase === "prompt_key" && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-msg", children: [
2108
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2109
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-phone-form", children: [
2110
+ /* @__PURE__ */ jsx7("label", { className: "hsk-cb-phone-label", children: "Paste your kiku key \u2014 or create one" }),
2111
+ /* @__PURE__ */ jsx7(
2112
+ "input",
2113
+ {
2114
+ type: "text",
2115
+ className: "hsk-cb-phone-input",
2116
+ placeholder: "kiku_\u2026",
2117
+ value: keyInput,
2118
+ onChange: (e) => setKeyInput(e.target.value),
2119
+ onKeyDown: (e) => e.key === "Enter" && handleUseExistingKey(),
2120
+ autoFocus: true
2121
+ }
2122
+ ),
2123
+ /* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 8 }, children: [
2124
+ /* @__PURE__ */ jsx7("button", { className: "hsk-cb-phone-submit", onClick: handleUseExistingKey, disabled: !keyInput.trim(), children: "Use my key" }),
2125
+ /* @__PURE__ */ jsx7("button", { className: "hsk-cb-phone-submit", onClick: handleCreateKey, disabled: minting, children: minting ? "Creating\u2026" : "I'm new \u2014 create my key" })
2126
+ ] })
2127
+ ] }) }) })
2128
+ ] }),
2129
+ mintedKey && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-msg", children: [
2130
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2131
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ jsxs6("div", { style: { padding: "10px 12px", border: "1px solid var(--hsk-border, #e5e5e5)", borderRadius: 8 }, children: [
2132
+ /* @__PURE__ */ jsx7("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "\u{1F511} Your kiku key \u2014 shown only once" }),
2133
+ /* @__PURE__ */ jsx7("code", { style: { display: "block", fontSize: 14, fontWeight: 700, marginBottom: 6, wordBreak: "break-all" }, children: mintedKey }),
2134
+ /* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2135
+ /* @__PURE__ */ jsx7("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => {
2136
+ try {
2137
+ navigator.clipboard?.writeText(mintedKey);
2138
+ } catch {
2139
+ }
2140
+ }, children: "Copy" }),
2141
+ /* @__PURE__ */ jsxs6("span", { style: { fontSize: 11, opacity: 0.7 }, children: [
2142
+ "Disappears in ",
2143
+ keyCountdown,
2144
+ "s. Save it like a password \u2014 if lost, the memory it opens is lost with it."
2145
+ ] })
2146
+ ] })
2147
+ ] }) }) })
2148
+ ] }),
2149
+ /* @__PURE__ */ jsx7("div", { ref: bottomRef, style: { height: 1 } })
2150
+ ] }),
2151
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-input-wrap", children: [
2152
+ showAtPicker && /* @__PURE__ */ jsx7(
2153
+ AtPickerMenu,
2183
2154
  {
2184
- type: "text",
2185
- className: "hsk-cb-phone-input",
2186
- placeholder: "kiku_\u2026",
2187
- value: keyInput,
2188
- onChange: (e) => setKeyInput(e.target.value),
2189
- onKeyDown: (e) => e.key === "Enter" && handleUseExistingKey(),
2190
- autoFocus: true
2155
+ onSelect: handleSelectExtension,
2156
+ onDismiss: () => setShowAtPicker(false)
2191
2157
  }
2192
2158
  ),
2193
- /* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 8 }, children: [
2194
- /* @__PURE__ */ jsx7("button", { className: "hsk-cb-phone-submit", onClick: handleUseExistingKey, disabled: !keyInput.trim(), children: "Use my key" }),
2195
- /* @__PURE__ */ jsx7("button", { className: "hsk-cb-phone-submit", onClick: handleCreateKey, disabled: minting, children: minting ? "Creating\u2026" : "I'm new \u2014 create my key" })
2196
- ] })
2197
- ] }) }) })
2198
- ] }),
2199
- !replayMessages && mintedKey && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-msg", children: [
2200
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
2201
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ jsxs6("div", { style: { padding: "10px 12px", border: "1px solid var(--hsk-border, #e5e5e5)", borderRadius: 8 }, children: [
2202
- /* @__PURE__ */ jsx7("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "\u{1F511} Your kiku key \u2014 shown only once" }),
2203
- /* @__PURE__ */ jsx7("code", { style: { display: "block", fontSize: 14, fontWeight: 700, marginBottom: 6, wordBreak: "break-all" }, children: mintedKey }),
2204
- /* @__PURE__ */ jsxs6("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2205
- /* @__PURE__ */ jsx7("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => {
2206
- try {
2207
- navigator.clipboard?.writeText(mintedKey);
2208
- } catch {
2159
+ showKikuPicker && /* @__PURE__ */ jsx7(
2160
+ KikuPickerMenu,
2161
+ {
2162
+ sources,
2163
+ referencedIds,
2164
+ defaultCurrency,
2165
+ onCapture: handleKikuCapture,
2166
+ onCaptureAll: handleKikuCaptureAll,
2167
+ onViewHistory: handleKikuViewHistory,
2168
+ onDelete: handleKikuDelete,
2169
+ onDismiss: () => setShowKikuPicker(false)
2170
+ }
2171
+ ),
2172
+ attachments.length > 0 && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-img-strip", children: attachments.map((att, i) => /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-img-thumb-wrap", children: [
2173
+ /* @__PURE__ */ jsx7("img", { src: att.data, alt: `attachment ${i + 1}`, className: "hsk-cb-img-thumb" }),
2174
+ /* @__PURE__ */ jsx7(
2175
+ "button",
2176
+ {
2177
+ className: "hsk-cb-img-thumb-remove",
2178
+ onClick: () => removeAttachment(i),
2179
+ "aria-label": "Remove image",
2180
+ children: "\xD7"
2181
+ }
2182
+ )
2183
+ ] }, i)) }),
2184
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-input-box", children: [
2185
+ /* @__PURE__ */ jsx7(
2186
+ "input",
2187
+ {
2188
+ ref: imageInputRef,
2189
+ type: "file",
2190
+ accept: "image/*",
2191
+ multiple: true,
2192
+ style: { display: "none" },
2193
+ onChange: (e) => handleImageFiles(e.target.files)
2209
2194
  }
2210
- }, children: "Copy" }),
2211
- /* @__PURE__ */ jsxs6("span", { style: { fontSize: 11, opacity: 0.7 }, children: [
2212
- "Disappears in ",
2213
- keyCountdown,
2214
- "s. Save it like a password \u2014 if lost, the memory it opens is lost with it."
2215
- ] })
2216
- ] })
2217
- ] }) }) })
2218
- ] }),
2219
- /* @__PURE__ */ jsx7("div", { ref: bottomRef, style: { height: 1 } })
2220
- ] }),
2221
- !replayMessages && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-input-wrap", children: [
2222
- showAtPicker && /* @__PURE__ */ jsx7(
2223
- AtPickerMenu,
2224
- {
2225
- onSelect: handleSelectExtension,
2226
- onDismiss: () => setShowAtPicker(false)
2227
- }
2228
- ),
2229
- showKikuPicker && /* @__PURE__ */ jsx7(
2230
- KikuPickerMenu,
2231
- {
2232
- sources,
2233
- referencedIds,
2234
- defaultCurrency,
2235
- onCapture: handleKikuCapture,
2236
- onCaptureAll: handleKikuCaptureAll,
2237
- onViewHistory: handleKikuViewHistory,
2238
- onDelete: handleKikuDelete,
2239
- onDismiss: () => setShowKikuPicker(false)
2240
- }
2241
- ),
2242
- attachments.length > 0 && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-img-strip", children: attachments.map((att, i) => /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-img-thumb-wrap", children: [
2243
- /* @__PURE__ */ jsx7("img", { src: att.data, alt: `attachment ${i + 1}`, className: "hsk-cb-img-thumb" }),
2244
- /* @__PURE__ */ jsx7(
2245
- "button",
2246
- {
2247
- className: "hsk-cb-img-thumb-remove",
2248
- onClick: () => removeAttachment(i),
2249
- "aria-label": "Remove image",
2250
- children: "\xD7"
2251
- }
2252
- )
2253
- ] }, i)) }),
2254
- /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-input-box", children: [
2255
- /* @__PURE__ */ jsx7(
2256
- "input",
2257
- {
2258
- ref: imageInputRef,
2259
- type: "file",
2260
- accept: "image/*",
2261
- multiple: true,
2262
- style: { display: "none" },
2263
- onChange: (e) => handleImageFiles(e.target.files)
2264
- }
2265
- ),
2266
- enableVision && /* @__PURE__ */ jsx7(
2267
- "button",
2268
- {
2269
- className: "hsk-cb-attach-btn",
2270
- onClick: () => imageInputRef.current?.click(),
2271
- disabled: loading,
2272
- "aria-label": "Attach image",
2273
- title: "Attach image",
2274
- children: /* @__PURE__ */ jsx7(PaperclipIcon, {})
2275
- }
2276
- ),
2277
- /* @__PURE__ */ jsx7(
2278
- "textarea",
2279
- {
2280
- ref: textareaRef,
2281
- className: cn("hsk-cb-textarea", classNames.input),
2282
- value: input,
2283
- onChange: handleInput,
2284
- onKeyDown: handleKeyDown,
2285
- placeholder: voiceState === "listening" ? "\u{1F399}\uFE0F Listening\u2026 tap the mic to stop" : voiceState === "processing" ? "Got it \u2014 sending\u2026" : activePlaceholder,
2286
- rows: 1,
2287
- disabled: loading,
2288
- autoFocus: true
2289
- }
2290
- ),
2291
- hasSpeechAPI && enableVoice && /* @__PURE__ */ jsxs6(
2292
- "button",
2293
- {
2294
- className: cn(
2295
- "hsk-cb-mic-btn",
2296
- voiceState === "listening" && "hsk-cb-mic-btn--listening",
2297
- voiceState === "processing" && "hsk-cb-mic-btn--processing"
2298
2195
  ),
2299
- onClick: voiceState === "idle" ? startVoice : stopVoice,
2300
- disabled: loading,
2301
- "aria-label": voiceState === "idle" ? "Start voice input" : "Stop recording",
2302
- title: voiceState === "idle" ? "Voice input" : "Stop",
2303
- children: [
2304
- voiceState === "listening" ? /* @__PURE__ */ jsx7(MicOffIcon, {}) : /* @__PURE__ */ jsx7(MicIcon2, {}),
2305
- voiceState === "listening" && /* @__PURE__ */ jsx7("span", { className: "hsk-cb-mic-pulse" })
2306
- ]
2307
- }
2308
- ),
2309
- /* @__PURE__ */ jsx7(
2310
- "button",
2311
- {
2312
- className: cn("hsk-cb-send", classNames.sendButton),
2313
- onClick: () => handleSend(),
2314
- disabled: !input.trim() && attachments.length === 0 || loading,
2315
- "aria-label": "Send message",
2316
- children: /* @__PURE__ */ jsx7(ArrowUpIcon2, {})
2317
- }
2318
- )
2319
- ] }),
2320
- /* @__PURE__ */ jsx7("div", { className: "hsk-cb-hint", children: "Akropolys AI \xB7 searches the whole catalogue in real time" })
2321
- ] })
2322
- ] })
2323
- ] })
2196
+ enableVision && /* @__PURE__ */ jsx7(
2197
+ "button",
2198
+ {
2199
+ className: "hsk-cb-attach-btn",
2200
+ onClick: () => imageInputRef.current?.click(),
2201
+ disabled: loading,
2202
+ "aria-label": "Attach image",
2203
+ title: "Attach image",
2204
+ children: /* @__PURE__ */ jsx7(PaperclipIcon, {})
2205
+ }
2206
+ ),
2207
+ /* @__PURE__ */ jsx7(
2208
+ "textarea",
2209
+ {
2210
+ ref: textareaRef,
2211
+ className: cn("hsk-cb-textarea", classNames.input),
2212
+ value: input,
2213
+ onChange: handleInput,
2214
+ onKeyDown: handleKeyDown,
2215
+ placeholder: voiceState === "listening" ? "\u{1F399}\uFE0F Listening\u2026 tap the mic to stop" : voiceState === "processing" ? "Got it \u2014 sending\u2026" : activePlaceholder,
2216
+ rows: 1,
2217
+ disabled: loading,
2218
+ autoFocus: true
2219
+ }
2220
+ ),
2221
+ hasSpeechAPI && enableVoice && /* @__PURE__ */ jsxs6(
2222
+ "button",
2223
+ {
2224
+ className: cn(
2225
+ "hsk-cb-mic-btn",
2226
+ voiceState === "listening" && "hsk-cb-mic-btn--listening",
2227
+ voiceState === "processing" && "hsk-cb-mic-btn--processing"
2228
+ ),
2229
+ onClick: voiceState === "idle" ? startVoice : stopVoice,
2230
+ disabled: loading,
2231
+ "aria-label": voiceState === "idle" ? "Start voice input" : "Stop recording",
2232
+ title: voiceState === "idle" ? "Voice input" : "Stop",
2233
+ children: [
2234
+ voiceState === "listening" ? /* @__PURE__ */ jsx7(MicOffIcon, {}) : /* @__PURE__ */ jsx7(MicIcon2, {}),
2235
+ voiceState === "listening" && /* @__PURE__ */ jsx7("span", { className: "hsk-cb-mic-pulse" })
2236
+ ]
2237
+ }
2238
+ ),
2239
+ loading || streaming ? /* @__PURE__ */ jsx7(
2240
+ "button",
2241
+ {
2242
+ className: cn("hsk-cb-send", "hsk-cb-send--stop", classNames.sendButton),
2243
+ onClick: stop,
2244
+ "aria-label": "Stop generating",
2245
+ title: "Stop generating",
2246
+ children: /* @__PURE__ */ jsx7(StopIcon, {})
2247
+ }
2248
+ ) : /* @__PURE__ */ jsx7(
2249
+ "button",
2250
+ {
2251
+ className: cn("hsk-cb-send", classNames.sendButton),
2252
+ onClick: () => handleSend(),
2253
+ disabled: !input.trim() && attachments.length === 0,
2254
+ "aria-label": "Send message",
2255
+ children: /* @__PURE__ */ jsx7(ArrowUpIcon2, {})
2256
+ }
2257
+ )
2258
+ ] }),
2259
+ /* @__PURE__ */ jsx7("div", { className: "hsk-cb-hint", children: "Akropolys AI \xB7 searches the whole catalogue in real time" })
2260
+ ] })
2261
+ ] })
2262
+ ]
2263
+ }
2264
+ )
2324
2265
  }
2325
2266
  );
2326
2267
  }