UNPKG

@ionic/core

Version:
174 lines (173 loc) • 5.56 kB
import { LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE, LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE } from '../../components/nav/constants'; const iosTransitionAnimation = () => import('./ios.transition'); const mdTransitionAnimation = () => import('./md.transition'); export function transition(opts) { return new Promise((resolve, reject) => { opts.queue.write(() => { beforeTransition(opts); runTransition(opts).then(result => { if (result.animation) { result.animation.destroy(); } afterTransition(opts); resolve(result); }, error => { afterTransition(opts); reject(error); }); }); }); } function beforeTransition(opts) { const enteringEl = opts.enteringEl; const leavingEl = opts.leavingEl; setZIndex(enteringEl, leavingEl, opts.direction); if (opts.showGoBack) { enteringEl.classList.add('can-go-back'); } else { enteringEl.classList.remove('can-go-back'); } setPageHidden(enteringEl, false); if (leavingEl) { setPageHidden(leavingEl, false); } } async function runTransition(opts) { const animationBuilder = await getAnimationBuilder(opts); const ani = (animationBuilder) ? animation(animationBuilder, opts) : noAnimation(opts); return ani; } function afterTransition(opts) { const enteringEl = opts.enteringEl; const leavingEl = opts.leavingEl; enteringEl.classList.remove('ion-page-invisible'); if (leavingEl !== undefined) { leavingEl.classList.remove('ion-page-invisible'); } } async function getAnimationBuilder(opts) { if (!opts.leavingEl || !opts.animated || opts.duration === 0) { return undefined; } if (opts.animationBuilder) { return opts.animationBuilder; } const builder = (opts.mode === 'ios') ? (await iosTransitionAnimation()).iosTransitionAnimation : (await mdTransitionAnimation()).mdTransitionAnimation; return builder; } async function animation(animationBuilder, opts) { await waitForReady(opts, true); const trans = await import('../animation').then(mod => mod.create(animationBuilder, opts.baseEl, opts)); fireWillEvents(opts.enteringEl, opts.leavingEl); await playTransition(trans, opts); if (opts.progressCallback) { opts.progressCallback(undefined); } if (trans.hasCompleted) { fireDidEvents(opts.enteringEl, opts.leavingEl); } return { hasCompleted: trans.hasCompleted, animation: trans }; } async function noAnimation(opts) { const enteringEl = opts.enteringEl; const leavingEl = opts.leavingEl; await waitForReady(opts, false); fireWillEvents(enteringEl, leavingEl); fireDidEvents(enteringEl, leavingEl); return { hasCompleted: true }; } async function waitForReady(opts, defaultDeep) { const deep = opts.deepWait !== undefined ? opts.deepWait : defaultDeep; const promises = deep ? [ deepReady(opts.enteringEl), deepReady(opts.leavingEl), ] : [ shallowReady(opts.enteringEl), shallowReady(opts.leavingEl), ]; await Promise.all(promises); await notifyViewReady(opts.viewIsReady, opts.enteringEl); } async function notifyViewReady(viewIsReady, enteringEl) { if (viewIsReady) { await viewIsReady(enteringEl); } } function playTransition(trans, opts) { const progressCallback = opts.progressCallback; const promise = new Promise(resolve => trans.onFinish(resolve)); if (progressCallback) { trans.progressStart(); progressCallback(trans); } else { trans.play(); } return promise; } function fireWillEvents(enteringEl, leavingEl) { lifecycle(leavingEl, LIFECYCLE_WILL_LEAVE); lifecycle(enteringEl, LIFECYCLE_WILL_ENTER); } function fireDidEvents(enteringEl, leavingEl) { lifecycle(enteringEl, LIFECYCLE_DID_ENTER); lifecycle(leavingEl, LIFECYCLE_DID_LEAVE); } export function lifecycle(el, eventName) { if (el) { const ev = new CustomEvent(eventName, { bubbles: false, cancelable: false, }); el.dispatchEvent(ev); } } function shallowReady(el) { if (el && el.componentOnReady) { return el.componentOnReady(); } return Promise.resolve(); } export async function deepReady(el) { const element = el; if (element) { if (element.componentOnReady != null) { const stencilEl = await element.componentOnReady(); if (stencilEl != null) { return; } } await Promise.all(Array.from(element.children).map(deepReady)); } } export function setPageHidden(el, hidden) { if (hidden) { el.setAttribute('aria-hidden', 'true'); el.classList.add('ion-page-hidden'); } else { el.hidden = false; el.removeAttribute('aria-hidden'); el.classList.remove('ion-page-hidden'); } } function setZIndex(enteringEl, leavingEl, direction) { if (enteringEl !== undefined) { enteringEl.style.zIndex = (direction === 'back') ? '99' : '101'; } if (leavingEl !== undefined) { leavingEl.style.zIndex = '100'; } }