The history() extension tracks undo and redo batches for an editor.
Usage
import { createEditor } from "@platejs/plite";
import { history } from "@platejs/plite-history";
const editor = createEditor({
extensions: [history()],
});
editor.read((state) => state.history.undos());
editor.update((tx) => {
tx.history.undo();
});
editor.update({ history: "skip" }).text.insert("draft");import { createEditor } from "@platejs/plite";
import { history } from "@platejs/plite-history";
const editor = createEditor({
extensions: [history()],
});
editor.read((state) => state.history.undos());
editor.update((tx) => {
tx.history.undo();
});
editor.update({ history: "skip" }).text.insert("draft");History Object
import type { EditorStatePatch, Operation, Range } from "@platejs/plite";
export interface History {
redos: Batch[];
undos: Batch[];
}
interface Batch {
operations: Operation[];
selectionBefore: Range | null;
selectionBeforeRoot?: string;
statePatches: EditorStatePatch[];
}import type { EditorStatePatch, Operation, Range } from "@platejs/plite";
export interface History {
redos: Batch[];
undos: Batch[];
}
interface Batch {
operations: Operation[];
selectionBefore: Range | null;
selectionBeforeRoot?: string;
statePatches: EditorStatePatch[];
}Static Methods
History.isHistory(value: unknown): value is History
Returns true if the passed in value is a History object and acts as a
type guard.
Editor API
state.history(): History
Read the current undo and redo stacks.
state.history.undos(): Batch[]
Read the undo stack.
state.history.redos(): Batch[]
Read the redo stack.
tx.history.undo(): void
Undo the previous history batch.
tx.history.redo(): void
Redo the next history batch.
tx.history.skip(): void
Do not save the current transaction to history.
tx.history.merge(): void
Merge the current transaction into the previous compatible undo batch.
tx.history.newBatch(): void
Start a fresh undo batch for the current transaction.
editor.update({ history: "skip" }, fn): void
Run one update without saving it to history.
editor.update({ history: "merge" }, fn): void
Run one update that merges into the previous compatible undo batch.
editor.update({ history: "new-batch" }, fn): void
Run one update where the first operation starts a fresh history batch, then the rest of the callback merges into that batch.
For one direct write, configure the update facade instead:
editor.update({ history: "skip" }).text.insert("draft");editor.update({ history: "skip" }).text.insert("draft");editor.update.history.undo(): void
Undo the previous history batch outside a larger transaction.
editor.update.history.redo(): void
Redo the next history batch outside a larger transaction.
Controlled Previews
Render proposed edits from local state, decorations, or sidecar UI until the user accepts them. Do not mutate document content for a preview and then try to make that preview history later.
Use a local defineStateField with persist: false and history: 'skip' for
preview state. Cancel by clearing that field. Accept by clearing the preview and
applying the real document edit in one normal update.
const previewReplacement = defineStateField<string | null>({
key: "local.preview.replacement",
history: "skip",
initial: () => null,
persist: false,
});
editor.update((tx) => {
tx.setField(previewReplacement, null);
tx.text.delete({ at: selectedRange });
tx.text.insert(acceptedText);
});const previewReplacement = defineStateField<string | null>({
key: "local.preview.replacement",
history: "skip",
initial: () => null,
persist: false,
});
editor.update((tx) => {
tx.setField(previewReplacement, null);
tx.text.delete({ at: selectedRange });
tx.text.insert(acceptedText);
});Undo then restores the document content without resurrecting preview UI.
On This Page
UsageHistory ObjectStatic MethodsHistory.isHistory(value: unknown): value is HistoryEditor APIstate.history(): Historystate.history.undos(): Batch[]state.history.redos(): Batch[]tx.history.undo(): voidtx.history.redo(): voidtx.history.skip(): voidtx.history.merge(): voidtx.history.newBatch(): voideditor.update({ history: "skip" }, fn): voideditor.update({ history: "merge" }, fn): voideditor.update({ history: "new-batch" }, fn): voideditor.update.history.undo(): voideditor.update.history.redo(): voidControlled Previews