@codeleap/hooks 7.0.2 → 7.1.1
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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -57
- package/dist/index.js.map +1 -1
- package/dist/onMount.js +3 -7
- package/dist/onMount.js.map +1 -1
- package/dist/onUpdate.js +3 -7
- package/dist/onUpdate.js.map +1 -1
- package/dist/useBooleanToggle.js +3 -6
- package/dist/useBooleanToggle.js.map +1 -1
- package/dist/useComponentTestId.js +6 -10
- package/dist/useComponentTestId.js.map +1 -1
- package/dist/useConditionalState.js +6 -10
- package/dist/useConditionalState.js.map +1 -1
- package/dist/useDebounce.js +5 -8
- package/dist/useDebounce.js.map +1 -1
- package/dist/useDebounceCallback.js +6 -9
- package/dist/useDebounceCallback.js.map +1 -1
- package/dist/useDerivedRef.js +4 -8
- package/dist/useDerivedRef.js.map +1 -1
- package/dist/useDerivedState.js +6 -10
- package/dist/useDerivedState.js.map +1 -1
- package/dist/useEffectOnce.js +3 -7
- package/dist/useEffectOnce.js.map +1 -1
- package/dist/useFilteredList.js +3 -6
- package/dist/useFilteredList.js.map +1 -1
- package/dist/useForceRender.js +3 -6
- package/dist/useForceRender.js.map +1 -1
- package/dist/useGuardedAsyncCallback.d.ts +31 -0
- package/dist/useGuardedAsyncCallback.d.ts.map +1 -0
- package/dist/useGuardedAsyncCallback.js +38 -0
- package/dist/useGuardedAsyncCallback.js.map +1 -0
- package/dist/useId.js +5 -9
- package/dist/useId.js.map +1 -1
- package/dist/useInterval.js +8 -11
- package/dist/useInterval.js.map +1 -1
- package/dist/useIsMounted.js +5 -9
- package/dist/useIsMounted.js.map +1 -1
- package/dist/useLazyStore.js +5 -8
- package/dist/useLazyStore.js.map +1 -1
- package/dist/useModal.js +5 -8
- package/dist/useModal.js.map +1 -1
- package/dist/useOptions.js +4 -7
- package/dist/useOptions.js.map +1 -1
- package/dist/usePartialState.js +6 -9
- package/dist/usePartialState.js.map +1 -1
- package/dist/usePlaces.js +23 -43
- package/dist/usePlaces.js.map +1 -1
- package/dist/usePlacesAutocompleteUtils.js +12 -19
- package/dist/usePlacesAutocompleteUtils.js.map +1 -1
- package/dist/usePrevious.js +4 -8
- package/dist/usePrevious.js.map +1 -1
- package/dist/usePromise.js +17 -32
- package/dist/usePromise.js.map +1 -1
- package/dist/useRenderCall.js +3 -6
- package/dist/useRenderCall.js.map +1 -1
- package/dist/useSearch/index.js +24 -38
- package/dist/useSearch/index.js.map +1 -1
- package/dist/useSearch/types.js +1 -2
- package/dist/useStableReference.js +5 -8
- package/dist/useStableReference.js.map +1 -1
- package/dist/useToggle.js +3 -6
- package/dist/useToggle.js.map +1 -1
- package/dist/useUncontrolled.js +6 -10
- package/dist/useUncontrolled.js.map +1 -1
- package/dist/useUnmount.js +5 -9
- package/dist/useUnmount.js.map +1 -1
- package/package.json +8 -8
- package/src/index.ts +1 -0
- package/src/useGuardedAsyncCallback.ts +43 -0
package/dist/useSearch/index.js
CHANGED
|
@@ -1,18 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.useSearch = useSearch;
|
|
13
|
-
const react_1 = require("react");
|
|
14
|
-
const useBooleanToggle_1 = require("../useBooleanToggle");
|
|
15
|
-
const types_1 = require("@codeleap/types");
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { useBooleanToggle } from '../useBooleanToggle';
|
|
3
|
+
import { TypeGuards } from '@codeleap/types';
|
|
16
4
|
/**
|
|
17
5
|
* Hook that manages searchable select/autocomplete state with async loading support.
|
|
18
6
|
* Handles both local filtering and remote data fetching.
|
|
@@ -29,11 +17,11 @@ const types_1 = require("@codeleap/types");
|
|
|
29
17
|
* search.onChangeSearch('query')
|
|
30
18
|
* search.load()
|
|
31
19
|
*/
|
|
32
|
-
function useSearch(props) {
|
|
33
|
-
const { value, multiple, options, filterItems, debugName, defaultOptions, loadOptions, onLoadOptionsError, } =
|
|
34
|
-
const [loading, setLoading] =
|
|
35
|
-
const isValueArray =
|
|
36
|
-
const [labelOptions, setLabelOptions] =
|
|
20
|
+
export function useSearch(props) {
|
|
21
|
+
const { value, multiple, options, filterItems, debugName, defaultOptions, loadOptions, onLoadOptionsError, } = { ...props };
|
|
22
|
+
const [loading, setLoading] = useBooleanToggle(false);
|
|
23
|
+
const isValueArray = TypeGuards.isArray(value) && multiple;
|
|
24
|
+
const [labelOptions, setLabelOptions] = useState(() => {
|
|
37
25
|
if (isValueArray) {
|
|
38
26
|
return defaultOptions.filter(o => value.includes(o.value));
|
|
39
27
|
}
|
|
@@ -43,32 +31,30 @@ function useSearch(props) {
|
|
|
43
31
|
}
|
|
44
32
|
return [_option];
|
|
45
33
|
});
|
|
46
|
-
const [filteredOptions, setFilteredOptions] =
|
|
47
|
-
const [, setSearchInput] =
|
|
48
|
-
function load() {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
setLoading(false);
|
|
59
|
-
});
|
|
34
|
+
const [filteredOptions, setFilteredOptions] = useState(defaultOptions);
|
|
35
|
+
const [, setSearchInput] = useState('');
|
|
36
|
+
async function load() {
|
|
37
|
+
setLoading(true);
|
|
38
|
+
try {
|
|
39
|
+
const options = await loadOptions('');
|
|
40
|
+
setFilteredOptions(options);
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
onLoadOptionsError(e);
|
|
44
|
+
}
|
|
45
|
+
setLoading(false);
|
|
60
46
|
}
|
|
61
|
-
const onChangeSearch = (searchValue) =>
|
|
47
|
+
const onChangeSearch = async (searchValue) => {
|
|
62
48
|
setSearchInput(searchValue);
|
|
63
49
|
if (!!loadOptions) {
|
|
64
50
|
setLoading(true);
|
|
65
51
|
try {
|
|
66
|
-
const _opts =
|
|
52
|
+
const _opts = await loadOptions(searchValue);
|
|
67
53
|
setFilteredOptions(_opts);
|
|
68
54
|
}
|
|
69
55
|
catch (e) {
|
|
70
56
|
console.error(`Error loading select options [${debugName}], e`);
|
|
71
|
-
onLoadOptionsError
|
|
57
|
+
onLoadOptionsError?.(e);
|
|
72
58
|
}
|
|
73
59
|
setTimeout(() => {
|
|
74
60
|
setLoading(false);
|
|
@@ -77,7 +63,7 @@ function useSearch(props) {
|
|
|
77
63
|
}
|
|
78
64
|
const _opts = filterItems(searchValue, options);
|
|
79
65
|
setFilteredOptions(_opts);
|
|
80
|
-
}
|
|
66
|
+
};
|
|
81
67
|
return { loading, setLoading, labelOptions, setLabelOptions, filteredOptions, load, onChangeSearch };
|
|
82
68
|
}
|
|
83
69
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/useSearch/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/useSearch/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,SAAS,CAAkE,KAAgC;IACzH,MAAM,EACJ,KAAK,EACL,QAAQ,EACR,OAAO,EACP,WAAW,EACX,SAAS,EACT,cAAc,EAEd,WAAW,EACX,kBAAkB,GACnB,GAAG,EAAE,GAAG,KAAK,EAAE,CAAA;IAEhB,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAA;IACrD,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAA;IAC1D,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;QACpD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAA;QAC5D,CAAC;QAED,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAA;QAE3D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,CAAA;QACX,CAAC;QAED,OAAO,CAAC,OAAO,CAAC,CAAA;IAClB,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,QAAQ,CAAC,cAAc,CAAC,CAAA;IACtE,MAAM,CAAC,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IAEvC,KAAK,UAAU,IAAI;QACjB,UAAU,CAAC,IAAI,CAAC,CAAA;QAChB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,CAAA;YACrC,kBAAkB,CAAC,OAAO,CAAC,CAAA;QAC7B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,kBAAkB,CAAC,CAAC,CAAC,CAAA;QACvB,CAAC;QACD,UAAU,CAAC,KAAK,CAAC,CAAA;IACnB,CAAC;IAED,MAAM,cAAc,GAAG,KAAK,EAAE,WAAkB,EAAE,EAAE;QAClD,cAAc,CAAC,WAAW,CAAC,CAAA;QAE3B,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAClB,UAAU,CAAC,IAAI,CAAC,CAAA;YAChB,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,CAAA;gBAC5C,kBAAkB,CAAC,KAAK,CAAC,CAAA;YAC3B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,iCAAiC,SAAS,MAAM,CAAC,CAAA;gBAC/D,kBAAkB,EAAE,CAAC,CAAC,CAAC,CAAA;YACzB,CAAC;YACD,UAAU,CAAC,GAAG,EAAE;gBACd,UAAU,CAAC,KAAK,CAAC,CAAA;YACnB,CAAC,EAAE,CAAC,CAAC,CAAA;YACL,OAAM;QACR,CAAC;QACD,MAAM,KAAK,GAAG,WAAW,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;QAC/C,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC,CAAA;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,CAAA;AACtG,CAAC"}
|
package/dist/useSearch/types.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.useStableReference = useStableReference;
|
|
4
|
-
const utils_1 = require("@codeleap/utils");
|
|
5
|
-
const react_1 = require("react");
|
|
1
|
+
import { deepEqual } from '@codeleap/utils';
|
|
2
|
+
import { useRef } from 'react';
|
|
6
3
|
/** Returns the previous ref value when the object is deeply equal to the last render, preventing unnecessary re-renders caused by referential inequality. */
|
|
7
|
-
function useStableReference(value) {
|
|
8
|
-
const ref =
|
|
9
|
-
const hasChanged = !
|
|
4
|
+
export function useStableReference(value) {
|
|
5
|
+
const ref = useRef(value);
|
|
6
|
+
const hasChanged = !deepEqual(ref.current, value);
|
|
10
7
|
if (hasChanged) {
|
|
11
8
|
ref.current = value;
|
|
12
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useStableReference.js","sourceRoot":"","sources":["../src/useStableReference.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useStableReference.js","sourceRoot":"","sources":["../src/useStableReference.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAE9B,6JAA6J;AAC7J,MAAM,UAAU,kBAAkB,CAAgC,KAAQ;IACxE,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAEzB,MAAM,UAAU,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAEjD,IAAI,UAAU,EAAE,CAAC;QACf,GAAG,CAAC,OAAO,GAAG,KAAK,CAAA;IACrB,CAAC;IAED,OAAO,GAAG,CAAC,OAAO,CAAA;AACpB,CAAC"}
|
package/dist/useToggle.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useToggle = useToggle;
|
|
4
|
-
const react_1 = require("react");
|
|
1
|
+
import { useState } from 'react';
|
|
5
2
|
/**
|
|
6
3
|
* Hook that toggles between two values.
|
|
7
4
|
*
|
|
@@ -10,8 +7,8 @@ const react_1 = require("react");
|
|
|
10
7
|
* toggleTheme() // Switches to 'dark'
|
|
11
8
|
* toggleTheme('light') // Sets to 'light'
|
|
12
9
|
*/
|
|
13
|
-
function useToggle(options, initial) {
|
|
14
|
-
const [value, setValue] =
|
|
10
|
+
export function useToggle(options, initial) {
|
|
11
|
+
const [value, setValue] = useState(initial);
|
|
15
12
|
function toggleOrSetValue(newValue) {
|
|
16
13
|
const v = newValue || (value === options[0] ? options[1] : options[0]);
|
|
17
14
|
setValue(v);
|
package/dist/useToggle.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useToggle.js","sourceRoot":"","sources":["../src/useToggle.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useToggle.js","sourceRoot":"","sources":["../src/useToggle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CACvB,OAAU,EACV,OAAU;IAEV,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE3C,SAAS,gBAAgB,CAAC,QAAY;QACpC,MAAM,CAAC,GAAM,QAAQ,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;QAEzE,QAAQ,CAAC,CAAC,CAAC,CAAA;IACb,CAAC;IAED,OAAO,CAAC,KAAK,EAAE,gBAAgB,CAAU,CAAA;AAC3C,CAAC"}
|
package/dist/useUncontrolled.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useUncontrolled = useUncontrolled;
|
|
4
|
-
const react_1 = require("react");
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
5
2
|
/**
|
|
6
3
|
* Hook that manages controlled/uncontrolled component pattern with smooth transitions.
|
|
7
4
|
*
|
|
@@ -14,16 +11,15 @@ const react_1 = require("react");
|
|
|
14
11
|
* onChange: (v) => props.onChange?.(v)
|
|
15
12
|
* })
|
|
16
13
|
*/
|
|
17
|
-
function useUncontrolled({ value, defaultValue, finalValue, rule, onChange, onValueUpdate, }) {
|
|
18
|
-
var _a;
|
|
14
|
+
export function useUncontrolled({ value, defaultValue, finalValue, rule, onChange, onValueUpdate, }) {
|
|
19
15
|
// determine, whether new props indicate controlled state
|
|
20
16
|
const shouldBeControlled = rule(value);
|
|
21
17
|
// initialize state
|
|
22
|
-
const modeRef =
|
|
18
|
+
const modeRef = useRef('initial');
|
|
23
19
|
const initialValue = rule(defaultValue) ? defaultValue : finalValue;
|
|
24
|
-
const [uncontrolledValue, setUncontrolledValue] =
|
|
20
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(initialValue);
|
|
25
21
|
// compute effective value
|
|
26
|
-
let effectiveValue = (
|
|
22
|
+
let effectiveValue = (shouldBeControlled ? value : uncontrolledValue) ?? null;
|
|
27
23
|
if (!shouldBeControlled && modeRef.current === 'controlled') {
|
|
28
24
|
// We are transitioning from controlled to uncontrolled
|
|
29
25
|
// this transition is special as it happens when clearing out
|
|
@@ -47,7 +43,7 @@ function useUncontrolled({ value, defaultValue, finalValue, rule, onChange, onVa
|
|
|
47
43
|
setUncontrolledValue(nextValue);
|
|
48
44
|
}
|
|
49
45
|
};
|
|
50
|
-
|
|
46
|
+
useEffect(() => {
|
|
51
47
|
if (mode === 'uncontrolled') {
|
|
52
48
|
setUncontrolledValue(effectiveValue);
|
|
53
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUncontrolled.js","sourceRoot":"","sources":["../src/useUncontrolled.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useUncontrolled.js","sourceRoot":"","sources":["../src/useUncontrolled.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAanD;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAI,EACjC,KAAK,EACL,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,QAAQ,EACR,aAAa,GACU;IACvB,yDAAyD;IACzD,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAA;IAEtC,mBAAmB;IACnB,MAAM,OAAO,GAAG,MAAM,CAAmB,SAAS,CAAC,CAAA;IACnD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAA;IACnE,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAA;IAExE,0BAA0B;IAC1B,IAAI,cAAc,GAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,IAAI,CAAA;IAEvF,IAAI,CAAC,kBAAkB,IAAI,OAAO,CAAC,OAAO,KAAK,YAAY,EAAE,CAAC;QAC5D,uDAAuD;QACvD,6DAA6D;QAC7D,iEAAiE;QACjE,EAAE;QACF,4DAA4D;QAC5D,+DAA+D;QAC/D,sDAAsD;QACtD,wDAAwD;QACxD,EAAE;QACF,qEAAqE;QAErE,cAAc,GAAG,UAAU,CAAA;IAC7B,CAAC;IAED,OAAO,CAAC,OAAO,GAAG,kBAAkB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,cAAc,CAAA;IACpE,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAA;IAE5B,MAAM,YAAY,GAAG,CAAC,SAAmB,EAAE,EAAE;QAC3C,OAAO,QAAQ,KAAK,UAAU,IAAI,QAAQ,CAAC,SAAS,CAAC,CAAA;QAErD,4DAA4D;QAC5D,8CAA8C;QAC9C,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;YAC5B,oBAAoB,CAAC,SAAS,CAAC,CAAA;QACjC,CAAC;IACH,CAAC,CAAA;IAED,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;YAC5B,oBAAoB,CAAC,cAAc,CAAC,CAAA;QACtC,CAAC;QACD,OAAO,aAAa,KAAK,UAAU,IAAI,aAAa,CAAC,cAAc,CAAC,CAAA;IACtE,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAA;IAE1B,OAAO,CAAC,cAAc,EAAE,YAAY,EAAE,OAAO,CAAC,OAAO,CAAU,CAAA;AACjE,CAAC"}
|
package/dist/useUnmount.js
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.useUnmount = void 0;
|
|
4
|
-
const react_1 = require("react");
|
|
5
|
-
const useEffectOnce_1 = require("./useEffectOnce");
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import { useEffectOnce } from './useEffectOnce';
|
|
6
3
|
/**
|
|
7
4
|
* Hook that runs a cleanup function when the component unmounts.
|
|
8
5
|
* The function reference is updated on each render to always use the latest version.
|
|
@@ -13,11 +10,10 @@ const useEffectOnce_1 = require("./useEffectOnce");
|
|
|
13
10
|
* // Cleanup logic here
|
|
14
11
|
* })
|
|
15
12
|
*/
|
|
16
|
-
const useUnmount = (fn) => {
|
|
17
|
-
const fnRef =
|
|
13
|
+
export const useUnmount = (fn) => {
|
|
14
|
+
const fnRef = useRef(fn);
|
|
18
15
|
// update the ref each render so if it change the newest callback will be invoked
|
|
19
16
|
fnRef.current = fn;
|
|
20
|
-
|
|
17
|
+
useEffectOnce(() => () => fnRef.current());
|
|
21
18
|
};
|
|
22
|
-
exports.useUnmount = useUnmount;
|
|
23
19
|
//# sourceMappingURL=useUnmount.js.map
|
package/dist/useUnmount.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useUnmount.js","sourceRoot":"","sources":["../src/useUnmount.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useUnmount.js","sourceRoot":"","sources":["../src/useUnmount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAE/C;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAa,EAAQ,EAAE;IAChD,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,CAAA;IAExB,iFAAiF;IACjF,KAAK,CAAC,OAAO,GAAG,EAAE,CAAA;IAElB,aAAa,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;AAC5C,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeleap/hooks",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.1.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"directory": "packages/hooks"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@codeleap/config": "7.0.
|
|
26
|
-
"@codeleap/types": "7.0.
|
|
27
|
-
"@codeleap/utils": "7.0.
|
|
28
|
-
"@codeleap/logger": "7.0.
|
|
25
|
+
"@codeleap/config": "7.0.2",
|
|
26
|
+
"@codeleap/types": "7.0.2",
|
|
27
|
+
"@codeleap/utils": "7.0.2",
|
|
28
|
+
"@codeleap/logger": "7.0.2",
|
|
29
29
|
"ts-node-dev": "1.1.8"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
@@ -33,9 +33,9 @@
|
|
|
33
33
|
"typecheck": "bun tsc --noEmit -p ./tsconfig.json"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
|
-
"@codeleap/types": "7.0.
|
|
37
|
-
"@codeleap/utils": "7.0.
|
|
38
|
-
"@codeleap/logger": "7.0.
|
|
36
|
+
"@codeleap/types": "7.0.2",
|
|
37
|
+
"@codeleap/utils": "7.0.2",
|
|
38
|
+
"@codeleap/logger": "7.0.2",
|
|
39
39
|
"axios": "^1.7.9",
|
|
40
40
|
"typescript": "6.0.3",
|
|
41
41
|
"react": "19.1.0",
|
package/src/index.ts
CHANGED
|
@@ -36,6 +36,7 @@ export * from './useDebounceCallback'
|
|
|
36
36
|
export * from './useDerivedRef'
|
|
37
37
|
export * from './useDerivedState'
|
|
38
38
|
export * from './useFilteredList'
|
|
39
|
+
export * from './useGuardedAsyncCallback'
|
|
39
40
|
export * from './useLazyStore'
|
|
40
41
|
export * from './useStableReference'
|
|
41
42
|
export * from './useOptions'
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useCallback, useRef, type DependencyList } from "react";
|
|
2
|
+
|
|
3
|
+
export type GuardedResult<T> = { dropped: true } | { dropped: false; result: T };
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns a stable callback that silently drops invocations while a previous
|
|
7
|
+
* call is still in flight, preventing overlapping async executions.
|
|
8
|
+
*
|
|
9
|
+
* @typeParam T - The resolved return type of the async callback.
|
|
10
|
+
* @param cb - The async function to guard. Only one instance runs at a time.
|
|
11
|
+
* @param deps - Dependency list, same semantics as `useCallback`.
|
|
12
|
+
* @returns A callback that resolves to `{ dropped: true }` if a call was
|
|
13
|
+
* already in progress, or `{ dropped: false, result: T }` on completion.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* const save = useGuardedAsyncCallback(async () => {
|
|
18
|
+
* return await api.saveForm(formData);
|
|
19
|
+
* }, [formData]);
|
|
20
|
+
*
|
|
21
|
+
* const handleClick = async () => {
|
|
22
|
+
* const res = await save();
|
|
23
|
+
* if (!res.dropped) showToast("Saved!");
|
|
24
|
+
* };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function useGuardedAsyncCallback<T>(
|
|
28
|
+
cb: () => Promise<T>,
|
|
29
|
+
deps: DependencyList
|
|
30
|
+
): () => Promise<GuardedResult<T>> {
|
|
31
|
+
const running = useRef(false);
|
|
32
|
+
|
|
33
|
+
return useCallback(async () => {
|
|
34
|
+
if (running.current) return { dropped: true };
|
|
35
|
+
|
|
36
|
+
running.current = true;
|
|
37
|
+
try {
|
|
38
|
+
return { dropped: false, result: await cb() };
|
|
39
|
+
} finally {
|
|
40
|
+
running.current = false;
|
|
41
|
+
}
|
|
42
|
+
}, deps);
|
|
43
|
+
}
|