@unseenco/theatre-core 0.4.2 → 0.4.3

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/index.d.ts CHANGED
@@ -1705,6 +1705,13 @@ declare function setCoreRafDriver(driver: IRafDriver): void;
1705
1705
  */
1706
1706
  declare function isRemoteEditorWindow(): boolean;
1707
1707
 
1708
+ /**
1709
+ * Drives registered GSAP animations from the sheet sequence playhead.
1710
+ *
1711
+ * @returns Disposer — call to detach the bridge.
1712
+ */
1713
+ declare function attachGsapSequenceBridge(sheet: ISheet): () => void;
1714
+
1708
1715
  /**
1709
1716
  * Returns a project of the given id, or creates one if it doesn't already exist.
1710
1717
  *
@@ -1790,4 +1797,4 @@ declare function val<T>(pointer: PointerType<T>): T;
1790
1797
  */
1791
1798
  type __UNSTABLE_Project_OnDiskState = OnDiskState;
1792
1799
 
1793
- export { IProject, IProjectConfig, IRafDriver, ISequence, ISheet, ISheetObject, ISheetObjectOptions, ISheetOptions, UnknownShorthandCompoundProps, __UNSTABLE_Project_OnDiskState, createRafDriver, getProject, isRemoteEditorWindow, notify, onChange, setCoreRafDriver, index_d as types, val };
1800
+ export { IProject, IProjectConfig, IRafDriver, ISequence, ISheet, ISheetObject, ISheetObjectOptions, ISheetOptions, UnknownShorthandCompoundProps, __UNSTABLE_Project_OnDiskState, attachGsapSequenceBridge, createRafDriver, getProject, isRemoteEditorWindow, notify, onChange, setCoreRafDriver, index_d as types, val };
package/dist/index.js CHANGED
@@ -241,6 +241,7 @@ var require_propose = __commonJS({
241
241
  // core/src/index.ts
242
242
  var index_exports = {};
243
243
  __export(index_exports, {
244
+ attachGsapSequenceBridge: () => attachGsapSequenceBridge,
244
245
  createRafDriver: () => createRafDriver,
245
246
  getProject: () => getProject,
246
247
  isRemoteEditorWindow: () => isRemoteEditorWindow,
@@ -250,13 +251,14 @@ __export(index_exports, {
250
251
  setCoreRafDriver: () => setCoreRafDriver,
251
252
  setPrivateAPI: () => setPrivateAPI,
252
253
  types: () => propTypes_exports,
253
- val: () => val10
254
+ val: () => val11
254
255
  });
255
256
  module.exports = __toCommonJS(index_exports);
256
257
 
257
258
  // core/src/coreExports.ts
258
259
  var coreExports_exports = {};
259
260
  __export(coreExports_exports, {
261
+ attachGsapSequenceBridge: () => attachGsapSequenceBridge,
260
262
  createRafDriver: () => createRafDriver,
261
263
  getProject: () => getProject,
262
264
  isRemoteEditorWindow: () => isRemoteEditorWindow,
@@ -266,7 +268,7 @@ __export(coreExports_exports, {
266
268
  setCoreRafDriver: () => setCoreRafDriver,
267
269
  setPrivateAPI: () => setPrivateAPI,
268
270
  types: () => propTypes_exports,
269
- val: () => val10
271
+ val: () => val11
270
272
  });
271
273
 
272
274
  // core/src/projects/projectsSingleton.ts
@@ -3234,11 +3236,11 @@ function sanitizeCompoundProps(props) {
3234
3236
  );
3235
3237
  }
3236
3238
  }
3237
- const val11 = props[key];
3238
- if (isLonghandPropType(val11)) {
3239
- sanitizedProps[key] = val11;
3239
+ const val12 = props[key];
3240
+ if (isLonghandPropType(val12)) {
3241
+ sanitizedProps[key] = val12;
3240
3242
  } else {
3241
- sanitizedProps[key] = toLonghandProp(val11);
3243
+ sanitizedProps[key] = toLonghandProp(val12);
3242
3244
  }
3243
3245
  }
3244
3246
  return sanitizedProps;
@@ -3336,15 +3338,15 @@ var file = (defaultValue, opts = {}) => {
3336
3338
  deserializeAndSanitize: _ensureFile
3337
3339
  };
3338
3340
  };
3339
- var _ensureFile = (val11) => {
3340
- if (!val11) return void 0;
3341
+ var _ensureFile = (val12) => {
3342
+ if (!val12) return void 0;
3341
3343
  let valid = true;
3342
- if (typeof val11.id !== "string" && ![null, void 0].includes(val11.id)) {
3344
+ if (typeof val12.id !== "string" && ![null, void 0].includes(val12.id)) {
3343
3345
  valid = false;
3344
3346
  }
3345
- if (val11.type !== "file") valid = false;
3347
+ if (val12.type !== "file") valid = false;
3346
3348
  if (!valid) return void 0;
3347
- return val11;
3349
+ return val12;
3348
3350
  };
3349
3351
  var image = (defaultValue, opts = {}) => {
3350
3352
  if (process.env.NODE_ENV !== "production") {
@@ -3368,15 +3370,15 @@ var image = (defaultValue, opts = {}) => {
3368
3370
  deserializeAndSanitize: _ensureImage
3369
3371
  };
3370
3372
  };
3371
- var _ensureImage = (val11) => {
3372
- if (!val11) return void 0;
3373
+ var _ensureImage = (val12) => {
3374
+ if (!val12) return void 0;
3373
3375
  let valid = true;
3374
- if (typeof val11.id !== "string" && ![null, void 0].includes(val11.id)) {
3376
+ if (typeof val12.id !== "string" && ![null, void 0].includes(val12.id)) {
3375
3377
  valid = false;
3376
3378
  }
3377
- if (val11.type !== "image") valid = false;
3379
+ if (val12.type !== "image") valid = false;
3378
3380
  if (!valid) return void 0;
3379
- return val11;
3381
+ return val12;
3380
3382
  };
3381
3383
  var number = (defaultValue, opts = {}) => {
3382
3384
  if (process.env.NODE_ENV !== "production") {
@@ -3499,11 +3501,11 @@ var rgba = (defaultValue = { r: 0, g: 0, b: 0, a: 1 }, opts = {}) => {
3499
3501
  deserializeAndSanitize: _sanitizeRgba
3500
3502
  };
3501
3503
  };
3502
- var _sanitizeRgba = (val11) => {
3503
- if (!val11) return void 0;
3504
+ var _sanitizeRgba = (val12) => {
3505
+ if (!val12) return void 0;
3504
3506
  let valid = true;
3505
3507
  for (const c2 of ["r", "g", "b", "a"]) {
3506
- if (!Object.prototype.hasOwnProperty.call(val11, c2) || typeof val11[c2] !== "number") {
3508
+ if (!Object.prototype.hasOwnProperty.call(val12, c2) || typeof val12[c2] !== "number") {
3507
3509
  valid = false;
3508
3510
  }
3509
3511
  }
@@ -3512,7 +3514,7 @@ var _sanitizeRgba = (val11) => {
3512
3514
  for (const c2 of ["r", "g", "b", "a"]) {
3513
3515
  ;
3514
3516
  sanitized[c2] = Math.min(
3515
- Math.max(val11[c2], 0),
3517
+ Math.max(val12[c2], 0),
3516
3518
  1
3517
3519
  );
3518
3520
  }
@@ -3551,8 +3553,8 @@ var boolean = (defaultValue, opts = {}) => {
3551
3553
  deserializeAndSanitize: _ensureBoolean
3552
3554
  };
3553
3555
  };
3554
- var _ensureBoolean = (val11) => {
3555
- return typeof val11 === "boolean" ? val11 : void 0;
3556
+ var _ensureBoolean = (val12) => {
3557
+ return typeof val12 === "boolean" ? val12 : void 0;
3556
3558
  };
3557
3559
  function leftInterpolate(left) {
3558
3560
  return left;
@@ -3759,8 +3761,8 @@ var TheatreSheetObject = class {
3759
3761
  }
3760
3762
  return der.getValue();
3761
3763
  }
3762
- set initialValue(val11) {
3763
- privateAPI(this).setInitialValue(val11);
3764
+ set initialValue(val12) {
3765
+ privateAPI(this).setInitialValue(val12);
3764
3766
  }
3765
3767
  showPropsOf(objects) {
3766
3768
  const host = privateAPI(this);
@@ -4528,9 +4530,9 @@ var SheetObject = class {
4528
4530
  }
4529
4531
  validateValue(pointer3, value) {
4530
4532
  }
4531
- setInitialValue(val11) {
4532
- this.validateValue(this.propsP, val11);
4533
- this._initialValue.set(val11);
4533
+ setInitialValue(val12) {
4534
+ this.validateValue(this.propsP, val12);
4535
+ this._initialValue.set(val12);
4534
4536
  }
4535
4537
  setSessionOverride(path, value) {
4536
4538
  const propConfig = getPropConfigByPath(this.template.staticConfig, path);
@@ -4550,8 +4552,8 @@ var SheetObject = class {
4550
4552
  * Internal: called by `RemoteSync` when a value update for this object
4551
4553
  * arrives from a remote editor window. Not exposed on the public API.
4552
4554
  */
4553
- setRemoteOverride(val11) {
4554
- this._remoteOverride.set(val11);
4555
+ setRemoteOverride(val12) {
4556
+ this._remoteOverride.set(val12);
4555
4557
  }
4556
4558
  /**
4557
4559
  * Internal: used by `RemoteSync` to subscribe to this object's fully
@@ -6223,6 +6225,19 @@ function isBasicKeyframedTrack(track) {
6223
6225
  function isGsapClipTrack(track) {
6224
6226
  return track.type === "GsapClipTrack";
6225
6227
  }
6228
+ function gsapClipEndTime(clip) {
6229
+ return clip.start + clip.duration;
6230
+ }
6231
+ function gsapClipSyncProgress(sequencePosition, clip) {
6232
+ if (clip.duration <= 0) return 0;
6233
+ if (sequencePosition < clip.start) return 0;
6234
+ const clipEnd = gsapClipEndTime(clip);
6235
+ if (sequencePosition >= clipEnd - 1e-5) return 1;
6236
+ const raw = (sequencePosition - clip.start) / clip.duration;
6237
+ if (raw <= 0) return 0;
6238
+ if (raw >= 1) return 1;
6239
+ return raw;
6240
+ }
6226
6241
 
6227
6242
  // core/src/sequences/Sequence.ts
6228
6243
  var possibleDirections = [
@@ -8351,13 +8366,13 @@ var Project = class {
8351
8366
  };
8352
8367
 
8353
8368
  // shared/src/utils/sanitizers.ts
8354
- var _validateSym = (val11, thingy, range) => {
8355
- if (typeof val11 !== "string") {
8356
- return "".concat(thingy, " must be a string. ").concat(userReadableTypeOfValue_default(val11), " given.");
8357
- } else if (val11.trim().length !== val11.length) {
8358
- return "".concat(thingy, " must not have leading or trailing spaces. '").concat(val11, "' given.");
8359
- } else if (val11.length < range[0] || val11.length > range[1]) {
8360
- return "".concat(thingy, " must have between ").concat(range[0], " and ").concat(range[1], " characters. '").concat(val11, "' given.");
8369
+ var _validateSym = (val12, thingy, range) => {
8370
+ if (typeof val12 !== "string") {
8371
+ return "".concat(thingy, " must be a string. ").concat(userReadableTypeOfValue_default(val12), " given.");
8372
+ } else if (val12.trim().length !== val12.length) {
8373
+ return "".concat(thingy, " must not have leading or trailing spaces. '").concat(val12, "' given.");
8374
+ } else if (val12.length < range[0] || val12.length > range[1]) {
8375
+ return "".concat(thingy, " must have between ").concat(range[0], " and ").concat(range[1], " characters. '").concat(val12, "' given.");
8361
8376
  }
8362
8377
  };
8363
8378
  var validateName = (name, thingy, shouldThrow = false) => {
@@ -8473,8 +8488,194 @@ var TheatreProject = class {
8473
8488
 
8474
8489
  // core/src/coreExports.ts
8475
8490
  var import_fast_deep_equal3 = __toESM(require_fast_deep_equal());
8491
+ var import_theatre_dataverse23 = require("@unseenco/theatre-dataverse");
8492
+ var import_theatre_dataverse24 = require("@unseenco/theatre-dataverse");
8493
+
8494
+ // shared/src/gsap/applyTimelineChildTiming.ts
8495
+ function applyTimelineChildTimingToGsap(rootAnimation, timelineChildren, childById, onRebuild) {
8496
+ if (!timelineChildren.length) return true;
8497
+ let ok = applyTimelineChildTimingToGsapInner(
8498
+ rootAnimation,
8499
+ timelineChildren,
8500
+ childById
8501
+ );
8502
+ if (!ok && onRebuild) {
8503
+ const rebuilt = onRebuild();
8504
+ if (rebuilt) {
8505
+ ok = applyTimelineChildTimingToGsapInner(
8506
+ rebuilt,
8507
+ timelineChildren,
8508
+ childById
8509
+ );
8510
+ }
8511
+ }
8512
+ return ok;
8513
+ }
8514
+ function applyTimelineChildTimingToGsapInner(rootAnimation, timelineChildren, childById) {
8515
+ if (!childById || timelineChildren.length === 0) return true;
8516
+ let ok = true;
8517
+ for (const childState of timelineChildren) {
8518
+ const tween = childById.get(childState.childId);
8519
+ if (!tween) continue;
8520
+ try {
8521
+ const t2 = tween;
8522
+ if (typeof t2.startTime === "function") {
8523
+ t2.startTime(childState.localStart);
8524
+ }
8525
+ if (typeof t2.duration === "function") {
8526
+ t2.duration(childState.localDuration);
8527
+ }
8528
+ } catch {
8529
+ ok = false;
8530
+ }
8531
+ }
8532
+ return ok;
8533
+ }
8534
+
8535
+ // shared/src/gsap/syncGsapClipProgress.ts
8536
+ function getGsapAnimationTargetKey(animation, fallbackAnimationId) {
8537
+ const tween = animation;
8538
+ const targets = tween.targets?.();
8539
+ if (targets && targets.length > 0) {
8540
+ return targets[0];
8541
+ }
8542
+ return fallbackAnimationId;
8543
+ }
8544
+ function syncRegisteredGsapAnimationsForClips(sequencePosition, clips) {
8545
+ const enriched = [];
8546
+ for (const clip of clips) {
8547
+ const entry = getAnimationEntryBySheetAddressKey(
8548
+ clip.sheetObjectAddressKey,
8549
+ clip.gsapAnimationId
8550
+ );
8551
+ if (!entry?.animation) continue;
8552
+ enriched.push({
8553
+ ...clip,
8554
+ entry,
8555
+ targetKey: getGsapAnimationTargetKey(
8556
+ entry.animation,
8557
+ clip.gsapAnimationId
8558
+ )
8559
+ });
8560
+ }
8561
+ const byTarget = /* @__PURE__ */ new Map();
8562
+ for (const item of enriched) {
8563
+ const list = byTarget.get(item.targetKey) ?? [];
8564
+ list.push(item);
8565
+ byTarget.set(item.targetKey, list);
8566
+ }
8567
+ for (const group of byTarget.values()) {
8568
+ const sorted = [...group].sort((a2, b2) => a2.start - b2.start);
8569
+ for (const clip of sorted) {
8570
+ const progress = gsapClipSyncProgress(sequencePosition, clip);
8571
+ const entry = clip.entry;
8572
+ const animation = entry.animation;
8573
+ if (entry.kind === "timeline" && clip.timelineChildren && clip.timelineChildren.length > 0) {
8574
+ applyTimelineChildTimingToGsap(
8575
+ entry.animation,
8576
+ clip.timelineChildren,
8577
+ entry.timelineChildById,
8578
+ entry.onRebuildTimeline
8579
+ );
8580
+ const span = clip.timelineSpan ?? readGsapTweenTimelineDuration(entry.animation);
8581
+ const t2 = progress * Math.max(span, 0.01);
8582
+ if (typeof animation.time === "function") {
8583
+ animation.time(t2, true);
8584
+ } else {
8585
+ animation.progress?.(progress, true);
8586
+ }
8587
+ } else {
8588
+ animation.progress?.(progress, true);
8589
+ }
8590
+ }
8591
+ }
8592
+ }
8593
+ function readGsapTweenTimelineDuration(animation) {
8594
+ const tween = animation;
8595
+ const total = tween.totalDuration?.();
8596
+ if (typeof total === "number" && total > 0) return total;
8597
+ const d2 = tween.duration();
8598
+ return d2 > 0 ? d2 : 1;
8599
+ }
8600
+
8601
+ // shared/src/gsap/gsapStudioRegistryRevision.ts
8476
8602
  var import_theatre_dataverse21 = require("@unseenco/theatre-dataverse");
8603
+ var revisionAtom = new import_theatre_dataverse21.Atom(0);
8604
+ var gsapStudioRegistryRevisionPointer = revisionAtom.pointer;
8605
+
8606
+ // shared/src/gsap/gsapAnimationRegistry.ts
8607
+ var DEFAULT_SHEET_INSTANCE_ID = "default";
8608
+ var REGISTRY_KEY = "__unseenco_theatre_gsap_animationRegistry__";
8609
+ function sheetObjectAddressKeyFromParts(address) {
8610
+ const sheetInstanceId = address.sheetInstanceId ?? DEFAULT_SHEET_INSTANCE_ID;
8611
+ return "".concat(address.projectId, "|").concat(address.sheetId, "|").concat(sheetInstanceId, "|").concat(address.objectKey);
8612
+ }
8613
+ function getStore() {
8614
+ const g2 = globalThis;
8615
+ if (!g2[REGISTRY_KEY]) {
8616
+ g2[REGISTRY_KEY] = {
8617
+ bySheetAddress: /* @__PURE__ */ new Map()
8618
+ };
8619
+ }
8620
+ return g2[REGISTRY_KEY];
8621
+ }
8622
+ function getAnimationEntryBySheetAddressKey(sheetObjectAddressKey, animationId) {
8623
+ return getStore().bySheetAddress.get(sheetObjectAddressKey)?.get(animationId);
8624
+ }
8625
+
8626
+ // shared/src/gsap/subscribeGsapClipSyncAtPlayhead.ts
8477
8627
  var import_theatre_dataverse22 = require("@unseenco/theatre-dataverse");
8628
+
8629
+ // shared/src/gsap/syncGsapClipsAtSequencePosition.ts
8630
+ function syncGsapClipsAtSequencePosition(position, clips) {
8631
+ syncRegisteredGsapAnimationsForClips(
8632
+ position,
8633
+ clips
8634
+ );
8635
+ }
8636
+
8637
+ // shared/src/gsap/subscribeGsapClipSyncAtPlayhead.ts
8638
+ function subscribeGsapClipSyncAtPlayhead(source) {
8639
+ const positionPointer = source.pointer.position;
8640
+ const positionPrism = (0, import_theatre_dataverse22.pointerToPrism)(positionPointer);
8641
+ const clipsPrism = (0, import_theatre_dataverse22.prism)(() => source.getGsapClipTimings());
8642
+ const syncNow = () => {
8643
+ const clips = clipsPrism.getValue();
8644
+ if (clips.length === 0) return;
8645
+ syncGsapClipsAtSequencePosition((0, import_theatre_dataverse22.val)(positionPointer), clips);
8646
+ };
8647
+ const untapPosition = positionPrism.onStale(syncNow);
8648
+ const untapClips = clipsPrism.onStale(syncNow);
8649
+ syncNow();
8650
+ return () => {
8651
+ untapPosition();
8652
+ untapClips();
8653
+ };
8654
+ }
8655
+
8656
+ // core/src/gsap/attachGsapSequenceBridge.ts
8657
+ function attachGsapSequenceBridge(sheet) {
8658
+ const sequence = sheet.sequence;
8659
+ const sheetAddress = privateAPI(sheet).address;
8660
+ return subscribeGsapClipSyncAtPlayhead({
8661
+ pointer: sequence.pointer,
8662
+ getGsapClipTimings: () => sequence.__experimental_getGsapClips().map(({ objectKey, clip }) => ({
8663
+ sheetObjectAddressKey: sheetObjectAddressKeyFromParts({
8664
+ projectId: sheetAddress.projectId,
8665
+ sheetId: sheetAddress.sheetId,
8666
+ sheetInstanceId: sheetAddress.sheetInstanceId,
8667
+ objectKey
8668
+ }),
8669
+ gsapAnimationId: clip.gsapAnimationId,
8670
+ start: clip.start,
8671
+ duration: clip.duration,
8672
+ timelineChildren: clip.timelineChildren,
8673
+ timelineSpan: clip.timelineSpan
8674
+ }))
8675
+ });
8676
+ }
8677
+
8678
+ // core/src/coreExports.ts
8478
8679
  function getProject(id, config = {}) {
8479
8680
  const existingProject = projectsSingleton_default.get(id);
8480
8681
  if (existingProject) {
@@ -8554,10 +8755,10 @@ var validateProjectIdOrThrow = (value) => {
8554
8755
  };
8555
8756
  function onChange(pointer3, callback, rafDriver) {
8556
8757
  const ticker = rafDriver ? privateAPI(rafDriver).ticker : getCoreTicker();
8557
- if ((0, import_theatre_dataverse21.isPointer)(pointer3)) {
8558
- const pr = (0, import_theatre_dataverse22.pointerToPrism)(pointer3);
8758
+ if ((0, import_theatre_dataverse23.isPointer)(pointer3)) {
8759
+ const pr = (0, import_theatre_dataverse24.pointerToPrism)(pointer3);
8559
8760
  return pr.onChange(ticker, callback, true);
8560
- } else if ((0, import_theatre_dataverse22.isPrism)(pointer3)) {
8761
+ } else if ((0, import_theatre_dataverse24.isPrism)(pointer3)) {
8561
8762
  return pointer3.onChange(ticker, callback, true);
8562
8763
  } else {
8563
8764
  throw new Error(
@@ -8565,9 +8766,9 @@ function onChange(pointer3, callback, rafDriver) {
8565
8766
  );
8566
8767
  }
8567
8768
  }
8568
- function val10(pointer3) {
8569
- if ((0, import_theatre_dataverse21.isPointer)(pointer3)) {
8570
- return (0, import_theatre_dataverse22.pointerToPrism)(pointer3).getValue();
8769
+ function val11(pointer3) {
8770
+ if ((0, import_theatre_dataverse23.isPointer)(pointer3)) {
8771
+ return (0, import_theatre_dataverse24.pointerToPrism)(pointer3).getValue();
8571
8772
  } else {
8572
8773
  throw new Error("Called val(p) where p is not a pointer.");
8573
8774
  }
@@ -8582,7 +8783,7 @@ var CoreBundle = class {
8582
8783
  return "Theatre_CoreBundle";
8583
8784
  }
8584
8785
  get version() {
8585
- return "0.4.2";
8786
+ return "0.4.3";
8586
8787
  }
8587
8788
  getBitsForStudio(studio, callback) {
8588
8789
  if (this._studio) {