intl-tel-input 27.3.0 → 28.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/css/intlTelInput-no-assets.css +2 -2
  2. package/dist/css/intlTelInput.css +3 -3
  3. package/dist/js/data.d.ts +1 -4
  4. package/dist/js/data.js +3 -9
  5. package/dist/js/data.min.js +2 -2
  6. package/dist/js/data.mjs +2 -8
  7. package/dist/js/i18n.d.ts +1 -1592
  8. package/dist/js/intlTelInput.d.ts +62 -49
  9. package/dist/js/intlTelInput.js +221 -182
  10. package/dist/js/intlTelInput.min.js +6 -6
  11. package/dist/js/intlTelInput.mjs +219 -180
  12. package/dist/js/intlTelInputWithUtils.js +622 -568
  13. package/dist/js/intlTelInputWithUtils.min.js +6 -6
  14. package/dist/js/intlTelInputWithUtils.mjs +620 -566
  15. package/dist/js/utils.js +56 -55
  16. package/package.json +14 -181
  17. package/CHANGELOG.md +0 -33
  18. package/angular/README.md +0 -13
  19. package/angular/dist/IntlTelInput.d.ts +0 -110
  20. package/angular/dist/IntlTelInput.js +0 -5096
  21. package/angular/dist/IntlTelInputWithUtils.d.ts +0 -3
  22. package/angular/dist/IntlTelInputWithUtils.js +0 -11435
  23. package/react/README.md +0 -13
  24. package/react/dist/IntlTelInput.d.ts +0 -25
  25. package/react/dist/IntlTelInput.js +0 -4788
  26. package/react/dist/IntlTelInputWithUtils.d.ts +0 -4
  27. package/react/dist/IntlTelInputWithUtils.js +0 -11127
  28. package/svelte/README.md +0 -14
  29. package/svelte/src/IntlTelInput.svelte +0 -233
  30. package/svelte/src/IntlTelInput.svelte.d.ts +0 -36
  31. package/svelte/src/IntlTelInputWithUtils.svelte +0 -24
  32. package/vue/README.md +0 -14
  33. package/vue/dist/IntlTelInput-jw1tkqdD.js +0 -2657
  34. package/vue/dist/IntlTelInput.js +0 -5
  35. package/vue/dist/IntlTelInput.vue.d.ts +0 -43
  36. package/vue/dist/IntlTelInputWithUtils.js +0 -49403
  37. package/vue/dist/index.d.ts +0 -4
  38. package/vue/dist/indexWithUtils.d.ts +0 -3
@@ -1,4 +1,4 @@
1
- // src/js/data.ts
1
+ // packages/core/src/js/data.ts
2
2
  var rawCountryData = [
3
3
  [
4
4
  "af",
@@ -1743,20 +1743,14 @@ for (const c of rawCountryData) {
1743
1743
  dialCode: c[1],
1744
1744
  priority: c[2] || 0,
1745
1745
  areaCodes: c[3] || null,
1746
- nationalPrefix: c[4] || null,
1747
- normalisedName: "",
1748
- // populated in the plugin
1749
- initials: "",
1750
- // populated in the plugin
1751
- dialCodePlus: ""
1752
- // populated in the plugin
1746
+ nationalPrefix: c[4] || null
1753
1747
  });
1754
1748
  }
1755
1749
  var iso2Set = new Set(allCountries.map((c) => c.iso2));
1756
1750
  var isIso2 = (val) => iso2Set.has(val);
1757
1751
  var data_default = allCountries;
1758
1752
 
