1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | const index = require('./index-a0a08b2a.js');
|
6 | const ionicGlobal = require('./ionic-global-06f21c1a.js');
|
7 | const cubicBezier = require('./cubic-bezier-0b2ccc35.js');
|
8 | const helpers = require('./helpers-d381ec4d.js');
|
9 | const index$1 = require('./index-222357e4.js');
|
10 | const frameworkDelegate = require('./framework-delegate-45524d8c.js');
|
11 |
|
12 | const VIEW_STATE_NEW = 1;
|
13 | const VIEW_STATE_ATTACHED = 2;
|
14 | const VIEW_STATE_DESTROYED = 3;
|
15 | class ViewController {
|
16 | constructor(component, params) {
|
17 | this.component = component;
|
18 | this.params = params;
|
19 | this.state = VIEW_STATE_NEW;
|
20 | }
|
21 | async init(container) {
|
22 | this.state = VIEW_STATE_ATTACHED;
|
23 | if (!this.element) {
|
24 | const component = this.component;
|
25 | this.element = await frameworkDelegate.attachComponent(this.delegate, container, component, ['ion-page', 'ion-page-invisible'], this.params);
|
26 | }
|
27 | }
|
28 | |
29 |
|
30 |
|
31 | _destroy() {
|
32 | helpers.assert(this.state !== VIEW_STATE_DESTROYED, 'view state must be ATTACHED');
|
33 | const element = this.element;
|
34 | if (element) {
|
35 | if (this.delegate) {
|
36 | this.delegate.removeViewFromDom(element.parentElement, element);
|
37 | }
|
38 | else {
|
39 | element.remove();
|
40 | }
|
41 | }
|
42 | this.nav = undefined;
|
43 | this.state = VIEW_STATE_DESTROYED;
|
44 | }
|
45 | }
|
46 | const matches = (view, id, params) => {
|
47 | if (!view) {
|
48 | return false;
|
49 | }
|
50 | if (view.component !== id) {
|
51 | return false;
|
52 | }
|
53 | const currentParams = view.params;
|
54 | if (currentParams === params) {
|
55 | return true;
|
56 | }
|
57 | if (!currentParams && !params) {
|
58 | return true;
|
59 | }
|
60 | if (!currentParams || !params) {
|
61 | return false;
|
62 | }
|
63 | const keysA = Object.keys(currentParams);
|
64 | const keysB = Object.keys(params);
|
65 | if (keysA.length !== keysB.length) {
|
66 | return false;
|
67 | }
|
68 |
|
69 | for (const key of keysA) {
|
70 | if (currentParams[key] !== params[key]) {
|
71 | return false;
|
72 | }
|
73 | }
|
74 | return true;
|
75 | };
|
76 | const convertToView = (page, params) => {
|
77 | if (!page) {
|
78 | return null;
|
79 | }
|
80 | if (page instanceof ViewController) {
|
81 | return page;
|
82 | }
|
83 | return new ViewController(page, params);
|
84 | };
|
85 | const convertToViews = (pages) => {
|
86 | return pages.map(page => {
|
87 | if (page instanceof ViewController) {
|
88 | return page;
|
89 | }
|
90 | if ('component' in page) {
|
91 | |
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 | return convertToView(page.component, (page.componentProps === null) ? undefined : page.componentProps);
|
99 | }
|
100 | return convertToView(page, undefined);
|
101 | }).filter(v => v !== null);
|
102 | };
|
103 |
|
104 | const navCss = ":host{left:0;right:0;top:0;bottom:0;position:absolute;contain:layout size style;overflow:hidden;z-index:0}";
|
105 |
|
106 | const Nav = class {
|
107 | constructor(hostRef) {
|
108 | index.registerInstance(this, hostRef);
|
109 | this.ionNavWillLoad = index.createEvent(this, "ionNavWillLoad", 7);
|
110 | this.ionNavWillChange = index.createEvent(this, "ionNavWillChange", 3);
|
111 | this.ionNavDidChange = index.createEvent(this, "ionNavDidChange", 3);
|
112 | this.transInstr = [];
|
113 | this.animationEnabled = true;
|
114 | this.useRouter = false;
|
115 | this.isTransitioning = false;
|
116 | this.destroyed = false;
|
117 | this.views = [];
|
118 | |
119 |
|
120 |
|
121 | this.animated = true;
|
122 | }
|
123 | swipeGestureChanged() {
|
124 | if (this.gesture) {
|
125 | this.gesture.enable(this.swipeGesture === true);
|
126 | }
|
127 | }
|
128 | rootChanged() {
|
129 | if (this.root !== undefined) {
|
130 | if (!this.useRouter) {
|
131 | this.setRoot(this.root, this.rootParams);
|
132 | }
|
133 | }
|
134 | }
|
135 | componentWillLoad() {
|
136 | this.useRouter =
|
137 | !!document.querySelector('ion-router') &&
|
138 | !this.el.closest('[no-router]');
|
139 | if (this.swipeGesture === undefined) {
|
140 | const mode = ionicGlobal.getIonMode(this);
|
141 | this.swipeGesture = ionicGlobal.config.getBoolean('swipeBackEnabled', mode === 'ios');
|
142 | }
|
143 | this.ionNavWillLoad.emit();
|
144 | }
|
145 | async componentDidLoad() {
|
146 | this.rootChanged();
|
147 | this.gesture = (await Promise.resolve().then(function () { return require('./swipe-back-e654d7fd.js'); })).createSwipeBackGesture(this.el, this.canStart.bind(this), this.onStart.bind(this), this.onMove.bind(this), this.onEnd.bind(this));
|
148 | this.swipeGestureChanged();
|
149 | }
|
150 | disconnectedCallback() {
|
151 | for (const view of this.views) {
|
152 | index$1.lifecycle(view.element, index$1.LIFECYCLE_WILL_UNLOAD);
|
153 | view._destroy();
|
154 | }
|
155 | if (this.gesture) {
|
156 | this.gesture.destroy();
|
157 | this.gesture = undefined;
|
158 | }
|
159 |
|
160 | this.transInstr.length = this.views.length = 0;
|
161 | this.destroyed = true;
|
162 | }
|
163 | |
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 | push(component, componentProps, opts, done) {
|
174 | return this.queueTrns({
|
175 | insertStart: -1,
|
176 | insertViews: [{ component, componentProps }],
|
177 | opts
|
178 | }, done);
|
179 | }
|
180 | |
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 | insert(insertIndex, component, componentProps, opts, done) {
|
191 | return this.queueTrns({
|
192 | insertStart: insertIndex,
|
193 | insertViews: [{ component, componentProps }],
|
194 | opts
|
195 | }, done);
|
196 | }
|
197 | |
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 |
|
204 |
|
205 |
|
206 |
|
207 | insertPages(insertIndex, insertComponents, opts, done) {
|
208 | return this.queueTrns({
|
209 | insertStart: insertIndex,
|
210 | insertViews: insertComponents,
|
211 | opts
|
212 | }, done);
|
213 | }
|
214 | |
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 | pop(opts, done) {
|
222 | return this.queueTrns({
|
223 | removeStart: -1,
|
224 | removeCount: 1,
|
225 | opts
|
226 | }, done);
|
227 | }
|
228 | |
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 | popTo(indexOrViewCtrl, opts, done) {
|
236 | const tiConfig = {
|
237 | removeStart: -1,
|
238 | removeCount: -1,
|
239 | opts
|
240 | };
|
241 | if (typeof indexOrViewCtrl === 'object' && indexOrViewCtrl.component) {
|
242 | tiConfig.removeView = indexOrViewCtrl;
|
243 | tiConfig.removeStart = 1;
|
244 | }
|
245 | else if (typeof indexOrViewCtrl === 'number') {
|
246 | tiConfig.removeStart = indexOrViewCtrl + 1;
|
247 | }
|
248 | return this.queueTrns(tiConfig, done);
|
249 | }
|
250 | |
251 |
|
252 |
|
253 |
|
254 |
|
255 |
|
256 | popToRoot(opts, done) {
|
257 | return this.queueTrns({
|
258 | removeStart: 1,
|
259 | removeCount: -1,
|
260 | opts
|
261 | }, done);
|
262 | }
|
263 | |
264 |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 | removeIndex(startIndex, removeCount = 1, opts, done) {
|
272 | return this.queueTrns({
|
273 | removeStart: startIndex,
|
274 | removeCount,
|
275 | opts
|
276 | }, done);
|
277 | }
|
278 | |
279 |
|
280 |
|
281 |
|
282 |
|
283 |
|
284 |
|
285 |
|
286 | setRoot(component, componentProps, opts, done) {
|
287 | return this.setPages([{ component, componentProps }], opts, done);
|
288 | }
|
289 | |
290 |
|
291 |
|
292 |
|
293 |
|
294 |
|
295 |
|
296 |
|
297 |
|
298 |
|
299 | setPages(views, opts, done) {
|
300 | if (opts == null) {
|
301 | opts = {};
|
302 | }
|
303 |
|
304 | if (opts.animated !== true) {
|
305 | opts.animated = false;
|
306 | }
|
307 | return this.queueTrns({
|
308 | insertStart: 0,
|
309 | insertViews: views,
|
310 | removeStart: 0,
|
311 | removeCount: -1,
|
312 | opts
|
313 | }, done);
|
314 | }
|
315 |
|
316 | setRouteId(id, params, direction, animation) {
|
317 | const active = this.getActiveSync();
|
318 | if (matches(active, id, params)) {
|
319 | return Promise.resolve({
|
320 | changed: false,
|
321 | element: active.element
|
322 | });
|
323 | }
|
324 | let resolve;
|
325 | const promise = new Promise(r => (resolve = r));
|
326 | let finish;
|
327 | const commonOpts = {
|
328 | updateURL: false,
|
329 | viewIsReady: enteringEl => {
|
330 | let mark;
|
331 | const p = new Promise(r => (mark = r));
|
332 | resolve({
|
333 | changed: true,
|
334 | element: enteringEl,
|
335 | markVisible: async () => {
|
336 | mark();
|
337 | await finish;
|
338 | }
|
339 | });
|
340 | return p;
|
341 | }
|
342 | };
|
343 | if (direction === 'root') {
|
344 | finish = this.setRoot(id, params, commonOpts);
|
345 | }
|
346 | else {
|
347 | const viewController = this.views.find(v => matches(v, id, params));
|
348 | if (viewController) {
|
349 | finish = this.popTo(viewController, Object.assign(Object.assign({}, commonOpts), { direction: 'back', animationBuilder: animation }));
|
350 | }
|
351 | else if (direction === 'forward') {
|
352 | finish = this.push(id, params, Object.assign(Object.assign({}, commonOpts), { animationBuilder: animation }));
|
353 | }
|
354 | else if (direction === 'back') {
|
355 | finish = this.setRoot(id, params, Object.assign(Object.assign({}, commonOpts), { direction: 'back', animated: true, animationBuilder: animation }));
|
356 | }
|
357 | }
|
358 | return promise;
|
359 | }
|
360 |
|
361 | async getRouteId() {
|
362 | const active = this.getActiveSync();
|
363 | return active
|
364 | ? {
|
365 | id: active.element.tagName,
|
366 | params: active.params,
|
367 | element: active.element
|
368 | }
|
369 | : undefined;
|
370 | }
|
371 | |
372 |
|
373 |
|
374 | getActive() {
|
375 | return Promise.resolve(this.getActiveSync());
|
376 | }
|
377 | |
378 |
|
379 |
|
380 |
|
381 |
|
382 | getByIndex(index) {
|
383 | return Promise.resolve(this.views[index]);
|
384 | }
|
385 | |
386 |
|
387 |
|
388 |
|
389 |
|
390 | canGoBack(view) {
|
391 | return Promise.resolve(this.canGoBackSync(view));
|
392 | }
|
393 | |
394 |
|
395 |
|
396 |
|
397 |
|
398 | getPrevious(view) {
|
399 | return Promise.resolve(this.getPreviousSync(view));
|
400 | }
|
401 | getLength() {
|
402 | return this.views.length;
|
403 | }
|
404 | getActiveSync() {
|
405 | return this.views[this.views.length - 1];
|
406 | }
|
407 | canGoBackSync(view = this.getActiveSync()) {
|
408 | return !!(view && this.getPreviousSync(view));
|
409 | }
|
410 | getPreviousSync(view = this.getActiveSync()) {
|
411 | if (!view) {
|
412 | return undefined;
|
413 | }
|
414 | const views = this.views;
|
415 | const index = views.indexOf(view);
|
416 | return index > 0 ? views[index - 1] : undefined;
|
417 | }
|
418 |
|
419 |
|
420 |
|
421 |
|
422 |
|
423 |
|
424 |
|
425 |
|
426 |
|
427 |
|
428 | async queueTrns(ti, done) {
|
429 | if (this.isTransitioning && ti.opts != null && ti.opts.skipIfBusy) {
|
430 | return Promise.resolve(false);
|
431 | }
|
432 | const promise = new Promise((resolve, reject) => {
|
433 | ti.resolve = resolve;
|
434 | ti.reject = reject;
|
435 | });
|
436 | ti.done = done;
|
437 | |
438 |
|
439 |
|
440 |
|
441 |
|
442 |
|
443 | if (ti.opts && ti.opts.updateURL !== false && this.useRouter) {
|
444 | const router = document.querySelector('ion-router');
|
445 | if (router) {
|
446 | const canTransition = await router.canTransition();
|
447 | if (canTransition === false) {
|
448 | return Promise.resolve(false);
|
449 | }
|
450 | else if (typeof canTransition === 'string') {
|
451 | router.push(canTransition, ti.opts.direction || 'back');
|
452 | return Promise.resolve(false);
|
453 | }
|
454 | }
|
455 | }
|
456 |
|
457 | if (ti.insertViews && ti.insertViews.length === 0) {
|
458 | ti.insertViews = undefined;
|
459 | }
|
460 |
|
461 | this.transInstr.push(ti);
|
462 |
|
463 |
|
464 | this.nextTrns();
|
465 | return promise;
|
466 | }
|
467 | success(result, ti) {
|
468 | if (this.destroyed) {
|
469 | this.fireError('nav controller was destroyed', ti);
|
470 | return;
|
471 | }
|
472 | if (ti.done) {
|
473 | ti.done(result.hasCompleted, result.requiresTransition, result.enteringView, result.leavingView, result.direction);
|
474 | }
|
475 | ti.resolve(result.hasCompleted);
|
476 | if (ti.opts.updateURL !== false && this.useRouter) {
|
477 | const router = document.querySelector('ion-router');
|
478 | if (router) {
|
479 | const direction = result.direction === 'back' ? 'back' : 'forward';
|
480 | router.navChanged(direction);
|
481 | }
|
482 | }
|
483 | }
|
484 | failed(rejectReason, ti) {
|
485 | if (this.destroyed) {
|
486 | this.fireError('nav controller was destroyed', ti);
|
487 | return;
|
488 | }
|
489 | this.transInstr.length = 0;
|
490 | this.fireError(rejectReason, ti);
|
491 | }
|
492 | fireError(rejectReason, ti) {
|
493 | if (ti.done) {
|
494 | ti.done(false, false, rejectReason);
|
495 | }
|
496 | if (ti.reject && !this.destroyed) {
|
497 | ti.reject(rejectReason);
|
498 | }
|
499 | else {
|
500 | ti.resolve(false);
|
501 | }
|
502 | }
|
503 | nextTrns() {
|
504 |
|
505 |
|
506 | if (this.isTransitioning) {
|
507 | return false;
|
508 | }
|
509 |
|
510 |
|
511 | const ti = this.transInstr.shift();
|
512 | if (!ti) {
|
513 | return false;
|
514 | }
|
515 | this.runTransition(ti);
|
516 | return true;
|
517 | }
|
518 | async runTransition(ti) {
|
519 | try {
|
520 |
|
521 | this.ionNavWillChange.emit();
|
522 | this.isTransitioning = true;
|
523 | this.prepareTI(ti);
|
524 | const leavingView = this.getActiveSync();
|
525 | const enteringView = this.getEnteringView(ti, leavingView);
|
526 | if (!leavingView && !enteringView) {
|
527 | throw new Error('no views in the stack to be removed');
|
528 | }
|
529 | if (enteringView && enteringView.state === VIEW_STATE_NEW) {
|
530 | await enteringView.init(this.el);
|
531 | }
|
532 | this.postViewInit(enteringView, leavingView, ti);
|
533 |
|
534 | const requiresTransition = (ti.enteringRequiresTransition || ti.leavingRequiresTransition) &&
|
535 | enteringView !== leavingView;
|
536 | if (requiresTransition && ti.opts && leavingView) {
|
537 | const isBackDirection = ti.opts.direction === 'back';
|
538 | |
539 |
|
540 |
|
541 |
|
542 | if (isBackDirection) {
|
543 | ti.opts.animationBuilder = ti.opts.animationBuilder || (enteringView && enteringView.animationBuilder);
|
544 | }
|
545 | leavingView.animationBuilder = ti.opts.animationBuilder;
|
546 | }
|
547 | const result = requiresTransition
|
548 | ? await this.transition(enteringView, leavingView, ti)
|
549 | : {
|
550 |
|
551 |
|
552 |
|
553 |
|
554 | hasCompleted: true,
|
555 | requiresTransition: false
|
556 | };
|
557 | this.success(result, ti);
|
558 | this.ionNavDidChange.emit();
|
559 | }
|
560 | catch (rejectReason) {
|
561 | this.failed(rejectReason, ti);
|
562 | }
|
563 | this.isTransitioning = false;
|
564 | this.nextTrns();
|
565 | }
|
566 | prepareTI(ti) {
|
567 | const viewsLength = this.views.length;
|
568 | ti.opts = ti.opts || {};
|
569 | if (ti.opts.delegate === undefined) {
|
570 | ti.opts.delegate = this.delegate;
|
571 | }
|
572 | if (ti.removeView !== undefined) {
|
573 | helpers.assert(ti.removeStart !== undefined, 'removeView needs removeStart');
|
574 | helpers.assert(ti.removeCount !== undefined, 'removeView needs removeCount');
|
575 | const index = this.views.indexOf(ti.removeView);
|
576 | if (index < 0) {
|
577 | throw new Error('removeView was not found');
|
578 | }
|
579 | ti.removeStart += index;
|
580 | }
|
581 | if (ti.removeStart !== undefined) {
|
582 | if (ti.removeStart < 0) {
|
583 | ti.removeStart = viewsLength - 1;
|
584 | }
|
585 | if (ti.removeCount < 0) {
|
586 | ti.removeCount = viewsLength - ti.removeStart;
|
587 | }
|
588 | ti.leavingRequiresTransition =
|
589 | ti.removeCount > 0 && ti.removeStart + ti.removeCount === viewsLength;
|
590 | }
|
591 | if (ti.insertViews) {
|
592 |
|
593 |
|
594 | if (ti.insertStart < 0 || ti.insertStart > viewsLength) {
|
595 | ti.insertStart = viewsLength;
|
596 | }
|
597 | ti.enteringRequiresTransition = ti.insertStart === viewsLength;
|
598 | }
|
599 | const insertViews = ti.insertViews;
|
600 | if (!insertViews) {
|
601 | return;
|
602 | }
|
603 | helpers.assert(insertViews.length > 0, 'length can not be zero');
|
604 | const viewControllers = convertToViews(insertViews);
|
605 | if (viewControllers.length === 0) {
|
606 | throw new Error('invalid views to insert');
|
607 | }
|
608 |
|
609 | for (const view of viewControllers) {
|
610 | view.delegate = ti.opts.delegate;
|
611 | const nav = view.nav;
|
612 | if (nav && nav !== this) {
|
613 | throw new Error('inserted view was already inserted');
|
614 | }
|
615 | if (view.state === VIEW_STATE_DESTROYED) {
|
616 | throw new Error('inserted view was already destroyed');
|
617 | }
|
618 | }
|
619 | ti.insertViews = viewControllers;
|
620 | }
|
621 | getEnteringView(ti, leavingView) {
|
622 | const insertViews = ti.insertViews;
|
623 | if (insertViews !== undefined) {
|
624 |
|
625 |
|
626 | return insertViews[insertViews.length - 1];
|
627 | }
|
628 | const removeStart = ti.removeStart;
|
629 | if (removeStart !== undefined) {
|
630 | const views = this.views;
|
631 | const removeEnd = removeStart + ti.removeCount;
|
632 | for (let i = views.length - 1; i >= 0; i--) {
|
633 | const view = views[i];
|
634 | if ((i < removeStart || i >= removeEnd) && view !== leavingView) {
|
635 | return view;
|
636 | }
|
637 | }
|
638 | }
|
639 | return undefined;
|
640 | }
|
641 | postViewInit(enteringView, leavingView, ti) {
|
642 | helpers.assert(leavingView || enteringView, 'Both leavingView and enteringView are null');
|
643 | helpers.assert(ti.resolve, 'resolve must be valid');
|
644 | helpers.assert(ti.reject, 'reject must be valid');
|
645 | const opts = ti.opts;
|
646 | const insertViews = ti.insertViews;
|
647 | const removeStart = ti.removeStart;
|
648 | const removeCount = ti.removeCount;
|
649 | let destroyQueue;
|
650 |
|
651 | if (removeStart !== undefined && removeCount !== undefined) {
|
652 | helpers.assert(removeStart >= 0, 'removeStart can not be negative');
|
653 | helpers.assert(removeCount >= 0, 'removeCount can not be negative');
|
654 | destroyQueue = [];
|
655 | for (let i = 0; i < removeCount; i++) {
|
656 | const view = this.views[i + removeStart];
|
657 | if (view && view !== enteringView && view !== leavingView) {
|
658 | destroyQueue.push(view);
|
659 | }
|
660 | }
|
661 |
|
662 | opts.direction = opts.direction || 'back';
|
663 | }
|
664 | const finalBalance = this.views.length +
|
665 | (insertViews !== undefined ? insertViews.length : 0) -
|
666 | (removeCount !== undefined ? removeCount : 0);
|
667 | helpers.assert(finalBalance >= 0, 'final balance can not be negative');
|
668 | if (finalBalance === 0) {
|
669 | console.warn(`You can't remove all the pages in the navigation stack. nav.pop() is probably called too many times.`, this, this.el);
|
670 | throw new Error('navigation stack needs at least one root page');
|
671 | }
|
672 |
|
673 |
|
674 | if (insertViews) {
|
675 |
|
676 | let insertIndex = ti.insertStart;
|
677 | for (const view of insertViews) {
|
678 | this.insertViewAt(view, insertIndex);
|
679 | insertIndex++;
|
680 | }
|
681 | if (ti.enteringRequiresTransition) {
|
682 |
|
683 | opts.direction = opts.direction || 'forward';
|
684 | }
|
685 | }
|
686 |
|
687 |
|
688 |
|
689 |
|
690 |
|
691 | if (destroyQueue && destroyQueue.length > 0) {
|
692 | for (const view of destroyQueue) {
|
693 | index$1.lifecycle(view.element, index$1.LIFECYCLE_WILL_LEAVE);
|
694 | index$1.lifecycle(view.element, index$1.LIFECYCLE_DID_LEAVE);
|
695 | index$1.lifecycle(view.element, index$1.LIFECYCLE_WILL_UNLOAD);
|
696 | }
|
697 |
|
698 | for (const view of destroyQueue) {
|
699 | this.destroyView(view);
|
700 | }
|
701 | }
|
702 | }
|
703 | async transition(enteringView, leavingView, ti) {
|
704 |
|
705 |
|
706 | const opts = ti.opts;
|
707 | const progressCallback = opts.progressAnimation
|
708 | ? (ani) => this.sbAni = ani
|
709 | : undefined;
|
710 | const mode = ionicGlobal.getIonMode(this);
|
711 | const enteringEl = enteringView.element;
|
712 | const leavingEl = leavingView && leavingView.element;
|
713 | const animationOpts = Object.assign(Object.assign({ mode, showGoBack: this.canGoBackSync(enteringView), baseEl: this.el, progressCallback, animated: this.animated && ionicGlobal.config.getBoolean('animated', true), enteringEl,
|
714 | leavingEl }, opts), { animationBuilder: opts.animationBuilder || this.animation || ionicGlobal.config.get('navAnimation') });
|
715 | const { hasCompleted } = await index$1.transition(animationOpts);
|
716 | return this.transitionFinish(hasCompleted, enteringView, leavingView, opts);
|
717 | }
|
718 | transitionFinish(hasCompleted, enteringView, leavingView, opts) {
|
719 | const cleanupView = hasCompleted ? enteringView : leavingView;
|
720 | if (cleanupView) {
|
721 | this.cleanup(cleanupView);
|
722 | }
|
723 | return {
|
724 | hasCompleted,
|
725 | requiresTransition: true,
|
726 | enteringView,
|
727 | leavingView,
|
728 | direction: opts.direction
|
729 | };
|
730 | }
|
731 | insertViewAt(view, index) {
|
732 | const views = this.views;
|
733 | const existingIndex = views.indexOf(view);
|
734 | if (existingIndex > -1) {
|
735 |
|
736 |
|
737 | helpers.assert(view.nav === this, 'view is not part of the nav');
|
738 | views.splice(index, 0, views.splice(existingIndex, 1)[0]);
|
739 | }
|
740 | else {
|
741 | helpers.assert(!view.nav, 'nav is used');
|
742 |
|
743 |
|
744 | view.nav = this;
|
745 |
|
746 | views.splice(index, 0, view);
|
747 | }
|
748 | }
|
749 | removeView(view) {
|
750 | helpers.assert(view.state === VIEW_STATE_ATTACHED || view.state === VIEW_STATE_DESTROYED, 'view state should be loaded or destroyed');
|
751 | const views = this.views;
|
752 | const index = views.indexOf(view);
|
753 | helpers.assert(index > -1, 'view must be part of the stack');
|
754 | if (index >= 0) {
|
755 | views.splice(index, 1);
|
756 | }
|
757 | }
|
758 | destroyView(view) {
|
759 | view._destroy();
|
760 | this.removeView(view);
|
761 | }
|
762 | |
763 |
|
764 |
|
765 | cleanup(activeView) {
|
766 |
|
767 |
|
768 |
|
769 | if (this.destroyed) {
|
770 | return;
|
771 | }
|
772 | const views = this.views;
|
773 | const activeViewIndex = views.indexOf(activeView);
|
774 | for (let i = views.length - 1; i >= 0; i--) {
|
775 | const view = views[i];
|
776 | |
777 |
|
778 |
|
779 |
|
780 |
|
781 |
|
782 |
|
783 |
|
784 | const element = view.element;
|
785 | if (element) {
|
786 | if (i > activeViewIndex) {
|
787 |
|
788 |
|
789 | index$1.lifecycle(element, index$1.LIFECYCLE_WILL_UNLOAD);
|
790 | this.destroyView(view);
|
791 | }
|
792 | else if (i < activeViewIndex) {
|
793 |
|
794 |
|
795 | index$1.setPageHidden(element, true);
|
796 | }
|
797 | }
|
798 | }
|
799 | }
|
800 | canStart() {
|
801 | return (!!this.swipeGesture &&
|
802 | !this.isTransitioning &&
|
803 | this.transInstr.length === 0 &&
|
804 | this.animationEnabled &&
|
805 | this.canGoBackSync());
|
806 | }
|
807 | onStart() {
|
808 | this.queueTrns({
|
809 | removeStart: -1,
|
810 | removeCount: 1,
|
811 | opts: {
|
812 | direction: 'back',
|
813 | progressAnimation: true
|
814 | }
|
815 | }, undefined);
|
816 | }
|
817 | onMove(stepValue) {
|
818 | if (this.sbAni) {
|
819 | this.sbAni.progressStep(stepValue);
|
820 | }
|
821 | }
|
822 | onEnd(shouldComplete, stepValue, dur) {
|
823 | if (this.sbAni) {
|
824 | this.animationEnabled = false;
|
825 | this.sbAni.onFinish(() => {
|
826 | this.animationEnabled = true;
|
827 | }, { oneTimeCallback: true });
|
828 |
|
829 | let newStepValue = (shouldComplete) ? -0.001 : 0.001;
|
830 | |
831 |
|
832 |
|
833 |
|
834 |
|
835 |
|
836 |
|
837 |
|
838 | if (!shouldComplete) {
|
839 | this.sbAni.easing('cubic-bezier(1, 0, 0.68, 0.28)');
|
840 | newStepValue += cubicBezier.getTimeGivenProgression([0, 0], [1, 0], [0.68, 0.28], [1, 1], stepValue)[0];
|
841 | }
|
842 | else {
|
843 | newStepValue += cubicBezier.getTimeGivenProgression([0, 0], [0.32, 0.72], [0, 1], [1, 1], stepValue)[0];
|
844 | }
|
845 | this.sbAni.progressEnd(shouldComplete ? 1 : 0, newStepValue, dur);
|
846 | }
|
847 | }
|
848 | render() {
|
849 | return (index.h("slot", null));
|
850 | }
|
851 | get el() { return index.getElement(this); }
|
852 | static get watchers() { return {
|
853 | "swipeGesture": ["swipeGestureChanged"],
|
854 | "root": ["rootChanged"]
|
855 | }; }
|
856 | };
|
857 | Nav.style = navCss;
|
858 |
|
859 | const navLink = (el, routerDirection, component, componentProps, routerAnimation) => {
|
860 | const nav = el.closest('ion-nav');
|
861 | if (nav) {
|
862 | if (routerDirection === 'forward') {
|
863 | if (component !== undefined) {
|
864 | return nav.push(component, componentProps, { skipIfBusy: true, animationBuilder: routerAnimation });
|
865 | }
|
866 | }
|
867 | else if (routerDirection === 'root') {
|
868 | if (component !== undefined) {
|
869 | return nav.setRoot(component, componentProps, { skipIfBusy: true, animationBuilder: routerAnimation });
|
870 | }
|
871 | }
|
872 | else if (routerDirection === 'back') {
|
873 | return nav.pop({ skipIfBusy: true, animationBuilder: routerAnimation });
|
874 | }
|
875 | }
|
876 | return Promise.resolve(false);
|
877 | };
|
878 |
|
879 | const NavLink = class {
|
880 | constructor(hostRef) {
|
881 | index.registerInstance(this, hostRef);
|
882 | |
883 |
|
884 |
|
885 | this.routerDirection = 'forward';
|
886 | this.onClick = () => {
|
887 | return navLink(this.el, this.routerDirection, this.component, this.componentProps, this.routerAnimation);
|
888 | };
|
889 | }
|
890 | render() {
|
891 | return (index.h(index.Host, { onClick: this.onClick }));
|
892 | }
|
893 | get el() { return index.getElement(this); }
|
894 | };
|
895 |
|
896 | exports.ion_nav = Nav;
|
897 | exports.ion_nav_link = NavLink;
|