react-simplikit 0.0.47 → 0.0.49

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.
Files changed (57) hide show
  1. package/dist/components/ImpressionArea/index.cjs +7 -4
  2. package/dist/components/Separated/index.cjs +1 -1
  3. package/dist/hooks/useCallbackOncePerRender/index.cjs +6 -3
  4. package/dist/hooks/useDebounce/index.cjs +14 -8
  5. package/dist/hooks/useDebouncedCallback/index.cjs +7 -4
  6. package/dist/hooks/useDoubleClick/index.cjs +6 -3
  7. package/dist/hooks/useImpressionRef/index.cjs +7 -4
  8. package/dist/hooks/useIntersectionObserver/index.cjs +6 -3
  9. package/dist/hooks/useInterval/index.cjs +24 -15
  10. package/dist/hooks/useIsClient/index.cjs +40 -0
  11. package/dist/hooks/useIsClient/index.d.cts +40 -0
  12. package/dist/hooks/useList/index.cjs +104 -0
  13. package/dist/hooks/useList/index.d.cts +50 -0
  14. package/dist/hooks/useLoading/index.cjs +9 -6
  15. package/dist/hooks/useLongPress/index.cjs +6 -3
  16. package/dist/hooks/useOutsideClickEffect/index.cjs +6 -3
  17. package/dist/hooks/usePreservedCallback/index.cjs +6 -3
  18. package/dist/hooks/useRefEffect/index.cjs +6 -3
  19. package/dist/hooks/useRefEffect/index.d.cts +3 -3
  20. package/dist/hooks/useSet/index.cjs +105 -0
  21. package/dist/hooks/useSet/index.d.cts +39 -0
  22. package/dist/hooks/useThrottle/index.cjs +6 -3
  23. package/dist/hooks/useThrottledCallback/index.cjs +172 -0
  24. package/dist/hooks/useThrottledCallback/index.d.cts +30 -0
  25. package/dist/hooks/useTimeout/index.cjs +8 -5
  26. package/dist/hooks/useTimeout/index.d.cts +1 -1
  27. package/dist/index.cjs +252 -96
  28. package/dist/index.d.cts +4 -0
  29. package/esm/components/ImpressionArea/index.js +7 -4
  30. package/esm/components/Separated/index.js +1 -1
  31. package/esm/hooks/useCallbackOncePerRender/index.js +6 -3
  32. package/esm/hooks/useDebounce/index.js +14 -8
  33. package/esm/hooks/useDebouncedCallback/index.js +7 -4
  34. package/esm/hooks/useDoubleClick/index.js +6 -3
  35. package/esm/hooks/useImpressionRef/index.js +7 -4
  36. package/esm/hooks/useIntersectionObserver/index.js +6 -3
  37. package/esm/hooks/useInterval/index.js +24 -15
  38. package/esm/hooks/useIsClient/index.d.ts +40 -0
  39. package/esm/hooks/useIsClient/index.js +14 -0
  40. package/esm/hooks/useList/index.d.ts +50 -0
  41. package/esm/hooks/useList/index.js +78 -0
  42. package/esm/hooks/useLoading/index.js +9 -6
  43. package/esm/hooks/useLongPress/index.js +6 -3
  44. package/esm/hooks/useOutsideClickEffect/index.js +6 -3
  45. package/esm/hooks/usePreservedCallback/index.js +6 -3
  46. package/esm/hooks/useRefEffect/index.d.ts +3 -3
  47. package/esm/hooks/useRefEffect/index.js +6 -3
  48. package/esm/hooks/useSet/index.d.ts +39 -0
  49. package/esm/hooks/useSet/index.js +79 -0
  50. package/esm/hooks/useThrottle/index.js +6 -3
  51. package/esm/hooks/useThrottledCallback/index.d.ts +30 -0
  52. package/esm/hooks/useThrottledCallback/index.js +146 -0
  53. package/esm/hooks/useTimeout/index.d.ts +1 -1
  54. package/esm/hooks/useTimeout/index.js +8 -5
  55. package/esm/index.d.ts +4 -0
  56. package/esm/index.js +222 -70
  57. package/package.json +18 -19
