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