/* AICAN MVP — Globe-icon language dropdown. Sits in the topbar next to the Upload button. Same shape as the main project's language-selector.tsx but using inline SVGs and design tokens. */ const LSIcon = ({ d, size = 16, viewBox = '0 0 24 24' }) => ( {typeof d === 'string' ? : d} ); const IconGlobe = (p) => }/>; const IconChevron = (p) => ; const IconCheck = (p) => ; const IconCloseLs = (p) => ; const IconSearchLs = (p) => }/>; const LanguageSelector = () => { const lang = useLanguage(); const [open, setOpen] = React.useState(false); const [search, setSearch] = React.useState(''); const [busy, setBusy] = React.useState(false); const wrapRef = React.useRef(null); React.useEffect(() => { const onClick = (e) => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(false); }; document.addEventListener('mousedown', onClick); return () => document.removeEventListener('mousedown', onClick); }, []); const filtered = !search ? window.SUPPORTED_LANGUAGES : window.SUPPORTED_LANGUAGES.filter(l => l.name.toLowerCase().includes(search.toLowerCase()) || l.nativeName.toLowerCase().includes(search.toLowerCase()) || l.code.toLowerCase().includes(search.toLowerCase())); const pick = async (l) => { setBusy(true); setOpen(false); setSearch(''); try { await window.AicanLang.setLanguage(l); } finally { setBusy(false); } }; return (
{open && (
{lang.t('Language')}
setSearch(e.target.value)} placeholder="Search languages..." />
{filtered.map((l) => { const active = lang.current.code === l.code; return ( ); })}
)}
); }; window.LanguageSelector = LanguageSelector;