@extend-ai/react-xlsx 0.8.3 → 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 +904 -178
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +904 -178
- 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.cjs
CHANGED
|
@@ -4575,6 +4575,10 @@ function parseSheetState(archive, path, options) {
|
|
|
4575
4575
|
let hasVerticalMerges = false;
|
|
4576
4576
|
let maxHorizontalMergeEndCol = -1;
|
|
4577
4577
|
let maxVerticalMergeEndRow = -1;
|
|
4578
|
+
let minContentCol = Number.POSITIVE_INFINITY;
|
|
4579
|
+
let minContentRow = Number.POSITIVE_INFINITY;
|
|
4580
|
+
let maxContentCol = -1;
|
|
4581
|
+
let maxContentRow = -1;
|
|
4578
4582
|
const columnWidthCharacterWidthPx = measureColumnCharacterWidthPx(
|
|
4579
4583
|
options?.defaultFont?.family,
|
|
4580
4584
|
options?.defaultFont?.sizePt
|
|
@@ -4587,6 +4591,26 @@ function parseSheetState(archive, path, options) {
|
|
|
4587
4591
|
sheetViewNode?.getAttribute("zoomScale") ?? sheetViewNode?.getAttribute("zoomScaleNormal") ?? Number.NaN
|
|
4588
4592
|
);
|
|
4589
4593
|
const zoomScale = Number.isFinite(rawZoomScale) && rawZoomScale > 0 ? rawZoomScale : 100;
|
|
4594
|
+
const trackContentCell = (cellRef) => {
|
|
4595
|
+
if (!cellRef) {
|
|
4596
|
+
return;
|
|
4597
|
+
}
|
|
4598
|
+
const cell = parseA1CellReference(cellRef);
|
|
4599
|
+
if (!cell) {
|
|
4600
|
+
return;
|
|
4601
|
+
}
|
|
4602
|
+
minContentCol = Math.min(minContentCol, cell.col);
|
|
4603
|
+
minContentRow = Math.min(minContentRow, cell.row);
|
|
4604
|
+
maxContentCol = Math.max(maxContentCol, cell.col);
|
|
4605
|
+
maxContentRow = Math.max(maxContentRow, cell.row);
|
|
4606
|
+
};
|
|
4607
|
+
const isMeaningfulCellNode = (cellNode) => {
|
|
4608
|
+
if (getFirstChild(cellNode, "f") || getFirstChild(cellNode, "is")) {
|
|
4609
|
+
return true;
|
|
4610
|
+
}
|
|
4611
|
+
const valueNode = getFirstChild(cellNode, "v");
|
|
4612
|
+
return Boolean(valueNode && (valueNode.textContent ?? "").length > 0);
|
|
4613
|
+
};
|
|
4590
4614
|
getLocalElements(document2, "row").forEach((rowNode) => {
|
|
4591
4615
|
const rowIndex = Number(rowNode.getAttribute("r") ?? 0) - 1;
|
|
4592
4616
|
const height = Number(rowNode.getAttribute("ht") ?? Number.NaN);
|
|
@@ -4601,17 +4625,36 @@ function parseSheetState(archive, path, options) {
|
|
|
4601
4625
|
if (rowIndex >= 0 && isHidden) {
|
|
4602
4626
|
hiddenRows.add(rowIndex);
|
|
4603
4627
|
}
|
|
4604
|
-
|
|
4605
|
-
|
|
4628
|
+
getChildElements(rowNode, "c").forEach((cellNode) => {
|
|
4629
|
+
const cellRef = cellNode.getAttribute("r");
|
|
4630
|
+
if (isMeaningfulCellNode(cellNode)) {
|
|
4631
|
+
trackContentCell(cellRef);
|
|
4632
|
+
}
|
|
4633
|
+
if (includeCachedFormulaValues) {
|
|
4606
4634
|
const formulaNode = getFirstChild(cellNode, "f");
|
|
4607
4635
|
const valueNode = getFirstChild(cellNode, "v");
|
|
4608
|
-
const cellRef = cellNode.getAttribute("r");
|
|
4609
4636
|
if (formulaNode && valueNode && cellRef) {
|
|
4610
4637
|
cachedFormulaValues[cellRef] = valueNode.textContent ?? "";
|
|
4611
4638
|
}
|
|
4612
|
-
}
|
|
4639
|
+
}
|
|
4640
|
+
});
|
|
4641
|
+
});
|
|
4642
|
+
getLocalElements(document2, "mergeCell").forEach((mergeNode) => {
|
|
4643
|
+
const reference = mergeNode.getAttribute("ref");
|
|
4644
|
+
const range = reference ? parseA1RangeReference(reference) : null;
|
|
4645
|
+
if (!range) {
|
|
4646
|
+
return;
|
|
4647
|
+
}
|
|
4648
|
+
if (range.end.col > range.start.col) {
|
|
4649
|
+
hasHorizontalMerges = true;
|
|
4650
|
+
maxHorizontalMergeEndCol = Math.max(maxHorizontalMergeEndCol, range.end.col);
|
|
4651
|
+
}
|
|
4652
|
+
if (range.end.row > range.start.row) {
|
|
4653
|
+
hasVerticalMerges = true;
|
|
4654
|
+
maxVerticalMergeEndRow = Math.max(maxVerticalMergeEndRow, range.end.row);
|
|
4613
4655
|
}
|
|
4614
4656
|
});
|
|
4657
|
+
const maxMetadataCol = Math.max(maxContentCol, maxHorizontalMergeEndCol, 0) + 256;
|
|
4615
4658
|
getLocalElements(document2, "col").forEach((colNode) => {
|
|
4616
4659
|
const min = Number(colNode.getAttribute("min") ?? 0) - 1;
|
|
4617
4660
|
const max = Number(colNode.getAttribute("max") ?? 0) - 1;
|
|
@@ -4623,7 +4666,7 @@ function parseSheetState(archive, path, options) {
|
|
|
4623
4666
|
return;
|
|
4624
4667
|
}
|
|
4625
4668
|
}
|
|
4626
|
-
for (let col = min; col <= max; col += 1) {
|
|
4669
|
+
for (let col = min; col <= Math.min(max, maxMetadataCol); col += 1) {
|
|
4627
4670
|
if (col >= 0) {
|
|
4628
4671
|
if (Number.isFinite(width)) {
|
|
4629
4672
|
const widthPx = sheetColumnWidthToPixels(width, columnWidthCharacterWidthPx);
|
|
@@ -4638,21 +4681,6 @@ function parseSheetState(archive, path, options) {
|
|
|
4638
4681
|
}
|
|
4639
4682
|
}
|
|
4640
4683
|
});
|
|
4641
|
-
getLocalElements(document2, "mergeCell").forEach((mergeNode) => {
|
|
4642
|
-
const reference = mergeNode.getAttribute("ref");
|
|
4643
|
-
const range = reference ? parseA1RangeReference(reference) : null;
|
|
4644
|
-
if (!range) {
|
|
4645
|
-
return;
|
|
4646
|
-
}
|
|
4647
|
-
if (range.end.col > range.start.col) {
|
|
4648
|
-
hasHorizontalMerges = true;
|
|
4649
|
-
maxHorizontalMergeEndCol = Math.max(maxHorizontalMergeEndCol, range.end.col);
|
|
4650
|
-
}
|
|
4651
|
-
if (range.end.row > range.start.row) {
|
|
4652
|
-
hasVerticalMerges = true;
|
|
4653
|
-
maxVerticalMergeEndRow = Math.max(maxVerticalMergeEndRow, range.end.row);
|
|
4654
|
-
}
|
|
4655
|
-
});
|
|
4656
4684
|
return {
|
|
4657
4685
|
cachedFormulaValues,
|
|
4658
4686
|
columnWidthCharacterWidthPx,
|
|
@@ -4665,6 +4693,10 @@ function parseSheetState(archive, path, options) {
|
|
|
4665
4693
|
hasVerticalMerges,
|
|
4666
4694
|
maxHorizontalMergeEndCol,
|
|
4667
4695
|
maxVerticalMergeEndRow,
|
|
4696
|
+
maxContentCol,
|
|
4697
|
+
maxContentRow,
|
|
4698
|
+
minContentCol: Number.isFinite(minContentCol) ? minContentCol : -1,
|
|
4699
|
+
minContentRow: Number.isFinite(minContentRow) ? minContentRow : -1,
|
|
4668
4700
|
hiddenCols: [...hiddenCols].sort((left, right) => left - right),
|
|
4669
4701
|
hiddenRows: [...hiddenRows].sort((left, right) => left - right),
|
|
4670
4702
|
rowHeightOverridesPx,
|
|
@@ -6694,6 +6726,20 @@ function resolveDisplayFileName(src, fileName) {
|
|
|
6694
6726
|
return lastSegment;
|
|
6695
6727
|
}
|
|
6696
6728
|
}
|
|
6729
|
+
function resolveSheetDisplayUsedRange(usedRange, sheetState) {
|
|
6730
|
+
const [minRow, minCol, maxRow, maxCol] = usedRange;
|
|
6731
|
+
const maxMeaningfulRow = Math.max(sheetState?.maxContentRow ?? -1, sheetState?.maxVerticalMergeEndRow ?? -1);
|
|
6732
|
+
const maxMeaningfulCol = Math.max(sheetState?.maxContentCol ?? -1, sheetState?.maxHorizontalMergeEndCol ?? -1);
|
|
6733
|
+
if (maxMeaningfulRow < 0 && maxMeaningfulCol < 0) {
|
|
6734
|
+
return usedRange;
|
|
6735
|
+
}
|
|
6736
|
+
return [
|
|
6737
|
+
sheetState?.minContentRow !== void 0 && sheetState.minContentRow >= 0 ? Math.min(minRow, sheetState.minContentRow) : minRow,
|
|
6738
|
+
sheetState?.minContentCol !== void 0 && sheetState.minContentCol >= 0 ? Math.min(minCol, sheetState.minContentCol) : minCol,
|
|
6739
|
+
maxMeaningfulRow >= 0 ? Math.min(maxRow, maxMeaningfulRow) : maxRow,
|
|
6740
|
+
maxMeaningfulCol >= 0 ? Math.min(maxCol, maxMeaningfulCol) : maxCol
|
|
6741
|
+
];
|
|
6742
|
+
}
|
|
6697
6743
|
function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette, styleById, namedCellStyleByName, tableStyleByName, showHiddenSheets = false) {
|
|
6698
6744
|
const sheets = [];
|
|
6699
6745
|
for (let index = 0; index < workbook.sheetCount; index += 1) {
|
|
@@ -6760,7 +6806,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
|
|
|
6760
6806
|
});
|
|
6761
6807
|
continue;
|
|
6762
6808
|
}
|
|
6763
|
-
const [minRow, minCol, maxRow, maxCol] = usedRange;
|
|
6809
|
+
const [minRow, minCol, maxRow, maxCol] = resolveSheetDisplayUsedRange(usedRange, sheetState);
|
|
6764
6810
|
let visibleRowsCache = null;
|
|
6765
6811
|
let visibleColsCache = null;
|
|
6766
6812
|
let rowHeightsCache = null;
|
|
@@ -16502,7 +16548,11 @@ var SELECTION_DRAG_THRESHOLD_PX = 4;
|
|
|
16502
16548
|
var IMAGE_MIN_SIZE_PX = 16;
|
|
16503
16549
|
var IMAGE_HANDLE_SIZE_PX = 10;
|
|
16504
16550
|
var CANVAS_RESIZE_HIT_SLOP_PX = 8;
|
|
16505
|
-
var CANVAS_VIEWPORT_OVERSCAN_PX =
|
|
16551
|
+
var CANVAS_VIEWPORT_OVERSCAN_PX = 480;
|
|
16552
|
+
var CANVAS_SCROLL_BUFFER_PX = 480;
|
|
16553
|
+
var CANVAS_DEFERRED_VIEWPORT_SYNC_THRESHOLD_PX = CANVAS_SCROLL_BUFFER_PX - 96;
|
|
16554
|
+
var CANVAS_IMMEDIATE_VIEWPORT_SYNC_THRESHOLD_PX = CANVAS_SCROLL_BUFFER_PX * 1.5;
|
|
16555
|
+
var CANVAS_DIRTY_CELL_CULL_MARGIN_PX = CANVAS_VIEWPORT_OVERSCAN_PX * 2;
|
|
16506
16556
|
var THUMBNAIL_DEFAULT_MAX_DIMENSION = 192;
|
|
16507
16557
|
var THUMBNAIL_FALLBACK_ROWS = 12;
|
|
16508
16558
|
var THUMBNAIL_FALLBACK_COLS = 8;
|
|
@@ -16517,6 +16567,12 @@ var CHART_SOURCE_HIGHLIGHT_COLORS = ["#2563eb", "#dc2626", "#7c3aed", "#059669",
|
|
|
16517
16567
|
var SHEET_SURFACE = "#ffffff";
|
|
16518
16568
|
var DEFAULT_CELL_PADDING = "0 4px";
|
|
16519
16569
|
var IMAGE_HANDLE_POSITIONS = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
16570
|
+
var CANVAS_CELL_STYLE_CACHE_LIMIT = 4096;
|
|
16571
|
+
var CANVAS_TEXT_MEASURE_CACHE_LIMIT = 2e4;
|
|
16572
|
+
var CANVAS_TEXT_TRUNCATE_CACHE_LIMIT = 4096;
|
|
16573
|
+
var CANVAS_TEXT_WRAP_CACHE_LIMIT = 2048;
|
|
16574
|
+
var CANVAS_PATH2D_CACHE_LIMIT = 512;
|
|
16575
|
+
var EMPTY_VIRTUAL_ITEMS = [];
|
|
16520
16576
|
var IMAGE_HANDLE_CURSOR = {
|
|
16521
16577
|
e: "ew-resize",
|
|
16522
16578
|
n: "ns-resize",
|
|
@@ -16560,6 +16616,50 @@ var NUMERIC_LENGTH_STYLE_KEYS = /* @__PURE__ */ new Set([
|
|
|
16560
16616
|
"top",
|
|
16561
16617
|
"width"
|
|
16562
16618
|
]);
|
|
16619
|
+
var canvasCellStyleCache = /* @__PURE__ */ new Map();
|
|
16620
|
+
var canvasTextMeasureCache = /* @__PURE__ */ new Map();
|
|
16621
|
+
var canvasTextTruncateCache = /* @__PURE__ */ new Map();
|
|
16622
|
+
var canvasTextWrapCache = /* @__PURE__ */ new Map();
|
|
16623
|
+
var canvasPath2DCache = /* @__PURE__ */ new Map();
|
|
16624
|
+
function rememberBoundedCacheValue(cache, key, value, limit) {
|
|
16625
|
+
if (cache.size >= limit) {
|
|
16626
|
+
const oldestKey = cache.keys().next().value;
|
|
16627
|
+
if (oldestKey !== void 0) {
|
|
16628
|
+
cache.delete(oldestKey);
|
|
16629
|
+
}
|
|
16630
|
+
}
|
|
16631
|
+
cache.set(key, value);
|
|
16632
|
+
return value;
|
|
16633
|
+
}
|
|
16634
|
+
function roundCanvasCacheWidth(width) {
|
|
16635
|
+
return Math.round(width * 4) / 4;
|
|
16636
|
+
}
|
|
16637
|
+
function measureCanvasTextWidth(context, text) {
|
|
16638
|
+
if (text.length === 0) {
|
|
16639
|
+
return 0;
|
|
16640
|
+
}
|
|
16641
|
+
const cacheKey = `${context.font}\0${text}`;
|
|
16642
|
+
const cached = canvasTextMeasureCache.get(cacheKey);
|
|
16643
|
+
if (cached !== void 0) {
|
|
16644
|
+
return cached;
|
|
16645
|
+
}
|
|
16646
|
+
return rememberBoundedCacheValue(
|
|
16647
|
+
canvasTextMeasureCache,
|
|
16648
|
+
cacheKey,
|
|
16649
|
+
context.measureText(text).width,
|
|
16650
|
+
CANVAS_TEXT_MEASURE_CACHE_LIMIT
|
|
16651
|
+
);
|
|
16652
|
+
}
|
|
16653
|
+
function getCachedCanvasPath2D(path) {
|
|
16654
|
+
if (typeof Path2D === "undefined") {
|
|
16655
|
+
return null;
|
|
16656
|
+
}
|
|
16657
|
+
const cached = canvasPath2DCache.get(path);
|
|
16658
|
+
if (cached) {
|
|
16659
|
+
return cached;
|
|
16660
|
+
}
|
|
16661
|
+
return rememberBoundedCacheValue(canvasPath2DCache, path, new Path2D(path), CANVAS_PATH2D_CACHE_LIMIT);
|
|
16662
|
+
}
|
|
16563
16663
|
function scaleCssLengthExpression(value, scale) {
|
|
16564
16664
|
if (scale === 1) {
|
|
16565
16665
|
return value;
|
|
@@ -16740,7 +16840,6 @@ function strokeCanvasBorderSide(context, side, rect, border) {
|
|
|
16740
16840
|
const right = rect.left + rect.width;
|
|
16741
16841
|
const top = rect.top;
|
|
16742
16842
|
const bottom = rect.top + rect.height;
|
|
16743
|
-
context.save();
|
|
16744
16843
|
context.strokeStyle = border.color;
|
|
16745
16844
|
context.lineWidth = border.width;
|
|
16746
16845
|
applyCanvasBorderDash(context, border.style, border.width);
|
|
@@ -16770,13 +16869,22 @@ function strokeCanvasBorderSide(context, side, rect, border) {
|
|
|
16770
16869
|
} else {
|
|
16771
16870
|
strokeLine(0);
|
|
16772
16871
|
}
|
|
16773
|
-
context.
|
|
16872
|
+
context.setLineDash([]);
|
|
16873
|
+
context.lineCap = "butt";
|
|
16874
|
+
context.lineWidth = 1;
|
|
16774
16875
|
}
|
|
16775
16876
|
function truncateCanvasText(context, text, maxWidth) {
|
|
16776
16877
|
if (maxWidth <= 0 || text.length === 0) {
|
|
16777
16878
|
return "";
|
|
16778
16879
|
}
|
|
16779
|
-
|
|
16880
|
+
const roundedMaxWidth = roundCanvasCacheWidth(maxWidth);
|
|
16881
|
+
const cacheKey = `${context.font}\0${roundedMaxWidth}\0${text}`;
|
|
16882
|
+
const cached = canvasTextTruncateCache.get(cacheKey);
|
|
16883
|
+
if (cached !== void 0) {
|
|
16884
|
+
return cached;
|
|
16885
|
+
}
|
|
16886
|
+
if (measureCanvasTextWidth(context, text) <= maxWidth) {
|
|
16887
|
+
rememberBoundedCacheValue(canvasTextTruncateCache, cacheKey, text, CANVAS_TEXT_TRUNCATE_CACHE_LIMIT);
|
|
16780
16888
|
return text;
|
|
16781
16889
|
}
|
|
16782
16890
|
const ellipsis = "\u2026";
|
|
@@ -16785,13 +16893,18 @@ function truncateCanvasText(context, text, maxWidth) {
|
|
|
16785
16893
|
while (low < high) {
|
|
16786
16894
|
const mid = Math.ceil((low + high) / 2);
|
|
16787
16895
|
const candidate = `${text.slice(0, mid)}${ellipsis}`;
|
|
16788
|
-
if (context
|
|
16896
|
+
if (measureCanvasTextWidth(context, candidate) <= maxWidth) {
|
|
16789
16897
|
low = mid;
|
|
16790
16898
|
} else {
|
|
16791
16899
|
high = mid - 1;
|
|
16792
16900
|
}
|
|
16793
16901
|
}
|
|
16794
|
-
return
|
|
16902
|
+
return rememberBoundedCacheValue(
|
|
16903
|
+
canvasTextTruncateCache,
|
|
16904
|
+
cacheKey,
|
|
16905
|
+
low <= 0 ? ellipsis : `${text.slice(0, low)}${ellipsis}`,
|
|
16906
|
+
CANVAS_TEXT_TRUNCATE_CACHE_LIMIT
|
|
16907
|
+
);
|
|
16795
16908
|
}
|
|
16796
16909
|
function resolveCanvasFontSizePx(style, fallbackSize = 12) {
|
|
16797
16910
|
const rawFontSize = style.fontSize;
|
|
@@ -16850,7 +16963,7 @@ function resolveCanvasWrapIndex(context, text, maxWidth) {
|
|
|
16850
16963
|
while (low <= high) {
|
|
16851
16964
|
const mid = Math.floor((low + high) / 2);
|
|
16852
16965
|
const candidate = text.slice(0, mid);
|
|
16853
|
-
if (context
|
|
16966
|
+
if (measureCanvasTextWidth(context, candidate) <= maxWidth) {
|
|
16854
16967
|
best = mid;
|
|
16855
16968
|
low = mid + 1;
|
|
16856
16969
|
} else {
|
|
@@ -16867,6 +16980,12 @@ function wrapCanvasText(context, text, maxWidth) {
|
|
|
16867
16980
|
return text.replace(/\r\n?/g, "\n").split("\n");
|
|
16868
16981
|
}
|
|
16869
16982
|
const normalized = text.replace(/\r\n?/g, "\n");
|
|
16983
|
+
const roundedMaxWidth = roundCanvasCacheWidth(maxWidth);
|
|
16984
|
+
const cacheKey = `${context.font}\0${roundedMaxWidth}\0${normalized}`;
|
|
16985
|
+
const cached = canvasTextWrapCache.get(cacheKey);
|
|
16986
|
+
if (cached) {
|
|
16987
|
+
return cached;
|
|
16988
|
+
}
|
|
16870
16989
|
const paragraphs = normalized.split("\n");
|
|
16871
16990
|
const lines = [];
|
|
16872
16991
|
for (const paragraph of paragraphs) {
|
|
@@ -16876,7 +16995,7 @@ function wrapCanvasText(context, text, maxWidth) {
|
|
|
16876
16995
|
}
|
|
16877
16996
|
let remaining = paragraph;
|
|
16878
16997
|
while (remaining.length > 0) {
|
|
16879
|
-
if (context
|
|
16998
|
+
if (measureCanvasTextWidth(context, remaining) <= maxWidth) {
|
|
16880
16999
|
lines.push(remaining);
|
|
16881
17000
|
break;
|
|
16882
17001
|
}
|
|
@@ -16894,10 +17013,31 @@ function wrapCanvasText(context, text, maxWidth) {
|
|
|
16894
17013
|
remaining = remaining.slice(breakIndex).replace(/^\s+/g, "");
|
|
16895
17014
|
}
|
|
16896
17015
|
}
|
|
16897
|
-
return lines;
|
|
17016
|
+
return rememberBoundedCacheValue(canvasTextWrapCache, cacheKey, lines, CANVAS_TEXT_WRAP_CACHE_LIMIT);
|
|
16898
17017
|
}
|
|
16899
17018
|
function buildCanvasCellStyleCache(style) {
|
|
16900
|
-
|
|
17019
|
+
const cacheKey = [
|
|
17020
|
+
style.font,
|
|
17021
|
+
style.fontStyle,
|
|
17022
|
+
style.fontWeight,
|
|
17023
|
+
style.fontSize,
|
|
17024
|
+
style.fontFamily,
|
|
17025
|
+
style.borderTop,
|
|
17026
|
+
style.borderRight,
|
|
17027
|
+
style.borderBottom,
|
|
17028
|
+
style.borderLeft,
|
|
17029
|
+
style.padding,
|
|
17030
|
+
style.textAlign,
|
|
17031
|
+
style.color,
|
|
17032
|
+
style.textDecoration,
|
|
17033
|
+
style.textOverflow,
|
|
17034
|
+
style.whiteSpace
|
|
17035
|
+
].map((value) => value == null ? "" : String(value)).join("");
|
|
17036
|
+
const cached = canvasCellStyleCache.get(cacheKey);
|
|
17037
|
+
if (cached) {
|
|
17038
|
+
return cached;
|
|
17039
|
+
}
|
|
17040
|
+
return rememberBoundedCacheValue(canvasCellStyleCache, cacheKey, {
|
|
16901
17041
|
baseFont: resolveCanvasFont(style, 12),
|
|
16902
17042
|
bottomBorder: parseCanvasBorderDeclaration(style.borderBottom),
|
|
16903
17043
|
leftBorder: parseCanvasBorderDeclaration(style.borderLeft),
|
|
@@ -16909,7 +17049,7 @@ function buildCanvasCellStyleCache(style) {
|
|
|
16909
17049
|
textOverflowEllipsis: style.textOverflow === "ellipsis",
|
|
16910
17050
|
topBorder: parseCanvasBorderDeclaration(style.borderTop),
|
|
16911
17051
|
usesWrappedText: style.whiteSpace === "pre-wrap"
|
|
16912
|
-
};
|
|
17052
|
+
}, CANVAS_CELL_STYLE_CACHE_LIMIT);
|
|
16913
17053
|
}
|
|
16914
17054
|
function splitCssGradientArgs(value) {
|
|
16915
17055
|
const parts = [];
|
|
@@ -18418,6 +18558,44 @@ function resolveShapeVector(shape) {
|
|
|
18418
18558
|
}
|
|
18419
18559
|
return buildPresetShapePath(shape);
|
|
18420
18560
|
}
|
|
18561
|
+
function drawCanvasRoundedRect(context, left, top, width, height, radius) {
|
|
18562
|
+
const safeRadius = Math.max(0, Math.min(radius, width / 2, height / 2));
|
|
18563
|
+
context.beginPath();
|
|
18564
|
+
context.moveTo(left + safeRadius, top);
|
|
18565
|
+
context.lineTo(left + width - safeRadius, top);
|
|
18566
|
+
context.quadraticCurveTo(left + width, top, left + width, top + safeRadius);
|
|
18567
|
+
context.lineTo(left + width, top + height - safeRadius);
|
|
18568
|
+
context.quadraticCurveTo(left + width, top + height, left + width - safeRadius, top + height);
|
|
18569
|
+
context.lineTo(left + safeRadius, top + height);
|
|
18570
|
+
context.quadraticCurveTo(left, top + height, left, top + height - safeRadius);
|
|
18571
|
+
context.lineTo(left, top + safeRadius);
|
|
18572
|
+
context.quadraticCurveTo(left, top, left + safeRadius, top);
|
|
18573
|
+
context.closePath();
|
|
18574
|
+
}
|
|
18575
|
+
function applyCanvasShapeDash(context, dash, lineWidth) {
|
|
18576
|
+
if (!dash) {
|
|
18577
|
+
context.setLineDash([]);
|
|
18578
|
+
return;
|
|
18579
|
+
}
|
|
18580
|
+
const unit = Math.max(1, lineWidth);
|
|
18581
|
+
switch (dash) {
|
|
18582
|
+
case "dash":
|
|
18583
|
+
context.setLineDash([4 * unit, 3 * unit]);
|
|
18584
|
+
break;
|
|
18585
|
+
case "dashDot":
|
|
18586
|
+
context.setLineDash([4 * unit, 2 * unit, unit, 2 * unit]);
|
|
18587
|
+
break;
|
|
18588
|
+
case "dot":
|
|
18589
|
+
context.setLineDash([unit, 2 * unit]);
|
|
18590
|
+
break;
|
|
18591
|
+
case "lgDash":
|
|
18592
|
+
context.setLineDash([8 * unit, 3 * unit]);
|
|
18593
|
+
break;
|
|
18594
|
+
default:
|
|
18595
|
+
context.setLineDash([]);
|
|
18596
|
+
break;
|
|
18597
|
+
}
|
|
18598
|
+
}
|
|
18421
18599
|
function resolveShapeLineEndMarker(type, markerId, color, strokeWidth, rect, viewBox) {
|
|
18422
18600
|
if (type !== "triangle") {
|
|
18423
18601
|
return null;
|
|
@@ -19020,12 +19198,12 @@ function measureTextWidth(value, style) {
|
|
|
19020
19198
|
return value.length * 7;
|
|
19021
19199
|
}
|
|
19022
19200
|
textMeasureCanvas ??= document.createElement("canvas");
|
|
19023
|
-
const context = textMeasureCanvas.getContext("2d");
|
|
19201
|
+
const context = textMeasureCanvas.getContext("2d", { alpha: false });
|
|
19024
19202
|
if (!context) {
|
|
19025
19203
|
return value.length * 7;
|
|
19026
19204
|
}
|
|
19027
19205
|
context.font = buildCanvasFont(style);
|
|
19028
|
-
return context
|
|
19206
|
+
return measureCanvasTextWidth(context, value);
|
|
19029
19207
|
}
|
|
19030
19208
|
function measureWrappedTextHeight(value, style, widthPx) {
|
|
19031
19209
|
if (!value) {
|
|
@@ -19039,7 +19217,7 @@ function measureWrappedTextHeight(value, style, widthPx) {
|
|
|
19039
19217
|
return fallbackLineCount * lineHeight + padding.top + padding.bottom;
|
|
19040
19218
|
}
|
|
19041
19219
|
textMeasureCanvas ??= document.createElement("canvas");
|
|
19042
|
-
const context = textMeasureCanvas.getContext("2d");
|
|
19220
|
+
const context = textMeasureCanvas.getContext("2d", { alpha: false });
|
|
19043
19221
|
if (!context) {
|
|
19044
19222
|
return fallbackLineCount * lineHeight + padding.top + padding.bottom;
|
|
19045
19223
|
}
|
|
@@ -20137,7 +20315,7 @@ function blitCanvasWithScrollDelta(canvas, context, bufferCanvas, dpr, width, he
|
|
|
20137
20315
|
if (bufferCanvas.height !== deviceHeight) {
|
|
20138
20316
|
bufferCanvas.height = deviceHeight;
|
|
20139
20317
|
}
|
|
20140
|
-
const bufferContext = bufferCanvas.getContext("2d");
|
|
20318
|
+
const bufferContext = bufferCanvas.getContext("2d", { alpha: false });
|
|
20141
20319
|
if (!bufferContext) {
|
|
20142
20320
|
return null;
|
|
20143
20321
|
}
|
|
@@ -20994,6 +21172,8 @@ function XlsxGrid({
|
|
|
20994
21172
|
selectionHeaderColor,
|
|
20995
21173
|
showImages = true
|
|
20996
21174
|
}) {
|
|
21175
|
+
const xlsxCanvasProfileTarget = typeof window !== "undefined" ? window.__xlsxCanvasProfile : void 0;
|
|
21176
|
+
const xlsxGridRenderStart = xlsxCanvasProfileTarget ? performance.now() : 0;
|
|
20997
21177
|
const {
|
|
20998
21178
|
activeCell,
|
|
20999
21179
|
activeSheet,
|
|
@@ -21077,6 +21257,11 @@ function XlsxGrid({
|
|
|
21077
21257
|
const leftFrozenHeaderCanvasRef = React4.useRef(null);
|
|
21078
21258
|
const leftScrollHeaderCanvasRef = React4.useRef(null);
|
|
21079
21259
|
const cornerHeaderCanvasRef = React4.useRef(null);
|
|
21260
|
+
const canvasScrollOverlayContentRef = React4.useRef(null);
|
|
21261
|
+
const canvasTopOverlayContentRef = React4.useRef(null);
|
|
21262
|
+
const canvasLeftOverlayContentRef = React4.useRef(null);
|
|
21263
|
+
const canvasCornerOverlayContentRef = React4.useRef(null);
|
|
21264
|
+
const canvasImageCacheRef = React4.useRef(/* @__PURE__ */ new Map());
|
|
21080
21265
|
const selectionOverlayRef = React4.useRef(null);
|
|
21081
21266
|
const activeValidationOverlayRef = React4.useRef(null);
|
|
21082
21267
|
const fillHandleRef = React4.useRef(null);
|
|
@@ -21105,6 +21290,7 @@ function XlsxGrid({
|
|
|
21105
21290
|
const pendingLiveZoomCommitRef = React4.useRef(null);
|
|
21106
21291
|
const touchPinchStateRef = React4.useRef(null);
|
|
21107
21292
|
const safariPinchStartZoomRef = React4.useRef(null);
|
|
21293
|
+
const canvasTransformStyleCacheRef = React4.useRef(/* @__PURE__ */ new WeakMap());
|
|
21108
21294
|
const displayedSelectionRef = React4.useRef(null);
|
|
21109
21295
|
const firstVisibleColRef = React4.useRef(void 0);
|
|
21110
21296
|
const lastVisibleColRef = React4.useRef(void 0);
|
|
@@ -21130,12 +21316,19 @@ function XlsxGrid({
|
|
|
21130
21316
|
const [fillPreviewRange, setFillPreviewRange] = React4.useState(null);
|
|
21131
21317
|
const [chartPreviewRect, setChartPreviewRect] = React4.useState(null);
|
|
21132
21318
|
const [liveGestureZoom, setLiveGestureZoom] = React4.useState(null);
|
|
21319
|
+
const [canvasImageLoadVersion, setCanvasImageLoadVersion] = React4.useState(0);
|
|
21133
21320
|
const liveDrawingViewportRef = React4.useRef({
|
|
21134
21321
|
height: 0,
|
|
21135
21322
|
left: 0,
|
|
21136
21323
|
top: 0,
|
|
21137
21324
|
width: 0
|
|
21138
21325
|
});
|
|
21326
|
+
const canvasLayoutMetricsRef = React4.useRef({
|
|
21327
|
+
displayHeaderHeight: HEADER_HEIGHT,
|
|
21328
|
+
displayRowHeaderWidth: ROW_HEADER_WIDTH,
|
|
21329
|
+
frozenPaneBottom: HEADER_HEIGHT,
|
|
21330
|
+
frozenPaneRight: ROW_HEADER_WIDTH
|
|
21331
|
+
});
|
|
21139
21332
|
const paintedDrawingViewportRef = React4.useRef({
|
|
21140
21333
|
height: 0,
|
|
21141
21334
|
left: 0,
|
|
@@ -21245,6 +21438,12 @@ function XlsxGrid({
|
|
|
21245
21438
|
const applyCanvasViewportCompensation = React4.useCallback((liveViewport) => {
|
|
21246
21439
|
const nextLiveViewport = liveViewport ?? liveDrawingViewportRef.current;
|
|
21247
21440
|
const paintedViewport = paintedDrawingViewportRef.current;
|
|
21441
|
+
const {
|
|
21442
|
+
displayHeaderHeight: liveDisplayHeaderHeight,
|
|
21443
|
+
displayRowHeaderWidth: liveDisplayRowHeaderWidth,
|
|
21444
|
+
frozenPaneBottom: liveFrozenPaneBottom,
|
|
21445
|
+
frozenPaneRight: liveFrozenPaneRight
|
|
21446
|
+
} = canvasLayoutMetricsRef.current;
|
|
21248
21447
|
const currentLiveGestureZoom = liveGestureZoomRef.current;
|
|
21249
21448
|
const isLiveZooming2 = currentLiveGestureZoom !== null && zoomScale === currentLiveGestureZoom.baseZoomScale;
|
|
21250
21449
|
const liveZoomScale2 = isLiveZooming2 ? Math.max(0.1, currentLiveGestureZoom.targetZoomScale / currentLiveGestureZoom.baseZoomScale) : 1;
|
|
@@ -21252,12 +21451,41 @@ function XlsxGrid({
|
|
|
21252
21451
|
const scrollDeltaY = paintedViewport.top - nextLiveViewport.top;
|
|
21253
21452
|
const liveZoomTranslateX2 = isLiveZooming2 ? currentLiveGestureZoom.anchor.x * (1 - liveZoomScale2) : 0;
|
|
21254
21453
|
const liveZoomTranslateY2 = isLiveZooming2 ? currentLiveGestureZoom.anchor.y * (1 - liveZoomScale2) : 0;
|
|
21255
|
-
const
|
|
21256
|
-
if (!
|
|
21454
|
+
const applyElementTransform = (element, transform, willChange, transformOrigin = null) => {
|
|
21455
|
+
if (!element) {
|
|
21257
21456
|
return;
|
|
21258
21457
|
}
|
|
21259
|
-
|
|
21260
|
-
|
|
21458
|
+
const cached = canvasTransformStyleCacheRef.current.get(element);
|
|
21459
|
+
if (cached?.transform !== transform || element.style.transform !== transform) {
|
|
21460
|
+
element.style.transform = transform;
|
|
21461
|
+
}
|
|
21462
|
+
if (cached?.willChange !== willChange || element.style.willChange !== willChange) {
|
|
21463
|
+
element.style.willChange = willChange;
|
|
21464
|
+
}
|
|
21465
|
+
if (transformOrigin !== null && (cached?.transformOrigin !== transformOrigin || element.style.transformOrigin !== transformOrigin)) {
|
|
21466
|
+
element.style.transformOrigin = transformOrigin;
|
|
21467
|
+
}
|
|
21468
|
+
canvasTransformStyleCacheRef.current.set(element, {
|
|
21469
|
+
transform,
|
|
21470
|
+
transformOrigin,
|
|
21471
|
+
willChange
|
|
21472
|
+
});
|
|
21473
|
+
};
|
|
21474
|
+
const applyCanvasTransform = (canvas, translateX, translateY) => {
|
|
21475
|
+
const shouldTransform = translateX !== 0 || translateY !== 0 || liveZoomScale2 !== 1;
|
|
21476
|
+
applyElementTransform(
|
|
21477
|
+
canvas,
|
|
21478
|
+
shouldTransform ? `translate3d(${translateX}px, ${translateY}px, 0) scale(${liveZoomScale2})` : "",
|
|
21479
|
+
shouldTransform ? "transform" : ""
|
|
21480
|
+
);
|
|
21481
|
+
};
|
|
21482
|
+
const applyOverlayTransform = (element, translateX, translateY) => {
|
|
21483
|
+
applyElementTransform(
|
|
21484
|
+
element,
|
|
21485
|
+
liveZoomScale2 !== 1 ? `translate3d(${translateX + liveZoomTranslateX2}px, ${translateY + liveZoomTranslateY2}px, 0) scale(${liveZoomScale2})` : `translate3d(${translateX}px, ${translateY}px, 0)`,
|
|
21486
|
+
"transform",
|
|
21487
|
+
"0 0"
|
|
21488
|
+
);
|
|
21261
21489
|
};
|
|
21262
21490
|
applyCanvasTransform(
|
|
21263
21491
|
scrollBodyCanvasRef.current,
|
|
@@ -21304,6 +21532,26 @@ function XlsxGrid({
|
|
|
21304
21532
|
liveZoomTranslateX2,
|
|
21305
21533
|
liveZoomTranslateY2
|
|
21306
21534
|
);
|
|
21535
|
+
applyOverlayTransform(
|
|
21536
|
+
canvasScrollOverlayContentRef.current,
|
|
21537
|
+
-nextLiveViewport.left - liveFrozenPaneRight,
|
|
21538
|
+
-nextLiveViewport.top - liveFrozenPaneBottom
|
|
21539
|
+
);
|
|
21540
|
+
applyOverlayTransform(
|
|
21541
|
+
canvasTopOverlayContentRef.current,
|
|
21542
|
+
-nextLiveViewport.left - liveFrozenPaneRight,
|
|
21543
|
+
-liveDisplayHeaderHeight
|
|
21544
|
+
);
|
|
21545
|
+
applyOverlayTransform(
|
|
21546
|
+
canvasLeftOverlayContentRef.current,
|
|
21547
|
+
-liveDisplayRowHeaderWidth,
|
|
21548
|
+
-nextLiveViewport.top - liveFrozenPaneBottom
|
|
21549
|
+
);
|
|
21550
|
+
applyOverlayTransform(
|
|
21551
|
+
canvasCornerOverlayContentRef.current,
|
|
21552
|
+
-liveDisplayRowHeaderWidth,
|
|
21553
|
+
-liveDisplayHeaderHeight
|
|
21554
|
+
);
|
|
21307
21555
|
}, [zoomScale]);
|
|
21308
21556
|
const updateLiveGestureZoomState = React4.useCallback((nextState) => {
|
|
21309
21557
|
const resolvedState = typeof nextState === "function" ? nextState(liveGestureZoomRef.current) : nextState;
|
|
@@ -21406,6 +21654,11 @@ function XlsxGrid({
|
|
|
21406
21654
|
if (matchesLiveViewport && matchesStateViewport) {
|
|
21407
21655
|
return;
|
|
21408
21656
|
}
|
|
21657
|
+
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);
|
|
21658
|
+
if (!shouldCommitDeferredViewport) {
|
|
21659
|
+
pendingDrawingViewportRef.current = null;
|
|
21660
|
+
return;
|
|
21661
|
+
}
|
|
21409
21662
|
pendingDrawingViewportRef.current = nextViewport;
|
|
21410
21663
|
if (drawingViewportFrameRef.current !== null) {
|
|
21411
21664
|
return;
|
|
@@ -21693,6 +21946,12 @@ function XlsxGrid({
|
|
|
21693
21946
|
) : displayRowHeaderWidth,
|
|
21694
21947
|
[displayActualColWidths, displayDefaultColWidth, displayRowHeaderWidth, frozenCols, stickyLeftByCol]
|
|
21695
21948
|
);
|
|
21949
|
+
canvasLayoutMetricsRef.current = {
|
|
21950
|
+
displayHeaderHeight,
|
|
21951
|
+
displayRowHeaderWidth,
|
|
21952
|
+
frozenPaneBottom,
|
|
21953
|
+
frozenPaneRight
|
|
21954
|
+
};
|
|
21696
21955
|
const rowPrefixSumsRef = React4.useRef(rowPrefixSums);
|
|
21697
21956
|
const colPrefixSumsRef = React4.useRef(colPrefixSums);
|
|
21698
21957
|
const firstVisibleRow = visibleRows[0];
|
|
@@ -21744,6 +22003,7 @@ function XlsxGrid({
|
|
|
21744
22003
|
}, [charts, images, shapes]);
|
|
21745
22004
|
const shouldVirtualizeRows = visibleRows.length > 0;
|
|
21746
22005
|
const shouldVirtualizeCols = visibleCols.length > 0 && frozenCols.length === 0;
|
|
22006
|
+
const shouldUseDomVirtualizer = !experimentalCanvas;
|
|
21747
22007
|
const getScrollElement = React4.useCallback(() => scrollRef.current, []);
|
|
21748
22008
|
const estimateRowSize = React4.useCallback(
|
|
21749
22009
|
(index) => displayEffectiveRowHeights[index] ?? displayDefaultRowHeight,
|
|
@@ -21757,6 +22017,7 @@ function XlsxGrid({
|
|
|
21757
22017
|
const getColItemKey = React4.useCallback((index) => visibleCols[index] ?? index, [visibleCols]);
|
|
21758
22018
|
const rowVirtualizer = (0, import_react_virtual.useVirtualizer)({
|
|
21759
22019
|
count: visibleRows.length,
|
|
22020
|
+
enabled: shouldUseDomVirtualizer,
|
|
21760
22021
|
estimateSize: estimateRowSize,
|
|
21761
22022
|
getScrollElement,
|
|
21762
22023
|
getItemKey: getRowItemKey,
|
|
@@ -21764,14 +22025,15 @@ function XlsxGrid({
|
|
|
21764
22025
|
});
|
|
21765
22026
|
const colVirtualizer = (0, import_react_virtual.useVirtualizer)({
|
|
21766
22027
|
count: visibleCols.length,
|
|
22028
|
+
enabled: shouldUseDomVirtualizer,
|
|
21767
22029
|
estimateSize: estimateColSize,
|
|
21768
22030
|
getScrollElement,
|
|
21769
22031
|
getItemKey: getColItemKey,
|
|
21770
22032
|
horizontal: true,
|
|
21771
22033
|
overscan: 6
|
|
21772
22034
|
});
|
|
21773
|
-
const currentRowVirtualItems = rowVirtualizer.getVirtualItems();
|
|
21774
|
-
const currentColVirtualItems = colVirtualizer.getVirtualItems();
|
|
22035
|
+
const currentRowVirtualItems = shouldUseDomVirtualizer ? rowVirtualizer.getVirtualItems() : EMPTY_VIRTUAL_ITEMS;
|
|
22036
|
+
const currentColVirtualItems = shouldUseDomVirtualizer ? colVirtualizer.getVirtualItems() : EMPTY_VIRTUAL_ITEMS;
|
|
21775
22037
|
const frozenRowVirtualIndices = React4.useMemo(
|
|
21776
22038
|
() => frozenRows.map((row) => rowIndexByActual.get(row)).filter((index) => index !== void 0),
|
|
21777
22039
|
[frozenRows, rowIndexByActual]
|
|
@@ -22007,10 +22269,12 @@ function XlsxGrid({
|
|
|
22007
22269
|
scroller.scrollTop = scroller.scrollTop / previousZoomFactor * zoomFactor;
|
|
22008
22270
|
}
|
|
22009
22271
|
previousZoomFactorRef.current = zoomFactor;
|
|
22010
|
-
|
|
22011
|
-
|
|
22272
|
+
if (shouldUseDomVirtualizer) {
|
|
22273
|
+
rowVirtualizer.measure();
|
|
22274
|
+
colVirtualizer.measure();
|
|
22275
|
+
}
|
|
22012
22276
|
syncDrawingViewport(scroller, { immediate: true });
|
|
22013
|
-
}, [syncDrawingViewport, zoomFactor]);
|
|
22277
|
+
}, [shouldUseDomVirtualizer, syncDrawingViewport, zoomFactor]);
|
|
22014
22278
|
React4.useLayoutEffect(() => {
|
|
22015
22279
|
syncDrawingViewport(scrollRef.current, { immediate: true });
|
|
22016
22280
|
}, [activeSheet, activeTabIndex, displayColLimit, displayRowLimit, syncDrawingViewport, zoomFactor]);
|
|
@@ -22106,7 +22370,7 @@ function XlsxGrid({
|
|
|
22106
22370
|
const initialUsedCol = resolveFirstUsedVisibleIndex(visibleCols, activeSheet?.minUsedCol ?? -1);
|
|
22107
22371
|
const initialScrollTop = initialUsedRow > 0 ? sumPrefixRange(actualRowPrefixSums, 0, initialUsedRow - 1) : 0;
|
|
22108
22372
|
const initialScrollLeft = initialUsedCol > 0 ? sumPrefixRange(actualColPrefixSums, 0, initialUsedCol - 1) : 0;
|
|
22109
|
-
if (shouldVirtualizeRows) {
|
|
22373
|
+
if (shouldUseDomVirtualizer && shouldVirtualizeRows) {
|
|
22110
22374
|
rowVirtualizer.scrollToOffset(initialScrollTop);
|
|
22111
22375
|
} else if (scrollRef.current) {
|
|
22112
22376
|
scrollRef.current.scrollTop = initialScrollTop;
|
|
@@ -22114,7 +22378,7 @@ function XlsxGrid({
|
|
|
22114
22378
|
if (scrollRef.current) {
|
|
22115
22379
|
scrollRef.current.scrollLeft = initialScrollLeft;
|
|
22116
22380
|
}
|
|
22117
|
-
if (shouldVirtualizeCols && frozenCols.length === 0) {
|
|
22381
|
+
if (shouldUseDomVirtualizer && shouldVirtualizeCols && frozenCols.length === 0) {
|
|
22118
22382
|
colVirtualizer.scrollToOffset(initialScrollLeft);
|
|
22119
22383
|
}
|
|
22120
22384
|
if (scrollRef.current) {
|
|
@@ -22135,6 +22399,7 @@ function XlsxGrid({
|
|
|
22135
22399
|
isWorkerBacked,
|
|
22136
22400
|
shouldVirtualizeCols,
|
|
22137
22401
|
shouldVirtualizeRows,
|
|
22402
|
+
shouldUseDomVirtualizer,
|
|
22138
22403
|
syncDrawingViewport,
|
|
22139
22404
|
rowVirtualizer,
|
|
22140
22405
|
visibleCols,
|
|
@@ -22154,24 +22419,40 @@ function XlsxGrid({
|
|
|
22154
22419
|
setPendingNavigation(null);
|
|
22155
22420
|
}, [activeSheetIndex, pendingNavigation, selectCell]);
|
|
22156
22421
|
React4.useEffect(() => {
|
|
22157
|
-
if (shouldVirtualizeRows) {
|
|
22422
|
+
if (shouldUseDomVirtualizer && shouldVirtualizeRows) {
|
|
22158
22423
|
rowVirtualizer.measure();
|
|
22159
22424
|
}
|
|
22160
|
-
if (shouldVirtualizeCols) {
|
|
22425
|
+
if (shouldUseDomVirtualizer && shouldVirtualizeCols) {
|
|
22161
22426
|
colVirtualizer.measure();
|
|
22162
22427
|
}
|
|
22163
|
-
}, [
|
|
22428
|
+
}, [
|
|
22429
|
+
activeSheetIndex,
|
|
22430
|
+
revision,
|
|
22431
|
+
shouldUseDomVirtualizer,
|
|
22432
|
+
shouldVirtualizeCols,
|
|
22433
|
+
shouldVirtualizeRows,
|
|
22434
|
+
visibleCols.length,
|
|
22435
|
+
visibleRows.length
|
|
22436
|
+
]);
|
|
22164
22437
|
const handleScrollerScroll = React4.useCallback((event) => {
|
|
22165
22438
|
const currentScroller = event.currentTarget;
|
|
22166
22439
|
cachedScrollerRectRef.current = null;
|
|
22167
|
-
|
|
22440
|
+
const paintedViewport = paintedDrawingViewportRef.current;
|
|
22441
|
+
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;
|
|
22442
|
+
syncDrawingViewport(currentScroller, { immediate: shouldSyncDrawingViewportImmediately });
|
|
22168
22443
|
if (currentScroller.scrollHeight - (currentScroller.scrollTop + currentScroller.clientHeight) < OPEN_GRID_VERTICAL_EDGE_PX) {
|
|
22169
|
-
setDisplayRowLimit((current) =>
|
|
22444
|
+
setDisplayRowLimit((current) => {
|
|
22445
|
+
const nextLimit = current + OPEN_GRID_ROW_GROWTH;
|
|
22446
|
+
return readOnly && current < maxRowDisplayLimit ? Math.min(maxRowDisplayLimit, nextLimit) : nextLimit;
|
|
22447
|
+
});
|
|
22170
22448
|
}
|
|
22171
22449
|
if (currentScroller.scrollWidth - (currentScroller.scrollLeft + currentScroller.clientWidth) < OPEN_GRID_HORIZONTAL_EDGE_PX) {
|
|
22172
|
-
setDisplayColLimit((current) =>
|
|
22450
|
+
setDisplayColLimit((current) => {
|
|
22451
|
+
const nextLimit = current + OPEN_GRID_COL_GROWTH;
|
|
22452
|
+
return readOnly && current < maxColDisplayLimit ? Math.min(maxColDisplayLimit, nextLimit) : nextLimit;
|
|
22453
|
+
});
|
|
22173
22454
|
}
|
|
22174
|
-
}, [syncDrawingViewport]);
|
|
22455
|
+
}, [maxColDisplayLimit, maxRowDisplayLimit, readOnly, syncDrawingViewport]);
|
|
22175
22456
|
React4.useEffect(() => {
|
|
22176
22457
|
const scroller = scrollRef.current;
|
|
22177
22458
|
if (!scroller || !enableGestureZoom) {
|
|
@@ -23077,14 +23358,14 @@ function XlsxGrid({
|
|
|
23077
23358
|
},
|
|
23078
23359
|
left: {
|
|
23079
23360
|
cols: frozenColItems,
|
|
23080
|
-
rows:
|
|
23361
|
+
rows: scrollRowItems
|
|
23081
23362
|
},
|
|
23082
23363
|
scroll: {
|
|
23083
|
-
cols:
|
|
23084
|
-
rows:
|
|
23364
|
+
cols: scrollColItems,
|
|
23365
|
+
rows: scrollRowItems
|
|
23085
23366
|
},
|
|
23086
23367
|
top: {
|
|
23087
|
-
cols:
|
|
23368
|
+
cols: scrollColItems,
|
|
23088
23369
|
rows: frozenRowItems
|
|
23089
23370
|
}
|
|
23090
23371
|
};
|
|
@@ -23218,6 +23499,51 @@ function XlsxGrid({
|
|
|
23218
23499
|
visibleRows
|
|
23219
23500
|
]
|
|
23220
23501
|
);
|
|
23502
|
+
const shouldBakeCanvasStaticDrawings = Boolean(experimentalCanvas && readOnly && showImages);
|
|
23503
|
+
const shouldBakeCanvasImages = Boolean(shouldBakeCanvasStaticDrawings && !renderImage && !renderImageSelection);
|
|
23504
|
+
const bakedShapeRects = React4.useMemo(
|
|
23505
|
+
() => shouldBakeCanvasStaticDrawings ? shapeRects.filter(({ shape }) => !shape.hyperlink) : [],
|
|
23506
|
+
[shapeRects, shouldBakeCanvasStaticDrawings]
|
|
23507
|
+
);
|
|
23508
|
+
const domShapeRects = React4.useMemo(
|
|
23509
|
+
() => shouldBakeCanvasStaticDrawings ? shapeRects.filter(({ shape }) => shape.hyperlink) : shapeRects,
|
|
23510
|
+
[shapeRects, shouldBakeCanvasStaticDrawings]
|
|
23511
|
+
);
|
|
23512
|
+
const bakedFormControlRects = React4.useMemo(
|
|
23513
|
+
() => shouldBakeCanvasStaticDrawings ? formControlRects : [],
|
|
23514
|
+
[formControlRects, shouldBakeCanvasStaticDrawings]
|
|
23515
|
+
);
|
|
23516
|
+
const domFormControlRects = React4.useMemo(
|
|
23517
|
+
() => shouldBakeCanvasStaticDrawings ? [] : formControlRects,
|
|
23518
|
+
[formControlRects, shouldBakeCanvasStaticDrawings]
|
|
23519
|
+
);
|
|
23520
|
+
const bakedImageRects = React4.useMemo(
|
|
23521
|
+
() => shouldBakeCanvasImages ? imageRects.filter(({ image }) => !image.hyperlink && selectedImageId !== image.id) : [],
|
|
23522
|
+
[imageRects, selectedImageId, shouldBakeCanvasImages]
|
|
23523
|
+
);
|
|
23524
|
+
const domImageRects = React4.useMemo(
|
|
23525
|
+
() => shouldBakeCanvasImages ? imageRects.filter(({ image }) => image.hyperlink || selectedImageId === image.id) : imageRects,
|
|
23526
|
+
[imageRects, selectedImageId, shouldBakeCanvasImages]
|
|
23527
|
+
);
|
|
23528
|
+
const hasCanvasDomDrawingOverlays = Boolean(
|
|
23529
|
+
showImages && (chartRects.length > 0 || domShapeRects.length > 0 || domFormControlRects.length > 0 || domImageRects.length > 0)
|
|
23530
|
+
);
|
|
23531
|
+
const bakedCanvasDrawingSignature = React4.useMemo(() => {
|
|
23532
|
+
if (!shouldBakeCanvasStaticDrawings) {
|
|
23533
|
+
return "";
|
|
23534
|
+
}
|
|
23535
|
+
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("|");
|
|
23536
|
+
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("|");
|
|
23537
|
+
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("|");
|
|
23538
|
+
return `${revision}:${canvasImageLoadVersion}:${shapeSignature}:${controlSignature}:${imageSignature}`;
|
|
23539
|
+
}, [
|
|
23540
|
+
bakedFormControlRects,
|
|
23541
|
+
bakedImageRects,
|
|
23542
|
+
bakedShapeRects,
|
|
23543
|
+
canvasImageLoadVersion,
|
|
23544
|
+
revision,
|
|
23545
|
+
shouldBakeCanvasStaticDrawings
|
|
23546
|
+
]);
|
|
23221
23547
|
const resolveMountedCellOverlayRect = React4.useCallback((element) => {
|
|
23222
23548
|
const wrapper = wrapperRef.current;
|
|
23223
23549
|
if (!wrapper) {
|
|
@@ -24086,6 +24412,24 @@ function XlsxGrid({
|
|
|
24086
24412
|
rowPrefixSums,
|
|
24087
24413
|
stickyTopByRow
|
|
24088
24414
|
]);
|
|
24415
|
+
const scrollBodyViewportWidth = Math.max(0, drawingViewport.width - frozenPaneRight);
|
|
24416
|
+
const scrollBodyViewportHeight = Math.max(0, drawingViewport.height - frozenPaneBottom);
|
|
24417
|
+
const canvasScrollBufferX = Math.min(CANVAS_SCROLL_BUFFER_PX, scrollBodyViewportWidth);
|
|
24418
|
+
const canvasScrollBufferY = Math.min(CANVAS_SCROLL_BUFFER_PX, scrollBodyViewportHeight);
|
|
24419
|
+
const scrollBodyCanvasLeft = frozenPaneRight - canvasScrollBufferX;
|
|
24420
|
+
const scrollBodyCanvasTop = frozenPaneBottom - canvasScrollBufferY;
|
|
24421
|
+
const scrollBodyCanvasWidth = scrollBodyViewportWidth + canvasScrollBufferX * 2;
|
|
24422
|
+
const scrollBodyCanvasHeight = scrollBodyViewportHeight + canvasScrollBufferY * 2;
|
|
24423
|
+
const topBodyCanvasWidth = scrollBodyCanvasWidth;
|
|
24424
|
+
const topBodyCanvasHeight = Math.max(0, frozenPaneBottom - displayHeaderHeight);
|
|
24425
|
+
const leftBodyCanvasWidth = Math.max(0, frozenPaneRight - displayRowHeaderWidth);
|
|
24426
|
+
const leftBodyCanvasHeight = scrollBodyCanvasHeight;
|
|
24427
|
+
const cornerBodyCanvasWidth = leftBodyCanvasWidth;
|
|
24428
|
+
const cornerBodyCanvasHeight = topBodyCanvasHeight;
|
|
24429
|
+
const topFrozenHeaderCanvasWidth = leftBodyCanvasWidth;
|
|
24430
|
+
const topScrollHeaderCanvasWidth = scrollBodyCanvasWidth;
|
|
24431
|
+
const leftFrozenHeaderCanvasHeight = topBodyCanvasHeight;
|
|
24432
|
+
const leftScrollHeaderCanvasHeight = scrollBodyCanvasHeight;
|
|
24089
24433
|
const canvasColumnHeaderCells = React4.useMemo(
|
|
24090
24434
|
() => canvasVisibleColItems.flatMap((column) => {
|
|
24091
24435
|
const rect = resolveCanvasColumnHeaderRect(column.actualCol);
|
|
@@ -24098,7 +24442,7 @@ function XlsxGrid({
|
|
|
24098
24442
|
height: displayHeaderHeight,
|
|
24099
24443
|
isFrozen,
|
|
24100
24444
|
left: rect.left,
|
|
24101
|
-
localLeft: rect.left - (isFrozen ? displayRowHeaderWidth :
|
|
24445
|
+
localLeft: rect.left - (isFrozen ? displayRowHeaderWidth : scrollBodyCanvasLeft),
|
|
24102
24446
|
width: rect.width
|
|
24103
24447
|
}];
|
|
24104
24448
|
}),
|
|
@@ -24106,8 +24450,8 @@ function XlsxGrid({
|
|
|
24106
24450
|
canvasVisibleColItems,
|
|
24107
24451
|
displayHeaderHeight,
|
|
24108
24452
|
displayRowHeaderWidth,
|
|
24109
|
-
frozenPaneRight,
|
|
24110
24453
|
resolveCanvasColumnHeaderRect,
|
|
24454
|
+
scrollBodyCanvasLeft,
|
|
24111
24455
|
stickyLeftByCol
|
|
24112
24456
|
]
|
|
24113
24457
|
);
|
|
@@ -24122,15 +24466,15 @@ function XlsxGrid({
|
|
|
24122
24466
|
actualRow: row.actualRow,
|
|
24123
24467
|
height: rect.height,
|
|
24124
24468
|
isFrozen,
|
|
24125
|
-
localTop: rect.top - (isFrozen ? displayHeaderHeight :
|
|
24469
|
+
localTop: rect.top - (isFrozen ? displayHeaderHeight : scrollBodyCanvasTop),
|
|
24126
24470
|
top: rect.top
|
|
24127
24471
|
}];
|
|
24128
24472
|
}),
|
|
24129
24473
|
[
|
|
24130
24474
|
canvasVisibleRowItems,
|
|
24131
24475
|
displayHeaderHeight,
|
|
24132
|
-
frozenPaneBottom,
|
|
24133
24476
|
resolveCanvasRowHeaderRect,
|
|
24477
|
+
scrollBodyCanvasTop,
|
|
24134
24478
|
stickyTopByRow
|
|
24135
24479
|
]
|
|
24136
24480
|
);
|
|
@@ -24397,10 +24741,46 @@ function XlsxGrid({
|
|
|
24397
24741
|
rowPrefixSums,
|
|
24398
24742
|
startCellSelection
|
|
24399
24743
|
]);
|
|
24744
|
+
const getCanvasImage = React4.useCallback((image) => {
|
|
24745
|
+
if (typeof Image === "undefined") {
|
|
24746
|
+
return null;
|
|
24747
|
+
}
|
|
24748
|
+
const cacheKey = image.id;
|
|
24749
|
+
const cached = canvasImageCacheRef.current.get(cacheKey);
|
|
24750
|
+
if (cached && cached.src === image.src) {
|
|
24751
|
+
return cached.loaded && !cached.failed ? cached.image : null;
|
|
24752
|
+
}
|
|
24753
|
+
const imageElement = new Image();
|
|
24754
|
+
const entry = {
|
|
24755
|
+
failed: false,
|
|
24756
|
+
image: imageElement,
|
|
24757
|
+
loaded: false,
|
|
24758
|
+
src: image.src
|
|
24759
|
+
};
|
|
24760
|
+
canvasImageCacheRef.current.set(cacheKey, entry);
|
|
24761
|
+
imageElement.onload = () => {
|
|
24762
|
+
entry.loaded = true;
|
|
24763
|
+
setCanvasImageLoadVersion((version) => version + 1);
|
|
24764
|
+
};
|
|
24765
|
+
imageElement.onerror = () => {
|
|
24766
|
+
entry.failed = true;
|
|
24767
|
+
setCanvasImageLoadVersion((version) => version + 1);
|
|
24768
|
+
};
|
|
24769
|
+
imageElement.src = image.src;
|
|
24770
|
+
return null;
|
|
24771
|
+
}, []);
|
|
24400
24772
|
React4.useLayoutEffect(() => {
|
|
24401
24773
|
if (!experimentalCanvas) {
|
|
24402
24774
|
return;
|
|
24403
24775
|
}
|
|
24776
|
+
const canvasProfileTarget = typeof window !== "undefined" ? window.__xlsxCanvasProfile : void 0;
|
|
24777
|
+
const canvasProfileStart = canvasProfileTarget ? performance.now() : 0;
|
|
24778
|
+
let canvasProfileBodyStart = 0;
|
|
24779
|
+
let canvasProfileBodyMs = 0;
|
|
24780
|
+
let canvasProfileCulledCells = 0;
|
|
24781
|
+
let canvasProfileDirtyRects = 0;
|
|
24782
|
+
let canvasProfileLookedUpCells = 0;
|
|
24783
|
+
let canvasProfilePaintedCells = 0;
|
|
24404
24784
|
const dpr = typeof window === "undefined" ? 1 : Math.max(1, window.devicePixelRatio || 1);
|
|
24405
24785
|
function configureCanvas(canvas, width, height, options) {
|
|
24406
24786
|
if (!canvas) {
|
|
@@ -24420,7 +24800,7 @@ function XlsxGrid({
|
|
|
24420
24800
|
if (canvas.style.height !== `${height}px`) {
|
|
24421
24801
|
canvas.style.height = `${height}px`;
|
|
24422
24802
|
}
|
|
24423
|
-
const context = canvas.getContext("2d");
|
|
24803
|
+
const context = canvas.getContext("2d", { alpha: false });
|
|
24424
24804
|
if (!context) {
|
|
24425
24805
|
return null;
|
|
24426
24806
|
}
|
|
@@ -24439,6 +24819,7 @@ function XlsxGrid({
|
|
|
24439
24819
|
const rangeSignature = buildRangeSignature(normalizedVisibleRange);
|
|
24440
24820
|
const nextBodyCanvasSignature = {
|
|
24441
24821
|
activeSheet: activeSheet ?? null,
|
|
24822
|
+
bakedDrawingSignature: bakedCanvasDrawingSignature,
|
|
24442
24823
|
bodyHeight,
|
|
24443
24824
|
bodyWidth,
|
|
24444
24825
|
colSignature: buildRenderedAxisSignature(canvasVisibleColItems, (item) => item.index),
|
|
@@ -24466,10 +24847,10 @@ function XlsxGrid({
|
|
|
24466
24847
|
const previousBodyCanvasSignature = paintedBodyCanvasSignatureRef.current;
|
|
24467
24848
|
const previousHeaderCanvasSignature = paintedHeaderCanvasSignatureRef.current;
|
|
24468
24849
|
const previousPaintedViewport = paintedDrawingViewportRef.current;
|
|
24469
|
-
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);
|
|
24850
|
+
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);
|
|
24470
24851
|
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);
|
|
24471
24852
|
const canBlitBody = Boolean(
|
|
24472
|
-
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
|
|
24853
|
+
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
|
|
24473
24854
|
);
|
|
24474
24855
|
const canBlitTopHeader = Boolean(
|
|
24475
24856
|
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
|
|
@@ -24480,49 +24861,37 @@ function XlsxGrid({
|
|
|
24480
24861
|
if (!shouldRepaintBody && !shouldRepaintHeaders) {
|
|
24481
24862
|
return;
|
|
24482
24863
|
}
|
|
24483
|
-
const scrollBodyCanvasWidth2 = Math.max(0, drawingViewport.width - frozenPaneRight);
|
|
24484
|
-
const scrollBodyCanvasHeight2 = Math.max(0, drawingViewport.height - frozenPaneBottom);
|
|
24485
|
-
const topBodyCanvasWidth2 = scrollBodyCanvasWidth2;
|
|
24486
|
-
const topBodyCanvasHeight2 = Math.max(0, frozenPaneBottom - displayHeaderHeight);
|
|
24487
|
-
const leftBodyCanvasWidth2 = Math.max(0, frozenPaneRight - displayRowHeaderWidth);
|
|
24488
|
-
const leftBodyCanvasHeight2 = scrollBodyCanvasHeight2;
|
|
24489
|
-
const cornerBodyCanvasWidth2 = leftBodyCanvasWidth2;
|
|
24490
|
-
const cornerBodyCanvasHeight2 = topBodyCanvasHeight2;
|
|
24491
|
-
const topFrozenHeaderCanvasWidth2 = leftBodyCanvasWidth2;
|
|
24492
|
-
const topScrollHeaderCanvasWidth2 = scrollBodyCanvasWidth2;
|
|
24493
|
-
const leftFrozenHeaderCanvasHeight2 = topBodyCanvasHeight2;
|
|
24494
|
-
const leftScrollHeaderCanvasHeight2 = scrollBodyCanvasHeight2;
|
|
24495
24864
|
const paneBounds = {
|
|
24496
24865
|
corner: {
|
|
24497
|
-
height:
|
|
24866
|
+
height: cornerBodyCanvasHeight,
|
|
24498
24867
|
left: displayRowHeaderWidth,
|
|
24499
24868
|
top: displayHeaderHeight,
|
|
24500
|
-
width:
|
|
24869
|
+
width: cornerBodyCanvasWidth
|
|
24501
24870
|
},
|
|
24502
24871
|
left: {
|
|
24503
|
-
height:
|
|
24872
|
+
height: leftBodyCanvasHeight,
|
|
24504
24873
|
left: displayRowHeaderWidth,
|
|
24505
|
-
top:
|
|
24506
|
-
width:
|
|
24874
|
+
top: scrollBodyCanvasTop,
|
|
24875
|
+
width: leftBodyCanvasWidth
|
|
24507
24876
|
},
|
|
24508
24877
|
scroll: {
|
|
24509
|
-
height:
|
|
24510
|
-
left:
|
|
24511
|
-
top:
|
|
24512
|
-
width:
|
|
24878
|
+
height: scrollBodyCanvasHeight,
|
|
24879
|
+
left: scrollBodyCanvasLeft,
|
|
24880
|
+
top: scrollBodyCanvasTop,
|
|
24881
|
+
width: scrollBodyCanvasWidth
|
|
24513
24882
|
},
|
|
24514
24883
|
top: {
|
|
24515
|
-
height:
|
|
24516
|
-
left:
|
|
24884
|
+
height: topBodyCanvasHeight,
|
|
24885
|
+
left: scrollBodyCanvasLeft,
|
|
24517
24886
|
top: displayHeaderHeight,
|
|
24518
|
-
width:
|
|
24887
|
+
width: topBodyCanvasWidth
|
|
24519
24888
|
}
|
|
24520
24889
|
};
|
|
24521
24890
|
const bodyContexts = shouldRepaintBody ? {
|
|
24522
|
-
corner: configureCanvas(cornerBodyCanvasRef.current,
|
|
24523
|
-
left: configureCanvas(leftBodyCanvasRef.current,
|
|
24524
|
-
scroll: configureCanvas(scrollBodyCanvasRef.current,
|
|
24525
|
-
top: configureCanvas(topBodyCanvasRef.current,
|
|
24891
|
+
corner: configureCanvas(cornerBodyCanvasRef.current, cornerBodyCanvasWidth, cornerBodyCanvasHeight, { clear: !canBlitBody }),
|
|
24892
|
+
left: configureCanvas(leftBodyCanvasRef.current, leftBodyCanvasWidth, leftBodyCanvasHeight, { clear: !canBlitBody }),
|
|
24893
|
+
scroll: configureCanvas(scrollBodyCanvasRef.current, scrollBodyCanvasWidth, scrollBodyCanvasHeight, { clear: !canBlitBody }),
|
|
24894
|
+
top: configureCanvas(topBodyCanvasRef.current, topBodyCanvasWidth, topBodyCanvasHeight, { clear: !canBlitBody })
|
|
24526
24895
|
} : {
|
|
24527
24896
|
corner: null,
|
|
24528
24897
|
left: null,
|
|
@@ -24530,21 +24899,21 @@ function XlsxGrid({
|
|
|
24530
24899
|
top: null
|
|
24531
24900
|
};
|
|
24532
24901
|
const topHeaderContexts = shouldRepaintHeaders ? {
|
|
24533
|
-
frozen: configureCanvas(topFrozenHeaderCanvasRef.current,
|
|
24534
|
-
scroll: configureCanvas(topScrollHeaderCanvasRef.current,
|
|
24902
|
+
frozen: configureCanvas(topFrozenHeaderCanvasRef.current, topFrozenHeaderCanvasWidth, headerHeight),
|
|
24903
|
+
scroll: configureCanvas(topScrollHeaderCanvasRef.current, topScrollHeaderCanvasWidth, headerHeight, { clear: !canBlitTopHeader })
|
|
24535
24904
|
} : {
|
|
24536
24905
|
frozen: null,
|
|
24537
24906
|
scroll: null
|
|
24538
24907
|
};
|
|
24539
24908
|
const leftHeaderContexts = shouldRepaintHeaders ? {
|
|
24540
|
-
frozen: configureCanvas(leftFrozenHeaderCanvasRef.current, rowHeaderWidth,
|
|
24541
|
-
scroll: configureCanvas(leftScrollHeaderCanvasRef.current, rowHeaderWidth,
|
|
24909
|
+
frozen: configureCanvas(leftFrozenHeaderCanvasRef.current, rowHeaderWidth, leftFrozenHeaderCanvasHeight),
|
|
24910
|
+
scroll: configureCanvas(leftScrollHeaderCanvasRef.current, rowHeaderWidth, leftScrollHeaderCanvasHeight, { clear: !canBlitLeftHeader })
|
|
24542
24911
|
} : {
|
|
24543
24912
|
frozen: null,
|
|
24544
24913
|
scroll: null
|
|
24545
24914
|
};
|
|
24546
24915
|
const cornerContext = shouldRepaintHeaders ? configureCanvas(cornerHeaderCanvasRef.current, rowHeaderWidth, headerHeight) : null;
|
|
24547
|
-
if (shouldRepaintBody && (!bodyContexts.scroll || !bodyContexts.top || !bodyContexts.left || !bodyContexts.corner) || shouldRepaintHeaders && (!cornerContext ||
|
|
24916
|
+
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)) {
|
|
24548
24917
|
return;
|
|
24549
24918
|
}
|
|
24550
24919
|
const showGridLines = activeSheet?.showGridLines ?? true;
|
|
@@ -24561,10 +24930,282 @@ function XlsxGrid({
|
|
|
24561
24930
|
scroll: [],
|
|
24562
24931
|
top: []
|
|
24563
24932
|
};
|
|
24564
|
-
let topScrollHeaderDirtyRects = buildFullCanvasDirtyRect(
|
|
24565
|
-
let leftScrollHeaderDirtyRects = buildFullCanvasDirtyRect(rowHeaderWidth,
|
|
24933
|
+
let topScrollHeaderDirtyRects = buildFullCanvasDirtyRect(topScrollHeaderCanvasWidth, headerHeight);
|
|
24934
|
+
let leftScrollHeaderDirtyRects = buildFullCanvasDirtyRect(rowHeaderWidth, leftScrollHeaderCanvasHeight);
|
|
24935
|
+
const bakedCanvasDrawingEntries = shouldBakeCanvasStaticDrawings ? [
|
|
24936
|
+
...bakedShapeRects.map(({ rect, shape }) => ({
|
|
24937
|
+
kind: "shape",
|
|
24938
|
+
rect,
|
|
24939
|
+
shape,
|
|
24940
|
+
zIndex: shape.zIndex
|
|
24941
|
+
})),
|
|
24942
|
+
...bakedFormControlRects.map(({ control, rect }) => ({
|
|
24943
|
+
control,
|
|
24944
|
+
kind: "formControl",
|
|
24945
|
+
rect,
|
|
24946
|
+
zIndex: control.zIndex
|
|
24947
|
+
})),
|
|
24948
|
+
...bakedImageRects.map(({ image, rect }) => ({
|
|
24949
|
+
image,
|
|
24950
|
+
kind: "image",
|
|
24951
|
+
rect,
|
|
24952
|
+
zIndex: image.zIndex
|
|
24953
|
+
}))
|
|
24954
|
+
].sort((left, right) => left.zIndex - right.zIndex) : [];
|
|
24955
|
+
const resolveBakedCanvasLocalRect = (rect, pane) => {
|
|
24956
|
+
const bounds = paneBounds[pane];
|
|
24957
|
+
const scrollX = pane === "scroll" || pane === "top" ? drawingViewport.left : 0;
|
|
24958
|
+
const scrollY = pane === "scroll" || pane === "left" ? drawingViewport.top : 0;
|
|
24959
|
+
return {
|
|
24960
|
+
height: rect.height,
|
|
24961
|
+
left: rect.left - scrollX - bounds.left,
|
|
24962
|
+
top: rect.top - scrollY - bounds.top,
|
|
24963
|
+
width: rect.width
|
|
24964
|
+
};
|
|
24965
|
+
};
|
|
24966
|
+
const drawBakedShapeText = (context, shape, left, top, width, height) => {
|
|
24967
|
+
if (shape.paragraphs.length === 0) {
|
|
24968
|
+
return;
|
|
24969
|
+
}
|
|
24970
|
+
const inset = shape.textBox?.insetPx;
|
|
24971
|
+
const paddingLeft = (inset?.left ?? 6) * zoomFactor;
|
|
24972
|
+
const paddingRight = (inset?.right ?? 6) * zoomFactor;
|
|
24973
|
+
const paddingTop = (inset?.top ?? 4) * zoomFactor;
|
|
24974
|
+
const paddingBottom = (inset?.bottom ?? 4) * zoomFactor;
|
|
24975
|
+
const textLeft = left + paddingLeft;
|
|
24976
|
+
const textTop = top + paddingTop;
|
|
24977
|
+
const textWidth = Math.max(0, width - paddingLeft - paddingRight);
|
|
24978
|
+
const textHeight = Math.max(0, height - paddingTop - paddingBottom);
|
|
24979
|
+
if (textWidth <= 0 || textHeight <= 0) {
|
|
24980
|
+
return;
|
|
24981
|
+
}
|
|
24982
|
+
const lineMetrics = shape.paragraphs.map((paragraph) => {
|
|
24983
|
+
const lineHeight = Math.max(
|
|
24984
|
+
12 * zoomFactor,
|
|
24985
|
+
...paragraph.runs.map((run) => (run.fontSizePt ?? 11) * 96 / 72 * zoomFactor * 1.2)
|
|
24986
|
+
);
|
|
24987
|
+
const widthPx = paragraph.runs.reduce((total, run) => {
|
|
24988
|
+
const fontSize = (run.fontSizePt ?? 11) * 96 / 72 * zoomFactor;
|
|
24989
|
+
context.font = `${run.italic ? "italic " : ""}${run.bold ? "700 " : "400 "}${fontSize}px ${run.fontFamily ?? "Calibri, sans-serif"}`;
|
|
24990
|
+
return total + measureCanvasTextWidth(context, run.text);
|
|
24991
|
+
}, 0);
|
|
24992
|
+
return { lineHeight, widthPx };
|
|
24993
|
+
});
|
|
24994
|
+
const totalTextHeight = lineMetrics.reduce((total, metric) => total + metric.lineHeight, 0);
|
|
24995
|
+
let y = textTop;
|
|
24996
|
+
if (shape.textBox?.verticalAlign === "middle") {
|
|
24997
|
+
y = textTop + Math.max(0, (textHeight - totalTextHeight) / 2);
|
|
24998
|
+
} else if (shape.textBox?.verticalAlign === "bottom") {
|
|
24999
|
+
y = textTop + Math.max(0, textHeight - totalTextHeight);
|
|
25000
|
+
}
|
|
25001
|
+
context.save();
|
|
25002
|
+
context.beginPath();
|
|
25003
|
+
context.rect(textLeft, textTop, textWidth, textHeight);
|
|
25004
|
+
context.clip();
|
|
25005
|
+
context.textBaseline = "middle";
|
|
25006
|
+
shape.paragraphs.forEach((paragraph, paragraphIndex) => {
|
|
25007
|
+
const metric = lineMetrics[paragraphIndex] ?? { lineHeight: 14 * zoomFactor, widthPx: 0 };
|
|
25008
|
+
let x = textLeft;
|
|
25009
|
+
const align = paragraph.align ?? shape.textBox?.horizontalAlign ?? "left";
|
|
25010
|
+
if (align === "center") {
|
|
25011
|
+
x = textLeft + Math.max(0, (textWidth - metric.widthPx) / 2);
|
|
25012
|
+
} else if (align === "right") {
|
|
25013
|
+
x = textLeft + Math.max(0, textWidth - metric.widthPx);
|
|
25014
|
+
}
|
|
25015
|
+
paragraph.runs.forEach((run) => {
|
|
25016
|
+
const fontSize = (run.fontSizePt ?? 11) * 96 / 72 * zoomFactor;
|
|
25017
|
+
context.font = `${run.italic ? "italic " : ""}${run.bold ? "700 " : "400 "}${fontSize}px ${run.fontFamily ?? "Calibri, sans-serif"}`;
|
|
25018
|
+
context.fillStyle = run.color ?? "#000000";
|
|
25019
|
+
context.textAlign = "left";
|
|
25020
|
+
const textY = y + metric.lineHeight / 2;
|
|
25021
|
+
context.fillText(run.text, x, textY);
|
|
25022
|
+
if (run.underline && run.text.length > 0) {
|
|
25023
|
+
const textWidthPx = measureCanvasTextWidth(context, run.text);
|
|
25024
|
+
context.strokeStyle = run.color ?? "#000000";
|
|
25025
|
+
context.lineWidth = Math.max(1, zoomFactor * 0.75);
|
|
25026
|
+
context.beginPath();
|
|
25027
|
+
context.moveTo(x, textY + Math.max(2, fontSize * 0.28));
|
|
25028
|
+
context.lineTo(x + textWidthPx, textY + Math.max(2, fontSize * 0.28));
|
|
25029
|
+
context.stroke();
|
|
25030
|
+
}
|
|
25031
|
+
x += measureCanvasTextWidth(context, run.text);
|
|
25032
|
+
});
|
|
25033
|
+
y += metric.lineHeight;
|
|
25034
|
+
});
|
|
25035
|
+
context.restore();
|
|
25036
|
+
};
|
|
25037
|
+
const drawBakedShape = (context, shape, rect) => {
|
|
25038
|
+
const fillColor = shape.fill?.none ? "transparent" : shape.fill?.color ?? "transparent";
|
|
25039
|
+
const strokeColor = shape.stroke?.none ? "transparent" : shape.stroke?.color ?? "transparent";
|
|
25040
|
+
const lineWidth = Math.max(0, (shape.stroke?.widthPx ?? (shape.geometry === "line" ? 2 : 1)) * zoomFactor);
|
|
25041
|
+
const vectorShape = resolveShapeVector(shape);
|
|
25042
|
+
const opacity = Math.min(shape.fill?.opacity ?? 1, shape.stroke?.opacity ?? 1);
|
|
25043
|
+
context.save();
|
|
25044
|
+
context.translate(rect.left + rect.width / 2, rect.top + rect.height / 2);
|
|
25045
|
+
if (shape.rotationDeg) {
|
|
25046
|
+
context.rotate(shape.rotationDeg * Math.PI / 180);
|
|
25047
|
+
}
|
|
25048
|
+
context.scale(shape.flipH ? -1 : 1, shape.flipV ? -1 : 1);
|
|
25049
|
+
context.globalAlpha *= opacity;
|
|
25050
|
+
context.lineWidth = lineWidth;
|
|
25051
|
+
context.strokeStyle = strokeColor;
|
|
25052
|
+
context.fillStyle = fillColor;
|
|
25053
|
+
applyCanvasShapeDash(context, shape.stroke?.dash, lineWidth);
|
|
25054
|
+
const localLeft = -rect.width / 2;
|
|
25055
|
+
const localTop = -rect.height / 2;
|
|
25056
|
+
if (vectorShape && typeof Path2D !== "undefined") {
|
|
25057
|
+
context.save();
|
|
25058
|
+
context.translate(localLeft, localTop);
|
|
25059
|
+
context.scale(
|
|
25060
|
+
rect.width / Math.max(1, vectorShape.viewBox.width),
|
|
25061
|
+
rect.height / Math.max(1, vectorShape.viewBox.height)
|
|
25062
|
+
);
|
|
25063
|
+
const path = getCachedCanvasPath2D(vectorShape.path);
|
|
25064
|
+
if (!path) {
|
|
25065
|
+
context.restore();
|
|
25066
|
+
context.restore();
|
|
25067
|
+
return;
|
|
25068
|
+
}
|
|
25069
|
+
if (fillColor !== "transparent") {
|
|
25070
|
+
context.fill(path);
|
|
25071
|
+
}
|
|
25072
|
+
if (strokeColor !== "transparent" && lineWidth > 0) {
|
|
25073
|
+
context.stroke(path);
|
|
25074
|
+
}
|
|
25075
|
+
context.restore();
|
|
25076
|
+
} else if (shape.geometry === "ellipse") {
|
|
25077
|
+
context.beginPath();
|
|
25078
|
+
context.ellipse(0, 0, rect.width / 2, rect.height / 2, 0, 0, Math.PI * 2);
|
|
25079
|
+
if (fillColor !== "transparent") {
|
|
25080
|
+
context.fill();
|
|
25081
|
+
}
|
|
25082
|
+
if (strokeColor !== "transparent" && lineWidth > 0) {
|
|
25083
|
+
context.stroke();
|
|
25084
|
+
}
|
|
25085
|
+
} else {
|
|
25086
|
+
const radius = shape.geometry === "roundRect" ? 12 * zoomFactor : 0;
|
|
25087
|
+
drawCanvasRoundedRect(context, localLeft, localTop, rect.width, rect.height, radius);
|
|
25088
|
+
if (fillColor !== "transparent") {
|
|
25089
|
+
context.fill();
|
|
25090
|
+
}
|
|
25091
|
+
if (strokeColor !== "transparent" && lineWidth > 0) {
|
|
25092
|
+
context.stroke();
|
|
25093
|
+
}
|
|
25094
|
+
}
|
|
25095
|
+
drawBakedShapeText(context, shape, localLeft, localTop, rect.width, rect.height);
|
|
25096
|
+
context.restore();
|
|
25097
|
+
};
|
|
25098
|
+
const drawBakedFormControl = (context, control, rect) => {
|
|
25099
|
+
const label = resolveFormControlLabel(control);
|
|
25100
|
+
const stroke = paletteIsDark(palette) ? "#cbd5e1" : "#475569";
|
|
25101
|
+
const textColor = control.textColor ?? "#000000";
|
|
25102
|
+
const fontSizePx = Math.max(9 * zoomFactor, (control.fontSizePt ?? 9) * 96 / 72 * zoomFactor);
|
|
25103
|
+
const iconSize = Math.min(14 * zoomFactor, Math.max(0, rect.height - 4 * zoomFactor));
|
|
25104
|
+
context.save();
|
|
25105
|
+
context.font = `400 ${fontSizePx}px ${control.fontFamily ?? "Calibri, sans-serif"}`;
|
|
25106
|
+
context.textBaseline = "middle";
|
|
25107
|
+
context.fillStyle = textColor;
|
|
25108
|
+
context.strokeStyle = stroke;
|
|
25109
|
+
context.lineWidth = Math.max(1, zoomFactor);
|
|
25110
|
+
if (control.kind === "group-box") {
|
|
25111
|
+
const labelInset = label ? Math.max(7, fontSizePx * 0.5) : 0;
|
|
25112
|
+
drawCanvasRoundedRect(context, rect.left, rect.top + labelInset, rect.width, Math.max(0, rect.height - labelInset), 2 * zoomFactor);
|
|
25113
|
+
context.stroke();
|
|
25114
|
+
if (label) {
|
|
25115
|
+
context.fillStyle = SHEET_SURFACE;
|
|
25116
|
+
const labelWidth = Math.min(rect.width - 16 * zoomFactor, measureCanvasTextWidth(context, label) + 8 * zoomFactor);
|
|
25117
|
+
context.fillRect(rect.left + 8 * zoomFactor, rect.top, labelWidth, fontSizePx * 1.2);
|
|
25118
|
+
context.fillStyle = textColor;
|
|
25119
|
+
context.textAlign = "left";
|
|
25120
|
+
context.fillText(label, rect.left + 12 * zoomFactor, rect.top + fontSizePx * 0.55);
|
|
25121
|
+
}
|
|
25122
|
+
context.restore();
|
|
25123
|
+
return;
|
|
25124
|
+
}
|
|
25125
|
+
if (control.kind === "button" || control.kind === "dropdown" || control.kind === "editbox" || control.kind === "listbox" || control.kind === "scrollbar" || control.kind === "spinner" || control.kind === "unknown") {
|
|
25126
|
+
if (control.kind === "button") {
|
|
25127
|
+
const gradient = context.createLinearGradient(rect.left, rect.top, rect.left, rect.top + rect.height);
|
|
25128
|
+
gradient.addColorStop(0, "#f8fafc");
|
|
25129
|
+
gradient.addColorStop(1, "#e2e8f0");
|
|
25130
|
+
context.fillStyle = gradient;
|
|
25131
|
+
} else {
|
|
25132
|
+
context.fillStyle = "transparent";
|
|
25133
|
+
}
|
|
25134
|
+
drawCanvasRoundedRect(context, rect.left, rect.top, rect.width, rect.height, control.kind === "button" ? 4 * zoomFactor : 2 * zoomFactor);
|
|
25135
|
+
if (control.kind === "button") {
|
|
25136
|
+
context.fill();
|
|
25137
|
+
}
|
|
25138
|
+
context.stroke();
|
|
25139
|
+
}
|
|
25140
|
+
let textLeft = rect.left + 2 * zoomFactor;
|
|
25141
|
+
const textRightInset = control.kind === "dropdown" ? 18 * zoomFactor : 6 * zoomFactor;
|
|
25142
|
+
if (control.kind === "checkbox") {
|
|
25143
|
+
context.strokeRect(rect.left + 2 * zoomFactor, rect.top + (rect.height - iconSize) / 2, iconSize, iconSize);
|
|
25144
|
+
if (control.checked) {
|
|
25145
|
+
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
25146
|
+
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));
|
|
25147
|
+
context.strokeStyle = paletteIsDark(palette) ? "#020617" : "#ffffff";
|
|
25148
|
+
context.beginPath();
|
|
25149
|
+
context.moveTo(rect.left + 2 * zoomFactor + iconSize * 0.24, rect.top + rect.height / 2 + iconSize * 0.06);
|
|
25150
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.45, rect.top + rect.height / 2 + iconSize * 0.26);
|
|
25151
|
+
context.lineTo(rect.left + 2 * zoomFactor + iconSize * 0.8, rect.top + rect.height / 2 - iconSize * 0.2);
|
|
25152
|
+
context.stroke();
|
|
25153
|
+
}
|
|
25154
|
+
textLeft += iconSize + 4 * zoomFactor;
|
|
25155
|
+
} else if (control.kind === "radio") {
|
|
25156
|
+
context.beginPath();
|
|
25157
|
+
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize / 2, 0, Math.PI * 2);
|
|
25158
|
+
context.stroke();
|
|
25159
|
+
if (control.checked) {
|
|
25160
|
+
context.fillStyle = paletteIsDark(palette) ? "#60a5fa" : "#2563eb";
|
|
25161
|
+
context.beginPath();
|
|
25162
|
+
context.arc(rect.left + 2 * zoomFactor + iconSize / 2, rect.top + rect.height / 2, iconSize * 0.25, 0, Math.PI * 2);
|
|
25163
|
+
context.fill();
|
|
25164
|
+
}
|
|
25165
|
+
textLeft += iconSize + 4 * zoomFactor;
|
|
25166
|
+
}
|
|
25167
|
+
if (label) {
|
|
25168
|
+
const maxTextWidth = Math.max(0, rect.left + rect.width - textLeft - textRightInset);
|
|
25169
|
+
const text = truncateCanvasText(context, label, maxTextWidth);
|
|
25170
|
+
context.fillStyle = textColor;
|
|
25171
|
+
context.textAlign = control.textAlign === "right" ? "right" : control.textAlign === "center" ? "center" : "left";
|
|
25172
|
+
const textX = context.textAlign === "right" ? rect.left + rect.width - textRightInset : context.textAlign === "center" ? textLeft + maxTextWidth / 2 : textLeft;
|
|
25173
|
+
context.fillText(text, textX, rect.top + rect.height / 2);
|
|
25174
|
+
}
|
|
25175
|
+
if (control.kind === "dropdown") {
|
|
25176
|
+
context.fillStyle = textColor;
|
|
25177
|
+
context.textAlign = "center";
|
|
25178
|
+
context.fillText("\u25BC", rect.left + rect.width - 10 * zoomFactor, rect.top + rect.height / 2);
|
|
25179
|
+
}
|
|
25180
|
+
context.restore();
|
|
25181
|
+
};
|
|
25182
|
+
const drawBakedCanvasDrawings = (pane, context, dirtyRects) => {
|
|
25183
|
+
if (bakedCanvasDrawingEntries.length === 0 || dirtyRects.length === 0) {
|
|
25184
|
+
return;
|
|
25185
|
+
}
|
|
25186
|
+
for (const entry of bakedCanvasDrawingEntries) {
|
|
25187
|
+
if (resolveDrawingPane(entry.rect) !== pane) {
|
|
25188
|
+
continue;
|
|
25189
|
+
}
|
|
25190
|
+
const localRect = resolveBakedCanvasLocalRect(entry.rect, pane);
|
|
25191
|
+
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)) {
|
|
25192
|
+
continue;
|
|
25193
|
+
}
|
|
25194
|
+
if (entry.kind === "shape") {
|
|
25195
|
+
drawBakedShape(context, entry.shape, localRect);
|
|
25196
|
+
} else if (entry.kind === "formControl") {
|
|
25197
|
+
drawBakedFormControl(context, entry.control, localRect);
|
|
25198
|
+
} else {
|
|
25199
|
+
const imageElement = getCanvasImage(entry.image);
|
|
25200
|
+
if (imageElement) {
|
|
25201
|
+
context.drawImage(imageElement, localRect.left, localRect.top, localRect.width, localRect.height);
|
|
25202
|
+
}
|
|
25203
|
+
}
|
|
25204
|
+
}
|
|
25205
|
+
};
|
|
24566
25206
|
const cellPaneOrder = ["scroll", "top", "left", "corner"];
|
|
24567
25207
|
if (shouldRepaintBody) {
|
|
25208
|
+
canvasProfileBodyStart = canvasProfileTarget ? performance.now() : 0;
|
|
24568
25209
|
for (const pane of Object.keys(bodyContexts)) {
|
|
24569
25210
|
const context = bodyContexts[pane];
|
|
24570
25211
|
const bounds = paneBounds[pane];
|
|
@@ -24595,6 +25236,7 @@ function XlsxGrid({
|
|
|
24595
25236
|
context.clearRect(0, 0, bounds.width, bounds.height);
|
|
24596
25237
|
}
|
|
24597
25238
|
bodyDirtyRectsByPane[pane] = dirtyRects;
|
|
25239
|
+
canvasProfileDirtyRects += dirtyRects.length;
|
|
24598
25240
|
if (dirtyRects.length === 0) {
|
|
24599
25241
|
continue;
|
|
24600
25242
|
}
|
|
@@ -24611,6 +25253,22 @@ function XlsxGrid({
|
|
|
24611
25253
|
if (!paneContext || paneDirtyRects.length === 0 || paneBoundsForCell.width <= 0 || paneBoundsForCell.height <= 0 || paneAxisItems.rows.length === 0 || paneAxisItems.cols.length === 0) {
|
|
24612
25254
|
continue;
|
|
24613
25255
|
}
|
|
25256
|
+
let hasPendingGridlinePath = false;
|
|
25257
|
+
const enqueueGridlinePath = () => {
|
|
25258
|
+
if (!hasPendingGridlinePath) {
|
|
25259
|
+
paneContext.beginPath();
|
|
25260
|
+
hasPendingGridlinePath = true;
|
|
25261
|
+
}
|
|
25262
|
+
};
|
|
25263
|
+
const flushPendingGridlines = () => {
|
|
25264
|
+
if (!hasPendingGridlinePath) {
|
|
25265
|
+
return;
|
|
25266
|
+
}
|
|
25267
|
+
paneContext.strokeStyle = palette.border;
|
|
25268
|
+
paneContext.lineWidth = 1;
|
|
25269
|
+
paneContext.stroke();
|
|
25270
|
+
hasPendingGridlinePath = false;
|
|
25271
|
+
};
|
|
24614
25272
|
const drawnMergedAnchorKeys = /* @__PURE__ */ new Set();
|
|
24615
25273
|
for (const rowItem of paneAxisItems.rows) {
|
|
24616
25274
|
for (const colItem of paneAxisItems.cols) {
|
|
@@ -24618,6 +25276,33 @@ function XlsxGrid({
|
|
|
24618
25276
|
const anchorCell = resolveMergeAnchorCell(cell);
|
|
24619
25277
|
const anchorKey = `${anchorCell.row}:${anchorCell.col}`;
|
|
24620
25278
|
let drawCell = anchorCell;
|
|
25279
|
+
const drawRowIndex = rowIndexByActual.get(drawCell.row);
|
|
25280
|
+
const drawColIndex = colIndexByActual.get(drawCell.col);
|
|
25281
|
+
if (drawRowIndex === void 0 || drawColIndex === void 0) {
|
|
25282
|
+
continue;
|
|
25283
|
+
}
|
|
25284
|
+
const baseCellLeft = displayRowHeaderWidth + (colPrefixSums[drawColIndex] ?? 0);
|
|
25285
|
+
const baseCellTop = displayHeaderHeight + (rowPrefixSums[drawRowIndex] ?? 0);
|
|
25286
|
+
const useFrozenHorizontalPosition = pane === "left" || pane === "corner";
|
|
25287
|
+
const useFrozenVerticalPosition = pane === "top" || pane === "corner";
|
|
25288
|
+
const roughLocalRect = {
|
|
25289
|
+
height: displayEffectiveRowHeights[drawRowIndex] ?? rowItem.size,
|
|
25290
|
+
left: (useFrozenHorizontalPosition ? stickyLeftByCol.get(drawCell.col) ?? baseCellLeft - drawingViewport.left : baseCellLeft - drawingViewport.left) - paneBoundsForCell.left,
|
|
25291
|
+
top: (useFrozenVerticalPosition ? stickyTopByRow.get(drawCell.row) ?? baseCellTop - drawingViewport.top : baseCellTop - drawingViewport.top) - paneBoundsForCell.top,
|
|
25292
|
+
width: displayEffectiveColWidths[drawColIndex] ?? colItem.size
|
|
25293
|
+
};
|
|
25294
|
+
const isMergedSecondaryProbe = anchorCell.row !== cell.row || anchorCell.col !== cell.col;
|
|
25295
|
+
if (!isMergedSecondaryProbe && !intersectsCanvasDirtyRects(
|
|
25296
|
+
roughLocalRect.left - CANVAS_DIRTY_CELL_CULL_MARGIN_PX,
|
|
25297
|
+
roughLocalRect.top - CANVAS_DIRTY_CELL_CULL_MARGIN_PX,
|
|
25298
|
+
roughLocalRect.width + CANVAS_DIRTY_CELL_CULL_MARGIN_PX * 2,
|
|
25299
|
+
roughLocalRect.height + CANVAS_DIRTY_CELL_CULL_MARGIN_PX * 2,
|
|
25300
|
+
paneDirtyRects
|
|
25301
|
+
)) {
|
|
25302
|
+
canvasProfileCulledCells += 1;
|
|
25303
|
+
continue;
|
|
25304
|
+
}
|
|
25305
|
+
canvasProfileLookedUpCells += 1;
|
|
24621
25306
|
let cellData = getCellData(drawCell.row, drawCell.col);
|
|
24622
25307
|
if ((cellData.colSpan || cellData.rowSpan) && drawnMergedAnchorKeys.has(anchorKey)) {
|
|
24623
25308
|
continue;
|
|
@@ -24628,16 +25313,9 @@ function XlsxGrid({
|
|
|
24628
25313
|
if (cellData.colSpan || cellData.rowSpan) {
|
|
24629
25314
|
drawnMergedAnchorKeys.add(anchorKey);
|
|
24630
25315
|
}
|
|
24631
|
-
const drawRowIndex = rowIndexByActual.get(drawCell.row);
|
|
24632
|
-
const drawColIndex = colIndexByActual.get(drawCell.col);
|
|
24633
|
-
if (drawRowIndex === void 0 || drawColIndex === void 0) {
|
|
24634
|
-
continue;
|
|
24635
|
-
}
|
|
24636
25316
|
const displayRect = cellData.colSpan || cellData.rowSpan ? resolveCellDisplayRect(drawCell) : null;
|
|
24637
|
-
const baseLeft = displayRect?.left ??
|
|
24638
|
-
const baseTop = displayRect?.top ??
|
|
24639
|
-
const useFrozenHorizontalPosition = pane === "left" || pane === "corner";
|
|
24640
|
-
const useFrozenVerticalPosition = pane === "top" || pane === "corner";
|
|
25317
|
+
const baseLeft = displayRect?.left ?? baseCellLeft;
|
|
25318
|
+
const baseTop = displayRect?.top ?? baseCellTop;
|
|
24641
25319
|
const localRect = {
|
|
24642
25320
|
height: displayRect?.height ?? (displayEffectiveRowHeights[drawRowIndex] ?? rowItem.size),
|
|
24643
25321
|
left: (useFrozenHorizontalPosition ? stickyLeftByCol.get(drawCell.col) ?? baseLeft - drawingViewport.left : baseLeft - drawingViewport.left) - paneBoundsForCell.left,
|
|
@@ -24649,13 +25327,18 @@ function XlsxGrid({
|
|
|
24649
25327
|
continue;
|
|
24650
25328
|
}
|
|
24651
25329
|
if (!intersectsCanvasDirtyRects(localRect.left, localRect.top, drawableWidth, localRect.height, paneDirtyRects)) {
|
|
25330
|
+
canvasProfileCulledCells += 1;
|
|
24652
25331
|
continue;
|
|
24653
25332
|
}
|
|
25333
|
+
canvasProfilePaintedCells += 1;
|
|
24654
25334
|
const cellStyle = cellData.style;
|
|
24655
25335
|
const canvasCellStyle = cellData.canvas ?? buildCanvasCellStyleCache(cellStyle);
|
|
24656
25336
|
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellStyle.backgroundColor === "string" ? cellStyle.backgroundColor : sheetSurface);
|
|
24657
25337
|
const gradientFill = !cellData.conditionalColorScale && typeof cellStyle.backgroundImage === "string" ? resolveCanvasGradientFill(paneContext, localRect, cellStyle.backgroundImage) : null;
|
|
24658
25338
|
const hasExplicitCellFill = cellData.conditionalColorScale !== null || gradientFill !== null || typeof cellStyle.backgroundColor === "string" && cellStyle.backgroundColor !== sheetSurface;
|
|
25339
|
+
if (hasExplicitCellFill || cellData.chartHighlight) {
|
|
25340
|
+
flushPendingGridlines();
|
|
25341
|
+
}
|
|
24659
25342
|
paneContext.fillStyle = gradientFill ?? fillColor;
|
|
24660
25343
|
paneContext.fillRect(localRect.left, localRect.top, localRect.width, localRect.height);
|
|
24661
25344
|
if (cellData.chartHighlight) {
|
|
@@ -24701,10 +25384,8 @@ function XlsxGrid({
|
|
|
24701
25384
|
const bottomNeighborTopBorder = bottomNeighborData?.isMergedSecondary ? null : bottomNeighborData?.canvas?.topBorder ?? parseCanvasBorderDeclaration(bottomNeighborData?.style.borderTop);
|
|
24702
25385
|
const resolvedRightBorder = resolveCanvasBoundaryBorder(rightBorder, rightNeighborLeftBorder);
|
|
24703
25386
|
const resolvedBottomBorder = resolveCanvasBoundaryBorder(bottomBorder, bottomNeighborTopBorder);
|
|
24704
|
-
if (showGridLines && !hasExplicitCellFill) {
|
|
24705
|
-
|
|
24706
|
-
paneContext.lineWidth = 1;
|
|
24707
|
-
paneContext.beginPath();
|
|
25387
|
+
if (showGridLines && !hasExplicitCellFill && (!resolvedRightBorder || !resolvedBottomBorder)) {
|
|
25388
|
+
enqueueGridlinePath();
|
|
24708
25389
|
if (!resolvedRightBorder) {
|
|
24709
25390
|
paneContext.moveTo(localRect.left + localRect.width - 0.5, localRect.top);
|
|
24710
25391
|
paneContext.lineTo(localRect.left + localRect.width - 0.5, localRect.top + localRect.height);
|
|
@@ -24713,7 +25394,9 @@ function XlsxGrid({
|
|
|
24713
25394
|
paneContext.moveTo(localRect.left, localRect.top + localRect.height - 0.5);
|
|
24714
25395
|
paneContext.lineTo(localRect.left + localRect.width, localRect.top + localRect.height - 0.5);
|
|
24715
25396
|
}
|
|
24716
|
-
|
|
25397
|
+
}
|
|
25398
|
+
if (topBorder || resolvedRightBorder || resolvedBottomBorder || leftBorder || cellData.chartHighlight) {
|
|
25399
|
+
flushPendingGridlines();
|
|
24717
25400
|
}
|
|
24718
25401
|
if (topBorder && drawRowIndex === 0) {
|
|
24719
25402
|
strokeCanvasBorderSide(paneContext, "top", localRect, topBorder);
|
|
@@ -24746,17 +25429,26 @@ function XlsxGrid({
|
|
|
24746
25429
|
strokeCanvasBorderSide(paneContext, "left", localRect, highlightBorder);
|
|
24747
25430
|
}
|
|
24748
25431
|
}
|
|
25432
|
+
const rawText = cellData.value ?? "";
|
|
25433
|
+
const shouldDrawCanvasContent = cellData.checkboxState != null || cellData.sparkline || rawText.length > 0 || cellData.conditionalIcon || cellData.isTableHeader;
|
|
25434
|
+
if (!shouldDrawCanvasContent) {
|
|
25435
|
+
continue;
|
|
25436
|
+
}
|
|
24749
25437
|
const padding = canvasCellStyle.padding;
|
|
24750
25438
|
const contentLeft = localRect.left + padding.left;
|
|
24751
25439
|
const contentTop = localRect.top + padding.top;
|
|
24752
25440
|
const contentWidth = Math.max(0, localRect.width - padding.left - padding.right);
|
|
24753
25441
|
const contentHeight = Math.max(0, localRect.height - padding.top - padding.bottom);
|
|
25442
|
+
if (contentWidth <= 0 || contentHeight <= 0) {
|
|
25443
|
+
continue;
|
|
25444
|
+
}
|
|
24754
25445
|
const activeFontSizePx = cellData.shrinkToFitFontSizePx ?? resolveCanvasFontSizePx(cellStyle, 12 * zoomFactor);
|
|
24755
25446
|
const textClipOverscan = Math.max(
|
|
24756
25447
|
1,
|
|
24757
25448
|
zoomFactor * 1.5,
|
|
24758
25449
|
activeFontSizePx * (cellData.textRotationDeg ? 0.75 : 0.18)
|
|
24759
25450
|
);
|
|
25451
|
+
flushPendingGridlines();
|
|
24760
25452
|
paneContext.save();
|
|
24761
25453
|
paneContext.beginPath();
|
|
24762
25454
|
paneContext.rect(
|
|
@@ -24888,7 +25580,6 @@ function XlsxGrid({
|
|
|
24888
25580
|
const trailingInset = (cellData.conditionalIcon ? 18 * zoomFactor : 0) + (cellData.isTableHeader ? 16 * zoomFactor : 0);
|
|
24889
25581
|
const spillMaxWidth = cellData.spillWidth && cellData.spillWidth > 0 ? Math.max(0, cellData.spillWidth - trailingInset) : null;
|
|
24890
25582
|
const maxTextWidth = spillMaxWidth ?? Math.max(0, contentWidth - trailingInset);
|
|
24891
|
-
const rawText = cellData.value ?? "";
|
|
24892
25583
|
const textColor = canvasCellStyle.textColor;
|
|
24893
25584
|
const shouldEllipsizeText = canvasCellStyle.textOverflowEllipsis;
|
|
24894
25585
|
const shouldWrapText = canvasCellStyle.usesWrappedText || rawText.includes("\n");
|
|
@@ -24920,7 +25611,7 @@ function XlsxGrid({
|
|
|
24920
25611
|
const textY = textBlockTop + lineIndex * lineHeight + lineHeight / 2;
|
|
24921
25612
|
paneContext.fillText(line, textX, textY);
|
|
24922
25613
|
if (canvasCellStyle.textDecoration?.includes("underline") && line.length > 0) {
|
|
24923
|
-
const measured = Math.min(maxTextWidth, paneContext
|
|
25614
|
+
const measured = Math.min(maxTextWidth, measureCanvasTextWidth(paneContext, line));
|
|
24924
25615
|
const underlineStartX = align === "right" ? textX - measured : align === "center" ? textX - measured / 2 : textX;
|
|
24925
25616
|
paneContext.beginPath();
|
|
24926
25617
|
paneContext.moveTo(underlineStartX, textY + Math.max(2, lineHeight * 0.24));
|
|
@@ -24954,7 +25645,7 @@ function XlsxGrid({
|
|
|
24954
25645
|
const textY = contentTop + contentHeight / 2;
|
|
24955
25646
|
paneContext.fillText(text, textX, textY);
|
|
24956
25647
|
if (canvasCellStyle.textDecoration?.includes("underline") && text.length > 0) {
|
|
24957
|
-
const measured = shouldEllipsizeText ? Math.min(maxTextWidth, paneContext
|
|
25648
|
+
const measured = shouldEllipsizeText ? Math.min(maxTextWidth, measureCanvasTextWidth(paneContext, text)) : measureCanvasTextWidth(paneContext, text);
|
|
24958
25649
|
const underlineStartX = align === "right" ? textX - measured : align === "center" ? textX - measured / 2 : textX;
|
|
24959
25650
|
paneContext.beginPath();
|
|
24960
25651
|
paneContext.moveTo(underlineStartX, textY + 6 * zoomFactor);
|
|
@@ -24979,6 +25670,7 @@ function XlsxGrid({
|
|
|
24979
25670
|
paneContext.restore();
|
|
24980
25671
|
}
|
|
24981
25672
|
}
|
|
25673
|
+
flushPendingGridlines();
|
|
24982
25674
|
}
|
|
24983
25675
|
for (const pane of cellPaneOrder) {
|
|
24984
25676
|
const paneContext = bodyContexts[pane];
|
|
@@ -24996,7 +25688,7 @@ function XlsxGrid({
|
|
|
24996
25688
|
paneContext.textBaseline = "middle";
|
|
24997
25689
|
paneContext.fillText(spillText.text, spillText.textX, spillText.textY);
|
|
24998
25690
|
if (spillText.textDecoration?.includes("underline") && spillText.text.length > 0) {
|
|
24999
|
-
const measured = spillText.ellipsize ? Math.min(spillText.maxWidth, paneContext
|
|
25691
|
+
const measured = spillText.ellipsize ? Math.min(spillText.maxWidth, measureCanvasTextWidth(paneContext, spillText.text)) : measureCanvasTextWidth(paneContext, spillText.text);
|
|
25000
25692
|
const underlineStartX = spillText.align === "right" ? spillText.textX - measured : spillText.align === "center" ? spillText.textX - measured / 2 : spillText.textX;
|
|
25001
25693
|
paneContext.beginPath();
|
|
25002
25694
|
paneContext.moveTo(underlineStartX, spillText.underlineY);
|
|
@@ -25008,6 +25700,14 @@ function XlsxGrid({
|
|
|
25008
25700
|
paneContext.restore();
|
|
25009
25701
|
}
|
|
25010
25702
|
}
|
|
25703
|
+
for (const pane of cellPaneOrder) {
|
|
25704
|
+
const paneContext = bodyContexts[pane];
|
|
25705
|
+
if (!paneContext) {
|
|
25706
|
+
continue;
|
|
25707
|
+
}
|
|
25708
|
+
drawBakedCanvasDrawings(pane, paneContext, bodyDirtyRectsByPane[pane]);
|
|
25709
|
+
}
|
|
25710
|
+
canvasProfileBodyMs = canvasProfileTarget ? performance.now() - canvasProfileBodyStart : 0;
|
|
25011
25711
|
}
|
|
25012
25712
|
if (shouldRepaintHeaders && cornerContext) {
|
|
25013
25713
|
const topFrozenHeaderContext = topHeaderContexts.frozen;
|
|
@@ -25022,7 +25722,7 @@ function XlsxGrid({
|
|
|
25022
25722
|
topScrollHeaderContext,
|
|
25023
25723
|
bufferCanvas,
|
|
25024
25724
|
dpr,
|
|
25025
|
-
|
|
25725
|
+
topScrollHeaderCanvasWidth,
|
|
25026
25726
|
headerHeight,
|
|
25027
25727
|
drawingViewport.left - previousPaintedViewport.left,
|
|
25028
25728
|
0
|
|
@@ -25041,7 +25741,7 @@ function XlsxGrid({
|
|
|
25041
25741
|
bufferCanvas,
|
|
25042
25742
|
dpr,
|
|
25043
25743
|
rowHeaderWidth,
|
|
25044
|
-
|
|
25744
|
+
leftScrollHeaderCanvasHeight,
|
|
25045
25745
|
0,
|
|
25046
25746
|
drawingViewport.top - previousPaintedViewport.top
|
|
25047
25747
|
);
|
|
@@ -25050,11 +25750,11 @@ function XlsxGrid({
|
|
|
25050
25750
|
}
|
|
25051
25751
|
}
|
|
25052
25752
|
}
|
|
25053
|
-
if (topFrozenHeaderContext &&
|
|
25753
|
+
if (topFrozenHeaderContext && topFrozenHeaderCanvasWidth > 0) {
|
|
25054
25754
|
topFrozenHeaderContext.fillStyle = palette.headerSurface;
|
|
25055
|
-
topFrozenHeaderContext.fillRect(0, 0,
|
|
25755
|
+
topFrozenHeaderContext.fillRect(0, 0, topFrozenHeaderCanvasWidth, headerHeight);
|
|
25056
25756
|
}
|
|
25057
|
-
if (topScrollHeaderContext &&
|
|
25757
|
+
if (topScrollHeaderContext && topScrollHeaderCanvasWidth > 0) {
|
|
25058
25758
|
topScrollHeaderContext.fillStyle = palette.headerSurface;
|
|
25059
25759
|
for (const dirtyRect of topScrollHeaderDirtyRects) {
|
|
25060
25760
|
topScrollHeaderContext.fillRect(dirtyRect.left, dirtyRect.top, dirtyRect.width, dirtyRect.height);
|
|
@@ -25073,7 +25773,7 @@ function XlsxGrid({
|
|
|
25073
25773
|
if (!paneContext) {
|
|
25074
25774
|
continue;
|
|
25075
25775
|
}
|
|
25076
|
-
if (column.localLeft + column.width < 0 || column.localLeft > (column.isFrozen ?
|
|
25776
|
+
if (column.localLeft + column.width < 0 || column.localLeft > (column.isFrozen ? topFrozenHeaderCanvasWidth : topScrollHeaderCanvasWidth)) {
|
|
25077
25777
|
continue;
|
|
25078
25778
|
}
|
|
25079
25779
|
if (!column.isFrozen && !intersectsCanvasDirtyRects(column.localLeft, 0, column.width, column.height, topScrollHeaderDirtyRects)) {
|
|
@@ -25099,11 +25799,11 @@ function XlsxGrid({
|
|
|
25099
25799
|
column.height / 2
|
|
25100
25800
|
);
|
|
25101
25801
|
}
|
|
25102
|
-
if (leftFrozenHeaderContext &&
|
|
25802
|
+
if (leftFrozenHeaderContext && leftFrozenHeaderCanvasHeight > 0) {
|
|
25103
25803
|
leftFrozenHeaderContext.fillStyle = palette.rowHeaderSurface;
|
|
25104
|
-
leftFrozenHeaderContext.fillRect(0, 0, rowHeaderWidth,
|
|
25804
|
+
leftFrozenHeaderContext.fillRect(0, 0, rowHeaderWidth, leftFrozenHeaderCanvasHeight);
|
|
25105
25805
|
}
|
|
25106
|
-
if (leftScrollHeaderContext &&
|
|
25806
|
+
if (leftScrollHeaderContext && leftScrollHeaderCanvasHeight > 0) {
|
|
25107
25807
|
leftScrollHeaderContext.fillStyle = palette.rowHeaderSurface;
|
|
25108
25808
|
for (const dirtyRect of leftScrollHeaderDirtyRects) {
|
|
25109
25809
|
leftScrollHeaderContext.fillRect(dirtyRect.left, dirtyRect.top, dirtyRect.width, dirtyRect.height);
|
|
@@ -25122,7 +25822,7 @@ function XlsxGrid({
|
|
|
25122
25822
|
if (!paneContext) {
|
|
25123
25823
|
continue;
|
|
25124
25824
|
}
|
|
25125
|
-
if (row.localTop + row.height < 0 || row.localTop > (row.isFrozen ?
|
|
25825
|
+
if (row.localTop + row.height < 0 || row.localTop > (row.isFrozen ? leftFrozenHeaderCanvasHeight : leftScrollHeaderCanvasHeight)) {
|
|
25126
25826
|
continue;
|
|
25127
25827
|
}
|
|
25128
25828
|
if (!row.isFrozen && !intersectsCanvasDirtyRects(0, row.localTop, rowHeaderWidth, row.height, leftScrollHeaderDirtyRects)) {
|
|
@@ -25162,9 +25862,29 @@ function XlsxGrid({
|
|
|
25162
25862
|
paintedHeaderCanvasSignatureRef.current = nextHeaderCanvasSignature;
|
|
25163
25863
|
}
|
|
25164
25864
|
applyCanvasViewportCompensation();
|
|
25865
|
+
if (canvasProfileTarget) {
|
|
25866
|
+
canvasProfileTarget.push({
|
|
25867
|
+
bodyMs: canvasProfileBodyMs,
|
|
25868
|
+
culledCells: canvasProfileCulledCells,
|
|
25869
|
+
dirtyRects: canvasProfileDirtyRects,
|
|
25870
|
+
lookedUpCells: canvasProfileLookedUpCells,
|
|
25871
|
+
paintedCells: canvasProfilePaintedCells,
|
|
25872
|
+
repaintBody: shouldRepaintBody,
|
|
25873
|
+
repaintHeaders: shouldRepaintHeaders,
|
|
25874
|
+
renderToLayoutMs: canvasProfileStart - xlsxGridRenderStart,
|
|
25875
|
+
totalMs: performance.now() - canvasProfileStart
|
|
25876
|
+
});
|
|
25877
|
+
if (canvasProfileTarget.length > 500) {
|
|
25878
|
+
canvasProfileTarget.splice(0, canvasProfileTarget.length - 500);
|
|
25879
|
+
}
|
|
25880
|
+
}
|
|
25165
25881
|
}, [
|
|
25166
25882
|
activeSheet,
|
|
25167
25883
|
applyCanvasViewportCompensation,
|
|
25884
|
+
bakedCanvasDrawingSignature,
|
|
25885
|
+
bakedFormControlRects,
|
|
25886
|
+
bakedImageRects,
|
|
25887
|
+
bakedShapeRects,
|
|
25168
25888
|
canvasColumnHeaderCells,
|
|
25169
25889
|
canvasPaneAxisItems,
|
|
25170
25890
|
canvasRowHeaderCells,
|
|
@@ -25185,15 +25905,16 @@ function XlsxGrid({
|
|
|
25185
25905
|
frozenPaneBottom,
|
|
25186
25906
|
frozenPaneRight,
|
|
25187
25907
|
getCellData,
|
|
25908
|
+
getCanvasImage,
|
|
25188
25909
|
getBodyBlitBufferCanvas,
|
|
25189
25910
|
getHeaderBlitBufferCanvas,
|
|
25190
25911
|
palette,
|
|
25191
25912
|
resolveCellDisplayRect,
|
|
25192
25913
|
resolveMergeAnchorCell,
|
|
25193
|
-
resizeGuide,
|
|
25194
25914
|
rowIndexByActual,
|
|
25195
25915
|
rowPrefixSums,
|
|
25196
25916
|
selectionHeaderSurface,
|
|
25917
|
+
shouldBakeCanvasStaticDrawings,
|
|
25197
25918
|
stickyLeftByCol,
|
|
25198
25919
|
stickyTopByRow,
|
|
25199
25920
|
visibleCols,
|
|
@@ -25411,7 +26132,7 @@ function XlsxGrid({
|
|
|
25411
26132
|
start: virtualRow?.start ?? (rowPrefixSums[index] ?? 0)
|
|
25412
26133
|
};
|
|
25413
26134
|
});
|
|
25414
|
-
const totalHeight = shouldVirtualizeRows ? rowVirtualizer.getTotalSize() : rowPrefixSums[rowPrefixSums.length - 1] ?? 0;
|
|
26135
|
+
const totalHeight = shouldUseDomVirtualizer && shouldVirtualizeRows ? rowVirtualizer.getTotalSize() : rowPrefixSums[rowPrefixSums.length - 1] ?? 0;
|
|
25415
26136
|
const totalWidth = totalContentWidth + displayRowHeaderWidth;
|
|
25416
26137
|
const sheetContentHeight = displayHeaderHeight + totalHeight;
|
|
25417
26138
|
const isLiveZooming = liveGestureZoom !== null && zoomScale === liveGestureZoom.baseZoomScale;
|
|
@@ -25485,18 +26206,6 @@ function XlsxGrid({
|
|
|
25485
26206
|
width: 0,
|
|
25486
26207
|
zIndex: canvasHeaderOverlayZIndex
|
|
25487
26208
|
};
|
|
25488
|
-
const scrollBodyCanvasWidth = Math.max(0, drawingViewport.width - frozenPaneRight);
|
|
25489
|
-
const scrollBodyCanvasHeight = Math.max(0, drawingViewport.height - frozenPaneBottom);
|
|
25490
|
-
const topBodyCanvasWidth = scrollBodyCanvasWidth;
|
|
25491
|
-
const topBodyCanvasHeight = Math.max(0, frozenPaneBottom - displayHeaderHeight);
|
|
25492
|
-
const leftBodyCanvasWidth = Math.max(0, frozenPaneRight - displayRowHeaderWidth);
|
|
25493
|
-
const leftBodyCanvasHeight = scrollBodyCanvasHeight;
|
|
25494
|
-
const cornerBodyCanvasWidth = leftBodyCanvasWidth;
|
|
25495
|
-
const cornerBodyCanvasHeight = topBodyCanvasHeight;
|
|
25496
|
-
const topFrozenHeaderCanvasWidth = leftBodyCanvasWidth;
|
|
25497
|
-
const topScrollHeaderCanvasWidth = scrollBodyCanvasWidth;
|
|
25498
|
-
const leftFrozenHeaderCanvasHeight = topBodyCanvasHeight;
|
|
25499
|
-
const leftScrollHeaderCanvasHeight = scrollBodyCanvasHeight;
|
|
25500
26209
|
const canvasBodyBaseStyle = {
|
|
25501
26210
|
cursor: "cell",
|
|
25502
26211
|
pointerEvents: "auto",
|
|
@@ -25508,13 +26217,13 @@ function XlsxGrid({
|
|
|
25508
26217
|
const canvasScrollBodyStyle = {
|
|
25509
26218
|
...canvasBodyBaseStyle,
|
|
25510
26219
|
display: scrollBodyCanvasWidth > 0 && scrollBodyCanvasHeight > 0 ? "block" : "none",
|
|
25511
|
-
left:
|
|
25512
|
-
top:
|
|
26220
|
+
left: scrollBodyCanvasLeft,
|
|
26221
|
+
top: scrollBodyCanvasTop
|
|
25513
26222
|
};
|
|
25514
26223
|
const canvasTopBodyStyle = {
|
|
25515
26224
|
...canvasBodyBaseStyle,
|
|
25516
26225
|
display: topBodyCanvasWidth > 0 && topBodyCanvasHeight > 0 ? "block" : "none",
|
|
25517
|
-
left:
|
|
26226
|
+
left: scrollBodyCanvasLeft,
|
|
25518
26227
|
top: displayHeaderHeight,
|
|
25519
26228
|
zIndex: 30
|
|
25520
26229
|
};
|
|
@@ -25522,7 +26231,7 @@ function XlsxGrid({
|
|
|
25522
26231
|
...canvasBodyBaseStyle,
|
|
25523
26232
|
display: leftBodyCanvasWidth > 0 && leftBodyCanvasHeight > 0 ? "block" : "none",
|
|
25524
26233
|
left: displayRowHeaderWidth,
|
|
25525
|
-
top:
|
|
26234
|
+
top: scrollBodyCanvasTop,
|
|
25526
26235
|
zIndex: 30
|
|
25527
26236
|
};
|
|
25528
26237
|
const canvasCornerBodyStyle = {
|
|
@@ -25548,7 +26257,7 @@ function XlsxGrid({
|
|
|
25548
26257
|
const canvasTopScrollHeaderStyle = {
|
|
25549
26258
|
...canvasHeaderBaseStyle,
|
|
25550
26259
|
display: topScrollHeaderCanvasWidth > 0 && drawingViewport.height > 0 ? "block" : "none",
|
|
25551
|
-
left:
|
|
26260
|
+
left: scrollBodyCanvasLeft,
|
|
25552
26261
|
top: 0,
|
|
25553
26262
|
zIndex: canvasHeaderOverlayZIndex
|
|
25554
26263
|
};
|
|
@@ -25563,7 +26272,7 @@ function XlsxGrid({
|
|
|
25563
26272
|
...canvasHeaderBaseStyle,
|
|
25564
26273
|
display: leftScrollHeaderCanvasHeight > 0 && drawingViewport.width > 0 ? "block" : "none",
|
|
25565
26274
|
left: 0,
|
|
25566
|
-
top:
|
|
26275
|
+
top: scrollBodyCanvasTop,
|
|
25567
26276
|
zIndex: canvasHeaderOverlayZIndex
|
|
25568
26277
|
};
|
|
25569
26278
|
const canvasCornerHeaderStyle = {
|
|
@@ -26119,26 +26828,26 @@ function XlsxGrid({
|
|
|
26119
26828
|
};
|
|
26120
26829
|
const canvasScrollOverlayPaneStyle = {
|
|
26121
26830
|
...canvasOverlayPaneBaseStyle,
|
|
26122
|
-
display:
|
|
26123
|
-
height:
|
|
26831
|
+
display: scrollBodyViewportWidth > 0 && scrollBodyViewportHeight > 0 ? "block" : "none",
|
|
26832
|
+
height: scrollBodyViewportHeight,
|
|
26124
26833
|
left: frozenPaneRight,
|
|
26125
26834
|
top: frozenPaneBottom,
|
|
26126
|
-
width:
|
|
26835
|
+
width: scrollBodyViewportWidth,
|
|
26127
26836
|
zIndex: 20
|
|
26128
26837
|
};
|
|
26129
26838
|
const canvasTopOverlayPaneStyle = {
|
|
26130
26839
|
...canvasOverlayPaneBaseStyle,
|
|
26131
|
-
display:
|
|
26840
|
+
display: scrollBodyViewportWidth > 0 && topBodyCanvasHeight > 0 ? "block" : "none",
|
|
26132
26841
|
height: topBodyCanvasHeight,
|
|
26133
26842
|
left: frozenPaneRight,
|
|
26134
26843
|
top: displayHeaderHeight,
|
|
26135
|
-
width:
|
|
26844
|
+
width: scrollBodyViewportWidth,
|
|
26136
26845
|
zIndex: 35
|
|
26137
26846
|
};
|
|
26138
26847
|
const canvasLeftOverlayPaneStyle = {
|
|
26139
26848
|
...canvasOverlayPaneBaseStyle,
|
|
26140
|
-
display: leftBodyCanvasWidth > 0 &&
|
|
26141
|
-
height:
|
|
26849
|
+
display: leftBodyCanvasWidth > 0 && scrollBodyViewportHeight > 0 ? "block" : "none",
|
|
26850
|
+
height: scrollBodyViewportHeight,
|
|
26142
26851
|
left: displayRowHeaderWidth,
|
|
26143
26852
|
top: frozenPaneBottom,
|
|
26144
26853
|
width: leftBodyCanvasWidth,
|
|
@@ -26153,8 +26862,9 @@ function XlsxGrid({
|
|
|
26153
26862
|
width: cornerBodyCanvasWidth,
|
|
26154
26863
|
zIndex: 36
|
|
26155
26864
|
};
|
|
26865
|
+
const drawingViewportCacheSignature = `${Math.floor(drawingViewport.left / CANVAS_VIEWPORT_OVERSCAN_PX)}:${Math.floor(drawingViewport.top / CANVAS_VIEWPORT_OVERSCAN_PX)}:${drawingViewport.width}:${drawingViewport.height}`;
|
|
26156
26866
|
const previousPaneDrawingNodes = paneDrawingNodesCacheRef.current;
|
|
26157
|
-
const canReusePaneDrawingNodes = previousPaneDrawingNodes !== null && previousPaneDrawingNodes.showImages === showImages && previousPaneDrawingNodes.chartRects === chartRects && previousPaneDrawingNodes.formControlRects ===
|
|
26867
|
+
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;
|
|
26158
26868
|
const paneDrawingNodes = canReusePaneDrawingNodes ? previousPaneDrawingNodes.value : !showImages ? {
|
|
26159
26869
|
corner: null,
|
|
26160
26870
|
left: null,
|
|
@@ -26163,35 +26873,35 @@ function XlsxGrid({
|
|
|
26163
26873
|
} : {
|
|
26164
26874
|
corner: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26165
26875
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "corner")),
|
|
26166
|
-
|
|
26167
|
-
|
|
26168
|
-
|
|
26876
|
+
domShapeRects.map(({ shape, rect }) => renderShapeDrawing(shape, rect, "corner")),
|
|
26877
|
+
domFormControlRects.map(({ control, rect }) => renderFormControlDrawing(control, rect, "corner")),
|
|
26878
|
+
domImageRects.map(({ image, rect }) => renderImageDrawing(image, rect, "corner"))
|
|
26169
26879
|
] }),
|
|
26170
26880
|
left: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26171
26881
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "left")),
|
|
26172
|
-
|
|
26173
|
-
|
|
26174
|
-
|
|
26882
|
+
domShapeRects.map(({ shape, rect }) => renderShapeDrawing(shape, rect, "left")),
|
|
26883
|
+
domFormControlRects.map(({ control, rect }) => renderFormControlDrawing(control, rect, "left")),
|
|
26884
|
+
domImageRects.map(({ image, rect }) => renderImageDrawing(image, rect, "left"))
|
|
26175
26885
|
] }),
|
|
26176
26886
|
scroll: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26177
26887
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "scroll")),
|
|
26178
|
-
|
|
26179
|
-
|
|
26180
|
-
|
|
26888
|
+
domShapeRects.map(({ shape, rect }) => renderShapeDrawing(shape, rect, "scroll")),
|
|
26889
|
+
domFormControlRects.map(({ control, rect }) => renderFormControlDrawing(control, rect, "scroll")),
|
|
26890
|
+
domImageRects.map(({ image, rect }) => renderImageDrawing(image, rect, "scroll"))
|
|
26181
26891
|
] }),
|
|
26182
26892
|
top: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26183
26893
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "top")),
|
|
26184
|
-
|
|
26185
|
-
|
|
26186
|
-
|
|
26894
|
+
domShapeRects.map(({ shape, rect }) => renderShapeDrawing(shape, rect, "top")),
|
|
26895
|
+
domFormControlRects.map(({ control, rect }) => renderFormControlDrawing(control, rect, "top")),
|
|
26896
|
+
domImageRects.map(({ image, rect }) => renderImageDrawing(image, rect, "top"))
|
|
26187
26897
|
] })
|
|
26188
26898
|
};
|
|
26189
26899
|
if (!canReusePaneDrawingNodes) {
|
|
26190
26900
|
paneDrawingNodesCacheRef.current = {
|
|
26191
26901
|
chartRects,
|
|
26192
|
-
|
|
26193
|
-
formControlRects,
|
|
26194
|
-
imageRects,
|
|
26902
|
+
drawingViewportSignature: drawingViewportCacheSignature,
|
|
26903
|
+
formControlRects: domFormControlRects,
|
|
26904
|
+
imageRects: domImageRects,
|
|
26195
26905
|
isChartsLoading,
|
|
26196
26906
|
palette,
|
|
26197
26907
|
readOnly,
|
|
@@ -26201,7 +26911,7 @@ function XlsxGrid({
|
|
|
26201
26911
|
selectedChartId,
|
|
26202
26912
|
selectedImageId,
|
|
26203
26913
|
selectionStroke,
|
|
26204
|
-
shapeRects,
|
|
26914
|
+
shapeRects: domShapeRects,
|
|
26205
26915
|
showImages,
|
|
26206
26916
|
value: paneDrawingNodes
|
|
26207
26917
|
};
|
|
@@ -26709,10 +27419,11 @@ function XlsxGrid({
|
|
|
26709
27419
|
style: canvasCornerBodyStyle
|
|
26710
27420
|
}
|
|
26711
27421
|
),
|
|
26712
|
-
|
|
27422
|
+
hasCanvasDomDrawingOverlays ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26713
27423
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasScrollOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
26714
27424
|
"div",
|
|
26715
27425
|
{
|
|
27426
|
+
ref: canvasScrollOverlayContentRef,
|
|
26716
27427
|
style: {
|
|
26717
27428
|
height: sheetContentHeight,
|
|
26718
27429
|
left: 0,
|
|
@@ -26720,6 +27431,7 @@ function XlsxGrid({
|
|
|
26720
27431
|
position: "absolute",
|
|
26721
27432
|
top: 0,
|
|
26722
27433
|
transform: `translate(${-drawingViewport.left - frozenPaneRight}px, ${-drawingViewport.top - frozenPaneBottom}px)`,
|
|
27434
|
+
transformOrigin: "0 0",
|
|
26723
27435
|
width: totalWidth
|
|
26724
27436
|
},
|
|
26725
27437
|
children: paneDrawingNodes.scroll
|
|
@@ -26728,6 +27440,7 @@ function XlsxGrid({
|
|
|
26728
27440
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasTopOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
26729
27441
|
"div",
|
|
26730
27442
|
{
|
|
27443
|
+
ref: canvasTopOverlayContentRef,
|
|
26731
27444
|
style: {
|
|
26732
27445
|
height: sheetContentHeight,
|
|
26733
27446
|
left: 0,
|
|
@@ -26735,6 +27448,7 @@ function XlsxGrid({
|
|
|
26735
27448
|
position: "absolute",
|
|
26736
27449
|
top: 0,
|
|
26737
27450
|
transform: `translate(${-drawingViewport.left - frozenPaneRight}px, ${-displayHeaderHeight}px)`,
|
|
27451
|
+
transformOrigin: "0 0",
|
|
26738
27452
|
width: totalWidth
|
|
26739
27453
|
},
|
|
26740
27454
|
children: paneDrawingNodes.top
|
|
@@ -26743,6 +27457,7 @@ function XlsxGrid({
|
|
|
26743
27457
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasLeftOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
26744
27458
|
"div",
|
|
26745
27459
|
{
|
|
27460
|
+
ref: canvasLeftOverlayContentRef,
|
|
26746
27461
|
style: {
|
|
26747
27462
|
height: sheetContentHeight,
|
|
26748
27463
|
left: 0,
|
|
@@ -26750,6 +27465,7 @@ function XlsxGrid({
|
|
|
26750
27465
|
position: "absolute",
|
|
26751
27466
|
top: 0,
|
|
26752
27467
|
transform: `translate(${-displayRowHeaderWidth}px, ${-drawingViewport.top - frozenPaneBottom}px)`,
|
|
27468
|
+
transformOrigin: "0 0",
|
|
26753
27469
|
width: totalWidth
|
|
26754
27470
|
},
|
|
26755
27471
|
children: paneDrawingNodes.left
|
|
@@ -26758,6 +27474,7 @@ function XlsxGrid({
|
|
|
26758
27474
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasCornerOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
26759
27475
|
"div",
|
|
26760
27476
|
{
|
|
27477
|
+
ref: canvasCornerOverlayContentRef,
|
|
26761
27478
|
style: {
|
|
26762
27479
|
height: sheetContentHeight,
|
|
26763
27480
|
left: 0,
|
|
@@ -26765,6 +27482,7 @@ function XlsxGrid({
|
|
|
26765
27482
|
position: "absolute",
|
|
26766
27483
|
top: 0,
|
|
26767
27484
|
transform: `translate(${-displayRowHeaderWidth}px, ${-displayHeaderHeight}px)`,
|
|
27485
|
+
transformOrigin: "0 0",
|
|
26768
27486
|
width: totalWidth
|
|
26769
27487
|
},
|
|
26770
27488
|
children: paneDrawingNodes.corner
|
|
@@ -27684,7 +28402,7 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27684
28402
|
if (!canvas) {
|
|
27685
28403
|
return false;
|
|
27686
28404
|
}
|
|
27687
|
-
const context = canvas.getContext("2d");
|
|
28405
|
+
const context = canvas.getContext("2d", { alpha: false });
|
|
27688
28406
|
if (!context) {
|
|
27689
28407
|
return false;
|
|
27690
28408
|
}
|
|
@@ -27708,9 +28426,10 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27708
28426
|
}
|
|
27709
28427
|
context.setTransform(dpr * scale, 0, 0, dpr * scale, 0, 0);
|
|
27710
28428
|
context.clearRect(0, 0, Math.max(1, sourceWidth), Math.max(1, sourceHeight));
|
|
28429
|
+
const thumbnailSheetSurface = resolveSheetSurface(sheet, palette);
|
|
27711
28430
|
context.fillStyle = palette.canvas;
|
|
27712
28431
|
context.fillRect(0, 0, Math.max(1, sourceWidth), Math.max(1, sourceHeight));
|
|
27713
|
-
context.fillStyle =
|
|
28432
|
+
context.fillStyle = thumbnailSheetSurface;
|
|
27714
28433
|
context.fillRect(rowHeaderWidth, headerHeight, Math.max(1, colAxis.totalSize), Math.max(1, rowAxis.totalSize));
|
|
27715
28434
|
if (includeHeaders) {
|
|
27716
28435
|
context.fillStyle = palette.headerSurface;
|
|
@@ -27831,8 +28550,8 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27831
28550
|
};
|
|
27832
28551
|
const canvasCellStyle = cellData.canvas ?? buildCanvasCellStyleCache(cellData.style);
|
|
27833
28552
|
const gradientFill = typeof cellData.style.backgroundImage === "string" ? resolveCanvasGradientFill(context, rect, cellData.style.backgroundImage) : null;
|
|
27834
|
-
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellData.style.backgroundColor === "string" ? cellData.style.backgroundColor :
|
|
27835
|
-
const hasExplicitCellFill = cellData.conditionalColorScale !== null || gradientFill !== null || typeof cellData.style.backgroundColor === "string" && cellData.style.backgroundColor !==
|
|
28553
|
+
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellData.style.backgroundColor === "string" ? cellData.style.backgroundColor : thumbnailSheetSurface);
|
|
28554
|
+
const hasExplicitCellFill = cellData.conditionalColorScale !== null || gradientFill !== null || typeof cellData.style.backgroundColor === "string" && cellData.style.backgroundColor !== thumbnailSheetSurface;
|
|
27836
28555
|
context.fillStyle = gradientFill ?? fillColor;
|
|
27837
28556
|
context.fillRect(rect.left, rect.top, rect.width, rect.height);
|
|
27838
28557
|
if (cellData.conditionalDataBar) {
|
|
@@ -27887,12 +28606,19 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27887
28606
|
if (canvasCellStyle.leftBorder) {
|
|
27888
28607
|
strokeCanvasBorderSide(context, "left", rect, canvasCellStyle.leftBorder);
|
|
27889
28608
|
}
|
|
28609
|
+
const rawText = cellData.value ?? "";
|
|
28610
|
+
const shouldDrawThumbnailContent = cellData.checkboxState != null || cellData.sparkline || rawText.length > 0 || cellData.conditionalIcon;
|
|
28611
|
+
if (!shouldDrawThumbnailContent) {
|
|
28612
|
+
continue;
|
|
28613
|
+
}
|
|
27890
28614
|
const padding = canvasCellStyle.padding;
|
|
27891
28615
|
const contentLeft = rect.left + padding.left;
|
|
27892
28616
|
const contentTop = rect.top + padding.top;
|
|
27893
28617
|
const contentWidth = Math.max(0, rect.width - padding.left - padding.right);
|
|
27894
28618
|
const contentHeight = Math.max(0, rect.height - padding.top - padding.bottom);
|
|
27895
|
-
|
|
28619
|
+
if (contentWidth <= 0 || contentHeight <= 0) {
|
|
28620
|
+
continue;
|
|
28621
|
+
}
|
|
27896
28622
|
context.save();
|
|
27897
28623
|
context.beginPath();
|
|
27898
28624
|
context.rect(contentLeft, contentTop, contentWidth, contentHeight);
|