From 3f6b937cec602954020e3c422a30e5de87f16415 Mon Sep 17 00:00:00 2001 From: Dan Bucholtz Date: Sat, 2 Dec 2017 00:54:21 -0600 Subject: [PATCH] refactor(popover): Make api and events match other overlays --- .../popover-controller/popover-controller.tsx | 14 +-- .../core/src/components/popover/popover.tsx | 115 ++++++++++-------- .../components/popover/test/basic/index.html | 10 +- 3 files changed, 78 insertions(+), 61 deletions(-) diff --git a/packages/core/src/components/popover-controller/popover-controller.tsx b/packages/core/src/components/popover-controller/popover-controller.tsx index 0d01deef0f..2d6b2dbc52 100644 --- a/packages/core/src/components/popover-controller/popover-controller.tsx +++ b/packages/core/src/components/popover-controller/popover-controller.tsx @@ -1,5 +1,5 @@ import { Component, Listen, Method } from '@stencil/core'; -import { Popover, PopoverEvent, PopoverOptions } from '../../index'; +import { PopoverEvent, PopoverOptions } from '../../index'; @Component({ tag: 'ion-popover-controller' @@ -7,14 +7,14 @@ import { Popover, PopoverEvent, PopoverOptions } from '../../index'; export class PopoverController { private ids = 0; private popoverResolves: {[popoverId: string]: Function} = {}; - private popovers: Popover[] = []; + private popovers: HTMLIonPopoverElement[] = []; /** * Create a popover component instance * @param opts Options when creating a new popover instance */ @Method() - create(opts?: PopoverOptions) { + create(opts?: PopoverOptions): Promise { // create ionic's wrapping ion-popover component const popover = document.createElement('ion-popover'); const id = this.ids++; @@ -32,7 +32,7 @@ export class PopoverController { appRoot.appendChild(popover as any); // store the resolve function to be called later up when the popover loads - return new Promise(resolve => { + return new Promise(resolve => { this.popoverResolves[popover.popoverId] = resolve; }); } @@ -40,7 +40,7 @@ export class PopoverController { @Listen('body:ionPopoverDidLoad') protected didLoad(ev: PopoverEvent) { - const popover = ev.detail.popover; + const popover = ev.target as HTMLIonPopoverElement; const popoverResolve = this.popoverResolves[popover.popoverId]; if (popoverResolve) { popoverResolve(popover); @@ -51,13 +51,13 @@ export class PopoverController { @Listen('body:ionPopoverWillPresent') protected willPresent(ev: PopoverEvent) { - this.popovers.push(ev.detail.popover); + this.popovers.push(ev.target as HTMLIonPopoverElement); } @Listen('body:ionPopoverWillDismiss, body:ionPopoverDidUnload') protected willDismiss(ev: PopoverEvent) { - const index = this.popovers.indexOf(ev.detail.popover); + const index = this.popovers.indexOf(ev.target as HTMLIonPopoverElement); if (index > -1) { this.popovers.splice(index, 1); } diff --git a/packages/core/src/components/popover/popover.tsx b/packages/core/src/components/popover/popover.tsx index b41aacbd02..a96a685e5a 100644 --- a/packages/core/src/components/popover/popover.tsx +++ b/packages/core/src/components/popover/popover.tsx @@ -1,6 +1,13 @@ -import { Component, Element, Event, EventEmitter, Listen, Prop, State } from '@stencil/core'; -import { Animation, AnimationBuilder, AnimationController, Config } from '../../index'; - +import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; +import { + Animation, + AnimationBuilder, + AnimationController, + Config, + OverlayDismissEvent, + OverlayDismissEventDetail +} from '../../index'; +import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; import { createThemedClasses } from '../../utils/theme'; import iosEnterAnimation from './animations/ios.enter'; @@ -26,32 +33,32 @@ export class Popover { /** * @output {PopoverEvent} Emitted after the popover has loaded. */ - @Event() ionPopoverDidLoad: EventEmitter; + @Event() ionPopoverDidLoad: EventEmitter; /** * @output {PopoverEvent} Emitted after the popover has presented. */ - @Event() ionPopoverDidPresent: EventEmitter; + @Event() ionPopoverDidPresent: EventEmitter; /** * @output {PopoverEvent} Emitted before the popover has presented. */ - @Event() ionPopoverWillPresent: EventEmitter; + @Event() ionPopoverWillPresent: EventEmitter; /** * @output {PopoverEvent} Emitted before the popover has dismissed. */ - @Event() ionPopoverWillDismiss: EventEmitter; + @Event() ionPopoverWillDismiss: EventEmitter; /** * @output {PopoverEvent} Emitted after the popover has dismissed. */ - @Event() ionPopoverDidDismiss: EventEmitter; + @Event() ionPopoverDidDismiss: EventEmitter; /** * @output {PopoverEvent} Emitted after the popover has unloaded. */ - @Event() ionPopoverDidUnload: EventEmitter; + @Event() ionPopoverDidUnload: EventEmitter; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ context: 'config' }) config: Config; @@ -68,76 +75,76 @@ export class Popover { @Prop() popoverId: string; @Prop() showBackdrop: boolean = true; @Prop() translucent: boolean = false; + @Prop() animate: boolean; + @Method() present() { - return new Promise(resolve => { - this._present(resolve); - }); - } - - private _present(resolve: Function) { if (this.animation) { this.animation.destroy(); this.animation = null; } - this.ionPopoverWillPresent.emit({ popover: this }); + this.ionPopoverWillPresent.emit(); // get the user's animation fn if one was provided const animationBuilder = this.enterAnimation || this.config.get('popoverEnter', this.mode === 'ios' ? iosEnterAnimation : mdEnterAnimation); - // build the animation and kick it off - this.animationCtrl.create(animationBuilder, this.el, this.ev).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.ionPopoverWillDismiss.emit({ popover: this }); - // get the user's animation fn if one was provided - const animationBuilder = this.leaveAnimation || this.config.get('popoverLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation); + this.ionPopoverWillDismiss.emit({ + data, + role + }); - // build the animation and kick it off - this.animationCtrl.create(animationBuilder, this.el).then(animation => { - this.animation = animation; + const animationBuilder = this.leaveAnimation || this.config.get('popoverLeave', this.mode === 'ios' ? iosLeaveAnimation : mdLeaveAnimation); - animation.onFinish((a: any) => { - a.destroy(); - this.ionPopoverDidDismiss.emit({ popover: 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.ionPopoverDidDismiss.emit({ + data, + role }); }); } componentDidLoad() { - this.ionPopoverDidLoad.emit({ popover: this }); + this.ionPopoverDidLoad.emit(); } componentDidEnter() { - this.ionPopoverDidPresent.emit({ popover: this }); + this.ionPopoverDidPresent.emit(); } componentDidUnload() { - this.ionPopoverDidUnload.emit({ popover: this }); + this.ionPopoverDidUnload.emit(); } @Listen('ionDismiss') @@ -205,10 +212,20 @@ export interface PopoverOptions { ev: Event; } -export interface PopoverEvent { - detail: { - popover: Popover; - }; +export interface PopoverEvent extends CustomEvent { + detail: PopoverEventDetail; +} + +export interface PopoverEventDetail { + +} + +export interface PopoverDismissEventDetail extends OverlayDismissEventDetail { + // keep this just for the sake of static types and potential future extensions +} + +export interface PopoverDismissEvent extends OverlayDismissEvent { + // keep this just for the sake of static types and potential future extensions } export const POPOVER_POSITION_PROPERTIES: any = { diff --git a/packages/core/src/components/popover/test/basic/index.html b/packages/core/src/components/popover/test/basic/index.html index bfd2375c10..e1def3cede 100644 --- a/packages/core/src/components/popover/test/basic/index.html +++ b/packages/core/src/components/popover/test/basic/index.html @@ -44,11 +44,11 @@