@codeleap/hooks 7.0.0 → 7.0.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.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/onMount.js +16 -0
- package/dist/onMount.js.map +1 -0
- package/dist/onUpdate.js +15 -0
- package/dist/onUpdate.js.map +1 -0
- package/dist/useBooleanToggle.js +22 -0
- package/dist/useBooleanToggle.js.map +1 -0
- package/dist/useComponentTestId.js +43 -0
- package/dist/useComponentTestId.js.map +1 -0
- package/dist/useConditionalState.js +23 -0
- package/dist/useConditionalState.js.map +1 -0
- package/dist/useDebounce.js +25 -0
- package/dist/useDebounce.js.map +1 -0
- package/dist/useDebounceCallback.js +39 -0
- package/dist/useDebounceCallback.js.map +1 -0
- package/dist/useDerivedRef.js +16 -0
- package/dist/useDerivedRef.js.map +1 -0
- package/dist/useDerivedState.js +24 -0
- package/dist/useDerivedState.js.map +1 -0
- package/dist/useEffectOnce.js +14 -0
- package/dist/useEffectOnce.js.map +1 -0
- package/dist/useFilteredList.js +21 -0
- package/dist/useFilteredList.js.map +1 -0
- package/dist/useForceRender.js +13 -0
- package/dist/useForceRender.js.map +1 -0
- package/dist/useId.js +15 -0
- package/dist/useId.js.map +1 -0
- package/dist/useInterval.js +46 -0
- package/dist/useInterval.js.map +1 -0
- package/dist/useIsMounted.js +35 -0
- package/dist/useIsMounted.js.map +1 -0
- package/dist/useLazyStore.js +17 -0
- package/dist/useLazyStore.js.map +1 -0
- package/dist/useModal.js +31 -0
- package/dist/useModal.js.map +1 -0
- package/dist/useOptions.js +25 -0
- package/dist/useOptions.js.map +1 -0
- package/dist/usePartialState.js +23 -0
- package/dist/usePartialState.js.map +1 -0
- package/dist/usePlaces.js +73 -0
- package/dist/usePlaces.js.map +1 -0
- package/dist/usePlacesAutocompleteUtils.js +58 -0
- package/dist/usePlacesAutocompleteUtils.js.map +1 -0
- package/dist/usePrevious.js +19 -0
- package/dist/usePrevious.js.map +1 -0
- package/dist/usePromise.js +62 -0
- package/dist/usePromise.js.map +1 -0
- package/dist/useRenderCall.js +10 -0
- package/dist/useRenderCall.js.map +1 -0
- package/dist/useSearch/index.js +80 -0
- package/dist/useSearch/index.js.map +1 -0
- package/dist/useSearch/types.js +2 -0
- package/dist/useSearch/types.js.map +1 -0
- package/dist/useStableReference.js +12 -0
- package/dist/useStableReference.js.map +1 -0
- package/dist/useToggle.js +18 -0
- package/dist/useToggle.js.map +1 -0
- package/dist/useUncontrolled.js +55 -0
- package/dist/useUncontrolled.js.map +1 -0
- package/dist/useUnmount.js +19 -0
- package/dist/useUnmount.js.map +1 -0
- package/package.json +9 -9
package/dist/index.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useEffect, useRef, useState, useImperativeHandle, useMemo, useCallback, useContext, useLayoutEffect, useDebugValue, useReducer, } from 'react';
|
|
2
|
+
export * from './useConditionalState';
|
|
3
|
+
export * from './usePromise';
|
|
4
|
+
export * from './useUncontrolled';
|
|
5
|
+
export * from './useForceRender';
|
|
6
|
+
export * from './useDebounce';
|
|
7
|
+
export * from './useInterval';
|
|
8
|
+
export * from './onMount';
|
|
9
|
+
export * from './onUpdate';
|
|
10
|
+
export * from './usePrevious';
|
|
11
|
+
export * from './useToggle';
|
|
12
|
+
export * from './useBooleanToggle';
|
|
13
|
+
export * from './useModal';
|
|
14
|
+
export * from './usePlaces';
|
|
15
|
+
export * from './usePlacesAutocompleteUtils';
|
|
16
|
+
export * from './useEffectOnce';
|
|
17
|
+
export * from './useUnmount';
|
|
18
|
+
export * from './useSearch';
|
|
19
|
+
export * from './usePartialState';
|
|
20
|
+
export * from './useIsMounted';
|
|
21
|
+
export * from './useComponentTestId';
|
|
22
|
+
export * from './useId';
|
|
23
|
+
export * from './useDebounceCallback';
|
|
24
|
+
export * from './useDerivedRef';
|
|
25
|
+
export * from './useDerivedState';
|
|
26
|
+
export * from './useFilteredList';
|
|
27
|
+
export * from './useLazyStore';
|
|
28
|
+
export * from './useStableReference';
|
|
29
|
+
export * from './useOptions';
|
|
30
|
+
export * from './useRenderCall';
|
|
31
|
+
export { useEffect, useRef, useState, useImperativeHandle, useMemo, useCallback, useContext, useLayoutEffect, useDebugValue, useReducer, };
|
|
32
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,MAAM,EACN,QAAQ,EACR,mBAAmB,EACnB,OAAO,EACP,WAAW,EACX,UAAU,EACV,eAAe,EACf,aAAa,EACb,UAAU,GACX,MAAM,OAAO,CAAA;AAEd,cAAc,uBAAuB,CAAA;AACrC,cAAc,cAAc,CAAA;AAC5B,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,oBAAoB,CAAA;AAClC,cAAc,YAAY,CAAA;AAC1B,cAAc,aAAa,CAAA;AAC3B,cAAc,8BAA8B,CAAA;AAC5C,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,SAAS,CAAA;AACvB,cAAc,uBAAuB,CAAA;AACrC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA;AACjC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,sBAAsB,CAAA;AACpC,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAE/B,OAAO,EACL,SAAS,EACT,MAAM,EACN,QAAQ,EACR,mBAAmB,EACnB,OAAO,EACP,WAAW,EACX,UAAU,EACV,eAAe,EACf,aAAa,EACb,UAAU,GACX,CAAA"}
|
package/dist/onMount.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that runs a function once when the component mounts.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* onMount(() => {
|
|
7
|
+
* console.log('Component mounted')
|
|
8
|
+
* return () => console.log('Component unmounted')
|
|
9
|
+
* })
|
|
10
|
+
*/
|
|
11
|
+
export const onMount = (func) => {
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
return func();
|
|
14
|
+
}, []);
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=onMount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onMount.js","sourceRoot":"","sources":["../src/onMount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGjC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAiB,EAAE,EAAE;IAC3C,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,IAAI,EAAE,CAAA;IACf,CAAC,EAAE,EAAE,CAAC,CAAA;AACR,CAAC,CAAA"}
|
package/dist/onUpdate.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that runs a function when specified dependencies change.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* onUpdate(() => {
|
|
7
|
+
* console.log('Count changed:', count)
|
|
8
|
+
* }, [count])
|
|
9
|
+
*/
|
|
10
|
+
export const onUpdate = (func, listeners = []) => {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
return func();
|
|
13
|
+
}, listeners);
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=onUpdate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onUpdate.js","sourceRoot":"","sources":["../src/onUpdate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGjC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,IAAiB,EAAE,SAAS,GAAG,EAAE,EAAE,EAAE;IAC5D,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,IAAI,EAAE,CAAA;IACf,CAAC,EAAE,SAAS,CAAC,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that manages a boolean state with toggle functionality.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const [isOpen, toggleOpen] = useBooleanToggle(false)
|
|
7
|
+
* toggleOpen() // Toggles the value
|
|
8
|
+
* toggleOpen(true) // Sets to true
|
|
9
|
+
*/
|
|
10
|
+
export function useBooleanToggle(initial) {
|
|
11
|
+
const [v, setV] = useState(initial);
|
|
12
|
+
function toggleOrSet(value) {
|
|
13
|
+
if (typeof value === 'boolean') {
|
|
14
|
+
setV(value);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
setV((previous) => !previous);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return [v, toggleOrSet];
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=useBooleanToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBooleanToggle.js","sourceRoot":"","sources":["../src/useBooleanToggle.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAC/C,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAEnC,SAAS,WAAW,CAAC,KAAe;QAClC,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC,KAAK,CAAC,CAAA;QACb,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;IAED,OAAO,CAAC,CAAC,EAAE,WAAW,CAAU,CAAA;AAClC,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useRef, Children } from 'react';
|
|
2
|
+
const simpleHash = (str) => {
|
|
3
|
+
let hash = 0;
|
|
4
|
+
for (let i = 0; i < str.length; i++) {
|
|
5
|
+
hash = (hash << 5) - hash + str.charCodeAt(i);
|
|
6
|
+
hash |= 0;
|
|
7
|
+
}
|
|
8
|
+
return Math.abs(hash).toString();
|
|
9
|
+
};
|
|
10
|
+
const normalizeProps = (props, keys) => {
|
|
11
|
+
return keys.reduce((acc, key) => {
|
|
12
|
+
if (key === 'children') {
|
|
13
|
+
acc[key] = Children.map(props[key], (child) => typeof child === 'object' ? '[Component]' : child);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
acc[key] = props[key];
|
|
17
|
+
}
|
|
18
|
+
return acc;
|
|
19
|
+
}, {});
|
|
20
|
+
};
|
|
21
|
+
const normalizeDebugName = (debugName) => {
|
|
22
|
+
return debugName.trim().replace(/\s+/g, '-').toLowerCase();
|
|
23
|
+
};
|
|
24
|
+
const generateComponentTestId = (componentName, props, keys) => {
|
|
25
|
+
const hasDebugName = typeof (props === null || props === void 0 ? void 0 : props.debugName) === 'string';
|
|
26
|
+
if (hasDebugName)
|
|
27
|
+
return `${componentName}:${normalizeDebugName(props === null || props === void 0 ? void 0 : props.debugName)}`;
|
|
28
|
+
const extractedProps = normalizeProps(props, keys);
|
|
29
|
+
return `${componentName}:${simpleHash(JSON.stringify(extractedProps))}`;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Hook that generates a stable test ID for a component based on its props.
|
|
33
|
+
* Uses debugName if available, otherwise generates a hash from specified prop keys.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* const testId = useComponentTestId(Button, props, ['label', 'variant'])
|
|
37
|
+
* // Returns: "Button:debug-name" or "Button:123456"
|
|
38
|
+
*/
|
|
39
|
+
export const useComponentTestId = (Component, props, keys) => {
|
|
40
|
+
const testIdRef = useRef(generateComponentTestId(Component.styleRegistryName, props, keys));
|
|
41
|
+
return testIdRef.current;
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=useComponentTestId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useComponentTestId.js","sourceRoot":"","sources":["../src/useComponentTestId.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAExC,MAAM,UAAU,GAAG,CAAC,GAAW,EAAU,EAAE;IACzC,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QAC7C,IAAI,IAAI,CAAC,CAAA;IACX,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAA;AAClC,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,CAAsB,KAAQ,EAAE,IAAoB,EAAc,EAAE;IACzF,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC9B,IAAI,GAAG,KAAK,UAAU,EAAE,CAAC;YACvB,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAC/F,CAAA;QACH,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAA;QACvB,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC,EAAE,EAAgB,CAAC,CAAA;AACtB,CAAC,CAAA;AAED,MAAM,kBAAkB,GAAG,CAAC,SAAiB,EAAE,EAAE;IAC/C,OAAO,SAAS,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;AAC5D,CAAC,CAAA;AAED,MAAM,uBAAuB,GAAG,CAAsB,aAAqB,EAAE,KAAQ,EAAE,IAAoB,EAAE,EAAE;IAC7G,MAAM,YAAY,GAAG,OAAO,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,SAAS,CAAA,KAAK,QAAQ,CAAA;IACzD,IAAI,YAAY;QAAE,OAAO,GAAG,aAAa,IAAI,kBAAkB,CAAC,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,SAAS,CAAC,EAAE,CAAA;IACnF,MAAM,cAAc,GAAG,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAClD,OAAO,GAAG,aAAa,IAAI,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,EAAE,CAAA;AACzE,CAAC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAChC,SAAc,EACd,KAAQ,EACR,IAAoB,EACpB,EAAE;IACF,MAAM,SAAS,GAAG,MAAM,CAAC,uBAAuB,CAAC,SAAS,CAAC,iBAAiB,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;IAC3F,OAAO,SAAS,CAAC,OAAO,CAAA;AAC1B,CAAC,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { useBooleanToggle } from './useBooleanToggle';
|
|
3
|
+
/**
|
|
4
|
+
* Hook that uses external state if provided, otherwise creates internal state.
|
|
5
|
+
* Useful for creating controlled/uncontrolled component patterns.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // Controlled mode
|
|
9
|
+
* const [value, setValue] = useConditionalState(props.value, props.onChange)
|
|
10
|
+
*
|
|
11
|
+
* // Uncontrolled mode
|
|
12
|
+
* const [value, setValue] = useConditionalState(undefined, undefined, { initialValue: 'default' })
|
|
13
|
+
*/
|
|
14
|
+
export const useConditionalState = (value, setter, options = {}) => {
|
|
15
|
+
const state = (options === null || options === void 0 ? void 0 : options.isBooleanToggle)
|
|
16
|
+
? useBooleanToggle(options === null || options === void 0 ? void 0 : options.initialValue)
|
|
17
|
+
: useState(options === null || options === void 0 ? void 0 : options.initialValue);
|
|
18
|
+
if (typeof value !== 'undefined' && typeof setter === 'function') {
|
|
19
|
+
return [value, setter];
|
|
20
|
+
}
|
|
21
|
+
return state;
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=useConditionalState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useConditionalState.js","sourceRoot":"","sources":["../src/useConditionalState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAA4B,MAAM,OAAO,CAAA;AAE1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AASrD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,KAAoB,EACpB,MAAmB,EACnB,UAAyC,EAAE,EACzB,EAAE;IACpB,MAAM,KAAK,GAAG,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,eAAe;QACpC,CAAC,CAAC,gBAAgB,CAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAuB,CAAC;QACpD,CAAC,CAAC,QAAQ,CAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY,CAAC,CAAA;IAEnC,IAAI,OAAO,KAAK,KAAK,WAAW,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;QACjE,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;IACxB,CAAC;IAED,OAAO,KAAoC,CAAA;AAC7C,CAAC,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that debounces a value, updating it after a specified delay.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const [debouncedSearch, resetDebounce] = useDebounce(searchTerm, 500)
|
|
7
|
+
* // debouncedSearch updates 500ms after searchTerm stops changing
|
|
8
|
+
*/
|
|
9
|
+
export function useDebounce(value, debounce) {
|
|
10
|
+
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
11
|
+
const timeoutRef = useRef(null);
|
|
12
|
+
const reset = () => {
|
|
13
|
+
if (timeoutRef.current) {
|
|
14
|
+
clearTimeout(timeoutRef.current);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
timeoutRef.current = setTimeout(() => {
|
|
19
|
+
setDebouncedValue(value);
|
|
20
|
+
}, debounce);
|
|
21
|
+
return reset;
|
|
22
|
+
}, [value]);
|
|
23
|
+
return [debouncedValue, reset];
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=useDebounce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDebounce.js","sourceRoot":"","sources":["../src/useDebounce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEnD;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,KAAQ,EACR,QAAgB;IAEhB,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE3D,MAAM,UAAU,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAA;IAErE,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QAClC,CAAC;IACH,CAAC,CAAA;IACD,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,iBAAiB,CAAC,KAAK,CAAC,CAAA;QAC1B,CAAC,EAAE,QAAQ,CAAC,CAAA;QAEZ,OAAO,KAAK,CAAA;IACd,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,OAAO,CAAC,cAAc,EAAE,KAAK,CAAC,CAAA;AAChC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { useRef, useCallback } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that creates debounced, flush, and cancel functions for a callback.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const { debounce, flush, cancel } = useDebounceCallback((value) => {
|
|
7
|
+
* console.log(value)
|
|
8
|
+
* }, 500)
|
|
9
|
+
*
|
|
10
|
+
* debounce('hello') // Will call callback after 500ms
|
|
11
|
+
* flush('immediate') // Calls callback immediately
|
|
12
|
+
* cancel() // Cancels pending debounced call
|
|
13
|
+
*/
|
|
14
|
+
export function useDebounceCallback(callback, delay = 1000) {
|
|
15
|
+
const timeoutRef = useRef(null);
|
|
16
|
+
const debounce = useCallback((...args) => {
|
|
17
|
+
cancel();
|
|
18
|
+
timeoutRef.current = setTimeout(() => {
|
|
19
|
+
callback(...args);
|
|
20
|
+
timeoutRef.current = null;
|
|
21
|
+
}, delay);
|
|
22
|
+
}, [callback]);
|
|
23
|
+
const flush = useCallback((...args) => {
|
|
24
|
+
cancel();
|
|
25
|
+
callback(...args);
|
|
26
|
+
}, [callback]);
|
|
27
|
+
const cancel = useCallback(() => {
|
|
28
|
+
if (timeoutRef.current) {
|
|
29
|
+
clearTimeout(timeoutRef.current);
|
|
30
|
+
timeoutRef.current = null;
|
|
31
|
+
}
|
|
32
|
+
}, []);
|
|
33
|
+
return {
|
|
34
|
+
debounce,
|
|
35
|
+
flush,
|
|
36
|
+
cancel,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=useDebounceCallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDebounceCallback.js","sourceRoot":"","sources":["../src/useDebounceCallback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAE3C;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAA8B,EAC9B,KAAK,GAAG,IAAI;IAEZ,MAAM,UAAU,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAA;IAErE,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,GAAG,IAAO,EAAE,EAAE;QAC1C,MAAM,EAAE,CAAA;QAER,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YACnC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAA;YACjB,UAAU,CAAC,OAAO,GAAG,IAAI,CAAA;QAC3B,CAAC,EAAE,KAAK,CAAC,CAAA;IACX,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,GAAG,IAAO,EAAE,EAAE;QACvC,MAAM,EAAE,CAAA;QACR,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAA;IACnB,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAA;IAEd,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE;QAC9B,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;YAChC,UAAU,CAAC,OAAO,GAAG,IAAI,CAAA;QAC3B,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO;QACL,QAAQ;QACR,KAAK;QACL,MAAM;KACP,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that creates a ref that automatically updates when a derived value changes.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const userNameRef = useDerivedRef(user, (u) => u.name)
|
|
7
|
+
* // userNameRef.current will always contain the latest user name
|
|
8
|
+
*/
|
|
9
|
+
export const useDerivedRef = (derivedValue, getValue) => {
|
|
10
|
+
const ref = useRef(getValue(derivedValue));
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
ref.current = getValue(derivedValue);
|
|
13
|
+
}, [derivedValue]);
|
|
14
|
+
return ref;
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=useDerivedRef.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDerivedRef.js","sourceRoot":"","sources":["../src/useDerivedRef.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAEzC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,YAAe,EACf,QAAgC,EACL,EAAE;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAA;IAE1C,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,CAAC,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAA;IACtC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAA;IAElB,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { deepEqual } from '@codeleap/utils';
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Hook that creates a state that synchronizes with a derived value, with customizable equality check.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const [state, setState] = useDerivedState(props.value, {
|
|
8
|
+
* getValue: (v) => v.id,
|
|
9
|
+
* areEqual: (a, b) => a === b.id
|
|
10
|
+
* })
|
|
11
|
+
*/
|
|
12
|
+
export const useDerivedState = (derivedValue, options = {}) => {
|
|
13
|
+
const { getValue = (value) => value, transform = (value) => value, areEqual = (currentState, derivedValue) => deepEqual(currentState, derivedValue), } = options;
|
|
14
|
+
const [state, setState] = useState(() => getValue(derivedValue));
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const newValue = getValue(derivedValue);
|
|
17
|
+
const stateAreEqual = areEqual(transform(state), transform(derivedValue));
|
|
18
|
+
if (!stateAreEqual) {
|
|
19
|
+
setState(newValue);
|
|
20
|
+
}
|
|
21
|
+
}, [derivedValue]);
|
|
22
|
+
return [state, setState];
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=useDerivedState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDerivedState.js","sourceRoot":"","sources":["../src/useDerivedState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAQ3C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,YAAe,EACf,UAAyB,EAAE,EACmB,EAAE;IAChD,MAAM,EACJ,QAAQ,GAAG,CAAC,KAAU,EAAE,EAAE,CAAC,KAAU,EACrC,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAC5B,QAAQ,GAAG,CAAC,YAAY,EAAE,YAAY,EAAE,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,GACjF,GAAG,OAAO,CAAA;IAEX,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAA;IAEnE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAA;QAEvC,MAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC,CAAA;QAEzE,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,QAAQ,CAAC,QAAQ,CAAC,CAAA;QACpB,CAAC;IACH,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAA;IAElB,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;AAC1B,CAAC,CAAA"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that runs an effect only once when the component mounts.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* useEffectOnce(() => {
|
|
7
|
+
* console.log('Runs only once on mount')
|
|
8
|
+
* return () => console.log('Cleanup on unmount')
|
|
9
|
+
* })
|
|
10
|
+
*/
|
|
11
|
+
export const useEffectOnce = (effect) => {
|
|
12
|
+
useEffect(effect, []);
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=useEffectOnce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useEffectOnce.js","sourceRoot":"","sources":["../src/useEffectOnce.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,MAAsB,EAAE,EAAE;IACtD,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;AACvB,CAAC,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that filters out the first item from a list that matches a predicate.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const filteredUsers = useFilteredList(users, (user) => user.id === deletedId)
|
|
7
|
+
* // Returns users array without the first user matching the predicate
|
|
8
|
+
*/
|
|
9
|
+
export function useFilteredList(list, predicate) {
|
|
10
|
+
return useMemo(() => {
|
|
11
|
+
if (!list)
|
|
12
|
+
return [];
|
|
13
|
+
const index = list.findIndex(predicate);
|
|
14
|
+
if (index === -1)
|
|
15
|
+
return list;
|
|
16
|
+
const newList = [...list];
|
|
17
|
+
newList.splice(index, 1);
|
|
18
|
+
return newList;
|
|
19
|
+
}, [list, predicate]);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=useFilteredList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useFilteredList.js","sourceRoot":"","sources":["../src/useFilteredList.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAE/B;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAI,IAAS,EAAE,SAA+B;IAC3E,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAA;QAEpB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QACvC,IAAI,KAAK,KAAK,CAAC,CAAC;YAAE,OAAO,IAAI,CAAA;QAE7B,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;QACzB,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;QACxB,OAAO,OAAO,CAAA;IAChB,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAA;AACvB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useReducer } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that returns a function to force a component re-render.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const forceRender = useForceRender()
|
|
7
|
+
* forceRender() // Forces component to re-render
|
|
8
|
+
*/
|
|
9
|
+
export function useForceRender() {
|
|
10
|
+
const [_, forceRender] = useReducer((x) => x + 1, 0);
|
|
11
|
+
return forceRender;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=useForceRender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useForceRender.js","sourceRoot":"","sources":["../src/useForceRender.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAElC;;;;;;GAMG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IACpD,OAAO,WAAW,CAAA;AACpB,CAAC"}
|
package/dist/useId.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useRef, useId as _useId } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that returns a stable ID, using provided ID if available or generating one.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const id = useId('custom-id') // Returns 'custom-id'
|
|
7
|
+
* const id = useId() // Returns generated ID like ':r1:'
|
|
8
|
+
*/
|
|
9
|
+
export function useId(id) {
|
|
10
|
+
var _a;
|
|
11
|
+
const defaultId = _useId();
|
|
12
|
+
const idRef = useRef(id);
|
|
13
|
+
return (_a = idRef.current) !== null && _a !== void 0 ? _a : defaultId;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=useId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useId.js","sourceRoot":"","sources":["../src/useId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,MAAM,EAAE,MAAM,OAAO,CAAA;AAE/C;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAI,EAAM;;IAC7B,MAAM,SAAS,GAAG,MAAM,EAAE,CAAA;IAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,CAAA;IAExB,OAAO,MAAA,KAAK,CAAC,OAAO,mCAAI,SAAS,CAAA;AACnC,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useRef, useCallback, useEffect } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that manages an interval with start and clear controls.
|
|
4
|
+
* The handler receives a clear function to stop the interval from within.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const { start, clear } = useInterval((clearFn) => {
|
|
8
|
+
* console.log('Tick')
|
|
9
|
+
* if (shouldStop) clearFn()
|
|
10
|
+
* }, 1000)
|
|
11
|
+
*
|
|
12
|
+
* start() // Starts the interval
|
|
13
|
+
* clear() // Stops the interval
|
|
14
|
+
*/
|
|
15
|
+
export function useInterval(handler, interval) {
|
|
16
|
+
const intervalRef = useRef(null);
|
|
17
|
+
const handlerRef = useRef(handler);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
handlerRef.current = handler;
|
|
20
|
+
}, [handler]);
|
|
21
|
+
const clear = useCallback(() => {
|
|
22
|
+
if (intervalRef.current != null) {
|
|
23
|
+
clearInterval(intervalRef.current);
|
|
24
|
+
intervalRef.current = null;
|
|
25
|
+
}
|
|
26
|
+
}, []);
|
|
27
|
+
const start = useCallback(() => {
|
|
28
|
+
clear();
|
|
29
|
+
if (intervalRef.current == null) {
|
|
30
|
+
intervalRef.current = setInterval(() => {
|
|
31
|
+
handlerRef.current(clear);
|
|
32
|
+
}, interval);
|
|
33
|
+
}
|
|
34
|
+
}, []);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
return () => {
|
|
37
|
+
clear();
|
|
38
|
+
};
|
|
39
|
+
}, [clear]);
|
|
40
|
+
return {
|
|
41
|
+
clear,
|
|
42
|
+
start,
|
|
43
|
+
interval: intervalRef.current,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=useInterval.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useInterval.js","sourceRoot":"","sources":["../src/useInterval.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,OAA2B,EAAE,QAAgB;IACvE,MAAM,WAAW,GAAG,MAAM,CAAwC,IAAI,CAAC,CAAA;IACvE,MAAM,UAAU,GAAG,MAAM,CAAqB,OAAO,CAAC,CAAA;IAEtD,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,OAAO,GAAG,OAAO,CAAA;IAC9B,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAA;IAEb,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,IAAI,WAAW,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;YAChC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;YAClC,WAAW,CAAC,OAAO,GAAG,IAAI,CAAA;QAC5B,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,KAAK,EAAE,CAAA;QAEP,IAAI,WAAW,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC;YAChC,WAAW,CAAC,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;gBACrC,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;YAC3B,CAAC,EAAE,QAAQ,CAAC,CAAA;QACd,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,SAAS,CAAC,GAAG,EAAE;QACb,OAAO,GAAG,EAAE;YACV,KAAK,EAAE,CAAA;QACT,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAEX,OAAO;QACL,KAAK;QACL,KAAK;QACL,QAAQ,EAAE,WAAW,CAAC,OAAO;KAC9B,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useEffect, useLayoutEffect, useState } from 'react';
|
|
2
|
+
const isReactNativeOrServer = typeof navigator !== 'undefined';
|
|
3
|
+
const useIsomorphicLayoutEffect = isReactNativeOrServer ? useLayoutEffect : useEffect;
|
|
4
|
+
/**
|
|
5
|
+
* Hook to check if the component has mounted. SSR safe.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const isMounted = useIsMounted()
|
|
9
|
+
* if (isMounted) {
|
|
10
|
+
* // Safe to use browser APIs
|
|
11
|
+
* }
|
|
12
|
+
*/
|
|
13
|
+
export function useIsMounted() {
|
|
14
|
+
const [mounted, setMounted] = useState(false);
|
|
15
|
+
useIsomorphicLayoutEffect(() => {
|
|
16
|
+
setMounted(true);
|
|
17
|
+
}, []);
|
|
18
|
+
return mounted;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Hook to check if the code is running on the client-side.
|
|
22
|
+
* NOTE: This is just a mirror of `useIsMounted` for retrocompatibility reasons
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* const { isClient } = useIsClient()
|
|
26
|
+
* if (isClient) {
|
|
27
|
+
* // Safe to use browser APIs
|
|
28
|
+
* }
|
|
29
|
+
*/
|
|
30
|
+
export function useIsClient() {
|
|
31
|
+
return {
|
|
32
|
+
isClient: useIsMounted(),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=useIsMounted.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useIsMounted.js","sourceRoot":"","sources":["../src/useIsMounted.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAE5D,MAAM,qBAAqB,GAAG,OAAO,SAAS,KAAK,WAAW,CAAA;AAE9D,MAAM,yBAAyB,GAC7B,qBAAqB,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,CAAA;AAErD;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAE7C,yBAAyB,CAAC,GAAG,EAAE;QAC7B,UAAU,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,WAAW;IACzB,OAAO;QACL,QAAQ,EAAE,YAAY,EAAE;KACzB,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { globalState } from '@codeleap/store';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Hook that lazily creates a global store with an initial value.
|
|
5
|
+
* The store is created only once and persists across re-renders.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const counterStore = useLazyStore(0)
|
|
9
|
+
* // Store is created once and can be used across components
|
|
10
|
+
*/
|
|
11
|
+
export function useLazyStore(initialValue) {
|
|
12
|
+
const store = useMemo(() => {
|
|
13
|
+
return globalState(initialValue);
|
|
14
|
+
}, []);
|
|
15
|
+
return store;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=useLazyStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useLazyStore.js","sourceRoot":"","sources":["../src/useLazyStore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAE/B;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAI,YAAe;IAC7C,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE;QACzB,OAAO,WAAW,CAAC,YAAY,CAAC,CAAA;IAClC,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,OAAO,KAAK,CAAA;AACd,CAAC"}
|
package/dist/useModal.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { TypeGuards } from '@codeleap/types';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Hook that manages modal visibility state with open, close, and toggle functions.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const modal = useModal()
|
|
8
|
+
* modal.open() // Opens modal
|
|
9
|
+
* modal.close() // Closes modal
|
|
10
|
+
* modal.toggle() // Toggles visibility
|
|
11
|
+
* modal.toggle(true) // Forces open
|
|
12
|
+
*/
|
|
13
|
+
export function useModal(startsOpen = false) {
|
|
14
|
+
const [visible, setVisible] = useState(startsOpen);
|
|
15
|
+
function open() {
|
|
16
|
+
setVisible(true);
|
|
17
|
+
}
|
|
18
|
+
function close() {
|
|
19
|
+
setVisible(false);
|
|
20
|
+
}
|
|
21
|
+
function toggle(forceVisible) {
|
|
22
|
+
setVisible(prev => TypeGuards.isBoolean(forceVisible) ? forceVisible : !prev);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
visible,
|
|
26
|
+
toggle,
|
|
27
|
+
open,
|
|
28
|
+
close,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=useModal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useModal.js","sourceRoot":"","sources":["../src/useModal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CAAC,UAAU,GAAG,KAAK;IACzC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAA;IAElD,SAAS,IAAI;QACX,UAAU,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC;IAED,SAAS,KAAK;QACZ,UAAU,CAAC,KAAK,CAAC,CAAA;IACnB,CAAC;IAED,SAAS,MAAM,CAAC,YAAsB;QACpC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IAC/E,CAAC;IAED,OAAO;QACL,OAAO;QACP,MAAM;QACN,IAAI;QACJ,KAAK;KACN,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useMemo, useState } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that manages selected option state with boolean flags for each option.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const { selectedOption, setSelectedOption, isSelected } = useOptions(['light', 'dark'] as const)
|
|
7
|
+
* // isSelected = { light: true, dark: false }
|
|
8
|
+
* setSelectedOption('dark')
|
|
9
|
+
* // isSelected = { light: false, dark: true }
|
|
10
|
+
*/
|
|
11
|
+
export function useOptions(options, initialOptions = options[0]) {
|
|
12
|
+
const [selectedOption, setSelectedOption] = useState(initialOptions);
|
|
13
|
+
const isSelected = useMemo(() => {
|
|
14
|
+
return options.reduce((acc, option) => {
|
|
15
|
+
acc[option] = option === selectedOption;
|
|
16
|
+
return acc;
|
|
17
|
+
}, {});
|
|
18
|
+
}, [selectedOption, options]);
|
|
19
|
+
return {
|
|
20
|
+
selectedOption,
|
|
21
|
+
setSelectedOption,
|
|
22
|
+
isSelected,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=useOptions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOptions.js","sourceRoot":"","sources":["../src/useOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEzC;;;;;;;;GAQG;AACH,MAAM,UAAU,UAAU,CAAmB,OAAqB,EAAE,iBAAoB,OAAO,CAAC,CAAC,CAAC;IAChG,MAAM,CAAC,cAAc,EAAE,iBAAiB,CAAC,GAAG,QAAQ,CAAI,cAAc,CAAC,CAAA;IAEvE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE;QAC9B,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACpC,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,KAAK,cAAc,CAAA;YACvC,OAAO,GAAG,CAAA;QACZ,CAAC,EAAE,EAAwB,CAAC,CAAA;IAC9B,CAAC,EAAE,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAA;IAE7B,OAAO;QACL,cAAc;QACd,iBAAiB;QACjB,UAAU;KACX,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { deepMerge } from '@codeleap/utils';
|
|
3
|
+
/**
|
|
4
|
+
* Hook that manages state with partial updates using deep merge.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const [user, setUser] = usePartialState({ name: 'John', age: 30 })
|
|
8
|
+
* setUser({ age: 31 }) // Only updates age, keeps name
|
|
9
|
+
* setUser(prev => ({ age: prev.age + 1 })) // Functional update
|
|
10
|
+
*/
|
|
11
|
+
export function usePartialState(initial) {
|
|
12
|
+
const [state, setState] = useState(initial);
|
|
13
|
+
function setPartial(value) {
|
|
14
|
+
if (typeof value === 'function') {
|
|
15
|
+
setState((v) => deepMerge(v, value(v)));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
setState(deepMerge(state, value));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return [state, setPartial];
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=usePartialState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePartialState.js","sourceRoot":"","sources":["../src/usePartialState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAI3C;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAyB,OAAsB;IAC5E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE3C,SAAS,UAAU,CACjB,KAAkD;QAElD,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;YAChC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAM,CAAC,CAAC,CAAC,CAAA;QAC9C,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;QACnC,CAAC;IACH,CAAC;IAED,OAAO,CAAC,KAAU,EAAE,UAAU,CAAU,CAAA;AAC1C,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import axios from 'axios';
|
|
11
|
+
import { useQuery } from '@tanstack/react-query';
|
|
12
|
+
const BASE_URL = 'https://maps.googleapis.com/maps/api/place/autocomplete/json';
|
|
13
|
+
const BASE_URL_DETAILS = 'https://maps.googleapis.com/maps/api/place/details/json';
|
|
14
|
+
const BASE_URL_GEOCODING = 'https://maps.googleapis.com/maps/api/geocode/json';
|
|
15
|
+
const latLngRegex = /^-?\d+(\.\d+)?,-?\d+(\.\d+)?$/;
|
|
16
|
+
/**
|
|
17
|
+
* Retrieves detailed information for a specific Google Place.
|
|
18
|
+
*/
|
|
19
|
+
export const retrievePlaceDetails = (placeId, apiKey) => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
+
var _a;
|
|
21
|
+
const response = yield axios.get(BASE_URL_DETAILS, {
|
|
22
|
+
params: {
|
|
23
|
+
place_id: placeId,
|
|
24
|
+
key: apiKey,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
return (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.result;
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Retrieves places from Google Places API or Geocoding API.
|
|
31
|
+
* Supports both text search and lat/lng coordinates.
|
|
32
|
+
*/
|
|
33
|
+
export const retrievePlaces = (params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
var _a, _b, _c, _d, _e;
|
|
35
|
+
let response;
|
|
36
|
+
const inputWithoutSpaces = (_b = (_a = params === null || params === void 0 ? void 0 : params.input) === null || _a === void 0 ? void 0 : _a.replace(/\s/g, '')) !== null && _b !== void 0 ? _b : '';
|
|
37
|
+
const isLatLng = latLngRegex === null || latLngRegex === void 0 ? void 0 : latLngRegex.test(inputWithoutSpaces);
|
|
38
|
+
if (isLatLng) {
|
|
39
|
+
response = yield (axios === null || axios === void 0 ? void 0 : axios.get(BASE_URL_GEOCODING, { params: { latlng: params === null || params === void 0 ? void 0 : params.input, key: params === null || params === void 0 ? void 0 : params.key } }));
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
response = yield (axios === null || axios === void 0 ? void 0 : axios.get(BASE_URL, { params }));
|
|
43
|
+
}
|
|
44
|
+
let places = ((_c = response === null || response === void 0 ? void 0 : response.data) === null || _c === void 0 ? void 0 : _c.results) || ((_d = response === null || response === void 0 ? void 0 : response.data) === null || _d === void 0 ? void 0 : _d.predictions);
|
|
45
|
+
if (params === null || params === void 0 ? void 0 : params.showDetails) {
|
|
46
|
+
const apiKey = (_e = params === null || params === void 0 ? void 0 : params.key) !== null && _e !== void 0 ? _e : '';
|
|
47
|
+
places = yield Promise.all(places === null || places === void 0 ? void 0 : places.map((place) => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
const placeId = place === null || place === void 0 ? void 0 : place.place_id;
|
|
49
|
+
const details = yield retrievePlaceDetails(placeId, apiKey);
|
|
50
|
+
return Object.assign(Object.assign({}, place), { details });
|
|
51
|
+
})));
|
|
52
|
+
}
|
|
53
|
+
return places;
|
|
54
|
+
});
|
|
55
|
+
/**
|
|
56
|
+
* Hook that fetches Google Places using React Query.
|
|
57
|
+
* Automatically handles caching and refetching.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const places = usePlaces({
|
|
61
|
+
* input: 'New York',
|
|
62
|
+
* key: 'YOUR_API_KEY',
|
|
63
|
+
* showDetails: true
|
|
64
|
+
* })
|
|
65
|
+
*/
|
|
66
|
+
export const usePlaces = (params) => {
|
|
67
|
+
const places = useQuery({
|
|
68
|
+
queryKey: ['places', params],
|
|
69
|
+
queryFn: () => retrievePlaces(params),
|
|
70
|
+
});
|
|
71
|
+
return places;
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=usePlaces.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePlaces.js","sourceRoot":"","sources":["../src/usePlaces.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAA;AAEhD,MAAM,QAAQ,GAAG,8DAA8D,CAAA;AAC/E,MAAM,gBAAgB,GAAG,yDAAyD,CAAA;AAClF,MAAM,kBAAkB,GAAG,mDAAmD,CAAA;AAE9E,MAAM,WAAW,GAAG,+BAA+B,CAAA;AAQnD;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAO,OAAe,EAAE,MAAc,EAAE,EAAE;;IAC5E,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,gBAAgB,EAAE;QACjD,MAAM,EAAE;YACN,QAAQ,EAAE,OAAO;YACjB,GAAG,EAAE,MAAM;SACZ;KACF,CAAC,CAAA;IAEF,OAAO,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,0CAAE,MAAM,CAAA;AAC/B,CAAC,CAAA,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAO,MAAc,EAAE,EAAE;;IACrD,IAAI,QAAQ,CAAA;IACZ,MAAM,kBAAkB,GAAG,MAAA,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,0CAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,mCAAI,EAAE,CAAA;IAClE,MAAM,QAAQ,GAAG,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,IAAI,CAAC,kBAAkB,CAAC,CAAA;IAEtD,IAAI,QAAQ,EAAE,CAAC;QACb,QAAQ,GAAG,MAAM,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,GAAG,CAAC,kBAAkB,EAAE,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,KAAK,EAAE,GAAG,EAAE,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,GAAG,EAAE,EAAE,CAAC,CAAA,CAAA;IAC1G,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,MAAM,CAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA,CAAA;IACnD,CAAC;IAED,IAAI,MAAM,GAAG,CAAA,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,0CAAE,OAAO,MAAI,MAAA,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,IAAI,0CAAE,WAAW,CAAA,CAAA;IAEnE,IAAI,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,WAAW,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,MAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,GAAG,mCAAI,EAAE,CAAA;QAChC,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CACxB,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,GAAG,CAAC,CAAO,KAAU,EAAE,EAAE;YAC/B,MAAM,OAAO,GAAG,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,QAAQ,CAAA;YAC/B,MAAM,OAAO,GAAG,MAAM,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;YAC3D,uCAAY,KAAK,KAAE,OAAO,IAAE;QAC9B,CAAC,CAAA,CAAC,CACH,CAAA;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA,CAAA;AAID;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,MAAc,EAAE,EAAE;IAC1C,MAAM,MAAM,GAAG,QAAQ,CAAC;QACtB,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC5B,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC;KACtC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { TypeGuards } from '@codeleap/types';
|
|
3
|
+
/**
|
|
4
|
+
* Hook that manages address autocomplete state with debounced input handling.
|
|
5
|
+
* Useful for Google Places autocomplete implementations.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const {
|
|
9
|
+
* address,
|
|
10
|
+
* handleChangeAddress,
|
|
11
|
+
* handlePressAddress,
|
|
12
|
+
* isTyping
|
|
13
|
+
* } = usePlacesAutocompleteUtils({
|
|
14
|
+
* debounce: 500,
|
|
15
|
+
* onValueChange: (addr) => fetchPlaces(addr),
|
|
16
|
+
* onPress: (addr, item) => console.log('Selected:', item)
|
|
17
|
+
* })
|
|
18
|
+
*/
|
|
19
|
+
export const usePlacesAutocompleteUtils = (props) => {
|
|
20
|
+
const { debounce = 250, onValueChange, onPress, } = props;
|
|
21
|
+
const [address, setAddress] = React.useState('');
|
|
22
|
+
const [isTyping, setIsTyping] = React.useState(false);
|
|
23
|
+
const setSearchTimeout = React.useRef(null);
|
|
24
|
+
const handleChangeAddress = (address) => {
|
|
25
|
+
setAddress(address);
|
|
26
|
+
if (TypeGuards.isNil(debounce)) {
|
|
27
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(address);
|
|
28
|
+
setTimeout(() => setIsTyping(false), 250);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
if (setSearchTimeout.current) {
|
|
32
|
+
clearTimeout(setSearchTimeout.current);
|
|
33
|
+
setSearchTimeout.current = null;
|
|
34
|
+
}
|
|
35
|
+
setSearchTimeout.current = setTimeout(() => {
|
|
36
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(address);
|
|
37
|
+
setIsTyping(false);
|
|
38
|
+
}, debounce !== null && debounce !== void 0 ? debounce : 0);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const handlePressAddress = (address, item) => {
|
|
42
|
+
setAddress(address);
|
|
43
|
+
onPress === null || onPress === void 0 ? void 0 : onPress(address, item);
|
|
44
|
+
};
|
|
45
|
+
const handleClearAddress = () => {
|
|
46
|
+
setAddress('');
|
|
47
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange('');
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
handleChangeAddress,
|
|
51
|
+
handlePressAddress,
|
|
52
|
+
handleClearAddress,
|
|
53
|
+
address,
|
|
54
|
+
isTyping,
|
|
55
|
+
setIsTyping,
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=usePlacesAutocompleteUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePlacesAutocompleteUtils.js","sourceRoot":"","sources":["../src/usePlacesAutocompleteUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAQ5C;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAgC,KAAyC,EAAE,EAAE;IACrH,MAAM,EACJ,QAAQ,GAAG,GAAG,EACd,aAAa,EACb,OAAO,GACR,GAAG,KAAK,CAAA;IAET,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;IAChD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAErD,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAAuC,IAAI,CAAC,CAAA;IAEjF,MAAM,mBAAmB,GAAG,CAAC,OAAe,EAAE,EAAE;QAC9C,UAAU,CAAC,OAAO,CAAC,CAAA;QAEnB,IAAI,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/B,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAG,OAAO,CAAC,CAAA;YACxB,UAAU,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAA;QAC3C,CAAC;aAAM,CAAC;YACN,IAAI,gBAAgB,CAAC,OAAO,EAAE,CAAC;gBAC7B,YAAY,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAA;gBACtC,gBAAgB,CAAC,OAAO,GAAG,IAAI,CAAA;YACjC,CAAC;YAED,gBAAgB,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;gBACzC,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAG,OAAO,CAAC,CAAA;gBACxB,WAAW,CAAC,KAAK,CAAC,CAAA;YACpB,CAAC,EAAE,QAAQ,aAAR,QAAQ,cAAR,QAAQ,GAAI,CAAC,CAAC,CAAA;QACnB,CAAC;IACH,CAAC,CAAA;IAED,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAAE,IAAO,EAAE,EAAE;QACtD,UAAU,CAAC,OAAO,CAAC,CAAA;QACnB,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAG,OAAO,EAAE,IAAI,CAAC,CAAA;IAC1B,CAAC,CAAA;IAED,MAAM,kBAAkB,GAAG,GAAG,EAAE;QAC9B,UAAU,CAAC,EAAE,CAAC,CAAA;QACd,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAG,EAAE,CAAC,CAAA;IACrB,CAAC,CAAA;IAED,OAAO;QACL,mBAAmB;QACnB,kBAAkB;QAClB,kBAAkB;QAClB,OAAO;QACP,QAAQ;QACR,WAAW;KACZ,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that returns the previous value of a variable.
|
|
4
|
+
* The value is updated after render is committed to the DOM.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* const [count, setCount] = useState(0)
|
|
8
|
+
* const prevCount = usePrevious(count)
|
|
9
|
+
* // On first render: count=0, prevCount=null
|
|
10
|
+
* // After setCount(1): count=1, prevCount=0
|
|
11
|
+
*/
|
|
12
|
+
export const usePrevious = (value) => {
|
|
13
|
+
const ref = useRef(null);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
ref.current = value;
|
|
16
|
+
});
|
|
17
|
+
return ref.current;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=usePrevious.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePrevious.js","sourceRoot":"","sources":["../src/usePrevious.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAEzC;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAI,KAAQ,EAAE,EAAE;IACzC,MAAM,GAAG,GAAG,MAAM,CAAI,IAAI,CAAC,CAAA;IAC3B,SAAS,CAAC,GAAG,EAAE;QACb,GAAG,CAAC,OAAO,GAAG,KAAK,CAAA;IACrB,CAAC,CAAC,CAAA;IACF,OAAO,GAAG,CAAC,OAAO,CAAA;AACpB,CAAC,CAAA"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { useRef } from 'react';
|
|
11
|
+
import { TypeGuards } from '@codeleap/types';
|
|
12
|
+
/**
|
|
13
|
+
* Hook that creates a deferred promise with manual resolve/reject control.
|
|
14
|
+
* Useful for coordinating asynchronous operations across component lifecycle.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const promise = usePromise({ timeout: 5000 })
|
|
18
|
+
* const handleClick = async () => {
|
|
19
|
+
* const result = await promise._await()
|
|
20
|
+
* console.log(result)
|
|
21
|
+
* }
|
|
22
|
+
* // Later, from another callback:
|
|
23
|
+
* promise.resolve('success')
|
|
24
|
+
*/
|
|
25
|
+
export const usePromise = (options) => {
|
|
26
|
+
const rejectRef = useRef(null);
|
|
27
|
+
const resolveRef = useRef(null);
|
|
28
|
+
const timeoutRef = useRef(null);
|
|
29
|
+
const reject = (err) => __awaiter(void 0, void 0, void 0, function* () {
|
|
30
|
+
var _a, _b;
|
|
31
|
+
yield ((_a = rejectRef.current) === null || _a === void 0 ? void 0 : _a.call(rejectRef, err));
|
|
32
|
+
(_b = options === null || options === void 0 ? void 0 : options.onReject) === null || _b === void 0 ? void 0 : _b.call(options, err);
|
|
33
|
+
if (timeoutRef.current)
|
|
34
|
+
clearTimeout(timeoutRef.current);
|
|
35
|
+
rejectRef.current = null;
|
|
36
|
+
});
|
|
37
|
+
const resolve = (value) => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
|
+
var _a, _b;
|
|
39
|
+
yield ((_a = resolveRef.current) === null || _a === void 0 ? void 0 : _a.call(resolveRef, value));
|
|
40
|
+
(_b = options === null || options === void 0 ? void 0 : options.onResolve) === null || _b === void 0 ? void 0 : _b.call(options, value);
|
|
41
|
+
if (timeoutRef.current)
|
|
42
|
+
clearTimeout(timeoutRef.current);
|
|
43
|
+
resolveRef.current = null;
|
|
44
|
+
});
|
|
45
|
+
const _await = () => {
|
|
46
|
+
return new Promise((resolve, reject) => {
|
|
47
|
+
rejectRef.current = reject;
|
|
48
|
+
resolveRef.current = resolve;
|
|
49
|
+
if (TypeGuards.isNumber(options === null || options === void 0 ? void 0 : options.timeout) && (options === null || options === void 0 ? void 0 : options.timeout) > 0) {
|
|
50
|
+
timeoutRef.current = setTimeout(() => {
|
|
51
|
+
reject(new Error(`usePromise: ${(options === null || options === void 0 ? void 0 : options.debugName) || ''} timed out after ${options === null || options === void 0 ? void 0 : options.timeout}ms`));
|
|
52
|
+
}, options === null || options === void 0 ? void 0 : options.timeout);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
return {
|
|
57
|
+
_await,
|
|
58
|
+
resolve,
|
|
59
|
+
reject,
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
//# sourceMappingURL=usePromise.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePromise.js","sourceRoot":"","sources":["../src/usePromise.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,UAAU,EAAe,MAAM,iBAAiB,CAAA;AASzD;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAU,OAA8B,EAAE,EAAE;IACpE,MAAM,SAAS,GAAG,MAAM,CAAc,IAAI,CAAC,CAAA;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAe,IAAI,CAAC,CAAA;IAC7C,MAAM,UAAU,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAA;IAErE,MAAM,MAAM,GAAG,CAAO,GAAQ,EAAE,EAAE;;QAChC,MAAM,CAAA,MAAA,SAAS,CAAC,OAAO,0DAAG,GAAG,CAAC,CAAA,CAAA;QAC9B,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,QAAQ,wDAAG,GAAG,CAAC,CAAA;QACxB,IAAI,UAAU,CAAC,OAAO;YAAE,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QACxD,SAAS,CAAC,OAAO,GAAG,IAAI,CAAA;IAC1B,CAAC,CAAA,CAAA;IAED,MAAM,OAAO,GAAG,CAAO,KAAQ,EAAE,EAAE;;QACjC,MAAM,CAAA,MAAA,UAAU,CAAC,OAAO,2DAAG,KAAK,CAAC,CAAA,CAAA;QACjC,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,SAAS,wDAAG,KAAK,CAAC,CAAA;QAC3B,IAAI,UAAU,CAAC,OAAO;YAAE,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,CAAA;QACxD,UAAU,CAAC,OAAO,GAAG,IAAI,CAAA;IAC3B,CAAC,CAAA,CAAA;IAED,MAAM,MAAM,GAAG,GAAG,EAAE;QAClB,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,SAAS,CAAC,OAAO,GAAG,MAAM,CAAA;YAC1B,UAAU,CAAC,OAAO,GAAG,OAAO,CAAA;YAC5B,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,CAAC,IAAI,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,IAAG,CAAC,EAAE,CAAC;gBAClE,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;oBACnC,MAAM,CAAC,IAAI,KAAK,CAAC,eAAe,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,SAAS,KAAI,EAAE,oBAAoB,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,IAAI,CAAC,CAAC,CAAA;gBACpG,CAAC,EAAE,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,CAAC,CAAA;YACtB,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAA;IAED,OAAO;QACL,MAAM;QACN,OAAO;QACP,MAAM;KACP,CAAA;AACH,CAAC,CAAA"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
/** Calls `fn` synchronously during render, capped at `maxRunCount` renders (default 1). Does not use effects — execution happens inline during the render phase. */
|
|
3
|
+
export function useRenderCall(fn, maxRunCount = 1) {
|
|
4
|
+
const callCount = useRef(0);
|
|
5
|
+
if (callCount.current < maxRunCount) {
|
|
6
|
+
callCount.current++;
|
|
7
|
+
fn();
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=useRenderCall.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRenderCall.js","sourceRoot":"","sources":["../src/useRenderCall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAE9B,oKAAoK;AACpK,MAAM,UAAU,aAAa,CAAC,EAAc,EAAE,WAAW,GAAG,CAAC;IAC3D,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;IAC3B,IAAI,SAAS,CAAC,OAAO,GAAG,WAAW,EAAE,CAAC;QACpC,SAAS,CAAC,OAAO,EAAE,CAAA;QACnB,EAAE,EAAE,CAAA;IACN,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { useState } from 'react';
|
|
11
|
+
import { useBooleanToggle } from '../useBooleanToggle';
|
|
12
|
+
import { TypeGuards } from '@codeleap/types';
|
|
13
|
+
/**
|
|
14
|
+
* Hook that manages searchable select/autocomplete state with async loading support.
|
|
15
|
+
* Handles both local filtering and remote data fetching.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* const search = useSearch({
|
|
19
|
+
* value: 'selected-value',
|
|
20
|
+
* multiple: false,
|
|
21
|
+
* defaultOptions: [...],
|
|
22
|
+
* loadOptions: async (query) => fetchOptions(query),
|
|
23
|
+
* filterItems: (query, opts) => opts.filter(o => o.label.includes(query))
|
|
24
|
+
* })
|
|
25
|
+
*
|
|
26
|
+
* search.onChangeSearch('query')
|
|
27
|
+
* search.load()
|
|
28
|
+
*/
|
|
29
|
+
export function useSearch(props) {
|
|
30
|
+
const { value, multiple, options, filterItems, debugName, defaultOptions, loadOptions, onLoadOptionsError, } = Object.assign({}, props);
|
|
31
|
+
const [loading, setLoading] = useBooleanToggle(false);
|
|
32
|
+
const isValueArray = TypeGuards.isArray(value) && multiple;
|
|
33
|
+
const [labelOptions, setLabelOptions] = useState(() => {
|
|
34
|
+
if (isValueArray) {
|
|
35
|
+
return defaultOptions.filter(o => value.includes(o.value));
|
|
36
|
+
}
|
|
37
|
+
const _option = defaultOptions.find(o => o.value === value);
|
|
38
|
+
if (!_option) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
return [_option];
|
|
42
|
+
});
|
|
43
|
+
const [filteredOptions, setFilteredOptions] = useState(defaultOptions);
|
|
44
|
+
const [, setSearchInput] = useState('');
|
|
45
|
+
function load() {
|
|
46
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
+
setLoading(true);
|
|
48
|
+
try {
|
|
49
|
+
const options = yield loadOptions('');
|
|
50
|
+
setFilteredOptions(options);
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
onLoadOptionsError(e);
|
|
54
|
+
}
|
|
55
|
+
setLoading(false);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const onChangeSearch = (searchValue) => __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
setSearchInput(searchValue);
|
|
60
|
+
if (!!loadOptions) {
|
|
61
|
+
setLoading(true);
|
|
62
|
+
try {
|
|
63
|
+
const _opts = yield loadOptions(searchValue);
|
|
64
|
+
setFilteredOptions(_opts);
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
console.error(`Error loading select options [${debugName}], e`);
|
|
68
|
+
onLoadOptionsError === null || onLoadOptionsError === void 0 ? void 0 : onLoadOptionsError(e);
|
|
69
|
+
}
|
|
70
|
+
setTimeout(() => {
|
|
71
|
+
setLoading(false);
|
|
72
|
+
}, 0);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const _opts = filterItems(searchValue, options);
|
|
76
|
+
setFilteredOptions(_opts);
|
|
77
|
+
});
|
|
78
|
+
return { loading, setLoading, labelOptions, setLabelOptions, filteredOptions, load, onChangeSearch };
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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,qBAAQ,KAAK,CAAE,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,SAAe,IAAI;;YACjB,UAAU,CAAC,IAAI,CAAC,CAAA;YAChB,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,EAAE,CAAC,CAAA;gBACrC,kBAAkB,CAAC,OAAO,CAAC,CAAA;YAC7B,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,kBAAkB,CAAC,CAAC,CAAC,CAAA;YACvB,CAAC;YACD,UAAU,CAAC,KAAK,CAAC,CAAA;QACnB,CAAC;KAAA;IAED,MAAM,cAAc,GAAG,CAAO,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,aAAlB,kBAAkB,uBAAlB,kBAAkB,CAAG,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,CAAA;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,IAAI,EAAE,cAAc,EAAE,CAAA;AACtG,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/useSearch/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { deepEqual } from '@codeleap/utils';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
/** Returns the previous ref value when the object is deeply equal to the last render, preventing unnecessary re-renders caused by referential inequality. */
|
|
4
|
+
export function useStableReference(value) {
|
|
5
|
+
const ref = useRef(value);
|
|
6
|
+
const hasChanged = !deepEqual(ref.current, value);
|
|
7
|
+
if (hasChanged) {
|
|
8
|
+
ref.current = value;
|
|
9
|
+
}
|
|
10
|
+
return ref.current;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=useStableReference.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that toggles between two values.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const [theme, toggleTheme] = useToggle(['light', 'dark'] as const, 'light')
|
|
7
|
+
* toggleTheme() // Switches to 'dark'
|
|
8
|
+
* toggleTheme('light') // Sets to 'light'
|
|
9
|
+
*/
|
|
10
|
+
export function useToggle(options, initial) {
|
|
11
|
+
const [value, setValue] = useState(initial);
|
|
12
|
+
function toggleOrSetValue(newValue) {
|
|
13
|
+
const v = newValue || (value === options[0] ? options[1] : options[0]);
|
|
14
|
+
setValue(v);
|
|
15
|
+
}
|
|
16
|
+
return [value, toggleOrSetValue];
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=useToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Hook that manages controlled/uncontrolled component pattern with smooth transitions.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const [value, handleChange, mode] = useUncontrolled({
|
|
7
|
+
* value: props.value,
|
|
8
|
+
* defaultValue: 'default',
|
|
9
|
+
* finalValue: '',
|
|
10
|
+
* rule: (v) => v !== undefined,
|
|
11
|
+
* onChange: (v) => props.onChange?.(v)
|
|
12
|
+
* })
|
|
13
|
+
*/
|
|
14
|
+
export function useUncontrolled({ value, defaultValue, finalValue, rule, onChange, onValueUpdate, }) {
|
|
15
|
+
var _a;
|
|
16
|
+
// determine, whether new props indicate controlled state
|
|
17
|
+
const shouldBeControlled = rule(value);
|
|
18
|
+
// initialize state
|
|
19
|
+
const modeRef = useRef('initial');
|
|
20
|
+
const initialValue = rule(defaultValue) ? defaultValue : finalValue;
|
|
21
|
+
const [uncontrolledValue, setUncontrolledValue] = useState(initialValue);
|
|
22
|
+
// compute effective value
|
|
23
|
+
let effectiveValue = (_a = (shouldBeControlled ? value : uncontrolledValue)) !== null && _a !== void 0 ? _a : null;
|
|
24
|
+
if (!shouldBeControlled && modeRef.current === 'controlled') {
|
|
25
|
+
// We are transitioning from controlled to uncontrolled
|
|
26
|
+
// this transition is special as it happens when clearing out
|
|
27
|
+
// the input using "invalid" value (typically null or undefined).
|
|
28
|
+
//
|
|
29
|
+
// Since the value is invalid, doing nothing would mean just
|
|
30
|
+
// transitioning to uncontrolled state and using whatever value
|
|
31
|
+
// it currently holds which is likely not the behavior
|
|
32
|
+
// user expects, so lets change the state to finalValue.
|
|
33
|
+
//
|
|
34
|
+
// The value will be propagated to internal state by useEffect below.
|
|
35
|
+
effectiveValue = finalValue;
|
|
36
|
+
}
|
|
37
|
+
modeRef.current = shouldBeControlled ? 'controlled' : 'uncontrolled';
|
|
38
|
+
const mode = modeRef.current;
|
|
39
|
+
const handleChange = (nextValue) => {
|
|
40
|
+
typeof onChange === 'function' && onChange(nextValue);
|
|
41
|
+
// Controlled input only triggers onChange event and expects
|
|
42
|
+
// the controller to propagate new value back.
|
|
43
|
+
if (mode === 'uncontrolled') {
|
|
44
|
+
setUncontrolledValue(nextValue);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (mode === 'uncontrolled') {
|
|
49
|
+
setUncontrolledValue(effectiveValue);
|
|
50
|
+
}
|
|
51
|
+
typeof onValueUpdate === 'function' && onValueUpdate(effectiveValue);
|
|
52
|
+
}, [mode, effectiveValue]);
|
|
53
|
+
return [effectiveValue, handleChange, modeRef.current];
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=useUncontrolled.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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,MAAA,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,mCAAI,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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import { useEffectOnce } from './useEffectOnce';
|
|
3
|
+
/**
|
|
4
|
+
* Hook that runs a cleanup function when the component unmounts.
|
|
5
|
+
* The function reference is updated on each render to always use the latest version.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* useUnmount(() => {
|
|
9
|
+
* console.log('Component unmounting')
|
|
10
|
+
* // Cleanup logic here
|
|
11
|
+
* })
|
|
12
|
+
*/
|
|
13
|
+
export const useUnmount = (fn) => {
|
|
14
|
+
const fnRef = useRef(fn);
|
|
15
|
+
// update the ref each render so if it change the newest callback will be invoked
|
|
16
|
+
fnRef.current = fn;
|
|
17
|
+
useEffectOnce(() => () => fnRef.current());
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=useUnmount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codeleap/hooks",
|
|
3
|
-
"version": "7.0.
|
|
4
|
-
"main": "
|
|
3
|
+
"version": "7.0.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": {
|
|
@@ -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.1",
|
|
26
|
+
"@codeleap/types": "7.0.1",
|
|
27
|
+
"@codeleap/utils": "7.0.1",
|
|
28
|
+
"@codeleap/logger": "7.0.1",
|
|
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.1",
|
|
37
|
+
"@codeleap/utils": "7.0.1",
|
|
38
|
+
"@codeleap/logger": "7.0.1",
|
|
39
39
|
"axios": "^1.7.9",
|
|
40
40
|
"typescript": "6.0.3",
|
|
41
41
|
"react": "19.1.0",
|