@extend-ai/react-xlsx 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +975 -199
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +213 -0
- package/dist/index.d.ts +213 -0
- package/dist/index.js +975 -199
- package/dist/index.js.map +1 -1
- package/dist/xlsx-worker.js +67 -21
- package/dist/xlsx-worker.js.map +1 -1
- package/package.json +1 -1
package/dist/index.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
|
}
|
|
@@ -20988,12 +21166,14 @@ function XlsxGrid({
|
|
|
20988
21166
|
renderImageSelection,
|
|
20989
21167
|
renderTableHeaderMenu,
|
|
20990
21168
|
enableGestureZoom = true,
|
|
20991
|
-
experimentalCanvas =
|
|
21169
|
+
experimentalCanvas = true,
|
|
20992
21170
|
selectionColor,
|
|
20993
21171
|
selectionFillColor,
|
|
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) {
|
|
@@ -22428,17 +22709,17 @@ function XlsxGrid({
|
|
|
22428
22709
|
}, []);
|
|
22429
22710
|
const resolvePointerCellFromClient = React4.useCallback((clientX, clientY) => {
|
|
22430
22711
|
const geometryCell = resolvePointerCellFromGeometry(clientX, clientY);
|
|
22431
|
-
if (geometryCell
|
|
22432
|
-
return
|
|
22712
|
+
if (geometryCell) {
|
|
22713
|
+
return geometryCell;
|
|
22433
22714
|
}
|
|
22434
|
-
const resolvedCell = resolvePointerCellFromHitTest(clientX, clientY)
|
|
22715
|
+
const resolvedCell = resolvePointerCellFromHitTest(clientX, clientY);
|
|
22435
22716
|
return resolvedCell ? resolveMergeAnchorCell(resolvedCell) : null;
|
|
22436
|
-
}, [resolveMergeAnchorCell, resolvePointerCellFromGeometry, resolvePointerCellFromHitTest
|
|
22717
|
+
}, [resolveMergeAnchorCell, resolvePointerCellFromGeometry, resolvePointerCellFromHitTest]);
|
|
22437
22718
|
const resolveDraggedSelectionCell = React4.useCallback((dragState, clientX, clientY) => {
|
|
22438
22719
|
const geometryCell = resolvePointerCellFromGeometry(clientX, clientY);
|
|
22439
22720
|
const hitCell = resolvePointerCellFromHitTest(clientX, clientY);
|
|
22440
|
-
const actualRow = hitCell && rowIndexByActual.has(hitCell.row) ? hitCell.row :
|
|
22441
|
-
const actualCol =
|
|
22721
|
+
const actualRow = geometryCell?.row ?? (hitCell && rowIndexByActual.has(hitCell.row) ? hitCell.row : void 0);
|
|
22722
|
+
const actualCol = geometryCell?.col ?? hitCell?.col;
|
|
22442
22723
|
if (actualRow === void 0 || actualCol === void 0) {
|
|
22443
22724
|
return null;
|
|
22444
22725
|
}
|
|
@@ -22448,8 +22729,8 @@ function XlsxGrid({
|
|
|
22448
22729
|
if (dragState.axis === "column") {
|
|
22449
22730
|
return { row: dragState.originCell.row, col: actualCol };
|
|
22450
22731
|
}
|
|
22451
|
-
return
|
|
22452
|
-
}, [
|
|
22732
|
+
return { row: actualRow, col: actualCol };
|
|
22733
|
+
}, [resolvePointerCellFromGeometry, resolvePointerCellFromHitTest, rowIndexByActual]);
|
|
22453
22734
|
const resolveCellPointerOrigin = React4.useCallback((cell, rect, clientX, clientY) => {
|
|
22454
22735
|
const rowIndex = rowIndexByActual.get(cell.row);
|
|
22455
22736
|
const colIndex = colIndexByActual.get(cell.col);
|
|
@@ -22467,6 +22748,40 @@ function XlsxGrid({
|
|
|
22467
22748
|
originContentY: (rowPrefixSums[rowIndex] ?? 0) + clampContentOffset((clientY - rect.top) / contentScaleY, displayHeight)
|
|
22468
22749
|
};
|
|
22469
22750
|
}, [colIndexByActual, colPrefixSums, displayDefaultColWidth, displayDefaultRowHeight, displayEffectiveColWidths, displayEffectiveRowHeights, rowIndexByActual, rowPrefixSums]);
|
|
22751
|
+
const resolveCellPointerOriginFromClient = React4.useCallback((cell, clientX, clientY) => {
|
|
22752
|
+
const scroller = scrollRef.current;
|
|
22753
|
+
const rowIndex = rowIndexByActual.get(cell.row);
|
|
22754
|
+
const colIndex = colIndexByActual.get(cell.col);
|
|
22755
|
+
if (!scroller || rowIndex === void 0 || colIndex === void 0) {
|
|
22756
|
+
return null;
|
|
22757
|
+
}
|
|
22758
|
+
const scrollerRect = cachedScrollerRectRef.current ?? scroller.getBoundingClientRect();
|
|
22759
|
+
const pointerOffsetX = clientX - scrollerRect.left;
|
|
22760
|
+
const pointerOffsetY = clientY - scrollerRect.top;
|
|
22761
|
+
const localX = pointerOffsetX + (pointerOffsetX >= frozenPaneRight ? scroller.scrollLeft : 0);
|
|
22762
|
+
const localY = pointerOffsetY + (pointerOffsetY >= frozenPaneBottom ? scroller.scrollTop : 0);
|
|
22763
|
+
const displayWidth = displayEffectiveColWidths[colIndex] ?? displayDefaultColWidth;
|
|
22764
|
+
const displayHeight = displayEffectiveRowHeights[rowIndex] ?? displayDefaultRowHeight;
|
|
22765
|
+
return {
|
|
22766
|
+
contentScaleX: 1,
|
|
22767
|
+
contentScaleY: 1,
|
|
22768
|
+
originContentX: (colPrefixSums[colIndex] ?? 0) + clampContentOffset(localX - displayRowHeaderWidth - (colPrefixSums[colIndex] ?? 0), displayWidth),
|
|
22769
|
+
originContentY: (rowPrefixSums[rowIndex] ?? 0) + clampContentOffset(localY - displayHeaderHeight - (rowPrefixSums[rowIndex] ?? 0), displayHeight)
|
|
22770
|
+
};
|
|
22771
|
+
}, [
|
|
22772
|
+
colIndexByActual,
|
|
22773
|
+
colPrefixSums,
|
|
22774
|
+
displayDefaultColWidth,
|
|
22775
|
+
displayDefaultRowHeight,
|
|
22776
|
+
displayEffectiveColWidths,
|
|
22777
|
+
displayEffectiveRowHeights,
|
|
22778
|
+
displayHeaderHeight,
|
|
22779
|
+
displayRowHeaderWidth,
|
|
22780
|
+
frozenPaneBottom,
|
|
22781
|
+
frozenPaneRight,
|
|
22782
|
+
rowIndexByActual,
|
|
22783
|
+
rowPrefixSums
|
|
22784
|
+
]);
|
|
22470
22785
|
const resolveRowPointerOrigin = React4.useCallback((actualRow, rect, clientY) => {
|
|
22471
22786
|
const rowIndex = rowIndexByActual.get(actualRow);
|
|
22472
22787
|
if (rowIndex === void 0) {
|
|
@@ -23043,14 +23358,14 @@ function XlsxGrid({
|
|
|
23043
23358
|
},
|
|
23044
23359
|
left: {
|
|
23045
23360
|
cols: frozenColItems,
|
|
23046
|
-
rows:
|
|
23361
|
+
rows: scrollRowItems
|
|
23047
23362
|
},
|
|
23048
23363
|
scroll: {
|
|
23049
|
-
cols:
|
|
23050
|
-
rows:
|
|
23364
|
+
cols: scrollColItems,
|
|
23365
|
+
rows: scrollRowItems
|
|
23051
23366
|
},
|
|
23052
23367
|
top: {
|
|
23053
|
-
cols:
|
|
23368
|
+
cols: scrollColItems,
|
|
23054
23369
|
rows: frozenRowItems
|
|
23055
23370
|
}
|
|
23056
23371
|
};
|
|
@@ -23184,6 +23499,51 @@ function XlsxGrid({
|
|
|
23184
23499
|
visibleRows
|
|
23185
23500
|
]
|
|
23186
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
|
+
]);
|
|
23187
23547
|
const resolveMountedCellOverlayRect = React4.useCallback((element) => {
|
|
23188
23548
|
const wrapper = wrapperRef.current;
|
|
23189
23549
|
if (!wrapper) {
|
|
@@ -23215,10 +23575,11 @@ function XlsxGrid({
|
|
|
23215
23575
|
}, [resolveMountedCellOverlayRect]);
|
|
23216
23576
|
const resolveGeometryOverlayRect = React4.useCallback((range) => {
|
|
23217
23577
|
const normalized = normalizeRange2(range);
|
|
23218
|
-
const startCell = resolveMergeAnchorCell(normalized.start);
|
|
23219
23578
|
const isSingleCellSelection = normalized.start.row === normalized.end.row && normalized.start.col === normalized.end.col;
|
|
23220
|
-
const
|
|
23221
|
-
const
|
|
23579
|
+
const isMergedSecondarySelection = isSingleCellSelection ? worksheet?.isMergedSecondary(normalized.start.row, normalized.start.col) === true : false;
|
|
23580
|
+
const startCell = isSingleCellSelection && !isMergedSecondarySelection ? resolveMergeAnchorCell(normalized.start) : normalized.start;
|
|
23581
|
+
const merge = isSingleCellSelection && !isMergedSecondarySelection ? worksheet?.getMergeSpan(startCell.row, startCell.col) : null;
|
|
23582
|
+
const endCell = isSingleCellSelection && !isMergedSecondarySelection ? {
|
|
23222
23583
|
row: startCell.row + Math.max(1, merge?.rowSpan ?? 1) - 1,
|
|
23223
23584
|
col: startCell.col + Math.max(1, merge?.colSpan ?? 1) - 1
|
|
23224
23585
|
} : normalized.end;
|
|
@@ -23850,13 +24211,14 @@ function XlsxGrid({
|
|
|
23850
24211
|
}
|
|
23851
24212
|
event.preventDefault();
|
|
23852
24213
|
focusGrid();
|
|
24214
|
+
const targetCell = event.currentTarget.colSpan > 1 || event.currentTarget.rowSpan > 1 ? resolvePointerCellFromGeometry(event.clientX, event.clientY) ?? cell : cell;
|
|
23853
24215
|
const currentSelection = selectionRef.current;
|
|
23854
|
-
const anchor = event.shiftKey && currentSelection ? currentSelection.start :
|
|
23855
|
-
const initialRange = normalizeRange2({ start: anchor, end:
|
|
23856
|
-
const isActive = isSameCell(activeCellRef.current,
|
|
24216
|
+
const anchor = event.shiftKey && currentSelection ? currentSelection.start : targetCell;
|
|
24217
|
+
const initialRange = normalizeRange2({ start: anchor, end: targetCell });
|
|
24218
|
+
const isActive = isSameCell(activeCellRef.current, targetCell);
|
|
23857
24219
|
const committedOnPointerDown = !isActive || !editingCellRef.current;
|
|
23858
|
-
const pointerOrigin = resolveCellPointerOrigin(cell, event.currentTarget.getBoundingClientRect(), event.clientX, event.clientY);
|
|
23859
|
-
const originOverlayRect = resolveMountedCellOverlayRect(event.currentTarget);
|
|
24220
|
+
const pointerOrigin = targetCell.row === cell.row && targetCell.col === cell.col ? resolveCellPointerOrigin(cell, event.currentTarget.getBoundingClientRect(), event.clientX, event.clientY) : resolveCellPointerOriginFromClient(targetCell, event.clientX, event.clientY);
|
|
24221
|
+
const originOverlayRect = targetCell.row === cell.row && targetCell.col === cell.col ? resolveMountedCellOverlayRect(event.currentTarget) : resolveOverlayRect(initialRange);
|
|
23860
24222
|
if (!pointerOrigin) {
|
|
23861
24223
|
return;
|
|
23862
24224
|
}
|
|
@@ -23864,7 +24226,7 @@ function XlsxGrid({
|
|
|
23864
24226
|
event.pointerId,
|
|
23865
24227
|
anchor,
|
|
23866
24228
|
"cell",
|
|
23867
|
-
|
|
24229
|
+
targetCell,
|
|
23868
24230
|
pointerOrigin,
|
|
23869
24231
|
originOverlayRect,
|
|
23870
24232
|
committedOnPointerDown,
|
|
@@ -23872,11 +24234,25 @@ function XlsxGrid({
|
|
|
23872
24234
|
event.clientX,
|
|
23873
24235
|
event.clientY
|
|
23874
24236
|
);
|
|
23875
|
-
|
|
24237
|
+
if (targetCell.row === cell.row && targetCell.col === cell.col) {
|
|
24238
|
+
applyPreviewOverlayFromElement(event.currentTarget, initialRange);
|
|
24239
|
+
} else {
|
|
24240
|
+
applyPreviewOverlay(initialRange);
|
|
24241
|
+
}
|
|
23876
24242
|
if (committedOnPointerDown) {
|
|
23877
24243
|
commitSelectionRange(initialRange);
|
|
23878
24244
|
}
|
|
23879
|
-
}, [
|
|
24245
|
+
}, [
|
|
24246
|
+
applyPreviewOverlay,
|
|
24247
|
+
applyPreviewOverlayFromElement,
|
|
24248
|
+
commitSelectionRange,
|
|
24249
|
+
focusGrid,
|
|
24250
|
+
resolveCellPointerOrigin,
|
|
24251
|
+
resolveCellPointerOriginFromClient,
|
|
24252
|
+
resolveMountedCellOverlayRect,
|
|
24253
|
+
resolveOverlayRect,
|
|
24254
|
+
resolvePointerCellFromGeometry
|
|
24255
|
+
]);
|
|
23880
24256
|
const handleRowPointerDown = React4.useCallback((event, actualRow) => {
|
|
23881
24257
|
if (event.button !== 0 || firstVisibleCol === void 0 || lastVisibleCol === void 0) {
|
|
23882
24258
|
return;
|
|
@@ -24036,6 +24412,24 @@ function XlsxGrid({
|
|
|
24036
24412
|
rowPrefixSums,
|
|
24037
24413
|
stickyTopByRow
|
|
24038
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;
|
|
24039
24433
|
const canvasColumnHeaderCells = React4.useMemo(
|
|
24040
24434
|
() => canvasVisibleColItems.flatMap((column) => {
|
|
24041
24435
|
const rect = resolveCanvasColumnHeaderRect(column.actualCol);
|
|
@@ -24048,7 +24442,7 @@ function XlsxGrid({
|
|
|
24048
24442
|
height: displayHeaderHeight,
|
|
24049
24443
|
isFrozen,
|
|
24050
24444
|
left: rect.left,
|
|
24051
|
-
localLeft: rect.left - (isFrozen ? displayRowHeaderWidth :
|
|
24445
|
+
localLeft: rect.left - (isFrozen ? displayRowHeaderWidth : scrollBodyCanvasLeft),
|
|
24052
24446
|
width: rect.width
|
|
24053
24447
|
}];
|
|
24054
24448
|
}),
|
|
@@ -24056,8 +24450,8 @@ function XlsxGrid({
|
|
|
24056
24450
|
canvasVisibleColItems,
|
|
24057
24451
|
displayHeaderHeight,
|
|
24058
24452
|
displayRowHeaderWidth,
|
|
24059
|
-
frozenPaneRight,
|
|
24060
24453
|
resolveCanvasColumnHeaderRect,
|
|
24454
|
+
scrollBodyCanvasLeft,
|
|
24061
24455
|
stickyLeftByCol
|
|
24062
24456
|
]
|
|
24063
24457
|
);
|
|
@@ -24072,15 +24466,15 @@ function XlsxGrid({
|
|
|
24072
24466
|
actualRow: row.actualRow,
|
|
24073
24467
|
height: rect.height,
|
|
24074
24468
|
isFrozen,
|
|
24075
|
-
localTop: rect.top - (isFrozen ? displayHeaderHeight :
|
|
24469
|
+
localTop: rect.top - (isFrozen ? displayHeaderHeight : scrollBodyCanvasTop),
|
|
24076
24470
|
top: rect.top
|
|
24077
24471
|
}];
|
|
24078
24472
|
}),
|
|
24079
24473
|
[
|
|
24080
24474
|
canvasVisibleRowItems,
|
|
24081
24475
|
displayHeaderHeight,
|
|
24082
|
-
frozenPaneBottom,
|
|
24083
24476
|
resolveCanvasRowHeaderRect,
|
|
24477
|
+
scrollBodyCanvasTop,
|
|
24084
24478
|
stickyTopByRow
|
|
24085
24479
|
]
|
|
24086
24480
|
);
|
|
@@ -24347,10 +24741,46 @@ function XlsxGrid({
|
|
|
24347
24741
|
rowPrefixSums,
|
|
24348
24742
|
startCellSelection
|
|
24349
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
|
+
}, []);
|
|
24350
24772
|
React4.useLayoutEffect(() => {
|
|
24351
24773
|
if (!experimentalCanvas) {
|
|
24352
24774
|
return;
|
|
24353
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;
|
|
24354
24784
|
const dpr = typeof window === "undefined" ? 1 : Math.max(1, window.devicePixelRatio || 1);
|
|
24355
24785
|
function configureCanvas(canvas, width, height, options) {
|
|
24356
24786
|
if (!canvas) {
|
|
@@ -24370,7 +24800,7 @@ function XlsxGrid({
|
|
|
24370
24800
|
if (canvas.style.height !== `${height}px`) {
|
|
24371
24801
|
canvas.style.height = `${height}px`;
|
|
24372
24802
|
}
|
|
24373
|
-
const context = canvas.getContext("2d");
|
|
24803
|
+
const context = canvas.getContext("2d", { alpha: false });
|
|
24374
24804
|
if (!context) {
|
|
24375
24805
|
return null;
|
|
24376
24806
|
}
|
|
@@ -24389,6 +24819,7 @@ function XlsxGrid({
|
|
|
24389
24819
|
const rangeSignature = buildRangeSignature(normalizedVisibleRange);
|
|
24390
24820
|
const nextBodyCanvasSignature = {
|
|
24391
24821
|
activeSheet: activeSheet ?? null,
|
|
24822
|
+
bakedDrawingSignature: bakedCanvasDrawingSignature,
|
|
24392
24823
|
bodyHeight,
|
|
24393
24824
|
bodyWidth,
|
|
24394
24825
|
colSignature: buildRenderedAxisSignature(canvasVisibleColItems, (item) => item.index),
|
|
@@ -24416,10 +24847,10 @@ function XlsxGrid({
|
|
|
24416
24847
|
const previousBodyCanvasSignature = paintedBodyCanvasSignatureRef.current;
|
|
24417
24848
|
const previousHeaderCanvasSignature = paintedHeaderCanvasSignatureRef.current;
|
|
24418
24849
|
const previousPaintedViewport = paintedDrawingViewportRef.current;
|
|
24419
|
-
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);
|
|
24420
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);
|
|
24421
24852
|
const canBlitBody = Boolean(
|
|
24422
|
-
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
|
|
24423
24854
|
);
|
|
24424
24855
|
const canBlitTopHeader = Boolean(
|
|
24425
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
|
|
@@ -24430,49 +24861,37 @@ function XlsxGrid({
|
|
|
24430
24861
|
if (!shouldRepaintBody && !shouldRepaintHeaders) {
|
|
24431
24862
|
return;
|
|
24432
24863
|
}
|
|
24433
|
-
const scrollBodyCanvasWidth2 = Math.max(0, drawingViewport.width - frozenPaneRight);
|
|
24434
|
-
const scrollBodyCanvasHeight2 = Math.max(0, drawingViewport.height - frozenPaneBottom);
|
|
24435
|
-
const topBodyCanvasWidth2 = scrollBodyCanvasWidth2;
|
|
24436
|
-
const topBodyCanvasHeight2 = Math.max(0, frozenPaneBottom - displayHeaderHeight);
|
|
24437
|
-
const leftBodyCanvasWidth2 = Math.max(0, frozenPaneRight - displayRowHeaderWidth);
|
|
24438
|
-
const leftBodyCanvasHeight2 = scrollBodyCanvasHeight2;
|
|
24439
|
-
const cornerBodyCanvasWidth2 = leftBodyCanvasWidth2;
|
|
24440
|
-
const cornerBodyCanvasHeight2 = topBodyCanvasHeight2;
|
|
24441
|
-
const topFrozenHeaderCanvasWidth2 = leftBodyCanvasWidth2;
|
|
24442
|
-
const topScrollHeaderCanvasWidth2 = scrollBodyCanvasWidth2;
|
|
24443
|
-
const leftFrozenHeaderCanvasHeight2 = topBodyCanvasHeight2;
|
|
24444
|
-
const leftScrollHeaderCanvasHeight2 = scrollBodyCanvasHeight2;
|
|
24445
24864
|
const paneBounds = {
|
|
24446
24865
|
corner: {
|
|
24447
|
-
height:
|
|
24866
|
+
height: cornerBodyCanvasHeight,
|
|
24448
24867
|
left: displayRowHeaderWidth,
|
|
24449
24868
|
top: displayHeaderHeight,
|
|
24450
|
-
width:
|
|
24869
|
+
width: cornerBodyCanvasWidth
|
|
24451
24870
|
},
|
|
24452
24871
|
left: {
|
|
24453
|
-
height:
|
|
24872
|
+
height: leftBodyCanvasHeight,
|
|
24454
24873
|
left: displayRowHeaderWidth,
|
|
24455
|
-
top:
|
|
24456
|
-
width:
|
|
24874
|
+
top: scrollBodyCanvasTop,
|
|
24875
|
+
width: leftBodyCanvasWidth
|
|
24457
24876
|
},
|
|
24458
24877
|
scroll: {
|
|
24459
|
-
height:
|
|
24460
|
-
left:
|
|
24461
|
-
top:
|
|
24462
|
-
width:
|
|
24878
|
+
height: scrollBodyCanvasHeight,
|
|
24879
|
+
left: scrollBodyCanvasLeft,
|
|
24880
|
+
top: scrollBodyCanvasTop,
|
|
24881
|
+
width: scrollBodyCanvasWidth
|
|
24463
24882
|
},
|
|
24464
24883
|
top: {
|
|
24465
|
-
height:
|
|
24466
|
-
left:
|
|
24884
|
+
height: topBodyCanvasHeight,
|
|
24885
|
+
left: scrollBodyCanvasLeft,
|
|
24467
24886
|
top: displayHeaderHeight,
|
|
24468
|
-
width:
|
|
24887
|
+
width: topBodyCanvasWidth
|
|
24469
24888
|
}
|
|
24470
24889
|
};
|
|
24471
24890
|
const bodyContexts = shouldRepaintBody ? {
|
|
24472
|
-
corner: configureCanvas(cornerBodyCanvasRef.current,
|
|
24473
|
-
left: configureCanvas(leftBodyCanvasRef.current,
|
|
24474
|
-
scroll: configureCanvas(scrollBodyCanvasRef.current,
|
|
24475
|
-
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 })
|
|
24476
24895
|
} : {
|
|
24477
24896
|
corner: null,
|
|
24478
24897
|
left: null,
|
|
@@ -24480,21 +24899,21 @@ function XlsxGrid({
|
|
|
24480
24899
|
top: null
|
|
24481
24900
|
};
|
|
24482
24901
|
const topHeaderContexts = shouldRepaintHeaders ? {
|
|
24483
|
-
frozen: configureCanvas(topFrozenHeaderCanvasRef.current,
|
|
24484
|
-
scroll: configureCanvas(topScrollHeaderCanvasRef.current,
|
|
24902
|
+
frozen: configureCanvas(topFrozenHeaderCanvasRef.current, topFrozenHeaderCanvasWidth, headerHeight),
|
|
24903
|
+
scroll: configureCanvas(topScrollHeaderCanvasRef.current, topScrollHeaderCanvasWidth, headerHeight, { clear: !canBlitTopHeader })
|
|
24485
24904
|
} : {
|
|
24486
24905
|
frozen: null,
|
|
24487
24906
|
scroll: null
|
|
24488
24907
|
};
|
|
24489
24908
|
const leftHeaderContexts = shouldRepaintHeaders ? {
|
|
24490
|
-
frozen: configureCanvas(leftFrozenHeaderCanvasRef.current, rowHeaderWidth,
|
|
24491
|
-
scroll: configureCanvas(leftScrollHeaderCanvasRef.current, rowHeaderWidth,
|
|
24909
|
+
frozen: configureCanvas(leftFrozenHeaderCanvasRef.current, rowHeaderWidth, leftFrozenHeaderCanvasHeight),
|
|
24910
|
+
scroll: configureCanvas(leftScrollHeaderCanvasRef.current, rowHeaderWidth, leftScrollHeaderCanvasHeight, { clear: !canBlitLeftHeader })
|
|
24492
24911
|
} : {
|
|
24493
24912
|
frozen: null,
|
|
24494
24913
|
scroll: null
|
|
24495
24914
|
};
|
|
24496
24915
|
const cornerContext = shouldRepaintHeaders ? configureCanvas(cornerHeaderCanvasRef.current, rowHeaderWidth, headerHeight) : null;
|
|
24497
|
-
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)) {
|
|
24498
24917
|
return;
|
|
24499
24918
|
}
|
|
24500
24919
|
const showGridLines = activeSheet?.showGridLines ?? true;
|
|
@@ -24511,10 +24930,282 @@ function XlsxGrid({
|
|
|
24511
24930
|
scroll: [],
|
|
24512
24931
|
top: []
|
|
24513
24932
|
};
|
|
24514
|
-
let topScrollHeaderDirtyRects = buildFullCanvasDirtyRect(
|
|
24515
|
-
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
|
+
};
|
|
24516
25206
|
const cellPaneOrder = ["scroll", "top", "left", "corner"];
|
|
24517
25207
|
if (shouldRepaintBody) {
|
|
25208
|
+
canvasProfileBodyStart = canvasProfileTarget ? performance.now() : 0;
|
|
24518
25209
|
for (const pane of Object.keys(bodyContexts)) {
|
|
24519
25210
|
const context = bodyContexts[pane];
|
|
24520
25211
|
const bounds = paneBounds[pane];
|
|
@@ -24545,6 +25236,7 @@ function XlsxGrid({
|
|
|
24545
25236
|
context.clearRect(0, 0, bounds.width, bounds.height);
|
|
24546
25237
|
}
|
|
24547
25238
|
bodyDirtyRectsByPane[pane] = dirtyRects;
|
|
25239
|
+
canvasProfileDirtyRects += dirtyRects.length;
|
|
24548
25240
|
if (dirtyRects.length === 0) {
|
|
24549
25241
|
continue;
|
|
24550
25242
|
}
|
|
@@ -24561,6 +25253,22 @@ function XlsxGrid({
|
|
|
24561
25253
|
if (!paneContext || paneDirtyRects.length === 0 || paneBoundsForCell.width <= 0 || paneBoundsForCell.height <= 0 || paneAxisItems.rows.length === 0 || paneAxisItems.cols.length === 0) {
|
|
24562
25254
|
continue;
|
|
24563
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
|
+
};
|
|
24564
25272
|
const drawnMergedAnchorKeys = /* @__PURE__ */ new Set();
|
|
24565
25273
|
for (const rowItem of paneAxisItems.rows) {
|
|
24566
25274
|
for (const colItem of paneAxisItems.cols) {
|
|
@@ -24568,6 +25276,33 @@ function XlsxGrid({
|
|
|
24568
25276
|
const anchorCell = resolveMergeAnchorCell(cell);
|
|
24569
25277
|
const anchorKey = `${anchorCell.row}:${anchorCell.col}`;
|
|
24570
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;
|
|
24571
25306
|
let cellData = getCellData(drawCell.row, drawCell.col);
|
|
24572
25307
|
if ((cellData.colSpan || cellData.rowSpan) && drawnMergedAnchorKeys.has(anchorKey)) {
|
|
24573
25308
|
continue;
|
|
@@ -24578,16 +25313,9 @@ function XlsxGrid({
|
|
|
24578
25313
|
if (cellData.colSpan || cellData.rowSpan) {
|
|
24579
25314
|
drawnMergedAnchorKeys.add(anchorKey);
|
|
24580
25315
|
}
|
|
24581
|
-
const drawRowIndex = rowIndexByActual.get(drawCell.row);
|
|
24582
|
-
const drawColIndex = colIndexByActual.get(drawCell.col);
|
|
24583
|
-
if (drawRowIndex === void 0 || drawColIndex === void 0) {
|
|
24584
|
-
continue;
|
|
24585
|
-
}
|
|
24586
25316
|
const displayRect = cellData.colSpan || cellData.rowSpan ? resolveCellDisplayRect(drawCell) : null;
|
|
24587
|
-
const baseLeft = displayRect?.left ??
|
|
24588
|
-
const baseTop = displayRect?.top ??
|
|
24589
|
-
const useFrozenHorizontalPosition = pane === "left" || pane === "corner";
|
|
24590
|
-
const useFrozenVerticalPosition = pane === "top" || pane === "corner";
|
|
25317
|
+
const baseLeft = displayRect?.left ?? baseCellLeft;
|
|
25318
|
+
const baseTop = displayRect?.top ?? baseCellTop;
|
|
24591
25319
|
const localRect = {
|
|
24592
25320
|
height: displayRect?.height ?? (displayEffectiveRowHeights[drawRowIndex] ?? rowItem.size),
|
|
24593
25321
|
left: (useFrozenHorizontalPosition ? stickyLeftByCol.get(drawCell.col) ?? baseLeft - drawingViewport.left : baseLeft - drawingViewport.left) - paneBoundsForCell.left,
|
|
@@ -24599,13 +25327,18 @@ function XlsxGrid({
|
|
|
24599
25327
|
continue;
|
|
24600
25328
|
}
|
|
24601
25329
|
if (!intersectsCanvasDirtyRects(localRect.left, localRect.top, drawableWidth, localRect.height, paneDirtyRects)) {
|
|
25330
|
+
canvasProfileCulledCells += 1;
|
|
24602
25331
|
continue;
|
|
24603
25332
|
}
|
|
25333
|
+
canvasProfilePaintedCells += 1;
|
|
24604
25334
|
const cellStyle = cellData.style;
|
|
24605
25335
|
const canvasCellStyle = cellData.canvas ?? buildCanvasCellStyleCache(cellStyle);
|
|
24606
25336
|
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellStyle.backgroundColor === "string" ? cellStyle.backgroundColor : sheetSurface);
|
|
24607
25337
|
const gradientFill = !cellData.conditionalColorScale && typeof cellStyle.backgroundImage === "string" ? resolveCanvasGradientFill(paneContext, localRect, cellStyle.backgroundImage) : null;
|
|
24608
25338
|
const hasExplicitCellFill = cellData.conditionalColorScale !== null || gradientFill !== null || typeof cellStyle.backgroundColor === "string" && cellStyle.backgroundColor !== sheetSurface;
|
|
25339
|
+
if (hasExplicitCellFill || cellData.chartHighlight) {
|
|
25340
|
+
flushPendingGridlines();
|
|
25341
|
+
}
|
|
24609
25342
|
paneContext.fillStyle = gradientFill ?? fillColor;
|
|
24610
25343
|
paneContext.fillRect(localRect.left, localRect.top, localRect.width, localRect.height);
|
|
24611
25344
|
if (cellData.chartHighlight) {
|
|
@@ -24651,10 +25384,8 @@ function XlsxGrid({
|
|
|
24651
25384
|
const bottomNeighborTopBorder = bottomNeighborData?.isMergedSecondary ? null : bottomNeighborData?.canvas?.topBorder ?? parseCanvasBorderDeclaration(bottomNeighborData?.style.borderTop);
|
|
24652
25385
|
const resolvedRightBorder = resolveCanvasBoundaryBorder(rightBorder, rightNeighborLeftBorder);
|
|
24653
25386
|
const resolvedBottomBorder = resolveCanvasBoundaryBorder(bottomBorder, bottomNeighborTopBorder);
|
|
24654
|
-
if (showGridLines && !hasExplicitCellFill) {
|
|
24655
|
-
|
|
24656
|
-
paneContext.lineWidth = 1;
|
|
24657
|
-
paneContext.beginPath();
|
|
25387
|
+
if (showGridLines && !hasExplicitCellFill && (!resolvedRightBorder || !resolvedBottomBorder)) {
|
|
25388
|
+
enqueueGridlinePath();
|
|
24658
25389
|
if (!resolvedRightBorder) {
|
|
24659
25390
|
paneContext.moveTo(localRect.left + localRect.width - 0.5, localRect.top);
|
|
24660
25391
|
paneContext.lineTo(localRect.left + localRect.width - 0.5, localRect.top + localRect.height);
|
|
@@ -24663,7 +25394,9 @@ function XlsxGrid({
|
|
|
24663
25394
|
paneContext.moveTo(localRect.left, localRect.top + localRect.height - 0.5);
|
|
24664
25395
|
paneContext.lineTo(localRect.left + localRect.width, localRect.top + localRect.height - 0.5);
|
|
24665
25396
|
}
|
|
24666
|
-
|
|
25397
|
+
}
|
|
25398
|
+
if (topBorder || resolvedRightBorder || resolvedBottomBorder || leftBorder || cellData.chartHighlight) {
|
|
25399
|
+
flushPendingGridlines();
|
|
24667
25400
|
}
|
|
24668
25401
|
if (topBorder && drawRowIndex === 0) {
|
|
24669
25402
|
strokeCanvasBorderSide(paneContext, "top", localRect, topBorder);
|
|
@@ -24696,17 +25429,26 @@ function XlsxGrid({
|
|
|
24696
25429
|
strokeCanvasBorderSide(paneContext, "left", localRect, highlightBorder);
|
|
24697
25430
|
}
|
|
24698
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
|
+
}
|
|
24699
25437
|
const padding = canvasCellStyle.padding;
|
|
24700
25438
|
const contentLeft = localRect.left + padding.left;
|
|
24701
25439
|
const contentTop = localRect.top + padding.top;
|
|
24702
25440
|
const contentWidth = Math.max(0, localRect.width - padding.left - padding.right);
|
|
24703
25441
|
const contentHeight = Math.max(0, localRect.height - padding.top - padding.bottom);
|
|
25442
|
+
if (contentWidth <= 0 || contentHeight <= 0) {
|
|
25443
|
+
continue;
|
|
25444
|
+
}
|
|
24704
25445
|
const activeFontSizePx = cellData.shrinkToFitFontSizePx ?? resolveCanvasFontSizePx(cellStyle, 12 * zoomFactor);
|
|
24705
25446
|
const textClipOverscan = Math.max(
|
|
24706
25447
|
1,
|
|
24707
25448
|
zoomFactor * 1.5,
|
|
24708
25449
|
activeFontSizePx * (cellData.textRotationDeg ? 0.75 : 0.18)
|
|
24709
25450
|
);
|
|
25451
|
+
flushPendingGridlines();
|
|
24710
25452
|
paneContext.save();
|
|
24711
25453
|
paneContext.beginPath();
|
|
24712
25454
|
paneContext.rect(
|
|
@@ -24838,7 +25580,6 @@ function XlsxGrid({
|
|
|
24838
25580
|
const trailingInset = (cellData.conditionalIcon ? 18 * zoomFactor : 0) + (cellData.isTableHeader ? 16 * zoomFactor : 0);
|
|
24839
25581
|
const spillMaxWidth = cellData.spillWidth && cellData.spillWidth > 0 ? Math.max(0, cellData.spillWidth - trailingInset) : null;
|
|
24840
25582
|
const maxTextWidth = spillMaxWidth ?? Math.max(0, contentWidth - trailingInset);
|
|
24841
|
-
const rawText = cellData.value ?? "";
|
|
24842
25583
|
const textColor = canvasCellStyle.textColor;
|
|
24843
25584
|
const shouldEllipsizeText = canvasCellStyle.textOverflowEllipsis;
|
|
24844
25585
|
const shouldWrapText = canvasCellStyle.usesWrappedText || rawText.includes("\n");
|
|
@@ -24870,7 +25611,7 @@ function XlsxGrid({
|
|
|
24870
25611
|
const textY = textBlockTop + lineIndex * lineHeight + lineHeight / 2;
|
|
24871
25612
|
paneContext.fillText(line, textX, textY);
|
|
24872
25613
|
if (canvasCellStyle.textDecoration?.includes("underline") && line.length > 0) {
|
|
24873
|
-
const measured = Math.min(maxTextWidth, paneContext
|
|
25614
|
+
const measured = Math.min(maxTextWidth, measureCanvasTextWidth(paneContext, line));
|
|
24874
25615
|
const underlineStartX = align === "right" ? textX - measured : align === "center" ? textX - measured / 2 : textX;
|
|
24875
25616
|
paneContext.beginPath();
|
|
24876
25617
|
paneContext.moveTo(underlineStartX, textY + Math.max(2, lineHeight * 0.24));
|
|
@@ -24904,7 +25645,7 @@ function XlsxGrid({
|
|
|
24904
25645
|
const textY = contentTop + contentHeight / 2;
|
|
24905
25646
|
paneContext.fillText(text, textX, textY);
|
|
24906
25647
|
if (canvasCellStyle.textDecoration?.includes("underline") && text.length > 0) {
|
|
24907
|
-
const measured = shouldEllipsizeText ? Math.min(maxTextWidth, paneContext
|
|
25648
|
+
const measured = shouldEllipsizeText ? Math.min(maxTextWidth, measureCanvasTextWidth(paneContext, text)) : measureCanvasTextWidth(paneContext, text);
|
|
24908
25649
|
const underlineStartX = align === "right" ? textX - measured : align === "center" ? textX - measured / 2 : textX;
|
|
24909
25650
|
paneContext.beginPath();
|
|
24910
25651
|
paneContext.moveTo(underlineStartX, textY + 6 * zoomFactor);
|
|
@@ -24929,6 +25670,7 @@ function XlsxGrid({
|
|
|
24929
25670
|
paneContext.restore();
|
|
24930
25671
|
}
|
|
24931
25672
|
}
|
|
25673
|
+
flushPendingGridlines();
|
|
24932
25674
|
}
|
|
24933
25675
|
for (const pane of cellPaneOrder) {
|
|
24934
25676
|
const paneContext = bodyContexts[pane];
|
|
@@ -24946,7 +25688,7 @@ function XlsxGrid({
|
|
|
24946
25688
|
paneContext.textBaseline = "middle";
|
|
24947
25689
|
paneContext.fillText(spillText.text, spillText.textX, spillText.textY);
|
|
24948
25690
|
if (spillText.textDecoration?.includes("underline") && spillText.text.length > 0) {
|
|
24949
|
-
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);
|
|
24950
25692
|
const underlineStartX = spillText.align === "right" ? spillText.textX - measured : spillText.align === "center" ? spillText.textX - measured / 2 : spillText.textX;
|
|
24951
25693
|
paneContext.beginPath();
|
|
24952
25694
|
paneContext.moveTo(underlineStartX, spillText.underlineY);
|
|
@@ -24958,6 +25700,14 @@ function XlsxGrid({
|
|
|
24958
25700
|
paneContext.restore();
|
|
24959
25701
|
}
|
|
24960
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;
|
|
24961
25711
|
}
|
|
24962
25712
|
if (shouldRepaintHeaders && cornerContext) {
|
|
24963
25713
|
const topFrozenHeaderContext = topHeaderContexts.frozen;
|
|
@@ -24972,7 +25722,7 @@ function XlsxGrid({
|
|
|
24972
25722
|
topScrollHeaderContext,
|
|
24973
25723
|
bufferCanvas,
|
|
24974
25724
|
dpr,
|
|
24975
|
-
|
|
25725
|
+
topScrollHeaderCanvasWidth,
|
|
24976
25726
|
headerHeight,
|
|
24977
25727
|
drawingViewport.left - previousPaintedViewport.left,
|
|
24978
25728
|
0
|
|
@@ -24991,7 +25741,7 @@ function XlsxGrid({
|
|
|
24991
25741
|
bufferCanvas,
|
|
24992
25742
|
dpr,
|
|
24993
25743
|
rowHeaderWidth,
|
|
24994
|
-
|
|
25744
|
+
leftScrollHeaderCanvasHeight,
|
|
24995
25745
|
0,
|
|
24996
25746
|
drawingViewport.top - previousPaintedViewport.top
|
|
24997
25747
|
);
|
|
@@ -25000,11 +25750,11 @@ function XlsxGrid({
|
|
|
25000
25750
|
}
|
|
25001
25751
|
}
|
|
25002
25752
|
}
|
|
25003
|
-
if (topFrozenHeaderContext &&
|
|
25753
|
+
if (topFrozenHeaderContext && topFrozenHeaderCanvasWidth > 0) {
|
|
25004
25754
|
topFrozenHeaderContext.fillStyle = palette.headerSurface;
|
|
25005
|
-
topFrozenHeaderContext.fillRect(0, 0,
|
|
25755
|
+
topFrozenHeaderContext.fillRect(0, 0, topFrozenHeaderCanvasWidth, headerHeight);
|
|
25006
25756
|
}
|
|
25007
|
-
if (topScrollHeaderContext &&
|
|
25757
|
+
if (topScrollHeaderContext && topScrollHeaderCanvasWidth > 0) {
|
|
25008
25758
|
topScrollHeaderContext.fillStyle = palette.headerSurface;
|
|
25009
25759
|
for (const dirtyRect of topScrollHeaderDirtyRects) {
|
|
25010
25760
|
topScrollHeaderContext.fillRect(dirtyRect.left, dirtyRect.top, dirtyRect.width, dirtyRect.height);
|
|
@@ -25023,7 +25773,7 @@ function XlsxGrid({
|
|
|
25023
25773
|
if (!paneContext) {
|
|
25024
25774
|
continue;
|
|
25025
25775
|
}
|
|
25026
|
-
if (column.localLeft + column.width < 0 || column.localLeft > (column.isFrozen ?
|
|
25776
|
+
if (column.localLeft + column.width < 0 || column.localLeft > (column.isFrozen ? topFrozenHeaderCanvasWidth : topScrollHeaderCanvasWidth)) {
|
|
25027
25777
|
continue;
|
|
25028
25778
|
}
|
|
25029
25779
|
if (!column.isFrozen && !intersectsCanvasDirtyRects(column.localLeft, 0, column.width, column.height, topScrollHeaderDirtyRects)) {
|
|
@@ -25049,11 +25799,11 @@ function XlsxGrid({
|
|
|
25049
25799
|
column.height / 2
|
|
25050
25800
|
);
|
|
25051
25801
|
}
|
|
25052
|
-
if (leftFrozenHeaderContext &&
|
|
25802
|
+
if (leftFrozenHeaderContext && leftFrozenHeaderCanvasHeight > 0) {
|
|
25053
25803
|
leftFrozenHeaderContext.fillStyle = palette.rowHeaderSurface;
|
|
25054
|
-
leftFrozenHeaderContext.fillRect(0, 0, rowHeaderWidth,
|
|
25804
|
+
leftFrozenHeaderContext.fillRect(0, 0, rowHeaderWidth, leftFrozenHeaderCanvasHeight);
|
|
25055
25805
|
}
|
|
25056
|
-
if (leftScrollHeaderContext &&
|
|
25806
|
+
if (leftScrollHeaderContext && leftScrollHeaderCanvasHeight > 0) {
|
|
25057
25807
|
leftScrollHeaderContext.fillStyle = palette.rowHeaderSurface;
|
|
25058
25808
|
for (const dirtyRect of leftScrollHeaderDirtyRects) {
|
|
25059
25809
|
leftScrollHeaderContext.fillRect(dirtyRect.left, dirtyRect.top, dirtyRect.width, dirtyRect.height);
|
|
@@ -25072,7 +25822,7 @@ function XlsxGrid({
|
|
|
25072
25822
|
if (!paneContext) {
|
|
25073
25823
|
continue;
|
|
25074
25824
|
}
|
|
25075
|
-
if (row.localTop + row.height < 0 || row.localTop > (row.isFrozen ?
|
|
25825
|
+
if (row.localTop + row.height < 0 || row.localTop > (row.isFrozen ? leftFrozenHeaderCanvasHeight : leftScrollHeaderCanvasHeight)) {
|
|
25076
25826
|
continue;
|
|
25077
25827
|
}
|
|
25078
25828
|
if (!row.isFrozen && !intersectsCanvasDirtyRects(0, row.localTop, rowHeaderWidth, row.height, leftScrollHeaderDirtyRects)) {
|
|
@@ -25112,9 +25862,29 @@ function XlsxGrid({
|
|
|
25112
25862
|
paintedHeaderCanvasSignatureRef.current = nextHeaderCanvasSignature;
|
|
25113
25863
|
}
|
|
25114
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
|
+
}
|
|
25115
25881
|
}, [
|
|
25116
25882
|
activeSheet,
|
|
25117
25883
|
applyCanvasViewportCompensation,
|
|
25884
|
+
bakedCanvasDrawingSignature,
|
|
25885
|
+
bakedFormControlRects,
|
|
25886
|
+
bakedImageRects,
|
|
25887
|
+
bakedShapeRects,
|
|
25118
25888
|
canvasColumnHeaderCells,
|
|
25119
25889
|
canvasPaneAxisItems,
|
|
25120
25890
|
canvasRowHeaderCells,
|
|
@@ -25135,15 +25905,16 @@ function XlsxGrid({
|
|
|
25135
25905
|
frozenPaneBottom,
|
|
25136
25906
|
frozenPaneRight,
|
|
25137
25907
|
getCellData,
|
|
25908
|
+
getCanvasImage,
|
|
25138
25909
|
getBodyBlitBufferCanvas,
|
|
25139
25910
|
getHeaderBlitBufferCanvas,
|
|
25140
25911
|
palette,
|
|
25141
25912
|
resolveCellDisplayRect,
|
|
25142
25913
|
resolveMergeAnchorCell,
|
|
25143
|
-
resizeGuide,
|
|
25144
25914
|
rowIndexByActual,
|
|
25145
25915
|
rowPrefixSums,
|
|
25146
25916
|
selectionHeaderSurface,
|
|
25917
|
+
shouldBakeCanvasStaticDrawings,
|
|
25147
25918
|
stickyLeftByCol,
|
|
25148
25919
|
stickyTopByRow,
|
|
25149
25920
|
visibleCols,
|
|
@@ -25361,7 +26132,7 @@ function XlsxGrid({
|
|
|
25361
26132
|
start: virtualRow?.start ?? (rowPrefixSums[index] ?? 0)
|
|
25362
26133
|
};
|
|
25363
26134
|
});
|
|
25364
|
-
const totalHeight = shouldVirtualizeRows ? rowVirtualizer.getTotalSize() : rowPrefixSums[rowPrefixSums.length - 1] ?? 0;
|
|
26135
|
+
const totalHeight = shouldUseDomVirtualizer && shouldVirtualizeRows ? rowVirtualizer.getTotalSize() : rowPrefixSums[rowPrefixSums.length - 1] ?? 0;
|
|
25365
26136
|
const totalWidth = totalContentWidth + displayRowHeaderWidth;
|
|
25366
26137
|
const sheetContentHeight = displayHeaderHeight + totalHeight;
|
|
25367
26138
|
const isLiveZooming = liveGestureZoom !== null && zoomScale === liveGestureZoom.baseZoomScale;
|
|
@@ -25435,18 +26206,6 @@ function XlsxGrid({
|
|
|
25435
26206
|
width: 0,
|
|
25436
26207
|
zIndex: canvasHeaderOverlayZIndex
|
|
25437
26208
|
};
|
|
25438
|
-
const scrollBodyCanvasWidth = Math.max(0, drawingViewport.width - frozenPaneRight);
|
|
25439
|
-
const scrollBodyCanvasHeight = Math.max(0, drawingViewport.height - frozenPaneBottom);
|
|
25440
|
-
const topBodyCanvasWidth = scrollBodyCanvasWidth;
|
|
25441
|
-
const topBodyCanvasHeight = Math.max(0, frozenPaneBottom - displayHeaderHeight);
|
|
25442
|
-
const leftBodyCanvasWidth = Math.max(0, frozenPaneRight - displayRowHeaderWidth);
|
|
25443
|
-
const leftBodyCanvasHeight = scrollBodyCanvasHeight;
|
|
25444
|
-
const cornerBodyCanvasWidth = leftBodyCanvasWidth;
|
|
25445
|
-
const cornerBodyCanvasHeight = topBodyCanvasHeight;
|
|
25446
|
-
const topFrozenHeaderCanvasWidth = leftBodyCanvasWidth;
|
|
25447
|
-
const topScrollHeaderCanvasWidth = scrollBodyCanvasWidth;
|
|
25448
|
-
const leftFrozenHeaderCanvasHeight = topBodyCanvasHeight;
|
|
25449
|
-
const leftScrollHeaderCanvasHeight = scrollBodyCanvasHeight;
|
|
25450
26209
|
const canvasBodyBaseStyle = {
|
|
25451
26210
|
cursor: "cell",
|
|
25452
26211
|
pointerEvents: "auto",
|
|
@@ -25458,13 +26217,13 @@ function XlsxGrid({
|
|
|
25458
26217
|
const canvasScrollBodyStyle = {
|
|
25459
26218
|
...canvasBodyBaseStyle,
|
|
25460
26219
|
display: scrollBodyCanvasWidth > 0 && scrollBodyCanvasHeight > 0 ? "block" : "none",
|
|
25461
|
-
left:
|
|
25462
|
-
top:
|
|
26220
|
+
left: scrollBodyCanvasLeft,
|
|
26221
|
+
top: scrollBodyCanvasTop
|
|
25463
26222
|
};
|
|
25464
26223
|
const canvasTopBodyStyle = {
|
|
25465
26224
|
...canvasBodyBaseStyle,
|
|
25466
26225
|
display: topBodyCanvasWidth > 0 && topBodyCanvasHeight > 0 ? "block" : "none",
|
|
25467
|
-
left:
|
|
26226
|
+
left: scrollBodyCanvasLeft,
|
|
25468
26227
|
top: displayHeaderHeight,
|
|
25469
26228
|
zIndex: 30
|
|
25470
26229
|
};
|
|
@@ -25472,7 +26231,7 @@ function XlsxGrid({
|
|
|
25472
26231
|
...canvasBodyBaseStyle,
|
|
25473
26232
|
display: leftBodyCanvasWidth > 0 && leftBodyCanvasHeight > 0 ? "block" : "none",
|
|
25474
26233
|
left: displayRowHeaderWidth,
|
|
25475
|
-
top:
|
|
26234
|
+
top: scrollBodyCanvasTop,
|
|
25476
26235
|
zIndex: 30
|
|
25477
26236
|
};
|
|
25478
26237
|
const canvasCornerBodyStyle = {
|
|
@@ -25498,7 +26257,7 @@ function XlsxGrid({
|
|
|
25498
26257
|
const canvasTopScrollHeaderStyle = {
|
|
25499
26258
|
...canvasHeaderBaseStyle,
|
|
25500
26259
|
display: topScrollHeaderCanvasWidth > 0 && drawingViewport.height > 0 ? "block" : "none",
|
|
25501
|
-
left:
|
|
26260
|
+
left: scrollBodyCanvasLeft,
|
|
25502
26261
|
top: 0,
|
|
25503
26262
|
zIndex: canvasHeaderOverlayZIndex
|
|
25504
26263
|
};
|
|
@@ -25513,7 +26272,7 @@ function XlsxGrid({
|
|
|
25513
26272
|
...canvasHeaderBaseStyle,
|
|
25514
26273
|
display: leftScrollHeaderCanvasHeight > 0 && drawingViewport.width > 0 ? "block" : "none",
|
|
25515
26274
|
left: 0,
|
|
25516
|
-
top:
|
|
26275
|
+
top: scrollBodyCanvasTop,
|
|
25517
26276
|
zIndex: canvasHeaderOverlayZIndex
|
|
25518
26277
|
};
|
|
25519
26278
|
const canvasCornerHeaderStyle = {
|
|
@@ -26069,26 +26828,26 @@ function XlsxGrid({
|
|
|
26069
26828
|
};
|
|
26070
26829
|
const canvasScrollOverlayPaneStyle = {
|
|
26071
26830
|
...canvasOverlayPaneBaseStyle,
|
|
26072
|
-
display:
|
|
26073
|
-
height:
|
|
26831
|
+
display: scrollBodyViewportWidth > 0 && scrollBodyViewportHeight > 0 ? "block" : "none",
|
|
26832
|
+
height: scrollBodyViewportHeight,
|
|
26074
26833
|
left: frozenPaneRight,
|
|
26075
26834
|
top: frozenPaneBottom,
|
|
26076
|
-
width:
|
|
26835
|
+
width: scrollBodyViewportWidth,
|
|
26077
26836
|
zIndex: 20
|
|
26078
26837
|
};
|
|
26079
26838
|
const canvasTopOverlayPaneStyle = {
|
|
26080
26839
|
...canvasOverlayPaneBaseStyle,
|
|
26081
|
-
display:
|
|
26840
|
+
display: scrollBodyViewportWidth > 0 && topBodyCanvasHeight > 0 ? "block" : "none",
|
|
26082
26841
|
height: topBodyCanvasHeight,
|
|
26083
26842
|
left: frozenPaneRight,
|
|
26084
26843
|
top: displayHeaderHeight,
|
|
26085
|
-
width:
|
|
26844
|
+
width: scrollBodyViewportWidth,
|
|
26086
26845
|
zIndex: 35
|
|
26087
26846
|
};
|
|
26088
26847
|
const canvasLeftOverlayPaneStyle = {
|
|
26089
26848
|
...canvasOverlayPaneBaseStyle,
|
|
26090
|
-
display: leftBodyCanvasWidth > 0 &&
|
|
26091
|
-
height:
|
|
26849
|
+
display: leftBodyCanvasWidth > 0 && scrollBodyViewportHeight > 0 ? "block" : "none",
|
|
26850
|
+
height: scrollBodyViewportHeight,
|
|
26092
26851
|
left: displayRowHeaderWidth,
|
|
26093
26852
|
top: frozenPaneBottom,
|
|
26094
26853
|
width: leftBodyCanvasWidth,
|
|
@@ -26103,8 +26862,9 @@ function XlsxGrid({
|
|
|
26103
26862
|
width: cornerBodyCanvasWidth,
|
|
26104
26863
|
zIndex: 36
|
|
26105
26864
|
};
|
|
26865
|
+
const drawingViewportCacheSignature = `${Math.floor(drawingViewport.left / CANVAS_VIEWPORT_OVERSCAN_PX)}:${Math.floor(drawingViewport.top / CANVAS_VIEWPORT_OVERSCAN_PX)}:${drawingViewport.width}:${drawingViewport.height}`;
|
|
26106
26866
|
const previousPaneDrawingNodes = paneDrawingNodesCacheRef.current;
|
|
26107
|
-
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;
|
|
26108
26868
|
const paneDrawingNodes = canReusePaneDrawingNodes ? previousPaneDrawingNodes.value : !showImages ? {
|
|
26109
26869
|
corner: null,
|
|
26110
26870
|
left: null,
|
|
@@ -26113,35 +26873,35 @@ function XlsxGrid({
|
|
|
26113
26873
|
} : {
|
|
26114
26874
|
corner: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26115
26875
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "corner")),
|
|
26116
|
-
|
|
26117
|
-
|
|
26118
|
-
|
|
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"))
|
|
26119
26879
|
] }),
|
|
26120
26880
|
left: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26121
26881
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "left")),
|
|
26122
|
-
|
|
26123
|
-
|
|
26124
|
-
|
|
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"))
|
|
26125
26885
|
] }),
|
|
26126
26886
|
scroll: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26127
26887
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "scroll")),
|
|
26128
|
-
|
|
26129
|
-
|
|
26130
|
-
|
|
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"))
|
|
26131
26891
|
] }),
|
|
26132
26892
|
top: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26133
26893
|
chartRects.map(({ chart, rect }) => renderChartDrawing(chart, rect, "top")),
|
|
26134
|
-
|
|
26135
|
-
|
|
26136
|
-
|
|
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"))
|
|
26137
26897
|
] })
|
|
26138
26898
|
};
|
|
26139
26899
|
if (!canReusePaneDrawingNodes) {
|
|
26140
26900
|
paneDrawingNodesCacheRef.current = {
|
|
26141
26901
|
chartRects,
|
|
26142
|
-
|
|
26143
|
-
formControlRects,
|
|
26144
|
-
imageRects,
|
|
26902
|
+
drawingViewportSignature: drawingViewportCacheSignature,
|
|
26903
|
+
formControlRects: domFormControlRects,
|
|
26904
|
+
imageRects: domImageRects,
|
|
26145
26905
|
isChartsLoading,
|
|
26146
26906
|
palette,
|
|
26147
26907
|
readOnly,
|
|
@@ -26151,7 +26911,7 @@ function XlsxGrid({
|
|
|
26151
26911
|
selectedChartId,
|
|
26152
26912
|
selectedImageId,
|
|
26153
26913
|
selectionStroke,
|
|
26154
|
-
shapeRects,
|
|
26914
|
+
shapeRects: domShapeRects,
|
|
26155
26915
|
showImages,
|
|
26156
26916
|
value: paneDrawingNodes
|
|
26157
26917
|
};
|
|
@@ -26659,10 +27419,11 @@ function XlsxGrid({
|
|
|
26659
27419
|
style: canvasCornerBodyStyle
|
|
26660
27420
|
}
|
|
26661
27421
|
),
|
|
26662
|
-
|
|
27422
|
+
hasCanvasDomDrawingOverlays ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
26663
27423
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasScrollOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
26664
27424
|
"div",
|
|
26665
27425
|
{
|
|
27426
|
+
ref: canvasScrollOverlayContentRef,
|
|
26666
27427
|
style: {
|
|
26667
27428
|
height: sheetContentHeight,
|
|
26668
27429
|
left: 0,
|
|
@@ -26670,6 +27431,7 @@ function XlsxGrid({
|
|
|
26670
27431
|
position: "absolute",
|
|
26671
27432
|
top: 0,
|
|
26672
27433
|
transform: `translate(${-drawingViewport.left - frozenPaneRight}px, ${-drawingViewport.top - frozenPaneBottom}px)`,
|
|
27434
|
+
transformOrigin: "0 0",
|
|
26673
27435
|
width: totalWidth
|
|
26674
27436
|
},
|
|
26675
27437
|
children: paneDrawingNodes.scroll
|
|
@@ -26678,6 +27440,7 @@ function XlsxGrid({
|
|
|
26678
27440
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasTopOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
26679
27441
|
"div",
|
|
26680
27442
|
{
|
|
27443
|
+
ref: canvasTopOverlayContentRef,
|
|
26681
27444
|
style: {
|
|
26682
27445
|
height: sheetContentHeight,
|
|
26683
27446
|
left: 0,
|
|
@@ -26685,6 +27448,7 @@ function XlsxGrid({
|
|
|
26685
27448
|
position: "absolute",
|
|
26686
27449
|
top: 0,
|
|
26687
27450
|
transform: `translate(${-drawingViewport.left - frozenPaneRight}px, ${-displayHeaderHeight}px)`,
|
|
27451
|
+
transformOrigin: "0 0",
|
|
26688
27452
|
width: totalWidth
|
|
26689
27453
|
},
|
|
26690
27454
|
children: paneDrawingNodes.top
|
|
@@ -26693,6 +27457,7 @@ function XlsxGrid({
|
|
|
26693
27457
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasLeftOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
26694
27458
|
"div",
|
|
26695
27459
|
{
|
|
27460
|
+
ref: canvasLeftOverlayContentRef,
|
|
26696
27461
|
style: {
|
|
26697
27462
|
height: sheetContentHeight,
|
|
26698
27463
|
left: 0,
|
|
@@ -26700,6 +27465,7 @@ function XlsxGrid({
|
|
|
26700
27465
|
position: "absolute",
|
|
26701
27466
|
top: 0,
|
|
26702
27467
|
transform: `translate(${-displayRowHeaderWidth}px, ${-drawingViewport.top - frozenPaneBottom}px)`,
|
|
27468
|
+
transformOrigin: "0 0",
|
|
26703
27469
|
width: totalWidth
|
|
26704
27470
|
},
|
|
26705
27471
|
children: paneDrawingNodes.left
|
|
@@ -26708,6 +27474,7 @@ function XlsxGrid({
|
|
|
26708
27474
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasCornerOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
26709
27475
|
"div",
|
|
26710
27476
|
{
|
|
27477
|
+
ref: canvasCornerOverlayContentRef,
|
|
26711
27478
|
style: {
|
|
26712
27479
|
height: sheetContentHeight,
|
|
26713
27480
|
left: 0,
|
|
@@ -26715,6 +27482,7 @@ function XlsxGrid({
|
|
|
26715
27482
|
position: "absolute",
|
|
26716
27483
|
top: 0,
|
|
26717
27484
|
transform: `translate(${-displayRowHeaderWidth}px, ${-displayHeaderHeight}px)`,
|
|
27485
|
+
transformOrigin: "0 0",
|
|
26718
27486
|
width: totalWidth
|
|
26719
27487
|
},
|
|
26720
27488
|
children: paneDrawingNodes.corner
|
|
@@ -27121,7 +27889,7 @@ function XlsxViewerInner({
|
|
|
27121
27889
|
enableCanvasSelectionAnimation = true,
|
|
27122
27890
|
enableGestureZoom = true,
|
|
27123
27891
|
errorState,
|
|
27124
|
-
experimentalCanvas =
|
|
27892
|
+
experimentalCanvas = true,
|
|
27125
27893
|
fileTooLargeState,
|
|
27126
27894
|
height,
|
|
27127
27895
|
isDark = false,
|
|
@@ -27634,7 +28402,7 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27634
28402
|
if (!canvas) {
|
|
27635
28403
|
return false;
|
|
27636
28404
|
}
|
|
27637
|
-
const context = canvas.getContext("2d");
|
|
28405
|
+
const context = canvas.getContext("2d", { alpha: false });
|
|
27638
28406
|
if (!context) {
|
|
27639
28407
|
return false;
|
|
27640
28408
|
}
|
|
@@ -27658,9 +28426,10 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27658
28426
|
}
|
|
27659
28427
|
context.setTransform(dpr * scale, 0, 0, dpr * scale, 0, 0);
|
|
27660
28428
|
context.clearRect(0, 0, Math.max(1, sourceWidth), Math.max(1, sourceHeight));
|
|
28429
|
+
const thumbnailSheetSurface = resolveSheetSurface(sheet, palette);
|
|
27661
28430
|
context.fillStyle = palette.canvas;
|
|
27662
28431
|
context.fillRect(0, 0, Math.max(1, sourceWidth), Math.max(1, sourceHeight));
|
|
27663
|
-
context.fillStyle =
|
|
28432
|
+
context.fillStyle = thumbnailSheetSurface;
|
|
27664
28433
|
context.fillRect(rowHeaderWidth, headerHeight, Math.max(1, colAxis.totalSize), Math.max(1, rowAxis.totalSize));
|
|
27665
28434
|
if (includeHeaders) {
|
|
27666
28435
|
context.fillStyle = palette.headerSurface;
|
|
@@ -27781,8 +28550,8 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27781
28550
|
};
|
|
27782
28551
|
const canvasCellStyle = cellData.canvas ?? buildCanvasCellStyleCache(cellData.style);
|
|
27783
28552
|
const gradientFill = typeof cellData.style.backgroundImage === "string" ? resolveCanvasGradientFill(context, rect, cellData.style.backgroundImage) : null;
|
|
27784
|
-
const fillColor = cellData.conditionalColorScale?.color ?? (typeof cellData.style.backgroundColor === "string" ? cellData.style.backgroundColor :
|
|
27785
|
-
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;
|
|
27786
28555
|
context.fillStyle = gradientFill ?? fillColor;
|
|
27787
28556
|
context.fillRect(rect.left, rect.top, rect.width, rect.height);
|
|
27788
28557
|
if (cellData.conditionalDataBar) {
|
|
@@ -27837,12 +28606,19 @@ function useXlsxViewerThumbnails(options = {}) {
|
|
|
27837
28606
|
if (canvasCellStyle.leftBorder) {
|
|
27838
28607
|
strokeCanvasBorderSide(context, "left", rect, canvasCellStyle.leftBorder);
|
|
27839
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
|
+
}
|
|
27840
28614
|
const padding = canvasCellStyle.padding;
|
|
27841
28615
|
const contentLeft = rect.left + padding.left;
|
|
27842
28616
|
const contentTop = rect.top + padding.top;
|
|
27843
28617
|
const contentWidth = Math.max(0, rect.width - padding.left - padding.right);
|
|
27844
28618
|
const contentHeight = Math.max(0, rect.height - padding.top - padding.bottom);
|
|
27845
|
-
|
|
28619
|
+
if (contentWidth <= 0 || contentHeight <= 0) {
|
|
28620
|
+
continue;
|
|
28621
|
+
}
|
|
27846
28622
|
context.save();
|
|
27847
28623
|
context.beginPath();
|
|
27848
28624
|
context.rect(contentLeft, contentTop, contentWidth, contentHeight);
|