@cardstack/choreo 0.0.0 → 0.1.0-unstable.0

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.
Files changed (165) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -0
  3. package/README.md +55 -6
  4. package/addon-main.cjs +4 -0
  5. package/declarations/anchors.d.ts +26 -0
  6. package/declarations/anchors.d.ts.map +1 -0
  7. package/declarations/arming.d.ts +33 -0
  8. package/declarations/arming.d.ts.map +1 -0
  9. package/declarations/beacon.d.ts +9 -0
  10. package/declarations/beacon.d.ts.map +1 -0
  11. package/declarations/beacons.d.ts +23 -0
  12. package/declarations/beacons.d.ts.map +1 -0
  13. package/declarations/changeset.d.ts +46 -0
  14. package/declarations/changeset.d.ts.map +1 -0
  15. package/declarations/choreo.d.ts +261 -0
  16. package/declarations/choreo.d.ts.map +1 -0
  17. package/declarations/compile.d.ts +45 -0
  18. package/declarations/compile.d.ts.map +1 -0
  19. package/declarations/deliver.d.ts +44 -0
  20. package/declarations/deliver.d.ts.map +1 -0
  21. package/declarations/easings.d.ts +20 -0
  22. package/declarations/easings.d.ts.map +1 -0
  23. package/declarations/far.d.ts +33 -0
  24. package/declarations/far.d.ts.map +1 -0
  25. package/declarations/film/clip.d.ts +51 -0
  26. package/declarations/film/clip.d.ts.map +1 -0
  27. package/declarations/film/clips.d.ts +155 -0
  28. package/declarations/film/clips.d.ts.map +1 -0
  29. package/declarations/film/film.d.ts +1208 -0
  30. package/declarations/film/film.d.ts.map +1 -0
  31. package/declarations/film/graph/adjust.d.ts +112 -0
  32. package/declarations/film/graph/adjust.d.ts.map +1 -0
  33. package/declarations/film/graph/compile.d.ts +140 -0
  34. package/declarations/film/graph/compile.d.ts.map +1 -0
  35. package/declarations/film/graph/host.d.ts +67 -0
  36. package/declarations/film/graph/host.d.ts.map +1 -0
  37. package/declarations/film/graph/nodes.d.ts +287 -0
  38. package/declarations/film/graph/nodes.d.ts.map +1 -0
  39. package/declarations/film/index.d.ts +24 -0
  40. package/declarations/film/index.d.ts.map +1 -0
  41. package/declarations/film/joins.d.ts +143 -0
  42. package/declarations/film/joins.d.ts.map +1 -0
  43. package/declarations/film/math.d.ts +15 -0
  44. package/declarations/film/math.d.ts.map +1 -0
  45. package/declarations/film/overlays.d.ts +54 -0
  46. package/declarations/film/overlays.d.ts.map +1 -0
  47. package/declarations/film/picture.d.ts +104 -0
  48. package/declarations/film/picture.d.ts.map +1 -0
  49. package/declarations/film/plate.d.ts +37 -0
  50. package/declarations/film/plate.d.ts.map +1 -0
  51. package/declarations/film/player.d.ts +120 -0
  52. package/declarations/film/player.d.ts.map +1 -0
  53. package/declarations/film/rail.d.ts +40 -0
  54. package/declarations/film/rail.d.ts.map +1 -0
  55. package/declarations/film/schedule.d.ts +93 -0
  56. package/declarations/film/schedule.d.ts.map +1 -0
  57. package/declarations/film/seam.d.ts +38 -0
  58. package/declarations/film/seam.d.ts.map +1 -0
  59. package/declarations/film/titles.d.ts +37 -0
  60. package/declarations/film/titles.d.ts.map +1 -0
  61. package/declarations/film/types.d.ts +544 -0
  62. package/declarations/film/types.d.ts.map +1 -0
  63. package/declarations/film.d.ts +3 -0
  64. package/declarations/film.d.ts.map +1 -0
  65. package/declarations/gesture.d.ts +33 -0
  66. package/declarations/gesture.d.ts.map +1 -0
  67. package/declarations/index.d.ts +26 -0
  68. package/declarations/index.d.ts.map +1 -0
  69. package/declarations/measure.d.ts +29 -0
  70. package/declarations/measure.d.ts.map +1 -0
  71. package/declarations/path.d.ts +73 -0
  72. package/declarations/path.d.ts.map +1 -0
  73. package/declarations/registry.d.ts +46 -0
  74. package/declarations/registry.d.ts.map +1 -0
  75. package/declarations/run.d.ts +406 -0
  76. package/declarations/run.d.ts.map +1 -0
  77. package/declarations/space.d.ts +31 -0
  78. package/declarations/space.d.ts.map +1 -0
  79. package/declarations/steps.d.ts +479 -0
  80. package/declarations/steps.d.ts.map +1 -0
  81. package/declarations/test-support/index.d.ts +30 -0
  82. package/declarations/test-support/index.d.ts.map +1 -0
  83. package/declarations/types.d.ts +761 -0
  84. package/declarations/types.d.ts.map +1 -0
  85. package/dist/anchors.js +34 -0
  86. package/dist/anchors.js.map +1 -0
  87. package/dist/arming.js +120 -0
  88. package/dist/arming.js.map +1 -0
  89. package/dist/beacon.js +25 -0
  90. package/dist/beacon.js.map +1 -0
  91. package/dist/beacons.js +77 -0
  92. package/dist/beacons.js.map +1 -0
  93. package/dist/changeset.js +129 -0
  94. package/dist/changeset.js.map +1 -0
  95. package/dist/choreo.js +1026 -0
  96. package/dist/choreo.js.map +1 -0
  97. package/dist/compile.js +1403 -0
  98. package/dist/compile.js.map +1 -0
  99. package/dist/deliver.js +326 -0
  100. package/dist/deliver.js.map +1 -0
  101. package/dist/easings.js +39 -0
  102. package/dist/easings.js.map +1 -0
  103. package/dist/far.js +147 -0
  104. package/dist/far.js.map +1 -0
  105. package/dist/film/clip.js +100 -0
  106. package/dist/film/clip.js.map +1 -0
  107. package/dist/film/clips.js +147 -0
  108. package/dist/film/clips.js.map +1 -0
  109. package/dist/film/film.js +4424 -0
  110. package/dist/film/film.js.map +1 -0
  111. package/dist/film/graph/adjust.js +160 -0
  112. package/dist/film/graph/adjust.js.map +1 -0
  113. package/dist/film/graph/compile.js +225 -0
  114. package/dist/film/graph/compile.js.map +1 -0
  115. package/dist/film/graph/host.js +77 -0
  116. package/dist/film/graph/host.js.map +1 -0
  117. package/dist/film/graph/nodes.js +500 -0
  118. package/dist/film/graph/nodes.js.map +1 -0
  119. package/dist/film/index.js +18 -0
  120. package/dist/film/index.js.map +1 -0
  121. package/dist/film/joins.js +260 -0
  122. package/dist/film/joins.js.map +1 -0
  123. package/dist/film/math.js +49 -0
  124. package/dist/film/math.js.map +1 -0
  125. package/dist/film/overlays.js +66 -0
  126. package/dist/film/overlays.js.map +1 -0
  127. package/dist/film/picture.js +58 -0
  128. package/dist/film/picture.js.map +1 -0
  129. package/dist/film/plate.js +36 -0
  130. package/dist/film/plate.js.map +1 -0
  131. package/dist/film/player.js +79 -0
  132. package/dist/film/player.js.map +1 -0
  133. package/dist/film/rail.js +38 -0
  134. package/dist/film/rail.js.map +1 -0
  135. package/dist/film/schedule.js +238 -0
  136. package/dist/film/schedule.js.map +1 -0
  137. package/dist/film/seam.js +64 -0
  138. package/dist/film/seam.js.map +1 -0
  139. package/dist/film/titles.js +45 -0
  140. package/dist/film/titles.js.map +1 -0
  141. package/dist/film/types.js +2 -0
  142. package/dist/film/types.js.map +1 -0
  143. package/dist/film.js +18 -0
  144. package/dist/film.js.map +1 -0
  145. package/dist/gesture.js +111 -0
  146. package/dist/gesture.js.map +1 -0
  147. package/dist/index.js +9 -0
  148. package/dist/index.js.map +1 -0
  149. package/dist/measure.js +99 -0
  150. package/dist/measure.js.map +1 -0
  151. package/dist/path.js +272 -0
  152. package/dist/path.js.map +1 -0
  153. package/dist/registry.js +55 -0
  154. package/dist/registry.js.map +1 -0
  155. package/dist/run.js +2423 -0
  156. package/dist/run.js.map +1 -0
  157. package/dist/space.js +57 -0
  158. package/dist/space.js.map +1 -0
  159. package/dist/steps.js +831 -0
  160. package/dist/steps.js.map +1 -0
  161. package/dist/test-support/index.js +150 -0
  162. package/dist/test-support/index.js.map +1 -0
  163. package/dist/types.js +2 -0
  164. package/dist/types.js.map +1 -0
  165. package/package.json +202 -6