package/dist/index.cjs CHANGED
@@ -41,7 +41,9 @@ __export(index_exports, {
41
41
  useInputState: () => useInputState,
42
42
  useIntersectionObserver: () => useIntersectionObserver,
43
43
  useInterval: () => useInterval,
44
+ useIsClient: () => useIsClient,
44
45
  useIsomorphicLayoutEffect: () => useIsomorphicLayoutEffect,
46
+ useList: () => useList,
45
47
  useLoading: () => useLoading,
46
48
  useLongPress: () => useLongPress,
47
49
  useMap: () => useMap,
@@ -50,8 +52,10 @@ __export(index_exports, {
50
52
  usePreservedReference: () => usePreservedReference,
51
53
  usePrevious: () => usePrevious,
52
54
  useRefEffect: () => useRefEffect,
55
+ useSet: () => useSet,
53
56
  useStorageState: () => useStorageState,
54
57
  useThrottle: () => useThrottle,
58
+ useThrottledCallback: () => useThrottledCallback,
55
59
  useTimeout: () => useTimeout,
56
60
  useToggle: () => useToggle,
57
61
  useVisibilityEvent: () => useVisibilityEvent
@@ -124,9 +128,12 @@ function debounce(func, debounceMs, { edges = ["leading", "trailing"] } = {}) {
124
128
  var import_react = require("react");
125
129
  function usePreservedCallback(callback) {
126
130
  const callbackRef = (0, import_react.useRef)(callback);
127
- (0, import_react.useEffect)(() => {
128
- callbackRef.current = callback;
129
- }, [callback]);
131
+ (0, import_react.useEffect)(
132
+ function syncCallbackRef() {
133
+ callbackRef.current = callback;
134
+ },
135
+ [callback]
136
+ );
130
137
  return (0, import_react.useCallback)((...args) => {
131
138
  return callbackRef.current(...args);
132
139
  }, []);
@@ -142,7 +149,7 @@ function useDebouncedCallback({
142
149
  const handleChange = usePreservedCallback(onChange);
143
150
  const ref = (0, import_react2.useRef)({ value: false, clearPreviousDebounce: () => {
144
151
  } });
145
- (0, import_react2.useEffect)(() => {
152
+ (0, import_react2.useEffect)(function clearDebouncedOnUnmount() {
146
153
  const current = ref.current;
147
154
  return () => {
148
155
  current.clearPreviousDebounce();
@@ -328,7 +335,7 @@ function Separated({ children, by: separator }) {
328
335
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: childrenArray.map((child, i, { length }) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_react8.Fragment, { children: [
329
336
  child,
330
337
  i + 1 !== length && separator
331
- ] }, i)) });
338
+ ] }, child.key ?? i)) });
332
339
  }
333
340
 
334
341
  // src/components/SwitchCase/SwitchCase.tsx
@@ -492,11 +499,14 @@ function useDebounce(callback, wait, options = {}) {
492
499
  const debounced = (0, import_react16.useMemo)(() => {
493
500
  return debounce(preservedCallback, wait, { edges });
494
501
  }, [preservedCallback, wait, edges]);
495
- (0, import_react15.useEffect)(() => {
496
- return () => {
497
- debounced.cancel();
498
- };
499
- }, [debounced]);
502
+ (0, import_react15.useEffect)(
503
+ function cancelDebouncedOnUnmount() {
504
+ return () => {
505
+ debounced.cancel();
506
+ };
507
+ },
508
+ [debounced]
509
+ );
500
510
  return debounced;
501
511
  }
502
512
 
@@ -679,31 +689,106 @@ function useInterval(callback, options) {
679
689
  const immediate = typeof options === "number" ? false : options.immediate;
680
690
  const enabled = typeof options === "number" ? true : options.enabled ?? true;
681
691
  const preservedCallback = usePreservedCallback(callback);
682
- (0, import_react20.useEffect)(() => {
683
- if (immediate === true && enabled) {
684
- preservedCallback();
685
- }
686
- }, [immediate, preservedCallback, enabled]);
687
- (0, import_react20.useEffect)(() => {
688
- if (!enabled) {
689
- return;
690
- }
691
- const id = window.setInterval(preservedCallback, delay);
692
- return () => window.clearInterval(id);
693
- }, [delay, preservedCallback, enabled]);
692
+ (0, import_react20.useEffect)(
693
+ function runImmediateCallback() {
694
+ if (immediate === true && enabled) {
695
+ preservedCallback();
696
+ }
697
+ },
698
+ [immediate, preservedCallback, enabled]
699
+ );
700
+ (0, import_react20.useEffect)(
701
+ function startInterval() {
702
+ if (!enabled) {
703
+ return;
704
+ }
705
+ const id = setInterval(preservedCallback, delay);
706
+ return () => clearInterval(id);
707
+ },
708
+ [delay, preservedCallback, enabled]
709
+ );
694
710
  }
695
711
 
696
- // src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts
712
+ // src/hooks/useIsClient/useIsClient.ts
697
713
  var import_react21 = require("react");
714
+ function useIsClient() {
715
+ const [isClient, setIsClient] = (0, import_react21.useState)(false);
716
+ (0, import_react21.useEffect)(function syncClientState() {
717
+ setIsClient(true);
718
+ }, []);
719
+ return isClient;
720
+ }
721
+
722
+ // src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts
723
+ var import_react22 = require("react");
698
724
  var isServer = typeof window === "undefined";
699
- var useIsomorphicLayoutEffect = isServer ? import_react21.useEffect : import_react21.useLayoutEffect;
725
+ var useIsomorphicLayoutEffect = isServer ? import_react22.useEffect : import_react22.useLayoutEffect;
726
+
727
+ // src/hooks/useList/useList.ts
728
+ var import_react24 = require("react");
729
+
730
+ // src/hooks/usePreservedReference/usePreservedReference.ts
731
+ var import_react23 = require("react");
732
+ function usePreservedReference(value, areValuesEqual = areDeeplyEqual) {
733
+ const ref = (0, import_react23.useRef)(value);
734
+ return (0, import_react23.useMemo)(() => {
735
+ if (!areValuesEqual(ref.current, value)) {
736
+ ref.current = value;
737
+ }
738
+ return ref.current;
739
+ }, [areValuesEqual, value]);
740
+ }
741
+ function areDeeplyEqual(x, y) {
742
+ return JSON.stringify(x) === JSON.stringify(y);
743
+ }
744
+
745
+ // src/hooks/useList/useList.ts
746
+ function useList(initialState = []) {
747
+ const [list, setList] = (0, import_react24.useState)(initialState);
748
+ const preservedInitialState = usePreservedReference(initialState);
749
+ const push = usePreservedCallback((value) => {
750
+ setList((prev) => [...prev, value]);
751
+ });
752
+ const insertAt = usePreservedCallback((index, value) => {
753
+ setList((prev) => {
754
+ const next = [...prev];
755
+ next.splice(index, 0, value);
756
+ return next;
757
+ });
758
+ });
759
+ const updateAt = usePreservedCallback((index, value) => {
760
+ setList((prev) => {
761
+ const next = [...prev];
762
+ next[index] = value;
763
+ return next;
764
+ });
765
+ });
766
+ const removeAt = usePreservedCallback((index) => {
767
+ setList((prev) => {
768
+ const next = [...prev];
769
+ next.splice(index, 1);
770
+ return next;
771
+ });
772
+ });
773
+ const setAll = usePreservedCallback((values) => {
774
+ setList(values);
775
+ });
776
+ const reset = usePreservedCallback(() => {
777
+ setList(preservedInitialState);
778
+ });
779
+ const actions = (0, import_react24.useMemo)(
780
+ () => ({ push, insertAt, updateAt, removeAt, setAll, reset }),
781
+ [push, insertAt, updateAt, removeAt, setAll, reset]
782
+ );
783
+ return [list, actions];
784
+ }
700
785
 
701
786
  // src/hooks/useLoading/useLoading.ts
702
- var import_react22 = require("react");
787
+ var import_react25 = require("react");
703
788
  function useLoading() {
704
- const [loading, setLoading] = (0, import_react22.useState)(false);
789
+ const [loading, setLoading] = (0, import_react25.useState)(false);
705
790
  const ref = useIsMountedRef();
706
- const startTransition = (0, import_react22.useCallback)(
791
+ const startTransition = (0, import_react25.useCallback)(
707
792
  async (promise) => {
708
793
  try {
709
794
  setLoading(true);
@@ -717,32 +802,35 @@ function useLoading() {
717
802
  },
718
803
  [ref.isMounted]
719
804
  );
720
- return (0, import_react22.useMemo)(() => [loading, startTransition], [loading, startTransition]);
805
+ return (0, import_react25.useMemo)(() => [loading, startTransition], [loading, startTransition]);
721
806
  }
722
807
  function useIsMountedRef() {
723
- const ref = (0, import_react22.useRef)({ isMounted: true }).current;
724
- (0, import_react22.useEffect)(() => {
725
- ref.isMounted = true;
726
- return () => {
727
- ref.isMounted = false;
728
- };
729
- }, [ref]);
808
+ const ref = (0, import_react25.useRef)({ isMounted: true }).current;
809
+ (0, import_react25.useEffect)(
810
+ function trackMountedState() {
811
+ ref.isMounted = true;
812
+ return () => {
813
+ ref.isMounted = false;
814
+ };
815
+ },
816
+ [ref]
817
+ );
730
818
  return ref;
731
819
  }
732
820
 
733
821
  // src/hooks/useLongPress/useLongPress.ts
734
- var import_react23 = require("react");
822
+ var import_react26 = require("react");
735
823
  function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLongPressEnd } = {}) {
736
- const timeoutRef = (0, import_react23.useRef)(null);
737
- const isLongPressActiveRef = (0, import_react23.useRef)(false);
738
- const initialPositionRef = (0, import_react23.useRef)({ x: 0, y: 0 });
824
+ const timeoutRef = (0, import_react26.useRef)(null);
825
+ const isLongPressActiveRef = (0, import_react26.useRef)(false);
826
+ const initialPositionRef = (0, import_react26.useRef)({ x: 0, y: 0 });
739
827
  const preservedOnLongPress = usePreservedCallback(onLongPress);
740
828
  const preservedOnClick = usePreservedCallback(onClick || (() => {
741
829
  }));
742
830
  const preservedOnLongPressEnd = usePreservedCallback(onLongPressEnd || (() => {
743
831
  }));
744
832
  const hasThreshold = moveThreshold?.x !== void 0 || moveThreshold?.y !== void 0;
745
- const getClientPosition = (0, import_react23.useCallback)((event) => {
833
+ const getClientPosition = (0, import_react26.useCallback)((event) => {
746
834
  if ("touches" in event.nativeEvent) {
747
835
  const touch = event.nativeEvent.touches[0];
748
836
  return { x: touch.clientX, y: touch.clientY };
@@ -752,7 +840,7 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
752
840
  y: event.nativeEvent.clientY
753
841
  };
754
842
  }, []);
755
- const isMovedBeyondThreshold = (0, import_react23.useCallback)(
843
+ const isMovedBeyondThreshold = (0, import_react26.useCallback)(
756
844
  (event) => {
757
845
  const { x, y } = getClientPosition(event);
758
846
  const deltaX = Math.abs(x - initialPositionRef.current.x);
@@ -761,13 +849,13 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
761
849
  },
762
850
  [getClientPosition, moveThreshold]
763
851
  );
764
- const cancelLongPress = (0, import_react23.useCallback)(() => {
852
+ const cancelLongPress = (0, import_react26.useCallback)(() => {
765
853
  if (timeoutRef.current !== null) {
766
854
  window.clearTimeout(timeoutRef.current);
767
855
  timeoutRef.current = null;
768
856
  }
769
857
  }, []);
770
- const handlePressStart = (0, import_react23.useCallback)(
858
+ const handlePressStart = (0, import_react26.useCallback)(
771
859
  (event) => {
772
860
  cancelLongPress();
773
861
  const position = getClientPosition(event);
@@ -780,7 +868,7 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
780
868
  },
781
869
  [cancelLongPress, delay, getClientPosition, preservedOnLongPress]
782
870
  );
783
- const handlePressEnd = (0, import_react23.useCallback)(
871
+ const handlePressEnd = (0, import_react26.useCallback)(
784
872
  (event) => {
785
873
  if (isLongPressActiveRef.current) {
786
874
  preservedOnLongPressEnd(event);
@@ -792,7 +880,7 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
792
880
  },
793
881
  [cancelLongPress, preservedOnClick, preservedOnLongPressEnd]
794
882
  );
795
- const handlePressMove = (0, import_react23.useCallback)(
883
+ const handlePressMove = (0, import_react26.useCallback)(
796
884
  (event) => {
797
885
  if (timeoutRef.current !== null && isMovedBeyondThreshold(event)) {
798
886
  cancelLongPress();
@@ -811,57 +899,40 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
811
899
  }
812
900
 
813
901
  // src/hooks/useMap/useMap.ts
814
- var import_react25 = require("react");
815
-
816
- // src/hooks/usePreservedReference/usePreservedReference.ts
817
- var import_react24 = require("react");
818
- function usePreservedReference(value, areValuesEqual = areDeeplyEqual) {
819
- const ref = (0, import_react24.useRef)(value);
820
- return (0, import_react24.useMemo)(() => {
821
- if (!areValuesEqual(ref.current, value)) {
822
- ref.current = value;
823
- }
824
- return ref.current;
825
- }, [areValuesEqual, value]);
826
- }
827
- function areDeeplyEqual(x, y) {
828
- return JSON.stringify(x) === JSON.stringify(y);
829
- }
830
-
831
- // src/hooks/useMap/useMap.ts
902
+ var import_react27 = require("react");
832
903
  function useMap(initialState = /* @__PURE__ */ new Map()) {
833
- const [map, setMap] = (0, import_react25.useState)(() => new Map(initialState));
904
+ const [map, setMap] = (0, import_react27.useState)(() => new Map(initialState));
834
905
  const preservedInitialState = usePreservedReference(initialState);
835
- const set = (0, import_react25.useCallback)((key, value) => {
906
+ const set = (0, import_react27.useCallback)((key, value) => {
836
907
  setMap((prev) => {
837
908
  const nextMap = new Map(prev);
838
909
  nextMap.set(key, value);
839
910
  return nextMap;
840
911
  });
841
912
  }, []);
842
- const setAll = (0, import_react25.useCallback)((entries) => {
913
+ const setAll = (0, import_react27.useCallback)((entries) => {
843
914
  setMap(() => new Map(entries));
844
915
  }, []);
845
- const remove = (0, import_react25.useCallback)((key) => {
916
+ const remove = (0, import_react27.useCallback)((key) => {
846
917
  setMap((prev) => {
847
918
  const nextMap = new Map(prev);
848
919
  nextMap.delete(key);
849
920
  return nextMap;
850
921
  });
851
922
  }, []);
852
- const reset = (0, import_react25.useCallback)(() => {
923
+ const reset = (0, import_react27.useCallback)(() => {
853
924
  setMap(() => new Map(preservedInitialState));
854
925
  }, [preservedInitialState]);
855
- const actions = (0, import_react25.useMemo)(() => {
926
+ const actions = (0, import_react27.useMemo)(() => {
856
927
  return { set, setAll, remove, reset };
857
928
  }, [set, setAll, remove, reset]);
858
929
  return [map, actions];
859
930
  }
860
931
 
861
932
  // src/hooks/useOutsideClickEffect/useOutsideClickEffect.ts
862
- var import_react26 = require("react");
933
+ var import_react28 = require("react");
863
934
  function useOutsideClickEffect(container, callback) {
864
- const containers = (0, import_react26.useRef)([]);
935
+ const containers = (0, import_react28.useRef)([]);
865
936
  const handleDocumentClick = usePreservedCallback(({ target }) => {
866
937
  if (target === null) {
867
938
  return;
@@ -874,10 +945,10 @@ function useOutsideClickEffect(container, callback) {
874
945
  }
875
946
  callback();
876
947
  });
877
- (0, import_react26.useEffect)(() => {
948
+ (0, import_react28.useEffect)(() => {
878
949
  containers.current = [container].flat(1).filter((item) => item != null);
879
950
  }, [container]);
880
- (0, import_react26.useEffect)(() => {
951
+ (0, import_react28.useEffect)(() => {
881
952
  document.addEventListener("click", handleDocumentClick);
882
953
  return () => {
883
954
  document.removeEventListener("click", handleDocumentClick);
@@ -886,12 +957,12 @@ function useOutsideClickEffect(container, callback) {
886
957
  }
887
958
 
888
959
  // src/hooks/usePrevious/usePrevious.ts
889
- var import_react27 = require("react");
960
+ var import_react29 = require("react");
890
961
  var strictEquals = (prev, next) => prev === next;
891
962
  function usePrevious(state, compare = strictEquals) {
892
- const prevRef = (0, import_react27.useRef)(state);
893
- const currentRef = (0, import_react27.useRef)(state);
894
- const isFirstRender = (0, import_react27.useRef)(true);
963
+ const prevRef = (0, import_react29.useRef)(state);
964
+ const currentRef = (0, import_react29.useRef)(state);
965
+ const isFirstRender = (0, import_react29.useRef)(true);
895
966
  if (isFirstRender.current) {
896
967
  isFirstRender.current = false;
897
968
  return prevRef.current;
@@ -903,8 +974,51 @@ function usePrevious(state, compare = strictEquals) {
903
974
  return prevRef.current;
904
975
  }
905
976
 
977
+ // src/hooks/useSet/useSet.ts
978
+ var import_react30 = require("react");
979
+ function useSet(initialState = /* @__PURE__ */ new Set()) {
980
+ const [set, setSet] = (0, import_react30.useState)(() => new Set(initialState));
981
+ const preservedInitialState = usePreservedReference(initialState);
982
+ const add = usePreservedCallback((value) => {
983
+ setSet((prev) => {
984
+ const nextSet = new Set(prev);
985
+ nextSet.add(value);
986
+ return nextSet;
987
+ });
988
+ });
989
+ const remove = usePreservedCallback((value) => {
990
+ setSet((prev) => {
991
+ const nextSet = new Set(prev);
992
+ nextSet.delete(value);
993
+ return nextSet;
994
+ });
995
+ });
996
+ const toggle2 = usePreservedCallback((value) => {
997
+ setSet((prev) => {
998
+ const nextSet = new Set(prev);
999
+ if (nextSet.has(value)) {
1000
+ nextSet.delete(value);
1001
+ } else {
1002
+ nextSet.add(value);
1003
+ }
1004
+ return nextSet;
1005
+ });
1006
+ });
1007
+ const setAll = usePreservedCallback((values) => {
1008
+ setSet(() => new Set(values));
1009
+ });
1010
+ const reset = usePreservedCallback(() => {
1011
+ setSet(() => new Set(preservedInitialState));
1012
+ });
1013
+ const actions = (0, import_react30.useMemo)(
1014
+ () => ({ add, remove, toggle: toggle2, setAll, reset }),
1015
+ [add, remove, toggle2, setAll, reset]
1016
+ );
1017
+ return [set, actions];
1018
+ }
1019
+
906
1020
  // src/hooks/useStorageState/useStorageState.ts
907
- var import_react28 = require("react");
1021
+ var import_react31 = require("react");
908
1022
 
909
1023
  // src/hooks/useStorageState/storage.ts
910
1024
  var MemoStorage = class {
@@ -1016,11 +1130,11 @@ function useStorageState(key, {
1016
1130
  ...options
1017
1131
  } = {}) {
1018
1132
  const serializedDefaultValue = defaultValue;
1019
- const cache = (0, import_react28.useRef)({
1133
+ const cache = (0, import_react31.useRef)({
1020
1134
  data: null,
1021
1135
  parsed: serializedDefaultValue
1022
1136
  });
1023
- const getSnapshot = (0, import_react28.useCallback)(() => {
1137
+ const getSnapshot = (0, import_react31.useCallback)(() => {
1024
1138
  const deserializer = "deserializer" in options ? options.deserializer : JSON.parse;
1025
1139
  const data = storage.get(key);
1026
1140
  if (data !== cache.current.data) {
@@ -1033,7 +1147,7 @@ function useStorageState(key, {
1033
1147
  }
1034
1148
  return cache.current.parsed;
1035
1149
  }, [defaultValue, key, storage]);
1036
- const storageState = (0, import_react28.useSyncExternalStore)(
1150
+ const storageState = (0, import_react31.useSyncExternalStore)(
1037
1151
  (onStoreChange) => {
1038
1152
  listeners.add(onStoreChange);
1039
1153
  const handler = (event) => {
@@ -1050,7 +1164,7 @@ function useStorageState(key, {
1050
1164
  () => getSnapshot(),
1051
1165
  () => serializedDefaultValue
1052
1166
  );
1053
- const setStorageState = (0, import_react28.useCallback)(
1167
+ const setStorageState = (0, import_react31.useCallback)(
1054
1168
  (value) => {
1055
1169
  const serializer = "serializer" in options ? options.serializer : JSON.stringify;
1056
1170
  const nextValue = typeof value === "function" ? value(getSnapshot()) : value;
@@ -1063,14 +1177,14 @@ function useStorageState(key, {
1063
1177
  },
1064
1178
  [getSnapshot, key, storage]
1065
1179
  );
1066
- const refreshStorageState = (0, import_react28.useCallback)(() => {
1180
+ const refreshStorageState = (0, import_react31.useCallback)(() => {
1067
1181
  setStorageState(getSnapshot());
1068
1182
  }, [storage, getSnapshot, setStorageState]);
1069
1183
  return ensureSerializable([storageState, setStorageState, refreshStorageState]);
1070
1184
  }
1071
1185
 
1072
1186
  // src/hooks/useThrottle/useThrottle.ts
1073
- var import_react29 = require("react");
1187
+ var import_react32 = require("react");
1074
1188
 
1075
1189
  // src/hooks/useThrottle/throttle.ts
1076
1190
  function throttle(func, throttleMs, { edges = ["leading", "trailing"] } = {}) {
@@ -1095,11 +1209,11 @@ function throttle(func, throttleMs, { edges = ["leading", "trailing"] } = {}) {
1095
1209
  function useThrottle(callback, wait, options) {
1096
1210
  const preservedCallback = usePreservedCallback(callback);
1097
1211
  const preservedOptions = usePreservedReference(options ?? {});
1098
- const throttledCallback = (0, import_react29.useMemo)(
1212
+ const throttledCallback = (0, import_react32.useMemo)(
1099
1213
  () => throttle(preservedCallback, wait, preservedOptions),
1100
1214
  [preservedOptions, preservedCallback, wait]
1101
1215
  );
1102
- (0, import_react29.useEffect)(() => {
1216
+ (0, import_react32.useEffect)(() => {
1103
1217
  return () => {
1104
1218
  throttledCallback.cancel();
1105
1219
  };
@@ -1107,30 +1221,68 @@ function useThrottle(callback, wait, options) {
1107
1221
  return throttledCallback;
1108
1222
  }
1109
1223
 
1224
+ // src/hooks/useThrottledCallback/useThrottledCallback.ts
1225
+ var import_react33 = require("react");
1226
+ function useThrottledCallback({
1227
+ onChange,
1228
+ timeThreshold,
1229
+ edges = ["leading", "trailing"]
1230
+ }) {
1231
+ const handleChange = usePreservedCallback(onChange);
1232
+ const ref = (0, import_react33.useRef)({ value: false, clearPreviousThrottle: () => {
1233
+ } });
1234
+ (0, import_react33.useEffect)(function cleanupThrottleOnUnmount() {
1235
+ const current = ref.current;
1236
+ return () => {
1237
+ current.clearPreviousThrottle();
1238
+ };
1239
+ }, []);
1240
+ const preservedEdges = usePreservedReference(edges);
1241
+ return (0, import_react33.useCallback)(
1242
+ (nextValue) => {
1243
+ if (nextValue === ref.current.value) {
1244
+ return;
1245
+ }
1246
+ const throttled = throttle(
1247
+ () => {
1248
+ handleChange(nextValue);
1249
+ ref.current.value = nextValue;
1250
+ },
1251
+ timeThreshold,
1252
+ { edges: preservedEdges }
1253
+ );
1254
+ ref.current.clearPreviousThrottle();
1255
+ throttled();
1256
+ ref.current.clearPreviousThrottle = throttled.cancel;
1257
+ },
1258
+ [handleChange, timeThreshold, preservedEdges]
1259
+ );
1260
+ }
1261
+
1110
1262
  // src/hooks/useTimeout/useTimeout.ts
1111
- var import_react30 = require("react");
1263
+ var import_react34 = require("react");
1112
1264
  function useTimeout(callback, delay = 0) {
1113
1265
  const preservedCallback = usePreservedCallback(callback);
1114
- (0, import_react30.useEffect)(() => {
1115
- const timeoutId = window.setTimeout(preservedCallback, delay);
1116
- return () => window.clearTimeout(timeoutId);
1266
+ (0, import_react34.useEffect)(() => {
1267
+ const timeoutId = setTimeout(preservedCallback, delay);
1268
+ return () => clearTimeout(timeoutId);
1117
1269
  }, [delay, preservedCallback]);
1118
1270
  }
1119
1271
 
1120
1272
  // src/hooks/useToggle/useToggle.ts
1121
- var import_react31 = require("react");
1273
+ var import_react35 = require("react");
1122
1274
  function useToggle(initialValue = false) {
1123
- return (0, import_react31.useReducer)(toggle, initialValue);
1275
+ return (0, import_react35.useReducer)(toggle, initialValue);
1124
1276
  }
1125
1277
  var toggle = (state) => !state;
1126
1278
 
1127
1279
  // src/utils/buildContext/buildContext.tsx
1128
- var import_react32 = require("react");
1280
+ var import_react36 = require("react");
1129
1281
  var import_jsx_runtime3 = require("react/jsx-runtime");
1130
1282
  function buildContext(contextName, defaultContextValues) {
1131
- const Context = (0, import_react32.createContext)(defaultContextValues ?? void 0);
1283
+ const Context = (0, import_react36.createContext)(defaultContextValues ?? void 0);
1132
1284
  function Provider({ children, ...contextValues }) {
1133
- const value = (0, import_react32.useMemo)(
1285
+ const value = (0, import_react36.useMemo)(
1134
1286
  () => Object.keys(contextValues).length > 0 ? contextValues : null,
1135
1287
  // eslint-disable-next-line react-hooks/exhaustive-deps
1136
1288
  [...Object.values(contextValues)]
@@ -1138,7 +1290,7 @@ function buildContext(contextName, defaultContextValues) {
1138
1290
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Context.Provider, { value, children });
1139
1291
  }
1140
1292
  function useInnerContext() {
1141
- const context = (0, import_react32.useContext)(Context);
1293
+ const context = (0, import_react36.useContext)(Context);
1142
1294
  if (context != null) {
1143
1295
  return context;
1144
1296
  }
@@ -1212,7 +1364,9 @@ function mergeFunction(a, b) {
1212
1364
  useInputState,
1213
1365
  useIntersectionObserver,
1214
1366
  useInterval,
1367
+ useIsClient,
1215
1368
  useIsomorphicLayoutEffect,
1369
+ useList,
1216
1370
  useLoading,
1217
1371
  useLongPress,
1218
1372
  useMap,
@@ -1221,8 +1375,10 @@ function mergeFunction(a, b) {
1221
1375
  usePreservedReference,
1222
1376
  usePrevious,
1223
1377
  useRefEffect,
1378
+ useSet,
1224
1379
  useStorageState,
1225
1380
  useThrottle,
1381
+ useThrottledCallback,
1226
1382
  useTimeout,
1227
1383
  useToggle,
1228
1384
  useVisibilityEvent
package/dist/index.d.cts CHANGED
@@ -15,7 +15,9 @@ export { useImpressionRef } from './hooks/useImpressionRef/index.cjs';
15
15
  export { useInputState } from './hooks/useInputState/index.cjs';
16
16
  export { useIntersectionObserver } from './hooks/useIntersectionObserver/index.cjs';
17
17
  export { useInterval } from './hooks/useInterval/index.cjs';
18
+ export { useIsClient } from './hooks/useIsClient/index.cjs';
18
19
  export { useIsomorphicLayoutEffect } from './hooks/useIsomorphicLayoutEffect/index.cjs';
20
+ export { useList } from './hooks/useList/index.cjs';
19
21
  export { useLoading } from './hooks/useLoading/index.cjs';
20
22
  export { useLongPress } from './hooks/useLongPress/index.cjs';
21
23
  export { useMap } from './hooks/useMap/index.cjs';
@@ -24,8 +26,10 @@ export { usePreservedCallback } from './hooks/usePreservedCallback/index.cjs';
24
26
  export { usePreservedReference } from './hooks/usePreservedReference/index.cjs';
25
27
  export { usePrevious } from './hooks/usePrevious/index.cjs';
26
28
  export { useRefEffect } from './hooks/useRefEffect/index.cjs';
29
+ export { useSet } from './hooks/useSet/index.cjs';
27
30
  export { useStorageState } from './hooks/useStorageState/index.cjs';
28
31
  export { useThrottle } from './hooks/useThrottle/index.cjs';
32
+ export { useThrottledCallback } from './hooks/useThrottledCallback/index.cjs';
29
33
  export { useTimeout } from './hooks/useTimeout/index.cjs';
30
34
  export { useToggle } from './hooks/useToggle/index.cjs';
31
35
  export { useVisibilityEvent } from './hooks/useVisibilityEvent/index.cjs';
@@ -66,9 +66,12 @@ function debounce(func, debounceMs, { edges = ["leading", "trailing"] } = {}) {
66
66
  import { useCallback, useEffect, useRef } from "react";
67
67
  function usePreservedCallback(callback) {
68
68
  const callbackRef = useRef(callback);
69
- useEffect(() => {
70
- callbackRef.current = callback;
71
- }, [callback]);
69
+ useEffect(
70
+ function syncCallbackRef() {
71
+ callbackRef.current = callback;
72
+ },
73
+ [callback]
74
+ );
72
75
  return useCallback((...args) => {
73
76
  return callbackRef.current(...args);
74
77
  }, []);
@@ -84,7 +87,7 @@ function useDebouncedCallback({
84
87
  const handleChange = usePreservedCallback(onChange);
85
88
  const ref = useRef2({ value: false, clearPreviousDebounce: () => {
86
89
  } });
87
- useEffect2(() => {
90
+ useEffect2(function clearDebouncedOnUnmount() {
88
91
  const current = ref.current;
89
92
  return () => {
90
93
  current.clearPreviousDebounce();
@@ -8,7 +8,7 @@ function Separated({ children, by: separator }) {
8
8
  return /* @__PURE__ */ jsx(Fragment2, { children: childrenArray.map((child, i, { length }) => /* @__PURE__ */ jsxs(Fragment, { children: [
9
9
  child,
10
10
  i + 1 !== length && separator
11
- ] }, i)) });
11
+ ] }, child.key ?? i)) });
12
12
  }
13
13
  export {
14
14
  Separated
@@ -7,9 +7,12 @@ import { useEffect as useEffect2, useRef as useRef2 } from "react";
7
7
  import { useCallback, useEffect, useRef } from "react";
8
8
  function usePreservedCallback(callback) {
9
9
  const callbackRef = useRef(callback);
10
- useEffect(() => {
11
- callbackRef.current = callback;
12
- }, [callback]);
10
+ useEffect(
11
+ function syncCallbackRef() {
12
+ callbackRef.current = callback;
13
+ },
14
+ [callback]
15
+ );
13
16
  return useCallback((...args) => {
14
17
  return callbackRef.current(...args);
15
18
  }, []);