@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.
@@ -2,9 +2,61 @@ import { ClassValue } from "clsx";
2
2
  import * as React from "react";
3
3
 
4
4
  //#region src/functions/cookie.d.ts
5
+
6
+ /**
7
+ * Sets a client-side cookie with optional expiration and path.
8
+ *
9
+ * @param name - The name of the cookie
10
+ * @param value - The value to store in the cookie
11
+ * @param days - Optional number of days until the cookie expires
12
+ * @param path - Optional path for the cookie (defaults to '/')
13
+ *
14
+ * @example
15
+ * // Set a cookie that expires in 7 days
16
+ * setClientSideCookie('userId', '12345', 7);
17
+ *
18
+ * @example
19
+ * // Set a session cookie (no expiration)
20
+ * setClientSideCookie('sessionId', 'abc123');
21
+ */
5
22
  declare const setClientSideCookie: (name: string, value: string, days?: number, path?: string) => void;
23
+ /**
24
+ * Deletes a client-side cookie by setting its expiration to a past date.
25
+ *
26
+ * @param name - The name of the cookie to delete
27
+ * @param path - Optional path for the cookie (defaults to '/')
28
+ *
29
+ * @example
30
+ * // Delete a cookie
31
+ * deleteClientSideCookie('userId');
32
+ */
6
33
  declare const deleteClientSideCookie: (name: string, path?: string) => void;
34
+ /**
35
+ * Checks if a client-side cookie exists.
36
+ *
37
+ * @param name - The name of the cookie to check
38
+ * @returns True if the cookie exists, false otherwise
39
+ *
40
+ * @example
41
+ * // Check if a cookie exists
42
+ * if (hasClientSideCookie('userId')) {
43
+ * console.log('User is logged in');
44
+ * }
45
+ */
7
46
  declare const hasClientSideCookie: (name: string) => boolean;
47
+ /**
48
+ * Retrieves the value of a client-side cookie.
49
+ *
50
+ * @param name - The name of the cookie to retrieve
51
+ * @returns An object containing the cookie value, or undefined if not found
52
+ *
53
+ * @example
54
+ * // Get a cookie value
55
+ * const { value } = getClientSideCookie('userId');
56
+ * if (value) {
57
+ * console.log('User ID:', value);
58
+ * }
59
+ */
8
60
  declare const getClientSideCookie: (name: string) => {
9
61
  value: string | undefined;
10
62
  };
@@ -40,20 +92,52 @@ type TMerged<T> = [T] extends [Array<any>] ? { [K in keyof T]: TMerged<T[K]> } :
40
92
  * @returns The merged object with proper typing
41
93
  *
42
94
  * @example
43
- * // Basic merge
95
+ * // Basic shallow merge
44
96
  * deepmerge({ a: 1 }, { b: 2 }) // { a: 1, b: 2 }
45
97
  *
46
98
  * @example
47
- * // Nested merge
48
- * deepmerge({ a: { x: 1 } }, { a: { y: 2 } }) // { a: { x: 1, y: 2 } }
99
+ * // Deep merge of nested objects
100
+ * deepmerge({ user: { name: 'John' } }, { user: { age: 30 } })
101
+ * // { user: { name: 'John', age: 30 } }
102
+ *
103
+ * @example
104
+ * // Array concatenation
105
+ * deepmerge({ tags: ['react'] }, { tags: ['typescript'] }, { arrayMerge: 'concat' })
106
+ * // { tags: ['react', 'typescript'] }
49
107
  *
50
108
  * @example
51
- * // Array concat
52
- * deepmerge({ arr: [1] }, { arr: [2] }, { arrayMerge: 'concat' }) // { arr: [1, 2] }
109
+ * // Array replacement (default)
110
+ * deepmerge({ items: [1, 2] }, { items: [3, 4] })
111
+ * // { items: [3, 4] }
53
112
  *
54
113
  * @example