1759
- // src/js/constants.ts
1753
+ // packages/core/src/js/constants.ts
1760
1754
  var EVENTS = {
1761
1755
  OPEN_COUNTRY_DROPDOWN: "open:countrydropdown",
1762
1756
  CLOSE_COUNTRY_DROPDOWN: "close:countrydropdown",
@@ -1802,10 +1796,6 @@ var TIMINGS = {
1802
1796
  HIDDEN_SEARCH_RESET_MS: 1e3,
1803
1797
  NEXT_TICK: 0
1804
1798
  };
1805
- var SENTINELS = {
1806
- UNKNOWN_NUMBER_TYPE: -99,
1807
- UNKNOWN_VALIDATION_ERROR: -99
1808
- };
1809
1799
  var LAYOUT = {
1810
1800
  NARROW_VIEWPORT_WIDTH: 500,
1811
1801
  // keep in sync with .iti__country-list CSS media query
@@ -1847,6 +1837,12 @@ var PLACEHOLDER_MODES = {
1847
1837
  var INITIAL_COUNTRY = {
1848
1838
  AUTO: "auto"
1849
1839
  };
1840
+ var NUMBER_FORMATS = [
1841
+ "E164",
1842
+ "INTERNATIONAL",
1843
+ "NATIONAL",
1844
+ "RFC3966"
1845
+ ];
1850
1846
  var NUMBER_TYPES = [
1851
1847
  "FIXED_LINE",
1852
1848
  "MOBILE",
@@ -1861,11 +1857,21 @@ var NUMBER_TYPES = [
1861
1857
  "VOICEMAIL",
1862
1858
  "UNKNOWN"
1863
1859
  ];
1864
- var NUMBER_TYPE_SET = new Set(NUMBER_TYPES);
1860
+ var VALIDATION_ERRORS = [
1861
+ "IS_POSSIBLE",
1862
+ "INVALID_COUNTRY_CODE",
1863
+ "TOO_SHORT",
1864
+ "TOO_LONG",
1865
+ "IS_POSSIBLE_LOCAL_ONLY",
1866
+ "INVALID_LENGTH"
1867
+ ];
1868
+ var toEnumObject = (arr) => Object.fromEntries(arr.map((v) => [v, v]));
1869
+ var NUMBER_FORMAT = toEnumObject(NUMBER_FORMATS);
1870
+ var NUMBER_TYPE = toEnumObject(NUMBER_TYPES);
1871
+ var VALIDATION_ERROR = toEnumObject(VALIDATION_ERRORS);
1865
1872
  var DATA_KEYS = {
1866
- // e.g. <li data-country-code="us"> for country items in dropdown
1867
- // in the future, the value should be changed to "iso2", but this is a breaking change for another day
1868
- ISO2: "countryCode",
1873
+ // e.g. <li data-iso2="us"> for country items in dropdown
1874
+ ISO2: "iso2",
1869
1875
  DIAL_CODE: "dialCode",
1870
1876
  // e.g. <input data-intl-tel-input-id="0"> on the input element
1871
1877
  INSTANCE_ID: "intlTelInputId"
@@ -1882,7 +1888,7 @@ var ARIA = {
1882
1888
  MODAL: "aria-modal"
1883
1889
  };
1884
1890
 
1885
- // src/js/i18n/en.ts
1891
+ // packages/core/src/js/i18n/en.ts
1886
1892
  var interfaceTranslations = {
1887
1893
  selectedCountryAriaLabel: "Change country for phone number, currently selected ${countryName} (${dialCode})",
1888
1894
  noCountrySelected: "Select country for phone number",
@@ -1902,7 +1908,7 @@ var interfaceTranslations = {
1902
1908
  };
1903
1909
  var en_default = interfaceTranslations;
1904
1910
 
1905
- // src/js/core/options.ts
1911
+ // packages/core/src/js/core/options.ts
1906
1912
  var mediaQuery = (q) => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(q).matches;
1907
1913
  var isNarrowViewport = () => mediaQuery(`(max-width: ${LAYOUT.NARROW_VIEWPORT_WIDTH}px)`);
1908
1914
  var computeDefaultUseFullscreenPopup = () => {
@@ -1917,7 +1923,7 @@ var defaults = {
1917
1923
  //* Whether or not to allow the dropdown.
1918
1924
  allowDropdown: true,
1919
1925
  //* The number type to enforce during validation.
1920
- allowedNumberTypes: ["MOBILE", "FIXED_LINE"],
1926
+ allowedNumberTypes: [NUMBER_TYPE.MOBILE, NUMBER_TYPE.FIXED_LINE],
1921
1927
  //* Whether or not to allow extensions after the main number.
1922
1928
  allowNumberExtensions: false,
1923
1929
  // Allow alphanumeric "phonewords" (e.g. +1 800 FLOWERS) as valid numbers
@@ -1928,6 +1934,8 @@ var defaults = {
1928
1934
  containerClass: "",
1929
1935
  //* Locale for localising country names via Intl.DisplayNames.
1930
1936
  countryNameLocale: "en",
1937
+ //* Override individual country names by iso2 code.
1938
+ countryNameOverrides: {},
1931
1939
  //* The order of the countries in the dropdown. Defaults to alphabetical.
1932
1940
  countryOrder: null,
1933
1941
  //* Add a country search input at the top of the dropdown.
@@ -1961,17 +1969,17 @@ var defaults = {
1961
1969
  //* Display only these countries.
1962
1970
  onlyCountries: null,
1963
1971
  //* Number type to use for placeholders.
1964
- placeholderNumberType: "MOBILE",
1972
+ placeholderNumberType: NUMBER_TYPE.MOBILE,
1965
1973
  //* Add custom classes to the search input element.
1966
1974
  searchInputClass: "",
1967
1975
  //* Display the international dial code next to the selected flag.
1968
- separateDialCode: false,
1976
+ separateDialCode: true,
1969
1977
  //* When strictMode rejects a key (etc), play a short feedback animation
1970
- strictRejectAnimation: false,
1978
+ strictRejectAnimation: true,
1971
1979
  //* Show flags - for both the selected country, and in the country dropdown
1972
1980
  showFlags: true,
1973
1981
  //* Only allow certain chars e.g. a plus followed by numeric digits, and cap at max valid length.
1974
- strictMode: false,
1982
+ strictMode: true,
1975
1983
  //* Use full screen popup instead of dropdown for country list.
1976
1984
  useFullscreenPopup: computeDefaultUseFullscreenPopup()
1977
1985
  };
@@ -2115,6 +2123,13 @@ var validateOptions = (customOptions) => {
2115
2123
  }
2116
2124
  validatedOptions[key] = value;
2117
2125
  break;
2126
+ case "countryNameOverrides":
2127
+ if (value && !isPlainObject(value)) {
2128
+ warnOption("countryNameOverrides", "an object", value);
2129
+ break;
2130
+ }
2131
+ validatedOptions[key] = value;
2132
+ break;
2118
2133
  case "initialCountry": {
2119
2134
  if (typeof value !== "string") {
2120
2135
  warnOption("initialCountry", "a string", value);
@@ -2133,8 +2148,8 @@ var validateOptions = (customOptions) => {
2133
2148
  break;
2134
2149
  }
2135
2150
  case "placeholderNumberType":
2136
- if (typeof value !== "string" || !NUMBER_TYPE_SET.has(value)) {
2137
- const validTypes = Array.from(NUMBER_TYPE_SET).join(", ");
2151
+ if (typeof value !== "string" || !NUMBER_TYPES.includes(value)) {
2152
+ const validTypes = NUMBER_TYPES.join(", ");
2138
2153
  warnOption("placeholderNumberType", `one of ${validTypes}`, value);
2139
2154
  break;
2140
2155
  }
@@ -2152,8 +2167,8 @@ var validateOptions = (customOptions) => {
2152
2167
  }
2153
2168
  let allValid = true;
2154
2169
  for (const v of value) {
2155
- if (typeof v !== "string" || !NUMBER_TYPE_SET.has(v)) {
2156
- const validTypes = Array.from(NUMBER_TYPE_SET).join(", ");
2170
+ if (typeof v !== "string" || !NUMBER_TYPES.includes(v)) {
2171
+ const validTypes = NUMBER_TYPES.join(", ");
2157
2172
  warnOption(
2158
2173
  "allowedNumberTypes",
2159
2174
  `an array of valid number types (${validTypes})`,
@@ -2215,11 +2230,11 @@ var applyOptionSideEffects = (o) => {
2215
2230
  o.i18n = { ...en_default, ...o.i18n };
2216
2231
  };
2217
2232
 
2218
- // src/js/helpers/string.ts
2233
+ // packages/core/src/js/helpers/string.ts
2219
2234
  var getNumeric = (s) => s.replace(/\D/g, "");
2220
2235
  var normaliseString = (s = "") => s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
2221
2236
 
2222
- // src/js/helpers/dom.ts
2237
+ // packages/core/src/js/helpers/dom.ts
2223
2238
  var buildClassNames = (flags) => Object.keys(flags).filter((k) => Boolean(flags[k])).join(" ");
2224
2239
  var createEl = (tagName, attrs, container) => {
2225
2240
  const el = document.createElement(tagName);
@@ -2234,7 +2249,7 @@ var createEl = (tagName, attrs, container) => {
2234
2249
  return el;
2235
2250
  };
2236
2251
 
2237
- // src/js/core/icons.ts
2252
+ // packages/core/src/js/core/icons.ts
2238
2253
  var buildSearchIcon = () => `
2239
2254
  <svg class="iti__search-icon-svg" width="14" height="14" viewBox="0 0 24 24" focusable="false" ${ARIA.HIDDEN}="true">
2240
2255
  <circle cx="11" cy="11" r="7" />
@@ -2261,8 +2276,21 @@ var buildGlobeIcon = () => `
2261
2276
  <path d="m261 428-2-2-22-21a40 40 0 0 0-32-11h-1a37 37 0 0 0-18 8l-1 1-4 2-2 2-5 4c-9-3-36-31-47-44s-32-45-34-55l3-2a151 151 0 0 0 11-9v-1a39 39 0 0 0 5-48l-3-3-11-19-3-4-5-7h-1l-3-3-4-3-5-2a35 35 0 0 0-16-3h-5c-4 1-14 5-24 11l-4 2-4 3-4 2c-9 8-17 17-18 27a380 380 0 0 0 212 259h3c12 0 25-10 36-21l10-12 6-11a39 39 0 0 0-8-40"/>
2262
2277
  </svg>`;
2263
2278
 
2264
- // src/js/core/countrySearch.ts
2265
- var getMatchedCountries = (countries, query) => {
2279
+ // packages/core/src/js/core/countrySearch.ts
2280
+ var buildSearchTokens = (countries) => {
2281
+ const tokens = /* @__PURE__ */ new Map();
2282
+ for (const c of countries) {
2283
+ const normalisedName = normaliseString(c.name);
2284
+ const initials = normalisedName.split(/[^a-z]/).map((word) => word[0]).join("");
2285
+ tokens.set(c.iso2, {
2286
+ normalisedName,
2287
+ initials,
2288
+ dialCodePlus: `+${c.dialCode}`
2289
+ });
2290
+ }
2291
+ return tokens;
2292
+ };
2293
+ var getMatchedCountries = (countries, searchTokens, query) => {
2266
2294
  const normalisedQuery = normaliseString(query);
2267
2295
  const iso2Matches = [];
2268
2296
  const nameStartsWith = [];
@@ -2271,17 +2299,18 @@ var getMatchedCountries = (countries, query) => {
2271
2299
  const dialCodeContains = [];
2272
2300
  const initialsMatches = [];
2273
2301
  for (const c of countries) {
2302
+ const t = searchTokens.get(c.iso2);
2274
2303
  if (c.iso2 === normalisedQuery) {
2275
2304
  iso2Matches.push(c);
2276
- } else if (c.normalisedName.startsWith(normalisedQuery)) {
2305
+ } else if (t.normalisedName.startsWith(normalisedQuery)) {
2277
2306
  nameStartsWith.push(c);
2278
- } else if (c.normalisedName.includes(normalisedQuery)) {
2307
+ } else if (t.normalisedName.includes(normalisedQuery)) {
2279
2308
  nameContains.push(c);
2280
- } else if (normalisedQuery === c.dialCode || normalisedQuery === c.dialCodePlus) {
2309
+ } else if (normalisedQuery === c.dialCode || normalisedQuery === t.dialCodePlus) {
2281
2310
  dialCodeMatches.push(c);
2282
- } else if (c.dialCodePlus.includes(normalisedQuery)) {
2311
+ } else if (t.dialCodePlus.includes(normalisedQuery)) {
2283
2312
  dialCodeContains.push(c);
2284
- } else if (c.initials.includes(normalisedQuery)) {
2313
+ } else if (t.initials.includes(normalisedQuery)) {
2285
2314
  initialsMatches.push(c);
2286
2315
  }
2287
2316
  }
@@ -2296,17 +2325,76 @@ var getMatchedCountries = (countries, query) => {
2296
2325
  ...initialsMatches
2297
2326
  ];
2298
2327
  };
2299
- var findFirstCountryStartingWith = (countries, query) => {
2328
+ var findFirstCountryStartingWith = (countries, searchTokens, query) => {
2300
2329
  const normalisedQuery = normaliseString(query);
2301
2330
  for (const c of countries) {
2302
- if (c.normalisedName.startsWith(normalisedQuery)) {
2331
+ const { normalisedName } = searchTokens.get(c.iso2);
2332
+ if (normalisedName.startsWith(normalisedQuery)) {
2303
2333
  return c;
2304
2334
  }
2305
2335
  }
2306
2336
  return null;
2307
2337
  };
2308
2338
 
2309
- // src/js/core/ui.ts
2339
+ // packages/core/src/js/core/numerals.ts
2340
+ var Numerals = class _Numerals {
2341
+ #userNumeralSet;
2342
+ //* Stateless conversion of any Arabic-Indic / Persian digits to ASCII 0-9.
2343
+ //* Use this when you need to normalise digits without affecting any instance's tracked numeral set (e.g. for the country-search query).
2344
+ static toAscii(str) {
2345
+ if (!str) {
2346
+ return "";
2347
+ }
2348
+ return str.replace(
2349
+ /[٠-٩]/g,
2350
+ (ch) => String.fromCharCode(48 + (ch.charCodeAt(0) - 1632))
2351
+ ).replace(
2352
+ /[۰-۹]/g,
2353
+ (ch) => String.fromCharCode(48 + (ch.charCodeAt(0) - 1776))
2354
+ );
2355
+ }
2356
+ constructor(initialValue) {
2357
+ if (initialValue) {
2358
+ this.#updateNumeralSet(initialValue);
2359
+ }
2360
+ }
2361
+ // If any Arabic-Indic digits, then label it as that set. Same for Persian. Otherwise assume ASCII.
2362
+ #updateNumeralSet(str) {
2363
+ if (/[٠-٩]/.test(str)) {
2364
+ this.#userNumeralSet = "arabic-indic";
2365
+ } else if (/[۰-۹]/.test(str)) {
2366
+ this.#userNumeralSet = "persian";
2367
+ } else {
2368
+ this.#userNumeralSet = "ascii";
2369
+ }
2370
+ }
2371
+ // Denormalise ASCII 0-9 to the user's numeral set. If not yet known, return as-is.
2372
+ // NOTE: normalise is always called before this, so it should be impossible for the numeral set to be unknown at this point.
2373
+ denormalise(str) {
2374
+ if (!this.#userNumeralSet || this.#userNumeralSet === "ascii") {
2375
+ return str;
2376
+ }
2377
+ const base = this.#userNumeralSet === "arabic-indic" ? 1632 : 1776;
2378
+ return str.replace(/[0-9]/g, (d) => String.fromCharCode(base + Number(d)));
2379
+ }
2380
+ // Normalize Eastern Arabic (U+0660-0669) and Persian/Extended Arabic-Indic (U+06F0-06F9) numerals to ASCII 0-9.
2381
+ // Tracks the user's numeral set as a side effect so denormalise can mirror it back.
2382
+ normalise(str) {
2383
+ if (!str) {
2384
+ return "";
2385
+ }
2386
+ this.#updateNumeralSet(str);
2387
+ if (this.#userNumeralSet === "ascii") {
2388
+ return str;
2389
+ }
2390
+ return _Numerals.toAscii(str);
2391
+ }
2392
+ isAscii() {
2393
+ return !this.#userNumeralSet || this.#userNumeralSet === "ascii";
2394
+ }
2395
+ };
2396
+
2397
+ // packages/core/src/js/core/ui.ts
2310
2398
  var UI = class _UI {
2311
2399
  // private
2312
2400
  #options;
@@ -2314,6 +2402,7 @@ var UI = class _UI {
2314
2402
  #isRTL;
2315
2403
  #originalPaddingLeft = "";
2316
2404
  #countries;
2405
+ #searchTokens;
2317
2406
  #searchDebounceTimer = null;
2318
2407
  #inlineDropdownHeight;
2319
2408
  #countryContainerEl;
@@ -2359,8 +2448,9 @@ var UI = class _UI {
2359
2448
  }
2360
2449
  }
2361
2450
  //* Generate all of the markup for the plugin: the selected country overlay, and the dropdown.
2362
- buildMarkup(countries) {
2451
+ buildMarkup(countries, searchTokens) {
2363
2452
  this.#countries = countries;
2453
+ this.#searchTokens = searchTokens;
2364
2454
  this.telInputEl.classList.add("iti__tel-input");
2365
2455
  if (!this.telInputEl.hasAttribute("type")) {
2366
2456
  this.telInputEl.setAttribute("type", "tel");
@@ -2728,7 +2818,12 @@ var UI = class _UI {
2728
2818
  if (query === "") {
2729
2819
  matchedCountries = this.#countries;
2730
2820
  } else {
2731
- matchedCountries = getMatchedCountries(this.#countries, query);
2821
+ const normalisedQuery = Numerals.toAscii(query);
2822
+ matchedCountries = getMatchedCountries(
2823
+ this.#countries,
2824
+ this.#searchTokens,
2825
+ normalisedQuery
2826
+ );
2732
2827
  }
2733
2828
  this.#showFilteredCountries(matchedCountries);
2734
2829
  }
@@ -3023,7 +3118,11 @@ var UI = class _UI {
3023
3118
  }
3024
3119
  //* Hidden search (countrySearch disabled): jump to the first list item whose name starts with the query.
3025
3120
  #searchForCountry(query) {
3026
- const match = findFirstCountryStartingWith(this.#countries, query);
3121
+ const match = findFirstCountryStartingWith(
3122
+ this.#countries,
3123
+ this.#searchTokens,
3124
+ query
3125
+ );
3027
3126
  if (match) {
3028
3127
  const listItem = this.#listItemByIso2.get(match.iso2);
3029
3128
  this.#highlightListItem(listItem);
@@ -3048,7 +3147,7 @@ var UI = class _UI {
3048
3147
  }
3049
3148
  if (iso2 && !this.#selectedListItemEl) {
3050
3149
  const newListItem = this.#countryListEl.querySelector(
3051
- `[data-country-code="${iso2}"]`
3150
+ `[data-iso2="${iso2}"]`
3052
3151
  );
3053
3152
  if (newListItem) {
3054
3153
  newListItem.setAttribute(ARIA.SELECTED, "true");
@@ -3236,7 +3335,7 @@ var UI = class _UI {
3236
3335
  }
3237
3336
  };
3238
3337
 
3239
- // src/js/data/country-data.ts
3338
+ // packages/core/src/js/data/country-data.ts
3240
3339
  var processAllCountries = (options) => {
3241
3340
  const { onlyCountries, excludeCountries } = options;
3242
3341
  if (onlyCountries?.length) {
@@ -3251,7 +3350,7 @@ var processAllCountries = (options) => {
3251
3350
  return [...data_default];
3252
3351
  };
3253
3352
  var generateCountryNames = (countries, options) => {
3254
- const { countryNameLocale, i18n } = options;
3353
+ const { countryNameLocale, countryNameOverrides } = options;
3255
3354
  let displayNames;
3256
3355
  try {
3257
3356
  const hasDisplayNames = typeof Intl !== "undefined" && typeof Intl.DisplayNames === "function";
@@ -3267,7 +3366,7 @@ var generateCountryNames = (countries, options) => {
3267
3366
  displayNames = null;
3268
3367
  }
3269
3368
  for (const c of countries) {
3270
- c.name = i18n[c.iso2] || displayNames?.of(c.iso2.toUpperCase()) || "";
3369
+ c.name = countryNameOverrides[c.iso2] || displayNames?.of(c.iso2.toUpperCase()) || "";
3271
3370
  }
3272
3371
  };
3273
3372
  var processDialCodes = (countries) => {
@@ -3335,15 +3434,8 @@ var sortCountries = (countries, options) => {
3335
3434
  return a.name.localeCompare(b.name);
3336
3435
  });
3337
3436
  };
3338
- var cacheSearchTokens = (countries) => {
3339
- for (const c of countries) {
3340
- c.normalisedName = normaliseString(c.name);
3341
- c.initials = c.normalisedName.split(/[^a-z]/).map((word) => word[0]).join("");
3342
- c.dialCodePlus = `+${c.dialCode}`;
3343
- }
3344
- };
3345
3437
 
3346
- // src/js/data/intl-regionless.ts
3438
+ // packages/core/src/js/data/intl-regionless.ts
3347
3439
  var regionlessDialCodes = /* @__PURE__ */ new Set([
3348
3440
  "800",
3349
3441
  "808",
@@ -3359,7 +3451,7 @@ var hasRegionlessDialCode = (number) => {
3359
3451
  return number.startsWith("+") && regionlessDialCodes.has(dialCode);
3360
3452
  };
3361
3453
 
3362
- // src/js/format/formatting.ts
3454
+ // packages/core/src/js/format/formatting.ts
3363
3455
  var stripSeparateDialCode = (fullNumber, hasValidDialCode, separateDialCode, selectedCountryData) => {
3364
3456
  if (!separateDialCode || !hasValidDialCode) {
3365
3457
  return fullNumber;
@@ -3378,7 +3470,7 @@ var formatNumberAsYouType = (fullNumber, telInputValue, utils, selectedCountryDa
3378
3470
  return result;
3379
3471
  };
3380
3472
 
3381
- // src/js/format/caret.ts
3473
+ // packages/core/src/js/format/caret.ts
3382
3474
  var computeNewCaretPosition = (relevantChars, formattedValue, prevCaretPos, isDeleteForwards) => {
3383
3475
  if (prevCaretPos === 0 && !isDeleteForwards) {
3384
3476
  return 0;
@@ -3398,7 +3490,7 @@ var computeNewCaretPosition = (relevantChars, formattedValue, prevCaretPos, isDe
3398
3490
  return formattedValue.length;
3399
3491
  };
3400
3492
 
3401
- // src/js/data/nanp-regionless.ts
3493
+ // packages/core/src/js/data/nanp-regionless.ts
3402
3494
  var regionlessNanpAreaCodes = /* @__PURE__ */ new Set([
3403
3495
  "800",
3404
3496
  "822",
@@ -3427,55 +3519,7 @@ var isRegionlessNanp = (number) => {
3427
3519
  return false;
3428
3520
  };
3429
3521
 
3430
- // src/js/core/numerals.ts
3431
- var Numerals = class {
3432
- #userNumeralSet;
3433
- constructor(initialValue) {
3434
- if (initialValue) {
3435
- this.#updateNumeralSet(initialValue);
3436
- }
3437
- }
3438
- // If any Arabic-Indic digits, then label it as that set. Same for Persian. Otherwise assume ASCII.
3439
- #updateNumeralSet(str) {
3440
- if (/[\u0660-\u0669]/.test(str)) {
3441
- this.#userNumeralSet = "arabic-indic";
3442
- } else if (/[\u06F0-\u06F9]/.test(str)) {
3443
- this.#userNumeralSet = "persian";
3444
- } else {
3445
- this.#userNumeralSet = "ascii";
3446
- }
3447
- }
3448
- // Denormalise ASCII 0-9 to the user's numeral set. If not yet known, return as-is.
3449
- // NOTE: normalise is always called before this, so it should be impossible for the numeral set to be unknown at this point.
3450
- denormalise(str) {
3451
- if (!this.#userNumeralSet || this.#userNumeralSet === "ascii") {
3452
- return str;
3453
- }
3454
- const base = this.#userNumeralSet === "arabic-indic" ? 1632 : 1776;
3455
- return str.replace(/[0-9]/g, (d) => String.fromCharCode(base + Number(d)));
3456
- }
3457
- // Normalize Eastern Arabic (U+0660-0669) and Persian/Extended Arabic-Indic (U+06F0-06F9) numerals to ASCII 0-9
3458
- normalise(str) {
3459
- if (!str) {
3460
- return "";
3461
- }
3462
- this.#updateNumeralSet(str);
3463
- if (this.#userNumeralSet === "ascii") {
3464
- return str;
3465
- }
3466
- const base = this.#userNumeralSet === "arabic-indic" ? 1632 : 1776;
3467
- const regex = this.#userNumeralSet === "arabic-indic" ? /[\u0660-\u0669]/g : /[\u06F0-\u06F9]/g;
3468
- return str.replace(
3469
- regex,
3470
- (ch) => String.fromCharCode(48 + (ch.charCodeAt(0) - base))
3471
- );
3472
- }
3473
- isAscii() {
3474
- return !this.#userNumeralSet || this.#userNumeralSet === "ascii";
3475
- }
3476
- };
3477
-
3478
- // src/js/intlTelInput.ts
3522
+ // packages/core/src/js/intlTelInput.ts
3479
3523
  var nextId = 0;
3480
3524
  var ensureUtils = (methodName) => {
3481
3525
  if (!intlTelInput.utils) {
@@ -3509,6 +3553,7 @@ var Iti = class _Iti {
3509
3553
  #dialCodeToIso2Map;
3510
3554
  #dialCodes;
3511
3555
  #countryByIso2;
3556
+ #searchTokens;
3512
3557
  #selectedCountry = null;
3513
3558
  #maxCoreNumberLength = null;
3514
3559
  #fallbackCountryIso2;
@@ -3565,7 +3610,7 @@ var Iti = class _Iti {
3565
3610
  #init() {
3566
3611
  this.#abortController = new AbortController();
3567
3612
  this.#processCountryData();
3568
- this.#ui.buildMarkup(this.#countries);
3613
+ this.#ui.buildMarkup(this.#countries, this.#searchTokens);
3569
3614
  this.#setInitialState();
3570
3615
  this.#initListeners();
3571
3616
  this.#startAsyncLoads();
@@ -3580,7 +3625,7 @@ var Iti = class _Iti {
3580
3625
  #processCountryData() {
3581
3626
  generateCountryNames(this.#countries, this.#options);
3582
3627
  sortCountries(this.#countries, this.#options);
3583
- cacheSearchTokens(this.#countries);
3628
+ this.#searchTokens = buildSearchTokens(this.#countries);
3584
3629
  }
3585
3630
  //* Set the initial state of the input value and the selected country by:
3586
3631
  //* 1. Extracting a dial code from the given number
@@ -3641,7 +3686,7 @@ var Iti = class _Iti {
3641
3686
  if (this.#utilsDeferred) {
3642
3687
  const { loadUtils } = this.#options;
3643
3688
  const doAttachUtils = () => {
3644
- intlTelInput.attachUtils(loadUtils)?.catch(() => {
3689
+ intlTelInput.attachUtils(loadUtils).catch(() => {
3645
3690
  });
3646
3691
  };
3647
3692
  if (intlTelInput.documentReady()) {
@@ -3661,7 +3706,7 @@ var Iti = class _Iti {
3661
3706
  }
3662
3707
  }
3663
3708
  //* Perform the geo ip lookup.
3664
- #loadAutoCountry() {
3709
+ async #loadAutoCountry() {
3665
3710
  if (intlTelInput.autoCountry) {
3666
3711
  this.#handleAutoCountryLoaded();
3667
3712
  return;
@@ -3672,19 +3717,18 @@ var Iti = class _Iti {
3672
3717
  }
3673
3718
  intlTelInput.startedLoadingAutoCountry = true;
3674
3719
  if (typeof this.#options.geoIpLookup === "function") {
3675
- const successCallback = (iso2 = "") => {
3676
- const iso2Lower = iso2.toLowerCase();
3677
- if (isIso2(iso2Lower)) {
3678
- intlTelInput.autoCountry = iso2Lower;
3679
- setTimeout(() => _Iti.forEachInstance("handleAutoCountryLoaded"));
3680
- } else {
3720
+ try {
3721
+ const iso2 = await this.#options.geoIpLookup();
3722
+ const iso2Lower = typeof iso2 === "string" ? iso2.toLowerCase() : "";
3723
+ if (!isIso2(iso2Lower)) {
3681
3724
  _Iti.forEachInstance("handleAutoCountryFailure");
3725
+ return;
3682
3726
  }
3683
- };
3684
- const failureCallback = () => {
3727
+ intlTelInput.autoCountry = iso2Lower;
3728
+ setTimeout(() => _Iti.forEachInstance("handleAutoCountryLoaded"));
3729
+ } catch {
3685
3730
  _Iti.forEachInstance("handleAutoCountryFailure");
3686
- };
3687
- this.#options.geoIpLookup(successCallback, failureCallback);
3731
+ }
3688
3732
  }
3689
3733
  }
3690
3734
  #openDropdownWithPlus() {
@@ -3703,7 +3747,7 @@ var Iti = class _Iti {
3703
3747
  #bindAllTelInputListeners() {
3704
3748
  this.#bindInputListener();
3705
3749
  this.#bindKeydownListener();
3706
- this.#bindPasteListener();
3750
+ this.#bindStrictPasteListener();
3707
3751
  }
3708
3752
  //* Android workaround for handling plus when separateDialCode enabled (as impossible to handle with keydown/keyup, for which e.key always returns "Unidentified", see https://stackoverflow.com/q/59584061/217866)
3709
3753
  #handleAndroidPlusKey(inputValue) {
@@ -3871,15 +3915,16 @@ var Iti = class _Iti {
3871
3915
  e.preventDefault();
3872
3916
  }
3873
3917
  };
3874
- #bindPasteListener() {
3918
+ #bindStrictPasteListener() {
3875
3919
  if (!this.#options.strictMode) {
3876
3920
  return;
3877
3921
  }
3878
- this.#ui.telInputEl.addEventListener("paste", this.#handlePasteEvent, {
3922
+ this.#ui.telInputEl.addEventListener("paste", this.#handleStrictPasteEvent, {
3879
3923
  signal: this.#abortController.signal
3880
3924
  });
3881
3925
  }
3882
- #handlePasteEvent = (e) => {
3926
+ // Handle paste events when strictMode is enabled by sanitising the pasted content before it's inserted into the input, and rejecting it entirely if it would result in an invalid number
3927
+ #handleStrictPasteEvent = (e) => {
3883
3928
  e.preventDefault();
3884
3929
  const input = this.#ui.telInputEl;
3885
3930
  const selStart = input.selectionStart;
@@ -3898,6 +3943,15 @@ var Iti = class _Iti {
3898
3943
  const sanitised = hasLeadingPlus && allowLeadingPlus ? `+${numerics}` : numerics;
3899
3944
  let newValue = before + sanitised + after;
3900
3945
  let rejectReason = sanitised !== pasted ? "invalid" : null;
3946
+ if (newValue.length > 30) {
3947
+ this.#playStrictRejectAnimation();
3948
+ this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3949
+ source: "paste",
3950
+ rejectedInput: pastedRaw,
3951
+ reason: "max-length"
3952
+ });
3953
+ return;
3954
+ }
3901
3955
  if (newValue.length > 5 && intlTelInput.utils) {
3902
3956
  let coreNumber = intlTelInput.utils.getCoreNumber(newValue, iso2);
3903
3957
  while (coreNumber.length === 0 && newValue.length > 0) {
@@ -3989,8 +4043,7 @@ var Iti = class _Iti {
3989
4043
  if (formatOnDisplay && intlTelInput.utils && this.#selectedCountry) {
3990
4044
  const isRegionless = hasRegionlessDialCode(fullNumber);
3991
4045
  const useNational = nationalMode && !isRegionless || !number.startsWith("+") && !separateDialCode;
3992
- const { NATIONAL, INTERNATIONAL } = intlTelInput.utils.numberFormat;
3993
- const format = useNational ? NATIONAL : INTERNATIONAL;
4046
+ const format = useNational ? NUMBER_FORMAT.NATIONAL : NUMBER_FORMAT.INTERNATIONAL;
3994
4047
  number = intlTelInput.utils.formatNumber(
3995
4048
  number,
3996
4049
  this.#selectedCountry?.iso2,
@@ -4110,11 +4163,10 @@ var Iti = class _Iti {
4110
4163
  this.#maxCoreNumberLength = null;
4111
4164
  return;
4112
4165
  }
4113
- const numberType = intlTelInput.utils.numberType[placeholderNumberType];
4114
4166
  let exampleNumber = intlTelInput.utils.getExampleNumber(
4115
4167
  iso2,
4116
4168
  false,
4117
- numberType,
4169
+ placeholderNumberType,
4118
4170
  true
4119
4171
  );
4120
4172
  let validNumber = exampleNumber;
@@ -4144,11 +4196,10 @@ var Iti = class _Iti {
4144
4196
  if (!intlTelInput.utils || !shouldSetPlaceholder) {
4145
4197
  return;
4146
4198
  }
4147
- const numberType = intlTelInput.utils.numberType[placeholderNumberType];
4148
4199
  let placeholder = this.#selectedCountry ? intlTelInput.utils.getExampleNumber(
4149
4200
  this.#selectedCountry.iso2,
4150
4201
  nationalMode,
4151
- numberType
4202
+ placeholderNumberType
4152
4203
  ) : "";
4153
4204
  placeholder = this.#prepareNumberForInput(placeholder);
4154
4205
  if (typeof customPlaceholder === "function") {
@@ -4258,19 +4309,9 @@ var Iti = class _Iti {
4258
4309
  );
4259
4310
  return this.#truncateToMaxLength(number);
4260
4311
  }
4261
- //* Return only the public-facing subset of the selected country data.
4262
- #getPublicCountryData() {
4263
- const d = this.#selectedCountry;
4264
- if (!d) {
4265
- return null;
4266
- }
4267
- const { iso2, dialCode, name } = d;
4268
- return { iso2, dialCode, name };
4269
- }
4270
4312
  //* Dispatch the 'countrychange' event.
4271
4313
  #dispatchCountryChangeEvent() {
4272
- const countryData = this.#getPublicCountryData();
4273
- this.#dispatchEvent(EVENTS.COUNTRY_CHANGE, countryData);
4314
+ this.#dispatchEvent(EVENTS.COUNTRY_CHANGE, this.#selectedCountry ?? null);
4274
4315
  }
4275
4316
  //**************************
4276
4317
  //* INTERNAL METHODS
@@ -4361,7 +4402,7 @@ var Iti = class _Iti {
4361
4402
  this.#selectedCountry?.iso2
4362
4403
  );
4363
4404
  }
4364
- //* Format the number to the given format.
4405
+ //* Format the number to the given format (defaults to "E164").
4365
4406
  getNumber(format) {
4366
4407
  if (!this.#isActive) {
4367
4408
  return "";
@@ -4376,10 +4417,10 @@ var Iti = class _Iti {
4376
4417
  );
4377
4418
  return this.#numerals.denormalise(formattedNumber);
4378
4419
  }
4379
- //* Get the type of the entered number e.g. landline/mobile.
4420
+ //* Get the type of the entered number e.g. "FIXED_LINE" / "MOBILE", or null if it can't be determined / instance is destroyed.
4380
4421
  getNumberType() {
4381
4422
  if (!this.#isActive) {
4382
- return SENTINELS.UNKNOWN_NUMBER_TYPE;
4423
+ return null;
4383
4424
  }
4384
4425
  ensureUtils("getNumberType");
4385
4426
  return intlTelInput.utils.getNumberType(
@@ -4389,12 +4430,12 @@ var Iti = class _Iti {
4389
4430
  }
4390
4431
  //* Get the country data for the currently selected country.
4391
4432
  getSelectedCountryData() {
4392
- return this.#getPublicCountryData();
4433
+ return this.#selectedCountry ?? null;
4393
4434
  }
4394
- //* Get the validation error.
4435
+ //* Get the validation error e.g. "TOO_SHORT" / "TOO_LONG", or null if it can't be determined / instance is destroyed.
4395
4436
  getValidationError() {
4396
4437
  if (!this.#isActive) {
4397
- return SENTINELS.UNKNOWN_VALIDATION_ERROR;
4438
+ return null;
4398
4439
  }
4399
4440
  ensureUtils("getValidationError");
4400
4441
  const iso2 = this.#selectedCountry?.iso2;
@@ -4543,39 +4584,31 @@ var Iti = class _Iti {
4543
4584
  });
4544
4585
  }
4545
4586
  };
4546
- var attachUtils = (source) => {
4547
- if (!intlTelInput.utils && !intlTelInput.startedLoadingUtils) {
4548
- let loadCall;
4549
- if (typeof source === "function") {
4550
- try {
4551
- loadCall = Promise.resolve(source());
4552
- } catch (error) {
4553
- return Promise.reject(error);
4554
- }
4555
- } else {
4556
- return Promise.reject(
4557
- new TypeError(
4558
- `The argument passed to attachUtils must be a function that returns a promise for the utils module, not ${typeof source}`
4559
- )
4587
+ var attachUtils = async (source) => {
4588
+ if (intlTelInput.utils || intlTelInput.startedLoadingUtils) {
4589
+ return null;
4590
+ }
4591
+ if (typeof source !== "function") {
4592
+ throw new TypeError(
4593
+ `The argument passed to attachUtils must be a function that returns a promise for the utils module, not ${typeof source}`
4594
+ );
4595
+ }
4596
+ intlTelInput.startedLoadingUtils = true;
4597
+ try {
4598
+ const module = await source();
4599
+ const utils = module?.default;
4600
+ if (!utils || typeof utils !== "object") {
4601
+ throw new TypeError(
4602
+ "The loader function passed to attachUtils did not resolve to a module object with utils as its default export."
4560
4603
  );
4561
4604
  }
4562
- intlTelInput.startedLoadingUtils = true;
4563
- return loadCall.then((module) => {
4564
- const utils = module?.default;
4565
- if (!utils || typeof utils !== "object") {
4566
- throw new TypeError(
4567
- "The loader function passed to attachUtils did not resolve to a module object with utils as its default export."
4568
- );
4569
- }
4570
- intlTelInput.utils = utils;
4571
- Iti.forEachInstance("handleUtilsLoaded");
4572
- return true;
4573
- }).catch((error) => {
4574
- Iti.forEachInstance("handleUtilsFailure", error);
4575
- throw error;
4576
- });
4605
+ intlTelInput.utils = utils;
4606
+ Iti.forEachInstance("handleUtilsLoaded");
4607
+ return true;
4608
+ } catch (error) {
4609
+ Iti.forEachInstance("handleUtilsFailure", error);
4610
+ throw error;
4577
4611
  }
4578
- return null;
4579
4612
  };
4580
4613
  var intlTelInput = Object.assign(
4581
4614
  (input, options) => {
@@ -4600,11 +4633,17 @@ var intlTelInput = Object.assign(
4600
4633
  attachUtils,
4601
4634
  startedLoadingUtils: false,
4602
4635
  startedLoadingAutoCountry: false,
4603
- version: "27.3.0"
4636
+ version: "28.0.0",
4637
+ NUMBER_FORMAT,
4638
+ NUMBER_TYPE,
4639
+ VALIDATION_ERROR
4604
4640
  }
4605
4641
  );
4606
4642
  var intlTelInput_default = intlTelInput;
4607
4643
  export {
4608
4644
  Iti,
4645
+ NUMBER_FORMAT,
4646
+ NUMBER_TYPE,
4647
+ VALIDATION_ERROR,
4609
4648
  intlTelInput_default as default
4610
4649
  };