@extend-ai/react-xlsx 0.17.0 → 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.d.cts CHANGED
@@ -17,6 +17,7 @@ interface XlsxResolvedCellStyle {
17
17
  };
18
18
  fill?: Record<string, unknown>;
19
19
  font?: Record<string, unknown>;
20
+ tableStyleOverrides?: XlsxResolvedCellStyle;
20
21
  }
21
22
  interface XlsxTableStyleDefinition {
22
23
  [elementType: string]: XlsxResolvedCellStyle;
@@ -99,6 +100,7 @@ interface XlsxFreezePanes {
99
100
  }
100
101
  type XlsxSheetVisibility = "hidden" | "veryHidden" | "visible";
101
102
  interface XlsxSheetData {
103
+ cellStyleIds?: Record<string, number>;
102
104
  autoFilterRanges: XlsxCellRange[];
103
105
  cachedFormulaValues: Record<string, string>;
104
106
  colWidthOverridesPx: Record<number, number>;
package/dist/index.d.ts CHANGED
@@ -17,6 +17,7 @@ interface XlsxResolvedCellStyle {
17
17
  };
18
18
  fill?: Record<string, unknown>;
19
19
  font?: Record<string, unknown>;
20
+ tableStyleOverrides?: XlsxResolvedCellStyle;
20
21
  }
21
22
  interface XlsxTableStyleDefinition {
22
23
  [elementType: string]: XlsxResolvedCellStyle;
@@ -99,6 +100,7 @@ interface XlsxFreezePanes {
99
100
  }
100
101
  type XlsxSheetVisibility = "hidden" | "veryHidden" | "visible";
101
102
  interface XlsxSheetData {
103
+ cellStyleIds?: Record<string, number>;
102
104
  autoFilterRanges: XlsxCellRange[];
103
105
  cachedFormulaValues: Record<string, string>;
104
106
  colWidthOverridesPx: Record<number, number>;
package/dist/index.js CHANGED
@@ -3581,7 +3581,7 @@ function resolveWorkbookColor(color, themePalette) {
3581
3581
  if (directHex) {
3582
3582
  return normalizeHexColor2(directHex);
3583
3583
  }
3584
- const themeValue = color.theme;
3584
+ const themeValue = color.theme ?? color.themeIndex;
3585
3585
  const numericTheme = typeof themeValue === "number" ? themeValue : typeof themeValue === "string" && themeValue.trim().length > 0 ? Number(themeValue) : Number.NaN;
3586
3586
  const themeColor = Number.isFinite(numericTheme) ? themePalette?.colorsByIndex[numericTheme] ?? null : null;
3587
3587
  if (!themeColor) {
@@ -4209,6 +4209,12 @@ function parseSpreadsheetFont(node) {
4209
4209
  return void 0;
4210
4210
  }
4211
4211
  const font = {};
4212
+ for (const [tag, property] of [["b", "bold"], ["i", "italic"], ["strike", "strikethrough"]]) {
4213
+ const flag = getFirstChild(node, tag);
4214
+ if (flag) {
4215
+ font[property] = hasEnabledSpreadsheetFlag(flag);
4216
+ }
4217
+ }
4212
4218
  const size = getFirstChild(node, "sz")?.getAttribute("val");
4213
4219
  const name = getFirstChild(node, "name")?.getAttribute("val");
4214
4220
  const family = getFirstChild(node, "family")?.getAttribute("val");
@@ -4216,15 +4222,6 @@ function parseSpreadsheetFont(node) {
4216
4222
  const charset = getFirstChild(node, "charset")?.getAttribute("val");
4217
4223
  const verticalAlign = getFirstChild(node, "vertAlign")?.getAttribute("val");
4218
4224
  const color = parseSpreadsheetColor(getFirstChild(node, "color"));
4219
- if (hasEnabledSpreadsheetFlag(getFirstChild(node, "b"))) {
4220
- font.bold = true;
4221
- }
4222
- if (hasEnabledSpreadsheetFlag(getFirstChild(node, "i"))) {
4223
- font.italic = true;
4224
- }
4225
- if (hasEnabledSpreadsheetFlag(getFirstChild(node, "strike"))) {
4226
- font.strikethrough = true;
4227
- }
4228
4225
  if (getFirstChild(node, "u")) {
4229
4226
  font.underline = getFirstChild(node, "u")?.getAttribute("val") ?? "single";
4230
4227
  }
@@ -4473,7 +4470,14 @@ function parseWorkbookStyles(archive) {
4473
4470
  const styleById = {};
4474
4471
  const tableStyleByName = {};
4475
4472
  getChildElements(cellXfsNode, "xf").forEach((xfNode, index) => {
4476
- styleById[index] = parseResolvedXfStyle(xfNode, fonts, fills, borders, checkboxComplementIndices);
4473
+ const style = parseResolvedXfStyle(xfNode, fonts, fills, borders, checkboxComplementIndices);
4474
+ const overrides = {};
4475
+ for (const component of ["font", "fill", "border"]) {
4476
+ if (Number(xfNode.getAttribute(`${component}Id`) ?? 0) > 0 && xfNode.getAttribute(`apply${component[0].toUpperCase()}${component.slice(1)}`) !== "0") {
4477
+ Object.assign(overrides, { [component]: style[component] });
4478
+ }
4479
+ }
4480
+ styleById[index] = { ...style, tableStyleOverrides: overrides };
4477
4481
  });
4478
4482
  getChildElements(cellStylesNode ?? document2.documentElement, "cellStyle").forEach((cellStyleNode) => {
4479
4483
  const name = cellStyleNode.getAttribute("name");
@@ -4817,6 +4821,7 @@ function parseSheetState(archive, path, options) {
4817
4821
  const rowHeightOverridesPx = {};
4818
4822
  const colWidthOverridesPx = {};
4819
4823
  const rowStyleIds = {};
4824
+ const cellStyleIds = {};
4820
4825
  const colStyleIds = {};
4821
4826
  let minContentCol = Number.POSITIVE_INFINITY;
4822
4827
  let minContentRow = Number.POSITIVE_INFINITY;
@@ -4866,6 +4871,10 @@ function parseSheetState(archive, path, options) {
4866
4871
  }
4867
4872
  getChildElements(rowNode, "c").forEach((cellNode) => {
4868
4873
  const cellRef = cellNode.getAttribute("r");
4874
+ const cellStyleId = Number(cellNode.getAttribute("s") ?? Number.NaN);
4875
+ if (cellRef && Number.isFinite(cellStyleId)) {
4876
+ cellStyleIds[cellRef] = cellStyleId;
4877
+ }
4869
4878
  if (isMeaningfulCellNode(cellNode)) {
4870
4879
  trackContentCell(cellRef);
4871
4880
  }
@@ -4904,6 +4913,7 @@ function parseSheetState(archive, path, options) {
4904
4913
  return {
4905
4914
  autoFilterRanges,
4906
4915
  cachedFormulaValues,
4916
+ cellStyleIds,
4907
4917
  columnWidthCharacterWidthPx,
4908
4918
  colWidthOverridesPx,
4909
4919
  colStyleIds,
@@ -7406,6 +7416,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
7406
7416
  colCount: 0,
7407
7417
  rowHeightOverridesPx: sheetState?.rowHeightOverridesPx ?? {},
7408
7418
  rowStyleIds: sheetState?.rowStyleIds ?? {},
7419
+ cellStyleIds: sheetState?.cellStyleIds ?? {},
7409
7420
  styleById: styleById ?? {},
7410
7421
  sparklines: sheetState?.sparklines ?? [],
7411
7422
  tableStyleByName: tableStyleByName ?? {},
@@ -7492,6 +7503,7 @@ function buildSheetList(workbook, sheetStatesByWorkbookSheetIndex, themePalette,
7492
7503
  namedCellStyleByName: namedCellStyleByName ?? {},
7493
7504
  rowHeightOverridesPx: sheetState?.rowHeightOverridesPx ?? {},
7494
7505
  rowStyleIds: sheetState?.rowStyleIds ?? {},
7506
+ cellStyleIds: sheetState?.cellStyleIds ?? {},
7495
7507
  showGridLines: sheetState?.showGridLines ?? true,
7496
7508
  styleById: styleById ?? {},
7497
7509
  sparklines: sheetState?.sparklines ?? [],
@@ -9955,7 +9967,7 @@ function useXlsxViewerController(options) {
9955
9967
  return;
9956
9968
  }
9957
9969
  const dataStartRow = targetTable.start.row + Math.max(targetTable.headerRowCount, 1);
9958
- const totalsRowOffset = targetTable.totalsRowShown ? Math.max(targetTable.totalsRowCount, 1) : 0;
9970
+ const totalsRowOffset = targetTable.totalsRowCount;
9959
9971
  const dataEndRow = targetTable.end.row - totalsRowOffset;
9960
9972
  const startCol = targetTable.start.col;
9961
9973
  const endCol = targetTable.end.col;
@@ -19136,7 +19148,8 @@ function applyCanvasBorderDash(context, style, width) {
19136
19148
  context.setLineDash([]);
19137
19149
  }
19138
19150
  function strokeCanvasBorderSide(context, side, rect, border) {
19139
- const halfWidth = border.width / 2;
19151
+ const strokeWidth = border.style === "double" ? border.width / 3 : border.width;
19152
+ const halfWidth = strokeWidth / 2;
19140
19153
  const left = rect.left;
19141
19154
  const right = rect.left + rect.width;
19142
19155
  const top = rect.top;
@@ -19162,8 +19175,8 @@ function strokeCanvasBorderSide(context, side, rect, border) {
19162
19175
  context.stroke();
19163
19176
  };
19164
19177
  if (border.style === "double") {
19165
- const inset = Math.max(1, border.width);
19166
- context.lineWidth = Math.max(1, border.width / 3);
19178
+ const inset = border.width - strokeWidth;
19179
+ context.lineWidth = strokeWidth;
19167
19180
  context.setLineDash([]);
19168
19181
  strokeLine(0);
19169
19182
  strokeLine(inset);
@@ -22076,6 +22089,43 @@ function mergeResolvedCellStyle(base, overlay, options) {
22076
22089
  }
22077
22090
  return nextStyle;
22078
22091
  }
22092
+ function resolveCellTableOverrides(rawStyle, sheet, row, col) {
22093
+ const styleId = sheet?.cellStyleIds?.[cellAddressToA12({ row, col })] ?? sheet?.rowStyleIds[row] ?? sheet?.colStyleIds[col];
22094
+ const declared = styleId === void 0 ? void 0 : sheet?.styleById[styleId]?.tableStyleOverrides;
22095
+ const overrides = {};
22096
+ const font = asRecord(rawStyle?.font);
22097
+ if (font) {
22098
+ const explicitFont = {};
22099
+ const fontDefaults = {
22100
+ name: "Calibri",
22101
+ size: 11,
22102
+ bold: false,
22103
+ italic: false,
22104
+ underline: "none",
22105
+ strikethrough: false,
22106
+ verticalAlign: "baseline"
22107
+ };
22108
+ for (const [key, value] of Object.entries(font)) {
22109
+ const isExplicit = declared ? Object.hasOwn(declared.font ?? {}, key) : key === "color" ? asRecord(value)?.colorType !== "auto" : value !== fontDefaults[key];
22110
+ if (isExplicit) {
22111
+ explicitFont[key] = value;
22112
+ }
22113
+ }
22114
+ overrides.font = explicitFont;
22115
+ }
22116
+ const fill = asRecord(rawStyle?.fill);
22117
+ if (fill && fill.fillType !== "none") {
22118
+ overrides.fill = fill;
22119
+ }
22120
+ const border = asRecord(rawStyle?.border);
22121
+ if (border) {
22122
+ overrides.border = Object.fromEntries(Object.entries(border).filter(([, edge]) => {
22123
+ const style = asRecord(edge)?.style;
22124
+ return typeof style === "string" && style !== "none";
22125
+ }));
22126
+ }
22127
+ return overrides;
22128
+ }
22079
22129
  function resolveBorderEdgePriority(edge) {
22080
22130
  const style = typeof edge?.style === "string" ? edge.style : "none";
22081
22131
  const stylePriority = {
@@ -22204,7 +22254,7 @@ function resolveTableCellStyle(table, row, col, activeSheet) {
22204
22254
  return null;
22205
22255
  }
22206
22256
  const headerRowCount = Math.max(table.headerRowCount, 1);
22207
- const totalsRowCount = table.totalsRowShown ? Math.max(table.totalsRowCount, 1) : 0;
22257
+ const totalsRowCount = table.totalsRowCount;
22208
22258
  const headerEndRow = table.start.row + headerRowCount - 1;
22209
22259
  const totalsStartRow = table.end.row - totalsRowCount + 1;
22210
22260
  const bodyStartRow = headerEndRow + 1;
@@ -26528,7 +26578,10 @@ function XlsxGrid({
26528
26578
  });
26529
26579
  const targetTable = getTableAtCell(effectiveTables, targetRow, targetCol);
26530
26580
  const targetTableStyle = resolveTableCellStyle(targetTable, targetRow, targetCol, activeSheet);
26531
- const resolvedStyle = mergeResolvedCellStyle(targetRawStyle, targetTableStyle);
26581
+ const resolvedStyle = targetTableStyle ? mergeResolvedCellStyle(
26582
+ mergeResolvedCellStyle(targetRawStyle, targetTableStyle),
26583
+ resolveCellTableOverrides(targetRawStyle, activeSheet, targetRow, targetCol)
26584
+ ) : targetRawStyle;
26532
26585
  cellBaseRawStyleCacheRef.current.set(targetCacheKey, resolvedStyle);
26533
26586
  return resolvedStyle;
26534
26587
  };
@@ -28899,6 +28952,14 @@ function XlsxGrid({
28899
28952
  hasPendingGridlinePath = false;
28900
28953
  };
28901
28954
  const drawnMergedAnchorKeys = /* @__PURE__ */ new Set();
28955
+ const deferredDoubleBorders = [];
28956
+ const drawCellBorder = (side, rect, border) => {
28957
+ if (border.style === "double") {
28958
+ deferredDoubleBorders.push({ side, rect, border });
28959
+ } else {
28960
+ strokeCanvasBorderSide(paneContext, side, rect, border);
28961
+ }
28962
+ };
28902
28963
  for (const rowItem of paneAxisItems.rows) {
28903
28964
  for (const colItem of paneAxisItems.cols) {
28904
28965
  const cell = { row: rowItem.actualRow, col: colItem.actualCol };
@@ -29045,16 +29106,24 @@ function XlsxGrid({
29045
29106
  flushPendingGridlines();
29046
29107
  }
29047
29108
  if (topBorder && drawRowIndex === 0) {
29048
- strokeCanvasBorderSide(paneContext, "top", localRect, topBorder);
29109
+ drawCellBorder("top", localRect, topBorder);
29049
29110
  }
29050
29111
  if (resolvedRightBorder) {
29051
- strokeCanvasBorderSide(paneContext, "right", localRect, resolvedRightBorder);
29112
+ if (resolvedRightBorder.style === "double" && resolvedRightBorder === rightNeighborLeftBorder) {
29113
+ drawCellBorder("left", { ...localRect, left: localRect.left + localRect.width }, resolvedRightBorder);
29114
+ } else {
29115
+ drawCellBorder("right", localRect, resolvedRightBorder);
29116
+ }
29052
29117
  }
29053
29118
  if (resolvedBottomBorder) {
29054
- strokeCanvasBorderSide(paneContext, "bottom", localRect, resolvedBottomBorder);
29119
+ if (resolvedBottomBorder.style === "double" && resolvedBottomBorder === bottomNeighborTopBorder) {
29120
+ drawCellBorder("top", { ...localRect, top: localRect.top + localRect.height }, resolvedBottomBorder);
29121
+ } else {
29122
+ drawCellBorder("bottom", localRect, resolvedBottomBorder);
29123
+ }
29055
29124
  }
29056
29125
  if (leftBorder && drawColIndex === 0) {
29057
- strokeCanvasBorderSide(paneContext, "left", localRect, leftBorder);
29126
+ drawCellBorder("left", localRect, leftBorder);
29058
29127
  }
29059
29128
  if (cellData.chartHighlight) {
29060
29129
  const highlightBorder = {
@@ -29327,6 +29396,9 @@ function XlsxGrid({
29327
29396
  }
29328
29397
  }
29329
29398
  flushPendingGridlines();
29399
+ for (const { side, rect, border } of deferredDoubleBorders) {
29400
+ strokeCanvasBorderSide(paneContext, side, rect, border);
29401
+ }
29330
29402
  }
29331
29403
  for (const pane of cellPaneOrder) {
29332
29404
  const paneContext = bodyContexts[pane];