hyperframes 0.8.126 → 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-7NBR6B3F.js → add-DI4T5YLH.js} +15 -15
  2. package/dist/{animatedGifPrep-L5V2GEUO.js → animatedGifPrep-TSK322QL.js} +6 -6
  3. package/dist/{asset-JBGYRDTW.js → asset-CFW5RUI3.js} +2 -2
  4. package/dist/{assetCataloger-2DWSDIJG.js → assetCataloger-MDMKZM4O.js} +2 -2
  5. package/dist/{auth-6CYSAYBB.js → auth-7GR2JYK4.js} +2 -2
  6. package/dist/{autoUpdate-NOG7CHB6.js → autoUpdate-VPEWPSH6.js} +2 -2
  7. package/dist/{backgroundChecks-7CCDAF4Q.js → backgroundChecks-XU7Y6JEZ.js} +3 -3
  8. package/dist/backgroundChecksWorker.js +3 -3
  9. package/dist/{batchRender-KOMFN3WS.js → batchRender-HIRFZIUO.js} +3 -3
  10. package/dist/{beats-TUAVN7GG.js → beats-6EJDWT63.js} +14 -14
  11. package/dist/{benchmark-TE726E5O.js → benchmark-F7U6WZGQ.js} +12 -12
  12. package/dist/{browser-2LX4CSEG.js → browser-3ECFI3DA.js} +9 -9
  13. package/dist/{bundleWithLocalizedFonts-5RRZNHVZ.js → bundleWithLocalizedFonts-OVFXAXV3.js} +2 -2
  14. package/dist/{capture-35UCVULB.js → capture-AC5TRHS5.js} +2 -2
  15. package/dist/{capture-VP3NXL6L.js → capture-YH5MUSL7.js} +9 -9
  16. package/dist/{catalog-AGTKIUQX.js → catalog-TRZAPAXM.js} +15 -15
  17. package/dist/{check-6FNESOS3.js → check-HP7N4TPB.js} +34 -34
  18. package/dist/{checkBrowser-QSTDEWYE.js → checkBrowser-BHLSXZ3V.js} +35 -35
  19. package/dist/{chunk-INWZRXCW.js → chunk-2CACHG7K.js} +3 -3
  20. package/dist/{chunk-HWTQNKW5.js → chunk-34C66AH5.js} +2 -2
  21. package/dist/{chunk-3GSNYSFF.js → chunk-3PDQ4PS2.js} +1 -1
  22. package/dist/{chunk-JR73DPKV.js → chunk-4AH73ZQW.js} +1 -1
  23. package/dist/{chunk-TO6DMAUZ.js → chunk-4DGJUQFZ.js} +1 -1
  24. package/dist/{chunk-KB37AHZU.js → chunk-4IZNC32H.js} +1 -1
  25. package/dist/{chunk-NSVHO5LZ.js → chunk-4NWOGZZS.js} +50 -40
  26. package/dist/{chunk-KTJUHHEQ.js → chunk-4QJQOVN4.js} +1 -1
  27. package/dist/{chunk-ONACH4F6.js → chunk-56P5SEOM.js} +1 -1
  28. package/dist/{chunk-PWZANSLF.js → chunk-5NZVDRRZ.js} +226 -160
  29. package/dist/{chunk-STZBZXZT.js → chunk-6F63NYFZ.js} +1 -1
  30. package/dist/{chunk-JMI5PVKK.js → chunk-6RGOHYPP.js} +1 -1
  31. package/dist/{chunk-44ABPBX3.js → chunk-72WHJNAR.js} +2 -2
  32. package/dist/{chunk-UB7MYXCO.js → chunk-77EJSKGP.js} +2 -2
  33. package/dist/{chunk-THTG3VL4.js → chunk-A7VIBZLC.js} +2 -2
  34. package/dist/{chunk-SXPMTU6B.js → chunk-AQUXI6ZL.js} +5 -5
  35. package/dist/{chunk-F7MXHGU3.js → chunk-AVUUN2XD.js} +51 -41
  36. package/dist/{chunk-I2AFLOPD.js → chunk-BELUXCL4.js} +1 -1
  37. package/dist/{chunk-TKWTL6GV.js → chunk-BK2KLAYO.js} +3 -3
  38. package/dist/{chunk-U4FYLOXY.js → chunk-BW773MMX.js} +4 -4
  39. package/dist/{chunk-5CJ3YWEE.js → chunk-CF6QQ6CL.js} +7 -7
  40. package/dist/{chunk-5WXI4DPS.js → chunk-COD4GMYB.js} +1 -1
  41. package/dist/{chunk-ZLJXATSQ.js → chunk-FI4I7CME.js} +1 -1
  42. package/dist/{chunk-ZKUDKJDT.js → chunk-FN7KZDH7.js} +1 -1
  43. package/dist/{chunk-ZZWX22ZL.js → chunk-H5TVAQAK.js} +4 -4
  44. package/dist/{chunk-BVY7I3HG.js → chunk-IKSUSTJT.js} +1 -1
  45. package/dist/{chunk-NZWMOYQ4.js → chunk-JDNYDR3Y.js} +1 -1
  46. package/dist/{chunk-G2XWQ4ZE.js → chunk-KC5COKLP.js} +1 -1
  47. package/dist/{chunk-4X2UFVOK.js → chunk-KUZTSKD2.js} +1 -1
  48. package/dist/{chunk-2JJO2O4F.js → chunk-L5IFUB5G.js} +2 -2
  49. package/dist/{chunk-BKXZGOH7.js → chunk-LGTAOCIM.js} +1 -1
  50. package/dist/{chunk-67QQI7JH.js → chunk-LRDOFHS5.js} +2 -2
  51. package/dist/{chunk-WYPGIFYA.js → chunk-OESXJGYM.js} +1 -1
  52. package/dist/{chunk-GA46NF76.js → chunk-PDAMK4Q5.js} +1 -1
  53. package/dist/{chunk-X34RX267.js → chunk-Q767NO4V.js} +3 -3
  54. package/dist/{chunk-OQS3A7QF.js → chunk-QFQET76X.js} +54 -13
  55. package/dist/{chunk-IRAEOBDX.js → chunk-QPRIMML2.js} +1 -1
  56. package/dist/{chunk-CHMDN7EH.js → chunk-RLK4ARFU.js} +2 -2
  57. package/dist/{chunk-2GIIUVKT.js → chunk-UROSVQOH.js} +2 -2
  58. package/dist/{chunk-ECF5RGLH.js → chunk-VKBSHU24.js} +5 -5
  59. package/dist/{chunk-RHXKUUEP.js → chunk-VQME2GRN.js} +11 -11
  60. package/dist/{chunk-32MY4AZN.js → chunk-WPHMNO44.js} +1345 -23
  61. package/dist/{chunk-VVKADE6I.js → chunk-WULYBA5Y.js} +3 -3
  62. package/dist/{chunk-BW5F5OXO.js → chunk-WVU5CJXG.js} +1 -1
  63. package/dist/{chunk-3XZK3GNY.js → chunk-YRKBFZDQ.js} +1 -1
  64. package/dist/{chunk-N4RVOW43.js → chunk-ZJUKFZ2P.js} +2 -2
  65. package/dist/{chunk-YYMPS4RQ.js → chunk-ZT4WM4B6.js} +12 -12
  66. package/dist/{clean-AUQHQ42C.js → clean-6Q36AWQL.js} +18 -18
  67. package/dist/cli.js +52 -52
  68. package/dist/{cloud-4AEBQ4XH.js → cloud-GQ5UHZZN.js} +4 -4
  69. package/dist/{cloudrun-S7IW2H35.js → cloudrun-JD7H36SS.js} +4 -4
  70. package/dist/{compare-ZCPVJC7Y.js → compare-YONA7IFI.js} +26 -26
  71. package/dist/{compiler-ONZBL2Z2.js → compiler-GNV7YQRO.js} +2 -2
  72. package/dist/{component-D5WGH5CE.js → component-BXHWGVG4.js} +3 -3
  73. package/dist/{compositions-L5HA7YJU.js → compositions-XC7Y2FPL.js} +11 -11
  74. package/dist/{delete-WWRSJ4KP.js → delete-73UVP2DH.js} +3 -3
  75. package/dist/{deterministicFonts-HHGHYN6V.js → deterministicFonts-HAEMV4TM.js} +5 -4
  76. package/dist/{dist-RUZFIHUD.js → dist-FNNGCKFS.js} +1 -1
  77. package/dist/{dist-6YFMU2EX.js → dist-NDHKRZTY.js} +2 -2
  78. package/dist/{doctor-JISX7NCX.js → doctor-J76TZOKL.js} +10 -10
  79. package/dist/{events-XD7RFVVW.js → events-FB2W7SMV.js} +9 -9
  80. package/dist/{events-YVGY4DDL.js → events-I3JMSDHY.js} +8 -8
  81. package/dist/{feedback-S7GVNKI5.js → feedback-WSIA7ROU.js} +12 -12
  82. package/dist/{figma-PGHX2SST.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-GCOZY5GX.js → get-DXEKFVNL.js} +3 -3
  86. package/dist/{gpuPolicy-PF25HSOC.js → gpuPolicy-IGXJ6JGL.js} +6 -6
  87. package/dist/{grade-compare-6GXSZOQD.js → grade-compare-PXBFW53F.js} +26 -26
  88. package/dist/{gsapParser-ZGBBDA54.js → gsapParser-DIYYX6JT.js} +83 -53
  89. package/dist/{gsapParserAcorn-3Z742FXU.js → gsapParserAcorn-E3GEIRZB.js} +1 -1
  90. package/dist/{help-MGQRBCOB.js → help-Z6TEXIAO.js} +1 -1
  91. package/dist/{history-OR4CFVKW.js → history-EFWP3CMR.js} +18 -18
  92. package/dist/hyperframes-player.global.js +1 -1
  93. package/dist/{info-ORCBX5QT.js → info-AQ2ZLWSB.js} +11 -11
  94. package/dist/{init-2VMWQT7Q.js → init-6ZEBBSR5.js} +22 -22
  95. package/dist/{inspect-ESXETWYQ.js → inspect-EUOV4DGL.js} +27 -27
  96. package/dist/{installer-DY5EJGH4.js → installer-WI6EKOWS.js} +4 -4
  97. package/dist/{keyframes-SVZSP2IX.js → keyframes-U6LVMYGO.js} +62 -52
  98. package/dist/{lambda-SU52VKMJ.js → lambda-F6SI24C7.js} +5 -5
  99. package/dist/{layout-2QQITNZH.js → layout-VQRYMZRP.js} +27 -27
  100. package/dist/{lint-JWDUEMAF.js → lint-EBHMQRKO.js} +14 -14
  101. package/dist/{lintProject-MXUZEBDH.js → lintProject-OHBBM3DJ.js} +1 -1
  102. package/dist/{list-DMA3RMP3.js → list-EUOXTLX6.js} +3 -3
  103. package/dist/{login-L3YG6OGU.js → login-OXGFQNHT.js} +4 -4
  104. package/dist/{media-treatment-NVAU46UZ.js → media-treatment-TVCTGGDO.js} +14 -14
  105. package/dist/{models-ULNRSUPZ.js → models-XNX7UHKU.js} +7 -7
  106. package/dist/{motionShot-UZ55EFYK.js → motionShot-JXQIO5VJ.js} +12 -12
  107. package/dist/{normalize-audio-E5S32LB7.js → normalize-audio-L5LTPJIR.js} +13 -13
  108. package/dist/{open-IF42Y7XZ.js → open-BON6TWUG.js} +10 -10
  109. package/dist/{pipeline-2SJBNWN6.js → pipeline-NID4HZDH.js} +6 -6
  110. package/dist/{play-NWZVZ2VG.js → play-GH43JSBS.js} +29 -29
  111. package/dist/{preflight-DLBJ2ORQ.js → preflight-VSZD4AND.js} +7 -7
  112. package/dist/{present-G3D32OYG.js → present-7PTSYTYU.js} +20 -20
  113. package/dist/{preview-2DFT6L5Y.js → preview-X2WVPV66.js} +20 -20
  114. package/dist/{producer-HDJFB63D.js → producer-TLATG6GZ.js} +1 -1
  115. package/dist/{projectConfig-MNOSK2QD.js → projectConfig-KKPSSHER.js} +6 -6
  116. package/dist/{publication-YDMJ7ZWP.js → publication-6BFZTAYA.js} +2 -2
  117. package/dist/{publish-2U3QFDUG.js → publish-ZDRTAWEH.js} +11 -11
  118. package/dist/{remove-background-WGQL5TTE.js → remove-background-OZ4OR3B2.js} +7 -7
  119. package/dist/{render-Z2JVFMEG.js → render-U3BRPPSW.js} +3 -3
  120. package/dist/{render-KOZDACHF.js → render-ZH5ZCLWA.js} +17 -17
  121. package/dist/{render-IP5YBVN3.js → render-ZTIEKMAN.js} +26 -26
  122. package/dist/{render-batch-MLATEYNJ.js → render-batch-3JALVFQN.js} +3 -3
  123. package/dist/{renderCancellation-GIVVJ4Y5.js → renderCancellation-NHRJYSHT.js} +6 -6
  124. package/dist/renderSetupWorker.js +1 -1
  125. package/dist/{resolver-YPSQI4QB.js → resolver-Z2T2GU2O.js} +4 -4
  126. package/dist/{sherpa-XJUQMGO2.js → sherpa-DRIVXEAC.js} +7 -7
  127. package/dist/{skills-C4AYI3JQ.js → skills-XLN4DLZP.js} +11 -11
  128. package/dist/{skillsUpdateCheck-SZ5YHOKU.js → skillsUpdateCheck-CDL66I4W.js} +3 -3
  129. package/dist/{snapshot-ITGMVKHC.js → snapshot-63YZCABA.js} +32 -32
  130. package/dist/{src-T3KNHVM4.js → src-3M44XVWE.js} +5 -5
  131. package/dist/{src-B2EJ6PDH.js → src-3Q2T2TAT.js} +11 -12
  132. package/dist/{staticProjectServer-XMPCVKOC.js → staticProjectServer-F563BICS.js} +14 -14
  133. package/dist/{status-26CCBKGN.js → status-HPLBWFSU.js} +6 -6
  134. package/dist/studio/assets/{hyperframes-player-BbbN-wWN.js → hyperframes-player-CKCx0CFA.js} +1 -1
  135. package/dist/studio/assets/{index-Cll7uTNy.js → index-CF31Pq1E.js} +1 -1
  136. package/dist/studio/assets/{index-B8kU2xXl.js → index-ClLzyuwb.js} +172 -172
  137. package/dist/studio/assets/{index-nvLF29ZH.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 +2184 -1745
  148. package/dist/studio/index.js.map +1 -1
  149. package/dist/studio/player.js +2 -2
  150. package/dist/{studio-api-RGD6QIM6.js → studio-api-PH5PMXQW.js} +8 -8
  151. package/dist/{studioServer-4KI47OI7.js → studioServer-4CEIYT2G.js} +47 -47
  152. package/dist/{system-KCJSXBNN.js → system-G6PL23LG.js} +6 -6
  153. package/dist/{telemetry-4O4ERZUD.js → telemetry-ILX6SWZM.js} +9 -9
  154. package/dist/{timeline-MFCQASNE.js → timeline-3K3WNFPP.js} +18 -18
  155. package/dist/{tokens-TI7WWQJ6.js → tokens-GKA5I6SX.js} +2 -2
  156. package/dist/{transcribe-GUOLCXLE.js → transcribe-P76R64RU.js} +7 -7
  157. package/dist/{transcribe-P72V4E5C.js → transcribe-ZZSCMKNC.js} +12 -12
  158. package/dist/{tts-CGUXR7R4.js → tts-P3LIPIL5.js} +1 -1
  159. package/dist/{updateCheck-GGXGOFYE.js → updateCheck-QBLDWYDK.js} +2 -2
  160. package/dist/{upgrade-CJRMDDJD.js → upgrade-RDBANWHF.js} +2 -2
  161. package/dist/{urlDownloader-F7DTZEP4.js → urlDownloader-VVG2YURO.js} +5 -5
  162. package/dist/{validate-VJ4JRMM2.js → validate-55V46LZZ.js} +16 -16
  163. package/dist/{video-KVK4KZPN.js → video-S2W6UQ4H.js} +6 -6
  164. package/package.json +1 -1
  165. package/dist/chunk-NSY245QZ.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-U4FYLOXY.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-CHMDN7EH.js";
63
+ } from "./chunk-RLK4ARFU.js";
64
64
  import {
65
65
  findTimelineScript,
66
66
  parseGsapScriptAcorn
67
- } from "./chunk-NSVHO5LZ.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-3XZK3GNY.js";
84
+ } from "./chunk-YRKBFZDQ.js";
85
85
  import {
86
86
  MagicString,
87
87
  VALID_CANVAS_RESOLUTIONS,
88
88
  unrollComputedTimeline
89
- } from "./chunk-F7MXHGU3.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-BW5F5OXO.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-N4RVOW43.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,26 @@ function classifyPropertyGroup(prop) {
2213
2214
  }
