@extend-ai/react-xlsx 0.15.1 → 0.16.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/README.md CHANGED
@@ -468,6 +468,8 @@ Common rendering props:
468
468
  - `height?: React.CSSProperties["height"]`
469
469
  - `className?: string`
470
470
  - `isDark?: boolean`
471
+ - `headerBackgroundColor?: string`
472
+ - `headerTextColor?: string`
471
473
  - `rounded?: boolean`
472
474
  - `showDefaultToolbar?: boolean`
473
475
  - `toolbar?: React.ReactNode | ((controller: XlsxViewerController) => React.ReactNode)`
package/dist/index.cjs CHANGED
@@ -11089,6 +11089,14 @@ function useXlsxViewerController(options) {
11089
11089
  var React4 = __toESM(require("react"), 1);
11090
11090
  var import_react_virtual = require("@tanstack/react-virtual");
11091
11091
 
11092
+ // src/cell-text-clip.ts
11093
+ function resolveCellTextClipOverscan(overscan, usesWrappedText) {
11094
+ return {
11095
+ horizontal: overscan,
11096
+ vertical: usesWrappedText ? 0 : overscan
11097
+ };
11098
+ }
11099
+
11092
11100
  // src/chart-renderer.tsx
11093
11101
  var import_d3_hierarchy = require("d3-hierarchy");
11094
11102
  var import_d3_geo = require("d3-geo");
@@ -17834,6 +17842,67 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({
17834
17842
  );
17835
17843
  }, (prev, next) => prev.chart === next.chart && prev.onChartElementDoubleClick === next.onChartElementDoubleClick && prev.onChartElementPointerDown === next.onChartElementPointerDown && prev.palette === next.palette && prev.rect.height === next.rect.height && prev.rect.width === next.rect.width && prev.rect.left === next.rect.left && prev.rect.top === next.rect.top && prev.selectedChartElement === next.selectedChartElement);
17836
17844
 
17845
+ // src/viewer-palette.ts
17846
+ var LIGHT_PALETTE = {
17847
+ border: "#e4e4e7",
17848
+ buttonSurface: "#ffffff",
17849
+ buttonText: "#18181b",
17850
+ canvas: "#fafafa",
17851
+ danger: "#dc2626",
17852
+ headerSurface: "#f4f4f5",
17853
+ headerText: "#71717a",
17854
+ mutedSurface: "#f5f5f5",
17855
+ mutedText: "#71717a",
17856
+ rowHeaderSurface: "#f4f4f5",
17857
+ shadow: "0 1px 2px rgba(0, 0, 0, 0.04)",
17858
+ sheetActiveSurface: "#ffffff",
17859
+ sheetActiveText: "#18181b",
17860
+ sheetInactiveSurface: "#e4e4e7",
17861
+ sheetInactiveText: "#52525b",
17862
+ strongBorder: "#d4d4d8",
17863
+ subtleSurface: "#fafafa",
17864
+ surface: "#ffffff",
17865
+ text: "#18181b",
17866
+ toolbarSurface: "#f5f5f5"
17867
+ };
17868
+ var DARK_PALETTE = {
17869
+ border: "rgba(255, 255, 255, 0.10)",
17870
+ buttonSurface: "rgba(255, 255, 255, 0.06)",
17871
+ buttonText: "#f4f4f5",
17872
+ canvas: "#09090b",
17873
+ danger: "#f87171",
17874
+ headerSurface: "#18181b",
17875
+ headerText: "#a1a1aa",
17876
+ mutedSurface: "#111113",
17877
+ mutedText: "#a1a1aa",
17878
+ rowHeaderSurface: "#18181b",
17879
+ shadow: "0 1px 2px rgba(0, 0, 0, 0.28)",
17880
+ sheetActiveSurface: "#27272a",
17881
+ sheetActiveText: "#fafafa",
17882
+ sheetInactiveSurface: "#18181b",
17883
+ sheetInactiveText: "#a1a1aa",
17884
+ strongBorder: "rgba(255, 255, 255, 0.16)",
17885
+ subtleSurface: "#101012",
17886
+ surface: "#111113",
17887
+ text: "#f4f4f5",
17888
+ toolbarSurface: "#101012"
17889
+ };
17890
+ function isDarkViewerPalette(palette) {
17891
+ return palette.surface === DARK_PALETTE.surface;
17892
+ }
17893
+ function resolveViewerPalette(isDark = false, headerBackgroundColor, headerTextColor) {
17894
+ const basePalette = isDark ? DARK_PALETTE : LIGHT_PALETTE;
17895
+ if (headerBackgroundColor === void 0 && headerTextColor === void 0) {
17896
+ return basePalette;
17897
+ }
17898
+ return {
17899
+ ...basePalette,
17900
+ headerSurface: headerBackgroundColor ?? basePalette.headerSurface,
17901
+ headerText: headerTextColor ?? basePalette.headerText,
17902
+ rowHeaderSurface: headerBackgroundColor ?? basePalette.rowHeaderSurface
17903
+ };
17904
+ }
17905
+
17837
17906
  // src/XlsxViewer.tsx
