reframe-video 0.6.33 → 0.6.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/labels.js CHANGED
@@ -239,11 +239,68 @@ function compileScene(ir) {
239
239
  const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
240
240
  const natural = durationOf(grouping, 0);
241
241
  const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, natural) : 1);
242
- const beatStart = tl.at ?? start + (tl.gap ?? 0);
242
+ const at = typeof tl.at === "number" ? tl.at : void 0;
243
+ const beatStart = at ?? start + (tl.gap ?? 0);
243
244
  return beatStart + k * natural;
244
245
  }
245
246
  }
246
247
  };
248
+ let labelClock;
249
+ const anyAnchor = (tl) => tl.kind === "beat" && typeof tl.at === "string" || "children" in tl && tl.children.some(anyAnchor);
250
+ if (ir.timeline && anyAnchor(ir.timeline)) {
251
+ const clock = /* @__PURE__ */ new Map();
252
+ const clockWalk = (tl, start) => {
253
+ let end = start;
254
+ switch (tl.kind) {
255
+ case "seq": {
256
+ let t = start;
257
+ for (const c of orderBeats(tl.children)) t = clockWalk(c, t);
258
+ end = t;
259
+ break;
260
+ }
261
+ case "par": {
262
+ for (const c of tl.children) end = Math.max(end, clockWalk(c, start));
263
+ break;
264
+ }
265
+ case "stagger": {
266
+ tl.children.forEach((c, i) => {
267
+ end = Math.max(end, clockWalk(c, start + i * tl.interval));
268
+ });
269
+ break;
270
+ }
271
+ case "wait":
272
+ end = start + tl.duration;
273
+ break;
274
+ case "tween":
275
+ end = start + (tl.duration ?? DEFAULT_TWEEN_DURATION);
276
+ break;
277
+ case "motionPath":
278
+ end = start + (tl.duration ?? DEFAULT_MOTIONPATH_DURATION);
279
+ break;
280
+ case "to": {
281
+ const override = ir.states?.[tl.state] ?? {};
282
+ const si = tl.stagger ?? 0;
283
+ const targets = nodeOrder.filter((id) => id in override && (tl.filter === void 0 || tl.filter.includes(id)));
284
+ end = start + (tl.duration ?? DEFAULT_TO_DURATION) + Math.max(0, targets.length - 1) * si;
285
+ break;
286
+ }
287
+ case "beat": {
288
+ const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
289
+ const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, durationOf(grouping, 0)) : 1);
290
+ const inner = k === 1 ? grouping : scaleTimeline(grouping, k);
291
+ const at = typeof tl.at === "number" ? tl.at : void 0;
292
+ const beatStart = at ?? start + (tl.gap ?? 0);
293
+ end = clockWalk(inner, beatStart);
294
+ clock.set(tl.name, { t0: beatStart, t1: end });
295
+ break;
296
+ }
297
+ }
298
+ if ("label" in tl && tl.label !== void 0) clock.set(tl.label, { t0: start, t1: end });
299
+ return end;
300
+ };
301
+ clockWalk(ir.timeline, 0);
302
+ labelClock = clock;
303
+ }
247
304
  const walk = (tl, start) => {
248
305
  const end = walkInner(tl, start);
249
306
  if ("label" in tl && tl.label !== void 0) labelTimes.set(tl.label, { t0: start, t1: end });
@@ -260,7 +317,8 @@ function compileScene(ir) {
260
317
  const grouping = { kind: tl.parallel ? "par" : "seq", children: tl.children };
261
318
  const k = tl.scale ?? (tl.duration !== void 0 ? tl.duration / Math.max(1e-9, durationOf(grouping, 0)) : 1);
262
319
  const inner = k === 1 ? grouping : scaleTimeline(grouping, k);
263
- const beatStart = tl.at ?? start + (tl.gap ?? 0);
320
+ const anchored = typeof tl.at === "string" ? labelClock?.get(tl.at)?.t0 : tl.at;
321
+ const beatStart = anchored !== void 0 ? anchored + (typeof tl.at === "string" ? tl.gap ?? 0 : 0) : start + (tl.gap ?? 0);
264
322
  const end = walk(inner, beatStart);
265
323
  beatTimes.set(tl.name, { t0: beatStart, t1: end });
266
324
  labelTimes.set(tl.name, { t0: beatStart, t1: end });
@@ -461,6 +519,7 @@ ${problems.map((p) => ` - ${p}`).join("\n")}`);
461
519
  function validateScene(ir) {
462
520
  const problems = [];
463
521
  const nodeById = /* @__PURE__ */ new Map();
522
+ const startAnchors = [];
464
523
  const checkPaint = (where, value) => {
465
524
  if (typeof value !== "object" || value === null) return;
466
525
  const g = value;
@@ -493,6 +552,7 @@ function validateScene(ir) {
493
552
  if (typeof props.shadowBlur === "number" && props.shadowBlur < 0) problems.push(`node "${node.id}": shadowBlur must be >= 0`);
494
553
  if (typeof props.blend === "string" && !BLEND_MODES.has(props.blend)) problems.push(`node "${node.id}": unknown blend "${props.blend}" \u2014 use ${[...BLEND_MODES].join(", ")}`);
495
554
  if (typeof props.fit === "string" && !IMAGE_FITS.has(props.fit)) problems.push(`node "${node.id}": unknown fit "${props.fit}" \u2014 use ${[...IMAGE_FITS].join(", ")}`);
555
+ if (node.type === "video" && typeof node.props.start === "string") startAnchors.push({ id: node.id, at: node.props.start });
496
556
  if (node.type === "group") {
497
557
  const clip = node.props.clip;
498
558
  if (clip) {
@@ -553,6 +613,7 @@ function validateScene(ir) {
553
613
  );
554
614
  }
555
615
  const labels = /* @__PURE__ */ new Set();
616
+ const beatAnchors = [];
556
617
  const checkEase = (path3, ease) => {
557
618
  if (ease === void 0) return;
558
619
  if (typeof ease === "string") {
@@ -644,6 +705,7 @@ function validateScene(ir) {
644
705
  );
645
706
  }
646
707
  labels.add(tl.name);
708
+ if (typeof tl.at === "string") beatAnchors.push({ name: tl.name, at: tl.at, path: path3 });
647
709
  if (tl.duration !== void 0 && tl.duration <= 0) {
648
710
  problems.push(`${path3}: beat "${tl.name}" duration must be > 0`);
649
711
  }
@@ -662,6 +724,22 @@ function validateScene(ir) {
662
724
  }
663
725
  };
664
726
  if (ir.timeline) checkTimeline(ir.timeline, "timeline");
727
+ for (const a of beatAnchors) {
728
+ if (a.at === a.name) {
729
+ problems.push(`${a.path}: beat "${a.name}" at: "${a.at}" cannot anchor to itself`);
730
+ } else if (!labels.has(a.at)) {
731
+ problems.push(
732
+ `${a.path}: beat "${a.name}" at: "${a.at}" \u2014 unknown timeline label \u2014 known labels: ${[...labels].join(", ") || "(none)"}`
733
+ );
734
+ }
735
+ }
736
+ for (const a of startAnchors) {
737
+ if (!labels.has(a.at)) {
738
+ problems.push(
739
+ `video "${a.id}" start: "${a.at}" \u2014 unknown timeline label \u2014 known labels: ${[...labels].join(", ") || "(none)"}`
740
+ );
741
+ }
742
+ }
665
743
  for (const [i, b] of (ir.behaviors ?? []).entries()) {
666
744
  checkProps(`behaviors[${i}]`, b.target, { [b.prop]: 0 });
667
745
  }