@sohanemon/utils 6.4.7 → 7.0.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,970 +0,0 @@
1
- import { ClassValue } from "clsx";
2
- import * as React from "react";
3
-
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
- */
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
- */
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
- */
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
- */
60
- declare const getClientSideCookie: (name: string) => {
61
- value: string | undefined;
62
- };
63
- //#endregion
64
- //#region src/functions/deepmerge.d.ts
65
- type TAllKeys<T> = T extends any ? keyof T : never;
66
- type TIndexValue<T, K$1 extends PropertyKey, D = never> = T extends any ? K$1 extends keyof T ? T[K$1] : D : never;
67
- type TPartialKeys<T, K$1 extends keyof T> = Omit<T, K$1> & Partial<Pick<T, K$1>> extends infer O ? { [P in keyof O]: O[P] } : never;
68
- type TFunction = (...a: any[]) => any;
69
- type TPrimitives = string | number | boolean | bigint | symbol | Date | TFunction;
70
- type DeepMergeOptions = {
71
- arrayMerge?: 'replace' | 'concat' | 'merge' | ((target: any[], source: any[]) => any[]);
72
- clone?: boolean;
73
- customMerge?: (key: string | symbol, targetValue: any, sourceValue: any) => any;
74
- functionMerge?: 'replace' | 'compose';
75
- maxDepth?: number;
76
- };
77
- type TMerged<T> = [T] extends [Array<any>] ? { [K in keyof T]: TMerged<T[K]> } : [T] extends [TPrimitives] ? T : [T] extends [object] ? TPartialKeys<{ [K in TAllKeys<T>]: TMerged<TIndexValue<T, K>> }, never> : T;
78
- /**
79
- * Deeply merges multiple objects, with later sources taking precedence.
80
- * Handles nested objects, arrays, and special object types with circular reference detection.
81
- *
82
- * Features:
83
- * - Deep merging of nested objects
84
- * - Configurable array merging strategies
85
- * - Circular reference detection and handling
86
- * - Support for symbols and special objects (Date, RegExp, etc.)
87
- * - Type-safe with improved generics
88
- * - Optional cloning to avoid mutation
89
- * - Custom merge functions for specific keys
90
- *
91
- * @template T - The target object type
92
- * @param target - The target object to merge into
93
- * @param sources - Source objects to merge from (can have additional properties)
94
- * @param options - Configuration options
95
- * @param options.clone - Whether to clone the target (default: true)
96
- * @param options.customMerge - Custom merge function for specific keys
97
- * @param options.arrayMerge - How to merge arrays: 'replace' (default), 'concat', or 'merge'
98
- * @param options.functionMerge - How to merge functions: 'replace' (default) or 'compose'
99
- * @param options.maxDepth - Maximum recursion depth (default: 100)
100
- * @returns The merged object with proper typing
101
- *
102
- * @example
103
- * // Basic shallow merge
104
- * deepmerge({ a: 1 }, { b: 2 }) // { a: 1, b: 2 }
105
- *
106
- * @example
107
- * // Deep merge of nested objects
108
- * deepmerge({ user: { name: 'John' } }, { user: { age: 30 } })
109
- * // { user: { name: 'John', age: 30 } }
110
- *
111
- * @example
112
- * // Array concatenation
113
- * deepmerge({ tags: ['react'] }, { tags: ['typescript'] }, { arrayMerge: 'concat' })
114
- * // { tags: ['react', 'typescript'] }
115
- *
116
- * @example
117
- * // Array replacement (default)
118
- * deepmerge({ items: [1, 2] }, { items: [3, 4] })
119
- * // { items: [3, 4] }
120
- *
121
- * @example
122
- * // Custom array merging
123
- * deepmerge(
124
- * { scores: [85, 90] },
125
- * { scores: [95] },
126
- * { arrayMerge: (target, source) => [...target, ...source] }
127
- * )
128
- * // { scores: [85, 90, 95] }
129
- *
130
- * @example
131
- * // Configuration merging
132
- * const defaultConfig = { theme: 'light', features: { darkMode: false } };
133
- * const userConfig = { theme: 'dark', features: { darkMode: true, animations: true } };
134
- * deepmerge(defaultConfig, userConfig);
135
- * // { theme: 'dark', features: { darkMode: true, animations: true } }
136
- *
137
- * @example
138
- * // State updates in reducers
139
- * const initialState = { user: { profile: { name: '' } }, settings: {} };
140
- * const action = { user: { profile: { name: 'Alice' } }, settings: { theme: 'dark' } };
141
- * const newState = deepmerge(initialState, action);
142
- *
143
- * @example
144
- * // Merging API responses
145
- * const cachedData = { posts: [{ id: 1, title: 'Old' }] };
146
- * const freshData = { posts: [{ id: 1, title: 'Updated', author: 'Bob' }] };
147
- * deepmerge(cachedData, freshData);
148
- * // { posts: [{ id: 1, title: 'Updated', author: 'Bob' }] }
149
- *
150
- * @example
151
- * // Function composition
152
- * const log1 = () => console.log('first');
153
- * const log2 = () => console.log('second');
154
- * const composed = deepmerge(log1, log2, { functionMerge: 'compose' });
155
- * composed(); // logs 'first' then 'second'
156
- */
157
- declare function deepmerge<T extends Record<string, any>, S extends Record<string, any>[]>(target: T, ...sources: S): TMerged<T | S[number]>;
158
- declare function deepmerge<T extends Record<string, any>, S extends Record<string, any>[]>(target: T, sources: S, options?: DeepMergeOptions): TMerged<T | S[number]>;
159
- //#endregion
160
- //#region src/functions/hydrate.d.ts
161
- type Hydrate<T> = T extends null ? undefined : T extends (infer U)[] ? Hydrate<U>[] : T extends object ? { [K in keyof T]: Hydrate<T[K]> } : T;
162
- /**
163
- * Converts all `null` values to `undefined` in the data structure recursively.
164
- *
165
- * @param data - Any input data (object, array, primitive)
166
- * @returns Same type as input, but with all nulls replaced by undefined
167
- *
168
- * @example
169
- * ```ts
170
- * // Basic object hydration
171
- * hydrate({ name: null, age: 25 }) // { name: undefined, age: 25 }
172
- *
173
- * // Nested object hydration
174
- * hydrate({
175
- * user: { email: null, profile: { avatar: null } },
176
- * settings: { theme: 'dark' }
177
- * })
178
- * // { user: { email: undefined, profile: { avatar: undefined } }, settings: { theme: 'dark' } }
179
- *
180
- * // Array hydration
181
- * hydrate([null, 'hello', null, 42]) // [undefined, 'hello', undefined, 42]
182
- *
183
- * // Mixed data structures
184
- * hydrate({
185
- * posts: [null, { title: 'Hello', content: null }],
186
- * metadata: { published: null, tags: ['react', null] }
187
- * })
188
- * ```
189
- *
190
- * @example
191
- * ```ts
192
- * // API response normalization
193
- * const apiResponse = await fetch('/api/user');
194
- * const rawData = await apiResponse.json(); // May contain null values
195
- * const normalizedData = hydrate(rawData); // Convert nulls to undefined
196
- *
197
- * // Database result processing
198
- * const dbResult = query('SELECT * FROM users'); // Some fields may be NULL
199
- * const cleanData = hydrate(dbResult); // Normalize for consistent handling
200
- *
201
- * // Form data sanitization
202
- * const formData = getFormValues(); // May have null values from empty fields
203
- * const sanitizedData = hydrate(formData); // Prepare for validation/state
204
- * ```
205
- */
206
- declare function hydrate<T>(data: T): Hydrate<T>;
207
- //#endregion
208
- //#region src/functions/object.d.ts
209
- /**
210
- * Type representing a path split into segments
211
- * @template S - The original path string type
212
- */
213
- type SplitPath<S extends string> = S extends `${infer First}.${infer Rest}` ? [First, ...SplitPath<Rest>] : [S];
214
- /**
215
- * Recursive type to resolve nested object types based on path
216
- * @template T - Current object type
217
- * @template K - Array of path segments
218
- */
219
- type GetValue<T, K$1 extends Array<string | number>> = K$1 extends [infer First, ...infer Rest] ? First extends keyof T ? GetValue<T[First], Rest extends Array<string | number> ? Rest : []> : First extends `${number}` ? T extends any[] ? GetValue<T[number], Rest extends Array<string | number> ? Rest : []> : undefined : undefined : T;
220
- /**
221
- * Get a nested value from an object using array path segments
222
- * @template T - Object type
223
- * @template K - Path segments array type
224
- * @template D - Default value type
225
- * @param obj - Source object
226
- * @param path - Array of path segments
227
- * @param defaultValue - Fallback value if path not found
228
- * @returns Value at path or default value
229
- *
230
- * @example
231
- * getObjectValue({a: [{b: 1}]}, ['a', 0, 'b']) // 1
232
- */
233
- declare function getObjectValue<T, K$1 extends Array<string | number>, D>(obj: T, path: K$1, defaultValue: D): Exclude<GetValue<T, K$1>, undefined> | D;
234
- /**
235
- * Get a nested value from an object using array path segments
236
- * @template T - Object type
237
- * @template K - Path segments array type
238
- * @param obj - Source object
239
- * @param path - Array of path segments
240
- * @returns Value at path or undefined
241
- *
242
- * @example
243
- * getObjectValue({a: [{b: 1}]}, ['a', 0, 'b']) // 1
244
- */
245
- declare function getObjectValue<T, K$1 extends Array<string | number>>(obj: T, path: K$1): GetValue<T, K$1> | undefined;
246
- /**
247
- * Get a nested value from an object using dot notation path
248
- * @template T - Object type
249
- * @template S - Path string literal type
250
- * @template D - Default value type
251
- * @param obj - Source object
252
- * @param path - Dot-separated path string
253
- * @param defaultValue - Fallback value if path not found
254
- * @returns Value at path or default value
255
- *
256
- * @example
257
- * getObjectValue({a: [{b: 1}]}, 'a.0.b', 2) // 1
258
- */
259
- declare function getObjectValue<T, S extends string, D>(obj: T, path: S, defaultValue: D): Exclude<GetValue<T, SplitPath<S>>, undefined> | D;
260
- /**
261
- * Get a nested value from an object using dot notation path
262
- * @template T - Object type
263
- * @template S - Path string literal type
264
- * @param obj - Source object
265
- * @param path - Dot-separated path string
266
- * @returns Value at path or undefined
267
- *
268
- * @example
269
- * getObjectValue({a: [{b: 1}]}, 'a.0.b') // 1
270
- */
271
- declare function getObjectValue<T, S extends string>(obj: T, path: S): GetValue<T, SplitPath<S>> | undefined;
272
- /**
273
- * Extend an object or function with additional properties while
274
- * preserving the original type information.
275
- *
276
- * Works with both plain objects and callable functions since
277
- * functions in JavaScript are objects too. Also handles nullable types.
278
- *
279
- * @template T The base object or function type (can be null/undefined)
280
- * @template P The additional properties type
281
- *
282
- * @param base - The object or function to extend (can be null/undefined)
283
- * @param props - An object containing properties to attach
284
- *
285
- * @returns The same object/function, augmented with the given properties, or the original value if null/undefined
286
- *
287
- * @example
288
- * ```ts
289
- * // Extend a plain object
290
- * const config = extendProps({ apiUrl: '/api' }, { timeout: 5000 });
291
- * // config has both apiUrl and timeout properties
292
- *
293
- * // Extend a function with metadata
294
- * const fetchData = (url: string) => fetch(url).then(r => r.json());
295
- * const enhancedFetch = extendProps(fetchData, {
296
- * description: 'Data fetching utility',
297
- * version: '1.0'
298
- * });
299
- * // enhancedFetch is callable and has description/version properties
300
- *
301
- * // Create plugin system
302
- * const basePlugin = { name: 'base', enabled: true };
303
- * const authPlugin = extendProps(basePlugin, {
304
- * authenticate: (token: string) => validateToken(token)
305
- * });
306
- *
307
- * // Build configuration objects
308
- * const defaultSettings = { theme: 'light', lang: 'en' };
309
- * const userSettings = extendProps(defaultSettings, {
310
- * theme: 'dark',
311
- * notifications: true
312
- * });
313
- *
314
- * // Handle nullable types (e.g., Supabase Session | null)
315
- * const session: Session | null = getSession();
316
- * const extendedSession = extendProps(session, { customProp: 'value' });
317
- * // extendedSession is (Session & { customProp: string }) | null
318
- * ```
319
- */
320
- declare function extendProps<T, P$1 extends object>(base: T, props: P$1): T extends null | undefined ? T : T & P$1;
321
- //#endregion
322
- //#region src/functions/poll.d.ts
323
- /**
324
- * Repeatedly polls an async `cond` function UNTIL it returns a TRUTHY value,
325
- * or until the operation times out or is aborted.
326
- *
327
- * Designed for waiting on async jobs, external state, or delayed availability.
328
- *
329
- * @template T The type of the successful result.
330
- *
331
- * @param cond
332
- * A function returning a Promise that resolves to:
333
- * - a truthy value `T` → stop polling and return it
334
- * - falsy/null/undefined → continue polling
335
- *
336
- * @param options
337
- * Configuration options:
338
- * - `interval` (number) — Time between polls in ms (default: 5000 ms)
339
- * - `timeout` (number) — Max total duration before failing (default: 5 min)
340
- * - `jitter` (boolean) — Add small random offset (±10%) to intervals to avoid sync bursts (default: true)
341
- * - `signal` (AbortSignal) — Optional abort signal to cancel polling
342
- *
343
- * @returns
344
- * Resolves with the truthy value `T` when successful.
345
- * Throws `AbortError` if aborted
346
- *
347
- * @example
348
- * ```ts
349
- * // Poll for job completion
350
- * const job = await poll(async () => {
351
- * const status = await getJobStatus();
352
- * return status === 'done' ? status : null;
353
- * }, { interval: 3000, timeout: 60000 });
354
- * ```
355
- *
356
- * @example
357
- * ```ts
358
- * // Wait for API endpoint to be ready
359
- * const apiReady = await poll(async () => {
360
- * try {
361
- * await fetch('/api/health');
362
- * return true;
363
- * } catch {
364
- * return null;
365
- * }
366
- * }, { interval: 1000, timeout: 30000 });
367
- * ```
368
- *
369
- * @example
370
- * ```ts
371
- * // Poll with abort signal for cancellation
372
- * const controller = new AbortController();
373
- * setTimeout(() => controller.abort(), 10000); // Cancel after 10s
374
- *
375
- * try {
376
- * const result = await poll(
377
- * () => checkExternalService(),
378
- * { interval: 2000, signal: controller.signal }
379
- * );
380
- * } catch (err) {
381
- * if (err.name === 'AbortError') {
382
- * console.log('Polling was cancelled');
383
- * }
384
- * }
385
- * ```
386
- *
387
- * @example
388
- * ```ts
389
- * // Poll for user action completion
390
- * const userConfirmed = await poll(async () => {
391
- * const confirmations = await getPendingConfirmations();
392
- * return confirmations.length > 0 ? confirmations[0] : null;
393
- * }, { interval: 5000, timeout: 300000 }); // 5 min timeout
394
- * ```
395
- */
396
- declare function poll<T>(cond: () => Promise<T | null | false | undefined>, {
397
- interval,
398
- timeout,
399
- jitter,
400
- signal
401
- }?: Partial<{
402
- interval: number;
403
- timeout: number;
404
- signal: AbortSignal;
405
- jitter: boolean;
406
- }>): Promise<T>;
407
- //#endregion
408
- //#region src/functions/schedule.d.ts
409
- /**
410
- * A task function that can be synchronous or asynchronous.
411
- */
412
- type Task = () => Promise<void> | void;
413
- /**
414
- * Options for configuring the schedule function.
415
- */
416
- interface ScheduleOpts {
417
- /** Number of retry attempts on failure. Defaults to 0. */
418
- retry?: number;
419
- /** Delay in milliseconds between retries. Defaults to 0. */
420
- delay?: number;
421
- /** Maximum time in milliseconds to wait for the task to complete. */
422
- timeout?: number;
423
- }
424
- /**
425
- * Runs a function asynchronously in the background without blocking the main thread.
426
- *
427
- * Executes the task immediately using setTimeout, with optional retry logic on failure.
428
- * Useful for non-critical operations like analytics, logging, or background processing.
429
- * Logs execution time and retry attempts to the console.
430
- *
431
- * @param task - The function to execute asynchronously
432
- * @param options - Configuration options for retries and timing
433
- *
434
- * @example
435
- * ```ts
436
- * // Simple background task
437
- * schedule(() => {
438
- * console.log('Background work done');
439
- * });
440
- *
441
- * // Task with retry on failure
442
- * schedule(
443
- * () => sendAnalytics(),
444
- * { retry: 3, delay: 1000 }
445
- * );
446
- * ```
447
- */
448
- declare function schedule(task: Task, options?: ScheduleOpts): void;
449
- //#endregion
450
- //#region src/functions/shield.d.ts
451
- /**
452
- * A helper to run sync or async operations safely without try/catch.
453
- *
454
- * Returns a tuple `[error, data]`:
455
- * - `error`: the thrown error (if any), otherwise `null`
456
- * - `data`: the resolved value (if successful), otherwise `null`
457
- *
458
- * @example
459
- * ```ts
460
- * // Synchronous error handling
461
- * const [err, value] = shield(() => {
462
- * if (Math.random() > 0.5) throw new Error('Random failure');
463
- * return 'success';
464
- * });
465
- * if (err) {
466
- * console.error('Operation failed:', err);
467
- * } else {
468
- * console.log('Result:', value);
469
- * }
470
- *
471
- * // Asynchronous error handling
472
- * const [asyncErr, result] = await shield(async () => {
473
- * const response = await fetch('/api/data');
474
- * if (!response.ok) throw new Error('API error');
475
- * return response.json();
476
- * });
477
- * if (asyncErr) {
478
- * console.error('API call failed:', asyncErr);
479
- * } else {
480
- * processData(result);
481
- * }
482
- *
483
- * // API calls with fallbacks
484
- * const [fetchErr, data] = await shield(fetchUserData(userId));
485
- * const userData = fetchErr ? getCachedUserData(userId) : data;
486
- *
487
- * // File operations
488
- * const [fileErr, content] = shield(() => readFileSync('config.json'));
489
- * if (fileErr) {
490
- * console.warn('Could not read config, using defaults');
491
- * return defaultConfig;
492
- * }
493
- * ```
494
- *
495
- * @example
496
- * ```ts
497
- * // In async functions
498
- * async function safeApiCall() {
499
- * const [err, result] = await shield(callExternalAPI());
500
- * if (err) {
501
- * await logError(err);
502
- * return null;
503
- * }
504
- * return result;
505
- * }
506
- *
507
- * // In event handlers
508
- * function handleSubmit(formData) {
509
- * const [validationErr, validatedData] = shield(() => validateForm(formData));
510
- * if (validationErr) {
511
- * showValidationError(validationErr);
512
- * return;
513
- * }
514
- * submitData(validatedData);
515
- * }
516
- * ```
517
- */
518
- declare function shield<T, E = Error>(operation: Promise<T>): Promise<[E | null, T | null]>;
519
- declare function shield<T, E = Error>(operation: () => T): [E | null, T | null];
520
- //#endregion
521
- //#region src/functions/utils.d.ts
522
- /**
523
- * Utility to merge class names with Tailwind CSS and additional custom merging logic.
524
- *
525
- * @param {...ClassValue[]} inputs - Class names to merge.
526
- * @returns {string} - A string of merged class names.
527
- *
528
- * @example
529
- * ```ts
530
- * cn('px-2 py-1', 'bg-red-500') // 'px-2 py-1 bg-red-500'
531
- * cn('px-2', 'px-4') // 'px-4' (Tailwind resolves conflicts)
532
- * ```
533
- */
534
- declare function cn(...inputs: ClassValue[]): string;
535
- /**
536
- * @deprecated Use isLinkActive instead.
537
- *
538
- * Determines if a navigation link is active based on the current path.
539
- *
540
- * @param href - The target URL.
541
- * @param path - The current browser path.
542
- * @returns - True if the navigation is active, false otherwise.
543
- *
544
- * @example
545
- * ```ts
546
- * isNavActive('/about', '/about/team') // true
547
- * isNavActive('/contact', '/about') // false
548
- * ```
549
- */
550
- declare function isNavActive(href: string, path: string): boolean;
551
- /**
552
- * Checks if a link is active, considering optional localization prefixes.
553
- *
554
- * Compares paths while ignoring locale prefixes (e.g., /en/, /fr/) for consistent
555
- * navigation highlighting across different language versions of the same page.
556
- *
557
- * @param params - Parameters object.
558
- * @param params.path - The target path of the link.
559
- * @param params.currentPath - The current browser path.
560
- * @param params.locales - Supported locale prefixes to ignore during comparison.
561
- * @param params.exact - Whether to require exact path match (default: true). If false, checks if current path starts with target path.
562
- * @returns True if the link is active, false otherwise.
563
- *
564
- * @example
565
- * ```ts
566
- * // Exact match
567
- * isLinkActive({ path: '/about', currentPath: '/about' }) // true
568
- * isLinkActive({ path: '/about', currentPath: '/about/team' }) // false
569
- *
570
- * // With locales
571
- * isLinkActive({ path: '/about', currentPath: '/en/about' }) // true
572
- * isLinkActive({ path: '/about', currentPath: '/fr/about' }) // true
573
- *
574
- * // Partial match
575
- * isLinkActive({ path: '/blog', currentPath: '/blog/post-1', exact: false }) // true
576
- * ```
577
- */
578
- declare function isLinkActive({
579
- path,
580
- currentPath,
581
- locales,
582
- exact
583
- }: {
584
- path: string;
585
- currentPath: string;
586
- locales?: string[];
587
- exact?: boolean;
588
- }): boolean;
589
- /**
590
- * Cleans a file path by removing the `/public/` prefix if present.
591
- *
592
- * Useful when working with static assets that may have been processed
593
- * or when normalizing paths between development and production environments.
594
- *
595
- * @param src - The source path to clean.
596
- * @returns The cleaned path with `/public/` prefix removed and whitespace trimmed.
597
- *
598
- * @example
599
- * ```ts
600
- * cleanSrc('/public/images/logo.png') // '/images/logo.png'
601
- * cleanSrc('images/logo.png') // 'images/logo.png'
602
- * cleanSrc(' /public/docs/readme.md ') // '/docs/readme.md'
603
- * ```
604
- */
605
- declare function cleanSrc(src: string): string;
606
- /**
607
- * Smoothly scrolls to the top or bottom of a specified container.
608
- *
609
- * Provides smooth scrolling animation to either end of a scrollable element.
610
- * Accepts either a CSS selector string or a React ref to the container element.
611
- *
612
- * @param containerSelector - The CSS selector string or React ref for the scrollable container.
613
- * @param to - Direction to scroll: 'top' for top of container, 'bottom' for bottom.
614
- *
615
- * @example
616
- * ```ts
617
- * // Scroll to top using selector
618
- * scrollTo('.main-content', 'top');
619
- *
620
- * // Scroll to bottom using ref
621
- * scrollTo(containerRef, 'bottom');
622
- * ```
623
- */
624
- declare const scrollTo: (containerSelector: string | React.RefObject<HTMLDivElement>, to: "top" | "bottom") => void;
625
- /**
626
- * Copies a given string to the clipboard using the modern Clipboard API.
627
- *
628
- * Safely attempts to copy text to the user's clipboard. Falls back gracefully
629
- * if the Clipboard API is not available or if the operation fails.
630
- *
631
- * @param value - The text value to copy to the clipboard.
632
- * @param onSuccess - Optional callback executed after successful copy operation.
633
- *
634
- * @example
635
- * ```ts
636
- * copyToClipboard('Hello World!', () => {
637
- * console.log('Text copied successfully');
638
- * });
639
- * ```
640
- */
641
- declare const copyToClipboard: (value: string, onSuccess?: () => void) => void;
642
- /**
643
- * Converts various case styles (camelCase, PascalCase, kebab-case, snake_case) into readable normal case.
644
- *
645
- * Transforms technical naming conventions into human-readable titles by:
646
- * - Adding spaces between words
647
- * - Capitalizing the first letter of each word
648
- * - Handling common separators (-, _, camelCase boundaries)
649
- *
650
- * @param inputString - The string to convert (supports camelCase, PascalCase, kebab-case, snake_case).
651
- * @returns The converted string in normal case (title case).
652
- *
653
- * @example
654
- * ```ts
655
- * convertToNormalCase('camelCase') // 'Camel Case'
656
- * convertToNormalCase('kebab-case') // 'Kebab Case'
657
- * convertToNormalCase('snake_case') // 'Snake Case'
658
- * convertToNormalCase('PascalCase') // 'Pascal Case'
659
- * ```
660
- */
661
- declare function convertToNormalCase(inputString: string): string;
662
- /**
663
- * Converts a string to a URL-friendly slug by trimming, converting to lowercase,
664
- * replacing diacritics, removing invalid characters, and replacing spaces with hyphens.
665
- * @param {string} [str] - The input string to convert.
666
- * @returns {string} The generated slug.
667
- * @example
668
- * convertToSlug("Hello World!"); // "hello-world"
669
- * convertToSlug("Déjà Vu"); // "deja-vu"
670
- */
671
- declare const convertToSlug: (str: string) => string;
672
- /**
673
- * Checks if the code is running in a server-side environment.
674
- *
675
- * @returns - True if the code is executed in SSR (Server-Side Rendering) context, false otherwise
676
- *
677
- * @example
678
- * ```ts
679
- * if (isSSR) {
680
- * // Server-side only code
681
- * console.log('Running on server');
682
- * } else {
683
- * // Client-side only code
684
- * window.addEventListener('load', () => {});
685
- * }
686
- * ```
687
- */
688
- declare const isSSR: boolean;
689
- /**
690
- * Converts an SVG string to a Base64-encoded string.
691
- *
692
- * @param str - The SVG string to encode
693
- * @returns - Base64-encoded string representation of the SVG
694
- *
695
- * @example
696
- * ```ts
697
- * const svg = '<svg><circle cx="50" cy="50" r="40"/></svg>';
698
- * const base64 = svgToBase64(svg);
699
- * // Use in data URL: `data:image/svg+xml;base64,${base64}`
700
- * ```
701
- */
702
- declare const svgToBase64: (str: string) => string;
703
- /**
704
- * Pauses execution for the specified time.
705
- *
706
- * `signal` allows cancelling the sleep via AbortSignal.
707
- *
708
- * @param time - Time in milliseconds to sleep (default is 1000ms)
709
- * @param signal - Optional AbortSignal to cancel the sleep early
710
- * @returns - A Promise that resolves after the specified time or when aborted
711
- */
712
- declare const sleep: (time?: number, signal?: AbortSignal) => Promise<void>;
713
- type DebouncedFunction<F extends (...args: any[]) => any> = {
714
- (...args: Parameters<F>): ReturnType<F> | undefined;
715
- readonly isPending: boolean;
716
- };
717
- /**
718
- * Creates a debounced function that delays invoking the provided function until
719
- * after the specified `wait` time has elapsed since the last invocation.
720
- *
721
- * If the `immediate` option is set to `true`, the function will be invoked immediately
722
- * on the leading edge of the wait interval. Subsequent calls during the wait interval
723
- * will reset the timer but not invoke the function until the interval elapses again.
724
- *
725
- * The returned function includes the `isPending` property to check if the debounce
726
- * timer is currently active.
727
- *
728
- * @typeParam F - The type of the function to debounce.
729
- *
730
- * @param function_ - The function to debounce.
731
- * @param wait - The number of milliseconds to delay (default is 100ms).
732
- * @param options - An optional object with the following properties:
733
- * - `immediate` (boolean): If `true`, invokes the function on the leading edge
734
- * of the wait interval instead of the trailing edge.
735
- *
736
- * @returns A debounced version of the provided function, enhanced with the `isPending` property.
737
- *
738
- * @throws {TypeError} If the first parameter is not a function.
739
- * @throws {RangeError} If the `wait` parameter is negative.
740
- *
741
- * @example
742
- * ```ts
743
- * // Basic debouncing
744
- * const log = debounce((message: string) => console.log(message), 200);
745
- * log('Hello'); // Logs "Hello" after 200ms if no other call is made.
746
- * console.log(log.isPending); // true if the timer is active.
747
- *
748
- * // Immediate execution
749
- * const save = debounce(() => saveToServer(), 500, { immediate: true });
750
- * save(); // Executes immediately, then waits 500ms for subsequent calls
751
- *
752
- * // Check pending state
753
- * const debouncedSearch = debounce(searchAPI, 300);
754
- * debouncedSearch('query');
755
- * if (debouncedSearch.isPending) {
756
- * showLoadingIndicator();
757
- * }
758
- * ```
759
- */
760
- declare function debounce<F extends (...args: any[]) => any>(function_: F, wait?: number, options?: {
761
- immediate: boolean;
762
- }): DebouncedFunction<F>;
763
- type ThrottledFunction<F extends (...args: any[]) => any> = {
764
- (...args: Parameters<F>): ReturnType<F> | undefined;
765
- readonly isPending: boolean;
766
- };
767
- /**
768
- * Creates a throttled function that invokes the provided function at most once
769
- * every `wait` milliseconds.
770
- *
771
- * If the `leading` option is set to `true`, the function will be invoked immediately
772
- * on the leading edge of the throttle interval. If the `trailing` option is set to `true`,
773
- * the function will also be invoked at the end of the throttle interval if additional
774
- * calls were made during the interval.
775
- *
776
- * The returned function includes the `isPending` property to check if the throttle
777
- * timer is currently active.
778
- *
779
- * @typeParam F - The type of the function to throttle.
780
- *
781
- * @param function_ - The function to throttle.
782
- * @param wait - The number of milliseconds to wait between invocations (default is 100ms).
783
- * @param options - An optional object with the following properties:
784
- * - `leading` (boolean): If `true`, invokes the function on the leading edge of the interval.
785
- * - `trailing` (boolean): If `true`, invokes the function on the trailing edge of the interval.
786
- *
787
- * @returns A throttled version of the provided function, enhanced with the `isPending` property.
788
- *
789
- * @throws {TypeError} If the first parameter is not a function.
790
- * @throws {RangeError} If the `wait` parameter is negative.
791
- *
792
- * @example
793
- * ```ts
794
- * // Basic throttling (leading edge by default)
795
- * const log = throttle((message: string) => console.log(message), 200);
796
- * log('Hello'); // Logs "Hello" immediately
797
- * log('World'); // Ignored for 200ms
798
- * console.log(log.isPending); // true if within throttle window
799
- *
800
- * // Trailing edge only
801
- * const trailingLog = throttle(() => console.log('trailing'), 200, {
802
- * leading: false,
803
- * trailing: true
804
- * });
805
- * trailingLog(); // No immediate execution
806
- * // After 200ms: logs "trailing"
807
- *
808
- * // Both edges
809
- * const bothLog = throttle(() => console.log('both'), 200, {
810
- * leading: true,
811
- * trailing: true
812
- * });
813
- * bothLog(); // Immediate execution
814
- * // After 200ms: executes again if called during window
815
- * ```
816
- */
817
- declare function throttle<F extends (...args: any[]) => any>(function_: F, wait?: number, options?: {
818
- leading?: boolean;
819
- trailing?: boolean;
820
- }): ThrottledFunction<F>;
821
- /**
822
- * Formats a string by replacing each '%s' placeholder with the corresponding argument.
823
- *
824
- * Mimics the basic behavior of C's printf for %s substitution. Supports both
825
- * variadic arguments and array-based argument passing. Extra placeholders
826
- * are left as-is, missing arguments result in empty strings.
827
- *
828
- * @param format - The format string containing '%s' placeholders.
829
- * @param args - The values to substitute, either as separate arguments or a single array.
830
- * @returns The formatted string with placeholders replaced by arguments.
831
- *
832
- * @example
833
- * ```ts
834
- * // Basic usage with separate arguments
835
- * printf("%s love %s", "I", "Bangladesh") // "I love Bangladesh"
836
- *
837
- * // Using array of arguments
838
- * printf("%s love %s", ["I", "Bangladesh"]) // "I love Bangladesh"
839
- *
840
- * // Extra placeholders remain unchanged
841
- * printf("%s %s %s", "Hello", "World") // "Hello World %s"
842
- *
843
- * // Missing arguments become empty strings
844
- * printf("%s and %s", "this") // "this and "
845
- *
846
- * // Multiple occurrences
847
- * printf("%s %s %s", "repeat", "repeat", "repeat") // "repeat repeat repeat"
848
- * ```
849
- */
850
- declare function printf(format: string, ...args: unknown[]): string;
851
- /**
852
- * Merges multiple refs into a single ref callback.
853
- *
854
- * @param refs - An array of refs to merge.
855
- * @returns - A function that updates the merged ref with the provided value.
856
- *
857
- * @example
858
- * ```tsx
859
- * const MyComponent = () => {
860
- * const ref1 = useRef<HTMLDivElement>(null);
861
- * const ref2 = useRef<HTMLDivElement>(null);
862
- *
863
- * const mergedRef = mergeRefs(ref1, ref2);
864
- *
865
- * return <div ref={mergedRef}>Content</div>;
866
- * };
867
- * ```
868
- */
869
- type MergeRefs = <T>(...refs: Array<React.Ref<T> | undefined>) => React.RefCallback<T>;
870
- declare const mergeRefs: MergeRefs;
871
- /**
872
- * Navigates to the specified client-side hash without triggering SSR.
873
- *
874
- * Smoothly scrolls to an element by ID and updates the URL hash.
875
- * Use `scroll-margin-top` CSS property to add margins for fixed headers.
876
- *
877
- * @param id - The ID of the element (without #) to navigate to.
878
- * @param opts - Additional options for scrollIntoView.
879
- *
880
- * @example
881
- * ```ts
882
- * // Navigate to an element
883
- * goToClientSideHash('section-about');
884
- *
885
- * // With custom scroll behavior
886
- * goToClientSideHash('contact', { behavior: 'auto', block: 'center' });
887
- * ```
888
- */
889
- declare function goToClientSideHash(id: string, opts?: ScrollIntoViewOptions): void;
890
- /**
891
- * Escapes a string for use in a regular expression.
892
- *
893
- * @param str - The string to escape
894
- * @returns - The escaped string safe for use in RegExp constructor
895
- *
896
- * @example
897
- * ```ts
898
- * const escapedString = escapeRegExp('Hello, world!');
899
- * // escapedString === 'Hello\\, world!'
900
- *
901
- * const regex = new RegExp(escapeRegExp(userInput));
902
- * ```
903
- */
904
- declare function escapeRegExp(str: string): string;
905
- /**
906
- * Normalizes a string by:
907
- * - Applying Unicode normalization (NFC)
908
- * - Optionally removing diacritic marks (accents)
909
- * - Optionally trimming leading/trailing non-alphanumeric characters
910
- * - Optionally converting to lowercase
911
- *
912
- * @param str - The string to normalize
913
- * @param options - Normalization options
914
- * @param options.lowercase - Whether to convert the result to lowercase (default: true)
915
- * @param options.removeAccents - Whether to remove diacritic marks like accents (default: true)
916
- * @param options.removeNonAlphanumeric - Whether to trim non-alphanumeric characters from the edges (default: true)
917
- * @returns The normalized string
918
- *
919
- * @example
920
- * ```ts
921
- * normalizeText('Café') // 'cafe'
922
- * normalizeText(' Hello! ') // 'hello'
923
- * normalizeText('José', { removeAccents: false }) // 'josé'
924
- * ```
925
- */
926
- declare function normalizeText(str?: string | null, options?: {
927
- lowercase?: boolean;
928
- removeAccents?: boolean;
929
- removeNonAlphanumeric?: boolean;
930
- }): string;
931
- //#endregion
932
- //#region src/functions/worker.d.ts
933
- /**
934
- * Converts a regular function into a workerized version that runs in a Web Worker.
935
- *
936
- * This provides the ultimate DX for Web Workers - just write a normal function
937
- * and "workerize" it to run in the background without blocking the UI.
938
- *
939
- * @param fn - The function to workerize
940
- * @returns A function that calls the original function in a worker and returns a Promise
941
- *
942
- * @example
943
- * ```ts
944
- * // Define a normal function
945
- * function fibonacci(n: number): number {
946
- * if (n <= 1) return n;
947
- * return fibonacci(n - 1) + fibonacci(n - 2);
948
- * }
949
- *
950
- * // Workerize it
951
- * const workerizedFib = workerize(fibonacci);
952
- *
953
- * // Use like a normal async function!
954
- * const result = await workerizedFib(35);
955
- * console.log(result); // Works just like the original function
956
- * ```
957
- *
958
- * @example
959
- * ```ts
960
- * // Works with any function signature
961
- * const sumArray = workerize((arr: number[]) =>
962
- * arr.reduce((a, b) => a + b, 0)
963
- * );
964
- *
965
- * const result = await sumArray([1, 2, 3, 4, 5]); // 15
966
- * ```
967
- */
968
- declare function workerize<T extends (...args: any[]) => any>(fn: T): (...args: Parameters<T>) => Promise<ReturnType<T>>;
969
- //#endregion
970
- export { deepmerge as A, Task as C, getObjectValue as D, extendProps as E, getClientSideCookie as M, hasClientSideCookie as N, hydrate as O, setClientSideCookie as P, ScheduleOpts as S, poll as T, scrollTo as _, convertToNormalCase as a, throttle as b, debounce as c, isLinkActive as d, isNavActive as f, printf as g, normalizeText as h, cn as i, deleteClientSideCookie as j, DeepMergeOptions as k, escapeRegExp as l, mergeRefs as m, MergeRefs as n, convertToSlug as o, isSSR as p, cleanSrc as r, copyToClipboard as s, workerize as t, goToClientSideHash as u, sleep as v, schedule as w, shield as x, svgToBase64 as y };