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
JavaScript
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 };