intl-tel-input
Version:
A JavaScript library for entering, formatting, and validating international telephone numbers
2,719 lines (2,710 loc) • 121 kB
JavaScript
// packages/core/src/js/data.ts
var rawCountryData = [
[
"af",
// Afghanistan
"93",
0,
null,
"0"
],
[
"ax",
// Åland Islands (AKA Aland Islands)
"358",
1,
["18", "4"],
// (4 is a mobile range shared with FI)
// NOTE: https://en.wikipedia.org/wiki/Telephone%20numbers%20in%20%C3%85land says some 4XXX ranges (e.g. 4570) are specific to AX, but LPN doesn't respect this (https://libphonenumber.appspot.com/phonenumberparser?number=%2B3584570123456 says region=FI) so we won't either. Also it's too much of a maintenance burden to keep track of. Keep the 4 area code range here so that if the user selects AX and types this kind of number, we wont change the flag to FI. Whereas if they type a FI-only range then we will.
"0"
],
[
"al",
// Albania
"355",
0,
null,
"0"
],
[
"dz",
// Algeria
"213",
0,
null,
"0"
],
[
"as",
// American Samoa
"1",
5,
["684"],
"1"
],
[
"ad",
// Andorra
"376"
],
[
"ao",
// Angola
"244"
],
[
"ai",
// Anguilla
"1",
6,
["264"],
"1"
],
[
"ag",
// Antigua and Barbuda
"1",
7,
["268"],
"1"
],
[
"ar",
// Argentina
"54",
0,
null,
"0"
],
[
"am",
// Armenia
"374",
0,
null,
"0"
],
[
"aw",
// Aruba
"297"
],
[
"ac",
// Ascension Island
"247"
],
[
"au",
// Australia
"61",
0,
["4"],
// (mobile range shared with CX and CC)
"0"
],
[
"at",
// Austria
"43",
0,
null,
"0"
],
[
"az",
// Azerbaijan
"994",
0,
null,
"0"
],
[
"bs",
// Bahamas
"1",
8,
["242"],
"1"
],
[
"bh",
// Bahrain
"973"
],
[
"bd",
// Bangladesh
"880",
0,
null,
"0"
],
[
"bb",
// Barbados
"1",
9,
["246"],
"1"
],
[
"by",
// Belarus
"375",
0,
null,
"8"
],
[
"be",
// Belgium
"32",
0,
null,
"0"
],
[
"bz",
// Belize
"501"
],
[
"bj",
// Benin
"229"
],
[
"bm",
// Bermuda
"1",
10,
["441"],
"1"
],
[
"bt",
// Bhutan
"975"
],
[
"bo",
// Bolivia
"591",
0,
null,
"0"
],
[
"ba",
// Bosnia and Herzegovina
"387",
0,
null,
"0"
],
[
"bw",
// Botswana
"267"
],
[
"br",
// Brazil
"55",
0,
null,
"0"
],
[
"io",
// British Indian Ocean Territory
"246"
],
[
"vg",
// British Virgin Islands
"1",
11,
["284"],
"1"
],
[
"bn",
// Brunei
"673"
],
[
"bg",
// Bulgaria
"359",
0,
null,
"0"
],
[
"bf",
// Burkina Faso
"226"
],
[
"bi",
// Burundi
"257"
],
[
"kh",
// Cambodia
"855",
0,
null,
"0"
],
[
"cm",
// Cameroon
"237"
],
[
"ca",
// Canada
"1",
1,
[
"204",
"226",
"236",
"249",
"250",
"257",
"263",
"289",
"306",
"343",
"354",
"365",
"367",
"368",
"382",
"403",
"416",
"418",
"428",
"431",
"437",
"438",
"450",
"468",
"474",
"506",
"514",
"519",
"548",
"579",
"581",
"584",
"587",
"604",
"613",
"639",
"647",
"672",
"683",
"705",
"709",
"742",
"753",
"778",
"780",
"782",
"807",
"819",
"825",
"867",
"873",
"879",
"902",
"905",
"942"
],
"1"
],
[
"cv",
// Cape Verde
"238"
],
[
"bq",
// Caribbean Netherlands
"599",
1,
["3", "4", "7"]
],
[
"ky",
// Cayman Islands
"1",
12,
["345"],
"1"
],
[
"cf",
// Central African Republic
"236"
],
[
"td",
// Chad
"235"
],
[
"cl",
// Chile
"56"
],
[
"cn",
// China
"86",
0,
null,
"0"
],
[
"cx",
// Christmas Island
"61",
2,
["4", "89164"],
// (4 is a mobile range shared with AU and CC)
"0"
],
[
"cc",
// Cocos (Keeling) Islands
"61",
1,
["4", "89162"],
// (4 is a mobile range shared with AU and CX)
"0"
],
[
"co",
// Colombia
"57",
0,
null,
"0"
],
[
"km",
// Comoros
"269"
],
[
"cg",
// Congo (Brazzaville)
"242"
],
[
"cd",
// Congo (Kinshasa)
"243",
0,
null,
"0"
],
[
"ck",
// Cook Islands
"682"
],
[
"cr",
// Costa Rica
"506"
],
[
"ci",
// Côte d'Ivoire
"225"
],
[
"hr",
// Croatia
"385",
0,
null,
"0"
],
[
"cu",
// Cuba
"53",
0,
null,
"0"
],
[
"cw",
// Curaçao
"599",
0
],
[
"cy",
// Cyprus
"357"
],
[
"cz",
// Czech Republic
"420"
],
[
"dk",
// Denmark
"45"
],
[
"dj",
// Djibouti
"253"
],
[
"dm",
// Dominica
"1",
13,
["767"],
"1"
],
[
"do",
// Dominican Republic
"1",
2,
["809", "829", "849"],
"1"
],
[
"ec",
// Ecuador
"593",
0,
null,
"0"
],
[
"eg",
// Egypt
"20",
0,
null,
"0"
],
[
"sv",
// El Salvador
"503"
],
[
"gq",
// Equatorial Guinea
"240"
],
[
"er",
// Eritrea
"291",
0,
null,
"0"
],
[
"ee",
// Estonia
"372"
],
[
"sz",
// Eswatini
"268"
],
[
"et",
// Ethiopia
"251",
0,
null,
"0"
],
[
"fk",
// Falkland Islands (Malvinas)
"500"
],
[
"fo",
// Faroe Islands
"298"
],
[
"fj",
// Fiji
"679"
],
[
"fi",
// Finland
"358",
0,
["4"],
// (mobile range shared with AX)
"0"
],
[
"fr",
// France
"33",
0,
null,
"0"
],
[
"gf",
// French Guiana
"594",
0,
null,
"0"
],
[
"pf",
// French Polynesia
"689"
],
[
"ga",
// Gabon
"241"
],
[
"gm",
// Gambia
"220"
],
[
"ge",
// Georgia
"995",
0,
null,
"0"
],
[
"de",
// Germany
"49",
0,
null,
"0"
],
[
"gh",
// Ghana
"233",
0,
null,
"0"
],
[
"gi",
// Gibraltar
"350"
],
[
"gr",
// Greece
"30"
],
[
"gl",
// Greenland
"299"
],
[
"gd",
// Grenada
"1",
14,
["473"],
"1"
],
[
"gp",
// Guadeloupe
"590",
0,
null,
"0"
],
[
"gu",
// Guam
"1",
15,
["671"],
"1"
],
[
"gt",
// Guatemala
"502"
],
[
"gg",
// Guernsey
"44",
1,
["1481", "7781", "7839", "7911"],
"0"
],
[
"gn",
// Guinea
"224"
],
[
"gw",
// Guinea-Bissau
"245"
],
[
"gy",
// Guyana
"592"
],
[
"ht",
// Haiti
"509"
],
[
"hn",
// Honduras
"504"
],
[
"hk",
// Hong Kong SAR China
"852"
],
[
"hu",
// Hungary
"36",
0,
null,
"06"
],
[
"is",
// Iceland
"354"
],
[
"in",
// India
"91",
0,
null,
"0"
],
[
"id",
// Indonesia
"62",
0,
null,
"0"
],
[
"ir",
// Iran
"98",
0,
null,
"0"
],
[
"iq",
// Iraq
"964",
0,
null,
"0"
],
[
"ie",
// Ireland
"353",
0,
null,
"0"
],
[
"im",
// Isle of Man
"44",
2,
["1624", "74576", "7524", "7624", "7924"],
"0"
],
[
"il",
// Israel
"972",
0,
null,
"0"
],
[
"it",
// Italy
"39",
0,
["3"]
// (mobile range shared with VA)
],
[
"jm",
// Jamaica
"1",
4,
["658", "876"],
"1"
],
[
"jp",
// Japan
"81",
0,
null,
"0"
],
[
"je",
// Jersey
"44",
3,
["1534", "7509", "7700", "7797", "7829", "7937"],
"0"
],
[
"jo",
// Jordan
"962",
0,
null,
"0"
],
[
"kz",
// Kazakhstan
"7",
1,
["33", "7"],
// (33 is shared with RU)
"8"
],
[
"ke",
// Kenya
"254",
0,
null,
"0"
],
[
"ki",
// Kiribati
"686",
0,
null,
"0"
],
[
"xk",
// Kosovo
"383",
0,
null,
"0"
],
[
"kw",
// Kuwait
"965"
],
[
"kg",
// Kyrgyzstan
"996",
0,
null,
"0"
],
[
"la",
// Laos
"856",
0,
null,
"0"
],
[
"lv",
// Latvia
"371"
],
[
"lb",
// Lebanon
"961",
0,
null,
"0"
],
[
"ls",
// Lesotho
"266"
],
[
"lr",
// Liberia
"231",
0,
null,
"0"
],
[
"ly",
// Libya
"218",
0,
null,
"0"
],
[
"li",
// Liechtenstein
"423",
0,
null,
"0"
],
[
"lt",
// Lithuania
"370",
0,
null,
"0"
],
[
"lu",
// Luxembourg
"352"
],
[
"mo",
// Macao SAR China
"853"
],
[
"mg",
// Madagascar
"261",
0,
null,
"0"
],
[
"mw",
// Malawi
"265",
0,
null,
"0"
],
[
"my",
// Malaysia
"60",
0,
null,
"0"
],
[
"mv",
// Maldives
"960"
],
[
"ml",
// Mali
"223"
],
[
"mt",
// Malta
"356"
],
[
"mh",
// Marshall Islands
"692",
0,
null,
"1"
],
[
"mq",
// Martinique
"596",
0,
null,
"0"
],
[
"mr",
// Mauritania
"222"
],
[
"mu",
// Mauritius
"230"
],
[
"yt",
// Mayotte
"262",
1,
["269", "639"],
"0"
],
[
"mx",
// Mexico
"52"
],
[
"fm",
// Micronesia
"691"
],
[
"md",
// Moldova
"373",
0,
null,
"0"
],
[
"mc",
// Monaco
"377",
0,
null,
"0"
],
[
"mn",
// Mongolia
"976",
0,
null,
"0"
],
[
"me",
// Montenegro
"382",
0,
null,
"0"
],
[
"ms",
// Montserrat
"1",
16,
["664"],
"1"
],
[
"ma",
// Morocco
"212",
0,
["6", "7"],
// (mobile ranges shared with EH)
"0"
],
[
"mz",
// Mozambique
"258"
],
[
"mm",
// Myanmar (Burma)
"95",
0,
null,
"0"
],
[
"na",
// Namibia
"264",
0,
null,
"0"
],
[
"nr",
// Nauru
"674"
],
[
"np",
// Nepal
"977",
0,
null,
"0"
],
[
"nl",
// Netherlands
"31",
0,
null,
"0"
],
[
"nc",
// New Caledonia
"687"
],
[
"nz",
// New Zealand
"64",
0,
null,
"0"
],
[
"ni",
// Nicaragua
"505"
],
[
"ne",
// Niger
"227"
],
[
"ng",
// Nigeria
"234",
0,
null,
"0"
],
[
"nu",
// Niue
"683"
],
[
"nf",
// Norfolk Island
"672"
],
[
"kp",
// North Korea
"850",
0,
null,
"0"
],
[
"mk",
// North Macedonia
"389",
0,
null,
"0"
],
[
"mp",
// Northern Mariana Islands
"1",
17,
["670"],
"1"
],
[
"no",
// Norway
"47",
0,
["4", "9"]
// (mobile ranges shared with SJ)
],
[
"om",
// Oman
"968"
],
[
"pk",
// Pakistan
"92",
0,
null,
"0"
],
[
"pw",
// Palau
"680"
],
[
"ps",
// Palestinian Territories
"970",
0,
null,
"0"
],
[
"pa",
// Panama
"507"
],
[
"pg",
// Papua New Guinea
"675"
],
[
"py",
// Paraguay
"595",
0,
null,
"0"
],
[
"pe",
// Peru
"51",
0,
null,
"0"
],
[
"ph",
// Philippines
"63",
0,
null,
"0"
],
[
"pl",
// Poland
"48"
],
[
"pt",
// Portugal
"351"
],
[
"pr",
// Puerto Rico
"1",
3,
["787", "939"],
"1"
],
[
"qa",
// Qatar
"974"
],
[
"re",
// Réunion
"262",
0,
null,
"0"
],
[
"ro",
// Romania
"40",
0,
null,
"0"
],
[
"ru",
// Russia
"7",
0,
["33"],
// (shared with KZ)
"8"
],
[
"rw",
// Rwanda
"250",
0,
null,
"0"
],
[
"ws",
// Samoa
"685"
],
[
"sm",
// San Marino
"378"
],
[
"st",
// São Tomé & Príncipe
"239"
],
[
"sa",
// Saudi Arabia
"966",
0,
null,
"0"
],
[
"sn",
// Senegal
"221"
],
[
"rs",
// Serbia
"381",
0,
null,
"0"
],
[
"sc",
// Seychelles
"248"
],
[
"sl",
// Sierra Leone
"232",
0,
null,
"0"
],
[
"sg",
// Singapore
"65"
],
[
"sx",
// Sint Maarten
"1",
21,
["721"],
"1"
],
[
"sk",
// Slovakia
"421",
0,
null,
"0"
],
[
"si",
// Slovenia
"386",
0,
null,
"0"
],
[
"sb",
// Solomon Islands
"677"
],
[
"so",
// Somalia
"252",
0,
null,
"0"
],
[
"za",
// South Africa
"27",
0,
null,
"0"
],
[
"kr",
// South Korea
"82",
0,
null,
"0"
],
[
"ss",
// South Sudan
"211",
0,
null,
"0"
],
[
"es",
// Spain
"34"
],
[
"lk",
// Sri Lanka
"94",
0,
null,
"0"
],
[
"bl",
// St. Barthélemy
"590",
1,
null,
"0"
],
[
"sh",
// St. Helena
"290"
],
[
"kn",
// St. Kitts & Nevis
"1",
18,
["869"],
"1"
],
[
"lc",
// St. Lucia
"1",
19,
["758"],
"1"
],
[
"mf",
// St. Martin
"590",
2,
null,
"0"
],
[
"pm",
// St. Pierre & Miquelon
"508",
0,
null,
"0"
],
[
"vc",
// St. Vincent & Grenadines
"1",
20,
["784"],
"1"
],
[
"sd",
// Sudan
"249",
0,
null,
"0"
],
[
"sr",
// Suriname
"597"
],
[
"sj",
// Svalbard & Jan Mayen
"47",
1,
["4", "79", "9"]
// (4 and 9 are mobile ranges shared with NO)
],
[
"se",
// Sweden
"46",
0,
null,
"0"
],
[
"ch",
// Switzerland
"41",
0,
null,
"0"
],
[
"sy",
// Syria
"963",
0,
null,
"0"
],
[
"tw",
// Taiwan
"886",
0,
null,
"0"
],
[
"tj",
// Tajikistan
"992"
],
[
"tz",
// Tanzania
"255",
0,
null,
"0"
],
[
"th",
// Thailand
"66",
0,
null,
"0"
],
[
"tl",
// Timor-Leste
"670"
],
[
"tg",
// Togo
"228"
],
[
"tk",
// Tokelau
"690"
],
[
"to",
// Tonga
"676"
],
[
"tt",
// Trinidad & Tobago
"1",
22,
["868"],
"1"
],
[
"tn",
// Tunisia
"216"
],
[
"tr",
// Turkey
"90",
0,
null,
"0"
],
[
"tm",
// Turkmenistan
"993",
0,
null,
"8"
],
[
"tc",
// Turks & Caicos Islands
"1",
23,
["649"],
"1"
],
[
"tv",
// Tuvalu
"688"
],
[
"vi",
// U.S. Virgin Islands
"1",
24,
["340"],
"1"
],
[
"ug",
// Uganda
"256",
0,
null,
"0"
],
[
"ua",
// Ukraine
"380",
0,
null,
"0"
],
[
"ae",
// United Arab Emirates
"971",
0,
null,
"0"
],
[
"gb",
// United Kingdom
"44",
0,
null,
"0"
],
[
"us",
// United States
"1",
0,
null,
"1"
],
[
"uy",
// Uruguay
"598",
0,
null,
"0"
],
[
"uz",
// Uzbekistan
"998"
],
[
"vu",
// Vanuatu
"678"
],
[
"va",
// Vatican City
"39",
1,
["06698", "3"]
// (3 is a mobile range shared with IT)
],
[
"ve",
// Venezuela
"58",
0,
null,
"0"
],
[
"vn",
// Vietnam
"84",
0,
null,
"0"
],
[
"wf",
// Wallis & Futuna
"681"
],
[
"eh",
// Western Sahara
"212",
1,
["5288", "5289", "6", "7"],
// (6 and 7 are mobile ranges shared with MA)
"0"
],
[
"ye",
// Yemen
"967",
0,
null,
"0"
],
[
"zm",
// Zambia
"260",
0,
null,
"0"
],
[
"zw",
// Zimbabwe
"263",
0,
null,
"0"
]
];
var allCountries = [];
for (const c of rawCountryData) {
allCountries.push({
name: "",
// populated in the core library
iso2: c[0],
dialCode: c[1],
priority: c[2] || 0,
areaCodes: c[3] || null,
nationalPrefix: c[4] || null
});
}
var iso2Set = new Set(allCountries.map((c) => c.iso2));
var isIso2 = (val) => iso2Set.has(val);
var data_default = allCountries;
// packages/core/src/js/constants.ts
var EVENTS = {
OPEN_COUNTRY_DROPDOWN: "open:countrydropdown",
CLOSE_COUNTRY_DROPDOWN: "close:countrydropdown",
COUNTRY_CHANGE: "countrychange",
INPUT: "input",
// used for synthetic input trigger
STRICT_REJECT: "strict:reject"
};
var CLASSES = {
HIDE: "iti__hide",
V_HIDE: "iti__v-hide",
ARROW_UP: "iti__arrow--up",
GLOBE: "iti__globe",
FLAG: "iti__flag",
LOADING: "iti__loading",
COUNTRY_ITEM: "iti__country",
HIGHLIGHT: "iti__highlight"
};
var KEYS = {
ARROW_UP: "ArrowUp",
ARROW_DOWN: "ArrowDown",
SPACE: " ",
ENTER: "Enter",
ESC: "Escape",
TAB: "Tab"
};
var INPUT_TYPES = {
PASTE: "insertFromPaste",
DELETE_FORWARD: "deleteContentForward"
};
var REGEX = {
ALPHA_UNICODE: /\p{L}/u,
// any kind of letter from any language
NON_PLUS_NUMERIC: /[^+0-9]/,
// chars that are NOT + or digit
NON_PLUS_NUMERIC_GLOBAL: /[^+0-9]/g,
// chars that are NOT + or digit (global)
HIDDEN_SEARCH_CHAR: /^[a-zA-ZÀ-ÿа-яА-Я ]$/
// single acceptable hidden-search char
};
var TIMINGS = {
SEARCH_DEBOUNCE_MS: 100,
HIDDEN_SEARCH_RESET_MS: 1e3,
NEXT_TICK: 0
};
var LAYOUT = {
NARROW_VIEWPORT_WIDTH: 500,
// keep in sync with .iti__country-list CSS media query
FALLBACK_SELECTED_WITH_DIAL_WIDTH: 78,
// px width fallback when separateDialCode enabled
FALLBACK_SELECTED_NO_DIAL_WIDTH: 42,
// px width fallback when no separate dial code
INPUT_PADDING_EXTRA_LEFT: 6,
// px gap between selected country container and input text
DROPDOWN_MARGIN: 3,
// px margin between dropdown and tel input
FALLBACK_DROPDOWN_HEIGHT: 200
// px height fallback for dropdown
};
var DIAL_CODE = {
PLUS: "+",
NANP: "1"
// North American Numbering Plan
};
var UK = {
ISO2: "gb",
DIAL_CODE: "44",
// +44 United Kingdom
MOBILE_PREFIX: "7",
// UK mobile numbers start with 7 after national trunk (0) or core section
MOBILE_CORE_LENGTH: 10
// core number length (excluding dial code / national prefix) for mobiles
};
var US = {
ISO2: "us",
DIAL_CODE: "1"
// +1 United States
};
var PLACEHOLDER_MODES = {
AGGRESSIVE: "aggressive",
POLITE: "polite",
OFF: "off"
};
var INITIAL_COUNTRY = {
AUTO: "auto"
};
var NUMBER_FORMATS = [
"E164",
"INTERNATIONAL",
"NATIONAL",
"RFC3966"
];
var NUMBER_TYPES = [
"FIXED_LINE",
"MOBILE",
"FIXED_LINE_OR_MOBILE",
"TOLL_FREE",
"PREMIUM_RATE",
"SHARED_COST",
"VOIP",
"PERSONAL_NUMBER",
"PAGER",
"UAN",
"VOICEMAIL",
"UNKNOWN"
];
var VALIDATION_ERRORS = [
"IS_POSSIBLE",
"INVALID_COUNTRY_CODE",
"TOO_SHORT",
"TOO_LONG",
"IS_POSSIBLE_LOCAL_ONLY",
"INVALID_LENGTH"
];
var toEnumObject = (arr) => Object.fromEntries(arr.map((v) => [v, v]));
var NUMBER_FORMAT = toEnumObject(NUMBER_FORMATS);
var NUMBER_TYPE = toEnumObject(NUMBER_TYPES);
var VALIDATION_ERROR = toEnumObject(VALIDATION_ERRORS);
var DATA_KEYS = {
// e.g. <li data-iso2="us"> for country items in dropdown
ISO2: "iso2",
DIAL_CODE: "dialCode",
// e.g. <input data-intl-tel-input-id="0"> on the input element
INSTANCE_ID: "intlTelInputId"
};
var ARIA = {
EXPANDED: "aria-expanded",
LABEL: "aria-label",
SELECTED: "aria-selected",
ACTIVE_DESCENDANT: "aria-activedescendant",
HASPOPUP: "aria-haspopup",
CONTROLS: "aria-controls",
HIDDEN: "aria-hidden",
AUTOCOMPLETE: "aria-autocomplete",
MODAL: "aria-modal"
};
// packages/core/src/js/i18n/en.ts
var interfaceTranslations = {
selectedCountryAriaLabel: "Change country for phone number, currently selected ${countryName} (${dialCode})",
noCountrySelected: "Select country for phone number",
countryListAriaLabel: "List of countries",
searchPlaceholder: "Search",
clearSearchAriaLabel: "Clear search",
searchEmptyState: "No results found",
searchSummaryAria(count) {
if (count === 0) {
return "No results found";
}
if (count === 1) {
return "1 result found";
}
return `${count} results found`;
}
};
var en_default = interfaceTranslations;
// packages/core/src/js/core/options.ts
var mediaQuery = (q) => typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(q).matches;
var isNarrowViewport = () => mediaQuery(`(max-width: ${LAYOUT.NARROW_VIEWPORT_WIDTH}px)`);
var computeDefaultUseFullscreenPopup = () => {
if (typeof navigator !== "undefined" && typeof window !== "undefined") {
const isShortViewport = mediaQuery("(max-height: 600px)");
const isCoarsePointer = mediaQuery("(pointer: coarse)");
return isNarrowViewport() || isCoarsePointer && isShortViewport;
}
return false;
};
var defaults = {
//* Whether or not to allow the dropdown.
allowDropdown: true,
//* The number type to enforce during validation.
allowedNumberTypes: [NUMBER_TYPE.MOBILE, NUMBER_TYPE.FIXED_LINE],
//* Whether or not to allow extensions after the main number.
allowNumberExtensions: false,
// Allow alphanumeric "phonewords" (e.g. +1 800 FLOWERS) as valid numbers
allowPhonewords: false,
//* Add a placeholder in the input with an example number for the selected country.
autoPlaceholder: PLACEHOLDER_MODES.POLITE,
//* Add a custom class to the (injected) container element.
containerClass: "",
//* Locale for localising country names via Intl.DisplayNames.
countryNameLocale: "en",
//* Override individual country names by iso2 code.
countryNameOverrides: {},
//* The order of the countries in the dropdown. Defaults to alphabetical.
countryOrder: null,
//* Add a country search input at the top of the dropdown.
countrySearch: true,
//* Modify the auto placeholder.
customPlaceholder: null,
//* Always show the dropdown
dropdownAlwaysOpen: false,
//* Append menu to specified element.
dropdownContainer: null,
//* Don't display these countries.
excludeCountries: null,
//* Fix the dropdown width to the input width (rather than being as wide as the longest country name).
fixDropdownWidth: true,
//* Format the number as the user types
formatAsYouType: true,
//* Format the input value during initialisation and on setNumber.
formatOnDisplay: true,
//* geoIp lookup function.
geoIpLookup: null,
//* Inject a hidden input with the name returned from this function, and on submit, populate it with the result of getNumber.
hiddenInput: null,
//* Internationalise the core library text e.g. search input placeholder, country names.
i18n: {},
//* Initial country.
initialCountry: "",
//* A function to load the utils script.
loadUtils: null,
//* National vs international formatting for numbers e.g. placeholders and displaying existing numbers.
nationalMode: false,
//* Display only these countries.
onlyCountries: null,
//* Number type to use for placeholders.
placeholderNumberType: NUMBER_TYPE.MOBILE,
//* Add custom classes to the search input element.
searchInputClass: "",
//* Display the international dial code next to the selected flag.
separateDialCode: true,
//* When strictMode rejects a key (etc), play a short feedback animation
strictRejectAnimation: true,
//* Show flags - for both the selected country, and in the country dropdown
showFlags: true,
//* Only allow certain chars e.g. a plus followed by numeric digits, and cap at max valid length.
strictMode: true,
//* Use full screen popup instead of dropdown for country list.
useFullscreenPopup: computeDefaultUseFullscreenPopup()
};
var toString = (val) => JSON.stringify(val);
var isPlainObject = (val) => Boolean(val) && typeof val === "object" && !Array.isArray(val);
var isFunction = (val) => typeof val === "function";
var isElLike = (val) => {
if (!val || typeof val !== "object") {
return false;
}
const v = val;
return v.nodeType === 1 && typeof v.tagName === "string" && typeof v.appendChild === "function";
};
var placeholderModeSet = new Set(Object.values(PLACEHOLDER_MODES));
var warn = (message) => {
console.warn(`[intl-tel-input] ${message}`);
};
var warnOption = (optionName, expectedType, actualValue) => {
warn(
`Option '${optionName}' must be ${expectedType}; got ${toString(actualValue)}. Ignoring.`
);
};
var validateIso2Array = (key, value) => {
const expectedType = "an array of iso2 country code strings";
if (!Array.isArray(value)) {
warnOption(key, expectedType, value);
return false;
}
const valid = [];
for (const v of value) {
if (typeof v !== "string") {
warnOption(key, expectedType, value);
return false;
}
const lower = v.toLowerCase();
if (!isIso2(lower)) {
warn(`Invalid iso2 code in '${key}': '${v}'. Skipping.`);
} else {
valid.push(v);
}
}
return valid;
};
var validateOptions = (customOptions) => {
if (customOptions === void 0) {
return {};
}
if (!isPlainObject(customOptions)) {
const error = `The second argument must be an options object; got ${toString(customOptions)}. Using defaults.`;
warn(error);
return {};
}
const validatedOptions = {};
for (const [key, value] of Object.entries(customOptions)) {
if (!Object.hasOwn(defaults, key)) {
warn(`Unknown option '${key}'. Ignoring.`);
continue;
}
switch (key) {
case "allowDropdown":
case "allowNumberExtensions":
case "allowPhonewords":
case "countrySearch":
case "dropdownAlwaysOpen":
case "fixDropdownWidth":
case "formatAsYouType":
case "formatOnDisplay":
case "nationalMode":
case "showFlags":
case "separateDialCode":
case "strictMode":
case "strictRejectAnimation":
case "useFullscreenPopup":
if (typeof value !== "boolean") {
warnOption(key, "a boolean", value);
break;
}
validatedOptions[key] = value;
break;
case "autoPlaceholder":
if (typeof value !== "string" || !placeholderModeSet.has(value)) {
const validModes = Array.from(placeholderModeSet).join(", ");
warnOption("autoPlaceholder", `one of ${validModes}`, value);
break;
}
validatedOptions[key] = value;
break;
case "containerClass":
case "searchInputClass":
case "countryNameLocale":
if (typeof value !== "string") {
warnOption(key, "a string", value);
break;
}
validatedOptions[key] = value;
break;
case "countryOrder": {
if (value === null) {
validatedOptions[key] = value;
} else {
const filtered = validateIso2Array(key, value);
if (filtered !== false) {
validatedOptions[key] = filtered;
}
}
break;
}
case "customPlaceholder":
case "geoIpLookup":
case "hiddenInput":
case "loadUtils":
if (value !== null && !isFunction(value)) {
warnOption(key, "a function or null", value);
break;
}
validatedOptions[key] = value;
break;
case "dropdownContainer":
if (value !== null && !isElLike(value)) {
warnOption("dropdownContainer", "an HTMLElement or null", value);
break;
}
validatedOptions[key] = value;
break;
case "excludeCountries":
case "onlyCountries": {
if (value === null) {
validatedOptions[key] = value;
} else {
const filtered = validateIso2Array(key, value);
if (filtered !== false) {
validatedOptions[key] = filtered;
}
}
break;
}
case "i18n":
if (value && !isPlainObject(value)) {
warnOption("i18n", "an object", value);
break;
}
validatedOptions[key] = value;
break;
case "countryNameOverrides":
if (value && !isPlainObject(value)) {
warnOption("countryNameOverrides", "an object", value);
break;
}
validatedOptions[key] = value;
break;
case "initialCountry": {
if (typeof value !== "string") {
warnOption("initialCountry", "a string", value);
break;
}
const lower = value.toLowerCase();
if (lower && lower !== INITIAL_COUNTRY.AUTO && !isIso2(lower)) {
warnOption(
"initialCountry",
"a valid iso2 country code or 'auto'",
value
);
break;
}
validatedOptions[key] = value;
break;
}
case "placeholderNumberType":
if (typeof value !== "string" || !NUMBER_TYPES.includes(value)) {
const validTypes = NUMBER_TYPES.join(", ");
warnOption("placeholderNumberType", `one of ${validTypes}`, value);
break;
}
validatedOptions[key] = value;
break;
case "allowedNumberTypes":
if (value !== null) {
if (!Array.isArray(value)) {
warnOption(
"allowedNumberTypes",
"an array of number types or null",
value
);
break;
}
let allValid = true;
for (const v of value) {
if (typeof v !== "string" || !NUMBER_TYPES.includes(v)) {
const validTypes = NUMBER_TYPES.join(", ");
warnOption(
"allowedNumberTypes",
`an array of valid number types (${validTypes})`,
v
);
allValid = false;
break;
}
}
if (allValid) {
validatedOptions[key] = value;
}
} else {
validatedOptions[key] = null;
}
break;
}
}
return validatedOptions;
};
var normaliseOptions = (o) => {
if (o.initialCountry) {
o.initialCountry = o.initialCountry.toLowerCase();
}
if (o.onlyCountries?.length) {
o.onlyCountries = o.onlyCountries.map((c) => c.toLowerCase());
}
if (o.excludeCountries?.length) {
o.excludeCountries = o.excludeCountries.map((c) => c.toLowerCase());
}
if (o.countryOrder) {
o.countryOrder = o.countryOrder.map((c) => c.toLowerCase());
}
};
var applyOptionSideEffects = (o) => {
if (o.dropdownAlwaysOpen) {
o.useFullscreenPopup = false;
o.allowDropdown = true;
}
if (o.useFullscreenPopup) {
o.fixDropdownWidth = false;
} else {
if (isNarrowViewport()) {
o.fixDropdownWidth = true;
}
}
if (o.onlyCountries?.length === 1) {
o.initialCountry = o.onlyCountries[0];
}
if (o.separateDialCode) {
o.nationalMode = false;
}
if (o.allowDropdown && !o.showFlags && !o.separateDialCode) {
o.nationalMode = false;
}
if (o.useFullscreenPopup && !o.dropdownContainer) {
o.dropdownContainer = document.body;
}
o.i18n = { ...en_default, ...o.i18n };
};
// packages/core/src/js/helpers/string.ts
var getNumeric = (s) => s.replace(/\D/g, "");
var normaliseString = (s = "") => s.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
// packages/core/src/js/helpers/dom.ts
var buildClassNames = (flags) => Object.keys(flags).filter((k) => Boolean(flags[k])).join(" ");
var createEl = (tagName, attrs, container) => {
const el = document.createElement(tagName);
if (attrs) {
Object.entries(attrs).forEach(
([key, value]) => el.setAttribute(key, value)
);
}
if (container) {
container.appendChild(el);
}
return el;
};
// packages/core/src/js/core/icons.ts
var SVG_NS = "http://www.w3.org/2000/svg";
var buildSvg = ([tag, attrs, children]) => {
const el = document.createElementNS(SVG_NS, tag);
if (attrs) {
for (const k in attrs) {
el.setAttribute(k, String(attrs[k]));
}
}
if (children) {
for (const c of children) {
el.appendChild(buildSvg(c));
}
}
return el;
};
var buildSearchIcon = () => buildSvg(
["svg", { class: "iti__search-icon-svg", width: 14, height: 14, viewBox: "0 0 24 24", focusable: "false", [ARIA.HIDDEN]: "true" }, [
["circle", { cx: 11, cy: 11, r: 7 }],
["line", { x1: 21, y1: 21, x2: 16.65, y2: 16.65 }]
]]
);
var buildClearIcon = (id) => {
const maskId = `iti-${id}-clear-mask`;
return buildSvg(
["svg", { class: "iti__search-clear-svg", width: 12, height: 12, viewBox: "0 0 16 16", [ARIA.HIDDEN]: "true", focusable: "false" }, [
["mask", { id: maskId, maskUnits: "userSpaceOnUse" }, [
["rect", { width: 16, height: 16, fill: "white" }],
["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" }]
]],
["circle", { cx: 8, cy: 8, r: 8, class: "iti__search-clear-bg", mask: `url(#${maskId})` }]
]]
);
};
var buildCheckIcon = () => buildSvg(
["svg", { class: "iti__country-check-svg", width: 14, height: 14, viewBox: "0 0 16 16", fill: "currentColor", focusable: "false", [ARIA.HIDDEN]: "true" }, [
["path", { d: "M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0m-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z" }]
]]
);
var buildGlobeIcon = () => buildSvg(
["svg", { width: 256, height: 256, viewBox: "0 0 512 512", class: "iti__globe-svg" }, [
["path", { d: "M508 213a240 240 0 0 0-449-87l-2 5-2 5c-8 14-13 30-17 46a65 65 0 0 1 56 4c16-10 35-19 56-27l9-3c-6 23-10 48-10 74h-16l4 6c3 4 5 8 6 13h6c0 22 3 44 8 65l2 10-25-10-4 5 12 18 9 3 6 2 8 3 9 26 1 2 16-7h1l-5-13-1-2c24 6 49 9 75 10v26l11 10 7 7v-30l1-13c22 0 44-3 65-8l10-2-21 48-1 1a317 317 0 0 1-14 23l-21 5h-2c6 16 7 33 1 50a240 240 0 0 0 211-265m-401-56-11 6c19-44 54-79 98-98-11 20-21 44-29 69-21 6-40 15-58 23m154 182v4c-29-1-57-6-81-13-7-25-12-52-13-81h94zm0-109h-94c1-29 6-56 13-81 24-7 52-12 81-13zm0-112c-22 1-44 4-65 8l-10 2 12-30 9-17 1-2a332 332 0 0 1 13-23c13-4 26-6 40-7zm187 69 6 4c4 12 6 25 6 38v1h-68c-1-26-4-51-10-74l48 20 1 1 14 8zm-14-44 10 20c-20-11-43-21-68-29-8-25-18-49-29-69 37 16 67 44 87 78M279 49h1c13 1 27 3 39 7l14 23 1 2a343 343 0 0 1 12 26l2 5 6 16c-23-6-48-9-74-10h-1zm0 87h1c29 1 56 6 81 13 7 24 12 51 12 80v1h-94zm2 207h-2v-94h95c-1 29-6 56-13 81-24 7-51 12-80 13m86 60-20 10c11-20 21-43 29-68 25-8 48-18 68-29-16 37-43 67-77 87m87-115-7 5-16 9-2 1a337 337 0 0 1-47 21c6-24 9-49 10-75h68c0 13-2 27-6 39" }],
["path", { d: "m261 428-2-2-22-21a40 40 0 0 0-32-11h-1a37 37 0 0 0-18 8l-1 1-4 2-2 2-5 4c-9-3-36-31-47-44s-32-45-34-55l3-2a151 151 0 0 0 11-9v-1a39 39 0 0 0 5-48l-3-3-11-19-3-4-5-7h-1l-3-3-4-3-5-2a35 35 0 0 0-16-3h-5c-4 1-14 5-24 11l-4 2-4 3-4 2c-9 8-17 17-18 27a380 380 0 0 0 212 259h3c12 0 25-10 36-21l10-12 6-11a39 39 0 0 0-8-40" }]
]]
);
// packages/core/src/js/core/countrySearch.ts
var buildSearchTokens = (countries) => {
const tokens = /* @__PURE__ */ new Map();
for (const c of countries) {
const normalisedName = normaliseString(c.name);
const initials = normalisedName.split(/[^a-z]/).map((word) => word[0]).join("");
tokens.set(c.iso2, {
normalisedName,
initials,
dialCodePlus: `+${c.dialCode}`
});
}
return tokens;
};
var getMatchedCountries = (countries, searchTokens, query) => {
const normalisedQuery = normaliseString(query);
const iso2Matches = [];
const nameStartsWith = [];
const nameContains = [];
const dialCodeMatches = [];
const dialCodeContains = [];
const initialsMatches = [];
for (const c of countries) {
const t = searchTokens.get(c.iso2);
if (c.iso2 === normalisedQuery) {
iso2Matches.push(c);
} else if (t.normalisedName.startsWith(normalisedQuery)) {
nameStartsWith.push(c);
} else if (t.normalisedName.includes(normalisedQuery)) {
nameContains.push(c);
} else if (normalisedQuery === c.dialCode || normalisedQuery === t.dialCodePlus) {
dialCodeMatches.push(c);
} else if (t.dialCodePlus.includes(normalisedQuery)) {
dialCodeContains.push(c);
} else if (t.initials.includes(normalisedQuery)) {
initialsMatches.push(c);
}
}
const sortByPriority = (a, b) => a.priority - b.priority;
return [
...iso2Matches,
...nameStartsWith,
...nameContains,
// priority sort is only relevant when showing multiple countries with the same dial code (that's what the priority field is used to distinguish between)
...dialCodeMatches.sort(sortByPriority),
...dialCodeContains.sort(sortByPriority),
...initialsMatches
];
};
var findFirstCountryStartingWith = (countries, searchTokens, query) => {
const normalisedQuery = normaliseString(query);
for (const c of countries) {
const { normalisedName } = searchTokens.get(c.iso2);
if (normalisedName.startsWith(normalisedQuery)) {
return c;
}
}
return null;
};
// packages/core/src/js/core/numerals.ts
var Numerals = class _Numerals {
#userNumeralSet;
//* Stateless conversion of any Arabic-Indic / Persian digits to ASCII 0-9.
//* Use this when you need to normalise digits without affecting any instance's tracked numeral set (e.g. for the country-search query).
static toAscii(str) {
if (!str) {
return "";
}
return str.replace(
/[٠-٩]/g,
(ch) => String.fromCharCode(48 + (ch.charCodeAt(0) - 1632))
).replace(
/[۰-۹]/g,
(ch) => String.fromCharCode(48 + (ch.charCodeAt(0) - 1776))
);
}
constructor(initialValue) {
if (initialValue) {
this.#updateNumeralSet(initialValue);
}
}
// If any Arabic-Indic digits, then label it as that set. Same for Persian. Otherwise assume ASCII.
#updateNumeralSet(str) {
if (/[٠-٩]/.test(str)) {
this.#userNumeralSet = "arabic-indic";
} else if (/[۰-۹]/.test(str)) {
this.#userNumeralSet = "persian";
} else {
this.#userNumeralSet = "ascii";
}
}
// Denormalise ASCII 0-9 to the user's numeral set. If not yet known, return as-is.
// NOTE: normalise is always called before this, so it should be impossible for the numeral set to be unknown at this point.
denormalise(str) {
if (!this.#userNumeralSet || this.#userNumeralSet === "ascii") {
return str;
}
const base = this.#userNumeralSet === "arabic-indic" ? 1632 : 1776;
return str.replace(/[0-9]/g, (d) => String.fromCharCode(base + Number(d)));
}
// Normalize Eastern Arabic (U+0660-0669) and Persian/Extended Arabic-Indic (U+06F0-06F9) numerals to ASCII 0-9.
// Tracks the user's numeral set as a side effect so denormalise can mirror it back.
normalise(str) {
if (!str) {
return "";
}
this.#updateNumeralSet(str);
if (this.#userNumeralSet === "ascii") {
return str;
}
return _Numerals.toAscii(str);
}
isAscii() {
return !this.#userNumeralSet || this.#userNumeralSet === "ascii";
}
};
// packages/core/src/js/core/ui.ts
var UI = class _UI {
// private
#options;
#id;
#isRTL;
#originalPaddingLeft = "";
#countries;
#searchTokens;
#searchDebounceTimer = null;
#inlineDropdownHeight;
#countryContainerEl;
#selectedCountryEl;
#selectedFlagEl;
#selectedDialCodeEl;
#dropdownArrowEl;
#dropdownContentEl;
#searchIconEl;
#searchInputEl;
#searchClearButtonEl;
#countryListEl;
#hiddenInputPhoneEl;
#hiddenInputCountryEl;
#noResultsMessageEl;
#searchResultsLiveRegionEl;
#detachedDropdownEl;
#selectedListItemEl = null;
#highlightedListItemEl = null;
#listItemByIso2 = /* @__PURE__ */ new Map();
#dropdownAbortController = null;
// public
telInputEl;
hadInitialPlaceholder;
constructor(input, options, id) {
input.dataset[DATA_KEYS.INSTANCE_ID] = id.toString();
this.telInputEl = input;
this.#options = options;
this.#id = id;
this.hadInitialPlaceholder = Boolean(input.getAttribute("placeholder"));
this.#isRTL = !!this.telInputEl.closest("[dir=rtl]");
this.#originalPaddingLeft = this.telInputEl.style.paddingLeft;
}
// Validate that the provided element is an HTMLInputElement.
static validateInput(input) {
const tagName = input?.tagName;
const isInputEl = Boolean(input) && typeof input === "object" && tagName === "INPUT" && typeof input.setAttribute === "function";
if (!isInputEl) {
const type = Object.prototype.toString.call(input);
throw new TypeError(
`The first argument must be an HTMLInputElement, not ${type}`
);
}
}
//* Generate all of the markup for the core library: the selected country overlay, and the dropdown.
buildMarkup(countries, searchTokens) {
this.#countries = countries;
this.#searchTokens = searchTokens;
this.telInputEl.classList.add("iti__tel-input");
if (!this.telInputEl.hasAttribute("type")) {
this.telInputEl.setAttribute("type", "tel");
}
if (!this.telInputEl.hasAttribute("autocomplete")) {
this.telInputEl.setAttribute("autocomplete", "tel");
}
if (!this.telInputEl.hasAttribute("inputmode")) {
this.telInputEl.setAttribute("inputmode", "tel");
}
const wrapper = this.#createWrapperAndInsert();
this.#buildCountryContainer(wrapper);
wrapper.appendChild(this.telInputEl);
this.#updateInputPaddingAndReveal();
this.#buildHiddenInputs(wrapper);
this.ensureDropdownWidthSet();
}
#createWrapperAndInsert() {
const { allowDropdown, showFlags, containerClass, useFullscreenPopup } = this.#options;
const parentClasses = buildClassNames({
iti: true,
"iti--allow-dropdown": allowDropdown,
"iti--show-flags": showFlags,
"iti--inline-dropdown": !useFullscreenPopup,
[containerClass]: Boolean(containerClass)
});
const wrapper = createEl("div", { class: parentClasses });
if (this.#isRTL) {
wrapper.setAttribute("dir", "ltr");
}
this.telInputEl.before(wrapper);
return wrapper;
}
#buildCountryContainer(wrapper) {
const { allowDropdown, separateDialCode, showFlags } = this.#options;
if (!allowDropdown && !showFlags && !separateDialCode) {
return;
}
this.#countryContainerEl = createEl(
"div",
// visibly hidden until we measure its width to set the input padding correctly
{ class: `iti__country-container ${CLASSES.V_HIDE}` },
wrapper
);
if (allowDropdown) {
this.#selectedCountryEl = createEl(
"button",
{
type: "button",
class: "iti__selected-country",
[ARIA.EXPANDED]: "false",
[ARIA.LABEL]: this.#options.i18n.noCountrySelected,
[ARIA.HASPOPUP]: "dialog",
[ARIA.CONTROLS]: `iti-${this.#id}__dropdown-content`
},
this.#countryContainerEl
);
if (this.telInputEl.disabled) {
this.#selectedCountryEl.setAttribute("disabled", "true");
}
} else {
this.#selectedCountryEl = createEl(
"div",
{ class: "iti__selected-country" },
this.#countryContainerEl
);
}
const selectedCountryPrimary = createEl(
"div",
{ class: "iti__selected-country-primary" },
this.#selectedCountryEl
);
this.#selectedFlagEl = createEl(
"div",
{ class: CLASSES.FLAG },
selectedCountryPrimary
);
if (allowDropdown) {
this.#dropdownArrowEl = createEl(
"div",
{ class: "iti__arrow", [ARIA.HIDDEN]: "true" },
selectedCountryPrimary
);
}
if (separateDialCode) {
this.#selectedDialCodeEl = createEl(
"div",
{ class: "iti__selected-dial-code" },
this.#selectedCountryEl
);
}
if (allowDropdown) {
this.#buildDropdownContent();
}
}
ensureDropdownWidthSet() {
const { fixDropdownWidth, allowDropdown } = this.#options;
if (!allowDropdown || !fixDropdownWidth || this.#dropdownContentEl.style.width) {
return;
}
const inputWidth = this.telInputEl.offsetWidth;
if (inputWidth > 0) {
this.#dropdownContentEl.style.width = `${inputWidth}px`;
}
}
#buildDropdownContent() {
const {
fixDropdownWidth,
useFullscreenPopup,
countrySearch,
i18n,
dropdownContainer,
containerClass
} = this.#options;
const extraClasses = fixDropdownWidth ? "" : "iti--flexible-dropdown-width";
this.#dropdownContentEl = createEl("div", {
id: `iti-${this.#id}__dropdown-content`,
class: `iti__dropdown-content ${CLASSES.HIDE} ${extraClasses}`,
role: "dialog",
[ARIA.MODAL]: "true"
});
if (this.#isRTL) {
this.#dropdownContentEl.setAttribute("dir", "rtl");
}
if (countrySearch) {
this.#buildSearchUI();
}
this.#countryListEl = createEl(
"ul",
{
class: "iti__country-list",
id: `iti-${this.#id}__country-listbox`,
role: "listbox",
[ARIA.LABEL]: i18n.countryListAriaLabel
},
this.#dropdownContentEl
);
this.#appendListItems();
if (countrySearch) {
this.#updateSearchResultsA11yText();
}
if (!useFullscreenPopup) {
this.#inlineDropdownHeight = this.#getHiddenInlineDropdownHeight();
if (countrySearch) {
this.#dropdownContentEl.style.height = `${this.#inlineDropdownHeight}px`;
}
}
if (dropdownContainer) {
const dropdownClasses = buildClassNames({
iti: true,
"iti--container": true,
"iti--fullscreen-popup": useFullscreenPopup,
"iti--inline-dropdown": !useFullscreenPopup,
[containerClass]: Boolean(containerClass)
});
this.#detachedDropdownEl = createEl("div", { class: dropdownClasses });
this.#detachedDropdownEl.appendChild(this.#dropdownContentEl);
} else {
this.#countryContainerEl.appendChild(this.#dropdownContentEl);
}
}
#buildSearchUI() {
const { i18n, searchInputClass } = this.#options;
const searchWrapper = createEl(
"div",
{ class: "iti__search-input-wrapper" },
this.#dropdownContentEl
);
this.#searchIconEl = createEl(
"span",
{
class: "iti__search-icon",
[ARIA.HIDDEN]: "true"
},
searchWrapper
);
this.#searchIconEl.appendChild(buildSearchIcon());
this.#searchInputEl = createEl(
"input",
{
id: `iti-${this.#id}__search-input`,
// Chrome says inputs need either a name or an id
type: "search",
class: `iti__search-input ${searchInputClass}`,
placeholder: i18n.searchPlaceholder,
// 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
role: "combobox",
[ARIA.EXPANDED]: "true",
[ARIA.LABEL]: i18n.searchPlaceholder,
[ARIA.CONTROLS]: `iti-${this.#id}__country-listbox`,
[ARIA.AUTOCOMPLETE]: "list",
autocomplete: "off"
},
searchWrapper
);
this.#searchClearButtonEl = createEl(
"button",
{
type: "button",
class: `iti__search-clear ${CLASSES.HIDE}`,
[ARIA.LABEL]: i18n.clearSearchAriaLabel,
tabindex: "-1"
},
searchWrapper
);
this.#searchClearButtonEl.appendChild(buildClearIcon(this.#id));
this.#searchResultsLiveRegionEl = createEl(
"span",
{ class: "iti__a11y-text" },
this.#dropdownContentEl
);
this.#noResultsMessageEl = createEl(
"div",
{
class: `iti__no-results ${CLASSES.HIDE}`,
[ARIA.HIDDEN]: "true"
// all a11y messaging happens in this.#searchResultsLiveRegionEl
},
this.#dropdownContentEl
);
this.#noResultsMessageEl.textContent = i18n.searchEmptyState ?? null;
}
#updateInputPaddingAndReveal() {
if (!this.#countryContainerEl) {
return;
}
this.#updateInputPadding();
this.#countryContainerEl.classList.remove(CLASSES.V_HIDE);
}
#buildHiddenInputs(wrapper) {
const { hiddenInput } = this.#options;
if (!hiddenInput) {
return;
}
const telInputName = this.telInputEl.getAttribute("name") || "";
const names = hiddenInput(telInputName);
if (names.phone) {
const existingInput = this.telInputEl.form?.querySelector(
`input[name="${names.phone}"]`
);
if (existingInput) {
this.#hiddenInputPhoneEl = existingInput;
} else {
this.#hiddenInputPhoneEl = createEl("input", {
type: "hidden",
name: names.phone
});