@sohanemon/utils 4.0.16 → 4.0.19

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.
@@ -6,5 +6,5 @@ type MediaWrapperProps = React.ComponentProps<'div'> & {
6
6
  fallback?: React.ElementType;
7
7
  classNameFallback?: string;
8
8
  };
9
- export declare function MediaWrapper({ breakpoint, as, fallback, classNameFallback, className: classNameOriginal, ...props }: MediaWrapperProps): any;
9
+ export declare function MediaWrapper({ breakpoint, as, fallback, classNameFallback, className: classNameOriginal, ...props }: MediaWrapperProps): import("react/jsx-runtime").JSX.Element;
10
10
  export {};
@@ -1,13 +1,30 @@
1
- import { type Dispatch, type EffectCallback, type SetStateAction } from 'react';
2
- export declare const useClickOutside: (callback?: () => void) => any;
3
- export declare function useMediaQuery(tailwindBreakpoint: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | `(${string})`): any;
1
+ import { type Dispatch, type EffectCallback, type SetStateAction, useEffect } from 'react';
2
+ export declare const useClickOutside: (callback?: () => void) => import("react").MutableRefObject<HTMLDivElement>;
3
+ export declare function useMediaQuery(tailwindBreakpoint: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | `(${string})`): boolean;
4
4
  export declare function useEffectOnce(effect: EffectCallback): void;
5
5
  export declare function useUpdateEffect(effect: EffectCallback, deps: any[]): void;
6
6
  export declare function useDebounce<T>(state: T, delay?: number): T;
7
- export declare const useIsomorphicEffect: any;
7
+ export declare const useIsomorphicEffect: typeof useEffect;
8
8
  export declare function useTimeout(callback: () => void, delay?: number | null): void;
9
9
  export declare function useWindowEvent<K extends string = keyof WindowEventMap>(type: K, listener: K extends keyof WindowEventMap ? (this: Window, ev: WindowEventMap[K]) => void : (this: Window, ev: CustomEvent) => void, options?: boolean | AddEventListenerOptions): void;
10
10
  type LocalStorageValue<T> = [T, Dispatch<SetStateAction<T>>];
11
11
  export declare const useLocalStorage: <T extends Record<string, any>>(key: string, defaultValue: T) => LocalStorageValue<T>;
12
12
  export declare const useUrlParams: <T extends string | number | boolean>(key: string, defaultValue: T) => [T, (value: T) => void];
