@hyperframes/studio 0.8.33 → 0.8.35
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-CNhkujVy.js → hyperframes-player-lPOqAC3l.js} +1 -1
- package/dist/assets/{index-DOoo96Tb.js → index-BRr1JoHX.js} +182 -172
- package/dist/assets/{index-CslAQ3JV.js → index-RPEcu_bT.js} +1 -1
- package/dist/assets/{index-DiStlnx7.js → index-ywAULfGT.js} +1 -1
- package/dist/{chunk-A7S5SGNA.js → chunk-7BP32G62.js} +294 -53
- package/dist/chunk-7BP32G62.js.map +1 -0
- package/dist/{domEditingLayers-JMMVOGTO.js → domEditingLayers-UKMVYXT6.js} +2 -2
- package/dist/index.html +1 -1
- package/dist/index.js +369 -220
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/src/App.tsx +6 -4
- package/src/captions/components/CaptionOverlay.sender.test.tsx +47 -0
- package/src/captions/components/CaptionOverlay.tsx +1 -0
- package/src/captions/generator.test.ts +30 -0
- package/src/captions/generator.ts +5 -3
- package/src/captions/hooks/useCaptionSync.ts +3 -2
- package/src/components/MediaPreview.tsx +2 -1
- package/src/components/editor/AnimationCard.test.tsx +3 -3
- package/src/components/editor/PropertyPanel.test.tsx +18 -14
- package/src/components/editor/SnapGuideOverlay.tsx +2 -6
- package/src/components/editor/domEditLayerWalkCache.test.ts +284 -0
- package/src/components/editor/domEditLayerWalkCache.ts +327 -0
- package/src/components/editor/domEditOverlayBasis.ts +72 -0
- package/src/components/editor/domEditOverlayGeometry.ts +78 -83
- package/src/components/editor/domEditOverlayMeasurePass.ts +60 -0
- package/src/components/editor/domEditOverlayTransform.ts +47 -9
- package/src/components/editor/domEditingDom.ts +63 -14
- package/src/components/editor/domEditingElement.ts +56 -14
- package/src/components/editor/domEditingLayers.test.ts +48 -0
- package/src/components/editor/domEditingLayers.ts +22 -35
- package/src/components/editor/offCanvasIndicatorGeometry.complexity.test.ts +373 -0
- package/src/components/editor/offCanvasIndicatorGeometry.ts +50 -11
- package/src/components/editor/offCanvasIndicatorRefresh.ts +43 -16
- package/src/components/editor/overlayFrameLoop.test.ts +246 -0
- package/src/components/editor/overlayFrameLoop.ts +204 -0
- package/src/components/editor/probeSourceElement.ts +29 -0
- package/src/components/editor/propertyPanelFill.tsx +2 -1
- package/src/components/editor/propertyPanelFlatEffectsSection.test.tsx +2 -2
- package/src/components/editor/useDomEditCompositionRect.ts +2 -4
- package/src/components/editor/useDomEditOverlayRects.ts +15 -9
- package/src/components/editor/useMotionPathData.ts +2 -4
- package/src/components/feedback/projectProvenance.ts +4 -1
- package/src/components/nle/NLEContext.tsx +2 -1
- package/src/components/nle/PreviewOverlays.tsx +1 -1
- package/src/components/nle/useCompositionStack.ts +11 -4
- package/src/components/renders/RenderQueue.test.tsx +2 -2
- package/src/components/renders/RenderQueueItem.tsx +2 -1
- package/src/components/renders/useRenderQueue.ts +3 -2
- package/src/components/sidebar/AssetsTab.tsx +2 -1
- package/src/components/sidebar/CompositionsTab.tsx +2 -1
- package/src/components/storyboard/FramePoster.tsx +2 -1
- package/src/hooks/useAskAgentModal.ts +2 -1
- package/src/hooks/useCaptionDetection.sender.test.tsx +54 -0
- package/src/hooks/useCaptionDetection.ts +3 -1
- package/src/hooks/useCompositionContentLoader.ts +3 -1
- package/src/hooks/useCompositionDimensions.test.tsx +47 -0
- package/src/hooks/useCompositionDimensions.ts +3 -2
- package/src/hooks/useDomEditCommits.ts +5 -4
- package/src/hooks/useElementLifecycleOps.ts +5 -1
- package/src/hooks/useFileTree.ts +5 -4
- package/src/hooks/useGroupCommits.ts +2 -1
- package/src/hooks/useGsapInteractionFailureTelemetry.test.tsx +2 -2
- package/src/hooks/useLintModal.ts +2 -1
- package/src/hooks/useRenderClipContent.ts +6 -5
- package/src/hooks/useTimelineDeleteOps.ts +5 -1
- package/src/player/components/Player.tsx +6 -4
- package/src/player/components/TimelineAutomationLane.test.tsx +9 -9
- package/src/player/components/thumbnailUtils.ts +6 -2
- package/src/player/components/timelineDragDrop.test.tsx +3 -3
- package/src/player/lib/timelineIframeHelpers.test.ts +36 -0
- package/src/player/lib/timelineIframeHelpers.ts +17 -1
- package/src/test-setup.ts +8 -0
- package/src/utils/blockInstaller.ts +2 -1
- package/src/utils/projectRouting.test.ts +9 -0
- package/src/utils/projectRouting.ts +18 -1
- package/src/utils/razorSplitTransaction.test.ts +3 -3
- package/src/utils/sourceScopedSelectorIndex.test.ts +148 -0
- package/src/utils/sourceScopedSelectorIndex.ts +64 -6
- package/src/utils/studioFileHistory.ts +2 -1
- package/src/utils/studioHelpers.test.ts +5 -1
- package/src/utils/studioHelpers.ts +3 -2
- package/src/utils/timelineCompositionInsert.test.ts +3 -3
- package/src/webmcp/types.ts +5 -1
- package/src/webmcp/useStudioAgentTools.polyfill.test.tsx +219 -0
- package/src/webmcp/useStudioAgentTools.test.tsx +81 -67
- package/src/webmcp/useStudioAgentTools.ts +49 -28
- package/src/webmcp/webmcpTestUtils.ts +56 -0
- package/dist/chunk-A7S5SGNA.js.map +0 -1
- /package/dist/{domEditingLayers-JMMVOGTO.js.map → domEditingLayers-UKMVYXT6.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DOM_EDIT_LAYER_OBSERVER_INIT,
|
|
2
3
|
buildDefaultDomEditTextField,
|
|
3
4
|
buildDomEditPatchTarget,
|
|
4
5
|
buildDomEditRichTextPatchOperation,
|
|
5
6
|
buildDomEditStylePatchOperation,
|
|
6
7
|
buildDomEditTextPatchOperation,
|
|
8
|
+
buildProjectApiPath,
|
|
9
|
+
buildProjectHash,
|
|
7
10
|
buildStableSelector,
|
|
8
11
|
buildTextFieldChildLocator,
|
|
9
12
|
collectDomEditLayerItems,
|
|
13
|
+
createDomEditLayerWalkCache,
|
|
10
14
|
domEditSelectionToFacts,
|
|
15
|
+
drainPendingLayerMutations,
|
|
11
16
|
escapeCssString,
|
|
12
17
|
findElementForSelection,
|
|
13
18
|
findElementForTimelineElement,
|
|
@@ -20,12 +25,14 @@ import {
|
|
|
20
25
|
isElementVisibleThroughAncestors,
|
|
21
26
|
isHtmlElement,
|
|
22
27
|
isTextEditableSelection,
|
|
28
|
+
parseProjectHashRoute,
|
|
29
|
+
parseProjectIdFromHash,
|
|
23
30
|
readHfId,
|
|
24
31
|
resolveAllVisualDomEditTargets,
|
|
25
32
|
resolveDomEditSelection,
|
|
26
33
|
serializeDomEditTextFields,
|
|
27
34
|
setCompositionSourceMap
|
|
28
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-7BP32G62.js";
|
|
29
36
|
import {
|
|
30
37
|
__export
|
|
31
38
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -532,15 +539,14 @@ var Player = forwardRef2(
|
|
|
532
539
|
useMountEffect(() => {
|
|
533
540
|
const container = containerRef.current;
|
|
534
541
|
if (!container) return;
|
|
542
|
+
const previewSource = directUrl || (projectId ? buildProjectApiPath(projectId, "/preview") : null);
|
|
543
|
+
if (!previewSource) return;
|
|
535
544
|
let canceled = false;
|
|
536
545
|
let cleanup;
|
|
537
546
|
import("@hyperframes/player").then(() => {
|
|
538
547
|
if (canceled) return;
|
|
539
548
|
const player = document.createElement("hyperframes-player");
|
|
540
|
-
const srcUrl = new URL(
|
|
541
|
-
directUrl || `/api/projects/${projectId}/preview`,
|
|
542
|
-
window.location.origin
|
|
543
|
-
);
|
|
549
|
+
const srcUrl = new URL(previewSource, window.location.origin);
|
|
544
550
|
applyPreviewVariablesToUrl(srcUrl);
|
|
545
551
|
const src = srcUrl.pathname + srcUrl.search;
|
|
546
552
|
const retryPreview = () => {
|
|
@@ -3764,10 +3770,13 @@ var scrubAudioEl = null;
|
|
|
3764
3770
|
var scrubStopTimer = null;
|
|
3765
3771
|
var scrubPrevMuted = null;
|
|
3766
3772
|
var scrubPrevVolume = null;
|
|
3773
|
+
function isAudioNode(node) {
|
|
3774
|
+
return node !== null && node.namespaceURI === "http://www.w3.org/1999/xhtml" && node.localName === "audio";
|
|
3775
|
+
}
|
|
3767
3776
|
function resolveScrubAudioEl(doc, musicId) {
|
|
3768
3777
|
if (musicId) {
|
|
3769
3778
|
const byId = doc.getElementById(musicId);
|
|
3770
|
-
if (byId
|
|
3779
|
+
if (isAudioNode(byId)) return byId;
|
|
3771
3780
|
}
|
|
3772
3781
|
return doc.querySelector("audio[data-timeline-role='music']") ?? doc.querySelector("audio");
|
|
3773
3782
|
}
|
|
@@ -13093,7 +13102,7 @@ async function resolveDroppedAssetDuration(projectId, assetPath, kind) {
|
|
|
13093
13102
|
if (kind === "image") return DEFAULT_TIMELINE_ASSET_DURATION.image;
|
|
13094
13103
|
const media = document.createElement(kind === "video" ? "video" : "audio");
|
|
13095
13104
|
media.preload = "metadata";
|
|
13096
|
-
media.src = `/
|
|
13105
|
+
media.src = buildProjectApiPath(projectId, `/preview/${assetPath}`);
|
|
13097
13106
|
const duration = await new Promise((resolve) => {
|
|
13098
13107
|
const timeout = window.setTimeout(() => resolve(DEFAULT_TIMELINE_ASSET_DURATION[kind]), 3e3);
|
|
13099
13108
|
const finalize = (value) => {
|
|
@@ -16401,7 +16410,7 @@ async function retryStudioSave(operation, options = {}) {
|
|
|
16401
16410
|
|
|
16402
16411
|
// src/utils/studioFileHistory.ts
|
|
16403
16412
|
async function readProjectFileContent(pid, path) {
|
|
16404
|
-
const response = await fetch(`/
|
|
16413
|
+
const response = await fetch(buildProjectApiPath(pid, `/files/${encodeURIComponent(path)}`));
|
|
16405
16414
|
if (!response.ok) {
|
|
16406
16415
|
throw await createStudioSaveHttpError(response, `Failed to read ${path}`);
|
|
16407
16416
|
}
|
|
@@ -24058,7 +24067,7 @@ function resolveMediaPreviewUrl(src, projectId, studioOrigin) {
|
|
|
24058
24067
|
return src;
|
|
24059
24068
|
}
|
|
24060
24069
|
if (!studioOrigin || parsed.origin !== studioOrigin) return src;
|
|
24061
|
-
const previewPath = new URL(`/
|
|
24070
|
+
const previewPath = new URL(buildProjectApiPath(projectId, `/preview/`), studioOrigin).pathname;
|
|
24062
24071
|
if (parsed.pathname.startsWith(previewPath)) return src;
|
|
24063
24072
|
if (parsed.pathname.startsWith("/api/")) return src;
|
|
24064
24073
|
try {
|
|
@@ -24068,7 +24077,10 @@ function resolveMediaPreviewUrl(src, projectId, studioOrigin) {
|
|
|
24068
24077
|
}
|
|
24069
24078
|
suffix = `${parsed.search}${parsed.hash}`;
|
|
24070
24079
|
}
|
|
24071
|
-
return
|
|
24080
|
+
return buildProjectApiPath(
|
|
24081
|
+
projectId,
|
|
24082
|
+
`/preview/${encodePreviewPath(relativePath.replace(/^\/+/, ""))}${suffix}`
|
|
24083
|
+
);
|
|
24072
24084
|
}
|
|
24073
24085
|
|
|
24074
24086
|
// src/player/components/VideoThumbnail.tsx
|
|
@@ -26679,7 +26691,7 @@ function useCompositionStack({
|
|
|
26679
26691
|
{
|
|
26680
26692
|
id: "master",
|
|
26681
26693
|
label: "Master",
|
|
26682
|
-
previewUrl: `/
|
|
26694
|
+
previewUrl: buildProjectApiPath(projectId, `/preview`)
|
|
26683
26695
|
}
|
|
26684
26696
|
]);
|
|
26685
26697
|
const onCompositionChangeRef = useRef47(onCompositionChange);
|
|
@@ -26725,7 +26737,10 @@ function useCompositionStack({
|
|
|
26725
26737
|
return prev.slice(0, -1);
|
|
26726
26738
|
}
|
|
26727
26739
|
const label = resolvedPath.split("/").pop()?.replace(/\.html$/, "") || resolvedPath;
|
|
26728
|
-
const previewUrl =
|
|
26740
|
+
const previewUrl = buildProjectApiPath(
|
|
26741
|
+
projectId,
|
|
26742
|
+
`/preview/comp/${encodePreviewPath(resolvedPath)}`
|
|
26743
|
+
);
|
|
26729
26744
|
return [...prev, { id: resolvedPath, label, previewUrl }];
|
|
26730
26745
|
});
|
|
26731
26746
|
},
|
|
@@ -26736,14 +26751,17 @@ function useCompositionStack({
|
|
|
26736
26751
|
const master = {
|
|
26737
26752
|
id: "master",
|
|
26738
26753
|
label: "Master",
|
|
26739
|
-
previewUrl: `/
|
|
26754
|
+
previewUrl: buildProjectApiPath(projectId, `/preview`)
|
|
26740
26755
|
};
|
|
26741
26756
|
if (activeCompositionPath === "index.html") {
|
|
26742
26757
|
usePlayerStore.getState().setElements([]);
|
|
26743
26758
|
updateCompositionStack([master]);
|
|
26744
26759
|
} else if (activeCompositionPath) {
|
|
26745
26760
|
const label = activeCompositionPath.replace(/^compositions\//, "").replace(/\.html$/, "");
|
|
26746
|
-
const previewUrl =
|
|
26761
|
+
const previewUrl = buildProjectApiPath(
|
|
26762
|
+
projectId,
|
|
26763
|
+
`/preview/comp/${encodePreviewPath(activeCompositionPath)}`
|
|
26764
|
+
);
|
|
26747
26765
|
usePlayerStore.getState().setElements([]);
|
|
26748
26766
|
updateCompositionStack((prev) => {
|
|
26749
26767
|
if (prev[prev.length - 1]?.id === activeCompositionPath) return prev;
|
|
@@ -26923,7 +26941,7 @@ function NLEProvider({
|
|
|
26923
26941
|
setCompIdToSrc(emptyMap);
|
|
26924
26942
|
setCompositionSourceMap(emptyMap);
|
|
26925
26943
|
onCompIdToSrcChangeRef.current?.(emptyMap);
|
|
26926
|
-
fetch(`/
|
|
26944
|
+
fetch(buildProjectApiPath(projectId, `/files/index.html`), {
|
|
26927
26945
|
signal: controller.signal
|
|
26928
26946
|
}).then((r) => {
|
|
26929
26947
|
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
|
@@ -27865,6 +27883,7 @@ var CaptionOverlay = memo20(function CaptionOverlay2({ iframeRef }) {
|
|
|
27865
27883
|
};
|
|
27866
27884
|
const unsubPlayer = usePlayerStore.subscribe(scheduleTick);
|
|
27867
27885
|
const handleMessage = (e) => {
|
|
27886
|
+
if (!e.source || e.source !== iframeRef.current?.contentWindow) return;
|
|
27868
27887
|
const data = e.data;
|
|
27869
27888
|
if (data?.source === "hf-preview") scheduleTick();
|
|
27870
27889
|
};
|
|
@@ -28570,6 +28589,36 @@ function buildAgentContextPreview(selection, activeCompPath) {
|
|
|
28570
28589
|
].filter(Boolean).join("\n");
|
|
28571
28590
|
}
|
|
28572
28591
|
|
|
28592
|
+
// src/components/editor/domEditOverlayBasis.ts
|
|
28593
|
+
function readPositiveDimension(value) {
|
|
28594
|
+
if (!value) return null;
|
|
28595
|
+
const parsed = Number.parseFloat(value);
|
|
28596
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
|
28597
|
+
}
|
|
28598
|
+
function findOverlayRootElement(doc) {
|
|
28599
|
+
return doc?.querySelector("[data-composition-id]") ?? doc?.documentElement ?? null;
|
|
28600
|
+
}
|
|
28601
|
+
function resolveRootDimensions(root) {
|
|
28602
|
+
if (!root) return null;
|
|
28603
|
+
const rootRect = root.getBoundingClientRect();
|
|
28604
|
+
const width = readPositiveDimension(root.getAttribute("data-width")) ?? rootRect.width;
|
|
28605
|
+
const height = readPositiveDimension(root.getAttribute("data-height")) ?? rootRect.height;
|
|
28606
|
+
if (!width || !height) return null;
|
|
28607
|
+
return { width, height };
|
|
28608
|
+
}
|
|
28609
|
+
function computeOverlayRootScale(overlayEl, iframe, doc) {
|
|
28610
|
+
const iframeRect = iframe.getBoundingClientRect();
|
|
28611
|
+
const overlayRect = overlayEl.getBoundingClientRect();
|
|
28612
|
+
const dims = resolveRootDimensions(findOverlayRootElement(doc));
|
|
28613
|
+
if (!dims) return null;
|
|
28614
|
+
return {
|
|
28615
|
+
iframeRect,
|
|
28616
|
+
overlayRect,
|
|
28617
|
+
rootScaleX: iframeRect.width / dims.width,
|
|
28618
|
+
rootScaleY: iframeRect.height / dims.height
|
|
28619
|
+
};
|
|
28620
|
+
}
|
|
28621
|
+
|
|
28573
28622
|
// src/components/editor/domEditOverlayTransform.ts
|
|
28574
28623
|
var COMPOSITION_ROOT_ATTR = "data-composition-id";
|
|
28575
28624
|
function individualRotateDegrees(value) {
|
|
@@ -28587,19 +28636,33 @@ function individualRotateDegrees(value) {
|
|
|
28587
28636
|
const deg = Number.parseFloat(angle);
|
|
28588
28637
|
return Number.isFinite(deg) ? deg : 0;
|
|
28589
28638
|
}
|
|
28590
|
-
function
|
|
28591
|
-
|
|
28639
|
+
function ownNodeTransform(node, ops, getStyle) {
|
|
28640
|
+
const style = getStyle(node);
|
|
28641
|
+
if (!style) return null;
|
|
28642
|
+
const transform = style.transform;
|
|
28643
|
+
const own = transform && transform !== "none" ? ops.fromTransform(transform) : ops.identity();
|
|
28644
|
+
if (!own) return null;
|
|
28645
|
+
const spin = individualRotateDegrees(style.rotate);
|
|
28646
|
+
return spin === 0 ? own : ops.compose(ops.fromRotate(spin), own);
|
|
28647
|
+
}
|
|
28648
|
+
function composeElementTransform(element, ops, getStyle, memo52) {
|
|
28649
|
+
const pending2 = [];
|
|
28650
|
+
let above;
|
|
28592
28651
|
for (let node = element; node; node = node.parentElement) {
|
|
28593
|
-
|
|
28594
|
-
if (
|
|
28595
|
-
|
|
28596
|
-
let own = transform && transform !== "none" ? ops.fromTransform(transform) : ops.identity();
|
|
28597
|
-
if (!own) return null;
|
|
28598
|
-
const spin = individualRotateDegrees(style.rotate);
|
|
28599
|
-
if (spin !== 0) own = ops.compose(ops.fromRotate(spin), own);
|
|
28600
|
-
acc = ops.compose(own, acc);
|
|
28652
|
+
above = memo52?.get(node);
|
|
28653
|
+
if (above !== void 0) break;
|
|
28654
|
+
pending2.push(node);
|
|
28601
28655
|
if (node.hasAttribute(COMPOSITION_ROOT_ATTR)) break;
|
|
28602
28656
|
}
|
|
28657
|
+
let acc = above === void 0 ? ops.identity() : above;
|
|
28658
|
+
for (let i = pending2.length - 1; i >= 0; i -= 1) {
|
|
28659
|
+
const node = pending2[i];
|
|
28660
|
+
if (acc !== null) {
|
|
28661
|
+
const own = ownNodeTransform(node, ops, getStyle);
|
|
28662
|
+
acc = own === null ? null : ops.compose(acc, own);
|
|
28663
|
+
}
|
|
28664
|
+
memo52?.set(node, acc);
|
|
28665
|
+
}
|
|
28603
28666
|
return acc;
|
|
28604
28667
|
}
|
|
28605
28668
|
|
|
@@ -28832,24 +28895,44 @@ function rotateDeltaIntoFrame(deltaX, deltaY, angleDeg) {
|
|
|
28832
28895
|
return { deltaX: deltaX * cos - deltaY * sin, deltaY: deltaX * sin + deltaY * cos };
|
|
28833
28896
|
}
|
|
28834
28897
|
|
|
28898
|
+
// src/components/editor/domEditOverlayMeasurePass.ts
|
|
28899
|
+
function createOverlayMeasurePass() {
|
|
28900
|
+
return {
|
|
28901
|
+
visible: /* @__PURE__ */ new Map(),
|
|
28902
|
+
transform: /* @__PURE__ */ new Map(),
|
|
28903
|
+
sourceBoundary: /* @__PURE__ */ new Map(),
|
|
28904
|
+
sourceBoundaryRect: /* @__PURE__ */ new Map()
|
|
28905
|
+
};
|
|
28906
|
+
}
|
|
28907
|
+
function readThroughPass(memo52, key2, compute) {
|
|
28908
|
+
const answered = memo52.get(key2);
|
|
28909
|
+
if (answered !== void 0) return answered;
|
|
28910
|
+
const value = compute();
|
|
28911
|
+
memo52.set(key2, value);
|
|
28912
|
+
return value;
|
|
28913
|
+
}
|
|
28914
|
+
|
|
28835
28915
|
// src/components/editor/domEditOverlayGeometry.ts
|
|
28836
28916
|
function isElementVisibleForOverlay(el) {
|
|
28837
28917
|
return isElementVisibleThroughAncestors(el);
|
|
28838
28918
|
}
|
|
28839
|
-
|
|
28840
|
-
|
|
28841
|
-
const
|
|
28842
|
-
|
|
28843
|
-
|
|
28844
|
-
|
|
28845
|
-
|
|
28846
|
-
|
|
28847
|
-
|
|
28848
|
-
|
|
28919
|
+
var isSourceBoundary = (node) => node.hasAttribute("data-composition-file") || node.hasAttribute("data-composition-src");
|
|
28920
|
+
function findSourceBoundary(element, pass) {
|
|
28921
|
+
const pending2 = [];
|
|
28922
|
+
let boundary;
|
|
28923
|
+
for (let node = element; node; node = node.parentElement) {
|
|
28924
|
+
boundary = pass?.sourceBoundary.get(node);
|
|
28925
|
+
if (boundary !== void 0) break;
|
|
28926
|
+
if (isSourceBoundary(node)) {
|
|
28927
|
+
boundary = node;
|
|
28928
|
+
pass?.sourceBoundary.set(node, node);
|
|
28929
|
+
break;
|
|
28849
28930
|
}
|
|
28850
|
-
|
|
28931
|
+
pending2.push(node);
|
|
28851
28932
|
}
|
|
28852
|
-
|
|
28933
|
+
const answer = boundary ?? null;
|
|
28934
|
+
if (pass) for (const node of pending2) pass.sourceBoundary.set(node, answer);
|
|
28935
|
+
return answer;
|
|
28853
28936
|
}
|
|
28854
28937
|
function resolveDomEditCoordinateScale(input) {
|
|
28855
28938
|
const rootScaleX = input.rootScaleX > 0 ? input.rootScaleX : 1;
|
|
@@ -28861,8 +28944,8 @@ function resolveDomEditCoordinateScale(input) {
|
|
|
28861
28944
|
scaleY: sourceScaleY > 0 ? sourceScaleY : rootScaleY
|
|
28862
28945
|
};
|
|
28863
28946
|
}
|
|
28864
|
-
function toVisibleOverlayRect(overlayEl, iframe, element) {
|
|
28865
|
-
const rect = toOverlayRect(overlayEl, iframe, element);
|
|
28947
|
+
function toVisibleOverlayRect(overlayEl, iframe, element, precomputedScale) {
|
|
28948
|
+
const rect = toOverlayRect(overlayEl, iframe, element, precomputedScale);
|
|
28866
28949
|
return rect ? { ...rect, ...hugRectForElement(rect, element) } : null;
|
|
28867
28950
|
}
|
|
28868
28951
|
function toVisibleOverlayRects(overlayEl, iframe, elements) {
|
|
@@ -28873,7 +28956,7 @@ function toVisibleOverlayRects(overlayEl, iframe, elements) {
|
|
|
28873
28956
|
return rect ? { ...rect, ...hugRectForElement(rect, element) } : null;
|
|
28874
28957
|
});
|
|
28875
28958
|
}
|
|
28876
|
-
function readElementTransformSnapshot(win, element) {
|
|
28959
|
+
function readElementTransformSnapshot(win, element, pass) {
|
|
28877
28960
|
const DOMMatrixCtor = win.DOMMatrix;
|
|
28878
28961
|
if (!DOMMatrixCtor) return null;
|
|
28879
28962
|
const cs = win.getComputedStyle(element);
|
|
@@ -28887,7 +28970,8 @@ function readElementTransformSnapshot(win, element) {
|
|
|
28887
28970
|
const matrix = composeElementTransform(
|
|
28888
28971
|
element,
|
|
28889
28972
|
ops,
|
|
28890
|
-
(node) => node === element ? cs : win.getComputedStyle(node)
|
|
28973
|
+
(node) => node === element ? cs : win.getComputedStyle(node),
|
|
28974
|
+
pass?.transform
|
|
28891
28975
|
);
|
|
28892
28976
|
return matrix ? { matrix, cs } : null;
|
|
28893
28977
|
} catch {
|
|
@@ -28906,36 +28990,17 @@ function rotationDegreesFromMatrix(matrix) {
|
|
|
28906
28990
|
return Number.isFinite(deg) ? deg : 0;
|
|
28907
28991
|
}
|
|
28908
28992
|
var ROTATION_GATE_EPSILON_DEG = 1e-4;
|
|
28909
|
-
function
|
|
28910
|
-
return doc?.querySelector("[data-composition-id]") ?? doc?.documentElement ?? null;
|
|
28911
|
-
}
|
|
28912
|
-
function resolveRootDimensions(root) {
|
|
28913
|
-
if (!root) return null;
|
|
28914
|
-
const rootRect = root.getBoundingClientRect();
|
|
28915
|
-
const width = readPositiveDimension(root.getAttribute("data-width")) ?? rootRect.width;
|
|
28916
|
-
const height = readPositiveDimension(root.getAttribute("data-height")) ?? rootRect.height;
|
|
28917
|
-
if (!width || !height) return null;
|
|
28918
|
-
return { width, height };
|
|
28919
|
-
}
|
|
28920
|
-
function computeOverlayRootScale(overlayEl, iframe, doc) {
|
|
28921
|
-
const iframeRect = iframe.getBoundingClientRect();
|
|
28922
|
-
const overlayRect = overlayEl.getBoundingClientRect();
|
|
28923
|
-
const dims = resolveRootDimensions(findOverlayRootElement(doc));
|
|
28924
|
-
if (!dims) return null;
|
|
28925
|
-
return {
|
|
28926
|
-
iframeRect,
|
|
28927
|
-
overlayRect,
|
|
28928
|
-
rootScaleX: iframeRect.width / dims.width,
|
|
28929
|
-
rootScaleY: iframeRect.height / dims.height
|
|
28930
|
-
};
|
|
28931
|
-
}
|
|
28932
|
-
function toOverlayRect(overlayEl, iframe, element, precomputedScale) {
|
|
28993
|
+
function toOverlayRect(overlayEl, iframe, element, precomputedScale, pass) {
|
|
28933
28994
|
const scale = precomputedScale ?? computeOverlayRootScale(overlayEl, iframe, iframe.contentDocument);
|
|
28934
28995
|
if (!scale) return null;
|
|
28935
28996
|
const { iframeRect, overlayRect, rootScaleX, rootScaleY } = scale;
|
|
28936
28997
|
const elementRect = element.getBoundingClientRect();
|
|
28937
|
-
const sourceBoundary = findSourceBoundary(element);
|
|
28938
|
-
const sourceBoundaryRect = sourceBoundary
|
|
28998
|
+
const sourceBoundary = findSourceBoundary(element, pass);
|
|
28999
|
+
const sourceBoundaryRect = sourceBoundary && pass ? readThroughPass(
|
|
29000
|
+
pass.sourceBoundaryRect,
|
|
29001
|
+
sourceBoundary,
|
|
29002
|
+
() => sourceBoundary.getBoundingClientRect()
|
|
29003
|
+
) : sourceBoundary?.getBoundingClientRect();
|
|
28939
29004
|
const editScale = resolveDomEditCoordinateScale({
|
|
28940
29005
|
rootScaleX,
|
|
28941
29006
|
rootScaleY,
|
|
@@ -29005,13 +29070,13 @@ function elementCornerOverlayPoints(overlayEl, iframe, element, precomputedScale
|
|
|
29005
29070
|
sw: toOverlay(relCorners.sw)
|
|
29006
29071
|
};
|
|
29007
29072
|
}
|
|
29008
|
-
function orientedOverlayRect(overlayEl, iframe, element) {
|
|
29009
|
-
const scale = computeOverlayRootScale(overlayEl, iframe, iframe.contentDocument);
|
|
29073
|
+
function orientedOverlayRect(overlayEl, iframe, element, precomputedScale, pass) {
|
|
29074
|
+
const scale = precomputedScale ?? computeOverlayRootScale(overlayEl, iframe, iframe.contentDocument);
|
|
29010
29075
|
if (!scale) return null;
|
|
29011
|
-
const base2 = toOverlayRect(overlayEl, iframe, element, scale);
|
|
29076
|
+
const base2 = toOverlayRect(overlayEl, iframe, element, scale, pass);
|
|
29012
29077
|
if (!base2) return null;
|
|
29013
29078
|
const win = iframe.contentWindow;
|
|
29014
|
-
const transform = win ? readElementTransformSnapshot(win, element) : null;
|
|
29079
|
+
const transform = win ? readElementTransformSnapshot(win, element, pass) : null;
|
|
29015
29080
|
const angle = transform ? rotationDegreesFromMatrix(transform.matrix) : 0;
|
|
29016
29081
|
if (Math.abs(angle) < ROTATION_GATE_EPSILON_DEG) return base2;
|
|
29017
29082
|
const corners = elementCornerOverlayPoints(overlayEl, iframe, element, scale, transform);
|
|
@@ -29033,8 +29098,8 @@ function orientedOverlayRect(overlayEl, iframe, element) {
|
|
|
29033
29098
|
angle
|
|
29034
29099
|
};
|
|
29035
29100
|
}
|
|
29036
|
-
function orientedVisibleOverlayRect(overlayEl, iframe, element) {
|
|
29037
|
-
const rect = orientedOverlayRect(overlayEl, iframe, element);
|
|
29101
|
+
function orientedVisibleOverlayRect(overlayEl, iframe, element, precomputedScale) {
|
|
29102
|
+
const rect = orientedOverlayRect(overlayEl, iframe, element, precomputedScale);
|
|
29038
29103
|
return rect ? { ...rect, ...hugRectForElement(rect, element) } : null;
|
|
29039
29104
|
}
|
|
29040
29105
|
var OVERLAY_RECT_EPSILON_PX = 0.5;
|
|
@@ -29076,20 +29141,26 @@ function resolveDomEditGroupOverlayRect(rects) {
|
|
|
29076
29141
|
editScaleY: 1
|
|
29077
29142
|
};
|
|
29078
29143
|
}
|
|
29079
|
-
function groupAwareOverlayRect(overlayEl, iframe, el) {
|
|
29080
|
-
const rect = toOverlayRect(overlayEl, iframe, el);
|
|
29144
|
+
function groupAwareOverlayRect(overlayEl, iframe, el, precomputedScale, pass) {
|
|
29145
|
+
const rect = toOverlayRect(overlayEl, iframe, el, precomputedScale, pass);
|
|
29081
29146
|
if (!rect || !el.hasAttribute("data-hf-group")) return rect;
|
|
29082
29147
|
const rects = [];
|
|
29083
29148
|
for (const child of Array.from(el.children)) {
|
|
29084
|
-
const childRect = toOverlayRect(
|
|
29149
|
+
const childRect = toOverlayRect(
|
|
29150
|
+
overlayEl,
|
|
29151
|
+
iframe,
|
|
29152
|
+
child,
|
|
29153
|
+
precomputedScale,
|
|
29154
|
+
pass
|
|
29155
|
+
);
|
|
29085
29156
|
if (childRect) rects.push(childRect);
|
|
29086
29157
|
}
|
|
29087
29158
|
const union = rects.length > 0 ? resolveDomEditGroupOverlayRect(rects) : null;
|
|
29088
29159
|
if (!union) return rect;
|
|
29089
29160
|
return { ...union, editScaleX: rect.editScaleX, editScaleY: rect.editScaleY };
|
|
29090
29161
|
}
|
|
29091
|
-
function orientedGroupAwareOverlayRect(overlayEl, iframe, el) {
|
|
29092
|
-
return el.hasAttribute("data-hf-group") ? groupAwareOverlayRect(overlayEl, iframe, el) : orientedOverlayRect(overlayEl, iframe, el);
|
|
29162
|
+
function orientedGroupAwareOverlayRect(overlayEl, iframe, el, precomputedScale, pass) {
|
|
29163
|
+
return el.hasAttribute("data-hf-group") ? groupAwareOverlayRect(overlayEl, iframe, el, precomputedScale, pass) : orientedOverlayRect(overlayEl, iframe, el, precomputedScale, pass);
|
|
29093
29164
|
}
|
|
29094
29165
|
function filterNestedDomEditGroupItems(items) {
|
|
29095
29166
|
return items.filter(
|
|
@@ -29437,6 +29508,125 @@ function hasDomEditRotationChanged(initialAngle, nextAngle) {
|
|
|
29437
29508
|
|
|
29438
29509
|
// src/components/editor/useDomEditOverlayRects.ts
|
|
29439
29510
|
import { useRef as useRef54, useState as useState36 } from "react";
|
|
29511
|
+
|
|
29512
|
+
// src/components/editor/overlayFrameLoop.ts
|
|
29513
|
+
var AWAKE_MS = 400;
|
|
29514
|
+
var IDLE_POLL_MS = 250;
|
|
29515
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
29516
|
+
var frameId = null;
|
|
29517
|
+
var idleTimerId = null;
|
|
29518
|
+
var awakeUntil = 0;
|
|
29519
|
+
var listenersAttached = false;
|
|
29520
|
+
var WINDOW_EVENTS = [
|
|
29521
|
+
"pointerdown",
|
|
29522
|
+
"pointermove",
|
|
29523
|
+
"pointerup",
|
|
29524
|
+
"wheel",
|
|
29525
|
+
"keydown",
|
|
29526
|
+
"keyup",
|
|
29527
|
+
"scroll",
|
|
29528
|
+
"resize",
|
|
29529
|
+
"visibilitychange"
|
|
29530
|
+
];
|
|
29531
|
+
var lastPreviewFrame = null;
|
|
29532
|
+
var lastPreviewPlaying = null;
|
|
29533
|
+
function isFromPreviewOrigin(event) {
|
|
29534
|
+
if (typeof window === "undefined") return true;
|
|
29535
|
+
return event.origin === window.location.origin;
|
|
29536
|
+
}
|
|
29537
|
+
function isPreviewPayload(data) {
|
|
29538
|
+
if (data == null || typeof data !== "object") return false;
|
|
29539
|
+
return data.source === "hf-preview";
|
|
29540
|
+
}
|
|
29541
|
+
function previewStateOf(data) {
|
|
29542
|
+
if (data.type !== "state") return null;
|
|
29543
|
+
const frame = data.frame;
|
|
29544
|
+
return {
|
|
29545
|
+
frame: typeof frame === "number" ? frame : null,
|
|
29546
|
+
playing: data.isPlaying === true
|
|
29547
|
+
};
|
|
29548
|
+
}
|
|
29549
|
+
function onPreviewMessage(event) {
|
|
29550
|
+
if (!isFromPreviewOrigin(event)) return;
|
|
29551
|
+
const data = event.data;
|
|
29552
|
+
if (!isPreviewPayload(data)) return;
|
|
29553
|
+
const state = previewStateOf(data);
|
|
29554
|
+
if (state) {
|
|
29555
|
+
if (state.frame === lastPreviewFrame && state.playing === lastPreviewPlaying) return;
|
|
29556
|
+
lastPreviewFrame = state.frame;
|
|
29557
|
+
lastPreviewPlaying = state.playing;
|
|
29558
|
+
}
|
|
29559
|
+
requestOverlayFrames();
|
|
29560
|
+
}
|
|
29561
|
+
function runFrame() {
|
|
29562
|
+
frameId = null;
|
|
29563
|
+
schedule();
|
|
29564
|
+
for (const subscriber of subscribers) {
|
|
29565
|
+
try {
|
|
29566
|
+
subscriber();
|
|
29567
|
+
} catch (error) {
|
|
29568
|
+
queueMicrotask(() => {
|
|
29569
|
+
throw error;
|
|
29570
|
+
});
|
|
29571
|
+
}
|
|
29572
|
+
}
|
|
29573
|
+
}
|
|
29574
|
+
function schedule() {
|
|
29575
|
+
if (subscribers.size === 0) return;
|
|
29576
|
+
if (frameId != null || idleTimerId != null) return;
|
|
29577
|
+
if (performance.now() < awakeUntil) {
|
|
29578
|
+
frameId = requestAnimationFrame(runFrame);
|
|
29579
|
+
return;
|
|
29580
|
+
}
|
|
29581
|
+
idleTimerId = setTimeout(() => {
|
|
29582
|
+
idleTimerId = null;
|
|
29583
|
+
frameId = requestAnimationFrame(runFrame);
|
|
29584
|
+
}, IDLE_POLL_MS);
|
|
29585
|
+
}
|
|
29586
|
+
function requestOverlayFrames() {
|
|
29587
|
+
awakeUntil = performance.now() + AWAKE_MS;
|
|
29588
|
+
if (idleTimerId != null) {
|
|
29589
|
+
clearTimeout(idleTimerId);
|
|
29590
|
+
idleTimerId = null;
|
|
29591
|
+
}
|
|
29592
|
+
schedule();
|
|
29593
|
+
}
|
|
29594
|
+
function attachListeners() {
|
|
29595
|
+
if (listenersAttached || typeof window === "undefined") return;
|
|
29596
|
+
listenersAttached = true;
|
|
29597
|
+
for (const type of WINDOW_EVENTS) {
|
|
29598
|
+
window.addEventListener(type, requestOverlayFrames, { capture: true, passive: true });
|
|
29599
|
+
}
|
|
29600
|
+
window.addEventListener("message", onPreviewMessage, { capture: true, passive: true });
|
|
29601
|
+
}
|
|
29602
|
+
function detachListeners() {
|
|
29603
|
+
if (!listenersAttached || typeof window === "undefined") return;
|
|
29604
|
+
listenersAttached = false;
|
|
29605
|
+
for (const type of WINDOW_EVENTS) {
|
|
29606
|
+
window.removeEventListener(type, requestOverlayFrames, { capture: true });
|
|
29607
|
+
}
|
|
29608
|
+
window.removeEventListener("message", onPreviewMessage, { capture: true });
|
|
29609
|
+
}
|
|
29610
|
+
function subscribeOverlayFrame(update) {
|
|
29611
|
+
subscribers.add(update);
|
|
29612
|
+
attachListeners();
|
|
29613
|
+
requestOverlayFrames();
|
|
29614
|
+
return () => {
|
|
29615
|
+
subscribers.delete(update);
|
|
29616
|
+
if (subscribers.size > 0) return;
|
|
29617
|
+
if (frameId != null) {
|
|
29618
|
+
cancelAnimationFrame(frameId);
|
|
29619
|
+
frameId = null;
|
|
29620
|
+
}
|
|
29621
|
+
if (idleTimerId != null) {
|
|
29622
|
+
clearTimeout(idleTimerId);
|
|
29623
|
+
idleTimerId = null;
|
|
29624
|
+
}
|
|
29625
|
+
detachListeners();
|
|
29626
|
+
};
|
|
29627
|
+
}
|
|
29628
|
+
|
|
29629
|
+
// src/components/editor/useDomEditOverlayRects.ts
|
|
29440
29630
|
function childRectsEqual(a, b) {
|
|
29441
29631
|
if (a.length !== b.length) return false;
|
|
29442
29632
|
for (let i = 0; i < a.length; i++) {
|
|
@@ -29492,14 +29682,12 @@ function useDomEditOverlayRects({
|
|
|
29492
29682
|
return next;
|
|
29493
29683
|
};
|
|
29494
29684
|
useMountEffect(() => {
|
|
29495
|
-
let frame = 0;
|
|
29496
29685
|
const clearAll = () => {
|
|
29497
29686
|
setOverlayRect(null);
|
|
29498
29687
|
setHoverRect(null);
|
|
29499
29688
|
setGroupOverlayItems([]);
|
|
29500
29689
|
};
|
|
29501
29690
|
const update = () => {
|
|
29502
|
-
frame = requestAnimationFrame(update);
|
|
29503
29691
|
if (rafPausedRef.current) {
|
|
29504
29692
|
if (childRectsRef.current.length > 0) {
|
|
29505
29693
|
childRectsRef.current = [];
|
|
@@ -29525,6 +29713,7 @@ function useDomEditOverlayRects({
|
|
|
29525
29713
|
clearAll();
|
|
29526
29714
|
return;
|
|
29527
29715
|
}
|
|
29716
|
+
const scale = computeOverlayRootScale(overlayEl, iframe, doc);
|
|
29528
29717
|
if (sel) {
|
|
29529
29718
|
const el = resolveElementForOverlay(
|
|
29530
29719
|
doc,
|
|
@@ -29533,7 +29722,7 @@ function useDomEditOverlayRects({
|
|
|
29533
29722
|
resolvedElementRef
|
|
29534
29723
|
);
|
|
29535
29724
|
if (el && isElementVisibleForOverlay(el)) {
|
|
29536
|
-
const nextRect = orientedGroupAwareOverlayRect(overlayEl, iframe, el);
|
|
29725
|
+
const nextRect = orientedGroupAwareOverlayRect(overlayEl, iframe, el, scale);
|
|
29537
29726
|
setOverlayRect(nextRect);
|
|
29538
29727
|
const descendants = el.querySelectorAll("*");
|
|
29539
29728
|
if (descendants.length > 0 && descendants.length <= 60) {
|
|
@@ -29541,7 +29730,7 @@ function useDomEditOverlayRects({
|
|
|
29541
29730
|
for (let i = 0; i < descendants.length; i++) {
|
|
29542
29731
|
const child = descendants[i];
|
|
29543
29732
|
if (!child.getBoundingClientRect) continue;
|
|
29544
|
-
const r = orientedVisibleOverlayRect(overlayEl, iframe, child);
|
|
29733
|
+
const r = orientedVisibleOverlayRect(overlayEl, iframe, child, scale);
|
|
29545
29734
|
if (r && r.width > 2 && r.height > 2) nextChildRects.push(r);
|
|
29546
29735
|
}
|
|
29547
29736
|
if (!childRectsEqual(childRectsRef.current, nextChildRects)) {
|
|
@@ -29576,7 +29765,7 @@ function useDomEditOverlayRects({
|
|
|
29576
29765
|
if (liveGroupKeys.has(key2)) continue;
|
|
29577
29766
|
liveGroupKeys.add(key2);
|
|
29578
29767
|
const el = resolveGroupElement(doc, groupSelection);
|
|
29579
|
-
const base2 = el ? groupAwareOverlayRect(overlayEl, iframe, el) : null;
|
|
29768
|
+
const base2 = el ? groupAwareOverlayRect(overlayEl, iframe, el, scale) : null;
|
|
29580
29769
|
const rect = base2 && el ? { ...base2, ...hugRectForElement(base2, el) } : base2;
|
|
29581
29770
|
if (el && rect)
|
|
29582
29771
|
nextGroupItems.push({ key: key2, selection: groupSelection, element: el, rect });
|
|
@@ -29611,10 +29800,9 @@ function useDomEditOverlayRects({
|
|
|
29611
29800
|
setHoverRect(null);
|
|
29612
29801
|
return;
|
|
29613
29802
|
}
|
|
29614
|
-
setHoverRect(orientedGroupAwareOverlayRect(overlayEl, iframe, hoverEl));
|
|
29803
|
+
setHoverRect(orientedGroupAwareOverlayRect(overlayEl, iframe, hoverEl, scale));
|
|
29615
29804
|
};
|
|
29616
|
-
|
|
29617
|
-
return () => cancelAnimationFrame(frame);
|
|
29805
|
+
return subscribeOverlayFrame(update);
|
|
29618
29806
|
});
|
|
29619
29807
|
return {
|
|
29620
29808
|
overlayRect,
|
|
@@ -29692,7 +29880,7 @@ function OffCanvasIndicators({
|
|
|
29692
29880
|
const selectOffCanvas = async () => {
|
|
29693
29881
|
const el = elements.current.get(r.key);
|
|
29694
29882
|
if (!el) return;
|
|
29695
|
-
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-
|
|
29883
|
+
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-UKMVYXT6.js");
|
|
29696
29884
|
const acp = activeCompositionPathRef.current ?? "index.html";
|
|
29697
29885
|
const sel = await resolveDomEditSelection2(el, {
|
|
29698
29886
|
activeCompositionPath: acp,
|
|
@@ -32553,9 +32741,7 @@ var SnapGuideOverlay = memo21(function SnapGuideOverlay2({
|
|
|
32553
32741
|
height: compositionHeight
|
|
32554
32742
|
};
|
|
32555
32743
|
useMountEffect(() => {
|
|
32556
|
-
let frame = 0;
|
|
32557
32744
|
const update = () => {
|
|
32558
|
-
frame = requestAnimationFrame(update);
|
|
32559
32745
|
const state = snapGuidesRef.current;
|
|
32560
32746
|
const guides = state?.guides ?? [];
|
|
32561
32747
|
const spacingGuides = state?.spacingGuides ?? [];
|
|
@@ -32611,8 +32797,7 @@ var SnapGuideOverlay = memo21(function SnapGuideOverlay2({
|
|
|
32611
32797
|
}
|
|
32612
32798
|
}
|
|
32613
32799
|
};
|
|
32614
|
-
|
|
32615
|
-
return () => cancelAnimationFrame(frame);
|
|
32800
|
+
return subscribeOverlayFrame(update);
|
|
32616
32801
|
});
|
|
32617
32802
|
return /* @__PURE__ */ jsxs56("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-0", children: [
|
|
32618
32803
|
Array.from({ length: MAX_GUIDES }, (_, i) => /* @__PURE__ */ jsx73(
|
|
@@ -33269,9 +33454,7 @@ function useDomEditCompositionRect({
|
|
|
33269
33454
|
scaleY: 1
|
|
33270
33455
|
});
|
|
33271
33456
|
useMountEffect(() => {
|
|
33272
|
-
let frame = 0;
|
|
33273
33457
|
const update = () => {
|
|
33274
|
-
frame = requestAnimationFrame(update);
|
|
33275
33458
|
const iframe = iframeRef.current;
|
|
33276
33459
|
const overlayEl = overlayRef.current;
|
|
33277
33460
|
if (!iframe || !overlayEl) return;
|
|
@@ -33289,8 +33472,7 @@ function useDomEditCompositionRect({
|
|
|
33289
33472
|
const next = { left, top, width: iRect.width, height: iRect.height, scaleX, scaleY };
|
|
33290
33473
|
setCompRect((prev) => sameRect(prev, next) ? prev : next);
|
|
33291
33474
|
};
|
|
33292
|
-
|
|
33293
|
-
return () => cancelAnimationFrame(frame);
|
|
33475
|
+
return subscribeOverlayFrame(update);
|
|
33294
33476
|
});
|
|
33295
33477
|
return compRect;
|
|
33296
33478
|
}
|
|
@@ -33312,7 +33494,12 @@ function extendsOutside(rect, comp) {
|
|
|
33312
33494
|
const centerY = rect.top + rect.height / 2;
|
|
33313
33495
|
return centerX - halfWidth < comp.left || centerX + halfWidth > comp.left + comp.width || centerY - halfHeight < comp.top || centerY + halfHeight > comp.top + comp.height;
|
|
33314
33496
|
}
|
|
33315
|
-
function
|
|
33497
|
+
function measureItemRect(overlay, iframe, element, scale, pass) {
|
|
33498
|
+
if (!isElementComputedVisible(element, pass.visible)) return null;
|
|
33499
|
+
const base2 = orientedGroupAwareOverlayRect(overlay, iframe, element, scale, pass);
|
|
33500
|
+
return base2 ? { ...base2, ...hugRectForElement(base2, element) } : null;
|
|
33501
|
+
}
|
|
33502
|
+
function recomputeOffCanvasIndicators(iframe, overlay, doc, comp, activeCompositionPath, sigRef, elementsRef, setRects, walkCache) {
|
|
33316
33503
|
if (comp.width <= 0 || !doc) {
|
|
33317
33504
|
sigRef.current = "";
|
|
33318
33505
|
elementsRef.current = /* @__PURE__ */ new Map();
|
|
@@ -33321,16 +33508,18 @@ function recomputeOffCanvasIndicators(iframe, overlay, doc, comp, activeComposit
|
|
|
33321
33508
|
}
|
|
33322
33509
|
const root = doc.querySelector("[data-composition-id]") ?? doc.body;
|
|
33323
33510
|
const acp = activeCompositionPath ?? "index.html";
|
|
33324
|
-
const items = collectDomEditLayerItems(
|
|
33325
|
-
|
|
33326
|
-
isMasterView: !acp || acp === "index.html"
|
|
33327
|
-
|
|
33511
|
+
const items = collectDomEditLayerItems(
|
|
33512
|
+
root,
|
|
33513
|
+
{ activeCompositionPath: acp, isMasterView: !acp || acp === "index.html" },
|
|
33514
|
+
void 0,
|
|
33515
|
+
walkCache
|
|
33516
|
+
);
|
|
33517
|
+
const scale = computeOverlayRootScale(overlay, iframe, doc);
|
|
33518
|
+
const pass = createOverlayMeasurePass();
|
|
33328
33519
|
const rects = [];
|
|
33329
33520
|
const elMap = /* @__PURE__ */ new Map();
|
|
33330
33521
|
for (const item of items) {
|
|
33331
|
-
|
|
33332
|
-
const base2 = orientedGroupAwareOverlayRect(overlay, iframe, item.element);
|
|
33333
|
-
const r = base2 ? { ...base2, ...hugRectForElement(base2, item.element) } : null;
|
|
33522
|
+
const r = measureItemRect(overlay, iframe, item.element, scale, pass);
|
|
33334
33523
|
if (!r) continue;
|
|
33335
33524
|
if (extendsOutside(r, comp)) {
|
|
33336
33525
|
rects.push({
|
|
@@ -33361,20 +33550,14 @@ function clearIndicators(options) {
|
|
|
33361
33550
|
options.elementsRef.current = /* @__PURE__ */ new Map();
|
|
33362
33551
|
options.setRects([]);
|
|
33363
33552
|
}
|
|
33364
|
-
function observeDoc(doc, markDirty) {
|
|
33553
|
+
function observeDoc(doc, cache2, markDirty) {
|
|
33365
33554
|
const Observer = doc.defaultView?.MutationObserver ?? globalThis.MutationObserver;
|
|
33366
33555
|
if (!Observer) return null;
|
|
33367
|
-
const observer = new Observer(
|
|
33368
|
-
|
|
33369
|
-
|
|
33370
|
-
// data-hidden is included explicitly: hiding an element writes data-hidden, and
|
|
33371
|
-
// although the runtime honoring also writes display:"none" (a style mutation we'd
|
|
33372
|
-
// catch anyway), keying on the attribute directly makes the coupling robust to any
|
|
33373
|
-
// future throttling of that runtime sync.
|
|
33374
|
-
attributeFilter: ["style", "class", "transform", "width", "height", "data-hidden"],
|
|
33375
|
-
childList: true,
|
|
33376
|
-
subtree: true
|
|
33556
|
+
const observer = new Observer((records) => {
|
|
33557
|
+
cache2.ingest(records);
|
|
33558
|
+
markDirty();
|
|
33377
33559
|
});
|
|
33560
|
+
observer.observe(doc.documentElement, DOM_EDIT_LAYER_OBSERVER_INIT);
|
|
33378
33561
|
return observer;
|
|
33379
33562
|
}
|
|
33380
33563
|
var RECOMPUTE_INTERVAL_MS = 100;
|
|
@@ -33382,20 +33565,21 @@ function rebuildDue(dirty, lastAt, now2) {
|
|
|
33382
33565
|
return dirty && now2 - lastAt >= RECOMPUTE_INTERVAL_MS;
|
|
33383
33566
|
}
|
|
33384
33567
|
function startOffCanvasIndicatorRefresh(options) {
|
|
33385
|
-
let frame = 0;
|
|
33386
33568
|
let lastCompSig = "";
|
|
33387
33569
|
let lastRecomputeAt = Number.NEGATIVE_INFINITY;
|
|
33570
|
+
const walkCache = createDomEditLayerWalkCache();
|
|
33388
33571
|
const markDirty = () => {
|
|
33389
33572
|
options.dirtyRef.current = true;
|
|
33573
|
+
requestOverlayFrames();
|
|
33390
33574
|
};
|
|
33391
33575
|
const attachObserver = (doc) => {
|
|
33392
33576
|
options.observerRef.current?.disconnect();
|
|
33393
|
-
|
|
33577
|
+
walkCache.invalidateAll();
|
|
33578
|
+
options.observerRef.current = doc?.documentElement ? observeDoc(doc, walkCache, markDirty) : null;
|
|
33394
33579
|
options.observedDocRef.current = doc;
|
|
33395
33580
|
options.sigRef.current = "";
|
|
33396
33581
|
};
|
|
33397
33582
|
const update = () => {
|
|
33398
|
-
frame = requestAnimationFrame(update);
|
|
33399
33583
|
const iframe = options.iframeRef.current;
|
|
33400
33584
|
const overlayEl = options.overlayRef.current;
|
|
33401
33585
|
const doc = iframe?.contentDocument ?? null;
|
|
@@ -33417,6 +33601,7 @@ function startOffCanvasIndicatorRefresh(options) {
|
|
|
33417
33601
|
if (!rebuildDue(options.dirtyRef.current, lastRecomputeAt, now2)) return;
|
|
33418
33602
|
lastRecomputeAt = now2;
|
|
33419
33603
|
options.dirtyRef.current = false;
|
|
33604
|
+
drainPendingLayerMutations(options.observerRef.current, walkCache);
|
|
33420
33605
|
recomputeOffCanvasIndicators(
|
|
33421
33606
|
iframe,
|
|
33422
33607
|
overlayEl,
|
|
@@ -33425,12 +33610,13 @@ function startOffCanvasIndicatorRefresh(options) {
|
|
|
33425
33610
|
options.activeCompositionPathRef.current,
|
|
33426
33611
|
options.sigRef,
|
|
33427
33612
|
options.elementsRef,
|
|
33428
|
-
options.setRects
|
|
33613
|
+
options.setRects,
|
|
33614
|
+
walkCache
|
|
33429
33615
|
);
|
|
33430
33616
|
};
|
|
33431
|
-
|
|
33617
|
+
const unsubscribe = subscribeOverlayFrame(update);
|
|
33432
33618
|
return () => {
|
|
33433
|
-
|
|
33619
|
+
unsubscribe();
|
|
33434
33620
|
options.observerRef.current?.disconnect();
|
|
33435
33621
|
options.observerRef.current = null;
|
|
33436
33622
|
options.observedDocRef.current = null;
|
|
@@ -37066,7 +37252,6 @@ function useMotionPathData(iframeRef, selector) {
|
|
|
37066
37252
|
return;
|
|
37067
37253
|
}
|
|
37068
37254
|
setHome(null);
|
|
37069
|
-
let raf = 0;
|
|
37070
37255
|
const tick = () => {
|
|
37071
37256
|
const el = iframeRef.current;
|
|
37072
37257
|
if (el) {
|
|
@@ -37097,10 +37282,8 @@ function useMotionPathData(iframeRef, selector) {
|
|
|
37097
37282
|
setPScale((p) => Math.abs(p - ps) < 1e-3 ? p : ps);
|
|
37098
37283
|
}
|
|
37099
37284
|
}
|
|
37100
|
-
raf = requestAnimationFrame(tick);
|
|
37101
37285
|
};
|
|
37102
|
-
|
|
37103
|
-
return () => cancelAnimationFrame(raf);
|
|
37286
|
+
return subscribeOverlayFrame(tick);
|
|
37104
37287
|
}, [selector, iframeRef]);
|
|
37105
37288
|
useEffect44(() => {
|
|
37106
37289
|
if (!selector) {
|
|
@@ -37703,12 +37886,13 @@ function readPositiveDimensions(width, height) {
|
|
|
37703
37886
|
if (parsedWidth === null || parsedHeight === null) return null;
|
|
37704
37887
|
return { width: parsedWidth, height: parsedHeight };
|
|
37705
37888
|
}
|
|
37706
|
-
function useCompositionDimensions() {
|
|
37889
|
+
function useCompositionDimensions(iframeRef) {
|
|
37707
37890
|
const [compositionDimensions, setCompositionDimensions] = useState46(
|
|
37708
37891
|
null
|
|
37709
37892
|
);
|
|
37710
37893
|
useMountEffect(() => {
|
|
37711
37894
|
const handleMessage = (e) => {
|
|
37895
|
+
if (!e.source || e.source !== iframeRef.current?.contentWindow) return;
|
|
37712
37896
|
const dimensions = readCompositionSizeMessage(e.data);
|
|
37713
37897
|
if (!dimensions) return;
|
|
37714
37898
|
setCompositionDimensions(
|
|
@@ -39169,7 +39353,10 @@ function useElementLifecycleOps({
|
|
|
39169
39353
|
}
|
|
39170
39354
|
domEditSaveTimestampRef.current = Date.now();
|
|
39171
39355
|
const removeResponse = await fetch(
|
|
39172
|
-
|
|
39356
|
+
buildProjectApiPath(
|
|
39357
|
+
pid,
|
|
39358
|
+
`/file-mutations/remove-elements/${encodeURIComponent(targetPath)}`
|
|
39359
|
+
),
|
|
39173
39360
|
{
|
|
39174
39361
|
method: "POST",
|
|
39175
39362
|
headers: { "Content-Type": "application/json", ...studioWriteHeaders() },
|
|
@@ -39647,7 +39834,7 @@ function PreviewOverlays({
|
|
|
39647
39834
|
}) {
|
|
39648
39835
|
const { activeCompPath, previewIframeRef } = useStudioShellContext();
|
|
39649
39836
|
const { captionEditMode, compositionLoading, isPlaying } = useStudioPlaybackContext();
|
|
39650
|
-
const compositionDimensions = useCompositionDimensions();
|
|
39837
|
+
const compositionDimensions = useCompositionDimensions(previewIframeRef);
|
|
39651
39838
|
const captionModelPresent = useCaptionStore((state) => state.model !== null);
|
|
39652
39839
|
const captionDismissed = useCaptionStore((state) => state.dismissed);
|
|
39653
39840
|
const captionSyncError = useCaptionStore((state) => state.syncError);
|
|
@@ -41796,52 +41983,6 @@ var STUDIO_SEEK_DESCRIPTION = [
|
|
|
41796
41983
|
"Returns `ok: true`, or `ok: false` with `kind`, `reason` and a `hint`."
|
|
41797
41984
|
].join(" ");
|
|
41798
41985
|
|
|
41799
|
-
// src/utils/projectRouting.ts
|
|
41800
|
-
var PROJECT_HASH_PREFIX = "#project/";
|
|
41801
|
-
function decodeHashProjectId(value) {
|
|
41802
|
-
try {
|
|
41803
|
-
return decodeURIComponent(value);
|
|
41804
|
-
} catch {
|
|
41805
|
-
return value;
|
|
41806
|
-
}
|
|
41807
|
-
}
|
|
41808
|
-
function normalizeHashParams(params) {
|
|
41809
|
-
if (!params) return new URLSearchParams();
|
|
41810
|
-
if (params instanceof URLSearchParams) return params;
|
|
41811
|
-
const next = new URLSearchParams();
|
|
41812
|
-
for (const [key2, value] of Object.entries(params)) {
|
|
41813
|
-
if (!key2 || value == null || value === "") continue;
|
|
41814
|
-
next.set(key2, value);
|
|
41815
|
-
}
|
|
41816
|
-
return next;
|
|
41817
|
-
}
|
|
41818
|
-
function encodeProjectId(projectId) {
|
|
41819
|
-
return encodeURIComponent(projectId);
|
|
41820
|
-
}
|
|
41821
|
-
function buildProjectHash(projectId, params) {
|
|
41822
|
-
const search = normalizeHashParams(params).toString();
|
|
41823
|
-
return `${PROJECT_HASH_PREFIX}${encodeProjectId(projectId)}${search ? `?${search}` : ""}`;
|
|
41824
|
-
}
|
|
41825
|
-
function parseProjectHashRoute(hash) {
|
|
41826
|
-
if (!hash.startsWith(PROJECT_HASH_PREFIX)) return null;
|
|
41827
|
-
const route = hash.slice(PROJECT_HASH_PREFIX.length);
|
|
41828
|
-
const queryIndex = route.indexOf("?");
|
|
41829
|
-
const encodedProjectId = queryIndex >= 0 ? route.slice(0, queryIndex) : route;
|
|
41830
|
-
if (!encodedProjectId || encodedProjectId.includes("/")) return null;
|
|
41831
|
-
const rawParams = queryIndex >= 0 ? route.slice(queryIndex + 1) : "";
|
|
41832
|
-
return {
|
|
41833
|
-
projectId: decodeHashProjectId(encodedProjectId),
|
|
41834
|
-
params: new URLSearchParams(rawParams)
|
|
41835
|
-
};
|
|
41836
|
-
}
|
|
41837
|
-
function parseProjectIdFromHash(hash) {
|
|
41838
|
-
return parseProjectHashRoute(hash)?.projectId ?? null;
|
|
41839
|
-
}
|
|
41840
|
-
function buildProjectApiPath(projectId, suffix = "") {
|
|
41841
|
-
const normalizedSuffix = suffix && !suffix.startsWith("/") ? `/${suffix}` : suffix;
|
|
41842
|
-
return `/api/projects/${encodeProjectId(projectId)}${normalizedSuffix}`;
|
|
41843
|
-
}
|
|
41844
|
-
|
|
41845
41986
|
// src/utils/frameCapture.ts
|
|
41846
41987
|
function normalizeCompositionPath(compositionPath) {
|
|
41847
41988
|
return compositionPath && compositionPath !== "master" ? compositionPath : "index.html";
|
|
@@ -42710,6 +42851,7 @@ function reportRegistration(report, native) {
|
|
|
42710
42851
|
}
|
|
42711
42852
|
}
|
|
42712
42853
|
function buildStudioTools(depsRef) {
|
|
42854
|
+
const writeTool = (name, run) => (input, options) => runToolBody(name, () => run(depsRef.current, input, options?.signal));
|
|
42713
42855
|
return [
|
|
42714
42856
|
{
|
|
42715
42857
|
name: "studio_look",
|
|
@@ -42774,9 +42916,9 @@ function buildStudioTools(depsRef) {
|
|
|
42774
42916
|
description: STUDIO_SET_TEXT_DESCRIPTION,
|
|
42775
42917
|
inputSchema: STUDIO_SET_TEXT_INPUT_SCHEMA,
|
|
42776
42918
|
annotations: { readOnlyHint: false, untrustedContentHint: true },
|
|
42777
|
-
execute: (
|
|
42919
|
+
execute: writeTool(
|
|
42778
42920
|
"studio_set_text",
|
|
42779
|
-
() => studioSetText(
|
|
42921
|
+
(deps, input, signal) => studioSetText(deps, input, signal)
|
|
42780
42922
|
)
|
|
42781
42923
|
},
|
|
42782
42924
|
{
|
|
@@ -42785,9 +42927,9 @@ function buildStudioTools(depsRef) {
|
|
|
42785
42927
|
description: STUDIO_SET_STYLE_DESCRIPTION,
|
|
42786
42928
|
inputSchema: STUDIO_SET_STYLE_INPUT_SCHEMA,
|
|
42787
42929
|
annotations: { readOnlyHint: false },
|
|
42788
|
-
execute: (
|
|
42930
|
+
execute: writeTool(
|
|
42789
42931
|
"studio_set_style",
|
|
42790
|
-
() => studioSetStyle(
|
|
42932
|
+
(deps, input, signal) => studioSetStyle(deps, input, signal)
|
|
42791
42933
|
)
|
|
42792
42934
|
},
|
|
42793
42935
|
{
|
|
@@ -42796,9 +42938,9 @@ function buildStudioTools(depsRef) {
|
|
|
42796
42938
|
description: STUDIO_TRANSFORM_DESCRIPTION,
|
|
42797
42939
|
inputSchema: STUDIO_TRANSFORM_INPUT_SCHEMA,
|
|
42798
42940
|
annotations: { readOnlyHint: false },
|
|
42799
|
-
execute: (
|
|
42941
|
+
execute: writeTool(
|
|
42800
42942
|
"studio_transform",
|
|
42801
|
-
() => studioTransform(
|
|
42943
|
+
(deps, input, signal) => studioTransform(deps, input, signal)
|
|
42802
42944
|
)
|
|
42803
42945
|
},
|
|
42804
42946
|
{
|
|
@@ -42807,9 +42949,9 @@ function buildStudioTools(depsRef) {
|
|
|
42807
42949
|
description: STUDIO_ADD_ANIMATION_DESCRIPTION,
|
|
42808
42950
|
inputSchema: STUDIO_ADD_ANIMATION_INPUT_SCHEMA,
|
|
42809
42951
|
annotations: { readOnlyHint: false },
|
|
42810
|
-
execute: (
|
|
42952
|
+
execute: writeTool(
|
|
42811
42953
|
"studio_add_animation",
|
|
42812
|
-
() => studioAddAnimation(
|
|
42954
|
+
(deps, input, signal) => studioAddAnimation(deps, input, signal)
|
|
42813
42955
|
)
|
|
42814
42956
|
},
|
|
42815
42957
|
{
|
|
@@ -42818,9 +42960,9 @@ function buildStudioTools(depsRef) {
|
|
|
42818
42960
|
description: STUDIO_UPDATE_ANIMATION_DESCRIPTION,
|
|
42819
42961
|
inputSchema: STUDIO_UPDATE_ANIMATION_INPUT_SCHEMA,
|
|
42820
42962
|
annotations: { readOnlyHint: false },
|
|
42821
|
-
execute: (
|
|
42963
|
+
execute: writeTool(
|
|
42822
42964
|
"studio_update_animation",
|
|
42823
|
-
() => studioUpdateAnimation(
|
|
42965
|
+
(deps, input, signal) => studioUpdateAnimation(deps, input, signal)
|
|
42824
42966
|
)
|
|
42825
42967
|
},
|
|
42826
42968
|
{
|
|
@@ -42829,9 +42971,9 @@ function buildStudioTools(depsRef) {
|
|
|
42829
42971
|
description: STUDIO_ADD_KEYFRAME_DESCRIPTION,
|
|
42830
42972
|
inputSchema: STUDIO_ADD_KEYFRAME_INPUT_SCHEMA,
|
|
42831
42973
|
annotations: { readOnlyHint: false },
|
|
42832
|
-
execute: (
|
|
42974
|
+
execute: writeTool(
|
|
42833
42975
|
"studio_add_keyframe",
|
|
42834
|
-
() => studioAddKeyframe(
|
|
42976
|
+
(deps, input, signal) => studioAddKeyframe(deps, input, signal)
|
|
42835
42977
|
)
|
|
42836
42978
|
},
|
|
42837
42979
|
{
|
|
@@ -42840,9 +42982,9 @@ function buildStudioTools(depsRef) {
|
|
|
42840
42982
|
description: STUDIO_DELETE_ANIMATION_DESCRIPTION,
|
|
42841
42983
|
inputSchema: STUDIO_DELETE_ANIMATION_INPUT_SCHEMA,
|
|
42842
42984
|
annotations: { readOnlyHint: false },
|
|
42843
|
-
execute: (
|
|
42985
|
+
execute: writeTool(
|
|
42844
42986
|
"studio_delete_animation",
|
|
42845
|
-
() => studioDeleteAnimation(
|
|
42987
|
+
(deps, input, signal) => studioDeleteAnimation(deps, input, signal)
|
|
42846
42988
|
)
|
|
42847
42989
|
}
|
|
42848
42990
|
];
|
|
@@ -48645,7 +48787,7 @@ function ImageFillField({
|
|
|
48645
48787
|
selectedAsset && /* @__PURE__ */ jsx104("div", { className: "overflow-hidden rounded-xl border border-neutral-800 bg-neutral-900/80", children: /* @__PURE__ */ jsx104(
|
|
48646
48788
|
"img",
|
|
48647
48789
|
{
|
|
48648
|
-
src: `/
|
|
48790
|
+
src: buildProjectApiPath(projectId, `/preview/${selectedAsset}`),
|
|
48649
48791
|
alt: selectedAsset.split("/").pop() ?? selectedAsset,
|
|
48650
48792
|
className: "h-28 w-full object-contain bg-neutral-950/80"
|
|
48651
48793
|
}
|
|
@@ -62863,7 +63005,7 @@ function useRenderQueue(projectId, activeCompPathRef) {
|
|
|
62863
63005
|
const loadRenders = useCallback80(async () => {
|
|
62864
63006
|
if (!projectId) return;
|
|
62865
63007
|
try {
|
|
62866
|
-
const res = await fetch(`/
|
|
63008
|
+
const res = await fetch(buildProjectApiPath(projectId, `/renders`));
|
|
62867
63009
|
if (!res.ok) {
|
|
62868
63010
|
setLoadError(`Couldn't load render history (server error ${res.status}).`);
|
|
62869
63011
|
return;
|
|
@@ -62950,7 +63092,7 @@ function useRenderQueue(projectId, activeCompPathRef) {
|
|
|
62950
63092
|
}
|
|
62951
63093
|
let res;
|
|
62952
63094
|
try {
|
|
62953
|
-
res = await fetch(`/
|
|
63095
|
+
res = await fetch(buildProjectApiPath(projectId, `/render`), {
|
|
62954
63096
|
method: "POST",
|
|
62955
63097
|
headers: { "Content-Type": "application/json" },
|
|
62956
63098
|
body: JSON.stringify(body)
|
|
@@ -63600,7 +63742,9 @@ async function captureProjectProvenance(projectId, files, compositions) {
|
|
|
63600
63742
|
};
|
|
63601
63743
|
if (!scaffolded) return;
|
|
63602
63744
|
try {
|
|
63603
|
-
const res = await fetch(
|
|
63745
|
+
const res = await fetch(
|
|
63746
|
+
buildProjectApiPath(projectId, `/files/${encodeURIComponent(CONFIG_FILE)}`)
|
|
63747
|
+
);
|
|
63604
63748
|
if (!res.ok) return;
|
|
63605
63749
|
const envelope = await res.json();
|
|
63606
63750
|
const raw = envelope.content;
|
|
@@ -64276,7 +64420,7 @@ function useCaptionSync(projectId) {
|
|
|
64276
64420
|
}
|
|
64277
64421
|
const seqAtSave = editSeqRef.current;
|
|
64278
64422
|
const overrides = buildOverrides(state.model);
|
|
64279
|
-
fetch(`/
|
|
64423
|
+
fetch(buildProjectApiPath(pid, `/files/${encodeURIComponent("caption-overrides.json")}`), {
|
|
64280
64424
|
method: "PUT",
|
|
64281
64425
|
headers: { "Content-Type": "text/plain", ...studioWriteHeaders() },
|
|
64282
64426
|
body: JSON.stringify(overrides, null, 2)
|
|
@@ -64334,7 +64478,7 @@ function useCaptionSync(projectId) {
|
|
|
64334
64478
|
let data;
|
|
64335
64479
|
try {
|
|
64336
64480
|
const res = await fetch(
|
|
64337
|
-
`/
|
|
64481
|
+
buildProjectApiPath(pid, `/files/${encodeURIComponent("caption-overrides.json")}`)
|
|
64338
64482
|
);
|
|
64339
64483
|
if (!res.ok) return;
|
|
64340
64484
|
data = await res.json();
|
|
@@ -65026,7 +65170,7 @@ function useFileTree({ projectId, projectIdRef }) {
|
|
|
65026
65170
|
}
|
|
65027
65171
|
let cancelled = false;
|
|
65028
65172
|
setFileTreeLoaded(false);
|
|
65029
|
-
fetch(
|
|
65173
|
+
fetch(buildProjectApiPath(projectId)).then((r) => r.json()).then((data) => {
|
|
65030
65174
|
if (cancelled) return;
|
|
65031
65175
|
if (data.files) setFileTree(data.files);
|
|
65032
65176
|
if (data.compositions) setCompositionPaths(data.compositions);
|
|
@@ -65044,7 +65188,7 @@ function useFileTree({ projectId, projectIdRef }) {
|
|
|
65044
65188
|
const refreshFileTree = useCallback86(async () => {
|
|
65045
65189
|
const pid = projectIdRef.current;
|
|
65046
65190
|
if (!pid) return;
|
|
65047
|
-
const res = await fetch(
|
|
65191
|
+
const res = await fetch(buildProjectApiPath(pid));
|
|
65048
65192
|
const data = await res.json();
|
|
65049
65193
|
if (data.files) setFileTree(data.files);
|
|
65050
65194
|
}, [projectIdRef]);
|
|
@@ -65054,10 +65198,10 @@ function useFileTree({ projectId, projectIdRef }) {
|
|
|
65054
65198
|
[fileTree]
|
|
65055
65199
|
);
|
|
65056
65200
|
const fontAssets = useMemo58(
|
|
65057
|
-
() => assets.filter((asset) => FONT_EXT.test(asset)).map((asset) => ({
|
|
65201
|
+
() => (projectId ? assets : []).filter((asset) => FONT_EXT.test(asset)).map((asset) => ({
|
|
65058
65202
|
family: fontFamilyFromAssetPath(asset),
|
|
65059
65203
|
path: asset,
|
|
65060
|
-
url: `/
|
|
65204
|
+
url: projectId ? buildProjectApiPath(projectId, `/preview/${asset}`) : ""
|
|
65061
65205
|
})),
|
|
65062
65206
|
[assets, projectId]
|
|
65063
65207
|
);
|
|
@@ -66760,7 +66904,10 @@ function useTimelineDeleteOps({
|
|
|
66760
66904
|
throw new Error(`Timeline element ${target.id} is missing a patchable target`);
|
|
66761
66905
|
}
|
|
66762
66906
|
const removeResponse = await fetch(
|
|
66763
|
-
|
|
66907
|
+
buildProjectApiPath(
|
|
66908
|
+
pid,
|
|
66909
|
+
`/file-mutations/remove-element/${encodeURIComponent(targetPath)}`
|
|
66910
|
+
),
|
|
66764
66911
|
{
|
|
66765
66912
|
method: "POST",
|
|
66766
66913
|
headers: { "Content-Type": "application/json", ...studioWriteHeaders() },
|
|
@@ -68070,7 +68217,7 @@ function useAskAgentModal({
|
|
|
68070
68217
|
const targetPath = selection.sourceFile || activeCompPath || "index.html";
|
|
68071
68218
|
try {
|
|
68072
68219
|
const response = await fetch(
|
|
68073
|
-
`/
|
|
68220
|
+
buildProjectApiPath(pid, `/files/${encodeURIComponent(targetPath)}`)
|
|
68074
68221
|
);
|
|
68075
68222
|
if (!response.ok) return;
|
|
68076
68223
|
const data = await response.json();
|
|
@@ -70362,11 +70509,11 @@ function useDomEditCommits({
|
|
|
70362
70509
|
const asset = fileTree.find(
|
|
70363
70510
|
(path) => FONT_EXT.test(path) && fontFamilyFromAssetPath(path).toLowerCase() === family.toLowerCase()
|
|
70364
70511
|
);
|
|
70365
|
-
if (!asset) return null;
|
|
70512
|
+
if (!asset || !projectId) return null;
|
|
70366
70513
|
return {
|
|
70367
70514
|
family: fontFamilyFromAssetPath(asset),
|
|
70368
70515
|
path: asset,
|
|
70369
|
-
url: `/
|
|
70516
|
+
url: buildProjectApiPath(projectId, `/preview/${asset}`)
|
|
70370
70517
|
};
|
|
70371
70518
|
},
|
|
70372
70519
|
[fileTree, projectId, importedFontAssetsRef]
|
|
@@ -70386,7 +70533,7 @@ function useDomEditCommits({
|
|
|
70386
70533
|
return result;
|
|
70387
70534
|
};
|
|
70388
70535
|
const readResponse = await fetch(
|
|
70389
|
-
`/
|
|
70536
|
+
buildProjectApiPath(pid, `/files/${encodeURIComponent(targetPath)}`)
|
|
70390
70537
|
);
|
|
70391
70538
|
if (!readResponse.ok) {
|
|
70392
70539
|
throw await createStudioSaveHttpError(readResponse, `Failed to read ${targetPath}`);
|
|
@@ -70426,7 +70573,7 @@ function useDomEditCommits({
|
|
|
70426
70573
|
}
|
|
70427
70574
|
domEditSaveTimestampRef.current = Date.now();
|
|
70428
70575
|
const patchResponse = await fetch(
|
|
70429
|
-
`/
|
|
70576
|
+
buildProjectApiPath(pid, `/file-mutations/patch-element/${encodeURIComponent(targetPath)}`),
|
|
70430
70577
|
{
|
|
70431
70578
|
method: "POST",
|
|
70432
70579
|
headers: { "Content-Type": "application/json", ...studioWriteHeaders() },
|
|
@@ -70691,7 +70838,7 @@ async function commitStructuralMutation(pid, targetPath, route, body, label, dep
|
|
|
70691
70838
|
const originalContent = await readProjectFileContent(pid, targetPath);
|
|
70692
70839
|
deps.domEditSaveTimestampRef.current = Date.now();
|
|
70693
70840
|
const mutateResponse = await fetch(
|
|
70694
|
-
`/
|
|
70841
|
+
buildProjectApiPath(pid, `/file-mutations/${route}/${encodeURIComponent(targetPath)}`),
|
|
70695
70842
|
{
|
|
70696
70843
|
method: "POST",
|
|
70697
70844
|
headers: { "Content-Type": "application/json", ...studioWriteHeaders() },
|
|
@@ -75244,7 +75391,7 @@ async function installRegistryItem({
|
|
|
75244
75391
|
blockName,
|
|
75245
75392
|
showToast
|
|
75246
75393
|
}) {
|
|
75247
|
-
const response = await fetch(`/
|
|
75394
|
+
const response = await fetch(buildProjectApiPath(projectId, `/registry/install`), {
|
|
75248
75395
|
method: "POST",
|
|
75249
75396
|
headers: { "Content-Type": "application/json" },
|
|
75250
75397
|
body: JSON.stringify({ blockName })
|
|
@@ -76443,7 +76590,7 @@ function useCaptionDetection({
|
|
|
76443
76590
|
if (!captionSrcPath) return;
|
|
76444
76591
|
activating = true;
|
|
76445
76592
|
const srcPath = captionSrcPath;
|
|
76446
|
-
fetch(`/
|
|
76593
|
+
fetch(buildProjectApiPath(projectId, `/files/${encodeURIComponent(srcPath)}`)).then((r) => r.json()).then((data) => {
|
|
76447
76594
|
if (!data.content || !doc || !win || useCaptionStore.getState().isEditMode) return;
|
|
76448
76595
|
const root = doc.querySelector("[data-composition-id]");
|
|
76449
76596
|
const w = parseInt(root?.getAttribute("data-width") ?? "1920", 10);
|
|
@@ -76462,6 +76609,7 @@ function useCaptionDetection({
|
|
|
76462
76609
|
});
|
|
76463
76610
|
};
|
|
76464
76611
|
const handleMessage = (e) => {
|
|
76612
|
+
if (!e.source || e.source !== previewIframeRef.current?.contentWindow) return;
|
|
76465
76613
|
const data = e.data;
|
|
76466
76614
|
if (data?.source === "hf-preview" && (data?.type === "state" || data?.type === "timeline")) {
|
|
76467
76615
|
if (!acceptStudioRuntimeMessage(data)) return;
|
|
@@ -76753,7 +76901,7 @@ var ImageThumbnail = memo37(function ImageThumbnail2({
|
|
|
76753
76901
|
function normalizeCompositionSrc(compSrc, projectId, origin) {
|
|
76754
76902
|
try {
|
|
76755
76903
|
const parsed = new URL(compSrc, origin);
|
|
76756
|
-
const previewPrefix = `/
|
|
76904
|
+
const previewPrefix = buildProjectApiPath(projectId, `/preview/`);
|
|
76757
76905
|
if (parsed.pathname.startsWith(previewPrefix)) {
|
|
76758
76906
|
return parsed.pathname.slice(previewPrefix.length);
|
|
76759
76907
|
}
|
|
@@ -76765,7 +76913,7 @@ function resolvePreviewRelative(src, pid, origin) {
|
|
|
76765
76913
|
if (!src) return null;
|
|
76766
76914
|
try {
|
|
76767
76915
|
const parsed = new URL(src, origin);
|
|
76768
|
-
const base2 = new URL(`/
|
|
76916
|
+
const base2 = new URL(buildProjectApiPath(pid, `/preview/`), origin).pathname;
|
|
76769
76917
|
return parsed.pathname.startsWith(base2) ? decodeURIComponent(parsed.pathname.slice(base2.length)) : null;
|
|
76770
76918
|
} catch {
|
|
76771
76919
|
return null;
|
|
@@ -76784,7 +76932,7 @@ function renderAudioClip(el, pid, sessionEpoch, labelColor, context) {
|
|
|
76784
76932
|
const audioUrl = resolveMediaPreviewUrl(el.src ?? "", pid, window.location.origin);
|
|
76785
76933
|
const srcRelative = resolvePreviewRelative(audioUrl, pid, window.location.origin);
|
|
76786
76934
|
const encodedRelative = srcRelative ? encodePreviewPath(srcRelative) : null;
|
|
76787
|
-
const waveformUrl = encodedRelative ? `/
|
|
76935
|
+
const waveformUrl = encodedRelative ? buildProjectApiPath(pid, `/waveform/${encodedRelative}`) : void 0;
|
|
76788
76936
|
const { start, end } = trimFractions(el);
|
|
76789
76937
|
return createElement3(AudioWaveform, {
|
|
76790
76938
|
audioUrl,
|
|
@@ -76827,7 +76975,7 @@ function useRenderClipContent({
|
|
|
76827
76975
|
}
|
|
76828
76976
|
if (compSrc) {
|
|
76829
76977
|
return createElement3(CompositionThumbnail, {
|
|
76830
|
-
previewUrl: `/
|
|
76978
|
+
previewUrl: buildProjectApiPath(pid, `/preview/comp/${encodePreviewPath(compSrc)}`),
|
|
76831
76979
|
label: "",
|
|
76832
76980
|
labelColor: style.label,
|
|
76833
76981
|
seekTime: 0,
|
|
@@ -76887,7 +77035,7 @@ function useRenderClipContent({
|
|
|
76887
77035
|
}
|
|
76888
77036
|
if (htmlPreviewEligible) {
|
|
76889
77037
|
return createElement3(CompositionThumbnail, {
|
|
76890
|
-
previewUrl: `/
|
|
77038
|
+
previewUrl: buildProjectApiPath(pid, `/preview`),
|
|
76891
77039
|
label: "",
|
|
76892
77040
|
labelColor: style.label,
|
|
76893
77041
|
selector: el.selector,
|
|
@@ -77103,7 +77251,7 @@ function useLintModal(projectId, refreshKey) {
|
|
|
77103
77251
|
if (!projectId) return;
|
|
77104
77252
|
if (!opts?.background) setLinting(true);
|
|
77105
77253
|
try {
|
|
77106
|
-
const res = await fetch(`/
|
|
77254
|
+
const res = await fetch(buildProjectApiPath(projectId, `/lint`));
|
|
77107
77255
|
const data = await res.json();
|
|
77108
77256
|
const parsed = (data.findings ?? []).map(parseFinding);
|
|
77109
77257
|
if (opts?.background) {
|
|
@@ -77238,9 +77386,10 @@ function useCompositionContentLoader({
|
|
|
77238
77386
|
}) {
|
|
77239
77387
|
return useCallback137(
|
|
77240
77388
|
(comp) => {
|
|
77389
|
+
if (!projectId) return;
|
|
77241
77390
|
setActiveCompPath(comp.endsWith(".html") ? comp : null);
|
|
77242
77391
|
setEditingFile({ path: comp, content: null });
|
|
77243
|
-
fetch(`/
|
|
77392
|
+
fetch(buildProjectApiPath(projectId, `/files/${encodeURIComponent(comp)}`)).then(async (r) => {
|
|
77244
77393
|
if (!r.ok) throw new Error(`Failed to load ${comp} (${r.status})`);
|
|
77245
77394
|
return r.json();
|
|
77246
77395
|
}).then((data) => {
|
|
@@ -79314,7 +79463,7 @@ function CompCard({
|
|
|
79314
79463
|
setLivePreviewLoaded(false);
|
|
79315
79464
|
};
|
|
79316
79465
|
const name = comp.replace(/^compositions\//, "").replace(/\.html$/, "");
|
|
79317
|
-
const previewUrl = `/
|
|
79466
|
+
const previewUrl = buildProjectApiPath(projectId, `/preview/comp/${comp}`);
|
|
79318
79467
|
const thumbnailUrl2 = buildCompositionThumbnailUrl({
|
|
79319
79468
|
previewUrl,
|
|
79320
79469
|
seekTime: THUMBNAIL_SEEK_TIME_SECONDS,
|
|
@@ -80669,7 +80818,7 @@ var AssetsTab = memo40(function AssetsTab2({
|
|
|
80669
80818
|
useEffect121(() => {
|
|
80670
80819
|
if (manifest404Ref.current.has(projectId)) return;
|
|
80671
80820
|
let cancelled = false;
|
|
80672
|
-
fetch(`/
|
|
80821
|
+
fetch(buildProjectApiPath(projectId, `/preview/.media/manifest.jsonl`)).then((r) => {
|
|
80673
80822
|
if (!r.ok) {
|
|
80674
80823
|
manifest404Ref.current.add(projectId);
|
|
80675
80824
|
return "";
|
|
@@ -81683,7 +81832,7 @@ function MediaErrorPanel({ name, filePath }) {
|
|
|
81683
81832
|
] });
|
|
81684
81833
|
}
|
|
81685
81834
|
function MediaPreview({ projectId, filePath }) {
|
|
81686
|
-
const serveUrl = `/
|
|
81835
|
+
const serveUrl = buildProjectApiPath(projectId, `/preview/${filePath}`);
|
|
81687
81836
|
const name = filePath.split("/").pop() ?? filePath;
|
|
81688
81837
|
const [failedPath, setFailedPath] = useState131(null);
|
|
81689
81838
|
const failed2 = failedPath === filePath;
|
|
@@ -83360,7 +83509,7 @@ var RenderQueueItem = memo47(function RenderQueueItem2({
|
|
|
83360
83509
|
const [hovered, setHovered] = useState137(false);
|
|
83361
83510
|
const [videoReady, setVideoReady] = useState137(false);
|
|
83362
83511
|
const [confirmingDelete, setConfirmingDelete] = useState137(false);
|
|
83363
|
-
const fileSrc = `/
|
|
83512
|
+
const fileSrc = buildProjectApiPath(projectId, `/renders/file/${job.filename}`);
|
|
83364
83513
|
const handleOpen = useCallback157(() => {
|
|
83365
83514
|
window.open(fileSrc, "_blank");
|
|
83366
83515
|
}, [fileSrc]);
|
|
@@ -87894,7 +88043,7 @@ function FramePoster({
|
|
|
87894
88043
|
return /* @__PURE__ */ jsx208("div", { className: "flex h-full w-full items-center justify-center text-[11px] text-neutral-600", children: "Preview unavailable" });
|
|
87895
88044
|
}
|
|
87896
88045
|
let url = buildCompositionThumbnailUrl({
|
|
87897
|
-
previewUrl: `/
|
|
88046
|
+
previewUrl: buildProjectApiPath(projectId, `/preview/comp/${src}`),
|
|
87898
88047
|
seekTime: seconds,
|
|
87899
88048
|
duration: 0,
|
|
87900
88049
|
origin: window.location.origin,
|
|
@@ -89673,10 +89822,10 @@ function StudioApp() {
|
|
|
89673
89822
|
const renderClipContent = useRenderClipContent({
|
|
89674
89823
|
projectIdRef: fileManager.projectIdRef,
|
|
89675
89824
|
compIdToSrc,
|
|
89676
|
-
activePreviewUrl: activeCompPath ? `/
|
|
89825
|
+
activePreviewUrl: activeCompPath && projectId ? buildProjectApiPath(projectId, `/preview/comp/${activeCompPath}`) : null,
|
|
89677
89826
|
effectiveTimelineDuration
|
|
89678
89827
|
});
|
|
89679
|
-
const compositionDimensions = useCompositionDimensions();
|
|
89828
|
+
const compositionDimensions = useCompositionDimensions(previewIframeRef);
|
|
89680
89829
|
const { lintModal, linting, handleLint, closeLintModal, findingsByFile } = useLintModal(
|
|
89681
89830
|
projectId,
|
|
89682
89831
|
refreshKey
|