@hyperframes/studio 0.8.116 → 0.8.117

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 (38) hide show
  1. package/dist/assets/{hyperframes-player-mGYvPVpw.js → hyperframes-player-5fcgSstJ.js} +1 -1
  2. package/dist/assets/{index-DYNaXPVf.js → index-C5qKdpgl.js} +178 -176
  3. package/dist/assets/{index-BWHt0-ir.js → index-XJSawwYe.js} +1 -1
  4. package/dist/assets/{index-Dr3hNpvS.js → index-tg2LXUeu.js} +1 -1
  5. package/dist/index.d.ts +28 -19
  6. package/dist/index.html +1 -1
  7. package/dist/index.js +77 -64
  8. package/dist/index.js.map +1 -1
  9. package/package.json +8 -8
  10. package/src/components/editor/DomEditOverlay.tsx +1 -0
  11. package/src/components/editor/domEditOverlayGestures.ts +1 -0
  12. package/src/components/editor/domEditOverlayStartGesture.ts +2 -2
  13. package/src/components/editor/manualOffsetDrag.ts +3 -3
  14. package/src/components/editor/plainTranslate.ts +5 -3
  15. package/src/components/editor/propertyPanelHelpers.ts +2 -2
  16. package/src/components/editor/propertyPanelTransformCommit.ts +2 -2
  17. package/src/components/editor/rotationDraft.ts +2 -1
  18. package/src/components/editor/useDomEditOverlayGestures.ts +2 -2
  19. package/src/hooks/gsapRuntimeKeyframes.ts +16 -3
  20. package/src/hooks/gsapScriptCommitTypes.ts +1 -1
  21. package/src/hooks/plainRotation.ts +5 -1
  22. package/src/hooks/useDomEditPersist.test.tsx +335 -0
  23. package/src/hooks/useDomGeometryCommit.test.tsx +5 -1
  24. package/src/hooks/useDomGeometryCommit.ts +6 -9
  25. package/src/hooks/useFreezeFrame.test.ts +39 -3
  26. package/src/hooks/useFreezeFrame.ts +4 -1
  27. package/src/hooks/useGsapAwareEditing.test.tsx +25 -0
  28. package/src/hooks/useGsapAwareEditing.ts +12 -8
  29. package/src/hooks/useGsapAwareGroupMove.ts +2 -2
  30. package/src/hooks/useGsapScriptCommits.test.tsx +69 -1
  31. package/src/hooks/useGsapScriptCommits.ts +9 -7
  32. package/src/hooks/usePersistentEditHistory.test.ts +25 -2
  33. package/src/hooks/usePersistentEditHistory.ts +3 -9
  34. package/src/utils/gsapSoftReload.test.ts +39 -0
  35. package/src/utils/gsapSoftReload.ts +7 -11
  36. package/src/utils/gsapUndoRestore.browser.test.ts +91 -44
  37. package/src/utils/softReloadTargets.ts +4 -3
  38. package/src/utils/studioFileHistory.ts +1 -0
