@sohanemon/utils 6.3.8 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,13 +1,51 @@
1
- import { n as Task, t as ScheduleOpts } from "../schedule-CRsY0oqG.cjs";
1
+ import { n as Task, t as ScheduleOpts } from "../schedule-BqFAJlSO.cjs";
2
2
  import * as React from "react";
3
3
 
4
4
  //#region src/hooks/action.d.ts
5
+ /**
6
+ * Type definition for an action function that takes input and returns a promise.
7
+ */
5
8
  type ActionType<Input, Result> = (input: Input) => Promise<Result>;
9
+ /**
10
+ * Options for configuring the useAction hook behavior.
11
+ */
6
12
  interface UseActionOptions<_Input, Result> {
13
+ /** Callback executed when the action succeeds. */
7
14
  onSuccess?: (data: Result) => void;
15
+ /** Callback executed when the action fails. */
8
16
  onError?: (error: Error) => void;
17
+ /** Callback executed when the action completes (success or failure). */
9
18
  onSettled?: () => void;
10
19
  }
20
+ /**
21
+ * Hook for managing async actions with loading states and callbacks.
22
+ *
23
+ * Provides a clean API for executing async operations with built-in state management,
24
+ * error handling, and lifecycle callbacks. Supports both synchronous and asynchronous consumption.
25
+ *
26
+ * @template Input - The type of input the action accepts
27
+ * @template Result - The type of result the action returns
28
+ * @param action - The async function to execute
29
+ * @param options - Configuration options for callbacks
30
+ * @returns Object with execution methods, state, and data
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * const { execute, isLoading, data, error } = useAction(
35
+ * async (userId: string) => {
36
+ * const user = await fetchUser(userId);
37
+ * return user;
38
+ * },
39
+ * {
40
+ * onSuccess: (user) => console.log('User loaded:', user),
41
+ * onError: (err) => console.error('Failed to load user:', err),
42
+ * }
43
+ * );
44
+ *
45
+ * // Execute the action
46
+ * const handleClick = () => execute('user123');
47
+ * ```
48
+ */
11
49
  declare const useAction: <Input, Result>(action: ActionType<Input, Result>, options?: UseActionOptions<Input, Result>) => {
12
50
  execute: (input: Input) => void;
13
51
  executeAsync: (input: Input) => Promise<Result>;
@@ -88,14 +126,46 @@ declare function useSchedule(options?: ScheduleOpts): (task: Task) => void;
88
126
  declare function useScheduledEffect(effect: () => void | (() => void), deps?: React.DependencyList, options?: ScheduleOpts): void;
89
127
  //#endregion
90
128
  //#region src/hooks/scroll-tracker.d.ts
129
+ /**
130
+ * Options for the useScrollTracker hook.
131
+ */
91
132
  interface UseScrollTrackerOptions {
133
+ /** The scroll distance threshold to consider as "scrolled past". Defaults to 300. */
92
134
  threshold?: number;
93
- container?: React.RefObject<HTMLElement | null>;
135
+ /** CSS selector or ref to the scrollable container. Defaults to window. */
136
+ container?: string | React.RefObject<HTMLElement | null>;
94
137
  }
138
+ /**
139
+ * State returned by the useScrollTracker hook.
140
+ */
95
141
  interface ScrollTrackerState {
142
+ /** Whether the scroll position has exceeded the threshold. */
96
143
  scrolledPast: boolean;
144
+ /** The current scroll direction. */
97
145
  direction: 'forward' | 'backward';
98
146
  }
147
+ /**
148
+ * Hook to track scroll position and direction relative to a threshold.
149
+ *
150
+ * Monitors scroll events on a specified container (or window) and provides
151
+ * information about whether the user has scrolled past a threshold and the scroll direction.
152
+ *
153
+ * @param options - Configuration options for scroll tracking
154
+ * @returns Object containing scroll state: scrolledPast and direction
155
+ *
156
+ * @example
157
+ * ```tsx
158
+ * const { scrolledPast, direction } = useScrollTracker({ threshold: 200 });
159
+ *
160
+ * if (scrolledPast) {
161
+ * // Show sticky header or hide elements
162
+ * }
163
+ *
164
+ * if (direction === 'forward') {
165
+ * // User is scrolling down
166
+ * }
167
+ * ```
168
+ */
99
169
  declare const useScrollTracker: ({
100
170
  threshold,
101
171
  container
@@ -106,23 +176,63 @@ declare const useScrollTracker: ({
106
176
  * Hook to detect clicks outside of a referenced element.
107
177
  * @param callback - A function to invoke when a click outside is detected.
108
178
  * @returns A React ref object to attach to the target element.
179
+ *
180
+ * @example
181
+ * ```tsx
182
+ * const ref = useClickOutside(() => {
183
+ * console.log('Clicked outside!');
184
+ * setIsOpen(false);
185
+ * });
186
+ *
187
+ * return <div ref={ref}>Click outside me</div>;
188
+ * ```
109
189
  */
110
190
  declare const useClickOutside: (callback?: () => void) => React.RefObject<HTMLDivElement | null>;
111
191
  /**
112
192
  * Hook to match a media query based on Tailwind CSS breakpoints or custom queries.
113
193
  * @param tailwindBreakpoint - The Tailwind breakpoint or custom query string.
114
194
  * @returns A boolean indicating whether the media query matches.
195
+ *
196
+ * @example
197
+ * ```tsx
198
+ * const isMobile = useMediaQuery('md'); // false on screens >= 768px
199
+ * const isLarge = useMediaQuery('lg'); // true on screens >= 1024px
200
+ * const isDark = useMediaQuery('(prefers-color-scheme: dark)');
201
+ *
202
+ * return (
203
+ * <div className={isMobile ? 'mobile-layout' : 'desktop-layout'}>
204
+ * Content
205
+ * </div>
206
+ * );
207
+ * ```
115
208
  */
116
209
  declare function useMediaQuery(tailwindBreakpoint: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | `(${string})`): boolean;
117
210
  /**
118
211
  * Runs an effect only once when the component mounts.
119
212
  * @param effect - The effect callback function.
213
+ *
214
+ * @example
215
+ * ```tsx
216
+ * useEffectOnce(() => {
217
+ * console.log('Component mounted');
218
+ * // Initialize something once
219
+ * });
220
+ * ```
120
221
  */
121
222
  declare function useEffectOnce(effect: React.EffectCallback): void;
122
223
  /**
123
224
  * Runs an effect only when dependencies update, excluding the initial render.
124
225
  * @param effect - The effect callback function.
125
226
  * @param deps - Dependency array for the effect.
227
+ *
228
+ * @example
229
+ * ```tsx
230
+ * const [count, setCount] = useState(0);
231
+ *
232
+ * useUpdateEffect(() => {
233
+ * console.log('Count updated:', count);
234
+ * }, [count]); // Runs only when count changes, not on mount
235
+ * ```
126
236
  */
127
237
  declare function useUpdateEffect(effect: React.EffectCallback, deps: React.DependencyList): void;
128
238
  /**
@@ -130,16 +240,45 @@ declare function useUpdateEffect(effect: React.EffectCallback, deps: React.Depen
130
240
  * @param state - The state value to debounce.
131
241
  * @param delay - The debounce delay in milliseconds (default: 500ms).
132
242
  * @returns The debounced state value.
243
+ *
244
+ * @example
245
+ * ```tsx
246
+ * const [searchTerm, setSearchTerm] = useState('');
247
+ * const debouncedSearchTerm = useDebounce(searchTerm, 300);
248
+ *
249
+ * useEffect(() => {
250
+ * if (debouncedSearchTerm) {
251
+ * performSearch(debouncedSearchTerm);
252
+ * }
253
+ * }, [debouncedSearchTerm]);
254
+ * ```
133
255
  */
134
256
  declare function useDebounce<T>(state: T, delay?: number): T;
135
257
  /**
136
258
  * Hook to handle effects with layout synchronization in the browser.
259
+ * Uses useLayoutEffect on client, useEffect on server.
260
+ *
261
+ * @example
262
+ * ```tsx
263
+ * useIsomorphicEffect(() => {
264
+ * // This runs after DOM mutations on client, during render on server
265
+ * measureElement();
266
+ * }, [dependencies]);
267
+ * ```
137
268
  */
138
269
  declare const useIsomorphicEffect: typeof React.useLayoutEffect;
139
270
  /**
140
271
  * Hook to invoke a callback after a specified timeout.
141
272
  * @param callback - The callback function to invoke.
142
273
  * @param delay - The timeout delay in milliseconds (default: 1000ms).
274
+ *
275
+ * @example
276
+ * ```tsx
277
+ * useTimeout(() => {
278
+ * console.log('Timeout triggered');
279
+ * setShowMessage(false);
280
+ * }, 2000);
281
+ * ```
143
282
  */
144
283
  declare function useTimeout(callback: () => void, delay?: number | null): void;
145
284
  /**
@@ -147,6 +286,15 @@ declare function useTimeout(callback: () => void, delay?: number | null): void;
147
286
  * @param type - The type of the event to listen for.
148
287
  * @param listener - The event listener callback.
149
288
  * @param options - Options for the event listener.
289
+ *
290
+ * @example
291
+ * ```tsx
292
+ * useWindowEvent('resize', () => {
293
+ * console.log('Window resized');
294
+ * });
295
+ *
296
+ * useWindowEvent('scroll', handleScroll, { passive: true });
297
+ * ```
150
298
  */
151
299
  declare function useWindowEvent<K extends keyof WindowEventMap>(type: K, listener: (this: Window, ev: WindowEventMap[K]) => void, options?: boolean | AddEventListenerOptions): void;
152
300
  /**
@@ -158,6 +306,15 @@ type SessionStorageValue<T> = [T, React.Dispatch<React.SetStateAction<T>>];
158
306
  * @param key - The key for session storage.
159
307
  * @param defaultValue - The default value if no value is found in session storage.
160
308
  * @returns A tuple of the stored value and an updater function.
309
+ *
310
+ * @example
311
+ * ```tsx
312
+ * const [user, setUser] = useSessionStorage('user', { name: '', email: '' });
313
+ *
314
+ * const handleLogin = (userData) => {
315
+ * setUser(userData); // Persists to sessionStorage
316
+ * };
317
+ * ```
161
318
  */
162
319
  declare const useSessionStorage: <T extends Record<string, any>>(key: string, defaultValue: T) => SessionStorageValue<T>;
163
320
  /**
@@ -169,6 +326,15 @@ type LocalStorageValue<T> = [T, React.Dispatch<React.SetStateAction<T>>];
169
326
  * @param key - The key for local storage.
170
327
  * @param defaultValue - The default value if no value is found in local storage.
171
328
  * @returns A tuple of the stored value and an updater function.
329
+ *
330
+ * @example
331
+ * ```tsx
332
+ * const [theme, setTheme] = useLocalStorage('theme', 'light');
333
+ *
334
+ * const toggleTheme = () => {
335
+ * setTheme(prev => prev === 'light' ? 'dark' : 'light');
336
+ * };
337
+ * ```
172
338
  */
173
339
  declare const useLocalStorage: <T extends Record<string, any>>(key: string, defaultValue: T) => LocalStorageValue<T>;
174
340
  /**
@@ -176,27 +342,84 @@ declare const useLocalStorage: <T extends Record<string, any>>(key: string, defa
176
342
  * @param key - The URL parameter key.
177
343
  * @param defaultValue - The default value if the parameter is not present.
178
344
  * @returns A tuple of the parameter value and a setter function.
345
+ *
346
+ * @example
347
+ * ```tsx
348
+ * const [page, setPage] = useUrlParams('page', 1);
349
+ *
350
+ * const nextPage = () => {
351
+ * setPage(prev => prev + 1); // Updates URL: ?page=2
352
+ * };
353
+ * ```
179
354
  */
180
355
  declare const useUrlParams: <T extends string | number | boolean>(key: string, defaultValue: T) => [T, (value: T) => void];
181
356
  /**
182
- * Hook to select a DOM element by CSS selector.
183
- * @param selector - The CSS selector string.
357
+ * Hook to select a DOM element by CSS selector or ref.
358
+ * @param selector - The CSS selector string or React ref object.
184
359
  * @returns The selected DOM element or null if not found.
360
+ *
361
+ * @example
362
+ * ```tsx
363
+ * // Using CSS selector
364
+ * const headerElement = useQuerySelector('.header');
365
+ *
366
+ * // Using ref
367
+ * const ref = useRef<HTMLDivElement>(null);
368
+ * const element = useQuerySelector(ref);
369
+ *
370
+ * useEffect(() => {
371
+ * if (headerElement) {
372
+ * headerElement.style.backgroundColor = 'blue';
373
+ * }
374
+ * }, [headerElement]);
375
+ * ```
185
376
  */
186
- declare const useQuerySelector: <T extends Element>(selector: string) => T | null;
377
+ declare const useQuerySelector: <T extends Element>(selector: string | React.RefObject<T | null>) => T | null;
187
378
  /**
188
379
  * Hook to detect if the code is running on the client side.
189
380
  * @returns A boolean indicating whether the code is running on the client.
381
+ *
382
+ * @example
383
+ * ```tsx
384
+ * const isClient = useIsClient();
385
+ *
386
+ * if (isClient) {
387
+ * // Client-side only code
388
+ * window.addEventListener('resize', handleResize);
389
+ * }
390
+ * ```
190
391
  */
191
392
  declare function useIsClient(): boolean;
192
393
  /**
193
394
  * Hook to lock scroll by disabling body overflow.
395
+ *
396
+ * @example
397
+ * ```tsx
398
+ * const [isModalOpen, setIsModalOpen] = useState(false);
399
+ *
400
+ * if (isModalOpen) {
401
+ * useLockScroll(); // Prevents background scrolling
402
+ * }
403
+ *
404
+ * return <Modal open={isModalOpen} />;
405
+ * ```
194
406
  */
195
407
  declare function useLockScroll(): void;
196
408
  /**
197
409
  * Hook to copy text to the clipboard and track the copy status.
198
410
  * @param timeout - The timeout duration in milliseconds to reset the copy status (default: 2000ms).
199
411
  * @returns An object with the `isCopied` state and `copy` function.
412
+ *
413
+ * @example
414
+ * ```tsx
415
+ * const { isCopied, copy } = useCopyToClipboard();
416
+ *
417
+ * return (
418
+ * <button onClick={() => copy('Hello World!')}>
419
+ * {isCopied ? 'Copied!' : 'Copy Text'}
420
+ * </button>
421
+ * );
422
+ * ```
200
423
  */
201
424
  declare function useCopyToClipboard({
202
425
  timeout
@@ -207,19 +430,37 @@ declare function useCopyToClipboard({
207
430
  copy: (value: string) => void;
208
431
  };
209
432
  /**
210
- * Properties for height calculation.
433
+ * Configuration options for height calculation.
211
434
  */
212
435
  type CalculationProps2 = {
436
+ /** Array of element IDs whose heights should be considered in calculation. */
213
437
  blockIds: string[];
438
+ /** Whether to recalculate on resize. If string, specifies ID of element to observe for changes. */
214
439
  dynamic?: boolean | string;
440
+ /** Additional margin to add/subtract from calculation. */
215
441
  margin?: number;
442
+ /** Whether to subtract block heights from viewport (true) or add them (false). */
216
443
  substract?: boolean;
217
444
  };
218
445
  /**
446
+ * Hook to calculate available height for an element based on viewport and other element heights.
447
+ *
448
+ * Useful for creating full-height layouts where you need to account for fixed headers,
449
+ * footers, or other elements that take up vertical space.
219
450
  *
220
- * Hook to calculate the height of an element based on viewport and other block heights.
221
451
  * @param params - Configuration object for height calculation.
222
- * @returns The calculated height.
452
+ * @returns The calculated height in pixels.
453
+ *
454
+ * @example
455
+ * ```tsx
456
+ * const contentHeight = useHeightCalculation({
457
+ * blockIds: ['header', 'footer'],
458
+ * margin: 20,
459
+ * dynamic: true
460
+ * });
461
+ *
462
+ * return <div style={{ height: contentHeight }}>Content</div>;
463
+ * ```
223
464
  */
224
465
  declare const useHeightCalculation: ({
225
466
  blockIds,
@@ -228,13 +469,18 @@ declare const useHeightCalculation: ({
228
469
  dynamic
229
470
  }: CalculationProps2) => number;
230
471
  /**
231
- * Properties for DOM calculation.
472
+ * Configuration options for DOM dimension calculation.
232
473
  */
233
474
  type CalculationProps = {
475
+ /** Array of element IDs whose dimensions should be considered. */
234
476
  blockIds: string[];
477
+ /** Whether to recalculate on resize. If string, specifies ID of element to observe. */
235
478
  dynamic?: boolean | string;
479
+ /** Additional margin to add/subtract from calculations. */
236
480
  margin?: number;
481
+ /** Whether to subtract block dimensions from viewport (true) or add them (false). */
237
482
  substract?: boolean;
483
+ /** Callback fired whenever dimensions change with detailed results. */
238
484
  onChange?: (results: {
239
485
  blocksHeight: number;
240
486
  blocksWidth: number;
@@ -243,9 +489,27 @@ type CalculationProps = {
243
489
  }) => void;
244
490
  };
245
491
  /**
246
- * Hook to calculate dimensions (height and width) of an element based on viewport and other block dimensions.
492
+ * Hook to calculate available dimensions for an element based on viewport and other element dimensions.
493
+ *
494
+ * Provides both height and width calculations with optional change callbacks.
495
+ * Useful for responsive layouts that need to adapt to dynamic content or viewport changes.
496
+ *
247
497
  * @param params - Configuration object for dimension calculation.
248
- * @returns An object containing the calculated height and width.
498
+ * @returns An object containing the calculated height and width in pixels.
499
+ *
500
+ * @example
501
+ * ```tsx
502
+ * const { height, width } = useDomCalculation({
503
+ * blockIds: ['sidebar', 'header'],
504
+ * margin: 10,
505
+ * dynamic: true,
506
+ * onChange: ({ remainingWidth, remainingHeight }) => {
507
+ * console.log(`Available: ${remainingWidth}x${remainingHeight}`);
508
+ * }
509
+ * });
510
+ *
511
+ * return <div style={{ height, width }}>Responsive content</div>;
512
+ * ```
249
513
  */
250
514
  declare const useDomCalculation: ({
251
515
  blockIds,
@@ -258,16 +522,55 @@ declare const useDomCalculation: ({
258
522
  width: number;
259
523
  };
260
524
  /**
261
- * Hook to detect if the user is scrolling.
262
- * @returns An object containing the isScrolling state and a ref to the scrollable container.
525
+ * Hook to detect if the user is currently scrolling within a container.
526
+ *
527
+ * Tracks scroll events and provides a debounced "is scrolling" state that
528
+ * becomes false 150ms after the last scroll event. Useful for showing/hiding
529
+ * scroll indicators, triggering animations, or optimizing performance during scroll.
530
+ *
531
+ * @returns An object containing:
532
+ * - `isScrolling`: Boolean indicating if scrolling is currently active
533
+ * - `scrollableContainerRef`: Ref to attach to the scrollable element
534
+ *
535
+ * @example
536
+ * ```tsx
537
+ * const { isScrolling, scrollableContainerRef } = useIsScrolling();
538
+ *
539
+ * return (
540
+ * <div ref={scrollableContainerRef}>
541
+ * {isScrolling && <ScrollIndicator />}
542
+ * <Content />
543
+ * </div>
544
+ * );
545
+ * ```
263
546
  */
264
547
  declare const useIsScrolling: () => {
265
548
  isScrolling: boolean;
266
549
  scrollableContainerRef: React.RefObject<HTMLElement | null>;
267
550
  };
268
551
  /**
269
- * Hook to detect if the user is at the top of the page.
270
- * @returns An object containing the isAtTop state and a ref to the scrollable container.
552
+ * Hook to detect if the scroll position is at the top of a container.
553
+ *
554
+ * Monitors scroll position and determines if the user has scrolled past
555
+ * a threshold from the top. Useful for sticky headers, navigation states,
556
+ * or triggering actions when reaching the top of content.
557
+ *
558
+ * @param offset - Optional offset in pixels from the top to consider as "at top" (default: 10).
559
+ * @returns An object containing:
560
+ * - `isAtTop`: Boolean indicating if scroll position is at the top
561
+ * - `scrollableContainerRef`: Ref to attach to the scrollable element
562
+ *
563
+ * @example
564
+ * ```tsx
565
+ * const { isAtTop, scrollableContainerRef } = useIsAtTop({ offset: 50 });
566
+ *
567
+ * return (
568
+ * <div ref={scrollableContainerRef}>
569
+ * <Header className={isAtTop ? 'transparent' : 'solid'} />
570
+ * <Content />
571
+ * </div>
572
+ * );
573
+ * ```
271
574
  */
272
575
  declare const useIsAtTop: ({
273
576
  offset
@@ -282,8 +585,20 @@ interface UseIntersectionOptions extends IntersectionObserverInit {
282
585
  onInteractionEnd?: () => void;
283
586
  }
284
587
  /**
285
- * React hook that tracks when an element enters or leaves the viewport
286
- * using the Intersection Observer API.
588
+ * React hook that tracks when an element enters or leaves the viewport using the Intersection Observer API.
589
+ *
590
+ * Provides efficient viewport detection for lazy loading, animations, analytics,
591
+ * and other effects that should trigger based on element visibility.
592
+ *
593
+ * @param options - Configuration for the intersection observer.
594
+ * @param options.threshold - How much of the element must be visible (0-1) to trigger intersection.
595
+ * @param options.root - The element to use as the viewport for checking visibility.
596
+ * @param options.rootMargin - Margin around the root element for intersection calculation.
597
+ * @param options.onInteractionStart - Callback when element enters viewport.
598
+ * @param options.onInteractionEnd - Callback when element leaves viewport.
599
+ * @returns Object containing:
600
+ * - `ref`: React ref to attach to the observed element.
601
+ * - `isIntersecting`: Whether the element is currently visible in the viewport.
287
602
  *
288
603
  * @example
289
604
  * ```tsx
@@ -293,13 +608,12 @@ interface UseIntersectionOptions extends IntersectionObserverInit {
293
608
  * onInteractionEnd: () => console.log('🙈 Element left viewport'),
294
609
  * });
295
610
  *
296
- * return <div ref={ref}>Watch me</div>;
611
+ * return (
612
+ * <div ref={ref} className={isIntersecting ? 'visible' : 'hidden'}>
613
+ * Watch me fade in/out
614
+ * </div>
615
+ * );
297
616
  * ```
298
- *
299
- * @param options - Configuration for the intersection observer.
300
- * @returns Object containing:
301
- * - `ref`: React ref to attach to the observed element.
302
- * - `isIntersecting`: Whether the element is currently visible.
303
617
  */
304
618
  declare const useIntersection: ({
305
619
  threshold,