import type { Key } from '../_util/type'; import { Teleport, computed, defineComponent, onMounted, watch, onUnmounted } from 'vue'; import type { HTMLAttributes, CSSProperties } from 'vue'; import type { MouseEventHandler } from '../_util/EventInterface'; import classNames from '../_util/classNames'; interface DivProps extends HTMLAttributes { // Ideally we would allow all data-* props but this would depend on https://github.com/microsoft/TypeScript/issues/28960 'data-testid'?: string; } export interface NoticeProps { prefixCls: string; duration?: number | null; updateMark?: string; /** Mark as final key since set maxCount may keep the key but user pass key is different */ noticeKey: Key; closeIcon?: any; closable?: boolean; props?: DivProps; onClick?: MouseEventHandler; onClose?: (key: Key) => void; /** @private Only for internal usage. We don't promise that we will refactor this */ holder?: HTMLDivElement; /** @private Provided by CSSMotionList */ visible?: boolean; } export default defineComponent({ name: 'Notice', inheritAttrs: false, props: [ 'prefixCls', 'duration', 'updateMark', 'noticeKey', 'closeIcon', 'closable', 'props', 'onClick', 'onClose', 'holder', 'visible', ] as any, setup(props, { attrs, slots }) { let closeTimer: any; let isUnMounted = false; const duration = computed(() => (props.duration === undefined ? 4.5 : props.duration)); const startCloseTimer = () => { if (duration.value && !isUnMounted) { closeTimer = setTimeout(() => { close(); }, duration.value * 1000); } }; const clearCloseTimer = () => { if (closeTimer) { clearTimeout(closeTimer); closeTimer = null; } }; const close = (e?: MouseEvent) => { if (e) { e.stopPropagation(); } clearCloseTimer(); const { onClose, noticeKey } = props; if (onClose) { onClose(noticeKey); } }; const restartCloseTimer = () => { clearCloseTimer(); startCloseTimer(); }; onMounted(() => { startCloseTimer(); }); onUnmounted(() => { isUnMounted = true; clearCloseTimer(); }); watch( [duration, () => props.updateMark, () => props.visible], ([preDuration, preUpdateMark, preVisible], [newDuration, newUpdateMark, newVisible]) => { if ( preDuration !== newDuration || preUpdateMark !== newUpdateMark || (preVisible !== newVisible && newVisible) ) { restartCloseTimer(); } }, { flush: 'post' }, ); return () => { const { prefixCls, closable, closeIcon = slots.closeIcon?.(), onClick, holder } = props; const { class: className, style } = attrs; const componentClass = `${prefixCls}-notice`; const dataOrAriaAttributeProps = Object.keys(attrs).reduce( (acc: Record, key: string) => { if (key.substr(0, 5) === 'data-' || key.substr(0, 5) === 'aria-' || key === 'role') { acc[key] = (attrs as any)[key]; } return acc; }, {}, ); const node = (
{slots.default?.()}
{closable ? ( {closeIcon || } ) : null}
); if (holder) { return node }}>; } return node; }; }, });