State.DeepHistory restores the recorded descendant configuration of its owning state. Use it when
resuming the right branch is not enough—the nested position inside that branch matters too.
Remember the path all the way down.
Shallow history remembers the active branch. Deep history keeps following that recorded path through descendants until it reaches the former leaf.
1 · Restore one level
Shallow history returns to the branch's beginning.
After leaving Editing.Body, shallow history restores the direct child Editing. Ordinary entry then follows Editing's initial path to Title; the deeper leaf is forgotten.
import {
HistoryDefault,
State,
Statechart,
States,
Transitions,
} from "@motive/motive";
import { Schema } from "effect";
const BeginEditing = Schema.TaggedStruct("BeginEditing", {});
const EditBody = Schema.TaggedStruct("EditBody", {});
const Pause = Schema.TaggedStruct("Pause", {});
const Resume = Schema.TaggedStruct("Resume", {});
export class Editor extends State.Compound<Editor>()("Editor") {
static states = States.make(() => [Workspace, Paused]);
}
class Workspace extends State.Compound<Workspace>()("Workspace") {
static states = States.make(() => [Browsing, Editing, Recent]);
static transitions = Transitions.make(this, ({ on }) => [on(Pause, Paused)]);
}
class Browsing extends State.Atomic<Browsing>()("Browsing") {
static transitions = Transitions.make(this, ({ on }) => [
on(BeginEditing, Editing),
]);
}
class Editing extends State.Compound<Editing>()("Editing") {
static states = States.make(() => [Title, Body]);
}
class Title extends State.Atomic<Title>()("Title") {
static transitions = Transitions.make(this, ({ on }) => [on(EditBody, Body)]);
}
class Body extends State.Atomic<Body>()("Body") {}
class Recent extends State.ShallowHistory()("Recent") {
static readonly default = HistoryDefault.make(this, () => Browsing);
}
class Paused extends State.Atomic<Paused>()("Paused") {
static transitions = Transitions.make(this, ({ on }) => [on(Resume, Recent)]);
}
export const EditorChart = Statechart.make(Editor);
2 · Restore the descendant path
State.DeepHistory returns to the recorded leaf.
Changing only the route kind records the full path beneath Workspace. The same pause and resume now returns directly to Editing.Body instead of restarting Editing at Title.
import {
HistoryDefault,
State,
Statechart,
States,
Transitions,
} from "@motive/motive";
import { Schema } from "effect";
const BeginEditing = Schema.TaggedStruct("BeginEditing", {});
const EditBody = Schema.TaggedStruct("EditBody", {});
const Pause = Schema.TaggedStruct("Pause", {});
const Resume = Schema.TaggedStruct("Resume", {});
export class Editor extends State.Compound<Editor>()("Editor") {
static states = States.make(() => [Workspace, Paused]);
}
class Workspace extends State.Compound<Workspace>()("Workspace") {
static states = States.make(() => [Browsing, Editing, Recent]);
static transitions = Transitions.make(this, ({ on }) => [on(Pause, Paused)]);
}
class Browsing extends State.Atomic<Browsing>()("Browsing") {
static transitions = Transitions.make(this, ({ on }) => [
on(BeginEditing, Editing),
]);
}
class Editing extends State.Compound<Editing>()("Editing") {
static states = States.make(() => [Title, Body]);
}
class Title extends State.Atomic<Title>()("Title") {
static transitions = Transitions.make(this, ({ on }) => [on(EditBody, Body)]);
}
class Body extends State.Atomic<Body>()("Body") {}
class Recent extends State.DeepHistory()("Recent") {
static readonly default = HistoryDefault.make(this, () => Browsing);
}
class Paused extends State.Atomic<Paused>()("Paused") {
static transitions = Transitions.make(this, ({ on }) => [on(Resume, Recent)]);
}
export const EditorChart = Statechart.make(Editor);
Shallow history stops at the direct child
The first frame uses State.ShallowHistory. Leaving Workspace from Editing.Body records
Editing, the direct child that was active. When Recent is targeted, the chart restores Editing
and follows its ordinary initial path to Title.
The remembered branch is correct, but the nested leaf is not. This is the intended boundary of shallow history, not a partial failure of deep restoration.
Deep history restores the descendant configuration
The second frame changes only Recent from State.ShallowHistory to State.DeepHistory. The same
exit now records the active path through Workspace: Editing.Body.
On resume, Recent routes directly through the recorded descendants. Editing becomes active with
Body; its initial child Title is not consulted because a deeper recorded path already determines
the entry.
As with shallow history, Recent is never active. It is an authored entry route through recorded
geometry, not a phase that sits between Paused and Body.
History belongs to its containing state
Deep describes the depth beneath Workspace, not the entire chart. Exiting Workspace records its
descendant configuration and eligible facets. States outside Workspace, including Paused, do
not become part of that record.
History is also not durable storage by itself. The selected engine determines whether the snapshot and its history records survive process or machine failure; the chart determines what geometry a history route means when that record exists.
Test the depth
- Add a child beneath
Body, enter it, and confirm that deep history restores the new leaf. - Change
Recentback toState.ShallowHistoryand identify the first initial path that replaces recorded geometry. - Add another compound branch beneath
Workspaceand verify that history restores whichever direct branch and descendants were active at exit.