From 48ed69b35eaed28ec12428e86e927e81db637b39 Mon Sep 17 00:00:00 2001 From: Rick <rick@belniakmedia.com> Date: Sat, 23 Nov 2024 02:21:14 -0600 Subject: [PATCH] Implements "pause on hover" feature & exposes onMouseEnter and onMouseLeave callback props --- packages/primevue/src/toast/BaseToast.vue | 8 +++++ packages/primevue/src/toast/Toast.d.ts | 8 +++++ packages/primevue/src/toast/ToastMessage.vue | 35 +++++++++++++++++--- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/packages/primevue/src/toast/BaseToast.vue b/packages/primevue/src/toast/BaseToast.vue index 3cd4dbb4e..70f612ce2 100644 --- a/packages/primevue/src/toast/BaseToast.vue +++ b/packages/primevue/src/toast/BaseToast.vue @@ -49,6 +49,14 @@ export default { closeButtonProps: { type: null, default: null + }, + onMouseEnter: { + type: Function, + default: undefined + }, + onMouseLeave: { + type: Function, + default: undefined } }, style: ToastStyle, diff --git a/packages/primevue/src/toast/Toast.d.ts b/packages/primevue/src/toast/Toast.d.ts index 6e5dece06..b0dea3f64 100755 --- a/packages/primevue/src/toast/Toast.d.ts +++ b/packages/primevue/src/toast/Toast.d.ts @@ -250,6 +250,14 @@ export interface ToastProps { * @defaultValue false */ unstyled?: boolean; + /** + * Used to specify a callback function to be run when the @mouseenter event is fired on the message component. + */ + onMouseEnter?: Function | undefined; + /** + * Used to specify a callback function to be run when the @mouseleave event is fired on the message component. + */ + onMouseLeave?: Function | undefined; } /** diff --git a/packages/primevue/src/toast/ToastMessage.vue b/packages/primevue/src/toast/ToastMessage.vue index 8e1a3988c..1e200b761 100755 --- a/packages/primevue/src/toast/ToastMessage.vue +++ b/packages/primevue/src/toast/ToastMessage.vue @@ -1,5 +1,5 @@ <template> - <div :class="[cx('message'), message.styleClass]" role="alert" aria-live="assertive" aria-atomic="true" v-bind="ptm('message')"> + <div :class="[cx('message'), message.styleClass]" role="alert" aria-live="assertive" aria-atomic="true" v-bind="ptm('message')" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave"> <component v-if="templates.container" :is="templates.container" :message="message" :closeCallback="onCloseClick" /> <div v-else :class="[cx('messageContent'), message.contentStyleClass]" v-bind="ptm('messageContent')"> <template v-if="!templates.message"> @@ -34,6 +34,8 @@ export default { extends: BaseComponent, emits: ['close'], closeTimeout: null, + createdAt: null, + lifeRemaining: null, props: { message: { type: null, @@ -70,15 +72,20 @@ export default { }, mounted() { if (this.message.life) { - this.closeTimeout = setTimeout(() => { - this.close({ message: this.message, type: 'life-end' }); - }, this.message.life); + this.lifeRemaining = this.message.life; + this.startTimeout(); } }, beforeUnmount() { this.clearCloseTimeout(); }, methods: { + startTimeout() { + this.createdAt = new Date().valueOf(); + this.closeTimeout = setTimeout(() => { + this.close({ message: this.message, type: 'life-end' }); + }, this.lifeRemaining); + }, close(params) { this.$emit('close', params); }, @@ -91,6 +98,26 @@ export default { clearTimeout(this.closeTimeout); this.closeTimeout = null; } + }, + onMouseEnter(event) { + this.props.onMouseEnter && this.props.onMouseEnter(event); + if (event.defaultPrevented) { + return; + } + if (this.message.life) { + this.lifeRemaining = this.createdAt + this.lifeRemaining - Date().valueOf(); + this.createdAt = null; + this.clearCloseTimeout(); + } + }, + onMouseLeave(event) { + this.props.onMouseLeave && this.props.onMouseLeave(event); + if (event.defaultPrevented) { + return; + } + if (this.message.life) { + this.startTimeout(); + } } }, computed: {