? = shortcuts
'; const blob = new Blob([html], {type:'text/html'}); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${c.name.replace(/[^a-zA-Z0-9]/g,'-')}.html`; a.click(); URL.revokeObjectURL(url); } function copyShareText() { const c = getActive(); if (!c) return; let txt = `${c.name} (${CANVAS_TYPES[c.type].name})\n${'='.repeat(40)}\n\n`; CANVAS_TYPES[c.type].sections.forEach(sec => { const items = c.sections[sec.id]||[]; txt += `${sec.title}:\n`; if (items.length === 0) txt += ' (empty)\n'; else items.forEach(i => txt += ` โ€ข ${i.text}\n`); txt += '\n'; }); navigator.clipboard.writeText(txt).then(() => alert('Copied to clipboard!')); } function importData() { const input = document.createElement('input'); input.type = 'file'; input.accept = '.json'; input.onchange = e => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = ev => { try { const data = JSON.parse(ev.target.result); if (Array.isArray(data)) { state.canvases = data; state.activeId = data.length > 0 ? data[0].id : null; save(); render(); alert(`Imported ${data.length} canvases!`); } } catch(e) { alert('Invalid JSON file'); } }; reader.readAsText(file); }; input.click(); } // ===================== KEYBOARD ===================== document.addEventListener('keydown', e => { if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA' || e.target.tagName === 'SELECT') { if (e.key === 'Escape') { e.target.blur(); if (state.modal) { state.modal = null; render(); } } return; } if (e.key === 'n' || e.key === 'N') { e.preventDefault(); showNewModal(); } if (e.key === '/') { e.preventDefault(); document.querySelector('.sidebar-search input')?.focus(); } if (e.key === '1') { state.view = 'canvas'; render(); } if (e.key === '2') { state.view = 'dashboard'; render(); } if (e.key === '3') { state.view = 'export'; render(); } if (e.key === 'd' || e.key === 'D') { e.preventDefault(); duplicateCanvas(); } if (e.key === 'e' || e.key === 'E') { e.preventDefault(); exportMarkdown(); } if (e.key === 'Escape') { if (state.modal) { state.modal = null; render(); } } if (e.key === '?') { alert('Keyboard Shortcuts:\n\nN = New canvas\n/ = Search\n1 = Canvas view\n2 = Dashboard\n3 = Export\nD = Duplicate\nE = Export Markdown\nEsc = Close modal\n\nIn cells: Enter = Add item'); } }); // ===================== INIT ===================== load(); seed(); render();