import { Box, InputAdornment, ListItem, ListItemIcon, ListItemText, Menu, MenuItem, TextField, Typography, } from '@mui/material'; import { useMemo, useRef, useState, type RefObject } from 'react'; import { ArrowDown2 } from 'iconsax-react'; import ReactCountryFlag from 'react-country-flag'; import { useTranslation } from 'react-i18next'; import { countries, type Country } from '@/data/countries'; interface CountryCodeSelectorProps { show: boolean; value: string; onChange: (newValue: string) => void; menuAnchor: HTMLElement | null; onCloseFocusRef: RefObject; } /** * An animated country code adornment that fades and slides into view. * Its visibility is controlled by the `show` prop. */ export function CountryCodeSelector({ show, value, onChange, menuAnchor, onCloseFocusRef, }: CountryCodeSelectorProps) { const [anchorEl, setAnchorEl] = useState(null); const [searchTerm, setSearchTerm] = useState(''); const open = Boolean(anchorEl); const searchInputRef = useRef(null); const menuWidth = menuAnchor ? menuAnchor.clientWidth : 'auto'; const { t, i18n } = useTranslation(); const selectedCountry = countries.find((c) => c.phone === value) || countries[0]; const handleClick = () => { setAnchorEl(menuAnchor); }; const handleClose = () => { setTimeout(() => { setAnchorEl(null); }, 0); setTimeout(() => { onCloseFocusRef.current?.focus(); }, 100); setSearchTerm(''); // Reset search on close }; const handleSelect = (country: Country) => { onChange(country.phone); handleClose(); }; const handleMenuEntered = () => { // Focus the input field after the menu has finished opening searchInputRef.current?.focus(); }; const filteredCountries = useMemo( () => countries.filter( (country) => t(country.label).toLowerCase().includes(searchTerm.toLowerCase()) || country.label.toLowerCase().includes(searchTerm.toLowerCase()) || country.phone.includes(searchTerm), ), [searchTerm, t], ); return ( theme.transitions.create(['width', 'opacity'], { duration: theme.transitions.duration.standard, }), // Prevent content from wrapping or spilling out during animation overflow: 'hidden', whiteSpace: 'nowrap', // layout styles height: '100%', display: 'flex', alignItems: 'center', gap: 0.25, pl: show ? 0.25 : 0, '&:hover': { cursor: 'pointer', }, }} > {/* This inner Box prevents the content from being squeezed during the transition */} {value} setSearchTerm(e.target.value)} /> {/* Can improve preformance with using virtual scrolling */} {filteredCountries.length === 0 ? ( {t('messages.noResualtFound')} ) : ( filteredCountries.map((country) => ( handleSelect(country)} > {country.phone} )) )} {/* virtual scrolling */} {/* ( {t('messages.noResultFound')} ), }} initialTopMostItemIndex={countries.indexOf(selectedCountry)} itemContent={(_, country) => ( handleSelect(country)} > {country.phone} )} /> */} ); }