ReoGrid ReoGrid Web

Release Notes

All notable changes to @reogrid/lite and @reogrid/pro.

Format follows Keep a Changelog; versioning follows Semantic Versioning.

v1.3.0

Feature release. Headline item: multi-sheet workbooks — a grid is now a workbook of N worksheets with a core-provided sheet tab bar, per-sheet undo, whole-workbook xlsx/JSON I/O, and cross-sheet formula references (`=Sheet1!A1`). No breaking public-API changes.

Highlights

  • Multi-sheet workbooks. A grid is now a workbook of N worksheets with one active sheet and a core-provided sheet tab bar (add, rename, delete, drag-to-reorder, hide, tab color). Each sheet has its own data, selection, scroll, frozen panes, and undo history. New instance.workbook coordinator (addSheet / removeSheet / renameSheet / moveSheet / setActiveSheet / getSheets / onActiveSheetChange / onSheetsChange). Whole-workbook I/O on the instance: saveAsXlsx, loadXlsx / loadFromFile / loadFromUrl (loads all sheets), and toJson / loadJson. Available in both Lite and Pro; tier guards and row/col limits apply per sheet.
  • Cross-sheet formula references. Formulas can reference cells on other sheets: =Sheet1!A1, ='My Sheet'!A1:B2, and unquoted non-ASCII sheet names (=シート1!A1). Aggregates and the LOOKUP family work over cross-sheet ranges (=SUM(明細!A1:A3)). Excel-compatible lifecycle: renaming a sheet rewrites referencing formulas, deleting one turns references into #REF!, row/column insert/delete shifts other sheets' references, and cross-sheet cycles are detected (#CYCLE!). Available in both Lite and Pro.
  • Instance-level events that follow the active sheet. New instance.onSelectionChange / onCellValueChange / onBulkCellsChange / onScrollChange / onViewportSizeChange / onStructureChange / onContextMenu forward the active sheet's events and re-point automatically on a sheet switch — subscribe once instead of re-binding per sheet.

~ Changed

  • instance.worksheet and instance.actionManager are now getters returning the active sheet's. Existing single-sheet code is unchanged. Note: single-sheet embeds now show a ~28px sheet tab bar by default — pass createReogrid({ showSheetTabs: false }) to hide it.
  • Multi-sheet xlsx import parses the file once and reuses the parsed workbook for every per-sheet import (previously O(N) re-parses for an N-sheet file). New parseXlsx() helper + ParsedXlsx type.
  • Workbook view state round-trips through xlsx: active sheet, per-sheet hidden state, and sheet tab colors are written on export and restored on load. ReoGrid-JSON also persists per-sheet view.showGridlines.

v1.2.3

Patch release fixing native scrolling on very tall/wide sheets — notably the 1,000,000-row delay-load scenario introduced in 1.2.2. No public-API changes.

🐛 Fixed

  • Huge sheets can now scroll all the way to the last row. Browsers clamp an element's scroll extent around 2^24 px, so a 1,000,000-row sheet (~22M px tall) silently stopped scrolling at row ~762,600. The scroll spacer is now capped at 14M px and native scroll positions are proportionally mapped onto the full worksheet range; wheel deltas are compensated so scroll speed is unchanged. Sheets below the cap keep the exact 1:1 mapping — no behavior change for normal-sized sheets.

v1.2.2

Headline item: a Pro-only delay-load data source for displaying 1,000,000-row datasets. Also Excel-style horizontal text overflow, decimal capping in General number display, vertical text-metric fixes matching Excel/Google Sheets, and a package-entry audit that ships previously documented-but-unexported APIs. No breaking public-API changes.

