UNPKG

@uifabric/utilities

Version:

Fluent UI React utilities for building components.

122 lines 4.66 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var EventGroup_1 = require("./EventGroup"); var scroll_1 = require("./scroll"); var getRect_1 = require("./dom/getRect"); var SCROLL_ITERATION_DELAY = 16; var SCROLL_GUTTER = 100; var MAX_SCROLL_VELOCITY = 15; /** * AutoScroll simply hooks up mouse events given a parent element, and scrolls the container * up/down depending on how close the mouse is to the top/bottom of the container. * * Once you don't want autoscroll any more, just dispose the helper and it will unhook events. * * @public * {@docCategory AutoScroll} */ var AutoScroll = /** @class */ (function () { function AutoScroll(element) { this._events = new EventGroup_1.EventGroup(this); this._scrollableParent = scroll_1.findScrollableParent(element); this._incrementScroll = this._incrementScroll.bind(this); this._scrollRect = getRect_1.getRect(this._scrollableParent); // eslint-disable-next-line @typescript-eslint/no-explicit-any if (this._scrollableParent === window) { this._scrollableParent = document.body; } if (this._scrollableParent) { this._events.on(window, 'mousemove', this._onMouseMove, true); this._events.on(window, 'touchmove', this._onTouchMove, true); } } AutoScroll.prototype.dispose = function () { this._events.dispose(); this._stopScroll(); }; AutoScroll.prototype._onMouseMove = function (ev) { this._computeScrollVelocity(ev); }; AutoScroll.prototype._onTouchMove = function (ev) { if (ev.touches.length > 0) { this._computeScrollVelocity(ev); } }; AutoScroll.prototype._computeScrollVelocity = function (ev) { if (!this._scrollRect) { return; } var clientX; var clientY; if ('clientX' in ev) { clientX = ev.clientX; clientY = ev.clientY; } else { clientX = ev.touches[0].clientX; clientY = ev.touches[0].clientY; } var scrollRectTop = this._scrollRect.top; var scrollRectLeft = this._scrollRect.left; var scrollClientBottom = scrollRectTop + this._scrollRect.height - SCROLL_GUTTER; var scrollClientRight = scrollRectLeft + this._scrollRect.width - SCROLL_GUTTER; // variables to use for alternating scroll direction var scrollRect; var clientDirection; var scrollClient; // if either of these conditions are met we are scrolling vertically else horizontally if (clientY < scrollRectTop + SCROLL_GUTTER || clientY > scrollClientBottom) { clientDirection = clientY; scrollRect = scrollRectTop; scrollClient = scrollClientBottom; this._isVerticalScroll = true; } else { clientDirection = clientX; scrollRect = scrollRectLeft; scrollClient = scrollClientRight; this._isVerticalScroll = false; } // calculate scroll velocity and direction if (clientDirection < scrollRect + SCROLL_GUTTER) { this._scrollVelocity = Math.max(-MAX_SCROLL_VELOCITY, -MAX_SCROLL_VELOCITY * ((SCROLL_GUTTER - (clientDirection - scrollRect)) / SCROLL_GUTTER)); } else if (clientDirection > scrollClient) { this._scrollVelocity = Math.min(MAX_SCROLL_VELOCITY, MAX_SCROLL_VELOCITY * ((clientDirection - scrollClient) / SCROLL_GUTTER)); } else { this._scrollVelocity = 0; } if (this._scrollVelocity) { this._startScroll(); } else { this._stopScroll(); } }; AutoScroll.prototype._startScroll = function () { if (!this._timeoutId) { this._incrementScroll(); } }; AutoScroll.prototype._incrementScroll = function () { if (this._scrollableParent) { if (this._isVerticalScroll) { this._scrollableParent.scrollTop += Math.round(this._scrollVelocity); } else { this._scrollableParent.scrollLeft += Math.round(this._scrollVelocity); } } this._timeoutId = setTimeout(this._incrementScroll, SCROLL_ITERATION_DELAY); }; AutoScroll.prototype._stopScroll = function () { if (this._timeoutId) { clearTimeout(this._timeoutId); delete this._timeoutId; } }; return AutoScroll; }()); exports.AutoScroll = AutoScroll; //# sourceMappingURL=AutoScroll.js.map