@websolutespa/bom-mixer-hooks 1.2.1 → 1.3.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,12 @@
1
1
  # @websolutespa/bom-mixer-hooks
2
2
 
3
+ ## 1.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Added: useSearchParamsQs.
8
+ - Modified: useSearchParamsEncoded, useSearchParams, useScrollTo.
9
+
3
10
  ## 1.2.1
4
11
 
5
12
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -252,7 +252,7 @@ declare function useGeolocation(options?: PositionOptions): GeoLocationSensorSta
252
252
 
253
253
  declare function useIdle(delay?: number, immediate?: boolean): boolean;
254
254
 
255
- declare function useInfiniteLoader(items: any[], perPage?: number, delayInMs?: number): [any[], () => void, boolean];
255
+ declare function useInfiniteLoader<T = any>(items: T[], perPage?: number, delayInMs?: number): [T[], () => void, boolean];
256
256
 
257
257
  declare const useIsomorphicLayoutEffect: typeof useEffect;
258
258
 
@@ -461,7 +461,6 @@ declare function scrollToY(y?: number): void;
461
461
 
462
462
  declare function useScrolled(callback?: (top: number, left: number) => boolean): boolean;
463
463
 
464
- declare const isBrowser: boolean;
465
464
  declare function getSearchParams(url: string, key?: string): IParams | string | null;
