hyperframes 0.8.78 → 0.8.79
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/cli.js +1071 -523
- package/dist/fontLocalizeCli.js +99 -33
- package/dist/hyperframe-runtime.js +54 -54
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +54 -54
- package/dist/hyperframes-player.global.js +3 -3
- package/dist/skills/media-use/scripts/compatibility.test.mjs +2 -0
- package/dist/skills/media-use/scripts/lib/cache.mjs +6 -8
- package/dist/skills/media-use/scripts/lib/candidates.test.mjs +2 -2
- package/dist/skills/media-use/scripts/lib/manifest.test.mjs +2 -0
- package/dist/skills/media-use/scripts/lib/media-home.mjs +20 -0
- package/dist/skills/media-use/scripts/lib/media-home.test.mjs +61 -0
- package/dist/skills/media-use/scripts/lib/misses.mjs +6 -6
- package/dist/skills/media-use/scripts/lib/misses.test.mjs +12 -1
- package/dist/skills/media-use/scripts/lib/prefs-store.mjs +2 -2
- package/dist/skills/media-use/scripts/lib/prefs-store.test.mjs +1 -1
- package/dist/skills/media-use/scripts/lib/recipe-store.mjs +2 -2
- package/dist/skills/media-use/scripts/lib/recipe-store.test.mjs +1 -1
- package/dist/skills/media-use/scripts/lib/stats.test.mjs +1 -1
- package/dist/skills/media-use/scripts/lib/telemetry.mjs +2 -1
- package/dist/skills/media-use/scripts/lib/telemetry.test.mjs +1 -0
- package/dist/studio/assets/{hyperframes-player-BdnQGwG5.js → hyperframes-player-Bx_Kw4Ey.js} +3 -3
- package/dist/studio/assets/{index-C_n__Uh3.js → index-CJP92F4-.js} +1 -1
- package/dist/studio/assets/{index-CX_4MYbk.js → index-DBKySIo7.js} +187 -187
- package/dist/studio/assets/{index-DdpuHaGN.js → index-ORZXYB0k.js} +1 -1
- package/dist/studio/{chunk-5VANA2TG.js → chunk-I7XNAIOF.js} +2 -1
- package/dist/studio/{domEditingLayers-IGPLTI5E.js → domEditingLayers-MHFDKAQ7.js} +2 -2
- package/dist/studio/index.d.ts +22 -15
- package/dist/studio/index.html +1 -1
- package/dist/studio/index.js +452 -256
- package/dist/studio/index.js.map +1 -1
- package/package.json +1 -1
- /package/dist/studio/{chunk-5VANA2TG.js.map → chunk-I7XNAIOF.js.map} +0 -0
- /package/dist/studio/{domEditingLayers-IGPLTI5E.js.map → domEditingLayers-MHFDKAQ7.js.map} +0 -0
package/dist/studio/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
getDomEditTargetKey,
|
|
22
22
|
getDomLayerPatchTarget,
|
|
23
23
|
getSelectorIndex,
|
|
24
|
+
getSourceFileForElement,
|
|
24
25
|
getSourceScopedSelectorIndex,
|
|
25
26
|
isElementComputedVisible,
|
|
26
27
|
isElementVisibleThroughAncestors,
|
|
@@ -34,7 +35,7 @@ import {
|
|
|
34
35
|
resolveDomEditSelection,
|
|
35
36
|
serializeDomEditTextFields,
|
|
36
37
|
setCompositionSourceMap
|
|
37
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-I7XNAIOF.js";
|
|
38
39
|
import {
|
|
39
40
|
__export
|
|
40
41
|
} from "./chunk-PZ5AY32C.js";
|
|
@@ -4179,6 +4180,7 @@ var Player = forwardRef3(
|
|
|
4179
4180
|
}
|
|
4180
4181
|
player.setAttribute("shader-capture-scale", "1");
|
|
4181
4182
|
player.setAttribute("shader-loading", "player");
|
|
4183
|
+
player.setAttribute("low-power-idle", "");
|
|
4182
4184
|
player.setAttribute("width", String(portrait ? 1080 : 1920));
|
|
4183
4185
|
player.setAttribute("height", String(portrait ? 1920 : 1080));
|
|
4184
4186
|
player.style.width = "100%";
|
|
@@ -22638,6 +22640,85 @@ async function saveProjectFilesWithHistory({
|
|
|
22638
22640
|
// src/utils/gsapSoftReload.ts
|
|
22639
22641
|
import { COLOR_GRADING_SOURCE_HIDDEN_ATTR as COLOR_GRADING_SOURCE_HIDDEN_ATTR2 } from "@hyperframes/core/color-grading";
|
|
22640
22642
|
|
|
22643
|
+
// src/utils/authoredSource.ts
|
|
22644
|
+
import { ensureHfIds, isCompositionTemplate } from "@hyperframes/parsers/hf-ids";
|
|
22645
|
+
function parseSavedSource(html2) {
|
|
22646
|
+
return new DOMParser().parseFromString(ensureHfIds(html2), "text/html");
|
|
22647
|
+
}
|
|
22648
|
+
var rootsByDoc = /* @__PURE__ */ new WeakMap();
|
|
22649
|
+
function searchRoots(root) {
|
|
22650
|
+
const templates = Array.from(root.querySelectorAll("template")).filter(isCompositionTemplate);
|
|
22651
|
+
return [root, ...templates.flatMap((template) => searchRoots(template.content))];
|
|
22652
|
+
}
|
|
22653
|
+
function findByAttribute(doc, name, value) {
|
|
22654
|
+
let roots = rootsByDoc.get(doc);
|
|
22655
|
+
if (!roots) rootsByDoc.set(doc, roots = searchRoots(doc));
|
|
22656
|
+
const selector = `[${name}="${value.replace(/["\\]/g, "\\$&")}"]`;
|
|
22657
|
+
for (const root of roots) {
|
|
22658
|
+
const match = root.querySelector(selector);
|
|
22659
|
+
if (match) return match;
|
|
22660
|
+
}
|
|
22661
|
+
return null;
|
|
22662
|
+
}
|
|
22663
|
+
function findAuthoredElement(doc, live) {
|
|
22664
|
+
const hfId = live.getAttribute("data-hf-id");
|
|
22665
|
+
if (hfId) return findByAttribute(doc, "data-hf-id", hfId);
|
|
22666
|
+
return live.id ? findByAttribute(doc, "id", live.id) : null;
|
|
22667
|
+
}
|
|
22668
|
+
function findAuthoredElementById(doc, live) {
|
|
22669
|
+
return live.id ? findByAttribute(doc, "id", live.id) : null;
|
|
22670
|
+
}
|
|
22671
|
+
var PATH_ATTRS = ["src", "href"];
|
|
22672
|
+
var CSS_URL = /\burl\(\s*(["']?)([^)"'\s](?:[^)"']*[^)"'\s])?)\1\s*\)/g;
|
|
22673
|
+
function isRelative(path) {
|
|
22674
|
+
return !!path && !/^(?:[a-z][a-z\d+.-]*:|\/|#)/i.test(path);
|
|
22675
|
+
}
|
|
22676
|
+
function toProjectPath(sourceFile, path) {
|
|
22677
|
+
const parts = sourceFile.split("/").slice(0, -1);
|
|
22678
|
+
for (const part of path.split("/")) {
|
|
22679
|
+
if (part === "..") parts.pop();
|
|
22680
|
+
else if (part !== "." && part !== "") parts.push(part);
|
|
22681
|
+
}
|
|
22682
|
+
return parts.join("/");
|
|
22683
|
+
}
|
|
22684
|
+
function livePathsOf(live) {
|
|
22685
|
+
const paths = /* @__PURE__ */ new Set();
|
|
22686
|
+
for (const el of [live, ...Array.from(live.querySelectorAll("*"))]) {
|
|
22687
|
+
for (const attr of PATH_ATTRS) paths.add(el.getAttribute(attr) ?? "");
|
|
22688
|
+
for (const match of (el.getAttribute("style") ?? "").matchAll(CSS_URL)) paths.add(match[2]);
|
|
22689
|
+
}
|
|
22690
|
+
return paths;
|
|
22691
|
+
}
|
|
22692
|
+
function authoredMarkup(authored, live, sourceFile) {
|
|
22693
|
+
if (!sourceFile.includes("/")) return authored.outerHTML;
|
|
22694
|
+
const livePaths = livePathsOf(live);
|
|
22695
|
+
const rebase = (path) => {
|
|
22696
|
+
if (!isRelative(path)) return path;
|
|
22697
|
+
const cut = path.search(/[?#]/);
|
|
22698
|
+
const suffix = cut < 0 ? "" : path.slice(cut);
|
|
22699
|
+
const rebased = toProjectPath(sourceFile, cut < 0 ? path : path.slice(0, cut)) + suffix;
|
|
22700
|
+
return path.startsWith("../") || livePaths.has(rebased) ? rebased : path;
|
|
22701
|
+
};
|
|
22702
|
+
const copy = authored.cloneNode(true);
|
|
22703
|
+
for (const el of [copy, ...Array.from(copy.querySelectorAll("*"))]) {
|
|
22704
|
+
for (const attr of PATH_ATTRS) {
|
|
22705
|
+
const value = el.getAttribute(attr);
|
|
22706
|
+
if (value) el.setAttribute(attr, rebase(value.trim()));
|
|
22707
|
+
}
|
|
22708
|
+
const style = el.getAttribute("style");
|
|
22709
|
+
if (style) {
|
|
22710
|
+
el.setAttribute(
|
|
22711
|
+
"style",
|
|
22712
|
+
style.replace(
|
|
22713
|
+
CSS_URL,
|
|
22714
|
+
(_, quote, url) => `url(${quote}${rebase(url)}${quote})`
|
|
22715
|
+
)
|
|
22716
|
+
);
|
|
22717
|
+
}
|
|
22718
|
+
}
|
|
22719
|
+
return copy.outerHTML;
|
|
22720
|
+
}
|
|
22721
|
+
|
|
22641
22722
|
// src/utils/authoredOpacity.ts
|
|
22642
22723
|
import { COLOR_GRADING_AUTHORED_OPACITY_ATTR } from "@hyperframes/core/color-grading";
|
|
22643
22724
|
function readStampedAuthoredOpacity(element) {
|
|
@@ -22751,15 +22832,12 @@ function applySoftReload(iframe, scriptText, options = {}) {
|
|
|
22751
22832
|
const findAuthoredSource = (el) => {
|
|
22752
22833
|
if (authoredDoc === void 0) {
|
|
22753
22834
|
try {
|
|
22754
|
-
authoredDoc = authoredHtml ?
|
|
22835
|
+
authoredDoc = authoredHtml ? parseSavedSource(authoredHtml) : null;
|
|
22755
22836
|
} catch {
|
|
22756
22837
|
authoredDoc = null;
|
|
22757
22838
|
}
|
|
22758
22839
|
}
|
|
22759
|
-
|
|
22760
|
-
const hfId = el.getAttribute("data-hf-id");
|
|
22761
|
-
if (hfId) return authoredDoc.querySelector(`[data-hf-id="${hfId}"]`);
|
|
22762
|
-
return el.id ? authoredDoc.getElementById(el.id) : null;
|
|
22840
|
+
return authoredDoc ? findAuthoredElement(authoredDoc, el) : null;
|
|
22763
22841
|
};
|
|
22764
22842
|
const readAuthoredOpacity = (el) => {
|
|
22765
22843
|
const source = findAuthoredSource(el);
|
|
@@ -26155,6 +26233,7 @@ async function decodeFrames(sink, timestamps, signal, resources) {
|
|
|
26155
26233
|
throwIfAborted(signal);
|
|
26156
26234
|
resources.urls.push(URL.createObjectURL(blob));
|
|
26157
26235
|
}
|
|
26236
|
+
throwIfAborted(signal);
|
|
26158
26237
|
}
|
|
26159
26238
|
function loadedResult(resources, aspect, width, height) {
|
|
26160
26239
|
const firstUrl = resources.urls[0];
|
|
@@ -26188,8 +26267,12 @@ async function decodeVideoThumbnail(request, signal, budgets = TIMELINE_VIEWPORT
|
|
|
26188
26267
|
}
|
|
26189
26268
|
const metadataDuration = await track2.getDurationFromMetadata({ skipLiveWait: true });
|
|
26190
26269
|
throwIfAborted(signal);
|
|
26191
|
-
const
|
|
26192
|
-
const
|
|
26270
|
+
const requestedStart = Math.max(0, request.sourceStart ?? 0);
|
|
26271
|
+
const sourceDuration = Math.max(
|
|
26272
|
+
0,
|
|
26273
|
+
metadataDuration ?? requestedStart + (request.sourceRangeDuration ?? 0)
|
|
26274
|
+
);
|
|
26275
|
+
const sourceStart = Math.min(requestedStart, sourceDuration);
|
|
26193
26276
|
const requestedDuration = request.sourceRangeDuration ?? Math.max(0, sourceDuration - sourceStart);
|
|
26194
26277
|
const duration = Math.min(
|
|
26195
26278
|
Math.max(0, requestedDuration),
|
|
@@ -26200,6 +26283,16 @@ async function decodeVideoThumbnail(request, signal, budgets = TIMELINE_VIEWPORT
|
|
|
26200
26283
|
duration,
|
|
26201
26284
|
Math.min(request.frameCount, budgets.richPreviewFrameCount)
|
|
26202
26285
|
);
|
|
26286
|
+
const keys = new mediabunny.EncodedPacketSink(track2);
|
|
26287
|
+
const maxKeyframeLead = duration / Math.max(2, timestamps.length - 1) / 2;
|
|
26288
|
+
async function* decodeTimesAtNearbyKeyframes() {
|
|
26289
|
+
for (const time of timestamps) {
|
|
26290
|
+
const key2 = await keys.getKeyPacket(time, { metadataOnly: true });
|
|
26291
|
+
if (signal.aborted) return;
|
|
26292
|
+
const near2 = key2 && key2.timestamp >= sourceStart && time - key2.timestamp <= maxKeyframeLead;
|
|
26293
|
+
yield near2 ? key2.timestamp : time;
|
|
26294
|
+
}
|
|
26295
|
+
}
|
|
26203
26296
|
const aspect = displayWidth / displayHeight;
|
|
26204
26297
|
const target = targetDimensions(aspect, budgets);
|
|
26205
26298
|
const sink = new mediabunny.CanvasSink(track2, {
|
|
@@ -26208,7 +26301,7 @@ async function decodeVideoThumbnail(request, signal, budgets = TIMELINE_VIEWPORT
|
|
|
26208
26301
|
fit: request.fit ?? "cover",
|
|
26209
26302
|
poolSize: 1
|
|
26210
26303
|
});
|
|
26211
|
-
await decodeFrames(sink,
|
|
26304
|
+
await decodeFrames(sink, decodeTimesAtNearbyKeyframes(), signal, resources);
|
|
26212
26305
|
return loadedResult(resources, aspect, target.width, target.height);
|
|
26213
26306
|
} catch (error) {
|
|
26214
26307
|
releaseDecodedResources(resources);
|
|
@@ -26398,7 +26491,7 @@ var VideoThumbnail = memo17(function VideoThumbnail2({
|
|
|
26398
26491
|
useMountEffect(() => () => observerRef.current?.disconnect());
|
|
26399
26492
|
return /* @__PURE__ */ jsxs59("div", { ref: setContainerRef, className: "absolute inset-0 overflow-hidden", children: [
|
|
26400
26493
|
urls.length > 0 && /* @__PURE__ */ jsx84("div", { className: "absolute inset-0 flex", children: Array.from({ length: frameCount }, (_, index) => {
|
|
26401
|
-
const src = urls[index
|
|
26494
|
+
const src = urls[Math.round(index * (urls.length - 1) / Math.max(1, frameCount - 1))];
|
|
26402
26495
|
return /* @__PURE__ */ jsx84(
|
|
26403
26496
|
"div",
|
|
26404
26497
|
{
|
|
@@ -28236,24 +28329,32 @@ function useTimelineSyncCallbacks({
|
|
|
28236
28329
|
if (initializeAdapter(context)) return;
|
|
28237
28330
|
const iframe = iframeRef.current;
|
|
28238
28331
|
let settled = false;
|
|
28332
|
+
let retryFrame = 0;
|
|
28333
|
+
const stopWaiting = () => {
|
|
28334
|
+
window.removeEventListener("message", onMessage);
|
|
28335
|
+
cancelAnimationFrame(retryFrame);
|
|
28336
|
+
};
|
|
28239
28337
|
const trySettle = () => {
|
|
28240
28338
|
if (settled) return;
|
|
28241
28339
|
if (initializeAdapter(context)) {
|
|
28242
28340
|
settled = true;
|
|
28243
|
-
|
|
28341
|
+
stopWaiting();
|
|
28244
28342
|
if (probeIntervalRef.current) clearInterval(probeIntervalRef.current);
|
|
28343
|
+
return;
|
|
28245
28344
|
}
|
|
28345
|
+
cancelAnimationFrame(retryFrame);
|
|
28346
|
+
retryFrame = requestAnimationFrame(trySettle);
|
|
28246
28347
|
};
|
|
28247
28348
|
const onMessage = (e) => {
|
|
28248
28349
|
if (isPreviewReadinessMessage(e, iframe)) trySettle();
|
|
28249
28350
|
};
|
|
28250
28351
|
window.addEventListener("message", onMessage);
|
|
28251
|
-
stopWaitingRef.current =
|
|
28352
|
+
stopWaitingRef.current = stopWaiting;
|
|
28252
28353
|
probeIntervalRef.current = setTimeout(() => {
|
|
28253
28354
|
if (!settled) {
|
|
28254
28355
|
trySettle();
|
|
28255
28356
|
}
|
|
28256
|
-
|
|
28357
|
+
stopWaiting();
|
|
28257
28358
|
if (!settled) onLoadGiveUp?.(context);
|
|
28258
28359
|
revealIframe(iframeRef.current);
|
|
28259
28360
|
}, 5e3);
|
|
@@ -29218,7 +29319,12 @@ function useTimelinePlayer({
|
|
|
29218
29319
|
pause,
|
|
29219
29320
|
seek
|
|
29220
29321
|
});
|
|
29221
|
-
const {
|
|
29322
|
+
const {
|
|
29323
|
+
processTimelineMessageRef,
|
|
29324
|
+
enrichMissingCompositionsRef,
|
|
29325
|
+
onIframeLoad,
|
|
29326
|
+
cancelPendingLoad
|
|
29327
|
+
} = useTimelineSyncCallbacks({
|
|
29222
29328
|
iframeRef,
|
|
29223
29329
|
probeIntervalRef,
|
|
29224
29330
|
pendingSeekRef,
|
|
@@ -29289,8 +29395,8 @@ function useTimelinePlayer({
|
|
|
29289
29395
|
applyPreviewVariablesToUrl(url);
|
|
29290
29396
|
beginShadowReload(url.toString());
|
|
29291
29397
|
}, [saveSeekPosition, getAdapter, beginShadowReload]);
|
|
29292
|
-
const
|
|
29293
|
-
|
|
29398
|
+
const pauseRef = useRef53(pause);
|
|
29399
|
+
pauseRef.current = pause;
|
|
29294
29400
|
useMountEffect(() => {
|
|
29295
29401
|
const handleWindowKeyDown = (e) => playbackKeyDownRef.current(e);
|
|
29296
29402
|
const handleWindowKeyUp = (e) => playbackKeyUpRef.current(e);
|
|
@@ -29303,14 +29409,7 @@ function useTimelinePlayer({
|
|
|
29303
29409
|
syncTimelineElements
|
|
29304
29410
|
});
|
|
29305
29411
|
const handleVisibilityChange = () => {
|
|
29306
|
-
if (document.hidden && usePlayerStore.getState().isPlaying)
|
|
29307
|
-
const adapter = getAdapterRef.current?.();
|
|
29308
|
-
if (adapter) {
|
|
29309
|
-
adapter.pause();
|
|
29310
|
-
setIsPlaying(false);
|
|
29311
|
-
stopRAFLoop();
|
|
29312
|
-
}
|
|
29313
|
-
}
|
|
29412
|
+
if (document.hidden && usePlayerStore.getState().isPlaying) pauseRef.current();
|
|
29314
29413
|
};
|
|
29315
29414
|
window.addEventListener("keydown", handleWindowKeyDown, true);
|
|
29316
29415
|
window.addEventListener("keyup", handleWindowKeyUp, true);
|
|
@@ -29327,15 +29426,15 @@ function useTimelinePlayer({
|
|
|
29327
29426
|
stopReverseLoop();
|
|
29328
29427
|
stopScrubPreviewAudio();
|
|
29329
29428
|
releaseStaticSeekCache(staticSeekAdapterRef, staticSeekWarnedRef);
|
|
29330
|
-
|
|
29429
|
+
cancelPendingLoad();
|
|
29331
29430
|
};
|
|
29332
29431
|
});
|
|
29333
29432
|
const resetPlayer = useCallback41(() => {
|
|
29334
29433
|
stopRAFLoop();
|
|
29335
29434
|
stopReverseLoop();
|
|
29336
|
-
|
|
29435
|
+
cancelPendingLoad();
|
|
29337
29436
|
usePlayerStore.getState().reset();
|
|
29338
|
-
}, [stopRAFLoop, stopReverseLoop]);
|
|
29437
|
+
}, [stopRAFLoop, stopReverseLoop, cancelPendingLoad]);
|
|
29339
29438
|
useEffect36(() => {
|
|
29340
29439
|
return usePlayerStore.subscribe((state, prev) => {
|
|
29341
29440
|
const playbackRateChanged = state.playbackRate !== prev.playbackRate;
|
|
@@ -34111,7 +34210,7 @@ function OffCanvasIndicators({
|
|
|
34111
34210
|
const selectOffCanvas = async () => {
|
|
34112
34211
|
const el = elements.current.get(r.key);
|
|
34113
34212
|
if (!el) return;
|
|
34114
|
-
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-
|
|
34213
|
+
const { resolveDomEditSelection: resolveDomEditSelection2 } = await import("./domEditingLayers-MHFDKAQ7.js");
|
|
34115
34214
|
const acp = activeCompositionPathRef.current ?? "index.html";
|
|
34116
34215
|
const sel = await resolveDomEditSelection2(el, {
|
|
34117
34216
|
activeCompositionPath: acp,
|
|
@@ -71667,7 +71766,43 @@ function useTimelineAssetDropOps({
|
|
|
71667
71766
|
}
|
|
71668
71767
|
|
|
71669
71768
|
// src/hooks/timelineAudioGroupVolume.ts
|
|
71670
|
-
import { useCallback as
|
|
71769
|
+
import { useCallback as useCallback107, useRef as useRef139 } from "react";
|
|
71770
|
+
|
|
71771
|
+
// src/hooks/timelineEditPermission.ts
|
|
71772
|
+
import { useCallback as useCallback106 } from "react";
|
|
71773
|
+
function projectForTimelineSave(isRecording, projectId, showToast) {
|
|
71774
|
+
if (isRecording) {
|
|
71775
|
+
showToast("Cannot edit timeline while recording", "error");
|
|
71776
|
+
return { status: "refused", reason: "Cannot edit timeline while recording" };
|
|
71777
|
+
}
|
|
71778
|
+
return projectId ?? { status: "failed", reason: "No project is open" };
|
|
71779
|
+
}
|
|
71780
|
+
function timelineEditRefusal(canEdit, targets) {
|
|
71781
|
+
for (const element of targets) {
|
|
71782
|
+
const verdict = canEdit?.(element) ?? true;
|
|
71783
|
+
if (verdict !== true) return verdict.reason;
|
|
71784
|
+
}
|
|
71785
|
+
return null;
|
|
71786
|
+
}
|
|
71787
|
+
function useTimelineEditRefusal(canEdit, showToast) {
|
|
71788
|
+
return useCallback106(
|
|
71789
|
+
(targets) => {
|
|
71790
|
+
const reason = timelineEditRefusal(canEdit, targets);
|
|
71791
|
+
if (reason !== null) showToast(reason, "error");
|
|
71792
|
+
return reason;
|
|
71793
|
+
},
|
|
71794
|
+
[canEdit, showToast]
|
|
71795
|
+
);
|
|
71796
|
+
}
|
|
71797
|
+
function useTimelineEditGate(canEdit, showToast) {
|
|
71798
|
+
const refuse = useTimelineEditRefusal(canEdit, showToast);
|
|
71799
|
+
return useCallback106(
|
|
71800
|
+
(targets) => refuse(targets) === null,
|
|
71801
|
+
[refuse]
|
|
71802
|
+
);
|
|
71803
|
+
}
|
|
71804
|
+
|
|
71805
|
+
// src/hooks/timelineAudioGroupVolume.ts
|
|
71671
71806
|
import { HF_AUDIO_FX_ATTR as HF_AUDIO_FX_ATTR8 } from "@hyperframes/core/audio-fx";
|
|
71672
71807
|
import { HF_AUDIO_AUTOMATION_ATTR as HF_AUDIO_AUTOMATION_ATTR5 } from "@hyperframes/core/audio-automation";
|
|
71673
71808
|
function patchLiveGroupAttribute(iframe, groupId, attr, value) {
|
|
@@ -71734,7 +71869,7 @@ async function setAudioGroupAttribute({
|
|
|
71734
71869
|
const groupEl = previewIframe?.contentDocument?.getElementById(groupId) ?? null;
|
|
71735
71870
|
const targetPath = resolveGroupSourceFile(groupEl) || activeCompPath || "index.html";
|
|
71736
71871
|
const patchTarget = buildPatchTarget({ domId: groupId });
|
|
71737
|
-
if (!patchTarget) return
|
|
71872
|
+
if (!patchTarget) return null;
|
|
71738
71873
|
return persistElementAttribute({
|
|
71739
71874
|
projectId,
|
|
71740
71875
|
targetPath,
|
|
@@ -71759,7 +71894,7 @@ function useSetAudioGroupAttribute({
|
|
|
71759
71894
|
isRecordingRef
|
|
71760
71895
|
}) {
|
|
71761
71896
|
const liveBeforeRef = useRef139(/* @__PURE__ */ new Map());
|
|
71762
|
-
const setLive =
|
|
71897
|
+
const setLive = useCallback107(
|
|
71763
71898
|
(groupId, attr, value) => {
|
|
71764
71899
|
const key2 = audioGroupAttributeLiveKey(groupId, attr);
|
|
71765
71900
|
const target = previewIframeRef.current?.contentDocument?.getElementById(groupId);
|
|
@@ -71771,7 +71906,7 @@ function useSetAudioGroupAttribute({
|
|
|
71771
71906
|
},
|
|
71772
71907
|
[previewIframeRef]
|
|
71773
71908
|
);
|
|
71774
|
-
const revertLive =
|
|
71909
|
+
const revertLive = useCallback107(
|
|
71775
71910
|
(groupId, attr) => {
|
|
71776
71911
|
const key2 = audioGroupAttributeLiveKey(groupId, attr);
|
|
71777
71912
|
if (!liveBeforeRef.current.has(key2)) return;
|
|
@@ -71790,16 +71925,12 @@ function useSetAudioGroupAttribute({
|
|
|
71790
71925
|
},
|
|
71791
71926
|
[previewIframeRef]
|
|
71792
71927
|
);
|
|
71793
|
-
const setQuiet =
|
|
71928
|
+
const setQuiet = useCallback107(
|
|
71794
71929
|
async (groupId, attr, value, label) => {
|
|
71795
|
-
|
|
71796
|
-
|
|
71797
|
-
return;
|
|
71798
|
-
}
|
|
71799
|
-
const pid = projectIdRef.current;
|
|
71800
|
-
if (!pid) return;
|
|
71930
|
+
const pid = projectForTimelineSave(isRecordingRef?.current, projectIdRef.current, showToast);
|
|
71931
|
+
if (typeof pid !== "string") return pid;
|
|
71801
71932
|
try {
|
|
71802
|
-
await setAudioGroupAttribute({
|
|
71933
|
+
const written = await setAudioGroupAttribute({
|
|
71803
71934
|
projectId: pid,
|
|
71804
71935
|
activeCompPath,
|
|
71805
71936
|
groupId,
|
|
@@ -71812,7 +71943,9 @@ function useSetAudioGroupAttribute({
|
|
|
71812
71943
|
pendingTimelineEditPathRef
|
|
71813
71944
|
});
|
|
71814
71945
|
liveBeforeRef.current.delete(audioGroupAttributeLiveKey(groupId, attr));
|
|
71946
|
+
if (!written) return { status: "failed", reason: "This group has no id to save it by" };
|
|
71815
71947
|
syncStoredGroupAttribute(groupId, attr, value);
|
|
71948
|
+
return { status: "saved" };
|
|
71816
71949
|
} catch (error) {
|
|
71817
71950
|
const live = previewIframeRef.current?.contentDocument?.getElementById(groupId);
|
|
71818
71951
|
syncStoredGroupAttribute(groupId, attr, live?.getAttribute(attr) ?? null);
|
|
@@ -71820,6 +71953,7 @@ function useSetAudioGroupAttribute({
|
|
|
71820
71953
|
const message = error instanceof Error ? error.message : "Failed to update group";
|
|
71821
71954
|
showToast(message);
|
|
71822
71955
|
liveBeforeRef.current.delete(audioGroupAttributeLiveKey(groupId, attr));
|
|
71956
|
+
return { status: "failed", reason: message };
|
|
71823
71957
|
}
|
|
71824
71958
|
},
|
|
71825
71959
|
[
|
|
@@ -71837,7 +71971,7 @@ function useSetAudioGroupAttribute({
|
|
|
71837
71971
|
}
|
|
71838
71972
|
|
|
71839
71973
|
// src/hooks/timelineElementFxAttribute.ts
|
|
71840
|
-
import { useCallback as
|
|
71974
|
+
import { useCallback as useCallback108, useRef as useRef140 } from "react";
|
|
71841
71975
|
function patchLiveElementAttribute(iframe, element, attr, value, activeCompPath) {
|
|
71842
71976
|
const target = findTimelineElementInIframe(iframe, element, activeCompPath);
|
|
71843
71977
|
if (!target) return;
|
|
@@ -71861,7 +71995,7 @@ async function setElementAttribute({
|
|
|
71861
71995
|
}) {
|
|
71862
71996
|
const targetPath = element.sourceFile || activeCompPath || "index.html";
|
|
71863
71997
|
const patchTarget = buildPatchTarget(element);
|
|
71864
|
-
if (!patchTarget) return
|
|
71998
|
+
if (!patchTarget) return null;
|
|
71865
71999
|
return persistElementAttribute({
|
|
71866
72000
|
projectId,
|
|
71867
72001
|
targetPath,
|
|
@@ -71886,7 +72020,7 @@ function useSetElementAttribute({
|
|
|
71886
72020
|
isRecordingRef
|
|
71887
72021
|
}) {
|
|
71888
72022
|
const liveBeforeRef = useRef140(/* @__PURE__ */ new Map());
|
|
71889
|
-
const setLive =
|
|
72023
|
+
const setLive = useCallback108(
|
|
71890
72024
|
(element, attr, value) => {
|
|
71891
72025
|
const key2 = elementAttributeLiveKey(element, activeCompPath, attr);
|
|
71892
72026
|
const target = findTimelineElementInIframe(previewIframeRef.current, element, activeCompPath);
|
|
@@ -71897,7 +72031,7 @@ function useSetElementAttribute({
|
|
|
71897
72031
|
},
|
|
71898
72032
|
[previewIframeRef, activeCompPath]
|
|
71899
72033
|
);
|
|
71900
|
-
const revertLive =
|
|
72034
|
+
const revertLive = useCallback108(
|
|
71901
72035
|
(element, attr) => {
|
|
71902
72036
|
const key2 = elementAttributeLiveKey(element, activeCompPath, attr);
|
|
71903
72037
|
if (!liveBeforeRef.current.has(key2)) return;
|
|
@@ -71912,16 +72046,13 @@ function useSetElementAttribute({
|
|
|
71912
72046
|
},
|
|
71913
72047
|
[previewIframeRef, activeCompPath]
|
|
71914
72048
|
);
|
|
71915
|
-
const setQuiet =
|
|
72049
|
+
const setQuiet = useCallback108(
|
|
71916
72050
|
async (element, attr, value, label) => {
|
|
71917
|
-
|
|
71918
|
-
|
|
71919
|
-
|
|
71920
|
-
}
|
|
71921
|
-
const pid = projectIdRef.current;
|
|
71922
|
-
if (!pid) return;
|
|
72051
|
+
const pid = projectForTimelineSave(isRecordingRef?.current, projectIdRef.current, showToast);
|
|
72052
|
+
if (typeof pid !== "string") return pid;
|
|
72053
|
+
const liveKey = elementAttributeLiveKey(element, activeCompPath, attr);
|
|
71923
72054
|
try {
|
|
71924
|
-
await setElementAttribute({
|
|
72055
|
+
const written = await setElementAttribute({
|
|
71925
72056
|
projectId: pid,
|
|
71926
72057
|
activeCompPath,
|
|
71927
72058
|
element,
|
|
@@ -71933,12 +72064,15 @@ function useSetElementAttribute({
|
|
|
71933
72064
|
recordEdit,
|
|
71934
72065
|
pendingTimelineEditPathRef
|
|
71935
72066
|
});
|
|
71936
|
-
liveBeforeRef.current.delete(
|
|
72067
|
+
liveBeforeRef.current.delete(liveKey);
|
|
72068
|
+
if (written) return { status: "saved" };
|
|
72069
|
+
return { status: "failed", reason: "This clip has no id to save it by" };
|
|
71937
72070
|
} catch (error) {
|
|
71938
72071
|
console.error("[Timeline] Failed to set element attribute", error);
|
|
71939
72072
|
const message = error instanceof Error ? error.message : "Failed to update effect";
|
|
71940
72073
|
showToast(message);
|
|
71941
|
-
liveBeforeRef.current.delete(
|
|
72074
|
+
liveBeforeRef.current.delete(liveKey);
|
|
72075
|
+
return { status: "failed", reason: message };
|
|
71942
72076
|
}
|
|
71943
72077
|
},
|
|
71944
72078
|
[
|
|
@@ -71956,7 +72090,7 @@ function useSetElementAttribute({
|
|
|
71956
72090
|
}
|
|
71957
72091
|
|
|
71958
72092
|
// src/hooks/useTimelineDeleteOps.ts
|
|
71959
|
-
import { useCallback as
|
|
72093
|
+
import { useCallback as useCallback109, useRef as useRef141 } from "react";
|
|
71960
72094
|
function applyRippleShifts(survivors, changes) {
|
|
71961
72095
|
if (!changes) return survivors;
|
|
71962
72096
|
const newStartByElement = new Map(changes.map((c) => [c.element, c.start]));
|
|
@@ -71980,7 +72114,7 @@ function useTimelineDeleteOps({
|
|
|
71980
72114
|
handleTimelineGroupMove
|
|
71981
72115
|
}) {
|
|
71982
72116
|
const rippleNoticeShownRef = useRef141(false);
|
|
71983
|
-
const handleTimelineElementsDelete =
|
|
72117
|
+
const handleTimelineElementsDelete = useCallback109(
|
|
71984
72118
|
// fallow-ignore-next-line complexity
|
|
71985
72119
|
async (selection) => {
|
|
71986
72120
|
if (isRecordingRef?.current) {
|
|
@@ -72113,7 +72247,7 @@ function useTimelineDeleteOps({
|
|
|
72113
72247
|
handleTimelineGroupMove
|
|
72114
72248
|
]
|
|
72115
72249
|
);
|
|
72116
|
-
const handleTimelineElementDelete =
|
|
72250
|
+
const handleTimelineElementDelete = useCallback109(
|
|
72117
72251
|
async (element) => {
|
|
72118
72252
|
await handleTimelineElementsDelete([element]);
|
|
72119
72253
|
},
|
|
@@ -72123,10 +72257,10 @@ function useTimelineDeleteOps({
|
|
|
72123
72257
|
}
|
|
72124
72258
|
|
|
72125
72259
|
// src/hooks/useTrackPendingTimelineEdit.ts
|
|
72126
|
-
import { useCallback as
|
|
72260
|
+
import { useCallback as useCallback110, useRef as useRef142 } from "react";
|
|
72127
72261
|
function useTrackPendingTimelineEdit() {
|
|
72128
72262
|
const wrappedRef = useRef142(/* @__PURE__ */ new WeakMap());
|
|
72129
|
-
return
|
|
72263
|
+
return useCallback110((fn) => {
|
|
72130
72264
|
const key2 = fn;
|
|
72131
72265
|
const cached5 = wrappedRef.current.get(key2);
|
|
72132
72266
|
if (cached5) return cached5;
|
|
@@ -72141,11 +72275,11 @@ function useTrackPendingTimelineEdit() {
|
|
|
72141
72275
|
}
|
|
72142
72276
|
|
|
72143
72277
|
// src/hooks/timelineAudioGroupCreate.ts
|
|
72144
|
-
import { useCallback as
|
|
72278
|
+
import { useCallback as useCallback112 } from "react";
|
|
72145
72279
|
import { HF_AUDIO_GROUP_ATTR as HF_AUDIO_GROUP_ATTR4, HF_AUDIO_GROUP_TAG as HF_AUDIO_GROUP_TAG6 } from "@hyperframes/core/audio-groups";
|
|
72146
72280
|
|
|
72147
72281
|
// src/hooks/timelineTrackVisibility.ts
|
|
72148
|
-
import { useCallback as
|
|
72282
|
+
import { useCallback as useCallback111 } from "react";
|
|
72149
72283
|
function getTimelineElementTargetPath(element, activeCompPath) {
|
|
72150
72284
|
return element.sourceFile || activeCompPath || "index.html";
|
|
72151
72285
|
}
|
|
@@ -72305,7 +72439,7 @@ function useTimelineTrackVisibilityEditing({
|
|
|
72305
72439
|
forceReloadSdkSession
|
|
72306
72440
|
}) {
|
|
72307
72441
|
const timelineElements = usePlayerStore((state) => state.elements);
|
|
72308
|
-
return
|
|
72442
|
+
return useCallback111(
|
|
72309
72443
|
async (track2, hidden, displayNumber) => {
|
|
72310
72444
|
if (isRecordingRef?.current) {
|
|
72311
72445
|
showToast("Cannot edit timeline while recording", "error");
|
|
@@ -72359,7 +72493,7 @@ function useTimelineElementVisibilityEditing({
|
|
|
72359
72493
|
forceReloadSdkSession
|
|
72360
72494
|
}) {
|
|
72361
72495
|
const timelineElements = usePlayerStore((state) => state.elements);
|
|
72362
|
-
return
|
|
72496
|
+
return useCallback111(
|
|
72363
72497
|
async (elementKey3, hidden) => {
|
|
72364
72498
|
if (isRecordingRef?.current) {
|
|
72365
72499
|
showToast("Cannot edit timeline while recording", "error");
|
|
@@ -72552,7 +72686,7 @@ function useAudioGroupCarveAssignment({
|
|
|
72552
72686
|
checkEditable
|
|
72553
72687
|
}) {
|
|
72554
72688
|
const timelineElements = usePlayerStore((state) => state.elements);
|
|
72555
|
-
return
|
|
72689
|
+
return useCallback112(
|
|
72556
72690
|
async (clipIds, groupId, groupLabel2) => {
|
|
72557
72691
|
if (isRecordingRef?.current) {
|
|
72558
72692
|
showToast("Cannot edit timeline while recording", "error");
|
|
@@ -72607,7 +72741,7 @@ function useAudioGroupCarveAssignment({
|
|
|
72607
72741
|
}
|
|
72608
72742
|
|
|
72609
72743
|
// src/hooks/useTimelineGroupEditing.ts
|
|
72610
|
-
import { useCallback as
|
|
72744
|
+
import { useCallback as useCallback113 } from "react";
|
|
72611
72745
|
function targetPathFor(element, activeCompPath) {
|
|
72612
72746
|
return element.sourceFile || activeCompPath || "index.html";
|
|
72613
72747
|
}
|
|
@@ -72646,7 +72780,7 @@ function useTimelineGroupEditing({
|
|
|
72646
72780
|
showToast,
|
|
72647
72781
|
writeProjectFile
|
|
72648
72782
|
}) {
|
|
72649
|
-
const enqueueGroupOperation =
|
|
72783
|
+
const enqueueGroupOperation = useCallback113(
|
|
72650
72784
|
(label, operation) => {
|
|
72651
72785
|
if (isRecordingRef?.current) {
|
|
72652
72786
|
showToast("Cannot edit timeline while recording", "error");
|
|
@@ -72665,7 +72799,7 @@ function useTimelineGroupEditing({
|
|
|
72665
72799
|
},
|
|
72666
72800
|
[editQueueRef, isRecordingRef, projectIdRef, showToast]
|
|
72667
72801
|
);
|
|
72668
|
-
const persistServerBatch =
|
|
72802
|
+
const persistServerBatch = useCallback113(
|
|
72669
72803
|
async (projectId, label, batchChanges, coalesceKey, coalesceMs) => {
|
|
72670
72804
|
await persistTimelineBatchEdit({
|
|
72671
72805
|
projectId,
|
|
@@ -72688,7 +72822,7 @@ function useTimelineGroupEditing({
|
|
|
72688
72822
|
writeProjectFile
|
|
72689
72823
|
]
|
|
72690
72824
|
);
|
|
72691
|
-
const trySdkBatchPersist =
|
|
72825
|
+
const trySdkBatchPersist = useCallback113(
|
|
72692
72826
|
async (input) => {
|
|
72693
72827
|
const sharedPath = allChangesSharePath(input.changes, activeCompPath);
|
|
72694
72828
|
const canUseSdk = !input.needsExtension && sharedPath !== null && input.eligible && input.sdkChanges.every((change) => change !== null);
|
|
@@ -72724,7 +72858,7 @@ function useTimelineGroupEditing({
|
|
|
72724
72858
|
writeProjectFile
|
|
72725
72859
|
]
|
|
72726
72860
|
);
|
|
72727
|
-
const handleTimelineGroupMove =
|
|
72861
|
+
const handleTimelineGroupMove = useCallback113(
|
|
72728
72862
|
(changes, options) => {
|
|
72729
72863
|
if (changes.length === 0) return Promise.resolve();
|
|
72730
72864
|
for (const change of changes) {
|
|
@@ -72818,7 +72952,7 @@ function useTimelineGroupEditing({
|
|
|
72818
72952
|
invalidateGsapCache
|
|
72819
72953
|
]
|
|
72820
72954
|
);
|
|
72821
|
-
const handleTimelineGroupResize =
|
|
72955
|
+
const handleTimelineGroupResize = useCallback113(
|
|
72822
72956
|
(changes, options) => {
|
|
72823
72957
|
if (changes.length === 0) return Promise.resolve();
|
|
72824
72958
|
for (const change of changes) {
|
|
@@ -72920,11 +73054,11 @@ function useTimelineGroupEditing({
|
|
|
72920
73054
|
}
|
|
72921
73055
|
|
|
72922
73056
|
// src/hooks/useBlockedTimelineEditToast.ts
|
|
72923
|
-
import { useCallback as
|
|
73057
|
+
import { useCallback as useCallback114, useRef as useRef143 } from "react";
|
|
72924
73058
|
var BLOCKED_TOAST_INTERVAL_MS = 1500;
|
|
72925
73059
|
function useBlockedTimelineEditToast(showToast) {
|
|
72926
73060
|
const lastAtRef = useRef143(0);
|
|
72927
|
-
return
|
|
73061
|
+
return useCallback114(
|
|
72928
73062
|
(_element) => {
|
|
72929
73063
|
const now2 = Date.now();
|
|
72930
73064
|
if (now2 - lastAtRef.current < BLOCKED_TOAST_INTERVAL_MS) return;
|
|
@@ -72935,25 +73069,6 @@ function useBlockedTimelineEditToast(showToast) {
|
|
|
72935
73069
|
);
|
|
72936
73070
|
}
|
|
72937
73071
|
|
|
72938
|
-
// src/hooks/timelineEditPermission.ts
|
|
72939
|
-
import { useCallback as useCallback114 } from "react";
|
|
72940
|
-
function useTimelineEditGate(canEdit, showToast) {
|
|
72941
|
-
return useCallback114(
|
|
72942
|
-
(targets) => {
|
|
72943
|
-
if (!canEdit) return true;
|
|
72944
|
-
for (const element of targets) {
|
|
72945
|
-
const verdict = canEdit(element);
|
|
72946
|
-
if (verdict !== true) {
|
|
72947
|
-
showToast(verdict.reason, "error");
|
|
72948
|
-
return false;
|
|
72949
|
-
}
|
|
72950
|
-
}
|
|
72951
|
-
return true;
|
|
72952
|
-
},
|
|
72953
|
-
[canEdit, showToast]
|
|
72954
|
-
);
|
|
72955
|
-
}
|
|
72956
|
-
|
|
72957
73072
|
// src/hooks/useTimelineEditing.ts
|
|
72958
73073
|
function useTimelineEditing({
|
|
72959
73074
|
projectId,
|
|
@@ -72980,8 +73095,9 @@ function useTimelineEditing({
|
|
|
72980
73095
|
const editQueueRef = useRef144(Promise.resolve());
|
|
72981
73096
|
const track2 = useTrackPendingTimelineEdit();
|
|
72982
73097
|
const checkEditable = useTimelineEditGate(canEdit, showToast);
|
|
72983
|
-
const
|
|
72984
|
-
|
|
73098
|
+
const refuseEdit = useTimelineEditRefusal(canEdit, showToast);
|
|
73099
|
+
const refuseEditRef = useRef144(refuseEdit);
|
|
73100
|
+
refuseEditRef.current = refuseEdit;
|
|
72985
73101
|
const guardedRef = useRef144(/* @__PURE__ */ new WeakMap());
|
|
72986
73102
|
const guard = useCallback115(
|
|
72987
73103
|
(resolveTargets, fn, onRefused) => {
|
|
@@ -72996,10 +73112,9 @@ function useTimelineEditing({
|
|
|
72996
73112
|
entry2.resolveTargets = resolveTargets;
|
|
72997
73113
|
entry2.onRefused = onRefused;
|
|
72998
73114
|
entry2.wrapped = ((...args) => {
|
|
72999
|
-
|
|
73000
|
-
|
|
73001
|
-
return Promise.resolve();
|
|
73002
|
-
}
|
|
73115
|
+
const reason = refuseEditRef.current(entry2.resolveTargets(...args));
|
|
73116
|
+
if (reason !== null)
|
|
73117
|
+
return Promise.resolve(entry2.onRefused?.(reason, ...args));
|
|
73003
73118
|
return fn(...args);
|
|
73004
73119
|
});
|
|
73005
73120
|
guardedRef.current.set(key2, entry2);
|
|
@@ -73340,6 +73455,22 @@ function useTimelineEditing({
|
|
|
73340
73455
|
isRecordingRef,
|
|
73341
73456
|
forceReloadSdkSession
|
|
73342
73457
|
});
|
|
73458
|
+
const refused = (reason) => ({ status: "refused", reason });
|
|
73459
|
+
const audioGroupMembers = (groupId) => {
|
|
73460
|
+
const state = usePlayerStore.getState();
|
|
73461
|
+
const flatMembers = state.elements.filter((el) => el.audioGroup === groupId);
|
|
73462
|
+
const domMembers = state.domClipChildren.filter((child) => child.audioGroup === groupId).map(
|
|
73463
|
+
(child) => ({
|
|
73464
|
+
id: child.id,
|
|
73465
|
+
domId: child.id,
|
|
73466
|
+
tag: "div",
|
|
73467
|
+
start: 0,
|
|
73468
|
+
duration: 0,
|
|
73469
|
+
track: -1
|
|
73470
|
+
})
|
|
73471
|
+
);
|
|
73472
|
+
return [...flatMembers, ...domMembers];
|
|
73473
|
+
};
|
|
73343
73474
|
const trackedRazorSplit = track2(guard((element) => [element], handleRazorSplit));
|
|
73344
73475
|
return {
|
|
73345
73476
|
handleTimelineElementMove: track2(guard((element) => [element], handleTimelineElementMove)),
|
|
@@ -73363,25 +73494,10 @@ function useTimelineEditing({
|
|
|
73363
73494
|
// (timelineAudioGroupVolume.ts): a sub-composition's group members have
|
|
73364
73495
|
// no flat twin, only a domClipChildren entry, so both are checked.
|
|
73365
73496
|
setQuiet: track2(
|
|
73366
|
-
guard(
|
|
73367
|
-
(groupId)
|
|
73368
|
-
|
|
73369
|
-
|
|
73370
|
-
const domMembers = state.domClipChildren.filter((child) => child.audioGroup === groupId).map(
|
|
73371
|
-
(child) => ({
|
|
73372
|
-
id: child.id,
|
|
73373
|
-
domId: child.id,
|
|
73374
|
-
tag: "div",
|
|
73375
|
-
start: 0,
|
|
73376
|
-
duration: 0,
|
|
73377
|
-
track: -1
|
|
73378
|
-
})
|
|
73379
|
-
);
|
|
73380
|
-
return [...flatMembers, ...domMembers];
|
|
73381
|
-
},
|
|
73382
|
-
setAudioGroupAttribute2.setQuiet,
|
|
73383
|
-
(groupId, attr) => revertAudioGroupLive(groupId, attr)
|
|
73384
|
-
)
|
|
73497
|
+
guard(audioGroupMembers, setAudioGroupAttribute2.setQuiet, (reason, groupId, attr) => {
|
|
73498
|
+
revertAudioGroupLive(groupId, attr);
|
|
73499
|
+
return refused(reason);
|
|
73500
|
+
})
|
|
73385
73501
|
)
|
|
73386
73502
|
},
|
|
73387
73503
|
setElementFxAttribute: {
|
|
@@ -73390,7 +73506,10 @@ function useTimelineEditing({
|
|
|
73390
73506
|
guard(
|
|
73391
73507
|
(element) => [element],
|
|
73392
73508
|
setElementFxAttribute.setQuiet,
|
|
73393
|
-
(element, attr) =>
|
|
73509
|
+
(reason, element, attr) => {
|
|
73510
|
+
revertElementFxLive(element, attr);
|
|
73511
|
+
return refused(reason);
|
|
73512
|
+
}
|
|
73394
73513
|
)
|
|
73395
73514
|
)
|
|
73396
73515
|
},
|
|
@@ -81603,7 +81722,7 @@ function clipLabel(verb, clipCount) {
|
|
|
81603
81722
|
function clipToast(verbPast, clipCount) {
|
|
81604
81723
|
return clipCount > 1 ? `${verbPast} ${clipCount} clips` : `${verbPast} clip`;
|
|
81605
81724
|
}
|
|
81606
|
-
function
|
|
81725
|
+
function getSelectedDomElement(iframeRef, selection, activeCompositionPath) {
|
|
81607
81726
|
let doc = null;
|
|
81608
81727
|
try {
|
|
81609
81728
|
doc = iframeRef.current?.contentDocument ?? null;
|
|
@@ -81611,7 +81730,21 @@ function getElementOuterHtml(iframeRef, selection, activeCompositionPath) {
|
|
|
81611
81730
|
return null;
|
|
81612
81731
|
}
|
|
81613
81732
|
if (!doc) return null;
|
|
81614
|
-
return findElementForSelection(doc, selection, activeCompositionPath)
|
|
81733
|
+
return findElementForSelection(doc, selection, activeCompositionPath);
|
|
81734
|
+
}
|
|
81735
|
+
function savedMarkupElseLive(saved2, live, sourceFile) {
|
|
81736
|
+
const authored = findAuthoredElement(saved2, live) ?? findAuthoredElementById(saved2, live);
|
|
81737
|
+
return authored ? authoredMarkup(authored, live, sourceFile) : live.outerHTML;
|
|
81738
|
+
}
|
|
81739
|
+
async function readSavedMarkup(readSaved, paths, lives) {
|
|
81740
|
+
const sources = /* @__PURE__ */ new Map();
|
|
81741
|
+
return Promise.all(
|
|
81742
|
+
paths.map(async (path, index) => {
|
|
81743
|
+
if (!sources.has(path)) sources.set(path, readSaved(path).then(parseSavedSource));
|
|
81744
|
+
const saved2 = await sources.get(path);
|
|
81745
|
+
return savedMarkupElseLive(saved2, lives[index], path);
|
|
81746
|
+
})
|
|
81747
|
+
);
|
|
81615
81748
|
}
|
|
81616
81749
|
function tracksOverlap(a, b) {
|
|
81617
81750
|
return a.track === b.track && timeRangesOverlap(a.start, a.start + a.duration, b.start, b.start + b.duration);
|
|
@@ -81685,68 +81818,111 @@ function useClipboard({
|
|
|
81685
81818
|
reloadPreview,
|
|
81686
81819
|
handleTimelineElementsDelete,
|
|
81687
81820
|
handleDomEditElementDelete,
|
|
81688
|
-
previewIframeRef
|
|
81821
|
+
previewIframeRef,
|
|
81822
|
+
waitForPendingDomEditSaves
|
|
81689
81823
|
}) {
|
|
81690
81824
|
const clipboardRef = useRef161(null);
|
|
81691
81825
|
const projectIdRef = useRef161(projectId);
|
|
81692
81826
|
projectIdRef.current = projectId;
|
|
81693
|
-
const
|
|
81827
|
+
const readSaved = useCallback145(
|
|
81828
|
+
async (path) => {
|
|
81829
|
+
const pid = projectIdRef.current;
|
|
81830
|
+
if (!pid) throw new Error("No project is open.");
|
|
81831
|
+
await waitForPendingDomEditSaves().catch(() => {
|
|
81832
|
+
});
|
|
81833
|
+
return serializeStudioFileMutations(
|
|
81834
|
+
writeProjectFile,
|
|
81835
|
+
[path],
|
|
81836
|
+
() => readFileContent(pid, path)
|
|
81837
|
+
);
|
|
81838
|
+
},
|
|
81839
|
+
[waitForPendingDomEditSaves, writeProjectFile]
|
|
81840
|
+
);
|
|
81841
|
+
const findSelectedClips = useCallback145(() => {
|
|
81694
81842
|
const selected = getSelectedElements();
|
|
81695
81843
|
if (selected.length === 0) return null;
|
|
81696
|
-
const
|
|
81844
|
+
const lives = [];
|
|
81697
81845
|
for (const element of selected) {
|
|
81698
|
-
const
|
|
81699
|
-
if (!
|
|
81846
|
+
const live = findTimelineElementInIframe(previewIframeRef.current, element, activeCompPath);
|
|
81847
|
+
if (!live) {
|
|
81700
81848
|
showToast(`Unable to copy "${element.label ?? element.id}".`, "info");
|
|
81701
81849
|
return null;
|
|
81702
81850
|
}
|
|
81703
|
-
|
|
81704
|
-
|
|
81851
|
+
lives.push(live);
|
|
81852
|
+
}
|
|
81853
|
+
return { elements: selected, lives };
|
|
81854
|
+
}, [activeCompPath, previewIframeRef, showToast]);
|
|
81855
|
+
const readClips = useCallback145(
|
|
81856
|
+
async (targets) => {
|
|
81857
|
+
const paths = targets.elements.map((el) => el.sourceFile || activeCompPath || "index.html");
|
|
81858
|
+
const markup = await readSavedMarkup(readSaved, paths, targets.lives);
|
|
81859
|
+
return targets.elements.map((element, index) => ({
|
|
81860
|
+
html: markup[index],
|
|
81705
81861
|
start: element.start,
|
|
81706
81862
|
duration: element.duration,
|
|
81707
81863
|
// authoredTrack, not track: `track` can be a display-lane number
|
|
81708
81864
|
// remapped by normalizeToZones, and writing THAT into data-track-index
|
|
81709
81865
|
// re-targets the wrong track in the sparse authored file.
|
|
81710
81866
|
track: element.authoredTrack ?? element.track
|
|
81711
|
-
});
|
|
81712
|
-
}
|
|
81713
|
-
|
|
81714
|
-
|
|
81715
|
-
const
|
|
81716
|
-
|
|
81717
|
-
|
|
81718
|
-
|
|
81719
|
-
|
|
81720
|
-
|
|
81721
|
-
|
|
81722
|
-
|
|
81723
|
-
|
|
81724
|
-
|
|
81725
|
-
|
|
81726
|
-
|
|
81727
|
-
|
|
81728
|
-
if (domSelection) {
|
|
81729
|
-
const html2 = getElementOuterHtml(previewIframeRef, domSelection, activeCompPath);
|
|
81730
|
-
if (!html2) {
|
|
81867
|
+
}));
|
|
81868
|
+
},
|
|
81869
|
+
[activeCompPath, readSaved]
|
|
81870
|
+
);
|
|
81871
|
+
const copyTimelineSelection = useCallback145(() => {
|
|
81872
|
+
const targets = findSelectedClips();
|
|
81873
|
+
if (!targets) return null;
|
|
81874
|
+
const sourceFile = targets.elements[0]?.sourceFile || activeCompPath || "index.html";
|
|
81875
|
+
return readClips(targets).then((clips) => {
|
|
81876
|
+
showToast(clips.length > 1 ? `Copied ${clips.length} clips` : "Copied clip", "info");
|
|
81877
|
+
return { kind: "timeline-clip", clips, sourceFile };
|
|
81878
|
+
});
|
|
81879
|
+
}, [activeCompPath, findSelectedClips, readClips, showToast]);
|
|
81880
|
+
const copyDomSelection = useCallback145(
|
|
81881
|
+
(domSelection) => {
|
|
81882
|
+
const live = getSelectedDomElement(previewIframeRef, domSelection, activeCompPath);
|
|
81883
|
+
if (!live) {
|
|
81731
81884
|
showToast("Unable to copy this element.", "info");
|
|
81732
|
-
return
|
|
81885
|
+
return null;
|
|
81733
81886
|
}
|
|
81734
|
-
const
|
|
81735
|
-
|
|
81736
|
-
|
|
81737
|
-
|
|
81738
|
-
|
|
81739
|
-
|
|
81740
|
-
|
|
81741
|
-
|
|
81742
|
-
|
|
81743
|
-
|
|
81887
|
+
const sourceFile = domSelection.sourceFile || activeCompPath || "index.html";
|
|
81888
|
+
return readSaved(sourceFile).then((content) => {
|
|
81889
|
+
showToast("Copied element", "info");
|
|
81890
|
+
return {
|
|
81891
|
+
kind: "dom-element",
|
|
81892
|
+
html: savedMarkupElseLive(parseSavedSource(content), live, sourceFile),
|
|
81893
|
+
sourceFile,
|
|
81894
|
+
originSelector: domSelection.selector,
|
|
81895
|
+
originSelectorIndex: domSelection.selectorIndex
|
|
81896
|
+
};
|
|
81897
|
+
});
|
|
81898
|
+
},
|
|
81899
|
+
[activeCompPath, previewIframeRef, readSaved, showToast]
|
|
81900
|
+
);
|
|
81901
|
+
const copyToClipboard = useCallback145(() => {
|
|
81902
|
+
const domSelection = domEditSelectionRef.current;
|
|
81903
|
+
let pending2;
|
|
81904
|
+
if (usePlayerStore.getState().selectedElementId) pending2 = copyTimelineSelection();
|
|
81905
|
+
else if (domSelection) pending2 = copyDomSelection(domSelection);
|
|
81906
|
+
else {
|
|
81907
|
+
showToast("Nothing selected to copy.", "info");
|
|
81908
|
+
return null;
|
|
81744
81909
|
}
|
|
81745
|
-
|
|
81746
|
-
|
|
81747
|
-
|
|
81910
|
+
if (!pending2) return null;
|
|
81911
|
+
const own = pending2.catch((error) => {
|
|
81912
|
+
showToast(error instanceof Error ? error.message : "Failed to copy", "error");
|
|
81913
|
+
return null;
|
|
81914
|
+
});
|
|
81915
|
+
const previous = clipboardRef.current;
|
|
81916
|
+
const settled = own.then((payload) => payload ?? previous);
|
|
81917
|
+
clipboardRef.current = settled;
|
|
81918
|
+
void settled.then((payload) => {
|
|
81919
|
+
if (!payload && clipboardRef.current === settled) clipboardRef.current = null;
|
|
81920
|
+
});
|
|
81921
|
+
return own;
|
|
81922
|
+
}, [copyDomSelection, copyTimelineSelection, domEditSelectionRef, showToast]);
|
|
81923
|
+
const handleCopy2 = useCallback145(() => copyToClipboard() !== null, [copyToClipboard]);
|
|
81748
81924
|
const handlePaste2 = useCallback145(async () => {
|
|
81749
|
-
const payload = clipboardRef.current;
|
|
81925
|
+
const payload = await clipboardRef.current;
|
|
81750
81926
|
if (!payload) {
|
|
81751
81927
|
showToast("Nothing to paste.", "info");
|
|
81752
81928
|
return;
|
|
@@ -81789,14 +81965,15 @@ function useClipboard({
|
|
|
81789
81965
|
}
|
|
81790
81966
|
}, [activeCompPath, recordEdit, reloadPreview, showToast, writeProjectFile]);
|
|
81791
81967
|
const handleDuplicate = useCallback145(async () => {
|
|
81792
|
-
const
|
|
81793
|
-
if (!
|
|
81968
|
+
const targets = findSelectedClips();
|
|
81969
|
+
if (!targets) return false;
|
|
81794
81970
|
const pid = projectIdRef.current;
|
|
81795
81971
|
if (!pid) return false;
|
|
81796
|
-
const { elements
|
|
81972
|
+
const { elements } = targets;
|
|
81797
81973
|
const targetPath = elements[0]?.sourceFile || activeCompPath || "index.html";
|
|
81798
81974
|
const anchorTime = Math.max(...elements.map((el) => el.start + el.duration));
|
|
81799
81975
|
try {
|
|
81976
|
+
const clips = await readClips(targets);
|
|
81800
81977
|
const originalContent = await readFileContent(pid, targetPath);
|
|
81801
81978
|
const liveElements = usePlayerStore.getState().elements;
|
|
81802
81979
|
const pasted = pasteTimelineClips(originalContent, clips, anchorTime, liveElements);
|
|
@@ -81823,7 +82000,8 @@ function useClipboard({
|
|
|
81823
82000
|
}
|
|
81824
82001
|
}, [
|
|
81825
82002
|
activeCompPath,
|
|
81826
|
-
|
|
82003
|
+
findSelectedClips,
|
|
82004
|
+
readClips,
|
|
81827
82005
|
recordEdit,
|
|
81828
82006
|
reloadPreview,
|
|
81829
82007
|
showToast,
|
|
@@ -81831,19 +82009,24 @@ function useClipboard({
|
|
|
81831
82009
|
]);
|
|
81832
82010
|
const handleCut = useCallback145(async () => {
|
|
81833
82011
|
const selected = getSelectedElements();
|
|
81834
|
-
const
|
|
81835
|
-
|
|
82012
|
+
const domSelection = domEditSelectionRef.current;
|
|
82013
|
+
const copied = copyToClipboard();
|
|
82014
|
+
if (!copied || !await copied) return false;
|
|
81836
82015
|
if (selected.length > 0) {
|
|
81837
82016
|
await handleTimelineElementsDelete(selected);
|
|
81838
82017
|
return true;
|
|
81839
82018
|
}
|
|
81840
|
-
const domSelection = domEditSelectionRef.current;
|
|
81841
82019
|
if (domSelection) {
|
|
81842
82020
|
await handleDomEditElementDelete(domSelection);
|
|
81843
82021
|
return true;
|
|
81844
82022
|
}
|
|
81845
82023
|
return true;
|
|
81846
|
-
}, [
|
|
82024
|
+
}, [
|
|
82025
|
+
copyToClipboard,
|
|
82026
|
+
domEditSelectionRef,
|
|
82027
|
+
handleTimelineElementsDelete,
|
|
82028
|
+
handleDomEditElementDelete
|
|
82029
|
+
]);
|
|
81847
82030
|
const canPaste = useCallback145(() => clipboardRef.current !== null, []);
|
|
81848
82031
|
return { handleCopy: handleCopy2, handlePaste: handlePaste2, handleCut, handleDuplicate, canPaste };
|
|
81849
82032
|
}
|
|
@@ -82283,16 +82466,24 @@ function useFrameCapture({
|
|
|
82283
82466
|
showToast,
|
|
82284
82467
|
waitForPendingDomEditSaves
|
|
82285
82468
|
}) {
|
|
82286
|
-
const [captureFrameTime, setCaptureFrameTime] = useState122(
|
|
82469
|
+
const [captureFrameTime, setCaptureFrameTime] = useState122(
|
|
82470
|
+
() => usePlayerStore.getState().currentTime
|
|
82471
|
+
);
|
|
82287
82472
|
const [capturing, setCapturing] = useState122(false);
|
|
82288
82473
|
const capturingRef = useRef164(false);
|
|
82289
|
-
|
|
82290
|
-
|
|
82291
|
-
|
|
82292
|
-
|
|
82293
|
-
|
|
82294
|
-
|
|
82474
|
+
const livePlayheadRef = useRef164(captureFrameTime);
|
|
82475
|
+
useMountEffect(
|
|
82476
|
+
() => liveTime.subscribe((time) => {
|
|
82477
|
+
livePlayheadRef.current = time;
|
|
82478
|
+
})
|
|
82479
|
+
);
|
|
82480
|
+
const playheadTime = useCallback147(() => {
|
|
82481
|
+
const { isPlaying, currentTime } = usePlayerStore.getState();
|
|
82482
|
+
return isPlaying ? livePlayheadRef.current : currentTime;
|
|
82295
82483
|
}, []);
|
|
82484
|
+
const refreshCaptureFrameTime = useCallback147(() => {
|
|
82485
|
+
setCaptureFrameTime(playheadTime());
|
|
82486
|
+
}, [playheadTime]);
|
|
82296
82487
|
const handleCaptureFrameClick = useCallback147(
|
|
82297
82488
|
async (event) => {
|
|
82298
82489
|
if (!projectId) return;
|
|
@@ -82301,7 +82492,7 @@ function useFrameCapture({
|
|
|
82301
82492
|
capturingRef.current = true;
|
|
82302
82493
|
setCapturing(true);
|
|
82303
82494
|
try {
|
|
82304
|
-
const time =
|
|
82495
|
+
const time = playheadTime();
|
|
82305
82496
|
setCaptureFrameTime(time);
|
|
82306
82497
|
await Promise.race([
|
|
82307
82498
|
waitForPendingDomEditSaves(),
|
|
@@ -82352,7 +82543,7 @@ function useFrameCapture({
|
|
|
82352
82543
|
setCapturing(false);
|
|
82353
82544
|
}
|
|
82354
82545
|
},
|
|
82355
|
-
[activeCompPath, projectId, showToast, waitForPendingDomEditSaves]
|
|
82546
|
+
[activeCompPath, playheadTime, projectId, showToast, waitForPendingDomEditSaves]
|
|
82356
82547
|
);
|
|
82357
82548
|
const captureFrameHref = projectId ? buildFrameCaptureUrl({
|
|
82358
82549
|
projectId,
|
|
@@ -92593,7 +92784,8 @@ function StudioApp({ readOnlyPreview = false, readOnlyPreviewReason } = {}) {
|
|
|
92593
92784
|
reloadPreview,
|
|
92594
92785
|
handleTimelineElementsDelete: timelineEditing.handleTimelineElementsDelete,
|
|
92595
92786
|
handleDomEditElementDelete: domEditDeleteBridge,
|
|
92596
|
-
previewIframeRef
|
|
92787
|
+
previewIframeRef,
|
|
92788
|
+
waitForPendingDomEditSaves: previewPersistence.waitForPendingDomEditSaves
|
|
92597
92789
|
});
|
|
92598
92790
|
const appHotkeys = useAppHotkeys({
|
|
92599
92791
|
handleTimelineElementsDelete: timelineEditing.handleTimelineElementsDelete,
|
|
@@ -92978,39 +93170,12 @@ function useElementPicker(iframeRef, options) {
|
|
|
92978
93170
|
if (!activeIframe) return;
|
|
92979
93171
|
if (e.source !== activeIframe.contentWindow && e.source !== iframeRef.current?.contentWindow)
|
|
92980
93172
|
return;
|
|
92981
|
-
if (data.type === "element-picked") {
|
|
92982
|
-
|
|
92983
|
-
|
|
92984
|
-
const styles = readComputedStyles(activeIframe, el.selector);
|
|
92985
|
-
setPickedElement({
|
|
92986
|
-
id: el.id ?? null,
|
|
92987
|
-
tagName: el.tagName ?? "div",
|
|
92988
|
-
selector: el.selector ?? "",
|
|
92989
|
-
label: el.label ?? el.tagName ?? "Element",
|
|
92990
|
-
boundingBox: el.boundingBox ?? { x: 0, y: 0, width: 0, height: 0 },
|
|
92991
|
-
textContent: el.textContent ?? null,
|
|
92992
|
-
src: el.src ?? null,
|
|
92993
|
-
dataAttributes: el.dataAttributes ?? {},
|
|
92994
|
-
computedStyles: styles
|
|
92995
|
-
});
|
|
92996
|
-
setIsPickMode(false);
|
|
92997
|
-
}
|
|
93173
|
+
if (data.type === "element-picked" && data.elementInfo) {
|
|
93174
|
+
setPickedElement(toPickedElement(data.elementInfo, activeIframe));
|
|
93175
|
+
setIsPickMode(false);
|
|
92998
93176
|
} else if (data.type === "element-pick-candidates") {
|
|
92999
93177
|
const el = data.candidates?.[data.selectedIndex ?? 0];
|
|
93000
|
-
if (el)
|
|
93001
|
-
const styles = readComputedStyles(activeIframe, el.selector);
|
|
93002
|
-
setPickedElement({
|
|
93003
|
-
id: el.id ?? null,
|
|
93004
|
-
tagName: el.tagName ?? "div",
|
|
93005
|
-
selector: el.selector ?? "",
|
|
93006
|
-
label: el.label ?? el.tagName ?? "Element",
|
|
93007
|
-
boundingBox: el.boundingBox ?? { x: 0, y: 0, width: 0, height: 0 },
|
|
93008
|
-
textContent: el.textContent ?? null,
|
|
93009
|
-
src: el.src ?? null,
|
|
93010
|
-
dataAttributes: el.dataAttributes ?? {},
|
|
93011
|
-
computedStyles: styles
|
|
93012
|
-
});
|
|
93013
|
-
}
|
|
93178
|
+
if (el) setPickedElement(toPickedElement(el, activeIframe));
|
|
93014
93179
|
}
|
|
93015
93180
|
if (data.type === "pick-mode-cancelled") {
|
|
93016
93181
|
setIsPickMode(false);
|
|
@@ -93021,19 +93186,19 @@ function useElementPicker(iframeRef, options) {
|
|
|
93021
93186
|
});
|
|
93022
93187
|
const optionsRef = useRef189(options);
|
|
93023
93188
|
optionsRef.current = options;
|
|
93189
|
+
const pendingWritesRef = useRef189(/* @__PURE__ */ new Map());
|
|
93190
|
+
settlePendingWrites(pendingWritesRef.current, options?.workspaceFiles);
|
|
93024
93191
|
const syncToSource = useCallback183(
|
|
93025
|
-
(
|
|
93192
|
+
(picked, live, iframe, op) => {
|
|
93026
93193
|
const opts = optionsRef.current;
|
|
93027
|
-
if (!opts?.workspaceFiles || !opts.onSyncFiles
|
|
93028
|
-
const
|
|
93029
|
-
const
|
|
93030
|
-
|
|
93031
|
-
|
|
93032
|
-
|
|
93033
|
-
|
|
93034
|
-
|
|
93035
|
-
opts.onSyncFiles({ [sourceFile]: patched });
|
|
93036
|
-
}
|
|
93194
|
+
if (!opts?.workspaceFiles || !opts.onSyncFiles) return;
|
|
93195
|
+
const hfId = live.getAttribute("data-hf-id");
|
|
93196
|
+
const pending2 = pendingWritesRef.current;
|
|
93197
|
+
const files = withPendingWrites(opts.workspaceFiles, pending2);
|
|
93198
|
+
const patch = picked.id ? patchById(files, picked.id, picked.selector, op) : hfId ? patchByHfId(files, hfId, ownSourceFile(live, iframe), op) : null;
|
|
93199
|
+
if (!patch || patch.after === patch.before) return;
|
|
93200
|
+
recordPendingWrite(pending2, patch.path, opts.workspaceFiles[patch.path], patch.after);
|
|
93201
|
+
opts.onSyncFiles({ [patch.path]: patch.after });
|
|
93037
93202
|
},
|
|
93038
93203
|
[]
|
|
93039
93204
|
);
|
|
@@ -93052,27 +93217,11 @@ function useElementPicker(iframeRef, options) {
|
|
|
93052
93217
|
computedStyles: { ...prev.computedStyles, [prop]: value }
|
|
93053
93218
|
} : null
|
|
93054
93219
|
);
|
|
93055
|
-
|
|
93056
|
-
|
|
93057
|
-
|
|
93058
|
-
|
|
93059
|
-
|
|
93060
|
-
});
|
|
93061
|
-
} else {
|
|
93062
|
-
try {
|
|
93063
|
-
const fullHtml = activeIframe.contentDocument?.documentElement.outerHTML;
|
|
93064
|
-
if (fullHtml && optionsRef.current?.onSyncFiles) {
|
|
93065
|
-
const src = activeIframe.getAttribute("src") ?? "";
|
|
93066
|
-
const compMatch = src.match(/\/comp\/(.+?)(?:\?|$)/);
|
|
93067
|
-
const filePath = compMatch ? compMatch[1] : "index.html";
|
|
93068
|
-
optionsRef.current.onSyncFiles({
|
|
93069
|
-
[filePath]: `<!DOCTYPE html>
|
|
93070
|
-
<html>${fullHtml.replace(/<html[^>]*>/, "")}`
|
|
93071
|
-
});
|
|
93072
|
-
}
|
|
93073
|
-
} catch {
|
|
93074
|
-
}
|
|
93075
|
-
}
|
|
93220
|
+
syncToSource(pickedElement, el, activeIframe, {
|
|
93221
|
+
type: "inline-style",
|
|
93222
|
+
property: prop,
|
|
93223
|
+
value
|
|
93224
|
+
});
|
|
93076
93225
|
}
|
|
93077
93226
|
} catch {
|
|
93078
93227
|
}
|
|
@@ -93094,13 +93243,11 @@ function useElementPicker(iframeRef, options) {
|
|
|
93094
93243
|
dataAttributes: { ...prev.dataAttributes, [attr]: value }
|
|
93095
93244
|
} : null
|
|
93096
93245
|
);
|
|
93097
|
-
|
|
93098
|
-
|
|
93099
|
-
|
|
93100
|
-
|
|
93101
|
-
|
|
93102
|
-
});
|
|
93103
|
-
}
|
|
93246
|
+
syncToSource(pickedElement, el, activeIframe, {
|
|
93247
|
+
type: "attribute",
|
|
93248
|
+
property: attr,
|
|
93249
|
+
value
|
|
93250
|
+
});
|
|
93104
93251
|
}
|
|
93105
93252
|
} catch {
|
|
93106
93253
|
}
|
|
@@ -93117,13 +93264,11 @@ function useElementPicker(iframeRef, options) {
|
|
|
93117
93264
|
if (el) {
|
|
93118
93265
|
el.textContent = text;
|
|
93119
93266
|
setPickedElement((prev) => prev ? { ...prev, textContent: text } : null);
|
|
93120
|
-
|
|
93121
|
-
|
|
93122
|
-
|
|
93123
|
-
|
|
93124
|
-
|
|
93125
|
-
});
|
|
93126
|
-
}
|
|
93267
|
+
syncToSource(pickedElement, el, activeIframe, {
|
|
93268
|
+
type: "text-content",
|
|
93269
|
+
property: "textContent",
|
|
93270
|
+
value: text
|
|
93271
|
+
});
|
|
93127
93272
|
}
|
|
93128
93273
|
} catch {
|
|
93129
93274
|
}
|
|
@@ -93146,6 +93291,57 @@ function useElementPicker(iframeRef, options) {
|
|
|
93146
93291
|
activeIframeRef
|
|
93147
93292
|
};
|
|
93148
93293
|
}
|
|
93294
|
+
function settlePendingWrites(pending2, files) {
|
|
93295
|
+
for (const [path, write] of pending2) {
|
|
93296
|
+
const hostSource = files?.[path];
|
|
93297
|
+
if (hostSource === write.hostSource) continue;
|
|
93298
|
+
const caughtUpTo = hostSource === void 0 ? -1 : write.writes.indexOf(hostSource);
|
|
93299
|
+
if (caughtUpTo < 0 || caughtUpTo === write.writes.length - 1) {
|
|
93300
|
+
pending2.delete(path);
|
|
93301
|
+
} else {
|
|
93302
|
+
write.hostSource = hostSource;
|
|
93303
|
+
write.writes = write.writes.slice(caughtUpTo + 1);
|
|
93304
|
+
}
|
|
93305
|
+
}
|
|
93306
|
+
}
|
|
93307
|
+
function withPendingWrites(files, pending2) {
|
|
93308
|
+
const merged = { ...files };
|
|
93309
|
+
for (const [path, write] of pending2) merged[path] = write.writes.at(-1) ?? merged[path];
|
|
93310
|
+
return merged;
|
|
93311
|
+
}
|
|
93312
|
+
function recordPendingWrite(pending2, path, hostSource, after) {
|
|
93313
|
+
const write = pending2.get(path) ?? { hostSource, writes: [] };
|
|
93314
|
+
write.writes.push(after);
|
|
93315
|
+
pending2.set(path, write);
|
|
93316
|
+
}
|
|
93317
|
+
function toPickedElement(el, iframe) {
|
|
93318
|
+
return {
|
|
93319
|
+
id: el.id ?? null,
|
|
93320
|
+
tagName: el.tagName ?? "div",
|
|
93321
|
+
selector: el.selector ?? "",
|
|
93322
|
+
label: el.label ?? el.tagName ?? "Element",
|
|
93323
|
+
boundingBox: el.boundingBox ?? { x: 0, y: 0, width: 0, height: 0 },
|
|
93324
|
+
textContent: el.textContent ?? null,
|
|
93325
|
+
src: el.src ?? null,
|
|
93326
|
+
dataAttributes: el.dataAttributes ?? {},
|
|
93327
|
+
computedStyles: readComputedStyles(iframe, el.selector ?? "")
|
|
93328
|
+
};
|
|
93329
|
+
}
|
|
93330
|
+
function patchById(files, id, selector, op) {
|
|
93331
|
+
const path = resolveSourceFile(id, selector, files);
|
|
93332
|
+
const before = path ? files[path] : void 0;
|
|
93333
|
+
return path && before ? { path, before, after: applyPatch(before, id, op) } : null;
|
|
93334
|
+
}
|
|
93335
|
+
function ownSourceFile(live, iframe) {
|
|
93336
|
+
const previewed = compositionPathOfPreviewUrl(iframe.getAttribute("src") ?? "");
|
|
93337
|
+
return getSourceFileForElement(live, previewed).sourceFile;
|
|
93338
|
+
}
|
|
93339
|
+
function patchByHfId(files, hfId, ownFile, op) {
|
|
93340
|
+
const matches = Object.keys(files).filter((file) => findTagByTarget(files[file] ?? "", { hfId }));
|
|
93341
|
+
const path = matches.includes(ownFile) ? ownFile : matches.length === 1 ? matches[0] : void 0;
|
|
93342
|
+
const before = path ? files[path] : void 0;
|
|
93343
|
+
return path && before ? { path, before, after: applyPatchByTarget(before, { hfId }, op) } : null;
|
|
93344
|
+
}
|
|
93149
93345
|
function readComputedStyles(iframe, selector) {
|
|
93150
93346
|
const styles = {};
|
|
93151
93347
|
try {
|