react-simplikit 0.0.48 → 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 +1 -1
@@ -0,0 +1,146 @@
1
+ "use client";
2
+
3
+ // src/hooks/useThrottledCallback/useThrottledCallback.ts
4
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef3 } from "react";
5
+
6
+ // src/hooks/usePreservedCallback/usePreservedCallback.ts
7
+ import { useCallback, useEffect, useRef } from "react";
8
+ function usePreservedCallback(callback) {
9
+ const callbackRef = useRef(callback);
10
+ useEffect(
11
+ function syncCallbackRef() {
12
+ callbackRef.current = callback;
13
+ },
14
+ [callback]
15
+ );
16
+ return useCallback((...args) => {
17
+ return callbackRef.current(...args);
18
+ }, []);
19
+ }
20
+
21
+ // src/hooks/usePreservedReference/usePreservedReference.ts
22
+ import { useMemo, useRef as useRef2 } from "react";
23
+ function usePreservedReference(value, areValuesEqual = areDeeplyEqual) {
24
+ const ref = useRef2(value);
25
+ return useMemo(() => {
26
+ if (!areValuesEqual(ref.current, value)) {
27
+ ref.current = value;
28
+ }
29
+ return ref.current;
30
+ }, [areValuesEqual, value]);
31
+ }
32
+ function areDeeplyEqual(x, y) {
33
+ return JSON.stringify(x) === JSON.stringify(y);
34
+ }
35
+
36
+ // src/hooks/useDebounce/debounce.ts
37
+ function debounce(func, debounceMs, { edges = ["leading", "trailing"] } = {}) {
38
+ let pendingThis = void 0;
39
+ let pendingArgs = null;
40
+ const leading = edges != null && edges.includes("leading");
41
+ const trailing = edges == null || edges.includes("trailing");
42
+ const invoke = () => {
43
+ if (pendingArgs !== null) {
44
+ func.apply(pendingThis, pendingArgs);
45
+ pendingThis = void 0;
46
+ pendingArgs = null;
47
+ }
48
+ };
49
+ const onTimerEnd = () => {
50
+ if (trailing) {
51
+ invoke();
52
+ }
53
+ cancel();
54
+ };
55
+ let timeoutId = null;
56
+ const schedule = () => {
57
+ if (timeoutId != null) {
58
+ clearTimeout(timeoutId);
59
+ }
60
+ timeoutId = setTimeout(() => {
61
+ timeoutId = null;
62
+ onTimerEnd();
63
+ }, debounceMs);
64
+ };
65
+ const cancelTimer = () => {
66
+ if (timeoutId !== null) {
67
+ clearTimeout(timeoutId);
68
+ timeoutId = null;
69
+ }
70
+ };
71
+ const cancel = () => {
72
+ cancelTimer();
73
+ pendingThis = void 0;
74
+ pendingArgs = null;
75
+ };
76
+ const debounced = function(...args) {
77
+ pendingThis = this;
78
+ pendingArgs = args;
79
+ const isFirstCall = timeoutId == null;
80
+ schedule();
81
+ if (leading && isFirstCall) {
82
+ invoke();
83
+ }
84
+ };
85
+ debounced.cancel = cancel;
86
+ return debounced;
87
+ }
88
+
89
+ // src/hooks/useThrottle/throttle.ts
90
+ function throttle(func, throttleMs, { edges = ["leading", "trailing"] } = {}) {
91
+ let pendingAt = null;
92
+ const debounced = debounce(func, throttleMs, { edges });
93
+ const throttled = function(...args) {
94
+ if (pendingAt == null) {
95
+ pendingAt = Date.now();
96
+ } else {
97
+ if (Date.now() - pendingAt >= throttleMs) {
98
+ pendingAt = Date.now();
99
+ debounced.cancel();
100
+ }
101
+ }
102
+ debounced(...args);
103
+ };
104
+ throttled.cancel = debounced.cancel;
105
+ return throttled;
106
+ }
107
+
108
+ // src/hooks/useThrottledCallback/useThrottledCallback.ts
109
+ function useThrottledCallback({
110
+ onChange,
111
+ timeThreshold,
112
+ edges = ["leading", "trailing"]
113
+ }) {
114
+ const handleChange = usePreservedCallback(onChange);
115
+ const ref = useRef3({ value: false, clearPreviousThrottle: () => {
116
+ } });
117
+ useEffect2(function cleanupThrottleOnUnmount() {
118
+ const current = ref.current;
119
+ return () => {
120
+ current.clearPreviousThrottle();
121
+ };
122
+ }, []);
123
+ const preservedEdges = usePreservedReference(edges);
124
+ return useCallback2(
125
+ (nextValue) => {
126
+ if (nextValue === ref.current.value) {
127
+ return;
128
+ }
129
+ const throttled = throttle(
130
+ () => {
131
+ handleChange(nextValue);
132
+ ref.current.value = nextValue;
133
+ },
134
+ timeThreshold,
135
+ { edges: preservedEdges }
136
+ );
137
+ ref.current.clearPreviousThrottle();
138
+ throttled();
139
+ ref.current.clearPreviousThrottle = throttled.cancel;
140
+ },
141
+ [handleChange, timeThreshold, preservedEdges]
142
+ );
143
+ }
144
+ export {
145
+ useThrottledCallback
146
+ };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @description
3
3
  * `useTimeout` is a React hook that executes a callback function after a specified delay.
