778 lines
27 KiB
Markdown
778 lines
27 KiB
Markdown
# Core v2 API reference
|
|
|
|
`@native-vue-router/core-v2` is a routeless Vue scene compositor. A mounted
|
|
component can create another component, animate both through a local operation
|
|
frame, and retain either side when the operation resolves.
|
|
|
|
This document describes the experimental `0.1.0-experimental.0` API.
|
|
|
|
## Contents
|
|
|
|
- [Gesture start recognition](#gesture-start-recognition)
|
|
- [Minimum setup](#minimum-setup)
|
|
- [Components](#components)
|
|
- [Nested scenes](#nested-scenes)
|
|
- [Scene and view functions](#scene-and-view-functions)
|
|
- [Actions and history](#actions-and-history)
|
|
- [Gestures](#gestures)
|
|
- [Choreographies and effects](#choreographies-and-effects)
|
|
- [Node-scoped controls](#node-scoped-controls)
|
|
- [Scene diagnostics and manual operations](#scene-diagnostics-and-manual-operations)
|
|
- [Type reference](#type-reference)
|
|
- [Errors and constraints](#errors-and-constraints)
|
|
|
|
## Gesture start recognition
|
|
|
|
The builder separates where a gesture begins from the direction it moves:
|
|
|
|
```ts
|
|
const edgeBack = gesture.from
|
|
.left("clamp(24px, 7vw, 48px)")
|
|
.to.right()
|
|
.navigate((context) => (context.canGoBack ? back() : null))
|
|
.animate(slideRight);
|
|
```
|
|
|
|
Edges are measured from the **gesture host element**, not unconditionally from
|
|
the browser viewport. Supported start rules are:
|
|
|
|
```ts
|
|
gesture.from.left(distance);
|
|
gesture.from.right(distance);
|
|
gesture.from.top(distance);
|
|
gesture.from.bottom(distance);
|
|
gesture.from.anywhere();
|
|
gesture.from.when(predicate);
|
|
```
|
|
|
|
`distance` accepts a number in CSS pixels or a CSS length string, including
|
|
percentages, `calc()`, and `clamp()`. It is resolved against the current host
|
|
size at pointer-down.
|
|
|
|
`.from` is optional. A chain beginning at `.to` admits pointer-down anywhere:
|
|
|
|
```ts
|
|
gesture.to.right();
|
|
```
|
|
|
|
This is semantically equivalent to:
|
|
|
|
```ts
|
|
gesture.from.anywhere().to.right();
|
|
```
|
|
|
|
It does not capture on the first positive pixel. The recognizer waits until
|
|
directed movement crosses the intent threshold and dominates the cross-axis.
|
|
|
|
Custom shapes, safe-area rules, and exclusion zones belong in `.from.when()`:
|
|
|
|
```ts
|
|
const dropDialog = gesture.from
|
|
.when(({ point, bounds, event }) => {
|
|
const rail = Math.max(36, bounds.width * 0.08);
|
|
const outsideExcludedBand =
|
|
event.clientY < bounds.top + bounds.height * 0.35 ||
|
|
event.clientY > bounds.top + bounds.height * 0.65;
|
|
return point.localX <= rail && outsideExcludedBand;
|
|
})
|
|
.to.down()
|
|
.navigate(() => above(originView(DialogView)))
|
|
.animate(dropAnimation);
|
|
```
|
|
|
|
Interactive form controls are ignored automatically. Add
|
|
`data-origin-gesture="ignore"` to any other element or ancestor that should not
|
|
begin a gesture.
|
|
|
|
## Minimum setup
|
|
|
|
Import the required compositor stylesheet once:
|
|
|
|
```ts
|
|
import "@native-vue-router/core-v2/style.css";
|
|
```
|
|
|
|
Create a scene:
|
|
|
|
```ts
|
|
import { createOriginScene, originView } from "@native-vue-router/core-v2";
|
|
import HomeView from "./HomeView.vue";
|
|
|
|
export const scene = createOriginScene({
|
|
initial: originView(HomeView, undefined, {
|
|
key: "home",
|
|
name: "Home",
|
|
}),
|
|
});
|
|
```
|
|
|
|
Render it:
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
import { OriginScene } from "@native-vue-router/core-v2";
|
|
import { scene } from "./scene";
|
|
</script>
|
|
|
|
<template>
|
|
<OriginScene :scene="scene" />
|
|
</template>
|
|
```
|
|
|
|
`OriginScene` must have a non-zero width and height through its parent layout.
|
|
|
|
## Components
|
|
|
|
### `OriginScene`
|
|
|
|
Renders every currently mounted scene node as a stable, absolutely positioned
|
|
sibling.
|
|
|
|
| Prop | Type | Required | Description |
|
|
| ------- | ------------- | -------- | -------------------------------------- |
|
|
| `scene` | `OriginScene` | yes | Scene created by `createOriginScene()` |
|
|
|
|
The component provides node ownership to descendants, registers host elements
|
|
for measurement, and applies the scene's composited styles. Application views
|
|
must be rendered through this component before calling `useOrigin()` or
|
|
`useOriginGesture()`.
|
|
|
|
### `OriginGesture`
|
|
|
|
Convenience component that renders one HTML element and binds one gesture
|
|
recognizer to it.
|
|
|
|
| Prop | Type | Default | Description |
|
|
| --------- | ------------------------- | ------- | ---------------------------------- |
|
|
| `as` | `string` | `"div"` | HTML tag used for the gesture host |
|
|
| `gesture` | `OriginGestureDefinition` | — | Preferred builder definition |
|
|
|
|
Attributes, classes, and listeners not consumed as props are forwarded to the
|
|
rendered host.
|
|
|
|
```vue
|
|
<OriginGesture as="main" class="profile" :gesture="openDetailsGesture">
|
|
...
|
|
</OriginGesture>
|
|
```
|
|
|
|
For compatibility, the component also accepts the legacy mutually exclusive
|
|
set of `direction`, `edge`, `threshold`, and `action` props.
|
|
|
|
Use `useOriginGesture()` instead when an extra wrapper is undesirable.
|
|
|
|
### `OriginGestureSurface`
|
|
|
|
Policy-neutral host for multiple completed builder definitions:
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
const gestures = [forwardGesture, backGesture] as const;
|
|
</script>
|
|
|
|
<template>
|
|
<OriginGestureSurface as="main" :gestures="gestures">
|
|
...
|
|
</OriginGestureSurface>
|
|
</template>
|
|
```
|
|
|
|
| Prop | Type | Default | Description |
|
|
| ---------- | ------------------------------------ | -------- | ------------------------------ |
|
|
| `as` | `string` | `"div"` | Shared native gesture host |
|
|
| `gestures` | `readonly OriginGestureDefinition[]` | required | Fully defined page-owned rules |
|
|
|
|
The component adds no recognition or navigation policy. It installs each
|
|
definition with `useOriginGesture()`, forwards every pointer event to every
|
|
binding, and derives the least-permissive shared `touch-action`:
|
|
|
|
- horizontal only: `pan-y`;
|
|
- vertical only: `pan-x`;
|
|
- both axes: `none`.
|
|
|
|
Definitions should be immutable and stable for the lifetime of the rendered
|
|
surface. The owning page remains the visible declaration point for every
|
|
`.from`, `.to`, `.complete`, `.navigate`, and `.animate` choice.
|
|
|
|
## Nested scenes
|
|
|
|
`OriginScene` is a reusable compositor, not an application-only singleton. A
|
|
component may render another scene inside its own layout:
|
|
|
|
```vue
|
|
<section class="carousel">
|
|
<OriginScene :scene="carouselScene" />
|
|
</section>
|
|
```
|
|
|
|
The child scene gets independent mounted nodes, retained history, measurements,
|
|
operations, and clipping. `useOrigin()` and `useOriginGesture()` resolve the
|
|
nearest scene-node provider, so declarations inside a carousel slide operate
|
|
on carousel components rather than the outer page.
|
|
|
|
Parent/child gesture arbitration is currently pointer-down based. An eligible
|
|
child recognizer stops propagation immediately. If its later `.navigate()`
|
|
factory returns `null`, that same pointer sequence is not offered to the
|
|
parent. Cooperative nested components should reserve a start region with
|
|
`.from.when()` or `.from.left()` that allows the parent handler to receive
|
|
pointer-down.
|
|
|
|
The nested-scenes demo contains both this cooperative policy and an intentional
|
|
greedy-child conflict. A future gesture arena could delay ownership until
|
|
direction and navigation availability are known.
|
|
|
|
## Scene and view functions
|
|
|
|
### `originView(component, props?, options?)`
|
|
|
|
Creates a lightweight recipe for mounting a Vue component.
|
|
|
|
```ts
|
|
const profile = originView(
|
|
ProfileView,
|
|
{ userId: "42" },
|
|
{ key: "profile-42", name: "Profile" },
|
|
);
|
|
```
|
|
|
|
The recipe is not itself a mounted instance. A forward action creates an
|
|
instance from it, then retains that exact instance while its entry remains in
|
|
history. Back does not call the recipe again. Component definitions are marked
|
|
raw so Vue does not proxy them inside reactive scene structures.
|
|
|
|
`OriginViewOptions`:
|
|
|
|
| Field | Type | Description |
|
|
| ------ | -------- | --------------------------------------------- |
|
|
| `key` | `string` | Recipe identity and generated node-key prefix |
|
|
| `name` | `string` | Human-readable diagnostic label |
|
|
|
|
When no key is supplied, one is generated from the component/name and a
|
|
sequence number.
|
|
|
|
### `createOriginScene(options)`
|
|
|
|
Creates one independent scene graph, history context, and compositor.
|
|
|
|
```ts
|
|
const scene = createOriginScene({
|
|
initial: originView(HomeView),
|
|
});
|
|
```
|
|
|
|
`options.initial` accepts one `OriginView` or an array of independent root
|
|
views. Scenes do not share nodes, history, operation IDs, or measurements.
|
|
|
|
## Actions and history
|
|
|
|
### `forward(target, choreography?, options?)`
|
|
|
|
With choreography, creates a complete retained-history push action:
|
|
|
|
```ts
|
|
const openProfile = () =>
|
|
forward(originView(ProfileView, { userId: "42" }), slideLeft);
|
|
```
|
|
|
|
Without choreography, it creates an `OriginNavigationIntent` for a gesture
|
|
builder:
|
|
|
|
```ts
|
|
.navigate(() => forward(originView(ProfileView, { userId: "42" })))
|
|
```
|
|
|
|
When forward commits, the origin remains mounted but becomes parked. Its DOM,
|
|
component-local state, and nested scroll positions remain intact.
|
|
|
|
`OriginNavigationActionOptions.placement` defaults to `"above"`.
|
|
|
|
### `back(choreography?, options?)`
|
|
|
|
Creates a retained-history pop action:
|
|
|
|
```ts
|
|
const goBack = (context: OriginContext) =>
|
|
context.canGoBack ? back(slideRight) : null;
|
|
```
|
|
|
|
Back has no target recipe. When it begins, the scene resolves the origin's
|
|
`previousNodeKey` and reveals that exact mounted instance. A committed back
|
|
unmounts only the current entry. A cancelled back hides the previous entry
|
|
again and leaves the current entry active.
|
|
|
|
`back()` without choreography returns an animation-free navigation intent for
|
|
`.navigate()`. `back(slideRight)` returns a complete programmatic action.
|
|
|
|
`OriginNavigationActionOptions.placement` defaults to `"under"`.
|
|
|
|
### `replace(target, choreography?, options?)`
|
|
|
|
Creates a new target while removing the current history entry:
|
|
|
|
```ts
|
|
const confirmOrder = () =>
|
|
replace(
|
|
originView(OrderConfirmationView, { orderId: "NVO-2048" }),
|
|
slideLeft,
|
|
);
|
|
```
|
|
|
|
The target inherits the origin's `previousNodeKey`, so a later back skips the
|
|
replaced entry. The origin remains mounted while the operation is interactive
|
|
or settling and is unmounted only after commit. Cancelling removes the proposed
|
|
target and restores the origin without changing history.
|
|
|
|
Without choreography, `replace(target)` creates an intent suitable for a
|
|
gesture builder:
|
|
|
|
```ts
|
|
.navigate(() => replace(originView(OrderConfirmationView)))
|
|
.animate(slideLeft)
|
|
```
|
|
|
|
`OriginNavigationActionOptions.placement` defaults to `"above"`.
|
|
|
|
### `originAction(target, choreography, options?)`
|
|
|
|
Constructs a complete low-level `OriginAction`. Prefer `forward()`, `replace()`,
|
|
and `back()` when expressing retained navigation.
|
|
|
|
```ts
|
|
const action = originAction(profile, slideLeft, {
|
|
placement: "above",
|
|
history: "push",
|
|
});
|
|
```
|
|
|
|
`OriginActionOptions`:
|
|
|
|
| Field | Type | Default | Description |
|
|
| ----------- | -------------------- | --------- | ---------------------------- |
|
|
| `placement` | `"above" \| "under"` | `"above"` | Target stacking relationship |
|
|
| `history` | `OriginHistoryMode` | `"push"` | Target history mutation |
|
|
|
|
### `above(target, choreography?, options?)`
|
|
|
|
Shorthand for `originAction()` with `placement: "above"`.
|
|
|
|
```ts
|
|
const openProfile = () => above(originView(ProfileView), slideLeft);
|
|
```
|
|
|
|
Placement controls stacking only. It does not imply a movement direction.
|
|
Omitting choreography returns a navigation intent for a gesture builder.
|
|
|
|
### `under(target, choreography?, options?)`
|
|
|
|
Shorthand for `originAction()` with `placement: "under"`.
|
|
|
|
```ts
|
|
const goBack = (context: OriginContext) =>
|
|
context.previous ? back(slideRight) : null;
|
|
```
|
|
|
|
`under()` does not automatically mean history back. It remains available for
|
|
custom stacking actions; `back()` is the clearer retained-history primitive.
|
|
Omitting choreography returns a navigation intent for a gesture builder.
|
|
|
|
### History modes
|
|
|
|
History is a linked chain of mounted scene nodes.
|
|
|
|
| Mode | Commit behavior |
|
|
| ----------- | -------------------------------------------------------------- |
|
|
| `"push"` | Park and retain the origin; activate the new target |
|
|
| `"replace"` | Create a new target, inherit prior history, unmount the origin |
|
|
| `"back"` | Reuse the retained previous target; pop and unmount the origin |
|
|
|
|
Parked entries are `inert`, `aria-hidden`, invisible, and excluded from pointer
|
|
input. They remain mounted until back pops them or the scene is destroyed.
|
|
|
|
## Gestures
|
|
|
|
### `gesture`
|
|
|
|
Immutable fluent builder for component-owned gesture policy:
|
|
|
|
```ts
|
|
const swipeBack = gesture.from
|
|
.left(32)
|
|
.to.right({ threshold: 10 })
|
|
.complete(({ progress, velocity }) => progress >= 0.4 || velocity >= 0.9)
|
|
.navigate((context) => (context.canGoBack ? back() : null))
|
|
.animate(slideRight);
|
|
```
|
|
|
|
The stages have distinct responsibilities:
|
|
|
|
| Stage | Responsibility |
|
|
| ---------------------- | ---------------------------------------------------------- |
|
|
| `.from.*` | Optional pointer-down eligibility |
|
|
| `.to.*` | Required movement direction and intent-recognition options |
|
|
| `.complete(predicate)` | Optional release commit/cancel decision |
|
|
| `.navigate(factory)` | Required target and retained-history intent |
|
|
| `.animate(routine)` | Required source/target/frame choreography |
|
|
|
|
The builder is persistent and immutable. Reusing an earlier stage cannot
|
|
change a definition already produced from it.
|
|
|
|
`.to.left()`, `.to.right()`, `.to.up()`, and `.to.down()` accept optional
|
|
`OriginGestureDirectionOptions`:
|
|
|
|
| Field | Default | Description |
|
|
| --------------- | ------- | ------------------------------------------------- |
|
|
| `threshold` | `8` | Directed CSS pixels required before capture |
|
|
| `axisDominance` | `1.15` | Directed/cross-axis ratio required before capture |
|
|
|
|
If `.complete()` is omitted, the choreography's `commitThreshold` and
|
|
`commitVelocity` decide release normally.
|
|
|
|
The completion context contains the origin, direction, normalized progress and
|
|
velocity, directed pixel distance, cross-axis distance, duration, pointer-up
|
|
event, host, bounds, and start/current points. Completion predicates are
|
|
synchronous because they select operation intent at release.
|
|
|
|
### `useOriginGesture(definition)`
|
|
|
|
Creates one primary-pointer, single-axis recognizer owned by the component that
|
|
calls it.
|
|
|
|
```ts
|
|
const open = useOriginGesture(
|
|
gesture.to
|
|
.left({ threshold: 10 })
|
|
.navigate(() => forward(originView(DetailsView)))
|
|
.animate(slideLeft),
|
|
);
|
|
```
|
|
|
|
The return value contains:
|
|
|
|
```ts
|
|
interface OriginGestureBinding {
|
|
readonly style: Readonly<CSSProperties>;
|
|
readonly onPointerdown: (event: PointerEvent) => void;
|
|
readonly onPointermove: (event: PointerEvent) => void;
|
|
readonly onPointerup: (event: PointerEvent) => void;
|
|
readonly onPointercancel: () => void;
|
|
}
|
|
```
|
|
|
|
Apply all handlers to the same element. The returned style sets dimensions and
|
|
`touch-action` so native scrolling remains available on the cross-axis.
|
|
|
|
Recognition requires:
|
|
|
|
1. A primary, left-button pointer satisfies the optional start policy.
|
|
2. The target is not an ignored interactive element.
|
|
3. Directed movement reaches `threshold`.
|
|
4. Directed movement exceeds cross-axis movement by `axisDominance`.
|
|
5. The navigation factory returns an intent.
|
|
|
|
Progress is directed distance divided by host width or height. Release velocity
|
|
is normalized by the same dimension.
|
|
|
|
An asynchronous navigation factory is supported. If it resolves after the
|
|
pointer was released or cancelled, the stale result is discarded.
|
|
|
|
The legacy `OriginGestureOptions` object remains accepted. Its `edge` is a
|
|
number inferred from the side opposite `direction`, matching the previous API.
|
|
|
|
## Choreographies and effects
|
|
|
|
### `defineOriginChoreography(choreography)`
|
|
|
|
Type-safe identity helper for declaring custom visual routines.
|
|
|
|
```ts
|
|
const scaleIn = defineOriginChoreography({
|
|
name: "scale-in",
|
|
commitThreshold: 0.4,
|
|
commitVelocity: 0.8,
|
|
effects: ({ progress, viewport }) => ({
|
|
source: {
|
|
transform: `scale(${1 - progress * 0.08})`,
|
|
opacity: 1 - progress * 0.3,
|
|
},
|
|
target: {
|
|
transform: `translateY(${(1 - progress) * viewport.height}px)`,
|
|
},
|
|
}),
|
|
});
|
|
```
|
|
|
|
The function returns the same object. Its value is type checking and a clear
|
|
construction point.
|
|
|
|
Set `persistAtRest: true` when progress `1` should remain as a connected visual
|
|
relationship after a committed push:
|
|
|
|
```ts
|
|
const openPartialDrawer = defineOriginChoreography({
|
|
name: "partial-drawer-open",
|
|
persistAtRest: true,
|
|
effects: ({ progress }) => ({
|
|
source: {
|
|
transform: `translateX(${progress * 66.6667}%)`,
|
|
},
|
|
target: {
|
|
transform: `translateX(${(progress - 1) * 66.6667}%)`,
|
|
},
|
|
}),
|
|
});
|
|
```
|
|
|
|
This leaves the retained source mounted, visible, and inert instead of parking
|
|
it. The target remains the active history entry. Beginning back suspends the
|
|
resting relationship so a reciprocal close choreography can take over;
|
|
cancelling back restores it exactly.
|
|
|
|
Connected resting effects are supported only by retained-history push actions.
|
|
They are designed for partial drawers, inspectors, and other presentations
|
|
where both mounted views remain visible after commit. They do not appear in
|
|
`scene.operations`, which reports live interactive/settling edges only.
|
|
|
|
`effects()` may return:
|
|
|
|
| Effect | Applied to |
|
|
| -------- | ---------------------------------------------------------- |
|
|
| `frame` | Source, target, and descendants on both sides of this edge |
|
|
| `source` | Component that originated this operation |
|
|
| `target` | Component created by this operation and its descendants |
|
|
|
|
Transforms are concatenated from inherited frames to local frames. Opacity is
|
|
multiplied. Properties inside `style` use local-last precedence, except
|
|
`transform` and numeric `opacity`, which are also composed.
|
|
|
|
Choreography callbacks should be deterministic and free of side effects. They
|
|
can run repeatedly during rendering and animation.
|
|
|
|
### Commit thresholds
|
|
|
|
When `finish()` does not explicitly override the decision, a target commits
|
|
when either:
|
|
|
|
- `progress >= commitThreshold`, default `0.36`; or
|
|
- `progress >= 0.06` and `velocity >= commitVelocity`, default `0.9`.
|
|
|
|
The operation's intent becomes final before its spring settles.
|
|
|
|
### Included presets
|
|
|
|
| Export | Behavior |
|
|
| ------------ | ------------------------------------------------------------- |
|
|
| `slideLeft` | Target enters from the right above a slightly receding source |
|
|
| `slideRight` | Source exits right and reveals a target underneath |
|
|
| `fade` | Source fades out as target fades in |
|
|
|
|
These are ordinary `OriginChoreography` objects and can be replaced entirely.
|
|
|
|
### `normalizedEffect(effect, fallbackLayer?)`
|
|
|
|
Internal compositor helper exposed for custom diagnostics or compositors. It
|
|
returns a defined effect and adds `fallbackLayer` to the effect's own layer.
|
|
Applications normally return plain effects and let the scene normalize them.
|
|
|
|
## Node-scoped controls
|
|
|
|
### `useOrigin()`
|
|
|
|
Returns controls scoped to the scene node containing the calling component.
|
|
|
|
```ts
|
|
const origin = useOrigin();
|
|
|
|
await origin.perform(forward(originView(SettingsView), fade));
|
|
```
|
|
|
|
Return value:
|
|
|
|
| Field | Description |
|
|
| ----------------- | --------------------------------------------------- |
|
|
| `nodeKey` | Unique key of this mounted node |
|
|
| `scene` | Containing `OriginScene` |
|
|
| `context` | Reactive node-local `OriginContext` |
|
|
| `view` | Reactive shorthand for the current recipe |
|
|
| `previous` | Recipe belonging to the retained previous instance |
|
|
| `canGoBack` | Whether a retained previous instance exists |
|
|
| `begin(action)` | Create a target and return manual operation control |
|
|
| `perform(action)` | Create and programmatically commit a target |
|
|
|
|
The composable throws when called outside a view mounted by `OriginScene`.
|
|
There is no global `activeView`; the injected node containing the event is the
|
|
origin.
|
|
|
|
## Scene diagnostics and manual operations
|
|
|
|
### `OriginScene` fields
|
|
|
|
| Field | Type | Description |
|
|
| ------------ | ----------------------------------------- | ------------------------------------- |
|
|
| `nodes` | `ComputedRef<readonly OriginSceneNode[]>` | Currently mounted Vue component nodes |
|
|
| `operations` | `ComputedRef<readonly OriginOperation[]>` | Live operation edges |
|
|
| `roots` | `ShallowRef<readonly string[]>` | Visible operation-graph roots |
|
|
|
|
These fields are suitable for inspectors and diagnostics. Do not mutate their
|
|
contents.
|
|
|
|
### `scene.contextFor(nodeKey)`
|
|
|
|
Returns the `OriginContext` for a mounted node. Throws if the key no longer
|
|
exists.
|
|
|
|
### `scene.begin(originKey, action)`
|
|
|
|
For forward or replace, mounts a new target and waits one Vue tick for
|
|
measurement. For back, reveals and measures the retained previous node. It
|
|
then returns an `OriginOperationHandle`.
|
|
|
|
```ts
|
|
const handle = await scene.begin(nodeKey, action);
|
|
handle.update(0.25, 0.4);
|
|
const committed = await handle.finish();
|
|
```
|
|
|
|
Only one outgoing operation may exist for a given origin. Its created target
|
|
can immediately begin its own outgoing operation, enabling X → Y → Z chains.
|
|
|
|
### `OriginOperationHandle`
|
|
|
|
| Member | Description |
|
|
| ----------------------------- | --------------------------------------------------- |
|
|
| `id` | Unique operation ID |
|
|
| `originKey` | Source node key |
|
|
| `targetKey` | Created or retained target node key |
|
|
| `update(progress, velocity?)` | Update normalized interactive state |
|
|
| `finish(options?)` | Decide, settle, and return whether target committed |
|
|
| `cancel(options?)` | Force cancellation and remove the target branch |
|
|
|
|
`OriginFinishOptions`:
|
|
|
|
| Field | Default | Description |
|
|
| --------- | ------------------ | ---------------------------- |
|
|
| `commit` | threshold decision | Force commit or cancellation |
|
|
| `animate` | `true` | Run the settling spring |
|
|
|
|
### `scene.perform(originKey, action)`
|
|
|
|
Equivalent to beginning an operation and immediately finishing it with
|
|
`commit: true`. The target still uses the settling spring unless reduced motion
|
|
is active.
|
|
|
|
### Renderer integration methods
|
|
|
|
`registerElement()`, `registerContainer()`, `styleForNode()`, and
|
|
`isNodeInteractive()` are public at the TypeScript boundary because the Vue
|
|
renderer components consume them. They are internal integration APIs and may
|
|
change during the experimental series.
|
|
|
|
## Type reference
|
|
|
|
### `OriginView<Props>`
|
|
|
|
A component recipe containing `component`, optional `props`, optional `key`,
|
|
and optional diagnostic `name`.
|
|
|
|
### `OriginAction`
|
|
|
|
A choreography, placement, history mode, and—except for back—target recipe.
|
|
|
|
### `OriginNavigationIntent`
|
|
|
|
An animation-free target, placement, and history mutation returned by
|
|
`forward()`, `replace()`, `back()`, `above()`, or `under()` when choreography
|
|
is omitted. Gesture `.animate()` combines it with choreography to create the
|
|
internal action.
|
|
|
|
### Gesture definition types
|
|
|
|
- `OriginGestureDefinition`: immutable executable result passed to
|
|
`useOriginGesture()` or the `OriginGesture` component.
|
|
- `OriginGestureStart`: anywhere, edge, or predicate start policy.
|
|
- `OriginGestureDistance`: numeric CSS pixels or a CSS length string.
|
|
- `OriginGestureStartContext`: pointer-down event, origin, host, bounds, and
|
|
local/client point.
|
|
- `OriginGestureCompletionContext`: release metrics and origin/DOM context.
|
|
- `OriginGestureDirectionOptions`: `threshold` and `axisDominance`.
|
|
- `OriginGestureBinding`: host style and four pointer handlers.
|
|
- `OriginGestureSurfaceProps`: shared host tag and completed definition list.
|
|
- `MaybeOriginNavigationIntent`: synchronous or asynchronous nullable
|
|
navigation-factory result.
|
|
|
|
### `OriginContext`
|
|
|
|
Node-local action context:
|
|
|
|
- `nodeKey`: mounted origin identity.
|
|
- `view`: origin recipe.
|
|
- `canGoBack`: whether a retained previous instance exists.
|
|
- `previous`: recipe belonging to the mounted previous entry.
|
|
- `history`: recipes belonging to all retained previous entries.
|
|
|
|
### `MaybeOriginAction`
|
|
|
|
```ts
|
|
OriginAction | null | undefined | Promise<OriginAction | null | undefined>;
|
|
```
|
|
|
|
### `OriginEffect`
|
|
|
|
| Field | Description |
|
|
| ----------- | ----------------------------------------------- |
|
|
| `transform` | Composable CSS transform contribution |
|
|
| `opacity` | Multiplicative opacity contribution |
|
|
| `layer` | Relative stacking contribution |
|
|
| `style` | Other CSS properties with local-last precedence |
|
|
|
|
`above()` adds a default target layer of `+1`; `under()` adds `-1`.
|
|
|
|
### `OriginChoreographyContext`
|
|
|
|
| Field | Description |
|
|
| ------------ | ------------------------------------------------------ |
|
|
| `progress` | Normalized `0..1` progress |
|
|
| `velocity` | Normalized progress units per second |
|
|
| `phase` | `preparing`, `interactive`, `settling`, or `finished` |
|
|
| `intent` | `undecided`, `commit`, or `cancel` |
|
|
| `originRect` | Origin bounds captured before target mounting |
|
|
| `targetRect` | Target bounds measured after mounting |
|
|
| `viewport` | Scene-container bounds, with browser viewport fallback |
|
|
|
|
Rect values are viewport CSS pixels.
|
|
|
|
### Diagnostic types
|
|
|
|
- `OriginSceneNode`: mounted identity, retained previous key, state, recipe,
|
|
history, and incoming edge.
|
|
- `OriginSceneNodeState`: `active`, `transitioning`, `exposed`, or `parked`.
|
|
- `OriginOperation`: read-only live edge state.
|
|
- `OriginOperationPhase`: operation lifecycle phase.
|
|
- `OriginOperationIntent`: selected operation outcome.
|
|
- `OriginRect`: top, left, width, and height.
|
|
|
|
### Internal types
|
|
|
|
`OriginNodeScope` and `MutableOriginOperation` are renderer/runtime
|
|
implementation types. They are exported by the current barrel but marked
|
|
`@internal` and should not be application dependencies.
|
|
|
|
## Errors and constraints
|
|
|
|
- `useOrigin()` and `useOriginGesture()` must run inside a component mounted by
|
|
`OriginScene`.
|
|
- An origin can own only one outgoing operation at a time.
|
|
- Parked or exposed retained entries are inert and cannot originate operations.
|
|
The active connected target owns interactions until back reveals its source.
|
|
- A target can originate its own operation as soon as its incoming operation's
|
|
intent becomes commit.
|
|
- The included recognizer follows one primary pointer and one axis.
|
|
- Builder edges accept CSS lengths; arbitrary start policy belongs in
|
|
`.from.when()`.
|
|
- Every pushed history entry retains its Vue instance and DOM until a committed
|
|
back operation pops it. There is no eviction policy yet.
|
|
- Parked instances remain mounted, so their ordinary Vue effects and timers
|
|
continue running.
|
|
- A choreography creates one target. Chaining supports any number of
|
|
simultaneously mounted targets.
|
|
- Reduced-motion preference resolves settling immediately.
|