106 lines
3.5 KiB
Markdown
106 lines
3.5 KiB
Markdown
# Routeless origins architecture
|
||
|
||
The v2 experiment lives in `packages/core-v2` and its physical test application
|
||
lives in `apps/origins-demo`.
|
||
|
||
## State model
|
||
|
||
The scene contains:
|
||
|
||
- stable, flat Vue component nodes;
|
||
- linked mounted-instance history entries;
|
||
- temporary directed operation edges.
|
||
|
||
It does not contain an active route or current view.
|
||
|
||
For overlapping operations:
|
||
|
||
```text
|
||
Nodes: X, Y, Z
|
||
Edges: X → Y
|
||
Y → Z
|
||
```
|
||
|
||
Each edge records its own progress, velocity, outcome, choreography, and
|
||
source/target keys.
|
||
|
||
## Coordinate composition
|
||
|
||
Suppose A is X→Y and B is Y→Z:
|
||
|
||
```text
|
||
visual(X) = A.source
|
||
visual(Y) = A.target × B.source
|
||
visual(Z) = A.target × B.target
|
||
```
|
||
|
||
An optional frame effect is included on both sides of an edge:
|
||
|
||
```text
|
||
visual(Y) = A.frame × A.target × B.frame × B.source
|
||
visual(Z) = A.frame × A.target × B.frame × B.target
|
||
```
|
||
|
||
The implementation emits these operations as one combined transform on each
|
||
flat host. This has the visual semantics of nested coordinate frames without
|
||
reparenting Vue component VNodes.
|
||
|
||
## Completion
|
||
|
||
Committing a forward X→Y:
|
||
|
||
1. Keeps X mounted but marks it parked, inert, and visually hidden.
|
||
2. Places Y in X's former visual graph position.
|
||
3. Removes the X→Y edge.
|
||
4. Leaves any Y→Z edge and all mounted descendants intact.
|
||
|
||
Committing Y→Z before X→Y is also valid. Z replaces Y as the target of the
|
||
still-running X edge, after which X→Y effectively becomes X→Z. The unit suite
|
||
covers both completion orders.
|
||
|
||
Committing back from Y to X reveals the existing X node and removes Y. It does
|
||
not construct X again from its recipe. Cancelling a forward edge restores its
|
||
source and removes the newly created target branch; cancelling a back edge
|
||
re-parks its retained target.
|
||
|
||
## Interaction
|
||
|
||
Gesture recognition is declared within each component through
|
||
`OriginGesture` or `useOriginGesture()`. The injected scene-node key determines
|
||
the origin. Recognition never asks a coordinator which view is active.
|
||
|
||
The immutable `gesture` builder separates optional pointer-down policy
|
||
(`.from`), movement recognition (`.to`), release policy (`.complete`),
|
||
navigation intent (`.navigate`), and visual choreography (`.animate`). A chain
|
||
that begins at `.to` is valid and admits pointer-down anywhere on its host.
|
||
|
||
At pointer release, the operation decides synchronously whether it will commit
|
||
or cancel. Its spring may continue afterward. A retained target can therefore
|
||
originate another routine while the preceding spring is still visible.
|
||
|
||
### Nested scenes
|
||
|
||
An `OriginScene` may be rendered inside a view owned by another scene. The
|
||
nearest injected node scope makes carousel or deck gestures operate on the
|
||
nested scene, with local measurements and retained history.
|
||
|
||
Gesture ownership between nested scenes is currently selected at pointer-down.
|
||
An eligible child stops propagation even if its later navigation factory
|
||
declines. Parent fallback therefore requires the child to reserve a
|
||
non-matching `.from` region; automatic delayed arbitration remains future
|
||
gesture-arena work.
|
||
|
||
## Retained history
|
||
|
||
Each pushed node stores the key of its mounted previous entry. The chain is
|
||
local to that origin context rather than a URL:
|
||
|
||
```text
|
||
X (parked) ← Y (parked) ← Z (visible)
|
||
```
|
||
|
||
Back targets the previous node key directly. A node is unmounted only when a
|
||
committed back operation pops it, a forward operation is cancelled, or the
|
||
whole scene is destroyed. Because the same DOM survives parking, nested scroll
|
||
positions and component-local state survive without `<KeepAlive>`.
|