Add version history, screenshots, embed generator, collections, npm search, format-on-save, and custom fonts
This commit is contained in:
74
public/js/npm-search.js
Normal file
74
public/js/npm-search.js
Normal file
@@ -0,0 +1,74 @@
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user