import { ClassValue } from 'clsx'; /** * Merges and deduplicates CSS class names using clsx and tailwind-merge. * Tailwind-merge ensures conflicting utility classes are resolved correctly. * * @param inputs - Class values to merge (strings, arrays, objects, or falsy values) * @returns A single string of merged, deduplicated class names * * @example * ```ts * mergeClasses('px-2 py-1', 'px-4'); // 'py-1 px-4' * mergeClasses('text-sm', condition && 'text-lg'); // 'text-lg' if condition is true * ``` */ declare function mergeClasses(...inputs: ClassValue[]): string; /** * Joins CSS class strings, filtering out null/undefined values. * Unlike `mergeClasses` from utils, this does NOT resolve Tailwind conflicts - * it simply concatenates class strings. Use when classes are guaranteed not to conflict. * * @param classes - Class strings (may include null/undefined) * @returns Space-separated class string */ declare function joinClasses(...classes: (string | undefined | null)[]): string; /** * A debounced function wrapper with cancel and flush capabilities. * * @template T - The type of the original function. */ interface DebouncedFn void> { /** * Calls the debounced function. The actual execution is delayed until * the specified wait time has passed without another call. */ (...args: Parameters): void; /** * Cancels any pending debounced call. * Useful for cleanup in component destruction or effect cleanup. */ cancel(): void; /** * Immediately executes the pending debounced call if one exists. * Does nothing if no call is pending. */ flush(): void; /** * Returns whether there is a pending debounced call. */ pending(): boolean; } /** * Configuration options for the debounce function. */ interface DebounceOptions { /** * The number of milliseconds to delay execution. * @default 300 */ readonly wait?: number; /** * If `true`, the function is invoked on the leading edge of the timeout * instead of the trailing edge. * @default false */ readonly leading?: boolean; } /** * Creates a debounced version of the provided function that delays invoking * until after the specified wait time has elapsed since the last call. * * The debounced function includes `cancel()` to abort pending calls, * `flush()` to immediately execute pending calls, and `pending()` to check status. * * @template T - The type of the function to debounce. * @param fn - The function to debounce. * @param optionsOrWait - Wait time in ms or options object. * @returns The debounced function with control methods. * * @example * // Basic usage with default 300ms delay * const debouncedSearch = debounce((query: string) => { * console.log('Searching for:', query); * }); * debouncedSearch('hello'); // Logs after 300ms if no subsequent calls * * @example * // With custom wait time * const debouncedSave = debounce( * (data: { id: number; value: string }) => saveToServer(data), * 500 * ); * * @example * // With options object and leading edge execution * const debouncedClick = debounce( * () => handleClick(), * { wait: 200, leading: true } * ); * * @example * // Cleanup in Angular component * export class SearchComponent { * private debouncedSearch = debounce((q: string) => this.search(q), 300); * * ngOnDestroy(): void { * this.debouncedSearch.cancel(); * } * } */ declare function debounce void>(fn: T, optionsOrWait?: number | DebounceOptions): DebouncedFn; /** * A throttled function wrapper with cancel capability. * * @template T - The type of the original function. */ interface ThrottledFn void> { /** * Calls the throttled function. Execution is rate-limited to at most * once per the specified wait period. */ (...args: Parameters): void; /** * Cancels any pending throttled call. * Useful for cleanup in component destruction. */ cancel(): void; } /** * Creates a throttled version of the provided function that only invokes * at most once per the specified wait period. * * The function is invoked on the leading edge (immediately on first call) * and then at most once per wait period for subsequent calls. * * @template T - The type of the function to throttle. * @param fn - The function to throttle. * @param wait - The minimum time between invocations in milliseconds. * @returns The throttled function with a cancel method. * * @example * // Basic usage - scroll handler * const throttledScroll = throttle(() => { * console.log('Scroll position:', window.scrollY); * }, 100); * window.addEventListener('scroll', throttledScroll); * * @example * // With cleanup * export class ScrollComponent { * private throttledHandler = throttle((e: Event) => this.handleScroll(e), 100); * * ngOnDestroy(): void { * this.throttledHandler.cancel(); * } * } */ declare function throttle void>(fn: T, wait: number): ThrottledFn; /** * Configuration options for the retry function. */ interface RetryOptions { /** * Maximum number of retry attempts. */ readonly attempts: number; /** * Delay between retries in milliseconds. */ readonly delay: number; /** * Multiplier for exponential backoff (optional). * Each retry delay is multiplied by this factor. * @default 1 */ readonly backoff?: number; /** * Optional predicate to determine if an error should trigger a retry. * @param error - The error that occurred. * @returns `true` to retry, `false` to fail immediately. */ readonly shouldRetry?: (error: unknown) => boolean; } /** * Retries an async function with configurable attempts, delay, and backoff. * * @template T - The return type of the async function. * @param fn - The async function to retry. * @param options - Retry configuration. * @returns The result of the successful call. * @throws The last error if all attempts fail. * * @example * // Basic retry with 3 attempts * const data = await retry( * () => fetch('/api/data').then(r => r.json()), * { attempts: 3, delay: 1000 } * ); * * @example * // With exponential backoff * const result = await retry( * () => unreliableApiCall(), * { attempts: 5, delay: 100, backoff: 2 } // delays: 100, 200, 400, 800, 1600 * ); * * @example * // With conditional retry * const result = await retry( * () => apiCall(), * { * attempts: 3, * delay: 500, * shouldRetry: (err) => err instanceof NetworkError * } * ); */ declare function retry(fn: () => Promise, options: RetryOptions): Promise; /** * Creates a new object with only the specified keys from the source object. * * @template T - The type of the source object. * @template K - The keys to pick. * @param obj - The source object. * @param keys - The keys to pick from the object. * @returns A new object containing only the specified keys. * * @example * const user = { id: 1, name: 'John', email: 'john@example.com', age: 30 }; * pick(user, ['id', 'name']); // { id: 1, name: 'John' } * * @example * const config = { host: 'localhost', port: 3000, debug: true }; * pick(config, ['host', 'port']); // { host: 'localhost', port: 3000 } */ declare function pick(obj: T, keys: K[]): Pick; /** * Creates a new object with the specified keys omitted from the source object. * * @template T - The type of the source object. * @template K - The keys to omit. * @param obj - The source object. * @param keys - The keys to omit from the object. * @returns A new object without the specified keys. * * @example * const user = { id: 1, name: 'John', password: 'secret', email: 'john@example.com' }; * omit(user, ['password']); // { id: 1, name: 'John', email: 'john@example.com' } * * @example * const config = { host: 'localhost', port: 3000, debug: true }; * omit(config, ['debug']); // { host: 'localhost', port: 3000 } */ declare function omit(obj: T, keys: K[]): Omit; /** * Creates a deep clone of a value, handling objects, arrays, Date, and RegExp. * Note: Does not handle circular references, functions, or special objects like Map, Set. * For complex cloning needs, consider using `structuredClone()`. * * @template T - The type of the value to clone. * @param value - The value to deep clone. * @returns A deep clone of the value. * * @example * const original = { a: 1, b: { c: 2, d: [3, 4] } }; * const cloned = deepClone(original); * cloned.b.c = 5; * console.log(original.b.c); // 2 (unchanged) * * @example * const arr = [{ id: 1 }, { id: 2 }]; * const clonedArr = deepClone(arr); * clonedArr[0].id = 99; * console.log(arr[0].id); // 1 (unchanged) */ declare function deepClone(value: T): T; /** * Deep merges multiple source objects into a new object. * Later sources override earlier ones. Arrays are replaced, not merged. * * @template T - The type of the resulting object. * @param sources - The source objects to merge. * @returns A new deeply merged object. * * @example * const defaults = { theme: { color: 'blue', size: 'md' }, debug: false }; * const userConfig = { theme: { color: 'red' }, debug: true }; * deepMerge(defaults, userConfig); * // { theme: { color: 'red', size: 'md' }, debug: true } * * @example * const a = { arr: [1, 2], nested: { x: 1 } }; * const b = { arr: [3, 4], nested: { y: 2 } }; * deepMerge(a, b); * // { arr: [3, 4], nested: { x: 1, y: 2 } } - arrays are replaced */ declare function deepMerge(...sources: Partial[]): T; /** * Performs a deep equality comparison between two values. * Handles primitives, objects, arrays, Date, and RegExp. * * @template T - The type of values to compare. * @param a - The first value. * @param b - The second value. * @returns `true` if values are deeply equal; otherwise, `false`. * * @example * deepEqual({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } }); // true * deepEqual({ a: 1 }, { a: 2 }); // false * deepEqual([1, [2, 3]], [1, [2, 3]]); // true * deepEqual([1, 2], [1, 2, 3]); // false * deepEqual(new Date('2024-01-01'), new Date('2024-01-01')); // true */ declare function deepEqual(a: T, b: T): boolean; /** * Checks if a value is a plain object (not null, not an array). * * @param value - The value to check. * @returns `true` if value is a plain object; otherwise, `false`. * * @example * isPlainObject({ a: 1 }); // true * isPlainObject([1, 2]); // false * isPlainObject(null); // false */ declare function isPlainObject(value: unknown): value is Record; /** * Utility type that recursively maps the object type to the type of the resolved path. * * @example * type A = { user: { profile: { name: string } } }; * type Result = ResolvePath; // Result is string */ type ResolvePath = P extends `${infer Head}.${infer Tail}` ? Head extends keyof T ? ResolvePath : never : P extends keyof T ? T[P] : never; /** * Resolves a nested path in an object, returning the value at the specified path. * * This function splits the provided `path` into keys and iterates through the object to access the * corresponding value at each key. If any part of the path is undefined or if the path leads to a non-object, * it returns `undefined`. * * @template T - The type of the object. * @template P - The dot-separated string path type. * @param obj - The object to resolve the path within. * @param path - The dot-separated string representing the path to the value. * @returns The value at the resolved path, or `undefined` if any part of the path is invalid. * * @example * const obj = { user: { profile: { name: 'John Doe' } } }; * const result = resolvePath(obj, 'user.profile.name'); * console.log(result); // 'John Doe' * * @example * const result2 = resolvePath(obj, 'user.address.city'); * console.log(result2); // undefined */ declare function resolvePath(obj: T, path: P): ResolvePath | undefined; /** * Splits an array into chunks of the specified size. * * @template T - The type of array elements. * @param array - The array to split. * @param size - The size of each chunk (must be positive). * @returns An array of chunks. * * @example * chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]] * chunk([1, 2, 3, 4], 2); // [[1, 2], [3, 4]] * chunk([1, 2, 3], 5); // [[1, 2, 3]] * chunk([], 2); // [] */ declare function chunk(array: T[], size: number): T[][]; /** * Splits an array into two groups based on a predicate function. * The first array contains elements that satisfy the predicate, * the second contains elements that don't. * * @template T - The type of array elements. * @param array - The array to partition. * @param predicate - The function to test each element. * @returns A tuple of [truthy, falsy] arrays. * * @example * const numbers = [1, 2, 3, 4, 5, 6]; * partition(numbers, n => n % 2 === 0); // [[2, 4, 6], [1, 3, 5]] * * @example * const users = [ * { name: 'Alice', active: true }, * { name: 'Bob', active: false }, * { name: 'Charlie', active: true } * ]; * partition(users, u => u.active); * // [[{ name: 'Alice', active: true }, { name: 'Charlie', active: true }], [{ name: 'Bob', active: false }]] */ declare function partition(array: T[], predicate: (item: T) => boolean): [T[], T[]]; /** * Groups an array of items based on a provided predicate function. * * @template K - The type of keys produced by the predicate, typically a string, number, or symbol. * @template V - The type of items in the collection. * @param collection - The array of items to be grouped. * @param predicate - A function that takes an item and returns a key by which to group the item. * @returns An object where each key is a group identifier produced by the predicate, * and the value is an array of items belonging to that group. * * @example * // Group an array of people by their age * const people = [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 25 }, { name: 'Charlie', age: 30 }]; * const groupedByAge = groupBy(people, person => person.age); * // Output: * // { * // 25: [{ name: 'Alice', age: 25 }, { name: 'Bob', age: 25 }], * // 30: [{ name: 'Charlie', age: 30 }] * // } */ declare function groupBy(collection: V[], predicate: (item: V) => K): Record; export { chunk, debounce, deepClone, deepEqual, deepMerge, groupBy, isPlainObject, joinClasses, mergeClasses, omit, partition, pick, resolvePath, retry, throttle }; export type { DebounceOptions, DebouncedFn, ResolvePath, RetryOptions, ThrottledFn };