2214
2215
 
2215
2216
  // ../parsers/dist/gsapWriterAcorn.js
2217
+ var GSAP_DEFAULT_DURATION = 0.5;
2218
+ var BUILTIN_VAR_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "delay"]);
2219
+ var DROPPED_VAR_KEYS = /* @__PURE__ */ new Set([
2220
+ "onComplete",
2221
+ "onStart",
2222
+ "onUpdate",
2223
+ "onRepeat"
2224
+ ]);
2225
+ var EXTRAS_KEYS = /* @__PURE__ */ new Set([
2226
+ "stagger",
2227
+ "yoyo",
2228
+ "repeat",
2229
+ "repeatDelay",
2230
+ "snap",
2231
+ "overwrite",
2232
+ "immediateRender"
2233
+ ]);
2234
+ function isTweenConfigKey(key) {
2235
+ return BUILTIN_VAR_KEYS.has(key) || DROPPED_VAR_KEYS.has(key) || EXTRAS_KEYS.has(key);
2236
+ }
2216
2237
  var PROPERTY_GROUPS2 = {
2217
2238
  position: /* @__PURE__ */ new Set(["x", "y", "xPercent", "yPercent"]),
2218
2239
  scale: /* @__PURE__ */ new Set(["scale", "scaleX", "scaleY"]),
@@ -2252,22 +2273,23 @@ function positionHoldForAnimation(animation, animations) {
2252
2273
  if (!animation.keyframes) return null;
2253
2274
  const start = knownStart(animation) ?? 0;
2254
2275
  if (!(start > 1e-3)) return null;
2255
- const first = [...animation.keyframes.keyframes].sort(
2256
- (left, right) => left.percentage - right.percentage
2257
- )[0];
2258
- if (!first) return null;
2276
+ const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);
2277
+ if (!atStart) return null;
2259
2278
  const earlier = animations.filter((other) => {
2260
2279
  const otherStart = knownStart(other);
2261
2280
  return other !== animation && !other.global && other.targetSelector === animation.targetSelector && otherStart !== void 0 && otherStart < start - 1e-3;
2262
2281
  });
2263
2282
  const position = {};
2264
- for (const [property, value] of Object.entries(first.properties)) {
2283
+ for (const [property, value] of Object.entries(atStart.properties)) {
2265
2284
  if (classifyPropertyGroup2(property) !== "position" || typeof value !== "number") continue;
2266
2285
  if (earlier.some((other) => writesProperty(other, property))) continue;
2267
2286
  position[property] = value;
2268
2287
  }
2269
2288
  return Object.keys(position).length > 0 ? position : null;
2270
2289
  }
2290
+ function authorsKeyframes(anim) {
2291
+ return anim.keyframes !== void 0 || anim.hasUnresolvedKeyframes === true;
2292
+ }
2271
2293
  function mergePercentageKeyframes(keyframes) {
2272
2294
  const byPercentage = /* @__PURE__ */ new Map();
2273
2295
  for (const keyframe of keyframes) {
@@ -2411,34 +2433,27 @@ function readProvenance(node) {
2411
2433
  var roundPercentage = (percentage) => Math.round(percentage * 10) / 10;
2412
2434
  var OBJECT_ARRAY_PERCENTAGE_TOLERANCE = 2;
2413
2435
  function getObjectArrayKeyframeTiming(durations) {
2414
- const hasAuthoredDuration = durations.some((duration) => duration !== void 0);
2415
- if (hasAuthoredDuration) {
2416
- if (!durations.every(
2417
- (duration) => typeof duration === "number" && Number.isFinite(duration) && duration > 0
2418
- )) {
2419
- return null;
2420
- }
2421
- const totalDuration = durations.reduce((sum, duration) => sum + duration, 0);
2422
- let cumulative = 0;
2423
- return {
2424
- percentages: durations.map((duration) => {
2425
- cumulative += duration;
2426
- return roundPercentage(cumulative / totalDuration * 100);
2427
- }),
2428
- totalDuration
2429
- };
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;
2430
2441
  }
2431
- const lastIndex = durations.length - 1;
2442
+ const totalDuration = steps.reduce((sum, duration) => sum + duration, 0);
2443
+ let cumulative = 0;
2432
2444
  return {
2433
- percentages: durations.map(
2434
- (_, index) => lastIndex > 0 ? roundPercentage(index / lastIndex * 100) : 0
2435
- )
2445
+ percentages: steps.map((duration) => {
2446
+ cumulative += duration;
2447
+ return roundPercentage(cumulative / totalDuration * 100);
2448
+ }),
2449
+ totalDuration
2436
2450
  };
2437
2451
  }
2438
2452
  function getCompatibleObjectArrayKeyframeTiming(durations, outerDuration) {
2439
2453
  const timing = getObjectArrayKeyframeTiming(durations);
2440
2454
  if (!timing) return null;
2441
- 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;
2442
2457
  if (typeof outerDuration === "number" && Math.abs(outerDuration - timing.totalDuration) <= Number.EPSILON) {
2443
2458
  return timing;
2444
2459
  }
@@ -2954,17 +2969,6 @@ function findTimelineVar(ast, scope) {
2954
2969
  });
2955
2970
  return { timelineVar, ref, timelineCount, defaults };
2956
2971
  }
2957
- var BUILTIN_VAR_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "delay"]);
2958
- var DROPPED_VAR_KEYS = /* @__PURE__ */ new Set(["onComplete", "onStart", "onUpdate", "onRepeat"]);
2959
- var EXTRAS_KEYS = /* @__PURE__ */ new Set([
2960
- "stagger",
2961
- "yoyo",
2962
- "repeat",
2963
- "repeatDelay",
2964
- "snap",
2965
- "overwrite",
2966
- "immediateRender"
2967
- ]);
2968
2972
  function isTimelineRootedCall(callNode, ref) {
2969
2973
  let obj = callNode.callee?.object;
2970
2974
  while (obj?.type === "CallExpression") {
@@ -3043,6 +3047,7 @@ function parsePercentageKeyframes(node, scope, source) {
3043
3047
  if (typeof key !== "string") continue;
3044
3048
  const pctMatch = PERCENTAGE_KEY_RE.exec(key);
3045
3049
  if (pctMatch) {
3050
+ if (!isPlainStep(prop.value)) return void 0;
3046
3051
  const percentage = Number.parseFloat(pctMatch[1] ?? "0");
3047
3052
  const record = objectExpressionToRecord(prop.value, scope, source);
3048
3053
  const properties = {};
@@ -3061,6 +3066,8 @@ function parsePercentageKeyframes(node, scope, source) {
3061
3066
  ease = tryResolveStringProp(prop.value, scope, source) ?? ease;
3062
3067
  } else if (key === "easeEach") {
3063
3068
  easeEach = tryResolveStringProp(prop.value, scope, source) ?? easeEach;
3069
+ } else {
3070
+ return void 0;
3064
3071
  }
3065
3072
  }
3066
3073
  keyframes.sort((a, b) => a.percentage - b.percentage);
@@ -3084,11 +3091,19 @@ function computeKeyframesTotalDuration(varsNode, scope, source) {
3084
3091
  }
3085
3092
  return getObjectArrayKeyframeTiming(durations)?.totalDuration;
3086
3093
  }
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);
3087
3102
  function parseObjectArrayKeyframes(node, scope, source) {
3088
3103
  const elements = node.elements ?? [];
3089
3104
  const raw = [];
3090
3105
  for (const el of elements) {
3091
- if (!el || el.type !== "ObjectExpression") continue;
3106
+ if (!isPlainObject(el)) return void 0;
3092
3107
  const record = objectExpressionToRecord(el, scope, source);
3093
3108
  const properties = {};
3094
3109
  let duration;
@@ -3100,6 +3115,8 @@ function parseObjectArrayKeyframes(node, scope, source) {
3100
3115
  ease = v;
3101
3116
  } else if (typeof v === "number" || typeof v === "string") {
3102
3117
  properties[k] = v;
3118
+ } else {
3119
+ return void 0;
3103
3120
  }
3104
3121
  }
3105
3122
  raw.push({ properties, duration, ease });
@@ -3125,9 +3142,8 @@ function parseSimpleArrayKeyframes(node, scope) {
3125
3142
  const values = [];
3126
3143
  for (const el of prop.value.elements ?? []) {
3127
3144
  const val = resolveNode(el, scope);
3128
- if (typeof val === "number" || typeof val === "string") {
3129
- values.push(val);
3130
- }
3145
+ if (typeof val !== "number" && typeof val !== "string") return void 0;
3146
+ values.push(val);
3131
3147
  }
3132
3148
  if (values.length > 0) arrayProps.set(key, values);
3133
3149
  } else if (key === "ease") {
@@ -3160,6 +3176,7 @@ function parseKeyframesNode(node, scope, source) {
3160
3176
  }
3161
3177
  if (node.type !== "ObjectExpression") return void 0;
3162
3178
  const props = node.properties ?? [];
3179
+ if (!props.every((p) => staticKeyName(p) !== void 0)) return void 0;
3163
3180
  let hasPercentageKey = false;
3164
3181
  let hasArrayValue = false;
3165
3182
  for (const prop of props) {
@@ -3260,7 +3277,7 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
3260
3277
  percentage: waypoints.length > 1 ? Math.round(i / (waypoints.length - 1) * 100) : 0,
3261
3278
  properties: { x: wp.x, y: wp.y }
3262
3279
  }));
3263
- keyframesData = { format: "percentage", keyframes: kf };
3280
+ keyframesData = { format: "percentage", keyframes: kf, fromMotionPath: true };
3264
3281
  } else {
3265
3282
  const kfs = keyframesData.keyframes;
3266
3283
  if (kfs.length === waypoints.length) {
@@ -3290,10 +3307,10 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
3290
3307
  const position = typeof posVal === "number" ? posVal : typeof posVal === "string" ? posVal : hasPositionArg ? `__raw:${source.slice(call.positionArg.start, call.positionArg.end)}` : 0;
3291
3308
  let duration = typeof vars.duration === "number" ? vars.duration : void 0;
3292
3309
  const ease = typeof vars.ease === "string" ? vars.ease : void 0;
3293
- 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) {
3294
3312
  duration = computeKeyframesTotalDuration(call.varsArg, scope, source);
3295
3313
  }
3296
- const durationUnresolved = call.method !== "set" && duration === void 0 && hasUnknownDuration(call.varsArg, scope);
3297
3314
  let selector = call.selector;
3298
3315
  let targetIdentity;
3299
3316
  if (selector === "__unresolved__") {
@@ -3347,7 +3364,6 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
3347
3364
  if (provenance) anim.provenance = provenance;
3348
3365
  return anim;
3349
3366
  }
3350
- var GSAP_DEFAULT_DURATION = 0.5;
3351
3367
  function resolvePositionString(pos, cursor, prevStart) {
3352
3368
  const trimmed = pos.trim();
3353
3369
  if (trimmed === "") return cursor;
@@ -3380,7 +3396,7 @@ function applyTimelineDefaults(anims, defaults) {
3380
3396
  if (defaults.duration !== void 0) anim.duration = defaults.duration;
3381
3397
  else if (defaults.durationUnresolved) anim.durationUnresolved = true;
3382
3398
  }
3383
- 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)) {
3384
3400
  anim.ease = defaults.ease;
3385
3401
  }
3386
3402
  }
