@traky-app/ui 1.6.3 → 1.6.4
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.
- package/package.json +15 -1
- package/registry/traky/json/city-select.json +19 -0
- package/registry/traky/json/country-select.json +24 -0
- package/registry/traky/json/geo-search-select.json +24 -0
- package/registry/traky/json/geo-selectors.json +21 -0
- package/registry/traky/json/google-maps-address-picker.json +22 -0
- package/registry/traky/json/lib-geo-city-codes.json +14 -0
- package/registry/traky/json/lib-geo-countries.json +14 -0
- package/registry/traky/json/lib-geo-csc.json +17 -0
- package/registry/traky/json/lib-geo-locations.json +14 -0
- package/registry/traky/json/lib-geo-overrides.json +14 -0
- package/registry/traky/json/lib-geo-types.json +14 -0
- package/registry/traky/json/lib-google-maps-address.json +14 -0
- package/registry/traky/json/lib-phone-countries.json +14 -0
- package/registry/traky/json/lib-phone-e164.json +14 -0
- package/registry/traky/json/lib-utils.json +1 -1
- package/registry/traky/json/office-address-form-dialog.json +17 -0
- package/registry/traky/json/office-address-form.json +31 -0
- package/registry/traky/json/phone-number-input.json +25 -0
- package/registry/traky/json/state-select.json +19 -0
- package/registry/traky/lib/geo-city-codes.ts +234 -0
- package/registry/traky/lib/geo-countries.ts +75 -0
- package/registry/traky/lib/geo-csc.ts +82 -0
- package/registry/traky/lib/geo-locations.ts +171 -0
- package/registry/traky/lib/geo-overrides.ts +375 -0
- package/registry/traky/lib/geo-types.ts +34 -0
- package/registry/traky/lib/google-maps-address.ts +100 -0
- package/registry/traky/lib/phone-countries.ts +380 -0
- package/registry/traky/lib/phone-e164.ts +66 -0
- package/registry/traky/lib/utils.ts +24 -0
- package/registry/traky/registry.json +180 -0
- package/registry/traky/ui/city-select.tsx +113 -0
- package/registry/traky/ui/country-select.tsx +233 -0
- package/registry/traky/ui/geo-search-select.tsx +136 -0
- package/registry/traky/ui/geo-selectors.tsx +162 -0
- package/registry/traky/ui/google-maps-address-picker.tsx +422 -0
- package/registry/traky/ui/office-address-form-dialog.tsx +16 -0
- package/registry/traky/ui/office-address-form.tsx +868 -0
- package/registry/traky/ui/phone-number-input.tsx +253 -0
- package/registry/traky/ui/state-select.tsx +107 -0
- package/src/lib/geo-city-codes.ts +234 -0
- package/src/lib/geo-countries.ts +75 -0
- package/src/lib/geo-csc.ts +82 -0
- package/src/lib/geo-locations.ts +171 -0
- package/src/lib/geo-overrides.ts +375 -0
- package/src/lib/geo-types.ts +34 -0
- package/src/lib/google-maps-address.ts +100 -0
- package/src/lib/phone-countries.ts +380 -0
- package/src/lib/phone-e164.ts +66 -0
- package/src/test/setup.ts +31 -0
- package/src/ui/__tests__/geo-selects.test.tsx +504 -0
- package/src/ui/city-select.tsx +113 -0
- package/src/ui/country-select.tsx +233 -0
- package/src/ui/geo-search-select.tsx +136 -0
- package/src/ui/geo-selectors.tsx +162 -0
- package/src/ui/google-maps-address-picker.tsx +422 -0
- package/src/ui/office-address-form-dialog.tsx +16 -0
- package/src/ui/office-address-form.tsx +877 -0
- package/src/ui/phone-number-input.tsx +253 -0
- package/src/ui/state-select.tsx +107 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
export const OFFICE_ADDRESS_GEOCODE_SOURCE_GOOGLE_MAPS = "google_maps" as const
|
|
2
|
+
|
|
3
|
+
export type GoogleMapsAddressSelection = {
|
|
4
|
+
street: string
|
|
5
|
+
streetNumber?: string
|
|
6
|
+
city: string
|
|
7
|
+
state?: string
|
|
8
|
+
postalCode?: string
|
|
9
|
+
countryCode?: string
|
|
10
|
+
formattedAddress?: string
|
|
11
|
+
latitude: number
|
|
12
|
+
longitude: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type AddressComponentLike = {
|
|
16
|
+
types: string[]
|
|
17
|
+
long_name?: string
|
|
18
|
+
short_name?: string
|
|
19
|
+
longText?: string
|
|
20
|
+
shortText?: string
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function parseGoogleAddressComponents(
|
|
24
|
+
components: AddressComponentLike[] | undefined,
|
|
25
|
+
fallbackStreet: string,
|
|
26
|
+
latitude: number,
|
|
27
|
+
longitude: number,
|
|
28
|
+
): GoogleMapsAddressSelection | null {
|
|
29
|
+
let streetNumber = ""
|
|
30
|
+
let route = ""
|
|
31
|
+
let city = ""
|
|
32
|
+
let state = ""
|
|
33
|
+
let postalCode = ""
|
|
34
|
+
let countryCode = ""
|
|
35
|
+
|
|
36
|
+
for (const component of components ?? []) {
|
|
37
|
+
const types = component.types
|
|
38
|
+
const longName = component.long_name ?? component.longText ?? ""
|
|
39
|
+
const shortName = component.short_name ?? component.shortText ?? ""
|
|
40
|
+
|
|
41
|
+
if (types.includes("street_number")) streetNumber = longName
|
|
42
|
+
if (types.includes("route")) route = longName
|
|
43
|
+
if (types.includes("locality")) city = longName
|
|
44
|
+
else if (
|
|
45
|
+
!city &&
|
|
46
|
+
(types.includes("sublocality") || types.includes("postal_town"))
|
|
47
|
+
) {
|
|
48
|
+
city = longName
|
|
49
|
+
}
|
|
50
|
+
if (types.includes("administrative_area_level_1")) {
|
|
51
|
+
state = longName || shortName
|
|
52
|
+
}
|
|
53
|
+
if (types.includes("postal_code")) postalCode = longName
|
|
54
|
+
if (types.includes("country")) countryCode = shortName.toUpperCase()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const street = route || fallbackStreet
|
|
58
|
+
if (!street.trim() && !fallbackStreet.trim()) return null
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
street: street.trim() || fallbackStreet.trim(),
|
|
62
|
+
streetNumber: streetNumber.trim() || undefined,
|
|
63
|
+
city: city.trim(),
|
|
64
|
+
state: state.trim() || undefined,
|
|
65
|
+
postalCode: postalCode.trim() || undefined,
|
|
66
|
+
countryCode: countryCode.trim() || undefined,
|
|
67
|
+
latitude,
|
|
68
|
+
longitude,
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function googleMapsSelectionToFormPatch(
|
|
73
|
+
selection: GoogleMapsAddressSelection,
|
|
74
|
+
): Pick<
|
|
75
|
+
GoogleMapsAddressSelection,
|
|
76
|
+
"latitude" | "longitude"
|
|
77
|
+
> & {
|
|
78
|
+
address: string
|
|
79
|
+
city: string
|
|
80
|
+
stateOrProvince: string
|
|
81
|
+
postalCode: string
|
|
82
|
+
countryCode: string
|
|
83
|
+
addressGeocodeSource: string
|
|
84
|
+
} {
|
|
85
|
+
const addressLine =
|
|
86
|
+
[selection.streetNumber, selection.street].filter(Boolean).join(" ").trim() ||
|
|
87
|
+
selection.formattedAddress?.split(",")[0]?.trim() ||
|
|
88
|
+
selection.street
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
address: addressLine,
|
|
92
|
+
city: selection.city,
|
|
93
|
+
stateOrProvince: selection.state ?? "",
|
|
94
|
+
postalCode: selection.postalCode ?? "",
|
|
95
|
+
countryCode: selection.countryCode?.trim().toUpperCase() ?? "",
|
|
96
|
+
latitude: selection.latitude,
|
|
97
|
+
longitude: selection.longitude,
|
|
98
|
+
addressGeocodeSource: OFFICE_ADDRESS_GEOCODE_SOURCE_GOOGLE_MAPS,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
export type PhoneCountry = {
|
|
2
|
+
iso: string;
|
|
3
|
+
name: string;
|
|
4
|
+
dialCode: string;
|
|
5
|
+
/** Solo dígitos nacionales (sin código de país). */
|
|
6
|
+
nationalMinLength: number;
|
|
7
|
+
nationalMaxLength: number;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Catálogo mundial de códigos telefónicos (flags en /public/assets/flags).
|
|
12
|
+
* Prioriza LATAM / uso frecuente arriba; el resto va A–Z en español.
|
|
13
|
+
*/
|
|
14
|
+
export const PHONE_COUNTRIES: PhoneCountry[] = [
|
|
15
|
+
{ iso: "EC", name: "Ecuador", dialCode: "+593", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
16
|
+
{ iso: "CO", name: "Colombia", dialCode: "+57", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
17
|
+
{ iso: "MX", name: "México", dialCode: "+52", nationalMinLength: 10, nationalMaxLength: 11 },
|
|
18
|
+
{ iso: "PE", name: "Perú", dialCode: "+51", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
19
|
+
{ iso: "CL", name: "Chile", dialCode: "+56", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
20
|
+
{ iso: "AR", name: "Argentina", dialCode: "+54", nationalMinLength: 10, nationalMaxLength: 11 },
|
|
21
|
+
{ iso: "US", name: "Estados Unidos", dialCode: "+1", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
22
|
+
{ iso: "CA", name: "Canadá", dialCode: "+1", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
23
|
+
{ iso: "ES", name: "España", dialCode: "+34", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
24
|
+
{ iso: "BR", name: "Brasil", dialCode: "+55", nationalMinLength: 10, nationalMaxLength: 11 },
|
|
25
|
+
{ iso: "VE", name: "Venezuela", dialCode: "+58", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
26
|
+
{ iso: "PA", name: "Panamá", dialCode: "+507", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
27
|
+
{ iso: "CR", name: "Costa Rica", dialCode: "+506", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
28
|
+
{ iso: "GT", name: "Guatemala", dialCode: "+502", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
29
|
+
{ iso: "HN", name: "Honduras", dialCode: "+504", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
30
|
+
{ iso: "SV", name: "El Salvador", dialCode: "+503", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
31
|
+
{ iso: "NI", name: "Nicaragua", dialCode: "+505", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
32
|
+
{ iso: "BO", name: "Bolivia", dialCode: "+591", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
33
|
+
{ iso: "PY", name: "Paraguay", dialCode: "+595", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
34
|
+
{ iso: "UY", name: "Uruguay", dialCode: "+598", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
35
|
+
{ iso: "DO", name: "Rep. Dominicana", dialCode: "+1", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
36
|
+
{ iso: "PR", name: "Puerto Rico", dialCode: "+1", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
37
|
+
{ iso: "AF", name: "Afganistán", dialCode: "+93", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
38
|
+
{ iso: "AX", name: "Aland Islands", dialCode: "+358", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
39
|
+
{ iso: "AL", name: "Albania", dialCode: "+355", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
40
|
+
{ iso: "DE", name: "Alemania", dialCode: "+49", nationalMinLength: 10, nationalMaxLength: 11 },
|
|
41
|
+
{ iso: "AD", name: "Andorra", dialCode: "+376", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
42
|
+
{ iso: "AO", name: "Angola", dialCode: "+244", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
43
|
+
{ iso: "AI", name: "Anguila", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
44
|
+
{ iso: "AG", name: "Antigua y Barbuda", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
45
|
+
{ iso: "SA", name: "Arabia Saudita", dialCode: "+966", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
46
|
+
{ iso: "DZ", name: "Argelia", dialCode: "+213", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
47
|
+
{ iso: "AM", name: "Armenia", dialCode: "+374", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
48
|
+
{ iso: "AW", name: "Aruba", dialCode: "+297", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
49
|
+
{ iso: "AU", name: "Australia", dialCode: "+61", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
50
|
+
{ iso: "AT", name: "Austria", dialCode: "+43", nationalMinLength: 10, nationalMaxLength: 11 },
|
|
51
|
+
{ iso: "AZ", name: "Azerbaiyán", dialCode: "+994", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
52
|
+
{ iso: "BS", name: "Bahamas", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
53
|
+
{ iso: "BD", name: "Bangladés", dialCode: "+880", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
54
|
+
{ iso: "BB", name: "Barbados", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
55
|
+
{ iso: "BH", name: "Baréin", dialCode: "+973", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
56
|
+
{ iso: "BE", name: "Bélgica", dialCode: "+32", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
57
|
+
{ iso: "BZ", name: "Belice", dialCode: "+501", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
58
|
+
{ iso: "BJ", name: "Benín", dialCode: "+229", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
59
|
+
{ iso: "BM", name: "Bermudas", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
60
|
+
{ iso: "BY", name: "Bielorrusia", dialCode: "+375", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
61
|
+
{ iso: "BQ", name: "Bonaire, Sint Eustatius and Saba", dialCode: "+599", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
62
|
+
{ iso: "BA", name: "Bosnia y Herzegovina", dialCode: "+387", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
63
|
+
{ iso: "BW", name: "Botsuana", dialCode: "+267", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
64
|
+
{ iso: "BV", name: "Bouvet Island", dialCode: "+0055", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
65
|
+
{ iso: "IO", name: "British Indian Ocean Territory", dialCode: "+246", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
66
|
+
{ iso: "BN", name: "Brunéi", dialCode: "+673", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
67
|
+
{ iso: "BG", name: "Bulgaria", dialCode: "+359", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
68
|
+
{ iso: "BF", name: "Burkina Faso", dialCode: "+226", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
69
|
+
{ iso: "BI", name: "Burundi", dialCode: "+257", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
70
|
+
{ iso: "BT", name: "Bután", dialCode: "+975", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
71
|
+
{ iso: "CV", name: "Cabo Verde", dialCode: "+238", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
72
|
+
{ iso: "KH", name: "Camboya", dialCode: "+855", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
73
|
+
{ iso: "CM", name: "Camerún", dialCode: "+237", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
74
|
+
{ iso: "QA", name: "Catar", dialCode: "+974", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
75
|
+
{ iso: "KY", name: "Cayman Islands", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
76
|
+
{ iso: "TD", name: "Chad", dialCode: "+235", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
77
|
+
{ iso: "CN", name: "China", dialCode: "+86", nationalMinLength: 11, nationalMaxLength: 11 },
|
|
78
|
+
{ iso: "CY", name: "Chipre", dialCode: "+357", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
79
|
+
{ iso: "CX", name: "Christmas Island", dialCode: "+61", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
80
|
+
{ iso: "VA", name: "Ciudad del Vaticano", dialCode: "+379", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
81
|
+
{ iso: "CC", name: "Cocos (Keeling) Islands", dialCode: "+61", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
82
|
+
{ iso: "KM", name: "Comoras", dialCode: "+269", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
83
|
+
{ iso: "CG", name: "Congo", dialCode: "+242", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
84
|
+
{ iso: "CD", name: "Congo (RDC)", dialCode: "+243", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
85
|
+
{ iso: "CK", name: "Cook Islands", dialCode: "+682", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
86
|
+
{ iso: "KP", name: "Corea del Norte", dialCode: "+850", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
87
|
+
{ iso: "KR", name: "Corea del Sur", dialCode: "+82", nationalMinLength: 9, nationalMaxLength: 10 },
|
|
88
|
+
{ iso: "CI", name: "Costa de Marfil", dialCode: "+225", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
89
|
+
{ iso: "HR", name: "Croacia", dialCode: "+385", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
90
|
+
{ iso: "CU", name: "Cuba", dialCode: "+53", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
91
|
+
{ iso: "CW", name: "Curazao", dialCode: "+599", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
92
|
+
{ iso: "DK", name: "Dinamarca", dialCode: "+45", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
93
|
+
{ iso: "DM", name: "Dominica", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
94
|
+
{ iso: "EG", name: "Egipto", dialCode: "+20", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
95
|
+
{ iso: "AE", name: "Emiratos Árabes Unidos", dialCode: "+971", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
96
|
+
{ iso: "ER", name: "Eritrea", dialCode: "+291", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
97
|
+
{ iso: "SK", name: "Eslovaquia", dialCode: "+421", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
98
|
+
{ iso: "SI", name: "Eslovenia", dialCode: "+386", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
99
|
+
{ iso: "EE", name: "Estonia", dialCode: "+372", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
100
|
+
{ iso: "ET", name: "Etiopía", dialCode: "+251", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
101
|
+
{ iso: "FK", name: "Falkland Islands", dialCode: "+500", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
102
|
+
{ iso: "FO", name: "Faroe Islands", dialCode: "+298", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
103
|
+
{ iso: "PH", name: "Filipinas", dialCode: "+63", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
104
|
+
{ iso: "FI", name: "Finlandia", dialCode: "+358", nationalMinLength: 9, nationalMaxLength: 10 },
|
|
105
|
+
{ iso: "FJ", name: "Fiyi", dialCode: "+679", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
106
|
+
{ iso: "FR", name: "Francia", dialCode: "+33", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
107
|
+
{ iso: "TF", name: "French Southern Territories", dialCode: "+262", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
108
|
+
{ iso: "GA", name: "Gabón", dialCode: "+241", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
109
|
+
{ iso: "GM", name: "Gambia", dialCode: "+220", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
110
|
+
{ iso: "GE", name: "Georgia", dialCode: "+995", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
111
|
+
{ iso: "GH", name: "Ghana", dialCode: "+233", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
112
|
+
{ iso: "GI", name: "Gibraltar", dialCode: "+350", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
113
|
+
{ iso: "GD", name: "Granada", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
114
|
+
{ iso: "GR", name: "Grecia", dialCode: "+30", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
115
|
+
{ iso: "GL", name: "Groenlandia", dialCode: "+299", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
116
|
+
{ iso: "GP", name: "Guadalupe", dialCode: "+590", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
117
|
+
{ iso: "GU", name: "Guam", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
118
|
+
{ iso: "GF", name: "Guayana Francesa", dialCode: "+594", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
119
|
+
{ iso: "GG", name: "Guernsey", dialCode: "+44", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
120
|
+
{ iso: "GN", name: "Guinea", dialCode: "+224", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
121
|
+
{ iso: "GQ", name: "Guinea Ecuatorial", dialCode: "+240", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
122
|
+
{ iso: "GW", name: "Guinea-Bisáu", dialCode: "+245", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
123
|
+
{ iso: "GY", name: "Guyana", dialCode: "+592", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
124
|
+
{ iso: "HT", name: "Haití", dialCode: "+509", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
125
|
+
{ iso: "HM", name: "Heard Island and McDonald Islands", dialCode: "+672", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
126
|
+
{ iso: "HK", name: "Hong Kong", dialCode: "+852", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
127
|
+
{ iso: "HU", name: "Hungría", dialCode: "+36", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
128
|
+
{ iso: "IN", name: "India", dialCode: "+91", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
129
|
+
{ iso: "ID", name: "Indonesia", dialCode: "+62", nationalMinLength: 9, nationalMaxLength: 12 },
|
|
130
|
+
{ iso: "IQ", name: "Irak", dialCode: "+964", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
131
|
+
{ iso: "IR", name: "Irán", dialCode: "+98", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
132
|
+
{ iso: "IE", name: "Irlanda", dialCode: "+353", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
133
|
+
{ iso: "IS", name: "Islandia", dialCode: "+354", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
134
|
+
{ iso: "IL", name: "Israel", dialCode: "+972", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
135
|
+
{ iso: "IT", name: "Italia", dialCode: "+39", nationalMinLength: 9, nationalMaxLength: 10 },
|
|
136
|
+
{ iso: "JM", name: "Jamaica", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
137
|
+
{ iso: "JP", name: "Japón", dialCode: "+81", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
138
|
+
{ iso: "JE", name: "Jersey", dialCode: "+44", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
139
|
+
{ iso: "JO", name: "Jordania", dialCode: "+962", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
140
|
+
{ iso: "KZ", name: "Kazajistán", dialCode: "+7", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
141
|
+
{ iso: "KE", name: "Kenia", dialCode: "+254", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
142
|
+
{ iso: "KG", name: "Kirguistán", dialCode: "+996", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
143
|
+
{ iso: "KI", name: "Kiribati", dialCode: "+686", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
144
|
+
{ iso: "XK", name: "Kosovo", dialCode: "+383", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
145
|
+
{ iso: "KW", name: "Kuwait", dialCode: "+965", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
146
|
+
{ iso: "LA", name: "Laos", dialCode: "+856", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
147
|
+
{ iso: "LS", name: "Lesoto", dialCode: "+266", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
148
|
+
{ iso: "LV", name: "Letonia", dialCode: "+371", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
149
|
+
{ iso: "LB", name: "Líbano", dialCode: "+961", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
150
|
+
{ iso: "LR", name: "Liberia", dialCode: "+231", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
151
|
+
{ iso: "LY", name: "Libia", dialCode: "+218", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
152
|
+
{ iso: "LI", name: "Liechtenstein", dialCode: "+423", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
153
|
+
{ iso: "LT", name: "Lituania", dialCode: "+370", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
154
|
+
{ iso: "LU", name: "Luxemburgo", dialCode: "+352", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
155
|
+
{ iso: "MO", name: "Macao", dialCode: "+853", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
156
|
+
{ iso: "MK", name: "Macedonia del Norte", dialCode: "+389", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
157
|
+
{ iso: "MG", name: "Madagascar", dialCode: "+261", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
158
|
+
{ iso: "MY", name: "Malasia", dialCode: "+60", nationalMinLength: 9, nationalMaxLength: 10 },
|
|
159
|
+
{ iso: "MW", name: "Malaui", dialCode: "+265", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
160
|
+
{ iso: "MV", name: "Maldivas", dialCode: "+960", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
161
|
+
{ iso: "ML", name: "Malí", dialCode: "+223", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
162
|
+
{ iso: "MT", name: "Malta", dialCode: "+356", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
163
|
+
{ iso: "IM", name: "Man (Isle of)", dialCode: "+44", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
164
|
+
{ iso: "MA", name: "Marruecos", dialCode: "+212", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
165
|
+
{ iso: "MH", name: "Marshall Islands", dialCode: "+692", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
166
|
+
{ iso: "MQ", name: "Martinica", dialCode: "+596", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
167
|
+
{ iso: "MU", name: "Mauricio", dialCode: "+230", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
168
|
+
{ iso: "MR", name: "Mauritania", dialCode: "+222", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
169
|
+
{ iso: "YT", name: "Mayotte", dialCode: "+262", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
170
|
+
{ iso: "FM", name: "Micronesia", dialCode: "+691", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
171
|
+
{ iso: "MD", name: "Moldavia", dialCode: "+373", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
172
|
+
{ iso: "MC", name: "Mónaco", dialCode: "+377", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
173
|
+
{ iso: "MN", name: "Mongolia", dialCode: "+976", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
174
|
+
{ iso: "ME", name: "Montenegro", dialCode: "+382", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
175
|
+
{ iso: "MS", name: "Montserrat", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
176
|
+
{ iso: "MZ", name: "Mozambique", dialCode: "+258", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
177
|
+
{ iso: "MM", name: "Myanmar", dialCode: "+95", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
178
|
+
{ iso: "NA", name: "Namibia", dialCode: "+264", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
179
|
+
{ iso: "NR", name: "Nauru", dialCode: "+674", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
180
|
+
{ iso: "NP", name: "Nepal", dialCode: "+977", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
181
|
+
{ iso: "NE", name: "Níger", dialCode: "+227", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
182
|
+
{ iso: "NG", name: "Nigeria", dialCode: "+234", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
183
|
+
{ iso: "NU", name: "Niue", dialCode: "+683", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
184
|
+
{ iso: "NF", name: "Norfolk Island", dialCode: "+672", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
185
|
+
{ iso: "MP", name: "Northern Mariana Islands", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
186
|
+
{ iso: "NO", name: "Noruega", dialCode: "+47", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
187
|
+
{ iso: "NC", name: "Nueva Caledonia", dialCode: "+687", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
188
|
+
{ iso: "NZ", name: "Nueva Zelanda", dialCode: "+64", nationalMinLength: 8, nationalMaxLength: 10 },
|
|
189
|
+
{ iso: "OM", name: "Omán", dialCode: "+968", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
190
|
+
{ iso: "NL", name: "Países Bajos", dialCode: "+31", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
191
|
+
{ iso: "PK", name: "Pakistán", dialCode: "+92", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
192
|
+
{ iso: "PW", name: "Palaos", dialCode: "+680", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
193
|
+
{ iso: "PS", name: "Palestina", dialCode: "+970", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
194
|
+
{ iso: "PG", name: "Papúa Nueva Guinea", dialCode: "+675", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
195
|
+
{ iso: "PN", name: "Pitcairn Island", dialCode: "+870", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
196
|
+
{ iso: "PF", name: "Polinesia Francesa", dialCode: "+689", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
197
|
+
{ iso: "PL", name: "Polonia", dialCode: "+48", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
198
|
+
{ iso: "PT", name: "Portugal", dialCode: "+351", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
199
|
+
{ iso: "GB", name: "Reino Unido", dialCode: "+44", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
200
|
+
{ iso: "CZ", name: "Rep. Checa", dialCode: "+420", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
201
|
+
{ iso: "CF", name: "República Centroafricana", dialCode: "+236", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
202
|
+
{ iso: "RE", name: "Reunión", dialCode: "+262", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
203
|
+
{ iso: "RW", name: "Ruanda", dialCode: "+250", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
204
|
+
{ iso: "RO", name: "Rumanía", dialCode: "+40", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
205
|
+
{ iso: "RU", name: "Rusia", dialCode: "+7", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
206
|
+
{ iso: "EH", name: "Sáhara Occidental", dialCode: "+212", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
207
|
+
{ iso: "WS", name: "Samoa", dialCode: "+685", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
208
|
+
{ iso: "AS", name: "Samoa Americana", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
209
|
+
{ iso: "BL", name: "San Bartolomé", dialCode: "+590", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
210
|
+
{ iso: "KN", name: "San Cristóbal y Nieves", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
211
|
+
{ iso: "SM", name: "San Marino", dialCode: "+378", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
212
|
+
{ iso: "MF", name: "San Martín", dialCode: "+590", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
213
|
+
{ iso: "PM", name: "San Pedro y Miquelón", dialCode: "+508", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
214
|
+
{ iso: "VC", name: "San Vicente y las Granadinas", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
215
|
+
{ iso: "SH", name: "Santa Elena", dialCode: "+290", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
216
|
+
{ iso: "LC", name: "Santa Lucía", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
217
|
+
{ iso: "ST", name: "Santo Tomé y Príncipe", dialCode: "+239", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
218
|
+
{ iso: "SN", name: "Senegal", dialCode: "+221", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
219
|
+
{ iso: "RS", name: "Serbia", dialCode: "+381", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
220
|
+
{ iso: "SC", name: "Seychelles", dialCode: "+248", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
221
|
+
{ iso: "SL", name: "Sierra Leona", dialCode: "+232", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
222
|
+
{ iso: "SG", name: "Singapur", dialCode: "+65", nationalMinLength: 8, nationalMaxLength: 8 },
|
|
223
|
+
{ iso: "SX", name: "Sint Maarten", dialCode: "+1721", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
224
|
+
{ iso: "SY", name: "Siria", dialCode: "+963", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
225
|
+
{ iso: "SB", name: "Solomon Islands", dialCode: "+677", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
226
|
+
{ iso: "SO", name: "Somalia", dialCode: "+252", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
227
|
+
{ iso: "GS", name: "South Georgia", dialCode: "+500", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
228
|
+
{ iso: "LK", name: "Sri Lanka", dialCode: "+94", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
229
|
+
{ iso: "SZ", name: "Suazilandia", dialCode: "+268", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
230
|
+
{ iso: "ZA", name: "Sudáfrica", dialCode: "+27", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
231
|
+
{ iso: "SD", name: "Sudán", dialCode: "+249", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
232
|
+
{ iso: "SS", name: "Sudán del Sur", dialCode: "+211", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
233
|
+
{ iso: "SE", name: "Suecia", dialCode: "+46", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
234
|
+
{ iso: "CH", name: "Suiza", dialCode: "+41", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
235
|
+
{ iso: "SR", name: "Surinam", dialCode: "+597", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
236
|
+
{ iso: "SJ", name: "Svalbard and Jan Mayen Islands", dialCode: "+47", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
237
|
+
{ iso: "TH", name: "Tailandia", dialCode: "+66", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
238
|
+
{ iso: "TW", name: "Taiwán", dialCode: "+886", nationalMinLength: 9, nationalMaxLength: 9 },
|
|
239
|
+
{ iso: "TZ", name: "Tanzania", dialCode: "+255", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
240
|
+
{ iso: "TJ", name: "Tayikistán", dialCode: "+992", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
241
|
+
{ iso: "TL", name: "Timor Oriental", dialCode: "+670", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
242
|
+
{ iso: "TG", name: "Togo", dialCode: "+228", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
243
|
+
{ iso: "TK", name: "Tokelau", dialCode: "+690", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
244
|
+
{ iso: "TO", name: "Tonga", dialCode: "+676", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
245
|
+
{ iso: "TT", name: "Trinidad y Tobago", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
246
|
+
{ iso: "TN", name: "Túnez", dialCode: "+216", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
247
|
+
{ iso: "TM", name: "Turkmenistán", dialCode: "+993", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
248
|
+
{ iso: "TC", name: "Turks and Caicos Islands", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
249
|
+
{ iso: "TR", name: "Turquía", dialCode: "+90", nationalMinLength: 10, nationalMaxLength: 10 },
|
|
250
|
+
{ iso: "TV", name: "Tuvalu", dialCode: "+688", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
251
|
+
{ iso: "UA", name: "Ucrania", dialCode: "+380", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
252
|
+
{ iso: "UG", name: "Uganda", dialCode: "+256", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
253
|
+
{ iso: "UM", name: "United States Minor Outlying Islands", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
254
|
+
{ iso: "UZ", name: "Uzbekistán", dialCode: "+998", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
255
|
+
{ iso: "VU", name: "Vanuatu", dialCode: "+678", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
256
|
+
{ iso: "VN", name: "Vietnam", dialCode: "+84", nationalMinLength: 9, nationalMaxLength: 10 },
|
|
257
|
+
{ iso: "VG", name: "Virgin Islands (British)", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
258
|
+
{ iso: "VI", name: "Virgin Islands (US)", dialCode: "+1", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
259
|
+
{ iso: "WF", name: "Wallis and Futuna Islands", dialCode: "+681", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
260
|
+
{ iso: "YE", name: "Yemen", dialCode: "+967", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
261
|
+
{ iso: "DJ", name: "Yibuti", dialCode: "+253", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
262
|
+
{ iso: "ZM", name: "Zambia", dialCode: "+260", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
263
|
+
{ iso: "ZW", name: "Zimbabue", dialCode: "+263", nationalMinLength: 7, nationalMaxLength: 15 },
|
|
264
|
+
];
|
|
265
|
+
|
|
266
|
+
export const DEFAULT_PHONE_COUNTRY_ISO = "EC";
|
|
267
|
+
|
|
268
|
+
export function getPhoneCountryByIso(
|
|
269
|
+
iso?: string | null,
|
|
270
|
+
): PhoneCountry | undefined {
|
|
271
|
+
if (!iso) return undefined;
|
|
272
|
+
return PHONE_COUNTRIES.find((c) => c.iso === iso);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export function getPhoneCountryByDialCode(dialCode: string): PhoneCountry | undefined {
|
|
276
|
+
const normalized = dialCode.startsWith("+") ? dialCode : `+${dialCode}`;
|
|
277
|
+
return [...PHONE_COUNTRIES]
|
|
278
|
+
.sort((a, b) => b.dialCode.length - a.dialCode.length)
|
|
279
|
+
.find((c) => normalized.startsWith(c.dialCode));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function digitsOnly(value: string): string {
|
|
283
|
+
return value.replace(/\D/g, "");
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function findCountryByDialDigits(digits: string): PhoneCountry | undefined {
|
|
287
|
+
return [...PHONE_COUNTRIES]
|
|
288
|
+
.sort((a, b) => b.dialCode.length - a.dialCode.length)
|
|
289
|
+
.find((country) => digits.startsWith(digitsOnly(country.dialCode)));
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/** Quita el 0 de red después del código de país (+59309… → +5939…). */
|
|
293
|
+
function stripTrunkZeroAfterDialCode(digits: string): string {
|
|
294
|
+
const matched = matchInternationalE164(digits);
|
|
295
|
+
return matched ? digitsOnly(matched) : digits;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Si los dígitos ya traen código de país y el tramo nacional cierra,
|
|
300
|
+
* devuelve E.164. Evita tratar 3001234567 (Colombia) como +30 Grecia.
|
|
301
|
+
*/
|
|
302
|
+
function matchInternationalE164(digits: string): string | null {
|
|
303
|
+
const country = findCountryByDialDigits(digits);
|
|
304
|
+
if (!country) return null;
|
|
305
|
+
const dial = digitsOnly(country.dialCode);
|
|
306
|
+
if (digits.length <= dial.length) return null;
|
|
307
|
+
let national = digits.slice(dial.length);
|
|
308
|
+
if (national.startsWith("0")) national = national.slice(1);
|
|
309
|
+
if (
|
|
310
|
+
national.length >= country.nationalMinLength &&
|
|
311
|
+
national.length <= country.nationalMaxLength
|
|
312
|
+
) {
|
|
313
|
+
return `+${dial}${national}`;
|
|
314
|
+
}
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export function looksLikePhoneNumber(value: string): boolean {
|
|
319
|
+
const trimmed = value.trim();
|
|
320
|
+
if (!trimmed) return false;
|
|
321
|
+
if (/^https?:\/\//i.test(trimmed)) return false;
|
|
322
|
+
if (/www\./i.test(trimmed)) return false;
|
|
323
|
+
if (/\.[a-z]{2,}(\/|$)/i.test(trimmed) && !trimmed.startsWith("+")) {
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
const digits = digitsOnly(trimmed);
|
|
328
|
+
if (digits.length < 7 || digits.length > 15) return false;
|
|
329
|
+
|
|
330
|
+
return /^\+?[\d\s().-]+$/.test(trimmed);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/** Formato E.164 (+593…) al guardar prospectos de marketing. */
|
|
334
|
+
export function normalizePhoneForStorage(
|
|
335
|
+
raw: string,
|
|
336
|
+
countryCode?: string | null,
|
|
337
|
+
): string {
|
|
338
|
+
const trimmed = raw.trim();
|
|
339
|
+
if (!trimmed) return "";
|
|
340
|
+
|
|
341
|
+
const international =
|
|
342
|
+
trimmed.startsWith("+") || trimmed.startsWith("00");
|
|
343
|
+
let digits = digitsOnly(
|
|
344
|
+
international && trimmed.startsWith("00") ? trimmed.slice(2) : trimmed,
|
|
345
|
+
);
|
|
346
|
+
if (!digits) return trimmed;
|
|
347
|
+
|
|
348
|
+
const asInternational = matchInternationalE164(digits);
|
|
349
|
+
if (asInternational) return asInternational;
|
|
350
|
+
|
|
351
|
+
if (international) {
|
|
352
|
+
return `+${stripTrunkZeroAfterDialCode(digits)}`;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const phoneCountry =
|
|
356
|
+
getPhoneCountryByIso(countryCode) ??
|
|
357
|
+
getPhoneCountryByIso(DEFAULT_PHONE_COUNTRY_ISO)!;
|
|
358
|
+
const dialDigits = digitsOnly(phoneCountry.dialCode);
|
|
359
|
+
|
|
360
|
+
if (digits.startsWith(dialDigits)) {
|
|
361
|
+
return `+${stripTrunkZeroAfterDialCode(digits)}`;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
if (digits.startsWith("0")) {
|
|
365
|
+
digits = digits.slice(1);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
if (
|
|
369
|
+
digits.length >= phoneCountry.nationalMinLength &&
|
|
370
|
+
digits.length <= phoneCountry.nationalMaxLength
|
|
371
|
+
) {
|
|
372
|
+
return `${phoneCountry.dialCode}${digits}`;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (digits.length >= 10) {
|
|
376
|
+
return `+${stripTrunkZeroAfterDialCode(digits)}`;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return `${phoneCountry.dialCode}${digits}`;
|
|
380
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_PHONE_COUNTRY_ISO,
|
|
3
|
+
getPhoneCountryByDialCode,
|
|
4
|
+
getPhoneCountryByIso,
|
|
5
|
+
type PhoneCountry,
|
|
6
|
+
} from "./phone-countries";
|
|
7
|
+
|
|
8
|
+
/** Normaliza a E.164 básico para auth (+593..., +1..., etc.). */
|
|
9
|
+
export function normalizePhoneToE164(raw: string): string {
|
|
10
|
+
const trimmed = raw.trim().replace(/\s/g, "");
|
|
11
|
+
if (!trimmed) return "";
|
|
12
|
+
if (trimmed.startsWith("+")) return trimmed;
|
|
13
|
+
if (trimmed.startsWith("00")) return `+${trimmed.slice(2)}`;
|
|
14
|
+
return `+${trimmed}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function digitsOnly(value: string): string {
|
|
18
|
+
return value.replace(/\D/g, "");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function buildPhoneE164(country: PhoneCountry, nationalNumber: string): string {
|
|
22
|
+
const national = digitsOnly(nationalNumber);
|
|
23
|
+
if (!national) return "";
|
|
24
|
+
return `${country.dialCode}${national}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type ParsedPhone = {
|
|
28
|
+
country: PhoneCountry;
|
|
29
|
+
nationalNumber: string;
|
|
30
|
+
e164: string;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export function parsePhoneE164(
|
|
34
|
+
raw: string,
|
|
35
|
+
fallbackIso = DEFAULT_PHONE_COUNTRY_ISO,
|
|
36
|
+
): ParsedPhone | null {
|
|
37
|
+
const e164 = normalizePhoneToE164(raw);
|
|
38
|
+
const fallback = getPhoneCountryByIso(fallbackIso) ?? getPhoneCountryByIso("EC");
|
|
39
|
+
if (!fallback) return null;
|
|
40
|
+
|
|
41
|
+
if (!e164) {
|
|
42
|
+
return { country: fallback, nationalNumber: "", e164: "" };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const country = getPhoneCountryByDialCode(e164) ?? fallback;
|
|
46
|
+
const nationalNumber = digitsOnly(e164.slice(country.dialCode.length));
|
|
47
|
+
return {
|
|
48
|
+
country,
|
|
49
|
+
nationalNumber,
|
|
50
|
+
e164: nationalNumber ? buildPhoneE164(country, nationalNumber) : "",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function isNationalNumberValidForCountry(
|
|
55
|
+
country: PhoneCountry,
|
|
56
|
+
nationalNumber: string,
|
|
57
|
+
): boolean {
|
|
58
|
+
const len = digitsOnly(nationalNumber).length;
|
|
59
|
+
return len >= country.nationalMinLength && len <= country.nationalMaxLength;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function isPhoneE164ReadyForSms(raw: string): boolean {
|
|
63
|
+
const parsed = parsePhoneE164(raw);
|
|
64
|
+
if (!parsed?.e164 || !parsed.nationalNumber) return false;
|
|
65
|
+
return isNationalNumberValidForCountry(parsed.country, parsed.nationalNumber);
|
|
66
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import "@testing-library/jest-dom/vitest";
|
|
2
|
+
import { cleanup } from "@testing-library/react";
|
|
3
|
+
import { afterEach } from "vitest";
|
|
4
|
+
|
|
5
|
+
afterEach(() => {
|
|
6
|
+
cleanup();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
class ResizeObserverMock {
|
|
10
|
+
observe() {}
|
|
11
|
+
unobserve() {}
|
|
12
|
+
disconnect() {}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
globalThis.ResizeObserver = ResizeObserverMock;
|
|
16
|
+
|
|
17
|
+
if (!Element.prototype.scrollIntoView) {
|
|
18
|
+
Element.prototype.scrollIntoView = () => {};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!HTMLElement.prototype.hasPointerCapture) {
|
|
22
|
+
HTMLElement.prototype.hasPointerCapture = () => false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!HTMLElement.prototype.setPointerCapture) {
|
|
26
|
+
HTMLElement.prototype.setPointerCapture = () => {};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!HTMLElement.prototype.releasePointerCapture) {
|
|
30
|
+
HTMLElement.prototype.releasePointerCapture = () => {};
|
|
31
|
+
}
|