From 71ff57c5368927de1ab04094ed8a9b76f3e05fa0 Mon Sep 17 00:00:00 2001 From: Dan Bucholtz Date: Sat, 2 Dec 2017 00:46:21 -0600 Subject: [PATCH] refactor(picker): update picker api and events to match other overlays --- .../picker-controller/picker-controller.tsx | 14 +-- .../core/src/components/picker/picker.tsx | 115 ++++++++++-------- 2 files changed, 73 insertions(+), 56 deletions(-) diff --git a/packages/core/src/components/picker-controller/picker-controller.tsx b/packages/core/src/components/picker-controller/picker-controller.tsx index 6fe96e705d..424b89757c 100644 --- a/packages/core/src/components/picker-controller/picker-controller.tsx +++ b/packages/core/src/components/picker-controller/picker-controller.tsx @@ -1,5 +1,5 @@ import { Component, Listen, Method } from '@stencil/core'; -import { Picker, PickerEvent, PickerOptions } from '../../index'; +import { PickerEvent, PickerOptions } from '../../index'; @Component({ @@ -8,10 +8,10 @@ import { Picker, PickerEvent, PickerOptions } from '../../index'; export class PickerController { private ids = 0; private pickerResolves: {[pickerId: string]: Function} = {}; - private pickers: Picker[] = []; + private pickers: HTMLIonPickerElement[] = []; @Method() - create(opts?: PickerOptions): Promise { + create(opts?: PickerOptions): Promise { // create ionic's wrapping ion-picker component const picker = document.createElement('ion-picker'); @@ -30,7 +30,7 @@ export class PickerController { appRoot.appendChild(picker as any); // store the resolve function to be called later up when the picker loads - return new Promise(resolve => { + return new Promise(resolve => { this.pickerResolves[picker.pickerId] = resolve; }); } @@ -38,7 +38,7 @@ export class PickerController { @Listen('body:ionPickerDidLoad') protected didLoad(ev: PickerEvent) { - const picker = ev.detail.picker; + const picker = ev.target as HTMLIonPickerElement; const pickerResolve = this.pickerResolves[picker.pickerId]; if (pickerResolve) { pickerResolve(picker); @@ -49,13 +49,13 @@ export class PickerController { @Listen('body:ionPickerWillPresent') protected willPresent(ev: PickerEvent) { - this.pickers.push(ev.detail.picker); + this.pickers.push(ev.target as HTMLIonPickerElement); } @Listen('body:ionPickerWillDismiss, body:ionPickerDidUnload') protected willDismiss(ev: PickerEvent) { - const index = this.pickers.indexOf(ev.detail.picker); + const index = this.pickers.indexOf(ev.target as HTMLIonPickerElement); if (index > -1) { this.pickers.splice(index, 1); } diff --git a/packages/core/src/components/picker/picker.tsx b/packages/core/src/components/picker/picker.tsx index 5ce390e768..44c476ce6c 100644 --- a/packages/core/src/components/picker/picker.tsx +++ b/packages/core/src/components/picker/picker.tsx @@ -1,6 +1,16 @@ -import { Animation, AnimationBuilder, AnimationController, Config } from '../../index'; import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core'; +import { + Animation, + AnimationBuilder, + AnimationController, + Config, + OverlayDismissEvent, + OverlayDismissEventDetail +} from '../../index'; +import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; + + import iosEnterAnimation from './animations/ios.enter'; import iosLeaveAnimation from './animations/ios.leave'; @@ -24,32 +34,32 @@ export class Picker { /** * @output {PickerEvent} Emitted after the picker has loaded. */ - @Event() ionPickerDidLoad: EventEmitter; + @Event() ionPickerDidLoad: EventEmitter; /** * @output {PickerEvent} Emitted after the picker has presented. */ - @Event() ionPickerDidPresent: EventEmitter; + @Event() ionPickerDidPresent: EventEmitter; /** * @output {PickerEvent} Emitted before the picker has presented. */ - @Event() ionPickerWillPresent: EventEmitter; + @Event() ionPickerWillPresent: EventEmitter; /** * @output {PickerEvent} Emitted before the picker has dismissed. */ - @Event() ionPickerWillDismiss: EventEmitter; + @Event() ionPickerWillDismiss: EventEmitter; /** * @output {PickerEvent} Emitted after the picker has dismissed. */ - @Event() ionPickerDidDismiss: EventEmitter; + @Event() ionPickerDidDismiss: EventEmitter; /** * @output {PickerEvent} Emitted after the picker has unloaded. */ - @Event() ionPickerDidUnload: EventEmitter; + @Event() ionPickerDidUnload: EventEmitter; @State() private showSpinner: boolean = null; @State() private spinner: string; @@ -65,41 +75,40 @@ export class Picker { @Prop() pickerId: string; @Prop() showBackdrop: boolean = true; @Prop() enableBackdropDismiss: boolean = true; + @Prop() animate: boolean; @Prop() buttons: PickerButton[] = []; @Prop() columns: PickerColumn[] = []; + @Method() present() { - return new Promise(resolve => { - this._present(resolve); - }); - } - - private _present(resolve: Function) { if (this.animation) { this.animation.destroy(); this.animation = null; } - this.ionPickerWillPresent.emit({ picker: this }); + this.ionPickerWillPresent.emit(); // get the user's animation fn if one was provided const animationBuilder = this.enterAnimation || this.config.get('pickerEnter', iosEnterAnimation); // build the animation and kick it off - this.animationCtrl.create(animationBuilder, this.el).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) { clearTimeout(this.durationTimeout); if (this.animation) { @@ -107,27 +116,25 @@ export class Picker { this.animation = null; } - return new Promise(resolve => { - this.ionPickerWillDismiss.emit({ picker: this }); + this.ionPickerWillDismiss.emit({ + data, + role + }); - // get the user's animation fn if one was provided - const animationBuilder = this.leaveAnimation || this.config.get('pickerLeave', iosLeaveAnimation); + const animationBuilder = this.leaveAnimation || this.config.get('pickerLeave', iosLeaveAnimation); - // build the animation and kick it off - this.animationCtrl.create(animationBuilder, this.el).then(animation => { - this.animation = animation; - - animation.onFinish((a: any) => { - a.destroy(); - this.ionPickerDidDismiss.emit({ picker: 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.ionPickerDidDismiss.emit({ + data, + role }); }); } @@ -146,7 +153,7 @@ export class Picker { if (this.showSpinner === null || this.showSpinner === undefined) { this.showSpinner = !!(this.spinner && this.spinner !== 'hide'); } - this.ionPickerDidLoad.emit({ picker: this }); + this.ionPickerDidLoad.emit(); } componentDidEnter() { @@ -159,11 +166,11 @@ export class Picker { this.durationTimeout = setTimeout(() => this.dismiss(), this.duration); } - this.ionPickerDidPresent.emit({ picker: this }); + this.ionPickerDidPresent.emit(); } componentDidUnload() { - this.ionPickerDidUnload.emit({ picker: this }); + this.ionPickerDidUnload.emit(); } @@ -401,10 +408,20 @@ export interface PickerColumnOption { selected?: boolean; } -export interface PickerEvent extends Event { - detail: { - picker: Picker; - }; +export interface PickerEvent extends CustomEvent { + detail: PickerEventDetail; +} + +export interface PickerEventDetail { + +} + +export interface PickerDismissEventDetail extends OverlayDismissEventDetail { + // keep this just for the sake of static types and potential future extensions +} + +export interface PickerDismissEvent extends OverlayDismissEvent { + // keep this just for the sake of static types and potential future extensions } export {