13
- export {};
13
+ interface UseAsyncOptions<T extends (...args: any) => any> {
14
+ initialArgs?: Parameters<T>[0];
15
+ callback?: {
16
+ onSuccess?: (result: T) => void;
17
+ onError?: (error: Error) => void;
18
+ onExecute?: () => void;
19
+ onSettle?: () => void;
20
+ };
21
+ mode?: 'onLoad' | 'onTrigger';
22
+ }
23
+ export declare const useAsync: <T extends (...args: any) => any>(fn: T, opts?: UseAsyncOptions<T>) => {
24
+ execute: (args: Parameters<T>[0]) => Promise<void>;
25
+ isLoading: boolean;
26
+ result: Awaited<ReturnType<T>>;
27
+ error: Error;
28
+ };
29
+ export declare const useQuerySelector: <T extends Element>(selector: string) => T | null;
30
+ export default useQuerySelector;
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- import { useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
2
+ import { useEffect, useLayoutEffect, useMemo, useTransition, useCallback, useRef, useState, } from 'react';
3
3
  export const useClickOutside = (callback = () => alert('clicked outside')) => {
4
4
  const ref = useRef(null);
5
5
  const listener = (e) => {
@@ -51,12 +51,10 @@ export function useMediaQuery(tailwindBreakpoint) {
51
51
  return () => {
52
52
  matchMedia.removeEventListener('change', handleChange);
53
53
  };
54
- // eslint-disable-next-line react-hooks/exhaustive-deps
55
54
  }, [parsedQuery]);
56
55
  return matches;
57
56
  }
58
57
  export function useEffectOnce(effect) {
59
- // eslint-disable-next-line react-hooks/exhaustive-deps
60
58
  useEffect(effect, []);
61
59
  }
62
60
  export function useUpdateEffect(effect, deps) {
@@ -146,3 +144,71 @@ export const useUrlParams = (key, defaultValue) => {
146
144
  };
147
145
  return [value, updateValue];
148
146
  };
147
+ export const useAsync = (fn, opts = {}) => {
148
+ const { initialArgs, callback = {}, mode = 'onTrigger' } = opts;
149
+ const { onSuccess, onError, onExecute, onSettle } = callback;
150
+ const [isLoading, setIsLoading] = useState(false);
151
+ const [result, setValue] = useState(null);
152
+ const [error, setError] = useState(null);
153
+ const [isPending, startTransition] = useTransition();
154
+ const execute = useCallback(async (args) => {
155
+ setIsLoading(true);
156
+ setValue(null);
157
+ setError(null);
158
+ onExecute?.();
159
+ try {
160
+ startTransition(() => {
161
+ (async () => {
162
+ const response = await fn(args);
163
+ setValue(response);
164
+ onSuccess?.(response);
165
+ })();
166
+ });
167
+ }
168
+ catch (error) {
169
+ setError(error);
170
+ onError?.(error);
171
+ }
172
+ finally {
173
+ setIsLoading(false);
174
+ onSettle?.();
175
+ }
176
+ }, [fn, onExecute, onSuccess, onError, onSettle]);
177
+ useIsomorphicEffect(() => {
178
+ if (mode === 'onLoad') {
179
+ execute(initialArgs);
180
+ }
181
+ }, []);
182
+ return {
183
+ execute,
184
+ isLoading: isLoading || isPending,
185
+ result,
186
+ error,
187
+ };
188
+ };
189
+ export const useQuerySelector = (selector) => {
190
+ const [element, setElement] = useState(null);
191
+ const elementRef = useRef(null);
192
+ useLayoutEffect(() => {
193
+ const referenceElement = document.querySelector(selector);
194
+ if (!referenceElement)
195
+ return;
196
+ if (elementRef.current !== referenceElement) {
197
+ elementRef.current = referenceElement;
198
+ setElement(referenceElement);
199
+ }
200
+ const resizeObserver = new ResizeObserver(() => {
201
+ // Only update state if the element reference changes
202
+ if (elementRef.current !== referenceElement) {
203
+ elementRef.current = referenceElement;
204
+ setElement(referenceElement);
205
+ }
206
+ });
207
+ resizeObserver.observe(referenceElement);
208
+ return () => {
209
+ resizeObserver.disconnect();
210
+ };
211
+ }, [selector]);
212
+ return element;
213
+ };
214
+ export default useQuerySelector;
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@sohanemon/utils",
3
- "version": "4.0.16",
3
+ "version": "4.0.19",
4
+ "author": "Sohan Emon <sohanemon@outlook.com>",
4
5
  "description": "",
5
6
  "type": "module",
6
7
  "source": "./src/index.ts",
@@ -14,36 +15,28 @@
14
15
  },
15
16
  "typesVersions": {
16
17
  "*": {
17
- "hooks": [
18
- "dist/hooks/index.d.ts"
19
- ],
20
- "components": [
21
- "dist/components/index.d.ts"
22
- ]
18
+ "core": ["dist/index.d.ts"],
19
+ "hooks": ["dist/hooks/index.d.ts"],
20
+ "components": ["dist/components/index.d.ts"]
23
21
  }
24
22
  },
25
- "files": [
26
- "dist",
27
- "README.md"
28
- ],
23
+ "files": ["dist", "README.md"],
29
24
  "scripts": {
30
25
  "build": "tsc",
31
26
  "build:watch": "tsc --watch",
32
27
  "export": "tsc && npm publish"
33
28
  },
34
- "keywords": [
35
- "utils",
36
- "cn"
37
- ],
38
- "author": "sohanemon",
29
+ "keywords": ["utils", "cn"],
39
30
  "license": "ISC",
40
31
  "devDependencies": {
41
- "typescript": "^5.2.2"
32
+ "typescript": "^5.5.4"
42
33
  },
43
34
  "dependencies": {
44
35
  "@iconify/react": "^4.1.1",
45
- "clsx": "^2.0.0",
46
- "react": "^18.2.0",
36
+ "@types/node": "^22.4.0",
37
+ "@types/react": "^18.3.3",
38
+ "clsx": "^2.1.1",
39
+ "react": "^18.3.1",
47
40
  "tailwind-merge": "^1.14.0"
48
41
  }
49
42
  }