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