{"version":3,"sources":["../../src/number.mts"],"sourcesContent":["import numberToWords from 'number-to-words';\n\n/**\n * Abbreviates large numbers with appropriate suffixes (K, M, B, T, etc.).\n *\n * Converts numbers to abbreviated format using standard suffixes:\n * - K for thousands (1,000+)\n * - M for millions (1,000,000+)\n * - B for billions (1,000,000,000+)\n * - T for trillions (1,000,000,000,000+)\n *\n * @param num - The number to abbreviate\n * @returns The abbreviated number string with appropriate suffix\n *\n * @example\n * ```typescript\n * abbreviate(1000) // \"1K\"\n * abbreviate(1500) // \"1.5K\"\n * abbreviate(1000000) // \"1M\"\n * abbreviate(2500000) // \"2.5M\"\n * abbreviate(999) // \"999\"\n * ```\n */\nexport function abbreviate(num: number): string {\n  if (Math.abs(num) < 1000) {\n    return num.toString();\n  }\n\n  const suffixes = ['', 'K', 'M', 'B', 'T', 'P', 'E'];\n  const tier = (Math.log10(Math.abs(num)) / 3) | 0;\n\n  if (tier === 0) return num.toString();\n\n  const suffix = suffixes[tier];\n  const scale = 10 ** (tier * 3);\n  const scaled = num / scale;\n\n  if (scaled % 1 === 0) {\n    return scaled.toString() + suffix;\n  } else {\n    const fixed = parseFloat(scaled.toFixed(1));\n    return (fixed % 1 === 0 ? fixed.toString() : fixed.toFixed(1)) + suffix;\n  }\n}\n\n/**\n * Clamps a number between minimum and maximum values.\n *\n * Ensures that the input number falls within the specified range.\n * If the number is below the minimum, returns the minimum.\n * If the number is above the maximum, returns the maximum.\n * Otherwise, returns the original number.\n *\n * @param num - The number to clamp\n * @param min - The minimum allowed value\n * @param max - The maximum allowed value\n * @returns The clamped number within the specified range\n *\n * @example\n * ```typescript\n * clamp(5, 1, 10) // 5\n * clamp(-5, 1, 10) // 1\n * clamp(15, 1, 10) // 10\n * clamp(7.5, 0, 5) // 5\n * ```\n */\nexport function clamp(num: number, min: number, max: number): number {\n  return Math.min(Math.max(num, min), max);\n}\n\n/**\n * Formats a number as currency with proper locale formatting.\n *\n * Converts a numeric value to a formatted currency string using\n * the browser's Intl.NumberFormat API. Supports different currencies\n * and uses appropriate locale-specific formatting.\n *\n * @param num - The number to format as currency\n * @param currency - The currency code (ISO 4217) to use for formatting\n * @returns The formatted currency string\n *\n * @example\n * ```typescript\n * currencyFormat(1234.56) // \"$1,234.56\" (in USD)\n * currencyFormat(1234.56, 'EUR') // \"€1,234.56\" (in EUR)\n * currencyFormat(1000, 'GBP') // \"£1,000.00\" (in GBP)\n * currencyFormat(0) // \"$0.00\"\n * ```\n */\nexport function currencyFormat(num: number, currency: string = 'USD'): string {\n  return new Intl.NumberFormat('en-US', {\n    style: 'currency',\n    currency: currency,\n  }).format(num);\n}\n\n/**\n * Formats a number of bytes into a human-readable file size string.\n *\n * Converts byte values to appropriate units (B, KB, MB, GB, TB, PB, EB, ZB, YB)\n * with proper decimal formatting. Uses binary (1024) units for conversion.\n *\n * @param num - The number of bytes to format\n * @returns The formatted file size string with appropriate unit\n *\n * @example\n * ```typescript\n * fileSize(1024) // \"1 KB\"\n * fileSize(1536) // \"1.5 KB\"\n * fileSize(1048576) // \"1 MB\"\n * fileSize(500) // \"500 B\"\n * fileSize(0) // \"0 B\"\n * ```\n */\nexport function fileSize(num: number): string {\n  if (num === 0) return '0 B';\n\n  const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];\n  const base = 1024;\n  const unitIndex = Math.floor(Math.log(Math.abs(num)) / Math.log(base));\n  const size = num / base ** unitIndex;\n\n  return `${size % 1 === 0 ? size : size.toFixed(1)} ${units[unitIndex]}`;\n}\n\n/**\n * Formats a number with specified decimal places and thousands separators.\n *\n * Converts a number to a string with the specified number of decimal places\n * and includes thousands separators for better readability.\n *\n * @param num - The number to format\n * @param decimalPlaces - The number of decimal places to show (default: 2)\n * @returns The formatted number string with separators\n *\n * @example\n * ```typescript\n * format(1234.5678) // \"1,234.57\"\n * format(1234.5678, 1) // \"1,234.6\"\n * format(1000000) // \"1,000,000.00\"\n * format(42, 0) // \"42\"\n * ```\n */\nexport function format(num: number, decimalPlaces: number = 2): string {\n  return new Intl.NumberFormat('en-US', {\n    minimumFractionDigits: decimalPlaces,\n    maximumFractionDigits: decimalPlaces,\n  }).format(num);\n}\n\n/**\n * Converts a number to its ordinal string representation.\n *\n * Adds the appropriate ordinal suffix (st, nd, rd, th) to a number\n * based on English ordinal number rules.\n *\n * @param num - The number to convert to ordinal form\n * @returns The ordinal string representation of the number\n *\n * @example\n * ```typescript\n * ordinal(1) // \"1st\"\n * ordinal(2) // \"2nd\"\n * ordinal(3) // \"3rd\"\n * ordinal(4) // \"4th\"\n * ordinal(21) // \"21st\"\n * ordinal(22) // \"22nd\"\n * ordinal(23) // \"23rd\"\n * ordinal(101) // \"101st\"\n * ```\n */\nexport function ordinal(num: number): string {\n  const absNum = Math.abs(num);\n  const lastTwoDigits = absNum % 100;\n  const lastDigit = absNum % 10;\n\n  // Special case for 11th, 12th, 13th\n  if (lastTwoDigits >= 11 && lastTwoDigits <= 13) {\n    return `${num}th`;\n  }\n\n  // Regular cases\n  switch (lastDigit) {\n    case 1:\n      return `${num}st`;\n    case 2:\n      return `${num}nd`;\n    case 3:\n      return `${num}rd`;\n    default:\n      return `${num}th`;\n  }\n}\n\n/**\n * Parses a string or number to extract a numeric value.\n *\n * Attempts to parse a string representation of a number or return\n * the numeric value if already a number. Returns undefined if the\n * input cannot be parsed to a valid number. Properly handles the\n * case where the input is 0.\n *\n * @param str - The string, number, or undefined to parse as a number\n * @returns The parsed number or undefined if parsing fails\n *\n * @example\n * ```typescript\n * parse(\"123\") // 123\n * parse(\"123.45\") // 123.45\n * parse(\"-42\") // -42\n * parse(\"1,234\") // 1234\n * parse(\"0\") // 0\n * parse(0) // 0\n * parse(42) // 42\n * parse(\"not a number\") // undefined\n * parse(\"\") // undefined\n * parse(undefined) // undefined\n * ```\n */\nexport function parse(str: string | number | undefined): number | undefined {\n  // Handle undefined/null cases\n  if (str === undefined || str === null) {\n    return undefined;\n  }\n\n  // If it's already a number, return it (including 0)\n  if (typeof str === 'number') {\n    return isNaN(str) ? undefined : str;\n  }\n\n  // Handle string cases\n  if (typeof str !== 'string') {\n    return undefined;\n  }\n\n  // Handle empty string\n  if (str.trim() === '') {\n    return undefined;\n  }\n\n  // Remove common thousands separators and whitespace\n  const cleaned = str.replace(/[,\\s]/g, '');\n\n  // Try to parse the cleaned string\n  const parsed = globalThis.Number(cleaned);\n\n  // Return undefined if parsing resulted in NaN, otherwise return the number (including 0)\n  return isNaN(parsed) ? undefined : parsed;\n}\n\n/**\n * Converts a number to its written English word representation.\n *\n * Transforms numeric values into their English word equivalents.\n * Supports integers and handles negative numbers appropriately.\n *\n * @param num - The number to convert to words\n * @returns The written English representation of the number\n *\n * @example\n * ```typescript\n * spell(42) // \"forty-two\"\n * spell(100) // \"one hundred\"\n * spell(1001) // \"one thousand one\"\n * spell(-5) // \"minus five\"\n * spell(0) // \"zero\"\n * ```\n */\nexport function spell(num: number): string {\n  return numberToWords.toWords(Math.floor(num));\n}\n\n/**\n * Converts a number to its written English ordinal word representation.\n *\n * Transforms numeric values into their English ordinal word equivalents\n * (first, second, third, etc.). Supports positive integers.\n *\n * @param num - The number to convert to ordinal words\n * @returns The written English ordinal representation of the number\n *\n * @example\n * ```typescript\n * spellOrdinal(1) // \"first\"\n * spellOrdinal(2) // \"second\"\n * spellOrdinal(3) // \"third\"\n * spellOrdinal(21) // \"twenty-first\"\n * spellOrdinal(100) // \"one hundredth\"\n * ```\n */\nexport function spellOrdinal(num: number): string {\n  return numberToWords.toWordsOrdinal(Math.floor(Math.abs(num)));\n}\n\n/**\n * Rounds a number or array of numbers to a specified precision.\n *\n * Provides flexible rounding capabilities with configurable precision and rounding method.\n * Supports single numbers or arrays of numbers, returning the same type as the input.\n * Handles NaN values gracefully by preserving them in the output.\n *\n * Precision can be positive (decimal places), zero (nearest integer), or negative\n * (rounding to tens, hundreds, etc.).\n *\n * @param number - The number or array of numbers to round\n * @param options - Configuration options for rounding behavior\n * @param options.precision - Number of decimal places to round to (default: 1)\n *   - Positive: round to decimal places (e.g., 2 = 0.01, 3 = 0.001)\n *   - Zero: round to nearest integer\n *   - Negative: round to tens, hundreds, etc. (e.g., -1 = 10, -2 = 100)\n * @param options.method - Rounding method to use: 'round' (default), 'ceil', or 'floor'\n * @returns The rounded number or array of numbers, matching the input type\n *\n * @example\n * ```typescript\n * // Basic rounding with default precision (1 decimal place)\n * round(3.14159) // 3.1\n * round(2.718) // 2.7\n *\n * // Custom precision\n * round(3.14159, {precision: 2}) // 3.14\n * round(3.14159, {precision: 0}) // 3\n * round(1.23456, {precision: 3}) // 1.235\n *\n * // Negative precision (round to tens, hundreds, etc.)\n * round(1234.5678, {precision: -1}) // 1230\n * round(1234.5678, {precision: -2}) // 1200\n * round(1234.5678, {precision: -3}) // 1000\n *\n * // Different rounding methods\n * round(3.14159, {precision: 2, method: 'round'}) // 3.14\n * round(3.14159, {precision: 2, method: 'ceil'}) // 3.15\n * round(3.14159, {precision: 2, method: 'floor'}) // 3.14\n * round(1234, {precision: -1, method: 'ceil'}) // 1240\n * round(1234, {precision: -1, method: 'floor'}) // 1230\n *\n * // Array of numbers\n * round([3.14159, 2.71828], {precision: 2}) // [3.14, 2.72]\n * round([1.1, 2.2, 3.3], {precision: 0}) // [1, 2, 3]\n * round([1234, 5678], {precision: -2}) // [1200, 5700]\n *\n * // Handles NaN\n * round(NaN) // NaN\n * round([1.5, NaN, 2.7], {precision: 0}) // [2, NaN, 3]\n * ```\n */\nexport function round(\n  number: number,\n  options?: { precision?: number; method?: 'round' | 'ceil' | 'floor' }\n): number;\nexport function round(\n  number: number[],\n  options?: { precision?: number; method?: 'round' | 'ceil' | 'floor' }\n): number[];\nexport function round(\n  number: number | number[],\n  {\n    precision = 1,\n    method = 'round',\n  }: { precision?: number; method?: 'round' | 'ceil' | 'floor' } = {}\n): number | number[] {\n  if (Array.isArray(number)) {\n    return number.map((n) => {\n      return round(n, { precision, method });\n    });\n  }\n\n  if (isNaN(number)) return NaN;\n\n  const factor = 10 ** precision;\n  switch (method) {\n    case 'ceil':\n      return Math.ceil(number * factor) / factor;\n    case 'floor':\n      return Math.floor(number * factor) / factor;\n    case 'round':\n    default:\n      return Math.round(number * factor) / factor;\n  }\n}\n"],"mappings":"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","names":[]}