You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/src/arts/motion/README.md

85 lines
3.5 KiB

# motion — animation runtime
`EngineMotion` is the runtime engine for the UIX motion system: it registers
motion **presets** and **runs** them. It is an art (a pure runtime artifact,
public methods over private state, no reactive `$state`) so that **both** UIX
layers can consume it via `uix.motion` without a cross-layer dependency:
- **soma** (`Presence`) calls `motion.run(node, phase)` to run + await a JS
preset (a `spring`) before unmounting — the gating soma can't get from
`getAnimations()` alone.
- **eidos** generates the CSS (keyframes + preset rules), registers its visual
presets into the engine, and drives wrappers.
The engine owns the **execution**; eidos owns the **CSS generation** and the
visual presets **data**. Neither imports the other — they meet at `uix.motion`.
## The two moments
Motion occurs in two moments, each animable (one, the other, or both):
| | `--event` | `--state` |
|---|---|---|
| Attr | `data-event-*` (sema) | `data-state` (soma) |
| What | the perceptual **firma** during a signal's hold | the transition to/from a persistent condition |
| Registry | `signatures` (eidos generates CSS) | `presets` (named, per-component) |
`EngineMotion` runs the **`--state`** presets (CSS → settled; JS → driver). The
`--event` firma is CSS that eidos generates from `signatures`; the engine does
not run it.
## API
```ts
const motion = createEngineMotion({ dom }) // dom: a MotionDom port
motion.register('scale-fade', { driver: 'css', … }) // eidos registers presets
motion.register('pop', { driver: 'spring', enter: spring({ … }) })
motion.run(node, 'enter') // resolve node's data-animation-style + run
motion.enter(el, 'pop') // run a preset by name
motion.cancel(el) // cancel active JS motion on el
await motion.pending(el) // combined finished, for Presence
motion.dispose() // idempotent: cancel all + clear registry
```
- **CSS preset** → declarative: a settled handle (the generated CSS + soma's
`Presence` via `getAnimations()` do the work).
- **JS preset** → runs its `MotionRun` driver, normalises the result
(`Animation` | `Animation[]` | `MotionHandle`) to one handle, tracks it per
element. `pending(el)` is what Presence awaits for drivers (`spring`) that
`getAnimations()` can't see.
## Drivers (`./drivers`)
`MotionRun` factories for JS presets:
- **`spring`** — self-contained physics: an independent semi-implicit-Euler
spring per property, stepped via `ctx.dom.requestFrame`. Overshoot + settle —
the curve no cubic-bezier expresses. Cancellable via `ctx.signal`.
- **`waapi`** — `el.animate(...)`. The `Animation` is in `getAnimations()`, so
Presence awaits it for free.
- **`rect`** — FLIP: measures first/last rects, animates the inverse delta via
WAAPI (layout / shared-element transitions).
## The DOM port
This art imports no other art. The DOM dependency arrives **injected** and is
typed by the structural `MotionDom` port (`requestFrame` / `cancelFrame` /
`prefersReducedMotion`); the real `ActiveDom` satisfies it.
## Composition
```ts
// active-app (attach path)
const App = createActiveApp({
services: { dom: defineActiveDom(), motion: defineEngineMotion() }
});
// active-uix (standalone) creates it directly and exposes uix.motion.
```
Without a `dom` service the engine degrades (JS drivers settle; CSS is
declarative regardless). `duration` / `ease` are `string` (token keys or raw
values); eidos validates the keys — this art stays token-agnostic.

Powered by TurnKey Linux.