Until now every shipped motion preset was `driver: 'css'`: the `arts/motion` engine's `spring` driver (semi-implicit-Euler physics, velocity handoff) was built + tested but never CONSUMED. This ships the first JS preset, `spring-pop` — a PHYSICAL pop (overshoot + settle, the curve no cubic-bezier expresses; low damping on enter, stiffer exit). Run by `uix.motion` through soma's Presence (`motion.run` + `pending()`), with a CSS `scale-fade` fallback for reduced-motion / SSR. Use on a Presence surface: `<Popover.Content motion="spring-pop">`. Key architecture decision: JS presets are registered DIRECTLY with the engine in `ActiveEidos`, NOT via `config.motion.presets`. The `EidosConfig` is serializable (deep-cloned via `clonePlain`/`structuredClone`), and a `MotionRun` is a function — `structuredClone` throws on it (DataCloneError). Rather than make the whole config clone function-aware (which flattened special types and broke ~23 config tests), JS presets — framework built-ins — live outside the cloneable config. The config stays plain; `clonePlain` is untouched. - `lib/motion/presets/js.ts`: `BUILTIN_JS_PRESETS` (`spring-pop`). - `active-eidos`: registers `BUILTIN_JS_PRESETS` directly with `uix.motion`. - `registry.ts`: `spring-pop` added (type-safe `motion` prop). - `motion.test`: spring registration + driver test; F7 typegen extended to JS presets; fixed a stale shared-axis regex (the container-driven enter branch from `9d40ebe9` made the selector a comma-list — a pre-existing failure surfaced here). motion.test 23/23; the config-dependent suites are back to their pre-existing (unrelated, other-track) baseline — this adds zero failures. `check` clean for the touched files. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>active-uix
parent
3d41459936
commit
4878ccfbef
@ -0,0 +1,32 @@
|
|||||||
|
import { spring } from '$motion'
|
||||||
|
import type { JsStatePreset } from '$motion'
|
||||||
|
import { BUILTIN_CSS_PRESETS } from './css'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Built-in JS-driven presets — the first consumers of the `arts/motion` engine's
|
||||||
|
* `spring` driver (until now built + tested but DORMANT: every shipped preset was
|
||||||
|
* `driver: 'css'`). Registered with `uix.motion` (active-eidos) exactly like the
|
||||||
|
* CSS presets, but RUN by the engine — semi-implicit-Euler physics stepped on
|
||||||
|
* `requestFrame`, the overshoot/settle curve no cubic-bezier expresses. soma's
|
||||||
|
* `Presence` calls `motion.run(node, phase)` and awaits `pending(el)`, which
|
||||||
|
* `getAnimations()` can't see (the spring is invisible to it).
|
||||||
|
*
|
||||||
|
* They generate NO CSS (`render-css` skips non-`css` drivers), so adding one needs
|
||||||
|
* NO `base.css` regeneration. Each carries a `fallback` CSS preset: with no DOM
|
||||||
|
* port (SSR / headless) or under reduced motion, the engine settles on the
|
||||||
|
* fallback instead of stepping the physics.
|
||||||
|
*
|
||||||
|
* Runs only on a Presence surface (an overlay): `<Popover.Content motion="spring-pop">`.
|
||||||
|
*/
|
||||||
|
export const BUILTIN_JS_PRESETS: Readonly<Record<string, JsStatePreset>> = {
|
||||||
|
// A PHYSICAL pop. Low damping on enter → it overshoots and bounces (a real
|
||||||
|
// spring, not a keyframe); the exit is stiffer (snappy, no bounce). Scales from
|
||||||
|
// the element's `transform-origin` (the floating origin on an anchored panel).
|
||||||
|
'spring-pop': {
|
||||||
|
driver: 'spring',
|
||||||
|
enter: spring({ values: { scale: [0.7, 1], opacity: [0, 1] }, stiffness: 300, damping: 14 }),
|
||||||
|
exit: spring({ values: { scale: [1, 0.86], opacity: [1, 0] }, stiffness: 360, damping: 30 }),
|
||||||
|
reduce: 'opacity-only',
|
||||||
|
fallback: BUILTIN_CSS_PRESETS['scale-fade']
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in new issue