react-scrollbars-custom
Version:
The best React custom scrollbars component
1,635 lines (1,323 loc) • 67.4 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var cnbuilder = require('cnbuilder');
var React = require('react');
var zoomLevel = require('zoom-level');
var reactDraggable = require('react-draggable');
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var React__namespace = /*#__PURE__*/_interopNamespace(React);
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
function _typeof(obj) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
}, _typeof(obj);
}
var doc = (typeof document === "undefined" ? "undefined" : _typeof(document)) === 'object' ? document : null;
var isBrowser = typeof window !== 'undefined' && typeof navigator !== 'undefined' && typeof document !== 'undefined';
var isUndef = function isUndef(v) {
return typeof v === 'undefined';
};
var isFun = function isFun(v) {
return typeof v === 'function';
};
var isNum = function isNum(v) {
return typeof v === 'number';
};
/**
* @description Will return renderer result if presented, div element otherwise.
* If renderer is presented it'll receive `elementRef` function which should be used as HTMLElement's ref.
*
* @param props {ElementPropsWithElementRefAndRenderer}
* @param elementRef {ElementRef}
*/
var renderDivWithRenderer = function renderDivWithRenderer(props, elementRef) {
if (isFun(props.renderer)) {
props.elementRef = elementRef;
var renderer = props.renderer;
delete props.renderer;
return renderer(props);
}
delete props.elementRef;
return React__namespace.createElement("div", __assign({}, props, {
ref: elementRef
}));
};
var getInnerSize = function getInnerSize(el, dimension, padding1, padding2) {
var styles = getComputedStyle(el);
if (styles.boxSizing === 'border-box') {
return Math.max(0, (Number.parseFloat(styles[dimension]) || 0) - (Number.parseFloat(styles[padding1]) || 0) - (Number.parseFloat(styles[padding2]) || 0));
}
return Number.parseFloat(styles[dimension]) || 0;
};
/**
* @description Return element's height without padding
*/
var getInnerHeight = function getInnerHeight(el) {
return getInnerSize(el, 'height', 'paddingTop', 'paddingBottom');
};
/**
* @description Return element's width without padding
*/
var getInnerWidth = function getInnerWidth(el) {
return getInnerSize(el, 'width', 'paddingLeft', 'paddingRight');
};
/**
* @description Return unique UUID v4
*/
var uuid = function uuid() {
// eslint-disable-next-line @typescript-eslint/no-shadow
var uuid = '';
for (var i = 0; i < 32; i++) {
switch (i) {
case 8:
case 20:
{
uuid += "-".concat(Math.trunc(Math.random() * 16).toString(16));
break;
}
case 12:
{
uuid += '-4';
break;
}
case 16:
{
uuid += "-".concat((Math.random() * 16 | 0 & 3 | 8).toString(16));
break;
}
default:
{
uuid += Math.trunc(Math.random() * 16).toString(16);
}
}
}
return uuid;
};
/**
* @description Calculate thumb size for given viewport and track parameters
*
* @param {number} contentSize - Scrollable content size
* @param {number} viewportSize - Viewport size
* @param {number} trackSize - Track size thumb can move
* @param {number} minimalSize - Minimal thumb's size
* @param {number} maximalSize - Maximal thumb's size
*/
var calcThumbSize = function calcThumbSize(contentSize, viewportSize, trackSize, minimalSize, maximalSize) {
if (viewportSize >= contentSize) {
return 0;
}
var thumbSize = viewportSize / contentSize * trackSize;
if (isNum(maximalSize)) {
thumbSize = Math.min(maximalSize, thumbSize);
}
if (isNum(minimalSize)) {
thumbSize = Math.max(minimalSize, thumbSize);
}
return thumbSize;
};
/**
* @description Calculate thumb offset for given viewport, track and thumb parameters
*
* @param {number} contentSize - Scrollable content size
* @param {number} viewportSize - Viewport size
* @param {number} trackSize - Track size thumb can move
* @param {number} thumbSize - Thumb size
* @param {number} scroll - Scroll value to represent
*/
var calcThumbOffset = function calcThumbOffset(contentSize, viewportSize, trackSize, thumbSize, scroll) {
if (!scroll || !thumbSize || viewportSize >= contentSize) {
return 0;
}
return (trackSize - thumbSize) * scroll / (contentSize - viewportSize);
};
/**
* @description Calculate scroll for given viewport, track and thumb parameters
*
* @param {number} contentSize - Scrollable content size
* @param {number} viewportSize - Viewport size
* @param {number} trackSize - Track size thumb can move
* @param {number} thumbSize - Thumb size
* @param {number} thumbOffset - Thumb's offset representing the scroll
*/
var calcScrollForThumbOffset = function calcScrollForThumbOffset(contentSize, viewportSize, trackSize, thumbSize, thumbOffset) {
if (!thumbOffset || !thumbSize || viewportSize >= contentSize) {
return 0;
}
return thumbOffset * (contentSize - viewportSize) / (trackSize - thumbSize);
};
/**
* @description Returns scrollbar width specific for current environment. Can return undefined if DOM is not ready yet.
*/
var getScrollbarWidth = function getScrollbarWidth(force) {
if (force === void 0) {
force = false;
}
if (!doc) {
getScrollbarWidth._cache = 0;
return getScrollbarWidth._cache;
}
if (!force && !isUndef(getScrollbarWidth._cache)) {
return getScrollbarWidth._cache;
}
var el = doc.createElement('div');
el.setAttribute('style', 'position:absolute;width:100px;height:100px;top:-999px;left:-999px;overflow:scroll;');
doc.body.append(el);
/* istanbul ignore next */
if (el.clientWidth === 0) {
// Do not even cache this value because there is no calculations. Issue https://github.com/xobotyi/react-scrollbars-custom/issues/123
el.remove();
return;
}
getScrollbarWidth._cache = 100 - el.clientWidth;
el.remove();
return getScrollbarWidth._cache;
};
/**
* @description Detect need of horizontal scroll reverse while RTL.
*/
var shouldReverseRtlScroll = function shouldReverseRtlScroll(force) {
if (force === void 0) {
force = false;
}
if (!force && !isUndef(shouldReverseRtlScroll._cache)) {
return shouldReverseRtlScroll._cache;
}
if (!doc) {
shouldReverseRtlScroll._cache = false;
return shouldReverseRtlScroll._cache;
}
var el = doc.createElement('div');
var child = doc.createElement('div');
el.append(child);
el.setAttribute('style', 'position:absolute;width:100px;height:100px;top:-999px;left:-999px;overflow:scroll;direction:rtl');
child.setAttribute('style', 'width:1000px;height:1000px');
doc.body.append(el);
el.scrollLeft = -50;
shouldReverseRtlScroll._cache = el.scrollLeft === -50;
el.remove();
return shouldReverseRtlScroll._cache;
};
var Emittr =
/** @class */
function () {
function Emittr(maxHandlers) {
if (maxHandlers === void 0) {
maxHandlers = 10;
}
this.setMaxHandlers(maxHandlers);
this._handlers = Object.create(null);
}
Emittr._callEventHandlers = function (emitter, handlers, args) {
if (!handlers.length) {
return;
}
if (handlers.length === 1) {
Reflect.apply(handlers[0], emitter, args);
return;
}
handlers = __spreadArray([], handlers, true);
var idx;
for (idx = 0; idx < handlers.length; idx++) {
Reflect.apply(handlers[idx], emitter, args);
}
};
Emittr.prototype.setMaxHandlers = function (count) {
if (!isNum(count) || count <= 0) {
throw new TypeError("Expected maxHandlers to be a positive number, got '".concat(count, "' of type ").concat(_typeof(count)));
}
this._maxHandlers = count;
return this;
};
Emittr.prototype.getMaxHandlers = function () {
return this._maxHandlers;
};
Emittr.prototype.emit = function (name) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
if (_typeof(this._handlers[name]) !== 'object' || !Array.isArray(this._handlers[name])) {
return false;
}
Emittr._callEventHandlers(this, this._handlers[name], args);
return true;
};
Emittr.prototype.on = function (name, handler) {
Emittr._addHandler(this, name, handler);
return this;
};
Emittr.prototype.prependOn = function (name, handler) {
Emittr._addHandler(this, name, handler, true);
return this;
};
Emittr.prototype.once = function (name, handler) {
if (!isFun(handler)) {
throw new TypeError("Expected event handler to be a function, got ".concat(_typeof(handler)));
}
Emittr._addHandler(this, name, this._wrapOnceHandler(name, handler));
return this;
};
Emittr.prototype.prependOnce = function (name, handler) {
if (!isFun(handler)) {
throw new TypeError("Expected event handler to be a function, got ".concat(_typeof(handler)));
}
Emittr._addHandler(this, name, this._wrapOnceHandler(name, handler), true);
return this;
};
Emittr.prototype.off = function (name, handler) {
Emittr._removeHandler(this, name, handler);
return this;
};
Emittr.prototype.removeAllHandlers = function () {
var handlers = this._handlers;
this._handlers = Object.create(null);
var removeHandlers = handlers.removeHandler;
delete handlers.removeHandler;
var idx;
var eventName; // eslint-disable-next-line guard-for-in,no-restricted-syntax
for (eventName in handlers) {
for (idx = handlers[eventName].length - 1; idx >= 0; idx--) {
Emittr._callEventHandlers(this, removeHandlers, [eventName, handlers[eventName][idx].handler || handlers[eventName][idx]]);
}
}
return this;
};
Emittr.prototype._wrapOnceHandler = function (name, handler) {
var onceState = {
fired: false,
handler: handler,
wrappedHandler: undefined,
emitter: this,
event: name
};
var wrappedHandler = Emittr._onceWrapper.bind(onceState);
onceState.wrappedHandler = wrappedHandler;
wrappedHandler.handler = handler;
wrappedHandler.event = name;
return wrappedHandler;
};
Emittr._addHandler = function (emitter, name, handler, prepend) {
if (prepend === void 0) {
prepend = false;
}
if (!isFun(handler)) {
throw new TypeError("Expected event handler to be a function, got ".concat(_typeof(handler)));
}
emitter._handlers[name] = emitter._handlers[name] || [];
emitter.emit('addHandler', name, handler);
if (prepend) {
emitter._handlers[name].unshift(handler);
} else {
emitter._handlers[name].push(handler);
}
return emitter;
};
Emittr._onceWrapper = function _onceWrapper() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
if (!this.fired) {
this.fired = true;
this.emitter.off(this.event, this.wrappedHandler);
Reflect.apply(this.handler, this.emitter, args);
}
};
Emittr._removeHandler = function (emitter, name, handler) {
if (!isFun(handler)) {
throw new TypeError("Expected event handler to be a function, got ".concat(_typeof(handler)));
}
if (isUndef(emitter._handlers[name]) || !emitter._handlers[name].length) {
return emitter;
}
var idx = -1;
if (emitter._handlers[name].length === 1) {
if (emitter._handlers[name][0] === handler || emitter._handlers[name][0].handler === handler) {
idx = 0;
handler = emitter._handlers[name][0].handler || emitter._handlers[name][0];
}
} else {
for (idx = emitter._handlers[name].length - 1; idx >= 0; idx--) {
if (emitter._handlers[name][idx] === handler || emitter._handlers[name][idx].handler === handler) {
handler = emitter._handlers[name][idx].handler || emitter._handlers[name][idx];
break;
}
}
}
if (idx === -1) {
return emitter;
}
if (idx === 0) {
emitter._handlers[name].shift();
} else {
emitter._handlers[name].splice(idx, 1);
}
emitter.emit('removeHandler', name, handler);
return emitter;
};
return Emittr;
}();
var RAFLoop =
/** @class */
function () {
function RAFLoop() {
var _this = this;
/**
* @description List of targets to update
*/
this.targets = [];
/**
* @description ID of requested animation frame. Valuable only if loop is active and has items to iterate.
*/
this.animationFrameID = 0;
/**
* @description Loop's state.
*/
this._isActive = false;
/**
* @description Start the loop if it wasn't yet.
*/
this.start = function () {
if (!_this._isActive && _this.targets.length) {
_this._isActive = true;
if (_this.animationFrameID) cancelAnimationFrame(_this.animationFrameID);
_this.animationFrameID = requestAnimationFrame(_this.rafCallback);
}
return _this;
};
/**
* @description Stop the loop if is was active.
*/
this.stop = function () {
if (_this._isActive) {
_this._isActive = false;
if (_this.animationFrameID) cancelAnimationFrame(_this.animationFrameID);
_this.animationFrameID = 0;
}
return _this;
};
/**
* @description Add target to the iteration list if it's not there.
*/
this.addTarget = function (target, silent) {
if (silent === void 0) {
silent = false;
}
if (!_this.targets.includes(target)) {
_this.targets.push(target);
if (_this.targets.length === 1 && !silent) _this.start();
}
return _this;
};
/**
* @description Remove target from iteration list if it was there.
*/
this.removeTarget = function (target) {
var idx = _this.targets.indexOf(target);
if (idx !== -1) {
_this.targets.splice(idx, 1);
if (_this.targets.length === 0) _this.stop();
}
return _this;
};
/**
* @description Callback that called each animation frame.
*/
this.rafCallback = function () {
if (!_this._isActive) {
return 0;
}
for (var i = 0; i < _this.targets.length; i++) {
if (!_this.targets[i]._unmounted) _this.targets[i].update();
}
_this.animationFrameID = requestAnimationFrame(_this.rafCallback);
return _this.animationFrameID;
};
}
Object.defineProperty(RAFLoop.prototype, "isActive", {
/**
* @description Loop's state.
*/
get: function get() {
return this._isActive;
},
enumerable: false,
configurable: true
});
return RAFLoop;
}();
var Loop = new RAFLoop();
var AXIS_DIRECTION;
(function (AXIS_DIRECTION) {
AXIS_DIRECTION["X"] = "x";
AXIS_DIRECTION["Y"] = "y";
})(AXIS_DIRECTION || (AXIS_DIRECTION = {}));
var TRACK_CLICK_BEHAVIOR;
(function (TRACK_CLICK_BEHAVIOR) {
TRACK_CLICK_BEHAVIOR["JUMP"] = "jump";
TRACK_CLICK_BEHAVIOR["STEP"] = "step";
})(TRACK_CLICK_BEHAVIOR || (TRACK_CLICK_BEHAVIOR = {}));
var ScrollbarThumb =
/** @class */
function (_super) {
__extends(ScrollbarThumb, _super);
function ScrollbarThumb() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.element = null;
_this.initialOffsetX = 0;
_this.initialOffsetY = 0;
_this.elementRefHack = React__namespace.createRef();
_this.lastDragData = {
x: 0,
y: 0,
deltaX: 0,
deltaY: 0,
lastX: 0,
lastY: 0
};
_this.handleOnDragStart = function (ev, data) {
if (!_this.element) {
_this.handleOnDragStop(ev, data);
return;
}
if (isBrowser) {
_this.prevUserSelect = document.body.style.userSelect;
document.body.style.userSelect = 'none';
_this.prevOnSelectStart = document.onselectstart;
document.addEventListener('selectstart', ScrollbarThumb.selectStartReplacer);
}
if (_this.props.onDragStart) {
_this.props.onDragStart(_this.lastDragData = {
x: data.x - _this.initialOffsetX,
y: data.y - _this.initialOffsetY,
lastX: data.lastX - _this.initialOffsetX,
lastY: data.lastY - _this.initialOffsetY,
deltaX: data.deltaX,
deltaY: data.deltaY
});
}
_this.element.classList.add('dragging');
};
_this.handleOnDrag = function (ev, data) {
if (!_this.element) {
_this.handleOnDragStop(ev, data);
return;
}
if (_this.props.onDrag) {
_this.props.onDrag(_this.lastDragData = {
x: data.x - _this.initialOffsetX,
y: data.y - _this.initialOffsetY,
lastX: data.lastX - _this.initialOffsetX,
lastY: data.lastY - _this.initialOffsetY,
deltaX: data.deltaX,
deltaY: data.deltaY
});
}
};
_this.handleOnDragStop = function (ev, data) {
var resultData = data ? {
x: data.x - _this.initialOffsetX,
y: data.y - _this.initialOffsetY,
lastX: data.lastX - _this.initialOffsetX,
lastY: data.lastY - _this.initialOffsetY,
deltaX: data.deltaX,
deltaY: data.deltaY
} : _this.lastDragData;
if (_this.props.onDragEnd) _this.props.onDragEnd(resultData);
if (_this.element) _this.element.classList.remove('dragging');
if (isBrowser) {
document.body.style.userSelect = _this.prevUserSelect;
if (_this.prevOnSelectStart) {
document.addEventListener('selectstart', _this.prevOnSelectStart);
}
_this.prevOnSelectStart = null;
}
_this.initialOffsetX = 0;
_this.initialOffsetY = 0;
_this.lastDragData = {
x: 0,
y: 0,
deltaX: 0,
deltaY: 0,
lastX: 0,
lastY: 0
};
};
_this.handleOnMouseDown = function (ev) {
if (!_this.element) {
return;
}
ev.preventDefault();
ev.stopPropagation();
if (!isUndef(ev.offsetX)) {
/* istanbul ignore next */
_this.initialOffsetX = ev.offsetX;
/* istanbul ignore next */
_this.initialOffsetY = ev.offsetY;
} else {
var rect = _this.element.getBoundingClientRect();
_this.initialOffsetX = (ev.clientX || ev.touches[0].clientX) - rect.left;
_this.initialOffsetY = (ev.clientY || ev.touches[0].clientY) - rect.top;
}
};
_this.elementRef = function (ref) {
if (isFun(_this.props.elementRef)) _this.props.elementRef(ref);
_this.element = ref; // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
_this.elementRefHack.current = ref;
};
return _this;
}
ScrollbarThumb.prototype.componentDidMount = function () {
if (!this.element) {
this.setState(function () {
throw new Error("<ScrollbarThumb> Element was not created. Possibly you haven't provided HTMLDivElement to renderer's `elementRef` function.");
});
}
};
ScrollbarThumb.prototype.componentWillUnmount = function () {
this.handleOnDragStop();
this.elementRef(null);
};
ScrollbarThumb.prototype.render = function () {
var _a = this.props;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_a.elementRef;
var axis = _a.axis;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_a.onDrag;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_a.onDragEnd;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_a.onDragStart;
var props = __rest(_a, ["elementRef", "axis", "onDrag", "onDragEnd", "onDragStart"]);
props.className = cnbuilder.cnb('ScrollbarsCustom-Thumb', axis === AXIS_DIRECTION.X ? 'ScrollbarsCustom-ThumbX' : 'ScrollbarsCustom-ThumbY', props.className);
if (props.renderer) {
props.axis = axis;
}
return React__namespace.createElement(reactDraggable.DraggableCore, {
allowAnyClick: false,
enableUserSelectHack: false,
onMouseDown: this.handleOnMouseDown,
onDrag: this.handleOnDrag,
onStart: this.handleOnDragStart,
onStop: this.handleOnDragStop,
nodeRef: this.elementRefHack
}, renderDivWithRenderer(props, this.elementRef));
};
ScrollbarThumb.selectStartReplacer = function () {
return false;
};
return ScrollbarThumb;
}(React__namespace.Component);
var ScrollbarTrack =
/** @class */
function (_super) {
__extends(ScrollbarTrack, _super);
function ScrollbarTrack() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.element = null;
_this.elementRef = function (ref) {
if (isFun(_this.props.elementRef)) _this.props.elementRef(ref);
_this.element = ref;
};
_this.handleClick = function (ev) {
if (!ev || !_this.element || ev.button !== 0) {
return;
}
if (isFun(_this.props.onClick) && ev.target === _this.element) {
if (!isUndef(ev.offsetX)) {
_this.props.onClick(ev, {
axis: _this.props.axis,
offset: _this.props.axis === AXIS_DIRECTION.X ? ev.offsetX : ev.offsetY
});
} else {
// support for old browsers
/* istanbul ignore next */
var rect = _this.element.getBoundingClientRect();
/* istanbul ignore next */
_this.props.onClick(ev, {
axis: _this.props.axis,
offset: _this.props.axis === AXIS_DIRECTION.X ? (ev.clientX || ev.touches[0].clientX) - rect.left : (ev.clientY || ev.touches[0].clientY) - rect.top
});
}
}
return true;
};
return _this;
}
ScrollbarTrack.prototype.componentDidMount = function () {
if (!this.element) {
this.setState(function () {
throw new Error("Element was not created. Possibly you haven't provided HTMLDivElement to renderer's `elementRef` function.");
});
return;
}
this.element.addEventListener('click', this.handleClick);
};
ScrollbarTrack.prototype.componentWillUnmount = function () {
if (this.element) {
this.element.removeEventListener('click', this.handleClick);
this.element = null;
this.elementRef(null);
}
};
ScrollbarTrack.prototype.render = function () {
var _a = this.props;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_a.elementRef;
var axis = _a.axis;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
_a.onClick;
var props = __rest(_a, ["elementRef", "axis", "onClick"]);
props.className = cnbuilder.cnb('ScrollbarsCustom-Track', axis === AXIS_DIRECTION.X ? 'ScrollbarsCustom-TrackX' : 'ScrollbarsCustom-TrackY', props.className);
if (props.renderer) {
props.axis = axis;
}
return renderDivWithRenderer(props, this.elementRef);
};
return ScrollbarTrack;
}(React__namespace.Component);
var style = {
holder: {
position: 'relative',
width: '100%',
height: '100%'
},
wrapper: {
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0
},
content: {
boxSizing: 'border-box'
},
track: {
common: {
position: 'absolute',
overflow: 'hidden',
borderRadius: 4,
background: 'rgba(0,0,0,.1)',
userSelect: 'none'
},
x: {
height: 10,
width: 'calc(100% - 20px)',
bottom: 0,
left: 10
},
y: {
width: 10,
height: 'calc(100% - 20px)',
top: 10
}
},
thumb: {
common: {
cursor: 'pointer',
borderRadius: 4,
background: 'rgba(0,0,0,.4)'
},
x: {
height: '100%',
width: 0
},
y: {
width: '100%',
height: 0
}
}
};
var pageZoomLevel = isBrowser ? zoomLevel.zoomLevel() : 1;
if (isBrowser) {
window.addEventListener('resize', function () {
pageZoomLevel = zoomLevel.zoomLevel();
}, {
passive: true
});
}
var ScrollbarContext = React__namespace.createContext({
parentScrollbar: null
});
var Scrollbar =
/** @class */
function (_super) {
__extends(Scrollbar, _super);
function Scrollbar(props) {
var _this = _super.call(this, props) || this;
/**
* @description Get current scroll-related values.<br/>
* If <i>force</i> if truthy - will recalculate them instead of returning cached values.
*
* @return ScrollState
*/
_this.getScrollState = function (force) {
if (force === void 0) {
force = false;
}
if (_this.scrollValues && !force) {
return __assign({}, _this.scrollValues);
}
var scrollState = {
clientHeight: 0,
clientWidth: 0,
contentScrollHeight: 0,
contentScrollWidth: 0,
scrollHeight: 0,
scrollWidth: 0,
scrollTop: 0,
scrollLeft: 0,
scrollYBlocked: false,
scrollXBlocked: false,
scrollYPossible: false,
scrollXPossible: false,
trackYVisible: false,
trackXVisible: false,
zoomLevel: pageZoomLevel * 1,
isRTL: undefined
};
var props = _this.props;
scrollState.isRTL = _this.state.isRTL;
scrollState.scrollYBlocked = props.noScroll || props.noScrollY;
scrollState.scrollXBlocked = props.noScroll || props.noScrollX;
if (_this.scrollerElement) {
scrollState.clientHeight = _this.scrollerElement.clientHeight;
scrollState.clientWidth = _this.scrollerElement.clientWidth;
scrollState.scrollHeight = _this.scrollerElement.scrollHeight;
scrollState.scrollWidth = _this.scrollerElement.scrollWidth;
scrollState.scrollTop = _this.scrollerElement.scrollTop;
scrollState.scrollLeft = _this.scrollerElement.scrollLeft;
scrollState.scrollYPossible = !scrollState.scrollYBlocked && scrollState.scrollHeight > scrollState.clientHeight;
scrollState.scrollXPossible = !scrollState.scrollXBlocked && scrollState.scrollWidth > scrollState.clientWidth;
scrollState.trackYVisible = scrollState.scrollYPossible || props.permanentTracks || props.permanentTrackY;
scrollState.trackXVisible = scrollState.scrollXPossible || props.permanentTracks || props.permanentTrackX;
}
if (_this.contentElement) {
scrollState.contentScrollHeight = _this.contentElement.scrollHeight;
scrollState.contentScrollWidth = _this.contentElement.scrollWidth;
}
return scrollState;
};
/**
* @description Scroll to top border
*/
_this.scrollToTop = function () {
if (_this.scrollerElement) {
_this.scrollerElement.scrollTop = 0;
}
return _this;
};
/**
* @description Scroll to left border
*/
_this.scrollToLeft = function () {
if (_this.scrollerElement) {
_this.scrollerElement.scrollLeft = 0;
}
return _this;
};
/**
* @description Scroll to bottom border
*/
_this.scrollToBottom = function () {
if (_this.scrollerElement) {
_this.scrollerElement.scrollTop = _this.scrollerElement.scrollHeight - _this.scrollerElement.clientHeight;
}
return _this;
};
/**
* @description Scroll to right border
*/
_this.scrollToRight = function () {
if (_this.scrollerElement) {
_this.scrollerElement.scrollLeft = _this.scrollerElement.scrollWidth - _this.scrollerElement.clientWidth;
}
return _this;
};
/**
* @description Set the scrolls at given coordinates.<br/>
* If coordinate is undefined - current scroll value will persist.
*/
_this.scrollTo = function (x, y) {
if (_this.scrollerElement) {
if (isNum(x)) _this.scrollerElement.scrollLeft = x;
if (isNum(y)) _this.scrollerElement.scrollTop = y;
}
return _this;
};
/**
* @description Center the viewport at given coordinates.<br/>
* If coordinate is undefined - current scroll value will persist.
*/
_this.centerAt = function (x, y) {
if (_this.scrollerElement) {
if (isNum(x)) _this.scrollerElement.scrollLeft = x - _this.scrollerElement.clientWidth / 2;
if (isNum(y)) _this.scrollerElement.scrollTop = y - _this.scrollerElement.clientHeight / 2;
}
return _this;
};
_this.update = function (force) {
if (force === void 0) {
force = false;
}
if (!_this.scrollerElement) {
return;
} // autodetect direction if not defined
if (isUndef(_this.state.isRTL)) {
_this.setState({
isRTL: getComputedStyle(_this.scrollerElement).direction === 'rtl'
});
return _this.getScrollState();
}
var scrollState = _this.getScrollState(true);
var prevScrollState = __assign({}, _this.scrollValues);
var props = _this.props;
var bitmask = 0;
if (!force) {
if (prevScrollState.clientHeight !== scrollState.clientHeight) bitmask |= Math.trunc(1);
if (prevScrollState.clientWidth !== scrollState.clientWidth) bitmask |= 1 << 1;
if (prevScrollState.scrollHeight !== scrollState.scrollHeight) bitmask |= 1 << 2;
if (prevScrollState.scrollWidth !== scrollState.scrollWidth) bitmask |= 1 << 3;
if (prevScrollState.scrollTop !== scrollState.scrollTop) bitmask |= 1 << 4;
if (prevScrollState.scrollLeft !== scrollState.scrollLeft) bitmask |= 1 << 5;
if (prevScrollState.scrollYBlocked !== scrollState.scrollYBlocked) bitmask |= 1 << 6;
if (prevScrollState.scrollXBlocked !== scrollState.scrollXBlocked) bitmask |= 1 << 7;
if (prevScrollState.scrollYPossible !== scrollState.scrollYPossible) bitmask |= 1 << 8;
if (prevScrollState.scrollXPossible !== scrollState.scrollXPossible) bitmask |= 1 << 9;
if (prevScrollState.trackYVisible !== scrollState.trackYVisible) bitmask |= 1 << 10;
if (prevScrollState.trackXVisible !== scrollState.trackXVisible) bitmask |= 1 << 11;
if (prevScrollState.isRTL !== scrollState.isRTL) bitmask |= 1 << 12;
if (prevScrollState.contentScrollHeight !== scrollState.contentScrollHeight) bitmask |= 1 << 13;
if (prevScrollState.contentScrollWidth !== scrollState.contentScrollWidth) bitmask |= 1 << 14;
if (prevScrollState.zoomLevel !== scrollState.zoomLevel) bitmask |= 1 << 15; // if not forced and nothing has changed - skip this update
if (bitmask === 0) {
return prevScrollState;
}
} else {
bitmask = 32767;
}
if (!props.native && _this.holderElement) {
if (bitmask & 1 << 13 && (props.translateContentSizesToHolder || props.translateContentSizeYToHolder)) {
_this.holderElement.style.height = "".concat(scrollState.contentScrollHeight, "px");
}
if (bitmask & 1 << 14 && (props.translateContentSizesToHolder || props.translateContentSizeXToHolder)) {
_this.holderElement.style.width = "".concat(scrollState.contentScrollWidth, "px");
}
if (props.translateContentSizesToHolder || props.translateContentSizeYToHolder || props.translateContentSizeXToHolder) {
if (!scrollState.clientHeight && scrollState.contentScrollHeight || !scrollState.clientWidth && scrollState.contentScrollWidth) {
return;
}
}
} // if scrollbars visibility has changed
if (bitmask & 1 << 10 || bitmask & 1 << 11) {
prevScrollState.scrollYBlocked = scrollState.scrollYBlocked;
prevScrollState.scrollXBlocked = scrollState.scrollXBlocked;
prevScrollState.scrollYPossible = scrollState.scrollYPossible;
prevScrollState.scrollXPossible = scrollState.scrollXPossible;
if (_this.trackYElement && bitmask & 1 << 10) {
_this.trackYElement.style.display = scrollState.trackYVisible ? '' : 'none';
}
if (_this.trackXElement && bitmask & 1 << 11) {
_this.trackXElement.style.display = scrollState.trackXVisible ? '' : 'none';
}
_this.scrollValues = prevScrollState;
_this.setState({
trackYVisible: _this.scrollValues.trackYVisible = scrollState.trackYVisible,
trackXVisible: _this.scrollValues.trackXVisible = scrollState.trackXVisible
});
return;
}
(props.native ? _this.updaterNative : _this.updaterCustom)(bitmask, scrollState);
_this.scrollValues = scrollState;
if (!props.native && bitmask & 1 << 15) {
getScrollbarWidth(true);
_this.forceUpdate();
}
_this.eventEmitter.emit('update', __assign({}, scrollState), prevScrollState);
if (bitmask & 1 << 4 || bitmask & 1 << 5) _this.eventEmitter.emit('scroll', __assign({}, scrollState), prevScrollState);
return _this.scrollValues;
}; // eslint-disable-next-line class-methods-use-this
_this.updaterNative = function () {
// just for future
return true;
};
_this.updaterCustom = function (bitmask, scrollValues) {
var props = _this.props;
if (_this.trackYElement) {
if (_this.thumbYElement && (bitmask & Math.trunc(1) || bitmask & 1 << 2 || bitmask & 1 << 4 || bitmask & 1 << 6 || bitmask & 1 << 8)) {
if (scrollValues.scrollYPossible) {
var trackInnerSize = getInnerHeight(_this.trackYElement);
var thumbSize = calcThumbSize(scrollValues.scrollHeight, scrollValues.clientHeight, trackInnerSize, props.minimalThumbYSize || props.minimalThumbSize, props.maximalThumbYSize || props.maximalThumbSize);
var thumbOffset = calcThumbOffset(scrollValues.scrollHeight, scrollValues.clientHeight, trackInnerSize, thumbSize, scrollValues.scrollTop);
_this.thumbYElement.style.transform = "translateY(".concat(thumbOffset, "px)");
_this.thumbYElement.style.height = "".concat(thumbSize, "px");
_this.thumbYElement.style.display = '';
} else {
_this.thumbYElement.style.transform = '';
_this.thumbYElement.style.height = '0px';
_this.thumbYElement.style.display = 'none';
}
}
}
if (_this.trackXElement) {
if (_this.thumbXElement && (bitmask & 1 << 1 || bitmask & 1 << 3 || bitmask & 1 << 5 || bitmask & 1 << 7 || bitmask & 1 << 9 || bitmask & 1 << 12)) {
if (scrollValues.scrollXPossible) {
var trackInnerSize = getInnerWidth(_this.trackXElement);
var thumbSize = calcThumbSize(scrollValues.scrollWidth, scrollValues.clientWidth, trackInnerSize, props.minimalThumbXSize || props.minimalThumbSize, props.maximalThumbXSize || props.maximalThumbSize);
var thumbOffset = calcThumbOffset(scrollValues.scrollWidth, scrollValues.clientWidth, trackInnerSize, thumbSize, scrollValues.scrollLeft);
if (_this.state.isRTL && shouldReverseRtlScroll()) {
thumbOffset += trackInnerSize - thumbSize;
}
_this.thumbXElement.style.transform = "translateX(".concat(thumbOffset, "px)");
_this.thumbXElement.style.width = "".concat(thumbSize, "px");
_this.thumbXElement.style.display = '';
} else {
_this.thumbXElement.style.transform = '';
_this.thumbXElement.style.width = '0px';
_this.thumbXElement.style.display = 'none';
}
}
}
return true;
};
_this.elementRefHolder = function (ref) {
_this.holderElement = ref;
if (isFun(_this.props.elementRef)) {
_this.props.elementRef(ref);
}
};
_this.elementRefWrapper = function (ref) {
_this.wrapperElement = ref;
if (isFun(_this.props.wrapperProps.elementRef)) {
_this.props.wrapperProps.elementRef(ref);
}
};
_this.elementRefScroller = function (ref) {
_this.scrollerElement = ref;
if (isFun(_this.props.scrollerProps.elementRef)) {
_this.props.scrollerProps.elementRef(ref);
}
};
_this.elementRefContent = function (ref) {
_this.contentElement = ref;
if (isFun(_this.props.contentProps.elementRef)) {
_this.props.contentProps.elementRef(ref);
}
};
_this.elementRefTrackX = function (ref) {
_this.trackXElement = ref;
if (isFun(_this.props.trackXProps.elementRef)) {
_this.props.trackXProps.elementRef(ref);
}
};
_this.elementRefTrackY = function (ref) {
_this.trackYElement = ref;
if (isFun(_this.props.trackYProps.elementRef)) {
_this.props.trackYProps.elementRef(ref);
}
};
_this.elementRefThumbX = function (ref) {
_this.thumbXElement = ref;
if (isFun(_this.props.thumbXProps.elementRef)) {
_this.props.thumbXProps.elementRef(ref);
}
};
_this.elementRefThumbY = function (ref) {
_this.thumbYElement = ref;
if (isFun(_this.props.thumbYProps.elementRef)) {
_this.props.thumbYProps.elementRef(ref);
}
};
_this.handleTrackXClick = function (ev, values) {
if (_this.props.trackXProps.onClick) {
_this.props.trackXProps.onClick(ev, values);
}
if (!_this.scrollerElement || !_this.trackXElement || !_this.thumbXElement || !_this.scrollValues || !_this.scrollValues.scrollXPossible) {
return;
}
_this._scrollDetection();
var thumbSize = _this.thumbXElement.clientWidth;
var trackInnerSize = getInnerWidth(_this.trackXElement);
var thumbOffset = (_this.scrollValues.isRTL && shouldReverseRtlScroll() ? values.offset + thumbSize / 2 - trackInnerSize : values.offset - thumbSize / 2) - (Number.parseFloat(getComputedStyle(_this.trackXElement).paddingLeft) || 0);
var target = calcScrollForThumbOffset(_this.scrollValues.scrollWidth, _this.scrollValues.clientWidth, trackInnerSize, thumbSize, thumbOffset);
if (_this.props.trackClickBehavior === TRACK_CLICK_BEHAVIOR.STEP) {
target = (_this.scrollValues.isRTL ? _this.scrollValues.scrollLeft > target : _this.scrollValues.scrollLeft < target) ? _this.scrollValues.scrollLeft + _this.scrollValues.clientWidth : _this.scrollValues.scrollLeft - _this.scrollValues.clientWidth;
}
_this.scrollerElement.scrollLeft = target;
};
_this.handleTrackYClick = function (ev, values) {
if (_this.props.trackYProps.onClick) _this.props.trackYProps.onClick(ev, values);
if (!_this.scrollerElement || !_this.trackYElement || !_this.thumbYElement || !_this.scrollValues || !_this.scrollValues.scrollYPossible) {
return;
}
_this._scrollDetection();
var thumbSize = _this.thumbYElement.clientHeight;
var target = calcScrollForThumbOffset(_this.scrollValues.scrollHeight, _this.scrollValues.clientHeight, getInnerHeight(_this.trackYElement), thumbSize, values.offset - thumbSize / 2) - (Number.parseFloat(getComputedStyle(_this.trackYElement).paddingTop) || 0);
if (_this.props.trackClickBehavior === TRACK_CLICK_BEHAVIOR.JUMP) {
_this.scrollerElement.scrollTop = target;
} else {
_this.scrollerElement.scrollTop = _this.scrollValues.scrollTop < target ? _this.scrollValues.scrollTop + _this.scrollValues.clientHeight : _this.scrollValues.scrollTop - _this.scrollValues.clientHeight;
}
};
_this.handleTrackYMouseWheel = function (ev) {
var props = _this.props;
if (props.trackYProps && props.trackYProps.onWheel) {
props.trackYProps.onWheel(ev);
}
if (props.disableTracksMousewheelScrolling || props.disableTrackYMousewheelScrolling) {
return;
}
_this._scrollDetection();
if (!_this.scrollerElement || _this.scrollValues.scrollYBlocked) {
return;
}
_this.scrollTop += ev.deltaY;
};
_this.handleTrackXMouseWheel = function (ev) {
var props = _this.props;
if (props.trackXProps && props.trackXProps.onWheel) {
props.trackXProps.onWheel(ev);
}
if (props.disableTracksMousewheelScrolling || props.disableTrackXMousewheelScrolling) {
return;
}
_this._scrollDetection();
if (!_this.scrollerElement || _this.scrollValues.scrollXBlocked) {
return;
}
_this.scrollLeft += ev.deltaX;
};
_this.handleThumbXDrag = function (data) {
var _a;
if (!_this.trackXElement || !_this.thumbXElement || !_this.scrollerElement || !_this.scrollValues || !_this.scrollValues.scrollXPossible) {
return;
}
_this._scrollDetection();
var trackRect = _this.trackXElement.getBoundingClientRect();
var styles = getComputedStyle(_this.trackXElement);
var paddingLeft = Number.parseFloat(styles.paddingLeft) || 0;
var paddingRight = Number.parseFloat(styles.paddingRight) || 0;
var trackInnerSize = trackRect.width - paddingLeft - paddingRight;
var thumbSize = _this.thumbXElement.clientWidth;
var offset = _this.scrollValues.isRTL && shouldReverseRtlScroll() ? data.x + thumbSize - trackInnerSize + paddingLeft : data.lastX - paddingLeft;
_this.scrollerElement.scrollLeft = calcScrollForThumbOffset(_this.scrollValues.scrollWidth, _this.scrollValues.clientWidth, trackInnerSize, thumbSize, offset);
if ((_a = _this.props.thumbXProps) === null || _a === void 0 ? void 0 : _a.onDrag) {
_this.props.thumbXProps.onDrag(data);
}
};
_this.handleThumbXDragEnd = function (data) {
var _a;
_this.handleThumbXDrag(data);
if ((_a = _this.props.thumbXProps) === null || _a === void 0 ? void 0 : _a.onDragEnd) {
_this.props.thumbXProps.onDragEnd(data);
}
};
_this.handleThumbYDrag = function (data) {
var _a;
if (!_this.scrollerElement || !_this.trackYElement || !_this.thumbYElement || !_this.scrollValues || !_this.scrollValues.scrollYPossible) {
return;
}
_this._scrollDetection();
var trackRect = _this.trackYElement.getBoundingClientRect();
var styles = getComputedStyle(_this.trackYElement);
var paddingTop = Number.parseFloat(styles.paddingTop) || 0;
var paddingBottom = Number.parseFloat(styles.paddingBottom) || 0;
var trackInnerSize = trackRect.height - paddingTop - paddingBottom;
var thumbSize = _this.thumbYElement.clientHeight;
var offset = data.y - paddingTop;
_this.scrollerElement.scrollTop = calcScrollForThumbOffset(_this.scrollValues.scrollHeight, _this.scrollValues.clientHeight, trackInnerSize, thumbSize, offset);
if ((_a = _this.props.thumbYProps) === null || _a === void 0 ? void 0 : _a.onDrag) {
_this.props.thumbYProps.onDrag(data);
}
};
_this.handleThumbYDragEnd = function (data) {
var _a;
_this.handleThumbYDrag(data);
if ((_a = _this.props.thumbYProps) === null || _a === void 0 ? void 0 : _a.onDragEnd) {
_this.props.thumbYProps.onDragEnd(data);
}
};
_this.handleScrollerScroll = function () {
_this._scrollDetection();
};
_this._scrollDetection = function () {
if (!_this._scrollDetectionTO) {
_this.eventEmitter.emit('scrollStart', _this.getScrollState());
} else if (isBrowser) {
window.clearTimeout(_this._scrollDetectionTO);
}
_this._scrollDetectionTO = isBrowser ? window.setTimeout(_this._scrollDetectionCallback, _this.props.scrollDetectionThreshold || 0) : null;
};
_this._scrollDetectionCallback = function () {
_this._scrollDetectionTO = null;
_this.eventEmitter.emit('scrollStop', _this.getScrollState());
};
_this.state = {
trackXVisible: false,
trackYVisible: false,
isRTL: props.rtl
};
_this.scrollValues = _this.getScrollState(true);
_this.eventEmitter = new Emittr(15);
if (props.onUpdate) _this.eventEmitter.on('update', props.onUpdate);
if (props.onScroll) _this.eventEmitter.on('scroll', props.onScroll);
if (props.onScrollStart) _this.eventEmitter.on('scrollStart', props.onScrollStart);
if (props.onScrollStop) _this.eventEmitter.on('scrollStop', props.onScrollStop);
_this.id = uuid();
return _this;
}
Object.defineProperty(Scrollbar.prototype, "scrollTop", {
// eslint-disable-next-line react/sort-comp
get: function get() {
if (this.scrollerElement) {
return this.scrollerElement.scrollTop;
}
return 0;
},
set: function set(top) {
if (this.scrollerElement) {
this.scrollerElement.scrollTop = top;
this.update();
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scrollbar.prototype, "scrollLeft", {
get: function get() {
if (this.scrollerElement) {
return this.scrollerElement.scrollLeft;
}
return 0;
},
set: function set(left) {
if (this.scrollerElement) {
this.scrollerElement.scrollLeft = left;
}
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scrollbar.prototype, "scrollHeight", {
get: function get() {
if (this.scrollerElement) {
return this.scrollerElement.scrollHeight;
}
return 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scrollbar.prototype, "scrollWidth", {
get: function get() {
if (this.scrollerElement) {
return this.scrollerElement.scrollWidth;
}
return 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scrollbar.prototype, "clientHeight", {
get: function get() {
if (this.scrollerElement) {
return this.scrollerElement.clientHeight;
}
return 0;
},
enumerable: false,
configurable: true
});
Object.defineProperty(Scrollbar.prototype, "clientWidth", {
get: function get() {
if (this.scrollerElement) {
return this.scrollerElement.clientWidth;
}
return 0;
},
enumerable: false,
configurable: true
}); // eslint-disable-next-line react/sort-comp
Scrollbar.calculateStyles = function (props, state, scrollValues, scrollbarWidth) {
var _a, _b, _c, _d;
var useDefaultStyles = !props.noDefaultStyles;
return {
holder: __assign(__assign(__assign({}, useDefaultStyles && style.holder), {
position: 'relative'
}), props.style)