@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/dist/index.d.cts CHANGED
@@ -1495,6 +1495,10 @@ interface XlsxViewerProps extends UseXlsxViewerControllerOptions {
1495
1495
  * ```
1496
1496
  */
1497
1497
  getCellStyle?: (context: XlsxCellStyleContext) => React.CSSProperties | null | undefined;
1498
+ /** Background color used for row-number, column-letter, and corner headers. */
1499
+ headerBackgroundColor?: string;
1500
+ /** Text color used for row-number and column-letter headers. */
1501
+ headerTextColor?: string;
1498
1502
  /**
1499
1503
  * CSS height for the viewer container.
1500
1504
  *
package/dist/index.d.ts CHANGED
@@ -1495,6 +1495,10 @@ interface XlsxViewerProps extends UseXlsxViewerControllerOptions {
1495
1495
  * ```
1496
1496
  */
1497
1497
  getCellStyle?: (context: XlsxCellStyleContext) => React.CSSProperties | null | undefined;
1498
+ /** Background color used for row-number, column-letter, and corner headers. */
1499
+ headerBackgroundColor?: string;
1500
+ /** Text color used for row-number and column-letter headers. */
1501
+ headerTextColor?: string;
1498
1502
  /**
1499
1503
  * CSS height for the viewer container.
1500
1504
  *
package/dist/index.js CHANGED
@@ -11040,6 +11040,14 @@ import {
11040
11040
  useVirtualizer
11041
11041
  } from "@tanstack/react-virtual";
11042
11042
 
11043
+ // src/cell-text-clip.ts
11044
+ function resolveCellTextClipOverscan(overscan, usesWrappedText) {
11045
+ return {
11046
+ horizontal: overscan,
11047
+ vertical: usesWrappedText ? 0 : overscan
11048
+ };
11049
+ }
11050
+
11043
11051
  // src/chart-renderer.tsx
11044
11052
  import { hierarchy as d3Hierarchy, partition as d3Partition, treemap as d3Treemap, treemapBinary, treemapDice } from "d3-hierarchy";
11045
11053
  import { geoIdentity, geoMercator, geoNaturalEarth1, geoPath } from "d3-geo";
@@ -17800,6 +17808,67 @@ var MemoChartSvg = React3.memo(function MemoChartSvg2({
17800
17808
  );
17801
17809
  }, (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);
17802
17810
 
17811
+ // src/viewer-palette.ts
17812
+ var LIGHT_PALETTE = {
17813
+ border: "#e4e4e7",
17814
+ buttonSurface: "#ffffff",
17815
+ buttonText: "#18181b",
17816
+ canvas: "#fafafa",
17817
+ danger: "#dc2626",
17818
+ headerSurface: "#f4f4f5",
17819
+ headerText: "#71717a",
17820
+ mutedSurface: "#f5f5f5",
17821
+ mutedText: "#71717a",
17822
+ rowHeaderSurface: "#f4f4f5",
17823
+ shadow: "0 1px 2px rgba(0, 0, 0, 0.04)",
17824
+ sheetActiveSurface: "#ffffff",
17825
+ sheetActiveText: "#18181b",
17826
+ sheetInactiveSurface: "#e4e4e7",
17827
+ sheetInactiveText: "#52525b",
17828
+ strongBorder: "#d4d4d8",
17829
+ subtleSurface: "#fafafa",
17830
+ surface: "#ffffff",
17831
+ text: "#18181b",
17832
+ toolbarSurface: "#f5f5f5"
17833
+ };
17834
+ var DARK_PALETTE = {
17835
+ border: "rgba(255, 255, 255, 0.10)",
17836
+ buttonSurface: "rgba(255, 255, 255, 0.06)",
17837
+ buttonText: "#f4f4f5",
17838
+ canvas: "#09090b",
17839
+ danger: "#f87171",
17840
+ headerSurface: "#18181b",
17841
+ headerText: "#a1a1aa",
17842
+ mutedSurface: "#111113",
17843
+ mutedText: "#a1a1aa",
17844
+ rowHeaderSurface: "#18181b",
17845
+ shadow: "0 1px 2px rgba(0, 0, 0, 0.28)",
17846
+ sheetActiveSurface: "#27272a",
17847
+ sheetActiveText: "#fafafa",
17848
+ sheetInactiveSurface: "#18181b",
17849
+ sheetInactiveText: "#a1a1aa",
17850
+ strongBorder: "rgba(255, 255, 255, 0.16)",
17851
+ subtleSurface: "#101012",
17852
+ surface: "#111113",
17853
+ text: "#f4f4f5",
17854
+ toolbarSurface: "#101012"
17855
+ };
17856
+ function isDarkViewerPalette(palette) {
17857
+ return palette.surface === DARK_PALETTE.surface;
17858
+ }
17859
+ function resolveViewerPalette(isDark = false, headerBackgroundColor, headerTextColor) {
17860
+ const basePalette = isDark ? DARK_PALETTE : LIGHT_PALETTE;
17861
+ if (headerBackgroundColor === void 0 && headerTextColor === void 0) {
17862
+ return basePalette;
17863
+ }
17864
+ return {
17865
+ ...basePalette,
17866
+ headerSurface: headerBackgroundColor ?? basePalette.headerSurface,
17867
+ headerText: headerTextColor ?? basePalette.headerText,
17868
+ rowHeaderSurface: headerBackgroundColor ?? basePalette.rowHeaderSurface
17869
+ };
17870
+ }
17871
+
17803
17872
  // src/XlsxViewer.tsx
17804
17873
  import { Fragment as Fragment4, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
17805
17874
  var DEFAULT_ROW_HEIGHT2 = 24;
@@ -18557,48 +18626,6 @@ function resolveEventAnchor(clientX, clientY, rect) {
18557
18626
  function resolveTouchDistance(firstTouch, secondTouch) {
18558
18627
  return Math.hypot(firstTouch.clientX - secondTouch.clientX, firstTouch.clientY - secondTouch.clientY);
18559
18628
  }
18560
- var LIGHT_PALETTE = {
18561
- border: "#e4e4e7",
18562
- buttonSurface: "#ffffff",
18563
- buttonText: "#18181b",
18564
- canvas: "#fafafa",
18565
- danger: "#dc2626",
18566
- headerSurface: "#f4f4f5",
18567
- mutedSurface: "#f5f5f5",
18568
- mutedText: "#71717a",
18569
- rowHeaderSurface: "#f4f4f5",
18570
- shadow: "0 1px 2px rgba(0, 0, 0, 0.04)",
18571
- sheetActiveSurface: "#ffffff",
18572
- sheetActiveText: "#18181b",
18573
- sheetInactiveSurface: "#e4e4e7",
18574
- sheetInactiveText: "#52525b",
18575
- strongBorder: "#d4d4d8",
18576
- subtleSurface: "#fafafa",
18577
- surface: "#ffffff",
18578
- text: "#18181b",
18579
- toolbarSurface: "#f5f5f5"
18580
- };
18581
- var DARK_PALETTE = {
18582
- border: "rgba(255, 255, 255, 0.10)",
18583
- buttonSurface: "rgba(255, 255, 255, 0.06)",
18584
- buttonText: "#f4f4f5",
18585
- canvas: "#09090b",
18586
- danger: "#f87171",
18587
- headerSurface: "#18181b",
18588
- mutedSurface: "#111113",
18589
- mutedText: "#a1a1aa",
18590
- rowHeaderSurface: "#18181b",
18591
- shadow: "0 1px 2px rgba(0, 0, 0, 0.28)",
18592
- sheetActiveSurface: "#27272a",
18593
- sheetActiveText: "#fafafa",
18594
- sheetInactiveSurface: "#18181b",
18595
- sheetInactiveText: "#a1a1aa",
18596
- strongBorder: "rgba(255, 255, 255, 0.16)",
18597
- subtleSurface: "#101012",
18598
- surface: "#111113",
18599
- text: "#f4f4f5",
18600
- toolbarSurface: "#101012"
18601
- };
18602
18629
  function parseRgbColor3(color) {
18603
18630
  const match = /^#?([0-9a-f]{6})$/i.exec(color);
18604
18631
  if (!match) {
@@ -20053,8 +20080,11 @@ function resolveImageHandleStyle(position, stroke, surface, scale = 1) {
20053
20080
  }
20054
20081
  return style;
20055
20082
  }
20056
- function useViewerPalette(isDark = false) {
20057
- return isDark ? DARK_PALETTE : LIGHT_PALETTE;
20083
+ function useViewerPalette(isDark = false, headerBackgroundColor, headerTextColor) {
20084
+ return React4.useMemo(
20085
+ () => resolveViewerPalette(isDark, headerBackgroundColor, headerTextColor),
20086
+ [headerBackgroundColor, headerTextColor, isDark]
20087
+ );
20058
20088
  }
20059
20089
  function normalizeThumbnailResolution(resolution) {
20060
20090
  if (typeof resolution === "number" && Number.isFinite(resolution) && resolution > 0) {
@@ -20302,7 +20332,7 @@ function mapBorder2(edge, themePalette) {
20302
20332
  return `${widthMap[edge.style] ?? "1px"} ${styleMap[edge.style] ?? "solid"} ${color}`;
20303
20333
  }
20304
20334
  function paletteIsDark(palette) {
20305
- return palette.surface === DARK_PALETTE.surface;
20335
+ return isDarkViewerPalette(palette);
20306
20336
  }
20307
20337
  function parseHexColor3(color) {
20308
20338
  const normalized = color.trim().toLowerCase();
@@ -22628,7 +22658,7 @@ function GridRow({
22628
22658
  borderRight: "none",
22629
22659
  boxSizing: "border-box",
22630
22660
  boxShadow: gutterSeparatorShadow,
22631
- color: palette.mutedText,
22661
+ color: palette.headerText,
22632
22662
  fontSize: scaleCssLengthExpression("11px", zoomFactor),
22633
22663
  height: rowHeight,
22634
22664
  left: 0,
@@ -22760,6 +22790,16 @@ function GridRow({
22760
22790
  width: "100%",
22761
22791
  wordBreak: "inherit"
22762
22792
  };
22793
+ const usesWrappedText = cellData.style.whiteSpace === "pre-wrap" || cellData.value.includes("\n");
22794
+ const wrappedTextStyle = usesWrappedText ? {
22795
+ display: "block",
22796
+ flex: "0 0 auto",
22797
+ maxWidth: "100%",
22798
+ minWidth: 0
22799
+ } : null;
22800
+ if (usesWrappedText) {
22801
+ cellContentStyle.overflow = "clip";
22802
+ }
22763
22803
  const trailingInset = (adornment ? 20 : 0) + (cellData.conditionalIcon ? 18 : 0);
22764
22804
  if (cellData.conditionalDataBar) {
22765
22805
  cellContentStyle.position = "relative";
@@ -22955,7 +22995,7 @@ function GridRow({
22955
22995
  },
22956
22996
  children: renderCheckboxControl(cellData.checkboxState, palette, zoomFactor)
22957
22997
  }
22958
- ) : /* @__PURE__ */ jsx3("div", { style: cellContentStyle, children: rotatedTextStyle ? /* @__PURE__ */ jsx3("span", { style: rotatedTextStyle, children: cellData.value }) : cellData.value })
22998
+ ) : /* @__PURE__ */ jsx3("div", { style: cellContentStyle, children: rotatedTextStyle ? /* @__PURE__ */ jsx3("span", { style: rotatedTextStyle, children: cellData.value }) : wrappedTextStyle ? /* @__PURE__ */ jsx3("span", { style: wrappedTextStyle, children: cellData.value }) : cellData.value })
22959
22999
  ]