17838
17907
  var import_jsx_runtime3 = require("react/jsx-runtime");
17839
17908
  var DEFAULT_ROW_HEIGHT2 = 24;
@@ -18591,48 +18660,6 @@ function resolveEventAnchor(clientX, clientY, rect) {
18591
18660
  function resolveTouchDistance(firstTouch, secondTouch) {
18592
18661
  return Math.hypot(firstTouch.clientX - secondTouch.clientX, firstTouch.clientY - secondTouch.clientY);
18593
18662
  }
18594
- var LIGHT_PALETTE = {
18595
- border: "#e4e4e7",
18596
- buttonSurface: "#ffffff",
18597
- buttonText: "#18181b",
18598
- canvas: "#fafafa",
18599
- danger: "#dc2626",
18600
- headerSurface: "#f4f4f5",
18601
- mutedSurface: "#f5f5f5",
18602
- mutedText: "#71717a",
18603
- rowHeaderSurface: "#f4f4f5",
18604
- shadow: "0 1px 2px rgba(0, 0, 0, 0.04)",
18605
- sheetActiveSurface: "#ffffff",
18606
- sheetActiveText: "#18181b",
18607
- sheetInactiveSurface: "#e4e4e7",
18608
- sheetInactiveText: "#52525b",
18609
- strongBorder: "#d4d4d8",
18610
- subtleSurface: "#fafafa",
18611
- surface: "#ffffff",
18612
- text: "#18181b",
18613
- toolbarSurface: "#f5f5f5"
18614
- };
18615
- var DARK_PALETTE = {
18616
- border: "rgba(255, 255, 255, 0.10)",
18617
- buttonSurface: "rgba(255, 255, 255, 0.06)",
18618
- buttonText: "#f4f4f5",
18619
- canvas: "#09090b",
18620
- danger: "#f87171",
18621
- headerSurface: "#18181b",
18622
- mutedSurface: "#111113",
18623
- mutedText: "#a1a1aa",
18624
- rowHeaderSurface: "#18181b",
18625
- shadow: "0 1px 2px rgba(0, 0, 0, 0.28)",
18626
- sheetActiveSurface: "#27272a",
18627
- sheetActiveText: "#fafafa",
18628
- sheetInactiveSurface: "#18181b",
18629
- sheetInactiveText: "#a1a1aa",
18630
- strongBorder: "rgba(255, 255, 255, 0.16)",
18631
- subtleSurface: "#101012",
18632
- surface: "#111113",
18633
- text: "#f4f4f5",
18634
- toolbarSurface: "#101012"
18635
- };
18636
18663
  function parseRgbColor3(color) {
18637
18664
  const match = /^#?([0-9a-f]{6})$/i.exec(color);
18638
18665
  if (!match) {
@@ -20087,8 +20114,11 @@ function resolveImageHandleStyle(position, stroke, surface, scale = 1) {
20087
20114
  }
20088
20115
  return style;
20089
20116
  }
20090
- function useViewerPalette(isDark = false) {
20091
- return isDark ? DARK_PALETTE : LIGHT_PALETTE;
20117
+ function useViewerPalette(isDark = false, headerBackgroundColor, headerTextColor) {
20118
+ return React4.useMemo(
20119
+ () => resolveViewerPalette(isDark, headerBackgroundColor, headerTextColor),
20120
+ [headerBackgroundColor, headerTextColor, isDark]
20121
+ );
20092
20122
  }
20093
20123
  function normalizeThumbnailResolution(resolution) {
20094
20124
  if (typeof resolution === "number" && Number.isFinite(resolution) && resolution > 0) {
@@ -20336,7 +20366,7 @@ function mapBorder2(edge, themePalette) {
20336
20366
  return `${widthMap[edge.style] ?? "1px"} ${styleMap[edge.style] ?? "solid"} ${color}`;
20337
20367
  }
20338
20368
  function paletteIsDark(palette) {
20339
- return palette.surface === DARK_PALETTE.surface;
20369
+ return isDarkViewerPalette(palette);
20340
20370
  }
20341
20371
  function parseHexColor3(color) {
20342
20372
  const normalized = color.trim().toLowerCase();
@@ -22662,7 +22692,7 @@ function GridRow({
22662
22692
  borderRight: "none",
22663
22693
  boxSizing: "border-box",
22664
22694
  boxShadow: gutterSeparatorShadow,
22665
- color: palette.mutedText,
22695
+ color: palette.headerText,
22666
22696
  fontSize: scaleCssLengthExpression("11px", zoomFactor),
22667
22697
  height: rowHeight,
22668
22698
  left: 0,
@@ -22794,6 +22824,16 @@ function GridRow({
22794
22824
  width: "100%",
22795
22825
  wordBreak: "inherit"
22796
22826
  };
22827
+ const usesWrappedText = cellData.style.whiteSpace === "pre-wrap" || cellData.value.includes("\n");
22828
+ const wrappedTextStyle = usesWrappedText ? {
22829
+ display: "block",
22830
+ flex: "0 0 auto",
22831
+ maxWidth: "100%",
22832
+ minWidth: 0
22833
+ } : null;
22834
+ if (usesWrappedText) {
22835
+ cellContentStyle.overflow = "clip";
22836
+ }
22797
22837
  const trailingInset = (adornment ? 20 : 0) + (cellData.conditionalIcon ? 18 : 0);
22798
22838
  if (cellData.conditionalDataBar) {
22799
22839
  cellContentStyle.position = "relative";
@@ -22989,7 +23029,7 @@ function GridRow({
22989
23029
  },
22990
23030
  children: renderCheckboxControl(cellData.checkboxState, palette, zoomFactor)
22991
23031
  }
22992
- ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: cellContentStyle, children: rotatedTextStyle ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: rotatedTextStyle, children: cellData.value }) : cellData.value })
23032
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: cellContentStyle, children: rotatedTextStyle ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: rotatedTextStyle, children: cellData.value }) : wrappedTextStyle ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: wrappedTextStyle, children: cellData.value }) : cellData.value })
22993
23033
  ]