@@ -1 +1 @@
1
- import{g as P}from"./index-DYNaXPVf.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};
1
+ import{g as P}from"./index-C5qKdpgl.js";function j(c,d){for(var s=0;s<d.length;s++){const a=d[s];if(typeof a!="string"&&!Array.isArray(a)){for(const i in a)if(i!=="default"&&!(i in c)){const l=Object.getOwnPropertyDescriptor(a,i);l&&Object.defineProperty(c,i,l.get?l:{enumerable:!0,get:()=>a[i]})}}}return Object.freeze(Object.defineProperty(c,Symbol.toStringTag,{value:"Module"}))}var v={},w;function k(){if(w)return v;w=1,Object.defineProperty(v,"__esModule",{value:!0}),v.default=d;var c=window.OfflineAudioContext||window.webkitOfflineAudioContext;function d(e){var r=a(e);return r.start(0),[i,y,O(e.sampleRate),s].reduce(function(t,o){return o(t)},r.buffer.getChannelData(0))}function s(e){return e.sort(function(r,t){return t.count-r.count}).splice(0,5)[0].tempo}function a(e){var r=e.length,t=e.numberOfChannels,o=e.sampleRate,n=new c(t,r,o),u=n.createBufferSource();u.buffer=e;var f=n.createBiquadFilter();return f.type="lowpass",u.connect(f),f.connect(n.destination),u}function i(e){for(var r=[],t=.9,o=.3,n=15;r.length<n&&t>=o;)r=l(e,t),t-=.05;if(r.length<n)throw new Error("Could not find enough samples for a reliable detection.");return r}function l(e,r){for(var t=[],o=0,n=e.length;o<n;o+=1)e[o]>r&&(t.push(o),o+=1e4);return t}function y(e){var r=[];return e.forEach(function(t,o){for(var n=function(x){var g=e[o+x]-t,_=r.some(function(h){if(h.interval===g)return h.count+=1});_||r.push({interval:g,count:1})},u=0;u<10;u+=1)n(u)}),r}function O(e){return function(r){var t=[];return r.forEach(function(o){if(o.interval!==0){for(var n=60/(o.interval/e);n<90;)n*=2;for(;n>180;)n/=2;n=Math.round(n);var u=t.some(function(f){if(f.tempo===n)return f.count+=o.count});u||t.push({tempo:n,count:o.count})}}),t}}return v}var p,b;function q(){return b||(b=1,p=k().default),p}var m=q();const A=P(m),D=j({__proto__:null,default:A},[m]);export{D as i};
@@ -1,4 +1,4 @@
1
- import{n as Qi}from"./index-DYNaXPVf.js";/*!
1
+ import{n as Qi}from"./index-C5qKdpgl.js";/*!
2
2
  * Copyright (c) 2026-present, Vanilagy and contributors
3
3
  *
4
4
  * This Source Code Form is subject to the terms of the Mozilla Public
package/dist/index.d.ts CHANGED
@@ -823,6 +823,17 @@ interface TimelineRangeSelection {
823
823
  anchorY: number;
824
824
  }
825
825
 
826
+ interface RecordEditInput$5 {
827
+ label: string;
828
+ coalesceKey?: string;
829
+ coalesceMs?: number;
830
+ files: Record<string, {
831
+ before: string;
832
+ after: string;
833
+ }>;
834
+ created?: string[];
835
+ }
836
+
826
837
  interface ImportedFontAsset {
827
838
  family: string;
828
839
  path: string;
@@ -856,7 +867,7 @@ type CommitDomAttributeBatch = (selection: DomEditSelection, operations: PatchOp
856
867
  prepareContent?: (html: string) => string;
857
868
  }) => Promise<boolean>;
858
869
 
859
- interface RecordEditInput$5 {
870
+ interface RecordEditInput$4 {
860
871
  label: string;
861
872
  coalesceKey?: string;
862
873
  files: Record<string, {
@@ -880,7 +891,7 @@ interface UseTimelineEditingOptions {
880
891
  showToast: (message: string, tone?: "error" | "info") => void;
881
892
  writeProjectFile: (path: string, content: string, expectedContent?: string) => Promise<void>;
882
893
  observeProjectFileVersion?: (path: string, version: string | null) => void;
883
- recordEdit: (input: RecordEditInput$5) => Promise<void>;
894
+ recordEdit: (input: RecordEditInput$4) => Promise<void>;
884
895
  reloadPreview: () => void;
885
896
  previewIframeRef: RefObject<HTMLIFrameElement | null>;
886
897
  pendingTimelineEditPathRef: MutableRefObject<Set<string>>;
@@ -968,7 +979,7 @@ interface CommitMutationOptions {
968
979
  * error handling — a failed write still throws.
969
980
  */
970
981
  deferPreviewSync?: boolean;
971
- /** Shares an in-place patch miss with the final render of one multi-write action. */
982
+ /** Carries a deferred write not yet on screen (no patch, or a missed one) to the final render. */
972
983
  previewFallbackLatch?: {
973
984
  pending: boolean;
974
985
  };
@@ -2767,15 +2778,6 @@ interface UndoRestoreFile {
2767
2778
  }
2768
2779
  type RestoreFiles = Record<string, UndoRestoreFile>;
2769
2780
 
2770
- interface RecordEditInput$4 {
2771
- label: string;
2772
- coalesceKey?: string;
2773
- coalesceMs?: number;
2774
- files: Record<string, {
2775
- before: string;
2776
- after: string;
2777
- }>;
2778
- }
2779
2781
  interface ApplyCallbacks {
2780
2782
  readFile: (path: string) => Promise<string>;
2781
2783
  serialize?: <T>(paths: readonly string[], task: () => Promise<T>) => Promise<T>;
@@ -2811,7 +2813,7 @@ declare function usePersistentEditHistory({ projectId }: UsePersistentEditHistor
2811
2813
  createdAt: number;
2812
2814
  }[];
2813
2815
  };
