75 lines
2.2 KiB
JavaScript
75 lines
2.2 KiB
JavaScript
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 = '<div class="npm-no-results">No packages found</div>';
|
|
container.classList.remove('hidden');
|
|
return;
|
|
}
|
|
|
|
container.innerHTML = packages.map(p => {
|
|
const pkg = p.package;
|
|
const desc = (pkg.description || '').slice(0, 80);
|
|
return `<div class="npm-result" data-name="${esc(pkg.name)}" data-version="${esc(pkg.version)}">
|
|
<div class="npm-result-name">${esc(pkg.name)} <span class="npm-result-version">${esc(pkg.version)}</span></div>
|
|
<div class="npm-result-desc">${esc(desc)}</div>
|
|
</div>`;
|
|
}).join('');
|
|
|
|
container.querySelectorAll('.npm-result').forEach(el => {
|
|
el.addEventListener('click', () => {
|
|
const name = el.dataset.name;
|
|
const url = `https://esm.sh/${name}`;
|
|
onSelect({ name, url, type: 'js' });
|
|
input.value = '';
|
|
container.classList.add('hidden');
|
|
});
|
|
});
|
|
|
|
container.classList.remove('hidden');
|
|
} catch (_) {
|
|
container.classList.add('hidden');
|
|
}
|
|
}
|
|
|
|
function esc(str) {
|
|
const div = document.createElement('div');
|
|
div.textContent = str;
|
|
return div.innerHTML;
|
|
}
|