keyboard-controller-c05e747a.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*!
  2. * (C) Ionic http://ionicframework.com - MIT License
  3. */
  4. 'use strict';
  5. const index = require('./index-c8d52405.js');
  6. const keyboard = require('./keyboard-0272231f.js');
  7. /**
  8. * The element that resizes when the keyboard opens
  9. * is going to depend on the resize mode
  10. * which is why we check that here.
  11. */
  12. const getResizeContainer = (resizeMode) => {
  13. /**
  14. * If doc is undefined then we are
  15. * in an SSR environment, so the keyboard
  16. * adjustment does not apply.
  17. * If the webview does not resize then there
  18. * is no container to resize.
  19. */
  20. if (index.doc === undefined || resizeMode === keyboard.KeyboardResize.None || resizeMode === undefined) {
  21. return null;
  22. }
  23. /**
  24. * The three remaining resize modes: Native, Ionic, and Body
  25. * all cause `ion-app` to resize, so we can listen for changes
  26. * on that. In the event `ion-app` is not available then
  27. * we can fall back to `body`.
  28. */
  29. const ionApp = index.doc.querySelector('ion-app');
  30. return ionApp !== null && ionApp !== void 0 ? ionApp : index.doc.body;
  31. };
  32. /**
  33. * Get the height of ion-app or body.
  34. * This is used for determining if the webview
  35. * has resized before the keyboard closed.
  36. * */
  37. const getResizeContainerHeight = (resizeMode) => {
  38. const containerElement = getResizeContainer(resizeMode);
  39. return containerElement === null ? 0 : containerElement.clientHeight;
  40. };
  41. /**
  42. * Creates a controller that tracks and reacts to opening or closing the keyboard.
  43. *
  44. * @internal
  45. * @param keyboardChangeCallback A function to call when the keyboard opens or closes.
  46. */
  47. const createKeyboardController = async (keyboardChangeCallback) => {
  48. let keyboardWillShowHandler;
  49. let keyboardWillHideHandler;
  50. let keyboardVisible;
  51. /**
  52. * This lets us determine if the webview content
  53. * has resized as a result of the keyboard.
  54. */
  55. let initialResizeContainerHeight;
  56. const init = async () => {
  57. const resizeOptions = await keyboard.Keyboard.getResizeMode();
  58. const resizeMode = resizeOptions === undefined ? undefined : resizeOptions.mode;
  59. keyboardWillShowHandler = () => {
  60. /**
  61. * We need to compute initialResizeContainerHeight right before
  62. * the keyboard opens to guarantee the resize container is visible.
  63. * The resize container may not be visible if we compute this
  64. * as soon as the keyboard controller is created.
  65. * We should only need to do this once to avoid additional clientHeight
  66. * computations.
  67. */
  68. if (initialResizeContainerHeight === undefined) {
  69. initialResizeContainerHeight = getResizeContainerHeight(resizeMode);
  70. }
  71. keyboardVisible = true;
  72. fireChangeCallback(keyboardVisible, resizeMode);
  73. };
  74. keyboardWillHideHandler = () => {
  75. keyboardVisible = false;
  76. fireChangeCallback(keyboardVisible, resizeMode);
  77. };
  78. index.win === null || index.win === void 0 ? void 0 : index.win.addEventListener('keyboardWillShow', keyboardWillShowHandler);
  79. index.win === null || index.win === void 0 ? void 0 : index.win.addEventListener('keyboardWillHide', keyboardWillHideHandler);
  80. };
  81. const fireChangeCallback = (state, resizeMode) => {
  82. if (keyboardChangeCallback) {
  83. keyboardChangeCallback(state, createResizePromiseIfNeeded(resizeMode));
  84. }
  85. };
  86. /**
  87. * Code responding to keyboard lifecycles may need
  88. * to show/hide content once the webview has
  89. * resized as a result of the keyboard showing/hiding.
  90. * createResizePromiseIfNeeded provides a way for code to wait for the
  91. * resize event that was triggered as a result of the keyboard.
  92. */
  93. const createResizePromiseIfNeeded = (resizeMode) => {
  94. if (
  95. /**
  96. * If we are in an SSR environment then there is
  97. * no window to resize. Additionally, if there
  98. * is no resize mode or the resize mode is "None"
  99. * then initialResizeContainerHeight will be 0
  100. */
  101. initialResizeContainerHeight === 0 ||
  102. /**
  103. * If the keyboard is closed before the webview resizes initially
  104. * then the webview will never resize.
  105. */
  106. initialResizeContainerHeight === getResizeContainerHeight(resizeMode)) {
  107. return;
  108. }
  109. /**
  110. * Get the resize container so we can
  111. * attach the ResizeObserver below to
  112. * the correct element.
  113. */
  114. const containerElement = getResizeContainer(resizeMode);
  115. if (containerElement === null) {
  116. return;
  117. }
  118. /**
  119. * Some part of the web content should resize,
  120. * and we need to listen for a resize.
  121. */
  122. return new Promise((resolve) => {
  123. const callback = () => {
  124. /**
  125. * As per the spec, the ResizeObserver
  126. * will fire when observation starts if
  127. * the observed element is rendered and does not
  128. * have a size of 0 x 0. However, the watched element
  129. * may or may not have resized by the time this first
  130. * callback is fired. As a result, we need to check
  131. * the dimensions of the element.
  132. *
  133. * https://www.w3.org/TR/resize-observer/#intro
  134. */
  135. if (containerElement.clientHeight === initialResizeContainerHeight) {
  136. /**
  137. * The resize happened, so stop listening
  138. * for resize on this element.
  139. */
  140. ro.disconnect();
  141. resolve();
  142. }
  143. };
  144. /**
  145. * In Capacitor there can be delay between when the window
  146. * resizes and when the container element resizes, so we cannot
  147. * rely on a 'resize' event listener on the window.
  148. * Instead, we need to determine when the container
  149. * element resizes using a ResizeObserver.
  150. */
  151. const ro = new ResizeObserver(callback);
  152. ro.observe(containerElement);
  153. });
  154. };
  155. const destroy = () => {
  156. index.win === null || index.win === void 0 ? void 0 : index.win.removeEventListener('keyboardWillShow', keyboardWillShowHandler);
  157. index.win === null || index.win === void 0 ? void 0 : index.win.removeEventListener('keyboardWillHide', keyboardWillHideHandler);
  158. keyboardWillShowHandler = keyboardWillHideHandler = undefined;
  159. };
  160. const isKeyboardVisible = () => keyboardVisible;
  161. await init();
  162. return { init, destroy, isKeyboardVisible };
  163. };
  164. exports.createKeyboardController = createKeyboardController;