@extend-ai/react-xlsx 0.10.4 → 0.12.0

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
@@ -225,7 +225,7 @@ These hooks work inside `XlsxViewer` or `XlsxViewerProvider` context.
225
225
  - `useXlsxViewer()` for full controller access
226
226
  - `useXlsxViewerSelection()` for active cell and range state
227
227
  - `useXlsxViewerZoom()` for zoom controls and limits
228
- - `useXlsxViewerEditing()` for editing, undo/redo, fill, merge, clipboard, and export actions
228
+ - `useXlsxViewerEditing()` for editing, persisted style writes, undo/redo, fill, merge, clipboard, and export actions
229
229
  - `useXlsxViewerTables()` for table metadata and table sorting
230
230
  - `useXlsxViewerImages()` for embedded image and chart selection, movement, and resizing
231
231
  - `useXlsxViewerCharts()` for chart and chartsheet state
@@ -407,12 +407,108 @@ Common rendering props:
407
407
  - `loadingState?: React.ReactNode`
408
408
  - `errorState?: React.ReactNode | ((error: Error) => React.ReactNode)`
409
409
  - `fileTooLargeState?: React.ReactNode | ((props: XlsxFileTooLargeRenderProps) => React.ReactNode)`
410
+ - `getCellStyle?: (context: XlsxCellStyleContext) => React.CSSProperties | null | undefined`
410
411
  - `renderImage?: (props: XlsxImageRenderProps) => React.ReactNode`
411
412
  - `renderImageSelection?: (props: XlsxImageSelectionRenderProps) => React.ReactNode`
412
413
  - `renderChartLoading?: (props: XlsxChartLoadingRenderProps) => React.ReactNode`
413
414
  - `renderTableHeaderMenu?: (props: XlsxTableHeaderMenuRenderProps) => React.ReactNode`
414
415
  - `renderScroller?: (props: XlsxScrollerRenderProps) => React.ReactNode`
415
416
 
