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
|
@@ -1,62 +1,57 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { useCallback, useEffect, useMemo, useRef } from "react";
|
|
2
|
+
import { useDebounce } from "../useDebounce/useDebounce.mjs";
|
|
3
|
+
import { useRef } from "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 = useRef(NOT_INVOKED);
|
|
47
|
+
return useDebounce((nextValue) => {
|
|
48
|
+
if (nextValue === lastForwardedRef.current) return;
|
|
49
|
+
onChange(nextValue);
|
|
50
|
+
lastForwardedRef.current = nextValue;
|
|
51
|
+
}, timeThreshold, {
|
|
52
|
+
leading,
|
|
53
|
+
trailing
|
|
33
54
|
});
|
|
34
|
-
useEffect(function clearDebouncedOnUnmount() {
|
|
35
|
-
const current = ref.current;
|
|
36
|
-
return () => {
|
|
37
|
-
current.clearPreviousDebounce();
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
|
-
const edges = useMemo(() => {
|
|
41
|
-
const _edges = [];
|
|
42
|
-
if (leading) _edges.push("leading");
|
|
43
|
-
if (trailing) _edges.push("trailing");
|
|
44
|
-
return _edges;
|
|
45
|
-
}, [leading, trailing]);
|
|
46
|
-
return useCallback((nextValue) => {
|
|
47
|
-
if (nextValue === ref.current.value) return;
|
|
48
|
-
const debounced = 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
|
export { useDebouncedCallback };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const require_useDebounce = require("../useDebounce/useDebounce.cjs");
|
|
3
|
+
let react = require("react");
|
|
4
|
+
//#region src/hooks/useDebouncedValue/useDebouncedValue.ts
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `useDebouncedValue` is a React hook that returns a debounced copy of the given value.
|
|
8
|
+
* The caller keeps owning the state; the hook only delays how quickly the returned value follows it.
|
|
9
|
+
* The returned value updates `wait` milliseconds after the last change, which is useful for
|
|
10
|
+
* deriving a search query or a validation input from fast-changing state.
|
|
11
|
+
*
|
|
12
|
+
* On the first render and on the server the value is returned as is. A change is never scheduled
|
|
13
|
+
* on mount, so with `leading: true` the first change after mount is applied immediately.
|
|
14
|
+
* If both `leading` and `trailing` are `false`, the returned value never updates.
|
|
15
|
+
*
|
|
16
|
+
* The value is compared by reference. Passing a new object or array on every render keeps
|
|
17
|
+
* the returned value updating every `wait` milliseconds; stabilize the reference first, for
|
|
18
|
+
* example with `usePreservedReference`.
|
|
19
|
+
*
|
|
20
|
+
* @template T - The type of the value.
|
|
21
|
+
* @param {T} value - The value to debounce.
|
|
22
|
+
* @param {number} wait - The number of milliseconds to wait after the last change before updating.
|
|
23
|
+
* @param {DebounceOptions} [options] - Configuration options for debounce behavior.
|
|
24
|
+
* @param {boolean} [options.leading=false] - If `true`, the first change after an idle period is applied immediately.
|
|
25
|
+
* @param {boolean} [options.trailing=true] - If `true`, the last change is applied after `wait` milliseconds.
|
|
26
|
+
*
|
|
27
|
+
* @returns {T} The debounced value.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* import { useDebouncedValue } from 'react-simplikit';
|
|
31
|
+
* import { useState } from 'react';
|
|
32
|
+
*
|
|
33
|
+
* function SearchInput() {
|
|
34
|
+
* const [query, setQuery] = useState('');
|
|
35
|
+
* const debouncedQuery = useDebouncedValue(query, 300);
|
|
36
|
+
*
|
|
37
|
+
* return (
|
|
38
|
+
* <>
|
|
39
|
+
* <input value={query} onChange={e => setQuery(e.target.value)} />
|
|
40
|
+
* <SearchResults query={debouncedQuery} />
|
|
41
|
+
* </>
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
*/
|
|
45
|
+
function useDebouncedValue(value, wait, { leading = false, trailing = true } = {}) {
|
|
46
|
+
const [debouncedValue, setDebouncedValue] = (0, react.useState)(() => value);
|
|
47
|
+
const debounced = require_useDebounce.useDebounce((next) => setDebouncedValue(() => next), wait, {
|
|
48
|
+
leading,
|
|
49
|
+
trailing
|
|
50
|
+
});
|
|
51
|
+
const lastForwardedRef = (0, react.useRef)(value);
|
|
52
|
+
(0, react.useEffect)(function forwardChangedValue() {
|
|
53
|
+
if (Object.is(lastForwardedRef.current, value) && Object.is(value, debouncedValue)) return;
|
|
54
|
+
lastForwardedRef.current = value;
|
|
55
|
+
debounced(value);
|
|
56
|
+
}, [
|
|
57
|
+
value,
|
|
58
|
+
debouncedValue,
|
|
59
|
+
debounced
|
|
60
|
+
]);
|
|
61
|
+
return debouncedValue;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
exports.useDebouncedValue = useDebouncedValue;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/hooks/useDebouncedValue/useDebouncedValue.d.ts
|
|
3
|
+
type DebounceOptions = {
|
|
4
|
+
leading?: boolean;
|
|
5
|
+
trailing?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* @description
|
|
9
|
+
* `useDebouncedValue` is a React hook that returns a debounced copy of the given value.
|
|
10
|
+
* The caller keeps owning the state; the hook only delays how quickly the returned value follows it.
|
|
11
|
+
* The returned value updates `wait` milliseconds after the last change, which is useful for
|
|
12
|
+
* deriving a search query or a validation input from fast-changing state.
|
|
13
|
+
*
|
|
14
|
+
* On the first render and on the server the value is returned as is. A change is never scheduled
|
|
15
|
+
* on mount, so with `leading: true` the first change after mount is applied immediately.
|
|
16
|
+
* If both `leading` and `trailing` are `false`, the returned value never updates.
|
|
17
|
+
*
|
|
18
|
+
* The value is compared by reference. Passing a new object or array on every render keeps
|
|
19
|
+
* the returned value updating every `wait` milliseconds; stabilize the reference first, for
|
|
20
|
+
* example with `usePreservedReference`.
|
|
21
|
+
*
|
|
22
|
+
* @template T - The type of the value.
|
|
23
|
+
* @param {T} value - The value to debounce.
|
|
24
|
+
* @param {number} wait - The number of milliseconds to wait after the last change before updating.
|
|
25
|
+
* @param {DebounceOptions} [options] - Configuration options for debounce behavior.
|
|
26
|
+
* @param {boolean} [options.leading=false] - If `true`, the first change after an idle period is applied immediately.
|
|
27
|
+
* @param {boolean} [options.trailing=true] - If `true`, the last change is applied after `wait` milliseconds.
|
|
28
|
+
*
|
|
29
|
+
* @returns {T} The debounced value.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* import { useDebouncedValue } from 'react-simplikit';
|
|
33
|
+
* import { useState } from 'react';
|
|
34
|
+
*
|
|
35
|
+
* function SearchInput() {
|
|
36
|
+
* const [query, setQuery] = useState('');
|
|
37
|
+
* const debouncedQuery = useDebouncedValue(query, 300);
|
|
38
|
+
*
|
|
39
|
+
* return (
|
|
40
|
+
* <>
|
|
41
|
+
* <input value={query} onChange={e => setQuery(e.target.value)} />
|
|
42
|
+
* <SearchResults query={debouncedQuery} />
|
|
43
|
+
* </>
|
|
44
|
+
* );
|
|
45
|
+
* }
|
|
46
|
+
*/
|
|
47
|
+
declare function useDebouncedValue<T>(value: T, wait: number, { leading, trailing }?: DebounceOptions): T;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { useDebouncedValue };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/hooks/useDebouncedValue/useDebouncedValue.d.ts
|
|
3
|
+
type DebounceOptions = {
|
|
4
|
+
leading?: boolean;
|
|
5
|
+
trailing?: boolean;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* @description
|
|
9
|
+
* `useDebouncedValue` is a React hook that returns a debounced copy of the given value.
|
|
10
|
+
* The caller keeps owning the state; the hook only delays how quickly the returned value follows it.
|
|
11
|
+
* The returned value updates `wait` milliseconds after the last change, which is useful for
|
|
12
|
+
* deriving a search query or a validation input from fast-changing state.
|
|
13
|
+
*
|
|
14
|
+
* On the first render and on the server the value is returned as is. A change is never scheduled
|
|
15
|
+
* on mount, so with `leading: true` the first change after mount is applied immediately.
|
|
16
|
+
* If both `leading` and `trailing` are `false`, the returned value never updates.
|
|
17
|
+
*
|
|
18
|
+
* The value is compared by reference. Passing a new object or array on every render keeps
|
|
19
|
+
* the returned value updating every `wait` milliseconds; stabilize the reference first, for
|
|
20
|
+
* example with `usePreservedReference`.
|
|
21
|
+
*
|
|
22
|
+
* @template T - The type of the value.
|
|
23
|
+
* @param {T} value - The value to debounce.
|
|
24
|
+
* @param {number} wait - The number of milliseconds to wait after the last change before updating.
|
|
25
|
+
* @param {DebounceOptions} [options] - Configuration options for debounce behavior.
|
|
26
|
+
* @param {boolean} [options.leading=false] - If `true`, the first change after an idle period is applied immediately.
|
|
27
|
+
* @param {boolean} [options.trailing=true] - If `true`, the last change is applied after `wait` milliseconds.
|
|
28
|
+
*
|
|
29
|
+
* @returns {T} The debounced value.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* import { useDebouncedValue } from 'react-simplikit';
|
|
33
|
+
* import { useState } from 'react';
|
|
34
|
+
*
|
|
35
|
+
* function SearchInput() {
|
|
36
|
+
* const [query, setQuery] = useState('');
|
|
37
|
+
* const debouncedQuery = useDebouncedValue(query, 300);
|
|
38
|
+
*
|
|
39
|
+
* return (
|
|
40
|
+
* <>
|
|
41
|
+
* <input value={query} onChange={e => setQuery(e.target.value)} />
|
|
42
|
+
* <SearchResults query={debouncedQuery} />
|
|
43
|
+
* </>
|
|
44
|
+
* );
|
|
45
|
+
* }
|
|
46
|
+
*/
|
|
47
|
+
declare function useDebouncedValue<T>(value: T, wait: number, { leading, trailing }?: DebounceOptions): T;
|
|
48
|
+
//#endregion
|
|
49
|
+
export { useDebouncedValue };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useDebounce } from "../useDebounce/useDebounce.mjs";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
//#region src/hooks/useDebouncedValue/useDebouncedValue.ts
|
|
5
|
+
/**
|
|
6
|
+
* @description
|
|
7
|
+
* `useDebouncedValue` is a React hook that returns a debounced copy of the given value.
|
|
8
|
+
* The caller keeps owning the state; the hook only delays how quickly the returned value follows it.
|
|
9
|
+
* The returned value updates `wait` milliseconds after the last change, which is useful for
|
|
10
|
+
* deriving a search query or a validation input from fast-changing state.
|
|
11
|
+
*
|
|
12
|
+
* On the first render and on the server the value is returned as is. A change is never scheduled
|
|
13
|
+
* on mount, so with `leading: true` the first change after mount is applied immediately.
|
|
14
|
+
* If both `leading` and `trailing` are `false`, the returned value never updates.
|
|
15
|
+
*
|
|
16
|
+
* The value is compared by reference. Passing a new object or array on every render keeps
|
|
17
|
+
* the returned value updating every `wait` milliseconds; stabilize the reference first, for
|
|
18
|
+
* example with `usePreservedReference`.
|
|
19
|
+
*
|
|
20
|
+
* @template T - The type of the value.
|
|
21
|
+
* @param {T} value - The value to debounce.
|
|
22
|
+
* @param {number} wait - The number of milliseconds to wait after the last change before updating.
|
|
23
|
+
* @param {DebounceOptions} [options] - Configuration options for debounce behavior.
|
|
24
|
+
* @param {boolean} [options.leading=false] - If `true`, the first change after an idle period is applied immediately.
|
|
25
|
+
* @param {boolean} [options.trailing=true] - If `true`, the last change is applied after `wait` milliseconds.
|
|
26
|
+
*
|
|
27
|
+
* @returns {T} The debounced value.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* import { useDebouncedValue } from 'react-simplikit';
|
|
31
|
+
* import { useState } from 'react';
|
|
32
|
+
*
|
|
33
|
+
* function SearchInput() {
|
|
34
|
+
* const [query, setQuery] = useState('');
|
|
35
|
+
* const debouncedQuery = useDebouncedValue(query, 300);
|
|
36
|
+
*
|
|
37
|
+
* return (
|
|
38
|
+
* <>
|
|
39
|
+
* <input value={query} onChange={e => setQuery(e.target.value)} />
|
|
40
|
+
* <SearchResults query={debouncedQuery} />
|
|
41
|
+
* </>
|
|
42
|
+
* );
|
|
43
|
+
* }
|
|
44
|
+
*/
|
|
45
|
+
function useDebouncedValue(value, wait, { leading = false, trailing = true } = {}) {
|
|
46
|
+
const [debouncedValue, setDebouncedValue] = useState(() => value);
|
|
47
|
+
const debounced = useDebounce((next) => setDebouncedValue(() => next), wait, {
|
|
48
|
+
leading,
|
|
49
|
+
trailing
|
|
50
|
+
});
|
|
51
|
+
const lastForwardedRef = useRef(value);
|
|
52
|
+
useEffect(function forwardChangedValue() {
|
|
53
|
+
if (Object.is(lastForwardedRef.current, value) && Object.is(value, debouncedValue)) return;
|
|
54
|
+
lastForwardedRef.current = value;
|
|
55
|
+
debounced(value);
|
|
56
|
+
}, [
|
|
57
|
+
value,
|
|
58
|
+
debouncedValue,
|
|
59
|
+
debounced
|
|
60
|
+
]);
|
|
61
|
+
return debouncedValue;
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { useDebouncedValue };
|
|
@@ -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,23 +37,45 @@ 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 requestedImpressionRef = (0, react.useRef)(false);
|
|
41
|
+
const hasImpressionStartedRef = (0, react.useRef)(false);
|
|
44
42
|
const impressionEventHandler = require_useDebouncedCallback.useDebouncedCallback({
|
|
45
43
|
timeThreshold,
|
|
46
44
|
onChange: (impressed) => {
|
|
47
|
-
(impressed
|
|
45
|
+
if (impressed) {
|
|
46
|
+
hasImpressionStartedRef.current = true;
|
|
47
|
+
impressionStartHandler();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (hasImpressionStartedRef.current) {
|
|
51
|
+
hasImpressionStartedRef.current = false;
|
|
52
|
+
impressionEndHandler();
|
|
53
|
+
}
|
|
48
54
|
},
|
|
49
55
|
leading: true
|
|
50
56
|
});
|
|
57
|
+
const requestImpressionChange = (impressed) => {
|
|
58
|
+
requestedImpressionRef.current = impressed;
|
|
59
|
+
impressionEventHandler(impressed);
|
|
60
|
+
};
|
|
61
|
+
(0, react.useEffect)(function emitPendingImpressionEndOnUnmount() {
|
|
62
|
+
return () => {
|
|
63
|
+
if (hasImpressionStartedRef.current && !requestedImpressionRef.current) {
|
|
64
|
+
hasImpressionStartedRef.current = false;
|
|
65
|
+
impressionEndHandler();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}, [impressionEndHandler]);
|
|
51
69
|
require_useVisibilityEvent.useVisibilityEvent((documentVisible) => {
|
|
52
70
|
if (!isIntersectingRef.current) return;
|
|
53
|
-
|
|
71
|
+
requestImpressionChange(documentVisible === "visible");
|
|
54
72
|
});
|
|
55
73
|
return require_useIntersectionObserver.useIntersectionObserver((entry) => {
|
|
56
74
|
if (document.visibilityState === "hidden") return;
|
|
57
75
|
const currentRatio = entry.intersectionRatio;
|
|
58
76
|
const isIntersecting = areaThreshold === 0 ? entry.isIntersecting : currentRatio >= areaThreshold;
|
|
59
77
|
isIntersectingRef.current = isIntersecting;
|
|
60
|
-
|
|
78
|
+
requestImpressionChange(isIntersecting);
|
|
61
79
|
}, {
|
|
62
80
|
rootMargin,
|
|
63
81
|
threshold: areaThreshold
|
|
@@ -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.
|
|
@@ -3,13 +3,9 @@ import { usePreservedCallback } from "../usePreservedCallback/usePreservedCallba
|
|
|
3
3
|
import { useDebouncedCallback } from "../useDebouncedCallback/useDebouncedCallback.mjs";
|
|
4
4
|
import { useIntersectionObserver } from "../useIntersectionObserver/useIntersectionObserver.mjs";
|
|
5
5
|
import { useVisibilityEvent } from "../useVisibilityEvent/useVisibilityEvent.mjs";
|
|
6
|
-
import { useRef } from "react";
|
|
6
|
+
import { useEffect, 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,23 +37,45 @@ function useImpressionRef({ onImpressionStart = () => {}, onImpressionEnd = () =
|
|
|
41
37
|
const impressionStartHandler = usePreservedCallback(onImpressionStart);
|
|
42
38
|
const impressionEndHandler = usePreservedCallback(onImpressionEnd);
|
|
43
39
|
const isIntersectingRef = useRef(false);
|
|
40
|
+
const requestedImpressionRef = useRef(false);
|
|
41
|
+
const hasImpressionStartedRef = useRef(false);
|
|
44
42
|
const impressionEventHandler = useDebouncedCallback({
|
|
45
43
|
timeThreshold,
|
|
46
44
|
onChange: (impressed) => {
|
|
47
|
-
(impressed
|
|
45
|
+
if (impressed) {
|
|
46
|
+
hasImpressionStartedRef.current = true;
|
|
47
|
+
impressionStartHandler();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (hasImpressionStartedRef.current) {
|
|
51
|
+
hasImpressionStartedRef.current = false;
|
|
52
|
+
impressionEndHandler();
|
|
53
|
+
}
|
|
48
54
|
},
|
|
49
55
|
leading: true
|
|
50
56
|
});
|
|
57
|
+
const requestImpressionChange = (impressed) => {
|
|
58
|
+
requestedImpressionRef.current = impressed;
|
|
59
|
+
impressionEventHandler(impressed);
|
|
60
|
+
};
|
|
61
|
+
useEffect(function emitPendingImpressionEndOnUnmount() {
|
|
62
|
+
return () => {
|
|
63
|
+
if (hasImpressionStartedRef.current && !requestedImpressionRef.current) {
|
|
64
|
+
hasImpressionStartedRef.current = false;
|
|
65
|
+
impressionEndHandler();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}, [impressionEndHandler]);
|
|
51
69
|
useVisibilityEvent((documentVisible) => {
|
|
52
70
|
if (!isIntersectingRef.current) return;
|
|
53
|
-
|
|
71
|
+
requestImpressionChange(documentVisible === "visible");
|
|
54
72
|
});
|
|
55
73
|
return useIntersectionObserver((entry) => {
|
|
56
74
|
if (document.visibilityState === "hidden") return;
|
|
57
75
|
const currentRatio = entry.intersectionRatio;
|
|
58
76
|
const isIntersecting = areaThreshold === 0 ? entry.isIntersecting : currentRatio >= areaThreshold;
|
|
59
77
|
isIntersectingRef.current = isIntersecting;
|
|
60
|
-
|
|
78
|
+
requestImpressionChange(isIntersecting);
|
|
61
79
|
}, {
|
|
62
80
|
rootMargin,
|
|
63
81
|
threshold: areaThreshold
|
|
@@ -6,7 +6,7 @@ let react = require("react");
|
|
|
6
6
|
* `useInputState` is a React hook that manages an input state with optional value transformation.
|
|
7
7
|
* The returned `onChange` handler works with both `<input>` and `<textarea>` elements.
|
|
8
8
|
*
|
|
9
|
-
* @param {string} [initialValue=""] - The initial value of the input. Defaults to an empty string (`""`).
|
|
9
|
+
* @param {string | (() => string)} [initialValue=""] - The initial value of the input. Defaults to an empty string (`""`).
|
|
10
10
|
* @param {(value: string) => string} [transformValue=(v: string) => v] - A function to transform the input value.
|
|
11
11
|
* Defaults to an identity function that returns the input unchanged.
|
|
12
12
|
*
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
import { ChangeEventHandler } from "react";
|
|
3
3
|
//#region src/hooks/useInputState/useInputState.d.ts
|
|
4
4
|
type InputLikeElement = HTMLInputElement | HTMLTextAreaElement;
|
|
5
|
+
type InitialValue = string | (() => string);
|
|
5
6
|
/**
|
|
6
7
|
* @description
|
|
7
8
|
* `useInputState` is a React hook that manages an input state with optional value transformation.
|
|
8
9
|
* The returned `onChange` handler works with both `<input>` and `<textarea>` elements.
|
|
9
10
|
*
|
|
10
|
-
* @param {string} [initialValue=""] - The initial value of the input. Defaults to an empty string (`""`).
|
|
11
|
+
* @param {string | (() => string)} [initialValue=""] - The initial value of the input. Defaults to an empty string (`""`).
|
|
11
12
|
* @param {(value: string) => string} [transformValue=(v: string) => v] - A function to transform the input value.
|
|
12
13
|
* Defaults to an identity function that returns the input unchanged.
|
|
13
14
|
*
|
|
@@ -26,6 +27,6 @@ type InputLikeElement = HTMLInputElement | HTMLTextAreaElement;
|
|
|
26
27
|
* );
|
|
27
28
|
* }
|
|
28
29
|
*/
|
|
29
|
-
declare function useInputState(initialValue?:
|
|
30
|
+
declare function useInputState(initialValue?: InitialValue, transformValue?: (value: string) => string): readonly [string, ChangeEventHandler<InputLikeElement>];
|
|
30
31
|
//#endregion
|
|
31
32
|
export { useInputState };
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
import { ChangeEventHandler } from "react";
|
|
3
3
|
//#region src/hooks/useInputState/useInputState.d.ts
|
|
4
4
|
type InputLikeElement = HTMLInputElement | HTMLTextAreaElement;
|
|
5
|
+
type InitialValue = string | (() => string);
|
|
5
6
|
/**
|
|
6
7
|
* @description
|
|
7
8
|
* `useInputState` is a React hook that manages an input state with optional value transformation.
|
|
8
9
|
* The returned `onChange` handler works with both `<input>` and `<textarea>` elements.
|
|
9
10
|
*
|
|
10
|
-
* @param {string} [initialValue=""] - The initial value of the input. Defaults to an empty string (`""`).
|
|
11
|
+
* @param {string | (() => string)} [initialValue=""] - The initial value of the input. Defaults to an empty string (`""`).
|
|
11
12
|
* @param {(value: string) => string} [transformValue=(v: string) => v] - A function to transform the input value.
|
|
12
13
|
* Defaults to an identity function that returns the input unchanged.
|
|
13
14
|
*
|
|
@@ -26,6 +27,6 @@ type InputLikeElement = HTMLInputElement | HTMLTextAreaElement;
|
|
|
26
27
|
* );
|
|
27
28
|
* }
|
|
28
29
|
*/
|
|
29
|
-
declare function useInputState(initialValue?:
|
|
30
|
+
declare function useInputState(initialValue?: InitialValue, transformValue?: (value: string) => string): readonly [string, ChangeEventHandler<InputLikeElement>];
|
|
30
31
|
//#endregion
|
|
31
32
|
export { useInputState };
|
|
@@ -6,7 +6,7 @@ import { useCallback, useState } from "react";
|
|
|
6
6
|
* `useInputState` is a React hook that manages an input state with optional value transformation.
|
|
7
7
|
* The returned `onChange` handler works with both `<input>` and `<textarea>` elements.
|
|
8
8
|
*
|
|
9
|
-
* @param {string} [initialValue=""] - The initial value of the input. Defaults to an empty string (`""`).
|
|
9
|
+
* @param {string | (() => string)} [initialValue=""] - The initial value of the input. Defaults to an empty string (`""`).
|
|
10
10
|
* @param {(value: string) => string} [transformValue=(v: string) => v] - A function to transform the input value.
|
|
11
11
|
* Defaults to an identity function that returns the input unchanged.
|
|
12
12
|
*
|