intl-tel-input 25.10.12 → 25.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +62 -59
  2. package/angular/README.md +1 -1
  3. package/angular/build/IntlTelInput.js +887 -688
  4. package/angular/build/IntlTelInputWithUtils.js +891 -692
  5. package/angular/build/types/intl-tel-input/data.d.ts +3 -3
  6. package/angular/build/types/intl-tel-input.d.ts +22 -70
  7. package/angular/build/types/modules/constants.d.ts +84 -0
  8. package/angular/build/types/modules/core/countrySearch.d.ts +17 -0
  9. package/angular/build/types/modules/core/icons.d.ts +7 -0
  10. package/angular/build/types/modules/core/options.d.ts +2 -1
  11. package/angular/build/types/modules/core/ui.d.ts +44 -0
  12. package/angular/build/types/modules/data/country-data.d.ts +5 -5
  13. package/angular/build/types/modules/format/caret.d.ts +1 -1
  14. package/angular/build/types/modules/format/formatting.d.ts +3 -3
  15. package/angular/build/types/modules/types/events.d.ts +9 -0
  16. package/angular/build/types/modules/types/public-api.d.ts +3 -0
  17. package/angular/build/types/modules/utils/dom.d.ts +5 -0
  18. package/build/js/data.js +8 -2
  19. package/build/js/data.min.js +2 -2
  20. package/build/js/intlTelInput.d.ts +214 -83
  21. package/build/js/intlTelInput.js +1034 -770
  22. package/build/js/intlTelInput.min.js +13 -13
  23. package/build/js/intlTelInputWithUtils.js +1038 -774
  24. package/build/js/intlTelInputWithUtils.min.js +13 -13
  25. package/build/js/utils.js +4 -4
  26. package/package.json +3 -1
  27. package/react/README.md +1 -1
  28. package/react/build/IntlTelInput.cjs +1033 -769
  29. package/react/build/IntlTelInput.d.ts +214 -83
  30. package/react/build/IntlTelInput.js +1033 -769
  31. package/react/build/IntlTelInputWithUtils.cjs +1037 -773
  32. package/react/build/IntlTelInputWithUtils.js +1037 -773
  33. package/vue/README.md +1 -1
  34. package/vue/build/IntlTelInput.mjs +967 -739
  35. package/vue/build/IntlTelInputWithUtils.mjs +1279 -1051
@@ -1724,7 +1724,13 @@ for (const c of rawCountryData) {
1724
1724
  areaCodes: c[3] || null,
1725
1725
  nodeById: {},
1726
1726
  // populated by the plugin
1727
- nationalPrefix: c[4] || null
1727
+ nationalPrefix: c[4] || null,
1728
+ normalisedName: "",
1729
+ // populated in the plugin
1730
+ initials: "",
1731
+ // populated in the plugin
1732
+ dialCodePlus: ""
1733
+ // populated in the plugin
1728
1734
  });
1729
1735
  }
1730
1736
  var data_default = allCountries;
@@ -1996,13 +2002,111 @@ var interface_default = interfaceTranslations;
1996
2002
  var allTranslations = { ...countries_default, ...interface_default };
1997
2003
  var en_default = allTranslations;
1998
2004
 
