add telephone code select

This commit is contained in:
Samuel Newman
2025-11-12 16:50:04 +02:00
parent 4d50555e56
commit 7a78046c54
6 changed files with 453 additions and 40 deletions
@@ -0,0 +1,71 @@
import {Fragment, useMemo} from 'react'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {getCountriesWithTelephoneCodes} from '#/lib/international-telephone-codes'
import {useGeolocationStatus} from '#/state/geolocation'
import {atoms as a} from '#/alf'
import * as Select from '#/components/Select'
/**
* Country picker for a phone number input
*
* Pro tip: you can use `location?.countryCode` from `useGeolocationStatus()`
* to set a default value.
*/
export function InternationalPhoneCodeSelect({
value,
onChange,
}: {
value?: string
onChange: (value: string) => void
}) {
const {_, i18n} = useLingui()
const {location} = useGeolocationStatus()
const items = useMemo(() => {
const telCountryMap = getCountriesWithTelephoneCodes(i18n)
return (
Object.entries(telCountryMap)
.map(([value, {name, code}]) => ({
value,
name,
code,
label: `${name} ${code}`,
}))
// boost the default value to the top
.sort((a, b) =>
a.value === location.countryCode
? -1
: b.value === location.countryCode
? 1
: 0,
)
)
}, [i18n, location])
return (
<Select.Root value={value} onValueChange={onChange}>
<Select.Trigger label={_(msg`Select telephone code`)}>
<Select.ValueText placeholder={_(msg`Select telephone code`)} />
<Select.Icon />
</Select.Trigger>
<Select.Content
label={_(msg`Country code`)}
items={items}
renderItem={item => (
<Fragment key={item.value}>
<Select.Item value={item.value} label={item.label}>
<Select.ItemIndicator />
<Select.ItemText style={[a.flex_1]}>{item.name}</Select.ItemText>
<Select.ItemText style={[a.text_right]}>
{item.code}
</Select.ItemText>
</Select.Item>
{item.value === location?.countryCode && <Select.Separator />}
</Fragment>
)}
/>
</Select.Root>
)
}
+55 -36
View File
@@ -7,7 +7,7 @@ import {
useState,
} from 'react'
import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useTheme} from '#/alf'
@@ -15,9 +15,9 @@ import {atoms as a} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {useInteractionState} from '#/components/hooks/useInteractionState'
import {Check_Stroke2_Corner0_Rounded as CheckIcon} from '#/components/icons/Check'
import {ChevronTopBottom_Stroke2_Corner0_Rounded as ChevronUpDownIcon} from '#/components/icons/Chevron'
import {Text} from '#/components/Typography'
import {BaseRadio} from '../forms/Toggle'
import {
type ContentProps,
type IconProps,
@@ -162,15 +162,14 @@ export function Content<T>({
}
function ContentInner<T>({
label,
items,
renderItem,
valueExtractor,
...context
}: ContentProps<T> & ContextType) {
const control = Dialog.useDialogContext()
const {_} = useLingui()
const [headerHeight, setHeaderHeight] = useState(50)
const [headerHeight, setHeaderHeight] = useState(61)
const render = useCallback(
({item, index}: {item: T; index: number}) => {
@@ -179,33 +178,26 @@ function ContentInner<T>({
[renderItem, context.value],
)
const doneButton = useCallback(
() => (
<Button
label={_(msg`Done`)}
onPress={() => control.close()}
size="small"
color="primary"
variant="ghost"
style={[a.rounded_full]}>
<ButtonText style={[a.text_md]}>
<Trans>Done</Trans>
</ButtonText>
</Button>
),
[control, _],
)
return (
<Context.Provider value={context}>
<Dialog.Header
renderRight={doneButton}
onLayout={evt => setHeaderHeight(evt.nativeEvent.layout.height)}
style={[a.absolute, a.top_0, a.left_0, a.right_0, a.z_10]}>
<Dialog.HeaderText>
<Trans>Select an option</Trans>
style={[
a.absolute,
a.top_0,
a.left_0,
a.right_0,
a.z_10,
a.pt_3xl,
a.pb_sm,
a.border_b_0,
]}>
<Dialog.HeaderText
style={[a.flex_1, a.px_xl, a.text_left, a.font_bold, a.text_2xl]}>
{label ?? _(msg`Select an option`)}
</Dialog.HeaderText>
</Dialog.Header>
<Dialog.Handle />
<Dialog.InnerFlatList
headerOffset={headerHeight}
data={items}
@@ -258,11 +250,12 @@ export function Item({children, value, label, style}: ItemProps) {
<View
style={[
a.flex_1,
a.pl_md,
a.px_xl,
(focused || pressed) && t.atoms.bg_contrast_25,
a.flex_row,
a.align_center,
a.gap_sm,
a.py_md,
style,
]}>
{children}
@@ -273,20 +266,46 @@ export function Item({children, value, label, style}: ItemProps) {
)
}
export function ItemText({children}: ItemTextProps) {
export function ItemText({children, style}: ItemTextProps) {
const {selected} = useItemContext()
const t = useTheme()
// eslint-disable-next-line bsky-internal/avoid-unwrapped-text
return (
<View style={[a.flex_1, a.py_md, a.border_b, t.atoms.border_contrast_low]}>
<Text style={[a.text_md, selected && a.font_semi_bold]}>{children}</Text>
</View>
<Text style={[a.text_md, selected && a.font_semi_bold, style]}>
{children}
</Text>
)
}
export function ItemIndicator({icon: Icon = CheckIcon}: ItemIndicatorProps) {
const {selected} = useItemContext()
export function ItemIndicator({icon: Icon}: ItemIndicatorProps) {
const {selected, focused, hovered} = useItemContext()
return <View style={{width: 24}}>{selected && <Icon size="md" />}</View>
if (Icon) {
return <View style={{width: 24}}>{selected && <Icon size="md" />}</View>
}
return (
<BaseRadio
selected={selected}
focused={focused}
hovered={hovered}
isInvalid={false}
disabled={false}
/>
)
}
export function Separator() {
const t = useTheme()
return (
<View
style={[
a.flex_1,
a.border_b,
t.atoms.border_contrast_low,
a.mx_xl,
a.my_xs,
]}
/>
)
}
+33 -2
View File
@@ -1,4 +1,11 @@
import {createContext, forwardRef, Fragment, useContext, useMemo} from 'react'
import {
createContext,
type CSSProperties,
forwardRef,
Fragment,
useContext,
useMemo,
} from 'react'
import {View} from 'react-native'
import {Select as RadixSelect} from 'radix-ui'
@@ -16,6 +23,7 @@ import {
type IconProps,
type ItemIndicatorProps,
type ItemProps,
type ItemTextProps,
type RadixPassThroughTriggerProps,
type RootProps,
type TriggerProps,
@@ -278,7 +286,13 @@ export function Item({ref, value, style, children}: ItemProps) {
)
}
export const ItemText = RadixSelect.ItemText
export const ItemText = function ItemText({children, style}: ItemTextProps) {
return (
<RadixSelect.ItemText style={flatten(style) as CSSProperties}>
{children}
</RadixSelect.ItemText>
)
}
export function ItemIndicator({icon: Icon = CheckIcon}: ItemIndicatorProps) {
return (
@@ -294,3 +308,20 @@ export function ItemIndicator({icon: Icon = CheckIcon}: ItemIndicatorProps) {
</RadixSelect.ItemIndicator>
)
}
export function Separator() {
const t = useTheme()
return (
<RadixSelect.Separator
style={flatten([
{
height: 1,
backgroundColor: t.atoms.border_contrast_low.borderColor,
},
a.my_xs,
a.w_full,
])}
/>
)
}
+7
View File
@@ -137,6 +137,12 @@ export type ValueProps = {
export type IconProps = TextStyleProp
export type ContentProps<T> = {
/**
* Label at the top of the sheet on native.
*
* @default "Select an option"
*/
label?: string
/**
* Items to render. Recommended to be in the form {value: string, label: string} - if not,
* you need to provide a `valueExtractor` function to extract the value from an item and
@@ -180,6 +186,7 @@ export type ItemProps = {
export type ItemTextProps = {
children: React.ReactNode
style?: StyleProp<TextStyle>
}
export type ItemIndicatorProps = {
+17 -2
View File
@@ -503,9 +503,23 @@ export function Switch() {
}
export function Radio() {
const props = useContext(ItemContext)
return <BaseRadio {...props} />
}
export function BaseRadio({
hovered,
focused,
selected,
disabled,
isInvalid,
}: Pick<
ItemState,
'hovered' | 'focused' | 'selected' | 'disabled' | 'isInvalid'
>) {
const t = useTheme()
const {selected, hovered, focused, disabled, isInvalid} =
useContext(ItemContext)
const {baseStyles, baseHoverStyles, indicatorStyles} =
createSharedToggleStyles({
theme: t,
@@ -515,6 +529,7 @@ export function Radio() {
disabled,
isInvalid,
})
return (
<View
style={[
+270
View File
@@ -0,0 +1,270 @@
import {type I18n} from '@lingui/core'
import {msg} from '@lingui/macro'
export function getCountriesWithTelephoneCodes(i18n: I18n) {
return {
AD: {name: i18n._(msg`Andorra`), code: '+376'},
AF: {name: i18n._(msg`Afghanistan`), code: '+93'},
AG: {name: i18n._(msg`Antigua and Barbuda`), code: '+1268'},
AI: {name: i18n._(msg`Anguilla`), code: '+1264'},
AL: {name: i18n._(msg`Albania`), code: '+355'},
AM: {name: i18n._(msg`Armenia`), code: '+374'},
AO: {name: i18n._(msg`Angola`), code: '+244'},
AQ: {name: i18n._(msg`Antarctica`), code: '+672'},
AR: {name: i18n._(msg`Argentina`), code: '+54'},
AS: {name: i18n._(msg`American Samoa`), code: '+1684'},
AT: {name: i18n._(msg`Austria`), code: '+43'},
AU: {name: i18n._(msg`Australia`), code: '+61'},
AW: {name: i18n._(msg`Aruba`), code: '+297'},
AX: {name: i18n._(msg`Åland Islands`), code: '+358'},
AZ: {name: i18n._(msg`Azerbaijan`), code: '+994'},
BA: {name: i18n._(msg`Bosnia and Herzegovina`), code: '+387'},
BB: {name: i18n._(msg`Barbados`), code: '+1246'},
BD: {name: i18n._(msg`Bangladesh`), code: '+880'},
BE: {name: i18n._(msg`Belgium`), code: '+32'},
BF: {name: i18n._(msg`Burkina Faso`), code: '+226'},
BG: {name: i18n._(msg`Bulgaria`), code: '+359'},
BH: {name: i18n._(msg`Bahrain`), code: '+973'},
BI: {name: i18n._(msg`Burundi`), code: '+257'},
BJ: {name: i18n._(msg`Benin`), code: '+229'},
BL: {name: i18n._(msg`Saint Barthélemy`), code: '+590'},
BM: {name: i18n._(msg`Bermuda`), code: '+1441'},
BN: {name: i18n._(msg`Brunei Darussalam`), code: '+673'},
BO: {name: i18n._(msg`Bolivia (Plurinational State of)`), code: '+591'},
BQ: {name: i18n._(msg`Bonaire, Sint Eustatius and Saba`), code: '+5997'},
BR: {name: i18n._(msg`Brazil`), code: '+55'},
BT: {name: i18n._(msg`Bhutan`), code: '+975'},
BV: {name: i18n._(msg`Bouvet Island`), code: '+47'},
BW: {name: i18n._(msg`Botswana`), code: '+267'},
BY: {name: i18n._(msg`Belarus`), code: '+375'},
BZ: {name: i18n._(msg`Belize`), code: '+501'},
CA: {name: i18n._(msg`Canada`), code: '+1'},
CH: {name: i18n._(msg`Switzerland`), code: '+41'},
CI: {name: i18n._(msg`Côte d'Ivoire`), code: '+225'},
CL: {name: i18n._(msg`Chile`), code: '+56'},
CM: {name: i18n._(msg`Cameroon`), code: '+237'},
CN: {name: i18n._(msg`China`), code: '+86'},
CO: {name: i18n._(msg`Colombia`), code: '+57'},
CR: {name: i18n._(msg`Costa Rica`), code: '+506'},
CU: {name: i18n._(msg`Cuba`), code: '+53'},
CV: {name: i18n._(msg`Cabo Verde`), code: '+238'},
CW: {name: i18n._(msg`Curaçao`), code: '+599'},
CX: {name: i18n._(msg`Christmas Island`), code: '+61'},
CY: {name: i18n._(msg`Cyprus`), code: '+357'},
DE: {name: i18n._(msg`Germany`), code: '+49'},
DJ: {name: i18n._(msg`Djibouti`), code: '+253'},
DK: {name: i18n._(msg`Denmark`), code: '+45'},
DM: {name: i18n._(msg`Dominica`), code: '+767'},
DZ: {name: i18n._(msg`Algeria`), code: '+213'},
EC: {name: i18n._(msg`Ecuador`), code: '+593'},
EE: {name: i18n._(msg`Estonia`), code: '+372'},
EG: {name: i18n._(msg`Egypt`), code: '+20'},
EH: {name: i18n._(msg`Western Sahara`), code: '+212'},
ER: {name: i18n._(msg`Eritrea`), code: '+291'},
ES: {name: i18n._(msg`Spain`), code: '+34'},
ET: {name: i18n._(msg`Ethiopia`), code: '+251'},
FI: {name: i18n._(msg`Finland`), code: '+358'},
FJ: {name: i18n._(msg`Fiji`), code: '+679'},
FM: {name: i18n._(msg`Micronesia (Federated States of)`), code: '+691'},
FR: {name: i18n._(msg`France`), code: '+33'},
GA: {name: i18n._(msg`Gabon`), code: '+241'},
GD: {name: i18n._(msg`Grenada`), code: '+1473'},
GE: {name: i18n._(msg`Georgia`), code: '+995'},
GF: {name: i18n._(msg`French Guiana`), code: '+594'},
GG: {name: i18n._(msg`Guernsey`), code: '+44'},
GH: {name: i18n._(msg`Ghana`), code: '+233'},
GI: {name: i18n._(msg`Gibraltar`), code: '+350'},
GL: {name: i18n._(msg`Greenland`), code: '+299'},
GN: {name: i18n._(msg`Guinea`), code: '+224'},
GP: {name: i18n._(msg`Guadeloupe`), code: '+590'},
GQ: {name: i18n._(msg`Equatorial Guinea`), code: '+240'},
GR: {name: i18n._(msg`Greece`), code: '+30'},
GS: {
name: i18n._(msg`South Georgia and the South Sandwich Islands`),
code: '+500',
},
GT: {name: i18n._(msg`Guatemala`), code: '+502'},
GU: {name: i18n._(msg`Guam`), code: '+1'},
GW: {name: i18n._(msg`Guinea-Bissau`), code: '+245'},
GY: {name: i18n._(msg`Guyana`), code: '+592'},
HK: {name: i18n._(msg`Hong Kong`), code: '+852'},
HN: {name: i18n._(msg`Honduras`), code: '+504'},
HR: {name: i18n._(msg`Croatia`), code: '+385'},
HT: {name: i18n._(msg`Haiti`), code: '+509'},
HU: {name: i18n._(msg`Hungary`), code: '+36'},
ID: {name: i18n._(msg`Indonesia`), code: '+62'},
IE: {name: i18n._(msg`Ireland`), code: '+353'},
IL: {name: i18n._(msg`Israel`), code: '+972'},
IM: {name: i18n._(msg`Isle of Man`), code: '+44'},
IN: {name: i18n._(msg`India`), code: '+91'},
IO: {name: i18n._(msg`British Indian Ocean Territory`), code: '+246'},
IQ: {name: i18n._(msg`Iraq`), code: '+964'},
IR: {name: i18n._(msg`Iran (Islamic Republic of)`), code: '+98'},
IS: {name: i18n._(msg`Iceland`), code: '+354'},
IT: {name: i18n._(msg`Italy`), code: '+39'},
JE: {name: i18n._(msg`Jersey`), code: '+44'},
JM: {name: i18n._(msg`Jamaica`), code: '+876'},
JO: {name: i18n._(msg`Jordan`), code: '+962'},
JP: {name: i18n._(msg`Japan`), code: '+81'},
KE: {name: i18n._(msg`Kenya`), code: '+254'},
KG: {name: i18n._(msg`Kyrgyzstan`), code: '+996'},
KH: {name: i18n._(msg`Cambodia`), code: '+855'},
KP: {name: i18n._(msg`North Korea`), code: '+850'},
KR: {name: i18n._(msg`South Korea`), code: '+82'},
KI: {name: i18n._(msg`Kiribati`), code: '+686'},
KN: {name: i18n._(msg`Saint Kitts and Nevis`), code: '+1869'},
KW: {name: i18n._(msg`Kuwait`), code: '+965'},
KZ: {name: i18n._(msg`Kazakhstan`), code: '+7'},
LB: {name: i18n._(msg`Lebanon`), code: '+961'},
LC: {name: i18n._(msg`Saint Lucia`), code: '+1758'},
LI: {name: i18n._(msg`Liechtenstein`), code: '+423'},
LK: {name: i18n._(msg`Sri Lanka`), code: '+94'},
LR: {name: i18n._(msg`Liberia`), code: '+231'},
LS: {name: i18n._(msg`Lesotho`), code: '+266'},
LT: {name: i18n._(msg`Lithuania`), code: '+370'},
LU: {name: i18n._(msg`Luxembourg`), code: '+352'},
LV: {name: i18n._(msg`Latvia`), code: '+371'},
LY: {name: i18n._(msg`Libya`), code: '+218'},
MA: {name: i18n._(msg`Morocco`), code: '+212'},
MC: {name: i18n._(msg`Monaco`), code: '+377'},
ME: {name: i18n._(msg`Montenegro`), code: '+382'},
MF: {name: i18n._(msg`Saint Martin (French part)`), code: '+590'},
MG: {name: i18n._(msg`Madagascar`), code: '+261'},
ML: {name: i18n._(msg`Mali`), code: '+223'},
MM: {name: i18n._(msg`Myanmar`), code: '+95'},
MN: {name: i18n._(msg`Mongolia`), code: '+976'},
MO: {name: i18n._(msg`Macao`), code: '+853'},
MQ: {name: i18n._(msg`Martinique`), code: '+596'},
MR: {name: i18n._(msg`Mauritania`), code: '+222'},
MS: {name: i18n._(msg`Montserrat`), code: '+1664'},
MT: {name: i18n._(msg`Malta`), code: '+356'},
MU: {name: i18n._(msg`Mauritius`), code: '+230'},
MV: {name: i18n._(msg`Maldives`), code: '+960'},
MW: {name: i18n._(msg`Malawi`), code: '+265'},
MX: {name: i18n._(msg`Mexico`), code: '+52'},
MY: {name: i18n._(msg`Malaysia`), code: '+60'},
MZ: {name: i18n._(msg`Mozambique`), code: '+258'},
NA: {name: i18n._(msg`Namibia`), code: '+264'},
NC: {name: i18n._(msg`New Caledonia`), code: '+687'},
NF: {name: i18n._(msg`Norfolk Island`), code: '+672'},
NG: {name: i18n._(msg`Nigeria`), code: '+234'},
NI: {name: i18n._(msg`Nicaragua`), code: '+505'},
NO: {name: i18n._(msg`Norway`), code: '+47'},
NP: {name: i18n._(msg`Nepal`), code: '+977'},
NR: {name: i18n._(msg`Nauru`), code: '+674'},
NU: {name: i18n._(msg`Niue`), code: '+683'},
NZ: {name: i18n._(msg`New Zealand`), code: '+64'},
OM: {name: i18n._(msg`Oman`), code: '+968'},
PA: {name: i18n._(msg`Panama`), code: '+507'},
PE: {name: i18n._(msg`Peru`), code: '+51'},
PF: {name: i18n._(msg`French Polynesia`), code: '+689'},
PG: {name: i18n._(msg`Papua New Guinea`), code: '+675'},
PK: {name: i18n._(msg`Pakistan`), code: '+92'},
PL: {name: i18n._(msg`Poland`), code: '+48'},
PM: {name: i18n._(msg`Saint Pierre and Miquelon`), code: '+508'},
PN: {name: i18n._(msg`Pitcairn`), code: '+64'},
PR: {name: i18n._(msg`Puerto Rico`), code: '+1'},
PS: {name: i18n._(msg`Palestine, State of`), code: '+970'},
PT: {name: i18n._(msg`Portugal`), code: '+351'},
PW: {name: i18n._(msg`Palau`), code: '+680'},
PY: {name: i18n._(msg`Paraguay`), code: '+595'},
QA: {name: i18n._(msg`Qatar`), code: '+974'},
RE: {name: i18n._(msg`Réunion`), code: '+262'},
RO: {name: i18n._(msg`Romania`), code: '+40'},
RS: {name: i18n._(msg`Serbia`), code: '+381'},
RU: {name: i18n._(msg`Russia`), code: '+7'},
RW: {name: i18n._(msg`Rwanda`), code: '+250'},
SA: {name: i18n._(msg`Saudi Arabia`), code: '+966'},
SB: {name: i18n._(msg`Solomon Islands`), code: '+677'},
SC: {name: i18n._(msg`Seychelles`), code: '+248'},
SE: {name: i18n._(msg`Sweden`), code: '+46'},
SG: {name: i18n._(msg`Singapore`), code: '+65'},
SH: {
name: i18n._(msg`Saint Helena, Ascension and Tristan da Cunha`),
code: '+290',
},
SI: {name: i18n._(msg`Slovenia`), code: '+386'},
SJ: {name: i18n._(msg`Svalbard and Jan Mayen`), code: '+4779'},
SK: {name: i18n._(msg`Slovakia`), code: '+421'},
SL: {name: i18n._(msg`Sierra Leone`), code: '+232'},
SM: {name: i18n._(msg`Republic of San Marino`), code: '+378'},
SN: {name: i18n._(msg`Senegal`), code: '+221'},
SO: {name: i18n._(msg`Somalia`), code: '+252'},
SR: {name: i18n._(msg`Suriname`), code: '+597'},
SS: {name: i18n._(msg`South Sudan`), code: '+211'},
ST: {name: i18n._(msg`Sao Tome and Principe`), code: '+239'},
SV: {name: i18n._(msg`El Salvador`), code: '+503'},
SX: {name: i18n._(msg`Sint Maarten (Dutch part)`), code: '+1721'},
SY: {name: i18n._(msg`Syrian Arab Republic`), code: '+963'},
TD: {name: i18n._(msg`Chad`), code: '+235'},
TG: {name: i18n._(msg`Togo`), code: '+228'},
TH: {name: i18n._(msg`Thailand`), code: '+66'},
TJ: {name: i18n._(msg`Tajikistan`), code: '+992'},
TK: {name: i18n._(msg`Tokelau`), code: '+690'},
TL: {name: i18n._(msg`Timor-Leste`), code: '+670'},
TM: {name: i18n._(msg`Turkmenistan`), code: '+993'},
TN: {name: i18n._(msg`Tunisia`), code: '+216'},
TO: {name: i18n._(msg`Tonga`), code: '+676'},
TR: {name: i18n._(msg`Turkey`), code: '+90'},
TT: {name: i18n._(msg`Trinidad and Tobago`), code: '+868'},
TV: {name: i18n._(msg`Tuvalu`), code: '+688'},
TZ: {name: i18n._(msg`United Republic of Tanzania`), code: '+255'},
UA: {name: i18n._(msg`Ukraine`), code: '+380'},
UG: {name: i18n._(msg`Uganda`), code: '+256'},
US: {name: i18n._(msg`United States of America`), code: '+1'},
UY: {name: i18n._(msg`Uruguay`), code: '+598'},
UZ: {name: i18n._(msg`Uzbekistan`), code: '+998'},
VC: {name: i18n._(msg`Saint Vincent and the Grenadines`), code: '+1784'},
VE: {name: i18n._(msg`Venezuela (Bolivarian Republic of)`), code: '+58'},
VG: {name: i18n._(msg`Virgin Islands (British)`), code: '+1284'},
VI: {name: i18n._(msg`Virgin Islands (U.S.)`), code: '+1340'},
VN: {name: i18n._(msg`Vietnam`), code: '+84'},
VU: {name: i18n._(msg`Vanuatu`), code: '+678'},
WF: {name: i18n._(msg`Wallis and Futuna`), code: '+681'},
WS: {name: i18n._(msg`Samoa`), code: '+685'},
YE: {name: i18n._(msg`Yemen`), code: '+967'},
YT: {name: i18n._(msg`Mayotte`), code: '+262'},
ZA: {name: i18n._(msg`South Africa`), code: '+27'},
ZM: {name: i18n._(msg`Zambia`), code: '+260'},
ZW: {name: i18n._(msg`Zimbabwe`), code: '+263'},
SZ: {name: i18n._(msg`Eswatini`), code: '+268'},
MK: {name: i18n._(msg`North Macedonia`), code: '+389'},
PH: {name: i18n._(msg`Philippines`), code: '+63'},
NL: {name: i18n._(msg`Netherlands`), code: '+31'},
AE: {name: i18n._(msg`United Arab Emirates`), code: '+971'},
MD: {name: i18n._(msg`Republic of Moldova`), code: '+373'},
GM: {name: i18n._(msg`Gambia`), code: '+220'},
DO: {name: i18n._(msg`Dominican Republic`), code: '+1'},
SD: {name: i18n._(msg`Sudan`), code: '+249'},
LA: {name: i18n._(msg`Lao People's Democratic Republic`), code: '+856'},
TW: {name: i18n._(msg`Taiwan, Province of China`), code: '+886'},
CG: {name: i18n._(msg`Republic of the Congo`), code: '+242'},
CZ: {name: i18n._(msg`Czechia`), code: '+420'},
GB: {name: i18n._(msg`United Kingdom`), code: '+44'},
NE: {name: i18n._(msg`Niger`), code: '+227'},
CD: {name: i18n._(msg`Democratic Republic of the Congo`), code: '+243'},
BS: {name: i18n._(msg`Commonwealth of The Bahamas`), code: '+1 242'},
CC: {name: i18n._(msg`Cocos (Keeling) Islands`), code: '+61 891'},
CF: {name: i18n._(msg`Central African Republic`), code: '+236'},
CK: {name: i18n._(msg`Cook Islands`), code: '+682'},
FK: {name: i18n._(msg`Falkland Islands`), code: '+500'},
FO: {name: i18n._(msg`Faroe Islands`), code: '+298'},
HM: {
name: i18n._(msg`Territory of Heard Island and McDonald Islands`),
code: '+672',
},
KM: {name: i18n._(msg`Comoros`), code: '+269'},
KY: {name: i18n._(msg`Cayman Islands`), code: '+1 345'},
MH: {name: i18n._(msg`Republic of the Marshall Islands`), code: '+692'},
MP: {
name: i18n._(msg`Commonwealth of the Northern Mariana Islands`),
code: '+1 670',
},
TC: {name: i18n._(msg`Turks and Caicos Islands`), code: '+1 649'},
TF: {name: i18n._(msg`French Southern and Antarctic Lands`), code: '+672'},
UM: {name: i18n._(msg`United States Minor Outlying Islands`), code: '+1'},
VA: {name: i18n._(msg`Holy See`), code: '+39'},
XK: {name: i18n._(msg`Republic of Kosovo`), code: '+383'},
AN: {name: i18n._(msg`Netherlands Antilles`), code: '+599'},
}
}