93 lines
3.1 KiB
JavaScript
93 lines
3.1 KiB
JavaScript
(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;
|
|
active.workspace.scrollIntoView({ block:'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.composer.addEventListener('focus', entry.onFocus);
|
|
entry.workspace.addEventListener('focusout', entry.onFocusOut);
|
|
}
|
|
|
|
function unbind(entry) {
|
|
entry.composer.removeEventListener('focus', 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);
|
|
},
|
|
};
|
|
};
|
|
});
|