Reactive signals
One nested writable state bag whose individual leaves can be animated independently.
class PlaybackPanel extends Actor {
playback = reactiveSignal({
currentTime: 0,
selection: { start: 0, end: 0 },
markers: [{ frame: 30, label: "Beat" }],
});
}Every nested field becomes a reactive scalar with its own set, tween and transition.
The shape is authored once; the leaves move on their own schedules.
Reading and writing leaves
// Read
this.playback.currentTime();
this.playback.selection.start();
// Write immediately
this.playback.currentTime.set(120);
// Tween one leaf
yield* this.playback.currentTime.tween(240, 0.5);Arrays
Reactive arrays expose structural methods alongside the scalar ones:
this.playback.markers.push({ frame: 60, label: "Drop" });
this.playback.markers.replaceAt(0, { frame: 15, label: "Intro" });
this.playback.markers.removeAt(0);Root transition
When several fields move together as one logical change, transition from the root rather than tweening leaves in parallel. The whole bag becomes a single authored event.
yield* this.playback.transition(
(progress, from) => ({
...from,
currentTime: lerp(from.currentTime, 240, progress),
selection: { start: 0, end: lerp(from.selection.end, 240, progress) },
}),
0.4,
);Write rules
- Disjoint same-frame writes compose. Two writes to different paths at the same frame both land.
- Same-path same-frame animated writes fail loudly. Two animations competing for one leaf at one frame is ambiguous, so the runtime raises rather than picking a winner. That is intentional: a silent last-write-wins would make the ambiguity invisible until a seek produced the other answer.
Do not use it for
| Instead of | Use |
|---|---|
| Flat scalars like opacity or a label | signal |
| Pure computations | derived |
| Cross-actor coordination or semantic intent | events |
| A collection that always moves as one change | signal<T[]> with transition |
One bag, not many
reactiveSignal is for one nested app-local model — a playback state, a form model, a
structured collection. An actor with three of them is usually an actor that should have
been split, or flat signals grouped with group.