@akropolys/kiku 1.0.2 → 1.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.js CHANGED
@@ -1767,6 +1767,9 @@ function SparkleModal({
1767
1767
  const { results, loading: searchLoading, search } = (0, import_sdk6.useSearch)();
1768
1768
  const { messages, sources, loading: chatLoading, error: chatError, send } = (0, import_sdk6.useKiku)();
1769
1769
  const [chatInput, setChatInput] = (0, import_react4.useState)("");
1770
+ const [isMobile, setIsMobile] = (0, import_react4.useState)(false);
1771
+ const [showSpecs, setShowSpecs] = (0, import_react4.useState)(false);
1772
+ const [collapseSimilar, setCollapseSimilar] = (0, import_react4.useState)(false);
1770
1773
  const chatBottomRef = (0, import_react4.useRef)(null);
1771
1774
  const chatTextareaRef = (0, import_react4.useRef)(null);
1772
1775
  (0, import_react4.useEffect)(() => {
@@ -1779,6 +1782,14 @@ function SparkleModal({
1779
1782
  }
1780
1783
  search(productName, limit);
1781
1784
  }, [productName, initialProduct, fetchedProduct, client, limit, search]);
1785
+ (0, import_react4.useEffect)(() => {
1786
+ const handleResize = () => setIsMobile(window.innerWidth <= 768);
1787
+ handleResize();
1788
+ if (typeof window !== "undefined") {
1789
+ window.addEventListener("resize", handleResize);
1790
+ return () => window.removeEventListener("resize", handleResize);
1791
+ }
1792
+ }, []);
1782
1793
  (0, import_react4.useEffect)(() => {
1783
1794
  if (results.length > 0) onResult?.(results);
1784
1795
  }, [results, onResult]);
@@ -1842,6 +1853,170 @@ Question: ${q}`;
1842
1853
  content: `Hi! I can help you with **${displayProduct.name}**. Ask me about its specifications, features, compare it with other options, or find alternatives!`
1843
1854
  }
1844
1855
  ] : messages;
1856
+ if (isMobile) {
1857
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1858
+ "div",
1859
+ {
1860
+ className: cn("hsk-sp-backdrop hsk-sp-mobile-view", classNames.backdrop),
1861
+ onClick: onClose,
1862
+ style: {
1863
+ backdropFilter: `blur(${blurVal})`,
1864
+ WebkitBackdropFilter: `blur(${blurVal})`,
1865
+ background: bg ?? void 0,
1866
+ ...customStyles
1867
+ },
1868
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: cn("hsk-sp-card hsk-sp-fullscreen hsk-sp-mobile-card", classNames.card), onClick: (e) => e.stopPropagation(), children: [
1869
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-header", children: [
1870
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "hsk-sp-header-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SparkleIcon3, {}) }),
1871
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-header-body", children: [
1872
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-header-title-row", children: [
1873
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-header-title", children: displayProduct?.name || productName }),
1874
+ displayProduct && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1875
+ "button",
1876
+ {
1877
+ type: "button",
1878
+ className: "hsk-sp-header-specs-btn",
1879
+ onClick: () => setShowSpecs(true),
1880
+ children: "Specs"
1881
+ }
1882
+ )
1883
+ ] }),
1884
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-header-sub", children: "Akropolys AI Shopping Assistant" })
1885
+ ] }),
1886
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: "hsk-sp-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CloseIcon2, {}) })
1887
+ ] }),
1888
+ searchLoading && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-bar" }),
1889
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-chat-container", children: [
1890
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-cb-msgs", children: [
1891
+ displayMessages.map((msg, idx) => {
1892
+ const isUser = msg.role === "user";
1893
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-msg-group", children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-user-msg", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-user-bubble", children: msg.content }) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
1894
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SparkleIcon3, {}) }),
1895
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-cb-ai-body", children: [
1896
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-ai-text", children: renderMarkdown(msg.content) }),
1897
+ idx === 0 && displayProduct && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-attachment-deck", children: [
1898
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-main-card", children: [
1899
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-mobile-main-card-img", children: displayProduct.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: displayProduct.images[0], alt: displayProduct.name }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u{1F6CD}" }) }),
1900
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-main-card-info", children: [
1901
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-mobile-main-card-brand", children: displayProduct.brand || displayProduct.category || "Product" }),
1902
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-mobile-main-card-name", children: displayProduct.name }),
1903
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-main-card-price", children: [
1904
+ displayProduct.currency ?? "KES",
1905
+ " ",
1906
+ parseFloat(displayProduct.price?.replace(/[^0-9.]/g, "") || "0").toLocaleString()
1907
+ ] })
1908
+ ] }),
1909
+ (displayProduct.specs && Object.keys(displayProduct.specs).length > 0 || displayProduct.description) && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1910
+ "button",
1911
+ {
1912
+ type: "button",
1913
+ className: "hsk-sp-mobile-main-card-specs-btn",
1914
+ onClick: () => setShowSpecs(true),
1915
+ children: "Specs"
1916
+ }
1917
+ )
1918
+ ] }),
1919
+ (() => {
1920
+ const similarProducts = results.filter(
1921
+ (r) => {
1922
+ const isSameName = r.product.name.toLowerCase() === displayProduct?.name?.toLowerCase();
1923
+ const isSameSlug = r.product.slug && displayProduct?.slug && r.product.slug.toLowerCase() === displayProduct.slug.toLowerCase();
1924
+ return !isSameName && !isSameSlug;
1925
+ }
1926
+ );
1927
+ if (similarProducts.length === 0) return null;
1928
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-similar-carousel-inline", children: [
1929
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-title", children: "Similar Products" }),
1930
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-list", children: similarProducts.map((r) => {
1931
+ const price = parseFloat(r.product.price?.replace(/[^0-9.]/g, "") || "0");
1932
+ const currency = r.product.currency ?? "KES";
1933
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1934
+ "div",
1935
+ {
1936
+ className: "hsk-sp-mobile-similar-carousel-item",
1937
+ onClick: () => handleNav(r),
1938
+ children: [
1939
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-img", children: r.product.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: r.product.images[0], alt: r.product.name }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "\u{1F6CD}" }) }),
1940
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-similar-carousel-meta", children: [
1941
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-mobile-similar-carousel-name", title: r.product.name, children: r.product.name }),
1942
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-similar-carousel-price", children: [
1943
+ currency,
1944
+ " ",
1945
+ price.toLocaleString()
1946
+ ] })
1947
+ ] })
1948
+ ]
1949
+ },
1950
+ r.id
1951
+ );
1952
+ }) })
1953
+ ] });
1954
+ })()
1955
+ ] })
1956
+ ] })
1957
+ ] }) }, idx);
1958
+ }),
1959
+ chatLoading && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-cb-typing-row", children: [
1960
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SparkleIcon3, {}) }),
1961
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-cb-typing", children: [
1962
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-dot" }),
1963
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-dot" }),
1964
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-dot" })
1965
+ ] })
1966
+ ] }),
1967
+ chatError && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError2(chatError) }),
1968
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: chatBottomRef, style: { height: 1 } })
1969
+ ] }),
1970
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-cb-input-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-cb-input-box", children: [
1971
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1972
+ "textarea",
1973
+ {
1974
+ ref: chatTextareaRef,
1975
+ className: "hsk-cb-textarea",
1976
+ value: chatInput,
1977
+ onChange: handleInput,
1978
+ onKeyDown: handleKeyDown,
1979
+ placeholder: "Ask about this product, specs, or comparison...",
1980
+ rows: 1,
1981
+ disabled: chatLoading
1982
+ }
1983
+ ),
1984
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1985
+ "button",
1986
+ {
1987
+ className: "hsk-cb-send",
1988
+ onClick: () => handleSend(),
1989
+ disabled: !chatInput.trim() || chatLoading,
1990
+ "aria-label": "Send message",
1991
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ArrowUpIcon3, {})
1992
+ }
1993
+ )
1994
+ ] }) })
1995
+ ] }),
1996
+ showSpecs && displayProduct && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-mobile-specs-overlay", onClick: () => setShowSpecs(false), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-specs-drawer", onClick: (e) => e.stopPropagation(), children: [
1997
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-specs-header", children: [
1998
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h3", { children: "Specifications" }),
1999
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", onClick: () => setShowSpecs(false), children: "Close" })
2000
+ ] }),
2001
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-specs-body", children: [
2002
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h4", { className: "hsk-sp-mobile-specs-title", children: displayProduct.name }),
2003
+ displayProduct.description && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-specs-desc", children: [
2004
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h5", { children: "Description" }),
2005
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: displayProduct.description })
2006
+ ] }),
2007
+ displayProduct.specs && Object.keys(displayProduct.specs).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-specs-list", children: [
2008
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h5", { children: "Details" }),
2009
+ Object.entries(displayProduct.specs).map(([key, val]) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-mobile-spec-row", children: [
2010
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "hsk-sp-mobile-spec-label", children: key }),
2011
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "hsk-sp-mobile-spec-value", children: val })
2012
+ ] }, key))
2013
+ ] })
2014
+ ] })
2015
+ ] }) })
2016
+ ] })
2017
+ }
2018
+ );
2019
+ }
1845
2020
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1846
2021
  "div",
1847
2022
  {
@@ -1929,7 +2104,8 @@ Question: ${q}`;
1929
2104
  "div",
1930
2105
  {
1931
2106
  className: cn("hsk-sp-item", classNames.item),
1932
- style: { animationDelay: `${i * 55}ms` },
2107
+ style: { animationDelay: `${i * 55}ms`, cursor: "pointer" },
2108
+ onClick: () => handleNav(r),
1933
2109
  children: [
1934
2110
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "hsk-sp-img-wrap", children: r.product.images?.[0] ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: r.product.images[0], alt: r.product.name }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "hsk-sp-img-placeholder", children: "\u{1F6CD}" }) }),
1935
2111
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "hsk-sp-item-body", children: [
@@ -1945,7 +2121,10 @@ Question: ${q}`;
1945
2121
  "button",
1946
2122
  {
1947
2123
  className: "hsk-sp-action hsk-sp-action-primary",
1948
- onClick: () => handleNav(r),
2124
+ onClick: (e) => {
2125
+ e.stopPropagation();
2126
+ handleNav(r);
2127
+ },
1949
2128
  children: "View"
1950
2129
  }
1951
2130
  ) })