refactor(overlays): remove duplicated code

This commit is contained in:
Manu Mtz.-Almeida
2018-02-23 20:00:35 +01:00
parent 11b65c245b
commit 9e3f295bbf
8 changed files with 105 additions and 176 deletions

View File

@ -1,9 +1,9 @@
import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; import { Animation, AnimationBuilder, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { domControllerAsync, isDef, playAnimationAsync } from '../../utils/helpers'; import { domControllerAsync } from '../../utils/helpers';
import { createThemedClasses, getClassMap } from '../../utils/theme'; import { createThemedClasses, getClassMap } from '../../utils/theme';
import { OverlayInterface, BACKDROP } from '../../utils/overlays'; import { OverlayInterface, BACKDROP, overlayAnimation } from '../../utils/overlays';
import iosEnterAnimation from './animations/ios.enter'; import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave'; import iosLeaveAnimation from './animations/ios.leave';
@ -23,15 +23,15 @@ import mdLeaveAnimation from './animations/md.leave';
}) })
export class ActionSheet implements OverlayInterface { export class ActionSheet implements OverlayInterface {
private presented = false;
mode: string; mode: string;
color: string; color: string;
animation: Animation;
private presented = false;
private animation: Animation | null = null;
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: HTMLIonAnimationControllerElement;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'dom' }) dom: DomController;
@Prop() overlayId: number; @Prop() overlayId: number;
@ -178,25 +178,8 @@ export class ActionSheet implements OverlayInterface {
}); });
} }
private playAnimation(animationBuilder: AnimationBuilder) { private playAnimation(animationBuilder: AnimationBuilder): Promise<void> {
if (this.animation) { return overlayAnimation(this, animationBuilder, this.willAnimate, this.el, undefined);
this.animation.destroy();
this.animation = null;
}
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
// Check if prop animate is false or if the config for animate is defined/false
if (!this.willAnimate || (isDef(this.config.get('willAnimate')) && this.config.get('willAnimate') === false)) {
// 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.animation = null;
});
} }
protected buttonClick(button: ActionSheetButton) { protected buttonClick(button: ActionSheetButton) {

View File

@ -1,8 +1,8 @@
import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; import { Animation, AnimationBuilder, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { domControllerAsync, playAnimationAsync, autoFocus } from '../../utils/helpers'; import { domControllerAsync, autoFocus } from '../../utils/helpers';
import { createThemedClasses, getClassMap } from '../../utils/theme'; import { createThemedClasses, getClassMap } from '../../utils/theme';
import { OverlayInterface, BACKDROP } from '../../utils/overlays'; import { OverlayInterface, BACKDROP, overlayAnimation } from '../../utils/overlays';
import iosEnterAnimation from './animations/ios.enter'; import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave'; import iosLeaveAnimation from './animations/ios.leave';
@ -21,18 +21,19 @@ import mdLeaveAnimation from './animations/md.leave';
} }
}) })
export class Alert implements OverlayInterface { export class Alert implements OverlayInterface {
mode: string;
color: string;
private presented = false; private presented = false;
private animation: Animation | null = null;
private activeId: string; private activeId: string;
private inputType: string | null = null; private inputType: string | null = null;
private hdrId: string; private hdrId: string;
animation: Animation;
mode: string;
color: string;
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: HTMLIonAnimationControllerElement;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'dom' }) dom: DomController;
@Prop() overlayId: number; @Prop() overlayId: number;
@ -264,25 +265,10 @@ export class Alert implements OverlayInterface {
return values; return values;
} }
private playAnimation(animationBuilder: AnimationBuilder) { private playAnimation(animationBuilder: AnimationBuilder): Promise<void> {
if (this.animation) { return overlayAnimation(this, animationBuilder, this.willAnimate, this.el, undefined);
this.animation.destroy();
this.animation = null;
} }
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
if (!this.willAnimate) {
animation.duration(0);
}
return playAnimationAsync(animation);
}).then(animation => {
animation.destroy();
this.animation = null;
});
}
private renderCheckbox(inputs: AlertInput[]) { private renderCheckbox(inputs: AlertInput[]) {
if (inputs.length === 0) return null; if (inputs.length === 0) return null;

View File

@ -1,13 +1,13 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; import { Animation, AnimationBuilder, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; import { domControllerAsync } from '../../utils/helpers';
import { createThemedClasses, getClassMap } from '../../utils/theme'; import { createThemedClasses, getClassMap } from '../../utils/theme';
import iosEnterAnimation from './animations/ios.enter'; import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave'; import iosLeaveAnimation from './animations/ios.leave';
import mdEnterAnimation from './animations/md.enter'; import mdEnterAnimation from './animations/md.enter';
import mdLeaveAnimation from './animations/md.leave'; import mdLeaveAnimation from './animations/md.leave';
import { OverlayInterface, BACKDROP } from '../../utils/overlays'; import { OverlayInterface, BACKDROP, overlayAnimation } from '../../utils/overlays';
@Component({ @Component({
tag: 'ion-loading', tag: 'ion-loading',
@ -21,16 +21,17 @@ import { OverlayInterface, BACKDROP } from '../../utils/overlays';
}) })
export class Loading implements OverlayInterface { export class Loading implements OverlayInterface {
private presented = false;
private durationTimeout: any;
animation: Animation;
color: string; color: string;
mode: string; mode: string;
private presented = false;
private animation: Animation;
private durationTimeout: any;
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: HTMLIonAnimationControllerElement;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'dom' }) dom: DomController;
@Prop() overlayId: number; @Prop() overlayId: number;
@ -199,24 +200,8 @@ export class Loading implements OverlayInterface {
}); });
} }
private playAnimation(animationBuilder: AnimationBuilder) { private playAnimation(animationBuilder: AnimationBuilder): Promise<void> {
if (this.animation) { return overlayAnimation(this, animationBuilder, this.willAnimate, this.el, undefined);
this.animation.destroy();
this.animation = null;
}
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
if (!this.willAnimate) {
// if the duration is 0, it won't actually animate I don't think
// TODO - validate this
animation.duration(0);
}
return playAnimationAsync(animation);
}).then(animation => {
animation.destroy();
this.animation = null;
});
} }
hostData() { hostData() {

View File

@ -1,10 +1,10 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, DomController, FrameworkDelegate, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; import { Animation, AnimationBuilder, Config, DomController, FrameworkDelegate, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { DomFrameworkDelegate } from '../../utils/dom-framework-delegate'; import { DomFrameworkDelegate } from '../../utils/dom-framework-delegate';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; import { domControllerAsync } from '../../utils/helpers';
import { createThemedClasses } from '../../utils/theme'; import { createThemedClasses } from '../../utils/theme';
import { OverlayInterface, BACKDROP } from '../../utils/overlays'; import { OverlayInterface, BACKDROP, overlayAnimation } from '../../utils/overlays';
import iosEnterAnimation from './animations/ios.enter'; import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave'; import iosLeaveAnimation from './animations/ios.leave';
@ -25,14 +25,16 @@ import mdLeaveAnimation from './animations/md.leave';
export class Modal implements OverlayInterface { export class Modal implements OverlayInterface {
private presented = false; private presented = false;
private animation: Animation;
private usersComponentElement: HTMLElement; private usersComponentElement: HTMLElement;
animation: Animation;
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: HTMLIonAnimationControllerElement;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'dom' }) dom: DomController;
@Prop() overlayId: number; @Prop() overlayId: number;
@Prop({ mutable: true }) delegate: FrameworkDelegate; @Prop({ mutable: true }) delegate: FrameworkDelegate;
@ -208,22 +210,8 @@ export class Modal implements OverlayInterface {
}); });
} }
private playAnimation(animationBuilder: AnimationBuilder) { private playAnimation(animationBuilder: AnimationBuilder): Promise<void> {
if (this.animation) { return overlayAnimation(this, animationBuilder, this.willAnimate, this.el, undefined);
this.animation.destroy();
this.animation = null;
}
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
if (!this.willAnimate) {
animation.duration(0);
}
return playAnimationAsync(animation);
}).then((animation) => {
animation.destroy();
this.animation = null;
});
} }
@Method() @Method()

