@zayne-labs/toolkit-react 0.11.19 → 0.11.21
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/esm/hooks/createCustomContext.d.ts +21 -0
- package/dist/esm/hooks/createCustomContext.js +25 -0
- package/dist/esm/hooks/createCustomContext.js.map +1 -0
- package/dist/esm/hooks/effects/useAfterMountEffect.d.ts +7 -0
- package/dist/esm/hooks/effects/useAfterMountEffect.js +19 -0
- package/dist/esm/hooks/effects/useAfterMountEffect.js.map +1 -0
- package/dist/esm/hooks/effects/useAsyncEffect.d.ts +5 -0
- package/dist/esm/hooks/effects/useAsyncEffect.js +20 -0
- package/dist/esm/hooks/effects/useAsyncEffect.js.map +1 -0
- package/dist/esm/hooks/effects/useEffectOnce.d.ts +5 -0
- package/dist/esm/hooks/effects/useEffectOnce.js +17 -0
- package/dist/esm/hooks/effects/useEffectOnce.js.map +1 -0
- package/dist/esm/hooks/effects/useLifeCycle.d.ts +13 -0
- package/dist/esm/hooks/effects/useLifeCycle.js +16 -0
- package/dist/esm/hooks/effects/useLifeCycle.js.map +1 -0
- package/dist/esm/hooks/effects/useMountEffect.d.ts +5 -0
- package/dist/esm/hooks/effects/useMountEffect.js +10 -0
- package/dist/esm/hooks/effects/useMountEffect.js.map +1 -0
- package/dist/esm/hooks/effects/useUnMountEffect.d.ts +7 -0
- package/dist/esm/hooks/effects/useUnMountEffect.js +8 -0
- package/dist/esm/hooks/effects/useUnMountEffect.js.map +1 -0
- package/dist/esm/hooks/index.d.ts +27 -2
- package/dist/esm/hooks/index.js +27 -2
- package/dist/esm/hooks/useAnimateElementRefs.d.ts +19 -0
- package/dist/esm/hooks/useAnimateElementRefs.js +54 -0
- package/dist/esm/hooks/useAnimateElementRefs.js.map +1 -0
- package/dist/esm/hooks/useAnimationInterval.d.ts +15 -0
- package/dist/esm/hooks/useAnimationInterval.js +27 -0
- package/dist/esm/hooks/useAnimationInterval.js.map +1 -0
- package/dist/esm/hooks/useCallbackRef.d.ts +13 -0
- package/dist/esm/hooks/useCallbackRef.js +19 -0
- package/dist/esm/hooks/useCallbackRef.js.map +1 -0
- package/dist/esm/hooks/useClickOutside.d.ts +14 -0
- package/dist/esm/hooks/useClickOutside.js +25 -0
- package/dist/esm/hooks/useClickOutside.js.map +1 -0
- package/dist/esm/hooks/useComposeRefs.d.ts +8 -0
- package/dist/esm/hooks/useComposeRefs.js +11 -0
- package/dist/esm/hooks/useComposeRefs.js.map +1 -0
- package/dist/esm/hooks/useConstant.d.ts +6 -0
- package/dist/esm/hooks/useConstant.js +17 -0
- package/dist/esm/hooks/useConstant.js.map +1 -0
- package/dist/esm/hooks/useControllable.d.ts +55 -0
- package/dist/esm/hooks/useControllable.js +79 -0
- package/dist/esm/hooks/useControllable.js.map +1 -0
- package/dist/esm/hooks/useCopyToClipboard.d.ts +15 -0
- package/dist/esm/hooks/useCopyToClipboard.js +49 -0
- package/dist/esm/hooks/useCopyToClipboard.js.map +1 -0
- package/dist/esm/hooks/useDebounce.d.ts +23 -0
- package/dist/esm/hooks/useDebounce.js +32 -0
- package/dist/esm/hooks/useDebounce.js.map +1 -0
- package/dist/esm/hooks/useDisclosure.d.ts +14 -0
- package/dist/esm/hooks/useDisclosure.js +42 -0
- package/dist/esm/hooks/useDisclosure.js.map +1 -0
- package/dist/esm/hooks/useIsHydrated.d.ts +28 -0
- package/dist/esm/hooks/useIsHydrated.js +39 -0
- package/dist/esm/hooks/useIsHydrated.js.map +1 -0
- package/dist/esm/hooks/useLocationState.d.ts +17 -0
- package/dist/esm/hooks/useLocationState.js +24 -0
- package/dist/esm/hooks/useLocationState.js.map +1 -0
- package/dist/esm/hooks/useScrollObserver.d.ts +11 -0
- package/dist/esm/hooks/useScrollObserver.js +44 -0
- package/dist/esm/hooks/useScrollObserver.js.map +1 -0
- package/dist/esm/hooks/useSearch.d.ts +12 -0
- package/dist/esm/hooks/useSearch.js +40 -0
- package/dist/esm/hooks/useSearch.js.map +1 -0
- package/dist/esm/hooks/useSearchParams.d.ts +12 -0
- package/dist/esm/hooks/useSearchParams.js +36 -0
- package/dist/esm/hooks/useSearchParams.js.map +1 -0
- package/dist/esm/hooks/useShallowCompare.d.ts +8 -0
- package/dist/esm/hooks/useShallowCompare.js +26 -0
- package/dist/esm/hooks/useShallowCompare.js.map +1 -0
- package/dist/esm/hooks/useStorageState.d.ts +20 -0
- package/dist/esm/hooks/useStorageState.js +54 -0
- package/dist/esm/hooks/useStorageState.js.map +1 -0
- package/dist/esm/hooks/useStore.d.ts +8 -0
- package/dist/esm/hooks/useStore.js +13 -0
- package/dist/esm/hooks/useStore.js.map +1 -0
- package/dist/esm/hooks/useThrottle.d.ts +15 -0
- package/dist/esm/hooks/useThrottle.js +27 -0
- package/dist/esm/hooks/useThrottle.js.map +1 -0
- package/dist/esm/hooks/useToggle.d.ts +6 -0
- package/dist/esm/hooks/useToggle.js +18 -0
- package/dist/esm/hooks/useToggle.js.map +1 -0
- package/dist/esm/utils/composeEventHandlers.d.ts +8 -0
- package/dist/esm/utils/composeEventHandlers.js +36 -0
- package/dist/esm/utils/composeEventHandlers.js.map +1 -0
- package/dist/esm/utils/composeRefs.d.ts +17 -0
- package/dist/esm/utils/composeRefs.js +28 -0
- package/dist/esm/utils/composeRefs.js.map +1 -0
- package/dist/esm/utils/getSlot/getSlot.d.ts +60 -0
- package/dist/esm/utils/getSlot/getSlot.js +78 -0
- package/dist/esm/utils/getSlot/getSlot.js.map +1 -0
- package/dist/esm/utils/getSlotMap/getSlotMap.d.ts +86 -0
- package/dist/esm/utils/getSlotMap/getSlotMap.js +87 -0
- package/dist/esm/utils/getSlotMap/getSlotMap.js.map +1 -0
- package/dist/esm/utils/index.d.ts +8 -1
- package/dist/esm/utils/index.js +6 -1
- package/dist/esm/utils/mergeProps.d.ts +20 -0
- package/dist/esm/utils/mergeProps.js +31 -0
- package/dist/esm/utils/mergeProps.js.map +1 -0
- package/dist/esm/utils/mergeTwoProps.d.ts +5 -0
- package/dist/esm/utils/mergeTwoProps.js +42 -0
- package/dist/esm/utils/mergeTwoProps.js.map +1 -0
- package/dist/esm/utils/types/common.d.ts +43 -0
- package/dist/esm/utils/types/polymorphism.d.ts +13 -0
- package/dist/esm/zustand/createReactZustandStore.js +8 -0
- package/dist/esm/zustand/createReactZustandStore.js.map +1 -0
- package/dist/esm/zustand/createZustandContext.d.ts +13 -0
- package/dist/esm/zustand/createZustandContext.js +21 -0
- package/dist/esm/zustand/createZustandContext.js.map +1 -0
- package/dist/esm/zustand/createZustandStoreWithCombine.d.ts +12 -0
- package/dist/esm/zustand/createZustandStoreWithCombine.js +14 -0
- package/dist/esm/zustand/createZustandStoreWithCombine.js.map +1 -0
- package/dist/esm/zustand/createZustandStoreWithSubscribe.d.ts +17 -0
- package/dist/esm/zustand/createZustandStoreWithSubscribe.js +16 -0
- package/dist/esm/zustand/createZustandStoreWithSubscribe.js.map +1 -0
- package/dist/esm/zustand/index.d.ts +4 -38
- package/dist/esm/zustand/index.js +4 -42
- package/dist/esm/zustand/types.d.ts +20 -0
- package/package.json +11 -16
- package/dist/esm/hooks-iZivekUZ.js +0 -635
- package/dist/esm/hooks-iZivekUZ.js.map +0 -1
- package/dist/esm/index-DlScRgBk.d.ts +0 -228
- package/dist/esm/index-ouFKofvj.d.ts +0 -293
- package/dist/esm/utils-Bvs8tFDM.js +0 -279
- package/dist/esm/utils-Bvs8tFDM.js.map +0 -1
- package/dist/esm/zustand/index.js.map +0 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useLocationState } from "./useLocationState.js";
|
|
2
|
+
import { createSearchParams } from "@zayne-labs/toolkit-core";
|
|
3
|
+
import { isFunction } from "@zayne-labs/toolkit-type-helpers";
|
|
4
|
+
|
|
5
|
+
//#region src/hooks/useSearchParams.ts
|
|
6
|
+
const useSearchParams = (options) => {
|
|
7
|
+
const { action = "push",...restOfOptions } = options ?? {};
|
|
8
|
+
const [searchParams, actions] = useLocationState((state) => state.search, restOfOptions);
|
|
9
|
+
const setSearchParams = (newQueryParams) => {
|
|
10
|
+
const params = isFunction(newQueryParams) ? newQueryParams(searchParams) : newQueryParams;
|
|
11
|
+
const nextSearchParams = createSearchParams(params);
|
|
12
|
+
actions[action]({ search: nextSearchParams });
|
|
13
|
+
};
|
|
14
|
+
return [
|
|
15
|
+
searchParams,
|
|
16
|
+
setSearchParams,
|
|
17
|
+
actions.triggerPopstateEvent
|
|
18
|
+
];
|
|
19
|
+
};
|
|
20
|
+
const useSearchParamsObject = (options) => {
|
|
21
|
+
const [searchParams, setSearchParams, triggerPopstateEvent] = useSearchParams(options);
|
|
22
|
+
const searchParamsObject = Object.fromEntries(searchParams);
|
|
23
|
+
const setSearchParamsObject = (newQueryParams) => {
|
|
24
|
+
const params = isFunction(newQueryParams) ? newQueryParams(searchParamsObject) : newQueryParams;
|
|
25
|
+
setSearchParams(params);
|
|
26
|
+
};
|
|
27
|
+
return [
|
|
28
|
+
searchParamsObject,
|
|
29
|
+
setSearchParamsObject,
|
|
30
|
+
triggerPopstateEvent
|
|
31
|
+
];
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { useSearchParams, useSearchParamsObject };
|
|
36
|
+
//# sourceMappingURL=useSearchParams.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSearchParams.js","names":[],"sources":["../../../src/hooks/useSearchParams.ts"],"sourcesContent":["import {\n\tcreateSearchParams,\n\ttype LocationStoreOptions,\n\ttype URLSearchParamsInit,\n} from \"@zayne-labs/toolkit-core\";\nimport { isFunction } from \"@zayne-labs/toolkit-type-helpers\";\nimport { useLocationState } from \"./useLocationState\";\n\ntype UseSearchParamsOptions = LocationStoreOptions & {\n\taction?: \"push\" | \"replace\";\n};\n\nexport const useSearchParams = <TSearchParams extends URLSearchParamsInit>(\n\toptions?: UseSearchParamsOptions\n) => {\n\tconst { action = \"push\", ...restOfOptions } = options ?? {};\n\n\tconst [searchParams, actions] = useLocationState((state) => state.search, restOfOptions);\n\n\tconst setSearchParams = (\n\t\tnewQueryParams: TSearchParams | ((prev: URLSearchParams) => TSearchParams)\n\t) => {\n\t\tconst params = isFunction(newQueryParams) ? newQueryParams(searchParams) : newQueryParams;\n\n\t\tconst nextSearchParams = createSearchParams(params);\n\n\t\tactions[action]({ search: nextSearchParams });\n\t};\n\n\treturn [searchParams, setSearchParams, actions.triggerPopstateEvent] as [\n\t\tsearchParams: typeof searchParams,\n\t\tsetSearchParams: typeof setSearchParams,\n\t\ttriggerPopstateEvent: typeof actions.triggerPopstateEvent,\n\t];\n};\n\nexport const useSearchParamsObject = <TSearchParams extends Record<string, string>>(\n\toptions?: UseSearchParamsOptions\n) => {\n\tconst [searchParams, setSearchParams, triggerPopstateEvent] = useSearchParams(options);\n\n\tconst searchParamsObject = Object.fromEntries(searchParams) as TSearchParams;\n\n\tconst setSearchParamsObject = (\n\t\tnewQueryParams: TSearchParams | ((prev: TSearchParams) => TSearchParams)\n\t) => {\n\t\tconst params = isFunction(newQueryParams) ? newQueryParams(searchParamsObject) : newQueryParams;\n\n\t\tsetSearchParams(params);\n\t};\n\n\treturn [searchParamsObject, setSearchParamsObject, triggerPopstateEvent] as [\n\t\tsearchParamsObject: typeof searchParamsObject,\n\t\tsetSearchParamsObject: typeof setSearchParamsObject,\n\t\ttriggerPopstateEvent: typeof triggerPopstateEvent,\n\t];\n};\n"],"mappings":";;;;;AAYA,MAAa,mBACZ,YACI;CACJ,MAAM,EAAE,SAAS,OAAQ,GAAG,kBAAkB,WAAW,EAAE;CAE3D,MAAM,CAAC,cAAc,WAAW,kBAAkB,UAAU,MAAM,QAAQ,cAAc;CAExF,MAAM,mBACL,mBACI;EACJ,MAAM,SAAS,WAAW,eAAe,GAAG,eAAe,aAAa,GAAG;EAE3E,MAAM,mBAAmB,mBAAmB,OAAO;AAEnD,UAAQ,QAAQ,EAAE,QAAQ,kBAAkB,CAAC;;AAG9C,QAAO;EAAC;EAAc;EAAiB,QAAQ;EAAqB;;AAOrE,MAAa,yBACZ,YACI;CACJ,MAAM,CAAC,cAAc,iBAAiB,wBAAwB,gBAAgB,QAAQ;CAEtF,MAAM,qBAAqB,OAAO,YAAY,aAAa;CAE3D,MAAM,yBACL,mBACI;EACJ,MAAM,SAAS,WAAW,eAAe,GAAG,eAAe,mBAAmB,GAAG;AAEjF,kBAAgB,OAAO;;AAGxB,QAAO;EAAC;EAAoB;EAAuB;EAAqB"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SelectorFn } from "@zayne-labs/toolkit-type-helpers";
|
|
2
|
+
|
|
3
|
+
//#region src/hooks/useShallowCompare.d.ts
|
|
4
|
+
declare const useShallowCompSelector: <TState, TResult>(selector: SelectorFn<TState, TResult> | undefined) => (state: TState) => TResult;
|
|
5
|
+
declare const useShallowCompValue: <TValue>(value: TValue) => TValue;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { useShallowCompSelector, useShallowCompValue };
|
|
8
|
+
//# sourceMappingURL=useShallowCompare.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useCallbackRef } from "./useCallbackRef.js";
|
|
2
|
+
import { useInsertionEffect, useRef } from "react";
|
|
3
|
+
import { shallowCompare } from "@zayne-labs/toolkit-core";
|
|
4
|
+
|
|
5
|
+
//#region src/hooks/useShallowCompare.ts
|
|
6
|
+
const useShallowCompSelector = (selector) => {
|
|
7
|
+
const prevStateRef = useRef(void 0);
|
|
8
|
+
return useCallbackRef((state) => {
|
|
9
|
+
const nextState = selector?.(state);
|
|
10
|
+
if (!nextState) return prevStateRef.current;
|
|
11
|
+
if (shallowCompare(prevStateRef.current, nextState)) return prevStateRef.current;
|
|
12
|
+
return prevStateRef.current = nextState;
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
const useShallowCompValue = (value) => {
|
|
16
|
+
const prevValueRef = useRef(value);
|
|
17
|
+
useInsertionEffect(() => {
|
|
18
|
+
if (shallowCompare(prevValueRef.current, value)) return;
|
|
19
|
+
prevValueRef.current = value;
|
|
20
|
+
});
|
|
21
|
+
return prevValueRef.current;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
export { useShallowCompSelector, useShallowCompValue };
|
|
26
|
+
//# sourceMappingURL=useShallowCompare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useShallowCompare.js","names":[],"sources":["../../../src/hooks/useShallowCompare.ts"],"sourcesContent":["import { shallowCompare } from \"@zayne-labs/toolkit-core\";\nimport type { SelectorFn } from \"@zayne-labs/toolkit-type-helpers\";\nimport { useInsertionEffect, useRef } from \"react\";\nimport { useCallbackRef } from \"./useCallbackRef\";\n\nexport const useShallowCompSelector = <TState, TResult>(\n\tselector: SelectorFn<TState, TResult> | undefined\n) => {\n\tconst prevStateRef = useRef<TResult>(undefined as never);\n\n\tconst shallowSelector = useCallbackRef((state: TState) => {\n\t\tconst nextState = selector?.(state);\n\n\t\tif (!nextState) {\n\t\t\treturn prevStateRef.current;\n\t\t}\n\n\t\tif (shallowCompare(prevStateRef.current, nextState)) {\n\t\t\treturn prevStateRef.current;\n\t\t}\n\n\t\treturn (prevStateRef.current = nextState);\n\t});\n\n\treturn shallowSelector;\n};\n\nexport const useShallowCompValue = <TValue>(value: TValue) => {\n\tconst prevValueRef = useRef<TValue>(value);\n\n\tuseInsertionEffect(() => {\n\t\tif (shallowCompare(prevValueRef.current, value)) return;\n\n\t\tprevValueRef.current = value;\n\t});\n\n\t// eslint-disable-next-line react-hooks/refs -- Allow this for convenience\n\treturn prevValueRef.current;\n};\n"],"mappings":";;;;;AAKA,MAAa,0BACZ,aACI;CACJ,MAAM,eAAe,OAAgB,OAAmB;AAgBxD,QAdwB,gBAAgB,UAAkB;EACzD,MAAM,YAAY,WAAW,MAAM;AAEnC,MAAI,CAAC,UACJ,QAAO,aAAa;AAGrB,MAAI,eAAe,aAAa,SAAS,UAAU,CAClD,QAAO,aAAa;AAGrB,SAAQ,aAAa,UAAU;GAC9B;;AAKH,MAAa,uBAA+B,UAAkB;CAC7D,MAAM,eAAe,OAAe,MAAM;AAE1C,0BAAyB;AACxB,MAAI,eAAe,aAAa,SAAS,MAAM,CAAE;AAEjD,eAAa,UAAU;GACtB;AAGF,QAAO,aAAa"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as _zayne_labs_toolkit_core4 from "@zayne-labs/toolkit-core";
|
|
2
|
+
import { StorageOptions, StorageStoreApi } from "@zayne-labs/toolkit-core";
|
|
3
|
+
import { SelectorFn } from "@zayne-labs/toolkit-type-helpers";
|
|
4
|
+
|
|
5
|
+
//#region src/hooks/useStorageState.d.ts
|
|
6
|
+
type UseStorageResult<TState, TSlice = TState> = [state: TSlice, actions: StorageStoreApi<TState>];
|
|
7
|
+
/**
|
|
8
|
+
* @description Creates a custom hook that returns a storage state and actions to modify it. You can use this if you need shared options.
|
|
9
|
+
* @note You must use this if you want to be able to prevent syncing state across tabs.
|
|
10
|
+
*/
|
|
11
|
+
declare const createUseStorageState: <TState>(baseOptions: StorageOptions<TState>) => _zayne_labs_toolkit_core4.StoreApi<TState> & {
|
|
12
|
+
removeState: () => void;
|
|
13
|
+
} & (<TSlice = TState>(selector?: SelectorFn<TState, TSlice>) => UseStorageResult<TState, TSlice>);
|
|
14
|
+
type UseStorageStateOptions<TValue> = Omit<StorageOptions<TValue>, "initialValue" | "key">;
|
|
15
|
+
declare const useStorageState: <TValue, TSlice = TValue>(key: string, initialValue?: TValue, options?: UseStorageStateOptions<TValue> & {
|
|
16
|
+
select?: SelectorFn<TValue, TSlice>;
|
|
17
|
+
}) => UseStorageResult<TValue, TSlice>;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { createUseStorageState, useStorageState };
|
|
20
|
+
//# sourceMappingURL=useStorageState.d.ts.map
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { useCallbackRef } from "./useCallbackRef.js";
|
|
2
|
+
import { useStore } from "./useStore.js";
|
|
3
|
+
import { useMemo } from "react";
|
|
4
|
+
import { createExternalStorageStore } from "@zayne-labs/toolkit-core";
|
|
5
|
+
|
|
6
|
+
//#region src/hooks/useStorageState.ts
|
|
7
|
+
/**
|
|
8
|
+
* @description Creates a custom hook that returns a storage state and actions to modify it. You can use this if you need shared options.
|
|
9
|
+
* @note You must use this if you want to be able to prevent syncing state across tabs.
|
|
10
|
+
*/
|
|
11
|
+
const createUseStorageState = (baseOptions) => {
|
|
12
|
+
const externalStore = createExternalStorageStore(baseOptions);
|
|
13
|
+
const useStorageState$1 = (selector) => {
|
|
14
|
+
return [useStore(externalStore, selector), externalStore];
|
|
15
|
+
};
|
|
16
|
+
Object.assign(useStorageState$1, externalStore);
|
|
17
|
+
return useStorageState$1;
|
|
18
|
+
};
|
|
19
|
+
const useStorageState = (key, initialValue, options) => {
|
|
20
|
+
const { equalityFn, logger, parser, partialize, select, serializer, storageArea, syncStateAcrossTabs } = options ?? {};
|
|
21
|
+
const savedEquality = useCallbackRef(equalityFn);
|
|
22
|
+
const savedLogger = useCallbackRef(logger);
|
|
23
|
+
const savedParser = useCallbackRef(parser);
|
|
24
|
+
const savedPartialize = useCallbackRef(partialize);
|
|
25
|
+
const savedSerializer = useCallbackRef(serializer);
|
|
26
|
+
const externalStore = useMemo(() => {
|
|
27
|
+
return createExternalStorageStore({
|
|
28
|
+
equalityFn: savedEquality,
|
|
29
|
+
initialValue,
|
|
30
|
+
key,
|
|
31
|
+
logger: savedLogger,
|
|
32
|
+
parser: savedParser,
|
|
33
|
+
partialize: savedPartialize,
|
|
34
|
+
serializer: savedSerializer,
|
|
35
|
+
storageArea,
|
|
36
|
+
syncStateAcrossTabs
|
|
37
|
+
});
|
|
38
|
+
}, [
|
|
39
|
+
initialValue,
|
|
40
|
+
key,
|
|
41
|
+
savedEquality,
|
|
42
|
+
savedLogger,
|
|
43
|
+
savedParser,
|
|
44
|
+
savedPartialize,
|
|
45
|
+
savedSerializer,
|
|
46
|
+
storageArea,
|
|
47
|
+
syncStateAcrossTabs
|
|
48
|
+
]);
|
|
49
|
+
return [useStore(externalStore, select), externalStore];
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
export { createUseStorageState, useStorageState };
|
|
54
|
+
//# sourceMappingURL=useStorageState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStorageState.js","names":["useStorageState"],"sources":["../../../src/hooks/useStorageState.ts"],"sourcesContent":["import {\n\tcreateExternalStorageStore,\n\ttype StorageOptions,\n\ttype StorageStoreApi,\n} from \"@zayne-labs/toolkit-core\";\nimport type { SelectorFn } from \"@zayne-labs/toolkit-type-helpers\";\nimport { useMemo } from \"react\";\nimport { useCallbackRef } from \"./useCallbackRef\";\nimport { useStore } from \"./useStore\";\n\ntype UseStorageResult<TState, TSlice = TState> = [state: TSlice, actions: StorageStoreApi<TState>];\n\n/**\n * @description Creates a custom hook that returns a storage state and actions to modify it. You can use this if you need shared options.\n * @note You must use this if you want to be able to prevent syncing state across tabs.\n */\nexport const createUseStorageState = <TState>(baseOptions: StorageOptions<TState>) => {\n\tconst externalStore = createExternalStorageStore(baseOptions);\n\n\ttype UseBoundStorageState = StorageStoreApi<TState>\n\t\t& (<TSlice = TState>(selector?: SelectorFn<TState, TSlice>) => UseStorageResult<TState, TSlice>);\n\n\tconst useStorageState = <TSlice = TState>(\n\t\tselector?: SelectorFn<TState, TSlice>\n\t): UseStorageResult<TState, TSlice> => {\n\t\tconst stateInStorage = useStore(externalStore, selector);\n\n\t\treturn [stateInStorage, externalStore];\n\t};\n\n\tObject.assign(useStorageState, externalStore);\n\n\treturn useStorageState as UseBoundStorageState;\n};\n\ntype UseStorageStateOptions<TValue> = Omit<StorageOptions<TValue>, \"initialValue\" | \"key\">;\n\nexport const useStorageState = <TValue, TSlice = TValue>(\n\tkey: string,\n\tinitialValue?: TValue,\n\toptions?: UseStorageStateOptions<TValue> & { select?: SelectorFn<TValue, TSlice> }\n): UseStorageResult<TValue, TSlice> => {\n\tconst { equalityFn, logger, parser, partialize, select, serializer, storageArea, syncStateAcrossTabs } =\n\t\toptions ?? {};\n\n\tconst savedEquality = useCallbackRef(equalityFn);\n\tconst savedLogger = useCallbackRef(logger);\n\tconst savedParser = useCallbackRef(parser);\n\tconst savedPartialize = useCallbackRef(partialize);\n\tconst savedSerializer = useCallbackRef(serializer);\n\n\tconst externalStore = useMemo(() => {\n\t\treturn createExternalStorageStore({\n\t\t\tequalityFn: savedEquality,\n\t\t\tinitialValue,\n\t\t\tkey,\n\t\t\tlogger: savedLogger,\n\t\t\tparser: savedParser,\n\t\t\tpartialize: savedPartialize,\n\t\t\tserializer: savedSerializer,\n\t\t\tstorageArea,\n\t\t\tsyncStateAcrossTabs,\n\t\t});\n\t}, [\n\t\tinitialValue,\n\t\tkey,\n\t\tsavedEquality,\n\t\tsavedLogger,\n\t\tsavedParser,\n\t\tsavedPartialize,\n\t\tsavedSerializer,\n\t\tstorageArea,\n\t\tsyncStateAcrossTabs,\n\t]);\n\n\tconst stateInStorage = useStore(externalStore as never, select as never);\n\n\treturn [stateInStorage as never, externalStore];\n};\n"],"mappings":";;;;;;;;;;AAgBA,MAAa,yBAAiC,gBAAwC;CACrF,MAAM,gBAAgB,2BAA2B,YAAY;CAK7D,MAAMA,qBACL,aACsC;AAGtC,SAAO,CAFgB,SAAS,eAAe,SAAS,EAEhC,cAAc;;AAGvC,QAAO,OAAOA,mBAAiB,cAAc;AAE7C,QAAOA;;AAKR,MAAa,mBACZ,KACA,cACA,YACsC;CACtC,MAAM,EAAE,YAAY,QAAQ,QAAQ,YAAY,QAAQ,YAAY,aAAa,wBAChF,WAAW,EAAE;CAEd,MAAM,gBAAgB,eAAe,WAAW;CAChD,MAAM,cAAc,eAAe,OAAO;CAC1C,MAAM,cAAc,eAAe,OAAO;CAC1C,MAAM,kBAAkB,eAAe,WAAW;CAClD,MAAM,kBAAkB,eAAe,WAAW;CAElD,MAAM,gBAAgB,cAAc;AACnC,SAAO,2BAA2B;GACjC,YAAY;GACZ;GACA;GACA,QAAQ;GACR,QAAQ;GACR,YAAY;GACZ,YAAY;GACZ;GACA;GACA,CAAC;IACA;EACF;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC;AAIF,QAAO,CAFgB,SAAS,eAAwB,OAAgB,EAEvC,cAAc"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { StoreApi } from "@zayne-labs/toolkit-core";
|
|
2
|
+
import { SelectorFn } from "@zayne-labs/toolkit-type-helpers";
|
|
3
|
+
|
|
4
|
+
//#region src/hooks/useStore.d.ts
|
|
5
|
+
declare const useStore: <TState, TSlice = TState>(store: StoreApi<TState>, selector?: SelectorFn<TState, TSlice>) => TSlice;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { useStore };
|
|
8
|
+
//# sourceMappingURL=useStore.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { useCallback, useDebugValue, useSyncExternalStore } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/hooks/useStore.ts
|
|
4
|
+
const identity = (value) => value;
|
|
5
|
+
const useStore = (store, selector = identity) => {
|
|
6
|
+
const slice = useSyncExternalStore(store.subscribe, useCallback(() => selector(store.getState()), [store, selector]), useCallback(() => selector(store.getInitialState()), [store, selector]));
|
|
7
|
+
useDebugValue(slice);
|
|
8
|
+
return slice;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
//#endregion
|
|
12
|
+
export { useStore };
|
|
13
|
+
//# sourceMappingURL=useStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useStore.js","names":[],"sources":["../../../src/hooks/useStore.ts"],"sourcesContent":["import type { StoreApi } from \"@zayne-labs/toolkit-core\";\nimport type { SelectorFn } from \"@zayne-labs/toolkit-type-helpers\";\nimport { useCallback, useDebugValue, useSyncExternalStore } from \"react\";\n\nconst identity = <TState>(value: TState) => value;\n\nconst useStore = <TState, TSlice = TState>(\n\tstore: StoreApi<TState>,\n\tselector: SelectorFn<TState, TSlice> = identity as never\n) => {\n\tconst slice = useSyncExternalStore(\n\t\tstore.subscribe,\n\t\tuseCallback(() => selector(store.getState()), [store, selector]),\n\t\tuseCallback(() => selector(store.getInitialState()), [store, selector])\n\t);\n\n\tuseDebugValue(slice);\n\n\treturn slice;\n};\n\nexport { useStore };\n"],"mappings":";;;AAIA,MAAM,YAAoB,UAAkB;AAE5C,MAAM,YACL,OACA,WAAuC,aACnC;CACJ,MAAM,QAAQ,qBACb,MAAM,WACN,kBAAkB,SAAS,MAAM,UAAU,CAAC,EAAE,CAAC,OAAO,SAAS,CAAC,EAChE,kBAAkB,SAAS,MAAM,iBAAiB,CAAC,EAAE,CAAC,OAAO,SAAS,CAAC,CACvE;AAED,eAAc,MAAM;AAEpB,QAAO"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CallbackFn } from "@zayne-labs/toolkit-type-helpers";
|
|
2
|
+
|
|
3
|
+
//#region src/hooks/useThrottle.d.ts
|
|
4
|
+
declare const useThrottleBySetTimeout: <TParams>(callbackFn: CallbackFn<TParams>, delay: number) => {
|
|
5
|
+
(...params: TParams[]): void;
|
|
6
|
+
cancelTimeout(): void;
|
|
7
|
+
};
|
|
8
|
+
declare const useThrottleByTimer: <TParams>(callbackFn: CallbackFn<TParams>, delay: number) => (...params: TParams[]) => void;
|
|
9
|
+
declare const useThrottleByFrame: <TParams>(callbackFn: CallbackFn<TParams>) => {
|
|
10
|
+
(...params: TParams[]): void;
|
|
11
|
+
cancelAnimation(): void;
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { useThrottleByFrame, useThrottleBySetTimeout, useThrottleByTimer };
|
|
15
|
+
//# sourceMappingURL=useThrottle.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { useCallbackRef } from "./useCallbackRef.js";
|
|
2
|
+
import { useUnmountEffect } from "./effects/useUnMountEffect.js";
|
|
3
|
+
import { useConstant } from "./useConstant.js";
|
|
4
|
+
import { useMemo } from "react";
|
|
5
|
+
import { throttleByFrame, throttleBySetTimeout, throttleByTime } from "@zayne-labs/toolkit-core";
|
|
6
|
+
|
|
7
|
+
//#region src/hooks/useThrottle.ts
|
|
8
|
+
const useThrottleBySetTimeout = (callbackFn, delay) => {
|
|
9
|
+
const latestCallback = useCallbackRef(callbackFn);
|
|
10
|
+
const throttledCallback = useMemo(() => throttleBySetTimeout(latestCallback, delay), [delay, latestCallback]);
|
|
11
|
+
useUnmountEffect(() => throttledCallback.cancelTimeout());
|
|
12
|
+
return throttledCallback;
|
|
13
|
+
};
|
|
14
|
+
const useThrottleByTimer = (callbackFn, delay) => {
|
|
15
|
+
const latestCallback = useCallbackRef(callbackFn);
|
|
16
|
+
return useMemo(() => throttleByTime(latestCallback, delay), [delay, latestCallback]);
|
|
17
|
+
};
|
|
18
|
+
const useThrottleByFrame = (callbackFn) => {
|
|
19
|
+
const latestCallback = useCallbackRef(callbackFn);
|
|
20
|
+
const throttledCallback = useConstant(() => throttleByFrame(latestCallback));
|
|
21
|
+
useUnmountEffect(() => throttledCallback.cancelAnimation());
|
|
22
|
+
return throttledCallback;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { useThrottleByFrame, useThrottleBySetTimeout, useThrottleByTimer };
|
|
27
|
+
//# sourceMappingURL=useThrottle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useThrottle.js","names":[],"sources":["../../../src/hooks/useThrottle.ts"],"sourcesContent":["import { throttleByFrame, throttleBySetTimeout, throttleByTime } from \"@zayne-labs/toolkit-core\";\nimport type { CallbackFn } from \"@zayne-labs/toolkit-type-helpers\";\nimport { useMemo } from \"react\";\nimport { useUnmountEffect } from \"./effects\";\nimport { useCallbackRef } from \"./useCallbackRef\";\nimport { useConstant } from \"./useConstant\";\n\nexport const useThrottleBySetTimeout = <TParams>(callbackFn: CallbackFn<TParams>, delay: number) => {\n\tconst latestCallback = useCallbackRef(callbackFn);\n\n\tconst throttledCallback = useMemo(\n\t\t() => throttleBySetTimeout(latestCallback, delay),\n\t\t[delay, latestCallback]\n\t);\n\n\tuseUnmountEffect(() => throttledCallback.cancelTimeout());\n\n\treturn throttledCallback;\n};\n\nexport const useThrottleByTimer = <TParams>(callbackFn: CallbackFn<TParams>, delay: number) => {\n\tconst latestCallback = useCallbackRef(callbackFn);\n\n\tconst throttledCallback = useMemo(() => throttleByTime(latestCallback, delay), [delay, latestCallback]);\n\n\treturn throttledCallback;\n};\n\nexport const useThrottleByFrame = <TParams>(callbackFn: CallbackFn<TParams>) => {\n\tconst latestCallback = useCallbackRef(callbackFn);\n\n\tconst throttledCallback = useConstant(() => throttleByFrame(latestCallback));\n\n\tuseUnmountEffect(() => throttledCallback.cancelAnimation());\n\n\treturn throttledCallback;\n};\n"],"mappings":";;;;;;;AAOA,MAAa,2BAAoC,YAAiC,UAAkB;CACnG,MAAM,iBAAiB,eAAe,WAAW;CAEjD,MAAM,oBAAoB,cACnB,qBAAqB,gBAAgB,MAAM,EACjD,CAAC,OAAO,eAAe,CACvB;AAED,wBAAuB,kBAAkB,eAAe,CAAC;AAEzD,QAAO;;AAGR,MAAa,sBAA+B,YAAiC,UAAkB;CAC9F,MAAM,iBAAiB,eAAe,WAAW;AAIjD,QAF0B,cAAc,eAAe,gBAAgB,MAAM,EAAE,CAAC,OAAO,eAAe,CAAC;;AAKxG,MAAa,sBAA+B,eAAoC;CAC/E,MAAM,iBAAiB,eAAe,WAAW;CAEjD,MAAM,oBAAoB,kBAAkB,gBAAgB,eAAe,CAAC;AAE5E,wBAAuB,kBAAkB,iBAAiB,CAAC;AAE3D,QAAO"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
//#region src/hooks/useToggle.d.ts
|
|
2
|
+
type InitialState = boolean | (() => boolean);
|
|
3
|
+
declare const useToggle: (initialValue?: InitialState) => [value: boolean, toggleValue: <TValue>(newValue?: TValue) => void];
|
|
4
|
+
//#endregion
|
|
5
|
+
export { useToggle };
|
|
6
|
+
//# sourceMappingURL=useToggle.d.ts.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useCallback, useState } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/hooks/useToggle.ts
|
|
4
|
+
const useToggle = (initialValue = false) => {
|
|
5
|
+
const [value, setValue] = useState(initialValue);
|
|
6
|
+
const toggleValue = useCallback((newValue) => {
|
|
7
|
+
if (typeof newValue === "boolean") {
|
|
8
|
+
setValue(newValue);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
setValue((prev) => !prev);
|
|
12
|
+
}, []);
|
|
13
|
+
return [value, toggleValue];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { useToggle };
|
|
18
|
+
//# sourceMappingURL=useToggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useToggle.js","names":[],"sources":["../../../src/hooks/useToggle.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\n\ntype InitialState = boolean | (() => boolean);\n\nconst useToggle = (initialValue: InitialState = false) => {\n\tconst [value, setValue] = useState(initialValue);\n\n\tconst toggleValue = useCallback(<TValue>(newValue?: TValue) => {\n\t\tif (typeof newValue === \"boolean\") {\n\t\t\tsetValue(newValue);\n\t\t\treturn;\n\t\t}\n\n\t\tsetValue((prev) => !prev);\n\t}, []);\n\n\treturn [value, toggleValue] as [value: typeof value, toggleValue: typeof toggleValue];\n};\n\nexport { useToggle };\n"],"mappings":";;;AAIA,MAAM,aAAa,eAA6B,UAAU;CACzD,MAAM,CAAC,OAAO,YAAY,SAAS,aAAa;CAEhD,MAAM,cAAc,aAAqB,aAAsB;AAC9D,MAAI,OAAO,aAAa,WAAW;AAClC,YAAS,SAAS;AAClB;;AAGD,YAAU,SAAS,CAAC,KAAK;IACvB,EAAE,CAAC;AAEN,QAAO,CAAC,OAAO,YAAY"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AnyFunction } from "@zayne-labs/toolkit-type-helpers";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/composeEventHandlers.d.ts
|
|
4
|
+
declare const composeTwoEventHandlers: (formerHandler: AnyFunction | undefined, latterHandler: AnyFunction | undefined) => (event: unknown) => unknown;
|
|
5
|
+
declare const composeEventHandlers: (...eventHandlerArray: Array<AnyFunction | undefined>) => (event: unknown) => unknown;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { composeEventHandlers, composeTwoEventHandlers };
|
|
8
|
+
//# sourceMappingURL=composeEventHandlers.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { isObject } from "@zayne-labs/toolkit-type-helpers";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/composeEventHandlers.ts
|
|
4
|
+
const isSyntheticEvent = (event) => {
|
|
5
|
+
return isObject(event) && Object.hasOwn(event, "nativeEvent");
|
|
6
|
+
};
|
|
7
|
+
const composeTwoEventHandlers = (formerHandler, latterHandler) => {
|
|
8
|
+
const mergedEventHandler = (event) => {
|
|
9
|
+
if (isSyntheticEvent(event)) {
|
|
10
|
+
const result$1 = latterHandler?.(event);
|
|
11
|
+
if (!event.defaultPrevented) formerHandler?.(event);
|
|
12
|
+
return result$1;
|
|
13
|
+
}
|
|
14
|
+
const result = latterHandler?.(event);
|
|
15
|
+
formerHandler?.(event);
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
18
|
+
return mergedEventHandler;
|
|
19
|
+
};
|
|
20
|
+
const composeEventHandlers = (...eventHandlerArray) => {
|
|
21
|
+
const mergedEventHandler = (event) => {
|
|
22
|
+
if (eventHandlerArray.length === 0) return;
|
|
23
|
+
if (eventHandlerArray.length === 1) return eventHandlerArray[0]?.(event);
|
|
24
|
+
let accumulatedHandlers;
|
|
25
|
+
for (const eventHandler of eventHandlerArray) {
|
|
26
|
+
if (!eventHandler) continue;
|
|
27
|
+
accumulatedHandlers = composeTwoEventHandlers(accumulatedHandlers, eventHandler);
|
|
28
|
+
}
|
|
29
|
+
return accumulatedHandlers?.(event);
|
|
30
|
+
};
|
|
31
|
+
return mergedEventHandler;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
//#endregion
|
|
35
|
+
export { composeEventHandlers, composeTwoEventHandlers };
|
|
36
|
+
//# sourceMappingURL=composeEventHandlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composeEventHandlers.js","names":["result","accumulatedHandlers: AnyFunction | undefined"],"sources":["../../../src/utils/composeEventHandlers.ts"],"sourcesContent":["import { type AnyFunction, isObject } from \"@zayne-labs/toolkit-type-helpers\";\n\nconst isSyntheticEvent = (event: unknown): event is React.SyntheticEvent => {\n\treturn isObject(event) && Object.hasOwn(event, \"nativeEvent\");\n};\n\nexport const composeTwoEventHandlers = (\n\tformerHandler: AnyFunction | undefined,\n\tlatterHandler: AnyFunction | undefined\n) => {\n\tconst mergedEventHandler = (event: unknown) => {\n\t\tif (isSyntheticEvent(event)) {\n\t\t\tconst result = latterHandler?.(event) as unknown;\n\n\t\t\tif (!event.defaultPrevented) {\n\t\t\t\tformerHandler?.(event);\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tconst result = latterHandler?.(event) as unknown;\n\t\tformerHandler?.(event);\n\t\treturn result;\n\t};\n\n\treturn mergedEventHandler;\n};\n\nexport const composeEventHandlers = (...eventHandlerArray: Array<AnyFunction | undefined>) => {\n\tconst mergedEventHandler = (event: unknown) => {\n\t\tif (eventHandlerArray.length === 0) return;\n\n\t\tif (eventHandlerArray.length === 1) {\n\t\t\treturn eventHandlerArray[0]?.(event) as unknown;\n\t\t}\n\n\t\tlet accumulatedHandlers: AnyFunction | undefined;\n\n\t\tfor (const eventHandler of eventHandlerArray) {\n\t\t\tif (!eventHandler) continue;\n\n\t\t\taccumulatedHandlers = composeTwoEventHandlers(accumulatedHandlers, eventHandler);\n\t\t}\n\n\t\treturn accumulatedHandlers?.(event) as unknown;\n\t};\n\n\treturn mergedEventHandler;\n};\n"],"mappings":";;;AAEA,MAAM,oBAAoB,UAAkD;AAC3E,QAAO,SAAS,MAAM,IAAI,OAAO,OAAO,OAAO,cAAc;;AAG9D,MAAa,2BACZ,eACA,kBACI;CACJ,MAAM,sBAAsB,UAAmB;AAC9C,MAAI,iBAAiB,MAAM,EAAE;GAC5B,MAAMA,WAAS,gBAAgB,MAAM;AAErC,OAAI,CAAC,MAAM,iBACV,iBAAgB,MAAM;AAGvB,UAAOA;;EAGR,MAAM,SAAS,gBAAgB,MAAM;AACrC,kBAAgB,MAAM;AACtB,SAAO;;AAGR,QAAO;;AAGR,MAAa,wBAAwB,GAAG,sBAAsD;CAC7F,MAAM,sBAAsB,UAAmB;AAC9C,MAAI,kBAAkB,WAAW,EAAG;AAEpC,MAAI,kBAAkB,WAAW,EAChC,QAAO,kBAAkB,KAAK,MAAM;EAGrC,IAAIC;AAEJ,OAAK,MAAM,gBAAgB,mBAAmB;AAC7C,OAAI,CAAC,aAAc;AAEnB,yBAAsB,wBAAwB,qBAAqB,aAAa;;AAGjF,SAAO,sBAAsB,MAAM;;AAGpC,QAAO"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { RefCallback } from "react";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/composeRefs.d.ts
|
|
4
|
+
type PossibleRef<TRef extends HTMLElement> = React.Ref<TRef> | undefined;
|
|
5
|
+
/**
|
|
6
|
+
* @description Set a given ref to a given value.
|
|
7
|
+
*
|
|
8
|
+
* This utility takes care of different types of refs: callback refs and RefObject(s)
|
|
9
|
+
*/
|
|
10
|
+
declare const setRef: <TRef extends HTMLElement>(ref: PossibleRef<TRef>, node: TRef | null) => ReturnType<RefCallback<TRef>>;
|
|
11
|
+
/**
|
|
12
|
+
* @description A utility to combine refs. Accepts callback refs and RefObject(s)
|
|
13
|
+
*/
|
|
14
|
+
declare const composeRefs: <TRef extends HTMLElement>(...refs: Array<PossibleRef<TRef>>) => RefCallback<TRef>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { PossibleRef, composeRefs, setRef };
|
|
17
|
+
//# sourceMappingURL=composeRefs.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { isFunction } from "@zayne-labs/toolkit-type-helpers";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/composeRefs.ts
|
|
4
|
+
/**
|
|
5
|
+
* @description Set a given ref to a given value.
|
|
6
|
+
*
|
|
7
|
+
* This utility takes care of different types of refs: callback refs and RefObject(s)
|
|
8
|
+
*/
|
|
9
|
+
const setRef = (ref, node) => {
|
|
10
|
+
if (!ref) return;
|
|
11
|
+
if (isFunction(ref)) return ref(node);
|
|
12
|
+
ref.current = node;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* @description A utility to combine refs. Accepts callback refs and RefObject(s)
|
|
16
|
+
*/
|
|
17
|
+
const composeRefs = (...refs) => {
|
|
18
|
+
const mergedRefCallBack = (node) => {
|
|
19
|
+
const cleanupFnArray = refs.map((ref) => setRef(ref, node));
|
|
20
|
+
const cleanupFn = () => cleanupFnArray.forEach((cleanup) => cleanup?.());
|
|
21
|
+
return cleanupFn;
|
|
22
|
+
};
|
|
23
|
+
return mergedRefCallBack;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
//#endregion
|
|
27
|
+
export { composeRefs, setRef };
|
|
28
|
+
//# sourceMappingURL=composeRefs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composeRefs.js","names":["mergedRefCallBack: RefCallback<TRef>"],"sources":["../../../src/utils/composeRefs.ts"],"sourcesContent":["import { isFunction } from \"@zayne-labs/toolkit-type-helpers\";\nimport type { RefCallback } from \"react\";\n\nexport type PossibleRef<TRef extends HTMLElement> = React.Ref<TRef> | undefined;\n\n/**\n * @description Set a given ref to a given value.\n *\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n */\nexport const setRef = <TRef extends HTMLElement>(\n\tref: PossibleRef<TRef>,\n\tnode: TRef | null\n): ReturnType<RefCallback<TRef>> => {\n\tif (!ref) return;\n\n\tif (isFunction(ref)) {\n\t\treturn ref(node);\n\t}\n\n\t// eslint-disable-next-line no-param-reassign -- Mutation is needed here\n\tref.current = node;\n};\n\n/**\n * @description A utility to combine refs. Accepts callback refs and RefObject(s)\n */\nexport const composeRefs = <TRef extends HTMLElement>(\n\t...refs: Array<PossibleRef<TRef>>\n): RefCallback<TRef> => {\n\tconst mergedRefCallBack: RefCallback<TRef> = (node) => {\n\t\tconst cleanupFnArray = refs.map((ref) => setRef(ref, node));\n\n\t\tconst cleanupFn = () => cleanupFnArray.forEach((cleanup) => cleanup?.());\n\n\t\treturn cleanupFn;\n\t};\n\n\treturn mergedRefCallBack;\n};\n"],"mappings":";;;;;;;;AAUA,MAAa,UACZ,KACA,SACmC;AACnC,KAAI,CAAC,IAAK;AAEV,KAAI,WAAW,IAAI,CAClB,QAAO,IAAI,KAAK;AAIjB,KAAI,UAAU;;;;;AAMf,MAAa,eACZ,GAAG,SACoB;CACvB,MAAMA,qBAAwC,SAAS;EACtD,MAAM,iBAAiB,KAAK,KAAK,QAAQ,OAAO,KAAK,KAAK,CAAC;EAE3D,MAAM,kBAAkB,eAAe,SAAS,YAAY,WAAW,CAAC;AAExE,SAAO;;AAGR,QAAO"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as react13 from "react";
|
|
2
|
+
import { Prettify, UnknownObject } from "@zayne-labs/toolkit-type-helpers";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/getSlot/getSlot.d.ts
|
|
5
|
+
type FunctionalComponent<TProps extends UnknownObject = never> = React.FunctionComponent<TProps>;
|
|
6
|
+
/**
|
|
7
|
+
* @description Checks if a react child (within the children array) matches the provided SlotComponent using multiple matching strategies:
|
|
8
|
+
* 1. Matches by slot symbol property
|
|
9
|
+
* 2. Matches by component name
|
|
10
|
+
*/
|
|
11
|
+
declare const matchesSlotComponent: (child: React.ReactNode, SlotComponent: FunctionalComponent) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* @description Checks if a react child (within the children array) matches any of the provided SlotComponents.
|
|
14
|
+
*/
|
|
15
|
+
declare const matchesAnySlotComponent: (child: React.ReactNode, SlotComponents: FunctionalComponent[]) => boolean;
|
|
16
|
+
type SlotOptions = {
|
|
17
|
+
/**
|
|
18
|
+
* @description The error message to throw when multiple slots are found for a given slot component
|
|
19
|
+
*/
|
|
20
|
+
errorMessage?: string;
|
|
21
|
+
/**
|
|
22
|
+
* @description When true, an AssertionError will be thrown if multiple slots are found for a given slot component
|
|
23
|
+
*/
|
|
24
|
+
throwOnMultipleSlotMatch?: boolean;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* @description Retrieves a single slot element from a collection of React children that matches the provided SlotComponent component.
|
|
28
|
+
*
|
|
29
|
+
* @throws { AssertionError } when throwOnMultipleSlotMatch is true and multiple slots are found
|
|
30
|
+
*/
|
|
31
|
+
declare const getSingleSlot: (children: React.ReactNode, SlotComponent: FunctionalComponent, options?: SlotOptions) => react13.ReactNode;
|
|
32
|
+
type MultipleSlotsOptions = {
|
|
33
|
+
/**
|
|
34
|
+
* @description The error message to throw when multiple slots are found for a given slot component
|
|
35
|
+
* If a string is provided, the same message will be used for all slot components
|
|
36
|
+
* If an array is provided, each string in the array will be used as the errorMessage for the corresponding slot component
|
|
37
|
+
*/
|
|
38
|
+
errorMessage?: string | string[];
|
|
39
|
+
/**
|
|
40
|
+
* @description When true, an AssertionError will be thrown if multiple slots are found for a given slot component
|
|
41
|
+
* If a boolean is provided, the same value will be used for all slot components
|
|
42
|
+
* If an array is provided, each boolean in the array will be used as the throwOnMultipleSlotMatch value for the corresponding slot component
|
|
43
|
+
*/
|
|
44
|
+
throwOnMultipleSlotMatch?: boolean | boolean[];
|
|
45
|
+
};
|
|
46
|
+
type GetMultipleSlotsResult<TSlotComponents extends FunctionalComponent[]> = {
|
|
47
|
+
regularChildren: React.ReactNode[];
|
|
48
|
+
slots: { [Key in keyof TSlotComponents]: ReturnType<TSlotComponents[Key]> };
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* @description The same as getSingleSlot, but for multiple slot components
|
|
52
|
+
*/
|
|
53
|
+
declare const getMultipleSlots: <const TSlotComponents extends FunctionalComponent[]>(children: React.ReactNode, SlotComponents: TSlotComponents, options?: MultipleSlotsOptions) => Prettify<GetMultipleSlotsResult<TSlotComponents>>;
|
|
54
|
+
/**
|
|
55
|
+
* @description Returns all children that are not slot elements (i.e., don't match any of the provided slot components)
|
|
56
|
+
*/
|
|
57
|
+
declare const getRegularChildren: (children: React.ReactNode, SlotComponentOrComponents: FunctionalComponent | FunctionalComponent[]) => react13.ReactNode[];
|
|
58
|
+
//#endregion
|
|
59
|
+
export { FunctionalComponent, getMultipleSlots, getRegularChildren, getSingleSlot, matchesAnySlotComponent, matchesSlotComponent };
|
|
60
|
+
//# sourceMappingURL=getSlot.d.ts.map
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Fragment, isValidElement } from "react";
|
|
2
|
+
import { toArray } from "@zayne-labs/toolkit-core";
|
|
3
|
+
import { AssertionError, isArray, isFunction } from "@zayne-labs/toolkit-type-helpers";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/getSlot/getSlot.ts
|
|
6
|
+
const isWithSlotSymbol = (component) => {
|
|
7
|
+
return "slotSymbol" in component && Boolean(component.slotSymbol);
|
|
8
|
+
};
|
|
9
|
+
const isWithSlotReference = (component) => {
|
|
10
|
+
return "slotReference" in component && Boolean(component.slotReference);
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* @description Checks if a react child (within the children array) matches the provided SlotComponent using multiple matching strategies:
|
|
14
|
+
* 1. Matches by slot symbol property
|
|
15
|
+
* 2. Matches by component name
|
|
16
|
+
*/
|
|
17
|
+
const matchesSlotComponent = (child, SlotComponent) => {
|
|
18
|
+
if (!isValidElement(child) || !isFunction(child.type)) return false;
|
|
19
|
+
const resolvedChildType = isWithSlotReference(child.type) ? child.type.slotReference : child.type;
|
|
20
|
+
if (isWithSlotSymbol(resolvedChildType) && isWithSlotSymbol(SlotComponent) && resolvedChildType.slotSymbol === SlotComponent.slotSymbol) return true;
|
|
21
|
+
if (child.type.name === SlotComponent.name) return true;
|
|
22
|
+
return false;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* @description Checks if a react child (within the children array) matches any of the provided SlotComponents.
|
|
26
|
+
*/
|
|
27
|
+
const matchesAnySlotComponent = (child, SlotComponents) => {
|
|
28
|
+
return SlotComponents.some((SlotComponent) => matchesSlotComponent(child, SlotComponent));
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* @description Counts how many times a given slot component appears in an array of children
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
const calculateSlotOccurrences = (childrenArray, SlotComponent) => {
|
|
35
|
+
let count = 0;
|
|
36
|
+
for (const child of childrenArray) {
|
|
37
|
+
if (!matchesSlotComponent(child, SlotComponent)) continue;
|
|
38
|
+
count += 1;
|
|
39
|
+
}
|
|
40
|
+
return count;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* @description Retrieves a single slot element from a collection of React children that matches the provided SlotComponent component.
|
|
44
|
+
*
|
|
45
|
+
* @throws { AssertionError } when throwOnMultipleSlotMatch is true and multiple slots are found
|
|
46
|
+
*/
|
|
47
|
+
const getSingleSlot = (children, SlotComponent, options = {}) => {
|
|
48
|
+
const { errorMessage = "Only one instance of the SlotComponent is allowed", throwOnMultipleSlotMatch = false } = options;
|
|
49
|
+
const actualChildren = isValidElement(children) && children.type === Fragment ? children.props.children : children;
|
|
50
|
+
const childrenArray = toArray(actualChildren);
|
|
51
|
+
if (throwOnMultipleSlotMatch && calculateSlotOccurrences(childrenArray, SlotComponent) > 1) throw new AssertionError(errorMessage);
|
|
52
|
+
return childrenArray.find((child) => matchesSlotComponent(child, SlotComponent));
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* @description The same as getSingleSlot, but for multiple slot components
|
|
56
|
+
*/
|
|
57
|
+
const getMultipleSlots = (children, SlotComponents, options) => {
|
|
58
|
+
const { errorMessage, throwOnMultipleSlotMatch } = options ?? {};
|
|
59
|
+
const slots = SlotComponents.map((SlotComponent, index) => getSingleSlot(children, SlotComponent, {
|
|
60
|
+
errorMessage: isArray(errorMessage) ? errorMessage[index] : errorMessage,
|
|
61
|
+
throwOnMultipleSlotMatch: isArray(throwOnMultipleSlotMatch) ? throwOnMultipleSlotMatch[index] : throwOnMultipleSlotMatch
|
|
62
|
+
}));
|
|
63
|
+
return {
|
|
64
|
+
regularChildren: getRegularChildren(children, SlotComponents),
|
|
65
|
+
slots
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* @description Returns all children that are not slot elements (i.e., don't match any of the provided slot components)
|
|
70
|
+
*/
|
|
71
|
+
const getRegularChildren = (children, SlotComponentOrComponents) => {
|
|
72
|
+
const actualChildren = isValidElement(children) && children.type === Fragment ? children.props.children : children;
|
|
73
|
+
return toArray(actualChildren).filter((child) => !matchesAnySlotComponent(child, toArray(SlotComponentOrComponents)));
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
//#endregion
|
|
77
|
+
export { getMultipleSlots, getRegularChildren, getSingleSlot, matchesAnySlotComponent, matchesSlotComponent };
|
|
78
|
+
//# sourceMappingURL=getSlot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSlot.js","names":["ReactFragment"],"sources":["../../../../src/utils/getSlot/getSlot.ts"],"sourcesContent":["import { toArray } from \"@zayne-labs/toolkit-core\";\nimport {\n\ttype AnyFunction,\n\tAssertionError,\n\tisArray,\n\tisFunction,\n\ttype Prettify,\n\ttype UnknownObject,\n} from \"@zayne-labs/toolkit-type-helpers\";\nimport { isValidElement, Fragment as ReactFragment } from \"react\";\nimport type { InferProps } from \"../types\";\n\nexport type FunctionalComponent<TProps extends UnknownObject = never> = React.FunctionComponent<TProps>;\n\nconst isWithSlotSymbol = <TFunction extends AnyFunction>(\n\tcomponent: TFunction\n): component is Record<\"slotSymbol\", unknown> & TFunction => {\n\treturn \"slotSymbol\" in component && Boolean(component.slotSymbol);\n};\n\nconst isWithSlotReference = <TFunction extends AnyFunction>(\n\tcomponent: TFunction\n): component is Record<\"slotReference\", unknown> & TFunction => {\n\treturn \"slotReference\" in component && Boolean(component.slotReference);\n};\n/**\n * @description Checks if a react child (within the children array) matches the provided SlotComponent using multiple matching strategies:\n * 1. Matches by slot symbol property\n * 2. Matches by component name\n */\n\nexport const matchesSlotComponent = (child: React.ReactNode, SlotComponent: FunctionalComponent) => {\n\tif (!isValidElement(child) || !isFunction(child.type)) {\n\t\treturn false;\n\t}\n\n\tconst resolvedChildType =\n\t\tisWithSlotReference(child.type) ? (child.type.slotReference as FunctionalComponent) : child.type;\n\n\tconst hasMatchingSlotSymbol =\n\t\tisWithSlotSymbol(resolvedChildType)\n\t\t&& isWithSlotSymbol(SlotComponent)\n\t\t&& resolvedChildType.slotSymbol === SlotComponent.slotSymbol;\n\n\tif (hasMatchingSlotSymbol) {\n\t\treturn true;\n\t}\n\n\tif (child.type.name === SlotComponent.name) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n/**\n * @description Checks if a react child (within the children array) matches any of the provided SlotComponents.\n */\nexport const matchesAnySlotComponent = (child: React.ReactNode, SlotComponents: FunctionalComponent[]) => {\n\tconst matchesSlot = SlotComponents.some((SlotComponent) => matchesSlotComponent(child, SlotComponent));\n\n\treturn matchesSlot;\n};\n\ntype SlotOptions = {\n\t/**\n\t * @description The error message to throw when multiple slots are found for a given slot component\n\t */\n\terrorMessage?: string;\n\t/**\n\t * @description When true, an AssertionError will be thrown if multiple slots are found for a given slot component\n\t */\n\tthrowOnMultipleSlotMatch?: boolean;\n};\n\n/**\n * @description Counts how many times a given slot component appears in an array of children\n * @internal\n */\nconst calculateSlotOccurrences = (\n\tchildrenArray: React.ReactNode[],\n\tSlotComponent: FunctionalComponent\n) => {\n\tlet count = 0;\n\n\tfor (const child of childrenArray) {\n\t\tif (!matchesSlotComponent(child, SlotComponent)) continue;\n\n\t\tcount += 1;\n\t}\n\n\treturn count;\n};\n\n/**\n * @description Retrieves a single slot element from a collection of React children that matches the provided SlotComponent component.\n *\n * @throws { AssertionError } when throwOnMultipleSlotMatch is true and multiple slots are found\n */\nexport const getSingleSlot = (\n\tchildren: React.ReactNode,\n\tSlotComponent: FunctionalComponent,\n\toptions: SlotOptions = {}\n) => {\n\tconst {\n\t\terrorMessage = \"Only one instance of the SlotComponent is allowed\",\n\t\tthrowOnMultipleSlotMatch = false,\n\t} = options;\n\n\tconst actualChildren =\n\t\tisValidElement<InferProps<typeof ReactFragment>>(children) && children.type === ReactFragment ?\n\t\t\tchildren.props.children\n\t\t:\tchildren;\n\n\tconst childrenArray = toArray<React.ReactNode>(actualChildren);\n\n\tconst shouldThrow =\n\t\tthrowOnMultipleSlotMatch && calculateSlotOccurrences(childrenArray, SlotComponent) > 1;\n\n\tif (shouldThrow) {\n\t\tthrow new AssertionError(errorMessage);\n\t}\n\n\tconst slotElement = childrenArray.find((child) => matchesSlotComponent(child, SlotComponent));\n\n\treturn slotElement;\n};\n\n// NOTE - You can imitate const type parameter by extending readonly[] | []\n\ntype MultipleSlotsOptions = {\n\t/**\n\t * @description The error message to throw when multiple slots are found for a given slot component\n\t * If a string is provided, the same message will be used for all slot components\n\t * If an array is provided, each string in the array will be used as the errorMessage for the corresponding slot component\n\t */\n\terrorMessage?: string | string[];\n\t/**\n\t * @description When true, an AssertionError will be thrown if multiple slots are found for a given slot component\n\t * If a boolean is provided, the same value will be used for all slot components\n\t * If an array is provided, each boolean in the array will be used as the throwOnMultipleSlotMatch value for the corresponding slot component\n\t */\n\tthrowOnMultipleSlotMatch?: boolean | boolean[];\n};\n\ntype GetMultipleSlotsResult<TSlotComponents extends FunctionalComponent[]> = {\n\tregularChildren: React.ReactNode[];\n\tslots: { [Key in keyof TSlotComponents]: ReturnType<TSlotComponents[Key]> };\n};\n\n/**\n * @description The same as getSingleSlot, but for multiple slot components\n */\nexport const getMultipleSlots = <const TSlotComponents extends FunctionalComponent[]>(\n\tchildren: React.ReactNode,\n\tSlotComponents: TSlotComponents,\n\toptions?: MultipleSlotsOptions\n): Prettify<GetMultipleSlotsResult<TSlotComponents>> => {\n\tconst { errorMessage, throwOnMultipleSlotMatch } = options ?? {};\n\n\tconst slots = SlotComponents.map((SlotComponent, index) =>\n\t\tgetSingleSlot(children, SlotComponent, {\n\t\t\terrorMessage: isArray(errorMessage) ? errorMessage[index] : errorMessage,\n\t\t\tthrowOnMultipleSlotMatch:\n\t\t\t\tisArray(throwOnMultipleSlotMatch) ? throwOnMultipleSlotMatch[index] : throwOnMultipleSlotMatch,\n\t\t})\n\t);\n\n\tconst regularChildren = getRegularChildren(children, SlotComponents);\n\n\treturn { regularChildren, slots } as GetMultipleSlotsResult<TSlotComponents>;\n};\n\n/**\n * @description Returns all children that are not slot elements (i.e., don't match any of the provided slot components)\n */\nexport const getRegularChildren = (\n\tchildren: React.ReactNode,\n\tSlotComponentOrComponents: FunctionalComponent | FunctionalComponent[]\n) => {\n\tconst actualChildren =\n\t\tisValidElement<InferProps<typeof ReactFragment>>(children) && children.type === ReactFragment ?\n\t\t\tchildren.props.children\n\t\t:\tchildren;\n\n\tconst childrenArray = toArray<React.ReactNode>(actualChildren);\n\n\tconst regularChildren = childrenArray.filter(\n\t\t(child) => !matchesAnySlotComponent(child, toArray(SlotComponentOrComponents))\n\t);\n\n\treturn regularChildren;\n};\n"],"mappings":";;;;;AAcA,MAAM,oBACL,cAC4D;AAC5D,QAAO,gBAAgB,aAAa,QAAQ,UAAU,WAAW;;AAGlE,MAAM,uBACL,cAC+D;AAC/D,QAAO,mBAAmB,aAAa,QAAQ,UAAU,cAAc;;;;;;;AAQxE,MAAa,wBAAwB,OAAwB,kBAAuC;AACnG,KAAI,CAAC,eAAe,MAAM,IAAI,CAAC,WAAW,MAAM,KAAK,CACpD,QAAO;CAGR,MAAM,oBACL,oBAAoB,MAAM,KAAK,GAAI,MAAM,KAAK,gBAAwC,MAAM;AAO7F,KAJC,iBAAiB,kBAAkB,IAChC,iBAAiB,cAAc,IAC/B,kBAAkB,eAAe,cAAc,WAGlD,QAAO;AAGR,KAAI,MAAM,KAAK,SAAS,cAAc,KACrC,QAAO;AAGR,QAAO;;;;;AAMR,MAAa,2BAA2B,OAAwB,mBAA0C;AAGzG,QAFoB,eAAe,MAAM,kBAAkB,qBAAqB,OAAO,cAAc,CAAC;;;;;;AAoBvG,MAAM,4BACL,eACA,kBACI;CACJ,IAAI,QAAQ;AAEZ,MAAK,MAAM,SAAS,eAAe;AAClC,MAAI,CAAC,qBAAqB,OAAO,cAAc,CAAE;AAEjD,WAAS;;AAGV,QAAO;;;;;;;AAQR,MAAa,iBACZ,UACA,eACA,UAAuB,EAAE,KACrB;CACJ,MAAM,EACL,eAAe,qDACf,2BAA2B,UACxB;CAEJ,MAAM,iBACL,eAAiD,SAAS,IAAI,SAAS,SAASA,WAC/E,SAAS,MAAM,WACd;CAEH,MAAM,gBAAgB,QAAyB,eAAe;AAK9D,KAFC,4BAA4B,yBAAyB,eAAe,cAAc,GAAG,EAGrF,OAAM,IAAI,eAAe,aAAa;AAKvC,QAFoB,cAAc,MAAM,UAAU,qBAAqB,OAAO,cAAc,CAAC;;;;;AA8B9F,MAAa,oBACZ,UACA,gBACA,YACuD;CACvD,MAAM,EAAE,cAAc,6BAA6B,WAAW,EAAE;CAEhE,MAAM,QAAQ,eAAe,KAAK,eAAe,UAChD,cAAc,UAAU,eAAe;EACtC,cAAc,QAAQ,aAAa,GAAG,aAAa,SAAS;EAC5D,0BACC,QAAQ,yBAAyB,GAAG,yBAAyB,SAAS;EACvE,CAAC,CACF;AAID,QAAO;EAAE,iBAFe,mBAAmB,UAAU,eAAe;EAE1C;EAAO;;;;;AAMlC,MAAa,sBACZ,UACA,8BACI;CACJ,MAAM,iBACL,eAAiD,SAAS,IAAI,SAAS,SAASA,WAC/E,SAAS,MAAM,WACd;AAQH,QANsB,QAAyB,eAAe,CAExB,QACpC,UAAU,CAAC,wBAAwB,OAAO,QAAQ,0BAA0B,CAAC,CAC9E"}
|