hyperframes 0.8.3 → 0.8.5
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/README.md +23 -1
- package/dist/cli.js +3421 -2107
- package/dist/hyperframe-runtime.js +25 -25
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +25 -25
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/skills/hyperframes-cli/SKILL.md +2 -2
- package/dist/skills/hyperframes-cli/references/preview-render.md +8 -6
- package/dist/studio/assets/{hyperframes-player-C-CeZlk1.js → hyperframes-player-DcM3fVcp.js} +1 -1
- package/dist/studio/assets/{index-B4X3myFN.js → index-Cx_UrhoW.js} +202 -202
- package/dist/studio/assets/{index-BSDQyOWB.js → index-Del6XWZj.js} +1 -1
- package/dist/studio/assets/{index-BU-aDh5r.js → index-DgJrvYGf.js} +1 -1
- package/dist/studio/{chunk-AZYHQC6V.js → chunk-ZALQ3CW7.js} +2 -2
- package/dist/studio/chunk-ZALQ3CW7.js.map +1 -0
- package/dist/studio/{domEditingLayers-7AMZ7GFI.js → domEditingLayers-XRVXRTNX.js} +2 -2
- package/dist/studio/index.html +1 -1
- package/dist/studio/index.js +240 -163
- package/dist/studio/index.js.map +1 -1
- package/dist/templates/_shared/AGENTS.md +9 -4
- package/dist/templates/_shared/CLAUDE.md +9 -4
- package/package.json +1 -1
- package/dist/studio/chunk-AZYHQC6V.js.map +0 -1
- /package/dist/studio/{domEditingLayers-7AMZ7GFI.js.map → domEditingLayers-XRVXRTNX.js.map} +0 -0
package/dist/studio/index.js
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
resolveDomEditSelection,
|
|
25
25
|
serializeDomEditTextFields,
|
|
26
26
|
setCompositionSourceMap
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-ZALQ3CW7.js";
|
|
28
28
|
import {
|
|
29
29
|
__export
|
|
30
30
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -21832,12 +21832,14 @@ function buildCompositionThumbnailUrl({
|
|
|
21832
21832
|
duration = 5,
|
|
21833
21833
|
selector,
|
|
21834
21834
|
selectorIndex,
|
|
21835
|
-
origin
|
|
21835
|
+
origin,
|
|
21836
|
+
output
|
|
21836
21837
|
}) {
|
|
21837
21838
|
const thumbnailBase = previewUrl.replace("/preview/comp/", "/thumbnail/").replace(/\/preview$/, "/thumbnail/index.html");
|
|
21838
21839
|
const thumbnailUrl2 = new URL(thumbnailBase, origin);
|
|
21839
21840
|
thumbnailUrl2.searchParams.set("t", (seekTime + duration / 2).toFixed(2));
|
|
21840
21841
|
thumbnailUrl2.searchParams.set("v", THUMBNAIL_URL_VERSION);
|
|
21842
|
+
if (output) thumbnailUrl2.searchParams.set("output", output);
|
|
21841
21843
|
if (selector) {
|
|
21842
21844
|
thumbnailUrl2.searchParams.set("selector", selector);
|
|
21843
21845
|
if (selectorIndex != null && selectorIndex > 0) {
|
|
@@ -23822,20 +23824,6 @@ var NLEPreview = memo19(function NLEPreview2({
|
|
|
23822
23824
|
document.addEventListener("wheel", handleWheel, { passive: false, capture: true });
|
|
23823
23825
|
return () => document.removeEventListener("wheel", handleWheel, { capture: true });
|
|
23824
23826
|
}, [applyZoom, applyPan]);
|
|
23825
|
-
useEffect27(() => {
|
|
23826
|
-
const viewport = viewportRef.current;
|
|
23827
|
-
if (!viewport) return;
|
|
23828
|
-
const handleDblClick = (event) => {
|
|
23829
|
-
if (isPreviewAtFit(zoomRef.current)) return;
|
|
23830
|
-
const rect = viewport.getBoundingClientRect();
|
|
23831
|
-
if (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom) {
|
|
23832
|
-
return;
|
|
23833
|
-
}
|
|
23834
|
-
applyZoom(DEFAULT_PREVIEW_ZOOM);
|
|
23835
|
-
};
|
|
23836
|
-
document.addEventListener("dblclick", handleDblClick, { capture: true });
|
|
23837
|
-
return () => document.removeEventListener("dblclick", handleDblClick, { capture: true });
|
|
23838
|
-
}, [applyZoom]);
|
|
23839
23827
|
useEffect27(() => {
|
|
23840
23828
|
const isInsideViewport = (clientX, clientY) => {
|
|
23841
23829
|
const viewport = viewportRef.current;
|
|
@@ -26425,7 +26413,7 @@ function resolveElementForOverlay(doc, sel, activeCompositionPath, cacheRef) {
|
|
|
26425
26413
|
|
|
26426
26414
|
// src/components/editor/marqueeCommit.ts
|
|
26427
26415
|
var MARQUEE_THRESHOLD_PX = 4;
|
|
26428
|
-
function
|
|
26416
|
+
function collectMarqueeCandidates(iframe, overlayEl, activeCompositionPath) {
|
|
26429
26417
|
const doc = iframe.contentDocument;
|
|
26430
26418
|
if (!doc) return [];
|
|
26431
26419
|
const root = doc.querySelector("[data-composition-id]") ?? doc.body;
|
|
@@ -26438,28 +26426,32 @@ function collectMarqueeHits(rect, iframe, overlayEl, activeCompositionPath) {
|
|
|
26438
26426
|
width: declW > 0 ? declW : rootEl.getBoundingClientRect().width || 1,
|
|
26439
26427
|
height: declH > 0 ? declH : rootEl.getBoundingClientRect().height || 1
|
|
26440
26428
|
};
|
|
26441
|
-
const
|
|
26429
|
+
const candidates = [];
|
|
26442
26430
|
for (const item of items) {
|
|
26443
26431
|
const el = item.element;
|
|
26444
26432
|
if (!isElementComputedVisible(el)) continue;
|
|
26445
26433
|
if (coversComposition(el.getBoundingClientRect(), viewport)) continue;
|
|
26446
26434
|
const overlayRect = toVisibleOverlayRect(overlayEl, iframe, el);
|
|
26447
26435
|
if (!overlayRect) continue;
|
|
26448
|
-
|
|
26449
|
-
|
|
26450
|
-
|
|
26451
|
-
|
|
26452
|
-
|
|
26453
|
-
|
|
26454
|
-
|
|
26455
|
-
|
|
26436
|
+
candidates.push({
|
|
26437
|
+
element: el,
|
|
26438
|
+
rect: {
|
|
26439
|
+
left: overlayRect.left,
|
|
26440
|
+
top: overlayRect.top,
|
|
26441
|
+
width: overlayRect.width,
|
|
26442
|
+
height: overlayRect.height
|
|
26443
|
+
}
|
|
26444
|
+
});
|
|
26456
26445
|
}
|
|
26457
|
-
return
|
|
26446
|
+
return candidates;
|
|
26447
|
+
}
|
|
26448
|
+
function hitsWithin(rect, candidates) {
|
|
26449
|
+
return candidates.filter((candidate) => rectsOverlap(rect, candidate.rect));
|
|
26458
26450
|
}
|
|
26459
|
-
async function runMarqueeIntersection(rect,
|
|
26451
|
+
async function runMarqueeIntersection(rect, candidates, activeCompositionPath) {
|
|
26460
26452
|
const isMasterView = !activeCompositionPath || activeCompositionPath === "index.html";
|
|
26461
26453
|
const hits = [];
|
|
26462
|
-
for (const { element } of
|
|
26454
|
+
for (const { element } of hitsWithin(rect, candidates)) {
|
|
26463
26455
|
const sel = await resolveDomEditSelection(element, {
|
|
26464
26456
|
activeCompositionPath,
|
|
26465
26457
|
isMasterView,
|
|
@@ -26473,13 +26465,15 @@ function useMarqueeGestures(deps) {
|
|
|
26473
26465
|
const marqueeRef = useRef45(null);
|
|
26474
26466
|
const [marqueeRect, setMarqueeRect] = useState29(null);
|
|
26475
26467
|
const [candidateRects, setCandidateRects] = useState29([]);
|
|
26468
|
+
const candidatesRef = useRef45(null);
|
|
26476
26469
|
const commitMarquee = useCallback43(
|
|
26477
26470
|
async (rect, additive) => {
|
|
26478
26471
|
const iframe = deps.iframeRef.current;
|
|
26479
26472
|
const overlay = deps.overlayRef.current;
|
|
26480
26473
|
if (!iframe || !overlay || !deps.onMarqueeSelectRef.current) return;
|
|
26481
26474
|
const acp = deps.activeCompositionPathRef.current ?? "index.html";
|
|
26482
|
-
const
|
|
26475
|
+
const candidates = candidatesRef.current ?? collectMarqueeCandidates(iframe, overlay, acp);
|
|
26476
|
+
const hits = await runMarqueeIntersection(rect, candidates, acp);
|
|
26483
26477
|
deps.onMarqueeSelectRef.current(hits, additive);
|
|
26484
26478
|
},
|
|
26485
26479
|
[deps.iframeRef, deps.overlayRef, deps.onMarqueeSelectRef, deps.activeCompositionPathRef]
|
|
@@ -26497,6 +26491,7 @@ function useMarqueeGestures(deps) {
|
|
|
26497
26491
|
const dy = m.currentY - m.startY;
|
|
26498
26492
|
if (Math.hypot(dx, dy) < MARQUEE_THRESHOLD_PX) return;
|
|
26499
26493
|
m.pastThreshold = true;
|
|
26494
|
+
candidatesRef.current = null;
|
|
26500
26495
|
}
|
|
26501
26496
|
const rect = {
|
|
26502
26497
|
left: Math.min(m.startX, m.currentX),
|
|
@@ -26509,7 +26504,8 @@ function useMarqueeGestures(deps) {
|
|
|
26509
26504
|
const overlay = deps.overlayRef.current;
|
|
26510
26505
|
if (iframe && overlay) {
|
|
26511
26506
|
const acp = deps.activeCompositionPathRef.current ?? "index.html";
|
|
26512
|
-
|
|
26507
|
+
candidatesRef.current ??= collectMarqueeCandidates(iframe, overlay, acp);
|
|
26508
|
+
setCandidateRects(hitsWithin(rect, candidatesRef.current).map((h) => h.rect));
|
|
26513
26509
|
}
|
|
26514
26510
|
return;
|
|
26515
26511
|
}
|
|
@@ -26541,6 +26537,7 @@ function useMarqueeGestures(deps) {
|
|
|
26541
26537
|
}
|
|
26542
26538
|
setMarqueeRect(null);
|
|
26543
26539
|
setCandidateRects([]);
|
|
26540
|
+
candidatesRef.current = null;
|
|
26544
26541
|
return;
|
|
26545
26542
|
}
|
|
26546
26543
|
deps.gestures.onPointerUp(event);
|
|
@@ -26552,6 +26549,7 @@ function useMarqueeGestures(deps) {
|
|
|
26552
26549
|
marqueeRef.current = null;
|
|
26553
26550
|
setMarqueeRect(null);
|
|
26554
26551
|
setCandidateRects([]);
|
|
26552
|
+
candidatesRef.current = null;
|
|
26555
26553
|
return;
|
|
26556
26554
|
}
|
|
26557
26555
|
deps.gestures.clearPointerState(deps.selectionRef);
|
|
@@ -26989,7 +26987,7 @@ function OffCanvasIndicators({
|
|
|
26989
26987
|
const selectOffCanvas = async () => {
|
|
26990
26988
|
const el = elements.current.get(r.key);
|
|
26991
26989
|
if (!el) return;
|
|
26992
|
-
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-
|
|
26990
|
+
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-XRVXRTNX.js");
|
|
26993
26991
|
const acp = activeCompositionPathRef.current ?? "index.html";
|
|
26994
26992
|
const sel = await resolveDomEditSelection2(el, {
|
|
26995
26993
|
activeCompositionPath: acp,
|
|
@@ -30590,9 +30588,14 @@ function observeDoc(doc, markDirty) {
|
|
|
30590
30588
|
});
|
|
30591
30589
|
return observer;
|
|
30592
30590
|
}
|
|
30591
|
+
var RECOMPUTE_INTERVAL_MS = 100;
|
|
30592
|
+
function rebuildDue(dirty, lastAt, now2) {
|
|
30593
|
+
return dirty && now2 - lastAt >= RECOMPUTE_INTERVAL_MS;
|
|
30594
|
+
}
|
|
30593
30595
|
function startOffCanvasIndicatorRefresh(options) {
|
|
30594
30596
|
let frame = 0;
|
|
30595
30597
|
let lastCompSig = "";
|
|
30598
|
+
let lastRecomputeAt = Number.NEGATIVE_INFINITY;
|
|
30596
30599
|
const markDirty = () => {
|
|
30597
30600
|
options.dirtyRef.current = true;
|
|
30598
30601
|
};
|
|
@@ -30621,7 +30624,9 @@ function startOffCanvasIndicatorRefresh(options) {
|
|
|
30621
30624
|
if (options.dirtyRef.current) clearIndicators(options);
|
|
30622
30625
|
return;
|
|
30623
30626
|
}
|
|
30624
|
-
|
|
30627
|
+
const now2 = performance.now();
|
|
30628
|
+
if (!rebuildDue(options.dirtyRef.current, lastRecomputeAt, now2)) return;
|
|
30629
|
+
lastRecomputeAt = now2;
|
|
30625
30630
|
options.dirtyRef.current = false;
|
|
30626
30631
|
recomputeOffCanvasIndicators(
|
|
30627
30632
|
iframe,
|
|
@@ -35368,35 +35373,52 @@ function useElementLifecycleOps({
|
|
|
35368
35373
|
commitDomEditPatchBatches,
|
|
35369
35374
|
onElementDeleted
|
|
35370
35375
|
}) {
|
|
35371
|
-
const
|
|
35376
|
+
const handleDomEditElementsDelete = useCallback51(
|
|
35372
35377
|
// fallow-ignore-next-line complexity
|
|
35373
|
-
async (
|
|
35378
|
+
async (selections) => {
|
|
35374
35379
|
const pid = projectIdRef.current;
|
|
35375
35380
|
if (!pid) return;
|
|
35376
|
-
const
|
|
35381
|
+
const [selection] = selections;
|
|
35382
|
+
if (!selection) return;
|
|
35383
|
+
const label = selections.length === 1 ? selection.label || selection.id || selection.selector || selection.tagName : `${selections.length} elements`;
|
|
35384
|
+
if (selections.length > 1) showToast(`Deleting ${label}...`, "info");
|
|
35377
35385
|
const targetPath = selection.sourceFile || activeCompPath || "index.html";
|
|
35386
|
+
const sameFile = selections.filter(
|
|
35387
|
+
(candidate) => (candidate.sourceFile || activeCompPath || "index.html") === targetPath
|
|
35388
|
+
);
|
|
35378
35389
|
try {
|
|
35379
35390
|
const originalContent = await readProjectFileContent(pid, targetPath);
|
|
35380
|
-
const
|
|
35381
|
-
if (!
|
|
35391
|
+
const patchTargets = sameFile.map((member) => buildDomEditPatchTarget(member));
|
|
35392
|
+
if (patchTargets.some((t) => !t.id && !t.selector && !t.hfId)) {
|
|
35382
35393
|
throw new Error("Selected element has no patchable target");
|
|
35383
35394
|
}
|
|
35384
|
-
|
|
35385
|
-
|
|
35386
|
-
|
|
35395
|
+
const hfIds = sameFile.map((member) => member.hfId).filter((hfId) => Boolean(hfId));
|
|
35396
|
+
if (onTrySdkDelete && hfIds.length === sameFile.length) {
|
|
35397
|
+
let allHandled = true;
|
|
35398
|
+
for (const hfId of hfIds) {
|
|
35399
|
+
const handled = await onTrySdkDelete(hfId, originalContent, targetPath);
|
|
35400
|
+
if (!cutoverCommittedOrThrow(handled)) {
|
|
35401
|
+
allHandled = false;
|
|
35402
|
+
break;
|
|
35403
|
+
}
|
|
35404
|
+
}
|
|
35405
|
+
if (allHandled) {
|
|
35387
35406
|
clearDomSelection();
|
|
35388
35407
|
usePlayerStore.getState().setSelectedElementId(null);
|
|
35389
|
-
showToast(
|
|
35408
|
+
showToast(
|
|
35409
|
+
`Deleted ${label}. Use Undo to restore ${sameFile.length === 1 ? "it" : "them"}.`,
|
|
35410
|
+
"info"
|
|
35411
|
+
);
|
|
35390
35412
|
return;
|
|
35391
35413
|
}
|
|
35392
35414
|
}
|
|
35393
35415
|
domEditSaveTimestampRef.current = Date.now();
|
|
35394
35416
|
const removeResponse = await fetch(
|
|
35395
|
-
`/api/projects/${pid}/file-mutations/remove-
|
|
35417
|
+
`/api/projects/${pid}/file-mutations/remove-elements/${encodeURIComponent(targetPath)}`,
|
|
35396
35418
|
{
|
|
35397
35419
|
method: "POST",
|
|
35398
35420
|
headers: { "Content-Type": "application/json", ...studioWriteHeaders() },
|
|
35399
|
-
body: JSON.stringify({
|
|
35421
|
+
body: JSON.stringify({ targets: patchTargets })
|
|
35400
35422
|
}
|
|
35401
35423
|
);
|
|
35402
35424
|
if (!removeResponse.ok) {
|
|
@@ -35406,6 +35428,10 @@ function useElementLifecycleOps({
|
|
|
35406
35428
|
);
|
|
35407
35429
|
}
|
|
35408
35430
|
const removeData = await removeResponse.json();
|
|
35431
|
+
if (!removeData.changed) {
|
|
35432
|
+
reloadPreview();
|
|
35433
|
+
throw new Error("Nothing to delete \u2014 the preview was out of date. Try again.");
|
|
35434
|
+
}
|
|
35409
35435
|
const patchedContent = typeof removeData.content === "string" ? removeData.content : originalContent;
|
|
35410
35436
|
await saveProjectFilesWithHistory({
|
|
35411
35437
|
projectId: pid,
|
|
@@ -35423,8 +35449,11 @@ function useElementLifecycleOps({
|
|
|
35423
35449
|
usePlayerStore.getState().setSelectedElementId(null);
|
|
35424
35450
|
forceReloadSdkSession?.();
|
|
35425
35451
|
reloadPreview();
|
|
35426
|
-
onElementDeleted?.(
|
|
35427
|
-
showToast(
|
|
35452
|
+
for (const member of sameFile) onElementDeleted?.(member);
|
|
35453
|
+
showToast(
|
|
35454
|
+
`Deleted ${label}. Use Undo to restore ${sameFile.length === 1 ? "it" : "them"}.`,
|
|
35455
|
+
"info"
|
|
35456
|
+
);
|
|
35428
35457
|
} catch (error) {
|
|
35429
35458
|
const message = error instanceof Error ? error.message : "Failed to delete element";
|
|
35430
35459
|
showToast(message);
|
|
@@ -35551,8 +35580,15 @@ function useElementLifecycleOps({
|
|
|
35551
35580
|
},
|
|
35552
35581
|
[commitDomEditPatchBatches, onReorderShadow]
|
|
35553
35582
|
);
|
|
35583
|
+
const handleDomEditElementDelete = useCallback51(
|
|
35584
|
+
async (selection) => {
|
|
35585
|
+
await handleDomEditElementsDelete([selection]);
|
|
35586
|
+
},
|
|
35587
|
+
[handleDomEditElementsDelete]
|
|
35588
|
+
);
|
|
35554
35589
|
return {
|
|
35555
35590
|
handleDomEditElementDelete,
|
|
35591
|
+
handleDomEditElementsDelete,
|
|
35556
35592
|
handleDomZIndexReorderCommit
|
|
35557
35593
|
};
|
|
35558
35594
|
}
|
|
@@ -37638,6 +37674,9 @@ function selectionIdsMatch(currentIds, selectedIds, currentAnchor, wantedAnchor)
|
|
|
37638
37674
|
}
|
|
37639
37675
|
return currentAnchor === wantedAnchor;
|
|
37640
37676
|
}
|
|
37677
|
+
function anchorIsOutsideSelection(anchor2, selectedIds) {
|
|
37678
|
+
return anchor2 !== null && !selectedIds.includes(anchor2);
|
|
37679
|
+
}
|
|
37641
37680
|
function useTimelineSelectionPreviewSync({
|
|
37642
37681
|
selectedElementId,
|
|
37643
37682
|
selectedElementIds,
|
|
@@ -37688,6 +37727,11 @@ function useTimelineSelectionPreviewSync({
|
|
|
37688
37727
|
return;
|
|
37689
37728
|
}
|
|
37690
37729
|
let cancelled = false;
|
|
37730
|
+
const warnSelectionMissingOnce = () => {
|
|
37731
|
+
if (missingSelectionKeyRef.current === selectedKey) return;
|
|
37732
|
+
missingSelectionKeyRef.current = selectedKey;
|
|
37733
|
+
onSelectionNotFound();
|
|
37734
|
+
};
|
|
37691
37735
|
const syncSelection = async () => {
|
|
37692
37736
|
const selections = [];
|
|
37693
37737
|
let resolvableCount = 0;
|
|
@@ -37700,9 +37744,9 @@ function useTimelineSelectionPreviewSync({
|
|
|
37700
37744
|
}
|
|
37701
37745
|
if (cancelled) return;
|
|
37702
37746
|
if (selections.length < resolvableCount) {
|
|
37703
|
-
|
|
37704
|
-
|
|
37705
|
-
|
|
37747
|
+
warnSelectionMissingOnce();
|
|
37748
|
+
if (anchorIsOutsideSelection(currentAnchor, selectedIds)) {
|
|
37749
|
+
applyDomSelection(null, { revealPanel: false, announce: false });
|
|
37706
37750
|
}
|
|
37707
37751
|
return;
|
|
37708
37752
|
}
|
|
@@ -39358,6 +39402,14 @@ import { resolveEditingSections } from "@hyperframes/core/editing";
|
|
|
39358
39402
|
|
|
39359
39403
|
// src/components/editor/propertyPanelMediaSection.tsx
|
|
39360
39404
|
import { useEffect as useEffect48, useState as useState47 } from "react";
|
|
39405
|
+
import {
|
|
39406
|
+
AUDIO_GAIN_FADER_MAX,
|
|
39407
|
+
AUDIO_GAIN_FADER_MIN,
|
|
39408
|
+
audioFaderPositionToGain,
|
|
39409
|
+
formatAudioGain,
|
|
39410
|
+
audioGainToFaderPosition,
|
|
39411
|
+
audioGainToText
|
|
39412
|
+
} from "@hyperframes/core/audio-gain";
|
|
39361
39413
|
import { Fragment as Fragment25, jsx as jsx83, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
39362
39414
|
function MediaSection({
|
|
39363
39415
|
projectDir,
|
|
@@ -39375,7 +39427,7 @@ function MediaSection({
|
|
|
39375
39427
|
const isVisualMedia = isVideo || isImage;
|
|
39376
39428
|
const el = element.element;
|
|
39377
39429
|
const volume = parseNumericValue(element.dataAttributes.volume ?? "") ?? 1;
|
|
39378
|
-
const
|
|
39430
|
+
const volumeFaderPosition = audioGainToFaderPosition(volume);
|
|
39379
39431
|
const mediaStart = Number.parseFloat(
|
|
39380
39432
|
element.dataAttributes["media-start"] ?? element.dataAttributes["playback-start"] ?? "0"
|
|
39381
39433
|
) || 0;
|
|
@@ -39557,14 +39609,14 @@ function MediaSection({
|
|
|
39557
39609
|
SliderControl,
|
|
39558
39610
|
{
|
|
39559
39611
|
trackName: "Volume",
|
|
39560
|
-
value:
|
|
39561
|
-
min:
|
|
39562
|
-
max:
|
|
39612
|
+
value: volumeFaderPosition,
|
|
39613
|
+
min: AUDIO_GAIN_FADER_MIN,
|
|
39614
|
+
max: AUDIO_GAIN_FADER_MAX,
|
|
39563
39615
|
step: 1,
|
|
39564
|
-
displayValue:
|
|
39565
|
-
formatDisplayValue: (next) =>
|
|
39616
|
+
displayValue: audioGainToText(volume),
|
|
39617
|
+
formatDisplayValue: (next) => audioGainToText(audioFaderPositionToGain(next)),
|
|
39566
39618
|
onCommit: (next) => {
|
|
39567
|
-
void onSetAttribute("volume",
|
|
39619
|
+
void onSetAttribute("volume", formatAudioGain(audioFaderPositionToGain(next)));
|
|
39568
39620
|
}
|
|
39569
39621
|
}
|
|
39570
39622
|
)
|
|
@@ -51435,6 +51487,14 @@ function FlatToggle({
|
|
|
51435
51487
|
}
|
|
51436
51488
|
|
|
51437
51489
|
// src/components/editor/propertyPanelFlatMediaSection.tsx
|
|
51490
|
+
import {
|
|
51491
|
+
AUDIO_GAIN_FADER_MAX as AUDIO_GAIN_FADER_MAX2,
|
|
51492
|
+
AUDIO_GAIN_FADER_MIN as AUDIO_GAIN_FADER_MIN2,
|
|
51493
|
+
audioFaderPositionToGain as audioFaderPositionToGain2,
|
|
51494
|
+
formatAudioGain as formatAudioGain2,
|
|
51495
|
+
audioGainToFaderPosition as audioGainToFaderPosition2,
|
|
51496
|
+
audioGainToText as audioGainToText2
|
|
51497
|
+
} from "@hyperframes/core/audio-gain";
|
|
51438
51498
|
import { Fragment as Fragment37, jsx as jsx131, jsxs as jsxs106 } from "react/jsx-runtime";
|
|
51439
51499
|
function FlatMediaSection({
|
|
51440
51500
|
projectDir,
|
|
@@ -51455,7 +51515,7 @@ function FlatMediaSection({
|
|
|
51455
51515
|
const isVisualMedia = isVideo || isImage;
|
|
51456
51516
|
const el = element.element;
|
|
51457
51517
|
const volume = parseNumericValue(element.dataAttributes.volume ?? "") ?? 1;
|
|
51458
|
-
const
|
|
51518
|
+
const volumeFaderPosition = audioGainToFaderPosition2(volume);
|
|
51459
51519
|
const mediaStart = Number.parseFloat(
|
|
51460
51520
|
element.dataAttributes["media-start"] ?? element.dataAttributes["playback-start"] ?? "0"
|
|
51461
51521
|
) || 0;
|
|
@@ -51598,13 +51658,14 @@ function FlatMediaSection({
|
|
|
51598
51658
|
FlatSlider,
|
|
51599
51659
|
{
|
|
51600
51660
|
label: "Volume",
|
|
51601
|
-
value:
|
|
51602
|
-
min:
|
|
51603
|
-
max:
|
|
51604
|
-
tier:
|
|
51605
|
-
displayValue:
|
|
51661
|
+
value: volumeFaderPosition,
|
|
51662
|
+
min: AUDIO_GAIN_FADER_MIN2,
|
|
51663
|
+
max: AUDIO_GAIN_FADER_MAX2,
|
|
51664
|
+
tier: volume === 1 ? "default" : "explicitCustom",
|
|
51665
|
+
displayValue: audioGainToText2(volume),
|
|
51606
51666
|
disabled: volumeAutomated,
|
|
51607
|
-
|
|
51667
|
+
centerTick: true,
|
|
51668
|
+
onCommit: (next) => void onSetAttribute("volume", formatAudioGain2(audioFaderPositionToGain2(next)))
|
|
51608
51669
|
}
|
|
51609
51670
|
) }),
|
|
51610
51671
|
/* @__PURE__ */ jsx131(
|
|
@@ -61820,36 +61881,44 @@ function useTimelineEditing({
|
|
|
61820
61881
|
isRecordingRef,
|
|
61821
61882
|
forceReloadSdkSession
|
|
61822
61883
|
});
|
|
61823
|
-
const
|
|
61884
|
+
const handleTimelineElementsDelete = useCallback91(
|
|
61824
61885
|
// fallow-ignore-next-line complexity
|
|
61825
|
-
async (
|
|
61886
|
+
async (selection) => {
|
|
61826
61887
|
if (isRecordingRef?.current) {
|
|
61827
61888
|
showToast("Cannot edit timeline while recording", "error");
|
|
61828
61889
|
return;
|
|
61829
61890
|
}
|
|
61830
61891
|
const pid = projectIdRef.current;
|
|
61831
61892
|
if (!pid) throw new Error("No active project");
|
|
61832
|
-
const
|
|
61893
|
+
const [element] = selection;
|
|
61894
|
+
if (!element) return;
|
|
61895
|
+
const label = selection.length === 1 ? getTimelineElementLabel(element) : `${selection.length} clips`;
|
|
61833
61896
|
const targetPath = element.sourceFile || activeCompPath || "index.html";
|
|
61897
|
+
const sameFile = selection.filter(
|
|
61898
|
+
(candidate) => (candidate.sourceFile || activeCompPath || "index.html") === targetPath
|
|
61899
|
+
);
|
|
61834
61900
|
try {
|
|
61835
61901
|
const originalContent = await readFileContent(pid, targetPath);
|
|
61836
|
-
|
|
61837
|
-
|
|
61838
|
-
|
|
61839
|
-
|
|
61840
|
-
|
|
61841
|
-
`/api/projects/${pid}/file-mutations/remove-element/${encodeURIComponent(targetPath)}`,
|
|
61842
|
-
{
|
|
61843
|
-
method: "POST",
|
|
61844
|
-
headers: { "Content-Type": "application/json", ...studioWriteHeaders() },
|
|
61845
|
-
body: JSON.stringify({ target: patchTarget })
|
|
61902
|
+
let removedContent = originalContent;
|
|
61903
|
+
for (const target of sameFile) {
|
|
61904
|
+
const patchTarget = buildPatchTarget(target);
|
|
61905
|
+
if (!patchTarget) {
|
|
61906
|
+
throw new Error(`Timeline element ${target.id} is missing a patchable target`);
|
|
61846
61907
|
}
|
|
61847
|
-
|
|
61848
|
-
|
|
61849
|
-
|
|
61908
|
+
const removeResponse = await fetch(
|
|
61909
|
+
`/api/projects/${pid}/file-mutations/remove-element/${encodeURIComponent(targetPath)}`,
|
|
61910
|
+
{
|
|
61911
|
+
method: "POST",
|
|
61912
|
+
headers: { "Content-Type": "application/json", ...studioWriteHeaders() },
|
|
61913
|
+
body: JSON.stringify({ target: patchTarget })
|
|
61914
|
+
}
|
|
61915
|
+
);
|
|
61916
|
+
if (!removeResponse.ok) {
|
|
61917
|
+
throw new Error(`Failed to delete ${target.id} from ${targetPath}`);
|
|
61918
|
+
}
|
|
61919
|
+
const removeData = await removeResponse.json();
|
|
61920
|
+
if (typeof removeData.content === "string") removedContent = removeData.content;
|
|
61850
61921
|
}
|
|
61851
|
-
const removeData = await removeResponse.json();
|
|
61852
|
-
const removedContent = typeof removeData.content === "string" ? removeData.content : originalContent;
|
|
61853
61922
|
const deleteContentEnd = furthestClipEndFromSource(removedContent);
|
|
61854
61923
|
const patchedContent = setCompositionDurationToContent(removedContent, deleteContentEnd);
|
|
61855
61924
|
const rollbackDuration = captureDurationRollback(previewIframeRef.current);
|
|
@@ -61874,13 +61943,16 @@ function useTimelineEditing({
|
|
|
61874
61943
|
rollbackDuration();
|
|
61875
61944
|
throw error;
|
|
61876
61945
|
}
|
|
61877
|
-
|
|
61878
|
-
|
|
61879
|
-
);
|
|
61946
|
+
const deletedKeys = new Set(sameFile.map((te) => te.key ?? te.id));
|
|
61947
|
+
usePlayerStore.getState().setElements(timelineElements.filter((te) => !deletedKeys.has(te.key ?? te.id)));
|
|
61880
61948
|
usePlayerStore.getState().setSelectedElementId(null);
|
|
61949
|
+
usePlayerStore.getState().setSelectedElementIds(/* @__PURE__ */ new Set());
|
|
61881
61950
|
forceReloadSdkSession?.();
|
|
61882
61951
|
reloadPreview();
|
|
61883
|
-
showToast(
|
|
61952
|
+
showToast(
|
|
61953
|
+
`Deleted ${label}. Use Undo to restore ${sameFile.length === 1 ? "it" : "them"}.`,
|
|
61954
|
+
"info"
|
|
61955
|
+
);
|
|
61884
61956
|
} catch (error) {
|
|
61885
61957
|
const message = error instanceof Error ? error.message : "Failed to delete timeline clip";
|
|
61886
61958
|
showToast(message);
|
|
@@ -61899,6 +61971,12 @@ function useTimelineEditing({
|
|
|
61899
61971
|
previewIframeRef
|
|
61900
61972
|
]
|
|
61901
61973
|
);
|
|
61974
|
+
const handleTimelineElementDelete = useCallback91(
|
|
61975
|
+
async (element) => {
|
|
61976
|
+
await handleTimelineElementsDelete([element]);
|
|
61977
|
+
},
|
|
61978
|
+
[handleTimelineElementsDelete]
|
|
61979
|
+
);
|
|
61902
61980
|
const { handleTimelineAssetDrop, handleTimelineFileDrop, handleTimelineCompositionDrop } = useTimelineAssetDropOps({
|
|
61903
61981
|
projectIdRef,
|
|
61904
61982
|
activeCompPath,
|
|
@@ -61940,6 +62018,7 @@ function useTimelineEditing({
|
|
|
61940
62018
|
handleToggleTrackHidden,
|
|
61941
62019
|
handleToggleElementHidden,
|
|
61942
62020
|
handleTimelineElementDelete,
|
|
62021
|
+
handleTimelineElementsDelete,
|
|
61943
62022
|
handleTimelineElementSplit: handleRazorSplit,
|
|
61944
62023
|
handleRazorSplit,
|
|
61945
62024
|
handleRazorSplitAll,
|
|
@@ -62341,7 +62420,7 @@ function useDomSelection({
|
|
|
62341
62420
|
domEditGroupSelectionsRef.current = [];
|
|
62342
62421
|
setDomEditSelection(null);
|
|
62343
62422
|
setDomEditGroupSelections([]);
|
|
62344
|
-
announceTimelineSelection2([], null);
|
|
62423
|
+
if (options?.announce !== false) announceTimelineSelection2([], null);
|
|
62345
62424
|
return;
|
|
62346
62425
|
}
|
|
62347
62426
|
const isAdditiveSelection = Boolean(options?.additive);
|
|
@@ -62487,7 +62566,11 @@ function useDomSelection({
|
|
|
62487
62566
|
}
|
|
62488
62567
|
const selection = await buildDomSelectionForTimelineElement(element);
|
|
62489
62568
|
if (seq !== timelineSelectSeqRef.current) return;
|
|
62490
|
-
if (selection)
|
|
62569
|
+
if (selection) {
|
|
62570
|
+
applyDomSelection(selection);
|
|
62571
|
+
return;
|
|
62572
|
+
}
|
|
62573
|
+
applyDomSelection(null, { revealPanel: false, announce: false });
|
|
62491
62574
|
},
|
|
62492
62575
|
[applyDomSelection, buildDomSelectionForTimelineElement]
|
|
62493
62576
|
);
|
|
@@ -64463,7 +64546,7 @@ function useDomEditCommits({
|
|
|
64463
64546
|
showToast,
|
|
64464
64547
|
commitPositionPatchToHtml
|
|
64465
64548
|
});
|
|
64466
|
-
const { handleDomEditElementDelete, handleDomZIndexReorderCommit } = useElementLifecycleOps({
|
|
64549
|
+
const { handleDomEditElementDelete, handleDomEditElementsDelete, handleDomZIndexReorderCommit } = useElementLifecycleOps({
|
|
64467
64550
|
activeCompPath,
|
|
64468
64551
|
showToast,
|
|
64469
64552
|
writeProjectFile,
|
|
@@ -64496,6 +64579,7 @@ function useDomEditCommits({
|
|
|
64496
64579
|
handleDomRotationCommit,
|
|
64497
64580
|
handleDomManualEditsReset,
|
|
64498
64581
|
handleDomEditElementDelete,
|
|
64582
|
+
handleDomEditElementsDelete,
|
|
64499
64583
|
handleDomZIndexReorderCommit
|
|
64500
64584
|
};
|
|
64501
64585
|
}
|
|
@@ -66051,7 +66135,7 @@ function useDomEditPreviewSync({
|
|
|
66051
66135
|
refreshDomEditGroupSelectionsFromPreview,
|
|
66052
66136
|
buildDomSelectionFromTarget,
|
|
66053
66137
|
refreshPreviewDocumentVersion,
|
|
66054
|
-
|
|
66138
|
+
syncPreviewHotkeys,
|
|
66055
66139
|
applyStudioManualEditsToPreviewRef,
|
|
66056
66140
|
openSourceForSelection,
|
|
66057
66141
|
getSidebarTab,
|
|
@@ -66090,12 +66174,12 @@ function useDomEditPreviewSync({
|
|
|
66090
66174
|
applyDomSelection(nextSelection, { revealPanel: false, preserveGroup: true });
|
|
66091
66175
|
}
|
|
66092
66176
|
};
|
|
66093
|
-
|
|
66177
|
+
syncPreviewHotkeys(previewIframe);
|
|
66094
66178
|
void applyStudioManualEditsToPreviewRef.current(previewIframe);
|
|
66095
66179
|
void syncSelectionFromDocument();
|
|
66096
66180
|
refreshPreviewDocumentVersion();
|
|
66097
66181
|
const handleLoad = () => {
|
|
66098
|
-
|
|
66182
|
+
syncPreviewHotkeys(previewIframe);
|
|
66099
66183
|
void applyStudioManualEditsToPreviewRef.current(previewIframe);
|
|
66100
66184
|
void syncSelectionFromDocument();
|
|
66101
66185
|
refreshPreviewDocumentVersion();
|
|
@@ -66114,7 +66198,7 @@ function useDomEditPreviewSync({
|
|
|
66114
66198
|
previewIframe,
|
|
66115
66199
|
refreshDomEditGroupSelectionsFromPreview,
|
|
66116
66200
|
refreshPreviewDocumentVersion,
|
|
66117
|
-
|
|
66201
|
+
syncPreviewHotkeys,
|
|
66118
66202
|
applyStudioManualEditsToPreviewRef,
|
|
66119
66203
|
gsapCacheVersion
|
|
66120
66204
|
]);
|
|
@@ -66522,7 +66606,7 @@ function useDomEditWiring({
|
|
|
66522
66606
|
bumpGsapCache,
|
|
66523
66607
|
showToast,
|
|
66524
66608
|
refreshPreviewDocumentVersion,
|
|
66525
|
-
|
|
66609
|
+
syncPreviewHotkeys,
|
|
66526
66610
|
applyStudioManualEditsToPreviewRef,
|
|
66527
66611
|
applyDomSelection,
|
|
66528
66612
|
buildDomSelectionFromTarget,
|
|
@@ -66633,7 +66717,7 @@ function useDomEditWiring({
|
|
|
66633
66717
|
refreshDomEditGroupSelectionsFromPreview,
|
|
66634
66718
|
buildDomSelectionFromTarget,
|
|
66635
66719
|
refreshPreviewDocumentVersion,
|
|
66636
|
-
|
|
66720
|
+
syncPreviewHotkeys,
|
|
66637
66721
|
applyStudioManualEditsToPreviewRef,
|
|
66638
66722
|
openSourceForSelection,
|
|
66639
66723
|
getSidebarTab,
|
|
@@ -67849,6 +67933,9 @@ function useKeyframeEaseCommits({
|
|
|
67849
67933
|
}
|
|
67850
67934
|
|
|
67851
67935
|
// src/hooks/useDomEditSession.ts
|
|
67936
|
+
function membersForDelete(selection, group, options) {
|
|
67937
|
+
return options?.expandGroup && group.length > 0 ? group : [selection];
|
|
67938
|
+
}
|
|
67852
67939
|
function useDomEditSession({
|
|
67853
67940
|
projectId,
|
|
67854
67941
|
activeCompPath,
|
|
@@ -67863,6 +67950,7 @@ function useDomEditSession({
|
|
|
67863
67950
|
setRightCollapsed,
|
|
67864
67951
|
setRightPanelTab,
|
|
67865
67952
|
showToast,
|
|
67953
|
+
isRecordingRef,
|
|
67866
67954
|
refreshPreviewDocumentVersion,
|
|
67867
67955
|
queueDomEditSave,
|
|
67868
67956
|
readProjectFile,
|
|
@@ -67879,7 +67967,7 @@ function useDomEditSession({
|
|
|
67879
67967
|
previewDocumentVersion,
|
|
67880
67968
|
rightPanelTab,
|
|
67881
67969
|
applyStudioManualEditsToPreviewRef,
|
|
67882
|
-
|
|
67970
|
+
syncPreviewHotkeys,
|
|
67883
67971
|
reloadPreview,
|
|
67884
67972
|
setRefreshKey: _setRefreshKey,
|
|
67885
67973
|
openSourceForSelection,
|
|
@@ -68006,7 +68094,7 @@ function useDomEditSession({
|
|
|
68006
68094
|
handleDomRemoveTextField,
|
|
68007
68095
|
handleDomBoxSizeCommit,
|
|
68008
68096
|
handleDomManualEditsReset,
|
|
68009
|
-
|
|
68097
|
+
handleDomEditElementsDelete,
|
|
68010
68098
|
handleDomZIndexReorderCommit
|
|
68011
68099
|
} = useDomEditCommits({
|
|
68012
68100
|
activeCompPath,
|
|
@@ -68080,6 +68168,17 @@ function useDomEditSession({
|
|
|
68080
68168
|
clearDomSelection,
|
|
68081
68169
|
forceReloadSdkSession
|
|
68082
68170
|
});
|
|
68171
|
+
const handleDomEditElementDelete = useCallback114(
|
|
68172
|
+
async (selection, options) => {
|
|
68173
|
+
if (isRecordingRef?.current) {
|
|
68174
|
+
showToast("Cannot edit timeline while recording", "error");
|
|
68175
|
+
return;
|
|
68176
|
+
}
|
|
68177
|
+
const members = membersForDelete(selection, domEditGroupSelectionsRef.current, options);
|
|
68178
|
+
await handleDomEditElementsDelete(members);
|
|
68179
|
+
},
|
|
68180
|
+
[domEditGroupSelectionsRef, handleDomEditElementsDelete, isRecordingRef, showToast]
|
|
68181
|
+
);
|
|
68083
68182
|
const handleGroupSelection = useCallback114(() => {
|
|
68084
68183
|
const group = domEditGroupSelectionsRef.current;
|
|
68085
68184
|
const single = domEditSelectionRef.current;
|
|
@@ -68143,7 +68242,7 @@ function useDomEditSession({
|
|
|
68143
68242
|
bumpGsapCache,
|
|
68144
68243
|
showToast,
|
|
68145
68244
|
refreshPreviewDocumentVersion,
|
|
68146
|
-
|
|
68245
|
+
syncPreviewHotkeys,
|
|
68147
68246
|
applyStudioManualEditsToPreviewRef,
|
|
68148
68247
|
applyDomSelection,
|
|
68149
68248
|
buildDomSelectionFromTarget,
|
|
@@ -69437,21 +69536,19 @@ function dispatchPlainKey(event, key2, cb) {
|
|
|
69437
69536
|
return;
|
|
69438
69537
|
}
|
|
69439
69538
|
}
|
|
69539
|
+
const domSel = cb.domEditSelectionRef.current;
|
|
69540
|
+
if (domSel) {
|
|
69541
|
+
event.preventDefault();
|
|
69542
|
+
void cb.handleDomEditElementDelete(domSel, { expandGroup: true });
|
|
69543
|
+
return;
|
|
69544
|
+
}
|
|
69440
69545
|
const { selectedElementId, selectedElementIds, elements } = usePlayerStore.getState();
|
|
69441
69546
|
const selectionKeys = new Set(selectedElementIds);
|
|
69442
69547
|
if (selectedElementId) selectionKeys.add(selectedElementId);
|
|
69443
|
-
|
|
69444
|
-
|
|
69445
|
-
if (el) {
|
|
69446
|
-
event.preventDefault();
|
|
69447
|
-
void cb.handleTimelineElementDelete(el);
|
|
69448
|
-
return;
|
|
69449
|
-
}
|
|
69450
|
-
}
|
|
69451
|
-
const domSel = cb.domEditSelectionRef.current;
|
|
69452
|
-
if (domSel) {
|
|
69548
|
+
const selected = elements.filter((e) => selectionKeys.has(e.key ?? e.id));
|
|
69549
|
+
if (selected.length > 0) {
|
|
69453
69550
|
event.preventDefault();
|
|
69454
|
-
void cb.
|
|
69551
|
+
void cb.handleTimelineElementsDelete(selected);
|
|
69455
69552
|
}
|
|
69456
69553
|
return;
|
|
69457
69554
|
}
|
|
@@ -69461,7 +69558,7 @@ function dispatchPlainKey(event, key2, cb) {
|
|
|
69461
69558
|
}
|
|
69462
69559
|
}
|
|
69463
69560
|
function useAppHotkeys({
|
|
69464
|
-
|
|
69561
|
+
handleTimelineElementsDelete,
|
|
69465
69562
|
handleTimelineElementSplit,
|
|
69466
69563
|
handleDomEditElementDelete,
|
|
69467
69564
|
domEditSelectionRef,
|
|
@@ -69486,7 +69583,6 @@ function useAppHotkeys({
|
|
|
69486
69583
|
activeCompPath,
|
|
69487
69584
|
forceReloadSdkSession
|
|
69488
69585
|
}) {
|
|
69489
|
-
const previewHotkeyWindowRef = useRef126(null);
|
|
69490
69586
|
const previewHistoryCleanupRef = useRef126(null);
|
|
69491
69587
|
const readHistoryFile = useCallback119(
|
|
69492
69588
|
(path) => path === STUDIO_MOTION_PATH ? readOptionalProjectFile(path) : readProjectFile(path),
|
|
@@ -69545,7 +69641,7 @@ function useAppHotkeys({
|
|
|
69545
69641
|
const handleRedo = useCallback119(() => applyHistory("redo"), [applyHistory]);
|
|
69546
69642
|
const cbRef = useRef126(null);
|
|
69547
69643
|
cbRef.current = {
|
|
69548
|
-
|
|
69644
|
+
handleTimelineElementsDelete,
|
|
69549
69645
|
handleTimelineElementSplit,
|
|
69550
69646
|
handleDomEditElementDelete,
|
|
69551
69647
|
handleUndo,
|
|
@@ -69575,31 +69671,6 @@ function useAppHotkeys({
|
|
|
69575
69671
|
window.addEventListener("keydown", handleAppKeyDown, true);
|
|
69576
69672
|
return () => window.removeEventListener("keydown", handleAppKeyDown, true);
|
|
69577
69673
|
}, [handleAppKeyDown]);
|
|
69578
|
-
const syncPreviewTimelineHotkey = useCallback119(
|
|
69579
|
-
(iframe) => {
|
|
69580
|
-
const nextWindow = iframeContentWindow(iframe);
|
|
69581
|
-
if (previewHotkeyWindowRef.current === nextWindow) return;
|
|
69582
|
-
safeRemoveListener(
|
|
69583
|
-
previewHotkeyWindowRef.current,
|
|
69584
|
-
"keydown",
|
|
69585
|
-
handleAppKeyDown
|
|
69586
|
-
);
|
|
69587
|
-
previewHotkeyWindowRef.current = nextWindow;
|
|
69588
|
-
safeAddListener(nextWindow, "keydown", handleAppKeyDown, true);
|
|
69589
|
-
},
|
|
69590
|
-
[handleAppKeyDown]
|
|
69591
|
-
);
|
|
69592
|
-
useEffect99(
|
|
69593
|
-
() => () => {
|
|
69594
|
-
safeRemoveListener(
|
|
69595
|
-
previewHotkeyWindowRef.current,
|
|
69596
|
-
"keydown",
|
|
69597
|
-
handleAppKeyDown
|
|
69598
|
-
);
|
|
69599
|
-
previewHotkeyWindowRef.current = null;
|
|
69600
|
-
},
|
|
69601
|
-
[handleAppKeyDown]
|
|
69602
|
-
);
|
|
69603
69674
|
const handleHistoryHotkey = useCallback119((event) => {
|
|
69604
69675
|
if (!(event.metaKey || event.ctrlKey) || shouldIgnoreHistoryShortcut(event.target)) return;
|
|
69605
69676
|
handleUndoRedoKey(
|
|
@@ -69608,7 +69679,7 @@ function useAppHotkeys({
|
|
|
69608
69679
|
() => void cbRef.current.handleRedo()
|
|
69609
69680
|
);
|
|
69610
69681
|
}, []);
|
|
69611
|
-
const
|
|
69682
|
+
const syncPreviewHotkeys = useCallback119(
|
|
69612
69683
|
(iframe) => {
|
|
69613
69684
|
previewHistoryCleanupRef.current?.();
|
|
69614
69685
|
previewHistoryCleanupRef.current = null;
|
|
@@ -69621,14 +69692,17 @@ function useAppHotkeys({
|
|
|
69621
69692
|
}
|
|
69622
69693
|
if (!win && !doc) return;
|
|
69623
69694
|
const handler = handleHistoryHotkey;
|
|
69695
|
+
const appHandler = handleAppKeyDown;
|
|
69624
69696
|
safeAddListener(win, "keydown", handler, true);
|
|
69697
|
+
safeAddListener(win, "keydown", appHandler, true);
|
|
69625
69698
|
doc?.addEventListener("keydown", handleHistoryHotkey, true);
|
|
69626
69699
|
previewHistoryCleanupRef.current = () => {
|
|
69627
69700
|
safeRemoveListener(win, "keydown", handler);
|
|
69701
|
+
safeRemoveListener(win, "keydown", appHandler);
|
|
69628
69702
|
doc?.removeEventListener("keydown", handleHistoryHotkey, true);
|
|
69629
69703
|
};
|
|
69630
69704
|
},
|
|
69631
|
-
[handleHistoryHotkey]
|
|
69705
|
+
[handleAppKeyDown, handleHistoryHotkey]
|
|
69632
69706
|
);
|
|
69633
69707
|
useEffect99(
|
|
69634
69708
|
() => () => {
|
|
@@ -69640,8 +69714,7 @@ function useAppHotkeys({
|
|
|
69640
69714
|
return {
|
|
69641
69715
|
handleUndo,
|
|
69642
69716
|
handleRedo,
|
|
69643
|
-
|
|
69644
|
-
syncPreviewHistoryHotkey
|
|
69717
|
+
syncPreviewHotkeys
|
|
69645
69718
|
};
|
|
69646
69719
|
}
|
|
69647
69720
|
|
|
@@ -71207,7 +71280,7 @@ function findUrlSelectionElement(doc, target, fallbackSourceFile, activeCompPath
|
|
|
71207
71280
|
}
|
|
71208
71281
|
async function buildOptionalDomSelection(element, buildDomSelection) {
|
|
71209
71282
|
if (!element) return null;
|
|
71210
|
-
return buildDomSelection(element, { preferClipAncestor: false });
|
|
71283
|
+
return buildDomSelection(element, { preferClipAncestor: false, skipSourceProbe: true });
|
|
71211
71284
|
}
|
|
71212
71285
|
async function resolveUrlSelections({
|
|
71213
71286
|
doc,
|
|
@@ -75568,6 +75641,7 @@ function getVisibleLayers(layers, collapsed) {
|
|
|
75568
75641
|
|
|
75569
75642
|
// src/components/editor/LayersPanel.tsx
|
|
75570
75643
|
import { jsx as jsx175, jsxs as jsxs145 } from "react/jsx-runtime";
|
|
75644
|
+
var LAYERS_PANEL_MAX_ROWS = 80;
|
|
75571
75645
|
var TAG_ICONS = {
|
|
75572
75646
|
video: "Vi",
|
|
75573
75647
|
audio: "Au",
|
|
@@ -75652,11 +75726,13 @@ var LayersPanel = memo43(function LayersPanel2() {
|
|
|
75652
75726
|
const root = doc.querySelector("[data-composition-id]") ?? doc.documentElement ?? null;
|
|
75653
75727
|
if (!root) return;
|
|
75654
75728
|
if (activeGroupElement && !activeGroupElement.isConnected) setActiveGroupElement(null);
|
|
75655
|
-
const items = collectDomEditLayerItems(
|
|
75656
|
-
|
|
75657
|
-
isMasterView,
|
|
75658
|
-
|
|
75659
|
-
|
|
75729
|
+
const items = collectDomEditLayerItems(
|
|
75730
|
+
root,
|
|
75731
|
+
{ activeCompositionPath: activeCompPath, isMasterView, activeGroupElement },
|
|
75732
|
+
// How many rows this panel is willing to render, nothing more. Hit-testing
|
|
75733
|
+
// callers deliberately take the whole document instead.
|
|
75734
|
+
LAYERS_PANEL_MAX_ROWS
|
|
75735
|
+
);
|
|
75660
75736
|
setLayers(sortLayersByZIndex(items));
|
|
75661
75737
|
}, [previewIframeRef, activeCompPath, isMasterView, activeGroupElement, setActiveGroupElement]);
|
|
75662
75738
|
useEffect114(() => {
|
|
@@ -80959,11 +81035,11 @@ function FramePoster({
|
|
|
80959
81035
|
src,
|
|
80960
81036
|
seconds,
|
|
80961
81037
|
title,
|
|
80962
|
-
|
|
81038
|
+
surface = "tile",
|
|
80963
81039
|
posterVersion
|
|
80964
81040
|
}) {
|
|
80965
81041
|
const [failed2, setFailed] = useState140(false);
|
|
80966
|
-
useEffect126(() => setFailed(false), [src, seconds, posterVersion]);
|
|
81042
|
+
useEffect126(() => setFailed(false), [src, seconds, posterVersion, surface]);
|
|
80967
81043
|
if (failed2) {
|
|
80968
81044
|
return /* @__PURE__ */ jsx195("div", { className: "flex h-full w-full items-center justify-center text-[11px] text-neutral-600", children: "Preview unavailable" });
|
|
80969
81045
|
}
|
|
@@ -80971,7 +81047,11 @@ function FramePoster({
|
|
|
80971
81047
|
previewUrl: `/api/projects/${projectId}/preview/comp/${src}`,
|
|
80972
81048
|
seekTime: seconds,
|
|
80973
81049
|
duration: 0,
|
|
80974
|
-
origin: window.location.origin
|
|
81050
|
+
origin: window.location.origin,
|
|
81051
|
+
// The normal 240x135 preview is unreadable in the contact sheet, while source
|
|
81052
|
+
// density is unbounded across all tiles. Give tiles a capped review density
|
|
81053
|
+
// and reserve true source output for the single focus hero.
|
|
81054
|
+
output: surface === "hero" ? "source" : "storyboard"
|
|
80975
81055
|
});
|
|
80976
81056
|
if (posterVersion) {
|
|
80977
81057
|
const withVersion = new URL(url, window.location.origin);
|
|
@@ -80986,7 +81066,7 @@ function FramePoster({
|
|
|
80986
81066
|
draggable: false,
|
|
80987
81067
|
loading: "lazy",
|
|
80988
81068
|
onError: () => setFailed(true),
|
|
80989
|
-
className: `h-full w-full ${
|
|
81069
|
+
className: `h-full w-full ${surface === "hero" ? "object-contain" : "object-cover"}`
|
|
80990
81070
|
}
|
|
80991
81071
|
);
|
|
80992
81072
|
}
|
|
@@ -81507,7 +81587,7 @@ function StoryboardFrameFocus({
|
|
|
81507
81587
|
src: frame.src,
|
|
81508
81588
|
seconds: posterTime(frame),
|
|
81509
81589
|
title,
|
|
81510
|
-
|
|
81590
|
+
surface: "hero",
|
|
81511
81591
|
posterVersion
|
|
81512
81592
|
}
|
|
81513
81593
|
) : /* @__PURE__ */ jsx201(FramePlan, { frame }) }) }),
|
|
@@ -82607,11 +82687,9 @@ function StudioApp() {
|
|
|
82607
82687
|
const clearDomSelectionRef = useRef157(() => {
|
|
82608
82688
|
});
|
|
82609
82689
|
const domEditSelectionBridgeRef = useRef157(null);
|
|
82610
|
-
const handleDomEditElementDeleteRef = useRef157(
|
|
82611
|
-
|
|
82612
|
-
|
|
82613
|
-
);
|
|
82614
|
-
const domEditDeleteBridge = (s) => handleDomEditElementDeleteRef.current(s);
|
|
82690
|
+
const handleDomEditElementDeleteRef = useRef157(async () => {
|
|
82691
|
+
});
|
|
82692
|
+
const domEditDeleteBridge = (s, o) => handleDomEditElementDeleteRef.current(s, o);
|
|
82615
82693
|
const resetKeyframesRef = useRef157(() => false);
|
|
82616
82694
|
const deleteSelectedKeyframesRef = useRef157(() => {
|
|
82617
82695
|
});
|
|
@@ -82629,7 +82707,7 @@ function StudioApp() {
|
|
|
82629
82707
|
previewIframeRef
|
|
82630
82708
|
});
|
|
82631
82709
|
const appHotkeys = useAppHotkeys({
|
|
82632
|
-
|
|
82710
|
+
handleTimelineElementsDelete: timelineEditing.handleTimelineElementsDelete,
|
|
82633
82711
|
handleTimelineElementSplit: timelineEditing.handleTimelineElementSplit,
|
|
82634
82712
|
handleDomEditElementDelete: domEditDeleteBridge,
|
|
82635
82713
|
domEditSelectionRef: domEditSelectionBridgeRef,
|
|
@@ -82673,6 +82751,7 @@ function StudioApp() {
|
|
|
82673
82751
|
setRightCollapsed: panelLayout.setRightCollapsed,
|
|
82674
82752
|
setRightPanelTab: panelLayout.setRightPanelTab,
|
|
82675
82753
|
showToast,
|
|
82754
|
+
isRecordingRef: isGestureRecordingRef,
|
|
82676
82755
|
refreshPreviewDocumentVersion,
|
|
82677
82756
|
queueDomEditSave: previewPersistence.queueDomEditSave,
|
|
82678
82757
|
readProjectFile: fileManager.readProjectFile,
|
|
@@ -82689,7 +82768,7 @@ function StudioApp() {
|
|
|
82689
82768
|
previewDocumentVersion,
|
|
82690
82769
|
rightPanelTab: panelLayout.rightPanelTab,
|
|
82691
82770
|
applyStudioManualEditsToPreviewRef: previewPersistence.applyStudioManualEditsToPreviewRef,
|
|
82692
|
-
|
|
82771
|
+
syncPreviewHotkeys: appHotkeys.syncPreviewHotkeys,
|
|
82693
82772
|
reloadPreview,
|
|
82694
82773
|
setRefreshKey,
|
|
82695
82774
|
openSourceForSelection: fileManager.openSourceForSelection,
|
|
@@ -82755,7 +82834,6 @@ function StudioApp() {
|
|
|
82755
82834
|
isGestureRecordingRef
|
|
82756
82835
|
});
|
|
82757
82836
|
handleToggleRecordingRef.current = handleToggleRecording;
|
|
82758
|
-
const recordingToggle = handleToggleRecording;
|
|
82759
82837
|
const canvasRectRef = useRef157(null);
|
|
82760
82838
|
useLayoutEffect9(() => {
|
|
82761
82839
|
if (gestureState !== "recording" || !previewIframe) {
|
|
@@ -82768,8 +82846,7 @@ function StudioApp() {
|
|
|
82768
82846
|
(iframe) => {
|
|
82769
82847
|
previewIframeRef.current = iframe;
|
|
82770
82848
|
setPreviewIframe(iframe);
|
|
82771
|
-
appHotkeys.
|
|
82772
|
-
appHotkeys.syncPreviewHistoryHotkey(iframe);
|
|
82849
|
+
appHotkeys.syncPreviewHotkeys(iframe);
|
|
82773
82850
|
resetConsoleErrors();
|
|
82774
82851
|
refreshPreviewDocumentVersion();
|
|
82775
82852
|
},
|
|
@@ -82920,7 +82997,7 @@ function StudioApp() {
|
|
|
82920
82997
|
},
|
|
82921
82998
|
recordingState: gestureState,
|
|
82922
82999
|
recordingDuration: gestureRecording.recordingDuration,
|
|
82923
|
-
onToggleRecording:
|
|
83000
|
+
onToggleRecording: handleToggleRecording,
|
|
82924
83001
|
sdkSession: sdkHandle.session,
|
|
82925
83002
|
publishSdkSession: sdkHandle.publish,
|
|
82926
83003
|
forceReloadSdkSession: sdkHandle.forceReload,
|
|
@@ -82954,7 +83031,7 @@ function StudioApp() {
|
|
|
82954
83031
|
shouldShowSelectedDomBounds,
|
|
82955
83032
|
isGestureRecording: gestureState === "recording",
|
|
82956
83033
|
recordingState: gestureState,
|
|
82957
|
-
onToggleRecording:
|
|
83034
|
+
onToggleRecording: handleToggleRecording,
|
|
82958
83035
|
blockPreview,
|
|
82959
83036
|
gestureOverlay: gestureState === "recording" && previewIframe ? /* @__PURE__ */ jsx206(
|
|
82960
83037
|
GestureTrailOverlay,
|