/**
 * Ported from
 * `packages/react/src/number-field/utils/parse.ts`. Locale-aware numeric
 * parsing for every numeral system / decimal-group separator / currency /
 * unit combination `Intl.NumberFormat` can produce.
 *
 * Pure helpers — no Solid reactivity. Safe to call in render and event
 * handlers alike.
 */

const FORMATTER_CACHE = new Map();
function getFormatter(locale, options) {
  const key = JSON.stringify({
    locale,
    options
  });
  const cached = FORMATTER_CACHE.get(key);
  if (cached) return cached;
  const formatter = new Intl.NumberFormat(locale, options);
  FORMATTER_CACHE.set(key, formatter);
  return formatter;
}
const HAN_NUMERALS = ["零", "〇", "一", "二", "三", "四", "五", "六", "七", "八", "九"];
const HAN_NUMERAL_TO_DIGIT = {
  零: "0",
  〇: "0",
  一: "1",
  二: "2",
  三: "3",
  四: "4",
  五: "5",
  六: "6",
  七: "7",
  八: "8",
  九: "9"
};
const ARABIC_NUMERALS = ["٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"];
const PERSIAN_NUMERALS = ["۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"];
const FULLWIDTH_NUMERALS = ["０", "１", "２", "３", "４", "５", "６", "７", "８", "９"];
export const PERCENTAGES = ["%", "٪", "％", "﹪"];
export const PERMILLE = ["‰", "؉"];
const UNICODE_MINUS_SIGNS = ["−", "－", "‒", "–", "—", "﹣"];
const UNICODE_PLUS_SIGNS = ["＋", "﹢"];
const FULLWIDTH_DECIMAL = "．";
const FULLWIDTH_GROUP = "，";
const ARABIC_RE = new RegExp(`[${ARABIC_NUMERALS.join("")}]`, "g");
const PERSIAN_RE = new RegExp(`[${PERSIAN_NUMERALS.join("")}]`, "g");
const FULLWIDTH_RE = new RegExp(`[${FULLWIDTH_NUMERALS.join("")}]`, "g");
const HAN_RE = new RegExp(`[${HAN_NUMERALS.join("")}]`, "g");
const PERCENT_RE = new RegExp(`[${PERCENTAGES.join("")}]`);
const PERMILLE_RE = new RegExp(`[${PERMILLE.join("")}]`);
export const ARABIC_DETECT_RE = /[٠١٢٣٤٥٦٧٨٩]/;
export const PERSIAN_DETECT_RE = /[۰۱۲۳۴۵۶۷۸۹]/;
export const HAN_DETECT_RE = /[零〇一二三四五六七八九]/;
export const FULLWIDTH_DETECT_RE = new RegExp(`[${FULLWIDTH_NUMERALS.join("")}]`);
export const BASE_NON_NUMERIC_SYMBOLS = [".", ",", FULLWIDTH_DECIMAL, FULLWIDTH_GROUP, "٫", "٬"];
export const SPACE_SEPARATOR_RE = /\p{Zs}/u;
export const PLUS_SIGNS_WITH_ASCII = ["+", ...UNICODE_PLUS_SIGNS];
export const MINUS_SIGNS_WITH_ASCII = ["-", ...UNICODE_MINUS_SIGNS];
const escapeRegExp = s => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const escapeClassChar = s => s.replace(/[-\\\]^]/g, m => `\\${m}`);
const charClassFrom = chars => `[${chars.map(escapeClassChar).join("")}]`;
const ANY_MINUS_CLASS = charClassFrom(["-", ...UNICODE_MINUS_SIGNS]);
const ANY_PLUS_CLASS = charClassFrom(["+", ...UNICODE_PLUS_SIGNS]);
export const ANY_MINUS_RE = new RegExp(ANY_MINUS_CLASS, "gu");
export const ANY_PLUS_RE = new RegExp(ANY_PLUS_CLASS, "gu");
export const ANY_MINUS_DETECT_RE = new RegExp(ANY_MINUS_CLASS);
export const ANY_PLUS_DETECT_RE = new RegExp(ANY_PLUS_CLASS);
export function getNumberLocaleDetails(locale, options) {
  const parts = getFormatter(locale, options).formatToParts(11111.1);
  const result = {};
  for (const part of parts) {
    result[part.type] = part.value;
  }

  // The formatting options may result in not returning a decimal.
  for (const part of getFormatter(locale).formatToParts(0.1)) {
    if (part.type === "decimal") {
      result[part.type] = part.value;
    }
  }
  return result;
}
export function parseNumber(formattedNumber, locale, options) {
  if (formattedNumber == null) {
    return null;
  }
  let input = String(formattedNumber).replace(/\p{Cf}/gu, "").trim();
  input = input.replace(ANY_MINUS_RE, "-").replace(ANY_PLUS_RE, "+");
  let isNegative = false;
  const trailing = input.match(/([+-])\s*$/);
  if (trailing) {
    if (trailing[1] === "-") {
      isNegative = true;
    }
    input = input.replace(/([+-])\s*$/, "");
  }
  const leading = input.match(/^\s*([+-])/);
  if (leading) {
    if (leading[1] === "-") {
      isNegative = true;
    }
    input = input.replace(/^\s*[+-]/, "");
  }
  let computedLocale = locale;
  if (computedLocale === undefined) {
    if (ARABIC_DETECT_RE.test(input) || PERSIAN_DETECT_RE.test(input)) {
      computedLocale = "ar";
    } else if (HAN_DETECT_RE.test(input)) {
      computedLocale = "zh";
    }
  }
  const {
    group,
    decimal,
    currency
  } = getNumberLocaleDetails(computedLocale, options);
  const unitParts = getFormatter(computedLocale, options).formatToParts(1).filter(p => p.type === "unit").map(p => escapeRegExp(p.value));
  const unitRegex = unitParts.length ? new RegExp(unitParts.join("|"), "g") : null;
  let groupRegex = null;
  if (group) {
    const isSpaceGroup = /\p{Zs}/u.test(group);
    const isApostropheGroup = group === "'" || group === "\u2019";
    if (isSpaceGroup) {
      groupRegex = /\p{Zs}/gu;
    } else if (isApostropheGroup) {
      groupRegex = /['\u2019]/g;
    } else {
      groupRegex = new RegExp(escapeRegExp(group), "g");
    }
  }
  const replacements = [{
    regex: group ? groupRegex : null,
    replacement: ""
  }, {
    regex: decimal ? new RegExp(escapeRegExp(decimal), "g") : null,
    replacement: "."
  }, {
    regex: /．/g,
    replacement: "."
  }, {
    regex: /，/g,
    replacement: ""
  }, {
    regex: /٫/g,
    replacement: "."
  }, {
    regex: /٬/g,
    replacement: ""
  }, {
    regex: currency ? new RegExp(escapeRegExp(currency), "g") : null,
    replacement: ""
  }, {
    regex: unitRegex,
    replacement: ""
  }, {
    regex: ARABIC_RE,
    replacement: ch => String(ARABIC_NUMERALS.indexOf(ch))
  }, {
    regex: PERSIAN_RE,
    replacement: ch => String(PERSIAN_NUMERALS.indexOf(ch))
  }, {
    regex: FULLWIDTH_RE,
    replacement: ch => String(FULLWIDTH_NUMERALS.indexOf(ch))
  }, {
    regex: HAN_RE,
    replacement: ch => HAN_NUMERAL_TO_DIGIT[ch] ?? ch
  }];
  let unformatted = replacements.reduce((acc, {
    regex,
    replacement
  }) => {
    return regex ? acc.replace(regex, replacement) : acc;
  }, input);
  const lastDot = unformatted.lastIndexOf(".");
  if (lastDot !== -1) {
    unformatted = `${unformatted.slice(0, lastDot).replace(/\./g, "")}.${unformatted.slice(lastDot + 1).replace(/\./g, "")}`;
  }
  if (/^[-+]?Infinity$/i.test(input) || /[∞]/.test(input)) {
    return null;
  }
  const parseTarget = (isNegative ? "-" : "") + unformatted;
  let num = Number.parseFloat(parseTarget);
  const style = options?.style;
  const isUnitPercent = style === "unit" && options?.unit === "percent";
  const hasPercentSymbol = PERCENT_RE.test(formattedNumber) || style === "percent";
  const hasPermilleSymbol = PERMILLE_RE.test(formattedNumber);
  if (hasPermilleSymbol) {
    num /= 1000;
  } else if (!isUnitPercent && hasPercentSymbol) {
    num /= 100;
  }
  if (Number.isNaN(num)) {
    return null;
  }
  return num;
}
//# sourceMappingURL=parse.jsx.map
