mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-15 17:42:15 +08:00

refactor(vue): drop support for "on" prefixed overlay events and bump minimum required version of vue to 3.0.6 BREAKING CHANGE: - Dropped support for prefixed overlay events in favor of non prefixed events (I.e. `@onDidDismiss` becomes `@didDismiss`). - Minimum required version of Vue is now Vue v3.0.6 or newer.
116 lines
2.9 KiB
TypeScript
116 lines
2.9 KiB
TypeScript
import { defineComponent, h, ref, VNode } from 'vue';
|
|
|
|
export interface OverlayProps {
|
|
isOpen?: boolean;
|
|
}
|
|
|
|
export const defineOverlayContainer = <Props extends object>(name: string, componentProps: string[] = [], controller: any) => {
|
|
const eventListeners = [
|
|
{ componentEv: `${name}-will-present`, frameworkEv: 'willPresent' },
|
|
{ componentEv: `${name}-did-present`, frameworkEv: 'didPresent' },
|
|
{ componentEv: `${name}-will-dismiss`, frameworkEv: 'willDismiss' },
|
|
{ componentEv: `${name}-did-dismiss`, frameworkEv: 'didDismiss' },
|
|
];
|
|
|
|
const Container = defineComponent<Props & OverlayProps>((props, { slots, emit }) => {
|
|
const overlay = ref();
|
|
const onVnodeMounted = async () => {
|
|
const isOpen = props.isOpen;
|
|
isOpen && (await present(props))
|
|
}
|
|
|
|
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 present(props);
|
|
} else {
|
|
await dismiss();
|
|
}
|
|
}
|
|
|
|
const onVnodeBeforeUnmount = async () => {
|
|
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;
|
|
}
|
|
|
|
/**
|
|
* These are getting passed as props.
|
|
* Potentially a Vue bug with Web Components?
|
|
*/
|
|
const restOfProps = { ...(props as any) };
|
|
delete restOfProps.onWillPresent;
|
|
delete restOfProps.onDidPresent;
|
|
delete restOfProps.onWillDismiss;
|
|
delete restOfProps.onDidDismiss;
|
|
|
|
const component = slots.default && slots.default()[0];
|
|
overlay.value = controller.create({
|
|
...restOfProps,
|
|
component
|
|
});
|
|
|
|
overlay.value = await overlay.value;
|
|
|
|
eventListeners.forEach(eventListener => {
|
|
overlay.value.addEventListener(eventListener.componentEv, () => {
|
|
emit(eventListener.frameworkEv);
|
|
});
|
|
})
|
|
|
|
await overlay.value.present();
|
|
}
|
|
|
|
return () => {
|
|
return h(
|
|
'div',
|
|
{
|
|
style: { display: 'none' },
|
|
onVnodeMounted,
|
|
onVnodeUpdated,
|
|
onVnodeBeforeUnmount,
|
|
isOpen: props.isOpen
|
|
}
|
|
);
|
|
}
|
|
});
|
|
|
|
Container.displayName = name;
|
|
Container.props = [...componentProps, 'isOpen'];
|
|
Container.emits = ['willPresent', 'didPresent', 'willDismiss', 'didDismiss'];
|
|
|
|
return Container;
|
|
}
|