Split app.js into one script per feature; versioning covers every public file; README for the new features
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c1f4a220f9
commit
1564941ea5
20 files changed
+2297
-2275
No files matched your search
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
// ---- Bottom sheet (dialog on tablet/desktop). Body content is built by the caller from trusted/escaped HTML.
|
||||
function openSheet(title, sub, bodyHtml) {
|
||||
closeSheet();
|
||||
const el = document.createElement('div');
|
||||
el.id = 'sheet';
|
||||
el.innerHTML = `<div class="scrim"></div><div class="sheet" role="dialog" aria-modal="true" aria-label="${esc(title)}">
|
||||
<div class="grip"></div><h3>${esc(title)}</h3>${sub ? `<p class="sub">${esc(sub)}</p>` : ''}${bodyHtml}</div>`;
|
||||
document.body.appendChild(el);
|
||||
el.querySelector('.scrim').onclick = closeSheet;
|
||||
requestAnimationFrame(() => el.classList.add('on'));
|
||||
return el;
|
||||
}
|
||||
function closeSheet() { document.getElementById('sheet')?.remove(); }
|
||||
addEventListener('keydown', e => { if (e.key === 'Escape') closeSheet(); });
|
||||
|
||||
function actionSheet(title, sub, actions) {
|
||||
const el = openSheet(title, sub, `<div class="list">${actions.map((a, i) => `
|
||||
<button class="row ${a.danger ? 'dng' : ''}" data-i="${i}">${icon(a.icon)}<span class="grow"><b>${esc(a.label)}</b></span></button>`).join('')}</div>
|
||||
<div class="bar"><button class="btn ghost" id="sx" style="flex:1;justify-content:center">Cancel</button></div>`);
|
||||
el.querySelector('#sx').onclick = closeSheet;
|
||||
el.querySelectorAll('button.row').forEach(b => b.onclick = () => { closeSheet(); actions[b.dataset.i].run(); });
|
||||
}
|
||||
|
||||
function textSheet(title, label, okLabel, onOk, initial = '', validate) {
|
||||
const el = openSheet(title, '', `<form><label>${esc(label)}</label><input type="text" id="tv" autocapitalize="off" autocomplete="off" required value="${esc(initial)}">
|
||||
<div class="err" id="te" style="margin-top:6px"></div>
|
||||
<div class="bar"><button class="btn ghost" type="button" id="sx" style="flex:1;justify-content:center">Cancel</button>
|
||||
<button class="btn" style="flex:1;justify-content:center">${esc(okLabel)}</button></div></form>`);
|
||||
el.querySelector('#sx').onclick = closeSheet;
|
||||
el.querySelector('form').onsubmit = e => {
|
||||
e.preventDefault(); const v = el.querySelector('#tv').value.trim(); if (!v) return;
|
||||
const bad = validate && validate(v); if (bad) { el.querySelector('#te').textContent = bad; return; }
|
||||
closeSheet(); onOk(v);
|
||||
};
|
||||
setTimeout(() => { const t = el.querySelector('#tv'); t.focus(); const d = initial.lastIndexOf('.'); t.setSelectionRange(0, d > 0 ? d : initial.length); }, 50);
|
||||
}
|
||||
|
||||
function confirmSheet(title, sub, okLabel, onOk) {
|
||||
const el = openSheet(title, sub, `<div class="bar"><button class="btn ghost" id="sx" style="flex:1;justify-content:center">Cancel</button>
|
||||
<button class="btn" id="so" style="flex:1;justify-content:center;background:var(--danger);color:#fff">${esc(okLabel)}</button></div>`);
|
||||
el.querySelector('#sx').onclick = closeSheet;
|
||||
el.querySelector('#so').onclick = () => { closeSheet(); onOk(); };
|
||||
}
|
||||
Reference in new issue
Block a user