intl-tel-input 25.10.12 → 25.11.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.
@@ -2086,6 +2086,7 @@ var getNumeric = (s) => s.replace(/\D/g, "");
2086
2086
  var normaliseString = (s = "") => s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
2087
2087
 
2088
2088
  // src/js/modules/utils/dom.ts
2089
+ var buildClassNames = (flags) => Object.keys(flags).filter((k) => Boolean(flags[k])).join(" ");
2089
2090
  var createEl = (tagName, attrs, container) => {
2090
2091
  const el = document.createElement(tagName);
2091
2092
  if (attrs) {
@@ -2097,251 +2098,23 @@ var createEl = (tagName, attrs, container) => {
2097
2098
  return el;
2098
2099
  };
2099
2100
 
2100
- // src/js/modules/data/country-data.ts
2101
- function processAllCountries(options) {
2102
- const { onlyCountries, excludeCountries } = options;
2103
- if (onlyCountries.length) {
2104
- const lowerCaseOnlyCountries = onlyCountries.map((country) => country.toLowerCase());
2105
- return data_default.filter((country) => lowerCaseOnlyCountries.includes(country.iso2));
2106
- } else if (excludeCountries.length) {
2107
- const lowerCaseExcludeCountries = excludeCountries.map((country) => country.toLowerCase());
2108
- return data_default.filter((country) => !lowerCaseExcludeCountries.includes(country.iso2));
2109
- }
2110
- return data_default;
2111
- }
2112
- function translateCountryNames(countries, options) {
2113
- for (const c of countries) {
2114
- const iso2 = c.iso2.toLowerCase();
2115
- if (options.i18n[iso2]) {
2116
- c.name = options.i18n[iso2];
2117
- }
2118
- }
2119
- }
2120
- function processDialCodes(countries, options) {
2121
- const dialCodes = /* @__PURE__ */ new Set();
2122
- let dialCodeMaxLen = 0;
2123
- const dialCodeToIso2Map = {};
2124
- const _addToDialCodeMap = (iso2, dialCode, priority) => {
2125
- if (!iso2 || !dialCode) {
2126
- return;
2127
- }
2128
- if (dialCode.length > dialCodeMaxLen) {
2129
- dialCodeMaxLen = dialCode.length;
2130
- }
2131
- if (!dialCodeToIso2Map.hasOwnProperty(dialCode)) {
2132
- dialCodeToIso2Map[dialCode] = [];
2133
- }
2134
- const iso2List = dialCodeToIso2Map[dialCode];
2135
- if (iso2List.includes(iso2)) {
2136
- return;
2137
- }
2138
- const index = priority !== void 0 ? priority : iso2List.length;
2139
- iso2List[index] = iso2;
2140
- };
2141
- for (const c of countries) {
2142
- if (!dialCodes.has(c.dialCode)) {
2143
- dialCodes.add(c.dialCode);
2144
- }
2145
- for (let k = 1; k < c.dialCode.length; k++) {
2146
- const partialDialCode = c.dialCode.substring(0, k);
2147
- _addToDialCodeMap(c.iso2, partialDialCode);
2148
- }
2149
- _addToDialCodeMap(c.iso2, c.dialCode, c.priority);
2150
- }
2151
- if (options.onlyCountries.length || options.excludeCountries.length) {
2152
- dialCodes.forEach((dialCode) => {
2153
- dialCodeToIso2Map[dialCode] = dialCodeToIso2Map[dialCode].filter(Boolean);
2154
- });
2155
- }
2156
- for (const c of countries) {
2157
- if (c.areaCodes) {
2158
- const rootIso2Code = dialCodeToIso2Map[c.dialCode][0];
2159
- for (const areaCode of c.areaCodes) {
2160
- for (let k = 1; k < areaCode.length; k++) {
2161
- const partialAreaCode = areaCode.substring(0, k);
2162
- const partialDialCode = c.dialCode + partialAreaCode;
2163
- _addToDialCodeMap(rootIso2Code, partialDialCode);
2164
- _addToDialCodeMap(c.iso2, partialDialCode);
2165
- }
2166
- _addToDialCodeMap(c.iso2, c.dialCode + areaCode);
2167
- }
2168
- }
2169
- }
2170
- return { dialCodes, dialCodeMaxLen, dialCodeToIso2Map };
2171
- }
2172
- function sortCountries(countries, options) {
2173
- if (options.countryOrder) {
2174
- options.countryOrder = options.countryOrder.map((iso2) => iso2.toLowerCase());
2175
- }
2176
- countries.sort((a, b) => {
2177
- const { countryOrder } = options;
2178
- if (countryOrder) {
2179
- const aIndex = countryOrder.indexOf(a.iso2);
2180
- const bIndex = countryOrder.indexOf(b.iso2);
2181
- const aIndexExists = aIndex > -1;
2182
- const bIndexExists = bIndex > -1;
2183
- if (aIndexExists || bIndexExists) {
2184
- if (aIndexExists && bIndexExists) {
2185
- return aIndex - bIndex;
2186
- }
2187
- return aIndexExists ? -1 : 1;
2188
- }
2189
- }
2190
- return a.name.localeCompare(b.name);
2191
- });
2192
- }
2193
- function cacheSearchTokens(countries) {
2194
- for (const c of countries) {
2195
- c.normalisedName = normaliseString(c.name);
2196
- c.initials = c.name.split(/[^a-zA-ZÀ-ÿа-яА-Я]/).map((word) => word[0]).join("").toLowerCase();
2197
- c.dialCodePlus = `+${c.dialCode}`;
2198
- }
2199
- }
2200
-
2201
- // src/js/modules/format/formatting.ts
2202
- function beforeSetNumber(fullNumber, dialCode, separateDialCode, selectedCountryData) {
2203
- let number = fullNumber;
2204
- if (separateDialCode) {
2205
- if (dialCode) {
2206
- dialCode = `+${selectedCountryData.dialCode}`;
2207
- const start = number[dialCode.length] === " " || number[dialCode.length] === "-" ? dialCode.length + 1 : dialCode.length;
2208
- number = number.substring(start);
2209
- }
2210
- }
2211
- return number;
2212
- }
2213
- function formatNumberAsYouType(fullNumber, telInputValue, utils, selectedCountryData, separateDialCode) {
2214
- const result = utils ? utils.formatNumberAsYouType(fullNumber, selectedCountryData.iso2) : fullNumber;
2215
- const { dialCode } = selectedCountryData;
2216
- if (separateDialCode && telInputValue.charAt(0) !== "+" && result.includes(`+${dialCode}`)) {
2217
- const afterDialCode = result.split(`+${dialCode}`)[1] || "";
2218
- return afterDialCode.trim();
2219
- }
2220
- return result;
2221
- }
2222
-
2223
- // src/js/modules/format/caret.ts
2224
- function translateCursorPosition(relevantChars, formattedValue, prevCaretPos, isDeleteForwards) {
2225
- if (prevCaretPos === 0 && !isDeleteForwards) {
2226
- return 0;
2227
- }
2228
- let relevantCharCount = 0;
2229
- for (let i = 0; i < formattedValue.length; i++) {
2230
- if (/[+0-9]/.test(formattedValue[i])) {
2231
- relevantCharCount++;
2232
- }
2233
- if (relevantCharCount === relevantChars && !isDeleteForwards) {
2234
- return i + 1;
2235
- }
2236
- if (isDeleteForwards && relevantCharCount === relevantChars + 1) {
2237
- return i;
2238
- }
2239
- }
2240
- return formattedValue.length;
2241
- }
2242
-
2243
- // src/js/modules/data/nanp-regionless.ts
2244
- var regionlessNanpNumbers = [
2245
- "800",
2246
- "822",
2247
- "833",
2248
- "844",
2249
- "855",
2250
- "866",
2251
- "877",
2252
- "880",
2253
- "881",
2254
- "882",
2255
- "883",
2256
- "884",
2257
- "885",
2258
- "886",
2259
- "887",
2260
- "888",
2261
- "889"
2262
- ];
2263
- var isRegionlessNanp = (number) => {
2264
- const numeric = getNumeric(number);
2265
- if (numeric.charAt(0) === "1") {
2266
- const areaCode = numeric.substring(1, 4);
2267
- return regionlessNanpNumbers.includes(areaCode);
2268
- }
2269
- return false;
2270
- };
2271
-
2272
- // src/js/intl-tel-input.ts
2273
- for (const c of data_default) {
2274
- c.name = en_default[c.iso2];
2275
- }
2276
- var id = 0;
2277
- var iso2Set = new Set(data_default.map((c) => c.iso2));
2278
- var isIso2 = (val) => iso2Set.has(val);
2279
- var forEachInstance = (method, ...args) => {
2280
- const { instances } = intlTelInput;
2281
- Object.values(instances).forEach((instance) => instance[method](...args));
2282
- };
2283
- var Iti = class _Iti {
2284
- /**
2285
- * Build a space-delimited class string from an object map of className -> truthy/falsey.
2286
- * Only keys with truthy values are included.
2287
- */
2288
- static _buildClassNames(flags) {
2289
- return Object.keys(flags).filter((k) => Boolean(flags[k])).join(" ");
2290
- }
2291
- constructor(input, customOptions = {}) {
2292
- this.id = id++;
2293
- this.telInput = input;
2101
+ // src/js/modules/core/ui.ts
2102
+ var UI = class {
2103
+ constructor(input, options, id2) {
2294
2104
  this.highlightedItem = null;
2295
- this.options = Object.assign({}, defaults, customOptions);
2105
+ input.dataset.intlTelInputId = id2.toString();
2106
+ this.telInput = input;
2107
+ this.options = options;
2108
+ this.id = id2;
2296
2109
  this.hadInitialPlaceholder = Boolean(input.getAttribute("placeholder"));
2297
- }
2298
- _detectEnvironmentAndLayout() {
2299
- this.isAndroid = typeof navigator !== "undefined" ? /Android/i.test(navigator.userAgent) : false;
2300
2110
  this.isRTL = !!this.telInput.closest("[dir=rtl]");
2301
2111
  if (this.options.separateDialCode) {
2302
2112
  this.originalPaddingLeft = this.telInput.style.paddingLeft;
2303
2113
  }
2304
2114
  }
2305
- _createInitPromises() {
2306
- const autoCountryPromise = new Promise((resolve, reject) => {
2307
- this.resolveAutoCountryPromise = resolve;
2308
- this.rejectAutoCountryPromise = reject;
2309
- });
2310
- const utilsScriptPromise = new Promise((resolve, reject) => {
2311
- this.resolveUtilsScriptPromise = resolve;
2312
- this.rejectUtilsScriptPromise = reject;
2313
- });
2314
- this.promise = Promise.all([autoCountryPromise, utilsScriptPromise]);
2315
- }
2316
- //* Can't be private as it's called from intlTelInput convenience wrapper.
2317
- _init() {
2318
- applyOptionSideEffects(this.options);
2319
- this._detectEnvironmentAndLayout();
2320
- this._createInitPromises();
2321
- this.selectedCountryData = {};
2322
- this._processCountryData();
2323
- this._generateMarkup();
2324
- this._setInitialState();
2325
- this._initListeners();
2326
- this._initRequests();
2327
- }
2328
- //********************
2329
- //* PRIVATE METHODS
2330
- //********************
2331
- //* Prepare all of the country data, including onlyCountries, excludeCountries, countryOrder options.
2332
- _processCountryData() {
2333
- this.countries = processAllCountries(this.options);
2334
- const dialRes = processDialCodes(this.countries, this.options);
2335
- this.dialCodes = dialRes.dialCodes;
2336
- this.dialCodeMaxLen = dialRes.dialCodeMaxLen;
2337
- this.dialCodeToIso2Map = dialRes.dialCodeToIso2Map;
2338
- translateCountryNames(this.countries, this.options);
2339
- sortCountries(this.countries, this.options);
2340
- this.countryByIso2 = new Map(this.countries.map((c) => [c.iso2, c]));
2341
- cacheSearchTokens(this.countries);
2342
- }
2343
2115
  //* Generate all of the markup for the plugin: the selected country overlay, and the dropdown.
2344
- _generateMarkup() {
2116
+ generateMarkup(countries) {
2117
+ this.countries = countries;
2345
2118
  this._prepareTelInput();
2346
2119
  const wrapper = this._createWrapperAndInsert();
2347
2120
  this._maybeBuildCountryContainer(wrapper);
@@ -2351,7 +2124,7 @@ var Iti = class _Iti {
2351
2124
  }
2352
2125
  _prepareTelInput() {
2353
2126
  this.telInput.classList.add("iti__tel-input");
2354
- if (!this.telInput.hasAttribute("autocomplete") && !(this.telInput.form && this.telInput.form.hasAttribute("autocomplete"))) {
2127
+ if (!this.telInput.hasAttribute("autocomplete") && !this.telInput.form?.hasAttribute("autocomplete")) {
2355
2128
  this.telInput.setAttribute("autocomplete", "off");
2356
2129
  }
2357
2130
  }
@@ -2362,8 +2135,8 @@ var Iti = class _Iti {
2362
2135
  containerClass,
2363
2136
  useFullscreenPopup
2364
2137
  } = this.options;
2365
- const parentClasses = _Iti._buildClassNames({
2366
- "iti": true,
2138
+ const parentClasses = buildClassNames({
2139
+ iti: true,
2367
2140
  "iti--allow-dropdown": allowDropdown,
2368
2141
  "iti--show-flags": showFlags,
2369
2142
  "iti--inline-dropdown": !useFullscreenPopup,
@@ -2373,15 +2146,11 @@ var Iti = class _Iti {
2373
2146
  if (this.isRTL) {
2374
2147
  wrapper.setAttribute("dir", "ltr");
2375
2148
  }
2376
- this.telInput.parentNode?.insertBefore(wrapper, this.telInput);
2149
+ this.telInput.before(wrapper);
2377
2150
  return wrapper;
2378
2151
  }
2379
2152
  _maybeBuildCountryContainer(wrapper) {
2380
- const {
2381
- allowDropdown,
2382
- separateDialCode,
2383
- showFlags
2384
- } = this.options;
2153
+ const { allowDropdown, separateDialCode, showFlags } = this.options;
2385
2154
  if (allowDropdown || showFlags || separateDialCode) {
2386
2155
  this.countryContainer = createEl(
2387
2156
  "div",
@@ -2474,12 +2243,12 @@ var Iti = class _Iti {
2474
2243
  this.dropdownContent
2475
2244
  );
2476
2245
  this._appendListItems();
2477
- if (countrySearch) {
2478
- this._updateSearchResultsA11yText();
2246
+ if (this.options.countrySearch) {
2247
+ this.updateSearchResultsA11yText();
2479
2248
  }
2480
2249
  if (dropdownContainer) {
2481
- const dropdownClasses = _Iti._buildClassNames({
2482
- "iti": true,
2250
+ const dropdownClasses = buildClassNames({
2251
+ iti: true,
2483
2252
  "iti--container": true,
2484
2253
  "iti--fullscreen-popup": useFullscreenPopup,
2485
2254
  "iti--inline-dropdown": !useFullscreenPopup,
@@ -2525,7 +2294,7 @@ var Iti = class _Iti {
2525
2294
  "aria-label": i18n.searchPlaceholder,
2526
2295
  "aria-controls": `iti-${this.id}__country-listbox`,
2527
2296
  "aria-autocomplete": "list",
2528
- "autocomplete": "off"
2297
+ autocomplete: "off"
2529
2298
  },
2530
2299
  searchWrapper
2531
2300
  );
@@ -2562,80 +2331,478 @@ var Iti = class _Iti {
2562
2331
  },
2563
2332
  this.dropdownContent
2564
2333
  );
2565
- this.searchNoResults.textContent = i18n.zeroSearchResults;
2334
+ this.searchNoResults.textContent = i18n.zeroSearchResults;
2335
+ }
2336
+ _maybeUpdateInputPaddingAndReveal() {
2337
+ if (this.countryContainer) {
2338
+ this.updateInputPadding();
2339
+ this.countryContainer.classList.remove("iti__v-hide");
2340
+ }
2341
+ }
2342
+ _maybeBuildHiddenInputs(wrapper) {
2343
+ const { hiddenInput } = this.options;
2344
+ if (hiddenInput) {
2345
+ const telInputName = this.telInput.getAttribute("name") || "";
2346
+ const names = hiddenInput(telInputName);
2347
+ if (names.phone) {
2348
+ const existingInput = this.telInput.form?.querySelector(
2349
+ `input[name="${names.phone}"]`
2350
+ );
2351
+ if (existingInput) {
2352
+ this.hiddenInput = existingInput;
2353
+ } else {
2354
+ this.hiddenInput = createEl("input", {
2355
+ type: "hidden",
2356
+ name: names.phone
2357
+ });
2358
+ wrapper.appendChild(this.hiddenInput);
2359
+ }
2360
+ }
2361
+ if (names.country) {
2362
+ const existingInput = this.telInput.form?.querySelector(
2363
+ `input[name="${names.country}"]`
2364
+ );
2365
+ if (existingInput) {
2366
+ this.hiddenInputCountry = existingInput;
2367
+ } else {
2368
+ this.hiddenInputCountry = createEl("input", {
2369
+ type: "hidden",
2370
+ name: names.country
2371
+ });
2372
+ wrapper.appendChild(this.hiddenInputCountry);
2373
+ }
2374
+ }
2375
+ }
2376
+ }
2377
+ //* For each country: add a country list item <li> to the countryList <ul> container.
2378
+ _appendListItems() {
2379
+ const frag = document.createDocumentFragment();
2380
+ for (let i = 0; i < this.countries.length; i++) {
2381
+ const c = this.countries[i];
2382
+ const liClass = buildClassNames({
2383
+ iti__country: true,
2384
+ iti__highlight: i === 0
2385
+ });
2386
+ const listItem = createEl("li", {
2387
+ id: `iti-${this.id}__item-${c.iso2}`,
2388
+ class: liClass,
2389
+ tabindex: "-1",
2390
+ role: "option",
2391
+ "aria-selected": "false"
2392
+ });
2393
+ listItem.dataset.dialCode = c.dialCode;
2394
+ listItem.dataset.countryCode = c.iso2;
2395
+ c.nodeById[this.id] = listItem;
2396
+ if (this.options.showFlags) {
2397
+ createEl("div", { class: `iti__flag iti__${c.iso2}` }, listItem);
2398
+ }
2399
+ const nameEl = createEl("span", { class: "iti__country-name" }, listItem);
2400
+ nameEl.textContent = c.name;
2401
+ const dialEl = createEl("span", { class: "iti__dial-code" }, listItem);
2402
+ if (this.isRTL) {
2403
+ dialEl.setAttribute("dir", "ltr");
2404
+ }
2405
+ dialEl.textContent = `+${c.dialCode}`;
2406
+ frag.appendChild(listItem);
2407
+ }
2408
+ this.countryList.appendChild(frag);
2409
+ }
2410
+ //* Update the input padding to make space for the selected country/dial code.
2411
+ updateInputPadding() {
2412
+ if (this.selectedCountry) {
2413
+ const saneDefaultWidth = this.options.separateDialCode ? 78 : 42;
2414
+ const selectedCountryWidth = this.selectedCountry.offsetWidth || this._getHiddenSelectedCountryWidth() || saneDefaultWidth;
2415
+ const inputPadding = selectedCountryWidth + 6;
2416
+ this.telInput.style.paddingLeft = `${inputPadding}px`;
2417
+ }
2418
+ }
2419
+ //* When input is in a hidden container during init, we cannot calculate the selected country width.
2420
+ //* Fix: clone the markup, make it invisible, add it to the end of the DOM, and then measure it's width.
2421
+ //* To get the right styling to apply, all we need is a shallow clone of the container,
2422
+ //* and then to inject a deep clone of the selectedCountry element.
2423
+ _getHiddenSelectedCountryWidth() {
2424
+ if (this.telInput.parentNode) {
2425
+ let body;
2426
+ try {
2427
+ body = window.top.document.body;
2428
+ } catch (e) {
2429
+ body = document.body;
2430
+ }
2431
+ const containerClone = this.telInput.parentNode.cloneNode(
2432
+ false
2433
+ );
2434
+ containerClone.style.visibility = "hidden";
2435
+ body.appendChild(containerClone);
2436
+ const countryContainerClone = this.countryContainer.cloneNode();
2437
+ containerClone.appendChild(countryContainerClone);
2438
+ const selectedCountryClone = this.selectedCountry.cloneNode(
2439
+ true
2440
+ );
2441
+ countryContainerClone.appendChild(selectedCountryClone);
2442
+ const width = selectedCountryClone.offsetWidth;
2443
+ body.removeChild(containerClone);
2444
+ return width;
2445
+ }
2446
+ return 0;
2447
+ }
2448
+ //* Update search results text (for a11y).
2449
+ updateSearchResultsA11yText() {
2450
+ const { i18n } = this.options;
2451
+ const count = this.countryList.childElementCount;
2452
+ let searchText;
2453
+ if (count === 0) {
2454
+ searchText = i18n.zeroSearchResults;
2455
+ } else {
2456
+ if (i18n.searchResultsText) {
2457
+ searchText = i18n.searchResultsText(count);
2458
+ } else if (count === 1) {
2459
+ searchText = i18n.oneSearchResult;
2460
+ } else {
2461
+ searchText = i18n.multipleSearchResults.replace(
2462
+ "${count}",
2463
+ count.toString()
2464
+ );
2465
+ }
2466
+ }
2467
+ this.searchResultsA11yText.textContent = searchText;
2468
+ }
2469
+ //* Check if an element is visible within it's container, else scroll until it is.
2470
+ scrollTo(element) {
2471
+ const container = this.countryList;
2472
+ const scrollTop = document.documentElement.scrollTop;
2473
+ const containerHeight = container.offsetHeight;
2474
+ const containerTop = container.getBoundingClientRect().top + scrollTop;
2475
+ const containerBottom = containerTop + containerHeight;
2476
+ const elementHeight = element.offsetHeight;
2477
+ const elementTop = element.getBoundingClientRect().top + scrollTop;
2478
+ const elementBottom = elementTop + elementHeight;
2479
+ const newScrollTop = elementTop - containerTop + container.scrollTop;
2480
+ if (elementTop < containerTop) {
2481
+ container.scrollTop = newScrollTop;
2482
+ } else if (elementBottom > containerBottom) {
2483
+ const heightDifference = containerHeight - elementHeight;
2484
+ container.scrollTop = newScrollTop - heightDifference;
2485
+ }
2486
+ }
2487
+ //* Remove highlighting from other list items and highlight the given item.
2488
+ highlightListItem(listItem, shouldFocus) {
2489
+ const prevItem = this.highlightedItem;
2490
+ if (prevItem) {
2491
+ prevItem.classList.remove("iti__highlight");
2492
+ prevItem.setAttribute("aria-selected", "false");
2493
+ }
2494
+ this.highlightedItem = listItem;
2495
+ if (this.highlightedItem) {
2496
+ this.highlightedItem.classList.add("iti__highlight");
2497
+ this.highlightedItem.setAttribute("aria-selected", "true");
2498
+ if (this.options.countrySearch) {
2499
+ const activeDescendant = this.highlightedItem.getAttribute("id") || "";
2500
+ this.searchInput.setAttribute(
2501
+ "aria-activedescendant",
2502
+ activeDescendant
2503
+ );
2504
+ }
2505
+ }
2506
+ if (shouldFocus) {
2507
+ this.highlightedItem.focus();
2508
+ }
2509
+ }
2510
+ //* Country search: Filter the country list to the given array of countries.
2511
+ filterCountries(matchedCountries) {
2512
+ this.countryList.innerHTML = "";
2513
+ let noCountriesAddedYet = true;
2514
+ for (const c of matchedCountries) {
2515
+ const listItem = c.nodeById[this.id];
2516
+ if (listItem) {
2517
+ this.countryList.appendChild(listItem);
2518
+ if (noCountriesAddedYet) {
2519
+ this.highlightListItem(listItem, false);
2520
+ noCountriesAddedYet = false;
2521
+ }
2522
+ }
2523
+ }
2524
+ if (noCountriesAddedYet) {
2525
+ this.highlightListItem(null, false);
2526
+ if (this.searchNoResults) {
2527
+ this.searchNoResults.classList.remove("iti__hide");
2528
+ }
2529
+ } else if (this.searchNoResults) {
2530
+ this.searchNoResults.classList.add("iti__hide");
2531
+ }
2532
+ this.countryList.scrollTop = 0;
2533
+ this.updateSearchResultsA11yText();
2534
+ }
2535
+ destroy() {
2536
+ this.telInput.iti = void 0;
2537
+ delete this.telInput.dataset.intlTelInputId;
2538
+ if (this.options.separateDialCode) {
2539
+ this.telInput.style.paddingLeft = this.originalPaddingLeft;
2540
+ }
2541
+ const wrapper = this.telInput.parentNode;
2542
+ wrapper.before(this.telInput);
2543
+ wrapper.remove();
2544
+ this.telInput = null;
2545
+ this.countryContainer = null;
2546
+ this.selectedCountry = null;
2547
+ this.selectedCountryInner = null;
2548
+ this.selectedDialCode = null;
2549
+ this.dropdownArrow = null;
2550
+ this.dropdownContent = null;
2551
+ this.searchInput = null;
2552
+ this.searchIcon = null;
2553
+ this.searchClearButton = null;
2554
+ this.searchNoResults = null;
2555
+ this.searchResultsA11yText = null;
2556
+ this.countryList = null;
2557
+ this.dropdown = null;
2558
+ this.hiddenInput = null;
2559
+ this.hiddenInputCountry = null;
2560
+ this.highlightedItem = null;
2561
+ for (const c of this.countries) {
2562
+ delete c.nodeById[this.id];
2563
+ }
2564
+ this.countries = null;
2565
+ }
2566
+ };
2567
+
2568
+ // src/js/modules/data/country-data.ts
2569
+ function processAllCountries(options) {
2570
+ const { onlyCountries, excludeCountries } = options;
2571
+ if (onlyCountries.length) {
2572
+ const lowerCaseOnlyCountries = onlyCountries.map((country) => country.toLowerCase());
2573
+ return data_default.filter((country) => lowerCaseOnlyCountries.includes(country.iso2));
2574
+ } else if (excludeCountries.length) {
2575
+ const lowerCaseExcludeCountries = excludeCountries.map((country) => country.toLowerCase());
2576
+ return data_default.filter((country) => !lowerCaseExcludeCountries.includes(country.iso2));
2577
+ }
2578
+ return data_default;
2579
+ }
2580
+ function translateCountryNames(countries, options) {
2581
+ for (const c of countries) {
2582
+ const iso2 = c.iso2.toLowerCase();
2583
+ if (options.i18n[iso2]) {
2584
+ c.name = options.i18n[iso2];
2585
+ }
2586
+ }
2587
+ }
2588
+ function processDialCodes(countries, options) {
2589
+ const dialCodes = /* @__PURE__ */ new Set();
2590
+ let dialCodeMaxLen = 0;
2591
+ const dialCodeToIso2Map = {};
2592
+ const _addToDialCodeMap = (iso2, dialCode, priority) => {
2593
+ if (!iso2 || !dialCode) {
2594
+ return;
2595
+ }
2596
+ if (dialCode.length > dialCodeMaxLen) {
2597
+ dialCodeMaxLen = dialCode.length;
2598
+ }
2599
+ if (!dialCodeToIso2Map.hasOwnProperty(dialCode)) {
2600
+ dialCodeToIso2Map[dialCode] = [];
2601
+ }
2602
+ const iso2List = dialCodeToIso2Map[dialCode];
2603
+ if (iso2List.includes(iso2)) {
2604
+ return;
2605
+ }
2606
+ const index = priority !== void 0 ? priority : iso2List.length;
2607
+ iso2List[index] = iso2;
2608
+ };
2609
+ for (const c of countries) {
2610
+ if (!dialCodes.has(c.dialCode)) {
2611
+ dialCodes.add(c.dialCode);
2612
+ }
2613
+ for (let k = 1; k < c.dialCode.length; k++) {
2614
+ const partialDialCode = c.dialCode.substring(0, k);
2615
+ _addToDialCodeMap(c.iso2, partialDialCode);
2616
+ }
2617
+ _addToDialCodeMap(c.iso2, c.dialCode, c.priority);
2618
+ }
2619
+ if (options.onlyCountries.length || options.excludeCountries.length) {
2620
+ dialCodes.forEach((dialCode) => {
2621
+ dialCodeToIso2Map[dialCode] = dialCodeToIso2Map[dialCode].filter(Boolean);
2622
+ });
2623
+ }
2624
+ for (const c of countries) {
2625
+ if (c.areaCodes) {
2626
+ const rootIso2Code = dialCodeToIso2Map[c.dialCode][0];
2627
+ for (const areaCode of c.areaCodes) {
2628
+ for (let k = 1; k < areaCode.length; k++) {
2629
+ const partialAreaCode = areaCode.substring(0, k);
2630
+ const partialDialCode = c.dialCode + partialAreaCode;
2631
+ _addToDialCodeMap(rootIso2Code, partialDialCode);
2632
+ _addToDialCodeMap(c.iso2, partialDialCode);
2633
+ }
2634
+ _addToDialCodeMap(c.iso2, c.dialCode + areaCode);
2635
+ }
2636
+ }
2637
+ }
2638
+ return { dialCodes, dialCodeMaxLen, dialCodeToIso2Map };
2639
+ }
2640
+ function sortCountries(countries, options) {
2641
+ if (options.countryOrder) {
2642
+ options.countryOrder = options.countryOrder.map((iso2) => iso2.toLowerCase());
2643
+ }
2644
+ countries.sort((a, b) => {
2645
+ const { countryOrder } = options;
2646
+ if (countryOrder) {
2647
+ const aIndex = countryOrder.indexOf(a.iso2);
2648
+ const bIndex = countryOrder.indexOf(b.iso2);
2649
+ const aIndexExists = aIndex > -1;
2650
+ const bIndexExists = bIndex > -1;
2651
+ if (aIndexExists || bIndexExists) {
2652
+ if (aIndexExists && bIndexExists) {
2653
+ return aIndex - bIndex;
2654
+ }
2655
+ return aIndexExists ? -1 : 1;
2656
+ }
2657
+ }
2658
+ return a.name.localeCompare(b.name);
2659
+ });
2660
+ }
2661
+ function cacheSearchTokens(countries) {
2662
+ for (const c of countries) {
2663
+ c.normalisedName = normaliseString(c.name);
2664
+ c.initials = c.name.split(/[^a-zA-ZÀ-ÿа-яА-Я]/).map((word) => word[0]).join("").toLowerCase();
2665
+ c.dialCodePlus = `+${c.dialCode}`;
2666
+ }
2667
+ }
2668
+
2669
+ // src/js/modules/format/formatting.ts
2670
+ function beforeSetNumber(fullNumber, dialCode, separateDialCode, selectedCountryData) {
2671
+ let number = fullNumber;
2672
+ if (separateDialCode) {
2673
+ if (dialCode) {
2674
+ dialCode = `+${selectedCountryData.dialCode}`;
2675
+ const start = number[dialCode.length] === " " || number[dialCode.length] === "-" ? dialCode.length + 1 : dialCode.length;
2676
+ number = number.substring(start);
2677
+ }
2678
+ }
2679
+ return number;
2680
+ }
2681
+ function formatNumberAsYouType(fullNumber, telInputValue, utils, selectedCountryData, separateDialCode) {
2682
+ const result = utils ? utils.formatNumberAsYouType(fullNumber, selectedCountryData.iso2) : fullNumber;
2683
+ const { dialCode } = selectedCountryData;
2684
+ if (separateDialCode && telInputValue.charAt(0) !== "+" && result.includes(`+${dialCode}`)) {
2685
+ const afterDialCode = result.split(`+${dialCode}`)[1] || "";
2686
+ return afterDialCode.trim();
2687
+ }
2688
+ return result;
2689
+ }
2690
+
2691
+ // src/js/modules/format/caret.ts
2692
+ function translateCursorPosition(relevantChars, formattedValue, prevCaretPos, isDeleteForwards) {
2693
+ if (prevCaretPos === 0 && !isDeleteForwards) {
2694
+ return 0;
2695
+ }
2696
+ let relevantCharCount = 0;
2697
+ for (let i = 0; i < formattedValue.length; i++) {
2698
+ if (/[+0-9]/.test(formattedValue[i])) {
2699
+ relevantCharCount++;
2700
+ }
2701
+ if (relevantCharCount === relevantChars && !isDeleteForwards) {
2702
+ return i + 1;
2703
+ }
2704
+ if (isDeleteForwards && relevantCharCount === relevantChars + 1) {
2705
+ return i;
2706
+ }
2707
+ }
2708
+ return formattedValue.length;
2709
+ }
2710
+
2711
+ // src/js/modules/data/nanp-regionless.ts
2712
+ var regionlessNanpNumbers = [
2713
+ "800",
2714
+ "822",
2715
+ "833",
2716
+ "844",
2717
+ "855",
2718
+ "866",
2719
+ "877",
2720
+ "880",
2721
+ "881",
2722
+ "882",
2723
+ "883",
2724
+ "884",
2725
+ "885",
2726
+ "886",
2727
+ "887",
2728
+ "888",
2729
+ "889"
2730
+ ];
2731
+ var isRegionlessNanp = (number) => {
2732
+ const numeric = getNumeric(number);
2733
+ if (numeric.charAt(0) === "1") {
2734
+ const areaCode = numeric.substring(1, 4);
2735
+ return regionlessNanpNumbers.includes(areaCode);
2736
+ }
2737
+ return false;
2738
+ };
2739
+
2740
+ // src/js/intl-tel-input.ts
2741
+ for (const c of data_default) {
2742
+ c.name = countries_default[c.iso2];
2743
+ }
2744
+ var id = 0;
2745
+ var iso2Set = new Set(data_default.map((c) => c.iso2));
2746
+ var isIso2 = (val) => iso2Set.has(val);
2747
+ var Iti = class _Iti {
2748
+ constructor(input, customOptions = {}) {
2749
+ this.id = id++;
2750
+ this.options = { ...defaults, ...customOptions };
2751
+ applyOptionSideEffects(this.options);
2752
+ this.ui = new UI(input, this.options, this.id);
2753
+ this.isAndroid = _Iti._getIsAndroid();
2754
+ this.promise = this._createInitPromises();
2755
+ this.countries = processAllCountries(this.options);
2756
+ const { dialCodes, dialCodeMaxLen, dialCodeToIso2Map } = processDialCodes(
2757
+ this.countries,
2758
+ this.options
2759
+ );
2760
+ this.dialCodes = dialCodes;
2761
+ this.dialCodeMaxLen = dialCodeMaxLen;
2762
+ this.dialCodeToIso2Map = dialCodeToIso2Map;
2763
+ this.countryByIso2 = new Map(this.countries.map((c) => [c.iso2, c]));
2764
+ this._init();
2566
2765
  }
2567
- _maybeUpdateInputPaddingAndReveal() {
2568
- if (this.countryContainer) {
2569
- this._updateInputPadding();
2570
- this.countryContainer.classList.remove("iti__v-hide");
2571
- }
2766
+ static _getIsAndroid() {
2767
+ return typeof navigator !== "undefined" ? /Android/i.test(navigator.userAgent) : false;
2572
2768
  }
2573
- _maybeBuildHiddenInputs(wrapper) {
2574
- const { hiddenInput } = this.options;
2575
- if (hiddenInput) {
2576
- const telInputName = this.telInput.getAttribute("name") || "";
2577
- const names = hiddenInput(telInputName);
2578
- if (names.phone) {
2579
- const existingInput = this.telInput.form?.querySelector(`input[name="${names.phone}"]`);
2580
- if (existingInput) {
2581
- this.hiddenInput = existingInput;
2582
- } else {
2583
- this.hiddenInput = createEl("input", {
2584
- type: "hidden",
2585
- name: names.phone
2586
- });
2587
- wrapper.appendChild(this.hiddenInput);
2588
- }
2589
- }
2590
- if (names.country) {
2591
- const existingInput = this.telInput.form?.querySelector(`input[name="${names.country}"]`);
2592
- if (existingInput) {
2593
- this.hiddenInputCountry = existingInput;
2594
- } else {
2595
- this.hiddenInputCountry = createEl("input", {
2596
- type: "hidden",
2597
- name: names.country
2598
- });
2599
- wrapper.appendChild(this.hiddenInputCountry);
2600
- }
2601
- }
2602
- }
2769
+ _createInitPromises() {
2770
+ const autoCountryPromise = new Promise((resolve, reject) => {
2771
+ this.resolveAutoCountryPromise = resolve;
2772
+ this.rejectAutoCountryPromise = reject;
2773
+ });
2774
+ const utilsScriptPromise = new Promise((resolve, reject) => {
2775
+ this.resolveUtilsScriptPromise = resolve;
2776
+ this.rejectUtilsScriptPromise = reject;
2777
+ });
2778
+ return Promise.all([autoCountryPromise, utilsScriptPromise]);
2603
2779
  }
2604
- //* For each country: add a country list item <li> to the countryList <ul> container.
2605
- _appendListItems() {
2606
- for (let i = 0; i < this.countries.length; i++) {
2607
- const c = this.countries[i];
2608
- const extraClass = i === 0 ? "iti__highlight" : "";
2609
- const listItem = createEl(
2610
- "li",
2611
- {
2612
- id: `iti-${this.id}__item-${c.iso2}`,
2613
- class: `iti__country ${extraClass}`,
2614
- tabindex: "-1",
2615
- role: "option",
2616
- "data-dial-code": c.dialCode,
2617
- "data-country-code": c.iso2,
2618
- "aria-selected": "false"
2619
- },
2620
- this.countryList
2621
- );
2622
- c.nodeById[this.id] = listItem;
2623
- let content = "";
2624
- if (this.options.showFlags) {
2625
- content += `<div class='iti__flag iti__${c.iso2}'></div>`;
2626
- }
2627
- content += `<span class='iti__country-name'>${c.name}</span>`;
2628
- content += `<span class='iti__dial-code' dir='ltr'>+${c.dialCode}</span>`;
2629
- listItem.insertAdjacentHTML("beforeend", content);
2630
- }
2780
+ //* Can't be private as it's called from intlTelInput convenience wrapper.
2781
+ _init() {
2782
+ this.selectedCountryData = {};
2783
+ this.abortController = new AbortController();
2784
+ this._processCountryData();
2785
+ this.ui.generateMarkup(this.countries);
2786
+ this._setInitialState();
2787
+ this._initListeners();
2788
+ this._initRequests();
2789
+ }
2790
+ //********************
2791
+ //* PRIVATE METHODS
2792
+ //********************
2793
+ //* Prepare all of the country data, including onlyCountries, excludeCountries, countryOrder options.
2794
+ _processCountryData() {
2795
+ translateCountryNames(this.countries, this.options);
2796
+ sortCountries(this.countries, this.options);
2797
+ cacheSearchTokens(this.countries);
2631
2798
  }
2632
2799
  //* Set the initial state of the input value and the selected country by:
2633
2800
  //* 1. Extracting a dial code from the given number
2634
2801
  //* 2. Using explicit initialCountry
2635
2802
  _setInitialState(overrideAutoCountry = false) {
2636
- const attributeValue = this.telInput.getAttribute("value");
2637
- const inputValue = this.telInput.value;
2638
- const useAttribute = attributeValue && attributeValue.charAt(0) === "+" && (!inputValue || inputValue.charAt(0) !== "+");
2803
+ const attributeValue = this.ui.telInput.getAttribute("value");
2804
+ const inputValue = this.ui.telInput.value;
2805
+ const useAttribute = attributeValue && attributeValue.startsWith("+") && (!inputValue || !inputValue.startsWith("+"));
2639
2806
  const val = useAttribute ? attributeValue : inputValue;
2640
2807
  const dialCode = this._getDialCode(val);
2641
2808
  const isRegionlessNanpNumber = isRegionlessNanp(val);
@@ -2665,47 +2832,49 @@ var Iti = class _Iti {
2665
2832
  if (this.options.allowDropdown) {
2666
2833
  this._initDropdownListeners();
2667
2834
  }
2668
- if ((this.hiddenInput || this.hiddenInputCountry) && this.telInput.form) {
2835
+ if ((this.ui.hiddenInput || this.ui.hiddenInputCountry) && this.ui.telInput.form) {
2669
2836
  this._initHiddenInputListener();
2670
2837
  }
2671
2838
  }
2672
2839
  //* Update hidden input on form submit.
2673
2840
  _initHiddenInputListener() {
2674
- this._handleHiddenInputSubmit = () => {
2675
- if (this.hiddenInput) {
2676
- this.hiddenInput.value = this.getNumber();
2841
+ const handleHiddenInputSubmit = () => {
2842
+ if (this.ui.hiddenInput) {
2843
+ this.ui.hiddenInput.value = this.getNumber();
2677
2844
  }
2678
- if (this.hiddenInputCountry) {
2679
- this.hiddenInputCountry.value = this.getSelectedCountryData().iso2 || "";
2845
+ if (this.ui.hiddenInputCountry) {
2846
+ this.ui.hiddenInputCountry.value = this.selectedCountryData.iso2 || "";
2680
2847
  }
2681
2848
  };
2682
- this.telInput.form?.addEventListener(
2683
- "submit",
2684
- this._handleHiddenInputSubmit
2685
- );
2849
+ this.ui.telInput.form?.addEventListener("submit", handleHiddenInputSubmit, {
2850
+ signal: this.abortController.signal
2851
+ });
2686
2852
  }
2687
2853
  //* initialise the dropdown listeners.
2688
2854
  _initDropdownListeners() {
2689
- this._handleLabelClick = (e) => {
2690
- if (this.dropdownContent.classList.contains("iti__hide")) {
2691
- this.telInput.focus();
2855
+ const signal = this.abortController.signal;
2856
+ const handleLabelClick = (e) => {
2857
+ if (this.ui.dropdownContent.classList.contains("iti__hide")) {
2858
+ this.ui.telInput.focus();
2692
2859
  } else {
2693
2860
  e.preventDefault();
2694
2861
  }
2695
2862
  };
2696
- const label = this.telInput.closest("label");
2863
+ const label = this.ui.telInput.closest("label");
2697
2864
  if (label) {
2698
- label.addEventListener("click", this._handleLabelClick);
2865
+ label.addEventListener("click", handleLabelClick, { signal });
2699
2866
  }
2700
- this._handleClickSelectedCountry = () => {
2701
- const dropdownClosed = this.dropdownContent.classList.contains("iti__hide");
2702
- if (dropdownClosed && !this.telInput.disabled && !this.telInput.readOnly) {
2867
+ const handleClickSelectedCountry = () => {
2868
+ const dropdownClosed = this.ui.dropdownContent.classList.contains("iti__hide");
2869
+ if (dropdownClosed && !this.ui.telInput.disabled && !this.ui.telInput.readOnly) {
2703
2870
  this._openDropdown();
2704
2871
  }
2705
2872
  };
2706
- this.selectedCountry.addEventListener("click", this._handleClickSelectedCountry);
2707
- this._handleCountryContainerKeydown = (e) => {
2708
- const isDropdownHidden = this.dropdownContent.classList.contains("iti__hide");
2873
+ this.ui.selectedCountry.addEventListener("click", handleClickSelectedCountry, {
2874
+ signal
2875
+ });
2876
+ const handleCountryContainerKeydown = (e) => {
2877
+ const isDropdownHidden = this.ui.dropdownContent.classList.contains("iti__hide");
2709
2878
  if (isDropdownHidden && ["ArrowUp", "ArrowDown", " ", "Enter"].includes(e.key)) {
2710
2879
  e.preventDefault();
2711
2880
  e.stopPropagation();
@@ -2715,26 +2884,29 @@ var Iti = class _Iti {
2715
2884
  this._closeDropdown();
2716
2885
  }
2717
2886
  };
2718
- this.countryContainer.addEventListener(
2887
+ this.ui.countryContainer.addEventListener(
2719
2888
  "keydown",
2720
- this._handleCountryContainerKeydown
2889
+ handleCountryContainerKeydown,
2890
+ { signal }
2721
2891
  );
2722
2892
  }
2723
2893
  //* Init many requests: utils script / geo ip lookup.
2724
2894
  _initRequests() {
2725
- let { loadUtils, initialCountry, geoIpLookup } = this.options;
2895
+ const { loadUtils, initialCountry, geoIpLookup } = this.options;
2726
2896
  if (loadUtils && !intlTelInput.utils) {
2727
- this._doAttachUtils = () => {
2897
+ const doAttachUtils = () => {
2728
2898
  intlTelInput.attachUtils(loadUtils)?.catch(() => {
2729
2899
  });
2730
2900
  };
2731
2901
  if (intlTelInput.documentReady()) {
2732
- this._doAttachUtils();
2902
+ doAttachUtils();
2733
2903
  } else {
2734
- this._handlePageLoad = () => {
2735
- this._doAttachUtils();
2904
+ const handlePageLoad = () => {
2905
+ doAttachUtils();
2736
2906
  };
2737
- window.addEventListener("load", this._handlePageLoad);
2907
+ window.addEventListener("load", handlePageLoad, {
2908
+ signal: this.abortController.signal
2909
+ });
2738
2910
  }
2739
2911
  } else {
2740
2912
  this.resolveUtilsScriptPromise();
@@ -2774,8 +2946,8 @@ var Iti = class _Iti {
2774
2946
  }
2775
2947
  _openDropdownWithPlus() {
2776
2948
  this._openDropdown();
2777
- this.searchInput.value = "+";
2778
- this._filterCountries("");
2949
+ this.ui.searchInput.value = "+";
2950
+ this._filterCountriesByQuery("");
2779
2951
  }
2780
2952
  //* Initialize the tel input listeners.
2781
2953
  _initTelInputListeners() {
@@ -2784,55 +2956,77 @@ var Iti = class _Iti {
2784
2956
  this._maybeBindPasteListener();
2785
2957
  }
2786
2958
  _bindInputListener() {
2787
- const { strictMode, formatAsYouType, separateDialCode, allowDropdown, countrySearch } = this.options;
2959
+ const {
2960
+ strictMode,
2961
+ formatAsYouType,
2962
+ separateDialCode,
2963
+ allowDropdown,
2964
+ countrySearch
2965
+ } = this.options;
2788
2966
  let userOverrideFormatting = false;
2789
- if (/\p{L}/u.test(this.telInput.value)) {
2967
+ if (/\p{L}/u.test(this.ui.telInput.value)) {
2790
2968
  userOverrideFormatting = true;
2791
2969
  }
2792
- this._handleInputEvent = (e) => {
2970
+ const handleInputEvent = (e) => {
2793
2971
  if (this.isAndroid && e?.data === "+" && separateDialCode && allowDropdown && countrySearch) {
2794
- const currentCaretPos = this.telInput.selectionStart || 0;
2795
- const valueBeforeCaret = this.telInput.value.substring(0, currentCaretPos - 1);
2796
- const valueAfterCaret = this.telInput.value.substring(currentCaretPos);
2797
- this.telInput.value = valueBeforeCaret + valueAfterCaret;
2972
+ const currentCaretPos = this.ui.telInput.selectionStart || 0;
2973
+ const valueBeforeCaret = this.ui.telInput.value.substring(
2974
+ 0,
2975
+ currentCaretPos - 1
2976
+ );
2977
+ const valueAfterCaret = this.ui.telInput.value.substring(currentCaretPos);
2978
+ this.ui.telInput.value = valueBeforeCaret + valueAfterCaret;
2798
2979
  this._openDropdownWithPlus();
2799
2980
  return;
2800
2981
  }
2801
- if (this._updateCountryFromNumber(this.telInput.value)) {
2982
+ if (this._updateCountryFromNumber(this.ui.telInput.value)) {
2802
2983
  this._triggerCountryChange();
2803
2984
  }
2804
2985
  const isFormattingChar = e?.data && /[^+0-9]/.test(e.data);
2805
- const isPaste = e?.inputType === "insertFromPaste" && this.telInput.value;
2986
+ const isPaste = e?.inputType === "insertFromPaste" && this.ui.telInput.value;
2806
2987
  if (isFormattingChar || isPaste && !strictMode) {
2807
2988
  userOverrideFormatting = true;
2808
- } else if (!/[^+0-9]/.test(this.telInput.value)) {
2989
+ } else if (!/[^+0-9]/.test(this.ui.telInput.value)) {
2809
2990
  userOverrideFormatting = false;
2810
2991
  }
2811
2992
  const isSetNumber = e?.detail && e.detail["isSetNumber"];
2812
2993
  if (formatAsYouType && !userOverrideFormatting && !isSetNumber) {
2813
- const currentCaretPos = this.telInput.selectionStart || 0;
2814
- const valueBeforeCaret = this.telInput.value.substring(0, currentCaretPos);
2815
- const relevantCharsBeforeCaret = valueBeforeCaret.replace(/[^+0-9]/g, "").length;
2994
+ const currentCaretPos = this.ui.telInput.selectionStart || 0;
2995
+ const valueBeforeCaret = this.ui.telInput.value.substring(
2996
+ 0,
2997
+ currentCaretPos
2998
+ );
2999
+ const relevantCharsBeforeCaret = valueBeforeCaret.replace(
3000
+ /[^+0-9]/g,
3001
+ ""
3002
+ ).length;
2816
3003
  const isDeleteForwards = e?.inputType === "deleteContentForward";
2817
3004
  const fullNumber = this._getFullNumber();
2818
3005
  const formattedValue = formatNumberAsYouType(
2819
3006
  fullNumber,
2820
- this.telInput.value,
3007
+ this.ui.telInput.value,
2821
3008
  intlTelInput.utils,
2822
3009
  this.selectedCountryData,
2823
3010
  this.options.separateDialCode
2824
3011
  );
2825
- const newCaretPos = translateCursorPosition(relevantCharsBeforeCaret, formattedValue, currentCaretPos, isDeleteForwards);
2826
- this.telInput.value = formattedValue;
2827
- this.telInput.setSelectionRange(newCaretPos, newCaretPos);
3012
+ const newCaretPos = translateCursorPosition(
3013
+ relevantCharsBeforeCaret,
3014
+ formattedValue,
3015
+ currentCaretPos,
3016
+ isDeleteForwards
3017
+ );
3018
+ this.ui.telInput.value = formattedValue;
3019
+ this.ui.telInput.setSelectionRange(newCaretPos, newCaretPos);
2828
3020
  }
2829
3021
  };
2830
- this.telInput.addEventListener("input", this._handleInputEvent);
3022
+ this.ui.telInput.addEventListener("input", handleInputEvent, {
3023
+ signal: this.abortController.signal
3024
+ });
2831
3025
  }
2832
3026
  _maybeBindKeydownListener() {
2833
3027
  const { strictMode, separateDialCode, allowDropdown, countrySearch } = this.options;
2834
3028
  if (strictMode || separateDialCode) {
2835
- this._handleKeydownEvent = (e) => {
3029
+ const handleKeydownEvent = (e) => {
2836
3030
  if (e.key && e.key.length === 1 && !e.altKey && !e.ctrlKey && !e.metaKey) {
2837
3031
  if (separateDialCode && allowDropdown && countrySearch && e.key === "+") {
2838
3032
  e.preventDefault();
@@ -2840,14 +3034,17 @@ var Iti = class _Iti {
2840
3034
  return;
2841
3035
  }
2842
3036
  if (strictMode) {
2843
- const value = this.telInput.value;
2844
- const alreadyHasPlus = value.charAt(0) === "+";
2845
- const isInitialPlus = !alreadyHasPlus && this.telInput.selectionStart === 0 && e.key === "+";
3037
+ const value = this.ui.telInput.value;
3038
+ const alreadyHasPlus = value.startsWith("+");
3039
+ const isInitialPlus = !alreadyHasPlus && this.ui.telInput.selectionStart === 0 && e.key === "+";
2846
3040
  const isNumeric = /^[0-9]$/.test(e.key);
2847
3041
  const isAllowedChar = separateDialCode ? isNumeric : isInitialPlus || isNumeric;
2848
- const newValue = value.slice(0, this.telInput.selectionStart) + e.key + value.slice(this.telInput.selectionEnd);
3042
+ const newValue = value.slice(0, this.ui.telInput.selectionStart) + e.key + value.slice(this.ui.telInput.selectionEnd);
2849
3043
  const newFullNumber = this._getFullNumber(newValue);
2850
- const coreNumber = intlTelInput.utils.getCoreNumber(newFullNumber, this.selectedCountryData.iso2);
3044
+ const coreNumber = intlTelInput.utils.getCoreNumber(
3045
+ newFullNumber,
3046
+ this.selectedCountryData.iso2
3047
+ );
2851
3048
  const hasExceededMaxLength = this.maxCoreNumberLength && coreNumber.length > this.maxCoreNumberLength;
2852
3049
  const newCountry = this._getNewCountryFromNumber(newFullNumber);
2853
3050
  const isChangingDialCode = newCountry !== null;
@@ -2857,14 +3054,16 @@ var Iti = class _Iti {
2857
3054
  }
2858
3055
  }
2859
3056
  };
2860
- this.telInput.addEventListener("keydown", this._handleKeydownEvent);
3057
+ this.ui.telInput.addEventListener("keydown", handleKeydownEvent, {
3058
+ signal: this.abortController.signal
3059
+ });
2861
3060
  }
2862
3061
  }
2863
3062
  _maybeBindPasteListener() {
2864
3063
  if (this.options.strictMode) {
2865
- this._handlePasteEvent = (e) => {
3064
+ const handlePasteEvent = (e) => {
2866
3065
  e.preventDefault();
2867
- const input = this.telInput;
3066
+ const input = this.ui.telInput;
2868
3067
  const selStart = input.selectionStart;
2869
3068
  const selEnd = input.selectionEnd;
2870
3069
  const before = input.value.slice(0, selStart);
@@ -2899,82 +3098,95 @@ var Iti = class _Iti {
2899
3098
  input.setSelectionRange(caretPos, caretPos);
2900
3099
  input.dispatchEvent(new InputEvent("input", { bubbles: true }));
2901
3100
  };
2902
- this.telInput.addEventListener("paste", this._handlePasteEvent);
3101
+ this.ui.telInput.addEventListener("paste", handlePasteEvent, {
3102
+ signal: this.abortController.signal
3103
+ });
2903
3104
  }
2904
3105
  }
2905
3106
  //* Adhere to the input's maxlength attr.
2906
3107
  _cap(number) {
2907
- const max = parseInt(this.telInput.getAttribute("maxlength") || "", 10);
3108
+ const max = Number(this.ui.telInput.getAttribute("maxlength"));
2908
3109
  return max && number.length > max ? number.substring(0, max) : number;
2909
3110
  }
2910
- //* Trigger a custom event on the input.
3111
+ //* Trigger a custom event on the input (typed via ItiEventMap).
2911
3112
  _trigger(name, detailProps = {}) {
2912
3113
  const e = new CustomEvent(name, {
2913
3114
  bubbles: true,
2914
3115
  cancelable: true,
2915
3116
  detail: detailProps
2916
3117
  });
2917
- this.telInput.dispatchEvent(e);
3118
+ this.ui.telInput.dispatchEvent(e);
2918
3119
  }
2919
3120
  //* Open the dropdown.
2920
3121
  _openDropdown() {
2921
3122
  const { fixDropdownWidth, countrySearch } = this.options;
3123
+ this.dropdownAbortController = new AbortController();
2922
3124
  if (fixDropdownWidth) {
2923
- this.dropdownContent.style.width = `${this.telInput.offsetWidth}px`;
3125
+ this.ui.dropdownContent.style.width = `${this.ui.telInput.offsetWidth}px`;
2924
3126
  }
2925
- this.dropdownContent.classList.remove("iti__hide");
2926
- this.selectedCountry.setAttribute("aria-expanded", "true");
3127
+ this.ui.dropdownContent.classList.remove("iti__hide");
3128
+ this.ui.selectedCountry.setAttribute("aria-expanded", "true");
2927
3129
  this._setDropdownPosition();
2928
3130
  if (countrySearch) {
2929
- const firstCountryItem = this.countryList.firstElementChild;
3131
+ const firstCountryItem = this.ui.countryList.firstElementChild;
2930
3132
  if (firstCountryItem) {
2931
- this._highlightListItem(firstCountryItem, false);
2932
- this.countryList.scrollTop = 0;
3133
+ this.ui.highlightListItem(firstCountryItem, false);
3134
+ this.ui.countryList.scrollTop = 0;
2933
3135
  }
2934
- this.searchInput.focus();
3136
+ this.ui.searchInput.focus();
2935
3137
  }
2936
3138
  this._bindDropdownListeners();
2937
- this.dropdownArrow.classList.add("iti__arrow--up");
3139
+ this.ui.dropdownArrow.classList.add("iti__arrow--up");
2938
3140
  this._trigger("open:countrydropdown");
2939
3141
  }
2940
3142
  //* Set the dropdown position
2941
3143
  _setDropdownPosition() {
2942
3144
  if (this.options.dropdownContainer) {
2943
- this.options.dropdownContainer.appendChild(this.dropdown);
3145
+ this.options.dropdownContainer.appendChild(this.ui.dropdown);
2944
3146
  }
2945
3147
  if (!this.options.useFullscreenPopup) {
2946
- const inputPosRelativeToVP = this.telInput.getBoundingClientRect();
2947
- const inputHeight = this.telInput.offsetHeight;
3148
+ const inputPosRelativeToVP = this.ui.telInput.getBoundingClientRect();
3149
+ const inputHeight = this.ui.telInput.offsetHeight;
2948
3150
  if (this.options.dropdownContainer) {
2949
- this.dropdown.style.top = `${inputPosRelativeToVP.top + inputHeight}px`;
2950
- this.dropdown.style.left = `${inputPosRelativeToVP.left}px`;
2951
- this._handleWindowScroll = () => this._closeDropdown();
2952
- window.addEventListener("scroll", this._handleWindowScroll);
3151
+ this.ui.dropdown.style.top = `${inputPosRelativeToVP.top + inputHeight}px`;
3152
+ this.ui.dropdown.style.left = `${inputPosRelativeToVP.left}px`;
3153
+ const handleWindowScroll = () => this._closeDropdown();
3154
+ window.addEventListener("scroll", handleWindowScroll, {
3155
+ signal: this.dropdownAbortController.signal
3156
+ });
2953
3157
  }
2954
3158
  }
2955
3159
  }
2956
3160
  //* We only bind dropdown listeners when the dropdown is open.
2957
3161
  _bindDropdownListeners() {
2958
- this._handleMouseoverCountryList = (e) => {
2959
- const listItem = e.target?.closest(".iti__country");
3162
+ const signal = this.dropdownAbortController.signal;
3163
+ const handleMouseoverCountryList = (e) => {
3164
+ const listItem = e.target?.closest(
3165
+ ".iti__country"
3166
+ );
2960
3167
  if (listItem) {
2961
- this._highlightListItem(listItem, false);
3168
+ this.ui.highlightListItem(listItem, false);
2962
3169
  }
2963
3170
  };
2964
- this.countryList.addEventListener(
2965
- "mouseover",
2966
- this._handleMouseoverCountryList
2967
- );
2968
- this._handleClickCountryList = (e) => {
2969
- const listItem = e.target?.closest(".iti__country");
3171
+ this.ui.countryList.addEventListener("mouseover", handleMouseoverCountryList, {
3172
+ signal
3173
+ });
3174
+ const handleClickCountryList = (e) => {
3175
+ const listItem = e.target?.closest(
3176
+ ".iti__country"
3177
+ );
2970
3178
  if (listItem) {
2971
3179
  this._selectListItem(listItem);
2972
3180
  }
2973
3181
  };
2974
- this.countryList.addEventListener("click", this._handleClickCountryList);
2975
- this._handleClickOffToClose = (e) => {
3182
+ this.ui.countryList.addEventListener("click", handleClickCountryList, {
3183
+ signal
3184
+ });
3185
+ const handleClickOffToClose = (e) => {
2976
3186
  const target = e.target;
2977
- const clickedInsideDropdown = !!target.closest(`#iti-${this.id}__dropdown-content`);
3187
+ const clickedInsideDropdown = !!target.closest(
3188
+ `#iti-${this.id}__dropdown-content`
3189
+ );
2978
3190
  if (!clickedInsideDropdown) {
2979
3191
  this._closeDropdown();
2980
3192
  }
@@ -2982,12 +3194,13 @@ var Iti = class _Iti {
2982
3194
  setTimeout(() => {
2983
3195
  document.documentElement.addEventListener(
2984
3196
  "click",
2985
- this._handleClickOffToClose
3197
+ handleClickOffToClose,
3198
+ { signal }
2986
3199
  );
2987
3200
  }, 0);
2988
3201
  let query = "";
2989
3202
  let queryTimer = null;
2990
- this._handleKeydownOnDropdown = (e) => {
3203
+ const handleKeydownOnDropdown = (e) => {
2991
3204
  if (["ArrowUp", "ArrowDown", "Enter", "Escape"].includes(e.key)) {
2992
3205
  e.preventDefault();
2993
3206
  e.stopPropagation();
@@ -3011,19 +3224,19 @@ var Iti = class _Iti {
3011
3224
  }, 1e3);
3012
3225
  }
3013
3226
  };
3014
- document.addEventListener("keydown", this._handleKeydownOnDropdown);
3227
+ document.addEventListener("keydown", handleKeydownOnDropdown, { signal });
3015
3228
  if (this.options.countrySearch) {
3016
3229
  const doFilter = () => {
3017
- const inputQuery = this.searchInput.value.trim();
3018
- this._filterCountries(inputQuery);
3019
- if (this.searchInput.value) {
3020
- this.searchClearButton.classList.remove("iti__hide");
3230
+ const inputQuery = this.ui.searchInput.value.trim();
3231
+ this._filterCountriesByQuery(inputQuery);
3232
+ if (this.ui.searchInput.value) {
3233
+ this.ui.searchClearButton.classList.remove("iti__hide");
3021
3234
  } else {
3022
- this.searchClearButton.classList.add("iti__hide");
3235
+ this.ui.searchClearButton.classList.add("iti__hide");
3023
3236
  }
3024
3237
  };
3025
3238
  let keyupTimer = null;
3026
- this._handleSearchChange = () => {
3239
+ const handleSearchChange = () => {
3027
3240
  if (keyupTimer) {
3028
3241
  clearTimeout(keyupTimer);
3029
3242
  }
@@ -3032,13 +3245,17 @@ var Iti = class _Iti {
3032
3245
  keyupTimer = null;
3033
3246
  }, 100);
3034
3247
  };
3035
- this.searchInput.addEventListener("input", this._handleSearchChange);
3036
- this._handleSearchClear = () => {
3037
- this.searchInput.value = "";
3038
- this.searchInput.focus();
3248
+ this.ui.searchInput.addEventListener("input", handleSearchChange, {
3249
+ signal
3250
+ });
3251
+ const handleSearchClear = () => {
3252
+ this.ui.searchInput.value = "";
3253
+ this.ui.searchInput.focus();
3039
3254
  doFilter();
3040
3255
  };
3041
- this.searchClearButton.addEventListener("click", this._handleSearchClear);
3256
+ this.ui.searchClearButton.addEventListener("click", handleSearchClear, {
3257
+ signal
3258
+ });
3042
3259
  }
3043
3260
  }
3044
3261
  //* Hidden search (countrySearch disabled): Find the first list item whose name starts with the query string.
@@ -3047,42 +3264,21 @@ var Iti = class _Iti {
3047
3264
  const startsWith = c.name.substring(0, query.length).toLowerCase() === query;
3048
3265
  if (startsWith) {
3049
3266
  const listItem = c.nodeById[this.id];
3050
- this._highlightListItem(listItem, false);
3051
- this._scrollTo(listItem);
3267
+ this.ui.highlightListItem(listItem, false);
3268
+ this.ui.scrollTo(listItem);
3052
3269
  break;
3053
3270
  }
3054
3271
  }
3055
3272
  }
3056
- //* Country search enabled: Filter the countries according to the search query.
3057
- _filterCountries(query) {
3058
- this.countryList.innerHTML = "";
3273
+ //* Country search: Filter the countries according to the search query.
3274
+ _filterCountriesByQuery(query) {
3059
3275
  let matchedCountries;
3060
3276
  if (query === "") {
3061
3277
  matchedCountries = this.countries;
3062
3278
  } else {
3063
3279
  matchedCountries = this._getMatchedCountries(query);
3064
3280
  }
3065
- let noCountriesAddedYet = true;
3066
- for (const c of matchedCountries) {
3067
- const listItem = c.nodeById[this.id];
3068
- if (listItem) {
3069
- this.countryList.appendChild(listItem);
3070
- if (noCountriesAddedYet) {
3071
- this._highlightListItem(listItem, false);
3072
- noCountriesAddedYet = false;
3073
- }
3074
- }
3075
- }
3076
- if (noCountriesAddedYet) {
3077
- this._highlightListItem(null, false);
3078
- if (this.searchNoResults) {
3079
- this.searchNoResults.classList.remove("iti__hide");
3080
- }
3081
- } else if (this.searchNoResults) {
3082
- this.searchNoResults.classList.add("iti__hide");
3083
- }
3084
- this.countryList.scrollTop = 0;
3085
- this._updateSearchResultsA11yText();
3281
+ this.ui.filterCountries(matchedCountries);
3086
3282
  }
3087
3283
  _getMatchedCountries(query) {
3088
3284
  const normalisedQuery = normaliseString(query);
@@ -3116,39 +3312,21 @@ var Iti = class _Iti {
3116
3312
  ...initialsMatches.sort((a, b) => a.priority - b.priority)
3117
3313
  ];
3118
3314
  }
3119
- //* Update search results text (for a11y).
3120
- _updateSearchResultsA11yText() {
3121
- const { i18n } = this.options;
3122
- const count = this.countryList.childElementCount;
3123
- let searchText;
3124
- if (count === 0) {
3125
- searchText = i18n.zeroSearchResults;
3126
- } else {
3127
- if (i18n.searchResultsText) {
3128
- searchText = i18n.searchResultsText(count);
3129
- } else if (count === 1) {
3130
- searchText = i18n.oneSearchResult;
3131
- } else {
3132
- searchText = i18n.multipleSearchResults.replace("${count}", count.toString());
3133
- }
3134
- }
3135
- this.searchResultsA11yText.textContent = searchText;
3136
- }
3137
3315
  //* Highlight the next/prev item in the list (and ensure it is visible).
3138
3316
  _handleUpDownKey(key) {
3139
- let next = key === "ArrowUp" ? this.highlightedItem?.previousElementSibling : this.highlightedItem?.nextElementSibling;
3140
- if (!next && this.countryList.childElementCount > 1) {
3141
- next = key === "ArrowUp" ? this.countryList.lastElementChild : this.countryList.firstElementChild;
3317
+ let next = key === "ArrowUp" ? this.ui.highlightedItem?.previousElementSibling : this.ui.highlightedItem?.nextElementSibling;
3318
+ if (!next && this.ui.countryList.childElementCount > 1) {
3319
+ next = key === "ArrowUp" ? this.ui.countryList.lastElementChild : this.ui.countryList.firstElementChild;
3142
3320
  }
3143
3321
  if (next) {
3144
- this._scrollTo(next);
3145
- this._highlightListItem(next, false);
3322
+ this.ui.scrollTo(next);
3323
+ this.ui.highlightListItem(next, false);
3146
3324
  }
3147
3325
  }
3148
3326
  //* Select the currently highlighted item.
3149
3327
  _handleEnterKey() {
3150
- if (this.highlightedItem) {
3151
- this._selectListItem(this.highlightedItem);
3328
+ if (this.ui.highlightedItem) {
3329
+ this._selectListItem(this.ui.highlightedItem);
3152
3330
  }
3153
3331
  }
3154
3332
  //* Update the input's value to the given val (format first if possible)
@@ -3156,7 +3334,7 @@ var Iti = class _Iti {
3156
3334
  _updateValFromNumber(fullNumber) {
3157
3335
  let number = fullNumber;
3158
3336
  if (this.options.formatOnDisplay && intlTelInput.utils && this.selectedCountryData) {
3159
- const useNational = this.options.nationalMode || number.charAt(0) !== "+" && !this.options.separateDialCode;
3337
+ const useNational = this.options.nationalMode || !number.startsWith("+") && !this.options.separateDialCode;
3160
3338
  const { NATIONAL, INTERNATIONAL } = intlTelInput.utils.numberFormat;
3161
3339
  const format = useNational ? NATIONAL : INTERNATIONAL;
3162
3340
  number = intlTelInput.utils.formatNumber(
@@ -3166,7 +3344,7 @@ var Iti = class _Iti {
3166
3344
  );
3167
3345
  }
3168
3346
  number = this._beforeSetNumber(number);
3169
- this.telInput.value = number;
3347
+ this.ui.telInput.value = number;
3170
3348
  }
3171
3349
  //* Check if need to select a new country based on the given number
3172
3350
  //* Note: called from _setInitialState, keyup handler, setNumber.
@@ -3180,11 +3358,11 @@ var Iti = class _Iti {
3180
3358
  // if there is a selected country, and the number doesn't start with a dial code, then add it
3181
3359
  _ensureHasDialCode(number) {
3182
3360
  const { dialCode, nationalPrefix } = this.selectedCountryData;
3183
- const alreadyHasPlus = number.charAt(0) === "+";
3361
+ const alreadyHasPlus = number.startsWith("+");
3184
3362
  if (alreadyHasPlus || !dialCode) {
3185
3363
  return number;
3186
3364
  }
3187
- const hasPrefix = nationalPrefix && number.charAt(0) === nationalPrefix && !this.options.separateDialCode;
3365
+ const hasPrefix = nationalPrefix && number.startsWith(nationalPrefix) && !this.options.separateDialCode;
3188
3366
  const cleanNumber = hasPrefix ? number.substring(1) : number;
3189
3367
  return `+${dialCode}${cleanNumber}`;
3190
3368
  }
@@ -3217,7 +3395,9 @@ var Iti = class _Iti {
3217
3395
  }
3218
3396
  const { areaCodes, priority } = this.selectedCountryData;
3219
3397
  if (areaCodes) {
3220
- const dialCodeAreaCodes = areaCodes.map((areaCode) => `${selectedDialCode}${areaCode}`);
3398
+ const dialCodeAreaCodes = areaCodes.map(
3399
+ (areaCode) => `${selectedDialCode}${areaCode}`
3400
+ );
3221
3401
  for (const dialCodeAreaCode of dialCodeAreaCodes) {
3222
3402
  if (numeric.startsWith(dialCodeAreaCode)) {
3223
3403
  return null;
@@ -3231,33 +3411,13 @@ var Iti = class _Iti {
3231
3411
  if (!isValidSelection && !alreadySelected) {
3232
3412
  return iso2Codes[0];
3233
3413
  }
3234
- } else if (number.charAt(0) === "+" && numeric.length) {
3414
+ } else if (number.startsWith("+") && numeric.length) {
3235
3415
  return "";
3236
3416
  } else if ((!number || number === "+") && !selectedIso2) {
3237
3417
  return this.defaultCountry;
3238
3418
  }
3239
3419
  return null;
3240
3420
  }
3241
- //* Remove highlighting from other list items and highlight the given item.
3242
- _highlightListItem(listItem, shouldFocus) {
3243
- const prevItem = this.highlightedItem;
3244
- if (prevItem) {
3245
- prevItem.classList.remove("iti__highlight");
3246
- prevItem.setAttribute("aria-selected", "false");
3247
- }
3248
- this.highlightedItem = listItem;
3249
- if (this.highlightedItem) {
3250
- this.highlightedItem.classList.add("iti__highlight");
3251
- this.highlightedItem.setAttribute("aria-selected", "true");
3252
- if (this.options.countrySearch) {
3253
- const activeDescendant = this.highlightedItem.getAttribute("id") || "";
3254
- this.searchInput.setAttribute("aria-activedescendant", activeDescendant);
3255
- }
3256
- }
3257
- if (shouldFocus) {
3258
- this.highlightedItem.focus();
3259
- }
3260
- }
3261
3421
  //* Update the selected country, dial code (if separateDialCode), placeholder, title, and active list item.
3262
3422
  //* Note: called from _setInitialState, _updateCountryFromNumber, _selectListItem, setCountry.
3263
3423
  _setCountry(iso2) {
@@ -3267,7 +3427,7 @@ var Iti = class _Iti {
3267
3427
  if (this.selectedCountryData.iso2) {
3268
3428
  this.defaultCountry = this.selectedCountryData.iso2;
3269
3429
  }
3270
- if (this.selectedCountry) {
3430
+ if (this.ui.selectedCountry) {
3271
3431
  const flagClass = iso2 && showFlags ? `iti__flag iti__${iso2}` : "iti__flag iti__globe";
3272
3432
  let ariaLabel, title;
3273
3433
  if (iso2) {
@@ -3278,28 +3438,19 @@ var Iti = class _Iti {
3278
3438
  title = i18n.noCountrySelected;
3279
3439
  ariaLabel = i18n.noCountrySelected;
3280
3440
  }
3281
- this.selectedCountryInner.className = flagClass;
3282
- this.selectedCountry.setAttribute("title", title);
3283
- this.selectedCountry.setAttribute("aria-label", ariaLabel);
3441
+ this.ui.selectedCountryInner.className = flagClass;
3442
+ this.ui.selectedCountry.setAttribute("title", title);
3443
+ this.ui.selectedCountry.setAttribute("aria-label", ariaLabel);
3284
3444
  }
3285
3445
  if (separateDialCode) {
3286
3446
  const dialCode = this.selectedCountryData.dialCode ? `+${this.selectedCountryData.dialCode}` : "";
3287
- this.selectedDialCode.innerHTML = dialCode;
3288
- this._updateInputPadding();
3447
+ this.ui.selectedDialCode.textContent = dialCode;
3448
+ this.ui.updateInputPadding();
3289
3449
  }
3290
3450
  this._updatePlaceholder();
3291
3451
  this._updateMaxLength();
3292
3452
  return prevIso2 !== iso2;
3293
3453
  }
3294
- //* Update the input padding to make space for the selected country/dial code.
3295
- _updateInputPadding() {
3296
- if (this.selectedCountry) {
3297
- const saneDefaultWidth = this.options.separateDialCode ? 78 : 42;
3298
- const selectedCountryWidth = this.selectedCountry.offsetWidth || this._getHiddenSelectedCountryWidth() || saneDefaultWidth;
3299
- const inputPadding = selectedCountryWidth + 6;
3300
- this.telInput.style.paddingLeft = `${inputPadding}px`;
3301
- }
3302
- }
3303
3454
  //* Update the maximum valid number length for the currently selected country.
3304
3455
  _updateMaxLength() {
3305
3456
  const { strictMode, placeholderNumberType, validationNumberTypes } = this.options;
@@ -3314,7 +3465,11 @@ var Iti = class _Iti {
3314
3465
  true
3315
3466
  );
3316
3467
  let validNumber = exampleNumber;
3317
- while (intlTelInput.utils.isPossibleNumber(exampleNumber, iso2, validationNumberTypes)) {
3468
+ while (intlTelInput.utils.isPossibleNumber(
3469
+ exampleNumber,
3470
+ iso2,
3471
+ validationNumberTypes
3472
+ )) {
3318
3473
  validNumber = exampleNumber;
3319
3474
  exampleNumber += "0";
3320
3475
  }
@@ -3328,31 +3483,6 @@ var Iti = class _Iti {
3328
3483
  }
3329
3484
  }
3330
3485
  }
3331
- //* When input is in a hidden container during init, we cannot calculate the selected country width.
3332
- //* Fix: clone the markup, make it invisible, add it to the end of the DOM, and then measure it's width.
3333
- //* To get the right styling to apply, all we need is a shallow clone of the container,
3334
- //* and then to inject a deep clone of the selectedCountry element.
3335
- _getHiddenSelectedCountryWidth() {
3336
- if (this.telInput.parentNode) {
3337
- let body;
3338
- try {
3339
- body = window.top.document.body;
3340
- } catch (e) {
3341
- body = document.body;
3342
- }
3343
- const containerClone = this.telInput.parentNode.cloneNode(false);
3344
- containerClone.style.visibility = "hidden";
3345
- body.appendChild(containerClone);
3346
- const countryContainerClone = this.countryContainer.cloneNode();
3347
- containerClone.appendChild(countryContainerClone);
3348
- const selectedCountryClone = this.selectedCountry.cloneNode(true);
3349
- countryContainerClone.appendChild(selectedCountryClone);
3350
- const width = selectedCountryClone.offsetWidth;
3351
- body.removeChild(containerClone);
3352
- return width;
3353
- }
3354
- return 0;
3355
- }
3356
3486
  //* Update the input placeholder to an example number from the currently selected country.
3357
3487
  _updatePlaceholder() {
3358
3488
  const {
@@ -3361,7 +3491,7 @@ var Iti = class _Iti {
3361
3491
  nationalMode,
3362
3492
  customPlaceholder
3363
3493
  } = this.options;
3364
- const shouldSetPlaceholder = autoPlaceholder === "aggressive" || !this.hadInitialPlaceholder && autoPlaceholder === "polite";
3494
+ const shouldSetPlaceholder = autoPlaceholder === "aggressive" || !this.ui.hadInitialPlaceholder && autoPlaceholder === "polite";
3365
3495
  if (intlTelInput.utils && shouldSetPlaceholder) {
3366
3496
  const numberType = intlTelInput.utils.numberType[placeholderNumberType];
3367
3497
  let placeholder = this.selectedCountryData.iso2 ? intlTelInput.utils.getExampleNumber(
@@ -3373,98 +3503,66 @@ var Iti = class _Iti {
3373
3503
  if (typeof customPlaceholder === "function") {
3374
3504
  placeholder = customPlaceholder(placeholder, this.selectedCountryData);
3375
3505
  }
3376
- this.telInput.setAttribute("placeholder", placeholder);
3506
+ this.ui.telInput.setAttribute("placeholder", placeholder);
3377
3507
  }
3378
3508
  }
3379
3509
  //* Called when the user selects a list item from the dropdown.
3380
3510
  _selectListItem(listItem) {
3381
- const iso2 = listItem.getAttribute("data-country-code");
3511
+ const iso2 = listItem.dataset.countryCode;
3382
3512
  const countryChanged = this._setCountry(iso2);
3383
3513
  this._closeDropdown();
3384
- const dialCode = listItem.getAttribute("data-dial-code");
3514
+ const dialCode = listItem.dataset.dialCode;
3385
3515
  this._updateDialCode(dialCode);
3386
3516
  if (this.options.formatOnDisplay) {
3387
- this._updateValFromNumber(this.telInput.value);
3517
+ this._updateValFromNumber(this.ui.telInput.value);
3388
3518
  }
3389
- this.telInput.focus();
3519
+ this.ui.telInput.focus();
3390
3520
  if (countryChanged) {
3391
3521
  this._triggerCountryChange();
3392
3522
  }
3393
3523
  }
3394
3524
  //* Close the dropdown and unbind any listeners.
3395
3525
  _closeDropdown() {
3396
- this.dropdownContent.classList.add("iti__hide");
3397
- this.selectedCountry.setAttribute("aria-expanded", "false");
3398
- if (this.highlightedItem) {
3399
- this.highlightedItem.setAttribute("aria-selected", "false");
3526
+ if (this.ui.dropdownContent.classList.contains("iti__hide")) {
3527
+ return;
3400
3528
  }
3401
- if (this.options.countrySearch) {
3402
- this.searchInput.removeAttribute("aria-activedescendant");
3529
+ this.ui.dropdownContent.classList.add("iti__hide");
3530
+ this.ui.selectedCountry.setAttribute("aria-expanded", "false");
3531
+ if (this.ui.highlightedItem) {
3532
+ this.ui.highlightedItem.setAttribute("aria-selected", "false");
3403
3533
  }
3404
- this.dropdownArrow.classList.remove("iti__arrow--up");
3405
3534
  if (this.options.countrySearch) {
3406
- this.searchInput.removeEventListener("input", this._handleSearchChange);
3407
- this.searchClearButton.removeEventListener("click", this._handleSearchClear);
3535
+ this.ui.searchInput.removeAttribute("aria-activedescendant");
3408
3536
  }
3409
- document.removeEventListener("keydown", this._handleKeydownOnDropdown);
3410
- document.documentElement.removeEventListener(
3411
- "click",
3412
- this._handleClickOffToClose
3413
- );
3414
- this.countryList.removeEventListener(
3415
- "mouseover",
3416
- this._handleMouseoverCountryList
3417
- );
3418
- this.countryList.removeEventListener("click", this._handleClickCountryList);
3537
+ this.ui.dropdownArrow.classList.remove("iti__arrow--up");
3538
+ this.dropdownAbortController.abort();
3539
+ this.dropdownAbortController = null;
3419
3540
  if (this.options.dropdownContainer) {
3420
- if (!this.options.useFullscreenPopup) {
3421
- window.removeEventListener("scroll", this._handleWindowScroll);
3422
- }
3423
- if (this.dropdown.parentNode) {
3424
- this.dropdown.parentNode.removeChild(this.dropdown);
3425
- }
3541
+ this.ui.dropdown.remove();
3426
3542
  }
3427
3543
  this._trigger("close:countrydropdown");
3428
3544
  }
3429
- //* Check if an element is visible within it's container, else scroll until it is.
3430
- _scrollTo(element) {
3431
- const container = this.countryList;
3432
- const scrollTop = document.documentElement.scrollTop;
3433
- const containerHeight = container.offsetHeight;
3434
- const containerTop = container.getBoundingClientRect().top + scrollTop;
3435
- const containerBottom = containerTop + containerHeight;
3436
- const elementHeight = element.offsetHeight;
3437
- const elementTop = element.getBoundingClientRect().top + scrollTop;
3438
- const elementBottom = elementTop + elementHeight;
3439
- const newScrollTop = elementTop - containerTop + container.scrollTop;
3440
- if (elementTop < containerTop) {
3441
- container.scrollTop = newScrollTop;
3442
- } else if (elementBottom > containerBottom) {
3443
- const heightDifference = containerHeight - elementHeight;
3444
- container.scrollTop = newScrollTop - heightDifference;
3445
- }
3446
- }
3447
3545
  //* Replace any existing dial code with the new one
3448
3546
  //* Note: called from _selectListItem and setCountry
3449
3547
  _updateDialCode(newDialCodeBare) {
3450
- const inputVal = this.telInput.value;
3548
+ const inputVal = this.ui.telInput.value;
3451
3549
  const newDialCode = `+${newDialCodeBare}`;
3452
3550
  let newNumber;
3453
- if (inputVal.charAt(0) === "+") {
3551
+ if (inputVal.startsWith("+")) {
3454
3552
  const prevDialCode = this._getDialCode(inputVal);
3455
3553
  if (prevDialCode) {
3456
3554
  newNumber = inputVal.replace(prevDialCode, newDialCode);
3457
3555
  } else {
3458
3556
  newNumber = newDialCode;
3459
3557
  }
3460
- this.telInput.value = newNumber;
3558
+ this.ui.telInput.value = newNumber;
3461
3559
  }
3462
3560
  }
3463
3561
  //* Try and extract a valid international dial code from a full telephone number.
3464
3562
  //* Note: returns the raw string inc plus character and any whitespace/dots etc.
3465
3563
  _getDialCode(number, includeAreaCode) {
3466
3564
  let dialCode = "";
3467
- if (number.charAt(0) === "+") {
3565
+ if (number.startsWith("+")) {
3468
3566
  let numericChars = "";
3469
3567
  for (let i = 0; i < number.length; i++) {
3470
3568
  const c = number.charAt(i);
@@ -3490,11 +3588,11 @@ var Iti = class _Iti {
3490
3588
  }
3491
3589
  //* Get the input val, adding the dial code if separateDialCode is enabled.
3492
3590
  _getFullNumber(overrideVal) {
3493
- const val = overrideVal || this.telInput.value.trim();
3591
+ const val = overrideVal || this.ui.telInput.value.trim();
3494
3592
  const { dialCode } = this.selectedCountryData;
3495
3593
  let prefix;
3496
3594
  const numericVal = getNumeric(val);
3497
- if (this.options.separateDialCode && val.charAt(0) !== "+" && dialCode && numericVal) {
3595
+ if (this.options.separateDialCode && !val.startsWith("+") && dialCode && numericVal) {
3498
3596
  prefix = `+${dialCode}`;
3499
3597
  } else {
3500
3598
  prefix = "";
@@ -3523,7 +3621,7 @@ var Iti = class _Iti {
3523
3621
  handleAutoCountry() {
3524
3622
  if (this.options.initialCountry === "auto" && intlTelInput.autoCountry) {
3525
3623
  this.defaultCountry = intlTelInput.autoCountry;
3526
- const hasSelectedCountryOrGlobe = this.selectedCountryData.iso2 || this.selectedCountryInner.classList.contains("iti__globe");
3624
+ const hasSelectedCountryOrGlobe = this.selectedCountryData.iso2 || this.ui.selectedCountryInner.classList.contains("iti__globe");
3527
3625
  if (!hasSelectedCountryOrGlobe) {
3528
3626
  this.setCountry(this.defaultCountry);
3529
3627
  }
@@ -3533,8 +3631,8 @@ var Iti = class _Iti {
3533
3631
  //* This is called when the utils request completes.
3534
3632
  handleUtils() {
3535
3633
  if (intlTelInput.utils) {
3536
- if (this.telInput.value) {
3537
- this._updateValFromNumber(this.telInput.value);
3634
+ if (this.ui.telInput.value) {
3635
+ this._updateValFromNumber(this.ui.telInput.value);
3538
3636
  }
3539
3637
  if (this.selectedCountryData.iso2) {
3540
3638
  this._updatePlaceholder();
@@ -3548,45 +3646,20 @@ var Iti = class _Iti {
3548
3646
  //********************
3549
3647
  //* Remove plugin.
3550
3648
  destroy() {
3551
- this.telInput.iti = void 0;
3552
- const { allowDropdown, separateDialCode } = this.options;
3553
- if (allowDropdown) {
3554
- this._closeDropdown();
3555
- this.selectedCountry.removeEventListener(
3556
- "click",
3557
- this._handleClickSelectedCountry
3558
- );
3559
- this.countryContainer.removeEventListener(
3560
- "keydown",
3561
- this._handleCountryContainerKeydown
3562
- );
3563
- const label = this.telInput.closest("label");
3564
- if (label) {
3565
- label.removeEventListener("click", this._handleLabelClick);
3566
- }
3567
- }
3568
- const { form } = this.telInput;
3569
- if (this._handleHiddenInputSubmit && form) {
3570
- form.removeEventListener("submit", this._handleHiddenInputSubmit);
3571
- }
3572
- this.telInput.removeEventListener("input", this._handleInputEvent);
3573
- if (this._handleKeydownEvent) {
3574
- this.telInput.removeEventListener("keydown", this._handleKeydownEvent);
3575
- }
3576
- if (this._handlePasteEvent) {
3577
- this.telInput.removeEventListener("paste", this._handlePasteEvent);
3649
+ if (!this.ui.telInput) {
3650
+ return;
3578
3651
  }
3579
- if (this._handlePageLoad) {
3580
- window.removeEventListener("load", this._handlePageLoad);
3652
+ if (this.options.allowDropdown) {
3653
+ this._closeDropdown();
3581
3654
  }
3582
- this.telInput.removeAttribute("data-intl-tel-input-id");
3583
- if (separateDialCode) {
3584
- this.telInput.style.paddingLeft = this.originalPaddingLeft;
3655
+ this.abortController.abort();
3656
+ this.abortController = null;
3657
+ this.ui.destroy();
3658
+ if (intlTelInput.instances instanceof Map) {
3659
+ intlTelInput.instances.delete(this.id);
3660
+ } else {
3661
+ delete intlTelInput.instances[this.id];
3585
3662
  }
3586
- const wrapper = this.telInput.parentNode;
3587
- wrapper?.parentNode?.insertBefore(this.telInput, wrapper);
3588
- wrapper?.parentNode?.removeChild(wrapper);
3589
- delete intlTelInput.instances[this.id];
3590
3663
  }
3591
3664
  //* Get the extension from the current number.
3592
3665
  getExtension() {
@@ -3649,7 +3722,11 @@ var Iti = class _Iti {
3649
3722
  return this._validateNumber(true);
3650
3723
  }
3651
3724
  _utilsIsPossibleNumber(val) {
3652
- return intlTelInput.utils ? intlTelInput.utils.isPossibleNumber(val, this.selectedCountryData.iso2, this.options.validationNumberTypes) : null;
3725
+ return intlTelInput.utils ? intlTelInput.utils.isPossibleNumber(
3726
+ val,
3727
+ this.selectedCountryData.iso2,
3728
+ this.options.validationNumberTypes
3729
+ ) : null;
3653
3730
  }
3654
3731
  //* Shared internal validation logic to handle alpha character extension rules.
3655
3732
  _validateNumber(precise) {
@@ -3672,7 +3749,11 @@ var Iti = class _Iti {
3672
3749
  return testValidity(val);
3673
3750
  }
3674
3751
  _utilsIsValidNumber(val) {
3675
- return intlTelInput.utils ? intlTelInput.utils.isValidNumber(val, this.selectedCountryData.iso2, this.options.validationNumberTypes) : null;
3752
+ return intlTelInput.utils ? intlTelInput.utils.isValidNumber(
3753
+ val,
3754
+ this.selectedCountryData.iso2,
3755
+ this.options.validationNumberTypes
3756
+ ) : null;
3676
3757
  }
3677
3758
  //* Update the selected country, and update the input val accordingly.
3678
3759
  setCountry(iso2) {
@@ -3686,7 +3767,7 @@ var Iti = class _Iti {
3686
3767
  this._setCountry(iso2Lower);
3687
3768
  this._updateDialCode(this.selectedCountryData.dialCode);
3688
3769
  if (this.options.formatOnDisplay) {
3689
- this._updateValFromNumber(this.telInput.value);
3770
+ this._updateValFromNumber(this.ui.telInput.value);
3690
3771
  }
3691
3772
  this._triggerCountryChange();
3692
3773
  }
@@ -3706,11 +3787,11 @@ var Iti = class _Iti {
3706
3787
  this._updatePlaceholder();
3707
3788
  }
3708
3789
  setDisabled(disabled) {
3709
- this.telInput.disabled = disabled;
3790
+ this.ui.telInput.disabled = disabled;
3710
3791
  if (disabled) {
3711
- this.selectedCountry.setAttribute("disabled", "true");
3792
+ this.ui.selectedCountry.setAttribute("disabled", "true");
3712
3793
  } else {
3713
- this.selectedCountry.removeAttribute("disabled");
3794
+ this.ui.selectedCountry.removeAttribute("disabled");
3714
3795
  }
3715
3796
  }
3716
3797
  };
@@ -3724,13 +3805,19 @@ var attachUtils = (source) => {
3724
3805
  return Promise.reject(error);
3725
3806
  }
3726
3807
  } else {
3727
- return Promise.reject(new TypeError(`The argument passed to attachUtils must be a function that returns a promise for the utilities module, not ${typeof source}`));
3808
+ return Promise.reject(
3809
+ new TypeError(
3810
+ `The argument passed to attachUtils must be a function that returns a promise for the utilities module, not ${typeof source}`
3811
+ )
3812
+ );
3728
3813
  }
3729
3814
  intlTelInput.startedLoadingUtilsScript = true;
3730
3815
  return loadCall.then((module2) => {
3731
3816
  const utils = module2?.default;
3732
3817
  if (!utils || typeof utils !== "object") {
3733
- throw new TypeError("The loader function passed to attachUtils did not resolve to a module object with utils as its default export.");
3818
+ throw new TypeError(
3819
+ "The loader function passed to attachUtils did not resolve to a module object with utils as its default export."
3820
+ );
3734
3821
  }
3735
3822
  intlTelInput.utils = utils;
3736
3823
  forEachInstance("handleUtils");
@@ -3742,11 +3829,17 @@ var attachUtils = (source) => {
3742
3829
  }
3743
3830
  return null;
3744
3831
  };
3832
+ var forEachInstance = (method, ...args) => {
3833
+ Object.values(intlTelInput.instances).forEach((instance) => {
3834
+ const fn = instance[method];
3835
+ if (typeof fn === "function") {
3836
+ fn.apply(instance, args);
3837
+ }
3838
+ });
3839
+ };
3745
3840
  var intlTelInput = Object.assign(
3746
3841
  (input, options) => {
3747
3842
  const iti = new Iti(input, options);
3748
- iti._init();
3749
- input.setAttribute("data-intl-tel-input-id", iti.id.toString());
3750
3843
  intlTelInput.instances[iti.id] = iti;
3751
3844
  input.iti = iti;
3752
3845
  return iti;
@@ -3759,7 +3852,7 @@ var intlTelInput = Object.assign(
3759
3852
  getCountryData: () => data_default,
3760
3853
  //* A getter for the plugin instance.
3761
3854
  getInstance: (input) => {
3762
- const id2 = input.getAttribute("data-intl-tel-input-id");
3855
+ const id2 = input.dataset.intlTelInputId;
3763
3856
  return id2 ? intlTelInput.instances[id2] : null;
3764
3857
  },
3765
3858
  //* A map from instance ID to instance object.
@@ -3767,7 +3860,7 @@ var intlTelInput = Object.assign(
3767
3860
  attachUtils,
3768
3861
  startedLoadingUtilsScript: false,
3769
3862
  startedLoadingAutoCountry: false,
3770
- version: "25.10.12"
3863
+ version: "25.11.0"
3771
3864
  }
3772
3865
  );
3773
3866
  var intl_tel_input_default = intlTelInput;