diff --git a/src/components/badge/badge.ios.scss b/src/components/badge/badge.ios.scss index 4bb667076c..bcc0ebf8ce 100644 --- a/src/components/badge/badge.ios.scss +++ b/src/components/badge/badge.ios.scss @@ -16,11 +16,9 @@ $badge-ios-text-color: color-contrast($colors-ios, $badge-ios-background .badge-ios { - @include host-context() { - border-radius: $badge-ios-border-radius; - color: $badge-ios-text-color; - background-color: $badge-ios-background-color; - } + border-radius: $badge-ios-border-radius; + color: $badge-ios-text-color; + background-color: $badge-ios-background-color; } @@ -30,10 +28,8 @@ $badge-ios-text-color: color-contrast($colors-ios, $badge-ios-background @each $color-name, $color-base, $color-contrast in get-colors($colors-ios) { .badge-ios-#{$color-name} { - @include host-context() { - color: $color-contrast; - background-color: $color-base; - } + color: $color-contrast; + background-color: $color-base; } } diff --git a/src/components/badge/badge.md.scss b/src/components/badge/badge.md.scss index ded2fd56f7..ac9680a815 100644 --- a/src/components/badge/badge.md.scss +++ b/src/components/badge/badge.md.scss @@ -16,20 +16,9 @@ $badge-md-text-color: color-contrast($colors-md, $badge-md-backgro .badge-md { - @include host-context() { - border-radius: $badge-md-border-radius; - color: $badge-md-text-color; - background-color: $badge-md-background-color; - } -} - - -.badge-md { - @include host-context() { - border-radius: $badge-md-border-radius; - color: $badge-md-text-color; - background-color: $badge-md-background-color; - } + border-radius: $badge-md-border-radius; + color: $badge-md-text-color; + background-color: $badge-md-background-color; } @@ -39,10 +28,8 @@ $badge-md-text-color: color-contrast($colors-md, $badge-md-backgro @each $color-name, $color-base, $color-contrast in get-colors($colors-md) { .badge-md-#{$color-name} { - @include host-context() { - color: $color-contrast; - background-color: $color-base; - } + color: $color-contrast; + background-color: $color-base; } } diff --git a/src/components/badge/badge.scss b/src/components/badge/badge.scss index 1684f3749f..b17d1b13ad 100644 --- a/src/components/badge/badge.scss +++ b/src/components/badge/badge.scss @@ -12,31 +12,25 @@ $badge-font-weight: bold !default; ion-badge { - @include host() { - display: inline-block; - visibility: inherit !important; - contain: content; - } + display: inline-block; + visibility: inherit !important; + contain: content; } .badge { - @include host() { - padding: 3px 8px; + padding: 3px 8px; - min-width: 10px; + min-width: 10px; - font-size: $badge-font-size; - font-weight: $badge-font-weight; - line-height: 1; + font-size: $badge-font-size; + font-weight: $badge-font-weight; + line-height: 1; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - } + text-align: center; + white-space: nowrap; + vertical-align: baseline; } ion-badge:empty { - @include host(':empty') { - display: none; - } + display: none; } \ No newline at end of file diff --git a/src/components/badge/badge.ts b/src/components/badge/badge.ts index 7e604444a0..c332885517 100644 --- a/src/components/badge/badge.ts +++ b/src/components/badge/badge.ts @@ -7,12 +7,11 @@ import { Component, h, Ionic } from '../index'; ios: 'badge.ios.scss', md: 'badge.md.scss', wp: 'badge.wp.scss' - } + }, + shadow: false }) export class Badge { render() { - return h(this, Ionic.theme(this, 'badge'), - h('slot') - ); + return h(this, Ionic.theme(this, 'badge')); } } diff --git a/src/components/badge/badge.wp.scss b/src/components/badge/badge.wp.scss index 87ab16a215..b860dc5a87 100644 --- a/src/components/badge/badge.wp.scss +++ b/src/components/badge/badge.wp.scss @@ -16,11 +16,9 @@ $badge-wp-text-color: color-contrast($colors-wp, $badge-wp-backgro .badge-wp { - @include host-context() { - border-radius: $badge-wp-border-radius; - color: $badge-wp-text-color; - background-color: $badge-wp-background-color; - } + border-radius: $badge-wp-border-radius; + color: $badge-wp-text-color; + background-color: $badge-wp-background-color; } @@ -30,10 +28,8 @@ $badge-wp-text-color: color-contrast($colors-wp, $badge-wp-backgro @each $color-name, $color-base, $color-contrast in get-colors($colors-wp) { .badge-wp-#{$color-name} { - @include host-context() { - color: $color-contrast; - background-color: $color-base; - } + color: $color-contrast; + background-color: $color-base; } } diff --git a/src/components/card-content/card-content.scss b/src/components/card-content/card-content.scss index 6c95458857..37e14e36da 100644 --- a/src/components/card-content/card-content.scss +++ b/src/components/card-content/card-content.scss @@ -4,8 +4,7 @@ // Card Content // -------------------------------------------------- -ion-card-content, -:host { +ion-card-content { display: block; visibility: inherit !important; } diff --git a/src/components/card-content/card-content.ts b/src/components/card-content/card-content.ts index 4c85e2b82a..bbdbb93959 100644 --- a/src/components/card-content/card-content.ts +++ b/src/components/card-content/card-content.ts @@ -7,12 +7,11 @@ import { Component, h, Ionic } from '../index'; ios: 'card-content.ios.scss', md: 'card-content.md.scss', wp: 'card-content.wp.scss' - } + }, + shadow: false }) export class CardContent { render() { - return h(this, Ionic.theme(this, 'card-content'), - h('slot') - ); + return h(this, Ionic.theme(this, 'card-content')); } } diff --git a/src/components/card-header/card-header.scss b/src/components/card-header/card-header.scss index 9106d52f39..62ab23b6fd 100644 --- a/src/components/card-header/card-header.scss +++ b/src/components/card-header/card-header.scss @@ -5,8 +5,7 @@ // -------------------------------------------------- -ion-card-header, -:host { +ion-card-header { display: block; overflow: hidden; visibility: inherit !important; diff --git a/src/components/card-header/card-header.ts b/src/components/card-header/card-header.ts index db89db1726..2a379438b9 100644 --- a/src/components/card-header/card-header.ts +++ b/src/components/card-header/card-header.ts @@ -7,12 +7,11 @@ import { Component, h, Ionic } from '../index'; ios: 'card-header.ios.scss', md: 'card-header.md.scss', wp: 'card-header.wp.scss' - } + }, + shadow: false }) export class CardHeader { render() { - return h(this, Ionic.theme(this, 'card-header'), - h('slot') - ); + return h(this, Ionic.theme(this, 'card-header')); } } diff --git a/src/components/card-title/card-title.scss b/src/components/card-title/card-title.scss index 3f7dcee4b1..b5b34b109a 100644 --- a/src/components/card-title/card-title.scss +++ b/src/components/card-title/card-title.scss @@ -4,8 +4,7 @@ // Card Title // -------------------------------------------------- -ion-card-title, -:host { +ion-card-title { display: block; visibility: inherit !important; } diff --git a/src/components/card-title/card-title.ts b/src/components/card-title/card-title.ts index 8e6b461dfb..0ef311ceff 100644 --- a/src/components/card-title/card-title.ts +++ b/src/components/card-title/card-title.ts @@ -7,12 +7,11 @@ import { Component, h, Ionic } from '../index'; ios: 'card-title.ios.scss', md: 'card-title.md.scss', wp: 'card-title.wp.scss' - } + }, + shadow: false }) export class CardTitle { render() { - return h(this, Ionic.theme(this, 'card-title'), - h('slot') - ); + return h(this, Ionic.theme(this, 'card-title')); } } diff --git a/src/components/card/card.scss b/src/components/card/card.scss index e75c5208ad..46bcdc36a7 100755 --- a/src/components/card/card.scss +++ b/src/components/card/card.scss @@ -4,8 +4,7 @@ // -------------------------------------------------- -ion-card, -:host { +ion-card { display: block; overflow: hidden; visibility: inherit !important; diff --git a/src/components/card/card.ts b/src/components/card/card.ts index a9006db4b1..8463e9e1d6 100644 --- a/src/components/card/card.ts +++ b/src/components/card/card.ts @@ -7,12 +7,11 @@ import { Component, h, Ionic } from '../index'; ios: 'card.ios.scss', md: 'card.md.scss', wp: 'card.wp.scss' - } + }, + shadow: false }) export class Card { render() { - return h(this, Ionic.theme(this, 'card'), - h('slot') - ); + return h(this, Ionic.theme(this, 'card')); } } diff --git a/src/components/gesture/gesture.ts b/src/components/gesture/gesture.ts index 3c96e95a5c..1e7adbcf3c 100644 --- a/src/components/gesture/gesture.ts +++ b/src/components/gesture/gesture.ts @@ -1,5 +1,5 @@ import { applyStyles, getElementReference, pointerCoordX, pointerCoordY } from '../../util/helpers'; -import { Component, Listen, Ionic, Prop } from '../index'; +import { Component, Ionic, Listen, Prop } from '../index'; import { GestureCallback, GestureDetail } from '../../util/interfaces'; import { GestureController, GestureDelegate } from './gesture-controller'; import { PanRecognizer } from './recognizers'; @@ -25,7 +25,7 @@ export class Gesture { @Prop() direction: string = 'x'; @Prop() gestureName: string = ''; @Prop() gesturePriority: number = 0; - @Prop() listenOn: string = 'child'; + @Prop() attachTo: string = 'child'; @Prop() maxAngle: number = 40; @Prop() threshold: number = 20; @Prop() type: string = 'pan'; @@ -52,11 +52,11 @@ export class Gesture { this.hasPress = (types.indexOf('press') > -1); if (this.pan || this.hasPress) { - Ionic.listener.enable(this, 'touchstart', true, this.listenOn); - Ionic.listener.enable(this, 'mousedown', true, this.listenOn); + Ionic.listener.enable(this, 'touchstart', true, this.attachTo); + Ionic.listener.enable(this, 'mousedown', true, this.attachTo); Ionic.dom.write(() => { - applyStyles(getElementReference(this.$el, this.listenOn), GESTURE_INLINE_STYLES); + applyStyles(getElementReference(this.$el, this.attachTo), GESTURE_INLINE_STYLES); }); } } diff --git a/src/components/index.ts b/src/components/index.ts index 7113f8a1bf..9628ce4a15 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -10,6 +10,8 @@ export declare const Ionic: interfaces.Ionic; export declare const Listen: interfaces.ListenDecorator; +export declare const Method: interfaces.MethodDecorator; + export declare const Prop: interfaces.PropDecorator; export declare const Watch: interfaces.WatchDecorator; diff --git a/src/components/slides/slides.ts b/src/components/slides/slides.ts index 65545c3571..6feb1fc131 100644 --- a/src/components/slides/slides.ts +++ b/src/components/slides/slides.ts @@ -529,7 +529,7 @@ export class Slides { /** * @hidden */ - ngOnDestroy() { + ionViewWillUnload() { this._init = false; this.swiper.destroy(true, true); diff --git a/src/components/toggle/toggle.ts b/src/components/toggle/toggle.ts index 286bc26d15..b40ef77753 100644 --- a/src/components/toggle/toggle.ts +++ b/src/components/toggle/toggle.ts @@ -1,5 +1,5 @@ import { BooleanInputComponent, GestureDetail } from '../../util/interfaces'; -import { Component, h, Ionic, Listen, Prop, Watch } from '../index'; +import { Component, h, Ionic, Listen, Method, Prop, Watch } from '../index'; @Component({ @@ -28,18 +28,18 @@ export class Toggle implements BooleanInputComponent { } - canStart() { + private canStart() { return !this.disabled; } - onDragStart(detail: GestureDetail) { + private onDragStart(detail: GestureDetail) { this.startX = detail.startX; this.fireFocus(); } - onDragMove(detail: GestureDetail) { + private onDragMove(detail: GestureDetail) { if (this.checked) { if (detail.currentX + 15 < this.startX) { this.checked = false; @@ -55,7 +55,7 @@ export class Toggle implements BooleanInputComponent { } - onDragEnd(detail: GestureDetail) { + private onDragEnd(detail: GestureDetail) { if (this.checked) { if (detail.startX + 4 > detail.currentX) { this.checked = false; @@ -78,12 +78,13 @@ export class Toggle implements BooleanInputComponent { ev.preventDefault(); } - + @Method() toggle() { if (!this.disabled) { this.checked = !this.checked; this.fireFocus(); } + return this.checked; } @@ -122,7 +123,7 @@ export class Toggle implements BooleanInputComponent { 'type': 'pan,press', 'direction': 'x', 'threshold': 20, - 'listenOn': 'parent' + 'attachTo': 'parent' } }), [ diff --git a/src/themes/ionic.mixins.scss b/src/themes/ionic.mixins.scss index e712475f1e..5063b48a6a 100644 --- a/src/themes/ionic.mixins.scss +++ b/src/themes/ionic.mixins.scss @@ -160,7 +160,6 @@ // Based on a selector, apply the content to that selector and the :host @mixin host($selector: null) { - @debug $selector; @at-root { @if ($selector) { :host(#{$selector}), diff --git a/src/util/helpers.ts b/src/util/helpers.ts index 9dadcf6c03..38d3c080b4 100644 --- a/src/util/helpers.ts +++ b/src/util/helpers.ts @@ -108,3 +108,20 @@ export function applyStyles(elm: HTMLElement, styles: {[styleProp: string]: stri (elm.style)[styleProps[i]] = styles[styleProps[i]]; } } + +export function asyncFn(queue: Function[], cb: Function) { + if (queue === null) { + cb(); + } else { + queue.push(cb); + } +} + +export function drainAsyncFns(queue: Function[]): any { + if (queue) { + for (var i = 0; i < queue.length; i++) { + queue[i](); + } + } + return null; +} diff --git a/src/util/interfaces.ts b/src/util/interfaces.ts index 70cd05e7fb..520acf7d68 100644 --- a/src/util/interfaces.ts +++ b/src/util/interfaces.ts @@ -3,6 +3,7 @@ export interface Ionic { emit: EventEmit; listener: { enable: EventListenerEnable; + add: AddEventListenerApi; }; theme: IonicTheme; controllers: { @@ -10,6 +11,69 @@ export interface Ionic { }; dom: DomControllerApi; config: ConfigApi; + modal: ModalControllerApi; + Animation: Animation; +} + + +export interface IonicGlobal { + staticDir?: string; + components?: LoadComponents; + loadComponents?: (coreVersion: number, bundleId: string, modulesImporterFn: ModulesImporterFn, cmp0?: ComponentModeData, cmp1?: ComponentModeData, cmp2?: ComponentModeData) => void; + eventNameFn?: (eventName: string) => string; + config?: Object; + ConfigCtrl?: ConfigApi; + DomCtrl?: DomControllerApi; + NextTickCtrl?: NextTickApi; + Animation: any; +} + + +export interface ModalControllerApi { + create: (component: string, params?: any, opts?: ModalOptions) => Promise; +} + + +export interface ModalControllerInternalApi extends ModalControllerApi { + _create?: any[]; +} + + +export interface Modal { + component: string; + id: string; + style?: { + zIndex: number; + }; + showBackdrop: boolean; + enableBackdropDismiss: boolean; + enterAnimation: AnimationBuilder; + exitAnimation: AnimationBuilder; + cssClass: string; + params: any; + present: (done?: Function) => void; + dismiss: (done?: Function) => void; +} + + +export interface ModalOptions { + showBackdrop?: boolean; + enableBackdropDismiss?: boolean; + enterAnimation?: AnimationBuilder; + exitAnimation?: AnimationBuilder; + cssClass?: string; +} + + +export interface ModalEvent extends Event { + detail: { + modal: Modal; + }; +} + + +export interface AddEventListenerApi { + (elm: HTMLElement|HTMLDocument|Window, eventName: string, cb: (ev?: any) => void, opts?: ListenOptions): Function; } @@ -27,7 +91,7 @@ export interface CustomEventOptions { export interface EventListenerEnable { - (instance: any, eventName: string, enabled: boolean, listenOn?: string): void; + (instance: any, eventName: string, enabled: boolean, attachTo?: string): void; } @@ -100,18 +164,6 @@ export interface ContentDimensions { } -export interface IonicGlobal { - staticDir?: string; - components?: LoadComponents; - loadComponents?: {(bundleId: string, modulesImporterFn: ModulesImporterFn, cmp0?: ComponentModeData, cmp1?: ComponentModeData, cmp2?: ComponentModeData): void}; - eventNameFn?: {(eventName: string): string}; - config?: Object; - ConfigCtrl?: ConfigApi; - DomCtrl?: DomControllerApi; - NextTickCtrl?: NextTickApi; -} - - export interface NextTickApi { nextTick: NextTick; } @@ -150,9 +202,9 @@ export interface ComponentModeData { [0]: string; /** - * component class name (Badge) + * methods */ - [1]: string; + [1]: Methods; /** * listeners @@ -245,22 +297,29 @@ export interface PropOptions { } -export interface Props { - [propName: string]: PropOptions; +export interface PropMeta { + propName?: string; + propType?: any; } +export type Methods = string[]; + + +export interface MethodDecorator { + (opts?: MethodOptions): any; +} + + +export interface MethodOptions {} + + export interface ListenDecorator { - (eventName: string, opts?: ListenOpts): any; + (eventName: string, opts?: ListenOptions): any; } -export interface ComponentMetaListeners { - [methodName: string]: ListenOpts; -} - - -export interface ListenOpts { +export interface ListenOptions { eventName?: string; capture?: boolean; passive?: boolean; @@ -268,6 +327,11 @@ export interface ListenOpts { } +export interface ListenMeta extends ListenOptions { + methodName?: string; +} + + export interface WatchDecorator { (propName: string): any; } @@ -278,8 +342,8 @@ export interface WatchOpts { } -export interface Watchers { - [propName: string]: WatchOpts; +export interface WatchMeta extends WatchOpts { + propName?: string; } @@ -297,18 +361,21 @@ export interface ConfigApi { export interface ComponentMeta { tag?: string; - props?: Props; - listeners?: ComponentMetaListeners; - watchers?: Watchers; + methods?: Methods; + props?: PropMeta[]; + listeners?: ListenMeta[]; + watchers?: WatchMeta[]; + modes: ModeMeta[]; shadow?: boolean; + namedSlots?: string[]; obsAttrs?: string[]; componentModule?: any; - modes: {[modeName: string]: ComponentMode}; priority?: 'high'|'low'; } -export interface ComponentMode { +export interface ModeMeta { + modeName?: string; bundleId?: string; styles?: string; styleUrls?: string[]; @@ -317,10 +384,10 @@ export interface ComponentMode { export interface Component { - ionViewDidLoad?: {(): void}; - ionViewWillUnload?: {(): void}; + ionViewDidLoad?: () => void; + ionViewWillUnload?: () => void; - render?: {(): VNode}; + render?: () => VNode; mode?: string; color?: string; @@ -328,8 +395,10 @@ export interface Component { $el?: ProxyElement; $meta?: ComponentMeta; $listeners?: ComponentActiveListeners; + $watchers?: ComponentActiveWatchers; $root?: HTMLElement | ShadowRoot; $vnode?: VNode; + $values?: ComponentActiveValues; [memberName: string]: any; } @@ -340,19 +409,27 @@ export interface ComponentActiveListeners { } +export type ComponentActiveWatchers = Function[]; + + +export interface ComponentActiveValues { + [propName: string]: any; +} + + export interface BaseInputComponent extends Component { disabled: boolean; hasFocus: boolean; value: string; - fireFocus: {(): void}; - fireBlur: {(): void}; + fireFocus: () => void; + fireBlur: () => void; } export interface BooleanInputComponent extends BaseInputComponent { checked: boolean; - toggle: {(ev: UIEvent): void}; + toggle: (ev: UIEvent) => void; } @@ -367,22 +444,28 @@ export interface ComponentRegistry { export interface ProxyElement extends HTMLElement { - connectedCallback: {(): void}; - attributeChangedCallback: {(attrName: string, oldVal: string, newVal: string, namespace: string): void}; - disconnectedCallback: {(): void}; + connectedCallback: () => void; + attributeChangedCallback: (attrName: string, oldVal: string, newVal: string, namespace: string) => void; + disconnectedCallback: () => void; + $queueUpdate: () => void; $queued?: boolean; $instance?: Component; + $hostContent?: HostContentNodes; + $tmpDisconnected?: boolean; [memberName: string]: any; } +export type QueueHandlerId = number; + + export type Side = 'left' | 'right' | 'start' | 'end'; export interface RendererApi { - (oldVnode: VNode | Element, vnode: VNode, manualSlotProjection?: boolean): VNode; + (oldVnode: VNode | Element, vnode: VNode, hostContentNodes?: HostContentNodes): VNode; } @@ -411,6 +494,12 @@ export interface VNode { } +export interface HostContentNodes { + $defaultSlot: Node[]; + $namedSlots?: {[slotName: string]: Node[]}; +} + + export interface VNodeData { props?: any; attrs?: any; @@ -418,7 +507,7 @@ export interface VNodeData { style?: any; dataset?: any; on?: any; - attachData?: any; + ref?: (elm: any) => void; vkey?: Key; vns?: string; // for SVGs [key: string]: any; // for any other 3rd party module @@ -428,7 +517,7 @@ export interface VNodeData { export interface PlatformApi { registerComponent: (tag: string, data: any[]) => ComponentMeta; getComponentMeta: (tag: string) => ComponentMeta; - loadComponent: (bundleId: string, priority: string, cb: Function) => void; + loadBundle: (bundleId: string, priority: string, cb: Function) => void; nextTick: NextTick; isElement: (node: Node) => node is Element; @@ -463,3 +552,92 @@ export interface ServerInitConfig { staticDir: string; config?: Object; } + + +export interface Animation { + new(elm?: Node|Node[]|NodeList): Animation; + addChildAnimation: (childAnimation: Animation) => Animation; + addElement: (elm: Node|Node[]|NodeList) => Animation; + afterAddClass: (className: string) => Animation; + afterClearStyles: (propertyNames: string[]) => Animation; + afterRemoveClass: (className: string) => Animation; + afterStyles: (styles: { [property: string]: any; }) => Animation; + beforeAddClass: (className: string) => Animation; + beforeClearStyles: (propertyNames: string[]) => Animation; + beforeRemoveClass: (className: string) => Animation; + beforeStyles: (styles: { [property: string]: any; }) => Animation; + destroy: () => void; + duration: (milliseconds: number) => Animation; + easing: (name: string) => Animation; + from: (prop: string, val: any) => Animation; + fromTo: (prop: string, fromVal: any, toVal: any, clearProperyAfterTransition?: boolean) => Animation; + hasCompleted: boolean; + isPlaying: boolean; + onFinish: (callback: (animation?: Animation) => void, opts?: {oneTimeCallback: boolean, clearExistingCallacks: boolean}) => Animation; + play: (opts?: PlayOptions) => void; + progressEnd: (shouldComplete: boolean, currentStepValue: number, dur: number) => void; + progressStep: (stepValue: number) => void; + progressStart: () => void; + reverse: (shouldReverse?: boolean) => Animation; + stop: (stepValue?: number) => void; + to: (prop: string, val: any, clearProperyAfterTransition?: boolean) => Animation; +} + + +export interface AnimationBuilder { + (elm?: HTMLElement): Animation; +} + + +export interface AnimationOptions { + animation?: string; + duration?: number; + easing?: string; + direction?: string; + isRTL?: boolean; + ev?: any; +} + + +export interface PlayOptions { + duration?: number; + promise?: boolean; +} + + +export interface EffectProperty { + effectName: string; + trans: boolean; + wc?: string; + to?: EffectState; + from?: EffectState; + [state: string]: any; +} + + +export interface EffectState { + val: any; + num: number; + effectUnit: string; +} + + +export interface RequestIdleCallback { + (callback: IdleCallback): number; +} + + +export interface IdleCallback { + (deadline: IdleDeadline, options?: IdleOptions): void; +} + + +export interface IdleDeadline { + didTimeout: boolean; + timeRemaining: () => number; +} + + +export interface IdleOptions { + timeout?: number; +}