fluid-dnd
Version:
An agnostic drag and drop library to sort all kind of lists. With current support for vue, react and svelte
53 lines (52 loc) • 2.46 kB
JavaScript
import { draggableIsCompleteOutside, getAxisValue, getBefore, getDistanceValue, getRect } from '../utils/GetStyles';
const scrollByDirection = (element, direction, scrollAmount) => {
if (scrollAmount == 0) {
return;
}
if (direction === 'vertical') {
element.scrollBy(0, scrollAmount);
}
else {
element.scrollBy(scrollAmount, 0);
}
};
export const useScroll = (draggedElement) => {
let lastScrollAmount = 0.5;
const minScrollAmountDiff = 0.03;
const updateScrollByPosition = (direction, parent, position, translate) => {
const [distanceValue] = getDistanceValue(direction, getRect(draggedElement));
const parentBoundingClientRect = getRect(parent);
const positionInsideParent = getBefore(direction, position) -
getBefore(direction, parentBoundingClientRect) +
getAxisValue(direction, translate);
const [parentDistance] = getDistanceValue(direction, parentBoundingClientRect);
const totalDistance = parentDistance - distanceValue;
const relativePosition = positionInsideParent / totalDistance;
const relativeDistanceValue = distanceValue / totalDistance;
const velocity = 0.25;
const infLimit = 0.2;
const upperLimit = 0.8;
let percent = 0;
const isOutside = draggableIsCompleteOutside(draggedElement, parent);
if (!isOutside && relativePosition < infLimit && relativePosition > -relativeDistanceValue) {
percent = scrollFuncionToStart(relativePosition < 0 ? 0 : relativePosition, infLimit);
}
else if (!isOutside &&
relativePosition > upperLimit &&
relativePosition < 1 + relativeDistanceValue) {
percent = scrollFuncionToEnd(relativePosition, upperLimit);
}
const scrollAmount = velocity * distanceValue * percent;
lastScrollAmount =
Math.sign(scrollAmount) *
Math.min(Math.abs(scrollAmount), Math.abs(lastScrollAmount) + minScrollAmountDiff);
scrollByDirection(parent, direction, lastScrollAmount);
};
const scrollFuncionToStart = (relativePosition, infLimit) => {
return Math.pow(relativePosition / infLimit, 1 / 3) - 1;
};
const scrollFuncionToEnd = (relativePosition, upperLimit) => {
return Math.pow((1 / (1 - upperLimit)) * (relativePosition - upperLimit), 3);
};
return [updateScrollByPosition];
};