UNPKG

element-plus

Version:

A Component Library for Vue3.0

277 lines (266 loc) 9.04 kB
import { defineComponent, computed, ref, onMounted, onBeforeUnmount, openBlock, createBlock, Transition, withCtx, withDirectives, createVNode, createCommentVNode, renderSlot, toDisplayString, Fragment, withModifiers, vShow, render as render$1 } from 'vue'; import { isVNode } from '../utils/util'; import PopupManager from '../utils/popup-manager'; import isServer from '../utils/isServer'; const EVENT_CODE = { tab: 'Tab', enter: 'Enter', space: 'Space', left: 'ArrowLeft', up: 'ArrowUp', right: 'ArrowRight', down: 'ArrowDown', esc: 'Escape', delete: 'Delete', backspace: 'Backspace', }; /** * Make a map and return a function for checking if a key * is in that map. * IMPORTANT: all calls of this function must be prefixed with * \/\*#\_\_PURE\_\_\*\/ * So that rollup can tree-shake them if necessary. */ const EMPTY_OBJ = (process.env.NODE_ENV !== 'production') ? Object.freeze({}) : {}; const EMPTY_ARR = (process.env.NODE_ENV !== 'production') ? Object.freeze([]) : []; const on = function (element, event, handler, useCapture = false) { if (element && event && handler) { element.addEventListener(event, handler, useCapture); } }; const off = function (element, event, handler, useCapture = false) { if (element && event && handler) { element.removeEventListener(event, handler, useCapture); } }; const TypeMap = { success: 'success', info: 'info', warning: 'warning', error: 'error', }; var script = defineComponent({ name: 'ElMessage', props: { customClass: { type: String, default: '' }, center: { type: Boolean, default: false }, dangerouslyUseHTMLString: { type: Boolean, default: false }, duration: { type: Number, default: 3000 }, iconClass: { type: String, default: '' }, id: { type: String, default: '' }, message: { type: [String, Object], default: '', }, onClose: { type: Function, required: true, }, showClose: { type: Boolean, default: false }, type: { type: String, default: 'info' }, offset: { type: Number, default: 20 }, zIndex: { type: Number, default: 0 }, }, emits: ['destroy'], setup(props) { const typeClass = computed(() => { const type = props.type; return type && TypeMap[type] ? `el-message__icon el-icon-${TypeMap[type]}` : ''; }); const customStyle = computed(() => { return { top: `${props.offset}px`, zIndex: props.zIndex, }; }); const visible = ref(false); let timer = null; function startTimer() { if (props.duration > 0) { timer = setTimeout(() => { if (visible.value) { close(); } }, props.duration); } } function clearTimer() { clearTimeout(timer); timer = null; } function close() { visible.value = false; } function keydown({ code }) { if (code === EVENT_CODE.esc) { if (visible.value) { close(); } } else { startTimer(); } } onMounted(() => { startTimer(); visible.value = true; on(document, 'keydown', keydown); }); onBeforeUnmount(() => { off(document, 'keydown', keydown); }); return { typeClass, customStyle, visible, close, clearTimer, startTimer, }; }, }); const _hoisted_1 = { key: 0, class: "el-message__content" }; function render(_ctx, _cache, $props, $setup, $data, $options) { return (openBlock(), createBlock(Transition, { name: "el-message-fade", onBeforeLeave: _ctx.onClose, onAfterLeave: _cache[4] || (_cache[4] = $event => (_ctx.$emit('destroy'))) }, { default: withCtx(() => [ withDirectives(createVNode("div", { id: _ctx.id, class: [ 'el-message', _ctx.type && !_ctx.iconClass ? `el-message--${_ctx.type}` : '', _ctx.center ? 'is-center' : '', _ctx.showClose ? 'is-closable' : '', _ctx.customClass, ], style: _ctx.customStyle, role: "alert", onMouseenter: _cache[2] || (_cache[2] = (...args) => (_ctx.clearTimer && _ctx.clearTimer(...args))), onMouseleave: _cache[3] || (_cache[3] = (...args) => (_ctx.startTimer && _ctx.startTimer(...args))) }, [ (_ctx.type || _ctx.iconClass) ? (openBlock(), createBlock("i", { key: 0, class: [_ctx.typeClass, _ctx.iconClass] }, null, 2 /* CLASS */)) : createCommentVNode("v-if", true), renderSlot(_ctx.$slots, "default", {}, () => [ (!_ctx.dangerouslyUseHTMLString) ? (openBlock(), createBlock("p", _hoisted_1, toDisplayString(_ctx.message), 1 /* TEXT */)) : (openBlock(), createBlock(Fragment, { key: 1 }, [ createCommentVNode(" Caution here, message could've been compromised, never use user's input as message "), createCommentVNode(" eslint-disable-next-line "), createVNode("p", { class: "el-message__content", innerHTML: _ctx.message }, null, 8 /* PROPS */, ["innerHTML"]) ], 64 /* STABLE_FRAGMENT */)) ]), (_ctx.showClose) ? (openBlock(), createBlock("div", { key: 1, class: "el-message__closeBtn el-icon-close", onClick: _cache[1] || (_cache[1] = withModifiers((...args) => (_ctx.close && _ctx.close(...args)), ["stop"])) })) : createCommentVNode("v-if", true) ], 46 /* CLASS, STYLE, PROPS, HYDRATE_EVENTS */, ["id"]), [ [vShow, _ctx.visible] ]) ]), _: 3 /* FORWARDED */ }, 8 /* PROPS */, ["onBeforeLeave"])) } script.render = render; script.__file = "packages/message/src/index.vue"; const instances = []; let seed = 1; const Message = function (opts = {}) { if (isServer) return; if (typeof opts === 'string') { opts = { message: opts, }; } let options = opts; let verticalOffset = opts.offset || 20; instances.forEach(({ vm }) => { verticalOffset += (vm.el.offsetHeight || 0) + 16; }); verticalOffset += 16; const id = 'message_' + seed++; const userOnClose = options.onClose; options = Object.assign(Object.assign({}, options), { onClose: () => { close(id, userOnClose); }, offset: verticalOffset, id, zIndex: PopupManager.nextZIndex() }); const container = document.createElement('div'); container.className = `container_${id}`; const message = options.message; const vm = createVNode(script, options, isVNode(options.message) ? { default: () => message } : null); vm.props.onDestroy = () => { render$1(null, container); }; render$1(vm, container); instances.push({ vm }); document.body.appendChild(container.firstElementChild); return { close: () => vm.component.proxy.visible = false, }; }; function close(id, userOnClose) { const idx = instances.findIndex(({ vm }) => { const { id: _id } = vm.component.props; return id === _id; }); if (idx === -1) { return; } const { vm } = instances[idx]; if (!vm) return; userOnClose === null || userOnClose === void 0 ? void 0 : userOnClose(vm); const removedHeight = vm.el.offsetHeight; instances.splice(idx, 1); const len = instances.length; if (len < 1) return; for (let i = idx; i < len; i++) { const pos = parseInt(instances[i].vm.el.style['top'], 10) - removedHeight - 16; instances[i].vm.component.props.offset = pos; } } function closeAll() { for (let i = instances.length - 1; i >= 0; i--) { const instance = instances[i].vm.component; instance.ctx.close(); } } ['success', 'warning', 'info', 'error'].forEach(type => { Message[type] = options => { if (typeof options === 'string') { options = { message: options, type, }; } else { options.type = type; } return Message(options); }; }); Message.closeAll = closeAll; Message.install = (app) => { app.config.globalProperties.$message = Message; }; export default Message;