{"version":3,"file":"amount.cjs","sources":["../../../components/amount/amount.tsx"],"sourcesContent":["import { cx } from 'class-variance-authority';\nimport { type ComponentProps } from 'react';\nimport styles from './amount.module.css';\n\nexport interface AmountProps extends ComponentProps<'span'> {\n  /**\n   * The monetary value to display.\n   * For exact precision beyond 2^53, pass either:\n   *   - a `string` — supports decimals (e.g. \"1299\" or \"12.99\")\n   *   - a `bigint` — integer-only; treated as already in major units, so\n   *     `valueInMinorUnits` is ignored when value is a bigint\n   * @default 0\n   * @example\n   * valueInMinorUnits=true: 1299 => \"$12.99\"\n   * valueInMinorUnits=false: 12.99 => \"$12.99\"\n   * Large strings: \"999999999999999\" => \"$9,999,999,999,999.99\"\n   * BigInt: 1299n => \"$1,299.00\" (always major units)\n   */\n  value: number | string | bigint;\n\n  /**\n   * ISO 4217 currency code\n   * @default 'USD'\n   */\n  currency?: string;\n\n  /**\n   * Whether the value is in minor units (cents, paise, etc.)\n   * If true, the value will be converted based on the currency's decimal places\n   * If false, the value will be used as is\n   * @default true\n   * @example\n   * USD: 1299 => $12.99 (2 decimals)\n   * JPY: 1299 => ¥1,299 (0 decimals)\n   * BHD: 1299 => BHD 1.299 (3 decimals)\n   */\n  valueInMinorUnits?: boolean;\n\n  /**\n   * BCP 47 language tag\n   * @default 'en-US'\n   * @example 'en-US', 'de-DE', 'ja-JP'\n   */\n  locale?: string;\n\n  /**\n   * Truncates decimal places\n   * @default false\n   */\n  hideDecimals?: boolean;\n\n  /**\n   * Currency display format\n   * @default 'symbol'\n   * @example 'symbol' - $12.99, 'code' - USD 12.99, 'name' - 12.99 US Dollars\n   */\n  currencyDisplay?: 'symbol' | 'code' | 'name';\n\n  /**\n   * Number of minimum fraction digits\n   * @default undefined (uses currency's default)\n   */\n  minimumFractionDigits?: number;\n\n  /**\n   * Number of maximum fraction digits\n   * @default undefined (uses currency's default)\n   */\n  maximumFractionDigits?: number;\n\n  /**\n   * Group digits (e.g., thousand separators)\n   * @default true\n   */\n  groupDigits?: boolean;\n\n  /**\n   * Render the formatted number without a currency symbol, code, or name.\n   * Locale-driven separators, grouping, and fraction digits are preserved.\n   * When true, `currencyDisplay` is ignored.\n   * @default false\n   * @example\n   * <Amount value={1299} hideCurrency /> => \"12.99\"\n   */\n  hideCurrency?: boolean;\n}\n\n/**\n * Get the number of decimal places for a currency\n */\nfunction getCurrencyDecimals(currency: string): number {\n  try {\n    const formatter = new Intl.NumberFormat('en', {\n      style: 'currency',\n      currency: currency.toUpperCase()\n    });\n\n    // Format a number and count the decimal places\n    const formatted = formatter.format(1); // Get string representation of 1 unit with currency symbol\n    const match = formatted.match(/\\.([\\d]+)/); // Extract the decimal part\n    return match ? match[1].length : 0;\n  } catch {\n    // Default to 2 decimal places\n    return 2;\n  }\n}\n\n/**\n * Check if a currency is valid\n */\nfunction isValidCurrency(currency: string): boolean {\n  try {\n    new Intl.NumberFormat('en', {\n      style: 'currency',\n      currency: currency.toUpperCase()\n    });\n    return true;\n  } catch {\n    return false;\n  }\n}\n\n/**\n * Amount component for displaying monetary values.\n * Automatically formats currencies using Intl.NumberFormat.\n * Inherits styling from parent Text component.\n *\n * @example\n * ```tsx\n * // Basic usage\n * <Text>\n *   Total: <Amount value={1299} />  // Shows as \"$12.99\"\n * </Text>\n *\n * // With different currency and locale\n * <Text>\n *   Prix: <Amount value={1299} currency=\"EUR\" locale=\"fr-FR\" />  // Shows as \"12,99 €\"\n * </Text>\n *\n * // Without decimals\n * <Text>\n *   Price: <Amount value={1299} hideDecimals />  // Shows as \"$12\"\n * </Text>\n *\n * // With currency code\n * <Text>\n *   Amount: <Amount value={1299} currencyDisplay=\"code\" />  // Shows as \"USD 12.99\"\n * </Text>\n *\n * // With value in major units\n * <Text>\n *   Amount: <Amount value={12.99} valueInMinorUnits={false} />  // Shows as \"$12.99\"\n * </Text>\n *\n * // With groupDigits (default is true)\n * <Text>\n *   Amount: <Amount value={129999999} groupDigits />  // Shows as \"$129,999,999.99\"\n * </Text>\n * ```\n */\nexport const Amount = ({\n  value = 0,\n  currency = 'USD',\n  locale = 'en-US',\n  hideDecimals = false,\n  currencyDisplay = 'symbol',\n  minimumFractionDigits,\n  maximumFractionDigits,\n  groupDigits = true,\n  valueInMinorUnits = true,\n  hideCurrency = false,\n  className,\n  ...props\n}: AmountProps) => {\n  try {\n    if (\n      typeof value === 'number' &&\n      Math.abs(value) > Number.MAX_SAFE_INTEGER\n    ) {\n      console.warn(\n        `Warning: The number ${value} exceeds JavaScript's safe integer limit (${Number.MAX_SAFE_INTEGER}). ` +\n          'For large numbers, pass the value as a bigint or string to maintain precision.'\n      );\n    }\n\n    const validCurrency = isValidCurrency(currency) ? currency : 'USD';\n    if (validCurrency !== currency) {\n      console.warn(`Invalid currency code: ${currency}. Falling back to USD.`);\n    }\n\n    const decimals = getCurrencyDecimals(validCurrency);\n\n    /**\n     * Convert minor → major units.\n     * Three input shapes: bigint, string, number.\n     * BigInt is always treated as already in major units (it cannot represent fractions),\n     * so `valueInMinorUnits` is ignored for BigInt.\n     */\n    let baseValue: number | string | bigint;\n    if (typeof value === 'bigint') {\n      baseValue = value;\n    } else if (valueInMinorUnits && decimals > 0) {\n      if (typeof value === 'string') {\n        const isNegative = value.startsWith('-');\n        const unsigned = isNegative ? value.slice(1) : value;\n        const [intPart, fracPart = ''] = unsigned.split('.');\n        // Shift the existing decimal point left by `decimals` without\n        // round-tripping through Number — preserves precision for large strings\n        // and handles decimal strings like \"12.99\" (=> \"0.1299\" for USD).\n        const allDigits = intPart + fracPart;\n        const fracLen = fracPart.length + decimals;\n        const padded = allDigits.padStart(fracLen + 1, '0');\n        const major = padded.slice(0, -fracLen);\n        const minor = padded.slice(-fracLen);\n        baseValue = `${isNegative ? '-' : ''}${major}.${minor}`;\n      } else {\n        baseValue = value / Math.pow(10, decimals);\n      }\n    } else {\n      baseValue = value;\n    }\n\n    // Remove decimals when hideDecimals is true. BigInt has no decimals, so it's a no-op there.\n    const finalBaseValue: number | string | bigint = !hideDecimals\n      ? baseValue\n      : typeof baseValue === 'bigint'\n        ? baseValue\n        : typeof baseValue === 'string'\n          ? baseValue.split('.')[0]\n          : Math.trunc(baseValue);\n\n    /**\n     * Always format in currency mode — Intl's currency-style handles fraction digits per the currency,\n     * locale-correct grouping/separators,\n     * and auto-clamps when only one of min/max is user-provided.\n     * For hideCurrency, we then strip the currency token from the output via formatToParts(),\n     * which avoids the divergent defaults of style: 'decimal'.\n     */\n    const formatOptions: Intl.NumberFormatOptions = {\n      style: 'currency',\n      currency: validCurrency.toUpperCase(),\n      currencyDisplay,\n      minimumFractionDigits: hideDecimals ? 0 : minimumFractionDigits,\n      maximumFractionDigits: hideDecimals ? 0 : maximumFractionDigits,\n      useGrouping: groupDigits\n    };\n\n    const formatter = new Intl.NumberFormat(locale, formatOptions);\n\n    /**\n     * For hideCurrency, strip the `currency` parts and trim leading/trailing\n     * whitespace that locales like de-DE leave behind\n     * (e.g. \"1.234,56 €\" becomes \"1.234,56 \" before the trim).\n     * Otherwise format directly.\n     */\n    const formattedValue: string = hideCurrency\n      ? formatter\n          .formatToParts(\n            // @ts-expect-error TS lib types omit `string` from formatToParts() params, but Intl accepts numeric strings at runtime.\n            finalBaseValue\n          )\n          .filter(p => p.type !== 'currency')\n          .map(p => p.value)\n          .join('')\n          .trim()\n      : formatter.format(\n          // @ts-expect-error TS lib types omit `string` from format() params, but Intl.NumberFormat accepts numeric strings at runtime — needed for large values that would lose precision as `number`.\n          finalBaseValue\n        );\n\n    return (\n      <span\n        data-slot='amount'\n        {...props}\n        className={cx(styles.amount, className)}\n      >\n        {formattedValue}\n      </span>\n    );\n  } catch (error) {\n    console.error('Error formatting amount:', error);\n    return (\n      <span\n        data-slot='amount'\n        {...props}\n        className={cx(styles.amount, className)}\n      >\n        {String(value)}\n      </span>\n    );\n  }\n};\n\nAmount.displayName = 'Amount';\n"],"names":["_jsx","cx","styles"],"mappings":"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"}