|
|
4 months ago | |
|---|---|---|
| .. | ||
| README.md | 4 months ago | |
| drivers.ts | 4 months ago | |
| engine-motion.test.ts | 4 months ago | |
| engine-motion.ts | 4 months ago | |
| index.ts | 4 months ago | |
| types.ts | 4 months ago | |
README.md
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) callsmotion.run(node, phase)to run + await a JS preset (aspring) before unmounting — the gating soma can't get fromgetAnimations()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
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
PresenceviagetAnimations()do the work). - JS preset → runs its
MotionRundriver, normalises the result (Animation|Animation[]|MotionHandle) to one handle, tracks it per element.pending(el)is what Presence awaits for drivers (spring) thatgetAnimations()can't see.
Drivers (./drivers)
MotionRun factories for JS presets:
spring— self-contained physics: an independent semi-implicit-Euler spring per property, stepped viactx.dom.requestFrame. Overshoot + settle — the curve no cubic-bezier expresses. Cancellable viactx.signal.waapi—el.animate(...). TheAnimationis ingetAnimations(), 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
// 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.