@smoove/core 0.3.0 → 0.3.2

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 (50) hide show
  1. package/dist/engine/marker.d.ts +77 -0
  2. package/dist/engine/marker.d.ts.map +1 -0
  3. package/dist/engine/marker.js +107 -0
  4. package/dist/engine/marker.js.map +1 -0
  5. package/dist/engine/sequence.d.ts +54 -11
  6. package/dist/engine/sequence.d.ts.map +1 -1
  7. package/dist/engine/sequence.js +90 -22
  8. package/dist/engine/sequence.js.map +1 -1
  9. package/dist/engine/series.d.ts +20 -4
  10. package/dist/engine/series.d.ts.map +1 -1
  11. package/dist/engine/series.js +42 -3
  12. package/dist/engine/series.js.map +1 -1
  13. package/dist/index.d.ts +3 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +4 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/layout/block.d.ts +3 -0
  18. package/dist/layout/block.d.ts.map +1 -1
  19. package/dist/layout/block.js +5 -0
  20. package/dist/layout/block.js.map +1 -1
  21. package/dist/layout/contract.d.ts +20 -0
  22. package/dist/layout/contract.d.ts.map +1 -1
  23. package/dist/layout/contract.js.map +1 -1
  24. package/dist/layout/flex/flex.d.ts +3 -0
  25. package/dist/layout/flex/flex.d.ts.map +1 -1
  26. package/dist/layout/flex/flex.js +5 -0
  27. package/dist/layout/flex/flex.js.map +1 -1
  28. package/dist/layout/flex/mixin.d.ts +4 -1
  29. package/dist/layout/flex/mixin.d.ts.map +1 -1
  30. package/dist/layout/flex/mixin.js +5 -0
  31. package/dist/layout/flex/mixin.js.map +1 -1
  32. package/dist/layout/image.d.ts +3 -0
  33. package/dist/layout/image.d.ts.map +1 -1
  34. package/dist/layout/image.js +5 -0
  35. package/dist/layout/image.js.map +1 -1
  36. package/dist/layout/measure.d.ts +48 -0
  37. package/dist/layout/measure.d.ts.map +1 -0
  38. package/dist/layout/measure.js +105 -0
  39. package/dist/layout/measure.js.map +1 -0
  40. package/dist/layout/shapes.d.ts +39 -13
  41. package/dist/layout/shapes.d.ts.map +1 -1
  42. package/dist/layout/text/ink.d.ts +25 -0
  43. package/dist/layout/text/ink.d.ts.map +1 -0
  44. package/dist/layout/text/ink.js +62 -0
  45. package/dist/layout/text/ink.js.map +1 -0
  46. package/dist/layout/text/text.d.ts +6 -1
  47. package/dist/layout/text/text.d.ts.map +1 -1
  48. package/dist/layout/text/text.js +33 -0
  49. package/dist/layout/text/text.js.map +1 -1
  50. package/package.json +7 -1
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Timeline markers: lazily-resolving, immutable handles onto a scene's
3
+ * placement inside a marker source (`Series`, `TransitionSeries`, or a
4
+ * standalone `Sequence`). A marker stores no frame number — every read
5
+ * resolves against the source's *current* placement, so retiming a scene
6
+ * moves everything anchored to it.
7
+ *
8
+ * @module
9
+ */
10
+ /** Resolved placement of one scene: window open/close plus the settled point. */
11
+ export type ScenePlacement = {
12
+ /** Frame the scene's sequence window opens. */
13
+ from: number;
14
+ /** Frame the window closes (`from + durationInFrames`). */
15
+ end: number;
16
+ /**
17
+ * `from` + incoming overlap — the frame the scene is fully revealed. For
18
+ * `TransitionSeries` the overlap is the incoming transition's duration; for
19
+ * `Series` it is `max(0, −offset)`; for a standalone `Sequence` it is `0`
20
+ * (so `settled === from`).
21
+ */
22
+ settled: number;
23
+ };
24
+ /**
25
+ * Implemented by anything that hands out markers. `name` is `undefined` for
26
+ * single-scene sources (a standalone `Sequence`).
27
+ *
28
+ * @internal
29
+ */
30
+ export type MarkerSource = {
31
+ _kmResolveMarker(name: string | undefined): ScenePlacement;
32
+ };
33
+ export type MarkerKind = "start" | "end" | "settled";
34
+ /**
35
+ * One anchorable point of a marked scene (`start`, `end`, or `settled`),
36
+ * optionally shifted by an integer frame delta. Immutable: `add()` returns a
37
+ * new point. Accepted anywhere a {@link FrameAnchor} is.
38
+ */
39
+ export declare class MarkerPoint {
40
+ private readonly _source;
41
+ private readonly _name;
42
+ readonly kind: MarkerKind;
43
+ readonly delta: number;
44
+ /** @internal — obtain points via `Marker#start`/`end`/`settled`. */
45
+ constructor(_source: MarkerSource, _name: string | undefined, kind: MarkerKind, delta: number);
46
+ /** A new point shifted by `n` frames (integer; deltas accumulate). */
47
+ add(n: number): MarkerPoint;
48
+ /**
49
+ * Resolve to a frame number **now**. Prefer passing the point itself to
50
+ * `from:`/`until:` — an eagerly resolved number freezes and desyncs when
51
+ * the timeline is retimed.
52
+ */
53
+ resolve(): number;
54
+ }
55
+ /**
56
+ * Handle onto a marked scene. Exposes the three anchorable points; using the
57
+ * bare `Marker` as a {@link FrameAnchor} means its `.start`.
58
+ */
59
+ export declare class Marker {
60
+ private readonly _source;
61
+ private readonly _name?;
62
+ /** @internal — obtain via `series.marker(name)` / `sequence.marker()`. */
63
+ constructor(_source: MarkerSource, _name?: string | undefined);
64
+ /** The scene's window-open frame (under a transition: the transition begins). */
65
+ get start(): MarkerPoint;
66
+ /** The scene's window-close frame. */
67
+ get end(): MarkerPoint;
68
+ /** The frame the scene is fully revealed (start + incoming overlap). */
69
+ get settled(): MarkerPoint;
70
+ /** Sugar for `this.start.resolve()`. */
71
+ resolve(): number;
72
+ }
73
+ /** A timeline position: an absolute frame, a `Marker` (its `.start`), or a `MarkerPoint`. */
74
+ export type FrameAnchor = number | Marker | MarkerPoint;
75
+ /** Resolve a {@link FrameAnchor} to a frame number. @internal */
76
+ export declare function resolveFrameAnchor(anchor: FrameAnchor): number;
77
+ //# sourceMappingURL=marker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marker.d.ts","sourceRoot":"","sources":["../../src/engine/marker.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iFAAiF;AACjF,MAAM,MAAM,cAAc,GAAG;IAC3B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAAC;CAC5D,CAAC;AAuBF,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;AAErD;;;;GAIG;AACH,qBAAa,WAAW;IAGpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,QAAQ,CAAC,IAAI,EAAE,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,MAAM;IALxB,oEAAoE;gBAEjD,OAAO,EAAE,YAAY,EACrB,KAAK,EAAE,MAAM,GAAG,SAAS,EACjC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM;IAGxB,sEAAsE;IACtE,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,WAAW;IAO3B;;;;OAIG;IACH,OAAO,IAAI,MAAM;CAqBlB;AAED;;;GAGG;AACH,qBAAa,MAAM;IAGf,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;IAHzB,0EAA0E;gBAEvD,OAAO,EAAE,YAAY,EACrB,KAAK,CAAC,EAAE,MAAM,YAAA;IAGjC,iFAAiF;IACjF,IAAI,KAAK,IAAI,WAAW,CAEvB;IAED,sCAAsC;IACtC,IAAI,GAAG,IAAI,WAAW,CAErB;IAED,wEAAwE;IACxE,IAAI,OAAO,IAAI,WAAW,CAEzB;IAED,wCAAwC;IACxC,OAAO,IAAI,MAAM;CAGlB;AAED,6FAA6F;AAC7F,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,WAAW,CAAC;AAExD,iEAAiE;AACjE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAE9D"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Timeline markers: lazily-resolving, immutable handles onto a scene's
3
+ * placement inside a marker source (`Series`, `TransitionSeries`, or a
4
+ * standalone `Sequence`). A marker stores no frame number — every read
5
+ * resolves against the source's *current* placement, so retiming a scene
6
+ * moves everything anchored to it.
7
+ *
8
+ * @module
9
+ */
10
+ // Re-entrancy guard: resolving a marker may resolve the source's `from`,
11
+ // which may itself be a marker. A genuine loop revisits the same
12
+ // (source, name) pair — throw instead of recursing forever.
13
+ const resolutionStack = [];
14
+ function resolvePlacement(source, name) {
15
+ for (const entry of resolutionStack) {
16
+ if (entry.source === source && entry.name === name) {
17
+ throw new Error(`marker: circular anchoring while resolving "${name ?? "(sequence)"}" — its timeline position depends on itself`);
18
+ }
19
+ }
20
+ resolutionStack.push({ source, name });
21
+ try {
22
+ return source._kmResolveMarker(name);
23
+ }
24
+ finally {
25
+ resolutionStack.pop();
26
+ }
27
+ }
28
+ /**
29
+ * One anchorable point of a marked scene (`start`, `end`, or `settled`),
30
+ * optionally shifted by an integer frame delta. Immutable: `add()` returns a
31
+ * new point. Accepted anywhere a {@link FrameAnchor} is.
32
+ */
33
+ export class MarkerPoint {
34
+ _source;
35
+ _name;
36
+ kind;
37
+ delta;
38
+ /** @internal — obtain points via `Marker#start`/`end`/`settled`. */
39
+ constructor(_source, _name, kind, delta) {
40
+ this._source = _source;
41
+ this._name = _name;
42
+ this.kind = kind;
43
+ this.delta = delta;
44
+ }
45
+ /** A new point shifted by `n` frames (integer; deltas accumulate). */
46
+ add(n) {
47
+ if (!Number.isInteger(n)) {
48
+ throw new Error(`marker: add() delta must be an integer (got ${n})`);
49
+ }
50
+ return new MarkerPoint(this._source, this._name, this.kind, this.delta + n);
51
+ }
52
+ /**
53
+ * Resolve to a frame number **now**. Prefer passing the point itself to
54
+ * `from:`/`until:` — an eagerly resolved number freezes and desyncs when
55
+ * the timeline is retimed.
56
+ */
57
+ resolve() {
58
+ const placement = resolvePlacement(this._source, this._name);
59
+ const base = this.kind === "start"
60
+ ? placement.from
61
+ : this.kind === "end"
62
+ ? placement.end
63
+ : placement.settled;
64
+ if (!Number.isFinite(base)) {
65
+ throw new Error(`marker: cannot resolve "${this.kind}"${this._name ? ` of "${this._name}"` : ""} — the source sequence has no explicit duration and isn't attached to a composition`);
66
+ }
67
+ const frame = base + this.delta;
68
+ if (frame < 0) {
69
+ throw new Error(`marker: "${this._name ?? "(sequence)"}" ${this.kind}${this.delta ? ` ${this.delta > 0 ? "+" : ""}${this.delta}` : ""} resolves to ${frame}, before frame 0`);
70
+ }
71
+ return frame;
72
+ }
73
+ }
74
+ /**
75
+ * Handle onto a marked scene. Exposes the three anchorable points; using the
76
+ * bare `Marker` as a {@link FrameAnchor} means its `.start`.
77
+ */
78
+ export class Marker {
79
+ _source;
80
+ _name;
81
+ /** @internal — obtain via `series.marker(name)` / `sequence.marker()`. */
82
+ constructor(_source, _name) {
83
+ this._source = _source;
84
+ this._name = _name;
85
+ }
86
+ /** The scene's window-open frame (under a transition: the transition begins). */
87
+ get start() {
88
+ return new MarkerPoint(this._source, this._name, "start", 0);
89
+ }
90
+ /** The scene's window-close frame. */
91
+ get end() {
92
+ return new MarkerPoint(this._source, this._name, "end", 0);
93
+ }
94
+ /** The frame the scene is fully revealed (start + incoming overlap). */
95
+ get settled() {
96
+ return new MarkerPoint(this._source, this._name, "settled", 0);
97
+ }
98
+ /** Sugar for `this.start.resolve()`. */
99
+ resolve() {
100
+ return this.start.resolve();
101
+ }
102
+ }
103
+ /** Resolve a {@link FrameAnchor} to a frame number. @internal */
104
+ export function resolveFrameAnchor(anchor) {
105
+ return typeof anchor === "number" ? anchor : anchor.resolve();
106
+ }
107
+ //# sourceMappingURL=marker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marker.js","sourceRoot":"","sources":["../../src/engine/marker.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,25 @@
1
1
  import Konva from "konva";
