mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 11:17:19 +08:00
fix(modal, popover): overlays now automatically determine if they are inline (#23434)
This commit is contained in:
4
core/src/components.d.ts
vendored
4
core/src/components.d.ts
vendored
@ -1395,7 +1395,6 @@ export namespace Components {
|
||||
* Animation to use when the modal is presented.
|
||||
*/
|
||||
"enterAnimation"?: AnimationBuilder;
|
||||
"inline": boolean;
|
||||
/**
|
||||
* If `true`, the modal will open. If `false`, the modal will close. Use this if you need finer grained control over presentation, otherwise just use the modalController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the modal dismisses. You will need to do that in your code.
|
||||
*/
|
||||
@ -1707,7 +1706,6 @@ export namespace Components {
|
||||
*/
|
||||
"event": any;
|
||||
"getParentPopover": () => Promise<HTMLIonPopoverElement | null>;
|
||||
"inline": boolean;
|
||||
/**
|
||||
* If `true`, the popover will open. If `false`, the popover will close. Use this if you need finer grained control over presentation, otherwise just use the popoverController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the popover dismisses. You will need to do that in your code.
|
||||
*/
|
||||
@ -4854,7 +4852,6 @@ declare namespace LocalJSX {
|
||||
* Animation to use when the modal is presented.
|
||||
*/
|
||||
"enterAnimation"?: AnimationBuilder;
|
||||
"inline"?: boolean;
|
||||
/**
|
||||
* If `true`, the modal will open. If `false`, the modal will close. Use this if you need finer grained control over presentation, otherwise just use the modalController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the modal dismisses. You will need to do that in your code.
|
||||
*/
|
||||
@ -5099,7 +5096,6 @@ declare namespace LocalJSX {
|
||||
* The event to pass to the popover animation.
|
||||
*/
|
||||
"event"?: any;
|
||||
"inline"?: boolean;
|
||||
/**
|
||||
* If `true`, the popover will open. If `false`, the popover will close. Use this if you need finer grained control over presentation, otherwise just use the popoverController or the `trigger` property. Note: `isOpen` will not automatically be set back to `false` when the popover dismisses. You will need to do that in your code.
|
||||
*/
|
||||
|
@ -39,6 +39,9 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
private currentTransition?: Promise<any>;
|
||||
private destroyTriggerInteraction?: () => void;
|
||||
|
||||
private inline = false;
|
||||
private workingDelegate?: FrameworkDelegate;
|
||||
|
||||
// Reference to the user's provided modal content
|
||||
private usersElement?: HTMLElement;
|
||||
|
||||
@ -51,9 +54,6 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
|
||||
@Element() el!: HTMLIonModalElement;
|
||||
|
||||
/** @internal */
|
||||
@Prop() inline = true;
|
||||
|
||||
/** @internal */
|
||||
@Prop() overlayIndex!: number;
|
||||
|
||||
@ -249,6 +249,39 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
this.destroyTriggerInteraction = configureTriggerInteraction(triggerEl, el);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not an overlay
|
||||
* is being used inline or via a controller/JS
|
||||
* and returns the correct delegate.
|
||||
* By default, subsequent calls to getDelegate
|
||||
* will use a cached version of the delegate.
|
||||
* This is useful for calling dismiss after
|
||||
* present so that the correct delegate is given.
|
||||
*/
|
||||
private getDelegate(force = false) {
|
||||
if (this.workingDelegate && !force) {
|
||||
return {
|
||||
delegate: this.workingDelegate,
|
||||
inline: this.inline
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If using overlay inline
|
||||
* we potentially need to use the coreDelegate
|
||||
* so that this works in vanilla JS apps.
|
||||
* If a user has already placed the overlay
|
||||
* as a direct descendant of ion-app or
|
||||
* the body, then we can assume that
|
||||
* the overlay is already in the correct place.
|
||||
*/
|
||||
const parentEl = this.el.parentNode as HTMLElement | null;
|
||||
const inline = this.inline = parentEl !== null && parentEl.tagName !== 'ION-APP' && parentEl.tagName !== 'BODY';
|
||||
const delegate = this.workingDelegate = (inline) ? this.delegate || this.coreDelegate : this.delegate
|
||||
|
||||
return { inline, delegate }
|
||||
}
|
||||
|
||||
/**
|
||||
* Present the modal overlay after it has been created.
|
||||
*/
|
||||
@ -275,14 +308,8 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
modal: this.el
|
||||
};
|
||||
|
||||
/**
|
||||
* If using modal inline
|
||||
* we potentially need to use the coreDelegate
|
||||
* so that this works in vanilla JS apps
|
||||
*/
|
||||
const delegate = (this.inline) ? this.delegate || this.coreDelegate : this.delegate;
|
||||
|
||||
this.usersElement = await attachComponent(delegate, this.el, this.component, ['ion-page'], data, this.inline);
|
||||
const { inline, delegate } = this.getDelegate(true);
|
||||
this.usersElement = await attachComponent(delegate, this.el, this.component, ['ion-page'], data, inline);
|
||||
|
||||
await deepReady(this.usersElement);
|
||||
|
||||
@ -362,7 +389,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
const dismissed = await this.currentTransition;
|
||||
|
||||
if (dismissed) {
|
||||
const delegate = (this.inline) ? this.delegate || this.coreDelegate : this.delegate;
|
||||
const { delegate } = this.getDelegate();
|
||||
await detachComponent(delegate, this.usersElement);
|
||||
if (this.animation) {
|
||||
this.animation.destroy();
|
||||
|
@ -45,6 +45,9 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
||||
private destroyKeyboardInteraction?: () => void;
|
||||
private destroyDismissInteraction?: () => void;
|
||||
|
||||
private inline = false;
|
||||
private workingDelegate?: FrameworkDelegate;
|
||||
|
||||
private triggerEv?: Event;
|
||||
private focusDescendantOnPresent = false;
|
||||
|
||||
@ -54,9 +57,6 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
||||
|
||||
@Element() el!: HTMLIonPopoverElement;
|
||||
|
||||
/** @internal */
|
||||
@Prop() inline = true;
|
||||
|
||||
/** @internal */
|
||||
@Prop() delegate?: FrameworkDelegate;
|
||||
|
||||
@ -314,6 +314,39 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
||||
this.focusDescendantOnPresent = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not an overlay
|
||||
* is being used inline or via a controller/JS
|
||||
* and returns the correct delegate.
|
||||
* By default, subsequent calls to getDelegate
|
||||
* will use a cached version of the delegate.
|
||||
* This is useful for calling dismiss after
|
||||
* present so that the correct delegate is given.
|
||||
*/
|
||||
private getDelegate(force = false) {
|
||||
if (this.workingDelegate && !force) {
|
||||
return {
|
||||
delegate: this.workingDelegate,
|
||||
inline: this.inline
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If using overlay inline
|
||||
* we potentially need to use the coreDelegate
|
||||
* so that this works in vanilla JS apps.
|
||||
* If a user has already placed the overlay
|
||||
* as a direct descendant of ion-app or
|
||||
* the body, then we can assume that
|
||||
* the overlay is already in the correct place.
|
||||
*/
|
||||
const parentEl = this.el.parentNode as HTMLElement | null;
|
||||
const inline = this.inline = parentEl !== null && parentEl.tagName !== 'ION-APP' && parentEl.tagName !== 'BODY';
|
||||
const delegate = this.workingDelegate = (inline) ? this.delegate || this.coreDelegate : this.delegate
|
||||
|
||||
return { inline, delegate }
|
||||
}
|
||||
|
||||
/**
|
||||
* Present the popover overlay after it has been created.
|
||||
*/
|
||||
@ -340,14 +373,8 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
||||
popover: this.el
|
||||
};
|
||||
|
||||
/**
|
||||
* If using popover inline
|
||||
* we potentially need to use the coreDelegate
|
||||
* so that this works in vanilla JS apps
|
||||
*/
|
||||
const delegate = (this.inline) ? this.delegate || this.coreDelegate : this.delegate;
|
||||
|
||||
this.usersElement = await attachComponent(delegate, this.el, this.component, ['popover-viewport'], data, this.inline);
|
||||
const { inline, delegate } = this.getDelegate(true);
|
||||
this.usersElement = await attachComponent(delegate, this.el, this.component, ['popover-viewport'], data, inline);
|
||||
await deepReady(this.usersElement);
|
||||
|
||||
this.configureKeyboardInteraction();
|
||||
@ -421,7 +448,7 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
||||
* we potentially need to use the coreDelegate
|
||||
* so that this works in vanilla JS apps
|
||||
*/
|
||||
const delegate = (this.inline) ? this.delegate || this.coreDelegate : this.delegate;
|
||||
const { delegate } = this.getDelegate();
|
||||
await detachComponent(delegate, this.usersElement);
|
||||
}
|
||||
|
||||
|
@ -53,11 +53,8 @@ export const createOverlay = <T extends HTMLIonOverlayElement>(tagName: string,
|
||||
/**
|
||||
* Convert the passed in overlay options into props
|
||||
* that get passed down into the new overlay.
|
||||
* Inline is needed for ion-popover as it can
|
||||
* be presented via a controller or written
|
||||
* inline in a template.
|
||||
*/
|
||||
Object.assign(element, { ...opts, inline: false });
|
||||
Object.assign(element, { ...opts });
|
||||
|
||||
// append the overlay element to the document body
|
||||
getAppRoot(document).appendChild(element);
|
||||
|
Reference in New Issue
Block a user