{"version":3,"file":"index.cjs","names":[],"sources":["../src/join-paths.ts","../src/absolute-url.ts","../src/bytes.ts","../src/chunk.ts","../src/clsx.ts","../src/cn.ts","../src/compact.ts","../src/compact-object.ts","../src/count-by.ts","../src/difference.ts","../src/drop.ts","../src/drop-right.ts","../src/flatten.ts","../src/flatten-array.ts","../src/flatten-deep-array.ts","../src/format-time.ts","../src/get-initial-letter.ts","../src/get-os.ts","../src/get-token-exp-claim.ts","../src/group-by.ts","../src/group-consecutive.ts","../src/unique.ts","../src/intersection.ts","../src/is-array.ts","../src/is-boolean.ts","../src/is-dev.ts","../src/is-object.ts","../src/is-empty.ts","../src/is-function.ts","../src/is-navigator.ts","../src/is-number.ts","../src/is-string.ts","../src/is-symbol.ts","../src/is-token-expired.ts","../src/is-undef.ts","../src/is-url.ts","../src/is-valid-component-name.ts","../src/is-valid-json-string.ts","../src/is-valid-url.ts","../src/make-title.ts","../src/max-by.ts","../src/sum-by.ts","../src/mean-by.ts","../src/min-by.ts","../src/number.ts","../src/partition.ts","../src/pick.ts","../src/shuffle.ts","../src/sample.ts","../src/sort-by.ts","../src/symmetric-difference.ts","../src/take.ts","../src/take-right.ts","../src/to-case.ts","../src/to-iso.ts","../src/truncate-text.ts","../src/unique-by.ts","../src/v-card.ts","../src/zip.ts"],"sourcesContent":["/**\n * Joins multiple URL path segments together.\n *\n * @param segments - Array of path segments to join.\n * @returns The joined path string.\n *\n * @example\n * ```typescript\n * joinPaths([\"api\", \"users\", \"123\"]) // \"/api/users/123\"\n * joinPaths([\"\", \"api\", \"users\"])    // \"/api/users\"\n * ```\n */\nexport function joinPaths(segments: (string | null | undefined)[]): string {\n  const joined = segments\n    .filter((s): s is string => Boolean(s))\n    .map((s) => s.replace(/^\\/+|\\/+$/g, \"\"))\n    .filter(Boolean)\n    .join(\"/\")\n\n  return `/${joined}`\n}\n","import { joinPaths } from \"./join-paths\"\n\n/**\n * Creates an absolute URL by combining a base URL with a relative path.\n *\n * @param path - The relative path to append to the base URL. Can be null, undefined, or empty.\n * @param options - Optional configuration for URL generation.\n * @returns The absolute URL string.\n *\n * @example\n * ```typescript\n * absoluteUrl(\"/api/users\") // \"https://example.com/api/users\"\n * absoluteUrl(\"api/users\")  // \"https://example.com/api/users\"\n * absoluteUrl(\"\")           // \"https://example.com\"\n * absoluteUrl(null)         // \"https://example.com\"\n * absoluteUrl(\"/api/users\", { query: { id: \"123\" } }) // \"https://example.com/api/users?id=123\"\n * absoluteUrl(\"/api/users\", { fragment: \"section1\" }) // \"https://example.com/api/users#section1\"\n * ```\n */\nexport function absoluteUrl(\n  path?: string | null,\n  options?: {\n    query?: Record<string, string | number | boolean | null | undefined>\n    fragment?: string\n    baseUrl?: string\n  }\n): string {\n  const rawBase = options?.baseUrl ?? process.env.NEXT_PUBLIC_APP_URL ?? \"http://localhost:3000\"\n\n  let url: URL\n  try {\n    url = new URL(rawBase)\n  } catch {\n    throw new Error(`Invalid base URL: ${rawBase}`)\n  }\n\n  if (path?.trim()) {\n    url.pathname = joinPaths([url.pathname, path])\n  }\n\n  if (options?.query) {\n    for (const [key, value] of Object.entries(options.query)) {\n      if (value != null) {\n        url.searchParams.append(key, String(value))\n      }\n    }\n  }\n\n  if (options?.fragment) {\n    // Assigning to .hash handles encoding correctly; don't prepend '#'\n    url.hash = options.fragment\n  }\n\n  return url.toString()\n}\n","export type ByteUnit = \"b\" | \"kb\" | \"mb\" | \"gb\" | \"tb\" | \"pb\" | \"k\" | \"m\" | \"g\" | \"t\" | \"p\"\nexport type ByteInput = `${number}${ByteUnit}` | `${number}` | number\nexport type ByteBase = 1000 | 1024\n\nexport interface ByteConvertOptions {\n  /** Base for calculations: 1024 (binary) or 1000 (decimal). Default: 1024 */\n  base: ByteBase\n  /** Whether to round the result to the nearest integer. Default: true */\n  round: boolean\n}\n\nexport interface FormatBytesOptions {\n  base?: ByteBase\n  precision?: number\n  /** Use full unit names e.g. \"bytes\", not \"B\". Default: false */\n  verbose?: boolean\n}\n\nexport const BYTE_REGEX = /^([+-]?(?:[0-9]*\\.?[0-9]+(?:[eE][+-]?[0-9]+)?|Infinity))\\s*([a-zA-Z]*)$/i\n\ntype UnitMultiplierEntry = 1 | ((base: ByteBase) => number)\n\nconst UNIT_MULTIPLIERS: Record<string, UnitMultiplierEntry> = {\n  \"\": 1,\n  b: 1,\n  k: (base) => base,\n  kb: (base) => base,\n  m: (base) => base ** 2,\n  mb: (base) => base ** 2,\n  g: (base) => base ** 3,\n  gb: (base) => base ** 3,\n  t: (base) => base ** 4,\n  tb: (base) => base ** 4,\n  p: (base) => base ** 5,\n  pb: (base) => base ** 5,\n} as const\n\nconst SUPPORTED_UNITS = Object.keys(UNIT_MULTIPLIERS)\n  .filter((u) => u !== \"\")\n  .join(\", \")\n\n/**\n * Converts a byte string or number to raw bytes.\n *\n * @example\n * toBytes(\"1kb\")                    // 1024\n * toBytes(\"1mb\", { base: 1000 })   // 1000000\n * toBytes(\"2.5gb\")                  // 2684354560\n * toBytes(1024)                     // 1024\n */\nexport function toBytes(input: ByteInput, options: Partial<ByteConvertOptions> = {}): number {\n  const { base = 1024, round = true } = options\n\n  const normalizedInput = String(input).toLowerCase().trim()\n  const match = normalizedInput.match(BYTE_REGEX)\n\n  if (!match) {\n    throw new Error(`Invalid input: \"${input}\". Expected a number or formatted string like \"2.5kb\", \"33mb\"`)\n  }\n\n  const value = parseFloat(match[1])\n  const unit = match[2] as keyof typeof UNIT_MULTIPLIERS\n\n  if (!Number.isFinite(value)) {\n    throw new Error(`Non-finite values are not supported: \"${match[1]}\"`)\n  }\n\n  if (value < 0) {\n    throw new Error(`Negative values are not supported: \"${value}\"`)\n  }\n\n  const multiplierEntry = UNIT_MULTIPLIERS[unit]\n\n  if (multiplierEntry === undefined) {\n    throw new Error(`Unsupported unit: \"${unit}\". Supported units: ${SUPPORTED_UNITS}`)\n  }\n\n  const multiplier = typeof multiplierEntry === \"function\" ? multiplierEntry(base) : multiplierEntry\n  const result = value * multiplier\n\n  return round ? Math.round(result) : result\n}\n\nconst SHORT_UNITS = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"] as const\nconst LONG_UNITS = [\"bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"] as const\n\n/**\n * Formats a raw byte count into a human-readable string.\n *\n * @example\n * formatBytes(1536)                        // \"1.50 KB\"\n * formatBytes(1500, { base: 1000 })        // \"1.50 KB\"\n * formatBytes(1024, { verbose: true })     // \"1.00 KB\"\n * formatBytes(0)                           // \"0 B\"\n */\nexport function formatBytes(bytes: number, options: FormatBytesOptions = {}): string {\n  const { base = 1024, precision = 2, verbose = false } = options\n  const units = verbose ? LONG_UNITS : SHORT_UNITS\n\n  if (bytes < 0) throw new Error(`Negative values are not supported: \"${bytes}\"`)\n  if (bytes === 0) return `0 ${units[0]}`\n  if (bytes < 1) return `${bytes.toFixed(precision)} ${units[0]}`\n\n  const unitIndex = Math.min(Math.floor(Math.log(bytes) / Math.log(base)), units.length - 1)\n\n  const value = bytes / Math.pow(base, unitIndex)\n  return `${value.toFixed(precision)} ${units[unitIndex]}`\n}\n\n/** Creates a pre-configured `toBytes` converter with fixed defaults. */\nexport function createByteConverter(defaultOptions: Partial<ByteConvertOptions> = {}) {\n  return (input: ByteInput, overrides?: Partial<ByteConvertOptions>): number =>\n    toBytes(input, { ...defaultOptions, ...overrides })\n}\n","export const chunk = <T>(array: T[], size: number): T[][] => {\n  if (size <= 0) throw new Error(\"Chunk size must be greater than 0\")\n  if (array.length === 0) return []\n  return Array.from({ length: Math.ceil(array.length / size) }, (_, i) => {\n    const start = i * size\n    return array.slice(start, start + size)\n  })\n}\n","export type ClassValue = string | number | ClassRecord | ClassArray | undefined | null | boolean\n\nexport interface ClassRecord {\n  [key: string]: boolean | undefined | null\n}\n\nexport type ClassArray = Array<ClassValue>\n\nfunction resolveValue(value: ClassValue): string {\n  if (typeof value === \"string\") return value\n\n  if (typeof value === \"number\") return String(value) || \"\"\n\n  if (Array.isArray(value)) {\n    return value.map(resolveValue).filter(Boolean).join(\" \")\n  }\n\n  if (value !== null && typeof value === \"object\") {\n    return Object.entries(value)\n      .filter(([, v]) => Boolean(v))\n      .map(([k]) => k)\n      .join(\" \")\n  }\n\n  return \"\"\n}\n\n/**\n * Joins class names together.\n *\n * Accepts strings, numbers, arrays, or objects mapping keys to booleans.\n * Falsy values (false, null, undefined) are ignored.\n *\n * @example\n * clsx(\"foo\", \"bar\")                          // \"foo bar\"\n * clsx(\"foo\", { bar: true, baz: false })      // \"foo bar\"\n * clsx([\"foo\", null, \"bar\"])                  // \"foo bar\"\n * clsx(\"foo\", undefined, \"bar\")               // \"foo bar\"\n */\nexport function clsx(...args: ClassValue[]): string {\n  return args.map(resolveValue).filter(Boolean).join(\" \")\n}\n","import { twMerge } from \"tailwind-merge\"\nimport { clsx, type ClassValue } from \"./clsx\"\n\nexport const cn = (...inputs: ClassValue[]) => {\n  return twMerge(clsx(...inputs))\n}\n","export const compact = <T>(array: (T | null | undefined | false | 0 | \"\")[]): T[] => {\n  return array.filter(Boolean) as T[]\n}\n","type JSONPrimitive = string | number | boolean | null\ntype JSONValue = JSONPrimitive | JSONObject | JSONArray\ninterface JSONObject {\n  [key: string]: JSONValue\n}\ntype JSONArray = JSONValue[]\n\ninterface CompactOptions {\n  compactArrays?: boolean\n  removeEmptyArrays?: boolean\n  isEmpty?: (value: unknown) => boolean\n}\n\nconst defaultIsEmpty = (value: unknown): boolean => value === \"\" || value === null || value === undefined\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n  return Object.prototype.toString.call(value) === \"[object Object]\"\n}\n\nexport function compactObject<T extends Record<string, unknown>>(input: T, options: CompactOptions = {}): Partial<T> {\n  const { compactArrays = true, removeEmptyArrays = false, isEmpty = defaultIsEmpty } = options\n\n  const result: Record<string, unknown> = {}\n\n  for (const [key, value] of Object.entries(input)) {\n    if (isEmpty(value)) continue\n\n    // Array handling\n    if (Array.isArray(value)) {\n      if (!compactArrays) {\n        result[key] = value\n        continue\n      }\n\n      const next = value\n        .map((item) => {\n          if (isPlainObject(item)) {\n            const compacted = compactObject(item, options)\n            return Object.keys(compacted).length > 0 ? compacted : undefined\n          }\n\n          return isEmpty(item) ? undefined : item\n        })\n        .filter((v) => v !== undefined)\n\n      if (!removeEmptyArrays || next.length > 0) {\n        result[key] = next\n      }\n\n      continue\n    }\n\n    // Object handling\n    if (isPlainObject(value)) {\n      const compacted = compactObject(value, options)\n\n      if (Object.keys(compacted).length > 0) {\n        result[key] = compacted\n      }\n\n      continue\n    }\n\n    // Primitive\n    result[key] = value\n  }\n\n  return result as Partial<T>\n}\n","/**\n * Counts occurrences of each element in an array\n */\nexport const countBy = <T, K extends string | number | symbol>(\n  array: T[],\n  keyFn: (item: T) => K\n): Record<K, number> => {\n  return array.reduce(\n    (counts, item) => {\n      const key = keyFn(item)\n      counts[key] = (counts[key] || 0) + 1\n      return counts\n    },\n    {} as Record<K, number>\n  )\n}\n","export const difference = <T>(array1: T[], array2: T[]): T[] => {\n  const set2 = new Set(array2)\n  return array1.filter((item) => !set2.has(item))\n}\n","/**\n * Drops n elements from the beginning of an array\n */\nexport const drop = <T>(array: T[], n: number): T[] => {\n  return array.slice(Math.max(0, n))\n}\n","/**\n * Drops elements from the end of an array\n */\nexport const dropRight = <T>(array: T[], n: number): T[] => {\n  return n === 0 ? [...array] : array.slice(0, -n)\n}\n","/**\n * Flattens a nested object or array into a single-level object.\n * @param obj The object or array to flatten.\n * @param separator The string to use between nested keys.\n * @returns A flattened object.\n */\nexport const flatten = (obj: Record<string, unknown>, separator = \"-\"): Record<string, unknown> => {\n  const flattened: Record<string, unknown> = {}\n\n  // The recursive function now accepts `unknown` for type safety.\n  const recurse = (current: unknown, path: string) => {\n    // This type guard is crucial. We must check if `current` is a\n    // non-null object before trying to iterate over its entries.\n    if (typeof current !== \"object\" || current === null) {\n      return\n    }\n\n    // After the check, TypeScript knows `current` is an object (or array),\n    // so `Object.entries` can be used safely.\n    for (const [key, value] of Object.entries(current)) {\n      const newPath = path ? `${path}${separator}${key}` : key\n\n      // Recurse if the value is another non-null object.\n      if (typeof value === \"object\" && value !== null) {\n        recurse(value, newPath)\n      } else {\n        flattened[newPath] = value\n      }\n    }\n  }\n\n  recurse(obj, \"\")\n  return flattened\n}\n","export const flattenArray = <T>(array: (T | T[])[]): T[] => {\n  return array.reduce<T[]>((acc, val) => (Array.isArray(val) ? acc.concat(val) : acc.concat([val])), [])\n}\n","export const flattenDeepArray = <T>(array: (T | (T | T[])[])[]): T[] => {\n  return array.reduce<T[]>(\n    (acc, val) =>\n      Array.isArray(val) ? acc.concat(flattenDeepArray(val as (T | (T | T[])[])[])) : acc.concat(val as T),\n    []\n  )\n}\n","export interface FormatTimeOptions {\n  /**\n   * Format style for the time display\n   * - 'digital': \"1:05:30\" or \"5:30\"\n   * - 'long': \"1 hour 5 minutes 30 seconds\"\n   * - 'short': \"1h 5m 30s\"\n   * - 'compact': \"1:05:30\" (always shows hours)\n   * @default 'digital'\n   */\n  format?: \"digital\" | \"long\" | \"short\" | \"compact\"\n\n  /**\n   * Always show hours even if 0\n   * @default false\n   */\n  alwaysShowHours?: boolean\n\n  /**\n   * Round decimal seconds\n   * - 'floor': Round down (default)\n   * - 'ceil': Round up\n   * - 'round': Round to nearest\n   * @default 'floor'\n   */\n  roundingMode?: \"floor\" | \"ceil\" | \"round\"\n\n  /**\n   * Show leading zero for minutes when hours are present\n   * @default true\n   */\n  padMinutes?: boolean\n\n  /**\n   * Custom separator for digital format\n   * @default ':'\n   */\n  separator?: string\n}\n\n/**\n * Formats seconds into a human-readable time string\n *\n * @param seconds - The number of seconds to format (must be >= 0)\n * @param options - Formatting options\n * @returns Formatted time string\n *\n * @example\n * ```typescript\n * formatTime(65)                                    // \"1:05\"\n * formatTime(3665)                                  // \"1:01:05\"\n * formatTime(65, { format: 'short' })              // \"1m 5s\"\n * formatTime(65, { format: 'long' })               // \"1 minute 5 seconds\"\n * formatTime(5, { alwaysShowHours: true })         // \"0:00:05\"\n * formatTime(5.7, { roundingMode: 'ceil' })        // \"0:06\"\n * formatTime(65, { separator: '·' })               // \"1·05\"\n * ```\n */\nexport function formatTime(seconds: number, options: FormatTimeOptions = {}): string {\n  const {\n    format = \"digital\",\n    alwaysShowHours = false,\n    roundingMode = \"floor\",\n    padMinutes = true,\n    separator = \":\",\n  } = options\n\n  // Validate input\n  if (!Number.isFinite(seconds)) {\n    throw new Error(\"formatTime: seconds must be a finite number\")\n  }\n\n  if (seconds < 0) {\n    throw new Error(\"formatTime: seconds must be non-negative\")\n  }\n\n  // Round seconds based on mode\n  const roundedSeconds =\n    roundingMode === \"ceil\" ? Math.ceil(seconds) : roundingMode === \"round\" ? Math.round(seconds) : Math.floor(seconds)\n\n  // Calculate time components\n  const hours = Math.floor(roundedSeconds / 3600)\n  const minutes = Math.floor((roundedSeconds % 3600) / 60)\n  const secs = roundedSeconds % 60\n\n  const hasHours = hours > 0 || alwaysShowHours\n\n  // Format based on style\n  switch (format) {\n    case \"long\":\n      return formatLong(hours, minutes, secs, hasHours)\n\n    case \"short\":\n      return formatShort(hours, minutes, secs, hasHours)\n\n    case \"compact\":\n      return formatDigital(hours, minutes, secs, true, padMinutes, separator)\n\n    case \"digital\":\n    default:\n      return formatDigital(hours, minutes, secs, hasHours, padMinutes, separator)\n  }\n}\n\n/**\n * Helper: Format in digital style (1:05:30 or 5:30)\n */\nfunction formatDigital(\n  hours: number,\n  minutes: number,\n  seconds: number,\n  showHours: boolean,\n  padMinutes: boolean,\n  separator: string\n): string {\n  const parts: string[] = []\n\n  if (showHours) {\n    parts.push(hours.toString())\n    parts.push(minutes.toString().padStart(2, \"0\"))\n  } else {\n    parts.push(padMinutes ? minutes.toString().padStart(2, \"0\") : minutes.toString())\n  }\n\n  parts.push(seconds.toString().padStart(2, \"0\"))\n\n  return parts.join(separator)\n}\n\n/**\n * Helper: Format in long style (1 hour 5 minutes 30 seconds)\n */\nfunction formatLong(hours: number, minutes: number, seconds: number, showHours: boolean): string {\n  const parts: string[] = []\n\n  if (showHours && hours > 0) {\n    parts.push(`${hours} ${pluralize(\"hour\", hours)}`)\n  }\n\n  if (minutes > 0) {\n    parts.push(`${minutes} ${pluralize(\"minute\", minutes)}`)\n  }\n\n  if (seconds > 0 || parts.length === 0) {\n    parts.push(`${seconds} ${pluralize(\"second\", seconds)}`)\n  }\n\n  return parts.join(\" \")\n}\n\n/**\n * Helper: Format in short style (1h 5m 30s)\n */\nfunction formatShort(hours: number, minutes: number, seconds: number, showHours: boolean): string {\n  const parts: string[] = []\n\n  if (showHours && hours > 0) {\n    parts.push(`${hours}h`)\n  }\n\n  if (minutes > 0) {\n    parts.push(`${minutes}m`)\n  }\n\n  if (seconds > 0 || parts.length === 0) {\n    parts.push(`${seconds}s`)\n  }\n\n  return parts.join(\" \")\n}\n\n/**\n * Helper: Pluralize words\n */\nfunction pluralize(word: string, count: number): string {\n  return count === 1 ? word : `${word}s`\n}\n\n/**\n * Parses a formatted time string back to seconds\n *\n * @param timeString - Time string in format \"1:05:30\", \"1:05\", \"5:30\", etc.\n * @param separator - Separator used in the time string\n * @returns Number of seconds\n *\n * @example\n * ```typescript\n * parseTime(\"1:05\")      // 65\n * parseTime(\"1:01:05\")   // 3665\n * parseTime(\"5:30\")      // 330\n * ```\n */\nexport function parseTime(timeString: string, separator: string = \":\"): number {\n  if (!timeString || typeof timeString !== \"string\") {\n    throw new Error(\"parseTime: timeString must be a non-empty string\")\n  }\n\n  const parts = timeString.split(separator).map((part) => {\n    const num = parseInt(part, 10)\n    if (!Number.isFinite(num) || num < 0) {\n      throw new Error(`parseTime: invalid time component \"${part}\"`)\n    }\n    return num\n  })\n\n  if (parts.length === 0 || parts.length > 3) {\n    throw new Error(\"parseTime: timeString must have 1-3 components (SS, MM:SS, or HH:MM:SS)\")\n  }\n\n  // Handle different formats\n  if (parts.length === 1) {\n    // Just seconds\n    return parts[0]!\n  } else if (parts.length === 2) {\n    // MM:SS\n    return parts[0]! * 60 + parts[1]!\n  } else {\n    // HH:MM:SS\n    return parts[0]! * 3600 + parts[1]! * 60 + parts[2]!\n  }\n}\n","/**\n * Generates a one or two-letter initial string from a full name.\n * It takes the first letter of the first two name parts.\n * This function correctly handles diacritics, extra whitespace, and empty or invalid inputs.\n *\n * @example\n * getInitialLetter(\"John Doe\") // \"JD\"\n * getInitialLetter(\" Beyond  Knowles-Carter\") // \"BK\"\n * getInitialLetter(\"Cher\") // \"C\"\n * getInitialLetter(null) // \"?\"\n *\n * @param fullName The full name to process. Can be a string, null, or undefined.\n * @returns The uppercase initials (1 or 2 characters), or an empty string if the input is invalid.\n */\nexport function getInitialLetter(fullName?: string | null, fallback: string = \"?\"): string {\n  const cleanedName = fullName?.trim() ?? \"\"\n  if (!cleanedName) {\n    return fallback\n  }\n\n  return cleanedName\n    .split(/\\s+/)\n    .slice(0, 2)\n    .map(\n      (part) =>\n        part[0]\n          ?.normalize(\"NFD\")\n          .replace(/[\\u0300-\\u036f]/g, \"\")\n          .toUpperCase() ?? \"\"\n    )\n    .join(\"\")\n}\n","export type OS = \"windows\" | \"macos\" | \"linux\" | \"android\" | \"ios\" | \"unknown\"\n\nexport const osMap: Record<OS, { type: OS; label: string }> = {\n  windows: {\n    type: \"windows\",\n    label: \"Windows\",\n  },\n  macos: {\n    type: \"macos\",\n    label: \"macOS\",\n  },\n  linux: {\n    type: \"linux\",\n    label: \"Linux\",\n  },\n  android: {\n    type: \"android\",\n    label: \"Android\",\n  },\n  ios: {\n    type: \"ios\",\n    label: \"iOS\",\n  },\n  unknown: {\n    type: \"unknown\",\n    label: \"Unknown\",\n  },\n}\n\nexport function getOS(userAgent: string): { type: OS; label: string } {\n  const agent = userAgent.toLowerCase()\n\n  if (agent.includes(\"win\")) {\n    return osMap.windows\n  } else if (agent.includes(\"mac\")) {\n    return osMap.macos\n  } else if (agent.includes(\"linux\")) {\n    return osMap.linux\n  } else if (agent.includes(\"android\")) {\n    return osMap.android\n  } else if (agent.includes(\"ios\") || agent.includes(\"iphone\") || agent.includes(\"ipad\")) {\n    return osMap.ios\n  }\n\n  return osMap.unknown\n}\n","/**\n * Extract expiration claim from JWT token\n * @param token - JWT token\n * @returns expiration timestamp in seconds, or null if not found\n */\nexport function getTokenExpClaim(token: string): number | null {\n  const payload = decodeJWTPayload(token)\n  return payload && typeof payload.exp === \"number\" ? payload.exp : null\n}\n\n/**\n * Decode JWT payload without signature verification\n * @param token - JWT token\n * @returns decoded payload object\n */\nfunction decodeJWTPayload(token: string): Record<string, unknown> | null {\n  const parts = token.split(\".\")\n  if (parts.length !== 3) throw new Error(\"Invalid JWT format\")\n  const payload = parts[1] ?? \"\"\n  const json = base64UrlDecode(payload)\n  return JSON.parse(json)\n}\n\n/**\n * Decode base64url string to UTF-8 string\n * Works in both browser and Node.js environments\n * @param str - base64url encoded string\n * @returns decoded UTF-8 string\n */\nfunction base64UrlDecode(str: string): string {\n  // Convert base64url to standard base64\n  let base64Str = str.replace(/-/g, \"+\").replace(/_/g, \"/\")\n\n  // Add padding if needed\n  while (base64Str.length % 4) base64Str += \"=\"\n\n  if (\n    typeof globalThis !== \"undefined\" &&\n    typeof (globalThis as { atob?: (input: string) => string }).atob === \"function\"\n  ) {\n    // Browser or environments with atob\n    return decodeURIComponent(\n      Array.prototype.map\n        .call(\n          (globalThis as { atob: (input: string) => string }).atob(base64Str),\n          (c: string) => `%${(\"00\" + c.charCodeAt(0).toString(16)).slice(-2)}`\n        )\n        .join(\"\")\n    )\n  }\n  if (typeof Buffer !== \"undefined\") {\n    // Node.js environment\n    return Buffer.from(base64Str, \"base64\").toString(\"utf-8\")\n  }\n  throw new Error(\"No base64 decoder available\")\n}\n","export const groupBy = <T, K extends string | number | symbol>(array: T[], key: (item: T) => K): Record<K, T[]> => {\n  return array.reduce(\n    (groups, item) => {\n      const group = key(item)\n      groups[group] = groups[group] || []\n      groups[group].push(item)\n      return groups\n    },\n    {} as Record<K, T[]>\n  )\n}\n","/**\n * Creates an array of arrays, grouping consecutive elements by a key function\n */\nexport const groupConsecutive = <T, K>(array: T[], keyFn: (item: T) => K): T[][] => {\n  if (array.length === 0) return []\n\n  const result: T[][] = []\n  let currentGroup: T[] = [array[0] as T]\n  let currentKey = keyFn(array[0] as T)\n\n  for (let i = 1; i < array.length; i++) {\n    const key = keyFn(array[i] as T)\n    if (key === currentKey) {\n      currentGroup.push(array[i] as T)\n    } else {\n      result.push(currentGroup)\n      currentGroup = [array[i] as T]\n      currentKey = key\n    }\n  }\n\n  result.push(currentGroup)\n  return result\n}\n","export const unique = <T>(array: T[]): T[] => {\n  return [...new Set(array)]\n}\n","import { unique } from \"./unique\"\n\nexport const intersection = <T>(array1: T[], array2: T[]): T[] => {\n  const set2 = new Set(array2)\n  return unique(array1.filter((item) => set2.has(item)))\n}\n","/**\n * Checks if the given value is an array.\n */\nexport const isArray = (input: unknown) => Array.isArray(input)\n","/**\n * Checks if the given value is a boolean primitive.\n */\n\nexport const isBoolean = (value: unknown) => typeof value === \"boolean\"\n","/**\n * Checks if the current environment is a development environment.\n * Returns true if NODE_ENV is 'development' or 'test'.\n */\n\nexport const isDev = process.env.NODE_ENV === \"development\" || process.env.NODE_ENV === \"test\"\n","/**\n * Checks if the given value is an object.\n * Returns true if the value is not null and is of type 'object'.\n */\nexport const isObject = (value: unknown) => value !== null && typeof value === \"object\"\n","import { isArray } from \"./is-array\"\nimport { isObject } from \"./is-object\"\n\n/**\n * Checks if the given value is empty.\n */\n\nexport const isEmpty = (input: unknown) => {\n  return (\n    input === null ||\n    input === undefined ||\n    (isObject(input) && Object.keys(input).length === 0) ||\n    (isArray(input) && (input as unknown[]).length === 0) ||\n    (typeof input === \"string\" && input.trim().length === 0)\n  )\n}\n","/**\n * Checks if the given value is a function.\n */\nexport const isFunction = (value: unknown): value is (...args: unknown[]) => unknown => {\n  return typeof value === \"function\"\n}\n","/**\n * Checks if navigator is available.\n */\nexport const isNavigator = typeof navigator !== \"undefined\"\n","/**\n * Checks if the given value is a number.\n */\nexport const isNumber = (value: unknown) => typeof value === \"number\" && Number.isNaN(value) === false\n","/**\n * Checks if the given value is a string primitive.\n */\nexport const isString = (value: unknown) => typeof value === \"string\"\n","/**\n * Checks if the given value is a symbol.\n */\nexport function isSymbol(value: unknown) {\n  return (\n    typeof value === \"symbol\" ||\n    (value != null && typeof value === \"object\" && Object.prototype.toString.call(value) === \"[object Symbol]\")\n  )\n}\n","import { getTokenExpClaim } from \"./get-token-exp-claim\"\n\n/**\n * Is token expired?\n *\n * @param token - JWT token to check\n * @param offsetSeconds - Optional offset in seconds to consider token expired earlier\n * @returns true if token is expired or invalid, false if valid\n */\nexport function isTokenExpired(token: string, offsetSeconds = 0): boolean {\n  if (!token) return true\n\n  try {\n    const exp = getTokenExpClaim(token)\n    if (typeof exp !== \"number\") return true\n    return !(exp * 1000 > Date.now() + offsetSeconds * 1000)\n  } catch {\n    return true\n  }\n}\n","/**\n * Checks if the given value is undefined.\n *\n * @param value - The value to check.\n * @returns Whether the value is undefined.\n */\nexport const isUndef = (value: unknown) => typeof value === \"undefined\"\n","/**\n * Checks if the given url is valid\n * @param url - The url to check\n * @returns True if url is valid, false otherwise\n */\nexport function isUrl(url: string | URL): boolean {\n  try {\n    const parsedUrl = typeof url === \"string\" ? new URL(url) : url\n\n    // Additional check for valid protocols if the URL is a string\n    if (typeof url === \"string\" && ![\"http:\", \"https:\"].includes(parsedUrl.protocol)) {\n      return false\n    }\n\n    return true\n  } catch {\n    return false\n  }\n}\n","/**\n * Utility type for component validation results\n */\nexport type ComponentValidationResult = {\n  valid: boolean\n  errors: string[]\n}\n\n/**\n * Comprehensive validation for component names\n * @param name - The component name to validate\n * @param options - Validation options\n * @returns Validation result with detailed feedback\n * @example\n * isValidComponentName(\"my-component\") // { valid: true, errors: [] }\n * isValidComponentName(\"\") // { valid: false, errors: [\"Name cannot be empty\"] }\n * isValidComponentName(\"My-Component\") // { valid: false, errors: [\"Name must be lowercase\"] }\n */\nexport function isValidComponentName(\n  name: string,\n  options: {\n    allowEmpty?: boolean\n    minLength?: number\n    maxLength?: number\n  } = {}\n): ComponentValidationResult {\n  const { allowEmpty = false, minLength = 1, maxLength = 50 } = options\n\n  const errors: string[] = []\n\n  // Type check\n  if (typeof name !== \"string\") {\n    errors.push(\"Name must be a string\")\n    return { valid: false, errors }\n  }\n\n  // Empty check\n  if (!allowEmpty && (!name || name.trim().length === 0)) {\n    errors.push(\"Name cannot be empty\")\n    return { valid: false, errors }\n  }\n\n  // Length checks\n  if (name.length < minLength) {\n    errors.push(`Name must be at least ${minLength} characters long`)\n  }\n\n  if (name.length > maxLength) {\n    errors.push(`Name must be no more than ${maxLength} characters long`)\n  }\n\n  // Format validation for kebab-case\n  const kebabCaseRegex = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/\n  if (!kebabCaseRegex.test(name)) {\n    if (!/^[a-z]/.test(name)) {\n      errors.push(\"Name must start with a lowercase letter\")\n    }\n    if (/[A-Z]/.test(name)) {\n      errors.push(\"Name must be lowercase (use kebab-case)\")\n    }\n    if (/--/.test(name)) {\n      errors.push(\"Name cannot contain consecutive dashes\")\n    }\n    if (/[^a-z0-9-]/.test(name)) {\n      errors.push(\"Name can only contain lowercase letters, numbers, and dashes\")\n    }\n    if (/^-|-$/.test(name)) {\n      errors.push(\"Name cannot start or end with a dash\")\n    }\n  }\n\n  // Reserved name checks\n  const reservedNames = [\"component\", \"element\", \"node\", \"ref\", \"key\", \"props\"]\n  if (reservedNames.includes(name)) {\n    errors.push(`\"${name}\" is a reserved name`)\n  }\n\n  return {\n    valid: errors.length === 0,\n    errors,\n  }\n}\n","/**\n * Checks if the given string is valid JSON.\n *\n * @param str - The string to check.\n * @returns True if the string is valid JSON, false otherwise.\n */\n\nexport function isValidJsonString(str: string) {\n  try {\n    JSON.parse(str)\n  } catch {\n    return false\n  }\n  return true\n}\n","/**\n * Validates if a string is a valid URL.\n *\n * @param url - The URL string to validate.\n * @returns True if the URL is valid, false otherwise.\n *\n * @example\n * ```typescript\n * isValidUrl(\"https://example.com\") // true\n * isValidUrl(\"not-a-url\")           // false\n * ```\n */\nexport function isValidUrl(url: string): boolean {\n  try {\n    new URL(url)\n    return true\n  } catch {\n    return false\n  }\n}\n","// ============================================================================\n// TYPES\n// ============================================================================\nexport type TextTemplate = string | ((value: string, site: string) => string)\n\nexport interface TemplateParams {\n  disableSuffix?: boolean\n  template?: TextTemplate\n}\n\n// ============================================================================\n// HELPERS\n// ============================================================================\nfunction applyTemplate(value: string, site: string, template?: TextTemplate): string {\n  if (!template) {\n    // Default: append site name if not already present\n    return value.toLowerCase().includes(site.toLowerCase()) ? value : `${value} | ${site}`\n  }\n\n  if (typeof template === \"function\") {\n    return template(value, site)\n  }\n\n  if (template.includes(\"%s\")) {\n    return template.replace(\"%s\", value)\n  }\n\n  // fallback: append site if no placeholder\n  return value.toLowerCase().includes(site.toLowerCase()) ? value : `${value} | ${site}`\n}\n\n/**\n * Makes a SEO text based on a template\n * @param base - The base text to apply the template to\n * @param site - The site name to append to the base text\n * @param params - The parameters to apply the template to\n * @returns\n * @example\n * ```ts\n * const siteName = \"Linkiri\"\n *\n * // Title with a custom string template\n * const pageTitle = makeTitle(\"Jobs in Tech\", siteName, {\n *   template: \"%s - Powered by Linkiri\"\n * })\n * // -> \"Jobs in Tech - Powered by Linkiri\"\n *\n * // Title with a function template\n * const fancyTitle = makeTitle(\"Developers\", siteName, {\n *   template: (title, site) => `${title.toUpperCase()} 👨‍💻 | ${site}`\n * })\n * // -> \"DEVELOPERS 👨‍💻 | Linkiri\"\n *\n * // Title with no template (defaults to `base | site`)\n * const defaultTitle = makeTitle(\"Careers\", siteName, {})\n * // -> \"Careers | Linkiri\"\n *\n * // Description example (reuses the same engine)\n * const description = makeTitle(\"Find your dream job fast.\", siteName, {\n *   template: \"%s 🚀\"\n * })\n * // -> \"Find your dream job fast. 🚀\"\n *\n * // OG title example with suffix disabled\n * const ogTitle = makeTitle(\"Linkiri OG Preview\", siteName, {\n *   disableSuffix: true\n * })\n * // -> \"Linkiri OG Preview\"\n * ```\n */\nexport function makeTitle(base: string, site: string, params: TemplateParams): string {\n  if (params.disableSuffix) return base\n  return applyTemplate(base, site, params.template)\n}\n","/**\n * Finds the maximum element in an array based on a selector function\n */\nexport const maxBy = <T>(array: T[], selector: (item: T) => number): T | undefined => {\n  if (array.length === 0) return undefined\n\n  return array.reduce((max, current) => (selector(current) > selector(max) ? current : max))\n}\n","/**\n * Calculates the sum of array elements based on a selector function\n */\nexport const sumBy = <T>(array: T[], selector: (item: T) => number): number => {\n  return array.reduce((sum, item) => sum + selector(item), 0)\n}\n","import { sumBy } from \"./sum-by\"\n\n/**\n * Calculates the average of array elements based on a selector function\n */\nexport const meanBy = <T>(array: T[], selector: (item: T) => number): number => {\n  if (array.length === 0) return 0\n  return sumBy(array, selector) / array.length\n}\n","/**\n * Finds the minimum element in an array based on a selector function\n */\nexport const minBy = <T>(array: T[], selector: (item: T) => number): T | undefined => {\n  if (array.length === 0) return undefined\n\n  return array.reduce((min, current) => (selector(current) < selector(min) ? current : min))\n}\n","const f = (s: string, l: number, r: number, op: number): string => {\n  const result: string[] = []\n  const len = s.length\n  const opConst = op * 6064\n\n  for (let i = 0; i < len; i++) {\n    const charCode = s.charCodeAt(i)\n    const diff = charCode - l\n    const newCharCode = charCode - opConst * (diff * (charCode - r) < 1 ? 1 : 0)\n    result.push(String.fromCharCode(newCharCode))\n  }\n\n  return result.join(\"\")\n}\n\nexport const toASCII = (s: string): string => {\n  return f(s, 6112, 6121, 1)\n}\n\nexport const toKhmer = (s: string): string => {\n  return f(s, 40, 57, -1)\n}\n\nconst SINGLE_DIGITS: string[] = [\"Zero\", \"One\", \"Two\", \"Three\", \"Four\", \"Five\", \"Six\", \"Seven\", \"Eight\", \"Nine\"]\nconst TEENS: string[] = [\n  \"Ten\",\n  \"Eleven\",\n  \"Twelve\",\n  \"Thirteen\",\n  \"Fourteen\",\n  \"Fifteen\",\n  \"Sixteen\",\n  \"Seventeen\",\n  \"Eighteen\",\n  \"Nineteen\",\n]\nconst TENS: string[] = [\"\", \"\", \"Twenty\", \"Thirty\", \"Forty\", \"Fifty\", \"Sixty\", \"Seventy\", \"Eighty\", \"Ninety\"]\n\n/**\n * @description\n * Converts a number to its word representation in English.\n * @example\n  // Example usage:\n  const doubleNumber = 1234567.99\n  //result: One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven Point Eight Nine\n  const wordRepresentation = convertToWord(doubleNumber)\n  console.log(`${doubleNumber} in words: ${wordRepresentation}`)\n */\nexport function numberToWord(n: number): string {\n  const integerPart = n.toString().split(\".\")[0] ?? \"0\"\n  const fractionalPart = n.toString().split(\".\")[1] || \"0\"\n\n  const integerPartWords = convertIntegerToWord(Number(integerPart))\n  const fractionalPartWords = convertFractionalToWord(Number(fractionalPart))\n\n  let wordRepresentation = integerPartWords\n  if (fractionalPartWords !== \"\") {\n    wordRepresentation += ` Point ${fractionalPartWords}`\n  }\n\n  return wordRepresentation\n}\n\nfunction convertIntegerToWord(n: number): string {\n  if (n === 0) {\n    return SINGLE_DIGITS[0] ?? \"\"\n  }\n\n  let words = \"\"\n  let i = 0\n\n  while (n > 0) {\n    if (n % 1000 !== 0) {\n      words = `${helper(n % 1000) + (getSuffix(i) ?? \"\")} ${words}`\n    }\n    n = Math.floor(n / 1000)\n    i++\n  }\n\n  return words.trim()\n}\n\nfunction convertFractionalToWord(n: number): string {\n  if (Number.isNaN(n) || n <= 0) return \"\"\n  const fractionalDigits = n.toString()\n  let fractionalWords = \"\"\n  for (let i = 0; i < fractionalDigits.length; i++) {\n    const digitChar = fractionalDigits[i] ?? \"0\"\n    const digit = Number.parseInt(digitChar, 10)\n    fractionalWords += `${SINGLE_DIGITS[digit] ?? \"Zero\"} `\n  }\n\n  return fractionalWords.trim()\n}\n\nfunction helper(n: number): string {\n  let word = \"\"\n\n  if (n >= 100) {\n    word += `${SINGLE_DIGITS[Math.floor(n / 100)]} Hundred `\n    n %= 100\n  }\n\n  if (n >= 10 && n <= 19) {\n    word += `${TEENS[n - 10]} `\n  } else if (n >= 20) {\n    word += `${TENS[Math.floor(n / 10)]} `\n    n %= 10\n  }\n\n  if (n >= 1 && n <= 9) {\n    word += `${SINGLE_DIGITS[n]} `\n  }\n\n  return word\n}\n\nfunction getSuffix(i: number): string {\n  const SUFFIXES: string[] = [\"\", \"Thousand\", \"Million\", \"Billion\", \"Trillion\", \"Quadrillion\", \"Quintillion\"]\n  return SUFFIXES[i] ?? \"\"\n}\n\nconst SINGLE_DIGITS_KM: string[] = [\"សូន្យ\", \"មួយ\", \"ពីរ\", \"បី\", \"បួន\", \"ប្រាំ\", \"ប្រាំមួយ\", \"ប្រាំពីរ\", \"ប្រាំបី\", \"ប្រាំបួន\"]\nconst MULTIPLE_DIGITS_KM: string[] = [\"\", \"ដប់\", \"ម្ភៃ\", \"សាមសិប\", \"សែសិប\", \"ហាសិប\", \"ហុកសិប\", \"ចិតសិប\", \"ប៉ែតសិប\", \"កៅសិប\"]\nconst SUFFIX_MAP: Map<number, string> = new Map([\n  [2, \"រយ\"],\n  [3, \"ពាន់\"],\n  [4, \"ម៉ឺន\"],\n  [5, \"សែន\"],\n  [6, \"លាន\"],\n  [9, \"ប៊ីលាន\"],\n  [12, \"ទ្រីលាន\"],\n])\n\n/**\n * Converts a number to a string representation in Khmer words.\n *\n * @param value - The number to convert to words\n * @param sep - Separator between number groups, default ' '\n * @param del - Decimal point separator, default ' ក្បៀស '\n * @returns String representation of the number in Khmer words\n * @example\n  console.log(numberToWordKm(1234567.89))\n  // result: មួយលាន ពីរសែន បីម៉ឺន បួនពាន់ ប្រាំរយ ហុកសិបប្រាំពីរ ក្បៀស ប្រាំបី ប្រាំបួន\n */\nexport function numberToWordKm(value: number, sep = \" \", del = \" ក្បៀស \"): string {\n  if (Number.isNaN(value)) return \"\"\n  if (Number.isInteger(value)) return integer(value, sep)\n\n  const right = value.toString().split(\".\")[1] ?? \"\"\n  const word = right\n    .split(\"\")\n    .map((char) => integer(+char))\n    .join(sep)\n  return integer(Math.floor(value), sep) + del + word\n}\n\nconst cachedValues: Map<number, string> = new Map()\n\nfunction getCachedValue(key: number): string | undefined {\n  return cachedValues.get(key)\n}\n\nfunction setCachedValue(key: number, value: string): void {\n  cachedValues.set(key, value)\n}\n\nfunction integer(value: number, sep = \"\"): string {\n  if (Number.isNaN(value)) return \"\"\n  if (value < 0) return `*ដក*${integer(Math.abs(value), sep)}`\n  value = Math.floor(value)\n\n  const cached = getCachedValue(value)\n  if (cached) return cached\n\n  let result = \"\"\n  if (value < 10) {\n    result = SINGLE_DIGITS_KM[value] ?? \"\"\n  } else if (value < 100) {\n    const r = value % 10\n    if (r === 0) {\n      result = MULTIPLE_DIGITS_KM[Math.floor(value / 10)] ?? \"\"\n    } else {\n      result = (MULTIPLE_DIGITS_KM[Math.floor(value / 10)] ?? \"\") + integer(r, sep)\n    }\n  } else {\n    let i = Math.floor(Math.log10(value))\n    while (!SUFFIX_MAP.has(i) && i > 0) {\n      i--\n    }\n    const d = 10 ** i\n    const pre = integer(Math.floor(value / d), sep)\n    const suf = SUFFIX_MAP.get(i)\n    const r = value % d\n    if (r === 0) {\n      result = pre + (suf ? suf : \"\")\n    } else {\n      result = pre + (suf ? suf : \"\") + sep + integer(r, sep)\n    }\n  }\n\n  setCachedValue(value, result)\n  return result\n}\n\n/**\n * Formats a number with standard suffixes (K, M, B, T, etc.).\n *\n * @param value - The number to format. If null, undefined, or 0, returns \"0\"\n * @param decimalPlaces - Number of decimal places to include. Defaults to 1\n * @returns The formatted number string with appropriate suffix\n *\n * @example\n * formatNumber(1234) // \"1.2K\"\n * formatNumber(1234567, 2) // \"1.23M\"\n * formatNumber(0) // \"0\"\n * formatNumber(-1500) // \"-1.5K\"\n */\nexport function formatNumber(value?: number | null, decimalPlaces: number = 1): string {\n  // Handle edge cases\n  if (value === null || value === undefined || value === 0) {\n    return \"0\"\n  }\n\n  // Handle negative numbers\n  const isNegative = value < 0\n  const absoluteValue = Math.abs(value)\n\n  // Standard number suffixes\n  const suffixes = [\n    { value: 1e18, symbol: \"E\" }, // Quintillion\n    { value: 1e15, symbol: \"P\" }, // Quadrillion\n    { value: 1e12, symbol: \"T\" }, // Trillion\n    { value: 1e9, symbol: \"B\" }, // Billion\n    { value: 1e6, symbol: \"M\" }, // Million\n    { value: 1e3, symbol: \"K\" }, // Thousand\n    { value: 1, symbol: \"\" }, // Units\n  ]\n\n  // Find the appropriate suffix (iterate from largest to smallest)\n  const suffix = suffixes.find((item) => absoluteValue >= item.value)\n\n  if (!suffix) {\n    return \"0\"\n  }\n\n  // Calculate the scaled value\n  const scaledValue = absoluteValue / suffix.value\n\n  // Format with specified decimal places and remove trailing zeros\n  const formattedValue = scaledValue.toFixed(Math.max(0, decimalPlaces)).replace(/\\.?0+$/, \"\") // Remove trailing zeros and decimal point if not needed\n\n  // Add negative sign if needed\n  const sign = isNegative ? \"-\" : \"\"\n\n  return `${sign}${formattedValue}${suffix.symbol}`\n}\n\nexport const formatCurrency = ({\n  amount,\n  currencyCode,\n  minFractionDigits,\n  maxFractionDigits,\n  locale = \"en-US\",\n}: {\n  amount: number\n  currencyCode: string\n  minFractionDigits?: number\n  maxFractionDigits?: number\n  locale?: string\n}) =>\n  currencyCode\n    ? new Intl.NumberFormat(locale, {\n        style: \"currency\",\n        currency: currencyCode,\n        minimumFractionDigits: minFractionDigits,\n        maximumFractionDigits: maxFractionDigits,\n      }).format(amount)\n    : amount.toString()\n","export const partition = <T>(array: T[], predicate: (item: T, index: number) => boolean): [T[], T[]] => {\n  const truthy: T[] = []\n  const falsy: T[] = []\n\n  array.forEach((item, index) => {\n    if (predicate(item, index)) {\n      truthy.push(item)\n    } else {\n      falsy.push(item)\n    }\n  })\n\n  return [truthy, falsy]\n}\n","/**\n * Returns a partial copy of an object containing only the keys specified.\n * If the key does not exist, the property is ignored.\n */\nfunction pick<T extends object, K extends keyof T>(names: readonly K[], obj: T): Pick<T, K>\nfunction pick<T extends object>(names: readonly string[]): (obj: T) => Partial<T>\nfunction pick<T extends object, K extends keyof T>(\n  names: readonly K[] | readonly string[],\n  obj?: T\n): Pick<T, K> | Partial<T> | ((obj: T) => Partial<T>) {\n  // Curried version - return function if only one argument\n  if (arguments.length === 1) {\n    return (obj: T) => pick(names as unknown as readonly K[], obj) as Partial<T>\n  }\n\n  // Main implementation\n  const result: Partial<T> = {}\n  let idx = 0\n\n  while (idx < names.length) {\n    const key = names[idx] as keyof T\n    if (key in obj!) {\n      result[key] = obj![key]\n    }\n    idx += 1\n  }\n\n  return result\n}\n\nexport { pick }\n\n// Usage examples:\n// const obj = { a: 1, b: 2, c: 3, d: 4 };\n// pick(['a', 'c'], obj); // => { a: 1, c: 3 }\n//\n// const pickAC = pick(['a', 'c']);\n// pickAC(obj); // => { a: 1, c: 3 }\n","/**\n * Shuffles an array using Fisher-Yates algorithm\n */\nexport const shuffle = <T>(array: T[]): T[] => {\n  const result = [...array]\n  for (let i = result.length - 1; i > 0; i--) {\n    const j = Math.floor(Math.random() * (i + 1))\n    ;[result[i], result[j]] = [result[j] as T, result[i] as T]\n  }\n  return result\n}\n","import { shuffle } from \"./shuffle\"\n\n/**\n * Returns a random sample of n elements from an array\n */\nexport const sample = <T>(array: T[], n: number = 1): T[] => {\n  if (n >= array.length) return shuffle(array)\n\n  const shuffled = shuffle(array)\n  return shuffled.slice(0, n)\n}\n","/**\n * Sorts an array by multiple criteria\n */\nexport const sortBy = <T>(array: T[], ...selectors: ((item: T) => unknown)[]): T[] => {\n  return [...array].sort((a, b) => {\n    for (const selector of selectors) {\n      const aVal = selector(a) as number | string | boolean | undefined | null\n      const bVal = selector(b) as number | string | boolean | undefined | null\n      if (aVal! < bVal!) return -1\n      if (aVal! > bVal!) return 1\n    }\n    return 0\n  })\n}\n","import { difference } from \"./difference\"\n\nexport const symmetricDifference = <T>(array1: T[], array2: T[]): T[] => {\n  return [...difference(array1, array2), ...difference(array2, array1)]\n}\n","/**\n * Takes n elements from the beginning of an array\n */\nexport const take = <T>(array: T[], n: number): T[] => {\n  return array.slice(0, Math.max(0, n))\n}\n","/**\n * Takes elements from the end of an array\n */\nexport const takeRight = <T>(array: T[], n: number): T[] => {\n  return n === 0 ? [] : array.slice(-n)\n}\n","type TransformContext = {\n  input: string\n  words: string[]\n}\n\ntype TransformStep = (ctx: TransformContext) => TransformContext\ntype Formatter = (ctx: TransformContext) => string\n\nconst WORD_SPLIT_REGEX =\n  /[^a-zA-Z0-9]+|(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])|(?<=[a-zA-Z])(?=[0-9])|(?<=[0-9])(?=[a-zA-Z])/\n\nconst tokenize: TransformStep = (ctx) => ({\n  ...ctx,\n  words: ctx.input.split(WORD_SPLIT_REGEX).filter(Boolean),\n})\n\nconst normalizeLower: TransformStep = (ctx) => ({\n  ...ctx,\n  words: ctx.words.map((w) => w.toLowerCase()),\n})\n\nconst normalizeUpper: TransformStep = (ctx) => ({\n  ...ctx,\n  words: ctx.words.map((w) => w.toUpperCase()),\n})\n\nconst capitalizeWords: TransformStep = (ctx) => ({\n  ...ctx,\n  words: ctx.words.map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()),\n})\n\nconst join =\n  (separator: string): Formatter =>\n  (ctx) =>\n    ctx.words.join(separator)\n\nconst camelFormatter: Formatter = (ctx) =>\n  ctx.words.length === 0\n    ? \"\"\n    : ctx.words[0]!.toLowerCase() +\n      ctx.words\n        .slice(1)\n        .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())\n        .join(\"\")\n\nexport type CaseType =\n  | \"lowercase\"\n  | \"uppercase\"\n  | \"sentence\"\n  | \"title\"\n  | \"snake\"\n  | \"kebab\"\n  | \"camel\"\n  | \"pascal\"\n  | \"dot\"\n  | \"constant\"\n\ntype CaseDefinition = {\n  steps: TransformStep[]\n  format: Formatter\n}\n\nconst cases: Record<CaseType, CaseDefinition> = {\n  lowercase: {\n    steps: [tokenize, normalizeLower],\n    format: join(\" \"),\n  },\n\n  uppercase: {\n    steps: [tokenize, normalizeUpper],\n    format: join(\" \"),\n  },\n\n  sentence: {\n    steps: [tokenize, normalizeLower],\n    format: (ctx) => {\n      const s = ctx.words.join(\" \")\n      return s.charAt(0).toUpperCase() + s.slice(1)\n    },\n  },\n\n  title: {\n    steps: [tokenize, capitalizeWords],\n    format: join(\" \"),\n  },\n\n  snake: {\n    steps: [tokenize, normalizeLower],\n    format: join(\"_\"),\n  },\n\n  kebab: {\n    steps: [tokenize, normalizeLower],\n    format: join(\"-\"),\n  },\n\n  dot: {\n    steps: [tokenize, normalizeLower],\n    format: join(\".\"),\n  },\n\n  constant: {\n    steps: [tokenize, normalizeUpper],\n    format: join(\"_\"),\n  },\n\n  pascal: {\n    steps: [tokenize, capitalizeWords],\n    format: join(\"\"),\n  },\n\n  camel: {\n    steps: [tokenize],\n    format: camelFormatter,\n  },\n}\n\nexport function toCase(input: string, type: CaseType): string {\n  if (typeof input !== \"string\" || !input.trim()) {\n    return \"\"\n  }\n\n  const def = cases[type]\n\n  if (!def) {\n    throw new Error(`Unsupported case type: ${type}`)\n  }\n\n  let ctx: TransformContext = {\n    input,\n    words: [],\n  }\n\n  for (const step of def.steps) {\n    ctx = step(ctx)\n  }\n\n  return def.format(ctx)\n}\n\nexport function extendCases(custom: Record<string, CaseDefinition>) {\n  Object.assign(cases, custom)\n}\n","export function toIso(value?: Date | string): string | undefined {\n  if (!value) return undefined\n  const date = value instanceof Date ? value : new Date(value)\n  return !isNaN(date.valueOf()) ? date.toISOString() : undefined\n}\n","type TruncateTextOptions = {\n  maxLength?: number\n  ellipsis?: string\n  preserveWords?: boolean\n  returnUndefinedIfEmpty?: boolean\n}\n\nexport function truncateText(text?: string, options: TruncateTextOptions = {}): string | undefined {\n  const { maxLength, ellipsis = \"…\", preserveWords = false, returnUndefinedIfEmpty = true } = options\n\n  if (text == null) return undefined\n\n  const clean = text.replace(/\\s+/g, \" \").trim()\n\n  if (!clean) {\n    return returnUndefinedIfEmpty ? undefined : \"\"\n  }\n\n  if (!maxLength || maxLength <= 0 || clean.length <= maxLength) {\n    return clean\n  }\n\n  const safeMaxLength = Math.max(maxLength, ellipsis.length)\n\n  let truncated = clean.slice(0, safeMaxLength - ellipsis.length)\n\n  if (preserveWords) {\n    const lastSpace = truncated.lastIndexOf(\" \")\n    if (lastSpace > 0) {\n      truncated = truncated.slice(0, lastSpace)\n    }\n  }\n\n  return truncated.trimEnd() + ellipsis\n}\n","export const uniqueBy = <T, K>(array: T[], keyFn: (item: T) => K): T[] => {\n  const seen = new Set<K>()\n  return array.filter((item) => {\n    const key = keyFn(item)\n    if (seen.has(key)) return false\n    seen.add(key)\n    return true\n  })\n}\n","/**\n * VCard Generator - A utility for creating vCard 4.0 format contact cards\n * Supports social media, messaging platforms, and comprehensive contact information\n */\n\n// Types for social media and messaging platforms\ninterface ISocialMedia {\n  facebook?: string\n  twitter?: string\n  linkedin?: string\n  instagram?: string\n  youtube?: string\n  github?: string\n}\n\ninterface IMessagingPlatforms {\n  telegram?: string\n  whatsapp?: string\n  messenger?: string\n  skype?: string\n  discord?: string\n}\n\ninterface IAddress {\n  type?: \"home\" | \"work\" | \"other\"\n  street?: string\n  city?: string\n  state?: string\n  postalCode?: string\n  country?: string\n}\n\ninterface VCardContact {\n  firstName?: string\n  lastName?: string\n  nickname?: string\n  organization?: string\n  title?: string\n  department?: string\n  email?: string | string[]\n  phone?: string | string[]\n  mobile?: string | string[]\n  fax?: string | string[]\n  address?: IAddress[]\n  website?: string\n  birthday?: Date\n  photo?: string // URL or base64 encoded image\n  social?: ISocialMedia\n  messaging?: IMessagingPlatforms\n  categories?: string[]\n  note?: string\n}\n\n/**\n * Utility class for generating vCard 4.0 format contact cards\n */\nexport class VCardGenerator {\n  private static readonly VCARD_VERSION = \"4.0\"\n\n  // Social media platform mappings\n  private static readonly SOCIAL_PLATFORMS = {\n    facebook: \"FACEBOOK\",\n    twitter: \"TWITTER\",\n    linkedin: \"LINKEDIN\",\n    instagram: \"INSTAGRAM\",\n    youtube: \"YOUTUBE\",\n    github: \"GITHUB\",\n  } as const\n\n  // Messaging platform mappings\n  private static readonly MESSAGING_PLATFORMS = {\n    telegram: \"TELEGRAM\",\n    whatsapp: \"WHATSAPP\",\n    messenger: \"MESSENGER\",\n    skype: \"SKYPE\",\n    discord: \"DISCORD\",\n  } as const\n\n  /**\n   * Escapes special characters for vCard format\n   * @param value - String to escape\n   * @returns Escaped string safe for vCard format\n   */\n  private static escapeVCard(value: string): string {\n    if (!value) return \"\"\n\n    return value\n      .replace(/\\\\/g, \"\\\\\\\\\")\n      .replace(/\\n/g, \"\\\\n\")\n      .replace(/,/g, \"\\\\,\")\n      .replace(/;/g, \"\\\\;\")\n      .replace(/:/g, \"\\\\:\")\n  }\n\n  /**\n   * Formats a date to vCard BDAY format (YYYYMMDD)\n   * @param date - Date to format\n   * @returns Formatted date string\n   */\n  private static formatDate(date: Date): string {\n    if (!(date instanceof Date) || isNaN(date.getTime())) {\n      throw new Error(\"Invalid date provided\")\n    }\n    const [isoDate] = date.toISOString().split(\"T\")\n    if (!isoDate) throw new Error(\"Failed to extract date from ISO string\")\n    return isoDate.replace(/-/g, \"\")\n  }\n\n  /**\n   * Formats email addresses for vCard\n   * @param emails - Single email or array of emails\n   * @returns Array of formatted email lines\n   */\n  private static formatEmails(emails: string | string[]): string[] {\n    if (!emails) return []\n\n    const emailArray = Array.isArray(emails) ? emails : [emails]\n    return emailArray\n      .filter((email) => email && typeof email === \"string\" && email.trim().length > 0)\n      .map((email) => `EMAIL;TYPE=INTERNET:${this.escapeVCard(email.trim())}`)\n  }\n\n  /**\n   * Formats address information for vCard\n   * @param address - Address object\n   * @returns Formatted address line\n   */\n  private static formatAddress(address: IAddress): string {\n    if (!address) return \"\"\n\n    const type = (address.type || \"work\").toUpperCase()\n    const parts = [\n      \"\", // PO Box\n      \"\", // Extended Address\n      address.street || \"\",\n      address.city || \"\",\n      address.state || \"\",\n      address.postalCode || \"\",\n      address.country || \"\",\n    ]\n\n    return `ADR;TYPE=${type}:${parts.map((part) => this.escapeVCard(part)).join(\";\")}`\n  }\n\n  /**\n   * Formats social media profiles for vCard\n   * @param social - Social media object\n   * @returns Array of formatted social media lines\n   */\n  private static formatSocialMedia(social: ISocialMedia = {}): string[] {\n    return Object.entries(social)\n      .filter(([, url]) => url && typeof url === \"string\")\n      .map(([platform, url]) => {\n        const label = this.SOCIAL_PLATFORMS[platform as keyof typeof this.SOCIAL_PLATFORMS]\n        return label ? `X-SOCIALPROFILE;TYPE=${label}:${this.escapeVCard(url.trim())}` : null\n      })\n      .filter((line): line is string => line !== null)\n  }\n\n  /**\n   * Formats messaging platform information for vCard\n   * @param messaging - Messaging platforms object\n   * @returns Array of formatted messaging lines\n   */\n  private static formatMessaging(messaging: IMessagingPlatforms = {}): string[] {\n    return Object.entries(messaging)\n      .filter(([, id]) => id && typeof id === \"string\")\n      .map(([platform, id]) => {\n        const label = this.MESSAGING_PLATFORMS[platform as keyof typeof this.MESSAGING_PLATFORMS]\n        return label ? `X-${label};TYPE=USERNAME:${this.escapeVCard(id.trim())}` : null\n      })\n      .filter((line): line is string => line !== null)\n  }\n\n  /**\n   * Formats phone numbers for vCard\n   * @param values - Phone number(s)\n   * @param type - Phone type (WORK,VOICE | CELL,VOICE | FAX)\n   * @returns Array of formatted phone lines\n   */\n  private static formatPhones(values: string | string[] | undefined, type: string): string[] {\n    if (!values) return []\n\n    const numbers = Array.isArray(values) ? values : [values]\n    return numbers\n      .filter((number) => number && typeof number === \"string\" && number.trim().length > 0)\n      .map((number) => `TEL;TYPE=${type}:${this.escapeVCard(number.trim())}`)\n  }\n\n  /**\n   * Formats photo data for vCard\n   * @param photo - Photo URL or base64 data\n   * @returns Formatted photo line or null\n   */\n  private static formatPhoto(photo: string): string | null {\n    if (!photo || typeof photo !== \"string\") return null\n\n    const trimmedPhoto = photo.trim()\n\n    if (trimmedPhoto.startsWith(\"data:image\")) {\n      const base64Data = trimmedPhoto.split(\",\")[1]\n      if (!base64Data) {\n        console.warn(\"Invalid base64 image data provided\")\n        return null\n      }\n      return `PHOTO;ENCODING=b;TYPE=JPEG:${base64Data}`\n    } else {\n      return `PHOTO;VALUE=URI:${this.escapeVCard(trimmedPhoto)}`\n    }\n  }\n\n  /**\n   * Validates contact data before generating vCard\n   * @param contact - Contact object to validate\n   * @throws Error if contact data is invalid\n   */\n  private static validateContact(contact: VCardContact): void {\n    if (!contact || typeof contact !== \"object\") {\n      throw new Error(\"Contact data must be an object\")\n    }\n\n    // At least one of these should be present\n    const hasBasicInfo = contact.firstName || contact.lastName || contact.organization || contact.email\n    if (!hasBasicInfo) {\n      throw new Error(\"Contact must have at least a name, organization, or email\")\n    }\n  }\n\n  /**\n   * Generates a vCard 4.0 string from contact information\n   * @param contact - Contact information object\n   * @returns vCard formatted string\n   * @throws Error if contact data is invalid\n   */\n  public static generate(contact: VCardContact): string {\n    this.validateContact(contact)\n\n    const vcard: string[] = [\"BEGIN:VCARD\", `VERSION:${this.VCARD_VERSION}`]\n\n    // Name information\n    const firstName = contact.firstName?.trim() || \"\"\n    const lastName = contact.lastName?.trim() || \"\"\n    const fullName = [firstName, lastName].filter(Boolean).join(\" \")\n\n    if (fullName) {\n      vcard.push(`FN:${this.escapeVCard(fullName)}`)\n      vcard.push(`N:${this.escapeVCard(lastName)};${this.escapeVCard(firstName)};;;`)\n    }\n\n    // Optional fields\n    if (contact.nickname?.trim()) {\n      vcard.push(`NICKNAME:${this.escapeVCard(contact.nickname.trim())}`)\n    }\n\n    if (contact.organization?.trim()) {\n      const org = contact.organization.trim()\n      const orgLine = contact.department?.trim() ? `${org};${contact.department.trim()}` : org\n      vcard.push(`ORG:${this.escapeVCard(orgLine)}`)\n    }\n\n    if (contact.title?.trim()) {\n      vcard.push(`TITLE:${this.escapeVCard(contact.title.trim())}`)\n    }\n\n    // Contact information\n    if (contact.email) {\n      vcard.push(...this.formatEmails(contact.email))\n    }\n\n    vcard.push(...this.formatPhones(contact.phone, \"WORK,VOICE\"))\n    vcard.push(...this.formatPhones(contact.mobile, \"CELL,VOICE\"))\n    vcard.push(...this.formatPhones(contact.fax, \"FAX\"))\n\n    // Address information\n    if (contact.address?.length) {\n      contact.address.forEach((addr) => {\n        const formatted = this.formatAddress(addr)\n        if (formatted) vcard.push(formatted)\n      })\n    }\n\n    // Web presence\n    if (contact.website?.trim()) {\n      vcard.push(`URL:${this.escapeVCard(contact.website.trim())}`)\n    }\n\n    // Birthday\n    if (contact.birthday) {\n      try {\n        vcard.push(`BDAY:${this.formatDate(contact.birthday)}`)\n      } catch (error) {\n        console.warn(\"Invalid birthday date provided:\", error)\n      }\n    }\n\n    // Photo\n    if (contact.photo) {\n      const photoLine = this.formatPhoto(contact.photo)\n      if (photoLine) vcard.push(photoLine)\n    }\n\n    // Social media\n    if (contact.social) {\n      vcard.push(...this.formatSocialMedia(contact.social))\n    }\n\n    // Messaging platforms\n    if (contact.messaging) {\n      vcard.push(...this.formatMessaging(contact.messaging))\n    }\n\n    // Categories\n    if (contact.categories?.length) {\n      const validCategories = contact.categories\n        .filter((cat) => cat && typeof cat === \"string\")\n        .map((cat) => cat.trim())\n        .filter((cat) => cat.length > 0)\n\n      if (validCategories.length > 0) {\n        const cats = validCategories.map((cat) => this.escapeVCard(cat)).join(\",\")\n        vcard.push(`CATEGORIES:${cats}`)\n      }\n    }\n\n    // Note\n    if (contact.note?.trim()) {\n      vcard.push(`NOTE:${this.escapeVCard(contact.note.trim())}`)\n    }\n\n    vcard.push(\"END:VCARD\")\n\n    return vcard.join(\"\\r\\n\")\n  }\n\n  /**\n   * Creates a downloadable blob for the vCard\n   * @param contact - Contact information\n   * @returns Blob object for download\n   */\n  public static createDownloadBlob(contact: VCardContact): Blob {\n    const vcardContent = this.generate(contact)\n    return new Blob([vcardContent], {\n      type: \"text/vcard;charset=utf-8\",\n    })\n  }\n}\n\n// Export types for external use\nexport type { IAddress, IMessagingPlatforms, ISocialMedia, VCardContact }\n","/**\n * Zips multiple arrays together\n */\nexport const zip = <T extends readonly unknown[][]>(\n  ...arrays: T\n): Array<{ [K in keyof T]: T[K] extends readonly (infer U)[] ? U : never }> => {\n  if (arrays.length === 0) return []\n  const maxLength = Math.max(...arrays.map((arr) => arr.length))\n  const result: Array<{\n    [K in keyof T]: T[K] extends readonly (infer U)[] ? U : never\n  }> = []\n  for (let i = 0; i < maxLength; i++) {\n    result.push(\n      arrays.map((arr) => arr[i]) as {\n        [K in keyof T]: T[K] extends readonly (infer U)[] ? U : never\n      }\n    )\n  }\n  return result\n}\n"],"mappings":"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"}