intl-tel-input 27.3.0 → 27.3.1

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.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  See the Github Releases page for changelog: https://github.com/jackocnr/intl-tel-input/releases
2
2
 
3
- Or to view a specific version, e.g. v27.3.0, update the URL accordingly, e.g. https://github.com/jackocnr/intl-tel-input/releases/tag/v27.3.0
3
+ Or to view a specific version, e.g. v27.3.1, update the URL accordingly, e.g. https://github.com/jackocnr/intl-tel-input/releases/tag/v27.3.1
4
4
 
5
5
  ## Breaking changes
6
6
 
@@ -1743,13 +1743,7 @@ 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));
@@ -2262,7 +2256,20 @@ var buildGlobeIcon = () => `
2262
2256
  </svg>`;
2263
2257
 
2264
2258
  // src/js/core/countrySearch.ts
2265
- var getMatchedCountries = (countries, query) => {
2259
+ var buildSearchTokens = (countries) => {
2260
+ const tokens = /* @__PURE__ */ new Map();
2261
+ for (const c of countries) {
2262
+ const normalisedName = normaliseString(c.name);
2263
+ const initials = normalisedName.split(/[^a-z]/).map((word) => word[0]).join("");
2264
+ tokens.set(c.iso2, {
2265
+ normalisedName,
2266
+ initials,
2267
+ dialCodePlus: `+${c.dialCode}`
2268
+ });
2269
+ }
2270
+ return tokens;
2271
+ };
2272
+ var getMatchedCountries = (countries, searchTokens, query) => {
2266
2273
  const normalisedQuery = normaliseString(query);
2267
2274
  const iso2Matches = [];
2268
2275
  const nameStartsWith = [];
@@ -2271,17 +2278,18 @@ var getMatchedCountries = (countries, query) => {
2271
2278
  const dialCodeContains = [];
2272
2279
  const initialsMatches = [];
2273
2280
  for (const c of countries) {
2281
+ const t = searchTokens.get(c.iso2);
2274
2282
  if (c.iso2 === normalisedQuery) {
2275
2283
  iso2Matches.push(c);
2276
- } else if (c.normalisedName.startsWith(normalisedQuery)) {
2284
+ } else if (t.normalisedName.startsWith(normalisedQuery)) {
2277
2285
  nameStartsWith.push(c);
2278
- } else if (c.normalisedName.includes(normalisedQuery)) {
2286
+ } else if (t.normalisedName.includes(normalisedQuery)) {
2279
2287
  nameContains.push(c);
2280
- } else if (normalisedQuery === c.dialCode || normalisedQuery === c.dialCodePlus) {
2288
+ } else if (normalisedQuery === c.dialCode || normalisedQuery === t.dialCodePlus) {
2281
2289
  dialCodeMatches.push(c);
2282
- } else if (c.dialCodePlus.includes(normalisedQuery)) {
2290
+ } else if (t.dialCodePlus.includes(normalisedQuery)) {
2283
2291
  dialCodeContains.push(c);
2284
- } else if (c.initials.includes(normalisedQuery)) {
2292
+ } else if (t.initials.includes(normalisedQuery)) {
2285
2293
  initialsMatches.push(c);
2286
2294
  }
2287
2295
  }
@@ -2296,16 +2304,75 @@ var getMatchedCountries = (countries, query) => {
2296
2304
  ...initialsMatches
2297
2305
  ];
2298
2306
  };
2299
- var findFirstCountryStartingWith = (countries, query) => {
2307
+ var findFirstCountryStartingWith = (countries, searchTokens, query) => {
2300
2308
  const normalisedQuery = normaliseString(query);
2301
2309
  for (const c of countries) {
2302
- if (c.normalisedName.startsWith(normalisedQuery)) {
2310
+ const { normalisedName } = searchTokens.get(c.iso2);
2311
+ if (normalisedName.startsWith(normalisedQuery)) {
2303
2312
  return c;
2304
2313
  }
2305
2314
  }
2306
2315
  return null;
2307
2316
  };
2308
2317
 
2318
+ // src/js/core/numerals.ts
2319
+ var Numerals = class _Numerals {
2320
+ #userNumeralSet;
2321
+ //* Stateless conversion of any Arabic-Indic / Persian digits to ASCII 0-9.
2322
+ //* Use this when you need to normalise digits without affecting any instance's tracked numeral set (e.g. for the country-search query).
2323
+ static toAscii(str) {
2324
+ if (!str) {
2325
+ return "";
2326
+ }
2327
+ return str.replace(
2328
+ /[٠-٩]/g,
2329
+ (ch) => String.fromCharCode(48 + (ch.charCodeAt(0) - 1632))
2330
+ ).replace(
2331
+ /[۰-۹]/g,
2332
+ (ch) => String.fromCharCode(48 + (ch.charCodeAt(0) - 1776))
2333
+ );
2334
+ }
2335
+ constructor(initialValue) {
2336
+ if (initialValue) {
2337
+ this.#updateNumeralSet(initialValue);
2338
+ }
2339
+ }
2340
+ // If any Arabic-Indic digits, then label it as that set. Same for Persian. Otherwise assume ASCII.
2341
+ #updateNumeralSet(str) {
2342
+ if (/[٠-٩]/.test(str)) {
2343
+ this.#userNumeralSet = "arabic-indic";
2344
+ } else if (/[۰-۹]/.test(str)) {
2345
+ this.#userNumeralSet = "persian";
2346
+ } else {
2347
+ this.#userNumeralSet = "ascii";
2348
+ }
2349
+ }
2350
+ // Denormalise ASCII 0-9 to the user's numeral set. If not yet known, return as-is.
2351
+ // NOTE: normalise is always called before this, so it should be impossible for the numeral set to be unknown at this point.
2352
+ denormalise(str) {
2353
+ if (!this.#userNumeralSet || this.#userNumeralSet === "ascii") {
2354
+ return str;
2355
+ }
2356
+ const base = this.#userNumeralSet === "arabic-indic" ? 1632 : 1776;
2357
+ return str.replace(/[0-9]/g, (d) => String.fromCharCode(base + Number(d)));
2358
+ }
2359
+ // Normalize Eastern Arabic (U+0660-0669) and Persian/Extended Arabic-Indic (U+06F0-06F9) numerals to ASCII 0-9.
2360
+ // Tracks the user's numeral set as a side effect so denormalise can mirror it back.
2361
+ normalise(str) {
2362
+ if (!str) {
2363
+ return "";
2364
+ }
2365
+ this.#updateNumeralSet(str);
2366
+ if (this.#userNumeralSet === "ascii") {
2367
+ return str;
2368
+ }
2369
+ return _Numerals.toAscii(str);
2370
+ }
2371
+ isAscii() {
2372
+ return !this.#userNumeralSet || this.#userNumeralSet === "ascii";
2373
+ }
2374
+ };
2375
+
2309
2376
  // src/js/core/ui.ts
2310
2377
  var UI = class _UI {
2311
2378
  // private
@@ -2314,6 +2381,7 @@ var UI = class _UI {
2314
2381
  #isRTL;
2315
2382
  #originalPaddingLeft = "";
2316
2383
  #countries;
2384
+ #searchTokens;
2317
2385
  #searchDebounceTimer = null;
2318
2386
  #inlineDropdownHeight;
2319
2387
  #countryContainerEl;
@@ -2359,8 +2427,9 @@ var UI = class _UI {
2359
2427
  }
2360
2428
  }
2361
2429
  //* Generate all of the markup for the plugin: the selected country overlay, and the dropdown.
2362
- buildMarkup(countries) {
2430
+ buildMarkup(countries, searchTokens) {
2363
2431
  this.#countries = countries;
2432
+ this.#searchTokens = searchTokens;
2364
2433
  this.telInputEl.classList.add("iti__tel-input");
2365
2434
  if (!this.telInputEl.hasAttribute("type")) {
2366
2435
  this.telInputEl.setAttribute("type", "tel");
@@ -2728,7 +2797,12 @@ var UI = class _UI {
2728
2797
  if (query === "") {
2729
2798
  matchedCountries = this.#countries;
2730
2799
  } else {
2731
- matchedCountries = getMatchedCountries(this.#countries, query);
2800
+ const normalisedQuery = Numerals.toAscii(query);
2801
+ matchedCountries = getMatchedCountries(
2802
+ this.#countries,
2803
+ this.#searchTokens,
2804
+ normalisedQuery
2805
+ );
2732
2806
  }
2733
2807
  this.#showFilteredCountries(matchedCountries);
2734
2808
  }
@@ -3023,7 +3097,11 @@ var UI = class _UI {
3023
3097
  }
3024
3098
  //* Hidden search (countrySearch disabled): jump to the first list item whose name starts with the query.
3025
3099
  #searchForCountry(query) {
3026
- const match = findFirstCountryStartingWith(this.#countries, query);
3100
+ const match = findFirstCountryStartingWith(
3101
+ this.#countries,
3102
+ this.#searchTokens,
3103
+ query
3104
+ );
3027
3105
  if (match) {
3028
3106
  const listItem = this.#listItemByIso2.get(match.iso2);
3029
3107
  this.#highlightListItem(listItem);
@@ -3335,13 +3413,6 @@ var sortCountries = (countries, options) => {
3335
3413
  return a.name.localeCompare(b.name);
3336
3414
  });
3337
3415
  };
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
3416
 
3346
3417
  // src/js/data/intl-regionless.ts
3347
3418
  var regionlessDialCodes = /* @__PURE__ */ new Set([
@@ -3427,54 +3498,6 @@ var isRegionlessNanp = (number) => {
3427
3498
  return false;
3428
3499
  };
3429
3500
 
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
3501
  // src/js/intlTelInput.ts
3479
3502
  var nextId = 0;
3480
3503
  var ensureUtils = (methodName) => {
@@ -3509,6 +3532,7 @@ var Iti = class _Iti {
3509
3532
  #dialCodeToIso2Map;
3510
3533
  #dialCodes;
3511
3534
  #countryByIso2;
3535
+ #searchTokens;
3512
3536
  #selectedCountry = null;
3513
3537
  #maxCoreNumberLength = null;
3514
3538
  #fallbackCountryIso2;
@@ -3565,7 +3589,7 @@ var Iti = class _Iti {
3565
3589
  #init() {
3566
3590
  this.#abortController = new AbortController();
3567
3591
  this.#processCountryData();
3568
- this.#ui.buildMarkup(this.#countries);
3592
+ this.#ui.buildMarkup(this.#countries, this.#searchTokens);
3569
3593
  this.#setInitialState();
3570
3594
  this.#initListeners();
3571
3595
  this.#startAsyncLoads();
@@ -3580,7 +3604,7 @@ var Iti = class _Iti {
3580
3604
  #processCountryData() {
3581
3605
  generateCountryNames(this.#countries, this.#options);
3582
3606
  sortCountries(this.#countries, this.#options);
3583
- cacheSearchTokens(this.#countries);
3607
+ this.#searchTokens = buildSearchTokens(this.#countries);
3584
3608
  }
3585
3609
  //* Set the initial state of the input value and the selected country by:
3586
3610
  //* 1. Extracting a dial code from the given number
@@ -3703,7 +3727,7 @@ var Iti = class _Iti {
3703
3727
  #bindAllTelInputListeners() {
3704
3728
  this.#bindInputListener();
3705
3729
  this.#bindKeydownListener();
3706
- this.#bindPasteListener();
3730
+ this.#bindStrictPasteListener();
3707
3731
  }
3708
3732
  //* 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
3733
  #handleAndroidPlusKey(inputValue) {
@@ -3871,15 +3895,16 @@ var Iti = class _Iti {
3871
3895
  e.preventDefault();
3872
3896
  }
3873
3897
  };
3874
- #bindPasteListener() {
3898
+ #bindStrictPasteListener() {
3875
3899
  if (!this.#options.strictMode) {
3876
3900
  return;
3877
3901
  }
3878
- this.#ui.telInputEl.addEventListener("paste", this.#handlePasteEvent, {
3902
+ this.#ui.telInputEl.addEventListener("paste", this.#handleStrictPasteEvent, {
3879
3903
  signal: this.#abortController.signal
3880
3904
  });
3881
3905
  }
3882
- #handlePasteEvent = (e) => {
3906
+ // 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
3907
+ #handleStrictPasteEvent = (e) => {
3883
3908
  e.preventDefault();
3884
3909
  const input = this.#ui.telInputEl;
3885
3910
  const selStart = input.selectionStart;
@@ -3898,6 +3923,15 @@ var Iti = class _Iti {
3898
3923
  const sanitised = hasLeadingPlus && allowLeadingPlus ? `+${numerics}` : numerics;
3899
3924
  let newValue = before + sanitised + after;
3900
3925
  let rejectReason = sanitised !== pasted ? "invalid" : null;
3926
+ if (newValue.length > 30) {
3927
+ this.#playStrictRejectAnimation();
3928
+ this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3929
+ source: "paste",
3930
+ rejectedInput: pastedRaw,
3931
+ reason: "max-length"
3932
+ });
3933
+ return;
3934
+ }
3901
3935
  if (newValue.length > 5 && intlTelInput.utils) {
3902
3936
  let coreNumber = intlTelInput.utils.getCoreNumber(newValue, iso2);
3903
3937
  while (coreNumber.length === 0 && newValue.length > 0) {
@@ -4600,7 +4634,7 @@ var intlTelInput = Object.assign(
4600
4634
  attachUtils,
4601
4635
  startedLoadingUtils: false,
4602
4636
  startedLoadingAutoCountry: false,
4603
- version: "27.3.0"
4637
+ version: "27.3.1"
4604
4638
  }
4605
4639
  );
4606
4640
  var intlTelInput_default = intlTelInput;
@@ -1743,13 +1743,7 @@ 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));
@@ -2262,7 +2256,20 @@ var buildGlobeIcon = () => `
2262
2256
  </svg>`;
2263
2257
 
2264
2258
  // src/js/core/countrySearch.ts
2265
- var getMatchedCountries = (countries, query) => {
2259
+ var buildSearchTokens = (countries) => {
2260
+ const tokens = /* @__PURE__ */ new Map();
2261
+ for (const c of countries) {
2262
+ const normalisedName = normaliseString(c.name);
2263
+ const initials = normalisedName.split(/[^a-z]/).map((word) => word[0]).join("");
2264
+ tokens.set(c.iso2, {
2265
+ normalisedName,
2266
+ initials,
2267
+ dialCodePlus: `+${c.dialCode}`
2268
+ });
2269
+ }
2270
+ return tokens;
2271
+ };
2272
+ var getMatchedCountries = (countries, searchTokens, query) => {
2266
2273
  const normalisedQuery = normaliseString(query);
2267
2274
  const iso2Matches = [];
2268
2275
  const nameStartsWith = [];
@@ -2271,17 +2278,18 @@ var getMatchedCountries = (countries, query) => {
2271
2278
  const dialCodeContains = [];
2272
2279
  const initialsMatches = [];
2273
2280
  for (const c of countries) {
2281
+ const t = searchTokens.get(c.iso2);
2274
2282
  if (c.iso2 === normalisedQuery) {
2275
2283
  iso2Matches.push(c);
2276
- } else if (c.normalisedName.startsWith(normalisedQuery)) {
2284
+ } else if (t.normalisedName.startsWith(normalisedQuery)) {
2277
2285
  nameStartsWith.push(c);
2278
- } else if (c.normalisedName.includes(normalisedQuery)) {
2286
+ } else if (t.normalisedName.includes(normalisedQuery)) {
2279
2287
  nameContains.push(c);
2280
- } else if (normalisedQuery === c.dialCode || normalisedQuery === c.dialCodePlus) {
2288
+ } else if (normalisedQuery === c.dialCode || normalisedQuery === t.dialCodePlus) {
2281
2289
  dialCodeMatches.push(c);
2282
- } else if (c.dialCodePlus.includes(normalisedQuery)) {
2290
+ } else if (t.dialCodePlus.includes(normalisedQuery)) {
2283
2291
  dialCodeContains.push(c);
2284
- } else if (c.initials.includes(normalisedQuery)) {
2292
+ } else if (t.initials.includes(normalisedQuery)) {
2285
2293
  initialsMatches.push(c);
2286
2294
  }
2287
2295
  }
@@ -2296,16 +2304,75 @@ var getMatchedCountries = (countries, query) => {
2296
2304
  ...initialsMatches
2297
2305
  ];
2298
2306
  };
2299
- var findFirstCountryStartingWith = (countries, query) => {
2307
+ var findFirstCountryStartingWith = (countries, searchTokens, query) => {
2300
2308
  const normalisedQuery = normaliseString(query);
2301
2309
  for (const c of countries) {
2302
- if (c.normalisedName.startsWith(normalisedQuery)) {
2310
+ const { normalisedName } = searchTokens.get(c.iso2);
2311
+ if (normalisedName.startsWith(normalisedQuery)) {
2303
2312
  return c;
2304
2313
  }
2305
2314
  }
2306
2315
  return null;
2307
2316
  };
2308
2317
 
2318
+ // src/js/core/numerals.ts
2319
+ var Numerals = class _Numerals {
2320
+ #userNumeralSet;
2321
+ //* Stateless conversion of any Arabic-Indic / Persian digits to ASCII 0-9.
2322
+ //* Use this when you need to normalise digits without affecting any instance's tracked numeral set (e.g. for the country-search query).
2323
+ static toAscii(str) {
2324
+ if (!str) {
2325
+ return "";
2326
+ }
2327
+ return str.replace(
2328
+ /[٠-٩]/g,
2329
+ (ch) => String.fromCharCode(48 + (ch.charCodeAt(0) - 1632))
2330
+ ).replace(
2331
+ /[۰-۹]/g,
2332
+ (ch) => String.fromCharCode(48 + (ch.charCodeAt(0) - 1776))
2333
+ );
2334
+ }
2335
+ constructor(initialValue) {
2336
+ if (initialValue) {
2337
+ this.#updateNumeralSet(initialValue);
2338
+ }
2339
+ }
2340
+ // If any Arabic-Indic digits, then label it as that set. Same for Persian. Otherwise assume ASCII.
2341
+ #updateNumeralSet(str) {
2342
+ if (/[٠-٩]/.test(str)) {
2343
+ this.#userNumeralSet = "arabic-indic";
2344
+ } else if (/[۰-۹]/.test(str)) {
2345
+ this.#userNumeralSet = "persian";
2346
+ } else {
2347
+ this.#userNumeralSet = "ascii";
2348
+ }
2349
+ }
2350
+ // Denormalise ASCII 0-9 to the user's numeral set. If not yet known, return as-is.
2351
+ // NOTE: normalise is always called before this, so it should be impossible for the numeral set to be unknown at this point.
2352
+ denormalise(str) {
2353
+ if (!this.#userNumeralSet || this.#userNumeralSet === "ascii") {
2354
+ return str;
2355
+ }
2356
+ const base = this.#userNumeralSet === "arabic-indic" ? 1632 : 1776;
2357
+ return str.replace(/[0-9]/g, (d) => String.fromCharCode(base + Number(d)));
2358
+ }
2359
+ // Normalize Eastern Arabic (U+0660-0669) and Persian/Extended Arabic-Indic (U+06F0-06F9) numerals to ASCII 0-9.
2360
+ // Tracks the user's numeral set as a side effect so denormalise can mirror it back.
2361
+ normalise(str) {
2362
+ if (!str) {
2363
+ return "";
2364
+ }
2365
+ this.#updateNumeralSet(str);
2366
+ if (this.#userNumeralSet === "ascii") {
2367
+ return str;
2368
+ }
2369
+ return _Numerals.toAscii(str);
2370
+ }
2371
+ isAscii() {
2372
+ return !this.#userNumeralSet || this.#userNumeralSet === "ascii";
2373
+ }
2374
+ };
2375
+
2309
2376
  // src/js/core/ui.ts
2310
2377
  var UI = class _UI {
2311
2378
  // private
@@ -2314,6 +2381,7 @@ var UI = class _UI {
2314
2381
  #isRTL;
2315
2382
  #originalPaddingLeft = "";
2316
2383
  #countries;
2384
+ #searchTokens;
2317
2385
  #searchDebounceTimer = null;
2318
2386
  #inlineDropdownHeight;
2319
2387
  #countryContainerEl;
@@ -2359,8 +2427,9 @@ var UI = class _UI {
2359
2427
  }
2360
2428
  }
2361
2429
  //* Generate all of the markup for the plugin: the selected country overlay, and the dropdown.
2362
- buildMarkup(countries) {
2430
+ buildMarkup(countries, searchTokens) {
2363
2431
  this.#countries = countries;
2432
+ this.#searchTokens = searchTokens;
2364
2433
  this.telInputEl.classList.add("iti__tel-input");
2365
2434
  if (!this.telInputEl.hasAttribute("type")) {
2366
2435
  this.telInputEl.setAttribute("type", "tel");
@@ -2728,7 +2797,12 @@ var UI = class _UI {
2728
2797
  if (query === "") {
2729
2798
  matchedCountries = this.#countries;
2730
2799
  } else {
2731
- matchedCountries = getMatchedCountries(this.#countries, query);
2800
+ const normalisedQuery = Numerals.toAscii(query);
2801
+ matchedCountries = getMatchedCountries(
2802
+ this.#countries,
2803
+ this.#searchTokens,
2804
+ normalisedQuery
2805
+ );
2732
2806
  }
2733
2807
  this.#showFilteredCountries(matchedCountries);
2734
2808
  }
@@ -3023,7 +3097,11 @@ var UI = class _UI {
3023
3097
  }
3024
3098
  //* Hidden search (countrySearch disabled): jump to the first list item whose name starts with the query.
3025
3099
  #searchForCountry(query) {
3026
- const match = findFirstCountryStartingWith(this.#countries, query);
3100
+ const match = findFirstCountryStartingWith(
3101
+ this.#countries,
3102
+ this.#searchTokens,
3103
+ query
3104
+ );
3027
3105
  if (match) {
3028
3106
  const listItem = this.#listItemByIso2.get(match.iso2);
3029
3107
  this.#highlightListItem(listItem);
@@ -3335,13 +3413,6 @@ var sortCountries = (countries, options) => {
3335
3413
  return a.name.localeCompare(b.name);
3336
3414
  });
3337
3415
  };
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
3416
 
3346
3417
  // src/js/data/intl-regionless.ts
3347
3418
  var regionlessDialCodes = /* @__PURE__ */ new Set([
@@ -3427,54 +3498,6 @@ var isRegionlessNanp = (number) => {
3427
3498
  return false;
3428
3499
  };
3429
3500
 
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
3501
  // src/js/intlTelInput.ts
3479
3502
  var nextId = 0;
3480
3503
  var ensureUtils = (methodName) => {
@@ -3509,6 +3532,7 @@ var Iti = class _Iti {
3509
3532
  #dialCodeToIso2Map;
3510
3533
  #dialCodes;
3511
3534
  #countryByIso2;
3535
+ #searchTokens;
3512
3536
  #selectedCountry = null;
3513
3537
  #maxCoreNumberLength = null;
3514
3538
  #fallbackCountryIso2;
@@ -3565,7 +3589,7 @@ var Iti = class _Iti {
3565
3589
  #init() {
3566
3590
  this.#abortController = new AbortController();
3567
3591
  this.#processCountryData();
3568
- this.#ui.buildMarkup(this.#countries);
3592
+ this.#ui.buildMarkup(this.#countries, this.#searchTokens);
3569
3593
  this.#setInitialState();
3570
3594
  this.#initListeners();
3571
3595
  this.#startAsyncLoads();
@@ -3580,7 +3604,7 @@ var Iti = class _Iti {
3580
3604
  #processCountryData() {
3581
3605
  generateCountryNames(this.#countries, this.#options);
3582
3606
  sortCountries(this.#countries, this.#options);
3583
- cacheSearchTokens(this.#countries);
3607
+ this.#searchTokens = buildSearchTokens(this.#countries);
3584
3608
  }
3585
3609
  //* Set the initial state of the input value and the selected country by:
3586
3610
  //* 1. Extracting a dial code from the given number
@@ -3703,7 +3727,7 @@ var Iti = class _Iti {
3703
3727
  #bindAllTelInputListeners() {
3704
3728
  this.#bindInputListener();
3705
3729
  this.#bindKeydownListener();
3706
- this.#bindPasteListener();
3730
+ this.#bindStrictPasteListener();
3707
3731
  }
3708
3732
  //* 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
3733
  #handleAndroidPlusKey(inputValue) {
@@ -3871,15 +3895,16 @@ var Iti = class _Iti {
3871
3895
  e.preventDefault();
3872
3896
  }
3873
3897
  };
3874
- #bindPasteListener() {
3898
+ #bindStrictPasteListener() {
3875
3899
  if (!this.#options.strictMode) {
3876
3900
  return;
3877
3901
  }
3878
- this.#ui.telInputEl.addEventListener("paste", this.#handlePasteEvent, {
3902
+ this.#ui.telInputEl.addEventListener("paste", this.#handleStrictPasteEvent, {
3879
3903
  signal: this.#abortController.signal
3880
3904
  });
3881
3905
  }
3882
- #handlePasteEvent = (e) => {
3906
+ // 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
3907
+ #handleStrictPasteEvent = (e) => {
3883
3908
  e.preventDefault();
3884
3909
  const input = this.#ui.telInputEl;
3885
3910
  const selStart = input.selectionStart;
@@ -3898,6 +3923,15 @@ var Iti = class _Iti {
3898
3923
  const sanitised = hasLeadingPlus && allowLeadingPlus ? `+${numerics}` : numerics;
3899
3924
  let newValue = before + sanitised + after;
3900
3925
  let rejectReason = sanitised !== pasted ? "invalid" : null;
3926
+ if (newValue.length > 30) {
3927
+ this.#playStrictRejectAnimation();
3928
+ this.#dispatchEvent(EVENTS.STRICT_REJECT, {
3929
+ source: "paste",
3930
+ rejectedInput: pastedRaw,
3931
+ reason: "max-length"
3932
+ });
3933
+ return;
3934
+ }
3901
3935
  if (newValue.length > 5 && intlTelInput.utils) {
3902
3936
  let coreNumber = intlTelInput.utils.getCoreNumber(newValue, iso2);
3903
3937
  while (coreNumber.length === 0 && newValue.length > 0) {
@@ -4600,7 +4634,7 @@ var intlTelInput = Object.assign(
4600
4634
  attachUtils,
4601
4635
  startedLoadingUtils: false,
4602
4636
  startedLoadingAutoCountry: false,
4603
- version: "27.3.0"
4637
+ version: "27.3.1"
4604
4638
  }
4605
4639
  );
4606
4640
  var intlTelInput_default = intlTelInput;
package/dist/js/data.d.ts CHANGED
@@ -1592,15 +1592,12 @@ export declare const rawCountryData: readonly [
1592
1592
  ];
1593
1593
  export type Iso2 = (typeof rawCountryData)[number][0];
1594
1594
  export type Country = {
1595
+ name: string;
1595
1596
  iso2: Iso2;
1596
1597
  dialCode: string;
1597
1598
  priority: number;
1598
1599
  areaCodes: readonly string[] | null;
1599
1600
  nationalPrefix: string | null;
1600
- name: string;
1601
- normalisedName: string;
1602
- initials: string;
1603
- dialCodePlus: string;
1604
1601
  };
1605
1602
  declare const allCountries: Country[];
1606
1603
  export declare const iso2Set: Set<Iso2>;