UNPKG

element-plus

Version:

A Component Library for Vue3.0

593 lines (580 loc) 22.1 kB
import { defineComponent, ref, reactive, computed, watch, nextTick, onMounted, onBeforeUnmount, resolveComponent, resolveDirective, openBlock, createBlock, Transition, withCtx, withDirectives, createVNode, withModifiers, createCommentVNode, toDisplayString, withKeys, renderSlot, vShow, createTextVNode, render as render$1, h } from 'vue'; import ElButton from '../el-button'; import ElInput from '../el-input'; import { t } from '../locale'; import { Overlay } from '../el-overlay'; import { useModal, usePreventGlobal, useLockScreen, useRestoreActive } from '../hooks'; import { TrapFocus } from '../directives'; import PopupManager from '../utils/popup-manager'; import { on, off } from '../utils/dom'; import { EVENT_CODE } from '../utils/aria'; import isServer from '../utils/isServer'; import { isString, isVNode } from '../utils/util'; /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } const TypeMap = { success: 'success', info: 'info', warning: 'warning', error: 'error', }; var script = defineComponent({ name: 'ElMessageBox', components: { ElButton, ElInput, ElOverlay: Overlay, }, directives: { TrapFocus, }, props: { beforeClose: { type: Function, default: undefined, }, callback: Function, cancelButtonText: { type: String, }, cancelButtonClass: String, center: Boolean, closeOnClickModal: { type: Boolean, default: true, }, closeOnPressEscape: { type: Boolean, default: true, }, closeOnHashChange: { type: Boolean, default: true, }, confirmButtonText: { type: String, }, confirmButtonClass: String, container: { type: String, default: 'body', }, customClass: String, dangerouslyUseHTMLString: Boolean, distinguishCancelAndClose: Boolean, iconClass: String, inputPattern: { type: Object, default: () => undefined, validator: (val) => (val instanceof RegExp || val === 'undefined'), }, inputPlaceholder: { type: String, }, inputType: { type: String, default: 'text', }, inputValue: { type: String, }, inputValidator: { type: Function, default: null, }, inputErrorMessage: String, lockScroll: { type: Boolean, default: true, }, message: String, modalFade: { type: Boolean, default: true, }, modalClass: String, modal: { type: Boolean, default: true, }, roundButton: Boolean, showCancelButton: Boolean, showConfirmButton: { type: Boolean, default: true, }, showClose: { type: Boolean, default: true, }, type: String, title: String, showInput: Boolean, zIndex: Number, }, emits: ['vanish', 'action'], setup(props, { emit }) { const visible = ref(false); const state = reactive({ action: '', inputValue: props.inputValue, confirmButtonLoading: false, cancelButtonLoading: false, cancelButtonText: props.cancelButtonText, confirmButtonDisabled: false, confirmButtonText: props.confirmButtonText, editorErrorMessage: '', validateError: false, zIndex: PopupManager.nextZIndex(), }); const icon = computed(() => props.iconClass || (props.type && TypeMap[props.type] ? `el-icon-${TypeMap[props.type]}` : '')); const hasMessage = computed(() => !!props.message); const inputRef = ref(null); const confirmRef = ref(null); const confirmButtonClasses = computed(() => `el-button--primary ${props.confirmButtonClass}`); watch(() => state.inputValue, (val) => __awaiter(this, void 0, void 0, function* () { yield nextTick(); if (props.type === 'prompt' && val !== null) { validate(); } }), { immediate: true }); watch(() => visible.value, val => { if (val) { if (props.type === 'alert' || props.type === 'confirm') { nextTick().then(() => { var _a, _b, _c; (_c = (_b = (_a = confirmRef.value) === null || _a === void 0 ? void 0 : _a.$el) === null || _b === void 0 ? void 0 : _b.focus) === null || _c === void 0 ? void 0 : _c.call(_b); }); } state.zIndex = PopupManager.nextZIndex(); } if (props.type !== 'prompt') return; if (val) { nextTick().then(() => { if (inputRef.value && inputRef.value.$el) { getInputElement().focus(); } }); } else { state.editorErrorMessage = ''; state.validateError = false; } }); onMounted(() => __awaiter(this, void 0, void 0, function* () { yield nextTick(); if (props.closeOnHashChange) { on(window, 'hashchange', doClose); } })); onBeforeUnmount(() => { if (props.closeOnHashChange) { off(window, 'hashchange', doClose); } }); function doClose() { if (!visible.value) return; visible.value = false; nextTick(() => { if (state.action) emit('action', state.action); }); } const handleWrapperClick = () => { if (props.closeOnClickModal) { handleAction(props.distinguishCancelAndClose ? 'close' : 'cancel'); } }; const handleInputEnter = () => { if (props.inputType !== 'textarea') { return handleAction('confirm'); } }; const handleAction = (action) => { var _a; if (props.type === 'prompt' && action === 'confirm' && !validate()) { return; } state.action = action; if (props.beforeClose) { (_a = props.beforeClose) === null || _a === void 0 ? void 0 : _a.call(props, action, state, doClose); } else { doClose(); } }; const validate = () => { if (props.type === 'prompt') { const inputPattern = props.inputPattern; if (inputPattern && !inputPattern.test(state.inputValue || '')) { state.editorErrorMessage = props.inputErrorMessage || t('el.messagebox.error'); state.validateError = true; return false; } const inputValidator = props.inputValidator; if (typeof inputValidator === 'function') { const validateResult = inputValidator(state.inputValue); if (validateResult === false) { state.editorErrorMessage = props.inputErrorMessage || t('el.messagebox.error'); state.validateError = true; return false; } if (typeof validateResult === 'string') { state.editorErrorMessage = validateResult; state.validateError = true; return false; } } } state.editorErrorMessage = ''; state.validateError = false; return true; }; const getInputElement = () => { const inputRefs = inputRef.value.$refs; return (inputRefs.input || inputRefs.textarea); }; const handleClose = () => { handleAction('close'); }; if (props.closeOnPressEscape) { useModal({ handleClose, }, visible); } else { usePreventGlobal(visible, 'keydown', (e) => e.code === EVENT_CODE.esc); } if (props.lockScroll) { useLockScreen(visible); } useRestoreActive(visible); return { state, visible, hasMessage, icon, confirmButtonClasses, inputRef, confirmRef, doClose, handleClose, handleWrapperClick, handleInputEnter, handleAction, t, }; }, }); const _hoisted_1 = { key: 0, class: "el-message-box__header" }; const _hoisted_2 = { class: "el-message-box__title" }; const _hoisted_3 = /*#__PURE__*/createVNode("i", { class: "el-message-box__close el-icon-close" }, null, -1 /* HOISTED */); const _hoisted_4 = { class: "el-message-box__content" }; const _hoisted_5 = { class: "el-message-box__container" }; const _hoisted_6 = { key: 1, class: "el-message-box__message" }; const _hoisted_7 = { key: 0 }; const _hoisted_8 = { class: "el-message-box__input" }; const _hoisted_9 = { class: "el-message-box__btns" }; function render(_ctx, _cache, $props, $setup, $data, $options) { const _component_el_input = resolveComponent("el-input"); const _component_el_button = resolveComponent("el-button"); const _component_el_overlay = resolveComponent("el-overlay"); const _directive_trap_focus = resolveDirective("trap-focus"); return (openBlock(), createBlock(Transition, { name: "fade-in-linear", onAfterLeave: _cache[8] || (_cache[8] = $event => (_ctx.$emit('vanish'))) }, { default: withCtx(() => [ withDirectives(createVNode(_component_el_overlay, { "z-index": _ctx.state.zIndex, "overlay-class": ['is-message-box', _ctx.modalClass], mask: _ctx.modal, onClick: withModifiers(_ctx.handleWrapperClick, ["self"]) }, { default: withCtx(() => [ withDirectives(createVNode("div", { ref: "root", "aria-label": _ctx.title || 'dialog', "aria-modal": "true", class: [ 'el-message-box', _ctx.customClass, { 'el-message-box--center': _ctx.center }, ] }, [ (_ctx.title !== null && _ctx.title !== undefined) ? (openBlock(), createBlock("div", _hoisted_1, [ createVNode("div", _hoisted_2, [ (_ctx.icon && _ctx.center) ? (openBlock(), createBlock("div", { key: 0, class: ['el-message-box__status', _ctx.icon] }, null, 2 /* CLASS */)) : createCommentVNode("v-if", true), createVNode("span", null, toDisplayString(_ctx.title), 1 /* TEXT */) ]), (_ctx.showClose) ? (openBlock(), createBlock("button", { key: 0, type: "button", class: "el-message-box__headerbtn", "aria-label": "Close", onClick: _cache[1] || (_cache[1] = $event => ( _ctx.handleAction(_ctx.distinguishCancelAndClose ? 'close' : 'cancel') )), onKeydown: _cache[2] || (_cache[2] = withKeys($event => ( _ctx.handleAction(_ctx.distinguishCancelAndClose ? 'close' : 'cancel') ), ["enter"])) }, [ _hoisted_3 ], 32 /* HYDRATE_EVENTS */)) : createCommentVNode("v-if", true) ])) : createCommentVNode("v-if", true), createVNode("div", _hoisted_4, [ createVNode("div", _hoisted_5, [ (_ctx.icon && !_ctx.center && _ctx.hasMessage) ? (openBlock(), createBlock("div", { key: 0, class: ['el-message-box__status', _ctx.icon] }, null, 2 /* CLASS */)) : createCommentVNode("v-if", true), (_ctx.hasMessage) ? (openBlock(), createBlock("div", _hoisted_6, [ renderSlot(_ctx.$slots, "default", {}, () => [ (!_ctx.dangerouslyUseHTMLString) ? (openBlock(), createBlock("p", _hoisted_7, toDisplayString(_ctx.message), 1 /* TEXT */)) : (openBlock(), createBlock("p", { key: 1, innerHTML: _ctx.message }, null, 8 /* PROPS */, ["innerHTML"])) ]) ])) : createCommentVNode("v-if", true) ]), withDirectives(createVNode("div", _hoisted_8, [ createVNode(_component_el_input, { ref: "inputRef", modelValue: _ctx.state.inputValue, "onUpdate:modelValue": _cache[3] || (_cache[3] = $event => (_ctx.state.inputValue = $event)), type: _ctx.inputType, placeholder: _ctx.inputPlaceholder, class: { invalid: _ctx.state.validateError }, onKeydown: withKeys(withModifiers(_ctx.handleInputEnter, ["prevent"]), ["enter"]) }, null, 8 /* PROPS */, ["modelValue", "type", "placeholder", "class", "onKeydown"]), createVNode("div", { class: "el-message-box__errormsg", style: { visibility: !!_ctx.state.editorErrorMessage ? 'visible' : 'hidden', } }, toDisplayString(_ctx.state.editorErrorMessage), 5 /* TEXT, STYLE */) ], 512 /* NEED_PATCH */), [ [vShow, _ctx.showInput] ]) ]), createVNode("div", _hoisted_9, [ (_ctx.showCancelButton) ? (openBlock(), createBlock(_component_el_button, { key: 0, loading: _ctx.state.cancelButtonLoading, class: [_ctx.cancelButtonClass], round: _ctx.roundButton, size: "small", onClick: _cache[4] || (_cache[4] = $event => (_ctx.handleAction('cancel'))), onKeydown: _cache[5] || (_cache[5] = withKeys($event => (_ctx.handleAction('cancel')), ["enter"])) }, { default: withCtx(() => [ createTextVNode(toDisplayString(_ctx.state.cancelButtonText || _ctx.t('el.messagebox.cancel')), 1 /* TEXT */) ]), _: 1 /* STABLE */ }, 8 /* PROPS */, ["loading", "class", "round"])) : createCommentVNode("v-if", true), withDirectives(createVNode(_component_el_button, { ref: "confirmRef", loading: _ctx.state.confirmButtonLoading, class: [_ctx.confirmButtonClasses], round: _ctx.roundButton, disabled: _ctx.state.confirmButtonDisabled, size: "small", onClick: _cache[6] || (_cache[6] = $event => (_ctx.handleAction('confirm'))), onKeydown: _cache[7] || (_cache[7] = withKeys($event => (_ctx.handleAction('confirm')), ["enter"])) }, { default: withCtx(() => [ createTextVNode(toDisplayString(_ctx.state.confirmButtonText || _ctx.t('el.messagebox.confirm')), 1 /* TEXT */) ]), _: 1 /* STABLE */ }, 8 /* PROPS */, ["loading", "class", "round", "disabled"]), [ [vShow, _ctx.showConfirmButton] ]) ]) ], 10 /* CLASS, PROPS */, ["aria-label"]), [ [_directive_trap_focus] ]) ]), _: 1 /* STABLE */ }, 8 /* PROPS */, ["z-index", "overlay-class", "mask", "onClick"]), [ [vShow, _ctx.visible] ]) ]), _: 1 /* STABLE */ })) } script.render = render; script.__file = "packages/message-box/src/index.vue"; const messageInstance = new Map(); const initInstance = (props, container) => { const vnode = h(script, props); render$1(vnode, container); document.body.appendChild(container.firstElementChild); return vnode.component; }; const genContainer = () => { return document.createElement('div'); }; const showMessage = (options) => { const container = genContainer(); options.onVanish = () => { render$1(null, container); messageInstance.delete(vm); }; options.onAction = (action) => { const currentMsg = messageInstance.get(vm); let resolve; if (options.showInput) { resolve = { value: vm.state.inputValue, action }; } else { resolve = action; } if (options.callback) { options.callback(resolve, instance.proxy); } else { if (action === 'cancel' || action === 'close') { if (options.distinguishCancelAndClose && action !== 'cancel') { currentMsg.reject('close'); } else { currentMsg.reject('cancel'); } } else { currentMsg.resolve(resolve); } } }; const instance = initInstance(options, container); const vm = instance.proxy; if (isVNode(options.message)) { instance.slots.default = () => [options.message]; } vm.visible = true; return vm; }; function MessageBox(options) { if (isServer) return; let callback; if (isString(options) || isVNode(options)) { options = { message: options, }; } else { callback = options.callback; } return new Promise((resolve, reject) => { const vm = showMessage(options); messageInstance.set(vm, { options, callback, resolve, reject, }); }); } MessageBox.alert = (message, title, options) => { if (typeof title === 'object') { options = title; title = ''; } else if (title === undefined) { title = ''; } return MessageBox(Object.assign({ title: title, message: message, type: 'alert', closeOnPressEscape: false, closeOnClickModal: false, }, options)); }; MessageBox.confirm = (message, title, options) => { if (typeof title === 'object') { options = title; title = ''; } else if (title === undefined) { title = ''; } return MessageBox(Object.assign({ title: title, message: message, type: 'confirm', showCancelButton: true, }, options)); }; MessageBox.prompt = (message, title, options) => { if (typeof title === 'object') { options = title; title = ''; } else if (title === undefined) { title = ''; } return MessageBox(Object.assign({ title: title, message: message, showCancelButton: true, showInput: true, type: 'prompt', }, options)); }; MessageBox.close = () => { messageInstance.forEach((_, vm) => { vm.doClose(); }); messageInstance.clear(); }; MessageBox.install = (app) => { app.config.globalProperties.$msgbox = MessageBox; app.config.globalProperties.$messageBox = MessageBox; app.config.globalProperties.$alert = MessageBox.alert; app.config.globalProperties.$confirm = MessageBox.confirm; app.config.globalProperties.$prompt = MessageBox.prompt; }; export default MessageBox;