Highlights

  • Delay-load data source (Pro) — display 1,000,000-row datasets. worksheet.setDataSource(config) attaches an on-demand row loader: only visible rows ± a configurable buffer are fetched through the user-supplied load(rows) callback (sync or async). Load requests are microtask-batched and deduplicated, scroll prefetch is debounced, a flood guard caps automatic request size (so select-all + copy doesn't scan the whole dataset), and epoch-based invalidation (invalidateAll() / invalidateRows()) discards stale in-flight results. The source auto-detaches on loadCells / loadCellsAsync / reset. v1 is display-only: no formulas / sort / filter over unloaded rows. Types DelayLoadConfig, DataRecord, DataLoadCallback, and DataSourceHandle are exported.
  • Excel-style horizontal text overflow. Un-wrapped cell text wider than its column now spills into adjacent empty cells and is clipped at the first cell that has content, an explicit fill, or belongs to a merge. Spill direction follows alignment (left→right, right→left, center→both).
  • General number display caps long decimals. Numeric cells without an explicit number format round their displayed decimals to a limit (default 4) — 0.300000000000000040.3, =1/30.3333. Display-only: stored values keep full precision. Configurable via createReogrid({ generalMaxFractionDigits }).

+ Added

  • New demo page: delay-load-demo.html — 1M rows with simulated server latency, fetch log, and jump-to-row.
  • Lite and Pro React/Vue wrappers now expose the worksheet event props/emits announced in v1.2: onSelectionChange, onCellValueChange, onBulkCellsChange, onScrollChange, onViewportSizeChange, onStructureChange. Pro wrappers type options as ReogridProOptions so licenseKey can be passed.
  • @reogrid/pro now exports the cell-type registration API (registerCellTypeHandler et al.), NumberFormat, the undoable action classes (ActionManager, ClipboardService, PasteAction, …), buildXlsxFromSnapshot, computeAutoFillValues / AutoFillAction, and common data types.
  • @reogrid/lite now exports the ReoGrid JSON I/O and the common data types. KeyboardController.clipboardService is now public readonly as documented.

🐛 Fixed

  • Cell text vertical metrics now match Excel / Google Sheets: default-font cells no longer auto-expand their row on first input; the inline editor is WYSIWYG (mirrors renderer line height and verticalAlign); bottom-aligned text sits close to the cell bottom (~2 px) instead of floating high.
  • Cells whose content is taller than their row now honor middle / bottom vertical alignment instead of clamping to the top.
  • HTML / browser-print output now draws merged-cell perimeter borders — the outer frame of merged title rows, notes boxes, and totals boxes is no longer dropped.

v1.2.1

Patch release. Extends the formula reference editing introduced in 1.2.0 with Excel-style drag-to-move and drag-to-resize on the on-grid reference highlights. No public-API changes.

+ Added

  • Drag-to-move and drag-to-resize for formula reference highlights. While editing a formula, dragging the dashed border of a reference rectangle translates the range; dragging one of the four corner grips resizes it. Every occurrence of that reference in the formula text is rewritten in step, preserving each token's absolute-reference ($) flags. Resize uses cell-center boundaries — a cell only joins or leaves the range once the pointer passes its midpoint — matching Excel and the .NET edition. Small colored corner squares are drawn on each highlight to make the resize hot-zone discoverable, with hover cursors (move, nwse-resize, nesw-resize) on the border and corners.

v1.2.0

Feature release. The formula library grows from 32 to 109 built-in functions, the cell editor gains Excel-style color-coded formula reference editing with click-to-insert, the selection now has a drag-fill handle, and conditional format rules can override borders per side. React and Vue wrappers expose worksheet events as component props. No breaking public-API changes.

Highlights

  • Auto-fill (drag fill handle). A small square at the bottom-right of the selection drags to extend values down / up / left / right. Single-cell drags tile-copy; two or more numeric cells extrapolate as an arithmetic progression (1, 23, 4, 5); a single date-formatted cell increments by one day; formulas shift their relative references the way Excel does ($-anchored cells preserved). Styles, number formats, and cell types propagate. Undo restores prior values.
  • Excel-style formula reference editing. While editing a formula (cell starting with =), clicking another cell inserts that cell's address at the caret; drag extends it into a range. Each unique reference is colored from a shared palette, and the grid draws a matching dashed rectangle around each referenced range. Highlight rectangles expand to enclose merged regions.
  • Enter starts cell editing. Mac-friendly default — Enter now begins edit mode (caret at end), matching Numbers and Excel for Mac. F2 still works.
  • 109 built-in formula functions (up from 32). New: VLOOKUP / HLOOKUP / INDEX / MATCH / XLOOKUP / XMATCH / ADDRESS; SUMIFS / COUNTIFS / AVERAGEIFS / MAXIFS / MINIFS / SWITCH; date TODAY / NOW / DATE / YEAR / MONTH / DAY / HOUR / MINUTE / SECOND / WEEKDAY / EDATE / EOMONTH / DAYS / DATEDIF; math SUMPRODUCT / CEILING / FLOOR / MROUND / MEDIAN / LARGE / SMALL / RANK / EXP / LN / LOG / LOG10 / SIGN / PI / RAND / RANDBETWEEN; trig SIN / COS / TAN / ASIN / ACOS / ATAN / ATAN2; text SEARCH / EXACT / PROPER / CHAR / CODE; info ROW / COLUMN / ROWS / COLUMNS.
  • Per-side border overrides in conditional formatting. CF rules can carry a border payload that paints right / top / bottom / left edges on matching cells, overriding manual borders per side. Read / written through the xlsx <dxf><border> round-trip.
  • React / Vue worksheet events as component props. Both wrappers now expose idiomatic event props for selection, cell value, bulk cell, scroll, viewport size, and structure changes. No more imperative worksheet.on*() subscriptions for the common cases.
  • reogrid-json I/O from the package main entry. Hosts persisting worksheets (e.g. ReoGrid Studio) no longer need to reach into deep paths — writeReoGridJson / readReoGridJson / parseReoGridJson and ReoGridJsonDocument / JsonWorksheet / JsonCell types are re-exported from both @reogrid/lite and @reogrid/pro.

+ Added

  • ReogridOptions.autoFill (default true) and Worksheet.setAutoFillEnabled() to toggle the fill handle.
  • AutoFillAction and computeAutoFillValues() exposed for programmatic auto-fill.
  • Worksheet.setFormulaRefHighlights() / CanvasWorksheet.setFormulaRefHighlights() and a THEME.formulaRefColors palette shared between editor and grid renderer.
  • Conditional format border payload (right / top / bottom / left, each with style + color), evaluated end-to-end through the engine, renderer, and xlsx writer.
  • React component event props: onSelectionChange, onCellValueChange, onBulkCellValueChange, onScroll, onViewportSizeChange, onStructureChange (in addition to onReady).
  • Vue component emits the same set of events with typed payloads.
  • @reogrid/lite and @reogrid/pro main entries now re-export writeReoGridJson, readReoGridJson, parseReoGridJson, plus the ReoGridJsonDocument / JsonWorksheet / JsonCell document types and the ReoGridJsonReadOptions / ReoGridJsonWriteOptions option types.
  • Formula function reference doc covering all 109 built-ins across 10 categories.

~ Changed

  • Formula reference highlight in the editor expands to enclose merged regions when a referenced cell or range overlaps a merge — matches Excel rather than Google Sheets.

🐛 Fixed

  • Auto-fill hover cursor is now applied on the scroll container as well, so the cross-hair cursor appears reliably across the entire fill-handle hit area.
  • Render-cache key no longer contains an embedded NUL byte; it is replaced with |, avoiding rare measurement-cache collisions and string-handling oddities.

Performance

  • Per-frame canvas state cache cuts redundant API calls on Book1.xlsx scroll: ctx.font= 129 → 34 (-74%), ctx.fillStyle= 179 → 46 (-74%), ctx.measureText() 126 → 35 (-72%), save()/restore() 122 → 85 (-30%). In real browsers, where ctx.font parsing and measureText shaping dominate per-cell cost, this translates directly to smoother scrolling on large sheets.
  • layoutPlainTextLines() output is cached per frame for wrapped / multi-line cells. Text-heavy sheets with wrap-text see a large reduction in per-frame work during scroll. Single-line unwrapped text takes a fast path that bypasses the cache.

v1.1.0

Maintenance release focused on xlsx I/O fidelity and load performance, plus outline read/write parity with the .NET edition. No breaking public-API changes.

Highlights

  • xlsx import is ~40% faster on large files. A 1945×503 sheet with ~440k cells now loads in 3.7 s instead of 6.2 s.
  • Optional chunked async load (LoadXlsxOptions.chunked) for snappier UI on big files — first paint at ~40 ms instead of one multi-second freeze. Default remains synchronous.
  • xlsx outline round-trip. Outline level, hidden, collapsed state, and summary direction (above/below, left/right) now read and write, matching the .NET edition.
  • ReoGrid JSON file format. Native lossless serialization covering cells, styles, number formats, rich text, merges, borders, sizes/visibility, freeze, conditional formats, outlines, filter, cell types, protection, and alternate rows.
  • Outline summary direction. setRowSummaryBelow / setColumnSummaryRight flip the toggle button to the leading edge of a group. The outline panel now reserves an "expand all" innermost slot, matching Excel.

+ Added

  • LoadXlsxOptions.chunkedfalse (default, sync), true (chunked with default batch size), or { batchSize } for explicit control. await ws.loadFromFile(file, { chunked: true }).
  • Worksheet.loadCellsAsync(cells, { batchSize }) — chunked async variant that yields between batches and renders progressively. Default batch size 5000 cells.
  • ReoGrid JSON read/write APIs (writer + reader).
  • xlsx read/write support for row and column outlines: level, hidden, collapsed, and summary direction.
  • setRowSummaryBelow(value) / setColumnSummaryRight(value) on Worksheet, with undo/redo support.
  • "Expand all" outline level button (innermost slot of the outline panel).
  • AutoFitMode option ('fit' | 'expandOnly' | 'shrinkOnly') on autoFitColumns, autoFitRows, and the RowHandle / ColumnHandle autoFit({ mode }) overloads. Default 'fit' preserves existing behavior.
  • value accepted as alias for value1 on conditional format cellIs rules. value2 remains required for between / notBetween. If both value and value1 are provided, value1 wins.
  • xlsx import now resolves theme colors and tint on cell fills.
  • xlsx import now reads dxf fills expressed via <bgColor> (in addition to <fgColor>), so conditional format fills written by Excel come through correctly.
  • Code runner demo page.

~ Changed

  • xlsx import now applies outlines and conditional formats before the async cell ingest, so the first paint shows the correct collapsed state instead of expanding then snapping.
  • Canvas font strings always include a generic sans-serif fallback so the italic / bold prefix survives when the named family isn't installed (e.g. xlsx files referencing "Aptos Narrow" on machines without Office).

🐛 Fixed

  • Borders no longer rendered for cells in hidden rows or columns. Previously, a left border on column A would still paint as a vertical line at the row-header boundary when columns A-J were hidden by a collapsed outline group. Matches .NET behavior.
  • xlsx import: bold defined via cellXf/font on plain shared strings now renders correctly. Previously every plain shared string was flagged as rich text and the renderer ignored the cell-level style.
  • Number format conditional sections ([=0], [<>N], [<N], [<=N], [>N], [>=N]) now evaluate independent of value type. Format codes like [=0]"-";m/d/yy no longer always pick the first section.
  • Excel serial date epoch off-by-one corrected. Serial 45658 now resolves to 2025-01-01 as expected.
  • xlsx import now resolves theme colors, tint, and dxf fills expressed via <bgColor> — all common in Excel-saved files.
  • Multi-word font families (e.g. "Aptos Narrow") on the plain-text render path are no longer double-quoted, which previously caused Canvas 2D to silently drop the italic / bold prefix.
  • Column header labels are now skipped for hidden columns. Collapsing an outline group no longer causes header letters to overprint at the next visible column.
  • Outline toggle buttons and bracket lines for groups hidden by a collapsed parent are now skipped — the inner toggle no longer paints on top of the outer toggle row.
  • Adding partially-overlapping outline groups now throws a clear error. Outline groups must form a strict tree; previously crossings produced visible-but-unclickable inner toggles.
  • Outline corner-area level-button hit test now aligns with the renderer when both row and column outline panels are present.
  • Malformed conditional format cellIs rules (missing value1) no longer crash the render loop; the rule simply returns no-match.
  • Playground demo: opening an xlsx file on the first click now works (the toolbar previously held a stale worksheet=null closure until a re-render).

Performance

  • xlsx end-to-end load time on a 1945×503 / ~440k-cell test file: 6.2 s → 3.9 s (-37%) in node. Improvements span the parser, the cell-extraction walk, the worksheet bulk-load path, and the formula engine's initial rebuild.
  • Lazy row auto-fit on import: only viewport-visible rows are measured up front, additional rows are measured once on first scroll into view. Skips ~1M useless cell visits on Book1-class sheets.
  • Optional chunked ingest ({ chunked: true }) collapses the user-visible "stuck" window from one multi-second freeze to 16-30 ms slices.

v1.0.0

First stable release. The public API is now considered frozen under semver: any breaking change after 1.0.0 will require a major bump.

Highlights

  • Handle-based public API. All structural and styling operations go through chained handles (worksheet.row(i), worksheet.column('B'), worksheet.range('A1:C5').setBold(), worksheet.selection.range?.setStyle(...)) instead of flat top-level methods. This is the API users should build against going forward.
  • Internal Manager layering. Worksheet is now an entry point; state mutation lives in StyleOperations, SizingManager, VisibilityManager, and StructureManager.
  • Formula engine. Lexer → parser → evaluator → dependency graph + 32 built-in functions. Imported xlsx formulas are re-evaluated. 151 formula tests across tests/formula.spec.ts and tests/formula-ext.spec.ts.
  • Pluggable cell types. CellTypeHandler registry with 8 built-in types: checkbox, dropdown, button, progress, rating, sparkline (line / area), and hyperlink.
  • Conditional formatting (Pro). addConditionalFormat, removeConditionalFormat, clearConditionalFormats, getConditionalFormats.
  • Cell tooltips (Pro). setCellTooltip, showCellTooltip, hideCellTooltip, clearCellTooltip.
  • Browser printing (Pro). printWorksheet(...) standalone function. In Lite this is a console.warn stub for upgrade prompting.
  • xlsx round-trip. Import/export with cross-validation against the .NET ReoGrid edition.
  • Lite / Pro tier guards. Lite enforces 100 rows × 26 columns and stubs Pro-only methods at both the public-handle layer and the internal Manager chokepoint.
  • React and Vue wrappers. Published as separate entry points: @reogrid/lite/react, @reogrid/lite/vue, @reogrid/pro/react, @reogrid/pro/vue.

+ Added

  • worksheet.reset(options?) — wipe the worksheet back to a blank state in-place. Clears values, styles, cell types, header dropdowns, conditional formats, cell protection, borders, merges, hidden rows/columns, outlines, frozen panes, custom row/column sizes, scroll, and selection; resets showGridLines to true. Optionally resizes the grid via options.rows / options.columns. CanvasWorksheet extends this to also clear images, the auto-filter, and tooltips. The xlsx importer now uses this as its single-shot pre-load reset.
  • worksheet.rows.setCount(count) and worksheet.columns.setCount(count) on RowCollection / ColumnCollection for single-axis resizing.
  • printWorksheet re-export from @reogrid/lite as a console.warn stub so the guard mechanism is uniform with PRO_METHODS.
  • PRO_MANAGER_METHODS + applyLiteWorksheetGuards close the Manager backdoor (structureManager.insertRows, visibilityManager.setRowHidden, …) so per-handle entry points cannot bypass tier guards.
  • yarn test:perf script and tests/**/*-benchmark.spec.ts naming convention so day-to-day yarn test stays fast while benchmarks remain opt-in.
  • ResizeObserver on the worksheet container so the canvas reacts to flex / sidebar / panel layout changes.
  • requestAnimationFrame-based render batching (Worksheet.scheduleRender).
  • bulkSetCells() API for fast bulk loading of large datasets.
  • Excel-style keyboard selection: anchor + focus model, Shift+click selection extension, direction-aware merge navigation, auto-scroll on keyboard / drag.
  • Auto-expanding cell editor with grid-snapped resize.
  • tsconfig.json stripInternal: true so @internal members no longer leak into published .d.ts.

~ Changed

  • Breaking: worksheet.setRowCount(n) and worksheet.setColumnCount(n) removed. Use worksheet.rows.setCount(n) / worksheet.columns.setCount(n), or worksheet.setGridSize(rows, cols) for atomic both-axes resize.
  • Breaking: worksheet.rows / worksheet.columns now refer to the RowCollection / ColumnCollection handles. The numeric counts moved to worksheet.rowCount / worksheet.columnCount.
  • Breaking: worksheet.selection is now a thin SelectionHandle exposing bounds / isEmpty / activeCell / range / moveTo only. Style and value operations on the current selection should go through worksheet.selection.range?.setBold() instead of delegators on the handle itself.
  • Breaking: Flat setSelection*Bold/Italic/Style/... methods removed in favour of the handle API (worksheet.range(...).setBold()).
  • KeyboardController now listens on the worksheet container, not on window, so multiple grid instances on the same page do not cross-fire keyboard events.
  • CellEditor inline textarea now uses position: absolute relative to the worksheet container instead of position: fixed, fixing misalignment inside CSS transform ancestors, modal dialogs, and iframes.
  • Merged cell rendering now draws content from the topmost-leftmost still-visible cell when the merge anchor has scrolled out of view.

🐛 Fixed

  • COUNT(1, 1/0, 2) and similar — errors in direct arguments now propagate (matches Excel semantics). Errors inside range arguments remain ignored.
  • #REF! correctly cached after row/column delete (was previously surfacing as #NAME? because EXCEL_ERROR_LITERALS was not consulted in the evaluator's name node).
  • bulkSetCells initial render path on big-data demo.
  • Editor backgrounds now respect cell backgroundColor.
  • Various double-click and edit-commit edge cases in the pointer / editor interaction.

Removed

  • Legacy flat setSelection* API surface (use the handle API).
  • worksheet.setRowCount / setColumnCount (use collection setCount).

! Known issues

  • worksheet.columnWidths / rowHeights arrays are still mutable via JS array indexing (not enforced by readonly).
  • React <Reogrid> ignores options prop changes after mount (use key to force remount).
  • Auto-fit is O(rows) per column.
  • devicePixelRatio is read once per resize() and is not updated on monitor change.

For the raw changelog and earlier history, see the @reogrid/lite package on npm.

Stay Updated

Be first to know — get updates as they ship

Get notified of new releases, features, and announcements.
No spam — just updates that matter.