UNPKG

@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
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;