@wix/design-system
Version:
@wix/design-system
103 lines (102 loc) • 3.53 kB
JavaScript
;
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 _useDragLayer = (0, _reactDnd.useDragLayer)(monitor => ({
isDragging: monitor.isDragging(),
currentOffset: monitor.getClientOffset()
})),
isDragging = _useDragLayer.isDragging,
currentOffset = _useDragLayer.currentOffset;
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 _window$getComputedSt = window.getComputedStyle(el),
overflowY = _window$getComputedSt.overflowY;
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.y;
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.containerRef;
useDragLayerAutoScroll(containerRef);
return null;
};
var _default = exports.default = AutoScroller;
//# sourceMappingURL=AutoScroller.js.map