4
- * It manages `window.setTimeout` in accordance with the React lifecycle, ensuring cleanup on unmount or when dependencies change.
4
+ * It manages `setTimeout` in accordance with the React lifecycle, ensuring cleanup on unmount or when dependencies change.
5
5
  *
6
6
  * @param {() => void} callback - The function to be executed after the delay.
7
7
  * @param {number} [delay=0] - The time in milliseconds to wait before executing the callback.
@@ -7,9 +7,12 @@ import { useEffect as useEffect2 } 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
  }, []);
@@ -19,8 +22,8 @@ function usePreservedCallback(callback) {
19
22
  function useTimeout(callback, delay = 0) {
20
23
  const preservedCallback = usePreservedCallback(callback);
21
24
  useEffect2(() => {
22
- const timeoutId = window.setTimeout(preservedCallback, delay);
23
- return () => window.clearTimeout(timeoutId);
25
+ const timeoutId = setTimeout(preservedCallback, delay);
26
+ return () => clearTimeout(timeoutId);
24
27
  }, [delay, preservedCallback]);
25
28
  }
26
29
  export {
package/esm/index.d.ts CHANGED
@@ -15,7 +15,9 @@ export { useImpressionRef } from './hooks/useImpressionRef/index.js';
15
15
  export { useInputState } from './hooks/useInputState/index.js';
16
16
  export { useIntersectionObserver } from './hooks/useIntersectionObserver/index.js';
17
17
  export { useInterval } from './hooks/useInterval/index.js';
18
+ export { useIsClient } from './hooks/useIsClient/index.js';
18
19
  export { useIsomorphicLayoutEffect } from './hooks/useIsomorphicLayoutEffect/index.js';
20
+ export { useList } from './hooks/useList/index.js';
19
21
  export { useLoading } from './hooks/useLoading/index.js';
20
22
  export { useLongPress } from './hooks/useLongPress/index.js';
21
23
  export { useMap } from './hooks/useMap/index.js';
@@ -24,8 +26,10 @@ export { usePreservedCallback } from './hooks/usePreservedCallback/index.js';
24
26
  export { usePreservedReference } from './hooks/usePreservedReference/index.js';
25
27
  export { usePrevious } from './hooks/usePrevious/index.js';
26
28
  export { useRefEffect } from './hooks/useRefEffect/index.js';
29
+ export { useSet } from './hooks/useSet/index.js';
27
30
  export { useStorageState } from './hooks/useStorageState/index.js';
28
31
  export { useThrottle } from './hooks/useThrottle/index.js';
32
+ export { useThrottledCallback } from './hooks/useThrottledCallback/index.js';
29
33
  export { useTimeout } from './hooks/useTimeout/index.js';
30
34
  export { useToggle } from './hooks/useToggle/index.js';
31
35
  export { useVisibilityEvent } from './hooks/useVisibilityEvent/index.js';
package/esm/index.js CHANGED
@@ -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();
@@ -270,7 +273,7 @@ function Separated({ children, by: separator }) {
270
273
  return /* @__PURE__ */ jsx2(Fragment2, { children: childrenArray.map((child, i, { length }) => /* @__PURE__ */ jsxs(Fragment, { children: [
271
274
  child,
272
275
  i + 1 !== length && separator
273
- ] }, i)) });
276
+ ] }, child.key ?? i)) });
274
277
  }
275
278
 
276
279
  // src/components/SwitchCase/SwitchCase.tsx