2814
- recordEdit: ({ label, coalesceKey, coalesceMs, files }: RecordEditInput$4) => Promise<void>;
2816
+ recordEdit: ({ label, coalesceKey, coalesceMs, files, created }: RecordEditInput$5) => Promise<void>;
2815
2817
  undo: (callbacks: ApplyCallbacks) => Promise<ApplyResult>;
2816
2818
  redo: (callbacks: ApplyCallbacks) => Promise<ApplyResult>;
2817
2819
  predict: (direction: "undo" | "redo") => {
@@ -3132,9 +3134,10 @@ interface CssRotationTarget {
3132
3134
  /** An inline box does not transform, so the turn makes it inline-block. */
3133
3135
  inline: boolean;
3134
3136
  }
3137
+ type PressChoseGsap = null;
3135
3138
  type RotationCommit = {
3136
3139
  angle: number;
3137
- plain?: CssRotationTarget;
3140
+ plain?: CssRotationTarget | PressChoseGsap;
3138
3141
  };
3139
3142
 
3140
3143
  declare const SNAP_THRESHOLD_PX = 6;
@@ -3446,7 +3449,9 @@ declare function useDomEditSession({ projectId, activeCompPath, compIdToSrc, cap
3446
3449
  }, offset?: {
3447
3450
  x: number;
3448
3451
  y: number;
3449
- }, restore?: () => void) => Promise<GeometryCommitResult>;
3452
+ }, restore?: () => void, route?: {
3453
+ plainTranslate: boolean;
3454
+ }) => Promise<GeometryCommitResult>;
3450
3455
  handleDomRotationCommit: (selection: DomEditSelection, next: RotationCommit) => Promise<GeometryCommitResult | undefined>;
3451
3456
  handleDomManualEditsReset: (selection: DomEditSelection) => Promise<DomEditPersistOutcome | undefined>;
3452
3457
  handleDomTextCommit: (value: string, fieldKey?: string) => Promise<DomEditCommitOutcome>;
@@ -3703,7 +3708,9 @@ interface DomEditOverlayProps {
3703
3708
  }, offset?: {
3704
3709
  x: number;
3705
3710
  y: number;
3706
- }, restore?: () => void) => Promise<unknown> | void;
3711
+ }, restore?: () => void, route?: {
3712
+ plainTranslate: boolean;
3713
+ }) => Promise<unknown> | void;
3707
3714
  onRotationCommit: (selection: DomEditSelection, next: RotationCommit) => Promise<unknown> | void;
3708
3715
  onStyleCommit?: (property: string, value: string) => Promise<unknown> | void;
3709
3716
  recordingState?: GestureRecordingState;
@@ -3799,8 +3806,8 @@ declare function GradientField({ value, fallbackColor, disabled, onCommit, }: {
3799
3806
  * mounts; drain `waitForPendingSaves` before switching projects.
3800
3807
  */
3801
3808
  interface UseDomGeometryCommitOptions extends UseDomStyleCommitOptions {
3802
- /** Called when a save cannot patch the preview in place; defaults to reloading the iframe. */
3803
- reloadPreview?: () => void;
3809
+ /** Reloads the host's preview when a save cannot patch it in place. */
3810
+ reloadPreview: () => void;
3804
3811
  }
3805
3812
  interface DomGeometryCommits {
3806
3813
  commitPathOffset: (selection: DomEditSelection, next: {
@@ -3814,7 +3821,9 @@ interface DomGeometryCommits {
3814
3821
  }, offset?: {
3815
3822
  x: number;
3816
3823
  y: number;
3817
- }, restore?: () => void) => Promise<DomEditCommitOutcome>;
3824
+ }, restore?: () => void, route?: {
3825
+ plainTranslate: boolean;
3826
+ }) => Promise<DomEditCommitOutcome>;
3818
3827
  commitRotation: (selection: DomEditSelection, next: RotationCommit) => Promise<DomEditCommitOutcome>;
3819
3828
  waitForPendingSaves: () => Promise<void>;
3820
3829
  }
package/dist/index.html CHANGED
@@ -14,7 +14,7 @@
14
14
  document.documentElement.dataset.theme = "paper";
15
15
  }
