// Icon sets management panel — list, upload, delete custom icon sets. import { el, mount, clear } from '../dom.js'; import { api } from '../api.js'; export function iconSetsPanel() { const root = el('div', { class: 'icon-sets-panel' }); async function refresh() { clear(root); let list = []; try { list = await api.get('/api/icon-sets'); } catch { root.appendChild(el('div', { class: 'muted' }, 'unavailable')); return; } for (const s of list) { const grid = el('div', { class: 'ip-grid' }, s.icons.map(f => el('div', { class: 'ip-icon' }, el('img', { src: `/api/icon-sets/${s.set}/${f}`, title: f }) ) ) ); const head = el('div', { class: 'isp-hd' }, el('b', {}, s.set), el('span', { class: 'muted' }, ` ${s.icons.length}`) ); if (!s.readonly) { const del = el('button', { class: 'ghost' }, 'Delete'); del.addEventListener('click', async () => { await api.del('/api/icon-sets/' + s.set); refresh(); }); head.appendChild(del); } root.appendChild(el('div', { class: 'isp-set' }, head, grid)); } root.appendChild(uploadForm(refresh)); } refresh(); return root; } function uploadForm(onDone) { const setI = el('input', { class: 'dv-edit-name', placeholder: 'new set name (a-z0-9-)' }); const fileI = el('input', { type: 'file', accept: '.svg,.png,.jpg,.jpeg,.zip', multiple: true }); const urlI = el('input', { class: 'dv-edit-name', placeholder: 'or ingest from URL (image or .zip)' }); const err = el('span', { class: 'muted', style: { fontSize: '11px' } }, ''); const up = el('button', { class: 'dv-add' }, 'Upload'); up.addEventListener('click', async () => { const set = setI.value.trim().toLowerCase(); if (!/^[a-z0-9-]+$/.test(set)) { err.textContent = 'set name: a-z 0-9 - only'; return; } if (!fileI.files.length && !urlI.value.trim()) { err.textContent = 'pick files or a URL'; return; } const fd = new FormData(); for (const f of fileI.files) fd.append('files', f); if (urlI.value.trim()) fd.append('url', urlI.value.trim()); up.textContent = 'Uploading…'; up.disabled = true; try { await api.postForm('/api/icon-sets/' + set, fd); onDone(); } catch { err.textContent = 'upload failed'; up.textContent = 'Upload'; up.disabled = false; } }); return el('div', { class: 'isp-upload' }, setI, fileI, urlI, up, err); }