466
465
  declare function updateSearchParams(currentPath: string, params: IParams): {
467
466
  pathname: string;
@@ -473,21 +472,20 @@ declare function replaceSearchParams(router: NextRouter, params: IParams): void;
473
472
  declare function pushSearchParams(router: NextRouter, params: IParams): void;
474
473
  declare function replaceSearchParamsSilently(params: IParams): void;
475
474
  declare function useSearchParams(): IUseSearchParamsResult;
476
- declare function useSearchParamsValue(key: string): IUseSearchParamsValueResult;
477
- type IUseSearchParamsResult = {
478
- params: IParams;
479
- replaceParamsSilently: (params: IParams) => void;
480
- replaceParams: (params: IParams) => void;
475
+ type IParams = {
476
+ [key: string]: string;
481
477
  };
482
478
  type IUseSearchParamsValueResult = {
483
479
  params: string | null;
484
480
  replaceParamsSilently: (params: IParams) => void;
485
481
  };
486
- type IParams = {
487
- [key: string]: string;
482
+ type IUseSearchParamsResult = {
483
+ params: IParams;
484
+ replaceParamsSilently: (params: IParams) => void;
485
+ replaceParams: (params: IParams) => void;
488
486
  };
487
+ declare function useSearchParamsValue(key: string): IUseSearchParamsValueResult;
489
488
 
490
- declare function decode(encoded: string | null | undefined, key?: string): IParamsEncoded;
491
489
  declare function getSearchParamsEncoded(url: string, key?: string): {} | null;
492
490
  declare function updateSearchParamsEncoded(currentPath: string, value: IParamsEncoded, key?: string): {
493
491
  pathname: string;
@@ -498,15 +496,33 @@ declare function updateSearchParamsEncoded(currentPath: string, value: IParamsEn
498
496
  declare function replaceSearchParamsEncoded(router: NextRouter, value: IParamsEncoded, key?: string): void;
499
497
  declare function pushSearchParamsEncoded(router: NextRouter, value: IParamsEncoded, key?: string): void;
500
498
  declare function replaceSearchParamsEncodedSilently(value: IParamsEncoded, key?: string): void;
501
- declare function useSearchParamsEncoded(key?: string): IUseSearchParamsEncodedResult;
499
+ type IParamsEncoded = {
500
+ [key: string]: any;
501
+ } | null;
502
502
  type IUseSearchParamsEncodedResult = {
503
503
  params: IParamsEncoded;
504
504
  replaceParamsSilently: (params: IParamsEncoded) => void;
505
505
  replaceParams: (params: IParamsEncoded) => void;
506
506
  };
507
- type IParamsEncoded = {
508
- [key: string]: any;
509
- } | null;
507
+ declare function useSearchParamsEncoded(key?: string): IUseSearchParamsEncodedResult;
508
+
509
+ declare function getSearchParamsQs(url: string, key?: string): {} | null;
510
+ declare function updateSearchParamsQs(currentPath: string, value: IParamsQs, key?: string): {
511
+ pathname: string;
512
+ query: {
513
+ [key: string]: string;
514
+ };
515
+ };
516
+ declare function replaceSearchParamsQs(router: NextRouter, value: IParamsQs, key?: string): void;
517
+ declare function pushSearchParamsQs(router: NextRouter, value: IParamsQs, key?: string): void;
518
+ declare function replaceSearchParamsQsSilently(value: IParamsQs, key?: string): void;
519
+ type IParamsQs = {};
520
+ type IUseSearchParamsQsResult = {
521
+ params: Record<string, any> | null;
522
+ replaceParamsSilently: (params: IParamsQs) => void;
523
+ replaceParams: (params: IParamsQs) => void;
524
+ };
525
+ declare function useSearchParamsQs(key?: string): IUseSearchParamsQsResult;
510
526
 
511
527
  type Sorting<T> = {
512
528
  items: T[];
@@ -555,4 +571,4 @@ type WindowSize = {
555
571
  };
556
572
  declare function useWindowSize(): WindowSize;
557
573
 
558
- 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, LabelService, 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, parseLabel, 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 };
574
+ export { BodyScrollOptions, CartContext, CartProvider, CheckoutContext, CheckoutProvider, ClickOutGetContainer, CurrentStateType, ElementStackItem, Filter, FilterMode, FilterParams, FilterValues, GeoLocationSensorState, IFilter, IFilterOption, IGeolocationPositionError, ILabelContext, ILayoutContext, IPageContext, IPaginationInfo, IParams, IParamsEncoded, IParamsQs, IUseSearchParamsEncodedResult, IUseSearchParamsQsResult, IUseSearchParamsResult, IUseSearchParamsValueResult, KeyCode, KeyMod, KeyboardOptions, KeyboardResult, LabelProvider, LabelService, LayoutProvider, PageProvider, SSRState, SizeResult, SizeType, Sorting, UIReducer, UIValue, UseFiltersResultType, UseKeyboard, UseKeyboardHandler, createElementWithId, createGenericContext, detectIsBrowser, filtersToParams, getCurrentPosition, getFilteredItems, getFilters, getOwnerPaddingRight, getOwnerScrollbarWidth, getPagedItems, getRealSize, getSearchParams, getSearchParamsEncoded, getSearchParamsQs, getUID, hasGeolocation, parseLabel, parseParams, pushSearchParams, pushSearchParamsEncoded, pushSearchParamsQs, replaceSearchParams, replaceSearchParamsEncoded, replaceSearchParamsEncodedSilently, replaceSearchParamsQs, replaceSearchParamsQsSilently, replaceSearchParamsSilently, scrollToRelativeY, scrollToSelector, scrollToY, setFilters, updateSearchParams, updateSearchParamsEncoded, updateSearchParamsQs, 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, useSearchParamsQs, useSearchParamsValue, useSorting, useSwiperIndex, useSyncedRef, useUI, useUnit, useUnmountEffect, useUser, useWindowSize };
package/dist/index.js CHANGED
@@ -83,7 +83,6 @@ __export(src_exports, {
83
83
  PageProvider: () => PageProvider,
84
84
  createElementWithId: () => createElementWithId,
85
85
  createGenericContext: () => createGenericContext,
86
- decode: () => decode,
87
86
  detectIsBrowser: () => detectIsBrowser,
88
87
  filtersToParams: () => filtersToParams,
89
88
  getCurrentPosition: () => getCurrentPosition,
@@ -95,16 +94,19 @@ __export(src_exports, {
95
94
  getRealSize: () => getRealSize,
96
95
  getSearchParams: () => getSearchParams,
97
96
  getSearchParamsEncoded: () => getSearchParamsEncoded,
97
+ getSearchParamsQs: () => getSearchParamsQs,
98
98
  getUID: () => getUID,
99
99
  hasGeolocation: () => hasGeolocation,
100
- isBrowser: () => isBrowser,
101
100
  parseLabel: () => parseLabel,
102
101
  parseParams: () => parseParams,
103
102
  pushSearchParams: () => pushSearchParams,
104
103
  pushSearchParamsEncoded: () => pushSearchParamsEncoded,
104
+ pushSearchParamsQs: () => pushSearchParamsQs,
105
105
  replaceSearchParams: () => replaceSearchParams,
106
106
  replaceSearchParamsEncoded: () => replaceSearchParamsEncoded,
107
107
  replaceSearchParamsEncodedSilently: () => replaceSearchParamsEncodedSilently,
108
+ replaceSearchParamsQs: () => replaceSearchParamsQs,
109
+ replaceSearchParamsQsSilently: () => replaceSearchParamsQsSilently,
108
110
  replaceSearchParamsSilently: () => replaceSearchParamsSilently,
109
111
  scrollToRelativeY: () => scrollToRelativeY,
110
112
  scrollToSelector: () => scrollToSelector,
@@ -112,6 +114,7 @@ __export(src_exports, {
112
114
  setFilters: () => setFilters,
113
115
  updateSearchParams: () => updateSearchParams,
114
116
  updateSearchParamsEncoded: () => updateSearchParamsEncoded,
117
+ updateSearchParamsQs: () => updateSearchParamsQs,
115
118
  useApi: () => useApi,
116
119
  useApiDelete: () => useApiDelete,
117
120
  useApiFetch: () => useApiFetch,
@@ -158,6 +161,7 @@ __export(src_exports, {
158
161
  useScrolled: () => useScrolled,
159
162
  useSearchParams: () => useSearchParams,
160
163
  useSearchParamsEncoded: () => useSearchParamsEncoded,
164
+ useSearchParamsQs: () => useSearchParamsQs,
161
165
  useSearchParamsValue: () => useSearchParamsValue,
162
166
  useSorting: () => useSorting,
163
167
  useSwiperIndex: () => useSwiperIndex,
@@ -334,8 +338,9 @@ var import_react6 = require("react");
334
338
  var import_react5 = require("react");
335
339
 
336
340
  // src/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts
341
+ var import_bom_core2 = require("@websolutespa/bom-core");
337
342
  var import_react4 = require("react");
338
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? import_react4.useLayoutEffect : import_react4.useEffect;
343
+ var useIsomorphicLayoutEffect = import_bom_core2.isBrowser ? import_react4.useLayoutEffect : import_react4.useEffect;
339
344
 
340
345
  // src/useEventListener/useEventListener.ts
341
346
  function useEventListener_(eventName, handler, element, options) {
@@ -1458,9 +1463,9 @@ function usePagination($items, $page = 1, $perPage = 15) {
1458
1463
  var import_react27 = require("react");
1459
1464
  var namespace = "theme";
1460
1465
  function usePortal(name = getUID(), getContainer) {
1461
- const { isBrowser: isBrowser2 } = useSSR();
1466
+ const { isBrowser: isBrowser6 } = useSSR();
1462
1467
  const id = `${namespace}-${name}`;
1463
- const [portal, setPortal] = (0, import_react27.useState)(isBrowser2 ? createElementWithId(id) : null);
1468
+ const [portal, setPortal] = (0, import_react27.useState)(isBrowser6 ? createElementWithId(id) : null);
1464
1469
  (0, import_react27.useEffect)(() => {
1465
1470
  const container = typeof getContainer === "function" ? getContainer() : null;
1466
1471
  const parentElement = container || document.body;
@@ -1552,6 +1557,7 @@ function useScroll() {
1552
1557
  }
1553
1558
 
1554
1559
  // src/useScrollTo/useScrollTo.ts
1560
+ var import_bom_core3 = require("@websolutespa/bom-core");
1555
1561
  var import_framer_motion = require("framer-motion");
1556
1562
  function useScrollTo(offset = 0) {
1557
1563
  const scrollToHash = (event) => {
@@ -1564,7 +1570,7 @@ function useScrollTo(offset = 0) {
1564
1570
  return scrollToHash;
1565
1571
  }
1566
1572
  function scrollToSelector(selector, offset = 0) {
1567
- if (selector && typeof window !== "undefined") {
1573
+ if (selector && import_bom_core3.isBrowser) {
1568
1574
  const element = document.querySelector(selector);
1569
1575
  if (element) {
1570
1576
  const rect = element.getBoundingClientRect();
@@ -1607,9 +1613,9 @@ function useScrolled(callback = DEFAULT_CALLBACK) {
1607
1613
  }
1608
1614
 
1609
1615
  // src/useSearchParams/useSearchParams.ts
1616
+ var import_bom_core4 = require("@websolutespa/bom-core");
1610
1617
  var import_router = require("next/router");
1611
1618
  var import_react32 = require("react");
1612
- var isBrowser = typeof window !== "undefined";
1613
1619
  function replace_(params) {
1614
1620
  if (window.history) {
1615
1621
  const title = document.title;
@@ -1660,7 +1666,7 @@ function pushSearchParams(router, params) {
1660
1666
  router.push({ pathname, query });
1661
1667
  }
1662
1668
  function replaceSearchParamsSilently(params) {
1663
- if (isBrowser) {
1669
+ if (import_bom_core4.isBrowser) {
1664
1670
  const searchParams = serialize_(window.location.search, params);
1665
1671
  replace_(searchParams);
1666
1672
  }
@@ -1696,18 +1702,19 @@ function useSearchParamsValue(key) {
1696
1702
  }
1697
1703
 
1698
1704
  // src/useSearchParamsEncoded/useSearchParamsEncoded.ts
1705
+ var import_bom_core5 = require("@websolutespa/bom-core");
1699
1706
  var import_router2 = require("next/router");
1700
1707
  var import_react33 = require("react");
1701
1708
  var USE_ENCRYPTION = true;
1702
1709
  function base64ToString(base64) {
1703
1710
  if (!USE_ENCRYPTION)
1704
1711
  return base64;
1705
- return isBrowser ? window.atob(base64) : Buffer.from(base64, "base64").toString();
1712
+ return import_bom_core5.isBrowser ? window.atob(base64) : Buffer.from(base64, "base64").toString();
1706
1713
  }
1707
1714
  function stringToBase64(text) {
1708
1715
  if (!USE_ENCRYPTION)
1709
1716
  return text;
1710
- return isBrowser ? window.btoa(text) : Buffer.from(text).toString("base64");
1717
+ return import_bom_core5.isBrowser ? window.btoa(text) : Buffer.from(text).toString("base64");
1711
1718
  }
1712
1719
  function stringToURLSearchParams(url) {
1713
1720
  return new URLSearchParams(url);
@@ -1796,7 +1803,7 @@ function pushSearchParamsEncoded(router, value, key) {
1796
1803
  router.push({ pathname, query });
1797
1804
  }
1798
1805
  function replaceSearchParamsEncodedSilently(value, key) {
1799
- if (isBrowser) {
1806
+ if (import_bom_core5.isBrowser) {
1800
1807
  const searchParams = serialize_2(window.location.search, value, key);
1801
1808
  replace_2(searchParams);
1802
1809
  }
@@ -1817,13 +1824,123 @@ function useSearchParamsEncoded(key) {
1817
1824
  return { params, replaceParamsSilently, replaceParams };
1818
1825
  }
1819
1826
 
1820
- // src/useSorting/useSorting.ts
1827
+ // src/useSearchParamsQs/useSearchParamsQs.ts
1828
+ var import_bom_core6 = require("@websolutespa/bom-core");
1829
+ var import_router3 = require("next/router");
1821
1830
  var import_react34 = require("react");
1831
+ function decode2(encoded, key) {
1832
+ let decoded = null;
1833
+ if (encoded) {
1834
+ decoded = (0, import_bom_core6.qsDeserializeRaw)(encoded);
1835
+ }
1836
+ if (key && decoded) {
1837
+ decoded = decoded[key];
1838
+ }
1839
+ return decoded || null;
1840
+ }
1841
+ function encode2(params, value, key) {
1842
+ if (key) {
1843
+ params = __spreadProps(__spreadValues({}, params), { [key]: value });
1844
+ } else if (typeof value === "object") {
1845
+ params = __spreadValues(__spreadValues({}, params), value);
1846
+ } else {
1847
+ params = __spreadValues({}, params);
1848
+ }
1849
+ const encoded = (0, import_bom_core6.qsSerializeRaw)(params);
1850
+ return encoded;
1851
+ }
1852
+ function stringToURLSearchParams2(url) {
1853
+ return new URLSearchParams(url);
1854
+ }
1855
+ function getURLSearchParams2(url, key) {
1856
+ const params = stringToURLSearchParams2(url);
1857
+ return params.get(key);
1858
+ }
1859
+ function setURLSearchParams2(url, keyOrValue, value) {
1860
+ const params = stringToURLSearchParams2(url);
1861
+ if (value != null) {
1862
+ params.set(keyOrValue, value);
1863
+ } else {
1864
+ params.set(keyOrValue, "");
1865
+ }
1866
+ return params;
1867
+ }
1868
+ function replace_3(params) {
1869
+ if (window.history) {
1870
+ const title = document.title;
1871
+ const url = `${window.location.href.split("?")[0]}?${params.toString()}`;
1872
+ window.history.replaceState(params.toString(), title, url);
1873
+ }
1874
+ }
1875
+ function deserialize_3(url, key) {
1876
+ const encoded = getURLSearchParams2(url, "params");
1877
+ return decode2(encoded, key);
1878
+ }
1879
+ function serialize_3(url, value, key) {
1880
+ const params = deserialize_3(url);
1881
+ const encoded = encode2(params, value, key);
1882
+ return setURLSearchParams2(url, "params", encoded);
1883
+ }
1884
+ function searchParamsToObject_3(params) {
1885
+ const entries = params.entries();
1886
+ const result = {};
1887
+ for (const [key, value] of entries) {
1888
+ result[key] = value;
1889
+ }
1890
+ return result;
1891
+ }
1892
+ function getSearchParamsQs(url, key) {
1893
+ const components = url.split("?");
1894
+ const search = components[1] || "";
1895
+ const searchParams = new URLSearchParams(search);
1896
+ const params = searchParams.get("params");
1897
+ const value = params ? decode2(params, key) : null;
1898
+ return value;
1899
+ }
1900
+ function updateSearchParamsQs(currentPath, value, key) {
1901
+ const components = currentPath.split("?");
1902
+ const searchParams = serialize_3(components[1] || "", value, key);
1903
+ const query = searchParamsToObject_3(searchParams);
1904
+ const pathname = components[0] || "";
1905
+ return { pathname, query };
1906
+ }
1907
+ function replaceSearchParamsQs(router, value, key) {
1908
+ const { pathname, query } = updateSearchParamsQs(router.asPath, value, key);
1909
+ router.replace({ pathname, query });
1910
+ }
1911
+ function pushSearchParamsQs(router, value, key) {
1912
+ const { pathname, query } = updateSearchParamsQs(router.asPath, value, key);
1913
+ router.push({ pathname, query });
1914
+ }
1915
+ function replaceSearchParamsQsSilently(value, key) {
1916
+ if (import_bom_core6.isBrowser) {
1917
+ const searchParams = serialize_3(window.location.search, value, key);
1918
+ replace_3(searchParams);
1919
+ }
1920
+ }
1921
+ function useSearchParamsQs(key) {
1922
+ const router = (0, import_router3.useRouter)();
1923
+ const initialValue = (0, import_react34.useMemo)(() => {
1924
+ const value = getSearchParamsQs(router.asPath, key);
1925
+ return value;
1926
+ }, [key, router.asPath]);
1927
+ const params = initialValue;
1928
+ const replaceParamsSilently = (0, import_react34.useCallback)((params2) => {
1929
+ replaceSearchParamsQsSilently(params2, key);
1930
+ }, [key]);
1931
+ const replaceParams = (0, import_react34.useCallback)((params2) => {
1932
+ replaceSearchParamsQs(router, params2, key);
1933
+ }, [key, router]);
1934
+ return { params, replaceParamsSilently, replaceParams };
1935
+ }
1936
+
1937
+ // src/useSorting/useSorting.ts
1938
+ var import_react35 = require("react");
1822
1939
  function useSorting(items_, callback_, sort_) {
1823
- const [sort, setSort] = (0, import_react34.useState)(sort_);
1824
- const [items, setItems] = (0, import_react34.useState)(callback_(items_.slice(), sort));
1825
- const isInitialMount = (0, import_react34.useRef)(true);
1826
- (0, import_react34.useEffect)(() => {
1940
+ const [sort, setSort] = (0, import_react35.useState)(sort_);
1941
+ const [items, setItems] = (0, import_react35.useState)(callback_(items_.slice(), sort));
1942
+ const isInitialMount = (0, import_react35.useRef)(true);
1943
+ (0, import_react35.useEffect)(() => {
1827
1944
  if (isInitialMount.current) {
1828
1945
  isInitialMount.current = false;
1829
1946
  } else {
@@ -1839,18 +1956,18 @@ function useSorting(items_, callback_, sort_) {
1839
1956
  }
1840
1957
 
1841
1958
  // src/useSwiperIndex/useSwiperIndex.ts
1842
- var import_react35 = require("react");
1843
- var import_react36 = require("swiper/react");
1959
+ var import_react36 = require("react");
1960
+ var import_react37 = require("swiper/react");
1844
1961
  function useSwiperIndex() {
1845
- const swiper = (0, import_react36.useSwiper)();
1846
- const [index, setIndex] = (0, import_react35.useState)(swiper.realIndex);
1847
- const slideTo = (0, import_react35.useCallback)((index2) => {
1962
+ const swiper = (0, import_react37.useSwiper)();
1963
+ const [index, setIndex] = (0, import_react36.useState)(swiper.realIndex);
1964
+ const slideTo = (0, import_react36.useCallback)((index2) => {
1848
1965
  swiper.slideTo(index2);
1849
1966
  }, [swiper]);
1850
1967
  const onSlideChange = (swiper2) => {
1851
1968
  setIndex(swiper2.realIndex);
1852
1969
  };
1853
- (0, import_react35.useEffect)(() => {
1970
+ (0, import_react36.useEffect)(() => {
1854
1971
  if (swiper) {
1855
1972
  swiper.on("slideChange", onSlideChange);
1856
1973
  }
@@ -1864,11 +1981,11 @@ function useSwiperIndex() {
1864
1981
  }
1865
1982
 
1866
1983
  // src/useSyncedRef/useSyncedRef.ts
1867
- var import_react37 = require("react");
1984
+ var import_react38 = require("react");
1868
1985
  function useSyncedRef(value) {
1869
- const ref = (0, import_react37.useRef)(value);
1986
+ const ref = (0, import_react38.useRef)(value);
1870
1987
  ref.current = value;
1871
- return (0, import_react37.useMemo)(() => Object.freeze({
1988
+ return (0, import_react38.useMemo)(() => Object.freeze({
1872
1989
  get current() {
1873
1990
  return ref.current;
1874
1991
  }
@@ -1881,10 +1998,10 @@ function useUnit(unit = "kilometer", locale) {
1881
1998
  }
1882
1999
 
1883
2000
  // src/useUnmountEffect/useUnmountEffect.ts
1884
- var import_react38 = require("react");
2001
+ var import_react39 = require("react");
1885
2002
  function useUnmountEffect(effect) {
1886
2003
  const effectRef = useSyncedRef(effect);
1887
- (0, import_react38.useEffect)(() => () => {
2004
+ (0, import_react39.useEffect)(() => () => {
1888
2005
  effectRef.current();
1889
2006
  }, []);
1890
2007
  }
@@ -1912,7 +2029,6 @@ var useUser = (0, import_zustand4.create)((set) => ({
1912
2029
  PageProvider,
1913
2030
  createElementWithId,
1914
2031
  createGenericContext,
1915
- decode,
1916
2032
  detectIsBrowser,
1917
2033
  filtersToParams,
1918
2034
  getCurrentPosition,
@@ -1924,16 +2040,19 @@ var useUser = (0, import_zustand4.create)((set) => ({
1924
2040
  getRealSize,
1925
2041
  getSearchParams,
1926
2042
  getSearchParamsEncoded,
2043
+ getSearchParamsQs,
1927
2044
  getUID,
1928
2045
  hasGeolocation,
1929
- isBrowser,
1930
2046
  parseLabel,
1931
2047
  parseParams,
1932
2048
  pushSearchParams,
1933
2049
  pushSearchParamsEncoded,
2050
+ pushSearchParamsQs,
1934
2051
  replaceSearchParams,
1935
2052
  replaceSearchParamsEncoded,
1936
2053
  replaceSearchParamsEncodedSilently,
2054
+ replaceSearchParamsQs,
2055
+ replaceSearchParamsQsSilently,
1937
2056
  replaceSearchParamsSilently,
1938
2057
  scrollToRelativeY,
1939
2058
  scrollToSelector,
@@ -1941,6 +2060,7 @@ var useUser = (0, import_zustand4.create)((set) => ({
1941
2060
  setFilters,
1942
2061
  updateSearchParams,
1943
2062
  updateSearchParamsEncoded,
2063
+ updateSearchParamsQs,
1944
2064
  useApi,
1945
2065
  useApiDelete,
1946
2066
  useApiFetch,
@@ -1987,6 +2107,7 @@ var useUser = (0, import_zustand4.create)((set) => ({
1987
2107
  useScrolled,
1988
2108
  useSearchParams,
1989
2109
  useSearchParamsEncoded,
2110
+ useSearchParamsQs,
1990
2111
  useSearchParamsValue,
1991
2112
  useSorting,
1992
2113
  useSwiperIndex,
package/dist/index.mjs CHANGED
@@ -214,8 +214,9 @@ import { useState as useState3 } from "react";
214
214
  import { useEffect as useEffect4, useRef as useRef2 } from "react";
215
215
 
216
216
  // src/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts
217
+ import { isBrowser } from "@websolutespa/bom-core";
217
218
  import { useEffect as useEffect3, useLayoutEffect } from "react";
218
- var useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect3;
219
+ var useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect3;
219
220
 
220
221
  // src/useEventListener/useEventListener.ts
221
222
  function useEventListener_(eventName, handler, element, options) {
@@ -1338,9 +1339,9 @@ function usePagination($items, $page = 1, $perPage = 15) {
1338
1339
  import { useEffect as useEffect19, useState as useState14 } from "react";
1339
1340
  var namespace = "theme";
1340
1341
  function usePortal(name = getUID(), getContainer) {
1341
- const { isBrowser: isBrowser2 } = useSSR();
1342
+ const { isBrowser: isBrowser6 } = useSSR();
1342
1343
  const id = `${namespace}-${name}`;
1343
- const [portal, setPortal] = useState14(isBrowser2 ? createElementWithId(id) : null);
1344
+ const [portal, setPortal] = useState14(isBrowser6 ? createElementWithId(id) : null);
1344
1345
  useEffect19(() => {
1345
1346
  const container = typeof getContainer === "function" ? getContainer() : null;
1346
1347
  const parentElement = container || document.body;
@@ -1432,6 +1433,7 @@ function useScroll() {
1432
1433
  }
1433
1434
 
1434
1435
  // src/useScrollTo/useScrollTo.ts
1436
+ import { isBrowser as isBrowser2 } from "@websolutespa/bom-core";
1435
1437
  import { animate } from "framer-motion";
1436
1438
  function useScrollTo(offset = 0) {
1437
1439
  const scrollToHash = (event) => {
@@ -1444,7 +1446,7 @@ function useScrollTo(offset = 0) {
1444
1446
  return scrollToHash;
1445
1447
  }
1446
1448
  function scrollToSelector(selector, offset = 0) {
1447
- if (selector && typeof window !== "undefined") {
1449
+ if (selector && isBrowser2) {
1448
1450
  const element = document.querySelector(selector);
1449
1451
  if (element) {
1450
1452
  const rect = element.getBoundingClientRect();
@@ -1487,9 +1489,9 @@ function useScrolled(callback = DEFAULT_CALLBACK) {
1487
1489
  }
1488
1490
 
1489
1491
  // src/useSearchParams/useSearchParams.ts
1492
+ import { isBrowser as isBrowser3 } from "@websolutespa/bom-core";
1490
1493
  import { useRouter } from "next/router";
1491
1494
  import { useCallback as useCallback4, useMemo as useMemo5 } from "react";
1492
- var isBrowser = typeof window !== "undefined";
1493
1495
  function replace_(params) {
1494
1496
  if (window.history) {
1495
1497
  const title = document.title;
@@ -1540,7 +1542,7 @@ function pushSearchParams(router, params) {
1540
1542
  router.push({ pathname, query });
1541
1543
  }
1542
1544
  function replaceSearchParamsSilently(params) {
1543
- if (isBrowser) {
1545
+ if (isBrowser3) {
1544
1546
  const searchParams = serialize_(window.location.search, params);
1545
1547
  replace_(searchParams);
1546
1548
  }
@@ -1576,18 +1578,19 @@ function useSearchParamsValue(key) {
1576
1578
  }
1577
1579
 
1578
1580
  // src/useSearchParamsEncoded/useSearchParamsEncoded.ts
1581
+ import { isBrowser as isBrowser4 } from "@websolutespa/bom-core";
1579
1582
  import { useRouter as useRouter2 } from "next/router";
1580
1583
  import { useCallback as useCallback5, useMemo as useMemo6 } from "react";
1581
1584
  var USE_ENCRYPTION = true;
1582
1585
  function base64ToString(base64) {
1583
1586
  if (!USE_ENCRYPTION)
1584
1587
  return base64;
1585
- return isBrowser ? window.atob(base64) : Buffer.from(base64, "base64").toString();
1588
+ return isBrowser4 ? window.atob(base64) : Buffer.from(base64, "base64").toString();
1586
1589
  }
1587
1590
  function stringToBase64(text) {
1588
1591
  if (!USE_ENCRYPTION)
1589
1592
  return text;
1590
- return isBrowser ? window.btoa(text) : Buffer.from(text).toString("base64");
1593
+ return isBrowser4 ? window.btoa(text) : Buffer.from(text).toString("base64");
1591
1594
  }
1592
1595
  function stringToURLSearchParams(url) {
1593
1596
  return new URLSearchParams(url);
@@ -1676,7 +1679,7 @@ function pushSearchParamsEncoded(router, value, key) {
1676
1679
  router.push({ pathname, query });
1677
1680
  }
1678
1681
  function replaceSearchParamsEncodedSilently(value, key) {
1679
- if (isBrowser) {
1682
+ if (isBrowser4) {
1680
1683
  const searchParams = serialize_2(window.location.search, value, key);
1681
1684
  replace_2(searchParams);
1682
1685
  }
@@ -1697,6 +1700,116 @@ function useSearchParamsEncoded(key) {
1697
1700
  return { params, replaceParamsSilently, replaceParams };
1698
1701
  }
1699
1702
 
1703
+ // src/useSearchParamsQs/useSearchParamsQs.ts
1704
+ import { isBrowser as isBrowser5, qsDeserializeRaw, qsSerializeRaw } from "@websolutespa/bom-core";
1705
+ import { useRouter as useRouter3 } from "next/router";
1706
+ import { useCallback as useCallback6, useMemo as useMemo7 } from "react";
1707
+ function decode2(encoded, key) {
1708
+ let decoded = null;
1709
+ if (encoded) {
1710
+ decoded = qsDeserializeRaw(encoded);
1711
+ }
1712
+ if (key && decoded) {
1713
+ decoded = decoded[key];
1714
+ }
1715
+ return decoded || null;
1716
+ }
1717
+ function encode2(params, value, key) {
1718
+ if (key) {
1719
+ params = __spreadProps(__spreadValues({}, params), { [key]: value });
1720
+ } else if (typeof value === "object") {
1721
+ params = __spreadValues(__spreadValues({}, params), value);
1722
+ } else {
1723
+ params = __spreadValues({}, params);
1724
+ }
1725
+ const encoded = qsSerializeRaw(params);
1726
+ return encoded;
1727
+ }
1728
+ function stringToURLSearchParams2(url) {
1729
+ return new URLSearchParams(url);
1730
+ }
1731
+ function getURLSearchParams2(url, key) {
1732
+ const params = stringToURLSearchParams2(url);
1733
+ return params.get(key);
1734
+ }
1735
+ function setURLSearchParams2(url, keyOrValue, value) {
1736
+ const params = stringToURLSearchParams2(url);
1737
+ if (value != null) {
1738
+ params.set(keyOrValue, value);
1739
+ } else {
1740
+ params.set(keyOrValue, "");
1741
+ }
1742
+ return params;
1743
+ }
1744
+ function replace_3(params) {
1745
+ if (window.history) {
1746
+ const title = document.title;
1747
+ const url = `${window.location.href.split("?")[0]}?${params.toString()}`;
1748
+ window.history.replaceState(params.toString(), title, url);
1749
+ }
1750
+ }
1751
+ function deserialize_3(url, key) {
1752
+ const encoded = getURLSearchParams2(url, "params");
1753
+ return decode2(encoded, key);
1754
+ }
1755
+ function serialize_3(url, value, key) {
1756
+ const params = deserialize_3(url);
1757
+ const encoded = encode2(params, value, key);
1758
+ return setURLSearchParams2(url, "params", encoded);
1759
+ }
1760
+ function searchParamsToObject_3(params) {
1761
+ const entries = params.entries();
1762
+ const result = {};
1763
+ for (const [key, value] of entries) {
1764
+ result[key] = value;
1765
+ }
1766
+ return result;
1767
+ }
1768
+ function getSearchParamsQs(url, key) {
1769
+ const components = url.split("?");
1770
+ const search = components[1] || "";
1771
+ const searchParams = new URLSearchParams(search);
1772
+ const params = searchParams.get("params");
1773
+ const value = params ? decode2(params, key) : null;
1774
+ return value;
1775
+ }
1776
+ function updateSearchParamsQs(currentPath, value, key) {
1777
+ const components = currentPath.split("?");
1778
+ const searchParams = serialize_3(components[1] || "", value, key);
1779
+ const query = searchParamsToObject_3(searchParams);
1780
+ const pathname = components[0] || "";
1781
+ return { pathname, query };
1782
+ }
1783
+ function replaceSearchParamsQs(router, value, key) {
1784
+ const { pathname, query } = updateSearchParamsQs(router.asPath, value, key);
1785
+ router.replace({ pathname, query });
1786
+ }
1787
+ function pushSearchParamsQs(router, value, key) {
1788
+ const { pathname, query } = updateSearchParamsQs(router.asPath, value, key);
1789
+ router.push({ pathname, query });
1790
+ }
1791
+ function replaceSearchParamsQsSilently(value, key) {
1792
+ if (isBrowser5) {
1793
+ const searchParams = serialize_3(window.location.search, value, key);
1794
+ replace_3(searchParams);
1795
+ }
1796
+ }
1797
+ function useSearchParamsQs(key) {
1798
+ const router = useRouter3();
1799
+ const initialValue = useMemo7(() => {
1800
+ const value = getSearchParamsQs(router.asPath, key);
1801
+ return value;
1802
+ }, [key, router.asPath]);
1803
+ const params = initialValue;
1804
+ const replaceParamsSilently = useCallback6((params2) => {
1805
+ replaceSearchParamsQsSilently(params2, key);
1806
+ }, [key]);
1807
+ const replaceParams = useCallback6((params2) => {
1808
+ replaceSearchParamsQs(router, params2, key);
1809
+ }, [key, router]);
1810
+ return { params, replaceParamsSilently, replaceParams };
1811
+ }
1812
+
1700
1813
  // src/useSorting/useSorting.ts
1701
1814
  import { useEffect as useEffect22, useRef as useRef11, useState as useState18 } from "react";
1702
1815
  function useSorting(items_, callback_, sort_) {
@@ -1719,12 +1832,12 @@ function useSorting(items_, callback_, sort_) {
1719
1832
  }
1720
1833
 
1721
1834
  // src/useSwiperIndex/useSwiperIndex.ts
1722
- import { useCallback as useCallback6, useEffect as useEffect23, useState as useState19 } from "react";
1835
+ import { useCallback as useCallback7, useEffect as useEffect23, useState as useState19 } from "react";
1723
1836
  import { useSwiper } from "swiper/react";
1724
1837
  function useSwiperIndex() {
1725
1838
  const swiper = useSwiper();
1726
1839
  const [index, setIndex] = useState19(swiper.realIndex);
1727
- const slideTo = useCallback6((index2) => {
1840
+ const slideTo = useCallback7((index2) => {
1728
1841
  swiper.slideTo(index2);
1729
1842
  }, [swiper]);
1730
1843
  const onSlideChange = (swiper2) => {
@@ -1744,11 +1857,11 @@ function useSwiperIndex() {
1744
1857
  }
1745
1858
 
1746
1859
  // src/useSyncedRef/useSyncedRef.ts
1747
- import { useMemo as useMemo7, useRef as useRef12 } from "react";
1860
+ import { useMemo as useMemo8, useRef as useRef12 } from "react";
1748
1861
  function useSyncedRef(value) {
1749
1862
  const ref = useRef12(value);
1750
1863
  ref.current = value;
1751
- return useMemo7(() => Object.freeze({
1864
+ return useMemo8(() => Object.freeze({
1752
1865
  get current() {
1753
1866
  return ref.current;
1754
1867
  }
@@ -1791,7 +1904,6 @@ export {
1791
1904
  PageProvider,
1792
1905
  createElementWithId,
1793
1906
  createGenericContext,
1794
- decode,
1795
1907
  detectIsBrowser,
1796
1908
  filtersToParams,
1797
1909
  getCurrentPosition,
@@ -1803,16 +1915,19 @@ export {
1803
1915
  getRealSize,
1804
1916
  getSearchParams,
1805
1917
  getSearchParamsEncoded,
1918
+ getSearchParamsQs,
1806
1919
  getUID,
1807
1920
  hasGeolocation,
1808
- isBrowser,
1809
1921
  parseLabel,
1810
1922
  parseParams,
1811
1923
  pushSearchParams,
1812
1924
  pushSearchParamsEncoded,
1925
+ pushSearchParamsQs,
1813
1926
  replaceSearchParams,
1814
1927
  replaceSearchParamsEncoded,
1815
1928
  replaceSearchParamsEncodedSilently,
1929
+ replaceSearchParamsQs,
1930
+ replaceSearchParamsQsSilently,
1816
1931
  replaceSearchParamsSilently,
1817
1932
  scrollToRelativeY,
1818
1933
  scrollToSelector,
@@ -1820,6 +1935,7 @@ export {
1820
1935
  setFilters,
1821
1936
  updateSearchParams,
1822
1937
  updateSearchParamsEncoded,
1938
+ updateSearchParamsQs,
1823
1939
  useApi,
1824
1940
  useApiDelete,
1825
1941
  useApiFetch,
@@ -1866,6 +1982,7 @@ export {
1866
1982
  useScrolled,
1867
1983
  useSearchParams,
1868
1984
  useSearchParamsEncoded,
1985
+ useSearchParamsQs,
1869
1986
  useSearchParamsValue,
1870
1987
  useSorting,
1871
1988
  useSwiperIndex,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websolutespa/bom-mixer-hooks",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "Mixer Hooks module of the BOM Repository",
5
5
  "keywords": [
6
6
  "bom",
package/src/index.ts CHANGED
@@ -43,6 +43,7 @@ export * from './useScrollTo/useScrollTo';
43
43
  export * from './useScrolled/useScrolled';
44
44
  export * from './useSearchParams/useSearchParams';
45
45
  export * from './useSearchParamsEncoded/useSearchParamsEncoded';
46
+ export * from './useSearchParamsQs/useSearchParamsQs';
46
47
  export * from './useSorting/useSorting';
47
48
  export * from './useSwiperIndex/useSwiperIndex';
48
49
  export * from './useSyncedRef/useSyncedRef';
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useMemo, useState } from 'react';
2
2
 
3
- export function useInfiniteLoader(items: any[], perPage: number = 12, delayInMs = 100): [any[], () => void, boolean] {
3
+ export function useInfiniteLoader<T = any>(items: T[], perPage: number = 12, delayInMs = 100): [T[], () => void, boolean] {
4
4
 
5
5
  const total = items.length;
6
6
 
@@ -1,3 +1,4 @@
1
+ import { isBrowser } from '@websolutespa/bom-core';
1
2
  import { useEffect, useLayoutEffect } from 'react';
2
3
 
3
- export const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
4
+ export const useIsomorphicLayoutEffect = isBrowser ? useLayoutEffect : useEffect;
@@ -1,3 +1,4 @@
1
+ import { isBrowser } from '@websolutespa/bom-core';
1
2
  import { animate } from 'framer-motion';
2
3
 
3
4
  export function useScrollTo(offset: number = 0): (event: React.MouseEvent<HTMLElement>) => void {
@@ -16,7 +17,7 @@ export function useScrollTo(offset: number = 0): (event: React.MouseEvent<HTMLEl
16
17
  }
17
18
 
18
19
  export function scrollToSelector(selector?: string, offset: number = 0) {
19
- if (selector && typeof window !== 'undefined') {
20
+ if (selector && isBrowser) {
20
21
  const element = document.querySelector(selector);
21
22
  if (element) {
22
23
  const rect = element.getBoundingClientRect();
@@ -1,8 +1,7 @@
1
+ import { isBrowser } from '@websolutespa/bom-core';
1
2
  import { NextRouter, useRouter } from 'next/router';
2
3
  import { useCallback, useMemo } from 'react';
3
4
 
4
- export const isBrowser = typeof window !== 'undefined';
5
-
6
5
  function replace_(params: URLSearchParams) {
7
6
  if (window.history) {
8
7
  const title = document.title;
@@ -91,6 +90,22 @@ export function useSearchParams(): IUseSearchParamsResult {
91
90
  return { params, replaceParamsSilently, replaceParams };
92
91
  }
93
92
 
93
+ export type IParams = {
94
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
+ [key: string]: string;
96
+ };
97
+
98
+ export type IUseSearchParamsValueResult = {
99
+ params: string | null,
100
+ replaceParamsSilently: (params: IParams) => void
101
+ };
102
+
103
+ export type IUseSearchParamsResult = {
104
+ params: IParams,
105
+ replaceParamsSilently: (params: IParams) => void,
106
+ replaceParams: (params: IParams) => void
107
+ };
108
+
94
109
  export function useSearchParamsValue(key: string): IUseSearchParamsValueResult {
95
110
  const router = useRouter();
96
111
 
@@ -108,16 +123,3 @@ export function useSearchParamsValue(key: string): IUseSearchParamsValueResult {
108
123
 
109
124
  return { params, replaceParamsSilently };
110
125
  }
111
-
112
- export type IUseSearchParamsResult = {
113
- params: IParams,
114
- replaceParamsSilently: (params: IParams) => void,
115
- replaceParams: (params: IParams) => void
116
- };
117
-
118
- export type IUseSearchParamsValueResult = { params: string | null, replaceParamsSilently: (params: IParams) => void };
119
-
120
- export type IParams = {
121
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
122
- [key: string]: string;
123
- };
@@ -1,6 +1,6 @@
1
+ import { isBrowser } from '@websolutespa/bom-core';
1
2
  import { NextRouter, useRouter } from 'next/router';
2
3
  import { useCallback, useMemo } from 'react';
3
- import { isBrowser } from '../useSearchParams/useSearchParams';
4
4
 
5
5
  const USE_ENCRYPTION = true;
6
6
 
@@ -89,7 +89,7 @@ function serialize_(url: string, value: IParamsEncoded, key?: string): URLSearch
89
89
  return setURLSearchParams(url, 'params', encoded);
90
90
  }
91
91
 
92
- export function decode(encoded: string | null | undefined, key?: string): IParamsEncoded {
92
+ function decode(encoded: string | null | undefined, key?: string): IParamsEncoded {
93
93
  let decoded = null;
94
94
  if (encoded) {
95
95
  const json = base64ToString(encoded);
@@ -161,6 +161,17 @@ export function replaceSearchParamsEncodedSilently(value: IParamsEncoded, key?:
161
161
  }
162
162
  }
163
163
 
164
+ export type IParamsEncoded = {
165
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
166
+ [key: string]: any;
167
+ } | null;
168
+
169
+ export type IUseSearchParamsEncodedResult = {
170
+ params: IParamsEncoded,
171
+ replaceParamsSilently: (params: IParamsEncoded) => void,
172
+ replaceParams: (params: IParamsEncoded) => void
173
+ };
174
+
164
175
  export function useSearchParamsEncoded(key?: string): IUseSearchParamsEncodedResult {
165
176
  const router = useRouter();
166
177
 
@@ -189,14 +200,3 @@ export function useSearchParamsEncoded(key?: string): IUseSearchParamsEncodedRes
189
200
 
190
201
  return { params, replaceParamsSilently, replaceParams };
191
202
  }
192
-
193
- export type IUseSearchParamsEncodedResult = {
194
- params: IParamsEncoded,
195
- replaceParamsSilently: (params: IParamsEncoded) => void,
196
- replaceParams: (params: IParamsEncoded) => void
197
- };
198
-
199
- export type IParamsEncoded = {
200
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
201
- [key: string]: any;
202
- } | null;
@@ -0,0 +1,80 @@
1
+
2
+ // readme https://testing-library.com/
3
+ import { act, renderHook } from '@testing-library/react';
4
+ import * as nextRouter from 'next/router';
5
+ import { useSearchParamsQs } from './useSearchParamsQs';
6
+
7
+ const useRouter = (nextRouter as any).useRouter = jest.fn();
8
+
9
+ describe('useSearchParamsQs', () => {
10
+
11
+ it('should work correctly', async () => {
12
+ useRouter.mockReturnValue({
13
+ asPath: '',
14
+ });
15
+ const { result } = renderHook(() => useSearchParamsQs());
16
+ expect(result.current.params).toEqual(null);
17
+ });
18
+
19
+ it('should work correctly with params', async () => {
20
+ useRouter.mockReturnValue({
21
+ asPath: '?params=where[market][equals]=ww',
22
+ });
23
+ const params = {
24
+ where: {
25
+ market: {
26
+ equals: 'ww',
27
+ },
28
+ },
29
+ };
30
+ const { result } = renderHook(() => useSearchParamsQs());
31
+ expect(result.current.params).toEqual(params);
32
+ });
33
+
34
+ it('should replace search params silently', async () => {
35
+ useRouter.mockReturnValue({
36
+ asPath: '',
37
+ });
38
+ const params = {
39
+ where: {
40
+ market: {
41
+ equals: 'ww',
42
+ },
43
+ },
44
+ };
45
+ const { result } = renderHook(() => useSearchParamsQs());
46
+ window.history.replaceState = jest.fn();
47
+ expect(result.current.replaceParamsSilently).toEqual(expect.any(Function));
48
+ act(() => result.current.replaceParamsSilently(params));
49
+ expect(window.history.replaceState).toBeCalledWith(
50
+ `params=${encodeURIComponent('where[market][equals]=ww')}`,
51
+ '',
52
+ `http://localhost/?params=${encodeURIComponent('where[market][equals]=ww')}`
53
+ );
54
+ });
55
+
56
+ it('should replace search params', async () => {
57
+ const handler = jest.fn();
58
+ useRouter.mockReturnValue({
59
+ asPath: '',
60
+ replace: handler,
61
+ });
62
+ const params = {
63
+ where: {
64
+ market: {
65
+ equals: 'ww',
66
+ },
67
+ },
68
+ };
69
+ const { result } = renderHook(() => useSearchParamsQs());
70
+ window.history.replaceState = jest.fn();
71
+ expect(result.current.replaceParams).toEqual(expect.any(Function));
72
+ act(() => result.current.replaceParams(params));
73
+ expect(handler).toBeCalledTimes(1);
74
+ expect(handler).toBeCalledWith({
75
+ pathname: '',
76
+ query: { params: 'where[market][equals]=ww' },
77
+ });
78
+ });
79
+
80
+ });
@@ -0,0 +1,136 @@
1
+ import { isBrowser, qsDeserializeRaw, qsSerializeRaw } from '@websolutespa/bom-core';
2
+ import { NextRouter, useRouter } from 'next/router';
3
+ import { useCallback, useMemo } from 'react';
4
+
5
+ function decode(encoded: string | null | undefined, key?: string): IParamsQs {
6
+ let decoded = null;
7
+ if (encoded) {
8
+ decoded = qsDeserializeRaw(encoded);
9
+ }
10
+ if (key && decoded) {
11
+ decoded = (decoded as any)[key];
12
+ }
13
+ return decoded || null;
14
+ }
15
+
16
+ function encode(params: IParamsQs, value: IParamsQs, key?: string) {
17
+ if (key) {
18
+ params = { ...params, [key]: value };
19
+ } else if (typeof value === 'object') {
20
+ params = { ...params, ...value };
21
+ } else {
22
+ params = { ...params };
23
+ }
24
+ const encoded = qsSerializeRaw(params);
25
+ return encoded;
26
+ }
27
+
28
+ function stringToURLSearchParams(url: string): URLSearchParams {
29
+ return new URLSearchParams(url);
30
+ }
31
+
32
+ function getURLSearchParams(url: string, key: string): string | null {
33
+ const params = stringToURLSearchParams(url);
34
+ return params.get(key);
35
+ }
36
+
37
+ function setURLSearchParams(url: string, keyOrValue: string, value: string | null | undefined): URLSearchParams { // !!! any
38
+ const params = stringToURLSearchParams(url);
39
+ if (value != null) {
40
+ params.set(keyOrValue, value);
41
+ } else {
42
+ params.set(keyOrValue, '');
43
+ }
44
+ return params;
45
+ }
46
+
47
+ function replace_(params: URLSearchParams) {
48
+ if (window.history) {
49
+ const title = document.title;
50
+ const url = `${window.location.href.split('?')[0]}?${params.toString()}`;
51
+ window.history.replaceState(params.toString(), title, url);
52
+ }
53
+ }
54
+
55
+ function deserialize_(url: string, key?: string) {
56
+ const encoded = getURLSearchParams(url, 'params');
57
+ return decode(encoded, key);
58
+ }
59
+
60
+ function serialize_(url: string, value: IParamsQs, key?: string): URLSearchParams {
61
+ const params = deserialize_(url);
62
+ const encoded = encode(params, value, key);
63
+ return setURLSearchParams(url, 'params', encoded);
64
+ }
65
+
66
+ function searchParamsToObject_(params: URLSearchParams): { [key: string]: string } {
67
+ const entries = params.entries();
68
+ const result: { [key: string]: string } = {};
69
+ for (const [key, value] of entries) {
70
+ result[key] = value;
71
+ }
72
+ return result;
73
+ }
74
+
75
+ export function getSearchParamsQs(url: string, key?: string): {} | null {
76
+ const components = url.split('?');
77
+ const search = components[1] || '';
78
+ const searchParams = new URLSearchParams(search);
79
+ const params = searchParams.get('params');
80
+ const value = params ? decode(params, key) : null;
81
+ return value;
82
+ }
83
+
84
+ export function updateSearchParamsQs(currentPath: string, value: IParamsQs, key?: string): { pathname: string, query: { [key: string]: string } } {
85
+ const components = currentPath.split('?');
86
+ const searchParams = serialize_(components[1] || '', value, key);
87
+ const query = searchParamsToObject_(searchParams);
88
+ const pathname = components[0] || '';
89
+ return { pathname, query };
90
+ }
91
+
92
+ export function replaceSearchParamsQs(router: NextRouter, value: IParamsQs, key?: string): void {
93
+ const { pathname, query } = updateSearchParamsQs(router.asPath, value, key);
94
+ router.replace({ pathname, query });
95
+ }
96
+
97
+ export function pushSearchParamsQs(router: NextRouter, value: IParamsQs, key?: string): void {
98
+ const { pathname, query } = updateSearchParamsQs(router.asPath, value, key);
99
+ router.push({ pathname, query });
100
+ }
101
+
102
+ export function replaceSearchParamsQsSilently(value: IParamsQs, key?: string): void {
103
+ if (isBrowser) {
104
+ const searchParams = serialize_(window.location.search, value, key);
105
+ replace_(searchParams);
106
+ }
107
+ }
108
+
109
+ export type IParamsQs = {};
110
+
111
+ export type IUseSearchParamsQsResult = {
112
+ params: Record<string, any> | null,
113
+ replaceParamsSilently: (params: IParamsQs) => void,
114
+ replaceParams: (params: IParamsQs) => void
115
+ };
116
+
117
+ export function useSearchParamsQs(key?: string): IUseSearchParamsQsResult {
118
+ const router = useRouter();
119
+
120
+ const initialValue = useMemo(() => {
121
+ const value = getSearchParamsQs(router.asPath, key);
122
+ return value;
123
+ }, [key, router.asPath]);
124
+
125
+ const params = initialValue;
126
+
127
+ const replaceParamsSilently = useCallback((params: IParamsQs) => {
128
+ replaceSearchParamsQsSilently(params, key);
129
+ }, [key]);
130
+
131
+ const replaceParams = useCallback((params: IParamsQs) => {
132
+ replaceSearchParamsQs(router, params, key);
133
+ }, [key, router]);
134
+
135
+ return { params, replaceParamsSilently, replaceParams };
136
+ }