Use when: users need to reverse discrete actions — a text editor, a canvas,
a form with destructive bulk edits.
Don’t use when: the state is large and serialization is expensive; consider
structural sharing or operation-log approaches instead.
Keep a stack of past states and a stack of future states alongside the current
one. Each mutation saves the previous state to past; undo pops from past and
pushes to future; redo reverses that.
Cubit<S> is a StateContainer<S> with emit / patch exposed as
public mutation surface. Today it adds nothing structurally beyond
StateContainer — both are inherited from the underlying
StructuralContainer<S>. Kept as a real class (not a type alias) because
downstream code does instance instanceof Cubit checks (see A2 audit).
The class body is intentionally empty: a no-op emit override would
still go through applyState, and patch is inherited from
StructuralContainer (path-diffed, microtask-flushed). If a caller
needs the old "skip if no real change" patch semantics, they can wrap
patch themselves or call emit after a manual equality check.
Cubit<
interface EditorState
EditorState,
interface Note
Note> {
// Hard cap prevents unbounded memory growth.
privatestaticreadonly
EditorCubit.MAX_HISTORY: 50
MAX_HISTORY=50;
// One instance per note title — args both seed and key the instance.
static
EditorCubit.key: (initial:Note)=> string
key=(
initial: Note
initial:
interface Note
Note)=>
initial: Note
initial.
Note.title: string
title;
constructor() {
super({
EditorState.note: Note
note: {
Note.title: string
title: '',
Note.body: string
body: '' },
EditorState.past: Note[]
past: [],
EditorState.future: Note[]
future: [] });
}
protected
EditorCubit.init(initial: Note): void
Called once after construction with the args passed at acquire time, before the first
state snapshot is read by any consumer. Override to seed args-derived state (via
this.emit(...)) or kick off loads.
Returns a copy of a section of an array.
For both start and end, a negative index can be used to indicate an offset from the end of the array.
For example, -2 refers to the second to last element of the array.
@param ― start The beginning index of the specified portion of the array.
If start is undefined, then the slice begins at index 0.
@param ― end The end index of the specified portion of the array. This is exclusive of the element at the index 'end'.
If end is undefined, then the slice extends to the end of the array.
Returns a copy of a section of an array.
For both start and end, a negative index can be used to indicate an offset from the end of the array.
For example, -2 refers to the second to last element of the array.
@param ― start The beginning index of the specified portion of the array.
If start is undefined, then the slice begins at index 0.
@param ― end The end index of the specified portion of the array. This is exclusive of the element at the index 'end'.
If end is undefined, then the slice extends to the end of the array.
Returns a copy of a section of an array.
For both start and end, a negative index can be used to indicate an offset from the end of the array.
For example, -2 refers to the second to last element of the array.
@param ― start The beginning index of the specified portion of the array.
If start is undefined, then the slice begins at index 0.
@param ― end The end index of the specified portion of the array. This is exclusive of the element at the index 'end'.
If end is undefined, then the slice extends to the end of the array.