UNPKG

@wix/design-system

Version:

@wix/design-system

109 lines (108 loc) 3.42 kB
"use strict"; exports.__esModule = true; exports.useDragLayerAutoScroll = exports.default = void 0; var _react = require("react"); var _reactDnd = require("react-dnd"); var SCROLL_ZONE_SIZE = 20; var SCROLL_SPEED = 10; var useDragLayerAutoScroll = containerRef => { var { isDragging, currentOffset } = (0, _reactDnd.useDragLayer)(monitor => ({ isDragging: monitor.isDragging(), currentOffset: monitor.getClientOffset() })); var animationFrame = (0, _react.useRef)(null); var getScrollContainer = (0, _react.useCallback)(() => { var startNode = containerRef && containerRef.current; if (!startNode) { return window; } // The virtualized container is itself the scroller, so check the ref node // before walking up. Non-virtualized renders an unscrolled wrapper here, // so the walk falls through to an ancestor scroller (or window) as before. var isScrollable = el => { var { overflowY } = window.getComputedStyle(el); return (overflowY === 'auto' || overflowY === 'scroll') && el.scrollHeight > el.clientHeight; }; if (isScrollable(startNode)) { return startNode; } var node = startNode.parentElement; while (node && node !== document.body) { if (isScrollable(node)) { return node; } node = node.parentElement; } return window; }, [containerRef]); var scroll = (0, _react.useCallback)(() => { if (!isDragging || !currentOffset) { animationFrame.current = requestAnimationFrame(scroll); return; } var container = getScrollContainer(); if (!container) { animationFrame.current = requestAnimationFrame(scroll); return; } var { y } = currentOffset; var scrollChange = 0; if (container === window) { var viewportHeight = window.innerHeight; if (y < SCROLL_ZONE_SIZE) { scrollChange = -SCROLL_SPEED; } else if (y > viewportHeight - SCROLL_ZONE_SIZE) { scrollChange = SCROLL_SPEED; } if (scrollChange !== 0) { window.scrollBy(0, scrollChange); } animationFrame.current = requestAnimationFrame(scroll); } else if (container instanceof HTMLElement) { var rect = container.getBoundingClientRect(); if (y < rect.top + SCROLL_ZONE_SIZE) { scrollChange = -SCROLL_SPEED; } else if (y > rect.bottom - SCROLL_ZONE_SIZE) { scrollChange = SCROLL_SPEED; } if (scrollChange !== 0) { container.scrollTop += scrollChange; } animationFrame.current = requestAnimationFrame(scroll); } }, [isDragging, currentOffset, getScrollContainer]); (0, _react.useEffect)(() => { if (isDragging) { animationFrame.current = requestAnimationFrame(scroll); } else { if (animationFrame.current) { cancelAnimationFrame(animationFrame.current); animationFrame.current = null; } } return () => { if (animationFrame.current) { cancelAnimationFrame(animationFrame.current); animationFrame.current = null; } }; }, [isDragging, scroll]); return null; }; exports.useDragLayerAutoScroll = useDragLayerAutoScroll; var AutoScroller = _ref => { var { containerRef } = _ref; useDragLayerAutoScroll(containerRef); return null; }; var _default = exports.default = AutoScroller; //# sourceMappingURL=AutoScroller.js.map