@kiwicom/orbit-components
Version:
Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com’s products.
128 lines (106 loc) • 4.18 kB
JavaScript
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import { useState, useEffect, useCallback } from "react";
import { throttle } from "./helpers";
var timing = 1 / 60 * 1000; // eslint-disable-next-line no-bitwise
var decay = function decay(v) {
return -0.1 * (1 / timing ^ 4) + v;
};
var useScroll = function useScroll(ref) {
var _useState = useState(),
_useState2 = _slicedToArray(_useState, 2),
clickStartX = _useState2[0],
setClickStartX = _useState2[1];
var _useState3 = useState(),
_useState4 = _slicedToArray(_useState3, 2),
scrollStartX = _useState4[0],
setScrollStartX = _useState4[1];
var _useState5 = useState(false),
_useState6 = _slicedToArray(_useState5, 2),
isDragging = _useState6[0],
setIsDragging = _useState6[1];
var _useState7 = useState(0),
_useState8 = _slicedToArray(_useState7, 2),
direction = _useState8[0],
setDirection = _useState8[1];
var _useState9 = useState(0),
_useState10 = _slicedToArray(_useState9, 2),
momentum = _useState10[0],
setMomentum = _useState10[1];
var _useState11 = useState(0),
_useState12 = _slicedToArray(_useState11, 2),
lastScrollX = _useState12[0],
setLastScrollX = _useState12[1];
var _useState13 = useState(0),
_useState14 = _slicedToArray(_useState13, 2),
speed = _useState14[0],
setSpeed = _useState14[1];
var scrollWrapperCurrent = ref.current;
var handleLastScrollX = useCallback(function (x) {
return setLastScrollX(x);
}, []);
var handleMomentum = throttle(function (nextMomentum) {
setMomentum(nextMomentum);
if (scrollWrapperCurrent) {
scrollWrapperCurrent.scrollLeft += nextMomentum * timing * direction;
}
}, timing);
useEffect(function () {
if (direction !== 0) {
if (momentum > 0.1 && !isDragging) {
handleMomentum(decay(momentum));
} else if (isDragging) {
setMomentum(speed);
} else {
setDirection(0);
}
}
}, [momentum, isDragging, speed, direction, handleMomentum]);
useEffect(function () {
if (ref.current) {
var handleDragStart = function handleDragStart(e) {
var _ref$current;
setClickStartX(e.screenX);
setScrollStartX((_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.scrollLeft);
setDirection(0);
};
var handleDragMove = function handleDragMove(e) {
e.preventDefault();
e.stopPropagation();
if (clickStartX !== undefined && scrollStartX !== undefined && ref.current) {
var touchDelta = clickStartX - e.screenX; // eslint-disable-next-line no-param-reassign
ref.current.scrollLeft = scrollStartX + touchDelta;
if (Math.abs(touchDelta) > 1) {
setIsDragging(true);
setDirection(touchDelta / Math.abs(touchDelta));
setSpeed(Math.abs((lastScrollX - e.screenX) / timing));
handleLastScrollX(e.screenX);
}
}
};
var handleDragEnd = function handleDragEnd() {
if (isDragging && clickStartX !== undefined) {
setClickStartX(undefined);
setScrollStartX(undefined);
setIsDragging(false);
}
}; // $FlowFixMe: on mobile browser is null, on desktop is undefined
if (ref.current && ref.current.ontouchstart === undefined) {
// eslint-disable-next-line no-param-reassign
ref.current.onmousedown = handleDragStart; // eslint-disable-next-line no-param-reassign
ref.current.onmousemove = handleDragMove; // eslint-disable-next-line no-param-reassign
ref.current.onmouseup = handleDragEnd; // eslint-disable-next-line no-param-reassign
ref.current.onmouseleave = handleDragEnd;
}
}
}, [scrollWrapperCurrent, clickStartX, isDragging, scrollStartX, handleLastScrollX, lastScrollX]);
return {
clickStartX: clickStartX,
scrollStartX: scrollStartX,
isDragging: isDragging,
direction: direction,
momentum: momentum,
lastScrollX: lastScrollX,
speed: speed
};
};
export default useScroll;