@@ -0,0 +1 @@
1
+ {"version":3,"file":"measure.d.ts","sourceRoot":"","sources":["../src/measure.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAW/C,0BAA0B;AAC1B,eAAO,MAAM,IAAI,GAAI,GAAG,OAAO,KAAG,IAKhC,CAAC;AAEH,iEAAiE;AACjE,eAAO,MAAM,KAAK,GAAI,GAAG,OAAO,EAAE,GAAG,OAAO,KAAG,IAK7C,CAAC;AAEH,qEAAqE;AACrE,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,OAAO,CAAC;IACZ,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;GAKG;AACH,eAAO,MAAM,MAAM,GAAI,IAAI,OAAO,KAAG,OAAO,GAAG,SAY9C,CAAC;AAeF,gFAAgF;AAChF,eAAO,MAAM,SAAS,GAAI,IAAI,OAAO,KAAG,OAKb,CAAC;AAE5B,eAAO,MAAM,OAAO,GAAI,IAAI,OAAO,KAAG,QAWpC,CAAC;AAEH,iEAAiE;AACjE,eAAO,MAAM,QAAQ,GAAI,MAAM,QAAQ,EAAE,MAAM,OAAO,KAAG,MAMvD,CAAC;AAEH,oEAAoE;AACpE,eAAO,MAAM,aAAa,GAAI,IAAI,OAAO,EAAE,MAAM,OAAO,KAAG,MAC9B,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * THE CAMERA'S PATH — the arithmetic behind `c.Camera3D @through`, and
3
+ * the only place in Choreo that owns a curve rather than a tween.
4
+ *
5
+ * Everything here is a pure function of PROGRESS. That is the whole
6
+ * point: a seek must land the shot exactly where playing there would, so
7
+ * nothing in this file may remember a previous frame. A spline that is
8
+ * sampled rather than integrated can be scrubbed, rendered a frame at a
9
+ * time, and played, and all three agree by construction.
10
+ */
11
+ import type { Camera3DState, Camera3DWaypoint } from './types.ts';
12
+ /**
13
+ * Sample the spline at overall progress p ∈ [0, 1] (uniform segments).
14
+ *
15
+ * SPLICES (docs/choreo-splices.md): a waypoint marked `cut` starts a new
16
+ * SHOT. Each shot is a clamped spline of its own points — endpoint
17
+ * tangents one-sided, so no shot's velocity crosses a seam — and each
18
+ * shot's window runs from its first slot to the next seam, its points
19
+ * spread uniformly across it. The outgoing shot therefore plays through
20
+ * the seam instant (its motion stretches by one slot rather than
21
+ * parking), the incoming one begins exactly on it, and the sampled pose
22
+ * is a step function at the seam. Waypoints keep their uniform slots, so
23
+ * cues anchored to waypoint moments keep their clock. A cut on the first
24
+ * waypoint drops the pose-in-force seed: the score opens inside its
25
+ * first shot.
26
+ */
27
+ export declare function sampleThrough(from: Camera3DState, through: Camera3DWaypoint[], progress: number, tension?: number): Camera3DState;
28
+ /**
29
+ * A SETTLE — the operator's second hand, written as a function of time.
30
+ *
31
+ * A cardinal spline crosses its waypoints with continuous velocity but
32
+ * not continuous acceleration: at every control point the curvature
33
+ * steps, and the eye reads that step as a tick. The usual cure is a
34
+ * spring chasing the pose, which works and costs the two things a
35
+ * seekable engine cannot pay — it remembers the last frame, so a scrub
36
+ * lands somewhere a play would not, and it lags, so the camera is always
37
+ * behind the score by however much smoothing it was given.
38
+ *
39
+ * This is the same cure without either cost: the reported pose is a
40
+ * Hann-weighted average of the SAME spline sampled around the current
41
+ * progress. Averaging a curve is a low-pass filter, and a Hann window
42
+ * kills the acceleration steps outright, so the result is a hand rather
43
+ * than a mechanism. Being centred, it has no lag — it reads slightly
44
+ * ahead of the score exactly as much as it reads behind. Being an
45
+ * average of one pure function, it is still a pure function: play,
46
+ * scrub and frame-by-frame render all report the same pose.
47
+ *
48
+ * TWO EDGES IT MUST NOT CROSS. A cut is a step in the pose on purpose,
49
+ * and an average that straddled it would smear the cut into a very fast
50
+ * pan. The window is therefore TAPERED to the shot the progress is in:
51
+ * near either edge the kernel shrinks to the room it has, reaching zero
52
+ * at the edge itself. So a cut stays a cut, a path still lands exactly
53
+ * on its last waypoint, and the pose handed forward to the next cue is
54
+ * the waypoint rather than an average of one — the filter is an identity
55
+ * at every boundary and a smoother everywhere else.
56
+ *
57
+ * The taper is `tanh`, not a `min`, and the difference is the whole
58
+ * reason it works. A hard `min(width, 2 × room)` has a corner in it
59
+ * where the two branches meet, and a filter whose width has a corner
60
+ * puts one back into what it filters: measured against a path with two
61
+ * right-angle corners in it, the hard taper LOST ground as the window
62
+ * widened (worst jerk 8.7e-4 at a window of 0.175, 2.5e-3 at 0.3) while
63
+ * the smooth one held 8.0e-4 at every width against 4.2e-3 unfiltered.
64
+ * `tanh(x) ≤ x` everywhere, which is what keeps the taps inside the
65
+ * shot; it is smooth, which is what keeps the tick out.
66
+ *
67
+ * `width` is in progress, not seconds: the kinks being filtered are at
68
+ * the waypoints, which are spread uniformly across the clock, so a
69
+ * window measured against the clock is a window measured against the
70
+ * spacing of the things it exists to smooth. The caller converts.
71
+ */
72
+ export declare function settleThrough(from: Camera3DState, through: Camera3DWaypoint[], progress: number, tension: number | undefined, width: number, taps?: number): Camera3DState;
73
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAmHlE;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,MAAM,GACf,aAAa,CAwCf;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB,EAAE,EAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GAAG,SAAS,EAC3B,KAAK,EAAE,MAAM,EACb,IAAI,SAAK,GACR,aAAa,CA0Df"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * A region is a participant host (glimmer-motion/participant): its root
3
+ * renders `data-motion-host` beside `data-choreo`, and registering a region
4
+ * here registers it as that element's participant host too, so the {{motion}}
5
+ * elements inside join it. The lookups below are Choreo's own, for code that
6
+ * already speaks in regions.
7
+ */
8
+ import { type ParticipantHost } from 'glimmer-motion';
9
+ import type { ChoreoRun } from './run.ts';
10
+ import type { ChoreoNode, TimelineNode } from './types.ts';
11
+ declare module 'glimmer-motion/participant' {
12
+ interface ParticipantArgs {
13
+ /**
14
+ * How Choreo measures this element for a shape-matched flight.
15
+ * `'box'` (default) is the layout border box — right for plates, cards,
16
+ * stages. `'content'` is the shrink-wrap (the ink): a full-bleed title
17
+ * still matches as a word. Written as `data-choreo-pack`; an explicit
18
+ * `[data-choreo-substance]` descendant still wins.
19
+ */
20
+ pack?: 'box' | 'content';
21
+ }
22
+ }
23
+ /** anything that can put a node on a region's timeline — a step component, or a lane from outside */
24
+ export interface ChoreoProvider {
25
+ node(): TimelineNode;
26
+ }
27
+ export interface ChoreoHost extends ParticipantHost {
28
+ /** a destroyed participant asks whether the region still needs its element; true → the region unmounts it later */
29
+ claim(node: ChoreoNode): boolean;
30
+ /**
31
+ * SPIKE (Lane): a provider from OUTSIDE the region's markup — a parent's
32
+ * lane addressed at this region — whose node joins the tree the region
33
+ * collects on every pass, after its own steps. Returns the remover.
34
+ */
35
+ contribute(provider: ChoreoProvider): () => void;
36
+ /** the run the region is playing or holding, for an attachment to drive; null between runs */
37
+ currentRun(): ChoreoRun | null;
38
+ register(node: ChoreoNode): () => void;
39
+ }
40
+ export declare function setChoreoHost(el: Element, host: ChoreoHost | undefined): void;
41
+ export declare function closestChoreo(el: Element): ChoreoHost | undefined;
42
+ /** the host of a region element itself (not an ancestor's) */
43
+ export declare function choreoHostAt(el: Element): ChoreoHost | undefined;
44
+ /** the host of the region rendered with `@id` — a lane's way of naming the region it plays in */
45
+ export declare function choreoHostById(id: string): ChoreoHost | undefined;
46
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,gBAAgB,CAAC;AAE1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAK3D,OAAO,QAAQ,4BAA4B,CAAC;IAC1C,UAAU,eAAe;QACvB;;;;;;WAMG;QACH,IAAI,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;KAC1B;CACF;AAED,qGAAqG;AACrG,MAAM,WAAW,cAAc;IAC7B,IAAI,IAAI,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,UAAW,SAAQ,eAAe;IACjD,mHAAmH;IACnH,KAAK,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IACjC;;;;OAIG;IACH,UAAU,CAAC,QAAQ,EAAE,cAAc,GAAG,MAAM,IAAI,CAAC;IACjD,8FAA8F;IAC9F,UAAU,IAAI,SAAS,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,IAAI,CAAC;CACxC;AAMD,wBAAgB,aAAa,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,GAAG,SAAS,QAkBtE;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAGjE;AAED,8DAA8D;AAC9D,wBAAgB,YAAY,CAAC,EAAE,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAEhE;AAED,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAEjE"}
@@ -0,0 +1,406 @@
1
+ import type { Camera3DState, CameraState, ChoreoNode, Compiled, Cue, PerformCommand, Sprite } from './types.ts';
2
+ /** how fast each value was moving, in units per second, keyed by element then property */
3
+ export type Velocities = Map<HTMLElement, Map<string, number>>;
4
+ export interface Run {
5
+ /** open the gate the run is parked at; mid-segment, complete the segment and park (§4.1) */
6
+ advance(): void;
7
+ /** stop everything; removed sprites are released unless a next run is keeping them (`keep`) */
8
+ cancel(keep?: Set<ChoreoNode>): void;
9
+ cues: Cue[];
10
+ /** the run's full length in seconds at 1×, gates included */
11
+ readonly duration: number;
12
+ finished: Promise<void>;
13
+ /** nothing left to play: the run completed or was cancelled */
14
+ isDone(): boolean;
15
+ /**
16
+ * The sprites this run is DRIVING through space right now — an
17
+ * unfinished move/spring/tween writing geometry — with each cue's
18
+ * transition. A replacement pass reads this to complete its score: a
19
+ * flying sprite the new score does not name gets a continuation move
20
+ * instead of a one-frame release to rest (§3.1).
21
+ */
22
+ midflight(): Map<ChoreoNode, Record<string, unknown> | undefined>;
23
+ /** standing at a gate, waiting for advance() — a still, and settled */
24
+ readonly parked: boolean;
25
+ pause(): void;
26
+ /**
27
+ * The run is not advancing itself: paused, parked at a gate, or otherwise
28
+ * held. Its clock belongs to whoever stopped it.
29
+ *
30
+ * A held run keeps writing: inline width, height and transform stay on
31
+ * every sprite it owns, so the geometry the page reports is the run's
32
+ * rather than the stylesheet's. Anything deciding whether the world has
33
+ * changed by measuring it has to know not to trust what it sees.
34
+ */
35
+ readonly paused: boolean;
36
+ play(): void;
37
+ /** a pass measured and decided to keep this run: put the picture back */
38
+ reassert(): void;
39
+ /** put every element this run has touched back to its resting layout NOW */
40
+ releaseForMeasure(): void;
41
+ /**
42
+ * One build backwards — Keynote's rule. Land PARKED at the previous
43
+ * gate with everything ahead re-closed, and HOLD: a retreat never
44
+ * plays, never self-opens a @delay gate, and the next advance() replays
45
+ * the un-built segment forward. False when nothing stands behind the
46
+ * clock (the caller falls through to whatever "back" means one level
47
+ * out — an outer run, the previous slide).
48
+ */
49
+ retreat(): boolean;
50
+ /** which gate-bounded segment the clock is in */
51
+ readonly segment: number;
52
+ /** playback rate: 1 is normal, 0.5 half, as Motion's controls */
53
+ speed: number;
54
+ /**
55
+ * This run has no end of its own: its score is nothing but OPEN steps, so
56
+ * it holds them — drawing its wires, keeping its holds — until it is
57
+ * cancelled or replaced. A standing run is SETTLED, not in flight: there
58
+ * is nothing to wait for, and `finished` will not resolve until a cancel.
59
+ */
60
+ readonly standing: boolean;
61
+ /** the clock, in seconds at 1× — settable; setting it across a gate parks there */
62
+ time: number;
63
+ /** what every driven value was doing at the moment of interruption */
64
+ velocities: Velocities;
65
+ }
66
+ interface RunOptions {
67
+ /** where the region's frame stands as this run begins */
68
+ camera?: CameraState;
69
+ /** where the SHOT stands as this run begins — a 3D host's own pose */
70
+ camera3d?: Camera3DState;
71
+ /** the aim point the prior run left applied — see ChoreoRun.cameraAim */
72
+ cameraAim?: {
73
+ x: number;
74
+ y: number;
75
+ } | null;
76
+ /** the element the camera transform drives (the region's scene wrapper) */
77
+ cameraFrame?: HTMLElement;
78
+ /**
79
+ * Nothing in this region is staying — every participant it can see is a
80
+ * leaver. See the note in `park`: it decides whether a gate this run stops
81
+ * at is a gate anybody could still open.
82
+ */
83
+ doomed?: boolean;
84
+ inherit?: Velocities;
85
+ /** a camera step landed or the run ended: the frame's new resting state */
86
+ onCamera?(state: CameraState): void;
87
+ /**
88
+ * The 3D shot moved. Called every frame a `c.Camera3D` cue changes the
89
+ * pose — including on a scrub, because the pose is sampled from the
90
+ * score rather than remembered from playback. Choreo has no renderer of
91
+ * its own; this is where the host's does the drawing.
92
+ */
93
+ onCamera3D?(state: Camera3DState): void;
94
+ /**
95
+ * A `c.Perform` command entered the folded set: dispatch it (§C4).
96
+ * Deferred past the render pass, in time order, once per fold entry.
97
+ */
98
+ onPerform?(command: PerformCommand): void;
99
+ /**
100
+ * The folded set shrank — the clock moved to before a command the host
101
+ * already holds. Reset commanded state; the remaining prefix is
102
+ * re-dispatched, in order, immediately after.
103
+ */
104
+ onPerformReset?(): void;
105
+ onSpriteDone(sprite: Sprite): void;
106
+ /** the region's elevated layer, where c.Raise promotes the living */
107
+ raisedLayer?: HTMLElement;
108
+ removed: Sprite[];
109
+ /** the svg the tethers draw into */
110
+ tetherLayer?: SVGSVGElement;
111
+ }
112
+ export declare class ChoreoRun implements Run {
113
+ cues: Cue[];
114
+ velocities: Velocities;
115
+ finished: Promise<void>;
116
+ private master;
117
+ private playing;
118
+ private parkedAt;
119
+ private rate;
120
+ private readonly scale;
121
+ readonly standing: boolean;
122
+ private readonly total;
123
+ private readonly gates;
124
+ private tracks;
125
+ private readonly rowEnd;
126
+ private released;
127
+ private pending;
128
+ private readonly options;
129
+ private borrowedValues;
130
+ /** rest is what releaseForMeasure jumps to: 0 for translates, 1 for scales, 'none' for clips */
131
+ private movedValues;
132
+ /** what the last releaseForMeasure retired, so a kept pass can put it back */
133
+ private retired;
134
+ private owned;
135
+ private cancelled;
136
+ private ended;
137
+ private resolveFinished;
138
+ private ticking;
139
+ private autoTimer;
140
+ constructor(compiled: Compiled, options: RunOptions);
141
+ get duration(): number;
142
+ get paused(): boolean;
143
+ get time(): number;
144
+ set time(seconds: number);
145
+ get speed(): number;
146
+ set speed(rate: number);
147
+ get segment(): number;
148
+ get parked(): boolean;
149
+ /**
150
+ * ATTACH: write each attached region's clock from this one's.
151
+ *
152
+ * Several windows may name one region — a film's every beat has a plate
153
+ * window, and the plate is one region re-keyed per beat — so the run
154
+ * resolves ONE governing window per region on every evaluate: the window
155
+ * that holds `now`; else the latest past one, if it holds; else the
156
+ * earliest future one, which stands the child at its head (Remotion's
157
+ * premount: mounted early, clock frozen at `in`). The child's run is
158
+ * paused and told `in + (now − start) × rate`. No history is kept on
159
+ * either side, which is what makes a seek into a window land where
160
+ * playing there would.
161
+ */
162
+ private driveAttachments;
163
+ /** does this run's score integrate — a spring, a follow — so that its state is its history? */
164
+ hasIntegrator(): boolean;
165
+ isDone(): boolean;
166
+ midflight(): Map<ChoreoNode, Record<string, unknown> | undefined>;
167
+ pause(): void;
168
+ play(): void;
169
+ advance(): void;
170
+ retreat(): boolean;
171
+ private startTicking;
172
+ private stopTicking;
173
+ private tick;
174
+ private park;
175
+ private finish;
176
+ private setPaused;
177
+ private seekTo;
178
+ /**
179
+ * The one cost WAAPI acceleration charges a scrubbable run: a finished
180
+ * accelerated animation commits its finals asynchronously, and that
181
+ * commit can land AFTER a still's jump and overwrite it. So a still is
182
+ * re-asserted on the two frames after it is entered — by then any
183
+ * pending commit has landed, and the computed frame wins again.
184
+ */
185
+ private restillPending;
186
+ private scheduleRestill;
187
+ private restill;
188
+ private evaluate;
189
+ /** perform tracks whose commands the host currently holds (see foldPerforms) */
190
+ private performed;
191
+ /** dispatches queued for after the render pass, in fold order */
192
+ private pendingPerforms;
193
+ private performFlushBooked;
194
+ /**
195
+ * The command fold (§C4): the set of Perform cues at or before the
196
+ * clock IS the commanded state. Every evaluate — a play tick and a seek
197
+ * alike — re-derives the eligible set; growth dispatches the new
198
+ * commands in time order, and any shrink (a backward seek) resets the
199
+ * host first and replays the whole remaining prefix. Commands are
200
+ * idempotent statements of state by contract (`lamp.on`, never a
201
+ * toggle), which is exactly what makes the replay a re-derivation.
202
+ *
203
+ * Dispatches are DEFERRED past the render pass: the constructor's first
204
+ * evaluate runs while Glimmer may still be rendering, and a command
205
+ * exists to mutate application state. A reset collapses the queue — the
206
+ * dropped dispatches were never seen, and the replay that follows
207
+ * restates everything still standing.
208
+ */
209
+ private foldPerforms;
210
+ /**
211
+ * Stand rewound tracks back on their origins — the part of a backward
212
+ * seek that must be ORDERED. A sprite with sequential cues has one
213
+ * origin per cue, each equal to the previous cue's landing; restored
214
+ * in track order they clobber forward and the sprite ends up standing
215
+ * on its LAST future cue's origin (the Playhead demo's hand parked on
216
+ * 'place' after a scrub to zero; its receipt refusing to dismiss). So:
217
+ * latest-first, which leaves the EARLIEST future cue's origin — the
218
+ * value the timeline actually holds at `now` — standing; and a key
219
+ * that any track AT or BEFORE `now` writes is not touched at all,
220
+ * because that track's own sample or landing is the answer.
221
+ */
222
+ private rewind;
223
+ /** the eased progress of a plain clock-driven track */
224
+ private flightlessProgress;
225
+ /**
226
+ * The orbit pose in force. Public for the same reason `camera` is: it is
227
+ * hand-off state, and a replacement run must continue from where this
228
+ * one left the shot rather than snapping back to the framing.
229
+ */
230
+ camera3d: Camera3DState;
231
+ private readonly initial3d;
232
+ camera: CameraState;
233
+ /**
234
+ * The aim point P in force, local px. With transform-origin pinned at
235
+ * 0 0, the applied transform is translate(x + (1−z)·P) scale(z) — the
236
+ * frame's centre cancels out of the algebra entirely, so neither a
237
+ * board that reflows mid-cue nor a stage that changes height between
238
+ * cues can move the picture: the formula reads no live DOM at all.
239
+ * z = 1 is the identity for any P. Public because it is hand-off state:
240
+ * the next run lerps from the point THIS run left aimed, exactly as it
241
+ * inherits the camera.
242
+ */
243
+ cameraAim: {
244
+ x: number;
245
+ y: number;
246
+ } | null;
247
+ /**
248
+ * The absolute pose a camera cue lands on, resolved against the pose it
249
+ * starts from. Absolute fields pass through; missing fields hold; a
250
+ * relative cue (Pan / SlowZoom) offsets and multiplies the pose in
251
+ * force — which is why resolution happens AT START (live) or during the
252
+ * prefix fold (reconstruction), never at compile.
253
+ */
254
+ private static resolveCameraTo;
255
+ private cameraProgress;
256
+ /**
257
+ * The camera and aim this run inherited, frozen at construction — the
258
+ * fold origin every reconstruction starts from. Public because a
259
+ * replacement run that re-executes the SAME score must inherit this
260
+ * origin, not the pose in force: the pose in force is what the score's
261
+ * prefix already produced, and folding the prefix from it applies every
262
+ * relative cue twice (the world-dock law).
263
+ */
264
+ readonly initialCamera: CameraState;
265
+ readonly initialAim: {
266
+ x: number;
267
+ y: number;
268
+ } | null;
269
+ /**
270
+ * Rebuild the camera fold from the score prefix before a seek's still
271
+ * (notes/external-clock-camera-seek-handoff.md). Forward playback folds
272
+ * each camera cue's landing into the run's cumulative camera as the
273
+ * clock crosses it — but a random-access seek can jump clean over a
274
+ * window, and a cue that never starts never folds: the clock reads `t`
275
+ * while the picture holds an earlier shot. So every camera track's
276
+ * bookkeeping (started, cameraFrom, aimFrom/aimTo, cameraP) is
277
+ * re-derived here in timeline order from the run's initial camera;
278
+ * evaluate() then recomputes exactly the numbers forward playback would
279
+ * have produced, and play-after-scrub resumes from them. Pure
280
+ * arithmetic over frozen numbers, like the rest of the camera: no DOM
281
+ * is read, so backward and repeated seeks agree to the pixel.
282
+ */
283
+ private reconstructCameraAt;
284
+ /**
285
+ * The damped counter-scale (§6.4): steady sprites scale with the host but
286
+ * not 1:1 — pow(z, .30) zoomed out so they stay readable, pow(z, .70)
287
+ * zoomed in so they don't feel stuck, clamped to what the eye tolerates.
288
+ */
289
+ private static damped;
290
+ /**
291
+ * The frame's APPLIED transform for a camera state at aim progress `p`.
292
+ *
293
+ * Transform-origin is pinned at 0 0, so the applied transform is
294
+ * translate(x + (1−z)·P) scale(z) with P the lerped aim point — pure
295
+ * arithmetic over frozen numbers. Nothing here reads the DOM, so a board
296
+ * that reflows mid-cue cannot move the camera, and every boundary
297
+ * (landing, re-aim, next run) agrees to the pixel. At z = 1 the aim term
298
+ * vanishes: an unpanned camera is EXACTLY the identity.
299
+ */
300
+ private appliedCamera;
301
+ private static cameraCss;
302
+ /**
303
+ * Fly the region's frame on the platform: two transform keyframes and the
304
+ * eased clock pre-sampled into a linear() easing. The biggest layer in the
305
+ * region composites off the main thread for the whole move.
306
+ */
307
+ private startCameraAnimation;
308
+ /**
309
+ * Retire the frame's platform animation and hand the picture back to
310
+ * inline style, written from the shadow state — so a cancel mid-zoom
311
+ * freezes exactly where the eye was, and a landing holds its final.
312
+ */
313
+ private dropCameraAnimation;
314
+ private applyCamera;
315
+ private tetherDrawScheduled;
316
+ private scheduleTetherDraw;
317
+ /**
318
+ * One frame of a derived value (§4.10): compose the context from the
319
+ * pass's measurements, hand it to the author's function, write what
320
+ * comes back.
321
+ *
322
+ * Nothing here touches the DOM — that is the design, not an
323
+ * optimisation (docs/postmortem-follow.md). The resting boxes were
324
+ * measured by the pass with every moved value released, and a source's
325
+ * `now` is its resting box composed with the motion values driving it
326
+ * this frame: JS-side numbers, not a measurement. So a follower is pure
327
+ * BY CONSTRUCTION — there is no live box in reach, it cannot read back
328
+ * its own output, and it cannot force a style recalculation in the
329
+ * middle of a move. It is also correct under INTERRUPTION for free: a
330
+ * replacement run's pass re-measures, so a run born mid-flight computes
331
+ * from rests that are right immediately, with no "last frame" to
332
+ * disagree with.
333
+ *
334
+ * `set`, not an animation: a derived value IS the frame, so there is
335
+ * nothing to interpolate toward and nothing the compositor could be
336
+ * given — this is the main-thread cost the step charges, and the reason
337
+ * it is the same cost `c.Tether` already pays.
338
+ */
339
+ private drive;
340
+ /** the window closed (or was scrubbed out of): put the declared rest back */
341
+ private restDerived;
342
+ private drawTether;
343
+ /**
344
+ * The scale between the layer's own pixels and the screen's, per axis.
345
+ *
346
+ * A promotion reads client rects and writes LOCAL pixels, and every
347
+ * transform above the region — a camera zoom, a page crossing carrying the
348
+ * whole scene, any ancestor with a scale on it — sits between the two. Read
349
+ * off the layer itself: its rect is what the screen shows, its offset size
350
+ * is what its own coordinate system calls that. Dividing by the camera zoom
351
+ * alone would catch the region's own transform and miss everything outside
352
+ * it, which is the double-scale the tether draw already dodges by mapping
353
+ * through the screen CTM.
354
+ */
355
+ private static layerScale;
356
+ private promote;
357
+ private restore;
358
+ private startScroll;
359
+ private stopScroll;
360
+ /** stop a track's animations at the value level — an async animation
361
+ * cancelled before it resolves stays 'idle' forever if only the controls
362
+ * are stopped, and its value then reads as animating for good */
363
+ private stopTrack;
364
+ /** land a cue's end values without ever having played it */
365
+ private jumpFinals;
366
+ private startTrack;
367
+ /** put the sprite at progress `p` of its sampled flight path (§4.4) */
368
+ private applyFlight;
369
+ /** the eased progress a flight sits at, `ms` into its window */
370
+ private flightProgress;
371
+ /**
372
+ * The sampled path as platform keyframes: each point becomes a transform,
373
+ * uniformly spaced (the points were sampled uniformly in progress), and
374
+ * the eased clock rides the animation's easing instead of per-frame JS.
375
+ */
376
+ private flightKeyframes;
377
+ private startFlight;
378
+ /** compute one still frame of a cue and jump the values onto the element */
379
+ private sampleStill;
380
+ private completeTrack;
381
+ private pinStarts;
382
+ private sampleVelocities;
383
+ releaseForMeasure(): void;
384
+ /**
385
+ * A pass measured this run's world at rest and then decided to KEEP the
386
+ * run — but the measurement itself was destructive: releaseForMeasure
387
+ * cancels platform animations, returns borrowed values, and jumps every
388
+ * moved value to rest, and a MotionValue.jump() STOPS the animation
389
+ * driving it. Left like that, a kept run keeps its clock and its landing
390
+ * but loses its picture: the flight freezes at rest until the finals
391
+ * land — which on a busy page (the gallery: neighbours re-pass the
392
+ * region every render) is every crossing, every time. So the keep path
393
+ * calls this: moved and borrowed values are stood back where they were,
394
+ * their bookkeeping is re-registered, every in-flight track's animation
395
+ * is retired so evaluate re-enters it — the machinery a scrub-then-play
396
+ * already uses — and the re-entered animations are seeked back onto the
397
+ * run's own clock, so a keep is invisible rather than a restart.
398
+ */
399
+ reassert(): void;
400
+ cancel(keep?: Set<ChoreoNode>): void;
401
+ }
402
+ /** every live run, for the test helpers that drive gates and clocks */
403
+ export declare const activeRuns: Set<ChoreoRun>;
404
+ export declare function execute(compiled: Compiled, options: RunOptions): ChoreoRun;
405
+ export {};
406
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The coordinate contract (docs/planes-and-cameras.md).
3
+ *
4
+ * A plane's camera is pure arithmetic over frozen numbers: with
5
+ * transform-origin pinned at 0 0, the applied transform is
6
+ * `translate(x + (1−z)·P) scale(z)` for aim point P (§6.3). Because it
7
+ * is arithmetic, it is invertible WITHOUT reading the DOM — and these
8
+ * two inverses are the whole compositor ⇄ plane-local ⇄ viewport
9
+ * conversion: cross-plane flights, cross-plane hit testing, and
10
+ * eventually cross-plane drag all reduce to them.
11
+ *
12
+ * A plane that scrolls adds its scroll offset to the same arithmetic —
13
+ * the one place a DOM read (the scroll position) legitimately enters,
14
+ * read once per conversion, never per frame.
15
+ */
16
+ import type { CameraState, Rect } from './types.ts';
17
+ export interface PlanePoint {
18
+ x: number;
19
+ y: number;
20
+ }
21
+ /**
22
+ * The translate the camera actually applies at aim point `aim` — the
23
+ * same algebra `applyCamera` paints with. At z = 1 the aim term
24
+ * vanishes: an unpanned camera is exactly the identity.
25
+ */
26
+ export declare function appliedCamera(cam: CameraState, aim?: PlanePoint): PlanePoint;
27
+ /** plane-local box → page space, through the plane's camera and scroll */
28
+ export declare function toPage(local: Rect, cam: CameraState, aim?: PlanePoint, scroll?: PlanePoint): Rect;
29
+ /** page-space box → the plane's local space: `(page − applied)/z + scroll` */
30
+ export declare function toLocal(page: Rect, cam: CameraState, aim?: PlanePoint, scroll?: PlanePoint): Rect;
31
+ //# sourceMappingURL=space.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space.d.ts","sourceRoot":"","sources":["../src/space.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAID;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,GAAG,EAAE,WAAW,EAChB,GAAG,GAAE,UAAmB,GACvB,UAAU,CAKZ;AAED,0EAA0E;AAC1E,wBAAgB,MAAM,CACpB,KAAK,EAAE,IAAI,EACX,GAAG,EAAE,WAAW,EAChB,GAAG,GAAE,UAAmB,EACxB,MAAM,GAAE,UAAmB,GAC1B,IAAI,CAQN;AAED,8EAA8E;AAC9E,wBAAgB,OAAO,CACrB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,WAAW,EAChB,GAAG,GAAE,UAAmB,EACxB,MAAM,GAAE,UAAmB,GAC1B,IAAI,CAQN"}