Created
January 22, 2025 20:02
-
-
Save a-c-m/36ebd796fe146c7147c6da927cb8f7bc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Box, TextField, Autocomplete } from '@mui/material'; | |
interface CountryType { | |
code: string; | |
label: string; | |
search?: string; | |
} | |
interface CountrySelectProps { | |
value?: CountryType | null; | |
onChange: (value: CountryType | null) => void; | |
disabled?: boolean; | |
error?: boolean; | |
helperText?: string; | |
required?: boolean; | |
} | |
// Filtered list without phone numbers | |
export const countries: CountryType[] = [ | |
// most common at the top | |
{ code: 'US', label: 'USA', search: 'USA U.S.A. America United States' }, // should be United States, but is USA | |
{ code: 'GB', label: 'United Kingdom', search: 'UK England Scotland Wales Great Britain' }, | |
{ code: 'CA', label: 'Canada' }, | |
{ code: 'FR', label: 'France' }, | |
{ code: 'ES', label: 'Spain' }, | |
{ code: 'DE', label: 'Germany' }, | |
{ code: 'MX', label: 'Mexico' }, | |
// the rest code sorted | |
{ code: 'AD', label: 'Andorra' }, | |
{ code: 'AE', label: 'United Arab Emirates' }, | |
{ code: 'AF', label: 'Afghanistan' }, | |
{ code: 'AG', label: 'Antigua and Barbuda' }, | |
{ code: 'AI', label: 'Anguilla' }, | |
{ code: 'AL', label: 'Albania' }, | |
{ code: 'AM', label: 'Armenia' }, | |
{ code: 'AO', label: 'Angola' }, | |
{ code: 'AQ', label: 'Antarctica' }, | |
{ code: 'AR', label: 'Argentina' }, | |
{ code: 'AS', label: 'American Samoa' }, | |
{ code: 'AT', label: 'Austria' }, | |
{ code: 'AU', label: 'Australia' }, | |
{ code: 'AW', label: 'Aruba' }, | |
{ code: 'AX', label: 'Alland Islands' }, | |
{ code: 'AZ', label: 'Azerbaijan' }, | |
{ code: 'BA', label: 'Bosnia and Herzegovina' }, | |
{ code: 'BB', label: 'Barbados' }, | |
{ code: 'BD', label: 'Bangladesh' }, | |
{ code: 'BE', label: 'Belgium' }, | |
{ code: 'BF', label: 'Burkina Faso' }, | |
{ code: 'BG', label: 'Bulgaria' }, | |
{ code: 'BH', label: 'Bahrain' }, | |
{ code: 'BI', label: 'Burundi' }, | |
{ code: 'BJ', label: 'Benin' }, | |
{ code: 'BL', label: 'Saint Barthelemy' }, | |
{ code: 'BM', label: 'Bermuda' }, | |
{ code: 'BN', label: 'Brunei Darussalam' }, | |
{ code: 'BO', label: 'Bolivia' }, | |
{ code: 'BR', label: 'Brazil' }, | |
{ code: 'BS', label: 'Bahamas' }, | |
{ code: 'BT', label: 'Bhutan' }, | |
{ code: 'BV', label: 'Bouvet Island' }, | |
{ code: 'BW', label: 'Botswana' }, | |
{ code: 'BY', label: 'Belarus' }, | |
{ code: 'BZ', label: 'Belize' }, | |
{ code: 'CC', label: 'Cocos (Keeling) Islands' }, | |
{ code: 'CD', label: 'Congo, Democratic Republic of the' }, | |
{ | |
code: 'CF', | |
label: 'Central African Republic', | |
}, | |
{ | |
code: 'CG', | |
label: 'Congo, Republic of the', | |
}, | |
{ code: 'CH', label: 'Switzerland' }, | |
{ code: 'CI', label: "Cote d'Ivoire" }, | |
{ code: 'CK', label: 'Cook Islands' }, | |
{ code: 'CL', label: 'Chile' }, | |
{ code: 'CM', label: 'Cameroon' }, | |
{ code: 'CN', label: 'China' }, | |
{ code: 'CO', label: 'Colombia' }, | |
{ code: 'CR', label: 'Costa Rica' }, | |
{ code: 'CU', label: 'Cuba' }, | |
{ code: 'CV', label: 'Cape Verde' }, | |
{ code: 'CW', label: 'Curacao' }, | |
{ code: 'CX', label: 'Christmas Island' }, | |
{ code: 'CY', label: 'Cyprus' }, | |
{ code: 'CZ', label: 'Czech Republic' }, | |
{ code: 'DJ', label: 'Djibouti' }, | |
{ code: 'DK', label: 'Denmark' }, | |
{ code: 'DM', label: 'Dominica' }, | |
{ | |
code: 'DO', | |
label: 'Dominican Republic', | |
}, | |
{ code: 'DZ', label: 'Algeria' }, | |
{ code: 'EC', label: 'Ecuador' }, | |
{ code: 'EE', label: 'Estonia' }, | |
{ code: 'EG', label: 'Egypt' }, | |
{ code: 'EH', label: 'Western Sahara' }, | |
{ code: 'ER', label: 'Eritrea' }, | |
{ code: 'ET', label: 'Ethiopia' }, | |
{ code: 'FI', label: 'Finland' }, | |
{ code: 'FJ', label: 'Fiji' }, | |
{ | |
code: 'FK', | |
label: 'Falkland Islands (Malvinas)', | |
}, | |
{ | |
code: 'FM', | |
label: 'Micronesia, Federated States of', | |
}, | |
{ code: 'FO', label: 'Faroe Islands' }, | |
{ code: 'GA', label: 'Gabon' }, | |
{ code: 'GD', label: 'Grenada' }, | |
{ code: 'GE', label: 'Georgia' }, | |
{ code: 'GF', label: 'French Guiana' }, | |
{ code: 'GG', label: 'Guernsey' }, | |
{ code: 'GH', label: 'Ghana' }, | |
{ code: 'GI', label: 'Gibraltar' }, | |
{ code: 'GL', label: 'Greenland' }, | |
{ code: 'GM', label: 'Gambia' }, | |
{ code: 'GN', label: 'Guinea' }, | |
{ code: 'GP', label: 'Guadeloupe' }, | |
{ code: 'GQ', label: 'Equatorial Guinea' }, | |
{ code: 'GR', label: 'Greece' }, | |
{ | |
code: 'GS', | |
label: 'South Georgia and the South Sandwich Islands', | |
}, | |
{ code: 'GT', label: 'Guatemala' }, | |
{ code: 'GU', label: 'Guam' }, | |
{ code: 'GW', label: 'Guinea-Bissau' }, | |
{ code: 'GY', label: 'Guyana' }, | |
{ code: 'HK', label: 'Hong Kong' }, | |
{ | |
code: 'HM', | |
label: 'Heard Island and McDonald Islands', | |
}, | |
{ code: 'HN', label: 'Honduras' }, | |
{ code: 'HR', label: 'Croatia' }, | |
{ code: 'HT', label: 'Haiti' }, | |
{ code: 'HU', label: 'Hungary' }, | |
{ code: 'ID', label: 'Indonesia' }, | |
{ code: 'IE', label: 'Ireland' }, | |
{ code: 'IL', label: 'Israel' }, | |
{ code: 'IM', label: 'Isle of Man' }, | |
{ code: 'IN', label: 'India' }, | |
{ | |
code: 'IO', | |
label: 'British Indian Ocean Territory', | |
}, | |
{ code: 'IQ', label: 'Iraq' }, | |
{ | |
code: 'IR', | |
label: 'Iran, Islamic Republic of', | |
}, | |
{ code: 'IS', label: 'Iceland' }, | |
{ code: 'IT', label: 'Italy' }, | |
{ code: 'JE', label: 'Jersey' }, | |
{ code: 'JM', label: 'Jamaica' }, | |
{ code: 'JO', label: 'Jordan' }, | |
{ | |
code: 'JP', | |
label: 'Japan', | |
}, | |
{ code: 'KE', label: 'Kenya' }, | |
{ code: 'KG', label: 'Kyrgyzstan' }, | |
{ code: 'KH', label: 'Cambodia' }, | |
{ code: 'KI', label: 'Kiribati' }, | |
{ code: 'KM', label: 'Comoros' }, | |
{ | |
code: 'KN', | |
label: 'Saint Kitts and Nevis', | |
}, | |
{ | |
code: 'KP', | |
label: "Korea, Democratic People's Republic of", | |
}, | |
{ code: 'KR', label: 'Korea, Republic of' }, | |
{ code: 'KW', label: 'Kuwait' }, | |
{ code: 'KY', label: 'Cayman Islands' }, | |
{ code: 'KZ', label: 'Kazakhstan' }, | |
{ | |
code: 'LA', | |
label: "Lao People's Democratic Republic", | |
}, | |
{ code: 'LB', label: 'Lebanon' }, | |
{ code: 'LC', label: 'Saint Lucia' }, | |
{ code: 'LI', label: 'Liechtenstein' }, | |
{ code: 'LK', label: 'Sri Lanka' }, | |
{ code: 'LR', label: 'Liberia' }, | |
{ code: 'LS', label: 'Lesotho' }, | |
{ code: 'LT', label: 'Lithuania' }, | |
{ code: 'LU', label: 'Luxembourg' }, | |
{ code: 'LV', label: 'Latvia' }, | |
{ code: 'LY', label: 'Libya' }, | |
{ code: 'MA', label: 'Morocco' }, | |
{ code: 'MC', label: 'Monaco' }, | |
{ | |
code: 'MD', | |
label: 'Moldova, Republic of', | |
}, | |
{ code: 'ME', label: 'Montenegro' }, | |
{ | |
code: 'MF', | |
label: 'Saint Martin (French part)', | |
}, | |
{ code: 'MG', label: 'Madagascar' }, | |
{ code: 'MH', label: 'Marshall Islands' }, | |
{ | |
code: 'MK', | |
label: 'Macedonia, the Former Yugoslav Republic of', | |
}, | |
{ code: 'ML', label: 'Mali' }, | |
{ code: 'MM', label: 'Myanmar' }, | |
{ code: 'MN', label: 'Mongolia' }, | |
{ code: 'MO', label: 'Macao' }, | |
{ | |
code: 'MP', | |
label: 'Northern Mariana Islands', | |
}, | |
{ code: 'MQ', label: 'Martinique' }, | |
{ code: 'MR', label: 'Mauritania' }, | |
{ code: 'MS', label: 'Montserrat' }, | |
{ code: 'MT', label: 'Malta' }, | |
{ code: 'MU', label: 'Mauritius' }, | |
{ code: 'MV', label: 'Maldives' }, | |
{ code: 'MW', label: 'Malawi' }, | |
{ code: 'MY', label: 'Malaysia' }, | |
{ code: 'MZ', label: 'Mozambique' }, | |
{ code: 'NA', label: 'Namibia' }, | |
{ code: 'NC', label: 'New Caledonia' }, | |
{ code: 'NE', label: 'Niger' }, | |
{ code: 'NF', label: 'Norfolk Island' }, | |
{ code: 'NG', label: 'Nigeria' }, | |
{ code: 'NI', label: 'Nicaragua' }, | |
{ code: 'NL', label: 'Netherlands' }, | |
{ code: 'NO', label: 'Norway' }, | |
{ code: 'NP', label: 'Nepal' }, | |
{ code: 'NR', label: 'Nauru' }, | |
{ code: 'NU', label: 'Niue' }, | |
{ code: 'NZ', label: 'New Zealand' }, | |
{ code: 'OM', label: 'Oman' }, | |
{ code: 'PA', label: 'Panama' }, | |
{ code: 'PE', label: 'Peru' }, | |
{ code: 'PF', label: 'French Polynesia' }, | |
{ code: 'PG', label: 'Papua New Guinea' }, | |
{ code: 'PH', label: 'Philippines' }, | |
{ code: 'PK', label: 'Pakistan' }, | |
{ code: 'PL', label: 'Poland' }, | |
{ | |
code: 'PM', | |
label: 'Saint Pierre and Miquelon', | |
}, | |
{ code: 'PN', label: 'Pitcairn' }, | |
{ code: 'PR', label: 'Puerto Rico' }, | |
{ | |
code: 'PS', | |
label: 'Palestine, State of', | |
}, | |
{ code: 'PT', label: 'Portugal' }, | |
{ code: 'PW', label: 'Palau' }, | |
{ code: 'PY', label: 'Paraguay' }, | |
{ code: 'QA', label: 'Qatar' }, | |
{ code: 'RE', label: 'Reunion' }, | |
{ code: 'RO', label: 'Romania' }, | |
{ code: 'RS', label: 'Serbia' }, | |
{ code: 'RU', label: 'Russian Federation' }, | |
{ code: 'RW', label: 'Rwanda' }, | |
{ code: 'SA', label: 'Saudi Arabia' }, | |
{ code: 'SB', label: 'Solomon Islands' }, | |
{ code: 'SC', label: 'Seychelles' }, | |
{ code: 'SD', label: 'Sudan' }, | |
{ code: 'SE', label: 'Sweden' }, | |
{ code: 'SG', label: 'Singapore' }, | |
{ code: 'SH', label: 'Saint Helena' }, | |
{ code: 'SI', label: 'Slovenia' }, | |
{ | |
code: 'SJ', | |
label: 'Svalbard and Jan Mayen', | |
}, | |
{ code: 'SK', label: 'Slovakia' }, | |
{ code: 'SL', label: 'Sierra Leone' }, | |
{ code: 'SM', label: 'San Marino' }, | |
{ code: 'SN', label: 'Senegal' }, | |
{ code: 'SO', label: 'Somalia' }, | |
{ code: 'SR', label: 'Suriname' }, | |
{ code: 'SS', label: 'South Sudan' }, | |
{ | |
code: 'ST', | |
label: 'Sao Tome and Principe', | |
}, | |
{ code: 'SV', label: 'El Salvador' }, | |
{ | |
code: 'SX', | |
label: 'Sint Maarten (Dutch part)', | |
}, | |
{ | |
code: 'SY', | |
label: 'Syrian Arab Republic', | |
}, | |
{ code: 'SZ', label: 'Swaziland' }, | |
{ | |
code: 'TC', | |
label: 'Turks and Caicos Islands', | |
}, | |
{ code: 'TD', label: 'Chad' }, | |
{ | |
code: 'TF', | |
label: 'French Southern Territories', | |
}, | |
{ code: 'TG', label: 'Togo' }, | |
{ code: 'TH', label: 'Thailand' }, | |
{ code: 'TJ', label: 'Tajikistan' }, | |
{ code: 'TK', label: 'Tokelau' }, | |
{ code: 'TL', label: 'Timor-Leste' }, | |
{ code: 'TM', label: 'Turkmenistan' }, | |
{ code: 'TN', label: 'Tunisia' }, | |
{ code: 'TO', label: 'Tonga' }, | |
{ code: 'TR', label: 'Turkey' }, | |
{ | |
code: 'TT', | |
label: 'Trinidad and Tobago', | |
}, | |
{ code: 'TV', label: 'Tuvalu' }, | |
{ | |
code: 'TW', | |
label: 'Taiwan', | |
}, | |
{ | |
code: 'TZ', | |
label: 'United Republic of Tanzania', | |
}, | |
{ code: 'UA', label: 'Ukraine' }, | |
{ code: 'UG', label: 'Uganda' }, | |
{ code: 'UY', label: 'Uruguay' }, | |
{ code: 'UZ', label: 'Uzbekistan' }, | |
{ | |
code: 'VA', | |
label: 'Holy See (Vatican City State)', | |
}, | |
{ | |
code: 'VC', | |
label: 'Saint Vincent and the Grenadines', | |
}, | |
{ code: 'VE', label: 'Venezuela' }, | |
{ | |
code: 'VG', | |
label: 'British Virgin Islands', | |
}, | |
{ | |
code: 'VI', | |
label: 'US Virgin Islands', | |
}, | |
{ code: 'VN', label: 'Vietnam' }, | |
{ code: 'VU', label: 'Vanuatu' }, | |
{ code: 'WF', label: 'Wallis and Futuna' }, | |
{ code: 'WS', label: 'Samoa' }, | |
{ code: 'XK', label: 'Kosovo' }, | |
{ code: 'YE', label: 'Yemen' }, | |
{ code: 'YT', label: 'Mayotte' }, | |
{ code: 'ZA', label: 'South Africa' }, | |
{ code: 'ZM', label: 'Zambia' }, | |
{ code: 'ZW', label: 'Zimbabwe' }, | |
]; | |
export function CountrySelect({ | |
value, | |
onChange, | |
disabled, | |
error, | |
helperText, | |
required, | |
}: CountrySelectProps) { | |
return ( | |
<Autocomplete | |
value={value} | |
onChange={(_, newValue) => onChange(newValue)} | |
options={countries} | |
disabled={disabled} | |
autoHighlight | |
size="small" | |
getOptionLabel={(option) => option.label.toUpperCase()} | |
isOptionEqualToValue={(option, selectedValue) => | |
option.code === selectedValue.code || | |
option.label.toLowerCase() === selectedValue.label.toLowerCase() | |
} | |
filterOptions={(options, { inputValue }) => { | |
const searchTerm = inputValue.toLowerCase(); | |
return options.filter( | |
(option) => | |
option.label.toLowerCase().includes(searchTerm) || | |
option.code.toLowerCase().includes(searchTerm) || | |
(option.search?.toLowerCase() ?? '').includes(searchTerm), | |
); | |
}} | |
renderOption={(props: React.HTMLAttributes<HTMLLIElement>, option) => ( | |
<Box component="li" sx={{ '& > img': { mr: 2, flexShrink: 0 } }} {...props}> | |
<img | |
loading="lazy" | |
width="20" | |
srcSet={`https://flagcdn.com/w40/${option.code.toLowerCase()}.png 2x`} | |
src={`https://flagcdn.com/w20/${option.code.toLowerCase()}.png`} | |
alt={`The flag of ${option.label}`} | |
/> | |
{option.label.toUpperCase()} ({option.code}) | |
</Box> | |
)} | |
renderInput={(params) => ( | |
<Box sx={{ position: 'relative' }}> | |
{value && ( | |
<img | |
loading="lazy" | |
width="20" | |
height="15" | |
style={{ | |
position: 'absolute', | |
left: 8, | |
top: '50%', | |
transform: 'translateY(-50%)', | |
zIndex: 1, | |
}} | |
srcSet={`https://flagcdn.com/w40/${value.code.toLowerCase()}.png 2x`} | |
src={`https://flagcdn.com/w20/${value.code.toLowerCase()}.png`} | |
alt={`The flag of ${value?.label}`} | |
/> | |
)} | |
<TextField | |
{...params} | |
label="Country" | |
required={required} | |
error={error} | |
helperText={helperText} | |
InputProps={{ | |
...params.InputProps, | |
sx: { | |
...(value && { | |
'& .MuiInputBase-input': { | |
paddingLeft: '32px !important', | |
}, | |
}), | |
}, | |
}} | |
/> | |
</Box> | |
)} | |
/> | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment