@hyperframes/studio 0.8.137 → 0.8.139
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-D_Mh6hbx.js → hyperframes-player-CckOoCJ8.js} +1 -1
- package/dist/assets/{index-CHEctGzc.js → index-BmIPrb8I.js} +1 -1
- package/dist/assets/{index-B3lJsA-e.js → index-Br1Whc0f.js} +189 -189
- package/dist/assets/{index-CC_E-Cbl.css → index-CVd4O6eH.css} +1 -1
- package/dist/assets/{index-rtccfg9b.js → index-DsEkE5_G.js} +1 -1
- package/dist/{chunk-4S3AYCOG.js → chunk-E422JDF5.js} +2 -2
- package/dist/{chunk-TDWGXBUT.js → chunk-TFLU2MGI.js} +1 -6
- package/dist/chunk-TFLU2MGI.js.map +1 -0
- package/dist/{chunk-7UQWVN52.js → chunk-UYWON5AX.js} +2 -2
- package/dist/{domEditingLayers-IEVLO54Z.js → domEditingLayers-KBTPQKGA.js} +3 -3
- package/dist/index.d.ts +2 -1
- package/dist/index.html +2 -2
- package/dist/index.js +867 -499
- package/dist/index.js.map +1 -1
- package/dist/player.js +2 -2
- package/dist/styles.css +1 -1
- package/package.json +9 -8
- package/src/App.tsx +11 -11
- package/src/components/editor/DomEditOverlay.tsx +9 -5
- package/src/components/editor/LayersPanel.test.ts +25 -0
- package/src/components/editor/LayersPanel.tsx +1 -1
- package/src/components/editor/PropertyPanel.test.tsx +600 -748
- package/src/components/editor/anchoredResizeCommitFeedsOffset.test.ts +2 -0
- package/src/components/editor/domEditOverlayGeometry.ts +7 -7
- package/src/components/editor/domEditOverlayGestures.ts +18 -0
- package/src/components/editor/domEditOverlayStartGesture.blocked.test.ts +1 -0
- package/src/components/editor/domEditOverlayStartGesture.test.ts +3 -0
- package/src/components/editor/domEditOverlayStartGesture.ts +9 -1
- package/src/components/editor/dragUndoPaint.test.ts +2 -0
- package/src/components/editor/gestureHoldsPreviewReload.test.tsx +432 -15
- package/src/components/editor/groupDropKeepsSelection.test.ts +1 -0
- package/src/components/editor/manualEditsDom.ts +7 -7
- package/src/components/editor/manualEditsTypes.ts +5 -0
- package/src/components/editor/manualOffsetDrag.test.ts +23 -0
- package/src/components/editor/manualOffsetDrag.ts +5 -0
- package/src/components/editor/previewGestureStarts.ts +284 -0
- package/src/components/editor/rotateInlineSave.test.ts +1 -0
- package/src/components/editor/shiftDragAxisLock.test.tsx +1 -0
- package/src/components/editor/useDomEditOverlayGestures.ts +67 -71
- package/src/components/nle/NLEContext.test.ts +26 -0
- package/src/components/nle/NLEContext.tsx +8 -3
- package/src/hooks/draggedGsapPosition.ts +8 -0
- package/src/hooks/editMoment.ts +13 -0
- package/src/hooks/gsapDragCommit.ts +2 -1
- package/src/hooks/gsapDragPositionCommit.ts +19 -7
- package/src/hooks/gsapPositionDetection.ts +5 -3
- package/src/hooks/gsapResizeIntercept.ts +11 -4
- package/src/hooks/gsapRuntimeBridge.ts +31 -11
- package/src/hooks/gsapValueAtPlayhead.test.ts +15 -0
- package/src/hooks/gsapValueAtPlayhead.ts +12 -5
- package/src/hooks/timelineEditingHelpers.test.ts +22 -0
- package/src/hooks/timelineEditingHelpers.ts +18 -2
- package/src/hooks/useConsoleErrorCapture.test.tsx +87 -0
- package/src/hooks/useConsoleErrorCapture.ts +18 -22
- package/src/hooks/useDomSelection.test.ts +21 -2
- package/src/hooks/useEditHistoryActions.test.tsx +20 -0
- package/src/hooks/useEditHistoryActions.ts +2 -0
- package/src/hooks/useGsapAwareEditing.test.tsx +38 -0
- package/src/hooks/useGsapAwareEditing.ts +148 -136
- package/src/hooks/useGsapAwareGroupMove.ts +126 -113
- package/src/hooks/useGsapScriptCommits.ts +5 -4
- package/src/hooks/usePreviewPersistence.history.test.tsx +7 -2
- package/src/hooks/usePreviewPersistence.ts +1 -4
- package/src/hooks/useTimelineDeleteOps.test.tsx +10 -0
- package/src/hooks/useTimelineDeleteOps.ts +9 -10
- package/src/index.ts +1 -0
- package/src/player/hooks/useShadowPreviewReload.ts +6 -6
- package/src/player/hooks/useTimelinePlayer.shadowReload.test.ts +14 -0
- package/src/player/hooks/useTimelinePlayer.ts +8 -5
- package/src/player/lib/thumbnailScheduler.test.ts +20 -1
- package/src/player/lib/thumbnailScheduler.ts +1 -1
- package/src/player/lib/timelineElementHelpers.ts +0 -11
- package/src/player/previewReloading.test.ts +48 -0
- package/src/player/previewReloading.ts +48 -0
- package/src/styles/studio.css +9 -0
- package/src/utils/gsapUndoRestore.browser.test.ts +21 -12
- package/src/utils/rootDuration.ts +5 -4
- package/src/utils/studioPendingEdits.test.ts +27 -0
- package/src/utils/studioPendingEdits.ts +9 -0
- package/src/utils/timelineAssetDrop.test.ts +13 -4
- package/src/utils/timelineAssetDrop.ts +6 -2
- package/dist/chunk-TDWGXBUT.js.map +0 -1
- /package/dist/{chunk-4S3AYCOG.js.map → chunk-E422JDF5.js.map} +0 -0
- /package/dist/{chunk-7UQWVN52.js.map → chunk-UYWON5AX.js.map} +0 -0
- /package/dist/{domEditingLayers-IEVLO54Z.js.map → domEditingLayers-KBTPQKGA.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ import {
|
|
|
39
39
|
usePreviewVariablesStore,
|
|
40
40
|
whenPreviewBooted,
|
|
41
41
|
writeStudioUiPreferences
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-E422JDF5.js";
|
|
43
43
|
import {
|
|
44
44
|
Button,
|
|
45
45
|
ContextMenu,
|
|
@@ -104,7 +104,7 @@ import {
|
|
|
104
104
|
resolveDomEditSelection,
|
|
105
105
|
serializeDomEditTextFields,
|
|
106
106
|
studioApiFetch
|
|
107
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-UYWON5AX.js";
|
|
108
108
|
import {
|
|
109
109
|
LAYER_REVEAL_PRIOR_POSITION_ATTR,
|
|
110
110
|
LAYER_REVEAL_PRIOR_Z_ATTR,
|
|
@@ -122,7 +122,6 @@ import {
|
|
|
122
122
|
findClipElementById,
|
|
123
123
|
formatCssColor,
|
|
124
124
|
furthestClipEndFromDocument,
|
|
125
|
-
furthestClipEndFromSource,
|
|
126
125
|
getAdapterDuration,
|
|
127
126
|
getDefaultStaticSeekPlaybackClock,
|
|
128
127
|
getSelectorIndex,
|
|
@@ -164,7 +163,7 @@ import {
|
|
|
164
163
|
splitTimelineElementKey,
|
|
165
164
|
toHexColor,
|
|
166
165
|
wrapTimeline
|
|
167
|
-
} from "./chunk-
|
|
166
|
+
} from "./chunk-TFLU2MGI.js";
|
|
168
167
|
import "./chunk-PZ5AY32C.js";
|
|
169
168
|
|
|
170
169
|
// src/components/EditorShell.tsx
|
|
@@ -3162,8 +3161,10 @@ var COMPOSITION_ROOT_OPEN_TAG_RE = /<[^>]*data-composition-id="[^"]+"[^>]*>/i;
|
|
|
3162
3161
|
var ROOT_COMPOSITION_OPEN_TAG_RE = /<[^>]*\bdata-composition-id(?=[\s=/>])[^>]*>/i;
|
|
3163
3162
|
var DATA_DURATION_ATTR_RE = /(\bdata-duration\s*=\s*)(["'])[^"']*\2/i;
|
|
3164
3163
|
function readRootCompositionDuration(source) {
|
|
3165
|
-
|
|
3166
|
-
|
|
3164
|
+
return rootCompositionDurationOf(new DOMParser().parseFromString(source, "text/html"));
|
|
3165
|
+
}
|
|
3166
|
+
function rootCompositionDurationOf(doc) {
|
|
3167
|
+
const raw = doc.querySelector("[data-composition-id]")?.getAttribute("data-duration");
|
|
3167
3168
|
if (raw == null) return null;
|
|
3168
3169
|
return Number.parseFloat(raw);
|
|
3169
3170
|
}
|
|
@@ -3260,9 +3261,9 @@ function buildTimelineAssetInsertHtml(input) {
|
|
|
3260
3261
|
}
|
|
3261
3262
|
return `<audio ${sharedAttrs} data-volume="1" style="z-index: ${input.zIndex}"></audio>`;
|
|
3262
3263
|
}
|
|
3263
|
-
function setCompositionDurationToContent(source, contentEnd) {
|
|
3264
|
+
function setCompositionDurationToContent(source, contentEnd, rootDuration) {
|
|
3264
3265
|
if (!Number.isFinite(contentEnd) || contentEnd <= 0) return source;
|
|
3265
|
-
const rootDur = readRootCompositionDuration(source);
|
|
3266
|
+
const rootDur = rootDuration === void 0 ? readRootCompositionDuration(source) : rootDuration;
|
|
3266
3267
|
if (rootDur == null) return source;
|
|
3267
3268
|
const next = roundToCenti(contentEnd);
|
|
3268
3269
|
if (rootDur === next) return source;
|
|
@@ -9443,6 +9444,13 @@ function setStudioPendingEditClaimClock(read2) {
|
|
|
9443
9444
|
historyClaims = read2 ?? (() => 0);
|
|
9444
9445
|
}
|
|
9445
9446
|
var NOT_SAVED = () => Promise.resolve(false);
|
|
9447
|
+
var cancelWaitingPress = null;
|
|
9448
|
+
function setStudioWaitingPressCancel(cancel) {
|
|
9449
|
+
cancelWaitingPress = cancel;
|
|
9450
|
+
}
|
|
9451
|
+
function cancelNewestStudioWaitingPress() {
|
|
9452
|
+
return cancelWaitingPress?.() ?? false;
|
|
9453
|
+
}
|
|
9446
9454
|
var adopting = null;
|
|
9447
9455
|
function adoptingStudioPendingEdit() {
|
|
9448
9456
|
return adopting;
|
|
@@ -15730,10 +15738,10 @@ var ThumbnailScheduler = class {
|
|
|
15730
15738
|
if (!scrolling) this.pump();
|
|
15731
15739
|
}
|
|
15732
15740
|
/** Holds composition renders while the preview loads: same server, and the preview is what the person awaits. */
|
|
15733
|
-
setPreviewReloading(
|
|
15734
|
-
if (this.previewReloading ===
|
|
15735
|
-
this.previewReloading =
|
|
15736
|
-
if (!
|
|
15741
|
+
setPreviewReloading(reloading2) {
|
|
15742
|
+
if (this.previewReloading === reloading2) return;
|
|
15743
|
+
this.previewReloading = reloading2;
|
|
15744
|
+
if (!reloading2) {
|
|
15737
15745
|
this.pump();
|
|
15738
15746
|
return;
|
|
15739
15747
|
}
|
|
@@ -15819,7 +15827,7 @@ var ThumbnailScheduler = class {
|
|
|
15819
15827
|
slotFree = true;
|
|
15820
15828
|
this.activeByBucket[bucket]--;
|
|
15821
15829
|
this.activeByKind[entry2.request.kind]--;
|
|
15822
|
-
this.pump();
|
|
15830
|
+
queueMicrotask(() => this.pump());
|
|
15823
15831
|
};
|
|
15824
15832
|
controller.signal.addEventListener("abort", freeSlot, { once: true });
|
|
15825
15833
|
this.notify(entry2);
|
|
@@ -18362,7 +18370,17 @@ function applyTimelineMoveAttributes(original, target, start, duration, track2,
|
|
|
18362
18370
|
return patched;
|
|
18363
18371
|
}
|
|
18364
18372
|
function syncCompositionDurationToContent(source) {
|
|
18365
|
-
return
|
|
18373
|
+
return syncCompositionDurationWithEnd(source).source;
|
|
18374
|
+
}
|
|
18375
|
+
function syncCompositionDurationWithEnd(source) {
|
|
18376
|
+
const doc = new DOMParser().parseFromString(source, "text/html");
|
|
18377
|
+
const contentEnd = furthestClipEndFromDocument(doc);
|
|
18378
|
+
const synced = setCompositionDurationToContent(
|
|
18379
|
+
source,
|
|
18380
|
+
contentEnd,
|
|
18381
|
+
rootCompositionDurationOf(doc)
|
|
18382
|
+
);
|
|
18383
|
+
return { source: synced, contentEnd };
|
|
18366
18384
|
}
|
|
18367
18385
|
function buildTimelineMoveTimingPatch(original, target, start, duration, track2, audioGroup) {
|
|
18368
18386
|
const patched = applyTimelineMoveAttributes(original, target, start, duration, track2, audioGroup);
|
|
@@ -29720,6 +29738,7 @@ import {
|
|
|
29720
29738
|
} from "@hyperframes/core/editing/draft-markers";
|
|
29721
29739
|
var STUDIO_ROTATION_PROP = "--hf-studio-rotation";
|
|
29722
29740
|
var STUDIO_PATH_OFFSET_ATTR = "data-hf-studio-path-offset";
|
|
29741
|
+
var STUDIO_EDIT_MOMENT_ATTR = "data-hf-studio-edit-at";
|
|
29723
29742
|
var STUDIO_BOX_SIZE_ATTR = "data-hf-studio-box-size";
|
|
29724
29743
|
var STUDIO_ROTATION_ATTR = "data-hf-studio-rotation";
|
|
29725
29744
|
var STUDIO_ORIGINAL_TRANSLATE_ATTR = "data-hf-studio-original-translate";
|
|
@@ -30432,10 +30451,12 @@ var GESTURE_DRAWS = {
|
|
|
30432
30451
|
rotate: ["rotate", "transform", "transform-origin", "display", STUDIO_ROTATION_PROP],
|
|
30433
30452
|
edit: []
|
|
30434
30453
|
};
|
|
30435
|
-
function beginStudioManualEditGesture(element, draws) {
|
|
30454
|
+
function beginStudioManualEditGesture(element, draws, at) {
|
|
30436
30455
|
studioManualEditGestureId += 1;
|
|
30437
30456
|
const token = `gesture-${studioManualEditGestureId}:${draws}`;
|
|
30438
30457
|
element.setAttribute(STUDIO_MANUAL_EDIT_GESTURE_ATTR, token);
|
|
30458
|
+
if (at) element.setAttribute(STUDIO_EDIT_MOMENT_ATTR, JSON.stringify(at));
|
|
30459
|
+
else element.removeAttribute(STUDIO_EDIT_MOMENT_ATTR);
|
|
30439
30460
|
return token;
|
|
30440
30461
|
}
|
|
30441
30462
|
var GESTURE_ENDED = "hf-manual-edit-gesture-ended";
|
|
@@ -30443,6 +30464,7 @@ function endStudioManualEditGesture(element, token) {
|
|
|
30443
30464
|
if (token && element.getAttribute(STUDIO_MANUAL_EDIT_GESTURE_ATTR) !== token) return;
|
|
30444
30465
|
if (!element.hasAttribute(STUDIO_MANUAL_EDIT_GESTURE_ATTR)) return;
|
|
30445
30466
|
element.removeAttribute(STUDIO_MANUAL_EDIT_GESTURE_ATTR);
|
|
30467
|
+
element.removeAttribute(STUDIO_EDIT_MOMENT_ATTR);
|
|
30446
30468
|
const doc = element.ownerDocument;
|
|
30447
30469
|
doc.dispatchEvent(new (doc.defaultView?.Event ?? Event)(GESTURE_ENDED));
|
|
30448
30470
|
}
|
|
@@ -30848,6 +30870,43 @@ function makeStudioDebugLogger(name) {
|
|
|
30848
30870
|
// src/utils/reloadDebug.ts
|
|
30849
30871
|
var logReload = makeStudioDebugLogger("reload");
|
|
30850
30872
|
|
|
30873
|
+
// src/player/previewReloading.ts
|
|
30874
|
+
var reloading = false;
|
|
30875
|
+
var reloadRequested = false;
|
|
30876
|
+
var scriptWrites = 0;
|
|
30877
|
+
var givenUp = false;
|
|
30878
|
+
var changing = () => reloading || reloadRequested || scriptWrites > 0;
|
|
30879
|
+
var noteIdle = () => {
|
|
30880
|
+
if (!changing()) givenUp = false;
|
|
30881
|
+
};
|
|
30882
|
+
function giveUpOnPreviewChange() {
|
|
30883
|
+
givenUp = changing();
|
|
30884
|
+
}
|
|
30885
|
+
function setPreviewReloading(next) {
|
|
30886
|
+
reloading = next;
|
|
30887
|
+
thumbnailScheduler.setPreviewReloading(next);
|
|
30888
|
+
noteIdle();
|
|
30889
|
+
}
|
|
30890
|
+
function requestPreviewReload() {
|
|
30891
|
+
reloadRequested = true;
|
|
30892
|
+
}
|
|
30893
|
+
function previewReloadBegun() {
|
|
30894
|
+
reloadRequested = false;
|
|
30895
|
+
noteIdle();
|
|
30896
|
+
}
|
|
30897
|
+
async function whileScriptWrites(write) {
|
|
30898
|
+
scriptWrites += 1;
|
|
30899
|
+
try {
|
|
30900
|
+
return await write();
|
|
30901
|
+
} finally {
|
|
30902
|
+
scriptWrites -= 1;
|
|
30903
|
+
noteIdle();
|
|
30904
|
+
}
|
|
30905
|
+
}
|
|
30906
|
+
function isPreviewChanging() {
|
|
30907
|
+
return changing() && !givenUp;
|
|
30908
|
+
}
|
|
30909
|
+
|
|
30851
30910
|
// src/player/sceneSwap.ts
|
|
30852
30911
|
var SCENES_SWAPPED = "hf-scenes-swapped";
|
|
30853
30912
|
var SCENE_SWAP_MS = 5e3;
|
|
@@ -30990,7 +31049,7 @@ function useShadowPreviewReload({
|
|
|
30990
31049
|
isRefreshingRef.current = false;
|
|
30991
31050
|
pendingSeekRef.current = null;
|
|
30992
31051
|
setPreviewSlots(planShadowDiscard);
|
|
30993
|
-
|
|
31052
|
+
setPreviewReloading(false);
|
|
30994
31053
|
const message = `The preview did not reload (${cause}). The previous preview is still showing.`;
|
|
30995
31054
|
logReload("shadow-failed", { cause });
|
|
30996
31055
|
console.error(`[studio] ${message}`);
|
|
@@ -31061,7 +31120,7 @@ function useShadowPreviewReload({
|
|
|
31061
31120
|
if (liveTime2 != null) handOverPlaybackRef.current(liveTime2, playing);
|
|
31062
31121
|
announcePreviewPromoted({ retired, live: shadow });
|
|
31063
31122
|
onPromotedRef.current?.();
|
|
31064
|
-
|
|
31123
|
+
setPreviewReloading(false);
|
|
31065
31124
|
},
|
|
31066
31125
|
[
|
|
31067
31126
|
stopPendingShadow,
|
|
@@ -31152,7 +31211,7 @@ function useShadowPreviewReload({
|
|
|
31152
31211
|
savesAtRequestRef.current = gestureSavesOnScreen();
|
|
31153
31212
|
armReadyTimer(gen);
|
|
31154
31213
|
setPreviewSlots((prev) => planShadowReload(prev, gen, url));
|
|
31155
|
-
|
|
31214
|
+
setPreviewReloading(true);
|
|
31156
31215
|
},
|
|
31157
31216
|
[stopPendingShadow, armReadyTimer, gestureSavesOnScreen]
|
|
31158
31217
|
);
|
|
@@ -31165,7 +31224,7 @@ function useShadowPreviewReload({
|
|
|
31165
31224
|
pendingSeekRef.current = null;
|
|
31166
31225
|
usePlayerStore.getState().setTimelineReady(false);
|
|
31167
31226
|
setPreviewSlots(planShadowDiscard);
|
|
31168
|
-
|
|
31227
|
+
setPreviewReloading(false);
|
|
31169
31228
|
}, [stopPendingShadow, isRefreshingRef, pendingSeekRef]);
|
|
31170
31229
|
useMountEffect(() => {
|
|
31171
31230
|
const onVisibilityChange = () => {
|
|
@@ -31180,7 +31239,7 @@ function useShadowPreviewReload({
|
|
|
31180
31239
|
return () => {
|
|
31181
31240
|
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
31182
31241
|
stopPendingShadow();
|
|
31183
|
-
|
|
31242
|
+
setPreviewReloading(false);
|
|
31184
31243
|
};
|
|
31185
31244
|
});
|
|
31186
31245
|
return {
|
|
@@ -32043,11 +32102,13 @@ function useTimelinePlayer({
|
|
|
32043
32102
|
const swapWouldReplaceGestureNode = !!iframe.contentDocument && isStudioManualEditGestureLiveIn(iframe.contentDocument);
|
|
32044
32103
|
if (!swap || isRefreshingRef.current || swapWouldReplaceGestureNode)
|
|
32045
32104
|
return reloadWholeFilm(url.toString());
|
|
32046
|
-
swap(url.toString(), isCurrent, cancel.signal).catch(
|
|
32047
|
-
|
|
32048
|
-
|
|
32049
|
-
|
|
32050
|
-
|
|
32105
|
+
whileScriptWrites(() => swap(url.toString(), isCurrent, cancel.signal)).catch(
|
|
32106
|
+
(error) => {
|
|
32107
|
+
if (!isCurrent()) return;
|
|
32108
|
+
logReload("scene-swap-refused", { reason: String(error) });
|
|
32109
|
+
reloadWholeFilm(url.toString());
|
|
32110
|
+
}
|
|
32111
|
+
);
|
|
32051
32112
|
}, [reloadWholeFilm, previewGeneration]);
|
|
32052
32113
|
const pauseRef = useRef47(pause);
|
|
32053
32114
|
pauseRef.current = pause;
|
|
@@ -32293,9 +32354,13 @@ function NLEProvider({
|
|
|
32293
32354
|
const [previewCompositionSize, setPreviewCompositionSize] = useState35(null);
|
|
32294
32355
|
const prevRefreshKeyRef = useRef49(refreshKey);
|
|
32295
32356
|
useEffect37(() => {
|
|
32296
|
-
|
|
32297
|
-
|
|
32298
|
-
|
|
32357
|
+
try {
|
|
32358
|
+
if (refreshKey === prevRefreshKeyRef.current) return;
|
|
32359
|
+
prevRefreshKeyRef.current = refreshKey;
|
|
32360
|
+
refreshPlayer();
|
|
32361
|
+
} finally {
|
|
32362
|
+
previewReloadBegun();
|
|
32363
|
+
}
|
|
32299
32364
|
}, [refreshKey, refreshPlayer]);
|
|
32300
32365
|
const afterLiveIframeLoad = useCallback44(() => {
|
|
32301
32366
|
ensureMotionPathPluginLoaded(iframeRef.current);
|
|
@@ -35975,6 +36040,11 @@ function readThroughPass(memo61, key2, compute) {
|
|
|
35975
36040
|
|
|
35976
36041
|
// src/components/editor/domEditOverlayGeometry.ts
|
|
35977
36042
|
var RESIZE_HANDLE_HIT_PX = 16;
|
|
36043
|
+
var shiftedOverlayRect = (rect, dx, dy) => ({
|
|
36044
|
+
...rect,
|
|
36045
|
+
left: rect.left + dx,
|
|
36046
|
+
top: rect.top + dy
|
|
36047
|
+
});
|
|
35978
36048
|
function isElementVisibleForOverlay(el) {
|
|
35979
36049
|
return isElementVisibleThroughAncestors(el);
|
|
35980
36050
|
}
|
|
@@ -36264,6 +36334,7 @@ var ROTATED_SNAP_BYPASS_DEGREES = 0.5;
|
|
|
36264
36334
|
function movesGesture(gesture, e) {
|
|
36265
36335
|
return e.pointerId === gesture.pointerId && (e.buttons & 1) === 1;
|
|
36266
36336
|
}
|
|
36337
|
+
var PRESS_WAITING_ATTR = "data-dom-edit-press-waiting";
|
|
36267
36338
|
function focusDomEditOverlayElement(element) {
|
|
36268
36339
|
element?.focus({ preventScroll: true });
|
|
36269
36340
|
}
|
|
@@ -36893,7 +36964,7 @@ function OffCanvasIndicators({
|
|
|
36893
36964
|
const selectOffCanvas = async () => {
|
|
36894
36965
|
const el = elements.current.get(r.key);
|
|
36895
36966
|
if (!el) return;
|
|
36896
|
-
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-
|
|
36967
|
+
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-KBTPQKGA.js");
|
|
36897
36968
|
const acp = activeCompositionPathRef.current ?? "index.html";
|
|
36898
36969
|
const sel = await resolveDomEditSelection2(el, {
|
|
36899
36970
|
activeCompositionPath: acp,
|
|
@@ -36947,6 +37018,68 @@ function ChildRectOutlines({
|
|
|
36947
37018
|
)) });
|
|
36948
37019
|
}
|
|
36949
37020
|
|
|
37021
|
+
// src/components/editor/domEditResizeLocal.ts
|
|
37022
|
+
var MIN_RESIZE_LOCAL_PX = 1;
|
|
37023
|
+
var DEGENERATE_START_DIST_PX = 3;
|
|
37024
|
+
function resolveCenterResizeScale(input) {
|
|
37025
|
+
const startDist = Math.hypot(
|
|
37026
|
+
input.pointerStart.x - input.centerStart.x,
|
|
37027
|
+
input.pointerStart.y - input.centerStart.y
|
|
37028
|
+
);
|
|
37029
|
+
if (!Number.isFinite(startDist) || startDist < DEGENERATE_START_DIST_PX) return 1;
|
|
37030
|
+
const nowDist = Math.hypot(
|
|
37031
|
+
input.pointer.x - input.centerStart.x,
|
|
37032
|
+
input.pointer.y - input.centerStart.y
|
|
37033
|
+
);
|
|
37034
|
+
return nowDist / startDist;
|
|
37035
|
+
}
|
|
37036
|
+
function resolveCenterResizeSize(input) {
|
|
37037
|
+
const baseWidth = Math.max(input.baseWidth, MIN_RESIZE_LOCAL_PX);
|
|
37038
|
+
const baseHeight = Math.max(input.baseHeight, MIN_RESIZE_LOCAL_PX);
|
|
37039
|
+
const rawScale = resolveCenterResizeScale({
|
|
37040
|
+
pointer: input.pointer,
|
|
37041
|
+
pointerStart: input.pointerStart,
|
|
37042
|
+
centerStart: input.centerStart
|
|
37043
|
+
});
|
|
37044
|
+
const minScale = MIN_RESIZE_LOCAL_PX / Math.min(baseWidth, baseHeight);
|
|
37045
|
+
const scale = Math.max(minScale, rawScale);
|
|
37046
|
+
return { width: baseWidth * scale, height: baseHeight * scale };
|
|
37047
|
+
}
|
|
37048
|
+
var CURSORS_8 = [
|
|
37049
|
+
"ns-resize",
|
|
37050
|
+
// 0° (up)
|
|
37051
|
+
"nesw-resize",
|
|
37052
|
+
// 45°
|
|
37053
|
+
"ew-resize",
|
|
37054
|
+
// 90° (right)
|
|
37055
|
+
"nwse-resize",
|
|
37056
|
+
// 135°
|
|
37057
|
+
"ns-resize",
|
|
37058
|
+
// 180° (down)
|
|
37059
|
+
"nesw-resize",
|
|
37060
|
+
// 225°
|
|
37061
|
+
"ew-resize",
|
|
37062
|
+
// 270° (left)
|
|
37063
|
+
"nwse-resize"
|
|
37064
|
+
// 315°
|
|
37065
|
+
];
|
|
37066
|
+
var CORNER_BASE_ANGLE_DEG = {
|
|
37067
|
+
nw: 315,
|
|
37068
|
+
ne: 45,
|
|
37069
|
+
se: 135,
|
|
37070
|
+
sw: 225
|
|
37071
|
+
};
|
|
37072
|
+
function resolveRotatedResizeCursor(handle, rotationDeg) {
|
|
37073
|
+
const angle = CORNER_BASE_ANGLE_DEG[handle] + rotationDeg;
|
|
37074
|
+
const normalized = (angle % 360 + 360) % 360;
|
|
37075
|
+
const bucket = Math.round(normalized / 45) % 8;
|
|
37076
|
+
return CURSORS_8[bucket];
|
|
37077
|
+
}
|
|
37078
|
+
function computeNextResizeAnchor(prev, fixedStart, fixedNow) {
|
|
37079
|
+
const base2 = prev ?? { dx: 0, dy: 0 };
|
|
37080
|
+
return { dx: base2.dx + (fixedStart.x - fixedNow.x), dy: base2.dy + (fixedStart.y - fixedNow.y) };
|
|
37081
|
+
}
|
|
37082
|
+
|
|
36950
37083
|
// src/components/editor/manualOffsetDrag.ts
|
|
36951
37084
|
import { isHtmlElement as isHtmlElement6 } from "@hyperframes/core/runtime/dom-realm";
|
|
36952
37085
|
|
|
@@ -37542,9 +37675,14 @@ function readDragStamp(element) {
|
|
|
37542
37675
|
origX: read2("data-hf-drag-initial-offset-x") || 0,
|
|
37543
37676
|
origY: read2("data-hf-drag-initial-offset-y") || 0,
|
|
37544
37677
|
baseX: read2("data-hf-drag-gsap-base-x"),
|
|
37545
|
-
baseY: read2("data-hf-drag-gsap-base-y")
|
|
37678
|
+
baseY: read2("data-hf-drag-gsap-base-y"),
|
|
37679
|
+
at: readEditMoment(element)
|
|
37546
37680
|
};
|
|
37547
37681
|
}
|
|
37682
|
+
function readEditMoment(element) {
|
|
37683
|
+
const raw = element.getAttribute(STUDIO_EDIT_MOMENT_ATTR);
|
|
37684
|
+
return raw ? JSON.parse(raw) : void 0;
|
|
37685
|
+
}
|
|
37548
37686
|
var freezeDragStamp = (element) => ({
|
|
37549
37687
|
...readDragStamp(element),
|
|
37550
37688
|
frozen: true
|
|
@@ -37876,7 +38014,8 @@ function createManualOffsetDragMember(input) {
|
|
|
37876
38014
|
const initialPathOffset = captureStudioPathOffset(input.element);
|
|
37877
38015
|
const gestureToken = beginStudioManualEditGesture(
|
|
37878
38016
|
input.element,
|
|
37879
|
-
input.gesture === "resize" ? "resize" : "move"
|
|
38017
|
+
input.gesture === "resize" ? "resize" : "move",
|
|
38018
|
+
input.at
|
|
37880
38019
|
);
|
|
37881
38020
|
const measured = measureManualOffsetDragScreenToOffsetMatrix(input.element, initialOffset, {
|
|
37882
38021
|
scaleX: input.rect.editScaleX,
|
|
@@ -37991,6 +38130,7 @@ function settleDraftTranslate(element, gsapOwnsPosition) {
|
|
|
37991
38130
|
}
|
|
37992
38131
|
function endManualOffsetDragMembers(members) {
|
|
37993
38132
|
for (const member of members) {
|
|
38133
|
+
if (!isStudioManualEditGestureCurrent(member.element, member.gestureToken)) continue;
|
|
37994
38134
|
endStudioManualEditGesture(member.element, member.gestureToken);
|
|
37995
38135
|
member.element.removeAttribute("data-hf-drag-initial-offset-x");
|
|
37996
38136
|
member.element.removeAttribute("data-hf-drag-initial-offset-y");
|
|
@@ -38170,119 +38310,6 @@ function readRotationBase(element, plain) {
|
|
|
38170
38310
|
return gsapRotation + readStudioRotation(element).angle;
|
|
38171
38311
|
}
|
|
38172
38312
|
|
|
38173
|
-
// src/components/editor/domEditResizeLocal.ts
|
|
38174
|
-
var MIN_RESIZE_LOCAL_PX = 1;
|
|
38175
|
-
var DEGENERATE_START_DIST_PX = 3;
|
|
38176
|
-
function resolveCenterResizeScale(input) {
|
|
38177
|
-
const startDist = Math.hypot(
|
|
38178
|
-
input.pointerStart.x - input.centerStart.x,
|
|
38179
|
-
input.pointerStart.y - input.centerStart.y
|
|
38180
|
-
);
|
|
38181
|
-
if (!Number.isFinite(startDist) || startDist < DEGENERATE_START_DIST_PX) return 1;
|
|
38182
|
-
const nowDist = Math.hypot(
|
|
38183
|
-
input.pointer.x - input.centerStart.x,
|
|
38184
|
-
input.pointer.y - input.centerStart.y
|
|
38185
|
-
);
|
|
38186
|
-
return nowDist / startDist;
|
|
38187
|
-
}
|
|
38188
|
-
function resolveCenterResizeSize(input) {
|
|
38189
|
-
const baseWidth = Math.max(input.baseWidth, MIN_RESIZE_LOCAL_PX);
|
|
38190
|
-
const baseHeight = Math.max(input.baseHeight, MIN_RESIZE_LOCAL_PX);
|
|
38191
|
-
const rawScale = resolveCenterResizeScale({
|
|
38192
|
-
pointer: input.pointer,
|
|
38193
|
-
pointerStart: input.pointerStart,
|
|
38194
|
-
centerStart: input.centerStart
|
|
38195
|
-
});
|
|
38196
|
-
const minScale = MIN_RESIZE_LOCAL_PX / Math.min(baseWidth, baseHeight);
|
|
38197
|
-
const scale = Math.max(minScale, rawScale);
|
|
38198
|
-
return { width: baseWidth * scale, height: baseHeight * scale };
|
|
38199
|
-
}
|
|
38200
|
-
var CURSORS_8 = [
|
|
38201
|
-
"ns-resize",
|
|
38202
|
-
// 0° (up)
|
|
38203
|
-
"nesw-resize",
|
|
38204
|
-
// 45°
|
|
38205
|
-
"ew-resize",
|
|
38206
|
-
// 90° (right)
|
|
38207
|
-
"nwse-resize",
|
|
38208
|
-
// 135°
|
|
38209
|
-
"ns-resize",
|
|
38210
|
-
// 180° (down)
|
|
38211
|
-
"nesw-resize",
|
|
38212
|
-
// 225°
|
|
38213
|
-
"ew-resize",
|
|
38214
|
-
// 270° (left)
|
|
38215
|
-
"nwse-resize"
|
|
38216
|
-
// 315°
|
|
38217
|
-
];
|
|
38218
|
-
var CORNER_BASE_ANGLE_DEG = {
|
|
38219
|
-
nw: 315,
|
|
38220
|
-
ne: 45,
|
|
38221
|
-
se: 135,
|
|
38222
|
-
sw: 225
|
|
38223
|
-
};
|
|
38224
|
-
function resolveRotatedResizeCursor(handle, rotationDeg) {
|
|
38225
|
-
const angle = CORNER_BASE_ANGLE_DEG[handle] + rotationDeg;
|
|
38226
|
-
const normalized = (angle % 360 + 360) % 360;
|
|
38227
|
-
const bucket = Math.round(normalized / 45) % 8;
|
|
38228
|
-
return CURSORS_8[bucket];
|
|
38229
|
-
}
|
|
38230
|
-
function computeNextResizeAnchor(prev, fixedStart, fixedNow) {
|
|
38231
|
-
const base2 = prev ?? { dx: 0, dy: 0 };
|
|
38232
|
-
return { dx: base2.dx + (fixedStart.x - fixedNow.x), dy: base2.dy + (fixedStart.y - fixedNow.y) };
|
|
38233
|
-
}
|
|
38234
|
-
|
|
38235
|
-
// src/components/editor/resizeDraft.ts
|
|
38236
|
-
function resolveResizeAnchor(g, corners, measureOrientedRect) {
|
|
38237
|
-
const fixedStart = g.resizeFixedCenterStart;
|
|
38238
|
-
if (corners && fixedStart) {
|
|
38239
|
-
return computeNextResizeAnchor(g.lastResizeAnchor, fixedStart, overlayCornersCentroid(corners));
|
|
38240
|
-
}
|
|
38241
|
-
const fallbackRect = measureOrientedRect();
|
|
38242
|
-
return resolveResizeCenterAnchorOffset({
|
|
38243
|
-
originWidth: g.originWidth,
|
|
38244
|
-
originHeight: g.originHeight,
|
|
38245
|
-
overlayWidth: fallbackRect ? fallbackRect.width : g.originWidth,
|
|
38246
|
-
overlayHeight: fallbackRect ? fallbackRect.height : g.originHeight
|
|
38247
|
-
});
|
|
38248
|
-
}
|
|
38249
|
-
function resolveAnchoredResizeDraft(g, member, element, overlayEl, iframe, measureOrientedRect) {
|
|
38250
|
-
const corners = overlayEl && iframe ? elementCornerOverlayPoints(overlayEl, iframe, element) : null;
|
|
38251
|
-
const anchor2 = resolveResizeAnchor(g, corners, measureOrientedRect);
|
|
38252
|
-
g.lastResizeAnchor = anchor2;
|
|
38253
|
-
applyManualOffsetDragDraft(member, anchor2.dx, anchor2.dy);
|
|
38254
|
-
return measureOrientedRect() ?? {
|
|
38255
|
-
left: g.originLeft + anchor2.dx,
|
|
38256
|
-
top: g.originTop + anchor2.dy,
|
|
38257
|
-
width: corners ? cornerEdgeLength(corners.nw, corners.ne) : g.originWidth,
|
|
38258
|
-
height: corners ? cornerEdgeLength(corners.nw, corners.sw) : g.originHeight,
|
|
38259
|
-
editScaleX: g.editScaleX,
|
|
38260
|
-
editScaleY: g.editScaleY,
|
|
38261
|
-
angle: g.actualRotation
|
|
38262
|
-
};
|
|
38263
|
-
}
|
|
38264
|
-
function resolveResizeDraftRect(g, element, overlayEl, iframe, measureOrientedRect) {
|
|
38265
|
-
if (g.pathOffsetMember) {
|
|
38266
|
-
return resolveAnchoredResizeDraft(
|
|
38267
|
-
g,
|
|
38268
|
-
g.pathOffsetMember,
|
|
38269
|
-
element,
|
|
38270
|
-
overlayEl,
|
|
38271
|
-
iframe,
|
|
38272
|
-
measureOrientedRect
|
|
38273
|
-
);
|
|
38274
|
-
}
|
|
38275
|
-
return measureOrientedRect() ?? {
|
|
38276
|
-
left: g.originLeft,
|
|
38277
|
-
top: g.originTop,
|
|
38278
|
-
width: g.originWidth,
|
|
38279
|
-
height: g.originHeight,
|
|
38280
|
-
editScaleX: g.editScaleX,
|
|
38281
|
-
editScaleY: g.editScaleY,
|
|
38282
|
-
angle: g.actualRotation
|
|
38283
|
-
};
|
|
38284
|
-
}
|
|
38285
|
-
|
|
38286
38313
|
// src/components/editor/snapEngine.ts
|
|
38287
38314
|
var SNAP_THRESHOLD_PX = 6;
|
|
38288
38315
|
var SNAP_ENGAGE_TRAVEL_PX = 4;
|
|
@@ -38760,7 +38787,7 @@ function notifyBlockedPress(e, opts, selection) {
|
|
|
38760
38787
|
if (e.button !== 0 || selection.capabilities.commitCheckPending) return;
|
|
38761
38788
|
opts.onBlockedMoveRef.current(selection);
|
|
38762
38789
|
}
|
|
38763
|
-
function startGroupDrag(e, opts) {
|
|
38790
|
+
function startGroupDrag(e, opts, at) {
|
|
38764
38791
|
const items = opts.groupOverlayItemsRef.current;
|
|
38765
38792
|
if (items.length <= 1) return false;
|
|
38766
38793
|
const blockedSelection = items.find(
|
|
@@ -38781,7 +38808,8 @@ function startGroupDrag(e, opts) {
|
|
|
38781
38808
|
selection: item.selection,
|
|
38782
38809
|
element: item.element,
|
|
38783
38810
|
rect: item.rect,
|
|
38784
|
-
gesture: "drag"
|
|
38811
|
+
gesture: "drag",
|
|
38812
|
+
at
|
|
38785
38813
|
});
|
|
38786
38814
|
if (!result.ok) {
|
|
38787
38815
|
restoreManualOffsetDragMembers(members);
|
|
@@ -38839,6 +38867,7 @@ function startGroupDrag(e, opts) {
|
|
|
38839
38867
|
return true;
|
|
38840
38868
|
}
|
|
38841
38869
|
function startGesture(kind, e, opts, options) {
|
|
38870
|
+
const at = options?.at;
|
|
38842
38871
|
const sel = options?.selection ?? opts.selectionRef.current;
|
|
38843
38872
|
const rect = options?.rect ?? opts.overlayRectRef.current;
|
|
38844
38873
|
const box = opts.boxRef.current;
|
|
@@ -38874,7 +38903,8 @@ function startGesture(kind, e, opts, options) {
|
|
|
38874
38903
|
selection: sel,
|
|
38875
38904
|
element: sel.element,
|
|
38876
38905
|
rect,
|
|
38877
|
-
gesture: "drag"
|
|
38906
|
+
gesture: "drag",
|
|
38907
|
+
at
|
|
38878
38908
|
});
|
|
38879
38909
|
if (!result.ok) {
|
|
38880
38910
|
opts.onBlockedMoveRef.current(result.selection, result.reason);
|
|
@@ -38892,7 +38922,8 @@ function startGesture(kind, e, opts, options) {
|
|
|
38892
38922
|
selection: sel,
|
|
38893
38923
|
element: sel.element,
|
|
38894
38924
|
rect,
|
|
38895
|
-
gesture: "resize"
|
|
38925
|
+
gesture: "resize",
|
|
38926
|
+
at
|
|
38896
38927
|
});
|
|
38897
38928
|
if (result.ok) {
|
|
38898
38929
|
pathOffsetMember = result.member;
|
|
@@ -38900,12 +38931,13 @@ function startGesture(kind, e, opts, options) {
|
|
|
38900
38931
|
manualEditDragToken = result.member.gestureToken;
|
|
38901
38932
|
if (result.member.plainTranslate) applyManualOffsetDragDraft(result.member, 0, 0);
|
|
38902
38933
|
} else {
|
|
38903
|
-
manualEditDragToken = beginStudioManualEditGesture(sel.element, "resize");
|
|
38934
|
+
manualEditDragToken = beginStudioManualEditGesture(sel.element, "resize", at);
|
|
38904
38935
|
}
|
|
38905
38936
|
} else {
|
|
38906
38937
|
manualEditDragToken = beginStudioManualEditGesture(
|
|
38907
38938
|
sel.element,
|
|
38908
|
-
kind === "rotate" ? "rotate" : "resize"
|
|
38939
|
+
kind === "rotate" ? "rotate" : "resize",
|
|
38940
|
+
at
|
|
38909
38941
|
);
|
|
38910
38942
|
}
|
|
38911
38943
|
}
|
|
@@ -38988,6 +39020,274 @@ function startGesture(kind, e, opts, options) {
|
|
|
38988
39020
|
return true;
|
|
38989
39021
|
}
|
|
38990
39022
|
|
|
39023
|
+
// src/hooks/editMoment.ts
|
|
39024
|
+
function playheadMoment() {
|
|
39025
|
+
const { currentTime, activeKeyframePct } = usePlayerStore.getState();
|
|
39026
|
+
return { time: currentTime, keyframePct: activeKeyframePct };
|
|
39027
|
+
}
|
|
39028
|
+
function editMoment(stamp) {
|
|
39029
|
+
return stamp?.at ?? playheadMoment();
|
|
39030
|
+
}
|
|
39031
|
+
|
|
39032
|
+
// src/components/editor/previewGestureStarts.ts
|
|
39033
|
+
var MAX_SETTLED_WAIT_FRAMES = 60;
|
|
39034
|
+
var PRESS_WAIT_MAX_MS = 1e4;
|
|
39035
|
+
function createPreviewGestureStarts(opts, moveActiveGesture, releaseActiveGesture) {
|
|
39036
|
+
const offerUndo = () => {
|
|
39037
|
+
let p = opts.waitingPressRef.current;
|
|
39038
|
+
while (p && !p.released) p = p.after;
|
|
39039
|
+
const press = p;
|
|
39040
|
+
setStudioWaitingPressCancel(press && (() => dropPress(press)));
|
|
39041
|
+
};
|
|
39042
|
+
const clearWaitingMark = () => {
|
|
39043
|
+
opts.boxRef.current?.removeAttribute(PRESS_WAITING_ATTR);
|
|
39044
|
+
opts.rafPausedRef.current = false;
|
|
39045
|
+
};
|
|
39046
|
+
const unlink = (press, next) => {
|
|
39047
|
+
for (let p = opts.waitingPressRef.current; p; p = p.after)
|
|
39048
|
+
if (p.after === press) p.after = next;
|
|
39049
|
+
};
|
|
39050
|
+
const endWaitingPress = (press = opts.waitingPressRef.current) => {
|
|
39051
|
+
for (let p = press; p && !p.ended; p = p.after) {
|
|
39052
|
+
p.ended = true;
|
|
39053
|
+
cancelAnimationFrame(p.frame);
|
|
39054
|
+
}
|
|
39055
|
+
if (press === opts.waitingPressRef.current) {
|
|
39056
|
+
opts.waitingPressRef.current = null;
|
|
39057
|
+
clearWaitingMark();
|
|
39058
|
+
} else if (press) unlink(press, null);
|
|
39059
|
+
offerUndo();
|
|
39060
|
+
};
|
|
39061
|
+
const showPressBefore = (press) => {
|
|
39062
|
+
const before = press.after;
|
|
39063
|
+
opts.waitingPressRef.current = before;
|
|
39064
|
+
const shown2 = before ?? press;
|
|
39065
|
+
const at = before?.moved;
|
|
39066
|
+
const [dx, dy] = at ? [at.clientX - shown2.startX, at.clientY - shown2.startY] : [0, 0];
|
|
39067
|
+
shown2.draw?.(dx, dy);
|
|
39068
|
+
if (!before) clearWaitingMark();
|
|
39069
|
+
};
|
|
39070
|
+
const dropPress = (press) => {
|
|
39071
|
+
if (press.ended) return false;
|
|
39072
|
+
press.ended = true;
|
|
39073
|
+
cancelAnimationFrame(press.frame);
|
|
39074
|
+
if (press === opts.waitingPressRef.current) showPressBefore(press);
|
|
39075
|
+
else unlink(press, press.after);
|
|
39076
|
+
offerUndo();
|
|
39077
|
+
return true;
|
|
39078
|
+
};
|
|
39079
|
+
const endHeldPress = () => {
|
|
39080
|
+
const held = opts.waitingPressRef.current;
|
|
39081
|
+
if (held && !held.released) dropPress(held);
|
|
39082
|
+
};
|
|
39083
|
+
const releaseWaitingPress = (press, e) => {
|
|
39084
|
+
press.released = e;
|
|
39085
|
+
offerUndo();
|
|
39086
|
+
};
|
|
39087
|
+
const drawPressedBox = (origin2) => origin2 && ((dx, dy) => opts.setOverlayRect(shiftedOverlayRect(origin2, dx, dy)));
|
|
39088
|
+
const drawResizedBox = (origin2, press) => {
|
|
39089
|
+
if (!origin2) return null;
|
|
39090
|
+
const bounds = opts.overlayRef.current?.getBoundingClientRect();
|
|
39091
|
+
const centre = {
|
|
39092
|
+
x: (bounds?.left ?? 0) + origin2.left + origin2.width / 2,
|
|
39093
|
+
y: (bounds?.top ?? 0) + origin2.top + origin2.height / 2
|
|
39094
|
+
};
|
|
39095
|
+
return (dx, dy) => {
|
|
39096
|
+
const pointer = { x: press.x + dx, y: press.y + dy };
|
|
39097
|
+
const scale = resolveCenterResizeScale({ pointer, pointerStart: press, centerStart: centre });
|
|
39098
|
+
const [width, height] = [origin2.width * scale, origin2.height * scale];
|
|
39099
|
+
opts.setOverlayRect({
|
|
39100
|
+
...origin2,
|
|
39101
|
+
left: origin2.left + (origin2.width - width) / 2,
|
|
39102
|
+
top: origin2.top + (origin2.height - height) / 2,
|
|
39103
|
+
width,
|
|
39104
|
+
height
|
|
39105
|
+
});
|
|
39106
|
+
};
|
|
39107
|
+
};
|
|
39108
|
+
const startOnShownPreview = (e, pressed, start, draw = null) => {
|
|
39109
|
+
const at = playheadMoment();
|
|
39110
|
+
if (!isPreviewChanging() && !opts.waitingPressRef.current) return start(e, at, false);
|
|
39111
|
+
e.preventDefault();
|
|
39112
|
+
e.stopPropagation();
|
|
39113
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
39114
|
+
const held = { setPointerCapture() {
|
|
39115
|
+
} };
|
|
39116
|
+
const down = { ...e, currentTarget: held, preventDefault() {
|
|
39117
|
+
}, stopPropagation() {
|
|
39118
|
+
} };
|
|
39119
|
+
const press = {
|
|
39120
|
+
pointerId: e.pointerId,
|
|
39121
|
+
startX: e.clientX,
|
|
39122
|
+
startY: e.clientY,
|
|
39123
|
+
draw,
|
|
39124
|
+
frame: 0,
|
|
39125
|
+
moved: null,
|
|
39126
|
+
released: null,
|
|
39127
|
+
after: opts.waitingPressRef.current,
|
|
39128
|
+
ended: false
|
|
39129
|
+
};
|
|
39130
|
+
opts.waitingPressRef.current = press;
|
|
39131
|
+
opts.boxRef.current?.setAttribute(PRESS_WAITING_ATTR, "true");
|
|
39132
|
+
opts.rafPausedRef.current = true;
|
|
39133
|
+
let shownFrames = 0;
|
|
39134
|
+
let settledFrames = 0;
|
|
39135
|
+
const since = performance.now();
|
|
39136
|
+
const countFrame = () => {
|
|
39137
|
+
const elements = pressed();
|
|
39138
|
+
const live = opts.iframeRef.current?.contentDocument;
|
|
39139
|
+
const settled = !isPreviewChanging();
|
|
39140
|
+
const shown2 = settled && elements.every((el) => el.ownerDocument === live);
|
|
39141
|
+
shownFrames = shown2 ? shownFrames + 1 : 0;
|
|
39142
|
+
settledFrames = settled ? settledFrames + 1 : 0;
|
|
39143
|
+
return elements.length;
|
|
39144
|
+
};
|
|
39145
|
+
const waitStep = () => {
|
|
39146
|
+
if (press.after && !press.after.ended) return "wait";
|
|
39147
|
+
const found = countFrame();
|
|
39148
|
+
const overdue = performance.now() - since > PRESS_WAIT_MAX_MS;
|
|
39149
|
+
if (overdue) giveUpOnPreviewChange();
|
|
39150
|
+
if (found === 0 || settledFrames > MAX_SETTLED_WAIT_FRAMES) return "lost";
|
|
39151
|
+
return overdue || shownFrames >= 2 ? "run" : "wait";
|
|
39152
|
+
};
|
|
39153
|
+
const poll = () => {
|
|
39154
|
+
if (press.ended) return;
|
|
39155
|
+
const step = waitStep();
|
|
39156
|
+
if (step === "wait") {
|
|
39157
|
+
press.frame = requestAnimationFrame(poll);
|
|
39158
|
+
return;
|
|
39159
|
+
}
|
|
39160
|
+
endWaitingPress(press);
|
|
39161
|
+
if (step === "lost" || !start(down, at, true))
|
|
39162
|
+
return;
|
|
39163
|
+
if (press.moved) moveActiveGesture(press.moved);
|
|
39164
|
+
if (press.released) releaseActiveGesture(press.released);
|
|
39165
|
+
};
|
|
39166
|
+
press.frame = requestAnimationFrame(poll);
|
|
39167
|
+
return true;
|
|
39168
|
+
};
|
|
39169
|
+
const shownSelection = (selection) => {
|
|
39170
|
+
const doc = opts.iframeRef.current?.contentDocument;
|
|
39171
|
+
if (!doc) return null;
|
|
39172
|
+
const element = findElementForSelection(doc, selection, opts.activeCompositionPathRef.current);
|
|
39173
|
+
return element && { ...selection, element };
|
|
39174
|
+
};
|
|
39175
|
+
const shownRect = (element) => {
|
|
39176
|
+
const overlay = opts.overlayRef.current;
|
|
39177
|
+
const iframe = opts.iframeRef.current;
|
|
39178
|
+
return overlay && iframe && orientedGroupAwareOverlayRect(overlay, iframe, element);
|
|
39179
|
+
};
|
|
39180
|
+
const startGroupDrag2 = (e) => {
|
|
39181
|
+
const items = opts.groupOverlayItemsRef.current;
|
|
39182
|
+
return startOnShownPreview(
|
|
39183
|
+
e,
|
|
39184
|
+
() => items.flatMap((item) => {
|
|
39185
|
+
const selection = shownSelection(item.selection);
|
|
39186
|
+
return selection ? [selection.element] : [];
|
|
39187
|
+
}),
|
|
39188
|
+
(pressed, at, waited) => {
|
|
39189
|
+
if (!waited) return startGroupDrag(pressed, opts, at);
|
|
39190
|
+
const overlay = opts.overlayRef.current;
|
|
39191
|
+
const iframe = opts.iframeRef.current;
|
|
39192
|
+
if (!overlay || !iframe) return false;
|
|
39193
|
+
const scale = computeOverlayRootScale(overlay, iframe, iframe.contentDocument);
|
|
39194
|
+
const measured = items.flatMap((item) => {
|
|
39195
|
+
const selection = shownSelection(item.selection);
|
|
39196
|
+
const rect = selection && orientedGroupAwareOverlayRect(overlay, iframe, selection.element, scale);
|
|
39197
|
+
return selection && rect ? [{ ...item, selection, element: selection.element, rect }] : [];
|
|
39198
|
+
});
|
|
39199
|
+
if (measured.length !== items.length) return false;
|
|
39200
|
+
return startGroupDrag(
|
|
39201
|
+
pressed,
|
|
39202
|
+
{ ...opts, groupOverlayItemsRef: { current: measured } },
|
|
39203
|
+
at
|
|
39204
|
+
);
|
|
39205
|
+
},
|
|
39206
|
+
(dx, dy) => opts.setGroupOverlayItems(
|
|
39207
|
+
items.map((item) => ({ ...item, rect: shiftedOverlayRect(item.rect, dx, dy) }))
|
|
39208
|
+
)
|
|
39209
|
+
);
|
|
39210
|
+
};
|
|
39211
|
+
const startGesture2 = (kind, e, options) => {
|
|
39212
|
+
const target = options?.selection ?? opts.selectionRef.current;
|
|
39213
|
+
let draw = null;
|
|
39214
|
+
if (kind === "drag") draw = drawPressedBox(opts.overlayRectRef.current);
|
|
39215
|
+
if (kind === "resize")
|
|
39216
|
+
draw = drawResizedBox(opts.overlayRectRef.current, { x: e.clientX, y: e.clientY });
|
|
39217
|
+
return startOnShownPreview(
|
|
39218
|
+
e,
|
|
39219
|
+
() => {
|
|
39220
|
+
const shown2 = target && shownSelection(target);
|
|
39221
|
+
return shown2 ? [shown2.element] : [];
|
|
39222
|
+
},
|
|
39223
|
+
(pressed, at, waited) => {
|
|
39224
|
+
if (!waited) return startGesture(kind, pressed, opts, { ...options, at });
|
|
39225
|
+
const selection = target && shownSelection(target);
|
|
39226
|
+
const rect = selection && shownRect(selection.element);
|
|
39227
|
+
return !!(selection && rect) && startGesture(kind, pressed, opts, {
|
|
39228
|
+
selection,
|
|
39229
|
+
rect,
|
|
39230
|
+
resizeHandle: options?.resizeHandle,
|
|
39231
|
+
at
|
|
39232
|
+
});
|
|
39233
|
+
},
|
|
39234
|
+
draw
|
|
39235
|
+
);
|
|
39236
|
+
};
|
|
39237
|
+
return { startGesture: startGesture2, startGroupDrag: startGroupDrag2, endWaitingPress, endHeldPress, releaseWaitingPress };
|
|
39238
|
+
}
|
|
39239
|
+
|
|
39240
|
+
// src/components/editor/resizeDraft.ts
|
|
39241
|
+
function resolveResizeAnchor(g, corners, measureOrientedRect) {
|
|
39242
|
+
const fixedStart = g.resizeFixedCenterStart;
|
|
39243
|
+
if (corners && fixedStart) {
|
|
39244
|
+
return computeNextResizeAnchor(g.lastResizeAnchor, fixedStart, overlayCornersCentroid(corners));
|
|
39245
|
+
}
|
|
39246
|
+
const fallbackRect = measureOrientedRect();
|
|
39247
|
+
return resolveResizeCenterAnchorOffset({
|
|
39248
|
+
originWidth: g.originWidth,
|
|
39249
|
+
originHeight: g.originHeight,
|
|
39250
|
+
overlayWidth: fallbackRect ? fallbackRect.width : g.originWidth,
|
|
39251
|
+
overlayHeight: fallbackRect ? fallbackRect.height : g.originHeight
|
|
39252
|
+
});
|
|
39253
|
+
}
|
|
39254
|
+
function resolveAnchoredResizeDraft(g, member, element, overlayEl, iframe, measureOrientedRect) {
|
|
39255
|
+
const corners = overlayEl && iframe ? elementCornerOverlayPoints(overlayEl, iframe, element) : null;
|
|
39256
|
+
const anchor2 = resolveResizeAnchor(g, corners, measureOrientedRect);
|
|
39257
|
+
g.lastResizeAnchor = anchor2;
|
|
39258
|
+
applyManualOffsetDragDraft(member, anchor2.dx, anchor2.dy);
|
|
39259
|
+
return measureOrientedRect() ?? {
|
|
39260
|
+
left: g.originLeft + anchor2.dx,
|
|
39261
|
+
top: g.originTop + anchor2.dy,
|
|
39262
|
+
width: corners ? cornerEdgeLength(corners.nw, corners.ne) : g.originWidth,
|
|
39263
|
+
height: corners ? cornerEdgeLength(corners.nw, corners.sw) : g.originHeight,
|
|
39264
|
+
editScaleX: g.editScaleX,
|
|
39265
|
+
editScaleY: g.editScaleY,
|
|
39266
|
+
angle: g.actualRotation
|
|
39267
|
+
};
|
|
39268
|
+
}
|
|
39269
|
+
function resolveResizeDraftRect(g, element, overlayEl, iframe, measureOrientedRect) {
|
|
39270
|
+
if (g.pathOffsetMember) {
|
|
39271
|
+
return resolveAnchoredResizeDraft(
|
|
39272
|
+
g,
|
|
39273
|
+
g.pathOffsetMember,
|
|
39274
|
+
element,
|
|
39275
|
+
overlayEl,
|
|
39276
|
+
iframe,
|
|
39277
|
+
measureOrientedRect
|
|
39278
|
+
);
|
|
39279
|
+
}
|
|
39280
|
+
return measureOrientedRect() ?? {
|
|
39281
|
+
left: g.originLeft,
|
|
39282
|
+
top: g.originTop,
|
|
39283
|
+
width: g.originWidth,
|
|
39284
|
+
height: g.originHeight,
|
|
39285
|
+
editScaleX: g.editScaleX,
|
|
39286
|
+
editScaleY: g.editScaleY,
|
|
39287
|
+
angle: g.actualRotation
|
|
39288
|
+
};
|
|
39289
|
+
}
|
|
39290
|
+
|
|
38991
39291
|
// src/components/editor/groupDragMove.ts
|
|
38992
39292
|
function createGroupDragMover(opts, setDraftGroupOverlayItems) {
|
|
38993
39293
|
let lastGroupPositions = {};
|
|
@@ -39147,7 +39447,7 @@ function logGestureCommitFailure(message, error) {
|
|
|
39147
39447
|
}
|
|
39148
39448
|
function createDomEditOverlayGestureHandlers(opts) {
|
|
39149
39449
|
const setDraftOverlayRect = (next) => {
|
|
39150
|
-
opts.setOverlayRect(next);
|
|
39450
|
+
if (!opts.waitingPressRef.current) opts.setOverlayRect(next);
|
|
39151
39451
|
};
|
|
39152
39452
|
const restoreGestureOverlayRect = (g) => {
|
|
39153
39453
|
setDraftOverlayRect({
|
|
@@ -39157,21 +39457,22 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
39157
39457
|
height: g.originHeight,
|
|
39158
39458
|
editScaleX: g.editScaleX,
|
|
39159
39459
|
editScaleY: g.editScaleY,
|
|
39160
|
-
//
|
|
39161
|
-
// renders rotate(overlayRect.angle), so an omitted angle straightens the
|
|
39162
|
-
// chrome for the duration of the draft (the "straightens while moving" bug).
|
|
39460
|
+
// Rotation keeps the chrome aligned with the element during its draft.
|
|
39163
39461
|
angle: g.actualRotation
|
|
39164
39462
|
});
|
|
39165
39463
|
};
|
|
39166
39464
|
const setDraftGroupOverlayItems = (next) => {
|
|
39167
|
-
opts.setGroupOverlayItems(next);
|
|
39465
|
+
if (!opts.waitingPressRef.current) opts.setGroupOverlayItems(next);
|
|
39168
39466
|
};
|
|
39169
39467
|
const restoreGroupPathOffsets = (g) => {
|
|
39170
39468
|
restoreManualOffsetDragMembers(g.members);
|
|
39171
39469
|
setDraftGroupOverlayItems(g.originItems);
|
|
39172
39470
|
};
|
|
39173
|
-
const startGroupDrag2
|
|
39174
|
-
|
|
39471
|
+
const { startGesture: startGesture2, startGroupDrag: startGroupDrag2, endWaitingPress, endHeldPress, releaseWaitingPress } = createPreviewGestureStarts(
|
|
39472
|
+
opts,
|
|
39473
|
+
(event) => moveActiveGesture(event),
|
|
39474
|
+
(event) => releaseActiveGesture(event)
|
|
39475
|
+
);
|
|
39175
39476
|
const startBlockedMove = (e, selection) => {
|
|
39176
39477
|
e.preventDefault();
|
|
39177
39478
|
e.stopPropagation();
|
|
@@ -39181,10 +39482,20 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
39181
39482
|
};
|
|
39182
39483
|
const moveGroupDrag = createGroupDragMover(opts, setDraftGroupOverlayItems);
|
|
39183
39484
|
const onPointerMove = (e) => {
|
|
39485
|
+
const waiting = opts.waitingPressRef.current;
|
|
39486
|
+
if (waiting && waiting.pointerId === e.pointerId) {
|
|
39487
|
+
if (waiting.released || !movesGesture(waiting, e)) return;
|
|
39488
|
+
waiting.moved = e;
|
|
39489
|
+
waiting.draw?.(e.clientX - waiting.startX, e.clientY - waiting.startY);
|
|
39490
|
+
return;
|
|
39491
|
+
}
|
|
39492
|
+
moveActiveGesture(e);
|
|
39493
|
+
};
|
|
39494
|
+
const moveActiveGesture = (e) => {
|
|
39184
39495
|
const g = opts.gestureRef.current;
|
|
39185
39496
|
const groupG = opts.groupGestureRef.current;
|
|
39186
39497
|
const sel = g?.selection ?? opts.selectionRef.current;
|
|
39187
|
-
const box = opts.boxRef.current;
|
|
39498
|
+
const box = opts.waitingPressRef.current ? null : opts.boxRef.current;
|
|
39188
39499
|
const blockedMove = opts.blockedMoveRef.current;
|
|
39189
39500
|
if (!blockedMove && !g && !groupG) {
|
|
39190
39501
|
opts.onCanvasPointerMoveRef.current(e, { preferClipAncestor: false });
|
|
@@ -39288,7 +39599,6 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
39288
39599
|
}
|
|
39289
39600
|
if (g.pathOffsetMember) applyManualOffsetDragDraft(g.pathOffsetMember, dx, dy);
|
|
39290
39601
|
} else {
|
|
39291
|
-
if (!box) return;
|
|
39292
39602
|
const nextSize = resolveCenterResizeSize({
|
|
39293
39603
|
baseWidth: g.actualWidth,
|
|
39294
39604
|
baseHeight: g.actualHeight,
|
|
@@ -39314,23 +39624,34 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
39314
39624
|
draftRect,
|
|
39315
39625
|
liveInlineStyle: sel.element.getAttribute("style")
|
|
39316
39626
|
});
|
|
39317
|
-
box
|
|
39318
|
-
|
|
39319
|
-
|
|
39320
|
-
|
|
39627
|
+
if (box) {
|
|
39628
|
+
box.style.left = `${draftRect.left}px`;
|
|
39629
|
+
box.style.top = `${draftRect.top}px`;
|
|
39630
|
+
box.style.width = `${draftRect.width}px`;
|
|
39631
|
+
box.style.height = `${draftRect.height}px`;
|
|
39632
|
+
}
|
|
39321
39633
|
setDraftOverlayRect(draftRect);
|
|
39322
39634
|
}
|
|
39323
39635
|
};
|
|
39324
39636
|
const onPointerUp = (e) => {
|
|
39637
|
+
const waiting = opts.waitingPressRef.current;
|
|
39638
|
+
if (waiting && waiting.pointerId === e.pointerId) {
|
|
39639
|
+
releaseWaitingPress(waiting, e);
|
|
39640
|
+
opts.suppressNextBoxClickRef.current = true;
|
|
39641
|
+
return;
|
|
39642
|
+
}
|
|
39643
|
+
releaseActiveGesture(e);
|
|
39644
|
+
};
|
|
39645
|
+
const releaseActiveGesture = (e) => {
|
|
39325
39646
|
opts.snapGuidesRef.current = null;
|
|
39326
39647
|
const g = opts.gestureRef.current;
|
|
39327
39648
|
const groupG = opts.groupGestureRef.current;
|
|
39328
39649
|
const sel = g?.selection ?? opts.selectionRef.current;
|
|
39329
|
-
const box = opts.boxRef.current;
|
|
39650
|
+
const box = opts.waitingPressRef.current ? null : opts.boxRef.current;
|
|
39330
39651
|
opts.blockedMoveRef.current = null;
|
|
39652
|
+
opts.rafPausedRef.current = opts.waitingPressRef.current !== null;
|
|
39331
39653
|
if (groupG) {
|
|
39332
39654
|
opts.groupGestureRef.current = null;
|
|
39333
|
-
opts.rafPausedRef.current = false;
|
|
39334
39655
|
const rawDx = e.clientX - groupG.startX;
|
|
39335
39656
|
const rawDy = e.clientY - groupG.startY;
|
|
39336
39657
|
opts.suppressNextBoxClickRef.current = true;
|
|
@@ -39349,7 +39670,7 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
39349
39670
|
setDraftGroupOverlayItems(
|
|
39350
39671
|
groupG.originItems.map((item) => ({
|
|
39351
39672
|
...item,
|
|
39352
|
-
rect:
|
|
39673
|
+
rect: shiftedOverlayRect(item.rect, dx, dy)
|
|
39353
39674
|
}))
|
|
39354
39675
|
);
|
|
39355
39676
|
const updates = groupG.members.map((member) => ({
|
|
@@ -39384,13 +39705,8 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
39384
39705
|
groupEdit.settle(groupSaved);
|
|
39385
39706
|
return;
|
|
39386
39707
|
}
|
|
39387
|
-
if (!g || !sel) {
|
|
39388
|
-
opts.gestureRef.current = null;
|
|
39389
|
-
opts.rafPausedRef.current = false;
|
|
39390
|
-
return;
|
|
39391
|
-
}
|
|
39392
39708
|
opts.gestureRef.current = null;
|
|
39393
|
-
|
|
39709
|
+
if (!g || !sel) return;
|
|
39394
39710
|
const movedDistance = Math.hypot(e.clientX - g.startX, e.clientY - g.startY);
|
|
39395
39711
|
if (g.kind === "drag" && isTap(g, e)) {
|
|
39396
39712
|
if (g.pathOffsetMember) restoreManualOffsetDragMembers([g.pathOffsetMember]);
|
|
@@ -39523,7 +39839,9 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
39523
39839
|
logResizeSettle(sel.element, "post-release");
|
|
39524
39840
|
}
|
|
39525
39841
|
};
|
|
39526
|
-
const clearPointerState = (selectionRef) => {
|
|
39842
|
+
const clearPointerState = (selectionRef, dropQueued = false) => {
|
|
39843
|
+
if (dropQueued) endWaitingPress();
|
|
39844
|
+
else endHeldPress();
|
|
39527
39845
|
opts.snapGuidesRef.current = null;
|
|
39528
39846
|
const groupG = opts.groupGestureRef.current;
|
|
39529
39847
|
if (groupG) restoreGroupPathOffsets(groupG);
|
|
@@ -39554,7 +39872,12 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
39554
39872
|
opts.blockedMoveRef.current = null;
|
|
39555
39873
|
opts.groupGestureRef.current = null;
|
|
39556
39874
|
opts.gestureRef.current = null;
|
|
39557
|
-
opts.rafPausedRef.current =
|
|
39875
|
+
opts.rafPausedRef.current = opts.waitingPressRef.current !== null;
|
|
39876
|
+
};
|
|
39877
|
+
const onLostPointerCapture = (e) => {
|
|
39878
|
+
const waiting = opts.waitingPressRef.current;
|
|
39879
|
+
if (waiting?.pointerId === e.pointerId && waiting.released) return;
|
|
39880
|
+
clearPointerState(opts.selectionRef);
|
|
39558
39881
|
};
|
|
39559
39882
|
return {
|
|
39560
39883
|
startGesture: startGesture2,
|
|
@@ -39562,6 +39885,7 @@ function createDomEditOverlayGestureHandlers(opts) {
|
|
|
39562
39885
|
startBlockedMove,
|
|
39563
39886
|
onPointerMove,
|
|
39564
39887
|
onPointerUp,
|
|
39888
|
+
onLostPointerCapture,
|
|
39565
39889
|
clearPointerState
|
|
39566
39890
|
};
|
|
39567
39891
|
}
|
|
@@ -41998,6 +42322,7 @@ var DomEditOverlay = memo28(function DomEditOverlay2({
|
|
|
41998
42322
|
const gestureRef = useRef70(null);
|
|
41999
42323
|
const groupGestureRef = useRef70(null);
|
|
42000
42324
|
const blockedMoveRef = useRef70(null);
|
|
42325
|
+
const waitingPressRef = useRef70(null);
|
|
42001
42326
|
const suppressNextBoxClickRef = useRef70(false);
|
|
42002
42327
|
const snapGuidesRef = useRef70(null);
|
|
42003
42328
|
const rafPausedRef = useRef70(false);
|
|
@@ -42086,6 +42411,7 @@ var DomEditOverlay = memo28(function DomEditOverlay2({
|
|
|
42086
42411
|
activeCompositionPath
|
|
42087
42412
|
});
|
|
42088
42413
|
const gestures = createDomEditOverlayGestureHandlers({
|
|
42414
|
+
activeCompositionPathRef,
|
|
42089
42415
|
overlayRef,
|
|
42090
42416
|
iframeRef,
|
|
42091
42417
|
boxRef,
|
|
@@ -42096,6 +42422,7 @@ var DomEditOverlay = memo28(function DomEditOverlay2({
|
|
|
42096
42422
|
gestureRef,
|
|
42097
42423
|
groupGestureRef,
|
|
42098
42424
|
blockedMoveRef,
|
|
42425
|
+
waitingPressRef,
|
|
42099
42426
|
rafPausedRef,
|
|
42100
42427
|
suppressNextBoxClickRef,
|
|
42101
42428
|
setOverlayRect,
|
|
@@ -42111,17 +42438,17 @@ var DomEditOverlay = memo28(function DomEditOverlay2({
|
|
|
42111
42438
|
snapGuidesRef
|
|
42112
42439
|
});
|
|
42113
42440
|
useEffect55(() => {
|
|
42114
|
-
if (readOnly) gestures.clearPointerState(selectionRef);
|
|
42441
|
+
if (readOnly) gestures.clearPointerState(selectionRef, true);
|
|
42115
42442
|
}, [gestures, readOnly, selectionRef]);
|
|
42116
|
-
const cancelGestureRef = useRef70(() => {
|
|
42443
|
+
const cancelGestureRef = useRef70((_dropQueued) => {
|
|
42117
42444
|
});
|
|
42118
|
-
cancelGestureRef.current = () => gestures.clearPointerState(selectionRef);
|
|
42445
|
+
cancelGestureRef.current = (dropQueued) => gestures.clearPointerState(selectionRef, dropQueued);
|
|
42119
42446
|
useMountEffect(() => {
|
|
42120
42447
|
const cancel = () => cancelGestureRef.current();
|
|
42121
42448
|
window.addEventListener("blur", cancel);
|
|
42122
42449
|
return () => {
|
|
42123
42450
|
window.removeEventListener("blur", cancel);
|
|
42124
|
-
|
|
42451
|
+
cancelGestureRef.current(true);
|
|
42125
42452
|
};
|
|
42126
42453
|
});
|
|
42127
42454
|
const { flushNudge } = useDomEditNudge({
|
|
@@ -42253,7 +42580,7 @@ var DomEditOverlay = memo28(function DomEditOverlay2({
|
|
|
42253
42580
|
onPointerLeave: () => onCanvasPointerLeaveRef.current(),
|
|
42254
42581
|
onPointerUp: marquee.onPointerUp,
|
|
42255
42582
|
onPointerCancel: marquee.onPointerCancel,
|
|
42256
|
-
onLostPointerCapture:
|
|
42583
|
+
onLostPointerCapture: gestures.onLostPointerCapture,
|
|
42257
42584
|
onContextMenu: hostInput ? void 0 : handleContextMenu,
|
|
42258
42585
|
children: [
|
|
42259
42586
|
!hostInput && hoverSelection && hoverRect && compRect.width > 0 && /* @__PURE__ */ jsx102(
|
|
@@ -45807,8 +46134,8 @@ import { isTweenConfigKey } from "@hyperframes/parsers/gsap-constants";
|
|
|
45807
46134
|
function newTweenTarget(selection) {
|
|
45808
46135
|
return writeTargetSelector(selection);
|
|
45809
46136
|
}
|
|
45810
|
-
function computeCurrentPercentage(selection, animation) {
|
|
45811
|
-
return computeElementPercentage(
|
|
46137
|
+
function computeCurrentPercentage(selection, animation, time = usePlayerStore.getState().currentTime) {
|
|
46138
|
+
return computeElementPercentage(time, selection, animation);
|
|
45812
46139
|
}
|
|
45813
46140
|
function parkPlayheadOnKeyframe(anim, pct) {
|
|
45814
46141
|
const time = percentageToAbsoluteForAnimation(pct, anim);
|
|
@@ -46173,9 +46500,8 @@ function animHasPosition(anim) {
|
|
|
46173
46500
|
}
|
|
46174
46501
|
return "x" in anim.properties || "y" in anim.properties;
|
|
46175
46502
|
}
|
|
46176
|
-
function findGsapPositionAnimation(animations, selector) {
|
|
46503
|
+
function findGsapPositionAnimation(animations, selector, currentTime = usePlayerStore.getState().currentTime) {
|
|
46177
46504
|
if (animations.length === 0) return null;
|
|
46178
|
-
const currentTime = usePlayerStore.getState().currentTime;
|
|
46179
46505
|
const scored = animations.filter(animHasPosition).map((a) => {
|
|
46180
46506
|
let score = 0;
|
|
46181
46507
|
if (a.keyframes) score += 5;
|
|
@@ -46203,9 +46529,8 @@ function statesValueAt(anim, time) {
|
|
|
46203
46529
|
if (anim.method === "from") return near4(0);
|
|
46204
46530
|
return near4(100) || anim.method === "fromTo" && near4(0);
|
|
46205
46531
|
}
|
|
46206
|
-
function pickClosestToPlayhead(anims) {
|
|
46532
|
+
function pickClosestToPlayhead(anims, ct = usePlayerStore.getState().currentTime) {
|
|
46207
46533
|
if (anims.length <= 1) return anims[0] ?? null;
|
|
46208
|
-
const ct = usePlayerStore.getState().currentTime;
|
|
46209
46534
|
return anims.reduce((best, a) => {
|
|
46210
46535
|
const dist = playheadDistance(a, ct);
|
|
46211
46536
|
const bestDist = playheadDistance(best, ct);
|
|
@@ -46670,9 +46995,13 @@ function planValueAtPlayhead(edit) {
|
|
|
46670
46995
|
added: keyframes.length > authored
|
|
46671
46996
|
};
|
|
46672
46997
|
}
|
|
46673
|
-
function planValueEdit(selection, anim, values, iframe, {
|
|
46998
|
+
function planValueEdit(selection, anim, values, iframe, {
|
|
46999
|
+
backfill,
|
|
47000
|
+
holdFromStart,
|
|
47001
|
+
moment = playheadMoment()
|
|
47002
|
+
} = {}) {
|
|
46674
47003
|
if (tweenReach(anim, selection.element) === "shared") return refuse("shared-tween");
|
|
46675
|
-
const { activeKeyframePct, currentTime } =
|
|
47004
|
+
const { keyframePct: activeKeyframePct, time: currentTime } = moment;
|
|
46676
47005
|
const tween = findParsedTween(iframe, selection.element, anim);
|
|
46677
47006
|
const timed = withExactStepTimes(anim, tween);
|
|
46678
47007
|
return planValueAtPlayhead({
|
|
@@ -46687,10 +47016,11 @@ function planValueEdit(selection, anim, values, iframe, { backfill, holdFromStar
|
|
|
46687
47016
|
}
|
|
46688
47017
|
async function commitValueAtPlayhead(selection, anim, values, iframe, callbacks, options) {
|
|
46689
47018
|
await materializeIfDynamic(anim, iframe, callbacks.commitMutation, selection);
|
|
46690
|
-
const
|
|
47019
|
+
const moment = editMoment(callbacks.stamp);
|
|
47020
|
+
const { setActiveKeyframePct } = usePlayerStore.getState();
|
|
46691
47021
|
const tween = findParsedTween(iframe, selection.element, anim);
|
|
46692
|
-
const parkAt =
|
|
46693
|
-
const plan = planValueEdit(selection, anim, values, iframe, options);
|
|
47022
|
+
const parkAt = moment.keyframePct == null ? null : exactKeyframePct(anim, tween, moment.keyframePct);
|
|
47023
|
+
const plan = planValueEdit(selection, anim, values, iframe, { ...options, moment });
|
|
46694
47024
|
if (!plan.ok) return { status: "blocked", reason: "keyframes-uneditable", detail: plan.reason };
|
|
46695
47025
|
await callbacks.commitMutation(selection, plan.mutation, {
|
|
46696
47026
|
label: options.label,
|
|
@@ -47936,7 +48266,7 @@ function buildExtendedKeyframes(anim, currentTime, position, sourceDuration = re
|
|
|
47936
48266
|
const keyframes = [...rescaled, added].sort((a, b) => a.percentage - b.percentage);
|
|
47937
48267
|
return { position: roundTo3(newStart), duration: newDuration, keyframes };
|
|
47938
48268
|
}
|
|
47939
|
-
function gsapPositionFromDragOutcome(selection, anim, studioOffset, gsapPos, iframe) {
|
|
48269
|
+
function gsapPositionFromDragOutcome(selection, anim, studioOffset, gsapPos, iframe, moment) {
|
|
47940
48270
|
if (anim.arcPath?.enabled) return { status: "persisted" };
|
|
47941
48271
|
const { newX, newY, baseGsapX, baseGsapY } = computeDraggedGsapPosition(
|
|
47942
48272
|
selection.element,
|
|
@@ -47944,7 +48274,8 @@ function gsapPositionFromDragOutcome(selection, anim, studioOffset, gsapPos, ifr
|
|
|
47944
48274
|
gsapPos
|
|
47945
48275
|
);
|
|
47946
48276
|
const plan = planValueEdit(selection, anim, { x: newX, y: newY }, iframe, {
|
|
47947
|
-
backfill: { x: baseGsapX, y: baseGsapY }
|
|
48277
|
+
backfill: { x: baseGsapX, y: baseGsapY },
|
|
48278
|
+
moment
|
|
47948
48279
|
});
|
|
47949
48280
|
return plan.ok ? { status: "persisted" } : { status: "blocked", reason: "keyframes-uneditable", detail: plan.reason };
|
|
47950
48281
|
}
|
|
@@ -47959,7 +48290,8 @@ async function commitGsapPositionFromDrag(selection, anim, studioOffset, gsapPos
|
|
|
47959
48290
|
);
|
|
47960
48291
|
const restoreOffset = () => restoreDragOffset(el, stamp);
|
|
47961
48292
|
if (anim.arcPath?.enabled) {
|
|
47962
|
-
const { activeKeyframePct, currentTime
|
|
48293
|
+
const { keyframePct: activeKeyframePct, time: currentTime } = editMoment(stamp);
|
|
48294
|
+
const { setActiveKeyframePct } = usePlayerStore.getState();
|
|
47963
48295
|
const tweenStart = resolveTweenStart(anim);
|
|
47964
48296
|
const tweenDuration = resolveTweenDuration(anim);
|
|
47965
48297
|
if (activeKeyframePct === null && tweenStart !== null && !isTimeWithinTween(currentTime, tweenStart, tweenDuration)) {
|
|
@@ -47988,7 +48320,7 @@ async function commitGsapPositionFromDrag(selection, anim, studioOffset, gsapPos
|
|
|
47988
48320
|
);
|
|
47989
48321
|
return { status: "persisted" };
|
|
47990
48322
|
}
|
|
47991
|
-
const pct = activeKeyframePct ?? computeCurrentPercentage(selection, anim);
|
|
48323
|
+
const pct = activeKeyframePct ?? computeCurrentPercentage(selection, anim, currentTime);
|
|
47992
48324
|
const keyframes = anim.keyframes?.keyframes ?? [];
|
|
47993
48325
|
const pointIndex = keyframes.findIndex((kf) => playsNear(anim, kf.percentage, pct));
|
|
47994
48326
|
if (pointIndex >= 0) {
|
|
@@ -48031,11 +48363,18 @@ async function commitGsapPositionFromDrag(selection, anim, studioOffset, gsapPos
|
|
|
48031
48363
|
);
|
|
48032
48364
|
return { status: "persisted" };
|
|
48033
48365
|
}
|
|
48034
|
-
return commitValueAtPlayhead(
|
|
48035
|
-
|
|
48036
|
-
|
|
48037
|
-
|
|
48038
|
-
|
|
48366
|
+
return commitValueAtPlayhead(
|
|
48367
|
+
selection,
|
|
48368
|
+
anim,
|
|
48369
|
+
{ x: newX, y: newY },
|
|
48370
|
+
iframe,
|
|
48371
|
+
{ ...callbacks, stamp },
|
|
48372
|
+
{
|
|
48373
|
+
label: "Move layer",
|
|
48374
|
+
backfill: { x: baseGsapX, y: baseGsapY },
|
|
48375
|
+
beforeReload: restoreOffset
|
|
48376
|
+
}
|
|
48377
|
+
);
|
|
48039
48378
|
}
|
|
48040
48379
|
|
|
48041
48380
|
// src/hooks/gsapElementMatch.ts
|
|
@@ -48066,12 +48405,12 @@ function getAnimationsForElement(animations, target, element) {
|
|
|
48066
48405
|
// src/hooks/gsapRuntimeBridge.ts
|
|
48067
48406
|
var POSITION_CHANNEL_SET = new Set(POSITION_CHANNELS);
|
|
48068
48407
|
var ROTATION_CHANNEL_SET = new Set(ROTATION_CHANNELS);
|
|
48069
|
-
async function resolveGroupTween(group, animations, _selection, _commitMutation, fetchFallbackAnimations) {
|
|
48408
|
+
async function resolveGroupTween(group, animations, _selection, _commitMutation, fetchFallbackAnimations, time) {
|
|
48070
48409
|
const inGroup = (list) => {
|
|
48071
48410
|
const tagged = list.filter((a) => a.propertyGroup === group);
|
|
48072
48411
|
const props = new Set(PROPERTY_GROUPS[group]);
|
|
48073
48412
|
const mixed = list.filter((a) => !a.propertyGroup && animationWritesAnyProperty(a, props));
|
|
48074
|
-
return pickClosestToPlayhead(tagged.length > 0 ? tagged : mixed);
|
|
48413
|
+
return pickClosestToPlayhead(tagged.length > 0 ? tagged : mixed, time);
|
|
48075
48414
|
};
|
|
48076
48415
|
const anim = inGroup(animations);
|
|
48077
48416
|
if (anim) return { anim, animations };
|
|
@@ -48138,15 +48477,22 @@ function dragRoute(posAnim, iframe, selector, altKey) {
|
|
|
48138
48477
|
if (!hasNonHold && !hasKeyframedPosTween) return "static";
|
|
48139
48478
|
return altKey || !usePlayerStore.getState().autoKeyframeEnabled ? "whole-path" : "at-playhead";
|
|
48140
48479
|
}
|
|
48141
|
-
async function planDrag(selection, offset, allAnimations, iframe, options) {
|
|
48480
|
+
async function planDrag(selection, offset, allAnimations, iframe, options, moment) {
|
|
48142
48481
|
const selector = selectorFromSelection(selection);
|
|
48143
48482
|
if (!selector) return { status: "blocked", reason: "no-selector" };
|
|
48144
48483
|
const own = tweensForThisElement(selection, allAnimations);
|
|
48145
48484
|
const keeper = positionWriteKeeper(own, selector);
|
|
48146
48485
|
const animations = keeper ? own.filter((a) => a === keeper || !isPositionWriteOf(selector)(a)) : own;
|
|
48147
|
-
const resolved2 = await resolveGroupTween(
|
|
48148
|
-
|
|
48149
|
-
|
|
48486
|
+
const resolved2 = await resolveGroupTween(
|
|
48487
|
+
"position",
|
|
48488
|
+
animations,
|
|
48489
|
+
selection,
|
|
48490
|
+
async () => {
|
|
48491
|
+
},
|
|
48492
|
+
void 0,
|
|
48493
|
+
moment.time
|
|
48494
|
+
);
|
|
48495
|
+
const posAnim = resolved2?.anim ?? findGsapPositionAnimation(animations, selector, moment.time);
|
|
48150
48496
|
const route = dragRoute(posAnim, iframe, selector, options.altKey);
|
|
48151
48497
|
if (route === "static") return { status: "persisted" };
|
|
48152
48498
|
if (!posAnim) {
|
|
@@ -48157,9 +48503,12 @@ async function planDrag(selection, offset, allAnimations, iframe, options) {
|
|
|
48157
48503
|
return step ? { status: "blocked", reason: "keyframes-uneditable", detail: step } : { status: "persisted" };
|
|
48158
48504
|
}
|
|
48159
48505
|
const gsapPos = readGsapPositionFromIframe(iframe, selector) ?? { x: 0, y: 0 };
|
|
48160
|
-
return gsapPositionFromDragOutcome(selection, posAnim, offset, gsapPos, iframe);
|
|
48506
|
+
return gsapPositionFromDragOutcome(selection, posAnim, offset, gsapPos, iframe, moment);
|
|
48161
48507
|
}
|
|
48162
48508
|
async function tryGsapDragIntercept(selection, offset, allAnimations, iframe, gestureCommit, fetchAllAnimations, options) {
|
|
48509
|
+
const stamp = options?.stamp ?? readDragStamp(selection.element);
|
|
48510
|
+
const moment = editMoment(stamp);
|
|
48511
|
+
const time = moment.time;
|
|
48163
48512
|
if (!options?.preflightPassed) {
|
|
48164
48513
|
const preflight = await preflightGsapDragIntercept(
|
|
48165
48514
|
selection,
|
|
@@ -48170,7 +48519,7 @@ async function tryGsapDragIntercept(selection, offset, allAnimations, iframe, ge
|
|
|
48170
48519
|
);
|
|
48171
48520
|
if (preflight.status !== "persisted") return preflight;
|
|
48172
48521
|
if (options?.preflightOnly) {
|
|
48173
|
-
return options.group ? planDrag(selection, offset, allAnimations, iframe, options) : preflight;
|
|
48522
|
+
return options.group ? planDrag(selection, offset, allAnimations, iframe, options, moment) : preflight;
|
|
48174
48523
|
}
|
|
48175
48524
|
}
|
|
48176
48525
|
const animations = tweensForThisElement(selection, allAnimations);
|
|
@@ -48202,16 +48551,17 @@ async function tryGsapDragIntercept(selection, offset, allAnimations, iframe, ge
|
|
|
48202
48551
|
workingAnimations,
|
|
48203
48552
|
selection,
|
|
48204
48553
|
commitMutation,
|
|
48205
|
-
fetchFallbackAnimations
|
|
48554
|
+
fetchFallbackAnimations,
|
|
48555
|
+
time
|
|
48206
48556
|
);
|
|
48207
48557
|
let posAnim = resolved2?.anim ?? null;
|
|
48208
48558
|
let resolvedAnimations = resolved2?.animations ?? workingAnimations;
|
|
48209
48559
|
if (!posAnim) {
|
|
48210
|
-
posAnim = findGsapPositionAnimation(workingAnimations, selector);
|
|
48560
|
+
posAnim = findGsapPositionAnimation(workingAnimations, selector, time);
|
|
48211
48561
|
if (!posAnim && fetchFallbackAnimations) {
|
|
48212
48562
|
const fresh = await fetchFallbackAnimations();
|
|
48213
48563
|
resolvedAnimations = fresh;
|
|
48214
|
-
posAnim = findGsapPositionAnimation(fresh, selector);
|
|
48564
|
+
posAnim = findGsapPositionAnimation(fresh, selector, time);
|
|
48215
48565
|
}
|
|
48216
48566
|
}
|
|
48217
48567
|
const gsapPos = readGsapPositionFromIframe(iframe, selector) ?? { x: 0, y: 0 };
|
|
@@ -48233,13 +48583,14 @@ async function tryGsapDragIntercept(selection, offset, allAnimations, iframe, ge
|
|
|
48233
48583
|
const freshMatch = fresh.find((a) => a.id === posAnim.id) ?? pickClosestToPlayhead(
|
|
48234
48584
|
fresh.filter(
|
|
48235
48585
|
(a) => a.targetSelector === posAnim.targetSelector && a.propertyGroup === posAnim.propertyGroup && isXYPositionWrite(a) === isXYPositionWrite(posAnim)
|
|
48236
|
-
)
|
|
48586
|
+
),
|
|
48587
|
+
time
|
|
48237
48588
|
);
|
|
48238
48589
|
if (freshMatch && freshMatch.id !== posAnim.id) {
|
|
48239
48590
|
posAnim = freshMatch;
|
|
48240
48591
|
}
|
|
48241
48592
|
}
|
|
48242
|
-
const cbs = { commitMutation, fetchAnimations: fetchFallbackAnimations, stamp
|
|
48593
|
+
const cbs = { commitMutation, fetchAnimations: fetchFallbackAnimations, stamp };
|
|
48243
48594
|
if (route === "whole-path") {
|
|
48244
48595
|
await commitWholePathOffset(selection, posAnim, offset, gsapPos, iframe, selector, cbs);
|
|
48245
48596
|
} else {
|
|
@@ -48270,7 +48621,8 @@ function preflightGsapRotationIntercept(selection, animations, iframe, fetchedAn
|
|
|
48270
48621
|
}
|
|
48271
48622
|
return { status: "persisted" };
|
|
48272
48623
|
}
|
|
48273
|
-
async function tryGsapRotationIntercept(selection, angle, animations, iframe, commitMutation, fetchFallbackAnimations) {
|
|
48624
|
+
async function tryGsapRotationIntercept(selection, angle, animations, iframe, commitMutation, fetchFallbackAnimations, stamp) {
|
|
48625
|
+
const time = editMoment(stamp).time;
|
|
48274
48626
|
const fetchedAnimations = fetchFallbackAnimations ? await fetchFallbackAnimations() : [];
|
|
48275
48627
|
const outcome = preflightGsapRotationIntercept(selection, animations, iframe, fetchedAnimations);
|
|
48276
48628
|
if (outcome.status === "blocked") return outcome;
|
|
@@ -48282,13 +48634,15 @@ async function tryGsapRotationIntercept(selection, angle, animations, iframe, co
|
|
|
48282
48634
|
workingAnimations,
|
|
48283
48635
|
selection,
|
|
48284
48636
|
commitMutation,
|
|
48285
|
-
postSplitFetch
|
|
48637
|
+
postSplitFetch,
|
|
48638
|
+
time
|
|
48286
48639
|
);
|
|
48287
48640
|
const resolvedAnimations = resolved2?.animations ?? workingAnimations;
|
|
48288
48641
|
let anim = resolved2?.anim && animationWritesAnyProperty(resolved2.anim, ROTATION_CHANNEL_SET) ? resolved2.anim : null;
|
|
48289
48642
|
if (!anim) {
|
|
48290
48643
|
anim = pickClosestToPlayhead(
|
|
48291
|
-
workingAnimations.filter((a) => animationWritesAnyProperty(a, ROTATION_CHANNEL_SET))
|
|
48644
|
+
workingAnimations.filter((a) => animationWritesAnyProperty(a, ROTATION_CHANNEL_SET)),
|
|
48645
|
+
time
|
|
48292
48646
|
);
|
|
48293
48647
|
}
|
|
48294
48648
|
const newRotation = roundTo3(angle);
|
|
@@ -48300,7 +48654,7 @@ async function tryGsapRotationIntercept(selection, angle, animations, iframe, co
|
|
|
48300
48654
|
});
|
|
48301
48655
|
return { status: "persisted" };
|
|
48302
48656
|
}
|
|
48303
|
-
const pct = computeCurrentPercentage(selection, anim);
|
|
48657
|
+
const pct = computeCurrentPercentage(selection, anim, time);
|
|
48304
48658
|
if (!usePlayerStore.getState().autoKeyframeEnabled) {
|
|
48305
48659
|
await commitWholePropertyOffset(
|
|
48306
48660
|
selection,
|
|
@@ -48318,7 +48672,7 @@ async function tryGsapRotationIntercept(selection, angle, animations, iframe, co
|
|
|
48318
48672
|
anim,
|
|
48319
48673
|
{ rotation: newRotation },
|
|
48320
48674
|
iframe,
|
|
48321
|
-
{ commitMutation, fetchAnimations: fetchFallbackAnimations },
|
|
48675
|
+
{ commitMutation, fetchAnimations: fetchFallbackAnimations, stamp },
|
|
48322
48676
|
{ label: "Rotate", backfill: { rotation: newRotation }, holdFromStart: true }
|
|
48323
48677
|
);
|
|
48324
48678
|
}
|
|
@@ -75224,10 +75578,7 @@ function usePreviewPersistence({
|
|
|
75224
75578
|
reloadPreview,
|
|
75225
75579
|
nestedFiles
|
|
75226
75580
|
);
|
|
75227
|
-
if (strategy === "full")
|
|
75228
|
-
usePlayerStore.getState().setSelectedElementId(null);
|
|
75229
|
-
return;
|
|
75230
|
-
}
|
|
75581
|
+
if (strategy === "full") return;
|
|
75231
75582
|
syncStoredAutomationFromPreview(previewIframeRef.current?.contentDocument ?? null);
|
|
75232
75583
|
},
|
|
75233
75584
|
[previewIframeRef, activeCompPathRef, reloadPreview, heldPreviewDoc]
|
|
@@ -76663,14 +77014,11 @@ function useTimelineDeleteOps({
|
|
|
76663
77014
|
}
|
|
76664
77015
|
const removeData = await removeResponse.json();
|
|
76665
77016
|
const removedContent = typeof removeData.content === "string" ? removeData.content : originalContent;
|
|
76666
|
-
const
|
|
76667
|
-
const patchedContent = unlinkInSource(
|
|
76668
|
-
setCompositionDurationToContent(removedContent, deleteContentEnd),
|
|
76669
|
-
alsoUnlink
|
|
76670
|
-
);
|
|
77017
|
+
const synced = syncCompositionDurationWithEnd(removedContent);
|
|
77018
|
+
const patchedContent = unlinkInSource(synced.source, alsoUnlink);
|
|
76671
77019
|
rollbackDuration = captureDurationRollback(previewIframeRef.current);
|
|
76672
|
-
if (
|
|
76673
|
-
usePlayerStore.getState().setDuration(
|
|
77020
|
+
if (synced.contentEnd > 0 && targetPath === (activeCompPath || "index.html")) {
|
|
77021
|
+
usePlayerStore.getState().setDuration(synced.contentEnd);
|
|
76674
77022
|
}
|
|
76675
77023
|
return { disk: removedContent, after: patchedContent };
|
|
76676
77024
|
}
|
|
@@ -82430,7 +82778,7 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
|
|
|
82430
82778
|
nestedFiles
|
|
82431
82779
|
});
|
|
82432
82780
|
}, [projectIdRef, previewIframeRef, reloadPreview, onCacheInvalidate, onFileContentChanged, forceReloadSdkSession, recordMutationEdit]);
|
|
82433
|
-
const runCommit = useCallback140(
|
|
82781
|
+
const runCommit = useCallback140((pid, compositionPath, targetPath, selection, mutation, options) => whileScriptWrites(async () => {
|
|
82434
82782
|
const result = await runMutationRequest(
|
|
82435
82783
|
[mutation],
|
|
82436
82784
|
options,
|
|
@@ -82441,8 +82789,8 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
|
|
|
82441
82789
|
trackKeyframeCommit([mutation], result, options);
|
|
82442
82790
|
options.onResult?.(result);
|
|
82443
82791
|
await finalizeSuccessfulMutation(pid, compositionPath, selection, mutation, targetPath, result, options);
|
|
82444
|
-
}, [showToast, finalizeSuccessfulMutation]);
|
|
82445
|
-
const runBatchCommit = useCallback140(
|
|
82792
|
+
}), [showToast, finalizeSuccessfulMutation]);
|
|
82793
|
+
const runBatchCommit = useCallback140((pid, compositionPath, targetPath, calls, options) => whileScriptWrites(async () => {
|
|
82446
82794
|
const first = calls[0];
|
|
82447
82795
|
const last = calls.at(-1);
|
|
82448
82796
|
if (!first || !last) return;
|
|
@@ -82462,7 +82810,7 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
|
|
|
82462
82810
|
const { instantPatch: _instantPatch, ...batchOptions } = options;
|
|
82463
82811
|
const allPatched = instantPatches.length === calls.length;
|
|
82464
82812
|
await finalizeSuccessfulMutation(pid, compositionPath, last.selection, last.mutation, targetPath, result, allPatched ? { ...batchOptions, instantPatches } : batchOptions);
|
|
82465
|
-
}, [showToast, finalizeSuccessfulMutation]);
|
|
82813
|
+
}), [showToast, finalizeSuccessfulMutation]);
|
|
82466
82814
|
const commitMutation = useMemo73(() => {
|
|
82467
82815
|
const serializeFile = (file, task) => {
|
|
82468
82816
|
if (writeProjectFile) {
|
|
@@ -83202,119 +83550,128 @@ function useGsapAwareGroupMove({
|
|
|
83202
83550
|
const writes = observeGsapGesture(gsapCommitMutation);
|
|
83203
83551
|
const writer = writes.commit;
|
|
83204
83552
|
if (!writer) return { ok: true, changed: false };
|
|
83205
|
-
const
|
|
83206
|
-
|
|
83207
|
-
|
|
83208
|
-
const
|
|
83209
|
-
|
|
83210
|
-
|
|
83211
|
-
|
|
83212
|
-
|
|
83213
|
-
|
|
83214
|
-
|
|
83215
|
-
|
|
83216
|
-
|
|
83217
|
-
|
|
83218
|
-
|
|
83219
|
-
|
|
83220
|
-
|
|
83221
|
-
|
|
83222
|
-
await writer(call.selection, call.mutation, call.options);
|
|
83223
|
-
}
|
|
83224
|
-
return;
|
|
83225
|
-
}
|
|
83226
|
-
await writer.batch(calls, {
|
|
83227
|
-
...calls.at(-1)?.options ?? { label: "Move animated layer (group)" },
|
|
83228
|
-
label: "Move animated layer (group)"
|
|
83553
|
+
const scripted = updates.some(
|
|
83554
|
+
({ selection, plainTranslate }) => !(plainTranslate ?? editsPlainCss(selection.element, "move"))
|
|
83555
|
+
);
|
|
83556
|
+
const commitGroup = async () => {
|
|
83557
|
+
const stamps = new Map(
|
|
83558
|
+
updates.map((u) => [u.selection, freezeDragStamp(u.selection.element)])
|
|
83559
|
+
);
|
|
83560
|
+
const toastRefusal = options.refusalToast !== false;
|
|
83561
|
+
const coalesceKey = `group-drag:${++groupDragCommitCounter}`;
|
|
83562
|
+
let renderOnCommit = false;
|
|
83563
|
+
const previewFallbackLatch = { pending: false };
|
|
83564
|
+
const withGroupOptions = (options2) => ({
|
|
83565
|
+
...options2,
|
|
83566
|
+
coalesceKey,
|
|
83567
|
+
coalesceMs: Number.POSITIVE_INFINITY,
|
|
83568
|
+
deferPreviewSync: !renderOnCommit,
|
|
83569
|
+
previewFallbackLatch
|
|
83229
83570
|
});
|
|
83230
|
-
|
|
83231
|
-
|
|
83232
|
-
|
|
83233
|
-
|
|
83234
|
-
|
|
83235
|
-
|
|
83236
|
-
|
|
83237
|
-
|
|
83238
|
-
|
|
83239
|
-
if (plainTranslate ?? editsPlainCss(selection.element, "move")) {
|
|
83240
|
-
refuseGsapTakeover(selection.element, toastRefusal ? showToast : () => {
|
|
83241
|
-
});
|
|
83242
|
-
return void offsetMembers.set(selection, true);
|
|
83571
|
+
const queued = [];
|
|
83572
|
+
const flushQueued = async () => {
|
|
83573
|
+
if (queued.length === 0) return;
|
|
83574
|
+
const calls = queued.splice(0, queued.length);
|
|
83575
|
+
if (!writer.batch) {
|
|
83576
|
+
for (const call of calls) {
|
|
83577
|
+
await writer(call.selection, call.mutation, call.options);
|
|
83578
|
+
}
|
|
83579
|
+
return;
|
|
83243
83580
|
}
|
|
83244
|
-
|
|
83245
|
-
|
|
83246
|
-
|
|
83247
|
-
|
|
83248
|
-
|
|
83249
|
-
|
|
83250
|
-
|
|
83251
|
-
|
|
83252
|
-
|
|
83253
|
-
|
|
83254
|
-
|
|
83255
|
-
|
|
83256
|
-
|
|
83257
|
-
|
|
83258
|
-
|
|
83259
|
-
|
|
83260
|
-
|
|
83261
|
-
|
|
83262
|
-
|
|
83263
|
-
|
|
83264
|
-
|
|
83265
|
-
|
|
83266
|
-
|
|
83267
|
-
|
|
83268
|
-
|
|
83269
|
-
|
|
83270
|
-
|
|
83271
|
-
|
|
83581
|
+
await writer.batch(calls, {
|
|
83582
|
+
...calls.at(-1)?.options ?? { label: "Move animated layer (group)" },
|
|
83583
|
+
label: "Move animated layer (group)"
|
|
83584
|
+
});
|
|
83585
|
+
};
|
|
83586
|
+
const coalescedCommit = (selection, mutation, options2) => {
|
|
83587
|
+
queued.push({ selection, mutation, options: withGroupOptions(options2) });
|
|
83588
|
+
return Promise.resolve();
|
|
83589
|
+
};
|
|
83590
|
+
const preflightAnimations = /* @__PURE__ */ new Map();
|
|
83591
|
+
const offsetMembers = /* @__PURE__ */ new Map();
|
|
83592
|
+
const preflightResults = await Promise.allSettled(
|
|
83593
|
+
updates.map(async ({ selection, next, plainTranslate }) => {
|
|
83594
|
+
if (plainTranslate ?? editsPlainCss(selection.element, "move")) {
|
|
83595
|
+
refuseGsapTakeover(selection.element, toastRefusal ? showToast : () => {
|
|
83596
|
+
});
|
|
83597
|
+
return void offsetMembers.set(selection, true);
|
|
83598
|
+
}
|
|
83599
|
+
const animations = await makeFetchFallback(selection, { failOnFetchError: true })();
|
|
83600
|
+
preflightAnimations.set(selection, animations);
|
|
83601
|
+
const outcome = await tryGsapDragIntercept(
|
|
83602
|
+
selection,
|
|
83603
|
+
next,
|
|
83604
|
+
animations,
|
|
83605
|
+
previewIframeRef.current,
|
|
83606
|
+
coalescedCommit,
|
|
83607
|
+
void 0,
|
|
83608
|
+
{ preflightOnly: true, group: true }
|
|
83609
|
+
);
|
|
83610
|
+
if (outcome.status === "element-offset") offsetMembers.set(selection, false);
|
|
83611
|
+
assertGsapEditPersisted(outcome);
|
|
83612
|
+
})
|
|
83272
83613
|
);
|
|
83273
|
-
|
|
83274
|
-
|
|
83275
|
-
|
|
83276
|
-
|
|
83277
|
-
|
|
83278
|
-
|
|
83279
|
-
|
|
83280
|
-
|
|
83281
|
-
|
|
83282
|
-
|
|
83283
|
-
|
|
83614
|
+
const preflightFailure = firstPreflightFailure(
|
|
83615
|
+
preflightResults,
|
|
83616
|
+
updates,
|
|
83617
|
+
offsetMembers,
|
|
83618
|
+
activeCompPath
|
|
83619
|
+
);
|
|
83620
|
+
if (preflightFailure) {
|
|
83621
|
+
trackGsapInteractionFailure(
|
|
83622
|
+
preflightFailure.error,
|
|
83623
|
+
preflightFailure.selection,
|
|
83624
|
+
"drag",
|
|
83625
|
+
"Move animated layer (group)",
|
|
83626
|
+
toastRefusal
|
|
83284
83627
|
);
|
|
83285
|
-
|
|
83286
|
-
|
|
83287
|
-
|
|
83628
|
+
throw preflightFailure.error;
|
|
83629
|
+
}
|
|
83630
|
+
const lastScriptWrite = updates.findLastIndex(
|
|
83631
|
+
({ selection }) => !offsetMembers.has(selection)
|
|
83632
|
+
);
|
|
83633
|
+
for (const [index, { selection, next }] of updates.entries()) {
|
|
83634
|
+
renderOnCommit = index === lastScriptWrite;
|
|
83635
|
+
const plain = offsetMembers.get(selection);
|
|
83636
|
+
if (plain !== void 0) {
|
|
83637
|
+
const staged = writes.drawKeepingUndone(
|
|
83638
|
+
() => stageElementPositionOffset(selection, next, plain, coalesceKey)
|
|
83639
|
+
);
|
|
83640
|
+
const result = await staged.save();
|
|
83641
|
+
writes.recordDomResult(result);
|
|
83642
|
+
continue;
|
|
83643
|
+
}
|
|
83644
|
+
try {
|
|
83645
|
+
const outcome = await tryGsapDragIntercept(
|
|
83646
|
+
selection,
|
|
83647
|
+
next,
|
|
83648
|
+
preflightAnimations.get(selection) ?? [],
|
|
83649
|
+
previewIframeRef.current,
|
|
83650
|
+
coalescedCommit,
|
|
83651
|
+
// The intercept re-reads the file to resolve a stale or shared tween.
|
|
83652
|
+
// Anything already queued has to be on disk before that read, or it
|
|
83653
|
+
// resolves against a file missing writes it is about to build on.
|
|
83654
|
+
async () => {
|
|
83655
|
+
await flushQueued();
|
|
83656
|
+
return makeFetchFallback(selection, { fresh: true })();
|
|
83657
|
+
},
|
|
83658
|
+
{ preflightPassed: true, stamp: stamps.get(selection) }
|
|
83659
|
+
);
|
|
83660
|
+
assertGsapEditPersisted(outcome);
|
|
83661
|
+
} catch (error) {
|
|
83662
|
+
trackGsapInteractionFailure(error, selection, "drag", "Move animated layer (group)");
|
|
83663
|
+
throw error;
|
|
83664
|
+
}
|
|
83288
83665
|
}
|
|
83289
83666
|
try {
|
|
83290
|
-
|
|
83291
|
-
|
|
83292
|
-
next,
|
|
83293
|
-
preflightAnimations.get(selection) ?? [],
|
|
83294
|
-
previewIframeRef.current,
|
|
83295
|
-
coalescedCommit,
|
|
83296
|
-
// The intercept re-reads the file to resolve a stale or shared tween.
|
|
83297
|
-
// Anything already queued has to be on disk before that read, or it
|
|
83298
|
-
// resolves against a file missing writes it is about to build on.
|
|
83299
|
-
async () => {
|
|
83300
|
-
await flushQueued();
|
|
83301
|
-
return makeFetchFallback(selection, { fresh: true })();
|
|
83302
|
-
},
|
|
83303
|
-
{ preflightPassed: true }
|
|
83304
|
-
);
|
|
83305
|
-
assertGsapEditPersisted(outcome);
|
|
83667
|
+
await flushQueued();
|
|
83668
|
+
return writes.finish();
|
|
83306
83669
|
} catch (error) {
|
|
83307
|
-
trackGsapInteractionFailure(error,
|
|
83670
|
+
trackGsapInteractionFailure(error, null, "drag", "Move animated layer (group)");
|
|
83308
83671
|
throw error;
|
|
83309
83672
|
}
|
|
83310
|
-
}
|
|
83311
|
-
|
|
83312
|
-
await flushQueued();
|
|
83313
|
-
return writes.finish();
|
|
83314
|
-
} catch (error) {
|
|
83315
|
-
trackGsapInteractionFailure(error, null, "drag", "Move animated layer (group)");
|
|
83316
|
-
throw error;
|
|
83317
|
-
}
|
|
83673
|
+
};
|
|
83674
|
+
return scripted ? whileScriptWrites(commitGroup) : commitGroup();
|
|
83318
83675
|
},
|
|
83319
83676
|
[
|
|
83320
83677
|
gsapCommitMutation,
|
|
@@ -83743,8 +84100,8 @@ function handOverDraftSize(selection, written, size, draw) {
|
|
|
83743
84100
|
});
|
|
83744
84101
|
return written;
|
|
83745
84102
|
}
|
|
83746
|
-
function firstSizeKey(selection, size, resizeGroup, animations) {
|
|
83747
|
-
const { autoKeyframeEnabled
|
|
84103
|
+
function firstSizeKey(selection, size, resizeGroup, animations, currentTime) {
|
|
84104
|
+
const { autoKeyframeEnabled } = usePlayerStore.getState();
|
|
83748
84105
|
const keyframed = animations.some(
|
|
83749
84106
|
(a) => a.keyframes && animationWritesAnyProperty(a, MOVED_OR_SIZED)
|
|
83750
84107
|
);
|
|
@@ -83759,6 +84116,7 @@ function tweenUsesScaleLonghands(anim) {
|
|
|
83759
84116
|
return inKeyframes || Object.keys(anim?.properties ?? {}).some(isLonghand);
|
|
83760
84117
|
}
|
|
83761
84118
|
async function tryGsapResizeIntercept(selection, size, animations, iframe, commitMutation, fetchFallbackAnimations, dragOffset, draw = (run) => run(), stamp) {
|
|
84119
|
+
const moment = editMoment(stamp);
|
|
83762
84120
|
const fetchedAnimations = fetchFallbackAnimations ? await fetchFallbackAnimations() : [];
|
|
83763
84121
|
const outcome = preflightGsapResizeIntercept(selection, animations, iframe, fetchedAnimations);
|
|
83764
84122
|
if (outcome.status === "blocked") return outcome;
|
|
@@ -83772,7 +84130,8 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
83772
84130
|
workingAnimations,
|
|
83773
84131
|
selection,
|
|
83774
84132
|
commitMutation,
|
|
83775
|
-
postSplitFetch
|
|
84133
|
+
postSplitFetch,
|
|
84134
|
+
moment.time
|
|
83776
84135
|
);
|
|
83777
84136
|
const anim = resolved2?.anim && animationWritesAnyProperty(resolved2.anim, resizeProperties) ? resolved2.anim : null;
|
|
83778
84137
|
logResize("intercept-enter", {
|
|
@@ -83788,7 +84147,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
83788
84147
|
(a) => animationWritesAnyProperty(a, SIZE_PROPS)
|
|
83789
84148
|
);
|
|
83790
84149
|
if (!scriptWritesSize) {
|
|
83791
|
-
const firstKey = firstSizeKey(selection, sized, resizeGroup, workingAnimations);
|
|
84150
|
+
const firstKey = firstSizeKey(selection, sized, resizeGroup, workingAnimations, moment.time);
|
|
83792
84151
|
if (!firstKey) return { status: "element-size" };
|
|
83793
84152
|
await commitMutation(selection, firstKey, { label: "Resize", softReload: true });
|
|
83794
84153
|
return handOverDraftSize(selection, { status: "persisted" }, sized, draw);
|
|
@@ -83800,7 +84159,8 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
83800
84159
|
const animatedTween = pickClosestToPlayhead(
|
|
83801
84160
|
workingAnimations.filter(
|
|
83802
84161
|
(a) => !isInstantHold(a) && resolveTweenDuration(a) > 0 && animationWritesAnyProperty(a, resizeProperties)
|
|
83803
|
-
)
|
|
84162
|
+
),
|
|
84163
|
+
moment.time
|
|
83804
84164
|
);
|
|
83805
84165
|
if (animatedTween) {
|
|
83806
84166
|
logResize("intercept-route", { route: "keyframed-size", tweenId: animatedTween.id });
|
|
@@ -83830,8 +84190,9 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
83830
84190
|
if (tweenDuration <= 0) {
|
|
83831
84191
|
return { status: "blocked", reason: "source-uneditable", detail: "zero-duration-tween" };
|
|
83832
84192
|
}
|
|
83833
|
-
const {
|
|
83834
|
-
const
|
|
84193
|
+
const { setActiveKeyframePct } = usePlayerStore.getState();
|
|
84194
|
+
const activeKeyframePct = moment.keyframePct;
|
|
84195
|
+
const pct = activeKeyframePct ?? computeCurrentPercentage(selection, anim, moment.time);
|
|
83835
84196
|
const selector = selectorFromSelection(selection);
|
|
83836
84197
|
let resizeProps;
|
|
83837
84198
|
let resizeBackfill;
|
|
@@ -83930,7 +84291,8 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
83930
84291
|
const positionTween = pickClosestToPlayhead(
|
|
83931
84292
|
currentAnimations.filter(
|
|
83932
84293
|
(a) => a.propertyGroup === "position" && !isInstantHold(a) && resolveTweenDuration(a) > 0
|
|
83933
|
-
)
|
|
84294
|
+
),
|
|
84295
|
+
moment.time
|
|
83934
84296
|
);
|
|
83935
84297
|
if (positionTween) {
|
|
83936
84298
|
logResize("scale-finalize", { route: "position-keyframe", tweenId: positionTween.id });
|
|
@@ -84371,7 +84733,10 @@ function useGsapAwareEditing({
|
|
|
84371
84733
|
const result = await stageElementPositionOffset(selection, next, true).save();
|
|
84372
84734
|
return writes.finish(result?.changed === true);
|
|
84373
84735
|
}
|
|
84374
|
-
|
|
84736
|
+
const writer = writes.commit;
|
|
84737
|
+
if (!writer) return;
|
|
84738
|
+
return whileScriptWrites(async () => {
|
|
84739
|
+
const stamp = freezeDragStamp(selection.element);
|
|
84375
84740
|
try {
|
|
84376
84741
|
const ownedAnimations = getGsapAnimationsForSelection(selection);
|
|
84377
84742
|
const targetAnimations = Array.isArray(ownedAnimations) ? ownedAnimations : await ownedAnimations;
|
|
@@ -84380,9 +84745,9 @@ function useGsapAwareEditing({
|
|
|
84380
84745
|
next,
|
|
84381
84746
|
targetAnimations,
|
|
84382
84747
|
previewIframeRef.current,
|
|
84383
|
-
|
|
84748
|
+
writer,
|
|
84384
84749
|
makeFetchFallback(selection),
|
|
84385
|
-
modifiers
|
|
84750
|
+
{ ...modifiers, stamp }
|
|
84386
84751
|
);
|
|
84387
84752
|
await saveMove(outcome, async () => {
|
|
84388
84753
|
const staged = writes.drawKeepingUndone(
|
|
@@ -84395,7 +84760,7 @@ function useGsapAwareEditing({
|
|
|
84395
84760
|
trackGsapInteractionFailure(error, selection, "drag", "Move animated layer");
|
|
84396
84761
|
throw error;
|
|
84397
84762
|
}
|
|
84398
|
-
}
|
|
84763
|
+
});
|
|
84399
84764
|
},
|
|
84400
84765
|
[
|
|
84401
84766
|
gsapCommitMutation,
|
|
@@ -84417,134 +84782,136 @@ function useGsapAwareEditing({
|
|
|
84417
84782
|
});
|
|
84418
84783
|
const handleGsapAwareBoxSizeCommit = useCallback147(
|
|
84419
84784
|
async (selection, next, offset, restore2 = () => void 0, route) => {
|
|
84420
|
-
const stamp = freezeDragStamp(selection.element);
|
|
84421
84785
|
const writes = observeGsapGesture(gsapCommitMutation);
|
|
84422
84786
|
if (route?.plainTranslate ?? editsPlainCss(selection.element, "resize")) {
|
|
84423
84787
|
const result = await handleDomBoxSizeCommit(selection, next, offset, restore2);
|
|
84424
84788
|
return writes.finish(result?.changed === true);
|
|
84425
84789
|
}
|
|
84426
|
-
|
|
84427
|
-
|
|
84428
|
-
|
|
84429
|
-
|
|
84430
|
-
|
|
84431
|
-
|
|
84432
|
-
|
|
84433
|
-
|
|
84434
|
-
|
|
84435
|
-
|
|
84436
|
-
const selector = selectorFromSelection(selection);
|
|
84437
|
-
const hasLivePositionTween = selector ? hasNonHoldTweenForElement(
|
|
84438
|
-
previewIframeRef.current,
|
|
84439
|
-
selector,
|
|
84440
|
-
void 0,
|
|
84441
|
-
POSITION_CHANNELS
|
|
84442
|
-
) : false;
|
|
84443
|
-
logResize("commit-route", {
|
|
84444
|
-
next,
|
|
84445
|
-
offset: offset ?? null,
|
|
84446
|
-
scaleRoute,
|
|
84447
|
-
animCount: targetAnimations.length,
|
|
84448
|
-
animGroups: targetAnimations.map((a) => `${a.propertyGroup}:${a.method}`)
|
|
84449
|
-
});
|
|
84450
|
-
let anchorMove = null;
|
|
84451
|
-
const stageCrop = prepareCropResize(selection.element);
|
|
84452
|
-
let cropUndoKey = null;
|
|
84453
|
-
const saveResizeAnchor = async (ownsDragOffset, commitMutation2, coalesceKey) => {
|
|
84454
|
-
if (offset && !ownsDragOffset) {
|
|
84455
|
-
const dragOutcome = await tryGsapDragIntercept(
|
|
84456
|
-
selection,
|
|
84457
|
-
offset,
|
|
84458
|
-
targetAnimations,
|
|
84459
|
-
previewIframeRef.current,
|
|
84460
|
-
commitMutation2,
|
|
84461
|
-
makeFetchFallback(selection),
|
|
84462
|
-
{ stamp }
|
|
84463
|
-
);
|
|
84464
|
-
await saveMove(dragOutcome, async () => {
|
|
84465
|
-
const plainAfterSettle = editsPlainCss(selection.element, "move");
|
|
84466
|
-
anchorMove = writes.drawKeepingUndone(
|
|
84467
|
-
() => stageElementPositionOffset(selection, offset, plainAfterSettle, coalesceKey)
|
|
84468
|
-
);
|
|
84469
|
-
});
|
|
84790
|
+
return whileScriptWrites(async () => {
|
|
84791
|
+
const stamp = freezeDragStamp(selection.element);
|
|
84792
|
+
let targetAnimations;
|
|
84793
|
+
try {
|
|
84794
|
+
const ownedAnimations = getGsapAnimationsForSelection(selection);
|
|
84795
|
+
targetAnimations = Array.isArray(ownedAnimations) ? ownedAnimations : await ownedAnimations;
|
|
84796
|
+
} catch (error) {
|
|
84797
|
+
restore2();
|
|
84798
|
+
trackGsapInteractionFailure(error, selection, "resize", "Resize animated layer");
|
|
84799
|
+
throw error;
|
|
84470
84800
|
}
|
|
84471
|
-
|
|
84472
|
-
|
|
84473
|
-
|
|
84474
|
-
|
|
84475
|
-
|
|
84476
|
-
|
|
84477
|
-
|
|
84478
|
-
|
|
84479
|
-
|
|
84480
|
-
|
|
84481
|
-
|
|
84482
|
-
|
|
84483
|
-
|
|
84484
|
-
|
|
84801
|
+
const scaleRoute = targetAnimations.some((anim) => anim.propertyGroup === "scale");
|
|
84802
|
+
const selector = selectorFromSelection(selection);
|
|
84803
|
+
const hasLivePositionTween = selector ? hasNonHoldTweenForElement(
|
|
84804
|
+
previewIframeRef.current,
|
|
84805
|
+
selector,
|
|
84806
|
+
void 0,
|
|
84807
|
+
POSITION_CHANNELS
|
|
84808
|
+
) : false;
|
|
84809
|
+
logResize("commit-route", {
|
|
84810
|
+
next,
|
|
84811
|
+
offset: offset ?? null,
|
|
84812
|
+
scaleRoute,
|
|
84813
|
+
animCount: targetAnimations.length,
|
|
84814
|
+
animGroups: targetAnimations.map((a) => `${a.propertyGroup}:${a.method}`)
|
|
84815
|
+
});
|
|
84816
|
+
let anchorMove = null;
|
|
84817
|
+
const stageCrop = prepareCropResize(selection.element);
|
|
84818
|
+
let cropUndoKey = null;
|
|
84819
|
+
const saveResizeAnchor = async (ownsDragOffset, commitMutation2, coalesceKey) => {
|
|
84820
|
+
if (offset && !ownsDragOffset) {
|
|
84821
|
+
const dragOutcome = await tryGsapDragIntercept(
|
|
84822
|
+
selection,
|
|
84485
84823
|
offset,
|
|
84486
|
-
|
|
84487
|
-
|
|
84824
|
+
targetAnimations,
|
|
84825
|
+
previewIframeRef.current,
|
|
84826
|
+
commitMutation2,
|
|
84827
|
+
makeFetchFallback(selection),
|
|
84828
|
+
{ stamp }
|
|
84488
84829
|
);
|
|
84489
|
-
|
|
84490
|
-
|
|
84491
|
-
|
|
84492
|
-
|
|
84493
|
-
|
|
84494
|
-
|
|
84495
|
-
|
|
84496
|
-
|
|
84497
|
-
|
|
84498
|
-
|
|
84499
|
-
|
|
84500
|
-
|
|
84501
|
-
|
|
84502
|
-
|
|
84503
|
-
|
|
84830
|
+
await saveMove(dragOutcome, async () => {
|
|
84831
|
+
const plainAfterSettle = editsPlainCss(selection.element, "move");
|
|
84832
|
+
anchorMove = writes.drawKeepingUndone(
|
|
84833
|
+
() => stageElementPositionOffset(selection, offset, plainAfterSettle, coalesceKey)
|
|
84834
|
+
);
|
|
84835
|
+
});
|
|
84836
|
+
}
|
|
84837
|
+
};
|
|
84838
|
+
await runGestureTransaction({
|
|
84839
|
+
element: selection.element,
|
|
84840
|
+
label: "Resize layer",
|
|
84841
|
+
draw: writes.drawKeepingUndone,
|
|
84842
|
+
settle: () => {
|
|
84843
|
+
if (!offset || scaleRoute || !selector) return;
|
|
84844
|
+
writes.drawKeepingUndone(() => {
|
|
84845
|
+
const gsapPos = readGsapPositionFromIframe(previewIframeRef.current, selector) ?? {
|
|
84846
|
+
x: 0,
|
|
84847
|
+
y: 0
|
|
84848
|
+
};
|
|
84849
|
+
const { newX, newY } = computeDraggedGsapPosition(
|
|
84850
|
+
selection.element,
|
|
84504
84851
|
offset,
|
|
84505
|
-
|
|
84852
|
+
gsapPos,
|
|
84506
84853
|
stamp
|
|
84507
84854
|
);
|
|
84508
|
-
|
|
84509
|
-
|
|
84510
|
-
|
|
84511
|
-
|
|
84855
|
+
logResize("sync-settle", { gsapPos, offset, newX, newY });
|
|
84856
|
+
setElementGsapPosition(selection.element, newX, newY);
|
|
84857
|
+
});
|
|
84858
|
+
},
|
|
84859
|
+
persist: async (commit2, coalesceKey) => {
|
|
84860
|
+
if (writes.commit) {
|
|
84861
|
+
const commitMutation2 = commit2(writes.commit);
|
|
84862
|
+
try {
|
|
84863
|
+
const outcome = await tryGsapResizeIntercept(
|
|
84864
|
+
selection,
|
|
84865
|
+
next,
|
|
84866
|
+
targetAnimations,
|
|
84867
|
+
previewIframeRef.current,
|
|
84868
|
+
commitMutation2,
|
|
84869
|
+
makeFetchFallback(selection),
|
|
84870
|
+
offset,
|
|
84871
|
+
writes.drawKeepingUndone,
|
|
84872
|
+
stamp
|
|
84512
84873
|
);
|
|
84513
|
-
|
|
84514
|
-
|
|
84515
|
-
|
|
84516
|
-
|
|
84517
|
-
|
|
84518
|
-
|
|
84519
|
-
|
|
84520
|
-
|
|
84521
|
-
|
|
84522
|
-
|
|
84523
|
-
|
|
84524
|
-
|
|
84525
|
-
|
|
84526
|
-
|
|
84874
|
+
assertGsapEditPersisted(outcome);
|
|
84875
|
+
if (outcome.status === "element-size") {
|
|
84876
|
+
const result = await writes.drawKeepingUndone(
|
|
84877
|
+
() => handleDomBoxSizeCommit(selection, next, void 0, void 0, coalesceKey)
|
|
84878
|
+
);
|
|
84879
|
+
writes.recordDomResult(result);
|
|
84880
|
+
} else cropUndoKey = coalesceKey;
|
|
84881
|
+
const ownsDragOffset = outcome.status === "persisted" && outcome.ownsDragOffset === true;
|
|
84882
|
+
logResize("intercept-handled", {
|
|
84883
|
+
scaleRoute,
|
|
84884
|
+
ownsDragOffset,
|
|
84885
|
+
willForwardOffset: !!(offset && !ownsDragOffset)
|
|
84886
|
+
});
|
|
84887
|
+
await saveResizeAnchor(ownsDragOffset, commitMutation2, coalesceKey);
|
|
84888
|
+
logResizeSettle(selection.element, ownsDragOffset ? "gsap-scale" : "gsap-size");
|
|
84889
|
+
return;
|
|
84890
|
+
} catch (error) {
|
|
84891
|
+
trackGsapInteractionFailure(error, selection, "resize", "Resize animated layer");
|
|
84892
|
+
throw error;
|
|
84893
|
+
}
|
|
84527
84894
|
}
|
|
84528
|
-
|
|
84529
|
-
|
|
84530
|
-
|
|
84531
|
-
|
|
84532
|
-
|
|
84533
|
-
|
|
84534
|
-
|
|
84535
|
-
|
|
84536
|
-
|
|
84537
|
-
|
|
84538
|
-
|
|
84539
|
-
}
|
|
84540
|
-
|
|
84541
|
-
|
|
84542
|
-
|
|
84543
|
-
|
|
84544
|
-
|
|
84545
|
-
|
|
84895
|
+
throw new Error("Resize of a GSAP-owned box has no GSAP writer");
|
|
84896
|
+
},
|
|
84897
|
+
afterBufferedCommitsSaved: async () => {
|
|
84898
|
+
const anchorResult = await anchorMove?.save();
|
|
84899
|
+
writes.recordDomResult(anchorResult);
|
|
84900
|
+
if (cropUndoKey) {
|
|
84901
|
+
const cropResult = await writes.drawKeepingUndone(
|
|
84902
|
+
() => saveCropResize(stageCrop, selection, commitPositionPatchToHtml, cropUndoKey)
|
|
84903
|
+
);
|
|
84904
|
+
writes.recordDomResult(cropResult);
|
|
84905
|
+
}
|
|
84906
|
+
},
|
|
84907
|
+
restore: () => {
|
|
84908
|
+
anchorMove?.rollback();
|
|
84909
|
+
restore2();
|
|
84910
|
+
},
|
|
84911
|
+
skipPixelAssert: hasLivePositionTween
|
|
84912
|
+
});
|
|
84913
|
+
return writes.finish();
|
|
84546
84914
|
});
|
|
84547
|
-
return writes.finish();
|
|
84548
84915
|
},
|
|
84549
84916
|
[
|
|
84550
84917
|
handleDomBoxSizeCommit,
|
|
@@ -84564,7 +84931,10 @@ function useGsapAwareEditing({
|
|
|
84564
84931
|
const result = await handleDomRotationCommit(selection, next);
|
|
84565
84932
|
return writes.finish(result?.changed === true);
|
|
84566
84933
|
}
|
|
84567
|
-
|
|
84934
|
+
const writer = writes.commit;
|
|
84935
|
+
if (!writer) return;
|
|
84936
|
+
return whileScriptWrites(async () => {
|
|
84937
|
+
const stamp = freezeDragStamp(selection.element);
|
|
84568
84938
|
try {
|
|
84569
84939
|
const targetAnimations = await getGsapAnimationsForSelection(selection);
|
|
84570
84940
|
const outcome = await tryGsapRotationIntercept(
|
|
@@ -84572,8 +84942,9 @@ function useGsapAwareEditing({
|
|
|
84572
84942
|
next.angle,
|
|
84573
84943
|
targetAnimations,
|
|
84574
84944
|
previewIframeRef.current,
|
|
84575
|
-
|
|
84576
|
-
makeFetchFallback(selection)
|
|
84945
|
+
writer,
|
|
84946
|
+
makeFetchFallback(selection),
|
|
84947
|
+
stamp
|
|
84577
84948
|
);
|
|
84578
84949
|
assertGsapEditPersisted(outcome);
|
|
84579
84950
|
return writes.finish();
|
|
@@ -84581,7 +84952,7 @@ function useGsapAwareEditing({
|
|
|
84581
84952
|
trackGsapInteractionFailure(error, selection, "rotation", "Rotate animated layer");
|
|
84582
84953
|
throw error;
|
|
84583
84954
|
}
|
|
84584
|
-
}
|
|
84955
|
+
});
|
|
84585
84956
|
},
|
|
84586
84957
|
[
|
|
84587
84958
|
gsapCommitMutation,
|
|
@@ -86929,6 +87300,7 @@ function useEditHistoryActions({
|
|
|
86929
87300
|
const apply = useCallback154(
|
|
86930
87301
|
async (direction) => {
|
|
86931
87302
|
const noun = direction === "undo" ? "Undo" : "Redo";
|
|
87303
|
+
if (direction === "undo" && cancelNewestStudioWaitingPress()) return;
|
|
86932
87304
|
const pendingEditShown = direction === "undo" ? paintBackNewestStudioPendingEdit() : null;
|
|
86933
87305
|
const predicted = pendingEditShown ? null : editHistory.predict?.(direction) ?? null;
|
|
86934
87306
|
const predictedShown = predicted ? showHistoryRestoreNow?.(predicted.files) ?? null : null;
|
|
@@ -88027,6 +88399,7 @@ function useCaptionDetection({
|
|
|
88027
88399
|
|
|
88028
88400
|
// src/hooks/useConsoleErrorCapture.ts
|
|
88029
88401
|
import { useCallback as useCallback157, useEffect as useEffect130, useRef as useRef160, useState as useState125 } from "react";
|
|
88402
|
+
import { STUDIO_PREVIEW_ERRORS } from "@hyperframes/core/studio-preview-mark";
|
|
88030
88403
|
function useConsoleErrorCapture(previewIframe) {
|
|
88031
88404
|
const [consoleErrors, setConsoleErrors] = useState125(null);
|
|
88032
88405
|
const consoleErrorsRef = useRef160([]);
|
|
@@ -88035,6 +88408,7 @@ function useConsoleErrorCapture(previewIframe) {
|
|
|
88035
88408
|
setConsoleErrors(null);
|
|
88036
88409
|
}, []);
|
|
88037
88410
|
useEffect130(() => {
|
|
88411
|
+
resetErrors();
|
|
88038
88412
|
if (!previewIframe) return;
|
|
88039
88413
|
let patchedWin = null;
|
|
88040
88414
|
let origConsoleError = null;
|
|
@@ -88054,48 +88428,42 @@ function useConsoleErrorCapture(previewIframe) {
|
|
|
88054
88428
|
};
|
|
88055
88429
|
const attachErrorCapture = () => {
|
|
88056
88430
|
detachErrorCapture();
|
|
88431
|
+
resetErrors();
|
|
88057
88432
|
try {
|
|
88058
88433
|
const win = previewIframe.contentWindow;
|
|
88059
88434
|
if (!win) return;
|
|
88060
88435
|
if (win.__hfErrorCapture) return;
|
|
88061
88436
|
win.__hfErrorCapture = true;
|
|
88062
88437
|
patchedWin = win;
|
|
88063
|
-
|
|
88064
|
-
|
|
88065
|
-
origConsoleError(...args);
|
|
88066
|
-
const text = args.map((a) => a instanceof Error ? a.message : String(a)).join(" ");
|
|
88067
|
-
if (text.includes("favicon")) return;
|
|
88438
|
+
const record = (texts) => {
|
|
88439
|
+
if (texts.length === 0) return;
|
|
88068
88440
|
consoleErrorsRef.current = [
|
|
88069
88441
|
...consoleErrorsRef.current,
|
|
88070
|
-
{ severity: "error", message
|
|
88442
|
+
...texts.map((message) => ({ severity: "error", message }))
|
|
88071
88443
|
];
|
|
88072
88444
|
setConsoleErrors([...consoleErrorsRef.current]);
|
|
88073
88445
|
};
|
|
88074
|
-
|
|
88075
|
-
|
|
88076
|
-
|
|
88077
|
-
|
|
88078
|
-
|
|
88079
|
-
];
|
|
88080
|
-
setConsoleErrors([...consoleErrorsRef.current]);
|
|
88446
|
+
origConsoleError = win.console.error.bind(win.console);
|
|
88447
|
+
win.console.error = function(...args) {
|
|
88448
|
+
origConsoleError(...args);
|
|
88449
|
+
const text = args.map((a) => a instanceof Error ? a.message : String(a)).join(" ");
|
|
88450
|
+
if (!text.includes("favicon")) record([text]);
|
|
88081
88451
|
};
|
|
88452
|
+
errorHandler = (e) => record([e.message || String(e)]);
|
|
88082
88453
|
win.addEventListener("error", errorHandler);
|
|
88454
|
+
const raised = Reflect.get(win, STUDIO_PREVIEW_ERRORS);
|
|
88455
|
+
if (Array.isArray(raised)) record(raised.map(String));
|
|
88083
88456
|
} catch {
|
|
88084
88457
|
}
|
|
88085
88458
|
};
|
|
88086
88459
|
attachErrorCapture();
|
|
88087
|
-
|
|
88088
|
-
consoleErrorsRef.current = [];
|
|
88089
|
-
setConsoleErrors(null);
|
|
88090
|
-
attachErrorCapture();
|
|
88091
|
-
};
|
|
88092
|
-
previewIframe.addEventListener("load", handleLoad);
|
|
88460
|
+
previewIframe.addEventListener("load", attachErrorCapture);
|
|
88093
88461
|
return () => {
|
|
88094
|
-
previewIframe.removeEventListener("load",
|
|
88462
|
+
previewIframe.removeEventListener("load", attachErrorCapture);
|
|
88095
88463
|
detachErrorCapture();
|
|
88096
88464
|
};
|
|
88097
|
-
}, [previewIframe]);
|
|
88098
|
-
return { consoleErrors, setConsoleErrors
|
|
88465
|
+
}, [previewIframe, resetErrors]);
|
|
88466
|
+
return { consoleErrors, setConsoleErrors };
|
|
88099
88467
|
}
|
|
88100
88468
|
|
|
88101
88469
|
// src/hooks/useFrameCapture.ts
|
|
@@ -93402,7 +93770,7 @@ var LayersPanel = memo50(function LayersPanel2({ host }) {
|
|
|
93402
93770
|
"div",
|
|
93403
93771
|
{
|
|
93404
93772
|
ref: scrollContainerRef,
|
|
93405
|
-
className: "relative min-h-0 flex-1 overflow-y-auto py-1",
|
|
93773
|
+
className: "relative min-h-0 flex-1 select-none overflow-y-auto py-1",
|
|
93406
93774
|
onPointerMove: handleContainerPointerMove,
|
|
93407
93775
|
onPointerUp: handleContainerPointerUp,
|
|
93408
93776
|
onPointerCancel: handleContainerPointerUp,
|
|
@@ -98665,7 +99033,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
|
|
|
98665
99033
|
const [compIdToSrc, setCompIdToSrc] = useState160(/* @__PURE__ */ new Map());
|
|
98666
99034
|
const previewIframe = useOwnPreviewIframe();
|
|
98667
99035
|
const [compositionLoading, setCompositionLoading] = useState160(true);
|
|
98668
|
-
const [refreshKey,
|
|
99036
|
+
const [refreshKey, setRefreshKeyState] = useState160(0);
|
|
98669
99037
|
const [previewDocumentVersion, refreshPreviewDocumentVersion] = usePreviewDocumentVersion();
|
|
98670
99038
|
const [blockPreview, setBlockPreview] = useState160(null);
|
|
98671
99039
|
const previewIframeRef = useRef187(null);
|
|
@@ -98690,7 +99058,11 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
|
|
|
98690
99058
|
const handleDomZIndexReorderCommitRef = useRef187(null);
|
|
98691
99059
|
const pendingTimelineEditPathRef = useRef187(/* @__PURE__ */ new Set());
|
|
98692
99060
|
const isGestureRecordingRef = useRef187(false);
|
|
98693
|
-
const
|
|
99061
|
+
const setRefreshKey = useCallback194((next) => {
|
|
99062
|
+
requestPreviewReload();
|
|
99063
|
+
setRefreshKeyState(next);
|
|
99064
|
+
}, []);
|
|
99065
|
+
const reloadPreview = useCallback194(() => setRefreshKey((k) => k + 1), [setRefreshKey]);
|
|
98694
99066
|
const fileManagerResult = useFileManager({
|
|
98695
99067
|
projectId,
|
|
98696
99068
|
showToast,
|
|
@@ -98729,7 +99101,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
|
|
|
98729
99101
|
recordEdit: editHistory.recordEdit,
|
|
98730
99102
|
previewIframeRef,
|
|
98731
99103
|
activeCompPathRef,
|
|
98732
|
-
reloadPreview
|
|
99104
|
+
reloadPreview
|
|
98733
99105
|
});
|
|
98734
99106
|
const previewPersistence = useStableHandlers(previewPersistenceResult, projectId);
|
|
98735
99107
|
const externalFileChanges = useStudioExternalFileChanges({
|
|
@@ -98941,11 +99313,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
|
|
|
98941
99313
|
waitForPendingDomEditSaves: previewPersistence.waitForPendingDomEditSaves
|
|
98942
99314
|
});
|
|
98943
99315
|
const frameCapture = useStableHandlers(frameCaptureResult, projectId);
|
|
98944
|
-
const {
|
|
98945
|
-
consoleErrors,
|
|
98946
|
-
setConsoleErrors,
|
|
98947
|
-
resetErrors: resetConsoleErrors
|
|
98948
|
-
} = useConsoleErrorCapture(previewIframe);
|
|
99316
|
+
const { consoleErrors, setConsoleErrors } = useConsoleErrorCapture(previewIframe);
|
|
98949
99317
|
const fileDrop = useGlobalFileDrop(timelineEditing.handleTimelineFileDrop);
|
|
98950
99318
|
const handleToggleRecordingRef = useRef187(() => {
|
|
98951
99319
|
});
|
|
@@ -98970,10 +99338,9 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
|
|
|
98970
99338
|
previewIframeRef.current = iframe;
|
|
98971
99339
|
usePreviewIframeStore.getState().setIframe(iframe);
|
|
98972
99340
|
appHotkeys.syncPreviewHotkeys(iframe);
|
|
98973
|
-
resetConsoleErrors();
|
|
98974
99341
|
refreshPreviewDocumentVersion();
|
|
98975
99342
|
},
|
|
98976
|
-
[appHotkeys,
|
|
99343
|
+
[appHotkeys, refreshPreviewDocumentVersion]
|
|
98977
99344
|
);
|
|
98978
99345
|
const rightPanel = useRightPanelIntent();
|
|
98979
99346
|
const { inspectorPanelActive, shouldShowMotionPath, shouldShowSelectedDomBounds } = useInspectorState(
|
|
@@ -99795,6 +100162,7 @@ export {
|
|
|
99795
100162
|
buttonBase,
|
|
99796
100163
|
buttonSizes,
|
|
99797
100164
|
buttonVariants,
|
|
100165
|
+
cancelNewestStudioWaitingPress,
|
|
99798
100166
|
cn,
|
|
99799
100167
|
collectSnapContext,
|
|
99800
100168
|
collectStudioLookScene,
|