Skip to content
GRID Editor

Changelog

  • Upgrade the underlying spreadsheet engine (Apiary) to 17.0.0, which brings pivot table support and replaces transient writes with explicit value snapshots. As a result of the value-snapshot change, ProxiedCell.isModifiedState (and its _v field) can no longer be derived and have been removed.
  • Add insertCells (shift down / shift right) with a right-click context menu and Ctrl++ keyboard shortcut, complementing delete cells.
  • Add a download XLSX button to the editor toolbar
  • Render row and column headers on the Mondrian canvas instead of in the DOM. The DOM header strips become invisible interaction shells that keep their geometry, test IDs, and handlers, while the labels, gridlines, and corner are painted as part of Mondrian’s single render pass. This removes a duplicate rendering path and keeps the header labels in sync with the canvas after fast scrolls. Header dimensions now derive from Mondrian’s font size (≈18×25px at font size 11).
  • Add an autoFocus option to focus the spreadsheet when it mounts, plus a focus() method on the editor controller to focus the spreadsheet programmatically. focus() accepts an optional cell reference (e.g. focus("Sheet1!A4")) to move the selection — switching sheets when the reference names one — before taking focus.
  • Add deleteCells (shift up / shift left) with a right-click context menu and Ctrl+- keyboard shortcut. Cut / Copy / Paste and row / column delete are also available from the new cell context menu.
  • Update @biomejs/biome to 2.5.1 and reformat SCSS to match its stricter checks. Also fixes two bugs found along the way:

    • headerlayer.module.scss used color.adjust(..., vars.$lightness: -5%), an invalid namespaced keyword argument, silently skipping the intended darkened background on hover/read-only-selected column and row headers.
    • Biome’s automatic property-sort fix moved @include reset.resetButton(); after explicit property overrides in four components (toolbar option buttons, the formatting menu item button, and the modal’s confirm/cancel buttons), so the mixin’s reset styles were clobbering the intended padding/margin. Restored the mixin to run first and pinned that order against future auto-formatting.
  • Simplify scroll handling by removing the scroll-position debounce: the canvas now paints synchronously from scroll events and clicks hit-test against the live scroll position, keeping selection and rendering in sync with scrolling.

  • Pin the cell canvas max/min width so host-page CSS resets can’t shrink it below the painted size, which was misaligning column headers from the cells.

  • Update dependencies: @jsfkit/types 2.4.0 → 2.5.0, lucide-react 1.16.0 → 1.21.0, sass 1.100.0 → 1.101.0, @types/react 19.2.15 → 19.2.17, and the build/test toolchain (vite, vitest, tsdown, @playwright/test, @vitejs/plugin-react).

  • Update dependencies: React 19.2.6 (react and react-dom), lucide-react 1.11.0 → 1.16.0, @jsfkit/types 2.2.0 → 2.4.0, postcss 8.5.14 → 8.5.15, sass 1.98.0 → 1.100.0, and the build/test toolchain (vite, vitest, tsdown, @playwright/test, @vitejs/plugin-react).

  • Keep the selection glued to the grid while scrolling. The selection overlay is translated to follow the synchronously painted canvas between React commits; on commit the translate was blanked to zero, which stranded the overlay a frame behind the cells whenever a newer scroll event had already moved the canvas past the committed position. The commit now re-derives the translate from the live scroll offset, so the selection tracks the grid frame-for-frame. Most visible on full-row/full-column selections, whose viewport-spanning borders made the lag obvious.

    Also make the performance cap on full-row/full-column selection boxes symmetric, leaving off-screen slack on every side instead of only the trailing edge.

  • Simplify how the editor handles scrolling. No change to how the editor behaves.

  • Update @grid-is/mondrian to 2.0.1, removing a workaround for a rendering type mismatch that mondrian 2.0.1 fixes upstream.

  • Cell coordinate calculations now share a single source of truth with the canvas renderer, preventing alignment drift between the grid and selection, header, and editing overlays.

  • Clamp the scrollable area to the interactive bounds. The scrollable area was slightly larger than the part of the sheet you can interact with, so a scroll could land past the content. The scrollable area now matches the interactive bounds.

  • Update @tsdown/css to 0.22.3 to match the already-updated tsdown version, and hoist postcss-modules to the workspace root so tsdown can resolve it at build time.

  • Upgrade to @grid-is/apiary 16 and @grid-is/mondrian 2.
  • Make keyboard navigation aware of merged cells
  • Upgrade to jsfkit/types v2 with structured Color objects, apiary 16, and mondrian 1.14
  • Export all editor event interfaces (WriteCellEvent, PasteEvent, etc.) from the package
  • Add tab cycling within a selected range
  • Add mergeAnchor property to Selection for merged cell anchor rendering
  • Handle shift+arrow contraction near merged cells
  • Bump vite from 7.3.1 to 8.0.2
  • Update @grid-is/apiary to 16.1.0.
  • Bump @jsfkit/types from 2.0.0 to 2.2.0
  • Bump tsdown from 0.19.0 to 0.21.10
  • Bump @vitejs/plugin-react from 5.2.0 to 6.0.1
  • Remove leftover eslint-disable directives (ESLint is not used in this project)
  • Bump lucide-react from 0.563.0 to 1.11.0
  • Bump sass from 1.97.3 to 1.98.0
  • Persist and restore sheet selection when switching between sheets
  • Bump jsdom from 27.4.0 to 29.0.1
  • Remove prop-types dependency
  • Remove unused ts-morph dependency
  • Set explicit build target to fix esbuild 0.27.7 compatibility with vite-plugin-top-level-await
  • Bump vite from 7.3.1 to 7.3.2
  • Programmatically navigate to any cell or range, including switching sheets, from outside the editor.
  • The onChange callback now receives structured editor events, letting embedding apps react to specific user actions like cell edits, formatting changes, sheet additions, and more.
  • Include documentation on the @grid-is/editor-react public API (auto-generated from JSDoc)
  • Fix formula references merging when dragging one over another
  • Add showErrorTooltips prop to display an error tooltip when a cell containing a formula error is selected
  • CSS is now auto-injected into the ESM bundle — ESM consumers no longer need to import @grid-is/editor-react/editor-styles.css separately. CJS consumers should continue importing it manually.
  • Remove Roboto Mono from the editor. The robotoMonoUrl prop has been removed from FontConfig. The formula bar and cell inputs fall back to the system monospace font stack.
  • Fix function docs and picker staying visible after committing a formula edit
  • Add initialSelection prop to SpreadsheetEditor and scroll it into view
  • Replace config prop with direct fontConfig prop on SpreadsheetEditor
  • Add formula reference highlighting on cell selection
  • Remove useApiaryEditor hook and accept Model directly on SpreadsheetEditor
  • Replace boundsConfig hook option with a size prop on SpreadsheetEditor.
  • Isolate editor styles from consumer CSS with defensive resets and scoped class selectors

  • Add documentation site with guides and API reference (https://docs.grid.is/editor/)

  • Fix scroll feedback loop causing jerky scrolling

  • Use modular string.quote to fix Sass deprecation warning for global quote() function

  • Upgrade @grid-is/apiary to ^15.3.1 and remove vite-plugin-node-polyfills

  • Remove xlsx-convert as a direct dependency, use apiary’s built-in conversion instead

  • Sheet tab bar redesign to match mondrian-react viewer. Adding a matching fx icon to the formula bar as well as polishing hover states, button alignments, dropdown behavior and documents statistics footer.

  • Fix Editor not reflecting changes made directly to Apiary model outside Editor methods. Consumers can update model directly, but UI stayed stale because Editor never detected external modifications.

    Editor now listens to Apiary recalc events and updates internal state when model changes occur outside Editor interface.