@wix/design-system
Version:
@wix/design-system
109 lines (108 loc) • 3.42 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 {
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