hyperframes 0.8.127 → 0.8.129

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/dist/{add-7CE5XYK2.js → add-MFBQ4JQ3.js} +16 -16
  2. package/dist/{animatedGifPrep-4VAIRX7D.js → animatedGifPrep-P2T6YM7Z.js} +7 -7
  3. package/dist/{asset-22WQELZE.js → asset-LOZG7JHC.js} +2 -2
  4. package/dist/{assetCataloger-A2AITAHA.js → assetCataloger-VBLPHX24.js} +3 -3
  5. package/dist/{auth-33GV2LO2.js → auth-JKCXKQRS.js} +2 -2
  6. package/dist/{autoUpdate-OIXGTNLS.js → autoUpdate-5KHORE4C.js} +2 -2
  7. package/dist/{backgroundChecks-BVP36PXK.js → backgroundChecks-DTVWBC74.js} +3 -3
  8. package/dist/backgroundChecksWorker.js +3 -3
  9. package/dist/{batchRender-URT4LT44.js → batchRender-FT7AP7XH.js} +4 -4
  10. package/dist/{beats-U34XHTAA.js → beats-ZLLBJMPB.js} +15 -15
  11. package/dist/{benchmark-FNGERKUQ.js → benchmark-RU2FBIWR.js} +13 -13
  12. package/dist/{browser-35LEQMCO.js → browser-RQV6NSLN.js} +10 -10
  13. package/dist/{bundleWithLocalizedFonts-4CGUDHCA.js → bundleWithLocalizedFonts-5QOPOB5D.js} +2 -2
  14. package/dist/{capture-M2JJS4F2.js → capture-RLZA6EMR.js} +10 -10
  15. package/dist/{capture-GZKMVNKK.js → capture-SZZ4IYJK.js} +2 -2
  16. package/dist/{catalog-OVTLU2MC.js → catalog-LYPHWJDJ.js} +16 -16
  17. package/dist/{check-DBVGHGKO.js → check-R4UNOR5Z.js} +36 -36
  18. package/dist/{checkBrowser-2SQIUOXA.js → checkBrowser-RSUTDBXE.js} +37 -37
  19. package/dist/{chunk-AGNZ2QLE.js → chunk-2YN64IN5.js} +2 -2
  20. package/dist/{chunk-ZZAHIKFK.js → chunk-3ZP5DXE7.js} +1 -1
  21. package/dist/{chunk-RUYSBG3F.js → chunk-4NWOGZZS.js} +32 -30
  22. package/dist/{chunk-G33WTKF3.js → chunk-557OWRHF.js} +2 -2
  23. package/dist/{chunk-ZOUDTLLH.js → chunk-6CTIGJY7.js} +2 -2
  24. package/dist/{chunk-CSHKZ3SL.js → chunk-7HG4BFIN.js} +1 -1
  25. package/dist/{chunk-7YJ7CCKW.js → chunk-7JZ4FXP2.js} +1 -1
  26. package/dist/{chunk-6252EFFW.js → chunk-A2Z4Z4VL.js} +1 -1
  27. package/dist/{chunk-7DPBFAYT.js → chunk-AVUUN2XD.js} +33 -31
  28. package/dist/{chunk-HXGPETEM.js → chunk-B6YD6JAS.js} +1 -1
  29. package/dist/{chunk-RHBM33JF.js → chunk-BI6TVCDI.js} +7 -7
  30. package/dist/{chunk-F4WYYNNG.js → chunk-CFKU7HTK.js} +1 -1
  31. package/dist/{chunk-NDPSG5WQ.js → chunk-CWPVM2QV.js} +2 -2
  32. package/dist/{chunk-YSCN66NT.js → chunk-FCSIGXXP.js} +1 -1
  33. package/dist/{chunk-ZLJXATSQ.js → chunk-FI4I7CME.js} +1 -1
  34. package/dist/{chunk-KPY6JX4K.js → chunk-GO74M65A.js} +11 -11
  35. package/dist/{chunk-TL7Y6IBY.js → chunk-GOAUWA46.js} +3 -3
  36. package/dist/{chunk-6ACXAUBT.js → chunk-H64TB7NB.js} +4 -4
  37. package/dist/{chunk-S2WNVYLQ.js → chunk-HRUGC23L.js} +1 -1
  38. package/dist/chunk-HWKCIWQT.js +3578 -0
  39. package/dist/{chunk-MK2HBL6E.js → chunk-IUZFXWSV.js} +1 -1
  40. package/dist/{chunk-YII7JZ2C.js → chunk-IXCQU5RO.js} +1 -1
  41. package/dist/{chunk-TP4PR3SL.js → chunk-JO2J4S2L.js} +3 -3
  42. package/dist/{chunk-OE66T7R2.js → chunk-K2EQN4VU.js} +1 -1
  43. package/dist/{chunk-D4NPKZFY.js → chunk-K2FTXJYH.js} +3 -3
  44. package/dist/{chunk-CX7NQZDE.js → chunk-KBJUXVOJ.js} +3 -3
  45. package/dist/{chunk-QR7IRRUX.js → chunk-KHSCFD7K.js} +5 -5
  46. package/dist/{chunk-BYI2K4RN.js → chunk-LHSR3M4M.js} +2 -2
  47. package/dist/{chunk-PVVUMILD.js → chunk-LYNI3FOL.js} +1 -1
  48. package/dist/{chunk-HZHXHO4V.js → chunk-MWB3ZIFM.js} +1 -1
  49. package/dist/{chunk-OQN3AUOV.js → chunk-NTIV6QFJ.js} +12 -12
  50. package/dist/{chunk-7TSIAYXZ.js → chunk-PDAMK4Q5.js} +1 -1
  51. package/dist/{chunk-LLU2BJYY.js → chunk-Q7IU7MOR.js} +2 -2
  52. package/dist/{chunk-BE6X3G5C.js → chunk-QC4FJVLM.js} +1 -1
  53. package/dist/{chunk-EKGD52A2.js → chunk-QZDMFVY7.js} +2 -2
  54. package/dist/{chunk-IAKZWKNV.js → chunk-RMHUQGRK.js} +4 -4
  55. package/dist/{chunk-V6LLKVWS.js → chunk-RZAAVJ2F.js} +1 -1
  56. package/dist/{chunk-Q3I4JEGM.js → chunk-S7NPLFWV.js} +286 -143
  57. package/dist/{chunk-PZSNUSBM.js → chunk-TCLGPL65.js} +2 -2
  58. package/dist/{chunk-L32XKBOF.js → chunk-UBC3SMKR.js} +1 -1
  59. package/dist/{chunk-SC4T53X4.js → chunk-UDO4A3HY.js} +3 -3
  60. package/dist/{chunk-T6HJCRJC.js → chunk-UEZXMWG3.js} +2 -2
  61. package/dist/{chunk-32MY4AZN.js → chunk-WPHMNO44.js} +1345 -23
  62. package/dist/{chunk-GBTGTS35.js → chunk-WWTEA2BG.js} +1 -1
  63. package/dist/{chunk-P4PMYDLR.js → chunk-XS4EJSKU.js} +1 -1
  64. package/dist/{chunk-S4AMCVAK.js → chunk-YQZNILVH.js} +5 -5
  65. package/dist/{chunk-OLVR6P6R.js → chunk-Z6B37SNM.js} +2 -2
  66. package/dist/{chunk-TPWWGKU7.js → chunk-ZJUKFZ2P.js} +2 -2
  67. package/dist/{chunk-K3ZB5A3K.js → chunk-ZMXUQLI2.js} +55 -14
  68. package/dist/{clean-STQ2XPVL.js → clean-RDKBYQYS.js} +20 -20
  69. package/dist/cli.js +52 -52
  70. package/dist/{cloud-OQNTIR2N.js → cloud-DRCSH3RO.js} +4 -4
  71. package/dist/{cloudrun-ELOBBQHC.js → cloudrun-AJUTHUEA.js} +5 -5
  72. package/dist/{compare-7PHURXFI.js → compare-EJNCWA7A.js} +28 -28
  73. package/dist/{compiler-A3FX5DBC.js → compiler-QO36EXLS.js} +3 -3
  74. package/dist/{component-56DVF6XU.js → component-55TKGKMP.js} +3 -3
  75. package/dist/{compositions-2DMUUOFR.js → compositions-LDU2NXG3.js} +12 -12
  76. package/dist/{delete-EECQVAVJ.js → delete-M5FEYAQW.js} +3 -3
  77. package/dist/{deterministicFonts-64U7A25I.js → deterministicFonts-HAEMV4TM.js} +5 -4
  78. package/dist/{dist-OJYO32WN.js → dist-FNNGCKFS.js} +1 -1
  79. package/dist/{dist-IPEAV427.js → dist-S3PJNPXQ.js} +3 -3
  80. package/dist/{doctor-F3CXFLFV.js → doctor-AGGUO5NJ.js} +11 -11
  81. package/dist/{events-2LJGIZKG.js → events-CIWUMG4Z.js} +10 -10
  82. package/dist/{events-H5RGIYVK.js → events-LBZKC7L7.js} +9 -9
  83. package/dist/{feedback-VCMOOK2O.js → feedback-J7I7VS4Q.js} +13 -13
  84. package/dist/{figma-BL4HCJ5P.js → figma-2AIFPR3T.js} +3 -3
  85. package/dist/{fontData.generated-BW5QEPUT.js → fontData.generated-NXAOI4GH.js} +1 -1
  86. package/dist/fontLocalizeCli.js +11 -12
  87. package/dist/{get-HWN5Z3BL.js → get-ZJBDIWZJ.js} +3 -3
  88. package/dist/{gpuPolicy-37CE57HN.js → gpuPolicy-2ZUZE5D6.js} +7 -7
  89. package/dist/{grade-compare-3OPZYNNZ.js → grade-compare-XVYJT6ZR.js} +28 -28
  90. package/dist/{gsapParser-LOSAMHNR.js → gsapParser-DIYYX6JT.js} +63 -41
  91. package/dist/{gsapParserAcorn-ZO2LPEZY.js → gsapParserAcorn-E3GEIRZB.js} +1 -1
  92. package/dist/{help-X3EPTRKV.js → help-TBVVVEDS.js} +1 -1
  93. package/dist/{history-YR6YTOLT.js → history-NZPEQU4L.js} +20 -20
  94. package/dist/hyperframe-runtime.js +30 -30
  95. package/dist/hyperframe.manifest.json +1 -1
  96. package/dist/hyperframe.runtime.iife.js +30 -30
  97. package/dist/hyperframes-player.global.js +3 -3
  98. package/dist/{info-QG7OXNW6.js → info-T6BT2MFN.js} +12 -12
  99. package/dist/{init-JUHW2ZN3.js → init-4EPQ7SDV.js} +23 -23
  100. package/dist/{inspect-LIDYSXAG.js → inspect-BPZFMWWW.js} +29 -29
  101. package/dist/{installer-YH76H5ML.js → installer-K6O5WF44.js} +5 -5
  102. package/dist/{keyframes-ZLHVLMRA.js → keyframes-UL3XY52K.js} +45 -43
  103. package/dist/{lambda-T33I4AX6.js → lambda-D7UMN4DJ.js} +6 -6
  104. package/dist/{layout-VD36CWWV.js → layout-YYGOEQKI.js} +29 -29
  105. package/dist/{lint-JAWDGLYW.js → lint-OW2KOTEE.js} +15 -15
  106. package/dist/{lintProject-IOQ4DBS4.js → lintProject-OHBBM3DJ.js} +1 -1
  107. package/dist/{list-24TGFCB3.js → list-EIDAPK3I.js} +3 -3
  108. package/dist/{login-E2PE6CAD.js → login-DWU6OUCZ.js} +4 -4
  109. package/dist/{media-treatment-2BMUTUGD.js → media-treatment-I7BTOWX4.js} +15 -15
  110. package/dist/{models-TS5PWNPS.js → models-C4E4IWJD.js} +8 -8
  111. package/dist/{motionShot-RU4MTVOO.js → motionShot-S4MIGMT5.js} +13 -13
  112. package/dist/{normalize-audio-245DPF4X.js → normalize-audio-X2M4VF2O.js} +15 -15
  113. package/dist/{open-RH7YWUVH.js → open-35JKHN2G.js} +11 -11
  114. package/dist/{pipeline-ZK3JBXX5.js → pipeline-TNGWUZQC.js} +7 -7
  115. package/dist/{play-VK6IF765.js → play-F2LMNJEH.js} +31 -31
  116. package/dist/{preflight-H7YMOAYQ.js → preflight-SMNV6RW2.js} +8 -8
  117. package/dist/{present-CLKL6QSK.js → present-AD4N25LI.js} +21 -21
  118. package/dist/{preview-GEPWX2GX.js → preview-QWMTUNE2.js} +21 -21
  119. package/dist/{producer-HBP36IDM.js → producer-ECLEN5RP.js} +1 -1
  120. package/dist/{projectConfig-FPSBKFQO.js → projectConfig-HYJMJ5BY.js} +7 -7
  121. package/dist/{publication-ACSV54DD.js → publication-HQ5Y3KBM.js} +3 -3
  122. package/dist/{publish-L2NGI7MV.js → publish-VHDYQASC.js} +12 -12
  123. package/dist/{remove-background-JRRBJN4U.js → remove-background-W2YX2NVH.js} +8 -8
  124. package/dist/{render-RXMA4QYX.js → render-2HZ6WDVA.js} +18 -18
  125. package/dist/{render-LZEOB6JN.js → render-AO5VX3YI.js} +4 -4
  126. package/dist/{render-TDSGRTQQ.js → render-JJVVEVIZ.js} +27 -27
  127. package/dist/{render-batch-ZJQ5VHY6.js → render-batch-YH7CTWNY.js} +4 -4
  128. package/dist/{renderCancellation-MS5MAATT.js → renderCancellation-JPIHE47X.js} +7 -7
  129. package/dist/renderSetupWorker.js +1 -1
  130. package/dist/{resolver-WODAPAQC.js → resolver-IZ647GBZ.js} +5 -5
  131. package/dist/{sherpa-B3IHJHTK.js → sherpa-KKLNW6U2.js} +8 -8
  132. package/dist/{skills-56DFZVPS.js → skills-O7QZLKAG.js} +12 -12
  133. package/dist/{skillsUpdateCheck-AXKUBY44.js → skillsUpdateCheck-W563PHIX.js} +3 -3
  134. package/dist/{snapshot-NYQJL43J.js → snapshot-4M37T4WP.js} +34 -34
  135. package/dist/{src-UQ72QBPU.js → src-6YQBJGWR.js} +12 -13
  136. package/dist/{src-4K2RSSO5.js → src-PVYUYV3M.js} +6 -6
  137. package/dist/{staticProjectServer-OJH6TFA3.js → staticProjectServer-7EU666GS.js} +16 -16
  138. package/dist/{status-MZT3S6U2.js → status-YM52BQ6S.js} +7 -7
  139. package/dist/studio/assets/{hyperframes-player-uqzDaxVL.js → hyperframes-player-DfEcBl9r.js} +1 -1
  140. package/dist/studio/assets/{index-DXSYlqmV.js → index-9ZaZFCMZ.js} +1 -1
  141. package/dist/studio/assets/{index-CLBNYlDY.js → index-Bmy-KVib.js} +1 -1
  142. package/dist/studio/assets/{index-COhbL1xq.js → index-C9YkEyN4.js} +189 -189
  143. package/dist/studio/{chunk-3F47EFCT.js → chunk-7UQWVN52.js} +17 -10
  144. package/dist/studio/chunk-7UQWVN52.js.map +1 -0
  145. package/dist/studio/{chunk-246VB2G3.js → chunk-DRVWEPO5.js} +35 -7
  146. package/dist/studio/chunk-DRVWEPO5.js.map +1 -0
  147. package/dist/studio/{chunk-5EKWJZLM.js → chunk-TDWGXBUT.js} +1 -1
  148. package/dist/studio/chunk-TDWGXBUT.js.map +1 -0
  149. package/dist/studio/{domEditingLayers-OL7GLSS4.js → domEditingLayers-IEVLO54Z.js} +3 -3
  150. package/dist/studio/index.d.ts +8 -9
  151. package/dist/studio/index.html +1 -1
  152. package/dist/studio/index.js +1396 -917
  153. package/dist/studio/index.js.map +1 -1
  154. package/dist/studio/player.js +2 -2
  155. package/dist/{studio-api-IT5SYLXJ.js → studio-api-PNQZRPX5.js} +10 -10
  156. package/dist/{studioServer-KHYH2K3Q.js → studioServer-PTUEDJ4R.js} +56 -50
  157. package/dist/{system-4KER4Y62.js → system-EZYZNUFD.js} +7 -7
  158. package/dist/{telemetry-G3NYQGWI.js → telemetry-DTSHY4NX.js} +10 -10
  159. package/dist/{timeline-CXK4RVZE.js → timeline-OQEMNGIW.js} +20 -20
  160. package/dist/{tokens-RLU7WBIC.js → tokens-IGPEYHDJ.js} +2 -2
  161. package/dist/{transcribe-SOY2USBA.js → transcribe-BNSJRR4M.js} +8 -8
  162. package/dist/{transcribe-Y37DWCAV.js → transcribe-LC5JLRDF.js} +13 -13
  163. package/dist/{tts-CGUXR7R4.js → tts-P3LIPIL5.js} +1 -1
  164. package/dist/{updateCheck-EJ5SAGDC.js → updateCheck-OJAVDMMV.js} +2 -2
  165. package/dist/{upgrade-MBWWBNGK.js → upgrade-2G4MARM4.js} +2 -2
  166. package/dist/{urlDownloader-ZJ2TZQ7C.js → urlDownloader-H6WRI2UE.js} +6 -6
  167. package/dist/{validate-4J3OCFET.js → validate-MOUGAHM2.js} +17 -17
  168. package/dist/{video-43437E6M.js → video-FGSGKRSV.js} +7 -7
  169. package/package.json +1 -1
  170. package/dist/chunk-4C656PVL.js +0 -1393
  171. package/dist/chunk-AQIS2UNW.js +0 -3578
  172. package/dist/fontCompression-ISNK7STS.js +0 -15
  173. package/dist/studio/chunk-246VB2G3.js.map +0 -1
  174. package/dist/studio/chunk-3F47EFCT.js.map +0 -1
  175. package/dist/studio/chunk-5EKWJZLM.js.map +0 -1
  176. package/dist/studio/{domEditingLayers-OL7GLSS4.js.map → domEditingLayers-IEVLO54Z.js.map} +0 -0
  177. 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-RMHUQGRK.js";