22994
23034
  },
22995
23035
  key
@@ -27713,14 +27753,18 @@ function XlsxGrid({
27713
27753
  zoomFactor * 1.5,
27714
27754
  activeFontSizePx * (cellData.textRotationDeg ? 0.75 : 0.18)
27715
27755
  );
27756
+ const textClip = resolveCellTextClipOverscan(
27757
+ textClipOverscan,
27758
+ canvasCellStyle.usesWrappedText || rawText.includes("\n")
27759
+ );
27716
27760
  flushPendingGridlines();
27717
27761
  paneContext.save();
27718
27762
  paneContext.beginPath();
27719
27763
  paneContext.rect(
27720
- contentLeft - textClipOverscan,
27721
- contentTop - textClipOverscan,
27722
- contentWidth + textClipOverscan * 2,
27723
- contentHeight + textClipOverscan * 2
27764
+ contentLeft - textClip.horizontal,
27765
+ contentTop - textClip.vertical,
27766
+ contentWidth + textClip.horizontal * 2,
27767
+ contentHeight + textClip.vertical * 2
27724
27768
  );
27725
27769
  paneContext.clip();
27726
27770
  paneContext.font = cellData.shrinkToFitFontSizePx ? resolveCanvasFontWithPxSize(cellStyle, cellData.shrinkToFitFontSizePx) : canvasCellStyle.baseFont;
@@ -28062,7 +28106,7 @@ function XlsxGrid({
28062
28106
  paneContext.lineTo(column.localLeft + column.width, column.height - 0.5);
28063
28107
  paneContext.stroke();
28064
28108
  paneContext.font = `600 ${11 * zoomFactor}px ui-sans-serif, system-ui, sans-serif`;
28065
- paneContext.fillStyle = palette.mutedText;
28109
+ paneContext.fillStyle = palette.headerText;
28066
28110
  paneContext.textAlign = "center";
28067
28111
  paneContext.textBaseline = "middle";
28068
28112
  paneContext.fillText(
@@ -28110,7 +28154,7 @@ function XlsxGrid({
28110
28154
  paneContext.lineTo(rowHeaderWidth - 0.5, row.localTop + row.height);
28111
28155
  paneContext.stroke();
28112
28156
  paneContext.font = `600 ${11 * zoomFactor}px ui-sans-serif, system-ui, sans-serif`;
28113
- paneContext.fillStyle = palette.mutedText;
28157
+ paneContext.fillStyle = palette.headerText;
28114
28158
  paneContext.textAlign = "center";
28115
28159
  paneContext.textBaseline = "middle";
28116
28160
  paneContext.fillText(`${row.actualRow + 1}`, rowHeaderWidth / 2, row.localTop + row.height / 2);
@@ -28453,7 +28497,7 @@ function XlsxGrid({
28453
28497
  borderBottom: "none",
28454
28498
  borderRight: "none",
28455
28499
  boxShadow: gutterSeparatorShadow,
28456
- color: palette.mutedText,
28500
+ color: palette.headerText,
28457
28501
  fontSize: "11px",
28458
28502
  fontWeight: 600,
28459
28503
  height: HEADER_HEIGHT,
@@ -30717,6 +30761,8 @@ function XlsxViewerInner({
30717
30761
  experimentalCanvas = true,
30718
30762
  fileTooLargeState,
30719
30763
  getCellStyle,
30764
+ headerBackgroundColor,
30765
+ headerTextColor,
30720
30766
  height,
30721
30767
  isDark = false,
30722
30768
  loadingComponent,
@@ -30737,7 +30783,7 @@ function XlsxViewerInner({
30737
30783
  showDefaultToolbar = true,
30738
30784
  toolbar
30739
30785
  }) {
30740
- const palette = useViewerPalette(isDark);
30786
+ const palette = useViewerPalette(isDark, headerBackgroundColor, headerTextColor);
30741
30787
  const { displayFileName, error } = controller;
30742
30788
  const customFileTooLarge = error instanceof XlsxFileSizeLimitExceededError ? renderCustomFileTooLarge(
30743
30789
  fileTooLargeState,
@@ -30748,7 +30794,7 @@ function XlsxViewerInner({
30748
30794
  },
30749
30795
  palette
30750
30796
  ) : void 0;
30751
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ViewerAppearanceContext.Provider, { value: { isDark }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ViewerContext.Provider, { value: controller, children: customFileTooLarge !== void 0 ? customFileTooLarge : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
30797
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ViewerAppearanceContext.Provider, { value: { headerBackgroundColor, headerTextColor, isDark }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ViewerContext.Provider, { value: controller, children: customFileTooLarge !== void 0 ? customFileTooLarge : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
30752
30798
  "div",
30753
30799
  {
30754
30800
  className: classNames("react-xlsx-viewer", className),
@@ -31219,8 +31265,8 @@ function useXlsxViewerThumbnails(options = {}) {
31219
31265
  workbook,
31220
31266
  sheets
31221
31267
  } = useXlsxViewer();
31222
- const { isDark } = React4.useContext(ViewerAppearanceContext);
31223
- const palette = useViewerPalette(isDark);
31268
+ const { headerBackgroundColor, headerTextColor, isDark } = React4.useContext(ViewerAppearanceContext);
31269
+ const palette = useViewerPalette(isDark, headerBackgroundColor, headerTextColor);
31224
31270
  const includeHeaders = options.includeHeaders ?? true;
31225
31271
  const resolution = options.resolution;
31226
31272
  const thumbnailImageCacheRef = React4.useRef(/* @__PURE__ */ new Map());
@@ -31832,7 +31878,7 @@ function useXlsxViewerThumbnails(options = {}) {
31832
31878
  context.strokeStyle = palette.border;
31833
31879
  context.lineWidth = 1;
31834
31880
  context.font = "600 11px ui-sans-serif, system-ui, sans-serif";
31835
- context.fillStyle = palette.mutedText;
31881
+ context.fillStyle = palette.headerText;
31836
31882
  context.textBaseline = "middle";
31837
31883
  for (const colItem of colAxis.items) {
31838
31884
  const left = rowHeaderWidth + colItem.start;
@@ -31919,8 +31965,8 @@ function XlsxViewer(props) {
31919
31965
  }
31920
31966
  function DefaultXlsxToolbar() {
31921
31967
  const controller = useXlsxViewer();
31922
- const { isDark } = React4.useContext(ViewerAppearanceContext);
31923
- const palette = useViewerPalette(isDark);
31968
+ const { headerBackgroundColor, headerTextColor, isDark } = React4.useContext(ViewerAppearanceContext);
31969
+ const palette = useViewerPalette(isDark, headerBackgroundColor, headerTextColor);
31924
31970
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(DefaultToolbar, { controller, palette });
31925
31971
  }
31926
31972
  // Annotate the CommonJS export names for ESM import in node: