@extend-ai/react-xlsx 0.8.2 → 0.8.4
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/dist/index.cjs +975 -199
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +213 -0
- package/dist/index.d.ts +213 -0
- package/dist/index.js +975 -199
- package/dist/index.js.map +1 -1
- package/dist/xlsx-worker.js +67 -21
- package/dist/xlsx-worker.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4527,6 +4527,10 @@ function parseSheetState(archive, path, options) {
|
|
|
4527
4527
|
let hasVerticalMerges = false;
|
|
4528
4528
|
let maxHorizontalMergeEndCol = -1;
|
|
4529
4529
|
let maxVerticalMergeEndRow = -1;
|
|
4530
|
+
let minContentCol = Number.POSITIVE_INFINITY;
|
|
4531
|
+
let minContentRow = Number.POSITIVE_INFINITY;
|
|
4532
|
+
let maxContentCol = -1;
|
|
4533
|
+
let maxContentRow = -1;
|
|
4530
4534
|
const columnWidthCharacterWidthPx = measureColumnCharacterWidthPx(
|
|
4531
4535
|
options?.defaultFont?.family,
|
|
4532
4536
|
options?.defaultFont?.sizePt
|
|
@@ -4539,6 +4543,26 @@ function parseSheetState(archive, path, options) {
|
|
|
4539
4543
|
sheetViewNode?.getAttribute("zoomScale") ?? sheetViewNode?.getAttribute("zoomScaleNormal") ?? Number.NaN
|
|
4540
4544
|
);
|
|
4541
4545
|
const zoomScale = Number.isFinite(rawZoomScale) && rawZoomScale > 0 ? rawZoomScale : 100;
|
|
4546
|
+
const trackContentCell = (cellRef) => {
|
|
4547
|
+
if (!cellRef) {
|
|
4548
|
+
return;
|
|
4549
|
+
}
|
|
4550
|
+
const cell = parseA1CellReference(cellRef);
|
|
4551
|
+
if (!cell) {
|
|
4552
|
+
return;
|
|
4553
|
+
}
|
|
4554
|
+
minContentCol = Math.min(minContentCol, cell.col);
|
|
4555
|
+
minContentRow = Math.min(minContentRow, cell.row);
|
|
4556
|
+
maxContentCol = Math.max(maxContentCol, cell.col);
|
|
4557
|
+
maxContentRow = Math.max(maxContentRow, cell.row);
|
|
4558
|
+
};
|
|
4559
|
+
const isMeaningfulCellNode = (cellNode) => {
|
|
4560
|
+
if (getFirstChild(cellNode, "f") || getFirstChild(cellNode, "is")) {
|
|
4561
|
+
return true;
|
|
4562
|
+
}
|
|
4563
|
+
const valueNode = getFirstChild(cellNode, "v");
|
|
4564
|
+
return Boolean(valueNode && (valueNode.textContent ?? "").length > 0);
|
|
4565
|
+
};
|
|
4542
4566
|
getLocalElements(document2, "row").forEach((rowNode) => {
|
|
4543
4567
|
const rowIndex = Number(rowNode.getAttribute("r") ?? 0) - 1;
|
|
4544
4568
|
const height = Number(rowNode.getAttribute("ht") ?? Number.NaN);
|
|
@@ -4553,17 +4577,36 @@ function parseSheetState(archive, path, options) {
|
|
|
4553
4577
|
if (rowIndex >= 0 && isHidden) {
|
|
4554
4578
|
hiddenRows.add(rowIndex);
|
|
4555
4579
|
}
|
|
4556
|
-
|
|
4557
|
-
|
|
4580
|
+
getChildElements(rowNode, "c").forEach((cellNode) => {
|
|
4581
|
+
const cellRef = cellNode.getAttribute("r");
|
|
4582
|
+
if (isMeaningfulCellNode(cellNode)) {
|
|
4583
|
+
trackContentCell(cellRef);
|
|
4584
|
+
}
|
|
4585
|
+
if (includeCachedFormulaValues) {
|
|
4558
4586
|
const formulaNode = getFirstChild(cellNode, "f");
|
|
4559
4587
|
const valueNode = getFirstChild(cellNode, "v");
|
|
4560
|
-
const cellRef = cellNode.getAttribute("r");
|
|
4561
4588
|
if (formulaNode && valueNode && cellRef) {
|
|
4562
4589
|
cachedFormulaValues[cellRef] = valueNode.textContent ?? "";
|
|
4563
4590
|
}
|
|
4564
|
-
}
|
|
4591
|
+
}
|
|
4592
|
+
});
|
|
4593
|
+
});
|
|
4594
|
+
getLocalElements(document2, "mergeCell").forEach((mergeNode) => {
|
|
4595
|
+
const reference = mergeNode.getAttribute("ref");
|
|
4596
|
+
const range = reference ? parseA1RangeReference(reference) : null;
|
|
4597
|
+
if (!range) {
|
|
4598
|
+
return;
|
|
4599
|
+
}
|
|
4600
|
+
if (range.end.col > range.start.col) {
|
|
4601
|
+
hasHorizontalMerges = true;
|
|
4602
|
+
maxHorizontalMergeEndCol = Math.max(maxHorizontalMergeEndCol, range.end.col);
|
|
4603
|
+
}
|
|
4604
|
+
if (range.end.row > range.start.row) {
|
|
4605
|
+
hasVerticalMerges = true;
|
|
4606
|
+
maxVerticalMergeEndRow = Math.max(maxVerticalMergeEndRow, range.end.row);
|
|
4565
4607
|
}
|
|
4566
4608
|
});
|
|
4609
|
+
const maxMetadataCol = Math.max(maxContentCol, maxHorizontalMergeEndCol, 0) + 256;
|
|
4567
4610
|
getLocalElements(document2, "col").forEach((colNode) => {
|
|
4568
4611
|
const min = Number(colNode.getAttribute("min") ?? 0) - 1;
|
|
4569
4612
|
const max = Number(colNode.getAttribute("max") ?? 0) - 1;
|
|
@@ -4575,7 +4618,7 @@ function parseSheetState(archive, path, options) {
|
|
|
4575
4618
|
return;
|
|
4576
4619
|
}
|
|
4577
4620
|
}
|
|
4578
|
-
for (let col = min; col <= max; col += 1) {
|
|
4621
|
+
for (let col = min; col <= Math.min(max, maxMetadataCol); col += 1) {
|
|
4579
4622
|
if (col >= 0) {
|
|
4580
4623
|
if (Number.isFinite(width)) {
|
|
4581
4624
|
const widthPx = sheetColumnWidthToPixels(width, columnWidthCharacterWidthPx);
|
|
@@ -4590,21 +4633,6 @@ function parseSheetState(archive, path, options) {
|
|
|
4590
4633
|
}
|
|
4591
4634
|
}
|
|
4592
4635
|
});
|
|
4593
|
-
getLocalElements(document2, "mergeCell").forEach((mergeNode) => {
|
|
4594
|
-
const reference = mergeNode.getAttribute("ref");
|
|
4595
|
-
const range = reference ? parseA1RangeReference(reference) : null;
|
|
4596
|
-
if (!range) {
|
|
4597
|
-
return;
|
|
4598
|
-
}
|
|
4599
|
-
if (range.end.col > range.start.col) {
|
|
4600
|
-
hasHorizontalMerges = true;
|
|
4601
|
-
maxHorizontalMergeEndCol = Math.max(maxHorizontalMergeEndCol, range.end.col);
|
|
4602
|
-
}
|
|
4603
|
-
if (range.end.row > range.start.row) {
|
|
4604
|
-
hasVerticalMerges = true;
|
|
4605
|
-
maxVerticalMergeEndRow = Math.max(maxVerticalMergeEndRow, range.end.row);
|
|
4606
|
-
}
|
|
4607
|
-
});
|
|
4608
4636
|
return {
|
|
4609
4637
|
cachedFormulaValues,
|
|
4610
4638
|
columnWidthCharacterWidthPx,
|
|
@@ -4617,6 +4645,10 @@ function parseSheetState(archive, path, options) {
|
|
|
4617
4645
|
hasVerticalMerges,
|
|
4618
4646
|
maxHorizontalMergeEndCol,
|
|
4619
4647
|
maxVerticalMergeEndRow,
|
|
4648
|
+
maxContentCol,
|
|
4649
|
+
maxContentRow,
|
|
4650
|
+
minContentCol: Number.isFinite(minContentCol) ? minContentCol : -1,
|
|
4651
|
+
minContentRow: Number.isFinite(minContentRow) ? minContentRow : -1,
|
|
4620
4652
|
hiddenCols: [...hiddenCols].sort((left, right) => left - right),
|
|
4621
4653
|
hiddenRows: [...hiddenRows].sort((left, right) => left - right),
|
|
4622
4654
|
rowHeightOverridesPx,
|
|
@@ -6645,6 +6677,20 @@ function resolveDisplayFileName(src, fileName) {
|
|
|
6645
6677
|
return lastSegment;
|
|
6646
6678
|
}
|
|
6647
6679
|
}
|
|
6680
|
+
function resolveSheetDisplayUsedRange(usedRange, sheetState) {
|
|
6681
|
+
const [minRow, minCol, maxRow, maxCol] = usedRange;
|
|
6682
|
+
const maxMeaningfulRow = Math.max(sheetState?.maxContentRow ?? -1, sheetState?.maxVerticalMergeEndRow ?? -1);
|
|
6683
|
+
const maxMeaningfulCol = Math.max(sheetState?.maxContentCol ?? -1, sheetState?.maxHorizontalMergeEndCol ?? -1);
|
|
6684
|
+
if (maxMeaningfulRow < 0 && maxMeaningfulCol < 0) {
|
|
6685
|
+
return usedRange;
|
|
6686
|
+
}
|
|
6687
|
+
return [
|
|
6688
|
+
sheetState?.minContentRow !== void 0 && sheetState.minContentRow >= 0 ? Math.min(minRow, sheetState.minContentRow) : minRow,
|
|
6689
|
+
sheetState?.minContentCol !== void 0 && sheetState.minContentCol >= 0 ? Math.min(minCol, sheetState.minContentCol) : minCol,
|
|
6690
|
+
maxMeaningfulRow >= 0 ? Math.min(maxRow, maxMeaningfulRow) : maxRow,
|
|
6691
|
+
maxMeaningfulCol >= 0 ? Math.min(maxCol, maxMeaningfulCol) : maxCol
|
|
6692
|
+
];
|
|
6693
|
+
}
|
|
6648
6694
|
function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette, styleById, namedCellStyleByName, tableStyleByName, showHiddenSheets = false) {
|
|
6649
6695
|
const sheets = [];
|
|
6650
6696
|
for (let index = 0; index < workbook.sheetCount; index += 1) {
|
|
@@ -6711,7 +6757,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
|
|
|
6711
6757
|
});
|
|
6712
6758
|
continue;
|
|
6713
6759
|
}
|
|
6714
|
-
const [minRow, minCol, maxRow, maxCol] = usedRange;
|
|
6760
|
+
const [minRow, minCol, maxRow, maxCol] = resolveSheetDisplayUsedRange(usedRange, sheetState);
|
|
6715
6761
|
let visibleRowsCache = null;
|
|
6716
6762
|
let visibleColsCache = null;
|
|
6717
6763
|
let rowHeightsCache = null;
|
|
@@ -16470,7 +16516,11 @@ var SELECTION_DRAG_THRESHOLD_PX = 4;
|
|
|
16470
16516
|
var IMAGE_MIN_SIZE_PX = 16;
|
|
16471
16517
|
var IMAGE_HANDLE_SIZE_PX = 10;
|
|
16472
16518
|
var CANVAS_RESIZE_HIT_SLOP_PX = 8;
|
|
16473
|
-
var CANVAS_VIEWPORT_OVERSCAN_PX =
|
|
16519
|
+
var CANVAS_VIEWPORT_OVERSCAN_PX = 480;
|
|
16520
|
+
var CANVAS_SCROLL_BUFFER_PX = 480;
|
|
16521
|
+
var CANVAS_DEFERRED_VIEWPORT_SYNC_THRESHOLD_PX = CANVAS_SCROLL_BUFFER_PX - 96;
|
|
16522
|
+
var CANVAS_IMMEDIATE_VIEWPORT_SYNC_THRESHOLD_PX = CANVAS_SCROLL_BUFFER_PX * 1.5;
|
|
16523
|
+
var CANVAS_DIRTY_CELL_CULL_MARGIN_PX = CANVAS_VIEWPORT_OVERSCAN_PX * 2;
|
|
16474
16524
|
var THUMBNAIL_DEFAULT_MAX_DIMENSION = 192;
|
|
16475
16525
|
var THUMBNAIL_FALLBACK_ROWS = 12;
|
|
16476
16526
|
var THUMBNAIL_FALLBACK_COLS = 8;
|
|
@@ -16485,6 +16535,12 @@ var CHART_SOURCE_HIGHLIGHT_COLORS = ["#2563eb", "#dc2626", "#7c3aed", "#059669",
|
|
|
16485
16535
|
var SHEET_SURFACE = "#ffffff";
|
|
16486
16536
|
var DEFAULT_CELL_PADDING = "0 4px";
|
|
16487
16537
|
var IMAGE_HANDLE_POSITIONS = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
16538
|
+
var CANVAS_CELL_STYLE_CACHE_LIMIT = 4096;
|
|
16539
|
+
var CANVAS_TEXT_MEASURE_CACHE_LIMIT = 2e4;
|
|
16540
|
+
var CANVAS_TEXT_TRUNCATE_CACHE_LIMIT = 4096;
|
|
16541
|
+
var CANVAS_TEXT_WRAP_CACHE_LIMIT = 2048;
|
|
16542
|
+
var CANVAS_PATH2D_CACHE_LIMIT = 512;
|
|
16543
|
+
var EMPTY_VIRTUAL_ITEMS = [];
|
|
16488
16544
|
var IMAGE_HANDLE_CURSOR = {
|
|
16489
16545
|
e: "ew-resize",
|
|
16490
16546
|
n: "ns-resize",
|
|
@@ -16528,6 +16584,50 @@ var NUMERIC_LENGTH_STYLE_KEYS = /* @__PURE__ */ new Set([
|
|
|
16528
16584
|
"top",
|
|
16529
16585
|
"width"
|
|
16530
16586
|
]);
|
|
16587
|
+
var canvasCellStyleCache = /* @__PURE__ */ new Map();
|
|
16588
|
+
var canvasTextMeasureCache = /* @__PURE__ */ new Map();
|
|
16589
|
+
var canvasTextTruncateCache = /* @__PURE__ */ new Map();
|
|
16590
|
+
var canvasTextWrapCache = /* @__PURE__ */ new Map();
|
|
16591
|
+
var canvasPath2DCache = /* @__PURE__ */ new Map();
|
|
16592
|
+
function rememberBoundedCacheValue(cache, key, value, limit) {
|
|
16593
|
+
if (cache.size >= limit) {
|
|
16594
|
+
const oldestKey = cache.keys().next().value;
|
|
16595
|
+
if (oldestKey !== void 0) {
|
|
16596
|
+
cache.delete(oldestKey);
|
|
16597
|
+
}
|
|
16598
|
+
}
|
|
16599
|
+
cache.set(key, value);
|
|
16600
|
+
return value;
|
|
16601
|
+
}
|
|
16602
|
+
function roundCanvasCacheWidth(width) {
|
|
16603
|
+
return Math.round(width * 4) / 4;
|
|
16604
|
+
}
|
|
16605
|
+
function measureCanvasTextWidth(context, text) {
|
|
16606
|
+
if (text.length === 0) {
|
|
16607
|
+
return 0;
|
|
16608
|
+
}
|
|
16609
|
+
const cacheKey = `${context.font}\0${text}`;
|
|
16610
|
+
const cached = canvasTextMeasureCache.get(cacheKey);
|
|
16611
|
+
if (cached !== void 0) {
|
|
16612
|
+
return cached;
|
|
16613
|
+
}
|
|
16614
|
+
return rememberBoundedCacheValue(
|
|
16615
|
+
canvasTextMeasureCache,
|
|
16616
|
+
cacheKey,
|
|
16617
|
+
context.measureText(text).width,
|
|
16618
|
+
CANVAS_TEXT_MEASURE_CACHE_LIMIT
|
|
16619
|
+
);
|
|
16620
|
+
}
|
|
16621
|
+
function getCachedCanvasPath2D(path) {
|
|
16622
|
+
if (typeof Path2D === "undefined") {
|
|
16623
|
+
return null;
|
|
16624
|
+
}
|
|
16625
|
+
const cached = canvasPath2DCache.get(path);
|
|
16626
|
+
if (cached) {
|
|
16627
|
+
return cached;
|
|
16628
|
+
}
|
|
16629
|
+
return rememberBoundedCacheValue(canvasPath2DCache, path, new Path2D(path), CANVAS_PATH2D_CACHE_LIMIT);
|
|
16630
|
+
}
|
|
16531
16631
|
function scaleCssLengthExpression(value, scale) {
|
|
16532
16632
|
if (scale === 1) {
|
|
16533
16633
|
return value;
|
|
@@ -16708,7 +16808,6 @@ function strokeCanvasBorderSide(context, side, rect, border) {
|
|
|
16708
16808
|
const right = rect.left + rect.width;
|
|
16709
16809
|
const top = rect.top;
|
|
16710
16810
|
const bottom = rect.top + rect.height;
|
|
16711
|
-
context.save();
|
|
16712
16811
|
context.strokeStyle = border.color;
|
|
16713
16812
|
context.lineWidth = border.width;
|
|
16714
16813
|
applyCanvasBorderDash(context, border.style, border.width);
|
|
@@ -16738,13 +16837,22 @@ function strokeCanvasBorderSide(context, side, rect, border) {
|
|
|
16738
16837
|
} else {
|
|
16739
16838
|
strokeLine(0);
|
|
16740
16839
|
}
|
|
16741
|
-
context.
|
|
16840
|
+
context.setLineDash([]);
|
|
16841
|
+
context.lineCap = "butt";
|
|
16842
|
+
context.lineWidth = 1;
|
|
16742
16843
|
}
|
|
16743
16844
|
function truncateCanvasText(context, text, maxWidth) {
|
|
16744
16845
|
if (maxWidth <= 0 || text.length === 0) {
|
|
16745
16846
|
return "";
|
|
16746
16847
|
}
|
|
16747
|
-
|
|
16848
|
+
const roundedMaxWidth = roundCanvasCacheWidth(maxWidth);
|
|
16849
|
+
const cacheKey = `${context.font}\0${roundedMaxWidth}\0${text}`;
|
|
16850
|
+
const cached = canvasTextTruncateCache.get(cacheKey);
|
|
16851
|
+
if (cached !== void 0) {
|
|
16852
|
+
return cached;
|
|
16853
|
+
}
|
|
16854
|
+
if (measureCanvasTextWidth(context, text) <= maxWidth) {
|
|
16855
|
+
rememberBoundedCacheValue(canvasTextTruncateCache, cacheKey, text, CANVAS_TEXT_TRUNCATE_CACHE_LIMIT);
|
|
16748
16856
|
return text;
|
|
16749
16857
|
}
|
|
16750
16858
|
const ellipsis = "\u2026";
|
|
@@ -16753,13 +16861,18 @@ function truncateCanvasText(context, text, maxWidth) {
|
|
|
16753
16861
|
while (low < high) {
|
|
16754
16862
|
const mid = Math.ceil((low + high) / 2);
|
|
16755
16863
|
const candidate = `${text.slice(0, mid)}${ellipsis}`;
|
|
16756
|
-
if (context
|
|
16864
|
+
if (measureCanvasTextWidth(context, candidate) <= maxWidth) {
|
|
16757
16865
|
low = mid;
|
|
16758
16866
|
} else {
|
|
16759
16867
|
high = mid - 1;
|
|
16760
16868
|
}
|
|
16761
16869
|
}
|
|
16762
|
-
return
|
|
16870
|
+
return rememberBoundedCacheValue(
|
|
16871
|
+
canvasTextTruncateCache,
|
|
16872
|
+
cacheKey,
|
|
16873
|
+
low <= 0 ? ellipsis : `${text.slice(0, low)}${ellipsis}`,
|
|
16874
|
+
CANVAS_TEXT_TRUNCATE_CACHE_LIMIT
|
|
16875
|
+
);
|
|
16763
16876
|
}
|
|
16764
16877
|
function resolveCanvasFontSizePx(style, fallbackSize = 12) {
|
|
16765
16878
|
const rawFontSize = style.fontSize;
|
|
@@ -16818,7 +16931,7 @@ function resolveCanvasWrapIndex(context, text, maxWidth) {
|
|
|
16818
16931
|
while (low <= high) {
|
|
16819
16932
|
const mid = Math.floor((low + high) / 2);
|
|
16820
16933
|
const candidate = text.slice(0, mid);
|
|
16821
|
-
if (context
|
|
16934
|
+
if (measureCanvasTextWidth(context, candidate) <= maxWidth) {
|
|
16822
16935
|
best = mid;
|
|
16823
16936
|
low = mid + 1;
|
|
16824
16937
|
} else {
|
|
@@ -16835,6 +16948,12 @@ function wrapCanvasText(context, text, maxWidth) {
|
|
|
16835
16948
|
return text.replace(/\r\n?/g, "\n").split("\n");
|
|
16836
16949
|
}
|
|
16837
16950
|
const normalized = text.replace(/\r\n?/g, "\n");
|
|
16951
|
+
const roundedMaxWidth = roundCanvasCacheWidth(maxWidth);
|
|
16952
|
+
const cacheKey = `${context.font}\0${roundedMaxWidth}\0${normalized}`;
|
|
16953
|
+
const cached = canvasTextWrapCache.get(cacheKey);
|
|
16954
|
+
if (cached) {
|
|
16955
|
+
return cached;
|
|
16956
|
+
}
|
|
16838
16957
|
const paragraphs = normalized.split("\n");
|
|
16839
16958
|
const lines = [];
|
|
16840
16959
|
for (const paragraph of paragraphs) {
|
|
@@ -16844,7 +16963,7 @@ function wrapCanvasText(context, text, maxWidth) {
|
|
|
16844
16963
|
}
|
|
16845
16964
|
let remaining = paragraph;
|
|
16846
16965
|
while (remaining.length > 0) {
|
|
16847
|
-
if (context
|
|
16966
|
+
if (measureCanvasTextWidth(context, remaining) <= maxWidth) {
|
|
16848
16967
|
lines.push(remaining);
|
|
16849
16968
|
break;
|
|
16850
16969
|
}
|
|
@@ -16862,10 +16981,31 @@ function wrapCanvasText(context, text, maxWidth) {
|
|
|
16862
16981
|
remaining = remaining.slice(breakIndex).replace(/^\s+/g, "");
|
|
16863
16982
|
}
|
|
16864
16983
|
}
|
|
16865
|
-
return lines;
|
|
16984
|
+
return rememberBoundedCacheValue(canvasTextWrapCache, cacheKey, lines, CANVAS_TEXT_WRAP_CACHE_LIMIT);
|
|
16866
16985
|
}
|
|
16867
16986
|
function buildCanvasCellStyleCache(style) {
|
|
16868
|
-
|
|
16987
|
+
const cacheKey = [
|
|
16988
|
+
style.font,
|
|
16989
|
+
style.fontStyle,
|
|
16990
|
+
style.fontWeight,
|
|
16991
|
+
style.fontSize,
|
|
16992
|
+
style.fontFamily,
|
|
16993
|
+
style.borderTop,
|
|
16994
|
+
style.borderRight,
|
|
16995
|
+
style.borderBottom,
|
|
16996
|
+
style.borderLeft,
|
|
16997
|
+
style.padding,
|
|
16998
|
+
style.textAlign,
|
|
16999
|
+
style.color,
|
|
17000
|
+
style.textDecoration,
|
|
17001
|
+
style.textOverflow,
|
|
17002
|
+
style.whiteSpace
|
|
17003
|
+
].map((value) => value == null ? "" : String(value)).join("");
|
|
17004
|
+
const cached = canvasCellStyleCache.get(cacheKey);
|
|
17005
|
+
if (cached) {
|
|
17006
|
+
return cached;
|
|
17007
|
+
}
|
|
17008
|
+
return rememberBoundedCacheValue(canvasCellStyleCache, cacheKey, {
|
|
16869
17009
|
baseFont: resolveCanvasFont(style, 12),
|
|
16870
17010
|
bottomBorder: parseCanvasBorderDeclaration(style.borderBottom),
|
|
16871
17011
|
leftBorder: parseCanvasBorderDeclaration(style.borderLeft),
|
|
@@ -16877,7 +17017,7 @@ function buildCanvasCellStyleCache(style) {
|
|
|
16877
17017
|
textOverflowEllipsis: style.textOverflow === "ellipsis",
|
|
16878
17018
|
topBorder: parseCanvasBorderDeclaration(style.borderTop),
|
|
16879
17019
|
usesWrappedText: style.whiteSpace === "pre-wrap"
|
|
16880
|
-
};
|
|
17020
|
+
}, CANVAS_CELL_STYLE_CACHE_LIMIT);
|
|
16881
17021
|
}
|
|
16882
17022
|
function splitCssGradientArgs(value) {
|
|
16883
17023
|
const parts = [];
|
|
@@ -18386,6 +18526,44 @@ function resolveShapeVector(shape) {
|
|
|
18386
18526
|
}
|
|
18387
18527
|
return buildPresetShapePath(shape);
|
|
18388
18528
|
}
|
|
18529
|
+
function drawCanvasRoundedRect(context, left, top, width, height, radius) {
|
|
18530
|
+
const safeRadius = Math.max(0, Math.min(radius, width / 2, height / 2));
|
|
18531
|
+
context.beginPath();
|
|
18532
|
+
context.moveTo(left + safeRadius, top);
|
|
18533
|
+
context.lineTo(left + width - safeRadius, top);
|
|
18534
|
+
context.quadraticCurveTo(left + width, top, left + width, top + safeRadius);
|
|
18535
|
+
context.lineTo(left + width, top + height - safeRadius);
|
|
18536
|
+
context.quadraticCurveTo(left + width, top + height, left + width - safeRadius, top + height);
|
|
18537
|
+
context.lineTo(left + safeRadius, top + height);
|
|
18538
|
+
context.quadraticCurveTo(left, top + height, left, top + height - safeRadius);
|
|
18539
|
+
context.lineTo(left, top + safeRadius);
|
|
18540
|
+
context.quadraticCurveTo(left, top, left + safeRadius, top);
|
|
18541
|
+
context.closePath();
|
|
18542
|
+
}
|
|
18543
|
+
function applyCanvasShapeDash(context, dash, lineWidth) {
|
|
18544
|
+
if (!dash) {
|
|
18545
|
+
context.setLineDash([]);
|
|
18546
|
+
return;
|
|
18547
|
+
}
|
|
18548
|
+
const unit = Math.max(1, lineWidth);
|
|
18549
|
+
switch (dash) {
|
|
18550
|
+
case "dash":
|
|
18551
|
+
context.setLineDash([4 * unit, 3 * unit]);
|
|
18552
|
+
break;
|
|
18553
|
+
case "dashDot":
|
|
18554
|
+
context.setLineDash([4 * unit, 2 * unit, unit, 2 * unit]);
|
|
18555
|
+
break;
|
|
18556
|
+
case "dot":
|
|
18557
|
+
context.setLineDash([unit, 2 * unit]);
|
|
18558
|
+
break;
|
|
18559
|
+
case "lgDash":
|
|
18560
|
+
context.setLineDash([8 * unit, 3 * unit]);
|
|
18561
|
+
break;
|
|
18562
|
+
default:
|
|
18563
|
+
context.setLineDash([]);
|
|
18564
|
+
break;
|
|
18565
|
+
}
|
|
18566
|
+
}
|
|
18389
18567
|
function resolveShapeLineEndMarker(type, markerId, color, strokeWidth, rect, viewBox) {
|
|
18390
18568
|
if (type !== "triangle") {
|
|
18391
18569
|
return null;
|
|
@@ -18988,12 +19166,12 @@ function measureTextWidth(value, style) {
|
|
|
18988
19166
|
return value.length * 7;
|
|
18989
19167
|
}
|
|
18990
19168
|
textMeasureCanvas ??= document.createElement("canvas");
|
|
18991
|
-
const context = textMeasureCanvas.getContext("2d");
|
|
19169
|
+
const context = textMeasureCanvas.getContext("2d", { alpha: false });
|
|
18992
19170
|
if (!context) {
|
|
18993
19171
|
return value.length * 7;
|
|
18994
19172
|
}
|
|
18995
19173
|
context.font = buildCanvasFont(style);
|
|
18996
|
-
return context
|
|
19174
|
+
return measureCanvasTextWidth(context, value);
|
|
18997
19175
|
}
|
|
18998
19176
|
function measureWrappedTextHeight(value, style, widthPx) {
|
|
18999
19177
|
if (!value) {
|
|
@@ -19007,7 +19185,7 @@ function measureWrappedTextHeight(value, style, widthPx) {
|
|
|
19007
19185
|
return fallbackLineCount * lineHeight + padding.top + padding.bottom;
|
|
19008
19186
|
}
|
|
19009
19187
|
textMeasureCanvas ??= document.createElement("canvas");
|
|
19010
|
-
const context = textMeasureCanvas.getContext("2d");
|
|
19188
|
+
const context = textMeasureCanvas.getContext("2d", { alpha: false });
|
|
19011
19189
|
if (!context) {
|
|
19012
19190
|
return fallbackLineCount * lineHeight + padding.top + padding.bottom;
|
|
19013
19191
|
}
|
|
@@ -20105,7 +20283,7 @@ function blitCanvasWithScrollDelta(canvas, context, bufferCanvas, dpr, width, he
|
|
|
20105
20283
|
if (bufferCanvas.height !== deviceHeight) {
|
|
20106
20284
|
bufferCanvas.height = deviceHeight;
|
|
20107
20285
|
}
|
|
20108
|
-
const bufferContext = bufferCanvas.getContext("2d");
|
|
20286
|
+
const bufferContext = bufferCanvas.getContext("2d", { alpha: false });
|
|
20109
20287
|
if (!bufferContext) {
|
|
20110
20288
|
return null;
|
|
20111
20289
|
}
|
|
@@ -20956,12 +21134,14 @@ function XlsxGrid({
|
|
|
20956
21134
|
renderImageSelection,
|
|
20957
21135
|
renderTableHeaderMenu,
|
|
20958
21136
|
enableGestureZoom = true,
|
|
20959
|
-
experimentalCanvas =
|
|
21137
|
+
experimentalCanvas = true,
|
|
20960
21138
|
selectionColor,
|
|
20961
21139
|
selectionFillColor,
|
|
20962
21140
|
selectionHeaderColor,
|
|
20963
21141
|
showImages = true
|
|
20964
21142
|
}) {
|
|
21143
|
+
const xlsxCanvasProfileTarget = typeof window !== "undefined" ? window.__xlsxCanvasProfile : void 0;
|
|
21144
|
+
const xlsxGridRenderStart = xlsxCanvasProfileTarget ? performance.now() : 0;
|
|
20965
21145
|
const {
|
|
20966
21146
|
activeCell,
|
|
20967
21147
|
activeSheet,
|
|
@@ -21045,6 +21225,11 @@ function XlsxGrid({
|
|
|
21045
21225
|
const leftFrozenHeaderCanvasRef = React4.useRef(null);
|
|
21046
21226
|
const leftScrollHeaderCanvasRef = React4.useRef(null);
|
|
21047
21227
|
const cornerHeaderCanvasRef = React4.useRef(null);
|
|
21228
|
+
const canvasScrollOverlayContentRef = React4.useRef(null);
|
|
21229
|
+
const canvasTopOverlayContentRef = React4.useRef(null);
|
|
21230
|
+
const canvasLeftOverlayContentRef = React4.useRef(null);
|
|
21231
|
+
const canvasCornerOverlayContentRef = React4.useRef(null);
|
|
21232
|
+
const canvasImageCacheRef = React4.useRef(/* @__PURE__ */ new Map());
|
|
21048
21233
|
const selectionOverlayRef = React4.useRef(null);
|
|
21049
21234
|
const activeValidationOverlayRef = React4.useRef(null);
|
|
21050
21235
|
const fillHandleRef = React4.useRef(null);
|
|
@@ -21073,6 +21258,7 @@ function XlsxGrid({
|
|
|
21073
21258
|
const pendingLiveZoomCommitRef = React4.useRef(null);
|
|
21074
21259
|
const touchPinchStateRef = React4.useRef(null);
|
|
21075
21260
|
const safariPinchStartZoomRef = React4.useRef(null);
|
|
21261
|
+
const canvasTransformStyleCacheRef = React4.useRef(/* @__PURE__ */ new WeakMap());
|
|
21076
21262
|
const displayedSelectionRef = React4.useRef(null);
|
|
21077
21263
|
const firstVisibleColRef = React4.useRef(void 0);
|
|
21078
21264
|
const lastVisibleColRef = React4.useRef(void 0);
|
|
@@ -21098,12 +21284,19 @@ function XlsxGrid({
|
|
|
21098
21284
|
const [fillPreviewRange, setFillPreviewRange] = React4.useState(null);
|
|
21099
21285
|
const [chartPreviewRect, setChartPreviewRect] = React4.useState(null);
|
|
21100
21286
|
const [liveGestureZoom, setLiveGestureZoom] = React4.useState(null);
|
|
21287
|
+
const [canvasImageLoadVersion, setCanvasImageLoadVersion] = React4.useState(0);
|
|
21101
21288
|
const liveDrawingViewportRef = React4.useRef({
|
|
21102
21289
|
height: 0,
|
|
21103
21290
|
left: 0,
|
|
21104
21291
|
top: 0,
|
|
21105
21292
|
width: 0
|
|
21106
21293
|
});
|
|
21294
|
+
const canvasLayoutMetricsRef = React4.useRef({
|
|
21295
|
+
displayHeaderHeight: HEADER_HEIGHT,
|
|
21296
|
+
displayRowHeaderWidth: ROW_HEADER_WIDTH,
|
|
21297
|
+
frozenPaneBottom: HEADER_HEIGHT,
|
|
21298
|
+
frozenPaneRight: ROW_HEADER_WIDTH
|
|
21299
|
+
});
|
|
21107
21300
|
const paintedDrawingViewportRef = React4.useRef({
|
|
21108
21301
|
height: 0,
|
|
21109
21302
|
left: 0,
|
|
@@ -21213,6 +21406,12 @@ function XlsxGrid({
|
|
|
21213
21406
|
const applyCanvasViewportCompensation = React4.useCallback((liveViewport) => {
|
|
21214
21407
|
const nextLiveViewport = liveViewport ?? liveDrawingViewportRef.current;
|
|
21215
21408
|
const paintedViewport = paintedDrawingViewportRef.current;
|
|
21409
|
+
const {
|
|
21410
|
+
displayHeaderHeight: liveDisplayHeaderHeight,
|
|
21411
|
+
displayRowHeaderWidth: liveDisplayRowHeaderWidth,
|
|
21412
|
+
frozenPaneBottom: liveFrozenPaneBottom,
|
|
21413
|
+
frozenPaneRight: liveFrozenPaneRight
|
|
21414
|
+
} = canvasLayoutMetricsRef.current;
|
|
21216
21415
|
const currentLiveGestureZoom = liveGestureZoomRef.current;
|
|
21217
21416
|
const isLiveZooming2 = currentLiveGestureZoom !== null && zoomScale === currentLiveGestureZoom.baseZoomScale;
|
|
21218
21417
|
const liveZoomScale2 = isLiveZooming2 ? Math.max(0.1, currentLiveGestureZoom.targetZoomScale / currentLiveGestureZoom.baseZoomScale) : 1;
|
|
@@ -21220,12 +21419,41 @@ function XlsxGrid({
|
|
|
21220
21419
|
const scrollDeltaY = paintedViewport.top - nextLiveViewport.top;
|
|
21221
21420
|
const liveZoomTranslateX2 = isLiveZooming2 ? currentLiveGestureZoom.anchor.x * (1 - liveZoomScale2) : 0;
|
|
21222
21421
|
const liveZoomTranslateY2 = isLiveZooming2 ? currentLiveGestureZoom.anchor.y * (1 - liveZoomScale2) : 0;
|
|
21223
|
-
const
|
|
21224
|
-
if (!
|
|
21422
|
+
const applyElementTransform = (element, transform, willChange, transformOrigin = null) => {
|
|
21423
|
+
if (!element) {
|
|
21225
21424
|
return;
|
|
21226
21425
|
}
|
|
21227
|
-
|
|
21228
|
-
|
|
21426
|
+
const cached = canvasTransformStyleCacheRef.current.get(element);
|
|
21427
|
+
if (cached?.transform !== transform || element.style.transform !== transform) {
|
|
21428
|
+
element.style.transform = transform;
|
|
21429
|
+
}
|
|
21430
|
+
if (cached?.willChange !== willChange || element.style.willChange !== willChange) {
|
|
21431
|
+
element.style.willChange = willChange;
|
|
21432
|
+
}
|
|
21433
|
+
if (transformOrigin !== null && (cached?.transformOrigin !== transformOrigin || element.style.transformOrigin !== transformOrigin)) {
|
|
21434
|
+
element.style.transformOrigin = transformOrigin;
|
|
21435
|
+
}
|
|
21436
|
+
canvasTransformStyleCacheRef.current.set(element, {
|
|
21437
|
+
transform,
|
|
21438
|
+
transformOrigin,
|
|
21439
|
+
willChange
|
|
21440
|
+
});
|
|
21441
|
+
};
|
|
21442
|
+
const applyCanvasTransform = (canvas, translateX, translateY) => {
|
|
21443
|
+
const shouldTransform = translateX !== 0 || translateY !== 0 || liveZoomScale2 !== 1;
|
|
21444
|
+
applyElementTransform(
|
|
21445
|
+
canvas,
|
|
21446
|
+
shouldTransform ? `translate3d(${translateX}px, ${translateY}px, 0) scale(${liveZoomScale2})` : "",
|
|
21447
|
+
shouldTransform ? "transform" : ""
|
|
21448
|
+
);
|
|
21449
|
+
};
|
|
21450
|
+
const applyOverlayTransform = (element, translateX, translateY) => {
|
|
21451
|
+
applyElementTransform(
|
|
21452
|
+
element,
|
|
21453
|
+
liveZoomScale2 !== 1 ? `translate3d(${translateX + liveZoomTranslateX2}px, ${translateY + liveZoomTranslateY2}px, 0) scale(${liveZoomScale2})` : `translate3d(${translateX}px, ${translateY}px, 0)`,
|
|
21454
|
+
"transform",
|
|
21455
|
+
"0 0"
|
|
21456
|
+
);
|
|
21229
21457
|
};
|
|
21230
21458
|
applyCanvasTransform(
|
|
21231
21459
|
scrollBodyCanvasRef.current,
|
|
@@ -21272,6 +21500,26 @@ function XlsxGrid({
|
|
|
21272
21500
|
liveZoomTranslateX2,
|
|
21273
21501
|
liveZoomTranslateY2
|
|
21274
21502
|
);
|
|
21503
|
+
applyOverlayTransform(
|
|
21504
|
+
canvasScrollOverlayContentRef.current,
|
|
21505
|
+
-nextLiveViewport.left - liveFrozenPaneRight,
|
|
21506
|
+
-nextLiveViewport.top - liveFrozenPaneBottom
|
|
21507
|
+
);
|
|
21508
|
+
applyOverlayTransform(
|
|
21509
|
+
canvasTopOverlayContentRef.current,
|
|
21510
|
+
-nextLiveViewport.left - liveFrozenPaneRight,
|
|
21511
|
+
-liveDisplayHeaderHeight
|
|
21512
|
+
);
|
|
21513
|
+
applyOverlayTransform(
|
|
21514
|
+
canvasLeftOverlayContentRef.current,
|
|
21515
|
+
-liveDisplayRowHeaderWidth,
|
|
21516
|
+
-nextLiveViewport.top - liveFrozenPaneBottom
|
|
21517
|
+
);
|
|
21518
|
+
applyOverlayTransform(
|
|
21519
|
+
canvasCornerOverlayContentRef.current,
|
|
21520
|
+
-liveDisplayRowHeaderWidth,
|
|
21521
|
+
-liveDisplayHeaderHeight
|
|
21522
|
+
);
|
|
21275
21523
|
}, [zoomScale]);
|
|
21276
21524
|
const updateLiveGestureZoomState = React4.useCallback((nextState) => {
|
|
21277
21525
|
const resolvedState = typeof nextState === "function" ? nextState(liveGestureZoomRef.current) : nextState;
|
|
@@ -21374,6 +21622,11 @@ function XlsxGrid({
|
|
|
21374
21622
|
if (matchesLiveViewport && matchesStateViewport) {
|
|
21375
21623
|
return;
|
|
21376
21624
|
}
|
|
21625
|
+
const shouldCommitDeferredViewport = !matchesStateViewport && (stateViewport.width !== nextViewport.width || stateViewport.height !== nextViewport.height || Math.abs(nextViewport.left - stateViewport.left) >= CANVAS_DEFERRED_VIEWPORT_SYNC_THRESHOLD_PX || Math.abs(nextViewport.top - stateViewport.top) >= CANVAS_DEFERRED_VIEWPORT_SYNC_THRESHOLD_PX);
|
|
21626
|
+
if (!shouldCommitDeferredViewport) {
|
|
21627
|
+
pendingDrawingViewportRef.current = null;
|
|
21628
|
+
return;
|
|
21629
|
+
}
|
|
21377
21630
|
pendingDrawingViewportRef.current = nextViewport;
|
|
21378
21631
|
if (drawingViewportFrameRef.current !== null) {
|
|
21379
21632
|
return;
|
|
@@ -21661,6 +21914,12 @@ function XlsxGrid({
|
|
|
21661
21914
|
) : displayRowHeaderWidth,
|
|
21662
21915
|
[displayActualColWidths, displayDefaultColWidth, displayRowHeaderWidth, frozenCols, stickyLeftByCol]
|
|
21663
21916
|
);
|
|
21917
|
+
canvasLayoutMetricsRef.current = {
|
|
21918
|
+
displayHeaderHeight,
|
|
21919
|
+
displayRowHeaderWidth,
|
|
21920
|
+
frozenPaneBottom,
|
|
21921
|
+
frozenPaneRight
|
|
21922
|
+
};
|
|
21664
21923
|
const rowPrefixSumsRef = React4.useRef(rowPrefixSums);
|
|
21665
21924
|
const colPrefixSumsRef = React4.useRef(colPrefixSums);
|
|
21666
21925
|
const firstVisibleRow = visibleRows[0];
|
|
@@ -21712,6 +21971,7 @@ function XlsxGrid({
|
|
|
21712
21971
|
}, [charts, images, shapes]);
|
|
21713
21972
|
const shouldVirtualizeRows = visibleRows.length > 0;
|
|
21714
21973
|
const shouldVirtualizeCols = visibleCols.length > 0 && frozenCols.length === 0;
|
|
21974
|
+
const shouldUseDomVirtualizer = !experimentalCanvas;
|
|
21715
21975
|
const getScrollElement = React4.useCallback(() => scrollRef.current, []);
|
|
21716
21976
|
const estimateRowSize = React4.useCallback(
|
|
21717
21977
|
(index) => displayEffectiveRowHeights[index] ?? displayDefaultRowHeight,
|
|
@@ -21725,6 +21985,7 @@ function XlsxGrid({
|
|
|
21725
21985
|
const getColItemKey = React4.useCallback((index) => visibleCols[index] ?? index, [visibleCols]);
|
|
21726
21986
|
const rowVirtualizer = useVirtualizer({
|
|
21727
21987
|
count: visibleRows.length,
|
|
21988
|
+
enabled: shouldUseDomVirtualizer,
|
|
21728
21989
|
estimateSize: estimateRowSize,
|
|
21729
21990
|
getScrollElement,
|
|
21730
21991
|
getItemKey: getRowItemKey,
|
|
@@ -21732,14 +21993,15 @@ function XlsxGrid({
|
|
|
21732
21993
|
});
|
|
21733
21994
|
const colVirtualizer = useVirtualizer({
|
|
21734
21995
|
count: visibleCols.length,
|
|
21996
|
+
enabled: shouldUseDomVirtualizer,
|
|
21735
21997
|
estimateSize: estimateColSize,
|
|
21736
21998
|
getScrollElement,
|
|
21737
21999
|
getItemKey: getColItemKey,
|
|
21738
22000
|
horizontal: true,
|
|
21739
22001
|
overscan: 6
|
|
21740
22002
|
});
|
|
21741
|
-
const currentRowVirtualItems = rowVirtualizer.getVirtualItems();
|
|
21742
|
-
const currentColVirtualItems = colVirtualizer.getVirtualItems();
|
|
22003
|
+
const currentRowVirtualItems = shouldUseDomVirtualizer ? rowVirtualizer.getVirtualItems() : EMPTY_VIRTUAL_ITEMS;
|
|
22004
|
+
const currentColVirtualItems = shouldUseDomVirtualizer ? colVirtualizer.getVirtualItems() : EMPTY_VIRTUAL_ITEMS;
|
|
21743
22005
|
const frozenRowVirtualIndices = React4.useMemo(
|
|
21744
22006
|
() => frozenRows.map((row) => rowIndexByActual.get(row)).filter((index) => index !== void 0),
|
|
21745
22007
|
[frozenRows, rowIndexByActual]
|
|
@@ -21975,10 +22237,12 @@ function XlsxGrid({
|
|
|
21975
22237
|
scroller.scrollTop = scroller.scrollTop / previousZoomFactor * zoomFactor;
|
|
21976
22238
|
}
|
|
21977
22239
|
previousZoomFactorRef.current = zoomFactor;
|
|
21978
|
-
|
|
21979
|
-
|
|
22240
|
+
if (shouldUseDomVirtualizer) {
|
|
22241
|
+
rowVirtualizer.measure();
|
|
22242
|
+
colVirtualizer.measure();
|
|
22243
|
+
}
|
|
21980
22244
|
syncDrawingViewport(scroller, { immediate: true });
|
|
21981
|
-
}, [syncDrawingViewport, zoomFactor]);
|
|
22245
|
+
}, [shouldUseDomVirtualizer, syncDrawingViewport, zoomFactor]);
|
|
21982
22246
|
React4.useLayoutEffect(() => {
|
|
21983
22247
|
syncDrawingViewport(scrollRef.current, { immediate: true });
|
|
21984
22248
|
}, [activeSheet, activeTabIndex, displayColLimit, displayRowLimit, syncDrawingViewport, zoomFactor]);
|
|
@@ -22074,7 +22338,7 @@ function XlsxGrid({
|
|
|
22074
22338
|
const initialUsedCol = resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1);
|
|
22075
22339
|
const initialScrollTop = initialUsedRow > 0 ? sumPrefixRange(actualRowPrefixSums, 0, initialUsedRow - 1) : 0;
|
|
22076
22340
|
const initialScrollLeft = initialUsedCol > 0 ? sumPrefixRange(actualColPrefixSums, 0, initialUsedCol - 1) : 0;
|
|
22077
|
-
if (shouldVirtualizeRows) {
|
|
22341
|
+
if (shouldUseDomVirtualizer && shouldVirtualizeRows) {
|
|
22078
22342
|
rowVirtualizer.scrollToOffset(initialScrollTop);
|
|
22079
22343
|
} else if (scrollRef.current) {
|
|
22080
22344
|
scrollRef.current.scrollTop = initialScrollTop;
|
|
@@ -22082,7 +22346,7 @@ function XlsxGrid({
|
|
|
22082
22346
|
if (scrollRef.current) {
|
|
22083
22347
|
scrollRef.current.scrollLeft = initialScrollLeft;
|
|
22084
22348
|
}
|
|
22085
|
-
if (shouldVirtualizeCols && frozenCols.length === 0) {
|
|
22349
|
+
if (shouldUseDomVirtualizer && shouldVirtualizeCols && frozenCols.length === 0) {
|
|
22086
22350
|
colVirtualizer.scrollToOffset(initialScrollLeft);
|
|
22087
22351
|
}
|
|
22088
22352
|
if (scrollRef.current) {
|
|
@@ -22103,6 +22367,7 @@ function XlsxGrid({
|
|
|
22103
22367
|
isWorkerBacked,
|
|
22104
22368
|
shouldVirtualizeCols,
|
|
22105
22369
|
shouldVirtualizeRows,
|
|
22370
|
+
shouldUseDomVirtualizer,
|
|
22106
22371
|
syncDrawingViewport,
|
|
22107
22372
|
rowVirtualizer,
|
|
22108
22373
|
visibleCols,
|
|
@@ -22122,24 +22387,40 @@ function XlsxGrid({
|
|
|
22122
22387
|
setPendingNavigation(null);
|
|
22123
22388
|
}, [activeSheetIndex, pendingNavigation, selectCell]);
|
|
22124
22389
|
React4.useEffect(() => {
|
|
22125
|
-
if (shouldVirtualizeRows) {
|
|
22390
|
+
if (shouldUseDomVirtualizer && shouldVirtualizeRows) {
|
|
22126
22391
|
rowVirtualizer.measure();
|
|
22127
22392
|
}
|
|
22128
|
-
if (shouldVirtualizeCols) {
|
|
22393
|
+
if (shouldUseDomVirtualizer && shouldVirtualizeCols) {
|
|
22129
22394
|
colVirtualizer.measure();
|
|
22130
22395
|
}
|
|
22131
|
-
}, [
|
|
22396
|
+
}, [
|
|
22397
|
+
activeSheetIndex,
|
|
22398
|
+
revision,
|
|
22399
|
+
shouldUseDomVirtualizer,
|
|
22400
|
+
shouldVirtualizeCols,
|
|
22401
|
+
shouldVirtualizeRows,
|
|
22402
|
+
visibleCols.length,
|
|
22403
|
+
visibleRows.length
|
|
22404
|
+
]);
|
|
22132
22405
|
const handleScrollerScroll = React4.useCallback((event) => {
|
|
22133
22406
|
const currentScroller = event.currentTarget;
|
|
22134
22407
|
cachedScrollerRectRef.current = null;
|
|
22135
|
-
|
|
22408
|
+
const paintedViewport = paintedDrawingViewportRef.current;
|
|
22409
|
+
const shouldSyncDrawingViewportImmediately = Math.abs(currentScroller.scrollLeft - paintedViewport.left) > CANVAS_IMMEDIATE_VIEWPORT_SYNC_THRESHOLD_PX || Math.abs(currentScroller.scrollTop - paintedViewport.top) > CANVAS_IMMEDIATE_VIEWPORT_SYNC_THRESHOLD_PX;
|
|
22410
|
+
syncDrawingViewport(currentScroller, { immediate: shouldSyncDrawingViewportImmediately });
|
|
22136
22411
|
if (currentScroller.scrollHeight - (currentScroller.scrollTop + currentScroller.clientHeight) < OPEN_GRID_VERTICAL_EDGE_PX) {
|
|
22137
|
-
setDisplayRowLimit((current) =>
|
|
22412
|
+
setDisplayRowLimit((current) => {
|
|
22413
|
+
const nextLimit = current + OPEN_GRID_ROW_GROWTH;
|
|
22414
|
+
return readOnly && current < maxRowDisplayLimit ? Math.min(maxRowDisplayLimit, nextLimit) : nextLimit;
|
|
22415
|
+
});
|
|
22138
22416
|
}
|
|
22139
22417
|
if (currentScroller.scrollWidth - (currentScroller.scrollLeft + currentScroller.clientWidth) < OPEN_GRID_HORIZONTAL_EDGE_PX) {
|
|
22140
|
-
setDisplayColLimit((current) =>
|
|
22418
|
+
setDisplayColLimit((current) => {
|
|
22419
|
+
const nextLimit = current + OPEN_GRID_COL_GROWTH;
|
|
22420
|
+
return readOnly && current < maxColDisplayLimit ? Math.min(maxColDisplayLimit, nextLimit) : nextLimit;
|
|
22421
|
+
});
|
|
22141
22422
|
}
|
|
22142
|
-
}, [syncDrawingViewport]);
|
|
22423
|
+
}, [maxColDisplayLimit, maxRowDisplayLimit, readOnly, syncDrawingViewport]);
|
|
22143
22424
|
React4.useEffect(() => {
|
|
22144
22425
|
const scroller = scrollRef.current;
|
|
22145
22426
|
if (!scroller || !enableGestureZoom) {
|
|
@@ -22396,17 +22677,17 @@ function XlsxGrid({
|
|
|
22396
22677
|
}, []);
|
|
22397
22678
|
const resolvePointerCellFromClient = React4.useCallback((clientX, clientY) => {
|
|
22398
22679
|
const geometryCell = resolvePointerCellFromGeometry(clientX, clientY);
|
|
22399
|
-
if (geometryCell
|
|
22400
|
-
return
|
|
22680
|
+
if (geometryCell) {
|
|
22681
|
+
return geometryCell;
|
|
22401
22682
|
}
|
|
22402
|
-
const resolvedCell = resolvePointerCellFromHitTest(clientX, clientY)
|
|
22683
|
+
const resolvedCell = resolvePointerCellFromHitTest(clientX, clientY);
|
|
22403
22684
|
return resolvedCell ? resolveMergeAnchorCell(resolvedCell) : null;
|
|
22404
|
-
}, [resolveMergeAnchorCell, resolvePointerCellFromGeometry, resolvePointerCellFromHitTest
|
|
22685
|
+
}, [resolveMergeAnchorCell, resolvePointerCellFromGeometry, resolvePointerCellFromHitTest]);
|
|
22405
22686
|
const resolveDraggedSelectionCell = React4.useCallback((dragState, clientX, clientY) => {
|
|
22406
22687
|
const geometryCell = resolvePointerCellFromGeometry(clientX, clientY);
|
|
22407
22688
|
const hitCell = resolvePointerCellFromHitTest(clientX, clientY);
|
|
22408
|
-
const actualRow = hitCell && rowIndexByActual.has(hitCell.row) ? hitCell.row :
|
|
22409
|
-
const actualCol =
|
|
22689
|
+
const actualRow = geometryCell?.row ?? (hitCell && rowIndexByActual.has(hitCell.row) ? hitCell.row : void 0);
|
|
22690
|
+
const actualCol = geometryCell?.col ?? hitCell?.col;
|
|
22410
22691
|
if (actualRow === void 0 || actualCol === void 0) {
|
|
22411
22692
|
return null;
|
|
22412
22693
|
}
|
|
@@ -22416,8 +22697,8 @@ function XlsxGrid({
|
|
|
22416
22697
|
if (dragState.axis === "column") {
|
|
22417
22698
|
return { row: dragState.originCell.row, col: actualCol };
|
|
22418
22699
|
}
|
|
22419
|
-
return
|
|
22420
|
-
}, [
|
|
22700
|
+
return { row: actualRow, col: actualCol };
|
|
22701
|
+
}, [resolvePointerCellFromGeometry, resolvePointerCellFromHitTest, rowIndexByActual]);
|
|
22421
22702
|
const resolveCellPointerOrigin = React4.useCallback((cell, rect, clientX, clientY) => {
|
|
22422
22703
|
const rowIndex = rowIndexByActual.get(cell.row);
|
|
22423
22704
|
const colIndex = colIndexByActual.get(cell.col);
|
|
@@ -22435,6 +22716,40 @@ function XlsxGrid({
|
|
|
22435
22716
|
originContentY: (rowPrefixSums[rowIndex] ?? 0) + clampContentOffset((clientY - rect.top) / contentScaleY, displayHeight)
|
|
22436
22717
|
};
|
|
22437
22718
|
}, [colIndexByActual, colPrefixSums, displayDefaultColWidth, displayDefaultRowHeight, displayEffectiveColWidths, displayEffectiveRowHeights, rowIndexByActual, rowPrefixSums]);
|
|
22719
|
+
const resolveCellPointerOriginFromClient = React4.useCallback((cell, clientX, clientY) => {
|
|
22720
|
+
const scroller = scrollRef.current;
|
|
22721
|
+
const rowIndex = rowIndexByActual.get(cell.row);
|
|
22722
|
+
const colIndex = colIndexByActual.get(cell.col);
|
|
22723
|
+
if (!scroller || rowIndex === void 0 || colIndex === void 0) {
|
|
22724
|
+
return null;
|
|
22725
|
+
}
|
|
22726
|
+
const scrollerRect = cachedScrollerRectRef.current ?? scroller.getBoundingClientRect();
|
|
22727
|
+
const pointerOffsetX = clientX - scrollerRect.left;
|
|
22728
|
+
const pointerOffsetY = clientY - scrollerRect.top;
|
|
22729
|
+
const localX = pointerOffsetX + (pointerOffsetX >= frozenPaneRight ? scroller.scrollLeft : 0);
|
|
22730
|
+
const localY = pointerOffsetY + (pointerOffsetY >= frozenPaneBottom ? scroller.scrollTop : 0);
|
|
22731
|
+
const displayWidth = displayEffectiveColWidths[colIndex] ?? displayDefaultColWidth;
|
|
22732
|
+
const displayHeight = displayEffectiveRowHeights[rowIndex] ?? displayDefaultRowHeight;
|
|
22733
|
+
return {
|
|
22734
|
+
contentScaleX: 1,
|
|
22735
|
+
contentScaleY: 1,
|
|
22736
|
+
originContentX: (colPrefixSums[colIndex] ?? 0) + clampContentOffset(localX - displayRowHeaderWidth - (colPrefixSums[colIndex] ?? 0), displayWidth),
|
|
22737
|
+
originContentY: (rowPrefixSums[rowIndex] ?? 0) + clampContentOffset(localY - displayHeaderHeight - (rowPrefixSums[rowIndex] ?? 0), displayHeight)
|
|
22738
|
+
};
|
|
22739
|
+
}, [
|
|
22740
|
+
colIndexByActual,
|
|
22741
|
+
colPrefixSums,
|
|
22742
|
+
displayDefaultColWidth,
|
|
22743
|
+
displayDefaultRowHeight,
|
|
22744
|
+
displayEffectiveColWidths,
|
|
22745
|
+
displayEffectiveRowHeights,
|
|
22746
|
+
displayHeaderHeight,
|
|
22747
|
+
displayRowHeaderWidth,
|
|
22748
|
+
frozenPaneBottom,
|
|
22749
|
+
frozenPaneRight,
|
|
22750
|
+
rowIndexByActual,
|
|
22751
|
+
rowPrefixSums
|
|
22752
|
+
]);
|
|
22438
22753
|
const resolveRowPointerOrigin = React4.useCallback((actualRow, rect, clientY) => {
|
|
22439
22754
|
const rowIndex = rowIndexByActual.get(actualRow);
|
|
22440
22755
|
if (rowIndex === void 0) {
|
|
@@ -23011,14 +23326,14 @@ function XlsxGrid({
|
|
|
23011
23326
|
},
|
|
23012
23327
|
left: {
|
|
23013
23328
|
cols: frozenColItems,
|
|
23014
|
-
rows:
|
|
23329
|
+
rows: scrollRowItems
|
|
23015
23330
|
},
|
|
23016
23331
|
scroll: {
|
|
23017
|
-
cols:
|
|
23018
|
-
rows:
|
|
23332
|
+
cols: scrollColItems,
|
|
23333
|
+
rows: scrollRowItems
|
|
23019
23334
|
},
|
|
23020
23335
|
top: {
|
|
23021
|
-
cols:
|
|
23336
|
+
cols: scrollColItems,
|
|
23022
23337
|
rows: frozenRowItems
|
|
23023
23338
|
}
|
|
23024
23339
|
};
|
|
@@ -23152,6 +23467,51 @@ function XlsxGrid({
|
|
|
23152
23467
|
visibleRows
|
|
23153
23468
|
]
|
|
23154
23469
|
);
|
|
23470
|
+
const shouldBakeCanvasStaticDrawings = Boolean(experimentalCanvas && readOnly && showImages);
|
|
23471
|
+
const shouldBakeCanvasImages = Boolean(shouldBakeCanvasStaticDrawings && !renderImage && !renderImageSelection);
|
|
23472
|
+
const bakedShapeRects = React4.useMemo(
|
|
23473
|
+
() => shouldBakeCanvasStaticDrawings ? shapeRects.filter(({ shape }) => !shape.hyperlink) : [],
|
|
23474
|
+
[shapeRects, shouldBakeCanvasStaticDrawings]
|
|
23475
|
+
);
|
|
23476
|
+
const domShapeRects = React4.useMemo(
|
|
23477
|
+
() => shouldBakeCanvasStaticDrawings ? shapeRects.filter(({ shape }) => shape.hyperlink) : shapeRects,
|
|
23478
|
+
[shapeRects, shouldBakeCanvasStaticDrawings]
|
|
23479
|
+
);
|
|
23480
|
+
const bakedFormControlRects = React4.useMemo(
|
|
23481
|
+
() => shouldBakeCanvasStaticDrawings ? formControlRects : [],
|
|
23482
|
+
[formControlRects, shouldBakeCanvasStaticDrawings]
|
|
23483
|
+
);
|
|
23484
|
+
const domFormControlRects = React4.useMemo(
|
|
23485
|
+
() => shouldBakeCanvasStaticDrawings ? [] : formControlRects,
|
|
23486
|
+
[formControlRects, shouldBakeCanvasStaticDrawings]
|
|
23487
|
+
);
|
|
23488
|
+
const bakedImageRects = React4.useMemo(
|
|
23489
|
+
() => shouldBakeCanvasImages ? imageRects.filter(({ image }) => !image.hyperlink && selectedImageId !== image.id) : [],
|
|
23490
|
+
[imageRects, selectedImageId, shouldBakeCanvasImages]
|
|
23491
|
+
);
|
|
23492
|
+
const domImageRects = React4.useMemo(
|
|
23493
|
+
() => shouldBakeCanvasImages ? imageRects.filter(({ image }) => image.hyperlink || selectedImageId === image.id) : imageRects,
|
|
23494
|
+
[imageRects, selectedImageId, shouldBakeCanvasImages]
|
|
23495
|
+
);
|
|
23496
|
+
const hasCanvasDomDrawingOverlays = Boolean(
|
|
23497
|
+
showImages && (chartRects.length > 0 || domShapeRects.length > 0 || domFormControlRects.length > 0 || domImageRects.length > 0)
|
|
23498
|
+
);
|
|
23499
|
+
const bakedCanvasDrawingSignature = React4.useMemo(() => {
|
|
23500
|
+
if (!shouldBakeCanvasStaticDrawings) {
|
|
23501
|
+
return "";
|
|
23502
|
+
}
|
|
23503
|
+
const shapeSignature = bakedShapeRects.map(({ rect, shape }) => `s:${shape.id}:${shape.zIndex}:${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(rect.width)}:${Math.round(rect.height)}`).join("|");
|
|
23504
|
+
const controlSignature = bakedFormControlRects.map(({ control, rect }) => `f:${control.id}:${control.zIndex}:${Boolean(control.checked)}:${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(rect.width)}:${Math.round(rect.height)}`).join("|");
|
|
23505
|
+
const imageSignature = bakedImageRects.map(({ image, rect }) => `i:${image.id}:${image.src}:${image.zIndex}:${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(rect.width)}:${Math.round(rect.height)}`).join("|");
|
|
23506
|
+
return `${revision}:${canvasImageLoadVersion}:${shapeSignature}:${controlSignature}:${imageSignature}`;
|
|
23507
|
+
}, [
|
|
23508
|
+
bakedFormControlRects,
|
|
23509
|
+
bakedImageRects,
|
|
23510
|
+
bakedShapeRects,
|
|
23511
|
+
canvasImageLoadVersion,
|
|
23512
|
+
revision,
|
|
23513
|
+
shouldBakeCanvasStaticDrawings
|
|
23514
|
+
]);
|
|
23155
23515
|
const resolveMountedCellOverlayRect = React4.useCallback((element) => {
|
|
23156
23516
|
const wrapper = wrapperRef.current;
|
|
23157
23517
|
if (!wrapper) {
|
|
@@ -23183,10 +23543,11 @@ function XlsxGrid({
|
|
|
23183
23543
|
}, [resolveMountedCellOverlayRect]);
|
|
23184
23544
|
const resolveGeometryOverlayRect = React4.useCallback((range) => {
|
|
23185
23545
|
const normalized = normalizeRange2(range);
|
|
23186
|
-
const startCell = resolveMergeAnchorCell(normalized.start);
|
|
23187
23546
|
const isSingleCellSelection = normalized.start.row === normalized.end.row && normalized.start.col === normalized.end.col;
|
|
23188
|
-
const
|
|
23189
|
-
const
|
|
23547
|
+
const isMergedSecondarySelection = isSingleCellSelection ? worksheet?.isMergedSecondary(normalized.start.row, normalized.start.col) === true : false;
|
|
23548
|
+
const startCell = isSingleCellSelection && !isMergedSecondarySelection ? resolveMergeAnchorCell(normalized.start) : normalized.start;
|
|
23549
|
+
const merge = isSingleCellSelection && !isMergedSecondarySelection ? worksheet?.getMergeSpan(startCell.row, startCell.col) : null;
|
|
23550
|
+
const endCell = isSingleCellSelection && !isMergedSecondarySelection ? {
|
|
23190
23551
|
row: startCell.row + Math.max(1, merge?.rowSpan ?? 1) - 1,
|
|
23191
23552
|
col: startCell.col + Math.max(1, merge?.colSpan ?? 1) - 1
|
|
23192
23553
|
} : normalized.end;
|
|
@@ -23818,13 +24179,14 @@ function XlsxGrid({
|
|
|
23818
24179
|
}
|
|
23819
24180
|
event.preventDefault();
|
|
23820
24181
|
focusGrid();
|
|
24182
|
+
const targetCell = event.currentTarget.colSpan > 1 || event.currentTarget.rowSpan > 1 ? resolvePointerCellFromGeometry(event.clientX, event.clientY) ?? cell : cell;
|
|
23821
24183
|
const currentSelection = selectionRef.current;
|
|
23822
|
-
const anchor = event.shiftKey && currentSelection ? currentSelection.start :
|
|
23823
|
-
const initialRange = normalizeRange2({ start: anchor, end:
|
|
23824
|
-
const isActive = isSameCell(activeCellRef.current,
|
|
24184
|
+
const anchor = event.shiftKey && currentSelection ? currentSelection.start : targetCell;
|
|
24185
|
+
const initialRange = normalizeRange2({ start: anchor, end: targetCell });
|
|
24186
|
+
const isActive = isSameCell(activeCellRef.current, targetCell);
|
|
23825
24187
|
const committedOnPointerDown = !isActive || !editingCellRef.current;
|
|
23826
|
-
const pointerOrigin = resolveCellPointerOrigin(cell, event.currentTarget.getBoundingClientRect(), event.clientX, event.clientY);
|
|
23827
|
-
const originOverlayRect = resolveMountedCellOverlayRect(event.currentTarget);
|
|
24188
|
+
const pointerOrigin = targetCell.row === cell.row && targetCell.col === cell.col ? resolveCellPointerOrigin(cell, event.currentTarget.getBoundingClientRect(), event.clientX, event.clientY) : resolveCellPointerOriginFromClient(targetCell, event.clientX, event.clientY);
|
|
24189
|
+
const originOverlayRect = targetCell.row === cell.row && targetCell.col === cell.col ? resolveMountedCellOverlayRect(event.currentTarget) : resolveOverlayRect(initialRange);
|
|
23828
24190
|
if (!pointerOrigin) {
|
|
23829
24191
|
return;
|
|
23830
24192
|
}
|
|
@@ -23832,7 +24194,7 @@ function XlsxGrid({
|
|
|
23832
24194
|
event.pointerId,
|
|
23833
24195
|
anchor,
|
|
23834
24196
|
"cell",
|
|
23835
|
-
|
|
24197
|
+
targetCell,
|
|
23836
24198
|
pointerOrigin,
|
|
23837
24199
|
originOverlayRect,
|
|
23838
24200
|
committedOnPointerDown,
|
|
@@ -23840,11 +24202,25 @@ function XlsxGrid({
|
|
|
23840
24202
|
event.clientX,
|
|
23841
24203
|
event.clientY
|
|
23842
24204
|
);
|
|
23843
|
-
|
|
24205
|
+
if (targetCell.row === cell.row && targetCell.col === cell.col) {
|
|
24206
|
+
applyPreviewOverlayFromElement(event.currentTarget, initialRange);
|
|
24207
|
+
} else {
|
|
24208
|
+
applyPreviewOverlay(initialRange);
|
|
24209
|
+
}
|
|
23844
24210
|
if (committedOnPointerDown) {
|
|
23845
24211
|
commitSelectionRange(initialRange);
|
|
23846
24212
|
}
|
|
23847
|
-
}, [
|
|
24213
|
+
}, [
|
|
24214
|
+
applyPreviewOverlay,
|
|
24215
|
+
applyPreviewOverlayFromElement,
|
|
24216
|
+
commitSelectionRange,
|
|
24217
|
+
focusGrid,
|
|
24218
|
+
resolveCellPointerOrigin,
|
|
24219
|
+
resolveCellPointerOriginFromClient,
|
|
24220
|
+
resolveMountedCellOverlayRect,
|
|
24221
|
+
resolveOverlayRect,
|
|
24222
|
+
resolvePointerCellFromGeometry
|
|
24223
|
+
]);
|
|
23848
24224
|
const handleRowPointerDown = React4.useCallback((event, actualRow) => {
|
|
23849
24225
|
if (event.button !== 0 || firstVisibleCol === void 0 || lastVisibleCol === void 0) {
|
|
23850
24226
|
return;
|
|
@@ -24004,6 +24380,24 @@ function XlsxGrid({
|
|
|
24004
24380
|
rowPrefixSums,
|
|
24005
24381
|
stickyTopByRow
|
|
24006
24382
|
]);
|
|
24383
|
+
const scrollBodyViewportWidth = Math.max(0, drawingViewport.width - frozenPaneRight);
|
|
24384
|
+
const scrollBodyViewportHeight = Math.max(0, drawingViewport.height - frozenPaneBottom);
|
|
24385
|
+
const canvasScrollBufferX = Math.min(CANVAS_SCROLL_BUFFER_PX, scrollBodyViewportWidth);
|
|
24386
|
+
const canvasScrollBufferY = Math.min(CANVAS_SCROLL_BUFFER_PX, scrollBodyViewportHeight);
|
|
24387
|
+
const scrollBodyCanvasLeft = frozenPaneRight - canvasScrollBufferX;
|
|
24388
|
+
const scrollBodyCanvasTop = frozenPaneBottom - canvasScrollBufferY;
|
|
24389
|
+
const scrollBodyCanvasWidth = scrollBodyViewportWidth + canvasScrollBufferX * 2;
|
|
24390
|
+
const scrollBodyCanvasHeight = scrollBodyViewportHeight + canvasScrollBufferY * 2;
|
|
24391
|
+
const topBodyCanvasWidth = scrollBodyCanvasWidth;
|
|
24392
|
+
const topBodyCanvasHeight = Math.max(0, frozenPaneBottom - displayHeaderHeight);
|
|
24393
|
+
const leftBodyCanvasWidth = Math.max(0, frozenPaneRight - displayRowHeaderWidth);
|
|
24394
|
+
const leftBodyCanvasHeight = scrollBodyCanvasHeight;
|
|
24395
|
+
const cornerBodyCanvasWidth = leftBodyCanvasWidth;
|
|
24396
|
+
const cornerBodyCanvasHeight = topBodyCanvasHeight;
|
|
24397
|
+
const topFrozenHeaderCanvasWidth = leftBodyCanvasWidth;
|
|
24398
|
+
const topScrollHeaderCanvasWidth = scrollBodyCanvasWidth;
|
|
24399
|
+
const leftFrozenHeaderCanvasHeight = topBodyCanvasHeight;
|
|
24400
|
+
const leftScrollHeaderCanvasHeight = scrollBodyCanvasHeight;
|
|
24007
24401
|
const canvasColumnHeaderCells = React4.useMemo(
|
|
24008
24402
|
() => canvasVisibleColItems.flatMap((column) => {
|
|
24009
24403
|
const rect = resolveCanvasColumnHeaderRect(column.actualCol);
|
|
@@ -24016,7 +24410,7 @@ function XlsxGrid({
|
|
|
24016
24410
|
height: displayHeaderHeight,
|
|
24017
24411
|
isFrozen,
|
|
24018
24412
|
left: rect.left,
|
|
24019
|
-
localLeft: rect.left - (isFrozen ? displayRowHeaderWidth :
|
|
24413
|
+
localLeft: rect.left - (isFrozen ? displayRowHeaderWidth : scrollBodyCanvasLeft),
|
|
24020
24414
|
width: rect.width
|
|
24021
24415
|
}];
|
|
24022
24416
|
}),
|
|
@@ -24024,8 +24418,8 @@ function XlsxGrid({
|
|
|
24024
24418
|
canvasVisibleColItems,
|
|
24025
24419
|
displayHeaderHeight,
|
|
24026
24420
|
displayRowHeaderWidth,
|
|
24027
|
-
frozenPaneRight,
|
|
24028
24421
|
resolveCanvasColumnHeaderRect,
|
|
24422
|
+
scrollBodyCanvasLeft,
|
|
24029
24423
|
stickyLeftByCol
|
|
24030
24424
|
]
|
|
24031
24425
|
);
|
|
@@ -24040,15 +24434,15 @@ function XlsxGrid({
|
|
|
24040
24434
|
actualRow: row.actualRow,
|
|
24041
24435
|
height: rect.height,
|
|
24042
24436
|
isFrozen,
|
|
24043
|
-
localTop: rect.top - (isFrozen ? displayHeaderHeight :
|
|
24437
|
+
localTop: rect.top - (isFrozen ? displayHeaderHeight : scrollBodyCanvasTop),
|
|
24044
24438
|
top: rect.top
|
|
24045
24439
|
}];
|
|
24046
24440
|
}),
|
|
24047
24441
|
[
|
|
24048
24442
|
canvasVisibleRowItems,
|
|
24049
24443
|
displayHeaderHeight,
|
|
24050
|
-
frozenPaneBottom,
|
|
24051
24444
|
resolveCanvasRowHeaderRect,
|
|
24445
|
+
scrollBodyCanvasTop,
|
|
24052
24446
|
stickyTopByRow
|
|
24053
24447
|
]
|
|
24054
24448
|
);
|
|
@@ -24315,10 +24709,46 @@ function XlsxGrid({
|
|
|
24315
24709
|
rowPrefixSums,
|
|
24316
24710
|
startCellSelection
|
|
24317
24711
|
]);
|
|
24712
|
+
const getCanvasImage = React4.useCallback((image) => {
|
|
24713
|
+
if (typeof Image === "undefined") {
|
|
24714
|
+
return null;
|
|
24715
|
+
}
|
|
24716
|
+
const cacheKey = image.id;
|
|
24717
|
+
const cached = canvasImageCacheRef.current.get(cacheKey);
|
|
24718
|
+
if (cached && cached.src === image.src) {
|
|
24719
|
+
return cached.loaded && !cached.failed ? cached.image : null;
|
|
24720
|
+
}
|
|
24721
|
+
const imageElement = new Image();
|
|
24722
|
+
const entry = {
|
|
24723
|
+
failed: false,
|
|
24724
|
+
image: imageElement,
|
|
24725
|
+
loaded: false,
|
|
24726
|
+
src: image.src
|
|
24727
|
+
};
|
|
24728
|
+
canvasImageCacheRef.current.set(cacheKey, entry);
|
|
24729
|
+
imageElement.onload = () => {
|
|
24730
|
+
entry.loaded = true;
|
|
24731
|
+
setCanvasImageLoadVersion((version) => version + 1);
|
|
24732
|
+
};
|
|
24733
|
+
imageElement.onerror = () => {
|
|
24734
|
+
entry.failed = true;
|
|
24735
|
+
setCanvasImageLoadVersion((version) => version + 1);
|
|
24736
|
+
};
|
|
24737
|
+
imageElement.src = image.src;
|
|
24738
|
+
return null;
|
|
24739
|
+
}, []);
|
|
24318
24740
|
React4.useLayoutEffect(() => {
|
|
24319
24741
|
if (!experimentalCanvas) {
|
|
24320
24742
|
return;
|
|
24321
24743
|
}
|
|
24744
|
+
const canvasProfileTarget = typeof window !== "undefined" ? window.__xlsxCanvasProfile : void 0;
|
|
24745
|
+
const canvasProfileStart = canvasProfileTarget ? performance.now() : 0;
|
|
24746
|
+
let canvasProfileBodyStart = 0;
|
|
24747
|
+
let canvasProfileBodyMs = 0;
|
|
24748
|
+
let canvasProfileCulledCells = 0;
|
|
24749
|
+
let canvasProfileDirtyRects = 0;
|
|
24750
|
+
let canvasProfileLookedUpCells = 0;
|
|
24751
|
+
let canvasProfilePaintedCells = 0;
|
|
24322
24752
|
const dpr = typeof window === "undefined" ? 1 : Math.max(1, window.devicePixelRatio || 1);
|
|
24323
24753
|
function configureCanvas(canvas, width, height, options) {
|
|
24324
24754
|
if (!canvas) {
|
|
@@ -24338,7 +24768,7 @@ function XlsxGrid({
|
|
|
24338
24768
|
if (canvas.style.height !== `${height}px`) {
|
|
24339
24769
|
canvas.style.height = `${height}px`;
|
|
24340
24770
|
}
|
|
24341
|
-
const context = canvas.getContext("2d");
|
|
24771
|
+
const context = canvas.getContext("2d", { alpha: false });
|
|
24342
24772
|
if (!context) {
|
|
24343
24773
|
return null;
|
|
24344
24774
|
}
|
|
@@ -24357,6 +24787,7 @@ function XlsxGrid({
|
|
|
24357
24787
|
const rangeSignature = buildRangeSignature(normalizedVisibleRange);
|
|
24358
24788
|
const nextBodyCanvasSignature = {
|
|
24359
24789
|
activeSheet: activeSheet ?? null,
|
|
24790
|
+
bakedDrawingSignature: bakedCanvasDrawingSignature,
|
|
24360
24791
|
bodyHeight,
|
|
24361
24792
|
bodyWidth,
|
|
24362
24793
|
colSignature: buildRenderedAxisSignature(canvasVisibleColItems, (item) => item.index),
|
|
@@ -24384,10 +24815,10 @@ function XlsxGrid({
|
|
|
24384
24815
|
const previousBodyCanvasSignature = paintedBodyCanvasSignatureRef.current;
|
|
24385
24816
|
const previousHeaderCanvasSignature = paintedHeaderCanvasSignatureRef.current;
|
|
24386
24817
|
const previousPaintedViewport = paintedDrawingViewportRef.current;
|
|
24387
|
-
const shouldRepaintBody = !(previousBodyCanvasSignature && previousBodyCanvasSignature.activeSheet === nextBodyCanvasSignature.activeSheet && previousBodyCanvasSignature.bodyHeight === nextBodyCanvasSignature.bodyHeight && previousBodyCanvasSignature.bodyWidth === nextBodyCanvasSignature.bodyWidth && previousBodyCanvasSignature.colSignature === nextBodyCanvasSignature.colSignature && previousBodyCanvasSignature.getCellData === nextBodyCanvasSignature.getCellData && previousBodyCanvasSignature.headerHeight === nextBodyCanvasSignature.headerHeight && previousBodyCanvasSignature.palette === nextBodyCanvasSignature.palette && previousBodyCanvasSignature.rowHeaderWidth === nextBodyCanvasSignature.rowHeaderWidth && previousBodyCanvasSignature.rowSignature === nextBodyCanvasSignature.rowSignature && previousBodyCanvasSignature.zoomFactor === nextBodyCanvasSignature.zoomFactor);
|
|
24818
|
+
const shouldRepaintBody = !(previousBodyCanvasSignature && previousBodyCanvasSignature.activeSheet === nextBodyCanvasSignature.activeSheet && previousBodyCanvasSignature.bakedDrawingSignature === nextBodyCanvasSignature.bakedDrawingSignature && previousBodyCanvasSignature.bodyHeight === nextBodyCanvasSignature.bodyHeight && previousBodyCanvasSignature.bodyWidth === nextBodyCanvasSignature.bodyWidth && previousBodyCanvasSignature.colSignature === nextBodyCanvasSignature.colSignature && previousBodyCanvasSignature.getCellData === nextBodyCanvasSignature.getCellData && previousBodyCanvasSignature.headerHeight === nextBodyCanvasSignature.headerHeight && previousBodyCanvasSignature.palette === nextBodyCanvasSignature.palette && previousBodyCanvasSignature.rowHeaderWidth === nextBodyCanvasSignature.rowHeaderWidth && previousBodyCanvasSignature.rowSignature === nextBodyCanvasSignature.rowSignature && previousBodyCanvasSignature.zoomFactor === nextBodyCanvasSignature.zoomFactor);
|
|
24388
24819
|
const shouldRepaintHeaders = !(previousHeaderCanvasSignature && previousHeaderCanvasSignature.activeSheet === nextHeaderCanvasSignature.activeSheet && previousHeaderCanvasSignature.bodyHeight === nextHeaderCanvasSignature.bodyHeight && previousHeaderCanvasSignature.bodyWidth === nextHeaderCanvasSignature.bodyWidth && previousHeaderCanvasSignature.colSignature === nextHeaderCanvasSignature.colSignature && previousHeaderCanvasSignature.headerHeight === nextHeaderCanvasSignature.headerHeight && previousHeaderCanvasSignature.palette === nextHeaderCanvasSignature.palette && previousHeaderCanvasSignature.rangeSignature === nextHeaderCanvasSignature.rangeSignature && previousHeaderCanvasSignature.rowHeaderWidth === nextHeaderCanvasSignature.rowHeaderWidth && previousHeaderCanvasSignature.rowSignature === nextHeaderCanvasSignature.rowSignature && previousHeaderCanvasSignature.viewportLeft === nextHeaderCanvasSignature.viewportLeft && previousHeaderCanvasSignature.viewportTop === nextHeaderCanvasSignature.viewportTop && previousHeaderCanvasSignature.zoomFactor === nextHeaderCanvasSignature.zoomFactor);
|
|
24389
24820
|
const canBlitBody = Boolean(
|
|
24390
|
-
shouldRepaintBody && previousBodyCanvasSignature && previousBodyCanvasSignature.activeSheet === nextBodyCanvasSignature.activeSheet && previousBodyCanvasSignature.bodyHeight === nextBodyCanvasSignature.bodyHeight && previousBodyCanvasSignature.bodyWidth === nextBodyCanvasSignature.bodyWidth && previousBodyCanvasSignature.getCellData === nextBodyCanvasSignature.getCellData && previousBodyCanvasSignature.headerHeight === nextBodyCanvasSignature.headerHeight && previousBodyCanvasSignature.palette === nextBodyCanvasSignature.palette && previousBodyCanvasSignature.rowHeaderWidth === nextBodyCanvasSignature.rowHeaderWidth && previousBodyCanvasSignature.zoomFactor === nextBodyCanvasSignature.zoomFactor
|
|
24821
|
+
shouldRepaintBody && previousBodyCanvasSignature && previousBodyCanvasSignature.activeSheet === nextBodyCanvasSignature.activeSheet && previousBodyCanvasSignature.bakedDrawingSignature === nextBodyCanvasSignature.bakedDrawingSignature && previousBodyCanvasSignature.bodyHeight === nextBodyCanvasSignature.bodyHeight && previousBodyCanvasSignature.bodyWidth === nextBodyCanvasSignature.bodyWidth && previousBodyCanvasSignature.getCellData === nextBodyCanvasSignature.getCellData && previousBodyCanvasSignature.headerHeight === nextBodyCanvasSignature.headerHeight && previousBodyCanvasSignature.palette === nextBodyCanvasSignature.palette && previousBodyCanvasSignature.rowHeaderWidth === nextBodyCanvasSignature.rowHeaderWidth && previousBodyCanvasSignature.zoomFactor === nextBodyCanvasSignature.zoomFactor
|
|
24391
24822
|
);
|
|
24392
24823
|
const canBlitTopHeader = Boolean(
|
|
24393
24824
|
shouldRepaintHeaders && previousHeaderCanvasSignature && previousHeaderCanvasSignature.activeSheet === nextHeaderCanvasSignature.activeSheet && previousHeaderCanvasSignature.bodyHeight === nextHeaderCanvasSignature.bodyHeight && previousHeaderCanvasSignature.bodyWidth === nextHeaderCanvasSignature.bodyWidth && previousHeaderCanvasSignature.headerHeight === nextHeaderCanvasSignature.headerHeight && previousHeaderCanvasSignature.palette === nextHeaderCanvasSignature.palette && previousHeaderCanvasSignature.rangeSignature === nextHeaderCanvasSignature.rangeSignature && previousHeaderCanvasSignature.rowHeaderWidth === nextHeaderCanvasSignature.rowHeaderWidth && previousHeaderCanvasSignature.zoomFactor === nextHeaderCanvasSignature.zoomFactor
|
|
@@ -24398,49 +24829,37 @@ function XlsxGrid({
|
|
|
24398
24829
|
if (!shouldRepaintBody && !shouldRepaintHeaders) {
|
|
24399
24830
|
return;
|
|
24400
24831
|
}
|
|
24401
|
-
const scrollBodyCanvasWidth2 = Math.max(0, drawingViewport.width - frozenPaneRight);
|
|
24402
|
-
const scrollBodyCanvasHeight2 = Math.max(0, drawingViewport.height - frozenPaneBottom);
|
|
24403
|
-
const topBodyCanvasWidth2 = scrollBodyCanvasWidth2;
|
|
24404
|
-
const topBodyCanvasHeight2 = Math.max(0, frozenPaneBottom - displayHeaderHeight);
|
|
24405
|
-
const leftBodyCanvasWidth2 = Math.max(0, frozenPaneRight - displayRowHeaderWidth);
|
|
24406
|
-
const leftBodyCanvasHeight2 = scrollBodyCanvasHeight2;
|
|
24407
|
-
const cornerBodyCanvasWidth2 = leftBodyCanvasWidth2;
|
|
24408
|
-
const cornerBodyCanvasHeight2 = topBodyCanvasHeight2;
|
|
24409
|
-
const topFrozenHeaderCanvasWidth2 = leftBodyCanvasWidth2;
|
|
24410
|
-
const topScrollHeaderCanvasWidth2 = scrollBodyCanvasWidth2;
|
|
24411
|
-
const leftFrozenHeaderCanvasHeight2 = topBodyCanvasHeight2;
|
|
24412
|
-
const leftScrollHeaderCanvasHeight2 = scrollBodyCanvasHeight2;
|
|
24413
24832
|
const paneBounds = {
|
|
24414
24833
|
corner: {
|
|
24415
|
-
height:
|
|
24834
|
+
height: cornerBodyCanvasHeight,
|
|
24416
24835
|
left: displayRowHeaderWidth,
|
|
24417
24836
|
top: displayHeaderHeight,
|
|
24418
|
-
width:
|
|
24837
|
+
width: cornerBodyCanvasWidth
|
|
24419
24838
|
},
|
|
24420
24839
|
left: {
|
|
24421
|
-
height:
|
|
24840
|
+
height: leftBodyCanvasHeight,
|
|
24422
24841
|
left: displayRowHeaderWidth,
|
|
24423
|
-
top:
|
|
24424
|
-
width:
|
|
24842
|
+
top: scrollBodyCanvasTop,
|
|
24843
|
+
width: leftBodyCanvasWidth
|
|
24425
24844
|
},
|
|
24426
24845
|
scroll: {
|
|
24427
|
-
height:
|
|
24428
|
-
left:
|
|
24429
|
-
top:
|
|
24430
|
-
width:
|
|
24846
|
+
height: scrollBodyCanvasHeight,
|
|
24847
|
+
left: scrollBodyCanvasLeft,
|
|
24848
|
+
top: scrollBodyCanvasTop,
|
|
24849
|
+
width: scrollBodyCanvasWidth
|
|
24431
24850
|
},
|
|
24432
24851
|
top: {
|
|
24433
|
-
height:
|
|
24434
|
-
left:
|
|
24852
|
+
height: topBodyCanvasHeight,
|
|
24853
|
+
left: scrollBodyCanvasLeft,
|
|
24435
24854
|
top: displayHeaderHeight,
|
|
24436
|
-
width:
|
|
24855
|
+
width: topBodyCanvasWidth
|
|
24437
24856
|
}
|
|
24438
24857
|
};
|
|
24439
24858
|
const bodyContexts = shouldRepaintBody ? {
|
|
24440
|
-
corner: configureCanvas(cornerBodyCanvasRef.current,
|
|
24441
|
-
left: configureCanvas(leftBodyCanvasRef.current,
|
|
24442
|
-
scroll: configureCanvas(scrollBodyCanvasRef.current,
|
|
24443
|
-
top: configureCanvas(topBodyCanvasRef.current,
|
|
24859
|
+
corner: configureCanvas(cornerBodyCanvasRef.current, cornerBodyCanvasWidth, cornerBodyCanvasHeight, { clear: !canBlitBody }),
|
|
24860
|
+
left: configureCanvas(leftBodyCanvasRef.current, leftBodyCanvasWidth, leftBodyCanvasHeight, { clear: !canBlitBody }),
|
|
24861
|
+
scroll: configureCanvas(scrollBodyCanvasRef.current, scrollBodyCanvasWidth, scrollBodyCanvasHeight, { clear: !canBlitBody }),
|
|
24862
|
+
top: configureCanvas(topBodyCanvasRef.current, topBodyCanvasWidth, topBodyCanvasHeight, { clear: !canBlitBody })
|
|
24444
24863
|
} : {
|
|
24445
24864
|
corner: null,
|
|
24446
24865
|
left: null,
|
|
@@ -24448,21 +24867,21 @@ function XlsxGrid({
|
|
|
24448
24867
|
top: null
|
|
24449
24868
|
};
|
|
24450
24869
|
const topHeaderContexts = shouldRepaintHeaders ? {
|
|
24451
|
-
frozen: configureCanvas(topFrozenHeaderCanvasRef.current,
|
|
24452
|
-
scroll: configureCanvas(topScrollHeaderCanvasRef.current,
|
|
24870
|
+
frozen: configureCanvas(topFrozenHeaderCanvasRef.current, topFrozenHeaderCanvasWidth, headerHeight),
|
|
24871
|
+
scroll: configureCanvas(topScrollHeaderCanvasRef.current, topScrollHeaderCanvasWidth, headerHeight, { clear: !canBlitTopHeader })
|
|
24453
24872
|
} : {
|
|
24454
24873
|
frozen: null,
|
|
24455
24874
|
scroll: null
|
|
24456
24875
|
};
|
|
24457
24876
|
const leftHeaderContexts = shouldRepaintHeaders ? {
|
|
24458
|
-
frozen: configureCanvas(leftFrozenHeaderCanvasRef.current, rowHeaderWidth,
|
|
24459
|
-
scroll: configureCanvas(leftScrollHeaderCanvasRef.current, rowHeaderWidth,
|
|
24877
|
+
frozen: configureCanvas(leftFrozenHeaderCanvasRef.current, rowHeaderWidth, leftFrozenHeaderCanvasHeight),
|
|
24878
|
+
scroll: configureCanvas(leftScrollHeaderCanvasRef.current, rowHeaderWidth, leftScrollHeaderCanvasHeight, { clear: !canBlitLeftHeader })
|
|
24460
24879
|
} : {
|
|
24461
24880
|
frozen: null,
|
|
24462
24881
|
scroll: null
|
|
24463
24882
|
};
|
|
24464
24883
|
const cornerContext = shouldRepaintHeaders ? configureCanvas(cornerHeaderCanvasRef.current, rowHeaderWidth, headerHeight) : null;
|
|
24465
|
-
if (shouldRepaintBody && (!bodyContexts.scroll || !bodyContexts.top || !bodyContexts.left || !bodyContexts.corner) || shouldRepaintHeaders && (!cornerContext ||
|
|
24884
|
+
if (shouldRepaintBody && (!bodyContexts.scroll || !bodyContexts.top || !bodyContexts.left || !bodyContexts.corner) || shouldRepaintHeaders && (!cornerContext || topFrozenHeaderCanvasWidth > 0 && !topHeaderContexts.frozen || topScrollHeaderCanvasWidth > 0 && !topHeaderContexts.scroll || leftFrozenHeaderCanvasHeight > 0 && !leftHeaderContexts.frozen || leftScrollHeaderCanvasHeight > 0 && !leftHeaderContexts.scroll)) {
|
|
24466
24885
|
return;
|
|
24467
24886
|
}
|
|
24468
24887
|
const showGridLines = activeSheet?.showGridLines ?? true;
|
|
@@ -24479,10 +24898,282 @@ function XlsxGrid({
|
|
|
24479
24898
|
scroll: [],
|
|
24480
24899
|
top: []
|
|
24481
24900
|
};
|
|
24482
|
-
let topScrollHeaderDirtyRects = buildFullCanvasDirtyRect(
|
|
24483
|
-
let leftScrollHeaderDirtyRects = buildFullCanvasDirtyRect(rowHeaderWidth,
|
|
24901
|
+
let topScrollHeaderDirtyRects = buildFullCanvasDirtyRect(topScrollHeaderCanvasWidth, headerHeight);
|
|
24902
|
+
let leftScrollHeaderDirtyRects = buildFullCanvasDirtyRect(rowHeaderWidth, leftScrollHeaderCanvasHeight);
|
|
24903
|
+
const bakedCanvasDrawingEntries = shouldBakeCanvasStaticDrawings ? [
|
|
24904
|
+
...bakedShapeRects.map(({ rect, shape }) => ({
|
|
24905
|
+
kind: "shape",
|
|
24906
|
+
rect,
|
|
24907
|
+
shape,
|
|
24908
|
+
zIndex: shape.zIndex
|
|
24909
|
+
})),
|
|
24910
|
+
...bakedFormControlRects.map(({ control, rect }) => ({
|
|
24911
|
+
control,
|
|
24912
|
+
kind: "formControl",
|
|
24913
|
+
rect,
|
|
24914
|
+
zIndex: control.zIndex
|
|
24915
|
+
})),
|
|
24916
|
+
...bakedImageRects.map(({ image, rect }) => ({
|
|
24917
|
+
image,
|
|
24918
|
+
kind: "image",
|
|
24919
|
+
rect,
|
|
24920
|
+
zIndex: image.zIndex
|
|
24921
|
+
}))
|
|
24922
|
+
].sort((left, right) => left.zIndex - right.zIndex) : [];
|
|
24923
|
+
const resolveBakedCanvasLocalRect = (rect, pane) => {
|
|
24924
|
+
const bounds = paneBounds[pane];
|
|
24925
|
+
const scrollX = pane === "scroll" || pane === "top" ? drawingViewport.left : 0;
|
|
24926
|
+
const scrollY = pane === "scroll" || pane === "left" ? drawingViewport.top : 0;
|
|
24927
|
+
return {
|
|
24928
|
+
height: rect.height,
|
|
24929
|
+
left: rect.left - scrollX - bounds.left,
|
|
24930
|
+
top: rect.top - scrollY - bounds.top,
|
|
24931
|
+
width: rect.width
|
|
24932
|
+
};
|
|
24933
|
+
};
|
|
24934
|
+
const drawBakedShapeText = (context, shape, left, top, width, height) => {
|
|
24935
|
+
if (shape.paragraphs.length === 0) {
|
|
24936
|
+
return;
|
|
24937
|
+
}
|
|
24938
|
+
const inset = shape.textBox?.insetPx;
|
|
24939
|
+
const paddingLeft = (inset?.left ?? 6) * zoomFactor;
|
|
24940
|
+
const paddingRight = (inset?.right ?? 6) * zoomFactor;
|
|
24941
|
+
const paddingTop = (inset?.top ?? 4) * zoomFactor;
|
|
24942
|
+
const paddingBottom = (inset?.bottom ?? 4) * zoomFactor;
|
|
24943
|
+
const textLeft = left + paddingLeft;
|
|
24944
|
+
const textTop = top + paddingTop;
|
|
24945
|
+
const textWidth = Math.max(0, width - paddingLeft - paddingRight);
|
|
24946
|
+
const textHeight = Math.max(0, height - paddingTop - paddingBottom);
|
|
24947
|
+
if (textWidth <= 0 || textHeight <= 0) {
|
|
24948
|
+
return;
|
|
24949
|
+
}
|
|
24950
|
+
const lineMetrics = shape.paragraphs.map((paragraph) => {
|
|
24951
|
+
const lineHeight = Math.max(
|
|
24952
|
+
12 * zoomFactor,
|
|
24953
|
+
...paragraph.runs.map((run) => (run.fontSizePt ?? 11) * 96 / 72 * zoomFactor * 1.2)
|
|
24954
|
+
);
|
|
24955
|
+
const widthPx = paragraph.runs.reduce((total, run) => {
|
|
24956
|
+
const fontSize = (run.fontSizePt ?? 11) * 96 / 72 * zoomFactor;
|
|
24957
|
+
context.font = `${run.italic ? "italic " : ""}${run.bold ? "700 " : "400 "}${fontSize}px ${run.fontFamily ?? "Calibri, sans-serif"}`;
|
|
24958
|
+
return total + measureCanvasTextWidth(context, run.text);
|
|
24959
|
+
}, 0);
|
|
24960
|
+
return { lineHeight, widthPx };
|
|
24961
|
+
});
|
|
24962
|
+
const totalTextHeight = lineMetrics.reduce((total, metric) => total + metric.lineHeight, 0);
|
|
24963
|
+
let y = textTop;
|
|
24964
|
+
if (shape.textBox?.verticalAlign === "middle") {
|
|
24965
|
+
y = textTop + Math.max(0, (textHeight - totalTextHeight) / 2);
|
|
24966
|
+
} else if (shape.textBox?.verticalAlign === "bottom") {
|
|
24967
|
+
y = textTop + Math.max(0, textHeight - totalTextHeight);
|
|
24968
|
+
}
|
|
24969
|
+
context.save();
|
|
24970
|
+
context.beginPath();
|
|
24971
|
+
context.rect(textLeft, textTop, textWidth, textHeight);
|
|
24972
|
+
context.clip();
|
|
24973
|
+
context.textBaseline = "middle";
|
|
24974
|
+
shape.paragraphs.forEach((paragraph, paragraphIndex) => {
|
|
24975
|
+
const metric = lineMetrics[paragraphIndex] ?? { lineHeight: 14 * zoomFactor, widthPx: 0 };
|
|
24976
|
+
let x = textLeft;
|
|
24977
|
+
const align = paragraph.align ?? shape.textBox?.horizontalAlign ?? "left";
|
|
24978
|
+
if (align === "center") {
|
|
24979
|
+
x = textLeft + Math.max(0, (textWidth - metric.widthPx) / 2);
|
|
24980
|
+
} else if (align === "right") {
|
|
24981
|
+
x = textLeft + Math.max(0, textWidth - metric.widthPx);
|
|
24982
|
+
}
|
|
24983
|
+
paragraph.runs.forEach((run) => {
|
|
24984
|
+
const fontSize = (run.fontSizePt ?? 11) * 96 / 72 * zoomFactor;
|
|
24985
|
+
context.font = `${run.italic ? "italic " : ""}${run.bold ? "700 " : "400 "}${fontSize}px ${run.fontFamily ?? "Calibri, sans-serif"}`;
|
|
24986
|
+
context.fillStyle = run.color ?? "#000000";
|
|
24987
|
+
context.textAlign = "left";
|
|
24988
|
+
const textY = y + metric.lineHeight / 2;
|
|
24989
|
+
context.fillText(run.text, x, textY);
|
|
24990
|
+
if (run.underline && run.text.length > 0) {
|
|
24991
|
+
const textWidthPx = measureCanvasTextWidth(context, run.text);
|
|
24992
|
+
context.strokeStyle = run.color ?? "#000000";
|
|
24993
|
+
context.lineWidth = Math.max(1, zoomFactor * 0.75);
|
|
24994
|
+
context.beginPath();
|
|
24995
|
+
context.moveTo(x, textY + Math.max(2, fontSize * 0.28));
|
|
24996
|
+
context.lineTo(x + textWidthPx, textY + Math.max(2, fontSize * 0.28));
|
|
24997
|
+
context.stroke();
|
|
24998
|
+
}
|
|
24999
|
+
x += measureCanvasTextWidth(context, run.text);
|
|
25000
|
+
});
|
|
25001
|
+
y += metric.lineHeight;
|
|
25002
|
+
});
|
|
25003
|
+
context.restore();
|
|
25004
|
+
};
|
|
25005
|
+
const drawBakedShape = (context, shape, rect) => {
|
|
25006
|
+
const fillColor = shape.fill?.none ? "transparent" : shape.fill?.color ?? "transparent";
|
|
25007
|
+
const strokeColor = shape.stroke?.none ? "transparent" : shape.stroke?.color ?? "transparent";
|
|
25008
|
+
const lineWidth = Math.max(0, (shape.stroke?.widthPx ?? (shape.geometry === "line" ? 2 : 1)) * zoomFactor);
|
|
25009
|
+
const vectorShape = resolveShapeVector(shape);
|
|
25010
|
+
const opacity = Math.min(shape.fill?.opacity ?? 1, shape.stroke?.opacity ?? 1);
|
|
25011
|
+
context.save();
|
|
25012
|
+
context.translate(rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
25013
|
+
if (shape.rotationDeg) {
|
|
25014
|
+
context.rotate(shape.rotationDeg * Math.PI / 180);
|
|
25015
|
+
}
|
|
25016
|
+
context.scale(shape.flipH ? -1 : 1, shape.flipV ? -1 : 1);
|
|
25017
|
+
context.globalAlpha *= opacity;
|
|
25018
|
+
context.lineWidth = lineWidth;
|
|
25019
|
+
context.strokeStyle = strokeColor;
|
|
25020
|
+
context.fillStyle = fillColor;
|
|
25021
|
+
applyCanvasShapeDash(context, shape.stroke?.dash, lineWidth);
|
|
25022
|
+
const localLeft = -rect.width / 2;
|
|
25023
|
+
const localTop = -rect.height / 2;
|
|
25024
|
+
if (vectorShape && typeof Path2D !== "undefined") {
|
|
25025
|
+
context.save();
|
|
25026
|
+
context.translate(localLeft, localTop);
|
|
25027
|
+
context.scale(
|
|
25028
|
+
rect.width / Math.max(1, vectorShape.viewBox.width),
|
|
25029
|
+
rect.height / Math.max(1, vectorShape.viewBox.height)
|
|
25030
|
+
);
|
|
25031
|
+
const path = getCachedCanvasPath2D(vectorShape.path);
|
|
25032
|
+
if (!path) {
|
|
25033
|
+
context.restore();
|
|
25034
|
+
context.restore();
|
|
25035
|
+
return;
|
|
25036
|
+
}
|
|
25037
|
+
if (fillColor !== "transparent") {
|
|
25038
|
+
context.fill(path);
|
|
25039
|
+
}
|
|
25040
|
+
if (strokeColor !== "transparent" && lineWidth > 0) {
|
|
25041
|
+
context.stroke(path);
|
|
25042
|
+
}
|
|
25043
|
+
context.restore();
|
|
25044
|
+
} else if (shape.geometry === "ellipse") {
|
|
25045
|
+
context.beginPath();
|
|
25046
|
+
context.ellipse(0, 0, rect.width / 2, rect.height / 2, 0, 0, Math.PI * 2);
|
|
25047
|
+
if (fillColor !== "transparent") {
|
|
25048
|
+
context.fill();
|
|
25049
|
+
}
|
|
25050
|
+
if (strokeColor !== "transparent" && lineWidth > 0) {
|
|
25051
|
+
context.stroke();
|
|
25052
|
+
}
|
|
25053
|
+
} else {
|
|
25054
|
+
const radius = shape.geometry === "roundRect" ? 12 * zoomFactor : 0;
|
|
25055
|
+
drawCanvasRoundedRect(context, localLeft, localTop, rect.width, rect.height, radius);
|
|
25056
|
+
if (fillColor !== "transparent") {
|
|
25057
|
+
context.fill();
|
|
25058
|
+
}
|
|
25059
|
+
if (strokeColor !== "transparent" && lineWidth > 0) {
|
|
25060
|
+
context.stroke();
|
|
25061
|
+
}
|
|
25062
|
+
}
|
|
25063
|
+
drawBakedShapeText(context, shape, localLeft, localTop, rect.width, rect.height);
|
|
25064
|
+
context.restore();
|
|
25065
|
+
};
|
|
25066
|
+
const drawBakedFormControl = (context, control, rect) => {
|
|
25067
|
+
const label = resolveFormControlLabel(control);
|
|
25068
|
+
const stroke = paletteIsDark(palette) ? "#cbd5e1" : "#475569";
|
|
25069
|
+
const textColor = control.textColor ?? "#000000";
|
|
25070
|
+
const fontSizePx = Math.max(9 * zoomFactor, (control.fontSizePt ?? 9) * 96 / 72 * zoomFactor);
|
|
25071
|
+
const iconSize = Math.min(14 * zoomFactor, Math.max(0, rect.height - 4 * zoomFactor));
|
|
25072
|
+
context.save();
|
|
25073
|
+
context.font = `400 ${fontSizePx}px ${control.fontFamily ?? "Calibri, sans-serif"}`;
|
|
25074
|
+
context.textBaseline = "middle";
|
|
25075
|
+
context.fillStyle = textColor;
|
|
25076
|
+
context.strokeStyle = stroke;
|
|
25077
|
+
context.lineWidth = Math.max(1, zoomFactor);
|
|
25078
|
+
if (control.kind === "group-box") {
|
|
25079
|
+
const labelInset = label ? Math.max(7, fontSizePx * 0.5) : 0;
|
|
25080
|
+
drawCanvasRoundedRect(context, rect.left, rect.top + labelInset, rect.width, Math.max(0, rect.height - labelInset), 2 * zoomFactor);
|
|
25081
|
+
context.stroke();
|
|
25082
|
+
if (label) {
|
|
25083
|
+
context.fillStyle = SHEET_SURFACE;
|
|
25084
|
+
const labelWidth = Math.min(rect.width - 16 * zoomFactor, measureCanvasTextWidth(context, label) + 8 * zoomFactor);
|
|
25085
|
+
context.fillRect(rect.left + 8 * zoomFactor, rect.top, labelWidth, fontSizePx * 1.2);
|
|
25086
|
+
context.fillStyle = textColor;
|
|
25087
|
+
context.textAlign = "left";
|
|
25088
|
+
context.fillText(label, rect.left + 12 * zoomFactor, rect.top + fontSizePx * 0.55);
|
|
25089
|
+
}
|
|
25090
|
+
context.restore();
|
|
25091
|
+
return;
|
|
25092
|
+
}
|
|
25093
|
+
if (control.kind === "button" || control.kind === "dropdown" || control.kind === "editbox" || control.kind === "listbox" || control.kind === "scrollbar" || control.kind === "spinner" || control.kind === "unknown") {
|
|
25094
|
+
if (control.kind === "button") {
|
|
25095
|
+
const gradient = context.createLinearGradient(rect.left, rect.top, rect.left, rect.top + rect.height);
|
|
25096
|
+
gradient.addColorStop(0, "#f8fafc");
|
|
25097
|
+
gradient.addColorStop(1, "#e2e8f0");
|
|
25098
|
+
context.fillStyle = gradient;
|
|
25099
|
+
} else {
|
|
25100
|
+
context.fillStyle = "transparent";
|
|
25101
|
+
}
|
|
25102
|
+
drawCanvasRoundedRect(context, rect.left, rect.top, rect.width, rect.height, control.kind === "button" ? 4 * zoomFactor : 2 * zoomFactor);
|
|
25103
|
+
if (control.kind === "button") {
|
|
25104
|
+
context.fill();
|
|
25105
|
+
}
|
|
25106
|
+
context.stroke();
|
|
25107
|
+
}
|
|
25108
|
+
let textLeft = rect.left + 2 * zoomFactor;
|
|
25109
|
+
const textRightInset = control.kind === "dropdown" ? 18 * zoomFactor : 6 * zoomFactor;
|
|
25110
|
+
if (control.kind === "checkbox") {
|
|
25111
|
+
context.strokeRect(rect.left + 2 * zoomFactor, rect.top + (rect.height - iconSize) / 2, iconSize, iconSize);
|
|
25112
|
+
if (control.checked) {
|
|
25113
|
+
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
25114
|
+
context.fillRect(rect.left + 2 * zoomFactor + 1.5, rect.top + (rect.height - iconSize) / 2 + 1.5, Math.max(0, iconSize - 3), Math.max(0, iconSize - 3));
|
|
25115
|
+
context.strokeStyle = paletteIsDark(palette) ? "#020617" : "#ffffff";
|
|
25116
|
+
context.beginPath();
|
|
25117
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.24, rect.top + rect.height / 2 + iconSize * 0.06);
|
|
25118
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.45, rect.top + rect.height / 2 + iconSize * 0.26);
|
|
25119
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.8, rect.top + rect.height / 2 - iconSize * 0.2);
|
|
25120
|
+
context.stroke();
|
|
25121
|
+
}
|
|
25122
|
+
textLeft += iconSize + 4 * zoomFactor;
|
|
25123
|
+
} else if (control.kind === "radio") {
|
|
25124
|
+
context.beginPath();
|
|
25125
|
+
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize / 2, 0, Math.PI * 2);
|
|
25126
|
+
context.stroke();
|
|
25127
|
+
if (control.checked) {
|
|
25128
|
+
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
25129
|
+
context.beginPath();
|
|
25130
|
+
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize * 0.25, 0, Math.PI * 2);
|
|
25131
|
+
context.fill();
|
|
25132
|
+
}
|
|
25133
|
+
textLeft += iconSize + 4 * zoomFactor;
|
|
25134
|
+
}
|
|
25135
|
+
if (label) {
|
|
25136
|
+
const maxTextWidth = Math.max(0, rect.left + rect.width - textLeft - textRightInset);
|
|
25137
|
+
const text = truncateCanvasText(context, label, maxTextWidth);
|
|
25138
|
+
context.fillStyle = textColor;
|
|
25139
|
+
context.textAlign = control.textAlign === "right" ? "right" : control.textAlign === "center" ? "center" : "left";
|
|
25140
|
+
const textX = context.textAlign === "right" ? rect.left + rect.width - textRightInset : context.textAlign === "center" ? textLeft + maxTextWidth / 2 : textLeft;
|
|
25141
|
+
context.fillText(text, textX, rect.top + rect.height / 2);
|
|
25142
|
+
}
|
|
25143
|
+
if (control.kind === "dropdown") {
|
|
25144
|
+
context.fillStyle = textColor;
|
|
25145
|
+
context.textAlign = "center";
|
|
25146
|
+
context.fillText("\u25BC", rect.left + rect.width - 10 * zoomFactor, rect.top + rect.height / 2);
|
|
25147
|
+
}
|
|
25148
|
+
context.restore();
|
|
25149
|
+
};
|
|
25150
|
+
const drawBakedCanvasDrawings = (pane, context, dirtyRects) => {
|
|
25151
|
+
if (bakedCanvasDrawingEntries.length === 0 || dirtyRects.length === 0) {
|
|
25152
|
+
return;
|
|
25153
|
+
}
|
|
25154
|
+
for (const entry of bakedCanvasDrawingEntries) {
|
|
25155
|
+
if (resolveDrawingPane(entry.rect) !== pane) {
|
|
25156
|
+
continue;
|
|
25157
|
+
}
|
|
25158
|
+
const localRect = resolveBakedCanvasLocalRect(entry.rect, pane);
|
|
25159
|
+
if (localRect.left + localRect.width < 0 || localRect.top + localRect.height < 0 || localRect.left > paneBounds[pane].width || localRect.top > paneBounds[pane].height || !intersectsCanvasDirtyRects(localRect.left, localRect.top, localRect.width, localRect.height, dirtyRects)) {
|
|
25160
|
+
continue;
|
|
25161
|
+
}
|
|
25162
|
+
if (entry.kind === "shape") {
|
|
25163
|
+
drawBakedShape(context, entry.shape, localRect);
|
|
25164
|
+
} else if (entry.kind === "formControl") {
|
|
25165
|
+
drawBakedFormControl(context, entry.control, localRect);
|
|
25166
|
+
} else {
|
|
25167
|
+
const imageElement = getCanvasImage(entry.image);
|
|
25168
|
+
if (imageElement) {
|
|
25169
|
+
context.drawImage(imageElement, localRect.left, localRect.top, localRect.width, localRect.height);
|
|
25170
|
+
}
|
|
25171
|
+
}
|
|
25172
|
+
}
|
|
25173
|
+
};
|
|
24484
25174
|
const cellPaneOrder = ["scroll", "top", "left", "corner"];
|
|
24485
25175
|
if (shouldRepaintBody) {
|
|
25176
|
+
canvasProfileBodyStart = canvasProfileTarget ? performance.now() : 0;
|
|
24486
25177
|
for (const pane of Object.keys(bodyContexts)) {
|
|
24487
25178
|
const context = bodyContexts[pane];
|
|
24488
25179
|
const bounds = paneBounds[pane];
|
|
@@ -24513,6 +25204,7 @@ function XlsxGrid({
|
|
|
24513
25204
|
context.clearRect(0, 0, bounds.width, bounds.height);
|
|
24514
25205
|
}
|
|
24515
25206
|
bodyDirtyRectsByPane[pane] = dirtyRects;
|
|
25207
|
+
canvasProfileDirtyRects += dirtyRects.length;
|
|
24516
25208
|
if (dirtyRects.length === 0) {
|
|
24517
25209
|
continue;
|
|
24518
25210
|
}
|
|
@@ -24529,6 +25221,22 @@ function XlsxGrid({
|
|
|
24529
25221
|
if (!paneContext || paneDirtyRects.length === 0 || paneBoundsForCell.width <= 0 || paneBoundsForCell.height <= 0 || paneAxisItems.rows.length === 0 || paneAxisItems.cols.length === 0) {
|
|
24530
25222
|
continue;
|
|
24531
25223
|
}
|
|
25224
|
+
let hasPendingGridlinePath = false;
|
|
25225
|
+
const enqueueGridlinePath = () => {
|
|
25226
|
+
if (!hasPendingGridlinePath) {
|
|
25227
|
+
paneContext.beginPath();
|
|
25228
|
+
hasPendingGridlinePath = true;
|
|
25229
|
+
}
|
|
25230
|
+
};
|
|
25231
|
+
const flushPendingGridlines = () => {
|
|
25232
|
+
if (!hasPendingGridlinePath) {
|
|
25233
|
+
return;
|
|
25234
|
+
}
|
|
25235
|
+
paneContext.strokeStyle = palette.border;
|
|
25236
|
+
paneContext.lineWidth = 1;
|
|
25237
|
+
paneContext.stroke();
|
|
25238
|
+
hasPendingGridlinePath = false;
|
|
25239
|
+
};
|
|
24532
25240
|
const drawnMergedAnchorKeys = /* @__PURE__ */ new Set();
|
|
24533
25241
|
for (const rowItem of paneAxisItems.rows) {
|
|
24534
25242
|
for (const colItem of paneAxisItems.cols) {
|
|
@@ -24536,6 +25244,33 @@ function XlsxGrid({
|
|
|
24536
25244
|
const anchorCell = resolveMergeAnchorCell(cell);
|
|
24537
25245
|
const anchorKey = `${anchorCell.row}:${anchorCell.col}`;
|
|
24538
25246
|
let drawCell = anchorCell;
|
|
25247
|
+
const drawRowIndex = rowIndexByActual.get(drawCell.row);
|
|
25248
|
+
const drawColIndex = colIndexByActual.get(drawCell.col);
|
|
25249
|
+
if (drawRowIndex === void 0 || drawColIndex === void 0) {
|
|
25250
|
+
continue;
|
|
25251
|
+
}
|
|
25252
|
+
const baseCellLeft = displayRowHeaderWidth + (colPrefixSums[drawColIndex] ?? 0);
|
|
25253
|
+
const baseCellTop = displayHeaderHeight + (rowPrefixSums[drawRowIndex] ?? 0);
|
|
25254
|
+
const useFrozenHorizontalPosition = pane === "left" || pane === "corner";
|
|
25255
|
+
const useFrozenVerticalPosition = pane === "top" || pane === "corner";
|
|
25256
|
+
const roughLocalRect = {
|
|
25257
|
+
height: displayEffectiveRowHeights[drawRowIndex] ?? rowItem.size,
|
|
25258
|
+
left: (useFrozenHorizontalPosition ? stickyLeftByCol.get(drawCell.col) ?? baseCellLeft - drawingViewport.left : baseCellLeft - drawingViewport.left) - paneBoundsForCell.left,
|
|
25259
|
+
top: (useFrozenVerticalPosition ? stickyTopByRow.get(drawCell.row) ?? baseCellTop - drawingViewport.top : baseCellTop - drawingViewport.top) - paneBoundsForCell.top,
|
|
25260
|
+
width: displayEffectiveColWidths[drawColIndex] ?? colItem.size
|
|
25261
|
+
};
|
|
25262
|
+
const isMergedSecondaryProbe = anchorCell.row !== cell.row || anchorCell.col !== cell.col;
|
|
25263
|
+
if (!isMergedSecondaryProbe && !intersectsCanvasDirtyRects(
|
|
25264
|
+
roughLocalRect.left - CANVAS_DIRTY_CELL_CULL_MARGIN_PX,
|
|
25265
|
+
roughLocalRect.top - CANVAS_DIRTY_CELL_CULL_MARGIN_PX,
|
|
25266
|
+
roughLocalRect.width + CANVAS_DIRTY_CELL_CULL_MARGIN_PX * 2,
|
|
25267
|
+
roughLocalRect.height + CANVAS_DIRTY_CELL_CULL_MARGIN_PX * 2,
|
|
25268
|
+
paneDirtyRects
|
|
25269
|
+
)) {
|
|
25270
|
+
canvasProfileCulledCells += 1;
|
|
25271
|
+
continue;
|
|
25272
|
+
}
|
|
25273
|
+
canvasProfileLookedUpCells += 1;
|
|
24539
25274
|
let cellData = getCellData(drawCell.row, drawCell.col);
|
|
24540
25275
|
if ((cellData.colSpan || cellData.rowSpan) && drawnMergedAnchorKeys.has(anchorKey)) {
|
|
24541
25276
|
continue;
|
|
@@ -24546,16 +25281,9 @@ function XlsxGrid({
|
|
|
24546
25281
|
if (cellData.colSpan || cellData.rowSpan) {
|
|
24547
25282
|
drawnMergedAnchorKeys.add(anchorKey);
|
|
24548
25283
|
}
|
|
24549
|
-
const drawRowIndex = rowIndexByActual.get(drawCell.row);
|
|
24550
|
-
const drawColIndex = colIndexByActual.get(drawCell.col);
|
|
24551
|
-
if (drawRowIndex === void 0 || drawColIndex === void 0) {
|
|
24552
|
-
continue;
|
|
24553
|
-
}
|
|
24554
25284
|
const displayRect = cellData.colSpan || cellData.rowSpan ? resolveCellDisplayRect(drawCell) : null;
|
|
24555
|
-
const baseLeft = displayRect?.left ??
|
|
24556
|
-
const baseTop = displayRect?.top ??
|
|
24557
|
-
const useFrozenHorizontalPosition = pane === "left" || pane === "corner";
|
|
24558
|
-
const useFrozenVerticalPosition = pane === "top" || pane === "corner";
|
|
25285
|
+
const baseLeft = displayRect?.left ?? baseCellLeft;
|
|
25286
|
+
const baseTop = displayRect?.top ?? baseCellTop;
|
|
24559
25287
|
const localRect = {
|
|
24560
25288
|
height: displayRect?.height ?? (displayEffectiveRowHeights[drawRowIndex] ?? rowItem.size),
|
|
24561
25289
|
left: (useFrozenHorizontalPosition ? stickyLeftByCol.get(drawCell.col) ?? baseLeft - drawingViewport.left : baseLeft - drawingViewport.left) - paneBoundsForCell.left,
|
|
@@ -24567,13 +25295,18 @@ function XlsxGrid({
|
|
|
24567
25295
|
continue;
|
|
24568
25296
|
}
|
|
24569
25297
|
if (!intersectsCanvasDirtyRects(localRect.left, localRect.top, drawableWidth, localRect.height, paneDirtyRects)) {
|
|
25298
|
+
canvasProfileCulledCells += 1;
|
|
24570
25299
|
continue;
|
|
24571
25300
|
}
|
|
25301
|
+
canvasProfilePaintedCells += 1;
|
|
24572
25302
|
const cellStyle = cellData.style;
|
|
24573
25303
|
const canvasCellStyle = cellData.canvas ?? buildCanvasCellStyleCache(cellStyle);
|
|
24574
25304
|
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellStyle.backgroundColor === "string" ? cellStyle.backgroundColor : sheetSurface);
|
|
24575
25305
|
const gradientFill = !cellData.conditionalColorScale && typeof cellStyle.backgroundImage === "string" ? resolveCanvasGradientFill(paneContext, localRect, cellStyle.backgroundImage) : null;
|
|
24576
25306
|
const hasExplicitCellFill = cellData.conditionalColorScale !== null || gradientFill !== null || typeof cellStyle.backgroundColor === "string" && cellStyle.backgroundColor !== sheetSurface;
|
|
25307
|
+
if (hasExplicitCellFill || cellData.chartHighlight) {
|
|
25308
|
+
flushPendingGridlines();
|
|
25309
|
+
}
|
|
24577
25310
|
paneContext.fillStyle = gradientFill ?? fillColor;
|
|
24578
25311
|
paneContext.fillRect(localRect.left, localRect.top, localRect.width, localRect.height);
|
|
24579
25312
|
if (cellData.chartHighlight) {
|
|
@@ -24619,10 +25352,8 @@ function XlsxGrid({
|
|
|
24619
25352
|
const bottomNeighborTopBorder = bottomNeighborData?.isMergedSecondary ? null : bottomNeighborData?.canvas?.topBorder ?? parseCanvasBorderDeclaration(bottomNeighborData?.style.borderTop);
|
|
24620
25353
|
const resolvedRightBorder = resolveCanvasBoundaryBorder(rightBorder, rightNeighborLeftBorder);
|
|
24621
25354
|
const resolvedBottomBorder = resolveCanvasBoundaryBorder(bottomBorder, bottomNeighborTopBorder);
|
|
24622
|
-
if (showGridLines && !hasExplicitCellFill) {
|
|
24623
|
-
|
|
24624
|
-
paneContext.lineWidth = 1;
|
|
24625
|
-
paneContext.beginPath();
|
|
25355
|
+
if (showGridLines && !hasExplicitCellFill && (!resolvedRightBorder || !resolvedBottomBorder)) {
|
|
25356
|
+
enqueueGridlinePath();
|
|
24626
25357
|
if (!resolvedRightBorder) {
|
|
24627
25358
|
paneContext.moveTo(localRect.left + localRect.width - 0.5, localRect.top);
|
|
24628
25359
|
paneContext.lineTo(localRect.left + localRect.width - 0.5, localRect.top + localRect.height);
|
|
@@ -24631,7 +25362,9 @@ function XlsxGrid({
|
|
|
24631
25362
|
paneContext.moveTo(localRect.left, localRect.top + localRect.height - 0.5);
|
|
24632
25363
|
paneContext.lineTo(localRect.left + localRect.width, localRect.top + localRect.height - 0.5);
|
|
24633
25364
|
}
|
|
24634
|
-
|
|
25365
|
+
}
|
|
25366
|
+
if (topBorder || resolvedRightBorder || resolvedBottomBorder || leftBorder || cellData.chartHighlight) {
|
|
25367
|
+
flushPendingGridlines();
|
|
24635
25368
|
}
|
|
24636
25369
|
if (topBorder && drawRowIndex === 0) {
|
|
24637
25370
|
strokeCanvasBorderSide(paneContext, "top", localRect, topBorder);
|
|
@@ -24664,17 +25397,26 @@ function XlsxGrid({
|
|
|
24664
25397
|
strokeCanvasBorderSide(paneContext, "left", localRect, highlightBorder);
|
|
24665
25398
|
}
|
|
24666
25399
|
}
|
|
25400
|
+
const rawText = cellData.value ?? "";
|
|
25401
|
+
const shouldDrawCanvasContent = cellData.checkboxState != null || cellData.sparkline || rawText.length > 0 || cellData.conditionalIcon || cellData.isTableHeader;
|
|
25402
|
+
if (!shouldDrawCanvasContent) {
|
|
25403
|
+
continue;
|
|
25404
|
+
}
|
|
24667
25405
|
const padding = canvasCellStyle.padding;
|
|
24668
25406
|
const contentLeft = localRect.left + padding.left;
|
|
24669
25407
|
const contentTop = localRect.top + padding.top;
|
|
24670
25408
|
const contentWidth = Math.max(0, localRect.width - padding.left - padding.right);
|
|
24671
25409
|
const contentHeight = Math.max(0, localRect.height - padding.top - padding.bottom);
|
|
25410
|
+
if (contentWidth <= 0 || contentHeight <= 0) {
|
|
25411
|
+
continue;
|
|
25412
|
+
}
|
|
24672
25413
|
const activeFontSizePx = cellData.shrinkToFitFontSizePx ?? resolveCanvasFontSizePx(cellStyle, 12 * zoomFactor);
|
|
24673
25414
|
const textClipOverscan = Math.max(
|
|
24674
25415
|
1,
|
|
24675
25416
|
zoomFactor * 1.5,
|
|
24676
25417
|
activeFontSizePx * (cellData.textRotationDeg ? 0.75 : 0.18)
|
|
24677
25418
|
);
|
|
25419
|
+
flushPendingGridlines();
|
|
24678
25420
|
paneContext.save();
|
|
24679
25421
|
paneContext.beginPath();
|
|
24680
25422
|
paneContext.rect(
|
|
@@ -24806,7 +25548,6 @@ function XlsxGrid({
|
|
|
24806
25548
|
const trailingInset = (cellData.conditionalIcon ? 18 * zoomFactor : 0) + (cellData.isTableHeader ? 16 * zoomFactor : 0);
|
|
24807
25549
|
const spillMaxWidth = cellData.spillWidth && cellData.spillWidth > 0 ? Math.max(0, cellData.spillWidth - trailingInset) : null;
|
|
24808
25550
|
const maxTextWidth = spillMaxWidth ?? Math.max(0, contentWidth - trailingInset);
|
|
24809
|
-
const rawText = cellData.value ?? "";
|
|
24810
25551
|
const textColor = canvasCellStyle.textColor;
|
|
24811
25552
|
const shouldEllipsizeText = canvasCellStyle.textOverflowEllipsis;
|
|
24812
25553
|
const shouldWrapText = canvasCellStyle.usesWrappedText || rawText.includes("\n");
|
|
@@ -24838,7 +25579,7 @@ function XlsxGrid({
|
|
|
24838
25579
|
const textY = textBlockTop + lineIndex * lineHeight + lineHeight / 2;
|
|
24839
25580
|
paneContext.fillText(line, textX, textY);
|
|
24840
25581
|
if (canvasCellStyle.textDecoration?.includes("underline") && line.length > 0) {
|
|
24841
|
-
const measured = Math.min(maxTextWidth, paneContext
|
|
25582
|
+
const measured = Math.min(maxTextWidth, measureCanvasTextWidth(paneContext, line));
|
|
24842
25583
|
const underlineStartX = align === "right" ? textX - measured : align === "center" ? textX - measured / 2 : textX;
|
|
24843
25584
|
paneContext.beginPath();
|
|
24844
25585
|
paneContext.moveTo(underlineStartX, textY + Math.max(2, lineHeight * 0.24));
|
|
@@ -24872,7 +25613,7 @@ function XlsxGrid({
|
|
|
24872
25613
|
const textY = contentTop + contentHeight / 2;
|
|
24873
25614
|
paneContext.fillText(text, textX, textY);
|
|
24874
25615
|
if (canvasCellStyle.textDecoration?.includes("underline") && text.length > 0) {
|
|
24875
|
-
const measured = shouldEllipsizeText ? Math.min(maxTextWidth, paneContext
|
|
25616
|
+
const measured = shouldEllipsizeText ? Math.min(maxTextWidth, measureCanvasTextWidth(paneContext, text)) : measureCanvasTextWidth(paneContext, text);
|
|
24876
25617
|
const underlineStartX = align === "right" ? textX - measured : align === "center" ? textX - measured / 2 : textX;
|
|
24877
25618
|
paneContext.beginPath();
|
|
24878
25619
|
paneContext.moveTo(underlineStartX, textY + 6 * zoomFactor);
|
|
@@ -24897,6 +25638,7 @@ function XlsxGrid({
|
|
|
24897
25638
|
paneContext.restore();
|
|
24898
25639
|
}
|
|
24899
25640
|
}
|
|
25641
|
+
flushPendingGridlines();
|
|
24900
25642
|
}
|
|
24901
25643
|
for (const pane of cellPaneOrder) {
|
|
24902
25644
|
const paneContext = bodyContexts[pane];
|
|
@@ -24914,7 +25656,7 @@ function XlsxGrid({
|
|
|
24914
25656
|
paneContext.textBaseline = "middle";
|
|
24915
25657
|
paneContext.fillText(spillText.text, spillText.textX, spillText.textY);
|
|
24916
25658
|
if (spillText.textDecoration?.includes("underline") && spillText.text.length > 0) {
|
|
24917
|
-
const measured = spillText.ellipsize ? Math.min(spillText.maxWidth, paneContext
|
|
25659
|
+
const measured = spillText.ellipsize ? Math.min(spillText.maxWidth, measureCanvasTextWidth(paneContext, spillText.text)) : measureCanvasTextWidth(paneContext, spillText.text);
|
|
24918
25660
|
const underlineStartX = spillText.align === "right" ? spillText.textX - measured : spillText.align === "center" ? spillText.textX - measured / 2 : spillText.textX;
|
|
24919
25661
|
paneContext.beginPath();
|
|
24920
25662
|
paneContext.moveTo(underlineStartX, spillText.underlineY);
|
|
@@ -24926,6 +25668,14 @@ function XlsxGrid({
|
|
|
24926
25668
|
paneContext.restore();
|
|
24927
25669
|
}
|
|
24928
25670
|
}
|
|
25671
|
+
for (const pane of cellPaneOrder) {
|
|
25672
|
+
const paneContext = bodyContexts[pane];
|
|
25673
|
+
if (!paneContext) {
|
|
25674
|
+
continue;
|
|
25675
|
+
}
|
|
25676
|
+
drawBakedCanvasDrawings(pane, paneContext, bodyDirtyRectsByPane[pane]);
|
|
25677
|
+
}
|
|
25678
|
+
canvasProfileBodyMs = canvasProfileTarget ? performance.now() - canvasProfileBodyStart : 0;
|
|
24929
25679
|
}
|
|
24930
25680
|
if (shouldRepaintHeaders && cornerContext) {
|
|
24931
25681
|
const topFrozenHeaderContext = topHeaderContexts.frozen;
|
|
@@ -24940,7 +25690,7 @@ function XlsxGrid({
|
|
|
24940
25690
|
topScrollHeaderContext,
|
|
24941
25691
|
bufferCanvas,
|
|
24942
25692
|
dpr,
|
|
24943
|
-
|
|
25693
|
+
topScrollHeaderCanvasWidth,
|
|
24944
25694
|
headerHeight,
|
|
24945
25695
|
drawingViewport.left - previousPaintedViewport.left,
|
|
24946
25696
|
0
|
|
@@ -24959,7 +25709,7 @@ function XlsxGrid({
|
|
|
24959
25709
|
bufferCanvas,
|
|
24960
25710
|
dpr,
|
|
24961
25711
|
rowHeaderWidth,
|
|
24962
|
-
|
|
25712
|
+
leftScrollHeaderCanvasHeight,
|
|
24963
25713
|
0,
|
|
24964
25714
|
drawingViewport.top - previousPaintedViewport.top
|
|
24965
25715
|
);
|
|
@@ -24968,11 +25718,11 @@ function XlsxGrid({
|
|
|
24968
25718
|
}
|
|
24969
25719
|
}
|
|
24970
25720
|
}
|
|
24971
|
-
if (topFrozenHeaderContext &&
|
|
25721
|
+
if (topFrozenHeaderContext && topFrozenHeaderCanvasWidth > 0) {
|
|
24972
25722
|
topFrozenHeaderContext.fillStyle = palette.headerSurface;
|
|
24973
|
-
topFrozenHeaderContext.fillRect(0, 0,
|
|
25723
|
+
topFrozenHeaderContext.fillRect(0, 0, topFrozenHeaderCanvasWidth, headerHeight);
|
|
24974
25724
|
}
|
|
24975
|
-
if (topScrollHeaderContext &&
|
|
25725
|
+
if (topScrollHeaderContext && topScrollHeaderCanvasWidth > 0) {
|
|
24976
25726
|
topScrollHeaderContext.fillStyle = palette.headerSurface;
|
|
24977
25727
|
for (const dirtyRect of topScrollHeaderDirtyRects) {
|
|
24978
25728
|
topScrollHeaderContext.fillRect(dirtyRect.left, dirtyRect.top, dirtyRect.width, dirtyRect.height);
|
|
@@ -24991,7 +25741,7 @@ function XlsxGrid({
|
|
|
24991
25741
|
if (!paneContext) {
|
|
24992
25742
|
continue;
|
|
24993
25743
|
}
|
|
24994
|
-
if (column.localLeft + column.width < 0 || column.localLeft > (column.isFrozen ?
|
|
25744
|
+
if (column.localLeft + column.width < 0 || column.localLeft > (column.isFrozen ? topFrozenHeaderCanvasWidth : topScrollHeaderCanvasWidth)) {
|
|
24995
25745
|
continue;
|
|
24996
25746
|
}
|
|
24997
25747
|
if (!column.isFrozen && !intersectsCanvasDirtyRects(column.localLeft, 0, column.width, column.height, topScrollHeaderDirtyRects)) {
|
|
@@ -25017,11 +25767,11 @@ function XlsxGrid({
|
|
|
25017
25767
|
column.height / 2
|
|
25018
25768
|
);
|
|
25019
25769
|
}
|
|
25020
|
-
if (leftFrozenHeaderContext &&
|
|
25770
|
+
if (leftFrozenHeaderContext && leftFrozenHeaderCanvasHeight > 0) {
|
|
25021
25771
|
leftFrozenHeaderContext.fillStyle = palette.rowHeaderSurface;
|
|
25022
|
-
leftFrozenHeaderContext.fillRect(0, 0, rowHeaderWidth,
|
|
25772
|
+
leftFrozenHeaderContext.fillRect(0, 0, rowHeaderWidth, leftFrozenHeaderCanvasHeight);
|
|
25023
25773
|
}
|
|
25024
|
-
if (leftScrollHeaderContext &&
|
|
25774
|
+
if (leftScrollHeaderContext && leftScrollHeaderCanvasHeight > 0) {
|
|
25025
25775
|
leftScrollHeaderContext.fillStyle = palette.rowHeaderSurface;
|
|
25026
25776
|
for (const dirtyRect of leftScrollHeaderDirtyRects) {
|
|
25027
25777
|
leftScrollHeaderContext.fillRect(dirtyRect.left, dirtyRect.top, dirtyRect.width, dirtyRect.height);
|
|
@@ -25040,7 +25790,7 @@ function XlsxGrid({
|
|
|
25040
25790
|
if (!paneContext) {
|
|
25041
25791
|
continue;
|
|
25042
25792
|
}
|
|
25043
|
-
if (row.localTop + row.height < 0 || row.localTop > (row.isFrozen ?
|
|
25793
|
+
if (row.localTop + row.height < 0 || row.localTop > (row.isFrozen ? leftFrozenHeaderCanvasHeight : leftScrollHeaderCanvasHeight)) {
|
|
25044
25794
|
continue;
|
|
25045
25795
|
}
|
|
25046
25796
|
if (!row.isFrozen && !intersectsCanvasDirtyRects(0, row.localTop, rowHeaderWidth, row.height, leftScrollHeaderDirtyRects)) {
|
|
@@ -25080,9 +25830,29 @@ function XlsxGrid({
|
|
|
25080
25830
|
paintedHeaderCanvasSignatureRef.current = nextHeaderCanvasSignature;
|
|
25081
25831
|
}
|
|
25082
25832
|
applyCanvasViewportCompensation();
|
|
25833
|
+
if (canvasProfileTarget) {
|
|
25834
|
+
canvasProfileTarget.push({
|
|
25835
|
+
bodyMs: canvasProfileBodyMs,
|
|
25836
|
+
culledCells: canvasProfileCulledCells,
|
|
25837
|
+
dirtyRects: canvasProfileDirtyRects,
|
|
25838
|
+
lookedUpCells: canvasProfileLookedUpCells,
|
|
25839
|
+
paintedCells: canvasProfilePaintedCells,
|
|
25840
|
+
repaintBody: shouldRepaintBody,
|
|
25841
|
+
repaintHeaders: shouldRepaintHeaders,
|
|
25842
|
+
renderToLayoutMs: canvasProfileStart - xlsxGridRenderStart,
|
|
25843
|
+
totalMs: performance.now() - canvasProfileStart
|
|
25844
|
+
});
|
|
25845
|
+
if (canvasProfileTarget.length > 500) {
|
|
25846
|
+
canvasProfileTarget.splice(0, canvasProfileTarget.length - 500);
|
|
25847
|
+
}
|
|
25848
|
+
}
|
|
25083
25849
|
}, [
|
|
25084
25850
|
activeSheet,
|
|
25085
25851
|
applyCanvasViewportCompensation,
|
|
25852
|
+
bakedCanvasDrawingSignature,
|
|
25853
|
+
bakedFormControlRects,
|
|
25854
|
+
bakedImageRects,
|
|
25855
|
+
bakedShapeRects,
|
|
25086
25856
|
canvasColumnHeaderCells,
|
|
25087
25857
|
canvasPaneAxisItems,
|
|
25088
25858
|
canvasRowHeaderCells,
|
|
@@ -25103,15 +25873,16 @@ function XlsxGrid({
|
|
|
25103
25873
|
frozenPaneBottom,
|
|
25104
25874
|
frozenPaneRight,
|
|
25105
25875
|
getCellData,
|
|
25876
|
+
getCanvasImage,
|
|
25106
25877
|
getBodyBlitBufferCanvas,
|
|
25107
25878
|
getHeaderBlitBufferCanvas,
|
|
25108
25879
|
palette,
|
|
25109
25880
|
resolveCellDisplayRect,
|
|
25110
25881
|
resolveMergeAnchorCell,
|
|
25111
|
-
resizeGuide,
|
|
25112
25882
|
rowIndexByActual,
|
|
25113
25883
|
rowPrefixSums,
|
|
25114
25884
|
selectionHeaderSurface,
|
|
25885
|
+
shouldBakeCanvasStaticDrawings,
|
|
25115
25886
|
stickyLeftByCol,
|
|
25116
25887
|
stickyTopByRow,
|
|
25117
25888
|
visibleCols,
|
|
@@ -25329,7 +26100,7 @@ function XlsxGrid({
|
|
|
25329
26100
|
start: virtualRow?.start ?? (rowPrefixSums[index] ?? 0)
|
|
25330
26101
|
};
|
|
25331
26102
|
});
|
|
25332
|
-
const totalHeight = shouldVirtualizeRows ? rowVirtualizer.getTotalSize() : rowPrefixSums[rowPrefixSums.length - 1] ?? 0;
|
|
26103
|
+
const totalHeight = shouldUseDomVirtualizer && shouldVirtualizeRows ? rowVirtualizer.getTotalSize() : rowPrefixSums[rowPrefixSums.length - 1] ?? 0;
|
|
25333
26104
|
const totalWidth = totalContentWidth + displayRowHeaderWidth;
|
|
25334
26105
|
const sheetContentHeight = displayHeaderHeight + totalHeight;
|
|
25335
26106
|
const isLiveZooming = liveGestureZoom !== null && zoomScale === liveGestureZoom.baseZoomScale;
|
|
@@ -25403,18 +26174,6 @@ function XlsxGrid({
|
|
|
25403
26174
|
width: 0,
|
|
25404
26175
|
zIndex: canvasHeaderOverlayZIndex
|
|
25405
26176
|
};
|
|
25406
|
-
const scrollBodyCanvasWidth = Math.max(0, drawingViewport.width - frozenPaneRight);
|
|
25407
|
-
const scrollBodyCanvasHeight = Math.max(0, drawingViewport.height - frozenPaneBottom);
|
|
25408
|
-
const topBodyCanvasWidth = scrollBodyCanvasWidth;
|
|
25409
|
-
const topBodyCanvasHeight = Math.max(0, frozenPaneBottom - displayHeaderHeight);
|
|
25410
|
-
const leftBodyCanvasWidth = Math.max(0, frozenPaneRight - displayRowHeaderWidth);
|
|
25411
|
-
const leftBodyCanvasHeight = scrollBodyCanvasHeight;
|
|
25412
|
-
const cornerBodyCanvasWidth = leftBodyCanvasWidth;
|
|
25413
|
-
const cornerBodyCanvasHeight = topBodyCanvasHeight;
|
|
25414
|
-
const topFrozenHeaderCanvasWidth = leftBodyCanvasWidth;
|
|
25415
|
-
const topScrollHeaderCanvasWidth = scrollBodyCanvasWidth;
|
|
25416
|
-
const leftFrozenHeaderCanvasHeight = topBodyCanvasHeight;
|
|
25417
|
-
const leftScrollHeaderCanvasHeight = scrollBodyCanvasHeight;
|
|
25418
26177
|
const canvasBodyBaseStyle = {
|
|
25419
26178
|
cursor: "cell",
|
|
25420
26179
|
pointerEvents: "auto",
|
|
@@ -25426,13 +26185,13 @@ function XlsxGrid({
|
|
|
25426
26185
|
const canvasScrollBodyStyle = {
|
|
25427
26186
|
...canvasBodyBaseStyle,
|
|
25428
26187
|
display: scrollBodyCanvasWidth > 0 && scrollBodyCanvasHeight > 0 ? "block" : "none",
|
|
25429
|
-
left:
|
|
25430
|
-
top:
|
|
26188
|
+
left: scrollBodyCanvasLeft,
|
|
26189
|
+
top: scrollBodyCanvasTop
|
|
25431
26190
|
};
|
|
25432
26191
|
const canvasTopBodyStyle = {
|
|
25433
26192
|
...canvasBodyBaseStyle,
|
|
25434
26193
|
display: topBodyCanvasWidth > 0 && topBodyCanvasHeight > 0 ? "block" : "none",
|
|
25435
|
-
left:
|
|
26194
|
+
left: scrollBodyCanvasLeft,
|
|
25436
26195
|
top: displayHeaderHeight,
|
|
25437
26196
|
zIndex: 30
|
|
25438
26197
|
};
|
|
@@ -25440,7 +26199,7 @@ function XlsxGrid({
|
|
|
25440
26199
|
...canvasBodyBaseStyle,
|
|
25441
26200
|
display: leftBodyCanvasWidth > 0 && leftBodyCanvasHeight > 0 ? "block" : "none",
|
|
25442
26201
|
left: displayRowHeaderWidth,
|
|
25443
|
-
top:
|
|
26202
|
+
top: scrollBodyCanvasTop,
|
|
25444
26203
|
zIndex: 30
|
|
25445
26204
|
};
|
|
25446
26205
|
const canvasCornerBodyStyle = {
|
|
@@ -25466,7 +26225,7 @@ function XlsxGrid({
|
|
|
25466
26225
|
const canvasTopScrollHeaderStyle = {
|
|
25467
26226
|
...canvasHeaderBaseStyle,
|
|
25468
26227
|
display: topScrollHeaderCanvasWidth > 0 && drawingViewport.height > 0 ? "block" : "none",
|
|
25469
|
-
left:
|
|
26228
|
+
left: scrollBodyCanvasLeft,
|
|
25470
26229
|
top: 0,
|
|
25471
26230
|
zIndex: canvasHeaderOverlayZIndex
|
|
25472
26231
|
};
|
|
@@ -25481,7 +26240,7 @@ function XlsxGrid({
|
|
|
25481
26240
|
...canvasHeaderBaseStyle,
|
|
25482
26241
|
display: leftScrollHeaderCanvasHeight > 0 && drawingViewport.width > 0 ? "block" : "none",
|
|
25483
26242
|
left: 0,
|
|
25484
|
-
top:
|
|
26243
|
+
top: scrollBodyCanvasTop,
|
|
25485
26244
|
zIndex: canvasHeaderOverlayZIndex
|
|
25486
26245
|
};
|
|
25487
26246
|
const canvasCornerHeaderStyle = {
|
|
@@ -26037,26 +26796,26 @@ function XlsxGrid({
|
|
|
26037
26796
|
};
|
|
26038
26797
|
const canvasScrollOverlayPaneStyle = {
|
|
26039
26798
|
...canvasOverlayPaneBaseStyle,
|
|
26040
|
-
display:
|
|
26041
|
-
height:
|
|
26799
|
+
display: scrollBodyViewportWidth > 0 && scrollBodyViewportHeight > 0 ? "block" : "none",
|
|
26800
|
+
height: scrollBodyViewportHeight,
|
|
26042
26801
|
left: frozenPaneRight,
|
|
26043
26802
|
top: frozenPaneBottom,
|
|
26044
|
-
width:
|
|
26803
|
+
width: scrollBodyViewportWidth,
|
|
26045
26804
|
zIndex: 20
|
|
26046
26805
|
};
|
|
26047
26806
|
const canvasTopOverlayPaneStyle = {
|
|
26048
26807
|
...canvasOverlayPaneBaseStyle,
|
|
26049
|
-
display:
|
|
26808
|
+
display: scrollBodyViewportWidth > 0 && topBodyCanvasHeight > 0 ? "block" : "none",
|
|
26050
26809
|
height: topBodyCanvasHeight,
|
|
26051
26810
|
left: frozenPaneRight,
|
|
26052
26811
|
top: displayHeaderHeight,
|
|
26053
|
-
width:
|
|
26812
|
+
width: scrollBodyViewportWidth,
|
|
26054
26813
|
zIndex: 35
|
|
26055
26814
|
};
|
|
26056
26815
|
const canvasLeftOverlayPaneStyle = {
|
|
26057
26816
|
...canvasOverlayPaneBaseStyle,
|
|
26058
|
-
display: leftBodyCanvasWidth > 0 &&
|
|
26059
|
-
height:
|
|
26817
|
+
display: leftBodyCanvasWidth > 0 && scrollBodyViewportHeight > 0 ? "block" : "none",
|
|
26818
|
+
height: scrollBodyViewportHeight,
|
|
26060
26819
|
left: displayRowHeaderWidth,
|
|
26061
26820
|
top: frozenPaneBottom,
|
|
26062
26821
|
width: leftBodyCanvasWidth,
|
|
@@ -26071,8 +26830,9 @@ function XlsxGrid({
|
|
|
26071
26830
|
width: cornerBodyCanvasWidth,
|
|
26072
26831
|
zIndex: 36
|
|
26073
26832
|
};
|
|
26833
|
+
const drawingViewportCacheSignature = `${Math.floor(drawingViewport.left / CANVAS_VIEWPORT_OVERSCAN_PX)}:${Math.floor(drawingViewport.top / CANVAS_VIEWPORT_OVERSCAN_PX)}:${drawingViewport.width}:${drawingViewport.height}`;
|
|
26074
26834
|
const previousPaneDrawingNodes = paneDrawingNodesCacheRef.current;
|
|
26075
|
-
const canReusePaneDrawingNodes = previousPaneDrawingNodes !== null && previousPaneDrawingNodes.showImages === showImages && previousPaneDrawingNodes.chartRects === chartRects && previousPaneDrawingNodes.formControlRects ===
|
|
26835
|
+
const canReusePaneDrawingNodes = previousPaneDrawingNodes !== null && previousPaneDrawingNodes.showImages === showImages && previousPaneDrawingNodes.chartRects === chartRects && previousPaneDrawingNodes.formControlRects === domFormControlRects && previousPaneDrawingNodes.shapeRects === domShapeRects && previousPaneDrawingNodes.imageRects === domImageRects && previousPaneDrawingNodes.selectedChartId === selectedChartId && previousPaneDrawingNodes.selectedImageId === selectedImageId && previousPaneDrawingNodes.readOnly === readOnly && previousPaneDrawingNodes.selectionStroke === selectionStroke && previousPaneDrawingNodes.renderChartLoading === renderChartLoading && previousPaneDrawingNodes.renderImage === renderImage && previousPaneDrawingNodes.renderImageSelection === renderImageSelection && previousPaneDrawingNodes.isChartsLoading === isChartsLoading && previousPaneDrawingNodes.palette === palette && previousPaneDrawingNodes.drawingViewportSignature === drawingViewportCacheSignature;
|
|
26076
26836
|
const paneDrawingNodes = canReusePaneDrawingNodes ? previousPaneDrawingNodes.value : !showImages ? {
|
|
26077
26837
|
corner: null,
|
|
26078
26838
|
left: null,
|
|
@@ -26081,35 +26841,35 @@ function XlsxGrid({
|
|
|
26081
26841
|
} : {
|
|
26082
26842
|
corner: /* @__PURE__ */ jsxs3(Fragment4, { children: [
|
|
26083
26843
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "corner")),
|
|
26084
|
-
|
|
26085
|
-
|
|
26086
|
-
|
|
26844
|
+
domShapeRects.map(({ shape, rect }) => renderShapeDrawing(shape, rect, "corner")),
|
|
26845
|
+
domFormControlRects.map(({ control, rect }) => renderFormControlDrawing(control, rect, "corner")),
|
|
26846
|
+
domImageRects.map(({ image, rect }) => renderImageDrawing(image, rect, "corner"))
|
|
26087
26847
|
] }),
|
|
26088
26848
|
left: /* @__PURE__ */ jsxs3(Fragment4, { children: [
|
|
26089
26849
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "left")),
|
|
26090
|
-
|
|
26091
|
-
|
|
26092
|
-
|
|
26850
|
+
domShapeRects.map(({ shape, rect }) => renderShapeDrawing(shape, rect, "left")),
|
|
26851
|
+
domFormControlRects.map(({ control, rect }) => renderFormControlDrawing(control, rect, "left")),
|
|
26852
|
+
domImageRects.map(({ image, rect }) => renderImageDrawing(image, rect, "left"))
|
|
26093
26853
|
] }),
|
|
26094
26854
|
scroll: /* @__PURE__ */ jsxs3(Fragment4, { children: [
|
|
26095
26855
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "scroll")),
|
|
26096
|
-
|
|
26097
|
-
|
|
26098
|
-
|
|
26856
|
+
domShapeRects.map(({ shape, rect }) => renderShapeDrawing(shape, rect, "scroll")),
|
|
26857
|
+
domFormControlRects.map(({ control, rect }) => renderFormControlDrawing(control, rect, "scroll")),
|
|
26858
|
+
domImageRects.map(({ image, rect }) => renderImageDrawing(image, rect, "scroll"))
|
|
26099
26859
|
] }),
|
|
26100
26860
|
top: /* @__PURE__ */ jsxs3(Fragment4, { children: [
|
|
26101
26861
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "top")),
|
|
26102
|
-
|
|
26103
|
-
|
|
26104
|
-
|
|
26862
|
+
domShapeRects.map(({ shape, rect }) => renderShapeDrawing(shape, rect, "top")),
|
|
26863
|
+
domFormControlRects.map(({ control, rect }) => renderFormControlDrawing(control, rect, "top")),
|
|
26864
|
+
domImageRects.map(({ image, rect }) => renderImageDrawing(image, rect, "top"))
|
|
26105
26865
|
] })
|
|
26106
26866
|
};
|
|
26107
26867
|
if (!canReusePaneDrawingNodes) {
|
|
26108
26868
|
paneDrawingNodesCacheRef.current = {
|
|
26109
26869
|
chartRects,
|
|
26110
|
-
|
|
26111
|
-
formControlRects,
|
|
26112
|
-
imageRects,
|
|
26870
|
+
drawingViewportSignature: drawingViewportCacheSignature,
|
|
26871
|
+
formControlRects: domFormControlRects,
|
|
26872
|
+
imageRects: domImageRects,
|
|
26113
26873
|
isChartsLoading,
|
|
26114
26874
|
palette,
|
|
26115
26875
|
readOnly,
|
|
@@ -26119,7 +26879,7 @@ function XlsxGrid({
|
|
|
26119
26879
|
selectedChartId,
|
|
26120
26880
|
selectedImageId,
|
|
26121
26881
|
selectionStroke,
|
|
26122
|
-
shapeRects,
|
|
26882
|
+
shapeRects: domShapeRects,
|
|
26123
26883
|
showImages,
|
|
26124
26884
|
value: paneDrawingNodes
|
|
26125
26885
|
};
|
|
@@ -26627,10 +27387,11 @@ function XlsxGrid({
|
|
|
26627
27387
|
style: canvasCornerBodyStyle
|
|
26628
27388
|
}
|
|
26629
27389
|
),
|
|
26630
|
-
|
|
27390
|
+
hasCanvasDomDrawingOverlays ? /* @__PURE__ */ jsxs3(Fragment4, { children: [
|
|
26631
27391
|
/* @__PURE__ */ jsx3("div", { style: canvasScrollOverlayPaneStyle, children: /* @__PURE__ */ jsx3(
|
|
26632
27392
|
"div",
|
|
26633
27393
|
{
|
|
27394
|
+
ref: canvasScrollOverlayContentRef,
|
|
26634
27395
|
style: {
|
|
26635
27396
|
height: sheetContentHeight,
|
|
26636
27397
|
left: 0,
|
|
@@ -26638,6 +27399,7 @@ function XlsxGrid({
|
|
|
26638
27399
|
position: "absolute",
|
|
26639
27400
|
top: 0,
|
|
26640
27401
|
transform: `translate(${-drawingViewport.left - frozenPaneRight}px, ${-drawingViewport.top - frozenPaneBottom}px)`,
|
|
27402
|
+
transformOrigin: "0 0",
|
|
26641
27403
|
width: totalWidth
|
|
26642
27404
|
},
|
|
26643
27405
|
children: paneDrawingNodes.scroll
|
|
@@ -26646,6 +27408,7 @@ function XlsxGrid({
|
|
|
26646
27408
|
/* @__PURE__ */ jsx3("div", { style: canvasTopOverlayPaneStyle, children: /* @__PURE__ */ jsx3(
|
|
26647
27409
|
"div",
|
|
26648
27410
|
{
|
|
27411
|
+
ref: canvasTopOverlayContentRef,
|
|
26649
27412
|
style: {
|
|
26650
27413
|
height: sheetContentHeight,
|
|
26651
27414
|
left: 0,
|
|
@@ -26653,6 +27416,7 @@ function XlsxGrid({
|
|
|
26653
27416
|
position: "absolute",
|
|
26654
27417
|
top: 0,
|
|
26655
27418
|
transform: `translate(${-drawingViewport.left - frozenPaneRight}px, ${-displayHeaderHeight}px)`,
|
|
27419
|
+
transformOrigin: "0 0",
|
|
26656
27420
|
width: totalWidth
|
|
26657
27421
|
},
|
|
26658
27422
|
children: paneDrawingNodes.top
|
|
@@ -26661,6 +27425,7 @@ function XlsxGrid({
|
|
|
26661
27425
|
/* @__PURE__ */ jsx3("div", { style: canvasLeftOverlayPaneStyle, children: /* @__PURE__ */ jsx3(
|
|
26662
27426
|
"div",
|
|
26663
27427
|
{
|
|
27428
|
+
ref: canvasLeftOverlayContentRef,
|
|
26664
27429
|
style: {
|
|
26665
27430
|
height: sheetContentHeight,
|
|
26666
27431
|
left: 0,
|
|
@@ -26668,6 +27433,7 @@ function XlsxGrid({
|
|
|
26668
27433
|
position: "absolute",
|
|
26669
27434
|
top: 0,
|
|
26670
27435
|
transform: `translate(${-displayRowHeaderWidth}px, ${-drawingViewport.top - frozenPaneBottom}px)`,
|
|
27436
|
+
transformOrigin: "0 0",
|
|
26671
27437
|
width: totalWidth
|
|
26672
27438
|
},
|
|
26673
27439
|
children: paneDrawingNodes.left
|
|
@@ -26676,6 +27442,7 @@ function XlsxGrid({
|
|
|
26676
27442
|
/* @__PURE__ */ jsx3("div", { style: canvasCornerOverlayPaneStyle, children: /* @__PURE__ */ jsx3(
|
|
26677
27443
|
"div",
|
|
26678
27444
|
{
|
|
27445
|
+
ref: canvasCornerOverlayContentRef,
|
|
26679
27446
|
style: {
|
|
26680
27447
|
height: sheetContentHeight,
|
|
26681
27448
|
left: 0,
|
|
@@ -26683,6 +27450,7 @@ function XlsxGrid({
|
|
|
26683
27450
|
position: "absolute",
|
|
26684
27451
|
top: 0,
|
|
26685
27452
|
transform: `translate(${-displayRowHeaderWidth}px, ${-displayHeaderHeight}px)`,
|
|
27453
|
+
transformOrigin: "0 0",
|
|
26686
27454
|
width: totalWidth
|
|
26687
27455
|
},
|
|
26688
27456
|
children: paneDrawingNodes.corner
|
|
@@ -27089,7 +27857,7 @@ function XlsxViewerInner({
|
|
|
27089
27857
|
enableCanvasSelectionAnimation = true,
|
|
27090
27858
|
enableGestureZoom = true,
|
|
27091
27859
|
errorState,
|
|
27092
|
-
experimentalCanvas =
|
|
27860
|
+
experimentalCanvas = true,
|
|
27093
27861
|
fileTooLargeState,
|
|
27094
27862
|
height,
|
|
27095
27863
|
isDark = false,
|
|
@@ -27602,7 +28370,7 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27602
28370
|
if (!canvas) {
|
|
27603
28371
|
return false;
|
|
27604
28372
|
}
|
|
27605
|
-
const context = canvas.getContext("2d");
|
|
28373
|
+
const context = canvas.getContext("2d", { alpha: false });
|
|
27606
28374
|
if (!context) {
|
|
27607
28375
|
return false;
|
|
27608
28376
|
}
|
|
@@ -27626,9 +28394,10 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27626
28394
|
}
|
|
27627
28395
|
context.setTransform(dpr * scale, 0, 0, dpr * scale, 0, 0);
|
|
27628
28396
|
context.clearRect(0, 0, Math.max(1, sourceWidth), Math.max(1, sourceHeight));
|
|
28397
|
+
const thumbnailSheetSurface = resolveSheetSurface(sheet, palette);
|
|
27629
28398
|
context.fillStyle = palette.canvas;
|
|
27630
28399
|
context.fillRect(0, 0, Math.max(1, sourceWidth), Math.max(1, sourceHeight));
|
|
27631
|
-
context.fillStyle =
|
|
28400
|
+
context.fillStyle = thumbnailSheetSurface;
|
|
27632
28401
|
context.fillRect(rowHeaderWidth, headerHeight, Math.max(1, colAxis.totalSize), Math.max(1, rowAxis.totalSize));
|
|
27633
28402
|
if (includeHeaders) {
|
|
27634
28403
|
context.fillStyle = palette.headerSurface;
|
|
@@ -27749,8 +28518,8 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27749
28518
|
};
|
|
27750
28519
|
const canvasCellStyle = cellData.canvas ?? buildCanvasCellStyleCache(cellData.style);
|
|
27751
28520
|
const gradientFill = typeof cellData.style.backgroundImage === "string" ? resolveCanvasGradientFill(context, rect, cellData.style.backgroundImage) : null;
|
|
27752
|
-
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellData.style.backgroundColor === "string" ? cellData.style.backgroundColor :
|
|
27753
|
-
const hasExplicitCellFill = cellData.conditionalColorScale !== null || gradientFill !== null || typeof cellData.style.backgroundColor === "string" && cellData.style.backgroundColor !==
|
|
28521
|
+
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellData.style.backgroundColor === "string" ? cellData.style.backgroundColor : thumbnailSheetSurface);
|
|
28522
|
+
const hasExplicitCellFill = cellData.conditionalColorScale !== null || gradientFill !== null || typeof cellData.style.backgroundColor === "string" && cellData.style.backgroundColor !== thumbnailSheetSurface;
|
|
27754
28523
|
context.fillStyle = gradientFill ?? fillColor;
|
|
27755
28524
|
context.fillRect(rect.left, rect.top, rect.width, rect.height);
|
|
27756
28525
|
if (cellData.conditionalDataBar) {
|
|
@@ -27805,12 +28574,19 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27805
28574
|
if (canvasCellStyle.leftBorder) {
|
|
27806
28575
|
strokeCanvasBorderSide(context, "left", rect, canvasCellStyle.leftBorder);
|
|
27807
28576
|
}
|
|
28577
|
+
const rawText = cellData.value ?? "";
|
|
28578
|
+
const shouldDrawThumbnailContent = cellData.checkboxState != null || cellData.sparkline || rawText.length > 0 || cellData.conditionalIcon;
|
|
28579
|
+
if (!shouldDrawThumbnailContent) {
|
|
28580
|
+
continue;
|
|
28581
|
+
}
|
|
27808
28582
|
const padding = canvasCellStyle.padding;
|
|
27809
28583
|
const contentLeft = rect.left + padding.left;
|
|
27810
28584
|
const contentTop = rect.top + padding.top;
|
|
27811
28585
|
const contentWidth = Math.max(0, rect.width - padding.left - padding.right);
|
|
27812
28586
|
const contentHeight = Math.max(0, rect.height - padding.top - padding.bottom);
|
|
27813
|
-
|
|
28587
|
+
if (contentWidth <= 0 || contentHeight <= 0) {
|
|
28588
|
+
continue;
|
|
28589
|
+
}
|
|
27814
28590
|
context.save();
|
|
27815
28591
|
context.beginPath();
|
|
27816
28592
|
context.rect(contentLeft, contentTop, contentWidth, contentHeight);
|