UNPKG

@geneui/components

Version:

The Gene UI components library designed for BI tools

1,297 lines (1,123 loc) 360 kB
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