import { Signal, computed, signal } from '@angular/core'; export interface History { readonly canUndo: Signal; readonly canRedo: Signal; /** Push a pre-edit snapshot onto the undo stack and drop the redo stack. */ record(snapshot: T): void; /** Undo: pop the last recorded snapshot and return it (moving `current` onto the redo stack); returns undefined and changes nothing when there's nothing to undo. */ undo(current: T): T | undefined; /** Redo: mirror of undo. */ redo(current: T): T | undefined; clear(): void; } /** * Generic undo/redo history over an immutable "document" value `T`. Elm-store editors * restore a returned snapshot by re-dispatching a `Seed`-style Msg — this helper only * shuffles references, it never mutates them, so the caller must hold copy-on-write state * (every edit produces a fresh value). Both stacks are capped so a long session can't grow * unbounded. Extracted from BriefStore's undo/redo; reused by the stamdata * editor. */ export function createHistory(cap = 50): History { const past = signal([]); const future = signal([]); return { canUndo: computed(() => past().length > 0), canRedo: computed(() => future().length > 0), record(snapshot) { past.update((p) => [...p, snapshot].slice(-cap)); future.set([]); }, undo(current) { const p = past(); if (p.length === 0) return undefined; past.set(p.slice(0, -1)); future.update((f) => [...f, current].slice(-cap)); return p[p.length - 1]; }, redo(current) { const f = future(); if (f.length === 0) return undefined; future.set(f.slice(0, -1)); past.update((p) => [...p, current].slice(-cap)); return f[f.length - 1]; }, clear() { past.set([]); future.set([]); }, }; }