react-simplikit 0.1.0 → 0.2.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -41
  3. package/dist/hooks/useDebouncedCallback/useDebouncedCallback.cjs +24 -6
  4. package/dist/hooks/useDebouncedCallback/useDebouncedCallback.d.cts +17 -7
  5. package/dist/hooks/useDebouncedCallback/useDebouncedCallback.d.mts +17 -7
  6. package/dist/hooks/useDebouncedCallback/useDebouncedCallback.mjs +24 -6
  7. package/dist/hooks/useDoubleClick/useDoubleClick.cjs +0 -4
  8. package/dist/hooks/useDoubleClick/useDoubleClick.d.cts +0 -4
  9. package/dist/hooks/useDoubleClick/useDoubleClick.d.mts +0 -4
  10. package/dist/hooks/useDoubleClick/useDoubleClick.mjs +0 -4
  11. package/dist/hooks/useGeolocation/useGeolocation.cjs +0 -4
  12. package/dist/hooks/useGeolocation/useGeolocation.d.cts +0 -4
  13. package/dist/hooks/useGeolocation/useGeolocation.d.mts +0 -4
  14. package/dist/hooks/useGeolocation/useGeolocation.mjs +0 -4
  15. package/dist/hooks/useImpressionRef/useImpressionRef.cjs +7 -5
  16. package/dist/hooks/useImpressionRef/useImpressionRef.d.cts +0 -4
  17. package/dist/hooks/useImpressionRef/useImpressionRef.d.mts +0 -4
  18. package/dist/hooks/useImpressionRef/useImpressionRef.mjs +7 -5
  19. package/dist/hooks/useIntersectionObserver/useIntersectionObserver.cjs +1 -5
  20. package/dist/hooks/useIntersectionObserver/useIntersectionObserver.d.cts +1 -5
  21. package/dist/hooks/useIntersectionObserver/useIntersectionObserver.d.mts +1 -5
  22. package/dist/hooks/useIntersectionObserver/useIntersectionObserver.mjs +1 -5
  23. package/dist/hooks/useList/useList.cjs +11 -8
  24. package/dist/hooks/useList/useList.d.cts +12 -9
  25. package/dist/hooks/useList/useList.d.mts +12 -9
  26. package/dist/hooks/useList/useList.mjs +11 -8
  27. package/dist/hooks/useLongPress/useLongPress.cjs +0 -4
  28. package/dist/hooks/useLongPress/useLongPress.d.cts +0 -4
  29. package/dist/hooks/useLongPress/useLongPress.d.mts +0 -4
  30. package/dist/hooks/useLongPress/useLongPress.mjs +0 -4
  31. package/dist/hooks/useOutsideClickEffect/useOutsideClickEffect.cjs +0 -4
  32. package/dist/hooks/useOutsideClickEffect/useOutsideClickEffect.d.cts +0 -4
  33. package/dist/hooks/useOutsideClickEffect/useOutsideClickEffect.d.mts +0 -4
  34. package/dist/hooks/useOutsideClickEffect/useOutsideClickEffect.mjs +0 -4
  35. package/dist/hooks/useSet/useSet.cjs +11 -2
  36. package/dist/hooks/useSet/useSet.d.cts +11 -2
  37. package/dist/hooks/useSet/useSet.d.mts +11 -2
  38. package/dist/hooks/useSet/useSet.mjs +11 -2
  39. package/dist/hooks/useStorageState/useStorageState.d.cts +0 -4
  40. package/dist/hooks/useStorageState/useStorageState.d.mts +0 -4
  41. package/dist/hooks/useThrottledCallback/useThrottledCallback.cjs +16 -9
  42. package/dist/hooks/useThrottledCallback/useThrottledCallback.d.cts +18 -11
  43. package/dist/hooks/useThrottledCallback/useThrottledCallback.d.mts +18 -11
  44. package/dist/hooks/useThrottledCallback/useThrottledCallback.mjs +16 -9
  45. package/dist/hooks/useVisibilityEvent/useVisibilityEvent.cjs +2 -4
  46. package/dist/hooks/useVisibilityEvent/useVisibilityEvent.d.cts +2 -4
  47. package/dist/hooks/useVisibilityEvent/useVisibilityEvent.d.mts +2 -4
  48. package/dist/hooks/useVisibilityEvent/useVisibilityEvent.mjs +2 -4
  49. package/dist/index.d.cts +2 -2
  50. package/dist/index.d.mts +2 -2
  51. package/dist/mobile/hooks/usePageVisibility/usePageVisibility.cjs +2 -0
  52. package/dist/mobile/hooks/usePageVisibility/usePageVisibility.d.cts +2 -0
  53. package/dist/mobile/hooks/usePageVisibility/usePageVisibility.d.mts +2 -0
  54. package/dist/mobile/hooks/usePageVisibility/usePageVisibility.mjs +2 -0
  55. package/dist/utils/mergeProps/mergeProps.cjs +1 -1
  56. package/dist/utils/mergeProps/mergeProps.d.cts +1 -1
  57. package/dist/utils/mergeProps/mergeProps.d.mts +1 -1
  58. package/dist/utils/mergeProps/mergeProps.mjs +1 -1
  59. package/dist/utils/mergeRefs/mergeRefs.cjs +1 -1
  60. package/dist/utils/mergeRefs/mergeRefs.d.cts +1 -1
  61. package/dist/utils/mergeRefs/mergeRefs.d.mts +1 -1
  62. package/dist/utils/mergeRefs/mergeRefs.mjs +1 -1
  63. package/package.json +1 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # react-simplikit
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#446](https://github.com/toss/react-simplikit/pull/446) [`0b66d40`](https://github.com/toss/react-simplikit/commit/0b66d40e56b4a183fd1fc5dce8a685e2a0da2839) Thanks [@hyesungoh](https://github.com/hyesungoh)! - `useDebouncedCallback` and `useThrottledCallback` now accept any value type: `onChange` is typed `(newValue: T) => void` instead of `(newValue: boolean) => void`, so a debounced search query or a throttled scroll position no longer needs a cast. Existing boolean callers are unaffected.
8
+
9
+ `useDebouncedCallback` no longer drops a first call of `false`. It compared incoming values against a seed of `false`, so the very first `false` looked redundant and was never forwarded; the comparison now starts from a sentinel, as `useThrottledCallback` already did. A `false` that arrives while an initial `true` is still pending now replaces it instead of being ignored.
10
+
11
+ `useImpressionRef` no longer emits `onImpressionEnd` for an element that was never impressed.
12
+
13
+ ### Patch Changes
14
+
15
+ - [#450](https://github.com/toss/react-simplikit/pull/450) [`a4251a3`](https://github.com/toss/react-simplikit/commit/a4251a30aafbfabc61e6cc9a80de1af86936bb2a) Thanks [@hyesungoh](https://github.com/hyesungoh)! - `useDebouncedCallback` and `useThrottledCallback` no longer forward a stale value when the caller returns to the last forwarded one. Calling with `'seo'` and then `'seoul'` right after `'seoul'` had already been forwarded used to skip the second call as a duplicate without cancelling the pending `'seo'`, so `onChange('seo')` fired anyway. The pending call is now cancelled first. For `useThrottledCallback` this only showed with `edges: ['trailing']`; the default leading edge forwards the intermediate value immediately and masked it.
16
+
17
+ - [#452](https://github.com/toss/react-simplikit/pull/452) [`fd312f5`](https://github.com/toss/react-simplikit/commit/fd312f589430154d38b7d5d5998f1f20ceb0be54) Thanks [@hyesungoh](https://github.com/hyesungoh)! - JSDoc corrections that show up in editor hover. `useIntersectionObserver`'s `options.root` is typed `Element | Document | null` instead of `boolean`. `useList` and `useSet` now declare their generic parameter, their optional initial state and every member they return. `mergeProps` and `mergeRefs` mark their rest parameter as one, so the documented signature matches the implementation.
18
+
19
+ - [#456](https://github.com/toss/react-simplikit/pull/456) [`65ce435`](https://github.com/toss/react-simplikit/commit/65ce435abfca276f2a22c01b6ff50dc5530831fc) Thanks [@mnxmnz](https://github.com/mnxmnz)! - Re-export the `SafeAreaInset` type from the package root. `@react-simplikit/mobile` exported it, but it was dropped when that package was absorbed into the root entry, leaving `import type { SafeAreaInset }` with no replacement.
20
+
21
+ - [#435](https://github.com/toss/react-simplikit/pull/435) [`9e05182`](https://github.com/toss/react-simplikit/commit/9e051826418a852996ae851a7f8c8e53c1408852) Thanks [@hyesungoh](https://github.com/hyesungoh)! - `useDoubleClick`, `useGeolocation`, `useImpressionRef`, `useIntersectionObserver`, `useLongPress`, `useOutsideClickEffect`, `useStorageState` and `useVisibilityEvent` are no longer marked `@deprecated`. They are maintained hooks again: editors stop rendering them struck-through, and no removal is planned.
22
+
3
23
  ## 0.1.0
4
24
 
5
25
  ### Minor Changes
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/toss/react-simplikit/blob/main/LICENSE)
5
5
  [![codecov](https://codecov.io/gh/toss/react-simplikit/graph/badge.svg?token=RHVOZ3J3TU)](https://codecov.io/gh/toss/react-simplikit)
6
6
 
7
- English | [한국어](./README-ko_kr.md) | [日本語](./README-ja_jp.md)
7
+ English | [한국어](./README-ko_kr.md) | [日本語](./README-ja_jp.md) | [简体中文](./README-zh_hans.md) | [Español](./README-es.md)
8
8
 
9
9
  A lightweight, zero-dependency React utilities library providing hooks, components, and utilities.
10
10
 
@@ -16,46 +16,6 @@ A lightweight, zero-dependency React utilities library providing hooks, componen
16
16
  - **SSR-safe** - Works with Next.js and other SSR frameworks
17
17
  - **Tree-shakeable** - Only bundle what you use
18
18
 
19
- ## Library Direction
20
-
21
- **react-simplikit is now maintained as a Universal Hook Library providing only pure state/logic hooks.**
22
-
23
- We are repositioning react-simplikit to focus exclusively on **platform-independent hooks** that work seamlessly across web and mobile (React Native, etc.).
24
-
25
- ### What's Maintained: Pure State/Logic Hooks
26
-
27
- Hooks that don't depend on specific platform APIs will continue to be actively maintained:
28
-
29
- - State management hooks like `useToggle`, `useBooleanState`, `useCounter`
30
- - Lifecycle hooks like `usePrevious`
31
- - Utility hooks like `useDebounce`, `useThrottle`
32
- - **Backward compatibility (BC) is preserved** for these existing pure logic hooks
33
-
34
- ### What's Deprecated: Browser/Platform-Dependent Hooks
35
-
36
- The following hooks that strongly depend on browser-specific APIs are now deprecated:
37
-
38
- - `useGeolocation` - depends on `navigator.geolocation`
39
- - `useStorageState` - depends on `localStorage`/`sessionStorage`
40
- - `useIntersectionObserver` - depends on `IntersectionObserver` API
41
- - `useImpressionRef` - depends on `IntersectionObserver` + Visibility API
42
- - `useDoubleClick`, `useLongPress` - depend on DOM events + `window.setTimeout`
43
- - `useOutsideClickEffect` - depends on DOM events + `document`
44
- - `useVisibilityEvent` - depends on `document.visibilityState`
45
-
46
- These hooks:
47
-
48
- - Will not receive new features or major enhancements
49
- - Are marked as `@deprecated` in documentation
50
- - May be removed in future major versions
51
-
52
- ### Package Status
53
-
54
- - react-simplikit will **not be archived**
55
- - Pure state/logic hooks will continue to be maintained
56
- - Critical bug fixes and minimal maintenance will continue
57
- - No new browser/platform-dependent hooks will be added
58
-
59
19
  ## Installation
60
20
 
61
21
  ```bash
@@ -4,31 +4,49 @@ const require_usePreservedCallback = require("../usePreservedCallback/usePreserv
4
4
  let react = require("react");
5
5
  //#region src/hooks/useDebouncedCallback/useDebouncedCallback.ts
6
6
  /**
7
+ * Marks that no value has been forwarded to `onChange` yet.
8
+ *
9
+ * The hook skips redundant invocations by comparing against the last forwarded value, but it
10
+ * receives no initial value from the caller. Seeding that comparison with a real value would treat
11
+ * the first call of that value as redundant and swallow it, so an unreachable sentinel is used instead.
12
+ */
13
+ const NOT_INVOKED = Symbol("NOT_INVOKED");
14
+ /**
7
15
  * @description
8
16
  * `useDebouncedCallback` is a React hook that returns a debounced version of the provided callback function.
9
17
  * It helps optimize event handling by delaying function execution and grouping multiple calls into one.
10
18
  *
11
19
  * Note that if both 'leading' and 'trailing' are set, the function will be called at both the start and end of the delay period. However, it must be called at least twice within debounceMs interval for this to happen, since one debounced function call cannot trigger the function twice.
12
20
  *
21
+ * @template T - The type of the value passed to `onChange`.
13
22
  * @param {Object} options - The options object.
14
- * @param {Function} options.onChange - The callback function to debounce.
23
+ * @param {(newValue: T) => void} options.onChange - The callback to debounce. A call with the same value as the last forwarded one is skipped.
15
24
  * @param {number} options.timeThreshold - The number of milliseconds to delay the function execution.
16
25
  * @param {boolean} [options.leading=false] - If `true`, the function is called at the start of the sequence.
17
26
  * @param {boolean} [options.trailing=true] - If `true`, the function is called at the end of the sequence.
18
27
  *
19
- * @returns {Function} A debounced function that delays invoking the callback.
28
+ * @returns {(nextValue: T) => void} A debounced function that forwards the value to `onChange`.
20
29
  *
21
30
  * @example
31
+ * import { useDebouncedCallback } from 'react-simplikit';
32
+ * import { useState } from 'react';
33
+ *
22
34
  * function SearchInput() {
23
35
  * const [query, setQuery] = useState('');
24
- * const debouncedSetQuery = useDebouncedCallback({ onChange: setQuery, timeThreshold: 100 });
25
- * return <input type="text" onChange={(e) => debouncedSetQuery(e.target.value)} />;
36
+ * const setQueryDebounced = useDebouncedCallback({ onChange: setQuery, timeThreshold: 300 });
37
+ *
38
+ * return (
39
+ * <>
40
+ * <input onChange={e => setQueryDebounced(e.target.value)} />
41
+ * <p>Searching for: {query}</p>
42
+ * </>
43
+ * );
26
44
  * }
27
45
  */
28
46
  function useDebouncedCallback({ onChange, timeThreshold, leading = false, trailing = true }) {
29
47
  const handleChange = require_usePreservedCallback.usePreservedCallback(onChange);
30
48
  const ref = (0, react.useRef)({
31
- value: false,
49
+ value: NOT_INVOKED,
32
50
  clearPreviousDebounce: () => {}
33
51
  });
34
52
  (0, react.useEffect)(function clearDebouncedOnUnmount() {
@@ -44,12 +62,12 @@ function useDebouncedCallback({ onChange, timeThreshold, leading = false, traili
44
62
  return _edges;
45
63
  }, [leading, trailing]);
46
64
  return (0, react.useCallback)((nextValue) => {
65
+ ref.current.clearPreviousDebounce();
47
66
  if (nextValue === ref.current.value) return;
48
67
  const debounced = require_debounce.debounce(() => {
49
68
  handleChange(nextValue);
50
69
  ref.current.value = nextValue;
51
70
  }, timeThreshold, { edges });
52
- ref.current.clearPreviousDebounce();
53
71
  debounced();
54
72
  ref.current.clearPreviousDebounce = debounced.cancel;
55
73
  }, [
@@ -11,24 +11,34 @@ type DebounceOptions = {
11
11
  *
12
12
  * Note that if both 'leading' and 'trailing' are set, the function will be called at both the start and end of the delay period. However, it must be called at least twice within debounceMs interval for this to happen, since one debounced function call cannot trigger the function twice.
13
13
  *
14
+ * @template T - The type of the value passed to `onChange`.
14
15
  * @param {Object} options - The options object.
15
- * @param {Function} options.onChange - The callback function to debounce.
16
+ * @param {(newValue: T) => void} options.onChange - The callback to debounce. A call with the same value as the last forwarded one is skipped.
16
17
  * @param {number} options.timeThreshold - The number of milliseconds to delay the function execution.
17
18
  * @param {boolean} [options.leading=false] - If `true`, the function is called at the start of the sequence.
18
19
  * @param {boolean} [options.trailing=true] - If `true`, the function is called at the end of the sequence.
19
20
  *
20
- * @returns {Function} A debounced function that delays invoking the callback.
21
+ * @returns {(nextValue: T) => void} A debounced function that forwards the value to `onChange`.
21
22
  *
22
23
  * @example
24
+ * import { useDebouncedCallback } from 'react-simplikit';
25
+ * import { useState } from 'react';
26
+ *
23
27
  * function SearchInput() {
24
28
  * const [query, setQuery] = useState('');
25
- * const debouncedSetQuery = useDebouncedCallback({ onChange: setQuery, timeThreshold: 100 });
26
- * return <input type="text" onChange={(e) => debouncedSetQuery(e.target.value)} />;
29
+ * const setQueryDebounced = useDebouncedCallback({ onChange: setQuery, timeThreshold: 300 });
30
+ *
31
+ * return (
32
+ * <>
33
+ * <input onChange={e => setQueryDebounced(e.target.value)} />
34
+ * <p>Searching for: {query}</p>
35
+ * </>
36
+ * );
27
37
  * }
28
38
  */
29
- declare function useDebouncedCallback({ onChange, timeThreshold, leading, trailing }: DebounceOptions & {
30
- onChange: (newValue: boolean) => void;
39
+ declare function useDebouncedCallback<T>({ onChange, timeThreshold, leading, trailing }: DebounceOptions & {
40
+ onChange: (newValue: T) => void;
31
41
  timeThreshold: number;
32
- }): (nextValue: boolean) => void;
42
+ }): (nextValue: T) => void;
33
43
  //#endregion
34
44
  export { useDebouncedCallback };
@@ -11,24 +11,34 @@ type DebounceOptions = {
11
11
  *
12
12
  * Note that if both 'leading' and 'trailing' are set, the function will be called at both the start and end of the delay period. However, it must be called at least twice within debounceMs interval for this to happen, since one debounced function call cannot trigger the function twice.
13
13
  *
14
+ * @template T - The type of the value passed to `onChange`.
14
15
  * @param {Object} options - The options object.
15
- * @param {Function} options.onChange - The callback function to debounce.
16
+ * @param {(newValue: T) => void} options.onChange - The callback to debounce. A call with the same value as the last forwarded one is skipped.
16
17
  * @param {number} options.timeThreshold - The number of milliseconds to delay the function execution.
17
18
  * @param {boolean} [options.leading=false] - If `true`, the function is called at the start of the sequence.
18
19
  * @param {boolean} [options.trailing=true] - If `true`, the function is called at the end of the sequence.
19
20
  *
20
- * @returns {Function} A debounced function that delays invoking the callback.
21
+ * @returns {(nextValue: T) => void} A debounced function that forwards the value to `onChange`.
21
22
  *
22
23
  * @example
24
+ * import { useDebouncedCallback } from 'react-simplikit';
25
+ * import { useState } from 'react';
26
+ *
23
27
  * function SearchInput() {
24
28
  * const [query, setQuery] = useState('');
25
- * const debouncedSetQuery = useDebouncedCallback({ onChange: setQuery, timeThreshold: 100 });
26
- * return <input type="text" onChange={(e) => debouncedSetQuery(e.target.value)} />;
29
+ * const setQueryDebounced = useDebouncedCallback({ onChange: setQuery, timeThreshold: 300 });
30
+ *
31
+ * return (
32
+ * <>
33
+ * <input onChange={e => setQueryDebounced(e.target.value)} />
34
+ * <p>Searching for: {query}</p>
35
+ * </>
36
+ * );
27
37
  * }
28
38
  */
29
- declare function useDebouncedCallback({ onChange, timeThreshold, leading, trailing }: DebounceOptions & {
30
- onChange: (newValue: boolean) => void;
39
+ declare function useDebouncedCallback<T>({ onChange, timeThreshold, leading, trailing }: DebounceOptions & {
40
+ onChange: (newValue: T) => void;
31
41
  timeThreshold: number;
32
- }): (nextValue: boolean) => void;
42
+ }): (nextValue: T) => void;
33
43
  //#endregion
34
44
  export { useDebouncedCallback };
@@ -4,31 +4,49 @@ import { usePreservedCallback } from "../usePreservedCallback/usePreservedCallba
4
4
  import { useCallback, useEffect, useMemo, useRef } from "react";
5
5
  //#region src/hooks/useDebouncedCallback/useDebouncedCallback.ts
6
6
  /**
7
+ * Marks that no value has been forwarded to `onChange` yet.
8
+ *
9
+ * The hook skips redundant invocations by comparing against the last forwarded value, but it
10
+ * receives no initial value from the caller. Seeding that comparison with a real value would treat
11
+ * the first call of that value as redundant and swallow it, so an unreachable sentinel is used instead.
12
+ */
13
+ const NOT_INVOKED = Symbol("NOT_INVOKED");
14
+ /**
7
15
  * @description
8
16
  * `useDebouncedCallback` is a React hook that returns a debounced version of the provided callback function.
9
17
  * It helps optimize event handling by delaying function execution and grouping multiple calls into one.
10
18
  *
11
19
  * Note that if both 'leading' and 'trailing' are set, the function will be called at both the start and end of the delay period. However, it must be called at least twice within debounceMs interval for this to happen, since one debounced function call cannot trigger the function twice.
12
20
  *
21
+ * @template T - The type of the value passed to `onChange`.
13
22
  * @param {Object} options - The options object.
14
- * @param {Function} options.onChange - The callback function to debounce.
23
+ * @param {(newValue: T) => void} options.onChange - The callback to debounce. A call with the same value as the last forwarded one is skipped.
15
24
  * @param {number} options.timeThreshold - The number of milliseconds to delay the function execution.
16
25
  * @param {boolean} [options.leading=false] - If `true`, the function is called at the start of the sequence.
17
26
  * @param {boolean} [options.trailing=true] - If `true`, the function is called at the end of the sequence.
18
27
  *
19
- * @returns {Function} A debounced function that delays invoking the callback.
28
+ * @returns {(nextValue: T) => void} A debounced function that forwards the value to `onChange`.
20
29
  *
21
30
  * @example
31
+ * import { useDebouncedCallback } from 'react-simplikit';
32
+ * import { useState } from 'react';
33
+ *
22
34
  * function SearchInput() {
23
35
  * const [query, setQuery] = useState('');
24
- * const debouncedSetQuery = useDebouncedCallback({ onChange: setQuery, timeThreshold: 100 });
25
- * return <input type="text" onChange={(e) => debouncedSetQuery(e.target.value)} />;
36
+ * const setQueryDebounced = useDebouncedCallback({ onChange: setQuery, timeThreshold: 300 });
37
+ *
38
+ * return (
39
+ * <>
40
+ * <input onChange={e => setQueryDebounced(e.target.value)} />
41
+ * <p>Searching for: {query}</p>
42
+ * </>
43
+ * );
26
44
  * }
27
45
  */
28
46
  function useDebouncedCallback({ onChange, timeThreshold, leading = false, trailing = true }) {
29
47
  const handleChange = usePreservedCallback(onChange);
30
48
  const ref = useRef({
31
- value: false,
49
+ value: NOT_INVOKED,
32
50
  clearPreviousDebounce: () => {}
33
51
  });
34
52
  useEffect(function clearDebouncedOnUnmount() {
@@ -44,12 +62,12 @@ function useDebouncedCallback({ onChange, timeThreshold, leading = false, traili
44
62
  return _edges;
45
63
  }, [leading, trailing]);
46
64
  return useCallback((nextValue) => {
65
+ ref.current.clearPreviousDebounce();
47
66
  if (nextValue === ref.current.value) return;
48
67
  const debounced = debounce(() => {
49
68
  handleChange(nextValue);
50
69
  ref.current.value = nextValue;
51
70
  }, timeThreshold, { edges });
52
- ref.current.clearPreviousDebounce();
53
71
  debounced();
54
72
  ref.current.clearPreviousDebounce = debounced.cancel;
55
73
  }, [
@@ -3,10 +3,6 @@ const require_usePreservedCallback = require("../usePreservedCallback/usePreserv
3
3
  let react = require("react");
4
4
  //#region src/hooks/useDoubleClick/useDoubleClick.ts
5
5
  /**
6
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (DOM events, window.setTimeout).
7
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
8
- * This hook will be removed in a future major version.
9
- *
10
6
  * @description
11
7
  * `useDoubleClick` is a React hook that differentiates between single and double click events.
12
8
  * It delays the single click callback execution for a specified time, and cancels it if a second click (i.e. a double click) occurs within that time.
@@ -7,10 +7,6 @@ type UseDoubleClickProps<E extends HTMLElement> = {
7
7
  doubleClick: (event: MouseEvent<E>) => void;
8
8
  };
9
9
  /**
10
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (DOM events, window.setTimeout).
11
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
12
- * This hook will be removed in a future major version.
13
- *
14
10
  * @description
15
11
  * `useDoubleClick` is a React hook that differentiates between single and double click events.
16
12
  * It delays the single click callback execution for a specified time, and cancels it if a second click (i.e. a double click) occurs within that time.
@@ -7,10 +7,6 @@ type UseDoubleClickProps<E extends HTMLElement> = {
7
7
  doubleClick: (event: MouseEvent<E>) => void;
8
8
  };
9
9
  /**
10
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (DOM events, window.setTimeout).
11
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
12
- * This hook will be removed in a future major version.
13
- *
14
10
  * @description
15
11
  * `useDoubleClick` is a React hook that differentiates between single and double click events.
16
12
  * It delays the single click callback execution for a specified time, and cancels it if a second click (i.e. a double click) occurs within that time.
@@ -3,10 +3,6 @@ import { usePreservedCallback } from "../usePreservedCallback/usePreservedCallba
3
3
  import { useCallback, useEffect, useRef } from "react";
4
4
  //#region src/hooks/useDoubleClick/useDoubleClick.ts
5
5
  /**
6
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (DOM events, window.setTimeout).
7
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
8
- * This hook will be removed in a future major version.
9
- *
10
6
  * @description
11
7
  * `useDoubleClick` is a React hook that differentiates between single and double click events.
12
8
  * It delays the single click callback execution for a specified time, and cancels it if a second click (i.e. a double click) occurs within that time.
@@ -14,10 +14,6 @@ const GeolocationMountBehavior = {
14
14
  WATCH: "watch"
15
15
  };
16
16
  /**
17
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (navigator.geolocation).
18
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
19
- * This hook will be removed in a future major version.
20
- *
21
17
  * @description
22
18
  * `useGeolocation` is a React hook that retrieves and tracks the user's geographical location.
23
19
  * It uses the browser's `Geolocation API` to support both one-time position retrieval and continuous location tracking.
@@ -26,10 +26,6 @@ type GeolocationOptions = {
26
26
  mountBehavior?: GeolocationMountBehaviorType;
27
27
  } & PositionOptions;
28
28
  /**
29
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (navigator.geolocation).
30
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
31
- * This hook will be removed in a future major version.
32
- *
33
29
  * @description
34
30
  * `useGeolocation` is a React hook that retrieves and tracks the user's geographical location.
35
31
  * It uses the browser's `Geolocation API` to support both one-time position retrieval and continuous location tracking.
@@ -26,10 +26,6 @@ type GeolocationOptions = {
26
26
  mountBehavior?: GeolocationMountBehaviorType;
27
27
  } & PositionOptions;
28
28
  /**
29
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (navigator.geolocation).
30
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
31
- * This hook will be removed in a future major version.
32
- *
33
29
  * @description
34
30
  * `useGeolocation` is a React hook that retrieves and tracks the user's geographical location.
35
31
  * It uses the browser's `Geolocation API` to support both one-time position retrieval and continuous location tracking.
@@ -14,10 +14,6 @@ const GeolocationMountBehavior = {
14
14
  WATCH: "watch"
15
15
  };
16
16
  /**
17
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (navigator.geolocation).
18
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
19
- * This hook will be removed in a future major version.
20
- *
21
17
  * @description
22
18
  * `useGeolocation` is a React hook that retrieves and tracks the user's geographical location.
23
19
  * It uses the browser's `Geolocation API` to support both one-time position retrieval and continuous location tracking.
@@ -6,10 +6,6 @@ const require_useVisibilityEvent = require("../useVisibilityEvent/useVisibilityE
6
6
  let react = require("react");
7
7
  //#region src/hooks/useImpressionRef/useImpressionRef.ts
8
8
  /**
9
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (IntersectionObserver, Visibility API).
10
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
11
- * This hook will be removed in a future major version.
12
- *
13
9
  * @description
14
10
  * `useImpressionRef` is a React hook that measures the time a specific DOM element is visible on the screen and executes callbacks when the element enters or exits the viewport.
15
11
  * It uses `IntersectionObserver` and the `Visibility API` to track the element's visibility.
@@ -41,10 +37,16 @@ function useImpressionRef({ onImpressionStart = () => {}, onImpressionEnd = () =
41
37
  const impressionStartHandler = require_usePreservedCallback.usePreservedCallback(onImpressionStart);
42
38
  const impressionEndHandler = require_usePreservedCallback.usePreservedCallback(onImpressionEnd);
43
39
  const isIntersectingRef = (0, react.useRef)(false);
40
+ const hasImpressionStartedRef = (0, react.useRef)(false);
44
41
  const impressionEventHandler = require_useDebouncedCallback.useDebouncedCallback({
45
42
  timeThreshold,
46
43
  onChange: (impressed) => {
47
- (impressed ? impressionStartHandler : impressionEndHandler)();
44
+ if (impressed) {
45
+ hasImpressionStartedRef.current = true;
46
+ impressionStartHandler();
47
+ return;
48
+ }
49
+ if (hasImpressionStartedRef.current) impressionEndHandler();
48
50
  },
49
51
  leading: true
50
52
  });
@@ -8,10 +8,6 @@ type UseImpressionRefOptions = Partial<{
8
8
  timeThreshold: number;
9
9
  }>;
10
10
  /**
11
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (IntersectionObserver, Visibility API).
12
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
13
- * This hook will be removed in a future major version.
14
- *
15
11
  * @description
16
12
  * `useImpressionRef` is a React hook that measures the time a specific DOM element is visible on the screen and executes callbacks when the element enters or exits the viewport.
17
13
  * It uses `IntersectionObserver` and the `Visibility API` to track the element's visibility.
@@ -8,10 +8,6 @@ type UseImpressionRefOptions = Partial<{
8
8
  timeThreshold: number;
9
9
  }>;
10
10
  /**
11
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (IntersectionObserver, Visibility API).
12
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
13
- * This hook will be removed in a future major version.
14
- *
15
11
  * @description
16
12
  * `useImpressionRef` is a React hook that measures the time a specific DOM element is visible on the screen and executes callbacks when the element enters or exits the viewport.
17
13
  * It uses `IntersectionObserver` and the `Visibility API` to track the element's visibility.
@@ -6,10 +6,6 @@ import { useVisibilityEvent } from "../useVisibilityEvent/useVisibilityEvent.mjs
6
6
  import { useRef } from "react";
7
7
  //#region src/hooks/useImpressionRef/useImpressionRef.ts
8
8
  /**
9
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (IntersectionObserver, Visibility API).
10
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
11
- * This hook will be removed in a future major version.
12
- *
13
9
  * @description
14
10
  * `useImpressionRef` is a React hook that measures the time a specific DOM element is visible on the screen and executes callbacks when the element enters or exits the viewport.
15
11
  * It uses `IntersectionObserver` and the `Visibility API` to track the element's visibility.
@@ -41,10 +37,16 @@ function useImpressionRef({ onImpressionStart = () => {}, onImpressionEnd = () =
41
37
  const impressionStartHandler = usePreservedCallback(onImpressionStart);
42
38
  const impressionEndHandler = usePreservedCallback(onImpressionEnd);
43
39
  const isIntersectingRef = useRef(false);
40
+ const hasImpressionStartedRef = useRef(false);
44
41
  const impressionEventHandler = useDebouncedCallback({
45
42
  timeThreshold,
46
43
  onChange: (impressed) => {
47
- (impressed ? impressionStartHandler : impressionEndHandler)();
44
+ if (impressed) {
45
+ hasImpressionStartedRef.current = true;
46
+ impressionStartHandler();
47
+ return;
48
+ }
49
+ if (hasImpressionStartedRef.current) impressionEndHandler();
48
50
  },
49
51
  leading: true
50
52
  });
@@ -4,10 +4,6 @@ const require_useRefEffect = require("../useRefEffect/useRefEffect.cjs");
4
4
  let react = require("react");
5
5
  //#region src/hooks/useIntersectionObserver/useIntersectionObserver.ts
6
6
  /**
7
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (IntersectionObserver).
8
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
9
- * This hook will be removed in a future major version.
10
- *
11
7
  * @description
12
8
  * `useIntersectionObserver` is a React hook that detects whether a specific DOM element is visible on the screen.
13
9
  * It uses the `IntersectionObserver` API to execute a callback when the element enters or exits the viewport.
@@ -15,7 +11,7 @@ let react = require("react");
15
11
  * @param {(entry: IntersectionObserverEntry) => void} callback - A callback function that is executed when the visibility of the element changes.
16
12
  * You can check `entry.isIntersecting` to determine if the element is in view.
17
13
  * @param {IntersectionObserverInit} options - Options for the `IntersectionObserver`.
18
- * @param {boolean} [options.root] - The element that is used as the viewport for checking visibility of the target.
14
+ * @param {Element | Document | null} [options.root] - The element that is used as the viewport for checking visibility of the target.
19
15
  * @param {string} [options.rootMargin] - Margin around the root.
20
16
  * @param {number | number[]} [options.threshold] - Either a single number or an array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed.
21
17
  *
@@ -1,10 +1,6 @@
1
1
 
2
2
  //#region src/hooks/useIntersectionObserver/useIntersectionObserver.d.ts
3
3
  /**
4
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (IntersectionObserver).
5
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
6
- * This hook will be removed in a future major version.
7
- *
8
4
  * @description
9
5
  * `useIntersectionObserver` is a React hook that detects whether a specific DOM element is visible on the screen.
10
6
  * It uses the `IntersectionObserver` API to execute a callback when the element enters or exits the viewport.
@@ -12,7 +8,7 @@
12
8
  * @param {(entry: IntersectionObserverEntry) => void} callback - A callback function that is executed when the visibility of the element changes.
13
9
  * You can check `entry.isIntersecting` to determine if the element is in view.
14
10
  * @param {IntersectionObserverInit} options - Options for the `IntersectionObserver`.
15
- * @param {boolean} [options.root] - The element that is used as the viewport for checking visibility of the target.
11
+ * @param {Element | Document | null} [options.root] - The element that is used as the viewport for checking visibility of the target.
16
12
  * @param {string} [options.rootMargin] - Margin around the root.
17
13
  * @param {number | number[]} [options.threshold] - Either a single number or an array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed.
18
14
  *
@@ -1,10 +1,6 @@
1
1
 
2
2
  //#region src/hooks/useIntersectionObserver/useIntersectionObserver.d.ts
3
3
  /**
4
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (IntersectionObserver).
5
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
6
- * This hook will be removed in a future major version.
7
- *
8
4
  * @description
9
5
  * `useIntersectionObserver` is a React hook that detects whether a specific DOM element is visible on the screen.
10
6
  * It uses the `IntersectionObserver` API to execute a callback when the element enters or exits the viewport.
@@ -12,7 +8,7 @@
12
8
  * @param {(entry: IntersectionObserverEntry) => void} callback - A callback function that is executed when the visibility of the element changes.
13
9
  * You can check `entry.isIntersecting` to determine if the element is in view.
14
10
  * @param {IntersectionObserverInit} options - Options for the `IntersectionObserver`.
15
- * @param {boolean} [options.root] - The element that is used as the viewport for checking visibility of the target.
11
+ * @param {Element | Document | null} [options.root] - The element that is used as the viewport for checking visibility of the target.
16
12
  * @param {string} [options.rootMargin] - Margin around the root.
17
13
  * @param {number | number[]} [options.threshold] - Either a single number or an array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed.
18
14
  *
@@ -4,10 +4,6 @@ import { useRefEffect } from "../useRefEffect/useRefEffect.mjs";
4
4
  import { useMemo } from "react";
5
5
  //#region src/hooks/useIntersectionObserver/useIntersectionObserver.ts
6
6
  /**
7
- * @deprecated This hook is deprecated as it depends on browser-specific APIs (IntersectionObserver).
8
- * react-simplikit is now focused on platform-independent, pure state/logic hooks.
9
- * This hook will be removed in a future major version.
10
- *
11
7
  * @description
12
8
  * `useIntersectionObserver` is a React hook that detects whether a specific DOM element is visible on the screen.
13
9
  * It uses the `IntersectionObserver` API to execute a callback when the element enters or exits the viewport.
@@ -15,7 +11,7 @@ import { useMemo } from "react";
15
11
  * @param {(entry: IntersectionObserverEntry) => void} callback - A callback function that is executed when the visibility of the element changes.
16
12
  * You can check `entry.isIntersecting` to determine if the element is in view.
17
13
  * @param {IntersectionObserverInit} options - Options for the `IntersectionObserver`.
18
- * @param {boolean} [options.root] - The element that is used as the viewport for checking visibility of the target.
14
+ * @param {Element | Document | null} [options.root] - The element that is used as the viewport for checking visibility of the target.
19
15
  * @param {string} [options.rootMargin] - Margin around the root.
20
16
  * @param {number | number[]} [options.threshold] - Either a single number or an array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed.
21
17
  *
@@ -8,15 +8,18 @@ let react = require("react");
8
8
  * A React hook that manages an array as state.
9
9
  * Provides efficient state management and stable action functions.
10
10
  *
11
- * @param {T[]} initialState - Initial array state
11
+ * @template T - The type of the values held in the list.
12
12
  *
13
- * @returns {UseListReturn<T>} A tuple containing the array state and actions to manipulate it
14
- * - `push` - Appends a value to the end of the list
15
- * - `insertAt` - Inserts a value at the specified index
16
- * - `updateAt` - Updates the value at the specified index
17
- * - `removeAt` - Removes the value at the specified index
18
- * - `setAll` - Replaces the entire list with a new array
19
- * - `reset` - Resets the list to its initial state
13
+ * @param {T[]} [initialState=[]] - Initial array state.
14
+ *
15
+ * @returns {UseListReturn<T>} A tuple containing the array state and actions to manipulate it.
16
+ * - list `ReadonlyArray<T>` - The current array state;
17
+ * - actions.push `(value: T) => void` - Appends a value to the end of the list;
18
+ * - actions.insertAt `(index: number, value: T) => void` - Inserts a value at the specified index;
19
+ * - actions.updateAt `(index: number, value: T) => void` - Updates the value at the specified index;
20
+ * - actions.removeAt `(index: number) => void` - Removes the value at the specified index;
21
+ * - actions.setAll `(values: T[]) => void` - Replaces the entire list with a new array;
22
+ * - actions.reset `() => void` - Resets the list to its initial state;
20
23
  *
21
24
  * @example
22
25
  * ```tsx
@@ -14,15 +14,18 @@ type UseListReturn<T> = [ReadonlyArray<T>, ListActions<T>];
14
14
  * A React hook that manages an array as state.
15
15
  * Provides efficient state management and stable action functions.
16
16
  *
17
- * @param {T[]} initialState - Initial array state
18
- *
19
- * @returns {UseListReturn<T>} A tuple containing the array state and actions to manipulate it
20
- * - `push` - Appends a value to the end of the list
21
- * - `insertAt` - Inserts a value at the specified index
22
- * - `updateAt` - Updates the value at the specified index
23
- * - `removeAt` - Removes the value at the specified index
24
- * - `setAll` - Replaces the entire list with a new array
25
- * - `reset` - Resets the list to its initial state
17
+ * @template T - The type of the values held in the list.
18
+ *
19
+ * @param {T[]} [initialState=[]] - Initial array state.
20
+ *
21
+ * @returns {UseListReturn<T>} A tuple containing the array state and actions to manipulate it.
22
+ * - list `ReadonlyArray<T>` - The current array state;
23
+ * - actions.push `(value: T) => void` - Appends a value to the end of the list;
24
+ * - actions.insertAt `(index: number, value: T) => void` - Inserts a value at the specified index;
25
+ * - actions.updateAt `(index: number, value: T) => void` - Updates the value at the specified index;
26
+ * - actions.removeAt `(index: number) => void` - Removes the value at the specified index;
27
+ * - actions.setAll `(values: T[]) => void` - Replaces the entire list with a new array;
28
+ * - actions.reset `() => void` - Resets the list to its initial state;
26
29
  *
27
30
  * @example
28
31
  * ```tsx