fix(vue): overlays function properly when used via controller or template (#22155)

resolves #22090
This commit is contained in:
Liam DeBeasi
2020-09-24 11:18:28 -04:00
committed by GitHub
parent b76bfa36c2
commit fe5fadf19c
14 changed files with 343 additions and 1065 deletions

View File

@ -0,0 +1,75 @@
import { defineComponent, h, ref } from 'vue';
export interface OverlayProps {
isOpen?: boolean;
}
export const defineOverlayContainer = <Props extends object>(name: string, componentProps: string[] = [], controller: any) => {
// TODO
const eventPrefix = name.toLowerCase().split('-').join('');
const eventListeners = [
{ componentEv: `${eventPrefix}willpresent`, frameworkEv: 'onWillPresent' },
{ componentEv: `${eventPrefix}didpresent`, frameworkEv: 'onDidPresent' },
{ componentEv: `${eventPrefix}willdismiss`, frameworkEv: 'onWillDismiss' },
{ componentEv: `${eventPrefix}diddismiss`, frameworkEv: 'onDidDismiss' },
];
const Container = defineComponent<Props & OverlayProps>((props, { slots, emit }) => {
const overlay = ref();
const content = ref();
const onVnodeMounted = async () => {
const isOpen = props.isOpen;
isOpen && (await present(props))
}
const onVnodeUpdated = async () => {
const isOpen = props.isOpen;
if (isOpen) {
await overlay.value?.present() || present(props);
} else {
await overlay.value?.dismiss();
overlay.value = undefined;
}
}
const onVnodeBeforeUnmount = async () => {
await overlay.value?.dismiss();
overlay.value = undefined;
}
const present = async (props: Readonly<Props>) => {
const component = (slots) ? h('div', { ref: content }, slots) : undefined;
overlay.value = await controller.create({
...props,
component
});
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
}
);
}
});
Container.displayName = name;
Container.props = [...componentProps, 'isOpen'];
Container.emits = eventListeners.map(ev => ev.frameworkEv);
return Container;
}