Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 43 additions & 9 deletions packages/vue/src/vue-component-lib/overlays.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defineComponent, h, ref } from 'vue';
import { defineComponent, h, ref, VNode } from 'vue';

export interface OverlayProps {
isOpen?: boolean;
Expand All @@ -21,28 +21,61 @@ export const defineOverlayContainer = <Props extends object>(name: string, compo
isOpen && (await present(props))
}

const onVnodeUpdated = async () => {
const isOpen = props.isOpen;
const onVnodeUpdated = async (node: VNode, prevNode: VNode) => {
const isOpen = node.props!.isOpen;
const prevIsOpen = prevNode.props!.isOpen;

/**
* Do not do anything if this prop
* did not change.
*/
if (isOpen === prevIsOpen) return;

if (isOpen) {
await overlay.value?.present() || present(props);
await present(props);
} else {
await overlay.value?.dismiss();
overlay.value = undefined;
await dismiss();
}
}

const onVnodeBeforeUnmount = async () => {
await overlay.value?.dismiss();
await dismiss();
}

const dismiss = async () => {
if (!overlay.value) return;

await overlay.value;

overlay.value = overlay.value.dismiss();

await overlay.value;

overlay.value = undefined;
}

const present = async (props: Readonly<Props>) => {
/**
* Do not open another instance
* if one is already opened.
*/
if (overlay.value) {
await overlay.value;
}

if (overlay.value?.present) {
await overlay.value.present();
return;
}

const component = slots.default && slots.default()[0];
overlay.value = await controller.create({
overlay.value = controller.create({
...props,
component
});

overlay.value = await overlay.value;

eventListeners.forEach(eventListener => {
overlay.value.addEventListener(eventListener.componentEv, () => {
emit(eventListener.frameworkEv);
Expand All @@ -59,7 +92,8 @@ export const defineOverlayContainer = <Props extends object>(name: string, compo
style: { display: 'none' },
onVnodeMounted,
onVnodeUpdated,
onVnodeBeforeUnmount
onVnodeBeforeUnmount,
isOpen: props.isOpen
}
);
}
Expand Down
15 changes: 14 additions & 1 deletion packages/vue/test-app/src/views/Overlays.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@

<br />

<ion-button expand="block" @click="present($event)" id="present-overlay">Present Overlay</ion-button>
<ion-button @click="present($event)" id="present-overlay">Present Overlay</ion-button>

<ion-button @click="changeLoadingProps()" id="change-loading-props">Quickly Change Loading Props</ion-button>

<ion-action-sheet
:is-open="isActionSheetOpen"
Expand Down Expand Up @@ -314,7 +316,18 @@ export default defineComponent({
}
}

const changeLoadingProps = () => {
setLoadingRef(true);
setTimeout(() => {
setLoadingRef(false);
setTimeout(() => {
setLoadingRef(true);
}, 10);
}, 10);
}

return {
changeLoadingProps,
overlayProps,
present,
componentType,
Expand Down
14 changes: 10 additions & 4 deletions packages/vue/test-app/tests/e2e/specs/overlays.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe('Overlays', () => {
cy.get('ion-toast').should('not.exist');
});

it('it should pass props to modal via controller', () => {
it('should pass props to modal via controller', () => {
cy.get('ion-radio#ion-modal').click();
cy.get('ion-radio#controller').click();

Expand All @@ -69,7 +69,7 @@ describe('Overlays', () => {
cy.get('ion-modal ion-content').should('have.text', 'Custom Title');
});

it('it should pass props to modal via component', () => {
it('should pass props to modal via component', () => {
cy.get('ion-radio#ion-modal').click();
cy.get('ion-radio#component').click();

Expand All @@ -79,7 +79,7 @@ describe('Overlays', () => {
cy.get('ion-modal ion-content').should('have.text', 'Custom Title');
});

it('it should pass props to popover via controller', () => {
it('should pass props to popover via controller', () => {
cy.get('ion-radio#ion-popover').click();
cy.get('ion-radio#controller').click();

Expand All @@ -89,7 +89,7 @@ describe('Overlays', () => {
cy.get('ion-popover ion-content').should('have.text', 'Custom Title');
});

it('it should pass props to popover via component', () => {
it('should pass props to popover via component', () => {
cy.get('ion-radio#ion-popover').click();
cy.get('ion-radio#component').click();

Expand All @@ -98,4 +98,10 @@ describe('Overlays', () => {

cy.get('ion-popover ion-content').should('have.text', 'Custom Title');
});

it('should only open one instance at a time when props change quickly on component', () => {
cy.get('#change-loading-props').click();

cy.get('ion-loading').should('have.length', 1);
});
})