@websolutespa/bom-mixer-hooks 0.2.2 → 1.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @websolutespa/bom-mixer-hooks
2
2
 
3
+ ## 1.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Modified: useHttp, useApi.
8
+
9
+ ## 1.0.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Added: useScrolled.
14
+
3
15
  ## 0.2.2
4
16
 
5
17
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,24 +1,26 @@
1
1
  import * as React$1 from 'react';
2
2
  import React__default, { RefObject, Dispatch, SetStateAction, MutableRefObject, ComponentProps, useEffect } from 'react';
3
- import { FetchRequestOptions, ISchema, IEquatable, ILayout, IPage } from '@websolutespa/bom-core';
3
+ import { ApiRequestOptions } from '@websolutespa/bom-mixer-store';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
5
  import * as zustand_middleware from 'zustand/middleware';
5
6
  import { StateStorage } from 'zustand/middleware';
6
7
  import * as zustand from 'zustand';
8
+ import { ISchema, IEquatable, ILayout, IPage } from '@websolutespa/bom-core';
7
9
  import { ICartItem, ICartAddItem, IAddressOptions, ICheckoutPartial, IFeatureType, IUser } from '@websolutespa/bom-mixer-models';
8
10
  import { NextRouter } from 'next/router';
9
11
 
10
- declare function useApiFetch<T = any>(pathname: string, options?: FetchRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
11
- declare function useApiGet<T = any>(pathname: string, options?: FetchRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
12
- declare function useApiPost<T = any>(pathname: string, payload: unknown, options?: FetchRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
13
- declare function useApiPut<T = any>(pathname: string, payload: unknown, options?: FetchRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
14
- declare function useApiPatch<T = any>(pathname: string, payload: unknown, options?: FetchRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
15
- declare function useApiDelete<T = any>(pathname: string, options?: FetchRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
12
+ declare function useApiFetch<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
13
+ declare function useApiGet<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
14
+ declare function useApiPost<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
15
+ declare function useApiPut<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
16
+ declare function useApiPatch<T = unknown>(pathname: string, payload: unknown, options?: ApiRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
17
+ declare function useApiDelete<T = unknown>(pathname: string, options?: ApiRequestOptions): [T | undefined, boolean, any, React$1.Dispatch<any>];
16
18
  type Api = {
17
- get: <T = any>(pathname: string, options?: FetchRequestOptions) => Promise<T>;
18
- post: <T = any>(pathname: string, payload?: unknown, options?: FetchRequestOptions) => Promise<T>;
19
- put: <T = any>(pathname: string, payload?: unknown, options?: FetchRequestOptions) => Promise<T>;
20
- patch: <T = any>(pathname: string, payload?: unknown, options?: FetchRequestOptions) => Promise<T>;
21
- delete: <T = any>(pathname: string, options?: FetchRequestOptions) => Promise<T>;
19
+ get: <T = unknown>(pathname: string, options?: ApiRequestOptions) => Promise<T>;
20
+ post: <T = unknown>(pathname: string, payload?: unknown, options?: ApiRequestOptions) => Promise<T>;
21
+ put: <T = unknown>(pathname: string, payload?: unknown, options?: ApiRequestOptions) => Promise<T>;
22
+ patch: <T = unknown>(pathname: string, payload?: unknown, options?: ApiRequestOptions) => Promise<T>;
23
+ delete: <T = unknown>(pathname: string, options?: ApiRequestOptions) => Promise<T>;
22
24
  };
23
25
  declare function useApi(): Api;
24
26
 
@@ -73,8 +75,8 @@ type CartProviderProps = React.PropsWithChildren<{
73
75
  items?: ICartItem[];
74
76
  storage?: StateStorage;
75
77
  }>;
76
- declare function CartProvider({ children, ...props }: CartProviderProps): JSX.Element;
77
- declare function useCart<T>(selector: (state: CartState) => T, equalityFn?: (left: T, right: T) => boolean): T;
78
+ declare function CartProvider({ children, ...props }: CartProviderProps): react_jsx_runtime.JSX.Element;
79
+ declare function useCart<T>(selector: (state: CartState) => T): T;
78
80
 
79
81
  type CheckoutProps = {
80
82
  hydrated: boolean;
@@ -103,8 +105,8 @@ type CheckoutProviderProps = React.PropsWithChildren<{
103
105
  checkout?: ICheckoutPartial;
104
106
  storage?: StateStorage;
105
107
  }>;
106
- declare function CheckoutProvider({ children, ...props }: CheckoutProviderProps): JSX.Element;
107
- declare function useCheckout<T>(selector: (state: CheckoutState) => T, equalityFn?: (left: T, right: T) => boolean): T;
108
+ declare function CheckoutProvider({ children, ...props }: CheckoutProviderProps): react_jsx_runtime.JSX.Element;
109
+ declare function useCheckout<T>(selector: (state: CheckoutState) => T): T;
108
110
 
109
111
  declare function useClickAnyWhere(handler: (event: MouseEvent) => void): void;
110
112
 
@@ -375,7 +377,7 @@ type ILabelContext = (key: string, params?: {
375
377
  declare const useLabel: () => ILabelContext;
376
378
  declare function LabelProvider({ children }: {
377
379
  children?: React__default.ReactNode;
378
- }): JSX.Element;
380
+ }): react_jsx_runtime.JSX.Element;
379
381
  declare function parseParams(label: string, params: {
380
382
  [key: string]: any;
381
383
  }): string;
@@ -385,7 +387,7 @@ declare const useLayout: () => ILayout;
385
387
  declare function LayoutProvider({ children, layout }: {
386
388
  children?: React__default.ReactNode;
387
389
  layout: ILayout;
388
- }): JSX.Element;
390
+ }): react_jsx_runtime.JSX.Element;
389
391
 
390
392
  declare function useModal(): [modal: UIValue, open: (value?: string) => void, close: () => void];
391
393
 
@@ -398,7 +400,7 @@ declare const usePage: () => NonNullable<IPage>;
398
400
  declare function PageProvider({ children, page }: {
399
401
  children?: React__default.ReactNode;
400
402
  page: IPage;
401
- }): JSX.Element;
403
+ }): react_jsx_runtime.JSX.Element;
402
404
 
403
405
  type IPaginationInfo<T> = {
404
406
  items: T[];
@@ -436,6 +438,13 @@ declare function getRealSize(element: HTMLElement | null): SizeType;
436
438
 
437
439
  declare function useResize(callback: () => unknown, immediate?: boolean): void;
438
440
 
441
+ type SSRState = {
442
+ isBrowser: boolean;
443
+ isServer: boolean;
444
+ };
445
+ declare const detectIsBrowser: () => boolean;
446
+ declare function useSSR(): SSRState;
447
+
439
448
  type Scroll = {
440
449
  left: number;
441
450
  top: number;
@@ -447,6 +456,8 @@ declare function scrollToSelector(selector?: string, offset?: number): void;
447
456
  declare function scrollToRelativeY(y?: number, offset?: number): void;
448
457
  declare function scrollToY(y?: number): void;
449
458
 
459
+ declare function useScrolled(callback?: (top: number, left: number) => boolean): boolean;
460
+
450
461
  declare const isBrowser: boolean;
451
462
  declare function getSearchParams(url: string, key?: string): IParams | string | null;
452
463
  declare function updateSearchParams(currentPath: string, params: IParams): {
@@ -504,13 +515,6 @@ declare function useSorting<T>(items_: T[], callback_: (items: T[], sort?: IEqua
504
515
  setSort: (sort?: IEquatable) => void;
505
516
  };
506
517
 
507
- type SSRState = {
508
- isBrowser: boolean;
509
- isServer: boolean;
510
- };
511
- declare const detectIsBrowser: () => boolean;
512
- declare function useSSR(): SSRState;
513
-
514
518
  declare function useSwiperIndex(): [number, (index: number) => void];
515
519
 
516
520
  /**
@@ -548,4 +552,4 @@ type WindowSize = {
548
552
  };
549
553
  declare function useWindowSize(): WindowSize;
550
554
 
551
- export { BodyScrollOptions, CartContext, CartProvider, CheckoutContext, CheckoutProvider, ClickOutGetContainer, CurrentStateType, ElementStackItem, Filter, FilterMode, FilterParams, FilterValues, GeoLocationSensorState, IFilter, IFilterOption, IGeolocationPositionError, ILabelContext, ILayoutContext, IPageContext, IPaginationInfo, IParams, IParamsEncoded, IUseSearchParamsEncodedResult, IUseSearchParamsResult, IUseSearchParamsValueResult, KeyCode, KeyMod, KeyboardOptions, KeyboardResult, LabelProvider, LayoutProvider, PageProvider, SSRState, SizeResult, SizeType, Sorting, UIReducer, UIValue, UseFiltersResultType, UseKeyboard, UseKeyboardHandler, createElementWithId, createGenericContext, decode, detectIsBrowser, filtersToParams, getCurrentPosition, getFilteredItems, getFilters, getOwnerPaddingRight, getOwnerScrollbarWidth, getPagedItems, getRealSize, getSearchParams, getSearchParamsEncoded, getUID, hasGeolocation, isBrowser, parseParams, pushSearchParams, pushSearchParamsEncoded, replaceSearchParams, replaceSearchParamsEncoded, replaceSearchParamsEncodedSilently, replaceSearchParamsSilently, scrollToRelativeY, scrollToSelector, scrollToY, setFilters, updateSearchParams, updateSearchParamsEncoded, useApi, useApiDelete, useApiFetch, useApiGet, useApiPatch, useApiPost, useApiPut, useBodyScroll, useBreakpoint, useCart, useCheckout, useClickAnyWhere, useClickOut, useCurrency, useCurrentState, useDateTimeFormat, useDebounce, useDebounceCallback, useDebugChangedProps, useDomObserver, useDrawer, useElementSize, useEventListener, useFilters, useGeolocation, useIdle, useInfiniteLoader, useIsomorphicLayoutEffect, useKeyboard, useLabel, useLayout, useModal, useMounted, useNumber, usePage, usePagination, usePortal, usePrevious, useRealSize, useResize, useSSR, useScroll, useScrollTo, useSearchParams, useSearchParamsEncoded, useSearchParamsValue, useSorting, useSwiperIndex, useSyncedRef, useUI, useUnit, useUnmountEffect, useUser, useWindowSize };
555
+ export { BodyScrollOptions, CartContext, CartProvider, CheckoutContext, CheckoutProvider, ClickOutGetContainer, CurrentStateType, ElementStackItem, Filter, FilterMode, FilterParams, FilterValues, GeoLocationSensorState, IFilter, IFilterOption, IGeolocationPositionError, ILabelContext, ILayoutContext, IPageContext, IPaginationInfo, IParams, IParamsEncoded, IUseSearchParamsEncodedResult, IUseSearchParamsResult, IUseSearchParamsValueResult, KeyCode, KeyMod, KeyboardOptions, KeyboardResult, LabelProvider, LayoutProvider, PageProvider, SSRState, SizeResult, SizeType, Sorting, UIReducer, UIValue, UseFiltersResultType, UseKeyboard, UseKeyboardHandler, createElementWithId, createGenericContext, decode, detectIsBrowser, filtersToParams, getCurrentPosition, getFilteredItems, getFilters, getOwnerPaddingRight, getOwnerScrollbarWidth, getPagedItems, getRealSize, getSearchParams, getSearchParamsEncoded, getUID, hasGeolocation, isBrowser, parseParams, pushSearchParams, pushSearchParamsEncoded, replaceSearchParams, replaceSearchParamsEncoded, replaceSearchParamsEncodedSilently, replaceSearchParamsSilently, scrollToRelativeY, scrollToSelector, scrollToY, setFilters, updateSearchParams, updateSearchParamsEncoded, useApi, useApiDelete, useApiFetch, useApiGet, useApiPatch, useApiPost, useApiPut, useBodyScroll, useBreakpoint, useCart, useCheckout, useClickAnyWhere, useClickOut, useCurrency, useCurrentState, useDateTimeFormat, useDebounce, useDebounceCallback, useDebugChangedProps, useDomObserver, useDrawer, useElementSize, useEventListener, useFilters, useGeolocation, useIdle, useInfiniteLoader, useIsomorphicLayoutEffect, useKeyboard, useLabel, useLayout, useModal, useMounted, useNumber, usePage, usePagination, usePortal, usePrevious, useRealSize, useResize, useSSR, useScroll, useScrollTo, useScrolled, useSearchParams, useSearchParamsEncoded, useSearchParamsValue, useSorting, useSwiperIndex, useSyncedRef, useUI, useUnit, useUnmountEffect, useUser, useWindowSize };
package/dist/index.js CHANGED
@@ -153,6 +153,7 @@ __export(src_exports, {
153
153
  useSSR: () => useSSR,
154
154
  useScroll: () => useScroll,
155
155
  useScrollTo: () => useScrollTo,
156
+ useScrolled: () => useScrolled,
156
157
  useSearchParams: () => useSearchParams,
157
158
  useSearchParamsEncoded: () => useSearchParamsEncoded,
158
159
  useSearchParamsValue: () => useSearchParamsValue,
@@ -218,7 +219,7 @@ function LayoutProvider({ children, layout }) {
218
219
  // src/useApi/useApi.ts
219
220
  function useApiFetch(pathname, options = {}) {
220
221
  const layout = useLayout();
221
- return useHttpFetch(pathname, options, import_bom_mixer_store.apiFetch, layout);
222
+ return useHttpFetch(pathname, options, import_bom_mixer_store.localApiFetch, layout);
222
223
  }
223
224
  function useApiGet(pathname, options = {}) {
224
225
  return useApiFetch(pathname, __spreadProps(__spreadValues({}, options), { method: "GET" }));
@@ -239,19 +240,19 @@ function useApi() {
239
240
  const layout = useLayout();
240
241
  return {
241
242
  get: (_0, ..._1) => __async(this, [_0, ..._1], function* (pathname, options = {}) {
242
- return (0, import_bom_mixer_store.apiGet)(pathname, options, layout);
243
+ return (0, import_bom_mixer_store.localApiGet)(pathname, options, layout);
243
244
  }),
244
245
  post: (_0, _1, ..._2) => __async(this, [_0, _1, ..._2], function* (pathname, payload, options = {}) {
245
- return (0, import_bom_mixer_store.apiPost)(pathname, payload, options, layout);
246
+ return (0, import_bom_mixer_store.localApiPost)(pathname, payload, options, layout);
246
247
  }),
247
248
  put: (_0, _1, ..._2) => __async(this, [_0, _1, ..._2], function* (pathname, payload, options = {}) {
248
- return (0, import_bom_mixer_store.apiPut)(pathname, payload, options, layout);
249
+ return (0, import_bom_mixer_store.localApiPut)(pathname, payload, options, layout);
249
250
  }),
250
251
  patch: (_0, _1, ..._2) => __async(this, [_0, _1, ..._2], function* (pathname, payload, options = {}) {
251
- return (0, import_bom_mixer_store.apiPatch)(pathname, payload, options, layout);
252
+ return (0, import_bom_mixer_store.localApiPatch)(pathname, payload, options, layout);
252
253
  }),
253
254
  delete: (_0, ..._1) => __async(this, [_0, ..._1], function* (pathname, options = {}) {
254
- return (0, import_bom_mixer_store.apiDelete)(pathname, options, layout);
255
+ return (0, import_bom_mixer_store.localApiDelete)(pathname, options, layout);
255
256
  })
256
257
  };
257
258
  }
@@ -488,11 +489,11 @@ function CartProvider(_a) {
488
489
  }
489
490
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CartContext.Provider, { value: storeRef.current, children });
490
491
  }
491
- function useCart(selector, equalityFn) {
492
+ function useCart(selector) {
492
493
  const store = (0, import_react8.useContext)(CartContext);
493
494
  if (!store)
494
495
  throw new Error("Missing CartContext.Provider in the tree");
495
- return (0, import_zustand.useStore)(store, selector, equalityFn);
496
+ return (0, import_zustand.useStore)(store, selector);
496
497
  }
497
498
 
498
499
  // src/useCheckout/useCheckout.tsx
@@ -548,11 +549,11 @@ function CheckoutProvider(_a) {
548
549
  }
549
550
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CheckoutContext.Provider, { value: storeRef.current, children });
550
551
  }
551
- function useCheckout(selector, equalityFn) {
552
+ function useCheckout(selector) {
552
553
  const store = (0, import_react9.useContext)(CheckoutContext);
553
554
  if (!store)
554
555
  throw new Error("Missing CheckoutContext.Provider in the tree");
555
- return (0, import_zustand2.useStore)(store, selector, equalityFn);
556
+ return (0, import_zustand2.useStore)(store, selector);
556
557
  }
557
558
 
558
559
  // src/useClickAnyWhere/useClickAnyWhere.ts
@@ -1523,8 +1524,8 @@ var import_react30 = require("react");
1523
1524
  function useScroll() {
1524
1525
  const [scroll, setScroll] = (0, import_react30.useState)({ left: 0, top: 0 });
1525
1526
  const onScroll = () => {
1526
- const left = window.pageXOffset;
1527
- const top = window.pageYOffset;
1527
+ const left = window.scrollX;
1528
+ const top = window.scrollY;
1528
1529
  if (scroll.left !== left || scroll.top !== top) {
1529
1530
  setScroll({ left, top });
1530
1531
  }
@@ -1558,11 +1559,11 @@ function scrollToSelector(selector, offset = 0) {
1558
1559
  }
1559
1560
  }
1560
1561
  function scrollToRelativeY(y = 0, offset = 0) {
1561
- const to = window.pageYOffset + y - 60 + offset;
1562
+ const to = window.scrollY + y - 60 + offset;
1562
1563
  return scrollToY(to);
1563
1564
  }
1564
1565
  function scrollToY(y = 0) {
1565
- const from = window.pageYOffset;
1566
+ const from = window.scrollY;
1566
1567
  const to = y;
1567
1568
  const duration = Math.sqrt(Math.abs(to - from) / 4e3);
1568
1569
  (0, import_framer_motion.animate)(from, to, {
@@ -1571,9 +1572,29 @@ function scrollToY(y = 0) {
1571
1572
  });
1572
1573
  }
1573
1574
 
1575
+ // src/useScrolled/useScrolled.ts
1576
+ var import_react31 = require("react");
1577
+ var DEFAULT_CALLBACK = (top, left) => {
1578
+ return top > 0;
1579
+ };
1580
+ function useScrolled(callback = DEFAULT_CALLBACK) {
1581
+ const [scrolled, setScrolled] = (0, import_react31.useState)(false);
1582
+ const onScrolled = () => {
1583
+ const scrolled_ = callback(window.scrollY, window.scrollX);
1584
+ if (scrolled !== scrolled_) {
1585
+ setScrolled(scrolled_);
1586
+ }
1587
+ };
1588
+ useEventListener("scroll", onScrolled);
1589
+ useIsomorphicLayoutEffect(() => {
1590
+ onScrolled();
1591
+ }, []);
1592
+ return scrolled;
1593
+ }
1594
+
1574
1595
  // src/useSearchParams/useSearchParams.ts
1575
1596
  var import_router = require("next/router");
1576
- var import_react31 = require("react");
1597
+ var import_react32 = require("react");
1577
1598
  var isBrowser = typeof window !== "undefined";
1578
1599
  function replace_(params) {
1579
1600
  if (window.history) {
@@ -1632,29 +1653,29 @@ function replaceSearchParamsSilently(params) {
1632
1653
  }
1633
1654
  function useSearchParams() {
1634
1655
  const router = (0, import_router.useRouter)();
1635
- const initialValue = (0, import_react31.useMemo)(() => {
1656
+ const initialValue = (0, import_react32.useMemo)(() => {
1636
1657
  const params2 = deserialize_(router.asPath);
1637
1658
  const value = Object.fromEntries(params2);
1638
1659
  return value;
1639
1660
  }, [router.asPath]);
1640
1661
  const params = initialValue;
1641
- const replaceParamsSilently = (0, import_react31.useCallback)((params2) => {
1662
+ const replaceParamsSilently = (0, import_react32.useCallback)((params2) => {
1642
1663
  replaceSearchParamsSilently(params2);
1643
1664
  }, []);
1644
- const replaceParams = (0, import_react31.useCallback)((params2) => {
1665
+ const replaceParams = (0, import_react32.useCallback)((params2) => {
1645
1666
  replaceSearchParams(router, params2);
1646
1667
  }, [router]);
1647
1668
  return { params, replaceParamsSilently, replaceParams };
1648
1669
  }
1649
1670
  function useSearchParamsValue(key) {
1650
1671
  const router = (0, import_router.useRouter)();
1651
- const initialValue = (0, import_react31.useMemo)(() => {
1672
+ const initialValue = (0, import_react32.useMemo)(() => {
1652
1673
  const params2 = deserialize_(router.asPath);
1653
1674
  const value = params2.get(key);
1654
1675
  return value;
1655
1676
  }, [key, router.asPath]);
1656
1677
  const params = initialValue;
1657
- const replaceParamsSilently = (0, import_react31.useCallback)((params2) => {
1678
+ const replaceParamsSilently = (0, import_react32.useCallback)((params2) => {
1658
1679
  replaceSearchParamsSilently(params2);
1659
1680
  }, []);
1660
1681
  return { params, replaceParamsSilently };
@@ -1662,7 +1683,7 @@ function useSearchParamsValue(key) {
1662
1683
 
1663
1684
  // src/useSearchParamsEncoded/useSearchParamsEncoded.ts
1664
1685
  var import_router2 = require("next/router");
1665
- var import_react32 = require("react");
1686
+ var import_react33 = require("react");
1666
1687
  var USE_ENCRYPTION = true;
1667
1688
  function base64ToString(base64) {
1668
1689
  if (!USE_ENCRYPTION)
@@ -1768,27 +1789,27 @@ function replaceSearchParamsEncodedSilently(value, key) {
1768
1789
  }
1769
1790
  function useSearchParamsEncoded(key) {
1770
1791
  const router = (0, import_router2.useRouter)();
1771
- const initialValue = (0, import_react32.useMemo)(() => {
1792
+ const initialValue = (0, import_react33.useMemo)(() => {
1772
1793
  const value = getSearchParamsEncoded(router.asPath, key);
1773
1794
  return value;
1774
1795
  }, [key, router.asPath]);
1775
1796
  const params = initialValue;
1776
- const replaceParamsSilently = (0, import_react32.useCallback)((params2) => {
1797
+ const replaceParamsSilently = (0, import_react33.useCallback)((params2) => {
1777
1798
  replaceSearchParamsEncodedSilently(params2, key);
1778
1799
  }, [key]);
1779
- const replaceParams = (0, import_react32.useCallback)((params2) => {
1800
+ const replaceParams = (0, import_react33.useCallback)((params2) => {
1780
1801
  replaceSearchParamsEncoded(router, params2, key);
1781
1802
  }, [key, router]);
1782
1803
  return { params, replaceParamsSilently, replaceParams };
1783
1804
  }
1784
1805
 
1785
1806
  // src/useSorting/useSorting.ts
1786
- var import_react33 = require("react");
1807
+ var import_react34 = require("react");
1787
1808
  function useSorting(items_, callback_, sort_) {
1788
- const [sort, setSort] = (0, import_react33.useState)(sort_);
1789
- const [items, setItems] = (0, import_react33.useState)(callback_(items_.slice(), sort));
1790
- const isInitialMount = (0, import_react33.useRef)(true);
1791
- (0, import_react33.useEffect)(() => {
1809
+ const [sort, setSort] = (0, import_react34.useState)(sort_);
1810
+ const [items, setItems] = (0, import_react34.useState)(callback_(items_.slice(), sort));
1811
+ const isInitialMount = (0, import_react34.useRef)(true);
1812
+ (0, import_react34.useEffect)(() => {
1792
1813
  if (isInitialMount.current) {
1793
1814
  isInitialMount.current = false;
1794
1815
  } else {
@@ -1804,18 +1825,18 @@ function useSorting(items_, callback_, sort_) {
1804
1825
  }
1805
1826
 
1806
1827
  // src/useSwiperIndex/useSwiperIndex.ts
1807
- var import_react34 = require("react");
1808
- var import_react35 = require("swiper/react");
1828
+ var import_react35 = require("react");
1829
+ var import_react36 = require("swiper/react");
1809
1830
  function useSwiperIndex() {
1810
- const swiper = (0, import_react35.useSwiper)();
1811
- const [index, setIndex] = (0, import_react34.useState)(swiper.realIndex);
1812
- const slideTo = (0, import_react34.useCallback)((index2) => {
1831
+ const swiper = (0, import_react36.useSwiper)();
1832
+ const [index, setIndex] = (0, import_react35.useState)(swiper.realIndex);
1833
+ const slideTo = (0, import_react35.useCallback)((index2) => {
1813
1834
  swiper.slideTo(index2);
1814
1835
  }, [swiper]);
1815
1836
  const onSlideChange = (swiper2) => {
1816
1837
  setIndex(swiper2.realIndex);
1817
1838
  };
1818
- (0, import_react34.useEffect)(() => {
1839
+ (0, import_react35.useEffect)(() => {
1819
1840
  if (swiper) {
1820
1841
  swiper.on("slideChange", onSlideChange);
1821
1842
  }
@@ -1829,11 +1850,11 @@ function useSwiperIndex() {
1829
1850
  }
1830
1851
 
1831
1852
  // src/useSyncedRef/useSyncedRef.ts
1832
- var import_react36 = require("react");
1853
+ var import_react37 = require("react");
1833
1854
  function useSyncedRef(value) {
1834
- const ref = (0, import_react36.useRef)(value);
1855
+ const ref = (0, import_react37.useRef)(value);
1835
1856
  ref.current = value;
1836
- return (0, import_react36.useMemo)(() => Object.freeze({
1857
+ return (0, import_react37.useMemo)(() => Object.freeze({
1837
1858
  get current() {
1838
1859
  return ref.current;
1839
1860
  }
@@ -1846,10 +1867,10 @@ function useUnit(unit = "kilometer", locale) {
1846
1867
  }
1847
1868
 
1848
1869
  // src/useUnmountEffect/useUnmountEffect.ts
1849
- var import_react37 = require("react");
1870
+ var import_react38 = require("react");
1850
1871
  function useUnmountEffect(effect) {
1851
1872
  const effectRef = useSyncedRef(effect);
1852
- (0, import_react37.useEffect)(() => () => {
1873
+ (0, import_react38.useEffect)(() => () => {
1853
1874
  effectRef.current();
1854
1875
  }, []);
1855
1876
  }
@@ -1947,6 +1968,7 @@ var useUser = (0, import_zustand4.create)((set) => ({
1947
1968
  useSSR,
1948
1969
  useScroll,
1949
1970
  useScrollTo,
1971
+ useScrolled,
1950
1972
  useSearchParams,
1951
1973
  useSearchParamsEncoded,
1952
1974
  useSearchParamsValue,
package/dist/index.mjs CHANGED
@@ -51,7 +51,7 @@ var __async = (__this, __arguments, generator) => {
51
51
  };
52
52
 
53
53
  // src/useApi/useApi.ts
54
- import { apiDelete, apiFetch, apiGet, apiPatch, apiPost, apiPut } from "@websolutespa/bom-mixer-store";
54
+ import { localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut } from "@websolutespa/bom-mixer-store";
55
55
 
56
56
  // src/useHttp/useHttp.ts
57
57
  import { httpFetch } from "@websolutespa/bom-core";
@@ -101,7 +101,7 @@ function LayoutProvider({ children, layout }) {
101
101
  // src/useApi/useApi.ts
102
102
  function useApiFetch(pathname, options = {}) {
103
103
  const layout = useLayout();
104
- return useHttpFetch(pathname, options, apiFetch, layout);
104
+ return useHttpFetch(pathname, options, localApiFetch, layout);
105
105
  }
106
106
  function useApiGet(pathname, options = {}) {
107
107
  return useApiFetch(pathname, __spreadProps(__spreadValues({}, options), { method: "GET" }));
@@ -122,19 +122,19 @@ function useApi() {
122
122
  const layout = useLayout();
123
123
  return {
124
124
  get: (_0, ..._1) => __async(this, [_0, ..._1], function* (pathname, options = {}) {
125
- return apiGet(pathname, options, layout);
125
+ return localApiGet(pathname, options, layout);
126
126
  }),
127
127
  post: (_0, _1, ..._2) => __async(this, [_0, _1, ..._2], function* (pathname, payload, options = {}) {
128
- return apiPost(pathname, payload, options, layout);
128
+ return localApiPost(pathname, payload, options, layout);
129
129
  }),
130
130
  put: (_0, _1, ..._2) => __async(this, [_0, _1, ..._2], function* (pathname, payload, options = {}) {
131
- return apiPut(pathname, payload, options, layout);
131
+ return localApiPut(pathname, payload, options, layout);
132
132
  }),
133
133
  patch: (_0, _1, ..._2) => __async(this, [_0, _1, ..._2], function* (pathname, payload, options = {}) {
134
- return apiPatch(pathname, payload, options, layout);
134
+ return localApiPatch(pathname, payload, options, layout);
135
135
  }),
136
136
  delete: (_0, ..._1) => __async(this, [_0, ..._1], function* (pathname, options = {}) {
137
- return apiDelete(pathname, options, layout);
137
+ return localApiDelete(pathname, options, layout);
138
138
  })
139
139
  };
140
140
  }
@@ -371,11 +371,11 @@ function CartProvider(_a) {
371
371
  }
372
372
  return /* @__PURE__ */ jsx2(CartContext.Provider, { value: storeRef.current, children });
373
373
  }
374
- function useCart(selector, equalityFn) {
374
+ function useCart(selector) {
375
375
  const store = useContext3(CartContext);
376
376
  if (!store)
377
377
  throw new Error("Missing CartContext.Provider in the tree");
378
- return useStore(store, selector, equalityFn);
378
+ return useStore(store, selector);
379
379
  }
380
380
 
381
381
  // src/useCheckout/useCheckout.tsx
@@ -431,11 +431,11 @@ function CheckoutProvider(_a) {
431
431
  }
432
432
  return /* @__PURE__ */ jsx3(CheckoutContext.Provider, { value: storeRef.current, children });
433
433
  }
434
- function useCheckout(selector, equalityFn) {
434
+ function useCheckout(selector) {
435
435
  const store = useContext4(CheckoutContext);
436
436
  if (!store)
437
437
  throw new Error("Missing CheckoutContext.Provider in the tree");
438
- return useStore2(store, selector, equalityFn);
438
+ return useStore2(store, selector);
439
439
  }
440
440
 
441
441
  // src/useClickAnyWhere/useClickAnyWhere.ts
@@ -1406,8 +1406,8 @@ import { useState as useState16 } from "react";
1406
1406
  function useScroll() {
1407
1407
  const [scroll, setScroll] = useState16({ left: 0, top: 0 });
1408
1408
  const onScroll = () => {
1409
- const left = window.pageXOffset;
1410
- const top = window.pageYOffset;
1409
+ const left = window.scrollX;
1410
+ const top = window.scrollY;
1411
1411
  if (scroll.left !== left || scroll.top !== top) {
1412
1412
  setScroll({ left, top });
1413
1413
  }
@@ -1441,11 +1441,11 @@ function scrollToSelector(selector, offset = 0) {
1441
1441
  }
1442
1442
  }
1443
1443
  function scrollToRelativeY(y = 0, offset = 0) {
1444
- const to = window.pageYOffset + y - 60 + offset;
1444
+ const to = window.scrollY + y - 60 + offset;
1445
1445
  return scrollToY(to);
1446
1446
  }
1447
1447
  function scrollToY(y = 0) {
1448
- const from = window.pageYOffset;
1448
+ const from = window.scrollY;
1449
1449
  const to = y;
1450
1450
  const duration = Math.sqrt(Math.abs(to - from) / 4e3);
1451
1451
  animate(from, to, {
@@ -1454,6 +1454,26 @@ function scrollToY(y = 0) {
1454
1454
  });
1455
1455
  }
1456
1456
 
1457
+ // src/useScrolled/useScrolled.ts
1458
+ import { useState as useState17 } from "react";
1459
+ var DEFAULT_CALLBACK = (top, left) => {
1460
+ return top > 0;
1461
+ };
1462
+ function useScrolled(callback = DEFAULT_CALLBACK) {
1463
+ const [scrolled, setScrolled] = useState17(false);
1464
+ const onScrolled = () => {
1465
+ const scrolled_ = callback(window.scrollY, window.scrollX);
1466
+ if (scrolled !== scrolled_) {
1467
+ setScrolled(scrolled_);
1468
+ }
1469
+ };
1470
+ useEventListener("scroll", onScrolled);
1471
+ useIsomorphicLayoutEffect(() => {
1472
+ onScrolled();
1473
+ }, []);
1474
+ return scrolled;
1475
+ }
1476
+
1457
1477
  // src/useSearchParams/useSearchParams.ts
1458
1478
  import { useRouter } from "next/router";
1459
1479
  import { useCallback as useCallback4, useMemo as useMemo5 } from "react";
@@ -1666,10 +1686,10 @@ function useSearchParamsEncoded(key) {
1666
1686
  }
1667
1687
 
1668
1688
  // src/useSorting/useSorting.ts
1669
- import { useEffect as useEffect22, useRef as useRef11, useState as useState17 } from "react";
1689
+ import { useEffect as useEffect22, useRef as useRef11, useState as useState18 } from "react";
1670
1690
  function useSorting(items_, callback_, sort_) {
1671
- const [sort, setSort] = useState17(sort_);
1672
- const [items, setItems] = useState17(callback_(items_.slice(), sort));
1691
+ const [sort, setSort] = useState18(sort_);
1692
+ const [items, setItems] = useState18(callback_(items_.slice(), sort));
1673
1693
  const isInitialMount = useRef11(true);
1674
1694
  useEffect22(() => {
1675
1695
  if (isInitialMount.current) {
@@ -1687,11 +1707,11 @@ function useSorting(items_, callback_, sort_) {
1687
1707
  }
1688
1708
 
1689
1709
  // src/useSwiperIndex/useSwiperIndex.ts
1690
- import { useCallback as useCallback6, useEffect as useEffect23, useState as useState18 } from "react";
1710
+ import { useCallback as useCallback6, useEffect as useEffect23, useState as useState19 } from "react";
1691
1711
  import { useSwiper } from "swiper/react";
1692
1712
  function useSwiperIndex() {
1693
1713
  const swiper = useSwiper();
1694
- const [index, setIndex] = useState18(swiper.realIndex);
1714
+ const [index, setIndex] = useState19(swiper.realIndex);
1695
1715
  const slideTo = useCallback6((index2) => {
1696
1716
  swiper.slideTo(index2);
1697
1717
  }, [swiper]);
@@ -1829,6 +1849,7 @@ export {
1829
1849
  useSSR,
1830
1850
  useScroll,
1831
1851
  useScrollTo,
1852
+ useScrolled,
1832
1853
  useSearchParams,
1833
1854
  useSearchParamsEncoded,
1834
1855
  useSearchParamsValue,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websolutespa/bom-mixer-hooks",
3
- "version": "0.2.2",
3
+ "version": "1.1.0",
4
4
  "description": "Mixer Hooks module of the BOM Repository",
5
5
  "keywords": [
6
6
  "bom",
@@ -34,7 +34,7 @@
34
34
  "react": ">= 18.2.0",
35
35
  "styled-components": ">= 5.3.5",
36
36
  "swiper": ">= 8.3.2",
37
- "zustand": ">= 4.1.1"
37
+ "zustand": ">= 4.4.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/react": "^18.0.18",
package/src/index.ts CHANGED
@@ -37,12 +37,13 @@ export * from './usePortal/usePortal';
37
37
  export * from './usePrevious/usePrevious';
38
38
  export * from './useRealSize/useRealSize';
39
39
  export * from './useResize/useResize';
40
+ export * from './useSSR/useSSR';
40
41
  export * from './useScroll/useScroll';
41
42
  export * from './useScrollTo/useScrollTo';
43
+ export * from './useScrolled/useScrolled';
42
44
  export * from './useSearchParams/useSearchParams';
43
45
  export * from './useSearchParamsEncoded/useSearchParamsEncoded';
44
46
  export * from './useSorting/useSorting';
45
- export * from './useSSR/useSSR';
46
47
  export * from './useSwiperIndex/useSwiperIndex';
47
48
  export * from './useSyncedRef/useSyncedRef';
48
49
  export * from './useUI/useUI';
@@ -1,12 +1,13 @@
1
1
  import '@testing-library/jest-dom';
2
2
  import { render, renderHook, screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react';
3
+ import { ILayout } from '@websolutespa/bom-core';
3
4
  import { LayoutDefaults } from '@websolutespa/bom-mixer-mock';
4
- import { getApiUrl } from '@websolutespa/bom-mixer-store';
5
+ import { getLocalApiUrl } from '@websolutespa/bom-mixer-store';
5
6
  import { LayoutProvider } from '../useLayout/useLayout';
6
7
  import { useApi, useApiDelete, useApiFetch, useApiGet, useApiPatch, useApiPost, useApiPut } from './useApi';
7
8
 
8
9
  const wrapper = (props: { children: React.ReactNode }) => (
9
- <LayoutProvider layout={LayoutDefaults}>{props.children}</LayoutProvider>
10
+ <LayoutProvider layout={LayoutDefaults as ILayout}>{props.children}</LayoutProvider>
10
11
  );
11
12
 
12
13
  const defaultResponse = {
@@ -21,7 +22,7 @@ function mockFetch(
21
22
  overrideResponse: Partial<typeof defaultResponse> = {}
22
23
  ) {
23
24
  const endpoint = '/endpoint';
24
- const url = `${getApiUrl(endpoint)}?locale=en&market=ww`;
25
+ const url = `${getLocalApiUrl(endpoint)}?locale=en&market=ww`;
25
26
  const payload = { data: 'data' };
26
27
  const response = {
27
28
  ...defaultResponse,
@@ -37,6 +38,7 @@ function mockFetch(
37
38
  method: string;
38
39
  } = {
39
40
  headers: {
41
+ 'Authorization': 'Bearer STORE_BEARER',
40
42
  'Content-Type': 'application/json',
41
43
  },
42
44
  method,
@@ -55,18 +57,18 @@ describe('useApi', () => {
55
57
  jest.resetModules();
56
58
  jest.resetAllMocks();
57
59
  jest.spyOn(console, 'error').mockImplementation(() => { });
60
+ jest.spyOn(console, 'log').mockImplementation(() => { });
58
61
  process.env = {
59
62
  NODE_ENV: 'test',
60
63
  NEXT_PUBLIC_URL: 'http://localhost:3000',
61
64
  NEXT_PUBLIC_MOCK_FALLBACK_URL: 'http://localhost:3000',
62
65
  NEXT_PUBLIC_API: '/api',
63
- NEXT_PUBLIC_GOOGLE_MAP_API_KEY: 'AIzaSyDvGw6iAoKdRv8mmaC9GeT-LWLPQtA8p60',
64
66
  STORE_URL: 'http://localhost:4000',
65
- STORE_API: '/api',
66
- STORE_BEARER: '7584f15d12972fb1e7695e998dd5e4c754f46c74d06a08e8d76f556adcd045e48cd52bed6faac098784471ac273ee40243194b9cff7eba3c4a768f8f41d2d51959a7f767b943c7f0170f6e5f632db523803c357083bf7a7bf03ee8e0df2d8ce5cd52e0211283b34d7781313da775018a9e950433d2b6faf711c20e5a63b25243',
67
+ STORE_API: '/bowl/api',
67
68
  STORE_STRATEGY: 'mock',
68
- SECRET_COOKIE_PASSWORD: '2gyZ3GDw3LHZQKDhPmPDL3sjREVRXPr8',
69
- HOOKS_SECRET: '7584f15d12972fb1e7695e998dd5e4',
69
+ STORE_BEARER: 'STORE_BEARER',
70
+ SECRET_COOKIE_PASSWORD: 'SECRET_COOKIE_PASSWORD',
71
+ HOOKS_SECRET: 'HOOKS_SECRET',
70
72
  };
71
73
  });
72
74
 
@@ -178,7 +180,7 @@ describe('useApi', () => {
178
180
  );
179
181
  };
180
182
  render(
181
- <LayoutProvider layout={LayoutDefaults}><Wrapper /></LayoutProvider>
183
+ <LayoutProvider layout={LayoutDefaults as ILayout}><Wrapper /></LayoutProvider>
182
184
  );
183
185
  expect(screen.getByTestId('loading')).toHaveTextContent('loading');
184
186
  await waitForElementToBeRemoved(() => screen.getByTestId('loading'));
@@ -1,58 +1,59 @@
1
- import { FetchRequestOptions } from '@websolutespa/bom-core';
2
- import { apiDelete, apiFetch, apiGet, apiPatch, apiPost, apiPut } from '@websolutespa/bom-mixer-store';
1
+ import { ApiRequestOptions, localApiDelete, localApiFetch, localApiGet, localApiPatch, localApiPost, localApiPut } from '@websolutespa/bom-mixer-store';
3
2
  import { useHttpFetch } from '../useHttp/useHttp';
4
3
  import { useLayout } from '../useLayout/useLayout';
5
4
 
6
- export function useApiFetch<T = any>(pathname: string, options: FetchRequestOptions = {}) {
5
+ export function useApiFetch<T = unknown>(pathname: string, options: ApiRequestOptions = {}) {
7
6
  const layout = useLayout();
8
- return useHttpFetch<T>(pathname, options, apiFetch, layout);
7
+ // const layout = { locale: '', market: '' };
8
+ return useHttpFetch<T>(pathname, options, localApiFetch, layout);
9
9
  }
10
10
 
11
- export function useApiGet<T = any>(pathname: string, options: FetchRequestOptions = {}) {
11
+ export function useApiGet<T = unknown>(pathname: string, options: ApiRequestOptions = {}) {
12
12
  return useApiFetch<T>(pathname, { ...options, method: 'GET' });
13
13
  }
14
14
 
15
- export function useApiPost<T = any>(pathname: string, payload: unknown, options: FetchRequestOptions = {}) {
15
+ export function useApiPost<T = unknown>(pathname: string, payload: unknown, options: ApiRequestOptions = {}) {
16
16
  return useApiFetch<T>(pathname, { ...options, method: 'POST', body: payload ? JSON.stringify(payload) : undefined });
17
17
  }
18
18
 
19
- export function useApiPut<T = any>(pathname: string, payload: unknown, options: FetchRequestOptions = {}) {
19
+ export function useApiPut<T = unknown>(pathname: string, payload: unknown, options: ApiRequestOptions = {}) {
20
20
  return useApiFetch<T>(pathname, { ...options, method: 'PUT', body: payload ? JSON.stringify(payload) : undefined });
21
21
  }
22
22
 
23
- export function useApiPatch<T = any>(pathname: string, payload: unknown, options: FetchRequestOptions = {}) {
23
+ export function useApiPatch<T = unknown>(pathname: string, payload: unknown, options: ApiRequestOptions = {}) {
24
24
  return useApiFetch<T>(pathname, { ...options, method: 'PATCH', body: payload ? JSON.stringify(payload) : undefined });
25
25
  }
26
26
 
27
- export function useApiDelete<T = any>(pathname: string, options: FetchRequestOptions = {}) {
27
+ export function useApiDelete<T = unknown>(pathname: string, options: ApiRequestOptions = {}) {
28
28
  return useApiFetch<T>(pathname, { ...options, method: 'DELETE' });
29
29
  }
30
30
 
31
31
  type Api = {
32
- get: <T = any>(pathname: string, options?: FetchRequestOptions) => Promise<T>;
33
- post: <T = any>(pathname: string, payload?: unknown, options?: FetchRequestOptions) => Promise<T>;
34
- put: <T = any>(pathname: string, payload?: unknown, options?: FetchRequestOptions) => Promise<T>;
35
- patch: <T = any>(pathname: string, payload?: unknown, options?: FetchRequestOptions) => Promise<T>;
36
- delete: <T = any>(pathname: string, options?: FetchRequestOptions) => Promise<T>;
32
+ get: <T = unknown>(pathname: string, options?: ApiRequestOptions) => Promise<T>;
33
+ post: <T = unknown>(pathname: string, payload?: unknown, options?: ApiRequestOptions) => Promise<T>;
34
+ put: <T = unknown>(pathname: string, payload?: unknown, options?: ApiRequestOptions) => Promise<T>;
35
+ patch: <T = unknown>(pathname: string, payload?: unknown, options?: ApiRequestOptions) => Promise<T>;
36
+ delete: <T = unknown>(pathname: string, options?: ApiRequestOptions) => Promise<T>;
37
37
  };
38
38
 
39
39
  export function useApi(): Api {
40
40
  const layout = useLayout();
41
+ // const layout = { locale: '', market: '' };
41
42
  return {
42
- get: async <T = any>(pathname: string, options: FetchRequestOptions = {}) => {
43
- return apiGet<T>(pathname, options, layout);
43
+ get: async <T = unknown>(pathname: string, options: ApiRequestOptions = {}) => {
44
+ return localApiGet<T>(pathname, options, layout);
44
45
  },
45
- post: async <T = any>(pathname: string, payload?: unknown, options: FetchRequestOptions = {}) => {
46
- return apiPost<T>(pathname, payload, options, layout);
46
+ post: async <T = unknown>(pathname: string, payload?: unknown, options: ApiRequestOptions = {}) => {
47
+ return localApiPost<T>(pathname, payload, options, layout);
47
48
  },
48
- put: async <T = any>(pathname: string, payload?: unknown, options: FetchRequestOptions = {}) => {
49
- return apiPut<T>(pathname, payload, options, layout);
49
+ put: async <T = unknown>(pathname: string, payload?: unknown, options: ApiRequestOptions = {}) => {
50
+ return localApiPut<T>(pathname, payload, options, layout);
50
51
  },
51
- patch: async <T = any>(pathname: string, payload?: unknown, options: FetchRequestOptions = {}) => {
52
- return apiPatch<T>(pathname, payload, options, layout);
52
+ patch: async <T = unknown>(pathname: string, payload?: unknown, options: ApiRequestOptions = {}) => {
53
+ return localApiPatch<T>(pathname, payload, options, layout);
53
54
  },
54
- delete: async <T = any>(pathname: string, options: FetchRequestOptions = {}) => {
55
- return apiDelete<T>(pathname, options, layout);
55
+ delete: async <T = unknown>(pathname: string, options: ApiRequestOptions = {}) => {
56
+ return localApiDelete<T>(pathname, options, layout);
56
57
  },
57
58
  };
58
59
  }
@@ -119,13 +119,10 @@ function CartProvider({ children, ...props }: CartProviderProps) {
119
119
  );
120
120
  }
121
121
 
122
- function useCart<T>(
123
- selector: (state: CartState) => T,
124
- equalityFn?: (left: T, right: T) => boolean
125
- ): T {
122
+ function useCart<T>(selector: (state: CartState) => T): T {
126
123
  const store = useContext(CartContext);
127
124
  if (!store) throw new Error('Missing CartContext.Provider in the tree');
128
- return useStore(store, selector, equalityFn);
125
+ return useStore(store, selector);
129
126
  }
130
127
 
131
128
  export { CartProvider, useCart };
@@ -1,7 +1,7 @@
1
1
  import { IAddressOptions, ICheckoutPartial } from '@websolutespa/bom-mixer-models';
2
2
  import { createContext, useContext, useRef } from 'react';
3
3
  import { createStore, useStore } from 'zustand';
4
- import { createJSONStorage, persist, StateStorage } from 'zustand/middleware';
4
+ import { StateStorage, createJSONStorage, persist } from 'zustand/middleware';
5
5
 
6
6
  type CheckoutInitialProps = {
7
7
  data: IAddressOptions;
@@ -82,13 +82,10 @@ function CheckoutProvider({ children, ...props }: CheckoutProviderProps) {
82
82
  );
83
83
  }
84
84
 
85
- function useCheckout<T>(
86
- selector: (state: CheckoutState) => T,
87
- equalityFn?: (left: T, right: T) => boolean
88
- ): T {
85
+ function useCheckout<T>(selector: (state: CheckoutState) => T): T {
89
86
  const store = useContext(CheckoutContext);
90
87
  if (!store) throw new Error('Missing CheckoutContext.Provider in the tree');
91
- return useStore(store, selector, equalityFn);
88
+ return useStore(store, selector);
92
89
  }
93
90
 
94
91
  export { CheckoutProvider, useCheckout };
@@ -1,10 +1,11 @@
1
1
  import { renderHook } from '@testing-library/react';
2
+ import { ILayout } from '@websolutespa/bom-core';
2
3
  import { LayoutDefaults } from '@websolutespa/bom-mixer-mock';
3
4
  import { LayoutProvider } from '../useLayout/useLayout';
4
5
  import { useCurrency } from './useCurrency';
5
6
 
6
7
  const wrapper = (props: { children: React.ReactNode }) => (
7
- <LayoutProvider layout={LayoutDefaults}>{props.children}</LayoutProvider>
8
+ <LayoutProvider layout={LayoutDefaults as ILayout}>{props.children}</LayoutProvider>
8
9
  );
9
10
 
10
11
  describe('useCurrency', () => {
@@ -6,7 +6,7 @@ export function useCurrency(currency: string = 'EUR', locale?: string): (value:
6
6
 
7
7
  /*
8
8
  import { useMemo } from 'react';
9
- import { useNumber } from 'src/useNumber/useNumber';
9
+ import { useNumber } from '../useNumber/useNumber';
10
10
  import { useLayout } from '../useLayout/useLayout';
11
11
 
12
12
  export function useCurrency(currency: string = 'EUR', locale?: string): (value: number) => string {
@@ -1,10 +1,11 @@
1
1
  import { renderHook } from '@testing-library/react';
2
+ import { ILayout } from '@websolutespa/bom-core';
2
3
  import { LayoutDefaults } from '@websolutespa/bom-mixer-mock';
3
4
  import { LayoutProvider } from '../useLayout/useLayout';
4
5
  import { useDateTimeFormat } from './useDateTimeFormat';
5
6
 
6
7
  const wrapper = (props: { children: React.ReactNode }) => (
7
- <LayoutProvider layout={LayoutDefaults}>{props.children}</LayoutProvider>
8
+ <LayoutProvider layout={LayoutDefaults as ILayout}>{props.children}</LayoutProvider>
8
9
  );
9
10
 
10
11
  describe('useDateTimeFormat', () => {
@@ -1,6 +1,6 @@
1
1
  import '@testing-library/jest-dom';
2
2
  import { render, screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react';
3
- import { getApiUrl } from '@websolutespa/bom-mixer-store';
3
+ import { getLocalApiUrl } from '@websolutespa/bom-mixer-store';
4
4
  import { useHttpDelete, useHttpFetch, useHttpGet, useHttpPatch, useHttpPost, useHttpPut } from './useHttp';
5
5
 
6
6
  const defaultResponse = {
@@ -12,7 +12,7 @@ const defaultResponse = {
12
12
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
13
  function mockFetch(method: string = 'GET', result: any = { message: 'ok' }, overrideResponse: Partial<typeof defaultResponse> = {}) {
14
14
  const endpoint = '/endpoint';
15
- const url = `${getApiUrl(endpoint)}?locale=en&market=ww`;
15
+ const url = `${getLocalApiUrl(endpoint)}?locale=en&market=ww`;
16
16
  const payload = { data: 'data' };
17
17
  const response = {
18
18
  ...defaultResponse,
@@ -45,22 +45,21 @@ describe('useHttp', () => {
45
45
  const FETCH = global.fetch;
46
46
 
47
47
  beforeEach(() => {
48
- // !!! act error
49
- jest.spyOn(console, 'error').mockImplementation(() => { });
50
48
  jest.resetModules();
51
49
  jest.resetAllMocks();
50
+ jest.spyOn(console, 'error').mockImplementation(() => { });
51
+ jest.spyOn(console, 'log').mockImplementation(() => { });
52
52
  process.env = {
53
53
  NODE_ENV: 'test',
54
54
  NEXT_PUBLIC_URL: 'http://localhost:3000',
55
55
  NEXT_PUBLIC_MOCK_FALLBACK_URL: 'http://localhost:3000',
56
56
  NEXT_PUBLIC_API: '/api',
57
- NEXT_PUBLIC_GOOGLE_MAP_API_KEY: 'AIzaSyDvGw6iAoKdRv8mmaC9GeT-LWLPQtA8p60',
58
57
  STORE_URL: 'http://localhost:4000',
59
- STORE_API: '/api',
60
- STORE_BEARER: '7584f15d12972fb1e7695e998dd5e4c754f46c74d06a08e8d76f556adcd045e48cd52bed6faac098784471ac273ee40243194b9cff7eba3c4a768f8f41d2d51959a7f767b943c7f0170f6e5f632db523803c357083bf7a7bf03ee8e0df2d8ce5cd52e0211283b34d7781313da775018a9e950433d2b6faf711c20e5a63b25243',
58
+ STORE_API: '/bowl/api',
61
59
  STORE_STRATEGY: 'mock',
62
- SECRET_COOKIE_PASSWORD: '2gyZ3GDw3LHZQKDhPmPDL3sjREVRXPr8',
63
- HOOKS_SECRET: '7584f15d12972fb1e7695e998dd5e4',
60
+ STORE_BEARER: 'STORE_BEARER',
61
+ SECRET_COOKIE_PASSWORD: 'SECRET_COOKIE_PASSWORD',
62
+ HOOKS_SECRET: 'HOOKS_SECRET',
64
63
  };
65
64
  });
66
65
 
@@ -1,15 +1,15 @@
1
- import { FetchRequestOptions, FetchService, httpFetch } from '@websolutespa/bom-core';
1
+ import { FetchError, FetchRequestOptions, FetchService, httpFetch } from '@websolutespa/bom-core';
2
2
  import { Dispatch, useEffect, useState } from 'react';
3
3
 
4
- export function useHttpFetch<T = any>(
4
+ export function useHttpFetch<T = unknown>(
5
5
  pathname: string,
6
6
  options: FetchRequestOptions = { method: 'GET' },
7
7
  service: FetchService<T> = httpFetch,
8
- serviceOptions?: any
9
- ): [T | undefined, boolean, any, Dispatch<any>] {
8
+ serviceOptions?: unknown
9
+ ): [T | undefined, boolean, FetchError, Dispatch<FetchError>] {
10
10
  const [response, setResponse] = useState<T>();
11
11
  const [loading, setLoading] = useState<boolean>(false);
12
- const [error, setError] = useState<any>(null);
12
+ const [error, setError] = useState<FetchError>(null);
13
13
  useEffect(() => {
14
14
  // const source = axios.CancelToken.source();
15
15
  const fetchData = async () => {
@@ -19,7 +19,7 @@ export function useHttpFetch<T = any>(
19
19
  const response = await service(pathname, options, serviceOptions);
20
20
  // console.log('useHttp.response', response);
21
21
  setResponse(response);
22
- } catch (error) {
22
+ } catch (error: FetchError) {
23
23
  // console.error(error)
24
24
  setError(error);
25
25
  }
@@ -31,22 +31,22 @@ export function useHttpFetch<T = any>(
31
31
  return [response, loading, error, setError];
32
32
  }
33
33
 
34
- export function useHttpGet<T = any>(pathname: string, options: FetchRequestOptions = {}) {
34
+ export function useHttpGet<T = unknown>(pathname: string, options: FetchRequestOptions = {}) {
35
35
  return useHttpFetch<T>(pathname, { ...options, method: 'GET' });
36
36
  }
37
37
 
38
- export function useHttpPost<T = any>(pathname: string, payload: any, options: FetchRequestOptions = {}) {
38
+ export function useHttpPost<T = unknown>(pathname: string, payload: unknown, options: FetchRequestOptions = {}) {
39
39
  return useHttpFetch<T>(pathname, { ...options, method: 'POST', body: payload ? JSON.stringify(payload) : undefined });
40
40
  }
41
41
 
42
- export function useHttpPut<T = any>(pathname: string, payload: any, options: FetchRequestOptions = {}) {
42
+ export function useHttpPut<T = unknown>(pathname: string, payload: unknown, options: FetchRequestOptions = {}) {
43
43
  return useHttpFetch<T>(pathname, { ...options, method: 'PUT', body: payload ? JSON.stringify(payload) : undefined });
44
44
  }
45
45
 
46
- export function useHttpPatch<T = any>(pathname: string, payload: any, options: FetchRequestOptions = {}) {
46
+ export function useHttpPatch<T = unknown>(pathname: string, payload: unknown, options: FetchRequestOptions = {}) {
47
47
  return useHttpFetch<T>(pathname, { ...options, method: 'PATCH', body: payload ? JSON.stringify(payload) : undefined });
48
48
  }
49
49
 
50
- export function useHttpDelete<T = any>(pathname: string, options: FetchRequestOptions = {}) {
50
+ export function useHttpDelete<T = unknown>(pathname: string, options: FetchRequestOptions = {}) {
51
51
  return useHttpFetch<T>(pathname, { ...options, method: 'DELETE' });
52
52
  }
@@ -1,10 +1,11 @@
1
1
  import { renderHook } from '@testing-library/react';
2
+ import { ILayout } from '@websolutespa/bom-core';
2
3
  import { LayoutDefaults } from '@websolutespa/bom-mixer-mock';
3
4
  import { LayoutProvider } from '../useLayout/useLayout';
4
5
  import { LabelProvider, parseParams, useLabel } from './useLabel';
5
6
 
6
7
  const wrapper = (props: { children: React.ReactNode }) => (
7
- <LayoutProvider layout={LayoutDefaults}>
8
+ <LayoutProvider layout={LayoutDefaults as ILayout}>
8
9
  <LabelProvider>{props.children}</LabelProvider>
9
10
  </LayoutProvider>
10
11
  );
@@ -1,10 +1,11 @@
1
1
  // readme https://testing-library.com/
2
2
  import { renderHook } from '@testing-library/react';
3
+ import { ILayout } from '@websolutespa/bom-core';
3
4
  import { LayoutDefaults } from '@websolutespa/bom-mixer-mock';
4
5
  import { LayoutProvider, useLayout } from './useLayout';
5
6
 
6
7
  const wrapper = (props: { children: React.ReactNode }) => (
7
- <LayoutProvider layout={LayoutDefaults}>{props.children}</LayoutProvider>
8
+ <LayoutProvider layout={LayoutDefaults as ILayout}>{props.children}</LayoutProvider>
8
9
  );
9
10
 
10
11
  describe('useLayout', () => {
@@ -15,5 +15,5 @@ function LayoutProvider({ children, layout }: { children?: React.ReactNode, layo
15
15
  );
16
16
  }
17
17
 
18
- export { useLayout, LayoutProvider };
18
+ export { LayoutProvider, useLayout };
19
19
 
@@ -1,10 +1,11 @@
1
1
  import { renderHook } from '@testing-library/react';
2
+ import { ILayout } from '@websolutespa/bom-core';
2
3
  import { LayoutDefaults } from '@websolutespa/bom-mixer-mock';
3
4
  import { LayoutProvider } from '../useLayout/useLayout';
4
5
  import { useNumber } from './useNumber';
5
6
 
6
7
  const wrapper = (props: { children: React.ReactNode }) => (
7
- <LayoutProvider layout={LayoutDefaults}>{props.children}</LayoutProvider>
8
+ <LayoutProvider layout={LayoutDefaults as ILayout}>{props.children}</LayoutProvider>
8
9
  );
9
10
 
10
11
  describe('useNumber', () => {
@@ -15,5 +15,5 @@ function PageProvider({ children, page }: { children?: React.ReactNode, page: IP
15
15
  );
16
16
  }
17
17
 
18
- export { usePage, PageProvider };
18
+ export { PageProvider, usePage };
19
19
 
@@ -3,7 +3,7 @@ import { act, renderHook } from '@testing-library/react';
3
3
  import { useScroll } from './useScroll';
4
4
 
5
5
  const windowScroll = (scrollTop: number): void => {
6
- window.pageYOffset = scrollTop;
6
+ window.scrollY = scrollTop;
7
7
  window.dispatchEvent(new Event('scroll'));
8
8
  };
9
9
 
@@ -11,8 +11,8 @@ export function useScroll(): Scroll {
11
11
  const [scroll, setScroll] = useState<Scroll>({ left: 0, top: 0 });
12
12
 
13
13
  const onScroll = () => {
14
- const left = window.pageXOffset;
15
- const top = window.pageYOffset;
14
+ const left = window.scrollX;
15
+ const top = window.scrollY;
16
16
  if (scroll.left !== left || scroll.top !== top) {
17
17
  setScroll({ left, top });
18
18
  }
@@ -77,8 +77,8 @@ describe('useScrollTo', () => {
77
77
  left: 0,
78
78
  }) as any);
79
79
  scrollTo = jest.spyOn(window, 'scrollTo').mockImplementation((left: number, top: number) => {
80
- window.pageXOffset = left;
81
- window.pageYOffset = top;
80
+ window.scrollX = left;
81
+ window.scrollY = top;
82
82
  });
83
83
  });
84
84
 
@@ -93,13 +93,13 @@ describe('useScrollTo', () => {
93
93
 
94
94
  it('should work correctly', async () => {
95
95
  render(<Wrapper />);
96
- expect(window.pageYOffset).toBe(0);
96
+ expect(window.scrollY).toBe(0);
97
97
  const trigger = screen.getByTestId('trigger');
98
98
  await userEvent.click(trigger);
99
99
  expect(scrollTo).toBeCalled();
100
100
  expect(scrollTo).toHaveBeenCalledTimes(2);
101
101
  expect(scrollTo).toHaveBeenCalledWith(0, 940);
102
- expect(window.pageYOffset).toBe(940);
102
+ expect(window.scrollY).toBe(940);
103
103
  });
104
104
 
105
105
  });
@@ -26,12 +26,12 @@ export function scrollToSelector(selector?: string, offset: number = 0) {
26
26
  }
27
27
 
28
28
  export function scrollToRelativeY(y: number = 0, offset: number = 0) {
29
- const to = window.pageYOffset + y - 60 + offset;
29
+ const to = window.scrollY + y - 60 + offset;
30
30
  return scrollToY(to);
31
31
  }
32
32
 
33
33
  export function scrollToY(y: number = 0) {
34
- const from = window.pageYOffset;
34
+ const from = window.scrollY;
35
35
  const to = y;
36
36
  const duration = Math.sqrt(Math.abs(to - from) / 4000);
37
37
  animate(from, to, {
@@ -0,0 +1,34 @@
1
+ // readme https://testing-library.com/
2
+ import { act, renderHook } from '@testing-library/react';
3
+ import { useScrolled } from './useScrolled';
4
+
5
+ const windowScroll = (scrollTop: number): void => {
6
+ window.scrollY = scrollTop;
7
+ window.dispatchEvent(new Event('scroll'));
8
+ };
9
+
10
+ const wrapper = (props: { children: React.ReactNode }) => (
11
+ <div data-testid="test" style={{ height: '2000px' }}>{props.children}</div>
12
+ );
13
+
14
+ describe('useScrolled', () => {
15
+
16
+ it('should work correctly', () => {
17
+ const { result } = renderHook(() => useScrolled(), { wrapper });
18
+ expect(result.current).toStrictEqual(false);
19
+ act(() => {
20
+ windowScroll(100);
21
+ });
22
+ expect(result.current).toStrictEqual(true);
23
+ });
24
+
25
+ it('should return false', () => {
26
+ const { result } = renderHook(() => useScrolled((top, left) => top > 200), { wrapper });
27
+ expect(result.current).toStrictEqual(false);
28
+ act(() => {
29
+ windowScroll(100);
30
+ });
31
+ expect(result.current).toStrictEqual(false);
32
+ });
33
+
34
+ });
@@ -0,0 +1,28 @@
1
+ import { useState } from 'react';
2
+ import { useEventListener } from '../useEventListener/useEventListener';
3
+ import { useIsomorphicLayoutEffect } from '../useIsomorphicLayoutEffect/useIsomorphicLayoutEffect';
4
+
5
+ const DEFAULT_CALLBACK = (top: number, left: number) => {
6
+ return top > 0;
7
+ };
8
+
9
+ export function useScrolled(callback: (top: number, left: number) => boolean = DEFAULT_CALLBACK): boolean {
10
+ const [scrolled, setScrolled] = useState<boolean>(false);
11
+
12
+ const onScrolled = () => {
13
+ const scrolled_ = callback(window.scrollY, window.scrollX);
14
+ if (scrolled !== scrolled_) {
15
+ setScrolled(scrolled_);
16
+ }
17
+ };
18
+
19
+ useEventListener('scroll', onScrolled);
20
+
21
+ // Set size at the first client-side load
22
+ useIsomorphicLayoutEffect(() => {
23
+ onScrolled();
24
+ // eslint-disable-next-line react-hooks/exhaustive-deps
25
+ }, []);
26
+
27
+ return scrolled;
28
+ }
@@ -1,10 +1,11 @@
1
1
  import { renderHook } from '@testing-library/react';
2
+ import { ILayout } from '@websolutespa/bom-core';
2
3
  import { LayoutDefaults } from '@websolutespa/bom-mixer-mock';
3
4
  import { LayoutProvider } from '../useLayout/useLayout';
4
5
  import { useUnit } from './useUnit';
5
6
 
6
7
  const wrapper = (props: { children: React.ReactNode }) => (
7
- <LayoutProvider layout={LayoutDefaults}>{props.children}</LayoutProvider>
8
+ <LayoutProvider layout={LayoutDefaults as ILayout}>{props.children}</LayoutProvider>
8
9
  );
9
10
 
10
11
  describe('useUnit', () => {