let debounceTimer = null; export function initNpmSearch(onSelect) { const input = document.getElementById('npm-search-input'); const results = document.getElementById('npm-search-results'); if (!input || !results) return; input.addEventListener('input', () => { clearTimeout(debounceTimer); const q = input.value.trim(); if (q.length < 2) { results.classList.add('hidden'); results.innerHTML = ''; return; } debounceTimer = setTimeout(() => searchNpm(q, results, input, onSelect), 300); }); input.addEventListener('keydown', (e) => { if (e.key === 'Escape') { results.classList.add('hidden'); } }); document.addEventListener('click', (e) => { if (!input.contains(e.target) && !results.contains(e.target)) { results.classList.add('hidden'); } }); } async function searchNpm(query, container, input, onSelect) { try { const res = await fetch(`https://registry.npmjs.org/-/v1/search?text=${encodeURIComponent(query)}&size=8`); if (!res.ok) return; const data = await res.json(); const packages = data.objects || []; if (!packages.length) { container.innerHTML = '