@clayui/shared
Version:
ClayShared component
101 lines (100 loc) • 3.3 kB
JavaScript
import { useEffect, useRef } from "react";
function useInteractOutside({
isDisabled = false,
onInteract,
onInteractStart,
ref,
triggerRef
}) {
const stateRef = useRef({
ignoreEmulatedMouseEvents: false,
isPointerDown: false,
onInteract
});
const state = stateRef.current;
state.onInteract = onInteract;
useEffect(() => {
if (isDisabled) {
return;
}
const onPointerDown = (event) => {
if (isValidEvent(event, ref, triggerRef) && state.onInteract) {
if (onInteractStart) {
onInteractStart(event);
}
state.isPointerDown = true;
}
};
const onBlur = (event) => {
if (state.onInteract && event.view === void 0) {
state.onInteract(event);
}
};
if (typeof PointerEvent !== "undefined") {
const onPointerUp = (event) => {
if (state.isPointerDown && state.onInteract && isValidEvent(event, ref, triggerRef)) {
state.isPointerDown = false;
state.onInteract(event);
}
};
document.addEventListener("pointerdown", onPointerDown, true);
document.addEventListener("pointerup", onPointerUp, true);
window.addEventListener("blur", onBlur, true);
return () => {
document.removeEventListener(
"pointerdown",
onPointerDown,
true
);
document.removeEventListener("pointerup", onPointerUp, true);
window.removeEventListener("blur", onBlur, true);
};
} else {
const onMouseUp = (event) => {
if (state.ignoreEmulatedMouseEvents) {
state.ignoreEmulatedMouseEvents = false;
} else if (state.isPointerDown && state.onInteract && isValidEvent(event, ref, triggerRef)) {
state.isPointerDown = false;
state.onInteract(event);
}
};
const onTouchEnd = (event) => {
state.ignoreEmulatedMouseEvents = true;
if (state.onInteract && state.isPointerDown && isValidEvent(event, ref, triggerRef)) {
state.isPointerDown = false;
state.onInteract(event);
}
};
document.addEventListener("mousedown", onPointerDown, true);
document.addEventListener("mouseup", onMouseUp, true);
document.addEventListener("touchstart", onPointerDown, true);
document.addEventListener("touchend", onTouchEnd, true);
window.addEventListener("blur", onBlur, true);
return () => {
document.removeEventListener("mousedown", onPointerDown, true);
document.removeEventListener("mouseup", onMouseUp, true);
document.removeEventListener("touchstart", onPointerDown, true);
document.removeEventListener("touchend", onTouchEnd, true);
window.removeEventListener("blur", onBlur, true);
};
}
}, [ref, state, isDisabled]);
}
function isValidEvent(event, ref, trigger) {
if (event.button > 0) {
return false;
}
if (event.target) {
const ownerDocument = event.target.ownerDocument;
if (!ownerDocument || !ownerDocument.documentElement.contains(event.target)) {
return false;
}
}
if (trigger.current && trigger.current.contains(event.target)) {
return false;
}
return ref.current && !ref.current.contains(event.target);
}
export {
useInteractOutside
};