Skip to content

Events

Ezygrid uses a serializable-operation event model. All model mutations flow through one channel.

Operation stream

ts
const unsubscribe = workbook.onOperation((op) => {
  console.log(op.type, op.payload);
});
// later
unsubscribe();
ts
interface Operation<T = unknown> {
  id: string;          // stable, collaboration-ready
  actorId?: string;
  workbookId: string;
  worksheetId?: string;
  type: OperationType;
  payload: T;
  timestamp: number;
}

Operation types

TypeEmitted by
cell.setsetValue, editor commits, paste, fill
cells.set / cells.replacebulk writes, sorting permutations
meta.setstyles, number formats, notes, cell editors, hidden rows/columns, sizes
merges.setmerge/unmerge (payload carries added/removed rects)
rows.insert / rows.delete / rows.movestructural row edits
columns.insert / columns.delete / columns.movestructural column edits
worksheet.add / worksheet.remove / worksheet.renamesheet management
validation.rejecta reject-action validation blocked a write
workbook.updateaggregated beginUpdate()/endUpdate() batch
undo / redohistory replay markers

Selection changes

ts
const off = renderer.selection.onChange((state) => {
  console.log(renderer.selection.describe()); // "A1" or "A1:C4"
});

Edit lifecycle

ts
import { EditService } from '@ezygrid/core';

const editing = new EditService({
  onEditStart(session) { /* session: { row, column, initial, mode } */ },
  onEditCancel() {},
  onCommit(session, value) {},
});
editing.editing; // boolean

The renderer drives its own EditService; hooks like onReady (React) give you access via renderer.editing.

Extending the channel

Plugins can emit operations through workbook APIs and observe everything with a single listener — this makes operation streams the natural bridge for persistence, syncing, and analytics.

Released under the MIT License.