hyperframes 0.8.127 → 0.8.128

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 (171) hide show
  1. package/dist/{add-7CE5XYK2.js → add-DI4T5YLH.js} +15 -15
  2. package/dist/{animatedGifPrep-4VAIRX7D.js → animatedGifPrep-TSK322QL.js} +6 -6
  3. package/dist/{asset-22WQELZE.js → asset-CFW5RUI3.js} +2 -2
  4. package/dist/{assetCataloger-A2AITAHA.js → assetCataloger-MDMKZM4O.js} +2 -2
  5. package/dist/{auth-33GV2LO2.js → auth-7GR2JYK4.js} +2 -2
  6. package/dist/{autoUpdate-OIXGTNLS.js → autoUpdate-VPEWPSH6.js} +2 -2
  7. package/dist/{backgroundChecks-BVP36PXK.js → backgroundChecks-XU7Y6JEZ.js} +3 -3
  8. package/dist/backgroundChecksWorker.js +3 -3
  9. package/dist/{batchRender-URT4LT44.js → batchRender-HIRFZIUO.js} +3 -3
  10. package/dist/{beats-U34XHTAA.js → beats-6EJDWT63.js} +14 -14
  11. package/dist/{benchmark-FNGERKUQ.js → benchmark-F7U6WZGQ.js} +12 -12
  12. package/dist/{browser-35LEQMCO.js → browser-3ECFI3DA.js} +9 -9
  13. package/dist/{bundleWithLocalizedFonts-4CGUDHCA.js → bundleWithLocalizedFonts-OVFXAXV3.js} +2 -2
  14. package/dist/{capture-GZKMVNKK.js → capture-AC5TRHS5.js} +2 -2
  15. package/dist/{capture-M2JJS4F2.js → capture-YH5MUSL7.js} +9 -9
  16. package/dist/{catalog-OVTLU2MC.js → catalog-TRZAPAXM.js} +15 -15
  17. package/dist/{check-DBVGHGKO.js → check-HP7N4TPB.js} +34 -34
  18. package/dist/{checkBrowser-2SQIUOXA.js → checkBrowser-BHLSXZ3V.js} +35 -35
  19. package/dist/{chunk-CX7NQZDE.js → chunk-2CACHG7K.js} +3 -3
  20. package/dist/{chunk-LLU2BJYY.js → chunk-34C66AH5.js} +2 -2
  21. package/dist/{chunk-T6HJCRJC.js → chunk-3PDQ4PS2.js} +1 -1
  22. package/dist/{chunk-L32XKBOF.js → chunk-4AH73ZQW.js} +1 -1
  23. package/dist/{chunk-S2WNVYLQ.js → chunk-4DGJUQFZ.js} +1 -1
  24. package/dist/{chunk-MK2HBL6E.js → chunk-4IZNC32H.js} +1 -1
  25. package/dist/{chunk-RUYSBG3F.js → chunk-4NWOGZZS.js} +32 -30
  26. package/dist/{chunk-P4PMYDLR.js → chunk-4QJQOVN4.js} +1 -1
  27. package/dist/{chunk-HZHXHO4V.js → chunk-56P5SEOM.js} +1 -1
  28. package/dist/{chunk-Q3I4JEGM.js → chunk-5NZVDRRZ.js} +204 -133
  29. package/dist/{chunk-PVVUMILD.js → chunk-6F63NYFZ.js} +1 -1
  30. package/dist/{chunk-CSHKZ3SL.js → chunk-6RGOHYPP.js} +1 -1
  31. package/dist/{chunk-EKGD52A2.js → chunk-72WHJNAR.js} +2 -2
  32. package/dist/{chunk-D4NPKZFY.js → chunk-77EJSKGP.js} +2 -2
  33. package/dist/{chunk-ZOUDTLLH.js → chunk-A7VIBZLC.js} +2 -2
  34. package/dist/{chunk-QR7IRRUX.js → chunk-AQUXI6ZL.js} +5 -5
  35. package/dist/{chunk-7DPBFAYT.js → chunk-AVUUN2XD.js} +33 -31
  36. package/dist/{chunk-F4WYYNNG.js → chunk-BELUXCL4.js} +1 -1
  37. package/dist/{chunk-TL7Y6IBY.js → chunk-BK2KLAYO.js} +3 -3
  38. package/dist/{chunk-IAKZWKNV.js → chunk-BW773MMX.js} +4 -4
  39. package/dist/{chunk-RHBM33JF.js → chunk-CF6QQ6CL.js} +7 -7
  40. package/dist/{chunk-OE66T7R2.js → chunk-COD4GMYB.js} +1 -1
  41. package/dist/{chunk-ZLJXATSQ.js → chunk-FI4I7CME.js} +1 -1
  42. package/dist/{chunk-7YJ7CCKW.js → chunk-FN7KZDH7.js} +1 -1
  43. package/dist/{chunk-6ACXAUBT.js → chunk-H5TVAQAK.js} +4 -4
  44. package/dist/{chunk-GBTGTS35.js → chunk-IKSUSTJT.js} +1 -1
  45. package/dist/{chunk-YII7JZ2C.js → chunk-JDNYDR3Y.js} +1 -1
  46. package/dist/{chunk-6252EFFW.js → chunk-KC5COKLP.js} +1 -1
  47. package/dist/{chunk-V6LLKVWS.js → chunk-KUZTSKD2.js} +1 -1
  48. package/dist/{chunk-G33WTKF3.js → chunk-L5IFUB5G.js} +2 -2
  49. package/dist/{chunk-ZZAHIKFK.js → chunk-LGTAOCIM.js} +1 -1
  50. package/dist/{chunk-NDPSG5WQ.js → chunk-LRDOFHS5.js} +2 -2
  51. package/dist/{chunk-HXGPETEM.js → chunk-OESXJGYM.js} +1 -1
  52. package/dist/{chunk-7TSIAYXZ.js → chunk-PDAMK4Q5.js} +1 -1
  53. package/dist/{chunk-SC4T53X4.js → chunk-Q767NO4V.js} +3 -3
  54. package/dist/{chunk-K3ZB5A3K.js → chunk-QFQET76X.js} +54 -13
  55. package/dist/{chunk-YSCN66NT.js → chunk-QPRIMML2.js} +1 -1
  56. package/dist/{chunk-PZSNUSBM.js → chunk-RLK4ARFU.js} +2 -2
  57. package/dist/{chunk-BYI2K4RN.js → chunk-UROSVQOH.js} +2 -2
  58. package/dist/{chunk-S4AMCVAK.js → chunk-VKBSHU24.js} +5 -5
  59. package/dist/{chunk-KPY6JX4K.js → chunk-VQME2GRN.js} +11 -11
  60. package/dist/{chunk-32MY4AZN.js → chunk-WPHMNO44.js} +1345 -23
  61. package/dist/{chunk-TP4PR3SL.js → chunk-WULYBA5Y.js} +3 -3
  62. package/dist/{chunk-OLVR6P6R.js → chunk-WVU5CJXG.js} +1 -1
  63. package/dist/{chunk-AGNZ2QLE.js → chunk-YRKBFZDQ.js} +1 -1
  64. package/dist/{chunk-TPWWGKU7.js → chunk-ZJUKFZ2P.js} +2 -2
  65. package/dist/{chunk-OQN3AUOV.js → chunk-ZT4WM4B6.js} +12 -12
  66. package/dist/{clean-STQ2XPVL.js → clean-6Q36AWQL.js} +18 -18
  67. package/dist/cli.js +52 -52
  68. package/dist/{cloud-OQNTIR2N.js → cloud-GQ5UHZZN.js} +4 -4
  69. package/dist/{cloudrun-ELOBBQHC.js → cloudrun-JD7H36SS.js} +4 -4
  70. package/dist/{compare-7PHURXFI.js → compare-YONA7IFI.js} +26 -26
  71. package/dist/{compiler-A3FX5DBC.js → compiler-GNV7YQRO.js} +2 -2
  72. package/dist/{component-56DVF6XU.js → component-BXHWGVG4.js} +3 -3
  73. package/dist/{compositions-2DMUUOFR.js → compositions-XC7Y2FPL.js} +11 -11
  74. package/dist/{delete-EECQVAVJ.js → delete-73UVP2DH.js} +3 -3
  75. package/dist/{deterministicFonts-64U7A25I.js → deterministicFonts-HAEMV4TM.js} +5 -4
  76. package/dist/{dist-OJYO32WN.js → dist-FNNGCKFS.js} +1 -1
  77. package/dist/{dist-IPEAV427.js → dist-NDHKRZTY.js} +2 -2
  78. package/dist/{doctor-F3CXFLFV.js → doctor-J76TZOKL.js} +10 -10
  79. package/dist/{events-2LJGIZKG.js → events-FB2W7SMV.js} +9 -9
  80. package/dist/{events-H5RGIYVK.js → events-I3JMSDHY.js} +8 -8
  81. package/dist/{feedback-VCMOOK2O.js → feedback-WSIA7ROU.js} +12 -12
  82. package/dist/{figma-BL4HCJ5P.js → figma-YOJEBRSS.js} +3 -3
  83. package/dist/{fontData.generated-BW5QEPUT.js → fontData.generated-NXAOI4GH.js} +1 -1
  84. package/dist/fontLocalizeCli.js +10 -11
  85. package/dist/{get-HWN5Z3BL.js → get-DXEKFVNL.js} +3 -3
  86. package/dist/{gpuPolicy-37CE57HN.js → gpuPolicy-IGXJ6JGL.js} +6 -6
  87. package/dist/{grade-compare-3OPZYNNZ.js → grade-compare-PXBFW53F.js} +26 -26
  88. package/dist/{gsapParser-LOSAMHNR.js → gsapParser-DIYYX6JT.js} +63 -41
  89. package/dist/{gsapParserAcorn-ZO2LPEZY.js → gsapParserAcorn-E3GEIRZB.js} +1 -1
  90. package/dist/{help-X3EPTRKV.js → help-Z6TEXIAO.js} +1 -1
  91. package/dist/{history-YR6YTOLT.js → history-EFWP3CMR.js} +18 -18
  92. package/dist/hyperframes-player.global.js +1 -1
  93. package/dist/{info-QG7OXNW6.js → info-AQ2ZLWSB.js} +11 -11
  94. package/dist/{init-JUHW2ZN3.js → init-6ZEBBSR5.js} +22 -22
  95. package/dist/{inspect-LIDYSXAG.js → inspect-EUOV4DGL.js} +27 -27
  96. package/dist/{installer-YH76H5ML.js → installer-WI6EKOWS.js} +4 -4
  97. package/dist/{keyframes-ZLHVLMRA.js → keyframes-U6LVMYGO.js} +44 -42
  98. package/dist/{lambda-T33I4AX6.js → lambda-F6SI24C7.js} +5 -5
  99. package/dist/{layout-VD36CWWV.js → layout-VQRYMZRP.js} +27 -27
  100. package/dist/{lint-JAWDGLYW.js → lint-EBHMQRKO.js} +14 -14
  101. package/dist/{lintProject-IOQ4DBS4.js → lintProject-OHBBM3DJ.js} +1 -1
  102. package/dist/{list-24TGFCB3.js → list-EUOXTLX6.js} +3 -3
  103. package/dist/{login-E2PE6CAD.js → login-OXGFQNHT.js} +4 -4
  104. package/dist/{media-treatment-2BMUTUGD.js → media-treatment-TVCTGGDO.js} +14 -14
  105. package/dist/{models-TS5PWNPS.js → models-XNX7UHKU.js} +7 -7
  106. package/dist/{motionShot-RU4MTVOO.js → motionShot-JXQIO5VJ.js} +12 -12
  107. package/dist/{normalize-audio-245DPF4X.js → normalize-audio-L5LTPJIR.js} +13 -13
  108. package/dist/{open-RH7YWUVH.js → open-BON6TWUG.js} +10 -10
  109. package/dist/{pipeline-ZK3JBXX5.js → pipeline-NID4HZDH.js} +6 -6
  110. package/dist/{play-VK6IF765.js → play-GH43JSBS.js} +29 -29
  111. package/dist/{preflight-H7YMOAYQ.js → preflight-VSZD4AND.js} +7 -7
  112. package/dist/{present-CLKL6QSK.js → present-7PTSYTYU.js} +20 -20
  113. package/dist/{preview-GEPWX2GX.js → preview-X2WVPV66.js} +20 -20
  114. package/dist/{producer-HBP36IDM.js → producer-TLATG6GZ.js} +1 -1
  115. package/dist/{projectConfig-FPSBKFQO.js → projectConfig-KKPSSHER.js} +6 -6
  116. package/dist/{publication-ACSV54DD.js → publication-6BFZTAYA.js} +2 -2
  117. package/dist/{publish-L2NGI7MV.js → publish-ZDRTAWEH.js} +11 -11
  118. package/dist/{remove-background-JRRBJN4U.js → remove-background-OZ4OR3B2.js} +7 -7
  119. package/dist/{render-LZEOB6JN.js → render-U3BRPPSW.js} +3 -3
  120. package/dist/{render-RXMA4QYX.js → render-ZH5ZCLWA.js} +17 -17
  121. package/dist/{render-TDSGRTQQ.js → render-ZTIEKMAN.js} +26 -26
  122. package/dist/{render-batch-ZJQ5VHY6.js → render-batch-3JALVFQN.js} +3 -3
  123. package/dist/{renderCancellation-MS5MAATT.js → renderCancellation-NHRJYSHT.js} +6 -6
  124. package/dist/renderSetupWorker.js +1 -1
  125. package/dist/{resolver-WODAPAQC.js → resolver-Z2T2GU2O.js} +4 -4
  126. package/dist/{sherpa-B3IHJHTK.js → sherpa-DRIVXEAC.js} +7 -7
  127. package/dist/{skills-56DFZVPS.js → skills-XLN4DLZP.js} +11 -11
  128. package/dist/{skillsUpdateCheck-AXKUBY44.js → skillsUpdateCheck-CDL66I4W.js} +3 -3
  129. package/dist/{snapshot-NYQJL43J.js → snapshot-63YZCABA.js} +32 -32
  130. package/dist/{src-4K2RSSO5.js → src-3M44XVWE.js} +5 -5
  131. package/dist/{src-UQ72QBPU.js → src-3Q2T2TAT.js} +11 -12
  132. package/dist/{staticProjectServer-OJH6TFA3.js → staticProjectServer-F563BICS.js} +14 -14
  133. package/dist/{status-MZT3S6U2.js → status-HPLBWFSU.js} +6 -6
  134. package/dist/studio/assets/{hyperframes-player-uqzDaxVL.js → hyperframes-player-CKCx0CFA.js} +1 -1
  135. package/dist/studio/assets/{index-DXSYlqmV.js → index-CF31Pq1E.js} +1 -1
  136. package/dist/studio/assets/{index-COhbL1xq.js → index-ClLzyuwb.js} +171 -171
  137. package/dist/studio/assets/{index-CLBNYlDY.js → index-CwS08gWW.js} +1 -1
  138. package/dist/studio/{chunk-3F47EFCT.js → chunk-7UQWVN52.js} +17 -10
  139. package/dist/studio/chunk-7UQWVN52.js.map +1 -0
  140. package/dist/studio/{chunk-246VB2G3.js → chunk-DRVWEPO5.js} +35 -7
  141. package/dist/studio/chunk-DRVWEPO5.js.map +1 -0
  142. package/dist/studio/{chunk-5EKWJZLM.js → chunk-TDWGXBUT.js} +1 -1
  143. package/dist/studio/chunk-TDWGXBUT.js.map +1 -0
  144. package/dist/studio/{domEditingLayers-OL7GLSS4.js → domEditingLayers-IEVLO54Z.js} +3 -3
  145. package/dist/studio/index.d.ts +8 -9
  146. package/dist/studio/index.html +1 -1
  147. package/dist/studio/index.js +1193 -869
  148. package/dist/studio/index.js.map +1 -1
  149. package/dist/studio/player.js +2 -2
  150. package/dist/{studio-api-IT5SYLXJ.js → studio-api-PH5PMXQW.js} +8 -8
  151. package/dist/{studioServer-KHYH2K3Q.js → studioServer-4CEIYT2G.js} +47 -47
  152. package/dist/{system-4KER4Y62.js → system-G6PL23LG.js} +6 -6
  153. package/dist/{telemetry-G3NYQGWI.js → telemetry-ILX6SWZM.js} +9 -9
  154. package/dist/{timeline-CXK4RVZE.js → timeline-3K3WNFPP.js} +18 -18
  155. package/dist/{tokens-RLU7WBIC.js → tokens-GKA5I6SX.js} +2 -2
  156. package/dist/{transcribe-SOY2USBA.js → transcribe-P76R64RU.js} +7 -7
  157. package/dist/{transcribe-Y37DWCAV.js → transcribe-ZZSCMKNC.js} +12 -12
  158. package/dist/{tts-CGUXR7R4.js → tts-P3LIPIL5.js} +1 -1
  159. package/dist/{updateCheck-EJ5SAGDC.js → updateCheck-QBLDWYDK.js} +2 -2
  160. package/dist/{upgrade-MBWWBNGK.js → upgrade-RDBANWHF.js} +2 -2
  161. package/dist/{urlDownloader-ZJ2TZQ7C.js → urlDownloader-VVG2YURO.js} +5 -5
  162. package/dist/{validate-4J3OCFET.js → validate-55V46LZZ.js} +16 -16
  163. package/dist/{video-43437E6M.js → video-S2W6UQ4H.js} +6 -6
  164. package/package.json +1 -1
  165. package/dist/chunk-4C656PVL.js +0 -1393
  166. package/dist/fontCompression-ISNK7STS.js +0 -15
  167. package/dist/studio/chunk-246VB2G3.js.map +0 -1
  168. package/dist/studio/chunk-3F47EFCT.js.map +0 -1
  169. package/dist/studio/chunk-5EKWJZLM.js.map +0 -1
  170. package/dist/studio/{domEditingLayers-OL7GLSS4.js.map → domEditingLayers-IEVLO54Z.js.map} +0 -0
  171. package/dist/{synthesize-BDXNRYZN.js → synthesize-K62TIZWI.js} +4 -4
