@cognite/underscore 1.0.1 → 1.48411.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/README.md +2 -0
- package/dist/arrays.d.ts +31 -31
- package/dist/arrays.js +53 -18
- package/dist/arrays.js.map +1 -0
- package/dist/assert.d.ts +6 -6
- package/dist/assert.js +12 -5
- package/dist/assert.js.map +1 -0
- package/dist/brand.d.ts +41 -38
- package/dist/brand.js +39 -0
- package/dist/brand.js.map +1 -0
- package/dist/chunk-and-process-in-parallel.d.ts +112 -106
- package/dist/chunk-and-process-in-parallel.js +138 -29
- package/dist/chunk-and-process-in-parallel.js.map +1 -0
- package/dist/chunk-array.d.ts +25 -25
- package/dist/chunk-array.js +34 -6
- package/dist/chunk-array.js.map +1 -0
- package/dist/class.d.ts +8 -8
- package/dist/class.js +11 -5
- package/dist/class.js.map +1 -0
- package/dist/exhaustive-guard.d.ts +15 -15
- package/dist/exhaustive-guard.js +19 -5
- package/dist/exhaustive-guard.js.map +1 -0
- package/dist/exponential-backoff-with-jitter.d.ts +13 -13
- package/dist/exponential-backoff-with-jitter.js +23 -7
- package/dist/exponential-backoff-with-jitter.js.map +1 -0
- package/dist/generate-unique-name.d.ts +17 -17
- package/dist/generate-unique-name.js +46 -10
- package/dist/generate-unique-name.js.map +1 -0
- package/dist/get-numbers-between.d.ts +15 -15
- package/dist/get-numbers-between.js +21 -5
- package/dist/get-numbers-between.js.map +1 -0
- package/dist/humanize-value.d.ts +3 -3
- package/dist/humanize-value.js +33 -15
- package/dist/humanize-value.js.map +1 -0
- package/dist/index.d.ts +23 -23
- package/dist/index.js +23 -23
- package/dist/index.js.map +1 -0
- package/dist/is-function.d.ts +5 -5
- package/dist/is-function.js +9 -5
- package/dist/is-function.js.map +1 -0
- package/dist/is-primitive.d.ts +7 -7
- package/dist/is-primitive.js +16 -6
- package/dist/is-primitive.js.map +1 -0
- package/dist/is-valid-url.d.ts +11 -14
- package/dist/is-valid-url.js +39 -16
- package/dist/is-valid-url.js.map +1 -0
- package/dist/iterators.d.ts +7 -7
- package/dist/iterators.js +16 -6
- package/dist/iterators.js.map +1 -0
- package/dist/math.d.ts +10 -10
- package/dist/math.js +16 -7
- package/dist/math.js.map +1 -0
- package/dist/random.d.ts +24 -24
- package/dist/random.js +52 -18
- package/dist/random.js.map +1 -0
- package/dist/react/use-debounce.d.ts +21 -21
- package/dist/react/use-debounce.js +39 -14
- package/dist/react/use-debounce.js.map +1 -0
- package/dist/react/use-derived-promise.d.ts +28 -29
- package/dist/react/use-derived-promise.js +70 -33
- package/dist/react/use-derived-promise.js.map +1 -0
- package/dist/react/use-stable-sync-external-store.d.ts +25 -25
- package/dist/react/use-stable-sync-external-store.js +52 -11
- package/dist/react/use-stable-sync-external-store.js.map +1 -0
- package/dist/react.d.ts +3 -3
- package/dist/react.js +5 -4
- package/dist/react.js.map +1 -0
- package/dist/repeat.d.ts +5 -5
- package/dist/repeat.js +11 -5
- package/dist/repeat.js.map +1 -0
- package/dist/retry-async.d.ts +87 -87
- package/dist/retry-async.js +88 -17
- package/dist/retry-async.js.map +1 -0
- package/dist/sleep.d.ts +5 -5
- package/dist/sleep.js +9 -5
- package/dist/sleep.js.map +1 -0
- package/dist/string.d.ts +35 -35
- package/dist/string.js +48 -9
- package/dist/string.js.map +1 -0
- package/dist/structMap/index.d.ts +3 -3
- package/dist/structMap/index.js +4 -0
- package/dist/structMap/index.js.map +1 -0
- package/dist/structMap/stableStringify.d.ts +21 -21
- package/dist/structMap/stableStringify.js +69 -22
- package/dist/structMap/stableStringify.js.map +1 -0
- package/dist/structMap/structMap.d.ts +111 -108
- package/dist/structMap/structMap.js +131 -28
- package/dist/structMap/structMap.js.map +1 -0
- package/dist/structMap/testUtils.d.ts +8 -8
- package/dist/structMap/testUtils.js +26 -0
- package/dist/structMap/testUtils.js.map +1 -0
- package/dist/structMap/types.d.ts +4 -4
- package/dist/structMap/types.js +5 -0
- package/dist/structMap/types.js.map +1 -0
- package/package.json +7 -4
package/dist/random.js
CHANGED
|
@@ -1,22 +1,56 @@
|
|
|
1
|
-
import { repeat
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { repeat } from "./repeat.js";
|
|
2
|
+
/**
|
|
3
|
+
* Generates a random string of the specified length using alphanumeric characters.
|
|
4
|
+
*
|
|
5
|
+
* @param {number} length - The length of the random string to generate. Must be greater than 0.
|
|
6
|
+
* @returns {string} A random string of the specified length.
|
|
7
|
+
* @throws {Error} If the length is less than 1.
|
|
8
|
+
*/ export function randomString(length) {
|
|
9
|
+
if (length < 1) {
|
|
10
|
+
throw new Error('Length must be greater than 0');
|
|
11
|
+
}
|
|
12
|
+
const validCharacters = [
|
|
13
|
+
...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
|
14
|
+
];
|
|
15
|
+
let result = '';
|
|
16
|
+
repeat(()=>{
|
|
17
|
+
result += randomElement(validCharacters);
|
|
18
|
+
}, length);
|
|
19
|
+
return result;
|
|
9
20
|
}
|
|
10
|
-
|
|
11
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Returns a random element from the given array.
|
|
23
|
+
*
|
|
24
|
+
* @template T - The type of elements in the array.
|
|
25
|
+
* @param {T[]} array - The array from which to select a random element.
|
|
26
|
+
* @returns {T} A random element from the array.
|
|
27
|
+
*/ export function randomElement(array) {
|
|
28
|
+
const index = randomInteger(0, array.length);
|
|
29
|
+
return array[index];
|
|
12
30
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Returns a random integer between minInclusive and maxExclusive.
|
|
33
|
+
*
|
|
34
|
+
* @param minInclusive
|
|
35
|
+
* @param maxExclusive
|
|
36
|
+
* @returns
|
|
37
|
+
*/ export function randomInteger(minInclusive, maxExclusive) {
|
|
38
|
+
if (minInclusive >= maxExclusive) {
|
|
39
|
+
throw new Error('The `minInclusive` value must be less than the `maxExclusive` value.');
|
|
40
|
+
}
|
|
41
|
+
return Math.floor(Math.random() * (maxExclusive - minInclusive)) + minInclusive;
|
|
16
42
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Generates a random float within the given range [min, max).
|
|
45
|
+
*
|
|
46
|
+
* @param {number} minInclusive - The minimum value (inclusive).
|
|
47
|
+
* @param {number} maxExclusive - The maximum value (exclusive).
|
|
48
|
+
* @returns {number} A random float within the range [min, max).
|
|
49
|
+
*/ export function randomFloat(minInclusive, maxExclusive) {
|
|
50
|
+
if (minInclusive >= maxExclusive) {
|
|
51
|
+
throw new Error('The `minInclusive` value must be less than the `maxExclusive` value.');
|
|
52
|
+
}
|
|
53
|
+
return Math.random() * (maxExclusive - minInclusive) + minInclusive;
|
|
20
54
|
}
|
|
21
|
-
|
|
22
|
-
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=random.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/random.ts"],"sourcesContent":["import { repeat } from './repeat';\n\n/**\n * Generates a random string of the specified length using alphanumeric characters.\n *\n * @param {number} length - The length of the random string to generate. Must be greater than 0.\n * @returns {string} A random string of the specified length.\n * @throws {Error} If the length is less than 1.\n */\nexport function randomString(length: number): string {\n if (length < 1) {\n throw new Error('Length must be greater than 0');\n }\n const validCharacters = [\n ...'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',\n ];\n let result = '';\n repeat(() => {\n result += randomElement(validCharacters);\n }, length);\n return result;\n}\n\n/**\n * Returns a random element from the given array.\n *\n * @template T - The type of elements in the array.\n * @param {T[]} array - The array from which to select a random element.\n * @returns {T} A random element from the array.\n */\nexport function randomElement<T>(array: readonly T[]): T {\n const index = randomInteger(0, array.length);\n return array[index];\n}\n\n/**\n * Returns a random integer between minInclusive and maxExclusive.\n *\n * @param minInclusive\n * @param maxExclusive\n * @returns\n */\nexport function randomInteger(\n minInclusive: number,\n maxExclusive: number\n): number {\n if (minInclusive >= maxExclusive) {\n throw new Error(\n 'The `minInclusive` value must be less than the `maxExclusive` value.'\n );\n }\n return (\n Math.floor(Math.random() * (maxExclusive - minInclusive)) + minInclusive\n );\n}\n\n/**\n * Generates a random float within the given range [min, max).\n *\n * @param {number} minInclusive - The minimum value (inclusive).\n * @param {number} maxExclusive - The maximum value (exclusive).\n * @returns {number} A random float within the range [min, max).\n */\nexport function randomFloat(\n minInclusive: number,\n maxExclusive: number\n): number {\n if (minInclusive >= maxExclusive) {\n throw new Error(\n 'The `minInclusive` value must be less than the `maxExclusive` value.'\n );\n }\n return Math.random() * (maxExclusive - minInclusive) + minInclusive;\n}\n"],"names":["repeat","randomString","length","Error","validCharacters","result","randomElement","array","index","randomInteger","minInclusive","maxExclusive","Math","floor","random","randomFloat"],"mappings":"AAAA,SAASA,MAAM,QAAQ,cAAW;AAElC;;;;;;CAMC,GACD,OAAO,SAASC,aAAaC,MAAc;IACzC,IAAIA,SAAS,GAAG;QACd,MAAM,IAAIC,MAAM;IAClB;IACA,MAAMC,kBAAkB;WACnB;KACJ;IACD,IAAIC,SAAS;IACbL,OAAO;QACLK,UAAUC,cAAcF;IAC1B,GAAGF;IACH,OAAOG;AACT;AAEA;;;;;;CAMC,GACD,OAAO,SAASC,cAAiBC,KAAmB;IAClD,MAAMC,QAAQC,cAAc,GAAGF,MAAML,MAAM;IAC3C,OAAOK,KAAK,CAACC,MAAM;AACrB;AAEA;;;;;;CAMC,GACD,OAAO,SAASC,cACdC,YAAoB,EACpBC,YAAoB;IAEpB,IAAID,gBAAgBC,cAAc;QAChC,MAAM,IAAIR,MACR;IAEJ;IACA,OACES,KAAKC,KAAK,CAACD,KAAKE,MAAM,KAAMH,CAAAA,eAAeD,YAAW,KAAMA;AAEhE;AAEA;;;;;;CAMC,GACD,OAAO,SAASK,YACdL,YAAoB,EACpBC,YAAoB;IAEpB,IAAID,gBAAgBC,cAAc;QAChC,MAAM,IAAIR,MACR;IAEJ;IACA,OAAOS,KAAKE,MAAM,KAAMH,CAAAA,eAAeD,YAAW,IAAKA;AACzD"}
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
* Hook that debounces a value by a specified delay.
|
|
3
|
+
*
|
|
4
|
+
* The returned value will only update after the specified delay has passed
|
|
5
|
+
* since the last change to the input value. This is useful for reducing
|
|
6
|
+
* the frequency of expensive operations triggered by rapidly changing values.
|
|
7
|
+
*
|
|
8
|
+
* @param value - The value to debounce
|
|
9
|
+
* @param delayInMs - The delay in milliseconds
|
|
10
|
+
* @returns The debounced value
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* const [searchTerm, setSearchTerm] = useState('');
|
|
15
|
+
* const debouncedSearchTerm = useDebounce(searchTerm, 300);
|
|
16
|
+
*
|
|
17
|
+
* // API call only triggers when user stops typing for 300ms
|
|
18
|
+
* useEffect(() => {
|
|
19
|
+
* searchApi(debouncedSearchTerm);
|
|
20
|
+
* }, [debouncedSearchTerm]);
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
23
|
export declare function useDebounce<T>(value: T, delayInMs: number): T;
|
|
@@ -1,15 +1,40 @@
|
|
|
1
|
-
import { useEffect
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Hook that debounces a value by a specified delay.
|
|
4
|
+
*
|
|
5
|
+
* The returned value will only update after the specified delay has passed
|
|
6
|
+
* since the last change to the input value. This is useful for reducing
|
|
7
|
+
* the frequency of expensive operations triggered by rapidly changing values.
|
|
8
|
+
*
|
|
9
|
+
* @param value - The value to debounce
|
|
10
|
+
* @param delayInMs - The delay in milliseconds
|
|
11
|
+
* @returns The debounced value
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* const [searchTerm, setSearchTerm] = useState('');
|
|
16
|
+
* const debouncedSearchTerm = useDebounce(searchTerm, 300);
|
|
17
|
+
*
|
|
18
|
+
* // API call only triggers when user stops typing for 300ms
|
|
19
|
+
* useEffect(() => {
|
|
20
|
+
* searchApi(debouncedSearchTerm);
|
|
21
|
+
* }, [debouncedSearchTerm]);
|
|
22
|
+
* ```
|
|
23
|
+
*/ export function useDebounce(value, delayInMs) {
|
|
24
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
25
|
+
useEffect(()=>{
|
|
26
|
+
const handler = setTimeout(()=>{
|
|
27
|
+
setDebouncedValue(value);
|
|
28
|
+
}, delayInMs);
|
|
29
|
+
// Cancel the timeout if value changes (also on delayInMs change or unmount)
|
|
30
|
+
return ()=>{
|
|
31
|
+
clearTimeout(handler);
|
|
32
|
+
};
|
|
33
|
+
}, [
|
|
34
|
+
value,
|
|
35
|
+
delayInMs
|
|
36
|
+
]);
|
|
37
|
+
return debouncedValue;
|
|
13
38
|
}
|
|
14
|
-
|
|
15
|
-
|
|
39
|
+
|
|
40
|
+
//# sourceMappingURL=use-debounce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/use-debounce.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\n\n/**\n * Hook that debounces a value by a specified delay.\n *\n * The returned value will only update after the specified delay has passed\n * since the last change to the input value. This is useful for reducing\n * the frequency of expensive operations triggered by rapidly changing values.\n *\n * @param value - The value to debounce\n * @param delayInMs - The delay in milliseconds\n * @returns The debounced value\n *\n * @example\n * ```tsx\n * const [searchTerm, setSearchTerm] = useState('');\n * const debouncedSearchTerm = useDebounce(searchTerm, 300);\n *\n * // API call only triggers when user stops typing for 300ms\n * useEffect(() => {\n * searchApi(debouncedSearchTerm);\n * }, [debouncedSearchTerm]);\n * ```\n */\nexport function useDebounce<T>(value: T, delayInMs: number): T {\n const [debouncedValue, setDebouncedValue] = useState(value);\n\n useEffect(() => {\n const handler = setTimeout(() => {\n setDebouncedValue(value);\n }, delayInMs);\n\n // Cancel the timeout if value changes (also on delayInMs change or unmount)\n return (): void => {\n clearTimeout(handler);\n };\n }, [value, delayInMs]);\n\n return debouncedValue;\n}\n"],"names":["useEffect","useState","useDebounce","value","delayInMs","debouncedValue","setDebouncedValue","handler","setTimeout","clearTimeout"],"mappings":"AAAA,SAASA,SAAS,EAAEC,QAAQ,QAAQ,QAAQ;AAE5C;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,OAAO,SAASC,YAAeC,KAAQ,EAAEC,SAAiB;IACxD,MAAM,CAACC,gBAAgBC,kBAAkB,GAAGL,SAASE;IAErDH,UAAU;QACR,MAAMO,UAAUC,WAAW;YACzBF,kBAAkBH;QACpB,GAAGC;QAEH,4EAA4E;QAC5E,OAAO;YACLK,aAAaF;QACf;IACF,GAAG;QAACJ;QAAOC;KAAU;IAErB,OAAOC;AACT"}
|
|
@@ -1,34 +1,33 @@
|
|
|
1
|
-
type UseDerivedPromiseResult<T> = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export type UseDerivedPromiseResult<T> = {
|
|
2
|
+
data: T | undefined;
|
|
3
|
+
error: Error | undefined;
|
|
4
|
+
isLoading: true;
|
|
5
5
|
} | {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
data: T;
|
|
7
|
+
error: undefined;
|
|
8
|
+
isLoading: false;
|
|
9
9
|
} | {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
data: undefined;
|
|
11
|
+
error: Error;
|
|
12
|
+
isLoading: false;
|
|
13
13
|
};
|
|
14
14
|
/**
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
15
|
+
* A custom React hook that executes a promise function whenever its dependencies change.
|
|
16
|
+
* It manages the loading state, error handling, and the result of the promise.
|
|
17
|
+
*
|
|
18
|
+
* @param promiseFn - A function that returns a promise.
|
|
19
|
+
* @param deps - An array of dependencies that trigger the promise execution when changed.
|
|
20
|
+
* @returns An object containing the data, loading state, and error from the promise execution.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Usage inside a React component
|
|
24
|
+
* const { data: user, error, isLoading } = useDerivedPromise(
|
|
25
|
+
* () => getUserFromId(userId),
|
|
26
|
+
* [userId]
|
|
27
|
+
* );
|
|
28
|
+
*
|
|
29
|
+
* if (isLoading) return <div>Loading...</div>;
|
|
30
|
+
* if (error) return <div>Error: {error.message}</div>;
|
|
31
|
+
* return <div>User: {user.name}</div>;
|
|
32
|
+
*/
|
|
33
33
|
export declare function useDerivedPromise<T>(promiseFn: () => Promise<T>, deps: React.DependencyList): UseDerivedPromiseResult<T>;
|
|
34
|
-
export {};
|
|
@@ -1,34 +1,71 @@
|
|
|
1
|
-
import { useEffect
|
|
2
|
-
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
/* eslint-disable @eslint-react/hooks-extra/no-direct-set-state-in-use-effect */ import { useEffect, useState } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* A custom React hook that executes a promise function whenever its dependencies change.
|
|
4
|
+
* It manages the loading state, error handling, and the result of the promise.
|
|
5
|
+
*
|
|
6
|
+
* @param promiseFn - A function that returns a promise.
|
|
7
|
+
* @param deps - An array of dependencies that trigger the promise execution when changed.
|
|
8
|
+
* @returns An object containing the data, loading state, and error from the promise execution.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // Usage inside a React component
|
|
12
|
+
* const { data: user, error, isLoading } = useDerivedPromise(
|
|
13
|
+
* () => getUserFromId(userId),
|
|
14
|
+
* [userId]
|
|
15
|
+
* );
|
|
16
|
+
*
|
|
17
|
+
* if (isLoading) return <div>Loading...</div>;
|
|
18
|
+
* if (error) return <div>Error: {error.message}</div>;
|
|
19
|
+
* return <div>User: {user.name}</div>;
|
|
20
|
+
*/ export function useDerivedPromise(promiseFn, deps) {
|
|
21
|
+
const [data, setData] = useState(undefined);
|
|
22
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
23
|
+
const [error, setError] = useState(undefined);
|
|
24
|
+
useEffect(()=>{
|
|
25
|
+
let isActive = true;
|
|
26
|
+
// If a dependency changes, reset loading state
|
|
27
|
+
setIsLoading(true);
|
|
28
|
+
const executePromise = async ()=>{
|
|
29
|
+
try {
|
|
30
|
+
const result = await promiseFn();
|
|
31
|
+
if (isActive) {
|
|
32
|
+
setData(result);
|
|
33
|
+
}
|
|
34
|
+
} catch (err) {
|
|
35
|
+
if (isActive) {
|
|
36
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
37
|
+
}
|
|
38
|
+
} finally{
|
|
39
|
+
if (isActive) {
|
|
40
|
+
setIsLoading(false);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
executePromise();
|
|
45
|
+
return ()=>{
|
|
46
|
+
isActive = false;
|
|
47
|
+
};
|
|
48
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
|
+
}, deps); // Effect re-runs only when these dependencies change
|
|
50
|
+
if (isLoading) {
|
|
51
|
+
return {
|
|
52
|
+
data,
|
|
53
|
+
error,
|
|
54
|
+
isLoading: true
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (error) {
|
|
58
|
+
return {
|
|
59
|
+
data: undefined,
|
|
60
|
+
error,
|
|
61
|
+
isLoading: false
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
data: data,
|
|
66
|
+
error: undefined,
|
|
67
|
+
isLoading: false
|
|
68
|
+
};
|
|
32
69
|
}
|
|
33
|
-
|
|
34
|
-
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=use-derived-promise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/use-derived-promise.ts"],"sourcesContent":["/* eslint-disable @eslint-react/hooks-extra/no-direct-set-state-in-use-effect */\nimport { useEffect, useState } from 'react';\n\nexport type UseDerivedPromiseResult<T> =\n // Loading state\n | {\n data: T | undefined;\n error: Error | undefined;\n isLoading: true;\n }\n // Resolved state\n | {\n data: T;\n error: undefined;\n isLoading: false;\n }\n // Rejected state\n | {\n data: undefined;\n error: Error;\n isLoading: false;\n };\n\n/**\n * A custom React hook that executes a promise function whenever its dependencies change.\n * It manages the loading state, error handling, and the result of the promise.\n *\n * @param promiseFn - A function that returns a promise.\n * @param deps - An array of dependencies that trigger the promise execution when changed.\n * @returns An object containing the data, loading state, and error from the promise execution.\n *\n * @example\n * // Usage inside a React component\n * const { data: user, error, isLoading } = useDerivedPromise(\n * () => getUserFromId(userId),\n * [userId]\n * );\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n * return <div>User: {user.name}</div>;\n */\nexport function useDerivedPromise<T>(\n promiseFn: () => Promise<T>,\n deps: React.DependencyList\n): UseDerivedPromiseResult<T> {\n const [data, setData] = useState<T | undefined>(undefined);\n const [isLoading, setIsLoading] = useState<boolean>(true);\n const [error, setError] = useState<Error | undefined>(undefined);\n\n useEffect(() => {\n let isActive = true;\n\n // If a dependency changes, reset loading state\n setIsLoading(true);\n\n const executePromise = async (): Promise<void> => {\n try {\n const result = await promiseFn();\n if (isActive) {\n setData(result);\n }\n } catch (err) {\n if (isActive) {\n setError(err instanceof Error ? err : new Error(String(err)));\n }\n } finally {\n if (isActive) {\n setIsLoading(false);\n }\n }\n };\n\n executePromise();\n\n return (): void => {\n isActive = false;\n };\n\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, deps); // Effect re-runs only when these dependencies change\n\n if (isLoading) {\n return { data, error, isLoading: true };\n }\n if (error) {\n return { data: undefined, error, isLoading: false };\n }\n return { data: data as T, error: undefined, isLoading: false };\n}\n"],"names":["useEffect","useState","useDerivedPromise","promiseFn","deps","data","setData","undefined","isLoading","setIsLoading","error","setError","isActive","executePromise","result","err","Error","String"],"mappings":"AAAA,8EAA8E,GAC9E,SAASA,SAAS,EAAEC,QAAQ,QAAQ,QAAQ;AAsB5C;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,SAASC,kBACdC,SAA2B,EAC3BC,IAA0B;IAE1B,MAAM,CAACC,MAAMC,QAAQ,GAAGL,SAAwBM;IAChD,MAAM,CAACC,WAAWC,aAAa,GAAGR,SAAkB;IACpD,MAAM,CAACS,OAAOC,SAAS,GAAGV,SAA4BM;IAEtDP,UAAU;QACR,IAAIY,WAAW;QAEf,+CAA+C;QAC/CH,aAAa;QAEb,MAAMI,iBAAiB;YACrB,IAAI;gBACF,MAAMC,SAAS,MAAMX;gBACrB,IAAIS,UAAU;oBACZN,QAAQQ;gBACV;YACF,EAAE,OAAOC,KAAK;gBACZ,IAAIH,UAAU;oBACZD,SAASI,eAAeC,QAAQD,MAAM,IAAIC,MAAMC,OAAOF;gBACzD;YACF,SAAU;gBACR,IAAIH,UAAU;oBACZH,aAAa;gBACf;YACF;QACF;QAEAI;QAEA,OAAO;YACLD,WAAW;QACb;IAEA,uDAAuD;IACzD,GAAGR,OAAO,qDAAqD;IAE/D,IAAII,WAAW;QACb,OAAO;YAAEH;YAAMK;YAAOF,WAAW;QAAK;IACxC;IACA,IAAIE,OAAO;QACT,OAAO;YAAEL,MAAME;YAAWG;YAAOF,WAAW;QAAM;IACpD;IACA,OAAO;QAAEH,MAAMA;QAAWK,OAAOH;QAAWC,WAAW;IAAM;AAC/D"}
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
2
|
+
* A wrapper around React's `useSyncExternalStore` that returns a referentially
|
|
3
|
+
* stable value from a mutable data source.
|
|
4
|
+
*
|
|
5
|
+
* This hook uses structural cloning and deep equality checks to keep returning
|
|
6
|
+
* the same reference for the same value, making it safe to use with dependency
|
|
7
|
+
* arrays in other hooks.
|
|
8
|
+
*
|
|
9
|
+
* This is performance-sensitive and should be used with small slices of data.
|
|
10
|
+
*
|
|
11
|
+
* @template T - structurally-cloneable data type from your store
|
|
12
|
+
*
|
|
13
|
+
* @param subscribe - A function that subscribes to the external store and
|
|
14
|
+
* returns an unsubscribe function. Called with a callback that should be
|
|
15
|
+
* invoked whenever the store changes. Should be memoized.
|
|
16
|
+
* @param getSnapshot - A function that retrieves the current value from the
|
|
17
|
+
* external store. Must be a pure function and can be called multiple times
|
|
18
|
+
* per render. Must return a structurally-cloneable value. Does not need to be
|
|
19
|
+
* memoized.
|
|
20
|
+
*
|
|
21
|
+
* @returns The current value from the store, with referential stability
|
|
22
|
+
* guaranteed when the value content hasn't changed.
|
|
23
|
+
*
|
|
24
|
+
* @see [React
|
|
25
|
+
* useSyncExternalStore](https://react.dev/reference/react/useSyncExternalStore)
|
|
26
|
+
*/
|
|
27
27
|
export declare function useStableSyncExternalStore<T>(subscribe: (callback: VoidFunction) => VoidFunction, getSnapshot: () => T): T;
|
|
@@ -1,12 +1,53 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
import { useRef, useSyncExternalStore } from "react";
|
|
2
|
+
import { isEqual } from "lodash-es";
|
|
3
|
+
/**
|
|
4
|
+
* A wrapper around React's `useSyncExternalStore` that returns a referentially
|
|
5
|
+
* stable value from a mutable data source.
|
|
6
|
+
*
|
|
7
|
+
* This hook uses structural cloning and deep equality checks to keep returning
|
|
8
|
+
* the same reference for the same value, making it safe to use with dependency
|
|
9
|
+
* arrays in other hooks.
|
|
10
|
+
*
|
|
11
|
+
* This is performance-sensitive and should be used with small slices of data.
|
|
12
|
+
*
|
|
13
|
+
* @template T - structurally-cloneable data type from your store
|
|
14
|
+
*
|
|
15
|
+
* @param subscribe - A function that subscribes to the external store and
|
|
16
|
+
* returns an unsubscribe function. Called with a callback that should be
|
|
17
|
+
* invoked whenever the store changes. Should be memoized.
|
|
18
|
+
* @param getSnapshot - A function that retrieves the current value from the
|
|
19
|
+
* external store. Must be a pure function and can be called multiple times
|
|
20
|
+
* per render. Must return a structurally-cloneable value. Does not need to be
|
|
21
|
+
* memoized.
|
|
22
|
+
*
|
|
23
|
+
* @returns The current value from the store, with referential stability
|
|
24
|
+
* guaranteed when the value content hasn't changed.
|
|
25
|
+
*
|
|
26
|
+
* @see [React
|
|
27
|
+
* useSyncExternalStore](https://react.dev/reference/react/useSyncExternalStore)
|
|
28
|
+
*/ export function useStableSyncExternalStore(subscribe, getSnapshot) {
|
|
29
|
+
// Store the previous value to compare against for referential stability
|
|
30
|
+
const prevValueRef = useRef(null);
|
|
31
|
+
// Wrap the snapshot getter to add cloning and deep equality comparison.
|
|
32
|
+
// useSyncExternalStore does not benefit from memoizing this function,
|
|
33
|
+
// performance instead relies on consumers leveraging the returned stable
|
|
34
|
+
// reference in their own memoization.
|
|
35
|
+
const wrappedGetSnapshot = ()=>{
|
|
36
|
+
// Get the raw value from the snapshot function
|
|
37
|
+
const rawValue = getSnapshot();
|
|
38
|
+
// Clone the value to ensure immutability and to compare with previous value
|
|
39
|
+
const clonedValue = structuredClone(rawValue);
|
|
40
|
+
// Check if the value is equal to the previous value
|
|
41
|
+
const prevValue = prevValueRef.current;
|
|
42
|
+
if (prevValue !== null && isEqual(prevValue, clonedValue)) {
|
|
43
|
+
// Return the previous reference to maintain referential identity
|
|
44
|
+
return prevValue;
|
|
45
|
+
}
|
|
46
|
+
// Update the memoized value and return the new one
|
|
47
|
+
prevValueRef.current = clonedValue;
|
|
48
|
+
return clonedValue;
|
|
49
|
+
};
|
|
50
|
+
return useSyncExternalStore(subscribe, wrappedGetSnapshot);
|
|
10
51
|
}
|
|
11
|
-
|
|
12
|
-
|
|
52
|
+
|
|
53
|
+
//# sourceMappingURL=use-stable-sync-external-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/react/use-stable-sync-external-store.ts"],"sourcesContent":["import { useRef, useSyncExternalStore } from 'react';\n\nimport { isEqual } from 'lodash-es';\n\n/**\n * A wrapper around React's `useSyncExternalStore` that returns a referentially\n * stable value from a mutable data source.\n *\n * This hook uses structural cloning and deep equality checks to keep returning\n * the same reference for the same value, making it safe to use with dependency\n * arrays in other hooks.\n *\n * This is performance-sensitive and should be used with small slices of data.\n *\n * @template T - structurally-cloneable data type from your store\n *\n * @param subscribe - A function that subscribes to the external store and\n * returns an unsubscribe function. Called with a callback that should be\n * invoked whenever the store changes. Should be memoized.\n * @param getSnapshot - A function that retrieves the current value from the\n * external store. Must be a pure function and can be called multiple times\n * per render. Must return a structurally-cloneable value. Does not need to be\n * memoized.\n *\n * @returns The current value from the store, with referential stability\n * guaranteed when the value content hasn't changed.\n *\n * @see [React\n * useSyncExternalStore](https://react.dev/reference/react/useSyncExternalStore)\n */\nexport function useStableSyncExternalStore<T>(\n subscribe: (callback: VoidFunction) => VoidFunction,\n getSnapshot: () => T\n): T {\n // Store the previous value to compare against for referential stability\n const prevValueRef = useRef<T | null>(null);\n\n // Wrap the snapshot getter to add cloning and deep equality comparison.\n // useSyncExternalStore does not benefit from memoizing this function,\n // performance instead relies on consumers leveraging the returned stable\n // reference in their own memoization.\n const wrappedGetSnapshot = (): T => {\n // Get the raw value from the snapshot function\n const rawValue = getSnapshot();\n\n // Clone the value to ensure immutability and to compare with previous value\n const clonedValue = structuredClone(rawValue);\n\n // Check if the value is equal to the previous value\n const prevValue = prevValueRef.current;\n if (prevValue !== null && isEqual(prevValue, clonedValue)) {\n // Return the previous reference to maintain referential identity\n return prevValue;\n }\n\n // Update the memoized value and return the new one\n prevValueRef.current = clonedValue;\n return clonedValue;\n };\n\n return useSyncExternalStore(subscribe, wrappedGetSnapshot);\n}\n"],"names":["useRef","useSyncExternalStore","isEqual","useStableSyncExternalStore","subscribe","getSnapshot","prevValueRef","wrappedGetSnapshot","rawValue","clonedValue","structuredClone","prevValue","current"],"mappings":"AAAA,SAASA,MAAM,EAAEC,oBAAoB,QAAQ,QAAQ;AAErD,SAASC,OAAO,QAAQ,YAAY;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;CAyBC,GACD,OAAO,SAASC,2BACdC,SAAmD,EACnDC,WAAoB;IAEpB,wEAAwE;IACxE,MAAMC,eAAeN,OAAiB;IAEtC,wEAAwE;IACxE,sEAAsE;IACtE,yEAAyE;IACzE,sCAAsC;IACtC,MAAMO,qBAAqB;QACzB,+CAA+C;QAC/C,MAAMC,WAAWH;QAEjB,4EAA4E;QAC5E,MAAMI,cAAcC,gBAAgBF;QAEpC,oDAAoD;QACpD,MAAMG,YAAYL,aAAaM,OAAO;QACtC,IAAID,cAAc,QAAQT,QAAQS,WAAWF,cAAc;YACzD,iEAAiE;YACjE,OAAOE;QACT;QAEA,mDAAmD;QACnDL,aAAaM,OAAO,GAAGH;QACvB,OAAOA;IACT;IAEA,OAAOR,qBAAqBG,WAAWG;AACzC"}
|
package/dist/react.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { useDebounce } from
|
|
2
|
-
export { useDerivedPromise } from
|
|
3
|
-
export { useStableSyncExternalStore } from
|
|
1
|
+
export { useDebounce } from "./react/use-debounce";
|
|
2
|
+
export { useDerivedPromise, type UseDerivedPromiseResult } from "./react/use-derived-promise";
|
|
3
|
+
export { useStableSyncExternalStore } from "./react/use-stable-sync-external-store";
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
export { useDebounce } from "./react/use-debounce.js";
|
|
2
|
+
export { useDerivedPromise } from "./react/use-derived-promise.js";
|
|
3
|
+
export { useStableSyncExternalStore } from "./react/use-stable-sync-external-store.js";
|
|
4
|
+
|
|
5
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/react.ts"],"sourcesContent":["export { useDebounce } from './react/use-debounce';\nexport {\n useDerivedPromise,\n type UseDerivedPromiseResult,\n} from './react/use-derived-promise';\nexport { useStableSyncExternalStore } from './react/use-stable-sync-external-store';\n"],"names":["useDebounce","useDerivedPromise","useStableSyncExternalStore"],"mappings":"AAAA,SAASA,WAAW,QAAQ,0BAAuB;AACnD,SACEC,iBAAiB,QAEZ,iCAA8B;AACrC,SAASC,0BAA0B,QAAQ,4CAAyC"}
|
package/dist/repeat.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
* Repeats the execution of a given function a specified number of times.
|
|
3
|
+
*
|
|
4
|
+
* @param fn - The function to be executed repeatedly.
|
|
5
|
+
* @param times - The number of times to execute the function.
|
|
6
|
+
*/
|
|
7
7
|
export declare function repeat(fn: VoidFunction, times: number): void;
|
package/dist/repeat.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
function
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Repeats the execution of a given function a specified number of times.
|
|
3
|
+
*
|
|
4
|
+
* @param fn - The function to be executed repeatedly.
|
|
5
|
+
* @param times - The number of times to execute the function.
|
|
6
|
+
*/ export function repeat(fn, times) {
|
|
7
|
+
for(let i = 0; i < times; ++i){
|
|
8
|
+
fn();
|
|
9
|
+
}
|
|
4
10
|
}
|
|
5
|
-
|
|
6
|
-
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=repeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/repeat.ts"],"sourcesContent":["/**\n * Repeats the execution of a given function a specified number of times.\n *\n * @param fn - The function to be executed repeatedly.\n * @param times - The number of times to execute the function.\n */\nexport function repeat(fn: VoidFunction, times: number): void {\n for (let i = 0; i < times; ++i) {\n fn();\n }\n}\n"],"names":["repeat","fn","times","i"],"mappings":"AAAA;;;;;CAKC,GACD,OAAO,SAASA,OAAOC,EAAgB,EAAEC,KAAa;IACpD,IAAK,IAAIC,IAAI,GAAGA,IAAID,OAAO,EAAEC,EAAG;QAC9BF;IACF;AACF"}
|