View File

@ -1,9 +1,9 @@
import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core'; import { Component, CssClassMap, Element, Event, EventEmitter, Listen, Method, Prop, State } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; import { Animation, AnimationBuilder, Config, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; import { domControllerAsync } from '../../utils/helpers';
import { getClassMap } from '../../utils/theme'; import { getClassMap } from '../../utils/theme';
import { OverlayInterface } from '../../utils/overlays'; import { OverlayInterface, overlayAnimation } from '../../utils/overlays';
import iosEnterAnimation from './animations/ios.enter'; import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave'; import iosLeaveAnimation from './animations/ios.leave';
@ -21,16 +21,17 @@ import iosLeaveAnimation from './animations/ios.leave';
export class Picker implements OverlayInterface { export class Picker implements OverlayInterface {
private presented = false; private presented = false;
private animation: Animation;
private durationTimeout: any; private durationTimeout: any;
private mode: string; private mode: string;
animation: Animation;
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@State() private showSpinner: boolean = null; @State() private showSpinner: boolean = null;
@State() private spinner: string; @State() private spinner: string;
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: HTMLIonAnimationControllerElement;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'dom' }) dom: DomController;
@Prop() overlayId: number; @Prop() overlayId: number;
@ -231,22 +232,8 @@ export class Picker implements OverlayInterface {
return this.columns; return this.columns;
} }
private playAnimation(animationBuilder: AnimationBuilder) { private playAnimation(animationBuilder: AnimationBuilder): Promise<void> {
if (this.animation) { return overlayAnimation(this, animationBuilder, this.willAnimate, this.el, undefined);
this.animation.destroy();
this.animation = null;
}
return this.animationCtrl.create(animationBuilder, this.el).then(animation => {
this.animation = animation;
if (!this.willAnimate) {
animation.duration(0);
}
return playAnimationAsync(animation);
}).then(animation => {
animation.destroy();
this.animation = null;
})
} }
private buttonClick(button: PickerButton) { private buttonClick(button: PickerButton) {

View File

@ -1,10 +1,10 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, DomController, FrameworkDelegate, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; import { Animation, AnimationBuilder, Config, DomController, FrameworkDelegate, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { DomFrameworkDelegate } from '../../utils/dom-framework-delegate'; import { DomFrameworkDelegate } from '../../utils/dom-framework-delegate';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; import { domControllerAsync } from '../../utils/helpers';
import { createThemedClasses } from '../../utils/theme'; import { createThemedClasses } from '../../utils/theme';
import { OverlayInterface, BACKDROP } from '../../utils/overlays'; import { OverlayInterface, BACKDROP, overlayAnimation } from '../../utils/overlays';
import iosEnterAnimation from './animations/ios.enter'; import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave'; import iosLeaveAnimation from './animations/ios.leave';
@ -24,12 +24,13 @@ import mdLeaveAnimation from './animations/md.leave';
export class Popover implements OverlayInterface { export class Popover implements OverlayInterface {
private presented = false; private presented = false;
private animation: Animation;
private usersComponentElement: HTMLElement; private usersComponentElement: HTMLElement;
animation: Animation;
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: HTMLIonAnimationControllerElement;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'dom' }) dom: DomController;
@Prop({ mutable: true }) delegate: FrameworkDelegate; @Prop({ mutable: true }) delegate: FrameworkDelegate;
@ -224,22 +225,8 @@ export class Popover implements OverlayInterface {
}); });
} }
private playAnimation(animationBuilder: AnimationBuilder) { private playAnimation(animationBuilder: AnimationBuilder): Promise<void> {
if (this.animation) { return overlayAnimation(this, animationBuilder, this.willAnimate, this.el, this.ev);
this.animation.destroy();
this.animation = null;
}
return this.animationCtrl.create(animationBuilder, this.el, this.ev).then((animation) => {
this.animation = animation;
if (!this.willAnimate) {
animation.duration(0);
}
return playAnimationAsync(animation);
}).then(animation => {
animation.destroy();
this.animation = null;
})
} }
hostData() { hostData() {

View File

@ -1,9 +1,9 @@
import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Animation, AnimationBuilder, AnimationController, Config, CssClassMap, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index'; import { Animation, AnimationBuilder, Config, CssClassMap, DomController, OverlayDismissEvent, OverlayDismissEventDetail } from '../../index';
import { domControllerAsync, playAnimationAsync } from '../../utils/helpers'; import { domControllerAsync } from '../../utils/helpers';
import { createThemedClasses, getClassMap } from '../../utils/theme'; import { createThemedClasses, getClassMap } from '../../utils/theme';
import { OverlayInterface } from '../../utils/overlays'; import { OverlayInterface, overlayAnimation } from '../../utils/overlays';
import iosEnterAnimation from './animations/ios.enter'; import iosEnterAnimation from './animations/ios.enter';
import iosLeaveAnimation from './animations/ios.leave'; import iosLeaveAnimation from './animations/ios.leave';
@ -24,14 +24,14 @@ import mdLeaveAnimation from './animations/md.leave';
export class Toast implements OverlayInterface { export class Toast implements OverlayInterface {
private presented = false; private presented = false;
private animation: Animation | null;
@Element() private el: HTMLElement; @Element() private el: HTMLElement;
mode: string; mode: string;
color: string; color: string;
animation: Animation | null;
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController; @Prop({ connect: 'ion-animation-controller' }) animationCtrl: HTMLIonAnimationControllerElement;
@Prop({ context: 'config' }) config: Config; @Prop({ context: 'config' }) config: Config;
@Prop({ context: 'dom' }) dom: DomController; @Prop({ context: 'dom' }) dom: DomController;
@Prop() overlayId: number; @Prop() overlayId: number;
@ -123,6 +123,22 @@ export class Toast implements OverlayInterface {
*/ */
@Event() ionToastDidUnload: EventEmitter<ToastEventDetail>; @Event() ionToastDidUnload: EventEmitter<ToastEventDetail>;
componentDidLoad() {
this.ionToastDidLoad.emit();
}
componentDidUnload() {
this.ionToastDidUnload.emit();
}
@Listen('ionDismiss')
protected onDismiss(ev: UIEvent) {
ev.stopPropagation();
ev.preventDefault();
this.dismiss();
}
/** /**
* Present the toast overlay after it has been created. * Present the toast overlay after it has been created.
*/ */
@ -169,38 +185,8 @@ export class Toast implements OverlayInterface {
}); });
} }
playAnimation(animationBuilder: AnimationBuilder) { private playAnimation(animationBuilder: AnimationBuilder): Promise<void> {
if (this.animation) { return overlayAnimation(this, animationBuilder, this.willAnimate, this.el, this.position);
this.animation.destroy();
this.animation = null;
}
return this.animationCtrl.create(animationBuilder, this.el, this.position).then(animation => {
this.animation = animation;
if (!this.willAnimate) {
animation.duration(0);
}
return playAnimationAsync(animation);
}).then((animation) => {
animation.destroy();
this.animation = null;
});
}
componentDidLoad() {
this.ionToastDidLoad.emit();
}
componentDidUnload() {
this.ionToastDidUnload.emit();
}
@Listen('ionDismiss')
protected onDismiss(ev: UIEvent) {
ev.stopPropagation();
ev.preventDefault();
this.dismiss();
} }
private wrapperClass(): CssClassMap { private wrapperClass(): CssClassMap {

View File

@ -1,3 +1,5 @@
import { AnimationBuilder, Animation } from "..";
import { playAnimationAsync } from "./helpers";
let lastId = 1; let lastId = 1;
@ -56,8 +58,33 @@ export function removeLastOverlay(overlays: OverlayMap) {
return toRemove ? toRemove.dismiss() : Promise.resolve(); return toRemove ? toRemove.dismiss() : Promise.resolve();
} }
export function overlayAnimation(
overlay: OverlayInterface,
animationBuilder: AnimationBuilder,
animate: boolean,
baseEl: HTMLElement,
opts: any
): Promise<void> {
if (overlay.animation) {
overlay.animation.destroy();
overlay.animation = null;
}
return overlay.animationCtrl.create(animationBuilder, baseEl, opts).then(animation => {
overlay.animation = animation;
if (!animate) {
animation.duration(0);
}
return playAnimationAsync(animation);
}).then((animation) => {
animation.destroy();
overlay.animation = null;
});
}
export interface OverlayInterface { export interface OverlayInterface {
overlayId: number; overlayId: number;
animation: Animation;
animationCtrl: HTMLIonAnimationControllerElement;
present(): Promise<void>; present(): Promise<void>;
dismiss(data?: any, role?: string): Promise<void>; dismiss(data?: any, role?: string): Promise<void>;