// MNote UI 基础运行时:全局 portal 与 toast API。 (function initMnoteUiRuntime() { if (window.__mnoteUiRuntimeStarted) return; window.__mnoteUiRuntimeStarted = true; function ensurePortalRoot() { var root = document.getElementById('mnote-portal-root'); if (root instanceof HTMLElement) return root; root = document.createElement('div'); root.id = 'mnote-portal-root'; root.setAttribute('data-mnote-portal-root', 'true'); document.body.appendChild(root); return root; } function ensureToastRegion() { var root = ensurePortalRoot(); var region = root.querySelector('[data-mnote-toast-region="true"]'); if (region instanceof HTMLElement) return region; region = document.createElement('div'); region.className = 'mnote-toast-region'; region.setAttribute('data-mnote-toast-region', 'true'); region.setAttribute('role', 'status'); region.setAttribute('aria-live', 'polite'); root.appendChild(region); return region; } function toast(message, options) { var text = String(message || '').trim(); if (!text) return null; var config = options || {}; var kind = String(config.kind || config.type || 'info').trim() || 'info'; var timeoutMs = Number(config.timeoutMs || config.duration || 3200); if (!Number.isFinite(timeoutMs) || timeoutMs < 800) timeoutMs = 3200; var region = ensureToastRegion(); var item = document.createElement('div'); item.className = 'mnote-toast mnote-toast--' + kind; item.setAttribute('data-mnote-toast', 'true'); item.setAttribute('data-kind', kind); item.textContent = text; region.appendChild(item); requestAnimationFrame(function showToast() { item.classList.add('mnote-toast--visible'); }); window.setTimeout(function hideToast() { item.classList.remove('mnote-toast--visible'); window.setTimeout(function removeToast() { if (item.parentNode) item.parentNode.removeChild(item); }, 180); }, timeoutMs); return item; } window.mnote = window.mnote || {}; window.mnote.ensurePortalRoot = ensurePortalRoot; window.mnote.toast = toast; window.addEventListener('mnote:toast', function onMnoteToast(event) { var detail = event && event.detail ? event.detail : {}; toast(detail.message, detail); }); if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', ensurePortalRoot, { once: true }); } else { ensurePortalRoot(); } })();