@@ -434,11 +437,14 @@ function useDebounce(callback, wait, options = {}) {
434
437
  const debounced = useMemo3(() => {
435
438
  return debounce(preservedCallback, wait, { edges });
436
439
  }, [preservedCallback, wait, edges]);
437
- useEffect7(() => {
438
- return () => {
439
- debounced.cancel();
440
- };
441
- }, [debounced]);
440
+ useEffect7(
441
+ function cancelDebouncedOnUnmount() {
442
+ return () => {
443
+ debounced.cancel();
444
+ };
445
+ },
446
+ [debounced]
447
+ );
442
448
  return debounced;
443
449
  }
444
450
 
@@ -621,29 +627,104 @@ function useInterval(callback, options) {
621
627
  const immediate = typeof options === "number" ? false : options.immediate;
622
628
  const enabled = typeof options === "number" ? true : options.enabled ?? true;
623
629
  const preservedCallback = usePreservedCallback(callback);
624
- useEffect10(() => {
625
- if (immediate === true && enabled) {
626
- preservedCallback();
627
- }
628
- }, [immediate, preservedCallback, enabled]);
629
- useEffect10(() => {
630
- if (!enabled) {
631
- return;
632
- }
633
- const id = window.setInterval(preservedCallback, delay);
634
- return () => window.clearInterval(id);
635
- }, [delay, preservedCallback, enabled]);
630
+ useEffect10(
631
+ function runImmediateCallback() {
632
+ if (immediate === true && enabled) {
633
+ preservedCallback();
634
+ }
635
+ },
636
+ [immediate, preservedCallback, enabled]
637
+ );
638
+ useEffect10(
639
+ function startInterval() {
640
+ if (!enabled) {
641
+ return;
642
+ }
643
+ const id = setInterval(preservedCallback, delay);
644
+ return () => clearInterval(id);
645
+ },
646
+ [delay, preservedCallback, enabled]
647
+ );
648
+ }
649
+
650
+ // src/hooks/useIsClient/useIsClient.ts
651
+ import { useEffect as useEffect11, useState as useState6 } from "react";
652
+ function useIsClient() {
653
+ const [isClient, setIsClient] = useState6(false);
654
+ useEffect11(function syncClientState() {
655
+ setIsClient(true);
656
+ }, []);
657
+ return isClient;
636
658
  }
637
659
 
638
660
  // src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts
639
- import { useEffect as useEffect11, useLayoutEffect } from "react";
661
+ import { useEffect as useEffect12, useLayoutEffect } from "react";
640
662
  var isServer = typeof window === "undefined";
641
- var useIsomorphicLayoutEffect = isServer ? useEffect11 : useLayoutEffect;
663
+ var useIsomorphicLayoutEffect = isServer ? useEffect12 : useLayoutEffect;
664
+
665
+ // src/hooks/useList/useList.ts
666
+ import { useMemo as useMemo5, useState as useState7 } from "react";
667
+
668
+ // src/hooks/usePreservedReference/usePreservedReference.ts
669
+ import { useMemo as useMemo4, useRef as useRef9 } from "react";
670
+ function usePreservedReference(value, areValuesEqual = areDeeplyEqual) {
671
+ const ref = useRef9(value);
672
+ return useMemo4(() => {
673
+ if (!areValuesEqual(ref.current, value)) {
674
+ ref.current = value;
675
+ }
676
+ return ref.current;
677
+ }, [areValuesEqual, value]);
678
+ }
679
+ function areDeeplyEqual(x, y) {
680
+ return JSON.stringify(x) === JSON.stringify(y);
681
+ }
682
+
683
+ // src/hooks/useList/useList.ts
684
+ function useList(initialState = []) {
685
+ const [list, setList] = useState7(initialState);
686
+ const preservedInitialState = usePreservedReference(initialState);
687
+ const push = usePreservedCallback((value) => {
688
+ setList((prev) => [...prev, value]);
689
+ });
690
+ const insertAt = usePreservedCallback((index, value) => {
691
+ setList((prev) => {
692
+ const next = [...prev];
693
+ next.splice(index, 0, value);
694
+ return next;
695
+ });
696
+ });
697
+ const updateAt = usePreservedCallback((index, value) => {
698
+ setList((prev) => {
699
+ const next = [...prev];
700
+ next[index] = value;
701
+ return next;
702
+ });
703
+ });
704
+ const removeAt = usePreservedCallback((index) => {
705
+ setList((prev) => {
706
+ const next = [...prev];
707
+ next.splice(index, 1);
708
+ return next;
709
+ });
710
+ });
711
+ const setAll = usePreservedCallback((values) => {
712
+ setList(values);
713
+ });
714
+ const reset = usePreservedCallback(() => {
715
+ setList(preservedInitialState);
716
+ });
717
+ const actions = useMemo5(
718
+ () => ({ push, insertAt, updateAt, removeAt, setAll, reset }),
719
+ [push, insertAt, updateAt, removeAt, setAll, reset]
720
+ );
721
+ return [list, actions];
722
+ }
642
723
 