16
16
  </script>
17
- <script type="module" crossorigin src="/assets/index-DYNaXPVf.js"></script>
17
+ <script type="module" crossorigin src="/assets/index-C5qKdpgl.js"></script>
18
18
  <link rel="stylesheet" crossorigin href="/assets/index-t1LH6H5H.css">
19
19
  </head>
20
20
  <body>
package/dist/index.js CHANGED
@@ -16941,6 +16941,28 @@ function applyAuthoredInlineOpacity(style, authored) {
16941
16941
  else style.setProperty("opacity", authored);
16942
16942
  }
16943
16943
 
16944
+ // src/utils/elementGsap.ts
16945
+ function gsapOf(element) {
16946
+ return element.ownerDocument.defaultView?.gsap;
16947
+ }
16948
+ function setElementGsapPosition(element, x, y) {
16949
+ const gsap3 = gsapOf(element);
16950
+ if (!gsap3?.set) return false;
16951
+ gsap3.set(element, { x, y });
16952
+ return true;
16953
+ }
16954
+ function setElementGsapScale(element, x, y) {
16955
+ const gsap3 = gsapOf(element);
16956
+ if (!gsap3?.set) return false;
16957
+ gsap3.set(element, { scaleX: x, scaleY: y });
16958
+ return true;
16959
+ }
16960
+ function elementTargets(tween) {
16961
+ return (tween.targets?.() ?? []).filter(
16962
+ (t2) => Boolean(t2?.style && t2.nodeType)
16963
+ );
16964
+ }
16965
+
16944
16966
  // src/utils/softReloadTargets.ts
16945
16967
  var NESTED_VARS = /* @__PURE__ */ new Set(["css", "startAt", "keyframes"]);
