frontix
Version:
Modern utility toolkit for frontend developers — 25+ utilities for strings, dates, validation, async operations, deep objects, and more. TypeScript-first, tree-shakable, and lightweight. Includes debounce, throttle, deep cloning, date formatting, validati
1 lines • 53.3 kB
Source Map (JSON)
{"version":3,"sources":["../src/string/truncate.ts","../src/number/convert.ts","../src/array/toDropdown.ts","../src/date/formatDate.ts","../src/misc/debounce.ts","../src/validation/safeValue.ts","../src/validation/validateEmail.ts","../src/validation/validatePhone.ts","../src/async/retry.ts","../src/async/timeout.ts","../src/async/throttle.ts","../src/deep/clone.ts","../src/deep/isEqual.ts","../src/deep/merge.ts","../src/date/timeAgo.ts","../src/date/toTimeZone.ts","../src/date/comparison.ts","../src/string/slugify.ts","../src/string/capitalize.ts","../src/string/caseConversion.ts"],"names":["truncate","str","length","suffix","toNumber","value","parsed","toString","toDropdown","arr","item","formatDate","date","format","locale","dayjsDate","dayjs","debounce","func","wait","timeout","args","safeValue","fallback","validateEmail","email","emailRegex","validatePhone","phone","cleaned","digitsOnly","separatorCount","digitCount","groups","group","retry","fn","retries","delay","resolve","reject","attempts","attempt","result","error","backoffDelay","ms","timer","throttle","lastCall","timeoutId","now","deepClone","obj","visited","cloned","i","key","clonedObj","isEqual","a","b","found","bValue","keysA","keysB","merge","target","sources","source","sourceValue","targetValue","timeAgo","targetDate","diffInMs","diffInSeconds","diffInMinutes","diffInHours","diffInDays","diffInWeeks","diffInMonths","diffInYears","isPast","prefix","toTimeZone","timeZone","options","isToday","today","isYesterday","yesterday","isThisWeek","startOfWeek","dayOfWeek","endOfWeek","isThisMonth","isThisYear","slugify","separator","escapedSeparator","capitalize","allWords","word","index","camelCase","trimmed","parts","part","kebabCase","snakeCase","pascalCase","camel"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Truncates a string to a specified length with an optional custom suffix.\n *\n * @param str - The input string to truncate\n * @param length - The maximum length of the truncated string (excluding suffix)\n * @param suffix - The suffix to append when truncating (default: \"...\")\n * @returns The truncated string with suffix if truncated, or the original string if no truncation needed\n *\n * @example\n * ```typescript\n * truncate(\"Hello World\", 5); // \"Hello...\"\n * truncate(\"Short\", 10); // \"Short\"\n * truncate(\"Very Long Text\", 7, \"~\"); // \"Very Lo~\"\n * ```\n */\nexport function truncate(\n str: string,\n length: number,\n suffix: string = \"...\"\n): string {\n if (!str || typeof str !== \"string\") return \"\";\n if (length < 0) return str;\n\n return str.length > length ? str.slice(0, length) + suffix : str;\n}\n","/**\n * Safely converts a value to a number with fallback to 0.\n *\n * @param value - The value to convert (string, number, or any other type)\n * @returns A number, or 0 if the conversion fails\n *\n * @example\n * ```typescript\n * toNumber(\"42\"); // 42\n * toNumber(\"abc\"); // 0\n * toNumber(123); // 123\n * toNumber(null); // 0\n * toNumber(undefined); // 0\n * ```\n */\nexport function toNumber(value: unknown): number {\n if (typeof value === \"number\") return value;\n if (typeof value === \"string\") {\n const parsed = Number(value);\n return isNaN(parsed) ? 0 : parsed;\n }\n return 0;\n}\n\n/**\n * Safely converts a value to a string with fallback to empty string.\n *\n * @param value - The value to convert (string, number, or any other type)\n * @returns A string representation of the value, or empty string if null/undefined\n *\n * @example\n * ```typescript\n * toString(42); // \"42\"\n * toString(\"hello\"); // \"hello\"\n * toString(null); // \"\"\n * toString(undefined); // \"\"\n * ```\n */\nexport function toString(value: unknown): string {\n if (value === null || value === undefined) return \"\";\n return String(value);\n}\n","/**\n * Converts an array to dropdown-friendly objects with label and value properties.\n *\n * @param arr - The input array to convert\n * @returns An array of objects with `label` and `value` properties\n *\n * @example\n * ```typescript\n * toDropdown([\"Apple\", \"Banana\"]);\n * // Returns: [{ label: \"Apple\", value: \"Apple\" }, { label: \"Banana\", value: \"Banana\" }]\n *\n * toDropdown([1, 2, 3]);\n * // Returns: [{ label: 1, value: 1 }, { label: 2, value: 2 }, { label: 3, value: 3 }]\n * ```\n */\nexport function toDropdown<T>(arr: T[]): { label: T; value: T }[] {\n if (!Array.isArray(arr)) return [];\n return arr.map(item => ({ label: item, value: item }));\n}\n","import dayjs from \"dayjs\";\n\n/**\n * Formats a date with custom format and locale support.\n *\n * @param date - The date to format (string, Date object, or dayjs object)\n * @param format - The format string (default: \"DD/MM/YYYY\")\n * @param locale - The locale for formatting (default: \"en\")\n * @returns Formatted date string\n *\n * @example\n * ```typescript\n * formatDate(\"2025-01-15\"); // \"15/01/2025\"\n * formatDate(\"2025-01-15\", \"MMMM D, YYYY\"); // \"January 15, 2025\"\n * formatDate(\"2025-01-15\", \"DD/MM/YYYY\", \"fr\"); // \"15/01/2025\"\n * ```\n */\nexport function formatDate(\n date: string | Date | dayjs.Dayjs,\n format: string = \"DD/MM/YYYY\",\n locale: string = \"en\"\n): string {\n try {\n // Handle empty strings and null/undefined\n if (!date || (typeof date === \"string\" && date.trim() === \"\")) {\n return \"\";\n }\n\n const dayjsDate = dayjs(date);\n\n // Check if the date is valid\n if (!dayjsDate.isValid()) {\n return \"\";\n }\n\n return dayjsDate.locale(locale).format(format);\n } catch {\n console.warn(\"Invalid date provided to formatDate:\", date);\n return \"\";\n }\n}\n","/**\n * Creates a debounced function that delays invoking the provided function\n * until after the specified wait time has elapsed since the last time it was invoked.\n *\n * @param func - The function to debounce\n * @param wait - The number of milliseconds to delay\n * @returns A debounced version of the provided function\n *\n * @example\n * ```typescript\n * const debouncedSearch = debounce((query) => {\n * console.log(\"Searching for:\", query);\n * }, 300);\n *\n * // Only the last call will execute after 300ms\n * debouncedSearch(\"a\");\n * debouncedSearch(\"ab\");\n * debouncedSearch(\"abc\"); // Only this will execute\n * ```\n */\nexport function debounce<T extends (...args: unknown[]) => void>(\n func: T,\n wait: number\n): (...args: Parameters<T>) => void {\n let timeout: ReturnType<typeof globalThis.setTimeout> | undefined;\n\n return (...args: Parameters<T>): void => {\n if (timeout) {\n globalThis.clearTimeout(timeout);\n }\n timeout = globalThis.setTimeout(() => func(...args), wait);\n };\n}\n","/**\r\n * Replaces null, undefined, or empty string values with a fallback value.\r\n * Useful for displaying \"N/A\" or \"---\" in UI components.\r\n *\r\n * @param value - The value to check\r\n * @param fallback - The fallback value to use if the original is null/undefined/empty\r\n * @returns The original value if valid, otherwise the fallback value\r\n *\r\n * @example\r\n * ```typescript\r\n * safeValue(null, \"N/A\"); // \"N/A\"\r\n * safeValue(undefined, \"---\"); // \"---\"\r\n * safeValue(\"\", \"Empty\"); // \"Empty\"\r\n * safeValue(\"Hello\", \"World\"); // \"Hello\"\r\n * safeValue(42, \"N/A\"); // 42\r\n * ```\r\n */\r\nexport function safeValue<T>(value: T, fallback: T): T {\r\n // Check if value is null, undefined, or empty string\r\n if (value === null || value === undefined) {\r\n return fallback;\r\n }\r\n \r\n // Check for empty string\r\n if (typeof value === 'string' && value.trim() === '') {\r\n return fallback;\r\n }\r\n \r\n return value;\r\n}\r\n","/**\r\n * Validates an email address format.\r\n * Uses a comprehensive regex pattern to check email validity.\r\n *\r\n * @param email - The email address to validate\r\n * @returns true if the email format is valid, false otherwise\r\n *\r\n * @example\r\n * ```typescript\r\n * validateEmail(\"user@example.com\"); // true\r\n * validateEmail(\"invalid-email\"); // false\r\n * validateEmail(\"\"); // false\r\n * validateEmail(\"user@domain.co.uk\"); // true\r\n * ```\r\n */\r\nexport function validateEmail(email: string): boolean {\r\n if (!email || typeof email !== 'string') {\r\n return false;\r\n }\r\n \r\n // Comprehensive email regex pattern with stricter validation\r\n const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;\r\n \r\n // Additional checks for common invalid patterns\r\n if (email.includes('..') || email.includes('@@') || email.startsWith('.') || email.endsWith('.')) {\r\n return false;\r\n }\r\n \r\n return emailRegex.test(email.trim());\r\n}\r\n","/**\r\n * Validates a phone number format.\r\n * Supports international formats and common patterns.\r\n *\r\n * @param phone - The phone number to validate\r\n * @returns true if the phone number format is valid, false otherwise\r\n *\r\n * @example\r\n * ```typescript\r\n * validatePhone(\"+1-555-123-4567\"); // true\r\n * validatePhone(\"555-123-4567\"); // true\r\n * validatePhone(\"(555) 123-4567\"); // true\r\n * validatePhone(\"555.123.4567\"); // true\r\n * validatePhone(\"invalid\"); // false\r\n * ```\r\n */\r\nexport function validatePhone(phone: string): boolean {\r\n if (!phone || typeof phone !== 'string') {\r\n return false;\r\n }\r\n \r\n // Remove all non-digit characters except + for international prefix\r\n const cleaned = phone.replace(/[^\\d+]/g, '');\r\n \r\n // Check if it starts with + (international) or just digits\r\n if (cleaned.startsWith('+')) {\r\n // International format: + followed by 7-15 digits\r\n if (!/^\\+\\d{7,15}$/.test(cleaned)) {\r\n return false;\r\n }\r\n } else {\r\n // Local format: 7-15 digits\r\n if (!/^\\d{7,15}$/.test(cleaned)) {\r\n return false;\r\n }\r\n }\r\n \r\n // Additional validation: check if the cleaned number is reasonable\r\n const digitsOnly = cleaned.replace('+', '');\r\n if (digitsOnly.length < 7 || digitsOnly.length > 15) {\r\n return false;\r\n }\r\n \r\n // Check for excessive length in the original input\r\n const originalDigits = phone.replace(/[^\\d+]/g, '');\r\n if (originalDigits.length > 20) { // Allow some extra characters but not too many\r\n return false;\r\n }\r\n \r\n // Additional check: reject if there are too many consecutive non-digit characters\r\n if (phone.replace(/[\\d+\\s]/g, '').length > 10) {\r\n return false;\r\n }\r\n \r\n // Additional check: reject if the phone number is too long overall\r\n if (phone.length > 25) {\r\n return false;\r\n }\r\n \r\n // Additional check: reject if there are too many consecutive separators\r\n if (/([^\\d+\\s]){3,}/.test(phone)) {\r\n return false;\r\n }\r\n \r\n // Additional check: reject if there are too many separators relative to digits\r\n const separatorCount = phone.replace(/[\\d+\\s]/g, '').length;\r\n const digitCount = phone.replace(/[^\\d]/g, '').length;\r\n if (separatorCount > digitCount / 2) {\r\n return false;\r\n }\r\n \r\n // Additional check: reject if the phone number has an unreasonable pattern\r\n // A typical phone number should not have more than 4-5 separators\r\n if (separatorCount > 5) {\r\n return false;\r\n }\r\n \r\n // Additional check: reject if the phone number doesn't follow typical grouping patterns\r\n // For non-international numbers, check if the grouping makes sense\r\n if (!cleaned.startsWith('+')) {\r\n const groups = phone.split(/[^\\d]/).filter(group => group.length > 0);\r\n // If there are no separators, the entire number should be valid\r\n if (groups.length === 1) {\r\n // Single group - just check the total length (already done above)\r\n return true;\r\n }\r\n // Multiple groups - check if any group is unreasonably large\r\n for (const group of groups) {\r\n if (group.length > 4) {\r\n return false;\r\n }\r\n }\r\n // Additional check: reject if there are too many groups\r\n // Most phone numbers have 2-4 groups (e.g., 555-123-4567 has 3 groups)\r\n if (groups.length > 4) {\r\n return false;\r\n }\r\n // Additional check: reject if the pattern is unusual\r\n // A typical phone number should not have 4 groups unless it's a very long number\r\n if (groups.length === 4 && digitCount < 12) {\r\n return false;\r\n }\r\n // Additional check: reject if the pattern is unusual for 12-digit numbers\r\n // A 12-digit number with 4 groups like '555-123-4567-890' is not standard\r\n if (groups.length === 4 && digitCount === 12) {\r\n return false;\r\n }\r\n }\r\n \r\n return true;\r\n}\r\n","/**\r\n * Retries a failed async function with configurable retry attempts and delay.\r\n * Useful for handling network failures or temporary errors.\r\n *\r\n * @param fn - The async function to retry\r\n * @param retries - Maximum number of retry attempts (default: 3)\r\n * @param delay - Base delay between retries in milliseconds (default: 1000)\r\n * @returns Promise that resolves with the function result or rejects after all retries\r\n *\r\n * @example\r\n * ```typescript\r\n * const fetchData = retry(async () => {\r\n * const response = await fetch('/api/data');\r\n * if (!response.ok) throw new Error('Failed to fetch');\r\n * return response.json();\r\n * }, 3, 2000);\r\n * ```\r\n */\r\nexport function retry<T>(\r\n fn: () => Promise<T>,\r\n retries: number = 3,\r\n delay: number = 1000\r\n): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n let attempts = 0;\r\n \r\n const attempt = async () => {\r\n try {\r\n attempts++;\r\n const result = await fn();\r\n resolve(result);\r\n } catch (error) {\r\n if (attempts >= retries) {\r\n reject(error);\r\n return;\r\n }\r\n \r\n // Exponential backoff: delay * 2^(attempts-1)\r\n const backoffDelay = delay * Math.pow(2, attempts - 1);\r\n \r\n // Use setTimeout with a callback to ensure proper async behavior\r\n setTimeout(() => {\r\n attempt();\r\n }, backoffDelay);\r\n }\r\n };\r\n \r\n // Start the first attempt\r\n attempt();\r\n });\r\n}\r\n","/**\r\n * Executes a function with a timeout. If the function doesn't complete within\r\n * the specified time, it rejects with a timeout error.\r\n *\r\n * @param fn - The async function to execute\r\n * @param ms - Timeout in milliseconds\r\n * @returns Promise that resolves with the function result or rejects on timeout\r\n *\r\n * @example\r\n * ```typescript\r\n * const result = await timeout(\r\n * async () => await fetch('/api/slow-endpoint'),\r\n * 5000\r\n * );\r\n * ```\r\n */\r\nexport function timeout<T>(\r\n fn: () => Promise<T>,\r\n ms: number\r\n): Promise<T> {\r\n return new Promise((resolve, reject) => {\r\n const timer = setTimeout(() => {\r\n reject(new Error(`Operation timed out after ${ms}ms`));\r\n }, ms);\r\n \r\n fn()\r\n .then((result) => {\r\n clearTimeout(timer);\r\n resolve(result);\r\n })\r\n .catch((error) => {\r\n clearTimeout(timer);\r\n reject(error);\r\n });\r\n });\r\n}\r\n","/**\r\n * Throttles function calls to a maximum frequency.\r\n * Ensures the function is called at most once per specified time interval.\r\n *\r\n * @param fn - The function to throttle\r\n * @param ms - Minimum time interval between function calls in milliseconds\r\n * @returns A throttled version of the function\r\n *\r\n * @example\r\n * ```typescript\r\n * const throttledScroll = throttle(() => {\r\n * console.log('Scroll event throttled');\r\n * }, 100);\r\n * \r\n * window.addEventListener('scroll', throttledScroll);\r\n * ```\r\n */\r\nexport function throttle<T extends (...args: any[]) => any>(\r\n fn: T,\r\n ms: number\r\n): (...args: Parameters<T>) => void {\r\n let lastCall = 0;\r\n let timeoutId: NodeJS.Timeout | null = null;\r\n \r\n return (...args: Parameters<T>) => {\r\n const now = Date.now();\r\n \r\n if (now - lastCall >= ms) {\r\n // Enough time has passed, execute immediately\r\n lastCall = now;\r\n fn(...args);\r\n } else {\r\n // Schedule execution for later\r\n if (timeoutId) {\r\n clearTimeout(timeoutId);\r\n }\r\n \r\n timeoutId = setTimeout(() => {\r\n lastCall = Date.now();\r\n fn(...args);\r\n timeoutId = null;\r\n }, ms - (now - lastCall));\r\n }\r\n };\r\n}\r\n","/**\r\n * Creates a deep clone of an object, handling circular references.\r\n * Supports primitives, objects, arrays, dates, and other built-in types.\r\n *\r\n * @param obj - The object to clone\r\n * @returns A deep clone of the object\r\n *\r\n * @example\r\n * ```typescript\r\n * const original = { a: 1, b: { c: 2 } };\r\n * const cloned = deepClone(original);\r\n * cloned.b.c = 3;\r\n * console.log(original.b.c); // 2 (unchanged)\r\n * ```\r\n */\r\nexport function deepClone<T>(obj: T, visited = new WeakMap()): T {\r\n // Handle primitives and null\r\n if (obj === null || typeof obj !== 'object') {\r\n return obj;\r\n }\r\n \r\n // Handle circular references\r\n if (visited.has(obj)) {\r\n return visited.get(obj);\r\n }\r\n \r\n // Handle Date objects\r\n if (obj instanceof Date) {\r\n const cloned = new Date(obj.getTime()) as T;\r\n visited.set(obj, cloned);\r\n return cloned;\r\n }\r\n \r\n // Handle Array objects\r\n if (Array.isArray(obj)) {\r\n const cloned: any[] = [];\r\n visited.set(obj, cloned as T);\r\n for (let i = 0; i < obj.length; i++) {\r\n cloned[i] = deepClone(obj[i], visited);\r\n }\r\n return cloned as T;\r\n }\r\n \r\n // Handle RegExp objects\r\n if (obj instanceof RegExp) {\r\n const cloned = new RegExp(obj.source, obj.flags) as T;\r\n visited.set(obj, cloned);\r\n return cloned;\r\n }\r\n \r\n // Handle Map objects\r\n if (obj instanceof Map) {\r\n const cloned = new Map();\r\n visited.set(obj, cloned as T);\r\n obj.forEach((value, key) => {\r\n cloned.set(deepClone(key, visited), deepClone(value, visited));\r\n });\r\n return cloned as T;\r\n }\r\n \r\n // Handle Set objects\r\n if (obj instanceof Set) {\r\n const cloned = new Set();\r\n visited.set(obj, cloned as T);\r\n obj.forEach(value => {\r\n cloned.add(deepClone(value, visited));\r\n });\r\n return cloned as T;\r\n }\r\n \r\n // Handle plain objects\r\n const clonedObj: any = {};\r\n visited.set(obj, clonedObj as T);\r\n \r\n for (const key in obj) {\r\n if (obj.hasOwnProperty(key)) {\r\n clonedObj[key] = deepClone((obj as any)[key], visited);\r\n }\r\n }\r\n \r\n return clonedObj as T;\r\n}\r\n","/**\r\n * Performs a deep equality comparison between two values.\r\n * Handles objects, arrays, dates, and other complex types.\r\n *\r\n * @param a - First value to compare\r\n * @param b - Second value to compare\r\n * @returns true if the values are deeply equal, false otherwise\r\n *\r\n * @example\r\n * ```typescript\r\n * isEqual({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } }); // true\r\n * isEqual([1, 2, 3], [1, 2, 3]); // true\r\n * isEqual(new Date('2023-01-01'), new Date('2023-01-01')); // true\r\n * isEqual({ a: 1 }, { a: 2 }); // false\r\n * ```\r\n */\r\nexport function isEqual(a: any, b: any): boolean {\r\n // Handle primitive values\r\n if (a === b) {\r\n return true;\r\n }\r\n \r\n // Handle null/undefined\r\n if (a == null || b == null) {\r\n return a === b;\r\n }\r\n \r\n // Handle different types\r\n if (typeof a !== typeof b) {\r\n return false;\r\n }\r\n \r\n // Handle Date objects\r\n if (a instanceof Date && b instanceof Date) {\r\n return a.getTime() === b.getTime();\r\n }\r\n \r\n // Handle RegExp objects\r\n if (a instanceof RegExp && b instanceof RegExp) {\r\n return a.source === b.source && a.flags === b.flags;\r\n }\r\n \r\n // Handle Map objects\r\n if (a instanceof Map && b instanceof Map) {\r\n if (a.size !== b.size) return false;\r\n for (const [key, value] of a) {\r\n if (!b.has(key) || !isEqual(value, b.get(key))) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n \r\n // Handle Set objects\r\n if (a instanceof Set && b instanceof Set) {\r\n if (a.size !== b.size) return false;\r\n for (const value of a) {\r\n let found = false;\r\n for (const bValue of b) {\r\n if (isEqual(value, bValue)) {\r\n found = true;\r\n break;\r\n }\r\n }\r\n if (!found) return false;\r\n }\r\n return true;\r\n }\r\n \r\n // Handle arrays\r\n if (Array.isArray(a) && Array.isArray(b)) {\r\n if (a.length !== b.length) return false;\r\n for (let i = 0; i < a.length; i++) {\r\n if (!isEqual(a[i], b[i])) return false;\r\n }\r\n return true;\r\n }\r\n \r\n // Handle objects\r\n if (typeof a === 'object' && typeof b === 'object') {\r\n const keysA = Object.keys(a);\r\n const keysB = Object.keys(b);\r\n \r\n if (keysA.length !== keysB.length) return false;\r\n \r\n for (const key of keysA) {\r\n if (!keysB.includes(key) || !isEqual(a[key], b[key])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n \r\n return false;\r\n}\r\n","/**\r\n * Deeply merges multiple objects, with later objects taking precedence.\r\n * Handles nested objects, arrays, and preserves non-object values.\r\n *\r\n * @param target - The target object to merge into\r\n * @param sources - Source objects to merge from\r\n * @returns The merged object\r\n *\r\n * @example\r\n * ```typescript\r\n * const obj1 = { a: 1, b: { c: 2 } };\r\n * const obj2 = { b: { d: 3 }, e: 4 };\r\n * const merged = merge(obj1, obj2);\r\n * // Result: { a: 1, b: { c: 2, d: 3 }, e: 4 }\r\n * ```\r\n */\r\nexport function merge<T extends Record<string, any>>(\r\n target: T,\r\n ...sources: Partial<T>[]\r\n): T {\r\n if (!sources.length) {\r\n return target;\r\n }\r\n \r\n const source = sources.shift();\r\n if (!source) {\r\n return target;\r\n }\r\n \r\n if (typeof source !== 'object' || source === null) {\r\n return target;\r\n }\r\n \r\n for (const key in source) {\r\n if (source.hasOwnProperty(key)) {\r\n const sourceValue = source[key];\r\n const targetValue = target[key];\r\n \r\n if (\r\n sourceValue &&\r\n typeof sourceValue === 'object' &&\r\n !Array.isArray(sourceValue) &&\r\n targetValue &&\r\n typeof targetValue === 'object' &&\r\n !Array.isArray(targetValue)\r\n ) {\r\n // Recursively merge nested objects\r\n (target as any)[key] = merge(targetValue, sourceValue);\r\n } else {\r\n // Override with source value\r\n (target as any)[key] = sourceValue;\r\n }\r\n }\r\n }\r\n \r\n // Continue with remaining sources\r\n return merge(target, ...sources);\r\n}\r\n","/**\r\n * Converts a date to a human-readable relative time string.\r\n * Shows time differences like \"5 minutes ago\", \"2 hours ago\", etc.\r\n *\r\n * @param date - The date to convert\r\n * @param now - Reference date (defaults to current time)\r\n * @returns Human-readable relative time string\r\n *\r\n * @example\r\n * ```typescript\r\n * timeAgo(new Date('2023-01-01T10:00:00Z')); // \"2 years ago\"\r\n * timeAgo(Date.now() - 300000); // \"5 minutes ago\"\r\n * timeAgo(Date.now() + 86400000); // \"in 1 day\"\r\n * ```\r\n */\r\nexport function timeAgo(date: Date | number, now: Date | number = Date.now()): string {\r\n const targetDate = new Date(date);\r\n const currentDate = new Date(now);\r\n \r\n const diffInMs = currentDate.getTime() - targetDate.getTime();\r\n const diffInSeconds = Math.floor(Math.abs(diffInMs) / 1000);\r\n const diffInMinutes = Math.floor(diffInSeconds / 60);\r\n const diffInHours = Math.floor(diffInMinutes / 60);\r\n const diffInDays = Math.floor(diffInHours / 24);\r\n const diffInWeeks = Math.floor(diffInDays / 7);\r\n const diffInMonths = Math.floor(diffInDays / 30);\r\n const diffInYears = Math.floor(diffInDays / 365);\r\n \r\n const isPast = diffInMs > 0;\r\n const prefix = isPast ? '' : 'in ';\r\n const suffix = isPast ? ' ago' : '';\r\n \r\n // Handle \"just now\" case for very recent times (within 1 minute)\r\n if (diffInSeconds < 60) {\r\n return 'just now';\r\n } else if (diffInMinutes < 60) {\r\n const unit = diffInMinutes === 1 ? 'minute' : 'minutes';\r\n return `${prefix}${diffInMinutes} ${unit}${suffix}`;\r\n } else if (diffInHours < 24) {\r\n const unit = diffInHours === 1 ? 'hour' : 'hours';\r\n return `${prefix}${diffInHours} ${unit}${suffix}`;\r\n } else if (diffInDays < 7) {\r\n const unit = diffInDays === 1 ? 'day' : 'days';\r\n return `${prefix}${diffInDays} ${unit}${suffix}`;\r\n } else if (diffInWeeks < 4) {\r\n const unit = diffInWeeks === 1 ? 'week' : 'weeks';\r\n return `${prefix}${diffInWeeks} ${unit}${suffix}`;\r\n } else if (diffInMonths < 12) {\r\n const unit = diffInMonths === 1 ? 'month' : 'months';\r\n return `${prefix}${diffInMonths} ${unit}${suffix}`;\r\n } else {\r\n const unit = diffInYears === 1 ? 'year' : 'years';\r\n return `${prefix}${diffInYears} ${unit}${suffix}`;\r\n }\r\n}\r\n","/**\r\n * Converts a date to a specific timezone.\r\n * Returns the date in the target timezone with proper formatting.\r\n *\r\n * @param date - The date to convert\r\n * @param timeZone - The target timezone (e.g., 'America/New_York', 'Europe/London')\r\n * @param options - Intl.DateTimeFormatOptions for formatting\r\n * @returns Formatted date string in the target timezone\r\n *\r\n * @example\r\n * ```typescript\r\n * toTimeZone(new Date(), 'America/New_York'); // \"1/15/2024, 10:30:00 AM EST\"\r\n * toTimeZone(new Date(), 'Europe/London', { \r\n * dateStyle: 'full' \r\n * }); // \"Monday, January 15, 2024\"\r\n * ```\r\n */\r\nexport function toTimeZone(\r\n date: Date | number,\r\n timeZone: string,\r\n options: Intl.DateTimeFormatOptions = {}\r\n): string {\r\n const targetDate = new Date(date);\r\n \r\n try {\r\n // Use Intl.DateTimeFormat for timezone conversion\r\n const formatter = new Intl.DateTimeFormat('en-US', {\r\n timeZone,\r\n ...options\r\n });\r\n \r\n return formatter.format(targetDate);\r\n } catch (error) {\r\n // Fallback if timezone is invalid\r\n console.warn(`Invalid timezone: ${timeZone}. Using local timezone.`);\r\n const fallbackFormatter = new Intl.DateTimeFormat('en-US', options);\r\n return fallbackFormatter.format(targetDate);\r\n }\r\n}\r\n","/**\r\n * Date comparison utility functions for common date checks.\r\n * Provides easy ways to check if dates fall within specific time periods.\r\n */\r\n\r\n/**\r\n * Checks if a date is today.\r\n *\r\n * @param date - The date to check\r\n * @returns true if the date is today, false otherwise\r\n *\r\n * @example\r\n * ```typescript\r\n * isToday(new Date()); // true\r\n * isToday(new Date('2023-01-01')); // false\r\n * ```\r\n */\r\nexport function isToday(date: Date | number): boolean {\r\n const targetDate = new Date(date);\r\n const today = new Date();\r\n \r\n return (\r\n targetDate.getDate() === today.getDate() &&\r\n targetDate.getMonth() === today.getMonth() &&\r\n targetDate.getFullYear() === today.getFullYear()\r\n );\r\n}\r\n\r\n/**\r\n * Checks if a date is yesterday.\r\n *\r\n * @param date - The date to check\r\n * @returns true if the date is yesterday, false otherwise\r\n *\r\n * @example\r\n * ```typescript\r\n * const yesterday = new Date();\r\n * yesterday.setDate(yesterday.getDate() - 1);\r\n * isYesterday(yesterday); // true\r\n * ```\r\n */\r\nexport function isYesterday(date: Date | number): boolean {\r\n const targetDate = new Date(date);\r\n const today = new Date();\r\n const yesterday = new Date(today);\r\n yesterday.setDate(today.getDate() - 1);\r\n \r\n return (\r\n targetDate.getDate() === yesterday.getDate() &&\r\n targetDate.getMonth() === yesterday.getMonth() &&\r\n targetDate.getFullYear() === yesterday.getFullYear()\r\n );\r\n}\r\n\r\n/**\r\n * Checks if a date is within the current week.\r\n *\r\n * @param date - The date to check\r\n * @returns true if the date is within the current week, false otherwise\r\n *\r\n * @example\r\n * ```typescript\r\n * isThisWeek(new Date()); // true\r\n * isThisWeek(new Date('2023-01-01')); // false\r\n * ```\r\n */\r\nexport function isThisWeek(date: Date | number): boolean {\r\n const targetDate = new Date(date);\r\n const today = new Date();\r\n \r\n // Get start of current week (Sunday = 0, Monday = 1, etc.)\r\n const startOfWeek = new Date(today);\r\n const dayOfWeek = today.getDay(); // 0 for Sunday, 1 for Monday, etc.\r\n startOfWeek.setDate(today.getDate() - dayOfWeek);\r\n startOfWeek.setHours(0, 0, 0, 0);\r\n \r\n // Get end of current week (Saturday)\r\n const endOfWeek = new Date(startOfWeek);\r\n endOfWeek.setDate(startOfWeek.getDate() + 6);\r\n endOfWeek.setHours(23, 59, 59, 999);\r\n \r\n // Ensure targetDate is within the week boundaries\r\n return targetDate >= startOfWeek && targetDate <= endOfWeek;\r\n}\r\n\r\n/**\r\n * Checks if a date is within the current month.\r\n *\r\n * @param date - The date to check\r\n * @returns true if the date is within the current month, false otherwise\r\n *\r\n * @example\r\n * ```typescript\r\n * isThisMonth(new Date()); // true\r\n * isThisMonth(new Date('2023-01-01')); // false\r\n * ```\r\n */\r\nexport function isThisMonth(date: Date | number): boolean {\r\n const targetDate = new Date(date);\r\n const today = new Date();\r\n \r\n return (\r\n targetDate.getMonth() === today.getMonth() &&\r\n targetDate.getFullYear() === today.getFullYear()\r\n );\r\n}\r\n\r\n/**\r\n * Checks if a date is within the current year.\r\n *\r\n * @param date - The date to check\r\n * @returns true if the date is within the current year, false otherwise\r\n *\r\n * @example\r\n * ```typescript\r\n * isThisYear(new Date()); // true\r\n * isThisYear(new Date('2023-01-01')); // false\r\n * ```\r\n */\r\nexport function isThisYear(date: Date | number): boolean {\r\n const targetDate = new Date(date);\r\n const today = new Date();\r\n \r\n return targetDate.getFullYear() === today.getFullYear();\r\n}\r\n","/**\r\n * Converts a string to a URL-friendly slug.\r\n * Removes special characters, converts spaces to hyphens, and makes lowercase.\r\n *\r\n * @param str - The string to convert\r\n * @param separator - Character to use as separator (default: '-')\r\n * @returns URL-friendly slug string\r\n *\r\n * @example\r\n * ```typescript\r\n * slugify(\"Hello World!\"); // \"hello-world\"\r\n * slugify(\"User's Profile\", '_'); // \"users_profile\"\r\n * slugify(\"Café & Résumé\"); // \"cafe-resume\"\r\n * ```\r\n */\r\nexport function slugify(str: string, separator: string = '-'): string {\r\n if (!str || typeof str !== 'string') {\r\n return '';\r\n }\r\n \r\n // Handle empty separator case\r\n if (separator === '') {\r\n return str\r\n .toLowerCase()\r\n .trim()\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '')\r\n .replace(/[^a-z0-9]/g, '');\r\n }\r\n \r\n // Escape special regex characters in separator\r\n const escapedSeparator = separator.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\r\n \r\n return str\r\n .toLowerCase()\r\n .trim()\r\n // Replace accented characters with their ASCII equivalents\r\n .normalize('NFD')\r\n .replace(/[\\u0300-\\u036f]/g, '')\r\n // First, normalize consecutive separators in the input (like -- or ___)\r\n .replace(/[-_]{2,}/g, separator)\r\n // Remove apostrophes and periods entirely\r\n .replace(/['.]/g, '')\r\n // Replace other special characters with separator\r\n .replace(/[^a-z0-9\\s-]/g, separator)\r\n // Replace spaces with separator\r\n .replace(/\\s+/g, separator)\r\n // Normalize consecutive separators again\r\n .replace(new RegExp(`${escapedSeparator}+`, 'g'), separator)\r\n // Remove leading/trailing separators\r\n .replace(new RegExp(`^${escapedSeparator}|${escapedSeparator}$`, 'g'), '');\r\n}\r\n","/**\r\n * Capitalizes the first letter of a string.\r\n * Optionally capitalizes all words in the string.\r\n *\r\n * @param str - The string to capitalize\r\n * @param allWords - Whether to capitalize all words (default: false)\r\n * @returns Capitalized string\r\n *\r\n * @example\r\n * ```typescript\r\n * capitalize(\"hello world\"); // \"Hello world\"\r\n * capitalize(\"hello world\", true); // \"Hello World\"\r\n * capitalize(\"JOHN DOE\", true); // \"John Doe\"\r\n * ```\r\n */\r\nexport function capitalize(str: string, allWords: boolean = false): string {\r\n if (!str || typeof str !== 'string') {\r\n return '';\r\n }\r\n \r\n if (allWords) {\r\n // First convert separators to spaces, then split and capitalize\r\n const normalized = str.replace(/[_-]/g, ' ');\r\n const words = normalized.split(/(\\s+)/);\r\n return words\r\n .map((word, index) => {\r\n // If it's a space sequence, keep it as is\r\n if (/^\\s+$/.test(word)) {\r\n return word;\r\n }\r\n // If it's a word, capitalize it\r\n if (/^[a-zA-Z]/.test(word)) {\r\n return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();\r\n }\r\n // If it's not a word, keep it as is\r\n return word;\r\n })\r\n .join('');\r\n }\r\n \r\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\r\n}\r\n","/**\r\n * String case conversion utility functions.\r\n * Provides various ways to convert strings between different case formats.\r\n */\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n *\r\n * @param str - The string to convert\r\n * @returns camelCase string\r\n *\r\n * @example\r\n * ```typescript\r\n * camelCase(\"hello world\");