@hyperframes/studio 0.8.97 → 0.8.99
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-Biu5_W0l.js → hyperframes-player-Rml34FRW.js} +1 -1
- package/dist/assets/{index-BdV5T-QI.js → index-CVDArg3m.js} +188 -188
- package/dist/assets/{index-B5Z-1RW9.js → index-C_fi-jTe.js} +1 -1
- package/dist/assets/{index-CWuozokW.js → index-D9YzDuBx.js} +1 -1
- package/dist/index.d.ts +16 -4
- package/dist/index.html +1 -1
- package/dist/index.js +758 -607
- package/dist/index.js.map +1 -1
- package/package.json +10 -9
- package/src/components/EditorShell.tsx +7 -0
- package/src/components/editor/DomEditCropHandles.test.tsx +34 -66
- package/src/components/editor/DomEditCropHandles.tsx +30 -62
- package/src/components/editor/DomEditOverlay.test.ts +2 -2
- package/src/components/editor/DomEditOverlay.tsx +0 -27
- package/src/components/editor/DomEditSelectionChrome.test.tsx +0 -5
- package/src/components/editor/DomEditSelectionChrome.tsx +0 -6
- package/src/components/editor/clickAfterPreventedPress.test.tsx +122 -0
- package/src/components/editor/cropResize.test.ts +129 -0
- package/src/components/editor/cropResize.ts +143 -0
- package/src/components/editor/domEditOverlayCrop.ts +65 -15
- package/src/components/editor/domEditOverlayCropLift.test.ts +44 -0
- package/src/components/editor/domEditOverlayGestures.ts +2 -5
- package/src/components/editor/elementPositionOffset.ts +5 -4
- package/src/components/editor/manualEdits.test.ts +22 -8
- package/src/components/editor/manualEditsDom.ts +27 -11
- package/src/components/editor/manualEditsParsing.ts +0 -4
- package/src/components/editor/manualEditsSnapshot.ts +3 -0
- package/src/components/editor/manualOffsetDrag.test.ts +14 -0
- package/src/components/editor/propertyPanelFont.test.tsx +48 -5
- package/src/components/editor/propertyPanelFont.tsx +2 -1
- package/src/components/editor/shiftDragAxisLock.test.tsx +0 -2
- package/src/components/nle/TimelinePane.tsx +4 -0
- package/src/hooks/domSelectionTestHarness.ts +8 -0
- package/src/hooks/draggedGsapPosition.ts +4 -2
- package/src/hooks/gsapDragCommit.ts +6 -6
- package/src/hooks/gsapEditOutcome.ts +6 -0
- package/src/hooks/gsapResizeIntercept.ts +5 -5
- package/src/hooks/gsapRuntimeBridge.test.ts +11 -0
- package/src/hooks/gsapRuntimeBridge.ts +2 -1
- package/src/hooks/gsapRuntimeKeyframes.test.ts +7 -0
- package/src/hooks/gsapRuntimeKeyframes.ts +34 -21
- package/src/hooks/timelineTimingSync.ts +40 -4
- package/src/hooks/useAnimatedPropertyCommit.test.tsx +40 -1
- package/src/hooks/useAnimatedPropertyCommit.ts +11 -13
- package/src/hooks/useCommitPreflightCapabilities.ts +3 -11
- package/src/hooks/useCropOverlay.ts +8 -2
- package/src/hooks/useDomEditCommits.test.tsx +6 -1
- package/src/hooks/useDomEditCommits.ts +1 -0
- package/src/hooks/useDomEditPositionPatchCommit.ts +2 -2
- package/src/hooks/useDomEditSession.ts +2 -0
- package/src/hooks/useDomGeometryCommit.ts +1 -0
- package/src/hooks/useDomGeometryCommits.test.tsx +112 -0
- package/src/hooks/useDomGeometryCommits.ts +5 -0
- package/src/hooks/useElementLifecycleOps.multiDelete.test.tsx +3 -1
- package/src/hooks/useGsapAnimationFetchFallback.test.ts +44 -3
- package/src/hooks/useGsapAnimationFetchFallback.ts +11 -35
- package/src/hooks/useGsapAwareEditing.test.tsx +101 -5
- package/src/hooks/useGsapAwareEditing.ts +37 -23
- package/src/hooks/useGsapTweenCache.element.test.tsx +23 -1
- package/src/hooks/useGsapTweenCache.ts +0 -24
- package/src/hooks/useTimelineEditing.test.tsx +190 -135
- package/src/hooks/useTimelineEditing.ts +13 -13
- package/src/hooks/useTimelineGroupEditing.ts +13 -9
- package/src/index.ts +4 -1
- package/src/player/components/ClipContextMenu.test.tsx +182 -0
- package/src/player/components/ClipContextMenu.tsx +52 -10
- package/src/player/components/TimelineOverlays.test.ts +30 -7
- package/src/player/components/TimelineOverlays.tsx +7 -1
- package/src/player/components/TimelineProvider.tsx +1 -0
- package/src/player/components/TimelineTypes.ts +10 -0
- package/src/player/components/menuKeyboardNav.ts +12 -5
- package/src/player/components/useTimelineProviderState.tsx +2 -0
- package/src/player/components/useTimelineVirtualRows.test.tsx +30 -1
- package/src/utils/rounding.ts +5 -0
- package/src/utils/sdkEditTransaction.ts +10 -3
package/dist/index.js
CHANGED
|
@@ -2173,6 +2173,9 @@ function getTimelinePlayheadTransform(time, pixelsPerSecond, contentOrigin, atRe
|
|
|
2173
2173
|
function roundTo3(val) {
|
|
2174
2174
|
return Math.round(val * 1e3) / 1e3;
|
|
2175
2175
|
}
|
|
2176
|
+
function roundToLayoutPx(val) {
|
|
2177
|
+
return Math.round(val);
|
|
2178
|
+
}
|
|
2176
2179
|
function roundToCenti(val) {
|
|
2177
2180
|
return Math.round(val * 100) / 100;
|
|
2178
2181
|
}
|
|
@@ -12872,6 +12875,7 @@ function useTimelineProviderState({
|
|
|
12872
12875
|
onPasteClip,
|
|
12873
12876
|
onDuplicateClip,
|
|
12874
12877
|
canPasteClip,
|
|
12878
|
+
clipMenuItems,
|
|
12875
12879
|
theme: themeOverrides,
|
|
12876
12880
|
showAudioEffects = true,
|
|
12877
12881
|
showKeyframes = true,
|
|
@@ -13170,6 +13174,7 @@ function useTimelineProviderState({
|
|
|
13170
13174
|
onPasteClip,
|
|
13171
13175
|
onDuplicateClip,
|
|
13172
13176
|
canPasteClip,
|
|
13177
|
+
clipMenuItems,
|
|
13173
13178
|
onSelectElement,
|
|
13174
13179
|
selectedElementId,
|
|
13175
13180
|
setRangeSelectionRef,
|
|
@@ -19806,6 +19811,8 @@ async function postGsapMutation(projectId, filePath, mutation, fallback) {
|
|
|
19806
19811
|
}
|
|
19807
19812
|
|
|
19808
19813
|
// src/hooks/timelineTimingSync.ts
|
|
19814
|
+
import { findTimelineScript } from "@hyperframes/core/gsap-parser-acorn";
|
|
19815
|
+
import { walkCompositionDescendants } from "@hyperframes/parsers/hf-ids";
|
|
19809
19816
|
async function readFileContent(projectId, targetPath) {
|
|
19810
19817
|
if (targetPath.includes("\0") || targetPath.includes("..")) {
|
|
19811
19818
|
throw new Error(`Unsafe path: ${targetPath}`);
|
|
@@ -20005,8 +20012,19 @@ async function scaleGsapPositions(projectId, filePath, elementId2, oldStart, old
|
|
|
20005
20012
|
"scale-positions failed"
|
|
20006
20013
|
);
|
|
20007
20014
|
}
|
|
20015
|
+
function sdkTimingGsapSync(result) {
|
|
20016
|
+
const timelineText = (html2) => {
|
|
20017
|
+
const scripts = [];
|
|
20018
|
+
walkCompositionDescendants(new DOMParser().parseFromString(html2, "text/html"), (el) => {
|
|
20019
|
+
if (el.tagName.toLowerCase() === "script") scripts.push(el);
|
|
20020
|
+
});
|
|
20021
|
+
return findTimelineScript(scripts)?.textContent ?? null;
|
|
20022
|
+
};
|
|
20023
|
+
if (timelineText(result.before) === timelineText(result.after)) return null;
|
|
20024
|
+
return { mutated: true, scriptText: extractGsapScriptText(result.after) };
|
|
20025
|
+
}
|
|
20008
20026
|
function finishClipTimingFallback(input) {
|
|
20009
|
-
const { projectId, targetPath, domId, edit } = input;
|
|
20027
|
+
const { projectId, targetPath, domId, edit, sdkGsap } = input;
|
|
20010
20028
|
const timingChanged = edit.kind === "shift" ? edit.delta !== 0 : edit.from.start !== edit.to.start || edit.from.duration !== edit.to.duration;
|
|
20011
20029
|
const runMutation = (pid, id) => edit.kind === "shift" ? shiftGsapPositions(pid, targetPath, id, edit.delta) : scaleGsapPositions(
|
|
20012
20030
|
pid,
|
|
@@ -20021,7 +20039,7 @@ function finishClipTimingFallback(input) {
|
|
|
20021
20039
|
return finishTimelineTimingFallback({
|
|
20022
20040
|
iframe: input.iframe,
|
|
20023
20041
|
reloadPreview: input.reloadPreview,
|
|
20024
|
-
gsapMutation: timingChanged && domId && projectId ? () => foldGsapMutationIntoHistory({
|
|
20042
|
+
gsapMutation: sdkGsap ? () => Promise.resolve(sdkGsap) : timingChanged && domId && projectId ? () => foldGsapMutationIntoHistory({
|
|
20025
20043
|
writeFile: input.writeProjectFile,
|
|
20026
20044
|
paths: [targetPath],
|
|
20027
20045
|
projectId,
|
|
@@ -20041,6 +20059,17 @@ async function finishGroupTimingGsapFallback(input) {
|
|
|
20041
20059
|
(change) => input.resolveChangePath(change.element) !== activePath
|
|
20042
20060
|
);
|
|
20043
20061
|
const onGsapError = (err) => console.error(`[Timeline] ${input.errorLabel}`, err);
|
|
20062
|
+
const { sdkGsap } = input;
|
|
20063
|
+
if (sdkGsap) {
|
|
20064
|
+
await finishTimelineTimingFallback({
|
|
20065
|
+
iframe: input.iframe,
|
|
20066
|
+
reloadPreview: input.reloadPreview,
|
|
20067
|
+
gsapMutation: () => Promise.resolve(sdkGsap),
|
|
20068
|
+
onGsapError,
|
|
20069
|
+
rebindWhenUnmutated: !otherFileChanged
|
|
20070
|
+
});
|
|
20071
|
+
return;
|
|
20072
|
+
}
|
|
20044
20073
|
await finishTimelineTimingFallback({
|
|
20045
20074
|
iframe: input.iframe,
|
|
20046
20075
|
reloadPreview: input.reloadPreview,
|
|
@@ -21575,7 +21604,7 @@ var TimelineCanvas = memo13(function TimelineCanvas2() {
|
|
|
21575
21604
|
});
|
|
21576
21605
|
|
|
21577
21606
|
// src/player/components/TimelineOverlays.tsx
|
|
21578
|
-
import { useEffect as useEffect30 } from "react";
|
|
21607
|
+
import { useEffect as useEffect30, useMemo as useMemo32 } from "react";
|
|
21579
21608
|
|
|
21580
21609
|
// src/player/components/EditModal.tsx
|
|
21581
21610
|
import { useState as useState24, useCallback as useCallback33, useMemo as useMemo31, useRef as useRef40 } from "react";
|
|
@@ -21831,7 +21860,9 @@ function useMenuKeyboardNav(menuRef) {
|
|
|
21831
21860
|
menu.addEventListener("keydown", onKeyDown);
|
|
21832
21861
|
return () => {
|
|
21833
21862
|
menu.removeEventListener("keydown", onKeyDown);
|
|
21834
|
-
|
|
21863
|
+
const active = document.activeElement;
|
|
21864
|
+
const focusLeftWithMenu = active === null || active === document.body || menu.contains(active);
|
|
21865
|
+
if (focusLeftWithMenu && previouslyFocused instanceof HTMLElement && document.contains(previouslyFocused)) {
|
|
21835
21866
|
previouslyFocused.focus();
|
|
21836
21867
|
}
|
|
21837
21868
|
};
|
|
@@ -21967,6 +21998,36 @@ function KeyframeDiamondContextMenu({
|
|
|
21967
21998
|
import { memo as memo14 } from "react";
|
|
21968
21999
|
import { createPortal as createPortal4 } from "react-dom";
|
|
21969
22000
|
import { Fragment as Fragment18, jsx as jsx58, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
22001
|
+
var itemClass = (enabled) => `w-full flex items-center justify-between px-3 py-1.5 text-xs text-left outline-none${enabled ? " focus-visible:bg-neutral-800 text-neutral-300 hover:bg-neutral-800 cursor-pointer" : " text-neutral-600 cursor-not-allowed"}`;
|
|
22002
|
+
function HostItems({
|
|
22003
|
+
items,
|
|
22004
|
+
onClose
|
|
22005
|
+
}) {
|
|
22006
|
+
return /* @__PURE__ */ jsxs38(Fragment18, { children: [
|
|
22007
|
+
items.map((item) => /* @__PURE__ */ jsxs38(
|
|
22008
|
+
"button",
|
|
22009
|
+
{
|
|
22010
|
+
type: "button",
|
|
22011
|
+
role: "menuitem",
|
|
22012
|
+
className: itemClass(!item.disabled),
|
|
22013
|
+
disabled: item.disabled,
|
|
22014
|
+
onClick: () => {
|
|
22015
|
+
onClose();
|
|
22016
|
+
item.onSelect();
|
|
22017
|
+
},
|
|
22018
|
+
children: [
|
|
22019
|
+
/* @__PURE__ */ jsxs38("span", { className: "flex items-center gap-2", children: [
|
|
22020
|
+
item.icon,
|
|
22021
|
+
item.label
|
|
22022
|
+
] }),
|
|
22023
|
+
item.shortcut && /* @__PURE__ */ jsx58("span", { className: "text-neutral-500 text-[10px] ml-3", children: item.shortcut })
|
|
22024
|
+
]
|
|
22025
|
+
},
|
|
22026
|
+
item.id
|
|
22027
|
+
)),
|
|
22028
|
+
/* @__PURE__ */ jsx58("div", { className: "my-1 border-t border-neutral-700/60" })
|
|
22029
|
+
] });
|
|
22030
|
+
}
|
|
21970
22031
|
var ClipContextMenu = memo14(function ClipContextMenu2({
|
|
21971
22032
|
x,
|
|
21972
22033
|
y,
|
|
@@ -21978,7 +22039,8 @@ var ClipContextMenu = memo14(function ClipContextMenu2({
|
|
|
21978
22039
|
onCopy,
|
|
21979
22040
|
onPaste,
|
|
21980
22041
|
onDuplicate,
|
|
21981
|
-
canPaste
|
|
22042
|
+
canPaste,
|
|
22043
|
+
hostItems = []
|
|
21982
22044
|
}) {
|
|
21983
22045
|
const menuRef = useContextMenuDismiss(onClose);
|
|
21984
22046
|
useMenuKeyboardNav(menuRef);
|
|
@@ -21990,14 +22052,14 @@ var ClipContextMenu = memo14(function ClipContextMenu2({
|
|
|
21990
22052
|
const canSplit = isSplittable && currentTime > element.start && currentTime < element.start + element.duration;
|
|
21991
22053
|
const splitLabel = !isSplittable ? null : canSplit ? `Split at ${currentTime.toFixed(2)}s` : "Split (move playhead inside clip)";
|
|
21992
22054
|
const clipboardItemCount = [onCopy, onPaste, onDuplicate].filter(Boolean).length;
|
|
21993
|
-
const
|
|
21994
|
-
const
|
|
22055
|
+
const hostRows = hostItems.length;
|
|
22056
|
+
const rowCount = hostRows + (splitLabel ? 1 : 0) + clipboardItemCount + 1;
|
|
22057
|
+
const dividerCount = (hostRows > 0 ? 1 : 0) + (splitLabel ? 1 : 0) + (clipboardItemCount > 0 ? 1 : 0);
|
|
21995
22058
|
const menuWidth = 200;
|
|
21996
22059
|
const menuHeight = rowCount * 30 + dividerCount * 9 + 8;
|
|
21997
22060
|
const overflowY = y + menuHeight - window.innerHeight;
|
|
21998
22061
|
const adjustedX = x + menuWidth > window.innerWidth ? x - menuWidth : x;
|
|
21999
22062
|
const adjustedY = overflowY > 0 ? y - overflowY - 8 : y;
|
|
22000
|
-
const itemClass = (enabled) => `w-full flex items-center justify-between px-3 py-1.5 text-xs text-left outline-none${enabled ? " focus-visible:bg-neutral-800 text-neutral-300 hover:bg-neutral-800 cursor-pointer" : " text-neutral-600 cursor-not-allowed"}`;
|
|
22001
22063
|
return createPortal4(
|
|
22002
22064
|
/* @__PURE__ */ jsxs38(
|
|
22003
22065
|
"div",
|
|
@@ -22008,6 +22070,7 @@ var ClipContextMenu = memo14(function ClipContextMenu2({
|
|
|
22008
22070
|
className: "fixed z-200 bg-neutral-900 border border-neutral-700 rounded-md shadow-lg py-1 min-w-[180px]",
|
|
22009
22071
|
style: { left: adjustedX, top: adjustedY },
|
|
22010
22072
|
children: [
|
|
22073
|
+
hostRows > 0 && /* @__PURE__ */ jsx58(HostItems, { items: hostItems, onClose }),
|
|
22011
22074
|
splitLabel && /* @__PURE__ */ jsxs38(Fragment18, { children: [
|
|
22012
22075
|
/* @__PURE__ */ jsxs38(
|
|
22013
22076
|
"button",
|
|
@@ -22128,7 +22191,7 @@ var TrackGapContextMenu = memo15(function TrackGapContextMenu2({
|
|
|
22128
22191
|
const overflowY = y + menuHeight - window.innerHeight;
|
|
22129
22192
|
const adjustedX = x + menuWidth > window.innerWidth ? x - menuWidth : x;
|
|
22130
22193
|
const adjustedY = overflowY > 0 ? y - overflowY - 8 : y;
|
|
22131
|
-
const
|
|
22194
|
+
const itemClass2 = (enabled) => `w-full flex items-center justify-between px-3 py-1.5 text-xs text-left ${enabled ? "text-neutral-300 hover:bg-neutral-800 cursor-pointer" : "text-neutral-600 cursor-not-allowed"}`;
|
|
22132
22195
|
const closeGapTitle = canCloseGap ? void 0 : gapWidth == null ? "No gap here" : "A clip on this track can't be moved";
|
|
22133
22196
|
const closeAllTitle = canCloseAllGaps ? void 0 : hasAnyGaps ? "A clip on this track can't be moved" : "No gaps on this track";
|
|
22134
22197
|
return createPortal5(
|
|
@@ -22144,7 +22207,7 @@ var TrackGapContextMenu = memo15(function TrackGapContextMenu2({
|
|
|
22144
22207
|
"button",
|
|
22145
22208
|
{
|
|
22146
22209
|
type: "button",
|
|
22147
|
-
className:
|
|
22210
|
+
className: itemClass2(canCloseGap),
|
|
22148
22211
|
disabled: !canCloseGap,
|
|
22149
22212
|
title: closeGapTitle,
|
|
22150
22213
|
onPointerEnter: () => onHoverAction(canCloseGap ? "close-gap" : null),
|
|
@@ -22166,7 +22229,7 @@ var TrackGapContextMenu = memo15(function TrackGapContextMenu2({
|
|
|
22166
22229
|
"button",
|
|
22167
22230
|
{
|
|
22168
22231
|
type: "button",
|
|
22169
|
-
className:
|
|
22232
|
+
className: itemClass2(canCloseAllGaps),
|
|
22170
22233
|
disabled: !canCloseAllGaps,
|
|
22171
22234
|
title: closeAllTitle,
|
|
22172
22235
|
onPointerEnter: () => onHoverAction(canCloseAllGaps ? "close-all" : null),
|
|
@@ -22330,6 +22393,11 @@ function TimelineClipMenuOverlay() {
|
|
|
22330
22393
|
useEffect30(() => {
|
|
22331
22394
|
if (clipContextMenu && !element) setClipContextMenu(null);
|
|
22332
22395
|
}, [element, clipContextMenu, setClipContextMenu]);
|
|
22396
|
+
const { clipMenuItems } = overlay;
|
|
22397
|
+
const hostItems = useMemo32(
|
|
22398
|
+
() => element ? clipMenuItems?.(element) : void 0,
|
|
22399
|
+
[clipMenuItems, element]
|
|
22400
|
+
);
|
|
22333
22401
|
if (!clipContextMenu || !element) return null;
|
|
22334
22402
|
const readCurrentElement = () => resolveTimelineContextElement({
|
|
22335
22403
|
capturedElement: element,
|
|
@@ -22360,7 +22428,8 @@ function TimelineClipMenuOverlay() {
|
|
|
22360
22428
|
onCopy: overlay.onCopyClip,
|
|
22361
22429
|
onPaste: overlay.onPasteClip,
|
|
22362
22430
|
onDuplicate: overlay.onDuplicateClip,
|
|
22363
|
-
canPaste: overlay.canPasteClip?.() ?? false
|
|
22431
|
+
canPaste: overlay.canPasteClip?.() ?? false,
|
|
22432
|
+
hostItems
|
|
22364
22433
|
}
|
|
22365
22434
|
);
|
|
22366
22435
|
}
|
|
@@ -22570,7 +22639,7 @@ var Timeline = Object.assign(TimelineComposed, {
|
|
|
22570
22639
|
});
|
|
22571
22640
|
|
|
22572
22641
|
// src/player/components/VideoThumbnail.tsx
|
|
22573
|
-
import { memo as memo17, useMemo as
|
|
22642
|
+
import { memo as memo17, useMemo as useMemo33 } from "react";
|
|
22574
22643
|
|
|
22575
22644
|
// src/hooks/useThumbnailLease.ts
|
|
22576
22645
|
import { useCallback as useCallback34, useLayoutEffect as useLayoutEffect7, useRef as useRef41, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
@@ -23260,7 +23329,7 @@ var VideoThumbnail = memo17(function VideoThumbnail2({
|
|
|
23260
23329
|
const requestFrameCount = quantizeThumbnailFrameCount(
|
|
23261
23330
|
computeThumbnailStrip(container.width, 16 / 9, container.height).frameCount
|
|
23262
23331
|
);
|
|
23263
|
-
const requestProps =
|
|
23332
|
+
const requestProps = useMemo33(
|
|
23264
23333
|
() => ({
|
|
23265
23334
|
videoSrc,
|
|
23266
23335
|
sourceStart,
|
|
@@ -23272,11 +23341,11 @@ var VideoThumbnail = memo17(function VideoThumbnail2({
|
|
|
23272
23341
|
}),
|
|
23273
23342
|
[duration, priority, projectId, sessionEpoch, sourceRangeDuration, sourceStart, videoSrc]
|
|
23274
23343
|
);
|
|
23275
|
-
const posterRequest =
|
|
23344
|
+
const posterRequest = useMemo33(
|
|
23276
23345
|
() => createVideoThumbnailRequest(requestProps, 1, false),
|
|
23277
23346
|
[requestProps]
|
|
23278
23347
|
);
|
|
23279
|
-
const richRequest =
|
|
23348
|
+
const richRequest = useMemo33(
|
|
23280
23349
|
() => createVideoThumbnailRequest(requestProps, requestFrameCount, true),
|
|
23281
23350
|
[requestFrameCount, requestProps]
|
|
23282
23351
|
);
|
|
@@ -23340,7 +23409,7 @@ var VideoThumbnail = memo17(function VideoThumbnail2({
|
|
|
23340
23409
|
});
|
|
23341
23410
|
|
|
23342
23411
|
// src/player/components/CompositionThumbnail.tsx
|
|
23343
|
-
import { memo as memo18, useMemo as
|
|
23412
|
+
import { memo as memo18, useMemo as useMemo34 } from "react";
|
|
23344
23413
|
import { jsx as jsx66, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
23345
23414
|
var THUMBNAIL_URL_VERSION = "v3";
|
|
23346
23415
|
var THUMBNAIL_SEEK_TIME_SECONDS = 3;
|
|
@@ -23419,7 +23488,7 @@ var CompositionThumbnail = memo18(function CompositionThumbnail2({
|
|
|
23419
23488
|
origin: window.location.origin,
|
|
23420
23489
|
contentRevision
|
|
23421
23490
|
});
|
|
23422
|
-
const request =
|
|
23491
|
+
const request = useMemo34(
|
|
23423
23492
|
() => ({
|
|
23424
23493
|
key: createThumbnailKey({ kind: "composition", url }),
|
|
23425
23494
|
projectId,
|
|
@@ -26406,7 +26475,7 @@ function useTimelinePlayer({
|
|
|
26406
26475
|
}
|
|
26407
26476
|
|
|
26408
26477
|
// src/player/hooks/usePlayerHandle.ts
|
|
26409
|
-
import { useCallback as useCallback43, useMemo as
|
|
26478
|
+
import { useCallback as useCallback43, useMemo as useMemo35 } from "react";
|
|
26410
26479
|
|
|
26411
26480
|
// src/components/nle/NLEContext.tsx
|
|
26412
26481
|
import { useContext as useContext7, useState as useState29, useCallback as useCallback42, useRef as useRef48, useEffect as useEffect33 } from "react";
|
|
@@ -26784,7 +26853,7 @@ function usePlayerHandle() {
|
|
|
26784
26853
|
const subscribeTime = useCallback43((listener2) => {
|
|
26785
26854
|
return liveTime.subscribe(listener2);
|
|
26786
26855
|
}, []);
|
|
26787
|
-
const handleElements =
|
|
26856
|
+
const handleElements = useMemo35(() => elements.map(toHandleElement), [elements]);
|
|
26788
26857
|
return {
|
|
26789
26858
|
ready,
|
|
26790
26859
|
playing,
|
|
@@ -27697,7 +27766,7 @@ function CompositionBreadcrumb({ stack, onNavigate }) {
|
|
|
27697
27766
|
import { useCallback as useCallback48, useRef as useRef53, useState as useState32 } from "react";
|
|
27698
27767
|
|
|
27699
27768
|
// src/components/editor/previewReadOnlyContext.tsx
|
|
27700
|
-
import { useContext as useContext8, useMemo as
|
|
27769
|
+
import { useContext as useContext8, useMemo as useMemo36 } from "react";
|
|
27701
27770
|
import { jsx as jsx72 } from "react/jsx-runtime";
|
|
27702
27771
|
var DEFAULT_REASON = "Preview is read-only.";
|
|
27703
27772
|
var PreviewReadOnlyContext = createStableContext("PreviewReadOnlyContext", {
|
|
@@ -27709,7 +27778,7 @@ function PreviewReadOnlyProvider({
|
|
|
27709
27778
|
reason,
|
|
27710
27779
|
children
|
|
27711
27780
|
}) {
|
|
27712
|
-
const value =
|
|
27781
|
+
const value = useMemo36(() => ({ readOnly, reason: reason ?? DEFAULT_REASON }), [readOnly, reason]);
|
|
27713
27782
|
return /* @__PURE__ */ jsx72(PreviewReadOnlyContext, { value, children });
|
|
27714
27783
|
}
|
|
27715
27784
|
function usePreviewReadOnly() {
|
|
@@ -28457,7 +28526,7 @@ import {
|
|
|
28457
28526
|
memo as memo21,
|
|
28458
28527
|
useCallback as useCallback51,
|
|
28459
28528
|
useEffect as useEffect38,
|
|
28460
|
-
useMemo as
|
|
28529
|
+
useMemo as useMemo38,
|
|
28461
28530
|
useRef as useRef58
|
|
28462
28531
|
} from "react";
|
|
28463
28532
|
import {
|
|
@@ -28480,7 +28549,7 @@ var useAudioMetersVisible = create5((set) => ({
|
|
|
28480
28549
|
}));
|
|
28481
28550
|
|
|
28482
28551
|
// src/utils/audioMeterMath.ts
|
|
28483
|
-
import { useMemo as
|
|
28552
|
+
import { useMemo as useMemo37 } from "react";
|
|
28484
28553
|
import { audioDbToGain, audioGainToDb } from "@hyperframes/core/audio-gain";
|
|
28485
28554
|
var METER_DB_MARKS = [0, -3, -6, -12, -24];
|
|
28486
28555
|
var FLOOR_DB = -60;
|
|
@@ -28520,7 +28589,7 @@ function hasProjectAudio(elements) {
|
|
|
28520
28589
|
}
|
|
28521
28590
|
function useProjectHasAudio() {
|
|
28522
28591
|
const elements = usePlayerStore((s) => s.elements);
|
|
28523
|
-
return
|
|
28592
|
+
return useMemo37(() => hasProjectAudio(elements), [elements]);
|
|
28524
28593
|
}
|
|
28525
28594
|
|
|
28526
28595
|
// src/components/nle/AudioMeterStrip.tsx
|
|
@@ -28531,7 +28600,7 @@ var RED_AT = markFraction(-3);
|
|
|
28531
28600
|
function useStrips() {
|
|
28532
28601
|
const elements = usePlayerStore((s) => s.elements);
|
|
28533
28602
|
const masterVolume = usePlayerStore((s) => s.audioVolume);
|
|
28534
|
-
return
|
|
28603
|
+
return useMemo38(() => {
|
|
28535
28604
|
const labels = /* @__PURE__ */ new Map();
|
|
28536
28605
|
const volumes = /* @__PURE__ */ new Map();
|
|
28537
28606
|
for (const el of elements) {
|
|
@@ -28878,7 +28947,8 @@ function TimelinePane({
|
|
|
28878
28947
|
onCopyClip,
|
|
28879
28948
|
onPasteClip,
|
|
28880
28949
|
onDuplicateClip,
|
|
28881
|
-
canPasteClip
|
|
28950
|
+
canPasteClip,
|
|
28951
|
+
clipMenuItems
|
|
28882
28952
|
}) {
|
|
28883
28953
|
const {
|
|
28884
28954
|
seek,
|
|
@@ -28933,7 +29003,8 @@ function TimelinePane({
|
|
|
28933
29003
|
onCopyClip,
|
|
28934
29004
|
onPasteClip,
|
|
28935
29005
|
onDuplicateClip,
|
|
28936
|
-
canPasteClip
|
|
29006
|
+
canPasteClip,
|
|
29007
|
+
clipMenuItems
|
|
28937
29008
|
}
|
|
28938
29009
|
) }),
|
|
28939
29010
|
/* @__PURE__ */ jsx78(AudioMeterStrip, {})
|
|
@@ -29594,7 +29665,7 @@ var CaptionOverlay = memo22(function CaptionOverlay2({ iframeRef }) {
|
|
|
29594
29665
|
});
|
|
29595
29666
|
|
|
29596
29667
|
// src/components/editor/DomEditOverlay.tsx
|
|
29597
|
-
import { memo as memo25, useEffect as useEffect49, useMemo as
|
|
29668
|
+
import { memo as memo25, useEffect as useEffect49, useMemo as useMemo39, useRef as useRef69 } from "react";
|
|
29598
29669
|
|
|
29599
29670
|
// src/components/editor/marqueeCommit.ts
|
|
29600
29671
|
import { useCallback as useCallback53, useEffect as useEffect40, useRef as useRef60, useState as useState36 } from "react";
|
|
@@ -30115,12 +30186,52 @@ function cropRectFromInsets(rect, insets, scaleX, scaleY) {
|
|
|
30115
30186
|
height: Math.max(0, rect.height - (insets.top + insets.bottom) * sy)
|
|
30116
30187
|
};
|
|
30117
30188
|
}
|
|
30118
|
-
|
|
30189
|
+
var cropLifts = /* @__PURE__ */ new WeakMap();
|
|
30190
|
+
function liftSelector(element) {
|
|
30191
|
+
const quote = (value) => `"${value.replace(/["\\]/g, "\\$&")}"`;
|
|
30192
|
+
const hfId = element.getAttribute("data-hf-id");
|
|
30193
|
+
if (hfId) return `[data-hf-id=${quote(hfId)}]`;
|
|
30194
|
+
return element.id ? `[id=${quote(element.id)}]` : null;
|
|
30195
|
+
}
|
|
30196
|
+
function liftElementCrop(element) {
|
|
30197
|
+
const selector = liftSelector(element);
|
|
30198
|
+
if (!selector || cropLifts.has(element)) return;
|
|
30199
|
+
const doc = element.ownerDocument;
|
|
30200
|
+
const rule = doc.createElement("style");
|
|
30201
|
+
rule.textContent = `${selector}{clip-path:none!important}`;
|
|
30202
|
+
(doc.head ?? doc.documentElement).append(rule);
|
|
30203
|
+
cropLifts.set(element, { rule });
|
|
30204
|
+
}
|
|
30205
|
+
function dropElementCropLift(element) {
|
|
30206
|
+
cropLifts.get(element)?.rule.remove();
|
|
30207
|
+
cropLifts.delete(element);
|
|
30208
|
+
}
|
|
30209
|
+
function isElementCropLifted(element) {
|
|
30210
|
+
return cropLifts.has(element);
|
|
30211
|
+
}
|
|
30212
|
+
var computedClipPath = (element) => element.ownerDocument.defaultView?.getComputedStyle(element).clipPath.trim() || "";
|
|
30213
|
+
function readElementClipPath(element) {
|
|
30119
30214
|
const inline = element.style.getPropertyValue("clip-path").trim();
|
|
30120
|
-
const
|
|
30215
|
+
const lift = cropLifts.get(element);
|
|
30216
|
+
if (inline || !lift) return inline || computedClipPath(element);
|
|
30217
|
+
if (lift.sheetClip === void 0) {
|
|
30218
|
+
const { parentNode, nextSibling } = lift.rule;
|
|
30219
|
+
lift.rule.remove();
|
|
30220
|
+
lift.sheetClip = computedClipPath(element);
|
|
30221
|
+
parentNode?.insertBefore(lift.rule, nextSibling);
|
|
30222
|
+
}
|
|
30223
|
+
return lift.sheetClip;
|
|
30224
|
+
}
|
|
30225
|
+
function parseCropClipPath(value) {
|
|
30121
30226
|
if (!value || value === "none") return { top: 0, right: 0, bottom: 0, left: 0, radius: 0 };
|
|
30122
30227
|
return parseInsetClipPathSides(value);
|
|
30123
30228
|
}
|
|
30229
|
+
function readElementCropInsets(element) {
|
|
30230
|
+
return parseCropClipPath(readElementClipPath(element));
|
|
30231
|
+
}
|
|
30232
|
+
function hasCropInsets(insets) {
|
|
30233
|
+
return insets.top > 0 || insets.right > 0 || insets.bottom > 0 || insets.left > 0;
|
|
30234
|
+
}
|
|
30124
30235
|
function clampInset(value, max) {
|
|
30125
30236
|
if (!Number.isFinite(value)) return 0;
|
|
30126
30237
|
return Math.min(Math.max(0, value), Math.max(0, max));
|
|
@@ -30162,7 +30273,7 @@ function resolveCropInsetFromMoveDrag(input) {
|
|
|
30162
30273
|
return { left, right: totalX - left, top, bottom: totalY - top };
|
|
30163
30274
|
}
|
|
30164
30275
|
function hugRectForElement(rect, element) {
|
|
30165
|
-
const insets = readElementCropInsets(element);
|
|
30276
|
+
const insets = isElementCropLifted(element) ? null : readElementCropInsets(element);
|
|
30166
30277
|
if (!insets || insets.top <= 0 && insets.right <= 0 && insets.bottom <= 0 && insets.left <= 0)
|
|
30167
30278
|
return rect;
|
|
30168
30279
|
return cropRectFromInsets(rect, insets, rect.editScaleX, rect.editScaleY);
|
|
@@ -30900,9 +31011,6 @@ function pointerAngleDegrees(centerX, centerY, x, y) {
|
|
|
30900
31011
|
function normalizeAngleDelta(delta) {
|
|
30901
31012
|
return ((delta + 180) % 360 + 360) % 360 - 180;
|
|
30902
31013
|
}
|
|
30903
|
-
function roundAngle(angle) {
|
|
30904
|
-
return Math.round(angle * 10) / 10;
|
|
30905
|
-
}
|
|
30906
31014
|
function resolveDomEditRotationGesture(input) {
|
|
30907
31015
|
const startAngle = pointerAngleDegrees(input.centerX, input.centerY, input.startX, input.startY);
|
|
30908
31016
|
const currentAngle = pointerAngleDegrees(
|
|
@@ -30914,7 +31022,7 @@ function resolveDomEditRotationGesture(input) {
|
|
|
30914
31022
|
const delta = normalizeAngleDelta(currentAngle - startAngle);
|
|
30915
31023
|
const angle = input.actualAngle + delta;
|
|
30916
31024
|
return {
|
|
30917
|
-
angle: input.snap ? Math.round(angle / ROTATION_SNAP_DEGREES) * ROTATION_SNAP_DEGREES :
|
|
31025
|
+
angle: input.snap ? Math.round(angle / ROTATION_SNAP_DEGREES) * ROTATION_SNAP_DEGREES : roundTo3(angle)
|
|
30918
31026
|
};
|
|
30919
31027
|
}
|
|
30920
31028
|
function hasDomEditRotationChanged(initialAngle, nextAngle) {
|
|
@@ -31273,9 +31381,6 @@ var STUDIO_ROTATION_TRANSFORM_ORIGIN = "center center";
|
|
|
31273
31381
|
function finiteNumber2(value) {
|
|
31274
31382
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
31275
31383
|
}
|
|
31276
|
-
function roundRotationAngle(angle) {
|
|
31277
|
-
return Math.round(angle * 10) / 10;
|
|
31278
|
-
}
|
|
31279
31384
|
function normalizeStudioFileChangePath(path) {
|
|
31280
31385
|
return path.trim().replace(/\\/g, "/").replace(/^\.?\//, "");
|
|
31281
31386
|
}
|
|
@@ -31479,8 +31584,8 @@ function prepareStudioPathOffsetBase(element, updateBase) {
|
|
|
31479
31584
|
function writeStudioPathOffsetVars(element, offset, options = {}) {
|
|
31480
31585
|
prepareStudioPathOffsetBase(element, options.updateBase ?? true);
|
|
31481
31586
|
element.setAttribute(STUDIO_PATH_OFFSET_ATTR, "true");
|
|
31482
|
-
element.style.setProperty(STUDIO_OFFSET_X_PROP, `${
|
|
31483
|
-
element.style.setProperty(STUDIO_OFFSET_Y_PROP, `${
|
|
31587
|
+
element.style.setProperty(STUDIO_OFFSET_X_PROP, `${roundTo3(offset.x)}px`);
|
|
31588
|
+
element.style.setProperty(STUDIO_OFFSET_Y_PROP, `${roundTo3(offset.y)}px`);
|
|
31484
31589
|
}
|
|
31485
31590
|
function isIdentityAfterTranslateStrip(m) {
|
|
31486
31591
|
return m.is2D && m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1;
|
|
@@ -31550,7 +31655,7 @@ function applyStudioPathOffsetDraft(element, offset) {
|
|
|
31550
31655
|
if (applyStudioPathOffsetViaGsap(element, offset)) return;
|
|
31551
31656
|
element.style.setProperty(
|
|
31552
31657
|
"translate",
|
|
31553
|
-
composeTranslateValue(element, `${
|
|
31658
|
+
composeTranslateValue(element, `${roundTo3(offset.x)}px`, `${roundTo3(offset.y)}px`)
|
|
31554
31659
|
);
|
|
31555
31660
|
stripGsapTranslateFromTransform(element);
|
|
31556
31661
|
}
|
|
@@ -31560,7 +31665,7 @@ function readParentFlexBasisPixels(element, size) {
|
|
|
31560
31665
|
const display2 = readStyleOrComputed(parent, "display").trim();
|
|
31561
31666
|
if (display2 !== "flex" && display2 !== "inline-flex") return null;
|
|
31562
31667
|
const direction = readStyleOrComputed(parent, "flex-direction").trim();
|
|
31563
|
-
return
|
|
31668
|
+
return roundToLayoutPx(Math.max(1, direction.startsWith("column") ? size.height : size.width));
|
|
31564
31669
|
}
|
|
31565
31670
|
function restoreStaleStudioScaleResize(element) {
|
|
31566
31671
|
if (!element.hasAttribute(STUDIO_ORIGINAL_SCALE_ATTR)) return;
|
|
@@ -31623,14 +31728,14 @@ function writeStudioBoxSizeVars(element, size) {
|
|
|
31623
31728
|
element.setAttribute(STUDIO_ORIGINAL_DISPLAY_ATTR, element.style.getPropertyValue("display"));
|
|
31624
31729
|
}
|
|
31625
31730
|
element.setAttribute(STUDIO_BOX_SIZE_ATTR, "true");
|
|
31626
|
-
element.style.setProperty(STUDIO_WIDTH_PROP, `${
|
|
31627
|
-
element.style.setProperty(STUDIO_HEIGHT_PROP, `${
|
|
31731
|
+
element.style.setProperty(STUDIO_WIDTH_PROP, `${roundToLayoutPx(Math.max(1, size.width))}px`);
|
|
31732
|
+
element.style.setProperty(STUDIO_HEIGHT_PROP, `${roundToLayoutPx(Math.max(1, size.height))}px`);
|
|
31628
31733
|
}
|
|
31629
31734
|
function applyStudioBoxSizeDimensions(element, size) {
|
|
31630
31735
|
writeStudioBoxSizeVars(element, size);
|
|
31631
31736
|
restoreStaleStudioScaleResize(element);
|
|
31632
|
-
const width =
|
|
31633
|
-
const height =
|
|
31737
|
+
const width = roundToLayoutPx(Math.max(1, size.width));
|
|
31738
|
+
const height = roundToLayoutPx(Math.max(1, size.height));
|
|
31634
31739
|
element.style.setProperty("box-sizing", "border-box");
|
|
31635
31740
|
element.style.setProperty("width", `${width}px`);
|
|
31636
31741
|
element.style.setProperty("height", `${height}px`);
|
|
@@ -31653,7 +31758,17 @@ function applyStudioBoxSize(element, size) {
|
|
|
31653
31758
|
promoteInlineForTransform(element);
|
|
31654
31759
|
applyStudioBoxSizeDimensions(element, size);
|
|
31655
31760
|
}
|
|
31761
|
+
var boxSizeDraftBases = /* @__PURE__ */ new WeakMap();
|
|
31762
|
+
function readStudioBoxSizeDraftBase(element) {
|
|
31763
|
+
return boxSizeDraftBases.get(element) ?? null;
|
|
31764
|
+
}
|
|
31765
|
+
function forgetStudioBoxSizeDraftBase(element) {
|
|
31766
|
+
boxSizeDraftBases.delete(element);
|
|
31767
|
+
}
|
|
31656
31768
|
function applyStudioBoxSizeDraft(element, size) {
|
|
31769
|
+
if (!boxSizeDraftBases.has(element)) {
|
|
31770
|
+
boxSizeDraftBases.set(element, { width: element.offsetWidth, height: element.offsetHeight });
|
|
31771
|
+
}
|
|
31657
31772
|
promoteInlineForTransform(element);
|
|
31658
31773
|
applyStudioBoxSizeDimensions(element, size);
|
|
31659
31774
|
}
|
|
@@ -31691,7 +31806,7 @@ function prepareStudioRotationBase(element, updateBase) {
|
|
|
31691
31806
|
function writeStudioRotationVars(element, rotation, options = {}) {
|
|
31692
31807
|
prepareStudioRotationBase(element, options.updateBase ?? true);
|
|
31693
31808
|
element.setAttribute(STUDIO_ROTATION_ATTR, "true");
|
|
31694
|
-
element.style.setProperty(STUDIO_ROTATION_PROP, `${
|
|
31809
|
+
element.style.setProperty(STUDIO_ROTATION_PROP, `${roundTo3(rotation.angle)}deg`);
|
|
31695
31810
|
element.style.setProperty("transform-origin", STUDIO_ROTATION_TRANSFORM_ORIGIN);
|
|
31696
31811
|
}
|
|
31697
31812
|
function applyStudioRotation(element, rotation) {
|
|
@@ -31709,7 +31824,7 @@ function applyStudioRotationDraft(element, rotation) {
|
|
|
31709
31824
|
element.setAttribute(STUDIO_ROTATION_DRAFT_ATTR, "true");
|
|
31710
31825
|
element.style.setProperty(
|
|
31711
31826
|
"rotate",
|
|
31712
|
-
composeStudioRotationValue(element, `${
|
|
31827
|
+
composeStudioRotationValue(element, `${roundTo3(rotation.angle)}deg`)
|
|
31713
31828
|
);
|
|
31714
31829
|
}
|
|
31715
31830
|
|
|
@@ -31877,6 +31992,7 @@ function restoreStyleProperty(element, property, value) {
|
|
|
31877
31992
|
else element.style.removeProperty(property);
|
|
31878
31993
|
}
|
|
31879
31994
|
function restoreStudioBoxSize(element, previous) {
|
|
31995
|
+
forgetStudioBoxSizeDraftBase(element);
|
|
31880
31996
|
restoreStyleProperty(element, "width", previous.width);
|
|
31881
31997
|
restoreStyleProperty(element, "height", previous.height);
|
|
31882
31998
|
restoreStyleProperty(element, "min-width", previous.minWidth);
|
|
@@ -32006,6 +32122,7 @@ function clearStudioRotation(element) {
|
|
|
32006
32122
|
element.removeAttribute(STUDIO_ORIGINAL_ROTATION_TRANSFORM_ORIGIN_ATTR);
|
|
32007
32123
|
}
|
|
32008
32124
|
function clearStudioBoxSize(element) {
|
|
32125
|
+
forgetStudioBoxSizeDraftBase(element);
|
|
32009
32126
|
if (element.hasAttribute(STUDIO_BOX_SIZE_ATTR) || styleUsesStudioSize(element.style.getPropertyValue("width")) || styleUsesStudioSize(element.style.getPropertyValue("height")) || element.hasAttribute(STUDIO_ORIGINAL_SCALE_ATTR)) {
|
|
32010
32127
|
restoreOriginalBoxSizeProperty(element, "width", STUDIO_ORIGINAL_WIDTH_ATTR);
|
|
32011
32128
|
restoreOriginalBoxSizeProperty(element, "height", STUDIO_ORIGINAL_HEIGHT_ATTR);
|
|
@@ -32259,8 +32376,8 @@ function computeDraggedGsapPosition(element, studioOffset, fallbackBase) {
|
|
|
32259
32376
|
const baseGsapX = Number.isFinite(parsedBaseX) ? parsedBaseX : fallbackBase.x;
|
|
32260
32377
|
const baseGsapY = Number.isFinite(parsedBaseY) ? parsedBaseY : fallbackBase.y;
|
|
32261
32378
|
return {
|
|
32262
|
-
newX:
|
|
32263
|
-
newY:
|
|
32379
|
+
newX: roundTo3(baseGsapX + adjX),
|
|
32380
|
+
newY: roundTo3(baseGsapY + adjY),
|
|
32264
32381
|
baseGsapX,
|
|
32265
32382
|
baseGsapY
|
|
32266
32383
|
};
|
|
@@ -34257,6 +34374,340 @@ var SnapGuideOverlay = memo23(function SnapGuideOverlay2({
|
|
|
34257
34374
|
|
|
34258
34375
|
// src/components/editor/DomEditCropHandles.tsx
|
|
34259
34376
|
import { useEffect as useEffect44, useRef as useRef65, useState as useState40 } from "react";
|
|
34377
|
+
|
|
34378
|
+
// src/hooks/gsapRuntimeKeyframes.ts
|
|
34379
|
+
import { buildArcPath } from "@hyperframes/core/gsap-parser-acorn";
|
|
34380
|
+
var FLAT_SKIP_KEYS = /* @__PURE__ */ new Set([
|
|
34381
|
+
"ease",
|
|
34382
|
+
"duration",
|
|
34383
|
+
"delay",
|
|
34384
|
+
"stagger",
|
|
34385
|
+
"motionPath",
|
|
34386
|
+
"overwrite",
|
|
34387
|
+
"immediateRender",
|
|
34388
|
+
"onComplete",
|
|
34389
|
+
"onUpdate",
|
|
34390
|
+
"onStart",
|
|
34391
|
+
"keyframes"
|
|
34392
|
+
]);
|
|
34393
|
+
function timelinesOf(iframe) {
|
|
34394
|
+
if (!iframe?.contentWindow) return null;
|
|
34395
|
+
try {
|
|
34396
|
+
return iframe.contentWindow.__timelines ?? null;
|
|
34397
|
+
} catch {
|
|
34398
|
+
return null;
|
|
34399
|
+
}
|
|
34400
|
+
}
|
|
34401
|
+
function isXY(p) {
|
|
34402
|
+
return !!p && typeof p.x === "number" && typeof p.y === "number";
|
|
34403
|
+
}
|
|
34404
|
+
function isZeroDurationSet(duration) {
|
|
34405
|
+
return !(duration > 0);
|
|
34406
|
+
}
|
|
34407
|
+
function coordsFromMotionPath(mp) {
|
|
34408
|
+
if (!mp || typeof mp !== "object") return null;
|
|
34409
|
+
const obj = mp;
|
|
34410
|
+
const pathVal = Array.isArray(mp) ? mp : obj.path;
|
|
34411
|
+
if (!Array.isArray(pathVal)) return null;
|
|
34412
|
+
const coords = pathVal.filter(isXY).map((p) => ({ x: p.x, y: p.y }));
|
|
34413
|
+
if (coords.length < 2) return null;
|
|
34414
|
+
const curviness = typeof obj.curviness === "number" ? obj.curviness : 1;
|
|
34415
|
+
const autoRotate = typeof obj.autoRotate === "number" ? obj.autoRotate : obj.autoRotate === true;
|
|
34416
|
+
return { coords, curviness, autoRotate, isCubic: obj.type === "cubic" };
|
|
34417
|
+
}
|
|
34418
|
+
function flatTweenKeyframes(vars) {
|
|
34419
|
+
const properties = {};
|
|
34420
|
+
for (const [k, v] of Object.entries(vars)) {
|
|
34421
|
+
if (FLAT_SKIP_KEYS.has(k)) continue;
|
|
34422
|
+
if (typeof v === "number") properties[k] = roundTo3(v);
|
|
34423
|
+
else if (typeof v === "string") properties[k] = v;
|
|
34424
|
+
}
|
|
34425
|
+
if (Object.keys(properties).length === 0) return null;
|
|
34426
|
+
return [
|
|
34427
|
+
{ percentage: 0, properties },
|
|
34428
|
+
{ percentage: 100, properties }
|
|
34429
|
+
];
|
|
34430
|
+
}
|
|
34431
|
+
function readTween(vars) {
|
|
34432
|
+
if (vars.keyframes && typeof vars.keyframes === "object") {
|
|
34433
|
+
const parsed = parsePercentageKeyframes(vars.keyframes);
|
|
34434
|
+
if (parsed) return parsed;
|
|
34435
|
+
}
|
|
34436
|
+
const mp = coordsFromMotionPath(vars.motionPath);
|
|
34437
|
+
if (mp) {
|
|
34438
|
+
const shape = buildArcPath(mp.coords, mp.curviness, mp.autoRotate, mp.isCubic);
|
|
34439
|
+
if (shape) {
|
|
34440
|
+
const n = shape.waypoints.length;
|
|
34441
|
+
const keyframes = shape.waypoints.map((wp, i) => ({
|
|
34442
|
+
percentage: n > 1 ? Math.round(i / (n - 1) * 100) : 0,
|
|
34443
|
+
properties: { x: wp.x, y: wp.y }
|
|
34444
|
+
}));
|
|
34445
|
+
return { keyframes, arcPath: shape.arcPath };
|
|
34446
|
+
}
|
|
34447
|
+
}
|
|
34448
|
+
const flat = flatTweenKeyframes(vars);
|
|
34449
|
+
return flat ? { keyframes: flat } : null;
|
|
34450
|
+
}
|
|
34451
|
+
function matchesElement(tween, el) {
|
|
34452
|
+
if (!tween.targets) return false;
|
|
34453
|
+
for (const t of tween.targets()) {
|
|
34454
|
+
if (t === el || el.id && t.id === el.id) return true;
|
|
34455
|
+
}
|
|
34456
|
+
return false;
|
|
34457
|
+
}
|
|
34458
|
+
function tweenTiming(tween) {
|
|
34459
|
+
const rawStart = typeof tween.startTime === "function" ? tween.startTime() : 0;
|
|
34460
|
+
const rawDur = typeof tween.duration === "function" ? tween.duration() : 0;
|
|
34461
|
+
return {
|
|
34462
|
+
start: Number.isFinite(rawStart) ? rawStart : 0,
|
|
34463
|
+
duration: Number.isFinite(rawDur) ? rawDur : 0
|
|
34464
|
+
};
|
|
34465
|
+
}
|
|
34466
|
+
function varsCarryChannel(vars, channels) {
|
|
34467
|
+
if (!vars) return false;
|
|
34468
|
+
for (const ch of channels) {
|
|
34469
|
+
if (Object.prototype.hasOwnProperty.call(vars, ch)) return true;
|
|
34470
|
+
}
|
|
34471
|
+
return false;
|
|
34472
|
+
}
|
|
34473
|
+
function keyframeVarsCarryChannel(vars, channels) {
|
|
34474
|
+
const kf = vars?.keyframes;
|
|
34475
|
+
if (!kf || typeof kf !== "object") return false;
|
|
34476
|
+
if (!Array.isArray(kf) && channels.some((ch) => Object.prototype.hasOwnProperty.call(kf, ch)))
|
|
34477
|
+
return true;
|
|
34478
|
+
const steps = Array.isArray(kf) ? kf : Object.values(kf);
|
|
34479
|
+
return steps.some(
|
|
34480
|
+
(step) => step != null && typeof step === "object" && channels.some((ch) => Object.prototype.hasOwnProperty.call(step, ch))
|
|
34481
|
+
);
|
|
34482
|
+
}
|
|
34483
|
+
function resolveRuntimeTween(iframe, selector, kind, compositionId, channels) {
|
|
34484
|
+
const timelines = timelinesOf(iframe);
|
|
34485
|
+
if (!timelines) return null;
|
|
34486
|
+
let targetEl = null;
|
|
34487
|
+
try {
|
|
34488
|
+
targetEl = iframe?.contentDocument?.querySelector(selector) ?? null;
|
|
34489
|
+
} catch {
|
|
34490
|
+
return null;
|
|
34491
|
+
}
|
|
34492
|
+
if (!targetEl) return null;
|
|
34493
|
+
const tlIds = compositionId ? [compositionId] : Object.keys(timelines).filter((k) => typeof timelines[k]?.getChildren === "function");
|
|
34494
|
+
const wantChannels = channels && channels.length > 0 ? channels : null;
|
|
34495
|
+
let first = null;
|
|
34496
|
+
let channelMatch = null;
|
|
34497
|
+
for (const tlId of tlIds) {
|
|
34498
|
+
const timeline = timelines[tlId];
|
|
34499
|
+
if (!timeline?.getChildren) continue;
|
|
34500
|
+
const now2 = typeof timeline.time === "function" ? timeline.time() : null;
|
|
34501
|
+
for (const tween of timeline.getChildren(true)) {
|
|
34502
|
+
if (!tween.vars || !matchesElement(tween, targetEl)) continue;
|
|
34503
|
+
const dur = typeof tween.duration === "function" ? tween.duration() : 0;
|
|
34504
|
+
const isSet = !(dur > 0);
|
|
34505
|
+
if (kind === "set" ? !isSet : isSet) continue;
|
|
34506
|
+
if (wantChannels) {
|
|
34507
|
+
const carries = kind === "set" ? varsCarryChannel(tween.vars, wantChannels) : keyframeVarsCarryChannel(tween.vars, wantChannels);
|
|
34508
|
+
if (carries) {
|
|
34509
|
+
if (channelMatch === null) channelMatch = { tween, timeline };
|
|
34510
|
+
} else if (first === null) {
|
|
34511
|
+
first = { tween, timeline };
|
|
34512
|
+
}
|
|
34513
|
+
continue;
|
|
34514
|
+
}
|
|
34515
|
+
if (first === null) first = { tween, timeline };
|
|
34516
|
+
if (kind === "keyframe" && now2 != null) {
|
|
34517
|
+
const start = typeof tween.startTime === "function" ? tween.startTime() : 0;
|
|
34518
|
+
if (now2 >= start - 1e-3 && now2 <= start + dur + 1e-3) return { tween, timeline };
|
|
34519
|
+
}
|
|
34520
|
+
}
|
|
34521
|
+
}
|
|
34522
|
+
return channelMatch ?? first;
|
|
34523
|
+
}
|
|
34524
|
+
function readCarriesChannel(read, channels) {
|
|
34525
|
+
return read.keyframes.some((kf) => channels.some((c) => kf.properties[c] != null));
|
|
34526
|
+
}
|
|
34527
|
+
function readRuntimeKeyframes(iframe, selector, compositionId, requireChannels) {
|
|
34528
|
+
const timelines = timelinesOf(iframe);
|
|
34529
|
+
if (!timelines) return null;
|
|
34530
|
+
let targetEl = null;
|
|
34531
|
+
try {
|
|
34532
|
+
targetEl = iframe?.contentDocument?.querySelector(selector) ?? null;
|
|
34533
|
+
} catch {
|
|
34534
|
+
return null;
|
|
34535
|
+
}
|
|
34536
|
+
if (!targetEl) return null;
|
|
34537
|
+
const tlIds = compositionId ? [compositionId] : Object.keys(timelines).filter((k) => typeof timelines[k]?.getChildren === "function");
|
|
34538
|
+
if (tlIds.length === 0) return null;
|
|
34539
|
+
let firstRead = null;
|
|
34540
|
+
for (const tlId of tlIds) {
|
|
34541
|
+
const timeline = timelines[tlId];
|
|
34542
|
+
if (!timeline?.getChildren) continue;
|
|
34543
|
+
const now2 = typeof timeline.time === "function" ? timeline.time() : null;
|
|
34544
|
+
for (const tween of timeline.getChildren(true)) {
|
|
34545
|
+
if (!tween.vars || !matchesElement(tween, targetEl)) continue;
|
|
34546
|
+
const dur = typeof tween.duration === "function" ? tween.duration() : 0;
|
|
34547
|
+
if (isZeroDurationSet(dur)) continue;
|
|
34548
|
+
const read = readTween(tween.vars);
|
|
34549
|
+
if (!read) continue;
|
|
34550
|
+
if (requireChannels && !readCarriesChannel(read, requireChannels)) continue;
|
|
34551
|
+
if (firstRead === null) firstRead = read;
|
|
34552
|
+
if (now2 != null) {
|
|
34553
|
+
const start = typeof tween.startTime === "function" ? tween.startTime() : 0;
|
|
34554
|
+
if (now2 >= start - 1e-3 && now2 <= start + dur + 1e-3) return read;
|
|
34555
|
+
}
|
|
34556
|
+
}
|
|
34557
|
+
}
|
|
34558
|
+
return firstRead;
|
|
34559
|
+
}
|
|
34560
|
+
function hasNonHoldTweenForElement(iframe, selector, compositionId, channels) {
|
|
34561
|
+
let targetEl = null;
|
|
34562
|
+
try {
|
|
34563
|
+
targetEl = iframe?.contentDocument?.querySelector(selector) ?? null;
|
|
34564
|
+
} catch {
|
|
34565
|
+
return false;
|
|
34566
|
+
}
|
|
34567
|
+
return !!targetEl && hasNonHoldTween(timelinesOf(iframe), targetEl, channels, compositionId);
|
|
34568
|
+
}
|
|
34569
|
+
function elementHasNonHoldTween(el, channels) {
|
|
34570
|
+
const win = el.ownerDocument.defaultView;
|
|
34571
|
+
return hasNonHoldTween(win?.__timelines ?? null, el, channels);
|
|
34572
|
+
}
|
|
34573
|
+
function hasNonHoldTween(timelines, targetEl, channels, compositionId) {
|
|
34574
|
+
if (!timelines) return false;
|
|
34575
|
+
for (const tlId of compositionId ? [compositionId] : Object.keys(timelines)) {
|
|
34576
|
+
for (const tween of timelines[tlId]?.getChildren?.(true) ?? []) {
|
|
34577
|
+
if (!tween.vars || !matchesElement(tween, targetEl)) continue;
|
|
34578
|
+
const dur = typeof tween.duration === "function" ? tween.duration() : 0;
|
|
34579
|
+
if (isZeroDurationSet(dur)) continue;
|
|
34580
|
+
if (channels && keyframeVarsCarryChannel(tween.vars, channels)) return true;
|
|
34581
|
+
const read = readTween(tween.vars);
|
|
34582
|
+
if (read && (!channels || readCarriesChannel(read, channels))) return true;
|
|
34583
|
+
}
|
|
34584
|
+
}
|
|
34585
|
+
return false;
|
|
34586
|
+
}
|
|
34587
|
+
function toClipRelative(keyframes, tweenStart, tweenDuration, clip) {
|
|
34588
|
+
if (!clip || clip.duration <= 0) return keyframes;
|
|
34589
|
+
return keyframes.map((kf) => {
|
|
34590
|
+
const abs = toAbsoluteTime(tweenStart, tweenDuration, kf.percentage);
|
|
34591
|
+
return { ...kf, percentage: Math.round((abs - clip.start) / clip.duration * 1e5) / 1e3 };
|
|
34592
|
+
});
|
|
34593
|
+
}
|
|
34594
|
+
function buildEntry(read, start, duration, clip) {
|
|
34595
|
+
return {
|
|
34596
|
+
keyframes: toClipRelative(read.keyframes, start, duration, clip),
|
|
34597
|
+
tweenStart: start,
|
|
34598
|
+
tweenDuration: duration,
|
|
34599
|
+
...read.easeEach ? { easeEach: read.easeEach } : {},
|
|
34600
|
+
...read.arcPath ? { arcPath: read.arcPath } : {}
|
|
34601
|
+
};
|
|
34602
|
+
}
|
|
34603
|
+
function addScanEntry(result, tween, clipById) {
|
|
34604
|
+
if (!tween.targets || !tween.vars) return;
|
|
34605
|
+
const { start, duration } = tweenTiming(tween);
|
|
34606
|
+
if (isZeroDurationSet(duration)) return;
|
|
34607
|
+
const read = readTween(tween.vars);
|
|
34608
|
+
if (!read) return;
|
|
34609
|
+
for (const target of tween.targets()) {
|
|
34610
|
+
const id = target.id;
|
|
34611
|
+
if (id && !result.has(id)) result.set(id, buildEntry(read, start, duration, clipById?.get(id)));
|
|
34612
|
+
}
|
|
34613
|
+
}
|
|
34614
|
+
function scanAllRuntimeKeyframes(iframe, clipById) {
|
|
34615
|
+
const result = /* @__PURE__ */ new Map();
|
|
34616
|
+
const timelines = timelinesOf(iframe);
|
|
34617
|
+
if (!timelines) return result;
|
|
34618
|
+
for (const timeline of Object.values(timelines)) {
|
|
34619
|
+
if (!timeline?.getChildren) continue;
|
|
34620
|
+
for (const tween of timeline.getChildren(true)) addScanEntry(result, tween, clipById);
|
|
34621
|
+
}
|
|
34622
|
+
return result;
|
|
34623
|
+
}
|
|
34624
|
+
|
|
34625
|
+
// src/components/editor/cropResize.ts
|
|
34626
|
+
var boxOf = (element) => ({
|
|
34627
|
+
width: element.offsetWidth,
|
|
34628
|
+
height: element.offsetHeight
|
|
34629
|
+
});
|
|
34630
|
+
function cropFollows(element) {
|
|
34631
|
+
const clip = gsapAnimatesProperty(element, "clipPath");
|
|
34632
|
+
return {
|
|
34633
|
+
width: !clip && !elementHasNonHoldTween(element, ["width"]),
|
|
34634
|
+
height: !clip && !elementHasNonHoldTween(element, ["height"])
|
|
34635
|
+
};
|
|
34636
|
+
}
|
|
34637
|
+
function scaleCrop(crop, from, to, follows) {
|
|
34638
|
+
const sx = follows.width && from.width > 0 ? to.width / from.width : 1;
|
|
34639
|
+
const sy = follows.height && from.height > 0 ? to.height / from.height : 1;
|
|
34640
|
+
return {
|
|
34641
|
+
top: crop.top * sy,
|
|
34642
|
+
right: crop.right * sx,
|
|
34643
|
+
bottom: crop.bottom * sy,
|
|
34644
|
+
left: crop.left * sx,
|
|
34645
|
+
radius: crop.radius
|
|
34646
|
+
};
|
|
34647
|
+
}
|
|
34648
|
+
function readCropFollowingResize(element) {
|
|
34649
|
+
const crop = readElementCropInsets(element);
|
|
34650
|
+
const base2 = readStudioBoxSizeDraftBase(element);
|
|
34651
|
+
return crop && base2 ? scaleCrop(crop, base2, boxOf(element), cropFollows(element)) : crop;
|
|
34652
|
+
}
|
|
34653
|
+
function prepareCropResize(element) {
|
|
34654
|
+
const from = readStudioBoxSizeDraftBase(element) ?? boxOf(element);
|
|
34655
|
+
const before = element.style.getPropertyValue("clip-path");
|
|
34656
|
+
const priority = element.style.getPropertyPriority("clip-path");
|
|
34657
|
+
const follows = cropFollows(element);
|
|
34658
|
+
const crop = readElementCropInsets(element);
|
|
34659
|
+
return () => {
|
|
34660
|
+
forgetStudioBoxSizeDraftBase(element);
|
|
34661
|
+
const to = boxOf(element);
|
|
34662
|
+
const untouched = element.style.getPropertyValue("clip-path") === before;
|
|
34663
|
+
if (!crop || !hasCropInsets(crop) || !untouched || !(to.width > 0 && to.height > 0))
|
|
34664
|
+
return null;
|
|
34665
|
+
const clip = buildInsetClipPathSides(scaleCrop(crop, from, to, follows), crop.radius);
|
|
34666
|
+
if (clip === buildInsetClipPathSides(crop, crop.radius)) return null;
|
|
34667
|
+
element.style.setProperty("clip-path", clip, priority);
|
|
34668
|
+
return {
|
|
34669
|
+
patch: {
|
|
34670
|
+
type: "inline-style",
|
|
34671
|
+
property: "clip-path",
|
|
34672
|
+
value: priority ? `${clip} !important` : clip
|
|
34673
|
+
},
|
|
34674
|
+
revert: () => {
|
|
34675
|
+
if (before) element.style.setProperty("clip-path", before, priority);
|
|
34676
|
+
else element.style.removeProperty("clip-path");
|
|
34677
|
+
}
|
|
34678
|
+
};
|
|
34679
|
+
};
|
|
34680
|
+
}
|
|
34681
|
+
async function saveCropResize(stage, selection, commit, coalesceKey) {
|
|
34682
|
+
const crop = stage();
|
|
34683
|
+
if (!crop) return;
|
|
34684
|
+
try {
|
|
34685
|
+
await commit(selection, [crop.patch], {
|
|
34686
|
+
label: "Resize layer",
|
|
34687
|
+
coalesceKey,
|
|
34688
|
+
coalesceMs: Number.POSITIVE_INFINITY
|
|
34689
|
+
});
|
|
34690
|
+
} catch (error) {
|
|
34691
|
+
crop.revert();
|
|
34692
|
+
throw error;
|
|
34693
|
+
}
|
|
34694
|
+
}
|
|
34695
|
+
var sizeWriteCounter = 0;
|
|
34696
|
+
async function writeSizeWithCrop(selection, properties, mutation, commit, write) {
|
|
34697
|
+
if (!mutation || !("width" in properties || "height" in properties)) return write();
|
|
34698
|
+
const stage = prepareCropResize(selection.element);
|
|
34699
|
+
const coalesceKey = `size-write:${++sizeWriteCounter}`;
|
|
34700
|
+
const undoStep = { coalesceKey, coalesceMs: Number.POSITIVE_INFINITY };
|
|
34701
|
+
const keyed = (s, m, options) => mutation(s, m, { ...options, ...undoStep });
|
|
34702
|
+
if (mutation.batch) {
|
|
34703
|
+
const batch = mutation.batch;
|
|
34704
|
+
keyed.batch = (calls, options) => batch(calls, { ...options, ...undoStep });
|
|
34705
|
+
}
|
|
34706
|
+
await write(keyed);
|
|
34707
|
+
await saveCropResize(stage, selection, commit, coalesceKey);
|
|
34708
|
+
}
|
|
34709
|
+
|
|
34710
|
+
// src/components/editor/DomEditCropHandles.tsx
|
|
34260
34711
|
import { Fragment as Fragment26, jsx as jsx84, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
34261
34712
|
var EDGE_HIT_THICKNESS = 12;
|
|
34262
34713
|
var EDGE_HIT_LENGTH = 32;
|
|
@@ -34297,6 +34748,7 @@ function repositionHandleSize(rect) {
|
|
|
34297
34748
|
return Math.min(REPOSITION_HANDLE_PX, Math.max(rect.width, rect.height) - RESIZE_HANDLE_HIT_PX);
|
|
34298
34749
|
}
|
|
34299
34750
|
var EDGES = ["top", "right", "bottom", "left"];
|
|
34751
|
+
var NO_CROP = { top: 0, right: 0, bottom: 0, left: 0, radius: 0 };
|
|
34300
34752
|
function DomEditCropHandles({
|
|
34301
34753
|
selection,
|
|
34302
34754
|
overlayRect,
|
|
@@ -34307,38 +34759,28 @@ function DomEditCropHandles({
|
|
|
34307
34759
|
const [hotEdge, setHotEdge] = useState40(null);
|
|
34308
34760
|
const cropStateFor = (element) => {
|
|
34309
34761
|
const parsed = readElementCropInsets(element);
|
|
34310
|
-
const {
|
|
34311
|
-
return { element, croppable: parsed !== null, insets,
|
|
34762
|
+
const { top, right, bottom, left } = parsed ?? NO_CROP;
|
|
34763
|
+
return { element, croppable: parsed !== null, insets: { top, right, bottom, left } };
|
|
34312
34764
|
};
|
|
34313
34765
|
const [state, setState] = useState40(() => cropStateFor(selection.element));
|
|
34314
34766
|
if (state.element !== selection.element) {
|
|
34315
34767
|
setState(cropStateFor(selection.element));
|
|
34316
34768
|
}
|
|
34317
|
-
const
|
|
34318
|
-
const
|
|
34319
|
-
const
|
|
34320
|
-
const committedClipRef = useRef65(null);
|
|
34769
|
+
const committed = readCropFollowingResize(selection.element) ?? NO_CROP;
|
|
34770
|
+
const insets = dragging ? state.insets : committed;
|
|
34771
|
+
const hasCrop = hasCropInsets(insets);
|
|
34321
34772
|
useEffect44(() => {
|
|
34322
34773
|
const el = selection.element;
|
|
34323
34774
|
if (readElementCropInsets(el) === null) return;
|
|
34324
|
-
|
|
34325
|
-
|
|
34326
|
-
el.style.setProperty("clip-path", "none");
|
|
34327
|
-
liftedRef.current = true;
|
|
34328
|
-
return () => {
|
|
34329
|
-
liftedRef.current = false;
|
|
34330
|
-
const committed = committedClipRef.current;
|
|
34331
|
-
const restore = committed !== null ? committed || null : preLiftInlineClipRef.current || null;
|
|
34332
|
-
if (restore) el.style.setProperty("clip-path", restore);
|
|
34333
|
-
else el.style.removeProperty("clip-path");
|
|
34334
|
-
};
|
|
34775
|
+
liftElementCrop(el);
|
|
34776
|
+
return () => dropElementCropLift(el);
|
|
34335
34777
|
}, [selection.element]);
|
|
34336
34778
|
const frame = readElementCropFrame(selection.element, overlayRect);
|
|
34337
34779
|
const width = frame.width / frame.scaleX;
|
|
34338
34780
|
const height = frame.height / frame.scaleY;
|
|
34339
34781
|
const cropRect = cropRectFromInsets(
|
|
34340
34782
|
{ left: 0, top: 0, width: frame.width, height: frame.height },
|
|
34341
|
-
|
|
34783
|
+
insets,
|
|
34342
34784
|
frame.scaleX,
|
|
34343
34785
|
frame.scaleY
|
|
34344
34786
|
);
|
|
@@ -34348,17 +34790,20 @@ function DomEditCropHandles({
|
|
|
34348
34790
|
event.preventDefault();
|
|
34349
34791
|
event.stopPropagation();
|
|
34350
34792
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
34793
|
+
const pressed = readCropFollowingResize(selection.element) ?? NO_CROP;
|
|
34351
34794
|
gestureRef.current = {
|
|
34352
34795
|
edge,
|
|
34353
34796
|
pointerId: event.pointerId,
|
|
34354
34797
|
startX: event.clientX,
|
|
34355
34798
|
startY: event.clientY,
|
|
34356
|
-
startInsets:
|
|
34357
|
-
insets:
|
|
34799
|
+
startInsets: pressed,
|
|
34800
|
+
insets: pressed,
|
|
34801
|
+
radius: pressed.radius,
|
|
34358
34802
|
angleDeg: frame.angleDeg,
|
|
34359
34803
|
scaleX: frame.scaleX,
|
|
34360
34804
|
scaleY: frame.scaleY
|
|
34361
34805
|
};
|
|
34806
|
+
setState((prev) => ({ ...prev, insets: pressed }));
|
|
34362
34807
|
setDragging(true);
|
|
34363
34808
|
};
|
|
34364
34809
|
const updateCropGesture = (event) => {
|
|
@@ -34394,19 +34839,10 @@ function DomEditCropHandles({
|
|
|
34394
34839
|
const finishCropGesture = (event) => {
|
|
34395
34840
|
const gesture = endCropGesture(event);
|
|
34396
34841
|
if (!gesture) return;
|
|
34397
|
-
const
|
|
34398
|
-
|
|
34399
|
-
|
|
34400
|
-
|
|
34401
|
-
const { insets } = gesture;
|
|
34402
|
-
const committedValue = buildInsetClipPathSides(insets, state.radius);
|
|
34403
|
-
if (committedValue === buildInsetClipPathSides(gesture.startInsets, state.radius)) return;
|
|
34404
|
-
const cropped = insets.top > 0 || insets.right > 0 || insets.bottom > 0 || insets.left > 0;
|
|
34405
|
-
const commit = onStyleCommit?.("clip-path", committedValue);
|
|
34406
|
-
reLift();
|
|
34407
|
-
void Promise.resolve(commit).then(() => {
|
|
34408
|
-
committedClipRef.current = cropped ? committedValue : "";
|
|
34409
|
-
}, reLift);
|
|
34842
|
+
const value = buildInsetClipPathSides(gesture.insets, gesture.radius);
|
|
34843
|
+
if (value === buildInsetClipPathSides(gesture.startInsets, gesture.radius)) return;
|
|
34844
|
+
const commit = onStyleCommit?.("clip-path", value);
|
|
34845
|
+
void Promise.resolve(commit).catch(() => void 0);
|
|
34410
34846
|
};
|
|
34411
34847
|
const cancelCropGesture = (event) => {
|
|
34412
34848
|
const gesture = endCropGesture(event);
|
|
@@ -34600,7 +35036,6 @@ function DomEditGroupChrome({
|
|
|
34600
35036
|
allowBodyDrag,
|
|
34601
35037
|
groupCanMove,
|
|
34602
35038
|
gestures,
|
|
34603
|
-
onBoxMouseDown,
|
|
34604
35039
|
onBoxClick
|
|
34605
35040
|
}) {
|
|
34606
35041
|
const canManipulate = allowCanvasMovement && !usePreviewReadOnly();
|
|
@@ -34635,7 +35070,6 @@ function DomEditGroupChrome({
|
|
|
34635
35070
|
if (!canManipulate || !allowBodyDrag || e.shiftKey && !groupCanMove) return;
|
|
34636
35071
|
gestures.startGroupDrag(e);
|
|
34637
35072
|
},
|
|
34638
|
-
onMouseDown: onBoxMouseDown,
|
|
34639
35073
|
onClick: onBoxClick
|
|
34640
35074
|
}
|
|
34641
35075
|
)
|
|
@@ -34654,7 +35088,6 @@ function DomEditSelectionChrome({
|
|
|
34654
35088
|
groupSelectionCount,
|
|
34655
35089
|
gestures,
|
|
34656
35090
|
onStyleCommit,
|
|
34657
|
-
onBoxMouseDown,
|
|
34658
35091
|
onBoxClick,
|
|
34659
35092
|
inlineText
|
|
34660
35093
|
}) {
|
|
@@ -34709,7 +35142,6 @@ function DomEditSelectionChrome({
|
|
|
34709
35142
|
}
|
|
34710
35143
|
if (!e.shiftKey) gestures.startBlockedMove(e, selection);
|
|
34711
35144
|
},
|
|
34712
|
-
onMouseDown: onBoxMouseDown,
|
|
34713
35145
|
onClick: onBoxClick,
|
|
34714
35146
|
children: cropOutlineInsetPx && /* @__PURE__ */ jsx86(
|
|
34715
35147
|
"div",
|
|
@@ -34763,19 +35195,19 @@ function DomEditSelectionChrome({
|
|
|
34763
35195
|
// src/hooks/useCropOverlay.ts
|
|
34764
35196
|
function useCropOverlay(params) {
|
|
34765
35197
|
const { selection, overlayRect } = params;
|
|
34766
|
-
const cropInsets = selection ? readElementCropInsets(selection.element) : null;
|
|
34767
|
-
const
|
|
35198
|
+
const cropInsets = selection && !isElementCropLifted(selection.element) ? readElementCropInsets(selection.element) : null;
|
|
35199
|
+
const hasCropInsets2 = Boolean(
|
|
34768
35200
|
cropInsets && (cropInsets.top > 0 || cropInsets.right > 0 || cropInsets.bottom > 0 || cropInsets.left > 0)
|
|
34769
35201
|
);
|
|
34770
35202
|
const sx = overlayRect && overlayRect.editScaleX > 0 ? overlayRect.editScaleX : 1;
|
|
34771
35203
|
const sy = overlayRect && overlayRect.editScaleY > 0 ? overlayRect.editScaleY : 1;
|
|
34772
|
-
const cropOutlineInsetPx = cropInsets &&
|
|
35204
|
+
const cropOutlineInsetPx = cropInsets && hasCropInsets2 ? {
|
|
34773
35205
|
top: cropInsets.top * sy,
|
|
34774
35206
|
right: cropInsets.right * sx,
|
|
34775
35207
|
bottom: cropInsets.bottom * sy,
|
|
34776
35208
|
left: cropInsets.left * sx
|
|
34777
35209
|
} : void 0;
|
|
34778
|
-
return { hasCropInsets, cropOutlineInsetPx };
|
|
35210
|
+
return { hasCropInsets: hasCropInsets2, cropOutlineInsetPx };
|
|
34779
35211
|
}
|
|
34780
35212
|
|
|
34781
35213
|
// src/components/editor/domEditOverlayShape.ts
|
|
@@ -36163,8 +36595,6 @@ var DomEditOverlay = memo25(function DomEditOverlay2({
|
|
|
36163
36595
|
const groupGestureRef = useRef69(null);
|
|
36164
36596
|
const blockedMoveRef = useRef69(null);
|
|
36165
36597
|
const suppressNextBoxClickRef = useRef69(false);
|
|
36166
|
-
const suppressNextBoxMouseDownRef = useRef69(false);
|
|
36167
|
-
const suppressNextOverlayMouseDownRef = useRef69(false);
|
|
36168
36598
|
const snapGuidesRef = useRef69(null);
|
|
36169
36599
|
const rafPausedRef = useRef69(false);
|
|
36170
36600
|
const selectionRef = useRef69(selection);
|
|
@@ -36232,11 +36662,11 @@ var DomEditOverlay = memo25(function DomEditOverlay2({
|
|
|
36232
36662
|
const compRect = useDomEditCompositionRect({ iframeRef, overlayRef });
|
|
36233
36663
|
const compRectRef = useRef69(compRect);
|
|
36234
36664
|
compRectRef.current = compRect;
|
|
36235
|
-
const { hasCropInsets, cropOutlineInsetPx } = useCropOverlay({
|
|
36665
|
+
const { hasCropInsets: hasCropInsets2, cropOutlineInsetPx } = useCropOverlay({
|
|
36236
36666
|
selection,
|
|
36237
36667
|
overlayRect
|
|
36238
36668
|
});
|
|
36239
|
-
const boxClipPath =
|
|
36669
|
+
const boxClipPath = hasCropInsets2 ? void 0 : selectionShapeStyles.clipPath;
|
|
36240
36670
|
const boxChromeClass = resolveBoxChromeClass(Boolean(cropOutlineInsetPx), boxClipPath);
|
|
36241
36671
|
const { offCanvasRects, offCanvasElementsRef } = useOffCanvasIndicators({
|
|
36242
36672
|
iframeRef,
|
|
@@ -36295,11 +36725,11 @@ var DomEditOverlay = memo25(function DomEditOverlay2({
|
|
|
36295
36725
|
selectionRef,
|
|
36296
36726
|
gestures
|
|
36297
36727
|
});
|
|
36298
|
-
const selectionKey =
|
|
36728
|
+
const selectionKey = useMemo39(() => {
|
|
36299
36729
|
if (!selection) return "none";
|
|
36300
36730
|
return `${selection.sourceFile}:${selection.id ?? selection.selector ?? selection.label}:${selection.selectorIndex ?? 0}`;
|
|
36301
36731
|
}, [selection]);
|
|
36302
|
-
const groupBounds =
|
|
36732
|
+
const groupBounds = useMemo39(
|
|
36303
36733
|
() => resolveDomEditGroupOverlayRect(groupOverlayItems.map((item) => item.rect)),
|
|
36304
36734
|
[groupOverlayItems]
|
|
36305
36735
|
);
|
|
@@ -36307,24 +36737,11 @@ var DomEditOverlay = memo25(function DomEditOverlay2({
|
|
|
36307
36737
|
const groupCanMove = hasGroupSelection && groupOverlayItems.length > 1 && groupOverlayItems.every((item) => item.selection.capabilities.canApplyManualOffset);
|
|
36308
36738
|
const handleOverlayMouseDown = (event) => {
|
|
36309
36739
|
if (!allowCanvasMovement) return;
|
|
36310
|
-
if (suppressNextOverlayMouseDownRef.current) {
|
|
36311
|
-
logSelect("mousedown-suppressed", { shift: event.shiftKey });
|
|
36312
|
-
suppressNextOverlayMouseDownRef.current = false;
|
|
36313
|
-
suppressNextBoxMouseDownRef.current = false;
|
|
36314
|
-
suppressNextBoxClickRef.current = false;
|
|
36315
|
-
event.preventDefault();
|
|
36316
|
-
event.stopPropagation();
|
|
36317
|
-
return;
|
|
36318
|
-
}
|
|
36319
36740
|
const target = event.target;
|
|
36320
36741
|
const onBox = Boolean(target?.closest('[data-dom-edit-selection-box="true"]'));
|
|
36321
36742
|
logSelect("mousedown", { shift: event.shiftKey, onBox });
|
|
36322
36743
|
if (onBox) return;
|
|
36323
36744
|
onCanvasMouseDown(event, { hoverSelection: hoverSelectionRef.current });
|
|
36324
|
-
if (event.shiftKey) {
|
|
36325
|
-
suppressNextBoxMouseDownRef.current = true;
|
|
36326
|
-
suppressNextBoxClickRef.current = true;
|
|
36327
|
-
}
|
|
36328
36745
|
};
|
|
36329
36746
|
const handleOverlayPointerDown = (event) => {
|
|
36330
36747
|
if (!allowCanvasMovement || hostInput || event.button !== 0) return;
|
|
@@ -36342,8 +36759,6 @@ var DomEditOverlay = memo25(function DomEditOverlay2({
|
|
|
36342
36759
|
if (!candidate) return;
|
|
36343
36760
|
event.preventDefault();
|
|
36344
36761
|
event.stopPropagation();
|
|
36345
|
-
suppressNextOverlayMouseDownRef.current = true;
|
|
36346
|
-
suppressNextBoxMouseDownRef.current = true;
|
|
36347
36762
|
suppressNextBoxClickRef.current = true;
|
|
36348
36763
|
onSelectionChangeRef.current(candidate, { additive: true });
|
|
36349
36764
|
return;
|
|
@@ -36367,7 +36782,6 @@ var DomEditOverlay = memo25(function DomEditOverlay2({
|
|
|
36367
36782
|
if (overlayRef.current) {
|
|
36368
36783
|
event.preventDefault();
|
|
36369
36784
|
event.stopPropagation();
|
|
36370
|
-
suppressNextOverlayMouseDownRef.current = true;
|
|
36371
36785
|
marquee.begin(event);
|
|
36372
36786
|
return;
|
|
36373
36787
|
}
|
|
@@ -36383,12 +36797,6 @@ var DomEditOverlay = memo25(function DomEditOverlay2({
|
|
|
36383
36797
|
}
|
|
36384
36798
|
onCanvasMouseDown(event, { hoverSelection: hoverSelectionRef.current });
|
|
36385
36799
|
};
|
|
36386
|
-
const suppressBoxMouseDown = (e) => {
|
|
36387
|
-
if (!suppressNextBoxMouseDownRef.current) return;
|
|
36388
|
-
suppressNextBoxMouseDownRef.current = false;
|
|
36389
|
-
e.preventDefault();
|
|
36390
|
-
e.stopPropagation();
|
|
36391
|
-
};
|
|
36392
36800
|
const { contextMenu, closeContextMenu, handleContextMenu } = useCanvasContextMenuState({
|
|
36393
36801
|
selection,
|
|
36394
36802
|
selectionRef,
|
|
@@ -36446,7 +36854,6 @@ var DomEditOverlay = memo25(function DomEditOverlay2({
|
|
|
36446
36854
|
allowBodyDrag: bodyDrag,
|
|
36447
36855
|
groupCanMove,
|
|
36448
36856
|
gestures,
|
|
36449
|
-
onBoxMouseDown: suppressBoxMouseDown,
|
|
36450
36857
|
onBoxClick: handleBoxClick
|
|
36451
36858
|
}
|
|
36452
36859
|
),
|
|
@@ -36466,7 +36873,6 @@ var DomEditOverlay = memo25(function DomEditOverlay2({
|
|
|
36466
36873
|
groupSelectionCount: groupSelections.length,
|
|
36467
36874
|
gestures,
|
|
36468
36875
|
onStyleCommit: onStyleCommitRef.current,
|
|
36469
|
-
onBoxMouseDown: suppressBoxMouseDown,
|
|
36470
36876
|
onBoxClick: handleBoxClick
|
|
36471
36877
|
}
|
|
36472
36878
|
),
|
|
@@ -37562,7 +37968,12 @@ async function commitCandidateEdit(edit, targetPath, originalContent, deps, opti
|
|
|
37562
37968
|
});
|
|
37563
37969
|
}
|
|
37564
37970
|
if (refreshTarget) refreshCommittedEdit(edit.after, deps, options);
|
|
37565
|
-
return {
|
|
37971
|
+
return {
|
|
37972
|
+
status: "committed",
|
|
37973
|
+
version: hashContent(edit.after),
|
|
37974
|
+
before: originalContent,
|
|
37975
|
+
after: edit.after
|
|
37976
|
+
};
|
|
37566
37977
|
}
|
|
37567
37978
|
async function persistSdkCandidateMutation(live, targetPath, originalContent, deps, mutate, options, sourceSnapshot) {
|
|
37568
37979
|
return serializeStudioFileMutation(
|
|
@@ -39840,6 +40251,10 @@ var GsapEditBlockedError = class extends Error {
|
|
|
39840
40251
|
function assertGsapEditPersisted(outcome) {
|
|
39841
40252
|
if (outcome.status === "blocked") throw new GsapEditBlockedError(outcome.reason, outcome.detail);
|
|
39842
40253
|
}
|
|
40254
|
+
async function saveMove(outcome, saveOnElement) {
|
|
40255
|
+
if (outcome.status === "element-offset") return saveOnElement();
|
|
40256
|
+
assertGsapEditPersisted(outcome);
|
|
40257
|
+
}
|
|
39843
40258
|
function assertGsapAnimationDirectlyEditable(animation) {
|
|
39844
40259
|
const editability = editabilityForProvenance(animation.provenance);
|
|
39845
40260
|
if (editability === "unroll") throw new GsapEditBlockedError("unroll-required");
|
|
@@ -40020,8 +40435,8 @@ async function commitStaticGsapRotation(selection, newRotation, selector, existi
|
|
|
40020
40435
|
);
|
|
40021
40436
|
}
|
|
40022
40437
|
async function commitStaticGsapSize(selection, size, selector, existingSet, callbacks) {
|
|
40023
|
-
const width =
|
|
40024
|
-
const height =
|
|
40438
|
+
const width = roundToLayoutPx(size.width);
|
|
40439
|
+
const height = roundToLayoutPx(size.height);
|
|
40025
40440
|
if (existingSet) {
|
|
40026
40441
|
await callbacks.commitMutation(
|
|
40027
40442
|
selection,
|
|
@@ -40049,7 +40464,7 @@ async function commitStaticGsapSize(selection, size, selector, existingSet, call
|
|
|
40049
40464
|
);
|
|
40050
40465
|
}
|
|
40051
40466
|
function positiveOr(n, fallback) {
|
|
40052
|
-
return Number.isFinite(n) && n > 0 ?
|
|
40467
|
+
return Number.isFinite(n) && n > 0 ? roundToLayoutPx(n) : fallback;
|
|
40053
40468
|
}
|
|
40054
40469
|
function resolvePriorSize(sizeSet, el, fallbackW, fallbackH) {
|
|
40055
40470
|
if (sizeSet) {
|
|
@@ -40066,8 +40481,8 @@ async function commitKeyframedSizeFromResize(selection, size, selector, sizeSet,
|
|
|
40066
40481
|
const ts = resolveTweenStart(animatedTween) ?? 0;
|
|
40067
40482
|
const td = resolveTweenDuration(animatedTween);
|
|
40068
40483
|
if (!(td > 0)) return false;
|
|
40069
|
-
const newW =
|
|
40070
|
-
const newH =
|
|
40484
|
+
const newW = roundToLayoutPx(size.width);
|
|
40485
|
+
const newH = roundToLayoutPx(size.height);
|
|
40071
40486
|
const prior = resolvePriorSize(sizeSet, selection.element, newW, newH);
|
|
40072
40487
|
const ct = usePlayerStore.getState().currentTime;
|
|
40073
40488
|
const pct = Math.max(0, Math.min(100, Math.round((ct - ts) / td * 1e3) / 10));
|
|
@@ -40397,249 +40812,6 @@ function commitCreatePath(targetSelector, position, x, y, commit) {
|
|
|
40397
40812
|
|
|
40398
40813
|
// src/components/editor/useMotionPathData.ts
|
|
40399
40814
|
import { useEffect as useEffect52, useRef as useRef73, useState as useState45 } from "react";
|
|
40400
|
-
|
|
40401
|
-
// src/hooks/gsapRuntimeKeyframes.ts
|
|
40402
|
-
import { buildArcPath } from "@hyperframes/core/gsap-parser-acorn";
|
|
40403
|
-
var FLAT_SKIP_KEYS = /* @__PURE__ */ new Set([
|
|
40404
|
-
"ease",
|
|
40405
|
-
"duration",
|
|
40406
|
-
"delay",
|
|
40407
|
-
"stagger",
|
|
40408
|
-
"motionPath",
|
|
40409
|
-
"overwrite",
|
|
40410
|
-
"immediateRender",
|
|
40411
|
-
"onComplete",
|
|
40412
|
-
"onUpdate",
|
|
40413
|
-
"onStart",
|
|
40414
|
-
"keyframes"
|
|
40415
|
-
]);
|
|
40416
|
-
function timelinesOf(iframe) {
|
|
40417
|
-
if (!iframe?.contentWindow) return null;
|
|
40418
|
-
try {
|
|
40419
|
-
return iframe.contentWindow.__timelines ?? null;
|
|
40420
|
-
} catch {
|
|
40421
|
-
return null;
|
|
40422
|
-
}
|
|
40423
|
-
}
|
|
40424
|
-
function isXY(p) {
|
|
40425
|
-
return !!p && typeof p.x === "number" && typeof p.y === "number";
|
|
40426
|
-
}
|
|
40427
|
-
function isZeroDurationSet(duration) {
|
|
40428
|
-
return !(duration > 0);
|
|
40429
|
-
}
|
|
40430
|
-
function coordsFromMotionPath(mp) {
|
|
40431
|
-
if (!mp || typeof mp !== "object") return null;
|
|
40432
|
-
const obj = mp;
|
|
40433
|
-
const pathVal = Array.isArray(mp) ? mp : obj.path;
|
|
40434
|
-
if (!Array.isArray(pathVal)) return null;
|
|
40435
|
-
const coords = pathVal.filter(isXY).map((p) => ({ x: p.x, y: p.y }));
|
|
40436
|
-
if (coords.length < 2) return null;
|
|
40437
|
-
const curviness = typeof obj.curviness === "number" ? obj.curviness : 1;
|
|
40438
|
-
const autoRotate = typeof obj.autoRotate === "number" ? obj.autoRotate : obj.autoRotate === true;
|
|
40439
|
-
return { coords, curviness, autoRotate, isCubic: obj.type === "cubic" };
|
|
40440
|
-
}
|
|
40441
|
-
function flatTweenKeyframes(vars) {
|
|
40442
|
-
const properties = {};
|
|
40443
|
-
for (const [k, v] of Object.entries(vars)) {
|
|
40444
|
-
if (FLAT_SKIP_KEYS.has(k)) continue;
|
|
40445
|
-
if (typeof v === "number") properties[k] = roundTo3(v);
|
|
40446
|
-
else if (typeof v === "string") properties[k] = v;
|
|
40447
|
-
}
|
|
40448
|
-
if (Object.keys(properties).length === 0) return null;
|
|
40449
|
-
return [
|
|
40450
|
-
{ percentage: 0, properties },
|
|
40451
|
-
{ percentage: 100, properties }
|
|
40452
|
-
];
|
|
40453
|
-
}
|
|
40454
|
-
function readTween(vars) {
|
|
40455
|
-
if (vars.keyframes && typeof vars.keyframes === "object") {
|
|
40456
|
-
const parsed = parsePercentageKeyframes(vars.keyframes);
|
|
40457
|
-
if (parsed) return parsed;
|
|
40458
|
-
}
|
|
40459
|
-
const mp = coordsFromMotionPath(vars.motionPath);
|
|
40460
|
-
if (mp) {
|
|
40461
|
-
const shape = buildArcPath(mp.coords, mp.curviness, mp.autoRotate, mp.isCubic);
|
|
40462
|
-
if (shape) {
|
|
40463
|
-
const n = shape.waypoints.length;
|
|
40464
|
-
const keyframes = shape.waypoints.map((wp, i) => ({
|
|
40465
|
-
percentage: n > 1 ? Math.round(i / (n - 1) * 100) : 0,
|
|
40466
|
-
properties: { x: wp.x, y: wp.y }
|
|
40467
|
-
}));
|
|
40468
|
-
return { keyframes, arcPath: shape.arcPath };
|
|
40469
|
-
}
|
|
40470
|
-
}
|
|
40471
|
-
const flat = flatTweenKeyframes(vars);
|
|
40472
|
-
return flat ? { keyframes: flat } : null;
|
|
40473
|
-
}
|
|
40474
|
-
function matchesElement(tween, el) {
|
|
40475
|
-
if (!tween.targets) return false;
|
|
40476
|
-
for (const t of tween.targets()) {
|
|
40477
|
-
if (t === el || el.id && t.id === el.id) return true;
|
|
40478
|
-
}
|
|
40479
|
-
return false;
|
|
40480
|
-
}
|
|
40481
|
-
function tweenTiming(tween) {
|
|
40482
|
-
const rawStart = typeof tween.startTime === "function" ? tween.startTime() : 0;
|
|
40483
|
-
const rawDur = typeof tween.duration === "function" ? tween.duration() : 0;
|
|
40484
|
-
return {
|
|
40485
|
-
start: Number.isFinite(rawStart) ? rawStart : 0,
|
|
40486
|
-
duration: Number.isFinite(rawDur) ? rawDur : 0
|
|
40487
|
-
};
|
|
40488
|
-
}
|
|
40489
|
-
function varsCarryChannel(vars, channels) {
|
|
40490
|
-
if (!vars) return false;
|
|
40491
|
-
for (const ch of channels) {
|
|
40492
|
-
if (Object.prototype.hasOwnProperty.call(vars, ch)) return true;
|
|
40493
|
-
}
|
|
40494
|
-
return false;
|
|
40495
|
-
}
|
|
40496
|
-
function keyframeVarsCarryChannel(vars, channels) {
|
|
40497
|
-
const kf = vars?.keyframes;
|
|
40498
|
-
if (!kf || typeof kf !== "object") return false;
|
|
40499
|
-
const steps = Array.isArray(kf) ? kf : Object.values(kf);
|
|
40500
|
-
return steps.some(
|
|
40501
|
-
(step) => step != null && typeof step === "object" && channels.some((ch) => Object.prototype.hasOwnProperty.call(step, ch))
|
|
40502
|
-
);
|
|
40503
|
-
}
|
|
40504
|
-
function resolveRuntimeTween(iframe, selector, kind, compositionId, channels) {
|
|
40505
|
-
const timelines = timelinesOf(iframe);
|
|
40506
|
-
if (!timelines) return null;
|
|
40507
|
-
let targetEl = null;
|
|
40508
|
-
try {
|
|
40509
|
-
targetEl = iframe?.contentDocument?.querySelector(selector) ?? null;
|
|
40510
|
-
} catch {
|
|
40511
|
-
return null;
|
|
40512
|
-
}
|
|
40513
|
-
if (!targetEl) return null;
|
|
40514
|
-
const tlIds = compositionId ? [compositionId] : Object.keys(timelines).filter((k) => typeof timelines[k]?.getChildren === "function");
|
|
40515
|
-
const wantChannels = channels && channels.length > 0 ? channels : null;
|
|
40516
|
-
let first = null;
|
|
40517
|
-
let channelMatch = null;
|
|
40518
|
-
for (const tlId of tlIds) {
|
|
40519
|
-
const timeline = timelines[tlId];
|
|
40520
|
-
if (!timeline?.getChildren) continue;
|
|
40521
|
-
const now2 = typeof timeline.time === "function" ? timeline.time() : null;
|
|
40522
|
-
for (const tween of timeline.getChildren(true)) {
|
|
40523
|
-
if (!tween.vars || !matchesElement(tween, targetEl)) continue;
|
|
40524
|
-
const dur = typeof tween.duration === "function" ? tween.duration() : 0;
|
|
40525
|
-
const isSet = !(dur > 0);
|
|
40526
|
-
if (kind === "set" ? !isSet : isSet) continue;
|
|
40527
|
-
if (wantChannels) {
|
|
40528
|
-
const carries = kind === "set" ? varsCarryChannel(tween.vars, wantChannels) : keyframeVarsCarryChannel(tween.vars, wantChannels);
|
|
40529
|
-
if (carries) {
|
|
40530
|
-
if (channelMatch === null) channelMatch = { tween, timeline };
|
|
40531
|
-
} else if (first === null) {
|
|
40532
|
-
first = { tween, timeline };
|
|
40533
|
-
}
|
|
40534
|
-
continue;
|
|
40535
|
-
}
|
|
40536
|
-
if (first === null) first = { tween, timeline };
|
|
40537
|
-
if (kind === "keyframe" && now2 != null) {
|
|
40538
|
-
const start = typeof tween.startTime === "function" ? tween.startTime() : 0;
|
|
40539
|
-
if (now2 >= start - 1e-3 && now2 <= start + dur + 1e-3) return { tween, timeline };
|
|
40540
|
-
}
|
|
40541
|
-
}
|
|
40542
|
-
}
|
|
40543
|
-
return channelMatch ?? first;
|
|
40544
|
-
}
|
|
40545
|
-
function readCarriesChannel(read, channels) {
|
|
40546
|
-
return read.keyframes.some((kf) => channels.some((c) => kf.properties[c] != null));
|
|
40547
|
-
}
|
|
40548
|
-
function readRuntimeKeyframes(iframe, selector, compositionId, requireChannels) {
|
|
40549
|
-
const timelines = timelinesOf(iframe);
|
|
40550
|
-
if (!timelines) return null;
|
|
40551
|
-
let targetEl = null;
|
|
40552
|
-
try {
|
|
40553
|
-
targetEl = iframe?.contentDocument?.querySelector(selector) ?? null;
|
|
40554
|
-
} catch {
|
|
40555
|
-
return null;
|
|
40556
|
-
}
|
|
40557
|
-
if (!targetEl) return null;
|
|
40558
|
-
const tlIds = compositionId ? [compositionId] : Object.keys(timelines).filter((k) => typeof timelines[k]?.getChildren === "function");
|
|
40559
|
-
if (tlIds.length === 0) return null;
|
|
40560
|
-
let firstRead = null;
|
|
40561
|
-
for (const tlId of tlIds) {
|
|
40562
|
-
const timeline = timelines[tlId];
|
|
40563
|
-
if (!timeline?.getChildren) continue;
|
|
40564
|
-
const now2 = typeof timeline.time === "function" ? timeline.time() : null;
|
|
40565
|
-
for (const tween of timeline.getChildren(true)) {
|
|
40566
|
-
if (!tween.vars || !matchesElement(tween, targetEl)) continue;
|
|
40567
|
-
const dur = typeof tween.duration === "function" ? tween.duration() : 0;
|
|
40568
|
-
if (isZeroDurationSet(dur)) continue;
|
|
40569
|
-
const read = readTween(tween.vars);
|
|
40570
|
-
if (!read) continue;
|
|
40571
|
-
if (requireChannels && !readCarriesChannel(read, requireChannels)) continue;
|
|
40572
|
-
if (firstRead === null) firstRead = read;
|
|
40573
|
-
if (now2 != null) {
|
|
40574
|
-
const start = typeof tween.startTime === "function" ? tween.startTime() : 0;
|
|
40575
|
-
if (now2 >= start - 1e-3 && now2 <= start + dur + 1e-3) return read;
|
|
40576
|
-
}
|
|
40577
|
-
}
|
|
40578
|
-
}
|
|
40579
|
-
return firstRead;
|
|
40580
|
-
}
|
|
40581
|
-
function hasNonHoldTweenForElement(iframe, selector, compositionId, channels) {
|
|
40582
|
-
const timelines = timelinesOf(iframe);
|
|
40583
|
-
if (!timelines) return false;
|
|
40584
|
-
const tlId = compositionId || Object.keys(timelines).find((k) => typeof timelines[k]?.getChildren === "function");
|
|
40585
|
-
if (!tlId) return false;
|
|
40586
|
-
const timeline = timelines[tlId];
|
|
40587
|
-
if (!timeline?.getChildren) return false;
|
|
40588
|
-
let targetEl = null;
|
|
40589
|
-
try {
|
|
40590
|
-
targetEl = iframe?.contentDocument?.querySelector(selector) ?? null;
|
|
40591
|
-
} catch {
|
|
40592
|
-
return false;
|
|
40593
|
-
}
|
|
40594
|
-
if (!targetEl) return false;
|
|
40595
|
-
for (const tween of timeline.getChildren(true)) {
|
|
40596
|
-
if (!tween.vars || !matchesElement(tween, targetEl)) continue;
|
|
40597
|
-
const dur = typeof tween.duration === "function" ? tween.duration() : 0;
|
|
40598
|
-
if (isZeroDurationSet(dur)) continue;
|
|
40599
|
-
const read = readTween(tween.vars);
|
|
40600
|
-
if (read && (!channels || readCarriesChannel(read, channels))) return true;
|
|
40601
|
-
}
|
|
40602
|
-
return false;
|
|
40603
|
-
}
|
|
40604
|
-
function toClipRelative(keyframes, tweenStart, tweenDuration, clip) {
|
|
40605
|
-
if (!clip || clip.duration <= 0) return keyframes;
|
|
40606
|
-
return keyframes.map((kf) => {
|
|
40607
|
-
const abs = toAbsoluteTime(tweenStart, tweenDuration, kf.percentage);
|
|
40608
|
-
return { ...kf, percentage: Math.round((abs - clip.start) / clip.duration * 1e5) / 1e3 };
|
|
40609
|
-
});
|
|
40610
|
-
}
|
|
40611
|
-
function buildEntry(read, start, duration, clip) {
|
|
40612
|
-
return {
|
|
40613
|
-
keyframes: toClipRelative(read.keyframes, start, duration, clip),
|
|
40614
|
-
tweenStart: start,
|
|
40615
|
-
tweenDuration: duration,
|
|
40616
|
-
...read.easeEach ? { easeEach: read.easeEach } : {},
|
|
40617
|
-
...read.arcPath ? { arcPath: read.arcPath } : {}
|
|
40618
|
-
};
|
|
40619
|
-
}
|
|
40620
|
-
function addScanEntry(result, tween, clipById) {
|
|
40621
|
-
if (!tween.targets || !tween.vars) return;
|
|
40622
|
-
const { start, duration } = tweenTiming(tween);
|
|
40623
|
-
if (isZeroDurationSet(duration)) return;
|
|
40624
|
-
const read = readTween(tween.vars);
|
|
40625
|
-
if (!read) return;
|
|
40626
|
-
for (const target of tween.targets()) {
|
|
40627
|
-
const id = target.id;
|
|
40628
|
-
if (id && !result.has(id)) result.set(id, buildEntry(read, start, duration, clipById?.get(id)));
|
|
40629
|
-
}
|
|
40630
|
-
}
|
|
40631
|
-
function scanAllRuntimeKeyframes(iframe, clipById) {
|
|
40632
|
-
const result = /* @__PURE__ */ new Map();
|
|
40633
|
-
const timelines = timelinesOf(iframe);
|
|
40634
|
-
if (!timelines) return result;
|
|
40635
|
-
for (const timeline of Object.values(timelines)) {
|
|
40636
|
-
if (!timeline?.getChildren) continue;
|
|
40637
|
-
for (const tween of timeline.getChildren(true)) addScanEntry(result, tween, clipById);
|
|
40638
|
-
}
|
|
40639
|
-
return result;
|
|
40640
|
-
}
|
|
40641
|
-
|
|
40642
|
-
// src/components/editor/useMotionPathData.ts
|
|
40643
40815
|
function transformTranslate(el) {
|
|
40644
40816
|
const t = el.ownerDocument?.defaultView?.getComputedStyle(el).transform;
|
|
40645
40817
|
if (!t || t === "none") return { x: 0, y: 0 };
|
|
@@ -41558,10 +41730,10 @@ function PreviewOverlays({
|
|
|
41558
41730
|
}
|
|
41559
41731
|
|
|
41560
41732
|
// src/components/nle/useTimelineEditCallbacks.ts
|
|
41561
|
-
import { useCallback as useCallback65, useMemo as
|
|
41733
|
+
import { useCallback as useCallback65, useMemo as useMemo41 } from "react";
|
|
41562
41734
|
|
|
41563
41735
|
// src/hooks/useGsapTweenCache.ts
|
|
41564
|
-
import { useEffect as useEffect56, useMemo as
|
|
41736
|
+
import { useEffect as useEffect56, useMemo as useMemo40, useRef as useRef76, useState as useState49, useCallback as useCallback64 } from "react";
|
|
41565
41737
|
|
|
41566
41738
|
// src/hooks/gsapRuntimeReaders.ts
|
|
41567
41739
|
import { classifyPropertyGroup as classifyPropertyGroup3 } from "@hyperframes/core/gsap-parser";
|
|
@@ -42437,7 +42609,7 @@ async function tryGsapRotationIntercept(selection, angle, animations, iframe, co
|
|
|
42437
42609
|
if (!anim) {
|
|
42438
42610
|
anim = workingAnimations.find((a) => animationWritesAnyProperty(a, ROTATION_CHANNEL_SET)) ?? null;
|
|
42439
42611
|
}
|
|
42440
|
-
const newRotation =
|
|
42612
|
+
const newRotation = roundTo3(angle);
|
|
42441
42613
|
if (!anim || isInstantHold(anim)) {
|
|
42442
42614
|
const existingSet = anim ?? findRotationSetAnimation(resolvedAnimations, selector, selection.element);
|
|
42443
42615
|
await commitStaticGsapRotation(selection, newRotation, selector, existingSet, {
|
|
@@ -42557,7 +42729,6 @@ function useGsapAnimationsForElement(projectId, sourceFile, target, version, ifr
|
|
|
42557
42729
|
const [multipleTimelines, setMultipleTimelines] = useState49(false);
|
|
42558
42730
|
const [unsupportedTimelinePattern, setUnsupportedTimelinePattern] = useState49(false);
|
|
42559
42731
|
const lastFetchKeyRef = useRef76("");
|
|
42560
|
-
const retryTimerRef = useRef76(null);
|
|
42561
42732
|
const domClipChildrenKey = usePlayerStore(
|
|
42562
42733
|
(s) => s.domClipChildren.map((c) => `${c.id}<${c.hostId}`).join("|")
|
|
42563
42734
|
);
|
|
@@ -42566,10 +42737,6 @@ function useGsapAnimationsForElement(projectId, sourceFile, target, version, ifr
|
|
|
42566
42737
|
const fetchKey = `${projectId}:${sourceFile}:${version}:${targetKey}`;
|
|
42567
42738
|
if (fetchKey === lastFetchKeyRef.current) return;
|
|
42568
42739
|
lastFetchKeyRef.current = fetchKey;
|
|
42569
|
-
if (retryTimerRef.current) {
|
|
42570
|
-
clearTimeout(retryTimerRef.current);
|
|
42571
|
-
retryTimerRef.current = null;
|
|
42572
|
-
}
|
|
42573
42740
|
if (!projectId) {
|
|
42574
42741
|
setAllAnimations([]);
|
|
42575
42742
|
setMultipleTimelines(false);
|
|
@@ -42590,29 +42757,14 @@ function useGsapAnimationsForElement(projectId, sourceFile, target, version, ifr
|
|
|
42590
42757
|
setAllAnimations(parsed.animations);
|
|
42591
42758
|
setMultipleTimelines(parsed.multipleTimelines === true);
|
|
42592
42759
|
setUnsupportedTimelinePattern(parsed.unsupportedTimelinePattern === true);
|
|
42593
|
-
if (parsed.animations.length === 0 && targetKey) {
|
|
42594
|
-
retryTimerRef.current = setTimeout(() => {
|
|
42595
|
-
if (cancelled) return;
|
|
42596
|
-
fetchParsedAnimations(projectId, sourceFile).then((retryParsed) => {
|
|
42597
|
-
if (cancelled) return;
|
|
42598
|
-
if (retryParsed && retryParsed.animations.length > 0) {
|
|
42599
|
-
setAllAnimations(retryParsed.animations);
|
|
42600
|
-
}
|
|
42601
|
-
});
|
|
42602
|
-
}, 800);
|
|
42603
|
-
}
|
|
42604
42760
|
});
|
|
42605
42761
|
return () => {
|
|
42606
42762
|
cancelled = true;
|
|
42607
|
-
if (retryTimerRef.current) {
|
|
42608
|
-
clearTimeout(retryTimerRef.current);
|
|
42609
|
-
retryTimerRef.current = null;
|
|
42610
|
-
}
|
|
42611
42763
|
};
|
|
42612
42764
|
}, [projectId, sourceFile, version, target?.id, target?.selector]);
|
|
42613
42765
|
const targetId = target?.id ?? null;
|
|
42614
42766
|
const targetSelector = target?.selector ?? null;
|
|
42615
|
-
const rawAnimations =
|
|
42767
|
+
const rawAnimations = useMemo40(() => {
|
|
42616
42768
|
if (!targetId && !targetSelector) return [];
|
|
42617
42769
|
const element = target ? findPreviewNode(iframeRef?.current?.contentDocument, target) : null;
|
|
42618
42770
|
return getAnimationsForElement(
|
|
@@ -42621,7 +42773,7 @@ function useGsapAnimationsForElement(projectId, sourceFile, target, version, ifr
|
|
|
42621
42773
|
element
|
|
42622
42774
|
);
|
|
42623
42775
|
}, [allAnimations, target, version, iframeRef]);
|
|
42624
|
-
const animations =
|
|
42776
|
+
const animations = useMemo40(() => {
|
|
42625
42777
|
const iframe = iframeRef?.current;
|
|
42626
42778
|
let result = rawAnimations;
|
|
42627
42779
|
if (iframe) {
|
|
@@ -42947,7 +43099,7 @@ function useTimelineEditCallbacks({
|
|
|
42947
43099
|
},
|
|
42948
43100
|
[handleGsapRemoveKeyframe]
|
|
42949
43101
|
);
|
|
42950
|
-
return
|
|
43102
|
+
return useMemo41(
|
|
42951
43103
|
() => ({
|
|
42952
43104
|
onMoveElement: handleTimelineElementMove,
|
|
42953
43105
|
onMoveElements: handleTimelineElementsMove,
|
|
@@ -43254,7 +43406,7 @@ var CaptionTimeline = memo29(function CaptionTimeline2({
|
|
|
43254
43406
|
});
|
|
43255
43407
|
|
|
43256
43408
|
// src/hooks/useTimelineSelectionPreviewSync.ts
|
|
43257
|
-
import { useEffect as useEffect57, useMemo as
|
|
43409
|
+
import { useEffect as useEffect57, useMemo as useMemo42, useRef as useRef77 } from "react";
|
|
43258
43410
|
var MAX_UNRESOLVED_SYNC_RETRIES = 3;
|
|
43259
43411
|
function orderSelectedIds(ids, anchor2) {
|
|
43260
43412
|
const ordered = [...ids];
|
|
@@ -43301,7 +43453,7 @@ function useTimelineSelectionPreviewSync({
|
|
|
43301
43453
|
applyMarqueeSelection,
|
|
43302
43454
|
onSelectionNotFound
|
|
43303
43455
|
}) {
|
|
43304
|
-
const selectedIds =
|
|
43456
|
+
const selectedIds = useMemo42(
|
|
43305
43457
|
() => orderSelectedIds(selectedElementIds, selectedElementId),
|
|
43306
43458
|
[selectedElementId, selectedElementIds]
|
|
43307
43459
|
);
|
|
@@ -43390,7 +43542,7 @@ function useTimelineSelectionPreviewSync({
|
|
|
43390
43542
|
}
|
|
43391
43543
|
|
|
43392
43544
|
// src/webmcp/StudioAgentTools.tsx
|
|
43393
|
-
import { useCallback as useCallback67, useEffect as useEffect59, useMemo as
|
|
43545
|
+
import { useCallback as useCallback67, useEffect as useEffect59, useMemo as useMemo43 } from "react";
|
|
43394
43546
|
|
|
43395
43547
|
// src/webmcp/useStudioAgentTools.ts
|
|
43396
43548
|
import { useEffect as useEffect58, useRef as useRef78 } from "react";
|
|
@@ -44713,7 +44865,7 @@ function StudioAgentTools() {
|
|
|
44713
44865
|
editHistory,
|
|
44714
44866
|
previewIframeRef
|
|
44715
44867
|
]);
|
|
44716
|
-
const deps =
|
|
44868
|
+
const deps = useMemo43(
|
|
44717
44869
|
() => ({
|
|
44718
44870
|
getSnapshot,
|
|
44719
44871
|
getPreviewDocument: () => previewIframeRef.current?.contentDocument ?? null,
|
|
@@ -45522,6 +45674,7 @@ function EditorShell({
|
|
|
45522
45674
|
onPasteClip,
|
|
45523
45675
|
onDuplicateClip,
|
|
45524
45676
|
canPasteClip,
|
|
45677
|
+
clipMenuItems,
|
|
45525
45678
|
setCompIdToSrc,
|
|
45526
45679
|
setCompositionLoading,
|
|
45527
45680
|
shouldShowMotionPath,
|
|
@@ -45609,6 +45762,7 @@ function EditorShell({
|
|
|
45609
45762
|
onPasteClip,
|
|
45610
45763
|
onDuplicateClip,
|
|
45611
45764
|
canPasteClip,
|
|
45765
|
+
clipMenuItems,
|
|
45612
45766
|
previewOverlay: /* @__PURE__ */ jsx102(
|
|
45613
45767
|
PreviewOverlays,
|
|
45614
45768
|
{
|
|
@@ -45643,7 +45797,8 @@ function EditorShellBody({
|
|
|
45643
45797
|
onCopyClip,
|
|
45644
45798
|
onPasteClip,
|
|
45645
45799
|
onDuplicateClip,
|
|
45646
|
-
canPasteClip
|
|
45800
|
+
canPasteClip,
|
|
45801
|
+
clipMenuItems
|
|
45647
45802
|
}) {
|
|
45648
45803
|
const { compositionStack, updateCompositionStack, containerRef } = useNLEContext();
|
|
45649
45804
|
const seekCaptionTime = useCallback71((time) => {
|
|
@@ -45689,6 +45844,7 @@ function EditorShellBody({
|
|
|
45689
45844
|
onPasteClip,
|
|
45690
45845
|
onDuplicateClip,
|
|
45691
45846
|
canPasteClip,
|
|
45847
|
+
clipMenuItems,
|
|
45692
45848
|
onSelectTimelineElement,
|
|
45693
45849
|
timelineFooter: captionEditMode ? /* @__PURE__ */ jsxs72("div", { className: "border-t border-neutral-800/30 shrink-0", style: { height: 60 }, children: [
|
|
45694
45850
|
/* @__PURE__ */ jsx102("div", { className: "flex items-center gap-1.5 px-2 py-0.5", children: /* @__PURE__ */ jsx102("span", { className: "text-[9px] font-medium text-neutral-500 uppercase tracking-wider", children: "Captions" }) }),
|
|
@@ -45704,7 +45860,7 @@ function EditorShellBody({
|
|
|
45704
45860
|
}
|
|
45705
45861
|
|
|
45706
45862
|
// src/player/components/AudioWaveform.tsx
|
|
45707
|
-
import { memo as memo30, useCallback as useCallback72, useEffect as useEffect61, useMemo as
|
|
45863
|
+
import { memo as memo30, useCallback as useCallback72, useEffect as useEffect61, useMemo as useMemo44, useRef as useRef80 } from "react";
|
|
45708
45864
|
|
|
45709
45865
|
// src/player/components/audioWaveformPeaks.ts
|
|
45710
45866
|
var LOUDNESS_OPACITY_FLOOR = 0.64;
|
|
@@ -45839,7 +45995,7 @@ var AudioWaveform = memo30(function AudioWaveform2({
|
|
|
45839
45995
|
const canvasRef = useRef80(null);
|
|
45840
45996
|
const observerRef = useRef80(null);
|
|
45841
45997
|
const cacheKey = waveformUrl ?? audioUrl;
|
|
45842
|
-
const request =
|
|
45998
|
+
const request = useMemo44(
|
|
45843
45999
|
() => ({
|
|
45844
46000
|
key: createThumbnailKey({ kind: "waveform", source: cacheKey }),
|
|
45845
46001
|
projectId,
|
|
@@ -45946,7 +46102,7 @@ var AudioWaveform = memo30(function AudioWaveform2({
|
|
|
45946
46102
|
});
|
|
45947
46103
|
|
|
45948
46104
|
// src/player/components/ImageThumbnail.tsx
|
|
45949
|
-
import { memo as memo31, useMemo as
|
|
46105
|
+
import { memo as memo31, useMemo as useMemo45 } from "react";
|
|
45950
46106
|
|
|
45951
46107
|
// src/player/lib/thumbnailImageDecoder.ts
|
|
45952
46108
|
function thumbnailSource(source) {
|
|
@@ -46024,7 +46180,7 @@ var ImageThumbnail = memo31(function ImageThumbnail2({
|
|
|
46024
46180
|
rich = false
|
|
46025
46181
|
}) {
|
|
46026
46182
|
const [container, setContainerRef] = useThumbnailStripSize();
|
|
46027
|
-
const request =
|
|
46183
|
+
const request = useMemo45(
|
|
46028
46184
|
() => ({
|
|
46029
46185
|
key: createThumbnailKey({ kind: "image", source: imageSrc, rich: Number(rich) }),
|
|
46030
46186
|
projectId,
|
|
@@ -46418,13 +46574,13 @@ var SourceEditor = memo32(function SourceEditor2({
|
|
|
46418
46574
|
});
|
|
46419
46575
|
|
|
46420
46576
|
// src/components/editor/PropertyPanel.tsx
|
|
46421
|
-
import { memo as memo36, useMemo as
|
|
46577
|
+
import { memo as memo36, useMemo as useMemo61, useRef as useRef112, useState as useState94 } from "react";
|
|
46422
46578
|
|
|
46423
46579
|
// src/components/editor/InspectorHeaderActions.tsx
|
|
46424
46580
|
import { Eye as Eye3, EyeSlash as EyeSlash2 } from "@phosphor-icons/react";
|
|
46425
46581
|
|
|
46426
46582
|
// src/contexts/DesignPanelInputContext.tsx
|
|
46427
|
-
import { useCallback as useCallback75, useContext as useContext11, useMemo as
|
|
46583
|
+
import { useCallback as useCallback75, useContext as useContext11, useMemo as useMemo46 } from "react";
|
|
46428
46584
|
|
|
46429
46585
|
// src/utils/designInputTracking.ts
|
|
46430
46586
|
var COALESCE_WINDOW_MS = 600;
|
|
@@ -46467,7 +46623,7 @@ function DesignPanelInputProvider({
|
|
|
46467
46623
|
children
|
|
46468
46624
|
}) {
|
|
46469
46625
|
const parent = useContext11(DesignPanelInputContext);
|
|
46470
|
-
const value =
|
|
46626
|
+
const value = useMemo46(
|
|
46471
46627
|
() => ({ ui: ui ?? parent.ui, section: section ?? parent.section }),
|
|
46472
46628
|
[ui, section, parent.ui, parent.section]
|
|
46473
46629
|
);
|
|
@@ -48084,7 +48240,7 @@ function MediaSection({
|
|
|
48084
48240
|
import { isHfColorGradingActive as isHfColorGradingActive2 } from "@hyperframes/core/color-grading";
|
|
48085
48241
|
|
|
48086
48242
|
// src/components/editor/propertyPanelColorGradingControls.tsx
|
|
48087
|
-
import { useMemo as
|
|
48243
|
+
import { useMemo as useMemo47, useRef as useRef86, useState as useState56 } from "react";
|
|
48088
48244
|
import {
|
|
48089
48245
|
HF_COLOR_GRADING_PRESETS,
|
|
48090
48246
|
normalizeHfColorGrading
|
|
@@ -48528,7 +48684,7 @@ function ColorGradingControls({
|
|
|
48528
48684
|
const [detailSettings, setDetailSettings] = useState56(null);
|
|
48529
48685
|
const [lutImporting, setLutImporting] = useState56(false);
|
|
48530
48686
|
const [lutImportError, setLutImportError] = useState56(null);
|
|
48531
|
-
const lutAssets =
|
|
48687
|
+
const lutAssets = useMemo47(
|
|
48532
48688
|
() => assets.filter((asset) => LUT_EXT.test(asset)).sort((a, b) => a.localeCompare(b)),
|
|
48533
48689
|
[assets]
|
|
48534
48690
|
);
|
|
@@ -48808,7 +48964,7 @@ function ColorGradingControls({
|
|
|
48808
48964
|
}
|
|
48809
48965
|
|
|
48810
48966
|
// src/components/editor/useColorGradingController.ts
|
|
48811
|
-
import { useCallback as useCallback80, useEffect as useEffect69, useMemo as
|
|
48967
|
+
import { useCallback as useCallback80, useEffect as useEffect69, useMemo as useMemo48, useRef as useRef88, useState as useState58 } from "react";
|
|
48812
48968
|
import {
|
|
48813
48969
|
HF_COLOR_GRADING_ATTR,
|
|
48814
48970
|
hasHfColorGradingAuthoredValues,
|
|
@@ -49229,7 +49385,7 @@ function useColorGradingController({
|
|
|
49229
49385
|
state: "pending",
|
|
49230
49386
|
message: "Waiting for runtime"
|
|
49231
49387
|
}));
|
|
49232
|
-
const selectedAssetPath =
|
|
49388
|
+
const selectedAssetPath = useMemo48(
|
|
49233
49389
|
() => selectedMediaAssetPath(element, projectId),
|
|
49234
49390
|
[element, projectId]
|
|
49235
49391
|
);
|
|
@@ -49276,7 +49432,7 @@ function useColorGradingController({
|
|
|
49276
49432
|
trackStudioPendingEdit(onSetAttributeLive(COLOR_GRADING_DATA_KEY, value));
|
|
49277
49433
|
};
|
|
49278
49434
|
}, [identityKey]);
|
|
49279
|
-
const target =
|
|
49435
|
+
const target = useMemo48(
|
|
49280
49436
|
() => ({
|
|
49281
49437
|
id: element.id ?? null,
|
|
49282
49438
|
hfId: element.hfId ?? null,
|
|
@@ -50256,7 +50412,7 @@ function ColorField({
|
|
|
50256
50412
|
}
|
|
50257
50413
|
|
|
50258
50414
|
// src/components/editor/propertyPanelFont.tsx
|
|
50259
|
-
import { useEffect as useEffect71, useMemo as
|
|
50415
|
+
import { useEffect as useEffect71, useMemo as useMemo49, useRef as useRef90, useState as useState60 } from "react";
|
|
50260
50416
|
|
|
50261
50417
|
// src/components/editor/fontAssets.ts
|
|
50262
50418
|
var FONT_EXT_RE = /\.(eot|otf|ttc|ttf|woff2?)$/i;
|
|
@@ -50480,13 +50636,14 @@ function FontFamilyField({
|
|
|
50480
50636
|
setImportingFonts(false);
|
|
50481
50637
|
}
|
|
50482
50638
|
};
|
|
50483
|
-
const projectFontAssets =
|
|
50639
|
+
const projectFontAssets = useMemo49(
|
|
50484
50640
|
() => uniqueFontOptions(
|
|
50485
50641
|
importedFonts.map((f) => ({ family: f.family, source: "Imported" }))
|
|
50486
50642
|
),
|
|
50487
50643
|
[importedFonts]
|
|
50488
50644
|
);
|
|
50489
|
-
const options =
|
|
50645
|
+
const options = useMemo49(() => {
|
|
50646
|
+
if (!open) return [];
|
|
50490
50647
|
const documentFonts = collectDocumentFontFamilies();
|
|
50491
50648
|
const googleSet = new Set(googleFonts.map((f) => f.toLowerCase()));
|
|
50492
50649
|
const taggedLocal = localFonts.map(
|
|
@@ -50505,8 +50662,8 @@ function FontFamilyField({
|
|
|
50505
50662
|
...DEFAULT_FONT_FAMILIES.map((f) => ({ family: f, source: "System" }))
|
|
50506
50663
|
])
|
|
50507
50664
|
);
|
|
50508
|
-
}, [currentFamily, googleFonts, localFonts, projectFontAssets]);
|
|
50509
|
-
const filteredOptions =
|
|
50665
|
+
}, [open, currentFamily, googleFonts, localFonts, projectFontAssets]);
|
|
50666
|
+
const filteredOptions = useMemo49(() => {
|
|
50510
50667
|
const matches = options.filter((o) => fontMatchesQuery(o.family, query));
|
|
50511
50668
|
if (query.trim()) return matches.slice(0, 200);
|
|
50512
50669
|
const bySource = /* @__PURE__ */ new Map();
|
|
@@ -50742,7 +50899,7 @@ function FontFamilyField({
|
|
|
50742
50899
|
import { useEffect as useEffect73 } from "react";
|
|
50743
50900
|
|
|
50744
50901
|
// src/components/panels/VariablesBindElement.tsx
|
|
50745
|
-
import { useMemo as
|
|
50902
|
+
import { useMemo as useMemo50, useState as useState62 } from "react";
|
|
50746
50903
|
|
|
50747
50904
|
// src/components/panels/VariablesValueControls.tsx
|
|
50748
50905
|
import { useState as useState61 } from "react";
|
|
@@ -51024,7 +51181,7 @@ function VariablesBindElement({
|
|
|
51024
51181
|
}) {
|
|
51025
51182
|
const [activeKey, setActiveKey] = useState62(null);
|
|
51026
51183
|
const [idDraft, setIdDraft] = useState62("");
|
|
51027
|
-
const actions =
|
|
51184
|
+
const actions = useMemo50(() => buildBindActions(selection, sdkSession), [selection, sdkSession]);
|
|
51028
51185
|
if (actions.length === 0) return null;
|
|
51029
51186
|
const active = actions.find((a) => a.key === activeKey) ?? null;
|
|
51030
51187
|
const trimmedId = sanitizeId(idDraft);
|
|
@@ -51135,7 +51292,7 @@ function uniqueId(base2, existing) {
|
|
|
51135
51292
|
}
|
|
51136
51293
|
|
|
51137
51294
|
// src/contexts/VariablePromoteContext.tsx
|
|
51138
|
-
import { useContext as useContext12, useEffect as useEffect72, useMemo as
|
|
51295
|
+
import { useContext as useContext12, useEffect as useEffect72, useMemo as useMemo51, useState as useState63 } from "react";
|
|
51139
51296
|
import { jsx as jsx118 } from "react/jsx-runtime";
|
|
51140
51297
|
var VariablePromoteContext = createStableContext(
|
|
51141
51298
|
"VariablePromoteContext",
|
|
@@ -51158,15 +51315,15 @@ function VariablePromoteProvider({
|
|
|
51158
51315
|
if (!session) return;
|
|
51159
51316
|
return session.on("change", () => setRevision((r) => r + 1));
|
|
51160
51317
|
}, [session]);
|
|
51161
|
-
const actions =
|
|
51318
|
+
const actions = useMemo51(() => {
|
|
51162
51319
|
if (!session || !selection) return [];
|
|
51163
51320
|
return buildBindActions(selection, session);
|
|
51164
51321
|
}, [session, selection, revision]);
|
|
51165
|
-
const declarations =
|
|
51322
|
+
const declarations = useMemo51(() => {
|
|
51166
51323
|
if (!session) return [];
|
|
51167
51324
|
return session.getVariableDeclarations();
|
|
51168
51325
|
}, [session, revision]);
|
|
51169
|
-
const value =
|
|
51326
|
+
const value = useMemo51(
|
|
51170
51327
|
() => ({ session, selection, actions, declarations, persist: persist2, onPersistError }),
|
|
51171
51328
|
[session, selection, actions, declarations, persist2, onPersistError]
|
|
51172
51329
|
);
|
|
@@ -51175,7 +51332,7 @@ function VariablePromoteProvider({
|
|
|
51175
51332
|
function useVariablePromoteChannel(channel) {
|
|
51176
51333
|
const ctx3 = useContext12(VariablePromoteContext);
|
|
51177
51334
|
const key2 = channel.kind === "style" ? `style:${channel.prop}` : channel.kind;
|
|
51178
|
-
return
|
|
51335
|
+
return useMemo51(() => {
|
|
51179
51336
|
if (!ctx3 || !ctx3.session || !ctx3.selection?.hfId) return null;
|
|
51180
51337
|
const { session, selection, actions, declarations, persist: persist2, onPersistError } = ctx3;
|
|
51181
51338
|
const hfId = selection.hfId;
|
|
@@ -51610,7 +51767,7 @@ function parseColorString(value) {
|
|
|
51610
51767
|
}
|
|
51611
51768
|
|
|
51612
51769
|
// src/components/editor/propertyPanelFill.tsx
|
|
51613
|
-
import { useMemo as
|
|
51770
|
+
import { useMemo as useMemo52, useRef as useRef91, useState as useState64 } from "react";
|
|
51614
51771
|
|
|
51615
51772
|
// src/components/icons/ReverseGradientIcon.tsx
|
|
51616
51773
|
import { jsx as jsx120, jsxs as jsxs86 } from "react/jsx-runtime";
|
|
@@ -51685,8 +51842,8 @@ function ImageFillField({
|
|
|
51685
51842
|
const fileInputRef = useRef91(null);
|
|
51686
51843
|
const [uploading, setUploading] = useState64(false);
|
|
51687
51844
|
const [uploadError, setUploadError] = useState64(null);
|
|
51688
|
-
const imageAssets =
|
|
51689
|
-
const selectedAsset =
|
|
51845
|
+
const imageAssets = useMemo52(() => assets.filter((a) => IMAGE_EXT.test(a)), [assets]);
|
|
51846
|
+
const selectedAsset = useMemo52(
|
|
51690
51847
|
() => resolveSelectedAsset(value, sourceFile, imageAssets),
|
|
51691
51848
|
[imageAssets, sourceFile, value]
|
|
51692
51849
|
);
|
|
@@ -53168,7 +53325,7 @@ import { useCallback as useCallback85, useState as useState69 } from "react";
|
|
|
53168
53325
|
import { useShallow } from "zustand/react/shallow";
|
|
53169
53326
|
|
|
53170
53327
|
// src/components/editor/AnimationCard.tsx
|
|
53171
|
-
import { memo as memo34, useCallback as useCallback84, useEffect as useEffect76, useMemo as
|
|
53328
|
+
import { memo as memo34, useCallback as useCallback84, useEffect as useEffect76, useMemo as useMemo53, useRef as useRef94, useState as useState68 } from "react";
|
|
53172
53329
|
import { SUPPORTED_EASES, SUPPORTED_PROPS } from "@hyperframes/core/gsap-constants";
|
|
53173
53330
|
|
|
53174
53331
|
// src/components/editor/gsapAnimationHelpers.ts
|
|
@@ -53709,21 +53866,21 @@ var AnimationCard = memo34(function AnimationCard2({
|
|
|
53709
53866
|
segment?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
53710
53867
|
pendingAutoScrollRef.current = false;
|
|
53711
53868
|
}, [expandedKfPct]);
|
|
53712
|
-
const usedProps =
|
|
53869
|
+
const usedProps = useMemo53(
|
|
53713
53870
|
() => new Set(Object.keys(animation.properties)),
|
|
53714
53871
|
[animation.properties]
|
|
53715
53872
|
);
|
|
53716
|
-
const availableProps =
|
|
53873
|
+
const availableProps = useMemo53(
|
|
53717
53874
|
() => SUPPORTED_PROPS.filter(
|
|
53718
53875
|
(p) => !usedProps.has(p) && (animation.method === "set" || !BOOLEAN_PROPS.has(p))
|
|
53719
53876
|
),
|
|
53720
53877
|
[usedProps, animation.method]
|
|
53721
53878
|
);
|
|
53722
|
-
const usedFromProps =
|
|
53879
|
+
const usedFromProps = useMemo53(
|
|
53723
53880
|
() => new Set(Object.keys(animation.fromProperties ?? {})),
|
|
53724
53881
|
[animation.fromProperties]
|
|
53725
53882
|
);
|
|
53726
|
-
const availableFromProps =
|
|
53883
|
+
const availableFromProps = useMemo53(
|
|
53727
53884
|
() => SUPPORTED_PROPS.filter((p) => !usedFromProps.has(p) && !BOOLEAN_PROPS.has(p)),
|
|
53728
53885
|
[usedFromProps]
|
|
53729
53886
|
);
|
|
@@ -53770,7 +53927,7 @@ var AnimationCard = memo34(function AnimationCard2({
|
|
|
53770
53927
|
const easeName = (animation.keyframes ? animation.keyframes.easeEach : void 0) ?? animation.ease ?? "none";
|
|
53771
53928
|
const easeLabel = easeName.startsWith("custom(") ? "Custom curve" : EASE_LABELS[easeName] ?? easeName;
|
|
53772
53929
|
const endTime = typeof animation.position === "number" ? animation.position + (animation.duration ?? 0) : animation.position;
|
|
53773
|
-
const summary =
|
|
53930
|
+
const summary = useMemo53(() => buildTweenSummary(animation), [animation]);
|
|
53774
53931
|
const setKeys = Object.keys(animation.properties);
|
|
53775
53932
|
if (animation.method === "set" && // `every` is vacuously true on an empty bag — require at least one key so a
|
|
53776
53933
|
// property-less set doesn't masquerade as a position row.
|
|
@@ -54918,7 +55075,7 @@ function PropertyPanel3dTransform({
|
|
|
54918
55075
|
}
|
|
54919
55076
|
|
|
54920
55077
|
// src/components/editor/PropertyPanelFlat.tsx
|
|
54921
|
-
import { useEffect as useEffect97, useMemo as
|
|
55078
|
+
import { useEffect as useEffect97, useMemo as useMemo60, useRef as useRef111, useState as useState93 } from "react";
|
|
54922
55079
|
import { useShallow as useShallow2 } from "zustand/react/shallow";
|
|
54923
55080
|
|
|
54924
55081
|
// src/components/editor/audioFxSummary.ts
|
|
@@ -57088,7 +57245,7 @@ function motionSectionLabel(args) {
|
|
|
57088
57245
|
}
|
|
57089
57246
|
|
|
57090
57247
|
// src/components/editor/propertyPanelAudioFxGroup.tsx
|
|
57091
|
-
import { useMemo as
|
|
57248
|
+
import { useMemo as useMemo56, useState as useState81 } from "react";
|
|
57092
57249
|
import {
|
|
57093
57250
|
HF_AUDIO_FX_ATTR as HF_AUDIO_FX_ATTR6,
|
|
57094
57251
|
HF_AUDIO_FX_DATA_KEY as HF_AUDIO_FX_DATA_KEY2,
|
|
@@ -57108,7 +57265,7 @@ import {
|
|
|
57108
57265
|
} from "@hyperframes/core/audio-automation";
|
|
57109
57266
|
|
|
57110
57267
|
// src/components/editor/propertyPanelFxSection.tsx
|
|
57111
|
-
import { useCallback as useCallback88, useEffect as useEffect84, useMemo as
|
|
57268
|
+
import { useCallback as useCallback88, useEffect as useEffect84, useMemo as useMemo55, useRef as useRef99, useState as useState79 } from "react";
|
|
57112
57269
|
|
|
57113
57270
|
// src/components/editor/audioFxRevealTarget.ts
|
|
57114
57271
|
import { parseAutomationTarget as parseAutomationTarget2 } from "@hyperframes/core/audio-automation";
|
|
@@ -58055,7 +58212,7 @@ function FxEqModule({
|
|
|
58055
58212
|
import { getAudioFxPreset as getAudioFxPreset3 } from "@hyperframes/core/audio-fx-presets";
|
|
58056
58213
|
|
|
58057
58214
|
// src/components/editor/propertyPanelFxNodeRow.tsx
|
|
58058
|
-
import { useMemo as
|
|
58215
|
+
import { useMemo as useMemo54, useState as useState78 } from "react";
|
|
58059
58216
|
import {
|
|
58060
58217
|
defaultAudioFxParams as defaultAudioFxParams3,
|
|
58061
58218
|
getAudioFxDef as getAudioFxDef3
|
|
@@ -58481,11 +58638,11 @@ function FxNodeRow({
|
|
|
58481
58638
|
trackKind
|
|
58482
58639
|
}) {
|
|
58483
58640
|
const registryDef = getAudioFxDef3(node.type);
|
|
58484
|
-
const def =
|
|
58641
|
+
const def = useMemo54(() => registryDef ? plainDef(registryDef) : null, [registryDef]);
|
|
58485
58642
|
const primary = registryDef ? primaryParamOf(registryDef) : null;
|
|
58486
58643
|
const profile = getAudioFxProfile2(node.type);
|
|
58487
|
-
const derived =
|
|
58488
|
-
const onlyPrimary =
|
|
58644
|
+
const derived = useMemo54(() => profileParam(node.type), [node.type]);
|
|
58645
|
+
const onlyPrimary = useMemo54(
|
|
58489
58646
|
() => def && primary ? { ...def, params: def.params.filter((p) => p.key === primary) } : def,
|
|
58490
58647
|
[def, primary]
|
|
58491
58648
|
);
|
|
@@ -59131,12 +59288,12 @@ function FxSection({
|
|
|
59131
59288
|
[chain.nodes, mutate, onRemoveNodeAutomation, trackKind]
|
|
59132
59289
|
);
|
|
59133
59290
|
const [carveOpen, setCarveOpen] = useState79(true);
|
|
59134
|
-
const carveNodes =
|
|
59135
|
-
const handBuilt =
|
|
59291
|
+
const carveNodes = useMemo55(() => chain.nodes.filter((n) => n.fromCarve), [chain.nodes]);
|
|
59292
|
+
const handBuilt = useMemo55(
|
|
59136
59293
|
() => chain.nodes.map((node, i) => ({ node, i })).filter(({ node }) => !node.fromCarve && !node.fromEq),
|
|
59137
59294
|
[chain.nodes]
|
|
59138
59295
|
);
|
|
59139
|
-
const runs =
|
|
59296
|
+
const runs = useMemo55(() => {
|
|
59140
59297
|
const out = [];
|
|
59141
59298
|
for (const item of handBuilt) {
|
|
59142
59299
|
const preset = item.node.fromPreset;
|
|
@@ -59147,8 +59304,8 @@ function FxSection({
|
|
|
59147
59304
|
return out;
|
|
59148
59305
|
}, [handBuilt]);
|
|
59149
59306
|
const [collapsedRuns, setCollapsedRuns] = useState79(/* @__PURE__ */ new Set());
|
|
59150
|
-
const eqIds =
|
|
59151
|
-
const positions =
|
|
59307
|
+
const eqIds = useMemo55(() => audioEqIds(chain), [chain]);
|
|
59308
|
+
const positions = useMemo55(() => {
|
|
59152
59309
|
const map = /* @__PURE__ */ new Map();
|
|
59153
59310
|
let at = (showCarve ? 1 : 0) + eqIds.length;
|
|
59154
59311
|
for (const { i } of handBuilt) map.set(i, ++at);
|
|
@@ -59941,7 +60098,7 @@ function AudioFxGroup({
|
|
|
59941
60098
|
const removeNodeAutomation = (nodeId) => removeNodesAutomation([nodeId]);
|
|
59942
60099
|
const [analysing, setAnalysing] = useState81(false);
|
|
59943
60100
|
const storeElements = usePlayerStore((s) => s.elements);
|
|
59944
|
-
const signalPath =
|
|
60101
|
+
const signalPath = useMemo56(() => {
|
|
59945
60102
|
const doc = element.element?.ownerDocument;
|
|
59946
60103
|
return audioFxSignalPath(
|
|
59947
60104
|
element.tagName?.toLowerCase(),
|
|
@@ -60609,7 +60766,7 @@ function createGsapLivePreview(iframeRef) {
|
|
|
60609
60766
|
}
|
|
60610
60767
|
|
|
60611
60768
|
// src/components/editor/propertyPanelFlatColorGradingSection.tsx
|
|
60612
|
-
import { useEffect as useEffect94, useMemo as
|
|
60769
|
+
import { useEffect as useEffect94, useMemo as useMemo58, useRef as useRef110, useState as useState89 } from "react";
|
|
60613
60770
|
import {
|
|
60614
60771
|
HF_COLOR_GRADING_GRADE_PRESETS,
|
|
60615
60772
|
normalizeHfColorGrading as normalizeHfColorGrading5,
|
|
@@ -60644,7 +60801,7 @@ function presetPreviewHandlers({
|
|
|
60644
60801
|
import { useState as useState85 } from "react";
|
|
60645
60802
|
|
|
60646
60803
|
// src/components/editor/propertyPanelColorCurveGraph.tsx
|
|
60647
|
-
import { useMemo as
|
|
60804
|
+
import { useMemo as useMemo57, useRef as useRef103 } from "react";
|
|
60648
60805
|
import {
|
|
60649
60806
|
compileHfColorCurve,
|
|
60650
60807
|
compileHfHueCurve,
|
|
@@ -60832,8 +60989,8 @@ function CurveGraph({
|
|
|
60832
60989
|
onCancel
|
|
60833
60990
|
}) {
|
|
60834
60991
|
const pointerRef = useRef103(null);
|
|
60835
|
-
const samples =
|
|
60836
|
-
const path =
|
|
60992
|
+
const samples = useMemo57(() => samplesFor(points, tab), [points, tab]);
|
|
60993
|
+
const path = useMemo57(() => curvePath(samples, tab), [samples, tab]);
|
|
60837
60994
|
const selectRelativePoint = (offset) => {
|
|
60838
60995
|
if (points.length === 0) return;
|
|
60839
60996
|
const current = selectedIndex ?? (offset > 0 ? -1 : 0);
|
|
@@ -62630,14 +62787,14 @@ function FlatColorGradingSection({
|
|
|
62630
62787
|
const lutInputRef = useRef110(null);
|
|
62631
62788
|
const [lutOpen, setLutOpen] = useState89(false);
|
|
62632
62789
|
const [detailSettingsOpen, setDetailSettingsOpen] = useState89(null);
|
|
62633
|
-
const lutAssets =
|
|
62790
|
+
const lutAssets = useMemo58(
|
|
62634
62791
|
() => assets.filter((asset) => LUT_EXT.test(asset)).sort((a, b) => a.localeCompare(b)),
|
|
62635
62792
|
[assets]
|
|
62636
62793
|
);
|
|
62637
62794
|
const lut = grading.lut;
|
|
62638
62795
|
const selectedLutName = lut?.src ? lut.src.split("/").pop() ?? lut.src : null;
|
|
62639
|
-
const resolvedGrading =
|
|
62640
|
-
const secondaryInputGrading =
|
|
62796
|
+
const resolvedGrading = useMemo58(() => resolveColorGrading(grading), [grading]);
|
|
62797
|
+
const secondaryInputGrading = useMemo58(
|
|
62641
62798
|
() => resolveColorGrading({
|
|
62642
62799
|
intensity: 1,
|
|
62643
62800
|
adjust: resolvedGrading.adjust,
|
|
@@ -62655,7 +62812,7 @@ function FlatColorGradingSection({
|
|
|
62655
62812
|
]
|
|
62656
62813
|
);
|
|
62657
62814
|
const actions = createColorGradingActions(grading, onCommitColorGrading);
|
|
62658
|
-
const scopesRefreshKey =
|
|
62815
|
+
const scopesRefreshKey = useMemo58(() => serializeHfColorGrading2(grading), [grading]);
|
|
62659
62816
|
useEffect94(() => {
|
|
62660
62817
|
if (presetPreviews.status === "idle") onRequestPresetPreviews();
|
|
62661
62818
|
}, [onRequestPresetPreviews, presetPreviews.status]);
|
|
@@ -63785,7 +63942,7 @@ function FlatEffectsSection({
|
|
|
63785
63942
|
import { useState as useState92 } from "react";
|
|
63786
63943
|
|
|
63787
63944
|
// src/hooks/useBlockCatalog.ts
|
|
63788
|
-
import { useState as useState91, useEffect as useEffect96, useMemo as
|
|
63945
|
+
import { useState as useState91, useEffect as useEffect96, useMemo as useMemo59 } from "react";
|
|
63789
63946
|
|
|
63790
63947
|
// src/utils/blockCategories.ts
|
|
63791
63948
|
import {
|
|
@@ -63852,7 +64009,7 @@ function useBlockCatalog() {
|
|
|
63852
64009
|
cancelled = true;
|
|
63853
64010
|
};
|
|
63854
64011
|
}, []);
|
|
63855
|
-
const filteredBlocks =
|
|
64012
|
+
const filteredBlocks = useMemo59(() => {
|
|
63856
64013
|
let result = blocks;
|
|
63857
64014
|
if (category) {
|
|
63858
64015
|
result = result.filter((b) => b.category === category);
|
|
@@ -64168,7 +64325,7 @@ function PropertyPanelFlat({
|
|
|
64168
64325
|
currentTime,
|
|
64169
64326
|
onSetAttributeQuiet ?? onSetAttributeLive
|
|
64170
64327
|
);
|
|
64171
|
-
const audioGroupLabel =
|
|
64328
|
+
const audioGroupLabel = useMemo60(() => {
|
|
64172
64329
|
const doc = element.element?.ownerDocument;
|
|
64173
64330
|
const id = element.id;
|
|
64174
64331
|
if (!doc || !id) return void 0;
|
|
@@ -64729,12 +64886,12 @@ var PropertyPanel = memo36(function PropertyPanel2(props) {
|
|
|
64729
64886
|
const cacheEntry = usePlayerStore((s) => s.keyframeCache.get(cacheElementKey));
|
|
64730
64887
|
const iframeRef = previewIframeRef ?? { current: null };
|
|
64731
64888
|
const gsapAnimIdForMemo = element ? gsapAnimations?.find((a) => a.keyframes)?.id ?? gsapAnimations?.[0]?.id ?? null : null;
|
|
64732
|
-
const gsapRuntimeValues =
|
|
64889
|
+
const gsapRuntimeValues = useMemo61(
|
|
64733
64890
|
() => element ? readGsapRuntimeValuesForPanel(gsapAnimIdForMemo, gsapAnimations, element, iframeRef) : null,
|
|
64734
64891
|
// eslint-disable-next-line react-hooks/exhaustive-deps -- iframeRef is stable; currentTime drives re-reads during playback
|
|
64735
64892
|
[gsapAnimIdForMemo, gsapAnimations, element, currentTime]
|
|
64736
64893
|
);
|
|
64737
|
-
const gsapBorderRadius =
|
|
64894
|
+
const gsapBorderRadius = useMemo61(
|
|
64738
64895
|
() => element ? readGsapBorderRadiusForPanel(gsapRuntimeValues, gsapAnimations, element, iframeRef) : null,
|
|
64739
64896
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
64740
64897
|
[gsapRuntimeValues, gsapAnimations, element, currentTime]
|
|
@@ -65122,11 +65279,11 @@ var PropertyPanel = memo36(function PropertyPanel2(props) {
|
|
|
65122
65279
|
});
|
|
65123
65280
|
|
|
65124
65281
|
// src/components/editor/FileTree.tsx
|
|
65125
|
-
import { memo as memo38, useState as useState96, useCallback as useCallback90, useMemo as
|
|
65282
|
+
import { memo as memo38, useState as useState96, useCallback as useCallback90, useMemo as useMemo63, useRef as useRef114 } from "react";
|
|
65126
65283
|
import { Plus as Plus2, FolderSimplePlus as FolderSimplePlus2 } from "@phosphor-icons/react";
|
|
65127
65284
|
|
|
65128
65285
|
// src/components/editor/FileTreeNodes.tsx
|
|
65129
|
-
import { memo as memo37, useState as useState95, useCallback as useCallback89, useMemo as
|
|
65286
|
+
import { memo as memo37, useState as useState95, useCallback as useCallback89, useMemo as useMemo62, useRef as useRef113, useEffect as useEffect98 } from "react";
|
|
65130
65287
|
import {
|
|
65131
65288
|
PencilSimple,
|
|
65132
65289
|
Copy,
|
|
@@ -65609,7 +65766,7 @@ var TreeFolder = memo37(function TreeFolder2({
|
|
|
65609
65766
|
}) {
|
|
65610
65767
|
const [isOpen, setIsOpen] = useState95(defaultOpen);
|
|
65611
65768
|
const toggle = useCallback89(() => setIsOpen((v) => !v), []);
|
|
65612
|
-
const children =
|
|
65769
|
+
const children = useMemo62(() => sortChildren(node.children), [node.children]);
|
|
65613
65770
|
const Chevron = isOpen ? ChevronDown : ChevronRight;
|
|
65614
65771
|
const isDragOver = dragOverFolder === node.fullPath;
|
|
65615
65772
|
const isRenaming = inlineInput?.mode === "rename" && inlineInput.originalPath === node.fullPath;
|
|
@@ -65740,8 +65897,8 @@ var FileTree = memo38(function FileTree2({
|
|
|
65740
65897
|
onImportFiles,
|
|
65741
65898
|
lintFindingsByFile
|
|
65742
65899
|
}) {
|
|
65743
|
-
const tree =
|
|
65744
|
-
const children =
|
|
65900
|
+
const tree = useMemo63(() => buildTree(files), [files]);
|
|
65901
|
+
const children = useMemo63(() => sortChildren(tree.children), [tree]);
|
|
65745
65902
|
const [contextMenu, setContextMenu] = useState96(null);
|
|
65746
65903
|
const [inlineInput, setInlineInput] = useState96(null);
|
|
65747
65904
|
const [deleteTarget, setDeleteTarget] = useState96(null);
|
|
@@ -66008,7 +66165,7 @@ var FileTree = memo38(function FileTree2({
|
|
|
66008
66165
|
});
|
|
66009
66166
|
|
|
66010
66167
|
// src/App.tsx
|
|
66011
|
-
import { useState as useState149, useCallback as useCallback185, useRef as useRef181, useMemo as
|
|
66168
|
+
import { useState as useState149, useCallback as useCallback185, useRef as useRef181, useMemo as useMemo81, useLayoutEffect as useLayoutEffect13 } from "react";
|
|
66012
66169
|
|
|
66013
66170
|
// src/hooks/useRightPanelIntents.ts
|
|
66014
66171
|
import { useCallback as useCallback91, useEffect as useEffect99, useRef as useRef115 } from "react";
|
|
@@ -66059,7 +66216,7 @@ function useRightPanelIntent() {
|
|
|
66059
66216
|
}
|
|
66060
66217
|
|
|
66061
66218
|
// src/components/renders/useRenderQueue.ts
|
|
66062
|
-
import { useState as useState98, useEffect as useEffect101, useCallback as useCallback93, useRef as useRef117, useMemo as
|
|
66219
|
+
import { useState as useState98, useEffect as useEffect101, useCallback as useCallback93, useRef as useRef117, useMemo as useMemo64 } from "react";
|
|
66063
66220
|
|
|
66064
66221
|
// src/components/renders/serverError.ts
|
|
66065
66222
|
async function readServerError(res) {
|
|
@@ -66582,7 +66739,7 @@ function useRenderQueue(projectId, activeCompPathRef) {
|
|
|
66582
66739
|
};
|
|
66583
66740
|
}, [projectId]);
|
|
66584
66741
|
const isRendering = jobs.some((j) => j.status === "rendering");
|
|
66585
|
-
return
|
|
66742
|
+
return useMemo64(
|
|
66586
66743
|
() => ({
|
|
66587
66744
|
jobs,
|
|
66588
66745
|
isRendering,
|
|
@@ -67868,7 +68025,7 @@ function useCaptionSync(projectId) {
|
|
|
67868
68025
|
}
|
|
67869
68026
|
|
|
67870
68027
|
// src/hooks/usePersistentEditHistory.ts
|
|
67871
|
-
import { useCallback as useCallback97, useEffect as useEffect105, useMemo as
|
|
68028
|
+
import { useCallback as useCallback97, useEffect as useEffect105, useMemo as useMemo65, useRef as useRef124, useState as useState104 } from "react";
|
|
67872
68029
|
var EMPTY3 = { entries: [], back: null, forward: null };
|
|
67873
68030
|
var DEFAULT_COALESCE_MS = 300;
|
|
67874
68031
|
function historyUrl(projectId, path = "") {
|
|
@@ -67992,7 +68149,7 @@ function usePersistentEditHistory({ projectId }) {
|
|
|
67992
68149
|
);
|
|
67993
68150
|
const undo = useCallback97((callbacks) => step("undo", callbacks), [step]);
|
|
67994
68151
|
const redo = useCallback97((callbacks) => step("redo", callbacks), [step]);
|
|
67995
|
-
const state =
|
|
68152
|
+
const state = useMemo65(() => {
|
|
67996
68153
|
const backAt = Math.max(view.back?.endedAt ?? 0, heldClaimRef.current?.at ?? 0);
|
|
67997
68154
|
const redoAt = redoneAt(view);
|
|
67998
68155
|
return {
|
|
@@ -68072,7 +68229,7 @@ function usePanelLayout(initialState2) {
|
|
|
68072
68229
|
import { useState as useState106, useCallback as useCallback102, useRef as useRef128 } from "react";
|
|
68073
68230
|
|
|
68074
68231
|
// src/hooks/useFileTree.ts
|
|
68075
|
-
import { useState as useState105, useCallback as useCallback99, useEffect as useEffect107, useMemo as
|
|
68232
|
+
import { useState as useState105, useCallback as useCallback99, useEffect as useEffect107, useMemo as useMemo66, useRef as useRef126 } from "react";
|
|
68076
68233
|
var EMPTY_FILE_LIST = [];
|
|
68077
68234
|
function useFileTree({ projectId, projectIdRef }) {
|
|
68078
68235
|
const [fetched, setFetched] = useState105(null);
|
|
@@ -68136,11 +68293,11 @@ function useFileTree({ projectId, projectIdRef }) {
|
|
|
68136
68293
|
);
|
|
68137
68294
|
}
|
|
68138
68295
|
}, [projectIdRef]);
|
|
68139
|
-
const assets =
|
|
68296
|
+
const assets = useMemo66(
|
|
68140
68297
|
() => fileTree.filter((f) => !f.endsWith(".html") && !f.endsWith(".md") && !f.endsWith(".json")),
|
|
68141
68298
|
[fileTree]
|
|
68142
68299
|
);
|
|
68143
|
-
const fontAssets =
|
|
68300
|
+
const fontAssets = useMemo66(
|
|
68144
68301
|
() => (projectId ? assets : []).filter((asset) => FONT_EXT.test(asset)).map((asset) => ({
|
|
68145
68302
|
family: fontFamilyFromAssetPath(asset),
|
|
68146
68303
|
path: asset,
|
|
@@ -68284,9 +68441,9 @@ function useEditorSave({
|
|
|
68284
68441
|
}
|
|
68285
68442
|
|
|
68286
68443
|
// src/hooks/useProjectFileWriter.ts
|
|
68287
|
-
import { useCallback as useCallback101, useMemo as
|
|
68444
|
+
import { useCallback as useCallback101, useMemo as useMemo67 } from "react";
|
|
68288
68445
|
function useProjectFileWriter({ projectId }) {
|
|
68289
|
-
const fileVersionScope =
|
|
68446
|
+
const fileVersionScope = useMemo67(
|
|
68290
68447
|
() => ({ projectId, versions: /* @__PURE__ */ new Map() }),
|
|
68291
68448
|
[projectId]
|
|
68292
68449
|
);
|
|
@@ -68391,7 +68548,7 @@ function useProjectFileWriter({ projectId }) {
|
|
|
68391
68548
|
},
|
|
68392
68549
|
[fileVersions, projectId]
|
|
68393
68550
|
);
|
|
68394
|
-
return
|
|
68551
|
+
return useMemo67(
|
|
68395
68552
|
() => ({
|
|
68396
68553
|
fileVersions,
|
|
68397
68554
|
readProjectFile,
|
|
@@ -70977,7 +71134,7 @@ function useTimelineGroupEditing({
|
|
|
70977
71134
|
async (input) => {
|
|
70978
71135
|
const sharedPath = allChangesSharePath(input.changes, activeCompPath);
|
|
70979
71136
|
const canUseSdk = !input.needsExtension && sharedPath !== null && input.eligible && input.sdkChanges.every((change) => change !== null);
|
|
70980
|
-
if (!canUseSdk) return
|
|
71137
|
+
if (!canUseSdk) return null;
|
|
70981
71138
|
const result = await sdkTimingBatchPersist(
|
|
70982
71139
|
input.sdkChanges.filter((change) => change !== null),
|
|
70983
71140
|
sharedPath,
|
|
@@ -70997,7 +71154,7 @@ function useTimelineGroupEditing({
|
|
|
70997
71154
|
skipRefresh: true
|
|
70998
71155
|
}
|
|
70999
71156
|
);
|
|
71000
|
-
return cutoverCommittedOrThrow(result);
|
|
71157
|
+
return cutoverCommittedOrThrow(result) ? { sdkGsap: sdkTimingGsapSync(result) } : null;
|
|
71001
71158
|
},
|
|
71002
71159
|
[
|
|
71003
71160
|
activeCompPath,
|
|
@@ -71034,7 +71191,7 @@ function useTimelineGroupEditing({
|
|
|
71034
71191
|
const label = options?.label ?? "Move timeline clips";
|
|
71035
71192
|
return enqueueGroupOperation(label, async (projectId) => {
|
|
71036
71193
|
await options?.beforeTiming;
|
|
71037
|
-
const
|
|
71194
|
+
const sdk = await trySdkBatchPersist({
|
|
71038
71195
|
changes,
|
|
71039
71196
|
sdkChanges: toSdkTimingChanges(changes, (change) => ({
|
|
71040
71197
|
start: toAuthoredStart(change.element, change.start)
|
|
@@ -71045,7 +71202,7 @@ function useTimelineGroupEditing({
|
|
|
71045
71202
|
coalesceKey,
|
|
71046
71203
|
coalesceMs
|
|
71047
71204
|
});
|
|
71048
|
-
if (!
|
|
71205
|
+
if (!sdk) {
|
|
71049
71206
|
await persistServerBatch(
|
|
71050
71207
|
projectId,
|
|
71051
71208
|
label,
|
|
@@ -71076,6 +71233,7 @@ function useTimelineGroupEditing({
|
|
|
71076
71233
|
writeProjectFile,
|
|
71077
71234
|
activeCompPath,
|
|
71078
71235
|
changes,
|
|
71236
|
+
sdkGsap: sdk?.sdkGsap,
|
|
71079
71237
|
resolveChangePath: (element) => targetPathFor(element, activeCompPath),
|
|
71080
71238
|
mutateChange: (change, changePath) => {
|
|
71081
71239
|
const delta = change.start - change.element.start;
|
|
@@ -71135,7 +71293,7 @@ function useTimelineGroupEditing({
|
|
|
71135
71293
|
const coalesceMs = options?.coalesceMs;
|
|
71136
71294
|
return enqueueGroupOperation("Resize timeline clips", async (projectId) => {
|
|
71137
71295
|
await options?.beforeTiming;
|
|
71138
|
-
const
|
|
71296
|
+
const sdk = await trySdkBatchPersist({
|
|
71139
71297
|
changes,
|
|
71140
71298
|
sdkChanges: toSdkTimingChanges(changes, (change) => ({
|
|
71141
71299
|
start: toAuthoredStart(change.element, change.start),
|
|
@@ -71147,7 +71305,7 @@ function useTimelineGroupEditing({
|
|
|
71147
71305
|
coalesceKey,
|
|
71148
71306
|
coalesceMs
|
|
71149
71307
|
});
|
|
71150
|
-
if (!
|
|
71308
|
+
if (!sdk) {
|
|
71151
71309
|
await persistServerBatch(
|
|
71152
71310
|
projectId,
|
|
71153
71311
|
"Resize timeline clips",
|
|
@@ -71175,6 +71333,7 @@ function useTimelineGroupEditing({
|
|
|
71175
71333
|
writeProjectFile,
|
|
71176
71334
|
activeCompPath,
|
|
71177
71335
|
changes,
|
|
71336
|
+
sdkGsap: sdk?.sdkGsap,
|
|
71178
71337
|
resolveChangePath: (element) => targetPathFor(element, activeCompPath),
|
|
71179
71338
|
mutateChange: (change, changePath) => {
|
|
71180
71339
|
const domId = change.element.domId;
|
|
@@ -71379,10 +71538,8 @@ function useTimelineEditing({
|
|
|
71379
71538
|
);
|
|
71380
71539
|
};
|
|
71381
71540
|
const coalesceKey = `timeline-move:${element.hfId ?? element.id}`;
|
|
71382
|
-
const finishMoveGsapSync = () => (
|
|
71383
|
-
//
|
|
71384
|
-
// durable clip-start commit. The SDK owns the attribute write; this
|
|
71385
|
-
// sync owns only the dependent animation rewrite and preview refresh.
|
|
71541
|
+
const finishMoveGsapSync = (sdkGsap) => (
|
|
71542
|
+
// One GSAP sync per edit: the SDK commit's own (sdkGsap), else the server rewrite here.
|
|
71386
71543
|
finishClipTimingFallback({
|
|
71387
71544
|
iframe: previewIframeRef.current,
|
|
71388
71545
|
reloadPreview,
|
|
@@ -71393,11 +71550,12 @@ function useTimelineEditing({
|
|
|
71393
71550
|
coalesceKey,
|
|
71394
71551
|
recordEdit,
|
|
71395
71552
|
writeProjectFile,
|
|
71396
|
-
edit: { kind: "shift", delta: updates.start - element.start }
|
|
71553
|
+
edit: { kind: "shift", delta: updates.start - element.start },
|
|
71554
|
+
sdkGsap
|
|
71397
71555
|
}).finally(() => invalidateGsapCache?.())
|
|
71398
71556
|
);
|
|
71399
71557
|
const moveFallback = () => enqueueEdit(element, "Move timeline clip", buildMovePatches, coalesceKey).then(
|
|
71400
|
-
finishMoveGsapSync
|
|
71558
|
+
() => finishMoveGsapSync()
|
|
71401
71559
|
);
|
|
71402
71560
|
return reorderDone.then(() => {
|
|
71403
71561
|
if (sdkSession && element.hfId && !needsExtension && !trackChanged) {
|
|
@@ -71419,7 +71577,7 @@ function useTimelineEditing({
|
|
|
71419
71577
|
{ label: "Move timeline clip", coalesceKey, skipRefresh: true }
|
|
71420
71578
|
).then((result) => {
|
|
71421
71579
|
if (!cutoverCommittedOrThrow(result)) return moveFallback();
|
|
71422
|
-
return finishMoveGsapSync();
|
|
71580
|
+
return finishMoveGsapSync(sdkTimingGsapSync(result));
|
|
71423
71581
|
});
|
|
71424
71582
|
}
|
|
71425
71583
|
return moveFallback();
|
|
@@ -71468,7 +71626,7 @@ function useTimelineEditing({
|
|
|
71468
71626
|
};
|
|
71469
71627
|
const hasPbsAdjustment = updates.playbackStart != null || updates.start !== element.start && element.playbackStart != null;
|
|
71470
71628
|
const coalesceKey = `timeline-resize:${element.hfId ?? element.id}`;
|
|
71471
|
-
const finishResizeGsapSync = () => finishClipTimingFallback({
|
|
71629
|
+
const finishResizeGsapSync = (sdkGsap) => finishClipTimingFallback({
|
|
71472
71630
|
iframe: previewIframeRef.current,
|
|
71473
71631
|
reloadPreview,
|
|
71474
71632
|
projectId: projectIdRef.current,
|
|
@@ -71482,10 +71640,11 @@ function useTimelineEditing({
|
|
|
71482
71640
|
kind: "scale",
|
|
71483
71641
|
from: { start: toCompositionTime(element, element.start), duration: element.duration },
|
|
71484
71642
|
to: { start: toCompositionTime(element, updates.start), duration: updates.duration }
|
|
71485
|
-
}
|
|
71643
|
+
},
|
|
71644
|
+
sdkGsap
|
|
71486
71645
|
}).finally(() => invalidateGsapCache?.());
|
|
71487
71646
|
const resizeFallback = () => enqueueEdit(element, "Resize timeline clip", buildResizePatches, coalesceKey).then(
|
|
71488
|
-
finishResizeGsapSync
|
|
71647
|
+
() => finishResizeGsapSync()
|
|
71489
71648
|
);
|
|
71490
71649
|
const persistDone = sdkSession && element.hfId && !hasPbsAdjustment && !needsExtension ? sdkTimingPersist(
|
|
71491
71650
|
element.hfId,
|
|
@@ -71505,7 +71664,7 @@ function useTimelineEditing({
|
|
|
71505
71664
|
{ label: "Resize timeline clip", coalesceKey, skipRefresh: true }
|
|
71506
71665
|
).then((result) => {
|
|
71507
71666
|
if (!cutoverCommittedOrThrow(result)) return resizeFallback();
|
|
71508
|
-
return finishResizeGsapSync();
|
|
71667
|
+
return finishResizeGsapSync(sdkTimingGsapSync(result));
|
|
71509
71668
|
}) : resizeFallback();
|
|
71510
71669
|
return persistDone.catch((error) => {
|
|
71511
71670
|
rollbackDuration();
|
|
@@ -73926,8 +74085,8 @@ function readDragStart(el, axis) {
|
|
|
73926
74085
|
function applyElementPositionOffset(el, gestureOffset) {
|
|
73927
74086
|
const cs = el.ownerDocument.defaultView?.getComputedStyle(el);
|
|
73928
74087
|
if (!cs) return "anchored";
|
|
73929
|
-
const dx =
|
|
73930
|
-
const dy =
|
|
74088
|
+
const dx = roundTo3(gestureOffset.x - readDragStart(el, "x"));
|
|
74089
|
+
const dy = roundTo3(gestureOffset.y - readDragStart(el, "y"));
|
|
73931
74090
|
const lifted = el.getAttribute(LAYER_REVEAL_PRIOR_POSITION_ATTR) === "static";
|
|
73932
74091
|
const isStatic = lifted || !/^(relative|absolute|fixed|sticky)$/.test(cs.position);
|
|
73933
74092
|
if (!isStatic && (cs.left.endsWith("%") || cs.top.endsWith("%"))) return "percent";
|
|
@@ -73936,8 +74095,8 @@ function applyElementPositionOffset(el, gestureOffset) {
|
|
|
73936
74095
|
const previous = { position: el.style.position, left: el.style.left, top: el.style.top };
|
|
73937
74096
|
const before = layoutBox(el);
|
|
73938
74097
|
if (isStatic) el.style.position = "relative";
|
|
73939
|
-
el.style.left = `${
|
|
73940
|
-
el.style.top = `${
|
|
74098
|
+
el.style.left = `${roundTo3(baseLeft + dx)}px`;
|
|
74099
|
+
el.style.top = `${roundTo3(baseTop + dy)}px`;
|
|
73941
74100
|
const after = layoutBox(el);
|
|
73942
74101
|
const shiftedExactly = Math.abs(after.left - before.left - dx) <= 1 && Math.abs(after.top - before.top - dy) <= 1 && Math.abs(after.width - before.width) <= 1 && Math.abs(after.height - before.height) <= 1;
|
|
73943
74102
|
if (!shiftedExactly) {
|
|
@@ -74239,8 +74398,11 @@ function useDomGeometryCommits({
|
|
|
74239
74398
|
if (gsapFallback) return gsapFallback;
|
|
74240
74399
|
const beforeSize = captureStudioBoxSize(selection.element);
|
|
74241
74400
|
const beforeOffset = offset ? captureStudioPathOffset(selection.element) : null;
|
|
74401
|
+
const stageCrop = prepareCropResize(selection.element);
|
|
74242
74402
|
applyStudioBoxSize(selection.element, next);
|
|
74403
|
+
const crop = stageCrop();
|
|
74243
74404
|
const patches = buildBoxSizePatches(selection.element);
|
|
74405
|
+
if (crop) patches.push(crop.patch);
|
|
74244
74406
|
if (offset) {
|
|
74245
74407
|
applyStudioPathOffset(selection.element, offset);
|
|
74246
74408
|
patches.push(...buildPathOffsetPatches(selection.element));
|
|
@@ -74251,6 +74413,7 @@ function useDomGeometryCommits({
|
|
|
74251
74413
|
}).catch((error) => {
|
|
74252
74414
|
restoreStudioBoxSize(selection.element, beforeSize);
|
|
74253
74415
|
if (beforeOffset) restoreStudioPathOffset(selection.element, beforeOffset);
|
|
74416
|
+
crop?.revert();
|
|
74254
74417
|
throw error;
|
|
74255
74418
|
});
|
|
74256
74419
|
},
|
|
@@ -74521,6 +74684,7 @@ function useDomEditCommits({
|
|
|
74521
74684
|
handleDomAddTextField,
|
|
74522
74685
|
handleDomRemoveTextField,
|
|
74523
74686
|
stageElementPositionOffset,
|
|
74687
|
+
commitPositionPatchToHtml,
|
|
74524
74688
|
handleDomPathOffsetCommit,
|
|
74525
74689
|
handleDomBoxSizeCommit,
|
|
74526
74690
|
handleDomRotationCommit,
|
|
@@ -74664,7 +74828,7 @@ function useGroupCommits(params) {
|
|
|
74664
74828
|
}
|
|
74665
74829
|
|
|
74666
74830
|
// src/hooks/useGsapScriptCommits.ts
|
|
74667
|
-
import { useCallback as useCallback132, useMemo as
|
|
74831
|
+
import { useCallback as useCallback132, useMemo as useMemo68, useRef as useRef144 } from "react";
|
|
74668
74832
|
import { findUnsafeMutationValues } from "@hyperframes/core/studio-api/finite-mutation";
|
|
74669
74833
|
|
|
74670
74834
|
// src/hooks/gsapRuntimePatch.ts
|
|
@@ -75987,7 +76151,7 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
|
|
|
75987
76151
|
const { instantPatch: _instantPatch, ...batchOptions } = options;
|
|
75988
76152
|
await finalizeSuccessfulMutation(pid, compositionPath, last.selection, last.mutation, targetPath, result, instantPatches.length > 0 ? { ...batchOptions, instantPatches } : batchOptions);
|
|
75989
76153
|
}, [showToast, finalizeSuccessfulMutation]);
|
|
75990
|
-
const commitMutation =
|
|
76154
|
+
const commitMutation = useMemo68(() => {
|
|
75991
76155
|
const serializeFile = (file, task) => {
|
|
75992
76156
|
if (writeProjectFile) {
|
|
75993
76157
|
return serializeStudioFileMutation(writeProjectFile, file, task);
|
|
@@ -76052,7 +76216,7 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
|
|
|
76052
76216
|
},
|
|
76053
76217
|
[activeProjectId]
|
|
76054
76218
|
);
|
|
76055
|
-
const sdkDeps =
|
|
76219
|
+
const sdkDeps = useMemo68(
|
|
76056
76220
|
() => writeProjectFile ? {
|
|
76057
76221
|
editHistory: { recordEdit: editHistory.recordEdit },
|
|
76058
76222
|
writeProjectFile,
|
|
@@ -76199,8 +76363,6 @@ function useDomEditPreviewSync({
|
|
|
76199
76363
|
|
|
76200
76364
|
// src/hooks/useGsapAnimationFetchFallback.ts
|
|
76201
76365
|
import { useCallback as useCallback133 } from "react";
|
|
76202
|
-
var COLD_PARSE_RETRIES = 5;
|
|
76203
|
-
var COLD_PARSE_DELAY_MS = 120;
|
|
76204
76366
|
var FETCH_ERROR_RETRIES = 1;
|
|
76205
76367
|
var FETCH_ERROR_DELAY_MS = 120;
|
|
76206
76368
|
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
@@ -76209,32 +76371,22 @@ function gsapSourceFileForSelection(selection) {
|
|
|
76209
76371
|
}
|
|
76210
76372
|
function selectElementAnimationsOrRetry(parsed, target, element) {
|
|
76211
76373
|
if (!parsed) return { kind: "fetch-error" };
|
|
76212
|
-
if (parsed.animations.length === 0) return { kind: "cold" };
|
|
76213
76374
|
return {
|
|
76214
76375
|
kind: "resolved",
|
|
76215
76376
|
animations: getAnimationsForElement(parsed.animations, target, element)
|
|
76216
76377
|
};
|
|
76217
76378
|
}
|
|
76218
76379
|
async function fetchElementAnimationsWithRetry(projectId, gsapSourceFile, target, element, failOnFetchError, fresh) {
|
|
76219
|
-
let
|
|
76220
|
-
let errorAttempts = 0;
|
|
76221
|
-
for (; ; ) {
|
|
76380
|
+
for (let errorAttempts = 0; ; errorAttempts++) {
|
|
76222
76381
|
const parsed = await fetchParsedAnimations(projectId, gsapSourceFile, { fresh });
|
|
76223
76382
|
fresh = false;
|
|
76224
76383
|
const outcome = selectElementAnimationsOrRetry(parsed, target, element);
|
|
76225
76384
|
if (outcome.kind === "resolved") return outcome.animations;
|
|
76226
|
-
if (
|
|
76227
|
-
if (
|
|
76228
|
-
|
|
76229
|
-
return [];
|
|
76230
|
-
}
|
|
76231
|
-
errorAttempts++;
|
|
76232
|
-
await delay(FETCH_ERROR_DELAY_MS);
|
|
76233
|
-
continue;
|
|
76385
|
+
if (errorAttempts >= FETCH_ERROR_RETRIES) {
|
|
76386
|
+
if (failOnFetchError) throw new Error("GSAP animation ownership could not be verified");
|
|
76387
|
+
return [];
|
|
76234
76388
|
}
|
|
76235
|
-
|
|
76236
|
-
coldAttempts++;
|
|
76237
|
-
await delay(COLD_PARSE_DELAY_MS);
|
|
76389
|
+
await delay(FETCH_ERROR_DELAY_MS);
|
|
76238
76390
|
}
|
|
76239
76391
|
}
|
|
76240
76392
|
function useGsapAnimationFetchFallback(projectId) {
|
|
@@ -76887,8 +77039,8 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
76887
77039
|
}
|
|
76888
77040
|
} else {
|
|
76889
77041
|
resizeProps = {
|
|
76890
|
-
width:
|
|
76891
|
-
height:
|
|
77042
|
+
width: roundToLayoutPx(size.width),
|
|
77043
|
+
height: roundToLayoutPx(size.height)
|
|
76892
77044
|
};
|
|
76893
77045
|
}
|
|
76894
77046
|
const finalizeScaleResizeCommit = async () => {
|
|
@@ -76914,8 +77066,8 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
76914
77066
|
return true;
|
|
76915
77067
|
}
|
|
76916
77068
|
const corrected = {
|
|
76917
|
-
x:
|
|
76918
|
-
y:
|
|
77069
|
+
x: roundTo3(base2.x + residual.x),
|
|
77070
|
+
y: roundTo3(base2.y + residual.y)
|
|
76919
77071
|
};
|
|
76920
77072
|
logResize("scale-finalize", {
|
|
76921
77073
|
dropPoint: scaleDraftDropPoint,
|
|
@@ -77304,8 +77456,8 @@ function useAnimatedPropertyCommit(deps) {
|
|
|
77304
77456
|
const commitAnimatedProperties = useCallback137(
|
|
77305
77457
|
// This is the single routing boundary for set, keyframe, whole-tween, and first-group writes.
|
|
77306
77458
|
// fallow-ignore-next-line complexity
|
|
77307
|
-
async (selection, props) => {
|
|
77308
|
-
if (!
|
|
77459
|
+
async (selection, props, commit = gsapCommitMutation) => {
|
|
77460
|
+
if (!commit) return;
|
|
77309
77461
|
const propEntries = Object.entries(props);
|
|
77310
77462
|
if (propEntries.length === 0) return;
|
|
77311
77463
|
const primaryProp = propEntries[0][0];
|
|
@@ -77342,7 +77494,7 @@ function useAnimatedPropertyCommit(deps) {
|
|
|
77342
77494
|
),
|
|
77343
77495
|
pct,
|
|
77344
77496
|
iframe,
|
|
77345
|
-
{ commitMutation:
|
|
77497
|
+
{ commitMutation: commit },
|
|
77346
77498
|
`Edit ${primaryProp} (whole animation)`
|
|
77347
77499
|
);
|
|
77348
77500
|
return;
|
|
@@ -77355,18 +77507,12 @@ function useAnimatedPropertyCommit(deps) {
|
|
|
77355
77507
|
primaryProp,
|
|
77356
77508
|
selector,
|
|
77357
77509
|
iframe,
|
|
77358
|
-
|
|
77510
|
+
commit
|
|
77359
77511
|
);
|
|
77360
77512
|
return;
|
|
77361
77513
|
}
|
|
77362
77514
|
if (!elementHasKeyframes) {
|
|
77363
|
-
await commitStaticSet(
|
|
77364
|
-
selection,
|
|
77365
|
-
propEntries,
|
|
77366
|
-
selector,
|
|
77367
|
-
selectedGsapAnimations,
|
|
77368
|
-
gsapCommitMutation
|
|
77369
|
-
);
|
|
77515
|
+
await commitStaticSet(selection, propEntries, selector, selectedGsapAnimations, commit);
|
|
77370
77516
|
return;
|
|
77371
77517
|
}
|
|
77372
77518
|
if (anim && isInstantHold(anim)) {
|
|
@@ -77376,7 +77522,7 @@ function useAnimatedPropertyCommit(deps) {
|
|
|
77376
77522
|
propEntries,
|
|
77377
77523
|
selector,
|
|
77378
77524
|
selectedGsapAnimations,
|
|
77379
|
-
|
|
77525
|
+
commit
|
|
77380
77526
|
);
|
|
77381
77527
|
return;
|
|
77382
77528
|
}
|
|
@@ -77392,7 +77538,7 @@ function useAnimatedPropertyCommit(deps) {
|
|
|
77392
77538
|
{ percentage: 0, properties: { ...newProps, _auto: 1 } },
|
|
77393
77539
|
{ percentage: pct, properties: newProps }
|
|
77394
77540
|
];
|
|
77395
|
-
await
|
|
77541
|
+
await commit(
|
|
77396
77542
|
selection,
|
|
77397
77543
|
{
|
|
77398
77544
|
type: "add-with-keyframes",
|
|
@@ -77421,10 +77567,6 @@ function useAnimatedPropertyCommit(deps) {
|
|
|
77421
77567
|
}
|
|
77422
77568
|
|
|
77423
77569
|
// src/hooks/useGsapAwareEditing.ts
|
|
77424
|
-
async function saveMove(outcome, saveOnElement) {
|
|
77425
|
-
if (outcome.status === "element-offset") return saveOnElement();
|
|
77426
|
-
assertGsapEditPersisted(outcome);
|
|
77427
|
-
}
|
|
77428
77570
|
var groupDragCommitCounter = 0;
|
|
77429
77571
|
function firstPreflightFailure(results, updates) {
|
|
77430
77572
|
for (const [index, result] of results.entries()) {
|
|
@@ -77445,6 +77587,7 @@ function useGsapAwareEditing({
|
|
|
77445
77587
|
trackGsapInteractionFailure,
|
|
77446
77588
|
stageElementPositionOffset,
|
|
77447
77589
|
handleDomBoxSizeCommit,
|
|
77590
|
+
commitPositionPatchToHtml,
|
|
77448
77591
|
addGsapAnimation,
|
|
77449
77592
|
convertToKeyframes,
|
|
77450
77593
|
setArcPath,
|
|
@@ -77622,6 +77765,8 @@ function useGsapAwareEditing({
|
|
|
77622
77765
|
animGroups: targetAnimations.map((a) => `${a.propertyGroup}:${a.method}`)
|
|
77623
77766
|
});
|
|
77624
77767
|
let anchorMove = null;
|
|
77768
|
+
const stageCrop = prepareCropResize(selection.element);
|
|
77769
|
+
let cropUndoKey = null;
|
|
77625
77770
|
return runGestureTransaction({
|
|
77626
77771
|
element: selection.element,
|
|
77627
77772
|
label: "Resize layer",
|
|
@@ -77648,6 +77793,7 @@ function useGsapAwareEditing({
|
|
|
77648
77793
|
makeFetchFallback(selection)
|
|
77649
77794
|
);
|
|
77650
77795
|
assertGsapEditPersisted(outcome);
|
|
77796
|
+
cropUndoKey = coalesceKey;
|
|
77651
77797
|
const ownsDragOffset = outcome.status === "persisted" && outcome.ownsDragOffset === true;
|
|
77652
77798
|
logResize("intercept-handled", {
|
|
77653
77799
|
scaleRoute,
|
|
@@ -77682,7 +77828,12 @@ function useGsapAwareEditing({
|
|
|
77682
77828
|
logResizeSettle(selection.element, "dom-route");
|
|
77683
77829
|
await handleDomBoxSizeCommit(selection, next, offset);
|
|
77684
77830
|
},
|
|
77685
|
-
afterBufferedCommitsSaved: () =>
|
|
77831
|
+
afterBufferedCommitsSaved: async () => {
|
|
77832
|
+
await anchorMove?.save();
|
|
77833
|
+
if (cropUndoKey) {
|
|
77834
|
+
await saveCropResize(stageCrop, selection, commitPositionPatchToHtml, cropUndoKey);
|
|
77835
|
+
}
|
|
77836
|
+
},
|
|
77686
77837
|
restore: () => {
|
|
77687
77838
|
anchorMove?.rollback();
|
|
77688
77839
|
restore();
|
|
@@ -77692,6 +77843,7 @@ function useGsapAwareEditing({
|
|
|
77692
77843
|
},
|
|
77693
77844
|
[
|
|
77694
77845
|
handleDomBoxSizeCommit,
|
|
77846
|
+
commitPositionPatchToHtml,
|
|
77695
77847
|
stageElementPositionOffset,
|
|
77696
77848
|
gsapCommitMutation,
|
|
77697
77849
|
previewIframeRef,
|
|
@@ -77729,10 +77881,7 @@ function useGsapAwareEditing({
|
|
|
77729
77881
|
getGsapAnimationsForSelection
|
|
77730
77882
|
]
|
|
77731
77883
|
);
|
|
77732
|
-
const {
|
|
77733
|
-
commitAnimatedProperty: commitAnimatedPropertyRaw,
|
|
77734
|
-
commitAnimatedProperties: commitAnimatedPropertiesRaw
|
|
77735
|
-
} = useAnimatedPropertyCommit({
|
|
77884
|
+
const { commitAnimatedProperties: commitAnimatedPropertiesRaw } = useAnimatedPropertyCommit({
|
|
77736
77885
|
selectedGsapAnimations,
|
|
77737
77886
|
gsapCommitMutation,
|
|
77738
77887
|
addGsapAnimation: (sel, method, time) => addGsapAnimation(sel, method, time),
|
|
@@ -77743,24 +77892,28 @@ function useGsapAwareEditing({
|
|
|
77743
77892
|
const commitAnimatedProperties = useCallback138(
|
|
77744
77893
|
async (selection, properties) => {
|
|
77745
77894
|
try {
|
|
77746
|
-
await
|
|
77895
|
+
await writeSizeWithCrop(
|
|
77896
|
+
selection,
|
|
77897
|
+
properties,
|
|
77898
|
+
gsapCommitMutation,
|
|
77899
|
+
commitPositionPatchToHtml,
|
|
77900
|
+
(keyed) => commitAnimatedPropertiesRaw(selection, properties, keyed)
|
|
77901
|
+
);
|
|
77747
77902
|
} catch (error) {
|
|
77748
77903
|
trackGsapInteractionFailure(error, selection, "property", "Edit animated property");
|
|
77749
77904
|
throw error;
|
|
77750
77905
|
}
|
|
77751
77906
|
},
|
|
77752
|
-
[
|
|
77907
|
+
[
|
|
77908
|
+
commitAnimatedPropertiesRaw,
|
|
77909
|
+
commitPositionPatchToHtml,
|
|
77910
|
+
gsapCommitMutation,
|
|
77911
|
+
trackGsapInteractionFailure
|
|
77912
|
+
]
|
|
77753
77913
|
);
|
|
77754
77914
|
const commitAnimatedProperty = useCallback138(
|
|
77755
|
-
|
|
77756
|
-
|
|
77757
|
-
await commitAnimatedPropertyRaw(selection, property, value);
|
|
77758
|
-
} catch (error) {
|
|
77759
|
-
trackGsapInteractionFailure(error, selection, "property", "Edit animated property");
|
|
77760
|
-
throw error;
|
|
77761
|
-
}
|
|
77762
|
-
},
|
|
77763
|
-
[commitAnimatedPropertyRaw, trackGsapInteractionFailure]
|
|
77915
|
+
(selection, property, value) => commitAnimatedProperties(selection, { [property]: value }),
|
|
77916
|
+
[commitAnimatedProperties]
|
|
77764
77917
|
);
|
|
77765
77918
|
const handleSetArcPath = useCallback138(
|
|
77766
77919
|
(animId, config) => {
|
|
@@ -78005,15 +78158,10 @@ function useKeyframeEaseCommits({
|
|
|
78005
78158
|
}
|
|
78006
78159
|
|
|
78007
78160
|
// src/hooks/useCommitPreflightCapabilities.ts
|
|
78008
|
-
import { useEffect as useEffect116, useMemo as
|
|
78161
|
+
import { useEffect as useEffect116, useMemo as useMemo69, useRef as useRef149, useState as useState112 } from "react";
|
|
78009
78162
|
function runCommitPreflights(selection, fileAnimations, iframe, group) {
|
|
78010
78163
|
const target = { id: selection.id ?? null, selector: selection.selector ?? null };
|
|
78011
|
-
const
|
|
78012
|
-
{ animations: fileAnimations },
|
|
78013
|
-
target,
|
|
78014
|
-
selection.element
|
|
78015
|
-
);
|
|
78016
|
-
const animations = matched.kind === "resolved" ? matched.animations : [];
|
|
78164
|
+
const animations = getAnimationsForElement(fileAnimations, target, selection.element);
|
|
78017
78165
|
return {
|
|
78018
78166
|
offset: dragEditOutcome(selection, animations, iframe, [], group),
|
|
78019
78167
|
size: preflightGsapResizeIntercept(selection, animations, iframe),
|
|
@@ -78079,7 +78227,7 @@ function useCommitPreflightCapabilities({
|
|
|
78079
78227
|
});
|
|
78080
78228
|
}
|
|
78081
78229
|
}, [enabled, projectId, selection, groupSelections, version]);
|
|
78082
|
-
return
|
|
78230
|
+
return useMemo69(() => {
|
|
78083
78231
|
void parseTick;
|
|
78084
78232
|
if (!enabled || !projectId) return { selection, groupSelections };
|
|
78085
78233
|
const group = groupSelections.length > 1;
|
|
@@ -78270,6 +78418,7 @@ function useDomEditSession({
|
|
|
78270
78418
|
handleDomAddTextField,
|
|
78271
78419
|
handleDomRemoveTextField,
|
|
78272
78420
|
stageElementPositionOffset,
|
|
78421
|
+
commitPositionPatchToHtml,
|
|
78273
78422
|
handleDomBoxSizeCommit,
|
|
78274
78423
|
handleDomManualEditsReset,
|
|
78275
78424
|
handleDomEditElementsDelete,
|
|
@@ -78500,6 +78649,7 @@ function useDomEditSession({
|
|
|
78500
78649
|
trackGsapInteractionFailure,
|
|
78501
78650
|
stageElementPositionOffset,
|
|
78502
78651
|
handleDomBoxSizeCommit,
|
|
78652
|
+
commitPositionPatchToHtml,
|
|
78503
78653
|
addGsapAnimation,
|
|
78504
78654
|
convertToKeyframes,
|
|
78505
78655
|
setArcPath,
|
|
@@ -79411,7 +79561,7 @@ function useStudioExternalFileChanges({
|
|
|
79411
79561
|
}
|
|
79412
79562
|
|
|
79413
79563
|
// src/hooks/useBlockHandlers.ts
|
|
79414
|
-
import { useCallback as useCallback144, useMemo as
|
|
79564
|
+
import { useCallback as useCallback144, useMemo as useMemo70, useRef as useRef152, useState as useState115 } from "react";
|
|
79415
79565
|
|
|
79416
79566
|
// src/utils/blockInstaller.ts
|
|
79417
79567
|
function getMaxZIndexFromIframe(iframe) {
|
|
@@ -79605,7 +79755,7 @@ function useBlockHandlers({
|
|
|
79605
79755
|
setRightPanelTab
|
|
79606
79756
|
}) {
|
|
79607
79757
|
const [activeBlockParams, setActiveBlockParams] = useState115(null);
|
|
79608
|
-
const blockCtx =
|
|
79758
|
+
const blockCtx = useMemo70(
|
|
79609
79759
|
() => ({
|
|
79610
79760
|
activeCompPath: blockCtxDeps.activeCompPath,
|
|
79611
79761
|
timelineElements: blockCtxDeps.timelineElements,
|
|
@@ -79935,7 +80085,7 @@ function dispatchPlainKey(event, key2, cb) {
|
|
|
79935
80085
|
}
|
|
79936
80086
|
|
|
79937
80087
|
// src/hooks/useEditHistoryActions.ts
|
|
79938
|
-
import { useCallback as useCallback145, useMemo as
|
|
80088
|
+
import { useCallback as useCallback145, useMemo as useMemo71 } from "react";
|
|
79939
80089
|
function useEditHistoryActions({
|
|
79940
80090
|
editHistory,
|
|
79941
80091
|
readOptionalProjectFile,
|
|
@@ -79999,7 +80149,7 @@ function useEditHistoryActions({
|
|
|
79999
80149
|
);
|
|
80000
80150
|
const undo = useCallback145(() => apply("undo"), [apply]);
|
|
80001
80151
|
const redo = useCallback145(() => apply("redo"), [apply]);
|
|
80002
|
-
return
|
|
80152
|
+
return useMemo71(() => ({ undo, redo }), [undo, redo]);
|
|
80003
80153
|
}
|
|
80004
80154
|
|
|
80005
80155
|
// src/hooks/useAppHotkeys.ts
|
|
@@ -80173,7 +80323,7 @@ function useAppHotkeys({
|
|
|
80173
80323
|
|
|
80174
80324
|
// src/hooks/useClipboard.ts
|
|
80175
80325
|
import { useCallback as useCallback147, useRef as useRef154 } from "react";
|
|
80176
|
-
import { EXCLUDED_TAGS, mintHfId, walkCompositionDescendants } from "@hyperframes/parsers/hf-ids";
|
|
80326
|
+
import { EXCLUDED_TAGS, mintHfId, walkCompositionDescendants as walkCompositionDescendants2 } from "@hyperframes/parsers/hf-ids";
|
|
80177
80327
|
|
|
80178
80328
|
// src/utils/clipboardPayload.ts
|
|
80179
80329
|
function insertAsSibling(source, newHtml, selector, selectorIndex) {
|
|
@@ -80372,7 +80522,7 @@ function remintHfIds(html2, parser, taken) {
|
|
|
80372
80522
|
return html2.replace(/\sdata-hf-id=("[^"]*"|'[^']*')/g, "");
|
|
80373
80523
|
}
|
|
80374
80524
|
const elements = [root];
|
|
80375
|
-
|
|
80525
|
+
walkCompositionDescendants2(root, (el) => elements.push(el));
|
|
80376
80526
|
for (const el of elements) {
|
|
80377
80527
|
if (EXCLUDED_TAGS.has(el.tagName.toLowerCase())) el.removeAttribute("data-hf-id");
|
|
80378
80528
|
else el.setAttribute("data-hf-id", mintHfId(el, taken));
|
|
@@ -81192,7 +81342,7 @@ function useFrameCapture({
|
|
|
81192
81342
|
}
|
|
81193
81343
|
|
|
81194
81344
|
// src/hooks/useLintModal.ts
|
|
81195
|
-
import { useState as useState118, useCallback as useCallback150, useEffect as useEffect124, useRef as useRef158, useMemo as
|
|
81345
|
+
import { useState as useState118, useCallback as useCallback150, useEffect as useEffect124, useRef as useRef158, useMemo as useMemo72 } from "react";
|
|
81196
81346
|
function parseFinding(f) {
|
|
81197
81347
|
return {
|
|
81198
81348
|
severity: f.severity === "error" ? "error" : "warning",
|
|
@@ -81265,8 +81415,8 @@ function useLintModal(projectId, refreshKey) {
|
|
|
81265
81415
|
},
|
|
81266
81416
|
[backgroundFindings]
|
|
81267
81417
|
);
|
|
81268
|
-
const findingsByElement =
|
|
81269
|
-
const findingsByFile =
|
|
81418
|
+
const findingsByElement = useMemo72(() => groupFindings((f) => f.elementId), [groupFindings]);
|
|
81419
|
+
const findingsByFile = useMemo72(() => groupFindings((f) => f.file), [groupFindings]);
|
|
81270
81420
|
const badgeFindings = lintModal ?? backgroundFindings;
|
|
81271
81421
|
const lintFindingCount = badgeFindings.length;
|
|
81272
81422
|
const hasLintError = badgeFindings.some((f) => f.severity === "error");
|
|
@@ -81731,16 +81881,16 @@ function useStudioUrlState({
|
|
|
81731
81881
|
}
|
|
81732
81882
|
|
|
81733
81883
|
// src/hooks/useEffectiveTimelineDuration.ts
|
|
81734
|
-
import { useMemo as
|
|
81884
|
+
import { useMemo as useMemo73 } from "react";
|
|
81735
81885
|
function useEffectiveTimelineDuration(timelineDuration2, timelineElements) {
|
|
81736
|
-
return
|
|
81886
|
+
return useMemo73(
|
|
81737
81887
|
() => getEffectiveTimelineDuration(timelineDuration2, timelineElements),
|
|
81738
81888
|
[timelineDuration2, timelineElements]
|
|
81739
81889
|
);
|
|
81740
81890
|
}
|
|
81741
81891
|
|
|
81742
81892
|
// src/hooks/useStudioContextValue.ts
|
|
81743
|
-
import { useCallback as useCallback153, useMemo as
|
|
81893
|
+
import { useCallback as useCallback153, useMemo as useMemo74 } from "react";
|
|
81744
81894
|
function buildStudioContextValue(input) {
|
|
81745
81895
|
return {
|
|
81746
81896
|
projectId: input.projectId,
|
|
@@ -81768,7 +81918,7 @@ function buildStudioContextValue(input) {
|
|
|
81768
81918
|
};
|
|
81769
81919
|
}
|
|
81770
81920
|
function useInspectorState(rightPanel, isPlaying, domEditSelection, isGestureRecording) {
|
|
81771
|
-
return
|
|
81921
|
+
return useMemo74(() => {
|
|
81772
81922
|
const inspectorPanelActive = rightPanel === "layers" || rightPanel === "design";
|
|
81773
81923
|
return {
|
|
81774
81924
|
inspectorPanelActive,
|
|
@@ -81811,7 +81961,7 @@ function useGlobalFileDrop(handleTimelineFileDrop) {
|
|
|
81811
81961
|
}
|
|
81812
81962
|
|
|
81813
81963
|
// src/contexts/PanelLayoutContext.tsx
|
|
81814
|
-
import { useContext as useContext13, useMemo as
|
|
81964
|
+
import { useContext as useContext13, useMemo as useMemo75 } from "react";
|
|
81815
81965
|
import { jsx as jsx188 } from "react/jsx-runtime";
|
|
81816
81966
|
var PanelLayoutContext = createStableContext("PanelLayoutContext", null);
|
|
81817
81967
|
function usePanelLayoutContext() {
|
|
@@ -81823,7 +81973,7 @@ function PanelLayoutProvider({
|
|
|
81823
81973
|
value: { rightCollapsed, setRightCollapsed, rightPanelTab, setRightPanelTab },
|
|
81824
81974
|
children
|
|
81825
81975
|
}) {
|
|
81826
|
-
const stable =
|
|
81976
|
+
const stable = useMemo75(
|
|
81827
81977
|
() => ({ rightCollapsed, setRightCollapsed, rightPanelTab, setRightPanelTab }),
|
|
81828
81978
|
[rightCollapsed, setRightCollapsed, rightPanelTab, setRightPanelTab]
|
|
81829
81979
|
);
|
|
@@ -82766,7 +82916,7 @@ function useGestureCommit({
|
|
|
82766
82916
|
}
|
|
82767
82917
|
|
|
82768
82918
|
// src/components/editor/GestureTrailOverlay.tsx
|
|
82769
|
-
import { memo as memo40, useMemo as
|
|
82919
|
+
import { memo as memo40, useMemo as useMemo76 } from "react";
|
|
82770
82920
|
import { Fragment as Fragment53, jsx as jsx191, jsxs as jsxs150 } from "react/jsx-runtime";
|
|
82771
82921
|
var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
|
|
82772
82922
|
samples,
|
|
@@ -82778,7 +82928,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
|
|
|
82778
82928
|
mode,
|
|
82779
82929
|
accentColor = "#3CE6AC"
|
|
82780
82930
|
}) {
|
|
82781
|
-
const trailPoints =
|
|
82931
|
+
const trailPoints = useMemo76(() => {
|
|
82782
82932
|
if (!canvasRect) return "";
|
|
82783
82933
|
if (trail2 && trail2.length > 1) {
|
|
82784
82934
|
return trail2.map((p) => `${p.x - canvasRect.left},${p.y - canvasRect.top}`).join(" ");
|
|
@@ -82786,7 +82936,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
|
|
|
82786
82936
|
if (samples.length === 0) return "";
|
|
82787
82937
|
return samples.filter((s) => s.properties.x != null && s.properties.y != null).map((s) => `${s.properties.x},${s.properties.y}`).join(" ");
|
|
82788
82938
|
}, [samples, trail2, sampleCount, canvasRect?.left, canvasRect?.top]);
|
|
82789
|
-
const simplifiedPath =
|
|
82939
|
+
const simplifiedPath = useMemo76(() => {
|
|
82790
82940
|
if (!simplifiedPoints || simplifiedPoints.size === 0) return "";
|
|
82791
82941
|
const pts = [];
|
|
82792
82942
|
for (const [pct, props] of simplifiedPoints) {
|
|
@@ -82798,7 +82948,7 @@ var GestureTrailOverlay = memo40(function GestureTrailOverlay2({
|
|
|
82798
82948
|
if (pts.length === 0) return "";
|
|
82799
82949
|
return pts.map((p) => `${p.x},${p.y}`).join(" ");
|
|
82800
82950
|
}, [simplifiedPoints]);
|
|
82801
|
-
const diamondPositions =
|
|
82951
|
+
const diamondPositions = useMemo76(() => {
|
|
82802
82952
|
if (!simplifiedPoints || simplifiedPoints.size === 0) return [];
|
|
82803
82953
|
const pts = [];
|
|
82804
82954
|
for (const [pct, props] of simplifiedPoints) {
|
|
@@ -82997,7 +83147,7 @@ function MediaPreview({ projectId, filePath }) {
|
|
|
82997
83147
|
}
|
|
82998
83148
|
|
|
82999
83149
|
// src/components/sidebar/AssetsTab.tsx
|
|
83000
|
-
import { memo as memo41, useState as useState129, useCallback as useCallback159, useRef as useRef166, useMemo as
|
|
83150
|
+
import { memo as memo41, useState as useState129, useCallback as useCallback159, useRef as useRef166, useMemo as useMemo78, useEffect as useEffect133 } from "react";
|
|
83001
83151
|
|
|
83002
83152
|
// src/components/ui/SearchInput.tsx
|
|
83003
83153
|
import { jsx as jsx193, jsxs as jsxs152 } from "react/jsx-runtime";
|
|
@@ -83609,7 +83759,7 @@ function AudioRow({
|
|
|
83609
83759
|
}
|
|
83610
83760
|
|
|
83611
83761
|
// src/components/sidebar/GlobalAssetsView.tsx
|
|
83612
|
-
import { useEffect as useEffect130, useMemo as
|
|
83762
|
+
import { useEffect as useEffect130, useMemo as useMemo77, useState as useState126 } from "react";
|
|
83613
83763
|
import { jsx as jsx196, jsxs as jsxs155 } from "react/jsx-runtime";
|
|
83614
83764
|
function globalAssetRows(records, query = "") {
|
|
83615
83765
|
const q = query.trim().toLowerCase();
|
|
@@ -83636,7 +83786,7 @@ function GlobalAssetsView({ searchQuery }) {
|
|
|
83636
83786
|
cancelled = true;
|
|
83637
83787
|
};
|
|
83638
83788
|
}, []);
|
|
83639
|
-
const rows =
|
|
83789
|
+
const rows = useMemo77(() => globalAssetRows(records ?? [], searchQuery), [records, searchQuery]);
|
|
83640
83790
|
if (records === null) {
|
|
83641
83791
|
return /* @__PURE__ */ jsx196("p", { className: "px-4 py-3 text-[11px] text-panel-text-5", children: "Loading global assets\u2026" });
|
|
83642
83792
|
}
|
|
@@ -84198,12 +84348,12 @@ var AssetsTab = memo41(function AssetsTab2({
|
|
|
84198
84348
|
setTimeout(() => setCopyFeedback(null), copied ? 1500 : 3e3);
|
|
84199
84349
|
}, []);
|
|
84200
84350
|
const elements = usePlayerStore((s) => s.elements);
|
|
84201
|
-
const usedPaths =
|
|
84202
|
-
const allMediaAssets =
|
|
84351
|
+
const usedPaths = useMemo78(() => deriveUsedPaths(elements), [elements]);
|
|
84352
|
+
const allMediaAssets = useMemo78(
|
|
84203
84353
|
() => assets.filter((a) => MEDIA_EXT.test(a) || FONT_EXT.test(a)),
|
|
84204
84354
|
[assets]
|
|
84205
84355
|
);
|
|
84206
|
-
const mediaAssets =
|
|
84356
|
+
const mediaAssets = useMemo78(() => {
|
|
84207
84357
|
const all = filterByUsage(allMediaAssets, usedPaths, usageFilter);
|
|
84208
84358
|
if (!searchQuery) return all;
|
|
84209
84359
|
const q = searchQuery.toLowerCase();
|
|
@@ -84213,7 +84363,7 @@ var AssetsTab = memo41(function AssetsTab2({
|
|
|
84213
84363
|
return rec?.description?.toLowerCase().includes(q);
|
|
84214
84364
|
});
|
|
84215
84365
|
}, [allMediaAssets, searchQuery, manifest, usageFilter, usedPaths]);
|
|
84216
|
-
const categorized =
|
|
84366
|
+
const categorized = useMemo78(() => {
|
|
84217
84367
|
const groups = { audio: [], images: [], video: [], fonts: [] };
|
|
84218
84368
|
for (const a of mediaAssets) {
|
|
84219
84369
|
const cat = getCategory(a);
|
|
@@ -84228,12 +84378,12 @@ var AssetsTab = memo41(function AssetsTab2({
|
|
|
84228
84378
|
}
|
|
84229
84379
|
return groups;
|
|
84230
84380
|
}, [mediaAssets, usedPaths]);
|
|
84231
|
-
const counts =
|
|
84381
|
+
const counts = useMemo78(() => {
|
|
84232
84382
|
const c = { all: mediaAssets.length };
|
|
84233
84383
|
for (const cat of FILTER_ORDER) c[cat] = categorized[cat].length;
|
|
84234
84384
|
return c;
|
|
84235
84385
|
}, [mediaAssets, categorized]);
|
|
84236
|
-
const usageCounts =
|
|
84386
|
+
const usageCounts = useMemo78(
|
|
84237
84387
|
() => countUsage(
|
|
84238
84388
|
assets.filter((a) => MEDIA_EXT.test(a) || FONT_EXT.test(a)),
|
|
84239
84389
|
usedPaths
|
|
@@ -88614,7 +88764,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
88614
88764
|
}
|
|
88615
88765
|
|
|
88616
88766
|
// src/components/panels/VariablesPanel.tsx
|
|
88617
|
-
import { memo as memo52, useCallback as useCallback175, useEffect as useEffect144, useMemo as
|
|
88767
|
+
import { memo as memo52, useCallback as useCallback175, useEffect as useEffect144, useMemo as useMemo79, useState as useState146 } from "react";
|
|
88618
88768
|
|
|
88619
88769
|
// src/hooks/useVariablesPersist.ts
|
|
88620
88770
|
import { useCallback as useCallback172 } from "react";
|
|
@@ -89310,22 +89460,22 @@ var VariablesPanel = memo52(function VariablesPanel2({
|
|
|
89310
89460
|
reloadPreview,
|
|
89311
89461
|
publishSdkSession
|
|
89312
89462
|
});
|
|
89313
|
-
const declarations =
|
|
89463
|
+
const declarations = useMemo79(
|
|
89314
89464
|
() => sdkSession?.getVariableDeclarations() ?? [],
|
|
89315
89465
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89316
89466
|
[sdkSession, refreshKey, revision]
|
|
89317
89467
|
);
|
|
89318
|
-
const usage =
|
|
89468
|
+
const usage = useMemo79(
|
|
89319
89469
|
() => sdkSession?.getVariableUsage() ?? null,
|
|
89320
89470
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89321
89471
|
[sdkSession, refreshKey, revision]
|
|
89322
89472
|
);
|
|
89323
|
-
const issues =
|
|
89473
|
+
const issues = useMemo79(
|
|
89324
89474
|
() => previewValues && sdkSession ? sdkSession.validateVariableValues(previewValues) : [],
|
|
89325
89475
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89326
89476
|
[sdkSession, previewValues, refreshKey, revision]
|
|
89327
89477
|
);
|
|
89328
|
-
const effectiveValues =
|
|
89478
|
+
const effectiveValues = useMemo79(
|
|
89329
89479
|
() => sdkSession?.getVariableValues(previewValues ?? void 0) ?? {},
|
|
89330
89480
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
89331
89481
|
[sdkSession, previewValues, refreshKey, revision]
|
|
@@ -89640,15 +89790,15 @@ function useSlideshowPersist({
|
|
|
89640
89790
|
}
|
|
89641
89791
|
|
|
89642
89792
|
// src/hooks/useSlideshowTabState.ts
|
|
89643
|
-
import { useMemo as
|
|
89793
|
+
import { useMemo as useMemo80 } from "react";
|
|
89644
89794
|
import { SLIDESHOW_ISLAND_TYPE as SLIDESHOW_ISLAND_TYPE2, slideshowIslandRegex as slideshowIslandRegex2 } from "@hyperframes/core/slideshow";
|
|
89645
89795
|
function useSlideshowTabState(params) {
|
|
89646
89796
|
const { editingFileContent, previewIframeRef, refreshKey, slideshowVisible } = params;
|
|
89647
|
-
const isSlideshowComposition =
|
|
89797
|
+
const isSlideshowComposition = useMemo80(() => {
|
|
89648
89798
|
if (!editingFileContent || !editingFileContent.includes(SLIDESHOW_ISLAND_TYPE2)) return false;
|
|
89649
89799
|
return slideshowIslandRegex2("i").test(editingFileContent);
|
|
89650
89800
|
}, [editingFileContent]);
|
|
89651
|
-
const slideshowScenes =
|
|
89801
|
+
const slideshowScenes = useMemo80(() => {
|
|
89652
89802
|
try {
|
|
89653
89803
|
const win = previewIframeRef.current?.contentWindow;
|
|
89654
89804
|
return (win?.__clipManifest?.scenes ?? []).map((s) => ({
|
|
@@ -91501,7 +91651,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
|
|
|
91501
91651
|
recordEdit: editHistory.recordEdit,
|
|
91502
91652
|
setRefreshKey
|
|
91503
91653
|
});
|
|
91504
|
-
const masterCompPath =
|
|
91654
|
+
const masterCompPath = useMemo81(
|
|
91505
91655
|
() => resolveMasterCompositionPath(fileManager.compositions),
|
|
91506
91656
|
[fileManager.compositions]
|
|
91507
91657
|
);
|
|
@@ -91605,7 +91755,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
|
|
|
91605
91755
|
});
|
|
91606
91756
|
const dismissBlockParams = useCallback185(() => setActiveBlockParams(null), [setActiveBlockParams]);
|
|
91607
91757
|
const setRightPanelTab = useDismissingTabSetter(panelLayout.setRightPanelTab, dismissBlockParams);
|
|
91608
|
-
const layout =
|
|
91758
|
+
const layout = useMemo81(
|
|
91609
91759
|
() => ({ ...panelLayout, setRightPanelTab }),
|
|
91610
91760
|
[panelLayout, setRightPanelTab]
|
|
91611
91761
|
);
|
|
@@ -91823,7 +91973,7 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
|
|
|
91823
91973
|
handlePreviewIframeRef,
|
|
91824
91974
|
refreshPreviewDocumentVersion
|
|
91825
91975
|
});
|
|
91826
|
-
const timelineToolbar =
|
|
91976
|
+
const timelineToolbar = useMemo81(
|
|
91827
91977
|
() => /* @__PURE__ */ jsx229(
|
|
91828
91978
|
TimelineToolbar,
|
|
91829
91979
|
{
|
|
@@ -92340,7 +92490,7 @@ function findElementBlock(html2, elementId2) {
|
|
|
92340
92490
|
}
|
|
92341
92491
|
|
|
92342
92492
|
// src/hooks/useDomStyleCommit.ts
|
|
92343
|
-
import { useCallback as useCallback187, useMemo as
|
|
92493
|
+
import { useCallback as useCallback187, useMemo as useMemo82, useRef as useRef183, useState as useState151 } from "react";
|
|
92344
92494
|
var noop = () => {
|
|
92345
92495
|
};
|
|
92346
92496
|
function useDomStyleCommit({
|
|
@@ -92356,7 +92506,7 @@ function useDomStyleCommit({
|
|
|
92356
92506
|
const [queue2] = useState151(createDomEditSaveQueue);
|
|
92357
92507
|
useMountEffect(() => () => queue2.destroy());
|
|
92358
92508
|
const versions = useRef183(/* @__PURE__ */ new Map()).current;
|
|
92359
|
-
const editHistory =
|
|
92509
|
+
const editHistory = useMemo82(() => ({ recordEdit }), [recordEdit]);
|
|
92360
92510
|
const persistDomEditOperations = useDomEditPersist({
|
|
92361
92511
|
activeCompPath,
|
|
92362
92512
|
previewIframeRef: iframeRef,
|
|
@@ -92388,7 +92538,7 @@ function useDomStyleCommit({
|
|
|
92388
92538
|
}
|
|
92389
92539
|
|
|
92390
92540
|
// src/hooks/useDomGeometryCommit.ts
|
|
92391
|
-
import { useCallback as useCallback188, useMemo as
|
|
92541
|
+
import { useCallback as useCallback188, useMemo as useMemo83, useRef as useRef184, useState as useState152 } from "react";
|
|
92392
92542
|
var noop2 = () => {
|
|
92393
92543
|
};
|
|
92394
92544
|
var NO_SELECTED_ANIMATIONS = [];
|
|
@@ -92405,7 +92555,7 @@ function useDomGeometryCommit({
|
|
|
92405
92555
|
const projectIdRef = useRef184(projectId);
|
|
92406
92556
|
projectIdRef.current = projectId;
|
|
92407
92557
|
const pending2 = useRef184(/* @__PURE__ */ new Set()).current;
|
|
92408
|
-
const editHistory =
|
|
92558
|
+
const editHistory = useMemo83(() => ({ recordEdit }), [recordEdit]);
|
|
92409
92559
|
const reload = useCallback188(
|
|
92410
92560
|
() => reloadPreview ? reloadPreview() : iframeRef.current?.contentWindow?.location.reload(),
|
|
92411
92561
|
[reloadPreview, iframeRef]
|
|
@@ -92473,6 +92623,7 @@ function useDomGeometryCommit({
|
|
|
92473
92623
|
trackGsapInteractionFailure,
|
|
92474
92624
|
stageElementPositionOffset,
|
|
92475
92625
|
handleDomBoxSizeCommit: noDomBoxSizeRoute,
|
|
92626
|
+
commitPositionPatchToHtml: commitWithFreshQueue,
|
|
92476
92627
|
addGsapAnimation: gsap3.addGsapAnimation,
|
|
92477
92628
|
convertToKeyframes: gsap3.convertToKeyframes,
|
|
92478
92629
|
setArcPath: gsap3.setArcPath,
|
|
@@ -92497,7 +92648,7 @@ function useDomGeometryCommit({
|
|
|
92497
92648
|
},
|
|
92498
92649
|
[pending2, showToast]
|
|
92499
92650
|
);
|
|
92500
|
-
return
|
|
92651
|
+
return useMemo83(
|
|
92501
92652
|
() => ({
|
|
92502
92653
|
commitPathOffset: (selection, next, modifiers) => saved2(() => handleGsapAwarePathOffsetCommit(selection, next, modifiers)),
|
|
92503
92654
|
commitGroupPathOffset: (updates) => saved2(() => handleGsapAwareGroupPathOffsetCommit(updates)),
|