UNPKG

vue-use-hover-intent

Version:

Vue 3 composable hover detection that waits until the user's mouse slows down enough.

83 lines (80 loc) 2.04 kB
import { ref, watchEffect } from 'vue-demi'; function useHoverIntent(target, options) { const { sensitivity = 6, interval = 100, timeout = 100 } = options ?? {}; const isHovering = ref(false); let x = 0; let y = 0; let pX = 0; let pY = 0; let timer = 0; const setIsHovering = (value) => { isHovering.value = value; return value; }; const delay = () => { if (timer) { clearTimeout(timer); } return setIsHovering(false); }; const tracker = (e) => { x = e.clientX; y = e.clientY; }; const compare = (e) => { if (timer) { clearTimeout(timer); } if (Math.abs(pX - x) + Math.abs(pY - y) < sensitivity) { return setIsHovering(true); } else { pX = x; pY = y; timer = window.setTimeout(() => compare(), interval); } }; const dispatchOver = (e) => { if (timer) { clearTimeout(timer); } if (target.value) { target.value.removeEventListener("mousemove", tracker, false); } if (!isHovering.value) { pX = e.clientX; pY = e.clientY; if (target.value) { target.value.addEventListener("mousemove", tracker, false); } timer = window.setTimeout(() => compare(), interval); } }; const dispatchOut = () => { if (timer) { clearTimeout(timer); } if (target.value) { target.value.removeEventListener("mousemove", tracker, false); } if (isHovering.value) { timer = window.setTimeout(() => delay(), timeout); } }; watchEffect(() => { if (target.value) { target.value.addEventListener("mouseover", dispatchOver, false); target.value.addEventListener("mouseout", dispatchOut, false); } return () => { if (timer) { clearTimeout(timer); } if (target) { target.value.removeEventListener("mouseover", dispatchOver, false); target.value.removeEventListener("mouseout", dispatchOut, false); } }; }); return isHovering; } export { useHoverIntent };