hyperframes 0.8.128 → 0.8.129

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 (147) hide show
  1. package/dist/{add-DI4T5YLH.js → add-MFBQ4JQ3.js} +14 -14
  2. package/dist/{animatedGifPrep-TSK322QL.js → animatedGifPrep-P2T6YM7Z.js} +5 -5
  3. package/dist/{asset-CFW5RUI3.js → asset-LOZG7JHC.js} +2 -2
  4. package/dist/{assetCataloger-MDMKZM4O.js → assetCataloger-VBLPHX24.js} +2 -2
  5. package/dist/{auth-7GR2JYK4.js → auth-JKCXKQRS.js} +2 -2
  6. package/dist/{autoUpdate-VPEWPSH6.js → autoUpdate-5KHORE4C.js} +2 -2
  7. package/dist/{backgroundChecks-XU7Y6JEZ.js → backgroundChecks-DTVWBC74.js} +3 -3
  8. package/dist/backgroundChecksWorker.js +3 -3
  9. package/dist/{batchRender-HIRFZIUO.js → batchRender-FT7AP7XH.js} +3 -3
  10. package/dist/{beats-6EJDWT63.js → beats-ZLLBJMPB.js} +11 -11
  11. package/dist/{benchmark-F7U6WZGQ.js → benchmark-RU2FBIWR.js} +11 -11
  12. package/dist/{browser-3ECFI3DA.js → browser-RQV6NSLN.js} +8 -8
  13. package/dist/{bundleWithLocalizedFonts-OVFXAXV3.js → bundleWithLocalizedFonts-5QOPOB5D.js} +2 -2
  14. package/dist/{capture-YH5MUSL7.js → capture-RLZA6EMR.js} +8 -8
  15. package/dist/{capture-AC5TRHS5.js → capture-SZZ4IYJK.js} +2 -2
  16. package/dist/{catalog-TRZAPAXM.js → catalog-LYPHWJDJ.js} +14 -14
  17. package/dist/{check-HP7N4TPB.js → check-R4UNOR5Z.js} +30 -30
  18. package/dist/{checkBrowser-BHLSXZ3V.js → checkBrowser-RSUTDBXE.js} +29 -29
  19. package/dist/{chunk-YRKBFZDQ.js → chunk-2YN64IN5.js} +1 -1
  20. package/dist/{chunk-LGTAOCIM.js → chunk-3ZP5DXE7.js} +1 -1
  21. package/dist/{chunk-L5IFUB5G.js → chunk-557OWRHF.js} +2 -2
  22. package/dist/{chunk-A7VIBZLC.js → chunk-6CTIGJY7.js} +1 -1
  23. package/dist/{chunk-6RGOHYPP.js → chunk-7HG4BFIN.js} +1 -1
  24. package/dist/{chunk-FN7KZDH7.js → chunk-7JZ4FXP2.js} +1 -1
  25. package/dist/{chunk-KC5COKLP.js → chunk-A2Z4Z4VL.js} +1 -1
  26. package/dist/{chunk-OESXJGYM.js → chunk-B6YD6JAS.js} +1 -1
  27. package/dist/{chunk-CF6QQ6CL.js → chunk-BI6TVCDI.js} +7 -7
  28. package/dist/{chunk-BELUXCL4.js → chunk-CFKU7HTK.js} +1 -1
  29. package/dist/{chunk-LRDOFHS5.js → chunk-CWPVM2QV.js} +2 -2
  30. package/dist/{chunk-QPRIMML2.js → chunk-FCSIGXXP.js} +1 -1
  31. package/dist/{chunk-VQME2GRN.js → chunk-GO74M65A.js} +9 -9
  32. package/dist/{chunk-BK2KLAYO.js → chunk-GOAUWA46.js} +2 -2
  33. package/dist/{chunk-H5TVAQAK.js → chunk-H64TB7NB.js} +4 -4
  34. package/dist/{chunk-4DGJUQFZ.js → chunk-HRUGC23L.js} +1 -1
  35. package/dist/chunk-HWKCIWQT.js +3578 -0
  36. package/dist/{chunk-4IZNC32H.js → chunk-IUZFXWSV.js} +1 -1
  37. package/dist/{chunk-JDNYDR3Y.js → chunk-IXCQU5RO.js} +1 -1
  38. package/dist/{chunk-WULYBA5Y.js → chunk-JO2J4S2L.js} +3 -3
  39. package/dist/{chunk-COD4GMYB.js → chunk-K2EQN4VU.js} +1 -1
  40. package/dist/{chunk-77EJSKGP.js → chunk-K2FTXJYH.js} +2 -2
  41. package/dist/{chunk-2CACHG7K.js → chunk-KBJUXVOJ.js} +3 -3
  42. package/dist/{chunk-AQUXI6ZL.js → chunk-KHSCFD7K.js} +5 -5
  43. package/dist/{chunk-UROSVQOH.js → chunk-LHSR3M4M.js} +2 -2
  44. package/dist/{chunk-6F63NYFZ.js → chunk-LYNI3FOL.js} +1 -1
  45. package/dist/{chunk-56P5SEOM.js → chunk-MWB3ZIFM.js} +1 -1
  46. package/dist/{chunk-ZT4WM4B6.js → chunk-NTIV6QFJ.js} +9 -9
  47. package/dist/{chunk-34C66AH5.js → chunk-Q7IU7MOR.js} +2 -2
  48. package/dist/{chunk-BE6X3G5C.js → chunk-QC4FJVLM.js} +1 -1
  49. package/dist/{chunk-72WHJNAR.js → chunk-QZDMFVY7.js} +2 -2
  50. package/dist/{chunk-BW773MMX.js → chunk-RMHUQGRK.js} +2 -2
  51. package/dist/{chunk-KUZTSKD2.js → chunk-RZAAVJ2F.js} +1 -1
  52. package/dist/{chunk-5NZVDRRZ.js → chunk-S7NPLFWV.js} +88 -16
  53. package/dist/{chunk-RLK4ARFU.js → chunk-TCLGPL65.js} +1 -1
  54. package/dist/{chunk-4AH73ZQW.js → chunk-UBC3SMKR.js} +1 -1
  55. package/dist/{chunk-Q767NO4V.js → chunk-UDO4A3HY.js} +3 -3
  56. package/dist/{chunk-3PDQ4PS2.js → chunk-UEZXMWG3.js} +2 -2
  57. package/dist/{chunk-IKSUSTJT.js → chunk-WWTEA2BG.js} +1 -1
  58. package/dist/{chunk-4QJQOVN4.js → chunk-XS4EJSKU.js} +1 -1
  59. package/dist/{chunk-VKBSHU24.js → chunk-YQZNILVH.js} +5 -5
  60. package/dist/{chunk-WVU5CJXG.js → chunk-Z6B37SNM.js} +1 -1
  61. package/dist/{chunk-QFQET76X.js → chunk-ZMXUQLI2.js} +7 -7
  62. package/dist/{clean-6Q36AWQL.js → clean-RDKBYQYS.js} +14 -14
  63. package/dist/cli.js +51 -51
  64. package/dist/{cloud-GQ5UHZZN.js → cloud-DRCSH3RO.js} +4 -4
  65. package/dist/{cloudrun-JD7H36SS.js → cloudrun-AJUTHUEA.js} +3 -3
  66. package/dist/{compare-YONA7IFI.js → compare-EJNCWA7A.js} +24 -24
  67. package/dist/{compiler-GNV7YQRO.js → compiler-QO36EXLS.js} +2 -2
  68. package/dist/{component-BXHWGVG4.js → component-55TKGKMP.js} +3 -3
  69. package/dist/{compositions-XC7Y2FPL.js → compositions-LDU2NXG3.js} +10 -10
  70. package/dist/{delete-73UVP2DH.js → delete-M5FEYAQW.js} +2 -2
  71. package/dist/{dist-NDHKRZTY.js → dist-S3PJNPXQ.js} +2 -2
  72. package/dist/{doctor-J76TZOKL.js → doctor-AGGUO5NJ.js} +9 -9
  73. package/dist/{events-FB2W7SMV.js → events-CIWUMG4Z.js} +8 -8
  74. package/dist/{events-I3JMSDHY.js → events-LBZKC7L7.js} +7 -7
  75. package/dist/{feedback-WSIA7ROU.js → feedback-J7I7VS4Q.js} +9 -9
  76. package/dist/{figma-YOJEBRSS.js → figma-2AIFPR3T.js} +3 -3
  77. package/dist/fontLocalizeCli.js +7 -7
  78. package/dist/{get-DXEKFVNL.js → get-ZJBDIWZJ.js} +2 -2
  79. package/dist/{gpuPolicy-IGXJ6JGL.js → gpuPolicy-2ZUZE5D6.js} +5 -5
  80. package/dist/{grade-compare-PXBFW53F.js → grade-compare-XVYJT6ZR.js} +24 -24
  81. package/dist/{help-Z6TEXIAO.js → help-TBVVVEDS.js} +1 -1
  82. package/dist/{history-EFWP3CMR.js → history-NZPEQU4L.js} +14 -14
  83. package/dist/hyperframe-runtime.js +30 -30
  84. package/dist/hyperframe.manifest.json +1 -1
  85. package/dist/hyperframe.runtime.iife.js +30 -30
  86. package/dist/hyperframes-player.global.js +3 -3
  87. package/dist/{info-AQ2ZLWSB.js → info-T6BT2MFN.js} +10 -10
  88. package/dist/{init-6ZEBBSR5.js → init-4EPQ7SDV.js} +21 -21
  89. package/dist/{inspect-EUOV4DGL.js → inspect-BPZFMWWW.js} +25 -25
  90. package/dist/{installer-WI6EKOWS.js → installer-K6O5WF44.js} +4 -4
  91. package/dist/{keyframes-U6LVMYGO.js → keyframes-UL3XY52K.js} +11 -11
  92. package/dist/{lambda-F6SI24C7.js → lambda-D7UMN4DJ.js} +4 -4
  93. package/dist/{layout-VQRYMZRP.js → layout-YYGOEQKI.js} +25 -25
  94. package/dist/{lint-EBHMQRKO.js → lint-OW2KOTEE.js} +11 -11
  95. package/dist/{list-EUOXTLX6.js → list-EIDAPK3I.js} +2 -2
  96. package/dist/{login-OXGFQNHT.js → login-DWU6OUCZ.js} +4 -4
  97. package/dist/{media-treatment-TVCTGGDO.js → media-treatment-I7BTOWX4.js} +11 -11
  98. package/dist/{models-XNX7UHKU.js → models-C4E4IWJD.js} +6 -6
  99. package/dist/{motionShot-JXQIO5VJ.js → motionShot-S4MIGMT5.js} +11 -11
  100. package/dist/{normalize-audio-L5LTPJIR.js → normalize-audio-X2M4VF2O.js} +10 -10
  101. package/dist/{open-BON6TWUG.js → open-35JKHN2G.js} +9 -9
  102. package/dist/{pipeline-NID4HZDH.js → pipeline-TNGWUZQC.js} +5 -5
  103. package/dist/{play-GH43JSBS.js → play-F2LMNJEH.js} +19 -19
  104. package/dist/{preflight-VSZD4AND.js → preflight-SMNV6RW2.js} +6 -6
  105. package/dist/{present-7PTSYTYU.js → present-AD4N25LI.js} +15 -15
  106. package/dist/{preview-X2WVPV66.js → preview-QWMTUNE2.js} +16 -16
  107. package/dist/{producer-TLATG6GZ.js → producer-ECLEN5RP.js} +1 -1
  108. package/dist/{projectConfig-KKPSSHER.js → projectConfig-HYJMJ5BY.js} +6 -6
  109. package/dist/{publication-6BFZTAYA.js → publication-HQ5Y3KBM.js} +2 -2
  110. package/dist/{publish-ZDRTAWEH.js → publish-VHDYQASC.js} +7 -7
  111. package/dist/{remove-background-OZ4OR3B2.js → remove-background-W2YX2NVH.js} +6 -6
  112. package/dist/{render-ZH5ZCLWA.js → render-2HZ6WDVA.js} +11 -11
  113. package/dist/{render-U3BRPPSW.js → render-AO5VX3YI.js} +3 -3
  114. package/dist/{render-ZTIEKMAN.js → render-JJVVEVIZ.js} +20 -20
  115. package/dist/{render-batch-3JALVFQN.js → render-batch-YH7CTWNY.js} +3 -3
  116. package/dist/{renderCancellation-NHRJYSHT.js → renderCancellation-JPIHE47X.js} +5 -5
  117. package/dist/{resolver-Z2T2GU2O.js → resolver-IZ647GBZ.js} +4 -4
  118. package/dist/{sherpa-DRIVXEAC.js → sherpa-KKLNW6U2.js} +6 -6
  119. package/dist/{skills-XLN4DLZP.js → skills-O7QZLKAG.js} +10 -10
  120. package/dist/{skillsUpdateCheck-CDL66I4W.js → skillsUpdateCheck-W563PHIX.js} +3 -3
  121. package/dist/{snapshot-63YZCABA.js → snapshot-4M37T4WP.js} +25 -25
  122. package/dist/{src-3Q2T2TAT.js → src-6YQBJGWR.js} +6 -6
  123. package/dist/{src-3M44XVWE.js → src-PVYUYV3M.js} +4 -4
  124. package/dist/{staticProjectServer-F563BICS.js → staticProjectServer-7EU666GS.js} +13 -13
  125. package/dist/{status-HPLBWFSU.js → status-YM52BQ6S.js} +5 -5
  126. package/dist/studio/assets/{hyperframes-player-CKCx0CFA.js → hyperframes-player-DfEcBl9r.js} +1 -1
  127. package/dist/studio/assets/{index-CF31Pq1E.js → index-9ZaZFCMZ.js} +1 -1
  128. package/dist/studio/assets/{index-CwS08gWW.js → index-Bmy-KVib.js} +1 -1
  129. package/dist/studio/assets/{index-ClLzyuwb.js → index-C9YkEyN4.js} +154 -154
  130. package/dist/studio/index.html +1 -1
  131. package/dist/studio/index.js +206 -51
  132. package/dist/studio/index.js.map +1 -1
  133. package/dist/{studio-api-PH5PMXQW.js → studio-api-PNQZRPX5.js} +7 -7
  134. package/dist/{studioServer-4CEIYT2G.js → studioServer-PTUEDJ4R.js} +44 -38
  135. package/dist/{system-G6PL23LG.js → system-EZYZNUFD.js} +5 -5
  136. package/dist/{telemetry-ILX6SWZM.js → telemetry-DTSHY4NX.js} +8 -8
  137. package/dist/{timeline-3K3WNFPP.js → timeline-OQEMNGIW.js} +14 -14
  138. package/dist/{tokens-GKA5I6SX.js → tokens-IGPEYHDJ.js} +2 -2
  139. package/dist/{transcribe-P76R64RU.js → transcribe-BNSJRR4M.js} +6 -6
  140. package/dist/{transcribe-ZZSCMKNC.js → transcribe-LC5JLRDF.js} +11 -11
  141. package/dist/{updateCheck-QBLDWYDK.js → updateCheck-OJAVDMMV.js} +2 -2
  142. package/dist/{upgrade-RDBANWHF.js → upgrade-2G4MARM4.js} +2 -2
  143. package/dist/{urlDownloader-VVG2YURO.js → urlDownloader-H6WRI2UE.js} +4 -4
  144. package/dist/{validate-55V46LZZ.js → validate-MOUGAHM2.js} +15 -15
  145. package/dist/{video-S2W6UQ4H.js → video-FGSGKRSV.js} +5 -5
  146. package/package.json +1 -1
  147. package/dist/chunk-AQIS2UNW.js +0 -3578
