@velumo/runtime 0.1.0-beta.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 (63) hide show
  1. package/dist/action-dispatcher.d.ts +27 -0
  2. package/dist/action-dispatcher.d.ts.map +1 -0
  3. package/dist/action-dispatcher.js +34 -0
  4. package/dist/action-dispatcher.js.map +1 -0
  5. package/dist/camera.d.ts +51 -0
  6. package/dist/camera.d.ts.map +1 -0
  7. package/dist/camera.js +327 -0
  8. package/dist/camera.js.map +1 -0
  9. package/dist/controller.d.ts +33 -0
  10. package/dist/controller.d.ts.map +1 -0
  11. package/dist/controller.js +109 -0
  12. package/dist/controller.js.map +1 -0
  13. package/dist/cue-dispatcher.d.ts +76 -0
  14. package/dist/cue-dispatcher.d.ts.map +1 -0
  15. package/dist/cue-dispatcher.js +164 -0
  16. package/dist/cue-dispatcher.js.map +1 -0
  17. package/dist/hash.d.ts +8 -0
  18. package/dist/hash.d.ts.map +1 -0
  19. package/dist/hash.js +27 -0
  20. package/dist/hash.js.map +1 -0
  21. package/dist/index.d.ts +13 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +13 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/notes.d.ts +32 -0
  26. package/dist/notes.d.ts.map +1 -0
  27. package/dist/notes.js +132 -0
  28. package/dist/notes.js.map +1 -0
  29. package/dist/registry.d.ts +32 -0
  30. package/dist/registry.d.ts.map +1 -0
  31. package/dist/registry.js +76 -0
  32. package/dist/registry.js.map +1 -0
  33. package/dist/scene-player.d.ts +40 -0
  34. package/dist/scene-player.d.ts.map +1 -0
  35. package/dist/scene-player.js +177 -0
  36. package/dist/scene-player.js.map +1 -0
  37. package/dist/spatial.d.ts +11 -0
  38. package/dist/spatial.d.ts.map +1 -0
  39. package/dist/spatial.js +28 -0
  40. package/dist/spatial.js.map +1 -0
  41. package/dist/theme-bundle.d.ts +32 -0
  42. package/dist/theme-bundle.d.ts.map +1 -0
  43. package/dist/theme-bundle.js +8 -0
  44. package/dist/theme-bundle.js.map +1 -0
  45. package/dist/timeline.d.ts +46 -0
  46. package/dist/timeline.d.ts.map +1 -0
  47. package/dist/timeline.js +217 -0
  48. package/dist/timeline.js.map +1 -0
  49. package/dist/tsconfig.tsbuildinfo +1 -0
  50. package/package.json +19 -0
  51. package/src/action-dispatcher.ts +81 -0
  52. package/src/camera.ts +513 -0
  53. package/src/controller.ts +171 -0
  54. package/src/cue-dispatcher.ts +299 -0
  55. package/src/hash.ts +39 -0
  56. package/src/index.ts +12 -0
  57. package/src/notes.ts +194 -0
  58. package/src/registry.ts +194 -0
  59. package/src/scene-player.ts +244 -0
  60. package/src/spatial.ts +40 -0
  61. package/src/theme-bundle.ts +35 -0
  62. package/src/timeline.ts +323 -0
  63. package/tsconfig.json +10 -0
