Primitives / foldkit-primitives/state
history
function · packages/primitives/src/state/history.ts:159
function history<const Name extends string, Value>(config: {
readonly name: Name
readonly value: Schema.Codec<Value, unknown>
readonly capacity?: number | undefined
}): Bundle.Bundle<
Name,
{ readonly initial: Value },
HistoryModel<Value>,
| {
readonly _tag: 'Push'
readonly value: Value
readonly group?: string | undefined
}
| { readonly _tag: 'Undo' }
| { readonly _tag: 'Redo' }
| { readonly _tag: 'GoTo'; readonly step: number }
| { readonly _tag: 'Clear' },
never,
never,
never,
void,
{},
{}
> & {
Message: MessageUnion<{
readonly Push: {
readonly value: Schema.Codec<Value, unknown, never, never>
readonly group: Schema.optional<Schema.String>
}
readonly Undo: {}
readonly Redo: {}
readonly GoTo: { readonly step: Schema.Number }
readonly Clear: {}
}>
}Undo/redo as a bundle factory: the past, present, and future of one value live in the Model, so every step replays. Pushing records, even an unchanged value; skipping duplicates is the application's policy, not the stack's.
A push may name a group. Consecutive pushes of the same group are one step:
the present moves and nothing new is recorded, so typing a word undoes as a
whole. Grouping needs no clock; the application names what belongs together.
The steps are also pure functions (History.push, undo, redo, goTo, clear),
for a parent that records an edit in the same transition that makes it
rather than dispatching a Message to a placed bundle.