@@ -21,7 +21,7 @@ import {
21
21
  splitElementInHtml,
22
22
  unwrapElementsFromHtml,
23
23
  wrapElementsInHtml
24
- } from "./chunk-IAKZWKNV.js";
24
+ } from "./chunk-BW773MMX.js";
25
25
  import {
26
26
  atomicTempPath,
27
27
  createFileAtomically,
@@ -60,11 +60,11 @@ import {
60
60
  shouldPrewarmProxy,
61
61
  waitForProxy,
62
62
  walkDir
63
- } from "./chunk-PZSNUSBM.js";
63
+ } from "./chunk-RLK4ARFU.js";
64
64
  import {
65
65
  findTimelineScript,
66
66
  parseGsapScriptAcorn
67
- } from "./chunk-RUYSBG3F.js";
67
+ } from "./chunk-4NWOGZZS.js";
68
68
  import {
69
69
  STUDIO_MANUAL_EDITS_PATH
70
70
  } from "./chunk-KC5XXX3X.js";
@@ -81,18 +81,18 @@ import {
81
81
  motionPathPluginUrl,
82
82
  parseFps,
83
83
  sameInstant
84
- } from "./chunk-AGNZ2QLE.js";
84
+ } from "./chunk-YRKBFZDQ.js";
85
85
  import {
86
86
  MagicString,
87
87
  VALID_CANVAS_RESOLUTIONS,
88
88
  unrollComputedTimeline
89
- } from "./chunk-7DPBFAYT.js";
89
+ } from "./chunk-AVUUN2XD.js";
90
90
  import {
91
91
  AFTER_FONTS_SCRIPT_TYPE,
92
92
  addScenePartsManifest,
93
93
  deferScriptsUntilFonts,
94
94
  ensureHfIds
95
- } from "./chunk-OLVR6P6R.js";
95
+ } from "./chunk-WVU5CJXG.js";
96
96
  import {
97
97
  RUNTIME_BOOTSTRAP_ATTR,
98
98
  findStartTags,
@@ -117,7 +117,7 @@ import {
117
117
  import {
118
118
  isWithinProjectRoot,
119
119
  readProjectFile
120
- } from "./chunk-TPWWGKU7.js";
120
+ } from "./chunk-ZJUKFZ2P.js";
121
121
  import {
122
122
  FFPROBE_PATH_ENV,
123
123
  findFfBinary
@@ -222,7 +222,7 @@ function stampFileHfIds(filePath) {
222
222
  }
223
223
  }
224
224
 
225
- // ../studio-server/dist/chunk-HY2KCPIA.js
225
+ // ../studio-server/dist/chunk-NU64EXIH.js
226
226
  import { randomUUID as randomUUID6 } from "crypto";
227
227
  import { mkdir as mkdir2, readdir as readdir3, rm as rm3, rmdir, writeFile } from "fs/promises";
228
228
  import {
@@ -1405,6 +1405,7 @@ var Engine = class {
1405
1405
  clearTimeout(this.claimed?.timer);
1406
1406
  const timer = Number.isFinite(idleMs) ? setTimeout(() => this.background(() => this.commitClaim()), idleMs) : void 0;
1407
1407
  timer?.unref?.();
1408
+ group.lastWriteAt = this.now();
1408
1409
  this.claimed = { group, key, timer };
1409
1410
  return group.changes.size ? { id: group.id } : null;
1410
1411
  }
@@ -2213,6 +2214,7 @@ function classifyPropertyGroup(prop) {
2213
2214
  }
2214
2215
 
2215
2216
  // ../parsers/dist/gsapWriterAcorn.js
2217
+ var GSAP_DEFAULT_DURATION = 0.5;
2216
2218
  var BUILTIN_VAR_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "delay"]);