55
- * // Sources with extra properties
56
- * deepmerge({ a: 1 }, { b: 2, c: 3 }) // { a: 1, b: 2, c: 3 }
114
+ * // Custom array merging
115
+ * deepmerge(
116
+ * { scores: [85, 90] },
117
+ * { scores: [95] },
118
+ * { arrayMerge: (target, source) => [...target, ...source] }
119
+ * )
120
+ * // { scores: [85, 90, 95] }
121
+ *
122
+ * @example
123
+ * // Configuration merging
124
+ * const defaultConfig = { theme: 'light', features: { darkMode: false } };
125
+ * const userConfig = { theme: 'dark', features: { darkMode: true, animations: true } };
126
+ * deepmerge(defaultConfig, userConfig);
127
+ * // { theme: 'dark', features: { darkMode: true, animations: true } }
128
+ *
129
+ * @example
130
+ * // State updates in reducers
131
+ * const initialState = { user: { profile: { name: '' } }, settings: {} };
132
+ * const action = { user: { profile: { name: 'Alice' } }, settings: { theme: 'dark' } };
133
+ * const newState = deepmerge(initialState, action);
134
+ *
135
+ * @example
136
+ * // Merging API responses
137
+ * const cachedData = { posts: [{ id: 1, title: 'Old' }] };
138
+ * const freshData = { posts: [{ id: 1, title: 'Updated', author: 'Bob' }] };
139
+ * deepmerge(cachedData, freshData);
140
+ * // { posts: [{ id: 1, title: 'Updated', author: 'Bob' }] }
57
141
  */
58
142
  declare function deepmerge<T extends Record<string, any>, S extends Record<string, any>[]>(target: T, ...sources: S): TMerged<T | S[number]>;
