import React from "react"; import { TransitionProps } from "react-transition-group/Transition"; import { Transition } from "../_util/transition"; import { BaseTransition } from "../transition/BaseTransition"; import { hashObject } from "../_util/hash-object"; import { insertCSS } from "../_util/insert-css"; const rootId = "tea-notification-root"; export function getRoot(classPrefix: string) { let root: HTMLElement = window[rootId] || document.getElementById(rootId); if (!root) { root = document.createElement("div"); root.id = rootId; root.className = `${classPrefix}-notification-wrap`; document.body.appendChild(root); window[rootId] = root; } return root; } const maxCountLimit = 3; const listKey = "tea-notification-list-identification"; interface NoticeItem { hide: () => void; renew: () => void; show: () => void; isExisted: () => boolean; identifier: string; } export function limit(notice: NoticeItem) { if (!window[listKey]) { window[listKey] = []; } if (notice.identifier) { const existedItem = (window[listKey] as NoticeItem[]).find( i => i.isExisted && i.isExisted() && i.identifier === notice.identifier ); // 存在相同内容,续期原内容 if (existedItem) { existedItem.renew(); return; } notice.show(); } else { notice.show(); } if (window[listKey].length >= maxCountLimit) { try { window[listKey][0].hide(); window[listKey].shift(); } catch (_) { // hide failed } } window[listKey].push(notice); } export interface NotificationTransitionProps extends Partial { /** * 动画元素目标高度 */ height?: number; } export function NotificationTransition(props: NotificationTransitionProps) { return ; } const generateCSS = (transition: Transition, targetMaxHeight: number) => ` .${transition.classNames}-enter { opacity: 0 !important; transform: translate3d(60px, 0px, 0); } .${transition.classNames}-enter-active { opacity: 1 !important; transform: translate3d(0, 0, 0); transition: opacity ${transition.timeout.enter}ms ease, transform ${transition.timeout.enter}ms ease; } .${transition.classNames}-exit { opacity: 1; max-height: ${targetMaxHeight}px; margin-bottom: 20px; } .${transition.classNames}-exit-active { max-height: 0; margin-bottom: 0 !important; opacity: 0; transition: max-height ${transition.timeout.exit}ms ease, margin-bottom ${transition.timeout.exit}ms ease, opacity ${transition.timeout.enter}ms ease; } `; const setupTransitions: { [hash: number]: Transition } = {}; export function transition( targetHeight = 150, enterTimeout = 300, leaveTimeout = 300 ) { const name = `tea-transition-notification`; const hash = hashObject({ name, targetHeight, enterTimeout, leaveTimeout }); if (!setupTransitions[hash]) { setupTransitions[hash] = { classNames: name + hash, timeout: { enter: enterTimeout, exit: leaveTimeout, }, unmountOnExit: true, mountOnEnter: true, }; const transition = setupTransitions[hash]; const css = generateCSS(transition, targetHeight); insertCSS(name + hash, css); } return setupTransitions[hash]; }