import { router } from "@/router"; import { createVNode, reactive, render, watch, watchEffect } from "vue"; import Locale from "@/config/locale.vue"; import type { App, Ref, VNode } from "vue"; interface ComponentConstructor

{ new (...args: any[]): { $props: P; }; } type Mutable = { -readonly [Key in keyof Type]: Type[Key]; }; export type MountContext

= { props?: P; children?: unknown; element?: HTMLElement; app?: App; }; function mount

( component: Readonly

, { props, children, element, app }: MountContext

= {} ) { let el = element; let vNode: VNode | undefined = createVNode( Locale, {}, { default: () => createVNode(component, props as any, children), } ); if (app && app._context) vNode.appContext = app._context; if (el) { render(vNode, el); } else if (typeof document !== "undefined") { render(vNode, (el = document.createElement("div"))); } const destroy = () => { if (el) render(null, el); el = undefined; vNode = undefined; }; return { vNode, destroy, el }; } let app: App; export const setApp = (application: App) => (app = application); export const extendProps = ( origin: T, append: E ): T & E => { const props = reactive({ ...append }) as T & E; watchEffect(() => { for (const key in origin) { (props as any)[key] = origin[key]; } }); return props; }; export const mountComponent =

( comp: ComponentConstructor

, props: Mutable

, children?: any ) => { const element = document.createElement("div"); const { destroy: destroyRaw } = mount(comp, { element, props, app: app, children, } as any); const destroy = () => { destroyRaw(); if (document.body.contains(element)) { document.body.removeChild(element); } stopWatch(); }; const stopWatch = watch(() => router.currentRoute.value.name, destroy); return destroy; }; import Dialog from "@/components/dialog/index.vue"; import { DialogProps, dialogPropsKeys } from "@/components/dialog/type"; export type QuiskExpose = { submit?: () => void; quit?: () => void; } & Partial<{ [key in keyof DialogProps]?: Ref }>; export const quiskMountFactory =

(comp: ComponentConstructor

, dprops: DialogProps) => ( props: Mutable

, dRef?: (expose: { quit: () => void; submit: () => void }) => void ): Promise => { let ref: QuiskExpose; return new Promise((resolve) => { const api = { onQuit: async () => { const ret = ref.quit && ((await ref.quit()) as any); if (ret) { resolve(ret); } else { resolve(false as any); } destroy(); }, onSubmit: async () => { const ret = ref.submit && ((await ref.submit()) as any); if (ret) { resolve(ret); } else { resolve(true as any); } destroy(); }, }; const layoutProps = reactive({ ...dprops, ref: undefined, show: true, ...api, }); const destroy = mountComponent(Dialog, layoutProps, { default: () => createVNode(comp, { ...props, ref: (v: any) => { for (const key in v) { if (dialogPropsKeys.includes(key as any)) { (layoutProps as any)[key] = v[key]; } } ref = v; }, }), }); dRef && dRef({ submit: () => api.onSubmit(), quit: () => api.onQuit(), }); }); };