@blinn-motion/core is the engine every adapter shares. It’s pure and DOM-free; you only need it directly when writing your own adapter or tooling.

Render

sample(doc, t)

Resolve a whole MotionDoc at time t (seconds) into a backend-agnostic RenderNode[] — every transform, color and vertex is a final number.

computeLayer(layer, t)

Resolve a single layer’s animated state at t → a LayerState. sample is built on this.

walk(tree, fn) · findNode(tree, id)

Traverse or look up resolved nodes.

Ticker

The shared playback clock that adapters build their player on. It owns time, looping, rate and the per-frame callback.
number
required
Timeline length in seconds.
boolean
default:"false"
Restart at the end.
number
default:"1"
Playback speed multiplier.
(t: number, fraction: number) => void
Called every frame with current time and progress.

Progress

Map any external 0..1 signal onto the timeline without caring about duration units:

Helpers

The core also exports the pure math the engine runs on:
Writing a new adapter? You only need sample (or computeLayer) and Ticker. Everything else is there so you don’t reimplement easing, color or shape math.