@hyperframes/studio 0.8.124 → 0.8.125
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.
- package/dist/assets/{hyperframes-player-ColOZ_78.js → hyperframes-player-CmIh-wq9.js} +1 -1
- package/dist/assets/{index-jQEqFKMk.js → index-4LRR6o2F.js} +1 -1
- package/dist/assets/{index-BuSTrK-Z.js → index-CrYoEZ5p.js} +139 -139
- package/dist/assets/{index-CVuUfURE.js → index-yCK8osBg.js} +1 -1
- package/dist/index.d.ts +43 -35
- package/dist/index.html +1 -1
- package/dist/index.js +213 -94
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/src/components/editor/domEditOverlayGestures.ts +2 -0
- package/src/components/editor/domEditOverlayStartGesture.ts +6 -0
- package/src/components/editor/dragUndoPaint.test.ts +170 -2
- package/src/components/editor/gestureUndoRevert.ts +104 -0
- package/src/components/editor/manualOffsetDrag.ts +1 -12
- package/src/components/editor/useDomEditNudge.ts +1 -1
- package/src/components/editor/useDomEditOverlayGestures.ts +9 -5
- package/src/hooks/gestureTransaction.test.ts +60 -0
- package/src/hooks/gestureTransaction.ts +5 -2
- package/src/hooks/gsapGestureOutcome.ts +9 -2
- package/src/hooks/gsapResizeDropPoint.test.ts +39 -1
- package/src/hooks/gsapResizeElementSize.test.tsx +27 -0
- package/src/hooks/gsapResizeIntercept.ts +55 -68
- package/src/hooks/gsapScriptCommitTypes.ts +2 -0
- package/src/hooks/useGsapAwareEditing.groupPlan.test.tsx +29 -1
- package/src/hooks/useGsapAwareEditing.test.tsx +1 -0
- package/src/hooks/useGsapAwareEditing.ts +21 -25
- package/src/hooks/useGsapAwareGroupMove.ts +4 -6
- package/src/hooks/useGsapScriptCommits.test.tsx +42 -1
- package/src/hooks/useGsapScriptCommits.ts +12 -3
- package/src/utils/studioPendingEdits.test.ts +52 -0
- package/src/utils/studioPendingEdits.ts +55 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as P}from"./index-
|
|
1
|
+
import{g as P}from"./index-CrYoEZ5p.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};
|
package/dist/index.d.ts
CHANGED
|
@@ -915,6 +915,48 @@ type TimelineMoveUpdates = Pick<TimelineElement, "start" | "track"> & {
|
|
|
915
915
|
stackingReorder?: TimelineStackingReorderIntent | null;
|
|
916
916
|
};
|
|
917
917
|
|
|
918
|
+
declare class StudioSaveHttpError extends Error {
|
|
919
|
+
readonly statusCode: number;
|
|
920
|
+
readonly alreadyToasted: boolean;
|
|
921
|
+
constructor(message: string, statusCode: number, options?: {
|
|
922
|
+
alreadyToasted?: boolean;
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
declare class StudioFileConflictError extends StudioSaveHttpError {
|
|
926
|
+
readonly filePath: string;
|
|
927
|
+
readonly currentVersion: string | null;
|
|
928
|
+
readonly currentContent: string | null;
|
|
929
|
+
readonly attemptedContent: string;
|
|
930
|
+
constructor(input: {
|
|
931
|
+
filePath: string;
|
|
932
|
+
currentVersion: string | null;
|
|
933
|
+
currentContent: string | null;
|
|
934
|
+
attemptedContent: string;
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
type StudioSaveDrainResult<Failure = unknown> = {
|
|
938
|
+
status: "clean";
|
|
939
|
+
} | {
|
|
940
|
+
status: "conflict";
|
|
941
|
+
error: StudioFileConflictError;
|
|
942
|
+
} | {
|
|
943
|
+
status: "failed";
|
|
944
|
+
error: Failure;
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
type StudioPendingEditsDrainResult = StudioSaveDrainResult;
|
|
948
|
+
interface StudioEditInFlight {
|
|
949
|
+
reverted: () => boolean;
|
|
950
|
+
within: <T>(run: () => T) => T;
|
|
951
|
+
drawUnlessUndone: (draw: () => void) => void;
|
|
952
|
+
drawKeepingUndone: <T>(draw: () => T) => T;
|
|
953
|
+
markSaved: () => void;
|
|
954
|
+
}
|
|
955
|
+
declare function revertNewestStudioPendingEdit(): (() => void) | null;
|
|
956
|
+
declare function flushStudioPendingEdits({ onlyCurrent, }?: {
|
|
957
|
+
onlyCurrent?: boolean | undefined;
|
|
958
|
+
}): Promise<StudioPendingEditsDrainResult>;
|
|
959
|
+
|
|
918
960
|
/** Value-only channels a `tl.set(...)` patch may touch. */
|
|
919
961
|
interface SetPatchProps {
|
|
920
962
|
x?: number;
|
|
@@ -984,6 +1026,7 @@ interface CommitMutationOptions {
|
|
|
984
1026
|
pending: boolean;
|
|
985
1027
|
};
|
|
986
1028
|
beforeReload?: () => void;
|
|
1029
|
+
pendingEdit?: StudioEditInFlight;
|
|
987
1030
|
/**
|
|
988
1031
|
* Serialize this commit against others sharing the same key. Used to chain
|
|
989
1032
|
* per-animationId GSAP meta updates. Every commit independently takes the
|
|
@@ -2881,41 +2924,6 @@ declare function useTimelineEditing({ projectId, activeCompPath, timelineElement
|
|
|
2881
2924
|
restoreLiveLanes: (restore: Parameters<(restore: LiveLaneRestore) => void>[0]) => void;
|
|
2882
2925
|
};
|
|
2883
2926
|
|
|
2884
|
-
declare class StudioSaveHttpError extends Error {
|
|
2885
|
-
readonly statusCode: number;
|
|
2886
|
-
readonly alreadyToasted: boolean;
|
|
2887
|
-
constructor(message: string, statusCode: number, options?: {
|
|
2888
|
-
alreadyToasted?: boolean;
|
|
2889
|
-
});
|
|
2890
|
-
}
|
|
2891
|
-
declare class StudioFileConflictError extends StudioSaveHttpError {
|
|
2892
|
-
readonly filePath: string;
|
|
2893
|
-
readonly currentVersion: string | null;
|
|
2894
|
-
readonly currentContent: string | null;
|
|
2895
|
-
readonly attemptedContent: string;
|
|
2896
|
-
constructor(input: {
|
|
2897
|
-
filePath: string;
|
|
2898
|
-
currentVersion: string | null;
|
|
2899
|
-
currentContent: string | null;
|
|
2900
|
-
attemptedContent: string;
|
|
2901
|
-
});
|
|
2902
|
-
}
|
|
2903
|
-
type StudioSaveDrainResult<Failure = unknown> = {
|
|
2904
|
-
status: "clean";
|
|
2905
|
-
} | {
|
|
2906
|
-
status: "conflict";
|
|
2907
|
-
error: StudioFileConflictError;
|
|
2908
|
-
} | {
|
|
2909
|
-
status: "failed";
|
|
2910
|
-
error: Failure;
|
|
2911
|
-
};
|
|
2912
|
-
|
|
2913
|
-
type StudioPendingEditsDrainResult = StudioSaveDrainResult;
|
|
2914
|
-
declare function revertNewestStudioPendingEdit(): (() => void) | null;
|
|
2915
|
-
declare function flushStudioPendingEdits({ onlyCurrent, }?: {
|
|
2916
|
-
onlyCurrent?: boolean | undefined;
|
|
2917
|
-
}): Promise<StudioPendingEditsDrainResult>;
|
|
2918
|
-
|
|
2919
2927
|
interface HistoryResult {
|
|
2920
2928
|
ok: boolean;
|
|
2921
2929
|
reason?: string;
|
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-
|
|
17
|
+
<script type="module" crossorigin src="/assets/index-CrYoEZ5p.js"></script>
|
|
18
18
|
<link rel="stylesheet" crossorigin href="/assets/index-D11atkBt.css">
|
|
19
19
|
</head>
|
|
20
20
|
<body>
|
package/dist/index.js
CHANGED
|
@@ -11834,7 +11834,10 @@ function asElement(target) {
|
|
|
11834
11834
|
var STUDIO_FLUSH_PENDING_EDITS_EVENT = "hf-studio-flush-pending-edits";
|
|
11835
11835
|
var pendingEdits = /* @__PURE__ */ new Map();
|
|
11836
11836
|
var NOT_SAVED = () => Promise.resolve(false);
|
|
11837
|
-
var adopting =
|
|
11837
|
+
var adopting = null;
|
|
11838
|
+
function adoptingStudioPendingEdit() {
|
|
11839
|
+
return adopting;
|
|
11840
|
+
}
|
|
11838
11841
|
function waitForPostBlurEffects() {
|
|
11839
11842
|
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
11840
11843
|
}
|
|
@@ -11877,7 +11880,7 @@ function trackStudioPendingEdit(result) {
|
|
|
11877
11880
|
if (!result) return void 0;
|
|
11878
11881
|
const promise = Promise.resolve(result);
|
|
11879
11882
|
if (adopting) return promise;
|
|
11880
|
-
pendingEdits.set(promise, { revert: null, landed: NOT_SAVED });
|
|
11883
|
+
pendingEdits.set(promise, { revert: null, landed: NOT_SAVED, redraws: [], showAgain: null });
|
|
11881
11884
|
promise.then(
|
|
11882
11885
|
() => pendingEdits.delete(promise),
|
|
11883
11886
|
() => pendingEdits.delete(promise)
|
|
@@ -11897,25 +11900,49 @@ function beginStudioPendingEdit(revert) {
|
|
|
11897
11900
|
const entry2 = pendingEdits.get(promise);
|
|
11898
11901
|
entry2.revert = revert;
|
|
11899
11902
|
let landed = Promise.resolve(false);
|
|
11903
|
+
let saved2 = false;
|
|
11900
11904
|
entry2.landed = () => landed;
|
|
11905
|
+
const inFlight = {
|
|
11906
|
+
reverted: () => entry2.revert === null && revert !== null,
|
|
11907
|
+
within(run) {
|
|
11908
|
+
const outer = adopting;
|
|
11909
|
+
adopting = inFlight;
|
|
11910
|
+
try {
|
|
11911
|
+
return run();
|
|
11912
|
+
} finally {
|
|
11913
|
+
adopting = outer;
|
|
11914
|
+
}
|
|
11915
|
+
},
|
|
11916
|
+
drawUnlessUndone(draw) {
|
|
11917
|
+
if (inFlight.reverted()) entry2.redraws.push(draw);
|
|
11918
|
+
else draw();
|
|
11919
|
+
},
|
|
11920
|
+
drawKeepingUndone(draw) {
|
|
11921
|
+
if (!inFlight.reverted()) return draw();
|
|
11922
|
+
entry2.showAgain?.();
|
|
11923
|
+
try {
|
|
11924
|
+
return draw();
|
|
11925
|
+
} finally {
|
|
11926
|
+
entry2.showAgain = revert();
|
|
11927
|
+
}
|
|
11928
|
+
},
|
|
11929
|
+
markSaved: () => void (saved2 = true)
|
|
11930
|
+
};
|
|
11901
11931
|
return {
|
|
11902
11932
|
settle,
|
|
11903
|
-
reverted:
|
|
11904
|
-
// Only what `start` registers synchronously is adopted; a
|
|
11933
|
+
reverted: inFlight.reverted,
|
|
11934
|
+
// Only what `start` registers synchronously is adopted; a later write joins only through `within`.
|
|
11905
11935
|
adopt(start) {
|
|
11906
|
-
adopting = true;
|
|
11907
11936
|
try {
|
|
11908
|
-
const committed = start
|
|
11937
|
+
const committed = inFlight.within(start);
|
|
11909
11938
|
landed = Promise.resolve(committed).then(
|
|
11910
11939
|
() => true,
|
|
11911
|
-
() =>
|
|
11940
|
+
() => saved2
|
|
11912
11941
|
);
|
|
11913
11942
|
return committed;
|
|
11914
11943
|
} catch (error) {
|
|
11915
11944
|
settle();
|
|
11916
11945
|
throw error;
|
|
11917
|
-
} finally {
|
|
11918
|
-
adopting = false;
|
|
11919
11946
|
}
|
|
11920
11947
|
}
|
|
11921
11948
|
};
|
|
@@ -11925,7 +11952,14 @@ function paintBackNewestStudioPendingEdit() {
|
|
|
11925
11952
|
const revert = newest?.revert;
|
|
11926
11953
|
if (!newest || !revert) return null;
|
|
11927
11954
|
newest.revert = null;
|
|
11928
|
-
|
|
11955
|
+
newest.showAgain = revert();
|
|
11956
|
+
return {
|
|
11957
|
+
showAgain: () => {
|
|
11958
|
+
newest.showAgain?.();
|
|
11959
|
+
for (const redraw of newest.redraws.splice(0)) redraw();
|
|
11960
|
+
},
|
|
11961
|
+
landed: newest.landed
|
|
11962
|
+
};
|
|
11929
11963
|
}
|
|
11930
11964
|
function revertNewestStudioPendingEdit() {
|
|
11931
11965
|
return paintBackNewestStudioPendingEdit()?.showAgain ?? null;
|
|
@@ -37150,14 +37184,6 @@ function restoreManualOffsetDragMember(member) {
|
|
|
37150
37184
|
}
|
|
37151
37185
|
endStudioManualEditGesture(member.element, member.gestureToken);
|
|
37152
37186
|
}
|
|
37153
|
-
function manualOffsetMoveRevert(members) {
|
|
37154
|
-
if (!members.every((member) => member.plainTranslate)) return null;
|
|
37155
|
-
return () => {
|
|
37156
|
-
const shown2 = members.map((member) => captureStudioPathOffset(member.element));
|
|
37157
|
-
for (const member of members) restoreStudioPathOffset(member.element, member.initialPathOffset);
|
|
37158
|
-
return () => members.forEach((member, i) => restoreStudioPathOffset(member.element, shown2[i]));
|
|
37159
|
-
};
|
|
37160
|
-
}
|
|
37161
37187
|
function restoreManualOffsetDragMembers(members) {
|
|
37162
37188
|
for (const member of members) {
|
|
37163
37189
|
restoreManualOffsetDragMember(member);
|
|
@@ -37202,6 +37228,70 @@ function resumeGsapTimelines(element) {
|
|
|
37202
37228
|
win.__player?.seek?.(t2);
|
|
37203
37229
|
}
|
|
37204
37230
|
|
|
37231
|
+
// src/components/editor/gestureUndoRevert.ts
|
|
37232
|
+
var PLACEMENT = ["position", "left", "top"];
|
|
37233
|
+
var placementOf = (element) => PLACEMENT.map((prop) => element.style.getPropertyValue(prop));
|
|
37234
|
+
function showPlacement(element, placement) {
|
|
37235
|
+
PLACEMENT.forEach((prop, i) => {
|
|
37236
|
+
if (placement[i]) element.style.setProperty(prop, placement[i]);
|
|
37237
|
+
else element.style.removeProperty(prop);
|
|
37238
|
+
});
|
|
37239
|
+
}
|
|
37240
|
+
function readMemberPosition(member) {
|
|
37241
|
+
const gsap3 = member.plainTranslate ? null : getOffsetDragGsap(member.element);
|
|
37242
|
+
return {
|
|
37243
|
+
offset: captureStudioPathOffset(member.element),
|
|
37244
|
+
gsap: gsap3 && {
|
|
37245
|
+
x: Number(gsap3.getProperty(member.element, "x")),
|
|
37246
|
+
y: Number(gsap3.getProperty(member.element, "y"))
|
|
37247
|
+
},
|
|
37248
|
+
placement: placementOf(member.element)
|
|
37249
|
+
};
|
|
37250
|
+
}
|
|
37251
|
+
function showMemberPosition(member, position) {
|
|
37252
|
+
restoreStudioPathOffset(member.element, position.offset);
|
|
37253
|
+
showPlacement(member.element, position.placement);
|
|
37254
|
+
if (position.gsap) getOffsetDragGsap(member.element)?.set(member.element, { ...position.gsap });
|
|
37255
|
+
if (!member.plainTranslate)
|
|
37256
|
+
stampGestureBase(member.element, member.initialOffset, member.baseGsap);
|
|
37257
|
+
}
|
|
37258
|
+
function manualOffsetMoveRevert(members) {
|
|
37259
|
+
const startPlacement = members.map((member) => placementOf(member.element));
|
|
37260
|
+
return () => {
|
|
37261
|
+
const shown2 = members.map(readMemberPosition);
|
|
37262
|
+
members.forEach(
|
|
37263
|
+
(member, i) => showMemberPosition(member, {
|
|
37264
|
+
offset: member.initialPathOffset,
|
|
37265
|
+
gsap: member.plainTranslate ? null : member.baseGsap,
|
|
37266
|
+
placement: startPlacement[i]
|
|
37267
|
+
})
|
|
37268
|
+
);
|
|
37269
|
+
return () => members.forEach((member, i) => showMemberPosition(member, shown2[i]));
|
|
37270
|
+
};
|
|
37271
|
+
}
|
|
37272
|
+
var GSAP_LOOK_PROPS = ["x", "y", "rotation", "scaleX", "scaleY"];
|
|
37273
|
+
function readElementLook(element, gsapOwned) {
|
|
37274
|
+
const gsap3 = gsapOwned ? getOffsetDragGsap(element) : null;
|
|
37275
|
+
return {
|
|
37276
|
+
style: element.getAttribute("style"),
|
|
37277
|
+
gsap: gsap3 && Object.fromEntries(
|
|
37278
|
+
GSAP_LOOK_PROPS.map((prop) => [prop, Number(gsap3.getProperty(element, prop))])
|
|
37279
|
+
)
|
|
37280
|
+
};
|
|
37281
|
+
}
|
|
37282
|
+
function showElementLook(element, look) {
|
|
37283
|
+
if (look.style === null) element.removeAttribute("style");
|
|
37284
|
+
else element.setAttribute("style", look.style);
|
|
37285
|
+
if (look.gsap) getOffsetDragGsap(element)?.set(element, { ...look.gsap });
|
|
37286
|
+
}
|
|
37287
|
+
function elementLookRevert(element, start) {
|
|
37288
|
+
return () => {
|
|
37289
|
+
const shown2 = readElementLook(element, start.gsap !== null);
|
|
37290
|
+
showElementLook(element, start);
|
|
37291
|
+
return () => showElementLook(element, shown2);
|
|
37292
|
+
};
|
|
37293
|
+
}
|
|
37294
|
+
|
|
37205
37295
|
// src/components/editor/rotationDraft.ts
|
|
37206
37296
|
function lastRuleTransform(element) {
|
|
37207
37297
|
let value = "";
|
|
@@ -37980,6 +38070,10 @@ function startGesture(kind, e, opts, options) {
|
|
|
37980
38070
|
const rawContentScaleY = rect.height / (rect.editScaleY * actualHeight);
|
|
37981
38071
|
const contentScaleX = Number.isFinite(rawContentScaleX) && rawContentScaleX > 0 ? rawContentScaleX : 1;
|
|
37982
38072
|
const contentScaleY = Number.isFinite(rawContentScaleY) && rawContentScaleY > 0 ? rawContentScaleY : 1;
|
|
38073
|
+
const initialLook = readElementLook(
|
|
38074
|
+
sel.element,
|
|
38075
|
+
kind !== "drag" && !editsPlainCss(sel.element, kind === "rotate" ? "rotate" : "resize")
|
|
38076
|
+
);
|
|
37983
38077
|
let initialPathOffset = captureStudioPathOffset(sel.element);
|
|
37984
38078
|
let manualEditDragToken;
|
|
37985
38079
|
let pathOffsetMember;
|
|
@@ -38059,6 +38153,7 @@ function startGesture(kind, e, opts, options) {
|
|
|
38059
38153
|
initialPathOffset,
|
|
38060
38154
|
initialRotation: captureStudioRotation(sel.element),
|
|
38061
38155
|
initialBoxSize: captureStudioBoxSize(sel.element),
|
|
38156
|
+
initialLook,
|
|
38062
38157
|
pathOffsetMember,
|
|
38063
38158
|
originLeft: rect.left,
|
|
38064
38159
|
originTop: rect.top,
|
|
@@ -38560,11 +38655,13 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
38560
38655
|
}
|
|
38561
38656
|
applyRotationDraft(sel.element, finalRotation.angle, g.plainRotation);
|
|
38562
38657
|
const commit = { ...finalRotation, plain: g.plainRotation };
|
|
38563
|
-
|
|
38658
|
+
const edit = beginStudioPendingEdit(elementLookRevert(sel.element, g.initialLook));
|
|
38659
|
+
const saved2 = Promise.resolve(edit.adopt(() => opts.onRotationCommitRef.current(sel, commit))).then((result) => trackPreviewEditResult("rotate", "drag", result)).catch((error) => {
|
|
38564
38660
|
logGestureCommitFailure("rotate commit failed", error);
|
|
38565
38661
|
if (g.manualEditDragToken && isStudioManualEditGestureCurrent(sel.element, g.manualEditDragToken))
|
|
38566
38662
|
restoreRotation();
|
|
38567
38663
|
}).finally(() => endStudioManualEditGesture(sel.element, g.manualEditDragToken));
|
|
38664
|
+
edit.settle(saved2);
|
|
38568
38665
|
} else if (g.kind === "drag") {
|
|
38569
38666
|
opts.suppressNextBoxClickRef.current = true;
|
|
38570
38667
|
const dx = g.lastSnappedDx ?? e.clientX - g.startX;
|
|
@@ -38624,14 +38721,15 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
38624
38721
|
restoreStudioBoxSize(sel.element, g.initialBoxSize);
|
|
38625
38722
|
if (finalOffset) restoreStudioPathOffset(sel.element, g.initialPathOffset);
|
|
38626
38723
|
};
|
|
38627
|
-
|
|
38628
|
-
|
|
38629
|
-
).then((result) => trackPreviewEditResult("resize", "drag", result)).catch((error) => {
|
|
38724
|
+
const commitSize = () => opts.onBoxSizeCommitRef.current(sel, finalSize, finalOffset ?? void 0, restore2, member);
|
|
38725
|
+
const edit = beginStudioPendingEdit(elementLookRevert(sel.element, g.initialLook));
|
|
38726
|
+
const saved2 = Promise.resolve(edit.adopt(commitSize)).then((result) => trackPreviewEditResult("resize", "drag", result)).catch((error) => {
|
|
38630
38727
|
logGestureCommitFailure("resize commit failed", error);
|
|
38631
38728
|
}).finally(() => {
|
|
38632
38729
|
if (member) endManualOffsetDragMembers([member]);
|
|
38633
38730
|
else endStudioManualEditGesture(sel.element, g.manualEditDragToken);
|
|
38634
38731
|
});
|
|
38732
|
+
edit.settle(saved2);
|
|
38635
38733
|
logResizeSettle(sel.element, "post-release");
|
|
38636
38734
|
}
|
|
38637
38735
|
};
|
|
@@ -44465,6 +44563,8 @@ function trackKeyframeCommit(mutations, result, options, memberOptions) {
|
|
|
44465
44563
|
|
|
44466
44564
|
// src/hooks/gsapGestureOutcome.ts
|
|
44467
44565
|
function observeGsapGesture(writer) {
|
|
44566
|
+
const edit = adoptingStudioPendingEdit();
|
|
44567
|
+
const join = (run) => edit ? edit.within(run) : run();
|
|
44468
44568
|
let changed = false;
|
|
44469
44569
|
let pendingResults = 0;
|
|
44470
44570
|
const actions = /* @__PURE__ */ new Set();
|
|
@@ -44472,12 +44572,14 @@ function observeGsapGesture(writer) {
|
|
|
44472
44572
|
pendingResults += 1;
|
|
44473
44573
|
return {
|
|
44474
44574
|
...options,
|
|
44575
|
+
...edit && { pendingEdit: edit },
|
|
44475
44576
|
keyframeTelemetry: false,
|
|
44476
44577
|
onResult: (result) => {
|
|
44477
44578
|
pendingResults -= 1;
|
|
44478
44579
|
options.onResult?.(result);
|
|
44479
44580
|
if (!result.ok || result.changed !== true) return;
|
|
44480
44581
|
changed = true;
|
|
44582
|
+
edit?.markSaved();
|
|
44481
44583
|
const members = changedMutationIndices(
|
|
44482
44584
|
result,
|
|
44483
44585
|
calls.length,
|
|
@@ -44493,16 +44595,18 @@ function observeGsapGesture(writer) {
|
|
|
44493
44595
|
};
|
|
44494
44596
|
let commit = null;
|
|
44495
44597
|
if (writer) {
|
|
44496
|
-
commit = (selection, mutation, options) => writer(selection, mutation, observe([{ selection, mutation, options }], options));
|
|
44598
|
+
commit = (selection, mutation, options) => join(() => writer(selection, mutation, observe([{ selection, mutation, options }], options)));
|
|
44497
44599
|
if (writer.batch) {
|
|
44498
44600
|
const batch = writer.batch;
|
|
44499
|
-
commit.batch = (calls, options) => batch(calls, observe(calls, options));
|
|
44601
|
+
commit.batch = (calls, options) => join(() => batch(calls, observe(calls, options)));
|
|
44500
44602
|
}
|
|
44501
44603
|
}
|
|
44502
44604
|
return {
|
|
44503
44605
|
commit,
|
|
44606
|
+
drawKeepingUndone: (draw) => edit ? edit.drawKeepingUndone(draw) : draw(),
|
|
44504
44607
|
recordDomResult: (result) => {
|
|
44505
44608
|
changed ||= result?.changed === true;
|
|
44609
|
+
if (result?.changed) edit?.markSaved();
|
|
44506
44610
|
},
|
|
44507
44611
|
finish: (domChanged = false) => {
|
|
44508
44612
|
if (pendingResults !== 0) return { ok: true, changed: false };
|
|
@@ -44746,7 +44850,8 @@ function runGestureTransaction(tx) {
|
|
|
44746
44850
|
logCommit("start", { label: tx.label, coalesceKey });
|
|
44747
44851
|
tx.settle();
|
|
44748
44852
|
logCommit("settled", { label: tx.label, coalesceKey });
|
|
44749
|
-
const
|
|
44853
|
+
const measure = () => tx.draw ? tx.draw(() => readPixelRect(tx.element)) : readPixelRect(tx.element);
|
|
44854
|
+
const before = !tx.skipPixelAssert ? measure() : null;
|
|
44750
44855
|
const commit = (commitMutation) => {
|
|
44751
44856
|
const wrapped = (selection, mutation, options) => {
|
|
44752
44857
|
mutationCount += 1;
|
|
@@ -44767,7 +44872,7 @@ function runGestureTransaction(tx) {
|
|
|
44767
44872
|
const durationMs = Math.round(performance.now() - startedAt2);
|
|
44768
44873
|
logCommit("persisted", { label: tx.label, coalesceKey });
|
|
44769
44874
|
if (before) {
|
|
44770
|
-
const after =
|
|
44875
|
+
const after = measure();
|
|
44771
44876
|
const delta = pixelDelta(before, after);
|
|
44772
44877
|
if (exceedsPixelTolerance(delta)) {
|
|
44773
44878
|
logCommit("persist-changed-pixels", { label: tx.label, before, after, delta });
|
|
@@ -81180,13 +81285,22 @@ async function runMutationRequest(mutations, options, showToast, request) {
|
|
|
81180
81285
|
function finishUnchangedMutation(iframe, result, options, reloadPreview) {
|
|
81181
81286
|
if (result.changed !== false) return false;
|
|
81182
81287
|
if (!options.skipReload && (instantPatchesFor(options).length > 0 || options.previewFallbackLatch?.pending)) {
|
|
81183
|
-
|
|
81288
|
+
redrawUnlessPaintedBack(
|
|
81289
|
+
options,
|
|
81290
|
+
() => applyPreviewSync(iframe, result, options, reloadPreview)
|
|
81291
|
+
);
|
|
81184
81292
|
}
|
|
81185
81293
|
return true;
|
|
81186
81294
|
}
|
|
81295
|
+
function redrawUnlessPaintedBack(options, redraw) {
|
|
81296
|
+
if (options.pendingEdit) options.pendingEdit.drawUnlessUndone(redraw);
|
|
81297
|
+
else redraw();
|
|
81298
|
+
}
|
|
81187
81299
|
function refreshMutationPreview(iframe, result, options, reloadPreview, onCacheInvalidate, nestedFiles) {
|
|
81188
|
-
options
|
|
81189
|
-
|
|
81300
|
+
redrawUnlessPaintedBack(options, () => {
|
|
81301
|
+
options.beforeReload?.();
|
|
81302
|
+
applyPreviewSync(iframe, result, options, reloadPreview, nestedFiles);
|
|
81303
|
+
});
|
|
81190
81304
|
onCacheInvalidate();
|
|
81191
81305
|
}
|
|
81192
81306
|
function isActiveCommitTarget(projectIdRef, activeCompPathRef, projectId, compositionPath) {
|
|
@@ -82208,12 +82322,10 @@ function useGsapAwareGroupMove({
|
|
|
82208
82322
|
renderOnCommit = index === lastScriptWrite;
|
|
82209
82323
|
const plain = offsetMembers.get(selection);
|
|
82210
82324
|
if (plain !== void 0) {
|
|
82211
|
-
const
|
|
82212
|
-
selection,
|
|
82213
|
-
|
|
82214
|
-
|
|
82215
|
-
coalesceKey
|
|
82216
|
-
).save();
|
|
82325
|
+
const staged = writes.drawKeepingUndone(
|
|
82326
|
+
() => stageElementPositionOffset(selection, next, plain, coalesceKey)
|
|
82327
|
+
);
|
|
82328
|
+
const result = await staged.save();
|
|
82217
82329
|
writes.recordDomResult(result);
|
|
82218
82330
|
continue;
|
|
82219
82331
|
}
|
|
@@ -82341,7 +82453,7 @@ function tweenUsesScaleLonghands(anim) {
|
|
|
82341
82453
|
);
|
|
82342
82454
|
return inKeyframes || Object.keys(anim?.properties ?? {}).some(isLonghand);
|
|
82343
82455
|
}
|
|
82344
|
-
async function tryGsapResizeIntercept(selection, size, animations, iframe, commitMutation, fetchFallbackAnimations, dragOffset) {
|
|
82456
|
+
async function tryGsapResizeIntercept(selection, size, animations, iframe, commitMutation, fetchFallbackAnimations, dragOffset, draw = (run) => run()) {
|
|
82345
82457
|
const fetchedAnimations = fetchFallbackAnimations ? await fetchFallbackAnimations() : [];
|
|
82346
82458
|
const outcome = preflightGsapResizeIntercept(selection, animations, iframe, fetchedAnimations);
|
|
82347
82459
|
if (outcome.status === "blocked") return outcome;
|
|
@@ -82437,7 +82549,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
82437
82549
|
scaleDraftEl = el;
|
|
82438
82550
|
committedScale = useScaleLonghands ? { x: newScaleX, y: newScaleY } : { x: newScaleX, y: newScaleX };
|
|
82439
82551
|
if (el) {
|
|
82440
|
-
const dropRect = el.getBoundingClientRect();
|
|
82552
|
+
const dropRect = draw(() => el.getBoundingClientRect());
|
|
82441
82553
|
scaleDraftDropPoint = { x: dropRect.x, y: dropRect.y };
|
|
82442
82554
|
}
|
|
82443
82555
|
} else {
|
|
@@ -82449,39 +82561,50 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
82449
82561
|
}
|
|
82450
82562
|
const finalizeScaleResizeCommit = async () => {
|
|
82451
82563
|
if (!scaleDraftEl) return false;
|
|
82452
|
-
|
|
82453
|
-
if (!scaleDraftDropPoint || !selector)
|
|
82454
|
-
|
|
82455
|
-
|
|
82456
|
-
}
|
|
82457
|
-
const gsapPos = readGsapPositionFromIframe(iframe, selector) ?? { x: 0, y: 0 };
|
|
82458
|
-
const { baseGsapX, baseGsapY } = computeDraggedGsapPosition(
|
|
82459
|
-
selection.element,
|
|
82460
|
-
{ x: 0, y: 0 },
|
|
82461
|
-
gsapPos
|
|
82462
|
-
);
|
|
82463
|
-
const base2 = { x: baseGsapX, y: baseGsapY };
|
|
82464
|
-
setElementGsapPosition(scaleDraftEl, base2.x, base2.y);
|
|
82465
|
-
const post2 = scaleDraftEl.getBoundingClientRect();
|
|
82466
|
-
const residual = { x: scaleDraftDropPoint.x - post2.x, y: scaleDraftDropPoint.y - post2.y };
|
|
82467
|
-
if (!Number.isFinite(residual.x) || !Number.isFinite(residual.y)) return false;
|
|
82468
|
-
if (Math.abs(residual.x) < 0.5 && Math.abs(residual.y) < 0.5) {
|
|
82469
|
-
logResize("scale-finalize", { skipped: "already-on-drop-point", residual, base: base2 });
|
|
82470
|
-
return true;
|
|
82564
|
+
const draftEl = scaleDraftEl;
|
|
82565
|
+
if (!scaleDraftDropPoint || !selector) {
|
|
82566
|
+
draw(() => clearStudioBoxSize(draftEl));
|
|
82567
|
+
return false;
|
|
82471
82568
|
}
|
|
82472
|
-
const
|
|
82473
|
-
|
|
82474
|
-
|
|
82475
|
-
|
|
82476
|
-
|
|
82477
|
-
|
|
82478
|
-
|
|
82479
|
-
|
|
82480
|
-
|
|
82481
|
-
|
|
82482
|
-
|
|
82569
|
+
const dropPoint = scaleDraftDropPoint;
|
|
82570
|
+
const measured = draw(() => {
|
|
82571
|
+
clearStudioBoxSize(draftEl);
|
|
82572
|
+
if (committedScale) {
|
|
82573
|
+
setElementGsapScale(draftEl, committedScale.x, committedScale.y);
|
|
82574
|
+
}
|
|
82575
|
+
const gsapPos = readGsapPositionFromIframe(iframe, selector) ?? { x: 0, y: 0 };
|
|
82576
|
+
const { baseGsapX, baseGsapY } = computeDraggedGsapPosition(
|
|
82577
|
+
selection.element,
|
|
82578
|
+
{ x: 0, y: 0 },
|
|
82579
|
+
gsapPos
|
|
82580
|
+
);
|
|
82581
|
+
const base3 = { x: baseGsapX, y: baseGsapY };
|
|
82582
|
+
setElementGsapPosition(draftEl, base3.x, base3.y);
|
|
82583
|
+
const post2 = draftEl.getBoundingClientRect();
|
|
82584
|
+
const residual = { x: dropPoint.x - post2.x, y: dropPoint.y - post2.y };
|
|
82585
|
+
if (!Number.isFinite(residual.x) || !Number.isFinite(residual.y)) return null;
|
|
82586
|
+
if (Math.abs(residual.x) < 0.5 && Math.abs(residual.y) < 0.5) {
|
|
82587
|
+
logResize("scale-finalize", { skipped: "already-on-drop-point", residual, base: base3 });
|
|
82588
|
+
return "settled";
|
|
82589
|
+
}
|
|
82590
|
+
const corrected2 = {
|
|
82591
|
+
x: roundTo3(base3.x + residual.x),
|
|
82592
|
+
y: roundTo3(base3.y + residual.y)
|
|
82593
|
+
};
|
|
82594
|
+
logResize("scale-finalize", {
|
|
82595
|
+
dropPoint,
|
|
82596
|
+
post: { x: post2.x, y: post2.y },
|
|
82597
|
+
residual,
|
|
82598
|
+
gsapPos,
|
|
82599
|
+
base: base3,
|
|
82600
|
+
corrected: corrected2
|
|
82601
|
+
});
|
|
82602
|
+
setElementGsapPosition(draftEl, corrected2.x, corrected2.y);
|
|
82603
|
+
return { base: base3, corrected: corrected2 };
|
|
82483
82604
|
});
|
|
82484
|
-
|
|
82605
|
+
if (measured === null) return false;
|
|
82606
|
+
if (measured === "settled") return true;
|
|
82607
|
+
const { base: base2, corrected } = measured;
|
|
82485
82608
|
const currentAnimations = fetchFallbackAnimations ? await fetchFallbackAnimations() : resolved2?.animations ?? animations;
|
|
82486
82609
|
const delta = { x: corrected.x - base2.x, y: corrected.y - base2.y };
|
|
82487
82610
|
const positionTween = pickClosestToPlayhead(
|
|
@@ -82932,8 +83055,10 @@ function useGsapAwareEditing({
|
|
|
82932
83055
|
modifiers
|
|
82933
83056
|
);
|
|
82934
83057
|
await saveMove(outcome, async () => {
|
|
82935
|
-
const
|
|
82936
|
-
|
|
83058
|
+
const staged = writes.drawKeepingUndone(
|
|
83059
|
+
() => stageElementPositionOffset(selection, next, false)
|
|
83060
|
+
);
|
|
83061
|
+
writes.recordDomResult(await staged.save());
|
|
82937
83062
|
});
|
|
82938
83063
|
return writes.finish();
|
|
82939
83064
|
} catch (error) {
|
|
@@ -83006,11 +83131,8 @@ function useGsapAwareEditing({
|
|
|
83006
83131
|
);
|
|
83007
83132
|
await saveMove(dragOutcome, async () => {
|
|
83008
83133
|
const plainAfterSettle = editsPlainCss(selection.element, "move");
|
|
83009
|
-
anchorMove =
|
|
83010
|
-
selection,
|
|
83011
|
-
offset,
|
|
83012
|
-
plainAfterSettle,
|
|
83013
|
-
coalesceKey
|
|
83134
|
+
anchorMove = writes.drawKeepingUndone(
|
|
83135
|
+
() => stageElementPositionOffset(selection, offset, plainAfterSettle, coalesceKey)
|
|
83014
83136
|
);
|
|
83015
83137
|
});
|
|
83016
83138
|
}
|
|
@@ -83018,15 +83140,18 @@ function useGsapAwareEditing({
|
|
|
83018
83140
|
await runGestureTransaction({
|
|
83019
83141
|
element: selection.element,
|
|
83020
83142
|
label: "Resize layer",
|
|
83143
|
+
draw: writes.drawKeepingUndone,
|
|
83021
83144
|
settle: () => {
|
|
83022
83145
|
if (!offset || scaleRoute || !selector) return;
|
|
83023
|
-
|
|
83024
|
-
|
|
83025
|
-
|
|
83026
|
-
|
|
83027
|
-
|
|
83028
|
-
|
|
83029
|
-
|
|
83146
|
+
writes.drawKeepingUndone(() => {
|
|
83147
|
+
const gsapPos = readGsapPositionFromIframe(previewIframeRef.current, selector) ?? {
|
|
83148
|
+
x: 0,
|
|
83149
|
+
y: 0
|
|
83150
|
+
};
|
|
83151
|
+
const { newX, newY } = computeDraggedGsapPosition(selection.element, offset, gsapPos);
|
|
83152
|
+
logResize("sync-settle", { gsapPos, offset, newX, newY });
|
|
83153
|
+
setElementGsapPosition(selection.element, newX, newY);
|
|
83154
|
+
});
|
|
83030
83155
|
},
|
|
83031
83156
|
persist: async (commit, coalesceKey) => {
|
|
83032
83157
|
if (writes.commit) {
|
|
@@ -83039,16 +83164,13 @@ function useGsapAwareEditing({
|
|
|
83039
83164
|
previewIframeRef.current,
|
|
83040
83165
|
commitMutation2,
|
|
83041
83166
|
makeFetchFallback(selection),
|
|
83042
|
-
offset
|
|
83167
|
+
offset,
|
|
83168
|
+
writes.drawKeepingUndone
|
|
83043
83169
|
);
|
|
83044
83170
|
assertGsapEditPersisted(outcome);
|
|
83045
83171
|
if (outcome.status === "element-size") {
|
|
83046
|
-
const result = await
|
|
83047
|
-
selection,
|
|
83048
|
-
next,
|
|
83049
|
-
void 0,
|
|
83050
|
-
void 0,
|
|
83051
|
-
coalesceKey
|
|
83172
|
+
const result = await writes.drawKeepingUndone(
|
|
83173
|
+
() => handleDomBoxSizeCommit(selection, next, void 0, void 0, coalesceKey)
|
|
83052
83174
|
);
|
|
83053
83175
|
writes.recordDomResult(result);
|
|
83054
83176
|
} else cropUndoKey = coalesceKey;
|
|
@@ -83072,11 +83194,8 @@ function useGsapAwareEditing({
|
|
|
83072
83194
|
const anchorResult = await anchorMove?.save();
|
|
83073
83195
|
writes.recordDomResult(anchorResult);
|
|
83074
83196
|
if (cropUndoKey) {
|
|
83075
|
-
const cropResult = await
|
|
83076
|
-
stageCrop,
|
|
83077
|
-
selection,
|
|
83078
|
-
commitPositionPatchToHtml,
|
|
83079
|
-
cropUndoKey
|
|
83197
|
+
const cropResult = await writes.drawKeepingUndone(
|
|
83198
|
+
() => saveCropResize(stageCrop, selection, commitPositionPatchToHtml, cropUndoKey)
|
|
83080
83199
|
);
|
|
83081
83200
|
writes.recordDomResult(cropResult);
|
|
83082
83201
|
}
|