@extend-ai/react-xlsx 0.16.6 → 0.17.1

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 CHANGED
@@ -35,6 +35,7 @@ __export(index_exports, {
35
35
  XlsxViewer: () => XlsxViewer,
36
36
  XlsxViewerProvider: () => XlsxViewerProvider,
37
37
  initWasm: () => initWasm,
38
+ parseXlsxRange: () => parseXlsxRange,
38
39
  setWasmSource: () => setWasmSource,
39
40
  useXlsxViewer: () => useXlsxViewer,
40
41
  useXlsxViewerCharts: () => useXlsxViewerCharts,
@@ -3631,7 +3632,7 @@ function resolveWorkbookColor(color, themePalette) {
3631
3632
  if (directHex) {
3632
3633
  return normalizeHexColor2(directHex);
3633
3634
  }
3634
- const themeValue = color.theme;
3635
+ const themeValue = color.theme ?? color.themeIndex;
3635
3636
  const numericTheme = typeof themeValue === "number" ? themeValue : typeof themeValue === "string" && themeValue.trim().length > 0 ? Number(themeValue) : Number.NaN;
3636
3637
  const themeColor = Number.isFinite(numericTheme) ? themePalette?.colorsByIndex[numericTheme] ?? null : null;
3637
3638
  if (!themeColor) {
@@ -3789,7 +3790,8 @@ function resolveWorksheetMergeMetadata(worksheet) {
3789
3790
  hasHorizontalMerges: false,
3790
3791
  hasVerticalMerges: false,
3791
3792
  maxHorizontalMergeEndCol: -1,
3792
- maxVerticalMergeEndRow: -1
3793
+ maxVerticalMergeEndRow: -1,
3794
+ mergedRanges: []
3793
3795
  };
3794
3796
  const mergedRegions = Array.isArray(worksheet.mergedRegions) ? worksheet.mergedRegions : [];
3795
3797
  for (const rawRegion of mergedRegions) {
@@ -3820,6 +3822,7 @@ function resolveWorksheetMergeMetadata(worksheet) {
3820
3822
  if (!range) {
3821
3823
  continue;
3822
3824
  }
3825
+ mergeMetadata.mergedRanges.push(range);
3823
3826
  if (range.end.col > range.start.col) {
3824
3827
  mergeMetadata.hasHorizontalMerges = true;
3825
3828
  mergeMetadata.maxHorizontalMergeEndCol = Math.max(mergeMetadata.maxHorizontalMergeEndCol, range.end.col);
@@ -4257,6 +4260,12 @@ function parseSpreadsheetFont(node) {
4257
4260
  return void 0;
4258
4261
  }
4259
4262
  const font = {};
4263
+ for (const [tag, property] of [["b", "bold"], ["i", "italic"], ["strike", "strikethrough"]]) {
4264
+ const flag = getFirstChild(node, tag);
4265
+ if (flag) {
4266
+ font[property] = hasEnabledSpreadsheetFlag(flag);
4267
+ }
4268
+ }
4260
4269
  const size = getFirstChild(node, "sz")?.getAttribute("val");
4261
4270
  const name = getFirstChild(node, "name")?.getAttribute("val");
4262
4271
  const family = getFirstChild(node, "family")?.getAttribute("val");
@@ -4264,15 +4273,6 @@ function parseSpreadsheetFont(node) {
4264
4273
  const charset = getFirstChild(node, "charset")?.getAttribute("val");
4265
4274
  const verticalAlign = getFirstChild(node, "vertAlign")?.getAttribute("val");
4266
4275
  const color = parseSpreadsheetColor(getFirstChild(node, "color"));
4267
- if (hasEnabledSpreadsheetFlag(getFirstChild(node, "b"))) {
4268
- font.bold = true;
4269
- }
4270
- if (hasEnabledSpreadsheetFlag(getFirstChild(node, "i"))) {
4271
- font.italic = true;
4272
- }
4273
- if (hasEnabledSpreadsheetFlag(getFirstChild(node, "strike"))) {
4274
- font.strikethrough = true;
4275
- }
4276
4276
  if (getFirstChild(node, "u")) {
4277
4277
  font.underline = getFirstChild(node, "u")?.getAttribute("val") ?? "single";
4278
4278
  }
@@ -4521,7 +4521,14 @@ function parseWorkbookStyles(archive) {
4521
4521
  const styleById = {};
4522
4522
  const tableStyleByName = {};
4523
4523
  getChildElements(cellXfsNode, "xf").forEach((xfNode, index) => {
4524
- styleById[index] = parseResolvedXfStyle(xfNode, fonts, fills, borders, checkboxComplementIndices);
4524
+ const style = parseResolvedXfStyle(xfNode, fonts, fills, borders, checkboxComplementIndices);
4525
+ const overrides = {};
4526
+ for (const component of ["font", "fill", "border"]) {
4527
+ if (Number(xfNode.getAttribute(`${component}Id`) ?? 0) > 0 && xfNode.getAttribute(`apply${component[0].toUpperCase()}${component.slice(1)}`) !== "0") {
4528
+ Object.assign(overrides, { [component]: style[component] });
4529
+ }
4530
+ }
4531
+ styleById[index] = { ...style, tableStyleOverrides: overrides };
4525
4532
  });
4526
4533
  getChildElements(cellStylesNode ?? document2.documentElement, "cellStyle").forEach((cellStyleNode) => {
4527
4534
  const name = cellStyleNode.getAttribute("name");
@@ -4865,6 +4872,7 @@ function parseSheetState(archive, path, options) {
4865
4872
  const rowHeightOverridesPx = {};
4866
4873
  const colWidthOverridesPx = {};
4867
4874
  const rowStyleIds = {};
4875
+ const cellStyleIds = {};
4868
4876
  const colStyleIds = {};
4869
4877
  let minContentCol = Number.POSITIVE_INFINITY;
4870
4878
  let minContentRow = Number.POSITIVE_INFINITY;
@@ -4914,6 +4922,10 @@ function parseSheetState(archive, path, options) {
4914
4922
  }
4915
4923
  getChildElements(rowNode, "c").forEach((cellNode) => {
4916
4924
  const cellRef = cellNode.getAttribute("r");
4925
+ const cellStyleId = Number(cellNode.getAttribute("s") ?? Number.NaN);
4926
+ if (cellRef && Number.isFinite(cellStyleId)) {
4927
+ cellStyleIds[cellRef] = cellStyleId;
4928
+ }
4917
4929
  if (isMeaningfulCellNode(cellNode)) {
4918
4930
  trackContentCell(cellRef);
4919
4931
  }
@@ -4952,6 +4964,7 @@ function parseSheetState(archive, path, options) {
4952
4964
  return {
4953
4965
  autoFilterRanges,
4954
4966
  cachedFormulaValues,
4967
+ cellStyleIds,
4955
4968
  columnWidthCharacterWidthPx,
4956
4969
  colWidthOverridesPx,
4957
4970
  colStyleIds,
@@ -6723,6 +6736,102 @@ function tryRecalculate(workbook) {
6723
6736
  }
6724
6737
  }
6725
6738
 
6739
+ // src/range-reference.ts
6740
+ var XLSX_MAX_ROWS = 1048576;
6741
+ var XLSX_MAX_COLUMNS = 16384;
6742
+ function parseColumn(value) {
6743
+ let column = 0;
6744
+ for (const character of value.toUpperCase()) {
6745
+ column = column * 26 + character.charCodeAt(0) - 64;
6746
+ }
6747
+ return column > 0 && column <= XLSX_MAX_COLUMNS ? column - 1 : null;
6748
+ }
6749
+ function parseRow(value) {
6750
+ const row = Number(value);
6751
+ return row > 0 && row <= XLSX_MAX_ROWS ? row - 1 : null;
6752
+ }
6753
+ function parseCell(value) {
6754
+ const match = /^\$?([a-z]{1,3})\$?([1-9]\d{0,6})$/i.exec(value);
6755
+ if (!match) {
6756
+ return null;
6757
+ }
6758
+ const col = parseColumn(match[1]);
6759
+ const row = parseRow(match[2]);
6760
+ return col === null || row === null ? null : { col, row };
6761
+ }
6762
+ function parseXlsxRange(reference) {
6763
+ if (typeof reference !== "string") {
6764
+ return null;
6765
+ }
6766
+ let address = reference.trim().replace(/^=\s*/, "");
6767
+ let sheetName = null;
6768
+ if (address.startsWith("'")) {
6769
+ const match = /^'((?:[^']|'')+)'!(.+)$/.exec(address);
6770
+ if (!match) {
6771
+ return null;
6772
+ }
6773
+ sheetName = match[1].replace(/''/g, "'");
6774
+ address = match[2];
6775
+ } else if (address.includes("!")) {
6776
+ const match = /^([^\s'!\[\]:*?/\\+,;(){}=<>"&^%\-]+)!(.+)$/.exec(address);
6777
+ if (!match) {
6778
+ return null;
6779
+ }
6780
+ sheetName = match[1];
6781
+ address = match[2];
6782
+ }
6783
+ if (sheetName !== null && (sheetName.length > 31 || /[\[\]:*?/\\\u0000-\u001f]/.test(sheetName) || sheetName.startsWith("'") || sheetName.endsWith("'"))) {
6784
+ return null;
6785
+ }
6786
+ const parts = address.split(":");
6787
+ if (parts.length > 2) {
6788
+ return null;
6789
+ }
6790
+ const start = parseCell(parts[0]);
6791
+ const end = parseCell(parts[1] ?? parts[0]);
6792
+ if (start && end) {
6793
+ return {
6794
+ kind: "cells",
6795
+ range: {
6796
+ start: { col: Math.min(start.col, end.col), row: Math.min(start.row, end.row) },
6797
+ end: { col: Math.max(start.col, end.col), row: Math.max(start.row, end.row) }
6798
+ },
6799
+ sheetName
6800
+ };
6801
+ }
6802
+ const columns = /^\$?([a-z]{1,3}):\$?([a-z]{1,3})$/i.exec(address);
6803
+ if (columns) {
6804
+ const first = parseColumn(columns[1]);
6805
+ const last = parseColumn(columns[2]);
6806
+ if (first !== null && last !== null) {
6807
+ return {
6808
+ kind: "columns",
6809
+ range: {
6810
+ start: { col: Math.min(first, last), row: 0 },
6811
+ end: { col: Math.max(first, last), row: XLSX_MAX_ROWS - 1 }
6812
+ },
6813
+ sheetName
6814
+ };
6815
+ }
6816
+ }
6817
+ const rows = /^\$?([1-9]\d{0,6}):\$?([1-9]\d{0,6})$/.exec(address);
6818
+ if (rows) {
6819
+ const first = parseRow(rows[1]);
6820
+ const last = parseRow(rows[2]);
6821
+ if (first !== null && last !== null) {
6822
+ return {
6823
+ kind: "rows",
6824
+ range: {
6825
+ start: { col: 0, row: Math.min(first, last) },
6826
+ end: { col: XLSX_MAX_COLUMNS - 1, row: Math.max(first, last) }
6827
+ },
6828
+ sheetName
6829
+ };
6830
+ }
6831
+ }
6832
+ return null;
6833
+ }
6834
+
6726
6835
  // src/wasm.ts
6727
6836
  var wasmModulePromise = null;
6728
6837
  var hasConfiguredWasmSource = false;
@@ -7345,6 +7454,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
7345
7454
  hasVerticalMerges: mergeMetadata.hasVerticalMerges,
7346
7455
  maxHorizontalMergeEndCol: mergeMetadata.maxHorizontalMergeEndCol,
7347
7456
  maxVerticalMergeEndRow: mergeMetadata.maxVerticalMergeEndRow,
7457
+ mergedRanges: mergeMetadata.mergedRanges,
7348
7458
  hiddenCols: [],
7349
7459
  hiddenRows: [],
7350
7460
  minUsedCol: -1,
@@ -7358,6 +7468,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
7358
7468
  colCount: 0,
7359
7469
  rowHeightOverridesPx: sheetState?.rowHeightOverridesPx ?? {},
7360
7470
  rowStyleIds: sheetState?.rowStyleIds ?? {},
7471
+ cellStyleIds: sheetState?.cellStyleIds ?? {},
7361
7472
  styleById: styleById ?? {},
7362
7473
  sparklines: sheetState?.sparklines ?? [],
7363
7474
  tableStyleByName: tableStyleByName ?? {},
@@ -7432,6 +7543,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
7432
7543
  hasVerticalMerges: mergeMetadata.hasVerticalMerges,
7433
7544
  maxHorizontalMergeEndCol: mergeMetadata.maxHorizontalMergeEndCol,
7434
7545
  maxVerticalMergeEndRow: mergeMetadata.maxVerticalMergeEndRow,
7546
+ mergedRanges: mergeMetadata.mergedRanges,
7435
7547
  hiddenCols: resolveWorksheetHiddenCols(worksheet, maxCol),
7436
7548
  hiddenRows: resolveWorksheetHiddenRows(worksheet, maxRow),
7437
7549
  minUsedCol: minCol,
@@ -7443,6 +7555,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
7443
7555
  namedCellStyleByName: namedCellStyleByName ?? {},
7444
7556
  rowHeightOverridesPx: sheetState?.rowHeightOverridesPx ?? {},
7445
7557
  rowStyleIds: sheetState?.rowStyleIds ?? {},
7558
+ cellStyleIds: sheetState?.cellStyleIds ?? {},
7446
7559
  showGridLines: sheetState?.showGridLines ?? true,
7447
7560
  styleById: styleById ?? {},
7448
7561
  sparklines: sheetState?.sparklines ?? [],
@@ -8433,6 +8546,7 @@ function useXlsxViewerController(options) {
8433
8546
  const [zoomScaleOverridesByTabId, setZoomScaleOverridesByTabId] = React.useState({});
8434
8547
  const [activeCell, setActiveCell] = React.useState(null);
8435
8548
  const [selection, setSelection] = React.useState(null);
8549
+ const [highlightedRanges, setHighlightedRanges] = React.useState([]);
8436
8550
  const [selectedChartId, setSelectedChartId] = React.useState(null);
8437
8551
  const [selectedChartElement, setSelectedChartElement] = React.useState(null);
8438
8552
  const [selectedImageId, setSelectedImageId] = React.useState(null);
@@ -8718,6 +8832,7 @@ function useXlsxViewerController(options) {
8718
8832
  setActiveTabIndexState(0);
8719
8833
  setActiveCell(null);
8720
8834
  setSelection(null);
8835
+ setHighlightedRanges([]);
8721
8836
  setSelectedChartId(null);
8722
8837
  setSelectedChartElement(null);
8723
8838
  setSelectedImageId(null);
@@ -8747,6 +8862,7 @@ function useXlsxViewerController(options) {
8747
8862
  setActiveTabIndexState(0);
8748
8863
  setActiveCell(null);
8749
8864
  setSelection(null);
8865
+ setHighlightedRanges([]);
8750
8866
  setSelectedChartId(null);
8751
8867
  setSelectedChartElement(null);
8752
8868
  setSelectedImageId(null);
@@ -8938,6 +9054,41 @@ function useXlsxViewerController(options) {
8938
9054
  return index;
8939
9055
  });
8940
9056
  }, [tabs]);
9057
+ const highlightRanges = React.useCallback((references, options2 = {}) => {
9058
+ const inputs = typeof references === "string" ? [references] : references;
9059
+ if (!Array.isArray(inputs) || isLoading || error) {
9060
+ return false;
9061
+ }
9062
+ const nextHighlights = [];
9063
+ let firstSheetIndex = activeSheetIndex;
9064
+ for (const reference of inputs) {
9065
+ const parsed = parseXlsxRange(reference);
9066
+ if (!parsed) {
9067
+ return false;
9068
+ }
9069
+ const requestedSheetName = parsed.sheetName?.toLowerCase();
9070
+ const sheetIndex = requestedSheetName === void 0 ? options2.sheetIndex ?? activeSheetIndex : sheets.findIndex((sheet2) => sheet2.name.toLowerCase() === requestedSheetName);
9071
+ const sheet = Number.isInteger(sheetIndex) ? sheets[sheetIndex] : void 0;
9072
+ if (!sheet) {
9073
+ return false;
9074
+ }
9075
+ if (nextHighlights.length === 0) {
9076
+ firstSheetIndex = sheetIndex;
9077
+ }
9078
+ nextHighlights.push({
9079
+ ...parsed,
9080
+ autoScroll: nextHighlights.length === 0 && (options2.autoScroll ?? true),
9081
+ sheetName: sheet.name,
9082
+ workbookSheetIndex: sheet.workbookSheetIndex
9083
+ });
9084
+ }
9085
+ setHighlightedRanges(nextHighlights);
9086
+ if (nextHighlights[0]?.autoScroll) {
9087
+ setActiveSheetIndex(firstSheetIndex);
9088
+ }
9089
+ return true;
9090
+ }, [activeSheetIndex, error, isLoading, setActiveSheetIndex, sheets]);
9091
+ const clearHighlightedRanges = React.useCallback(() => setHighlightedRanges([]), []);
8941
9092
  const setZoomScale = React.useCallback((nextZoomScale) => {
8942
9093
  const normalizedZoomScale = clampZoomScale(nextZoomScale);
8943
9094
  setZoomScaleOverridesByTabId((current) => {
@@ -9868,7 +10019,7 @@ function useXlsxViewerController(options) {
9868
10019
  return;
9869
10020
  }
9870
10021
  const dataStartRow = targetTable.start.row + Math.max(targetTable.headerRowCount, 1);
9871
- const totalsRowOffset = targetTable.totalsRowShown ? Math.max(targetTable.totalsRowCount, 1) : 0;
10022
+ const totalsRowOffset = targetTable.totalsRowCount;
9872
10023
  const dataEndRow = targetTable.end.row - totalsRowOffset;
9873
10024
  const startCol = targetTable.start.col;
9874
10025
  const endCol = targetTable.end.col;
@@ -10996,6 +11147,9 @@ function useXlsxViewerController(options) {
10996
11147
  clearSelectedCells,
10997
11148
  clearSelectedImage,
10998
11149
  clearSelection,
11150
+ clearHighlightedRanges,
11151
+ highlightRanges,
11152
+ highlightedRanges,
10999
11153
  continueDeferredLoad,
11000
11154
  copySelectionToClipboard,
11001
11155
  defaultZoomScale,
@@ -11116,6 +11270,9 @@ function useXlsxViewerController(options) {
11116
11270
  clearSelectedCells,
11117
11271
  clearSelectedImage,
11118
11272
  continueDeferredLoad,
11273
+ clearHighlightedRanges,
11274
+ highlightRanges,
11275
+ highlightedRanges,
11119
11276
  copySelectionToClipboard,
11120
11277
  defaultZoomScale,
11121
11278
  deferredLoadFileSize,
@@ -11799,6 +11956,62 @@ function growScrollDisplayLimit(current, growth, maximum, readOnly) {
11799
11956
  return readOnly ? Math.max(current, Math.min(maximum, nextLimit)) : nextLimit;
11800
11957
  }
11801
11958
 
11959
+ // src/range-highlight.ts
11960
+ function expandHighlightedRange(range, mergedRanges) {
11961
+ const expanded = { start: { ...range.start }, end: { ...range.end } };
11962
+ let changed;
11963
+ do {
11964
+ changed = false;
11965
+ for (const merged of mergedRanges) {
11966
+ if (merged.end.row < expanded.start.row || merged.start.row > expanded.end.row || merged.end.col < expanded.start.col || merged.start.col > expanded.end.col) {
11967
+ continue;
11968
+ }
11969
+ const startRow = Math.min(expanded.start.row, merged.start.row);
11970
+ const startCol = Math.min(expanded.start.col, merged.start.col);
11971
+ const endRow = Math.max(expanded.end.row, merged.end.row);
11972
+ const endCol = Math.max(expanded.end.col, merged.end.col);
11973
+ if (startRow !== expanded.start.row || startCol !== expanded.start.col || endRow !== expanded.end.row || endCol !== expanded.end.col) {
11974
+ expanded.start = { row: startRow, col: startCol };
11975
+ expanded.end = { row: endRow, col: endCol };
11976
+ changed = true;
11977
+ }
11978
+ }
11979
+ } while (changed);
11980
+ return expanded;
11981
+ }
11982
+ function lowerBound(indices, value) {
11983
+ let low = 0;
11984
+ let high = indices.length;
11985
+ while (low < high) {
11986
+ const middle = low + high >>> 1;
11987
+ if (indices[middle] < value) {
11988
+ low = middle + 1;
11989
+ } else {
11990
+ high = middle;
11991
+ }
11992
+ }
11993
+ return low;
11994
+ }
11995
+ function getHighlightAxisExtent(indices, prefixSums, start, end) {
11996
+ const first = lowerBound(indices, start);
11997
+ const afterLast = lowerBound(indices, end + 1);
11998
+ if (first >= afterLast) {
11999
+ return null;
12000
+ }
12001
+ return { start: prefixSums[first] ?? 0, end: prefixSums[afterLast] ?? 0 };
12002
+ }
12003
+ function getHighlightScrollOffset(start, end, frozenExtent, viewportExtent, currentOffset) {
12004
+ if (end <= frozenExtent || viewportExtent <= frozenExtent) {
12005
+ return currentOffset;
12006
+ }
12007
+ const scrollableStart = Math.max(start, frozenExtent);
12008
+ const availableExtent = viewportExtent - frozenExtent;
12009
+ if (scrollableStart < currentOffset + frozenExtent || end - scrollableStart > availableExtent) {
12010
+ return Math.max(0, scrollableStart - frozenExtent);
12011
+ }
12012
+ return end > currentOffset + viewportExtent ? end - viewportExtent : currentOffset;
12013
+ }
12014
+
11802
12015
  // src/chart-renderer.tsx
11803
12016
  var import_d3_hierarchy = require("d3-hierarchy");
11804
12017
  var import_d3_geo = require("d3-geo");
@@ -18607,6 +18820,17 @@ function resolveViewerPalette(isDark = false, headerBackgroundColor, headerTextC
18607
18820
 
18608
18821
  // src/XlsxViewer.tsx
18609
18822
  var import_jsx_runtime3 = require("react/jsx-runtime");
18823
+ var RANGE_HIGHLIGHT_STYLES = `
18824
+ :where(.react-xlsx-range-highlight) {
18825
+ background: var(--xlsx-highlight-fill, rgb(59 130 246 / 8%));
18826
+ border: var(--xlsx-highlight-border, var(--xlsx-highlight-default-border-width, 1px) solid #3b82f6);
18827
+ border-radius: var(--xlsx-highlight-radius, 2px);
18828
+ }
18829
+ :where(.react-xlsx-range-highlight[data-dark="true"]) {
18830
+ background: var(--xlsx-highlight-fill, rgb(147 197 253 / 12%));
18831
+ border: var(--xlsx-highlight-border, var(--xlsx-highlight-default-border-width, 1px) solid #93c5fd);
18832
+ }
18833
+ `;
18610
18834
  var DEFAULT_ROW_HEIGHT2 = 24;
18611
18835
  var DEFAULT_COL_WIDTH2 = 80;
18612
18836
  var HEADER_HEIGHT = 24;
@@ -18959,7 +19183,8 @@ function applyCanvasBorderDash(context, style, width) {
18959
19183
  context.setLineDash([]);
18960
19184
  }
18961
19185
  function strokeCanvasBorderSide(context, side, rect, border) {
18962
- const halfWidth = border.width / 2;
19186
+ const strokeWidth = border.style === "double" ? border.width / 3 : border.width;
19187
+ const halfWidth = strokeWidth / 2;
18963
19188
  const left = rect.left;
18964
19189
  const right = rect.left + rect.width;
18965
19190
  const top = rect.top;
@@ -18985,8 +19210,8 @@ function strokeCanvasBorderSide(context, side, rect, border) {
18985
19210
  context.stroke();
18986
19211
  };
18987
19212
  if (border.style === "double") {
18988
- const inset = Math.max(1, border.width);
18989
- context.lineWidth = Math.max(1, border.width / 3);
19213
+ const inset = border.width - strokeWidth;
19214
+ context.lineWidth = strokeWidth;
18990
19215
  context.setLineDash([]);
18991
19216
  strokeLine(0);
18992
19217
  strokeLine(inset);
@@ -21899,6 +22124,43 @@ function mergeResolvedCellStyle(base, overlay, options) {
21899
22124
  }
21900
22125
  return nextStyle;
21901
22126
  }
22127
+ function resolveCellTableOverrides(rawStyle, sheet, row, col) {
22128
+ const styleId = sheet?.cellStyleIds?.[cellAddressToA12({ row, col })] ?? sheet?.rowStyleIds[row] ?? sheet?.colStyleIds[col];
22129
+ const declared = styleId === void 0 ? void 0 : sheet?.styleById[styleId]?.tableStyleOverrides;
22130
+ const overrides = {};
22131
+ const font = asRecord(rawStyle?.font);
22132
+ if (font) {
22133
+ const explicitFont = {};
22134
+ const fontDefaults = {
22135
+ name: "Calibri",
22136
+ size: 11,
22137
+ bold: false,
22138
+ italic: false,
22139
+ underline: "none",
22140
+ strikethrough: false,
22141
+ verticalAlign: "baseline"
22142
+ };
22143
+ for (const [key, value] of Object.entries(font)) {
22144
+ const isExplicit = declared ? Object.hasOwn(declared.font ?? {}, key) : key === "color" ? asRecord(value)?.colorType !== "auto" : value !== fontDefaults[key];
22145
+ if (isExplicit) {
22146
+ explicitFont[key] = value;
22147
+ }
22148
+ }
22149
+ overrides.font = explicitFont;
22150
+ }
22151
+ const fill = asRecord(rawStyle?.fill);
22152
+ if (fill && fill.fillType !== "none") {
22153
+ overrides.fill = fill;
22154
+ }
22155
+ const border = asRecord(rawStyle?.border);
22156
+ if (border) {
22157
+ overrides.border = Object.fromEntries(Object.entries(border).filter(([, edge]) => {
22158
+ const style = asRecord(edge)?.style;
22159
+ return typeof style === "string" && style !== "none";
22160
+ }));
22161
+ }
22162
+ return overrides;
22163
+ }
21902
22164
  function resolveBorderEdgePriority(edge) {
21903
22165
  const style = typeof edge?.style === "string" ? edge.style : "none";
21904
22166
  const stylePriority = {
@@ -22027,7 +22289,7 @@ function resolveTableCellStyle(table, row, col, activeSheet) {
22027
22289
  return null;
22028
22290
  }
22029
22291
  const headerRowCount = Math.max(table.headerRowCount, 1);
22030
- const totalsRowCount = table.totalsRowShown ? Math.max(table.totalsRowCount, 1) : 0;
22292
+ const totalsRowCount = table.totalsRowCount;
22031
22293
  const headerEndRow = table.start.row + headerRowCount - 1;
22032
22294
  const totalsStartRow = table.end.row - totalsRowCount + 1;
22033
22295
  const bodyStartRow = headerEndRow + 1;
@@ -24098,6 +24360,7 @@ function XlsxGrid({
24098
24360
  errorState,
24099
24361
  fileTooLargeState,
24100
24362
  getCellStyle,
24363
+ highlightClassName,
24101
24364
  loadingComponent,
24102
24365
  loadingState,
24103
24366
  onFormControlAction,
@@ -24142,6 +24405,7 @@ function XlsxGrid({
24142
24405
  getClipboardData,
24143
24406
  getCellDisplayValue: getControllerCellDisplayValue,
24144
24407
  getFormControlItems,
24408
+ highlightedRanges,
24145
24409
  images,
24146
24410
  shapes,
24147
24411
  isLoadDeferred,
@@ -24188,6 +24452,7 @@ function XlsxGrid({
24188
24452
  ), [formControls, getFormControlItems]);
24189
24453
  const canResizeHeaders = !readOnly || allowResizeInReadOnly;
24190
24454
  const scrollRef = React4.useRef(null);
24455
+ const scrolledHighlightRef = React4.useRef(null);
24191
24456
  const wrapperRef = React4.useRef(null);
24192
24457
  const tableRef = React4.useRef(null);
24193
24458
  const gridKeyboardActiveRef = React4.useRef(false);
@@ -24376,6 +24641,10 @@ function XlsxGrid({
24376
24641
  const resolveMergeAnchorCell = React4.useCallback((cell) => {
24377
24642
  return mergedSecondaryAnchorMap.get(`${cell.row}:${cell.col}`) ?? cell;
24378
24643
  }, [mergedSecondaryAnchorMap]);
24644
+ const highlightedCellRanges = React4.useMemo(
24645
+ () => highlightedRanges.flatMap((highlight, index) => activeSheet?.workbookSheetIndex === highlight.workbookSheetIndex ? [{ highlight, index, range: expandHighlightedRange(highlight.range, activeSheet?.mergedRanges ?? mergedRegions) }] : []),
24646
+ [activeSheet?.mergedRanges, activeSheet?.workbookSheetIndex, highlightedRanges, mergedRegions]
24647
+ );
24379
24648
  const normalizedSelection = React4.useMemo(() => selection ? normalizeRange2(selection) : null, [selection]);
24380
24649
  const zoomFactor = React4.useMemo(() => Math.max(0.1, zoomScale / 100), [zoomScale]);
24381
24650
  const previousZoomFactorRef = React4.useRef(zoomFactor);
@@ -24415,7 +24684,7 @@ function XlsxGrid({
24415
24684
  frozenPaneRight: liveFrozenPaneRight
24416
24685
  } = canvasLayoutMetricsRef.current;
24417
24686
  const currentLiveGestureZoom = liveGestureZoomRef.current;
24418
- const isLiveZooming2 = currentLiveGestureZoom !== null && zoomScale === currentLiveGestureZoom.baseZoomScale;
24687
+ const isLiveZooming2 = experimentalCanvas && currentLiveGestureZoom !== null && zoomScale === currentLiveGestureZoom.baseZoomScale;
24419
24688
  const liveZoomScale2 = isLiveZooming2 ? Math.max(0.1, currentLiveGestureZoom.targetZoomScale / currentLiveGestureZoom.baseZoomScale) : 1;
24420
24689
  const scrollDeltaX = paintedViewport.left - nextLiveViewport.left;
24421
24690
  const scrollDeltaY = paintedViewport.top - nextLiveViewport.top;
@@ -25386,7 +25655,7 @@ function XlsxGrid({
25386
25655
  }, [shouldUseDomVirtualizer, syncDrawingViewport, zoomFactor]);
25387
25656
  React4.useLayoutEffect(() => {
25388
25657
  syncDrawingViewport(scrollRef.current, { immediate: true });
25389
- }, [activeSheet, activeTabIndex, displayColLimit, displayRowLimit, syncDrawingViewport, zoomFactor]);
25658
+ }, [activeSheet, activeTabIndex, displayColLimit, displayRowLimit, highlightedCellRanges, syncDrawingViewport, zoomFactor]);
25390
25659
  React4.useLayoutEffect(() => {
25391
25660
  const scroller = scrollRef.current;
25392
25661
  if (!scroller) {
@@ -26344,7 +26613,10 @@ function XlsxGrid({
26344
26613
  });
26345
26614
  const targetTable = getTableAtCell(effectiveTables, targetRow, targetCol);
26346
26615
  const targetTableStyle = resolveTableCellStyle(targetTable, targetRow, targetCol, activeSheet);
26347
- const resolvedStyle = mergeResolvedCellStyle(targetRawStyle, targetTableStyle);
26616
+ const resolvedStyle = targetTableStyle ? mergeResolvedCellStyle(
26617
+ mergeResolvedCellStyle(targetRawStyle, targetTableStyle),
26618
+ resolveCellTableOverrides(targetRawStyle, activeSheet, targetRow, targetCol)
26619
+ ) : targetRawStyle;
26348
26620
  cellBaseRawStyleCacheRef.current.set(targetCacheKey, resolvedStyle);
26349
26621
  return resolvedStyle;
26350
26622
  };
@@ -26530,11 +26802,11 @@ function XlsxGrid({
26530
26802
  if (textWidth > availableTextWidth) {
26531
26803
  const baseFontSizePx = resolveCanvasFontSizePx(nextData.style, 12 * zoomFactor);
26532
26804
  const minimumFontSizePx = Math.max(6 * zoomFactor, baseFontSizePx * 0.4);
26533
- let lowerBound = minimumFontSizePx;
26805
+ let lowerBound2 = minimumFontSizePx;
26534
26806
  let upperBound = baseFontSizePx;
26535
26807
  let bestFontSizePx = minimumFontSizePx;
26536
- while (upperBound - lowerBound > 0.25) {
26537
- const candidateFontSizePx = (lowerBound + upperBound) / 2;
26808
+ while (upperBound - lowerBound2 > 0.25) {
26809
+ const candidateFontSizePx = (lowerBound2 + upperBound) / 2;
26538
26810
  const candidateStyle = {
26539
26811
  ...nextData.style,
26540
26812
  font: void 0,
@@ -26543,7 +26815,7 @@ function XlsxGrid({
26543
26815
  const candidateWidth = measureTextWidth(nextData.value, candidateStyle);
26544
26816
  if (candidateWidth <= availableTextWidth) {
26545
26817
  bestFontSizePx = candidateFontSizePx;
26546
- lowerBound = candidateFontSizePx;
26818
+ lowerBound2 = candidateFontSizePx;
26547
26819
  } else {
26548
26820
  upperBound = candidateFontSizePx;
26549
26821
  }
@@ -26594,6 +26866,51 @@ function XlsxGrid({
26594
26866
  };
26595
26867
  }, [colIndexByActual, colPrefixSums, displayHeaderHeight, displayRowHeaderWidth, displayedSelection, rowIndexByActual, rowPrefixSums]);
26596
26868
  const resolvedSelectionOverlay = selectionOverlay;
26869
+ const rangeHighlightRects = React4.useMemo(() => highlightedCellRanges.map(({ highlight, index, range }) => {
26870
+ const rows = getHighlightAxisExtent(visibleRows, rowPrefixSums, range.start.row, range.end.row);
26871
+ const cols = getHighlightAxisExtent(visibleCols, colPrefixSums, range.start.col, range.end.col);
26872
+ return {
26873
+ highlight,
26874
+ index,
26875
+ range,
26876
+ rect: rows && cols ? {
26877
+ height: rows.end - rows.start,
26878
+ left: displayRowHeaderWidth + cols.start,
26879
+ top: displayHeaderHeight + rows.start,
26880
+ width: cols.end - cols.start
26881
+ } : null
26882
+ };
26883
+ }), [colPrefixSums, displayHeaderHeight, displayRowHeaderWidth, highlightedCellRanges, rowPrefixSums, visibleCols, visibleRows]);
26884
+ React4.useEffect(() => {
26885
+ let requiredRows = 0;
26886
+ let requiredCols = 0;
26887
+ for (const { highlight, range } of highlightedCellRanges) {
26888
+ if (highlight.kind !== "columns") {
26889
+ requiredRows = Math.max(requiredRows, Math.min(XLSX_MAX_ROWS, range.end.row + OPEN_GRID_ROW_PADDING + 1));
26890
+ }
26891
+ if (highlight.kind !== "rows") {
26892
+ requiredCols = Math.max(requiredCols, Math.min(XLSX_MAX_COLUMNS, range.end.col + OPEN_GRID_COL_PADDING + 1));
26893
+ }
26894
+ }
26895
+ setDisplayRowLimit((current) => Math.max(current, requiredRows));
26896
+ setDisplayColLimit((current) => Math.max(current, requiredCols));
26897
+ }, [activeSheet?.maxUsedCol, activeSheet?.maxUsedRow, highlightedCellRanges, activeSheetIndex, isWorkerBacked]);
26898
+ React4.useEffect(() => {
26899
+ const scroller = scrollRef.current;
26900
+ const target = rangeHighlightRects.find(({ highlight: highlight2 }) => highlight2.autoScroll);
26901
+ if (!scroller || !target?.rect || scrolledHighlightRef.current === target.highlight || isLoading || scroller.clientWidth === 0 || scroller.clientHeight === 0 || target.highlight.kind !== "columns" && displayRowLimit <= target.range.end.row || target.highlight.kind !== "rows" && displayColLimit <= target.range.end.col) {
26902
+ return;
26903
+ }
26904
+ const { highlight, rect } = target;
26905
+ if (highlight.kind !== "columns") {
26906
+ scroller.scrollTop = getHighlightScrollOffset(rect.top, rect.top + rect.height, frozenPaneBottom, scroller.clientHeight, scroller.scrollTop);
26907
+ }
26908
+ if (highlight.kind !== "rows") {
26909
+ scroller.scrollLeft = getHighlightScrollOffset(rect.left, rect.left + rect.width, frozenPaneRight, scroller.clientWidth, scroller.scrollLeft);
26910
+ }
26911
+ scrolledHighlightRef.current = highlight;
26912
+ syncDrawingViewport(scroller, { immediate: true });
26913
+ }, [displayColLimit, displayRowLimit, drawingViewport.height, drawingViewport.width, frozenPaneBottom, frozenPaneRight, isLoading, rangeHighlightRects, syncDrawingViewport]);
26597
26914
  const { fill: selectionFill, header: selectionHeaderSurface, stroke: selectionStroke } = React4.useMemo(() => resolveSelectionColors({
26598
26915
  palette,
26599
26916
  selectionColor,
@@ -28670,6 +28987,14 @@ function XlsxGrid({
28670
28987
  hasPendingGridlinePath = false;
28671
28988
  };
28672
28989
  const drawnMergedAnchorKeys = /* @__PURE__ */ new Set();
28990
+ const deferredDoubleBorders = [];
28991
+ const drawCellBorder = (side, rect, border) => {
28992
+ if (border.style === "double") {
28993
+ deferredDoubleBorders.push({ side, rect, border });
28994
+ } else {
28995
+ strokeCanvasBorderSide(paneContext, side, rect, border);
28996
+ }
28997
+ };
28673
28998
  for (const rowItem of paneAxisItems.rows) {
28674
28999
  for (const colItem of paneAxisItems.cols) {
28675
29000
  const cell = { row: rowItem.actualRow, col: colItem.actualCol };
@@ -28816,16 +29141,24 @@ function XlsxGrid({
28816
29141
  flushPendingGridlines();
28817
29142
  }
28818
29143
  if (topBorder && drawRowIndex === 0) {
28819
- strokeCanvasBorderSide(paneContext, "top", localRect, topBorder);
29144
+ drawCellBorder("top", localRect, topBorder);
28820
29145
  }
28821
29146
  if (resolvedRightBorder) {
28822
- strokeCanvasBorderSide(paneContext, "right", localRect, resolvedRightBorder);
29147
+ if (resolvedRightBorder.style === "double" && resolvedRightBorder === rightNeighborLeftBorder) {
29148
+ drawCellBorder("left", { ...localRect, left: localRect.left + localRect.width }, resolvedRightBorder);
29149
+ } else {
29150
+ drawCellBorder("right", localRect, resolvedRightBorder);
29151
+ }
28823
29152
  }
28824
29153
  if (resolvedBottomBorder) {
28825
- strokeCanvasBorderSide(paneContext, "bottom", localRect, resolvedBottomBorder);
29154
+ if (resolvedBottomBorder.style === "double" && resolvedBottomBorder === bottomNeighborTopBorder) {
29155
+ drawCellBorder("top", { ...localRect, top: localRect.top + localRect.height }, resolvedBottomBorder);
29156
+ } else {
29157
+ drawCellBorder("bottom", localRect, resolvedBottomBorder);
29158
+ }
28826
29159
  }
28827
29160
  if (leftBorder && drawColIndex === 0) {
28828
- strokeCanvasBorderSide(paneContext, "left", localRect, leftBorder);
29161
+ drawCellBorder("left", localRect, leftBorder);
28829
29162
  }
28830
29163
  if (cellData.chartHighlight) {
28831
29164
  const highlightBorder = {
@@ -29098,6 +29431,9 @@ function XlsxGrid({
29098
29431
  }
29099
29432
  }
29100
29433
  flushPendingGridlines();
29434
+ for (const { side, rect, border } of deferredDoubleBorders) {
29435
+ strokeCanvasBorderSide(paneContext, side, rect, border);
29436
+ }
29101
29437
  }
29102
29438
  for (const pane of cellPaneOrder) {
29103
29439
  const paneContext = bodyContexts[pane];
@@ -29609,6 +29945,7 @@ function XlsxGrid({
29609
29945
  backgroundColor: palette.headerSurface,
29610
29946
  borderBottom: "none",
29611
29947
  borderRight: "none",
29948
+ boxSizing: "border-box",
29612
29949
  boxShadow: gutterSeparatorShadow,
29613
29950
  color: palette.headerText,
29614
29951
  fontSize: "11px",
@@ -31300,6 +31637,51 @@ function XlsxGrid({
31300
31637
  width: "100%"
31301
31638
  }
31302
31639
  };
31640
+ const rangeHighlightNodes = rangeHighlightRects.flatMap(({ index, rect }) => rect ? [
31641
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31642
+ "div",
31643
+ {
31644
+ "aria-hidden": "true",
31645
+ className: classNames("react-xlsx-range-highlight", highlightClassName),
31646
+ "data-dark": paletteIsDark(palette) ? "true" : void 0,
31647
+ "data-xlsx-range-highlight": index,
31648
+ style: {
31649
+ ...rect,
31650
+ ["--xlsx-highlight-default-border-width"]: `${selectionBorderWidth}px`,
31651
+ boxSizing: "border-box",
31652
+ pointerEvents: "none",
31653
+ position: "absolute",
31654
+ zIndex: maxDrawingOverlayZIndex + 1
31655
+ }
31656
+ },
31657
+ index
31658
+ )
31659
+ ] : []);
31660
+ const drawingOverlayPanes = experimentalCanvas && hasCanvasDomDrawingOverlays || rangeHighlightNodes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...canvasBodyViewportLayerStyle, zIndex: experimentalCanvas ? 23 : 34 }, children: [
31661
+ { pane: "scroll", style: canvasScrollOverlayPaneStyle, ref: canvasScrollOverlayContentRef, left: -drawingViewport.left - frozenPaneRight, top: -drawingViewport.top - frozenPaneBottom },
31662
+ { pane: "top", style: canvasTopOverlayPaneStyle, ref: canvasTopOverlayContentRef, left: -drawingViewport.left - frozenPaneRight, top: -displayHeaderHeight },
31663
+ { pane: "left", style: canvasLeftOverlayPaneStyle, ref: canvasLeftOverlayContentRef, left: -displayRowHeaderWidth, top: -drawingViewport.top - frozenPaneBottom },
31664
+ { pane: "corner", style: canvasCornerOverlayPaneStyle, ref: canvasCornerOverlayContentRef, left: -displayRowHeaderWidth, top: -displayHeaderHeight }
31665
+ ].map(({ pane, style, ref, left, top }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
31666
+ "div",
31667
+ {
31668
+ ref,
31669
+ style: {
31670
+ height: sheetContentHeight,
31671
+ left: 0,
31672
+ pointerEvents: "none",
31673
+ position: "absolute",
31674
+ top: 0,
31675
+ transform: `translate(${left}px, ${top}px)`,
31676
+ transformOrigin: "0 0",
31677
+ width: totalWidth
31678
+ },
31679
+ children: [
31680
+ experimentalCanvas ? paneDrawingNodes[pane] : null,
31681
+ rangeHighlightNodes
31682
+ ]
31683
+ }
31684
+ ) }, pane)) }) : null;
31303
31685
  const scrollerContent = /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31304
31686
  "div",
31305
31687
  {
@@ -31333,6 +31715,7 @@ function XlsxGrid({
31333
31715
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: cornerOverlayStyle, children: paneDrawingNodes.corner }),
31334
31716
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: scrollOverlayStyle, children: paneDrawingNodes.scroll })
31335
31717
  ] }) : null,
31718
+ drawingOverlayPanes,
31336
31719
  experimentalCanvas ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
31337
31720
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: canvasBodyViewportLayerStyle, children: [
31338
31721
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -31374,77 +31757,7 @@ function XlsxGrid({
31374
31757
  onPointerDown: handleCanvasBodyPointerDown,
31375
31758
  style: canvasCornerBodyStyle
31376
31759
  }
31377
- ),
31378
- hasCanvasDomDrawingOverlays ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
31379
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasScrollOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31380
- "div",
31381
- {
31382
- ref: canvasScrollOverlayContentRef,
31383
- style: {
31384
- height: sheetContentHeight,
31385
- left: 0,
31386
- pointerEvents: "none",
31387
- position: "absolute",
31388
- top: 0,
31389
- transform: `translate(${-drawingViewport.left - frozenPaneRight}px, ${-drawingViewport.top - frozenPaneBottom}px)`,
31390
- transformOrigin: "0 0",
31391
- width: totalWidth
31392
- },
31393
- children: paneDrawingNodes.scroll
31394
- }
31395
- ) }),
31396
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasTopOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31397
- "div",
31398
- {
31399
- ref: canvasTopOverlayContentRef,
31400
- style: {
31401
- height: sheetContentHeight,
31402
- left: 0,
31403
- pointerEvents: "none",
31404
- position: "absolute",
31405
- top: 0,
31406
- transform: `translate(${-drawingViewport.left - frozenPaneRight}px, ${-displayHeaderHeight}px)`,
31407
- transformOrigin: "0 0",
31408
- width: totalWidth
31409
- },
31410
- children: paneDrawingNodes.top
31411
- }
31412
- ) }),
31413
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasLeftOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31414
- "div",
31415
- {
31416
- ref: canvasLeftOverlayContentRef,
31417
- style: {
31418
- height: sheetContentHeight,
31419
- left: 0,
31420
- pointerEvents: "none",
31421
- position: "absolute",
31422
- top: 0,
31423
- transform: `translate(${-displayRowHeaderWidth}px, ${-drawingViewport.top - frozenPaneBottom}px)`,
31424
- transformOrigin: "0 0",
31425
- width: totalWidth
31426
- },
31427
- children: paneDrawingNodes.left
31428
- }
31429
- ) }),
31430
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: canvasCornerOverlayPaneStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31431
- "div",
31432
- {
31433
- ref: canvasCornerOverlayContentRef,
31434
- style: {
31435
- height: sheetContentHeight,
31436
- left: 0,
31437
- pointerEvents: "none",
31438
- position: "absolute",
31439
- top: 0,
31440
- transform: `translate(${-displayRowHeaderWidth}px, ${-displayHeaderHeight}px)`,
31441
- transformOrigin: "0 0",
31442
- width: totalWidth
31443
- },
31444
- children: paneDrawingNodes.corner
31445
- }
31446
- ) })
31447
- ] }) : null
31760
+ )
31448
31761
  ] }),
31449
31762
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: canvasHeaderViewportLayerStyle, children: [
31450
31763
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -31890,6 +32203,7 @@ function XlsxGrid({
31890
32203
  }
31891
32204
  function XlsxViewerInner({
31892
32205
  allowResizeInReadOnly = false,
32206
+ autoScrollToHighlightedRanges = true,
31893
32207
  className,
31894
32208
  controller,
31895
32209
  emptyState,
@@ -31902,6 +32216,8 @@ function XlsxViewerInner({
31902
32216
  headerBackgroundColor,
31903
32217
  headerTextColor,
31904
32218
  height,
32219
+ highlightClassName,
32220
+ highlightedRanges,
31905
32221
  isDark = false,
31906
32222
  loadingComponent,
31907
32223
  loadingState,
@@ -31924,6 +32240,26 @@ function XlsxViewerInner({
31924
32240
  }) {
31925
32241
  const palette = useViewerPalette(isDark, headerBackgroundColor, headerTextColor);
31926
32242
  const { displayFileName, error } = controller;
32243
+ const appliedHighlightRef = React4.useRef(null);
32244
+ const { clearHighlightedRanges, file, highlightRanges, isLoading, sheets, src } = controller;
32245
+ React4.useEffect(() => {
32246
+ if (isLoading || highlightedRanges === void 0) {
32247
+ appliedHighlightRef.current = null;
32248
+ return;
32249
+ }
32250
+ if (highlightedRanges !== null && sheets.length === 0) {
32251
+ return;
32252
+ }
32253
+ const referenceKey = JSON.stringify(typeof highlightedRanges === "string" ? [highlightedRanges] : highlightedRanges ?? []);
32254
+ const previous = appliedHighlightRef.current;
32255
+ if (previous && previous.referenceKey === referenceKey && previous.autoScroll === autoScrollToHighlightedRanges && previous.file === file && previous.src === src && previous.clear === clearHighlightedRanges) {
32256
+ return;
32257
+ }
32258
+ appliedHighlightRef.current = { autoScroll: autoScrollToHighlightedRanges, clear: clearHighlightedRanges, file, referenceKey, src };
32259
+ if (highlightedRanges === null || !highlightRanges(highlightedRanges, { autoScroll: autoScrollToHighlightedRanges })) {
32260
+ clearHighlightedRanges();
32261
+ }
32262
+ }, [autoScrollToHighlightedRanges, clearHighlightedRanges, file, highlightRanges, highlightedRanges, isLoading, sheets.length, src]);
31927
32263
  const customFileTooLarge = error instanceof XlsxFileSizeLimitExceededError ? renderCustomFileTooLarge(
31928
32264
  fileTooLargeState,
31929
32265
  {
@@ -31956,6 +32292,7 @@ function XlsxViewerInner({
31956
32292
  width: "100%"
31957
32293
  },
31958
32294
  children: [
32295
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("style", { children: RANGE_HIGHLIGHT_STYLES }),
31959
32296
  resolveToolbar(toolbar, showDefaultToolbar, controller, palette),
31960
32297
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", flex: 1, minHeight: 0, minWidth: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31961
32298
  XlsxGrid,
@@ -31969,6 +32306,7 @@ function XlsxViewerInner({
31969
32306
  experimentalCanvas,
31970
32307
  fileTooLargeState,
31971
32308
  getCellStyle,
32309
+ highlightClassName,
31972
32310
  loadingComponent,
31973
32311
  loadingState,
31974
32312
  onFormControlAction,
@@ -33126,6 +33464,7 @@ function DefaultXlsxToolbar() {
33126
33464
  XlsxViewer,
33127
33465
  XlsxViewerProvider,
33128
33466
  initWasm,
33467
+ parseXlsxRange,
33129
33468
  setWasmSource,
33130
33469
  useXlsxViewer,
33131
33470
  useXlsxViewerCharts,