diff --git a/src/components.ts b/src/components.ts
deleted file mode 100644
index 18fd1ce1ba..0000000000
--- a/src/components.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-export { ActionSheet, ActionSheetController } from './components/action-sheet/action-sheet';
-export { ActionSheetOptions } from './components/action-sheet/action-sheet-options';
-export { Alert, AlertController } from './components/alert/alert';
-export { AlertOptions, AlertInputOptions } from './components/alert/alert-options';
-export { App } from './components/app/app';
-export { Backdrop } from './components/backdrop/backdrop';
-export { Badge } from './components/badge/badge';
-export { Button } from './components/button/button';
-export { Checkbox } from './components/checkbox/checkbox';
-export { Chip } from './components/chip/chip';
-export { Content } from './components/content/content';
-export { DateTime } from './components/datetime/datetime';
-export { Icon } from './components/icon/icon';
-export { Img } from './components/img/img';
-export { InfiniteScroll } from './components/infinite-scroll/infinite-scroll';
-export { InfiniteScrollContent } from './components/infinite-scroll/infinite-scroll-content';
-export { TextArea, TextInput } from './components/input/input';
-export { Item } from './components/item/item';
-export { ItemReorder } from './components/item/item-reorder';
-export { ItemSliding, ItemOptions, ItemSideFlags } from './components/item/item-sliding';
-export { Label } from './components/label/label';
-export { List, ListHeader } from './components/list/list';
-export { Loading, LoadingController } from './components/loading/loading';
-export { LoadingOptions } from './components/loading/loading-options';
-export { Menu } from './components/menu/menu';
-export { MenuClose } from './components/menu/menu-close';
-export { MenuController } from './components/menu/menu-controller';
-export { MenuToggle } from './components/menu/menu-toggle';
-export { MenuType } from './components/menu/menu-types';
-export { Modal, ModalController } from './components/modal/modal';
-export { ModalOptions } from './components/modal/modal-options';
-export { Nav } from './components/nav/nav';
-export { NavController } from './components/nav/nav-controller';
-export { NavOptions } from './components/nav/nav-interfaces';
-export { NavParams } from './components/nav/nav-params';
-export { NavPop } from './components/nav/nav-pop';
-export { NavPush } from './components/nav/nav-push';
-export { ViewController } from './components/nav/view-controller';
-export { Navbar, NavbarTemplate } from './components/navbar/navbar';
-export { Option } from './components/option/option';
-export { Picker, PickerController } from './components/picker/picker';
-export { PickerOptions, PickerColumn, PickerColumnOption } from './components/picker/picker-options';
-export { Popover, PopoverController } from './components/popover/popover';
-export { PopoverOptions } from './components/popover/popover-options';
-export { RadioButton } from './components/radio/radio-button';
-export { RadioGroup } from './components/radio/radio-group';
-export { Range, RangeKnob, ClientRect } from './components/range/range';
-export { Refresher } from './components/refresher/refresher';
-export { RefresherContent } from './components/refresher/refresher-content';
-export { Scroll } from './components/scroll/scroll';
-export { Searchbar } from './components/searchbar/searchbar';
-export { Segment, SegmentButton } from './components/segment/segment';
-export { Select } from './components/select/select';
-export { ShowWhen, HideWhen, DisplayWhen } from './components/show-hide-when/show-hide-when';
-export { Slides, Slide, SlideLazy } from './components/slides/slides';
-export { Spinner } from './components/spinner/spinner';
-export { Tab } from './components/tabs/tab';
-export { Tabs } from './components/tabs/tabs';
-export { TapClick, isActivatable } from './components/tap-click/tap-click';
-export { Toast, ToastController } from './components/toast/toast';
-export { ToastOptions } from './components/toast/toast-options';
-export { Toggle } from './components/toggle/toggle';
-export { Toolbar, ToolbarBase, Header, Footer } from './components/toolbar/toolbar';
-export { Typography } from './components/typography/typography';
-export { VirtualScroll } from './components/virtual-scroll/virtual-scroll';
diff --git a/src/components/app/app-root.ts b/src/components/app/app-root.ts
new file mode 100644
index 0000000000..06c155369d
--- /dev/null
+++ b/src/components/app/app-root.ts
@@ -0,0 +1,113 @@
+import { Component, ComponentFactoryResolver, ElementRef, Inject, OnInit, OpaqueToken, Renderer, ViewChild, ViewContainerRef } from '@angular/core';
+
+import { App } from './app';
+import { Config } from '../../config/config';
+import { FeatureDetect } from '../../util/feature-detect';
+import { Ion } from '../ion';
+import { OverlayPortal } from '../nav/overlay-portal';
+import { Platform } from '../../platform/platform';
+
+export const UserRoot = new OpaqueToken('USERROOT');
+
+/**
+ * @private
+ */
+@Component({
+ selector: 'ion-app',
+ template:
+ '
' +
+ '' +
+ '' +
+ '' +
+ ''
+})
+export class IonicApp extends Ion implements OnInit {
+
+ @ViewChild('viewport', {read: ViewContainerRef}) _viewport: ViewContainerRef;
+
+ @ViewChild('overlayPortal', { read: OverlayPortal }) _overlayPortal: OverlayPortal;
+
+ @ViewChild('loadingPortal', { read: OverlayPortal }) _loadingPortal: OverlayPortal;
+
+ @ViewChild('toastPortal', { read: OverlayPortal }) _toastPortal: OverlayPortal;
+
+ constructor(
+ @Inject(UserRoot) private _userCmp: any,
+ private _cfr: ComponentFactoryResolver,
+ elementRef: ElementRef,
+ renderer: Renderer,
+ config: Config,
+ private _platform: Platform,
+ private _featureDetect: FeatureDetect,
+ app: App
+ ) {
+ super(config, elementRef, renderer);
+ // register with App that this is Ionic's appRoot component. tada!
+ app._appRoot = this;
+ }
+
+ ngOnInit() {
+ // load the user root component
+ // into Ionic's root component
+ const factory = this._cfr.resolveComponentFactory(this._userCmp);
+ const componentRef = this._viewport.createComponent(factory);
+ this._renderer.setElementClass(componentRef.location.nativeElement, 'app-root', true);
+ componentRef.changeDetectorRef.detectChanges();
+
+ // set the mode class name
+ // ios/md/wp
+ this.setElementClass(this._config.get('mode'), true);
+
+ const versions = this._platform.versions();
+ this._platform.platforms().forEach(platformName => {
+ // platform-ios
+ let platformClass = 'platform-' + platformName;
+ this.setElementClass(platformClass, true);
+
+ let platformVersion = versions[platformName];
+ if (platformVersion) {
+ // platform-ios9
+ platformClass += platformVersion.major;
+ this.setElementClass(platformClass, true);
+
+ // platform-ios9_3
+ this.setElementClass(platformClass + '_' + platformVersion.minor, true);
+ }
+ });
+
+ // touch devices should not use :hover CSS pseudo
+ // enable :hover CSS when the "hoverCSS" setting is not false
+ if (this._config.getBoolean('hoverCSS', true)) {
+ this.setElementClass('enable-hover', true);
+ }
+
+ this._featureDetect.test(this);
+ }
+
+ /**
+ * @private
+ */
+ _getPortal(portal?: AppPortal): OverlayPortal {
+ if (portal === AppPortal.LOADING) {
+ return this._loadingPortal;
+ }
+ if (portal === AppPortal.TOAST) {
+ return this._toastPortal;
+ }
+ return this._overlayPortal;
+ }
+
+ /**
+ * @private
+ */
+ _disableScroll(shouldDisableScroll: boolean) {
+ this.setElementClass('disable-scroll', shouldDisableScroll);
+ }
+
+}
+
+export enum AppPortal {
+ DEFAULT,
+ LOADING,
+ TOAST
+};
diff --git a/src/components/app/app.ts b/src/components/app/app.ts
index 6d42cd39d5..17602ed0e4 100644
--- a/src/components/app/app.ts
+++ b/src/components/app/app.ts
@@ -1,22 +1,17 @@
-import { Component, ComponentResolver, EventEmitter, HostBinding, Injectable, Renderer, ViewChild, ViewContainerRef } from '@angular/core';
+import { EventEmitter, Injectable } from '@angular/core';
import { Title } from '@angular/platform-browser';
+import { AppPortal, IonicApp } from './app-root';
import { ClickBlock } from '../../util/click-block';
import { Config } from '../../config/config';
-import { NavController } from '../nav/nav-controller';
-import { isTabs, isNav } from '../nav/nav-controller-base';
-import { NavOptions } from '../nav/nav-interfaces';
-import { NavPortal } from '../nav/nav-portal';
+import { isNav, isTabs, NavOptions, DIRECTION_FORWARD, DIRECTION_BACK } from '../../navigation/nav-util';
+import { NavController } from '../../navigation/nav-controller';
import { Platform } from '../../platform/platform';
-
-/**
- * @private
- */
-export abstract class UserComponent {}
+import { ViewController } from '../../navigation/view-controller';
/**
- * Ionic App utility service.
+ * Ionic App
*/
@Injectable()
export class App {
@@ -25,17 +20,16 @@ export class App {
private _title: string = '';
private _titleSrv: Title = new Title();
private _rootNav: NavController = null;
- private _portal: NavPortal;
/**
* @private
*/
- clickBlock: ClickBlock;
+ _clickBlock: ClickBlock;
/**
* @private
*/
- appRoot: AppRoot;
+ _appRoot: IonicApp;
/**
* @private
@@ -67,11 +61,6 @@ export class App {
*/
viewWillUnload: EventEmitter = new EventEmitter();
- /**
- * @private
- */
- viewDidUnload: EventEmitter = new EventEmitter();
-
constructor(
private _config: Config,
private _platform: Platform
@@ -92,6 +81,13 @@ export class App {
}
}
+ /**
+ * @private
+ */
+ setElementClass(className: string, isAdd: boolean) {
+ this._appRoot.setElementClass(className, isAdd);
+ }
+
/**
* Sets if the app is currently enabled or not, meaning if it's
* available to accept new user commands. For example, this is set to `false`
@@ -106,14 +102,14 @@ export class App {
setEnabled(isEnabled: boolean, duration: number = 700) {
this._disTime = (isEnabled ? 0 : Date.now() + duration);
- if (this.clickBlock) {
+ if (this._clickBlock) {
if (isEnabled || duration <= 32) {
// disable the click block if it's enabled, or the duration is tiny
- this.clickBlock.activate(false, 0);
+ this._clickBlock.activate(false, 0);
} else {
// show the click block for duration + some number
- this.clickBlock.activate(true, duration + CLICK_BLOCK_BUFFER_IN_MILLIS);
+ this._clickBlock.activate(true, duration + CLICK_BLOCK_BUFFER_IN_MILLIS);
}
}
}
@@ -124,15 +120,9 @@ export class App {
* scrolling is enabled. When set to `true`, scrolling is disabled.
*/
setScrollDisabled(disableScroll: boolean) {
- let enabled = this._config.get('canDisableScroll', true);
- if (!enabled) {
- return;
+ if (this._config.get('canDisableScroll', true)) {
+ this._appRoot._disableScroll(disableScroll);
}
- if (!this.appRoot) {
- console.error('appRoot is missing, scrolling can not be enabled/disabled');
- return;
- }
- this.appRoot.disableScroll = disableScroll;
}
/**
@@ -187,38 +177,33 @@ export class App {
/**
* @private
*/
- setRootNav(nav: any) {
+ _setRootNav(nav: any) {
this._rootNav = nav;
}
/**
* @private
*/
- setPortal(portal: NavPortal) {
- this._portal = portal;
- }
+ present(enteringView: ViewController, opts: NavOptions, appPortal?: AppPortal): Promise {
+ const portal = this._appRoot._getPortal(appPortal);
- /**
- * @private
- */
- present(enteringView: any, opts: NavOptions = {}): Promise {
- enteringView.setNav(this._portal);
+ enteringView._setNav(portal);
opts.keyboardClose = false;
- opts.direction = 'forward';
+ opts.direction = DIRECTION_FORWARD;
if (!opts.animation) {
- opts.animation = enteringView.getTransitionName('forward');
+ opts.animation = enteringView.getTransitionName(DIRECTION_FORWARD);
}
enteringView.setLeavingOpts({
keyboardClose: false,
- direction: 'back',
- animation: enteringView.getTransitionName('back'),
+ direction: DIRECTION_BACK,
+ animation: enteringView.getTransitionName(DIRECTION_BACK),
ev: opts.ev
});
- return this._portal.insertViews(-1, [enteringView], opts);
+ return portal.insertPages(-1, [enteringView], opts);
}
/**
@@ -257,14 +242,15 @@ export class App {
// app must be enabled and there must be a
// root nav controller for go back to work
if (this._rootNav && this.isEnabled()) {
+ const portal = this._appRoot._getPortal();
// first check if the root navigation has any overlays
// opened in it's portal, like alert/actionsheet/popup
- if (this._portal && this._portal.length() > 0) {
+ if (portal.length() > 0) {
// there is an overlay view in the portal
// let's pop this one off to go back
console.debug('app, goBack pop overlay');
- return this._portal.pop();
+ return portal.pop();
}
// next get the active nav, check itself and climb up all
@@ -285,72 +271,6 @@ export class App {
return Promise.resolve();
}
- /**
- * @private
- */
- private getRegisteredComponent(cls: any): any {
- // deprecated warning: added 2016-04-28, beta7
- console.warn('Using app.getRegisteredComponent() to query components has been deprecated. ' +
- 'Please use Angular\'s ViewChild annotation instead:\n\nhttp://learnangular2.com/viewChild/');
- }
-
- /**
- * @private
- */
- private getComponent(id: string): any {
- // deprecated warning: added 2016-04-28, beta7
- console.warn('Using app.getComponent() to query components has been deprecated. ' +
- 'Please use Angular\'s ViewChild annotation instead:\n\nhttp://learnangular2.com/viewChild/');
- }
-
- /**
- * Get an instance of the global app injector that contains references to all of the instantiated providers
- * @returns {Injector}
- */
- private getAppInjector(): any {
- // deprecated warning: added 2016-06-27, beta10
- console.warn('Recent Angular2 versions should no longer require App.getAppInjector()');
- }
-}
-
-
-/**
- * @private
- */
-@Component({
- selector: 'ion-app',
- template: `
-
-
- `,
- directives: [NavPortal, ClickBlock]
-})
-export class AppRoot {
-
- @ViewChild('anchor', {read: ViewContainerRef}) private _viewport: ViewContainerRef;
-
- constructor(
- private _cmp: UserComponent,
- private _cr: ComponentResolver,
- private _renderer: Renderer,
- app: App
- ) {
- app.appRoot = this;
- }
-
- ngAfterViewInit() {
- // load the user app's root component
- this._cr.resolveComponent(this._cmp).then(componentFactory => {
- let appEle: HTMLElement = this._renderer.createElement(null, componentFactory.selector || 'div', null);
- appEle.setAttribute('class', 'app-root');
-
- let componentRef = componentFactory.create(this._viewport.injector, null, appEle);
- this._viewport.insert(componentRef.hostView, 0);
- });
- }
-
- @HostBinding('class.disable-scroll') disableScroll: boolean = false;
-
}
const CLICK_BLOCK_BUFFER_IN_MILLIS = 64;
diff --git a/src/components/ion.ts b/src/components/ion.ts
index 4f487ff8f5..227e03d631 100644
--- a/src/components/ion.ts
+++ b/src/components/ion.ts
@@ -1,7 +1,7 @@
-import { ElementRef } from '@angular/core';
-import { getDimensions, clearDimensions } from '../util/dom';
+import { ElementRef, Renderer } from '@angular/core';
-let ids: number = 0;
+import { Config } from '../config/config';
+import { getDimensions, clearDimensions } from '../util/dom';
/**
* Base class for all Ionic components. Exposes some common functionality
@@ -9,36 +9,109 @@ let ids: number = 0;
* sending/receiving app-level events.
*/
export class Ion {
- private _id: string;
+ private _ionId: string;
- constructor(protected elementRef: ElementRef) {
- this._id = 'i' + ids++;
+ /** @private */
+ _config: Config;
+
+ /** @private */
+ _elementRef: ElementRef;
+
+ /** @private */
+ _renderer: Renderer;
+
+ /** @private */
+ _color: string;
+
+ /** @private */
+ _mode: string;
+
+ constructor(config: Config, elementRef: ElementRef, renderer: Renderer) {
+ this._config = config;
+ this._elementRef = elementRef;
+ this._renderer = renderer;
}
+ /** @private */
+ setElementClass(className: string, isAdd: boolean) {
+ this._renderer.setElementClass(this._elementRef.nativeElement, className, isAdd);
+ }
+
+ /** @private */
+ setElementAttribute(attributeName: string, attributeValue: any) {
+ this._renderer.setElementAttribute(this._elementRef.nativeElement, attributeName, attributeValue);
+ }
+
+ /** @private */
+ setElementStyle(property: string, value: string) {
+ this._renderer.setElementStyle(this._elementRef.nativeElement, property, value);
+ }
+
+ /** @private */
+ _setColor(componentName: string, newColor: string) {
+ if (this._color) {
+ this.setElementClass(`${componentName}-${this._mode}-${this._color}`, false);
+ }
+ if (newColor) {
+ this.setElementClass(`${componentName}-${this._mode}-${newColor}`, true);
+ this._color = newColor;
+ }
+ }
+
+ /** @private */
+ _setMode(componentName: string, newMode: string) {
+ if (this._mode) {
+ this.setElementClass(`${componentName}-${this._mode}`, false);
+ }
+ if (newMode) {
+ this.setElementClass(`${componentName}-${newMode}`, true);
+
+ // Remove the color class associated with the previous mode,
+ // change the mode, then add the new color class
+ this._setColor(componentName, null);
+ this._mode = newMode;
+ this._setColor(componentName, this._color);
+ }
+ }
+
+ /** @private */
getElementRef(): ElementRef {
- return this.elementRef;
+ return this._elementRef;
}
+ /** @private */
getNativeElement(): any {
- return this.elementRef.nativeElement;
+ return this._elementRef.nativeElement;
}
- getDimensions(): {
- width: number, height: number, left: number, top: number
- } {
- return getDimensions(this.elementRef.nativeElement, this._id);
+ /** @private */
+ getDimensions(): { width: number, height: number, left: number, top: number} {
+ return getDimensions(this.getNativeElement(), this._getId());
}
+ /** @private */
width(): number {
- return getDimensions(this.elementRef.nativeElement, this._id).width;
+ return getDimensions(this.getNativeElement(), this._getId()).width;
}
+ /** @private */
height(): number {
- return getDimensions(this.elementRef.nativeElement, this._id).height;
+ return getDimensions(this.getNativeElement(), this._getId()).height;
}
- ngOnDestroy() {
- clearDimensions(this._id);
+ /** @private */
+ destroy() {
+ clearDimensions(this._ionId);
+ }
+
+ /** internal */
+ _getId() {
+ if (!this._ionId) {
+ this._ionId = 'i' + ids++;
+ }
+ return this._ionId;
}
}
+
+let ids: number = 0;
diff --git a/src/directives.ts b/src/directives.ts
new file mode 100644
index 0000000000..b047ab2085
--- /dev/null
+++ b/src/directives.ts
@@ -0,0 +1,241 @@
+
+/**
+ * Import Components
+ */
+import { Avatar } from './components/avatar/avatar';
+import { Backdrop } from './components/backdrop/backdrop';
+import { Badge } from './components/badge/badge';
+import { Button } from './components/button/button';
+import { Card, CardContent, CardHeader, CardTitle } from './components/card/card';
+import { Checkbox } from './components/checkbox/checkbox';
+import { Chip } from './components/chip/chip';
+import { Content } from './components/content/content';
+import { DateTime } from './components/datetime/datetime';
+import { Fixed } from './components/fixed/fixed';
+import { Grid, Row, Col } from './components/grid/grid';
+import { Icon } from './components/icon/icon';
+import { Img } from './components/img/img';
+import { InfiniteScroll } from './components/infinite-scroll/infinite-scroll';
+import { InfiniteScrollContent } from './components/infinite-scroll/infinite-scroll-content';
+import { IonicApp } from './components/app/app-root';
+import { Item, ItemContent, ItemGroup } from './components/item/item';
+import { ItemReorder, Reorder } from './components/item/item-reorder';
+import { ItemSliding, ItemOptions } from './components/item/item-sliding';
+import { Label } from './components/label/label';
+import { List } from './components/list/list';
+import { ListHeader } from './components/list/list-header';
+import { Menu } from './components/menu/menu';
+import { MenuClose } from './components/menu/menu-close';
+import { MenuToggle } from './components/menu/menu-toggle';
+import { NativeInput, NextInput } from './components/input/native-input';
+import { Nav } from './components/nav/nav';
+import { NavPop, NavPopAnchor } from './components/nav/nav-pop';
+import { NavPush, NavPushAnchor } from './components/nav/nav-push';
+import { Navbar } from './components/navbar/navbar';
+import { Note } from './components/note/note';
+import { Option } from './components/option/option';
+import { OverlayPortal } from './components/nav/overlay-portal';
+import { PickerColumnCmp } from './components/picker/picker-component';
+import { RadioButton } from './components/radio/radio-button';
+import { RadioGroup } from './components/radio/radio-group';
+import { Range, RangeKnob } from './components/range/range';
+import { Refresher } from './components/refresher/refresher';
+import { RefresherContent } from './components/refresher/refresher-content';
+import { Scroll } from './components/scroll/scroll';
+import { Searchbar } from './components/searchbar/searchbar';
+import { Segment, SegmentButton } from './components/segment/segment';
+import { Select } from './components/select/select';
+import { ShowWhen, HideWhen } from './components/show-hide-when/show-hide-when';
+import { Slides, Slide, SlideLazy } from './components/slides/slides';
+import { Spinner } from './components/spinner/spinner';
+import { Tab } from './components/tabs/tab';
+import { Tabs } from './components/tabs/tabs';
+import { TabButton } from './components/tabs/tab-button';
+import { TextInput, TextArea } from './components/input/input';
+import { Thumbnail } from './components/thumbnail/thumbnail';
+import { Toggle } from './components/toggle/toggle';
+import { Toolbar, Header, Footer } from './components/toolbar/toolbar';
+import { ToolbarItem } from './components/toolbar/toolbar-item';
+import { ToolbarTitle } from './components/toolbar/toolbar-title';
+import { Typography } from './components/typography/typography';
+import { VirtualScroll } from './components/virtual-scroll/virtual-scroll';
+import { VirtualItem, VirtualHeader, VirtualFooter } from './components/virtual-scroll/virtual-item';
+
+
+/**
+ * Export Components
+ */
+export { ActionSheet, ActionSheetController } from './components/action-sheet/action-sheet';
+export { ActionSheetOptions } from './components/action-sheet/action-sheet-options';
+export { Alert, AlertController } from './components/alert/alert';
+export { AlertOptions, AlertInputOptions } from './components/alert/alert-options';
+export { App } from './components/app/app';
+export { Avatar } from './components/avatar/avatar';
+export { Backdrop } from './components/backdrop/backdrop';
+export { Badge } from './components/badge/badge';
+export { Button } from './components/button/button';
+export { Card, CardContent, CardHeader, CardTitle } from './components/card/card';
+export { Checkbox } from './components/checkbox/checkbox';
+export { Chip } from './components/chip/chip';
+export { Content } from './components/content/content';
+export { DateTime } from './components/datetime/datetime';
+export { Fixed } from './components/fixed/fixed';
+export { Grid, Row, Col } from './components/grid/grid';
+export { Icon } from './components/icon/icon';
+export { Img } from './components/img/img';
+export { InfiniteScroll } from './components/infinite-scroll/infinite-scroll';
+export { InfiniteScrollContent } from './components/infinite-scroll/infinite-scroll-content';
+export { TextArea, TextInput } from './components/input/input';
+export { IonicApp } from './components/app/app-root';
+export { Item, ItemContent, ItemGroup } from './components/item/item';
+export { ItemReorder, Reorder } from './components/item/item-reorder';
+export { ItemSliding, ItemOptions, ItemSideFlags } from './components/item/item-sliding';
+export { Label } from './components/label/label';
+export { List } from './components/list/list';
+export { ListHeader } from './components/list/list-header';
+export { Loading, LoadingController } from './components/loading/loading';
+export { LoadingOptions } from './components/loading/loading-options';
+export { Menu } from './components/menu/menu';
+export { MenuClose } from './components/menu/menu-close';
+export { MenuController } from './components/menu/menu-controller';
+export { MenuToggle } from './components/menu/menu-toggle';
+export { MenuType } from './components/menu/menu-types';
+export { Modal, ModalController } from './components/modal/modal';
+export { ModalOptions } from './components/modal/modal-options';
+export { Nav } from './components/nav/nav';
+export { NavPop, NavPopAnchor } from './components/nav/nav-pop';
+export { NavPush, NavPushAnchor } from './components/nav/nav-push';
+export { Navbar } from './components/navbar/navbar';
+export { NativeInput, NextInput } from './components/input/native-input';
+export { Note } from './components/note/note';
+export { Option } from './components/option/option';
+export { OverlayPortal } from './components/nav/overlay-portal';
+export { Picker, PickerController } from './components/picker/picker';
+export { PickerOptions, PickerColumn, PickerColumnOption } from './components/picker/picker-options';
+export { Popover, PopoverController } from './components/popover/popover';
+export { PopoverOptions } from './components/popover/popover-options';
+export { RadioButton } from './components/radio/radio-button';
+export { RadioGroup } from './components/radio/radio-group';
+export { Range, RangeKnob, ClientRect } from './components/range/range';
+export { Refresher } from './components/refresher/refresher';
+export { RefresherContent } from './components/refresher/refresher-content';
+export { Scroll } from './components/scroll/scroll';
+export { Searchbar } from './components/searchbar/searchbar';
+export { Segment, SegmentButton } from './components/segment/segment';
+export { Select } from './components/select/select';
+export { ShowWhen, HideWhen, DisplayWhen } from './components/show-hide-when/show-hide-when';
+export { Slides, Slide, SlideLazy } from './components/slides/slides';
+export { Spinner } from './components/spinner/spinner';
+export { Tab } from './components/tabs/tab';
+export { Tabs } from './components/tabs/tabs';
+export { TabButton } from './components/tabs/tab-button';
+export { TabHighlight } from './components/tabs/tab-highlight';
+export { TapClick, isActivatable } from './components/tap-click/tap-click';
+export { Toast, ToastController } from './components/toast/toast';
+export { ToastOptions } from './components/toast/toast-options';
+export { Toggle } from './components/toggle/toggle';
+export { Toolbar, ToolbarBase, Header, Footer } from './components/toolbar/toolbar';
+export { ToolbarTitle } from'./components/toolbar/toolbar-title';
+export { Thumbnail } from './components/thumbnail/thumbnail';
+export { Typography } from './components/typography/typography';
+export { VirtualScroll } from './components/virtual-scroll/virtual-scroll';
+
+
+export { ActionSheetCmp } from './components/action-sheet/action-sheet-component';
+export { AlertCmp } from './components/alert/alert-component';
+export { LoadingCmp } from './components/loading/loading-component';
+export { ModalCmp } from './components/modal/modal-component';
+export { PickerCmp, PickerColumnCmp } from './components/picker/picker-component';
+export { PopoverCmp } from './components/popover/popover-component';
+export { ToastCmp } from './components/toast/toast-component';
+
+/**
+ * @private
+ * @name IONIC_DIRECTIVES
+ * @description
+ * The core Ionic directives are automatically available when you bootstrap your app
+ * with the `IonicModule`. This means if you are using custom components you do not
+ * need to import `IONIC_DIRECTIVES` as they are part of the app's default directives.
+ */
+export const IONIC_DIRECTIVES: any[] = [
+ Avatar,
+ Backdrop,
+ Badge,
+ Button,
+ Card,
+ CardContent,
+ CardHeader,
+ CardTitle,
+ Checkbox,
+ Chip,
+ Col,
+ Content,
+ DateTime,
+ Fixed,
+ Footer,
+ Grid,
+ Header,
+ HideWhen,
+ Icon,
+ Img,
+ InfiniteScroll,
+ InfiniteScrollContent,
+ IonicApp,
+ Item,
+ ItemContent,
+ ItemGroup,
+ ItemOptions,
+ ItemReorder,
+ ItemSliding,
+ Label,
+ List,
+ ListHeader,
+ Menu,
+ MenuClose,
+ MenuToggle,
+ NativeInput,
+ Nav,
+ Navbar,
+ NavPop,
+ NavPopAnchor,
+ NavPush,
+ NavPushAnchor,
+ NextInput,
+ Note,
+ Option,
+ OverlayPortal,
+ PickerColumnCmp,
+ RadioButton,
+ RadioGroup,
+ Range,
+ RangeKnob,
+ Refresher,
+ RefresherContent,
+ Reorder,
+ Row,
+ Scroll,
+ Searchbar,
+ Segment,
+ SegmentButton,
+ Select,
+ ShowWhen,
+ Slide,
+ Slides,
+ SlideLazy,
+ Spinner,
+ Tab,
+ Tabs,
+ TabButton,
+ TextArea,
+ TextInput,
+ Thumbnail,
+ Toggle,
+ Toolbar,
+ ToolbarItem,
+ ToolbarTitle,
+ Typography,
+ VirtualFooter,
+ VirtualHeader,
+ VirtualItem,
+ VirtualScroll,
+];
diff --git a/src/index.ts b/src/index.ts
index 5043478fb8..3dfbd3996a 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,12 +1,9 @@
-export { ionicBootstrap, ionicPostBootstrap } from './config/bootstrap';
export { Config } from './config/config';
-export { IONIC_DIRECTIVES } from './config/directives';
-export { ionicProviders } from './config/providers';
+export { IonicModule } from './module';
-export * from './decorators/page';
-
-export * from './components';
+export * from './directives';
+export * from './providers';
export * from './gestures/drag-gesture';
export * from './gestures/gesture';
@@ -15,7 +12,9 @@ export * from './gestures/slide-gesture';
export * from './gestures/gesture-controller';
export * from './platform/platform';
-export * from './platform/storage';
+export * from './storage/storage';
+export * from './storage/sql';
+export * from './storage/local-storage';
export * from './util/click-block';
export * from './util/events';
@@ -29,11 +28,3 @@ export * from './transitions/transition';
export * from './translation/translate';
export * from './translation/translate_pipe';
-
-// these modules don't export anything
-import './config/modes';
-import './platform/registry';
-import './animations/builtins';
-import './transitions/transition-ios';
-import './transitions/transition-md';
-import './transitions/transition-wp';
diff --git a/src/module.ts b/src/module.ts
new file mode 100644
index 0000000000..f78ce90810
--- /dev/null
+++ b/src/module.ts
@@ -0,0 +1,51 @@
+import { ModuleWithProviders, NgModule } from '@angular/core';
+import { BrowserModule } from '@angular/platform-browser';
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { HttpModule } from '@angular/http';
+
+import { ActionSheetCmp } from './components/action-sheet/action-sheet-component';
+import { AlertCmp } from './components/alert/alert-component';
+import { IONIC_DIRECTIVES } from './directives';
+import { IonicApp } from './components/app/app-root';
+import { ionicProviders } from './providers';
+import { LoadingCmp } from './components/loading/loading-component';
+import { ModalCmp } from './components/modal/modal-component';
+import { PickerCmp } from './components/picker/picker-component';
+import { PopoverCmp } from './components/popover/popover-component';
+import { ToastCmp } from './components/toast/toast-component';
+
+
+@NgModule({
+ imports: [BrowserModule, HttpModule, FormsModule, ReactiveFormsModule],
+ exports: [BrowserModule, HttpModule, FormsModule, ReactiveFormsModule, IONIC_DIRECTIVES],
+ declarations: [
+ ActionSheetCmp,
+ AlertCmp,
+ IONIC_DIRECTIVES,
+ LoadingCmp,
+ ModalCmp,
+ PickerCmp,
+ PopoverCmp,
+ ToastCmp
+ ],
+ entryComponents: [
+ ActionSheetCmp,
+ AlertCmp,
+ IonicApp,
+ LoadingCmp,
+ ModalCmp,
+ PickerCmp,
+ PopoverCmp,
+ ToastCmp
+ ]
+})
+export class IonicModule {
+
+ static forRoot(userAppRoot: any, userConfig?: any, userDeepLinkConfig?: any): ModuleWithProviders {
+ return {
+ ngModule: IonicModule,
+ providers: ionicProviders(userAppRoot, userConfig, userDeepLinkConfig)
+ };
+ }
+
+}
diff --git a/src/providers.ts b/src/providers.ts
new file mode 100644
index 0000000000..f5f81b96ae
--- /dev/null
+++ b/src/providers.ts
@@ -0,0 +1,118 @@
+import { ANALYZE_FOR_ENTRY_COMPONENTS } from '@angular/core';
+import { HAMMER_GESTURE_CONFIG } from '@angular/platform-browser';
+
+
+/**
+ * Import Providers
+ */
+import { ActionSheetController } from './components/action-sheet/action-sheet';
+import { AlertController } from './components/alert/alert';
+import { App } from './components/app/app';
+import { provideConfig } from './config/config';
+import { provideEvents } from './util/events';
+import { FeatureDetect } from './util/feature-detect';
+import { Form } from './util/form';
+import { GestureController } from './gestures/gesture-controller';
+import { IonicGestureConfig } from './gestures/gesture-config';
+import { Keyboard } from './util/keyboard';
+import { LoadingController } from './components/loading/loading';
+import { MenuController } from './components/menu/menu-controller';
+import { ModalController } from './components/modal/modal';
+import { PickerController } from './components/picker/picker';
+import { providePlatform, UserAgent, UserNavigatorPlatform, UserDir, UserLang } from './platform/platform';
+import { PopoverController } from './components/popover/popover';
+import { provideDeepLinker } from './navigation/deep-linker';
+import { provideQueryParams, UserUrl } from './platform/query-params';
+import { TapClick, provideTapClick } from './components/tap-click/tap-click';
+import { ToastController } from './components/toast/toast';
+import { Translate } from './translation/translate';
+import { TransitionController } from './transitions/transition-controller';
+import { UserRoot } from './components/app/app-root';
+
+
+/**
+ * Export Providers
+ */
+export { DeepLinker, provideDeepLinker } from './navigation/deep-linker';
+export { NavController } from './navigation/nav-controller';
+export { NavParams } from './navigation/nav-params';
+export { NavLink, NavOptions, DeepLink, DeepLinkConfig } from './navigation/nav-util';
+export { ViewController } from './navigation/view-controller';
+
+
+/**
+ * @private
+ * ionicProviders used by IonicModule
+ */
+export function ionicProviders(userRoot: any, userConfig?: any, userDeepLinkConfig?: any): any[] {
+ return [
+ { provide: ANALYZE_FOR_ENTRY_COMPONENTS, useValue: userRoot, multi: true },
+ { provide: HAMMER_GESTURE_CONFIG, useClass: IonicGestureConfig },
+ { provide: UserAgent, useFactory: getWindowUserAgent },
+ { provide: UserDir, useFactory: getDocumentDir },
+ { provide: UserLang, useFactory: getDocumentLang },
+ { provide: UserNavigatorPlatform, useFactory: getWindowPlatform },
+ { provide: UserRoot, useValue: userRoot },
+ { provide: UserUrl, useFactory: getWindowLocation },
+
+ provideConfig(userConfig),
+ provideDeepLinker(userDeepLinkConfig),
+ provideEvents(),
+ providePlatform(),
+ provideQueryParams(),
+ provideTapClick(),
+
+ ActionSheetController,
+ AlertController,
+ App,
+ Form,
+ FeatureDetect,
+ GestureController,
+ Keyboard,
+ LoadingController,
+ MenuController,
+ ModalController,
+ PickerController,
+ PopoverController,
+ TapClick,
+ ToastController,
+ Translate,
+ TransitionController
+ ];
+}
+
+
+/**
+ * @private
+ */
+export function getWindowUserAgent() {
+ return window && window.navigator.userAgent;
+}
+
+/**
+ * @private
+ */
+export function getWindowPlatform() {
+ return window && window.navigator.platform;
+}
+
+/**
+ * @private
+ */
+export function getWindowLocation() {
+ return window && window.location.href;
+}
+
+/**
+ * @private
+ */
+export function getDocumentDir() {
+ return document && document.documentElement.dir;
+}
+
+/**
+ * @private
+ */
+export function getDocumentLang() {
+ return document && document.documentElement.lang;
+}
diff --git a/src/util/click-block.ts b/src/util/click-block.ts
index 3c4b19ab89..632db61160 100644
--- a/src/util/click-block.ts
+++ b/src/util/click-block.ts
@@ -11,7 +11,7 @@ const DEFAULT_EXPIRE = 330;
* @private
*/
@Directive({
- selector: 'click-block'
+ selector: '.click-block'
})
export class ClickBlock {
private _tmrId: number;
@@ -24,7 +24,7 @@ export class ClickBlock {
private elementRef: ElementRef,
private renderer: Renderer
) {
- app.clickBlock = this;
+ app._clickBlock = this;
this.isEnabled = config.getBoolean('clickBlock', true);
}
diff --git a/src/util/feature-detect.ts b/src/util/feature-detect.ts
index 7f6ee48887..d281a6a9ba 100644
--- a/src/util/feature-detect.ts
+++ b/src/util/feature-detect.ts
@@ -1,58 +1,51 @@
+import { IonicApp } from '../components/app/app-root';
+
export class FeatureDetect {
- private _results: {[featureName: string]: boolean} = {};
+ private _r: {[featureName: string]: boolean} = {};
- run(window: Window, document: Document) {
+ test(appRoot: IonicApp) {
for (let name in featureDetects) {
- this._results[name] = featureDetects[name](window, document, document.body);
+ this._r[name] = !!featureDetects[name].test();
+ if (this._r[name]) {
+ appRoot.setElementClass(name, true);
+ }
}
+ featureDetects = null;
}
has(featureName: string): boolean {
- return !!this._results[featureName];
+ return !!this._r[featureName];
}
- static add(name: string, fn: any) {
- featureDetects[name] = fn;
+ static add(name: string, test: any) {
+ // feature detection tests should only run on client side
+ if ((this).window) {
+ featureDetects[name] = new test();
+ }
}
}
-let featureDetects: {[featureName: string]: Function} = {};
+let featureDetects: {[featureName: string]: FeatureDetectTest} = {};
-FeatureDetect.add('hairlines', function(window: Window, document: Document, body: HTMLBodyElement): boolean {
- /**
- * Hairline Shim
- * Add the "hairline" CSS class name to the body tag
- * if the browser supports subpixels.
- */
- let canDo = false;
- if (window.devicePixelRatio >= 2) {
- var hairlineEle = document.createElement('div');
- hairlineEle.style.border = '.5px solid transparent';
- body.appendChild(hairlineEle);
+export abstract class FeatureDetectTest {
+ abstract test(): boolean;
+}
- if (hairlineEle.offsetHeight === 1) {
- body.classList.add('hairlines');
- canDo = true;
- }
- body.removeChild(hairlineEle);
+
+/**
+* backdrop-filter Test
+* Checks if css backdrop-filter is implemented by the browser.
+*/
+export class BackdropFilterTest implements FeatureDetectTest {
+
+ test() {
+ const styles = document.documentElement.style;
+ return !!(styles['backdrop-filter'] !== undefined || styles['-webkit-backdrop-filter'] !== undefined);
}
- return canDo;
-});
-FeatureDetect.add('backdrop-filter', function(window: Window, document: Document, body: HTMLBodyElement): boolean {
- /**
- * backdrop-filter Shim
- * Checks if css backdrop-filter is implemented by the browser.
- */
- let styles = body.style;
- let backdrop = styles['backdrop-filter'] !== undefined ||
- styles['-webkit-backdrop-filter'] !== undefined;
- if (backdrop) {
- body.classList.add('backdrop-filter');
- }
- return backdrop;
-});
+}
+FeatureDetect.add('backdrop-filter', BackdropFilterTest);