refactor(app): remove router for now

This commit is contained in:
Dan Bucholtz
2017-12-20 15:34:09 -06:00
parent 25201d3a74
commit 049b89d87f
20 changed files with 270 additions and 320 deletions

View File

@ -2737,8 +2737,6 @@ declare global {
enabled?: boolean; enabled?: boolean;
icon?: string; icon?: string;
path?: string; path?: string;
root?: string;
rootParams?: any;
selected?: boolean; selected?: boolean;
show?: boolean; show?: boolean;
tabsHideOnSubPages?: boolean; tabsHideOnSubPages?: boolean;

View File

@ -148,22 +148,8 @@ sub {
} }
// Nav Container Structure ion-app {
// -------------------------------------------------- @extend .ion-page
ion-app,
ion-nav,
ion-tabs,
.ion-page {
@include position(0, null, null, 0);
position: absolute;
z-index: $z-index-page-container;
width: 100%;
height: 100%;
contain: layout size style;
} }
// Page Container Structure // Page Container Structure

View File

@ -95,7 +95,7 @@ export class App {
render() { render() {
const dom = [<slot></slot>]; const dom = [<slot></slot>];
if (this.useRouter) { if (this.useRouter) {
dom.push(<ion-router-controller></ion-router-controller>); // dom.push(<ion-router-controller></ion-router-controller>);
} }
return dom; return dom;
} }

View File

@ -0,0 +1,7 @@
// Util
// --------------------------------------------------
@import "../../themes/util";
ion-nav {
@extend .ion-page
}

View File

@ -58,6 +58,7 @@ const queueMap = new Map<number, TransitionInstruction[]>();
/* it is very important to keep this class in sync with ./nav-interface interface */ /* it is very important to keep this class in sync with ./nav-interface interface */
@Component({ @Component({
tag: 'ion-nav', tag: 'ion-nav',
styleUrl: 'nav.scss'
}) })
export class Nav implements PublicNav { export class Nav implements PublicNav {

View File

@ -0,0 +1,8 @@
// Util
// --------------------------------------------------
@import "../../themes/util";
ion-page {
@extend .ion-page
}

View File

@ -3,6 +3,7 @@ import { Component } from '@stencil/core';
@Component({ @Component({
tag: 'ion-page', tag: 'ion-page',
styleUrl: 'page.scss'
}) })
export class Page { export class Page {

View File

@ -11,16 +11,16 @@ export class TabButton {
@Prop() selected = false; @Prop() selected = false;
@Prop() tab: HTMLIonTabElement; @Prop() tab: HTMLIonTabElement;
@Event() ionTabbarClick: EventEmitter; @Event() ionTabbarClick: EventEmitter<TabButtonEventDetail>;
@Event() ionTabButtonDidLoad: EventEmitter; @Event() ionTabButtonDidLoad: EventEmitter<TabButtonEventDetail>;
@Event() ionTabButtonDidUnload: EventEmitter; @Event() ionTabButtonDidUnload: EventEmitter<TabButtonEventDetail>;
componentDidLoad() { componentDidLoad() {
this.ionTabButtonDidLoad.emit({ button: this }); this.ionTabButtonDidLoad.emit();
} }
componentDidUnload() { componentDidUnload() {
this.ionTabButtonDidUnload.emit({ button: this }); this.ionTabButtonDidUnload.emit();
} }
@Listen('click') @Listen('click')
@ -72,3 +72,11 @@ export class TabButton {
return items; return items;
} }
} }
export interface TabButtonEvent extends CustomEvent {
detail: TabButtonEventDetail;
}
export interface TabButtonEventDetail extends HTMLIonTabElement {
}

View File

@ -80,16 +80,6 @@ string
string string
#### root
string
#### rootParams
any
#### selected #### selected
boolean boolean
@ -142,16 +132,6 @@ string
string string
#### root
string
#### rootParams
any
#### selected #### selected
boolean boolean
@ -179,19 +159,10 @@ string
## Methods ## Methods
#### _setActive()
#### getActive()
#### getNav()
#### getPath() #### getPath()
#### goToRoot() #### setActive()

View File

@ -1,5 +1,4 @@
import { Component, Element, Event, EventEmitter, Method, Prop, PropDidChange, State } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Method, Prop, PropDidChange, State } from '@stencil/core';
import { PublicViewController, StencilElement } from '../../index';
@Component({ @Component({
@ -7,24 +6,11 @@ import { PublicViewController, StencilElement } from '../../index';
}) })
export class Tab { export class Tab {
private nav: Promise<HTMLIonNavElement>;
private resolveNav: (el: HTMLIonNavElement) => void;
@Element() el: HTMLElement; @Element() el: HTMLElement;
@State() init = false; @State() init = false;
@State() active = false; @State() active = false;
/**
* @input {Page} Set the root page for this tab.
*/
@Prop() root: string;
/**
* @input {object} Any nav-params to pass to the root page of this tab.
*/
@Prop() rootParams: any;
/** /**
* @input {string} Set the root page for this tab. * @input {string} Set the root page for this tab.
*/ */
@ -73,51 +59,24 @@ export class Tab {
*/ */
@Prop() tabsHideOnSubPages = false; @Prop() tabsHideOnSubPages = false;
constructor() {
this.nav = new Promise((resolve) => this.resolveNav = resolve);
}
@Prop({ mutable: true }) selected = false; @Prop({ mutable: true }) selected = false;
@PropDidChange('selected') @PropDidChange('selected')
selectedChanged(selected: boolean) { selectedChanged(selected: boolean) {
if (selected) { if (selected) {
this.ionSelect.emit(this.el); this.ionSelect.emit();
} }
} }
/** /**
* @output {Tab} Emitted when the current tab is selected. * @output {Tab} Emitted when the current tab is selected.
*/ */
@Event() ionSelect: EventEmitter; @Event() ionSelect: EventEmitter<TabEventDetail>;
protected componentDidUpdate() {
if (this.init && this.resolveNav) {
const nav = this.el.querySelector('ion-nav') as any as StencilElement;
nav.componentOnReady(this.resolveNav);
this.resolveNav = null;
}
}
@Method() @Method()
_setActive(shouldActive: boolean): Promise<any> { setActive(active: boolean): Promise<any> {
if (this.active === shouldActive) { this.active = active;
return Promise.resolve(); return Promise.resolve();
}
this.active = shouldActive;
this.selected = shouldActive;
const needsLifecycle = this.init;
if (shouldActive) {
this.init = true;
}
if (needsLifecycle) {
if (shouldActive) {
// lifecycle didEnter
} else {
// lifecycle didLeave
}
}
return this.nav;
} }
@Method() @Method()
@ -131,21 +90,6 @@ export class Tab {
return ''; return '';
} }
@Method()
goToRoot(opts: any = {}) {
return this.nav.then(nav => nav && nav.setRoot(nav.root, null, opts));
}
@Method()
getActive(): Promise<PublicViewController> {
return this.nav.then(nav => nav && nav.getActive());
}
@Method()
getNav(): Promise<HTMLIonNavElement> {
return this.nav;
}
hostData() { hostData() {
const visible = this.active && this.selected; const visible = this.active && this.selected;
return { return {
@ -159,9 +103,14 @@ export class Tab {
} }
render() { render() {
if (this.init) { return <slot></slot>;
return <ion-nav><slot></slot></ion-nav>;
}
return null;
} }
} }
export interface TabEvent extends CustomEvent {
detail: TabEventDetail;
}
export interface TabEventDetail {
}

View File

@ -167,9 +167,6 @@ boolean
#### ionChange #### ionChange
#### ionNavChanged
## Methods ## Methods
#### getByIndex() #### getByIndex()
@ -178,24 +175,15 @@ boolean
#### getIndex() #### getIndex()
#### getRoutes()
#### getSelected() #### getSelected()
#### getState()
#### getTabs() #### getTabs()
#### select() #### select()
#### setRouteId()
---------------------------------------------- ----------------------------------------------

View File

@ -1,5 +1,9 @@
@import "../../themes/ionic.globals"; @import "../../themes/ionic.globals";
// Util
// --------------------------------------------------
@import "../../themes/util";
// Tabs // Tabs
// -------------------------------------------------- // --------------------------------------------------
@ -215,3 +219,8 @@ ion-tabbar.scrollable .scroll-inner {
ion-tabbar.scrollable ion-button.inactive { ion-tabbar.scrollable ion-button.inactive {
visibility: hidden; visibility: hidden;
} }
ion-tabs {
@extend .ion-page
}

View File

@ -1,7 +1,5 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core';
import { Config, NavState, RouterEntries } from '../../index'; import { Config } from '../../index';
export interface NavOptions { }
@Component({ @Component({
@ -61,7 +59,6 @@ export class Tabs {
* @output {any} Emitted when the tab changes. * @output {any} Emitted when the tab changes.
*/ */
@Event() ionChange: EventEmitter; @Event() ionChange: EventEmitter;
@Event() ionNavChanged: EventEmitter;
componentDidLoad() { componentDidLoad() {
this.loadConfig('tabsPlacement', 'bottom'); this.loadConfig('tabsPlacement', 'bottom');
@ -69,10 +66,7 @@ export class Tabs {
this.loadConfig('tabsHighlight', true); this.loadConfig('tabsHighlight', true);
this.initTabs(); this.initTabs();
const useRouter = this.config.getBoolean('useRouter', false); this.initSelect();
if (!useRouter) {
this.initSelect();
}
} }
componentDidUnload() { componentDidUnload() {
@ -106,21 +100,21 @@ export class Tabs {
// The same selected was selected // The same selected was selected
// we need to set root in the nested ion-nav if it exist // we need to set root in the nested ion-nav if it exist
if (this.selectedTab === selectedTab) { /*if (this.selectedTab === selectedTab) {
return selectedTab.goToRoot(); return selectedTab.goToRoot();
} }
*/
const leavingTab = this.selectedTab; const leavingTab = this.selectedTab;
this.selectedTab = selectedTab; this.selectedTab = selectedTab;
let promise = selectedTab._setActive(true); let promise = selectedTab.setActive(true);
if (leavingTab) { if (leavingTab) {
promise = promise.then(() => leavingTab._setActive(false)); promise = promise.then(() => leavingTab.setActive(false));
} }
return promise.then(() => { return promise.then(() => {
this.ionChange.emit(selectedTab); this.ionChange.emit(selectedTab);
this.ionNavChanged.emit({ isPop: false });
}); });
} }
@ -152,7 +146,7 @@ export class Tabs {
return this.tabs; return this.tabs;
} }
@Method() /*@Method()
getState(): NavState { getState(): NavState {
const selectedTab = this.getSelected(); const selectedTab = this.getSelected();
if (!selectedTab) { if (!selectedTab) {
@ -175,6 +169,7 @@ export class Tabs {
return a; return a;
} }
@Method() @Method()
setRouteId(id: any, _: any = {}): Promise<void> { setRouteId(id: any, _: any = {}): Promise<void> {
if (this.selectedTab === id) { if (this.selectedTab === id) {
@ -182,10 +177,11 @@ export class Tabs {
} }
return this.select(id); return this.select(id);
} }
*/
private initTabs() { private initTabs() {
const tabs = this.tabs = Array.from(this.el.querySelectorAll('ion-tab')); const tabs = this.tabs = Array.from(this.el.querySelectorAll('ion-tab'));
for (let tab of tabs) { for (const tab of tabs) {
const id = `t-${this.tabsId}-${++this.ids}`; const id = `t-${this.tabsId}-${++this.ids}`;
tab.btnId = 'tab-' + id; tab.btnId = 'tab-' + id;
tab.id = 'tabpanel-' + id; tab.id = 'tabpanel-' + id;
@ -194,18 +190,16 @@ export class Tabs {
private initSelect() { private initSelect() {
// find pre-selected tabs // find pre-selected tabs
let selectedTab = this.tabs.find(t => t.selected); const selectedTab = this.tabs.find(t => t.selected) || this.tabs.find(t => t.show && t.enabled);
// reset all tabs none is selected // reset all tabs none is selected
for (let tab of this.tabs) { for (const tab of this.tabs) {
tab.selected = false; if (tab !== selectedTab) {
tab.selected = false;
}
} }
// find a tab candidate in case, the selected in null selectedTab.setActive(true);
if (!selectedTab) {
selectedTab = this.tabs.find(t => t.show && t.enabled);
}
selectedTab._setActive(true);
this.selectedTab = selectedTab; this.selectedTab = selectedTab;
} }
@ -241,3 +235,5 @@ export class Tabs {
} }
let tabIds = -1; let tabIds = -1;

View File

@ -14,68 +14,57 @@
<ion-app> <ion-app>
<ion-tabs> <ion-tabs>
<ion-tab title="Plain List" icon="star" path=""> <ion-tab title="Plain List" icon="star" path="">
<ion-route path="" component="page-tab"></ion-route> <ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Tab One</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
Tab One
</ion-content>
</ion-page>
</ion-tab> </ion-tab>
<ion-tab title="Schedule" icon="globe" path="tab2"> <ion-tab title="Schedule" icon="globe" path="tab2">
<ion-route path="" component="page-two"></ion-route> <ion-page>
<ion-route path="path/to/page/three" component="page-three"></ion-route> <ion-header>
<ion-toolbar>
<ion-title>Tab Two</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
Tab Two
</ion-content>
</ion-page>
</ion-tab> </ion-tab>
<ion-tab title="Stopwatch" icon="logo-facebook" path="tab3"> <ion-tab title="Stopwatch" icon="logo-facebook" path="tab3">
<ion-route path="/" component="page-three"></ion-route> <ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Tab Three</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
Tab Three
</ion-content>
</ion-page>
</ion-tab> </ion-tab>
<ion-tab title="Messages" icon="chatboxes" path="tab4"> <ion-tab title="Messages" icon="chatboxes" path="tab4">
<ion-route component="page-one"></ion-route> <ion-page>
<ion-route path="paginaaaa-two" component="page-two"></ion-route> <ion-header>
<ion-toolbar>
<ion-title>Tab Four</ion-title>
</ion-toolbar>
</ion-header>
<ion-content padding>
Tab Four
</ion-content>
</ion-page>
</ion-tab> </ion-tab>
</ion-tabs> </ion-tabs>
<ion-nav-controller></ion-nav-controller>
</ion-app> </ion-app>
<style>
f {
display: block;
background: blue;
width: 100%;
height: 200px;
margin: 20px auto;
}
.red {
background-color: #ea445a;
}
.green {
background-color: #76d672;
}
.blue {
background-color: #3478f6;
}
.yellow {
background-color: #ffff80;
}
.pink {
background-color: #ff6b86;
}
.purple {
background-color: #7e34f6;
}
.black {
background-color: #000;
}
.orange {
background-color: #f69234;
}
</style>
</body> </body>
</html> </html>

View File

@ -1,88 +0,0 @@
import { Component, Element } from '@stencil/core';
export interface Route {
path: string | null;
component: string;
}
@Component({
tag: 'page-tab'
})
export class PageTab {
@Element() element: HTMLElement;
getTabs() {
return this.element.closest('ion-tabs') as HTMLIonTabsElement;
}
setLayout(value: string) {
this.getTabs().tabbarLayout = value;
}
setPlacement(value: string) {
this.getTabs().tabbarPlacement = value;
}
setHidden(value: boolean) {
this.getTabs().tabbarHidden = value;
}
setHighlight(value: boolean) {
this.getTabs().tabbarHighlight = value;
}
render() {
return [
<ion-header>
<ion-toolbar>
<ion-title>Tab page</ion-title>
</ion-toolbar>
</ion-header>,
<ion-content fullscreen={true}>
<p>
<h2>Set tabbar layout</h2>
<ion-button onClick={() => this.setLayout('icon-top')}>icon-top</ion-button>
<ion-button onClick={() => this.setLayout('icon-start')}>icon-start</ion-button>
<ion-button onClick={() => this.setLayout('icon-end')}>icon-end</ion-button>
<ion-button onClick={() => this.setLayout('icon-bottom')}>icon-bottom</ion-button>
<ion-button onClick={() => this.setLayout('icon-hide')}>icon-hide</ion-button>
<ion-button onClick={() => this.setLayout('title-hide')}>title-hide</ion-button>
</p>
<p>
<h2>Set tabbar placement</h2>
<ion-button onClick={() => this.setPlacement('top')}>top</ion-button>
<ion-button onClick={() => this.setPlacement('bottom')}>bottom</ion-button>
</p>
<p>
<h2>Set tabbar hidden</h2>
<ion-button onClick={() => this.setHidden(true)}>hidden</ion-button>
<ion-button onClick={() => this.setHidden(false)}>visible</ion-button>
</p>
<p>
<h2>Set tabbar highlight</h2>
<ion-button onClick={() => this.setHighlight(true)}>enabled</ion-button>
<ion-button onClick={() => this.setHighlight(false)}>disabled</ion-button>
</p>
<p><a href='#/not-found'>Not found</a></p>
<p><a href='#/'>/</a></p>
<p><a href='#/tab2'>/tab2</a></p>
<p><a href='#/tab3'>/tab3</a></p>
<p><a href='#/tab4'>/tab4</a></p>
<p><a href='#/tab4/paginaaaa-two'>/tab4/paginaaaa-two</a></p>
<ion-grid>
<ion-row>
<ion-col col-6><f class='red'></f></ion-col>
<ion-col col-6><f class='green'></f></ion-col>
<ion-col col-6><f class='blue'></f></ion-col>
<ion-col col-6><f class='yellow'></f></ion-col>
<ion-col col-6><f class='pink'></f></ion-col>
<ion-col col-6><f class='purple'></f></ion-col>
<ion-col col-6><f class='black'></f></ion-col>
<ion-col col-6><f class='orange'></f></ion-col>
</ion-row>
</ion-grid>
</ion-content>
];
}
}

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="UTF-8">
<title>Tab - Basic</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<script src="/dist/ionic.js"></script>
<script type="text/javascript">
window.Ionic.config = {useRouter: true};
</script>
</head>
<body>
<ion-tabs>
<ion-tab title="Plain List" icon="star" path="">
<div class="div-one">Div One</div>
</ion-tab>
<ion-tab title="Schedule" icon="globe" path="tab2">
<div class="div-two">Div Two</div>
</ion-tab>
<ion-tab title="Schedule" icon="globe" path="tab2">
<div class="div-three">Div Three</div>
</ion-tabs>
<style>
.div-one {
background-color: blue;
height: 100%;
color: #FFF;
}
.div-two {
background-color: red;
height: 100%;
color: #FFF;
}
.div-three {
background-color: green;
height: 100%;
color: #FFF;
}
</style>
</body>
</html>

View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="UTF-8">
<title>Tab - Basic</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<script src="/dist/ionic.js"></script>
<script type="text/javascript">
window.Ionic.config = {useRouter: true};
</script>
</head>
<body>
<ion-tabs>
<ion-tab title="Plain List" icon="star" path="">
<div class="div-one">Div One</div>
</ion-tab>
<ion-tab title="Schedule" icon="globe" path="tab2">
<div class="div-two">Div Two</div>
</ion-tab>
<ion-tab title="Schedule" icon="globe" path="tab2">
<div class="div-three">Div Three</div>
</ion-tabs>
<style>
.div-one {
background-color: blue;
height: 100%;
color: #FFF;
}
.div-two {
background-color: red;
height: 100%;
color: #FFF;
}
.div-three {
background-color: green;
height: 100%;
color: #FFF;
}
</style>
</body>
</html>

View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="UTF-8">
<title>Tab - Basic</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<script src="/dist/ionic.js"></script>
<script type="text/javascript">
window.Ionic.config = {useRouter: true};
</script>
</head>
<body>
<ion-app>
<ion-tabs>
<ion-tab title="Plain List" icon="star" path="">
<div class="div-one">Div One</div>
</ion-tab>
<ion-tab title="Schedule" icon="globe" path="tab2">
<div class="div-two">Div Two</div>
</ion-tab>
<ion-tab title="Schedule" icon="globe" path="tab2">
<div class="div-three">Div Three</div>
</ion-tabs>
</ion-app>
<style>
.div-one {
background-color: blue;
height: 100%;
color: #FFF;
}
.div-two {
background-color: red;
height: 100%;
color: #FFF;
}
.div-three {
background-color: green;
height: 100%;
color: #FFF;
}
</style>
</body>
</html>

View File

@ -47,3 +47,19 @@ $z-index-item-options: 1; // scss-lint:disable DefaultRule
$z-index-item-divider: 100; // scss-lint:disable DefaultRule $z-index-item-divider: 100; // scss-lint:disable DefaultRule
$z-index-reorder-selected: 100; // scss-lint:disable DefaultRule $z-index-reorder-selected: 100; // scss-lint:disable DefaultRule
.ion-page {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: $z-index-page-container;
width: 100%;
height: 100%;
contain: layout size style;
}

View File

@ -40,31 +40,3 @@ $focus-outline-box-shadow: 0 0 8px 1px $focus-outline-border-color !default;
ion-input :focus { ion-input :focus {
outline: none; outline: none;
} }
// Click Block
// --------------------------------------------------
// Fill the screen to block clicks (a better pointer-events: none)
// to avoid full-page reflows and paints which can cause flickers
.click-block {
display: none;
}
.click-block-enabled {
@include position(0, 0, 0, 0);
@include transform(translate3d(0, -100%, 0), translateY(1px));
position: absolute;
z-index: $z-index-click-block;
display: block;
opacity: 0;
contain: strict;
}
.click-block-active {
@include transform(translate3d(0, 0, 0));
}