mirror of
https://github.com/itflow-org/itflow
synced 2026-09-14 18:55:12 +00:00
Bump intl-tel-input
This commit is contained in:
168
libs/intl-tel-input/js/data/country-data.ts
Normal file
168
libs/intl-tel-input/js/data/country-data.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import allCountries, { type Country, type Iso2 } from "../data.js";
|
||||
import type { AllOptions } from "../types/public-api.js";
|
||||
|
||||
export interface ProcessedDialCodes {
|
||||
dialCodes: Set<string>;
|
||||
dialCodeMaxLength: number;
|
||||
dialCodeToIso2Map: Record<string, Iso2[]>;
|
||||
}
|
||||
|
||||
//* Process onlyCountries or excludeCountries array if present.
|
||||
export const processAllCountries = (options: AllOptions): Country[] => {
|
||||
const { onlyCountries, excludeCountries } = options;
|
||||
if (onlyCountries?.length) {
|
||||
return allCountries.filter((country) =>
|
||||
onlyCountries.includes(country.iso2),
|
||||
);
|
||||
} else if (excludeCountries?.length) {
|
||||
return allCountries.filter(
|
||||
(country) => !excludeCountries.includes(country.iso2),
|
||||
);
|
||||
}
|
||||
//* Create new array so avoid a bug where multiple instances with different countryOrder options interfere with each other (as they were sharing the same allCountries array, which is mutated by sortCountries).
|
||||
return [...allCountries];
|
||||
};
|
||||
|
||||
//* Generate country names using Intl.DisplayNames
|
||||
export const generateCountryNames = (
|
||||
countries: Country[],
|
||||
options: AllOptions,
|
||||
): void => {
|
||||
const { countryNameLocale, countryNameOverrides, uiTranslations } = options;
|
||||
//* Some locales (e.g. bs, hy, is, mk, sq, uz) bundle their own country names
|
||||
//* because certain browsers' Intl.DisplayNames lacks region data for them and
|
||||
//* silently falls back to English (notably Chrome desktop). When the active
|
||||
//* uiTranslations carries these, they take precedence over Intl.DisplayNames.
|
||||
const bundledCountryNames = uiTranslations?.countryNames;
|
||||
|
||||
//* Populate country names using Intl.DisplayNames (per instance) with countryNameLocale.
|
||||
let displayNames;
|
||||
try {
|
||||
const hasDisplayNames =
|
||||
typeof Intl !== "undefined" &&
|
||||
typeof (Intl as any).DisplayNames === "function";
|
||||
if (hasDisplayNames) {
|
||||
displayNames = new (Intl as any).DisplayNames(countryNameLocale, {
|
||||
type: "region",
|
||||
});
|
||||
} else {
|
||||
displayNames = null;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
displayNames = null;
|
||||
}
|
||||
for (const c of countries) {
|
||||
c.name =
|
||||
countryNameOverrides[c.iso2] ||
|
||||
bundledCountryNames?.[c.iso2] ||
|
||||
displayNames?.of(c.iso2.toUpperCase()) ||
|
||||
"";
|
||||
}
|
||||
};
|
||||
|
||||
//* Generate dialCodes and dialCodeToIso2Map.
|
||||
export const processDialCodes = (
|
||||
countries: Country[],
|
||||
): ProcessedDialCodes => {
|
||||
//* Here we store just dial codes, where the key is the dial code, and the value is true
|
||||
//* e.g. { 1: true, 7: true, 20: true, ... }.
|
||||
const dialCodes = new Set<string>();
|
||||
let dialCodeMaxLength = 0;
|
||||
|
||||
//* Here we map dialCodes (inc both dialCode and dialCode+areaCode) to iso2 codes e.g.
|
||||
/*
|
||||
* {
|
||||
* 1: [ 'us', 'ca', ... ], # all NANP countries (with dial code "1")
|
||||
* 12: [ 'us', 'ca', ... ], # subset of NANP countries (that have area codes starting with "2")
|
||||
* 120: [ 'us', 'ca' ], # just US and Canada (that have area codes starting "20")
|
||||
* 1204: [ 'ca' ], # only Canada (that has a "204" area code)
|
||||
* ...
|
||||
* }
|
||||
*/
|
||||
const dialCodeToIso2Map: Record<string, Iso2[]> = {};
|
||||
|
||||
//* Add a dial code to this.dialCodeToIso2Map.
|
||||
const addToDialCodeMap = (iso2: Iso2, dialCode: string) => {
|
||||
// Bail if no iso2 or dialCode (this can happen with onlyCountries or excludeCountries options).
|
||||
if (!iso2 || !dialCode) {
|
||||
return;
|
||||
}
|
||||
//* Update dialCodeMaxLength.
|
||||
if (dialCode.length > dialCodeMaxLength) {
|
||||
dialCodeMaxLength = dialCode.length;
|
||||
}
|
||||
//* If this entry doesn't already exist, then create it.
|
||||
if (!Object.hasOwn(dialCodeToIso2Map, dialCode)) {
|
||||
dialCodeToIso2Map[dialCode] = [];
|
||||
}
|
||||
const iso2List = dialCodeToIso2Map[dialCode];
|
||||
//* Bail if we already have this country for this dialCode.
|
||||
if (iso2List.includes(iso2)) {
|
||||
return;
|
||||
}
|
||||
iso2List.push(iso2);
|
||||
};
|
||||
|
||||
// Sort countries by priority so that when we add to the dialCodeToIso2Map, higher priority countries come first
|
||||
const countriesSortedByPriority = [...countries].sort(
|
||||
(a, b) => a.priority - b.priority,
|
||||
);
|
||||
for (const c of countriesSortedByPriority) {
|
||||
if (!dialCodes.has(c.dialCode)) {
|
||||
dialCodes.add(c.dialCode);
|
||||
}
|
||||
// add the dial code partial matches to the map
|
||||
for (let k = 1; k < c.dialCode.length; k++) {
|
||||
const partialDialCode = c.dialCode.substring(0, k);
|
||||
addToDialCodeMap(c.iso2, partialDialCode);
|
||||
}
|
||||
// add the full dial code to the map
|
||||
addToDialCodeMap(c.iso2, c.dialCode);
|
||||
|
||||
if (c.areaCodes) {
|
||||
const rootIso2Code = dialCodeToIso2Map[c.dialCode][0];
|
||||
//* For each area code.
|
||||
for (const areaCode of c.areaCodes) {
|
||||
//* Add partial matches: For each digit in the area code
|
||||
for (let k = 1; k < areaCode.length; k++) {
|
||||
const partialAreaCode = areaCode.substring(0, k);
|
||||
const partialDialCode = c.dialCode + partialAreaCode;
|
||||
//* Start with the root country, as that also matches this partial dial code.
|
||||
addToDialCodeMap(rootIso2Code, partialDialCode);
|
||||
addToDialCodeMap(c.iso2, partialDialCode);
|
||||
}
|
||||
//* Add the full area code.
|
||||
addToDialCodeMap(c.iso2, c.dialCode + areaCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { dialCodes, dialCodeMaxLength, dialCodeToIso2Map };
|
||||
};
|
||||
|
||||
//* Sort countries by countryOrder option (if present), then name.
|
||||
export const sortCountries = (
|
||||
countries: Country[],
|
||||
options: AllOptions,
|
||||
): void => {
|
||||
const { countryOrder } = options;
|
||||
countries.sort((a: Country, b: Country): number => {
|
||||
//* Primary sort: countryOrder option
|
||||
if (countryOrder) {
|
||||
const aIndex = countryOrder.indexOf(a.iso2);
|
||||
const bIndex = countryOrder.indexOf(b.iso2);
|
||||
const aIndexExists = aIndex > -1;
|
||||
const bIndexExists = bIndex > -1;
|
||||
if (aIndexExists || bIndexExists) {
|
||||
if (aIndexExists && bIndexExists) {
|
||||
return aIndex - bIndex;
|
||||
}
|
||||
return aIndexExists ? -1 : 1;
|
||||
}
|
||||
}
|
||||
|
||||
//* Secondary sort: country name
|
||||
return a.name.localeCompare(b.name);
|
||||
});
|
||||
};
|
||||
20
libs/intl-tel-input/js/data/intl-regionless.ts
Normal file
20
libs/intl-tel-input/js/data/intl-regionless.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { getNumeric } from "../helpers/string.js";
|
||||
|
||||
// Non-geographic / regionless international dial codes that should always be
|
||||
// treated as international numbers (no associated iso2 country).
|
||||
// e.g. +800 is the Universal International Freephone Service (UIFS), which is not associated with any country
|
||||
export const regionlessDialCodes: Set<string> = new Set([
|
||||
"800",
|
||||
"808",
|
||||
"870",
|
||||
"881",
|
||||
"882",
|
||||
"883",
|
||||
"888",
|
||||
"979",
|
||||
]);
|
||||
|
||||
export const hasRegionlessDialCode = (number: string): boolean => {
|
||||
const dialCode = getNumeric(number).slice(0, 3);
|
||||
return number.startsWith("+") && regionlessDialCodes.has(dialCode);
|
||||
};
|
||||
37
libs/intl-tel-input/js/data/nanp-regionless.ts
Normal file
37
libs/intl-tel-input/js/data/nanp-regionless.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { DIAL_CODE } from "../constants.js";
|
||||
import { getNumeric } from "../helpers/string.js";
|
||||
|
||||
// NANP (North American Numbering Plan) countries (e.g. USA, Canada, and many more) use +1 as their international dial code
|
||||
|
||||
//* https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes#Non-geographic_area_codes
|
||||
// e.g. +1800 is a toll-free number, which can be used across NANP countries and is not associated with any specific country
|
||||
// NOTE: this export is used in the tests!
|
||||
export const regionlessNanpAreaCodes = new Set([
|
||||
"800",
|
||||
"822",
|
||||
"833",
|
||||
"844",
|
||||
"855",
|
||||
"866",
|
||||
"877",
|
||||
"880",
|
||||
"881",
|
||||
"882",
|
||||
"883",
|
||||
"884",
|
||||
"885",
|
||||
"886",
|
||||
"887",
|
||||
"888",
|
||||
"889",
|
||||
]);
|
||||
|
||||
//* Check if the given number is a regionless NANP number (expects the number to contain an international dial code)
|
||||
export const isRegionlessNanp = (number: string): boolean => {
|
||||
const numeric = getNumeric(number);
|
||||
if (numeric.startsWith(DIAL_CODE.NANP) && numeric.length >= 4) {
|
||||
const areaCode = numeric.substring(1, 4);
|
||||
return regionlessNanpAreaCodes.has(areaCode);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Reference in New Issue
Block a user