{"version":3,"file":"format.cjs","names":[],"sources":["../src/format/number.ts","../src/format/percent.ts","../src/format/skip-spaces.ts","../src/format/_exports.ts"],"sourcesContent":["import { parser } from 'yummies/parser';\nimport { typeGuard } from 'yummies/type-guard';\nimport type { Maybe } from 'yummies/types';\nimport { NO_VALUE } from './constants.js';\n\nexport interface NumberFormatSettings {\n  delimiter?: string;\n  /**\n   * digitsOnlyForFloat - Show digits after decimal point only if they are not zeros after converting to number.\n   * Example: \"0.00\" -> \"0\", \"0.10\" -> \"0.1\", but \"0.003\" -> \"0.003\"\n   *\n   * @default true\n   */\n  digitsOnlyForFloat?: boolean;\n  /**\n   * Text which will be returned if the value is undefined, null, NaN, Infinity or empty string.\n   * Example: \"–\" will be returned if the value is undefined and emptyText is \"–\".\n   */\n  emptyText?: string;\n  /**\n   * Text to append to the end of the formatted number.\n   * Example: if value is 1000 and postfix is \"₽\", result will be \"1 000₽\".\n   */\n  postfix?: string;\n  /**\n   * Fixed number of digits after the decimal point (number.toFixed() method)\n   * If set to false, the truncation is ignored!\n   */\n  digits?: number | false;\n  /**\n   * Remove trailing zeros from the end of the number\n   * Example: 0.010000000000000000000000000000000000000000000 -> 0.01\n   */\n  cutZeros?: boolean;\n  cropDigitsOnly?: boolean;\n}\n\n/**\n * Formats a numeric value with thousands separators, fractional digit control\n * and optional postfix text.\n *\n * Invalid, empty or unsupported values fall back to `emptyText`.\n *\n * @param rawValue Number or numeric string to format.\n * @param userSettings Formatting overrides merged with `number.defaultSettings`.\n * @returns Formatted number string or fallback text.\n *\n * @example\n * ```ts\n * number(12000); // '12 000'\n * ```\n *\n * @example\n * ```ts\n * number(12.5, { digits: 1, postfix: '%' }); // '12.5%'\n * ```\n */\nexport const number = (\n  rawValue: Maybe<string | number>,\n  userSettings?: Maybe<NumberFormatSettings>,\n): string => {\n  const settings = {\n    ...number.defaultSettings,\n    ...userSettings,\n  };\n\n  const digits = settings.digits ?? 0;\n  const cutZeros = settings?.cutZeros ?? false;\n  const delimiter = settings.delimiter ?? ' ';\n  const postfix = settings.postfix ?? '';\n  const emptyText = settings.emptyText ?? NO_VALUE;\n  const digitsOnlyForFloat = settings.digitsOnlyForFloat ?? true;\n\n  let value: Maybe<number>;\n\n  if (typeGuard.isString(rawValue)) {\n    value = parser.number(value, { fallback: undefined });\n  } else {\n    value = rawValue;\n  }\n\n  if (typeGuard.isNumber(value)) {\n    let raw: string = `${value}`;\n\n    if (digits !== false) {\n      if (settings.cropDigitsOnly) {\n        const [integerPart, decimalPart] = `${raw}`.split('.');\n        const leftPart = integerPart;\n        const rightPart = (decimalPart || '')\n          .slice(0, digits)\n          .padEnd(digits, '0');\n\n        if (rightPart) {\n          raw = `${leftPart}.${rightPart}`;\n        } else {\n          raw = leftPart;\n        }\n      } else {\n        raw = value.toFixed(digits);\n      }\n    }\n\n    if (cutZeros) {\n      raw = `${+raw}`;\n    }\n\n    const [integerPart, decimalPart] = raw.split('.', 2);\n\n    let formattedIntegerPart = integerPart;\n    let formattedDecimalPart = '';\n\n    if (decimalPart && (!digitsOnlyForFloat || !/^0+$/.test(decimalPart))) {\n      formattedDecimalPart = `.${decimalPart}`;\n    }\n\n    const rgx = /(\\d+)(\\d{3})/;\n\n    while (rgx.test(formattedIntegerPart) && delimiter) {\n      formattedIntegerPart = formattedIntegerPart.replace(\n        rgx,\n        `$1${delimiter}$2`,\n      );\n    }\n\n    return formattedIntegerPart + formattedDecimalPart + postfix;\n  }\n\n  return emptyText;\n};\n\nnumber.defaultSettings = {} as NumberFormatSettings;\n","import { parser } from 'yummies/parser';\nimport { typeGuard } from 'yummies/type-guard';\nimport type { Maybe } from 'yummies/types';\n\nimport { NO_VALUE } from './constants.js';\n\nexport interface PercentFormatSettings\n  extends Omit<parser.NumberParserSettings, 'fallback'> {\n  divider?: string;\n  delimiter?: string;\n  symbol?: string;\n  emptyText?: string;\n}\n\n/**\n * Formats a value as a percent string with configurable decimal precision,\n * decimal divider and suffix symbol.\n *\n * @param value Number or numeric string to format.\n * @param settings Parser and formatting options.\n * @returns Formatted percent string or fallback text for invalid values.\n *\n * @example\n * ```ts\n * percent(12.345); // '12.35%'\n * ```\n *\n * @example\n * ```ts\n * percent(12.345, { divider: ',', symbol: ' pct' }); // '12,35 pct'\n * ```\n */\nexport const percent = (\n  value: Maybe<number | string>,\n  settings?: PercentFormatSettings,\n) => {\n  const numericValue = parser.number(value, {\n    ...settings,\n    digits: settings?.digits ?? 2,\n    fallback: Number.NaN,\n  });\n\n  if (typeGuard.isNumber(numericValue)) {\n    const divider = settings?.divider ?? '.';\n\n    const formattedPercent =\n      divider === '.' ? numericValue : `${numericValue}`.replace('.', divider);\n\n    return `${formattedPercent}${settings?.delimiter ?? ''}${settings?.symbol ?? '%'}`;\n  } else {\n    return settings?.emptyText ?? NO_VALUE;\n  }\n};\n","/**\n * Removes all whitespace characters from a string.\n *\n * @param value Source string.\n * @returns String without spaces, tabs and line breaks.\n *\n * @example\n * ```ts\n * skipSpaces('1 000 000'); // '1000000'\n * ```\n *\n * @example\n * ```ts\n * skipSpaces('a\\tb\\nc'); // 'abc'\n * ```\n */\nexport const skipSpaces = (value: string) => value.replaceAll(/\\s/g, '');\n","/**\n * ---header-docs-section---\n * # yummies/format\n *\n * ## Description\n *\n * Namespace-style **number, percent, and string** formatting for UI tables, inputs, and charts.\n * Submodules cover locale-aware numbers, percent parsing/formatting, trimming helpers, and shared\n * constants so presentation rules stay centralized and tree-shakable behind the package\n * aggregated **format** export from this entry point.\n *\n * ## Usage\n *\n * ```ts\n * import { format } from \"yummies/format\";\n * ```\n */\n\nexport * from './constants.js';\nexport * from './number.js';\nexport * from './percent.js';\nexport * from './skip-spaces.js';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAyDA,IAAa,UACX,UACA,iBACW;CACX,MAAM,WAAW;EACf,GAAG,OAAO;EACV,GAAG;CACL;CAEA,MAAM,SAAS,SAAS,UAAU;CAClC,MAAM,WAAW,UAAU,YAAY;CACvC,MAAM,YAAY,SAAS,aAAa;CACxC,MAAM,UAAU,SAAS,WAAW;CACpC,MAAM,YAAY,SAAS,aAAA;CAC3B,MAAM,qBAAqB,SAAS,sBAAsB;CAE1D,IAAI;CAEJ,IAAI,mBAAA,UAAU,SAAS,QAAQ,GAC7B,QAAQ,eAAA,OAAO,OAAO,OAAO,EAAE,UAAU,KAAA,EAAU,CAAC;MAEpD,QAAQ;CAGV,IAAI,mBAAA,UAAU,SAAS,KAAK,GAAG;EAC7B,IAAI,MAAc,GAAG;EAErB,IAAI,WAAW,OACb,IAAI,SAAS,gBAAgB;GAC3B,MAAM,CAAC,aAAa,eAAe,GAAG,MAAM,MAAM,GAAG;GACrD,MAAM,WAAW;GACjB,MAAM,aAAa,eAAe,IAC/B,MAAM,GAAG,MAAM,EACf,OAAO,QAAQ,GAAG;GAErB,IAAI,WACF,MAAM,GAAG,SAAS,GAAG;QAErB,MAAM;EAEV,OACE,MAAM,MAAM,QAAQ,MAAM;EAI9B,IAAI,UACF,MAAM,GAAG,CAAC;EAGZ,MAAM,CAAC,aAAa,eAAe,IAAI,MAAM,KAAK,CAAC;EAEnD,IAAI,uBAAuB;EAC3B,IAAI,uBAAuB;EAE3B,IAAI,gBAAgB,CAAC,sBAAsB,CAAC,OAAO,KAAK,WAAW,IACjE,uBAAuB,IAAI;EAG7B,MAAM,MAAM;EAEZ,OAAO,IAAI,KAAK,oBAAoB,KAAK,WACvC,uBAAuB,qBAAqB,QAC1C,KACA,KAAK,UAAU,GACjB;EAGF,OAAO,uBAAuB,uBAAuB;CACvD;CAEA,OAAO;AACT;AAEA,OAAO,kBAAkB,CAAC;;;;;;;;;;;;;;;;;;;;;AClG1B,IAAa,WACX,OACA,aACG;CACH,MAAM,eAAe,eAAA,OAAO,OAAO,OAAO;EACxC,GAAG;EACH,QAAQ,UAAU,UAAU;EAC5B,UAAU;CACZ,CAAC;CAED,IAAI,mBAAA,UAAU,SAAS,YAAY,GAAG;EACpC,MAAM,UAAU,UAAU,WAAW;EAKrC,OAAO,GAFL,YAAY,MAAM,eAAe,GAAG,eAAe,QAAQ,KAAK,OAAO,IAE5C,UAAU,aAAa,KAAK,UAAU,UAAU;CAC/E,OACE,OAAO,UAAU,aAAA;AAErB;;;;;;;;;;;;;;;;;;;ACpCA,IAAa,cAAc,UAAkB,MAAM,WAAW,OAAO,EAAE"}