ion-router-outlet.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /*!
  2. * (C) Ionic http://ionicframework.com - MIT License
  3. */
  4. import { proxyCustomElement, HTMLElement, createEvent, h } from '@stencil/core/internal/client';
  5. import { g as getTimeGivenProgression } from './cubic-bezier.js';
  6. import { a as attachComponent, d as detachComponent } from './framework-delegate.js';
  7. import { s as shallowEqualStringMap, j as hasLazyBuild } from './helpers.js';
  8. import { c as createLockController } from './lock-controller.js';
  9. import { p as printIonError, c as config } from './index4.js';
  10. import { t as transition } from './index2.js';
  11. import { b as getIonMode } from './ionic-global.js';
  12. const routerOutletCss = ":host{left:0;right:0;top:0;bottom:0;position:absolute;contain:layout size style;z-index:0}";
  13. const IonRouterOutletStyle0 = routerOutletCss;
  14. const RouterOutlet = /*@__PURE__*/ proxyCustomElement(class RouterOutlet extends HTMLElement {
  15. constructor() {
  16. super();
  17. this.__registerHost();
  18. this.__attachShadow();
  19. this.ionNavWillLoad = createEvent(this, "ionNavWillLoad", 7);
  20. this.ionNavWillChange = createEvent(this, "ionNavWillChange", 3);
  21. this.ionNavDidChange = createEvent(this, "ionNavDidChange", 3);
  22. this.lockController = createLockController();
  23. this.gestureOrAnimationInProgress = false;
  24. this.mode = getIonMode(this);
  25. this.delegate = undefined;
  26. this.animated = true;
  27. this.animation = undefined;
  28. this.swipeHandler = undefined;
  29. }
  30. swipeHandlerChanged() {
  31. if (this.gesture) {
  32. this.gesture.enable(this.swipeHandler !== undefined);
  33. }
  34. }
  35. async connectedCallback() {
  36. const onStart = () => {
  37. this.gestureOrAnimationInProgress = true;
  38. if (this.swipeHandler) {
  39. this.swipeHandler.onStart();
  40. }
  41. };
  42. this.gesture = (await import('./swipe-back.js')).createSwipeBackGesture(this.el, () => !this.gestureOrAnimationInProgress && !!this.swipeHandler && this.swipeHandler.canStart(), () => onStart(), (step) => { var _a; return (_a = this.ani) === null || _a === void 0 ? void 0 : _a.progressStep(step); }, (shouldComplete, step, dur) => {
  43. if (this.ani) {
  44. this.ani.onFinish(() => {
  45. this.gestureOrAnimationInProgress = false;
  46. if (this.swipeHandler) {
  47. this.swipeHandler.onEnd(shouldComplete);
  48. }
  49. }, { oneTimeCallback: true });
  50. // Account for rounding errors in JS
  51. let newStepValue = shouldComplete ? -0.001 : 0.001;
  52. /**
  53. * Animation will be reversed here, so need to
  54. * reverse the easing curve as well
  55. *
  56. * Additionally, we need to account for the time relative
  57. * to the new easing curve, as `stepValue` is going to be given
  58. * in terms of a linear curve.
  59. */
  60. if (!shouldComplete) {
  61. this.ani.easing('cubic-bezier(1, 0, 0.68, 0.28)');
  62. newStepValue += getTimeGivenProgression([0, 0], [1, 0], [0.68, 0.28], [1, 1], step)[0];
  63. }
  64. else {
  65. newStepValue += getTimeGivenProgression([0, 0], [0.32, 0.72], [0, 1], [1, 1], step)[0];
  66. }
  67. this.ani.progressEnd(shouldComplete ? 1 : 0, newStepValue, dur);
  68. }
  69. else {
  70. this.gestureOrAnimationInProgress = false;
  71. }
  72. });
  73. this.swipeHandlerChanged();
  74. }
  75. componentWillLoad() {
  76. this.ionNavWillLoad.emit();
  77. }
  78. disconnectedCallback() {
  79. if (this.gesture) {
  80. this.gesture.destroy();
  81. this.gesture = undefined;
  82. }
  83. }
  84. /** @internal */
  85. async commit(enteringEl, leavingEl, opts) {
  86. const unlock = await this.lockController.lock();
  87. let changed = false;
  88. try {
  89. changed = await this.transition(enteringEl, leavingEl, opts);
  90. }
  91. catch (e) {
  92. printIonError('[ion-router-outlet] - Exception in commit:', e);
  93. }
  94. unlock();
  95. return changed;
  96. }
  97. /** @internal */
  98. async setRouteId(id, params, direction, animation) {
  99. const changed = await this.setRoot(id, params, {
  100. duration: direction === 'root' ? 0 : undefined,
  101. direction: direction === 'back' ? 'back' : 'forward',
  102. animationBuilder: animation,
  103. });
  104. return {
  105. changed,
  106. element: this.activeEl,
  107. };
  108. }
  109. /** @internal */
  110. async getRouteId() {
  111. const active = this.activeEl;
  112. return active
  113. ? {
  114. id: active.tagName,
  115. element: active,
  116. params: this.activeParams,
  117. }
  118. : undefined;
  119. }
  120. async setRoot(component, params, opts) {
  121. if (this.activeComponent === component && shallowEqualStringMap(params, this.activeParams)) {
  122. return false;
  123. }
  124. // attach entering view to DOM
  125. const leavingEl = this.activeEl;
  126. const enteringEl = await attachComponent(this.delegate, this.el, component, ['ion-page', 'ion-page-invisible'], params);
  127. this.activeComponent = component;
  128. this.activeEl = enteringEl;
  129. this.activeParams = params;
  130. // commit animation
  131. await this.commit(enteringEl, leavingEl, opts);
  132. await detachComponent(this.delegate, leavingEl);
  133. return true;
  134. }
  135. async transition(enteringEl, leavingEl, opts = {}) {
  136. if (leavingEl === enteringEl) {
  137. return false;
  138. }
  139. // emit nav will change event
  140. this.ionNavWillChange.emit();
  141. const { el, mode } = this;
  142. const animated = this.animated && config.getBoolean('animated', true);
  143. const animationBuilder = opts.animationBuilder || this.animation || config.get('navAnimation');
  144. await transition(Object.assign(Object.assign({ mode,
  145. animated,
  146. enteringEl,
  147. leavingEl, baseEl: el,
  148. /**
  149. * We need to wait for all Stencil components
  150. * to be ready only when using the lazy
  151. * loaded bundle.
  152. */
  153. deepWait: hasLazyBuild(el), progressCallback: opts.progressAnimation
  154. ? (ani) => {
  155. /**
  156. * Because this progress callback is called asynchronously
  157. * it is possible for the gesture to start and end before
  158. * the animation is ever set. In that scenario, we should
  159. * immediately call progressEnd so that the transition promise
  160. * resolves and the gesture does not get locked up.
  161. */
  162. if (ani !== undefined && !this.gestureOrAnimationInProgress) {
  163. this.gestureOrAnimationInProgress = true;
  164. ani.onFinish(() => {
  165. this.gestureOrAnimationInProgress = false;
  166. if (this.swipeHandler) {
  167. this.swipeHandler.onEnd(false);
  168. }
  169. }, { oneTimeCallback: true });
  170. /**
  171. * Playing animation to beginning
  172. * with a duration of 0 prevents
  173. * any flickering when the animation
  174. * is later cleaned up.
  175. */
  176. ani.progressEnd(0, 0, 0);
  177. }
  178. else {
  179. this.ani = ani;
  180. }
  181. }
  182. : undefined }, opts), { animationBuilder }));
  183. // emit nav changed event
  184. this.ionNavDidChange.emit();
  185. return true;
  186. }
  187. render() {
  188. return h("slot", { key: 'e34e02b5154172c8d5cdd187b6ea58119b6946eb' });
  189. }
  190. get el() { return this; }
  191. static get watchers() { return {
  192. "swipeHandler": ["swipeHandlerChanged"]
  193. }; }
  194. static get style() { return IonRouterOutletStyle0; }
  195. }, [1, "ion-router-outlet", {
  196. "mode": [1025],
  197. "delegate": [16],
  198. "animated": [4],
  199. "animation": [16],
  200. "swipeHandler": [16],
  201. "commit": [64],
  202. "setRouteId": [64],
  203. "getRouteId": [64]
  204. }, undefined, {
  205. "swipeHandler": ["swipeHandlerChanged"]
  206. }]);
  207. function defineCustomElement$1() {
  208. if (typeof customElements === "undefined") {
  209. return;
  210. }
  211. const components = ["ion-router-outlet"];
  212. components.forEach(tagName => { switch (tagName) {
  213. case "ion-router-outlet":
  214. if (!customElements.get(tagName)) {
  215. customElements.define(tagName, RouterOutlet);
  216. }
  217. break;
  218. } });
  219. }
  220. const IonRouterOutlet = RouterOutlet;
  221. const defineCustomElement = defineCustomElement$1;
  222. export { IonRouterOutlet, defineCustomElement };