2
+ import { type FrameAnchor, Marker, type MarkerSource, type ScenePlacement } from "./marker.js";
2
3
  export type SequenceOptions = Konva.LayerConfig & {
3
- /** Composition frame this sequence starts on. Defaults to `0`. */
4
- from?: number;
4
+ /**
5
+ * Composition frame this sequence starts on: an absolute frame, or a
6
+ * `Marker`/`MarkerPoint` resolved live (retiming the marked scene moves
7
+ * this sequence with it). Defaults to `0`.
8
+ */
9
+ from?: FrameAnchor;
5
10
  /**
6
11
  * How many frames the sequence spans. When omitted it defaults to the host
7
12
  * composition's `durationInFrames` — i.e. a layer spanning the whole comp.
8
13
  * Resolved live once added (see {@link Sequence.durationInFrames}).
14
+ * Mutually exclusive with {@link until}.
9
15
  */
10
16
  durationInFrames?: number;
17
+ /**
18
+ * End anchor: the span becomes `resolve(until) − resolve(from)`, kept live
19
+ * so retiming either end moves the window. Mutually exclusive with
20
+ * {@link durationInFrames}.
21
+ */
22
+ until?: FrameAnchor;
11
23
  };
12
24
  export type Updater = (localFrame: number) => void;
13
25
  /**
@@ -19,24 +31,40 @@ export type Updater = (localFrame: number) => void;
19
31
  export type SequenceProvider = {
20
32
  sequences(): Sequence[];
21
33
  };
22
- export declare class Sequence extends Konva.Layer {
23
- readonly from: number;
24
- /** Explicit span, or `undefined` to default to the host comp's duration. */
34
+ export declare class Sequence extends Konva.Layer implements MarkerSource {
35
+ private readonly _from;
36
+ /** Explicit span, or `undefined` to default to `until`/the host comp's duration. */
25
37
  private readonly _durationInFrames?;
38
+ private readonly _until?;
26
39
  private readonly _updaters;
27
40
  private _active;
28
41
  private _media;
29
42
  private _lastLocal;
30
43
  constructor(opts?: SequenceOptions);
31
44
  /**
32
- * Frames this sequence spans. When constructed without an explicit
33
- * `durationInFrames`, this resolves **live** to the host composition's
34
- * `durationInFrames` a layer that spans the whole comp. Before the sequence
35
- * is added to a composition (no reachable stage) it reports `Infinity`,
36
- * meaning "unbounded"; `_apply` is only ever driven by the comp, so by then
37
- * the real duration is reachable.
45
+ * Composition frame this sequence starts on. Marker-valued `from` resolves
46
+ * on every read (live, like {@link durationInFrames}), so retiming the
47
+ * marked scene moves this sequence automatically.
48
+ */
49
+ get from(): number;
50
+ /**
51
+ * Frames this sequence spans. With `until`, resolves live as
52
+ * `resolve(until) − resolve(from)`. When constructed without an explicit
53
+ * span, this resolves **live** to the host composition's
54
+ * `durationInFrames` — a layer that spans the whole comp. Before the
55
+ * sequence is added to a composition (no reachable stage) it reports
56
+ * `Infinity`, meaning "unbounded"; `_apply` is only ever driven by the
57
+ * comp, so by then the real duration is reachable.
38
58
  */
39
59
  get durationInFrames(): number;
60
+ /**
61
+ * A {@link Marker} onto this sequence's own placement — no name, a
62
+ * sequence *is* a single scene. Anchor other sequences to it:
63
+ * `new Sequence({ from: intro.marker().end })`.
64
+ */
65
+ marker(): Marker;
66
+ /** @internal marker-source hook. A plain sequence has no incoming overlap. */
67
+ _kmResolveMarker(): ScenePlacement;
40
68
  register(updater: Updater): () => void;
41
69
  /**
42
70
  * Internal — called by Composition on each frame change.
@@ -49,6 +77,21 @@ export declare class Sequence extends Konva.Layer {
49
77
  * nothing, or a same-frame re-entry), avoiding a wasted updater + layout + draw.
50
78
  */
51
79
  _apply(frame: number, force?: boolean): void;
80
+ /**
81
+ * Internal — the frame pass shared by {@link _apply} and `measure()`:
82
+ * updaters, ticks, then flex layout of every direct-child layout root. No
83
+ * visibility change, no draw, no `_lastLocal` bookkeeping — callers own
84
+ * that. With `tickMedia: false` (the measure path) media-only nodes
85
+ * (`MEDIA_MARK` without `TICK_MARK`) are skipped: media state never affects
86
+ * layout, and ticking a video at a foreign frame would trigger spurious
87
+ * seeks.
88
+ */
89
+ _kmRunFrame(local: number, tickMedia: boolean): void;
90
+ /**
91
+ * Internal — the live local frame while active, else `null`. `measure()`
92
+ * uses this to restore an active sequence after a foreign-frame pass.
93
+ */
94
+ _kmLiveLocal(): number | null;
52
95
  /**
53
96
  * Internal — force this sequence hidden and inactive, regardless of frame
54
97
  * range. Used by `Composition` while it buffers assets so the stage stays
@@ -1 +1 @@
1
- {"version":3,"file":"sequence.d.ts","sourceRoot":"","sources":["../../src/engine/sequence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,GAAG;IAChD,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAAE,SAAS,IAAI,QAAQ,EAAE,CAAA;CAAE,CAAC;AAQ3D,qBAAa,QAAS,SAAQ,KAAK,CAAC,KAAK;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAmB;IAIjC,OAAO,CAAC,UAAU,CAAM;gBAEZ,IAAI,GAAE,eAAoB;IAkBtC;;;;;;;OAOG;IACH,IAAI,gBAAgB,IAAI,MAAM,CAK7B;IAED,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,IAAI;IAOtC;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,IAAI;IAsC1C;;;;;OAKG;IACH,OAAO,IAAI,IAAI;CAOhB"}
1
+ {"version":3,"file":"sequence.d.ts","sourceRoot":"","sources":["../../src/engine/sequence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EACL,KAAK,WAAW,EAChB,MAAM,EACN,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAErB,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,WAAW,GAAG;IAChD;;;;OAIG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAAE,SAAS,IAAI,QAAQ,EAAE,CAAA;CAAE,CAAC;AAQ3D,qBAAa,QAAS,SAAQ,KAAK,CAAC,KAAM,YAAW,YAAY;IAC/D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,oFAAoF;IACpF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAc;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAmB;IAIjC,OAAO,CAAC,UAAU,CAAM;gBAEZ,IAAI,GAAE,eAAoB;IAyBtC;;;;OAIG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;;;OAQG;IACH,IAAI,gBAAgB,IAAI,MAAM,CAc7B;IAED;;;;OAIG;IACH,MAAM,IAAI,MAAM;IAIhB,8EAA8E;IAC9E,gBAAgB,IAAI,cAAc;IAKlC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,IAAI;IAOtC;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,UAAQ,GAAG,IAAI;IA+B1C;;;;;;;;OAQG;IACH,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI;IAuBpD;;;OAGG;IACH,YAAY,IAAI,MAAM,GAAG,IAAI;IAI7B;;;;;OAKG;IACH,OAAO,IAAI,IAAI;CAOhB"}
@@ -2,10 +2,12 @@ import Konva from "konva";
2
2
  import { isKMLayoutRoot } from "../layout/contract.js";
3
3
  import { MEDIA_MARK, TICK_MARK } from "../markers.js";
4
4
  import { getComposition } from "./composition.js";
5
+ import { Marker, resolveFrameAnchor, } from "./marker.js";
5
6
  export class Sequence extends Konva.Layer {
6
- from;
7
- /** Explicit span, or `undefined` to default to the host comp's duration. */
7
+ _from;
8
+ /** Explicit span, or `undefined` to default to `until`/the host comp's duration. */
8
9
  _durationInFrames;
10
+ _until;
9
11
  _updaters = new Set();
10
12
  _active = false;
11
13
  _media = [];
@@ -14,35 +16,73 @@ export class Sequence extends Konva.Layer {
14
16
  // a sentinel that never equals a real local frame, so the first apply always runs.
15
17
  _lastLocal = -1;
16
18
  constructor(opts = {}) {
17
- const { from = 0, durationInFrames, ...layerOpts } = opts;
18
- if (!Number.isInteger(from) || from < 0) {
19
+ const { from = 0, durationInFrames, until, ...layerOpts } = opts;
20
+ if (typeof from === "number" && (!Number.isInteger(from) || from < 0)) {
19
21
  throw new Error("Sequence: from must be a non-negative integer");
20
22
  }
23
+ if (durationInFrames !== undefined && until !== undefined) {
24
+ throw new Error("Sequence: durationInFrames and until are mutually exclusive — provide one");
25
+ }
21
26
  // durationInFrames is optional: when omitted it resolves to the host comp's
22
27
  // duration (see the getter). Only validate an explicitly provided value.
23
28
  if (durationInFrames !== undefined &&
24
29
  (!Number.isInteger(durationInFrames) || durationInFrames <= 0)) {
25
30
  throw new Error("Sequence: durationInFrames must be a positive integer");
26
31
  }
32
+ if (typeof until === "number" && (!Number.isInteger(until) || until <= 0)) {
33
+ throw new Error("Sequence: until must be a positive integer frame");
34
+ }
27
35
  super({ ...layerOpts, visible: false });
28
- this.from = from;
36
+ this._from = from;
29
37
  this._durationInFrames = durationInFrames;
38
+ this._until = until;
39
+ }
40
+ /**
41
+ * Composition frame this sequence starts on. Marker-valued `from` resolves
42
+ * on every read (live, like {@link durationInFrames}), so retiming the
43
+ * marked scene moves this sequence automatically.
44
+ */
45
+ get from() {
46
+ return resolveFrameAnchor(this._from);
30
47
  }
31
48
  /**
32
- * Frames this sequence spans. When constructed without an explicit
33
- * `durationInFrames`, this resolves **live** to the host composition's
34
- * `durationInFrames` a layer that spans the whole comp. Before the sequence
35
- * is added to a composition (no reachable stage) it reports `Infinity`,
36
- * meaning "unbounded"; `_apply` is only ever driven by the comp, so by then
37
- * the real duration is reachable.
49
+ * Frames this sequence spans. With `until`, resolves live as
50
+ * `resolve(until) resolve(from)`. When constructed without an explicit
51
+ * span, this resolves **live** to the host composition's
52
+ * `durationInFrames` a layer that spans the whole comp. Before the
53
+ * sequence is added to a composition (no reachable stage) it reports
54
+ * `Infinity`, meaning "unbounded"; `_apply` is only ever driven by the
55
+ * comp, so by then the real duration is reachable.
38
56
  */
39
57
  get durationInFrames() {
58
+ if (this._until !== undefined) {
59
+ const from = this.from;
60
+ const until = resolveFrameAnchor(this._until);
61
+ const d = until - from;
62
+ if (d <= 0) {
63
+ throw new Error(`Sequence: until (${until}) must be after from (${from})`);
64
+ }
65
+ return d;
66
+ }
40
67
  if (this._durationInFrames !== undefined)
41
68
  return this._durationInFrames;
42
69
  const stage = this.getStage();
43
70
  const comp = stage && getComposition(stage);
44
71
  return comp ? comp.durationInFrames.get() : Number.POSITIVE_INFINITY;
45
72
  }
73
+ /**
74
+ * A {@link Marker} onto this sequence's own placement — no name, a
75
+ * sequence *is* a single scene. Anchor other sequences to it:
76
+ * `new Sequence({ from: intro.marker().end })`.
77
+ */
78
+ marker() {
79
+ return new Marker(this);
80
+ }
81
+ /** @internal marker-source hook. A plain sequence has no incoming overlap. */
82
+ _kmResolveMarker() {
83
+ const from = this.from;
84
+ return { from, end: from + this.durationInFrames, settled: from };
85
+ }
46
86
  register(updater) {
47
87
  this._updaters.add(updater);
48
88
  return () => {
@@ -75,17 +115,7 @@ export class Sequence extends Konva.Layer {
75
115
  if (!becameActive && !force && local === this._lastLocal)
76
116
  return;
77
117
  this._lastLocal = local;
78
- for (const u of this._updaters)
79
- u(local);
80
- // Tick BEFORE layout: a ticked node may change its measured size (e.g. a
81
- // Text typewriter revealing another line), and the flex pass must see the
82
- // up-to-date size this frame rather than lagging one behind.
83
- for (const v of this._media)
84
- v._kmTick?.(local);
85
- for (const c of this.getChildren()) {
86
- if (isKMLayoutRoot(c))
87
- c._kmComputeLayout();
88
- }
118
+ this._kmRunFrame(local, true);
89
119
  // Draw synchronously the frame in which a sequence becomes visible — this
90
120
  // ensures fresh pixels are on the canvas before the browser paints the
91
121
  // newly-displayed layer (avoids a one-frame flash of stale content).
@@ -102,6 +132,44 @@ export class Sequence extends Konva.Layer {
102
132
  v._kmDeactivate?.();
103
133
  }
104
134
  }
135
+ /**
136
+ * Internal — the frame pass shared by {@link _apply} and `measure()`:
137
+ * updaters, ticks, then flex layout of every direct-child layout root. No
138
+ * visibility change, no draw, no `_lastLocal` bookkeeping — callers own
139
+ * that. With `tickMedia: false` (the measure path) media-only nodes
140
+ * (`MEDIA_MARK` without `TICK_MARK`) are skipped: media state never affects
141
+ * layout, and ticking a video at a foreign frame would trigger spurious
142
+ * seeks.
143
+ */
144
+ _kmRunFrame(local, tickMedia) {
145
+ // While inactive there is no cached tickable list (that cache is built on
146
+ // activation), so collect on demand.
147
+ const tickables = this._active
148
+ ? this._media
149
+ : this.find((n) => n.getAttr(MEDIA_MARK) === true || n.getAttr(TICK_MARK) === true);
150
+ for (const u of this._updaters)
151
+ u(local);
152
+ // Tick BEFORE layout: a ticked node may change its measured size (e.g. a
153
+ // Text typewriter revealing another line), and the flex pass must see the
154
+ // up-to-date size this frame rather than lagging one behind.
155
+ for (const v of tickables) {
156
+ if (!tickMedia && v.getAttr(MEDIA_MARK) === true && v.getAttr(TICK_MARK) !== true) {
157
+ continue;
158
+ }
159
+ v._kmTick?.(local);
160
+ }
161
+ for (const c of this.getChildren()) {
162
+ if (isKMLayoutRoot(c))
163
+ c._kmComputeLayout();
164
+ }
165
+ }
166
+ /**
167
+ * Internal — the live local frame while active, else `null`. `measure()`
168
+ * uses this to restore an active sequence after a foreign-frame pass.
169
+ */
170
+ _kmLiveLocal() {
171
+ return this._active ? this._lastLocal : null;
172
+ }
105
173
  /**
106
174
  * Internal — force this sequence hidden and inactive, regardless of frame
107
175
  * range. Used by `Composition` while it buffers assets so the stage stays
@@ -1 +1 @@
1
- {"version":3,"file":"sequence.js","sourceRoot":"","sources":["../../src/engine/sequence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA6BlD,MAAM,OAAO,QAAS,SAAQ,KAAK,CAAC,KAAK;IAC9B,IAAI,CAAS;IACtB,4EAA4E;IAC3D,iBAAiB,CAAU;IAC3B,SAAS,GAAG,IAAI,GAAG,EAAW,CAAC;IACxC,OAAO,GAAG,KAAK,CAAC;IAChB,MAAM,GAAgB,EAAE,CAAC;IACjC,4EAA4E;IAC5E,8EAA8E;IAC9E,mFAAmF;IAC3E,UAAU,GAAG,CAAC,CAAC,CAAC;IAExB,YAAY,OAAwB,EAAE;QACpC,MAAM,EAAE,IAAI,GAAG,CAAC,EAAE,gBAAgB,EAAE,GAAG,SAAS,EAAE,GAAG,IAAI,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QACD,4EAA4E;QAC5E,yEAAyE;QACzE,IACE,gBAAgB,KAAK,SAAS;YAC9B,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,IAAI,gBAAgB,IAAI,CAAC,CAAC,EAC9D,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QACD,KAAK,CAAC,EAAE,GAAG,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,CAAC;IAC5C,CAAC;IAED;;;;;;;OAOG;IACH,IAAI,gBAAgB;QAClB,IAAI,IAAI,CAAC,iBAAiB,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,iBAAiB,CAAC;QACxE,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK,IAAI,cAAc,CAAC,KAAK,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;IACvE,CAAC;IAED,QAAQ,CAAC,OAAgB;QACvB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5B,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC,CAAC;IACJ,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,KAAa,EAAE,KAAK,GAAG,KAAK;QACjC,MAAM,OAAO,GAAG,KAAK,IAAI,IAAI,CAAC,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAChF,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;YACnC,IAAI,YAAY,EAAE,CAAC;gBACjB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACnB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;gBACpB,yEAAyE;gBACzE,gFAAgF;gBAChF,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CACrB,CAAC,CAAa,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,IAAI,CACpE,CAAC;YACnB,CAAC;YACD,MAAM,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;YAChC,sEAAsE;YACtE,IAAI,CAAC,YAAY,IAAI,CAAC,KAAK,IAAI,KAAK,KAAK,IAAI,CAAC,UAAU;gBAAE,OAAO;YACjE,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YACxB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS;gBAAE,CAAC,CAAC,KAAK,CAAC,CAAC;YACzC,yEAAyE;YACzE,0EAA0E;YAC1E,6DAA6D;YAC7D,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM;gBAAE,CAAC,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YAChD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;gBACnC,IAAI,cAAc,CAAC,CAAC,CAAC;oBAAE,CAAC,CAAC,gBAAgB,EAAE,CAAC;YAC9C,CAAC;YACD,0EAA0E;YAC1E,uEAAuE;YACvE,qEAAqE;YACrE,IAAI,YAAY;gBAAE,IAAI,CAAC,IAAI,EAAE,CAAC;;gBACzB,IAAI,CAAC,SAAS,EAAE,CAAC;QACxB,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YACpB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;YACrB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM;gBAAE,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YAAE,OAAO;QAC7C,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;QACrB,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM;YAAE,CAAC,CAAC,aAAa,EAAE,EAAE,CAAC;IACnD,CAAC;CACF"}
1
+ {"version":3,"file":"sequence.js","sourceRoot":"","sources":["../../src/engine/sequence.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,11 @@
1
+ import { type FrameAnchor, Marker, type MarkerSource, type ScenePlacement } from "./marker.js";
1
2
  import { Sequence, type SequenceProvider } from "./sequence.js";
2
3
  export type SeriesOptions = {
3
- /** Frame the series starts at. Default `0`. */
4
- from?: number;
4
+ /**
5
+ * Frame the series starts at: an absolute frame or a `Marker`/`MarkerPoint`
6
+ * (e.g. another series' marker), resolved live. Default `0`.
7
+ */
8
+ from?: FrameAnchor;
5
9
  };
6
10
  export type SeriesSceneOptions = {
7
11
  durationInFrames: number;
@@ -10,6 +14,8 @@ export type SeriesSceneOptions = {
10
14
  * overlaps the previous scene; positive leaves a gap. Default `0` (back-to-back).
11
15
  */
12
16
  offset?: number;
17
+ /** Optional scene name for `series.marker(name)`. Unique per series. */
18
+ name?: string;
13
19
  };
14
20
  /**
15
21
  * Sequential sequencer: collects ordered scenes and auto-computes each
@@ -25,12 +31,22 @@ export type SeriesSceneOptions = {
25
31
  * series.durationInFrames; // total span accounting for offsets
26
32
  * ```
27
33
  */
28
- export declare class Series implements SequenceProvider {
29
- readonly from: number;
34
+ export declare class Series implements SequenceProvider, MarkerSource {
35
+ private readonly _from;
30
36
  private readonly _scenes;
31
37
  constructor(opts?: SeriesOptions);
38
+ /** Frame the series starts at. Marker-valued `from` resolves on every read. */
39
+ get from(): number;
32
40
  /** Append a scene. The `build` callback populates the created `Sequence`. */
33
41
  add(opts: SeriesSceneOptions, build: (seq: Sequence) => void): this;
42
+ /**
43
+ * A lazily-resolving {@link Marker} onto the named scene. Resolution runs
44
+ * this series' placement at read time, so retiming any earlier scene moves
45
+ * the marker — and everything anchored to it — automatically.
46
+ */
47
+ marker(name: string): Marker;
48
+ /** @internal marker-source hook. `settled` = start + `max(0, −offset)`. */
49
+ _kmResolveMarker(name: string | undefined): ScenePlacement;
34
50
  private _place;
35
51
  /** Build one `Sequence` per scene, with `from` resolved from the offsets. */
36
52
  sequences(): Sequence[];
@@ -1 +1 @@
1
- {"version":3,"file":"series.d.ts","sourceRoot":"","sources":["../../src/engine/series.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEhE,MAAM,MAAM,aAAa,GAAG;IAC1B,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAOF;;;;;;;;;;;;;GAaG;AACH,qBAAa,MAAO,YAAW,gBAAgB;IAC7C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;gBAE9B,IAAI,GAAE,aAAkB;IAQpC,6EAA6E;IAC7E,GAAG,CAAC,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAI;IAKnE,OAAO,CAAC,MAAM;IAQd,6EAA6E;IAC7E,SAAS,IAAI,QAAQ,EAAE;IAUvB,sEAAsE;IACtE,IAAI,gBAAgB,IAAI,MAAM,CAM7B;CACF"}
1
+ {"version":3,"file":"series.d.ts","sourceRoot":"","sources":["../../src/engine/series.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAChB,MAAM,EACN,KAAK,YAAY,EAEjB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,QAAQ,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEhE,MAAM,MAAM,aAAa,GAAG;IAC1B;;;OAGG;IACH,IAAI,CAAC,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAOF;;;;;;;;;;;;;GAaG;AACH,qBAAa,MAAO,YAAW,gBAAgB,EAAE,YAAY;IAC3D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;gBAE9B,IAAI,GAAE,aAAkB;IAQpC,+EAA+E;IAC/E,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,6EAA6E;IAC7E,GAAG,CAAC,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,GAAG,IAAI;IAQnE;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAO5B,2EAA2E;IAC3E,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc;IAqB1D,OAAO,CAAC,MAAM;IAQd,6EAA6E;IAC7E,SAAS,IAAI,QAAQ,EAAE;IAUvB,sEAAsE;IACtE,IAAI,gBAAgB,IAAI,MAAM,CAM7B;CACF"}
@@ -1,3 +1,4 @@
1
+ import { Marker, resolveFrameAnchor, } from "./marker.js";
1
2
  import { computeOffsets } from "./offsets.js";
2
3
  import { Sequence } from "./sequence.js";
3
4
  /**
@@ -15,20 +16,58 @@ import { Sequence } from "./sequence.js";
15
16
  * ```
16
17
  */
17
18
  export class Series {
18
- from;
19
+ _from;
19
20
  _scenes = [];
20
21
  constructor(opts = {}) {
21
22
  const from = opts.from ?? 0;
22
- if (!Number.isInteger(from) || from < 0) {
23
+ if (typeof from === "number" && (!Number.isInteger(from) || from < 0)) {
23
24
  throw new Error("Series: from must be a non-negative integer");
24
25
  }
25
- this.from = from;
26
+ this._from = from;
27
+ }
28
+ /** Frame the series starts at. Marker-valued `from` resolves on every read. */
29
+ get from() {
30
+ return resolveFrameAnchor(this._from);
26
31
  }
27
32
  /** Append a scene. The `build` callback populates the created `Sequence`. */
28
33
  add(opts, build) {
34
+ if (opts.name !== undefined && this._scenes.some((s) => s.opts.name === opts.name)) {
35
+ throw new Error(`Series: duplicate scene name "${opts.name}"`);
36
+ }
29
37
  this._scenes.push({ opts, build });
30
38
  return this;
31
39
  }
40
+ /**
41
+ * A lazily-resolving {@link Marker} onto the named scene. Resolution runs
42
+ * this series' placement at read time, so retiming any earlier scene moves
43
+ * the marker — and everything anchored to it — automatically.
44
+ */
45
+ marker(name) {
46
+ if (typeof name !== "string" || name.length === 0) {
47
+ throw new Error("Series: marker name must be a non-empty string");
48
+ }
49
+ return new Marker(this, name);
50
+ }
51
+ /** @internal marker-source hook. `settled` = start + `max(0, −offset)`. */
52
+ _kmResolveMarker(name) {
53
+ const i = this._scenes.findIndex((s) => s.opts.name === name);
54
+ if (name === undefined || i < 0) {
55
+ const names = this._scenes
56
+ .map((s) => s.opts.name)
57
+ .filter((n) => n !== undefined);
58
+ throw new Error(`Series: no scene named "${name}" (named scenes: ${names.length > 0 ? names.join(", ") : "none"})`);
59
+ }
60
+ const placed = this._place();
61
+ const p = placed[i];
62
+ if (!p)
63
+ throw new Error(`Series: scene "${name}" has no placement`);
64
+ const offset = this._scenes[i]?.opts.offset ?? 0;
65
+ return {
66
+ from: p.from,
67
+ end: p.from + p.durationInFrames,
68
+ settled: p.from + Math.max(0, -offset),
69
+ };
70
+ }
32
71
  _place() {
33
72
  const scenes = this._scenes.map((s) => ({
34
73
  durationInFrames: s.opts.durationInFrames,
@@ -1 +1 @@
1
- {"version":3,"file":"series.js","sourceRoot":"","sources":["../../src/engine/series.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAsC,MAAM,cAAc,CAAC;AAClF,OAAO,EAAE,QAAQ,EAAyB,MAAM,eAAe,CAAC;AAqBhE;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,MAAM;IACR,IAAI,CAAS;IACL,OAAO,GAAe,EAAE,CAAC;IAE1C,YAAY,OAAsB,EAAE;QAClC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,6EAA6E;IAC7E,GAAG,CAAC,IAAwB,EAAE,KAA8B;QAC1D,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,MAAM;QACZ,MAAM,MAAM,GAAkB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrD,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,gBAAgB;YACzC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;SACtB,CAAC,CAAC,CAAC;QACJ,OAAO,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IAClD,CAAC;IAED,6EAA6E;IAC7E,SAAS;QACP,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC5B,MAAM,GAAG,GAAG,IAAI,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC,gBAAgB,EAAE,CAAC,CAAC;YACjF,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;YAChB,OAAO,GAAG,CAAC;QACb,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sEAAsE;IACtE,IAAI,gBAAgB;QAClB,MAAM,MAAM,GAAkB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrD,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,gBAAgB;YACzC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;SACtB,CAAC,CAAC,CAAC;QACJ,OAAO,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC;IAC5D,CAAC;CACF"}
1
+ {"version":3,"file":"series.js","sourceRoot":"","sources":["../../src/engine/series.ts"],"names":[],"mappings":"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"}