@extend-ai/react-xlsx 0.17.1 → 0.17.3

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
@@ -6707,13 +6707,52 @@ function hasUnresolvedSheetReferences(workbook) {
6707
6707
  }
6708
6708
  return false;
6709
6709
  }
6710
+ function collectFormulaCellsWithSavedValues(workbook) {
6711
+ const positions = [];
6712
+ for (let sheetIdx = 0; sheetIdx < workbook.sheetCount; sheetIdx += 1) {
6713
+ let sheet;
6714
+ try {
6715
+ sheet = workbook.getSheet(sheetIdx);
6716
+ } catch {
6717
+ continue;
6718
+ }
6719
+ const cells = sheet.formulaCells;
6720
+ if (!Array.isArray(cells)) {
6721
+ continue;
6722
+ }
6723
+ for (const cell of cells) {
6724
+ if (typeof cell?.row !== "number" || typeof cell?.col !== "number") {
6725
+ continue;
6726
+ }
6727
+ let saved;
6728
+ try {
6729
+ saved = sheet.getCalculatedValueAt(cell.row, cell.col);
6730
+ } catch {
6731
+ continue;
6732
+ }
6733
+ if (!saved.is_empty && !saved.is_error) {
6734
+ positions.push({ sheetIdx, row: cell.row, col: cell.col });
6735
+ }
6736
+ }
6737
+ }
6738
+ return positions;
6739
+ }
6740
+ function anyBecameError(workbook, positions) {
6741
+ return positions.some(({ sheetIdx, row, col }) => {
6742
+ try {
6743
+ return workbook.getSheet(sheetIdx).getCalculatedValueAt(row, col).is_error;
6744
+ } catch {
6745
+ return false;
6746
+ }
6747
+ });
6748
+ }
6710
6749
  function safeCalculate(workbook, options = {}) {
6711
6750
  if (hasUnresolvedSheetReferences(workbook)) {
6712
6751
  return { workbook, calculated: false, skipReason: "unresolved-sheet-refs" };
6713
6752
  }
6753
+ const withSavedValues = options.reparse ? collectFormulaCellsWithSavedValues(workbook) : [];
6714
6754
  try {
6715
6755
  workbook.calculate();
6716
- return { workbook, calculated: true, skipReason: null };
6717
6756
  } catch (err) {
6718
6757
  console.warn("[react-xlsx] workbook.calculate() trapped; falling back to cached formula values", err);
6719
6758
  if (options.reparse) {
@@ -6725,6 +6764,14 @@ function safeCalculate(workbook, options = {}) {
6725
6764
  }
6726
6765
  return { workbook, calculated: false, skipReason: "calculate-trapped" };
6727
6766
  }
6767
+ if (options.reparse && anyBecameError(workbook, withSavedValues)) {
6768
+ try {
6769
+ return { workbook: options.reparse(), calculated: false, skipReason: "calculate-regressed" };
6770
+ } catch (reparseErr) {
6771
+ console.warn("[react-xlsx] workbook reparse after calculate regression failed", reparseErr);
6772
+ }
6773
+ }
6774
+ return { workbook, calculated: true, skipReason: null };
6728
6775
  }
6729
6776
  function tryRecalculate(workbook) {
6730
6777
  try {
@@ -24483,6 +24530,9 @@ function XlsxGrid({
24483
24530
  const canvasCornerOverlayContentRef = React4.useRef(null);
24484
24531
  const canvasImageCacheRef = React4.useRef(/* @__PURE__ */ new Map());
24485
24532
  const selectionOverlayRef = React4.useRef(null);
24533
+ const selectionPaneContentRefs = React4.useRef(/* @__PURE__ */ new Map());
24534
+ const selectionPaneOverlayRefs = React4.useRef(/* @__PURE__ */ new Map());
24535
+ const selectionPaneFillHandleRefs = React4.useRef(/* @__PURE__ */ new Map());
24486
24536
  const canvasSelectionLayerRef = React4.useRef(null);
24487
24537
  const activeValidationOverlayRef = React4.useRef(null);
24488
24538
  const fillHandleRef = React4.useRef(null);
@@ -24744,15 +24794,17 @@ function XlsxGrid({
24744
24794
  shouldTransform ? "transform" : ""
24745
24795
  );
24746
24796
  };
24747
- const applyOverlayTransform = (element, baseTranslateX, baseTranslateY, paneLeft, paneTop, anchorX, anchorY) => {
24797
+ const applyOverlayTransform = (pane, element, baseTranslateX, baseTranslateY, paneLeft, paneTop, anchorX, anchorY) => {
24748
24798
  const translateX = resolveLiveTranslation(baseTranslateX, anchorX, paneLeft);
24749
24799
  const translateY = resolveLiveTranslation(baseTranslateY, anchorY, paneTop);
24750
- applyElementTransform(
24751
- element,
24752
- liveZoomScale2 !== 1 ? `translate3d(${translateX}px, ${translateY}px, 0) scale(${liveZoomScale2})` : `translate3d(${baseTranslateX}px, ${baseTranslateY}px, 0)`,
24753
- "transform",
24754
- "0 0"
24755
- );
24800
+ for (const content of [element, selectionPaneContentRefs.current.get(pane) ?? null]) {
24801
+ applyElementTransform(
24802
+ content,
24803
+ liveZoomScale2 !== 1 ? `translate3d(${translateX}px, ${translateY}px, 0) scale(${liveZoomScale2})` : `translate3d(${baseTranslateX}px, ${baseTranslateY}px, 0)`,
24804
+ "transform",
24805
+ "0 0"
24806
+ );
24807
+ }
24756
24808
  };
24757
24809
  const liveScrollBodyViewportWidth = Math.max(0, nextLiveViewport.width - liveFrozenPaneRight);
24758
24810
  const liveScrollBodyViewportHeight = Math.max(0, nextLiveViewport.height - liveFrozenPaneBottom);
@@ -24849,6 +24901,7 @@ function XlsxGrid({
24849
24901
  0
24850
24902
  );
24851
24903
  applyOverlayTransform(
24904
+ "scroll",
24852
24905
  canvasScrollOverlayContentRef.current,
24853
24906
  -nextLiveViewport.left - liveFrozenPaneRight,
24854
24907
  -nextLiveViewport.top - liveFrozenPaneBottom,
@@ -24858,6 +24911,7 @@ function XlsxGrid({
24858
24911
  liveZoomAnchorY
24859
24912
  );
24860
24913
  applyOverlayTransform(
24914
+ "top",
24861
24915
  canvasTopOverlayContentRef.current,
24862
24916
  -nextLiveViewport.left - liveFrozenPaneRight,
24863
24917
  -liveDisplayHeaderHeight,
@@ -24867,6 +24921,7 @@ function XlsxGrid({
24867
24921
  0
24868
24922
  );
24869
24923
  applyOverlayTransform(
24924
+ "left",
24870
24925
  canvasLeftOverlayContentRef.current,
24871
24926
  -liveDisplayRowHeaderWidth,
24872
24927
  -nextLiveViewport.top - liveFrozenPaneBottom,
@@ -24876,6 +24931,7 @@ function XlsxGrid({
24876
24931
  liveZoomAnchorY
24877
24932
  );
24878
24933
  applyOverlayTransform(
24934
+ "corner",
24879
24935
  canvasCornerOverlayContentRef.current,
24880
24936
  -liveDisplayRowHeaderWidth,
24881
24937
  -liveDisplayHeaderHeight,
@@ -27489,36 +27545,46 @@ function XlsxGrid({
27489
27545
  colHeaderCellRefs.current.delete(actualCol);
27490
27546
  }, [experimentalCanvas, palette.headerSurface]);
27491
27547
  const applyPreviewOverlay = React4.useCallback((range, options) => {
27492
- const overlay = selectionOverlayRef.current;
27493
- if (!overlay || !range) {
27548
+ const overlays = experimentalCanvas ? [...selectionPaneOverlayRefs.current.values()] : [selectionOverlayRef.current];
27549
+ if (!range) {
27494
27550
  if (options?.updateHeaderSelection !== false) {
27495
27551
  applyHeaderSelection(range);
27496
27552
  }
27497
27553
  return;
27498
27554
  }
27499
- const nextRect = options?.preferGeometry ? resolveGeometryOverlayRect(range) ?? resolveOverlayRect(range) : selectionDragRef.current?.didDrag || fillDragRef.current ? resolveDragPreviewRect(range) ?? resolveGeometryOverlayRect(range) ?? resolveOverlayRect(range) : resolveOverlayRect(range);
27555
+ const nextRect = experimentalCanvas || options?.preferGeometry ? resolveGeometryOverlayRect(range) ?? resolveOverlayRect(range) : selectionDragRef.current?.didDrag || fillDragRef.current ? resolveDragPreviewRect(range) ?? resolveGeometryOverlayRect(range) ?? resolveOverlayRect(range) : resolveOverlayRect(range);
27500
27556
  if (!nextRect) {
27501
27557
  if (options?.updateHeaderSelection !== false) {
27502
27558
  applyHeaderSelection(range);
27503
27559
  }
27504
27560
  return;
27505
27561
  }
27506
- overlay.style.left = `${nextRect.left}px`;
27507
- overlay.style.top = `${nextRect.top}px`;
27508
- overlay.style.width = `${nextRect.width}px`;
27509
- overlay.style.height = `${nextRect.height}px`;
27510
- overlay.style.opacity = "1";
27511
- overlay.style.visibility = "visible";
27512
- const fillHandle = fillHandleRef.current;
27513
- if (fillHandle) {
27514
- fillHandle.style.left = `${nextRect.left + nextRect.width - 4 * zoomFactor}px`;
27515
- fillHandle.style.top = `${nextRect.top + nextRect.height - 4 * zoomFactor}px`;
27562
+ for (const overlay of overlays) {
27563
+ if (overlay) {
27564
+ overlay.style.left = `${nextRect.left}px`;
27565
+ overlay.style.top = `${nextRect.top}px`;
27566
+ overlay.style.width = `${nextRect.width}px`;
27567
+ overlay.style.height = `${nextRect.height}px`;
27568
+ overlay.style.opacity = "1";
27569
+ overlay.style.visibility = "visible";
27570
+ }
27571
+ }
27572
+ const fillHandles = experimentalCanvas ? [...selectionPaneFillHandleRefs.current.values()] : [fillHandleRef.current];
27573
+ for (const fillHandle of fillHandles) {
27574
+ if (fillHandle) {
27575
+ fillHandle.style.left = `${nextRect.left + nextRect.width - 4 * zoomFactor}px`;
27576
+ fillHandle.style.top = `${nextRect.top + nextRect.height - 4 * zoomFactor}px`;
27577
+ }
27516
27578
  }
27517
27579
  if (options?.updateHeaderSelection !== false) {
27518
27580
  applyHeaderSelection(range);
27519
27581
  }
27520
- }, [applyHeaderSelection, resolveDragPreviewRect, resolveGeometryOverlayRect, resolveOverlayRect, zoomFactor]);
27582
+ }, [applyHeaderSelection, experimentalCanvas, resolveDragPreviewRect, resolveGeometryOverlayRect, resolveOverlayRect, zoomFactor]);
27521
27583
  const applyPreviewOverlayFromElement = React4.useCallback((element, range) => {
27584
+ if (experimentalCanvas) {
27585
+ applyPreviewOverlay(range);
27586
+ return;
27587
+ }
27522
27588
  const overlay = selectionOverlayRef.current;
27523
27589
  if (!overlay) {
27524
27590
  return;
@@ -27540,7 +27606,7 @@ function XlsxGrid({
27540
27606
  fillHandle.style.top = `${nextRect.top + nextRect.height - 4 * zoomFactor}px`;
27541
27607
  }
27542
27608
  applyHeaderSelection(range);
27543
- }, [applyHeaderSelection, resolveMountedCellOverlayRect, resolveOverlayRect, zoomFactor]);
27609
+ }, [applyHeaderSelection, applyPreviewOverlay, experimentalCanvas, resolveMountedCellOverlayRect, resolveOverlayRect, zoomFactor]);
27544
27610
  const syncActiveValidationOverlay = React4.useCallback((cell) => {
27545
27611
  const overlay = activeValidationOverlayRef.current;
27546
27612
  if (!overlay || !cell || editingCellRef.current || selectionDragRef.current || fillDragRef.current) {
@@ -27974,9 +28040,11 @@ function XlsxGrid({
27974
28040
  const overlayRange = selectionPreviewRangeRef.current ?? displayedSelection;
27975
28041
  if (!overlayRange || !wrapperRef.current) {
27976
28042
  applyHeaderSelection(null);
27977
- if (selectionOverlayRef.current) {
27978
- selectionOverlayRef.current.style.opacity = "0";
27979
- selectionOverlayRef.current.style.visibility = "hidden";
28043
+ for (const overlay of [selectionOverlayRef.current, ...selectionPaneOverlayRefs.current.values()]) {
28044
+ if (overlay) {
28045
+ overlay.style.opacity = "0";
28046
+ overlay.style.visibility = "hidden";
28047
+ }
27980
28048
  }
27981
28049
  return;
27982
28050
  }
@@ -31657,12 +31725,104 @@ function XlsxGrid({
31657
31725
  index
31658
31726
  )
31659
31727
  ] : []);
31660
- const drawingOverlayPanes = experimentalCanvas && hasCanvasDomDrawingOverlays || rangeHighlightNodes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...canvasBodyViewportLayerStyle, zIndex: experimentalCanvas ? 23 : 34 }, children: [
31728
+ function renderSelectionOverlay(pane) {
31729
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
31730
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31731
+ "div",
31732
+ {
31733
+ ref: pane ? (element) => {
31734
+ if (element) {
31735
+ selectionPaneOverlayRefs.current.set(pane, element);
31736
+ } else {
31737
+ selectionPaneOverlayRefs.current.delete(pane);
31738
+ }
31739
+ } : selectionOverlayRef,
31740
+ style: {
31741
+ backgroundColor: selectionFill,
31742
+ boxSizing: "border-box",
31743
+ boxShadow: `inset 0 0 0 ${selectionBorderWidth}px ${selectionStroke}`,
31744
+ contain: "layout paint",
31745
+ height: resolvedSelectionOverlay?.height ?? 0,
31746
+ left: resolvedSelectionOverlay?.left ?? 0,
31747
+ opacity: resolvedSelectionOverlay ? 1 : 0,
31748
+ pointerEvents: "none",
31749
+ position: "absolute",
31750
+ top: resolvedSelectionOverlay?.top ?? 0,
31751
+ transition: canvasSelectionTransition,
31752
+ visibility: resolvedSelectionOverlay ? "visible" : "hidden",
31753
+ willChange: shouldAnimateCanvasSelectionGeometry ? "left, top, width, height" : void 0,
31754
+ width: resolvedSelectionOverlay?.width ?? 0,
31755
+ zIndex: 24
31756
+ }
31757
+ }
31758
+ ),
31759
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31760
+ "div",
31761
+ {
31762
+ ref: pane ? (element) => {
31763
+ if (element) {
31764
+ selectionPaneFillHandleRefs.current.set(pane, element);
31765
+ } else {
31766
+ selectionPaneFillHandleRefs.current.delete(pane);
31767
+ }
31768
+ } : fillHandleRef,
31769
+ onPointerDown: (event) => {
31770
+ if (readOnly || event.button !== 0 || !normalizedSelection || !resolvedSelectionOverlay) {
31771
+ return;
31772
+ }
31773
+ event.preventDefault();
31774
+ event.stopPropagation();
31775
+ startFillDrag(event.pointerId, normalizedSelection);
31776
+ },
31777
+ style: {
31778
+ backgroundColor: selectionStroke,
31779
+ border: `${Math.max(1, zoomFactor)}px solid ${palette.surface}`,
31780
+ contain: "layout paint",
31781
+ cursor: "crosshair",
31782
+ display: !readOnly && resolvedSelectionOverlay ? "block" : "none",
31783
+ height: 8 * zoomFactor,
31784
+ left: resolvedSelectionOverlay ? resolvedSelectionOverlay.left + resolvedSelectionOverlay.width - 4 * zoomFactor : 0,
31785
+ pointerEvents: "auto",
31786
+ position: "absolute",
31787
+ top: resolvedSelectionOverlay ? resolvedSelectionOverlay.top + resolvedSelectionOverlay.height - 4 * zoomFactor : 0,
31788
+ transition: shouldAnimateCanvasSelectionGeometry ? "left 120ms cubic-bezier(0.22, 1, 0.36, 1), top 120ms cubic-bezier(0.22, 1, 0.36, 1)" : "none",
31789
+ willChange: shouldAnimateCanvasSelectionGeometry ? "left, top" : void 0,
31790
+ width: 8 * zoomFactor,
31791
+ zIndex: 25
31792
+ }
31793
+ }
31794
+ )
31795
+ ] });
31796
+ }
31797
+ const overlayPanes = [
31661
31798
  { pane: "scroll", style: canvasScrollOverlayPaneStyle, ref: canvasScrollOverlayContentRef, left: -drawingViewport.left - frozenPaneRight, top: -drawingViewport.top - frozenPaneBottom },
31662
31799
  { pane: "top", style: canvasTopOverlayPaneStyle, ref: canvasTopOverlayContentRef, left: -drawingViewport.left - frozenPaneRight, top: -displayHeaderHeight },
31663
31800
  { pane: "left", style: canvasLeftOverlayPaneStyle, ref: canvasLeftOverlayContentRef, left: -displayRowHeaderWidth, top: -drawingViewport.top - frozenPaneBottom },
31664
31801
  { 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)(
31802
+ ];
31803
+ const selectionOverlayPanes = experimentalCanvas ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...canvasBodyViewportLayerStyle, zIndex: 40 }, children: overlayPanes.map(({ pane, style, left, top }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
31804
+ "div",
31805
+ {
31806
+ ref: (element) => {
31807
+ if (element) {
31808
+ selectionPaneContentRefs.current.set(pane, element);
31809
+ } else {
31810
+ selectionPaneContentRefs.current.delete(pane);
31811
+ }
31812
+ },
31813
+ style: {
31814
+ height: sheetContentHeight,
31815
+ left: 0,
31816
+ position: "absolute",
31817
+ top: 0,
31818
+ transform: `translate(${left}px, ${top}px)`,
31819
+ transformOrigin: "0 0",
31820
+ width: totalWidth
31821
+ },
31822
+ children: renderSelectionOverlay(pane)
31823
+ }
31824
+ ) }, pane)) }) : null;
31825
+ const drawingOverlayPanes = experimentalCanvas && hasCanvasDomDrawingOverlays || rangeHighlightNodes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...canvasBodyViewportLayerStyle, zIndex: experimentalCanvas ? 23 : 34 }, children: overlayPanes.map(({ pane, style, ref, left, top }) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
31666
31826
  "div",
31667
31827
  {
31668
31828
  ref,
@@ -31716,6 +31876,7 @@ function XlsxGrid({
31716
31876
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: scrollOverlayStyle, children: paneDrawingNodes.scroll })
31717
31877
  ] }) : null,
31718
31878
  drawingOverlayPanes,
31879
+ selectionOverlayPanes,
31719
31880
  experimentalCanvas ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
31720
31881
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: canvasBodyViewportLayerStyle, children: [
31721
31882
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -32048,29 +32209,7 @@ function XlsxGrid({
32048
32209
  zIndex: 24
32049
32210
  },
32050
32211
  children: [
32051
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
32052
- "div",
32053
- {
32054
- ref: selectionOverlayRef,
32055
- style: {
32056
- backgroundColor: selectionFill,
32057
- boxSizing: "border-box",
32058
- boxShadow: `inset 0 0 0 ${selectionBorderWidth}px ${selectionStroke}`,
32059
- contain: "layout paint",
32060
- height: resolvedSelectionOverlay?.height ?? 0,
32061
- left: resolvedSelectionOverlay?.left ?? 0,
32062
- opacity: resolvedSelectionOverlay ? 1 : 0,
32063
- pointerEvents: "none",
32064
- position: "absolute",
32065
- top: resolvedSelectionOverlay?.top ?? 0,
32066
- transition: canvasSelectionTransition,
32067
- visibility: resolvedSelectionOverlay ? "visible" : "hidden",
32068
- willChange: shouldAnimateCanvasSelectionGeometry ? "left, top, width, height" : void 0,
32069
- width: resolvedSelectionOverlay?.width ?? 0,
32070
- zIndex: 24
32071
- }
32072
- }
32073
- ),
32212
+ !experimentalCanvas ? renderSelectionOverlay() : null,
32074
32213
  activeCellOverlay != null && activeCellOverlayRect ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
32075
32214
  "div",
32076
32215
  {
@@ -32110,36 +32249,6 @@ function XlsxGrid({
32110
32249
  },
32111
32250
  children: "\u25BE"
32112
32251
  }
32113
- ),
32114
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
32115
- "div",
32116
- {
32117
- ref: fillHandleRef,
32118
- onPointerDown: (event) => {
32119
- if (readOnly || event.button !== 0 || !normalizedSelection || !resolvedSelectionOverlay) {
32120
- return;
32121
- }
32122
- event.preventDefault();
32123
- event.stopPropagation();
32124
- startFillDrag(event.pointerId, normalizedSelection);
32125
- },
32126
- style: {
32127
- backgroundColor: selectionStroke,
32128
- border: `${Math.max(1, zoomFactor)}px solid ${palette.surface}`,
32129
- contain: "layout paint",
32130
- cursor: "crosshair",
32131
- display: !readOnly && resolvedSelectionOverlay ? "block" : "none",
32132
- height: 8 * zoomFactor,
32133
- left: resolvedSelectionOverlay ? resolvedSelectionOverlay.left + resolvedSelectionOverlay.width - 4 * zoomFactor : 0,
32134
- pointerEvents: "auto",
32135
- position: "absolute",
32136
- top: resolvedSelectionOverlay ? resolvedSelectionOverlay.top + resolvedSelectionOverlay.height - 4 * zoomFactor : 0,
32137
- transition: shouldAnimateCanvasSelectionGeometry ? "left 120ms cubic-bezier(0.22, 1, 0.36, 1), top 120ms cubic-bezier(0.22, 1, 0.36, 1)" : "none",
32138
- willChange: shouldAnimateCanvasSelectionGeometry ? "left, top" : void 0,
32139
- width: 8 * zoomFactor,
32140
- zIndex: 25
32141
- }
32142
- }
32143
32252
  )
32144
32253
  ]
32145
32254
  }