Arm a tool in a pointer-mode (the rail slot reflects it). Idempotent.
Drop every subscriber (called on UI teardown).
The armed tool for a pointer-mode ('pointer'/null = default).
The tool a mode rests on when nothing special is armed.
A copy of the current state (safe to read; mutations don't leak back).
Whether a mode is currently registered (the four built-ins always are).
Whether a flyout is open (i.e. its mode is the active one).
Whether a pointer-mode's tool panel is currently expanded.
Whether a mode owns the tool panel. Unknown modes are not pointer-modes.
Add a mode's state to the store. Called by the rail-mode registry; the four built-ins are already present. Re-registering an id overwrites its record but keeps whatever tool/panel state it already had.
Expand / collapse a pointer-mode's tool panel. Idempotent.
Subscribe to state changes. Returns an unsubscribe fn (pass to UIComponent.track).
Open a flyout mode, or close it back to the last pointer-mode.
Toggle a pointer-mode's tool panel open/closed.
Drop a mode's state. The caller is responsible for moving off it first — the store will not decide what to activate instead.
A tiny observable holding the mode-rail state. The rail, contextual tool panel and the settings flyouts subscribe to it; clicks / keybindings dispatch to it. Setters are idempotent — they only notify when the value actually changes — and every notification carries a fresh snapshot so a listener can't mutate the store's internal state.
The four built-in modes are always present. Modes registered through
addRailModeare added with registerMode and hold state exactly like a built-in does.subscribefires on changes only; render initial state from getState first, then subscribe for updates.