UNPKG

@ionic/core

Version:
166 lines (163 loc) 6.77 kB
/*! * (C) Ionic http://ionicframework.com - MIT License */ import { w as win, d as doc } from './index5.js'; import { K as Keyboard, a as KeyboardResize } from './keyboard.js'; /** * The element that resizes when the keyboard opens * is going to depend on the resize mode * which is why we check that here. */ const getResizeContainer = (resizeMode) => { /** * If doc is undefined then we are * in an SSR environment, so the keyboard * adjustment does not apply. * If the webview does not resize then there * is no container to resize. */ if (doc === undefined || resizeMode === KeyboardResize.None || resizeMode === undefined) { return null; } /** * The three remaining resize modes: Native, Ionic, and Body * all cause `ion-app` to resize, so we can listen for changes * on that. In the event `ion-app` is not available then * we can fall back to `body`. */ const ionApp = doc.querySelector('ion-app'); return ionApp !== null && ionApp !== void 0 ? ionApp : doc.body; }; /** * Get the height of ion-app or body. * This is used for determining if the webview * has resized before the keyboard closed. * */ const getResizeContainerHeight = (resizeMode) => { const containerElement = getResizeContainer(resizeMode); return containerElement === null ? 0 : containerElement.clientHeight; }; /** * Creates a controller that tracks and reacts to opening or closing the keyboard. * * @internal * @param keyboardChangeCallback A function to call when the keyboard opens or closes. */ const createKeyboardController = async (keyboardChangeCallback) => { let keyboardWillShowHandler; let keyboardWillHideHandler; let keyboardVisible; /** * This lets us determine if the webview content * has resized as a result of the keyboard. */ let initialResizeContainerHeight; const init = async () => { const resizeOptions = await Keyboard.getResizeMode(); const resizeMode = resizeOptions === undefined ? undefined : resizeOptions.mode; keyboardWillShowHandler = () => { /** * We need to compute initialResizeContainerHeight right before * the keyboard opens to guarantee the resize container is visible. * The resize container may not be visible if we compute this * as soon as the keyboard controller is created. * We should only need to do this once to avoid additional clientHeight * computations. */ if (initialResizeContainerHeight === undefined) { initialResizeContainerHeight = getResizeContainerHeight(resizeMode); } keyboardVisible = true; fireChangeCallback(keyboardVisible, resizeMode); }; keyboardWillHideHandler = () => { keyboardVisible = false; fireChangeCallback(keyboardVisible, resizeMode); }; win === null || win === void 0 ? void 0 : win.addEventListener('keyboardWillShow', keyboardWillShowHandler); win === null || win === void 0 ? void 0 : win.addEventListener('keyboardWillHide', keyboardWillHideHandler); }; const fireChangeCallback = (state, resizeMode) => { if (keyboardChangeCallback) { keyboardChangeCallback(state, createResizePromiseIfNeeded(resizeMode)); } }; /** * Code responding to keyboard lifecycles may need * to show/hide content once the webview has * resized as a result of the keyboard showing/hiding. * createResizePromiseIfNeeded provides a way for code to wait for the * resize event that was triggered as a result of the keyboard. */ const createResizePromiseIfNeeded = (resizeMode) => { if ( /** * If we are in an SSR environment then there is * no window to resize. Additionally, if there * is no resize mode or the resize mode is "None" * then initialResizeContainerHeight will be 0 */ initialResizeContainerHeight === 0 || /** * If the keyboard is closed before the webview resizes initially * then the webview will never resize. */ initialResizeContainerHeight === getResizeContainerHeight(resizeMode)) { return; } /** * Get the resize container so we can * attach the ResizeObserver below to * the correct element. */ const containerElement = getResizeContainer(resizeMode); if (containerElement === null) { return; } /** * Some part of the web content should resize, * and we need to listen for a resize. */ return new Promise((resolve) => { const callback = () => { /** * As per the spec, the ResizeObserver * will fire when observation starts if * the observed element is rendered and does not * have a size of 0 x 0. However, the watched element * may or may not have resized by the time this first * callback is fired. As a result, we need to check * the dimensions of the element. * * https://www.w3.org/TR/resize-observer/#intro */ if (containerElement.clientHeight === initialResizeContainerHeight) { /** * The resize happened, so stop listening * for resize on this element. */ ro.disconnect(); resolve(); } }; /** * In Capacitor there can be delay between when the window * resizes and when the container element resizes, so we cannot * rely on a 'resize' event listener on the window. * Instead, we need to determine when the container * element resizes using a ResizeObserver. */ const ro = new ResizeObserver(callback); ro.observe(containerElement); }); }; const destroy = () => { win === null || win === void 0 ? void 0 : win.removeEventListener('keyboardWillShow', keyboardWillShowHandler); win === null || win === void 0 ? void 0 : win.removeEventListener('keyboardWillHide', keyboardWillHideHandler); keyboardWillShowHandler = keyboardWillHideHandler = undefined; }; const isKeyboardVisible = () => keyboardVisible; await init(); return { init, destroy, isKeyboardVisible }; }; export { createKeyboardController as c };