1999
- // src/js/modules/core/options.ts
2000
- var mq = (q) => {
2001
- return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(q).matches;
2005
+ // src/js/modules/constants.ts
2006
+ var EVENTS = {
2007
+ OPEN_COUNTRY_DROPDOWN: "open:countrydropdown",
2008
+ CLOSE_COUNTRY_DROPDOWN: "close:countrydropdown",
2009
+ COUNTRY_CHANGE: "countrychange",
2010
+ INPUT: "input"
2011
+ // used for synthetic input trigger
2012
+ };
2013
+ var CLASSES = {
2014
+ HIDE: "iti__hide",
2015
+ V_HIDE: "iti__v-hide",
2016
+ ARROW_UP: "iti__arrow--up",
2017
+ GLOBE: "iti__globe",
2018
+ FLAG: "iti__flag",
2019
+ COUNTRY_ITEM: "iti__country",
2020
+ HIGHLIGHT: "iti__highlight"
2021
+ };
2022
+ var KEYS = {
2023
+ ARROW_UP: "ArrowUp",
2024
+ ARROW_DOWN: "ArrowDown",
2025
+ SPACE: " ",
2026
+ ENTER: "Enter",
2027
+ ESC: "Escape",
2028
+ TAB: "Tab"
2029
+ };
2030
+ var INPUT_TYPES = {
2031
+ PASTE: "insertFromPaste",
2032
+ DELETE_FWD: "deleteContentForward"
2033
+ };
2034
+ var REGEX = {
2035
+ ALPHA_UNICODE: /\p{L}/u,
2036
+ // any kind of letter from any language
2037
+ NON_PLUS_NUMERIC: /[^+0-9]/,
2038
+ // chars that are NOT + or digit
2039
+ NON_PLUS_NUMERIC_GLOBAL: /[^+0-9]/g,
2040
+ // chars that are NOT + or digit (global)
2041
+ HIDDEN_SEARCH_CHAR: /^[a-zA-ZÀ-ÿа-яА-Я ]$/
2042
+ // single acceptable hidden-search char
2043
+ };
2044
+ var TIMINGS = {
2045
+ SEARCH_DEBOUNCE_MS: 100,
2046
+ HIDDEN_SEARCH_RESET_MS: 1e3,
2047
+ NEXT_TICK: 0
2048
+ };
2049
+ var SENTINELS = {
2050
+ UNKNOWN_NUMBER_TYPE: -99,
2051
+ UNKNOWN_VALIDATION_ERROR: -99
2052
+ };
2053
+ var LAYOUT = {
2054
+ SANE_SELECTED_WITH_DIAL_WIDTH: 78,
2055
+ // px width fallback when separateDialCode enabled
2056
+ SANE_SELECTED_NO_DIAL_WIDTH: 42,
2057
+ // px width fallback when no separate dial code
2058
+ INPUT_PADDING_EXTRA_LEFT: 6
2059
+ // px gap between selected country container and input text
2060
+ };
2061
+ var DIAL = {
2062
+ PLUS: "+",
2063
+ NANP: "1"
2064
+ // North American Numbering Plan
2065
+ };
2066
+ var UK = {
2067
+ ISO2: "gb",
2068
+ DIAL_CODE: "44",
2069
+ // +44 United Kingdom
2070
+ MOBILE_PREFIX: "7",
2071
+ // UK mobile numbers start with 7 after national trunk (0) or core section
2072
+ MOBILE_CORE_LENGTH: 10
2073
+ // core number length (excluding dial code / national prefix) for mobiles
2074
+ };
2075
+ var US = {
2076
+ ISO2: "us",
2077
+ DIAL_CODE: "1"
2078
+ // +1 United States
2079
+ };
2080
+ var PLACEHOLDER_MODES = {
2081
+ AGGRESSIVE: "aggressive",
2082
+ POLITE: "polite"
2083
+ };
2084
+ var INITIAL_COUNTRY = {
2085
+ AUTO: "auto"
2002
2086
  };
2087
+ var DATA_KEYS = {
2088
+ COUNTRY_CODE: "countryCode",
2089
+ DIAL_CODE: "dialCode"
2090
+ };
2091
+ var ARIA = {
2092
+ EXPANDED: "aria-expanded",
2093
+ LABEL: "aria-label",
2094
+ SELECTED: "aria-selected",
2095
+ ACTIVE_DESCENDANT: "aria-activedescendant",
2096
+ HASPOPUP: "aria-haspopup",
2097
+ CONTROLS: "aria-controls",
2098
+ HIDDEN: "aria-hidden",
2099
+ AUTOCOMPLETE: "aria-autocomplete",
2100
+ MODAL: "aria-modal"
2101
+ };
2102
+
2103
+ // src/js/modules/core/options.ts
2104
+ var mq = (q) => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(q).matches;
2003
2105
  var computeDefaultUseFullscreenPopup = () => {
2004
2106
  if (typeof navigator !== "undefined" && typeof window !== "undefined") {
2005
- const isMobileUserAgent = /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
2107
+ const isMobileUserAgent = /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
2108
+ navigator.userAgent
2109
+ );
2006
2110
  const isNarrowViewport = mq("(max-width: 500px)");
2007
2111
  const isShortViewport = mq("(max-height: 600px)");
2008
2112
  const isCoarsePointer = mq("(pointer: coarse)");
@@ -2016,7 +2120,7 @@ var defaults = {
2016
2120
  //* Whether or not to allow the dropdown.
2017
2121
  allowDropdown: true,
2018
2122
  //* Add a placeholder in the input with an example number for the selected country.
2019
- autoPlaceholder: "polite",
2123
+ autoPlaceholder: PLACEHOLDER_MODES.POLITE,
2020
2124
  //* Modify the parentClass.
2021
2125
  containerClass: "",
2022
2126
  //* The order of the countries in the dropdown. Defaults to alphabetical.
@@ -2062,7 +2166,7 @@ var defaults = {
2062
2166
  //* The number type to enforce during validation.
2063
2167
  validationNumberTypes: ["MOBILE"]
2064
2168
  };
2065
- function applyOptionSideEffects(o) {
2169
+ var applyOptionSideEffects = (o, defaultEnglishStrings) => {
2066
2170
  if (o.useFullscreenPopup) {
2067
2171
  o.fixDropdownWidth = false;
2068
2172
  }
@@ -2078,18 +2182,66 @@ function applyOptionSideEffects(o) {
2078
2182
  if (o.useFullscreenPopup && !o.dropdownContainer) {
2079
2183
  o.dropdownContainer = document.body;
2080
2184
  }
2081
- o.i18n = { ...en_default, ...o.i18n };
2082
- }
2185
+ o.i18n = { ...defaultEnglishStrings, ...o.i18n };
2186
+ };
2083
2187
 
2084
2188
  // src/js/modules/utils/string.ts
2085
2189
  var getNumeric = (s) => s.replace(/\D/g, "");
2086
2190
  var normaliseString = (s = "") => s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
2087
2191
 
2192
+ // src/js/modules/core/countrySearch.ts
2193
+ var getMatchedCountries = (countries, query) => {
2194
+ const normalisedQuery = normaliseString(query);
2195
+ const iso2Matches = [];
2196
+ const nameStartWith = [];
2197
+ const nameContains = [];
2198
+ const dialCodeMatches = [];
2199
+ const dialCodeContains = [];
2200
+ const initialsMatches = [];
2201
+ for (const c of countries) {
2202
+ if (c.iso2 === normalisedQuery) {
2203
+ iso2Matches.push(c);
2204
+ } else if (c.normalisedName.startsWith(normalisedQuery)) {
2205
+ nameStartWith.push(c);
2206
+ } else if (c.normalisedName.includes(normalisedQuery)) {
2207
+ nameContains.push(c);
2208
+ } else if (normalisedQuery === c.dialCode || normalisedQuery === c.dialCodePlus) {
2209
+ dialCodeMatches.push(c);
2210
+ } else if (c.dialCodePlus.includes(normalisedQuery)) {
2211
+ dialCodeContains.push(c);
2212
+ } else if (c.initials.includes(normalisedQuery)) {
2213
+ initialsMatches.push(c);
2214
+ }
2215
+ }
2216
+ const sortByPriority = (a, b) => a.priority - b.priority;
2217
+ return [
2218
+ ...iso2Matches.sort(sortByPriority),
2219
+ ...nameStartWith.sort(sortByPriority),
2220
+ ...nameContains.sort(sortByPriority),
2221
+ ...dialCodeMatches.sort(sortByPriority),
2222
+ ...dialCodeContains.sort(sortByPriority),
2223
+ ...initialsMatches.sort(sortByPriority)
2224
+ ];
2225
+ };
2226
+ var findFirstCountryStartingWith = (countries, query) => {
2227
+ const lowerQuery = query.toLowerCase();
2228
+ for (const c of countries) {
2229
+ const lowerName = c.name.toLowerCase();
2230
+ if (lowerName.startsWith(lowerQuery)) {
2231
+ return c;
2232
+ }
2233
+ }
2234
+ return null;
2235
+ };
2236
+
2088
2237
  // src/js/modules/utils/dom.ts
2238
+ var buildClassNames = (flags) => Object.keys(flags).filter((k) => Boolean(flags[k])).join(" ");
2089
2239
  var createEl = (tagName, attrs, container) => {
2090
2240
  const el = document.createElement(tagName);
2091
2241
  if (attrs) {
2092
- Object.entries(attrs).forEach(([key, value]) => el.setAttribute(key, value));
2242
+ Object.entries(attrs).forEach(
2243
+ ([key, value]) => el.setAttribute(key, value)
2244
+ );
2093
2245
  }
2094
2246
  if (container) {
2095
2247
  container.appendChild(el);
@@ -2097,251 +2249,41 @@ var createEl = (tagName, attrs, container) => {
2097
2249
  return el;
2098
2250
  };
2099
2251
 
2100
- // src/js/modules/data/country-data.ts
2101
- function processAllCountries(options) {
2102
- const { onlyCountries, excludeCountries } = options;
2103
- if (onlyCountries.length) {
2104
- const lowerCaseOnlyCountries = onlyCountries.map((country) => country.toLowerCase());
2105
- return data_default.filter((country) => lowerCaseOnlyCountries.includes(country.iso2));
2106
- } else if (excludeCountries.length) {
2107
- const lowerCaseExcludeCountries = excludeCountries.map((country) => country.toLowerCase());
2108
- return data_default.filter((country) => !lowerCaseExcludeCountries.includes(country.iso2));
2109
- }
2110
- return data_default;
2111
- }
2112
- function translateCountryNames(countries, options) {
2113
- for (const c of countries) {
2114
- const iso2 = c.iso2.toLowerCase();
2115
- if (options.i18n[iso2]) {
2116
- c.name = options.i18n[iso2];
2117
- }
2118
- }
2119
- }
2120
- function processDialCodes(countries, options) {
2121
- const dialCodes = /* @__PURE__ */ new Set();
2122
- let dialCodeMaxLen = 0;
2123
- const dialCodeToIso2Map = {};
2124
- const _addToDialCodeMap = (iso2, dialCode, priority) => {
2125
- if (!iso2 || !dialCode) {
2126
- return;
2127
- }
2128
- if (dialCode.length > dialCodeMaxLen) {
2129
- dialCodeMaxLen = dialCode.length;
2130
- }
2131
- if (!dialCodeToIso2Map.hasOwnProperty(dialCode)) {
2132
- dialCodeToIso2Map[dialCode] = [];
2133
- }
2134
- const iso2List = dialCodeToIso2Map[dialCode];
2135
- if (iso2List.includes(iso2)) {
2136
- return;
2137
- }
2138
- const index = priority !== void 0 ? priority : iso2List.length;
2139
- iso2List[index] = iso2;
2140
- };
2141
- for (const c of countries) {
2142
- if (!dialCodes.has(c.dialCode)) {
2143
- dialCodes.add(c.dialCode);
2144
- }
2145
- for (let k = 1; k < c.dialCode.length; k++) {
2146
- const partialDialCode = c.dialCode.substring(0, k);
2147
- _addToDialCodeMap(c.iso2, partialDialCode);
2148
- }
2149
- _addToDialCodeMap(c.iso2, c.dialCode, c.priority);
2150
- }
2151
- if (options.onlyCountries.length || options.excludeCountries.length) {
2152
- dialCodes.forEach((dialCode) => {
2153
- dialCodeToIso2Map[dialCode] = dialCodeToIso2Map[dialCode].filter(Boolean);
2154
- });
2155
- }
2156
- for (const c of countries) {
2157
- if (c.areaCodes) {
2158
- const rootIso2Code = dialCodeToIso2Map[c.dialCode][0];
2159
- for (const areaCode of c.areaCodes) {
2160
- for (let k = 1; k < areaCode.length; k++) {
2161
- const partialAreaCode = areaCode.substring(0, k);
2162
- const partialDialCode = c.dialCode + partialAreaCode;
2163
- _addToDialCodeMap(rootIso2Code, partialDialCode);
2164
- _addToDialCodeMap(c.iso2, partialDialCode);
2165
- }
2166
- _addToDialCodeMap(c.iso2, c.dialCode + areaCode);
2167
- }
2168
- }
2169
- }
2170
- return { dialCodes, dialCodeMaxLen, dialCodeToIso2Map };
2171
- }
2172
- function sortCountries(countries, options) {
2173
- if (options.countryOrder) {
2174
- options.countryOrder = options.countryOrder.map((iso2) => iso2.toLowerCase());
2175
- }
2176
- countries.sort((a, b) => {
2177
- const { countryOrder } = options;
2178
- if (countryOrder) {
2179
- const aIndex = countryOrder.indexOf(a.iso2);
2180
- const bIndex = countryOrder.indexOf(b.iso2);
2181
- const aIndexExists = aIndex > -1;
2182
- const bIndexExists = bIndex > -1;
2183
- if (aIndexExists || bIndexExists) {
2184
- if (aIndexExists && bIndexExists) {
2185
- return aIndex - bIndex;
2186
- }
2187
- return aIndexExists ? -1 : 1;
2188
- }
2189
- }
2190
- return a.name.localeCompare(b.name);
2191
- });
2192
- }
2193
- function cacheSearchTokens(countries) {
2194
- for (const c of countries) {
2195
- c.normalisedName = normaliseString(c.name);
2196
- c.initials = c.name.split(/[^a-zA-ZÀ-ÿа-яА-Я]/).map((word) => word[0]).join("").toLowerCase();
2197
- c.dialCodePlus = `+${c.dialCode}`;
2198
- }
2199
- }
2200
-
2201
- // src/js/modules/format/formatting.ts
2202
- function beforeSetNumber(fullNumber, dialCode, separateDialCode, selectedCountryData) {
2203
- let number = fullNumber;
2204
- if (separateDialCode) {
2205
- if (dialCode) {
2206
- dialCode = `+${selectedCountryData.dialCode}`;
2207
- const start = number[dialCode.length] === " " || number[dialCode.length] === "-" ? dialCode.length + 1 : dialCode.length;
2208
- number = number.substring(start);
2209
- }
2210
- }
2211
- return number;
2212
- }
2213
- function formatNumberAsYouType(fullNumber, telInputValue, utils, selectedCountryData, separateDialCode) {
2214
- const result = utils ? utils.formatNumberAsYouType(fullNumber, selectedCountryData.iso2) : fullNumber;
2215
- const { dialCode } = selectedCountryData;
2216
- if (separateDialCode && telInputValue.charAt(0) !== "+" && result.includes(`+${dialCode}`)) {
2217
- const afterDialCode = result.split(`+${dialCode}`)[1] || "";
2218
- return afterDialCode.trim();
2219
- }
2220
- return result;
2221
- }
2222
-
2223
- // src/js/modules/format/caret.ts
2224
- function translateCursorPosition(relevantChars, formattedValue, prevCaretPos, isDeleteForwards) {
2225
- if (prevCaretPos === 0 && !isDeleteForwards) {
2226
- return 0;
2227
- }
2228
- let relevantCharCount = 0;
2229
- for (let i = 0; i < formattedValue.length; i++) {
2230
- if (/[+0-9]/.test(formattedValue[i])) {
2231
- relevantCharCount++;
2232
- }
2233
- if (relevantCharCount === relevantChars && !isDeleteForwards) {
2234
- return i + 1;
2235
- }
2236
- if (isDeleteForwards && relevantCharCount === relevantChars + 1) {
2237
- return i;
2238
- }
2239
- }
2240
- return formattedValue.length;
2241
- }
2242
-
2243
- // src/js/modules/data/nanp-regionless.ts
2244
- var regionlessNanpNumbers = [
2245
- "800",
2246
- "822",
2247
- "833",
2248
- "844",
2249
- "855",
2250
- "866",
2251
- "877",
2252
- "880",
2253
- "881",
2254
- "882",
2255
- "883",
2256
- "884",
2257
- "885",
2258
- "886",
2259
- "887",
2260
- "888",
2261
- "889"
2262
- ];
2263
- var isRegionlessNanp = (number) => {
2264
- const numeric = getNumeric(number);
2265
- if (numeric.charAt(0) === "1") {
2266
- const areaCode = numeric.substring(1, 4);
2267
- return regionlessNanpNumbers.includes(areaCode);
2268
- }
2269
- return false;
2252
+ // src/js/modules/core/icons.ts
2253
+ var buildSearchIcon = () => `
2254
+ <svg class="iti__search-icon-svg" width="14" height="14" viewBox="0 0 24 24" focusable="false" ${ARIA.HIDDEN}="true">
2255
+ <circle cx="11" cy="11" r="7" />
2256
+ <line x1="21" y1="21" x2="16.65" y2="16.65" />
2257
+ </svg>`;
2258
+ var buildClearIcon = (id2) => {
2259
+ const maskId = `iti-${id2}-clear-mask`;
2260
+ return `
2261
+ <svg class="iti__search-clear-svg" width="12" height="12" viewBox="0 0 16 16" ${ARIA.HIDDEN}="true" focusable="false">
2262
+ <mask id="${maskId}" maskUnits="userSpaceOnUse">
2263
+ <rect width="16" height="16" fill="white" />
2264
+ <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" />
2265
+ </mask>
2266
+ <circle cx="8" cy="8" r="8" class="iti__search-clear-bg" mask="url(#${maskId})" />
2267
+ </svg>`;
2270
2268
  };
2271
2269
 
2272
- // src/js/intl-tel-input.ts
2273
- for (const c of data_default) {
2274
- c.name = en_default[c.iso2];
2275
- }
2276
- var id = 0;
2277
- var iso2Set = new Set(data_default.map((c) => c.iso2));
2278
- var isIso2 = (val) => iso2Set.has(val);
2279
- var forEachInstance = (method, ...args) => {
2280
- const { instances } = intlTelInput;
2281
- Object.values(instances).forEach((instance) => instance[method](...args));
2282
- };
2283
- var Iti = class _Iti {
2284
- /**
2285
- * Build a space-delimited class string from an object map of className -> truthy/falsey.
2286
- * Only keys with truthy values are included.
2287
- */
2288
- static _buildClassNames(flags) {
2289
- return Object.keys(flags).filter((k) => Boolean(flags[k])).join(" ");
2290
- }
2291
- constructor(input, customOptions = {}) {
2292
- this.id = id++;
2293
- this.telInput = input;
2270
+ // src/js/modules/core/ui.ts
2271
+ var UI = class {
2272
+ constructor(input, options, id2) {
2294
2273
  this.highlightedItem = null;
2295
- this.options = Object.assign({}, defaults, customOptions);
2274
+ input.dataset.intlTelInputId = id2.toString();
2275
+ this.telInput = input;
2276
+ this.options = options;
2277
+ this.id = id2;
2296
2278
  this.hadInitialPlaceholder = Boolean(input.getAttribute("placeholder"));
2297
- }
2298
- _detectEnvironmentAndLayout() {
2299
- this.isAndroid = typeof navigator !== "undefined" ? /Android/i.test(navigator.userAgent) : false;
2300
2279
  this.isRTL = !!this.telInput.closest("[dir=rtl]");
2301
2280
  if (this.options.separateDialCode) {
2302
2281
  this.originalPaddingLeft = this.telInput.style.paddingLeft;
2303
2282
  }
2304
2283
  }
2305
- _createInitPromises() {
2306
- const autoCountryPromise = new Promise((resolve, reject) => {
2307
- this.resolveAutoCountryPromise = resolve;
2308
- this.rejectAutoCountryPromise = reject;
2309
- });
2310
- const utilsScriptPromise = new Promise((resolve, reject) => {
2311
- this.resolveUtilsScriptPromise = resolve;
2312
- this.rejectUtilsScriptPromise = reject;
2313
- });
2314
- this.promise = Promise.all([autoCountryPromise, utilsScriptPromise]);
2315
- }
2316
- //* Can't be private as it's called from intlTelInput convenience wrapper.
2317
- _init() {
2318
- applyOptionSideEffects(this.options);
2319
- this._detectEnvironmentAndLayout();
2320
- this._createInitPromises();
2321
- this.selectedCountryData = {};
2322
- this._processCountryData();
2323
- this._generateMarkup();
2324
- this._setInitialState();
2325
- this._initListeners();
2326
- this._initRequests();
2327
- }
2328
- //********************
2329
- //* PRIVATE METHODS
2330
- //********************
2331
- //* Prepare all of the country data, including onlyCountries, excludeCountries, countryOrder options.
2332
- _processCountryData() {
2333
- this.countries = processAllCountries(this.options);
2334
- const dialRes = processDialCodes(this.countries, this.options);
2335
- this.dialCodes = dialRes.dialCodes;
2336
- this.dialCodeMaxLen = dialRes.dialCodeMaxLen;
2337
- this.dialCodeToIso2Map = dialRes.dialCodeToIso2Map;
2338
- translateCountryNames(this.countries, this.options);
2339
- sortCountries(this.countries, this.options);
2340
- this.countryByIso2 = new Map(this.countries.map((c) => [c.iso2, c]));
2341
- cacheSearchTokens(this.countries);
2342
- }
2343
2284
  //* Generate all of the markup for the plugin: the selected country overlay, and the dropdown.
2344
- _generateMarkup() {
2285
+ generateMarkup(countries) {
2286
+ this.countries = countries;
2345
2287
  this._prepareTelInput();
2346
2288
  const wrapper = this._createWrapperAndInsert();
2347
2289
  this._maybeBuildCountryContainer(wrapper);
@@ -2351,19 +2293,14 @@ var Iti = class _Iti {
2351
2293
  }
2352
2294
  _prepareTelInput() {
2353
2295
  this.telInput.classList.add("iti__tel-input");
2354
- if (!this.telInput.hasAttribute("autocomplete") && !(this.telInput.form && this.telInput.form.hasAttribute("autocomplete"))) {
2296
+ if (!this.telInput.hasAttribute("autocomplete") && !this.telInput.form?.hasAttribute("autocomplete")) {
2355
2297
  this.telInput.setAttribute("autocomplete", "off");
2356
2298
  }
2357
2299
  }
2358
2300
  _createWrapperAndInsert() {
2359
- const {
2360
- allowDropdown,
2361
- showFlags,
2362
- containerClass,
2363
- useFullscreenPopup
2364
- } = this.options;
2365
- const parentClasses = _Iti._buildClassNames({
2366
- "iti": true,
2301
+ const { allowDropdown, showFlags, containerClass, useFullscreenPopup } = this.options;
2302
+ const parentClasses = buildClassNames({
2303
+ iti: true,
2367
2304
  "iti--allow-dropdown": allowDropdown,
2368
2305
  "iti--show-flags": showFlags,
2369
2306
  "iti--inline-dropdown": !useFullscreenPopup,
@@ -2373,20 +2310,16 @@ var Iti = class _Iti {
2373
2310
  if (this.isRTL) {
2374
2311
  wrapper.setAttribute("dir", "ltr");
2375
2312
  }
2376
- this.telInput.parentNode?.insertBefore(wrapper, this.telInput);
2313
+ this.telInput.before(wrapper);
2377
2314
  return wrapper;
2378
2315
  }
2379
2316
  _maybeBuildCountryContainer(wrapper) {
2380
- const {
2381
- allowDropdown,
2382
- separateDialCode,
2383
- showFlags
2384
- } = this.options;
2317
+ const { allowDropdown, separateDialCode, showFlags } = this.options;
2385
2318
  if (allowDropdown || showFlags || separateDialCode) {
2386
2319
  this.countryContainer = createEl(
2387
2320
  "div",
2388
2321
  // visibly hidden until we measure it's width to set the input padding correctly
2389
- { class: "iti__country-container iti__v-hide" },
2322
+ { class: `iti__country-container ${CLASSES.V_HIDE}` },
2390
2323
  wrapper
2391
2324
  );
2392
2325
  if (allowDropdown) {
@@ -2395,10 +2328,10 @@ var Iti = class _Iti {
2395
2328
  {
2396
2329
  type: "button",
2397
2330
  class: "iti__selected-country",
2398
- "aria-expanded": "false",
2399
- "aria-label": this.options.i18n.noCountrySelected,
2400
- "aria-haspopup": "dialog",
2401
- "aria-controls": `iti-${this.id}__dropdown-content`
2331
+ [ARIA.EXPANDED]: "false",
2332
+ [ARIA.LABEL]: this.options.i18n.noCountrySelected,
2333
+ [ARIA.HASPOPUP]: "dialog",
2334
+ [ARIA.CONTROLS]: `iti-${this.id}__dropdown-content`
2402
2335
  },
2403
2336
  this.countryContainer
2404
2337
  );
@@ -2419,13 +2352,13 @@ var Iti = class _Iti {
2419
2352
  );
2420
2353
  this.selectedCountryInner = createEl(
2421
2354
  "div",
2422
- { class: "iti__flag" },
2355
+ { class: CLASSES.FLAG },
2423
2356
  selectedCountryPrimary
2424
2357
  );
2425
2358
  if (allowDropdown) {
2426
2359
  this.dropdownArrow = createEl(
2427
2360
  "div",
2428
- { class: "iti__arrow", "aria-hidden": "true" },
2361
+ { class: "iti__arrow", [ARIA.HIDDEN]: "true" },
2429
2362
  selectedCountryPrimary
2430
2363
  );
2431
2364
  }
@@ -2453,9 +2386,9 @@ var Iti = class _Iti {
2453
2386
  const extraClasses = fixDropdownWidth ? "" : "iti--flexible-dropdown-width";
2454
2387
  this.dropdownContent = createEl("div", {
2455
2388
  id: `iti-${this.id}__dropdown-content`,
2456
- class: `iti__dropdown-content iti__hide ${extraClasses}`,
2389
+ class: `iti__dropdown-content ${CLASSES.HIDE} ${extraClasses}`,
2457
2390
  role: "dialog",
2458
- "aria-modal": "true"
2391
+ [ARIA.MODAL]: "true"
2459
2392
  });
2460
2393
  if (this.isRTL) {
2461
2394
  this.dropdownContent.setAttribute("dir", "rtl");
@@ -2469,17 +2402,17 @@ var Iti = class _Iti {
2469
2402
  class: "iti__country-list",
2470
2403
  id: `iti-${this.id}__country-listbox`,
2471
2404
  role: "listbox",
2472
- "aria-label": i18n.countryListAriaLabel
2405
+ [ARIA.LABEL]: i18n.countryListAriaLabel
2473
2406
  },
2474
2407
  this.dropdownContent
2475
2408
  );
2476
2409
  this._appendListItems();
2477
2410
  if (countrySearch) {
2478
- this._updateSearchResultsA11yText();
2411
+ this.updateSearchResultsA11yText();
2479
2412
  }
2480
2413
  if (dropdownContainer) {
2481
- const dropdownClasses = _Iti._buildClassNames({
2482
- "iti": true,
2414
+ const dropdownClasses = buildClassNames({
2415
+ iti: true,
2483
2416
  "iti--container": true,
2484
2417
  "iti--fullscreen-popup": useFullscreenPopup,
2485
2418
  "iti--inline-dropdown": !useFullscreenPopup,
@@ -2502,15 +2435,11 @@ var Iti = class _Iti {
2502
2435
  "span",
2503
2436
  {
2504
2437
  class: "iti__search-icon",
2505
- "aria-hidden": "true"
2438
+ [ARIA.HIDDEN]: "true"
2506
2439
  },
2507
2440
  searchWrapper
2508
2441
  );
2509
- this.searchIcon.innerHTML = `
2510
- <svg class="iti__search-icon-svg" width="14" height="14" viewBox="0 0 24 24" focusable="false" aria-hidden="true">
2511
- <circle cx="11" cy="11" r="7" />
2512
- <line x1="21" y1="21" x2="16.65" y2="16.65" />
2513
- </svg>`;
2442
+ this.searchIcon.innerHTML = buildSearchIcon();
2514
2443
  this.searchInput = createEl(
2515
2444
  "input",
2516
2445
  {
@@ -2521,11 +2450,11 @@ var Iti = class _Iti {
2521
2450
  placeholder: i18n.searchPlaceholder,
2522
2451
  // 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
2523
2452
  role: "combobox",
2524
- "aria-expanded": "true",
2525
- "aria-label": i18n.searchPlaceholder,
2526
- "aria-controls": `iti-${this.id}__country-listbox`,
2527
- "aria-autocomplete": "list",
2528
- "autocomplete": "off"
2453
+ [ARIA.EXPANDED]: "true",
2454
+ [ARIA.LABEL]: i18n.searchPlaceholder,
2455
+ [ARIA.CONTROLS]: `iti-${this.id}__country-listbox`,
2456
+ [ARIA.AUTOCOMPLETE]: "list",
2457
+ autocomplete: "off"
2529
2458
  },
2530
2459
  searchWrapper
2531
2460
  );
@@ -2533,21 +2462,13 @@ var Iti = class _Iti {
2533
2462
  "button",
2534
2463
  {
2535
2464
  type: "button",
2536
- class: "iti__search-clear iti__hide",
2537
- "aria-label": i18n.clearSearchAriaLabel,
2465
+ class: `iti__search-clear ${CLASSES.HIDE}`,
2466
+ [ARIA.LABEL]: i18n.clearSearchAriaLabel,
2538
2467
  tabindex: "-1"
2539
2468
  },
2540
2469
  searchWrapper
2541
2470
  );
2542
- const maskId = `iti-${this.id}-clear-mask`;
2543
- this.searchClearButton.innerHTML = `
2544
- <svg class="iti__search-clear-svg" width="12" height="12" viewBox="0 0 16 16" aria-hidden="true" focusable="false">
2545
- <mask id="${maskId}" maskUnits="userSpaceOnUse">
2546
- <rect width="16" height="16" fill="white" />
2547
- <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" />
2548
- </mask>
2549
- <circle cx="8" cy="8" r="8" class="iti__search-clear-bg" mask="url(#${maskId})" />
2550
- </svg>`;
2471
+ this.searchClearButton.innerHTML = buildClearIcon(this.id);
2551
2472
  this.searchResultsA11yText = createEl(
2552
2473
  "span",
2553
2474
  { class: "iti__a11y-text" },
@@ -2556,91 +2477,496 @@ var Iti = class _Iti {
2556
2477
  this.searchNoResults = createEl(
2557
2478
  "div",
2558
2479
  {
2559
- class: "iti__no-results iti__hide",
2560
- "aria-hidden": "true"
2480
+ class: `iti__no-results ${CLASSES.HIDE}`,
2481
+ [ARIA.HIDDEN]: "true"
2561
2482
  // all a11y messaging happens in this.searchResultsA11yText
2562
2483
  },
2563
2484
  this.dropdownContent
2564
2485
  );
2565
- this.searchNoResults.textContent = i18n.zeroSearchResults;
2486
+ this.searchNoResults.textContent = i18n.zeroSearchResults;
2487
+ }
2488
+ _maybeUpdateInputPaddingAndReveal() {
2489
+ if (this.countryContainer) {
2490
+ this.updateInputPadding();
2491
+ this.countryContainer.classList.remove(CLASSES.V_HIDE);
2492
+ }
2493
+ }
2494
+ _maybeBuildHiddenInputs(wrapper) {
2495
+ const { hiddenInput } = this.options;
2496
+ if (hiddenInput) {
2497
+ const telInputName = this.telInput.getAttribute("name") || "";
2498
+ const names = hiddenInput(telInputName);
2499
+ if (names.phone) {
2500
+ const existingInput = this.telInput.form?.querySelector(
2501
+ `input[name="${names.phone}"]`
2502
+ );
2503
+ if (existingInput) {
2504
+ this.hiddenInput = existingInput;
2505
+ } else {
2506
+ this.hiddenInput = createEl("input", {
2507
+ type: "hidden",
2508
+ name: names.phone
2509
+ });
2510
+ wrapper.appendChild(this.hiddenInput);
2511
+ }
2512
+ }
2513
+ if (names.country) {
2514
+ const existingInput = this.telInput.form?.querySelector(
2515
+ `input[name="${names.country}"]`
2516
+ );
2517
+ if (existingInput) {
2518
+ this.hiddenInputCountry = existingInput;
2519
+ } else {
2520
+ this.hiddenInputCountry = createEl("input", {
2521
+ type: "hidden",
2522
+ name: names.country
2523
+ });
2524
+ wrapper.appendChild(this.hiddenInputCountry);
2525
+ }
2526
+ }
2527
+ }
2528
+ }
2529
+ //* For each country: add a country list item <li> to the countryList <ul> container.
2530
+ _appendListItems() {
2531
+ const frag = document.createDocumentFragment();
2532
+ for (let i = 0; i < this.countries.length; i++) {
2533
+ const c = this.countries[i];
2534
+ const liClass = buildClassNames({
2535
+ [CLASSES.COUNTRY_ITEM]: true,
2536
+ [CLASSES.HIGHLIGHT]: i === 0
2537
+ });
2538
+ const listItem = createEl("li", {
2539
+ id: `iti-${this.id}__item-${c.iso2}`,
2540
+ class: liClass,
2541
+ tabindex: "-1",
2542
+ role: "option",
2543
+ [ARIA.SELECTED]: "false"
2544
+ });
2545
+ listItem.dataset.dialCode = c.dialCode;
2546
+ listItem.dataset.countryCode = c.iso2;
2547
+ c.nodeById[this.id] = listItem;
2548
+ if (this.options.showFlags) {
2549
+ createEl("div", { class: `${CLASSES.FLAG} iti__${c.iso2}` }, listItem);
2550
+ }
2551
+ const nameEl = createEl("span", { class: "iti__country-name" }, listItem);
2552
+ nameEl.textContent = c.name;
2553
+ const dialEl = createEl("span", { class: "iti__dial-code" }, listItem);
2554
+ if (this.isRTL) {
2555
+ dialEl.setAttribute("dir", "ltr");
2556
+ }
2557
+ dialEl.textContent = `+${c.dialCode}`;
2558
+ frag.appendChild(listItem);
2559
+ }
2560
+ this.countryList.appendChild(frag);
2561
+ }
2562
+ //* Update the input padding to make space for the selected country/dial code.
2563
+ updateInputPadding() {
2564
+ if (this.selectedCountry) {
2565
+ const fallbackWidth = this.options.separateDialCode ? LAYOUT.SANE_SELECTED_WITH_DIAL_WIDTH : LAYOUT.SANE_SELECTED_NO_DIAL_WIDTH;
2566
+ const selectedCountryWidth = this.selectedCountry.offsetWidth || this._getHiddenSelectedCountryWidth() || fallbackWidth;
2567
+ const inputPadding = selectedCountryWidth + LAYOUT.INPUT_PADDING_EXTRA_LEFT;
2568
+ this.telInput.style.paddingLeft = `${inputPadding}px`;
2569
+ }
2570
+ }
2571
+ //* When input is in a hidden container during init, we cannot calculate the selected country width.
2572
+ //* Fix: clone the markup, make it invisible, add it to the end of the DOM, and then measure it's width.
2573
+ //* To get the right styling to apply, all we need is a shallow clone of the container,
2574
+ //* and then to inject a deep clone of the selectedCountry element.
2575
+ _getHiddenSelectedCountryWidth() {
2576
+ if (this.telInput.parentNode) {
2577
+ let body;
2578
+ try {
2579
+ body = window.top.document.body;
2580
+ } catch (e) {
2581
+ body = document.body;
2582
+ }
2583
+ const containerClone = this.telInput.parentNode.cloneNode(
2584
+ false
2585
+ );
2586
+ containerClone.style.visibility = "hidden";
2587
+ body.appendChild(containerClone);
2588
+ const countryContainerClone = this.countryContainer.cloneNode();
2589
+ containerClone.appendChild(countryContainerClone);
2590
+ const selectedCountryClone = this.selectedCountry.cloneNode(
2591
+ true
2592
+ );
2593
+ countryContainerClone.appendChild(selectedCountryClone);
2594
+ const width = selectedCountryClone.offsetWidth;
2595
+ body.removeChild(containerClone);
2596
+ return width;
2597
+ }
2598
+ return 0;
2599
+ }
2600
+ //* Update search results text (for a11y).
2601
+ updateSearchResultsA11yText() {
2602
+ const { i18n } = this.options;
2603
+ const count = this.countryList.childElementCount;
2604
+ let searchText;
2605
+ if (count === 0) {
2606
+ searchText = i18n.zeroSearchResults;
2607
+ } else {
2608
+ if (i18n.searchResultsText) {
2609
+ searchText = i18n.searchResultsText(count);
2610
+ } else if (count === 1) {
2611
+ searchText = i18n.oneSearchResult;
2612
+ } else {
2613
+ searchText = i18n.multipleSearchResults.replace(
2614
+ "${count}",
2615
+ count.toString()
2616
+ );
2617
+ }
2618
+ }
2619
+ this.searchResultsA11yText.textContent = searchText;
2620
+ }
2621
+ //* Check if an element is visible within it's container, else scroll until it is.
2622
+ scrollTo(element) {
2623
+ const container = this.countryList;
2624
+ const scrollTop = document.documentElement.scrollTop;
2625
+ const containerHeight = container.offsetHeight;
2626
+ const containerTop = container.getBoundingClientRect().top + scrollTop;
2627
+ const containerBottom = containerTop + containerHeight;
2628
+ const elementHeight = element.offsetHeight;
2629
+ const elementTop = element.getBoundingClientRect().top + scrollTop;
2630
+ const elementBottom = elementTop + elementHeight;
2631
+ const newScrollTop = elementTop - containerTop + container.scrollTop;
2632
+ if (elementTop < containerTop) {
2633
+ container.scrollTop = newScrollTop;
2634
+ } else if (elementBottom > containerBottom) {
2635
+ const heightDifference = containerHeight - elementHeight;
2636
+ container.scrollTop = newScrollTop - heightDifference;
2637
+ }
2638
+ }
2639
+ //* Remove highlighting from other list items and highlight the given item.
2640
+ highlightListItem(listItem, shouldFocus) {
2641
+ const prevItem = this.highlightedItem;
2642
+ if (prevItem) {
2643
+ prevItem.classList.remove(CLASSES.HIGHLIGHT);
2644
+ prevItem.setAttribute(ARIA.SELECTED, "false");
2645
+ }
2646
+ this.highlightedItem = listItem;
2647
+ if (this.highlightedItem) {
2648
+ this.highlightedItem.classList.add(CLASSES.HIGHLIGHT);
2649
+ this.highlightedItem.setAttribute(ARIA.SELECTED, "true");
2650
+ if (this.options.countrySearch) {
2651
+ const activeDescendant = this.highlightedItem.getAttribute("id") || "";
2652
+ this.searchInput.setAttribute(ARIA.ACTIVE_DESCENDANT, activeDescendant);
2653
+ }
2654
+ }
2655
+ if (shouldFocus) {
2656
+ this.highlightedItem.focus();
2657
+ }
2658
+ }
2659
+ //* Country search: Filter the country list to the given array of countries.
2660
+ filterCountries(matchedCountries) {
2661
+ this.countryList.innerHTML = "";
2662
+ let noCountriesAddedYet = true;
2663
+ for (const c of matchedCountries) {
2664
+ const listItem = c.nodeById[this.id];
2665
+ if (listItem) {
2666
+ this.countryList.appendChild(listItem);
2667
+ if (noCountriesAddedYet) {
2668
+ this.highlightListItem(listItem, false);
2669
+ noCountriesAddedYet = false;
2670
+ }
2671
+ }
2672
+ }
2673
+ if (noCountriesAddedYet) {
2674
+ this.highlightListItem(null, false);
2675
+ if (this.searchNoResults) {
2676
+ this.searchNoResults.classList.remove(CLASSES.HIDE);
2677
+ }
2678
+ } else if (this.searchNoResults) {
2679
+ this.searchNoResults.classList.add(CLASSES.HIDE);
2680
+ }
2681
+ this.countryList.scrollTop = 0;
2682
+ this.updateSearchResultsA11yText();
2683
+ }
2684
+ destroy() {
2685
+ this.telInput.iti = void 0;
2686
+ delete this.telInput.dataset.intlTelInputId;
2687
+ if (this.options.separateDialCode) {
2688
+ this.telInput.style.paddingLeft = this.originalPaddingLeft;
2689
+ }
2690
+ const wrapper = this.telInput.parentNode;
2691
+ wrapper.before(this.telInput);
2692
+ wrapper.remove();
2693
+ this.telInput = null;
2694
+ this.countryContainer = null;
2695
+ this.selectedCountry = null;
2696
+ this.selectedCountryInner = null;
2697
+ this.selectedDialCode = null;
2698
+ this.dropdownArrow = null;
2699
+ this.dropdownContent = null;
2700
+ this.searchInput = null;
2701
+ this.searchIcon = null;
2702
+ this.searchClearButton = null;
2703
+ this.searchNoResults = null;
2704
+ this.searchResultsA11yText = null;
2705
+ this.countryList = null;
2706
+ this.dropdown = null;
2707
+ this.hiddenInput = null;
2708
+ this.hiddenInputCountry = null;
2709
+ this.highlightedItem = null;
2710
+ for (const c of this.countries) {
2711
+ delete c.nodeById[this.id];
2712
+ }
2713
+ this.countries = null;
2714
+ }
2715
+ };
2716
+
2717
+ // src/js/modules/data/country-data.ts
2718
+ var processAllCountries = (options) => {
2719
+ const { onlyCountries, excludeCountries } = options;
2720
+ if (onlyCountries.length) {
2721
+ const lowerCaseOnlyCountries = onlyCountries.map(
2722
+ (country) => country.toLowerCase()
2723
+ );
2724
+ return data_default.filter(
2725
+ (country) => lowerCaseOnlyCountries.includes(country.iso2)
2726
+ );
2727
+ } else if (excludeCountries.length) {
2728
+ const lowerCaseExcludeCountries = excludeCountries.map(
2729
+ (country) => country.toLowerCase()
2730
+ );
2731
+ return data_default.filter(
2732
+ (country) => !lowerCaseExcludeCountries.includes(country.iso2)
2733
+ );
2734
+ }
2735
+ return data_default;
2736
+ };
2737
+ var translateCountryNames = (countries, options) => {
2738
+ for (const c of countries) {
2739
+ const iso2 = c.iso2.toLowerCase();
2740
+ if (options.i18n[iso2]) {
2741
+ c.name = options.i18n[iso2];
2742
+ }
2743
+ }
2744
+ };
2745
+ var processDialCodes = (countries, options) => {
2746
+ const dialCodes = /* @__PURE__ */ new Set();
2747
+ let dialCodeMaxLen = 0;
2748
+ const dialCodeToIso2Map = {};
2749
+ const _addToDialCodeMap = (iso2, dialCode, priority) => {
2750
+ if (!iso2 || !dialCode) {
2751
+ return;
2752
+ }
2753
+ if (dialCode.length > dialCodeMaxLen) {
2754
+ dialCodeMaxLen = dialCode.length;
2755
+ }
2756
+ if (!dialCodeToIso2Map.hasOwnProperty(dialCode)) {
2757
+ dialCodeToIso2Map[dialCode] = [];
2758
+ }
2759
+ const iso2List = dialCodeToIso2Map[dialCode];
2760
+ if (iso2List.includes(iso2)) {
2761
+ return;
2762
+ }
2763
+ const index = priority !== void 0 ? priority : iso2List.length;
2764
+ iso2List[index] = iso2;
2765
+ };
2766
+ for (const c of countries) {
2767
+ if (!dialCodes.has(c.dialCode)) {
2768
+ dialCodes.add(c.dialCode);
2769
+ }
2770
+ for (let k = 1; k < c.dialCode.length; k++) {
2771
+ const partialDialCode = c.dialCode.substring(0, k);
2772
+ _addToDialCodeMap(c.iso2, partialDialCode);
2773
+ }
2774
+ _addToDialCodeMap(c.iso2, c.dialCode, c.priority);
2775
+ }
2776
+ if (options.onlyCountries.length || options.excludeCountries.length) {
2777
+ dialCodes.forEach((dialCode) => {
2778
+ dialCodeToIso2Map[dialCode] = dialCodeToIso2Map[dialCode].filter(Boolean);
2779
+ });
2780
+ }
2781
+ for (const c of countries) {
2782
+ if (c.areaCodes) {
2783
+ const rootIso2Code = dialCodeToIso2Map[c.dialCode][0];
2784
+ for (const areaCode of c.areaCodes) {
2785
+ for (let k = 1; k < areaCode.length; k++) {
2786
+ const partialAreaCode = areaCode.substring(0, k);
2787
+ const partialDialCode = c.dialCode + partialAreaCode;
2788
+ _addToDialCodeMap(rootIso2Code, partialDialCode);
2789
+ _addToDialCodeMap(c.iso2, partialDialCode);
2790
+ }
2791
+ _addToDialCodeMap(c.iso2, c.dialCode + areaCode);
2792
+ }
2793
+ }
2794
+ }
2795
+ return { dialCodes, dialCodeMaxLen, dialCodeToIso2Map };
2796
+ };
2797
+ var sortCountries = (countries, options) => {
2798
+ if (options.countryOrder) {
2799
+ options.countryOrder = options.countryOrder.map(
2800
+ (iso2) => iso2.toLowerCase()
2801
+ );
2802
+ }
2803
+ countries.sort((a, b) => {
2804
+ const { countryOrder } = options;
2805
+ if (countryOrder) {
2806
+ const aIndex = countryOrder.indexOf(a.iso2);
2807
+ const bIndex = countryOrder.indexOf(b.iso2);
2808
+ const aIndexExists = aIndex > -1;
2809
+ const bIndexExists = bIndex > -1;
2810
+ if (aIndexExists || bIndexExists) {
2811
+ if (aIndexExists && bIndexExists) {
2812
+ return aIndex - bIndex;
2813
+ }
2814
+ return aIndexExists ? -1 : 1;
2815
+ }
2816
+ }
2817
+ return a.name.localeCompare(b.name);
2818
+ });
2819
+ };
2820
+ var cacheSearchTokens = (countries) => {
2821
+ for (const c of countries) {
2822
+ c.normalisedName = normaliseString(c.name);
2823
+ c.initials = c.normalisedName.split(/[^a-z]/).map((word) => word[0]).join("");
2824
+ c.dialCodePlus = `+${c.dialCode}`;
2825
+ }
2826
+ };
2827
+
2828
+ // src/js/modules/format/formatting.ts
2829
+ var beforeSetNumber = (fullNumber, dialCode, separateDialCode, selectedCountryData) => {
2830
+ let number = fullNumber;
2831
+ if (separateDialCode) {
2832
+ if (dialCode) {
2833
+ dialCode = `+${selectedCountryData.dialCode}`;
2834
+ const start = number[dialCode.length] === " " || number[dialCode.length] === "-" ? dialCode.length + 1 : dialCode.length;
2835
+ number = number.substring(start);
2836
+ }
2837
+ }
2838
+ return number;
2839
+ };
2840
+ var formatNumberAsYouType = (fullNumber, telInputValue, utils, selectedCountryData, separateDialCode) => {
2841
+ const result = utils ? utils.formatNumberAsYouType(fullNumber, selectedCountryData.iso2) : fullNumber;
2842
+ const { dialCode } = selectedCountryData;
2843
+ if (separateDialCode && telInputValue.charAt(0) !== "+" && result.includes(`+${dialCode}`)) {
2844
+ const afterDialCode = result.split(`+${dialCode}`)[1] || "";
2845
+ return afterDialCode.trim();
2846
+ }
2847
+ return result;
2848
+ };
2849
+
2850
+ // src/js/modules/format/caret.ts
2851
+ var translateCursorPosition = (relevantChars, formattedValue, prevCaretPos, isDeleteForwards) => {
2852
+ if (prevCaretPos === 0 && !isDeleteForwards) {
2853
+ return 0;
2854
+ }
2855
+ let relevantCharCount = 0;
2856
+ for (let i = 0; i < formattedValue.length; i++) {
2857
+ if (/[+0-9]/.test(formattedValue[i])) {
2858
+ relevantCharCount++;
2859
+ }
2860
+ if (relevantCharCount === relevantChars && !isDeleteForwards) {
2861
+ return i + 1;
2862
+ }
2863
+ if (isDeleteForwards && relevantCharCount === relevantChars + 1) {
2864
+ return i;
2865
+ }
2866
+ }
2867
+ return formattedValue.length;
2868
+ };
2869
+
2870
+ // src/js/modules/data/nanp-regionless.ts
2871
+ var regionlessNanpNumbers = [
2872
+ "800",
2873
+ "822",
2874
+ "833",
2875
+ "844",
2876
+ "855",
2877
+ "866",
2878
+ "877",
2879
+ "880",
2880
+ "881",
2881
+ "882",
2882
+ "883",
2883
+ "884",
2884
+ "885",
2885
+ "886",
2886
+ "887",
2887
+ "888",
2888
+ "889"
2889
+ ];
2890
+ var isRegionlessNanp = (number) => {
2891
+ const numeric = getNumeric(number);
2892
+ if (numeric.startsWith(DIAL.NANP) && numeric.length >= 4) {
2893
+ const areaCode = numeric.substring(1, 4);
2894
+ return regionlessNanpNumbers.includes(areaCode);
2895
+ }
2896
+ return false;
2897
+ };
2898
+
2899
+ // src/js/intl-tel-input.ts
2900
+ for (const c of data_default) {
2901
+ c.name = en_default[c.iso2];
2902
+ }
2903
+ var id = 0;
2904
+ var iso2Set = new Set(data_default.map((c) => c.iso2));
2905
+ var isIso2 = (val) => iso2Set.has(val);
2906
+ var Iti = class _Iti {
2907
+ constructor(input, customOptions = {}) {
2908
+ this.id = id++;
2909
+ this.options = { ...defaults, ...customOptions };
2910
+ applyOptionSideEffects(this.options, en_default);
2911
+ this.ui = new UI(input, this.options, this.id);
2912
+ this.isAndroid = _Iti._getIsAndroid();
2913
+ this.promise = this._createInitPromises();
2914
+ this.countries = processAllCountries(this.options);
2915
+ const { dialCodes, dialCodeMaxLen, dialCodeToIso2Map } = processDialCodes(
2916
+ this.countries,
2917
+ this.options
2918
+ );
2919
+ this.dialCodes = dialCodes;
2920
+ this.dialCodeMaxLen = dialCodeMaxLen;
2921
+ this.dialCodeToIso2Map = dialCodeToIso2Map;
2922
+ this.countryByIso2 = new Map(this.countries.map((c) => [c.iso2, c]));
2923
+ this._init();
2566
2924
  }
2567
- _maybeUpdateInputPaddingAndReveal() {
2568
- if (this.countryContainer) {
2569
- this._updateInputPadding();
2570
- this.countryContainer.classList.remove("iti__v-hide");
2571
- }
2925
+ static _getIsAndroid() {
2926
+ return typeof navigator !== "undefined" ? /Android/i.test(navigator.userAgent) : false;
2572
2927
  }
2573
- _maybeBuildHiddenInputs(wrapper) {
2574
- const { hiddenInput } = this.options;
2575
- if (hiddenInput) {
2576
- const telInputName = this.telInput.getAttribute("name") || "";
2577
- const names = hiddenInput(telInputName);
2578
- if (names.phone) {
2579
- const existingInput = this.telInput.form?.querySelector(`input[name="${names.phone}"]`);
2580
- if (existingInput) {
2581
- this.hiddenInput = existingInput;
2582
- } else {
2583
- this.hiddenInput = createEl("input", {
2584
- type: "hidden",
2585
- name: names.phone
2586
- });
2587
- wrapper.appendChild(this.hiddenInput);
2588
- }
2589
- }
2590
- if (names.country) {
2591
- const existingInput = this.telInput.form?.querySelector(`input[name="${names.country}"]`);
2592
- if (existingInput) {
2593
- this.hiddenInputCountry = existingInput;
2594
- } else {
2595
- this.hiddenInputCountry = createEl("input", {
2596
- type: "hidden",
2597
- name: names.country
2598
- });
2599
- wrapper.appendChild(this.hiddenInputCountry);
2600
- }
2601
- }
2602
- }
2928
+ _createInitPromises() {
2929
+ const autoCountryPromise = new Promise((resolve, reject) => {
2930
+ this.resolveAutoCountryPromise = resolve;
2931
+ this.rejectAutoCountryPromise = reject;
2932
+ });
2933
+ const utilsScriptPromise = new Promise((resolve, reject) => {
2934
+ this.resolveUtilsScriptPromise = resolve;
2935
+ this.rejectUtilsScriptPromise = reject;
2936
+ });
2937
+ return Promise.all([autoCountryPromise, utilsScriptPromise]);
2603
2938
  }
2604
- //* For each country: add a country list item <li> to the countryList <ul> container.
2605
- _appendListItems() {
2606
- for (let i = 0; i < this.countries.length; i++) {
2607
- const c = this.countries[i];
2608
- const extraClass = i === 0 ? "iti__highlight" : "";
2609
- const listItem = createEl(
2610
- "li",
2611
- {
2612
- id: `iti-${this.id}__item-${c.iso2}`,
2613
- class: `iti__country ${extraClass}`,
2614
- tabindex: "-1",
2615
- role: "option",
2616
- "data-dial-code": c.dialCode,
2617
- "data-country-code": c.iso2,
2618
- "aria-selected": "false"
2619
- },
2620
- this.countryList
2621
- );
2622
- c.nodeById[this.id] = listItem;
2623
- let content = "";
2624
- if (this.options.showFlags) {
2625
- content += `<div class='iti__flag iti__${c.iso2}'></div>`;
2626
- }
2627
- content += `<span class='iti__country-name'>${c.name}</span>`;
2628
- content += `<span class='iti__dial-code' dir='ltr'>+${c.dialCode}</span>`;
2629
- listItem.insertAdjacentHTML("beforeend", content);
2630
- }
2939
+ //* Can't be private as it's called from intlTelInput convenience wrapper.
2940
+ _init() {
2941
+ this.selectedCountryData = {};
2942
+ this.abortController = new AbortController();
2943
+ this._processCountryData();
2944
+ this.ui.generateMarkup(this.countries);
2945
+ this._setInitialState();
2946
+ this._initListeners();
2947
+ this._initRequests();
2948
+ }
2949
+ //********************
2950
+ //* PRIVATE METHODS
2951
+ //********************
2952
+ //* Prepare all of the country data, including onlyCountries, excludeCountries, countryOrder options.
2953
+ _processCountryData() {
2954
+ translateCountryNames(this.countries, this.options);
2955
+ sortCountries(this.countries, this.options);
2956
+ cacheSearchTokens(this.countries);
2631
2957
  }
2632
2958
  //* Set the initial state of the input value and the selected country by:
2633
2959
  //* 1. Extracting a dial code from the given number
2634
2960
  //* 2. Using explicit initialCountry
2635
2961
  _setInitialState(overrideAutoCountry = false) {
2636
- const attributeValue = this.telInput.getAttribute("value");
2637
- const inputValue = this.telInput.value;
2638
- const useAttribute = attributeValue && attributeValue.charAt(0) === "+" && (!inputValue || inputValue.charAt(0) !== "+");
2962
+ const attributeValue = this.ui.telInput.getAttribute("value");
2963
+ const inputValue = this.ui.telInput.value;
2964
+ const useAttribute = attributeValue && attributeValue.startsWith("+") && (!inputValue || !inputValue.startsWith("+"));
2639
2965
  const val = useAttribute ? attributeValue : inputValue;
2640
2966
  const dialCode = this._getDialCode(val);
2641
2967
  const isRegionlessNanpNumber = isRegionlessNanp(val);
2642
2968
  const { initialCountry, geoIpLookup } = this.options;
2643
- const isAutoCountry = initialCountry === "auto" && geoIpLookup;
2969
+ const isAutoCountry = initialCountry === INITIAL_COUNTRY.AUTO && geoIpLookup;
2644
2970
  if (dialCode && !isRegionlessNanpNumber) {
2645
2971
  this._updateCountryFromNumber(val);
2646
2972
  } else if (!isAutoCountry || overrideAutoCountry) {
@@ -2649,7 +2975,7 @@ var Iti = class _Iti {
2649
2975
  this._setCountry(lowerInitialCountry);
2650
2976
  } else {
2651
2977
  if (dialCode && isRegionlessNanpNumber) {
2652
- this._setCountry("us");
2978
+ this._setCountry(US.ISO2);
2653
2979
  } else {
2654
2980
  this._setCountry("");
2655
2981
  }
@@ -2665,81 +2991,94 @@ var Iti = class _Iti {
2665
2991
  if (this.options.allowDropdown) {
2666
2992
  this._initDropdownListeners();
2667
2993
  }
2668
- if ((this.hiddenInput || this.hiddenInputCountry) && this.telInput.form) {
2994
+ if ((this.ui.hiddenInput || this.ui.hiddenInputCountry) && this.ui.telInput.form) {
2669
2995
  this._initHiddenInputListener();
2670
2996
  }
2671
2997
  }
2672
2998
  //* Update hidden input on form submit.
2673
2999
  _initHiddenInputListener() {
2674
- this._handleHiddenInputSubmit = () => {
2675
- if (this.hiddenInput) {
2676
- this.hiddenInput.value = this.getNumber();
3000
+ const handleHiddenInputSubmit = () => {
3001
+ if (this.ui.hiddenInput) {
3002
+ this.ui.hiddenInput.value = this.getNumber();
2677
3003
  }
2678
- if (this.hiddenInputCountry) {
2679
- this.hiddenInputCountry.value = this.getSelectedCountryData().iso2 || "";
3004
+ if (this.ui.hiddenInputCountry) {
3005
+ this.ui.hiddenInputCountry.value = this.selectedCountryData.iso2 || "";
2680
3006
  }
2681
3007
  };
2682
- this.telInput.form?.addEventListener(
2683
- "submit",
2684
- this._handleHiddenInputSubmit
2685
- );
3008
+ this.ui.telInput.form?.addEventListener("submit", handleHiddenInputSubmit, {
3009
+ signal: this.abortController.signal
3010
+ });
2686
3011
  }
2687
3012
  //* initialise the dropdown listeners.
2688
3013
  _initDropdownListeners() {
2689
- this._handleLabelClick = (e) => {
2690
- if (this.dropdownContent.classList.contains("iti__hide")) {
2691
- this.telInput.focus();
3014
+ const signal = this.abortController.signal;
3015
+ const handleLabelClick = (e) => {
3016
+ if (this.ui.dropdownContent.classList.contains(CLASSES.HIDE)) {
3017
+ this.ui.telInput.focus();
2692
3018
  } else {
2693
3019
  e.preventDefault();
2694
3020
  }
2695
3021
  };
2696
- const label = this.telInput.closest("label");
3022
+ const label = this.ui.telInput.closest("label");
2697
3023
  if (label) {
2698
- label.addEventListener("click", this._handleLabelClick);
3024
+ label.addEventListener("click", handleLabelClick, { signal });
2699
3025
  }
2700
- this._handleClickSelectedCountry = () => {
2701
- const dropdownClosed = this.dropdownContent.classList.contains("iti__hide");
2702
- if (dropdownClosed && !this.telInput.disabled && !this.telInput.readOnly) {
3026
+ const handleClickSelectedCountry = () => {
3027
+ const dropdownClosed = this.ui.dropdownContent.classList.contains(
3028
+ CLASSES.HIDE
3029
+ );
3030
+ if (dropdownClosed && !this.ui.telInput.disabled && !this.ui.telInput.readOnly) {
2703
3031
  this._openDropdown();
2704
3032
  }
2705
3033
  };
2706
- this.selectedCountry.addEventListener("click", this._handleClickSelectedCountry);
2707
- this._handleCountryContainerKeydown = (e) => {
2708
- const isDropdownHidden = this.dropdownContent.classList.contains("iti__hide");
2709
- if (isDropdownHidden && ["ArrowUp", "ArrowDown", " ", "Enter"].includes(e.key)) {
3034
+ this.ui.selectedCountry.addEventListener(
3035
+ "click",
3036
+ handleClickSelectedCountry,
3037
+ {
3038
+ signal
3039
+ }
3040
+ );
3041
+ const handleCountryContainerKeydown = (e) => {
3042
+ const isDropdownHidden = this.ui.dropdownContent.classList.contains(
3043
+ CLASSES.HIDE
3044
+ );
3045
+ if (isDropdownHidden && [KEYS.ARROW_UP, KEYS.ARROW_DOWN, KEYS.SPACE, KEYS.ENTER].includes(e.key)) {
2710
3046
  e.preventDefault();
2711
3047
  e.stopPropagation();
2712
3048
  this._openDropdown();
2713
3049
  }
2714
- if (e.key === "Tab") {
3050
+ if (e.key === KEYS.TAB) {
2715
3051
  this._closeDropdown();
2716
3052
  }
2717
3053
  };
2718
- this.countryContainer.addEventListener(
3054
+ this.ui.countryContainer.addEventListener(
2719
3055
  "keydown",
2720
- this._handleCountryContainerKeydown
3056
+ handleCountryContainerKeydown,
3057
+ { signal }
2721
3058
  );
2722
3059
  }
2723
3060
  //* Init many requests: utils script / geo ip lookup.
2724
3061
  _initRequests() {
2725
- let { loadUtils, initialCountry, geoIpLookup } = this.options;
3062
+ const { loadUtils, initialCountry, geoIpLookup } = this.options;
2726
3063
  if (loadUtils && !intlTelInput.utils) {
2727
- this._doAttachUtils = () => {
3064
+ const doAttachUtils = () => {
2728
3065
  intlTelInput.attachUtils(loadUtils)?.catch(() => {
2729
3066
  });
2730
3067
  };
2731
3068
  if (intlTelInput.documentReady()) {
2732
- this._doAttachUtils();
3069
+ doAttachUtils();
2733
3070
  } else {
2734
- this._handlePageLoad = () => {
2735
- this._doAttachUtils();
3071
+ const handlePageLoad = () => {
3072
+ doAttachUtils();
2736
3073
  };
2737
- window.addEventListener("load", this._handlePageLoad);
3074
+ window.addEventListener("load", handlePageLoad, {
3075
+ signal: this.abortController.signal
3076
+ });
2738
3077
  }
2739
3078
  } else {
2740
3079
  this.resolveUtilsScriptPromise();
2741
3080
  }
2742
- const isAutoCountry = initialCountry === "auto" && geoIpLookup;
3081
+ const isAutoCountry = initialCountry === INITIAL_COUNTRY.AUTO && geoIpLookup;
2743
3082
  if (isAutoCountry && !this.selectedCountryData.iso2) {
2744
3083
  this._loadAutoCountry();
2745
3084
  } else {
@@ -2774,8 +3113,8 @@ var Iti = class _Iti {
2774
3113
  }
2775
3114
  _openDropdownWithPlus() {
2776
3115
  this._openDropdown();
2777
- this.searchInput.value = "+";
2778
- this._filterCountries("");
3116
+ this.ui.searchInput.value = "+";
3117
+ this._filterCountriesByQuery("");
2779
3118
  }
2780
3119
  //* Initialize the tel input listeners.
2781
3120
  _initTelInputListeners() {
@@ -2784,55 +3123,81 @@ var Iti = class _Iti {
2784
3123
  this._maybeBindPasteListener();
2785
3124
  }
2786
3125
  _bindInputListener() {
2787
- const { strictMode, formatAsYouType, separateDialCode, allowDropdown, countrySearch } = this.options;
3126
+ const {
3127
+ strictMode,
3128
+ formatAsYouType,
3129
+ separateDialCode,
3130
+ allowDropdown,
3131
+ countrySearch
3132
+ } = this.options;
2788
3133
  let userOverrideFormatting = false;
2789
- if (/\p{L}/u.test(this.telInput.value)) {
3134
+ if (REGEX.ALPHA_UNICODE.test(this.ui.telInput.value)) {
2790
3135
  userOverrideFormatting = true;
2791
3136
  }
2792
- this._handleInputEvent = (e) => {
3137
+ const handleInputEvent = (e) => {
2793
3138
  if (this.isAndroid && e?.data === "+" && separateDialCode && allowDropdown && countrySearch) {
2794
- const currentCaretPos = this.telInput.selectionStart || 0;
2795
- const valueBeforeCaret = this.telInput.value.substring(0, currentCaretPos - 1);
2796
- const valueAfterCaret = this.telInput.value.substring(currentCaretPos);
2797
- this.telInput.value = valueBeforeCaret + valueAfterCaret;
3139
+ const currentCaretPos = this.ui.telInput.selectionStart || 0;
3140
+ const valueBeforeCaret = this.ui.telInput.value.substring(
3141
+ 0,
3142
+ currentCaretPos - 1
3143
+ );
3144
+ const valueAfterCaret = this.ui.telInput.value.substring(currentCaretPos);
3145
+ this.ui.telInput.value = valueBeforeCaret + valueAfterCaret;
2798
3146
  this._openDropdownWithPlus();
2799
3147
  return;
2800
3148
  }
2801
- if (this._updateCountryFromNumber(this.telInput.value)) {
3149
+ if (this._updateCountryFromNumber(this.ui.telInput.value)) {
2802
3150
  this._triggerCountryChange();
2803
3151
  }
2804
- const isFormattingChar = e?.data && /[^+0-9]/.test(e.data);
2805
- const isPaste = e?.inputType === "insertFromPaste" && this.telInput.value;
3152
+ const isFormattingChar = e?.data && REGEX.NON_PLUS_NUMERIC.test(e.data);
3153
+ const isPaste = e?.inputType === INPUT_TYPES.PASTE && this.ui.telInput.value;
2806
3154
  if (isFormattingChar || isPaste && !strictMode) {
2807
3155
  userOverrideFormatting = true;
2808
- } else if (!/[^+0-9]/.test(this.telInput.value)) {
3156
+ } else if (!REGEX.NON_PLUS_NUMERIC.test(this.ui.telInput.value)) {
2809
3157
  userOverrideFormatting = false;
2810
3158
  }
2811
3159
  const isSetNumber = e?.detail && e.detail["isSetNumber"];
2812
3160
  if (formatAsYouType && !userOverrideFormatting && !isSetNumber) {
2813
- const currentCaretPos = this.telInput.selectionStart || 0;
2814
- const valueBeforeCaret = this.telInput.value.substring(0, currentCaretPos);
2815
- const relevantCharsBeforeCaret = valueBeforeCaret.replace(/[^+0-9]/g, "").length;
2816
- const isDeleteForwards = e?.inputType === "deleteContentForward";
3161
+ const currentCaretPos = this.ui.telInput.selectionStart || 0;
3162
+ const valueBeforeCaret = this.ui.telInput.value.substring(
3163
+ 0,
3164
+ currentCaretPos
3165
+ );
3166
+ const relevantCharsBeforeCaret = valueBeforeCaret.replace(
3167
+ REGEX.NON_PLUS_NUMERIC_GLOBAL,
3168
+ ""
3169
+ ).length;
3170
+ const isDeleteForwards = e?.inputType === INPUT_TYPES.DELETE_FWD;
2817
3171
  const fullNumber = this._getFullNumber();
2818
3172
  const formattedValue = formatNumberAsYouType(
2819
3173
  fullNumber,
2820
- this.telInput.value,
3174
+ this.ui.telInput.value,
2821
3175
  intlTelInput.utils,
2822
3176
  this.selectedCountryData,
2823
3177
  this.options.separateDialCode
2824
3178
  );
2825
- const newCaretPos = translateCursorPosition(relevantCharsBeforeCaret, formattedValue, currentCaretPos, isDeleteForwards);
2826
- this.telInput.value = formattedValue;
2827
- this.telInput.setSelectionRange(newCaretPos, newCaretPos);
3179
+ const newCaretPos = translateCursorPosition(
3180
+ relevantCharsBeforeCaret,
3181
+ formattedValue,
3182
+ currentCaretPos,
3183
+ isDeleteForwards
3184
+ );
3185
+ this.ui.telInput.value = formattedValue;
3186
+ this.ui.telInput.setSelectionRange(newCaretPos, newCaretPos);
2828
3187
  }
2829
3188
  };
2830
- this.telInput.addEventListener("input", this._handleInputEvent);
3189
+ this.ui.telInput.addEventListener(
3190
+ "input",
3191
+ handleInputEvent,
3192
+ {
3193
+ signal: this.abortController.signal
3194
+ }
3195
+ );
2831
3196
  }
2832
3197
  _maybeBindKeydownListener() {
2833
3198
  const { strictMode, separateDialCode, allowDropdown, countrySearch } = this.options;
2834
3199
  if (strictMode || separateDialCode) {
2835
- this._handleKeydownEvent = (e) => {
3200
+ const handleKeydownEvent = (e) => {
2836
3201
  if (e.key && e.key.length === 1 && !e.altKey && !e.ctrlKey && !e.metaKey) {
2837
3202
  if (separateDialCode && allowDropdown && countrySearch && e.key === "+") {
2838
3203
  e.preventDefault();
@@ -2840,14 +3205,17 @@ var Iti = class _Iti {
2840
3205
  return;
2841
3206
  }
2842
3207
  if (strictMode) {
2843
- const value = this.telInput.value;
2844
- const alreadyHasPlus = value.charAt(0) === "+";
2845
- const isInitialPlus = !alreadyHasPlus && this.telInput.selectionStart === 0 && e.key === "+";
3208
+ const value = this.ui.telInput.value;
3209
+ const alreadyHasPlus = value.startsWith("+");
3210
+ const isInitialPlus = !alreadyHasPlus && this.ui.telInput.selectionStart === 0 && e.key === "+";
2846
3211
  const isNumeric = /^[0-9]$/.test(e.key);
2847
3212
  const isAllowedChar = separateDialCode ? isNumeric : isInitialPlus || isNumeric;
2848
- const newValue = value.slice(0, this.telInput.selectionStart) + e.key + value.slice(this.telInput.selectionEnd);
3213
+ const newValue = value.slice(0, this.ui.telInput.selectionStart) + e.key + value.slice(this.ui.telInput.selectionEnd);
2849
3214
  const newFullNumber = this._getFullNumber(newValue);
2850
- const coreNumber = intlTelInput.utils.getCoreNumber(newFullNumber, this.selectedCountryData.iso2);
3215
+ const coreNumber = intlTelInput.utils.getCoreNumber(
3216
+ newFullNumber,
3217
+ this.selectedCountryData.iso2
3218
+ );
2851
3219
  const hasExceededMaxLength = this.maxCoreNumberLength && coreNumber.length > this.maxCoreNumberLength;
2852
3220
  const newCountry = this._getNewCountryFromNumber(newFullNumber);
2853
3221
  const isChangingDialCode = newCountry !== null;
@@ -2857,14 +3225,16 @@ var Iti = class _Iti {
2857
3225
  }
2858
3226
  }
2859
3227
  };
2860
- this.telInput.addEventListener("keydown", this._handleKeydownEvent);
3228
+ this.ui.telInput.addEventListener("keydown", handleKeydownEvent, {
3229
+ signal: this.abortController.signal
3230
+ });
2861
3231
  }
2862
3232
  }
2863
3233
  _maybeBindPasteListener() {
2864
3234
  if (this.options.strictMode) {
2865
- this._handlePasteEvent = (e) => {
3235
+ const handlePasteEvent = (e) => {
2866
3236
  e.preventDefault();
2867
- const input = this.telInput;
3237
+ const input = this.ui.telInput;
2868
3238
  const selStart = input.selectionStart;
2869
3239
  const selEnd = input.selectionEnd;
2870
3240
  const before = input.value.slice(0, selStart);
@@ -2873,7 +3243,7 @@ var Iti = class _Iti {
2873
3243
  const pasted = e.clipboardData.getData("text");
2874
3244
  const initialCharSelected = selStart === 0 && selEnd > 0;
2875
3245
  const allowLeadingPlus = !input.value.startsWith("+") || initialCharSelected;
2876
- const allowedChars = pasted.replace(/[^0-9+]/g, "");
3246
+ const allowedChars = pasted.replace(REGEX.NON_PLUS_NUMERIC_GLOBAL, "");
2877
3247
  const hasLeadingPlus = allowedChars.startsWith("+");
2878
3248
  const numerics = allowedChars.replace(/\+/g, "");
2879
3249
  const sanitised = hasLeadingPlus && allowLeadingPlus ? `+${numerics}` : numerics;
@@ -2899,82 +3269,117 @@ var Iti = class _Iti {
2899
3269
  input.setSelectionRange(caretPos, caretPos);
2900
3270
  input.dispatchEvent(new InputEvent("input", { bubbles: true }));
2901
3271
  };
2902
- this.telInput.addEventListener("paste", this._handlePasteEvent);
3272
+ this.ui.telInput.addEventListener("paste", handlePasteEvent, {
3273
+ signal: this.abortController.signal
3274
+ });
2903
3275
  }
2904
3276
  }
2905
3277
  //* Adhere to the input's maxlength attr.
2906
3278
  _cap(number) {
2907
- const max = parseInt(this.telInput.getAttribute("maxlength") || "", 10);
3279
+ const max = Number(this.ui.telInput.getAttribute("maxlength"));
2908
3280
  return max && number.length > max ? number.substring(0, max) : number;
2909
3281
  }
2910
- //* Trigger a custom event on the input.
3282
+ //* Trigger a custom event on the input (typed via ItiEventMap).
2911
3283
  _trigger(name, detailProps = {}) {
2912
3284
  const e = new CustomEvent(name, {
2913
3285
  bubbles: true,
2914
3286
  cancelable: true,
2915
3287
  detail: detailProps
2916
3288
  });
2917
- this.telInput.dispatchEvent(e);
3289
+ this.ui.telInput.dispatchEvent(e);
2918
3290
  }
2919
3291
  //* Open the dropdown.
2920
3292
  _openDropdown() {
2921
3293
  const { fixDropdownWidth, countrySearch } = this.options;
3294
+ this.dropdownAbortController = new AbortController();
2922
3295
  if (fixDropdownWidth) {
2923
- this.dropdownContent.style.width = `${this.telInput.offsetWidth}px`;
3296
+ this.ui.dropdownContent.style.width = `${this.ui.telInput.offsetWidth}px`;
2924
3297
  }
2925
- this.dropdownContent.classList.remove("iti__hide");
2926
- this.selectedCountry.setAttribute("aria-expanded", "true");
3298
+ this.ui.dropdownContent.classList.remove(CLASSES.HIDE);
3299
+ this.ui.selectedCountry.setAttribute(ARIA.EXPANDED, "true");
2927
3300
  this._setDropdownPosition();
2928
3301
  if (countrySearch) {
2929
- const firstCountryItem = this.countryList.firstElementChild;
3302
+ const firstCountryItem = this.ui.countryList.firstElementChild;
2930
3303
  if (firstCountryItem) {
2931
- this._highlightListItem(firstCountryItem, false);
2932
- this.countryList.scrollTop = 0;
3304
+ this.ui.highlightListItem(firstCountryItem, false);
3305
+ this.ui.countryList.scrollTop = 0;
2933
3306
  }
2934
- this.searchInput.focus();
3307
+ this.ui.searchInput.focus();
2935
3308
  }
2936
3309
  this._bindDropdownListeners();
2937
- this.dropdownArrow.classList.add("iti__arrow--up");
2938
- this._trigger("open:countrydropdown");
3310
+ this.ui.dropdownArrow.classList.add(CLASSES.ARROW_UP);
3311
+ this._trigger(EVENTS.OPEN_COUNTRY_DROPDOWN);
2939
3312
  }
2940
3313
  //* Set the dropdown position
2941
3314
  _setDropdownPosition() {
2942
3315
  if (this.options.dropdownContainer) {
2943
- this.options.dropdownContainer.appendChild(this.dropdown);
3316
+ this.options.dropdownContainer.appendChild(this.ui.dropdown);
2944
3317
  }
2945
3318
  if (!this.options.useFullscreenPopup) {
2946
- const inputPosRelativeToVP = this.telInput.getBoundingClientRect();
2947
- const inputHeight = this.telInput.offsetHeight;
3319
+ const inputPosRelativeToVP = this.ui.telInput.getBoundingClientRect();
3320
+ const inputHeight = this.ui.telInput.offsetHeight;
2948
3321
  if (this.options.dropdownContainer) {
2949
- this.dropdown.style.top = `${inputPosRelativeToVP.top + inputHeight}px`;
2950
- this.dropdown.style.left = `${inputPosRelativeToVP.left}px`;
2951
- this._handleWindowScroll = () => this._closeDropdown();
2952
- window.addEventListener("scroll", this._handleWindowScroll);
3322
+ this.ui.dropdown.style.top = `${inputPosRelativeToVP.top + inputHeight}px`;
3323
+ this.ui.dropdown.style.left = `${inputPosRelativeToVP.left}px`;
3324
+ const handleWindowScroll = () => this._closeDropdown();
3325
+ window.addEventListener("scroll", handleWindowScroll, {
3326
+ signal: this.dropdownAbortController.signal
3327
+ });
2953
3328
  }
2954
3329
  }
2955
3330
  }
2956
3331
  //* We only bind dropdown listeners when the dropdown is open.
2957
3332
  _bindDropdownListeners() {
2958
- this._handleMouseoverCountryList = (e) => {
2959
- const listItem = e.target?.closest(".iti__country");
3333
+ const signal = this.dropdownAbortController.signal;
3334
+ this._bindDropdownMouseoverListener(signal);
3335
+ this._bindDropdownCountryClickListener(signal);
3336
+ this._bindDropdownClickOffListener(signal);
3337
+ this._bindDropdownKeydownListener(signal);
3338
+ if (this.options.countrySearch) {
3339
+ this._bindDropdownSearchListeners(signal);
3340
+ }
3341
+ }
3342
+ //* When mouse over a list item, just highlight that one
3343
+ //* we add the class "highlight", so if they hit "enter" we know which one to select.
3344
+ _bindDropdownMouseoverListener(signal) {
3345
+ const handleMouseoverCountryList = (e) => {
3346
+ const listItem = e.target?.closest(
3347
+ `.${CLASSES.COUNTRY_ITEM}`
3348
+ );
2960
3349
  if (listItem) {
2961
- this._highlightListItem(listItem, false);
3350
+ this.ui.highlightListItem(listItem, false);
2962
3351
  }
2963
3352
  };
2964
- this.countryList.addEventListener(
3353
+ this.ui.countryList.addEventListener(
2965
3354
  "mouseover",
2966
- this._handleMouseoverCountryList
3355
+ handleMouseoverCountryList,
3356
+ {
3357
+ signal
3358
+ }
2967
3359
  );
2968
- this._handleClickCountryList = (e) => {
2969
- const listItem = e.target?.closest(".iti__country");
3360
+ }
3361
+ //* Listen for country selection.
3362
+ _bindDropdownCountryClickListener(signal) {
3363
+ const handleClickCountryList = (e) => {
3364
+ const listItem = e.target?.closest(
3365
+ `.${CLASSES.COUNTRY_ITEM}`
3366
+ );
2970
3367
  if (listItem) {
2971
3368
  this._selectListItem(listItem);
2972
3369
  }
2973
3370
  };
2974
- this.countryList.addEventListener("click", this._handleClickCountryList);
2975
- this._handleClickOffToClose = (e) => {
3371
+ this.ui.countryList.addEventListener("click", handleClickCountryList, {
3372
+ signal
3373
+ });
3374
+ }
3375
+ //* Click off to close (except when this initial opening click is bubbling up).
3376
+ //* We cannot just stopPropagation as it may be needed to close another instance.
3377
+ _bindDropdownClickOffListener(signal) {
3378
+ const handleClickOffToClose = (e) => {
2976
3379
  const target = e.target;
2977
- const clickedInsideDropdown = !!target.closest(`#iti-${this.id}__dropdown-content`);
3380
+ const clickedInsideDropdown = !!target.closest(
3381
+ `#iti-${this.id}__dropdown-content`
3382
+ );
2978
3383
  if (!clickedInsideDropdown) {
2979
3384
  this._closeDropdown();
2980
3385
  }
@@ -2982,24 +3387,37 @@ var Iti = class _Iti {
2982
3387
  setTimeout(() => {
2983
3388
  document.documentElement.addEventListener(
2984
3389
  "click",
2985
- this._handleClickOffToClose
3390
+ handleClickOffToClose,
3391
+ { signal }
2986
3392
  );
2987
3393
  }, 0);
3394
+ }
3395
+ //* Listen for up/down scrolling, enter to select, or escape to close.
3396
+ //* Use keydown as keypress doesn't fire for non-char keys and we want to catch if they
3397
+ //* just hit down and hold it to scroll down (no keyup event).
3398
+ //* Listen on the document because that's where key events are triggered if no input has focus.
3399
+ _bindDropdownKeydownListener(signal) {
2988
3400
  let query = "";
2989
3401
  let queryTimer = null;
2990
- this._handleKeydownOnDropdown = (e) => {
2991
- if (["ArrowUp", "ArrowDown", "Enter", "Escape"].includes(e.key)) {
3402
+ const handleKeydownOnDropdown = (e) => {
3403
+ const allowedKeys = [
3404
+ KEYS.ARROW_UP,
3405
+ KEYS.ARROW_DOWN,
3406
+ KEYS.ENTER,
3407
+ KEYS.ESC
3408
+ ];
3409
+ if (allowedKeys.includes(e.key)) {
2992
3410
  e.preventDefault();
2993
3411
  e.stopPropagation();
2994
- if (e.key === "ArrowUp" || e.key === "ArrowDown") {
3412
+ if (e.key === KEYS.ARROW_UP || e.key === KEYS.ARROW_DOWN) {
2995
3413
  this._handleUpDownKey(e.key);
2996
- } else if (e.key === "Enter") {
3414
+ } else if (e.key === KEYS.ENTER) {
2997
3415
  this._handleEnterKey();
2998
- } else if (e.key === "Escape") {
3416
+ } else if (e.key === KEYS.ESC) {
2999
3417
  this._closeDropdown();
3000
3418
  }
3001
3419
  }
3002
- if (!this.options.countrySearch && /^[a-zA-ZÀ-ÿа-яА-Я ]$/.test(e.key)) {
3420
+ if (!this.options.countrySearch && REGEX.HIDDEN_SEARCH_CHAR.test(e.key)) {
3003
3421
  e.stopPropagation();
3004
3422
  if (queryTimer) {
3005
3423
  clearTimeout(queryTimer);
@@ -3008,147 +3426,78 @@ var Iti = class _Iti {
3008
3426
  this._searchForCountry(query);
3009
3427
  queryTimer = setTimeout(() => {
3010
3428
  query = "";
3011
- }, 1e3);
3429
+ }, TIMINGS.HIDDEN_SEARCH_RESET_MS);
3012
3430
  }
3013
3431
  };
3014
- document.addEventListener("keydown", this._handleKeydownOnDropdown);
3015
- if (this.options.countrySearch) {
3016
- const doFilter = () => {
3017
- const inputQuery = this.searchInput.value.trim();
3018
- this._filterCountries(inputQuery);
3019
- if (this.searchInput.value) {
3020
- this.searchClearButton.classList.remove("iti__hide");
3021
- } else {
3022
- this.searchClearButton.classList.add("iti__hide");
3023
- }
3024
- };
3025
- let keyupTimer = null;
3026
- this._handleSearchChange = () => {
3027
- if (keyupTimer) {
3028
- clearTimeout(keyupTimer);
3029
- }
3030
- keyupTimer = setTimeout(() => {
3031
- doFilter();
3032
- keyupTimer = null;
3033
- }, 100);
3034
- };
3035
- this.searchInput.addEventListener("input", this._handleSearchChange);
3036
- this._handleSearchClear = () => {
3037
- this.searchInput.value = "";
3038
- this.searchInput.focus();
3432
+ document.addEventListener("keydown", handleKeydownOnDropdown, { signal });
3433
+ }
3434
+ //* Search input listeners when countrySearch enabled.
3435
+ _bindDropdownSearchListeners(signal) {
3436
+ const doFilter = () => {
3437
+ const inputQuery = this.ui.searchInput.value.trim();
3438
+ this._filterCountriesByQuery(inputQuery);
3439
+ if (this.ui.searchInput.value) {
3440
+ this.ui.searchClearButton.classList.remove(CLASSES.HIDE);
3441
+ } else {
3442
+ this.ui.searchClearButton.classList.add(CLASSES.HIDE);
3443
+ }
3444
+ };
3445
+ let keyupTimer = null;
3446
+ const handleSearchChange = () => {
3447
+ if (keyupTimer) {
3448
+ clearTimeout(keyupTimer);
3449
+ }
3450
+ keyupTimer = setTimeout(() => {
3039
3451
  doFilter();
3040
- };
3041
- this.searchClearButton.addEventListener("click", this._handleSearchClear);
3042
- }
3452
+ keyupTimer = null;
3453
+ }, 100);
3454
+ };
3455
+ this.ui.searchInput.addEventListener("input", handleSearchChange, {
3456
+ signal
3457
+ });
3458
+ const handleSearchClear = () => {
3459
+ this.ui.searchInput.value = "";
3460
+ this.ui.searchInput.focus();
3461
+ doFilter();
3462
+ };
3463
+ this.ui.searchClearButton.addEventListener("click", handleSearchClear, {
3464
+ signal
3465
+ });
3043
3466
  }
3044
3467
  //* Hidden search (countrySearch disabled): Find the first list item whose name starts with the query string.
3045
3468
  _searchForCountry(query) {
3046
- for (const c of this.countries) {
3047
- const startsWith = c.name.substring(0, query.length).toLowerCase() === query;
3048
- if (startsWith) {
3049
- const listItem = c.nodeById[this.id];
3050
- this._highlightListItem(listItem, false);
3051
- this._scrollTo(listItem);
3052
- break;
3053
- }
3469
+ const match = findFirstCountryStartingWith(this.countries, query);
3470
+ if (match) {
3471
+ const listItem = match.nodeById[this.id];
3472
+ this.ui.highlightListItem(listItem, false);
3473
+ this.ui.scrollTo(listItem);
3054
3474
  }
3055
3475
  }
3056
- //* Country search enabled: Filter the countries according to the search query.
3057
- _filterCountries(query) {
3058
- this.countryList.innerHTML = "";
3476
+ //* Country search: Filter the countries according to the search query.
3477
+ _filterCountriesByQuery(query) {
3059
3478
  let matchedCountries;
3060
3479
  if (query === "") {
3061
3480
  matchedCountries = this.countries;
3062
3481
  } else {
3063
- matchedCountries = this._getMatchedCountries(query);
3064
- }
3065
- let noCountriesAddedYet = true;
3066
- for (const c of matchedCountries) {
3067
- const listItem = c.nodeById[this.id];
3068
- if (listItem) {
3069
- this.countryList.appendChild(listItem);
3070
- if (noCountriesAddedYet) {
3071
- this._highlightListItem(listItem, false);
3072
- noCountriesAddedYet = false;
3073
- }
3074
- }
3075
- }
3076
- if (noCountriesAddedYet) {
3077
- this._highlightListItem(null, false);
3078
- if (this.searchNoResults) {
3079
- this.searchNoResults.classList.remove("iti__hide");
3080
- }
3081
- } else if (this.searchNoResults) {
3082
- this.searchNoResults.classList.add("iti__hide");
3083
- }
3084
- this.countryList.scrollTop = 0;
3085
- this._updateSearchResultsA11yText();
3086
- }
3087
- _getMatchedCountries(query) {
3088
- const normalisedQuery = normaliseString(query);
3089
- const iso2Matches = [];
3090
- const nameStartWith = [];
3091
- const nameContains = [];
3092
- const dialCodeMatches = [];
3093
- const dialCodeContains = [];
3094
- const initialsMatches = [];
3095
- for (const c of this.countries) {
3096
- if (c.iso2 === normalisedQuery) {
3097
- iso2Matches.push(c);
3098
- } else if (c.normalisedName.startsWith(normalisedQuery)) {
3099
- nameStartWith.push(c);
3100
- } else if (c.normalisedName.includes(normalisedQuery)) {
3101
- nameContains.push(c);
3102
- } else if (normalisedQuery === c.dialCode || normalisedQuery === c.dialCodePlus) {
3103
- dialCodeMatches.push(c);
3104
- } else if (c.dialCodePlus.includes(normalisedQuery)) {
3105
- dialCodeContains.push(c);
3106
- } else if (c.initials.includes(normalisedQuery)) {
3107
- initialsMatches.push(c);
3108
- }
3109
- }
3110
- return [
3111
- ...iso2Matches.sort((a, b) => a.priority - b.priority),
3112
- ...nameStartWith.sort((a, b) => a.priority - b.priority),
3113
- ...nameContains.sort((a, b) => a.priority - b.priority),
3114
- ...dialCodeMatches.sort((a, b) => a.priority - b.priority),
3115
- ...dialCodeContains.sort((a, b) => a.priority - b.priority),
3116
- ...initialsMatches.sort((a, b) => a.priority - b.priority)
3117
- ];
3118
- }
3119
- //* Update search results text (for a11y).
3120
- _updateSearchResultsA11yText() {
3121
- const { i18n } = this.options;
3122
- const count = this.countryList.childElementCount;
3123
- let searchText;
3124
- if (count === 0) {
3125
- searchText = i18n.zeroSearchResults;
3126
- } else {
3127
- if (i18n.searchResultsText) {
3128
- searchText = i18n.searchResultsText(count);
3129
- } else if (count === 1) {
3130
- searchText = i18n.oneSearchResult;
3131
- } else {
3132
- searchText = i18n.multipleSearchResults.replace("${count}", count.toString());
3133
- }
3482
+ matchedCountries = getMatchedCountries(this.countries, query);
3134
3483
  }
3135
- this.searchResultsA11yText.textContent = searchText;
3484
+ this.ui.filterCountries(matchedCountries);
3136
3485
  }
3137
3486
  //* Highlight the next/prev item in the list (and ensure it is visible).
3138
3487
  _handleUpDownKey(key) {
3139
- let next = key === "ArrowUp" ? this.highlightedItem?.previousElementSibling : this.highlightedItem?.nextElementSibling;
3140
- if (!next && this.countryList.childElementCount > 1) {
3141
- next = key === "ArrowUp" ? this.countryList.lastElementChild : this.countryList.firstElementChild;
3488
+ let next = key === KEYS.ARROW_UP ? this.ui.highlightedItem?.previousElementSibling : this.ui.highlightedItem?.nextElementSibling;
3489
+ if (!next && this.ui.countryList.childElementCount > 1) {
3490
+ next = key === KEYS.ARROW_UP ? this.ui.countryList.lastElementChild : this.ui.countryList.firstElementChild;
3142
3491
  }
3143
3492
  if (next) {
3144
- this._scrollTo(next);
3145
- this._highlightListItem(next, false);
3493
+ this.ui.scrollTo(next);
3494
+ this.ui.highlightListItem(next, false);
3146
3495
  }
3147
3496
  }
3148
3497
  //* Select the currently highlighted item.
3149
3498
  _handleEnterKey() {
3150
- if (this.highlightedItem) {
3151
- this._selectListItem(this.highlightedItem);
3499
+ if (this.ui.highlightedItem) {
3500
+ this._selectListItem(this.ui.highlightedItem);
3152
3501
  }
3153
3502
  }
3154
3503
  //* Update the input's value to the given val (format first if possible)
@@ -3156,7 +3505,7 @@ var Iti = class _Iti {
3156
3505
  _updateValFromNumber(fullNumber) {
3157
3506
  let number = fullNumber;
3158
3507
  if (this.options.formatOnDisplay && intlTelInput.utils && this.selectedCountryData) {
3159
- const useNational = this.options.nationalMode || number.charAt(0) !== "+" && !this.options.separateDialCode;
3508
+ const useNational = this.options.nationalMode || !number.startsWith("+") && !this.options.separateDialCode;
3160
3509
  const { NATIONAL, INTERNATIONAL } = intlTelInput.utils.numberFormat;
3161
3510
  const format = useNational ? NATIONAL : INTERNATIONAL;
3162
3511
  number = intlTelInput.utils.formatNumber(
@@ -3166,7 +3515,7 @@ var Iti = class _Iti {
3166
3515
  );
3167
3516
  }
3168
3517
  number = this._beforeSetNumber(number);
3169
- this.telInput.value = number;
3518
+ this.ui.telInput.value = number;
3170
3519
  }
3171
3520
  //* Check if need to select a new country based on the given number
3172
3521
  //* Note: called from _setInitialState, keyup handler, setNumber.
@@ -3180,11 +3529,11 @@ var Iti = class _Iti {
3180
3529
  // if there is a selected country, and the number doesn't start with a dial code, then add it
3181
3530
  _ensureHasDialCode(number) {
3182
3531
  const { dialCode, nationalPrefix } = this.selectedCountryData;
3183
- const alreadyHasPlus = number.charAt(0) === "+";
3532
+ const alreadyHasPlus = number.startsWith("+");
3184
3533
  if (alreadyHasPlus || !dialCode) {
3185
3534
  return number;
3186
3535
  }
3187
- const hasPrefix = nationalPrefix && number.charAt(0) === nationalPrefix && !this.options.separateDialCode;
3536
+ const hasPrefix = nationalPrefix && number.startsWith(nationalPrefix) && !this.options.separateDialCode;
3188
3537
  const cleanNumber = hasPrefix ? number.substring(1) : number;
3189
3538
  return `+${dialCode}${cleanNumber}`;
3190
3539
  }
@@ -3211,13 +3560,15 @@ var Iti = class _Iti {
3211
3560
  if (!selectedIso2 && this.defaultCountry && iso2Codes.includes(this.defaultCountry)) {
3212
3561
  return this.defaultCountry;
3213
3562
  }
3214
- const isRegionlessNanpNumber = selectedDialCode === "1" && isRegionlessNanp(numeric);
3563
+ const isRegionlessNanpNumber = selectedDialCode === DIAL.NANP && isRegionlessNanp(numeric);
3215
3564
  if (isRegionlessNanpNumber) {
3216
3565
  return null;
3217
3566
  }
3218
3567
  const { areaCodes, priority } = this.selectedCountryData;
3219
3568
  if (areaCodes) {
3220
- const dialCodeAreaCodes = areaCodes.map((areaCode) => `${selectedDialCode}${areaCode}`);
3569
+ const dialCodeAreaCodes = areaCodes.map(
3570
+ (areaCode) => `${selectedDialCode}${areaCode}`
3571
+ );
3221
3572
  for (const dialCodeAreaCode of dialCodeAreaCodes) {
3222
3573
  if (numeric.startsWith(dialCodeAreaCode)) {
3223
3574
  return null;
@@ -3231,33 +3582,13 @@ var Iti = class _Iti {
3231
3582
  if (!isValidSelection && !alreadySelected) {
3232
3583
  return iso2Codes[0];
3233
3584
  }
3234
- } else if (number.charAt(0) === "+" && numeric.length) {
3585
+ } else if (number.startsWith("+") && numeric.length) {
3235
3586
  return "";
3236
3587
  } else if ((!number || number === "+") && !selectedIso2) {
3237
3588
  return this.defaultCountry;
3238
3589
  }
3239
3590
  return null;
3240
3591
  }
3241
- //* Remove highlighting from other list items and highlight the given item.
3242
- _highlightListItem(listItem, shouldFocus) {
3243
- const prevItem = this.highlightedItem;
3244
- if (prevItem) {
3245
- prevItem.classList.remove("iti__highlight");
3246
- prevItem.setAttribute("aria-selected", "false");
3247
- }
3248
- this.highlightedItem = listItem;
3249
- if (this.highlightedItem) {
3250
- this.highlightedItem.classList.add("iti__highlight");
3251
- this.highlightedItem.setAttribute("aria-selected", "true");
3252
- if (this.options.countrySearch) {
3253
- const activeDescendant = this.highlightedItem.getAttribute("id") || "";
3254
- this.searchInput.setAttribute("aria-activedescendant", activeDescendant);
3255
- }
3256
- }
3257
- if (shouldFocus) {
3258
- this.highlightedItem.focus();
3259
- }
3260
- }
3261
3592
  //* Update the selected country, dial code (if separateDialCode), placeholder, title, and active list item.
3262
3593
  //* Note: called from _setInitialState, _updateCountryFromNumber, _selectListItem, setCountry.
3263
3594
  _setCountry(iso2) {
@@ -3267,8 +3598,8 @@ var Iti = class _Iti {
3267
3598
  if (this.selectedCountryData.iso2) {
3268
3599
  this.defaultCountry = this.selectedCountryData.iso2;
3269
3600
  }
3270
- if (this.selectedCountry) {
3271
- const flagClass = iso2 && showFlags ? `iti__flag iti__${iso2}` : "iti__flag iti__globe";
3601
+ if (this.ui.selectedCountry) {
3602
+ const flagClass = iso2 && showFlags ? `${CLASSES.FLAG} iti__${iso2}` : `${CLASSES.FLAG} ${CLASSES.GLOBE}`;
3272
3603
  let ariaLabel, title;
3273
3604
  if (iso2) {
3274
3605
  const { name, dialCode } = this.selectedCountryData;
@@ -3278,28 +3609,19 @@ var Iti = class _Iti {
3278
3609
  title = i18n.noCountrySelected;
3279
3610
  ariaLabel = i18n.noCountrySelected;
3280
3611
  }
3281
- this.selectedCountryInner.className = flagClass;
3282
- this.selectedCountry.setAttribute("title", title);
3283
- this.selectedCountry.setAttribute("aria-label", ariaLabel);
3612
+ this.ui.selectedCountryInner.className = flagClass;
3613
+ this.ui.selectedCountry.setAttribute("title", title);
3614
+ this.ui.selectedCountry.setAttribute(ARIA.LABEL, ariaLabel);
3284
3615
  }
3285
3616
  if (separateDialCode) {
3286
3617
  const dialCode = this.selectedCountryData.dialCode ? `+${this.selectedCountryData.dialCode}` : "";
3287
- this.selectedDialCode.innerHTML = dialCode;
3288
- this._updateInputPadding();
3618
+ this.ui.selectedDialCode.textContent = dialCode;
3619
+ this.ui.updateInputPadding();
3289
3620
  }
3290
3621
  this._updatePlaceholder();
3291
3622
  this._updateMaxLength();
3292
3623
  return prevIso2 !== iso2;
3293
3624
  }
3294
- //* Update the input padding to make space for the selected country/dial code.
3295
- _updateInputPadding() {
3296
- if (this.selectedCountry) {
3297
- const saneDefaultWidth = this.options.separateDialCode ? 78 : 42;
3298
- const selectedCountryWidth = this.selectedCountry.offsetWidth || this._getHiddenSelectedCountryWidth() || saneDefaultWidth;
3299
- const inputPadding = selectedCountryWidth + 6;
3300
- this.telInput.style.paddingLeft = `${inputPadding}px`;
3301
- }
3302
- }
3303
3625
  //* Update the maximum valid number length for the currently selected country.
3304
3626
  _updateMaxLength() {
3305
3627
  const { strictMode, placeholderNumberType, validationNumberTypes } = this.options;
@@ -3314,7 +3636,11 @@ var Iti = class _Iti {
3314
3636
  true
3315
3637
  );
3316
3638
  let validNumber = exampleNumber;
3317
- while (intlTelInput.utils.isPossibleNumber(exampleNumber, iso2, validationNumberTypes)) {
3639
+ while (intlTelInput.utils.isPossibleNumber(
3640
+ exampleNumber,
3641
+ iso2,
3642
+ validationNumberTypes
3643
+ )) {
3318
3644
  validNumber = exampleNumber;
3319
3645
  exampleNumber += "0";
3320
3646
  }
@@ -3328,31 +3654,6 @@ var Iti = class _Iti {
3328
3654
  }
3329
3655
  }
3330
3656
  }
3331
- //* When input is in a hidden container during init, we cannot calculate the selected country width.
3332
- //* Fix: clone the markup, make it invisible, add it to the end of the DOM, and then measure it's width.
3333
- //* To get the right styling to apply, all we need is a shallow clone of the container,
3334
- //* and then to inject a deep clone of the selectedCountry element.
3335
- _getHiddenSelectedCountryWidth() {
3336
- if (this.telInput.parentNode) {
3337
- let body;
3338
- try {
3339
- body = window.top.document.body;
3340
- } catch (e) {
3341
- body = document.body;
3342
- }
3343
- const containerClone = this.telInput.parentNode.cloneNode(false);
3344
- containerClone.style.visibility = "hidden";
3345
- body.appendChild(containerClone);
3346
- const countryContainerClone = this.countryContainer.cloneNode();
3347
- containerClone.appendChild(countryContainerClone);
3348
- const selectedCountryClone = this.selectedCountry.cloneNode(true);
3349
- countryContainerClone.appendChild(selectedCountryClone);
3350
- const width = selectedCountryClone.offsetWidth;
3351
- body.removeChild(containerClone);
3352
- return width;
3353
- }
3354
- return 0;
3355
- }
3356
3657
  //* Update the input placeholder to an example number from the currently selected country.
3357
3658
  _updatePlaceholder() {
3358
3659
  const {
@@ -3361,7 +3662,7 @@ var Iti = class _Iti {
3361
3662
  nationalMode,
3362
3663
  customPlaceholder
3363
3664
  } = this.options;
3364
- const shouldSetPlaceholder = autoPlaceholder === "aggressive" || !this.hadInitialPlaceholder && autoPlaceholder === "polite";
3665
+ const shouldSetPlaceholder = autoPlaceholder === "aggressive" || !this.ui.hadInitialPlaceholder && autoPlaceholder === "polite";
3365
3666
  if (intlTelInput.utils && shouldSetPlaceholder) {
3366
3667
  const numberType = intlTelInput.utils.numberType[placeholderNumberType];
3367
3668
  let placeholder = this.selectedCountryData.iso2 ? intlTelInput.utils.getExampleNumber(
@@ -3373,98 +3674,66 @@ var Iti = class _Iti {
3373
3674
  if (typeof customPlaceholder === "function") {
3374
3675
  placeholder = customPlaceholder(placeholder, this.selectedCountryData);
3375
3676
  }
3376
- this.telInput.setAttribute("placeholder", placeholder);
3677
+ this.ui.telInput.setAttribute("placeholder", placeholder);
3377
3678
  }
3378
3679
  }
3379
3680
  //* Called when the user selects a list item from the dropdown.
3380
3681
  _selectListItem(listItem) {
3381
- const iso2 = listItem.getAttribute("data-country-code");
3682
+ const iso2 = listItem.dataset[DATA_KEYS.COUNTRY_CODE];
3382
3683
  const countryChanged = this._setCountry(iso2);
3383
3684
  this._closeDropdown();
3384
- const dialCode = listItem.getAttribute("data-dial-code");
3685
+ const dialCode = listItem.dataset[DATA_KEYS.DIAL_CODE];
3385
3686
  this._updateDialCode(dialCode);
3386
3687
  if (this.options.formatOnDisplay) {
3387
- this._updateValFromNumber(this.telInput.value);
3688
+ this._updateValFromNumber(this.ui.telInput.value);
3388
3689
  }
3389
- this.telInput.focus();
3690
+ this.ui.telInput.focus();
3390
3691
  if (countryChanged) {
3391
3692
  this._triggerCountryChange();
3392
3693
  }
3393
3694
  }
3394
3695
  //* Close the dropdown and unbind any listeners.
3395
3696
  _closeDropdown() {
3396
- this.dropdownContent.classList.add("iti__hide");
3397
- this.selectedCountry.setAttribute("aria-expanded", "false");
3398
- if (this.highlightedItem) {
3399
- this.highlightedItem.setAttribute("aria-selected", "false");
3697
+ if (this.ui.dropdownContent.classList.contains(CLASSES.HIDE)) {
3698
+ return;
3400
3699
  }
3401
- if (this.options.countrySearch) {
3402
- this.searchInput.removeAttribute("aria-activedescendant");
3700
+ this.ui.dropdownContent.classList.add(CLASSES.HIDE);
3701
+ this.ui.selectedCountry.setAttribute(ARIA.EXPANDED, "false");
3702
+ if (this.ui.highlightedItem) {
3703
+ this.ui.highlightedItem.setAttribute(ARIA.SELECTED, "false");
3403
3704
  }
3404
- this.dropdownArrow.classList.remove("iti__arrow--up");
3405
3705
  if (this.options.countrySearch) {
3406
- this.searchInput.removeEventListener("input", this._handleSearchChange);
3407
- this.searchClearButton.removeEventListener("click", this._handleSearchClear);
3706
+ this.ui.searchInput.removeAttribute(ARIA.ACTIVE_DESCENDANT);
3408
3707
  }
3409
- document.removeEventListener("keydown", this._handleKeydownOnDropdown);
3410
- document.documentElement.removeEventListener(
3411
- "click",
3412
- this._handleClickOffToClose
3413
- );
3414
- this.countryList.removeEventListener(
3415
- "mouseover",
3416
- this._handleMouseoverCountryList
3417
- );
3418
- this.countryList.removeEventListener("click", this._handleClickCountryList);
3708
+ this.ui.dropdownArrow.classList.remove(CLASSES.ARROW_UP);
3709
+ this.dropdownAbortController.abort();
3710
+ this.dropdownAbortController = null;
3419
3711
  if (this.options.dropdownContainer) {
3420
- if (!this.options.useFullscreenPopup) {
3421
- window.removeEventListener("scroll", this._handleWindowScroll);
3422
- }
3423
- if (this.dropdown.parentNode) {
3424
- this.dropdown.parentNode.removeChild(this.dropdown);
3425
- }
3426
- }
3427
- this._trigger("close:countrydropdown");
3428
- }
3429
- //* Check if an element is visible within it's container, else scroll until it is.
3430
- _scrollTo(element) {
3431
- const container = this.countryList;
3432
- const scrollTop = document.documentElement.scrollTop;
3433
- const containerHeight = container.offsetHeight;
3434
- const containerTop = container.getBoundingClientRect().top + scrollTop;
3435
- const containerBottom = containerTop + containerHeight;
3436
- const elementHeight = element.offsetHeight;
3437
- const elementTop = element.getBoundingClientRect().top + scrollTop;
3438
- const elementBottom = elementTop + elementHeight;
3439
- const newScrollTop = elementTop - containerTop + container.scrollTop;
3440
- if (elementTop < containerTop) {
3441
- container.scrollTop = newScrollTop;
3442
- } else if (elementBottom > containerBottom) {
3443
- const heightDifference = containerHeight - elementHeight;
3444
- container.scrollTop = newScrollTop - heightDifference;
3712
+ this.ui.dropdown.remove();
3445
3713
  }
3714
+ this._trigger(EVENTS.CLOSE_COUNTRY_DROPDOWN);
3446
3715
  }
3447
3716
  //* Replace any existing dial code with the new one
3448
3717
  //* Note: called from _selectListItem and setCountry
3449
3718
  _updateDialCode(newDialCodeBare) {
3450
- const inputVal = this.telInput.value;
3719
+ const inputVal = this.ui.telInput.value;
3451
3720
  const newDialCode = `+${newDialCodeBare}`;
3452
3721
  let newNumber;
3453
- if (inputVal.charAt(0) === "+") {
3722
+ if (inputVal.startsWith("+")) {
3454
3723
  const prevDialCode = this._getDialCode(inputVal);
3455
3724
  if (prevDialCode) {
3456
3725
  newNumber = inputVal.replace(prevDialCode, newDialCode);
3457
3726
  } else {
3458
3727
  newNumber = newDialCode;
3459
3728
  }
3460
- this.telInput.value = newNumber;
3729
+ this.ui.telInput.value = newNumber;
3461
3730
  }
3462
3731
  }
3463
3732
  //* Try and extract a valid international dial code from a full telephone number.
3464
3733
  //* Note: returns the raw string inc plus character and any whitespace/dots etc.
3465
3734
  _getDialCode(number, includeAreaCode) {
3466
3735
  let dialCode = "";
3467
- if (number.charAt(0) === "+") {
3736
+ if (number.startsWith("+")) {
3468
3737
  let numericChars = "";
3469
3738
  for (let i = 0; i < number.length; i++) {
3470
3739
  const c = number.charAt(i);
@@ -3490,11 +3759,11 @@ var Iti = class _Iti {
3490
3759
  }
3491
3760
  //* Get the input val, adding the dial code if separateDialCode is enabled.
3492
3761
  _getFullNumber(overrideVal) {
3493
- const val = overrideVal || this.telInput.value.trim();
3762
+ const val = overrideVal || this.ui.telInput.value.trim();
3494
3763
  const { dialCode } = this.selectedCountryData;
3495
3764
  let prefix;
3496
3765
  const numericVal = getNumeric(val);
3497
- if (this.options.separateDialCode && val.charAt(0) !== "+" && dialCode && numericVal) {
3766
+ if (this.options.separateDialCode && !val.startsWith("+") && dialCode && numericVal) {
3498
3767
  prefix = `+${dialCode}`;
3499
3768
  } else {
3500
3769
  prefix = "";
@@ -3514,16 +3783,16 @@ var Iti = class _Iti {
3514
3783
  }
3515
3784
  //* Trigger the 'countrychange' event.
3516
3785
  _triggerCountryChange() {
3517
- this._trigger("countrychange");
3786
+ this._trigger(EVENTS.COUNTRY_CHANGE);
3518
3787
  }
3519
3788
  //**************************
3520
3789
  //* SECRET PUBLIC METHODS
3521
3790
  //**************************
3522
3791
  //* This is called when the geoip call returns.
3523
3792
  handleAutoCountry() {
3524
- if (this.options.initialCountry === "auto" && intlTelInput.autoCountry) {
3793
+ if (this.options.initialCountry === INITIAL_COUNTRY.AUTO && intlTelInput.autoCountry) {
3525
3794
  this.defaultCountry = intlTelInput.autoCountry;
3526
- const hasSelectedCountryOrGlobe = this.selectedCountryData.iso2 || this.selectedCountryInner.classList.contains("iti__globe");
3795
+ const hasSelectedCountryOrGlobe = this.selectedCountryData.iso2 || this.ui.selectedCountryInner.classList.contains(CLASSES.GLOBE);
3527
3796
  if (!hasSelectedCountryOrGlobe) {
3528
3797
  this.setCountry(this.defaultCountry);
3529
3798
  }
@@ -3533,8 +3802,8 @@ var Iti = class _Iti {
3533
3802
  //* This is called when the utils request completes.
3534
3803
  handleUtils() {
3535
3804
  if (intlTelInput.utils) {
3536
- if (this.telInput.value) {
3537
- this._updateValFromNumber(this.telInput.value);
3805
+ if (this.ui.telInput.value) {
3806
+ this._updateValFromNumber(this.ui.telInput.value);
3538
3807
  }
3539
3808
  if (this.selectedCountryData.iso2) {
3540
3809
  this._updatePlaceholder();
@@ -3548,45 +3817,20 @@ var Iti = class _Iti {
3548
3817
  //********************
3549
3818
  //* Remove plugin.
3550
3819
  destroy() {
3551
- this.telInput.iti = void 0;
3552
- const { allowDropdown, separateDialCode } = this.options;
3553
- if (allowDropdown) {
3554
- this._closeDropdown();
3555
- this.selectedCountry.removeEventListener(
3556
- "click",
3557
- this._handleClickSelectedCountry
3558
- );
3559
- this.countryContainer.removeEventListener(
3560
- "keydown",
3561
- this._handleCountryContainerKeydown
3562
- );
3563
- const label = this.telInput.closest("label");
3564
- if (label) {
3565
- label.removeEventListener("click", this._handleLabelClick);
3566
- }
3567
- }
3568
- const { form } = this.telInput;
3569
- if (this._handleHiddenInputSubmit && form) {
3570
- form.removeEventListener("submit", this._handleHiddenInputSubmit);
3571
- }
3572
- this.telInput.removeEventListener("input", this._handleInputEvent);
3573
- if (this._handleKeydownEvent) {
3574
- this.telInput.removeEventListener("keydown", this._handleKeydownEvent);
3575
- }
3576
- if (this._handlePasteEvent) {
3577
- this.telInput.removeEventListener("paste", this._handlePasteEvent);
3820
+ if (!this.ui.telInput) {
3821
+ return;
3578
3822
  }
3579
- if (this._handlePageLoad) {
3580
- window.removeEventListener("load", this._handlePageLoad);
3823
+ if (this.options.allowDropdown) {
3824
+ this._closeDropdown();
3581
3825
  }
3582
- this.telInput.removeAttribute("data-intl-tel-input-id");
3583
- if (separateDialCode) {
3584
- this.telInput.style.paddingLeft = this.originalPaddingLeft;
3826
+ this.abortController.abort();
3827
+ this.abortController = null;
3828
+ this.ui.destroy();
3829
+ if (intlTelInput.instances instanceof Map) {
3830
+ intlTelInput.instances.delete(this.id);
3831
+ } else {
3832
+ delete intlTelInput.instances[this.id];
3585
3833
  }
3586
- const wrapper = this.telInput.parentNode;
3587
- wrapper?.parentNode?.insertBefore(this.telInput, wrapper);
3588
- wrapper?.parentNode?.removeChild(wrapper);
3589
- delete intlTelInput.instances[this.id];
3590
3834
  }
3591
3835
  //* Get the extension from the current number.
3592
3836
  getExtension() {
@@ -3618,7 +3862,7 @@ var Iti = class _Iti {
3618
3862
  this.selectedCountryData.iso2
3619
3863
  );
3620
3864
  }
3621
- return -99;
3865
+ return SENTINELS.UNKNOWN_NUMBER_TYPE;
3622
3866
  }
3623
3867
  //* Get the country data for the currently selected country.
3624
3868
  getSelectedCountryData() {
@@ -3630,15 +3874,15 @@ var Iti = class _Iti {
3630
3874
  const { iso2 } = this.selectedCountryData;
3631
3875
  return intlTelInput.utils.getValidationError(this._getFullNumber(), iso2);
3632
3876
  }
3633
- return -99;
3877
+ return SENTINELS.UNKNOWN_VALIDATION_ERROR;
3634
3878
  }
3635
3879
  //* Validate the input val using number length only
3636
3880
  isValidNumber() {
3637
3881
  const { dialCode, iso2 } = this.selectedCountryData;
3638
- if (dialCode === "44" && intlTelInput.utils) {
3882
+ if (dialCode === UK.DIAL_CODE && intlTelInput.utils) {
3639
3883
  const number = this._getFullNumber();
3640
3884
  const coreNumber = intlTelInput.utils.getCoreNumber(number, iso2);
3641
- if (coreNumber[0] === "7" && coreNumber.length !== 10) {
3885
+ if (coreNumber[0] === UK.MOBILE_PREFIX && coreNumber.length !== UK.MOBILE_CORE_LENGTH) {
3642
3886
  return false;
3643
3887
  }
3644
3888
  }
@@ -3649,7 +3893,11 @@ var Iti = class _Iti {
3649
3893
  return this._validateNumber(true);
3650
3894
  }
3651
3895
  _utilsIsPossibleNumber(val) {
3652
- return intlTelInput.utils ? intlTelInput.utils.isPossibleNumber(val, this.selectedCountryData.iso2, this.options.validationNumberTypes) : null;
3896
+ return intlTelInput.utils ? intlTelInput.utils.isPossibleNumber(
3897
+ val,
3898
+ this.selectedCountryData.iso2,
3899
+ this.options.validationNumberTypes
3900
+ ) : null;
3653
3901
  }
3654
3902
  //* Shared internal validation logic to handle alpha character extension rules.
3655
3903
  _validateNumber(precise) {
@@ -3661,7 +3909,7 @@ var Iti = class _Iti {
3661
3909
  }
3662
3910
  const testValidity = (s) => precise ? this._utilsIsValidNumber(s) : this._utilsIsPossibleNumber(s);
3663
3911
  const val = this._getFullNumber();
3664
- const alphaCharPosition = val.search(/\p{L}/u);
3912
+ const alphaCharPosition = val.search(REGEX.ALPHA_UNICODE);
3665
3913
  const hasAlphaChar = alphaCharPosition > -1;
3666
3914
  if (hasAlphaChar && !this.options.allowPhonewords) {
3667
3915
  const beforeAlphaChar = val.substring(0, alphaCharPosition);
@@ -3672,7 +3920,11 @@ var Iti = class _Iti {
3672
3920
  return testValidity(val);
3673
3921
  }
3674
3922
  _utilsIsValidNumber(val) {
3675
- return intlTelInput.utils ? intlTelInput.utils.isValidNumber(val, this.selectedCountryData.iso2, this.options.validationNumberTypes) : null;
3923
+ return intlTelInput.utils ? intlTelInput.utils.isValidNumber(
3924
+ val,
3925
+ this.selectedCountryData.iso2,
3926
+ this.options.validationNumberTypes
3927
+ ) : null;
3676
3928
  }
3677
3929
  //* Update the selected country, and update the input val accordingly.
3678
3930
  setCountry(iso2) {
@@ -3686,7 +3938,7 @@ var Iti = class _Iti {
3686
3938
  this._setCountry(iso2Lower);
3687
3939
  this._updateDialCode(this.selectedCountryData.dialCode);
3688
3940
  if (this.options.formatOnDisplay) {
3689
- this._updateValFromNumber(this.telInput.value);
3941
+ this._updateValFromNumber(this.ui.telInput.value);
3690
3942
  }
3691
3943
  this._triggerCountryChange();
3692
3944
  }
@@ -3698,7 +3950,7 @@ var Iti = class _Iti {
3698
3950
  if (countryChanged) {
3699
3951
  this._triggerCountryChange();
3700
3952
  }
3701
- this._trigger("input", { isSetNumber: true });
3953
+ this._trigger(EVENTS.INPUT, { isSetNumber: true });
3702
3954
  }
3703
3955
  //* Set the placeholder number typ
3704
3956
  setPlaceholderNumberType(type) {
@@ -3706,11 +3958,11 @@ var Iti = class _Iti {
3706
3958
  this._updatePlaceholder();
3707
3959
  }
3708
3960
  setDisabled(disabled) {
3709
- this.telInput.disabled = disabled;
3961
+ this.ui.telInput.disabled = disabled;
3710
3962
  if (disabled) {
3711
- this.selectedCountry.setAttribute("disabled", "true");
3963
+ this.ui.selectedCountry.setAttribute("disabled", "true");
3712
3964
  } else {
3713
- this.selectedCountry.removeAttribute("disabled");
3965
+ this.ui.selectedCountry.removeAttribute("disabled");
3714
3966
  }
3715
3967
  }
3716
3968
  };
@@ -3724,13 +3976,19 @@ var attachUtils = (source) => {
3724
3976
  return Promise.reject(error);
3725
3977
  }
3726
3978
  } else {
3727
- return Promise.reject(new TypeError(`The argument passed to attachUtils must be a function that returns a promise for the utilities module, not ${typeof source}`));
3979
+ return Promise.reject(
3980
+ new TypeError(
3981
+ `The argument passed to attachUtils must be a function that returns a promise for the utilities module, not ${typeof source}`
3982
+ )
3983
+ );
3728
3984
  }
3729
3985
  intlTelInput.startedLoadingUtilsScript = true;
3730
3986
  return loadCall.then((module2) => {
3731
3987
  const utils = module2?.default;
3732
3988
  if (!utils || typeof utils !== "object") {
3733
- throw new TypeError("The loader function passed to attachUtils did not resolve to a module object with utils as its default export.");
3989
+ throw new TypeError(
3990
+ "The loader function passed to attachUtils did not resolve to a module object with utils as its default export."
3991
+ );
3734
3992
  }
3735
3993
  intlTelInput.utils = utils;
3736
3994
  forEachInstance("handleUtils");
@@ -3742,11 +4000,17 @@ var attachUtils = (source) => {
3742
4000
  }
3743
4001
  return null;
3744
4002
  };
4003
+ var forEachInstance = (method, ...args) => {
4004
+ Object.values(intlTelInput.instances).forEach((instance) => {
4005
+ const fn = instance[method];
4006
+ if (typeof fn === "function") {
4007
+ fn.apply(instance, args);
4008
+ }
4009
+ });
4010
+ };
3745
4011
  var intlTelInput = Object.assign(
3746
4012
  (input, options) => {
3747
4013
  const iti = new Iti(input, options);
3748
- iti._init();
3749
- input.setAttribute("data-intl-tel-input-id", iti.id.toString());
3750
4014
  intlTelInput.instances[iti.id] = iti;
3751
4015
  input.iti = iti;
3752
4016
  return iti;
@@ -3759,7 +4023,7 @@ var intlTelInput = Object.assign(
3759
4023
  getCountryData: () => data_default,
3760
4024
  //* A getter for the plugin instance.
3761
4025
  getInstance: (input) => {
3762
- const id2 = input.getAttribute("data-intl-tel-input-id");
4026
+ const id2 = input.dataset.intlTelInputId;
3763
4027
  return id2 ? intlTelInput.instances[id2] : null;
3764
4028
  },
3765
4029
  //* A map from instance ID to instance object.
@@ -3767,7 +4031,7 @@ var intlTelInput = Object.assign(
3767
4031
  attachUtils,
3768
4032
  startedLoadingUtilsScript: false,
3769
4033
  startedLoadingAutoCountry: false,
3770
- version: "25.10.12"
4034
+ version: "25.11.1"
3771
4035
  }
3772
4036
  );
3773
4037
  var intl_tel_input_default = intlTelInput;