diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts index 8b135c6519..8307503ed2 100644 --- a/packages/core/src/components.d.ts +++ b/packages/core/src/components.d.ts @@ -173,6 +173,7 @@ declare global { inputs?: AlertInput[], enableBackdropDismiss?: boolean, translucent?: boolean, + animate?: boolean, enterAnimation?: AnimationBuilder, exitAnimation?: AnimationBuilder, alertId?: string diff --git a/packages/core/src/components/alert/alert.tsx b/packages/core/src/components/alert/alert.tsx index 1394d06d1e..3ae2e18c99 100644 --- a/packages/core/src/components/alert/alert.tsx +++ b/packages/core/src/components/alert/alert.tsx @@ -1,8 +1,9 @@ -import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; -import { Animation, AnimationBuilder, AnimationController, Config } from '../../index'; -import { playAnimationAsync } from '../../utils/helpers'; +import { Component, CssClassMap, Element, Event, EventEmitter, Method, Prop } from '@stencil/core'; +import { Animation, AnimationBuilder, AnimationController, Config, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; +import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; +import { BACKDROP } from '../../utils/overlay-constants'; import { createThemedClasses } from '../../utils/theme'; import iOSEnterAnimation from './animations/ios.enter'; @@ -32,32 +33,32 @@ export class Alert { /** * @output {AlertEvent} Emitted after the alert has loaded. */ - @Event() ionAlertDidLoad: EventEmitter; + @Event() ionAlertDidLoad: EventEmitter; /** * @output {AlertEvent} Emitted after the alert has presented. */ - @Event() ionAlertDidPresent: EventEmitter; + @Event() ionAlertDidPresent: EventEmitter; /** * @output {AlertEvent} Emitted before the alert has presented. */ - @Event() ionAlertWillPresent: EventEmitter; + @Event() ionAlertWillPresent: EventEmitter; /** * @output {AlertEvent} Emitted before the alert has dismissed. */ - @Event() ionAlertWillDismiss: EventEmitter; + @Event() ionAlertWillDismiss: EventEmitter; /** * @output {AlertEvent} Emitted after the alert has dismissed. */ - @Event() ionAlertDidDismiss: EventEmitter; + @Event() ionAlertDidDismiss: EventEmitter; /** * @output {AlertEvent} Emitted after the alert has unloaded. */ - @Event() ionAlertDidUnload: EventEmitter; + @Event() ionAlertDidUnload: EventEmitter; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ context: 'config' }) config: Config; @@ -71,6 +72,7 @@ export class Alert { @Prop() enableBackdropDismiss: boolean = true; @Prop() translucent: boolean = false; + @Prop() animate: boolean = true; @Prop() enterAnimation: AnimationBuilder; @Prop() exitAnimation: AnimationBuilder; @Prop() alertId: string; @@ -93,6 +95,11 @@ export class Alert { // build the animation and kick it off return this.animationCtrl.create(animationBuilder, this.el).then(animation => { this.animation = animation; + 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(); @@ -105,12 +112,15 @@ export class Alert { }); } - @Method() dismiss() { + @Method() dismiss(data?: any, role?: string) { if (this.animation) { this.animation.destroy(); this.animation = null; } - this.ionAlertWillDismiss.emit(); + this.ionAlertWillDismiss.emit({ + data: data, + role: role + }); // get the user's animation fn if one was provided let animationBuilder = this.exitAnimation; @@ -125,40 +135,32 @@ export class Alert { return playAnimationAsync(animation); }).then((animation) => { animation.destroy(); - this.ionAlertDidDismiss.emit(); + this.ionAlertDidDismiss.emit({ + data: data, + role: role + }); - Context.dom.write(() => { + return domControllerAsync(Context.dom.write, () => { this.el.parentNode.removeChild(this.el); }); }); } componentDidLoad() { - this.ionAlertDidLoad.emit({ alert: this }); + this.ionAlertDidLoad.emit(); } componentDidEnter() { - this.ionAlertDidPresent.emit({ alert: this }); + this.ionAlertDidPresent.emit(); } componentDidUnload() { - this.ionAlertDidUnload.emit({ alert: this }); - } - - @Listen('ionDismiss') - protected onDismiss(ev: UIEvent) { - ev.stopPropagation(); - ev.preventDefault(); - - this.dismiss(); + this.ionAlertDidUnload.emit(); } protected backdropClick() { if (this.enableBackdropDismiss) { - // const opts: NavOptions = { - // minClickBlockDuration: 400 - // }; - this.dismiss(); + this.dismiss(null, BACKDROP); } } @@ -191,8 +193,6 @@ export class Alert { } buttonClick(button: any) { - console.log('buttonClick', button); - // TODO keep the time of the most recent button click // this.lastClick = Date.now(); @@ -208,7 +208,7 @@ export class Alert { } if (shouldDismiss) { - this.dismiss(); + this.dismiss(this.getValues(), button.role); } } @@ -468,7 +468,16 @@ export interface AlertButton { handler?: (value: any) => boolean|void; } -export interface AlertEvent extends Event { +export interface AlertEvent extends CustomEvent { + // keep this just for the sake of static types and potential future extensions +} + +export interface AlertDismissEventDetail extends OverlayDismissEventDetail { + // keep this just for the sake of static types and potential future extensions +} + +export interface AlertDismissEvent extends OverlayDismissEvent { + // keep this just for the sake of static types and potential future extensions } export { iOSEnterAnimation, iOSLeaveAnimation }; diff --git a/packages/core/src/index.d.ts b/packages/core/src/index.d.ts index d99e8beafc..c1d8f0fdfc 100644 --- a/packages/core/src/index.d.ts +++ b/packages/core/src/index.d.ts @@ -9,15 +9,7 @@ export { } from './components/action-sheet/action-sheet'; export { ActionSheetController } from './components/action-sheet-controller/action-sheet-controller'; -export { - Alert, - AlertButton, - AlertEvent, - AlertInput, - AlertOptions, - iOSEnterAnimation as AlertIOSEnterAnimation, - iOSLeaveAnimation as AlertIOSLeaveAnimation -} from './components/alert/alert'; +export * from './components/alert/alert'; export { AlertController } from './components/alert-controller/alert-controller'; export { Animation, @@ -163,6 +155,8 @@ export { ViewController } from './navigation/view-controller'; // export all of the component declarations that are dynamically created export * from './components'; +export { DomController, RafCallback } from './global/dom-controller' + export interface Config { get: (key: string, fallback?: any) => any; getBoolean: (key: string, fallback?: boolean) => boolean; @@ -183,4 +177,13 @@ export interface BaseInputComponent { export interface StencilElement extends HTMLElement { componentOnReady(): Promise; componentOnReady(done: (cmp?: HTMLElement) => void): void; +} + +export interface OverlayDismissEvent extends CustomEvent { + detail: OverlayDismissEventDetail +} + +export interface OverlayDismissEventDetail { + data?: any; + role?: string; } \ No newline at end of file diff --git a/packages/core/src/utils/helpers.ts b/packages/core/src/utils/helpers.ts index e04035f783..e8d8d485c1 100644 --- a/packages/core/src/utils/helpers.ts +++ b/packages/core/src/utils/helpers.ts @@ -1,4 +1,4 @@ -import { Animation, StencilElement } from '../index'; +import { Animation, DomController, StencilElement } from '../index'; export function clamp(min: number, n: number, max: number) { return Math.max(min, Math.min(n, max)); @@ -279,3 +279,12 @@ export function playAnimationAsync(animation: Animation): Promise { animation.play(); }); } + +export function domControllerAsync(domControllerFunction: Function, callback: Function) { + return new Promise((resolve) => { + domControllerFunction(() => { + callback(); + resolve(); + }); + }); +} diff --git a/packages/core/src/utils/overlay-constants.ts b/packages/core/src/utils/overlay-constants.ts new file mode 100644 index 0000000000..80fd8dae02 --- /dev/null +++ b/packages/core/src/utils/overlay-constants.ts @@ -0,0 +1,2 @@ + +export const BACKDROP = 'backdrop';