You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1 line
10 KiB

11 months ago
{"version":3,"file":"messageBox.mjs","sources":["../../../../../../packages/components/message-box/src/messageBox.ts"],"sourcesContent":["import { h, watch, render } from 'vue'\nimport { hasOwn } from '@vue/shared'\nimport { isClient } from '@vueuse/core'\nimport { isVNode, isString } from '@element-plus/utils/util'\nimport MessageBoxConstructor from './index.vue'\n\nimport type { ComponentPublicInstance, VNode } from 'vue'\nimport type {\n Action,\n Callback,\n MessageBoxState,\n IElMessageBox,\n ElMessageBoxOptions,\n MessageBoxData,\n} from './message-box.type'\n\n// component default merge props & data\n\nconst messageInstance = new Map<\n ComponentPublicInstance<{ doClose: () => void }>, // marking doClose as function\n {\n options: any\n callback: Callback\n resolve: (res: any) => void\n reject: (reason?: any) => void\n }\n>()\n\nconst initInstance = (props: any, container: HTMLElement) => {\n const vnode = h(MessageBoxConstructor, props)\n render(vnode, container)\n document.body.appendChild(container.firstElementChild)\n return vnode.component\n}\n\nconst genContainer = () => {\n return document.createElement('div')\n}\n\nconst showMessage = (options: any) => {\n const container = genContainer()\n // Adding destruct method.\n // when transition leaves emitting `vanish` evt. so that we can do the clean job.\n options.onVanish = () => {\n // not sure if this causes mem leak, need proof to verify that.\n // maybe calling out like 1000 msg-box then close them all.\n render(null, container)\n messageInstance.delete(vm) // Remove vm to avoid mem leak.\n // here we were suppose to call document.body.removeChild(container.firstElementChild)\n // but render(null, container) did that job for us. so that we do not call that directly\n }\n\n options.onAction = (action: Action) => {\n const currentMsg = messageInstance.get(vm)\n let resolve: Action | { value: string; action: Action }\n if (options.showInput) {\n resolve = { value: vm.inputValue, action }\n } else {\n resolve = action\n }\n if (options.callback) {\n options.callback(resolve, instance.proxy)\n } else {\n if (action === 'cancel' || action === 'close') {\n if (options.distinguishCancelAndClose && action !== 'cancel') {\n currentMsg.reject('close')\n } else {\n currentMsg.reject('cancel')\n }\n } else {\n currentMsg.resolve(resolve)\n }\n }\n }\n\n const instance = initInstance(options, container)\n\n // This is how we use message box programmably.\n // Maybe consider releasing a template version?\n // get component instance like v2.\n const vm = instance.proxy as ComponentPublicInstance<\n {\n visible: boolean\n doClose: () => void\n } & MessageBoxState\n >\n\n for (const prop in options) {\n if (hasOwn(options, prop) && !hasOwn(vm.$props, prop)) {\n vm[prop as string] = options[prop]\n }\n }\n\n watch(\n () => vm.message,\n (newVal, oldVal) => {\n if (isVNode(newVal)) {\n // Override slots since message is vnode type.\n instance.slots.default = () => [newVal]\n } else if (isVNode(oldVal) && !isVNode(newVal)) {\n delete instance.slots.default\n }\n },\n {\n immediate: true,\n }\n )\n\n // change visibility after everything is settled\n vm.visible = true\n return vm\n}\n\nasync function MessageBox(options: ElMessageBoxOptions): Promise<MessageBoxData>\nfunction MessageBox(\n options: ElMessageBoxOptions | string | VNode\n): Promise<{ value: string; action: Action } | Action> {\n if (!isClient) return\n let callback\n if (isString(options) || isVNode(options)) {\n options = {\n message: options,\n }\n } else {\n callback = options.callback\n }\n\n return new Promise((resolve, reject) => {\n const vm = showMessage(options)\n // collect this vm in order to handle upcoming events.\n messageInstance.set(vm, {\n options,\n callback,\n resolve,\n reject,\n })\n })\n}\n\nMess