/* 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 ( { setOpen(!open); setSearch(''); }} title={lang.t('Language')}> {lang.current.nativeName} {busy ? : } {open && ( {lang.t('Language')} setOpen(false)}> setSearch(e.target.value)} placeholder="Search languages..." /> {filtered.map((l) => { const active = lang.current.code === l.code; return ( pick(l)}> {l.nativeName} {l.name} {active && } ); })} )} ); }; window.LanguageSelector = LanguageSelector;