@sohanemon/utils 4.0.22 → 4.0.23

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.
@@ -0,0 +1,20 @@
1
+ type ActionType<Input, Result> = (input: Input) => Promise<Result>;
2
+ interface UseActionOptions<_Input, Result> {
3
+ onSuccess?: (data: Result) => void;
4
+ onError?: (error: Error) => void;
5
+ onSettled?: () => void;
6
+ }
7
+ export declare const useAction: <Input, Result>(action: ActionType<Input, Result>, options?: UseActionOptions<Input, Result>) => {
8
+ execute: (input: Input) => void;
9
+ executeAsync: (input: Input) => Promise<Result>;
10
+ reset: () => void;
11
+ useExecute: (input: Input) => void;
12
+ data: Result;
13
+ error: Error;
14
+ input: Input;
15
+ isIdle: boolean;
16
+ isLoading: boolean;
17
+ isSuccess: boolean;
18
+ isError: boolean;
19
+ };
20
+ export {};
@@ -0,0 +1,84 @@
1
+ import * as React from 'react';
2
+ import { useIsomorphicEffect } from '.';
3
+ export const useAction = (action, options) => {
4
+ const [status, setStatus] = React.useState('idle');
5
+ const [data, setData] = React.useState(null);
6
+ const [error, setError] = React.useState(null);
7
+ const [clientInput, setClientInput] = React.useState(undefined);
8
+ const [isTransitioning, startTransition] = React.useTransition();
9
+ // Derived state booleans
10
+ const isIdle = status === 'idle';
11
+ const isLoading = status === 'loading' || isTransitioning;
12
+ const isSuccess = status === 'success';
13
+ const isError = status === 'error';
14
+ const handleSuccess = React.useCallback((result) => {
15
+ setData(result);
16
+ setStatus('success');
17
+ options?.onSuccess?.(result); // Call onSuccess if provided
18
+ options?.onSettled?.(); // Call onSettled if provided
19
+ }, [options]);
20
+ const handleError = React.useCallback((err) => {
21
+ setError(err);
22
+ setStatus('error');
23
+ options?.onError?.(err); // Call onError if provided
24
+ options?.onSettled?.(); // Call onSettled if provided
25
+ }, [options]);
26
+ // Executes the action with the provided input, updating state accordingly
27
+ const execute = React.useCallback((input) => {
28
+ setClientInput(input);
29
+ setStatus('loading');
30
+ setError(null);
31
+ startTransition(() => {
32
+ action(input).then(handleSuccess).catch(handleError);
33
+ });
34
+ }, [action, handleSuccess, handleError]);
35
+ // Asynchronous version of execute for promise-based consumption
36
+ const executeAsync = React.useCallback((input) => {
37
+ return new Promise((resolve, reject) => {
38
+ setClientInput(input);
39
+ setStatus('loading');
40
+ setError(null);
41
+ startTransition(() => {
42
+ action(input)
43
+ .then((res) => {
44
+ handleSuccess(res);
45
+ resolve(res);
46
+ })
47
+ .catch((err) => {
48
+ handleError(err);
49
+ reject(err);
50
+ });
51
+ });
52
+ });
53
+ }, [action, handleSuccess, handleError]);
54
+ // Resets the hook's state to its initial "idle" status
55
+ const reset = React.useCallback(() => {
56
+ setStatus('idle');
57
+ setData(null);
58
+ setError(null);
59
+ setClientInput(undefined);
60
+ }, []);
61
+ // Hook to execute the action automatically on mount
62
+ const useExecute = (input) => {
63
+ useIsomorphicEffect(() => {
64
+ execute(input);
65
+ }, []);
66
+ };
67
+ return {
68
+ // Methods to trigger action
69
+ execute,
70
+ executeAsync,
71
+ reset,
72
+ // Hook for auto execution on mount
73
+ useExecute,
74
+ // Data and error objects
75
+ data,
76
+ error,
77
+ input: clientInput,
78
+ // Status booleans
79
+ isIdle,
80
+ isLoading,
81
+ isSuccess,
82
+ isError,
83
+ };
84
+ };
@@ -0,0 +1,17 @@
1
+ interface UseAsyncOptions<T extends (...args: any) => any> {
2
+ initialArgs?: Parameters<T>[0];
3
+ callback?: {
4
+ onSuccess?: (result: T) => void;
5
+ onError?: (error: Error) => void;
6
+ onExecute?: () => void;
7
+ onSettle?: () => void;
8
+ };
9
+ mode?: 'onLoad' | 'onTrigger';
10
+ }
11
+ export declare const useAsync: <T extends (...args: any) => any>(fn: T, opts?: UseAsyncOptions<T>) => {
12
+ execute: (args: Parameters<T>[0]) => Promise<void>;
13
+ isLoading: boolean;
14
+ result: Awaited<ReturnType<T>>;
15
+ error: Error;
16
+ };
17
+ export {};
@@ -0,0 +1,44 @@
1
+ import { useState, useTransition, useCallback } from 'react';
2
+ import { useIsomorphicEffect } from '.';
3
+ export const useAsync = (fn, opts = {}) => {
4
+ const { initialArgs, callback = {}, mode = 'onTrigger' } = opts;
5
+ const { onSuccess, onError, onExecute, onSettle } = callback;
6
+ const [isLoading, setIsLoading] = useState(false);
7
+ const [result, setValue] = useState(null);
8
+ const [error, setError] = useState(null);
9
+ const [isPending, startTransition] = useTransition();
10
+ const execute = useCallback(async (args) => {
11
+ setIsLoading(true);
12
+ setValue(null);
13
+ setError(null);
14
+ onExecute?.();
15
+ try {
16
+ startTransition(() => {
17
+ (async () => {
18
+ const response = await fn(args);
19
+ setValue(response);
20
+ onSuccess?.(response);
21
+ })();
22
+ });
23
+ }
24
+ catch (error) {
25
+ setError(error);
26
+ onError?.(error);
27
+ }
28
+ finally {
29
+ setIsLoading(false);
30
+ onSettle?.();
31
+ }
32
+ }, [fn, onExecute, onSuccess, onError, onSettle]);
33
+ useIsomorphicEffect(() => {
34
+ if (mode === 'onLoad') {
35
+ execute(initialArgs);
36
+ }
37
+ }, []);
38
+ return {
39
+ execute,
40
+ isLoading: isLoading || isPending,
41
+ result,
42
+ error,
43
+ };
44
+ };
@@ -1,32 +1,16 @@
1
- import { type Dispatch, type EffectCallback, type SetStateAction, useEffect } from 'react';
1
+ import { type Dispatch, type EffectCallback, type SetStateAction, useLayoutEffect } from 'react';
2
+ export * from './action';
2
3
  export declare const useClickOutside: (callback?: () => void) => import("react").MutableRefObject<HTMLDivElement>;