@@ -3544,14 +3560,25 @@ function parseGsapScriptAcornForWrite(script) {
3544
3560
  return null;
3545
3561
  }
3546
3562
  }
3547
- function clipTweenMatcher(clipSelectors, root) {
3563
+ function clipTweenMatcher(clipSelectors, root, queries = /* @__PURE__ */ new Map()) {
3548
3564
  const own = typeof clipSelectors === "string" ? [clipSelectors] : clipSelectors;
3549
- 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));
3550
3577
  return ({ targetSelector, hasPartialSelector }) => {
3551
3578
  if (hasPartialSelector) return false;
3552
3579
  if (own.includes(targetSelector)) return true;
3553
- if (!root || clips.length === 0) return false;
3554
- const targets = queryAll(root, targetSelector);
3580
+ if (clips.length === 0) return false;
3581
+ const targets = queryAll(targetSelector);
3555
3582
  return targets.length > 0 && targets.every((target) => {
3556
3583
  const owner = target.closest("[data-start]");
3557
3584
  return clips.includes(target) || owner !== null && clips.includes(owner);
@@ -3564,7 +3591,20 @@ function clipQueryRoot(script) {
3564
3591
  function hasExplicitTime(animation) {
3565
3592
  return typeof animation.position === "number" && !animation.implicitPosition;
3566
3593
  }
3567
- 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) {
3568
3608
  try {
3569
3609
  return Array.from(root.querySelectorAll(selector));
3570
3610
  } catch {
@@ -3678,24 +3718,8 @@ function upsertProp(ms, objNode, key, value) {
3678
3718
  ms.appendLeft(objNode.end - 1, `${sep4}${safeKey(key)}: ${valueToCode(value)}`);
3679
3719
  }
3680
3720
  }
3681
- var NON_EDITABLE_PROP_KEYS = /* @__PURE__ */ new Set([
3682
- "duration",
3683
- "ease",
3684
- "delay",
3685
- "onComplete",
3686
- "onStart",
3687
- "onUpdate",
3688
- "onRepeat",
3689
- "stagger",
3690
- "yoyo",
3691
- "repeat",
3692
- "repeatDelay",
3693
- "snap",
3694
- "overwrite",
3695
- "immediateRender"
3696
- ]);
3697
3721
  function isEditableVarKey(key) {
3698
- return !NON_EDITABLE_PROP_KEYS.has(key);
3722
+ return !isTweenConfigKey(key);
3699
3723
  }
3700
3724
  function preservedEntries(objNode, source, drop, overrides) {
3701
3725
  const entries = [];
@@ -3747,7 +3771,7 @@ function updateAnimationInScript(script, animationId, updates) {
3747
3771
  const parsed = parseGsapScriptAcornForWrite(script);
3748
3772
  if (!parsed) return script;
3749
3773
  const target = parsed.located.find((l) => l.id === animationId);
3750
- if (!target) return script;
3774
+ if (!target || updates.properties && target.animation.hasUnresolvedKeyframes) return script;
3751
3775
  const ms = new MagicString(script);
3752
3776
  const { call } = target;
3753
3777
  if (updates.properties) {
@@ -3810,47 +3834,56 @@ function overwritePosition(ms, call, position) {
3810
3834
  ms.appendLeft(last ? last.end : call.node.end - 1, `, ${valueToCode(position)}`);
3811
3835
  }
3812
3836
  }
3813
- function shiftPositionsInScript(script, targetSelector, delta, root) {
3814
- const parsed = parseGsapScriptAcornForWrite(script);
3815
- if (!parsed) return script;
3816
- 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));
3817
3864
  const ms = new MagicString(script);
3818
- let changed = false;
3865
+ let wrote = false;
3819
3866
  for (const entry of parsed.located) {
3820
- if (!carries(entry.animation) || !hasExplicitTime(entry.animation)) continue;
3821
- overwritePosition(ms, entry.call, shiftedPosition(entry.animation.position, delta));
3822
- 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;
3823
3881
  }
3824
- return changed ? ms.toString() : script;
3882
+ return { script: wrote ? ms.toString() : script, changed };
3825
3883
  }
3826
3884
  function shiftedPosition(position, delta) {
3827
3885
  return Math.max(0, Math.round((position + delta) * 1e3) / 1e3);
3828
3886
  }
3829
- function scalePositionsInScript(script, targetSelector, oldStart, oldDuration, newStart, newDuration, root) {
3830
- if (oldDuration <= 0 || newDuration <= 0) return script;
3831
- const ratio = newDuration / oldDuration;
3832
- const parsed = parseGsapScriptAcornForWrite(script);
3833
- if (!parsed) return script;
3834
- const carries = clipTweenMatcher(targetSelector, root);
3835
- const ms = new MagicString(script);
3836
- let changed = false;
3837
- for (const entry of parsed.located) {
3838
- if (!carries(entry.animation) || typeof entry.animation.position !== "number") continue;
3839
- if (hasExplicitTime(entry.animation)) {
3840
- const newPos = Math.max(
3841
- 0,
3842
- Math.round((newStart + (entry.animation.position - oldStart) * ratio) * 1e3) / 1e3
3843
- );
3844
- overwritePosition(ms, entry.call, newPos);
3845
- }
3846
- if (typeof entry.animation.duration === "number" && entry.animation.duration > 0) {
3847
- const newDur = Math.max(1e-3, Math.round(entry.animation.duration * ratio * 1e3) / 1e3);
3848
- upsertProp(ms, entry.call.varsArg, "duration", newDur);
3849
- }
3850
- changed = true;
3851
- }
3852
- return changed ? ms.toString() : script;
3853
- }
3854
3887
  function addAnimationToScript(script, animation) {
3855
3888
  const parsed = parseGsapScriptAcornForWrite(script);
3856
3889
  if (!parsed) return { script, id: "" };
@@ -4123,7 +4156,7 @@ function updateKeyframeInScript(script, animationId, percentage, properties, eas
4123
4156
  const parsed = parseGsapScriptAcornForWrite(script);
4124
4157
  if (!parsed) return script;
4125
4158
  const target = parsed.located.find((l) => l.id === animationId);
4126
- if (!target) return script;
4159
+ if (!target || target.animation.hasUnresolvedKeyframes) return script;
4127
4160
  const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
4128
4161
  if (!kfPropNode) {
4129
4162
  return updateMotionPathKeyframe(script, target, percentage, properties, ease) ?? script;
@@ -4191,7 +4224,7 @@ function locateWithKeyframes(script, animationId) {
4191
4224
  if (!parsed) return null;
4192
4225
  const convertedId = animationId.replace(/-from-|-fromTo-/, "-to-");
4193
4226
  const target = parsed.located.find((l) => l.id === animationId) ?? parsed.located.find((l) => l.id === convertedId);
4194
- if (!target) return null;
4227
+ if (!target || target.animation.hasUnresolvedKeyframes) return null;
4195
4228
  const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
4196
4229
  if (!kfPropNode || kfPropNode.value?.type !== "ObjectExpression") return null;
4197
4230
  return { script, parsed, target, kfNode: kfPropNode.value };
@@ -4215,8 +4248,12 @@ function convertArrayKeyframesToObject(script, target) {
4215
4248
  return `${JSON.stringify(`${timing.percentages[i]}%`)}: ${recordToCode(record)}`;
4216
4249
  });
4217
4250
  const ms = new MagicString(script);
4218
- ms.overwrite(kfPropNode.value.start, kfPropNode.value.end, `{ ${entries.join(", ")} }`);
4219
- 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) {
4220
4257
  upsertProp(ms, target.call.varsArg, "duration", timing.totalDuration);
4221
4258
  }
4222
4259
  return ms.toString();
@@ -4226,7 +4263,7 @@ function ensureKeyframesNode(script, animationId) {
4226
4263
  if (direct) return direct;
4227
4264
  const parsed = parseGsapScriptAcornForWrite(script);
4228
4265
  const target = parsed?.located.find((l) => l.id === animationId);
4229
- if (!target) return null;
4266
+ if (!target || target.animation.hasUnresolvedKeyframes) return null;
4230
4267
  const kfProp = findPropertyNode2(target.call.varsArg, "keyframes");
4231
4268
  if (kfProp?.value?.type === "ArrayExpression") {
4232
4269
  const normalized = convertArrayKeyframesToObject(script, target);
@@ -4328,7 +4365,7 @@ function removeKeyframeFromScript(script, animationId, percentage) {
4328
4365
  const parsed = parseGsapScriptAcornForWrite(script);
4329
4366
  if (!parsed) return script;
4330
4367
  const target = parsed.located.find((l) => l.id === animationId);
4331
- if (!target) return script;
4368
+ if (!target || target.animation.hasUnresolvedKeyframes) return script;
4332
4369
  const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
4333
4370
  if (!kfPropNode) return script;
4334
4371
  if (kfPropNode.value?.type === "ArrayExpression") {
@@ -4452,7 +4489,7 @@ function convertToKeyframesFromScript(script, animationId, resolvedFromValues, s
4452
4489
  const target = parsed.located.find((l) => l.id === animationId);
4453
4490
  if (!target) return script;
4454
4491
  const { animation, call } = target;
4455
- if (animation.keyframes) return script;
4492
+ if (authorsKeyframes(animation)) return script;
4456
4493
  const isSet = call.method === "set";
4457
4494
  const { fromProps, toProps } = resolveConversionProps(animation, resolvedFromValues);
4458
4495
  const ms = new MagicString(script);
@@ -4668,6 +4705,7 @@ function splitIntoPropertyGroupsFromScript(script, animationId) {
4668
4705
  const target = parsed.located.find((l) => l.id === animationId);
4669
4706
  if (!target) return { script, ids: [animationId] };
4670
4707
  const { animation } = target;
4708
+ if (animation.hasUnresolvedKeyframes) return { script, ids: [animationId] };
4671
4709
  const allPropKeys = collectPropertyKeys(animation);
4672
4710
  const groupProps = partitionPropertyGroups(allPropKeys);
4673
4711
  if (groupProps.size <= 1) return { script, ids: [animationId] };
@@ -4942,8 +4980,8 @@ function computeForwardBaselines(matching, splitTime) {
4942
4980
  const pos = typeof anim.position === "number" ? anim.position : 0;
4943
4981
  const dur = anim.duration ?? 0;
4944
4982
  const animEnd = pos + dur;
4945
- if (anim.keyframes) {
4946
- const kfs = anim.keyframes.keyframes;
4983
+ if (authorsKeyframes(anim)) {
4984
+ const kfs = anim.keyframes?.keyframes ?? [];
4947
4985
  if (pos >= splitTime) {
4948
4986
  } else if (animEnd > splitTime) {
4949
4987
  for (const kf of kfs) {
@@ -5004,17 +5042,22 @@ function buildSpanningSplit(result, anim, pos, dur, fromSource, ctx) {
5004
5042
  extras: anim.extras
5005
5043
  }).script;
5006
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
+ }
5007
5055
  function applyTweenSplit(result, anim, baselineBefore, ctx, skippedSelectors) {
5008
5056
  const pos = typeof anim.position === "number" ? anim.position : 0;
5009
5057
  const dur = anim.duration ?? 0;
5010
5058
  const animEnd = pos + dur;
5011
- if (anim.keyframes) {
5012
- if (pos >= ctx.splitTime)
5013
- return updateAnimationSelectorInScript(result, anim.id, ctx.newSelector);
5014
- if (animEnd > ctx.splitTime) {
5015
- skippedSelectors.push(`${ctx.originalSelector} (keyframes spanning split)`);
5016
- }
5017
- return result;
5059
+ if (authorsKeyframes(anim)) {
5060
+ return applyKeyframedTweenSplit(result, anim, pos, animEnd, ctx, skippedSelectors);
5018
5061
  }
5019
5062
  if (animEnd <= ctx.splitTime) return result;
5020
5063
  if (pos >= ctx.splitTime)
@@ -5961,7 +6004,7 @@ function requestSubPath(url, route) {
5961
6004
  return decodeURIComponent(segments.slice(start + routeSegments.length).join("/"));
5962
6005
  }
5963
6006
  async function loadGsapParser() {
5964
- return import("./gsapParser-ZGBBDA54.js");
6007
+ return import("./gsapParser-DIYYX6JT.js");
5965
6008
  }
5966
6009
  function isDanglingSymlinkInProject(projectDir, lexicalPath) {
5967
6010
  if (!isSafePath(projectDir, dirname32(lexicalPath))) return false;
@@ -6622,7 +6665,7 @@ async function prepareGsapMutationScript(c, res, firstMutation) {
6622
6665
  let block = extractGsapScriptBlock(html);
6623
6666
  if (!block && (firstMutation.type === "add" || firstMutation.type === "add-with-keyframes")) {
6624
6667
  const compId = html.match(/data-composition-id="([^"]+)"/)?.[1] ?? "main";
6625
- const { GSAP_CDN } = await import("./dist-6YFMU2EX.js");
6668
+ const { GSAP_CDN } = await import("./dist-NDHKRZTY.js");
6626
6669
  const bootstrap = [
6627
6670
  `<script src="${GSAP_CDN}"></script>`,
6628
6671
  "<script>",
@@ -6654,6 +6697,38 @@ ${bootstrap}`;
6654
6697
  if (!block) return c.json({ error: "no GSAP script found in file" }, 400);
6655
6698
  return { html, beforeHtml, block };
6656
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
+ }
6657
6732
  async function applyGsapMutations(c, res, mutations) {
6658
6733
  const firstMutation = mutations[0];
6659
6734
  if (!firstMutation) return c.json({ error: "mutations array required" }, 400);
@@ -6672,7 +6747,17 @@ async function applyGsapMutations(c, res, mutations) {
6672
6747
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);
6673
6748
  }
6674
6749
  const mutationChanges = [];
6675
- 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];
6676
6761
  const previousScript = block.scriptText;
6677
6762
  const result = await executeGsapMutation(mutation, block, respond, writer);
6678
6763
  if (result instanceof Response) return result;
@@ -6984,33 +7069,14 @@ function executeGsapMutationAcorn(body, block, respond) {
6984
7069
  case "unroll-timeline": {
6985
7070
  return unrollComputedTimeline(block.scriptText);
6986
7071
  }
6987
- case "shift-positions": {
6988
- const { targetSelector, delta } = body;
6989
- if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;
6990
- return shiftPositionsInScript(block.scriptText, targetSelector, delta, block.root);
6991
- }
6992
7072
  case "shift-positions-batch": {
6993
- let script = block.scriptText;
6994
- for (const s of body.shifts) {
6995
- if (!s.targetSelector || !Number.isFinite(s.delta) || s.delta === 0) continue;
6996
- script = shiftPositionsInScript(script, s.targetSelector, s.delta, block.root);
6997
- }
6998
- 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;
6999
7075
  }
7076
+ case "shift-positions":
7000
7077
  case "scale-positions": {
7001
- const { targetSelector, oldStart, oldDuration, newStart, newDuration } = body;
7002
- if (!targetSelector || !Number.isFinite(oldStart) || !Number.isFinite(oldDuration) || !Number.isFinite(newStart) || !Number.isFinite(newDuration) || oldDuration <= 0 || newDuration <= 0)
7003
- return block.scriptText;
7004
- if (oldStart === newStart && oldDuration === newDuration) return block.scriptText;
7005
- return scalePositionsInScript(
7006
- block.scriptText,
7007
- targetSelector,
7008
- oldStart,
7009
- oldDuration,
7010
- newStart,
7011
- newDuration,
7012
- block.root
7013
- );
7078
+ const retime = clipRetimeOf(body);
7079
+ return retime && retime !== "no-op" ? retimeClipTweensInScript(block.scriptText, [retime], block.root).script : block.scriptText;
7014
7080
  }
7015
7081
  default:
7016
7082
  return respond({ error: `unknown mutation type: ${body.type}` }, 400);
@@ -7309,15 +7375,15 @@ async function executeGsapMutationRecast(body, block, respond) {
7309
7375
  case "shift-positions": {
7310
7376
  const { targetSelector, delta } = body;
7311
7377
  if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;
7312
- const { shiftPositionsInScript: shiftPositionsInScript2 } = parser;
7313
- return shiftPositionsInScript2(block.scriptText, targetSelector, delta, block.root);
7378
+ const { shiftPositionsInScript } = parser;
7379
+ return shiftPositionsInScript(block.scriptText, targetSelector, delta, block.root);
7314
7380
  }
7315
7381
  case "shift-positions-batch": {
7316
- const { shiftPositionsInScript: shiftPositionsInScript2 } = parser;
7382
+ const { shiftPositionsInScript } = parser;
7317
7383
  let script = block.scriptText;
7318
7384
  for (const s of body.shifts) {
7319
7385
  if (!s.targetSelector || !Number.isFinite(s.delta) || s.delta === 0) continue;
7320
- script = shiftPositionsInScript2(script, s.targetSelector, s.delta, block.root);
7386
+ script = shiftPositionsInScript(script, s.targetSelector, s.delta, block.root);
7321
7387
  }
7322
7388
  return script;
7323
7389
  }
@@ -7326,8 +7392,8 @@ async function executeGsapMutationRecast(body, block, respond) {
7326
7392
  if (!targetSelector || !Number.isFinite(oldStart) || !Number.isFinite(oldDuration) || !Number.isFinite(newStart) || !Number.isFinite(newDuration) || oldDuration <= 0 || newDuration <= 0)
7327
7393
  return block.scriptText;
7328
7394
  if (oldStart === newStart && oldDuration === newDuration) return block.scriptText;
7329
- const { scalePositionsInScript: scalePositionsInScript2 } = parser;
7330
- return scalePositionsInScript2(
7395
+ const { scalePositionsInScript } = parser;
7396
+ return scalePositionsInScript(
7331
7397
  block.scriptText,
7332
7398
  targetSelector,
7333
7399
  oldStart,