83 lines
2.5 KiB
JavaScript
83 lines
2.5 KiB
JavaScript
// 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();
|
|
},
|
|
};
|