643
724
  // src/hooks/useLoading/useLoading.ts
644
- import { useCallback as useCallback12, useEffect as useEffect12, useMemo as useMemo4, useRef as useRef9, useState as useState6 } from "react";
725
+ import { useCallback as useCallback12, useEffect as useEffect13, useMemo as useMemo6, useRef as useRef10, useState as useState8 } from "react";
645
726
  function useLoading() {
646
- const [loading, setLoading] = useState6(false);
727
+ const [loading, setLoading] = useState8(false);
647
728
  const ref = useIsMountedRef();
648
729
  const startTransition = useCallback12(
649
730
  async (promise) => {
@@ -659,25 +740,28 @@ function useLoading() {
659
740
  },
660
741
  [ref.isMounted]
661
742
  );
662
- return useMemo4(() => [loading, startTransition], [loading, startTransition]);
743
+ return useMemo6(() => [loading, startTransition], [loading, startTransition]);
663
744
  }
664
745
  function useIsMountedRef() {
665
- const ref = useRef9({ isMounted: true }).current;
666
- useEffect12(() => {
667
- ref.isMounted = true;
668
- return () => {
669
- ref.isMounted = false;
670
- };
671
- }, [ref]);
746
+ const ref = useRef10({ isMounted: true }).current;
747
+ useEffect13(
748
+ function trackMountedState() {
749
+ ref.isMounted = true;
750
+ return () => {
751
+ ref.isMounted = false;
752
+ };
753
+ },
754
+ [ref]
755
+ );
672
756
  return ref;
673
757
  }
674
758
 
675
759
  // src/hooks/useLongPress/useLongPress.ts
676
- import { useCallback as useCallback13, useRef as useRef10 } from "react";
760
+ import { useCallback as useCallback13, useRef as useRef11 } from "react";
677
761
  function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLongPressEnd } = {}) {
678
- const timeoutRef = useRef10(null);
679
- const isLongPressActiveRef = useRef10(false);
680
- const initialPositionRef = useRef10({ x: 0, y: 0 });
762
+ const timeoutRef = useRef11(null);
763
+ const isLongPressActiveRef = useRef11(false);
764
+ const initialPositionRef = useRef11({ x: 0, y: 0 });
681
765
  const preservedOnLongPress = usePreservedCallback(onLongPress);
682
766
  const preservedOnClick = usePreservedCallback(onClick || (() => {
683
767
  }));
@@ -753,26 +837,9 @@ function useLongPress(onLongPress, { delay = 500, moveThreshold, onClick, onLong
753
837
  }
754
838
 
755
839
  // src/hooks/useMap/useMap.ts
756
- import { useCallback as useCallback14, useMemo as useMemo6, useState as useState7 } from "react";
757
-
758
- // src/hooks/usePreservedReference/usePreservedReference.ts
759
- import { useMemo as useMemo5, useRef as useRef11 } from "react";
760
- function usePreservedReference(value, areValuesEqual = areDeeplyEqual) {
761
- const ref = useRef11(value);
762
- return useMemo5(() => {
763
- if (!areValuesEqual(ref.current, value)) {
764
- ref.current = value;
765
- }
766
- return ref.current;
767
- }, [areValuesEqual, value]);
768
- }
769
- function areDeeplyEqual(x, y) {
770
- return JSON.stringify(x) === JSON.stringify(y);
771
- }
772
-
773
- // src/hooks/useMap/useMap.ts
840
+ import { useCallback as useCallback14, useMemo as useMemo7, useState as useState9 } from "react";
774
841
  function useMap(initialState = /* @__PURE__ */ new Map()) {
775
- const [map, setMap] = useState7(() => new Map(initialState));
842
+ const [map, setMap] = useState9(() => new Map(initialState));
776
843
  const preservedInitialState = usePreservedReference(initialState);
777
844
  const set = useCallback14((key, value) => {
778
845
  setMap((prev) => {
@@ -794,14 +861,14 @@ function useMap(initialState = /* @__PURE__ */ new Map()) {
794
861
  const reset = useCallback14(() => {
795
862
  setMap(() => new Map(preservedInitialState));
796
863
  }, [preservedInitialState]);
797
- const actions = useMemo6(() => {
864
+ const actions = useMemo7(() => {
798
865
  return { set, setAll, remove, reset };
799
866
  }, [set, setAll, remove, reset]);
800
867
  return [map, actions];
801
868
  }
802
869
 
803
870
  // src/hooks/useOutsideClickEffect/useOutsideClickEffect.ts
804
- import { useEffect as useEffect13, useRef as useRef12 } from "react";
871
+ import { useEffect as useEffect14, useRef as useRef12 } from "react";
805
872
  function useOutsideClickEffect(container, callback) {
806
873
  const containers = useRef12([]);
807
874
  const handleDocumentClick = usePreservedCallback(({ target }) => {
@@ -816,10 +883,10 @@ function useOutsideClickEffect(container, callback) {
816
883
  }
817
884
  callback();
818
885
  });
819
- useEffect13(() => {
886
+ useEffect14(() => {
820
887
  containers.current = [container].flat(1).filter((item) => item != null);
821
888
  }, [container]);
822
- useEffect13(() => {
889
+ useEffect14(() => {
823
890
  document.addEventListener("click", handleDocumentClick);
824
891
  return () => {
825
892
  document.removeEventListener("click", handleDocumentClick);
@@ -845,6 +912,49 @@ function usePrevious(state, compare = strictEquals) {
845
912
  return prevRef.current;
846
913
  }
847
914
 
915
+ // src/hooks/useSet/useSet.ts
916
+ import { useMemo as useMemo8, useState as useState10 } from "react";
917
+ function useSet(initialState = /* @__PURE__ */ new Set()) {
918
+ const [set, setSet] = useState10(() => new Set(initialState));
919
+ const preservedInitialState = usePreservedReference(initialState);
920
+ const add = usePreservedCallback((value) => {
921
+ setSet((prev) => {
922
+ const nextSet = new Set(prev);
923
+ nextSet.add(value);
924
+ return nextSet;
925
+ });
926
+ });
927
+ const remove = usePreservedCallback((value) => {
928
+ setSet((prev) => {
929
+ const nextSet = new Set(prev);
930
+ nextSet.delete(value);
931
+ return nextSet;
932
+ });
933
+ });
934
+ const toggle2 = usePreservedCallback((value) => {
935
+ setSet((prev) => {
936
+ const nextSet = new Set(prev);
937
+ if (nextSet.has(value)) {
938
+ nextSet.delete(value);
939
+ } else {
940
+ nextSet.add(value);
941
+ }
942
+ return nextSet;
943
+ });
944
+ });
945
+ const setAll = usePreservedCallback((values) => {
946
+ setSet(() => new Set(values));
947
+ });
948
+ const reset = usePreservedCallback(() => {
949
+ setSet(() => new Set(preservedInitialState));
950
+ });
951
+ const actions = useMemo8(
952
+ () => ({ add, remove, toggle: toggle2, setAll, reset }),
953
+ [add, remove, toggle2, setAll, reset]
954
+ );
955
+ return [set, actions];
956
+ }
957
+
848
958
  // src/hooks/useStorageState/useStorageState.ts
849
959
  import { useCallback as useCallback15, useRef as useRef14, useSyncExternalStore } from "react";
850
960
 
@@ -1012,7 +1122,7 @@ function useStorageState(key, {
1012
1122
  }
1013
1123
 
1014
1124
  // src/hooks/useThrottle/useThrottle.ts
1015
- import { useEffect as useEffect14, useMemo as useMemo7 } from "react";
1125
+ import { useEffect as useEffect15, useMemo as useMemo9 } from "react";
1016
1126
 
1017
1127
  // src/hooks/useThrottle/throttle.ts
1018
1128
  function throttle(func, throttleMs, { edges = ["leading", "trailing"] } = {}) {
@@ -1037,11 +1147,11 @@ function throttle(func, throttleMs, { edges = ["leading", "trailing"] } = {}) {
1037
1147
  function useThrottle(callback, wait, options) {
1038
1148
  const preservedCallback = usePreservedCallback(callback);
1039
1149
  const preservedOptions = usePreservedReference(options ?? {});
1040
- const throttledCallback = useMemo7(
1150
+ const throttledCallback = useMemo9(
1041
1151
  () => throttle(preservedCallback, wait, preservedOptions),
1042
1152
  [preservedOptions, preservedCallback, wait]
1043
1153
  );
1044
- useEffect14(() => {
1154
+ useEffect15(() => {
1045
1155
  return () => {
1046
1156
  throttledCallback.cancel();
1047
1157
  };
@@ -1049,13 +1159,51 @@ function useThrottle(callback, wait, options) {
1049
1159
  return throttledCallback;
1050
1160
  }
1051
1161
 
1162
+ // src/hooks/useThrottledCallback/useThrottledCallback.ts
1163
+ import { useCallback as useCallback16, useEffect as useEffect16, useRef as useRef15 } from "react";
1164
+ function useThrottledCallback({
1165
+ onChange,
1166
+ timeThreshold,
1167
+ edges = ["leading", "trailing"]
1168
+ }) {
1169
+ const handleChange = usePreservedCallback(onChange);
1170
+ const ref = useRef15({ value: false, clearPreviousThrottle: () => {
1171
+ } });
1172
+ useEffect16(function cleanupThrottleOnUnmount() {
1173
+ const current = ref.current;
1174
+ return () => {
1175
+ current.clearPreviousThrottle();
1176
+ };
1177
+ }, []);
1178
+ const preservedEdges = usePreservedReference(edges);
1179
+ return useCallback16(
1180
+ (nextValue) => {
1181
+ if (nextValue === ref.current.value) {
1182
+ return;
1183
+ }
1184
+ const throttled = throttle(
1185
+ () => {
1186
+ handleChange(nextValue);
1187
+ ref.current.value = nextValue;
1188
+ },
1189
+ timeThreshold,
1190
+ { edges: preservedEdges }
1191
+ );
1192
+ ref.current.clearPreviousThrottle();
1193
+ throttled();
1194
+ ref.current.clearPreviousThrottle = throttled.cancel;
1195
+ },
1196
+ [handleChange, timeThreshold, preservedEdges]
1197
+ );
1198
+ }
1199
+
1052
1200
  // src/hooks/useTimeout/useTimeout.ts
1053
- import { useEffect as useEffect15 } from "react";
1201
+ import { useEffect as useEffect17 } from "react";
1054
1202
  function useTimeout(callback, delay = 0) {
1055
1203
  const preservedCallback = usePreservedCallback(callback);
1056
- useEffect15(() => {
1057
- const timeoutId = window.setTimeout(preservedCallback, delay);
1058
- return () => window.clearTimeout(timeoutId);
1204
+ useEffect17(() => {
1205
+ const timeoutId = setTimeout(preservedCallback, delay);
1206
+ return () => clearTimeout(timeoutId);
1059
1207
  }, [delay, preservedCallback]);
1060
1208
  }
1061
1209
 
@@ -1067,12 +1215,12 @@ function useToggle(initialValue = false) {
1067
1215
  var toggle = (state) => !state;
1068
1216
 
1069
1217
  // src/utils/buildContext/buildContext.tsx
1070
- import { createContext, useContext, useMemo as useMemo8 } from "react";
1218
+ import { createContext, useContext, useMemo as useMemo10 } from "react";
1071
1219
  import { jsx as jsx3 } from "react/jsx-runtime";
1072
1220
  function buildContext(contextName, defaultContextValues) {
1073
1221
  const Context = createContext(defaultContextValues ?? void 0);
1074
1222
  function Provider({ children, ...contextValues }) {
1075
- const value = useMemo8(
1223
+ const value = useMemo10(
1076
1224
  () => Object.keys(contextValues).length > 0 ? contextValues : null,
1077
1225
  // eslint-disable-next-line react-hooks/exhaustive-deps
1078
1226
  [...Object.values(contextValues)]
@@ -1153,7 +1301,9 @@ export {
1153
1301
  useInputState,
1154
1302
  useIntersectionObserver,
1155
1303
  useInterval,
1304
+ useIsClient,
1156
1305
  useIsomorphicLayoutEffect,
1306
+ useList,
1157
1307
  useLoading,
1158
1308
  useLongPress,
1159
1309
  useMap,
@@ -1162,8 +1312,10 @@ export {
1162
1312
  usePreservedReference,
1163
1313
  usePrevious,
1164
1314
  useRefEffect,
1315
+ useSet,
1165
1316
  useStorageState,
1166
1317
  useThrottle,
1318
+ useThrottledCallback,
1167
1319
  useTimeout,
1168
1320
  useToggle,
1169
1321
  useVisibilityEvent
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-simplikit",
3
- "version": "0.0.48",
3
+ "version": "0.0.49",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./esm/index.js",
6
6
  "types": "./dist/index.d.cts",