UNPKG

@fesjs/fes-design

Version:
142 lines (139 loc) 3.99 kB
import { defineComponent, ref, onBeforeUnmount, cloneVNode, createVNode, TransitionGroup, createApp, onMounted, mergeProps } from 'vue'; import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties'; import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled, ExclamationCircleFilled } from '../icon'; import { useTheme } from '../_theme/useTheme'; import { getFirstValidNode } from './vnode'; const _excluded = ["getContainer"]; let seed = 0; const now = Date.now(); function genUid() { return `notice_manager_${now}_${seed++}`; } const Notification = defineComponent({ props: { maxCount: Number, transitionName: String }, setup(props) { const notices = ref([]); const timers = new Set(); function remove(key) { const index = notices.value.findIndex(item => item.key === key); const notice = notices.value[index]; if (notice) { var _notice$afterRemove; notices.value.splice(index, 1); (_notice$afterRemove = notice.afterRemove) === null || _notice$afterRemove === void 0 || _notice$afterRemove.call(notice); } } function append(notice) { if (!notice.key) { notice.key = genUid(); } if (props.maxCount && notices.value.length >= props.maxCount) { notices.value.shift(); } notices.value.push(notice); if (notice.duration > 0) { const timer = setTimeout(() => { remove(notice.key); clearTimeout(timer); }, notice.duration * 1000); timers.add(timer); } return notice; } onBeforeUnmount(() => { // 清理所有未触发的定时器 timers.forEach(timer => { clearTimeout(timer); }); timers.clear(); }); return { notices, append, remove }; }, render() { const { notices, transitionName } = this; const children = notices.map(notice => { let vNode = typeof notice.children === 'function' ? notice.children() : notice.children; vNode = getFirstValidNode([vNode]); if (vNode) { return cloneVNode(vNode, { key: notice.key }); } }); return createVNode(TransitionGroup, { "name": transitionName, "tag": "div" }, { default: () => [children] }); } }); function createManager(opt) { return new Promise(resolve => { const { getContainer } = opt, props = _objectWithoutProperties(opt, _excluded); const div = document.createElement('div'); if (getContainer) { const root = getContainer(); root === null || root === void 0 || root.appendChild(div); } else { document.body.appendChild(div); } const app = createApp({ setup() { useTheme(); const notificationRef = ref(); const instance = { append: noticeProps => notificationRef.value.append(noticeProps), remove: key => notificationRef.value.remove(key), destroy() { app.unmount(); if (div.parentNode) { div.parentNode.removeChild(div); } }, exited() { // 容器是否存在 if (!getContainer) { return true; } try { if (!getContainer()) { instance.destroy(); return false; } } catch (error) { instance.destroy(); return false; } return true; } }; onMounted(() => resolve(instance)); return () => createVNode(Notification, mergeProps({ "ref": notificationRef }, props), null); } }); app.mount(div); }); } const iconComponentMap = { info: InfoCircleFilled, success: CheckCircleFilled, error: CloseCircleFilled, warning: ExclamationCircleFilled }; export { createManager, iconComponentMap };