react-virtualized
Version:
React components for efficiently rendering large, scrollable lists and tabular data
5,450 lines • 180 kB
JavaScript
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const jsxRuntime = require("react/jsx-runtime");
const react = require("react");
const scrollbarSize = require("dom-helpers/scrollbarSize");
const clsx = require("clsx");
const useIsomorphicLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
const defaultArrowKeyStepperProps = /* @__PURE__ */ Object.freeze({
disabled: false,
isControlled: false,
mode: "edges",
scrollToColumn: 0,
scrollToRow: 0
});
const initialState = {
scrollToColumn: 0,
scrollToRow: 0,
prevScrollToColumn: 0,
prevScrollToRow: 0
};
function deriveState(isControlled, scrollToColumn, scrollToRow, prevState) {
if (!isControlled && (scrollToColumn !== prevState.prevScrollToColumn || scrollToRow !== prevState.prevScrollToRow)) {
return {
scrollToColumn,
scrollToRow,
prevScrollToColumn: scrollToColumn,
prevScrollToRow: scrollToRow
};
}
return prevState;
}
const ArrowKeyStepper = /* @__PURE__ */ react.memo(
/* @__PURE__ */ react.forwardRef(function ArrowKeyStepper2({
children,
className,
columnCount,
disabled = defaultArrowKeyStepperProps.disabled,
isControlled = defaultArrowKeyStepperProps.isControlled,
mode = defaultArrowKeyStepperProps.mode,
onScrollToChange,
rowCount,
scrollToColumn: scrollToColumnProp = defaultArrowKeyStepperProps.scrollToColumn,
scrollToRow: scrollToRowProp = defaultArrowKeyStepperProps.scrollToRow
}, ref) {
const [storedState, setState] = react.useState(
() => deriveState(
isControlled,
scrollToColumnProp,
scrollToRowProp,
initialState
)
);
const state = deriveState(
isControlled,
scrollToColumnProp,
scrollToRowProp,
storedState
);
if (state !== storedState) {
setState(state);
}
const scrollToColumn = isControlled ? scrollToColumnProp : state.scrollToColumn;
const scrollToRow = isControlled ? scrollToRowProp : state.scrollToRow;
const renderedSectionRef = react.useRef({
columnStartIndex: 0,
columnStopIndex: 0,
rowStartIndex: 0,
rowStopIndex: 0
});
const childRef = react.useRef(null);
const activeCellRef = react.useRef({
scrollToColumn,
scrollToRow
});
const lastScrolledRef = react.useRef(null);
const scrollChildToActiveCell = react.useCallback(() => {
const child = childRef.current;
const { scrollToColumn: scrollToColumn2, scrollToRow: scrollToRow2 } = activeCellRef.current;
const lastScrolled = lastScrolledRef.current;
if (child === null || lastScrolled !== null && lastScrolled.child === child && lastScrolled.scrollToColumn === scrollToColumn2 && lastScrolled.scrollToRow === scrollToRow2) {
return;
}
lastScrolledRef.current = { child, scrollToColumn: scrollToColumn2, scrollToRow: scrollToRow2 };
child.scrollToCell({
columnIndex: scrollToColumn2,
rowIndex: scrollToRow2
});
}, []);
const registerChild = react.useCallback(
(child) => {
childRef.current = child;
if (child !== null) {
scrollChildToActiveCell();
}
},
[scrollChildToActiveCell]
);
useIsomorphicLayoutEffect(() => {
activeCellRef.current = { scrollToColumn, scrollToRow };
scrollChildToActiveCell();
}, [scrollChildToActiveCell, scrollToColumn, scrollToRow]);
const onSectionRendered = react.useCallback(
({
columnStartIndex,
columnStopIndex,
rowStartIndex,
rowStopIndex
}) => {
renderedSectionRef.current = {
columnStartIndex,
columnStopIndex,
rowStartIndex,
rowStopIndex
};
},
[]
);
react.useImperativeHandle(
ref,
() => ({
setScrollIndexes({ scrollToColumn: scrollToColumn2, scrollToRow: scrollToRow2 }) {
setState((prevState) => ({
...prevState,
scrollToColumn: scrollToColumn2,
scrollToRow: scrollToRow2
}));
}
}),
[]
);
const onKeyDown = (event) => {
if (disabled) {
return;
}
const { columnStartIndex, columnStopIndex, rowStartIndex, rowStopIndex } = renderedSectionRef.current;
let nextScrollToColumn = scrollToColumn;
let nextScrollToRow = scrollToRow;
switch (event.key) {
case "ArrowDown":
nextScrollToRow = mode === "cells" ? Math.min(scrollToRow + 1, rowCount - 1) : Math.min(rowStopIndex + 1, rowCount - 1);
break;
case "ArrowLeft":
nextScrollToColumn = mode === "cells" ? Math.max(scrollToColumn - 1, 0) : Math.max(columnStartIndex - 1, 0);
break;
case "ArrowRight":
nextScrollToColumn = mode === "cells" ? Math.min(scrollToColumn + 1, columnCount - 1) : Math.min(columnStopIndex + 1, columnCount - 1);
break;
case "ArrowUp":
nextScrollToRow = mode === "cells" ? Math.max(scrollToRow - 1, 0) : Math.max(rowStartIndex - 1, 0);
break;
}
if (nextScrollToColumn !== scrollToColumn || nextScrollToRow !== scrollToRow) {
event.preventDefault();
if (typeof onScrollToChange === "function") {
onScrollToChange({
scrollToColumn: nextScrollToColumn,
scrollToRow: nextScrollToRow
});
}
if (!isControlled) {
setState((prevState) => ({
...prevState,
scrollToColumn: nextScrollToColumn,
scrollToRow: nextScrollToRow
}));
}
}
};
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, onKeyDown, children: children({
onSectionRendered,
registerChild,
scrollToColumn,
scrollToRow
}) });
})
);
const CellMeasurer = /* @__PURE__ */ Object.assign(
/* @__PURE__ */ react.memo(function CellMeasurer2(props) {
const { children } = props;
const [internals] = react.useState(createInternals);
const latestPropsRef = react.useRef(props);
react.useInsertionEffect(() => {
latestPropsRef.current = props;
});
const maybeMeasureCell = react.useCallback(() => {
const { cache, columnIndex = 0, index, parent } = latestPropsRef.current;
const rowIndex = latestPropsRef.current.rowIndex ?? index ?? 0;
if (!cache.has(rowIndex, columnIndex)) {
const measurements = getCellMeasurements(
cache,
getMeasurableNode(internals)
);
if (measurements === null) {
if (process.env.NODE_ENV !== "production") {
warnAboutMissingNode(cache, internals);
}
return;
}
cache.set(
rowIndex,
columnIndex,
measurements.width,
measurements.height
);
if (parent && typeof parent.invalidateCellSizeAfterRender === "function") {
parent.invalidateCellSizeAfterRender({
columnIndex,
rowIndex
});
}
}
}, [internals]);
const measure = react.useCallback(() => {
const { cache, columnIndex = 0, index, parent } = latestPropsRef.current;
const rowIndex = latestPropsRef.current.rowIndex ?? index ?? 0;
if (!internals.isMounted) {
return;
}
const measurements = getCellMeasurements(
cache,
getMeasurableNode(internals)
);
if (measurements === null) {
if (process.env.NODE_ENV !== "production") {
warnAboutMissingNode(cache, internals);
}
return;
}
const { height, width } = measurements;
if (height !== cache.getHeight(rowIndex, columnIndex) || width !== cache.getWidth(rowIndex, columnIndex)) {
cache.set(rowIndex, columnIndex, width, height);
if (parent && typeof parent.recomputeGridSize === "function") {
parent.recomputeGridSize({
columnIndex,
rowIndex
});
}
}
}, [internals]);
const registerChild = react.useCallback(
(element2) => {
if (element2 && !(element2 instanceof Element)) {
console.warn(
"CellMeasurer registerChild expects to be passed Element or null"
);
}
internals.registeredNode = element2 ?? null;
if (element2) {
maybeMeasureCell();
}
},
[internals, maybeMeasureCell]
);
useIsomorphicLayoutEffect(() => {
internals.isMounted = true;
return () => {
internals.isMounted = false;
};
}, [internals]);
useIsomorphicLayoutEffect(() => {
maybeMeasureCell();
});
const resolvedChildren = typeof children === "function" ? children({ measure, registerChild }) : children;
const element = getMeasurableElement(resolvedChildren);
const hasMeasurableElement = element !== null;
react.useInsertionEffect(() => {
internals.hasMeasurableElement = hasMeasurableElement;
});
const childRef = element !== null ? getElementRef(element) : null;
const composedRef = react.useCallback(
(node) => {
if (node === null) {
if (typeof internals.childRefCleanup === "function") {
internals.childRefCleanup();
} else {
assignRef(childRef, null);
}
internals.childRefCleanup = void 0;
internals.clonedNode = null;
} else {
internals.childRefCleanup = assignRef(childRef, node);
internals.clonedNode = node;
}
},
[childRef, internals]
);
if (element === null) {
return resolvedChildren === void 0 ? null : resolvedChildren;
}
return react.cloneElement(element, { ref: composedRef });
}),
{
// Lets Grid's DEV warning about a missing "style" check the CellMeasurer's child instead (see issue #611)
__internalCellMeasurerFlag: process.env.NODE_ENV !== "production"
}
);
function createInternals() {
return {
childRefCleanup: void 0,
clonedNode: null,
hasMeasurableElement: false,
isMounted: false,
registeredNode: null
};
}
function isHTMLElement(node) {
if (node == null || typeof node !== "object") {
return false;
}
const view = node.ownerDocument?.defaultView;
return view != null && node instanceof view.HTMLElement;
}
function getMeasurableNode(internals) {
if (isHTMLElement(internals.registeredNode)) {
return internals.registeredNode;
} else if (isHTMLElement(internals.clonedNode)) {
return internals.clonedNode;
}
return null;
}
function getCellMeasurements(cache, node) {
if (node === null) {
return null;
}
const styleWidth = node.style.width;
const styleHeight = node.style.height;
if (!cache.hasFixedWidth()) {
node.style.width = "auto";
}
if (!cache.hasFixedHeight()) {
node.style.height = "auto";
}
const height = Math.ceil(node.offsetHeight);
const width = Math.ceil(node.offsetWidth);
if (styleWidth) {
node.style.width = styleWidth;
}
if (styleHeight) {
node.style.height = styleHeight;
}
return { height, width };
}
function getMeasurableElement(children) {
if (!react.isValidElement(children) || children.type === react.Fragment) {
return null;
}
if (!isReact19OrNewer() && isPlainFunctionComponent(children.type)) {
return null;
}
return children;
}
const MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo");
function isPlainFunctionComponent(type) {
if (typeof type === "function") {
return !(type.prototype && type.prototype.isReactComponent);
} else if (type != null && typeof type === "object" && type.$$typeof === MEMO_TYPE) {
return isPlainFunctionComponent(type.type);
}
return false;
}
function isReact19OrNewer() {
return parseInt(react.version, 10) >= 19;
}
function getElementRef(element) {
const props = element.props;
if (props != null && "ref" in props) {
return props.ref ?? null;
}
return element.ref ?? null;
}
function assignRef(ref, value) {
if (typeof ref === "function") {
return ref(value);
} else if (ref) {
ref.current = value;
}
}
const warnedCaches = /* @__PURE__ */ new WeakSet();
function warnAboutMissingNode(cache, internals) {
if (warnedCaches.has(cache)) {
return;
}
warnedCaches.add(cache);
console.warn(
internals.hasMeasurableElement ? "CellMeasurer could not find a DOM element to measure. Its child should be a DOM element (e.g. <div>) or a component that passes its ref along to one (in React 18, function components must use forwardRef). Otherwise, use a function child and pass registerChild as the ref of the element to be measured." : "CellMeasurer could not find a DOM element to measure. Its child should be a single DOM element (e.g. <div>), not text, an array or a fragment (or, in React 18, a function component that doesn't use forwardRef). Otherwise, use a function child and pass registerChild as the ref of the element to be measured."
);
}
const DEFAULT_HEIGHT = 30;
const DEFAULT_WIDTH = 100;
class CellMeasurerCache {
_cellHeightCache = {};
_cellWidthCache = {};
_columnWidthCache = {};
_rowHeightCache = {};
// The number of rows (or columns) that each derived column width (or row height) was computed over,
// so that it can be updated incrementally when a cell is measured (#1747)
_columnWidthRowCount = {};
_rowHeightColumnCount = {};
_defaultHeight;
_defaultWidth;
_minHeight;
_minWidth;
_keyMapper;
_hasFixedHeight;
_hasFixedWidth;
_columnCount = 0;
_rowCount = 0;
constructor(params = {}) {
const {
defaultHeight,
defaultWidth,
fixedHeight,
fixedWidth,
keyMapper,
minHeight,
minWidth
} = params;
this._hasFixedHeight = fixedHeight === true;
this._hasFixedWidth = fixedWidth === true;
this._minHeight = minHeight || 0;
this._minWidth = minWidth || 0;
this._keyMapper = keyMapper || defaultKeyMapper;
this._defaultHeight = Math.max(
this._minHeight,
typeof defaultHeight === "number" ? defaultHeight : DEFAULT_HEIGHT
);
this._defaultWidth = Math.max(
this._minWidth,
typeof defaultWidth === "number" ? defaultWidth : DEFAULT_WIDTH
);
if (process.env.NODE_ENV !== "production") {
if (this._hasFixedHeight === false && this._hasFixedWidth === false) {
console.warn(
"CellMeasurerCache should only measure a cell's width or height. You have configured CellMeasurerCache to measure both. This will result in poor performance."
);
}
if (this._hasFixedHeight === false && this._defaultHeight === 0) {
console.warn(
"Fixed height CellMeasurerCache should specify a :defaultHeight greater than 0. Failing to do so will lead to unnecessary layout and poor performance."
);
}
if (this._hasFixedWidth === false && this._defaultWidth === 0) {
console.warn(
"Fixed width CellMeasurerCache should specify a :defaultWidth greater than 0. Failing to do so will lead to unnecessary layout and poor performance."
);
}
}
}
/**
* Reset cached measurements for a specific cell.
*
* This should be called when a cell needs to be re-measured to handle dynamic content
* (eg. replacing a loading indicator with loaded content or reacting to state-changes for stateful cells).
*/
clear(rowIndex, columnIndex = 0) {
const key = this._keyMapper(rowIndex, columnIndex);
delete this._cellHeightCache[key];
delete this._cellWidthCache[key];
this._updateCachedColumnAndRowSizes(rowIndex, columnIndex);
}
/**
* Reset cached measurements for all cells.
*
* This method should be called when a `Grid`, `List` or `Table` needs to reflow content due to a resizing event
* for a responsive layout (eg. a window width resize may have an impact on the height of cells).
*/
clearAll() {
this._cellHeightCache = {};
this._cellWidthCache = {};
this._columnWidthCache = {};
this._rowHeightCache = {};
this._columnWidthRowCount = {};
this._rowHeightColumnCount = {};
this._rowCount = 0;
this._columnCount = 0;
}
/**
* Returns the derived width of a column (the widest measured cell in that column) or the default width.
* Compatible with the `columnWidth` prop of `Grid`.
*/
columnWidth = ({ index }) => {
const key = this._keyMapper(0, index);
return this._columnWidthCache[key] !== void 0 ? this._columnWidthCache[key] : this._defaultWidth;
};
/** Height reported for unmeasured cells. */
get defaultHeight() {
return this._defaultHeight;
}
/** Width reported for unmeasured cells. */
get defaultWidth() {
return this._defaultWidth;
}
/** Returns true if cells have a fixed height (and a dynamic, measured width). */
hasFixedHeight() {
return this._hasFixedHeight;
}
/** Returns true if cells have a fixed width (and a dynamic, measured height). */
hasFixedWidth() {
return this._hasFixedWidth;
}
/** Returns the (measured or default) height of the specified cell. */
getHeight(rowIndex, columnIndex = 0) {
if (this._hasFixedHeight) {
return this._defaultHeight;
} else {
const key = this._keyMapper(rowIndex, columnIndex);
return this._cellHeightCache[key] !== void 0 ? Math.max(this._minHeight, this._cellHeightCache[key]) : this._defaultHeight;
}
}
/** Returns the (measured or default) width of the specified cell. */
getWidth(rowIndex, columnIndex = 0) {
if (this._hasFixedWidth) {
return this._defaultWidth;
} else {
const key = this._keyMapper(rowIndex, columnIndex);
return this._cellWidthCache[key] !== void 0 ? Math.max(this._minWidth, this._cellWidthCache[key]) : this._defaultWidth;
}
}
/** Returns true if the specified cell has already been measured. */
has(rowIndex, columnIndex = 0) {
const key = this._keyMapper(rowIndex, columnIndex);
return this._cellHeightCache[key] !== void 0;
}
/**
* Returns the derived height of a row (the tallest measured cell in that row) or the default height.
* Compatible with the `rowHeight` prop of `Grid`.
*/
rowHeight = ({ index }) => {
const key = this._keyMapper(index, 0);
return this._rowHeightCache[key] !== void 0 ? this._rowHeightCache[key] : this._defaultHeight;
};
/** Stores the measured size of the specified cell. */
set(rowIndex, columnIndex, width, height) {
const key = this._keyMapper(rowIndex, columnIndex);
const previousCachedWidth = this._cellWidthCache[key];
const previousCachedHeight = this._cellHeightCache[key];
if (columnIndex >= this._columnCount) {
this._columnCount = columnIndex + 1;
}
if (rowIndex >= this._rowCount) {
this._rowCount = rowIndex + 1;
}
this._cellHeightCache[key] = height;
this._cellWidthCache[key] = width;
this._updateCachedColumnAndRowSizes(rowIndex, columnIndex, {
height: this._canUpdateIncrementally(
this._rowHeightCache[this._keyMapper(rowIndex, 0)],
this._rowHeightColumnCount[this._keyMapper(rowIndex, 0)],
columnIndex,
this.getHeight(rowIndex, columnIndex),
previousCachedHeight === void 0 ? void 0 : Math.max(this._minHeight, previousCachedHeight)
),
width: this._canUpdateIncrementally(
this._columnWidthCache[this._keyMapper(0, columnIndex)],
this._columnWidthRowCount[this._keyMapper(0, columnIndex)],
rowIndex,
this.getWidth(rowIndex, columnIndex),
previousCachedWidth === void 0 ? void 0 : Math.max(this._minWidth, previousCachedWidth)
)
});
}
/**
* Whether a derived column width (or row height) can be updated incrementally after a cell is measured:
* i.e. whether the previous derived size is still a lower bound of the new one.
* The maximum can only decrease if the cell's previous size was the maximum and it got smaller.
*
* @param derivedSize The current derived size (the maximum of the measured cells counted so far, if any)
* @param countedCells The number of cells (rows of a column, or columns of a row) that the derived size was computed over
* @param cellIndex The index of the measured cell within the column (or row)
* @param size The cell's new (effective) size
* @param previousSize The cell's previous (effective) size, or undefined if it wasn't measured (so it wasn't part of the maximum)
*/
_canUpdateIncrementally(derivedSize, countedCells, cellIndex, size, previousSize) {
if (countedCells === void 0) {
return false;
}
if (this._keyMapper === defaultKeyMapper && cellIndex >= countedCells) {
return true;
}
return previousSize === void 0 || size >= previousSize || derivedSize !== void 0 && previousSize < derivedSize;
}
_updateCachedColumnAndRowSizes(rowIndex, columnIndex, incremental = {
height: false,
width: false
}) {
if (!this._hasFixedWidth) {
const columnKey = this._keyMapper(0, columnIndex);
const cachedWidth = this._columnWidthCache[columnKey];
const countedRows = this._columnWidthRowCount[columnKey];
let columnWidth;
let firstRow;
if (incremental.width && countedRows !== void 0) {
columnWidth = Math.max(
cachedWidth ?? 0,
this.getWidth(rowIndex, columnIndex)
);
firstRow = countedRows;
} else {
columnWidth = void 0;
firstRow = 0;
}
for (let i = firstRow; i < this._rowCount; i++) {
if (this.has(i, columnIndex)) {
columnWidth = Math.max(
columnWidth ?? 0,
this.getWidth(i, columnIndex)
);
}
}
if (columnWidth === void 0) {
delete this._columnWidthCache[columnKey];
} else {
this._columnWidthCache[columnKey] = columnWidth;
}
this._columnWidthRowCount[columnKey] = this._rowCount;
}
if (!this._hasFixedHeight) {
const rowKey = this._keyMapper(rowIndex, 0);
const cachedHeight = this._rowHeightCache[rowKey];
const countedColumns = this._rowHeightColumnCount[rowKey];
let rowHeight;
let firstColumn;
if (incremental.height && countedColumns !== void 0) {
rowHeight = Math.max(
cachedHeight ?? 0,
this.getHeight(rowIndex, columnIndex)
);
firstColumn = countedColumns;
} else {
rowHeight = void 0;
firstColumn = 0;
}
for (let i = firstColumn; i < this._columnCount; i++) {
if (this.has(rowIndex, i)) {
rowHeight = Math.max(rowHeight ?? 0, this.getHeight(rowIndex, i));
}
}
if (rowHeight === void 0) {
delete this._rowHeightCache[rowKey];
} else {
this._rowHeightCache[rowKey] = rowHeight;
}
this._rowHeightColumnCount[rowKey] = this._columnCount;
}
}
}
function defaultKeyMapper(rowIndex, columnIndex) {
return `${rowIndex}-${columnIndex}`;
}
const ColumnSizer = /* @__PURE__ */ react.memo(function ColumnSizer2({
children,
columnMaxWidth,
columnMinWidth,
columnCount,
width
}) {
const registeredChildRef = react.useRef(null);
const registerChild = react.useCallback(
(child) => {
if (child && typeof child.recomputeGridSize !== "function") {
throw Error(
"Unexpected child type registered; only Grid/MultiGrid children are supported."
);
}
registeredChildRef.current = child;
if (child) {
child.recomputeGridSize();
}
},
[]
);
const committedInputsRef = react.useRef(null);
useIsomorphicLayoutEffect(() => {
const prev = committedInputsRef.current;
committedInputsRef.current = {
columnCount,
columnMaxWidth,
columnMinWidth,
width
};
if (prev !== null && (columnMaxWidth !== prev.columnMaxWidth || columnMinWidth !== prev.columnMinWidth || columnCount !== prev.columnCount || width !== prev.width)) {
registeredChildRef.current?.recomputeGridSize();
}
}, [columnCount, columnMaxWidth, columnMinWidth, width]);
const safeColumnMinWidth = columnMinWidth || 1;
const safeColumnMaxWidth = columnMaxWidth ? Math.min(columnMaxWidth, width) : width;
let columnWidth = width / columnCount;
columnWidth = Math.max(safeColumnMinWidth, columnWidth);
columnWidth = Math.min(safeColumnMaxWidth, columnWidth);
columnWidth = Math.floor(columnWidth);
const adjustedWidth = Math.min(width, columnWidth * columnCount);
return children({
adjustedWidth,
columnWidth,
getColumnWidth: () => columnWidth,
registerChild
});
});
const SCROLL_DIRECTION_FORWARD$1 = 1;
function accessibilityOverscanIndicesGetter({
cellCount,
overscanCellsCount,
scrollDirection,
startIndex,
stopIndex
}) {
overscanCellsCount = Math.max(1, overscanCellsCount);
if (scrollDirection === SCROLL_DIRECTION_FORWARD$1) {
return {
overscanStartIndex: Math.max(0, startIndex - 1),
overscanStopIndex: Math.min(cellCount - 1, stopIndex + overscanCellsCount)
};
} else {
return {
overscanStartIndex: Math.max(0, startIndex - overscanCellsCount),
overscanStopIndex: Math.min(cellCount - 1, stopIndex + 1)
};
}
}
function defaultCellRangeRenderer({
cellCache,
cellRenderer,
columnSizeAndPositionManager,
columnStartIndex,
columnStopIndex,
deferredMeasurementCache,
horizontalOffsetAdjustment,
isScrolling,
isScrollingOptOut,
parent,
// Grid (or List or Table)
rowSizeAndPositionManager,
rowStartIndex,
rowStopIndex,
styleCache,
verticalOffsetAdjustment,
visibleColumnIndices,
visibleRowIndices
}) {
const renderedCells = [];
const areOffsetsAdjusted = columnSizeAndPositionManager.areOffsetsAdjusted() || rowSizeAndPositionManager.areOffsetsAdjusted();
const canCacheStyle = !isScrolling && !areOffsetsAdjusted;
for (let rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {
const rowDatum = rowSizeAndPositionManager.getSizeAndPositionOfCell(rowIndex);
for (let columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) {
const columnDatum = columnSizeAndPositionManager.getSizeAndPositionOfCell(columnIndex);
const isVisible = columnIndex >= visibleColumnIndices.start && columnIndex <= visibleColumnIndices.stop && rowIndex >= visibleRowIndices.start && rowIndex <= visibleRowIndices.stop;
const key = `${rowIndex}-${columnIndex}`;
let style;
if (canCacheStyle && styleCache[key]) {
style = styleCache[key];
} else {
if (deferredMeasurementCache && !deferredMeasurementCache.has(rowIndex, columnIndex)) {
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;
}
}
const cellRendererParams = {
columnIndex,
isScrolling,
isVisible,
key,
parent,
rowIndex,
style
};
let renderedCell;
if ((isScrollingOptOut || isScrolling) && !horizontalOffsetAdjustment && !verticalOffsetAdjustment) {
if (!cellCache[key]) {
cellCache[key] = cellRenderer(cellRendererParams);
}
renderedCell = cellCache[key];
} else {
renderedCell = cellRenderer(cellRendererParams);
}
if (renderedCell == null || renderedCell === false) {
continue;
}
const cellElement = renderedCell;
if (process.env.NODE_ENV !== "production") {
warnAboutMissingStyle(parent, cellElement);
}
if (!cellElement.props.role) {
renderedCell = react.cloneElement(cellElement, { role: "gridcell" });
}
renderedCells.push(renderedCell);
}
}
return renderedCells;
}
function warnAboutMissingStyle(parent, renderedCell) {
if (process.env.NODE_ENV !== "production") {
if (renderedCell) {
if (renderedCell.type && renderedCell.type.__internalCellMeasurerFlag) {
renderedCell = renderedCell.props.children;
}
if (renderedCell && renderedCell.props && renderedCell.props.style === void 0 && parent.__warnedAboutMissingStyle !== true) {
parent.__warnedAboutMissingStyle = true;
console.warn(
"Rendered cell should include style property for positioning."
);
}
}
}
}
const DEFAULT_SCROLLING_RESET_TIME_INTERVAL$1 = 150;
const SCROLL_DIRECTION_BACKWARD = -1;
const SCROLL_DIRECTION_FORWARD = 1;
function defaultOverscanIndicesGetter({
cellCount,
overscanCellsCount,
scrollDirection,
startIndex,
stopIndex
}) {
if (scrollDirection === SCROLL_DIRECTION_FORWARD) {
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)
};
}
}
const noop$2 = () => {
};
const defaultGridProps = /* @__PURE__ */ Object.freeze({
"aria-label": "grid",
"aria-readonly": true,
autoContainerWidth: false,
cellRangeRenderer: defaultCellRangeRenderer,
containerRole: "row",
containerStyle: /* @__PURE__ */ Object.freeze({}),
estimatedColumnSize: 100,
estimatedRowSize: 30,
getScrollbarSize: scrollbarSize,
isScrollingOptOut: false,
noContentRenderer: () => null,
onScroll: noop$2,
onScrollbarPresenceChange: noop$2,
onSectionRendered: noop$2,
overscanColumnCount: 0,
overscanIndicesGetter: defaultOverscanIndicesGetter,
overscanRowCount: 10,
role: "grid",
scrollingResetTimeInterval: DEFAULT_SCROLLING_RESET_TIME_INTERVAL$1,
style: /* @__PURE__ */ Object.freeze({}),
tabIndex: 0
});
function createCallbackMemoizer(requireAllKeys = true) {
let cachedIndices = {};
return ({
callback,
indices
}) => {
const indicesMap = indices;
const keys = Object.keys(indices);
const allInitialized = !requireAllKeys || keys.every((key) => {
const value = indicesMap[key];
return Array.isArray(value) ? value.length > 0 : value >= 0;
});
const indexChanged = keys.length !== Object.keys(cachedIndices).length || keys.some((key) => {
const cachedValue = cachedIndices[key];
const value = indicesMap[key];
return Array.isArray(value) ? cachedValue.join(",") !== value.join(",") : cachedValue !== value;
});
cachedIndices = indicesMap;
if (allInitialized && indexChanged) {
callback(indices);
}
};
}
function getUpdatedOffsetForIndex({
align = "auto",
cellOffset,
cellSize,
containerSize,
currentOffset
}) {
const maxOffset = cellOffset;
const minOffset = maxOffset - containerSize + cellSize;
switch (align) {
case "start":
return maxOffset;
case "end":
return minOffset;
case "center":
return maxOffset - (containerSize - cellSize) / 2;
default:
if (cellSize >= containerSize) {
return maxOffset;
}
return Math.max(minOffset, Math.min(maxOffset, currentOffset));
}
}
let win;
if (typeof window !== "undefined") {
win = window;
} else if (typeof self !== "undefined") {
win = self;
} else {
win = {};
}
const request = win.requestAnimationFrame || win.webkitRequestAnimationFrame || win.mozRequestAnimationFrame || win.oRequestAnimationFrame || win.msRequestAnimationFrame || function(callback) {
return win.setTimeout(callback, 1e3 / 60);
};
const cancel = win.cancelAnimationFrame || win.webkitCancelAnimationFrame || win.mozCancelAnimationFrame || win.oCancelAnimationFrame || win.msCancelAnimationFrame || function(id) {
win.clearTimeout(id);
};
const raf = request;
const caf = cancel;
const cancelAnimationTimeout = (frame) => caf(frame.id);
const requestAnimationTimeout = (callback, delay) => {
let start;
Promise.resolve().then(() => {
start = Date.now();
});
const timeout = () => {
if (Date.now() - start >= delay) {
callback.call(void 0);
} else {
frame.id = raf(timeout);
}
};
const frame = {
id: raf(timeout)
};
return frame;
};
function useMissingHeightWarning(componentName, height, scrollElement) {
const heightMissing = height === void 0 && scrollElement === void 0;
react.useEffect(() => {
if (process.env.NODE_ENV !== "production" && heightMissing) {
console.warn(
`${componentName} requires a height prop (unless a scrollElement is specified)`
);
}
}, [componentName, heightMissing]);
}
const isWindow = (element) => element === window;
const getBoundingBox = (element) => element.getBoundingClientRect();
function getDimensions(scrollElement) {
if (isWindow(scrollElement)) {
const { innerHeight, innerWidth } = window;
return {
height: typeof innerHeight === "number" ? innerHeight : 0,
width: typeof innerWidth === "number" ? innerWidth : 0
};
} else {
const { height, width } = getBoundingBox(scrollElement);
return { height, width };
}
}
function getPositionOffset(element, container) {
if (isWindow(container) && document.documentElement) {
const containerElement = document.documentElement;
const elementRect = getBoundingBox(element);
const containerRect = getBoundingBox(containerElement);
return {
top: elementRect.top - containerRect.top,
left: elementRect.left - containerRect.left
};
} else {
const scrollOffset = getScrollOffset(container);
const elementRect = getBoundingBox(element);
const containerRect = getBoundingBox(container);
return {
top: elementRect.top + scrollOffset.top - containerRect.top,
left: elementRect.left + scrollOffset.left - containerRect.left
};
}
}
function getScrollOffset(element) {
if (isWindow(element) && document.documentElement) {
return {
top: "scrollY" in window ? window.scrollY : document.documentElement.scrollTop,
left: "scrollX" in window ? window.scrollX : document.documentElement.scrollLeft
};
} else {
return {
top: element.scrollTop,
left: element.scrollLeft
};
}
}
let registrations = [];
let originalBodyPointerEvents = null;
let disablePointerEventsTimeoutId = null;
function enablePointerEventsIfDisabled() {
if (disablePointerEventsTimeoutId) {
disablePointerEventsTimeoutId = null;
if (document.body && originalBodyPointerEvents != null) {
document.body.style.pointerEvents = originalBodyPointerEvents;
}
originalBodyPointerEvents = null;
}
}
function enablePointerEventsAfterDelayCallback() {
enablePointerEventsIfDisabled();
registrations.forEach(({ listener }) => listener.resetIsScrolling());
}
function enablePointerEventsAfterDelay() {
if (disablePointerEventsTimeoutId) {
cancelAnimationTimeout(disablePointerEventsTimeoutId);
}
let maximumTimeout = 0;
registrations.forEach(({ listener }) => {
maximumTimeout = Math.max(
maximumTimeout,
listener.getScrollingResetTimeInterval()
);
});
disablePointerEventsTimeoutId = requestAnimationTimeout(
enablePointerEventsAfterDelayCallback,
maximumTimeout
);
}
function onScroll(event) {
if (event.currentTarget === window && originalBodyPointerEvents == null && document.body) {
originalBodyPointerEvents = document.body.style.pointerEvents;
document.body.style.pointerEvents = "none";
}
enablePointerEventsAfterDelay();
registrations.forEach(({ listener, element }) => {
if (element === event.currentTarget) {
listener.handleScrollEvent();
}
});
}
function registerScrollListener(listener, element) {
if (registrations.some(
(registration) => registration.listener === listener && registration.element === element
)) {
return;
}
if (!registrations.some((registration) => registration.element === element)) {
element.addEventListener("scroll", onScroll);
}
registrations.push({ listener, element });
}
function unregisterScrollListener(listener, element) {
registrations = registrations.filter(
(registration) => registration.listener !== listener || registration.element !== element
);
if (!registrations.some((registration) => registration.element === element)) {
element.removeEventListener("scroll", onScroll);
}
if (!registrations.length) {
if (disablePointerEventsTimeoutId) {
cancelAnimationTimeout(disablePointerEventsTimeoutId);
enablePointerEventsIfDisabled();
}
}
}
function resolveScrollElement(scrollElement) {
if (scrollElement === "window") {
return typeof window !== "undefined" ? window : null;
}
return scrollElement ?? null;
}
function measureViewport(element, target, isScrolling) {
const targetElement = target.getElement();
const positionFromTop = targetElement ? getPositionOffset(targetElement, element).top : 0;
return {
height: getDimensions(element).height,
isScrolling,
scrollTop: getScrollOffset(element).top - positionFromTop
};
}
function createInstance(target, scrollingResetTimeInterval) {
const instance = {
element: null,
scrollingResetTimeInterval,
target,
viewport: { height: 0, isScrolling: false, scrollTop: 0 },
source: {
scrollTo(scrollTop) {
const { element } = instance;
if (element === null) {
return false;
}
const targetElement = instance.target.getElement();
const positionFromTop = targetElement ? getPositionOffset(targetElement, element).top : 0;
const scrollOffset = getScrollOffset(element);
const top = scrollTop + positionFromTop;
if (Math.abs(scrollOffset.top - top) < 1) {
return false;
}
if (typeof element.scrollTo === "function") {
element.scrollTo(scrollOffset.left, top);
} else {
element.scrollTop = top;
}
return true;
}
},
update(isScrolling) {
const { element } = instance;
if (element === null) {
return;
}
const viewport = measureViewport(element, instance.target, isScrolling);
const prevViewport = instance.viewport;
if (viewport.height !== prevViewport.height || viewport.isScrolling !== prevViewport.isScrolling || viewport.scrollTop !== prevViewport.scrollTop) {
instance.viewport = viewport;
instance.target.setViewport(viewport);
}
},
// ScrollElementListener (called by scrollListeners.ts)
getScrollingResetTimeInterval() {
return instance.scrollingResetTimeInterval;
},
handleScrollEvent() {
instance.update(true);
},
resetIsScrolling() {
instance.update(false);
}
};
return instance;
}
function observeResize(element, onResize) {
if (element === window) {
window.addEventListener("resize", onResize, false);
return () => window.removeEventListener("resize", onResize, false);
}
const ResizeObserverImpl = element.ownerDocument?.defaultView?.ResizeObserver ?? (typeof ResizeObserver !== "undefined" ? ResizeObserver : void 0);
if (!ResizeObserverImpl) {
return () => {
};
}
const resizeObserver = new ResizeObserverImpl(onResize);
resizeObserver.observe(element, { box: "border-box" });
return () => resizeObserver.disconnect();
}
function useScrollElementLink(scrollElement, target, scrollingResetTimeInterval) {
const [instance] = react.useState(
() => createInstance(target, scrollingResetTimeInterval)
);
react.useInsertionEffect(() => {
instance.scrollingResetTimeInterval = scrollingResetTimeInterval;
});
const element = resolveScrollElement(scrollElement);
useIsomorphicLayoutEffect(() => {
if (element === null) {
return;
}
instance.element = element;
instance.viewport = measureViewport(element, instance.target, false);
instance.target.link(instance.source, instance.viewport);
registerScrollListener(instance, element);
const stopObservingResize = observeResize(
element,
() => instance.update(instance.viewport.isScrolling)
);
return () => {
unregisterScrollListener(instance, element);
stopObservingResize();
instance.element = null;
instance.target.link(null, instance.viewport);
};
}, [element, instance]);
useIsomorphicLayoutEffect(() => {
instance.update(instance.viewport.isScrolling);
});
}
class CellSizeAndPositionManager {
// 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
_cellSizeAndPositionData = {};
// Measurements for cells up to this index can be trusted; cells afterward should be estimated.
_lastMeasuredIndex = -1;
// Used in deferred mode to track which cells have been queued for measurement.
_lastBatchedIndex = -1;
_cellCount;
_cellSizeGetter;
_estimatedCellSize;
constructor({
cellCount,
cellSizeGetter,
estimatedCellSize
}) {
this._cellSizeGetter = cellSizeGetter;
this._cellCount = cellCount;
this._estimatedCellSize = estimatedCellSize;
}
areOffsetsAdjusted() {
return false;
}
configure({ cellCount, estimatedCellSize, cellSizeGetter }) {
this._cellCount = cellCount;
this._lastMeasuredIndex = Math.min(this._lastMeasuredIndex, cellCount - 1);
this._estimatedCellSize = estimatedCellSize;
this._cellSizeGetter = cellSizeGetter;
}
getCellCount() {
return this._cellCount;
}
getEstimatedCellSize() {
return this._estimatedCellSize;
}
getLastMeasuredIndex() {
return this._lastMeasuredIndex;
}
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.
*/
getSizeAndPositionOfCell(index) {
if (index < 0 || index >= this._cellCount) {
throw Error(
`Requested index ${index} is outside of range 0..${this._cellCount}`
);
}
if (index > this._lastMeasuredIndex) {
const lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
let offset = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size;
for (let i = this._lastMeasuredIndex + 1; i <= index; i++) {
const size = this._cellSizeGetter({ index: i });
if (size === void 0 || isNaN(size)) {
throw Error(`Invalid size returned for cell ${i} of value ${size}`);
} else if (size === null) {
this._cellSizeAndPositionData[i] = {
offset,
size: 0
};
this._lastBatchedIndex = index;
} else {
this._cellSizeAndPositionData[i] = {
offset,
size
};
offset += size;
this._lastMeasuredIndex = i;
}
}
}
return this._cellSizeAndPositionData[index];
}
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.
*/
getTotalSize() {
const lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
const totalSizeOfMeasuredCells = lastMeasuredCellSizeAndPosition.offset + lastMeasuredCellSizeAndPosition.size;
const numUnmeasuredCells = this._cellCount - this._lastMeasuredIndex - 1;
const 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
*/
getUpdatedOffsetForIndex({
align = "auto",
containerSize,
currentOffset,
targetIndex
}) {
if (containerSize <= 0) {
return 0;
}
const datum = this.getSizeAndPositionOfCell(targetIndex);
const maxOffset = datum.offset;
const minOffset = maxOffset - containerSize + datum.size;
let idealOffset;
switch (align) {
case "start":
idealOffset = maxOffset;
break;
case "end":
idealOffset = minOffset;
break;
case "center":
idealOffset = maxOffset - (containerSize - datum.size) / 2;
break;
default:
idealOffset = datum.size >= containerSize ? maxOffset : Math.max(minOffset, Math.min(maxOffset, currentOffset));
break;
}
const totalSize = this.getTotalSize();
return Math.max(0, Math.min(totalSize - containerSize, idealOffset));
}
getVisibleCellRange(params) {
const { containerSize } = params;
let { offset } = params;
const totalSize = this.getTotalSize();
if (totalSize === 0) {
return {};
}
const maxOffset = offset + containerSize;
const start = this._findNearestCell(offset);
const datum = this.getSizeAndPositionOfCell(start);
offset = datum.offset + datum.size;
let stop = start;
while (offset < maxOffset && stop < this._cellCount - 1) {
stop++;
offset += this.getSizeAndPositionOfCell(stop).size;
}
return {
start,
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.
*/
resetCell(index) {
this._lastMeasuredIndex = Math.min(this._lastMeasuredIndex, index - 1);
}
_binarySearch(high, low, offset) {
while (low <= high) {
const middle = low + Math.floor((high - low) / 2);
const 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;
}
}
_exponentialSearch(index, offset) {
let 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.
*/
_findNearestCell(offset) {
if (isNaN(offset)) {
throw Error(`Invalid offset ${offset} specified`);
}
offset = Math.max(0, offset);
const lastMeasuredCellSizeAndPosition = this.getSizeAndPositionOfLastMeasuredCell();
const lastMeasuredIndex = Math.max(0, this._lastMeasuredIndex);
if (lastMeasuredCellSizeAndPosition.offset >= offset) {
return this._binarySearch(lastMeasuredIndex, 0, offset);
} else {
return this._exponentialSearch(lastMeasuredIndex, offset);
}
}
}
const MAX_ELEMENT_SIZE = 16777100;
const getMaxElementSize = () => MAX_ELEMENT_SIZE;
class ScalingCellSizeAndPositionManager {
_cellSizeAndPositionManager;
_maxScrollSize;
constructor({ maxScrollSize = getMaxElementSize(), ...params }) {
this._cellSizeAndPositionManager = new CellSizeAndPositionManager(params);
this._maxScrollSize = maxScrollSize;
}
areOffsetsAdjusted() {
return this._cellSizeAndPositionManager.getTotalSize() > this._maxScrollSize;
}
configure(params) {
this._cellSizeAndPositionManager.configure(params);
}
getCellCount() {
return this._cellSizeAndPositionManager.getCellCount();
}
getEstimatedCellSize() {
return this._cellSizeAndPositionManager.getEstimatedCellSize();
}
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.
*/
getOffsetAdjustment({
containerSize,
offset
// safe
}) {
const totalSize = this._cellSizeAndPositionManager.getTotalSize();
const safeTotalSize = this.getTotalSize();
const offsetPercentage = this._getOffsetPercentage({
containerSize,
offset,
totalSize: safeTotalSize
});
return Math.round(offsetPercentage * (safeTotalSize - totalSize));
}
getSizeAndPositionOfCell(index) {
return this._cellSizeAndPositionManager.getSizeAndPositionOfCell(index);
}
getSizeAndPositionOfLastMeasuredCell() {
return this._cellSizeAndPositionManager.getSizeAndPositionOfLastMeasuredCell();
}
/** See CellSizeAndPositionManager#getTotalSize */
getTotalSize() {
return Math.min(
this._maxScrollSize,
this._cellSizeAndPositionManager.getTotalSize()
);
}
/** See CellSizeAndPositionManager#getUpdatedOffsetForIndex */
getUpdatedOffsetForIndex({
align = "auto",
containerSize,
currentOffset,
// safe
targetIndex
}) {
currentOffset = this._safeOffsetToOffset({
containerSize,
offset: currentOffset
});
const offset = this._cellSizeAndPositionManager.getUpdatedOffsetForIndex({
align,
containerSize,
currentOffset,
targetIndex
});
return this._offsetToSafeOffset({
containerSize,
offset
});
}
/** See CellSizeAndPositionManager#getVisibleCellRange */
getVisibleCellRange({
containerSize,
offset
// safe
}) {
offset = this._safeOffsetToOffset({
containerSize,
offset
});
return this._cellSizeAndPositionManager.getVisibleCellRange({
containerSize,
offset
});
}
resetCell(index) {
this._cellSizeAndPositionManager.resetCell(index);
}
_getOffsetPercentage({
containerSize,
offset,
// safe
totalSize
}) {
return totalSize <= containerSize ? 0 : offset / (totalSize - containerSize);
}
_offsetToSafeOffset({
containerSize,
offset
// unsafe
}) {
const totalSize = this._cellSizeAndPositionManager.getTotalSize();
const safeTotalSize = this.getTotalSize();
if (totalSize === safeTotalSize) {
return offset;
} else {
const offsetPercentage = this._getOffsetPercentage({
containerSize,
offset,
totalSize
});
return Math.round(offsetPercentage * (safeTotalSize - containerSize));
}
}
_safeOffsetToOffset({
containerSize,
offset
// safe
}) {
const totalSize = this._cellSizeAndPositionManager.getTotalSize();
const safeTotalSize = this.getTotalSize();
if (totalSize === safeTotalSize) {
return offset;
} else {
const offsetPercentage = this._getOffsetPercentage({
containerSize,
offset,
totalSize: safeTotalSize
});
return Math.round(offsetPercentage * (totalSize - containerSize));
}
}
}
function updateScrollIndexHelper({
cellSizeAndPositionManager,
previousCellsCount,
previousSize,
scrollOffset,
size,
updateScrollIndexCallback
}) {
const cellCount = cellSizeAndPositionManager.getCellCount();
if (cellCount > 0 && (size < previousSize || cellCount < previousCellsCount)) {
if (scrollOffset > cellSizeAndPositionManager.getTotalSize() - size) {
updateScrollIndexCallback(cellCount - 1);
}
}
}
const SCROLL_POSITION_CHANGE_REASONS = {
OBSERVED: "observed",
REQUESTED: "requested"
};
const INITIAL_SCROLL_STATE = {
isScrolling: false,
scrollDirectionHorizontal: SCROLL_DIRECTION_FORWARD,
scrollDirectionVertical: SCROLL_DIRECTION_FORWARD,
scrollLeft: 0,
scrollTop: 0,
scrollPositionChangeReason: null
};
const increment$2 = (value) => value + 1;
const subscribeToNothing = () => () => {
};
const getServerScrollbarSize = () => void 0;
const getClientRendered = () => true;
const getServerRendered = () => false;
function wrapSizeGetter(value) {
return typeof value === "function" ? value : () => value;
}
function isNumericSizeChange$1(prevSize, nextSize) {
return (typeof prevSize === "number" || typeof nextSize === "number") && prevSize !== nextSize;
}
function createGridInstance(initialProps, setLinkState, forceUpdate) {
const {
columnCount,
columnWidth,
estimatedColumnSize,
estimatedRowSize,
rowCount,
rowHeight
} = initialProps;
const columnSizeGetter = wrapSizeGetter(columnWidth);
const rowSizeGetter = wrapSizeGetter(rowHeight);
const internals = {
cellCache: {},
cellCacheForceUpdateCount: 0,
cellCacheProps: null,
columnSizeAndPositionManager: new ScalingCellSizeAndPositionManager({
cellCount: columnCount,
cellSizeGetter: columnSizeGetter,
estimatedCellSize: typeof columnWidth === "number" ? columnWidth : estimatedColumnSize
}),
renderedRange: null,
rowSizeAndPositionManager: new ScalingCellSizeAndPositionManager({
cellCount: rowCount,
cellSizeGetter: rowSizeGetter,
estimatedCellSize: typeof rowHeight === "number" ? rowHeight : estimatedRowSize
}),
sizeInputs: {
columnCount,
columnSizeGetter,
columnWidth,
estimatedColumnSize,
estimatedRowSize,
rowCount,
rowHeight,
rowSizeGetter
},
styleCache: {},
committed: null,
deferredInvalidateColumnIndex: null,
deferredInvalidateRowIndex: null,
disablePointerEventsTimeoutId: null,
element: null,
latest: {
columnCount,
height: initialProps.height,
onScroll: initialProps.onScroll,
rowCount,
scrollbarSize: 0,
scrollbarSizeMeasured: false,
scrollingResetTimeInterval: initialProps.scrollingResetTimeInterval,
width: initialProps.width
},
link: null,
// Invokes onSectionRendered callback only when start/stop row or column indices change
onGridRenderedMemoizer: createCallbackMemoizer(),
onScrollMemoizer: createCallbackMemoizer(false),
scrollbarPresence: { horizontal: 0, vertical: 0 },
scrollState: INITIAL_SCROLL_STATE,
scrollStateDispatch: null,
scrollOffsetsPendingHydration: false
};
const { initialScrollLeft = 0, initialScrollTop = 0 } = initialProps;
internals.scrollState = {
...INITIAL_SCROLL_STATE,
scrollLeft: Math.max(
0,
Math.min(
initialScrollLeft,
internals.columnSizeAndPositionManager.getTotalSize() - initialProps.width
)
),
scrollTop: Math.max(
0,
Math.min(
initialScrollTop,
internals.rowSizeAndPositionManager.getTotalSize() - initialProps.height
)
)
};
const setScrollState = (update) => {
const prevState = internals.scrollState;
let changed = false;
for (const key in update) {
if (update[key] !== prevState[key]) {
changed = true;
break;
}
}
if (changed) {
const nextState = { ...prevState, ...update };
internals.scrollState = nextState;
internals.scrollStateDispatch?.(nextState);
}
};
const getCalculatedScrollLeft = (alignment, scrollToColumn, currentScrollLeft) => {
const { columnCount: columnCount2, height, scrollbarSize: scrollbarSize2, scrollbarSizeMeasured, width } = internals.latest;
if (columnCount2 > 0) {
const finalColumn = columnCount2 - 1;
const targetIndex = scrollToColumn < 0 ? finalColumn : Math.min(finalColumn, scrollToColumn);
const totalRowsHeight = internals.rowSizeAndPositionManager.getTotalSize();
const scrollBarSize = scrollbarSizeMeasured && totalRowsHeight > height ? scrollbarSize2 : 0;
return internals.columnSizeAndPositionManager.getUpdatedOffsetForIndex({
align: alignment,
containerSize: width - scrollBarSize,
currentOffset: currentScrollLeft,
targetIndex
});
}
return 0;
};
const getCalculatedScrollTop = (alignment, scrollToRow, currentScrollTop) => {
const { height, rowCount: rowCount2, scrollbarSize: scrollbarSize2, scrollbarSizeMeasured, width } = internals.latest;
if (rowCount2 > 0) {
const finalRow = rowCount2 - 1;
const targetIndex = scrollToRow < 0 ? finalRow : Math.min(finalRow, scrollToRow);
const totalColumnsWidth = internals.columnSizeAndPositionManager.getTotalSize();
const scrollBarSize = scrollbarSizeMeasured && totalColumnsWidth > width ? scrollbarSize2 : 0;
const containerSize = height - scrollBarSize;
const rowSizeAndPositionManager = internals.rowSizeAndPositionManager;
if (internals.link !== null && containerSize > 0 && !rowSizeAndPositionManager.areOffsetsAdjusted()) {
const { offset, size } = rowSizeAndPositionManager.getSizeAndPositionOfCell(targetIndex);
if (alignment === "auto" && offset >= currentScrollTop && offset + size <= currentScrollTop + containerSize) {
return currentScrollTop;
}
return getUpdatedOffsetForIndex({
align: alignment,
cellOffset: offset,
cellSize: size,
containerSize,
currentOffset: currentScrollTop
});
}
return rowSizeAndPositionManager.getUpdatedOffsetForIndex({
align: alignment,
containerSize,
currentOffset: currentScrollTop,
targetIndex
});
}
return 0;
};
const getCurrentScrollTop = () => internals.link !== null ? internals.link.viewport.scrollTop : internals.scrollState.scrollTop;
const scrollLinkTo = (link, scrollTop) => {
link.source.scrollTo(scrollTop);
};
const updateScrollLeftForColumn = (alignment, columnIndex) => {
const { scrollLeft } = internals.scrollState;
const calculatedScrollLeft = getCalculatedScrollLeft(
alignment,
columnIndex,
scrollLeft
);
if (calculatedScrollLeft >= 0 && calculatedScrollLeft !== scrollLeft) {
setScrollState({
scrollDirectionHorizontal: calculatedScrollLeft > scrollLeft ? SCROLL_DIRECTION_FORWARD : SCROLL_DIRECTION_BACKWARD,
scrollLeft: calculatedScrollLeft,
scrollPositionChangeReason: SCROLL_POSITION_CHANGE_REASONS.REQUESTED
});
}
};
const updateScrollTopForRow = (alignment, rowIndex) => {
const scrollTop = getCurrentScrollTop();
const calculatedScrollTop = getCalculatedScrollTop(
alignment,
rowIndex,
scrollTop
);
const link = internals.link;
if (link !== null) {
if (calculatedScrollTop !== scrollTop) {
scrollLinkTo(link, calculatedScrollTop);
}
return;
}
if (calculatedScrollTop >= 0 && calculatedScrollTop !== scrollTop) {
setScrollState({
scrollDirectionVertical: calculatedScrollTop > scrollTop ? SCROLL_DIRECTION_FORWARD : SCROLL_DIRECTION_BACKWARD,
scrollPositionChangeReason: SCROLL_POSITION_CHANGE_REASONS.REQUESTED,
scrollTop: calculatedScrollTop
});
}
};
const invokeOnScrollMemoizer = (scrollLeft, scrollTop, totalColumnsWidth, totalRowsHeight) => {
internals.onScrollMemoizer({
callback: ({ scrollLeft: scrollLeft2, scrollTop: scrollTop2 }) => {
const { height, onScroll: onScroll22, width } = internals.latest;
onScroll22({
clientHeight: height,
clientWidth: width,
scrollHeight: totalRowsHeight,
scrollLeft: scrollLeft2,
scrollTop: scrollTop2,
scrollWidth: totalColumnsWidth
});
},
indices: {
scrollLeft,
scrollTop
}
});
};
const debounceScrollEndedCallback = () => {
internals.disablePointerEventsTimeoutId = null;
setScrollState({ isScrolling: false });
};
const debounceScrollEnded = () => {
if (internals.disablePointerEventsTimeoutId) {
cancelAnimationTimeout(internals.disablePointerEventsTimeoutId);
}
internals.disablePointerEventsTimeoutId = requestAnimationTimeout(
debounceScrollEndedCallback,
internals.latest.scrollingResetTimeInterval
);
};
const handle = {
forceUpdate() {
forceUpdate();
},
getOffsetForCell({
alignment = "auto",
columnIndex = -1,
rowIndex = -1
} = {}) {
const { scrollLeft } = internals.scrollState;
return {
scrollLeft: getCalculatedScrollLeft(alignment, columnIndex, scrollLeft),
scrollTop: getCalculatedScrollTop(
alignment,
rowIndex,
getCurrentScrollTop()
)
};
},
getTotalRowsHeight() {
return internals.rowSizeAndPositionManager.getTotalSize();
},
getTotalColumnsWidth() {
return internals.columnSizeAndPositionManager.getTotalSize();
},
handleScrollEvent({
scrollLeft: scrollLeftParam = 0,
scrollTop: scrollTopParam = 0
}) {
if (scrollTopParam < 0) {
return;
}
debounceScrollEnded();
const { height, scrollbarSize: scrollbarSize2, width } = internals.latest;
const link = internals.link;
const totalRowsHeight = internals.rowSizeAndPositionManager.getTotalSize();
const totalColumnsWidth = internals.columnSizeAndPositionManager.getTotalSize();
const scrollLeft = Math.min(
Math.max(0, totalColumnsWidth - width + scrollbarSize2),
scrollLeftParam
);
const scrollTop = Math.min(
Math.max(0, totalRowsHeight - height + scrollbarSize2),
scrollTopParam
);
const prevState = internals.scrollState;
if (prevState.scrollLeft !== scrollLeft || prevState.scrollTop !== scrollTop) {
const scrollDirectionHorizontal = scrollLeft !== prevState.scrollLeft ? scrollLeft > prevState.scrollLeft ? SCROLL_DIRECTION_FORWARD : SCROLL_DIRECTION_BACKWARD : prevState.scrollDirectionHorizontal;
const scrollDirectionVertical = scrollTop !== prevState.scrollTop ? scrollTop > prevState.scrollTop ? SCROLL_DIRECTION_FORWARD : SCROLL_DIRECTION_BACKWARD : prevState.scrollDirectionVertical;
const update = {
isScrolling: true,
scrollDirectionHorizontal,
scrollDirectionVertical,
scrollPositionChangeReason: SCROLL_POSITION_CHANGE_REASONS.OBSERVED
};
if (link === null) {
update.scrollTop = scrollTop;
}
update.scrollLeft = scrollLeft;
setScrollState(update);
}
invokeOnScrollMemoizer(
scrollLeft,
link !== null ? Math.max(0, link.viewport.scrollTop) : scrollTop,
totalColumnsWidth,
totalRowsHeight
);
},
invalidateCellSizeAfterRender({ columnIndex, rowIndex }) {
internals.deferredInvalidateColumnIndex = typeof internals.deferredInvalidateColumnIndex === "number" ? Math.min(internals.deferredInvalidateColumnIndex, columnIndex) : columnIndex;
internals.deferredInvalidateRowIndex = typeof internals.deferredInvalidateRowIndex === "number" ? Math.min(internals.deferredInvalidateRowIndex, rowIndex) : rowIndex;
},
measureAllCells() {
const { columnCount: columnCount2, rowCount: rowCount2 } = internals.latest;
if (columnCount2 > 0) {
internals.columnSizeAndPositionManager.getSizeAndPositionOfCell(
columnCount2 - 1
);
}
if (rowCount2 > 0) {
internals.rowSizeAndPositionManager.getSizeAndPositionOfCell(
rowCount2 - 1
);
}
},
recomputeGridSize({ columnIndex = 0, rowIndex = 0 } = {}) {
internals.columnSizeAndPositionManager.resetCell(columnIndex);
internals.rowSizeAndPositionManager.resetCell(rowIndex);
internals.styleCache = {};
internals.cellCache = {};
forceUpdate();
},
scrollToCell({ align = "auto", columnIndex, rowIndex }) {
const { columnCount: columnCount2, height, width } = internals.latest;
if (height <= 0 || width <= 0) {
return;
}
if (columnCount2 > 1 && columnIndex !== void 0 && columnIndex >= 0) {
updateScrollLeftForColumn(align, columnIndex);
}
if (rowIndex !== void 0 && rowIndex >= 0) {
updateScrollTopForRow(align, rowIndex);
}
},
scrollToPosition({ scrollLeft, scrollTop }) {
const { height, scrollbarSize: scrollbarSize2, width } = internals.latest;
const prevState = internals.scrollState;
const update = {};
const totalRowsHeight = internals.rowSizeAndPositionManager.getTotalSize();
const totalColumnsWidth = internals.columnSizeAndPositionManager.getTotalSize();
if (typeof scrollLeft === "number" && !isNaN(scrollLeft)) {
const clampedScrollLeft = Math.max(
0,
Math.min(scrollLeft, totalColumnsWidth - width + scrollbarSize2)
);
if (clampedScrollLeft !== prevState.scrollLeft) {
update.scrollDirectionHorizontal = clampedScrollLeft > prevState.scrollLeft ? SCROLL_DIRECTION_FORWARD : SCROLL_DIRECTION_BACKWARD;
update.scrollLeft = clampedScrollLeft;
}
}
const link = internals.link;
if (typeof scrollTop === "number" && !isNaN(scrollTop) && link !== null) {
const maxScrollTop = Math.max(0, totalRowsHeight - height);
const clampedScrollTop = Math.max(0, Math.min(scrollTop, maxScrollTop));
const currentScrollTop = Math.max(
0,
Math.min(link.viewport.scrollTop, maxScrollTop)
);
if (clampedScrollTop !== currentScrollTop) {
scrollLinkTo(link, clampedScrollTop);
}
} else if (typeof scrollTop === "number" && !isNaN(scrollTop)) {
const clampedScrollTop = Math.max(
0,
Math.min(scrollTop, totalRowsHeight - height + scrollbarSize2)
);
if (clampedScrollTop !== prevState.scrollTop) {
update.scrollDirectionVertical = clampedScrollTop > prevState.scrollTop ? SCROLL_DIRECTION_FORWARD : SCROLL_DIRECTION_BACKWARD;
update.scrollTop = clampedScrollTop;
}
}
if (update.scrollLeft !== void 0 || update.scrollTop !== void 0) {
update.scrollPositionChangeReason = SCROLL_POSITION_CHANGE_REASONS.REQUESTED;
setScrollState(update);
}
}
};
const linkTarget = {
getElement() {
return internals.element;
},
link(source, viewport) {
if (source === null) {
if (internals.link !== null) {
internals.link = null;
setLinkState(null);
}
return;
}
const direction = internals.link?.direction ?? SCROLL_DIRECTION_FORWARD;
internals.link = { direction, source, viewport };
setLinkState({ direction, viewport });
},
setViewport(viewport) {
const link = internals.link;
if (link === null) {
return;
}
const prevViewport = link.viewport;
if (prevViewport.height === viewport.height && prevViewport.isScrolling === viewport.isScrolling && prevViewport.scrollTop === viewport.scrollTop) {
return;
}
if (viewport.scrollTop !== prevViewport.scrollTop) {
link.direction = viewport.scrollTop > prevViewport.scrollTop ? SCROLL_DIRECTION_FORWARD : SCROLL_DIRECTION_BACKWARD;
}
link.viewport = viewport;
setLinkState({ direction: link.direction, viewport });
}
};
const onScroll2 = (event) => {
if (event.target === internals.element) {
handle.handleScrollEvent(event.target);
}
};
return {
handle,
internals,
linkTarget,
invokeOnScrollMemoizer,
onScroll: onScroll2,
setScrollState,
updateScrollLeftForColumn,
updateScrollTopForRow
};
}
function updateSizeInputs(internals, next) {
const prev = internals.sizeInputs;
if (next.columnWidth !== prev.columnWidth || next.rowHeight !== prev.rowHeight || next.columnCount !== prev.columnCount || next.rowCount !== prev.rowCount) {
internals.styleCache = {};
internals.cellCache = {};
}
internals.columnSizeAndPositionManager.configure({
cellCount: next.columnCount,
estimatedCellSize: typeof next.columnWidth === "number" ? next.columnWidth : next.estimatedColumnSize,
cellSizeGetter: next.columnSizeGetter
});
internals.rowSizeAndPositionManager.configure({
cellCount: next.rowCount,
estimatedCellSize: typeof next.rowHeight === "number" ? next.rowHeight : next.estimatedRowSize,
cellSizeGetter: next.rowSizeGetter
});
const eitherCountWasZero = prev.columnCount === 0 || prev.rowCount === 0;
if (eitherCountWasZero || prev.columnCount !== next.columnCount || isNumericSizeChange$1(prev.columnWidth, next.columnWidth)) {
internals.columnSizeAndPositionManager.resetCell(0);
}
if (eitherCountWasZero || prev.rowCount !== next.rowCount || isNumericSizeChange$1(prev.rowHeight, next.rowHeight)) {
internals.rowSizeAndPositionManager.resetCell(0);
}
internals.sizeInputs = next;
}
function areCellPropsEqual(prevProps, nextProps) {
if (prevProps === nextProps) {
return true;
}
const prev = prevProps;
const next = nextProps;
for (const key in prev) {
if (prev[key] !== next[key]) {
return false;
}
}
for (const key in next) {
if (!(key in prev)) {
return false;
}
}
return true;
}
function resetStyleCache(internals, keepCells) {
const { cellCache, renderedRange, styleCache } = internals;
const nextCellCache = {};
const nextStyleCache = {};
if (renderedRange !== null) {
for (let rowIndex = renderedRange.rowStartIndex; rowIndex <= renderedRange.rowStopIndex; rowIndex++) {
for (let columnIndex = renderedRange.columnStartIndex; columnIndex <= renderedRange.columnStopIndex; columnIndex++) {
const key = `${rowIndex}-${columnIndex}`;
const style = styleCache[key];
if (style !== void 0) {
nextStyleCache[key] = style;
}
if (keepCells) {
const cell = cellCache[key];
if (cell !== void 0) {
nextCellCache[key] = cell;
}
}
}
}
}
internals.cellCache = nextCellCache;
internals.styleCache = nextStyleCache;
}
const Grid = /* @__PURE__ */ react.memo(
/* @__PURE__ */ react.forwardRef(
function Grid2(props, ref) {
const {
"aria-label": ariaLabel = defaultGridProps["aria-label"],
"aria-readonly": ariaReadonly = defaultGridProps["aria-readonly"],
autoContainerWidth = defaultGridProps.autoContainerWidth,
cellRangeRenderer = defaultGridProps.cellRangeRenderer,
cellRenderer,
className,
columnCount,
columnWidth,
containerProps,
containerRole = defaultGridProps.containerRole,
containerStyle = defaultGridProps.containerStyle,
deferredMeasurementCache,
elementRef,
estimatedColumnSize = defaultGridProps.estimatedColumnSize,
estimatedRowSize = defaultGridProps.estimatedRowSize,
getScrollbarSize = defaultGridProps.getScrollbarSize,
height: heightProp,
id,
initialScrollLeft,
initialScrollTop,
isScrollingOptOut = defaultGridProps.isScrollingOptOut,
noContentRenderer = defaultGridProps.noContentRenderer,
onScroll: onScroll2 = defaultGridProps.onScroll,
onScrollbarPresenceChange = defaultGridProps.onScrollbarPresenceChange,
onSectionRendered = defaultGridProps.onSectionRendered,
overscanColumnCount = defaultGridProps.overscanColumnCount,
overscanIndicesGetter = defaultGridProps.overscanIndicesGetter,
overscanRowCount = defaultGridProps.overscanRowCount,
role = defaultGridProps.role,
rowCount,
rowHeight,
scrollElement,
scrollingResetTimeInterval = defaultGridProps.scrollingResetTimeInterval,
style = defaultGridProps.style,
tabIndex = defaultGridProps.tabIndex,
width
} = props;
const [linkState, setLinkState] = react.useState(null);
const [forceUpdateCount, forceUpdate] = react.useReducer(increment$2, 0);
const linked = scrollElement !== void 0;
const height = linkState !== null ? linkState.viewport.height : heightProp ?? 0;
useMissingHeightWarning("Grid", heightProp, scrollElement);
const [
{
handle,
internals,
invokeOnScrollMemoizer,
onScroll: onScrollEvent,
setScrollState,
updateScrollLeftForColumn,
updateScrollTopForRow,
linkTarget
}
] = react.useState(
() => createGridInstance(
{
columnCount,
columnWidth,
estimatedColumnSize,
estimatedRowSize,
height,
initialScrollLeft,
// The vertical offset of a Grid with a scrollElement is determined by the scroll element
initialScrollTop: linked ? void 0 : initialScrollTop,
onScroll: onScroll2,
rowCount,
rowHeight,
scrollingResetTimeInterval,
width
},
setLinkState,
forceUpdate
)
);
const [scrollState, setScrollStateDispatch] = react.useState(
() => internals.scrollState
);
react.useImperativeHandle(ref, () => handle, [handle]);
useScrollElementLink(
scrollElement,
linkTarget,
scrollingResetTimeInterval
);
const measuredScrollbarSize = react.useSyncExternalStore(
subscribeToNothing,
getScrollbarSize,
getServerScrollbarSize
);
const scrollbarSizeMeasured = measuredScrollbarSize !== void 0;
const scrollbarSize2 = measuredScrollbarSize ?? 0;
const latest = {
columnCount,
height,
onScroll: onScroll2,
rowCount,
scrollbarSize: scrollbarSize2,
scrollbarSizeMeasured,
scrollingResetTimeInterval,
width
};
react.useInsertionEffect(() => {
internals.latest = latest;
internals.scrollStateDispatch = setScrollStateDispatch;
});
const clientRendered = react.useSyncExternalStore(
subscribeToNothing,
getClientRendered,
getServerRendered
);
const [hydrationShift, setHydrationShift] = react.useState(
() => clientRendered || internals.scrollState.scrollLeft === 0 && internals.scrollState.scrollTop === 0 ? null : {
left: internals.scrollState.scrollLeft,
top: internals.scrollState.scrollTop
}
);
const setScrollingContainerRef = react.useCallback(
(element) => {
internals.element = element;
if (typeof elementRef === "function") {
elementRef(element);
} else if (elementRef) {
elementRef.current = element;
}
},
[elementRef, internals]
);
const sizeInputs = internals.sizeInputs;
if (columnCount !== sizeInputs.columnCount || columnWidth !== sizeInputs.columnWidth || estimatedColumnSize !== sizeInputs.estimatedColumnSize || rowCount !== sizeInputs.rowCount || rowHeight !== sizeInputs.rowHeight || estimatedRowSize !== sizeInputs.estimatedRowSize) {
updateSizeInputs(internals, {
columnCount,
columnSizeGetter: columnWidth === sizeInputs.columnWidth ? sizeInputs.columnSizeGetter : wrapSizeGetter(columnWidth),
columnWidth,
estimatedColumnSize,
estimatedRowSize,
rowCount,
rowHeight,
rowSizeGetter: rowHeight === sizeInputs.rowHeight ? sizeInputs.rowSizeGetter : wrapSizeGetter(rowHeight)
});
}
const { columnSizeAndPositionManager, rowSizeAndPositionManager } = internals;
const isScrolling = scrollState.isScrolling || linkState !== null && linkState.viewport.isScrolling;
const scrollLeft = scrollState.scrollLeft;
const scrollTop = linked ? Math.max(0, linkState?.viewport.scrollTop ?? 0) : scrollState.scrollTop;
const scrollDirectionHorizontal = scrollState.scrollDirectionHorizontal;
const scrollDirectionVertical = linkState !== null ? linkState.direction : scrollState.scrollDirectionVertical;
if (!isScrolling) {
const keepCells = isScrollingOptOut && internals.cellCacheForceUpdateCount === forceUpdateCount && internals.cellCacheProps !== null && areCellPropsEqual(internals.cellCacheProps, props);
resetStyleCache(internals, keepCells);
internals.cellCacheProps = props;
internals.cellCacheForceUpdateCount = forceUpdateCount;
}
let childrenToDisplay = [];
let renderedSection = null;
if (height > 0 && width > 0) {
const visibleColumnIndices = columnSizeAndPositionManager.getVisibleCellRange({
containerSize: width,
offset: scrollLeft
});
const visibleRowIndices = rowSizeAndPositionManager.getVisibleCellRange(
{
containerSize: height,
offset: scrollTop
}
);
const horizontalOffsetAdjustment = columnSizeAndPositionManager.getOffsetAdjustment({
containerSize: width,
offset: scrollLeft
});
const verticalOffsetAdjustment = rowSizeAndPositionManager.getOffsetAdjustment({
containerSize: height,
offset: scrollTop
});
const overscanColumnIndices = overscanIndicesGetter({
direction: "horizontal",
cellCount: columnCount,
overscanCellsCount: overscanColumnCount,
scrollDirection: scrollDirectionHorizontal,
startIndex: typeof visibleColumnIndices.start === "number" ? visibleColumnIndices.start : 0,
stopIndex: typeof visibleColumnIndices.stop === "number" ? visibleColumnIndices.stop : -1
});
const overscanRowIndices = overscanIndicesGetter({
direction: "vertical",
cellCount: rowCount,
overscanCellsCount: overscanRowCount,
scrollDirection: scrollDirectionVertical,
startIndex: typeof visibleRowIndices.start === "number" ? visibleRowIndices.start : 0,
stopIndex: typeof visibleRowIndices.stop === "number" ? visibleRowIndices.stop : -1
});
let columnStartIndex = overscanColumnIndices.overscanStartIndex;
let columnStopIndex = overscanColumnIndices.overscanStopIndex;
let rowStartIndex = overscanRowIndices.overscanStartIndex;
let rowStopIndex = overscanRowIndices.overscanStopIndex;
if (deferredMeasurementCache) {
if (!deferredMeasurementCache.hasFixedHeight()) {
for (let rowIndex = rowStartIndex; rowIndex <= rowStopIndex; rowIndex++) {
if (!deferredMeasurementCache.has(rowIndex, 0)) {
columnStartIndex = 0;
columnStopIndex = columnCount - 1;
break;
}
}
}
if (!deferredMeasurementCache.hasFixedWidth()) {
for (let columnIndex = columnStartIndex; columnIndex <= columnStopIndex; columnIndex++) {
if (!deferredMeasurementCache.has(0, columnIndex)) {
rowStartIndex = 0;
rowStopIndex = rowCount - 1;
break;
}
}
}
}
childrenToDisplay = cellRangeRenderer({
cellCache: internals.cellCache,
cellRenderer,
columnSizeAndPositionManager,
columnStartIndex,
columnStopIndex,
deferredMeasurementCache,
horizontalOffsetAdjustment,
isScrolling,
isScrollingOptOut,
parent: handle,
rowSizeAndPositionManager,
rowStartIndex,
rowStopIndex,
scrollLeft,
scrollTop,
styleCache: internals.styleCache,
verticalOffsetAdjustment,
visibleColumnIndices,
visibleRowIndices
});
internals.renderedRange = {
columnStartIndex,
columnStopIndex,
rowStartIndex,
rowStopIndex
};
renderedSection = {
columnOverscanStartIndex: columnStartIndex,
columnOverscanStopIndex: columnStopIndex,
columnStartIndex: visibleColumnIndices.start,
columnStopIndex: visibleColumnIndices.stop,
rowOverscanStartIndex: rowStartIndex,
rowOverscanStopIndex: rowStopIndex,
rowStartIndex: visibleRowIndices.start,
rowStopIndex: visibleRowIndices.stop
};
}
const totalColumnsWidth = columnSizeAndPositionManager.getTotalSize();
const totalRowsHeight = rowSizeAndPositionManager.getTotalSize();
const verticalScrollBarSize = totalRowsHeight > height ? scrollbarSize2 : 0;
const horizontalScrollBarSize = totalColumnsWidth > width ? scrollbarSize2 : 0;
useIsomorphicLayoutEffect(() => {
const committed = internals.committed;
const element = internals.element;
if (typeof internals.deferredInvalidateColumnIndex === "number" && typeof internals.deferredInvalidateRowIndex === "number") {
const columnIndex = internals.deferredInvalidateColumnIndex;
const rowIndex = internals.deferredInvalidateRowIndex;
internals.deferredInvalidateColumnIndex = null;
internals.deferredInvalidateRowIndex = null;
handle.recomputeGridSize({ columnIndex, rowIndex });
}
if (committed === null && hydrationShift !== null) {
internals.scrollOffsetsPendingHydration = true;
setHydrationShift(null);
if (element && (element.scrollLeft > 0 || element.scrollTop > 0)) {
setScrollState({
scrollLeft: hydrationShift.left + element.scrollLeft,
scrollTop: hydrationShift.top + element.scrollTop
});
}
} else if (committed === null) {
if (element) {
if (element.scrollLeft !== scrollState.scrollLeft) {
element.scrollLeft = scrollState.scrollLeft;
}
if (element.scrollTop !== scrollState.scrollTop) {
element.scrollTop = scrollState.scrollTop;
}
}
} else {
if (internals.scrollOffsetsPendingHydration && hydrationShift === null) {
internals.scrollOffsetsPendingHydration = false;
if (element) {
element.scrollLeft = scrollState.scrollLeft;
if (!linked) {
element.scrollTop = scrollState.scrollTop;
}
}
}
const columnOrRowCountJustIncreasedFromZero = columnCount > 0 && committed.columnCount === 0 || rowCount > 0 && committed.rowCount === 0;
if (element && scrollState.scrollPositionChangeReason === SCROLL_POSITION_CHANGE_REASONS.REQUESTED) {
const update = {};
if (scrollState.scrollLeft >= 0 && (scrollState.scrollLeft !== element.scrollLeft || columnOrRowCountJustIncreasedFromZero)) {
element.scrollLeft = scrollState.scrollLeft;
if (Math.abs(element.scrollLeft - scrollState.scrollLeft) >= 1) {
update.scrollLeft = element.scrollLeft;
}
}
if (!linked && scrollState.scrollTop >= 0 && (scrollState.scrollTop !== element.scrollTop || columnOrRowCountJustIncreasedFromZero)) {
element.scrollTop = scrollState.scrollTop;
if (Math.abs(element.scrollTop - scrollState.scrollTop) >= 1) {
update.scrollTop = element.scrollTop;
}
}
if (update.scrollLeft !== void 0 || update.scrollTop !== void 0) {
update.scrollPositionChangeReason = SCROLL_POSITION_CHANGE_REASONS.OBSERVED;
setScrollState(update);
}
}
updateScrollIndexHelper({
cellSizeAndPositionManager: columnSizeAndPositionManager,
previousCellsCount: committed.columnCount,
previousSize: committed.width,
scrollOffset: scrollState.scrollLeft,
size: width,
updateScrollIndexCallback: (columnIndex) => updateScrollLeftForColumn("auto", columnIndex)
});
updateScrollIndexHelper({
cellSizeAndPositionManager: rowSizeAndPositionManager,
previousCellsCount: committed.rowCount,
previousSize: committed.height,
// The viewport of a linked Grid may extend past its end (e.g. the window may be scrolled past it),
// so its offset doesn't need to be corrected when rows are removed
scrollOffset: linked ? 0 : scrollState.scrollTop,
size: height,
updateScrollIndexCallback: (rowIndex) => updateScrollTopForRow("auto", rowIndex)
});
}
if (columnCount === 0 && scrollState.scrollLeft !== 0 || rowCount === 0 && scrollState.scrollTop !== 0) {
setScrollState({ scrollLeft: 0, scrollTop: 0 });
}
if (renderedSection !== null) {
internals.onGridRenderedMemoizer({
callback: onSectionRendered,
indices: renderedSection
});
}
if (committed === null || scrollLeft !== committed.scrollLeft || scrollTop !== committed.scrollTop) {
invokeOnScrollMemoizer(
scrollLeft,
scrollTop,
totalColumnsWidth,
totalRowsHeight
);
}
const { scrollbarPresence } = internals;
if (horizontalScrollBarSize !== scrollbarPresence.horizontal || verticalScrollBarSize !== scrollbarPresence.vertical) {
internals.scrollbarPresence = {
horizontal: horizontalScrollBarSize,
vertical: verticalScrollBarSize
};
const params = {
horizontal: horizontalScrollBarSize > 0,
size: scrollbarSize2,
vertical: verticalScrollBarSize > 0
};
onScrollbarPresenceChange(params);
}
internals.committed = {
columnCount,
columnWidth,
height,
rowCount,
rowHeight,
scrollLeft,
scrollTop,
width
};
});
react.useEffect(
() => () => {
if (internals.disablePointerEventsTimeoutId) {
cancelAnimationTimeout(internals.disablePointerEventsTimeoutId);
internals.disablePointerEventsTimeoutId = null;
}
},
[internals]
);
const gridStyle = {
boxSizing: "border-box",
direction: "ltr",
// A linked Grid renders at its full height (it doesn't scroll vertically itself)
height: linked ? "auto" : height,
position: "relative",
width,
WebkitOverflowScrolling: "touch",
willChange: "transform"
};
gridStyle.overflowX = totalColumnsWidth + verticalScrollBarSize <= width ? "hidden" : "auto";
gridStyle.overflowY = totalRowsHeight + horizontalScrollBarSize <= height ? "hidden" : "auto";
const showNoContentRenderer = childrenToDisplay.length === 0 && height > 0 && width > 0;
return /* @__PURE__ */ jsxRuntime.jsxs(
"div",
{
ref: setScrollingContainerRef,
...containerProps,
"aria-label": ariaLabel,
"aria-readonly": ariaReadonly,
className: clsx("ReactVirtualized__Grid", className),
id,
onScroll: onScrollEvent,
role,
style: {
...gridStyle,
...style
},
tabIndex,
children: [
childrenToDisplay.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: "ReactVirtualized__Grid__innerScrollContainer",
role: containerRole,
style: {
width: autoContainerWidth ? "auto" : totalColumnsWidth,
height: totalRowsHeight,
maxWidth: totalColumnsWidth,
maxHeight: totalRowsHeight,
overflow: "hidden",
pointerEvents: isScrolling ? "none" : "",
position: "relative",
...hydrationShift !== null && {
marginLeft: -hydrationShift.left,
marginTop: -hydrationShift.top
},
...containerStyle
},
children: childrenToDisplay
}
),
showNoContentRenderer && noContentRenderer()
]
}
);
}
)
);
const defaultInfiniteLoaderProps = /* @__PURE__ */ Object.freeze({
minimumBatchSize: 10,
rowCount: 0,
threshold: 15
});
function isRangeVisible({
lastRenderedStartIndex,
lastRenderedStopIndex,
startIndex,
stopIndex
}) {
return !(startIndex > lastRenderedStopIndex || stopIndex < lastRenderedStartIndex);
}
function scanForUnloadedRanges({
isRowLoaded,
minimumBatchSize,
rowCount,
startIndex,
stopIndex
}) {
const unloadedRanges = [];
let rangeStartIndex = null;
let rangeStopIndex = null;
for (let index = startIndex; index <= stopIndex; index++) {
const loaded = isRowLoaded({ index });
if (!loaded) {
rangeStopIndex = index;
if (rangeStartIndex === null) {
rangeStartIndex = index;
}
} else if (rangeStopIndex !== null) {
unloadedRanges.push({
startIndex: rangeStartIndex,
stopIndex: rangeStopIndex
});
rangeStartIndex = rangeStopIndex = null;
}
}
if (rangeStopIndex !== null) {
const potentialStopIndex = Math.min(
Math.max(rangeStopIndex, rangeStartIndex + minimumBatchSize - 1),
rowCount - 1
);
for (let index = rangeStopIndex + 1; index <= potentialStopIndex; index++) {
if (!isRowLoaded({ index })) {
rangeStopIndex = index;
} else {
break;
}
}
unloadedRanges.push({
startIndex: rangeStartIndex,
stopIndex: rangeStopIndex
});
}
if (unloadedRanges.length) {
const firstUnloadedRange = unloadedRanges[0];
while (firstUnloadedRange.stopIndex - firstUnloadedRange.startIndex + 1 < minimumBatchSize && firstUnloadedRange.startIndex > 0) {
const index = firstUnloadedRange.startIndex - 1;
if (!isRowLoaded({ index })) {
firstUnloadedRange.startIndex = index;
} else {
break;
}
}
}
return unloadedRanges;
}
function forceUpdateReactVirtualizedComponent(component, currentIndex = 0) {
if (typeof component.recomputeGridSize === "function") {
component.recomputeGridSize({ rowIndex: currentIndex });
} else if (typeof component.recomputeRowHeights === "function") {
component.recomputeRowHeights(currentIndex);
} else if (typeof component.forceUpdateGrid === "function") {
component.forceUpdateGrid();
} else if (typeof component.forceUpdate === "function") {
component.forceUpdate();
} else if (process.env.NODE_ENV !== "production") {
console.warn(
"InfiniteLoader: the registered child does not implement recomputeGridSize(), recomputeRowHeights(), forceUpdateGrid() or forceUpdate(); it can't be re-rendered after rows have loaded."
);
}
}
const InfiniteLoader = /* @__PURE__ */ react.memo(
/* @__PURE__ */ react.forwardRef(
function InfiniteLoader2({
children,
isRowLoaded,
loadMoreRows,
minimumBatchSize = defaultInfiniteLoaderProps.minimumBatchSize,
rowCount = defaultInfiniteLoaderProps.rowCount,
threshold = defaultInfiniteLoaderProps.threshold
}, ref) {
const latestPropsRef = react.useRef({
isRowLoaded,
loadMoreRows,
minimumBatchSize,
rowCount,
threshold
});
react.useInsertionEffect(() => {
latestPropsRef.current = {
isRowLoaded,
loadMoreRows,
minimumBatchSize,
rowCount,
threshold
};
});
const lastRenderedRangeRef = react.useRef({ startIndex: void 0, stopIndex: void 0 });
const loadMoreRowsMemoizerRef = react.useRef(null);
const registeredChildRef = react.useRef(
null
);
const getLoadMoreRowsMemoizer = react.useCallback(() => {
if (loadMoreRowsMemoizerRef.current === null) {
loadMoreRowsMemoizerRef.current = createCallbackMemoizer();
}
return loadMoreRowsMemoizerRef.current;
}, []);
const loadUnloadedRanges = react.useCallback((unloadedRanges) => {
const { loadMoreRows: loadMoreRows2 } = latestPropsRef.current;
unloadedRanges.forEach((unloadedRange) => {
const promise = loadMoreRows2(unloadedRange);
if (promise) {
promise.then(() => {
const { startIndex, stopIndex } = lastRenderedRangeRef.current;
if (isRangeVisible({
lastRenderedStartIndex: startIndex,
lastRenderedStopIndex: stopIndex,
startIndex: unloadedRange.startIndex,
stopIndex: unloadedRange.stopIndex
})) {
const registeredChild = registeredChildRef.current;
if (registeredChild) {
forceUpdateReactVirtualizedComponent(
registeredChild,
startIndex
);
}
}
});
}
});
}, []);
const loadRange = react.useCallback(
(startIndex, stopIndex) => {
const { isRowLoaded: isRowLoaded2, minimumBatchSize: minimumBatchSize2, rowCount: rowCount2, threshold: threshold2 } = latestPropsRef.current;
const unloadedRanges = scanForUnloadedRanges({
isRowLoaded: isRowLoaded2,
minimumBatchSize: minimumBatchSize2,
rowCount: rowCount2,
startIndex: Math.max(0, startIndex - threshold2),
stopIndex: Math.min(rowCount2 - 1, stopIndex + threshold2)
});
const squashedUnloadedRanges = [].concat(
...unloadedRanges.map(({ startIndex: startIndex2, stopIndex: stopIndex2 }) => [
startIndex2,
stopIndex2
])
);
getLoadMoreRowsMemoizer()({
callback: () => {
loadUnloadedRanges(unloadedRanges);
},
indices: { squashedUnloadedRanges }
});
},
[getLoadMoreRowsMemoizer, loadUnloadedRanges]
);
const onRowsRendered = react.useCallback(
({ startIndex, stopIndex }) => {
lastRenderedRangeRef.current = { startIndex, stopIndex };
loadRange(startIndex, stopIndex);
},
[loadRange]
);
const registerChild = react.useCallback(
(registeredChild) => {
registeredChildRef.current = registeredChild;
},
[]
);
const imperativeHandle = react.useMemo(
() => ({
resetLoadMoreRowsCache(autoReload) {
loadMoreRowsMemoizerRef.current = createCallbackMemoizer();
if (autoReload) {
const { startIndex, stopIndex } = lastRenderedRangeRef.current;
loadRange(startIndex, stopIndex);
}
}
}),
[loadRange]
);
react.useImperativeHandle(ref, () => imperativeHandle, [imperativeHandle]);
return children({
onRowsRendered,
registerChild
});
}
)
);
const noop$1 = () => {
};
const defaultListProps = /* @__PURE__ */ Object.freeze({
estimatedRowSize: 30,
noRowsRenderer: () => null,
onRowsRendered: noop$1,
onScroll: noop$1,
overscanIndicesGetter: accessibilityOverscanIndicesGetter,
overscanRowCount: 10,
role: "list",
style: /* @__PURE__ */ Object.freeze({}),
tabIndex: 0
});
const mergeCellPositions = (prev, next) => prev === null ? next : {
columnIndex: Math.min(prev.columnIndex, next.columnIndex),
rowIndex: Math.min(prev.rowIndex, next.rowIndex)
};
function createInnerGridRef() {
let grid = null;
let pendingInvalidation = null;
let pendingRecomputation = null;
return {
getGrid: () => grid,
setGridRef(value) {
grid = value;
if (grid === null) {
return;
}
if (pendingRecomputation !== null) {
const cell = pendingRecomputation;
pendingRecomputation = null;
grid.recomputeGridSize(cell);
}
if (pendingInvalidation !== null) {
const cell = pendingInvalidation;
pendingInvalidation = null;
grid.invalidateCellSizeAfterRender(cell);
}
},
invalidateCellSizeAfterRender(cell) {
if (grid !== null) {
grid.invalidateCellSizeAfterRender(cell);
} else {
pendingInvalidation = mergeCellPositions(pendingInvalidation, cell);
}
},
recomputeGridSize(cell) {
if (grid !== null) {
grid.recomputeGridSize(cell);
} else {
pendingRecomputation = mergeCellPositions(pendingRecomputation, cell);
}
}
};
}
const List = /* @__PURE__ */ react.memo(
/* @__PURE__ */ react.forwardRef(
function List2(props, ref) {
const {
"aria-label": ariaLabel,
"aria-readonly": ariaReadonly,
className,
containerRole,
estimatedRowSize = defaultListProps.estimatedRowSize,
noRowsRenderer = defaultListProps.noRowsRenderer,
onRowsRendered = defaultListProps.onRowsRendered,
onScroll: onScroll2 = defaultListProps.onScroll,
overscanIndicesGetter = defaultListProps.overscanIndicesGetter,
overscanRowCount = defaultListProps.overscanRowCount,
role = defaultListProps.role,
rowRenderer,
style = defaultListProps.style,
tabIndex = defaultListProps.tabIndex,
height,
scrollElement,
width,
...rest
} = props;
const [{ handle, setGridRef }] = react.useState(createListInstance);
react.useImperativeHandle(ref, () => handle, [handle]);
useMissingHeightWarning("List", height, scrollElement);
const isList = role === "list";
const cellRenderer = react.useCallback(
({
isScrolling,
isVisible,
key,
rowIndex,
style: cellStyle
}) => {
const widthDescriptor = Object.getOwnPropertyDescriptor(
cellStyle,
"width"
);
if (widthDescriptor && widthDescriptor.writable) {
cellStyle.width = "100%";
}
const row = rowRenderer({
index: rowIndex,
isScrolling,
isVisible,
key,
parent: handle,
style: cellStyle
});
if (isList && react.isValidElement(row) && !row.props.role) {
return react.cloneElement(row, {
role: "listitem"
});
}
return row;
},
[handle, isList, rowRenderer]
);
const onGridScroll = react.useCallback(
({ clientHeight, scrollHeight, scrollTop }) => {
onScroll2({ clientHeight, scrollHeight, scrollTop });
},
[onScroll2]
);
const onSectionRendered = react.useCallback(
({
rowOverscanStartIndex,
rowOverscanStopIndex,
rowStartIndex,
rowStopIndex
}) => {
onRowsRendered({
overscanStartIndex: rowOverscanStartIndex,
overscanStopIndex: rowOverscanStopIndex,
startIndex: rowStartIndex,
stopIndex: rowStopIndex
});
},
[onRowsRendered]
);
return /* @__PURE__ */ jsxRuntime.jsx(
Grid,
{
...rest,
"aria-label": ariaLabel ?? (isList ? null : void 0),
"aria-readonly": ariaReadonly ?? (isList ? null : void 0),
autoContainerWidth: true,
cellRenderer,
className: clsx("ReactVirtualized__List", className),
columnCount: 1,
columnWidth: width,
containerRole: containerRole ?? (isList ? "presentation" : void 0),
estimatedRowSize,
height: height ?? (scrollElement === void 0 ? 0 : void 0),
noContentRenderer: noRowsRenderer,
onScroll: onGridScroll,
onSectionRendered,
overscanIndicesGetter,
overscanRowCount,
ref: setGridRef,
role,
scrollElement,
style,
tabIndex,
width
}
);
}
)
);
function createListInstance() {
const innerGrid = createInnerGridRef();
const { getGrid } = innerGrid;
const handle = {
forceUpdateGrid() {
getGrid()?.forceUpdate();
},
getOffsetForRow({ align, alignment, index } = {}) {
const grid = getGrid();
if (grid) {
const { scrollTop } = grid.getOffsetForCell({
alignment: align ?? alignment,
columnIndex: 0,
rowIndex: index
});
return scrollTop;
}
return 0;
},
invalidateCellSizeAfterRender({ columnIndex, rowIndex }) {
innerGrid.invalidateCellSizeAfterRender({ columnIndex, rowIndex });
},
measureAllRows() {
getGrid()?.measureAllCells();
},
recomputeGridSize({ columnIndex = 0, rowIndex = 0 } = {}) {
innerGrid.recomputeGridSize({ columnIndex, rowIndex });
},
recomputeRowHeights(index = 0) {
innerGrid.recomputeGridSize({ columnIndex: 0, rowIndex: index });
},
scrollToCell({ align, columnIndex, rowIndex }) {
getGrid()?.scrollToCell({ align, columnIndex, rowIndex });
},
scrollToPosition({ scrollTop }) {
getGrid()?.scrollToPosition({ scrollTop });
},
scrollToRow({ align, index }) {
getGrid()?.scrollToCell({ align, columnIndex: 0, rowIndex: index });
}
};
return { handle, setGridRef: innerGrid.setGridRef };
}
const DEFAULT_SCROLLING_RESET_TIME_INTERVAL = 150;
const noop = () => {
};
const defaultMasonryProps = /* @__PURE__ */ Object.freeze({
keyMapper: (index) => index,
onCellsRendered: noop,
onScroll: noop,
overscanByPixels: 20,
role: "grid",
rowDirection: "ltr",
scrollingResetTimeInterval: DEFAULT_SCROLLING_RESET_TIME_INTERVAL,
style: /* @__PURE__ */ Object.freeze({}),
tabIndex: 0
});
function createCellPositioner({
cellMeasurerCache,
columnCount,
columnWidth,
spacer = 0
}) {
let columnHeights;
initOrResetDerivedValues();
function cellPositioner(index) {
let columnIndex = 0;
for (let i = 1; i < columnHeights.length; i++) {
if (columnHeights[i] < columnHeights[columnIndex]) {
columnIndex = i;
}
}
const left = columnIndex * (columnWidth + spacer);
const top = columnHeights[columnIndex] || 0;
columnHeights[columnIndex] = top + cellMeasurerCache.getHeight(index) + spacer;
return {
left,
top
};
}
function initOrResetDerivedValues() {
columnHeights = [];
for (let i = 0; i < columnCount; i++) {
columnHeights[i] = 0;
}
}
function reset(params) {
columnCount = params.columnCount;
columnWidth = params.columnWidth;
spacer = params.spacer ?? 0;
initOrResetDerivedValues();
}
cellPositioner.reset = reset;
return cellPositioner;
}
function _GEA(a, l, h, y) {
let i = h + 1;
while (l <= h) {
const m = l + h >>> 1, x = a[m];
if (x >= y) {
i = m;
h = m - 1;
} else {
l = m + 1;
}
}
return i;
}
function _GEP(a, l, h, y, c) {
let i = h + 1;
while (l <= h) {
const m = l + h >>> 1, x = a[m];
if (c(x, y) >= 0) {
i = m;
h = m - 1;
} else {
l = m + 1;
}
}
return i;
}
function dispatchBsearchGE(a, y, c, l, h) {
if (typeof c === "function") {
return _GEP(
a,
l === void 0 ? 0 : l | 0,
h === void 0 ? a.length - 1 : h | 0,
y,
c
);
} else {
return _GEA(
a,
c === void 0 ? 0 : c | 0,
l === void 0 ? a.length - 1 : l | 0,
y
);
}
}
function _GTA(a, l, h, y) {
let i = h + 1;
while (l <= h) {
const m = l + h >>> 1, x = a[m];
if (x > y) {
i = m;
h = m - 1;
} else {
l = m + 1;
}
}
return i;
}
function _GTP(a, l, h, y, c) {
let i = h + 1;
while (l <= h) {
const m = l + h >>> 1, x = a[m];
if (c(x, y) > 0) {
i = m;
h = m - 1;
} else {
l = m + 1;
}
}
return i;
}
function dispatchBsearchGT(a, y, c, l, h) {
if (typeof c === "function") {
return _GTP(
a,
l === void 0 ? 0 : l | 0,
h === void 0 ? a.length - 1 : h | 0,
y,
c
);
} else {
return _GTA(
a,
c === void 0 ? 0 : c | 0,
l === void 0 ? a.length - 1 : l | 0,
y
);
}
}
function _LTA(a, l, h, y) {
let i = l - 1;
while (l <= h) {
const m = l + h >>> 1, x = a[m];
if (x < y) {
i = m;
l = m + 1;
} else {
h = m - 1;
}
}
return i;
}
function _LTP(a, l, h, y, c) {
let i = l - 1;
while (l <= h) {
const m = l + h >>> 1, x = a[m];
if (c(x, y) < 0) {
i = m;
l = m + 1;
} else {
h = m - 1;
}
}
return i;
}
function dispatchBsearchLT(a, y, c, l, h) {
if (typeof c === "function") {
return _LTP(
a,
l === void 0 ? 0 : l | 0,
h === void 0 ? a.length - 1 : h | 0,
y,
c
);
} else {
return _LTA(
a,
c === void 0 ? 0 : c | 0,
l === void 0 ? a.length - 1 : l | 0,
y
);
}
}
function _LEA(a, l, h, y) {
let i = l - 1;
while (l <= h) {
const m = l + h >>> 1, x = a[m];
if (x <= y) {
i = m;
l = m + 1;
} else {
h = m - 1;
}
}
return i;
}
function _LEP(a, l, h, y, c) {
let i = l - 1;
while (l <= h) {
const m = l + h >>> 1, x = a[m];
if (c(x, y) <= 0) {
i = m;
l = m + 1;
} else {
h = m - 1;
}
}
return i;
}
function dispatchBsearchLE(a, y, c, l, h) {
if (typeof c === "function") {
return _LEP(
a,
l === void 0 ? 0 : l | 0,
h === void 0 ? a.length - 1 : h | 0,
y,
c
);
} else {
return _LEA(
a,
c === void 0 ? 0 : c | 0,
l === void 0 ? a.length - 1 : l | 0,
y
);
}
}
function _EQA(a, l, h, y) {
while (l <= h) {
const m = l + h >>> 1, x = a[m];
if (x === y) {
return m;
} else if (x <= y) {
l = m + 1;
} else {
h = m - 1;
}
}
return -1;
}
function _EQP(a, l, h, y, c) {
while (l <= h) {
const m = l + h >>> 1, x = a[m];
const p = c(x, y);
if (p === 0) {
return m;
} else if (p <= 0) {
l = m + 1;
} else {
h = m - 1;
}
}
return -1;
}
function dispatchBsearchEQ(a, y, c, l, h) {
if (typeof c === "function") {
return _EQP(
a,
l === void 0 ? 0 : l | 0,
h === void 0 ? a.length - 1 : h | 0,
y,
c
);
} else {
return _EQA(
a,
c === void 0 ? 0 : c | 0,
l === void 0 ? a.length - 1 : l | 0,
y
);
}
}
const binarySearchBounds = {
ge: dispatchBsearchGE,
gt: dispatchBsearchGT,
lt: dispatchBsearchLT,
le: dispatchBsearchLE,
eq: dispatchBsearchEQ
};
const NOT_FOUND = 0;
const SUCCESS = 1;
const EMPTY = 2;
class IntervalTreeNode {
mid;
left;
right;
leftPoints;
rightPoints;
count;
constructor(mid, left, right, leftPoints, rightPoints) {
this.mid = mid;
this.left = left;
this.right = right;
this.leftPoints = leftPoints;
this.rightPoints = rightPoints;
this.count = (left ? left.count : 0) + (right ? right.count : 0) + leftPoints.length;
}
intervals(result) {
result.push.apply(result, this.leftPoints);
if (this.left) {
this.left.intervals(result);
}
if (this.right) {
this.right.intervals(result);
}
return result;
}
insert(interval) {
const weight = this.count - this.leftPoints.length;
this.count += 1;
if (interval[1] < this.mid) {
if (this.left) {
if (4 * (this.left.count + 1) > 3 * (weight + 1)) {
rebuildWithInterval(this, interval);
} else {
this.left.insert(interval);
}
} else {
this.left = createIntervalTreeNode([interval]);
}
} else if (interval[0] > this.mid) {
if (this.right) {
if (4 * (this.right.count + 1) > 3 * (weight + 1)) {
rebuildWithInterval(this, interval);
} else {
this.right.insert(interval);
}
} else {
this.right = createIntervalTreeNode([interval]);
}
} else {
const l = binarySearchBounds.ge(this.leftPoints, interval, compareBegin);
const r = binarySearchBounds.ge(this.rightPoints, interval, compareEnd);
this.leftPoints.splice(l, 0, interval);
this.rightPoints.splice(r, 0, interval);
}
}
remove(interval) {
const weight = this.count - this.leftPoints.length;
if (interval[1] < this.mid) {
if (!this.left) {
return NOT_FOUND;
}
const rw = this.right ? this.right.count : 0;
if (4 * rw > 3 * (weight - 1)) {
return rebuildWithoutInterval(this, interval);
}
const r = this.left.remove(interval);
if (r === EMPTY) {
this.left = null;
this.count -= 1;
return SUCCESS;
} else if (r === SUCCESS) {
this.count -= 1;
}
return r;
} else if (interval[0] > this.mid) {
if (!this.right) {
return NOT_FOUND;
}
const lw = this.left ? this.left.count : 0;
if (4 * lw > 3 * (weight - 1)) {
return rebuildWithoutInterval(this, interval);
}
const r = this.right.remove(interval);
if (r === EMPTY) {
this.right = null;
this.count -= 1;
return SUCCESS;
} else if (r === SUCCESS) {
this.count -= 1;
}
return r;
} else {
if (this.count === 1) {
if (this.leftPoints[0] === interval) {
return EMPTY;
} else {
return NOT_FOUND;
}
}
if (this.leftPoints.length === 1 && this.leftPoints[0] === interval) {
if (this.left && this.right) {
return rebuildWithoutInterval(this, interval);
} else if (this.left) {
copy(this, this.left);
} else {
copy(this, this.right);
}
return SUCCESS;
}
for (let l = binarySearchBounds.ge(this.leftPoints, interval, compareBegin); l < this.leftPoints.length; ++l) {
if (this.leftPoints[l][0] !== interval[0]) {
break;
}
if (this.leftPoints[l] === interval) {
this.count -= 1;
this.leftPoints.splice(l, 1);
for (let r = binarySearchBounds.ge(this.rightPoints, interval, compareEnd); r < this.rightPoints.length; ++r) {
if (this.rightPoints[r][1] !== interval[1]) {
break;
} else if (this.rightPoints[r] === interval) {
this.rightPoints.splice(r, 1);
return SUCCESS;
}
}
}
}
return NOT_FOUND;
}
}
queryPoint(x, cb) {
if (x < this.mid) {
if (this.left) {
const r = this.left.queryPoint(x, cb);
if (r) {
return r;
}
}
return reportLeftRange(this.leftPoints, x, cb);
} else if (x > this.mid) {
if (this.right) {
const r = this.right.queryPoint(x, cb);
if (r) {
return r;
}
}
return reportRightRange(this.rightPoints, x, cb);
} else {
return reportRange(this.leftPoints, cb);
}
}
queryInterval(lo, hi, cb) {
if (lo < this.mid && this.left) {
const r = this.left.queryInterval(lo, hi, cb);
if (r) {
return r;
}
}
if (hi > this.mid && this.right) {
const r = this.right.queryInterval(lo, hi, cb);
if (r) {
return r;
}
}
if (hi < this.mid) {
return reportLeftRange(this.leftPoints, hi, cb);
} else if (lo > this.mid) {
return reportRightRange(this.rightPoints, lo, cb);
} else {
return reportRange(this.leftPoints, cb);
}
}
}
function copy(a, b) {
a.mid = b.mid;
a.left = b.left;
a.right = b.right;
a.leftPoints = b.leftPoints;
a.rightPoints = b.rightPoints;
a.count = b.count;
}
function rebuild(node, intervals) {
const ntree = createIntervalTreeNode(intervals);
node.mid = ntree.mid;
node.left = ntree.left;
node.right = ntree.right;
node.leftPoints = ntree.leftPoints;
node.rightPoints = ntree.rightPoints;
node.count = ntree.count;
}
function rebuildWithInterval(node, interval) {
const intervals = node.intervals([]);
intervals.push(interval);
rebuild(node, intervals);
}
function rebuildWithoutInterval(node, interval) {
const intervals = node.intervals([]);
const idx = intervals.indexOf(interval);
if (idx < 0) {
return NOT_FOUND;
}
intervals.splice(idx, 1);
if (intervals.length === 0) {
return EMPTY;
}
rebuild(node, intervals);
return SUCCESS;
}
function reportLeftRange(arr, hi, cb) {
for (let i = 0; i < arr.length && arr[i][0] <= hi; ++i) {
const r = cb(arr[i]);
if (r) {
return r;
}
}
}
function reportRightRange(arr, lo, cb) {
for (let i = arr.length - 1; i >= 0 && arr[i][1] >= lo; --i) {
const r = cb(arr[i]);
if (r) {
return r;
}
}
}
function reportRange(arr, cb) {
for (let i = 0; i < arr.length; ++i) {
const r = cb(arr[i]);
if (r) {
return r;
}
}
}
function compareNumbers(a, b) {
return a - b;
}
function compareBegin(a, b) {
const d = a[0] - b[0];
if (d) {
return d;
}
return a[1] - b[1];
}
function compareEnd(a, b) {
const d = a[1] - b[1];
if (d) {
return d;
}
return a[0] - b[0];
}
function createIntervalTreeNode(intervals) {
if (intervals.length === 0) {
return null;
}
const pts = [];
for (let i = 0; i < intervals.length; ++i) {
pts.push(intervals[i][0], intervals[i][1]);
}
pts.sort(compareNumbers);
const mid = pts[pts.length >> 1];
const leftIntervals = [];
const rightIntervals = [];
const centerIntervals = [];
for (let i = 0; i < intervals.length; ++i) {
const s = intervals[i];
if (s[1] < mid) {
leftIntervals.push(s);
} else if (mid < s[0]) {
rightIntervals.push(s);
} else {
centerIntervals.push(s);
}
}
const leftPoints = centerIntervals;
const rightPoints = centerIntervals.slice();
leftPoints.sort(compareBegin);
rightPoints.sort(compareEnd);
return new IntervalTreeNode(
mid,
createIntervalTreeNode(leftIntervals),
createIntervalTreeNode(rightIntervals),
leftPoints,
rightPoints
);
}
class IntervalTreeWrapper {
root;
constructor(root) {
this.root = root;
}
insert(interval) {
if (this.root) {
this.root.insert(interval);
} else {
this.root = new IntervalTreeNode(
interval[0],
null,
null,
[interval],
[interval]
);
}
}
remove(interval) {
if (this.root) {
const r = this.root.remove(interval);
if (r === EMPTY) {
this.root = null;
}
return r !== NOT_FOUND;
}
return false;
}
queryPoint(p, cb) {
if (this.root) {
return this.root.queryPoint(p, cb);
}
}
queryInterval(lo, hi, cb) {
if (lo <= hi && this.root) {
return this.root.queryInterval(lo, hi, cb);
}
}
get count() {
if (this.root) {
return this.root.count;
}
return 0;
}
get intervals() {
if (this.root) {
return this.root.intervals([]);
}
return [];
}
}
function createIntervalTree(intervals) {
{
return new IntervalTreeWrapper(null);
}
}
class PositionCache {
// Tracks the height of each column
_columnSizeMap = {};
// Store tops and bottoms of each cell for fast intersection lookup.
_intervalTree = createIntervalTree();
// Maps cell index to x coordinates for quick lookup.
_leftMap = {};
// Maps cell index to the y coordinate of its bottom edge.
_bottomMap = {};
estimateTotalHeight(cellCount, columnCount, defaultCellHeight) {
const unmeasuredCellCount = cellCount - this.count;
if (unmeasuredCellCount < 0) {
let size = 0;
for (let index = 0; index < cellCount; index++) {
const bottom = this._bottomMap[index];
if (bottom !== void 0 && bottom > size) {
size = bottom;
}
}
return size;
}
return this.tallestColumnSize + Math.ceil(unmeasuredCellCount / columnCount) * defaultCellHeight;
}
// Render all cells visible within the viewport range defined.
range(scrollTop, clientHeight, renderCallback) {
this._intervalTree.queryInterval(
scrollTop,
scrollTop + clientHeight,
([top, , index]) => renderCallback(index, this._leftMap[index], top)
);
}
setPosition(index, left, top, height) {
this._intervalTree.insert([top, top + height, index]);
this._leftMap[index] = left;
this._bottomMap[index] = top + height;
const columnSizeMap = this._columnSizeMap;
const columnHeight = columnSizeMap[left];
if (columnHeight === void 0) {
columnSizeMap[left] = top + height;
} else {
columnSizeMap[left] = Math.max(columnHeight, top + height);
}
}
get count() {
return this._intervalTree.count;
}
get shortestColumnSize() {
const columnSizeMap = this._columnSizeMap;
let size = Infinity;
for (const i in columnSizeMap) {
const height = columnSizeMap[i];
size = Math.min(size, height);
}
return size === Infinity ? 0 : size;
}
get tallestColumnSize() {
const columnSizeMap = this._columnSizeMap;
let size = 0;
for (const i in columnSizeMap) {
const height = columnSizeMap[i];
size = Math.max(size, height);
}
return size;
}
}
const increment$1 = (value) => value + 1;
const Masonry = /* @__PURE__ */ react.memo(
/* @__PURE__ */ react.forwardRef(
function Masonry2(props, ref) {
const {
"aria-label": ariaLabel,
cellCount,
cellMeasurerCache,
cellPositioner,
cellRenderer,
className,
height: heightProp,
id,
keyMapper = defaultMasonryProps.keyMapper,
onCellsRendered = defaultMasonryProps.onCellsRendered,
onScroll: onScroll2 = defaultMasonryProps.onScroll,
overscanByPixels = defaultMasonryProps.overscanByPixels,
role = defaultMasonryProps.role,
rowDirection = defaultMasonryProps.rowDirection,
scrollElement,
scrollingResetTimeInterval = defaultMasonryProps.scrollingResetTimeInterval,
style = defaultMasonryProps.style,
tabIndex = defaultMasonryProps.tabIndex,
width
} = props;
const [state, setState] = react.useState(() => ({
isScrolling: false,
linkedViewport: null,
scrollTop: 0
}));
const [, forceUpdate] = react.useReducer(increment$1, 0);
const linked = scrollElement !== void 0;
const { linkedViewport } = state;
const height = linkedViewport !== null ? linkedViewport.height : heightProp ?? 0;
const [
{
handle,
internals,
linkTarget,
onScroll: onScrollEvent,
setElementRef
}
] = react.useState(
() => createMasonryInstance(
{
cellCount,
cellMeasurerCache,
cellPositioner,
height,
scrollingResetTimeInterval,
width
},
setState,
forceUpdate
)
);
react.useImperativeHandle(ref, () => handle, [handle]);
useMissingHeightWarning("Masonry", heightProp, scrollElement);
useScrollElementLink(
scrollElement,
linkTarget,
scrollingResetTimeInterval
);
const latest = {
cellCount,
cellMeasurerCache,
cellPositioner,
height,
scrollingResetTimeInterval,
width
};
react.useInsertionEffect(() => {
internals.latest = latest;
});
const { isScrolling } = state;
const scrollTop = linked ? linkedViewport?.scrollTop ?? 0 : state.scrollTop;
const positionCache = internals.positionCache;
const children = [];
const estimatedTotalHeight = getEstimatedTotalHeight(
positionCache,
cellCount,
cellMeasurerCache,
width
);
const shortestColumnSize = positionCache.shortestColumnSize;
const measuredCellCount = positionCache.count;
let startIndex = 0;
let stopIndex;
positionCache.range(
Math.max(0, scrollTop - overscanByPixels),
height + overscanByPixels * 2,
(index, left, top) => {
if (index >= cellCount) {
return;
}
if (typeof stopIndex === "undefined") {
startIndex = index;
stopIndex = index;
} else {
startIndex = Math.min(startIndex, index);
stopIndex = Math.max(stopIndex, index);
}
children.push(
cellRenderer({
index,
isScrolling,
key: keyMapper(index),
parent: handle,
style: {
height: cellMeasurerCache.getHeight(index),
[rowDirection === "ltr" ? "left" : "right"]: left,
position: "absolute",
top,
width: cellMeasurerCache.getWidth(index)
}
})
);
}
);
if (shortestColumnSize < scrollTop + height + overscanByPixels && measuredCellCount < cellCount) {
const batchSize = Math.min(
cellCount - measuredCellCount,
Math.ceil(
(scrollTop + height + overscanByPixels - shortestColumnSize) / cellMeasurerCache.defaultHeight * width / cellMeasurerCache.defaultWidth
)
);
for (let index = measuredCellCount; index < measuredCellCount + batchSize; index++) {
stopIndex = index;
children.push(
cellRenderer({
index,
isScrolling,
key: keyMapper(index),
parent: handle,
style: {
width: cellMeasurerCache.getWidth(index)
}
})
);
}
}
useIsomorphicLayoutEffect(() => {
if (typeof internals.invalidateOnUpdateStartIndex === "number") {
const invalidateStartIndex = internals.invalidateOnUpdateStartIndex;
const invalidateStopIndex = internals.invalidateOnUpdateStopIndex;
internals.invalidateOnUpdateStartIndex = null;
internals.invalidateOnUpdateStopIndex = null;
populatePositionCache(
internals.positionCache,
cellMeasurerCache,
cellPositioner,
invalidateStartIndex,
invalidateStopIndex
);
forceUpdate();
}
if (internals.onScrollMemoized !== scrollTop) {
internals.onScrollMemoized = scrollTop;
if (onScroll2) {
onScroll2({
clientHeight: height,
scrollHeight: getEstimatedTotalHeight(
internals.positionCache,
cellCount,
cellMeasurerCache,
width
),
scrollTop
});
}
}
if (internals.startIndexMemoized !== startIndex || internals.stopIndexMemoized !== stopIndex) {
internals.startIndexMemoized = startIndex;
internals.stopIndexMemoized = stopIndex;
if (onCellsRendered) {
onCellsRendered({ startIndex, stopIndex });
}
}
});
react.useEffect(
() => () => {
if (internals.debounceResetIsScrollingId) {
cancelAnimationTimeout(internals.debounceResetIsScrollingId);
internals.debounceResetIsScrollingId = null;
}
},
[internals]
);
return /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
"aria-label": ariaLabel,
className: clsx("ReactVirtualized__Masonry", className),
id: id ?? void 0,
onScroll: onScrollEvent,
ref: setElementRef,
role,
style: {
boxSizing: "border-box",
direction: "ltr",
// A linked Masonry renders at its full height (it doesn't scroll itself)
height: linked ? "auto" : height,
overflowX: "hidden",
overflowY: estimatedTotalHeight < height ? "hidden" : "auto",
position: "relative",
width,
WebkitOverflowScrolling: "touch",
willChange: "transform",
...style
},
tabIndex,
children: /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: "ReactVirtualized__Masonry__innerScrollContainer",
style: {
width: "100%",
height: estimatedTotalHeight,
maxWidth: "100%",
maxHeight: estimatedTotalHeight,
overflow: "hidden",
pointerEvents: isScrolling ? "none" : "",
position: "relative"
},
children
}
)
}
);
}
)
);
function getEstimatedTotalHeight(positionCache, cellCount, cellMeasurerCache, width) {
const estimatedColumnCount = Math.max(
1,
Math.floor(width / cellMeasurerCache.defaultWidth)
);
return positionCache.estimateTotalHeight(
cellCount,
estimatedColumnCount,
cellMeasurerCache.defaultHeight
);
}
function populatePositionCache(positionCache, cellMeasurerCache, cellPositioner, startIndex, stopIndex) {
for (let index = startIndex; index <= stopIndex; index++) {
const { left, top } = cellPositioner(index);
positionCache.setPosition(
index,
left,
top,
cellMeasurerCache.getHeight(index)
);
}
}
function createMasonryInstance(initialValues, setState, forceUpdate) {
const internals = {
debounceResetIsScrollingId: null,
element: null,
invalidateOnUpdateStartIndex: null,
invalidateOnUpdateStopIndex: null,
latest: initialValues,
linkedViewport: null,
onScrollMemoized: void 0,
positionCache: new PositionCache(),
startIndexMemoized: null,
stopIndexMemoized: null
};
const debounceResetIsScrollingCallback = () => {
internals.debounceResetIsScrollingId = null;
setState(
(prevState) => prevState.isScrolling ? { ...prevState, isScrolling: false } : prevState
);
};
const debounceResetIsScrolling = () => {
if (internals.debounceResetIsScrollingId) {
cancelAnimationTimeout(internals.debounceResetIsScrollingId);
}
internals.debounceResetIsScrollingId = requestAnimationTimeout(
debounceResetIsScrollingCallback,
internals.latest.scrollingResetTimeInterval
);
};
const onScroll2 = (event) => {
const { cellCount, cellMeasurerCache, height, width } = internals.latest;
const eventScrollTop = event.currentTarget.scrollTop;
const scrollTop = Math.min(
Math.max(
0,
getEstimatedTotalHeight(
internals.positionCache,
cellCount,
cellMeasurerCache,
width
) - height
),
eventScrollTop
);
if (eventScrollTop !== scrollTop) {
return;
}
debounceResetIsScrolling();
setState(
(prevState) => prevState.scrollTop !== scrollTop ? { ...prevState, isScrolling: true, scrollTop } : prevState
);
};
const linkTarget = {
getElement() {
return internals.element;
},
link(source, viewport) {
const linkedViewport = source !== null ? {
height: viewport.height,
scrollTop: Math.max(0, viewport.scrollTop)
} : null;
internals.linkedViewport = linkedViewport;
setState((prevState) => ({ ...prevState, linkedViewport }));
},
setViewport(viewport) {
const prevViewport = internals.linkedViewport;
if (prevViewport === null) {
return;
}
const linkedViewport = {
height: viewport.height,
scrollTop: Math.max(0, viewport.scrollTop)
};
if (linkedViewport.height === prevViewport.height && linkedViewport.scrollTop === prevViewport.scrollTop) {
return;
}
internals.linkedViewport = linkedViewport;
const scrolled = linkedViewport.scrollTop !== prevViewport.scrollTop;
if (scrolled) {
debounceResetIsScrolling();
}
setState((prevState) => ({
...prevState,
isScrolling: prevState.isScrolling || scrolled,
linkedViewport
}));
}
};
const handle = {
clearCellPositions() {
internals.positionCache = new PositionCache();
forceUpdate();
},
forceUpdate() {
forceUpdate();
},
// HACK This method signature was intended for Grid
invalidateCellSizeAfterRender({ rowIndex: index }) {
if (internals.invalidateOnUpdateStartIndex === null) {
internals.invalidateOnUpdateStartIndex = index;
internals.invalidateOnUpdateStopIndex = index;
} else {
internals.invalidateOnUpdateStartIndex = Math.min(
internals.invalidateOnUpdateStartIndex,
index
);
internals.invalidateOnUpdateStopIndex = Math.max(
internals.invalidateOnUpdateStopIndex,
index
);
}
forceUpdate();
},
recomputeCellPositions() {
const { cellCount, cellMeasurerCache, cellPositioner } = internals.latest;
const stopIndex = Math.min(internals.positionCache.count, cellCount) - 1;
const positionCache = new PositionCache();
populatePositionCache(
positionCache,
cellMeasurerCache,
cellPositioner,
0,
stopIndex
);
internals.positionCache = positionCache;
forceUpdate();
},
recomputeGridSize() {
forceUpdate();
}
};
const setElementRef = (element) => {
internals.element = element;
};
return { handle, internals, linkTarget, onScroll: onScroll2, setElementRef };
}
const defaultMultiGridProps = /* @__PURE__ */ Object.freeze({
classNameBottomLeftGrid: "",
classNameBottomRightGrid: "",
classNameTopLeftGrid: "",
classNameTopRightGrid: "",
enableFixedColumnScroll: false,
enableFixedRowScroll: false,
fixedColumnCount: 0,
fixedRowCount: 0,
hideBottomLeftGridScrollbar: false,
hideTopRightGridScrollbar: false,
style: /* @__PURE__ */ Object.freeze({}),
styleBottomLeftGrid: /* @__PURE__ */ Object.freeze({}),
styleBottomRightGrid: /* @__PURE__ */ Object.freeze({}),
styleTopLeftGrid: /* @__PURE__ */ Object.freeze({}),
styleTopRightGrid: /* @__PURE__ */ Object.freeze({})
});
class CellMeasurerCacheDecorator {
_cellMeasurerCache;
_columnIndexOffset;
_rowIndexOffset;
constructor(params = {}) {
const {
cellMeasurerCache,
columnIndexOffset = 0,
rowIndexOffset = 0
} = params;
this._cellMeasurerCache = cellMeasurerCache;
this._columnIndexOffset = columnIndexOffset;
this._rowIndexOffset = rowIndexOffset;
}
clear(rowIndex, columnIndex) {
this._cellMeasurerCache.clear(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset
);
}
clearAll() {
this._cellMeasurerCache.clearAll();
}
columnWidth = ({ index }) => {
return this._cellMeasurerCache.columnWidth({
index: index + this._columnIndexOffset
});
};
get defaultHeight() {
return this._cellMeasurerCache.defaultHeight;
}
get defaultWidth() {
return this._cellMeasurerCache.defaultWidth;
}
hasFixedHeight() {
return this._cellMeasurerCache.hasFixedHeight();
}
hasFixedWidth() {
return this._cellMeasurerCache.hasFixedWidth();
}
getHeight(rowIndex, columnIndex = 0) {
return this._cellMeasurerCache.getHeight(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset
);
}
getWidth(rowIndex, columnIndex = 0) {
return this._cellMeasurerCache.getWidth(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset
);
}
has(rowIndex, columnIndex = 0) {
return this._cellMeasurerCache.has(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset
);
}
rowHeight = ({ index }) => {
return this._cellMeasurerCache.rowHeight({
index: index + this._rowIndexOffset
});
};
set(rowIndex, columnIndex, width, height) {
this._cellMeasurerCache.set(
rowIndex + this._rowIndexOffset,
columnIndex + this._columnIndexOffset,
width,
height
);
}
}
const SCROLLBAR_SIZE_BUFFER = 20;
const INITIAL_SCROLLBAR_STATE = {
scrollbarSize: 0,
showHorizontalScrollbar: false,
showVerticalScrollbar: false
};
const increment = (value) => value + 1;
function isNumericSizeChange(prevSize, nextSize) {
return (typeof prevSize === "number" || typeof nextSize === "number") && prevSize !== nextSize;
}
function getFixedCellsSize(size, count) {
if (typeof size === "function") {
let total = 0;
for (let index = 0; index < count; index++) {
total += size({ index });
}
return total;
}
return size * count;
}
function createMultiGridInstance(initialLatest, setScrollbarState, forceUpdate) {
const internals = {
bottomLeftGrid: null,
bottomRightGrid: null,
topLeftGrid: null,
topRightGrid: null,
committedSizes: null,
deferredInvalidateColumnIndex: null,
deferredInvalidateRowIndex: null,
latest: initialLatest,
scrollbarState: INITIAL_SCROLLBAR_STATE,
scrollLeft: 0,
scrollTop: 0
};
const recomputeGrids = (columnIndex, rowIndex) => {
const { fixedColumnCount, fixedRowCount } = internals.latest;
const adjustedColumnIndex = Math.max(0, columnIndex - fixedColumnCount);
const adjustedRowIndex = Math.max(0, rowIndex - fixedRowCount);
internals.bottomLeftGrid?.recomputeGridSize({
columnIndex,
rowIndex: adjustedRowIndex
});
internals.bottomRightGrid?.recomputeGridSize({
columnIndex: adjustedColumnIndex,
rowIndex: adjustedRowIndex
});
internals.topLeftGrid?.recomputeGridSize({
columnIndex,
rowIndex
});
internals.topRightGrid?.recomputeGridSize({
columnIndex: adjustedColumnIndex,
rowIndex
});
};
const syncFixedGridScrollPositions = () => {
const { scrollLeft, scrollTop } = internals;
internals.topRightGrid?.scrollToPosition({ scrollLeft });
internals.bottomLeftGrid?.scrollToPosition({ scrollTop });
};
const handle = {
forceUpdateGrids() {
internals.bottomLeftGrid?.forceUpdate();
internals.bottomRightGrid?.forceUpdate();
internals.topLeftGrid?.forceUpdate();
internals.topRightGrid?.forceUpdate();
},
invalidateCellSizeAfterRender({ columnIndex = 0, rowIndex = 0 } = {}) {
internals.deferredInvalidateColumnIndex = typeof internals.deferredInvalidateColumnIndex === "number" ? Math.min(internals.deferredInvalidateColumnIndex, columnIndex) : columnIndex;
internals.deferredInvalidateRowIndex = typeof internals.deferredInvalidateRowIndex === "number" ? Math.min(internals.deferredInvalidateRowIndex, rowIndex) : rowIndex;
forceUpdate();
},
measureAllCells() {
internals.bottomLeftGrid?.measureAllCells();
internals.bottomRightGrid?.measureAllCells();
internals.topLeftGrid?.measureAllCells();
internals.topRightGrid?.measureAllCells();
},
recomputeGridSize({ columnIndex = 0, rowIndex = 0 } = {}) {
recomputeGrids(columnIndex, rowIndex);
forceUpdate();
},
scrollToCell({ align, columnIndex, rowIndex }) {
const { fixedColumnCount, fixedRowCount } = internals.latest;
const adjustedColumnIndex = columnIndex !== void 0 && columnIndex >= fixedColumnCount ? columnIndex - fixedColumnCount : void 0;
const adjustedRowIndex = rowIndex !== void 0 && rowIndex >= fixedRowCount ? rowIndex - fixedRowCount : void 0;
internals.bottomRightGrid?.scrollToCell({
align,
columnIndex: adjustedColumnIndex,
rowIndex: adjustedRowIndex
});
},
scrollToPosition({ scrollLeft, scrollTop }) {
internals.bottomRightGrid?.scrollToPosition({ scrollLeft, scrollTop });
}
};
const onCommit = (columnWidth, rowHeight) => {
const committedSizes = internals.committedSizes;
internals.committedSizes = { columnWidth, rowHeight };
if (committedSizes !== null && (isNumericSizeChange(committedSizes.columnWidth, columnWidth) || isNumericSizeChange(committedSizes.rowHeight, rowHeight))) {
recomputeGrids(0, 0);
}
if (typeof internals.deferredInvalidateColumnIndex === "number") {
const columnIndex = internals.deferredInvalidateColumnIndex;
const rowIndex = internals.deferredInvalidateRowIndex;
internals.deferredInvalidateColumnIndex = null;
internals.deferredInvalidateRowIndex = null;
handle.recomputeGridSize({ columnIndex, rowIndex });
}
syncFixedGridScrollPositions();
};
const onScroll2 = (scrollInfo) => {
const { scrollLeft, scrollTop } = scrollInfo;
internals.scrollLeft = scrollLeft;
internals.scrollTop = scrollTop;
syncFixedGridScrollPositions();
const { onScroll: onScroll22 } = internals.latest;
if (onScroll22) {
onScroll22(scrollInfo);
}
};
const onScrollbarPresenceChange = ({
horizontal,
size,
vertical
}) => {
const { showHorizontalScrollbar, showVerticalScrollbar } = internals.scrollbarState;
if (horizontal !== showHorizontalScrollbar || vertical !== showVerticalScrollbar) {
const scrollbarState = {
scrollbarSize: size,
showHorizontalScrollbar: horizontal,
showVerticalScrollbar: vertical
};
internals.scrollbarState = scrollbarState;
setScrollbarState(scrollbarState);
const { onScrollbarPresenceChange: onScrollbarPresenceChange2 } = internals.latest;
if (typeof onScrollbarPresenceChange2 === "function") {
onScrollbarPresenceChange2({
horizontal,
size,
vertical
});
}
}
};
const onScrollLeft = ({ scrollLeft }) => {
internals.bottomRightGrid?.scrollToPosition({ scrollLeft });
onScroll2({
scrollLeft,
scrollTop: internals.scrollTop
});
};
const onScrollTop = ({ scrollTop }) => {
internals.bottomRightGrid?.scrollToPosition({ scrollTop });
onScroll2({
scrollLeft: internals.scrollLeft,
scrollTop
});
};
return {
handle,
internals,
onCommit,
onScroll: onScroll2,
onScrollbarPresenceChange,
onScrollLeft,
onScrollTop,
setBottomLeftGrid: (grid) => {
internals.bottomLeftGrid = grid;
},
setBottomRightGrid: (grid) => {
internals.bottomRightGrid = grid;
},
setTopLeftGrid: (grid) => {
internals.topLeftGrid = grid;
},
setTopRightGrid: (grid) => {
internals.topRightGrid = grid;
}
};
}
function createDeferredMeasurementCaches(deferredMeasurementCache, fixedColumnCount, fixedRowCount) {
if (!deferredMeasurementCache) {
return {
bottomLeftGrid: void 0,
bottomRightGrid: void 0,
topRightGrid: void 0
};
}
const cellMeasurerCache = deferredMeasurementCache;
return {
bottomLeftGrid: fixedRowCount > 0 ? new CellMeasurerCacheDecorator({
cellMeasurerCache,
columnIndexOffset: 0,
rowIndexOffset: fixedRowCount
}) : deferredMeasurementCache,
bottomRightGrid: fixedColumnCount > 0 || fixedRowCount > 0 ? new CellMeasurerCacheDecorator({
cellMeasurerCache,
columnIndexOffset: fixedColumnCount,
rowIndexOffset: fixedRowCount
}) : deferredMeasurementCache,
topRightGrid: fixedColumnCount > 0 ? new CellMeasurerCacheDecorator({
cellMeasurerCache,
columnIndexOffset: fixedColumnCount,
rowIndexOffset: 0
}) : deferredMeasurementCache
};
}
const MultiGrid = /* @__PURE__ */ react.memo(
/* @__PURE__ */ react.forwardRef(
function MultiGrid2(props, ref) {
const {
cellRenderer,
classNameBottomLeftGrid = defaultMultiGridProps.classNameBottomLeftGrid,
classNameBottomRightGrid = defaultMultiGridProps.classNameBottomRightGrid,
classNameTopLeftGrid = defaultMultiGridProps.classNameTopLeftGrid,
classNameTopRightGrid = defaultMultiGridProps.classNameTopRightGrid,
columnCount,
columnWidth,
deferredMeasurementCache,
enableFixedColumnScroll = defaultMultiGridProps.enableFixedColumnScroll,
enableFixedRowScroll = defaultMultiGridProps.enableFixedRowScroll,
fixedColumnCount = defaultMultiGridProps.fixedColumnCount,
fixedRowCount = defaultMultiGridProps.fixedRowCount,
height,
hideBottomLeftGridScrollbar = defaultMultiGridProps.hideBottomLeftGridScrollbar,
hideTopRightGridScrollbar = defaultMultiGridProps.hideTopRightGridScrollbar,
// The initial offsets only apply to the quadrants that scroll along the corresponding axis
initialScrollLeft,
initialScrollTop,
onScroll: onScroll2,
onScrollbarPresenceChange,
onSectionRendered,
rowCount,
rowHeight,
style = defaultMultiGridProps.style,
styleBottomLeftGrid = defaultMultiGridProps.styleBottomLeftGrid,
styleBottomRightGrid = defaultMultiGridProps.styleBottomRightGrid,
styleTopLeftGrid = defaultMultiGridProps.styleTopLeftGrid,
styleTopRightGrid = defaultMultiGridProps.styleTopRightGrid,
width,
// The remaining (Grid) props are relayed to all of the inner Grids
...gridProps
} = props;
const [layoutVersion, forceUpdate] = react.useReducer(increment, 0);
const [scrollbarState, setScrollbarState] = react.useState(
INITIAL_SCROLLBAR_STATE
);
const latest = {
fixedColumnCount,
fixedRowCount,
onScroll: onScroll2,
onScrollbarPresenceChange
};
const [
{
handle,
internals,
onCommit,
onScroll: onScrollBottomRightGrid,
onScrollbarPresenceChange: onScrollbarPresenceChangeBottomRightGrid,
onScrollLeft,
onScrollTop,
setBottomLeftGrid,
setBottomRightGrid,
setTopLeftGrid,
setTopRightGrid
}
] = react.useState(
() => createMultiGridInstance(latest, setScrollbarState, forceUpdate)
);
react.useImperativeHandle(ref, () => handle, [handle]);
react.useInsertionEffect(() => {
internals.latest = latest;
});
const { scrollbarSize: scrollbarSize2, showHorizontalScrollbar, showVerticalScrollbar } = scrollbarState;
const leftGridWidth = react.useMemo(
() => getFixedCellsSize(columnWidth, fixedColumnCount),
// eslint-disable-next-line react-hooks/exhaustive-deps
[columnWidth, fixedColumnCount, layoutVersion]
);
const topGridHeight = react.useMemo(
() => getFixedCellsSize(rowHeight, fixedRowCount),
// eslint-disable-next-line react-hooks/exhaustive-deps
[rowHeight, fixedRowCount, layoutVersion]
);
const bottomGridHeight = height - topGridHeight;
const rightGridWidth = width - leftGridWidth;
const additionalRowCount = showHorizontalScrollbar ? 1 : 0;
const additionalColumnCount = showVerticalScrollbar ? 1 : 0;
const containerOuterStyle = react.useMemo(
() => ({
height,
overflow: "visible",
// Let :focus outline show through
width,
...style
}),
[height, style, width]
);
const containerTopStyle = react.useMemo(
() => ({
height: topGridHeight,
position: "relative",
width
}),
[topGridHeight, width]
);
const containerBottomStyle = react.useMemo(
() => ({
height: bottomGridHeight,
overflow: "visible",
// Let :focus outline show through
position: "relative",
width
}),
[bottomGridHeight, width]
);
const bottomLeftGridStyle = react.useMemo(
() => ({
left: 0,
overflowX: "hidden",
overflowY: enableFixedColumnScroll ? "auto" : "hidden",
position: "absolute",
...styleBottomLeftGrid
}),
[enableFixedColumnScroll, styleBottomLeftGrid]
);
const bottomRightGridStyle = react.useMemo(
() => ({
left: leftGridWidth,
position: "absolute",
...styleBottomRightGrid
}),
[leftGridWidth, styleBottomRightGrid]
);
const topLeftGridStyle = react.useMemo(
() => ({
left: 0,
overflowX: "hidden",
overflowY: "hidden",
position: "absolute",
top: 0,
...styleTopLeftGrid
}),
[styleTopLeftGrid]
);
const topRightGridStyle = react.useMemo(
() => ({
left: leftGridWidth,
overflowX: enableFixedRowScroll ? "auto" : "hidden",
overflowY: "hidden",
position: "absolute",
top: 0,
...styleTopRightGrid
}),
[enableFixedRowScroll, leftGridWidth, styleTopRightGrid]
);
const topRightGridInnerStyle = react.useMemo(
() => hideTopRightGridScrollbar ? { ...topRightGridStyle, left: 0 } : topRightGridStyle,
[hideTopRightGridScrollbar, topRightGridStyle]
);
const deferredMeasurementCaches = react.useMemo(
() => createDeferredMeasurementCaches(
deferredMeasurementCache,
fixedColumnCount,
fixedRowCount
),
[deferredMeasurementCache, fixedColumnCount, fixedRowCount]
);
const columnWidthRightGrid = react.useCallback(
({ index }) => {
if (showVerticalScrollbar && index === columnCount - fixedColumnCount) {
return scrollbarSize2;
}
return typeof columnWidth === "function" ? columnWidth({ index: index + fixedColumnCount }) : columnWidth;
},
[
columnCount,
columnWidth,
fixedColumnCount,
scrollbarSize2,
showVerticalScrollbar
]
);
const rowHeightBottomGrid = react.useCallback(
({ index }) => {
if (showHorizontalScrollbar && index === rowCount - fixedRowCount) {
return scrollbarSize2;
}
return typeof rowHeight === "function" ? rowHeight({ index: index + fixedRowCount }) : rowHeight;
},
[
fixedRowCount,
rowCount,
rowHeight,
scrollbarSize2,
showHorizontalScrollbar
]
);
const cellRendererTopLeftGrid = react.useCallback(
(params) => cellRenderer({
...params,
// Bug #21: like the other quadrants (rather than the inner Grid)
parent: handle
}),
[cellRenderer, handle]
);
const cellRendererTopRightGrid = react.useCallback(
({ columnIndex, ...rest }) => {
if (columnIndex === columnCount - fixedColumnCount) {
return /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
style: {
...rest.style,
width: SCROLLBAR_SIZE_BUFFER
}
},
rest.key
);
} else {
return cellRenderer({
...rest,
columnIndex: columnIndex + fixedColumnCount,
parent: handle
});
}
},
[cellRenderer, columnCount, fixedColumnCount, handle]
);
const cellRendererBottomLeftGrid = react.useCallback(
({ rowIndex, ...rest }) => {
if (rowIndex === rowCount - fixedRowCount) {
return /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
style: {
...rest.style,
height: SCROLLBAR_SIZE_BUFFER
}
},
rest.key
);
} else {
return cellRenderer({
...rest,
parent: handle,
rowIndex: rowIndex + fixedRowCount
});
}
},
[cellRenderer, fixedRowCount, handle, rowCount]
);
const cellRendererBottomRightGrid = react.useCallback(
({ columnIndex, rowIndex, ...rest }) => cellRenderer({
...rest,
columnIndex: columnIndex + fixedColumnCount,
parent: handle,
rowIndex: rowIndex + fixedRowCount
}),
[cellRenderer, fixedColumnCount, fixedRowCount, handle]
);
useIsomorphicLayoutEffect(() => {
onCommit(columnWidth, rowHeight);
});
if (width === 0 || height === 0) {
return null;
}
let topLeftGrid = null;
if (fixedColumnCount && fixedRowCount) {
topLeftGrid = /* @__PURE__ */ jsxRuntime.jsx(
Grid,
{
...gridProps,
cellRenderer: cellRendererTopLeftGrid,
className: classNameTopLeftGrid,
columnCount: fixedColumnCount,
columnWidth,
deferredMeasurementCache,
height: topGridHeight,
ref: setTopLeftGrid,
rowCount: fixedRowCount,
rowHeight,
style: topLeftGridStyle,
tabIndex: null,
width: leftGridWidth
}
);
}
let topRightGrid = null;
if (fixedRowCount) {
const additionalHeight = showHorizontalScrollbar ? scrollbarSize2 : 0;
topRightGrid = /* @__PURE__ */ jsxRuntime.jsx(
Grid,
{
...gridProps,
cellRenderer: cellRendererTopRightGrid,
className: classNameTopRightGrid,
columnCount: Math.max(0, columnCount - fixedColumnCount) + additionalColumnCount,
columnWidth: columnWidthRightGrid,
deferredMeasurementCache: deferredMeasurementCaches.topRightGrid,
height: hideTopRightGridScrollbar ? topGridHeight + additionalHeight : topGridHeight,
initialScrollLeft,
onScroll: enableFixedRowScroll ? onScrollLeft : void 0,
ref: setTopRightGrid,
rowCount: fixedRowCount,
rowHeight,
style: topRightGridInnerStyle,
tabIndex: null,
width: rightGridWidth
}
);
if (hideTopRightGridScrollbar) {
topRightGrid = /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: "TopRightGrid_ScrollWrapper",
style: {
...topRightGridStyle,
height: topGridHeight,
width: rightGridWidth,
overflowX: "hidden"
},
children: topRightGrid
}
);
}
}
let bottomLeftGrid = null;
if (fixedColumnCount) {
const additionalWidth = showVerticalScrollbar ? scrollbarSize2 : 0;
bottomLeftGrid = /* @__PURE__ */ jsxRuntime.jsx(
Grid,
{
...gridProps,
cellRenderer: cellRendererBottomLeftGrid,
className: classNameBottomLeftGrid,
columnCount: fixedColumnCount,
columnWidth,
deferredMeasurementCache: deferredMeasurementCaches.bottomLeftGrid,
height: bottomGridHeight,
initialScrollTop,
onScroll: enableFixedColumnScroll ? onScrollTop : void 0,
ref: setBottomLeftGrid,
rowCount: Math.max(0, rowCount - fixedRowCount) + additionalRowCount,
rowHeight: rowHeightBottomGrid,
style: bottomLeftGridStyle,
tabIndex: null,
width: hideBottomLeftGridScrollbar ? leftGridWidth + additionalWidth : leftGridWidth
}
);
if (hideBottomLeftGridScrollbar) {
bottomLeftGrid = /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
className: "BottomLeftGrid_ScrollWrapper",
style: {
...bottomLeftGridStyle,
height: bottomGridHeight,
width: leftGridWidth,
overflowY: "hidden"
},
children: bottomLeftGrid
}
);
}
}
const bottomRightGrid = /* @__PURE__ */ jsxRuntime.jsx(
Grid,
{
...gridProps,
cellRenderer: cellRendererBottomRightGrid,
className: classNameBottomRightGrid,
columnCount: Math.max(0, columnCount - fixedColumnCount),
columnWidth: columnWidthRightGrid,
deferredMeasurementCache: deferredMeasurementCaches.bottomRightGrid,
height: bottomGridHeight,
initialScrollLeft,
initialScrollTop,
onScroll: onScrollBottomRightGrid,
onScrollbarPresenceChange: onScrollbarPresenceChangeBottomRightGrid,
onSectionRendered,
ref: setBottomRightGrid,
rowCount: Math.max(0, rowCount - fixedRowCount),
rowHeight: rowHeightBottomGrid,
style: bottomRightGridStyle,
width: rightGridWidth
}
);
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerOuterStyle, children: [
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerTopStyle, children: [
topLeftGrid,
topRightGrid
] }),
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerBottomStyle, children: [
bottomLeftGrid,
bottomRightGrid
] })
] });
}
)
);
const INITIAL_STATE = {
clientHeight: 0,
clientWidth: 0,
scrollHeight: 0,
scrollLeft: 0,
scrollTop: 0,
scrollWidth: 0
};
const ScrollSync = /* @__PURE__ */ react.memo(function ScrollSync2({
children
}) {
const [state, setState] = react.useState(INITIAL_STATE);
const childrenRef = react.useRef(/* @__PURE__ */ new Map());
const refCallbacksRef = react.useRef(/* @__PURE__ */ new Map());
const lastRegisteredRef = react.useRef(/* @__PURE__ */ new Map());
const syncedRef = react.useRef({ scrollLeft: 0, scrollTop: 0 });
const hasSyncedRef = react.useRef(false);
const onScroll2 = react.useCallback((params) => {
const synced = syncedRef.current;
const hasSynced = hasSyncedRef.current;
if (hasSynced && params.scrollLeft === synced.scrollLeft && params.scrollTop === synced.scrollTop) {
return;
}
const isClamped = (offset, syncedOffset, scrollSize, clientSize) => hasSynced && offset < syncedOffset && offset >= scrollSize - clientSize;
const leftChanged = typeof params.scrollLeft === "number" && params.scrollLeft !== synced.scrollLeft && !isClamped(
params.scrollLeft,
synced.scrollLeft,
params.scrollWidth,
params.clientWidth
);
const topChanged = typeof params.scrollTop === "number" && params.scrollTop !== synced.scrollTop && !isClamped(
params.scrollTop,
synced.scrollTop,
params.scrollHeight,
params.clientHeight
);
if (hasSynced && !leftChanged && !topChanged) {
return;
}
const scrollLeft = leftChanged ? params.scrollLeft : synced.scrollLeft;
const scrollTop = topChanged ? params.scrollTop : synced.scrollTop;
syncedRef.current = { scrollLeft, scrollTop };
setState({
clientHeight: params.clientHeight,
clientWidth: params.clientWidth,
scrollHeight: params.scrollHeight,
scrollLeft,
scrollTop,
scrollWidth: params.scrollWidth
});
if (leftChanged || topChanged) {
const position = {};
if (leftChanged) {
position.scrollLeft = scrollLeft;
}
if (topChanged) {
position.scrollTop = scrollTop;
}
childrenRef.current.forEach((child) => {
hasSyncedRef.current = true;
child.scrollToPosition(position);
});
}
}, []);
const registerChild = react.useCallback((key) => {
let refCallback = refCallbacksRef.current.get(key);
if (!refCallback) {
refCallback = (child) => {
const map = childrenRef.current;
if (child) {
if (typeof child.scrollToPosition !== "function") {
throw Error(
"Unexpected child type registered; only components with a scrollToPosition() method (e.g. Grid) are supported."
);
}
map.set(key, child);
const isNewChild = lastRegisteredRef.current.get(key) !== child;
lastRegisteredRef.current.set(key, child);
const { scrollLeft, scrollTop } = syncedRef.current;
if (isNewChild && (scrollLeft !== 0 || scrollTop !== 0)) {
hasSyncedRef.current = true;
child.scrollToPosition({ scrollLeft, scrollTop });
}
return () => {
if (map.get(key) === child) {
map.delete(key);
}
};
} else {
map.delete(key);
}
};
refCallbacksRef.current.set(key, refCallback);
}
return refCallback;
}, []);
const childProps = react.useMemo(
() => ({ ...state, onScroll: onScroll2, registerChild }),
[onScroll2, registerChild, state]
);
return children(childProps);
});
function Column(props) {
return null;
}
function createMultiSort(sortCallback, { defaultSortBy, defaultSortDirection = {} } = {}) {
if (!sortCallback) {
throw Error(`Required parameter "sortCallback" not specified`);
}
let sortBy = defaultSortBy ? [...defaultSortBy] : [];
let sortDirection = {};
sortBy.forEach((dataKey) => {
sortDirection[dataKey] = defaultSortDirection[dataKey] !== void 0 ? defaultSortDirection[dataKey] : "ASC";
});
const toggle = (direction) => direction === "ASC" ? "DESC" : "ASC";
function sort({
defaultSortDirection: defaultSortDirection2,
event,
sortBy: dataKey
}) {
if (event.shiftKey) {
if (sortDirection[dataKey] !== void 0) {
sortDirection = {
...sortDirection,
[dataKey]: toggle(sortDirection[dataKey])
};
} else {
sortBy = [...sortBy, dataKey];
sortDirection = { ...sortDirection, [dataKey]: defaultSortDirection2 };
}
} else if (event.ctrlKey || event.metaKey) {
if (sortBy.includes(dataKey)) {
sortBy = sortBy.filter((key) => key !== dataKey);
sortDirection = { ...sortDirection };
delete sortDirection[dataKey];
}
} else {
sortDirection = {
[dataKey]: sortDirection[dataKey] !== void 0 ? toggle(sortDirection[dataKey]) : defaultSortDirection2
};
sortBy = [dataKey];
}
sortCallback({
sortBy,
sortDirection
});
}
return {
sort,
// (Getters, since the sort criteria are replaced when they change)
get sortBy() {
return sortBy;
},
get sortDirection() {
return sortDirection;
}
};
}
function defaultCellDataGetter({
dataKey,
rowData
}) {
if (typeof rowData.get === "function") {
return rowData.get(dataKey);
} else {
return rowData[dataKey];
}
}
function defaultCellRenderer({
cellData
}) {
if (cellData == null) {
return "";
} else {
return String(cellData);
}
}
const SortDirection = {
/**
* Sort items in ascending order.
* This means arranging from the lowest value to the highest (e.g. a-z, 0-9).
*/
ASC: "ASC",
/**
* Sort items in descending order.
* This means arranging from the highest value to the lowest (e.g. z-a, 9-0).
*/
DESC: "DESC"
};
function SortIndicator({ sortDirection }) {
const classNames = clsx("ReactVirtualized__Table__sortableHeaderIcon", {
"ReactVirtualized__Table__sortableHeaderIcon--ASC": sortDirection === SortDirection.ASC,
"ReactVirtualized__Table__sortableHeaderIcon--DESC": sortDirection === SortDirection.DESC
});
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className: classNames, width: 18, height: 18, viewBox: "0 0 24 24", children: [
sortDirection === SortDirection.ASC ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 14l5-5 5 5z" }) : /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 10l5 5 5-5z" }),
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M0 0h24v24H0z", fill: "none" })
] });
}
function defaultHeaderRenderer({
dataKey,
label,
sortBy,
sortDirection
}) {
const showSortIndicator = sortBy === dataKey;
const children = [
/* @__PURE__ */ jsxRuntime.jsx(
"span",
{
className: "ReactVirtualized__Table__headerTruncatedText",
title: typeof label === "string" ? label : null,
children: label
},
"label"
)
];
if (showSortIndicator) {
children.push(
/* @__PURE__ */ jsxRuntime.jsx(SortIndicator, { sortDirection }, "SortIndicator")
);
}
return children;
}
const defaultColumnProps = /* @__PURE__ */ Object.freeze({
cellDataGetter: defaultCellDataGetter,
cellRenderer: defaultCellRenderer,
defaultSortDirection: SortDirection.ASC,
flexGrow: 0,
flexShrink: 1,
headerRenderer: defaultHeaderRenderer,
style: /* @__PURE__ */ Object.freeze({})
});
function defaultHeaderRowRenderer({
className,
columns,
style
}) {
return /* @__PURE__ */ jsxRuntime.jsx("div", { className, role: "row", style, children: columns });
}
function defaultRowRenderer({
className,
columns,
index,
key,
onRowClick,
onRowDoubleClick,
onRowMouseOut,
onRowMouseOver,
onRowRightClick,
rowData,
style
}) {
const a11yProps = {
"aria-rowindex": index + 1
};
if (onRowClick || onRowDoubleClick || onRowMouseOut || onRowMouseOver || onRowRightClick) {
a11yProps["aria-label"] = "row";
a11yProps.tabIndex = 0;
if (onRowClick) {
a11yProps.onClick = (event) => onRowClick({ event, index, rowData });
}
if (onRowDoubleClick) {
a11yProps.onDoubleClick = (event) => onRowDoubleClick({ event, index, rowData });
}
if (onRowMouseOut) {
a11yProps.onMouseOut = (event) => onRowMouseOut({ event, index, rowData });
}
if (onRowMouseOver) {
a11yProps.onMouseOver = (event) => onRowMouseOver({ event, index, rowData });
}
if (onRowRightClick) {
a11yProps.onContextMenu = (event) => onRowRightClick({ event, index, rowData });
}
}
return /* @__PURE__ */ react.createElement(
"div",
{
...a11yProps,
className,
key,
role: "row",
style
},
columns
);
}
const defaultTableProps = /* @__PURE__ */ Object.freeze({
disableHeader: false,
estimatedRowSize: 30,
headerHeight: 0,
headerRowRenderer: defaultHeaderRowRenderer,
headerStyle: /* @__PURE__ */ Object.freeze({}),
noRowsRenderer: () => null,
onRowsRendered: () => null,
onScroll: () => null,
overscanIndicesGetter: accessibilityOverscanIndicesGetter,
overscanRowCount: 10,
rowRenderer: defaultRowRenderer,
rowStyle: /* @__PURE__ */ Object.freeze({}),
style: /* @__PURE__ */ Object.freeze({})
});
function getColumnProps(child) {
const props = react.isValidElement(child) ? child.props : {};
const resolved = { ...props };
for (const key in defaultColumnProps) {
if (resolved[key] === void 0) {
resolved[key] = defaultColumnProps[key];
}
}
return resolved;
}
function getFlexStyleForColumn(column, customStyle = {}) {
const flexValue = `${column.flexGrow} ${column.flexShrink} ${column.width}px`;
const style = {
...customStyle,
flex: flexValue,
msFlex: flexValue,
WebkitFlex: flexValue
};
if (column.maxWidth) {
style.maxWidth = column.maxWidth;
}
if (column.minWidth) {
style.minWidth = column.minWidth;
}
return style;
}
function createTableInstance(latest) {
const internals = {
gridElement: null,
innerGrid: createInnerGridRef(),
latest
};
const { getGrid } = internals.innerGrid;
const handle = {
forceUpdateGrid() {
getGrid()?.forceUpdate();
},
getOffsetForRow({ align, alignment, index } = {}) {
const grid = getGrid();
if (grid) {
const { scrollTop } = grid.getOffsetForCell({
alignment: align ?? alignment,
rowIndex: index
});
return scrollTop;
}
return 0;
},
getScrollbarWidth() {
const element = internals.gridElement;
if (element) {
const clientWidth = element.clientWidth || 0;
const offsetWidth = element.offsetWidth || 0;
return offsetWidth - clientWidth;
}
return 0;
},
invalidateCellSizeAfterRender({ columnIndex, rowIndex }) {
internals.innerGrid.invalidateCellSizeAfterRender({
columnIndex,
rowIndex
});
},
measureAllRows() {
getGrid()?.measureAllCells();
},
recomputeGridSize({ columnIndex = 0, rowIndex = 0 } = {}) {
internals.innerGrid.recomputeGridSize({ columnIndex, rowIndex });
},
recomputeRowHeights(index = 0) {
internals.innerGrid.recomputeGridSize({
columnIndex: 0,
rowIndex: index
});
},
scrollToCell({ align, columnIndex, rowIndex }) {
getGrid()?.scrollToCell({ align, columnIndex, rowIndex });
},
scrollToPosition({ scrollTop }) {
getGrid()?.scrollToPosition({ scrollTop });
},
scrollToRow({ align, index }) {
getGrid()?.scrollToCell({ align, columnIndex: 0, rowIndex: index });
}
};
const onScroll2 = ({ clientHeight, scrollHeight, scrollTop }) => {
internals.latest.onScroll({ clientHeight, scrollHeight, scrollTop });
};
const onSectionRendered = ({
rowOverscanStartIndex,
rowOverscanStopIndex,
rowStartIndex,
rowStopIndex
}) => {
internals.latest.onRowsRendered({
overscanStartIndex: rowOverscanStartIndex,
overscanStopIndex: rowOverscanStopIndex,
startIndex: rowStartIndex,
stopIndex: rowStopIndex
});
};
const setGridRef = internals.innerGrid.setGridRef;
const setGridElementRef = (element) => {
internals.gridElement = element;
};
return {
handle,
internals,
onScroll: onScroll2,
onSectionRendered,
setGridElementRef,
setGridRef
};
}
const Table = /* @__PURE__ */ react.memo(
/* @__PURE__ */ react.forwardRef(
function Table2(props, ref) {
const {
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
children,
className,
disableHeader = defaultTableProps.disableHeader,
estimatedRowSize = defaultTableProps.estimatedRowSize,
gridClassName,
gridStyle,
headerClassName,
headerHeight = defaultTableProps.headerHeight,
headerRowRenderer = defaultTableProps.headerRowRenderer,
headerStyle = defaultTableProps.headerStyle,
height,
id,
noRowsRenderer = defaultTableProps.noRowsRenderer,
onColumnClick,
onHeaderClick,
onRowClick,
onRowDoubleClick,
onRowMouseOut,
onRowMouseOver,
onRowRightClick,
onRowsRendered = defaultTableProps.onRowsRendered,
onScroll: onScroll2 = defaultTableProps.onScroll,
overscanIndicesGetter = defaultTableProps.overscanIndicesGetter,
overscanRowCount = defaultTableProps.overscanRowCount,
rowClassName,
rowCount,
rowGetter,
rowHeight,
rowRenderer = defaultTableProps.rowRenderer,
rowStyle = defaultTableProps.rowStyle,
scrollElement,
sort,
sortBy,
sortDirection,
style = defaultTableProps.style,
width
} = props;
const [scrollbarWidth, setScrollbarWidth] = react.useState(0);
const [
{
handle,
internals,
onScroll: onGridScroll,
onSectionRendered,
setGridElementRef,
setGridRef
}
] = react.useState(() => createTableInstance({ onRowsRendered, onScroll: onScroll2 }));
react.useImperativeHandle(ref, () => handle, [handle]);
useMissingHeightWarning("Table", height, scrollElement);
react.useInsertionEffect(() => {
internals.latest = { onRowsRendered, onScroll: onScroll2 };
});
useIsomorphicLayoutEffect(() => {
setScrollbarWidth(handle.getScrollbarWidth());
});
const [columns, columnKeys] = react.useMemo(() => {
const columnElements = react.Children.toArray(children);
return [
columnElements.map(getColumnProps),
columnElements.map(
(child, index) => react.isValidElement(child) && child.key !== null ? String(child.key) : String(index)
)
];
}, [children]);
const cachedColumnStyles = react.useMemo(
() => columns.map(
(column) => ({
overflow: "hidden",
...getFlexStyleForColumn(
column,
column.style || defaultColumnProps.style
)
})
),
[columns]
);
const createRow = react.useCallback(
({
rowIndex: index,
isScrolling,
key,
style: cellStyle
}) => {
const rowClass2 = typeof rowClassName === "function" ? rowClassName({ index }) : rowClassName;
const rowStyleObject2 = typeof rowStyle === "function" ? rowStyle({ index }) : rowStyle;
const rowData = rowGetter({ index });
const renderedColumns = columns.map((column, columnIndex) => {
const {
cellDataGetter,
cellRenderer,
className: columnClassName,
columnData,
dataKey,
id: columnId
} = column;
const cellData = cellDataGetter({ columnData, dataKey, rowData });
const renderedCell = cellRenderer({
cellData,
columnData,
columnIndex,
dataKey,
isScrolling,
// CellMeasurer interop: the Table handle delegates to the inner Grid
parent: handle,
rowData,
rowIndex: index
});
const onClick = (event) => {
if (onColumnClick) {
onColumnClick({ columnData, dataKey, event });
}
};
const title = typeof renderedCell === "string" ? renderedCell : null;
return /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
"aria-colindex": columnIndex + 1,
"aria-describedby": columnId,
className: clsx(
"ReactVirtualized__Table__rowColumn",
columnClassName
),
onClick,
role: "gridcell",
style: cachedColumnStyles[columnIndex],
title,
children: renderedCell
},
"Row" + index + "-Col" + columnKeys[columnIndex]
);
});
const flattenedStyle = {
...cellStyle,
height: typeof rowHeight === "function" ? rowHeight({ index }) : rowHeight,
overflow: "hidden",
paddingRight: scrollbarWidth,
...rowStyleObject2
};
return rowRenderer({
className: clsx("ReactVirtualized__Table__row", rowClass2),
columns: renderedColumns,
index,
isScrolling,
key,
onRowClick,
onRowDoubleClick,
onRowRightClick,
onRowMouseOver,
onRowMouseOut,
rowData,
style: flattenedStyle
});
},
[
cachedColumnStyles,
columnKeys,
columns,
handle,
onColumnClick,
onRowClick,
onRowDoubleClick,
onRowMouseOut,
onRowMouseOver,
onRowRightClick,
rowClassName,
rowGetter,
rowHeight,
rowRenderer,
rowStyle,
scrollbarWidth
]
);
const createHeader = (column, index) => {
const {
columnData,
dataKey,
defaultSortDirection,
disableSort,
headerRenderer,
id: columnId,
label
} = column;
const sortEnabled = !disableSort && sort;
const classNames = clsx(
"ReactVirtualized__Table__headerColumn",
headerClassName,
column.headerClassName,
{
ReactVirtualized__Table__sortableHeaderColumn: sortEnabled
}
);
const headerColumnStyle = getFlexStyleForColumn(column, {
...headerStyle,
...column.headerStyle
});
const renderedHeader = headerRenderer({
columnData,
dataKey,
disableSort,
label,
sortBy,
sortDirection
});
let headerOnClick, headerOnKeyDown, headerTabIndex, headerAriaSort, headerAriaLabel;
if (sortEnabled || onHeaderClick) {
const isFirstTimeSort = sortBy !== dataKey;
const newSortDirection = isFirstTimeSort ? defaultSortDirection : sortDirection === SortDirection.DESC ? SortDirection.ASC : SortDirection.DESC;
const onClick = (event) => {
if (sortEnabled) {
sort({
defaultSortDirection,
event,
sortBy: dataKey,
sortDirection: newSortDirection
});
}
if (onHeaderClick) {
onHeaderClick({ columnData, dataKey, event });
}
};
const onKeyDown = (event) => {
if (event.key === "Enter" || event.key === " ") {
onClick(event);
}
};
headerAriaLabel = column["aria-label"] || label || dataKey;
if (sortEnabled) {
headerAriaSort = "none";
}
headerTabIndex = 0;
headerOnClick = onClick;
headerOnKeyDown = onKeyDown;
}
if (sortBy === dataKey) {
headerAriaSort = sortDirection === SortDirection.ASC ? "ascending" : "descending";
}
return /* @__PURE__ */ jsxRuntime.jsx(
"div",
{
"aria-label": headerAriaLabel,
"aria-sort": headerAriaSort,
className: classNames,
id: columnId,
onClick: headerOnClick,
onKeyDown: headerOnKeyDown,
role: "columnheader",
style: headerColumnStyle,
tabIndex: headerTabIndex,
children: renderedHeader
},
"Header-Col" + columnKeys[index]
);
};
const availableRowsHeight = scrollElement !== void 0 ? height : disableHeader ? height ?? 0 : (height ?? 0) - headerHeight;
const rowClass = typeof rowClassName === "function" ? rowClassName({ index: -1 }) : rowClassName;
const rowStyleObject = typeof rowStyle === "function" ? rowStyle({ index: -1 }) : rowStyle;
const gridProps = {
...props,
"aria-readonly": null,
estimatedRowSize,
overscanIndicesGetter,
overscanRowCount,
scrollbarWidth
};
return /* @__PURE__ */ jsxRuntime.jsxs(
"div",
{
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
"aria-colcount": columns.length,
"aria-rowcount": rowCount,
className: clsx("ReactVirtualized__Table", className),
id,
role: "grid",
style,
children: [
!disableHeader && headerRowRenderer({
className: clsx("ReactVirtualized__Table__headerRow", rowClass),
columns: columns.map(createHeader),
style: {
height: headerHeight,
overflow: "hidden",
paddingRight: scrollbarWidth,
width,
...rowStyleObject
}
}),
/* @__PURE__ */ jsxRuntime.jsx(
Grid,
{
...gridProps,
elementRef: setGridElementRef,
autoContainerWidth: true,
className: clsx("ReactVirtualized__Table__Grid", gridClassName),
cellRenderer: createRow,
columnWidth: width,
columnCount: 1,
height: availableRowsHeight,
id: void 0,
noContentRenderer: noRowsRenderer,
onScroll: onGridScroll,
onSectionRendered,
ref: setGridRef,
role: "rowgroup",
style: {
...gridStyle,
overflowX: "hidden"
}
}
)
]
}
);
}
)
);
exports.ArrowKeyStepper = ArrowKeyStepper;
exports.CellMeasurer = CellMeasurer;
exports.CellMeasurerCache = CellMeasurerCache;
exports.Column = Column;
exports.ColumnSizer = ColumnSizer;
exports.Grid = Grid;
exports.InfiniteLoader = InfiniteLoader;
exports.List = List;
exports.Masonry = Masonry;
exports.MultiGrid = MultiGrid;
exports.ScrollSync = ScrollSync;
exports.SortDirection = SortDirection;
exports.SortIndicator = SortIndicator;
exports.Table = Table;
exports.accessibilityOverscanIndicesGetter = accessibilityOverscanIndicesGetter;
exports.createMasonryCellPositioner = createCellPositioner;
exports.createTableMultiSort = createMultiSort;
exports.defaultArrowKeyStepperProps = defaultArrowKeyStepperProps;
exports.defaultCellRangeRenderer = defaultCellRangeRenderer;
exports.defaultColumnProps = defaultColumnProps;
exports.defaultGridProps = defaultGridProps;
exports.defaultInfiniteLoaderProps = defaultInfiniteLoaderProps;
exports.defaultListProps = defaultListProps;
exports.defaultMasonryProps = defaultMasonryProps;
exports.defaultMultiGridProps = defaultMultiGridProps;
exports.defaultOverscanIndicesGetter = defaultOverscanIndicesGetter;
exports.defaultTableCellDataGetter = defaultCellDataGetter;
exports.defaultTableCellRenderer = defaultCellRenderer;
exports.defaultTableHeaderRenderer = defaultHeaderRenderer;
exports.defaultTableHeaderRowRenderer = defaultHeaderRowRenderer;
exports.defaultTableProps = defaultTableProps;
exports.defaultTableRowRenderer = defaultRowRenderer;
//# sourceMappingURL=react-virtualized.cjs.map