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