25
25
  import {
26
26
  atomicTempPath,
27
27
  createFileAtomically,
@@ -34,7 +34,7 @@ import {
34
34
  measureAudio,
35
35
  requiredFfmpeg,
36
36
  resolveLocalAudioPath
37
- } from "./chunk-BE6X3G5C.js";
37
+ } from "./chunk-QC4FJVLM.js";
38
38
  import {
39
39
  PROXY_PARAMS_VERSION,
40
40
  PROXY_PENDING_RETRY_AFTER_SECONDS,
@@ -60,11 +60,11 @@ import {
60
60
  shouldPrewarmProxy,
61
61
  waitForProxy,
62
62
  walkDir
63
- } from "./chunk-PZSNUSBM.js";
63
+ } from "./chunk-TCLGPL65.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-2YN64IN5.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-Z6B37SNM.js";
96
96
  import {
97
97
  RUNTIME_BOOTSTRAP_ATTR,
98
98
  findStartTags,
@@ -104,7 +104,7 @@ import {
104
104
  resolveRateSpec,
105
105
  sourceTimeAt,
106
106
  stripEmbeddedRuntimeScripts
107
- } from "./chunk-AQIS2UNW.js";
107
+ } from "./chunk-HWKCIWQT.js";
108
108
  import {
109
109
  ProjectRootMissingError,
110
110
  folderGone,
@@ -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-36F5I56K.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 {
@@ -906,13 +906,16 @@ function saveRecord(file, log, record) {
906
906
  closeSync2(fd);
907
907
  }
908
908
  }
909
+ function baselineRecord(log) {
910
+ return {
911
+ type: "baseline",
912
+ files: Object.fromEntries(log.baseline),
913
+ ...log.keepsLedger && { keepsLedger: true }
914
+ };
915
+ }
909
916
  function writeLog(file, log) {
910
917
  const records = [
911
- {
912
- type: "baseline",
913
- files: Object.fromEntries(log.baseline),
914
- ...log.keepsLedger && { keepsLedger: true }
915
- },
918
+ baselineRecord(log),
916
919
  ...log.entries.map((entry) => ({ type: "entry", entry })),
917
920
  ...[...log.pins].map((id) => ({ type: "pin", id, pinned: true }))
918
921
  ];
@@ -1007,6 +1010,7 @@ function withoutHiddenPaths(log) {
1007
1010
  return log;
1008
1011
  }
1009
1012
  var historyFiles = (dir) => listProjectFiles(dir).filter((file) => isHistoryPath(file.path));
1013
+ var COPY_LATER_ABOVE_BYTES = 1024 ** 2;
1010
1014
  var sameWho = (a, b) => a.kind === b.kind && a.name === b.name;
1011
1015
  function splitAt(change, at, kept) {
1012
1016
  if (at === change.after) return [change, null];
@@ -1088,6 +1092,7 @@ var Engine = class {
1088
1092
  outside = null;
1089
1093
  /** A coalescing claim, open until another key, its idle timer, an operation, a window, or another write. */
1090
1094
  claimed = null;
1095
+ adopting = /* @__PURE__ */ new Map();
1091
1096
  /** Per path and hash an API write left, the hash of the bytes it replaced, until walked or written past. */
1092
1097
  overwritten = /* @__PURE__ */ new Map();
1093
1098
  stopHearing;
@@ -1158,6 +1163,9 @@ var Engine = class {
1158
1163
  const cached = cache.get(path);
1159
1164
  this.tracked.set(path, { hash, stat: cached?.hash === hash ? cached.stat : "" });
1160
1165
  }
1166
+ const left = this.readAdopting();
1167
+ const unadopted = (file) => left.has(file.path) && !this.tracked.has(file.path);
1168
+ this.adoptMediaInBackground(historyFiles(this.dir).filter(unadopted), this.now());
1161
1169
  this.reopenClosedWindow();
1162
1170
  await this.settleAll();
1163
1171
  }
@@ -1210,7 +1218,8 @@ var Engine = class {
1210
1218
  }
1211
1219
  async firstOpen() {
1212
1220
  const sweptAt = this.now();
1213
- for (const file of historyFiles(this.dir)) {
1221
+ const files = historyFiles(this.dir);
1222
+ for (const file of files.filter((file2) => file2.size <= COPY_LATER_ABOVE_BYTES)) {
1214
1223
  const hash = await this.storeIfPresent(file.path);
1215
1224
  if (this.whereFolder() !== "here") throw this.replaced();
1216
1225
  if (hash !== null) this.tracked.set(file.path, { hash, stat: statKey(file, sweptAt) });
@@ -1219,6 +1228,50 @@ var Engine = class {
1219
1228
  this.log.keepsLedger = true;
1220
1229
  this.persistLog();
1221
1230
  this.saveStatCache();
1231
+ this.adoptMediaInBackground(
1232
+ files.filter((file) => file.size > COPY_LATER_ABOVE_BYTES),
1233
+ sweptAt
1234
+ );
1235
+ }
1236
+ adoptMediaInBackground(files, sweptAt) {
1237
+ let copied = Promise.resolve();
1238
+ for (const file of files) {
1239
+ copied = copied.then(() => this.adopt(file, sweptAt));
1240
+ this.adopting.set(file.path, copied);
1241
+ }
1242
+ this.saveAdopting();
1243
+ }
1244
+ saveAdopting() {
1245
+ const file = join5(this.home, "adopting.json");
1246
+ if (!this.adopting.size) return rmSync2(file, { force: true });
1247
+ mkdirSync4(this.home, { recursive: true });
1248
+ replaceFileAtomically(file, JSON.stringify([...this.adopting.keys()]), 420);
1249
+ }
1250
+ async adopt(file, sweptAt) {
1251
+ try {
1252
+ if (this.whereFolder() !== "here") return;
1253
+ const stored = await this.storeIfPresent(file.path);
1254
+ await this.queue(async () => {
1255
+ await this.recordAdopted(file, sweptAt, stored);
1256
+ this.adopting.delete(file.path);
1257
+ this.saveAdopting();
1258
+ });
1259
+ } catch (error) {
1260
+ if (!(error instanceof HistoryClosedError)) this.options.onError?.(error);
1261
+ }
1262
+ }
1263
+ async recordAdopted(file, sweptAt, stored) {
1264
+ if (stored === null || this.whereFolder() !== "here") return;
1265
+ const hash = this.blobs.has(stored) ? stored : await this.storeIfPresent(file.path);
1266
+ if (hash === null) return;
1267
+ const change = { path: file.path, before: null, after: hash };
1268
+ const found = this.overwrittenBy(change, void 0, /* @__PURE__ */ new Set());
1269
+ const start = found && this.blobs.has(found) ? found : hash;
1270
+ this.tracked.set(file.path, { hash, stat: statKey(file, sweptAt) });
1271
+ this.log.baseline.set(file.path, start);
1272
+ if (start !== hash) addChange(this.outsideGroup(), file.path, start, hash);
1273
+ this.persistLog(baselineRecord(this.log));
1274
+ this.saveStatCache();
1222
1275
  }
1223
1276
  manifest() {
1224
1277
  return new Map([...this.tracked].map(([path, file]) => [path, file.hash]));
@@ -1231,6 +1284,15 @@ var Engine = class {
1231
1284
  return /* @__PURE__ */ new Map();
1232
1285
  }
1233
1286
  }
1287
+ readAdopting() {
1288
+ try {
1289
+ return new Set(
1290
+ JSON.parse(readFileSync6(join5(this.home, "adopting.json"), "utf-8"))
1291
+ );
1292
+ } catch {
1293
+ return /* @__PURE__ */ new Set();
1294
+ }
1295
+ }
1234
1296
  saveStatCache() {
1235
1297
  const files = JSON.stringify(Object.fromEntries(this.tracked));
1236
1298
  mkdirSync4(this.home, { recursive: true });
@@ -1244,7 +1306,7 @@ var Engine = class {
1244
1306
  if (this.whereFolder() !== "here") return;
1245
1307
  const sweptAt = this.now();
1246
1308
  const changedAt = (file) => Math.min(sweptAt, Math.max(file.mtimeMs, file.ctimeMs));
1247
- const seen = historyFiles(this.dir);
1309
+ const seen = historyFiles(this.dir).filter((file) => !this.adopting.has(file.path));
1248
1310
  const heard = new Map(this.overwritten);
1249
1311
  const present = new Set(seen.map((file) => file.path));
1250
1312
  const removed = [...this.tracked.keys()].filter((path) => !present.has(path)).map((path) => {
@@ -1405,6 +1467,7 @@ var Engine = class {
1405
1467
  clearTimeout(this.claimed?.timer);
1406
1468
  const timer = Number.isFinite(idleMs) ? setTimeout(() => this.background(() => this.commitClaim()), idleMs) : void 0;
1407
1469
  timer?.unref?.();
1470
+ group.lastWriteAt = this.now();
1408
1471
  this.claimed = { group, key, timer };
1409
1472
  return group.changes.size ? { id: group.id } : null;
1410
1473
  }
@@ -1707,7 +1770,10 @@ var Engine = class {
1707
1770
  return {
1708
1771
  projectId: this.projectId,
1709
1772
  beginWindow: (who, label, options = {}) => this.beginWindow(who, label, options.idleMs ?? this.options.maxGroupMs ?? 3e4),
1710
- claim: (who, label, paths, options = {}) => this.queue(() => this.claimNow(who, label, paths, options)),
1773
+ claim: async (who, label, paths, options = {}) => {
1774
+ await Promise.all(paths.map((path) => this.adopting.get(this.logPath(path))));
1775
+ return this.queue(() => this.claimNow(who, label, paths, options));
1776
+ },
1711
1777
  noteChange: (path) => {
1712
1778
  if (!this.closed) this.noteChange(path);
1713
1779
  },
@@ -1773,6 +1839,7 @@ var Engine = class {
1773
1839
  flush: () => this.queue(() => this.settleAll()),
1774
1840
  replacedAtPath: () => this.whereFolder() === "replaced",
1775
1841
  close: () => this.closing ??= (async () => {
1842
+ await Promise.all(this.adopting.values());
1776
1843
  if (this.notedTimer) clearTimeout(this.notedTimer);
1777
1844
  this.stopHearing?.();
1778
1845
  const settled = this.queue(() => this.settleAll());
@@ -2213,6 +2280,7 @@ function classifyPropertyGroup(prop) {
2213
2280
  }
2214
2281
 
2215
2282
  // ../parsers/dist/gsapWriterAcorn.js
2283
+ var GSAP_DEFAULT_DURATION = 0.5;
2216
2284
  var BUILTIN_VAR_KEYS = /* @__PURE__ */ new Set(["duration", "ease", "delay"]);
2217
2285
  var DROPPED_VAR_KEYS = /* @__PURE__ */ new Set([
2218
2286
  "onComplete",
@@ -2271,22 +2339,23 @@ function positionHoldForAnimation(animation, animations) {
2271
2339
  if (!animation.keyframes) return null;
2272
2340
  const start = knownStart(animation) ?? 0;
2273
2341
  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;
2342
+ const atStart = animation.keyframes.keyframes.find((keyframe) => keyframe.percentage === 0);
2343
+ if (!atStart) return null;
2278
2344
  const earlier = animations.filter((other) => {
2279
2345
  const otherStart = knownStart(other);
2280
2346
  return other !== animation && !other.global && other.targetSelector === animation.targetSelector && otherStart !== void 0 && otherStart < start - 1e-3;
2281
2347
  });
2282
2348
  const position = {};
2283
- for (const [property, value] of Object.entries(first.properties)) {
2349
+ for (const [property, value] of Object.entries(atStart.properties)) {
2284
2350
  if (classifyPropertyGroup2(property) !== "position" || typeof value !== "number") continue;
2285
2351
  if (earlier.some((other) => writesProperty(other, property))) continue;
2286
2352
  position[property] = value;
2287
2353
  }
2288
2354
  return Object.keys(position).length > 0 ? position : null;
2289
2355
  }
2356
+ function authorsKeyframes(anim) {
2357
+ return anim.keyframes !== void 0 || anim.hasUnresolvedKeyframes === true;
2358
+ }
2290
2359
  function mergePercentageKeyframes(keyframes) {
2291
2360
  const byPercentage = /* @__PURE__ */ new Map();
2292
2361
  for (const keyframe of keyframes) {
@@ -2430,34 +2499,27 @@ function readProvenance(node) {
2430
2499
  var roundPercentage = (percentage) => Math.round(percentage * 10) / 10;
2431
2500
  var OBJECT_ARRAY_PERCENTAGE_TOLERANCE = 2;
2432
2501
  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
- };
2502
+ const steps = durations.map((duration) => duration ?? GSAP_DEFAULT_DURATION);
2503
+ if (!steps.every(
2504
+ (duration) => typeof duration === "number" && Number.isFinite(duration) && duration > 0
2505
+ )) {
2506
+ return null;
2449
2507
  }
2450
- const lastIndex = durations.length - 1;
2508
+ const totalDuration = steps.reduce((sum, duration) => sum + duration, 0);
2509
+ let cumulative = 0;
2451
2510
  return {
2452
- percentages: durations.map(
2453
- (_, index) => lastIndex > 0 ? roundPercentage(index / lastIndex * 100) : 0
2454
- )
2511
+ percentages: steps.map((duration) => {
2512
+ cumulative += duration;
2513
+ return roundPercentage(cumulative / totalDuration * 100);
2514
+ }),
2515
+ totalDuration
2455
2516
  };
2456
2517
  }
2457
2518
  function getCompatibleObjectArrayKeyframeTiming(durations, outerDuration) {
2458
2519
  const timing = getObjectArrayKeyframeTiming(durations);
2459
2520
  if (!timing) return null;
2460
- if (timing.totalDuration === void 0 || outerDuration === void 0) return timing;
2521
+ const stepsAuthorDuration = durations.some((duration) => duration !== void 0);
2522
+ if (!stepsAuthorDuration || outerDuration === void 0) return timing;
2461
2523
  if (typeof outerDuration === "number" && Math.abs(outerDuration - timing.totalDuration) <= Number.EPSILON) {
2462
2524
  return timing;
2463
2525
  }
@@ -3051,6 +3113,7 @@ function parsePercentageKeyframes(node, scope, source) {
3051
3113
  if (typeof key !== "string") continue;
3052
3114
  const pctMatch = PERCENTAGE_KEY_RE.exec(key);
3053
3115
  if (pctMatch) {
3116
+ if (!isPlainStep(prop.value)) return void 0;
3054
3117
  const percentage = Number.parseFloat(pctMatch[1] ?? "0");
3055
3118
  const record = objectExpressionToRecord(prop.value, scope, source);
3056
3119
  const properties = {};
@@ -3069,6 +3132,8 @@ function parsePercentageKeyframes(node, scope, source) {
3069
3132
  ease = tryResolveStringProp(prop.value, scope, source) ?? ease;
3070
3133
  } else if (key === "easeEach") {
3071
3134
  easeEach = tryResolveStringProp(prop.value, scope, source) ?? easeEach;
3135
+ } else {
3136
+ return void 0;
3072
3137
  }
3073
3138
  }
3074
3139
  keyframes.sort((a, b) => a.percentage - b.percentage);
@@ -3092,12 +3157,19 @@ function computeKeyframesTotalDuration(varsNode, scope, source) {
3092
3157
  }
3093
3158
  return getObjectArrayKeyframeTiming(durations)?.totalDuration;
3094
3159
  }
3095
- var isFullyReadableStep = (el) => el?.type === "ObjectExpression" && !el.properties.some((p) => p.type === "SpreadElement");
3160
+ function staticKeyName(prop) {
3161
+ if (prop.type !== "ObjectProperty" && prop.type !== "Property") return void 0;
3162
+ if (prop.method || prop.kind && prop.kind !== "init") return void 0;
3163
+ const key = prop.computed ? prop.key?.type === "Literal" && prop.key.value : prop.key?.name ?? prop.key?.value;
3164
+ return typeof key === "string" ? key : void 0;
3165
+ }
3166
+ var isPlainObject = (node) => node?.type === "ObjectExpression" && (node.properties ?? []).every((p) => staticKeyName(p) !== void 0);
3167
+ var isPlainStep = (node) => node?.type === "Literal" || isPlainObject(node);
3096
3168
  function parseObjectArrayKeyframes(node, scope, source) {
3097
3169
  const elements = node.elements ?? [];
3098
3170
  const raw = [];
3099
3171
  for (const el of elements) {
3100
- if (!isFullyReadableStep(el)) return void 0;
3172
+ if (!isPlainObject(el)) return void 0;
3101
3173
  const record = objectExpressionToRecord(el, scope, source);
3102
3174
  const properties = {};
3103
3175
  let duration;
@@ -3136,9 +3208,8 @@ function parseSimpleArrayKeyframes(node, scope) {
3136
3208
  const values = [];
3137
3209
  for (const el of prop.value.elements ?? []) {
3138
3210
  const val = resolveNode(el, scope);
3139
- if (typeof val === "number" || typeof val === "string") {
3140
- values.push(val);
3141
- }
3211
+ if (typeof val !== "number" && typeof val !== "string") return void 0;
3212
+ values.push(val);
3142
3213
  }
3143
3214
  if (values.length > 0) arrayProps.set(key, values);
3144
3215
  } else if (key === "ease") {
@@ -3171,6 +3242,7 @@ function parseKeyframesNode(node, scope, source) {
3171
3242
  }
3172
3243
  if (node.type !== "ObjectExpression") return void 0;
3173
3244
  const props = node.properties ?? [];
3245
+ if (!props.every((p) => staticKeyName(p) !== void 0)) return void 0;
3174
3246
  let hasPercentageKey = false;
3175
3247
  let hasArrayValue = false;
3176
3248
  for (const prop of props) {
@@ -3271,7 +3343,7 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
3271
3343
  percentage: waypoints.length > 1 ? Math.round(i / (waypoints.length - 1) * 100) : 0,
3272
3344
  properties: { x: wp.x, y: wp.y }
3273
3345
  }));
3274
- keyframesData = { format: "percentage", keyframes: kf };
3346
+ keyframesData = { format: "percentage", keyframes: kf, fromMotionPath: true };
3275
3347
  } else {
3276
3348
  const kfs = keyframesData.keyframes;
3277
3349
  if (kfs.length === waypoints.length) {
@@ -3301,10 +3373,10 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
3301
3373
  const position = typeof posVal === "number" ? posVal : typeof posVal === "string" ? posVal : hasPositionArg ? `__raw:${source.slice(call.positionArg.start, call.positionArg.end)}` : 0;
3302
3374
  let duration = typeof vars.duration === "number" ? vars.duration : void 0;
3303
3375
  const ease = typeof vars.ease === "string" ? vars.ease : void 0;
3304
- if (duration === void 0 && keyframesData) {
3376
+ const durationUnresolved = call.method !== "set" && duration === void 0 && hasUnknownDuration(call.varsArg, scope);
3377
+ if (duration === void 0 && keyframesData && !durationUnresolved) {
3305
3378
  duration = computeKeyframesTotalDuration(call.varsArg, scope, source);
3306
3379
  }
3307
- const durationUnresolved = call.method !== "set" && duration === void 0 && hasUnknownDuration(call.varsArg, scope);
3308
3380
  let selector = call.selector;
3309
3381
  let targetIdentity;
3310
3382
  if (selector === "__unresolved__") {
@@ -3358,7 +3430,6 @@ function tweenCallToAnimation(call, scope, source, identifierBindings) {
3358
3430
  if (provenance) anim.provenance = provenance;
3359
3431
  return anim;
3360
3432
  }
3361
- var GSAP_DEFAULT_DURATION = 0.5;
3362
3433
  function resolvePositionString(pos, cursor, prevStart) {
3363
3434
  const trimmed = pos.trim();
3364
3435
  if (trimmed === "") return cursor;
@@ -3391,7 +3462,7 @@ function applyTimelineDefaults(anims, defaults) {
3391
3462
  if (defaults.duration !== void 0) anim.duration = defaults.duration;
3392
3463
  else if (defaults.durationUnresolved) anim.durationUnresolved = true;
3393
3464
  }
3394
- if (anim.ease === void 0 && defaults.ease !== void 0 && !anim.keyframes) {
3465
+ if (anim.ease === void 0 && defaults.ease !== void 0 && (!anim.keyframes || anim.keyframes.fromMotionPath)) {
3395
3466
  anim.ease = defaults.ease;
3396
3467
  }
3397
3468
  }
@@ -3555,14 +3626,25 @@ function parseGsapScriptAcornForWrite(script) {
3555
3626
  return null;
3556
3627
  }
3557
3628
  }
3558
- function clipTweenMatcher(clipSelectors, root) {
3629
+ function clipTweenMatcher(clipSelectors, root, queries = /* @__PURE__ */ new Map()) {
3559
3630
  const own = typeof clipSelectors === "string" ? [clipSelectors] : clipSelectors;
3560
- const clips = root ? own.flatMap((selector) => queryAll(root, selector)) : [];
3631
+ if (!root)
3632
+ return ({ targetSelector, hasPartialSelector }) => !hasPartialSelector && own.includes(targetSelector);
3633
+ const queryAll = (selector) => {
3634
+ if (ID_SELECTOR.test(selector)) {
3635
+ if (!queries.has(ALL_IDS)) indexIds(root, queries);
3636
+ return queries.get(selector) ?? [];
3637
+ }
3638
+ let found = queries.get(selector);
3639
+ if (!found) queries.set(selector, found = queryRoot(root, selector));
3640
+ return found;
3641
+ };
3642
+ const clips = own.flatMap((selector) => queryAll(selector));
3561
3643
  return ({ targetSelector, hasPartialSelector }) => {
3562
3644
  if (hasPartialSelector) return false;
3563
3645
  if (own.includes(targetSelector)) return true;
3564
- if (!root || clips.length === 0) return false;
3565
- const targets = queryAll(root, targetSelector);
3646
+ if (clips.length === 0) return false;
3647
+ const targets = queryAll(targetSelector);
3566
3648
  return targets.length > 0 && targets.every((target) => {
3567
3649
  const owner = target.closest("[data-start]");
3568
3650
  return clips.includes(target) || owner !== null && clips.includes(owner);
@@ -3575,7 +3657,20 @@ function clipQueryRoot(script) {
3575
3657
  function hasExplicitTime(animation) {
3576
3658
  return typeof animation.position === "number" && !animation.implicitPosition;
3577
3659
  }
3578
- function queryAll(root, selector) {
3660
+ var ID_SELECTOR = /^#-?[A-Za-z_][\w-]*$/;
3661
+ var ALL_IDS = "[id]";
3662
+ function indexIds(root, queries) {
3663
+ const all = queryRoot(root, ALL_IDS);
3664
+ queries.set(ALL_IDS, all);
3665
+ for (const el of all) {
3666
+ const key = `#${el.id}`;
3667
+ if (!ID_SELECTOR.test(key)) continue;
3668
+ const list = queries.get(key);
3669
+ if (list) list.push(el);
3670
+ else queries.set(key, [el]);
3671
+ }
3672
+ }
3673
+ function queryRoot(root, selector) {
3579
3674
  try {
3580
3675
  return Array.from(root.querySelectorAll(selector));
3581
3676
  } catch {
@@ -3742,7 +3837,7 @@ function updateAnimationInScript(script, animationId, updates) {
3742
3837
  const parsed = parseGsapScriptAcornForWrite(script);
3743
3838
  if (!parsed) return script;
3744
3839
  const target = parsed.located.find((l) => l.id === animationId);
3745
- if (!target) return script;
3840
+ if (!target || updates.properties && target.animation.hasUnresolvedKeyframes) return script;
3746
3841
  const ms = new MagicString(script);
3747
3842
  const { call } = target;
3748
3843
  if (updates.properties) {
@@ -3805,47 +3900,56 @@ function overwritePosition(ms, call, position) {
3805
3900
  ms.appendLeft(last ? last.end : call.node.end - 1, `, ${valueToCode(position)}`);
3806
3901
  }
3807
3902
  }
3808
- function shiftPositionsInScript(script, targetSelector, delta, root) {
3809
- const parsed = parseGsapScriptAcornForWrite(script);
3810
- if (!parsed) return script;
3811
- const carries = clipTweenMatcher(targetSelector, root);
3903
+ var isLiveRetime = (r) => r.kind === "shift" || r.oldDuration > 0 && r.newDuration > 0;
3904
+ function applyRetime(animation, retime) {
3905
+ if (retime.kind === "shift") {
3906
+ if (!hasExplicitTime(animation)) return { position: false, duration: false };
3907
+ animation.position = shiftedPosition(animation.position, retime.delta);
3908
+ return { position: true, duration: false };
3909
+ }
3910
+ const touched = { position: false, duration: false };
3911
+ if (!isLiveRetime(retime) || typeof animation.position !== "number") return touched;
3912
+ const ratio = retime.newDuration / retime.oldDuration;
3913
+ if (hasExplicitTime(animation)) {
3914
+ const scaled = retime.newStart + (animation.position - retime.oldStart) * ratio;
3915
+ animation.position = Math.max(0, Math.round(scaled * 1e3) / 1e3);
3916
+ touched.position = true;
3917
+ }
3918
+ if (typeof animation.duration === "number" && animation.duration > 0) {
3919
+ animation.duration = Math.max(1e-3, Math.round(animation.duration * ratio * 1e3) / 1e3);
3920
+ touched.duration = true;
3921
+ }
3922
+ return touched;
3923
+ }
3924
+ function retimeClipTweensInScript(script, retimes, root) {
3925
+ const changed = retimes.map(() => false);
3926
+ const parsed = retimes.some(isLiveRetime) ? parseGsapScriptAcornForWrite(script) : null;
3927
+ if (!parsed) return { script, changed };
3928
+ const queries = /* @__PURE__ */ new Map();
3929
+ const matchers = retimes.map((r) => clipTweenMatcher(r.targetSelector, root, queries));
3812
3930
  const ms = new MagicString(script);
3813
- let changed = false;
3931
+ let wrote = false;
3814
3932
  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;
3933
+ const animation = { ...entry.animation };
3934
+ let position = false;
3935
+ let duration = false;
3936
+ retimes.forEach((retime, i) => {
3937
+ if (!matchers[i](animation)) return;
3938
+ const before = [animation.position, animation.duration];
3939
+ const touched = applyRetime(animation, retime);
3940
+ position ||= touched.position;
3941
+ duration ||= touched.duration;
3942
+ if (before[0] !== animation.position || before[1] !== animation.duration) changed[i] = true;
3943
+ });
3944
+ if (position) overwritePosition(ms, entry.call, animation.position);
3945
+ if (duration) upsertProp(ms, entry.call.varsArg, "duration", animation.duration);
3946
+ wrote ||= position || duration;
3818
3947
  }
3819
- return changed ? ms.toString() : script;
3948
+ return { script: wrote ? ms.toString() : script, changed };
3820
3949
  }
3821
3950
  function shiftedPosition(position, delta) {
3822
3951
  return Math.max(0, Math.round((position + delta) * 1e3) / 1e3);
3823
3952
  }
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
3953
  function addAnimationToScript(script, animation) {
3850
3954
  const parsed = parseGsapScriptAcornForWrite(script);
3851
3955
  if (!parsed) return { script, id: "" };
@@ -4118,7 +4222,7 @@ function updateKeyframeInScript(script, animationId, percentage, properties, eas
4118
4222
  const parsed = parseGsapScriptAcornForWrite(script);
4119
4223
  if (!parsed) return script;
4120
4224
  const target = parsed.located.find((l) => l.id === animationId);
4121
- if (!target) return script;
4225
+ if (!target || target.animation.hasUnresolvedKeyframes) return script;
4122
4226
  const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
4123
4227
  if (!kfPropNode) {
4124
4228
  return updateMotionPathKeyframe(script, target, percentage, properties, ease) ?? script;
@@ -4186,7 +4290,7 @@ function locateWithKeyframes(script, animationId) {
4186
4290
  if (!parsed) return null;
4187
4291
  const convertedId = animationId.replace(/-from-|-fromTo-/, "-to-");
4188
4292
  const target = parsed.located.find((l) => l.id === animationId) ?? parsed.located.find((l) => l.id === convertedId);
4189
- if (!target) return null;
4293
+ if (!target || target.animation.hasUnresolvedKeyframes) return null;
4190
4294
  const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
4191
4295
  if (!kfPropNode || kfPropNode.value?.type !== "ObjectExpression") return null;
4192
4296
  return { script, parsed, target, kfNode: kfPropNode.value };
@@ -4210,8 +4314,12 @@ function convertArrayKeyframesToObject(script, target) {
4210
4314
  return `${JSON.stringify(`${timing.percentages[i]}%`)}: ${recordToCode(record)}`;
4211
4315
  });
4212
4316
  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) {
4317
+ ms.overwrite(
4318
+ kfPropNode.value.start,
4319
+ kfPropNode.value.end,
4320
+ `{ ${entries.join(", ")}, easeEach: "none" }`
4321
+ );
4322
+ if (findPropertyNode2(target.call.varsArg, "duration") === void 0) {
4215
4323
  upsertProp(ms, target.call.varsArg, "duration", timing.totalDuration);
4216
4324
  }
4217
4325
  return ms.toString();
@@ -4221,7 +4329,7 @@ function ensureKeyframesNode(script, animationId) {
4221
4329
  if (direct) return direct;
4222
4330
  const parsed = parseGsapScriptAcornForWrite(script);
4223
4331
  const target = parsed?.located.find((l) => l.id === animationId);
4224
- if (!target) return null;
4332
+ if (!target || target.animation.hasUnresolvedKeyframes) return null;
4225
4333
  const kfProp = findPropertyNode2(target.call.varsArg, "keyframes");
4226
4334
  if (kfProp?.value?.type === "ArrayExpression") {
4227
4335
  const normalized = convertArrayKeyframesToObject(script, target);
@@ -4323,7 +4431,7 @@ function removeKeyframeFromScript(script, animationId, percentage) {
4323
4431
  const parsed = parseGsapScriptAcornForWrite(script);
4324
4432
  if (!parsed) return script;
4325
4433
  const target = parsed.located.find((l) => l.id === animationId);
4326
- if (!target) return script;
4434
+ if (!target || target.animation.hasUnresolvedKeyframes) return script;
4327
4435
  const kfPropNode = findPropertyNode2(target.call.varsArg, "keyframes");
4328
4436
  if (!kfPropNode) return script;
4329
4437
  if (kfPropNode.value?.type === "ArrayExpression") {
@@ -4447,7 +4555,7 @@ function convertToKeyframesFromScript(script, animationId, resolvedFromValues, s
4447
4555
  const target = parsed.located.find((l) => l.id === animationId);
4448
4556
  if (!target) return script;
4449
4557
  const { animation, call } = target;
4450
- if (animation.keyframes) return script;
4558
+ if (authorsKeyframes(animation)) return script;
4451
4559
  const isSet = call.method === "set";
4452
4560
  const { fromProps, toProps } = resolveConversionProps(animation, resolvedFromValues);
4453
4561
  const ms = new MagicString(script);
@@ -4663,6 +4771,7 @@ function splitIntoPropertyGroupsFromScript(script, animationId) {
4663
4771
  const target = parsed.located.find((l) => l.id === animationId);
4664
4772
  if (!target) return { script, ids: [animationId] };
4665
4773
  const { animation } = target;
4774
+ if (animation.hasUnresolvedKeyframes) return { script, ids: [animationId] };
4666
4775
  const allPropKeys = collectPropertyKeys(animation);
4667
4776
  const groupProps = partitionPropertyGroups(allPropKeys);
4668
4777
  if (groupProps.size <= 1) return { script, ids: [animationId] };
@@ -4937,8 +5046,8 @@ function computeForwardBaselines(matching, splitTime) {
4937
5046
  const pos = typeof anim.position === "number" ? anim.position : 0;
4938
5047
  const dur = anim.duration ?? 0;
4939
5048
  const animEnd = pos + dur;
4940
- if (anim.keyframes) {
4941
- const kfs = anim.keyframes.keyframes;
5049
+ if (authorsKeyframes(anim)) {
5050
+ const kfs = anim.keyframes?.keyframes ?? [];
4942
5051
  if (pos >= splitTime) {
4943
5052
  } else if (animEnd > splitTime) {
4944
5053
  for (const kf of kfs) {
@@ -4999,17 +5108,22 @@ function buildSpanningSplit(result, anim, pos, dur, fromSource, ctx) {
4999
5108
  extras: anim.extras
5000
5109
  }).script;
5001
5110
  }
5111
+ function applyKeyframedTweenSplit(result, anim, pos, animEnd, ctx, skippedSelectors) {
5112
+ if (pos >= ctx.splitTime)
5113
+ return updateAnimationSelectorInScript(result, anim.id, ctx.newSelector);
5114
+ if (animEnd > ctx.splitTime) {
5115
+ skippedSelectors.push(`${ctx.originalSelector} (keyframes spanning split)`);
5116
+ } else if (anim.hasUnresolvedKeyframes) {
5117
+ skippedSelectors.push(`${ctx.originalSelector} (unreadable keyframes before split)`);
5118
+ }
5119
+ return result;
5120
+ }
5002
5121
  function applyTweenSplit(result, anim, baselineBefore, ctx, skippedSelectors) {
5003
5122
  const pos = typeof anim.position === "number" ? anim.position : 0;
5004
5123
  const dur = anim.duration ?? 0;
5005
5124
  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;
5125
+ if (authorsKeyframes(anim)) {
5126
+ return applyKeyframedTweenSplit(result, anim, pos, animEnd, ctx, skippedSelectors);
5013
5127
  }
5014
5128
  if (animEnd <= ctx.splitTime) return result;
5015
5129
  if (pos >= ctx.splitTime)
@@ -5956,7 +6070,7 @@ function requestSubPath(url, route) {
5956
6070
  return decodeURIComponent(segments.slice(start + routeSegments.length).join("/"));
5957
6071
  }
5958
6072
  async function loadGsapParser() {
5959
- return import("./gsapParser-LOSAMHNR.js");
6073
+ return import("./gsapParser-DIYYX6JT.js");
5960
6074
  }
5961
6075
  function isDanglingSymlinkInProject(projectDir, lexicalPath) {
5962
6076
  if (!isSafePath(projectDir, dirname32(lexicalPath))) return false;
@@ -6617,7 +6731,7 @@ async function prepareGsapMutationScript(c, res, firstMutation) {
6617
6731
  let block = extractGsapScriptBlock(html);
6618
6732
  if (!block && (firstMutation.type === "add" || firstMutation.type === "add-with-keyframes")) {
6619
6733
  const compId = html.match(/data-composition-id="([^"]+)"/)?.[1] ?? "main";
6620
- const { GSAP_CDN } = await import("./dist-IPEAV427.js");
6734
+ const { GSAP_CDN } = await import("./dist-S3PJNPXQ.js");
6621
6735
  const bootstrap = [
6622
6736
  `<script src="${GSAP_CDN}"></script>`,
6623
6737
  "<script>",
@@ -6649,6 +6763,38 @@ ${bootstrap}`;
6649
6763
  if (!block) return c.json({ error: "no GSAP script found in file" }, 400);
6650
6764
  return { html, beforeHtml, block };
6651
6765
  }
6766
+ function retimeRuns(mutations) {
6767
+ const runs = /* @__PURE__ */ new Map();
6768
+ let start = -1;
6769
+ mutations.forEach((mutation, index) => {
6770
+ const retime = clipRetimeOf(mutation);
6771
+ if (!retime) return void (start = -1);
6772
+ if (start < 0) runs.set(start = index, []);
6773
+ runs.get(start).push(retime);
6774
+ });
6775
+ return runs;
6776
+ }
6777
+ function clipRetimeOf(mutation) {
6778
+ if (mutation.type === "shift-positions") {
6779
+ const { targetSelector: targetSelector2, delta } = mutation;
6780
+ return targetSelector2 && Number.isFinite(delta) && delta !== 0 ? { kind: "shift", targetSelector: targetSelector2, delta } : "no-op";
6781
+ }
6782
+ if (mutation.type !== "scale-positions") return null;
6783
+ const { targetSelector, oldStart, oldDuration, newStart, newDuration } = mutation;
6784
+ const finite = [oldStart, oldDuration, newStart, newDuration].every(Number.isFinite);
6785
+ if (!targetSelector || !finite || oldDuration <= 0 || newDuration <= 0) return "no-op";
6786
+ if (oldStart === newStart && oldDuration === newDuration) return "no-op";
6787
+ return { kind: "scale", targetSelector, oldStart, oldDuration, newStart, newDuration };
6788
+ }
6789
+ function retimeRun(script, run, root) {
6790
+ const live = run.filter((slot) => slot !== "no-op");
6791
+ const retimed = retimeClipTweensInScript(script, live, root);
6792
+ const synced = syncPositionHoldsBeforeKeyframes(retimed.script);
6793
+ let next = 0;
6794
+ const changed = run.map((slot) => slot !== "no-op" && retimed.changed[next++]);
6795
+ if (synced !== retimed.script) changed[changed.length - 1] = true;
6796
+ return { script: synced, changed: synced === script ? changed.map(() => false) : changed };
6797
+ }
6652
6798
  async function applyGsapMutations(c, res, mutations) {
6653
6799
  const firstMutation = mutations[0];
6654
6800
  if (!firstMutation) return c.json({ error: "mutations array required" }, 400);
@@ -6667,7 +6813,17 @@ async function applyGsapMutations(c, res, mutations) {
6667
6813
  return c.json({ error: error instanceof Error ? error.message : String(error) }, 400);
6668
6814
  }
6669
6815
  const mutationChanges = [];
6670
- for (const mutation of mutations) {
6816
+ const retimes = writer === "acorn" ? retimeRuns(mutations) : /* @__PURE__ */ new Map();
6817
+ for (let index = 0; index < mutations.length; index++) {
6818
+ const run = retimes.get(index);
6819
+ if (run) {
6820
+ const retimed = retimeRun(block.scriptText, run, block.root);
6821
+ mutationChanges.push(...retimed.changed);
6822
+ block.scriptText = retimed.script;
6823
+ index += run.length - 1;
6824
+ continue;
6825
+ }
6826
+ const mutation = mutations[index];
6671
6827
  const previousScript = block.scriptText;
6672
6828
  const result = await executeGsapMutation(mutation, block, respond, writer);
6673
6829
  if (result instanceof Response) return result;
@@ -6979,33 +7135,14 @@ function executeGsapMutationAcorn(body, block, respond) {
6979
7135
  case "unroll-timeline": {
6980
7136
  return unrollComputedTimeline(block.scriptText);
6981
7137
  }
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
7138
  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;
7139
+ 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 }));
7140
+ return retimeClipTweensInScript(block.scriptText, shifts, block.root).script;
6994
7141
  }
7142
+ case "shift-positions":
6995
7143
  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
- );
7144
+ const retime = clipRetimeOf(body);
7145
+ return retime && retime !== "no-op" ? retimeClipTweensInScript(block.scriptText, [retime], block.root).script : block.scriptText;
7009
7146
  }
7010
7147
  default:
7011
7148
  return respond({ error: `unknown mutation type: ${body.type}` }, 400);
@@ -7304,15 +7441,15 @@ async function executeGsapMutationRecast(body, block, respond) {
7304
7441
  case "shift-positions": {
7305
7442
  const { targetSelector, delta } = body;
7306
7443
  if (!targetSelector || !Number.isFinite(delta) || delta === 0) return block.scriptText;
7307
- const { shiftPositionsInScript: shiftPositionsInScript2 } = parser;
7308
- return shiftPositionsInScript2(block.scriptText, targetSelector, delta, block.root);
7444
+ const { shiftPositionsInScript } = parser;
7445
+ return shiftPositionsInScript(block.scriptText, targetSelector, delta, block.root);
7309
7446
  }
7310
7447
  case "shift-positions-batch": {
7311
- const { shiftPositionsInScript: shiftPositionsInScript2 } = parser;
7448
+ const { shiftPositionsInScript } = parser;
7312
7449
  let script = block.scriptText;
7313
7450
  for (const s of body.shifts) {
7314
7451
  if (!s.targetSelector || !Number.isFinite(s.delta) || s.delta === 0) continue;
7315
- script = shiftPositionsInScript2(script, s.targetSelector, s.delta, block.root);
7452
+ script = shiftPositionsInScript(script, s.targetSelector, s.delta, block.root);
7316
7453
  }
7317
7454
  return script;
7318
7455
  }
@@ -7321,8 +7458,8 @@ async function executeGsapMutationRecast(body, block, respond) {
7321
7458
  if (!targetSelector || !Number.isFinite(oldStart) || !Number.isFinite(oldDuration) || !Number.isFinite(newStart) || !Number.isFinite(newDuration) || oldDuration <= 0 || newDuration <= 0)
7322
7459
  return block.scriptText;
7323
7460
  if (oldStart === newStart && oldDuration === newDuration) return block.scriptText;
7324
- const { scalePositionsInScript: scalePositionsInScript2 } = parser;
7325
- return scalePositionsInScript2(
7461
+ const { scalePositionsInScript } = parser;
7462
+ return scalePositionsInScript(
7326
7463
  block.scriptText,
7327
7464
  targetSelector,
7328
7465
  oldStart,
@@ -11059,6 +11196,12 @@ function createStudioApi(adapter) {
11059
11196
  const project = await Promise.resolve().then(() => adapter.resolveProject(c.req.param("id"))).catch(() => null);
11060
11197
  if (project) adapter.invalidateProjectSignature?.(project.dir);
11061
11198
  });
11199
+ api.use("/projects/:id/*", async function openHistorySoNoWriteBecomesItsBaseline(c, next) {
11200
+ if (c.req.method !== "GET" && c.req.method !== "HEAD" && adapter.history) {
11201
+ await Promise.resolve().then(() => adapter.resolveProject(c.req.param("id"))).then((project) => project && adapter.history?.(project)).catch(() => null);
11202
+ }
11203
+ await next();
11204
+ });
11062
11205
  registerProjectRoutes(api, adapter);
11063
11206
  registerFileRoutes(api, adapter);
11064
11207
  registerPreviewRoutes(api, adapter);