mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-09 16:16:41 +08:00
refactor(popover): Make api and events match other overlays
This commit is contained in:
@ -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<HTMLIonPopoverElement> {
|
||||
// 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<Popover>(resolve => {
|
||||
return new Promise<HTMLIonPopoverElement>(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);
|
||||
}
|
||||
|
||||
@ -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<PopoverEventDetail>;
|
||||
|
||||
/**
|
||||
* @output {PopoverEvent} Emitted after the popover has presented.
|
||||
*/
|
||||
@Event() ionPopoverDidPresent: EventEmitter;
|
||||
@Event() ionPopoverDidPresent: EventEmitter<PopoverEventDetail>;
|
||||
|
||||
/**
|
||||
* @output {PopoverEvent} Emitted before the popover has presented.
|
||||
*/
|
||||
@Event() ionPopoverWillPresent: EventEmitter;
|
||||
@Event() ionPopoverWillPresent: EventEmitter<PopoverEventDetail>;
|
||||
|
||||
/**
|
||||
* @output {PopoverEvent} Emitted before the popover has dismissed.
|
||||
*/
|
||||
@Event() ionPopoverWillDismiss: EventEmitter;
|
||||
@Event() ionPopoverWillDismiss: EventEmitter<PopoverDismissEventDetail>;
|
||||
|
||||
/**
|
||||
* @output {PopoverEvent} Emitted after the popover has dismissed.
|
||||
*/
|
||||
@Event() ionPopoverDidDismiss: EventEmitter;
|
||||
@Event() ionPopoverDidDismiss: EventEmitter<PopoverDismissEventDetail>;
|
||||
|
||||
/**
|
||||
* @output {PopoverEvent} Emitted after the popover has unloaded.
|
||||
*/
|
||||
@Event() ionPopoverDidUnload: EventEmitter;
|
||||
@Event() ionPopoverDidUnload: EventEmitter<PopoverEventDetail>;
|
||||
|
||||
@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<void>(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 = {
|
||||
|
||||
@ -44,11 +44,11 @@
|
||||
</ion-page>
|
||||
</ion-app>
|
||||
<script>
|
||||
function presentPopover(opts) {
|
||||
var popoverController = document.querySelector('ion-popover-controller');
|
||||
popoverController.create(opts).then(popover => {
|
||||
popover.present();
|
||||
});
|
||||
async function presentPopover(opts) {
|
||||
const popoverController = document.querySelector('ion-popover-controller');
|
||||
await popoverController.componentOnReady();
|
||||
const popoverElement = await popoverController.create(opts);
|
||||
return await popoverElement.present();
|
||||
}
|
||||
|
||||
class ProfilePage extends HTMLElement {
|
||||
|
||||
Reference in New Issue
Block a user