/** * Viewport and scrolling utilities for NexusReader. * Avoids eval() usage, supports CSP, AOT-safety, and prevents memory leaks. */ export function isMobileViewport() { return window.innerWidth < 768; } export function registerViewportObserver(dotNetHelper) { let currentIsMobile = window.innerWidth < 768; const listener = () => { const isMobile = window.innerWidth < 768; if (isMobile !== currentIsMobile) { currentIsMobile = isMobile; dotNetHelper.invokeMethodAsync('OnViewportChanged', isMobile); } }; // Store listener directly on the JS object wrapper of the DotNetObjectReference for elegant cleanup dotNetHelper._viewportListener = listener; window.addEventListener('resize', listener); } export function unregisterViewportObserver(dotNetHelper) { if (dotNetHelper && dotNetHelper._viewportListener) { window.removeEventListener('resize', dotNetHelper._viewportListener); delete dotNetHelper._viewportListener; } } export function scrollIntoView(id) { const el = document.getElementById(id); if (el) { el.scrollIntoView({ behavior: 'smooth', block: 'center' }); return true; } return false; } // NOTE: Assumes the selector matches the active scroll container (default '.reader-canvas'). // Scoping is flexible to avoid issues if SSR pre-render or animated layouts render multiple wrappers. export function scrollToTop(selector = '.reader-canvas') { const el = document.querySelector(selector); if (el) { el.scrollTop = 0; return true; } return false; }