2217
2219
  var DROPPED_VAR_KEYS = /* @__PURE__ */ new Set([
2218
2220
  "onComplete",
@@ -2271,22 +2273,23 @@ function positionHoldForAnimation(animation, animations) {
2271
2273
  if (!animation.keyframes) return null;
2272
2274
  const start = knownStart(animation) ?? 0;
2273
2275
  if (!(start > 1e-3)) return null;
2274
- const first = [...animation.keyframes.keyframes].sort(
2275
- (left, right) => left.percentage - right.percentage
2276
- )[0];
2277
- if (!first) return null;
2276
+ const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);
2277
+ if (!atStart) return null;
2278
2278
  const earlier = animations.filter((other) => {
2279
2279
  const otherStart = knownStart(other);
2280
2280
  return other !== animation && !other.global && other.targetSelector === animation.targetSelector && otherStart !== void 0 && otherStart < start - 1e-3;
2281
2281
  });
2282
2282
  const position = {};
2283
- for (const [property, value] of Object.entries(first.properties)) {
2283
+ for (const [property, value] of Object.entries(atStart.properties)) {
2284
2284
  if (classifyPropertyGroup2(property) !== "position" || typeof value !== "number") continue;
2285
2285
  if (earlier.some((other) => writesProperty(other, property))) continue;
2286
2286
  position[property] = value;
2287
2287
  }
2288
2288
  return Object.keys(position).length > 0 ? position : null;
2289
2289
  }
2290
+ function authorsKeyframes(anim) {
2291
+ return anim.keyframes !== void 0 || anim.hasUnresolvedKeyframes === true;
2292
+ }
2290
2293
  function mergePercentageKeyframes(keyframes) {
2291
2294
  const byPercentage = /* @__PURE__ */ new Map();
2292
2295
  for (const keyframe of keyframes) {
@@ -2430,34 +2433,27 @@ function readProvenance(node) {
2430
2433
  var roundPercentage = (percentage) => Math.round(percentage * 10) / 10;
2431
2434
  var OBJECT_ARRAY_PERCENTAGE_TOLERANCE = 2;
2432
2435
  function getObjectArrayKeyframeTiming(durations) {
2433
- const hasAuthoredDuration = durations.some((duration) => duration !== void 0);
2434
- if (hasAuthoredDuration) {
2435
- if (!durations.every(
2436
- (duration) => typeof duration === "number" && Number.isFinite(duration) && duration > 0
2437
- )) {
2438
- return null;
2439
- }
2440
- const totalDuration = durations.reduce((sum, duration) => sum + duration, 0);
2441
- let cumulative = 0;
2442
- return {
2443
- percentages: durations.map((duration) => {
2444
- cumulative += duration;
2445
- return roundPercentage(cumulative / totalDuration * 100);
2446
- }),
2447
- totalDuration
2448
- };
2436
+ const steps = durations.map((duration) => duration ?? GSAP_DEFAULT_DURATION);
2437
+ if (!steps.every(
2438
+ (duration) => typeof duration === "number" && Number.isFinite(duration) && duration > 0
2439
+ )) {
2440
+ return null;
2449
2441
  }
2450
- const lastIndex = durations.length - 1;
2442
+ const totalDuration = steps.reduce((sum, duration) => sum + duration, 0);
2443
+ let cumulative = 0;
2451
2444
  return {
2452
- percentages: durations.map(
2453
- (_, index) => lastIndex > 0 ? roundPercentage(index / lastIndex * 100) : 0
2454
- )
2445
+ percentages: steps.map((duration) => {
2446
+ cumulative += duration;
2447
+ return roundPercentage(cumulative / totalDuration * 100);
2448
+ }),
2449
+ totalDuration
2455
2450
  };
2456
2451
  }
2457
2452
  function getCompatibleObjectArrayKeyframeTiming(durations, outerDuration) {
2458
2453
  const timing = getObjectArrayKeyframeTiming(durations);
2459
2454
  if (!timing) return null;
2460
- if (timing.totalDuration === void 0 || outerDuration === void 0) return timing;
2455
+ const stepsAuthorDuration = durations.some((duration) => duration !== void 0);
2456
+ if (!stepsAuthorDuration || outerDuration === void 0) return timing;
2461
2457
  if (typeof outerDuration === "number" && Math.abs(outerDuration - timing.totalDuration) <= Number.EPSILON) {
2462
2458
  return timing;
2463
2459
  }
@@ -3051,6 +3047,7 @@ function parsePercentageKeyframes(node, scope, source) {
3051
3047
  if (typeof key !== "string") continue;
3052
3048
  const pctMatch = PERCENTAGE_KEY_RE.exec(key);
3053
3049
  if (pctMatch) {
3050
+ if (!isPlainStep(prop.value)) return void 0;
3054
3051
  const percentage = Number.parseFloat(pctMatch[1] ?? "0");
3055
3052
  const record = objectExpressionToRecord(prop.value, scope, source);
3056
3053
  const properties = {};
@@ -3069,6 +3066,8 @@ function parsePercentageKeyframes(node, scope, source) {
3069
3066
  ease = tryResolveStringProp(prop.value, scope, source) ?? ease;
3070
3067
  } else if (key === "easeEach") {
3071
3068
  easeEach = tryResolveStringProp(prop.value, scope, source) ?? easeEach;
3069
+ } else {
3070
+ return void 0;
3072
3071
  }
3073
3072
  }
3074
3073
  keyframes.sort((a, b) => a.percentage - b.percentage);
@@ -3092,12 +3091,19 @@ function computeKeyframesTotalDuration(varsNode, scope, source) {
3092
3091
  }
3093
3092
  return getObjectArrayKeyframeTiming(durations)?.totalDuration;
3094
3093
  }
3095
- var isFullyReadableStep = (el) => el?.type === "ObjectExpression" && !el.properties.some((p) => p.type === "SpreadElement");
3094
+ function staticKeyName(prop) {
3095
+ if (prop.type !== "ObjectProperty" && prop.type !== "Property") return void 0;
3096
+ if (prop.method || prop.kind && prop.kind !== "init") return void 0;
3097
+ const key = prop.computed ? prop.key?.type === "Literal" && prop.key.value : prop.key?.name ?? prop.key?.value;
3098
+ return typeof key === "string" ? key : void 0;
3099
+ }
3100
+ var isPlainObject = (node) => node?.type === "ObjectExpression" && (node.properties ?? []).every((p) => staticKeyName(p) !== void 0);
3101
+ var isPlainStep = (node) => node?.type === "Literal" || isPlainObject(node);
3096
3102
  function parseObjectArrayKeyframes(node, scope, source) {
3097
3103
  const elements = node.elements ?? [];
3098
3104
  const raw = [];
3099
3105
  for (const el of elements) {
3100
- if (!isFullyReadableStep(el)) return void 0;
3106
+ if (!isPlainObject(el)) return void 0;
3101
3107
  const record = objectExpressionToRecord(el, scope, source);
3102
3108
  const properties = {};
3103
3109
  let duration;
@@ -3136,9 +3142,8 @@ function parseSimpleArrayKeyframes(node, scope) {
3136
3142
  const values = [];
3137
3143
  for (const el of prop.value.elements ?? []) {
3138
3144
  const val = resolveNode(el, scope);
3139
- if (typeof val === "number" || typeof val === "string") {
3140
- values.push(val);
3141
- }
3145
+ if (typeof val !== "number" && typeof val !== "string") return void 0;
3146
+ values.push(val);
3142
3147
  }
3143
3148
  if (values.length > 0) arrayProps.set(key, values);
3144
3149
  } else if (key === "ease") {
@@ -3171,6 +3176,7 @@ function parseKeyframesNode(node, scope, source) {
3171
3176
  }
3172
3177
  if (node.type !== "ObjectExpression") return void 0;
3173
3178
  const props = node.properties ?? [];
3179
+ if (!props.every((p) => staticKeyName(p) !== void 0)) return void 0;
3174
3180
  let hasPercentageKey = false;
3175
3181
  let hasArrayValue = false;
3176
3182
  for (const prop of props) {
@@ -3271,7 +3277,7 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
3271
3277
  percentage: waypoints.length > 1 ? Math.round(i / (waypoints.length - 1) * 100) : 0,
3272
3278
  properties: { x: wp.x, y: wp.y }
3273
3279
  }));
3274
- keyframesData = { format: "percentage", keyframes: kf };
3280
+ keyframesData = { format: "percentage", keyframes: kf, fromMotionPath: true };
3275
3281
  } else {
3276
3282
  const kfs = keyframesData.keyframes;
3277
3283
  if (kfs.length === waypoints.length) {
@@ -3301,10 +3307,10 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
3301
3307
  const position = typeof posVal === "number" ? posVal : typeof posVal === "string" ? posVal : hasPositionArg ? `__raw:${source.slice(call.positionArg.start, call.positionArg.end)}` : 0;
3302
3308
  let duration = typeof vars.duration === "number" ? vars.duration : void 0;
3303
3309
  const ease = typeof vars.ease === "string" ? vars.ease : void 0;
3304
- if (duration === void 0 && keyframesData) {
3310
+ const durationUnresolved = call.method !== "set" && duration === void 0 && hasUnknownDuration(call.varsArg, scope);
3311
+ if (duration === void 0 && keyframesData && !durationUnresolved) {
3305
3312
  duration = computeKeyframesTotalDuration(call.varsArg, scope, source);
3306
3313
  }
3307
- const durationUnresolved = call.method !== "set" && duration === void 0 && hasUnknownDuration(call.varsArg, scope);
3308
3314
  let selector = call.selector;
3309
3315
  let targetIdentity;
3310
3316
  if (selector === "__unresolved__") {
@@ -3358,7 +3364,6 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
3358
3364
  if (provenance) anim.provenance = provenance;
3359
3365
  return anim;
3360
3366
  }
3361
- var GSAP_DEFAULT_DURATION = 0.5;
3362
3367
  function resolvePositionString(pos, cursor, prevStart) {
3363
3368
  const trimmed = pos.trim();
3364
3369
  if (trimmed === "") return cursor;
@@ -3391,7 +3396,7 @@ function applyTimelineDefaults(anims, defaults) {
3391
3396
  if (defaults.duration !== void 0) anim.duration = defaults.duration;
3392
3397
  else if (defaults.durationUnresolved) anim.durationUnresolved = true;
3393
3398
  }
3394
- if (anim.ease === void 0 && defaults.ease !== void 0 && !anim.keyframes) {
3399
+ if (anim.ease === void 0 && defaults.ease !== void 0 && (!anim.keyframes || anim.keyframes.fromMotionPath)) {
3395
3400
  anim.ease = defaults.ease;
3396
3401
  }
3397
3402
  }
@@ -3555,14 +3560,25 @@ function parseGsapScriptAcornForWrite(script) {
3555
3560
  return null;
3556
3561
  }
3557
3562
  }
3558
- function clipTweenMatcher(clipSelectors, root) {
3563
+ function clipTweenMatcher(clipSelectors, root, queries = /* @__PURE__ */ new Map()) {
3559
3564
  const own = typeof clipSelectors === "string" ? [clipSelectors] : clipSelectors;
3560
- const clips = root ? own.flatMap((selector) => queryAll(root, selector)) : [];
3565
+ if (!root)
3566
+ return ({ targetSelector, hasPartialSelector }) => !hasPartialSelector && own.includes(targetSelector);
3567
+ const queryAll = (selector) => {
3568
+ if (ID_SELECTOR.test(selector)) {
3569
+ if (!queries.has(ALL_IDS)) indexIds(root, queries);
3570
+ return queries.get(selector) ?? [];
3571
+ }
3572
+ let found = queries.get(selector);
3573
+ if (!found) queries.set(selector, found = queryRoot(root, selector));
3574
+ return found;
3575
+ };
3576
+ const clips = own.flatMap((selector) => queryAll(selector));
3561
3577
  return ({ targetSelector, hasPartialSelector }) => {
3562
3578
  if (hasPartialSelector) return false;
3563
3579
  if (own.includes(targetSelector)) return true;
3564
- if (!root || clips.length === 0) return false;
3565
- const targets = queryAll(root, targetSelector);
3580
+ if (clips.length === 0) return false;
3581
+ const targets = queryAll(targetSelector);
3566
3582
  return targets.length > 0 && targets.every((target) => {
3567
3583
  const owner = target.closest("[data-start]");
3568
3584
  return clips.includes(target) || owner !== null && clips.includes(owner);
@@ -3575,7 +3591,20 @@ function clipQueryRoot(script) {
3575
3591
  function hasExplicitTime(animation) {
3576
3592
  return typeof animation.position === "number" && !animation.implicitPosition;
3577
3593
  }
3578
- function queryAll(root, selector) {
3594
+ var ID_SELECTOR = /^#-?[A-Za-z_][\w-]*$/;
3595
+ var ALL_IDS = "[id]";
3596
+ function indexIds(root, queries) {
3597
+ const all = queryRoot(root, ALL_IDS);
3598
+ queries.set(ALL_IDS, all);
3599
+ for (const el of all) {
3600
+ const key = `#${el.id}`;
3601
+ if (!ID_SELECTOR.test(key)) continue;
3602
+ const list = queries.get(key);
3603
+ if (list) list.push(el);
3604
+ else queries.set(key, [el]);
3605
+ }
3606
+ }
3607
+ function queryRoot(root, selector) {
3579
3608
  try {
3580
3609
  return Array.from(root.querySelectorAll(selector));
3581
3610
  } catch {
@@ -3742,7 +3771,7 @@ function updateAnimationInScript(script, animationId, updates) {
3742
3771
  const parsed = parseGsapScriptAcornForWrite(script);
3743
3772
  if (!parsed) return script;
3744
3773
  const target = parsed.located.find((l) => l.id === animationId);
3745
- if (!target) return script;
3774
+ if (!target || updates.properties && target.animation.hasUnresolvedKeyframes) return script;
3746
3775
  const ms = new MagicString(script);
3747
3776
  const { call } = target;
3748
3777
  if (updates.properties) {
@@ -3805,47 +3834,56 @@ function overwritePosition(ms, call, position) {
3805
3834
  ms.appendLeft(last ? last.end : call.node.end - 1, `, ${valueToCode(position)}`);
3806
3835
  }
3807
3836
  }
3808
- function shiftPositionsInScript(script, targetSelector, delta, root) {
3809
- const parsed = parseGsapScriptAcornForWrite(script);
3810
- if (!parsed) return script;
3811
- const carries = clipTweenMatcher(targetSelector, root);
3837
+ var isLiveRetime = (r) => r.kind === "shift" || r.oldDuration > 0 && r.newDuration > 0;
3838
+ function applyRetime(animation, retime) {
3839
+ if (retime.kind === "shift") {
3840
+ if (!hasExplicitTime(animation)) return { position: false, duration: false };
3841
+ animation.position = shiftedPosition(animation.position, retime.delta);
3842
+ return { position: true, duration: false };
3843
+ }
3844
+ const touched = { position: false, duration: false };
3845
+ if (!isLiveRetime(retime) || typeof animation.position !== "number") return touched;
3846
+ const ratio = retime.newDuration / retime.oldDuration;
3847
+ if (hasExplicitTime(animation)) {
3848
+ const scaled = retime.newStart + (animation.position - retime.oldStart) * ratio;
3849
+ animation.position = Math.max(0, Math.round(scaled * 1e3) / 1e3);
3850
+ touched.position = true;
3851
+ }
3852
+ if (typeof animation.duration === "number" && animation.duration > 0) {
3853
+ animation.duration = Math.max(1e-3, Math.round(animation.duration * ratio * 1e3) / 1e3);
3854
+ touched.duration = true;
3855
+ }
3856
+ return touched;
3857
+ }
3858
+ function retimeClipTweensInScript(script, retimes, root) {
3859
+ const changed = retimes.map(() => false);
3860
+ const parsed = retimes.some(isLiveRetime) ? parseGsapScriptAcornForWrite(script) : null;
3861
+ if (!parsed) return { script, changed };
3862
+ const queries = /* @__PURE__ */ new Map();
3863
+ const matchers = retimes.map((r) => clipTweenMatcher(r.targetSelector, root, queries));
3812
3864
  const ms = new MagicString(script);
3813
- let changed = false;
3865
+ let wrote = false;
3814
3866
  for (const entry of parsed.located) {
3815
- if (!carries(entry.animation) || !hasExplicitTime(entry.animation)) continue;
3816
- overwritePosition(ms, entry.call, shiftedPosition(entry.animation.position, delta));
3817
- changed = true;
3867
+ const animation = { ...entry.animation };
3868
+ let position = false;
3869
+ let duration = false;
3870
+ retimes.forEach((retime, i) => {
3871
+ if (!matchers[i](animation)) return;
3872
+ const before = [animation.position, animation.duration];
3873
+ const touched = applyRetime(animation, retime);
3874
+ position ||= touched.position;
3875
+ duration ||= touched.duration;
3876
+ if (before[0] !== animation.position || before[1] !== animation.duration) changed[i] = true;
3877
+ });
3878
+ if (position) overwritePosition(ms, entry.call, animation.position);
3879
+ if (duration) upsertProp(ms, entry.call.varsArg, "duration", animation.duration);
3880
+ wrote ||= position || duration;
3818
3881
  }
3819
- return changed ? ms.toString() : script;
3882
+ return { script: wrote ? ms.toString() : script, changed };
3820
3883
  }
3821
3884
  function shiftedPosition(position, delta) {
3822
3885
  return Math.max(0, Math.round((position + delta) * 1e3) / 1e3);
3823
3886
  }
3824
- function scalePositionsInScript(script, targetSelector, oldStart, oldDuration, newStart, newDuration, root) {
3825
- if (oldDuration <= 0 || newDuration <= 0) return script;
3826
- const ratio = newDuration / oldDuration;
3827
- const parsed = parseGsapScriptAcornForWrite(script);
3828
- if (!parsed) return script;
3829
- const carries = clipTweenMatcher(targetSelector, root);
3830
- const ms = new MagicString(script);
3831
- let changed = false;
3832
- for (const entry of parsed.located) {
3833
- if (!carries(entry.animation) || typeof entry.animation.position !== "number") continue;
3834
- if (hasExplicitTime(entry.animation)) {
3835
- const newPos = Math.max(
3836
- 0,
3837
- Math.round((newStart + (entry.animation.position - oldStart) * ratio) * 1e3) / 1e3
3838
- );
3839
- overwritePosition(ms, entry.call, newPos);
3840
- }
3841
- if (typeof entry.animation.duration === "number" && entry.animation.duration > 0) {
3842
- const newDur = Math.max(1e-3, Math.round(entry.animation.duration * ratio * 1e3) / 1e3);
3843
- upsertProp(ms, entry.call.varsArg, "duration", newDur);
3844
- }
3845
- changed = true;
3846
- }
3847
- return changed ? ms.toString() : script;
3848
- }
3849
3887
  function addAnimationToScript(script, animation) {
3850
3888
  const parsed = parseGsapScriptAcornForWrite(script);
3851
3889
  if (!parsed) return { script, id: "" };
@@ -4118,7 +4156,7 @@ function updateKeyframeInScript(script, animationId, percentage, properties, eas
4118
4156
  const parsed = parseGsapScriptAcornForWrite(script);
4119
4157
  if (!parsed) return script;
4120
4158
  const target = parsed.located.find((l) => l.id === animationId);
4121
- if (!target) return script;
4159
+ if (!target || target.animation.hasUnresolvedKeyframes) return script;
4122
4160
  const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
4123
4161
  if (!kfPropNode) {
4124
4162
  return updateMotionPathKeyframe(script, target, percentage, properties, ease) ?? script;
@@ -4186,7 +4224,7 @@ function locateWithKeyframes(script, animationId) {
4186
4224
  if (!parsed) return null;
4187
4225
  const convertedId = animationId.replace(/-from-|-fromTo-/, "-to-");
4188
4226
  const target = parsed.located.find((l) => l.id === animationId) ?? parsed.located.find((l) => l.id === convertedId);
4189
- if (!target) return null;
4227
+ if (!target || target.animation.hasUnresolvedKeyframes) return null;
4190
4228
  const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
4191
4229
  if (!kfPropNode || kfPropNode.value?.type !== "ObjectExpression") return null;
4192
4230
  return { script, parsed, target, kfNode: kfPropNode.value };
@@ -4210,8 +4248,12 @@ function convertArrayKeyframesToObject(script, target) {
4210
4248
  return `${JSON.stringify(`${timing.percentages[i]}%`)}: ${recordToCode(record)}`;
4211
4249
  });
4212
4250
  const ms = new MagicString(script);
4213
- ms.overwrite(kfPropNode.value.start, kfPropNode.value.end, `{ ${entries.join(", ")} }`);
4214
- if (timing.totalDuration !== void 0 && findPropertyNode2(target.call.varsArg, "duration") === void 0) {
4251
+ ms.overwrite(
4252
+ kfPropNode.value.start,
4253
+ kfPropNode.value.end,
4254
+ `{ ${entries.join(", ")}, easeEach: "none" }`
4255
+ );
4256
+ if (findPropertyNode2(target.call.varsArg, "duration") === void 0) {
4215
4257
  upsertProp(ms, target.call.varsArg, "duration", timing.totalDuration);
4216
4258
  }
4217
4259
  return ms.toString();
@@ -4221,7 +4263,7 @@ function ensureKeyframesNode(script, animationId) {
4221
4263
  if (direct) return direct;
4222
4264
  const parsed = parseGsapScriptAcornForWrite(script);
4223
4265
  const target = parsed?.located.find((l) => l.id === animationId);
4224
- if (!target) return null;
4266
+ if (!target || target.animation.hasUnresolvedKeyframes) return null;
4225
4267
  const kfProp = findPropertyNode2(target.call.varsArg, "keyframes");
4226
4268
  if (kfProp?.value?.type === "ArrayExpression") {
4227
4269
  const normalized = convertArrayKeyframesToObject(script, target);
@@ -4323,7 +4365,7 @@ function removeKeyframeFromScript(script, animationId, percentage) {
4323
4365
  const parsed = parseGsapScriptAcornForWrite(script);
4324
4366
  if (!parsed) return script;
4325
4367
  const target = parsed.located.find((l) => l.id === animationId);
4326
- if (!target) return script;
4368
+ if (!target || target.animation.hasUnresolvedKeyframes) return script;
4327
4369
  const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
4328
4370
  if (!kfPropNode) return script;
4329
4371
  if (kfPropNode.value?.type === "ArrayExpression") {
@@ -4447,7 +4489,7 @@ function convertToKeyframesFromScript(script, animationId, resolvedFromValues, s
4447
4489
  const target = parsed.located.find((l) => l.id === animationId);
4448
4490
  if (!target) return script;
4449
4491
  const { animation, call } = target;
4450
- if (animation.keyframes) return script;
4492
+ if (authorsKeyframes(animation)) return script;
4451
4493
  const isSet = call.method === "set";
4452
4494
  const { fromProps, toProps } = resolveConversionProps(animation, resolvedFromValues);
4453
4495
  const ms = new MagicString(script);
@@ -4663,6 +4705,7 @@ function splitIntoPropertyGroupsFromScript(script, animationId) {
4663
4705
  const target = parsed.located.find((l) => l.id === animationId);
4664
4706
  if (!target) return { script, ids: [animationId] };
4665
4707
  const { animation } = target;
4708
+ if (animation.hasUnresolvedKeyframes) return { script, ids: [animationId] };
4666
4709
  const allPropKeys = collectPropertyKeys(animation);
4667
4710
  const groupProps = partitionPropertyGroups(allPropKeys);
4668
4711
  if (groupProps.size <= 1) return { script, ids: [animationId] };
@@ -4937,8 +4980,8 @@ function computeForwardBaselines(matching, splitTime) {
4937
4980
  const pos = typeof anim.position === "number" ? anim.position : 0;
4938
4981
  const dur = anim.duration ?? 0;
4939
4982
  const animEnd = pos + dur;
4940
- if (anim.keyframes) {
4941
- const kfs = anim.keyframes.keyframes;
4983
+ if (authorsKeyframes(anim)) {
4984
+ const kfs = anim.keyframes?.keyframes ?? [];
4942
4985
  if (pos >= splitTime) {
4943
4986
  } else if (animEnd > splitTime) {
4944
4987
  for (const kf of kfs) {
@@ -4999,17 +5042,22 @@ function buildSpanningSplit(result, anim, pos, dur, fromSource, ctx) {
4999
5042
  extras: anim.extras
5000
5043
  }).script;
5001
5044
  }
5045
+ function applyKeyframedTweenSplit(result, anim, pos, animEnd, ctx, skippedSelectors) {
5046
+ if (pos >= ctx.splitTime)
5047
+ return updateAnimationSelectorInScript(result, anim.id, ctx.newSelector);
5048
+ if (animEnd > ctx.splitTime) {
5049
+ skippedSelectors.push(`${ctx.originalSelector} (keyframes spanning split)`);
5050
+ } else if (anim.hasUnresolvedKeyframes) {
5051
+ skippedSelectors.push(`${ctx.originalSelector} (unreadable keyframes before split)`);
5052
+ }
5053
+ return result;
5054
+ }
5002
5055
  function applyTweenSplit(result, anim, baselineBefore, ctx, skippedSelectors) {
5003
5056
  const pos = typeof anim.position === "number" ? anim.position : 0;
5004
5057
  const dur = anim.duration ?? 0;
5005
5058
  const animEnd = pos + dur;
5006
- if (anim.keyframes) {
5007
- if (pos >= ctx.splitTime)
5008
- return updateAnimationSelectorInScript(result, anim.id, ctx.newSelector);
5009
- if (animEnd > ctx.splitTime) {
5010
- skippedSelectors.push(`${ctx.originalSelector} (keyframes spanning split)`);
5011
- }
5012
- return result;
5059
+ if (authorsKeyframes(anim)) {
5060
+ return applyKeyframedTweenSplit(result, anim, pos, animEnd, ctx, skippedSelectors);
5013
5061
  }
5014
5062
  if (animEnd <= ctx.splitTime) return result;
5015
5063
  if (pos >= ctx.splitTime)
@@ -5956,7 +6004,7 @@ function requestSubPath(url, route) {
5956
6004
  return decodeURIComponent(segments.slice(start + routeSegments.length).join("/"));
5957
6005
  }
5958
6006
  async function loadGsapParser() {
5959
- return import("./gsapParser-LOSAMHNR.js");
6007
+ return import("./gsapParser-DIYYX6JT.js");
5960
6008
  }
5961
6009
  function isDanglingSymlinkInProject(projectDir, lexicalPath) {
5962
6010
  if (!isSafePath(projectDir, dirname32(lexicalPath))) return false;
@@ -6617,7 +6665,7 @@ async function prepareGsapMutationScript(c, res, firstMutation) {
6617
6665
  let block = extractGsapScriptBlock(html);
6618
6666
  if (!block && (firstMutation.type === "add" || firstMutation.type === "add-with-keyframes")) {
6619
6667
  const compId = html.match(/data-composition-id="([^"]+)"/)?.[1] ?? "main";
6620
- const { GSAP_CDN } = await import("./dist-IPEAV427.js");
6668
+ const { GSAP_CDN } = await import("./dist-NDHKRZTY.js");
6621
6669
  const bootstrap = [
6622
6670
  `<script src="${GSAP_CDN}"></script>`,
6623
6671
  "<script>",
@@ -6649,6 +6697,38 @@ ${bootstrap}`;
6649
6697
  if (!block) return c.json({ error: "no GSAP script found in file" }, 400);
6650
6698
  return { html, beforeHtml, block };
6651
6699
  }
6700
+ function retimeRuns(mutations) {
6701
+ const runs = /* @__PURE__ */ new Map();
6702
+ let start = -1;
6703
+ mutations.forEach((mutation, index) => {
6704
+ const retime = clipRetimeOf(mutation);
6705
+ if (!retime) return void (start = -1);
6706
+ if (start < 0) runs.set(start = index, []);
6707
+ runs.get(start).push(retime);
6708
+ });
6709
+ return runs;
6710
+ }
6711
+ function clipRetimeOf(mutation) {
6712
+ if (mutation.type === "shift-positions") {
6713
+ const { targetSelector: targetSelector2, delta } = mutation;
6714
+ return targetSelector2 && Number.isFinite(delta) && delta !== 0 ? { kind: "shift", targetSelector: targetSelector2, delta } : "no-op";
6715
+ }
6716
+ if (mutation.type !== "scale-positions") return null;
6717
+ const { targetSelector, oldStart, oldDuration, newStart, newDuration } = mutation;
6718
+ const finite = [oldStart, oldDuration, newStart, newDuration].every(Number.isFinite);
6719
+ if (!targetSelector || !finite || oldDuration <= 0 || newDuration <= 0) return "no-op";
6720
+ if (oldStart === newStart && oldDuration === newDuration) return "no-op";
6721
+ return { kind: "scale", targetSelector, oldStart, oldDuration, newStart, newDuration };
6722
+ }
6723
+ function retimeRun(script, run, root) {
6724
+ const live = run.filter((slot) => slot !== "no-op");
6725
+ const retimed = retimeClipTweensInScript(script, live, root);
6726
+ const synced = syncPositionHoldsBeforeKeyframes(retimed.script);
6727
+ let next = 0;
6728
+ const changed = run.map((slot) => slot !== "no-op" && retimed.changed[next++]);
6729
+ if (synced !== retimed.script) changed[changed.length - 1] = true;
6730
+ return { script: synced, changed: synced === script ? changed.map(() => false) : changed };
6731
+ }
6652
6732
  async function applyGsapMutations(c, res, mutations) {
6653
6733
  const firstMutation = mutations[0];
6654
6734
  if (!firstMutation) return c.json({ error: "mutations array required" }, 400);
@@ -6667,7 +6747,17 @@ async function applyGsapMutations(c, res, mutations) {
6667
6747
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);
6668
6748
  }
6669
6749
  const mutationChanges = [];
6670
- for (const mutation of mutations) {
6750
+ const retimes = writer === "acorn" ? retimeRuns(mutations) : /* @__PURE__ */ new Map();
6751
+ for (let index = 0; index < mutations.length; index++) {
6752
+ const run = retimes.get(index);
6753
+ if (run) {
6754
+ const retimed = retimeRun(block.scriptText, run, block.root);
6755
+ mutationChanges.push(...retimed.changed);
6756
+ block.scriptText = retimed.script;
6757
+ index += run.length - 1;
6758
+ continue;
6759
+ }
6760
+ const mutation = mutations[index];
6671
6761
  const previousScript = block.scriptText;
6672
6762
  const result = await executeGsapMutation(mutation, block, respond, writer);
6673
6763
  if (result instanceof Response) return result;
@@ -6979,33 +7069,14 @@ function executeGsapMutationAcorn(body, block, respond) {
6979
7069
  case "unroll-timeline": {
6980
7070
  return unrollComputedTimeline(block.scriptText);
6981
7071
  }
6982
- case "shift-positions": {
6983
- const { targetSelector, delta } = body;
6984
- if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;
6985
- return shiftPositionsInScript(block.scriptText, targetSelector, delta, block.root);
6986
- }
6987
7072
  case "shift-positions-batch": {
6988
- let script = block.scriptText;
6989
- for (const s of body.shifts) {
6990
- if (!s.targetSelector || !Number.isFinite(s.delta) || s.delta === 0) continue;
6991
- script = shiftPositionsInScript(script, s.targetSelector, s.delta, block.root);
6992
- }
6993
- return script;
7073
+ const shifts = body.shifts.filter((s) => s.targetSelector && Number.isFinite(s.delta) && s.delta !== 0).map((s) => ({ kind: "shift", targetSelector: s.targetSelector, delta: s.delta }));
7074
+ return retimeClipTweensInScript(block.scriptText, shifts, block.root).script;
6994
7075
  }
7076
+ case "shift-positions":
6995
7077
  case "scale-positions": {
6996
- const { targetSelector, oldStart, oldDuration, newStart, newDuration } = body;
6997
- if (!targetSelector || !Number.isFinite(oldStart) || !Number.isFinite(oldDuration) || !Number.isFinite(newStart) || !Number.isFinite(newDuration) || oldDuration <= 0 || newDuration <= 0)
6998
- return block.scriptText;
6999
- if (oldStart === newStart && oldDuration === newDuration) return block.scriptText;
7000
- return scalePositionsInScript(
7001
- block.scriptText,
7002
- targetSelector,
7003
- oldStart,
7004
- oldDuration,
7005
- newStart,
7006
- newDuration,
7007
- block.root
7008
- );
7078
+ const retime = clipRetimeOf(body);
7079
+ return retime && retime !== "no-op" ? retimeClipTweensInScript(block.scriptText, [retime], block.root).script : block.scriptText;
7009
7080
  }
7010
7081
  default:
7011
7082
  return respond({ error: `unknown mutation type: ${body.type}` }, 400);
@@ -7304,15 +7375,15 @@ async function executeGsapMutationRecast(body, block, respond) {
7304
7375
  case "shift-positions": {
7305
7376
  const { targetSelector, delta } = body;
7306
7377
  if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;
7307
- const { shiftPositionsInScript: shiftPositionsInScript2 } = parser;
7308
- return shiftPositionsInScript2(block.scriptText, targetSelector, delta, block.root);
7378
+ const { shiftPositionsInScript } = parser;
7379
+ return shiftPositionsInScript(block.scriptText, targetSelector, delta, block.root);
7309
7380
  }
7310
7381
  case "shift-positions-batch": {
7311
- const { shiftPositionsInScript: shiftPositionsInScript2 } = parser;
7382
+ const { shiftPositionsInScript } = parser;
7312
7383
  let script = block.scriptText;
7313
7384
  for (const s of body.shifts) {
7314
7385
  if (!s.targetSelector || !Number.isFinite(s.delta) || s.delta === 0) continue;
7315
- script = shiftPositionsInScript2(script, s.targetSelector, s.delta, block.root);
7386
+ script = shiftPositionsInScript(script, s.targetSelector, s.delta, block.root);
7316
7387
  }
7317
7388
  return script;
7318
7389
  }
@@ -7321,8 +7392,8 @@ async function executeGsapMutationRecast(body, block, respond) {
7321
7392
  if (!targetSelector || !Number.isFinite(oldStart) || !Number.isFinite(oldDuration) || !Number.isFinite(newStart) || !Number.isFinite(newDuration) || oldDuration <= 0 || newDuration <= 0)
7322
7393
  return block.scriptText;
7323
7394
  if (oldStart === newStart && oldDuration === newDuration) return block.scriptText;
7324
- const { scalePositionsInScript: scalePositionsInScript2 } = parser;
7325
- return scalePositionsInScript2(
7395
+ const { scalePositionsInScript } = parser;
7396
+ return scalePositionsInScript(
7326
7397
  block.scriptText,
7327
7398
  targetSelector,
7328
7399
  oldStart,
@@ -8,7 +8,7 @@ import {
8
8
  DEFAULT_REGISTRY_URL,
9
9
  fetchItemManifest,
10
10
  fetchRegistryManifest
11
- } from "./chunk-6252EFFW.js";
11
+ } from "./chunk-KC5COKLP.js";
12
12
 
13
13
  // src/registry/resolver.ts
14
14
  function defaultWarn(message) {
@@ -6,7 +6,7 @@ var __filename = __hf_fileURLToPath(import.meta.url);
6
6
  var __dirname = __hf_dirname(__filename);
7
7
  import {
8
8
  resolveCaptureBrowserGpuMode
9
- } from "./chunk-P4PMYDLR.js";
9
+ } from "./chunk-4QJQOVN4.js";
10
10
  import {
11
11
  requestCliExit
12
12
  } from "./chunk-PBN6GBJE.js";