(function (root, factory) { const exported = factory(); if (typeof module === 'object' && module.exports) module.exports = exported; else root.createMobileComposerViewport = exported; })(typeof self !== 'undefined' ? self : this, function () { return function createMobileComposerViewport(options) { const entries = options.entries || []; const viewport = options.viewport; const mediaQuery = options.mediaQuery; const documentRef = options.document || document; const schedule = options.schedule || (callback => requestAnimationFrame(callback)); let active = null; let started = false; function reveal() { if (!active) return; const focused = documentRef.activeElement; const target = active.focusWithin && active.workspace.contains(focused) ? focused : active.workspace; target.scrollIntoView({ block:active.focusWithin ? 'nearest' : 'end', inline:'nearest' }); } function applyGeometry() { if (!active || !viewport || !mediaQuery.matches) return; active.panel.style.setProperty('--composer-viewport-top', `${viewport.offsetTop || 0}px`); active.panel.style.setProperty('--composer-viewport-height', `${viewport.height}px`); reveal(); } function onViewportChange() { schedule(applyGeometry); } function activate(entry) { if (!viewport || !mediaQuery.matches) return; if (active === entry) { schedule(applyGeometry); return; } if (active) deactivate(active, false); active = entry; entry.scrollTop = entry.panel.scrollTop; entry.panel.classList?.add('composer-keyboard-active'); viewport.addEventListener('resize', onViewportChange); viewport.addEventListener('scroll', onViewportChange); applyGeometry(); } function deactivate(entry, restore = true) { if (active !== entry) return; viewport?.removeEventListener('resize', onViewportChange); viewport?.removeEventListener('scroll', onViewportChange); entry.panel.classList?.remove('composer-keyboard-active'); entry.panel.style.removeProperty('--composer-viewport-top'); entry.panel.style.removeProperty('--composer-viewport-height'); active = null; if (restore) schedule(() => { entry.panel.scrollTop = entry.scrollTop; }); } function bind(entry) { entry.onFocus = () => activate(entry); entry.onFocusOut = () => schedule(() => { if (!entry.workspace.contains(documentRef.activeElement)) deactivate(entry); }); entry.focusTarget = entry.focusWithin ? entry.workspace : entry.composer; entry.focusEvent = entry.focusWithin ? 'focusin' : 'focus'; entry.focusTarget.addEventListener(entry.focusEvent, entry.onFocus); entry.workspace.addEventListener('focusout', entry.onFocusOut); } function unbind(entry) { entry.focusTarget.removeEventListener(entry.focusEvent, entry.onFocus); entry.workspace.removeEventListener('focusout', entry.onFocusOut); } return { start() { if (started) return; started = true; entries.forEach(bind); }, close(panel) { const entry = entries.find(candidate => candidate.panel === panel); if (entry) deactivate(entry, false); }, stop() { if (!started) return; if (active) deactivate(active, false); entries.forEach(unbind); started = false; }, revealActive() { schedule(applyGeometry); }, }; }; });