3
4
  export declare function useMediaQuery(tailwindBreakpoint: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | `(${string})`): boolean;
4
5
  export declare function useEffectOnce(effect: EffectCallback): void;
5
6
  export declare function useUpdateEffect(effect: EffectCallback, deps: any[]): void;
6
7
  export declare function useDebounce<T>(state: T, delay?: number): T;
7
- export declare const useIsomorphicEffect: typeof useEffect;
8
+ export declare const useIsomorphicEffect: typeof useLayoutEffect;
8
9
  export declare function useTimeout(callback: () => void, delay?: number | null): void;
9
10
  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
11
  type LocalStorageValue<T> = [T, Dispatch<SetStateAction<T>>];
11
12
  export declare const useLocalStorage: <T extends Record<string, any>>(key: string, defaultValue: T) => LocalStorageValue<T>;
12
13
  export declare const useUrlParams: <T extends string | number | boolean>(key: string, defaultValue: T) => [T, (value: T) => void];
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
14
  export declare const useQuerySelector: <T extends Element>(selector: string) => T | null;
30
15
  export declare function useIsClient(): boolean;
31
16
  export declare function useLockScroll(): void;
32
- export {};
@@ -1,5 +1,6 @@
1
1
  'use client';
2
- import { useEffect, useLayoutEffect, useMemo, useTransition, useCallback, useRef, useState, } from 'react';
2
+ import { useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
3
+ export * from './action';
3
4
  export const useClickOutside = (callback = () => alert('clicked outside')) => {
4
5
  const ref = useRef(null);
5
6
  const listener = (e) => {
@@ -147,48 +148,6 @@ export const useUrlParams = (key, defaultValue) => {
147
148
  };
148
149
  return [value, updateValue];
149
150
  };
150
- export const useAsync = (fn, opts = {}) => {
151
- const { initialArgs, callback = {}, mode = 'onTrigger' } = opts;
152
- const { onSuccess, onError, onExecute, onSettle } = callback;
153
- const [isLoading, setIsLoading] = useState(false);
154
- const [result, setValue] = useState(null);
155
- const [error, setError] = useState(null);
156
- const [isPending, startTransition] = useTransition();
157
- const execute = useCallback(async (args) => {
158
- setIsLoading(true);
159
- setValue(null);
160
- setError(null);
161
- onExecute?.();
162
- try {
163
- startTransition(() => {
164
- (async () => {
165
- const response = await fn(args);
166
- setValue(response);
167
- onSuccess?.(response);
168
- })();
169
- });
170
- }
171
- catch (error) {
172
- setError(error);
173
- onError?.(error);
174
- }
175
- finally {
176
- setIsLoading(false);
177
- onSettle?.();
178
- }
179
- }, [fn, onExecute, onSuccess, onError, onSettle]);
180
- useIsomorphicEffect(() => {
181
- if (mode === 'onLoad') {
182
- execute(initialArgs);
183
- }
184
- }, []);
185
- return {
186
- execute,
187
- isLoading: isLoading || isPending,
188
- result,
189
- error,
190
- };
191
- };
192
151
  export const useQuerySelector = (selector) => {
193
152
  const [element, setElement] = useState(null);
194
153
  const elementRef = useRef(null);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sohanemon/utils",
3
- "version": "4.0.22",
3
+ "version": "4.0.23",
4
4
  "author": "Sohan Emon <sohanemon@outlook.com>",
5
5
  "description": "",
6
6
  "type": "module",