@weasel-js/core 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -0
- package/dist/animation/useAnimator.js +20 -13
- package/dist/animation/useAnimator.js.map +1 -1
- package/dist/{builtins-BW32dOXy.d.ts → builtins-CMEh6-Oc.d.ts} +7 -0
- package/dist/core/scene/scene.js +9 -0
- package/dist/core/scene/scene.js.map +1 -1
- package/dist/core/selection/useSelection.js +27 -33
- package/dist/core/selection/useSelection.js.map +1 -1
- package/dist/core/stableStringify.js +8 -0
- package/dist/core/stableStringify.js.map +1 -0
- package/dist/index.d.ts +9 -9
- package/dist/index.js +269 -268
- package/dist/renderer/draw.js.map +1 -1
- package/dist/renderer/drawBatch.js.map +1 -1
- package/dist/renderer/shaders/batchFill.js +3 -2
- package/dist/renderer/shaders/batchFill.js.map +1 -1
- package/dist/renderer.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +16 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.8.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e07c4ca: An animation whose `onTick`, `onDone` or interpolator throws no longer stops the animator. The error is logged, that animation is removed, and every other animation keeps running — before, the rest of that frame's animations were skipped and no further frame was requested, while `isActive()` stayed true. `animator.watch` delivers a new `error` event carrying the thrown value, in place of `cancel`, or after `end` when `onDone` threw. A listener that switches exhaustively on `AnimatorEvent['type']` has one more case to handle.
|
|
8
|
+
- 934f195: The gesture dispatcher no longer takes a press that lands on a control inside its host — a button, field, link or anything with a control role. It used to open a pointer session that captured the pointer, so the browser delivered the click to the host instead, and a button laid over a canvas (labkit's instrument overlay, for one) could not be clicked with a real pointer. `isInControlWithin` and `CONTROL_SELECTOR`, which answer that question, move from weasel-ui's internals to `@weasel-js/gestures`, re-exported by routing and core.
|
|
9
|
+
- bf522cf: labkit: a lab can present one trial and nothing else — no lab chrome, no trial chrome, a transparent ground — for embedding it as a figure. `<Lab present>` or `?present` in the URL starts it that way, opened on `seed={{ instrument, config, state, view }}`; a stored lab then keeps its own records under `storageKey` + `':present'`, and a changed seed reopens the trial for returning visitors. `usePresentation()` gives `{ active, enter, exit }` inside any lab: `enter` presents the focused trial, Escape returns, and nothing remounts either way. While presenting, the page's root `color-scheme` is reset so an iframe embed stays transparent.
|
|
10
|
+
|
|
11
|
+
core: `stableStringify`, JSON with object keys sorted, moves here from forge, which re-exports it.
|
|
12
|
+
- c49c9e0: New package `@weasel-js/select`: selection as a value. `intentOf(modifiers, policy)` reads a press as `'replace'`, `'toggle'` or `'range'` under a policy naming which keys toggle and which range, and `select(state, id, intent, { order, eligible })` applies it to `{ ids, anchor }`. Ineligible ids — locked or disabled rows — are skipped by a range, dropped when a selection grows, and selected alone when pressed. `createSelectionStore` keeps ids outside a component, behind the `SelectionStore` contract, which core still exports under the same name.
|
|
13
|
+
|
|
14
|
+
core's `useSelection`, and `Tree` and `LayerList` in `@weasel-js/ui`, now select through it rather than each keeping its own rules. `SelectionMode` and `SelectionExtendKey` are declared in `@weasel-js/select` and still exported from `@weasel-js/routing` and `@weasel-js/core`. Two edges change: `LayerList`'s Shift+arrow with its anchor hidden in a collapsed branch now selects the row it reaches instead of doing nothing, and a Cmd/Ctrl-press in a multi-select `Tree` drops any disabled row from the selection it builds on.
|
|
15
|
+
- 2123049: A wheel the gesture dispatcher claims no longer reaches the element's other wheel listeners. It listens in the capture phase and stops the event there, so a labkit loupe over a canvas with its own camera controls — three.js `OrbitControls`, say — zooms the lens alone instead of the lens and the camera together. A wheel no binding claims still reaches them.
|
|
16
|
+
- Updated dependencies [934f195]
|
|
17
|
+
- Updated dependencies [7e72192]
|
|
18
|
+
- Updated dependencies [412e53a]
|
|
19
|
+
- Updated dependencies [6d800fb]
|
|
20
|
+
- Updated dependencies [2d97065]
|
|
21
|
+
- Updated dependencies [f9c137b]
|
|
22
|
+
- Updated dependencies [c49c9e0]
|
|
23
|
+
- Updated dependencies [2123049]
|
|
24
|
+
- @weasel-js/gestures@1.8.1
|
|
25
|
+
- @weasel-js/routing@1.8.1
|
|
26
|
+
- @weasel-js/geom@1.8.1
|
|
27
|
+
- @weasel-js/history@1.8.1
|
|
28
|
+
- @weasel-js/select@1.8.1
|
|
29
|
+
- @weasel-js/text@1.8.1
|
|
30
|
+
- @weasel-js/cursor@1.8.1
|
|
31
|
+
- @weasel-js/font@1.8.1
|
|
32
|
+
- @weasel-js/modes@1.8.1
|
|
33
|
+
- @weasel-js/paint@1.8.1
|
|
34
|
+
- @weasel-js/quantity@1.8.1
|
|
35
|
+
- @weasel-js/react@1.8.1
|
|
36
|
+
- @weasel-js/registry@1.8.1
|
|
37
|
+
|
|
3
38
|
## 1.8.0
|
|
4
39
|
|
|
5
40
|
### Minor Changes
|
|
@@ -63,30 +63,37 @@ function b(u = {}) {
|
|
|
63
63
|
type: "end",
|
|
64
64
|
animation: _(t)
|
|
65
65
|
}));
|
|
66
|
-
}, k = (e, t) => {
|
|
67
|
-
let
|
|
68
|
-
|
|
66
|
+
}, k = (e, t, n) => {
|
|
67
|
+
let r = x.current.get(e);
|
|
68
|
+
r && (r.onCancel?.(), g.stop(e), x.current.delete(e), p(e), !(!h.watched || r.ended || n) && h.emit(t ? {
|
|
69
69
|
type: "interrupt",
|
|
70
|
-
animation: _(
|
|
70
|
+
animation: _(r),
|
|
71
71
|
by: _(t)
|
|
72
72
|
} : {
|
|
73
73
|
type: "cancel",
|
|
74
|
-
animation: _(
|
|
74
|
+
animation: _(r)
|
|
75
75
|
}));
|
|
76
76
|
}, A = (e) => {
|
|
77
|
-
let t = [], n = w.current == null ? 0 : Math.max(0, e - w.current);
|
|
78
|
-
w.current = e, g.frame(
|
|
79
|
-
for (let
|
|
80
|
-
let
|
|
81
|
-
|
|
82
|
-
let
|
|
83
|
-
|
|
77
|
+
let t = [], n = [], r = w.current == null ? 0 : Math.max(0, e - w.current);
|
|
78
|
+
w.current = e, g.frame(r * (E.current ? 0 : T.current));
|
|
79
|
+
for (let r of x.current.values()) {
|
|
80
|
+
let i = r.lastRealNow == null ? 0 : Math.max(0, e - r.lastRealNow);
|
|
81
|
+
r.lastRealNow = e;
|
|
82
|
+
let a = E.current ? 0 : T.current * (r.paused ? 0 : r.timeScale);
|
|
83
|
+
r.virtualNow += i * a, C.current += 1;
|
|
84
84
|
try {
|
|
85
|
-
|
|
85
|
+
r.tick(r.virtualNow, a) && t.push(r);
|
|
86
|
+
} catch (e) {
|
|
87
|
+
n.push([r, e]);
|
|
86
88
|
} finally {
|
|
87
89
|
--C.current;
|
|
88
90
|
}
|
|
89
91
|
}
|
|
92
|
+
for (let [e, t] of n) console.error("useAnimator: animation tick threw; retiring it", t), x.current.get(e.id) === e && (e.ended ? (x.current.delete(e.id), p(e.id)) : k(e.id, void 0, !0), h.watched && h.emit({
|
|
93
|
+
type: "error",
|
|
94
|
+
animation: _(e),
|
|
95
|
+
error: t
|
|
96
|
+
}));
|
|
90
97
|
for (let e of t) x.current.get(e.id) === e && (v(e.id), x.current.delete(e.id), p(e.id));
|
|
91
98
|
for (let e of O.current) try {
|
|
92
99
|
e();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAnimator.js","names":["resolveSpringConstants","preset","o","SPRING_PRESETS","useAnimator","optsRef","useLatest","opts","animations","useRef","nextId","tickDepth","codecFrameT","globalTimeScale","globalPaused","colorOverrides","ColorOverrideRegistry","tickSubscribers","tickAllRef","frameLoop","useVisibleRaf","useCallback","t","anim","frameLoopRef","mountedRef","trippedRef","tripwire","useMemo","now","staggerTimers","c","m","cb","ms","x","h","completionListeners","fireCompletion","ls","id","watchCompletion","cur","idx","hub","AnimatorEventHub","codec","createCodec","infoOf","a","info","reportEnd","retire","by","tickAll","finished","frameDt","realDt","scale","sub","err","ensureLoop","cancelByKey","ids","key","rateOf","register","seed","s","createSupervisor","onCancelCb","base","tween","fromAxes","axesOf","toAxes","axes","easing","resolveEasing","easeOut","factoryFn","lastValueEmitted","reader","virtualNow","nowMs","value","eased","physics","add","b","subtract","v","k","magnitude","kBase","restThreshold","target","velocity","lastTime","damping","mass","kind","sameShape","baseHandle","dt","next","stepSpring","velRested","posRested","checkShape","what","newTo","api","friction","handle","retired","createLoop","factory","loopOpts","createTweenLoop","tweenLoopOpts","createStagger","items","delay","staggerOpts","createTimeline","animation","path","sup","listener","rows","row","useInsertionEffect","useEffect","overrides"],"sources":["../../src/animation/useAnimator.ts"],"sourcesContent":["import { useCallback, useEffect, useInsertionEffect, useMemo, useRef } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { useVisibleRaf } from '../scheduling/useVisibleRaf';\nimport { easeOut, SPRING_PRESETS, resolveEasing } from '@weasel-js/geom';\nimport { createLoop, createTweenLoop } from './loop';\nimport { stepSpring } from './engine/integrator';\nimport { createCodec, type SpringReader } from './engine/codec';\nimport { axesOf } from './engine/axes';\nimport { createStagger, type StaggerTimers } from './stagger';\nimport { createTimeline } from './timeline/createTimeline';\nimport { ColorOverrideRegistry } from './colorRegistry';\nimport { AnimatorEventHub } from './observe';\nimport type { Supervisor, SupervisorOptions, WatchCompletion } from './supervisor';\nimport type {\n AnimationHandle,\n AnimationInfo,\n AnimationKind,\n Animator,\n TweenOptions,\n SpringOptions,\n DecayOptions,\n PhysicsOptions,\n PhysicsHandle,\n UseAnimatorOptions,\n LiveAnimation,\n} from './types';\nimport type { TimelineOptions } from './timeline/types';\n\ninterface ActiveAnimation {\n id: number;\n kind: AnimationKind;\n cancelKey?: string;\n label?: string;\n /** Built the first time something reports on this entry, then shared. */\n info?: AnimationInfo;\n /** 0–1 where the animation has an end to measure against. */\n progress?(virtualNow: number): number;\n /** Its `end` is reported, though the entry stays on the table until the\n * frame's ticks are done. */\n ended?: boolean;\n paused: boolean;\n timeScale: number;\n virtualNow: number;\n lastRealNow: number | null;\n /** Returns true when finished. Called once per frame with the current\n * virtual-ms timestamp and the effective scale it advanced at this frame. */\n tick(virtualNow: number, scale: number): boolean;\n /** Called when the animation is cancelled. Skips onDone. */\n onCancel?(): void;\n}\n\nfunction resolveSpringConstants(o: { preset?: string; stiffness?: number; damping?: number; mass?: number }) {\n const preset = o.preset ? SPRING_PRESETS[o.preset as keyof typeof SPRING_PRESETS] : null;\n return {\n stiffness: o.stiffness ?? preset?.stiffness ?? 170,\n damping: o.damping ?? preset?.damping ?? 26,\n mass: o.mass ?? preset?.mass ?? 1,\n };\n}\n\n/** Create the animator for a canvas. One rAF loop drives every animation it\n * owns, and everything still running is cancelled on unmount. */\nexport function useAnimator(opts: UseAnimatorOptions = {}): Animator {\n const optsRef = useLatest(opts);\n const animations = useRef<Map<number, ActiveAnimation>>(new Map());\n const nextId = useRef(1);\n /**\n * Re-entrancy counter incremented around each animation tick in tickAll.\n * Exposed via `isTicking()`. > 0 ⇒ we're currently inside an animation's\n * onTick; an adapter wrapper (`animateOnSetPose`) seeing this flag should\n * write through to the base adapter rather than schedule a new tween.\n */\n const tickDepth = useRef(0);\n /** The timestamp the codec last advanced to. Null after the page was hidden and while nothing\n * runs, so neither gap is charged to the codec; a tween starting then seeds it from `now()`. */\n const codecFrameT = useRef<number | null>(null);\n const globalTimeScale = useRef(1);\n const globalPaused = useRef(false);\n const colorOverrides = useRef<ColorOverrideRegistry>(new ColorOverrideRegistry());\n // Per-frame tick subscribers. Notified after each batch of animation\n // ticks (i.e. after `colorOverrides` has settled to its latest values\n // but before the next RAF schedules). Used by `<SceneCanvas animator>`\n // to request a redraw on every active frame.\n const tickSubscribers = useRef<Set<() => void>>(new Set());\n\n // The loop runs behind the visibility gate. `tickAll` is built inside the\n // memo below, so the frame callback reaches it through a ref, published\n // once the memo's render commits.\n const tickAllRef = useRef<((t: number) => void) | null>(null);\n const frameLoop = useVisibleRaf(\n useCallback((t: number) => { tickAllRef.current?.(t); }, []),\n {\n requestFrame: opts.requestFrame,\n cancelFrame: opts.cancelFrame,\n // An hour spent hidden is not an hour the animation ran: dropping each\n // animation's last timestamp makes the resuming frame's `realDt` zero.\n onResume: () => {\n for (const anim of animations.current.values()) anim.lastRealNow = null;\n codecFrameT.current = null;\n },\n },\n );\n const frameLoopRef = useLatest(frameLoop);\n\n // Tripwire: dev-only flag that every tween/spring/decay's tick reads to\n // detect \"animation fired after the host component unmounted.\" This is a\n // symptom of cleanup not running (regression) — typically because someone\n // refactored useAnimator and forgot to wire the unmount effect. The flag\n // flips false on cleanup; ticks see it and log a one-time error so the\n // bug is loud rather than just visually-doubled animation.\n const mountedRef = useRef(true);\n const trippedRef = useRef(false);\n const tripwire = (): boolean => {\n if (mountedRef.current) return false;\n if (!trippedRef.current) {\n trippedRef.current = true;\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) {\n console.error(\n 'weasel useAnimator: animation tick fired after the host component unmounted. ' +\n 'This usually means cleanup logic was bypassed — check for refactors that ' +\n 'removed the unmount effect or replaced cancelAll with a custom path.',\n );\n }\n }\n return true;\n };\n\n const { api, tickAll } = useMemo(() => {\n // Default to performance.now() so the time origin matches the\n // requestAnimationFrame callback's DOMHighResTimeStamp argument.\n // Using Date.now() here would mix epoch-millis with page-relative-millis,\n // producing huge negative `elapsed` values that clamp tween `t` to 0\n // forever (never reaching completion).\n const now = (): number =>\n (optsRef.current.now ?? (typeof performance !== 'undefined' ? performance.now.bind(performance) : Date.now))();\n // Resolved timer pair, snapshotted lazily from optsRef on each call so a\n // test that updates the injection after mount still wins. Kept internal —\n // not exposed on the public Animator surface; passed directly into\n // `createStagger` at bind time below.\n const staggerTimers: StaggerTimers = {\n setTimer: (cb, ms) =>\n (optsRef.current.setTimer ?? ((c, m) => setTimeout(c, m)))(cb, ms),\n clearTimer: (h) =>\n (optsRef.current.clearTimer ??\n ((x) => clearTimeout(x as ReturnType<typeof setTimeout>)))(h),\n now,\n };\n\n // Per-id one-shot completion listeners. Used by stagger to detect when\n // each child has left the registry (natural completion OR cancel) so the\n // supervising composite can retire itself when the last child finishes.\n const completionListeners = new Map<number, (() => void)[]>();\n const fireCompletion = (id: number): void => {\n const ls = completionListeners.get(id);\n if (!ls) return;\n completionListeners.delete(id);\n for (const cb of ls) cb();\n };\n const watchCompletion: WatchCompletion = (id, cb) => {\n const ls = completionListeners.get(id) ?? [];\n ls.push(cb);\n completionListeners.set(id, ls);\n return () => {\n const cur = completionListeners.get(id);\n if (!cur) return;\n const idx = cur.indexOf(cb);\n if (idx >= 0) cur.splice(idx, 1);\n if (cur.length === 0) completionListeners.delete(id);\n };\n };\n\n const hub = new AnimatorEventHub();\n const codec = createCodec();\n const infoOf = (a: ActiveAnimation): AnimationInfo => {\n if (!a.info) {\n const info: { -readonly [K in keyof AnimationInfo]: AnimationInfo[K] } = { id: a.id, kind: a.kind };\n if (a.cancelKey != null) info.key = a.cancelKey;\n if (a.label != null) info.label = a.label;\n a.info = info;\n }\n return a.info;\n };\n\n /** Report `id` as finished, ahead of its `onDone`, so whatever that\n * handler starts is heard after it. Nothing revives a primitive; a\n * timeline, which can be revived, is reported as it leaves the table. */\n const reportEnd = (id: number): void => {\n const a = animations.current.get(id);\n if (!a || a.ended) return;\n a.ended = true;\n if (hub.watched) hub.emit({ type: 'end', animation: infoOf(a) });\n };\n\n /** Take `id` off the table as canceled — or, given `by`, as interrupted by\n * the animation claiming its key. */\n const retire = (id: number, by?: ActiveAnimation): void => {\n const a = animations.current.get(id);\n if (!a) return;\n a.onCancel?.();\n codec.stop(id);\n animations.current.delete(id);\n fireCompletion(id);\n if (!hub.watched || a.ended) return;\n hub.emit(by\n ? { type: 'interrupt', animation: infoOf(a), by: infoOf(by) }\n : { type: 'cancel', animation: infoOf(a) });\n };\n\n const tickAll = (t: number): void => {\n const finished: ActiveAnimation[] = [];\n const frameDt = codecFrameT.current == null ? 0 : Math.max(0, t - codecFrameT.current);\n codecFrameT.current = t;\n codec.frame(frameDt * (globalPaused.current ? 0 : globalTimeScale.current));\n for (const anim of animations.current.values()) {\n // `t` comes from the frame clock; `lastRealNow` is seeded at register()\n // from `now()`. The two share a time origin in a browser, where the rAF\n // timestamp and `performance.now()` are both page-relative — but not\n // everywhere: jsdom starts them ~600ms apart, which made the first\n // frame's delta hugely negative and left `virtualNow` climbing back\n // toward zero for dozens of frames before a tween advanced at all.\n // Time never runs backwards, so a negative sample is never real.\n const realDt = anim.lastRealNow == null ? 0 : Math.max(0, t - anim.lastRealNow);\n anim.lastRealNow = t;\n const scale = globalPaused.current\n ? 0\n : globalTimeScale.current * (anim.paused ? 0 : anim.timeScale);\n anim.virtualNow += realDt * scale;\n // Increment tick depth around each animation's tick so re-entrant\n // calls (e.g. `decay.onTick` → `adapter.setPose` →\n // `animateOnSetPose` checking `isTicking()`) see the flag and\n // skip scheduling a new wrap-tween that would fight the caller.\n tickDepth.current += 1;\n try {\n if (anim.tick(anim.virtualNow, scale)) finished.push(anim);\n } finally {\n tickDepth.current -= 1;\n }\n }\n for (const anim of finished) {\n // Gone already if its own tick canceled it; replaced if something\n // revived it under the same id since.\n if (animations.current.get(anim.id) !== anim) continue;\n reportEnd(anim.id);\n animations.current.delete(anim.id);\n fireCompletion(anim.id);\n }\n // Notify every onTick subscriber AFTER the tick batch so they\n // see the latest `colorOverrides` / pose values. Errors in one\n // subscriber don't suppress the others.\n for (const sub of tickSubscribers.current) {\n try { sub(); } catch (err) { console.error('useAnimator: onTick subscriber threw', err); }\n }\n if (animations.current.size > 0) frameLoopRef.current.request();\n else codecFrameT.current = null;\n };\n\n const ensureLoop = (): void => {\n if (animations.current.size === 0) return;\n frameLoopRef.current.request();\n };\n\n const cancelByKey = (key: string, by?: ActiveAnimation): void => {\n const ids: number[] = [];\n for (const anim of animations.current.values()) {\n if (anim.cancelKey === key) ids.push(anim.id);\n }\n for (const id of ids) retire(id, by);\n };\n\n type AnimationSeed =\n Omit<ActiveAnimation, 'paused' | 'timeScale' | 'virtualNow' | 'lastRealNow'>\n & {\n /** Registers under an existing `cancelKey` without cancelling whoever\n * holds it. For an animation re-registering itself — a revived\n * timeline — which is not a new claim on the key. */\n keepExisting?: boolean;\n };\n /** Gives a codec subject the rate its own pause and time scale now ask for. */\n const rateOf = (a: ActiveAnimation): void => {\n if (codec.has(a.id)) codec.rate(a.id, a.paused ? 0 : a.timeScale);\n };\n\n const register = (seed: AnimationSeed): AnimationHandle => {\n const anim = seed as ActiveAnimation;\n if (seed.cancelKey != null && !seed.keepExisting) cancelByKey(seed.cancelKey, anim);\n anim.paused = false;\n anim.timeScale = 1;\n anim.virtualNow = 0;\n // Seed lastRealNow at registration so the first frame's realDt reflects\n // the gap between register() and the first RAF callback: it places a\n // tween's end, and gives spring/decay a non-zero first dt sample.\n anim.lastRealNow = now();\n animations.current.set(anim.id, anim);\n if (hub.watched) hub.emit({ type: 'start', animation: infoOf(anim) });\n ensureLoop();\n return {\n id: anim.id,\n cancel: () => retire(anim.id),\n pause: () => { const a = animations.current.get(anim.id); if (a) { a.paused = true; rateOf(a); } },\n resume: () => { const a = animations.current.get(anim.id); if (a) { a.paused = false; rateOf(a); } },\n setTimeScale: (s) => { const a = animations.current.get(anim.id); if (a) { a.timeScale = s; rateOf(a); } },\n timeScale: () => animations.current.get(anim.id)?.timeScale ?? 1,\n isPaused: () => animations.current.get(anim.id)?.paused ?? false,\n };\n };\n\n // Supervisor: a registered animation whose tick is a no-op (never\n // finishes naturally) so loop/stagger can sit in the animator's id table\n // and benefit from `cancel`/`cancelKey`/`isActive`. The owning composite\n // (loop/stagger) installs an onCancel to actually tear down its children.\n const createSupervisor = ({ kind, cancelKey, label }: SupervisorOptions): Supervisor => {\n const id = nextId.current++;\n let onCancelCb: (() => void) | undefined;\n const base = register({\n id,\n kind,\n cancelKey,\n label,\n // tick is a no-op: the supervisor only ends when the owner calls\n // `cancel()` (either via animator.cancel, animator.cancelKey, or the\n // composite's natural-completion path which forwards to `cancel`).\n tick: () => false,\n onCancel: () => onCancelCb?.(),\n });\n return {\n id: base.id,\n cancel: base.cancel,\n pause: base.pause,\n resume: base.resume,\n setTimeScale: base.setTimeScale,\n timeScale: base.timeScale,\n isPaused: base.isPaused,\n setOnCancel: (cb) => { onCancelCb = cb; },\n finish: () => {\n if (!animations.current.has(id)) return;\n reportEnd(id);\n animations.current.delete(id);\n fireCompletion(id);\n },\n cancelKey,\n };\n };\n\n const tween = <T,>(o: TweenOptions<T>): AnimationHandle => {\n // blits blends in a straight line, which a caller's own function may not do.\n const fromAxes = o.interpolate || o.interpolator ? null : axesOf(o.from);\n const toAxes = fromAxes && axesOf(o.to);\n const axes = fromAxes && toAxes && toAxes.shape === fromAxes.shape ? fromAxes : null;\n // Refused here rather than on a tick, where a throw would stop every other animation.\n if (!axes && !o.interpolate && !o.interpolator) {\n throw new Error('tween: interpolate or interpolator is required for non-numeric T');\n }\n const id = nextId.current++;\n const easing = resolveEasing(o.easing ?? easeOut);\n // Precedence: factory > per-tick. Factory is built once at tween start so\n // expensive setup (color space conversion etc.) doesn't repeat per frame.\n const factoryFn = o.interpolator ? o.interpolator(o.from, o.to) : null;\n let lastValueEmitted = false;\n // Seeds the codec's clock where `register` seeds the call's, so both charge the same wait.\n if (codecFrameT.current == null) codecFrameT.current = now();\n // Started ahead of `register`, whose `start` listeners may already cancel it.\n const reader = codec.tween({\n id, ms: Math.max(o.ms, 1), ease: easing,\n from: axes ? axes.to(o.from) : [0],\n to: axes ? axes.to(o.to) : [1],\n });\n return register({\n id,\n kind: 'tween',\n cancelKey: o.cancelKey,\n label: o.label,\n progress: (virtualNow) => (o.ms <= 0 ? 1 : Math.min(1, virtualNow / o.ms)),\n // `nowMs` is the call's own virtual time, so it still decides when the tween ends; the codec\n // supplies only the value in between.\n tick(nowMs) {\n if (tripwire()) { codec.stop(id); return true; }\n const t = o.ms <= 0 ? 1 : Math.min(1, nowMs / o.ms);\n let value: T;\n if (axes) {\n value = t >= 1 ? o.to : axes.from(reader.cols, reader.at);\n } else {\n const eased = t >= 1 ? easing(1) : reader.cols[reader.at]!;\n value = factoryFn ? factoryFn(eased) : o.interpolate!(o.from, o.to, eased);\n }\n o.onTick(value);\n if (t >= 1 && !lastValueEmitted) {\n lastValueEmitted = true;\n codec.stop(id);\n // That last onTick may have cancelled us — deregistering the id.\n // A cancelled tween never completes, whenever the cancel landed.\n if (animations.current.has(id)) {\n reportEnd(id);\n o.onDone?.();\n }\n return true;\n }\n return false;\n },\n });\n };\n\n const physics = <T,>(o: PhysicsOptions<T>, kind: AnimationKind = 'physics'): PhysicsHandle<T> => {\n const id = nextId.current++;\n const isNumeric = typeof o.from === 'number';\n if (!isNumeric && (!o.add || !o.subtract || !o.scale || !o.magnitude)) {\n throw new Error('physics: add/subtract/scale/magnitude are required for non-numeric T');\n }\n const add = o.add ?? ((a: T, b: T) => ((a as unknown as number) + (b as unknown as number)) as unknown as T);\n const subtract = o.subtract ?? ((a: T, b: T) => ((a as unknown as number) - (b as unknown as number)) as unknown as T);\n const scale = o.scale ?? ((v: T, k: number) => ((v as unknown as number) * k) as unknown as T);\n const magnitude = o.magnitude ?? ((v: T) => Math.abs(v as unknown as number));\n const { stiffness: kBase, damping, mass } = resolveSpringConstants(o);\n const restThreshold = o.restThreshold ?? 0.01;\n\n let target: T | null = o.to ?? null;\n let value = o.from;\n // Default to zero velocity: assumes scale(_, 0) returns the zero vector of T. Pass an explicit velocity for unusual T where this isn't true.\n let velocity: T = o.velocity ?? scale(o.from, 0);\n let lastTime: number | null = null;\n\n // blits' closed forms need positive damping and mass, and a spring with a target needs\n // stiffness; decay's handle never takes a target.\n const solvable = damping > 0 && mass > 0 && (kBase > 0 || kind === 'decay');\n const fromAxes = solvable ? axesOf(o.from) : null;\n const sameShape = (v: T | null | undefined): boolean => v == null || axesOf(v)?.shape === fromAxes!.shape;\n const axes = fromAxes && sameShape(o.to) && sameShape(o.velocity) ? fromAxes : null;\n let reader: SpringReader | null = null;\n if (axes) {\n // Seeds the codec's clock where `register` seeds the call's, so both charge the same wait.\n if (codecFrameT.current == null) codecFrameT.current = now();\n // Started ahead of `register`, whose `start` listeners may already cancel it.\n reader = codec.spring({\n id, axes: axes.count,\n from: axes.to(o.from),\n to: o.to == null ? null : axes.to(o.to),\n velocity: o.velocity == null ? new Array<number>(axes.count).fill(0) : axes.to(o.velocity),\n stiffness: kBase, damping, mass,\n });\n }\n\n const baseHandle = register({\n id,\n kind,\n cancelKey: o.cancelKey,\n label: o.label,\n tick(nowMs) {\n if (tripwire()) { codec.stop(id); return true; }\n if (lastTime == null) {\n lastTime = nowMs;\n // Already-at-rest short-circuit: decay-mode (target == null)\n // with starting velocity below threshold should complete\n // immediately rather than emit a tick and wait a frame.\n if (target == null && magnitude(velocity) < restThreshold) {\n codec.stop(id);\n reportEnd(id);\n o.onDone?.();\n return true;\n }\n // The codec's voice has run since registration, so only Euler starts its clock here.\n if (!axes) {\n o.onTick(value);\n return false;\n }\n }\n if (axes) {\n const m = reader!.motion();\n value = axes.from(m.value);\n velocity = axes.from(m.velocity);\n } else {\n // Semi-implicit Euler, for a T blits cannot move as axes, or constants its closed forms can't solve.\n const dt = Math.min(0.064, (nowMs - lastTime) / 1000);\n const next = stepSpring({ add, subtract, scale }, value, velocity, target, kBase, damping, mass, dt);\n value = next.value;\n velocity = next.velocity;\n }\n lastTime = nowMs;\n o.onTick(value);\n const velRested = magnitude(velocity) < restThreshold;\n const posRested = target == null\n ? true\n : magnitude(subtract(value, target)) < restThreshold;\n if (velRested && posRested) {\n if (target != null) o.onTick(target);\n codec.stop(id);\n reportEnd(id);\n o.onDone?.();\n return true;\n }\n return false;\n },\n });\n\n const checkShape = (v: T, what: string): void => {\n if (!sameShape(v)) throw new Error(`physics: ${what} is not the same shape as \\`from\\``);\n };\n const handle: PhysicsHandle<T> = {\n ...baseHandle,\n setTarget: (newTo: T | null) => {\n if (axes && newTo != null) checkShape(newTo, 'setTarget');\n target = newTo;\n if (axes && codec.has(id)) codec.retarget(id, newTo == null ? null : axes.to(newTo));\n },\n setVelocity: (v: T) => {\n if (axes) checkShape(v, 'setVelocity');\n velocity = v;\n if (axes && codec.has(id)) codec.push(id, axes.to(v));\n },\n };\n return handle;\n };\n\n const spring = <T,>(o: SpringOptions<T>): AnimationHandle => physics<T>(o, 'spring');\n\n const decay = <T,>(o: DecayOptions<T>): AnimationHandle => {\n const friction = o.friction ?? 0.95;\n // Per-second friction v(t) = v0 * friction^t corresponds to\n // m*dv/dt = -c*v with c = -ln(friction), m = 1, k = 0.\n const damping = -Math.log(friction);\n return physics<T>({\n from: o.from,\n to: null,\n velocity: o.velocity,\n stiffness: 0,\n damping,\n mass: 1,\n restThreshold: o.threshold ?? 0.5,\n add: o.add,\n // DecayOptions doesn't carry subtract; derive from add+scale.\n subtract: (a, b) => o.add(a, o.scale(b, -1)),\n scale: o.scale,\n magnitude: o.magnitude,\n onTick: o.onTick,\n onDone: o.onDone,\n cancelKey: o.cancelKey,\n label: o.label,\n }, 'decay');\n };\n\n const cancelAll = (): void => {\n const retired: ActiveAnimation[] = [];\n for (const a of animations.current.values()) {\n a.onCancel?.();\n codec.stop(a.id);\n retired.push(a);\n }\n animations.current.clear();\n codecFrameT.current = null;\n for (const a of retired) fireCompletion(a.id);\n if (hub.watched) for (const a of retired) hub.emit({ type: 'cancel', animation: infoOf(a) });\n frameLoopRef.current.cancel();\n };\n const api: Animator = {\n tween,\n spring,\n decay,\n physics,\n cancel: (handle) => retire(handle.id),\n cancelKey: (key) => cancelByKey(key),\n cancelAll,\n isActive: (key) => {\n if (key == null) return animations.current.size > 0;\n for (const a of animations.current.values()) {\n if (a.cancelKey === key) return true;\n }\n return false;\n },\n isTicking: () => tickDepth.current > 0,\n pause: () => { globalPaused.current = true; },\n resume: () => { globalPaused.current = false; },\n isPaused: () => globalPaused.current,\n setTimeScale: (s) => { globalTimeScale.current = s; },\n timeScale: () => globalTimeScale.current,\n pauseKey: (key) => {\n for (const a of animations.current.values()) if (a.cancelKey === key) { a.paused = true; rateOf(a); }\n },\n resumeKey: (key) => {\n for (const a of animations.current.values()) if (a.cancelKey === key) { a.paused = false; rateOf(a); }\n },\n setTimeScaleByKey: (key, s) => {\n for (const a of animations.current.values()) if (a.cancelKey === key) { a.timeScale = s; rateOf(a); }\n },\n loop: (factory, loopOpts) => createLoop(createSupervisor, factory, loopOpts),\n tweenLoop: (tweenLoopOpts) =>\n createTweenLoop(api, createSupervisor, tweenLoopOpts),\n stagger: ((items, delay, factory, staggerOpts) =>\n createStagger(\n api,\n staggerTimers,\n createSupervisor,\n watchCompletion,\n items,\n delay,\n factory as never,\n staggerOpts,\n )) as Animator['stagger'],\n timeline: (o: TimelineOptions) => {\n const id = nextId.current++;\n const info = (): AnimationInfo | undefined => {\n const a = animations.current.get(id);\n return a && infoOf(a);\n };\n return createTimeline(register, id, o, {\n get watched() { return hub.watched; },\n fire: (track, path, event, lateBy) => {\n const animation = info();\n if (animation) hub.emit({ type: 'fire', animation, track, path: path.slice(), event, lateBy });\n },\n lap: (lap) => {\n const animation = info();\n if (animation) hub.emit({ type: 'lap', animation, lap });\n },\n });\n },\n colorOverrides: colorOverrides.current,\n onTick: (cb) => {\n tickSubscribers.current.add(cb);\n return () => { tickSubscribers.current.delete(cb); };\n },\n keepAlive: () => {\n const sup = createSupervisor({ kind: 'keepAlive' });\n return () => sup.cancel();\n },\n watch: (listener) => hub.add(listener),\n live: () => {\n const rows: LiveAnimation[] = [];\n for (const a of animations.current.values()) {\n const row: LiveAnimation = {\n ...infoOf(a),\n paused: a.paused,\n timeScale: a.timeScale,\n elapsed: a.virtualNow,\n ...(a.progress ? { progress: a.progress(a.virtualNow) } : {}),\n };\n rows.push(row);\n }\n return rows;\n },\n };\n return { api, tickAll };\n }, [frameLoopRef, optsRef]);\n\n useInsertionEffect(() => {\n tickAllRef.current = tickAll;\n }, [tickAll]);\n\n // StrictMode-safe cleanup: when the component unmounts (including the\n // dev-mode double-mount that StrictMode performs), cancel every running\n // animation and stop the RAF loop. Without this, the FIRST mount's\n // animator keeps ticking with stale callbacks pointing at the unmounted\n // adapter, while the SECOND mount creates its own animator on top —\n // visible to the user as every animation playing twice.\n useEffect(() => {\n const overrides = colorOverrides.current;\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n api.cancelAll();\n overrides.clearAll();\n };\n }, [api]);\n\n return api;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useAnimator.js","names":["resolveSpringConstants","preset","o","SPRING_PRESETS","useAnimator","optsRef","useLatest","opts","animations","useRef","nextId","tickDepth","codecFrameT","globalTimeScale","globalPaused","colorOverrides","ColorOverrideRegistry","tickSubscribers","tickAllRef","frameLoop","useVisibleRaf","useCallback","t","anim","frameLoopRef","mountedRef","trippedRef","tripwire","useMemo","now","staggerTimers","c","m","cb","ms","x","h","completionListeners","fireCompletion","ls","id","watchCompletion","cur","idx","hub","AnimatorEventHub","codec","createCodec","infoOf","a","info","reportEnd","retire","error","by","tickAll","finished","threw","frameDt","realDt","scale","sub","err","ensureLoop","cancelByKey","ids","key","rateOf","register","seed","s","createSupervisor","onCancelCb","base","tween","fromAxes","axesOf","toAxes","axes","easing","resolveEasing","easeOut","factoryFn","lastValueEmitted","reader","virtualNow","nowMs","value","eased","physics","add","b","subtract","v","k","magnitude","kBase","restThreshold","target","velocity","lastTime","damping","mass","kind","sameShape","baseHandle","dt","next","stepSpring","velRested","posRested","checkShape","what","newTo","api","friction","handle","retired","createLoop","factory","loopOpts","createTweenLoop","tweenLoopOpts","createStagger","items","delay","staggerOpts","createTimeline","animation","path","sup","listener","rows","row","useInsertionEffect","useEffect","overrides"],"sources":["../../src/animation/useAnimator.ts"],"sourcesContent":["import { useCallback, useEffect, useInsertionEffect, useMemo, useRef } from 'react';\nimport { useLatest } from '@weasel-js/react';\nimport { useVisibleRaf } from '../scheduling/useVisibleRaf';\nimport { easeOut, SPRING_PRESETS, resolveEasing } from '@weasel-js/geom';\nimport { createLoop, createTweenLoop } from './loop';\nimport { stepSpring } from './engine/integrator';\nimport { createCodec, type SpringReader } from './engine/codec';\nimport { axesOf } from './engine/axes';\nimport { createStagger, type StaggerTimers } from './stagger';\nimport { createTimeline } from './timeline/createTimeline';\nimport { ColorOverrideRegistry } from './colorRegistry';\nimport { AnimatorEventHub } from './observe';\nimport type { Supervisor, SupervisorOptions, WatchCompletion } from './supervisor';\nimport type {\n AnimationHandle,\n AnimationInfo,\n AnimationKind,\n Animator,\n TweenOptions,\n SpringOptions,\n DecayOptions,\n PhysicsOptions,\n PhysicsHandle,\n UseAnimatorOptions,\n LiveAnimation,\n} from './types';\nimport type { TimelineOptions } from './timeline/types';\n\ninterface ActiveAnimation {\n id: number;\n kind: AnimationKind;\n cancelKey?: string;\n label?: string;\n /** Built the first time something reports on this entry, then shared. */\n info?: AnimationInfo;\n /** 0–1 where the animation has an end to measure against. */\n progress?(virtualNow: number): number;\n /** Its `end` is reported, though the entry stays on the table until the\n * frame's ticks are done. */\n ended?: boolean;\n paused: boolean;\n timeScale: number;\n virtualNow: number;\n lastRealNow: number | null;\n /** Returns true when finished. Called once per frame with the current\n * virtual-ms timestamp and the effective scale it advanced at this frame. */\n tick(virtualNow: number, scale: number): boolean;\n /** Called when the animation is cancelled. Skips onDone. */\n onCancel?(): void;\n}\n\nfunction resolveSpringConstants(o: { preset?: string; stiffness?: number; damping?: number; mass?: number }) {\n const preset = o.preset ? SPRING_PRESETS[o.preset as keyof typeof SPRING_PRESETS] : null;\n return {\n stiffness: o.stiffness ?? preset?.stiffness ?? 170,\n damping: o.damping ?? preset?.damping ?? 26,\n mass: o.mass ?? preset?.mass ?? 1,\n };\n}\n\n/** Create the animator for a canvas. One rAF loop drives every animation it\n * owns, and everything still running is cancelled on unmount. */\nexport function useAnimator(opts: UseAnimatorOptions = {}): Animator {\n const optsRef = useLatest(opts);\n const animations = useRef<Map<number, ActiveAnimation>>(new Map());\n const nextId = useRef(1);\n /**\n * Re-entrancy counter incremented around each animation tick in tickAll.\n * Exposed via `isTicking()`. > 0 ⇒ we're currently inside an animation's\n * onTick; an adapter wrapper (`animateOnSetPose`) seeing this flag should\n * write through to the base adapter rather than schedule a new tween.\n */\n const tickDepth = useRef(0);\n /** The timestamp the codec last advanced to. Null after the page was hidden and while nothing\n * runs, so neither gap is charged to the codec; a tween starting then seeds it from `now()`. */\n const codecFrameT = useRef<number | null>(null);\n const globalTimeScale = useRef(1);\n const globalPaused = useRef(false);\n const colorOverrides = useRef<ColorOverrideRegistry>(new ColorOverrideRegistry());\n // Per-frame tick subscribers. Notified after each batch of animation\n // ticks (i.e. after `colorOverrides` has settled to its latest values\n // but before the next RAF schedules). Used by `<SceneCanvas animator>`\n // to request a redraw on every active frame.\n const tickSubscribers = useRef<Set<() => void>>(new Set());\n\n // The loop runs behind the visibility gate. `tickAll` is built inside the\n // memo below, so the frame callback reaches it through a ref, published\n // once the memo's render commits.\n const tickAllRef = useRef<((t: number) => void) | null>(null);\n const frameLoop = useVisibleRaf(\n useCallback((t: number) => { tickAllRef.current?.(t); }, []),\n {\n requestFrame: opts.requestFrame,\n cancelFrame: opts.cancelFrame,\n // An hour spent hidden is not an hour the animation ran: dropping each\n // animation's last timestamp makes the resuming frame's `realDt` zero.\n onResume: () => {\n for (const anim of animations.current.values()) anim.lastRealNow = null;\n codecFrameT.current = null;\n },\n },\n );\n const frameLoopRef = useLatest(frameLoop);\n\n // Tripwire: dev-only flag that every tween/spring/decay's tick reads to\n // detect \"animation fired after the host component unmounted.\" This is a\n // symptom of cleanup not running (regression) — typically because someone\n // refactored useAnimator and forgot to wire the unmount effect. The flag\n // flips false on cleanup; ticks see it and log a one-time error so the\n // bug is loud rather than just visually-doubled animation.\n const mountedRef = useRef(true);\n const trippedRef = useRef(false);\n const tripwire = (): boolean => {\n if (mountedRef.current) return false;\n if (!trippedRef.current) {\n trippedRef.current = true;\n const isDev = typeof process !== 'undefined' ? process.env.NODE_ENV !== 'production' : true;\n if (isDev) {\n console.error(\n 'weasel useAnimator: animation tick fired after the host component unmounted. ' +\n 'This usually means cleanup logic was bypassed — check for refactors that ' +\n 'removed the unmount effect or replaced cancelAll with a custom path.',\n );\n }\n }\n return true;\n };\n\n const { api, tickAll } = useMemo(() => {\n // Default to performance.now() so the time origin matches the\n // requestAnimationFrame callback's DOMHighResTimeStamp argument.\n // Using Date.now() here would mix epoch-millis with page-relative-millis,\n // producing huge negative `elapsed` values that clamp tween `t` to 0\n // forever (never reaching completion).\n const now = (): number =>\n (optsRef.current.now ?? (typeof performance !== 'undefined' ? performance.now.bind(performance) : Date.now))();\n // Resolved timer pair, snapshotted lazily from optsRef on each call so a\n // test that updates the injection after mount still wins. Kept internal —\n // not exposed on the public Animator surface; passed directly into\n // `createStagger` at bind time below.\n const staggerTimers: StaggerTimers = {\n setTimer: (cb, ms) =>\n (optsRef.current.setTimer ?? ((c, m) => setTimeout(c, m)))(cb, ms),\n clearTimer: (h) =>\n (optsRef.current.clearTimer ??\n ((x) => clearTimeout(x as ReturnType<typeof setTimeout>)))(h),\n now,\n };\n\n // Per-id one-shot completion listeners. Used by stagger to detect when\n // each child has left the registry (natural completion OR cancel) so the\n // supervising composite can retire itself when the last child finishes.\n const completionListeners = new Map<number, (() => void)[]>();\n const fireCompletion = (id: number): void => {\n const ls = completionListeners.get(id);\n if (!ls) return;\n completionListeners.delete(id);\n for (const cb of ls) cb();\n };\n const watchCompletion: WatchCompletion = (id, cb) => {\n const ls = completionListeners.get(id) ?? [];\n ls.push(cb);\n completionListeners.set(id, ls);\n return () => {\n const cur = completionListeners.get(id);\n if (!cur) return;\n const idx = cur.indexOf(cb);\n if (idx >= 0) cur.splice(idx, 1);\n if (cur.length === 0) completionListeners.delete(id);\n };\n };\n\n const hub = new AnimatorEventHub();\n const codec = createCodec();\n const infoOf = (a: ActiveAnimation): AnimationInfo => {\n if (!a.info) {\n const info: { -readonly [K in keyof AnimationInfo]: AnimationInfo[K] } = { id: a.id, kind: a.kind };\n if (a.cancelKey != null) info.key = a.cancelKey;\n if (a.label != null) info.label = a.label;\n a.info = info;\n }\n return a.info;\n };\n\n /** Report `id` as finished, ahead of its `onDone`, so whatever that\n * handler starts is heard after it. Nothing revives a primitive; a\n * timeline, which can be revived, is reported as it leaves the table. */\n const reportEnd = (id: number): void => {\n const a = animations.current.get(id);\n if (!a || a.ended) return;\n a.ended = true;\n if (hub.watched) hub.emit({ type: 'end', animation: infoOf(a) });\n };\n\n /** Take `id` off the table as canceled — or, given `by`, as interrupted by\n * the animation claiming its key; given `error`, the caller reports it. */\n const retire = (id: number, by?: ActiveAnimation, error?: true): void => {\n const a = animations.current.get(id);\n if (!a) return;\n a.onCancel?.();\n codec.stop(id);\n animations.current.delete(id);\n fireCompletion(id);\n if (!hub.watched || a.ended || error) return;\n hub.emit(by\n ? { type: 'interrupt', animation: infoOf(a), by: infoOf(by) }\n : { type: 'cancel', animation: infoOf(a) });\n };\n\n const tickAll = (t: number): void => {\n const finished: ActiveAnimation[] = [];\n const threw: [ActiveAnimation, unknown][] = [];\n const frameDt = codecFrameT.current == null ? 0 : Math.max(0, t - codecFrameT.current);\n codecFrameT.current = t;\n codec.frame(frameDt * (globalPaused.current ? 0 : globalTimeScale.current));\n for (const anim of animations.current.values()) {\n // `t` comes from the frame clock; `lastRealNow` is seeded at register()\n // from `now()`. The two share a time origin in a browser, where the rAF\n // timestamp and `performance.now()` are both page-relative — but not\n // everywhere: jsdom starts them ~600ms apart, which made the first\n // frame's delta hugely negative and left `virtualNow` climbing back\n // toward zero for dozens of frames before a tween advanced at all.\n // Time never runs backwards, so a negative sample is never real.\n const realDt = anim.lastRealNow == null ? 0 : Math.max(0, t - anim.lastRealNow);\n anim.lastRealNow = t;\n const scale = globalPaused.current\n ? 0\n : globalTimeScale.current * (anim.paused ? 0 : anim.timeScale);\n anim.virtualNow += realDt * scale;\n // Increment tick depth around each animation's tick so re-entrant\n // calls (e.g. `decay.onTick` → `adapter.setPose` →\n // `animateOnSetPose` checking `isTicking()`) see the flag and\n // skip scheduling a new wrap-tween that would fight the caller.\n tickDepth.current += 1;\n try {\n if (anim.tick(anim.virtualNow, scale)) finished.push(anim);\n } catch (error) {\n threw.push([anim, error]);\n } finally {\n tickDepth.current -= 1;\n }\n }\n for (const [anim, error] of threw) {\n console.error('useAnimator: animation tick threw; retiring it', error);\n if (animations.current.get(anim.id) !== anim) continue;\n // One that ended before throwing (from `onDone`) is finished, not canceled.\n if (anim.ended) {\n animations.current.delete(anim.id);\n fireCompletion(anim.id);\n } else {\n retire(anim.id, undefined, true);\n }\n if (hub.watched) hub.emit({ type: 'error', animation: infoOf(anim), error });\n }\n for (const anim of finished) {\n // Gone already if its own tick canceled it; replaced if something\n // revived it under the same id since.\n if (animations.current.get(anim.id) !== anim) continue;\n reportEnd(anim.id);\n animations.current.delete(anim.id);\n fireCompletion(anim.id);\n }\n // Notify every onTick subscriber AFTER the tick batch so they\n // see the latest `colorOverrides` / pose values. Errors in one\n // subscriber don't suppress the others.\n for (const sub of tickSubscribers.current) {\n try { sub(); } catch (err) { console.error('useAnimator: onTick subscriber threw', err); }\n }\n if (animations.current.size > 0) frameLoopRef.current.request();\n else codecFrameT.current = null;\n };\n\n const ensureLoop = (): void => {\n if (animations.current.size === 0) return;\n frameLoopRef.current.request();\n };\n\n const cancelByKey = (key: string, by?: ActiveAnimation): void => {\n const ids: number[] = [];\n for (const anim of animations.current.values()) {\n if (anim.cancelKey === key) ids.push(anim.id);\n }\n for (const id of ids) retire(id, by);\n };\n\n type AnimationSeed =\n Omit<ActiveAnimation, 'paused' | 'timeScale' | 'virtualNow' | 'lastRealNow'>\n & {\n /** Registers under an existing `cancelKey` without cancelling whoever\n * holds it. For an animation re-registering itself — a revived\n * timeline — which is not a new claim on the key. */\n keepExisting?: boolean;\n };\n /** Gives a codec subject the rate its own pause and time scale now ask for. */\n const rateOf = (a: ActiveAnimation): void => {\n if (codec.has(a.id)) codec.rate(a.id, a.paused ? 0 : a.timeScale);\n };\n\n const register = (seed: AnimationSeed): AnimationHandle => {\n const anim = seed as ActiveAnimation;\n if (seed.cancelKey != null && !seed.keepExisting) cancelByKey(seed.cancelKey, anim);\n anim.paused = false;\n anim.timeScale = 1;\n anim.virtualNow = 0;\n // Seed lastRealNow at registration so the first frame's realDt reflects\n // the gap between register() and the first RAF callback: it places a\n // tween's end, and gives spring/decay a non-zero first dt sample.\n anim.lastRealNow = now();\n animations.current.set(anim.id, anim);\n if (hub.watched) hub.emit({ type: 'start', animation: infoOf(anim) });\n ensureLoop();\n return {\n id: anim.id,\n cancel: () => retire(anim.id),\n pause: () => { const a = animations.current.get(anim.id); if (a) { a.paused = true; rateOf(a); } },\n resume: () => { const a = animations.current.get(anim.id); if (a) { a.paused = false; rateOf(a); } },\n setTimeScale: (s) => { const a = animations.current.get(anim.id); if (a) { a.timeScale = s; rateOf(a); } },\n timeScale: () => animations.current.get(anim.id)?.timeScale ?? 1,\n isPaused: () => animations.current.get(anim.id)?.paused ?? false,\n };\n };\n\n // Supervisor: a registered animation whose tick is a no-op (never\n // finishes naturally) so loop/stagger can sit in the animator's id table\n // and benefit from `cancel`/`cancelKey`/`isActive`. The owning composite\n // (loop/stagger) installs an onCancel to actually tear down its children.\n const createSupervisor = ({ kind, cancelKey, label }: SupervisorOptions): Supervisor => {\n const id = nextId.current++;\n let onCancelCb: (() => void) | undefined;\n const base = register({\n id,\n kind,\n cancelKey,\n label,\n // tick is a no-op: the supervisor only ends when the owner calls\n // `cancel()` (either via animator.cancel, animator.cancelKey, or the\n // composite's natural-completion path which forwards to `cancel`).\n tick: () => false,\n onCancel: () => onCancelCb?.(),\n });\n return {\n id: base.id,\n cancel: base.cancel,\n pause: base.pause,\n resume: base.resume,\n setTimeScale: base.setTimeScale,\n timeScale: base.timeScale,\n isPaused: base.isPaused,\n setOnCancel: (cb) => { onCancelCb = cb; },\n finish: () => {\n if (!animations.current.has(id)) return;\n reportEnd(id);\n animations.current.delete(id);\n fireCompletion(id);\n },\n cancelKey,\n };\n };\n\n const tween = <T,>(o: TweenOptions<T>): AnimationHandle => {\n // blits blends in a straight line, which a caller's own function may not do.\n const fromAxes = o.interpolate || o.interpolator ? null : axesOf(o.from);\n const toAxes = fromAxes && axesOf(o.to);\n const axes = fromAxes && toAxes && toAxes.shape === fromAxes.shape ? fromAxes : null;\n // Refused here rather than on a tick, where a throw would stop every other animation.\n if (!axes && !o.interpolate && !o.interpolator) {\n throw new Error('tween: interpolate or interpolator is required for non-numeric T');\n }\n const id = nextId.current++;\n const easing = resolveEasing(o.easing ?? easeOut);\n // Precedence: factory > per-tick. Factory is built once at tween start so\n // expensive setup (color space conversion etc.) doesn't repeat per frame.\n const factoryFn = o.interpolator ? o.interpolator(o.from, o.to) : null;\n let lastValueEmitted = false;\n // Seeds the codec's clock where `register` seeds the call's, so both charge the same wait.\n if (codecFrameT.current == null) codecFrameT.current = now();\n // Started ahead of `register`, whose `start` listeners may already cancel it.\n const reader = codec.tween({\n id, ms: Math.max(o.ms, 1), ease: easing,\n from: axes ? axes.to(o.from) : [0],\n to: axes ? axes.to(o.to) : [1],\n });\n return register({\n id,\n kind: 'tween',\n cancelKey: o.cancelKey,\n label: o.label,\n progress: (virtualNow) => (o.ms <= 0 ? 1 : Math.min(1, virtualNow / o.ms)),\n // `nowMs` is the call's own virtual time, so it still decides when the tween ends; the codec\n // supplies only the value in between.\n tick(nowMs) {\n if (tripwire()) { codec.stop(id); return true; }\n const t = o.ms <= 0 ? 1 : Math.min(1, nowMs / o.ms);\n let value: T;\n if (axes) {\n value = t >= 1 ? o.to : axes.from(reader.cols, reader.at);\n } else {\n const eased = t >= 1 ? easing(1) : reader.cols[reader.at]!;\n value = factoryFn ? factoryFn(eased) : o.interpolate!(o.from, o.to, eased);\n }\n o.onTick(value);\n if (t >= 1 && !lastValueEmitted) {\n lastValueEmitted = true;\n codec.stop(id);\n // That last onTick may have cancelled us — deregistering the id.\n // A cancelled tween never completes, whenever the cancel landed.\n if (animations.current.has(id)) {\n reportEnd(id);\n o.onDone?.();\n }\n return true;\n }\n return false;\n },\n });\n };\n\n const physics = <T,>(o: PhysicsOptions<T>, kind: AnimationKind = 'physics'): PhysicsHandle<T> => {\n const id = nextId.current++;\n const isNumeric = typeof o.from === 'number';\n if (!isNumeric && (!o.add || !o.subtract || !o.scale || !o.magnitude)) {\n throw new Error('physics: add/subtract/scale/magnitude are required for non-numeric T');\n }\n const add = o.add ?? ((a: T, b: T) => ((a as unknown as number) + (b as unknown as number)) as unknown as T);\n const subtract = o.subtract ?? ((a: T, b: T) => ((a as unknown as number) - (b as unknown as number)) as unknown as T);\n const scale = o.scale ?? ((v: T, k: number) => ((v as unknown as number) * k) as unknown as T);\n const magnitude = o.magnitude ?? ((v: T) => Math.abs(v as unknown as number));\n const { stiffness: kBase, damping, mass } = resolveSpringConstants(o);\n const restThreshold = o.restThreshold ?? 0.01;\n\n let target: T | null = o.to ?? null;\n let value = o.from;\n // Default to zero velocity: assumes scale(_, 0) returns the zero vector of T. Pass an explicit velocity for unusual T where this isn't true.\n let velocity: T = o.velocity ?? scale(o.from, 0);\n let lastTime: number | null = null;\n\n // blits' closed forms need positive damping and mass, and a spring with a target needs\n // stiffness; decay's handle never takes a target.\n const solvable = damping > 0 && mass > 0 && (kBase > 0 || kind === 'decay');\n const fromAxes = solvable ? axesOf(o.from) : null;\n const sameShape = (v: T | null | undefined): boolean => v == null || axesOf(v)?.shape === fromAxes!.shape;\n const axes = fromAxes && sameShape(o.to) && sameShape(o.velocity) ? fromAxes : null;\n let reader: SpringReader | null = null;\n if (axes) {\n // Seeds the codec's clock where `register` seeds the call's, so both charge the same wait.\n if (codecFrameT.current == null) codecFrameT.current = now();\n // Started ahead of `register`, whose `start` listeners may already cancel it.\n reader = codec.spring({\n id, axes: axes.count,\n from: axes.to(o.from),\n to: o.to == null ? null : axes.to(o.to),\n velocity: o.velocity == null ? new Array<number>(axes.count).fill(0) : axes.to(o.velocity),\n stiffness: kBase, damping, mass,\n });\n }\n\n const baseHandle = register({\n id,\n kind,\n cancelKey: o.cancelKey,\n label: o.label,\n tick(nowMs) {\n if (tripwire()) { codec.stop(id); return true; }\n if (lastTime == null) {\n lastTime = nowMs;\n // Already-at-rest short-circuit: decay-mode (target == null)\n // with starting velocity below threshold should complete\n // immediately rather than emit a tick and wait a frame.\n if (target == null && magnitude(velocity) < restThreshold) {\n codec.stop(id);\n reportEnd(id);\n o.onDone?.();\n return true;\n }\n // The codec's voice has run since registration, so only Euler starts its clock here.\n if (!axes) {\n o.onTick(value);\n return false;\n }\n }\n if (axes) {\n const m = reader!.motion();\n value = axes.from(m.value);\n velocity = axes.from(m.velocity);\n } else {\n // Semi-implicit Euler, for a T blits cannot move as axes, or constants its closed forms can't solve.\n const dt = Math.min(0.064, (nowMs - lastTime) / 1000);\n const next = stepSpring({ add, subtract, scale }, value, velocity, target, kBase, damping, mass, dt);\n value = next.value;\n velocity = next.velocity;\n }\n lastTime = nowMs;\n o.onTick(value);\n const velRested = magnitude(velocity) < restThreshold;\n const posRested = target == null\n ? true\n : magnitude(subtract(value, target)) < restThreshold;\n if (velRested && posRested) {\n if (target != null) o.onTick(target);\n codec.stop(id);\n reportEnd(id);\n o.onDone?.();\n return true;\n }\n return false;\n },\n });\n\n const checkShape = (v: T, what: string): void => {\n if (!sameShape(v)) throw new Error(`physics: ${what} is not the same shape as \\`from\\``);\n };\n const handle: PhysicsHandle<T> = {\n ...baseHandle,\n setTarget: (newTo: T | null) => {\n if (axes && newTo != null) checkShape(newTo, 'setTarget');\n target = newTo;\n if (axes && codec.has(id)) codec.retarget(id, newTo == null ? null : axes.to(newTo));\n },\n setVelocity: (v: T) => {\n if (axes) checkShape(v, 'setVelocity');\n velocity = v;\n if (axes && codec.has(id)) codec.push(id, axes.to(v));\n },\n };\n return handle;\n };\n\n const spring = <T,>(o: SpringOptions<T>): AnimationHandle => physics<T>(o, 'spring');\n\n const decay = <T,>(o: DecayOptions<T>): AnimationHandle => {\n const friction = o.friction ?? 0.95;\n // Per-second friction v(t) = v0 * friction^t corresponds to\n // m*dv/dt = -c*v with c = -ln(friction), m = 1, k = 0.\n const damping = -Math.log(friction);\n return physics<T>({\n from: o.from,\n to: null,\n velocity: o.velocity,\n stiffness: 0,\n damping,\n mass: 1,\n restThreshold: o.threshold ?? 0.5,\n add: o.add,\n // DecayOptions doesn't carry subtract; derive from add+scale.\n subtract: (a, b) => o.add(a, o.scale(b, -1)),\n scale: o.scale,\n magnitude: o.magnitude,\n onTick: o.onTick,\n onDone: o.onDone,\n cancelKey: o.cancelKey,\n label: o.label,\n }, 'decay');\n };\n\n const cancelAll = (): void => {\n const retired: ActiveAnimation[] = [];\n for (const a of animations.current.values()) {\n a.onCancel?.();\n codec.stop(a.id);\n retired.push(a);\n }\n animations.current.clear();\n codecFrameT.current = null;\n for (const a of retired) fireCompletion(a.id);\n if (hub.watched) for (const a of retired) hub.emit({ type: 'cancel', animation: infoOf(a) });\n frameLoopRef.current.cancel();\n };\n const api: Animator = {\n tween,\n spring,\n decay,\n physics,\n cancel: (handle) => retire(handle.id),\n cancelKey: (key) => cancelByKey(key),\n cancelAll,\n isActive: (key) => {\n if (key == null) return animations.current.size > 0;\n for (const a of animations.current.values()) {\n if (a.cancelKey === key) return true;\n }\n return false;\n },\n isTicking: () => tickDepth.current > 0,\n pause: () => { globalPaused.current = true; },\n resume: () => { globalPaused.current = false; },\n isPaused: () => globalPaused.current,\n setTimeScale: (s) => { globalTimeScale.current = s; },\n timeScale: () => globalTimeScale.current,\n pauseKey: (key) => {\n for (const a of animations.current.values()) if (a.cancelKey === key) { a.paused = true; rateOf(a); }\n },\n resumeKey: (key) => {\n for (const a of animations.current.values()) if (a.cancelKey === key) { a.paused = false; rateOf(a); }\n },\n setTimeScaleByKey: (key, s) => {\n for (const a of animations.current.values()) if (a.cancelKey === key) { a.timeScale = s; rateOf(a); }\n },\n loop: (factory, loopOpts) => createLoop(createSupervisor, factory, loopOpts),\n tweenLoop: (tweenLoopOpts) =>\n createTweenLoop(api, createSupervisor, tweenLoopOpts),\n stagger: ((items, delay, factory, staggerOpts) =>\n createStagger(\n api,\n staggerTimers,\n createSupervisor,\n watchCompletion,\n items,\n delay,\n factory as never,\n staggerOpts,\n )) as Animator['stagger'],\n timeline: (o: TimelineOptions) => {\n const id = nextId.current++;\n const info = (): AnimationInfo | undefined => {\n const a = animations.current.get(id);\n return a && infoOf(a);\n };\n return createTimeline(register, id, o, {\n get watched() { return hub.watched; },\n fire: (track, path, event, lateBy) => {\n const animation = info();\n if (animation) hub.emit({ type: 'fire', animation, track, path: path.slice(), event, lateBy });\n },\n lap: (lap) => {\n const animation = info();\n if (animation) hub.emit({ type: 'lap', animation, lap });\n },\n });\n },\n colorOverrides: colorOverrides.current,\n onTick: (cb) => {\n tickSubscribers.current.add(cb);\n return () => { tickSubscribers.current.delete(cb); };\n },\n keepAlive: () => {\n const sup = createSupervisor({ kind: 'keepAlive' });\n return () => sup.cancel();\n },\n watch: (listener) => hub.add(listener),\n live: () => {\n const rows: LiveAnimation[] = [];\n for (const a of animations.current.values()) {\n const row: LiveAnimation = {\n ...infoOf(a),\n paused: a.paused,\n timeScale: a.timeScale,\n elapsed: a.virtualNow,\n ...(a.progress ? { progress: a.progress(a.virtualNow) } : {}),\n };\n rows.push(row);\n }\n return rows;\n },\n };\n return { api, tickAll };\n }, [frameLoopRef, optsRef]);\n\n useInsertionEffect(() => {\n tickAllRef.current = tickAll;\n }, [tickAll]);\n\n // StrictMode-safe cleanup: when the component unmounts (including the\n // dev-mode double-mount that StrictMode performs), cancel every running\n // animation and stop the RAF loop. Without this, the FIRST mount's\n // animator keeps ticking with stale callbacks pointing at the unmounted\n // adapter, while the SECOND mount creates its own animator on top —\n // visible to the user as every animation playing twice.\n useEffect(() => {\n const overrides = colorOverrides.current;\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n api.cancelAll();\n overrides.clearAll();\n };\n }, [api]);\n\n return api;\n}\n"],"mappings":"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"}
|
|
@@ -2950,6 +2950,9 @@ interface LiveAnimation extends AnimationInfo {
|
|
|
2950
2950
|
* - `cancel` — stopped by its handle, `cancel`, `cancelKey` or `cancelAll`.
|
|
2951
2951
|
* - `interrupt` — stopped because `by` claimed its `cancelKey`. Delivered
|
|
2952
2952
|
* before `by`'s `start`.
|
|
2953
|
+
* - `error` — its tick threw (an `onTick`, `onDone` or interpolator), so it was
|
|
2954
|
+
* taken off the table, after the frame's other animations ticked. In place of
|
|
2955
|
+
* `cancel`, or after `end` when `onDone` threw. The error is also logged.
|
|
2953
2956
|
* - `lap` — a looping timeline wrapped; `lap` counts wraps since it started.
|
|
2954
2957
|
* - `fire` — an event on a timeline's event track was crossed, at any depth.
|
|
2955
2958
|
* `path` indexes from the root timeline's `tracks()` down through each
|
|
@@ -2962,6 +2965,10 @@ type AnimatorEvent = {
|
|
|
2962
2965
|
readonly type: 'interrupt';
|
|
2963
2966
|
readonly animation: AnimationInfo;
|
|
2964
2967
|
readonly by: AnimationInfo;
|
|
2968
|
+
} | {
|
|
2969
|
+
readonly type: 'error';
|
|
2970
|
+
readonly animation: AnimationInfo;
|
|
2971
|
+
readonly error: unknown;
|
|
2965
2972
|
} | {
|
|
2966
2973
|
readonly type: 'lap';
|
|
2967
2974
|
readonly animation: AnimationInfo;
|
package/dist/core/scene/scene.js
CHANGED
|
@@ -687,6 +687,12 @@ function d(o) {
|
|
|
687
687
|
recordEntry(e, t, n) {
|
|
688
688
|
x.recordEntry(e, t, n), z();
|
|
689
689
|
},
|
|
690
|
+
prune(e) {
|
|
691
|
+
x.prune(e), z();
|
|
692
|
+
},
|
|
693
|
+
switchBranch(e) {
|
|
694
|
+
x.switchBranch(e), z();
|
|
695
|
+
},
|
|
690
696
|
restore: (e) => {
|
|
691
697
|
$.restoreHistory(e);
|
|
692
698
|
},
|
|
@@ -695,6 +701,9 @@ function d(o) {
|
|
|
695
701
|
undoDepth: () => x.undoDepth(),
|
|
696
702
|
redoDepth: () => x.redoDepth(),
|
|
697
703
|
entries: () => x.entries(),
|
|
704
|
+
timestampAt: (e) => x.timestampAt(e),
|
|
705
|
+
depthAt: (e) => x.depthAt(e),
|
|
706
|
+
branches: () => x.branches(),
|
|
698
707
|
getVersion: () => x.getVersion(),
|
|
699
708
|
subscribe: (e) => x.subscribe(e),
|
|
700
709
|
serialize: () => x.serialize(),
|