@faceless-ui/slider
Version:
A React library for building every kind of slider
94 lines • 4.17 kB
JavaScript
import { useEffect, useState } from 'react';
export const useDraggable = (args) => {
const { buttons = [1, 4, 5], // See https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons
scrollYAxis, enable, ref, onDrag, onDragEnd } = args || {};
// Position of the mouse on the page on mousedown
const [startX, setStartX] = useState(0);
const [startY, setStartY] = useState(0);
// Amount the draggable element is already scrolled
const [startScrollLeft, setStartScrollLeft] = useState(0);
const [startScrollTop, setStartScrollTop] = useState(0);
useEffect(() => {
const handleDown = (e) => {
if ((ref === null || ref === void 0 ? void 0 : ref.current) && enable) {
// Only allow dragging inside of target element
if (!ref.current.contains(e.target)) {
return;
}
// Set initial positions of mouse element scroll
setStartX(e.pageX - ref.current.offsetLeft);
setStartY(e.pageY - ref.current.offsetTop);
setStartScrollLeft(ref.current.scrollLeft);
setStartScrollTop(ref.current.scrollTop);
if (typeof onDrag === 'function') {
onDrag();
}
}
};
const handleMove = (e) => {
if ((ref === null || ref === void 0 ? void 0 : ref.current) && enable) {
// Don't fire if other buttons are pressed
if (!buttons.includes(e.buttons) || !ref.current.contains(e.target)) {
return;
}
if (ref.current.children) {
// disable nested anchor links from navigating while dragging
const childrenAsArray = Array.from(ref.current.children);
childrenAsArray.forEach((child) => {
const childAsElement = child;
childAsElement.style.pointerEvents = 'none';
});
}
e.preventDefault();
// Position of mouse on the page
const mouseX = e.pageX - ref.current.offsetLeft;
const mouseY = e.pageY - ref.current.offsetTop;
// Distance of the mouse from the origin of the last mousedown event
const xDisplacement = mouseX - startX;
const yDisplacement = mouseY - startY;
// Finally, set the element's scroll
ref.current.scrollLeft = startScrollLeft - xDisplacement;
const newScrollTop = startScrollTop - yDisplacement;
if (scrollYAxis !== false) {
ref.current.scrollTop = newScrollTop;
}
}
};
const handleUp = () => {
var _a;
// reenable nested anchor links after dragging
if (((_a = ref === null || ref === void 0 ? void 0 : ref.current) === null || _a === void 0 ? void 0 : _a.children) && enable) {
const childrenAsArray = Array.from(ref.current.children);
childrenAsArray.forEach((child) => {
const childAsElement = child;
childAsElement.style.removeProperty('pointer-events');
});
if (typeof onDragEnd === 'function') {
onDragEnd();
}
}
};
// Add and clean up listeners
document.addEventListener('mousedown', handleDown);
document.addEventListener('mousemove', handleMove);
document.addEventListener('mouseup', handleUp);
return () => {
document.removeEventListener('mousedown', handleDown);
document.removeEventListener('mousemove', handleMove);
document.removeEventListener('mouseup', handleUp);
};
}, [
buttons,
startScrollLeft,
startScrollTop,
startX,
startY,
scrollYAxis,
enable,
ref,
onDragEnd,
onDrag
]);
return null;
};
//# sourceMappingURL=useDragScroll.js.map