{"version":3,"file":"formatters-CHQLHYgz.cjs","names":["isString","isFinite","errorMsg","getPreciseType","safeStableStringify","isPlainObject","isBoolean","isInteger","parseCurrencyString","isNaN","isUndefined","hasOwnProp","isFunction","createMessage","isString","isFinite","errorMsg","getPreciseType","createMessage","AsYouType","isNil","isString","isNumber","errorMsg","getPreciseType","isPlainObject","isBoolean","isUndefined","safeStableStringify","isNonEmptyString","createMessage","isUndefined","isNonEmptyString","isPlainObject","createMessage","getPreciseType","safeStableStringify","isNil","errorMsg","isInteger","getPreciseType","safeStableStringify","isPlainObject","normalizeSpaces","createMessage","isNonEmptyString","isPlainObject","isInteger","getPreciseType","safeStableStringify","isEmptyString","createMessage","isNil","isDate","isNonEmptyString","isPlainObject","id","enUS","isNaN","isNil","isDate","isNonEmptyString","isNaN","isPlainObject","isNil","isString","isDate","isNonEmptyString","isNaN","isNil","isString","isEmptyString","isDate","isNonEmptyString","isNaN"],"sources":["../src/formatters/currencies/formatCurrency.ts","../src/formatters/numbers/formatNumber.ts","../src/formatters/phones/_private/formatPhoneNumber.utils.ts","../src/formatters/phones/formatPhoneNumber.ts","../src/formatters/strings/_private/censorEmail.utils.ts","../src/formatters/strings/censorEmail.ts","../src/formatters/strings/chunkString.ts","../src/formatters/strings/truncateString.ts","../src/formatters/times/formatDateFns.ts","../src/formatters/times/formatDateIntl.ts","../src/formatters/times/formatDateTime.ts","../src/formatters/times/getGMTOffset.ts"],"sourcesContent":["import type { FormatCurrencyOptions } from \"@/formatters/currencies/formatCurrency.types\";\n\nimport { createMessage } from \"@/_private/logger\";\n\nimport { assertIsString } from \"@/assertions/strings/assertIsString\";\nimport { assertIsBoolean } from \"@/assertions/booleans/assertIsBoolean\";\n\nimport { parseCurrencyString } from \"@/conversions/currency/parsing\";\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\n\nimport { isNaN } from \"@/predicates/is/isNaN\";\nimport { isFinite } from \"@/predicates/is/isFinite\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isInteger } from \"@/predicates/is/isInteger\";\nimport { isBoolean } from \"@/predicates/is/isBoolean\";\nimport { isFunction } from \"@/predicates/is/isFunction\";\nimport { hasOwnProp } from \"@/predicates/has/hasOwnProp\";\nimport { isUndefined } from \"@/predicates/is/isUndefined\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\n\n/** ***Util helper for {@link formatCurrency}.***\n *\n * @internal\n */\nconst formatIndianNumber = ({\n  numStr,\n  separator\n}: {\n  numStr?: string;\n  separator: string;\n}) => {\n  const lastThree = numStr?.slice(-3);\n  const rest = numStr?.slice(0, -3);\n  if (!rest) return lastThree;\n  return (\n    rest.replace(/\\B(?=(\\d{2})+(?!\\d))/g, separator) + separator + lastThree\n  );\n};\n\n/** -------------------------------------------------------\n * * ***Utility: `formatCurrency`.***\n * --------------------------------------------------------\n * **Formats a number or messy currency string into a\n *   beautifully formatted currency string, with highly\n *   customizable separators, decimal control, rounding,\n *   currency symbols, and negative styling.**\n *\n * ---\n * - **Highlights:**\n *     - ***Accepts:***\n *          - Pure numbers: `15300.95`.\n *          - Messy currency strings from **any locale**:\n *            - `\"Rp 15.000,21\"` ***(Indonesian / Euro)***.\n *            - `\"$12,345.60\"` ***(US)***.\n *            - `\"CHF 12'345.60\"` ***(Swiss)***.\n *            - `\"1,23,456.78\"` ***(Indian)***.\n * - Auto extracts numeric value with smart multi-locale parsing\n *   via ***`parseCurrencyString` utility function***.\n * - Strong type checks & clear errors for misconfigured options.\n * - **Handles:**\n *     - Thousands separators: `.`, `,`, `'`, ` `.\n *     - Decimal separators: `,`, `.`.\n *     - Decimal suffix (eg. `\".-\"`, `\" USD\"`).\n *     - Currency prefix (eg. `\"Rp \"`, `\"$ \"`).\n *     - Rounding: `\"round\"`, `\"ceil\"`, `\"floor\"`, or truncate.\n *     - Negative styling: dash `-`, brackets `( )`, absolute, or custom.\n * - **How input is parsed:**\n *     - Removes all non-digit except `.`, `,`, `'` and spaces.\n *     - Detects bracket negatives: `\"(15.000,10)\"` ➔ `-15000.10`.\n *     - Uses last `,` or `.` as decimal separator (others are thousands).\n *     - Ignores currency symbols like `Rp`, `$` (must re-apply with `suffixCurrency`).\n * - **Note:**\n *     - Always re-apply symbols via `suffixCurrency`.\n *     - `parseCurrencyString` smartly detects last decimal,\n *       so `\"1.121.234,56\"` and `\"1,121,234.56\"` both parsed correctly.\n *\n * ---\n * @param {string|number} value\n *  ***The input value to format, examples:***\n *     - `\"Rp 15.000,21\"`.\n *     - `\"$12,345.60\"`.\n *     - `\"CHF 12'345.60\"`.\n *     - `15300.95`.\n * @param {FormatCurrencyOptions} [options] ***Optional configuration object.***\n * @param {FormatCurrencyOptions[\"separator\"]} [options.separator]\n *  ***Thousands separator:***\n *     - `{ separator: \".\" }` ➔ `1.000.000`.\n *     - *DefaultValue: `\".\"`.*\n * @param {FormatCurrencyOptions[\"separatorDecimals\"]} [options.separatorDecimals]\n *  ***Decimal separator:***\n *     - `{ separatorDecimals: \",\" }` ➔ `1.000,10`.\n *     - *DefaultValue: `\",\"`.*\n * @param {FormatCurrencyOptions[\"suffixCurrency\"]} [options.suffixCurrency]\n *  ***Prefix currency string:***\n *     - Does **not auto-keep input symbols**.\n *     - Must set manually e.g: `{ suffixCurrency: \"Rp \" }`.\n *         - `{ suffixCurrency: \"Rp \" }` ➔ `Rp 1.000`.\n *     - *DefaultValue: `\"\"`.*\n * @param {FormatCurrencyOptions[\"decimal\"]} [options.decimal]\n *  ***Whether to show decimals. If `false`, decimals are truncated:***\n *     - If `false`, cut the decimal.\n *     - *DefaultValue: `false`.*\n * @param {FormatCurrencyOptions[\"totalDecimal\"]} [options.totalDecimal]\n *  ***Total decimal digits:***\n *     - If `decimal: true` & `roundedDecimal: false`, simply cuts.\n *     - *DefaultValue: `2`.*\n * @param {FormatCurrencyOptions[\"separatorDecimals\"]} [options.suffixDecimal]\n *  ***Text appended after decimals:***\n *     - E.g: (`\".-\"`, `\" USD\"`).\n *     - Example 1: `\".-\"` ➔ `1.000,00.-`.\n *     - Example 2: `\" USD\"` ➔ `1.000,00 USD`.\n *     - *DefaultValue: `\"\"`.*\n * @param {FormatCurrencyOptions[\"endDecimal\"]} [options.endDecimal]\n *  ***Actually append `suffixDecimal`:***\n *     - *DefaultValue: `true`.*\n * @param {FormatCurrencyOptions[\"roundedDecimal\"]} [options.roundedDecimal]\n *  ***Rounding mode:***\n *     - `\"round\"` ➔ nearest.\n *     - `\"ceil\"` ➔ always up.\n *     - `\"floor\"` ➔ always down.\n *     - `false` ➔ truncate.\n *     - *DefaultValue: `\"round\"`.*\n * @param {FormatCurrencyOptions[\"negativeFormat\"]} [options.negativeFormat]\n *  ***How to format negatives:***\n *     - `\"dash\"` ➔ `-15.000`.\n *     - `\"brackets\"` ➔ `(15.000)`.\n *     - `\"abs\"` ➔ `15.000` (always positive).\n *     - Or object: `{ style: \"dash\" | \"brackets\" | \"abs\", space: true | false, custom: (formatted) => string }`.\n *     - *DefaultValue: `\"dash\"`.*\n * @param {FormatCurrencyOptions[\"indianFormat\"]} [options.indianFormat]\n *  ***Applies Indian Format:***\n *     - If `true`, formats as Indian: `12,34,567`.\n *     - Also forces `separator: \",\"`, `separatorDecimals: \".\"`.\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** ***If:***\n *     - The `value` is not string or number.\n *     - Cannot parse to valid number.\n *\n * ---\n * @returns {string}\n *  ***Nicely formatted currency string, examples:***\n *     - `\"15.000,10\"`.\n *     - `\"Rp 15.000,10.-\"`.\n *     - `\"15'000.10 USD\"`.\n *     - `\"12,34,567.89\"`.\n *\n * ---\n * @example\n *\n * 1. #### Number input (default, decimals off):\n *    ```ts\n *    formatCurrency(1234567.89);\n *    // ➔ \"1.234.567\"\n *    ```\n *    ---\n * 2. #### Decimals enabled:\n *    ```ts\n *    formatCurrency(1234567.89, { decimal: true });\n *    // ➔ \"1.234.567,89\"\n *    ```\n *    ---\n * 3. #### Indian format:\n *    ```ts\n *    formatCurrency(1234567.89, {\n *      decimal: true,\n *      indianFormat: true\n *    });\n *    // ➔ \"12,34,567.89\"\n *    ```\n *    ---\n * 4. #### String input (Indonesian style):\n *    ```ts\n *    formatCurrency(\"Rp 15.000,21\", {\n *      decimal: true\n *    });\n *    // ➔ \"15.000,21\"\n *    ```\n *    ---\n * 5. #### String input (US style):\n *    ```ts\n *    formatCurrency(\"$12,345.60\", {\n *      decimal: true\n *    });\n *    // ➔ \"12.345,60\"\n *    ```\n *    ---\n * 6. #### String input (Swiss style):\n *    ```ts\n *    formatCurrency(\"CHF 12'345.60\", {\n *      decimal: true\n *    });\n *    // ➔ \"12'345,60\"\n *    ```\n *    ---\n * 7. #### String input (Indian style):\n *    ```ts\n *    formatCurrency(\"1,23,456.78\", {\n *      decimal: true,\n *      indianFormat: true\n *    });\n *    // ➔ \"12,34,567.78\"\n *    ```\n *    ---\n * 8. #### Negative numbers (dash):\n *    ```ts\n *    formatCurrency(-1234.56, {\n *      decimal: true\n *    });\n *    // ➔ \"-1.234,56\"\n *    ```\n *    ---\n * 9. #### Negative numbers (brackets):\n *    ```ts\n *    formatCurrency(-1234.56, {\n *      decimal: true,\n *      negativeFormat: \"brackets\"\n *    });\n *    // ➔ \"(1.234,56)\"\n *    ```\n *    ---\n * 10. #### Negative numbers (custom object style):\n *     ```ts\n *     formatCurrency(-1234.56, {\n *       decimal: true,\n *       negativeFormat: {\n *         style: \"brackets\",\n *         space: true\n *       }\n *     });\n *     // ➔ \"( 1.234,56 )\"\n *     ```\n *     ---\n * 11. #### Negative numbers (custom function):\n *     ```ts\n *     formatCurrency(-1234.56, {\n *       decimal: true,\n *       negativeFormat: {\n *         custom: (val) => `NEGATIVE[${val}]`\n *       }\n *     });\n *     // ➔ \"NEGATIVE[1.234,56]\"\n *     ```\n *     ---\n * 12. #### With prefix currency:\n *     ```ts\n *     formatCurrency(1234.56, {\n *       decimal: true,\n *       suffixCurrency: \"Rp \"\n *     });\n *     // ➔ \"Rp 1.234,56\"\n *     ```\n *     ---\n * 13. #### With suffix decimal:\n *     ```ts\n *     formatCurrency(1234.56, {\n *       decimal: true,\n *       suffixDecimal: \".-\"\n *     });\n *     // ➔ \"1.234,56.-\"\n *     ```\n *     ---\n * 14. #### With suffix currency + suffix decimal:\n *     ```ts\n *     formatCurrency(1234.56, {\n *       decimal: true,\n *       suffixCurrency: \"Rp \",\n *       suffixDecimal: \".-\"\n *     });\n *     // ➔ \"Rp 1.234,56.-\"\n *     ```\n *     ---\n * 15. #### Custom separators:\n *     ```ts\n *     formatCurrency(1234567.89, {\n *       decimal: true,\n *       separator: \"'\",\n *       separatorDecimals: \".\"\n *     });\n *     // ➔ \"1'234'567.89\"\n *     ```\n *     ---\n * 16. #### Rounding: ceil:\n *     ```ts\n *     formatCurrency(1234.561, {\n *       decimal: true,\n *       roundedDecimal: \"ceil\"\n *     });\n *     // ➔ \"1.234,57\"\n *     ```\n *     ---\n * 17. #### Rounding: floor:\n *     ```ts\n *     formatCurrency(1234.569, {\n *       decimal: true,\n *       roundedDecimal: \"floor\"\n *     });\n *     // ➔ \"1.234,56\"\n *     ```\n *     ---\n * 18. #### Rounding: truncate:\n *     ```ts\n *     formatCurrency(1234.569, {\n *       decimal: true,\n *       roundedDecimal: false\n *     });\n *     // ➔ \"1.234,56\"\n *     ```\n *     ---\n * 19. #### Force no decimals:\n *     ```ts\n *     formatCurrency(1234.567, {\n *       decimal: false\n *     });\n *     // ➔ \"1.235\"\n *     ```\n *     ---\n * 20. #### Edge case: messy input with dots & commas:\n *     ```ts\n *     formatCurrency(\"1.121.234,561\", {\n *       decimal: true,\n *       totalDecimal: 2,\n *       roundedDecimal: \"ceil\",\n *       suffixCurrency: \"Rp \",\n *       negativeFormat: {\n *         style: \"brackets\"\n *       }\n *     });\n *     // ➔ \"(Rp 1.121.234,57)\"\n *     ```\n *     ---\n * 21. #### Edge case: integer string input:\n *     ```ts\n *     formatCurrency(\"1.121.234\", {\n *       decimal: true,\n *       suffixCurrency: \"Rp \",\n *       roundedDecimal: \"ceil\"\n *     });\n *     // ➔ \"Rp 1.121.234,00\"\n *     ```\n */\nexport const formatCurrency = (\n  value: string | number,\n  options?: FormatCurrencyOptions\n): string => {\n  if (!isString(value) && !isFinite(value)) {\n    throw new TypeError(\n      errorMsg(\n        `First parameter (\\`value\\`) must be of type \\`string\\` or \\`primitive-number\\`, but received: \\`${getPreciseType(\n          value\n        )}\\`, with value: \\`${safeStableStringify(value, {\n          keepUndefined: true\n        })}\\`.`\n      )\n    );\n  }\n\n  if (!isPlainObject(options)) options = {};\n\n  const decimal = options.decimal ?? false;\n  const totalDecimal = options.totalDecimal ?? 2;\n  const endDecimal = options.endDecimal ?? true;\n  const indianFormat = options.indianFormat ?? false;\n  const suffixCurrency = options.suffixCurrency ?? \"\";\n  const suffixDecimal = options.suffixDecimal ?? \"\";\n  const roundedDecimal = options.roundedDecimal ?? \"round\";\n  const negativeFormat = options.negativeFormat ?? \"dash\";\n  let separatorDecimals = options.separatorDecimals ?? \",\";\n  let separator = options.separator ?? \".\";\n\n  // validations\n  if (\n    !isString(separator) ||\n    !isString(separatorDecimals) ||\n    !isString(suffixCurrency) ||\n    !isString(suffixDecimal)\n  ) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`separator\\`, \\`separatorDecimals\\`, \\`suffixCurrency\\` and \\`suffixDecimal\\` property of the \\`options\\` (second parameter) must be of type \\`string\\`, but received: ['separator': \\`${getPreciseType(\n          separator\n        )}\\`, 'separatorDecimals': \\`${getPreciseType(\n          separatorDecimals\n        )}\\`, 'suffixCurrency': \\`${getPreciseType(\n          suffixCurrency\n        )}\\`, 'suffixDecimal': \\`${getPreciseType(suffixDecimal)}\\`].`\n      )\n    );\n  }\n\n  if (\n    !isBoolean(decimal) ||\n    !isBoolean(endDecimal) ||\n    !isBoolean(indianFormat)\n  ) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`decimal\\`, \\`endDecimal\\` and \\`indianFormat\\` property of the \\`options\\` (second parameter) must be of type \\`boolean\\`, but received: ['decimal': \\`${getPreciseType(\n          decimal\n        )}\\`, 'endDecimal': \\`${getPreciseType(\n          endDecimal\n        )}\\`, 'indianFormat': \\`${getPreciseType(indianFormat)}\\`].`\n      )\n    );\n  }\n\n  if (!isInteger(totalDecimal)) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`totalDecimal\\` property of the \\`options\\` (second parameter) must be of type \\`integer-number\\`, but received: \\`${getPreciseType(\n          totalDecimal\n        )}\\`, with value: \\`${safeStableStringify(length, {\n          keepUndefined: true\n        })}\\`.`\n      )\n    );\n  }\n\n  if (\n    !(\n      roundedDecimal === false ||\n      roundedDecimal === \"round\" ||\n      roundedDecimal === \"ceil\" ||\n      roundedDecimal === \"floor\"\n    )\n  ) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`roundedDecimal\\` property of the \\`options\\` (second parameter) must be of type \\`false\\` or \\`string\\` must be one of \"round\" | \"ceil\" | \"floor\", but received: \\`${getPreciseType(\n          roundedDecimal\n        )}\\`, with value: \\`${safeStableStringify(roundedDecimal, {\n          keepUndefined: true\n        })}\\`.`\n      )\n    );\n  }\n\n  if (\n    !(\n      negativeFormat === \"abs\" ||\n      negativeFormat === \"brackets\" ||\n      negativeFormat === \"dash\" ||\n      isPlainObject(negativeFormat)\n    )\n  ) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`negativeFormat\\` property of the \\`options\\` (second parameter) must be of type \\`string\\` must be one of \"abs\" | \"brackets\" | \"dash\" or \\`plain-object\\` type, but received: \\`${getPreciseType(\n          negativeFormat\n        )}\\`, with value: \\`${safeStableStringify(negativeFormat, {\n          keepUndefined: true\n        })}\\`.`\n      )\n    );\n  }\n\n  // parse number\n  const rawNum = isString(value) ? parseCurrencyString(value) : value;\n  if (isNaN(rawNum)) {\n    throw new TypeError(\n      \"First parameter (`value`) could not be parsed into a valid `number`.\"\n    );\n  }\n\n  let integerPart: string | undefined;\n  let decimalPartRaw: string | undefined;\n  let num = Math.abs(rawNum);\n  const factor = Math.pow(10, totalDecimal);\n\n  if (roundedDecimal) {\n    const scaled = num * factor;\n    switch (roundedDecimal) {\n      case \"round\":\n        num = Math.round(scaled) / factor;\n        break;\n      case \"ceil\":\n        num = Math.ceil(scaled) / factor;\n        break;\n      case \"floor\":\n        num = Math.floor(scaled) / factor;\n        break;\n    }\n  }\n\n  if (roundedDecimal) {\n    [integerPart, decimalPartRaw] = num.toFixed(totalDecimal).split(\".\");\n    decimalPartRaw = decimalPartRaw ?? \"\".padEnd(totalDecimal, \"0\");\n  } else {\n    // cut decimal manually\n    const split = String(num).split(\".\");\n    integerPart = split[0];\n    decimalPartRaw = (split[1] || \"\")\n      .slice(0, totalDecimal)\n      .padEnd(totalDecimal, \"0\");\n  }\n\n  let formattedInteger: string;\n\n  if (indianFormat) {\n    separator = \",\";\n    separatorDecimals = \".\";\n    formattedInteger =\n      (suffixCurrency.trim().length ? suffixCurrency : \"\") +\n      formatIndianNumber({ numStr: integerPart, separator });\n  } else {\n    formattedInteger =\n      (suffixCurrency.trim().length ? suffixCurrency : \"\") +\n      integerPart?.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator);\n  }\n\n  if (decimal && !isUndefined(decimalPartRaw) && totalDecimal > 0) {\n    let formattedDecimal = separatorDecimals + decimalPartRaw;\n    if (endDecimal) formattedDecimal += suffixDecimal;\n    formattedInteger += formattedDecimal;\n  }\n\n  // negative format\n  if (rawNum < 0) {\n    if (negativeFormat === \"dash\") {\n      formattedInteger = \"-\" + formattedInteger;\n    } else if (negativeFormat === \"brackets\") {\n      formattedInteger = \"(\" + formattedInteger + \")\";\n    } else if (negativeFormat === \"abs\") {\n      // no sign\n    } else if (isPlainObject(negativeFormat)) {\n      if (hasOwnProp(negativeFormat, \"custom\")) {\n        const formatCustomNegative = negativeFormat.custom;\n\n        if (!isFunction(formatCustomNegative)) {\n          throw new TypeError(\n            errorMsg(\n              `Parameter \\`negativeFormat.custom\\` property of the \\`options\\` (second parameter) must be of type function: \\`(formatted: string) => string\\`, but received: \\`${getPreciseType(\n                formatCustomNegative\n              )}\\`.`\n            )\n          );\n        }\n\n        const result = formatCustomNegative(formattedInteger);\n\n        assertIsString(result, {\n          message: ({ currentType, validType }) =>\n            errorMsg(\n              `Parameter \\`negativeFormat.custom\\` property of the \\`options\\` (second parameter) expected return a \\`${validType}\\` type value, but received: \\`${currentType}\\`.`\n            )\n        });\n\n        formattedInteger = result;\n      } else {\n        const formatStyleNegative = negativeFormat.style || \"dash\";\n        const formatSpaceNegative = !isUndefined(negativeFormat.space)\n          ? negativeFormat.space\n          : false;\n\n        assertIsBoolean(formatSpaceNegative, {\n          message: ({ currentType, validType }) =>\n            errorMsg(\n              `Parameter \\`negativeFormat.space\\` property of the \\`options\\` (second parameter) must be of type \\`${validType} or undefined\\`, but received: \\`${currentType}\\`.`\n            )\n        });\n\n        if (\n          !(\n            formatStyleNegative === \"abs\" ||\n            formatStyleNegative === \"brackets\" ||\n            formatStyleNegative === \"dash\"\n          )\n        ) {\n          throw new TypeError(\n            errorMsg(\n              `Parameter \\`negativeFormat.style\\` property of the \\`options\\` (second parameter) must be of type \\`string\\` must be of type \"abs\" | \"brackets\" | \"dash\", but received: \\`${getPreciseType(\n                formatStyleNegative\n              )}\\`, with value: \\`${safeStableStringify(formatStyleNegative, {\n                keepUndefined: true\n              })}\\`.`\n            )\n          );\n        }\n\n        switch (formatStyleNegative) {\n          case \"dash\":\n            formattedInteger =\n              \"-\" + (formatSpaceNegative ? \" \" : \"\") + formattedInteger;\n            break;\n          case \"brackets\":\n            formattedInteger = formatSpaceNegative\n              ? `( ${formattedInteger} )`\n              : `(${formattedInteger})`;\n            break;\n          case \"abs\":\n            // no sign\n            break;\n        }\n      }\n    }\n  }\n\n  return formattedInteger;\n};\n\n/**\n * @internal ***`Not part of the public API.`***\n */\nconst errorMsg = (msg: string) => createMessage(\"formatCurrency\", msg);\n","import { createMessage } from \"@/_private/logger\";\n\nimport { isFinite } from \"@/predicates/is/isFinite\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\n\n/** ----------------------------------------------------------\n * * ***Utility: `formatNumber`.***\n * -----------------------------------------------------------\n * **Formats a number or numeric string by adding a custom separator\n * every three digits (thousands separator), and intelligently flips\n * the decimal separator according to the chosen separator.**\n *\n * ---\n * - **Features:**\n *     - Converts a number to string before formatting.\n *     - Defaults to using `,` as the thousands separator.\n *     - If `.` is used as the separator, the decimal will automatically\n *       become `,`, and vice versa.\n *     - Handles input with existing formatting (e.g. \"1,234,567.89\") and normalizes it.\n *     - Supports custom separators, including spaces.\n *     - Preserves decimals even if more than 2 digits.\n *\n * ---\n * @param {string | number} value - The numeric value or string to format, can be plain numbers, or already formatted strings like `\"1,234,567.89\"`.\n * @param {string} [separator=\",\"] - The thousands separator to use, examples: `\",\"` ***(default)***, `\".\"`, `\" \"`, etc.\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `value` is not a string or number, or `separator` is not a string.\n *\n * ---\n * @returns {string} The formatted string with thousands separators and\n *   appropriate decimal separator.\n *\n * ---\n * @example\n * formatNumber(1000000);\n * // ➔ \"1,000,000\"\n * formatNumber(\"987654321\");\n * // ➔ \"987,654,321\"\n * formatNumber(1234567.89);\n * // ➔ \"1,234,567.89\"\n * formatNumber(\"1234567,89\");\n * // ➔ \"1,234,567.89\"\n * formatNumber(\"1234567.892\");\n * // ➔ \"1,234,567.892\"\n * formatNumber(\"1234567.89\", \".\");\n * // ➔ \"1.234.567,89\"\n * formatNumber(\"1234567,89\", \",\");\n * // ➔ \"1,234,567.89\"\n * formatNumber(\"987654321\", \" \");\n * // ➔ \"987 654 321\"\n * formatNumber(\"1,234,567.89\");\n * // ➔ \"1,234,567.89\"\n * formatNumber(\"1.234.567,89\", \",\");\n * // ➔ \"1,234,567.89\"\n * formatNumber(\"1.234.567,893\", \".\");\n * // ➔ \"1.234.567,893\"\n * formatNumber(\"1234.56\", \".\");\n * // ➔ \"1.234,56\"\n * formatNumber(\"1234,56\", \",\");\n * // ➔ \"1,234.56\"\n */\nexport const formatNumber = (\n  value: string | number,\n  separator: string = \",\"\n): string => {\n  if (!isString(value) && !isFinite(value)) {\n    throw new TypeError(\n      errorMsg(\n        `First parameter (\\`value\\`) must be of type \\`string\\` or \\`primitive number\\`, but received: \\`${getPreciseType(\n          value\n        )}\\`.`\n      )\n    );\n  }\n\n  if (!isString(separator)) {\n    throw new TypeError(\n      errorMsg(\n        `Second parameter (\\`separator\\`) must be of type \\`string\\` or empty as \\`undefined\\`, but received: \\`${getPreciseType(\n          separator\n        )}\\`.`\n      )\n    );\n  }\n\n  separator = isString(separator) ? separator : \",\";\n  const decimalSeparator =\n    separator === \".\" ? \",\" : separator === \",\" ? \".\" : \".\";\n\n  // Convert value to string\n  const stringValue = value.toString().trim();\n\n  // --- Normalize input ---\n  // Find the last decimal separator from the end\n  const lastDot = stringValue.lastIndexOf(\".\");\n  const lastComma = stringValue.lastIndexOf(\",\");\n\n  let actualDecimal = \"\";\n  if (lastDot > lastComma) {\n    actualDecimal = \".\";\n  } else if (lastComma > lastDot) {\n    actualDecimal = \",\";\n  }\n\n  // Split into integer and decimal parts\n  let integerPart = stringValue;\n  let decimalPart: string | undefined;\n\n  if (actualDecimal) {\n    const parts = stringValue.split(actualDecimal);\n    integerPart = parts.slice(0, -1).join(actualDecimal); // merge if more than one\n    decimalPart = parts.slice(-1)[0];\n  }\n\n  // Remove all non-digit characters from the integer part\n  integerPart = integerPart.replace(/[^\\d]/g, \"\");\n\n  // Format integer part with thousands separator\n  const formattedInteger = integerPart.replace(\n    /\\B(?=(\\d{3})+(?!\\d))/g,\n    separator\n  );\n\n  // Combine with decimal part if exists\n  return decimalPart\n    ? `${formattedInteger}${decimalSeparator}${decimalPart}`\n    : formattedInteger;\n};\n\n/**\n * @internal ***`Not part of the public API.`***\n */\nconst errorMsg = (msg: string) => createMessage(\"formatNumber\", msg);\n","import type { OmitStrict, Prettify } from \"@rzl-zone/ts-types-plus\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\n/* eslint-disable @typescript-eslint/no-unused-vars */\nimport type { formatPhoneNumber } from \"../formatPhoneNumber\";\nimport {\n  AsYouType,\n  type PhoneNumber,\n  type CountryCode\n} from \"libphonenumber-js/max\";\n\n/** ***Util constants `country code for special leading zero rule` for {@link formatPhoneNumber}.***\n *\n * @internal\n */\nexport const trunkZeroCountries: Record<string, string> = {\n  \"7\": \"Russia, Kazakhstan\",\n  \"20\": \"Egypt\",\n  \"27\": \"South Africa\",\n  \"30\": \"Greece\",\n  \"31\": \"Netherlands\",\n  \"32\": \"Belgium\",\n  \"33\": \"France\",\n  \"34\": \"Spain\",\n  \"36\": \"Hungary\",\n  \"39\": \"Italy, San Marino, Vatican\",\n  \"41\": \"Switzerland\",\n  \"43\": \"Austria\",\n  \"44\": \"United Kingdom\",\n  \"45\": \"Denmark\",\n  \"46\": \"Sweden\",\n  \"47\": \"Norway\",\n  \"48\": \"Poland\",\n  \"49\": \"Germany\",\n  \"51\": \"Peru\",\n  \"52\": \"Mexico\",\n  \"53\": \"Cuba\",\n  \"54\": \"Argentina\",\n  \"55\": \"Brazil\",\n  \"56\": \"Chile\",\n  \"57\": \"Colombia\",\n  \"58\": \"Venezuela\",\n  \"60\": \"Malaysia\",\n  \"61\": \"Australia\",\n  \"62\": \"Indonesia\",\n  \"63\": \"Philippines\",\n  \"64\": \"New Zealand\",\n  \"65\": \"Singapore\",\n  \"66\": \"Thailand\",\n  \"81\": \"Japan\",\n  \"82\": \"South Korea\",\n  \"84\": \"Vietnam\",\n  \"86\": \"China\",\n  \"90\": \"Turkey\",\n  \"91\": \"India\",\n  \"92\": \"Pakistan\",\n  \"351\": \"Portugal\",\n  \"352\": \"Luxembourg\",\n  \"355\": \"Albania\",\n  \"356\": \"Malta\",\n  \"358\": \"Finland\",\n  \"359\": \"Bulgaria\",\n  \"370\": \"Lithuania\",\n  \"371\": \"Latvia\",\n  \"372\": \"Estonia\",\n  \"373\": \"Moldova\",\n  \"374\": \"Armenia\",\n  \"375\": \"Belarus\",\n  \"376\": \"Andorra\",\n  \"377\": \"Monaco\",\n  \"378\": \"San Marino\",\n  \"379\": \"Vatican\",\n  \"971\": \"UAE\"\n};\n/** ***Util helper for {@link formatPhoneNumber}.***\n *\n * @internal\n */\nexport const isValidPhoneE164 = (value: unknown) => {\n  if (!isNonEmptyString(value)) return false;\n  return (\n    /^(\\+)?[0-9\\s().-]+$/.test(value) && value.replace(/\\D/g, \"\").length <= 15\n  );\n};\n\n/** ***Util parsing `phone-number` for {@link formatPhoneNumber}.***\n *\n * @internal\n */\nexport const parsingAsYouType = (\n  value: string,\n  defaultCountry?: CountryCode\n) => {\n  let parsed;\n  try {\n    parsed = new AsYouType(defaultCountry);\n    parsed.input(value);\n    return parsed;\n  } catch {\n    parsed?.reset();\n    return undefined;\n  }\n};\n\ntype ValidParseAsYouType = Prettify<\n  OmitStrict<AsYouType, \"getNumber\"> & {\n    getNumber(): PhoneNumber; // override agar tidak nullable\n  }\n>;\n\n/** ***Util validation parsing `phone-number` when using `AsYouType` for {@link formatPhoneNumber}.***\n *\n * @internal\n */\nexport const isValidParseAsYouType = (\n  parsedAsYouType?: AsYouType\n): parsedAsYouType is ValidParseAsYouType => {\n  const parsed = !!parsedAsYouType?.isValid() && !!parsedAsYouType.getNumber();\n  return parsed;\n};\n","import type {\n  FormatPhoneNumberMain,\n  FormatPhoneNumberTakeNumberOnly,\n  FormatPhoneNumberCheckValidOnly,\n  FormatPhoneNumberTransform,\n  ValueFormatPhoneNumber,\n  FormatPhoneNumberAllPassing,\n  FormatPhoneNumberAllPassingValidOnly,\n  FormatPhoneNumberAllPassingTakeOnly,\n  OutputFormat\n} from \"./_private/formatPhoneNumber.types\";\n\nimport { isSupportedCountry } from \"libphonenumber-js/max\";\n\nimport { createMessage } from \"@/_private/logger\";\n\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\n\nimport { isNil } from \"@/predicates/is/isNil\";\nimport { isNumber } from \"@/predicates/is/isNumber\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isBoolean } from \"@/predicates/is/isBoolean\";\nimport { isUndefined } from \"@/predicates/is/isUndefined\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport {\n  parsingAsYouType,\n  isValidParseAsYouType\n} from \"./_private/formatPhoneNumber.utils\";\n\n/** -------------------------------------------------------\n * * ***Utility: `formatPhoneNumber`.***\n * --------------------------------------------------------\n * **Formats a phone number into a customizable local or international style.**\n *\n * ---\n * - **Type:** ***`Formatting Number`.***\n * - **Can also:**\n *     - Return only digits string when **digits-only mode** (`takeNumberOnly`):\n *       - Return empty-string (\"\"), if invalid number phone.\n *     - Return boolean when **validity-check mode** (`checkValidOnly`):\n *       - ***Return `true` if:***\n *            - A phone number is \"valid\" when it has valid length, and the actual phone number digits match the\n *              regular expressions for its country (parameter options `defaultCountry`).\n * - **E.164 compliance:**\n *     - Optional leading `+` is recommended but **not required**.\n *     - If Without leading `+`, you must passing `defaultCountry`.\n *\n * ---\n * @param {ValueFormatPhoneNumber} value\n *  ***Phone number to format, accepts:***\n *     - `string` (recommended to preserve leading zeros).\n *     - `number` (leading zeros will be lost).\n *     - `null` or `undefined` (returns empty string).\n * @param {FormatPhoneNumberMain} [options]\n *  ***Main options object controlling:***\n *     - `separator` (**string**): Group separator, default `\" \"`.\n *     - `plusNumberCountry` (**string**): Country code with optional leading `+`.\n *     - `openingNumberCountry` (**string**): Characters before the country code, e.g. `\"(\"`.\n *     - `closingNumberCountry` (**string**): Characters after the country code, e.g. `\")\"`.\n *     - `checkValidOnly` (**boolean**): Return only validity.\n *     - `takeNumberOnly` (**boolean**): Return digits only.\n *     - `defaultCountry` (**string** - **`<ISO-3166-1 alpha-2>`**): Used to interpret numbers without an explicit `+<countryCode>`.\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `value` is not string, number, null or undefined.\n * @throws **{@link TypeError | `TypeError`}** if `options` is not an object or contains wrong types.\n *\n * ---\n * @returns {string|boolean} Formatted phone number string, digits-only string, or boolean.\n *\n * ---\n * @example\n *\n * 1. #### *Formatting Phone Number String:*\n *    ```ts\n *    formatPhoneNumber(\"081234567890\");\n *    // ➔ \"0812 3456 7890\"\n *    formatPhoneNumber(\"081234567890\", {\n *      separator: \"-\",\n *      plusNumberCountry: \"+44\",\n *      openingNumberCountry: \"(\",\n *      closingNumberCountry: \")\"\n *    });\n *    // ➔ \"(+44) 8123-4567-890\"\n *    ```\n *    ---\n * 2. #### *Digits-Only Mode:*\n *    ```ts\n *    formatPhoneNumber(\"(0812) 3456-7890\", {\n *      takeNumberOnly: true,\n *      defaultCountry: \"ID\"\n *    });\n *    // ➔ \"081234567890\"\n *    formatPhoneNumber(\"(0812) 3456-7890\", { takeNumberOnly: true });\n *    // ➔ \"\"\n *    formatPhoneNumber(\"(63) 917 123 4567\", {\n *      takeNumberOnly: true,\n *      defaultCountry: \"PH\"\n *    });\n *    // ➔ \"0917 123 4567\"\n *    formatPhoneNumber(\"(63) 4567-8901\", {\n *      takeNumberOnly: true,\n *      defaultCountry: \"PH\"\n *    });\n *    // ➔ \"\" // is not valid number from PH.\n *    formatPhoneNumber(\"(63) 917 123 4567\", { takeNumberOnly: true });\n *    // ➔ \"\"\n *    formatPhoneNumber(\"49 (151) 2345 6789\", {\n *      takeNumberOnly: true,\n *      defaultCountry: \"DE\"\n *    });\n *    // ➔ \"015123456789\"\n *    formatPhoneNumber(\"49 (151) 2345 6789\", { takeNumberOnly: true });\n *    // ➔ \"\"\n *    ```\n *    ---\n * 3. #### *Validity-Check Mode:*\n *    ```ts\n *    formatPhoneNumber(\"+6281234567890\", { checkValidOnly: true });\n *    // ➔ true\n *    formatPhoneNumber(\"0812-3456-7890\", {\n *      checkValidOnly: true,\n *      defaultCountry: \"ID\"\n *    });\n *    // ➔ true\n *    formatPhoneNumber(\"0812 3456 7890\", { checkValidOnly: true });\n *    // ➔ false\n *    formatPhoneNumber(\"(0812) 3456-7890\", {\n *      checkValidOnly: true,\n *      defaultCountry: \"ID\"\n *    });\n *    // ➔ true\n *    formatPhoneNumber(\"(0812) 3456-7890\", { checkValidOnly: true});\n *    // ➔ false\n *    formatPhoneNumber(\"+44 20 7946 0958\", { checkValidOnly: true });\n *    // ➔ true\n *    formatPhoneNumber(\"+1 (800) 123-4567\", { checkValidOnly: true });\n *    // ➔ true\n *    formatPhoneNumber(\"+62.812.3456.7890\", { checkValidOnly: true });\n *    // ➔ true\n *    formatPhoneNumber(\"+62(812)3456-7890\", { checkValidOnly: true });\n *    // ➔ true\n *    formatPhoneNumber(\"+62abc123\", { checkValidOnly: true });\n *    // ➔ false\n *    formatPhoneNumber(\"invalid@@@\", { checkValidOnly: true });\n *    // ➔ false\n *    formatPhoneNumber(\"0812-3456-hello\", { checkValidOnly: true });\n *    // ➔ false\n *    ```\n */\nexport function formatPhoneNumber(\n  value: ValueFormatPhoneNumber,\n  options?: FormatPhoneNumberTransform\n): string;\n/** -------------------------------------------------------\n * * ***Utility: `formatPhoneNumber`.***\n * --------------------------------------------------------\n * **Formats a phone number into a customizable local or international style.**\n *\n * ---\n * - **Type:** ***`Digits-only Mode`.***\n * - **Can also:**\n *     - Return only digits string when **digits-only mode** (`takeNumberOnly`).\n *     - Return boolean when **validity-check mode** (`checkValidOnly`) using a\n *       regex for international-style phone numbers:\n *       - ***Valid if:***\n *            - Only contains digits, optional leading `+`, spaces, parentheses `()`,\n *              hyphens `-`, or dots `.`.\n *            - Digits-only length < 16.\n * - **E.164 compliance:**\n *     - Optional leading `+` is recommended but **not required**.\n *     - If Without leading `+`, you must passing `defaultCountry`.\n *\n * ---\n * @param {ValueFormatPhoneNumber} value\n *   Phone number to format. Accepts:\n *    - `string` (recommended to preserve leading zeros).\n *    - `number` (leading zeros will be lost).\n *    - `null` or `undefined` (returns empty string).\n * @param {FormatPhoneNumberTakeNumberOnly} [options] Options to customize format output (country code, separator, etc).\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `value` is not string, number, null or undefined.\n * @throws **{@link TypeError | `TypeError`}** if `options` is not an object or contains wrong types.\n *\n * ---\n * @returns {string} Digits-only mode, return string a digits-only.\n *\n * ---\n * @example\n * ```ts\n * formatPhoneNumber(\"(0812) 3456-7890\", {\n *   takeNumberOnly: true,\n *   defaultCountry: \"ID\"\n * });\n * // ➔ \"081234567890\"\n * formatPhoneNumber(\"(0812) 3456-7890\", { takeNumberOnly: true });\n * // ➔ \"\"\n * formatPhoneNumber(\"(63) 917 123 4567\", {\n *   takeNumberOnly: true,\n *   defaultCountry: \"PH\"\n * });\n * // ➔ \"0917 123 4567\"\n * formatPhoneNumber(\"(63) 4567-8901\", {\n *   takeNumberOnly: true,\n *   defaultCountry: \"PH\"\n * });\n * // ➔ \"\" // is not valid number from PH.\n * formatPhoneNumber(\"(63) 917 123 4567\", { takeNumberOnly: true });\n * // ➔ \"\"\n * formatPhoneNumber(\"49 (151) 2345 6789\", {\n *   takeNumberOnly: true,\n *   defaultCountry: \"DE\"\n * });\n * // ➔ \"015123456789\"\n * formatPhoneNumber(\"49 (151) 2345 6789\", { takeNumberOnly: true });\n * // ➔ \"\"\n * ```\n */\nexport function formatPhoneNumber(\n  value: ValueFormatPhoneNumber,\n  options?: FormatPhoneNumberTakeNumberOnly\n): string;\n/** -------------------------------------------------------\n * * ***Utility: `formatPhoneNumber`.***\n * --------------------------------------------------------\n * **Formats a phone number into a customizable local or international style.**\n *\n * ---\n * - **Type:** ***`Validity-check Mode`.***\n * - **Can also:**\n *     - Return only digits string when **digits-only mode** (`takeNumberOnly`).\n *     - Return boolean when **validity-check mode** (`checkValidOnly`) using a\n *       regex for international-style phone numbers:\n *       - ***Valid if:***\n *            - Only contains digits, optional leading `+`, spaces, parentheses `()`,\n *              hyphens `-`, or dots `.`.\n *            - Digits-only length < 16.\n * - **E.164 compliance:**\n *     - Optional leading `+` is recommended but **not required**.\n *     - If Without leading `+`, you must passing `defaultCountry`.\n *\n * ---\n * @param {ValueFormatPhoneNumber} value\n *  Phone number to format. Accepts:\n *   - `string` (recommended to preserve leading zeros).\n *   - `number` (leading zeros will be lost).\n *   - `null` or `undefined` (returns empty string).\n * @param {FormatPhoneNumberTakeNumberOnly} [options] Options to customize format output (country code, separator, etc).\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `value` is not string, number, null or undefined.\n * @throws **{@link TypeError | `TypeError`}** if `options` is not an object or contains wrong types.\n *\n * ---\n * @returns {boolean} Validity-check mode, return a boolean.\n *\n * ---\n * @example\n * ```ts\n * formatPhoneNumber(\"+6281234567890\", { checkValidOnly: true });\n * // ➔ true\n * formatPhoneNumber(\"0812-3456-7890\", {\n *   checkValidOnly: true,\n *   defaultCountry: \"ID\"\n * });\n * // ➔ true\n * formatPhoneNumber(\"0812 3456 7890\", { checkValidOnly: true });\n * // ➔ false\n * formatPhoneNumber(\"(0812) 3456-7890\", {\n *   checkValidOnly: true,\n *   defaultCountry: \"ID\"\n * });\n * // ➔ true\n * formatPhoneNumber(\"(0812) 3456-7890\", { checkValidOnly: true});\n * // ➔ false\n * formatPhoneNumber(\"+44 20 7946 0958\", { checkValidOnly: true });\n * // ➔ true\n * formatPhoneNumber(\"+1 (800) 123-4567\", { checkValidOnly: true });\n * // ➔ true\n * formatPhoneNumber(\"+62.812.3456.7890\", { checkValidOnly: true });\n * // ➔ true\n * formatPhoneNumber(\"+62(812)3456-7890\", { checkValidOnly: true });\n * // ➔ true\n * formatPhoneNumber(\"+62abc123\", { checkValidOnly: true });\n * // ➔ false\n * formatPhoneNumber(\"invalid@@@\", { checkValidOnly: true });\n * // ➔ false\n * formatPhoneNumber(\"0812-3456-hello\", { checkValidOnly: true });\n * // ➔ false\n * ```\n */\nexport function formatPhoneNumber(\n  value: ValueFormatPhoneNumber,\n  options?: FormatPhoneNumberCheckValidOnly\n): boolean;\n/** -------------------------------------------------------\n * * ***Utility: `formatPhoneNumber`.***\n * --------------------------------------------------------\n * **Formats a phone number into a customizable local or international style.**\n *\n * ---\n * - **Type:** ***Forced to `Validity-check Mode`***, because `checkValidOnly` has set to `true`.\n * - **Can also:**\n *     - Return only digits string when **digits-only mode** (`takeNumberOnly`).\n *     - Return boolean when **validity-check mode** (`checkValidOnly`) using a\n *       regex for international-style phone numbers:\n *       - ***Valid if:***\n *            - Only contains digits, optional leading `+`, spaces, parentheses `()`,\n *              hyphens `-`, or dots `.`.\n *            - Digits-only length < 16.\n * - **E.164 compliance:**\n *     - Optional leading `+` is recommended but **not required**.\n *     - If Without leading `+`, you must passing `defaultCountry`.\n *\n * ---\n * @param {ValueFormatPhoneNumber} value\n *  Phone number to format. Accepts:\n *   - `string` (recommended to preserve leading zeros).\n *   - `number` (leading zeros will be lost).\n *   - `null` or `undefined` (returns empty string).\n * @param {FormatPhoneNumberTakeNumberOnly} [options] Options to customize format output (country code, separator, etc).\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `value` is not string, number, null or undefined.\n * @throws **{@link TypeError | `TypeError`}** if `options` is not an object or contains wrong types.\n *\n * ---\n * @returns {boolean} Validity-check mode, return a boolean.\n *\n * ---\n * @example\n * ```ts\n * formatPhoneNumber(\"+6281234567890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"0812-3456-7890\", {\n *   defaultCountry: \"ID\",\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"0812 3456 7890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n * });\n * // ➔ false\n * formatPhoneNumber(\"(0812) 3456-7890\", {\n *   defaultCountry: \"ID\",\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"(0812) 3456-7890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true\n * });\n * // ➔ false\n * formatPhoneNumber(\"+44 20 7946 0958\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true\n * });\n * // ➔ true\n * formatPhoneNumber(\"+1 (800) 123-4567\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true\n * });\n * // ➔ true\n * formatPhoneNumber(\"+62.812.3456.7890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true\n * });\n * // ➔ true\n * formatPhoneNumber(\"+62(812)3456-7890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true\n * });\n * // ➔ true\n * formatPhoneNumber(\"+62abc123\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true\n * });\n * // ➔ false\n * formatPhoneNumber(\"invalid@@@\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true\n * });\n * // ➔ false\n * formatPhoneNumber(\"0812-3456-hello\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true\n * });\n * // ➔ false\n * ```\n */\nexport function formatPhoneNumber(\n  value: ValueFormatPhoneNumber,\n  options?: FormatPhoneNumberAllPassingValidOnly\n): boolean;\n/** -------------------------------------------------------\n * * ***Utility: `formatPhoneNumber`.***\n * --------------------------------------------------------\n * **Formats a phone number into a customizable local or international style.**\n *\n * ---\n * - **Type:** ***Forced to `Digits-only Mode`***, because `takeNumberOnly` has set to `true`.\n * - **Can also:**\n *     - Return only digits string when **digits-only mode** (`takeNumberOnly`).\n *     - Return boolean when **validity-check mode** (`checkValidOnly`) using a\n *       regex for international-style phone numbers:\n *       - ***Valid if:***\n *            - Only contains digits, optional leading `+`, spaces, parentheses `()`,\n *              hyphens `-`, or dots `.`.\n *            - Digits-only length < 16.\n * - **E.164 compliance:**\n *     - Optional leading `+` is recommended but **not required**.\n *     - If Without leading `+`, you must passing `defaultCountry`.\n *\n * ---\n * @param {ValueFormatPhoneNumber} value\n *  Phone number to format. Accepts:\n *   - `string` (recommended to preserve leading zeros)\n *   - `number` (leading zeros will be lost)\n *   - `null` or `undefined` (returns empty string).\n * @param {FormatPhoneNumberTakeNumberOnly} [options] Options to customize format output (country code, separator, etc).\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `value` is not string, number, null or undefined.\n * @throws **{@link TypeError | `TypeError`}** if `options` is not an object or contains wrong types.\n *\n * ---\n * @returns {string} Digits-only mode, return string a digits-only.\n *\n * ---\n * @example\n * ```ts\n * formatPhoneNumber(\"(0812) 3456-7890\", {\n *   defaultCountry: \"ID\",\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ \"081234567890\"\n * formatPhoneNumber(\"(0812) 3456-7890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ \"\"\n * formatPhoneNumber(\"(63) 917 123 4567\", {\n *   defaultCountry: \"PH\",\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ \"0917 123 4567\"\n * formatPhoneNumber(\"(63) 4567-8901\", {\n *   defaultCountry: \"PH\",\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ \"\" // is not valid number from PH.\n * formatPhoneNumber(\"(63) 917 123 4567\", { takeNumberOnly: true });\n * // ➔ \"\"\n * formatPhoneNumber(\"49 (151) 2345 6789\", {\n *   defaultCountry: \"DE\",\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ \"015123456789\"\n * formatPhoneNumber(\"49 (151) 2345 6789\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ \"\"\n * ```\n */\nexport function formatPhoneNumber(\n  value: ValueFormatPhoneNumber,\n  options?: FormatPhoneNumberAllPassingTakeOnly\n): string;\n/** -------------------------------------------------------\n * * ***Utility: `formatPhoneNumber`.***\n * --------------------------------------------------------\n * **Formats a phone number into a customizable local or international style.**\n *\n * ---\n * - **Type:** ***Forced to `Validity-check Mode`***, because `checkValidOnly` and `takeNumberOnly` has set to `true`,\n *   but `checkValidOnly` will prioritize one.\n * - **Can also:**\n *     - Return only digits string when **digits-only mode** (`takeNumberOnly`).\n *     - Return boolean when **validity-check mode** (`checkValidOnly`) using a\n *       regex for international-style phone numbers:\n *       - ***Valid if:***\n *            - Only contains digits, optional leading `+`, spaces, parentheses `()`,\n *              hyphens `-`, or dots `.`.\n *            - Digits-only length < 16.\n * - **E.164 compliance:**\n *     - Optional leading `+` is recommended but **not required**.\n *     - If Without leading `+`, you must passing `defaultCountry`.\n *\n * ---\n * @param {ValueFormatPhoneNumber} value\n *  Phone number to format. Accepts:\n *   - `string` (recommended to preserve leading zeros).\n *   - `number` (leading zeros will be lost).\n *   - `null` or `undefined` (returns empty string).\n * @param {FormatPhoneNumberTakeNumberOnly} [options] Options to customize format output (country code, separator, etc).\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `value` is not string, number, null or undefined.\n * @throws **{@link TypeError | `TypeError`}** if `options` is not an object or contains wrong types.\n *\n * ---\n * @returns {boolean} Validity-check mode, return a boolean.\n *\n * ---\n * @example\n * ```ts\n * formatPhoneNumber(\"+6281234567890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"0812-3456-7890\", {\n *   defaultCountry: \"ID\",\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"0812 3456 7890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ false\n * formatPhoneNumber(\"(0812) 3456-7890\", {\n *   defaultCountry: \"ID\",\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"(0812) 3456-7890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ false\n * formatPhoneNumber(\"+44 20 7946 0958\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"+1 (800) 123-4567\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"+62.812.3456.7890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"+62(812)3456-7890\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ true\n * formatPhoneNumber(\"+62abc123\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ false\n * formatPhoneNumber(\"invalid@@@\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ false\n * formatPhoneNumber(\"0812-3456-hello\", {\n *   // Formatting Phone Number Options\n *   separator: \"-\",\n *   // Validity-check Mode\n *   checkValidOnly: true,\n *   // Digits-only Mode\n *   takeNumberOnly: true,\n * });\n * // ➔ false\n * ```\n */\nexport function formatPhoneNumber(\n  value: ValueFormatPhoneNumber,\n  options?: FormatPhoneNumberAllPassing\n): boolean;\nexport function formatPhoneNumber(\n  value: ValueFormatPhoneNumber,\n  options?: FormatPhoneNumberMain\n): string | boolean {\n  if (isNil(value)) return \"\";\n\n  if (!isString(value) && !isNumber(value)) {\n    throw new TypeError(\n      errorMsg(\n        `First parameter (\\`value\\`) must be of type \\`string\\`, \\`number\\`, \\`null\\` or \\`undefined\\`, but received: \\`${getPreciseType(\n          value\n        )}\\`.`\n      )\n    );\n  }\n\n  if (!isPlainObject(options)) options = {};\n\n  const takeNumberOnly = options.takeNumberOnly ?? false;\n  const checkValidOnly = options.checkValidOnly ?? false;\n  const defaultCountry: typeof options.defaultCountry =\n    options.defaultCountry ?? undefined;\n\n  const separator = options.separator ?? \" \";\n  const prependPlusCountryCode = options.prependPlusCountryCode ?? true;\n  const outputFormat: OutputFormat = options.outputFormat ?? \"INTERNATIONAL\";\n  const openingNumberCountry = options.openingNumberCountry ?? \"\";\n  const closingNumberCountry = options.closingNumberCountry ?? \"\";\n\n  if (\n    !isBoolean(takeNumberOnly) ||\n    !isBoolean(checkValidOnly) ||\n    !isBoolean(prependPlusCountryCode)\n  ) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`takeNumberOnly\\`, \\`checkValidOnly\\` and \\`prependPlusCountryCode\\` property of the \\`options\\` (second parameter) must be of type \\`boolean\\` or unset as \\`undefined\\` value, but received: ['takeNumberOnly': \\`${getPreciseType(\n          takeNumberOnly\n        )}\\`, 'checkValidOnly': \\`${getPreciseType(\n          checkValidOnly\n        )}\\`, 'prependPlusCountryCode': \\`${getPreciseType(prependPlusCountryCode)}\\`].`\n      )\n    );\n  }\n\n  if (!isUndefined(defaultCountry) && !isSupportedCountry(defaultCountry)) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`defaultCountry\\` property of the \\`options\\` (second parameter) must be of type \\`string\\` as \\`CountryCode\\` (ISO-3166-1 alpha-2) or unset as \\`undefined\\` value, but received: \\`${getPreciseType(\n          defaultCountry\n        )}\\`, with value: \\`${safeStableStringify(defaultCountry, {\n          keepUndefined: true\n        })}\\`.\\n\\nSee: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements, for all ISO 3166-1 alpha-2 code.`\n      )\n    );\n  }\n\n  if (\n    ![\"INTERNATIONAL\", \"NATIONAL\", \"RFC3966\", \"E.164\"].includes(outputFormat)\n  ) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`outputFormat\\` property of the \\`options\\` (second parameter) must be of type \\`string\\` as \\`OutputFormat\\` (\"NATIONAL\" | \"INTERNATIONAL\" | \"E.164\" | \"RFC3966\") or unset as \\`undefined\\` (default value to: \\`INTERNATIONAL\\`) value, but received: \\`${getPreciseType(\n          outputFormat\n        )}\\`, with value: ${safeStableStringify(outputFormat, { keepUndefined: true })}.`\n      )\n    );\n  }\n\n  if (\n    !isString(separator) ||\n    !isString(openingNumberCountry) ||\n    !isString(closingNumberCountry)\n  ) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`separator\\`, \\`plusNumberCountry\\`, \\`openingNumberCountry\\` and \\`closingNumberCountry\\` property of the \\`options\\` (second parameter) must be of type \\`string\\` or unset as \\`undefined\\` value, but received: ['separator': \\`${getPreciseType(\n          separator\n        )}\\`,'openingNumberCountry': \\`${getPreciseType(\n          openingNumberCountry\n        )}\\`, 'closingNumberCountry': \\`${getPreciseType(closingNumberCountry)}\\`].`\n      )\n    );\n  }\n\n  if (!isString(value)) value = String(value);\n\n  const parsedPhoneNumber = parsingAsYouType(value, defaultCountry);\n  const validPhoneNumber = isValidParseAsYouType(parsedPhoneNumber);\n\n  if (checkValidOnly) return validPhoneNumber;\n\n  // todo: return empty-string is invalid phone-number input.\n  if (!validPhoneNumber) return \"\";\n\n  if (takeNumberOnly) {\n    return parsedPhoneNumber.getNumber().formatNational().replace(/\\D/g, \"\");\n  }\n\n  const num = parsedPhoneNumber.getNumber();\n  // Result example: \"+49 1512 3456789\"\n  const intlNumb = num.format(outputFormat);\n\n  if (outputFormat === \"INTERNATIONAL\") {\n    // Split to: [\"+49\", \"1512\", \"3456789\"]\n    const [cc, ...rest] = intlNumb.split(\" \");\n    const countryCode = prependPlusCountryCode ? cc : cc?.replace(/^\\++/, \"\");\n    const restWithSeparator = rest.join(separator);\n\n    if (!countryCode) return restWithSeparator;\n\n    if (\n      isNonEmptyString(openingNumberCountry) &&\n      isNonEmptyString(closingNumberCountry)\n    ) {\n      return `${openingNumberCountry}${countryCode}${closingNumberCountry} ${restWithSeparator}`;\n    }\n\n    return `${countryCode} ${restWithSeparator}`;\n  }\n\n  if (outputFormat === \"NATIONAL\") {\n    const restWithSeparator = intlNumb.split(\" \").join(separator);\n\n    return `${restWithSeparator}`;\n  }\n\n  return intlNumb;\n}\n\n/**\n * @internal ***`Not part of the public API.`***\n */\nconst errorMsg = (msg: string) => createMessage(\"formatPhoneNumber\", msg);\n","// eslint-disable-next-line @typescript-eslint/no-unused-vars\nimport type { censorEmail } from \"../censorEmail\";\nimport { isUndefined } from \"@/predicates/is/isUndefined\";\n\n/** ----------------------------------------------------------\n * * ***Util helper for {@link censorEmail}.***\n * -----------------------------------------------------------\n *\n * @internal ***`Not part of the public API.`***\n */\nexport const hashSeedGenerate = (mode: \"random\" | \"fixed\", email: string) => {\n  const generateSeed = () => {\n    let hash = 0;\n    for (let i = 0; i < email.length; i++) {\n      hash = (hash << 5) - hash + email.charCodeAt(i);\n      hash |= 0; // Convert to 32bit int\n    }\n    return Math.abs(hash);\n  };\n\n  return mode === \"fixed\" ? generateSeed() : undefined;\n};\n\n/** ----------------------------------------------------------\n *  * ***Internal Randomly replaces characters in a string with \"\\*\".***\n * -----------------------------------------------------------\n *\n * @param {string} str - The string to censor.\n * @param {number} minCensor - Minimum number of characters to censor.\n * @param {number} maxPercentage - Maximum percentage of characters to censor.\n *\n * ---\n * @returns {string} - Censored string.\n *\n * ---\n * @internal ***Util helper for {@link censorEmail}.***\n */\nexport const _censor = (\n  str: string,\n  minCensor: number,\n  maxPercentage: number,\n  hashSeed: number | undefined\n): string => {\n  if (str.length <= minCensor) return \"*\".repeat(str.length);\n\n  const strArr = str.split(\"\");\n  const totalCensor = Math.max(\n    minCensor,\n    Math.ceil(str.length * maxPercentage)\n  );\n  const indexes = new Set<number>();\n\n  let i = 0;\n  while (indexes.size < totalCensor) {\n    const idx = !isUndefined(hashSeed)\n      ? (hashSeed + str.length + i * 31) % str.length\n      : Math.floor(Math.random() * str.length);\n    indexes.add(idx);\n    i++;\n  }\n\n  for (const index of indexes) {\n    strArr[index] = \"*\";\n  }\n\n  return strArr.join(\"\");\n};\n","import { createMessage } from \"@/_private/logger\";\n\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\n\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\nimport { _censor, hashSeedGenerate } from \"./_private/censorEmail.utils\";\n\ntype CensorEmailOptions = {\n  /** ----------------------------------------------------------\n   * * ***Censorship Mode.***\n   * -----------------------------------------------------------\n   * - **Valid value:**\n   *     - `\"random\"` – Each character is randomly replaced every time the function is called.\n   *     - `\"fixed\"` ***(default)*** – Deterministic censorship based on a hash of the email, same input always produces the same output.\n   *\n   * ---\n   * @default \"fixed\"\n   */\n  mode?: \"random\" | \"fixed\";\n};\n\n/** ----------------------------------------------------------\n * * ***Utility: `censorEmail`.***\n * -----------------------------------------------------------\n * **Censors an email by replacing characters with `\"*\"` while supporting random or fixed mode.**\n *\n * ---\n * - **This function replaces parts of an email with asterisks to protect privacy.**\n *      - **Modes:**\n *          - `\"fixed\"` **(default)** – Deterministic censorship based on a hash of the email, same input always produces the same output.\n *          - `\"random\"` – Each character is randomly replaced every time the function is called.\n *      - **Note:**\n *          - Invalid emails or non-string input will return an empty-string (`\"\"`).\n *\n * ---\n * @param {string | null | undefined} email - The email address to censor.\n * @param {CensorEmailOptions} [options={}] - Options object for mode.\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `options` is not a plain object or `mode` is invalid.\n *\n * ---\n * @returns {string} The censored email, or an empty string if input is invalid.\n *\n * ---\n * @example\n *\n * 1. #### Fixed mode (default, deterministic):\n *    ```ts\n *    censorEmail(\"john.doe@gmail.com\");\n *    // ➔ \"j**n.**e@g***l.com\"\n *    ```\n *    ---\n * 2. #### Fixed mode explicitly:\n *    ```ts\n *    censorEmail(\"john.doe@gmail.com\", { mode: \"fixed\" });\n *    // ➔ \"j**n.**e@g***l.com\"\n *    ```\n *    ---\n * 3. #### Random mode (output may vary each time):\n *    ```ts\n *    censorEmail(\"john.doe@gmail.com\", { mode: \"random\" });\n *    // ➔ \"j*hn.***e@g***l.com\" (random)\n *    ```\n *    ---\n * 4. #### Invalid email returns empty string:\n *    ```ts\n *    censorEmail(\"invalid-email\");\n *    // ➔ \"\"\n *    ```\n */\nexport const censorEmail = (\n  email: string | null | undefined,\n  options?: CensorEmailOptions\n): string => {\n  if (!isNonEmptyString(email)) return \"\";\n  if (!isPlainObject(options)) options = {};\n\n  const mode = options.mode ?? \"fixed\";\n\n  // Ensure mode is either \"random\" or \"fixed\"\n  if (mode !== \"random\" && mode !== \"fixed\") {\n    throw new TypeError(\n      createMessage(\n        \"censorEmail\",\n        `Parameter \\`mode\\` property of the \\`options\\` (second parameter) must be one of \"fixed\" or \"random\", but received: \\`${getPreciseType(\n          mode\n        )}\\`, with value: \\`${safeStableStringify(mode, {\n          keepUndefined: true\n        })}\\`.`\n      )\n    );\n  }\n\n  // Strict email validation regex\n  const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/;\n  if (!emailRegex.test(email)) return \"\";\n\n  const [local, domain] = email.split(\"@\");\n  const domainParts = domain?.split(\".\"); // Handle multi-level domain (e.g., example.co.uk)\n  if (!local || !domainParts || domainParts.length < 2) return \"\"; // Invalid domain structure\n\n  const [domainName, ...tldParts] = domainParts;\n\n  if (!domainName) return \"\";\n\n  const tld = tldParts.join(\".\");\n\n  const hashSeed = hashSeedGenerate(mode, email);\n\n  const localMinCensor = local.length < 4 ? 1 : 2;\n  const domainMinCensor = domainName.length < 4 ? 1 : 2;\n\n  const censoredLocal = _censor(local, localMinCensor, 0.6, hashSeed);\n  const censoredDomain = _censor(domainName, domainMinCensor, 0.5, hashSeed);\n  const censoredTLD = tld.length <= 2 ? tld : _censor(tld, 1, 0.4, hashSeed);\n\n  return `${censoredLocal}@${censoredDomain}.${censoredTLD}`;\n};\n","import { createMessage } from \"@/_private/logger\";\n\nimport { assertIsString } from \"@/assertions/strings/assertIsString\";\nimport { assertIsBoolean } from \"@/assertions/booleans/assertIsBoolean\";\n\nimport { normalizeSpaces } from \"@/strings/sanitizations/normalizeSpaces\";\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\n\nimport { isNil } from \"@/predicates/is/isNil\";\nimport { isInteger } from \"@/predicates/is/isInteger\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\n\ntype ChunkStringOptions = {\n  /** ---------------------------------------------------------\n   * * ***The separator string to insert between characters or words.***\n   * ----------------------------------------------------------\n   *\n   * - #### *Behavior:*\n   *      - Used when inserting separators every `limiter` characters.\n   *      - Default is a single space `\" \"`.\n   *\n   * ---\n   * @default \" \"\n   */\n  separator?: string;\n\n  /** ---------------------------------------------------------\n   * * ***Determines whether counting for `limiter` resets after each space.***\n   * ----------------------------------------------------------\n   *\n   * - #### *Behavior:*\n   *      - If `true`, the string is treated as words separated by spaces,\n   *        and separators are applied within words, then words are grouped.\n   *      - If `false` ***(default)***, counting is continuous across the whole string,\n   *        treating spaces as normal characters.\n   *\n   * ---\n   * @default false\n   */\n  reCountAfterSpace?: boolean;\n};\n\n/** ---------------------------------------------------------\n * * ***Utility: `chunkString`.***\n * ----------------------------------------------------------\n * **Chunks a string by inserting a separator every `limiter` characters.**\n *\n * - #### **This function handles two main behaviors based on `reCountAfterSpace`:**\n *      1. #### *If `reCountAfterSpace` is `false` (default):*\n *            - The separator is inserted strictly every `limiter` characters throughout the entire string, regardless of spaces, spaces are\n *              treated as regular characters in the count.\n *                - Example: `chunkString(\"1234567890\", 3, \"-\")` ➔ `\"123-456-789-0\"`.\n *                - Example: `chunkString(\"Hello World\", 3, \"-\")` ➔ `\"Hel-lo -Wor-ld\"`.\n *            ---\n *      2. #### *If `reCountAfterSpace` is `true`:*\n *            - The function first processes the input string to replace any multiple consecutive spaces with a\n *              single space (e.g., `\"A   B\"` becomes `\"A B\"`).\n *              Then, it treats the string as a sequence of **\"words\"** (segments separated by single spaces).\n *                - Each word is processed independently:\n *                  - if a word's length exceeds the `limiter`, separators are inserted internally within that word.\n *                  - Words are then grouped. Each group will contain `limiter` number of words.\n *                  - Words within the same group are joined by the specified `separator`.\n *                  - Finally, these groups are joined by a single space, preserving the original word separation\n *                    structure between groups.\n *\n * ---\n * @param {string} subject - ***The target string to chunk.****\n * @param {number} limiter\n *  ***The interval (number of characters) for inserting separators, behavior:***\n *   - If `reCountAfterSpace = false`, it counts characters.\n *   - If `reCountAfterSpace = true`, it counts both characters within words and words per group.\n * @param {ChunkStringOptions} [options={}] - ***Optional settings for separator and counting behavior.***\n *\n * ---\n * @returns {string} Return the formatted string with separators.\n *\n * ---\n * @example\n * // Basic usage\n * chunkString(\"1234567890\", 3);\n * // ➔ \"123 456 789 0\"\n *\n * // Basic usage `reCountAfterSpace = false` (default)\n * chunkString(\"1234567890\", 3, { separator: \"-\");\n * // ➔ \"123-456-789-0\"\n * chunkString(\"HelloWorld\", 2, { separator: \"_\", reCountAfterSpace: false });\n * // ➔ \"He_ll_oW_or_ld\"\n *\n * // Usage with reCountAfterSpace = true:\n * // Multiple spaces are normalized to single spaces before processing.\n * chunkString(\"AB  CD   EF GH\", 2, { separator: \"-\", reCountAfterSpace: true });\n * // ➔ \"AB-CD EF-GH\" (after normalization to \"AB CD EF GH\")\n * // Words \"AB\" and \"CD\" form a group and are joined by \"-\", \"EF\" and \"GH\" form another group.\n * // The groups \"AB-CD\" and \"EF-GH\" are then joined by a space.\n *\n * // Another usage with reCountAfterSpace = true:\n * chunkString(\"ABC DEF GHI JKL\", 3, { separator: \"-\", reCountAfterSpace: true });\n * // ➔ \"ABC-DEF-GHI JKL\"\n * // Words \"ABC\", \"DEF\", \"GHI\" form a group and are joined by \"-\".\n * // The word \"JKL\" forms its own group (as it's the last word and completes no other group).\n * // The groups \"ABC-DEF-GHI\" and \"JKL\" are then joined by a space.\n */\nexport function chunkString(\n  subject: string,\n  limiter: number,\n  options?: ChunkStringOptions\n): string {\n  if (isNil(subject) || limiter <= 0) return subject;\n\n  assertIsString(subject, {\n    message: ({ currentType, validType }) =>\n      errorMsg(\n        `First parameter (\\`subject\\`) must be of type \\`${validType}\\`, but received: \\`${currentType}\\`.`\n      )\n  });\n\n  if (!isInteger(limiter)) {\n    throw new TypeError(\n      errorMsg(\n        `Second parameter (\\`limiter\\`) must be of type \\`integer-number\\`, but received: \\`${getPreciseType(\n          limiter\n        )}\\`, with value: \\`${safeStableStringify(limiter, {\n          keepUndefined: true\n        })}\\`.`\n      )\n    );\n  }\n\n  if (!isPlainObject(options)) options = {};\n\n  const separator = options.separator ?? \" \";\n  const reCountAfterSpace = options.reCountAfterSpace ?? false;\n\n  assertIsString(separator, {\n    message: ({ currentType, validType }) =>\n      errorMsg(\n        `Parameter \\`separator\\` property of the \\`options\\` (third parameter) must be of type \\`${validType}\\`, but received: \\`${currentType}\\`.`\n      )\n  });\n\n  assertIsBoolean(reCountAfterSpace, {\n    message: ({ currentType, validType }) =>\n      errorMsg(\n        `Parameter \\`reCountAfterSpace\\` property of the \\`options\\` (third parameter) must be of type \\`${validType}\\`, but received: \\`${currentType}\\`.`\n      )\n  });\n\n  subject = normalizeSpaces(subject);\n\n  // Handle reCountAfterSpace = false (assumed correct from previous iterations)\n  if (!reCountAfterSpace) {\n    let result = \"\";\n    let currentCount = 0;\n\n    for (let i = 0; i < subject.length; i++) {\n      const char = subject[i];\n      if (currentCount === limiter) {\n        result += separator;\n        currentCount = 0;\n      }\n      result += char;\n      currentCount++;\n    }\n    return result;\n  }\n\n  // --- Dynamic Logic for reCountAfterSpace = true ---\n  const words = subject.split(\" \"); // Split the string into individual words by spaces\n  const finalSegments: string[] = [];\n\n  let currentGroup: string[] = [];\n  let wordsInCurrentGroupCount = 0; // This counts how many words are in the current group\n\n  for (let i = 0; i < words.length; i++) {\n    const word = words[i];\n\n    // Check if the current word itself needs internal separators (e.g., \"HelloWorld\" with limiter 2)\n    // For the given test cases (\"AB\", \"CD\", \"ABC\"), this inner loop doesn't add separators,\n    // as the words themselves are shorter than or equal to the limiter.\n    let processedWord = \"\";\n    let charCountInWord = 0;\n\n    if (word) {\n      for (let j = 0; j < word.length; j++) {\n        processedWord += word[j];\n        charCountInWord++;\n        if (charCountInWord === limiter && j < word.length - 1) {\n          processedWord += separator;\n          charCountInWord = 0;\n        }\n      }\n    }\n\n    currentGroup.push(processedWord);\n    wordsInCurrentGroupCount++;\n\n    // If the current group has reached the limiter (e.g., 2 words for limiter=2, or 3 words for limiter=3)\n    // OR if it's the last word in the entire subject, finalize the group.\n    if (wordsInCurrentGroupCount === limiter || i === words.length - 1) {\n      finalSegments.push(currentGroup.join(separator)); // Join words within the group by separator\n      currentGroup = []; // Reset group for the next set of words\n      wordsInCurrentGroupCount = 0; // Reset group word count\n    }\n  }\n\n  // Finally, join the main segments (groups) with spaces\n  return finalSegments.join(\" \");\n}\n\n/**\n * @internal ***`Not part of the public API.`***\n */\nconst errorMsg = (msg: string) => createMessage(\"chunkString\", msg);\n","import { createMessage } from \"@/_private/logger\";\n\nimport { assertIsString } from \"@/assertions/strings/assertIsString\";\nimport { assertIsBoolean } from \"@/assertions/booleans/assertIsBoolean\";\nimport { safeStableStringify } from \"@/conversions/stringify/safeStableStringify\";\n\nimport { isInteger } from \"@/predicates/is/isInteger\";\nimport { isEmptyString } from \"@/predicates/is/isEmptyString\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { getPreciseType } from \"@/predicates/type/getPreciseType\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\ntype TruncateStringOptions = {\n  /** ---------------------------------------------------------\n   * * ***Maximum length of the truncated string **(default: `10`)**.***\n   * ----------------------------------------------------------\n   *\n   * @default 10\n   */\n  length?: number;\n\n  /** ---------------------------------------------------------\n   * * ***String to append if truncation occurs.***\n   * ----------------------------------------------------------\n   *\n   * - Will be trimmed first; defaults to `\"...\"` if empty.\n   *\n   * @default \"...\"\n   */\n  ending?: string;\n\n  /** ---------------------------------------------------------\n   * * ***Whether to trim the input string before truncation ***(default: `true`)***.***\n   * ----------------------------------------------------------\n   *\n   * @default true\n   */\n  trim?: boolean;\n};\n\n/** ----------------------------------------------------------\n * * ***Utility: `truncateString`.***\n * -----------------------------------------------------------\n * - **Features:**\n *     - Truncates a string to a specified length and optionally appends an ending.\n *     - Supports trimming the input before truncation.\n *     - If truncation occurs, trailing spaces before the ending are removed.\n *     - The `ending` parameter is always trimmed first; if empty, it defaults to `\"...\"`.\n *\n * ---\n * @param {string|null|undefined} text\n *  ***The input string to truncate, behavior:***\n *    - If `null`, `undefined`, or empty after trim, returns `\"\"`.\n * @param {TruncateStringOptions} [options]\n *  ***Optional settings:***\n *     - `length` (number, default 10): Maximum length of the truncated string.\n *     - `ending` (string, default `\"...\"`): String to append if truncation occurs.\n *     - `trim` (boolean, default `true`): Whether to trim the input before truncation.\n *\n * ---\n * @throws **{@link TypeError | `TypeError`}** if `options.length` is not a finite number, or if `options.ending` is not a string, or if `options.trim` is not a boolean.\n *\n * ---\n * @returns {string} The truncated string with optional trimming and ending, returns `\"\"` if input is empty or length < 1.\n *\n * ---\n * @example\n * truncateString(\"hello world\", { length: 5 });\n * // ➔ \"hello...\"\n * truncateString(\"hello world\", { length: 5, ending: \"---\" });\n * // ➔ \"hello---\"\n * truncateString(\"hello world\", { length: 5, ending: \"   \" });\n * // ➔ \"hello...\" (ending trimmed to default)\n * truncateString(\"hello world\", { length: 5, ending: \"   !!!   \" });\n * // ➔ \"hello!!!\" (ending trimmed)\n * truncateString(\"   long data string   \", { length: 8, ending: \"...\", trim: true });\n * // ➔ \"long dat...\"\n * truncateString(\"   long data string   \", { length: 8, ending: \"...\", trim: false });\n * // ➔ \"   long ...\"\n * truncateString(null, { length: 5 });\n * // ➔ \"\"\n */\nexport const truncateString = (\n  text: string | null | undefined,\n  options?: TruncateStringOptions\n): string => {\n  if (!isNonEmptyString(text)) return \"\";\n  if (!isPlainObject(options)) options = {};\n\n  const trim = options.trim ?? true;\n  const length = options.length ?? 10;\n  let ending = options.ending ?? \"...\";\n\n  if (!isInteger(length)) {\n    throw new TypeError(\n      errorMsg(\n        `Parameter \\`length\\` property of the \\`options\\` (second parameter) must be of type \\`integer-number\\`, but received: \\`${getPreciseType(\n          length\n        )}\\`, with value: \\`${safeStableStringify(length, {\n          keepUndefined: true\n        })}\\`.`\n      )\n    );\n  }\n\n  if (length < 1) return \"\";\n\n  assertIsString(ending, {\n    message: ({ currentType, validType }) =>\n      errorMsg(\n        `Parameter \\`ending\\` property of the \\`options\\` (second parameter) must be of type \\`${validType}\\`, but received: \\`${currentType}\\`.`\n      )\n  });\n\n  assertIsBoolean(trim, {\n    message: ({ currentType, validType }) =>\n      errorMsg(\n        `Parameter \\`trim\\` property of the \\`options\\` (second parameter) must be of type \\`${validType}\\`, but received: \\`${currentType}\\`.`\n      )\n  });\n\n  if (isEmptyString(ending)) {\n    ending = \"...\";\n  } else {\n    ending = ending.trim();\n  }\n\n  const original = trim ? text.trim() : text;\n  const originalTrimmedLength = original.length;\n\n  if (originalTrimmedLength <= length) return original;\n\n  const sliced = original.slice(0, length);\n  const cleanSliced = trim ? sliced : sliced.trimEnd();\n\n  return cleanSliced + ending;\n};\n\n/**\n * @internal ***`Not part of the public API.`***\n */\nconst errorMsg = (msg: string) => createMessage(\"truncateString\", msg);\n","import type { FormatDateFnsOptions } from \"./_private/formatDateFns.types\";\n\nimport { id, enUS } from \"date-fns/locale\";\nimport { format as formatDns, parse } from \"date-fns\";\n\nimport { isNaN } from \"@/predicates/is/isNaN\";\nimport { isNil } from \"@/predicates/is/isNil\";\nimport { isDate } from \"@/predicates/is/isDate\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\n/** --------------------------------------------------------------------------------------------------\n * * ***Utility: `formatDateFns`.***\n * ---------------------------------------------------------------------------------------------------\n * **Formats a date into a human-readable string using `date-fns`.**\n *\n * ---\n * - **Features:**\n *      - Supports custom output formats using `date-fns/format`.\n *      - Can parse localized non-ISO strings via `inputFormat` & `inputLocale`.\n *      - Supports `locale` as `\"id\"`, `\"en\"` or `date-fns` `Locale` objects (like `id` or `enUS`).\n *      - Returns `null` if the date is invalid, not provided, or parsing fails.\n *\n * ---\n * @param {string | Date | null | undefined} date\n *  ***The date input to format, can be:***\n *      - A `Date` object.\n *      - An ISO string (e.g. `\"2024-01-01T12:00:00Z\"`).\n *      - A localized string (requires `inputFormat` + `inputLocale`).\n * @param {FormatDateFnsOptions} [options] ***Options for formatting and parsing.***\n * @param {FormatDateFnsOptions[\"format\"]} [options.format=\"dd MMM yyyy - HH:mm:ss\"]\n *   ***The output format string (passed to `date-fns/format`), e.g:***\n *      - `\"dd MMMM yyyy, HH:mm:ss\" ➔ \"14 Juli 2025, 17:25:42\"`.\n * @param {FormatDateFnsOptions[\"locale\"]} [options.locale=\"id\"]\n *   The output locale. If string, only `\"id\"` (Indonesian) or `\"en\"` (English)\n *   is recognized. Or you can pass a `date-fns` `Locale` object.\n *   - Example:\n *     ```ts\n *       import { ar } from \"date-fns/locale\";\n *       formatDateFns(new Date(), { locale: ar, format: \"PPPppp\" });\n *     ```\n * @param {FormatDateFnsOptions[\"inputLocale\"]} [options.inputLocale]\n *     Required if `date` is a localized non-ISO string. Used with `inputFormat`.\n *   - Example for Indonesian string:\n *     ```ts\n *       formatDateFns(\"14 Juli 2025 10:25:42\", { inputFormat: \"dd MMMM yyyy HH:mm:ss\", inputLocale: \"id\" });\n *     ```\n * @param {FormatDateFnsOptions[\"inputFormat\"]} [options.inputFormat]\n *   The format string to parse `date` if it is a non-ISO string.\n *   Required together with `inputLocale`.\n *\n * ---\n * @returns {string | null} A formatted date string or `null` if input is invalid.\n *\n * ---\n * @example\n * formatDateFns(new Date());\n * // ➔ \"14 Jul 2025 - 17:25:42\"\n * formatDateFns(\"2025-07-14T10:25:42Z\", { format: \"dd/MM/yyyy\", locale: \"en\" });\n * // ➔ \"14/07/2025\"\n * formatDateFns(\"14 Juli 2025 10:25:42\", {\n *   inputFormat: \"dd MMMM yyyy HH:mm:ss\",\n *   inputLocale: \"id\",\n *   format: \"yyyy-MM-dd\"\n * });\n * // ➔ \"2025-07-14\"\n * formatDateFns(null);\n * // ➔ null\n */\nexport const formatDateFns = (\n  date: string | Date | null | undefined,\n  options: FormatDateFnsOptions = {}\n): string | null => {\n  if (isNil(date) || !(isDate(date) || isNonEmptyString(date))) return null;\n\n  // Ensure options is an object and Defensive options check\n  if (!isPlainObject(options)) {\n    options = {};\n  }\n\n  const {\n    inputFormat,\n    locale = \"en\",\n    inputLocale = \"en\",\n    ...restOptions\n  } = options;\n\n  const format = options.format ?? \"dd MMM yyyy - HH:mm:ss\";\n\n  let parsedDate: Date;\n\n  try {\n    if (isNonEmptyString(date) && inputFormat && inputLocale) {\n      const valueOfInputLocale = isNonEmptyString(inputLocale)\n        ? inputLocale === \"id\"\n          ? id\n          : enUS\n        : inputLocale;\n\n      parsedDate = parse(date, inputFormat, new Date(), {\n        locale: valueOfInputLocale\n      });\n    } else {\n      parsedDate = new Date(date);\n    }\n\n    if (isNaN(parsedDate.getTime())) return null;\n\n    const valueOfLocale = isNonEmptyString(locale)\n      ? locale === \"id\"\n        ? id\n        : enUS\n      : locale;\n\n    return formatDns(parsedDate, format, {\n      ...restOptions,\n      locale: valueOfLocale\n    });\n  } catch {\n    return null;\n  }\n};\n","import type { FormatDateIntlOptions } from \"./_private/formatDateIntl.types\";\n\nimport { isNaN } from \"@/predicates/is/isNaN\";\nimport { isNil } from \"@/predicates/is/isNil\";\nimport { isDate } from \"@/predicates/is/isDate\";\nimport { isPlainObject } from \"@/predicates/is/isPlainObject\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\n/** ------------------------------------------------------------------------------------------\n * * ***Utility: `formatDateIntl`.***\n * -------------------------------------------------------------------------------------------\n * **Formats a date using the `Intl.DateTimeFormat` API.**\n *\n * ---\n * - **Features:**\n *      - Supports custom locales (type-safe `SupportedLocales`).\n *      - Accepts additional `Intl.DateTimeFormatOptions` like `timeZone`, `hour12`, etc.\n *      - Defaults to `\"en-US\"` if `locale` is not provided or is an empty string.\n *      - Returns `null` if the date is invalid, not provided, or options are invalid.\n *\n * ---\n * @param {string | Date | null | undefined} date\n *  ***The date to format.***\n *      - Can be a `Date` object or an ISO string.\n *      - If invalid or not provided, returns `null`.\n *\n * @param {FormatDateIntlOptions} [options] ***Optional formatting options for `Intl.DateTimeFormat`, use `locale` to specify the language & region format.***\n *\n * ---\n * @returns {string | null}\n *   - Formatted date string.\n *   - Returns `null` if date is invalid or options are of wrong type.\n *\n * ---\n * @example\n * formatDateIntl(new Date());\n * // ➔ \"7/14/2025\"\n * formatDateIntl(\"2025-07-14T00:00:00Z\", { locale: \"fr-FR\", dateStyle: \"long\" });\n * // ➔ \"14 juillet 2025\"\n * formatDateIntl(null);\n * // ➔ null\n * formatDateIntl(new Date(), { timeZone: \"UTC\", hour: \"2-digit\", minute: \"2-digit\" });\n * // ➔ \"01:30 AM\"\n */\nexport const formatDateIntl = (\n  date: string | Date | null | undefined,\n  options?: FormatDateIntlOptions\n): string | null => {\n  if (isNil(date) || !(isDate(date) || isNonEmptyString(date))) return null;\n\n  const parsedDate = new Date(date);\n  if (isNaN(parsedDate.getTime())) return null; // Handle invalid dates\n\n  // Ensure options is an object and Defensive options check\n  if (!isPlainObject(options)) options = {};\n\n  const { locale = \"en-US\", ...restProps } = options;\n\n  try {\n    return new Intl.DateTimeFormat(\n      isNonEmptyString(locale) ? locale.trim() : \"en-US\",\n      restProps\n    ).format(parsedDate);\n  } catch {\n    return null;\n  }\n};\n","import { isNaN } from \"@/predicates/is/isNaN\";\nimport { isNil } from \"@/predicates/is/isNil\";\nimport { isDate } from \"@/predicates/is/isDate\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\n/** -----------------------------------------------------------------------------------\n * * ***Utility: `formatDateTime`.***\n * ------------------------------------------------------------------------------------\n * **Formats a date and time into a custom string format.**\n *\n * ---\n *  - **Features:**\n *      - Supports only `YYYY`, `MM`, `DD`, `hh`, `mm`, and `ss` as placeholders.\n *      - Uses a simple string replace (no locale).\n *      - Returns `null` if the date is invalid or not provided.\n *      - Defaults to `\"YYYY-MM-DD hh:mm:ss\"` format if none is specified.\n *\n * ---\n * @param {string | Date | null| undefined} date - The date to format.\n * @param {string} [format=\"YYYY-MM-DD hh:mm:ss\"] - The desired date format, if format is `null` or `undefined` will force to defaultValue, defaultValue is: `\"YYYY-MM-DD hh:mm:ss\"`.\n *\n * ---\n * @returns {string | null} The formatted date string or `null` if invalid.\n *\n * ---\n * @example\n * formatDateTime(new Date());\n * // ➔ \"2024-02-09 14:30:45\" (example output with current time)\n * formatDateTime(\"2023-07-01T14:30:45\");\n * // ➔ \"2023-07-01 14:30:45\"\n * formatDateTime(\"2023-07-01T14:30:45\", \"DD/MM/YYYY\");\n * // ➔ \"01/07/2023\"\n * formatDateTime(\"2023-07-01T14:30:45\", \"YYYY/MM/DD hh-mm-ss\");\n * // ➔ \"2023/07/01 14-30-45\"\n * formatDateTime(\"2023-07-01T14:30:45\", \"hh:mm\");\n * // ➔ \"14:30\"\n * formatDateTime(\"2023-07-01T14:30:45\", \"DATE: YYYY.MM.DD\");\n * // ➔ \"DATE: 2023.07.01\"\n * formatDateTime(\"2023-07-01T14:30:45\", \"Year: YYYY, Time: hh:mm:ss\");\n * // ➔ \"Year: 2023, Time: 14:30:45\"\n * formatDateTime(\"2023-07-01T14:30:45\", \"YYYY-MM\");\n * // ➔ \"2023-07\"\n * formatDateTime(\"2023-07-01T14:30:45\", \"YYYYYYYY\");\n * // ➔ \"20232023\"\n * formatDateTime(\"2023-07-01T14:30:45\", \"hh:mm:ss:ss\");\n * // ➔ \"14:30:45:45\"\n * formatDateTime(\"invalid-date\");\n * // ➔ null\n * formatDateTime(null);\n * // ➔ null\n * formatDateTime(undefined);\n * // ➔ null\n */\nexport const formatDateTime = (\n  date: string | Date | null | undefined,\n  format: string = \"YYYY-MM-DD hh:mm:ss\"\n): string | null => {\n  if (isNil(format)) {\n    format = \"YYYY-MM-DD hh:mm:ss\";\n  }\n\n  if (!isString(format)) return null;\n\n  // Handle missing or invalid date input type\n  if (isNil(date) || !(isDate(date) || isNonEmptyString(date))) return null;\n\n  try {\n    const parsedDate = new Date(date);\n    if (isNaN(parsedDate.getTime())) return null; // Handle invalid dates\n\n    const pad2 = (n: number) => n.toString().padStart(2, \"0\");\n\n    const map: Record<string, string> = {\n      YYYY: parsedDate.getFullYear().toString(),\n      MM: pad2(parsedDate.getMonth() + 1),\n      DD: pad2(parsedDate.getDate()),\n      hh: pad2(parsedDate.getHours()),\n      mm: pad2(parsedDate.getMinutes()),\n      ss: pad2(parsedDate.getSeconds())\n    };\n\n    const result = Object.entries(map).reduce(\n      (prev, [key, value]) => prev.split(key).join(value),\n      format\n    );\n\n    return !result.includes(\"NaN\") ? result : null;\n  } catch {\n    return null;\n  }\n};\n","import { isNil } from \"@/predicates/is/isNil\";\nimport { isNaN } from \"@/predicates/is/isNaN\";\nimport { isDate } from \"@/predicates/is/isDate\";\nimport { isString } from \"@/predicates/is/isString\";\nimport { isEmptyString } from \"@/predicates/is/isEmptyString\";\nimport { isNonEmptyString } from \"@/predicates/is/isNonEmptyString\";\n\n/** ----------------------------------------------------------------------------------------------\n * * ***Utility: `getGMTOffset`.***\n * -----------------------------------------------------------------------------------------------\n * **Returns the formatted GMT offset (e.g., `+0700`, `-0500`) for a given date.**\n *\n * ---\n *  - **Features:**\n *      - If `date` is **not provided** or empty string, it defaults to the current date/time.\n *      - If `date` is **invalid** or of wrong type (like object or number), it returns `\"0\"`.\n *      - The returned string follows the **GMT offset format** (`±HHMM`), where:\n *        - `±` is `+` if ahead of UTC, `-` if behind.\n *        - `HH` is two-digit hours.\n *        - `MM` is two-digit minutes.\n *\n * ---\n * @param {string | Date | null} [date]\n *  ***The date to get the GMT offset from.***\n *     - Accepts `Date` object or ISO date string (e.g., `\"2024-01-01T12:00:00Z\"`).\n *     - If `null`, `undefined`, or empty string, uses current system date.\n *     - If invalid date or wrong type (like `123` or `{}`), returns `\"0\"`.\n *\n * ---\n * @returns {string} The GMT offset string in format `±HHMM`,\n *   e.g. `\"+0700\"`, `\"-0530\"`, or `\"0\"` if invalid.\n *\n * ---\n * @example\n * getGMTOffset();\n * // ➔ \"+0700\" (depends on your system timezone)\n * getGMTOffset(new Date(\"2024-02-09T12:00:00Z\"));\n * // ➔ \"+0000\"\n * getGMTOffset(\"2024-02-09\");\n * // ➔ \"+0700\" (depends on your system timezone)\n * getGMTOffset(\"invalid-date\");\n * // ➔ \"0\"\n * getGMTOffset(123);\n * // ➔ \"0\"\n */\nexport const getGMTOffset = (date?: string | Date | null): string => {\n  try {\n    if (isNil(date) || (isString(date) && isEmptyString(date))) {\n      date = new Date(); // Default to current date\n    } else if (!(isDate(date) || isNonEmptyString(date))) {\n      return \"0\"; // Invalid type\n    }\n\n    const parsedDate = new Date(date);\n    if (isNaN(parsedDate.getTime())) return \"0\"; // Handle invalid dates\n\n    const padZero = (num: number) => num.toString().padStart(2, \"0\");\n\n    let offset = parsedDate.getTimezoneOffset();\n    const sign = offset < 0 ? \"+\" : \"-\";\n    offset = Math.abs(offset);\n\n    return `${sign}${padZero(Math.floor(offset / 60))}${padZero(offset % 60)}`;\n  } catch {\n    return \"0\";\n  }\n};\n"],"mappings":"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"}
