@huskel/sdk 0.4.3 → 0.4.6

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
@@ -319,6 +319,9 @@ var _HuskelClient = class _HuskelClient {
319
319
  } catch (e) {
320
320
  }
321
321
  }
322
+ reRegister() {
323
+ instance = this;
324
+ }
322
325
  setShopperId(id) {
323
326
  this.shopperId = id;
324
327
  }
@@ -452,11 +455,17 @@ function HuskelProvider({ siteId, apiUrl, apiToken, shopperId, children }) {
452
455
  const clientRef = useRef2(null);
453
456
  if (!clientRef.current) {
454
457
  clientRef.current = new HuskelClient({ siteId, apiUrl, apiToken, shopperId });
458
+ } else {
459
+ clientRef.current.reRegister();
455
460
  }
456
461
  useEffect(() => {
457
462
  var _a;
458
463
  (_a = clientRef.current) == null ? void 0 : _a.setShopperId(shopperId);
459
464
  }, [shopperId]);
465
+ useEffect(() => {
466
+ var _a;
467
+ (_a = clientRef.current) == null ? void 0 : _a.reRegister();
468
+ }, []);
460
469
  useEffect(() => {
461
470
  return () => {
462
471
  var _a;
@@ -488,6 +497,7 @@ function useSearch() {
488
497
  return;
489
498
  }
490
499
  const gen = ++genRef.current;
500
+ setLoading(true);
491
501
  setError(null);
492
502
  try {
493
503
  const res = await client.api.searchAutocomplete(query, limit);
@@ -700,7 +710,7 @@ function cn(...inputs) {
700
710
  }
701
711
 
702
712
  // src/components/SearchBar.tsx
703
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
713
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
704
714
  var SearchIcon = () => /* @__PURE__ */ jsxs("svg", { width: "15", height: "15", viewBox: "0 0 20 20", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", children: [
705
715
  /* @__PURE__ */ jsx2("circle", { cx: "8.5", cy: "8.5", r: "5.5" }),
706
716
  /* @__PURE__ */ jsx2("line", { x1: "13", y1: "13", x2: "18", y2: "18" })
@@ -708,7 +718,7 @@ var SearchIcon = () => /* @__PURE__ */ jsxs("svg", { width: "15", height: "15",
708
718
  function SearchBar({
709
719
  placeholder = "Search products\u2026",
710
720
  limit = 10,
711
- debounceMs = 80,
721
+ debounceMs = 300,
712
722
  onSelect,
713
723
  className,
714
724
  inputClassName,
@@ -719,18 +729,28 @@ function SearchBar({
719
729
  }) {
720
730
  const [query, setQuery] = useState5("");
721
731
  const [open, setOpen] = useState5(false);
732
+ const [isDebouncing, setIsDebouncing] = useState5(false);
722
733
  const { results, loading, search, clear } = useSearch();
734
+ const client = useHuskelContext();
723
735
  const timer = useRef6();
724
736
  const wrap = useRef6(null);
737
+ const ignoreNextQueryChange = useRef6(false);
725
738
  useEffect4(() => {
739
+ if (ignoreNextQueryChange.current) {
740
+ ignoreNextQueryChange.current = false;
741
+ return;
742
+ }
726
743
  clearTimeout(timer.current);
727
744
  if (!query.trim()) {
728
745
  clear();
729
746
  setOpen(false);
747
+ setIsDebouncing(false);
730
748
  return;
731
749
  }
732
750
  setOpen(true);
751
+ setIsDebouncing(true);
733
752
  timer.current = setTimeout(() => {
753
+ setIsDebouncing(false);
734
754
  search(query, limit);
735
755
  }, debounceMs);
736
756
  return () => clearTimeout(timer.current);
@@ -743,10 +763,23 @@ function SearchBar({
743
763
  return () => document.removeEventListener("mousedown", h);
744
764
  }, []);
745
765
  const handleSelect = (r) => {
766
+ if (query.trim()) {
767
+ client.api.searchVector(query, 1).catch(() => {
768
+ });
769
+ }
770
+ ignoreNextQueryChange.current = true;
746
771
  setOpen(false);
747
772
  setQuery(r.product.name);
748
773
  onSelect == null ? void 0 : onSelect(r);
749
774
  };
775
+ const handleCommitSearch = () => {
776
+ if (!query.trim()) return;
777
+ client.api.searchVector(query, 1).catch(() => {
778
+ });
779
+ if (results.length > 0) {
780
+ handleSelect(results[0]);
781
+ }
782
+ };
750
783
  const showDrop = open && query.trim().length > 0;
751
784
  const customStyles = __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, (theme == null ? void 0 : theme.primaryColor) && { "--hsk-primary": theme.primaryColor }), (theme == null ? void 0 : theme.backgroundColor) && { "--hsk-bg": theme.backgroundColor }), (theme == null ? void 0 : theme.textColor) && { "--hsk-text": theme.textColor }), (theme == null ? void 0 : theme.fontFamily) && { "--hsk-font": theme.fontFamily }), (theme == null ? void 0 : theme.borderRadius) && { "--hsk-border-radius": theme.borderRadius });
752
785
  return /* @__PURE__ */ jsxs("div", { className: cn("hsk-sb-wrap", classNames.root, className), ref: wrap, style: customStyles, children: [
@@ -760,45 +793,67 @@ function SearchBar({
760
793
  placeholder,
761
794
  onChange: (e) => setQuery(e.target.value),
762
795
  onFocus: () => results.length > 0 && query.trim() && setOpen(true),
796
+ onKeyDown: (e) => {
797
+ if (e.key === "Enter") {
798
+ handleCommitSearch();
799
+ }
800
+ },
763
801
  autoComplete: "off",
764
802
  spellCheck: false
765
803
  }
766
804
  ),
767
805
  showDrop && /* @__PURE__ */ jsxs("div", { className: cn("hsk-sb-drop", classNames.dropdown, dropdownClassName), style: { position: "absolute" }, children: [
768
- loading && /* @__PURE__ */ jsx2("div", { className: "hsk-sb-loading-bar" }),
769
- results.length === 0 && !loading && /* @__PURE__ */ jsxs("div", { className: "hsk-sb-empty", children: [
770
- "No results for \u201C",
771
- query,
772
- "\u201D"
773
- ] }),
774
- results.map((r, i) => {
775
- var _a;
776
- return renderResult ? /* @__PURE__ */ jsx2(
777
- "div",
778
- {
779
- onClick: () => handleSelect(r),
780
- className: "hsk-sb-fade",
781
- style: { animationDelay: `${i * 18}ms` },
782
- children: renderResult(r)
783
- },
784
- r.id
785
- ) : /* @__PURE__ */ jsxs(
786
- "div",
787
- {
788
- className: cn("hsk-sb-row hsk-sb-fade", classNames.row),
789
- style: { animationDelay: `${i * 18}ms` },
790
- onClick: () => handleSelect(r),
791
- children: [
792
- /* @__PURE__ */ jsx2("span", { className: "hsk-sb-row-icon", children: /* @__PURE__ */ jsx2(SearchIcon, {}) }),
793
- /* @__PURE__ */ jsxs("div", { className: "hsk-sb-row-body", children: [
794
- /* @__PURE__ */ jsx2("div", { className: "hsk-sb-row-title", children: r.product.name }),
795
- (r.product.category || r.product.brand) && /* @__PURE__ */ jsx2("div", { className: "hsk-sb-row-sub", children: (_a = r.product.category) != null ? _a : r.product.brand })
796
- ] })
797
- ]
798
- },
799
- r.id
800
- );
801
- })
806
+ (loading || isDebouncing) && /* @__PURE__ */ jsx2("div", { className: "hsk-sb-loading-bar" }),
807
+ (loading || isDebouncing) && results.length === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
808
+ /* @__PURE__ */ jsxs("div", { className: "hsk-sb-skeleton-row", children: [
809
+ /* @__PURE__ */ jsx2("span", { className: "hsk-sb-skeleton-icon" }),
810
+ /* @__PURE__ */ jsxs("div", { className: "hsk-sb-row-body", children: [
811
+ /* @__PURE__ */ jsx2("div", { className: "hsk-sb-skeleton-text1" }),
812
+ /* @__PURE__ */ jsx2("div", { className: "hsk-sb-skeleton-text2" })
813
+ ] })
814
+ ] }),
815
+ /* @__PURE__ */ jsxs("div", { className: "hsk-sb-skeleton-row", children: [
816
+ /* @__PURE__ */ jsx2("span", { className: "hsk-sb-skeleton-icon" }),
817
+ /* @__PURE__ */ jsxs("div", { className: "hsk-sb-row-body", children: [
818
+ /* @__PURE__ */ jsx2("div", { className: "hsk-sb-skeleton-text1", style: { width: "45%" } }),
819
+ /* @__PURE__ */ jsx2("div", { className: "hsk-sb-skeleton-text2", style: { width: "25%" } })
820
+ ] })
821
+ ] })
822
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
823
+ results.length === 0 && !loading && !isDebouncing && /* @__PURE__ */ jsxs("div", { className: "hsk-sb-empty", children: [
824
+ "No results for \u201C",
825
+ query,
826
+ "\u201D"
827
+ ] }),
828
+ results.map((r, i) => {
829
+ var _a;
830
+ return renderResult ? /* @__PURE__ */ jsx2(
831
+ "div",
832
+ {
833
+ onClick: () => handleSelect(r),
834
+ className: "hsk-sb-fade",
835
+ style: { animationDelay: `${i * 18}ms` },
836
+ children: renderResult(r)
837
+ },
838
+ r.id
839
+ ) : /* @__PURE__ */ jsxs(
840
+ "div",
841
+ {
842
+ className: cn("hsk-sb-row hsk-sb-fade", classNames.row),
843
+ style: { animationDelay: `${i * 18}ms` },
844
+ onClick: () => handleSelect(r),
845
+ children: [
846
+ /* @__PURE__ */ jsx2("span", { className: "hsk-sb-row-icon", children: /* @__PURE__ */ jsx2(SearchIcon, {}) }),
847
+ /* @__PURE__ */ jsxs("div", { className: "hsk-sb-row-body", children: [
848
+ /* @__PURE__ */ jsx2("div", { className: "hsk-sb-row-title", children: r.product.name }),
849
+ (r.product.category || r.product.brand) && /* @__PURE__ */ jsx2("div", { className: "hsk-sb-row-sub", children: (_a = r.product.category) != null ? _a : r.product.brand })
850
+ ] })
851
+ ]
852
+ },
853
+ r.id
854
+ );
855
+ })
856
+ ] })
802
857
  ] })
803
858
  ] });
804
859
  }
@@ -808,7 +863,7 @@ import { useState as useState6, useEffect as useEffect5, useRef as useRef7 } fro
808
863
  import { createPortal } from "react-dom";
809
864
 
810
865
  // src/utils/markdown.tsx
811
- import { Fragment, jsx as jsx3 } from "react/jsx-runtime";
866
+ import { Fragment as Fragment2, jsx as jsx3 } from "react/jsx-runtime";
812
867
  var parseInline = (text, keyPrefix) => {
813
868
  const tokenRegex = /(\[[^\]]+\]\([^)]+\)|\*\*[^*]+\*\*|`[^`]+`)/g;
814
869
  const parts = text.split(tokenRegex);
@@ -889,11 +944,11 @@ function renderMarkdown(content) {
889
944
  );
890
945
  i++;
891
946
  }
892
- return /* @__PURE__ */ jsx3(Fragment, { children: elements });
947
+ return /* @__PURE__ */ jsx3(Fragment2, { children: elements });
893
948
  }
894
949
 
895
950
  // src/components/Sparkle.tsx
896
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
951
+ import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
897
952
  var SparkleIcon = ({ className }) => /* @__PURE__ */ jsx4("svg", { className, width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx4("path", { d: "m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z" }) });
898
953
  var CloseIcon = () => /* @__PURE__ */ jsxs2("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
899
954
  /* @__PURE__ */ jsx4("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
@@ -1201,7 +1256,7 @@ function Sparkle({
1201
1256
  setMounted(true);
1202
1257
  }, []);
1203
1258
  const customStyles = __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, (theme == null ? void 0 : theme.primaryColor) && { "--hsk-primary": theme.primaryColor }), (theme == null ? void 0 : theme.backgroundColor) && { "--hsk-bg": theme.backgroundColor }), (theme == null ? void 0 : theme.textColor) && { "--hsk-text": theme.textColor }), (theme == null ? void 0 : theme.fontFamily) && { "--hsk-font": theme.fontFamily }), (theme == null ? void 0 : theme.borderRadius) && { "--hsk-border-radius": theme.borderRadius });
1204
- return /* @__PURE__ */ jsxs2(Fragment2, { children: [
1259
+ return /* @__PURE__ */ jsxs2(Fragment3, { children: [
1205
1260
  /* @__PURE__ */ jsx4(
1206
1261
  "button",
1207
1262
  {
@@ -1370,7 +1425,7 @@ function ChatWidget({
1370
1425
  // src/components/AIChatButton.tsx
1371
1426
  import { useState as useState8, useEffect as useEffect7, useRef as useRef9, useCallback as useCallback5 } from "react";
1372
1427
  import { createPortal as createPortal2 } from "react-dom";
1373
- import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1428
+ import { Fragment as Fragment4, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
1374
1429
  var SparkleIcon3 = ({ className }) => /* @__PURE__ */ jsx6("svg", { className, width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx6("path", { d: "m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z" }) });
1375
1430
  var ArrowUpIcon3 = () => /* @__PURE__ */ jsxs4("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1376
1431
  /* @__PURE__ */ jsx6("path", { d: "m5 12 7-7 7 7" }),
@@ -1436,7 +1491,7 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource }) {
1436
1491
  si
1437
1492
  );
1438
1493
  }) }),
1439
- showNext && /* @__PURE__ */ jsxs4(Fragment3, { children: [
1494
+ showNext && /* @__PURE__ */ jsxs4(Fragment4, { children: [
1440
1495
  /* @__PURE__ */ jsx6(
1441
1496
  "div",
1442
1497
  {
@@ -1640,7 +1695,7 @@ function AIChatButton({
1640
1695
  setMounted(true);
1641
1696
  }, []);
1642
1697
  const customStyles = __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, (theme == null ? void 0 : theme.primaryColor) && { "--hsk-primary": theme.primaryColor }), (theme == null ? void 0 : theme.backgroundColor) && { "--hsk-bg": theme.backgroundColor }), (theme == null ? void 0 : theme.textColor) && { "--hsk-text": theme.textColor }), (theme == null ? void 0 : theme.fontFamily) && { "--hsk-font": theme.fontFamily }), (theme == null ? void 0 : theme.borderRadius) && { "--hsk-border-radius": theme.borderRadius });
1643
- return /* @__PURE__ */ jsxs4(Fragment3, { children: [
1698
+ return /* @__PURE__ */ jsxs4(Fragment4, { children: [
1644
1699
  /* @__PURE__ */ jsxs4(
1645
1700
  "button",
1646
1701
  {
@@ -1690,7 +1745,7 @@ import { createPortal as createPortal4 } from "react-dom";
1690
1745
  // src/components/CheckoutModal.tsx
1691
1746
  import { useState as useState9, useEffect as useEffect8 } from "react";
1692
1747
  import { createPortal as createPortal3 } from "react-dom";
1693
- import { Fragment as Fragment4, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1748
+ import { Fragment as Fragment5, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1694
1749
  function CheckoutModal({
1695
1750
  onClose,
1696
1751
  theme,
@@ -1756,7 +1811,7 @@ function CheckoutModal({
1756
1811
  ] }) : /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-split", children: [
1757
1812
  /* @__PURE__ */ jsxs5("div", { className: "hsk-checkout-summary", children: [
1758
1813
  /* @__PURE__ */ jsx8("h3", { children: "Order Summary" }),
1759
- cartLoading || !cart ? /* @__PURE__ */ jsx8("p", { className: "hsk-cart-loading", children: "Loading order..." }) : /* @__PURE__ */ jsxs5(Fragment4, { children: [
1814
+ cartLoading || !cart ? /* @__PURE__ */ jsx8("p", { className: "hsk-cart-loading", children: "Loading order..." }) : /* @__PURE__ */ jsxs5(Fragment5, { children: [
1760
1815
  /* @__PURE__ */ jsx8("ul", { className: "hsk-checkout-items", children: cart.items.map((item) => /* @__PURE__ */ jsxs5("li", { children: [
1761
1816
  /* @__PURE__ */ jsxs5("span", { children: [
1762
1817
  item.quantity,
@@ -1799,7 +1854,7 @@ function CheckoutModal({
1799
1854
  }
1800
1855
 
1801
1856
  // src/components/CartDrawer.tsx
1802
- import { Fragment as Fragment5, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1857
+ import { Fragment as Fragment6, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1803
1858
  function CartDrawer({
1804
1859
  trigger,
1805
1860
  className,
@@ -1838,7 +1893,7 @@ function CartDrawer({
1838
1893
  const isStringTheme = typeof theme === "string";
1839
1894
  const hskThemeAttr = isStringTheme ? theme : void 0;
1840
1895
  const customStyles = !isStringTheme && theme ? __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({}, (theme == null ? void 0 : theme.primaryColor) && { "--hsk-primary": theme.primaryColor, "--hsk-primary-color": theme.primaryColor }), (theme == null ? void 0 : theme.backgroundColor) && { "--hsk-bg": theme.backgroundColor }), (theme == null ? void 0 : theme.textColor) && { "--hsk-text": theme.textColor }), (theme == null ? void 0 : theme.fontFamily) && { "--hsk-font": theme.fontFamily }), (theme == null ? void 0 : theme.borderRadius) && { "--hsk-border-radius": theme.borderRadius }) : void 0;
1841
- return /* @__PURE__ */ jsxs6(Fragment5, { children: [
1896
+ return /* @__PURE__ */ jsxs6(Fragment6, { children: [
1842
1897
  /* @__PURE__ */ jsx9("div", { onClick: () => setOpen(true), style: { display: "inline-block" }, children: trigger || /* @__PURE__ */ jsxs6(
1843
1898
  "button",
1844
1899
  {