164 lines
4.5 KiB
JavaScript
164 lines
4.5 KiB
JavaScript
import { nextTick, Transition, h, defineComponent, ref, onMounted, inject } from 'vue';
|
|
import { keep } from "../../_utils/index.mjs";
|
|
import { notificationProviderInjectionKey } from "./context.mjs";
|
|
import { Notification, notificationProps, notificationPropKeys } from "./Notification.mjs";
|
|
export const notificationEnvOptions = Object.assign(Object.assign({}, notificationProps), {
|
|
duration: Number,
|
|
onClose: Function,
|
|
onLeave: Function,
|
|
onAfterEnter: Function,
|
|
onAfterLeave: Function,
|
|
/** @deprecated */
|
|
onHide: Function,
|
|
/** @deprecated */
|
|
onAfterShow: Function,
|
|
/** @deprecated */
|
|
onAfterHide: Function
|
|
});
|
|
export const NotificationEnvironment = defineComponent({
|
|
name: 'NotificationEnvironment',
|
|
props: Object.assign(Object.assign({}, notificationEnvOptions), {
|
|
// private
|
|
internalKey: {
|
|
type: String,
|
|
required: true
|
|
},
|
|
onInternalAfterLeave: {
|
|
type: Function,
|
|
required: true
|
|
}
|
|
}),
|
|
setup(props) {
|
|
const {
|
|
wipTransitionCountRef
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
} = inject(notificationProviderInjectionKey);
|
|
const showRef = ref(true);
|
|
let timerId = null;
|
|
function hide() {
|
|
showRef.value = false;
|
|
if (timerId) {
|
|
window.clearTimeout(timerId);
|
|
}
|
|
}
|
|
function handleBeforeEnter(el) {
|
|
wipTransitionCountRef.value++;
|
|
void nextTick(() => {
|
|
el.style.height = `${el.offsetHeight}px`;
|
|
el.style.maxHeight = '0';
|
|
el.style.transition = 'none';
|
|
void el.offsetHeight;
|
|
el.style.transition = '';
|
|
el.style.maxHeight = el.style.height;
|
|
});
|
|
}
|
|
function handleAfterEnter(el) {
|
|
wipTransitionCountRef.value--;
|
|
el.style.height = '';
|
|
el.style.maxHeight = '';
|
|
const {
|
|
onAfterEnter,
|
|
onAfterShow
|
|
} = props;
|
|
if (onAfterEnter) onAfterEnter();
|
|
// deprecated
|
|
if (onAfterShow) onAfterShow();
|
|
}
|
|
function handleBeforeLeave(el) {
|
|
wipTransitionCountRef.value++;
|
|
el.style.maxHeight = `${el.offsetHeight}px`;
|
|
el.style.height = `${el.offsetHeight}px`;
|
|
void el.offsetHeight;
|
|
}
|
|
function handleLeave(el) {
|
|
const {
|
|
onHide
|
|
} = props;
|
|
if (onHide) onHide();
|
|
el.style.maxHeight = '0';
|
|
void el.offsetHeight;
|
|
}
|
|
function handleAfterLeave() {
|
|
wipTransitionCountRef.value--;
|
|
const {
|
|
onAfterLeave,
|
|
onInternalAfterLeave,
|
|
onAfterHide,
|
|
internalKey
|
|
} = props;
|
|
if (onAfterLeave) onAfterLeave();
|
|
onInternalAfterLeave(internalKey);
|
|
// deprecated
|
|
if (onAfterHide) onAfterHide();
|
|
}
|
|
function setHideTimeout() {
|
|
const {
|
|
duration
|
|
} = props;
|
|
if (duration) {
|
|
timerId = window.setTimeout(hide, duration);
|
|
}
|
|
}
|
|
function handleMouseenter(e) {
|
|
if (e.currentTarget !== e.target) return;
|
|
if (timerId !== null) {
|
|
window.clearTimeout(timerId);
|
|
timerId = null;
|
|
}
|
|
}
|
|
function handleMouseleave(e) {
|
|
if (e.currentTarget !== e.target) return;
|
|
setHideTimeout();
|
|
}
|
|
function handleClose() {
|
|
const {
|
|
onClose
|
|
} = props;
|
|
if (onClose) {
|
|
void Promise.resolve(onClose()).then(feedback => {
|
|
if (feedback === false) return;
|
|
hide();
|
|
});
|
|
} else {
|
|
hide();
|
|
}
|
|
}
|
|
onMounted(() => {
|
|
if (props.duration) {
|
|
timerId = window.setTimeout(hide, props.duration);
|
|
}
|
|
});
|
|
return {
|
|
show: showRef,
|
|
hide,
|
|
handleClose,
|
|
handleAfterLeave,
|
|
handleLeave,
|
|
handleBeforeLeave,
|
|
handleAfterEnter,
|
|
handleBeforeEnter,
|
|
handleMouseenter,
|
|
handleMouseleave
|
|
};
|
|
},
|
|
render() {
|
|
return h(Transition, {
|
|
name: "notification-transition",
|
|
appear: true,
|
|
// convert to any since Element is not compatible with HTMLElement
|
|
onBeforeEnter: this.handleBeforeEnter,
|
|
onAfterEnter: this.handleAfterEnter,
|
|
onBeforeLeave: this.handleBeforeLeave,
|
|
onLeave: this.handleLeave,
|
|
onAfterLeave: this.handleAfterLeave
|
|
}, {
|
|
default: () => {
|
|
return this.show ? h(Notification, Object.assign({}, keep(this.$props, notificationPropKeys), {
|
|
onClose: this.handleClose,
|
|
onMouseenter: this.duration && this.keepAliveOnHover ? this.handleMouseenter : undefined,
|
|
onMouseleave: this.duration && this.keepAliveOnHover ? this.handleMouseleave : undefined
|
|
})) : null;
|
|
}
|
|
});
|
|
}
|
|
}); |