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.

94 lines (91 loc) 3.45 kB
"use strict"; exports.__esModule = true; exports.default = void 0; var _react = require("react"); var _helpers = require("./helpers"); const timing = 1 / 60 * 1000; // eslint-disable-next-line no-bitwise const decay = v => -0.1 * (1 / timing ^ 4) + v; const useScroll = ref => { const [clickStartX, setClickStartX] = (0, _react.useState)(undefined); const [scrollStartX, setScrollStartX] = (0, _react.useState)(undefined); const [isDragging, setIsDragging] = (0, _react.useState)(false); const [direction, setDirection] = (0, _react.useState)(0); const [momentum, setMomentum] = (0, _react.useState)(0); const [lastScrollX, setLastScrollX] = (0, _react.useState)(0); const [speed, setSpeed] = (0, _react.useState)(0); const scrollWrapperCurrent = ref.current; const handleLastScrollX = (0, _react.useCallback)(x => setLastScrollX(x), []); const handleMomentum = (0, _helpers.throttle)(nextMomentum => { setMomentum(nextMomentum); if (scrollWrapperCurrent) { scrollWrapperCurrent.scrollLeft += nextMomentum * timing * direction; } }, timing); (0, _react.useEffect)(() => { if (direction !== 0) { if (momentum > 0.1 && !isDragging) { handleMomentum(decay(momentum)); } else if (isDragging) { setMomentum(speed); } else { setDirection(0); } } }, [momentum, isDragging, speed, direction, handleMomentum]); // We only need to clean up the effect in case we add event listeners // eslint-disable-next-line consistent-return (0, _react.useEffect)(() => { const currentRef = ref.current; if (currentRef) { const handleDragStart = e => { setClickStartX(e.screenX); setScrollStartX(currentRef.scrollLeft); setDirection(0); }; const handleDragMove = e => { e.preventDefault(); e.stopPropagation(); if (clickStartX === undefined || scrollStartX === undefined) { return; } const touchDelta = clickStartX - e.screenX; currentRef.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); } }; const handleDragEnd = () => { setClickStartX(undefined); setScrollStartX(undefined); setIsDragging(false); }; // on mobile browser is null, on desktop is undefined if (currentRef.ontouchstart === undefined) { currentRef.addEventListener("mousedown", handleDragStart); currentRef.addEventListener("mousemove", handleDragMove); currentRef.addEventListener("mouseup", handleDragEnd); currentRef.addEventListener("mouseleave", handleDragEnd); return () => { currentRef.removeEventListener("mousedown", handleDragStart); currentRef.removeEventListener("mousemove", handleDragMove); currentRef.removeEventListener("mouseup", handleDragEnd); currentRef.removeEventListener("mouseleave", handleDragEnd); }; } } }, [scrollWrapperCurrent, clickStartX, isDragging, scrollStartX, handleLastScrollX, lastScrollX, ref]); return { clickStartX, scrollStartX, isDragging, direction, momentum, lastScrollX, speed }; }; var _default = exports.default = useScroll;