UNPKG

mobx-bonsai

Version:

A fast lightweight alternative to MobX-State-Tree + Y.js two-way binding

169 lines (168 loc) 4.86 kB
import { UndoEvent, UndoStore } from './UndoStore'; /** * Interface for managing attached state with undo events. */ export interface AttachedStateHandler<TAttachedState = unknown> { save(): TAttachedState; restore(state: TAttachedState): void; } /** * Options for creating an UndoManager. */ export interface UndoManagerOptions<TAttachedState = unknown> { /** * The subtree root to track changes on. */ rootNode: object; /** * Optional UndoStore to use. If not provided, a new one will be created. * * Note: The UndoStore is not subject to the undo manager, even if it is * a child of the rootNode. Changes to the UndoStore itself will not * be tracked or undoable. */ store?: UndoStore; /** * Maximum number of undo levels to keep. * @default Infinity */ maxUndoLevels?: number; /** * Maximum number of redo levels to keep. * @default Infinity */ maxRedoLevels?: number; /** * Attached state management for storing additional state with each undo event. */ attachedState?: AttachedStateHandler<TAttachedState>; /** * Time window in milliseconds for grouping changes into a single undo event. * If undefined (default), changes are only grouped within the same MobX action. * If set to a number, changes that occur within this time window will be merged * into the last undo event, even if they come from different actions. * * @default undefined */ groupingDebounceMs?: number; } /** * Manages undo/redo functionality for a mobx-bonsai node tree. * Automatically groups changes that occur within a single MobX action. */ export declare class UndoManager<TAttachedState = unknown> { #private; private disposer; private interceptDisposer; private isRecordingDisabled; private readonly _maxUndoLevels; private readonly _maxRedoLevels; private readonly attachedState?; private readonly groupingDebounceMs?; /** * Timestamp (performance.now()) of when the last undo event was recorded. * Used for grouping debounce logic. */ private lastEventTimestamp; /** * The root node being tracked. */ readonly rootNode: object; /** * The UndoStore holding the undo/redo queues. */ readonly store: UndoStore; /** * Array of changes accumulated during the current action. * These will be flushed as a single UndoEvent when the action completes. * If length > 0, a flush is already enqueued. */ private pendingChanges; /** * State saved at the start of the current pending event (before any changes). * This is captured lazily when the first change is intercepted. * Undefined means it hasn't been captured yet for the current event. */ private attachedStateBeforeNextEvent; constructor(options: UndoManagerOptions<TAttachedState>); /** * Starts tracking changes on the root node. */ private startTracking; /** * Records a change. If this is the first change in an action, schedules a flush. */ private recordChange; /** * Schedules a flush to occur when the current action completes. */ private scheduleFlush; /** * Flushes pending changes as a single UndoEvent. */ private flushPendingChanges; /** * The undo queue. */ get undoQueue(): ReadonlyArray<UndoEvent>; /** * The redo queue. */ get redoQueue(): ReadonlyArray<UndoEvent>; /** * Number of undo steps available. */ get undoLevels(): number; /** * Whether undo is possible. */ get canUndo(): boolean; /** * Number of redo steps available. */ get redoLevels(): number; /** * Whether redo is possible. */ get canRedo(): boolean; /** * Maximum number of undo levels to keep. */ get maxUndoLevels(): number; /** * Maximum number of redo levels to keep. */ get maxRedoLevels(): number; /** * Undoes the last change. * @throws if called while inside a MobX action * @throws if there are no undo events */ undo(): void; /** * Redoes the last undone change. * @throws if called while inside a MobX action * @throws if there are no redo events */ redo(): void; /** * Clears the undo queue. */ clearUndo: () => void; /** * Clears the redo queue. */ clearRedo: () => void; /** * Executes a function without recording changes. */ withoutUndo<T>(fn: () => T): T; /** * Whether undo recording is currently disabled. */ get isUndoRecordingDisabled(): boolean; /** * Disposes the undo manager, stopping change tracking. */ dispose(): void; }