Primitives / State
history: undo and redo over any value
import { history } from 'foldkit-primitives/state'
const EditHistory = history({ name: 'EditHistory', value: Schema.String, capacity: 50 })
const Editor = Bundle.compose({}).pipe(
Bundle.withChild('doc', EditHistory, { args: { initial: '' } }),
)The Model holds { past, present, future, group }. Push records a value and
drops the redo future (an already empty future is kept as it was, so a view
reading it is not redrawn per push); Undo and Redo move one step; GoTo { step }
jumps to any kept value, counted from the oldest (0), so the present is at
past.length; Clear empties both sides and keeps the present. The past holds
at most capacity entries (default 100); a negative or fractional capacity
throws at the factory. The factory attaches the Message union, so a placement
dispatches EditHistory.Message.Push({ value }). canUndo and canRedo read
the edges.
A Push may name a group: consecutive pushes of the same group are one
step, so typing a word, or dragging a brush, undoes as a whole, with no clock.
The steps are also pure functions, History.start, push, undo, redo,
goTo, and clear, for a parent that records an edit in the same transition
that makes it. Two more exist only as functions: History.close(model) ends
the current group, so the same group pushed again is a step of its own, and
History.revert(model, group) takes back the step group is making with
nothing left to redo, which is what a cancelled edit leaves.
examples/foldkit/pixel-art keeps its
grid this way, one group per stroke.
Locale and SelectionSet
Locale keeps one string, read from navigator.language at init with the
configured default as fallback; SetLocale switches it. It does not follow
later changes.
SelectionSet keeps string ids in first-selection order: Select keeps an
existing id's position, Deselect removes, Toggle re-appends, ReplaceAll
replaces (deduplicated), Clear empties. isSelected(model, id) reads
membership. It stores ids only; it neither loads rows nor persists. For a
selection a view's slots must reflect, with aria-selected and Shift ranges,
see Selection in interaction.