UNPKG

react-konva-grid

Version:

Canvas grid to render large set of tabular data with virtualization.

268 lines 9.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.cellIndentifier = exports.getEstimatedTotalWidth = exports.getEstimatedTotalHeight = exports.getItemMetadata = exports.getColumnWidth = exports.getRowHeight = exports.getColumnOffset = exports.getRowOffset = exports.itemKey = exports.getBoundedCells = exports.getColumnStopIndexForStartIndex = exports.getColumnStartIndexForOffset = exports.getRowStopIndexForStartIndex = exports.getRowStartIndexForOffset = void 0; exports.getRowStartIndexForOffset = ({ rowHeight, columnWidth, rowCount, columnCount, instanceProps, offset, }) => { return findNearestItem({ itemType: "row", rowHeight, columnWidth, rowCount, columnCount, instanceProps, offset, }); }; exports.getRowStopIndexForStartIndex = ({ startIndex, rowCount, rowHeight, columnWidth, scrollTop, containerHeight, instanceProps, }) => { const itemMetadata = exports.getItemMetadata({ itemType: "row", rowHeight, columnWidth, index: startIndex, instanceProps, }); const maxOffset = scrollTop + containerHeight; let offset = itemMetadata.offset + itemMetadata.size; let stopIndex = startIndex; while (stopIndex < rowCount - 1 && offset < maxOffset) { stopIndex++; offset += exports.getItemMetadata({ itemType: "row", rowHeight, columnWidth, index: stopIndex, instanceProps, }).size; } return stopIndex; }; exports.getColumnStartIndexForOffset = ({ rowHeight, columnWidth, rowCount, columnCount, instanceProps, offset, }) => { return findNearestItem({ itemType: "column", rowHeight, columnWidth, rowCount, columnCount, instanceProps, offset, }); }; exports.getColumnStopIndexForStartIndex = ({ startIndex, rowHeight, columnWidth, instanceProps, containerWidth, scrollLeft, columnCount, }) => { const itemMetadata = exports.getItemMetadata({ itemType: "column", index: startIndex, rowHeight, columnWidth, instanceProps, }); const maxOffset = scrollLeft + containerWidth; let offset = itemMetadata.offset + itemMetadata.size; let stopIndex = startIndex; while (stopIndex < columnCount - 1 && offset < maxOffset) { stopIndex++; offset += exports.getItemMetadata({ itemType: "column", rowHeight, columnWidth, index: stopIndex, instanceProps, }).size; } return stopIndex; }; exports.getBoundedCells = (area) => { const cells = new Set(); if (!area) return cells; const { top, bottom, left, right } = area; for (let i = top; i <= bottom; i++) { for (let j = left; j <= right; j++) { cells.add(exports.cellIndentifier(i, j)); } } return cells; }; exports.itemKey = ({ rowIndex, columnIndex }) => `${rowIndex}:${columnIndex}`; exports.getRowOffset = ({ index, rowHeight, columnWidth, instanceProps, }) => { return exports.getItemMetadata({ itemType: "row", index, rowHeight, columnWidth, instanceProps, }).offset; }; exports.getColumnOffset = ({ index, rowHeight, columnWidth, instanceProps, }) => { return exports.getItemMetadata({ itemType: "column", index, rowHeight, columnWidth, instanceProps, }).offset; }; exports.getRowHeight = (index, instanceProps) => { return instanceProps.rowMetadataMap[index].size; }; exports.getColumnWidth = (index, instanceProps) => { return instanceProps.columnMetadataMap[index].size; }; exports.getItemMetadata = ({ itemType, index, rowHeight, columnWidth, instanceProps, }) => { let itemMetadataMap, itemSize, lastMeasuredIndex; if (itemType === "column") { itemMetadataMap = instanceProps.columnMetadataMap; itemSize = columnWidth; lastMeasuredIndex = instanceProps.lastMeasuredColumnIndex; } else { itemMetadataMap = instanceProps.rowMetadataMap; itemSize = rowHeight; lastMeasuredIndex = instanceProps.lastMeasuredRowIndex; } if (index > lastMeasuredIndex) { let offset = 0; if (lastMeasuredIndex >= 0) { const itemMetadata = itemMetadataMap[lastMeasuredIndex]; offset = itemMetadata.offset + itemMetadata.size; } for (let i = lastMeasuredIndex + 1; i <= index; i++) { let size = itemSize(i); itemMetadataMap[i] = { offset, size, }; offset += size; } if (itemType === "column") { instanceProps.lastMeasuredColumnIndex = index; } else { instanceProps.lastMeasuredRowIndex = index; } } return itemMetadataMap[index]; }; const findNearestItem = ({ itemType, rowHeight, columnWidth, rowCount, columnCount, instanceProps, offset, }) => { let itemMetadataMap, lastMeasuredIndex; if (itemType === "column") { itemMetadataMap = instanceProps.columnMetadataMap; lastMeasuredIndex = instanceProps.lastMeasuredColumnIndex; } else { itemMetadataMap = instanceProps.rowMetadataMap; lastMeasuredIndex = instanceProps.lastMeasuredRowIndex; } const lastMeasuredItemOffset = lastMeasuredIndex > 0 ? itemMetadataMap[lastMeasuredIndex].offset : 0; if (lastMeasuredItemOffset >= offset) { // If we've already measured items within this range just use a binary search as it's faster. return findNearestItemBinarySearch({ itemType, rowHeight, columnWidth, instanceProps, high: lastMeasuredIndex, low: 0, offset, }); } else { // If we haven't yet measured this high, fallback to an exponential search with an inner binary search. // The exponential search avoids pre-computing sizes for the full set of items as a binary search would. // The overall complexity for this approach is O(log n). return findNearestItemExponentialSearch({ itemType, rowHeight, rowCount, columnCount, columnWidth, instanceProps, index: Math.max(0, lastMeasuredIndex), offset, }); } }; const findNearestItemBinarySearch = ({ itemType, rowHeight, columnWidth, instanceProps, high, low, offset, }) => { while (low <= high) { const middle = low + Math.floor((high - low) / 2); const currentOffset = exports.getItemMetadata({ itemType, rowHeight, columnWidth, index: middle, instanceProps, }).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; } }; const findNearestItemExponentialSearch = ({ itemType, rowHeight, columnWidth, rowCount, columnCount, instanceProps, index, offset, }) => { const itemCount = itemType === "column" ? columnCount : rowCount; let interval = 1; while (index < itemCount && exports.getItemMetadata({ itemType, rowHeight, columnWidth, index, instanceProps, }).offset < offset) { index += interval; interval *= 2; } return findNearestItemBinarySearch({ itemType, rowHeight, columnWidth, instanceProps, high: Math.min(index, itemCount - 1), low: Math.floor(index / 2), offset, }); }; exports.getEstimatedTotalHeight = (rowCount, estimatedRowHeight, instanceProps) => { let totalSizeOfMeasuredRows = 0; let { lastMeasuredRowIndex, rowMetadataMap } = instanceProps; // Edge case check for when the number of items decreases while a scroll is in progress. // https://github.com/bvaughn/react-window/pull/138 if (lastMeasuredRowIndex >= rowCount) { lastMeasuredRowIndex = rowCount - 1; } if (lastMeasuredRowIndex >= 0) { const itemMetadata = rowMetadataMap[lastMeasuredRowIndex]; totalSizeOfMeasuredRows = itemMetadata.offset + itemMetadata.size; } const numUnmeasuredItems = rowCount - lastMeasuredRowIndex - 1; const totalSizeOfUnmeasuredItems = numUnmeasuredItems * estimatedRowHeight; return totalSizeOfMeasuredRows + totalSizeOfUnmeasuredItems; }; exports.getEstimatedTotalWidth = (columnCount, estimatedColumnWidth, instanceProps) => { let totalSizeOfMeasuredRows = 0; let { lastMeasuredColumnIndex, columnMetadataMap } = instanceProps; // Edge case check for when the number of items decreases while a scroll is in progress. // https://github.com/bvaughn/react-window/pull/138 if (lastMeasuredColumnIndex >= columnCount) { lastMeasuredColumnIndex = columnCount - 1; } if (lastMeasuredColumnIndex >= 0) { const itemMetadata = columnMetadataMap[lastMeasuredColumnIndex]; totalSizeOfMeasuredRows = itemMetadata.offset + itemMetadata.size; } const numUnmeasuredItems = columnCount - lastMeasuredColumnIndex - 1; const totalSizeOfUnmeasuredItems = numUnmeasuredItems * estimatedColumnWidth; return totalSizeOfMeasuredRows + totalSizeOfUnmeasuredItems; }; /* Create a stringified cell identifier */ exports.cellIndentifier = (rowIndex, columnIndex) => [rowIndex, columnIndex].toString(); //# sourceMappingURL=helpers.js.map