EditorState
EditorState is the immutable container for all editor state. Every change produces a new EditorState instance.
Creating State
Section titled “Creating State”import { EditorState } from '@notectl/core';
const state = EditorState.create({ doc: myDocument, // Optional Document schema: mySchema, // Optional Schema selection: mySel, // Optional EditorSelection});Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
doc | Document | The document tree |
selection | EditorSelection | Current cursor/selection (text or node) |
schema | Schema | Active schema (node + mark types) |
storedMarks | readonly Mark[] | null | Marks to apply on next input |
Methods
Section titled “Methods”getBlock(blockId: BlockId): BlockNode | undefined
Section titled “getBlock(blockId: BlockId): BlockNode | undefined”Look up a block by its ID (O(1) via internal index).
getBlockOrder(): readonly BlockId[]
Section titled “getBlockOrder(): readonly BlockId[]”Returns leaf-block IDs in depth-first document order.
getNodePath(nodeId: BlockId): BlockId[] | undefined
Section titled “getNodePath(nodeId: BlockId): BlockId[] | undefined”Returns the path (array of block IDs) from root to the given node.
getParent(nodeId: BlockId): BlockNode | undefined
Section titled “getParent(nodeId: BlockId): BlockNode | undefined”Returns the parent BlockNode of a node, or undefined for top-level blocks.
transaction(origin?: TransactionOrigin): TransactionBuilder
Section titled “transaction(origin?: TransactionOrigin): TransactionBuilder”Creates a TransactionBuilder for this state. The origin defaults to 'api'.
const tr = state.transaction('command') .insertText(blockId, offset, 'hello', []) .addMark(blockId, 0, 5, { type: markType('bold') }) .build();apply(tr: Transaction): EditorState
Section titled “apply(tr: Transaction): EditorState”Applies a transaction to produce a new state. This is a pure function — the original state is unchanged.
toJSON(): { readonly doc: Document; readonly selection: EditorSelection }
Section titled “toJSON(): { readonly doc: Document; readonly selection: EditorSelection }”Serializes the state (document and selection) to a JSON-compatible object.
static fromJSON(json: { doc: Document; selection: EditorSelection }, schema?: Schema): EditorState
Section titled “static fromJSON(json: { doc: Document; selection: EditorSelection }, schema?: Schema): EditorState”Deserializes a state from a JSON object. Optionally accepts a schema.
const json = state.toJSON();const restored = EditorState.fromJSON(json);Immutability
Section titled “Immutability”EditorState is deeply immutable:
const state1 = editor.getState();const tr = state1.transaction('command') .insertText(blockId, 0, 'hello', []) .build();const state2 = state1.apply(tr);
// state1 is unchangedassert(state1 !== state2);assert(state1.doc !== state2.doc);This enables:
- Undo/redo via state snapshots
- Safe comparison between old and new states
- Predictable plugin behavior — plugins always see consistent state
HistoryManager
Section titled “HistoryManager”Manages undo/redo stacks with automatic transaction grouping.
import { HistoryManager } from '@notectl/core';
const history = new HistoryManager({ groupTimeoutMs: 500, maxDepth: 100 });Constructor Options
Section titled “Constructor Options”| Option | Type | Default | Description |
|---|---|---|---|
groupTimeoutMs | number | 500 | Time window for grouping consecutive input transactions |
maxDepth | number | 100 | Maximum number of undo groups to retain |
Methods
Section titled “Methods”push(tr)
Section titled “push(tr)”Pushes a transaction onto the undo stack. Consecutive input transactions within groupTimeoutMs are grouped together — undoing the group reverts all of them at once.
history.push(transaction);undo(state)
Section titled “undo(state)”Undoes the last group. Returns a HistoryResult with the new state and the inverse transaction, or null if nothing to undo:
const result = history.undo(state);if (result) { // result.state — new EditorState after undo // result.transaction — the inverse transaction that was applied}redo(state)
Section titled “redo(state)”Redoes the last undone group. Returns a HistoryResult or null:
const result = history.redo(state);canUndo() / canRedo()
Section titled “canUndo() / canRedo()”Returns true if there are groups available to undo or redo:
if (history.canUndo()) { /* show undo button */ }if (history.canRedo()) { /* show redo button */ }clear()
Section titled “clear()”Clears both undo and redo stacks:
history.clear();HistoryResult
Section titled “HistoryResult”interface HistoryResult { readonly state: EditorState; readonly transaction: Transaction;}Grouping Behavior
Section titled “Grouping Behavior”The HistoryManager groups consecutive transactions of the same input type (e.g. typing characters) into a single undo group when they arrive within groupTimeoutMs of each other. This means pressing undo after typing “hello” undoes the entire word, not individual characters.
Groups are broken when:
- The timeout between transactions exceeds
groupTimeoutMs - The transaction origin changes (e.g. from
'input'to'command') - A non-input transaction is pushed