// Notepad app — simple text editor with localStorage persistence. const uid = () => Date.now().toString(36) + Math.random().toString(36).slice(2, 7); export default { id: 'notepad', title: 'Notepad', render(container, api) { const docId = uid(); const storageKey = `meridian:notepad:${docId}`; let renamed = false; let saveTimer = null; // Load saved content const saved = localStorage.getItem(storageKey); let docTitle = 'Untitled'; let content = saved !== null ? saved : ''; // Build UI const toolbar = document.createElement('div'); toolbar.className = 'app-toolbar'; const titleEl = document.createElement('span'); titleEl.className = 'doc-title'; titleEl.textContent = docTitle; titleEl.title = 'Click to rename'; titleEl.style.cursor = 'pointer'; titleEl.addEventListener('click', () => { const newName = prompt('Rename document:', titleEl.textContent); if (newName !== null && newName.trim()) { docTitle = newName.trim(); titleEl.textContent = docTitle; renamed = true; api.setTitle(docTitle); } }); const saveBtn = document.createElement('button'); saveBtn.className = 'btn-amber'; saveBtn.textContent = 'Save'; saveBtn.addEventListener('click', () => { saveContent(); saveBtn.textContent = 'Saved!'; setTimeout(() => { saveBtn.textContent = 'Save'; }, 1200); }); toolbar.appendChild(titleEl); toolbar.appendChild(saveBtn); const textarea = document.createElement('textarea'); textarea.value = content; const statusbar = document.createElement('div'); statusbar.className = 'app-status'; function updateCounts() { const text = textarea.value; const chars = text.length; const words = text.trim() === '' ? 0 : text.trim().split(/\s+/).length; statusbar.textContent = `${words} word${words !== 1 ? 's' : ''} · ${chars} character${chars !== 1 ? 's' : ''}`; } textarea.addEventListener('input', () => { updateCounts(); api.bus.emit('text:typed', { chars: textarea.value.length }); // Auto-save after 1s of inactivity clearTimeout(saveTimer); saveTimer = setTimeout(saveContent, 1000); }); function saveContent() { localStorage.setItem(storageKey, textarea.value); } container.style.cssText = 'height:100%;display:flex;flex-direction:column;'; container.appendChild(toolbar); container.appendChild(textarea); container.appendChild(statusbar); updateCounts(); }, };