mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 01:52:19 +08:00
fix(vue): overlays function properly when used via controller or template (#22155)
resolves #22090
This commit is contained in:
75
packages/vue/src/vue-component-lib/overlays.ts
Normal file
75
packages/vue/src/vue-component-lib/overlays.ts
Normal 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;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { FunctionalComponent, VNode, defineComponent, h, inject, ref, Ref } from 'vue';
|
||||
import { VNode, defineComponent, h, inject, ref, Ref } from 'vue';
|
||||
|
||||
export interface InputProps extends Object {
|
||||
modelValue: string | boolean;
|
||||
@ -40,7 +40,7 @@ const getElementClasses = (ref: Ref<HTMLElement | undefined>, componentClasses:
|
||||
* options for the component such as router or v-model
|
||||
* integrations.
|
||||
*/
|
||||
export const defineContainer = <Props extends object>(name: string, componentProps: string[] = [], componentOptions: ComponentOptions = {}) => {
|
||||
export const defineContainer = <Props>(name: string, componentProps: string[] = [], componentOptions: ComponentOptions = {}) => {
|
||||
const { modelProp, modelUpdateEvent, routerLinkComponent } = componentOptions;
|
||||
|
||||
/**
|
||||
@ -48,7 +48,7 @@ export const defineContainer = <Props extends object>(name: string, componentPro
|
||||
* Note: The `props` here are not all properties on a component.
|
||||
* They refer to whatever properties are set on an instance of a component.
|
||||
*/
|
||||
const Container: FunctionalComponent<Props & InputProps> = defineComponent((props, { attrs, slots, emit }) => {
|
||||
const Container = defineComponent<Props & InputProps>((props, { attrs, slots, emit }) => {
|
||||
const containerRef = ref<HTMLElement>();
|
||||
const classes = new Set(getComponentClasses(attrs.class));
|
||||
const onVnodeBeforeMount = (vnode: VNode) => {
|
||||
|
Reference in New Issue
Block a user