@ricsam/react-spreadsheets 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -1
- package/dist/cjs/lib.cjs +302 -46
- package/dist/cjs/lib.cjs.map +4 -4
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/lib.mjs +303 -47
- package/dist/mjs/lib.mjs.map +4 -4
- package/dist/mjs/package.json +1 -1
- package/dist/styles.css +36 -0
- package/dist/types/lib.d.ts +2 -1
- package/dist/types/spreadsheet/spreadsheet.d.ts +13 -1
- package/package.json +3 -3
package/dist/cjs/package.json
CHANGED
package/dist/mjs/lib.mjs
CHANGED
|
@@ -1349,6 +1349,99 @@ var withReadableTextColor = (style) => {
|
|
|
1349
1349
|
return { ...style, color };
|
|
1350
1350
|
};
|
|
1351
1351
|
var hasBorderStyle = (style) => Boolean(style?.borderColor || style?.borderTopColor || style?.borderRightColor || style?.borderBottomColor || style?.borderLeftColor);
|
|
1352
|
+
var normalizeFiniteCount = (count) => {
|
|
1353
|
+
if (count === undefined || count === Infinity)
|
|
1354
|
+
return;
|
|
1355
|
+
if (!Number.isFinite(count))
|
|
1356
|
+
return 0;
|
|
1357
|
+
return Math.max(0, Math.floor(count));
|
|
1358
|
+
};
|
|
1359
|
+
var countToSelectionBound = (count) => count === undefined ? { type: "infinity" } : { type: "number", value: count };
|
|
1360
|
+
var alignScrollOffset = (current, itemStart, itemEnd, viewportSize, align) => {
|
|
1361
|
+
if (viewportSize <= 0)
|
|
1362
|
+
return current;
|
|
1363
|
+
if (align === "start")
|
|
1364
|
+
return itemStart;
|
|
1365
|
+
if (align === "end")
|
|
1366
|
+
return itemEnd - viewportSize;
|
|
1367
|
+
if (itemStart < current)
|
|
1368
|
+
return itemStart;
|
|
1369
|
+
if (itemEnd > current + viewportSize)
|
|
1370
|
+
return itemEnd - viewportSize;
|
|
1371
|
+
return current;
|
|
1372
|
+
};
|
|
1373
|
+
var hasCellData = (value) => value !== undefined && value !== "";
|
|
1374
|
+
var getSparseUsedRange = (cellData, rowCount, columnCount) => {
|
|
1375
|
+
let minRow = Infinity;
|
|
1376
|
+
let maxRow = -1;
|
|
1377
|
+
let minCol = Infinity;
|
|
1378
|
+
let maxCol = -1;
|
|
1379
|
+
for (const [reference, value] of cellData) {
|
|
1380
|
+
if (!hasCellData(value))
|
|
1381
|
+
continue;
|
|
1382
|
+
let rowIndex;
|
|
1383
|
+
let columnIndex;
|
|
1384
|
+
try {
|
|
1385
|
+
({ rowIndex, columnIndex } = parseCellReference(reference));
|
|
1386
|
+
} catch {
|
|
1387
|
+
continue;
|
|
1388
|
+
}
|
|
1389
|
+
if (rowIndex < 0 || columnIndex < 0 || rowCount !== undefined && rowIndex >= rowCount || columnCount !== undefined && columnIndex >= columnCount) {
|
|
1390
|
+
continue;
|
|
1391
|
+
}
|
|
1392
|
+
minRow = Math.min(minRow, rowIndex);
|
|
1393
|
+
maxRow = Math.max(maxRow, rowIndex);
|
|
1394
|
+
minCol = Math.min(minCol, columnIndex);
|
|
1395
|
+
maxCol = Math.max(maxCol, columnIndex);
|
|
1396
|
+
}
|
|
1397
|
+
if (maxRow < 0 || maxCol < 0)
|
|
1398
|
+
return;
|
|
1399
|
+
return {
|
|
1400
|
+
start: { row: minRow, col: minCol },
|
|
1401
|
+
end: {
|
|
1402
|
+
row: { type: "number", value: maxRow },
|
|
1403
|
+
col: { type: "number", value: maxCol }
|
|
1404
|
+
}
|
|
1405
|
+
};
|
|
1406
|
+
};
|
|
1407
|
+
var resolveSparseNavigationTarget = (request, cellData) => {
|
|
1408
|
+
if (request.kind !== "jump" || request.table)
|
|
1409
|
+
return;
|
|
1410
|
+
const isVertical = request.direction === "up" || request.direction === "down";
|
|
1411
|
+
const movingForward = request.direction === "down" || request.direction === "right";
|
|
1412
|
+
const originAxis = isVertical ? request.origin.row : request.origin.col;
|
|
1413
|
+
const fixedAxis = isVertical ? request.origin.col : request.origin.row;
|
|
1414
|
+
const occupied = new Set;
|
|
1415
|
+
for (const [reference, value] of cellData) {
|
|
1416
|
+
if (!hasCellData(value))
|
|
1417
|
+
continue;
|
|
1418
|
+
let rowIndex;
|
|
1419
|
+
let columnIndex;
|
|
1420
|
+
try {
|
|
1421
|
+
({ rowIndex, columnIndex } = parseCellReference(reference));
|
|
1422
|
+
} catch {
|
|
1423
|
+
continue;
|
|
1424
|
+
}
|
|
1425
|
+
if ((isVertical ? columnIndex : rowIndex) === fixedAxis) {
|
|
1426
|
+
occupied.add(isVertical ? rowIndex : columnIndex);
|
|
1427
|
+
}
|
|
1428
|
+
}
|
|
1429
|
+
const step = movingForward ? 1 : -1;
|
|
1430
|
+
let targetAxis;
|
|
1431
|
+
if (occupied.has(originAxis + step)) {
|
|
1432
|
+
targetAxis = originAxis + step;
|
|
1433
|
+
while (occupied.has(targetAxis + step))
|
|
1434
|
+
targetAxis += step;
|
|
1435
|
+
} else {
|
|
1436
|
+
const candidates = [...occupied].filter((index) => movingForward ? index > originAxis : index < originAxis);
|
|
1437
|
+
if (candidates.length > 0) {
|
|
1438
|
+
targetAxis = movingForward ? Math.min(...candidates) : Math.max(...candidates);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
if (targetAxis === undefined)
|
|
1442
|
+
return;
|
|
1443
|
+
return isVertical ? { row: targetAxis, col: request.origin.col } : { row: request.origin.row, col: targetAxis };
|
|
1444
|
+
};
|
|
1352
1445
|
var CellComponent = React2.memo(({
|
|
1353
1446
|
value,
|
|
1354
1447
|
row,
|
|
@@ -1652,6 +1745,8 @@ var Spreadsheet = forwardRef(({
|
|
|
1652
1745
|
cellData: controlledCellData,
|
|
1653
1746
|
onCellDataChange,
|
|
1654
1747
|
onCellDataChangeError,
|
|
1748
|
+
rowCount,
|
|
1749
|
+
columnCount,
|
|
1655
1750
|
columnWidths: controlledColumnWidths,
|
|
1656
1751
|
onColumnWidthsChange,
|
|
1657
1752
|
rowHeights: controlledRowHeights,
|
|
@@ -1673,14 +1768,35 @@ var Spreadsheet = forwardRef(({
|
|
|
1673
1768
|
const [containerDivRef, setContainerDivRef] = useState4(null);
|
|
1674
1769
|
const colorScheme = useColorScheme(containerDivRef);
|
|
1675
1770
|
const gridLineProbeRef = useRef3(null);
|
|
1771
|
+
const [internalCellData, setInternalCellData] = useState4(new Map);
|
|
1772
|
+
const [retryingEdit, setRetryingEdit] = useState4(null);
|
|
1773
|
+
const retryingEditVersionRef = useRef3(0);
|
|
1774
|
+
const cellData = controlledCellData ?? internalCellData;
|
|
1775
|
+
const cellDataRef = useRef3(cellData);
|
|
1776
|
+
cellDataRef.current = cellData;
|
|
1777
|
+
const finiteRowCount = normalizeFiniteCount(rowCount);
|
|
1778
|
+
const finiteColumnCount = normalizeFiniteCount(columnCount);
|
|
1779
|
+
const gridCountsRef = useRef3({ rows: finiteRowCount, columns: finiteColumnCount });
|
|
1780
|
+
gridCountsRef.current = { rows: finiteRowCount, columns: finiteColumnCount };
|
|
1781
|
+
const getNumRows = useCallback3(() => countToSelectionBound(gridCountsRef.current.rows), []);
|
|
1782
|
+
const getNumCols = useCallback3(() => countToSelectionBound(gridCountsRef.current.columns), []);
|
|
1783
|
+
const getDefaultUsedRange = useCallback3(() => getSparseUsedRange(cellDataRef.current, gridCountsRef.current.rows, gridCountsRef.current.columns), []);
|
|
1784
|
+
const defaultResolveTarget = useCallback3((request) => resolveSparseNavigationTarget(request, cellDataRef.current), []);
|
|
1785
|
+
const consumerNavigation = selection?.navigation;
|
|
1786
|
+
const navigation = useMemo(() => ({
|
|
1787
|
+
getUsedRange: consumerNavigation?.getUsedRange ?? getDefaultUsedRange,
|
|
1788
|
+
...consumerNavigation?.getTableAt ? { getTableAt: consumerNavigation.getTableAt } : {},
|
|
1789
|
+
resolveTarget: consumerNavigation?.resolveTarget ?? defaultResolveTarget
|
|
1790
|
+
}), [consumerNavigation, defaultResolveTarget, getDefaultUsedRange]);
|
|
1676
1791
|
const selectionManager = useInitializeSelectionManager({
|
|
1677
|
-
getNumCols
|
|
1678
|
-
getNumRows
|
|
1792
|
+
getNumCols,
|
|
1793
|
+
getNumRows,
|
|
1679
1794
|
initialState: selection?.initialState,
|
|
1680
1795
|
state: selection?.state,
|
|
1681
1796
|
onStateChange: selection?.onStateChange,
|
|
1682
1797
|
containerElement: containerDivRef,
|
|
1683
1798
|
formats: selection?.formats,
|
|
1799
|
+
navigation,
|
|
1684
1800
|
disableAutoClipboard: true
|
|
1685
1801
|
});
|
|
1686
1802
|
const effects = selection?.effects;
|
|
@@ -1689,12 +1805,6 @@ var Spreadsheet = forwardRef(({
|
|
|
1689
1805
|
return effects(selectionManager);
|
|
1690
1806
|
}
|
|
1691
1807
|
}, [selectionManager, effects]);
|
|
1692
|
-
const [internalCellData, setInternalCellData] = useState4(new Map);
|
|
1693
|
-
const [retryingEdit, setRetryingEdit] = useState4(null);
|
|
1694
|
-
const retryingEditVersionRef = useRef3(0);
|
|
1695
|
-
const cellData = controlledCellData ?? internalCellData;
|
|
1696
|
-
const cellDataRef = useRef3(cellData);
|
|
1697
|
-
cellDataRef.current = cellData;
|
|
1698
1808
|
const isControlled = controlledCellData !== undefined;
|
|
1699
1809
|
const prevIsControlledRef = useRef3(isControlled);
|
|
1700
1810
|
selectionManager.getCellsWithData = (area) => {
|
|
@@ -1870,7 +1980,7 @@ var Spreadsheet = forwardRef(({
|
|
|
1870
1980
|
ctx.lineWidth = 1;
|
|
1871
1981
|
let x = gridDims.headerWidth;
|
|
1872
1982
|
let colIndex = 0;
|
|
1873
|
-
while (x < viewport.scrollX + gridDims.headerWidth) {
|
|
1983
|
+
while (x < viewport.scrollX + gridDims.headerWidth && (finiteColumnCount === undefined || colIndex < finiteColumnCount)) {
|
|
1874
1984
|
const colWidth = (columnWidths.get(indexToColumn(colIndex)) || DEFAULT_CELL_WIDTH) * viewport.zoom;
|
|
1875
1985
|
if (x + colWidth > viewport.scrollX + gridDims.headerWidth) {
|
|
1876
1986
|
break;
|
|
@@ -1878,7 +1988,7 @@ var Spreadsheet = forwardRef(({
|
|
|
1878
1988
|
x += colWidth;
|
|
1879
1989
|
colIndex++;
|
|
1880
1990
|
}
|
|
1881
|
-
while (x - viewport.scrollX < width) {
|
|
1991
|
+
while (x - viewport.scrollX < width && (finiteColumnCount === undefined || colIndex < finiteColumnCount)) {
|
|
1882
1992
|
const drawX = x - viewport.scrollX;
|
|
1883
1993
|
if (drawX >= gridDims.headerWidth && drawX <= width) {
|
|
1884
1994
|
ctx.beginPath();
|
|
@@ -1892,7 +2002,7 @@ var Spreadsheet = forwardRef(({
|
|
|
1892
2002
|
}
|
|
1893
2003
|
let y = gridDims.headerHeight;
|
|
1894
2004
|
let rowNum = 1;
|
|
1895
|
-
while (y < viewport.scrollY + gridDims.headerHeight) {
|
|
2005
|
+
while (y < viewport.scrollY + gridDims.headerHeight && (finiteRowCount === undefined || rowNum <= finiteRowCount)) {
|
|
1896
2006
|
const rowHeight = (rowHeights.get(rowNum) || DEFAULT_CELL_HEIGHT) * viewport.zoom;
|
|
1897
2007
|
if (y + rowHeight > viewport.scrollY + gridDims.headerHeight) {
|
|
1898
2008
|
break;
|
|
@@ -1900,7 +2010,7 @@ var Spreadsheet = forwardRef(({
|
|
|
1900
2010
|
y += rowHeight;
|
|
1901
2011
|
rowNum++;
|
|
1902
2012
|
}
|
|
1903
|
-
while (y - viewport.scrollY < height) {
|
|
2013
|
+
while (y - viewport.scrollY < height && (finiteRowCount === undefined || rowNum <= finiteRowCount)) {
|
|
1904
2014
|
const drawY = y - viewport.scrollY;
|
|
1905
2015
|
if (drawY >= gridDims.headerHeight && drawY <= height) {
|
|
1906
2016
|
ctx.beginPath();
|
|
@@ -1914,6 +2024,8 @@ var Spreadsheet = forwardRef(({
|
|
|
1914
2024
|
}
|
|
1915
2025
|
}, [
|
|
1916
2026
|
columnWidths,
|
|
2027
|
+
finiteColumnCount,
|
|
2028
|
+
finiteRowCount,
|
|
1917
2029
|
gridDims.headerHeight,
|
|
1918
2030
|
gridDims.headerWidth,
|
|
1919
2031
|
height,
|
|
@@ -1931,7 +2043,7 @@ var Spreadsheet = forwardRef(({
|
|
|
1931
2043
|
const cells = [];
|
|
1932
2044
|
let x = 0;
|
|
1933
2045
|
let startCol = 0;
|
|
1934
|
-
while (x < viewport.scrollX) {
|
|
2046
|
+
while (x < viewport.scrollX && (finiteColumnCount === undefined || startCol < finiteColumnCount)) {
|
|
1935
2047
|
const colWidth = (columnWidths.get(indexToColumn(startCol)) || DEFAULT_CELL_WIDTH) * viewport.zoom;
|
|
1936
2048
|
if (x + colWidth > viewport.scrollX) {
|
|
1937
2049
|
break;
|
|
@@ -1941,7 +2053,7 @@ var Spreadsheet = forwardRef(({
|
|
|
1941
2053
|
}
|
|
1942
2054
|
let y = 0;
|
|
1943
2055
|
let startRow = 0;
|
|
1944
|
-
while (y < viewport.scrollY) {
|
|
2056
|
+
while (y < viewport.scrollY && (finiteRowCount === undefined || startRow < finiteRowCount)) {
|
|
1945
2057
|
const rowHeight = (rowHeights.get(startRow + 1) || DEFAULT_CELL_HEIGHT) * viewport.zoom;
|
|
1946
2058
|
if (y + rowHeight > viewport.scrollY) {
|
|
1947
2059
|
break;
|
|
@@ -1951,10 +2063,10 @@ var Spreadsheet = forwardRef(({
|
|
|
1951
2063
|
}
|
|
1952
2064
|
let rowY = y;
|
|
1953
2065
|
let row = startRow;
|
|
1954
|
-
while (rowY < viewport.scrollY + height) {
|
|
2066
|
+
while (rowY < viewport.scrollY + height && (finiteRowCount === undefined || row < finiteRowCount)) {
|
|
1955
2067
|
let colX = x;
|
|
1956
2068
|
let col = startCol;
|
|
1957
|
-
while (colX < viewport.scrollX + width) {
|
|
2069
|
+
while (colX < viewport.scrollX + width && (finiteColumnCount === undefined || col < finiteColumnCount)) {
|
|
1958
2070
|
const colKey = indexToColumn(col);
|
|
1959
2071
|
const rowNum = getRowNumber(row);
|
|
1960
2072
|
const cellKey = `${colKey}${rowNum}`;
|
|
@@ -1975,6 +2087,8 @@ var Spreadsheet = forwardRef(({
|
|
|
1975
2087
|
}, [
|
|
1976
2088
|
cellData,
|
|
1977
2089
|
columnWidths,
|
|
2090
|
+
finiteColumnCount,
|
|
2091
|
+
finiteRowCount,
|
|
1978
2092
|
height,
|
|
1979
2093
|
rowHeights,
|
|
1980
2094
|
viewport.scrollX,
|
|
@@ -2002,6 +2116,64 @@ var Spreadsheet = forwardRef(({
|
|
|
2002
2116
|
}
|
|
2003
2117
|
return { x, y };
|
|
2004
2118
|
}, [columnWidths, rowHeights]);
|
|
2119
|
+
const clampViewportOffsets = useCallback3((scrollX, scrollY, zoom) => {
|
|
2120
|
+
const bodyWidth = Math.max(0, width - HEADER_WIDTH * zoom);
|
|
2121
|
+
const bodyHeight = Math.max(0, height - HEADER_HEIGHT * zoom);
|
|
2122
|
+
const maxScrollX = finiteColumnCount === undefined ? Infinity : Math.max(0, getColumnEdgePosition(finiteColumnCount, columnWidths) * zoom - bodyWidth);
|
|
2123
|
+
const maxScrollY = finiteRowCount === undefined ? Infinity : Math.max(0, getRowEdgePosition(finiteRowCount, rowHeights) * zoom - bodyHeight);
|
|
2124
|
+
return {
|
|
2125
|
+
scrollX: Math.min(Math.max(0, scrollX), maxScrollX),
|
|
2126
|
+
scrollY: Math.min(Math.max(0, scrollY), maxScrollY)
|
|
2127
|
+
};
|
|
2128
|
+
}, [columnWidths, finiteColumnCount, finiteRowCount, height, rowHeights, width]);
|
|
2129
|
+
const revealCell = useCallback3((cell, options = {}) => {
|
|
2130
|
+
if (finiteRowCount === 0 || finiteColumnCount === 0)
|
|
2131
|
+
return;
|
|
2132
|
+
if (!Number.isFinite(cell.row) || !Number.isFinite(cell.col))
|
|
2133
|
+
return;
|
|
2134
|
+
const requestedRow = Math.max(0, Math.floor(cell.row));
|
|
2135
|
+
const requestedCol = Math.max(0, Math.floor(cell.col));
|
|
2136
|
+
const row = finiteRowCount === undefined ? requestedRow : Math.min(requestedRow, finiteRowCount - 1);
|
|
2137
|
+
const col = finiteColumnCount === undefined ? requestedCol : Math.min(requestedCol, finiteColumnCount - 1);
|
|
2138
|
+
setViewport((previous) => {
|
|
2139
|
+
const bodyWidth = Math.max(0, width - HEADER_WIDTH * previous.zoom);
|
|
2140
|
+
const bodyHeight = Math.max(0, height - HEADER_HEIGHT * previous.zoom);
|
|
2141
|
+
const left = getColumnEdgePosition(col, columnWidths) * previous.zoom;
|
|
2142
|
+
const right = getColumnEdgePosition(col + 1, columnWidths) * previous.zoom;
|
|
2143
|
+
const top = getRowEdgePosition(row, rowHeights) * previous.zoom;
|
|
2144
|
+
const bottom = getRowEdgePosition(row + 1, rowHeights) * previous.zoom;
|
|
2145
|
+
const desired = clampViewportOffsets(alignScrollOffset(previous.scrollX, left, right, bodyWidth, options.columnAlign ?? "nearest"), alignScrollOffset(previous.scrollY, top, bottom, bodyHeight, options.rowAlign ?? "nearest"), previous.zoom);
|
|
2146
|
+
if (desired.scrollX === previous.scrollX && desired.scrollY === previous.scrollY) {
|
|
2147
|
+
return previous;
|
|
2148
|
+
}
|
|
2149
|
+
return { ...previous, ...desired };
|
|
2150
|
+
});
|
|
2151
|
+
}, [
|
|
2152
|
+
clampViewportOffsets,
|
|
2153
|
+
columnWidths,
|
|
2154
|
+
finiteColumnCount,
|
|
2155
|
+
finiteRowCount,
|
|
2156
|
+
height,
|
|
2157
|
+
rowHeights,
|
|
2158
|
+
width
|
|
2159
|
+
]);
|
|
2160
|
+
const scrollToCell = useCallback3((cell, options = {}) => {
|
|
2161
|
+
const align = options.align ?? "nearest";
|
|
2162
|
+
revealCell(cell, { rowAlign: align, columnAlign: align });
|
|
2163
|
+
}, [revealCell]);
|
|
2164
|
+
useEffect3(() => selectionManager.listenToViewportRequest((request) => {
|
|
2165
|
+
const isVertical = request.direction === "up" || request.direction === "down";
|
|
2166
|
+
revealCell(request.cell, {
|
|
2167
|
+
rowAlign: isVertical ? request.align : "nearest",
|
|
2168
|
+
columnAlign: isVertical ? "nearest" : request.align
|
|
2169
|
+
});
|
|
2170
|
+
}), [revealCell, selectionManager]);
|
|
2171
|
+
useEffect3(() => {
|
|
2172
|
+
setViewport((previous) => {
|
|
2173
|
+
const next = clampViewportOffsets(previous.scrollX, previous.scrollY, previous.zoom);
|
|
2174
|
+
return next.scrollX === previous.scrollX && next.scrollY === previous.scrollY ? previous : { ...previous, ...next };
|
|
2175
|
+
});
|
|
2176
|
+
}, [clampViewportOffsets]);
|
|
2005
2177
|
React2.useEffect(() => {
|
|
2006
2178
|
return selectionManager.listenToUpdateData((updates) => {
|
|
2007
2179
|
const editingState = selectionManager.isEditing;
|
|
@@ -2076,12 +2248,11 @@ var Spreadsheet = forwardRef(({
|
|
|
2076
2248
|
const handleWheel = useCallback3((e) => {
|
|
2077
2249
|
e.preventDefault();
|
|
2078
2250
|
e.stopPropagation();
|
|
2079
|
-
setViewport((
|
|
2080
|
-
...
|
|
2081
|
-
scrollX
|
|
2082
|
-
scrollY: Math.max(0, prev.scrollY + e.deltaY)
|
|
2251
|
+
setViewport((previous) => ({
|
|
2252
|
+
...previous,
|
|
2253
|
+
...clampViewportOffsets(previous.scrollX + e.deltaX, previous.scrollY + e.deltaY, previous.zoom)
|
|
2083
2254
|
}));
|
|
2084
|
-
}, []);
|
|
2255
|
+
}, [clampViewportOffsets]);
|
|
2085
2256
|
const commitOverlayChildren = useCallback3((children) => {
|
|
2086
2257
|
overlayChildrenRef.current = children;
|
|
2087
2258
|
if (onOverlayChildrenChange) {
|
|
@@ -2500,7 +2671,7 @@ var Spreadsheet = forwardRef(({
|
|
|
2500
2671
|
const headers = [];
|
|
2501
2672
|
let x = 0;
|
|
2502
2673
|
let startCol = 0;
|
|
2503
|
-
while (x < viewport.scrollX) {
|
|
2674
|
+
while (x < viewport.scrollX && (finiteColumnCount === undefined || startCol < finiteColumnCount)) {
|
|
2504
2675
|
const col = indexToColumn(startCol);
|
|
2505
2676
|
const colWidth = getColumnWidth(col) * viewport.zoom;
|
|
2506
2677
|
if (x + colWidth > viewport.scrollX) {
|
|
@@ -2509,7 +2680,7 @@ var Spreadsheet = forwardRef(({
|
|
|
2509
2680
|
x += colWidth;
|
|
2510
2681
|
startCol++;
|
|
2511
2682
|
}
|
|
2512
|
-
while (x < viewport.scrollX + width) {
|
|
2683
|
+
while (x < viewport.scrollX + width && (finiteColumnCount === undefined || startCol < finiteColumnCount)) {
|
|
2513
2684
|
const col = indexToColumn(startCol);
|
|
2514
2685
|
const colWidth = getColumnWidth(col) * viewport.zoom;
|
|
2515
2686
|
headers.push({
|
|
@@ -2520,14 +2691,14 @@ var Spreadsheet = forwardRef(({
|
|
|
2520
2691
|
startCol++;
|
|
2521
2692
|
}
|
|
2522
2693
|
return headers;
|
|
2523
|
-
}, [width, viewport, getColumnWidth]);
|
|
2694
|
+
}, [finiteColumnCount, width, viewport, getColumnWidth]);
|
|
2524
2695
|
const getVisibleRowHeaders = useCallback3(() => {
|
|
2525
2696
|
if (!height)
|
|
2526
2697
|
return [];
|
|
2527
2698
|
const headers = [];
|
|
2528
2699
|
let y = 0;
|
|
2529
2700
|
let rowNum = 1;
|
|
2530
|
-
while (y < viewport.scrollY) {
|
|
2701
|
+
while (y < viewport.scrollY && (finiteRowCount === undefined || rowNum <= finiteRowCount)) {
|
|
2531
2702
|
const rowHeight = getRowHeight(rowNum) * viewport.zoom;
|
|
2532
2703
|
if (y + rowHeight > viewport.scrollY) {
|
|
2533
2704
|
break;
|
|
@@ -2535,7 +2706,7 @@ var Spreadsheet = forwardRef(({
|
|
|
2535
2706
|
y += rowHeight;
|
|
2536
2707
|
rowNum++;
|
|
2537
2708
|
}
|
|
2538
|
-
while (y < viewport.scrollY + height) {
|
|
2709
|
+
while (y < viewport.scrollY + height && (finiteRowCount === undefined || rowNum <= finiteRowCount)) {
|
|
2539
2710
|
const rowHeight = getRowHeight(rowNum) * viewport.zoom;
|
|
2540
2711
|
headers.push({
|
|
2541
2712
|
row: rowNum,
|
|
@@ -2545,7 +2716,7 @@ var Spreadsheet = forwardRef(({
|
|
|
2545
2716
|
rowNum++;
|
|
2546
2717
|
}
|
|
2547
2718
|
return headers;
|
|
2548
|
-
}, [height, viewport, getRowHeight]);
|
|
2719
|
+
}, [finiteRowCount, height, viewport, getRowHeight]);
|
|
2549
2720
|
const { visibleOverlays, overlaysToRender } = useMemo(() => {
|
|
2550
2721
|
if (!width || !height || !overlayChildren) {
|
|
2551
2722
|
return { visibleOverlays: [], overlaysToRender: [] };
|
|
@@ -2593,6 +2764,43 @@ var Spreadsheet = forwardRef(({
|
|
|
2593
2764
|
const visibleColumnHeaders = React2.useMemo(() => getVisibleColumnHeaders(), [getVisibleColumnHeaders]);
|
|
2594
2765
|
const visibleRowHeaders = React2.useMemo(() => getVisibleRowHeaders(), [getVisibleRowHeaders]);
|
|
2595
2766
|
const hasFocus = useSelectionManager(selectionManager, () => selectionManager.hasFocus);
|
|
2767
|
+
const referenceSelection = useSelectionManager(selectionManager, () => selectionManager.referenceSelection);
|
|
2768
|
+
const referenceSelectionRect = useMemo(() => {
|
|
2769
|
+
if (referenceSelection.type === "none")
|
|
2770
|
+
return;
|
|
2771
|
+
if (finiteRowCount === 0 || finiteColumnCount === 0)
|
|
2772
|
+
return;
|
|
2773
|
+
const range = referenceSelection.range;
|
|
2774
|
+
const lastVisibleRow = visibleCells.reduce((maximum, cell) => Math.max(maximum, cell.row - 1), range.start.row);
|
|
2775
|
+
const lastVisibleCol = visibleCells.reduce((maximum, cell) => Math.max(maximum, columnToIndex(cell.col)), range.start.col);
|
|
2776
|
+
const rawEndRow = range.end.row.type === "number" ? range.end.row.value : finiteRowCount === undefined ? lastVisibleRow : finiteRowCount - 1;
|
|
2777
|
+
const rawEndCol = range.end.col.type === "number" ? range.end.col.value : finiteColumnCount === undefined ? lastVisibleCol : finiteColumnCount - 1;
|
|
2778
|
+
const maxRow = finiteRowCount === undefined ? Infinity : finiteRowCount - 1;
|
|
2779
|
+
const maxCol = finiteColumnCount === undefined ? Infinity : finiteColumnCount - 1;
|
|
2780
|
+
const startRow = Math.min(Math.max(0, Math.min(range.start.row, rawEndRow)), maxRow);
|
|
2781
|
+
const endRow = Math.min(Math.max(0, Math.max(range.start.row, rawEndRow)), maxRow);
|
|
2782
|
+
const startCol = Math.min(Math.max(0, Math.min(range.start.col, rawEndCol)), maxCol);
|
|
2783
|
+
const endCol = Math.min(Math.max(0, Math.max(range.start.col, rawEndCol)), maxCol);
|
|
2784
|
+
const rect = getRectFromCellSnapAnchor({
|
|
2785
|
+
startCol,
|
|
2786
|
+
startRow,
|
|
2787
|
+
endCol: endCol + 1,
|
|
2788
|
+
endRow: endRow + 1
|
|
2789
|
+
}, columnWidths, rowHeights);
|
|
2790
|
+
return {
|
|
2791
|
+
left: HEADER_WIDTH + rect.x,
|
|
2792
|
+
top: HEADER_HEIGHT + rect.y,
|
|
2793
|
+
width: rect.width,
|
|
2794
|
+
height: rect.height
|
|
2795
|
+
};
|
|
2796
|
+
}, [
|
|
2797
|
+
columnWidths,
|
|
2798
|
+
finiteColumnCount,
|
|
2799
|
+
finiteRowCount,
|
|
2800
|
+
referenceSelection,
|
|
2801
|
+
rowHeights,
|
|
2802
|
+
visibleCells
|
|
2803
|
+
]);
|
|
2596
2804
|
React2.useEffect(() => {
|
|
2597
2805
|
if (!containerDivRef || !hasFocus || !parentSelected) {
|
|
2598
2806
|
return;
|
|
@@ -2610,8 +2818,9 @@ var Spreadsheet = forwardRef(({
|
|
|
2610
2818
|
},
|
|
2611
2819
|
blur: () => {
|
|
2612
2820
|
selectionManager.blur();
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2821
|
+
},
|
|
2822
|
+
scrollToCell
|
|
2823
|
+
}), [scrollToCell, selectionManager]);
|
|
2615
2824
|
return /* @__PURE__ */ jsx3("div", {
|
|
2616
2825
|
className: cn("rsp-root", className),
|
|
2617
2826
|
"data-rsp-scheme": colorScheme,
|
|
@@ -2715,28 +2924,38 @@ var Spreadsheet = forwardRef(({
|
|
|
2715
2924
|
zIndex: 40
|
|
2716
2925
|
}
|
|
2717
2926
|
}),
|
|
2718
|
-
/* @__PURE__ */
|
|
2927
|
+
/* @__PURE__ */ jsxs2("div", {
|
|
2719
2928
|
className: "rsp-cells",
|
|
2720
2929
|
"data-testid": "spreadsheet-cells",
|
|
2721
2930
|
style: {
|
|
2722
2931
|
transform: `translate(${-viewport.scrollX}px, ${-viewport.scrollY}px) scale(${viewport.zoom})`,
|
|
2723
2932
|
transformOrigin: "0 0"
|
|
2724
2933
|
},
|
|
2725
|
-
children:
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2934
|
+
children: [
|
|
2935
|
+
visibleCells.map((cell) => /* @__PURE__ */ jsx3(CellComponent, {
|
|
2936
|
+
value: cellData.get(`${cell.col}${cell.row}`) ?? "",
|
|
2937
|
+
row: cell.row,
|
|
2938
|
+
col: cell.col,
|
|
2939
|
+
selectionManager,
|
|
2940
|
+
cellToPixelBase,
|
|
2941
|
+
getColumnWidth,
|
|
2942
|
+
getRowHeight,
|
|
2943
|
+
customCellStyle,
|
|
2944
|
+
customCellRenderer,
|
|
2945
|
+
inputValue: cellData.get(`${cell.col}${cell.row}`) ?? "",
|
|
2946
|
+
editInputVersion: retryingEdit?.rowIndex === cell.row - 1 && retryingEdit?.colIndex === columnToIndex(cell.col) ? retryingEdit.version : 0,
|
|
2947
|
+
width,
|
|
2948
|
+
height
|
|
2949
|
+
}, `${cell.col}${cell.row}`)),
|
|
2950
|
+
referenceSelectionRect && referenceSelection.type !== "none" && /* @__PURE__ */ jsx3("div", {
|
|
2951
|
+
"aria-hidden": "true",
|
|
2952
|
+
className: cn("rsp-reference-selection", `rsp-reference-selection-${referenceSelection.type}`),
|
|
2953
|
+
"data-testid": "spreadsheet-reference-selection",
|
|
2954
|
+
"data-reference-id": referenceSelection.id,
|
|
2955
|
+
"data-reference-phase": referenceSelection.type,
|
|
2956
|
+
style: referenceSelectionRect
|
|
2957
|
+
})
|
|
2958
|
+
]
|
|
2740
2959
|
}),
|
|
2741
2960
|
components && overlayChildren && overlayChildren.length > 0 && /* @__PURE__ */ jsxs2("div", {
|
|
2742
2961
|
ref: overlayContainerRef,
|
|
@@ -2821,7 +3040,7 @@ import {
|
|
|
2821
3040
|
parseCellReference as parseCellReference2,
|
|
2822
3041
|
getCellReference as getCellReference3
|
|
2823
3042
|
} from "@ricsam/formula-engine";
|
|
2824
|
-
import React3, { useCallback as useCallback4, useRef as useRef4, useState as useState6 } from "react";
|
|
3043
|
+
import React3, { useCallback as useCallback4, useMemo as useMemo2, useRef as useRef4, useState as useState6 } from "react";
|
|
2825
3044
|
|
|
2826
3045
|
// src/utils/use-scheme-root.ts
|
|
2827
3046
|
import { useState as useState5 } from "react";
|
|
@@ -3345,6 +3564,42 @@ function FormulaSheet({
|
|
|
3345
3564
|
const clipboardManager = React3.useMemo(() => controlledClipboardManager ?? new WorkbookClipboardManager(engine), [controlledClipboardManager, engine]);
|
|
3346
3565
|
const state = useEngine(engine);
|
|
3347
3566
|
const sheet = state.workbooks.get(workbookName)?.sheets.get(sheetName);
|
|
3567
|
+
const getEngineTableAt = useCallback4((cell) => {
|
|
3568
|
+
const table = engine.isCellInTable({
|
|
3569
|
+
workbookName,
|
|
3570
|
+
sheetName,
|
|
3571
|
+
rowIndex: cell.row,
|
|
3572
|
+
colIndex: cell.col
|
|
3573
|
+
});
|
|
3574
|
+
if (!table)
|
|
3575
|
+
return;
|
|
3576
|
+
const endRow = table.endRow.type === "number" ? { type: "number", value: table.endRow.value } : { type: "infinity" };
|
|
3577
|
+
const endCol = {
|
|
3578
|
+
type: "number",
|
|
3579
|
+
value: table.start.colIndex + table.headers.size - 1
|
|
3580
|
+
};
|
|
3581
|
+
const hasDataRows = endRow.type === "infinity" || endRow.value > table.start.rowIndex;
|
|
3582
|
+
return {
|
|
3583
|
+
id: `${table.workbookName}/${table.name}`,
|
|
3584
|
+
bounds: {
|
|
3585
|
+
start: { row: table.start.rowIndex, col: table.start.colIndex },
|
|
3586
|
+
end: { row: endRow, col: endCol }
|
|
3587
|
+
},
|
|
3588
|
+
...hasDataRows ? {
|
|
3589
|
+
dataBounds: {
|
|
3590
|
+
start: {
|
|
3591
|
+
row: table.start.rowIndex + 1,
|
|
3592
|
+
col: table.start.colIndex
|
|
3593
|
+
},
|
|
3594
|
+
end: { row: endRow, col: endCol }
|
|
3595
|
+
}
|
|
3596
|
+
} : {}
|
|
3597
|
+
};
|
|
3598
|
+
}, [engine, sheetName, workbookName]);
|
|
3599
|
+
const formulaNavigation = useMemo2(() => ({
|
|
3600
|
+
...selection?.navigation,
|
|
3601
|
+
getTableAt: selection?.navigation?.getTableAt ?? getEngineTableAt
|
|
3602
|
+
}), [getEngineTableAt, selection?.navigation]);
|
|
3348
3603
|
const onCellDataChange = useCallback4((updatedSpreadsheet) => {
|
|
3349
3604
|
const data = new Map(updatedSpreadsheet);
|
|
3350
3605
|
data.forEach((value, key) => {
|
|
@@ -3518,6 +3773,7 @@ function FormulaSheet({
|
|
|
3518
3773
|
parentSelected: isSelected,
|
|
3519
3774
|
selection: {
|
|
3520
3775
|
...selection,
|
|
3776
|
+
navigation: formulaNavigation,
|
|
3521
3777
|
effects: selectionManagerEffects
|
|
3522
3778
|
},
|
|
3523
3779
|
containerProps: isSelected && selectedArea ? {
|
|
@@ -4107,4 +4363,4 @@ export {
|
|
|
4107
4363
|
useResizeObserver
|
|
4108
4364
|
};
|
|
4109
4365
|
|
|
4110
|
-
//# debugId=
|
|
4366
|
+
//# debugId=22D97CA826E5512F64756E2164756E21
|