417
+ ### Persisted Cell Styling
418
+
419
+ Use `setCellStyle`, `setSelectedCellStyle`, and `setRangeStyle` when a custom toolbar should write Excel formatting into the workbook. These APIs mutate workbook data, participate in undo/redo, refresh the viewer, and are included in `exportXlsx()`.
420
+
421
+ ```tsx
422
+ import {
423
+ useXlsxViewer,
424
+ type XlsxCellStyleInput
425
+ } from "@extend-ai/react-xlsx";
426
+
427
+ const highlightStyle: XlsxCellStyleInput = {
428
+ font: { bold: true, color: { colorType: "rgb", hex: "1D4ED8" } },
429
+ fill: { fillType: "solid", color: { colorType: "rgb", hex: "DBEAFE" } },
430
+ alignment: { horizontal: "center", vertical: "center", wrapText: true }
431
+ };
432
+
433
+ function FormattingButton() {
434
+ const { selection, setRangeStyle, setSelectedCellStyle } = useXlsxViewer();
435
+
436
+ return (
437
+ <button
438
+ type="button"
439
+ onClick={() => {
440
+ if (selection) {
441
+ setRangeStyle(selection, highlightStyle);
442
+ return;
443
+ }
444
+ setSelectedCellStyle(highlightStyle);
445
+ }}
446
+ >
447
+ Highlight
448
+ </button>
449
+ );
450
+ }
451
+ ```
452
+
453
+ `XlsxCellStyleInput` supports these persisted Excel style groups:
454
+
455
+ | Field | Type | Notes |
456
+ | --- | --- | --- |
457
+ | `font` | `XlsxCellFontStyleInput` | Font family, size, bold, italic, underline, strikethrough, color, superscript/subscript. |
458
+ | `fill` | `XlsxCellFillStyleInput` | Solid, pattern, and gradient fills. |
459
+ | `border` | `XlsxCellBorderStyleInput` | Per-edge borders, colors, styles, and diagonal borders. |
460
+ | `alignment` | `XlsxCellAlignmentInput` | Horizontal/vertical alignment, wrap text, shrink to fit, indent, rotation, reading order. |
461
+ | `numberFormat` | `XlsxCellNumberFormatInput` | General, builtin, or custom Excel number format strings. |
462
+ | `protection` | `XlsxCellProtectionInput` | Locked/hidden flags used when sheet protection is enabled. |
463
+
464
+ ### Render-Only Cell Styling
465
+
466
+ `getCellStyle` is an escape hatch for styling individual cells without forking the workbook data. It is called for every rendered cell and returns a partial `React.CSSProperties` that merges on top of the viewer's resolved style. Return `undefined` (or `null`) to leave a cell untouched.
467
+
468
+ ```tsx
469
+ import { XlsxViewer, type XlsxViewerProps } from "@extend-ai/react-xlsx";
470
+
471
+ function Workbook({ buffer, highlighted }: { buffer: ArrayBuffer; highlighted: Set<string> }) {
472
+ const getCellStyle = React.useCallback<NonNullable<XlsxViewerProps["getCellStyle"]>>(
473
+ ({ cell, isTableHeader }) => {
474
+ if (isTableHeader) {
475
+ return undefined;
476
+ }
477
+ if (highlighted.has(`${cell.row}:${cell.col}`)) {
478
+ return { backgroundColor: "rgba(37, 99, 235, 0.12)", outline: "1px solid #2563eb" };
479
+ }
480
+ return undefined;
481
+ },
482
+ [highlighted]
483
+ );
484
+
485
+ return <XlsxViewer file={buffer} getCellStyle={getCellStyle} />;
486
+ }
487
+ ```
488
+
489
+ The `context` passed to `getCellStyle` is an `XlsxCellStyleContext`:
490
+
491
+ | Field | Type | Notes |
492
+ | --- | --- | --- |
493
+ | `cell` | `XlsxCellAddress` | Address of the cell being styled. |
494
+ | `workbookSheetIndex` | `number` | Workbook sheet index of the cell's sheet. |
495
+ | `sheetName` | `string` | Display name of the cell's sheet. |
496
+ | `resolvedStyle` | `React.CSSProperties` | The style the viewer computed (workbook formatting + built-ins). Read-only. |
497
+ | `value` | `string` | The cell's resolved display value. |
498
+ | `hasValidation` | `boolean` | Cell has a data validation rule. |
499
+ | `hasHyperlink` | `boolean` | Cell has a hyperlink. |
500
+ | `hasConditionalFormat` | `boolean` | Cell is affected by a color scale, data bar, or icon set. |
501
+ | `hasChartHighlight` | `boolean` | Cell is in a selected chart's highlighted source range. |
502
+ | `isMerged` | `boolean` | Cell is the anchor of a merged range. |
503
+ | `isTableHeader` | `boolean` | Cell is a table header cell. |
504
+
505
+ Notes:
506
+
507
+ - Keep the callback stable (e.g. `useCallback`) so cell styling is not recomputed every render. When the callback identity changes, the viewer re-resolves and repaints cells.
508
+ - The DOM renderer (`experimentalCanvas={false}`) applies every returned CSS property.
509
+ - The canvas renderer (the default) honors the subset it can paint: `backgroundColor`, `backgroundImage` gradients, `color`, the four `border*` sides, `padding`, `textAlign`, `textDecoration`, `textOverflow`, and font properties. CSS-only effects such as `boxShadow`, `outline`, or `animation` apply in the DOM renderer.
510
+ - `getCellStyle` is not applied to worksheet thumbnails painted via `useXlsxViewerThumbnails(...)`.
511
+
416
512
  ### Custom Scroll Area
417
513
 
418
514
  By default, the viewer renders its native scroll viewport with the browser scrollbar. To use a custom scroll area, provide `renderScroller` and spread `viewportProps` onto the actual scrollable viewport element:
@@ -478,6 +574,8 @@ The package exports the main types you are likely to use for custom integrations
478
574
  - `XlsxViewerCharts`
479
575
  - `XlsxViewerThumbnails`
480
576
  - `XlsxScrollerRenderProps`
577
+ - `XlsxCellStyleContext`
578
+ - `XlsxCellStyleInput`, `XlsxCellFontStyleInput`, `XlsxCellFillStyleInput`, `XlsxCellBorderStyleInput`
481
579
  - `XlsxSheetThumbnail`
482
580
  - `UseXlsxViewerThumbnailsOptions`
483
581
  - `XlsxChart`, `XlsxChartSeries`, `XlsxChartAxis`, `XlsxChartsheet`
Binary file