@geneui/components
Version:
The Gene UI components library designed for BI tools
1,297 lines (1,123 loc) • 360 kB
JavaScript
import { _ as _extends$1 } from './_rollupPluginBabelHelpers-e8fb2e5c.js';
import * as React from 'react';
import React__default, { forwardRef, useMemo, useCallback, useRef, useState, useEffect } from 'react';
import { t as toPropertyKey, d as _typeof, a as _setPrototypeOf, b as _objectWithoutPropertiesLoose, _ as _defineProperty, c as _extends } from './objectWithoutPropertiesLoose-d8a4a68c.js';
import { p as polyfill } from './react-lifecycles-compat.es-6e1f3768.js';
import { c as clsx } from './clsx.m-2bb6df4b.js';
import PropTypes from 'prop-types';
import * as ReactDOM from 'react-dom';
import { findDOMNode } from 'react-dom';
import { c as classnames } from './index-031ff73c.js';
import useMount from './hooks/useMount.js';
import useClick from './hooks/useClick.js';
import useKeyDown from './hooks/useKeyDown.js';
import useDeviceType from './hooks/useDeviceType.js';
import useClickOutside from './hooks/useClickOutside.js';
import useUpdatableRef from './hooks/useUpdatableRef.js';
import { u as useEllipsisDetection } from './useEllipsisDetection-4d997d5d.js';
import { i as inputConfig, s as screenTypes, g as popoverConfig } from './configs-00612ce0.js';
import { s as stopEvent, n as noop$1 } from './index-a0e4e333.js';
import BusyLoader from './BusyLoader/index.js';
import Empty from './Empty/index.js';
import { P as PopoverV2 } from './index-08898b29.js';
import { T as Tooltip } from './index-6d7e99cd.js';
import ExtendedInput from './ExtendedInput/index.js';
import Icon from './Icon/index.js';
import Checkbox from './Checkbox/index.js';
import './index-0cbb1102.js';
import Tag from './Tag/index.js';
import { c as callAfterDelay } from './callAfterDelay-7272faca.js';
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, toPropertyKey(descriptor.key), descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
Object.defineProperty(Constructor, "prototype", {
writable: false
});
return Constructor;
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _possibleConstructorReturn(self, call) {
if (call && (_typeof(call) === "object" || typeof call === "function")) {
return call;
} else if (call !== void 0) {
throw new TypeError("Derived constructors may only return object or undefined");
}
return _assertThisInitialized(self);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
Object.defineProperty(subClass, "prototype", {
writable: false
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
/**
* Helper method that determines when to recalculate row or column metadata.
*/
function calculateSizeAndPositionDataAndUpdateScrollOffset(_ref) {
var cellCount = _ref.cellCount,
cellSize = _ref.cellSize,
computeMetadataCallback = _ref.computeMetadataCallback,
computeMetadataCallbackProps = _ref.computeMetadataCallbackProps,
nextCellsCount = _ref.nextCellsCount,
nextCellSize = _ref.nextCellSize,
nextScrollToIndex = _ref.nextScrollToIndex,
scrollToIndex = _ref.scrollToIndex,
updateScrollOffsetForScrollToIndex = _ref.updateScrollOffsetForScrollToIndex;
// Don't compare cell sizes if they are functions because inline functions would cause infinite loops.
// In that event users should use the manual recompute methods to inform of changes.
if (cellCount !== nextCellsCount || (typeof cellSize === 'number' || typeof nextCellSize === 'number') && cellSize !== nextCellSize) {
computeMetadataCallback(computeMetadataCallbackProps); // Updated cell metadata may have hidden the previous scrolled-to item.
// In this case we should also update the scrollTop to ensure it stays visible.
if (scrollToIndex >= 0 && scrollToIndex === nextScrollToIndex) {
updateScrollOffsetForScrollToIndex();
}
}
}
function _objectWithoutProperties(source, excluded) {
if (source == null) return {};
var target = _objectWithoutPropertiesLoose(source, excluded);
var key, i;
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
}
return target;
}
process.env.NODE_ENV === 'production' ? null : {
"columnIndex": PropTypes.number.isRequired,
"rowIndex": PropTypes.number.isRequired
};
process.env.NODE_ENV === 'production' ? null : {
"columnIndex": PropTypes.number.isRequired,
"isScrolling": PropTypes.bool.isRequired,
"isVisible": PropTypes.bool.isRequired,
"key": PropTypes.string.isRequired,
"parent": PropTypes.object.isRequired,
"rowIndex": PropTypes.number.isRequired,
"style": PropTypes.object.isRequired
};
var bpfrpt_proptype_CellRenderer = process.env.NODE_ENV === 'production' ? null : PropTypes.func;
process.env.NODE_ENV === 'production' ? null : PropTypes.objectOf(PropTypes.node.isRequired);
process.env.NODE_ENV === 'production' ? null : PropTypes.objectOf(PropTypes.object.isRequired);
process.env.NODE_ENV === 'production' ? null : {
"cellCache": PropTypes.objectOf(PropTypes.node.isRequired).isRequired,
"cellRenderer": PropTypes.func.isRequired,
"columnSizeAndPositionManager": function columnSizeAndPositionManager() {
return (typeof ScalingCellSizeAndPositionManager === "function" ? PropTypes.instanceOf(ScalingCellSizeAndPositionManager).isRequired : PropTypes.any.isRequired).apply(this, arguments);
},
"columnStartIndex": PropTypes.number.isRequired,
"columnStopIndex": PropTypes.number.isRequired,
"deferredMeasurementCache": PropTypes.object,
"horizontalOffsetAdjustment": PropTypes.number.isRequired,
"isScrolling": PropTypes.bool.isRequired,
"isScrollingOptOut": PropTypes.bool.isRequired,
"parent": PropTypes.object.isRequired,
"rowSizeAndPositionManager": function rowSizeAndPositionManager() {
return (typeof ScalingCellSizeAndPositionManager === "function" ? PropTypes.instanceOf(ScalingCellSizeAndPositionManager).isRequired : PropTypes.any.isRequired).apply(this, arguments);
},
"rowStartIndex": PropTypes.number.isRequired,
"rowStopIndex": PropTypes.number.isRequired,
"scrollLeft": PropTypes.number.isRequired,
"scrollTop": PropTypes.number.isRequired,
"styleCache": PropTypes.objectOf(PropTypes.object.isRequired).isRequired,
"verticalOffsetAdjustment": PropTypes.number.isRequired,
"visibleColumnIndices": PropTypes.object.isRequired,
"visibleRowIndices": PropTypes.object.isRequired
};
var bpfrpt_proptype_CellRangeRenderer = process.env.NODE_ENV === 'production' ? null : PropTypes.func;
process.env.NODE_ENV === 'production' ? null : PropTypes.func;
var bpfrpt_proptype_CellSize = process.env.NODE_ENV === 'production' ? null : PropTypes.oneOfType([PropTypes.func, PropTypes.number]);
var bpfrpt_proptype_NoContentRenderer = process.env.NODE_ENV === 'production' ? null : PropTypes.func;
process.env.NODE_ENV === 'production' ? null : {
"clientHeight": PropTypes.number.isRequired,
"clientWidth": PropTypes.number.isRequired,
"scrollHeight": PropTypes.number.isRequired,
"scrollLeft": PropTypes.number.isRequired,
"scrollTop": PropTypes.number.isRequired,
"scrollWidth": PropTypes.number.isRequired
};
process.env.NODE_ENV === 'production' ? null : {
"horizontal": PropTypes.bool.isRequired,
"vertical": PropTypes.bool.isRequired,
"size": PropTypes.number.isRequired
};
process.env.NODE_ENV === 'production' ? null : {
"columnOverscanStartIndex": PropTypes.number.isRequired,
"columnOverscanStopIndex": PropTypes.number.isRequired,
"columnStartIndex": PropTypes.number.isRequired,
"columnStopIndex": PropTypes.number.isRequired,
"rowOverscanStartIndex": PropTypes.number.isRequired,
"rowOverscanStopIndex": PropTypes.number.isRequired,
"rowStartIndex": PropTypes.number.isRequired,
"rowStopIndex": PropTypes.number.isRequired
};
process.env.NODE_ENV === 'production' ? null : {
// One of SCROLL_DIRECTION_HORIZONTAL or SCROLL_DIRECTION_VERTICAL
"direction": PropTypes.oneOf(["horizontal", "vertical"]).isRequired,
// One of SCROLL_DIRECTION_BACKWARD or SCROLL_DIRECTION_FORWARD
"scrollDirection": PropTypes.oneOf([-1, 1]).isRequired,
// Number of rows or columns in the current axis
"cellCount": PropTypes.number.isRequired,
// Maximum number of cells to over-render in either direction
"overscanCellsCount": PropTypes.number.isRequired,
// Begin of range of visible cells
"startIndex": PropTypes.number.isRequired,
// End of range of visible cells
"stopIndex": PropTypes.number.isRequired
};
process.env.NODE_ENV === 'production' ? null : {
"overscanStartIndex": PropTypes.number.isRequired,
"overscanStopIndex": PropTypes.number.isRequired
};
var bpfrpt_proptype_OverscanIndicesGetter = process.env.NODE_ENV === 'production' ? null : PropTypes.func;
var bpfrpt_proptype_Alignment = process.env.NODE_ENV === 'production' ? null : PropTypes.oneOf(["auto", "end", "start", "center"]);
process.env.NODE_ENV === 'production' ? null : {
"start": PropTypes.number,
"stop": PropTypes.number
};
/**
* Just-in-time calculates and caches size and position information for a collection of cells.
*/
var CellSizeAndPositionManager =
/*#__PURE__*/
function () {
// Cache of size and position data for cells, mapped by cell index.
// Note that invalid values may exist in this map so only rely on cells up to this._lastMeasuredIndex
// Measurements for cells up to this index can be trusted; cells afterward should be estimated.
// Used in deferred mode to track which cells have been queued for measurement.
function CellSizeAndPositionManager(_ref) {
var cellCount = _ref.cellCount,
cellSizeGetter = _ref.cellSizeGetter,
estimatedCellSize = _ref.estimatedCellSize;
_classCallCheck(this, CellSizeAndPositionManager);
_defineProperty(this, "_cellSizeAndPositionData", {});
_defineProperty(this, "_lastMeasuredIndex", -1);
_defineProperty(this, "_lastBatchedIndex", -1);
_defineProperty(this, "_cellCount", void 0);
_defineProperty(this, "_cellSizeGetter", void 0);
_defineProperty(this, "_estimatedCellSize", void 0);
this._cellSizeGetter = cellSizeGetter;
this._cellCount = cellCount;
this._estimatedCellSize = estimatedCellSize;
}
_createClass(CellSizeAndPositionManager, [{
key: "areOffsetsAdjusted",
value: function areOffsetsAdjusted() {
return false;
}
}, {
key: "configure",
value: function configure(_ref2) {
var cellCount = _ref2.cellCount,
estimatedCellSize = _ref2.estimatedCellSize,
cellSizeGetter = _ref2.cellSizeGetter;
this._cellCount = cellCount;
this._estimatedCellSize = estimatedCellSize;
this._cellSizeGetter = cellSizeGetter;
}
}, {
key: "getCellCount",
value: function getCellCount() {
return this._cellCount;
}
}, {
key: "getEstimatedCellSize",
value: function getEstimatedCellSize() {
return this._estimatedCellSize;
}
}, {
key: "getLastMeasuredIndex",
value: function getLastMeasuredIndex() {
return this._lastMeasuredIndex;
}
}, {
key: "getOffsetAdjustment",
value: function getOffsetAdjustment() {
return 0;
}
/**
* This method returns the size and position for the cell at the specified index.
* It just-in-time calculates (or used cached values) for cells leading up to the index.
*/
}, {
key: "getSizeAndPositionOfCell",
value: function getSizeAndPositionOfCell(index) {
if (index < 0 || index >= this._cellCount) {
throw Error("Requested index ".concat(index, " is outside of range 0..").concat(this._cellCount));
}
if (index > this._lastMeasuredIndex) {
var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
var offset = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size;
for (var i = this._lastMeasuredIndex + 1; i <= index; i++) {
var size = this._cellSizeGetter({
index: i
}); // undefined or NaN probably means a logic error in the size getter.
// null means we're using CellMeasurer and haven't yet measured a given index.
if (size === undefined || isNaN(size)) {
throw Error("Invalid size returned for cell ".concat(i, " of value ").concat(size));
} else if (size === null) {
this._cellSizeAndPositionData[i] = {
offset: offset,
size: 0
};
this._lastBatchedIndex = index;
} else {
this._cellSizeAndPositionData[i] = {
offset: offset,
size: size
};
offset += size;
this._lastMeasuredIndex = index;
}
}
}
return this._cellSizeAndPositionData[index];
}
}, {
key: "getSizeAndPositionOfLastMeasuredCell",
value: function getSizeAndPositionOfLastMeasuredCell() {
return this._lastMeasuredIndex >= 0 ? this._cellSizeAndPositionData[this._lastMeasuredIndex] : {
offset: 0,
size: 0
};
}
/**
* Total size of all cells being measured.
* This value will be completely estimated initially.
* As cells are measured, the estimate will be updated.
*/
}, {
key: "getTotalSize",
value: function getTotalSize() {
var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
var totalSizeOfMeasuredCells = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size;
var numUnmeasuredCells = this._cellCount - this._lastMeasuredIndex - 1;
var totalSizeOfUnmeasuredCells = numUnmeasuredCells * this._estimatedCellSize;
return totalSizeOfMeasuredCells + totalSizeOfUnmeasuredCells;
}
/**
* Determines a new offset that ensures a certain cell is visible, given the current offset.
* If the cell is already visible then the current offset will be returned.
* If the current offset is too great or small, it will be adjusted just enough to ensure the specified index is visible.
*
* @param align Desired alignment within container; one of "auto" (default), "start", or "end"
* @param containerSize Size (width or height) of the container viewport
* @param currentOffset Container's current (x or y) offset
* @param totalSize Total size (width or height) of all cells
* @return Offset to use to ensure the specified cell is visible
*/
}, {
key: "getUpdatedOffsetForIndex",
value: function getUpdatedOffsetForIndex(_ref3) {
var _ref3$align = _ref3.align,
align = _ref3$align === void 0 ? 'auto' : _ref3$align,
containerSize = _ref3.containerSize,
currentOffset = _ref3.currentOffset,
targetIndex = _ref3.targetIndex;
if (containerSize <= 0) {
return 0;
}
var datum = this.getSizeAndPositionOfCell(targetIndex);
var maxOffset = datum.offset;
var minOffset = maxOffset - containerSize + datum.size;
var idealOffset;
switch (align) {
case 'start':
idealOffset = maxOffset;
break;
case 'end':
idealOffset = minOffset;
break;
case 'center':
idealOffset = maxOffset - (containerSize - datum.size) / 2;
break;
default:
idealOffset = Math.max(minOffset, Math.min(maxOffset, currentOffset));
break;
}
var totalSize = this.getTotalSize();
return Math.max(0, Math.min(totalSize - containerSize, idealOffset));
}
}, {
key: "getVisibleCellRange",
value: function getVisibleCellRange(params) {
var containerSize = params.containerSize,
offset = params.offset;
var totalSize = this.getTotalSize();
if (totalSize === 0) {
return {};
}
var maxOffset = offset + containerSize;
var start = this._findNearestCell(offset);
var datum = this.getSizeAndPositionOfCell(start);
offset = datum.offset + datum.size;
var stop = start;
while (offset < maxOffset && stop < this._cellCount - 1) {
stop++;
offset += this.getSizeAndPositionOfCell(stop).size;
}
return {
start: start,
stop: stop
};
}
/**
* Clear all cached values for cells after the specified index.
* This method should be called for any cell that has changed its size.
* It will not immediately perform any calculations; they'll be performed the next time getSizeAndPositionOfCell() is called.
*/
}, {
key: "resetCell",
value: function resetCell(index) {
this._lastMeasuredIndex = Math.min(this._lastMeasuredIndex, index - 1);
}
}, {
key: "_binarySearch",
value: function _binarySearch(high, low, offset) {
while (low <= high) {
var middle = low + Math.floor((high - low) / 2);
var currentOffset = this.getSizeAndPositionOfCell(middle).offset;
if (currentOffset === offset) {
return middle;
} else if (currentOffset < offset) {
low = middle + 1;
} else if (currentOffset > offset) {
high = middle - 1;
}
}
if (low > 0) {
return low - 1;
} else {
return 0;
}
}
}, {
key: "_exponentialSearch",
value: function _exponentialSearch(index, offset) {
var interval = 1;
while (index < this._cellCount && this.getSizeAndPositionOfCell(index).offset < offset) {
index += interval;
interval *= 2;
}
return this._binarySearch(Math.min(index, this._cellCount - 1), Math.floor(index / 2), offset);
}
/**
* Searches for the cell (index) nearest the specified offset.
*
* If no exact match is found the next lowest cell index will be returned.
* This allows partially visible cells (with offsets just before/above the fold) to be visible.
*/
}, {
key: "_findNearestCell",
value: function _findNearestCell(offset) {
if (isNaN(offset)) {
throw Error("Invalid offset ".concat(offset, " specified"));
} // Our search algorithms find the nearest match at or below the specified offset.
// So make sure the offset is at least 0 or no match will be found.
offset = Math.max(0, offset);
var lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
var lastMeasuredIndex = Math.max(0, this._lastMeasuredIndex);
if (lastMeasuredCellSizeAndPosition.offset >= offset) {
// If we've already measured cells within this range just use a binary search as it's faster.
return this._binarySearch(lastMeasuredIndex, 0, offset);
} else {
// If we haven't yet measured this high, fallback to an exponential search with an inner binary search.
// The exponential search avoids pre-computing sizes for the full set of cells as a binary search would.
// The overall complexity for this approach is O(log n).
return this._exponentialSearch(lastMeasuredIndex, offset);
}
}
}]);
return CellSizeAndPositionManager;
}();
var DEFAULT_MAX_ELEMENT_SIZE = 1500000;
var CHROME_MAX_ELEMENT_SIZE = 1.67771e7;
var isBrowser = function isBrowser() {
return typeof window !== 'undefined';
};
var isChrome = function isChrome() {
return !!window.chrome;
};
var getMaxElementSize = function getMaxElementSize() {
if (isBrowser()) {
if (isChrome()) {
return CHROME_MAX_ELEMENT_SIZE;
}
}
return DEFAULT_MAX_ELEMENT_SIZE;
};
/**
* Extends CellSizeAndPositionManager and adds scaling behavior for lists that are too large to fit within a browser's native limits.
*/
var ScalingCellSizeAndPositionManager =
/*#__PURE__*/
function () {
function ScalingCellSizeAndPositionManager(_ref) {
var _ref$maxScrollSize = _ref.maxScrollSize,
maxScrollSize = _ref$maxScrollSize === void 0 ? getMaxElementSize() : _ref$maxScrollSize,
params = _objectWithoutProperties(_ref, ["maxScrollSize"]);
_classCallCheck(this, ScalingCellSizeAndPositionManager);
_defineProperty(this, "_cellSizeAndPositionManager", void 0);
_defineProperty(this, "_maxScrollSize", void 0);
// Favor composition over inheritance to simplify IE10 support
this._cellSizeAndPositionManager = new CellSizeAndPositionManager(params);
this._maxScrollSize = maxScrollSize;
}
_createClass(ScalingCellSizeAndPositionManager, [{
key: "areOffsetsAdjusted",
value: function areOffsetsAdjusted() {
return this._cellSizeAndPositionManager.getTotalSize() > this._maxScrollSize;
}
}, {
key: "configure",
value: function configure(params) {
this._cellSizeAndPositionManager.configure(params);
}
}, {
key: "getCellCount",
value: function getCellCount() {
return this._cellSizeAndPositionManager.getCellCount();
}
}, {
key: "getEstimatedCellSize",
value: function getEstimatedCellSize() {
return this._cellSizeAndPositionManager.getEstimatedCellSize();
}
}, {
key: "getLastMeasuredIndex",
value: function getLastMeasuredIndex() {
return this._cellSizeAndPositionManager.getLastMeasuredIndex();
}
/**
* Number of pixels a cell at the given position (offset) should be shifted in order to fit within the scaled container.
* The offset passed to this function is scaled (safe) as well.
*/
}, {
key: "getOffsetAdjustment",
value: function getOffsetAdjustment(_ref2) {
var containerSize = _ref2.containerSize,
offset = _ref2.offset;
var totalSize = this._cellSizeAndPositionManager.getTotalSize();
var safeTotalSize = this.getTotalSize();
var offsetPercentage = this._getOffsetPercentage({
containerSize: containerSize,
offset: offset,
totalSize: safeTotalSize
});
return Math.round(offsetPercentage * (safeTotalSize - totalSize));
}
}, {
key: "getSizeAndPositionOfCell",
value: function getSizeAndPositionOfCell(index) {
return this._cellSizeAndPositionManager.getSizeAndPositionOfCell(index);
}
}, {
key: "getSizeAndPositionOfLastMeasuredCell",
value: function getSizeAndPositionOfLastMeasuredCell() {
return this._cellSizeAndPositionManager.getSizeAndPositionOfLastMeasuredCell();
}
/** See CellSizeAndPositionManager#getTotalSize */
}, {
key: "getTotalSize",
value: function getTotalSize() {
return Math.min(this._maxScrollSize, this._cellSizeAndPositionManager.getTotalSize());
}
/** See CellSizeAndPositionManager#getUpdatedOffsetForIndex */
}, {
key: "getUpdatedOffsetForIndex",
value: function getUpdatedOffsetForIndex(_ref3) {
var _ref3$align = _ref3.align,
align = _ref3$align === void 0 ? 'auto' : _ref3$align,
containerSize = _ref3.containerSize,
currentOffset = _ref3.currentOffset,
targetIndex = _ref3.targetIndex;
currentOffset = this._safeOffsetToOffset({
containerSize: containerSize,
offset: currentOffset
});
var offset = this._cellSizeAndPositionManager.getUpdatedOffsetForIndex({
align: align,
containerSize: containerSize,
currentOffset: currentOffset,
targetIndex: targetIndex
});
return this._offsetToSafeOffset({
containerSize: containerSize,
offset: offset
});
}
/** See CellSizeAndPositionManager#getVisibleCellRange */
}, {
key: "getVisibleCellRange",
value: function getVisibleCellRange(_ref4) {
var containerSize = _ref4.containerSize,
offset = _ref4.offset;
offset = this._safeOffsetToOffset({
containerSize: containerSize,
offset: offset
});
return this._cellSizeAndPositionManager.getVisibleCellRange({
containerSize: containerSize,
offset: offset
});
}
}, {
key: "resetCell",
value: function resetCell(index) {
this._cellSizeAndPositionManager.resetCell(index);
}
}, {
key: "_getOffsetPercentage",
value: function _getOffsetPercentage(_ref5) {
var containerSize = _ref5.containerSize,
offset = _ref5.offset,
totalSize = _ref5.totalSize;
return totalSize <= containerSize ? 0 : offset / (totalSize - containerSize);
}
}, {
key: "_offsetToSafeOffset",
value: function _offsetToSafeOffset(_ref6) {
var containerSize = _ref6.containerSize,
offset = _ref6.offset;
var totalSize = this._cellSizeAndPositionManager.getTotalSize();
var safeTotalSize = this.getTotalSize();
if (totalSize === safeTotalSize) {
return offset;
} else {
var offsetPercentage = this._getOffsetPercentage({
containerSize: containerSize,
offset: offset,
totalSize: totalSize
});
return Math.round(offsetPercentage * (safeTotalSize - containerSize));
}
}
}, {
key: "_safeOffsetToOffset",
value: function _safeOffsetToOffset(_ref7) {
var containerSize = _ref7.containerSize,
offset = _ref7.offset;
var totalSize = this._cellSizeAndPositionManager.getTotalSize();
var safeTotalSize = this.getTotalSize();
if (totalSize === safeTotalSize) {
return offset;
} else {
var offsetPercentage = this._getOffsetPercentage({
containerSize: containerSize,
offset: offset,
totalSize: safeTotalSize
});
return Math.round(offsetPercentage * (totalSize - containerSize));
}
}
}]);
return ScalingCellSizeAndPositionManager;
}();
/**
* Helper utility that updates the specified callback whenever any of the specified indices have changed.
*/
function createCallbackMemoizer() {
var requireAllKeys = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
var cachedIndices = {};
return function (_ref) {
var callback = _ref.callback,
indices = _ref.indices;
var keys = Object.keys(indices);
var allInitialized = !requireAllKeys || keys.every(function (key) {
var value = indices[key];
return Array.isArray(value) ? value.length > 0 : value >= 0;
});
var indexChanged = keys.length !== Object.keys(cachedIndices).length || keys.some(function (key) {
var cachedValue = cachedIndices[key];
var value = indices[key];
return Array.isArray(value) ? cachedValue.join(',') !== value.join(',') : cachedValue !== value;
});
cachedIndices = indices;
if (allInitialized && indexChanged) {
callback(indices);
}
};
}
var SCROLL_DIRECTION_BACKWARD = -1;
var SCROLL_DIRECTION_FORWARD$1 = 1;
/**
* Calculates the number of cells to overscan before and after a specified range.
* This function ensures that overscanning doesn't exceed the available cells.
*/
function defaultOverscanIndicesGetter$1(_ref) {
var cellCount = _ref.cellCount,
overscanCellsCount = _ref.overscanCellsCount,
scrollDirection = _ref.scrollDirection,
startIndex = _ref.startIndex,
stopIndex = _ref.stopIndex;
if (scrollDirection === SCROLL_DIRECTION_FORWARD$1) {
return {
overscanStartIndex: Math.max(0, startIndex),
overscanStopIndex: Math.min(cellCount - 1, stopIndex + overscanCellsCount)
};
} else {
return {
overscanStartIndex: Math.max(0, startIndex - overscanCellsCount),
overscanStopIndex: Math.min(cellCount - 1, stopIndex)
};
}
}
/**
* Helper function that determines when to update scroll offsets to ensure that a scroll-to-index remains visible.
* This function also ensures that the scroll ofset isn't past the last column/row of cells.
*/
function updateScrollIndexHelper(_ref) {
var cellSize = _ref.cellSize,
cellSizeAndPositionManager = _ref.cellSizeAndPositionManager,
previousCellsCount = _ref.previousCellsCount,
previousCellSize = _ref.previousCellSize,
previousScrollToAlignment = _ref.previousScrollToAlignment,
previousScrollToIndex = _ref.previousScrollToIndex,
previousSize = _ref.previousSize,
scrollOffset = _ref.scrollOffset,
scrollToAlignment = _ref.scrollToAlignment,
scrollToIndex = _ref.scrollToIndex,
size = _ref.size,
sizeJustIncreasedFromZero = _ref.sizeJustIncreasedFromZero,
updateScrollIndexCallback = _ref.updateScrollIndexCallback;
var cellCount = cellSizeAndPositionManager.getCellCount();
var hasScrollToIndex = scrollToIndex >= 0 && scrollToIndex < cellCount;
var sizeHasChanged = size !== previousSize || sizeJustIncreasedFromZero || !previousCellSize || typeof cellSize === 'number' && cellSize !== previousCellSize; // If we have a new scroll target OR if height/row-height has changed,
// We should ensure that the scroll target is visible.
if (hasScrollToIndex && (sizeHasChanged || scrollToAlignment !== previousScrollToAlignment || scrollToIndex !== previousScrollToIndex)) {
updateScrollIndexCallback(scrollToIndex); // If we don't have a selected item but list size or number of children have decreased,
// Make sure we aren't scrolled too far past the current content.
} else if (!hasScrollToIndex && cellCount > 0 && (size < previousSize || cellCount < previousCellsCount)) {
// We need to ensure that the current scroll offset is still within the collection's range.
// To do this, we don't need to measure everything; CellMeasurer would perform poorly.
// Just check to make sure we're still okay.
// Only adjust the scroll position if we've scrolled below the last set of rows.
if (scrollOffset > cellSizeAndPositionManager.getTotalSize() - size) {
updateScrollIndexCallback(cellCount - 1);
}
}
}
/**
* Default implementation of cellRangeRenderer used by Grid.
* This renderer supports cell-caching while the user is scrolling.
*/
function defaultCellRangeRenderer(_ref) {
var cellCache = _ref.cellCache,
cellRenderer = _ref.cellRenderer,
columnSizeAndPositionManager = _ref.columnSizeAndPositionManager,
columnStartIndex = _ref.columnStartIndex,
columnStopIndex = _ref.columnStopIndex,
deferredMeasurementCache = _ref.deferredMeasurementCache,
horizontalOffsetAdjustment = _ref.horizontalOffsetAdjustment,
isScrolling = _ref.isScrolling,
isScrollingOptOut = _ref.isScrollingOptOut,
parent = _ref.parent,
rowSizeAndPositionManager = _ref.rowSizeAndPositionManager,
rowStartIndex = _ref.rowStartIndex,
rowStopIndex = _ref.rowStopIndex,
styleCache = _ref.styleCache,
verticalOffsetAdjustment = _ref.verticalOffsetAdjustment,
visibleColumnIndices = _ref.visibleColumnIndices,
visibleRowIndices = _ref.visibleRowIndices;
var renderedCells = []; // Browsers have native size limits for elements (eg Chrome 33M pixels, IE 1.5M pixes).
// User cannot scroll beyond these size limitations.
// In order to work around this, ScalingCellSizeAndPositionManager compresses offsets.
// We should never cache styles for compressed offsets though as this can lead to bugs.
// See issue #576 for more.
var areOffsetsAdjusted = columnSizeAndPositionManager.areOffsetsAdjusted() || rowSizeAndPositionManager.areOffsetsAdjusted();
var canCacheStyle = !isScrolling && !areOffsetsAdjusted;
for (var rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {
var rowDatum = rowSizeAndPositionManager.getSizeAndPositionOfCell(rowIndex);
for (var columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) {
var columnDatum = columnSizeAndPositionManager.getSizeAndPositionOfCell(columnIndex);
var isVisible = columnIndex >= visibleColumnIndices.start && columnIndex <= visibleColumnIndices.stop && rowIndex >= visibleRowIndices.start && rowIndex <= visibleRowIndices.stop;
var key = "".concat(rowIndex, "-").concat(columnIndex);
var style = void 0; // Cache style objects so shallow-compare doesn't re-render unnecessarily.
if (canCacheStyle && styleCache[key]) {
style = styleCache[key];
} else {
// In deferred mode, cells will be initially rendered before we know their size.
// Don't interfere with CellMeasurer's measurements by setting an invalid size.
if (deferredMeasurementCache && !deferredMeasurementCache.has(rowIndex, columnIndex)) {
// Position not-yet-measured cells at top/left 0,0,
// And give them width/height of 'auto' so they can grow larger than the parent Grid if necessary.
// Positioning them further to the right/bottom influences their measured size.
style = {
height: 'auto',
left: 0,
position: 'absolute',
top: 0,
width: 'auto'
};
} else {
style = {
height: rowDatum.size,
left: columnDatum.offset + horizontalOffsetAdjustment,
position: 'absolute',
top: rowDatum.offset + verticalOffsetAdjustment,
width: columnDatum.size
};
styleCache[key] = style;
}
}
var cellRendererParams = {
columnIndex: columnIndex,
isScrolling: isScrolling,
isVisible: isVisible,
key: key,
parent: parent,
rowIndex: rowIndex,
style: style
};
var renderedCell = void 0; // Avoid re-creating cells while scrolling.
// This can lead to the same cell being created many times and can cause performance issues for "heavy" cells.
// If a scroll is in progress- cache and reuse cells.
// This cache will be thrown away once scrolling completes.
// However if we are scaling scroll positions and sizes, we should also avoid caching.
// This is because the offset changes slightly as scroll position changes and caching leads to stale values.
// For more info refer to issue #395
//
// If isScrollingOptOut is specified, we always cache cells.
// For more info refer to issue #1028
if ((isScrollingOptOut || isScrolling) && !horizontalOffsetAdjustment && !verticalOffsetAdjustment) {
if (!cellCache[key]) {
cellCache[key] = cellRenderer(cellRendererParams);
}
renderedCell = cellCache[key]; // If the user is no longer scrolling, don't cache cells.
// This makes dynamic cell content difficult for users and would also lead to a heavier memory footprint.
} else {
renderedCell = cellRenderer(cellRendererParams);
}
if (renderedCell == null || renderedCell === false) {
continue;
}
if (process.env.NODE_ENV !== 'production') {
warnAboutMissingStyle(parent, renderedCell);
}
renderedCells.push(renderedCell);
}
}
return renderedCells;
}
function warnAboutMissingStyle(parent, renderedCell) {
if (process.env.NODE_ENV !== 'production') {
if (renderedCell) {
// If the direct child is a CellMeasurer, then we should check its child
// See issue #611
if (renderedCell.type && renderedCell.type.__internalCellMeasurerFlag) {
renderedCell = renderedCell.props.children;
}
if (renderedCell && renderedCell.props && renderedCell.props.style === undefined && parent.__warnedAboutMissingStyle !== true) {
parent.__warnedAboutMissingStyle = true;
console.warn('Rendered cell should include style property for positioning.');
}
}
}
}
var canUseDOM = !!(typeof window !== 'undefined' && window.document && window.document.createElement);
var size;
function scrollbarSize(recalc) {
if (!size && size !== 0 || recalc) {
if (canUseDOM) {
var scrollDiv = document.createElement('div');
scrollDiv.style.position = 'absolute';
scrollDiv.style.top = '-9999px';
scrollDiv.style.width = '50px';
scrollDiv.style.height = '50px';
scrollDiv.style.overflow = 'scroll';
document.body.appendChild(scrollDiv);
size = scrollDiv.offsetWidth - scrollDiv.clientWidth;
document.body.removeChild(scrollDiv);
}
}
return size;
}
// Properly handle server-side rendering.
var win;
if (typeof window !== 'undefined') {
win = window;
} else if (typeof self !== 'undefined') {
win = self;
} else {
win = {};
} // requestAnimationFrame() shim by Paul Irish
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
var request = win.requestAnimationFrame || win.webkitRequestAnimationFrame || win.mozRequestAnimationFrame || win.oRequestAnimationFrame || win.msRequestAnimationFrame || function (callback) {
return win.setTimeout(callback, 1000 / 60);
};
var cancel = win.cancelAnimationFrame || win.webkitCancelAnimationFrame || win.mozCancelAnimationFrame || win.oCancelAnimationFrame || win.msCancelAnimationFrame || function (id) {
win.clearTimeout(id);
};
var raf = request;
var caf = cancel;
process.env.NODE_ENV === 'production' ? null : {
"id": PropTypes.number.isRequired
};
var cancelAnimationTimeout = function cancelAnimationTimeout(frame) {
return caf(frame.id);
};
/**
* Recursively calls requestAnimationFrame until a specified delay has been met or exceeded.
* When the delay time has been reached the function you're timing out will be called.
*
* Credit: Joe Lambert (https://gist.github.com/joelambert/1002116#file-requesttimeout-js)
*/
var requestAnimationTimeout = function requestAnimationTimeout(callback, delay) {
var start; // wait for end of processing current event handler, because event handler may be long
Promise.resolve().then(function () {
start = Date.now();
});
var timeout = function timeout() {
if (Date.now() - start >= delay) {
callback.call();
} else {
frame.id = raf(timeout);
}
};
var frame = {
id: raf(timeout)
};
return frame;
};
var _class$6, _temp$6;
function ownKeys$7(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread$7(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys$7(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys$7(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
/**
* Specifies the number of milliseconds during which to disable pointer events while a scroll is in progress.
* This improves performance and makes scrolling smoother.
*/
var DEFAULT_SCROLLING_RESET_TIME_INTERVAL$1 = 150;
/**
* Controls whether the Grid updates the DOM element's scrollLeft/scrollTop based on the current state or just observes it.
* This prevents Grid from interrupting mouse-wheel animations (see issue #2).
*/
var SCROLL_POSITION_CHANGE_REASONS$1 = {
OBSERVED: 'observed',
REQUESTED: 'requested'
};
var renderNull = function renderNull() {
return null;
};
/**
* Renders tabular data with virtualization along the vertical and horizontal axes.
* Row heights and column widths must be known ahead of time and specified as properties.
*/
var Grid = (_temp$6 = _class$6 =
/*#__PURE__*/
function (_React$PureComponent) {
_inherits(Grid, _React$PureComponent);
// Invokes onSectionRendered callback only when start/stop row or column indices change
function Grid(props) {
var _this;
_classCallCheck(this, Grid);
_this = _possibleConstructorReturn(this, _getPrototypeOf(Grid).call(this, props));
_defineProperty(_assertThisInitialized(_this), "_onGridRenderedMemoizer", createCallbackMemoizer());
_defineProperty(_assertThisInitialized(_this), "_onScrollMemoizer", createCallbackMemoizer(false));
_defineProperty(_assertThisInitialized(_this), "_deferredInvalidateColumnIndex", null);
_defineProperty(_assertThisInitialized(_this), "_deferredInvalidateRowIndex", null);
_defineProperty(_assertThisInitialized(_this), "_recomputeScrollLeftFlag", false);
_defineProperty(_assertThisInitialized(_this), "_recomputeScrollTopFlag", false);
_defineProperty(_assertThisInitialized(_this), "_horizontalScrollBarSize", 0);
_defineProperty(_assertThisInitialized(_this), "_verticalScrollBarSize", 0);
_defineProperty(_assertThisInitialized(_this), "_scrollbarPresenceChanged", false);
_defineProperty(_assertThisInitialized(_this), "_scrollingContainer", void 0);
_defineProperty(_assertThisInitialized(_this), "_childrenToDisplay", void 0);
_defineProperty(_assertThisInitialized(_this), "_columnStartIndex", void 0);
_defineProperty(_assertThisInitialized(_this), "_columnStopIndex", void 0);
_defineProperty(_assertThisInitialized(_this), "_rowStartIndex", void 0);
_defineProperty(_assertThisInitialized(_this), "_rowStopIndex", void 0);
_defineProperty(_assertThisInitialized(_this), "_renderedColumnStartIndex", 0);
_defineProperty(_assertThisInitialized(_this), "_renderedColumnStopIndex", 0);
_defineProperty(_assertThisInitialized(_this), "_renderedRowStartIndex", 0);
_defineProperty(_assertThisInitialized(_this), "_renderedRowStopIndex", 0);
_defineProperty(_assertThisInitialized(_this), "_initialScrollTop", void 0);
_defineProperty(_assertThisInitialized(_this), "_initialScrollLeft", void 0);
_defineProperty(_assertThisInitialized(_this), "_disablePointerEventsTimeoutId", void 0);
_defineProperty(_assertThisInitialized(_this), "_styleCache", {});
_defineProperty(_assertThisInitialized(_this), "_cellCache", {});
_defineProperty(_assertThisInitialized(_this), "_debounceScrollEndedCallback", function () {
_this._disablePointerEventsTimeoutId = null; // isScrolling is used to determine if we reset styleCache
_this.setState({
isScrolling: false,
needToResetStyleCache: false
});
});
_defineProperty(_assertThisInitialized(_this), "_invokeOnGridRenderedHelper", function () {
var onSectionRendered = _this.props.onSectionRendered;
_this._onGridRenderedMemoizer({
callback: onSectionRendered,
indices: {
columnOverscanStartIndex: _this._columnStartIndex,
columnOverscanStopIndex: _this._columnStopIndex,
columnStartIndex: _this._renderedColumnStartIndex,
columnStopIndex: _this._renderedColumnStopIndex,
rowOverscanStartIndex: _this._rowStartIndex,
rowOverscanStopIndex: _this._rowStopIndex,
rowStartIndex: _this._renderedRowStartIndex,
rowStopIndex: _this._renderedRowStopIndex
}
});
});
_defineProperty(_assertThisInitialized(_this), "_setScrollingContainerRef", function (ref) {
_this._scrollingContainer = ref;
});
_defineProperty(_assertThisInitialized(_this), "_onScroll", function (event) {
// In certain edge-cases React dispatches an onScroll event with an invalid target.scrollLeft / target.scrollTop.
// This invalid event can be detected by comparing event.target to this component's scrollable DOM element.
// See issue #404 for more information.
if (event.target === _this._scrollingContainer) {
_this.handleScrollEvent(event.target);
}
});
var columnSizeAndPositionManager = new ScalingCellSizeAndPositionManager({
cellCount: props.columnCount,
cellSizeGetter: function cellSizeGetter(params) {
return Grid._wrapSizeGetter(props.columnWidth)(params);
},
estimatedCellSize: Grid._getEstimatedColumnSize(props)
});
var rowSizeAndPositionManager = new ScalingCellSizeAndPositionManager({
cellCount: props.rowCount,
cellSizeGetter: function cellSizeGetter(params) {
return Grid._wrapSizeGetter(props.rowHeight)(params);
},
estimatedCellSize: Grid._getEstimatedRowSize(props)
});
_this.state = {
instanceProps: {
columnSizeAndPositionManager: columnSizeAndPositionManager,
rowSizeAndPositionManager: rowSizeAndPositionManager,
prevColumnWidth: props.columnWidth,
prevRowHeight: props.rowHeight,
prevColumnCount: props.columnCount,
prevRowCount: props.rowCount,
prevIsScrolling: props.isScrolling === true,
prevScrollToColumn: props.scrollToColumn,
prevScrollToRow: props.scrollToRow,
scrollbarSize: 0,
scrollbarSizeMeasured: false
},
isScrolling: false,
scrollDirectionHorizontal: SCROLL_DIRECTION_FORWARD$1,
scrollDirectionVertical: SCROLL_DIRECTION_FORWARD$1,
scrollLeft: 0,
scrollTop: 0,
scrollPositionChangeReason: null,
needToResetStyleCache: false
};
if (props.scrollToRow > 0) {
_this._initialScrollTop = _this._getCalculatedScrollTop(props, _this.state);
}
if (props.scrollToColumn > 0) {
_this._initialScrollLeft = _this._getCalculatedScrollLeft(props, _this.state);
}
return _this;
}
/**
* Gets offsets for a given cell and alignment.
*/
_createClass(Grid, [{
key: "getOffsetForCell",
value: function getOffsetForCell() {
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_ref$alignment = _ref.alignment,
alignment = _ref$alignment === void 0 ? this.props.scrollToAlignment : _ref$alignment,
_ref$columnIndex = _ref.columnIndex,
columnIndex = _ref$columnIndex === void 0 ? this.props.scrollToColumn : _ref$columnIndex,
_ref$rowIndex = _ref.rowIndex,
rowIndex = _ref$rowIndex === void 0 ? this.props.scrollToRow : _ref$rowIndex;
var offsetProps = _objectSpread$7({}, this.props, {
scrollToAlignment: alignment,
scrollToColumn: columnIndex,
scrollToRow: rowIndex
});
return {
scrollLeft: this._getCalculatedScrollLeft(offsetProps),
scrollTop: this._getCalculatedScrollTop(offsetProps)
};
}
/**
* Gets estimated total rows' height.
*/
}, {
key: "getTotalRowsHeight",
value: function getTotalRowsHeight() {
return this.state.instanceProps.rowSizeAndPositionManager.getTotalSize();
}
/**
* Gets estimated total columns' width.
*/
}, {
key: "getTotalColumnsWidth",
value: function getTotalColumnsWidth() {
return this.state.instanceProps.columnSizeAndPositionManager.getTotalSize();
}
/**
* This method handles a scroll event originating from an external scroll control.
* It's an advanced method and should probably not be used unless you're implementing a custom scroll-bar solution.
*/
}, {
key: "handleScrollEvent",
value: function handleScrollEvent(_ref2) {
var _ref2$scrollLeft = _ref2.scrollLeft,
scrollLeftParam = _ref2$scrollLeft === void 0 ? 0 : _ref2$scrollLeft,
_ref2$scrollTop = _ref2.scrollTop,
scrollTopParam = _ref2$scrollTop === void 0 ? 0 : _ref2$scrollTop;
// On iOS, we can arrive at negative offsets by swiping past the start.
// To prevent flicker here, we make playing in the negative offset zone cause nothing to happen.
if (scrollTopParam < 0) {
return;
} // Prevent pointer events from interrupting a smooth scroll
this._debounceScrollEnded();
var _this$props = this.props,
autoHeight = _this$props.autoHeight,
autoWidth = _this$props.autoWidth,
height = _this$props.height,
width = _this$props.width;
var instanceProps = this.state.instanceProps; // When this component is shrunk drastically, React dispatches a series of back-to-back scroll events,
// Gradually converging on a scrollTop that is within the bounds of the new, smaller height.
// This causes a series of rapid renders that is slow for long lists.
// We can avoid that by doing some simple bounds checking to ensure that scroll offsets never exceed their bounds.
var scrollbarSize = instanceProps.scrollbarSize;
var totalRowsHeight = instanceProps.rowSizeAndPositionManager.getTotalSize();
var