diff --git a/packages/core/src/components/toast-controller/toast-controller.tsx b/packages/core/src/components/toast-controller/toast-controller.tsx index aaa94be9f1..172ad0c3d4 100644 --- a/packages/core/src/components/toast-controller/toast-controller.tsx +++ b/packages/core/src/components/toast-controller/toast-controller.tsx @@ -1,5 +1,5 @@ import { Component, Listen, Method } from '@stencil/core'; -import { Toast, ToastEvent, ToastOptions } from '../../index'; +import { ToastEvent, ToastOptions } from '../../index'; @Component({ tag: 'ion-toast-controller' @@ -7,10 +7,10 @@ import { Toast, ToastEvent, ToastOptions } from '../../index'; export class ToastController { private ids = 0; private toastResolves: { [toastId: string]: Function } = {}; - private toasts: Toast[] = []; + private toasts: HTMLIonToastElement[] = []; @Method() - create(opts?: ToastOptions) { + create(opts?: ToastOptions): Promise { // create ionic's wrapping ion-toast component const toast = document.createElement('ion-toast'); const id = this.ids++; @@ -28,14 +28,14 @@ export class ToastController { appRoot.appendChild(toast as any); // store the resolve function to be called later up when the toast loads - return new Promise(resolve => { + return new Promise(resolve => { this.toastResolves[toast.toastId] = resolve; }); } @Listen('body:ionToastDidLoad') protected didLoad(ev: ToastEvent) { - const toast = ev.detail.toast; + const toast = ev.target as HTMLIonToastElement; const toastResolve = this.toastResolves[toast.toastId]; if (toastResolve) { toastResolve(toast); @@ -45,12 +45,12 @@ export class ToastController { @Listen('body:ionToastWillPresent') protected willPresent(ev: ToastEvent) { - this.toasts.push(ev.detail.toast); + this.toasts.push(ev.target as HTMLIonToastElement); } @Listen('body:ionToastWillDismiss, body:ionToastDidUnload') protected willDismiss(ev: ToastEvent) { - const index = this.toasts.indexOf(ev.detail.toast); + const index = this.toasts.indexOf(ev.target as HTMLIonToastElement); if (index > -1) { this.toasts.splice(index, 1); } diff --git a/packages/core/src/components/toast/test/basic/index.html b/packages/core/src/components/toast/test/basic/index.html index 5c62259005..d7b5672c8a 100644 --- a/packages/core/src/components/toast/test/basic/index.html +++ b/packages/core/src/components/toast/test/basic/index.html @@ -59,22 +59,22 @@ diff --git a/packages/core/src/components/toast/toast.tsx b/packages/core/src/components/toast/toast.tsx index 86eca58643..b008b56074 100644 --- a/packages/core/src/components/toast/toast.tsx +++ b/packages/core/src/components/toast/toast.tsx @@ -1,5 +1,14 @@ -import { Component, Element, Event, EventEmitter, Listen, Prop } from '@stencil/core'; -import { Animation, AnimationBuilder, AnimationController, Config, CssClassMap } from '../../index'; +import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; +import { + Animation, + AnimationBuilder, + AnimationController, + Config, + CssClassMap, + OverlayDismissEvent, + OverlayDismissEventDetail +} from '../../index'; +import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; import { createThemedClasses } from '../../utils/theme'; @@ -30,32 +39,32 @@ export class Toast { /** * @output {ToastEvent} Emitted after the toast has loaded. */ - @Event() ionToastDidLoad: EventEmitter; + @Event() ionToastDidLoad: EventEmitter; /** * @output {ToastEvent} Emitted after the toast has presented. */ - @Event() ionToastDidPresent: EventEmitter; + @Event() ionToastDidPresent: EventEmitter; /** * @output {ToastEvent} Emitted before the toast has presented. */ - @Event() ionToastWillPresent: EventEmitter; + @Event() ionToastWillPresent: EventEmitter; /** * @output {ToastEvent} Emitted before the toast has dismissed. */ - @Event() ionToastWillDismiss: EventEmitter; + @Event() ionToastWillDismiss: EventEmitter; /** * @output {ToastEvent} Emitted after the toast has dismissed. */ - @Event() ionToastDidDismiss: EventEmitter; + @Event() ionToastDidDismiss: EventEmitter; /** * @output {ToastEvent} Emitted after the toast has unloaded. */ - @Event() ionToastDidUnload: EventEmitter; + @Event() ionToastDidUnload: EventEmitter; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ context: 'config' }) config: Config; @@ -69,73 +78,73 @@ export class Toast { @Prop() position: string; @Prop() translucent: boolean = false; @Prop() toastId: string; + @Prop() animate: boolean; @Prop() enterAnimation: AnimationBuilder; @Prop() leaveAnimation: AnimationBuilder; + @Method() present() { - return new Promise(resolve => { - this._present(resolve); - }); - } - - private _present(resolve: Function) { if (this.animation) { this.animation.destroy(); this.animation = null; } - this.ionToastWillPresent.emit({ toast: this }); + this.ionToastWillPresent.emit(); // get the user's animation fn if one was provided const animationBuilder = this.enterAnimation || this.config.get('toastEnter', this.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation); // build the animation and kick it off - this.animationCtrl.create(animationBuilder, this.el, this.position).then(animation => { + return this.animationCtrl.create(animationBuilder, this.el).then(animation => { this.animation = animation; - - animation.onFinish((a: any) => { - a.destroy(); - this.componentDidEnter(); - resolve(); - }).play(); + if (!this.animate) { + // if the duration is 0, it won't actually animate I don't think + // TODO - validate this + this.animation = animation.duration(0); + } + return playAnimationAsync(animation); + }).then((animation) => { + animation.destroy(); + this.componentDidEnter(); }); } - dismiss() { + @Method() + dismiss(data?: any, role?: string) { if (this.animation) { this.animation.destroy(); this.animation = null; } - return new Promise(resolve => { - this.ionToastWillDismiss.emit({ toast: this }); - // get the user's animation fn if one was provided - const animationBuilder = this.leaveAnimation || this.config.get('toastLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation); + this.ionToastWillDismiss.emit({ + data, + role + }); - // build the animation and kick it off - this.animationCtrl.create(animationBuilder, this.el, this.position).then(animation => { - this.animation = animation; + const animationBuilder = this.leaveAnimation || this.config.get('toastLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation); - animation.onFinish((a: any) => { - a.destroy(); - this.ionToastDidDismiss.emit({ toast: this }); - - Context.dom.write(() => { - this.el.parentNode.removeChild(this.el); - }); - - resolve(); - }).play(); + return this.animationCtrl.create(animationBuilder, this.el).then(animation => { + this.animation = animation; + return playAnimationAsync(animation); + }).then((animation) => { + animation.destroy(); + return domControllerAsync(Context.dom.write, () => { + this.el.parentNode.removeChild(this.el); + }); + }).then(() => { + this.ionToastDidDismiss.emit({ + data, + role }); }); } componentDidLoad() { - this.ionToastDidLoad.emit({ toast: this }); + this.ionToastDidLoad.emit(); } componentDidEnter() { - this.ionToastDidPresent.emit({ toast: this }); + this.ionToastDidPresent.emit(); if (this.duration) { setTimeout(() => { this.dismiss(); @@ -144,7 +153,7 @@ export class Toast { } componentDidUnload() { - this.ionToastDidUnload.emit({ toast: this }); + this.ionToastDidUnload.emit(); } @Listen('ionDismiss') @@ -190,7 +199,7 @@ export class Toast { ?
{this.message}
: null} {this.showCloseButton - ? this.dismiss()}> + ? this.dismiss()}> {this.closeButtonText || 'Close'} : null} @@ -214,10 +223,20 @@ export interface ToastOptions { exitAnimation?: AnimationBuilder; } -export interface ToastEvent { - detail: { - toast: Toast; - }; +export interface ToastEvent extends CustomEvent { + detail: ToastEventDetail; +} + +export interface ToastEventDetail { + +} + +export interface ToastDismissEventDetail extends OverlayDismissEventDetail { + // keep this just for the sake of static types and potential future extensions +} + +export interface ToastDismissEvent extends OverlayDismissEvent { + // keep this just for the sake of static types and potential future extensions } export {