16946
16968
  function tweenedProps(vars) {
@@ -16961,7 +16983,7 @@ function authoringFile(el) {
16961
16983
  }
16962
16984
  function addTweenTargets(tween, targets) {
16963
16985
  const props = tweenedProps(tween.vars);
16964
- for (const el of tween.targets?.() ?? []) {
16986
+ for (const el of elementTargets(tween)) {
16965
16987
  const seen = targets.get(el) ?? /* @__PURE__ */ new Set();
16966
16988
  for (const prop of props) seen.add(prop);
16967
16989
  targets.set(el, seen);
@@ -16987,7 +17009,7 @@ function tweenTargetsIn(timelines) {
16987
17009
  for (const tl of timelines) {
16988
17010
  try {
16989
17011
  for (const tween of tl?.getChildren?.(true) ?? []) {
16990
- for (const el of tween.targets?.() ?? []) els.add(el);
17012
+ for (const el of elementTargets(tween)) els.add(el);
16991
17013
  }
16992
17014
  } catch {
16993
17015
  }
@@ -17101,7 +17123,8 @@ function runSuppressed(win, reload) {
17101
17123
  if (win.__hfSuppressSceneMutations) win.__hfSuppressSceneMutations(reload);
17102
17124
  else reload();
17103
17125
  return true;
17104
- } catch {
17126
+ } catch (error) {
17127
+ console.error("[Studio] GSAP soft reload threw; falling back to a full reload", error);
17105
17128
  return false;
17106
17129
  }
17107
17130
  }
@@ -17173,15 +17196,10 @@ function applySoftReload(iframe, scriptText, options = {}) {
17173
17196
  }
17174
17197
  const allTargets = [...targets.keys()];
17175
17198
  if (allTargets.length > 0 && win.gsap?.set) {
17176
- const saved2 = [];
17177
- for (const el of allTargets) {
17178
- const styled = el;
17179
- if (styled.style?.cssText != null) saved2.push([styled, styled.style.cssText]);
17180
- }
17181
- try {
17182
- win.gsap.set(allTargets, { clearProps: "all" });
17183
- } catch {
17184
- }
17199
+ const saved2 = allTargets.map(
17200
+ (el) => [el, el.style.cssText]
17201
+ );
17202
+ win.gsap.set(allTargets, { clearProps: "all" });
17185
17203
  for (const [el, css2] of saved2) {
17186
17204
  const s = el.style;
17187
17205
  s.cssText = css2;
@@ -29411,6 +29429,14 @@ var BOX_CHANNELS = [
29411
29429
  function gsapWritesBox(el) {
29412
29430
  return gsapWritesPosition(el) || gsapWritesChannels(el, BOX_CHANNELS);
29413
29431
  }
29432
+ var GSAP_OWNS = {
29433
+ move: gsapWritesPosition,
29434
+ resize: gsapWritesBox,
29435
+ rotate: gsapWritesRotation
29436
+ };
29437
+ function editsPlainCss(el, gesture) {
29438
+ return !GSAP_OWNS[gesture](el);
29439
+ }
29414
29440
  function elementHasNonHoldTween(el, channels) {
29415
29441
  const win = el.ownerDocument.defaultView;
29416
29442
  return hasNonHoldTween(win?.__timelines ?? null, el, channels);
@@ -36716,11 +36742,11 @@ function writeTranslatePx(el, p) {
36716
36742
  }
36717
36743
  el.style.setProperty("translate", formatTranslatePx(p));
36718
36744
  }
36719
- function readMoveOffset(el, plainTranslate = !gsapWritesPosition(el)) {
36745
+ function readMoveOffset(el, plainTranslate = editsPlainCss(el, "move")) {
36720
36746
  return plainTranslate ? readTranslatePx(el) : readStudioPathOffset(el);
36721
36747
  }
36722
36748
  function readShownRotation(el) {
36723
- return gsapWritesRotation(el) ? readStudioRotation(el) : { angle: roundTo3(readCssRotation(el)) };
36749
+ return editsPlainCss(el, "rotate") ? { angle: roundTo3(readCssRotation(el)) } : readStudioRotation(el);
36724
36750
  }
36725
36751
 
36726
36752
  // src/components/editor/manualOffsetDrag.ts
@@ -36884,8 +36910,7 @@ function resolveManualOffsetForPointerDelta(input) {
36884
36910
  };
36885
36911
  }
36886
36912
  function createManualOffsetDragMember(input) {
36887
- const gsapOwns = input.gesture === "resize" ? gsapWritesBox : gsapWritesPosition;
36888
- const plainTranslate = !!input.gesture && !gsapOwns(input.element);
36913
+ const plainTranslate = !!input.gesture && editsPlainCss(input.element, input.gesture === "resize" ? "resize" : "move");
36889
36914
  const initialOffset = plainTranslate ? readTranslatePx(input.element) : readAppliedStudioPathOffset(input.element);
36890
36915
  if (!finitePoint(initialOffset))
36891
36916
  return { ok: false, reason: UNREADABLE_TRANSLATE, selection: input.selection };
@@ -37886,7 +37911,7 @@ function startGesture(kind, e, opts, options) {
37886
37911
  }
37887
37912
  }
37888
37913
  try {
37889
- const plain = !!pathOffsetMember?.plainTranslate || !gsapWritesRotation(sel.element);
37914
+ const plain = !!pathOffsetMember?.plainTranslate || editsPlainCss(sel.element, "rotate");
37890
37915
  const plainRotation = plain && kind === "rotate" ? readCssRotationTarget(sel.element) : null;
37891
37916
  const rotation = { angle: readRotationBase(sel.element, plain) };
37892
37917
  const overlayBounds = overlayEl?.getBoundingClientRect();
@@ -38419,7 +38444,7 @@ function createDomEditOverlayGestureHandlers(opts) {
38419
38444
  return;
38420
38445
  }
38421
38446
  applyRotationDraft(sel.element, finalRotation.angle, g.plainRotation);
38422
- const commit = g.plainRotation ? { ...finalRotation, plain: g.plainRotation } : finalRotation;
38447
+ const commit = { ...finalRotation, plain: g.plainRotation };
38423
38448
  void Promise.resolve(opts.onRotationCommitRef.current(sel, commit)).then((result) => trackPreviewEditResult("rotate", "drag", result)).catch((error) => {
38424
38449
  logGestureCommitFailure("rotate commit failed", error);
38425
38450
  if (g.manualEditDragToken && isStudioManualEditGestureCurrent(sel.element, g.manualEditDragToken))
@@ -38485,7 +38510,7 @@ function createDomEditOverlayGestureHandlers(opts) {
38485
38510
  if (finalOffset) restoreStudioPathOffset(sel.element, g.initialPathOffset);
38486
38511
  };
38487
38512
  void Promise.resolve(
38488
- opts.onBoxSizeCommitRef.current(sel, finalSize, finalOffset ?? void 0, restore2)
38513
+ opts.onBoxSizeCommitRef.current(sel, finalSize, finalOffset ?? void 0, restore2, member)
38489
38514
  ).then((result) => trackPreviewEditResult("resize", "drag", result)).catch((error) => {
38490
38515
  logGestureCommitFailure("resize commit failed", error);
38491
38516
  }).finally(() => {
@@ -46291,28 +46316,6 @@ function readAllAnimatedProperties(iframe, selector, anim, group) {
46291
46316
  return result;
46292
46317
  }
46293
46318
 
46294
- // src/utils/elementGsap.ts
46295
- function gsapOf(element) {
46296
- return element.ownerDocument.defaultView?.gsap;
46297
- }
46298
- function setElementGsapPosition(element, x, y) {
46299
- const gsap3 = gsapOf(element);
46300
- if (!gsap3?.set) return false;
46301
- gsap3.set(element, { x, y });
46302
- return true;
46303
- }
46304
- function setElementGsapScale(element, x, y) {
46305
- const gsap3 = gsapOf(element);
46306
- if (!gsap3?.set) return false;
46307
- gsap3.set(element, { scaleX: x, scaleY: y });
46308
- return true;
46309
- }
46310
- function elementTargets(tween) {
46311
- return (tween.targets?.() ?? []).filter(
46312
- (t2) => Boolean(t2?.style && t2.nodeType)
46313
- );
46314
- }
46315
-
46316
46319
  // src/hooks/gsapParsedTween.ts
46317
46320
  var PARSED_NAME = { scale: "scaleX", rotate: "rotation" };
46318
46321
  function findPropTween(pt, prop) {
@@ -51599,7 +51602,7 @@ function readGsapRuntimeValuesForPanel(gsapAnimId, gsapAnimations, element, prev
51599
51602
  const el = findPreviewNode(iframe.contentDocument, element);
51600
51603
  if (!el) return null;
51601
51604
  const propKeys = collectPanelPropKeys(gsapAnimations);
51602
- const readsTransform = gsapWritesPosition(el);
51605
+ const readsTransform = !editsPlainCss(el, "move");
51603
51606
  const result = {};
51604
51607
  for (const prop of propKeys) {
51605
51608
  if (!readsTransform && GSAP_TRANSFORM_KEYS.has(prop)) continue;
@@ -52279,7 +52282,7 @@ function createTransformCommitHandlers({
52279
52282
  "This element's position can't be edited here yet \u2014 it is driven by its animation"
52280
52283
  ))
52281
52284
  return;
52282
- const plainTranslate = !gsapWritesPosition(element.element);
52285
+ const plainTranslate = editsPlainCss(element.element, "move");
52283
52286
  const current = readMoveOffset(element.element, plainTranslate);
52284
52287
  if (!Number.isFinite(current.x) || !Number.isFinite(current.y))
52285
52288
  return void showToast?.(UNREADABLE_TRANSLATE);
@@ -72585,9 +72588,9 @@ function usePersistentEditHistory({ projectId }) {
72585
72588
  void refresh().finally(() => setLoaded(true));
72586
72589
  }, [refresh, own]);
72587
72590
  const recordEdit = useCallback99(
72588
- async ({ label, coalesceKey, coalesceMs, files }) => {
72591
+ async ({ label, coalesceKey, coalesceMs, files, created = [] }) => {
72589
72592
  if (!projectId) return;
72590
- const paths = Object.keys(files);
72593
+ const paths = [...Object.keys(files), ...created];
72591
72594
  own.overtake();
72592
72595
  const reply = await post(historyUrl(projectId, "/claim"), {
72593
72596
  label,
@@ -74088,7 +74091,7 @@ import { useCallback as useCallback107, useRef as useRef133 } from "react";
74088
74091
  function isFreezeFrameResponse(value) {
74089
74092
  if (typeof value !== "object" || value === null) return false;
74090
74093
  const body = value;
74091
- return typeof body.before === "string" && typeof body.after === "string" && typeof body.version === "string";
74094
+ return typeof body.before === "string" && typeof body.after === "string" && typeof body.version === "string" && typeof body.stillPath === "string";
74092
74095
  }
74093
74096
  function errorOf(value) {
74094
74097
  if (typeof value !== "object" || value === null || !("error" in value)) return null;
@@ -74149,7 +74152,8 @@ function useFreezeFrame(options) {
74149
74152
  const result = await requestFreezeFrame({ projectId, path, element, playhead });
74150
74153
  await opts.recordEdit({
74151
74154
  label: "Freeze frame",
74152
- files: { [path]: { before: result.before, after: result.after } }
74155
+ files: { [path]: { before: result.before, after: result.after } },
74156
+ created: [result.stillPath]
74153
74157
  });
74154
74158
  opts.observeProjectFileVersion?.(path, result.version);
74155
74159
  });
@@ -79354,7 +79358,11 @@ function savePlainRotation({ commitPositionPatchToHtml, readOnlyPreview }, selec
79354
79358
  const before = captureStudioRotation(element);
79355
79359
  const patches = element.hasAttribute(STUDIO_ROTATION_ATTR) ? buildClearRotationPatches(element) : [];
79356
79360
  if (patches.length) clearStudioRotation(element);
79357
- const drawn = applyCssRotation(element, next.angle, patches.length ? void 0 : next.plain);
79361
+ const drawn = applyCssRotation(
79362
+ element,
79363
+ next.angle,
79364
+ patches.length ? void 0 : next.plain ?? void 0
79365
+ );
79358
79366
  patches.push(...drawn);
79359
79367
  const turn = drawn.at(-1);
79360
79368
  return commitPositionPatchToHtml(selection, patches, {
@@ -81041,7 +81049,8 @@ function softReloadOrEscalate(iframe, scriptText, reloadPreview, origin2, author
81041
81049
  }
81042
81050
  function applyPreviewSync(iframe, result, options, reloadPreview, nestedFiles) {
81043
81051
  const patches = instantPatchesFor(options);
81044
- let needsFallback = options.previewFallbackLatch?.pending === true;
81052
+ const writtenWithoutPatch = patches.length === 0;
81053
+ let needsFallback = options.previewFallbackLatch?.pending === true || writtenWithoutPatch;
81045
81054
  if (patches.length > 0) {
81046
81055
  const deferSeek = options.deferPreviewSync === true;
81047
81056
  const missed = patches.find(
@@ -81161,9 +81170,12 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
81161
81170
  if (!result) return;
81162
81171
  trackKeyframeCommit(mutations, result, options, calls.map((call) => call.options));
81163
81172
  options.onResult?.(result);
81164
- const instantPatches = calls.map(({ options: callOptions }) => callOptions.instantPatch).filter((patch) => patch !== void 0);
81173
+ const instantPatches = calls.flatMap(
81174
+ ({ options: callOptions }) => callOptions.instantPatch ? [callOptions.instantPatch] : []
81175
+ );
81165
81176
  const { instantPatch: _instantPatch, ...batchOptions } = options;
81166
- await finalizeSuccessfulMutation(pid, compositionPath, last.selection, last.mutation, targetPath, result, instantPatches.length > 0 ? { ...batchOptions, instantPatches } : batchOptions);
81177
+ const allPatched = instantPatches.length === calls.length;
81178
+ await finalizeSuccessfulMutation(pid, compositionPath, last.selection, last.mutation, targetPath, result, allPatched ? { ...batchOptions, instantPatches } : batchOptions);
81167
81179
  }, [showToast, finalizeSuccessfulMutation]);
81168
81180
  const commitMutation = useMemo73(() => {
81169
81181
  const serializeFile = (file, task) => {
@@ -81963,7 +81975,7 @@ function useGsapAwareGroupMove({
81963
81975
  const offsetMembers = /* @__PURE__ */ new Map();
81964
81976
  const preflightResults = await Promise.allSettled(
81965
81977
  updates.map(async ({ selection, next, plainTranslate }) => {
81966
- if (plainTranslate ?? !gsapWritesPosition(selection.element)) {
81978
+ if (plainTranslate ?? editsPlainCss(selection.element, "move")) {
81967
81979
  refuseGsapTakeover(selection.element, toastRefusal ? showToast : () => {
81968
81980
  });
81969
81981
  return void offsetMembers.set(selection, true);
@@ -82712,7 +82724,7 @@ function useGsapAwareEditing({
82712
82724
  const handleGsapAwarePathOffsetCommit = useCallback146(
82713
82725
  async (selection, next, modifiers) => {
82714
82726
  const writes = observeGsapGesture(gsapCommitMutation);
82715
- if (modifiers?.plainTranslate ?? !gsapWritesPosition(selection.element)) {
82727
+ if (modifiers?.plainTranslate ?? editsPlainCss(selection.element, "move")) {
82716
82728
  const result = await stageElementPositionOffset(selection, next, true).save();
82717
82729
  return writes.finish(result?.changed === true);
82718
82730
  }
@@ -82759,9 +82771,9 @@ function useGsapAwareEditing({
82759
82771
  showToast
82760
82772
  });
82761
82773
  const handleGsapAwareBoxSizeCommit = useCallback146(
82762
- async (selection, next, offset, restore2 = () => void 0) => {
82774
+ async (selection, next, offset, restore2 = () => void 0, route) => {
82763
82775
  const writes = observeGsapGesture(gsapCommitMutation);
82764
- if (!gsapWritesBox(selection.element)) {
82776
+ if (route?.plainTranslate ?? editsPlainCss(selection.element, "resize")) {
82765
82777
  const result = await handleDomBoxSizeCommit(selection, next, offset, restore2);
82766
82778
  return writes.finish(result?.changed === true);
82767
82779
  }
@@ -82803,8 +82815,13 @@ function useGsapAwareEditing({
82803
82815
  makeFetchFallback(selection)
82804
82816
  );
82805
82817
  await saveMove(dragOutcome, async () => {
82806
- const plain = !gsapWritesPosition(selection.element);
82807
- anchorMove = stageElementPositionOffset(selection, offset, plain, coalesceKey);
82818
+ const plainAfterSettle = editsPlainCss(selection.element, "move");
82819
+ anchorMove = stageElementPositionOffset(
82820
+ selection,
82821
+ offset,
82822
+ plainAfterSettle,
82823
+ coalesceKey
82824
+ );
82808
82825
  });
82809
82826
  }
82810
82827
  };
@@ -82896,7 +82913,7 @@ function useGsapAwareEditing({
82896
82913
  const handleGsapAwareRotationCommit = useCallback146(
82897
82914
  async (selection, next) => {
82898
82915
  const writes = observeGsapGesture(gsapCommitMutation);
82899
- if (next.plain || !gsapWritesRotation(selection.element)) {
82916
+ if (next.plain === void 0 ? editsPlainCss(selection.element, "rotate") : next.plain) {
82900
82917
  const result = await handleDomRotationCommit(selection, next);
82901
82918
  return writes.finish(result?.changed === true);
82902
82919
  }
@@ -98060,17 +98077,13 @@ function useDomGeometryCommit({
98060
98077
  projectIdRef.current = projectId;
98061
98078
  const pending2 = useRef190(/* @__PURE__ */ new Set()).current;
98062
98079
  const editHistory = useMemo91(() => ({ recordEdit }), [recordEdit]);
98063
- const reload = useCallback197(
98064
- () => reloadPreview ? reloadPreview() : iframeRef.current?.contentWindow?.location.reload(),
98065
- [reloadPreview, iframeRef]
98066
- );
98067
98080
  const { bump: bumpGsapCache } = useGsapCacheVersion();
98068
98081
  const gsap3 = useGsapScriptCommits({
98069
98082
  projectIdRef,
98070
98083
  activeCompPath,
98071
98084
  previewIframeRef: iframeRef,
98072
98085
  editHistory,
98073
- reloadPreview: reload,
98086
+ reloadPreview,
98074
98087
  onCacheInvalidate: bumpGsapCache,
98075
98088
  showToast,
98076
98089
  writeProjectFile
@@ -98153,7 +98166,7 @@ function useDomGeometryCommit({
98153
98166
  () => ({
98154
98167
  commitPathOffset: (selection, next, modifiers) => saved2(() => handleGsapAwarePathOffsetCommit(selection, next, modifiers)),
98155
98168
  commitGroupPathOffset: (updates) => saved2(() => handleGsapAwareGroupPathOffsetCommit(updates)),
98156
- commitBoxSize: (selection, next, offset, restore2) => saved2(() => handleGsapAwareBoxSizeCommit(selection, next, offset, restore2), restore2),
98169
+ commitBoxSize: (selection, next, offset, restore2, route) => saved2(() => handleGsapAwareBoxSizeCommit(selection, next, offset, restore2, route), restore2),
98157
98170
  commitRotation: (selection, next) => saved2(() => handleGsapAwareRotationCommit(selection, next)),
98158
98171
  waitForPendingSaves: () => Promise.allSettled([...pending2]).then(noop2)
98159
98172
  }),