22960
23000
  },
22961
23001
  key
@@ -27679,14 +27719,18 @@ function XlsxGrid({
27679
27719
  zoomFactor * 1.5,
27680
27720
  activeFontSizePx * (cellData.textRotationDeg ? 0.75 : 0.18)
27681
27721
  );
27722
+ const textClip = resolveCellTextClipOverscan(
27723
+ textClipOverscan,
27724
+ canvasCellStyle.usesWrappedText || rawText.includes("\n")
27725
+ );
27682
27726
  flushPendingGridlines();
27683
27727
  paneContext.save();
27684
27728
  paneContext.beginPath();
27685
27729
  paneContext.rect(
27686
- contentLeft - textClipOverscan,
27687
- contentTop - textClipOverscan,
27688
- contentWidth + textClipOverscan * 2,
27689
- contentHeight + textClipOverscan * 2
27730
+ contentLeft - textClip.horizontal,
27731
+ contentTop - textClip.vertical,
27732
+ contentWidth + textClip.horizontal * 2,
27733
+ contentHeight + textClip.vertical * 2
27690
27734
  );
27691
27735
  paneContext.clip();
27692
27736
  paneContext.font = cellData.shrinkToFitFontSizePx ? resolveCanvasFontWithPxSize(cellStyle, cellData.shrinkToFitFontSizePx) : canvasCellStyle.baseFont;
@@ -28028,7 +28072,7 @@ function XlsxGrid({
28028
28072
  paneContext.lineTo(column.localLeft + column.width, column.height - 0.5);
28029
28073
  paneContext.stroke();
28030
28074
  paneContext.font = `600 ${11 * zoomFactor}px ui-sans-serif, system-ui, sans-serif`;
28031
- paneContext.fillStyle = palette.mutedText;
28075
+ paneContext.fillStyle = palette.headerText;
28032
28076
  paneContext.textAlign = "center";
28033
28077
  paneContext.textBaseline = "middle";
28034
28078
  paneContext.fillText(
@@ -28076,7 +28120,7 @@ function XlsxGrid({
28076
28120
  paneContext.lineTo(rowHeaderWidth - 0.5, row.localTop + row.height);
28077
28121
  paneContext.stroke();
28078
28122
  paneContext.font = `600 ${11 * zoomFactor}px ui-sans-serif, system-ui, sans-serif`;
28079
- paneContext.fillStyle = palette.mutedText;
28123
+ paneContext.fillStyle = palette.headerText;
28080
28124
  paneContext.textAlign = "center";
28081
28125
  paneContext.textBaseline = "middle";
28082
28126
  paneContext.fillText(`${row.actualRow + 1}`, rowHeaderWidth / 2, row.localTop + row.height / 2);
@@ -28419,7 +28463,7 @@ function XlsxGrid({
28419
28463
  borderBottom: "none",
28420
28464
  borderRight: "none",
28421
28465
  boxShadow: gutterSeparatorShadow,
28422
- color: palette.mutedText,
28466
+ color: palette.headerText,
28423
28467
  fontSize: "11px",
28424
28468
  fontWeight: 600,
28425
28469
  height: HEADER_HEIGHT,
@@ -30683,6 +30727,8 @@ function XlsxViewerInner({
30683
30727
  experimentalCanvas = true,
30684
30728
  fileTooLargeState,
30685
30729
  getCellStyle,
30730
+ headerBackgroundColor,
30731
+ headerTextColor,
30686
30732
  height,
30687
30733
  isDark = false,
30688
30734
  loadingComponent,
@@ -30703,7 +30749,7 @@ function XlsxViewerInner({
30703
30749
  showDefaultToolbar = true,
30704
30750
  toolbar
30705
30751
  }) {
30706
- const palette = useViewerPalette(isDark);
30752
+ const palette = useViewerPalette(isDark, headerBackgroundColor, headerTextColor);
30707
30753
  const { displayFileName, error } = controller;
30708
30754
  const customFileTooLarge = error instanceof XlsxFileSizeLimitExceededError ? renderCustomFileTooLarge(
30709
30755
  fileTooLargeState,
@@ -30714,7 +30760,7 @@ function XlsxViewerInner({
30714
30760
  },
30715
30761
  palette
30716
30762
  ) : void 0;
30717
- return /* @__PURE__ */ jsx3(ViewerAppearanceContext.Provider, { value: { isDark }, children: /* @__PURE__ */ jsx3(ViewerContext.Provider, { value: controller, children: customFileTooLarge !== void 0 ? customFileTooLarge : /* @__PURE__ */ jsxs3(
30763
+ return /* @__PURE__ */ jsx3(ViewerAppearanceContext.Provider, { value: { headerBackgroundColor, headerTextColor, isDark }, children: /* @__PURE__ */ jsx3(ViewerContext.Provider, { value: controller, children: customFileTooLarge !== void 0 ? customFileTooLarge : /* @__PURE__ */ jsxs3(
30718
30764
  "div",
30719
30765
  {
30720
30766
  className: classNames("react-xlsx-viewer", className),
@@ -31185,8 +31231,8 @@ function useXlsxViewerThumbnails(options = {}) {
31185
31231
  workbook,
31186
31232
  sheets
31187
31233
  } = useXlsxViewer();
31188
- const { isDark } = React4.useContext(ViewerAppearanceContext);
31189
- const palette = useViewerPalette(isDark);
31234
+ const { headerBackgroundColor, headerTextColor, isDark } = React4.useContext(ViewerAppearanceContext);
31235
+ const palette = useViewerPalette(isDark, headerBackgroundColor, headerTextColor);
31190
31236
  const includeHeaders = options.includeHeaders ?? true;
31191
31237
  const resolution = options.resolution;
31192
31238
  const thumbnailImageCacheRef = React4.useRef(/* @__PURE__ */ new Map());
@@ -31798,7 +31844,7 @@ function useXlsxViewerThumbnails(options = {}) {
31798
31844
  context.strokeStyle = palette.border;
31799
31845
  context.lineWidth = 1;
31800
31846
  context.font = "600 11px ui-sans-serif, system-ui, sans-serif";
31801
- context.fillStyle = palette.mutedText;
31847
+ context.fillStyle = palette.headerText;
31802
31848
  context.textBaseline = "middle";
31803
31849
  for (const colItem of colAxis.items) {
31804
31850
  const left = rowHeaderWidth + colItem.start;
@@ -31885,8 +31931,8 @@ function XlsxViewer(props) {
31885
31931
  }
31886
31932
  function DefaultXlsxToolbar() {
31887
31933
  const controller = useXlsxViewer();
31888
- const { isDark } = React4.useContext(ViewerAppearanceContext);
31889
- const palette = useViewerPalette(isDark);
31934
+ const { headerBackgroundColor, headerTextColor, isDark } = React4.useContext(ViewerAppearanceContext);
31935
+ const palette = useViewerPalette(isDark, headerBackgroundColor, headerTextColor);
31890
31936
  return /* @__PURE__ */ jsx3(DefaultToolbar, { controller, palette });
31891
31937
  }
31892
31938
  export {