react-simplikit 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +43 -0
- package/README.md +6 -73
- package/dist/hooks/useAsyncEffect/useAsyncEffect.cjs +2 -2
- package/dist/hooks/useAsyncEffect/useAsyncEffect.d.cts +2 -2
- package/dist/hooks/useAsyncEffect/useAsyncEffect.d.mts +2 -2
- package/dist/hooks/useAsyncEffect/useAsyncEffect.mjs +2 -2
- package/dist/{mobile/hooks → hooks}/useAvoidKeyboard/useAvoidKeyboard.cjs +1 -1
- package/dist/{mobile/hooks → hooks}/useAvoidKeyboard/useAvoidKeyboard.d.cts +1 -1
- package/dist/{mobile/hooks → hooks}/useAvoidKeyboard/useAvoidKeyboard.d.mts +1 -1
- package/dist/{mobile/hooks → hooks}/useAvoidKeyboard/useAvoidKeyboard.mjs +1 -1
- package/dist/{mobile/hooks → hooks}/useBodyScrollLock/useBodyScrollLock.cjs +1 -1
- package/dist/{mobile/hooks → hooks}/useBodyScrollLock/useBodyScrollLock.d.cts +1 -1
- package/dist/{mobile/hooks → hooks}/useBodyScrollLock/useBodyScrollLock.d.mts +1 -1
- package/dist/{mobile/hooks → hooks}/useBodyScrollLock/useBodyScrollLock.mjs +1 -1
- package/dist/hooks/useBooleanState/useBooleanState.cjs +3 -3
- package/dist/hooks/useBooleanState/useBooleanState.d.cts +3 -2
- package/dist/hooks/useBooleanState/useBooleanState.d.mts +3 -2
- package/dist/hooks/useBooleanState/useBooleanState.mjs +3 -3
- package/dist/hooks/useDebounce/debounce.cjs +1 -0
- package/dist/hooks/useDebounce/debounce.mjs +1 -0
- package/dist/hooks/useDebounce/useDebounce.cjs +1 -1
- package/dist/hooks/useDebounce/useDebounce.mjs +1 -1
- package/dist/hooks/useDebouncedCallback/useDebouncedCallback.cjs +31 -36
- package/dist/hooks/useDebouncedCallback/useDebouncedCallback.d.cts +17 -7
- package/dist/hooks/useDebouncedCallback/useDebouncedCallback.d.mts +17 -7
- package/dist/hooks/useDebouncedCallback/useDebouncedCallback.mjs +32 -37
- package/dist/hooks/useDebouncedValue/useDebouncedValue.cjs +64 -0
- package/dist/hooks/useDebouncedValue/useDebouncedValue.d.cts +49 -0
- package/dist/hooks/useDebouncedValue/useDebouncedValue.d.mts +49 -0
- package/dist/hooks/useDebouncedValue/useDebouncedValue.mjs +64 -0
- package/dist/hooks/useDoubleClick/useDoubleClick.cjs +0 -4
- package/dist/hooks/useDoubleClick/useDoubleClick.d.cts +0 -4
- package/dist/hooks/useDoubleClick/useDoubleClick.d.mts +0 -4
- package/dist/hooks/useDoubleClick/useDoubleClick.mjs +0 -4
- package/dist/hooks/useGeolocation/useGeolocation.cjs +0 -4
- package/dist/hooks/useGeolocation/useGeolocation.d.cts +0 -4
- package/dist/hooks/useGeolocation/useGeolocation.d.mts +0 -4
- package/dist/hooks/useGeolocation/useGeolocation.mjs +0 -4
- package/dist/hooks/useImpressionRef/useImpressionRef.cjs +25 -7
- package/dist/hooks/useImpressionRef/useImpressionRef.d.cts +0 -4
- package/dist/hooks/useImpressionRef/useImpressionRef.d.mts +0 -4
- package/dist/hooks/useImpressionRef/useImpressionRef.mjs +26 -8
- package/dist/hooks/useInputState/useInputState.cjs +1 -1
- package/dist/hooks/useInputState/useInputState.d.cts +3 -2
- package/dist/hooks/useInputState/useInputState.d.mts +3 -2
- package/dist/hooks/useInputState/useInputState.mjs +1 -1
- package/dist/hooks/useIntersectionObserver/useIntersectionObserver.cjs +9 -8
- package/dist/hooks/useIntersectionObserver/useIntersectionObserver.d.cts +1 -5
- package/dist/hooks/useIntersectionObserver/useIntersectionObserver.d.mts +1 -5
- package/dist/hooks/useIntersectionObserver/useIntersectionObserver.mjs +9 -8
- package/dist/{mobile/hooks → hooks}/useKeyboardHeight/useKeyboardHeight.cjs +1 -1
- package/dist/{mobile/hooks → hooks}/useKeyboardHeight/useKeyboardHeight.d.cts +1 -1
- package/dist/{mobile/hooks → hooks}/useKeyboardHeight/useKeyboardHeight.d.mts +1 -1
- package/dist/{mobile/hooks → hooks}/useKeyboardHeight/useKeyboardHeight.mjs +1 -1
- package/dist/hooks/useList/useList.cjs +11 -8
- package/dist/hooks/useList/useList.d.cts +12 -9
- package/dist/hooks/useList/useList.d.mts +12 -9
- package/dist/hooks/useList/useList.mjs +11 -8
- package/dist/hooks/useLongPress/useLongPress.cjs +3 -4
- package/dist/hooks/useLongPress/useLongPress.d.cts +0 -4
- package/dist/hooks/useLongPress/useLongPress.d.mts +0 -4
- package/dist/hooks/useLongPress/useLongPress.mjs +4 -5
- package/dist/{mobile/hooks → hooks}/useNetworkStatus/useNetworkStatus.cjs +1 -1
- package/dist/{mobile/hooks → hooks}/useNetworkStatus/useNetworkStatus.d.cts +1 -1
- package/dist/{mobile/hooks → hooks}/useNetworkStatus/useNetworkStatus.d.mts +1 -1
- package/dist/{mobile/hooks → hooks}/useNetworkStatus/useNetworkStatus.mjs +1 -1
- package/dist/hooks/useOutsideClickEffect/useOutsideClickEffect.cjs +0 -4
- package/dist/hooks/useOutsideClickEffect/useOutsideClickEffect.d.cts +0 -4
- package/dist/hooks/useOutsideClickEffect/useOutsideClickEffect.d.mts +0 -4
- package/dist/hooks/useOutsideClickEffect/useOutsideClickEffect.mjs +0 -4
- package/dist/{mobile/hooks → hooks}/usePageVisibility/usePageVisibility.cjs +3 -1
- package/dist/{mobile/hooks → hooks}/usePageVisibility/usePageVisibility.d.cts +3 -1
- package/dist/{mobile/hooks → hooks}/usePageVisibility/usePageVisibility.d.mts +3 -1
- package/dist/{mobile/hooks → hooks}/usePageVisibility/usePageVisibility.mjs +3 -1
- package/dist/hooks/useRefEffect/useRefEffect.cjs +6 -4
- package/dist/hooks/useRefEffect/useRefEffect.mjs +7 -5
- package/dist/{mobile/hooks → hooks}/useSafeAreaInset/useSafeAreaInset.cjs +1 -1
- package/dist/{mobile/hooks → hooks}/useSafeAreaInset/useSafeAreaInset.d.cts +1 -1
- package/dist/{mobile/hooks → hooks}/useSafeAreaInset/useSafeAreaInset.d.mts +1 -1
- package/dist/{mobile/hooks → hooks}/useSafeAreaInset/useSafeAreaInset.mjs +1 -1
- package/dist/{mobile/hooks → hooks}/useScrollDirection/useScrollDirection.cjs +1 -1
- package/dist/{mobile/hooks → hooks}/useScrollDirection/useScrollDirection.d.cts +1 -1
- package/dist/{mobile/hooks → hooks}/useScrollDirection/useScrollDirection.d.mts +1 -1
- package/dist/{mobile/hooks → hooks}/useScrollDirection/useScrollDirection.mjs +1 -1
- package/dist/hooks/useSet/useSet.cjs +11 -2
- package/dist/hooks/useSet/useSet.d.cts +11 -2
- package/dist/hooks/useSet/useSet.d.mts +11 -2
- package/dist/hooks/useSet/useSet.mjs +11 -2
- package/dist/hooks/useStorageState/useStorageState.cjs +1 -1
- package/dist/hooks/useStorageState/useStorageState.d.cts +0 -4
- package/dist/hooks/useStorageState/useStorageState.d.mts +0 -4
- package/dist/hooks/useStorageState/useStorageState.mjs +1 -1
- package/dist/hooks/useThrottle/throttle.cjs +22 -5
- package/dist/hooks/useThrottle/throttle.mjs +22 -5
- package/dist/hooks/useThrottledCallback/useThrottledCallback.cjs +22 -37
- package/dist/hooks/useThrottledCallback/useThrottledCallback.d.cts +18 -11
- package/dist/hooks/useThrottledCallback/useThrottledCallback.d.mts +18 -11
- package/dist/hooks/useThrottledCallback/useThrottledCallback.mjs +23 -38
- package/dist/hooks/useThrottledValue/useThrottledValue.cjs +66 -0
- package/dist/hooks/useThrottledValue/useThrottledValue.d.cts +48 -0
- package/dist/hooks/useThrottledValue/useThrottledValue.d.mts +48 -0
- package/dist/hooks/useThrottledValue/useThrottledValue.mjs +66 -0
- package/dist/hooks/useVisibilityEvent/useVisibilityEvent.cjs +2 -4
- package/dist/hooks/useVisibilityEvent/useVisibilityEvent.d.cts +2 -4
- package/dist/hooks/useVisibilityEvent/useVisibilityEvent.d.mts +2 -4
- package/dist/hooks/useVisibilityEvent/useVisibilityEvent.mjs +2 -4
- package/dist/{mobile/hooks → hooks}/useVisualViewport/useVisualViewport.cjs +1 -1
- package/dist/{mobile/hooks → hooks}/useVisualViewport/useVisualViewport.d.cts +1 -1
- package/dist/{mobile/hooks → hooks}/useVisualViewport/useVisualViewport.d.mts +1 -1
- package/dist/{mobile/hooks → hooks}/useVisualViewport/useVisualViewport.mjs +1 -1
- package/dist/index.cjs +23 -19
- package/dist/index.d.cts +21 -19
- package/dist/index.d.mts +21 -19
- package/dist/index.mjs +22 -20
- package/dist/{mobile/utils → utils}/disableBodyScrollLock/disableBodyScrollLock.cjs +1 -1
- package/dist/{mobile/utils → utils}/disableBodyScrollLock/disableBodyScrollLock.d.cts +1 -1
- package/dist/{mobile/utils → utils}/disableBodyScrollLock/disableBodyScrollLock.d.mts +1 -1
- package/dist/{mobile/utils → utils}/disableBodyScrollLock/disableBodyScrollLock.mjs +1 -1
- package/dist/{mobile/utils → utils}/enableBodyScrollLock/enableBodyScrollLock.cjs +1 -1
- package/dist/{mobile/utils → utils}/enableBodyScrollLock/enableBodyScrollLock.d.cts +1 -1
- package/dist/{mobile/utils → utils}/enableBodyScrollLock/enableBodyScrollLock.d.mts +1 -1
- package/dist/{mobile/utils → utils}/enableBodyScrollLock/enableBodyScrollLock.mjs +1 -1
- package/dist/{mobile/utils → utils}/getKeyboardHeight/getKeyboardHeight.cjs +1 -1
- package/dist/{mobile/utils → utils}/getKeyboardHeight/getKeyboardHeight.d.cts +1 -1
- package/dist/{mobile/utils → utils}/getKeyboardHeight/getKeyboardHeight.d.mts +1 -1
- package/dist/{mobile/utils → utils}/getKeyboardHeight/getKeyboardHeight.mjs +1 -1
- package/dist/{mobile/utils → utils}/getSafeAreaInset/getSafeAreaInset.cjs +1 -1
- package/dist/{mobile/utils → utils}/getSafeAreaInset/getSafeAreaInset.d.cts +1 -1
- package/dist/{mobile/utils → utils}/getSafeAreaInset/getSafeAreaInset.d.mts +1 -1
- package/dist/{mobile/utils → utils}/getSafeAreaInset/getSafeAreaInset.mjs +1 -1
- package/dist/{mobile/utils → utils}/isAndroid/isAndroid.cjs +1 -1
- package/dist/{mobile/utils → utils}/isAndroid/isAndroid.d.cts +1 -1
- package/dist/{mobile/utils → utils}/isAndroid/isAndroid.d.mts +1 -1
- package/dist/{mobile/utils → utils}/isAndroid/isAndroid.mjs +1 -1
- package/dist/{mobile/utils → utils}/isIOS/isIOS.cjs +1 -1
- package/dist/{mobile/utils → utils}/isIOS/isIOS.d.cts +1 -1
- package/dist/{mobile/utils → utils}/isIOS/isIOS.d.mts +1 -1
- package/dist/{mobile/utils → utils}/isIOS/isIOS.mjs +1 -1
- package/dist/{mobile/utils → utils}/isKeyboardVisible/isKeyboardVisible.cjs +1 -1
- package/dist/{mobile/utils → utils}/isKeyboardVisible/isKeyboardVisible.d.cts +1 -1
- package/dist/{mobile/utils → utils}/isKeyboardVisible/isKeyboardVisible.d.mts +1 -1
- package/dist/{mobile/utils → utils}/isKeyboardVisible/isKeyboardVisible.mjs +1 -1
- package/dist/{mobile/utils → utils}/isServer/isServer.cjs +1 -1
- package/dist/{mobile/utils → utils}/isServer/isServer.d.cts +1 -1
- package/dist/{mobile/utils → utils}/isServer/isServer.d.mts +1 -1
- package/dist/{mobile/utils → utils}/isServer/isServer.mjs +1 -1
- package/dist/utils/mergeProps/mergeProps.cjs +1 -1
- package/dist/utils/mergeProps/mergeProps.d.cts +1 -1
- package/dist/utils/mergeProps/mergeProps.d.mts +1 -1
- package/dist/utils/mergeProps/mergeProps.mjs +1 -1
- package/dist/utils/mergeRefs/mergeRefs.cjs +1 -1
- package/dist/utils/mergeRefs/mergeRefs.d.cts +1 -1
- package/dist/utils/mergeRefs/mergeRefs.d.mts +1 -1
- package/dist/utils/mergeRefs/mergeRefs.mjs +1 -1
- package/dist/{mobile/utils → utils}/subscribeKeyboardHeight/subscribeKeyboardHeight.cjs +1 -1
- package/dist/{mobile/utils → utils}/subscribeKeyboardHeight/subscribeKeyboardHeight.d.cts +1 -1
- package/dist/{mobile/utils → utils}/subscribeKeyboardHeight/subscribeKeyboardHeight.d.mts +1 -1
- package/dist/{mobile/utils → utils}/subscribeKeyboardHeight/subscribeKeyboardHeight.mjs +1 -1
- package/package.json +2 -4
- /package/dist/{mobile/hooks → hooks}/useAvoidKeyboard/index.d.cts +0 -0
- /package/dist/{mobile/hooks → hooks}/useAvoidKeyboard/index.d.mts +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# react-simplikit
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#471](https://github.com/toss/react-simplikit/pull/471) [`edddd4b`](https://github.com/toss/react-simplikit/commit/edddd4bdc2b4e86158e1d59fdcd71f9d4f084ec3) Thanks [@hyesungoh](https://github.com/hyesungoh)! - Add `useDebouncedValue` and `useThrottledValue`. Both take a value the caller owns and return a delayed copy of it: `useDebouncedValue(value, wait, { leading?, trailing? })` follows the value `wait` milliseconds after the last change, and `useThrottledValue(value, wait, { leading?, trailing? })` follows it at most once per `wait` milliseconds. They pair with the existing `useDebouncedCallback` and `useThrottledCallback`, which wrap a setter instead of a value.
|
|
8
|
+
|
|
9
|
+
- [#479](https://github.com/toss/react-simplikit/pull/479) [`72ed16e`](https://github.com/toss/react-simplikit/commit/72ed16e9bccabaa5b06ca408885b4440461574ad) Thanks [@Antoliny0919](https://github.com/Antoliny0919)! - Add lazy initializer support to useBooleanState.
|
|
10
|
+
|
|
11
|
+
- [#469](https://github.com/toss/react-simplikit/pull/469) [`cc8b69e`](https://github.com/toss/react-simplikit/commit/cc8b69e466b1ad11089bc5aca32c898c5c7204ea) Thanks [@DongEun02](https://github.com/DongEun02)! - Add lazy initializer support to useInputState.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#483](https://github.com/toss/react-simplikit/pull/483) [`6605918`](https://github.com/toss/react-simplikit/commit/66059185a194537b1b73224254683302324b9271) Thanks [@chungyo](https://github.com/chungyo)! - Use the updated callback when useRefEffect dependencies change during DOM ref attachment.
|
|
16
|
+
|
|
17
|
+
- [#482](https://github.com/toss/react-simplikit/pull/482) [`163ac5c`](https://github.com/toss/react-simplikit/commit/163ac5cc8418458d3c4c53624332ce6cb2d11109) Thanks [@chungyo](https://github.com/chungyo)! - Fix `useStorageState` retaining stale state when another tab clears localStorage.
|
|
18
|
+
|
|
19
|
+
- [#470](https://github.com/toss/react-simplikit/pull/470) [`52ed163`](https://github.com/toss/react-simplikit/commit/52ed163a7273faad99d1cf5fa7877b2a8a1c2e5f) Thanks [@hyesungoh](https://github.com/hyesungoh)! - `useThrottle` with `edges: ['trailing']` now invokes once per `wait` while calls keep coming in, instead of waiting for the calls to stop. `useThrottledCallback` and `useDebouncedCallback` now keep a single throttle or debounce across calls: `useThrottledCallback` forwards a stream of distinct values at most once per `timeThreshold` instead of every time, and `useDebouncedCallback` with `leading: true` forwards the first value of a burst once instead of every value immediately. Sharing one instance has two further consequences. A call carrying the same value as the last forwarded one is still skipped, but it now occupies a window, so a different value arriving inside that window waits for the window to close. And changing `timeThreshold`, `edges`, `leading` or `trailing` while a value is pending discards that pending value instead of forwarding it. `useImpressionRef` and `ImpressionArea` inherit the `useDebouncedCallback` change: an impression that ends within `timeThreshold` of its start now reports `onImpressionEnd` on the trailing edge rather than immediately, and an end still pending when the element unmounts is emitted during cleanup instead of being dropped.
|
|
20
|
+
|
|
21
|
+
- [#467](https://github.com/toss/react-simplikit/pull/467) [`92cbb34`](https://github.com/toss/react-simplikit/commit/92cbb349454a1b54f60db3edd1037240677984e4) Thanks [@constantly-dev](https://github.com/constantly-dev)! - `useIntersectionObserver` no longer recreates the underlying `IntersectionObserver` on every render when an inline `options` object is passed. It now recreates it only when `root`, `rootMargin`, or `threshold` actually change.
|
|
22
|
+
|
|
23
|
+
- [#473](https://github.com/toss/react-simplikit/pull/473) [`6f6361c`](https://github.com/toss/react-simplikit/commit/6f6361c38a5a951a813df8d033d60f6e7754a6d5) Thanks [@JetProc](https://github.com/JetProc)! - Cancel pending useLongPress timers when the component unmounts, preventing
|
|
24
|
+
onLongPress from firing after unmount.
|
|
25
|
+
|
|
26
|
+
## 0.2.0
|
|
27
|
+
|
|
28
|
+
### Minor Changes
|
|
29
|
+
|
|
30
|
+
- [#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.
|
|
31
|
+
|
|
32
|
+
`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.
|
|
33
|
+
|
|
34
|
+
`useImpressionRef` no longer emits `onImpressionEnd` for an element that was never impressed.
|
|
35
|
+
|
|
36
|
+
### Patch Changes
|
|
37
|
+
|
|
38
|
+
- [#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.
|
|
39
|
+
|
|
40
|
+
- [#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.
|
|
41
|
+
|
|
42
|
+
- [#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.
|
|
43
|
+
|
|
44
|
+
- [#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.
|
|
45
|
+
|
|
3
46
|
## 0.1.0
|
|
4
47
|
|
|
5
48
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://github.com/toss/react-simplikit/blob/main/LICENSE)
|
|
5
5
|
[](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
|
|
@@ -97,46 +57,19 @@ The debounced function exposes `.cancel()`, and pending calls are cancelled auto
|
|
|
97
57
|
|
|
98
58
|
## What's Included
|
|
99
59
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
| ------------------------- | ----------------------------------------------------- |
|
|
104
|
-
| `useBooleanState` | Manage boolean state with handlers |
|
|
105
|
-
| `useDebounce` | Debounce a callback function |
|
|
106
|
-
| `useDebouncedCallback` | Debounce an `onChange` callback via an options object |
|
|
107
|
-
| `useInterval` | Set up intervals declaratively |
|
|
108
|
-
| `useIntersectionObserver` | Observe element visibility |
|
|
109
|
-
| `usePreservedCallback` | Stable callback reference |
|
|
110
|
-
| `usePreservedReference` | Stable object reference |
|
|
111
|
-
| ... | [See all hooks](https://react-simplikit.slash.page) |
|
|
112
|
-
|
|
113
|
-
### Components
|
|
60
|
+
- **Hooks** — state and logic (`useToggle`, `useDebounce`, `useList`, …), browser events (`useIntersectionObserver`, `useOutsideClickEffect`, …) and mobile web (`useAvoidKeyboard`, `useSafeAreaInset`, `useVisualViewport`, …)
|
|
61
|
+
- **Components** — `SwitchCase`, `Separated`, `ImpressionArea`
|
|
62
|
+
- **Utils** — `buildContext`, `mergeProps`, `mergeRefs`, and mobile web helpers such as `isIOS` and `getKeyboardHeight`
|
|
114
63
|
|
|
115
|
-
|
|
116
|
-
| ---------------- | --------------------------------- |
|
|
117
|
-
| `SwitchCase` | Declarative switch-case rendering |
|
|
118
|
-
| `Separated` | Render items with separators |
|
|
119
|
-
| `ImpressionArea` | Track element impressions |
|
|
120
|
-
|
|
121
|
-
### Utilities
|
|
122
|
-
|
|
123
|
-
| Utility | Description |
|
|
124
|
-
| -------------- | --------------------------------------------------- |
|
|
125
|
-
| `buildContext` | Define React Context with less boilerplate |
|
|
126
|
-
| `mergeProps` | Merge props, composing `className`, `style`, events |
|
|
127
|
-
| `mergeRefs` | Combine multiple refs into a single ref |
|
|
64
|
+
The full list with a one-line description each is on the [reference page](https://react-simplikit.slash.page/reference.html).
|
|
128
65
|
|
|
129
66
|
## Documentation
|
|
130
67
|
|
|
131
68
|
Visit [react-simplikit.slash.page](https://react-simplikit.slash.page) for full documentation.
|
|
132
69
|
|
|
133
|
-
## Related Packages
|
|
134
|
-
|
|
135
|
-
- [Mobile web utilities](https://react-simplikit.slash.page/mobile/intro.html) - included in `react-simplikit`
|
|
136
|
-
|
|
137
70
|
## Contributing
|
|
138
71
|
|
|
139
|
-
We welcome contributions! Please see our [Contributing Guide](https://github.com/toss/react-simplikit/blob/main/CONTRIBUTING.md).
|
|
72
|
+
We welcome contributions! Please see our [Contributing Guide](https://github.com/toss/react-simplikit/blob/main/.github/CONTRIBUTING.md).
|
|
140
73
|
|
|
141
74
|
## License
|
|
142
75
|
|
|
@@ -6,10 +6,10 @@ let react = require("react");
|
|
|
6
6
|
* `useAsyncEffect` is a React hook for handling asynchronous side effects in React components.
|
|
7
7
|
* It follows the same cleanup pattern as `useEffect` while ensuring async operations are handled safely.
|
|
8
8
|
*
|
|
9
|
-
* @param {() => Promise<void | (() => void)>}
|
|
9
|
+
* @param {() => Promise<void | (() => void)>} effect - An asynchronous function executed in the `useEffect` pattern.
|
|
10
10
|
* This function can optionally return a cleanup function.
|
|
11
11
|
* @param {DependencyList} [deps] - A dependency array.
|
|
12
|
-
* The effect will re-run whenever any value in this array changes. If omitted, it runs
|
|
12
|
+
* The effect will re-run whenever any value in this array changes. If omitted, it runs after every render of the component.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* useAsyncEffect(async () => {
|
|
@@ -6,10 +6,10 @@ import { DependencyList } from "react";
|
|
|
6
6
|
* `useAsyncEffect` is a React hook for handling asynchronous side effects in React components.
|
|
7
7
|
* It follows the same cleanup pattern as `useEffect` while ensuring async operations are handled safely.
|
|
8
8
|
*
|
|
9
|
-
* @param {() => Promise<void | (() => void)>}
|
|
9
|
+
* @param {() => Promise<void | (() => void)>} effect - An asynchronous function executed in the `useEffect` pattern.
|
|
10
10
|
* This function can optionally return a cleanup function.
|
|
11
11
|
* @param {DependencyList} [deps] - A dependency array.
|
|
12
|
-
* The effect will re-run whenever any value in this array changes. If omitted, it runs
|
|
12
|
+
* The effect will re-run whenever any value in this array changes. If omitted, it runs after every render of the component.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* useAsyncEffect(async () => {
|
|
@@ -6,10 +6,10 @@ import { DependencyList } from "react";
|
|
|
6
6
|
* `useAsyncEffect` is a React hook for handling asynchronous side effects in React components.
|
|
7
7
|
* It follows the same cleanup pattern as `useEffect` while ensuring async operations are handled safely.
|
|
8
8
|
*
|
|
9
|
-
* @param {() => Promise<void | (() => void)>}
|
|
9
|
+
* @param {() => Promise<void | (() => void)>} effect - An asynchronous function executed in the `useEffect` pattern.
|
|
10
10
|
* This function can optionally return a cleanup function.
|
|
11
11
|
* @param {DependencyList} [deps] - A dependency array.
|
|
12
|
-
* The effect will re-run whenever any value in this array changes. If omitted, it runs
|
|
12
|
+
* The effect will re-run whenever any value in this array changes. If omitted, it runs after every render of the component.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* useAsyncEffect(async () => {
|
|
@@ -6,10 +6,10 @@ import { useEffect } from "react";
|
|
|
6
6
|
* `useAsyncEffect` is a React hook for handling asynchronous side effects in React components.
|
|
7
7
|
* It follows the same cleanup pattern as `useEffect` while ensuring async operations are handled safely.
|
|
8
8
|
*
|
|
9
|
-
* @param {() => Promise<void | (() => void)>}
|
|
9
|
+
* @param {() => Promise<void | (() => void)>} effect - An asynchronous function executed in the `useEffect` pattern.
|
|
10
10
|
* This function can optionally return a cleanup function.
|
|
11
11
|
* @param {DependencyList} [deps] - A dependency array.
|
|
12
|
-
* The effect will re-run whenever any value in this array changes. If omitted, it runs
|
|
12
|
+
* The effect will re-run whenever any value in this array changes. If omitted, it runs after every render of the component.
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
* useAsyncEffect(async () => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
const require_useKeyboardHeight = require("../useKeyboardHeight/useKeyboardHeight.cjs");
|
|
3
3
|
let react = require("react");
|
|
4
|
-
//#region src/
|
|
4
|
+
//#region src/hooks/useAvoidKeyboard/useAvoidKeyboard.ts
|
|
5
5
|
/**
|
|
6
6
|
* @description
|
|
7
7
|
* `useAvoidKeyboard` is a React hook that helps fixed-bottom elements avoid the on-screen keyboard.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { CSSProperties } from "react";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/hooks/useAvoidKeyboard/useAvoidKeyboard.d.ts
|
|
4
4
|
type UseAvoidKeyboardOptions = {
|
|
5
5
|
/**
|
|
6
6
|
* Base bottom offset in pixels when keyboard is hidden.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { CSSProperties } from "react";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/hooks/useAvoidKeyboard/useAvoidKeyboard.d.ts
|
|
4
4
|
type UseAvoidKeyboardOptions = {
|
|
5
5
|
/**
|
|
6
6
|
* Base bottom offset in pixels when keyboard is hidden.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { useKeyboardHeight } from "../useKeyboardHeight/useKeyboardHeight.mjs";
|
|
3
3
|
import { useMemo } from "react";
|
|
4
|
-
//#region src/
|
|
4
|
+
//#region src/hooks/useAvoidKeyboard/useAvoidKeyboard.ts
|
|
5
5
|
/**
|
|
6
6
|
* @description
|
|
7
7
|
* `useAvoidKeyboard` is a React hook that helps fixed-bottom elements avoid the on-screen keyboard.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
const require_disableBodyScrollLock = require("../../utils/disableBodyScrollLock/disableBodyScrollLock.cjs");
|
|
3
3
|
const require_enableBodyScrollLock = require("../../utils/enableBodyScrollLock/enableBodyScrollLock.cjs");
|
|
4
4
|
let react = require("react");
|
|
5
|
-
//#region src/
|
|
5
|
+
//#region src/hooks/useBodyScrollLock/useBodyScrollLock.ts
|
|
6
6
|
/**
|
|
7
7
|
* @description
|
|
8
8
|
* `useBodyScrollLock` is a React hook that locks body scroll while the component is mounted.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { disableBodyScrollLock } from "../../utils/disableBodyScrollLock/disableBodyScrollLock.mjs";
|
|
3
3
|
import { enableBodyScrollLock } from "../../utils/enableBodyScrollLock/enableBodyScrollLock.mjs";
|
|
4
4
|
import { useEffect } from "react";
|
|
5
|
-
//#region src/
|
|
5
|
+
//#region src/hooks/useBodyScrollLock/useBodyScrollLock.ts
|
|
6
6
|
/**
|
|
7
7
|
* @description
|
|
8
8
|
* `useBodyScrollLock` is a React hook that locks body scroll while the component is mounted.
|
|
@@ -6,7 +6,7 @@ let react = require("react");
|
|
|
6
6
|
* `useBooleanState` is a React hook that simplifies managing a boolean state.
|
|
7
7
|
* It provides functions to set the state to `true`, set it to `false`, and toggle its value.
|
|
8
8
|
*
|
|
9
|
-
* @param {boolean} [
|
|
9
|
+
* @param {boolean | (() => boolean)} [initialValue=false] - The initial value of the state. Defaults to `false`.
|
|
10
10
|
*
|
|
11
11
|
* @returns {readonly [state: boolean, setTrue: () => void, setFalse: () => void, toggle: () => void]} A tuple containing:
|
|
12
12
|
* - state `boolean` - The current state value;
|
|
@@ -17,8 +17,8 @@ let react = require("react");
|
|
|
17
17
|
* @example
|
|
18
18
|
* const [open, openBottomSheet, closeBottomSheet, toggleBottomSheet] = useBooleanState(false);
|
|
19
19
|
*/
|
|
20
|
-
function useBooleanState(
|
|
21
|
-
const [bool, setBool] = (0, react.useState)(
|
|
20
|
+
function useBooleanState(initialValue = false) {
|
|
21
|
+
const [bool, setBool] = (0, react.useState)(initialValue);
|
|
22
22
|
return [
|
|
23
23
|
bool,
|
|
24
24
|
(0, react.useCallback)(() => {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
//#region src/hooks/useBooleanState/useBooleanState.d.ts
|
|
3
|
+
type InitialValue = boolean | (() => boolean);
|
|
3
4
|
/**
|
|
4
5
|
* @description
|
|
5
6
|
* `useBooleanState` is a React hook that simplifies managing a boolean state.
|
|
6
7
|
* It provides functions to set the state to `true`, set it to `false`, and toggle its value.
|
|
7
8
|
*
|
|
8
|
-
* @param {boolean} [
|
|
9
|
+
* @param {boolean | (() => boolean)} [initialValue=false] - The initial value of the state. Defaults to `false`.
|
|
9
10
|
*
|
|
10
11
|
* @returns {readonly [state: boolean, setTrue: () => void, setFalse: () => void, toggle: () => void]} A tuple containing:
|
|
11
12
|
* - state `boolean` - The current state value;
|
|
@@ -16,6 +17,6 @@
|
|
|
16
17
|
* @example
|
|
17
18
|
* const [open, openBottomSheet, closeBottomSheet, toggleBottomSheet] = useBooleanState(false);
|
|
18
19
|
*/
|
|
19
|
-
declare function useBooleanState(
|
|
20
|
+
declare function useBooleanState(initialValue?: InitialValue): readonly [boolean, () => void, () => void, () => void];
|
|
20
21
|
//#endregion
|
|
21
22
|
export { useBooleanState };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
|
|
2
2
|
//#region src/hooks/useBooleanState/useBooleanState.d.ts
|
|
3
|
+
type InitialValue = boolean | (() => boolean);
|
|
3
4
|
/**
|
|
4
5
|
* @description
|
|
5
6
|
* `useBooleanState` is a React hook that simplifies managing a boolean state.
|
|
6
7
|
* It provides functions to set the state to `true`, set it to `false`, and toggle its value.
|
|
7
8
|
*
|
|
8
|
-
* @param {boolean} [
|
|
9
|
+
* @param {boolean | (() => boolean)} [initialValue=false] - The initial value of the state. Defaults to `false`.
|
|
9
10
|
*
|
|
10
11
|
* @returns {readonly [state: boolean, setTrue: () => void, setFalse: () => void, toggle: () => void]} A tuple containing:
|
|
11
12
|
* - state `boolean` - The current state value;
|
|
@@ -16,6 +17,6 @@
|
|
|
16
17
|
* @example
|
|
17
18
|
* const [open, openBottomSheet, closeBottomSheet, toggleBottomSheet] = useBooleanState(false);
|
|
18
19
|
*/
|
|
19
|
-
declare function useBooleanState(
|
|
20
|
+
declare function useBooleanState(initialValue?: InitialValue): readonly [boolean, () => void, () => void, () => void];
|
|
20
21
|
//#endregion
|
|
21
22
|
export { useBooleanState };
|
|
@@ -6,7 +6,7 @@ import { useCallback, useState } from "react";
|
|
|
6
6
|
* `useBooleanState` is a React hook that simplifies managing a boolean state.
|
|
7
7
|
* It provides functions to set the state to `true`, set it to `false`, and toggle its value.
|
|
8
8
|
*
|
|
9
|
-
* @param {boolean} [
|
|
9
|
+
* @param {boolean | (() => boolean)} [initialValue=false] - The initial value of the state. Defaults to `false`.
|
|
10
10
|
*
|
|
11
11
|
* @returns {readonly [state: boolean, setTrue: () => void, setFalse: () => void, toggle: () => void]} A tuple containing:
|
|
12
12
|
* - state `boolean` - The current state value;
|
|
@@ -17,8 +17,8 @@ import { useCallback, useState } from "react";
|
|
|
17
17
|
* @example
|
|
18
18
|
* const [open, openBottomSheet, closeBottomSheet, toggleBottomSheet] = useBooleanState(false);
|
|
19
19
|
*/
|
|
20
|
-
function useBooleanState(
|
|
21
|
-
const [bool, setBool] = useState(
|
|
20
|
+
function useBooleanState(initialValue = false) {
|
|
21
|
+
const [bool, setBool] = useState(initialValue);
|
|
22
22
|
return [
|
|
23
23
|
bool,
|
|
24
24
|
useCallback(() => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
const require_debounce = require("./debounce.cjs");
|
|
3
2
|
const require_usePreservedCallback = require("../usePreservedCallback/usePreservedCallback.cjs");
|
|
3
|
+
const require_debounce = require("./debounce.cjs");
|
|
4
4
|
let react = require("react");
|
|
5
5
|
//#region src/hooks/useDebounce/useDebounce.ts
|
|
6
6
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { debounce } from "./debounce.mjs";
|
|
3
2
|
import { usePreservedCallback } from "../usePreservedCallback/usePreservedCallback.mjs";
|
|
3
|
+
import { debounce } from "./debounce.mjs";
|
|
4
4
|
import { useEffect, useMemo } from "react";
|
|
5
5
|
//#region src/hooks/useDebounce/useDebounce.ts
|
|
6
6
|
/**
|
|
@@ -1,62 +1,57 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
const
|
|
3
|
-
const require_usePreservedCallback = require("../usePreservedCallback/usePreservedCallback.cjs");
|
|
2
|
+
const require_useDebounce = require("../useDebounce/useDebounce.cjs");
|
|
4
3
|
let react = require("react");
|
|
5
4
|
//#region src/hooks/useDebouncedCallback/useDebouncedCallback.ts
|
|
6
5
|
/**
|
|
6
|
+
* Marks that no value has been forwarded to `onChange` yet.
|
|
7
|
+
*
|
|
8
|
+
* The hook skips redundant invocations by comparing against the last forwarded value, but it
|
|
9
|
+
* receives no initial value from the caller. Seeding that comparison with a real value would treat
|
|
10
|
+
* the first call of that value as redundant and swallow it, so an unreachable sentinel is used instead.
|
|
11
|
+
*/
|
|
12
|
+
const NOT_INVOKED = Symbol("NOT_INVOKED");
|
|
13
|
+
/**
|
|
7
14
|
* @description
|
|
8
15
|
* `useDebouncedCallback` is a React hook that returns a debounced version of the provided callback function.
|
|
9
16
|
* It helps optimize event handling by delaying function execution and grouping multiple calls into one.
|
|
10
17
|
*
|
|
11
18
|
* 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
19
|
*
|
|
20
|
+
* @template T - The type of the value passed to `onChange`.
|
|
13
21
|
* @param {Object} options - The options object.
|
|
14
|
-
* @param {
|
|
22
|
+
* @param {(newValue: T) => void} options.onChange - The callback to debounce. A call with the same value as the last forwarded one is skipped.
|
|
15
23
|
* @param {number} options.timeThreshold - The number of milliseconds to delay the function execution.
|
|
16
24
|
* @param {boolean} [options.leading=false] - If `true`, the function is called at the start of the sequence.
|
|
17
25
|
* @param {boolean} [options.trailing=true] - If `true`, the function is called at the end of the sequence.
|
|
18
26
|
*
|
|
19
|
-
* @returns {
|
|
27
|
+
* @returns {(nextValue: T) => void} A debounced function that forwards the value to `onChange`.
|
|
20
28
|
*
|
|
21
29
|
* @example
|
|
30
|
+
* import { useDebouncedCallback } from 'react-simplikit';
|
|
31
|
+
* import { useState } from 'react';
|
|
32
|
+
*
|
|
22
33
|
* function SearchInput() {
|
|
23
34
|
* const [query, setQuery] = useState('');
|
|
24
|
-
* const
|
|
25
|
-
*
|
|
35
|
+
* const setQueryDebounced = useDebouncedCallback({ onChange: setQuery, timeThreshold: 300 });
|
|
36
|
+
*
|
|
37
|
+
* return (
|
|
38
|
+
* <>
|
|
39
|
+
* <input onChange={e => setQueryDebounced(e.target.value)} />
|
|
40
|
+
* <p>Searching for: {query}</p>
|
|
41
|
+
* </>
|
|
42
|
+
* );
|
|
26
43
|
* }
|
|
27
44
|
*/
|
|
28
45
|
function useDebouncedCallback({ onChange, timeThreshold, leading = false, trailing = true }) {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
46
|
+
const lastForwardedRef = (0, react.useRef)(NOT_INVOKED);
|
|
47
|
+
return require_useDebounce.useDebounce((nextValue) => {
|
|
48
|
+
if (nextValue === lastForwardedRef.current) return;
|
|
49
|
+
onChange(nextValue);
|
|
50
|
+
lastForwardedRef.current = nextValue;
|
|
51
|
+
}, timeThreshold, {
|
|
52
|
+
leading,
|
|
53
|
+
trailing
|
|
33
54
|
});
|
|
34
|
-
(0, react.useEffect)(function clearDebouncedOnUnmount() {
|
|
35
|
-
const current = ref.current;
|
|
36
|
-
return () => {
|
|
37
|
-
current.clearPreviousDebounce();
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
|
-
const edges = (0, react.useMemo)(() => {
|
|
41
|
-
const _edges = [];
|
|
42
|
-
if (leading) _edges.push("leading");
|
|
43
|
-
if (trailing) _edges.push("trailing");
|
|
44
|
-
return _edges;
|
|
45
|
-
}, [leading, trailing]);
|
|
46
|
-
return (0, react.useCallback)((nextValue) => {
|
|
47
|
-
if (nextValue === ref.current.value) return;
|
|
48
|
-
const debounced = require_debounce.debounce(() => {
|
|
49
|
-
handleChange(nextValue);
|
|
50
|
-
ref.current.value = nextValue;
|
|
51
|
-
}, timeThreshold, { edges });
|
|
52
|
-
ref.current.clearPreviousDebounce();
|
|
53
|
-
debounced();
|
|
54
|
-
ref.current.clearPreviousDebounce = debounced.cancel;
|
|
55
|
-
}, [
|
|
56
|
-
handleChange,
|
|
57
|
-
timeThreshold,
|
|
58
|
-
edges
|
|
59
|
-
]);
|
|
60
55
|
}
|
|
61
56
|
//#endregion
|
|
62
57
|
exports.useDebouncedCallback = 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 {
|
|
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 {
|
|
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
|
|
26
|
-
*
|
|
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:
|
|
39
|
+
declare function useDebouncedCallback<T>({ onChange, timeThreshold, leading, trailing }: DebounceOptions & {
|
|
40
|
+
onChange: (newValue: T) => void;
|
|
31
41
|
timeThreshold: number;
|
|
32
|
-
}): (nextValue:
|
|
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 {
|
|
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 {
|
|
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
|
|
26
|
-
*
|
|
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:
|
|
39
|
+
declare function useDebouncedCallback<T>({ onChange, timeThreshold, leading, trailing }: DebounceOptions & {
|
|
40
|
+
onChange: (newValue: T) => void;
|
|
31
41
|
timeThreshold: number;
|
|
32
|
-
}): (nextValue:
|
|
42
|
+
}): (nextValue: T) => void;
|
|
33
43
|
//#endregion
|
|
34
44
|
export { useDebouncedCallback };
|