@@ -14,7 +14,7 @@
14
14
  document.documentElement.dataset.theme = "paper";
15
15
  }
16
16
  </script>
17
- <script type="module" crossorigin src="/assets/index-ClLzyuwb.js"></script>
17
+ <script type="module" crossorigin src="/assets/index-C9YkEyN4.js"></script>
18
18
  <link rel="stylesheet" crossorigin href="/assets/index-D11atkBt.css">
19
19
  </head>
20
20
  <body>
@@ -17395,6 +17395,14 @@ function applySoftReloadFinalization(iframe, currentTime) {
17395
17395
  function timelineKeys(scriptText) {
17396
17396
  return [...scriptText.matchAll(/__timelines\s*\[\s*["'`]([^"'`]+)["'`]\s*\]/g)].map((m) => m[1]).filter((key2) => key2 !== "__proxied");
17397
17397
  }
17398
+ function scriptsRegistering(scripts, keys) {
17399
+ return scripts.filter((script) => {
17400
+ const text = script.textContent || "";
17401
+ return keys.some(
17402
+ (key2) => text.includes(`__timelines["${key2}"]`) || text.includes(`__timelines['${key2}']`)
17403
+ );
17404
+ });
17405
+ }
17398
17406
  function applySoftReload(iframe, scriptText, options = {}) {
17399
17407
  const { onAsyncFailure, currentTimeOverride, authoredHtml } = options;
17400
17408
  if (!iframe || !scriptText) return "cannot-soft-reload";
@@ -17407,12 +17415,7 @@ function applySoftReload(iframe, scriptText, options = {}) {
17407
17415
  if (targetKeys.length === 0) return "cannot-soft-reload";
17408
17416
  const gsapScripts = findGsapScriptElements(doc);
17409
17417
  if (gsapScripts.length === 0) return "cannot-soft-reload";
17410
- const staleScripts = gsapScripts.filter(
17411
- (script) => targetKeys.some((key2) => {
17412
- const text = script.textContent || "";
17413
- return text.includes(`__timelines["${key2}"]`) || text.includes(`__timelines['${key2}']`);
17414
- })
17415
- );
17418
+ const staleScripts = scriptsRegistering(gsapScripts, targetKeys);
17416
17419
  if (gsapScripts.length > 1 && staleScripts.length === 0) return "cannot-soft-reload";
17417
17420
  const currentTime = currentTimeOverride ?? win.__player?.getTime?.() ?? 0;
17418
17421
  let deferredToAsync = false;
@@ -17682,6 +17685,159 @@ function postGsapMutations(projectId, filePath, mutations, fallback) {
17682
17685
  // src/hooks/timelineTimingSync.ts
17683
17686
  import { findTimelineScript } from "@hyperframes/core/gsap-parser-acorn";
17684
17687
  import { walkCompositionDescendants } from "@hyperframes/parsers/hf-ids";
17688
+
17689
+ // src/utils/gsapLiveRetime.ts
17690
+ import { parseGsapScriptAcorn } from "@hyperframes/core/gsap-parser-acorn";
17691
+ import { hasExplicitTime } from "@hyperframes/parsers/gsap-writer-acorn";
17692
+ import { RUNTIME_FILLER } from "@hyperframes/core/runtime/protocol";
17693
+ var RERUN = { kind: "rerun" };
17694
+ var withoutLayout = (code) => code.replace(/\s+/g, " ").replace(/ ?([^\w$ ]) ?/g, "$1").trim();
17695
+ function untimedShape(animation) {
17696
+ const { id: _id, position: _p, resolvedStart: _s, duration: _d, ...rest } = animation;
17697
+ const provenance = rest.provenance && { ...rest.provenance, sourceRange: void 0 };
17698
+ return JSON.stringify(
17699
+ { ...rest, provenance },
17700
+ (_key, value) => typeof value === "string" && value.startsWith("__raw:") ? withoutLayout(value) : value
17701
+ );
17702
+ }
17703
+ var onTimeline = (animation) => !animation.global;
17704
+ var placedAlone = (animation) => hasExplicitTime(animation) && typeof animation.resolvedStart === "number";
17705
+ var lengthOf = (animation) => animation.method === "set" ? 0 : animation.durationUnresolved ? void 0 : animation.duration;
17706
+ var withoutNumbers = (script) => withoutLayout(script.replace(/(?<![\w$#.])\d*\.?\d+/g, "0"));
17707
+ function planLiveRetime(before, after) {
17708
+ if (withoutNumbers(before) !== withoutNumbers(after)) return RERUN;
17709
+ const keys = timelineKeys(after);
17710
+ if (keys.length !== 1 || timelineKeys(before).join() !== keys.join()) return RERUN;
17711
+ const was = parseGsapScriptAcorn(before).animations.filter(onTimeline);
17712
+ const now2 = parseGsapScriptAcorn(after).animations.filter(onTimeline);
17713
+ if (was.length !== now2.length) return RERUN;
17714
+ const tweens = [];
17715
+ for (const [index, next] of now2.entries()) {
17716
+ const prev = was[index];
17717
+ if (untimedShape(prev) !== untimedShape(next)) return RERUN;
17718
+ if (!placedAlone(next) || !placedAlone(prev)) return RERUN;
17719
+ const duration = lengthOf(next);
17720
+ const wasDuration = lengthOf(prev);
17721
+ if (duration === void 0 || wasDuration === void 0) return RERUN;
17722
+ tweens.push({
17723
+ selector: next.targetSelector,
17724
+ start: next.resolvedStart,
17725
+ duration,
17726
+ wasStart: prev.resolvedStart,
17727
+ wasDuration,
17728
+ moved: next.resolvedStart !== prev.resolvedStart || duration !== wasDuration,
17729
+ source: index
17730
+ });
17731
+ }
17732
+ tweens.sort((x, y) => x.wasStart - y.wasStart || x.source - y.source);
17733
+ return { kind: "retime", key: keys[0], after, tweens };
17734
+ }
17735
+ function planLiveRetimeFromPreview(iframe, after) {
17736
+ const doc = iframe?.contentDocument;
17737
+ const [key2] = timelineKeys(after);
17738
+ if (!doc || !key2) return RERUN;
17739
+ const [script, ...extra] = scriptsRegistering(findGsapScriptElements(doc), [key2]);
17740
+ if (!script || extra.length > 0) return RERUN;
17741
+ const plan = planLiveRetime(script.textContent ?? "", after);
17742
+ return plan.kind === "retime" ? { ...plan, script } : RERUN;
17743
+ }
17744
+ var same = (a, b) => Math.abs(a - b) < 1e-6;
17745
+ var targetsMatch = (tween, selector) => {
17746
+ const targets = tween.targets?.() ?? [];
17747
+ try {
17748
+ return targets.length > 0 && targets.every((t2) => t2.matches?.(selector) === true);
17749
+ } catch {
17750
+ return false;
17751
+ }
17752
+ };
17753
+ function pairedLiveTweens(timeline, plan) {
17754
+ const children = timeline.getChildren(false, true, false).filter((tween) => tween.data !== RUNTIME_FILLER);
17755
+ if (children.length !== plan.tweens.length) return null;
17756
+ const paired = plan.tweens.every((t2, i) => {
17757
+ const live = children[i];
17758
+ return targetsMatch(live, t2.selector) && same(live.startTime() - live.delay(), t2.wasStart) && same(live.duration(), t2.wasDuration);
17759
+ });
17760
+ return paired ? children : null;
17761
+ }
17762
+ var near2 = (a, b) => Math.abs(a - b) <= 2e-3;
17763
+ function sharesOneStretch(tweens) {
17764
+ const first = tweens[0];
17765
+ const last = tweens.at(-1);
17766
+ const longest = tweens.reduce((x, y) => y.wasDuration > x.wasDuration ? y : x);
17767
+ const spread = last.wasStart - first.wasStart;
17768
+ const stretch = spread > longest.wasDuration ? (last.start - first.start) / spread : longest.wasDuration > 0 ? longest.duration / longest.wasDuration : 1;
17769
+ const fits = tweens.every(
17770
+ (t2) => near2(t2.start, first.start + stretch * (t2.wasStart - first.wasStart)) && near2(t2.duration, stretch * t2.wasDuration)
17771
+ );
17772
+ return stretch > 0 && fits;
17773
+ }
17774
+ function inOrHostsSubComposition(target, ownId) {
17775
+ const element = target;
17776
+ const owner = element.closest?.("[data-composition-id]");
17777
+ return owner != null && owner.getAttribute("data-composition-id") !== ownId || element.querySelector?.("[data-composition-id]") != null;
17778
+ }
17779
+ var keepsOrder = (tweens) => tweens.every(
17780
+ (t2, k) => k === 0 || (tweens[k - 1].start - t2.start || tweens[k - 1].source - t2.source) < 0
17781
+ );
17782
+ function movesKeepEachElementsHistory(timeline, plan, children) {
17783
+ const byElement = /* @__PURE__ */ new Map();
17784
+ children.forEach((child, i) => {
17785
+ for (const target of child.targets?.() ?? []) {
17786
+ const indexes = byElement.get(target);
17787
+ if (indexes) indexes.push(i);
17788
+ else byElement.set(target, [i]);
17789
+ }
17790
+ });
17791
+ const moved = /* @__PURE__ */ new Set();
17792
+ for (const [target, indexes] of byElement) {
17793
+ if (!indexes.some((i) => plan.tweens[i].moved)) continue;
17794
+ if (inOrHostsSubComposition(target, plan.key)) return false;
17795
+ const tweens = indexes.map((i) => plan.tweens[i]);
17796
+ const shifted = tweens.every((t2) => t2.duration === t2.wasDuration);
17797
+ const undelayed = indexes.every((i) => !children[i].delay() && !children[i].repeatDelay?.());
17798
+ if (!keepsOrder(tweens) || !sharesOneStretch(tweens) || !(shifted || undelayed)) return false;
17799
+ moved.add(target);
17800
+ }
17801
+ return !timeline.getChildren(false, false, true).some(
17802
+ (sub) => sub.getChildren(true, true, false).some((tween) => tween.targets?.().some((t2) => moved.has(t2)))
17803
+ );
17804
+ }
17805
+ function applyLiveRetime(iframe, plan) {
17806
+ const win = iframe?.contentWindow;
17807
+ const timeline = win?.__timelines?.[plan.key];
17808
+ if (typeof timeline?.getChildren !== "function") return false;
17809
+ const children = pairedLiveTweens(timeline, plan);
17810
+ if (!children) return false;
17811
+ if (plan.tweens.some((t2) => t2.moved)) {
17812
+ if (!movesKeepEachElementsHistory(timeline, plan, children)) return false;
17813
+ const bySource = plan.tweens.map((t2, i) => ({ ...t2, tween: children[i] })).sort((a, b) => a.source - b.source);
17814
+ for (const { tween } of bySource) timeline.remove(tween);
17815
+ for (const { tween, start, duration } of bySource) {
17816
+ if (tween.duration() !== duration) tween.duration(duration);
17817
+ timeline.add(tween, start);
17818
+ }
17819
+ const at = timeline.time();
17820
+ timeline.progress(1e-4, true);
17821
+ timeline.totalTime(at, false);
17822
+ }
17823
+ plan.script.textContent = plan.after;
17824
+ return true;
17825
+ }
17826
+ function moveLiveTweens(iframe, scriptText, currentTime, reloadPreview) {
17827
+ const plan = planLiveRetimeFromPreview(iframe, scriptText);
17828
+ if (plan.kind !== "retime") return false;
17829
+ try {
17830
+ if (!applyLiveRetime(iframe, plan)) return false;
17831
+ } catch (error) {
17832
+ console.error("[Studio] Moving the live tweens threw; reloading the preview", error);
17833
+ reloadPreview();
17834
+ return true;
17835
+ }
17836
+ if (!applySoftReloadFinalization(iframe, currentTime)) reloadPreview();
17837
+ return true;
17838
+ }
17839
+
17840
+ // src/hooks/timelineTimingSync.ts
17685
17841
  async function readFileContent(projectId, targetPath) {
17686
17842
  if (targetPath.includes("\0") || targetPath.includes("..")) {
17687
17843
  throw new Error(`Unsafe path: ${targetPath}`);
@@ -17722,18 +17878,24 @@ function captureDurationRollback(iframe) {
17722
17878
  function rebindPreviewTiming(iframe, currentTime) {
17723
17879
  return applySoftReloadFinalization(iframe, currentTime);
17724
17880
  }
17725
- function syncTimingEditPreview(iframe, outcome, currentTime, reloadPreview, rebindWhenUnmutated, nestedFiles) {
17881
+ async function syncTimingEditPreview(iframe, outcome, projectId, reloadPreview, rebindWhenUnmutated) {
17882
+ const currentTime = () => usePlayerStore.getState().currentTime;
17726
17883
  if (!outcome.mutated && rebindWhenUnmutated) {
17727
- if (!rebindPreviewTiming(iframe, currentTime)) reloadPreview();
17884
+ if (!rebindPreviewTiming(iframe, currentTime())) reloadPreview();
17728
17885
  return;
17729
17886
  }
17730
- if (!iframe || !outcome.scriptText) {
17887
+ const { scriptText } = outcome;
17888
+ if (!iframe || !scriptText) {
17731
17889
  reloadPreview();
17732
17890
  return;
17733
17891
  }
17734
- const result = applySoftReload(iframe, outcome.scriptText, {
17892
+ if (moveLiveTweens(iframe, scriptText, currentTime(), reloadPreview)) return;
17893
+ const nestedFiles = await settleNestedReads(
17894
+ projectId ? readNestedFiles(iframe, scriptText, (path) => readFileContent(projectId, path)) : null
17895
+ );
17896
+ const result = applySoftReload(iframe, scriptText, {
17735
17897
  onAsyncFailure: reloadPreview,
17736
- currentTimeOverride: currentTime,
17898
+ currentTimeOverride: currentTime(),
17737
17899
  authoredHtml: outcome.after,
17738
17900
  nestedFiles
17739
17901
  });
@@ -17751,21 +17913,12 @@ async function finishTimelineTimingFallback(input) {
17751
17913
  return;
17752
17914
  }
17753
17915
  }
17754
- const { projectId } = input;
17755
- const nestedFiles = await settleNestedReads(
17756
- projectId && outcome.scriptText ? readNestedFiles(
17757
- input.iframe,
17758
- outcome.scriptText,
17759
- (path) => readFileContent(projectId, path)
17760
- ) : null
17761
- );
17762
- syncTimingEditPreview(
17916
+ await syncTimingEditPreview(
17763
17917
  input.iframe,
17764
17918
  outcome,
17765
- usePlayerStore.getState().currentTime,
17919
+ input.projectId,
17766
17920
  input.reloadPreview,
17767
- input.rebindWhenUnmutated,
17768
- nestedFiles
17921
+ input.rebindWhenUnmutated
17769
17922
  );
17770
17923
  }
17771
17924
  var UNTIL_NEXT_EDIT = Number.POSITIVE_INFINITY;
@@ -26306,9 +26459,9 @@ function mergeAudioInSource(source, input) {
26306
26459
  }
26307
26460
  var tagOf2 = (el) => el.tag.trim().toLowerCase();
26308
26461
  var keyOf11 = (el) => el.key ?? el.id;
26309
- var near2 = (a, b) => Math.abs(a - b) <= SYNC_TOLERANCE_S;
26462
+ var near3 = (a, b) => Math.abs(a - b) <= SYNC_TOLERANCE_S;
26310
26463
  function hasIdenticalTiming(a, b) {
26311
- return near2(a.start, b.start) && near2(a.duration, b.duration) && near2(a.playbackStart ?? 0, b.playbackStart ?? 0) && near2(a.playbackRate ?? 1, b.playbackRate ?? 1);
26464
+ return near3(a.start, b.start) && near3(a.duration, b.duration) && near3(a.playbackStart ?? 0, b.playbackStart ?? 0) && near3(a.playbackRate ?? 1, b.playbackRate ?? 1);
26312
26465
  }
26313
26466
  var sameAssetInScope = (a, b) => {
26314
26467
  const asset = mediaAssetIdentity(a);
@@ -26349,7 +26502,7 @@ function isPairInSync(a, b) {
26349
26502
  playbackRate: el.playbackRate ?? 1
26350
26503
  });
26351
26504
  const [x, y] = [timing(a), timing(b)];
26352
- return near2(x.playbackRate, y.playbackRate) && near2(sourceZeroTime(x), sourceZeroTime(y));
26505
+ return near3(x.playbackRate, y.playbackRate) && near3(sourceZeroTime(x), sourceZeroTime(y));
26353
26506
  }
26354
26507
  function pickDetachedAudioTrack(elements, window2) {
26355
26508
  const trackOf = (el) => el.authoredTrack ?? el.track;
@@ -27425,8 +27578,8 @@ async function decodeVideoThumbnail(request, signal, budgets = TIMELINE_VIEWPORT
27425
27578
  for (const time of timestamps) {
27426
27579
  const key2 = await keys.getKeyPacket(time, { metadataOnly: true });
27427
27580
  if (signal.aborted) return;
27428
- const near3 = key2 && key2.timestamp >= sourceStart && time - key2.timestamp <= maxKeyframeLead;
27429
- yield near3 ? key2.timestamp : time;
27581
+ const near4 = key2 && key2.timestamp >= sourceStart && time - key2.timestamp <= maxKeyframeLead;
27582
+ yield near4 ? key2.timestamp : time;
27430
27583
  }
27431
27584
  }
27432
27585
  const aspect = displayWidth / displayHeight;
@@ -45961,12 +46114,12 @@ function statesValueAt(anim, time) {
45961
46114
  const duration = resolveTweenDuration(anim);
45962
46115
  if (!(duration > 0)) return false;
45963
46116
  const pct = (time - (resolveTweenStart(anim) ?? 0)) / duration * 100;
45964
- const near3 = (keyframe) => Math.abs(keyframe - pct) <= KEYFRAME_PCT_MATCH;
46117
+ const near4 = (keyframe) => Math.abs(keyframe - pct) <= KEYFRAME_PCT_MATCH;
45965
46118
  const runEase = runEaseOf(anim);
45966
46119
  if (anim.keyframes)
45967
- return anim.keyframes.keyframes.some((kf) => near3(timeAtProgress(runEase, kf.percentage)));
45968
- if (anim.method === "from") return near3(0);
45969
- return near3(100) || anim.method === "fromTo" && near3(0);
46120
+ return anim.keyframes.keyframes.some((kf) => near4(timeAtProgress(runEase, kf.percentage)));
46121
+ if (anim.method === "from") return near4(0);
46122
+ return near4(100) || anim.method === "fromTo" && near4(0);
45970
46123
  }
45971
46124
  function pickClosestToPlayhead(anims) {
45972
46125
  if (anims.length <= 1) return anims[0] ?? null;
@@ -74513,7 +74666,7 @@ function useFileManager({
74513
74666
  import { useCallback as useCallback106, useRef as useRef130, useState as useState114 } from "react";
74514
74667
 
74515
74668
  // src/utils/gsapUndoRestore.ts
74516
- import { isCompositionTemplate as isCompositionTemplate2 } from "@hyperframes/parsers/hf-ids";
74669
+ import { ensureHfIds as ensureHfIds2, isCompositionTemplate as isCompositionTemplate2 } from "@hyperframes/parsers/hf-ids";
74517
74670
  function elementIdentityKey(el) {
74518
74671
  const hfId = el.getAttribute("data-hf-id");
74519
74672
  if (hfId) return `hf:${hfId}`;
@@ -74649,8 +74802,10 @@ function scopeTargets(scope, keys, restoredByKey, previousByKey) {
74649
74802
  return targets;
74650
74803
  }
74651
74804
  function fileTargets(doc, path, isActive, file) {
74652
- const prevDoc = parseRestoreSource(file.previous);
74653
- const nextDoc = parseRestoreSource(file.restored);
74805
+ const previewStamped = doc.querySelector("[data-hf-id]") !== null;
74806
+ const stampedLikeThePreview = (html2) => previewStamped && !html2.includes("data-hf-id") ? ensureHfIds2(html2) : html2;
74807
+ const prevDoc = parseRestoreSource(stampedLikeThePreview(file.previous));
74808
+ const nextDoc = parseRestoreSource(stampedLikeThePreview(file.restored));
74654
74809
  const scripted = restoreScripted(prevDoc, nextDoc, isActive);
74655
74810
  if (scripted === null) return null;
74656
74811
  const keys = diffRestoreDocs(prevDoc, nextDoc);
@@ -74802,11 +74957,11 @@ function syncStoredElementAttribute(target, attr, value) {
74802
74957
  const fields = STORED_FIELD[attr]?.(value);
74803
74958
  if (!fields) return;
74804
74959
  const key2 = getTimelineElementIdentity(target);
74805
- const same = (element) => Object.keys(fields).every((k) => element[k] === fields[k]);
74960
+ const same2 = (element) => Object.keys(fields).every((k) => element[k] === fields[k]);
74806
74961
  usePlayerStore.setState((state) => {
74807
74962
  let changed = false;
74808
74963
  const elements = state.elements.map((element) => {
74809
- if (getTimelineElementIdentity(element) !== key2 || same(element)) return element;
74964
+ if (getTimelineElementIdentity(element) !== key2 || same2(element)) return element;
74810
74965
  changed = true;
74811
74966
  return { ...element, ...fields };
74812
74967
  });
@@ -81675,13 +81830,13 @@ function useGsapKeyframeOps({
81675
81830
 
81676
81831
  // src/hooks/useGsapPropertyDebounce.ts
81677
81832
  import { useCallback as useCallback138, useEffect as useEffect118, useRef as useRef146 } from "react";
81678
- import { parseGsapScriptAcorn } from "@hyperframes/core/gsap-parser-acorn";
81833
+ import { parseGsapScriptAcorn as parseGsapScriptAcorn2 } from "@hyperframes/core/gsap-parser-acorn";
81679
81834
  var DEBOUNCE_MS = 150;
81680
81835
  function mergeTweenProperties(sdkSession, animationId, edited, kind) {
81681
81836
  try {
81682
81837
  const script = extractGsapScriptText(sdkSession.serialize());
81683
81838
  if (!script) return { ...edited };
81684
- const anim = parseGsapScriptAcorn(script).animations.find((a) => a.id === animationId);
81839
+ const anim = parseGsapScriptAcorn2(script).animations.find((a) => a.id === animationId);
81685
81840
  if (!anim) return { ...edited };
81686
81841
  const existing = kind === "from" ? anim.fromProperties ?? {} : anim.properties;
81687
81842
  return { ...existing, ...edited };
@@ -84234,8 +84389,8 @@ var resolvedSelections = /* @__PURE__ */ new WeakMap();
84234
84389
  var checkedSelections = /* @__PURE__ */ new WeakMap();
84235
84390
  function checkedPreflight(resolved2, inputs) {
84236
84391
  const known = checkedSelections.get(resolved2);
84237
- const same = known?.animations === inputs.animations && known.iframe === inputs.iframe && known.group === inputs.group && known.version === inputs.version;
84238
- if (same) return known;
84392
+ const same2 = known?.animations === inputs.animations && known.iframe === inputs.iframe && known.group === inputs.group && known.version === inputs.version;
84393
+ if (same2) return known;
84239
84394
  const { animations, iframe, group } = inputs;
84240
84395
  const checked = {
84241
84396
  ...inputs,
@@ -89052,16 +89207,16 @@ function averageSpeed(samples, from, to) {
89052
89207
  return total / (seg.length - 1);
89053
89208
  }
89054
89209
  function speedAtEdge(samples, t2, window2, side) {
89055
- const near3 = samples.filter(
89210
+ const near4 = samples.filter(
89056
89211
  (s) => side === "start" ? s.time >= t2 && s.time <= t2 + window2 : s.time >= t2 - window2 && s.time <= t2
89057
89212
  );
89058
- if (near3.length < 2) return 0;
89213
+ if (near4.length < 2) return 0;
89059
89214
  let total = 0;
89060
- for (let i = 1; i < near3.length; i++) {
89061
- const dt = near3[i].time - near3[i - 1].time;
89062
- if (dt > 0) total += Math.abs(near3[i].value - near3[i - 1].value) / dt;
89215
+ for (let i = 1; i < near4.length; i++) {
89216
+ const dt = near4[i].time - near4[i - 1].time;
89217
+ if (dt > 0) total += Math.abs(near4[i].value - near4[i - 1].value) / dt;
89063
89218
  }
89064
- return total / (near3.length - 1);
89219
+ return total / (near4.length - 1);
89065
89220
  }
89066
89221
  function fitEasesFromVelocity(keyframes, rawSamples, totalDuration) {
89067
89222
  if (keyframes.length < 2 || rawSamples.length < 3) return keyframes;
@@ -91692,9 +91847,9 @@ function useLastFrame(request, snapshot3) {
91692
91847
  }
91693
91848
  function useNearViewport() {
91694
91849
  const [element, setElement] = useState141(null);
91695
- const [near3, setNear] = useState141(false);
91850
+ const [near4, setNear] = useState141(false);
91696
91851
  useEffect144(() => {
91697
- if (!element || near3) return;
91852
+ if (!element || near4) return;
91698
91853
  if (typeof IntersectionObserver === "undefined") return setNear(true);
91699
91854
  const observer = new IntersectionObserver(
91700
91855
  (entries) => entries.some((entry2) => entry2.isIntersecting) && setNear(true),
@@ -91702,8 +91857,8 @@ function useNearViewport() {
91702
91857
  );
91703
91858
  observer.observe(element);
91704
91859
  return () => observer.disconnect();
91705
- }, [element, near3]);
91706
- return [setElement, near3];
91860
+ }, [element, near4]);
91861
+ return [setElement, near4];
91707
91862
  }
91708
91863
  function CompCard({
91709
91864
  projectId,