59
143
  declare function deepmerge<T extends Record<string, any>, S extends Record<string, any>[]>(target: T, sources: S, options?: {
@@ -72,8 +156,42 @@ type Hydrate<T> = T extends null ? undefined : T extends (infer U)[] ? Hydrate<U
72
156
  * @returns Same type as input, but with all nulls replaced by undefined
73
157
  *
74
158
  * @example
75
- * hydrate({ a: null, b: 'test' }) // { a: undefined, b: 'test' }
76
- * hydrate([null, 1, { c: null }]) // [undefined, 1, { c: undefined }]
159
+ * ```ts
160
+ * // Basic object hydration
161
+ * hydrate({ name: null, age: 25 }) // { name: undefined, age: 25 }
162
+ *
163
+ * // Nested object hydration
164
+ * hydrate({
165
+ * user: { email: null, profile: { avatar: null } },
166
+ * settings: { theme: 'dark' }
167
+ * })
168
+ * // { user: { email: undefined, profile: { avatar: undefined } }, settings: { theme: 'dark' } }
169
+ *
170
+ * // Array hydration
171
+ * hydrate([null, 'hello', null, 42]) // [undefined, 'hello', undefined, 42]
172
+ *
173
+ * // Mixed data structures
174
+ * hydrate({
175
+ * posts: [null, { title: 'Hello', content: null }],
176
+ * metadata: { published: null, tags: ['react', null] }
177
+ * })
178
+ * ```
179
+ *
180
+ * @example
181
+ * ```ts
182
+ * // API response normalization
183
+ * const apiResponse = await fetch('/api/user');
184
+ * const rawData = await apiResponse.json(); // May contain null values
185
+ * const normalizedData = hydrate(rawData); // Convert nulls to undefined
186
+ *
187
+ * // Database result processing
188
+ * const dbResult = query('SELECT * FROM users'); // Some fields may be NULL
189
+ * const cleanData = hydrate(dbResult); // Normalize for consistent handling
190
+ *
191
+ * // Form data sanitization
192
+ * const formData = getFormValues(); // May have null values from empty fields
193
+ * const sanitizedData = hydrate(formData); // Prepare for validation/state
194
+ * ```
77
195
  */
78
196
  declare function hydrate<T>(data: T): Hydrate<T>;
79
197
  //#endregion
@@ -157,14 +275,32 @@ declare function getObjectValue<T, S extends string>(obj: T, path: S): GetValue<
157
275
  * @returns The same object/function, augmented with the given properties
158
276
  *
159
277
  * @example
160
- * // Extend an object
161
- * const obj = extendProps({ a: 1 }, { b: "hello" });
162
- * // obj has { a: number; b: string }
163
- *
164
- * // Extend a function
165
- * const fn = (x: number) => x * 2;
166
- * const enhanced = extendProps(fn, { name: "doubler" });
167
- * // enhanced is callable and also has { name: string }
278
+ * ```ts
279
+ * // Extend a plain object
280
+ * const config = extendProps({ apiUrl: '/api' }, { timeout: 5000 });
281
+ * // config has both apiUrl and timeout properties
282
+ *
283
+ * // Extend a function with metadata
284
+ * const fetchData = (url: string) => fetch(url).then(r => r.json());
285
+ * const enhancedFetch = extendProps(fetchData, {
286
+ * description: 'Data fetching utility',
287
+ * version: '1.0'
288
+ * });
289
+ * // enhancedFetch is callable and has description/version properties
290
+ *
291
+ * // Create plugin system
292
+ * const basePlugin = { name: 'base', enabled: true };
293
+ * const authPlugin = extendProps(basePlugin, {
294
+ * authenticate: (token: string) => validateToken(token)
295
+ * });
296
+ *
297
+ * // Build configuration objects
298
+ * const defaultSettings = { theme: 'light', lang: 'en' };
299
+ * const userSettings = extendProps(defaultSettings, {
300
+ * theme: 'dark',
301
+ * notifications: true
302
+ * });
303
+ * ```
168
304
  */
169
305
  declare function extendProps<T extends object, P$1 extends object>(base: T, props: P$1): T & P$1;
170
306
  //#endregion
@@ -195,11 +331,52 @@ declare function extendProps<T extends object, P$1 extends object>(base: T, prop
195
331
  *
196
332
  * @example
197
333
  * ```ts
334
+ * // Poll for job completion
198
335
  * const job = await poll(async () => {
199
336
  * const status = await getJobStatus();
200
337
  * return status === 'done' ? status : null;
201
338
  * }, { interval: 3000, timeout: 60000 });
202
339
  * ```
340
+ *
341
+ * @example
342
+ * ```ts
343
+ * // Wait for API endpoint to be ready
344
+ * const apiReady = await poll(async () => {
345
+ * try {
346
+ * await fetch('/api/health');
347
+ * return true;
348
+ * } catch {
349
+ * return null;
350
+ * }
351
+ * }, { interval: 1000, timeout: 30000 });
352
+ * ```
353
+ *
354
+ * @example
355
+ * ```ts
356
+ * // Poll with abort signal for cancellation
357
+ * const controller = new AbortController();
358
+ * setTimeout(() => controller.abort(), 10000); // Cancel after 10s
359
+ *
360
+ * try {
361
+ * const result = await poll(
362
+ * () => checkExternalService(),
363
+ * { interval: 2000, signal: controller.signal }
364
+ * );
365
+ * } catch (err) {
366
+ * if (err.name === 'AbortError') {
367
+ * console.log('Polling was cancelled');
368
+ * }
369
+ * }
370
+ * ```
371
+ *
372
+ * @example
373
+ * ```ts
374
+ * // Poll for user action completion
375
+ * const userConfirmed = await poll(async () => {
376
+ * const confirmations = await getPendingConfirmations();
377
+ * return confirmations.length > 0 ? confirmations[0] : null;
378
+ * }, { interval: 5000, timeout: 300000 }); // 5 min timeout
379
+ * ```
203
380
  */
204
381
  declare function poll<T>(cond: () => Promise<T | null | false | undefined>, {
205
382
  interval,
@@ -214,16 +391,44 @@ declare function poll<T>(cond: () => Promise<T | null | false | undefined>, {
214
391
  }>): Promise<T>;
215
392
  //#endregion
216
393
  //#region src/functions/schedule.d.ts
394
+ /**
395
+ * A task function that can be synchronous or asynchronous.
396
+ */
217
397
  type Task = () => Promise<void> | void;
398
+ /**
399
+ * Options for configuring the schedule function.
400
+ */
218
401
  interface ScheduleOpts {
402
+ /** Number of retry attempts on failure. Defaults to 0. */
219
403
  retry?: number;
404
+ /** Delay in milliseconds between retries. Defaults to 0. */
220
405
  delay?: number;
406
+ /** Maximum time in milliseconds to wait for the task to complete. */
221
407
  timeout?: number;
222
408
  }
223
409
  /**
224
- * Runs a function asynchronously in the background.
225
- * Returns immediately, retries on failure if configured.
226
- * Logs total time taken.
410
+ * Runs a function asynchronously in the background without blocking the main thread.
411
+ *
412
+ * Executes the task immediately using setTimeout, with optional retry logic on failure.
413
+ * Useful for non-critical operations like analytics, logging, or background processing.
414
+ * Logs execution time and retry attempts to the console.
415
+ *
416
+ * @param task - The function to execute asynchronously
417
+ * @param options - Configuration options for retries and timing
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * // Simple background task
422
+ * schedule(() => {
423
+ * console.log('Background work done');
424
+ * });
425
+ *
426
+ * // Task with retry on failure
427
+ * schedule(
428
+ * () => sendAnalytics(),
429
+ * { retry: 3, delay: 1000 }
430
+ * );
431
+ * ```
227
432
  */
228
433
  declare function schedule(task: Task, options?: ScheduleOpts): void;
229
434
  //#endregion
@@ -237,11 +442,62 @@ declare function schedule(task: Task, options?: ScheduleOpts): void;
237
442
  *
238
443
  * @example
239
444
  * ```ts
240
- * const [err, value] = shield(() => riskySync());
241
- * if (err) console.error(err);
445
+ * // Synchronous error handling
446
+ * const [err, value] = shield(() => {
447
+ * if (Math.random() > 0.5) throw new Error('Random failure');
448
+ * return 'success';
449
+ * });
450
+ * if (err) {
451
+ * console.error('Operation failed:', err);
452
+ * } else {
453
+ * console.log('Result:', value);
454
+ * }
455
+ *
456
+ * // Asynchronous error handling
457
+ * const [asyncErr, result] = await shield(async () => {
458
+ * const response = await fetch('/api/data');
459
+ * if (!response.ok) throw new Error('API error');
460
+ * return response.json();
461
+ * });
462
+ * if (asyncErr) {
463
+ * console.error('API call failed:', asyncErr);
464
+ * } else {
465
+ * processData(result);
466
+ * }
467
+ *
468
+ * // API calls with fallbacks
469
+ * const [fetchErr, data] = await shield(fetchUserData(userId));
470
+ * const userData = fetchErr ? getCachedUserData(userId) : data;
471
+ *
472
+ * // File operations
473
+ * const [fileErr, content] = shield(() => readFileSync('config.json'));
474
+ * if (fileErr) {
475
+ * console.warn('Could not read config, using defaults');
476
+ * return defaultConfig;
477
+ * }
478
+ * ```
242
479
  *
243
- * const [asyncErr, result] = await shield(fetchData());
244
- * if (asyncErr) throw asyncErr;
480
+ * @example
481
+ * ```ts
482
+ * // In async functions
483
+ * async function safeApiCall() {
484
+ * const [err, result] = await shield(callExternalAPI());
485
+ * if (err) {
486
+ * await logError(err);
487
+ * return null;
488
+ * }
489
+ * return result;
490
+ * }
491
+ *
492
+ * // In event handlers
493
+ * function handleSubmit(formData) {
494
+ * const [validationErr, validatedData] = shield(() => validateForm(formData));
495
+ * if (validationErr) {
496
+ * showValidationError(validationErr);
497
+ * return;
498
+ * }
499
+ * submitData(validatedData);
500
+ * }
245
501
  * ```
246
502
  */
247
503
  declare function shield<T, E = Error>(operation: Promise<T>): Promise<[E | null, T | null]>;
@@ -253,6 +509,12 @@ declare function shield<T, E = Error>(operation: () => T): [E | null, T | null];
253
509
  *
254
510
  * @param {...ClassValue[]} inputs - Class names to merge.
255
511
  * @returns {string} - A string of merged class names.
512
+ *
513
+ * @example
514
+ * ```ts
515
+ * cn('px-2 py-1', 'bg-red-500') // 'px-2 py-1 bg-red-500'
516
+ * cn('px-2', 'px-4') // 'px-4' (Tailwind resolves conflicts)
517
+ * ```
256
518
  */
257
519
  declare function cn(...inputs: ClassValue[]): string;
258
520
  /**
@@ -263,16 +525,40 @@ declare function cn(...inputs: ClassValue[]): string;
263
525
  * @param href - The target URL.
264
526
  * @param path - The current browser path.
265
527
  * @returns - True if the navigation is active, false otherwise.
528
+ *
529
+ * @example
530
+ * ```ts
531
+ * isNavActive('/about', '/about/team') // true
532
+ * isNavActive('/contact', '/about') // false
533
+ * ```
266
534
  */
267
535
  declare function isNavActive(href: string, path: string): boolean;
268
536
  /**
269
537
  * Checks if a link is active, considering optional localization prefixes.
270
538
  *
271
- * @param {Object} params - Parameters object.
272
- * @param {string} params.path - The target path of the link.
273
- * @param {string} params.currentPath - The current browser path.
274
- * @param {string[]} [params.locales=['en', 'es', 'de', 'zh', 'bn', 'fr', 'it', 'nl']] - Supported locale prefixes.
275
- * @returns {boolean} - True if the link is active, false otherwise.
539
+ * Compares paths while ignoring locale prefixes (e.g., /en/, /fr/) for consistent
540
+ * navigation highlighting across different language versions of the same page.
541
+ *
542
+ * @param params - Parameters object.
543
+ * @param params.path - The target path of the link.
544
+ * @param params.currentPath - The current browser path.
545
+ * @param params.locales - Supported locale prefixes to ignore during comparison.
546
+ * @param params.exact - Whether to require exact path match (default: true). If false, checks if current path starts with target path.
547
+ * @returns True if the link is active, false otherwise.
548
+ *
549
+ * @example
550
+ * ```ts
551
+ * // Exact match
552
+ * isLinkActive({ path: '/about', currentPath: '/about' }) // true
553
+ * isLinkActive({ path: '/about', currentPath: '/about/team' }) // false
554
+ *
555
+ * // With locales
556
+ * isLinkActive({ path: '/about', currentPath: '/en/about' }) // true
557
+ * isLinkActive({ path: '/about', currentPath: '/fr/about' }) // true
558
+ *
559
+ * // Partial match
560
+ * isLinkActive({ path: '/blog', currentPath: '/blog/post-1', exact: false }) // true
561
+ * ```
276
562
  */
277
563
  declare function isLinkActive({
278
564
  path,
@@ -288,29 +574,74 @@ declare function isLinkActive({
288
574
  /**
289
575
  * Cleans a file path by removing the `/public/` prefix if present.
290
576
  *
291
- * @param src - The source path to clean.
292
- * @returns - The cleaned path.
577
+ * Useful when working with static assets that may have been processed
578
+ * or when normalizing paths between development and production environments.
579
+ *
580
+ * @param src - The source path to clean.
581
+ * @returns The cleaned path with `/public/` prefix removed and whitespace trimmed.
582
+ *
583
+ * @example
584
+ * ```ts
585
+ * cleanSrc('/public/images/logo.png') // '/images/logo.png'
586
+ * cleanSrc('images/logo.png') // 'images/logo.png'
587
+ * cleanSrc(' /public/docs/readme.md ') // '/docs/readme.md'
588
+ * ```
293
589
  */
294
590
  declare function cleanSrc(src: string): string;
295
591
  /**
296
592
  * Smoothly scrolls to the top or bottom of a specified container.
297
593
  *
298
- * @param containerSelector - The CSS selector or React ref for the container.
299
- * @param to - Specifies whether to scroll to the top or bottom.
594
+ * Provides smooth scrolling animation to either end of a scrollable element.
595
+ * Accepts either a CSS selector string or a React ref to the container element.
596
+ *
597
+ * @param containerSelector - The CSS selector string or React ref for the scrollable container.
598
+ * @param to - Direction to scroll: 'top' for top of container, 'bottom' for bottom.
599
+ *
600
+ * @example
601
+ * ```ts
602
+ * // Scroll to top using selector
603
+ * scrollTo('.main-content', 'top');
604
+ *
605
+ * // Scroll to bottom using ref
606
+ * scrollTo(containerRef, 'bottom');
607
+ * ```
300
608
  */
301
609
  declare const scrollTo: (containerSelector: string | React.RefObject<HTMLDivElement>, to: "top" | "bottom") => void;
302
610
  /**
303
- * Copies a given string to the clipboard.
611
+ * Copies a given string to the clipboard using the modern Clipboard API.
612
+ *
613
+ * Safely attempts to copy text to the user's clipboard. Falls back gracefully
614
+ * if the Clipboard API is not available or if the operation fails.
304
615
  *
305
- * @param value - The value to copy to the clipboard.
306
- * @param [onSuccess=() => {}] - Optional callback executed after successful copy.
616
+ * @param value - The text value to copy to the clipboard.
617
+ * @param onSuccess - Optional callback executed after successful copy operation.
618
+ *
619
+ * @example
620
+ * ```ts
621
+ * copyToClipboard('Hello World!', () => {
622
+ * console.log('Text copied successfully');
623
+ * });
624
+ * ```
307
625
  */
308
626
  declare const copyToClipboard: (value: string, onSuccess?: () => void) => void;
309
627
  /**
310
- * Converts camelCase, PascalCase, kebab-case, snake_case into normal case.
628
+ * Converts various case styles (camelCase, PascalCase, kebab-case, snake_case) into readable normal case.
629
+ *
630
+ * Transforms technical naming conventions into human-readable titles by:
631
+ * - Adding spaces between words
632
+ * - Capitalizing the first letter of each word
633
+ * - Handling common separators (-, _, camelCase boundaries)
634
+ *
635
+ * @param inputString - The string to convert (supports camelCase, PascalCase, kebab-case, snake_case).
636
+ * @returns The converted string in normal case (title case).
311
637
  *
312
- * @param inputString - The string need to be converted into normal case
313
- * @returns - Normal Case
638
+ * @example
639
+ * ```ts
640
+ * convertToNormalCase('camelCase') // 'Camel Case'
641
+ * convertToNormalCase('kebab-case') // 'Kebab Case'
642
+ * convertToNormalCase('snake_case') // 'Snake Case'
643
+ * convertToNormalCase('PascalCase') // 'Pascal Case'
644
+ * ```
314
645
  */
315
646
  declare function convertToNormalCase(inputString: string): string;
316
647
  /**
@@ -327,6 +658,17 @@ declare const convertToSlug: (str: string) => string;
327
658
  * Checks if the code is running in a server-side environment.
328
659
  *
329
660
  * @returns - True if the code is executed in SSR (Server-Side Rendering) context, false otherwise
661
+ *
662
+ * @example
663
+ * ```ts
664
+ * if (isSSR) {
665
+ * // Server-side only code
666
+ * console.log('Running on server');
667
+ * } else {
668
+ * // Client-side only code
669
+ * window.addEventListener('load', () => {});
670
+ * }
671
+ * ```
330
672
  */
331
673
  declare const isSSR: boolean;
332
674
  /**
@@ -334,6 +676,13 @@ declare const isSSR: boolean;
334
676
  *
335
677
  * @param str - The SVG string to encode
336
678
  * @returns - Base64-encoded string representation of the SVG
679
+ *
680
+ * @example
681
+ * ```ts
682
+ * const svg = '<svg><circle cx="50" cy="50" r="40"/></svg>';
683
+ * const base64 = svgToBase64(svg);
684
+ * // Use in data URL: `data:image/svg+xml;base64,${base64}`
685
+ * ```
337
686
  */
338
687
  declare const svgToBase64: (str: string) => string;
339
688
  /**
@@ -375,9 +724,23 @@ type DebouncedFunction<F extends (...args: any[]) => any> = {
375
724
  * @throws {RangeError} If the `wait` parameter is negative.
376
725
  *
377
726
  * @example
727
+ * ```ts
728
+ * // Basic debouncing
378
729
  * const log = debounce((message: string) => console.log(message), 200);
379
730
  * log('Hello'); // Logs "Hello" after 200ms if no other call is made.
380
731
  * console.log(log.isPending); // true if the timer is active.
732
+ *
733
+ * // Immediate execution
734
+ * const save = debounce(() => saveToServer(), 500, { immediate: true });
735
+ * save(); // Executes immediately, then waits 500ms for subsequent calls
736
+ *
737
+ * // Check pending state
738
+ * const debouncedSearch = debounce(searchAPI, 300);
739
+ * debouncedSearch('query');
740
+ * if (debouncedSearch.isPending) {
741
+ * showLoadingIndicator();
742
+ * }
743
+ * ```
381
744
  */
382
745
  declare function debounce<F extends (...args: any[]) => any>(function_: F, wait?: number, options?: {
383
746
  immediate: boolean;
@@ -412,9 +775,29 @@ type ThrottledFunction<F extends (...args: any[]) => any> = {
412
775
  * @throws {RangeError} If the `wait` parameter is negative.
413
776
  *
414
777
  * @example
778
+ * ```ts
779
+ * // Basic throttling (leading edge by default)
415
780
  * const log = throttle((message: string) => console.log(message), 200);
416
- * log('Hello'); // Logs "Hello" immediately if leading is true.
417
- * console.log(log.isPending); // true if the timer is active.
781
+ * log('Hello'); // Logs "Hello" immediately
782
+ * log('World'); // Ignored for 200ms
783
+ * console.log(log.isPending); // true if within throttle window
784
+ *
785
+ * // Trailing edge only
786
+ * const trailingLog = throttle(() => console.log('trailing'), 200, {
787
+ * leading: false,
788
+ * trailing: true
789
+ * });
790
+ * trailingLog(); // No immediate execution
791
+ * // After 200ms: logs "trailing"
792
+ *
793
+ * // Both edges
794
+ * const bothLog = throttle(() => console.log('both'), 200, {
795
+ * leading: true,
796
+ * trailing: true
797
+ * });
798
+ * bothLog(); // Immediate execution
799
+ * // After 200ms: executes again if called during window
800
+ * ```
418
801
  */
419
802
  declare function throttle<F extends (...args: any[]) => any>(function_: F, wait?: number, options?: {
420
803
  leading?: boolean;
@@ -422,26 +805,31 @@ declare function throttle<F extends (...args: any[]) => any>(function_: F, wait?
422
805
  }): ThrottledFunction<F>;
423
806
  /**
424
807
  * Formats a string by replacing each '%s' placeholder with the corresponding argument.
425
- * This function mimics the basic behavior of C's printf for %s substitution.
426
808
  *
427
- * It supports both calls like `printf(format, ...args)` and `printf(format, argsArray)`.
809
+ * Mimics the basic behavior of C's printf for %s substitution. Supports both
810
+ * variadic arguments and array-based argument passing. Extra placeholders
811
+ * are left as-is, missing arguments result in empty strings.
428
812
  *
429
813
  * @param format - The format string containing '%s' placeholders.
430
- * @param args - The values to substitute into the placeholders, either as separate arguments or as a single array.
431
- * @returns The formatted string with all '%s' replaced by the provided arguments.
814
+ * @param args - The values to substitute, either as separate arguments or a single array.
815
+ * @returns The formatted string with placeholders replaced by arguments.
432
816
  *
433
817
  * @example
434
818
  * ```ts
435
- * const message = printf("%s love %s", "I", "Bangladesh");
436
- * // message === "I love Bangladesh"
819
+ * // Basic usage with separate arguments
820
+ * printf("%s love %s", "I", "Bangladesh") // "I love Bangladesh"
821
+ *
822
+ * // Using array of arguments
823
+ * printf("%s love %s", ["I", "Bangladesh"]) // "I love Bangladesh"
437
824
  *
438
- * const arr = ["I", "Bangladesh"];
439
- * const message2 = printf("%s love %s", arr);
440
- * // message2 === "I love Bangladesh"
825
+ * // Extra placeholders remain unchanged
826
+ * printf("%s %s %s", "Hello", "World") // "Hello World %s"
441
827
  *
442
- * // If there are too few arguments:
443
- * const incomplete = printf("Bangladesh is %s %s", "beautiful");
444
- * // incomplete === "Bangladesh is beautiful"
828
+ * // Missing arguments become empty strings
829
+ * printf("%s and %s", "this") // "this and "
830
+ *
831
+ * // Multiple occurrences
832
+ * printf("%s %s %s", "repeat", "repeat", "repeat") // "repeat repeat repeat"
445
833
  * ```
446
834
  */
447
835
  declare function printf(format: string, ...args: unknown[]): string;
@@ -449,29 +837,54 @@ declare function printf(format: string, ...args: unknown[]): string;
449
837
  * Merges multiple refs into a single ref callback.
450
838
  *
451
839
  * @param refs - An array of refs to merge.
452
- *
453
840
  * @returns - A function that updates the merged ref with the provided value.
841
+ *
842
+ * @example
843
+ * ```tsx
844
+ * const MyComponent = () => {
845
+ * const ref1 = useRef<HTMLDivElement>(null);
846
+ * const ref2 = useRef<HTMLDivElement>(null);
847
+ *
848
+ * const mergedRef = mergeRefs(ref1, ref2);
849
+ *
850
+ * return <div ref={mergedRef}>Content</div>;
851
+ * };
852
+ * ```
454
853
  */
455
854
  type MergeRefs = <T>(...refs: Array<React.Ref<T> | undefined>) => React.RefCallback<T>;
456
855
  declare const mergeRefs: MergeRefs;
457
856
  /**
458
- * Navigates to the specified client-side hash without ssr.
459
- * use `scroll-margin-top` with css to add margins
857
+ * Navigates to the specified client-side hash without triggering SSR.
460
858
  *
461
- * @param id - The ID of the element without # to navigate to.
859
+ * Smoothly scrolls to an element by ID and updates the URL hash.
860
+ * Use `scroll-margin-top` CSS property to add margins for fixed headers.
861
+ *
862
+ * @param id - The ID of the element (without #) to navigate to.
863
+ * @param opts - Additional options for scrollIntoView.
864
+ *
865
+ * @example
866
+ * ```ts
867
+ * // Navigate to an element
868
+ * goToClientSideHash('section-about');
462
869
  *
463
- * @example goToClientSideHash('my-element');
870
+ * // With custom scroll behavior
871
+ * goToClientSideHash('contact', { behavior: 'auto', block: 'center' });
872
+ * ```
464
873
  */
465
874
  declare function goToClientSideHash(id: string, opts?: ScrollIntoViewOptions): void;
466
875
  /**
467
876
  * Escapes a string for use in a regular expression.
468
877
  *
469
878
  * @param str - The string to escape
470
- * @returns - The escaped string
879
+ * @returns - The escaped string safe for use in RegExp constructor
471
880
  *
472
881
  * @example
882
+ * ```ts
473
883
  * const escapedString = escapeRegExp('Hello, world!');
474
884
  * // escapedString === 'Hello\\, world!'
885
+ *
886
+ * const regex = new RegExp(escapeRegExp(userInput));
887
+ * ```
475
888
  */
476
889
  declare function escapeRegExp(str: string): string;
477
890
  /**
@@ -487,6 +900,13 @@ declare function escapeRegExp(str: string): string;
487
900
  * @param options.removeAccents - Whether to remove diacritic marks like accents (default: true)
488
901
  * @param options.removeNonAlphanumeric - Whether to trim non-alphanumeric characters from the edges (default: true)
489
902
  * @returns The normalized string
903
+ *
904
+ * @example
905
+ * ```ts
906
+ * normalizeText('Café') // 'cafe'
907
+ * normalizeText(' Hello! ') // 'hello'
908
+ * normalizeText('José', { removeAccents: false }) // 'josé'
909
+ * ```
490
910
  */
491
911
  declare function normalizeText(str?: string | null, options?: {
492
912
  lowercase?: boolean;