@@ -0,0 +1,40 @@
1
+ import type { CameraEasing, CameraStop, Cue } from "@velumo/core";
2
+ import { type ResolvedView } from "./spatial.js";
3
+ export type ScenePlayerDirection = "forward" | "backward";
4
+ export type ScenePlayerMove = "moved" | "exhausted";
5
+ export type ScenePlayerEventName = "camera:move" | "cue:fired" | "stop:enter";
6
+ export interface ScenePlayerCameraMoveEvent {
7
+ readonly type: "camera:move";
8
+ readonly view: ResolvedView;
9
+ readonly durationMs: number;
10
+ readonly easing: CameraEasing;
11
+ }
12
+ export interface ScenePlayerCueFiredEvent {
13
+ readonly type: "cue:fired";
14
+ readonly cue: Cue;
15
+ readonly stopIndex: number;
16
+ }
17
+ export interface ScenePlayerStopEnterEvent {
18
+ readonly type: "stop:enter";
19
+ readonly stopIndex: number;
20
+ }
21
+ export type ScenePlayerEvent = ScenePlayerCameraMoveEvent | ScenePlayerCueFiredEvent | ScenePlayerStopEnterEvent;
22
+ export type ScenePlayerEventHandler = (event: ScenePlayerEvent) => void;
23
+ export interface ScenePlayerOptions {
24
+ readonly stops: readonly CameraStop[];
25
+ readonly reducedMotion?: boolean;
26
+ }
27
+ export declare class ScenePlayer {
28
+ #private;
29
+ constructor(options: ScenePlayerOptions);
30
+ enter(direction: ScenePlayerDirection): void;
31
+ advance(): ScenePlayerMove;
32
+ back(): ScenePlayerMove;
33
+ tick(deltaMs: number): void;
34
+ getView(): ResolvedView;
35
+ getStopIndex(): number;
36
+ on(eventName: ScenePlayerEventName, handler: ScenePlayerEventHandler): () => void;
37
+ isIdle(): boolean;
38
+ }
39
+ export declare function createScenePlayer(options: ScenePlayerOptions): ScenePlayer;
40
+ //# sourceMappingURL=scene-player.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-player.d.ts","sourceRoot":"","sources":["../src/scene-player.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAc,GAAG,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,KAAK,YAAY,EAAe,MAAM,cAAc,CAAC;AAO9D,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,UAAU,CAAC;AAC1D,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,WAAW,CAAC;AAEpD,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAE9E,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,gBAAgB,GACxB,0BAA0B,GAC1B,wBAAwB,GACxB,yBAAyB,CAAC;AAE9B,MAAM,MAAM,uBAAuB,GAAG,CAAC,KAAK,EAAE,gBAAgB,KAAK,IAAI,CAAC;AAExE,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;CAClC;AAgBD,qBAAa,WAAW;;gBAaV,OAAO,EAAE,kBAAkB;IAKvC,KAAK,CAAC,SAAS,EAAE,oBAAoB,GAAG,IAAI;IAQ5C,OAAO,IAAI,eAAe;IAS1B,IAAI,IAAI,eAAe;IASvB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAgB3B,OAAO,IAAI,YAAY;IAIvB,YAAY,IAAI,MAAM;IAItB,EAAE,CACA,SAAS,EAAE,oBAAoB,EAC/B,OAAO,EAAE,uBAAuB,GAC/B,MAAM,IAAI;IA4Bb,MAAM,IAAI,OAAO;CAmFlB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAE1E"}
@@ -0,0 +1,177 @@
1
+ import { resolveView } from "./spatial.js";
2
+ import { TimelineScheduler } from "./timeline.js";
3
+ const DEFAULT_DURATION_MS = 800;
4
+ const DEFAULT_EASING = "ease-in-out";
5
+ const FINALIZE_SEEK_MS = Number.MAX_SAFE_INTEGER;
6
+ function isCameraView(value) {
7
+ if (typeof value !== "object" || value === null) {
8
+ return false;
9
+ }
10
+ const v = value;
11
+ if (!Number.isFinite(v.x) || !Number.isFinite(v.y)) {
12
+ return false;
13
+ }
14
+ if (v.zoom !== undefined && !Number.isFinite(v.zoom)) {
15
+ return false;
16
+ }
17
+ return true;
18
+ }
19
+ export class ScenePlayer {
20
+ #stops;
21
+ #reducedMotion;
22
+ #handlers = new Map();
23
+ #stopIndex = -1;
24
+ #view = { x: 0, y: 0, zoom: 1 };
25
+ #timeline;
26
+ #timelineCueCount = 0;
27
+ #elapsedSinceLand = 0;
28
+ constructor(options) {
29
+ this.#stops = options.stops;
30
+ this.#reducedMotion = options.reducedMotion ?? false;
31
+ }
32
+ enter(direction) {
33
+ const index = direction === "forward" ? 0 : this.#stops.length - 1;
34
+ this.#land(index);
35
+ if (direction === "backward") {
36
+ this.#finalizeTimeline();
37
+ }
38
+ }
39
+ advance() {
40
+ if (this.#stopIndex >= this.#stops.length - 1) {
41
+ return "exhausted";
42
+ }
43
+ this.#finalizeTimeline();
44
+ this.#land(this.#stopIndex + 1);
45
+ return "moved";
46
+ }
47
+ back() {
48
+ if (this.#stopIndex <= 0) {
49
+ return "exhausted";
50
+ }
51
+ this.#land(this.#stopIndex - 1);
52
+ this.#finalizeTimeline();
53
+ return "moved";
54
+ }
55
+ tick(deltaMs) {
56
+ if (this.#timeline !== undefined && deltaMs > 0) {
57
+ this.#timeline.advance(deltaMs);
58
+ }
59
+ this.#elapsedSinceLand += deltaMs;
60
+ const stop = this.#stops[this.#stopIndex];
61
+ if (stop !== undefined &&
62
+ stop.hold !== undefined &&
63
+ this.#elapsedSinceLand >= stop.hold &&
64
+ this.#stopIndex < this.#stops.length - 1) {
65
+ this.advance();
66
+ }
67
+ }
68
+ getView() {
69
+ return this.#view;
70
+ }
71
+ getStopIndex() {
72
+ return this.#stopIndex;
73
+ }
74
+ on(eventName, handler) {
75
+ let handlers = this.#handlers.get(eventName);
76
+ if (handlers === undefined) {
77
+ handlers = new Set();
78
+ this.#handlers.set(eventName, handlers);
79
+ }
80
+ handlers.add(handler);
81
+ return () => {
82
+ handlers.delete(handler);
83
+ };
84
+ }
85
+ #land(index) {
86
+ const stop = this.#stops[index];
87
+ if (stop === undefined) {
88
+ return;
89
+ }
90
+ this.#stopIndex = index;
91
+ this.#elapsedSinceLand = 0;
92
+ this.#view = resolveView(stop.camera);
93
+ this.#emitCameraMove(stop.transition?.duration, stop.transition?.easing);
94
+ this.#emit({ type: "stop:enter", stopIndex: index });
95
+ this.#startTimeline(stop);
96
+ if (this.#reducedMotion) {
97
+ this.#finalizeTimeline();
98
+ }
99
+ }
100
+ isIdle() {
101
+ if (this.#stopIndex === -1) {
102
+ return true;
103
+ }
104
+ // Unfired cues remain: timeline exists and has not yet fired all cues.
105
+ if (this.#timeline !== undefined) {
106
+ const fired = this.#timeline.getState().firedCueIndices.length;
107
+ if (fired < this.#timelineCueCount) {
108
+ return false;
109
+ }
110
+ }
111
+ // Hold pending: not on the last stop and elapsed has not reached the hold.
112
+ const stop = this.#stops[this.#stopIndex];
113
+ if (stop !== undefined &&
114
+ stop.hold !== undefined &&
115
+ this.#stopIndex < this.#stops.length - 1 &&
116
+ this.#elapsedSinceLand < stop.hold) {
117
+ return false;
118
+ }
119
+ return true;
120
+ }
121
+ #startTimeline(stop) {
122
+ const cues = stop.cues ?? [];
123
+ if (cues.length === 0) {
124
+ this.#timeline = undefined;
125
+ this.#timelineCueCount = 0;
126
+ return;
127
+ }
128
+ const timeline = new TimelineScheduler({ cues, initialPlaying: true });
129
+ timeline.on("cue:fired", (event) => {
130
+ if (event.type !== "cue:fired") {
131
+ return;
132
+ }
133
+ this.#handleCue(event.cue);
134
+ });
135
+ this.#timeline = timeline;
136
+ this.#timelineCueCount = cues.length;
137
+ }
138
+ #finalizeTimeline() {
139
+ if (this.#timeline === undefined) {
140
+ return;
141
+ }
142
+ // Seek far beyond any cue time: every not-yet-fired cue fires now,
143
+ // applying its end-state, so a press mid-sequence leaves state consistent.
144
+ this.#timeline.advance(FINALIZE_SEEK_MS);
145
+ this.#timeline = undefined;
146
+ this.#timelineCueCount = 0;
147
+ }
148
+ #handleCue(cue) {
149
+ if (cue.action.type === "camera" && isCameraView(cue.action.payload)) {
150
+ this.#view = resolveView(cue.action.payload);
151
+ this.#emitCameraMove(undefined, undefined);
152
+ return;
153
+ }
154
+ this.#emit({ type: "cue:fired", cue, stopIndex: this.#stopIndex });
155
+ }
156
+ #emitCameraMove(duration, easing) {
157
+ this.#emit({
158
+ type: "camera:move",
159
+ view: this.#view,
160
+ durationMs: this.#reducedMotion ? 0 : (duration ?? DEFAULT_DURATION_MS),
161
+ easing: easing ?? DEFAULT_EASING,
162
+ });
163
+ }
164
+ #emit(event) {
165
+ const handlers = this.#handlers.get(event.type);
166
+ if (handlers === undefined) {
167
+ return;
168
+ }
169
+ for (const handler of [...handlers]) {
170
+ handler(event);
171
+ }
172
+ }
173
+ }
174
+ export function createScenePlayer(options) {
175
+ return new ScenePlayer(options);
176
+ }
177
+ //# sourceMappingURL=scene-player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scene-player.js","sourceRoot":"","sources":["../src/scene-player.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { CameraEasing, CameraView } from "@velumo/core";
2
+ import { type EasingFunction } from "./timeline.js";
3
+ export declare const CAMERA_EASINGS: readonly CameraEasing[];
4
+ export declare function resolveEasing(name: CameraEasing | undefined): EasingFunction;
5
+ export interface ResolvedView {
6
+ readonly x: number;
7
+ readonly y: number;
8
+ readonly zoom: number;
9
+ }
10
+ export declare function resolveView(view: CameraView): ResolvedView;
11
+ //# sourceMappingURL=spatial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial.d.ts","sourceRoot":"","sources":["../src/spatial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,EAAE,KAAK,cAAc,EAAkB,MAAM,eAAe,CAAC;AAEpE,eAAO,MAAM,cAAc,EAAE,SAAS,YAAY,EAMjD,CAAC;AAkBF,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,SAAS,GAAG,cAAc,CAE5E;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,YAAY,CAE1D"}
@@ -0,0 +1,28 @@
1
+ import { easeInOutCubic } from "./timeline.js";
2
+ export const CAMERA_EASINGS = [
3
+ "linear",
4
+ "ease",
5
+ "ease-in",
6
+ "ease-out",
7
+ "ease-in-out",
8
+ ];
9
+ function easeIn(t) {
10
+ return t * t;
11
+ }
12
+ function easeOut(t) {
13
+ return 1 - (1 - t) * (1 - t);
14
+ }
15
+ const EASING_MAP = {
16
+ linear: (t) => t,
17
+ ease: easeInOutCubic,
18
+ "ease-in": easeIn,
19
+ "ease-out": easeOut,
20
+ "ease-in-out": easeInOutCubic,
21
+ };
22
+ export function resolveEasing(name) {
23
+ return name === undefined ? easeInOutCubic : EASING_MAP[name];
24
+ }
25
+ export function resolveView(view) {
26
+ return { x: view.x, y: view.y, zoom: view.zoom ?? 1 };
27
+ }
28
+ //# sourceMappingURL=spatial.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spatial.js","sourceRoot":"","sources":["../src/spatial.ts"],"names":[],"mappings":"AACA,OAAO,EAAuB,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpE,MAAM,CAAC,MAAM,cAAc,GAA4B;IACrD,QAAQ;IACR,MAAM;IACN,SAAS;IACT,UAAU;IACV,aAAa;CACd,CAAC;AAEF,SAAS,MAAM,CAAC,CAAS;IACvB,OAAO,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,GAAyC;IACvD,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAChB,IAAI,EAAE,cAAc;IACpB,SAAS,EAAE,MAAM;IACjB,UAAU,EAAE,OAAO;IACnB,aAAa,EAAE,cAAc;CAC9B,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,IAA8B;IAC1D,OAAO,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAChE,CAAC;AAQD,MAAM,UAAU,WAAW,CAAC,IAAgB;IAC1C,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC;AACxD,CAAC"}
@@ -0,0 +1,32 @@
1
+ import type { Theme } from "@velumo/core";
2
+ import type { VelumoPlugin } from "./registry.js";
3
+ /**
4
+ * A theme bundle is a heterogeneous container: it carries plugin factories
5
+ * whose internal renderer/action context types it deliberately does not track.
6
+ * Plugins are loosely coupled at registration — the registry stores renderers
7
+ * keyed by layer type and enforces context-correctness there — so the bundle
8
+ * uses `any` for the plugin generics to stay ergonomic for any host.
9
+ */
10
+ type AnyVelumoPlugin = VelumoPlugin<any, any, any>;
11
+ /**
12
+ * A host-side convenience that pairs a theme with everything it needs to run:
13
+ * its theme tokens, its CSS, and a factory for the plugins it depends on. A
14
+ * theme package can export one `ThemeBundle` so an author wires a single import
15
+ * instead of three (theme + css + plugin).
16
+ *
17
+ * Plugins stay explicit and host-controlled: the bundle only *carries* a plugin
18
+ * factory — the host still calls it and registers the result. The runtime never
19
+ * auto-loads plugins from a manifest or config reference.
20
+ */
21
+ export interface ThemeBundle {
22
+ readonly theme: Theme;
23
+ readonly css?: string;
24
+ readonly createPlugins?: () => readonly AnyVelumoPlugin[];
25
+ }
26
+ /**
27
+ * Resolve a bundle's plugins. Returns a fresh array (empty when the bundle
28
+ * brings no plugins) so the result is safe for the host to register directly.
29
+ */
30
+ export declare function themePlugins(bundle: ThemeBundle): readonly AnyVelumoPlugin[];
31
+ export {};
32
+ //# sourceMappingURL=theme-bundle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-bundle.d.ts","sourceRoot":"","sources":["../src/theme-bundle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;;GAMG;AACH,KAAK,eAAe,GAAG,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEnD;;;;;;;;;GASG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,SAAS,eAAe,EAAE,CAAC;CAC3D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS,eAAe,EAAE,CAE5E"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Resolve a bundle's plugins. Returns a fresh array (empty when the bundle
3
+ * brings no plugins) so the result is safe for the host to register directly.
4
+ */
5
+ export function themePlugins(bundle) {
6
+ return bundle.createPlugins?.() ?? [];
7
+ }
8
+ //# sourceMappingURL=theme-bundle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-bundle.js","sourceRoot":"","sources":["../src/theme-bundle.ts"],"names":[],"mappings":"AA4BA;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAmB;IAC9C,OAAO,MAAM,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC;AACxC,CAAC"}
@@ -0,0 +1,46 @@
1
+ import type { Cue } from "@velumo/core";
2
+ export type TimelineEventName = "cue:fired" | "scene:end" | "state:change";
3
+ export interface TimelineCueFiredEvent {
4
+ readonly type: "cue:fired";
5
+ readonly timeMs: number;
6
+ readonly cueIndex: number;
7
+ readonly cue: Cue;
8
+ }
9
+ export interface TimelineSceneEndEvent {
10
+ readonly type: "scene:end";
11
+ readonly timeMs: number;
12
+ }
13
+ export interface TimelineStateChangeEvent {
14
+ readonly type: "state:change";
15
+ readonly state: TimelineState;
16
+ }
17
+ export type TimelineEvent = TimelineCueFiredEvent | TimelineSceneEndEvent | TimelineStateChangeEvent;
18
+ export type TimelineEventHandler<E extends TimelineEvent = TimelineEvent> = (event: E) => void;
19
+ export interface TimelineState {
20
+ readonly timeMs: number;
21
+ readonly isPlaying: boolean;
22
+ readonly firedCueIndices: readonly number[];
23
+ readonly sceneEnded: boolean;
24
+ }
25
+ export interface TimelineSchedulerOptions {
26
+ readonly cues?: readonly Cue[];
27
+ readonly duration?: number;
28
+ readonly initialTimeMs?: number;
29
+ readonly initialPlaying?: boolean;
30
+ }
31
+ export declare class TimelineScheduler {
32
+ #private;
33
+ constructor(options?: TimelineSchedulerOptions);
34
+ getCues(): readonly Cue[];
35
+ getState(): TimelineState;
36
+ play(): void;
37
+ pause(): void;
38
+ seek(timeMs: number): void;
39
+ advance(deltaMs: number): void;
40
+ on(eventName: TimelineEventName, handler: TimelineEventHandler): () => void;
41
+ }
42
+ export declare function createTimelineScheduler(options?: TimelineSchedulerOptions): TimelineScheduler;
43
+ export type EasingFunction = (t: number) => number;
44
+ export declare function lerp(start: number, end: number, t: number): number;
45
+ export declare function easeInOutCubic(t: number): number;
46
+ //# sourceMappingURL=timeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.d.ts","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AA2DxC,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,WAAW,GAAG,cAAc,CAAC;AAE3E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;CAC/B;AAED,MAAM,MAAM,aAAa,GACrB,qBAAqB,GACrB,qBAAqB,GACrB,wBAAwB,CAAC;AAE7B,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,aAAa,GAAG,aAAa,IAAI,CAC1E,KAAK,EAAE,CAAC,KACL,IAAI,CAAC;AAEV,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,EAAE,CAAC;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,qBAAa,iBAAiB;;gBAShB,OAAO,GAAE,wBAA6B;IAwBlD,OAAO,IAAI,SAAS,GAAG,EAAE;IAIzB,QAAQ,IAAI,aAAa;IASzB,IAAI,IAAI,IAAI;IAQZ,KAAK,IAAI,IAAI;IAQb,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAiC1B,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAsE9B,EAAE,CAAC,SAAS,EAAE,iBAAiB,EAAE,OAAO,EAAE,oBAAoB,GAAG,MAAM,IAAI;CAkC5E;AAED,wBAAgB,uBAAuB,CACrC,OAAO,CAAC,EAAE,wBAAwB,GACjC,iBAAiB,CAEnB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;AAKnD,wBAAgB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAElE;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAKhD"}
@@ -0,0 +1,217 @@
1
+ const ERROR_PREFIX = "TimelineScheduler: ";
2
+ function validateNonNegativeFinite(value, field) {
3
+ if (!Number.isFinite(value)) {
4
+ throw new Error(`${ERROR_PREFIX}${field} must be a finite number; got ${String(value)}`);
5
+ }
6
+ if (value < 0) {
7
+ throw new Error(`${ERROR_PREFIX}${field} must be non-negative; got ${value}`);
8
+ }
9
+ }
10
+ function validateDuration(value) {
11
+ if (value === undefined) {
12
+ return;
13
+ }
14
+ validateNonNegativeFinite(value, "duration");
15
+ if (value === 0) {
16
+ throw new Error(`${ERROR_PREFIX}duration must be greater than 0; got 0`);
17
+ }
18
+ }
19
+ function validateInitialTimeMs(value, duration) {
20
+ if (value === undefined) {
21
+ return;
22
+ }
23
+ validateNonNegativeFinite(value, "initialTimeMs");
24
+ if (duration !== undefined && value > duration) {
25
+ throw new Error(`${ERROR_PREFIX}initialTimeMs (${value}) exceeds duration (${duration})`);
26
+ }
27
+ }
28
+ function validateCues(cues, duration) {
29
+ if (cues === undefined) {
30
+ return;
31
+ }
32
+ for (const cue of cues) {
33
+ validateNonNegativeFinite(cue.time, "cue.time");
34
+ if (duration !== undefined && cue.time > duration) {
35
+ throw new Error(`${ERROR_PREFIX}cue.time (${cue.time}) exceeds duration (${duration}); the cue could never fire`);
36
+ }
37
+ }
38
+ }
39
+ export class TimelineScheduler {
40
+ #cues;
41
+ #duration;
42
+ #handlers = new Map();
43
+ #timeMs;
44
+ #isPlaying;
45
+ #firedCueIndices;
46
+ #sceneEnded;
47
+ constructor(options = {}) {
48
+ validateDuration(options.duration);
49
+ validateCues(options.cues, options.duration);
50
+ validateInitialTimeMs(options.initialTimeMs, options.duration);
51
+ this.#duration = options.duration;
52
+ this.#cues = options.cues === undefined ? [] : [...options.cues];
53
+ this.#cues.sort((a, b) => a.time - b.time);
54
+ this.#timeMs = options.initialTimeMs ?? 0;
55
+ this.#isPlaying = options.initialPlaying ?? false;
56
+ this.#firedCueIndices = new Set();
57
+ this.#sceneEnded =
58
+ this.#duration !== undefined && this.#timeMs === this.#duration;
59
+ if (this.#timeMs > 0) {
60
+ for (let i = 0; i < this.#cues.length; i += 1) {
61
+ if (this.#cues[i].time <= this.#timeMs) {
62
+ this.#firedCueIndices.add(i);
63
+ }
64
+ }
65
+ }
66
+ }
67
+ getCues() {
68
+ return [...this.#cues];
69
+ }
70
+ getState() {
71
+ return {
72
+ timeMs: this.#timeMs,
73
+ isPlaying: this.#isPlaying,
74
+ firedCueIndices: [...this.#firedCueIndices].sort((a, b) => a - b),
75
+ sceneEnded: this.#sceneEnded,
76
+ };
77
+ }
78
+ play() {
79
+ if (this.#isPlaying) {
80
+ return;
81
+ }
82
+ this.#isPlaying = true;
83
+ this.#emitStateChange();
84
+ }
85
+ pause() {
86
+ if (!this.#isPlaying) {
87
+ return;
88
+ }
89
+ this.#isPlaying = false;
90
+ this.#emitStateChange();
91
+ }
92
+ seek(timeMs) {
93
+ if (!Number.isFinite(timeMs)) {
94
+ throw new Error(`${ERROR_PREFIX}seek(timeMs): timeMs must be a finite number; got ${String(timeMs)}`);
95
+ }
96
+ if (timeMs < 0) {
97
+ throw new Error(`${ERROR_PREFIX}seek(timeMs): timeMs must be non-negative; got ${timeMs}`);
98
+ }
99
+ const clamped = this.#duration !== undefined ? Math.min(timeMs, this.#duration) : timeMs;
100
+ this.#timeMs = clamped;
101
+ this.#firedCueIndices.clear();
102
+ // clamped > 0 leaves cue-at-time-0 unfired so the "cue at time === 0
103
+ // fires on first forward advance from 0" boundary rule still applies after seek(0).
104
+ if (clamped > 0) {
105
+ for (let i = 0; i < this.#cues.length; i += 1) {
106
+ if (this.#cues[i].time <= clamped) {
107
+ this.#firedCueIndices.add(i);
108
+ }
109
+ }
110
+ }
111
+ this.#sceneEnded =
112
+ this.#duration !== undefined && clamped === this.#duration;
113
+ this.#emitStateChange();
114
+ }
115
+ advance(deltaMs) {
116
+ if (!Number.isFinite(deltaMs)) {
117
+ throw new Error(`${ERROR_PREFIX}advance(deltaMs): deltaMs must be a finite number; got ${String(deltaMs)}`);
118
+ }
119
+ if (deltaMs < 0) {
120
+ throw new Error(`${ERROR_PREFIX}advance(deltaMs): deltaMs must be non-negative; got ${deltaMs}`);
121
+ }
122
+ if (deltaMs === 0) {
123
+ return;
124
+ }
125
+ if (!this.#isPlaying) {
126
+ return;
127
+ }
128
+ if (this.#sceneEnded) {
129
+ return;
130
+ }
131
+ const prevTime = this.#timeMs;
132
+ let newTime = prevTime + deltaMs;
133
+ let willEnd = false;
134
+ if (this.#duration !== undefined && newTime >= this.#duration) {
135
+ newTime = this.#duration;
136
+ willEnd = true;
137
+ }
138
+ const cuesToFire = [];
139
+ for (let i = 0; i < this.#cues.length; i += 1) {
140
+ const cue = this.#cues[i];
141
+ if (this.#firedCueIndices.has(i)) {
142
+ continue;
143
+ }
144
+ const inRange = cue.time <= newTime &&
145
+ (cue.time > prevTime || (prevTime === 0 && cue.time === 0));
146
+ if (inRange) {
147
+ cuesToFire.push(i);
148
+ }
149
+ }
150
+ this.#timeMs = newTime;
151
+ if (willEnd) {
152
+ this.#sceneEnded = true;
153
+ }
154
+ for (const cueIndex of cuesToFire) {
155
+ this.#firedCueIndices.add(cueIndex);
156
+ this.#emit("cue:fired", {
157
+ type: "cue:fired",
158
+ timeMs: newTime,
159
+ cueIndex,
160
+ cue: this.#cues[cueIndex],
161
+ });
162
+ }
163
+ if (willEnd) {
164
+ this.#emit("scene:end", {
165
+ type: "scene:end",
166
+ timeMs: newTime,
167
+ });
168
+ }
169
+ this.#emitStateChange();
170
+ }
171
+ on(eventName, handler) {
172
+ let handlers = this.#handlers.get(eventName);
173
+ if (handlers === undefined) {
174
+ handlers = new Set();
175
+ this.#handlers.set(eventName, handlers);
176
+ }
177
+ handlers.add(handler);
178
+ let disposed = false;
179
+ return () => {
180
+ if (disposed) {
181
+ return;
182
+ }
183
+ disposed = true;
184
+ handlers.delete(handler);
185
+ };
186
+ }
187
+ #emit(eventName, event) {
188
+ const handlers = this.#handlers.get(eventName);
189
+ if (handlers === undefined) {
190
+ return;
191
+ }
192
+ for (const handler of [...handlers]) {
193
+ handler(event);
194
+ }
195
+ }
196
+ #emitStateChange() {
197
+ this.#emit("state:change", {
198
+ type: "state:change",
199
+ state: this.getState(),
200
+ });
201
+ }
202
+ }
203
+ export function createTimelineScheduler(options) {
204
+ return new TimelineScheduler(options);
205
+ }
206
+ const _timelineEasingTypeCheck = (t) => t;
207
+ void _timelineEasingTypeCheck;
208
+ export function lerp(start, end, t) {
209
+ return start + (end - start) * t;
210
+ }
211
+ export function easeInOutCubic(t) {
212
+ if (t < 0.5) {
213
+ return 4 * t ** 3;
214
+ }
215
+ return 1 - Math.pow(-2 * t + 2, 3) / 2;
216
+ }
217
+ //# sourceMappingURL=timeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timeline.js","sourceRoot":"","sources":["../src/timeline.ts"],"names":[],"mappings":"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"}