import { cloneDeep } from "bolt-ui/utils/func"; import { BoDialog } from "bolt-ui"; import { defineComponent, Fragment, h, markRaw, nextTick, onScopeDispose, reactive, ref, resolveComponent, shallowRef, useAttrs, } from "vue"; import { createDialogContext } from "./context"; import { IDialogState } from "./type"; import useAsyncComponent from "bolt-ui/hooks/useAsyncComponent"; export interface LawDialogHookOptions { props?: object; dialogProps?: object; title?: string; argus?: object; autoInject?: boolean; renderUI: any; } let createComponentInModal = (opts: any) => { const { state, renderUI, _ } = opts; return defineComponent({ name: "LawDialog", setup(props: any, { slots, expose }) { const attrs = useAttrs() as any; const haveDefaule = !!slots?.default; const action = { show: _.show, hide: _.hide, }; createDialogContext([state, action]); const F = () => { return h(renderUI, { ...attrs, ...state.props }, () => []); }; const cloneAttrs = cloneDeep(attrs ?? {}); delete cloneAttrs.dialogProp return () => h( BoDialog, { show: state.visible, ["onUpdate:show"]: (e: any) => (state.visible = e), ...(attrs.dialogProps ?? {}), ...(state.dialogProps ?? {}), }, { default: () => h(Fragment, [ haveDefaule ? slots?.default?.({ ...cloneAttrs, ...state.props, }) : !!renderUI && h(F), ]), } ); }, }); }; function useDialog({ argus = {}, props = {}, dialogProps = {}, renderUI, autoInject = true, }: LawDialogHookOptions) { if (!createComponentInModal) { console.warn("请定义一个Modal组件控制器"); return new Proxy( {}, { get(target, p, receiver) { console.warn("请定义一个Modal组件控制器"); return; }, } ) as any; } const state = reactive({ visible: false, dialogProps: cloneDeep(dialogProps), props: cloneDeep(props), argus: cloneDeep(argus), }); let showResolve; function show(props, argus = {}) { state.props = props; state.argus = argus; let newState: IDialogState = { visible: true, }; Object.assign(state, newState); return new Promise((resolve, reject) => { showResolve = resolve; }); } const _ = { show, hide(value) { showResolve?.(value); state.visible = false; }, UI: null, }; if (typeof renderUI === "function") { renderUI = useAsyncComponent(renderUI); } const component = markRaw( createComponentInModal({ state, renderUI, _, }) ); _.UI = component; let markRawUI = markRaw(_.UI); if (autoInject) { allModals.value.push(markRawUI); // @ts-ignore _.destory = () => { let index = -1; for (let i = 0; i < allModals.value.length; i++) { const modal = allModals.value[i]; if (modal === markRawUI) { index = i; break; } } if (index !== -1) { allModals.value.splice(index, 1); } }; onScopeDispose(() => { let index = -1; for (let i = 0; i < allModals.value.length; i++) { const modal = allModals.value[i]; if (modal === markRawUI) { index = i; break; } } if (index !== -1) { allModals.value.splice(index, 1); } }); } return _; } const allModals = ref([]); export function ModalContainer() { const attrs = useAttrs() return h( Fragment, {}, allModals.value.map((V) => { return h(V, { dialogProps: attrs }); }) ); } export { useDialog }; export default useDialog;