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