UNPKG

6.72 kBJavaScriptView Raw
1import { writeTask, Build } from '@stencil/core/internal/client';
2import { c as componentOnReady } from './helpers.js';
3
4const LIFECYCLE_WILL_ENTER = 'ionViewWillEnter';
5const LIFECYCLE_DID_ENTER = 'ionViewDidEnter';
6const LIFECYCLE_WILL_LEAVE = 'ionViewWillLeave';
7const LIFECYCLE_DID_LEAVE = 'ionViewDidLeave';
8const LIFECYCLE_WILL_UNLOAD = 'ionViewWillUnload';
9
10const iosTransitionAnimation = () => import('./ios.transition.js');
11const mdTransitionAnimation = () => import('./md.transition.js');
12const transition = (opts) => {
13 return new Promise((resolve, reject) => {
14 writeTask(() => {
15 beforeTransition(opts);
16 runTransition(opts).then(result => {
17 if (result.animation) {
18 result.animation.destroy();
19 }
20 afterTransition(opts);
21 resolve(result);
22 }, error => {
23 afterTransition(opts);
24 reject(error);
25 });
26 });
27 });
28};
29const beforeTransition = (opts) => {
30 const enteringEl = opts.enteringEl;
31 const leavingEl = opts.leavingEl;
32 setZIndex(enteringEl, leavingEl, opts.direction);
33 if (opts.showGoBack) {
34 enteringEl.classList.add('can-go-back');
35 }
36 else {
37 enteringEl.classList.remove('can-go-back');
38 }
39 setPageHidden(enteringEl, false);
40 /**
41 * When transitioning, the page should not
42 * respond to click events. This resolves small
43 * issues like users double tapping the ion-back-button.
44 * These pointer events are removed in `afterTransition`.
45 */
46 enteringEl.style.setProperty('pointer-events', 'none');
47 if (leavingEl) {
48 setPageHidden(leavingEl, false);
49 leavingEl.style.setProperty('pointer-events', 'none');
50 }
51};
52const runTransition = async (opts) => {
53 const animationBuilder = await getAnimationBuilder(opts);
54 const ani = (animationBuilder && Build.isBrowser)
55 ? animation(animationBuilder, opts)
56 : noAnimation(opts); // fast path for no animation
57 return ani;
58};
59const afterTransition = (opts) => {
60 const enteringEl = opts.enteringEl;
61 const leavingEl = opts.leavingEl;
62 enteringEl.classList.remove('ion-page-invisible');
63 enteringEl.style.removeProperty('pointer-events');
64 if (leavingEl !== undefined) {
65 leavingEl.classList.remove('ion-page-invisible');
66 leavingEl.style.removeProperty('pointer-events');
67 }
68};
69const getAnimationBuilder = async (opts) => {
70 if (!opts.leavingEl || !opts.animated || opts.duration === 0) {
71 return undefined;
72 }
73 if (opts.animationBuilder) {
74 return opts.animationBuilder;
75 }
76 const getAnimation = (opts.mode === 'ios')
77 ? (await iosTransitionAnimation()).iosTransitionAnimation
78 : (await mdTransitionAnimation()).mdTransitionAnimation;
79 return getAnimation;
80};
81const animation = async (animationBuilder, opts) => {
82 await waitForReady(opts, true);
83 const trans = animationBuilder(opts.baseEl, opts);
84 fireWillEvents(opts.enteringEl, opts.leavingEl);
85 const didComplete = await playTransition(trans, opts);
86 if (opts.progressCallback) {
87 opts.progressCallback(undefined);
88 }
89 if (didComplete) {
90 fireDidEvents(opts.enteringEl, opts.leavingEl);
91 }
92 return {
93 hasCompleted: didComplete,
94 animation: trans
95 };
96};
97const noAnimation = async (opts) => {
98 const enteringEl = opts.enteringEl;
99 const leavingEl = opts.leavingEl;
100 await waitForReady(opts, false);
101 fireWillEvents(enteringEl, leavingEl);
102 fireDidEvents(enteringEl, leavingEl);
103 return {
104 hasCompleted: true
105 };
106};
107const waitForReady = async (opts, defaultDeep) => {
108 const deep = opts.deepWait !== undefined ? opts.deepWait : defaultDeep;
109 const promises = deep ? [
110 deepReady(opts.enteringEl),
111 deepReady(opts.leavingEl),
112 ] : [
113 shallowReady(opts.enteringEl),
114 shallowReady(opts.leavingEl),
115 ];
116 await Promise.all(promises);
117 await notifyViewReady(opts.viewIsReady, opts.enteringEl);
118};
119const notifyViewReady = async (viewIsReady, enteringEl) => {
120 if (viewIsReady) {
121 await viewIsReady(enteringEl);
122 }
123};
124const playTransition = (trans, opts) => {
125 const progressCallback = opts.progressCallback;
126 const promise = new Promise(resolve => {
127 trans.onFinish((currentStep) => resolve(currentStep === 1));
128 });
129 // cool, let's do this, start the transition
130 if (progressCallback) {
131 // this is a swipe to go back, just get the transition progress ready
132 // kick off the swipe animation start
133 trans.progressStart(true);
134 progressCallback(trans);
135 }
136 else {
137 // only the top level transition should actually start "play"
138 // kick it off and let it play through
139 // ******** DOM WRITE ****************
140 trans.play();
141 }
142 // create a callback for when the animation is done
143 return promise;
144};
145const fireWillEvents = (enteringEl, leavingEl) => {
146 lifecycle(leavingEl, LIFECYCLE_WILL_LEAVE);
147 lifecycle(enteringEl, LIFECYCLE_WILL_ENTER);
148};
149const fireDidEvents = (enteringEl, leavingEl) => {
150 lifecycle(enteringEl, LIFECYCLE_DID_ENTER);
151 lifecycle(leavingEl, LIFECYCLE_DID_LEAVE);
152};
153const lifecycle = (el, eventName) => {
154 if (el) {
155 const ev = new CustomEvent(eventName, {
156 bubbles: false,
157 cancelable: false,
158 });
159 el.dispatchEvent(ev);
160 }
161};
162const shallowReady = (el) => {
163 if (el) {
164 return new Promise(resolve => componentOnReady(el, resolve));
165 }
166 return Promise.resolve();
167};
168const deepReady = async (el) => {
169 const element = el;
170 if (element) {
171 if (element.componentOnReady != null) {
172 const stencilEl = await element.componentOnReady();
173 if (stencilEl != null) {
174 return;
175 }
176 }
177 await Promise.all(Array.from(element.children).map(deepReady));
178 }
179};
180const setPageHidden = (el, hidden) => {
181 if (hidden) {
182 el.setAttribute('aria-hidden', 'true');
183 el.classList.add('ion-page-hidden');
184 }
185 else {
186 el.hidden = false;
187 el.removeAttribute('aria-hidden');
188 el.classList.remove('ion-page-hidden');
189 }
190};
191const setZIndex = (enteringEl, leavingEl, direction) => {
192 if (enteringEl !== undefined) {
193 enteringEl.style.zIndex = (direction === 'back')
194 ? '99'
195 : '101';
196 }
197 if (leavingEl !== undefined) {
198 leavingEl.style.zIndex = '100';
199 }
200};
201const getIonPageElement = (element) => {
202 if (element.classList.contains('ion-page')) {
203 return element;
204 }
205 const ionPage = element.querySelector(':scope > .ion-page, :scope > ion-nav, :scope > ion-tabs');
206 if (ionPage) {
207 return ionPage;
208 }
209 // idk, return the original element so at least something animates and we don't have a null pointer
210 return element;
211};
212
213export { LIFECYCLE_WILL_ENTER as L, LIFECYCLE_DID_ENTER as a, LIFECYCLE_WILL_LEAVE as b, LIFECYCLE_DID_LEAVE as c, LIFECYCLE_WILL_UNLOAD as d, deepReady as e, getIonPageElement as g, lifecycle as l, setPageHidden as s, transition as t };