Vize

use-history

Record bounded undo/redo history over the writes of a ref.

Package @vizejs/composable/use-history
Own the source vize lib pull composable:use-history
Runtime exports useHistory
Gzip budget 2560 B

Usage

import { useHistory } from "@vizejs/composable/use-history";

Runtime contract

Utility Category Stability SSR Hydration Cleanup Targets Host globals Uses
useHistory state experimental safe stable reactive-scope web, server, worker, native, desktop, terminal — tryOnScopeDispose

API

useHistory

Record bounded undo/redo history over the writes of a ref. Recording is shallow and identity-based, matching Vue's own change detection: assignments to source.value are recorded (observed with flush: "sync", so every synchronous write counts), writes that are Object.is-equal to the current value are not changes, and in-place mutations of object values are invisible — pair mutable values with UseHistoryOptions.clone and reassign. Undoing and redoing restore values through clone as well, so snapshots never share identity with the live value unless the default identity clone is kept. When a user-provided clone throws, the failed operation leaves history unchanged and the error propagates. Safe during server rendering: no browser globals are read and no timers start. Cleanup rule: when the owning reactive scope stops, recording stops and every retained snapshot is released, so undo/redo return false afterwards; call inside an active scope, or the watcher lives as long as the source.

function useHistory<Value>( source: Ref<Value>, options: UseHistoryOptions<Value> = {}, ): HistoryControls
const text = shallowRef("");
const { undo, redo, batch } = useHistory(text);
text.value = "a";
batch(() => {
  text.value = "ab";
  text.value = "abc";
});
undo(); // text.value === "a" (the batch is one step)
redo(); // text.value === "abc"

Types

UseHistoryOptions

Options for useHistory.

Member Type Description
capacity? number Maximum number of undo entries retained; recording a change beyond it drops the oldest entry. The redo stack is bounded by construction, since redo entries only ever come from undone changes. Must be an integer greater than zero and is fixed at creation.
clone? (value: Value) => Value Clone applied to every value captured into history and to every value restored out of it, isolating snapshots from later in-place mutation.

HistoryControls

Reactive undo/redo controls returned by useHistory.

Member Type Description
canUndo ComputedRef<boolean> Whether HistoryControls.undo currently has an entry to restore.
canRedo ComputedRef<boolean> Whether HistoryControls.redo currently has an entry to restore.
undoCount ComputedRef<number> Number of retained undo entries.
redoCount ComputedRef<number> Number of retained redo entries.
undo () => boolean Restore the newest undo entry and move the current value onto the redo stack. The restoring write is not recorded.
redo () => boolean Restore the newest redo entry and move the current value back onto the undo stack. The restoring write is not recorded.
batch <Result>(run: () => Result) => Result Group every source write inside run into at most one undo entry. The entry restores the value from just before the batch. It is committed only when the final value differs (Object.is) from the starting value, and it is committed even when run throws, so a partially applied batch stays undoable as one step. Nested calls collapse into the outermost batch. The callback's return value is passed through.
clear () => void Drop every undo and redo entry while keeping the current value.