hyperframes 0.7.60 → 0.7.61
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/bin/hyperframes.mjs +11 -0
- package/dist/cli.js +13073 -9820
- package/dist/hyperframe-runtime.js +27 -27
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +27 -27
- package/dist/hyperframes-player.global.js +2 -2
- package/dist/runtimeVersion.js +17 -0
- package/dist/skills/hyperframes/SKILL.md +10 -0
- package/dist/skills/hyperframes-cli/SKILL.md +1 -1
- package/dist/skills/hyperframes-cli/references/preview-render.md +10 -0
- package/dist/skills/hyperframes-cli/references/upgrade-info-misc.md +1 -1
- package/dist/studio/assets/hyperframes-player-Xvx2hkrc.js +459 -0
- package/dist/studio/assets/{index-cH6NfVV_.js → index-2mxh_HSy.js} +177 -177
- package/dist/studio/assets/{index-D6etaey-.js → index-BCpoiv9S.js} +1 -1
- package/dist/studio/assets/index-BhWig0mx.css +1 -0
- package/dist/studio/assets/{index-Dh_WhagG.js → index-D-uFclFj.js} +1 -1
- package/dist/studio/index.html +2 -2
- package/dist/studio/index.js +1202 -673
- package/dist/studio/index.js.map +1 -1
- package/dist/templates/_shared/AGENTS.md +1 -1
- package/dist/templates/_shared/CLAUDE.md +1 -1
- package/package.json +4 -2
- package/dist/studio/assets/hyperframes-player-3XTTaVNf.js +0 -459
- package/dist/studio/assets/index-DXbu6IPT.css +0 -1
package/dist/studio/index.js
CHANGED
|
@@ -686,6 +686,9 @@ function formatFrameTime(time, duration, fps = STUDIO_PREVIEW_FPS) {
|
|
|
686
686
|
return `${currentFrame}f / ${totalFrames}f`;
|
|
687
687
|
}
|
|
688
688
|
|
|
689
|
+
// src/player/lib/timelineIframeHelpers.ts
|
|
690
|
+
import { readClipTiming } from "@hyperframes/core/composition-contract";
|
|
691
|
+
|
|
689
692
|
// src/player/lib/playbackAdapter.ts
|
|
690
693
|
function isFinitePositive(value) {
|
|
691
694
|
return Number.isFinite(value) && value > 0;
|
|
@@ -1239,95 +1242,130 @@ function stopScrubPreviewAudio() {
|
|
|
1239
1242
|
scrubPrevMuted = null;
|
|
1240
1243
|
scrubPrevVolume = null;
|
|
1241
1244
|
}
|
|
1245
|
+
function timelineDuration(iframeWin, compositionId) {
|
|
1246
|
+
return iframeWin.__timelines?.[compositionId]?.duration?.() ?? 0;
|
|
1247
|
+
}
|
|
1248
|
+
function createTimedElementLookup(doc) {
|
|
1249
|
+
const timedById = /* @__PURE__ */ new Map();
|
|
1250
|
+
for (const timed of doc.querySelectorAll("[data-start]")) {
|
|
1251
|
+
for (const id of [
|
|
1252
|
+
timed.id,
|
|
1253
|
+
timed.getAttribute("data-hf-id"),
|
|
1254
|
+
timed.getAttribute("data-composition-id")
|
|
1255
|
+
]) {
|
|
1256
|
+
if (id) timedById.set(id, timed);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
return timedById;
|
|
1260
|
+
}
|
|
1261
|
+
function createReferenceEndResolver(timedById, iframeWin) {
|
|
1262
|
+
const resolveEnd = (refId, visiting) => {
|
|
1263
|
+
if (visiting.has(refId)) return null;
|
|
1264
|
+
const referenced = timedById.get(refId);
|
|
1265
|
+
if (!referenced) return null;
|
|
1266
|
+
const next = new Set(visiting).add(refId);
|
|
1267
|
+
const timing = readClipTiming(referenced, {
|
|
1268
|
+
resolveReferenceEnd: (nestedId) => resolveEnd(nestedId, next)
|
|
1269
|
+
});
|
|
1270
|
+
if (timing.end != null) return timing.end;
|
|
1271
|
+
const compositionId = referenced.getAttribute("data-composition-id");
|
|
1272
|
+
const duration = compositionId ? timelineDuration(iframeWin, compositionId) : 0;
|
|
1273
|
+
return timing.start == null || duration <= 0 ? null : timing.start + duration;
|
|
1274
|
+
};
|
|
1275
|
+
return resolveEnd;
|
|
1276
|
+
}
|
|
1277
|
+
function clampCompositionWindow(start, duration, rootDuration) {
|
|
1278
|
+
if (!Number.isFinite(duration) || duration <= 0) return null;
|
|
1279
|
+
const safeStart = Number.isFinite(start) ? start : 0;
|
|
1280
|
+
if (!Number.isFinite(rootDuration) || rootDuration <= 0) {
|
|
1281
|
+
return { start: safeStart, duration };
|
|
1282
|
+
}
|
|
1283
|
+
if (safeStart >= rootDuration) return null;
|
|
1284
|
+
const clamped = Math.min(duration, Math.max(0, rootDuration - safeStart));
|
|
1285
|
+
return clamped > 0 ? { start: safeStart, duration: clamped } : null;
|
|
1286
|
+
}
|
|
1287
|
+
function nonEmpty(value, fallback) {
|
|
1288
|
+
return value || fallback;
|
|
1289
|
+
}
|
|
1290
|
+
function optionalNonEmpty(value) {
|
|
1291
|
+
return value || void 0;
|
|
1292
|
+
}
|
|
1293
|
+
function attachCompositionSource(entry, element, compositionSrc) {
|
|
1294
|
+
if (compositionSrc) return { ...entry, compositionSrc };
|
|
1295
|
+
const innerVideo = element.querySelector("video[src]");
|
|
1296
|
+
if (!innerVideo) return entry;
|
|
1297
|
+
return { ...entry, src: optionalNonEmpty(innerVideo.getAttribute("src")), tag: "video" };
|
|
1298
|
+
}
|
|
1299
|
+
function buildMissingCompositionEntry(params) {
|
|
1300
|
+
const { doc, iframeWin, element, compositionId, rootDuration, fallbackIndex, resolveEnd } = params;
|
|
1301
|
+
const timing = readClipTiming(element, {
|
|
1302
|
+
resolveReferenceEnd: (refId) => resolveEnd(refId, /* @__PURE__ */ new Set([compositionId]))
|
|
1303
|
+
});
|
|
1304
|
+
const window2 = clampCompositionWindow(
|
|
1305
|
+
timing.start ?? 0,
|
|
1306
|
+
timing.duration ?? timelineDuration(iframeWin, compositionId),
|
|
1307
|
+
rootDuration
|
|
1308
|
+
);
|
|
1309
|
+
if (!window2) return null;
|
|
1310
|
+
const preferredId = nonEmpty(element.id, compositionId);
|
|
1311
|
+
const compositionSrc = element.getAttribute("data-composition-src") ?? element.getAttribute("data-composition-file");
|
|
1312
|
+
const selector = getTimelineElementSelector(element);
|
|
1313
|
+
const sourceFile = getTimelineElementSourceFile(element);
|
|
1314
|
+
const selectorIndex = getTimelineElementSelectorIndex(doc, element, selector);
|
|
1315
|
+
const label = getTimelineElementDisplayLabel({
|
|
1316
|
+
id: preferredId,
|
|
1317
|
+
label: element.getAttribute("data-timeline-label") ?? element.getAttribute("data-label"),
|
|
1318
|
+
tag: element.tagName
|
|
1319
|
+
});
|
|
1320
|
+
const identity = buildTimelineElementIdentity({
|
|
1321
|
+
preferredId,
|
|
1322
|
+
label,
|
|
1323
|
+
fallbackIndex,
|
|
1324
|
+
domId: optionalNonEmpty(element.id),
|
|
1325
|
+
selector,
|
|
1326
|
+
selectorIndex,
|
|
1327
|
+
sourceFile
|
|
1328
|
+
});
|
|
1329
|
+
const entry = {
|
|
1330
|
+
id: identity.id,
|
|
1331
|
+
label,
|
|
1332
|
+
key: identity.key,
|
|
1333
|
+
tag: element.tagName.toLowerCase(),
|
|
1334
|
+
start: window2.start,
|
|
1335
|
+
duration: window2.duration,
|
|
1336
|
+
track: timing.trackIndex,
|
|
1337
|
+
domId: optionalNonEmpty(element.id),
|
|
1338
|
+
hfId: optionalNonEmpty(element.getAttribute("data-hf-id")),
|
|
1339
|
+
selector,
|
|
1340
|
+
selectorIndex,
|
|
1341
|
+
sourceFile,
|
|
1342
|
+
zIndex: readTimelineElementZIndex(element)
|
|
1343
|
+
};
|
|
1344
|
+
return attachCompositionSource(entry, element, compositionSrc);
|
|
1345
|
+
}
|
|
1242
1346
|
function buildMissingCompositionElements(doc, iframeWin, currentEls, rootDuration) {
|
|
1243
1347
|
const existingIds = new Set(currentEls.map((e) => e.id));
|
|
1244
1348
|
const rootComp = doc.querySelector("[data-composition-id]");
|
|
1245
1349
|
const rootCompId = rootComp?.getAttribute("data-composition-id");
|
|
1246
1350
|
const hosts = doc.querySelectorAll("[data-composition-id][data-start]");
|
|
1247
1351
|
const missing = [];
|
|
1248
|
-
|
|
1352
|
+
const resolveEnd = createReferenceEndResolver(createTimedElementLookup(doc), iframeWin);
|
|
1353
|
+
for (const host of hosts) {
|
|
1249
1354
|
const el = host;
|
|
1250
1355
|
const compId = el.getAttribute("data-composition-id");
|
|
1251
|
-
if (!compId || compId === rootCompId)
|
|
1252
|
-
if (existingIds.has(el.id) || existingIds.has(compId))
|
|
1253
|
-
const
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
let refStart = parseFloat(refStartAttr);
|
|
1260
|
-
if (isNaN(refStart)) {
|
|
1261
|
-
const refRef = doc.getElementById(refStartAttr) || doc.querySelector(`[data-composition-id="${CSS.escape(refStartAttr)}"]`);
|
|
1262
|
-
const rrStart = parseFloat(refRef?.getAttribute("data-start") ?? "0") || 0;
|
|
1263
|
-
const rrCompId = refRef?.getAttribute("data-composition-id");
|
|
1264
|
-
const rrDur = parseFloat(refRef?.getAttribute("data-duration") ?? "") || (rrCompId ? iframeWin.__timelines?.[rrCompId]?.duration?.() ?? 0 : 0);
|
|
1265
|
-
refStart = rrStart + rrDur;
|
|
1266
|
-
}
|
|
1267
|
-
const refCompId = ref.getAttribute("data-composition-id");
|
|
1268
|
-
const refDur = parseFloat(ref.getAttribute("data-duration") ?? "") || (refCompId ? iframeWin.__timelines?.[refCompId]?.duration?.() ?? 0 : 0);
|
|
1269
|
-
start = refStart + refDur;
|
|
1270
|
-
} else {
|
|
1271
|
-
start = 0;
|
|
1272
|
-
}
|
|
1273
|
-
}
|
|
1274
|
-
let dur = parseFloat(el.getAttribute("data-duration") ?? "");
|
|
1275
|
-
if (isNaN(dur) || dur <= 0) {
|
|
1276
|
-
dur = iframeWin.__timelines?.[compId]?.duration?.() ?? 0;
|
|
1277
|
-
}
|
|
1278
|
-
if (!Number.isFinite(dur) || dur <= 0) return;
|
|
1279
|
-
if (!Number.isFinite(start)) start = 0;
|
|
1280
|
-
if (Number.isFinite(rootDuration) && rootDuration > 0) {
|
|
1281
|
-
if (start >= rootDuration) return;
|
|
1282
|
-
dur = Math.min(dur, Math.max(0, rootDuration - start));
|
|
1283
|
-
if (dur <= 0) return;
|
|
1284
|
-
}
|
|
1285
|
-
const trackStr = el.getAttribute("data-track-index");
|
|
1286
|
-
const track = trackStr != null ? parseInt(trackStr, 10) : 0;
|
|
1287
|
-
const compSrc = el.getAttribute("data-composition-src") || el.getAttribute("data-composition-file");
|
|
1288
|
-
const selector = getTimelineElementSelector(el);
|
|
1289
|
-
const sourceFile = getTimelineElementSourceFile(el);
|
|
1290
|
-
const selectorIndex = getTimelineElementSelectorIndex(doc, el, selector);
|
|
1291
|
-
const label = getTimelineElementDisplayLabel({
|
|
1292
|
-
id: el.id || compId || null,
|
|
1293
|
-
label: el.getAttribute("data-timeline-label") ?? el.getAttribute("data-label"),
|
|
1294
|
-
tag: el.tagName
|
|
1295
|
-
});
|
|
1296
|
-
const identity = buildTimelineElementIdentity({
|
|
1297
|
-
preferredId: el.id || compId || null,
|
|
1298
|
-
label,
|
|
1356
|
+
if (!compId || compId === rootCompId) continue;
|
|
1357
|
+
if (existingIds.has(el.id) || existingIds.has(compId)) continue;
|
|
1358
|
+
const entry = buildMissingCompositionEntry({
|
|
1359
|
+
doc,
|
|
1360
|
+
iframeWin,
|
|
1361
|
+
element: el,
|
|
1362
|
+
compositionId: compId,
|
|
1363
|
+
rootDuration,
|
|
1299
1364
|
fallbackIndex: missing.length,
|
|
1300
|
-
|
|
1301
|
-
selector,
|
|
1302
|
-
selectorIndex,
|
|
1303
|
-
sourceFile
|
|
1365
|
+
resolveEnd
|
|
1304
1366
|
});
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
label,
|
|
1308
|
-
key: identity.key,
|
|
1309
|
-
tag: el.tagName.toLowerCase(),
|
|
1310
|
-
start,
|
|
1311
|
-
duration: dur,
|
|
1312
|
-
track: isNaN(track) ? 0 : track,
|
|
1313
|
-
domId: el.id || void 0,
|
|
1314
|
-
hfId: el.getAttribute("data-hf-id") || void 0,
|
|
1315
|
-
selector,
|
|
1316
|
-
selectorIndex,
|
|
1317
|
-
sourceFile,
|
|
1318
|
-
zIndex: readTimelineElementZIndex(el)
|
|
1319
|
-
};
|
|
1320
|
-
if (compSrc) {
|
|
1321
|
-
entry.compositionSrc = compSrc;
|
|
1322
|
-
} else {
|
|
1323
|
-
const innerVideo = el.querySelector("video[src]");
|
|
1324
|
-
if (innerVideo) {
|
|
1325
|
-
entry.src = innerVideo.getAttribute("src") || void 0;
|
|
1326
|
-
entry.tag = "video";
|
|
1327
|
-
}
|
|
1328
|
-
}
|
|
1329
|
-
missing.push(entry);
|
|
1330
|
-
});
|
|
1367
|
+
if (entry) missing.push(entry);
|
|
1368
|
+
}
|
|
1331
1369
|
let patched = false;
|
|
1332
1370
|
const updatedEls = currentEls.map((existing) => {
|
|
1333
1371
|
if (existing.compositionSrc) return existing;
|
|
@@ -3311,6 +3349,7 @@ import { useMemo as useMemo3 } from "react";
|
|
|
3311
3349
|
|
|
3312
3350
|
// src/player/lib/timelineDOM.ts
|
|
3313
3351
|
import { resolveCssStackingContextId } from "@hyperframes/core/runtime/stacking-context";
|
|
3352
|
+
import { readClipTiming as readClipTiming2 } from "@hyperframes/core/composition-contract";
|
|
3314
3353
|
function resolveClipTag(clip) {
|
|
3315
3354
|
return clip.tagName || clip.kind || "div";
|
|
3316
3355
|
}
|
|
@@ -3466,22 +3505,18 @@ function parseTimelineFromDOM(doc, rootDuration) {
|
|
|
3466
3505
|
if (node === rootComp) return;
|
|
3467
3506
|
if (isTimelineIgnoredElement(node)) return;
|
|
3468
3507
|
const el = node;
|
|
3469
|
-
const
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
if (isNaN(start)) return;
|
|
3508
|
+
const timing = readClipTiming2(el);
|
|
3509
|
+
const start = timing.start;
|
|
3510
|
+
if (start == null) return;
|
|
3473
3511
|
if (Number.isFinite(rootDuration) && rootDuration > 0 && start >= rootDuration) return;
|
|
3474
3512
|
const tagLower = el.tagName.toLowerCase();
|
|
3475
|
-
let dur = 0;
|
|
3476
|
-
|
|
3477
|
-
if (durStr != null) dur = parseFloat(durStr);
|
|
3478
|
-
if (isNaN(dur) || dur <= 0) dur = Math.max(0, rootDuration - start);
|
|
3513
|
+
let dur = timing.duration ?? 0;
|
|
3514
|
+
if (dur <= 0) dur = Math.max(0, rootDuration - start);
|
|
3479
3515
|
if (Number.isFinite(rootDuration) && rootDuration > 0) {
|
|
3480
3516
|
dur = Math.min(dur, Math.max(0, rootDuration - start));
|
|
3481
3517
|
}
|
|
3482
3518
|
if (!Number.isFinite(dur) || dur <= 0) return;
|
|
3483
|
-
const
|
|
3484
|
-
const track = trackStr != null ? parseInt(trackStr, 10) : trackCounter++;
|
|
3519
|
+
const track = timing.trackSource === "default" ? trackCounter++ : timing.trackIndex;
|
|
3485
3520
|
const compId = el.getAttribute("data-composition-id");
|
|
3486
3521
|
const selector = getTimelineElementSelector(el);
|
|
3487
3522
|
const sourceFile = getTimelineElementSourceFile(el);
|
|
@@ -3507,7 +3542,7 @@ function parseTimelineFromDOM(doc, rootDuration) {
|
|
|
3507
3542
|
tag: tagLower,
|
|
3508
3543
|
start,
|
|
3509
3544
|
duration: dur,
|
|
3510
|
-
track
|
|
3545
|
+
track,
|
|
3511
3546
|
domId: el.id || void 0,
|
|
3512
3547
|
hfId: el.getAttribute("data-hf-id") || void 0,
|
|
3513
3548
|
selector,
|
|
@@ -6498,7 +6533,7 @@ var STUDIO_SDK_RESOLVER_SHADOW_ENABLED = resolveStudioBooleanEnvFlag(
|
|
|
6498
6533
|
var STUDIO_FLAT_INSPECTOR_ENABLED = resolveStudioBooleanEnvFlag(
|
|
6499
6534
|
env,
|
|
6500
6535
|
["VITE_STUDIO_ENABLE_FLAT_INSPECTOR", "VITE_STUDIO_FLAT_INSPECTOR_ENABLED"],
|
|
6501
|
-
|
|
6536
|
+
true
|
|
6502
6537
|
);
|
|
6503
6538
|
var STUDIO_MANUAL_EDITING_DISABLED_TITLE = "Manual editing is temporarily disabled";
|
|
6504
6539
|
|
|
@@ -8765,7 +8800,7 @@ function snapTimelineTime(time, targets, thresholdSecs) {
|
|
|
8765
8800
|
}
|
|
8766
8801
|
return best ? { time: best.time, target: best } : { time, target: null };
|
|
8767
8802
|
}
|
|
8768
|
-
function snapMoveToTargets(start, duration, targets, pixelsPerSecond,
|
|
8803
|
+
function snapMoveToTargets(start, duration, targets, pixelsPerSecond, timelineDuration2) {
|
|
8769
8804
|
if (targets.length === 0) return { start, snapTime: null, snapType: null };
|
|
8770
8805
|
const thresholdSecs = TIMELINE_SNAP_PX / Math.max(pixelsPerSecond, 1);
|
|
8771
8806
|
const startSnap = snapTimelineTime(start, targets, thresholdSecs);
|
|
@@ -8781,7 +8816,7 @@ function snapMoveToTargets(start, duration, targets, pixelsPerSecond, timelineDu
|
|
|
8781
8816
|
candidate = endSnap.time - duration;
|
|
8782
8817
|
target = endSnap.target;
|
|
8783
8818
|
}
|
|
8784
|
-
const maxStart = Math.max(0,
|
|
8819
|
+
const maxStart = Math.max(0, timelineDuration2 - duration);
|
|
8785
8820
|
const roundedCandidate = Math.round(candidate * 1e3) / 1e3;
|
|
8786
8821
|
const clamped = Math.max(0, Math.min(maxStart, roundedCandidate));
|
|
8787
8822
|
if (target && Math.abs(clamped - roundedCandidate) > 1e-6) target = null;
|
|
@@ -28346,6 +28381,7 @@ function CommitField({
|
|
|
28346
28381
|
value,
|
|
28347
28382
|
disabled,
|
|
28348
28383
|
liveCommit,
|
|
28384
|
+
align = "left",
|
|
28349
28385
|
onCommit
|
|
28350
28386
|
}) {
|
|
28351
28387
|
const [draft, setDraft] = useState35(value);
|
|
@@ -28418,7 +28454,7 @@ function CommitField({
|
|
|
28418
28454
|
scheduleCommit(nextDraft);
|
|
28419
28455
|
},
|
|
28420
28456
|
title: parseNumericToken(value) ? "Scroll or use Arrow keys to adjust" : void 0,
|
|
28421
|
-
className:
|
|
28457
|
+
className: `min-w-0 w-full bg-transparent text-[11px] font-medium text-neutral-100 outline-none disabled:cursor-not-allowed disabled:text-neutral-600 ${align === "right" ? "text-right" : "text-left"}`
|
|
28422
28458
|
}
|
|
28423
28459
|
);
|
|
28424
28460
|
}
|
|
@@ -31843,7 +31879,7 @@ function PromotableControl({
|
|
|
31843
31879
|
bound && /* @__PURE__ */ jsxs58(
|
|
31844
31880
|
"span",
|
|
31845
31881
|
{
|
|
31846
|
-
className: "pointer-events-none absolute right-1.5
|
|
31882
|
+
className: "pointer-events-none absolute -top-2 right-1.5 z-10 inline-flex max-w-[60%] items-center gap-1 truncate rounded bg-studio-accent/20 px-1 py-px font-mono text-[8px] font-medium text-studio-accent",
|
|
31847
31883
|
title: `Bound to variable "${promote.boundId}"`,
|
|
31848
31884
|
children: [
|
|
31849
31885
|
"\u25C6 ",
|
|
@@ -31860,7 +31896,7 @@ function PromotableControl({
|
|
|
31860
31896
|
e.stopPropagation();
|
|
31861
31897
|
promote.promote();
|
|
31862
31898
|
},
|
|
31863
|
-
className: "absolute right-1.5
|
|
31899
|
+
className: "absolute -top-2 right-1.5 z-10 inline-flex items-center gap-1 rounded bg-neutral-800/80 px-1 py-px font-mono text-[8px] font-medium text-neutral-400 opacity-70 transition-colors hover:bg-studio-accent/20 hover:text-studio-accent hover:opacity-100",
|
|
31864
31900
|
children: "\u25C7 var"
|
|
31865
31901
|
}
|
|
31866
31902
|
)
|
|
@@ -36274,6 +36310,7 @@ function FlatRow({
|
|
|
36274
36310
|
value,
|
|
36275
36311
|
disabled,
|
|
36276
36312
|
liveCommit,
|
|
36313
|
+
align: "right",
|
|
36277
36314
|
onCommit: (nextValue) => {
|
|
36278
36315
|
track("metric", label);
|
|
36279
36316
|
onCommit(nextValue);
|
|
@@ -36845,7 +36882,7 @@ function FlatTextSection({
|
|
|
36845
36882
|
const activeField = textFields.find((field) => field.key === activeFieldKey) ?? textFields[0];
|
|
36846
36883
|
if (!activeField) return null;
|
|
36847
36884
|
if (textFields.length > 1) {
|
|
36848
|
-
return /* @__PURE__ */ jsxs77("div", { className: "space-y-
|
|
36885
|
+
return /* @__PURE__ */ jsxs77("div", { className: "space-y-2.5", children: [
|
|
36849
36886
|
/* @__PURE__ */ jsx90(
|
|
36850
36887
|
FlatTextLayerList,
|
|
36851
36888
|
{
|
|
@@ -36874,7 +36911,7 @@ function FlatTextSection({
|
|
|
36874
36911
|
)
|
|
36875
36912
|
] });
|
|
36876
36913
|
}
|
|
36877
|
-
return /* @__PURE__ */ jsxs77("div", { className: "space-y-
|
|
36914
|
+
return /* @__PURE__ */ jsxs77("div", { className: "space-y-2.5", children: [
|
|
36878
36915
|
/* @__PURE__ */ jsx90(
|
|
36879
36916
|
FlatTextFieldEditor,
|
|
36880
36917
|
{
|
|
@@ -36988,17 +37025,6 @@ var STROKE_STYLE_OPTIONS = [
|
|
|
36988
37025
|
"inset",
|
|
36989
37026
|
"outset"
|
|
36990
37027
|
];
|
|
36991
|
-
function formatStrokeSummary(widthPx, style) {
|
|
36992
|
-
return `${widthPx}px ${style}`;
|
|
36993
|
-
}
|
|
36994
|
-
function parseStrokeSummary(text) {
|
|
36995
|
-
const match = /^\s*(-?\d+(?:\.\d+)?)px\s+(\S+)\s*$/.exec(text);
|
|
36996
|
-
if (!match) return null;
|
|
36997
|
-
const widthPx = Number.parseFloat(match[1]);
|
|
36998
|
-
const style = match[2];
|
|
36999
|
-
if (!Number.isFinite(widthPx) || !style) return null;
|
|
37000
|
-
return { widthPx, style };
|
|
37001
|
-
}
|
|
37002
37028
|
|
|
37003
37029
|
// src/components/editor/propertyPanelFlatMaskInsetRows.tsx
|
|
37004
37030
|
import { Fragment as Fragment28, jsx as jsx91, jsxs as jsxs78 } from "react/jsx-runtime";
|
|
@@ -37187,24 +37213,17 @@ function FlatStrokeRow({
|
|
|
37187
37213
|
const borderWidthValue = parsePxMetricValue(styles["border-width"] ?? "") ?? parsePxMetricValue(styles["border-top-width"] ?? "") ?? 0;
|
|
37188
37214
|
const borderStyleValue = styles["border-style"] || styles["border-top-style"] || "none";
|
|
37189
37215
|
const borderColorValue = styles["border-color"] || styles["border-top-color"] || "rgba(255, 255, 255, 0.18)";
|
|
37190
|
-
const
|
|
37191
|
-
const tier = resolveValueTier(
|
|
37192
|
-
styles["border-width"] != null || styles["border-style"] != null ? summary : void 0,
|
|
37193
|
-
formatStrokeSummary(0, "none")
|
|
37194
|
-
);
|
|
37216
|
+
const widthDisplay = formatPxMetricValue(borderWidthValue);
|
|
37195
37217
|
return /* @__PURE__ */ jsxs79(Fragment29, { children: [
|
|
37196
37218
|
/* @__PURE__ */ jsx92(
|
|
37197
37219
|
FlatRow,
|
|
37198
37220
|
{
|
|
37199
|
-
label: "Stroke",
|
|
37200
|
-
value:
|
|
37201
|
-
tier,
|
|
37221
|
+
label: "Stroke width",
|
|
37222
|
+
value: widthDisplay,
|
|
37223
|
+
tier: resolveValueTier(styles["border-width"], "0px"),
|
|
37202
37224
|
disabled,
|
|
37203
37225
|
onCommit: async (next) => {
|
|
37204
|
-
const
|
|
37205
|
-
if (!parsed) return;
|
|
37206
|
-
if (!STROKE_STYLE_OPTIONS.includes(parsed.style)) return;
|
|
37207
|
-
const normalizedWidth = normalizePanelPxValue(`${parsed.widthPx}px`, {
|
|
37226
|
+
const normalizedWidth = normalizePanelPxValue(next, {
|
|
37208
37227
|
min: 0,
|
|
37209
37228
|
max: 200,
|
|
37210
37229
|
fallback: borderWidthValue
|
|
@@ -37212,24 +37231,11 @@ function FlatStrokeRow({
|
|
|
37212
37231
|
if (!normalizedWidth) return;
|
|
37213
37232
|
for (const [property, value] of buildStrokeWidthStyleUpdates(
|
|
37214
37233
|
normalizedWidth,
|
|
37215
|
-
|
|
37234
|
+
borderStyleValue
|
|
37216
37235
|
)) {
|
|
37217
37236
|
await onSetStyle(property, value);
|
|
37218
37237
|
}
|
|
37219
|
-
|
|
37220
|
-
await onSetStyle(property, value);
|
|
37221
|
-
}
|
|
37222
|
-
},
|
|
37223
|
-
suffix: /* @__PURE__ */ jsxs79(Fragment29, { children: [
|
|
37224
|
-
/* @__PURE__ */ jsx92(
|
|
37225
|
-
"span",
|
|
37226
|
-
{
|
|
37227
|
-
className: "h-4 w-4 flex-shrink-0 rounded border border-panel-border-input",
|
|
37228
|
-
style: { backgroundColor: borderColorValue }
|
|
37229
|
-
}
|
|
37230
|
-
),
|
|
37231
|
-
/* @__PURE__ */ jsx92("span", { className: "font-mono text-[10px] text-panel-text-3", children: borderColorValue })
|
|
37232
|
-
] })
|
|
37238
|
+
}
|
|
37233
37239
|
}
|
|
37234
37240
|
),
|
|
37235
37241
|
/* @__PURE__ */ jsx92(
|
|
@@ -39114,49 +39120,51 @@ function PropertyPanelFlat({
|
|
|
39114
39120
|
)
|
|
39115
39121
|
});
|
|
39116
39122
|
}
|
|
39117
|
-
|
|
39118
|
-
|
|
39119
|
-
|
|
39120
|
-
|
|
39121
|
-
|
|
39122
|
-
|
|
39123
|
-
|
|
39124
|
-
|
|
39125
|
-
|
|
39126
|
-
|
|
39127
|
-
|
|
39128
|
-
|
|
39129
|
-
|
|
39130
|
-
|
|
39131
|
-
|
|
39132
|
-
|
|
39133
|
-
|
|
39134
|
-
|
|
39135
|
-
|
|
39136
|
-
|
|
39137
|
-
|
|
39138
|
-
|
|
39139
|
-
|
|
39140
|
-
|
|
39141
|
-
|
|
39142
|
-
|
|
39143
|
-
|
|
39144
|
-
|
|
39145
|
-
|
|
39146
|
-
|
|
39147
|
-
|
|
39148
|
-
|
|
39149
|
-
|
|
39150
|
-
|
|
39151
|
-
|
|
39152
|
-
|
|
39153
|
-
|
|
39154
|
-
|
|
39155
|
-
|
|
39156
|
-
|
|
39157
|
-
|
|
39158
|
-
|
|
39159
|
-
|
|
39123
|
+
if (sections.layout) {
|
|
39124
|
+
groups.push({
|
|
39125
|
+
id: "layout",
|
|
39126
|
+
title: "Layout",
|
|
39127
|
+
// No scrub accessory: FlatRow/CommitField has no pointer-drag scrubbing
|
|
39128
|
+
// (wheel/arrow keys only) — advertising "drag values to scrub" here lies.
|
|
39129
|
+
summary: `${formatPxMetricValue(displayX)},${formatPxMetricValue(displayY)} \xB7 ${Math.round(displayW)}\xD7${Math.round(displayH)}`,
|
|
39130
|
+
content: /* @__PURE__ */ jsx99(
|
|
39131
|
+
FlatLayoutSection,
|
|
39132
|
+
{
|
|
39133
|
+
element,
|
|
39134
|
+
styles,
|
|
39135
|
+
onSetStyle,
|
|
39136
|
+
disabled: !element.capabilities.canEditStyles,
|
|
39137
|
+
displayX,
|
|
39138
|
+
displayY,
|
|
39139
|
+
displayW,
|
|
39140
|
+
displayH,
|
|
39141
|
+
displayR,
|
|
39142
|
+
manualOffsetEditingDisabled,
|
|
39143
|
+
manualSizeEditingDisabled,
|
|
39144
|
+
manualRotationEditingDisabled,
|
|
39145
|
+
commitManualOffset,
|
|
39146
|
+
commitManualSize,
|
|
39147
|
+
commitManualRotation,
|
|
39148
|
+
gsapAnimId,
|
|
39149
|
+
navKeyframes,
|
|
39150
|
+
currentPct,
|
|
39151
|
+
seekFromKfPct,
|
|
39152
|
+
animIdForProp,
|
|
39153
|
+
resolveAnimIdForProp: animIdForProp,
|
|
39154
|
+
gsapRuntimeValues,
|
|
39155
|
+
gsapKeyframes: navKeyframes,
|
|
39156
|
+
elStart,
|
|
39157
|
+
elDuration,
|
|
39158
|
+
onCommitAnimatedProperty,
|
|
39159
|
+
onCommitAnimatedProperties,
|
|
39160
|
+
onSeekToTime,
|
|
39161
|
+
onRemoveKeyframe,
|
|
39162
|
+
onConvertToKeyframes,
|
|
39163
|
+
onLivePreviewProps: createGsapLivePreview(previewIframeRef ?? { current: null })
|
|
39164
|
+
}
|
|
39165
|
+
)
|
|
39166
|
+
});
|
|
39167
|
+
}
|
|
39160
39168
|
if (showMotionGroup) {
|
|
39161
39169
|
groups.push({
|
|
39162
39170
|
id: "motion",
|
|
@@ -39623,8 +39631,8 @@ var PropertyPanel = memo31(function PropertyPanel2(props) {
|
|
|
39623
39631
|
const manualSizeEditingDisabled = !element.capabilities.canApplyManualSize;
|
|
39624
39632
|
const manualRotationEditingDisabled = !element.capabilities.canApplyManualRotation;
|
|
39625
39633
|
const sourceLabel = element.id ? `#${element.id}` : element.selector ?? "";
|
|
39626
|
-
const showEditableSections = element.capabilities.canEditStyles;
|
|
39627
39634
|
const sections = resolveEditingSections(domEditSelectionToFacts(element, gsapAnimations.length));
|
|
39635
|
+
const showEditableSections = element.capabilities.canEditStyles && sections.style;
|
|
39628
39636
|
const manualOffset = readStudioPathOffset(element.element);
|
|
39629
39637
|
const manualSize = readStudioBoxSize(element.element);
|
|
39630
39638
|
const resolvedWidth = manualSize.width > 0 ? manualSize.width : parsePxMetricValue(styles.width ?? "") ?? element.boundingBox.width;
|
|
@@ -39788,7 +39796,7 @@ var PropertyPanel = memo31(function PropertyPanel2(props) {
|
|
|
39788
39796
|
onRemoveBackground
|
|
39789
39797
|
}
|
|
39790
39798
|
),
|
|
39791
|
-
/* @__PURE__ */ jsxs89(Section, { title: "Layout", icon: /* @__PURE__ */ jsx102(Move, { size: 15 }), children: [
|
|
39799
|
+
sections.layout && /* @__PURE__ */ jsxs89(Section, { title: "Layout", icon: /* @__PURE__ */ jsx102(Move, { size: 15 }), children: [
|
|
39792
39800
|
/* @__PURE__ */ jsxs89("div", { className: RESPONSIVE_GRID, children: [
|
|
39793
39801
|
/* @__PURE__ */ jsxs89("div", { className: "flex items-center gap-1", children: [
|
|
39794
39802
|
/* @__PURE__ */ jsx102("div", { className: "flex-1", children: /* @__PURE__ */ jsx102(
|
|
@@ -40788,7 +40796,7 @@ var FileTree = memo33(function FileTree2({
|
|
|
40788
40796
|
});
|
|
40789
40797
|
|
|
40790
40798
|
// src/App.tsx
|
|
40791
|
-
import { useState as
|
|
40799
|
+
import { useState as useState120, useCallback as useCallback142, useRef as useRef120, useMemo as useMemo50, useEffect as useEffect102, useLayoutEffect as useLayoutEffect4 } from "react";
|
|
40792
40800
|
|
|
40793
40801
|
// src/components/renders/useRenderQueue.ts
|
|
40794
40802
|
import { useState as useState64, useEffect as useEffect52, useCallback as useCallback58, useRef as useRef63, useMemo as useMemo31 } from "react";
|
|
@@ -50811,8 +50819,20 @@ function useBlockHandlers({
|
|
|
50811
50819
|
};
|
|
50812
50820
|
}
|
|
50813
50821
|
|
|
50822
|
+
// src/hooks/useAddAssetAtPlayhead.ts
|
|
50823
|
+
import { useCallback as useCallback97 } from "react";
|
|
50824
|
+
function useAddAssetAtPlayhead(handleTimelineAssetDrop) {
|
|
50825
|
+
return useCallback97(
|
|
50826
|
+
(assetPath) => handleTimelineAssetDrop(assetPath, {
|
|
50827
|
+
start: usePlayerStore.getState().currentTime,
|
|
50828
|
+
track: 0
|
|
50829
|
+
}),
|
|
50830
|
+
[handleTimelineAssetDrop]
|
|
50831
|
+
);
|
|
50832
|
+
}
|
|
50833
|
+
|
|
50814
50834
|
// src/hooks/useAppHotkeys.ts
|
|
50815
|
-
import { useCallback as
|
|
50835
|
+
import { useCallback as useCallback98, useEffect as useEffect66, useRef as useRef90 } from "react";
|
|
50816
50836
|
function iframeContentWindow(iframe) {
|
|
50817
50837
|
try {
|
|
50818
50838
|
return iframe?.contentWindow ?? null;
|
|
@@ -51022,22 +51042,22 @@ function useAppHotkeys({
|
|
|
51022
51042
|
}) {
|
|
51023
51043
|
const previewHotkeyWindowRef = useRef90(null);
|
|
51024
51044
|
const previewHistoryCleanupRef = useRef90(null);
|
|
51025
|
-
const readHistoryFile =
|
|
51045
|
+
const readHistoryFile = useCallback98(
|
|
51026
51046
|
(path) => path === STUDIO_MOTION_PATH ? readOptionalProjectFile(path) : readProjectFile(path),
|
|
51027
51047
|
[readOptionalProjectFile, readProjectFile]
|
|
51028
51048
|
);
|
|
51029
|
-
const writeHistoryFile =
|
|
51049
|
+
const writeHistoryFile = useCallback98(
|
|
51030
51050
|
async (path, content) => {
|
|
51031
51051
|
domEditSaveTimestampRef.current = Date.now();
|
|
51032
51052
|
await writeProjectFile(path, content);
|
|
51033
51053
|
},
|
|
51034
51054
|
[domEditSaveTimestampRef, writeProjectFile]
|
|
51035
51055
|
);
|
|
51036
|
-
const serializeHistoryFiles =
|
|
51056
|
+
const serializeHistoryFiles = useCallback98(
|
|
51037
51057
|
(paths, task) => serializeStudioFileMutations(writeProjectFile, paths, task),
|
|
51038
51058
|
[writeProjectFile]
|
|
51039
51059
|
);
|
|
51040
|
-
const applyHistory =
|
|
51060
|
+
const applyHistory = useCallback98(
|
|
51041
51061
|
async (direction) => {
|
|
51042
51062
|
if (tryApplyBeatHistory(direction, editHistory.state, showToast)) return;
|
|
51043
51063
|
await waitForPendingDomEditSaves();
|
|
@@ -51075,8 +51095,8 @@ function useAppHotkeys({
|
|
|
51075
51095
|
forceReloadSdkSession
|
|
51076
51096
|
]
|
|
51077
51097
|
);
|
|
51078
|
-
const handleUndo =
|
|
51079
|
-
const handleRedo =
|
|
51098
|
+
const handleUndo = useCallback98(() => applyHistory("undo"), [applyHistory]);
|
|
51099
|
+
const handleRedo = useCallback98(() => applyHistory("redo"), [applyHistory]);
|
|
51080
51100
|
const cbRef = useRef90(null);
|
|
51081
51101
|
cbRef.current = {
|
|
51082
51102
|
handleTimelineElementDelete,
|
|
@@ -51096,7 +51116,7 @@ function useAppHotkeys({
|
|
|
51096
51116
|
domEditSelectionRef,
|
|
51097
51117
|
showToast
|
|
51098
51118
|
};
|
|
51099
|
-
const handleAppKeyDown =
|
|
51119
|
+
const handleAppKeyDown = useCallback98((event) => {
|
|
51100
51120
|
const cb = cbRef.current;
|
|
51101
51121
|
const key = event.key.toLowerCase();
|
|
51102
51122
|
if (event.metaKey || event.ctrlKey) {
|
|
@@ -51109,7 +51129,7 @@ function useAppHotkeys({
|
|
|
51109
51129
|
window.addEventListener("keydown", handleAppKeyDown, true);
|
|
51110
51130
|
return () => window.removeEventListener("keydown", handleAppKeyDown, true);
|
|
51111
51131
|
}, [handleAppKeyDown]);
|
|
51112
|
-
const syncPreviewTimelineHotkey =
|
|
51132
|
+
const syncPreviewTimelineHotkey = useCallback98(
|
|
51113
51133
|
(iframe) => {
|
|
51114
51134
|
const nextWindow = iframeContentWindow(iframe);
|
|
51115
51135
|
if (previewHotkeyWindowRef.current === nextWindow) return;
|
|
@@ -51134,7 +51154,7 @@ function useAppHotkeys({
|
|
|
51134
51154
|
},
|
|
51135
51155
|
[handleAppKeyDown]
|
|
51136
51156
|
);
|
|
51137
|
-
const handleHistoryHotkey =
|
|
51157
|
+
const handleHistoryHotkey = useCallback98((event) => {
|
|
51138
51158
|
if (!(event.metaKey || event.ctrlKey) || shouldIgnoreHistoryShortcut(event.target)) return;
|
|
51139
51159
|
handleUndoRedoKey(
|
|
51140
51160
|
event,
|
|
@@ -51142,7 +51162,7 @@ function useAppHotkeys({
|
|
|
51142
51162
|
() => void cbRef.current.handleRedo()
|
|
51143
51163
|
);
|
|
51144
51164
|
}, []);
|
|
51145
|
-
const syncPreviewHistoryHotkey =
|
|
51165
|
+
const syncPreviewHistoryHotkey = useCallback98(
|
|
51146
51166
|
(iframe) => {
|
|
51147
51167
|
previewHistoryCleanupRef.current?.();
|
|
51148
51168
|
previewHistoryCleanupRef.current = null;
|
|
@@ -51180,7 +51200,7 @@ function useAppHotkeys({
|
|
|
51180
51200
|
}
|
|
51181
51201
|
|
|
51182
51202
|
// src/hooks/useClipboard.ts
|
|
51183
|
-
import { useCallback as
|
|
51203
|
+
import { useCallback as useCallback99, useRef as useRef91 } from "react";
|
|
51184
51204
|
|
|
51185
51205
|
// src/utils/clipboardPayload.ts
|
|
51186
51206
|
function insertAsSibling(source, newHtml, selector, selectorIndex) {
|
|
@@ -51290,7 +51310,7 @@ function useClipboard({
|
|
|
51290
51310
|
const clipboardRef = useRef91(null);
|
|
51291
51311
|
const projectIdRef = useRef91(projectId);
|
|
51292
51312
|
projectIdRef.current = projectId;
|
|
51293
|
-
const handleCopy =
|
|
51313
|
+
const handleCopy = useCallback99(() => {
|
|
51294
51314
|
const { selectedElementId, elements } = usePlayerStore.getState();
|
|
51295
51315
|
if (selectedElementId) {
|
|
51296
51316
|
const element = elements.find((el) => (el.key ?? el.id) === selectedElementId);
|
|
@@ -51344,7 +51364,7 @@ function useClipboard({
|
|
|
51344
51364
|
}
|
|
51345
51365
|
return false;
|
|
51346
51366
|
}, [activeCompPath, domEditSelectionRef, previewIframeRef, showToast]);
|
|
51347
|
-
const handlePaste =
|
|
51367
|
+
const handlePaste = useCallback99(async () => {
|
|
51348
51368
|
const payload = clipboardRef.current;
|
|
51349
51369
|
if (!payload) {
|
|
51350
51370
|
showToast("Nothing to paste.", "info");
|
|
@@ -51400,7 +51420,7 @@ function useClipboard({
|
|
|
51400
51420
|
showToast,
|
|
51401
51421
|
writeProjectFile
|
|
51402
51422
|
]);
|
|
51403
|
-
const handleCut =
|
|
51423
|
+
const handleCut = useCallback99(async () => {
|
|
51404
51424
|
const copied = handleCopy();
|
|
51405
51425
|
if (!copied) return false;
|
|
51406
51426
|
const { selectedElementId, elements } = usePlayerStore.getState();
|
|
@@ -51762,11 +51782,11 @@ function useCaptionDetection({
|
|
|
51762
51782
|
}
|
|
51763
51783
|
|
|
51764
51784
|
// src/hooks/useRenderClipContent.ts
|
|
51765
|
-
import { useCallback as
|
|
51785
|
+
import { useCallback as useCallback102 } from "react";
|
|
51766
51786
|
import { createElement as createElement2 } from "react";
|
|
51767
51787
|
|
|
51768
51788
|
// src/player/components/AudioWaveform.tsx
|
|
51769
|
-
import { memo as memo34, useRef as useRef92, useState as useState77, useCallback as
|
|
51789
|
+
import { memo as memo34, useRef as useRef92, useState as useState77, useCallback as useCallback100, useEffect as useEffect68 } from "react";
|
|
51770
51790
|
import { jsx as jsx112, jsxs as jsxs98 } from "react/jsx-runtime";
|
|
51771
51791
|
var BAR_W = 2;
|
|
51772
51792
|
var GAP = 1;
|
|
@@ -51843,7 +51863,7 @@ var AudioWaveform = memo34(function AudioWaveform2({
|
|
|
51843
51863
|
cancelled = true;
|
|
51844
51864
|
};
|
|
51845
51865
|
}, [audioUrl, waveformUrl, cacheKey, peaks]);
|
|
51846
|
-
const draw =
|
|
51866
|
+
const draw = useCallback100(() => {
|
|
51847
51867
|
const container = containerRef.current;
|
|
51848
51868
|
const barsEl = barsRef.current;
|
|
51849
51869
|
if (!container || !barsEl || !peaks) return;
|
|
@@ -51864,7 +51884,7 @@ var AudioWaveform = memo34(function AudioWaveform2({
|
|
|
51864
51884
|
}
|
|
51865
51885
|
barsEl.innerHTML = html2;
|
|
51866
51886
|
}, [peaks, trimStartFraction, trimEndFraction]);
|
|
51867
|
-
const setContainerRef =
|
|
51887
|
+
const setContainerRef = useCallback100(
|
|
51868
51888
|
(el) => {
|
|
51869
51889
|
roRef.current?.disconnect();
|
|
51870
51890
|
containerRef.current = el;
|
|
@@ -51908,7 +51928,7 @@ var AudioWaveform = memo34(function AudioWaveform2({
|
|
|
51908
51928
|
});
|
|
51909
51929
|
|
|
51910
51930
|
// src/player/components/ImageThumbnail.tsx
|
|
51911
|
-
import { memo as memo35, useRef as useRef93, useState as useState78, useCallback as
|
|
51931
|
+
import { memo as memo35, useRef as useRef93, useState as useState78, useCallback as useCallback101, useEffect as useEffect69 } from "react";
|
|
51912
51932
|
import { jsx as jsx113, jsxs as jsxs99 } from "react/jsx-runtime";
|
|
51913
51933
|
var ImageThumbnail = memo35(function ImageThumbnail2({
|
|
51914
51934
|
imageSrc,
|
|
@@ -51921,7 +51941,7 @@ var ImageThumbnail = memo35(function ImageThumbnail2({
|
|
|
51921
51941
|
const [aspect, setAspect] = useState78(16 / 9);
|
|
51922
51942
|
const ioRef = useRef93(null);
|
|
51923
51943
|
const roRef = useRef93(null);
|
|
51924
|
-
const setContainerRef =
|
|
51944
|
+
const setContainerRef = useCallback101((el) => {
|
|
51925
51945
|
ioRef.current?.disconnect();
|
|
51926
51946
|
roRef.current?.disconnect();
|
|
51927
51947
|
if (!el) return;
|
|
@@ -52074,7 +52094,7 @@ function useRenderClipContent({
|
|
|
52074
52094
|
activePreviewUrl,
|
|
52075
52095
|
effectiveTimelineDuration
|
|
52076
52096
|
}) {
|
|
52077
|
-
return
|
|
52097
|
+
return useCallback102(
|
|
52078
52098
|
// Pre-existing clip-content dispatcher; reduced by extracting renderAudioClip.
|
|
52079
52099
|
// fallow-ignore-next-line complexity
|
|
52080
52100
|
(el, style) => {
|
|
@@ -52146,11 +52166,11 @@ function useRenderClipContent({
|
|
|
52146
52166
|
}
|
|
52147
52167
|
|
|
52148
52168
|
// src/hooks/useConsoleErrorCapture.ts
|
|
52149
|
-
import { useCallback as
|
|
52169
|
+
import { useCallback as useCallback103, useEffect as useEffect70, useRef as useRef94, useState as useState79 } from "react";
|
|
52150
52170
|
function useConsoleErrorCapture(previewIframe) {
|
|
52151
52171
|
const [consoleErrors, setConsoleErrors] = useState79(null);
|
|
52152
52172
|
const consoleErrorsRef = useRef94([]);
|
|
52153
|
-
const resetErrors =
|
|
52173
|
+
const resetErrors = useCallback103(() => {
|
|
52154
52174
|
consoleErrorsRef.current = [];
|
|
52155
52175
|
setConsoleErrors(null);
|
|
52156
52176
|
}, []);
|
|
@@ -52219,7 +52239,7 @@ function useConsoleErrorCapture(previewIframe) {
|
|
|
52219
52239
|
}
|
|
52220
52240
|
|
|
52221
52241
|
// src/hooks/useFrameCapture.ts
|
|
52222
|
-
import { useState as useState80, useCallback as
|
|
52242
|
+
import { useState as useState80, useCallback as useCallback104, useRef as useRef95 } from "react";
|
|
52223
52243
|
|
|
52224
52244
|
// src/utils/projectRouting.ts
|
|
52225
52245
|
var PROJECT_HASH_PREFIX = "#project/";
|
|
@@ -52308,10 +52328,10 @@ function useFrameCapture({
|
|
|
52308
52328
|
setCaptureFrameTime(usePlayerStore.getState().currentTime);
|
|
52309
52329
|
return liveTime.subscribe(setCaptureFrameTime);
|
|
52310
52330
|
});
|
|
52311
|
-
const refreshCaptureFrameTime =
|
|
52331
|
+
const refreshCaptureFrameTime = useCallback104(() => {
|
|
52312
52332
|
setCaptureFrameTime(usePlayerStore.getState().currentTime);
|
|
52313
52333
|
}, []);
|
|
52314
|
-
const handleCaptureFrameClick =
|
|
52334
|
+
const handleCaptureFrameClick = useCallback104(
|
|
52315
52335
|
async (event) => {
|
|
52316
52336
|
if (!projectId) return;
|
|
52317
52337
|
event.preventDefault();
|
|
@@ -52388,7 +52408,7 @@ function useFrameCapture({
|
|
|
52388
52408
|
}
|
|
52389
52409
|
|
|
52390
52410
|
// src/hooks/useLintModal.ts
|
|
52391
|
-
import { useState as useState81, useCallback as
|
|
52411
|
+
import { useState as useState81, useCallback as useCallback105, useEffect as useEffect71, useRef as useRef96, useMemo as useMemo37 } from "react";
|
|
52392
52412
|
function parseFinding(f) {
|
|
52393
52413
|
return {
|
|
52394
52414
|
severity: f.severity === "error" ? "error" : "warning",
|
|
@@ -52403,7 +52423,7 @@ function useLintModal(projectId, refreshKey) {
|
|
|
52403
52423
|
const [linting, setLinting] = useState81(false);
|
|
52404
52424
|
const [backgroundFindings, setBackgroundFindings] = useState81([]);
|
|
52405
52425
|
const autoLintRanRef = useRef96(false);
|
|
52406
|
-
const runLint =
|
|
52426
|
+
const runLint = useCallback105(
|
|
52407
52427
|
async (opts) => {
|
|
52408
52428
|
if (!projectId) return;
|
|
52409
52429
|
if (!opts?.background) setLinting(true);
|
|
@@ -52428,7 +52448,7 @@ function useLintModal(projectId, refreshKey) {
|
|
|
52428
52448
|
},
|
|
52429
52449
|
[projectId]
|
|
52430
52450
|
);
|
|
52431
|
-
const handleLint =
|
|
52451
|
+
const handleLint = useCallback105(() => runLint(), [runLint]);
|
|
52432
52452
|
const prevProjectIdRef = useRef96(projectId);
|
|
52433
52453
|
useEffect71(() => {
|
|
52434
52454
|
if (projectId !== prevProjectIdRef.current) {
|
|
@@ -52444,8 +52464,8 @@ function useLintModal(projectId, refreshKey) {
|
|
|
52444
52464
|
const timer = setTimeout(() => void runLint({ background: true }), 1e3);
|
|
52445
52465
|
return () => clearTimeout(timer);
|
|
52446
52466
|
}, [projectId, refreshKey, runLint]);
|
|
52447
|
-
const closeLintModal =
|
|
52448
|
-
const groupFindings =
|
|
52467
|
+
const closeLintModal = useCallback105(() => setLintModal(null), []);
|
|
52468
|
+
const groupFindings = useCallback105(
|
|
52449
52469
|
(keyFn) => {
|
|
52450
52470
|
const map = /* @__PURE__ */ new Map();
|
|
52451
52471
|
for (const f of backgroundFindings) {
|
|
@@ -52477,7 +52497,7 @@ function useLintModal(projectId, refreshKey) {
|
|
|
52477
52497
|
}
|
|
52478
52498
|
|
|
52479
52499
|
// src/hooks/useToast.ts
|
|
52480
|
-
import { useState as useState82, useCallback as
|
|
52500
|
+
import { useState as useState82, useCallback as useCallback106, useRef as useRef97 } from "react";
|
|
52481
52501
|
var AUTO_DISMISS_MS2 = 4e3;
|
|
52482
52502
|
var EXIT_MS = 160;
|
|
52483
52503
|
var MAX_TOASTS = 3;
|
|
@@ -52485,21 +52505,21 @@ var nextToastId = 1;
|
|
|
52485
52505
|
function useToast() {
|
|
52486
52506
|
const [toasts, setToasts] = useState82([]);
|
|
52487
52507
|
const timersRef = useRef97(/* @__PURE__ */ new Map());
|
|
52488
|
-
const clearTimer =
|
|
52508
|
+
const clearTimer = useCallback106((id) => {
|
|
52489
52509
|
const timer = timersRef.current.get(id);
|
|
52490
52510
|
if (timer) {
|
|
52491
52511
|
clearTimeout(timer);
|
|
52492
52512
|
timersRef.current.delete(id);
|
|
52493
52513
|
}
|
|
52494
52514
|
}, []);
|
|
52495
|
-
const removeToast =
|
|
52515
|
+
const removeToast = useCallback106(
|
|
52496
52516
|
(id) => {
|
|
52497
52517
|
clearTimer(id);
|
|
52498
52518
|
setToasts((prev) => prev.filter((t) => t.id !== id));
|
|
52499
52519
|
},
|
|
52500
52520
|
[clearTimer]
|
|
52501
52521
|
);
|
|
52502
|
-
const dismissToast =
|
|
52522
|
+
const dismissToast = useCallback106(
|
|
52503
52523
|
(id) => {
|
|
52504
52524
|
clearTimer(id);
|
|
52505
52525
|
setToasts((prev) => prev.map((t) => t.id === id ? { ...t, leaving: true } : t));
|
|
@@ -52508,7 +52528,7 @@ function useToast() {
|
|
|
52508
52528
|
},
|
|
52509
52529
|
[clearTimer, removeToast]
|
|
52510
52530
|
);
|
|
52511
|
-
const showToast =
|
|
52531
|
+
const showToast = useCallback106(
|
|
52512
52532
|
(message, tone = "error") => {
|
|
52513
52533
|
const id = nextToastId++;
|
|
52514
52534
|
setToasts((prev) => {
|
|
@@ -52534,14 +52554,14 @@ function useToast() {
|
|
|
52534
52554
|
}
|
|
52535
52555
|
|
|
52536
52556
|
// src/hooks/useCompositionContentLoader.ts
|
|
52537
|
-
import { useCallback as
|
|
52557
|
+
import { useCallback as useCallback107 } from "react";
|
|
52538
52558
|
function useCompositionContentLoader({
|
|
52539
52559
|
projectId,
|
|
52540
52560
|
setEditingFile,
|
|
52541
52561
|
setActiveCompPath,
|
|
52542
52562
|
showToast
|
|
52543
52563
|
}) {
|
|
52544
|
-
return
|
|
52564
|
+
return useCallback107(
|
|
52545
52565
|
(comp) => {
|
|
52546
52566
|
setActiveCompPath(comp.endsWith(".html") ? comp : null);
|
|
52547
52567
|
setEditingFile({ path: comp, content: null });
|
|
@@ -52560,7 +52580,7 @@ function useCompositionContentLoader({
|
|
|
52560
52580
|
}
|
|
52561
52581
|
|
|
52562
52582
|
// src/hooks/useStudioUrlState.ts
|
|
52563
|
-
import { useCallback as
|
|
52583
|
+
import { useCallback as useCallback108, useEffect as useEffect72, useRef as useRef98, useState as useState83 } from "react";
|
|
52564
52584
|
|
|
52565
52585
|
// src/utils/studioUrlState.ts
|
|
52566
52586
|
var VALID_TABS = ["layers", "design", "renders", "slideshow", "variables"];
|
|
@@ -52693,7 +52713,7 @@ function useStudioUrlState({
|
|
|
52693
52713
|
const [selectionHydrated, setSelectionHydrated] = useState83(initialState2.selection == null);
|
|
52694
52714
|
const pendingSelectionRef = useRef98(initialState2.selection);
|
|
52695
52715
|
const stableTimeRef = useRef98(initialState2.currentTime);
|
|
52696
|
-
const buildUrlState =
|
|
52716
|
+
const buildUrlState = useCallback108(
|
|
52697
52717
|
() => ({
|
|
52698
52718
|
activeCompPath,
|
|
52699
52719
|
currentTime: stableTimeRef.current,
|
|
@@ -52704,7 +52724,7 @@ function useStudioUrlState({
|
|
|
52704
52724
|
}),
|
|
52705
52725
|
[activeCompPath, domEditSelection, rightCollapsed, rightPanelTab]
|
|
52706
52726
|
);
|
|
52707
|
-
const applyUrlSelection =
|
|
52727
|
+
const applyUrlSelection = useCallback108(
|
|
52708
52728
|
(selection) => {
|
|
52709
52729
|
if (!selection) {
|
|
52710
52730
|
applyDomSelection(null, { revealPanel: false });
|
|
@@ -52820,7 +52840,7 @@ function useStudioUrlState({
|
|
|
52820
52840
|
}
|
|
52821
52841
|
|
|
52822
52842
|
// src/hooks/useStudioContextValue.ts
|
|
52823
|
-
import { useCallback as
|
|
52843
|
+
import { useCallback as useCallback109, useMemo as useMemo38, useRef as useRef99, useState as useState84 } from "react";
|
|
52824
52844
|
function buildStudioContextValue(input) {
|
|
52825
52845
|
return {
|
|
52826
52846
|
projectId: input.projectId,
|
|
@@ -52866,21 +52886,21 @@ function useInspectorState(rightPanelTab, rightInspectorPanes, rightCollapsed, i
|
|
|
52866
52886
|
function useDragOverlay(onImportFiles) {
|
|
52867
52887
|
const [active, setActive] = useState84(false);
|
|
52868
52888
|
const counterRef = useRef99(0);
|
|
52869
|
-
const onDragOver =
|
|
52889
|
+
const onDragOver = useCallback109((e) => {
|
|
52870
52890
|
if (!e.dataTransfer.types.includes("Files")) return;
|
|
52871
52891
|
e.preventDefault();
|
|
52872
52892
|
}, []);
|
|
52873
|
-
const onDragEnter =
|
|
52893
|
+
const onDragEnter = useCallback109((e) => {
|
|
52874
52894
|
if (!e.dataTransfer.types.includes("Files")) return;
|
|
52875
52895
|
e.preventDefault();
|
|
52876
52896
|
counterRef.current++;
|
|
52877
52897
|
setActive(true);
|
|
52878
52898
|
}, []);
|
|
52879
|
-
const onDragLeave =
|
|
52899
|
+
const onDragLeave = useCallback109(() => {
|
|
52880
52900
|
counterRef.current--;
|
|
52881
52901
|
if (counterRef.current === 0) setActive(false);
|
|
52882
52902
|
}, []);
|
|
52883
|
-
const onDrop =
|
|
52903
|
+
const onDrop = useCallback109(
|
|
52884
52904
|
(e) => {
|
|
52885
52905
|
counterRef.current = 0;
|
|
52886
52906
|
setActive(false);
|
|
@@ -52893,7 +52913,7 @@ function useDragOverlay(onImportFiles) {
|
|
|
52893
52913
|
return { active, onDragOver, onDragEnter, onDragLeave, onDrop };
|
|
52894
52914
|
}
|
|
52895
52915
|
function useGlobalFileDrop(handleTimelineFileDrop) {
|
|
52896
|
-
const onDrop =
|
|
52916
|
+
const onDrop = useCallback109(
|
|
52897
52917
|
(files) => {
|
|
52898
52918
|
const start = usePlayerStore.getState().currentTime;
|
|
52899
52919
|
void handleTimelineFileDrop(Array.from(files), { start, track: 0 });
|
|
@@ -52904,7 +52924,7 @@ function useGlobalFileDrop(handleTimelineFileDrop) {
|
|
|
52904
52924
|
}
|
|
52905
52925
|
|
|
52906
52926
|
// src/components/StudioHeader.tsx
|
|
52907
|
-
import { useRef as
|
|
52927
|
+
import { useRef as useRef101 } from "react";
|
|
52908
52928
|
|
|
52909
52929
|
// src/contexts/PanelLayoutContext.tsx
|
|
52910
52930
|
import { createContext as createContext8, useContext as useContext8, useMemo as useMemo39 } from "react";
|
|
@@ -52983,10 +53003,11 @@ function PanelLayoutProvider({
|
|
|
52983
53003
|
// src/contexts/ViewModeContext.tsx
|
|
52984
53004
|
import {
|
|
52985
53005
|
createContext as createContext9,
|
|
52986
|
-
useCallback as
|
|
53006
|
+
useCallback as useCallback110,
|
|
52987
53007
|
useContext as useContext9,
|
|
52988
53008
|
useEffect as useEffect73,
|
|
52989
53009
|
useMemo as useMemo40,
|
|
53010
|
+
useRef as useRef100,
|
|
52990
53011
|
useState as useState85
|
|
52991
53012
|
} from "react";
|
|
52992
53013
|
import { jsx as jsx115 } from "react/jsx-runtime";
|
|
@@ -53005,18 +53026,59 @@ function writeViewModeToUrl(mode) {
|
|
|
53005
53026
|
}
|
|
53006
53027
|
window.history.replaceState(window.history.state, "", url);
|
|
53007
53028
|
}
|
|
53029
|
+
function readHistoryLocation() {
|
|
53030
|
+
if (typeof window === "undefined") return null;
|
|
53031
|
+
return {
|
|
53032
|
+
href: window.location.href,
|
|
53033
|
+
state: window.history.state
|
|
53034
|
+
};
|
|
53035
|
+
}
|
|
53008
53036
|
function useViewModeState() {
|
|
53009
53037
|
const [viewMode, setMode] = useState85(() => readViewModeFromUrl());
|
|
53038
|
+
const guardsRef = useRef100(/* @__PURE__ */ new Set());
|
|
53039
|
+
const acceptedLocationRef = useRef100(readHistoryLocation());
|
|
53040
|
+
const canSetViewMode = useCallback110((mode) => {
|
|
53041
|
+
for (const guard of guardsRef.current) {
|
|
53042
|
+
if (!guard(mode)) return false;
|
|
53043
|
+
}
|
|
53044
|
+
return true;
|
|
53045
|
+
}, []);
|
|
53010
53046
|
useEffect73(() => {
|
|
53011
|
-
const onPopState = () =>
|
|
53047
|
+
const onPopState = () => {
|
|
53048
|
+
const mode = readViewModeFromUrl();
|
|
53049
|
+
if (mode !== viewMode && !canSetViewMode(mode)) {
|
|
53050
|
+
const acceptedLocation = acceptedLocationRef.current;
|
|
53051
|
+
if (acceptedLocation) {
|
|
53052
|
+
window.history.pushState(acceptedLocation.state, "", acceptedLocation.href);
|
|
53053
|
+
}
|
|
53054
|
+
return;
|
|
53055
|
+
}
|
|
53056
|
+
setMode(mode);
|
|
53057
|
+
acceptedLocationRef.current = readHistoryLocation();
|
|
53058
|
+
};
|
|
53012
53059
|
window.addEventListener("popstate", onPopState);
|
|
53013
53060
|
return () => window.removeEventListener("popstate", onPopState);
|
|
53061
|
+
}, [canSetViewMode, viewMode]);
|
|
53062
|
+
const setViewMode = useCallback110(
|
|
53063
|
+
(mode) => {
|
|
53064
|
+
if (!canSetViewMode(mode)) return false;
|
|
53065
|
+
setMode(mode);
|
|
53066
|
+
writeViewModeToUrl(mode);
|
|
53067
|
+
acceptedLocationRef.current = readHistoryLocation();
|
|
53068
|
+
return true;
|
|
53069
|
+
},
|
|
53070
|
+
[canSetViewMode]
|
|
53071
|
+
);
|
|
53072
|
+
const registerViewModeGuard = useCallback110((guard) => {
|
|
53073
|
+
guardsRef.current.add(guard);
|
|
53074
|
+
return () => {
|
|
53075
|
+
guardsRef.current.delete(guard);
|
|
53076
|
+
};
|
|
53014
53077
|
}, []);
|
|
53015
|
-
|
|
53016
|
-
|
|
53017
|
-
|
|
53018
|
-
|
|
53019
|
-
return useMemo40(() => ({ viewMode, setViewMode }), [viewMode, setViewMode]);
|
|
53078
|
+
return useMemo40(
|
|
53079
|
+
() => ({ viewMode, setViewMode, registerViewModeGuard }),
|
|
53080
|
+
[viewMode, setViewMode, registerViewModeGuard]
|
|
53081
|
+
);
|
|
53020
53082
|
}
|
|
53021
53083
|
var ViewModeContext = createContext9(null);
|
|
53022
53084
|
function useViewMode() {
|
|
@@ -53221,11 +53283,10 @@ var VIEW_MODE_OPTIONS = [
|
|
|
53221
53283
|
];
|
|
53222
53284
|
function ViewModeToggle() {
|
|
53223
53285
|
const { viewMode, setViewMode } = useViewMode();
|
|
53224
|
-
const tabRefs =
|
|
53286
|
+
const tabRefs = useRef101([]);
|
|
53225
53287
|
const selectMode = (mode) => {
|
|
53226
53288
|
if (mode === viewMode) return;
|
|
53227
|
-
trackStudioEvent("view_mode_toggle", { mode });
|
|
53228
|
-
setViewMode(mode);
|
|
53289
|
+
if (setViewMode(mode)) trackStudioEvent("view_mode_toggle", { mode });
|
|
53229
53290
|
};
|
|
53230
53291
|
const handleKeyDown = (e, index) => {
|
|
53231
53292
|
if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return;
|
|
@@ -53453,10 +53514,10 @@ function StudioHeader({
|
|
|
53453
53514
|
}
|
|
53454
53515
|
|
|
53455
53516
|
// src/hooks/useGestureCommit.ts
|
|
53456
|
-
import { useState as useState87, useCallback as
|
|
53517
|
+
import { useState as useState87, useCallback as useCallback112, useRef as useRef103, useEffect as useEffect75 } from "react";
|
|
53457
53518
|
|
|
53458
53519
|
// src/hooks/useGestureRecording.ts
|
|
53459
|
-
import { useCallback as
|
|
53520
|
+
import { useCallback as useCallback111, useEffect as useEffect74, useRef as useRef102, useState as useState86 } from "react";
|
|
53460
53521
|
function readBasePosition(element, iframeEl) {
|
|
53461
53522
|
let baseOpacity = 1;
|
|
53462
53523
|
let baseScale = 1;
|
|
@@ -53575,10 +53636,10 @@ function createRecordingRefs() {
|
|
|
53575
53636
|
function useGestureRecording() {
|
|
53576
53637
|
const [isRecording, setIsRecording] = useState86(false);
|
|
53577
53638
|
const [recordingDuration, setRecordingDuration] = useState86(0);
|
|
53578
|
-
const isRecordingRef =
|
|
53579
|
-
const refs =
|
|
53580
|
-
const samplesRef =
|
|
53581
|
-
const trailRef =
|
|
53639
|
+
const isRecordingRef = useRef102(false);
|
|
53640
|
+
const refs = useRef102(createRecordingRefs());
|
|
53641
|
+
const samplesRef = useRef102(refs.current.samples);
|
|
53642
|
+
const trailRef = useRef102(refs.current.trail);
|
|
53582
53643
|
useEffect74(() => {
|
|
53583
53644
|
const r = refs.current;
|
|
53584
53645
|
return () => {
|
|
@@ -53587,7 +53648,7 @@ function useGestureRecording() {
|
|
|
53587
53648
|
isRecordingRef.current = false;
|
|
53588
53649
|
};
|
|
53589
53650
|
}, []);
|
|
53590
|
-
const startRecording =
|
|
53651
|
+
const startRecording = useCallback111(
|
|
53591
53652
|
(element, iframeEl, elementEndTime) => {
|
|
53592
53653
|
if (isRecordingRef.current) return;
|
|
53593
53654
|
isRecordingRef.current = true;
|
|
@@ -53687,7 +53748,7 @@ function useGestureRecording() {
|
|
|
53687
53748
|
[]
|
|
53688
53749
|
// No deps — uses refs only for all mutable state
|
|
53689
53750
|
);
|
|
53690
|
-
const stopRecording =
|
|
53751
|
+
const stopRecording = useCallback111(() => {
|
|
53691
53752
|
if (!isRecordingRef.current) return [];
|
|
53692
53753
|
isRecordingRef.current = false;
|
|
53693
53754
|
const r = refs.current;
|
|
@@ -53717,7 +53778,7 @@ function useGestureRecording() {
|
|
|
53717
53778
|
setIsRecording(false);
|
|
53718
53779
|
return frozen;
|
|
53719
53780
|
}, []);
|
|
53720
|
-
const clearSamples =
|
|
53781
|
+
const clearSamples = useCallback111(() => {
|
|
53721
53782
|
const r = refs.current;
|
|
53722
53783
|
r.samples = [];
|
|
53723
53784
|
r.trail = [];
|
|
@@ -53974,13 +54035,13 @@ function useGestureCommit({
|
|
|
53974
54035
|
}) {
|
|
53975
54036
|
const gestureRecording = useGestureRecording();
|
|
53976
54037
|
const [gestureState, setGestureState] = useState87("idle");
|
|
53977
|
-
const gestureStateRef =
|
|
53978
|
-
const recordingAutoStopRef =
|
|
53979
|
-
const recordingStartTimeRef =
|
|
53980
|
-
const commitInFlightRef =
|
|
53981
|
-
const capturedSelectionRef =
|
|
54038
|
+
const gestureStateRef = useRef103("idle");
|
|
54039
|
+
const recordingAutoStopRef = useRef103(void 0);
|
|
54040
|
+
const recordingStartTimeRef = useRef103(0);
|
|
54041
|
+
const commitInFlightRef = useRef103(false);
|
|
54042
|
+
const capturedSelectionRef = useRef103(null);
|
|
53982
54043
|
useEffect75(() => () => clearInterval(recordingAutoStopRef.current), []);
|
|
53983
|
-
const stopAndCommitRecording =
|
|
54044
|
+
const stopAndCommitRecording = useCallback112(async () => {
|
|
53984
54045
|
clearInterval(recordingAutoStopRef.current);
|
|
53985
54046
|
if (commitInFlightRef.current) {
|
|
53986
54047
|
return;
|
|
@@ -54146,7 +54207,7 @@ function useGestureCommit({
|
|
|
54146
54207
|
commitInFlightRef.current = false;
|
|
54147
54208
|
}
|
|
54148
54209
|
}, [gestureRecording, showToast, isGestureRecordingRef, domEditSessionRef]);
|
|
54149
|
-
const handleToggleRecording =
|
|
54210
|
+
const handleToggleRecording = useCallback112(() => {
|
|
54150
54211
|
if (gestureStateRef.current === "recording") {
|
|
54151
54212
|
void stopAndCommitRecording();
|
|
54152
54213
|
return;
|
|
@@ -54304,20 +54365,20 @@ var GestureTrailOverlay = memo36(function GestureTrailOverlay2({
|
|
|
54304
54365
|
});
|
|
54305
54366
|
|
|
54306
54367
|
// src/components/StudioLeftSidebar.tsx
|
|
54307
|
-
import { useCallback as
|
|
54368
|
+
import { useCallback as useCallback119 } from "react";
|
|
54308
54369
|
|
|
54309
54370
|
// src/components/sidebar/LeftSidebar.tsx
|
|
54310
54371
|
import {
|
|
54311
54372
|
memo as memo40,
|
|
54312
54373
|
useState as useState96,
|
|
54313
|
-
useCallback as
|
|
54374
|
+
useCallback as useCallback118,
|
|
54314
54375
|
useImperativeHandle,
|
|
54315
|
-
useRef as
|
|
54376
|
+
useRef as useRef109,
|
|
54316
54377
|
forwardRef as forwardRef3
|
|
54317
54378
|
} from "react";
|
|
54318
54379
|
|
|
54319
54380
|
// src/components/sidebar/CompositionsTab.tsx
|
|
54320
|
-
import { memo as memo37, useCallback as
|
|
54381
|
+
import { memo as memo37, useCallback as useCallback113, useEffect as useEffect76, useRef as useRef104, useState as useState88 } from "react";
|
|
54321
54382
|
import { jsx as jsx118, jsxs as jsxs102 } from "react/jsx-runtime";
|
|
54322
54383
|
var DEFAULT_PREVIEW_STAGE = { width: 1920, height: 1080 };
|
|
54323
54384
|
var CARD_W = 80;
|
|
@@ -54386,10 +54447,10 @@ function CompCard({
|
|
|
54386
54447
|
}) {
|
|
54387
54448
|
const [hovered, setHovered] = useState88(false);
|
|
54388
54449
|
const [stageSize, setStageSize] = useState88(DEFAULT_PREVIEW_STAGE);
|
|
54389
|
-
const iframeRef =
|
|
54390
|
-
const hoverTimer =
|
|
54391
|
-
const syncTimer =
|
|
54392
|
-
const requestIframePlaybackSync =
|
|
54450
|
+
const iframeRef = useRef104(null);
|
|
54451
|
+
const hoverTimer = useRef104(null);
|
|
54452
|
+
const syncTimer = useRef104(null);
|
|
54453
|
+
const requestIframePlaybackSync = useCallback113((shouldPlay) => {
|
|
54393
54454
|
if (syncTimer.current) {
|
|
54394
54455
|
clearTimeout(syncTimer.current);
|
|
54395
54456
|
syncTimer.current = null;
|
|
@@ -54547,7 +54608,7 @@ var CompositionsTab = memo37(function CompositionsTab2({
|
|
|
54547
54608
|
});
|
|
54548
54609
|
|
|
54549
54610
|
// src/components/sidebar/AssetsTab.tsx
|
|
54550
|
-
import { memo as memo38, useState as useState93, useCallback as
|
|
54611
|
+
import { memo as memo38, useState as useState93, useCallback as useCallback116, useRef as useRef107, useMemo as useMemo43, useEffect as useEffect81 } from "react";
|
|
54551
54612
|
|
|
54552
54613
|
// src/components/sidebar/assetHelpers.ts
|
|
54553
54614
|
function getCategory(path) {
|
|
@@ -54597,7 +54658,7 @@ var CATEGORY_LABELS = {
|
|
|
54597
54658
|
var FILTER_ORDER = ["audio", "images", "video", "fonts"];
|
|
54598
54659
|
|
|
54599
54660
|
// src/components/sidebar/AudioRow.tsx
|
|
54600
|
-
import { useState as useState89, useRef as
|
|
54661
|
+
import { useState as useState89, useRef as useRef105, useEffect as useEffect77, useCallback as useCallback114 } from "react";
|
|
54601
54662
|
|
|
54602
54663
|
// src/components/sidebar/AssetContextMenu.tsx
|
|
54603
54664
|
import { jsx as jsx119, jsxs as jsxs103 } from "react/jsx-runtime";
|
|
@@ -54726,24 +54787,24 @@ function AudioRow({
|
|
|
54726
54787
|
const [contextMenu, setContextMenu] = useState89(null);
|
|
54727
54788
|
const [playing, setPlaying] = useState89(false);
|
|
54728
54789
|
const [bars, setBars] = useState89([]);
|
|
54729
|
-
const audioRef =
|
|
54730
|
-
const actxRef =
|
|
54731
|
-
const analyserRef =
|
|
54732
|
-
const sourceRef =
|
|
54733
|
-
const animRef =
|
|
54790
|
+
const audioRef = useRef105(null);
|
|
54791
|
+
const actxRef = useRef105(null);
|
|
54792
|
+
const analyserRef = useRef105(null);
|
|
54793
|
+
const sourceRef = useRef105(null);
|
|
54794
|
+
const animRef = useRef105(0);
|
|
54734
54795
|
const name = basename2(asset);
|
|
54735
54796
|
const subtype = getAudioSubtype(asset);
|
|
54736
54797
|
const serveUrl = resolveMediaPreviewUrl(asset, projectId);
|
|
54737
|
-
const pointerDownRef =
|
|
54798
|
+
const pointerDownRef = useRef105(null);
|
|
54738
54799
|
const setSelectedElementId = usePlayerStore((s) => s.setSelectedElementId);
|
|
54739
54800
|
const requestClipReveal = usePlayerStore((s) => s.requestClipReveal);
|
|
54740
54801
|
const elements = usePlayerStore((s) => s.elements);
|
|
54741
54802
|
const setPreviewAsset = useAssetPreviewStore((s) => s.setPreviewAsset);
|
|
54742
54803
|
const clearPreviewAsset = useAssetPreviewStore((s) => s.clearPreviewAsset);
|
|
54743
|
-
const handlePointerDown =
|
|
54804
|
+
const handlePointerDown = useCallback114((e) => {
|
|
54744
54805
|
pointerDownRef.current = { x: e.clientX, y: e.clientY };
|
|
54745
54806
|
}, []);
|
|
54746
|
-
const handlePointerUp =
|
|
54807
|
+
const handlePointerUp = useCallback114(
|
|
54747
54808
|
(e) => {
|
|
54748
54809
|
const origin = pointerDownRef.current;
|
|
54749
54810
|
pointerDownRef.current = null;
|
|
@@ -54807,7 +54868,7 @@ function AudioRow({
|
|
|
54807
54868
|
}
|
|
54808
54869
|
return () => cancelAnimationFrame(animRef.current);
|
|
54809
54870
|
}, [playing]);
|
|
54810
|
-
const togglePlay =
|
|
54871
|
+
const togglePlay = useCallback114(async () => {
|
|
54811
54872
|
if (playing) {
|
|
54812
54873
|
audioRef.current?.pause();
|
|
54813
54874
|
setPlaying(false);
|
|
@@ -54976,7 +55037,7 @@ function GlobalAssetsView({ searchQuery }) {
|
|
|
54976
55037
|
}
|
|
54977
55038
|
|
|
54978
55039
|
// src/components/sidebar/AssetCard.tsx
|
|
54979
|
-
import { useState as useState92, useEffect as useEffect80, useRef as
|
|
55040
|
+
import { useState as useState92, useEffect as useEffect80, useRef as useRef106, useCallback as useCallback115 } from "react";
|
|
54980
55041
|
|
|
54981
55042
|
// src/components/ui/VideoFrameThumbnail.tsx
|
|
54982
55043
|
import { useState as useState91, useEffect as useEffect79 } from "react";
|
|
@@ -55101,16 +55162,16 @@ function AssetCard({
|
|
|
55101
55162
|
const probedDuration = useProbedDuration(serveUrl, !isVideo || duration != null);
|
|
55102
55163
|
const resolvedDuration = duration ?? probedDuration ?? void 0;
|
|
55103
55164
|
const durationLabel = formatDuration(resolvedDuration ?? 0);
|
|
55104
|
-
const pointerDownRef =
|
|
55165
|
+
const pointerDownRef = useRef106(null);
|
|
55105
55166
|
const setSelectedElementId = usePlayerStore((s) => s.setSelectedElementId);
|
|
55106
55167
|
const requestClipReveal = usePlayerStore((s) => s.requestClipReveal);
|
|
55107
55168
|
const elements = usePlayerStore((s) => s.elements);
|
|
55108
55169
|
const setPreviewAsset = useAssetPreviewStore((s) => s.setPreviewAsset);
|
|
55109
55170
|
const clearPreviewAsset = useAssetPreviewStore((s) => s.clearPreviewAsset);
|
|
55110
|
-
const handlePointerDown =
|
|
55171
|
+
const handlePointerDown = useCallback115((e) => {
|
|
55111
55172
|
pointerDownRef.current = { x: e.clientX, y: e.clientY };
|
|
55112
55173
|
}, []);
|
|
55113
|
-
const handlePointerUp =
|
|
55174
|
+
const handlePointerUp = useCallback115(
|
|
55114
55175
|
(e) => {
|
|
55115
55176
|
const origin = pointerDownRef.current;
|
|
55116
55177
|
pointerDownRef.current = null;
|
|
@@ -55303,7 +55364,7 @@ var AssetsTab = memo38(function AssetsTab2({
|
|
|
55303
55364
|
onRename,
|
|
55304
55365
|
onAddAssetToTimeline
|
|
55305
55366
|
}) {
|
|
55306
|
-
const fileInputRef =
|
|
55367
|
+
const fileInputRef = useRef107(null);
|
|
55307
55368
|
const [dragOver, setDragOver] = useState93(false);
|
|
55308
55369
|
const [copiedPath, setCopiedPath] = useState93(null);
|
|
55309
55370
|
const [activeFilter, setActiveFilter] = useState93("all");
|
|
@@ -55311,7 +55372,7 @@ var AssetsTab = memo38(function AssetsTab2({
|
|
|
55311
55372
|
const [searchQuery, setSearchQuery] = useState93("");
|
|
55312
55373
|
const [viewMode, setViewMode] = useState93("local");
|
|
55313
55374
|
const [manifest, setManifest] = useState93(/* @__PURE__ */ new Map());
|
|
55314
|
-
const manifest404Ref =
|
|
55375
|
+
const manifest404Ref = useRef107(/* @__PURE__ */ new Set());
|
|
55315
55376
|
const assetsKey = assets.join("|");
|
|
55316
55377
|
useEffect81(() => {
|
|
55317
55378
|
if (manifest404Ref.current.has(projectId)) return;
|
|
@@ -55340,7 +55401,7 @@ var AssetsTab = memo38(function AssetsTab2({
|
|
|
55340
55401
|
cancelled = true;
|
|
55341
55402
|
};
|
|
55342
55403
|
}, [projectId, assetsKey]);
|
|
55343
|
-
const handleDrop =
|
|
55404
|
+
const handleDrop = useCallback116(
|
|
55344
55405
|
(e) => {
|
|
55345
55406
|
e.preventDefault();
|
|
55346
55407
|
setDragOver(false);
|
|
@@ -55348,7 +55409,7 @@ var AssetsTab = memo38(function AssetsTab2({
|
|
|
55348
55409
|
},
|
|
55349
55410
|
[onImport]
|
|
55350
55411
|
);
|
|
55351
|
-
const handleCopyPath =
|
|
55412
|
+
const handleCopyPath = useCallback116(async (path) => {
|
|
55352
55413
|
const copied = await copyTextToClipboard(path);
|
|
55353
55414
|
if (copied) {
|
|
55354
55415
|
setCopiedPath(path);
|
|
@@ -55632,7 +55693,7 @@ var AssetsTab = memo38(function AssetsTab2({
|
|
|
55632
55693
|
});
|
|
55633
55694
|
|
|
55634
55695
|
// src/components/sidebar/BlocksTab.tsx
|
|
55635
|
-
import { memo as memo39, useState as useState95, useCallback as
|
|
55696
|
+
import { memo as memo39, useState as useState95, useCallback as useCallback117, useRef as useRef108, useEffect as useEffect83 } from "react";
|
|
55636
55697
|
import { createPortal as createPortal7 } from "react-dom";
|
|
55637
55698
|
|
|
55638
55699
|
// src/hooks/useBlockCatalog.ts
|
|
@@ -55926,16 +55987,16 @@ function BlockCard({
|
|
|
55926
55987
|
}) {
|
|
55927
55988
|
const [hovered, setHovered] = useState95(false);
|
|
55928
55989
|
const [adding, setAdding] = useState95(false);
|
|
55929
|
-
const hoverTimer =
|
|
55990
|
+
const hoverTimer = useRef108(null);
|
|
55930
55991
|
const colors = getCategoryColors(category);
|
|
55931
55992
|
const needsWebGL = tags?.includes("html-in-canvas") || tags?.includes("webgl");
|
|
55932
|
-
const handleEnter =
|
|
55993
|
+
const handleEnter = useCallback117(() => {
|
|
55933
55994
|
hoverTimer.current = setTimeout(() => {
|
|
55934
55995
|
setHovered(true);
|
|
55935
55996
|
onPreview?.({ videoUrl, posterUrl, title });
|
|
55936
55997
|
}, 300);
|
|
55937
55998
|
}, [onPreview, videoUrl, posterUrl, title]);
|
|
55938
|
-
const handleLeave =
|
|
55999
|
+
const handleLeave = useCallback117(() => {
|
|
55939
56000
|
if (hoverTimer.current) {
|
|
55940
56001
|
clearTimeout(hoverTimer.current);
|
|
55941
56002
|
hoverTimer.current = null;
|
|
@@ -55948,7 +56009,7 @@ function BlockCard({
|
|
|
55948
56009
|
if (hoverTimer.current) clearTimeout(hoverTimer.current);
|
|
55949
56010
|
};
|
|
55950
56011
|
}, []);
|
|
55951
|
-
const handleAdd =
|
|
56012
|
+
const handleAdd = useCallback117(
|
|
55952
56013
|
(e) => {
|
|
55953
56014
|
e.stopPropagation();
|
|
55954
56015
|
if (adding || !onAdd) return;
|
|
@@ -55959,7 +56020,7 @@ function BlockCard({
|
|
|
55959
56020
|
[onAdd, adding]
|
|
55960
56021
|
);
|
|
55961
56022
|
const { activeCompPath, compositionDimensions } = useStudioShellContext();
|
|
55962
|
-
const handleShowPrompt =
|
|
56023
|
+
const handleShowPrompt = useCallback117(
|
|
55963
56024
|
(e) => {
|
|
55964
56025
|
e.stopPropagation();
|
|
55965
56026
|
const state = usePlayerStore.getState();
|
|
@@ -56104,11 +56165,11 @@ function PromptPreviewModal({
|
|
|
56104
56165
|
}) {
|
|
56105
56166
|
const [value, setValue] = useState95(prompt);
|
|
56106
56167
|
const [copied, setCopied] = useState95(false);
|
|
56107
|
-
const textareaRef =
|
|
56168
|
+
const textareaRef = useRef108(null);
|
|
56108
56169
|
useEffect83(() => {
|
|
56109
56170
|
requestAnimationFrame(() => textareaRef.current?.focus());
|
|
56110
56171
|
}, []);
|
|
56111
|
-
const handleCopy =
|
|
56172
|
+
const handleCopy = useCallback117(() => {
|
|
56112
56173
|
navigator.clipboard.writeText(value);
|
|
56113
56174
|
setCopied(true);
|
|
56114
56175
|
setTimeout(() => setCopied(false), 1500);
|
|
@@ -56232,14 +56293,14 @@ var LeftSidebar = memo40(
|
|
|
56232
56293
|
onAddAssetToTimeline
|
|
56233
56294
|
}, ref) {
|
|
56234
56295
|
const [tab, setTab] = useState96(getPersistedTab);
|
|
56235
|
-
const tabRef =
|
|
56296
|
+
const tabRef = useRef109(tab);
|
|
56236
56297
|
tabRef.current = tab;
|
|
56237
|
-
const selectTab =
|
|
56298
|
+
const selectTab = useCallback118((t) => {
|
|
56238
56299
|
setTab(t);
|
|
56239
56300
|
localStorage.setItem(STORAGE_KEY, t);
|
|
56240
56301
|
trackStudioEvent("tab_switch", { panel: "left_sidebar", tab: t });
|
|
56241
56302
|
}, []);
|
|
56242
|
-
const getTab =
|
|
56303
|
+
const getTab = useCallback118(() => tabRef.current, []);
|
|
56243
56304
|
useImperativeHandle(ref, () => ({ selectTab, getTab }), [selectTab, getTab]);
|
|
56244
56305
|
return /* @__PURE__ */ jsx126(
|
|
56245
56306
|
"div",
|
|
@@ -56580,7 +56641,7 @@ function StudioLeftSidebar({
|
|
|
56580
56641
|
handleImportFiles,
|
|
56581
56642
|
handleContentChange
|
|
56582
56643
|
} = useFileManagerContext();
|
|
56583
|
-
const handleRenderComposition =
|
|
56644
|
+
const handleRenderComposition = useCallback119(
|
|
56584
56645
|
async (comp) => {
|
|
56585
56646
|
await waitForPendingDomEditSaves();
|
|
56586
56647
|
const { format, quality, fps } = getPersistedRenderSettings();
|
|
@@ -56700,13 +56761,13 @@ function StudioLeftSidebar({
|
|
|
56700
56761
|
}
|
|
56701
56762
|
|
|
56702
56763
|
// src/components/StudioRightPanel.tsx
|
|
56703
|
-
import { useCallback as
|
|
56764
|
+
import { useCallback as useCallback135, useEffect as useEffect90, useRef as useRef115 } from "react";
|
|
56704
56765
|
|
|
56705
56766
|
// src/components/editor/LayersPanel.tsx
|
|
56706
|
-
import { memo as memo41, useState as useState99, useCallback as
|
|
56767
|
+
import { memo as memo41, useState as useState99, useCallback as useCallback121, useEffect as useEffect84, useRef as useRef111 } from "react";
|
|
56707
56768
|
|
|
56708
56769
|
// src/components/editor/useLayerDrag.ts
|
|
56709
|
-
import { useRef as
|
|
56770
|
+
import { useRef as useRef110, useState as useState98, useCallback as useCallback120 } from "react";
|
|
56710
56771
|
var DRAG_THRESHOLD_PX3 = 4;
|
|
56711
56772
|
function isLayerDraggable(layer) {
|
|
56712
56773
|
if (!(layer.selector || layer.id)) return false;
|
|
@@ -56773,10 +56834,10 @@ function useLayerDrag({
|
|
|
56773
56834
|
onReorder,
|
|
56774
56835
|
onSingleSibling
|
|
56775
56836
|
}) {
|
|
56776
|
-
const dragRef =
|
|
56837
|
+
const dragRef = useRef110(null);
|
|
56777
56838
|
const [dragKey, setDragKey] = useState98(null);
|
|
56778
56839
|
const [insertionLineY, setInsertionLineY] = useState98(null);
|
|
56779
|
-
const handleRowPointerDown =
|
|
56840
|
+
const handleRowPointerDown = useCallback120(
|
|
56780
56841
|
(layerIndex, e) => {
|
|
56781
56842
|
if (e.button !== 0) return;
|
|
56782
56843
|
const layer = visibleLayers[layerIndex];
|
|
@@ -56803,7 +56864,7 @@ function useLayerDrag({
|
|
|
56803
56864
|
},
|
|
56804
56865
|
[visibleLayers, scrollContainerRef, onSingleSibling]
|
|
56805
56866
|
);
|
|
56806
|
-
const handleContainerPointerMove =
|
|
56867
|
+
const handleContainerPointerMove = useCallback120(
|
|
56807
56868
|
(e) => {
|
|
56808
56869
|
const drag = dragRef.current;
|
|
56809
56870
|
if (!drag) return;
|
|
@@ -56829,7 +56890,7 @@ function useLayerDrag({
|
|
|
56829
56890
|
},
|
|
56830
56891
|
[visibleLayers, scrollContainerRef]
|
|
56831
56892
|
);
|
|
56832
|
-
const handleContainerPointerUp =
|
|
56893
|
+
const handleContainerPointerUp = useCallback120(() => {
|
|
56833
56894
|
const drag = dragRef.current;
|
|
56834
56895
|
dragRef.current = null;
|
|
56835
56896
|
setDragKey(null);
|
|
@@ -56978,15 +57039,15 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
56978
57039
|
} = useDomEditContext();
|
|
56979
57040
|
const [layers, setLayers] = useState99([]);
|
|
56980
57041
|
const [collapsed, setCollapsed] = useState99({});
|
|
56981
|
-
const prevDocVersionRef =
|
|
56982
|
-
const scrollContainerRef =
|
|
57042
|
+
const prevDocVersionRef = useRef111(0);
|
|
57043
|
+
const scrollContainerRef = useRef111(null);
|
|
56983
57044
|
const mirrorLayerReorderToTimeline = useLayerReorderTimelineMirror();
|
|
56984
57045
|
const { scheduleReveal } = useLayerRevealOverride({
|
|
56985
57046
|
isPlaying,
|
|
56986
57047
|
selectedElement: domEditSelection?.element ?? null
|
|
56987
57048
|
});
|
|
56988
57049
|
const isMasterView = !activeCompPath || activeCompPath === "index.html";
|
|
56989
|
-
const collectLayers =
|
|
57050
|
+
const collectLayers = useCallback121(() => {
|
|
56990
57051
|
const iframe = previewIframeRef.current;
|
|
56991
57052
|
if (!iframe) return;
|
|
56992
57053
|
let doc = null;
|
|
@@ -57033,7 +57094,7 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
57033
57094
|
throttle.cancel();
|
|
57034
57095
|
};
|
|
57035
57096
|
}, [collectLayers]);
|
|
57036
|
-
const resolveSelection =
|
|
57097
|
+
const resolveSelection = useCallback121(
|
|
57037
57098
|
(layer) => {
|
|
57038
57099
|
let el = layer.element;
|
|
57039
57100
|
if (!el.isConnected) {
|
|
@@ -57053,7 +57114,7 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
57053
57114
|
},
|
|
57054
57115
|
[activeCompPath, isMasterView, previewIframeRef, activeGroupElement]
|
|
57055
57116
|
);
|
|
57056
|
-
const seekToLayer =
|
|
57117
|
+
const seekToLayer = useCallback121(
|
|
57057
57118
|
async (layer) => {
|
|
57058
57119
|
const selection = await resolveSelection(layer);
|
|
57059
57120
|
if (!selection) return;
|
|
@@ -57082,7 +57143,7 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
57082
57143
|
},
|
|
57083
57144
|
[currentTime, resolveSelection, timelineElements]
|
|
57084
57145
|
);
|
|
57085
|
-
const handleSelectLayer =
|
|
57146
|
+
const handleSelectLayer = useCallback121(
|
|
57086
57147
|
async (layer) => {
|
|
57087
57148
|
const selection = await resolveSelection(layer);
|
|
57088
57149
|
if (!selection) return;
|
|
@@ -57092,7 +57153,7 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
57092
57153
|
},
|
|
57093
57154
|
[resolveSelection, applyDomSelection, seekToLayer, scheduleReveal]
|
|
57094
57155
|
);
|
|
57095
|
-
const handleLayerDoubleClick =
|
|
57156
|
+
const handleLayerDoubleClick = useCallback121(
|
|
57096
57157
|
async (layer) => {
|
|
57097
57158
|
const selection = await resolveSelection(layer);
|
|
57098
57159
|
if (selection?.element.hasAttribute("data-hf-group")) {
|
|
@@ -57103,7 +57164,7 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
57103
57164
|
},
|
|
57104
57165
|
[resolveSelection, setActiveGroupElement, handleSelectLayer]
|
|
57105
57166
|
);
|
|
57106
|
-
const handleLayerHover =
|
|
57167
|
+
const handleLayerHover = useCallback121(
|
|
57107
57168
|
async (layer) => {
|
|
57108
57169
|
if (!layer) {
|
|
57109
57170
|
updateDomEditHoverSelection(null);
|
|
@@ -57114,11 +57175,11 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
57114
57175
|
},
|
|
57115
57176
|
[resolveSelection, updateDomEditHoverSelection]
|
|
57116
57177
|
);
|
|
57117
|
-
const toggleCollapse =
|
|
57178
|
+
const toggleCollapse = useCallback121((key, e) => {
|
|
57118
57179
|
e.stopPropagation();
|
|
57119
57180
|
setCollapsed((prev) => ({ ...prev, [key]: !prev[key] }));
|
|
57120
57181
|
}, []);
|
|
57121
|
-
const handleReorder =
|
|
57182
|
+
const handleReorder = useCallback121(
|
|
57122
57183
|
(event) => {
|
|
57123
57184
|
const { siblingLayers, fromIndex, toIndex } = event;
|
|
57124
57185
|
const reordered = [...siblingLayers];
|
|
@@ -57181,7 +57242,7 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
57181
57242
|
);
|
|
57182
57243
|
const selectedKey = domEditSelection ? getDomEditLayerKey(domEditSelection) : null;
|
|
57183
57244
|
const visibleLayers = getVisibleLayers(layers, collapsed);
|
|
57184
|
-
const handleSingleSibling =
|
|
57245
|
+
const handleSingleSibling = useCallback121(() => {
|
|
57185
57246
|
showToast("Only one layer at this level", "info");
|
|
57186
57247
|
}, [showToast]);
|
|
57187
57248
|
const {
|
|
@@ -57310,10 +57371,10 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
57310
57371
|
});
|
|
57311
57372
|
|
|
57312
57373
|
// src/captions/components/CaptionPropertyPanel.tsx
|
|
57313
|
-
import { memo as memo43, useCallback as
|
|
57374
|
+
import { memo as memo43, useCallback as useCallback123, useState as useState100 } from "react";
|
|
57314
57375
|
|
|
57315
57376
|
// src/captions/components/CaptionAnimationPanel.tsx
|
|
57316
|
-
import { memo as memo42, useCallback as
|
|
57377
|
+
import { memo as memo42, useCallback as useCallback122 } from "react";
|
|
57317
57378
|
|
|
57318
57379
|
// src/captions/components/shared.tsx
|
|
57319
57380
|
import { jsx as jsx130, jsxs as jsxs113 } from "react/jsx-runtime";
|
|
@@ -57476,25 +57537,25 @@ var CaptionAnimationPanel = memo42(function CaptionAnimationPanel2() {
|
|
|
57476
57537
|
}
|
|
57477
57538
|
const group = resolvedGroupId ? model?.groups.get(resolvedGroupId) : void 0;
|
|
57478
57539
|
const animation = group?.animation;
|
|
57479
|
-
const handleEntranceChange =
|
|
57540
|
+
const handleEntranceChange = useCallback122(
|
|
57480
57541
|
(update) => {
|
|
57481
57542
|
if (resolvedGroupId) updateGroupAnimation(resolvedGroupId, "entrance", update);
|
|
57482
57543
|
},
|
|
57483
57544
|
[resolvedGroupId, updateGroupAnimation]
|
|
57484
57545
|
);
|
|
57485
|
-
const handleHighlightChange =
|
|
57546
|
+
const handleHighlightChange = useCallback122(
|
|
57486
57547
|
(update) => {
|
|
57487
57548
|
if (resolvedGroupId) updateGroupAnimation(resolvedGroupId, "highlight", update);
|
|
57488
57549
|
},
|
|
57489
57550
|
[resolvedGroupId, updateGroupAnimation]
|
|
57490
57551
|
);
|
|
57491
|
-
const handleExitChange =
|
|
57552
|
+
const handleExitChange = useCallback122(
|
|
57492
57553
|
(update) => {
|
|
57493
57554
|
if (resolvedGroupId) updateGroupAnimation(resolvedGroupId, "exit", update);
|
|
57494
57555
|
},
|
|
57495
57556
|
[resolvedGroupId, updateGroupAnimation]
|
|
57496
57557
|
);
|
|
57497
|
-
const handleApplyToAll =
|
|
57558
|
+
const handleApplyToAll = useCallback122(() => {
|
|
57498
57559
|
if (animation) applyAnimationToAll(animation);
|
|
57499
57560
|
}, [animation, applyAnimationToAll]);
|
|
57500
57561
|
if (!group || !resolvedGroupId || !animation) {
|
|
@@ -57572,7 +57633,7 @@ var CaptionPropertyPanel = memo43(function CaptionPropertyPanel2({
|
|
|
57572
57633
|
...groupStyle,
|
|
57573
57634
|
...segmentOverrides
|
|
57574
57635
|
};
|
|
57575
|
-
const applyToIframeDom =
|
|
57636
|
+
const applyToIframeDom = useCallback123(
|
|
57576
57637
|
(updates) => {
|
|
57577
57638
|
const iframe = iframeRef.current;
|
|
57578
57639
|
if (!iframe || !model) return;
|
|
@@ -57646,7 +57707,7 @@ var CaptionPropertyPanel = memo43(function CaptionPropertyPanel2({
|
|
|
57646
57707
|
},
|
|
57647
57708
|
[iframeRef, model, selectedSegmentIds]
|
|
57648
57709
|
);
|
|
57649
|
-
const handleStyleChange =
|
|
57710
|
+
const handleStyleChange = useCallback123(
|
|
57650
57711
|
(updates) => {
|
|
57651
57712
|
if (selectedGroupId) {
|
|
57652
57713
|
updateGroupStyle(selectedGroupId, updates);
|
|
@@ -57746,7 +57807,7 @@ var CaptionPropertyPanel = memo43(function CaptionPropertyPanel2({
|
|
|
57746
57807
|
});
|
|
57747
57808
|
|
|
57748
57809
|
// src/components/editor/BlockParamsPanel.tsx
|
|
57749
|
-
import { memo as memo44, useState as useState101, useCallback as
|
|
57810
|
+
import { memo as memo44, useState as useState101, useCallback as useCallback124 } from "react";
|
|
57750
57811
|
import { jsx as jsx133, jsxs as jsxs116 } from "react/jsx-runtime";
|
|
57751
57812
|
var BlockParamsPanel = memo44(function BlockParamsPanel2({
|
|
57752
57813
|
blockTitle,
|
|
@@ -57761,7 +57822,7 @@ var BlockParamsPanel = memo44(function BlockParamsPanel2({
|
|
|
57761
57822
|
}
|
|
57762
57823
|
return initial;
|
|
57763
57824
|
});
|
|
57764
|
-
const handleChange =
|
|
57825
|
+
const handleChange = useCallback124((key, value) => {
|
|
57765
57826
|
setValues((prev) => ({ ...prev, [key]: value }));
|
|
57766
57827
|
}, []);
|
|
57767
57828
|
return /* @__PURE__ */ jsxs116("div", { className: "flex flex-col h-full", children: [
|
|
@@ -57871,10 +57932,10 @@ function ParamControl({
|
|
|
57871
57932
|
}
|
|
57872
57933
|
|
|
57873
57934
|
// src/components/renders/RenderQueue.tsx
|
|
57874
|
-
import { memo as memo46, useState as useState103, useRef as
|
|
57935
|
+
import { memo as memo46, useState as useState103, useRef as useRef112, useEffect as useEffect85, useId as useId2 } from "react";
|
|
57875
57936
|
|
|
57876
57937
|
// src/components/renders/RenderQueueItem.tsx
|
|
57877
|
-
import { memo as memo45, useCallback as
|
|
57938
|
+
import { memo as memo45, useCallback as useCallback125, useState as useState102 } from "react";
|
|
57878
57939
|
import { Fragment as Fragment42, jsx as jsx134, jsxs as jsxs117 } from "react/jsx-runtime";
|
|
57879
57940
|
function formatDuration2(ms) {
|
|
57880
57941
|
if (ms < 1e3) return `${ms}ms`;
|
|
@@ -57897,10 +57958,10 @@ var RenderQueueItem = memo45(function RenderQueueItem2({
|
|
|
57897
57958
|
const [videoReady, setVideoReady] = useState102(false);
|
|
57898
57959
|
const [confirmingDelete, setConfirmingDelete] = useState102(false);
|
|
57899
57960
|
const fileSrc = `/api/projects/${projectId}/renders/file/${job.filename}`;
|
|
57900
|
-
const handleOpen =
|
|
57961
|
+
const handleOpen = useCallback125(() => {
|
|
57901
57962
|
window.open(fileSrc, "_blank");
|
|
57902
57963
|
}, [fileSrc]);
|
|
57903
|
-
const handleDownload =
|
|
57964
|
+
const handleDownload = useCallback125(
|
|
57904
57965
|
(e) => {
|
|
57905
57966
|
e.stopPropagation();
|
|
57906
57967
|
const a = document.createElement("a");
|
|
@@ -58161,7 +58222,7 @@ var FORMAT_INFO = {
|
|
|
58161
58222
|
};
|
|
58162
58223
|
function FormatInfoTooltip({ format }) {
|
|
58163
58224
|
const [open, setOpen] = useState103(false);
|
|
58164
|
-
const timeoutRef =
|
|
58225
|
+
const timeoutRef = useRef112(void 0);
|
|
58165
58226
|
const panelId = useId2();
|
|
58166
58227
|
const show = () => {
|
|
58167
58228
|
clearTimeout(timeoutRef.current);
|
|
@@ -58375,7 +58436,7 @@ var RenderQueue = memo46(function RenderQueue2({
|
|
|
58375
58436
|
onDismissActionError,
|
|
58376
58437
|
compositionDimensions
|
|
58377
58438
|
}) {
|
|
58378
|
-
const listRef =
|
|
58439
|
+
const listRef = useRef112(null);
|
|
58379
58440
|
useEffect85(() => {
|
|
58380
58441
|
if (listRef.current) {
|
|
58381
58442
|
listRef.current.scrollTo({ top: listRef.current.scrollHeight, behavior: "smooth" });
|
|
@@ -58484,11 +58545,11 @@ var RenderQueue = memo46(function RenderQueue2({
|
|
|
58484
58545
|
});
|
|
58485
58546
|
|
|
58486
58547
|
// src/components/panels/SlideshowPanel.tsx
|
|
58487
|
-
import { useState as useState105, useEffect as useEffect86, useCallback as
|
|
58548
|
+
import { useState as useState105, useEffect as useEffect86, useCallback as useCallback127, useRef as useRef113 } from "react";
|
|
58488
58549
|
import { parseSlideshowManifest } from "@hyperframes/core/slideshow";
|
|
58489
58550
|
|
|
58490
58551
|
// src/components/panels/SlideshowSubPanels.tsx
|
|
58491
|
-
import { useState as useState104, useCallback as
|
|
58552
|
+
import { useState as useState104, useCallback as useCallback126, useId as useId3 } from "react";
|
|
58492
58553
|
import { jsx as jsx136, jsxs as jsxs119 } from "react/jsx-runtime";
|
|
58493
58554
|
function SectionHeader({
|
|
58494
58555
|
children,
|
|
@@ -58673,7 +58734,7 @@ function BranchTree({
|
|
|
58673
58734
|
}) {
|
|
58674
58735
|
const [newLabel, setNewLabel] = useState104("");
|
|
58675
58736
|
const inputId = useId3();
|
|
58676
|
-
const handleCreate =
|
|
58737
|
+
const handleCreate = useCallback126(() => {
|
|
58677
58738
|
const label = newLabel.trim();
|
|
58678
58739
|
if (!label) return;
|
|
58679
58740
|
onCreateSequence(label);
|
|
@@ -58734,7 +58795,7 @@ function BranchItem({
|
|
|
58734
58795
|
}) {
|
|
58735
58796
|
const [editing, setEditing] = useState104(false);
|
|
58736
58797
|
const [draft, setDraft] = useState104(seq.label);
|
|
58737
|
-
const commitRename =
|
|
58798
|
+
const commitRename = useCallback126(() => {
|
|
58738
58799
|
const label = draft.trim();
|
|
58739
58800
|
if (label && label !== seq.label) onRename(seq.id, label);
|
|
58740
58801
|
setEditing(false);
|
|
@@ -58832,7 +58893,7 @@ function HotspotTool({
|
|
|
58832
58893
|
const selectedElementId = domEditSelection?.element?.id ?? null;
|
|
58833
58894
|
const selectedHfId = domEditSelection?.hfId ?? null;
|
|
58834
58895
|
const elementKey2 = selectedElementId || selectedHfId;
|
|
58835
|
-
const handleMakeHotspot =
|
|
58896
|
+
const handleMakeHotspot = useCallback126(() => {
|
|
58836
58897
|
if (!selectedSceneId || !targetSequenceId || !elementKey2) return;
|
|
58837
58898
|
const id = `hotspot-${elementKey2}-${generateId()}`;
|
|
58838
58899
|
const label = hotspotLabel.trim() || elementKey2;
|
|
@@ -59121,8 +59182,8 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59121
59182
|
);
|
|
59122
59183
|
const currentTime = usePlayerStore((s) => s.currentTime);
|
|
59123
59184
|
const { domEditSelection } = useDomEditSelectionContext();
|
|
59124
|
-
const manifestRef =
|
|
59125
|
-
const notesCtrlRef =
|
|
59185
|
+
const manifestRef = useRef113(manifest);
|
|
59186
|
+
const notesCtrlRef = useRef113(makeSlideshowNotesController());
|
|
59126
59187
|
useEffect86(() => {
|
|
59127
59188
|
if (!compHtml) {
|
|
59128
59189
|
notesCtrlRef.current.flush();
|
|
@@ -59136,7 +59197,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59136
59197
|
manifestRef.current = parsed;
|
|
59137
59198
|
setSelectedSequenceId(null);
|
|
59138
59199
|
}, [compHtml]);
|
|
59139
|
-
const applyManifest =
|
|
59200
|
+
const applyManifest = useCallback127(
|
|
59140
59201
|
async (next) => {
|
|
59141
59202
|
const merged = notesCtrlRef.current.mergeIntoDiscrete(next);
|
|
59142
59203
|
setManifest(merged);
|
|
@@ -59149,7 +59210,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59149
59210
|
},
|
|
59150
59211
|
[onPersist]
|
|
59151
59212
|
);
|
|
59152
|
-
const applyNotesManifest =
|
|
59213
|
+
const applyNotesManifest = useCallback127(
|
|
59153
59214
|
(next) => {
|
|
59154
59215
|
setManifest(next);
|
|
59155
59216
|
manifestRef.current = next;
|
|
@@ -59163,7 +59224,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59163
59224
|
ctrl.flush();
|
|
59164
59225
|
};
|
|
59165
59226
|
}, []);
|
|
59166
|
-
const toggleSection =
|
|
59227
|
+
const toggleSection = useCallback127((key) => {
|
|
59167
59228
|
setExpandedSections((prev) => {
|
|
59168
59229
|
const next = new Set(prev);
|
|
59169
59230
|
if (next.has(key)) {
|
|
@@ -59177,25 +59238,25 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59177
59238
|
const activeSlides = selectedSequenceId ? (manifest.slideSequences ?? []).find((s) => s.id === selectedSequenceId)?.slides ?? [] : manifest.slides;
|
|
59178
59239
|
const selectedSlide = activeSlides.find((s) => s.sceneId === selectedSceneId);
|
|
59179
59240
|
const sequences = manifest.slideSequences ?? [];
|
|
59180
|
-
const handleSelectBranchSlide =
|
|
59241
|
+
const handleSelectBranchSlide = useCallback127((sequenceId, sceneId) => {
|
|
59181
59242
|
setSelectedSceneId(sceneId);
|
|
59182
59243
|
setSelectedSequenceId(sequenceId);
|
|
59183
59244
|
}, []);
|
|
59184
|
-
const handleToggleSlide =
|
|
59245
|
+
const handleToggleSlide = useCallback127(
|
|
59185
59246
|
(sceneId) => {
|
|
59186
59247
|
applyManifest(toggleMainLineSlide(manifestRef.current, sceneId)).catch(() => {
|
|
59187
59248
|
});
|
|
59188
59249
|
},
|
|
59189
59250
|
[applyManifest]
|
|
59190
59251
|
);
|
|
59191
|
-
const handleReorder =
|
|
59252
|
+
const handleReorder = useCallback127(
|
|
59192
59253
|
(sceneId, dir) => {
|
|
59193
59254
|
applyManifest(reorderMainLineSlide(manifestRef.current, sceneId, dir)).catch(() => {
|
|
59194
59255
|
});
|
|
59195
59256
|
},
|
|
59196
59257
|
[applyManifest]
|
|
59197
59258
|
);
|
|
59198
|
-
const handleSetNotes =
|
|
59259
|
+
const handleSetNotes = useCallback127(
|
|
59199
59260
|
(notes) => {
|
|
59200
59261
|
if (!selectedSceneId) return;
|
|
59201
59262
|
applyNotesManifest(
|
|
@@ -59204,7 +59265,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59204
59265
|
},
|
|
59205
59266
|
[selectedSceneId, selectedSequenceId, applyNotesManifest]
|
|
59206
59267
|
);
|
|
59207
|
-
const handleMarkFragment =
|
|
59268
|
+
const handleMarkFragment = useCallback127(() => {
|
|
59208
59269
|
if (!selectedSceneId) return;
|
|
59209
59270
|
applyManifest(
|
|
59210
59271
|
addFragment(
|
|
@@ -59216,7 +59277,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59216
59277
|
).catch(() => {
|
|
59217
59278
|
});
|
|
59218
59279
|
}, [selectedSceneId, selectedSequenceId, currentTime, applyManifest]);
|
|
59219
|
-
const handleRemoveFragment =
|
|
59280
|
+
const handleRemoveFragment = useCallback127(
|
|
59220
59281
|
(time) => {
|
|
59221
59282
|
if (!selectedSceneId) return;
|
|
59222
59283
|
applyManifest(
|
|
@@ -59226,7 +59287,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59226
59287
|
},
|
|
59227
59288
|
[selectedSceneId, selectedSequenceId, applyManifest]
|
|
59228
59289
|
);
|
|
59229
|
-
const handleCreateSequence =
|
|
59290
|
+
const handleCreateSequence = useCallback127(
|
|
59230
59291
|
(label) => {
|
|
59231
59292
|
const id = `seq-${generateId()}`;
|
|
59232
59293
|
applyManifest(createSequence(manifestRef.current, id, label)).catch(() => {
|
|
@@ -59234,14 +59295,14 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59234
59295
|
},
|
|
59235
59296
|
[applyManifest]
|
|
59236
59297
|
);
|
|
59237
|
-
const handleRenameSequence =
|
|
59298
|
+
const handleRenameSequence = useCallback127(
|
|
59238
59299
|
(id, label) => {
|
|
59239
59300
|
applyManifest(renameSequence(manifestRef.current, id, label)).catch(() => {
|
|
59240
59301
|
});
|
|
59241
59302
|
},
|
|
59242
59303
|
[applyManifest]
|
|
59243
59304
|
);
|
|
59244
|
-
const handleDeleteSequence =
|
|
59305
|
+
const handleDeleteSequence = useCallback127(
|
|
59245
59306
|
(id) => {
|
|
59246
59307
|
const seq = (manifestRef.current.slideSequences ?? []).find((s) => s.id === id);
|
|
59247
59308
|
const count = seq?.slides.length ?? 0;
|
|
@@ -59255,7 +59316,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59255
59316
|
},
|
|
59256
59317
|
[applyManifest]
|
|
59257
59318
|
);
|
|
59258
|
-
const handleAssign =
|
|
59319
|
+
const handleAssign = useCallback127(
|
|
59259
59320
|
(sequenceId, sceneId, assign) => {
|
|
59260
59321
|
applyManifest(assignToBranch(manifestRef.current, sequenceId, sceneId, assign)).catch(
|
|
59261
59322
|
() => {
|
|
@@ -59264,7 +59325,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59264
59325
|
},
|
|
59265
59326
|
[applyManifest]
|
|
59266
59327
|
);
|
|
59267
|
-
const handleAddHotspot =
|
|
59328
|
+
const handleAddHotspot = useCallback127(
|
|
59268
59329
|
(sceneId, hotspot) => {
|
|
59269
59330
|
applyManifest(
|
|
59270
59331
|
addHotspot(manifestRef.current, sceneId, hotspot, selectedSequenceId ?? void 0)
|
|
@@ -59273,7 +59334,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59273
59334
|
},
|
|
59274
59335
|
[selectedSequenceId, applyManifest]
|
|
59275
59336
|
);
|
|
59276
|
-
const handleRemoveHotspot =
|
|
59337
|
+
const handleRemoveHotspot = useCallback127(
|
|
59277
59338
|
(sceneId, hotspotId) => {
|
|
59278
59339
|
applyManifest(
|
|
59279
59340
|
removeHotspot(manifestRef.current, sceneId, hotspotId, selectedSequenceId ?? void 0)
|
|
@@ -59377,10 +59438,10 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
59377
59438
|
}
|
|
59378
59439
|
|
|
59379
59440
|
// src/components/panels/VariablesPanel.tsx
|
|
59380
|
-
import { memo as memo47, useCallback as
|
|
59441
|
+
import { memo as memo47, useCallback as useCallback131, useEffect as useEffect88, useMemo as useMemo45, useState as useState109 } from "react";
|
|
59381
59442
|
|
|
59382
59443
|
// src/hooks/useVariablesPersist.ts
|
|
59383
|
-
import { useCallback as
|
|
59444
|
+
import { useCallback as useCallback128 } from "react";
|
|
59384
59445
|
function useVariablesPersist({
|
|
59385
59446
|
sdkSession,
|
|
59386
59447
|
activeCompPath,
|
|
@@ -59391,7 +59452,7 @@ function useVariablesPersist({
|
|
|
59391
59452
|
domEditSaveTimestampRef,
|
|
59392
59453
|
publishSdkSession
|
|
59393
59454
|
}) {
|
|
59394
|
-
return
|
|
59455
|
+
return useCallback128(
|
|
59395
59456
|
async (label, mutate) => {
|
|
59396
59457
|
if (!sdkSession) return false;
|
|
59397
59458
|
const path = activeCompPath ?? "index.html";
|
|
@@ -59428,10 +59489,10 @@ function useVariablesPersist({
|
|
|
59428
59489
|
}
|
|
59429
59490
|
|
|
59430
59491
|
// src/components/panels/VariablesOtherCompositions.tsx
|
|
59431
|
-
import { useCallback as
|
|
59492
|
+
import { useCallback as useCallback130, useState as useState108 } from "react";
|
|
59432
59493
|
|
|
59433
59494
|
// src/hooks/useProjectCompositionVariables.ts
|
|
59434
|
-
import { useCallback as
|
|
59495
|
+
import { useCallback as useCallback129, useEffect as useEffect87, useState as useState106 } from "react";
|
|
59435
59496
|
import { openComposition as openComposition4 } from "@hyperframes/sdk";
|
|
59436
59497
|
async function readGroup(path, readProjectFile) {
|
|
59437
59498
|
let content;
|
|
@@ -59474,7 +59535,7 @@ function useProjectCompositionVariables(fileTree, excludePath, readProjectFile,
|
|
|
59474
59535
|
}
|
|
59475
59536
|
function useEditVariablesInFile(deps) {
|
|
59476
59537
|
const { readProjectFile, writeProjectFile, recordEdit, reloadPreview, domEditSaveTimestampRef } = deps;
|
|
59477
|
-
return
|
|
59538
|
+
return useCallback129(
|
|
59478
59539
|
async (path, label, mutate) => {
|
|
59479
59540
|
const originalContent = await readProjectFile(path);
|
|
59480
59541
|
await persistSdkSerialize(
|
|
@@ -59854,7 +59915,7 @@ function VariablesOtherCompositions({
|
|
|
59854
59915
|
domEditSaveTimestampRef
|
|
59855
59916
|
});
|
|
59856
59917
|
const [editingKey, setEditingKey] = useState108(null);
|
|
59857
|
-
const onSave =
|
|
59918
|
+
const onSave = useCallback130(
|
|
59858
59919
|
(path, decl) => {
|
|
59859
59920
|
setEditingKey(null);
|
|
59860
59921
|
void editInFile(
|
|
@@ -59865,7 +59926,7 @@ function VariablesOtherCompositions({
|
|
|
59865
59926
|
},
|
|
59866
59927
|
[editInFile]
|
|
59867
59928
|
);
|
|
59868
|
-
const onRemove =
|
|
59929
|
+
const onRemove = useCallback130(
|
|
59869
59930
|
(path, id) => {
|
|
59870
59931
|
void editInFile(
|
|
59871
59932
|
path,
|
|
@@ -60101,7 +60162,7 @@ var VariablesPanel = memo47(function VariablesPanel2({
|
|
|
60101
60162
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
60102
60163
|
[sdkSession, previewValues, refreshKey, revision]
|
|
60103
60164
|
);
|
|
60104
|
-
const copyToClipboard =
|
|
60165
|
+
const copyToClipboard = useCallback131(
|
|
60105
60166
|
(text, what) => {
|
|
60106
60167
|
void copyTextToClipboard(text).then(
|
|
60107
60168
|
(ok) => showToast(
|
|
@@ -60112,7 +60173,7 @@ var VariablesPanel = memo47(function VariablesPanel2({
|
|
|
60112
60173
|
},
|
|
60113
60174
|
[showToast]
|
|
60114
60175
|
);
|
|
60115
|
-
const dropPreviewOverride =
|
|
60176
|
+
const dropPreviewOverride = useCallback131(
|
|
60116
60177
|
(id) => {
|
|
60117
60178
|
if (previewValues && id in previewValues) {
|
|
60118
60179
|
const next = { ...previewValues };
|
|
@@ -60122,7 +60183,7 @@ var VariablesPanel = memo47(function VariablesPanel2({
|
|
|
60122
60183
|
},
|
|
60123
60184
|
[previewValues, setPreviewValues]
|
|
60124
60185
|
);
|
|
60125
|
-
const commitPreviewValue =
|
|
60186
|
+
const commitPreviewValue = useCallback131(
|
|
60126
60187
|
(id, value, declDefault) => {
|
|
60127
60188
|
const next = { ...previewValues ?? {} };
|
|
60128
60189
|
if (JSON.stringify(value) === JSON.stringify(declDefault)) {
|
|
@@ -60135,7 +60196,7 @@ var VariablesPanel = memo47(function VariablesPanel2({
|
|
|
60135
60196
|
},
|
|
60136
60197
|
[previewValues, setPreviewValues, reloadPreview]
|
|
60137
60198
|
);
|
|
60138
|
-
const runSchemaEdit =
|
|
60199
|
+
const runSchemaEdit = useCallback131(
|
|
60139
60200
|
async (label, mutate) => {
|
|
60140
60201
|
try {
|
|
60141
60202
|
const changed = await persistVariables(label, mutate);
|
|
@@ -60149,7 +60210,7 @@ var VariablesPanel = memo47(function VariablesPanel2({
|
|
|
60149
60210
|
},
|
|
60150
60211
|
[persistVariables, showToast]
|
|
60151
60212
|
);
|
|
60152
|
-
const handleAdd =
|
|
60213
|
+
const handleAdd = useCallback131(
|
|
60153
60214
|
(decl) => {
|
|
60154
60215
|
if (!sdkSession) return;
|
|
60155
60216
|
const check = sdkSession.can({ type: "declareVariable", declaration: decl });
|
|
@@ -60162,7 +60223,7 @@ var VariablesPanel = memo47(function VariablesPanel2({
|
|
|
60162
60223
|
},
|
|
60163
60224
|
[sdkSession, runSchemaEdit, showToast]
|
|
60164
60225
|
);
|
|
60165
|
-
const handleUpdate =
|
|
60226
|
+
const handleUpdate = useCallback131(
|
|
60166
60227
|
(decl) => {
|
|
60167
60228
|
if (!sdkSession) return;
|
|
60168
60229
|
const check = sdkSession.can({
|
|
@@ -60182,7 +60243,7 @@ var VariablesPanel = memo47(function VariablesPanel2({
|
|
|
60182
60243
|
},
|
|
60183
60244
|
[sdkSession, runSchemaEdit, showToast]
|
|
60184
60245
|
);
|
|
60185
|
-
const handleRemove =
|
|
60246
|
+
const handleRemove = useCallback131(
|
|
60186
60247
|
(id) => {
|
|
60187
60248
|
if (!sdkSession) return;
|
|
60188
60249
|
const check = sdkSession.can({ type: "removeVariableDeclaration", id });
|
|
@@ -60198,18 +60259,18 @@ var VariablesPanel = memo47(function VariablesPanel2({
|
|
|
60198
60259
|
},
|
|
60199
60260
|
[sdkSession, runSchemaEdit, dropPreviewOverride, showToast]
|
|
60200
60261
|
);
|
|
60201
|
-
const handleSetDefault =
|
|
60262
|
+
const handleSetDefault = useCallback131(
|
|
60202
60263
|
(id, value) => {
|
|
60203
60264
|
void runSchemaEdit(`Set default for "${id}"`, (s) => s.setVariableValue(id, value));
|
|
60204
60265
|
dropPreviewOverride(id);
|
|
60205
60266
|
},
|
|
60206
60267
|
[runSchemaEdit, dropPreviewOverride]
|
|
60207
60268
|
);
|
|
60208
|
-
const resetPreview =
|
|
60269
|
+
const resetPreview = useCallback131(() => {
|
|
60209
60270
|
setPreviewValues(null);
|
|
60210
60271
|
reloadPreview();
|
|
60211
60272
|
}, [setPreviewValues, reloadPreview]);
|
|
60212
|
-
const handleBind =
|
|
60273
|
+
const handleBind = useCallback131(
|
|
60213
60274
|
// Guard chain (session, selection, type-compat) — one branch per guard.
|
|
60214
60275
|
// fallow-ignore-next-line complexity
|
|
60215
60276
|
(action, id) => {
|
|
@@ -60342,7 +60403,7 @@ function PanelTabButton({
|
|
|
60342
60403
|
}
|
|
60343
60404
|
|
|
60344
60405
|
// src/hooks/useSlideshowPersist.ts
|
|
60345
|
-
import { useCallback as
|
|
60406
|
+
import { useCallback as useCallback132 } from "react";
|
|
60346
60407
|
|
|
60347
60408
|
// src/utils/setSlideshowManifest.ts
|
|
60348
60409
|
import {
|
|
@@ -60400,7 +60461,7 @@ function useSlideshowPersist({
|
|
|
60400
60461
|
publishSdkSession,
|
|
60401
60462
|
coalesceKey
|
|
60402
60463
|
}) {
|
|
60403
|
-
return
|
|
60464
|
+
return useCallback132(
|
|
60404
60465
|
async (manifest) => {
|
|
60405
60466
|
if (!sdkSession) return;
|
|
60406
60467
|
const path = activeCompPath ?? "index.html";
|
|
@@ -60434,26 +60495,65 @@ function useSlideshowPersist({
|
|
|
60434
60495
|
);
|
|
60435
60496
|
}
|
|
60436
60497
|
|
|
60498
|
+
// src/hooks/useSlideshowTabState.ts
|
|
60499
|
+
import { useEffect as useEffect89, useMemo as useMemo46 } from "react";
|
|
60500
|
+
import { SLIDESHOW_ISLAND_TYPE as SLIDESHOW_ISLAND_TYPE2, slideshowIslandRegex as slideshowIslandRegex2 } from "@hyperframes/core/slideshow";
|
|
60501
|
+
function useSlideshowTabState(params) {
|
|
60502
|
+
const { editingFileContent, previewIframeRef, refreshKey, rightPanelTab, setRightPanelTab } = params;
|
|
60503
|
+
const isSlideshowComposition = useMemo46(() => {
|
|
60504
|
+
if (!editingFileContent || !editingFileContent.includes(SLIDESHOW_ISLAND_TYPE2)) return false;
|
|
60505
|
+
return slideshowIslandRegex2("i").test(editingFileContent);
|
|
60506
|
+
}, [editingFileContent]);
|
|
60507
|
+
const slideshowScenes = useMemo46(() => {
|
|
60508
|
+
try {
|
|
60509
|
+
const win = previewIframeRef.current?.contentWindow;
|
|
60510
|
+
return (win?.__clipManifest?.scenes ?? []).map((s) => ({
|
|
60511
|
+
id: s.id,
|
|
60512
|
+
label: s.label,
|
|
60513
|
+
start: s.start,
|
|
60514
|
+
duration: s.duration
|
|
60515
|
+
}));
|
|
60516
|
+
} catch {
|
|
60517
|
+
return [];
|
|
60518
|
+
}
|
|
60519
|
+
}, [previewIframeRef, rightPanelTab, refreshKey]);
|
|
60520
|
+
useEffect89(() => {
|
|
60521
|
+
if (rightPanelTab === "slideshow" && !isSlideshowComposition) {
|
|
60522
|
+
setRightPanelTab("renders");
|
|
60523
|
+
}
|
|
60524
|
+
}, [rightPanelTab, isSlideshowComposition, setRightPanelTab]);
|
|
60525
|
+
return { isSlideshowComposition, slideshowScenes };
|
|
60526
|
+
}
|
|
60527
|
+
|
|
60437
60528
|
// src/components/DesignPanelPromoteProvider.tsx
|
|
60438
|
-
import { useCallback as
|
|
60529
|
+
import { useCallback as useCallback133 } from "react";
|
|
60439
60530
|
import { jsx as jsx143 } from "react/jsx-runtime";
|
|
60440
60531
|
function DesignPanelPromoteProvider({
|
|
60441
60532
|
selection,
|
|
60442
60533
|
projectId,
|
|
60443
60534
|
activeCompPath,
|
|
60444
60535
|
showToast,
|
|
60536
|
+
forceReloadSharedSdkSession,
|
|
60445
60537
|
children,
|
|
60446
60538
|
...persistDeps
|
|
60447
60539
|
}) {
|
|
60448
60540
|
const targetPath = selection?.sourceFile || activeCompPath || "index.html";
|
|
60449
60541
|
const handle = useSdkSession(projectId, targetPath, persistDeps.domEditSaveTimestampRef);
|
|
60450
|
-
const
|
|
60542
|
+
const rawPersist = useVariablesPersist({
|
|
60451
60543
|
...persistDeps,
|
|
60452
60544
|
sdkSession: handle.session,
|
|
60453
60545
|
publishSdkSession: handle.publish,
|
|
60454
60546
|
activeCompPath: targetPath
|
|
60455
60547
|
});
|
|
60456
|
-
const
|
|
60548
|
+
const persist2 = useCallback133(
|
|
60549
|
+
async (label, mutate) => {
|
|
60550
|
+
const committed = await rawPersist(label, mutate);
|
|
60551
|
+
if (committed) forceReloadSharedSdkSession?.();
|
|
60552
|
+
return committed;
|
|
60553
|
+
},
|
|
60554
|
+
[rawPersist, forceReloadSharedSdkSession]
|
|
60555
|
+
);
|
|
60556
|
+
const handlePersistError = useCallback133(
|
|
60457
60557
|
(error) => showToast(getStudioSaveErrorMessage(error), "error"),
|
|
60458
60558
|
[showToast]
|
|
60459
60559
|
);
|
|
@@ -60688,14 +60788,14 @@ async function applyColorGradingScopeUpdate({
|
|
|
60688
60788
|
}
|
|
60689
60789
|
|
|
60690
60790
|
// src/hooks/useInspectorSplitResize.ts
|
|
60691
|
-
import { useCallback as
|
|
60791
|
+
import { useCallback as useCallback134, useRef as useRef114, useState as useState110 } from "react";
|
|
60692
60792
|
var MIN_INSPECTOR_SPLIT_PERCENT = 20;
|
|
60693
60793
|
var MAX_INSPECTOR_SPLIT_PERCENT = 75;
|
|
60694
60794
|
function useInspectorSplitResize() {
|
|
60695
60795
|
const [layersPanePercent, setLayersPanePercent] = useState110(40);
|
|
60696
|
-
const splitContainerRef =
|
|
60697
|
-
const splitDragRef =
|
|
60698
|
-
const handleInspectorSplitResizeStart =
|
|
60796
|
+
const splitContainerRef = useRef114(null);
|
|
60797
|
+
const splitDragRef = useRef114(null);
|
|
60798
|
+
const handleInspectorSplitResizeStart = useCallback134(
|
|
60699
60799
|
(event) => {
|
|
60700
60800
|
event.preventDefault();
|
|
60701
60801
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
@@ -60708,7 +60808,7 @@ function useInspectorSplitResize() {
|
|
|
60708
60808
|
},
|
|
60709
60809
|
[layersPanePercent]
|
|
60710
60810
|
);
|
|
60711
|
-
const handleInspectorSplitResizeMove =
|
|
60811
|
+
const handleInspectorSplitResizeMove = useCallback134((event) => {
|
|
60712
60812
|
const drag = splitDragRef.current;
|
|
60713
60813
|
if (!drag || drag.height <= 0) return;
|
|
60714
60814
|
const deltaPercent = (event.clientY - drag.startY) / drag.height * 100;
|
|
@@ -60718,7 +60818,7 @@ function useInspectorSplitResize() {
|
|
|
60718
60818
|
);
|
|
60719
60819
|
setLayersPanePercent(next);
|
|
60720
60820
|
}, []);
|
|
60721
|
-
const handleInspectorSplitResizeEnd =
|
|
60821
|
+
const handleInspectorSplitResizeEnd = useCallback134(() => {
|
|
60722
60822
|
splitDragRef.current = null;
|
|
60723
60823
|
}, []);
|
|
60724
60824
|
return {
|
|
@@ -60741,6 +60841,7 @@ function StudioRightPanel({
|
|
|
60741
60841
|
onToggleRecording,
|
|
60742
60842
|
sdkSession,
|
|
60743
60843
|
publishSdkSession,
|
|
60844
|
+
forceReloadSdkSession,
|
|
60744
60845
|
reloadPreview,
|
|
60745
60846
|
domEditSaveTimestampRef,
|
|
60746
60847
|
recordEdit,
|
|
@@ -60820,7 +60921,8 @@ function StudioRightPanel({
|
|
|
60820
60921
|
refreshFileTree,
|
|
60821
60922
|
readProjectFile,
|
|
60822
60923
|
writeProjectFile,
|
|
60823
|
-
fileTree
|
|
60924
|
+
fileTree,
|
|
60925
|
+
editingFile
|
|
60824
60926
|
} = useFileManagerContext();
|
|
60825
60927
|
const onPersistSlideshow = useSlideshowPersist({
|
|
60826
60928
|
sdkSession,
|
|
@@ -60850,8 +60952,8 @@ function StudioRightPanel({
|
|
|
60850
60952
|
handleInspectorSplitResizeMove,
|
|
60851
60953
|
handleInspectorSplitResizeEnd
|
|
60852
60954
|
} = useInspectorSplitResize();
|
|
60853
|
-
const backgroundRemovalAbortRef =
|
|
60854
|
-
|
|
60955
|
+
const backgroundRemovalAbortRef = useRef115(null);
|
|
60956
|
+
useEffect90(
|
|
60855
60957
|
() => () => {
|
|
60856
60958
|
backgroundRemovalAbortRef.current?.abort();
|
|
60857
60959
|
},
|
|
@@ -60859,19 +60961,13 @@ function StudioRightPanel({
|
|
|
60859
60961
|
);
|
|
60860
60962
|
const renderJobs = renderQueue.jobs;
|
|
60861
60963
|
const inspectorTabActive = rightPanelTab === "design" || rightPanelTab === "layers";
|
|
60862
|
-
const slideshowScenes =
|
|
60863
|
-
|
|
60864
|
-
|
|
60865
|
-
|
|
60866
|
-
|
|
60867
|
-
|
|
60868
|
-
|
|
60869
|
-
duration: s.duration
|
|
60870
|
-
}));
|
|
60871
|
-
} catch {
|
|
60872
|
-
return [];
|
|
60873
|
-
}
|
|
60874
|
-
}, [previewIframeRef, rightPanelTab, refreshKey]);
|
|
60964
|
+
const { isSlideshowComposition, slideshowScenes } = useSlideshowTabState({
|
|
60965
|
+
editingFileContent: editingFile?.content,
|
|
60966
|
+
previewIframeRef,
|
|
60967
|
+
refreshKey,
|
|
60968
|
+
rightPanelTab,
|
|
60969
|
+
setRightPanelTab
|
|
60970
|
+
});
|
|
60875
60971
|
const designPaneOpen = inspectorTabActive && rightInspectorPanes.design && designPanelActive;
|
|
60876
60972
|
const layersPaneOpen = inspectorTabActive && rightInspectorPanes.layers && STUDIO_INSPECTOR_PANELS_ENABLED;
|
|
60877
60973
|
const handleInspectorPaneButtonClick = (pane) => {
|
|
@@ -60885,7 +60981,7 @@ function StudioRightPanel({
|
|
|
60885
60981
|
}
|
|
60886
60982
|
toggleRightInspectorPane(pane);
|
|
60887
60983
|
};
|
|
60888
|
-
const handleApplyColorGradingScope =
|
|
60984
|
+
const handleApplyColorGradingScope = useCallback135(
|
|
60889
60985
|
async (scope, value) => applyColorGradingScopeUpdate({
|
|
60890
60986
|
scope,
|
|
60891
60987
|
value,
|
|
@@ -60920,7 +61016,7 @@ function StudioRightPanel({
|
|
|
60920
61016
|
writeProjectFile
|
|
60921
61017
|
]
|
|
60922
61018
|
);
|
|
60923
|
-
const handleRemoveBackground =
|
|
61019
|
+
const handleRemoveBackground = useCallback135(
|
|
60924
61020
|
// fallow-ignore-next-line complexity
|
|
60925
61021
|
async (inputPath, options) => {
|
|
60926
61022
|
const response = await fetch(
|
|
@@ -60973,6 +61069,7 @@ function StudioRightPanel({
|
|
|
60973
61069
|
recordEdit,
|
|
60974
61070
|
reloadPreview,
|
|
60975
61071
|
domEditSaveTimestampRef,
|
|
61072
|
+
forceReloadSharedSdkSession: forceReloadSdkSession,
|
|
60976
61073
|
children: /* @__PURE__ */ jsx144(
|
|
60977
61074
|
PropertyPanel,
|
|
60978
61075
|
{
|
|
@@ -61129,7 +61226,7 @@ function StudioRightPanel({
|
|
|
61129
61226
|
onClick: () => setRightPanelTab("renders")
|
|
61130
61227
|
}
|
|
61131
61228
|
),
|
|
61132
|
-
/* @__PURE__ */ jsx144(
|
|
61229
|
+
isSlideshowComposition && /* @__PURE__ */ jsx144(
|
|
61133
61230
|
PanelTabButton,
|
|
61134
61231
|
{
|
|
61135
61232
|
label: "Slideshow",
|
|
@@ -61158,7 +61255,7 @@ function StudioRightPanel({
|
|
|
61158
61255
|
onClose: onCloseBlockParams ?? (() => {
|
|
61159
61256
|
})
|
|
61160
61257
|
}
|
|
61161
|
-
) : rightPanelTab === "slideshow" ? /* @__PURE__ */ jsx144(
|
|
61258
|
+
) : rightPanelTab === "slideshow" && isSlideshowComposition ? /* @__PURE__ */ jsx144(
|
|
61162
61259
|
SlideshowPanel,
|
|
61163
61260
|
{
|
|
61164
61261
|
scenes: slideshowScenes,
|
|
@@ -61224,11 +61321,11 @@ function StudioRightPanel({
|
|
|
61224
61321
|
}
|
|
61225
61322
|
|
|
61226
61323
|
// src/components/TimelineToolbar.tsx
|
|
61227
|
-
import { useEffect as
|
|
61324
|
+
import { useEffect as useEffect92, useRef as useRef116 } from "react";
|
|
61228
61325
|
import { Magnet, MagnifyingGlassMinus, MagnifyingGlassPlus } from "@phosphor-icons/react";
|
|
61229
61326
|
|
|
61230
61327
|
// src/hooks/useEnableKeyframes.ts
|
|
61231
|
-
import { useCallback as
|
|
61328
|
+
import { useCallback as useCallback136 } from "react";
|
|
61232
61329
|
var enableKeyframesTransactionCounter = 0;
|
|
61233
61330
|
function animatedProps(anim) {
|
|
61234
61331
|
if (!anim) return ["x", "y"];
|
|
@@ -61445,7 +61542,7 @@ async function applyArcWaypointAtPlayhead(session, sel, arcAnim, t, iframe) {
|
|
|
61445
61542
|
);
|
|
61446
61543
|
}
|
|
61447
61544
|
function useEnableKeyframes(sessionRef) {
|
|
61448
|
-
return
|
|
61545
|
+
return useCallback136(async () => {
|
|
61449
61546
|
const session = sessionRef.current;
|
|
61450
61547
|
if (!session) return;
|
|
61451
61548
|
const sel = session.domEditSelection;
|
|
@@ -61527,7 +61624,7 @@ function useEnableKeyframes(sessionRef) {
|
|
|
61527
61624
|
}
|
|
61528
61625
|
|
|
61529
61626
|
// src/hooks/useKeyframeKeyboard.ts
|
|
61530
|
-
import { useEffect as
|
|
61627
|
+
import { useEffect as useEffect91, useCallback as useCallback137 } from "react";
|
|
61531
61628
|
function isTextInput(el) {
|
|
61532
61629
|
if (!el) return false;
|
|
61533
61630
|
const tag = el.tagName;
|
|
@@ -61544,7 +61641,7 @@ function useKeyframeKeyboard({
|
|
|
61544
61641
|
onToggleExpand,
|
|
61545
61642
|
onNudgeKeyframe
|
|
61546
61643
|
}) {
|
|
61547
|
-
const handler =
|
|
61644
|
+
const handler = useCallback137(
|
|
61548
61645
|
(e) => {
|
|
61549
61646
|
if (!enabled2) return;
|
|
61550
61647
|
if (isTextInput(document.activeElement)) return;
|
|
@@ -61595,7 +61692,7 @@ function useKeyframeKeyboard({
|
|
|
61595
61692
|
onNudgeKeyframe
|
|
61596
61693
|
]
|
|
61597
61694
|
);
|
|
61598
|
-
|
|
61695
|
+
useEffect91(() => {
|
|
61599
61696
|
if (!enabled2) return;
|
|
61600
61697
|
window.addEventListener("keydown", handler, { capture: true });
|
|
61601
61698
|
return () => window.removeEventListener("keydown", handler, { capture: true });
|
|
@@ -61606,7 +61703,7 @@ function useKeyframeKeyboard({
|
|
|
61606
61703
|
import { Fragment as Fragment45, jsx as jsx145, jsxs as jsxs125 } from "react/jsx-runtime";
|
|
61607
61704
|
function useKeyframeToggle(session) {
|
|
61608
61705
|
const currentTime = usePlayerStore((s) => s.currentTime);
|
|
61609
|
-
const sessionRef =
|
|
61706
|
+
const sessionRef = useRef116(session);
|
|
61610
61707
|
sessionRef.current = session;
|
|
61611
61708
|
const onToggle = useEnableKeyframes(
|
|
61612
61709
|
sessionRef
|
|
@@ -61650,7 +61747,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
|
|
|
61650
61747
|
enabled: STUDIO_KEYFRAMES_ENABLED && Boolean(onToggleKeyframe),
|
|
61651
61748
|
onAddKeyframe: onToggleKeyframe
|
|
61652
61749
|
});
|
|
61653
|
-
|
|
61750
|
+
useEffect92(() => {
|
|
61654
61751
|
const onKeyDown = (e) => {
|
|
61655
61752
|
if (e.key !== "n" && e.key !== "N") return;
|
|
61656
61753
|
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
@@ -61908,20 +62005,20 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
|
|
|
61908
62005
|
}
|
|
61909
62006
|
|
|
61910
62007
|
// src/components/storyboard/StoryboardView.tsx
|
|
61911
|
-
import { useState as
|
|
62008
|
+
import { useState as useState118 } from "react";
|
|
61912
62009
|
import { Copy as Copy2, Check as Check2 } from "@phosphor-icons/react";
|
|
61913
62010
|
|
|
61914
62011
|
// src/hooks/useStoryboard.ts
|
|
61915
|
-
import { useCallback as
|
|
62012
|
+
import { useCallback as useCallback138, useEffect as useEffect93, useRef as useRef117, useState as useState111 } from "react";
|
|
61916
62013
|
function useStoryboard(projectId) {
|
|
61917
62014
|
const [data, setData] = useState111(null);
|
|
61918
62015
|
const [loading, setLoading] = useState111(true);
|
|
61919
62016
|
const [error, setError] = useState111(null);
|
|
61920
62017
|
const [reloadKey, setReloadKey] = useState111(0);
|
|
61921
|
-
const hasDataRef =
|
|
61922
|
-
const lastProjectRef =
|
|
61923
|
-
const reload =
|
|
61924
|
-
|
|
62018
|
+
const hasDataRef = useRef117(false);
|
|
62019
|
+
const lastProjectRef = useRef117(null);
|
|
62020
|
+
const reload = useCallback138(() => setReloadKey((k) => k + 1), []);
|
|
62021
|
+
useEffect93(() => {
|
|
61925
62022
|
if (!projectId) return;
|
|
61926
62023
|
let cancelled = false;
|
|
61927
62024
|
if (lastProjectRef.current !== projectId) {
|
|
@@ -61953,7 +62050,7 @@ function useStoryboard(projectId) {
|
|
|
61953
62050
|
}
|
|
61954
62051
|
|
|
61955
62052
|
// src/hooks/useProjectSignaturePoll.ts
|
|
61956
|
-
import { useEffect as
|
|
62053
|
+
import { useEffect as useEffect94, useRef as useRef118 } from "react";
|
|
61957
62054
|
var POLL_INTERVAL_MS = 2e3;
|
|
61958
62055
|
async function fetchProjectSignature(projectId) {
|
|
61959
62056
|
try {
|
|
@@ -61966,11 +62063,11 @@ async function fetchProjectSignature(projectId) {
|
|
|
61966
62063
|
}
|
|
61967
62064
|
}
|
|
61968
62065
|
function useProjectSignaturePoll(projectId, currentSignature, onChange) {
|
|
61969
|
-
const signatureRef =
|
|
61970
|
-
const onChangeRef =
|
|
62066
|
+
const signatureRef = useRef118(currentSignature);
|
|
62067
|
+
const onChangeRef = useRef118(onChange);
|
|
61971
62068
|
signatureRef.current = currentSignature;
|
|
61972
62069
|
onChangeRef.current = onChange;
|
|
61973
|
-
|
|
62070
|
+
useEffect94(() => {
|
|
61974
62071
|
if (!projectId) return;
|
|
61975
62072
|
let disposed = false;
|
|
61976
62073
|
let inFlight = false;
|
|
@@ -61997,7 +62094,7 @@ function useProjectSignaturePoll(projectId, currentSignature, onChange) {
|
|
|
61997
62094
|
}
|
|
61998
62095
|
|
|
61999
62096
|
// src/components/storyboard/StoryboardLoaded.tsx
|
|
62000
|
-
import { useEffect as
|
|
62097
|
+
import { useEffect as useEffect100, useMemo as useMemo49, useState as useState117 } from "react";
|
|
62001
62098
|
|
|
62002
62099
|
// src/components/storyboard/StoryboardDirection.tsx
|
|
62003
62100
|
import { jsx as jsx146, jsxs as jsxs126 } from "react/jsx-runtime";
|
|
@@ -62020,7 +62117,7 @@ function StoryboardDirection({ globals, frameCount }) {
|
|
|
62020
62117
|
}
|
|
62021
62118
|
|
|
62022
62119
|
// src/components/storyboard/FramePoster.tsx
|
|
62023
|
-
import { useEffect as
|
|
62120
|
+
import { useEffect as useEffect95, useState as useState112 } from "react";
|
|
62024
62121
|
import { jsx as jsx147 } from "react/jsx-runtime";
|
|
62025
62122
|
function FramePoster({
|
|
62026
62123
|
projectId,
|
|
@@ -62031,7 +62128,7 @@ function FramePoster({
|
|
|
62031
62128
|
posterVersion
|
|
62032
62129
|
}) {
|
|
62033
62130
|
const [failed2, setFailed] = useState112(false);
|
|
62034
|
-
|
|
62131
|
+
useEffect95(() => setFailed(false), [src, seconds, posterVersion]);
|
|
62035
62132
|
if (failed2) {
|
|
62036
62133
|
return /* @__PURE__ */ jsx147("div", { className: "flex h-full w-full items-center justify-center text-[11px] text-neutral-600", children: "Preview unavailable" });
|
|
62037
62134
|
}
|
|
@@ -62216,41 +62313,24 @@ function StoryboardGrid({
|
|
|
62216
62313
|
)) });
|
|
62217
62314
|
}
|
|
62218
62315
|
|
|
62219
|
-
// src/components/storyboard/StoryboardStatusLegend.tsx
|
|
62220
|
-
import { jsx as jsx150, jsxs as jsxs128 } from "react/jsx-runtime";
|
|
62221
|
-
function StoryboardStatusLegend() {
|
|
62222
|
-
return /* @__PURE__ */ jsxs128("div", { className: "flex flex-wrap items-center gap-x-5 gap-y-1.5 text-[11px] text-neutral-500", children: [
|
|
62223
|
-
/* @__PURE__ */ jsx150("span", { className: "uppercase tracking-wider text-neutral-600", children: "Status" }),
|
|
62224
|
-
FRAME_STATUS_ORDER.map((status, i) => /* @__PURE__ */ jsxs128("span", { className: "flex items-center gap-1.5", children: [
|
|
62225
|
-
i > 0 && /* @__PURE__ */ jsx150("span", { className: "text-neutral-700", children: "\u2192" }),
|
|
62226
|
-
/* @__PURE__ */ jsx150("span", { className: `h-2 w-2 rounded-full ${FRAME_STATUS_META[status].dotClass}` }),
|
|
62227
|
-
/* @__PURE__ */ jsx150("span", { className: "font-medium text-neutral-300", children: FRAME_STATUS_META[status].label }),
|
|
62228
|
-
/* @__PURE__ */ jsxs128("span", { className: "text-neutral-500", children: [
|
|
62229
|
-
"\u2014 ",
|
|
62230
|
-
FRAME_STATUS_META[status].description
|
|
62231
|
-
] })
|
|
62232
|
-
] }, status))
|
|
62233
|
-
] });
|
|
62234
|
-
}
|
|
62235
|
-
|
|
62236
62316
|
// src/components/storyboard/StoryboardScriptPanel.tsx
|
|
62237
|
-
import { jsx as
|
|
62317
|
+
import { jsx as jsx150, jsxs as jsxs128 } from "react/jsx-runtime";
|
|
62238
62318
|
function StoryboardScriptPanel({ script }) {
|
|
62239
62319
|
if (!script.exists) return null;
|
|
62240
|
-
return /* @__PURE__ */
|
|
62241
|
-
/* @__PURE__ */
|
|
62320
|
+
return /* @__PURE__ */ jsxs128("details", { className: "mt-10 rounded-lg border border-neutral-800 bg-neutral-900/50", children: [
|
|
62321
|
+
/* @__PURE__ */ jsxs128("summary", { className: "cursor-pointer select-none px-4 py-3 text-sm font-medium text-neutral-300", children: [
|
|
62242
62322
|
"Narration script",
|
|
62243
|
-
/* @__PURE__ */
|
|
62323
|
+
/* @__PURE__ */ jsx150("span", { className: "ml-2 font-normal text-neutral-500", children: script.path })
|
|
62244
62324
|
] }),
|
|
62245
|
-
/* @__PURE__ */
|
|
62325
|
+
/* @__PURE__ */ jsx150("pre", { className: "max-h-[420px] overflow-auto whitespace-pre-wrap border-t border-neutral-800 px-4 py-3 text-xs leading-relaxed text-neutral-400", children: script.content })
|
|
62246
62326
|
] });
|
|
62247
62327
|
}
|
|
62248
62328
|
|
|
62249
62329
|
// src/components/storyboard/StoryboardSourceEditor.tsx
|
|
62250
|
-
import { useCallback as
|
|
62330
|
+
import { useCallback as useCallback139, useEffect as useEffect96, useMemo as useMemo47, useRef as useRef119, useState as useState113 } from "react";
|
|
62251
62331
|
import { marked } from "marked";
|
|
62252
62332
|
import DOMPurify from "dompurify";
|
|
62253
|
-
import { jsx as
|
|
62333
|
+
import { jsx as jsx151, jsxs as jsxs129 } from "react/jsx-runtime";
|
|
62254
62334
|
var DISCARD_PROMPT = "Discard unsaved markdown changes?";
|
|
62255
62335
|
function useEditableFile(path, onSaved) {
|
|
62256
62336
|
const { readProjectFile, writeProjectFile } = useFileManagerContext();
|
|
@@ -62259,7 +62339,7 @@ function useEditableFile(path, onSaved) {
|
|
|
62259
62339
|
const [loading, setLoading] = useState113(true);
|
|
62260
62340
|
const [saving, setSaving] = useState113(false);
|
|
62261
62341
|
const [error, setError] = useState113(null);
|
|
62262
|
-
|
|
62342
|
+
useEffect96(() => {
|
|
62263
62343
|
if (!path) return;
|
|
62264
62344
|
let cancelled = false;
|
|
62265
62345
|
setLoading(true);
|
|
@@ -62277,7 +62357,7 @@ function useEditableFile(path, onSaved) {
|
|
|
62277
62357
|
cancelled = true;
|
|
62278
62358
|
};
|
|
62279
62359
|
}, [path, readProjectFile]);
|
|
62280
|
-
const save =
|
|
62360
|
+
const save = useCallback139(() => {
|
|
62281
62361
|
if (saving) return;
|
|
62282
62362
|
setSaving(true);
|
|
62283
62363
|
setError(null);
|
|
@@ -62296,8 +62376,8 @@ function hardenLinks(node) {
|
|
|
62296
62376
|
}
|
|
62297
62377
|
function useMarkdownPreview(source) {
|
|
62298
62378
|
const [debounced, setDebounced] = useState113(source);
|
|
62299
|
-
const primed =
|
|
62300
|
-
|
|
62379
|
+
const primed = useRef119(false);
|
|
62380
|
+
useEffect96(() => {
|
|
62301
62381
|
if (!primed.current && source !== "") {
|
|
62302
62382
|
primed.current = true;
|
|
62303
62383
|
setDebounced(source);
|
|
@@ -62329,8 +62409,8 @@ function StoryboardSourceEditor({
|
|
|
62329
62409
|
const activePath = files.some((f) => f.path === selected) ? selected : files[0]?.path ?? "";
|
|
62330
62410
|
const file = useEditableFile(activePath, onSaved);
|
|
62331
62411
|
const previewHtml = useMarkdownPreview(file.content);
|
|
62332
|
-
|
|
62333
|
-
|
|
62412
|
+
useEffect96(() => onDirtyChange?.(file.dirty), [onDirtyChange, file.dirty]);
|
|
62413
|
+
useEffect96(() => {
|
|
62334
62414
|
if (!file.dirty) return;
|
|
62335
62415
|
const onBeforeUnload = (event) => {
|
|
62336
62416
|
event.preventDefault();
|
|
@@ -62344,7 +62424,7 @@ function StoryboardSourceEditor({
|
|
|
62344
62424
|
if (file.dirty && !window.confirm(DISCARD_PROMPT)) return;
|
|
62345
62425
|
setSelected(path);
|
|
62346
62426
|
};
|
|
62347
|
-
return /* @__PURE__ */
|
|
62427
|
+
return /* @__PURE__ */ jsxs129(
|
|
62348
62428
|
"div",
|
|
62349
62429
|
{
|
|
62350
62430
|
className: "flex flex-1 min-h-0 flex-col",
|
|
@@ -62354,8 +62434,8 @@ function StoryboardSourceEditor({
|
|
|
62354
62434
|
if (file.dirty && !file.saving) file.save();
|
|
62355
62435
|
},
|
|
62356
62436
|
children: [
|
|
62357
|
-
/* @__PURE__ */
|
|
62358
|
-
files.map((f) => /* @__PURE__ */
|
|
62437
|
+
/* @__PURE__ */ jsxs129("div", { className: "flex items-center gap-1 border-b border-neutral-800 px-4 py-2", children: [
|
|
62438
|
+
files.map((f) => /* @__PURE__ */ jsx151(
|
|
62359
62439
|
"button",
|
|
62360
62440
|
{
|
|
62361
62441
|
type: "button",
|
|
@@ -62365,10 +62445,10 @@ function StoryboardSourceEditor({
|
|
|
62365
62445
|
},
|
|
62366
62446
|
f.path
|
|
62367
62447
|
)),
|
|
62368
|
-
/* @__PURE__ */
|
|
62369
|
-
file.error && /* @__PURE__ */
|
|
62370
|
-
/* @__PURE__ */
|
|
62371
|
-
/* @__PURE__ */
|
|
62448
|
+
/* @__PURE__ */ jsxs129("div", { className: "ml-auto flex items-center gap-3", children: [
|
|
62449
|
+
file.error && /* @__PURE__ */ jsx151("span", { className: "text-xs text-red-400", children: file.error }),
|
|
62450
|
+
/* @__PURE__ */ jsx151("span", { className: "text-xs text-neutral-500", children: file.saving ? "Saving\u2026" : file.dirty ? "Unsaved changes" : "Saved" }),
|
|
62451
|
+
/* @__PURE__ */ jsx151(
|
|
62372
62452
|
"button",
|
|
62373
62453
|
{
|
|
62374
62454
|
type: "button",
|
|
@@ -62380,12 +62460,12 @@ function StoryboardSourceEditor({
|
|
|
62380
62460
|
)
|
|
62381
62461
|
] })
|
|
62382
62462
|
] }),
|
|
62383
|
-
/* @__PURE__ */
|
|
62384
|
-
/* @__PURE__ */
|
|
62463
|
+
/* @__PURE__ */ jsxs129("div", { className: "flex flex-1 min-h-0", children: [
|
|
62464
|
+
/* @__PURE__ */ jsx151("div", { className: "w-1/2 min-w-0 border-r border-neutral-800", children: file.loading ? /* @__PURE__ */ jsxs129("div", { className: "p-4 text-sm text-neutral-500", children: [
|
|
62385
62465
|
"Loading ",
|
|
62386
62466
|
activePath,
|
|
62387
62467
|
"\u2026"
|
|
62388
|
-
] }) : /* @__PURE__ */
|
|
62468
|
+
] }) : /* @__PURE__ */ jsx151(
|
|
62389
62469
|
SourceEditor,
|
|
62390
62470
|
{
|
|
62391
62471
|
content: file.content,
|
|
@@ -62394,7 +62474,7 @@ function StoryboardSourceEditor({
|
|
|
62394
62474
|
onChange: file.setContent
|
|
62395
62475
|
}
|
|
62396
62476
|
) }),
|
|
62397
|
-
/* @__PURE__ */
|
|
62477
|
+
/* @__PURE__ */ jsx151("div", { className: "w-1/2 min-w-0 overflow-auto bg-neutral-950 px-6 py-4", children: /* @__PURE__ */ jsx151("div", { className: PREVIEW_PROSE, dangerouslySetInnerHTML: { __html: previewHtml } }) })
|
|
62398
62478
|
] })
|
|
62399
62479
|
]
|
|
62400
62480
|
}
|
|
@@ -62402,9 +62482,38 @@ function StoryboardSourceEditor({
|
|
|
62402
62482
|
}
|
|
62403
62483
|
|
|
62404
62484
|
// src/components/storyboard/StoryboardFrameFocus.tsx
|
|
62405
|
-
import { useCallback as
|
|
62406
|
-
import {
|
|
62407
|
-
|
|
62485
|
+
import { useCallback as useCallback140, useEffect as useEffect98, useState as useState115 } from "react";
|
|
62486
|
+
import { setFrameVoiceover } from "@hyperframes/core/storyboard";
|
|
62487
|
+
|
|
62488
|
+
// src/components/storyboard/AgentChatMessageButton.tsx
|
|
62489
|
+
import { useEffect as useEffect97, useState as useState114 } from "react";
|
|
62490
|
+
import { jsx as jsx152 } from "react/jsx-runtime";
|
|
62491
|
+
var APPLY_STORYBOARD_FEEDBACK_MESSAGE = "Read the storyboard feedback I saved in .hyperframes/frame-comments.json and revise the frames.";
|
|
62492
|
+
function AgentChatMessageButton({
|
|
62493
|
+
message,
|
|
62494
|
+
label = "Copy prompt for agent",
|
|
62495
|
+
onCopied
|
|
62496
|
+
}) {
|
|
62497
|
+
const [copyState, setCopyState] = useState114("idle");
|
|
62498
|
+
useEffect97(() => {
|
|
62499
|
+
if (copyState !== "copied") return;
|
|
62500
|
+
const timeout = window.setTimeout(() => setCopyState("again"), 3e3);
|
|
62501
|
+
return () => window.clearTimeout(timeout);
|
|
62502
|
+
}, [copyState]);
|
|
62503
|
+
const copyMessage = async () => {
|
|
62504
|
+
try {
|
|
62505
|
+
await navigator.clipboard.writeText(message);
|
|
62506
|
+
setCopyState("copied");
|
|
62507
|
+
onCopied?.();
|
|
62508
|
+
} catch {
|
|
62509
|
+
setCopyState("failed");
|
|
62510
|
+
}
|
|
62511
|
+
};
|
|
62512
|
+
return /* @__PURE__ */ jsx152(Button, { size: "sm", variant: "secondary", onClick: () => void copyMessage(), children: copyState === "copied" ? "Copied \u2014 paste in your agent chat" : copyState === "again" ? "Copy again" : copyState === "failed" ? "Copy failed" : label });
|
|
62513
|
+
}
|
|
62514
|
+
|
|
62515
|
+
// src/components/storyboard/StoryboardFrameFocus.tsx
|
|
62516
|
+
import { jsx as jsx153, jsxs as jsxs130 } from "react/jsx-runtime";
|
|
62408
62517
|
function StoryboardFrameFocus({
|
|
62409
62518
|
projectId,
|
|
62410
62519
|
storyboardPath,
|
|
@@ -62414,24 +62523,38 @@ function StoryboardFrameFocus({
|
|
|
62414
62523
|
onNavigate,
|
|
62415
62524
|
onSaved,
|
|
62416
62525
|
onSelectComposition,
|
|
62526
|
+
scriptExists,
|
|
62527
|
+
commentDraft,
|
|
62528
|
+
onCommentDraftChange,
|
|
62529
|
+
pendingComment,
|
|
62530
|
+
pendingCommentCount,
|
|
62531
|
+
commentDraftCount,
|
|
62532
|
+
commentsSubmitState,
|
|
62533
|
+
commentsSubmitError,
|
|
62534
|
+
feedbackMessageCopied,
|
|
62535
|
+
onFeedbackMessageCopied,
|
|
62536
|
+
onSaveFeedback,
|
|
62417
62537
|
posterVersion
|
|
62418
62538
|
}) {
|
|
62419
62539
|
const { readProjectFile, writeProjectFile } = useFileManagerContext();
|
|
62420
|
-
const { setViewMode } = useViewMode();
|
|
62421
|
-
const [draft, setDraft] =
|
|
62422
|
-
const [
|
|
62423
|
-
const [
|
|
62424
|
-
const
|
|
62540
|
+
const { setViewMode, registerViewModeGuard } = useViewMode();
|
|
62541
|
+
const [draft, setDraft] = useState115(frame.voiceover ?? "");
|
|
62542
|
+
const [savedVoiceover, setSavedVoiceover] = useState115(frame.voiceover ?? "");
|
|
62543
|
+
const [busy, setBusy] = useState115(false);
|
|
62544
|
+
const [error, setError] = useState115(null);
|
|
62545
|
+
const applyEdit = useCallback140(
|
|
62425
62546
|
async (edit) => {
|
|
62426
|
-
if (busy) return;
|
|
62547
|
+
if (busy) return false;
|
|
62427
62548
|
setBusy(true);
|
|
62428
62549
|
setError(null);
|
|
62429
62550
|
try {
|
|
62430
62551
|
const source = await readProjectFile(storyboardPath);
|
|
62431
62552
|
await writeProjectFile(storyboardPath, edit(source));
|
|
62432
62553
|
onSaved();
|
|
62554
|
+
return true;
|
|
62433
62555
|
} catch (err) {
|
|
62434
62556
|
setError(err instanceof Error ? err.message : "failed to save");
|
|
62557
|
+
return false;
|
|
62435
62558
|
} finally {
|
|
62436
62559
|
setBusy(false);
|
|
62437
62560
|
}
|
|
@@ -62439,12 +62562,13 @@ function StoryboardFrameFocus({
|
|
|
62439
62562
|
[readProjectFile, writeProjectFile, storyboardPath, onSaved, busy]
|
|
62440
62563
|
);
|
|
62441
62564
|
const title = frame.title ?? `Frame ${frame.index}`;
|
|
62442
|
-
const dirty = draft !==
|
|
62443
|
-
const canOpenPreview = frame.srcExists && Boolean(frame.src);
|
|
62444
|
-
const saveVoiceover =
|
|
62445
|
-
|
|
62565
|
+
const dirty = draft !== savedVoiceover;
|
|
62566
|
+
const canOpenPreview = frame.status !== "outline" && frame.srcExists && Boolean(frame.src);
|
|
62567
|
+
const saveVoiceover = useCallback140(async () => {
|
|
62568
|
+
const saved = await applyEdit((src) => setFrameVoiceover(src, frame.index, draft));
|
|
62569
|
+
if (saved) setSavedVoiceover(draft);
|
|
62446
62570
|
}, [applyEdit, frame.index, draft]);
|
|
62447
|
-
|
|
62571
|
+
useEffect98(() => {
|
|
62448
62572
|
if (!dirty) return;
|
|
62449
62573
|
const onBeforeUnload = (e) => {
|
|
62450
62574
|
e.preventDefault();
|
|
@@ -62452,14 +62576,18 @@ function StoryboardFrameFocus({
|
|
|
62452
62576
|
window.addEventListener("beforeunload", onBeforeUnload);
|
|
62453
62577
|
return () => window.removeEventListener("beforeunload", onBeforeUnload);
|
|
62454
62578
|
}, [dirty]);
|
|
62455
|
-
const confirmLeave = (
|
|
62579
|
+
const confirmLeave = useCallback140(
|
|
62580
|
+
() => !dirty || window.confirm("Discard unsaved voiceover changes?"),
|
|
62581
|
+
[dirty]
|
|
62582
|
+
);
|
|
62583
|
+
useEffect98(() => registerViewModeGuard(confirmLeave), [confirmLeave, registerViewModeGuard]);
|
|
62456
62584
|
const handleBack = () => {
|
|
62457
62585
|
if (confirmLeave()) onBack();
|
|
62458
62586
|
};
|
|
62459
62587
|
const handleNavigate = (delta) => {
|
|
62460
62588
|
if (confirmLeave()) onNavigate(delta);
|
|
62461
62589
|
};
|
|
62462
|
-
|
|
62590
|
+
useEffect98(() => {
|
|
62463
62591
|
const onKey = (e) => {
|
|
62464
62592
|
const el = document.activeElement;
|
|
62465
62593
|
if (el instanceof HTMLTextAreaElement || el instanceof HTMLInputElement) return;
|
|
@@ -62471,11 +62599,11 @@ function StoryboardFrameFocus({
|
|
|
62471
62599
|
return () => window.removeEventListener("keydown", onKey);
|
|
62472
62600
|
});
|
|
62473
62601
|
const openInPreview = () => {
|
|
62602
|
+
if (!setViewMode("timeline")) return;
|
|
62474
62603
|
if (frame.src) onSelectComposition(frame.src);
|
|
62475
|
-
setViewMode("timeline");
|
|
62476
62604
|
};
|
|
62477
|
-
return /* @__PURE__ */
|
|
62478
|
-
/* @__PURE__ */
|
|
62605
|
+
return /* @__PURE__ */ jsxs130("div", { className: "flex w-full max-w-[100vw] flex-1 min-h-0 min-w-0 flex-col overflow-hidden bg-neutral-950 text-neutral-200", children: [
|
|
62606
|
+
/* @__PURE__ */ jsxs130("div", { className: "flex items-center gap-3 border-b border-neutral-800 px-4 py-2", children: [
|
|
62479
62607
|
/* @__PURE__ */ jsx153(
|
|
62480
62608
|
"button",
|
|
62481
62609
|
{
|
|
@@ -62485,13 +62613,13 @@ function StoryboardFrameFocus({
|
|
|
62485
62613
|
children: "\u2190 Board"
|
|
62486
62614
|
}
|
|
62487
62615
|
),
|
|
62488
|
-
/* @__PURE__ */
|
|
62616
|
+
/* @__PURE__ */ jsxs130("span", { className: "min-w-0 flex-1 truncate text-sm font-medium text-neutral-200", children: [
|
|
62489
62617
|
"Frame ",
|
|
62490
62618
|
frame.number ?? frame.index,
|
|
62491
62619
|
" \u2014 ",
|
|
62492
62620
|
title
|
|
62493
62621
|
] }),
|
|
62494
|
-
/* @__PURE__ */
|
|
62622
|
+
/* @__PURE__ */ jsxs130("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
62495
62623
|
/* @__PURE__ */ jsx153(
|
|
62496
62624
|
NavButton,
|
|
62497
62625
|
{
|
|
@@ -62510,8 +62638,35 @@ function StoryboardFrameFocus({
|
|
|
62510
62638
|
)
|
|
62511
62639
|
] })
|
|
62512
62640
|
] }),
|
|
62513
|
-
/* @__PURE__ */
|
|
62514
|
-
/* @__PURE__ */
|
|
62641
|
+
(commentDraftCount > 0 || pendingCommentCount > 0) && /* @__PURE__ */ jsxs130("div", { className: "flex flex-wrap items-center justify-between gap-2 border-b border-neutral-800 bg-neutral-900/80 px-4 py-2", children: [
|
|
62642
|
+
/* @__PURE__ */ jsxs130("div", { children: [
|
|
62643
|
+
/* @__PURE__ */ jsx153("div", { className: "text-xs font-medium text-neutral-200", children: commentDraftCount > 0 ? "Feedback ready to save" : "Feedback saved" }),
|
|
62644
|
+
/* @__PURE__ */ jsx153("div", { className: "text-[11px] text-neutral-500", children: commentDraftCount > 0 ? "Save this batch and copy the message for your agent." : feedbackMessageCopied ? "Message copied \u2014 paste it in your terminal or IDE agent chat." : "The agent has not been notified yet." })
|
|
62645
|
+
] }),
|
|
62646
|
+
commentDraftCount > 0 ? /* @__PURE__ */ jsxs130(
|
|
62647
|
+
Button,
|
|
62648
|
+
{
|
|
62649
|
+
size: "sm",
|
|
62650
|
+
variant: "primary",
|
|
62651
|
+
onClick: onSaveFeedback,
|
|
62652
|
+
loading: commentsSubmitState === "saving",
|
|
62653
|
+
children: [
|
|
62654
|
+
"Save & copy message (",
|
|
62655
|
+
commentDraftCount,
|
|
62656
|
+
")"
|
|
62657
|
+
]
|
|
62658
|
+
}
|
|
62659
|
+
) : /* @__PURE__ */ jsx153(
|
|
62660
|
+
AgentChatMessageButton,
|
|
62661
|
+
{
|
|
62662
|
+
message: APPLY_STORYBOARD_FEEDBACK_MESSAGE,
|
|
62663
|
+
label: feedbackMessageCopied ? "Copy again" : "Copy prompt for agent",
|
|
62664
|
+
onCopied: onFeedbackMessageCopied
|
|
62665
|
+
}
|
|
62666
|
+
)
|
|
62667
|
+
] }),
|
|
62668
|
+
/* @__PURE__ */ jsxs130("div", { className: "flex flex-1 min-h-0 flex-col overflow-auto lg:flex-row lg:overflow-hidden", children: [
|
|
62669
|
+
/* @__PURE__ */ jsx153("div", { className: "flex w-full shrink-0 items-center justify-center bg-neutral-900/40 p-4 sm:p-8 lg:h-full lg:w-3/5", children: /* @__PURE__ */ jsx153("div", { className: "aspect-video w-full max-w-[900px] overflow-hidden rounded-lg border border-neutral-800 bg-neutral-900", children: canOpenPreview && frame.src ? /* @__PURE__ */ jsx153(
|
|
62515
62670
|
FramePoster,
|
|
62516
62671
|
{
|
|
62517
62672
|
projectId,
|
|
@@ -62521,32 +62676,32 @@ function StoryboardFrameFocus({
|
|
|
62521
62676
|
fit: "contain",
|
|
62522
62677
|
posterVersion
|
|
62523
62678
|
}
|
|
62524
|
-
) : /* @__PURE__ */ jsx153(
|
|
62525
|
-
/* @__PURE__ */
|
|
62526
|
-
/* @__PURE__ */ jsx153(
|
|
62527
|
-
|
|
62528
|
-
{
|
|
62529
|
-
status: frame.status,
|
|
62530
|
-
busy,
|
|
62531
|
-
onSet: (s) => applyEdit((src) => setFrameStatus(src, frame.index, s))
|
|
62532
|
-
}
|
|
62533
|
-
),
|
|
62534
|
-
/* @__PURE__ */ jsxs131("div", { className: "flex flex-wrap gap-x-6 gap-y-1 text-[11px] text-neutral-500", children: [
|
|
62535
|
-
frame.duration && /* @__PURE__ */ jsxs131("span", { children: [
|
|
62679
|
+
) : /* @__PURE__ */ jsx153(FramePlan, { frame }) }) }),
|
|
62680
|
+
/* @__PURE__ */ jsxs130("div", { className: "w-full shrink-0 space-y-6 border-t border-neutral-800 px-4 py-5 sm:px-6 lg:h-full lg:w-2/5 lg:overflow-auto lg:border-t-0 lg:border-l", children: [
|
|
62681
|
+
/* @__PURE__ */ jsx153(ReadOnlyStatus, { status: frame.status }),
|
|
62682
|
+
/* @__PURE__ */ jsxs130("div", { className: "flex flex-wrap gap-x-6 gap-y-1 text-[11px] text-neutral-500", children: [
|
|
62683
|
+
frame.duration && /* @__PURE__ */ jsxs130("span", { children: [
|
|
62536
62684
|
"Duration ",
|
|
62537
62685
|
frame.duration
|
|
62538
62686
|
] }),
|
|
62539
|
-
frame.transitionIn && /* @__PURE__ */
|
|
62687
|
+
frame.transitionIn && /* @__PURE__ */ jsxs130("span", { children: [
|
|
62540
62688
|
"Transition ",
|
|
62541
62689
|
frame.transitionIn
|
|
62542
62690
|
] })
|
|
62543
62691
|
] }),
|
|
62544
|
-
/* @__PURE__ */
|
|
62545
|
-
/* @__PURE__ */
|
|
62546
|
-
/* @__PURE__ */
|
|
62547
|
-
"
|
|
62548
|
-
|
|
62549
|
-
|
|
62692
|
+
/* @__PURE__ */ jsxs130("section", { children: [
|
|
62693
|
+
/* @__PURE__ */ jsxs130("div", { className: "mb-1 flex items-center justify-between", children: [
|
|
62694
|
+
/* @__PURE__ */ jsxs130(
|
|
62695
|
+
"h3",
|
|
62696
|
+
{
|
|
62697
|
+
className: "text-xs font-semibold uppercase tracking-wider text-neutral-400",
|
|
62698
|
+
title: "Storyboard voiceover is a guide; SCRIPT.md is the final TTS source.",
|
|
62699
|
+
children: [
|
|
62700
|
+
"\u{1F399} Voiceover ",
|
|
62701
|
+
/* @__PURE__ */ jsx153("span", { className: "font-normal normal-case text-neutral-600", children: "guide" })
|
|
62702
|
+
]
|
|
62703
|
+
}
|
|
62704
|
+
),
|
|
62550
62705
|
/* @__PURE__ */ jsx153(
|
|
62551
62706
|
Button,
|
|
62552
62707
|
{
|
|
@@ -62555,8 +62710,7 @@ function StoryboardFrameFocus({
|
|
|
62555
62710
|
onClick: saveVoiceover,
|
|
62556
62711
|
disabled: !dirty,
|
|
62557
62712
|
loading: busy,
|
|
62558
|
-
|
|
62559
|
-
children: busy ? "Saving\u2026" : "Save"
|
|
62713
|
+
children: busy ? "Saving\u2026" : "Save voiceover"
|
|
62560
62714
|
}
|
|
62561
62715
|
)
|
|
62562
62716
|
] }),
|
|
@@ -62565,22 +62719,53 @@ function StoryboardFrameFocus({
|
|
|
62565
62719
|
{
|
|
62566
62720
|
value: draft,
|
|
62567
62721
|
onChange: (e) => setDraft(e.target.value),
|
|
62568
|
-
onBlur: () => {
|
|
62569
|
-
if (dirty && !busy) void saveVoiceover();
|
|
62570
|
-
},
|
|
62571
62722
|
rows: 3,
|
|
62572
62723
|
placeholder: "What the narrator says over this frame\u2026",
|
|
62573
62724
|
className: "w-full resize-y rounded border border-neutral-800 bg-neutral-900 p-2 text-sm text-neutral-200 outline-none focus:border-neutral-600"
|
|
62574
62725
|
}
|
|
62575
62726
|
),
|
|
62576
|
-
/* @__PURE__ */ jsx153("p", { className: "mt-1 text-[11px] text-neutral-600", children: "
|
|
62727
|
+
/* @__PURE__ */ jsx153("p", { className: "mt-1 text-[11px] text-neutral-600", children: dirty ? "Unsaved changes" : scriptExists ? "Saved. SCRIPT.md drives final TTS." : "Saved to STORYBOARD.md. This voiceover guides narration for the frame." }),
|
|
62577
62728
|
error && /* @__PURE__ */ jsx153("p", { className: "mt-1 text-[11px] text-red-400", children: error })
|
|
62578
62729
|
] }),
|
|
62579
|
-
|
|
62730
|
+
/* @__PURE__ */ jsxs130("section", { children: [
|
|
62731
|
+
/* @__PURE__ */ jsx153("div", { className: "mb-1", children: /* @__PURE__ */ jsx153("h3", { className: "text-xs font-semibold uppercase tracking-wider text-neutral-400", children: "Frame feedback" }) }),
|
|
62732
|
+
/* @__PURE__ */ jsx153(
|
|
62733
|
+
"textarea",
|
|
62734
|
+
{
|
|
62735
|
+
value: commentDraft,
|
|
62736
|
+
onChange: (e) => onCommentDraftChange(e.target.value),
|
|
62737
|
+
rows: 3,
|
|
62738
|
+
placeholder: "Tell your agent what to change in this frame\u2026",
|
|
62739
|
+
"aria-label": `Comment on ${title}`,
|
|
62740
|
+
className: "w-full resize-y rounded border border-neutral-800 bg-neutral-900 p-2 text-sm text-neutral-200 placeholder:text-neutral-600 outline-none focus:border-sky-700"
|
|
62741
|
+
}
|
|
62742
|
+
),
|
|
62743
|
+
pendingCommentCount > 0 ? /* @__PURE__ */ jsxs130("div", { className: "mt-2 flex flex-wrap items-center justify-between gap-2 rounded-md border border-sky-900/70 bg-sky-950/20 px-2.5 py-2", children: [
|
|
62744
|
+
/* @__PURE__ */ jsx153("p", { className: "text-[11px] text-sky-200", children: "Paste the agent prompt in your terminal or IDE chat." }),
|
|
62745
|
+
/* @__PURE__ */ jsx153(
|
|
62746
|
+
AgentChatMessageButton,
|
|
62747
|
+
{
|
|
62748
|
+
message: APPLY_STORYBOARD_FEEDBACK_MESSAGE,
|
|
62749
|
+
onCopied: onFeedbackMessageCopied
|
|
62750
|
+
}
|
|
62751
|
+
)
|
|
62752
|
+
] }) : /* @__PURE__ */ jsx153("p", { className: "mt-1 text-[11px] text-neutral-600", children: commentDraftCount > 0 ? "Your change is ready. Save it using the review bar above." : "Add a change to prepare feedback for the agent." }),
|
|
62753
|
+
pendingComment && /* @__PURE__ */ jsxs130("p", { className: "mt-1 text-[11px] text-sky-400/90", children: [
|
|
62754
|
+
/* @__PURE__ */ jsx153("span", { className: "font-medium", children: "Pending:" }),
|
|
62755
|
+
" \u201C",
|
|
62756
|
+
pendingComment,
|
|
62757
|
+
"\u201D"
|
|
62758
|
+
] }),
|
|
62759
|
+
commentsSubmitError && /* @__PURE__ */ jsxs130("p", { className: "mt-1 text-[11px] text-red-400", children: [
|
|
62760
|
+
"Couldn\u2019t submit: ",
|
|
62761
|
+
commentsSubmitError
|
|
62762
|
+
] })
|
|
62763
|
+
] }),
|
|
62764
|
+
frame.narrative && /* @__PURE__ */ jsxs130("section", { children: [
|
|
62580
62765
|
/* @__PURE__ */ jsx153("h3", { className: "mb-1 text-xs font-semibold uppercase tracking-wider text-neutral-400", children: "Narrative" }),
|
|
62581
62766
|
/* @__PURE__ */ jsx153("p", { className: "whitespace-pre-wrap text-sm text-neutral-300", children: frame.narrative })
|
|
62582
62767
|
] }),
|
|
62583
|
-
/* @__PURE__ */ jsx153(Button, { size: "sm", variant: "secondary", onClick: openInPreview,
|
|
62768
|
+
canOpenPreview ? /* @__PURE__ */ jsx153(Button, { size: "sm", variant: "secondary", onClick: openInPreview, children: "Open in Preview \u2192" }) : /* @__PURE__ */ jsx153("div", { className: "rounded-md border border-neutral-800 bg-neutral-900/60 px-3 py-2 text-xs text-neutral-500", children: "Preview becomes available after your agent builds this frame." })
|
|
62584
62769
|
] })
|
|
62585
62770
|
] })
|
|
62586
62771
|
] });
|
|
@@ -62601,31 +62786,280 @@ function NavButton({
|
|
|
62601
62786
|
}
|
|
62602
62787
|
);
|
|
62603
62788
|
}
|
|
62604
|
-
function
|
|
62605
|
-
status
|
|
62606
|
-
|
|
62607
|
-
onSet
|
|
62608
|
-
}) {
|
|
62609
|
-
return /* @__PURE__ */ jsxs131("div", { className: "flex items-center gap-2", children: [
|
|
62789
|
+
function ReadOnlyStatus({ status }) {
|
|
62790
|
+
const meta = FRAME_STATUS_META[status];
|
|
62791
|
+
return /* @__PURE__ */ jsxs130("div", { className: "flex items-center gap-2", children: [
|
|
62610
62792
|
/* @__PURE__ */ jsx153("span", { className: "text-xs font-semibold uppercase tracking-wider text-neutral-500", children: "Status" }),
|
|
62611
|
-
/* @__PURE__ */ jsx153("
|
|
62612
|
-
|
|
62793
|
+
/* @__PURE__ */ jsx153("span", { className: `rounded px-2 py-1 text-xs font-medium ${meta.chipClass}`, children: meta.label }),
|
|
62794
|
+
/* @__PURE__ */ jsx153("span", { className: "text-[11px] text-neutral-600", children: "Updated by your agent" })
|
|
62795
|
+
] });
|
|
62796
|
+
}
|
|
62797
|
+
function FramePlan({ frame }) {
|
|
62798
|
+
const title = frame.title ?? `Frame ${frame.index}`;
|
|
62799
|
+
const isOutline = frame.status === "outline";
|
|
62800
|
+
return /* @__PURE__ */ jsx153("div", { className: "flex h-full w-full items-center justify-center bg-[radial-gradient(circle_at_center,_rgba(38,38,38,0.8),_rgba(10,10,10,1))] p-10", children: /* @__PURE__ */ jsxs130("div", { className: "max-w-xl text-center", children: [
|
|
62801
|
+
/* @__PURE__ */ jsx153("span", { className: "rounded-full border border-neutral-700 px-2.5 py-1 text-[10px] font-semibold uppercase tracking-wider text-neutral-400", children: isOutline ? "Planned frame" : "Preview unavailable" }),
|
|
62802
|
+
/* @__PURE__ */ jsx153("h2", { className: "mt-4 text-2xl font-semibold text-neutral-100", children: title }),
|
|
62803
|
+
frame.scene && /* @__PURE__ */ jsx153("p", { className: "mt-3 text-base leading-relaxed text-neutral-300", children: frame.scene }),
|
|
62804
|
+
!frame.scene && frame.narrative && /* @__PURE__ */ jsx153("p", { className: "mt-3 line-clamp-4 text-sm leading-relaxed text-neutral-400", children: frame.narrative }),
|
|
62805
|
+
/* @__PURE__ */ jsx153("p", { className: "mt-5 text-xs text-neutral-600", children: isOutline ? "A visual preview will appear when your agent builds the sketch." : frame.src ? `Frame file not found: ${frame.src}` : "This frame does not link to a source file." })
|
|
62806
|
+
] }) });
|
|
62807
|
+
}
|
|
62808
|
+
|
|
62809
|
+
// src/components/storyboard/storyboardReviewStage.ts
|
|
62810
|
+
function deriveStoryboardHandoffStep(draftCount, pendingCount) {
|
|
62811
|
+
if (draftCount > 0) return 2;
|
|
62812
|
+
if (pendingCount > 0) return 3;
|
|
62813
|
+
return 1;
|
|
62814
|
+
}
|
|
62815
|
+
function deriveStoryboardReviewStage(frames) {
|
|
62816
|
+
const counts = { outline: 0, built: 0, animated: 0 };
|
|
62817
|
+
for (const frame of frames) counts[frame.status] += 1;
|
|
62818
|
+
let stage;
|
|
62819
|
+
if (frames.length === 0) stage = "empty";
|
|
62820
|
+
else if (counts.outline === frames.length) stage = "plan-review";
|
|
62821
|
+
else if (counts.outline > 0) stage = "sketch-in-progress";
|
|
62822
|
+
else if (counts.built === frames.length) stage = "sketch-review";
|
|
62823
|
+
else if (counts.built > 0) stage = "animation-in-progress";
|
|
62824
|
+
else stage = "final-review";
|
|
62825
|
+
return { stage, counts, frameCount: frames.length };
|
|
62826
|
+
}
|
|
62827
|
+
|
|
62828
|
+
// src/components/storyboard/StoryboardReviewGuide.tsx
|
|
62829
|
+
import { jsx as jsx154, jsxs as jsxs131 } from "react/jsx-runtime";
|
|
62830
|
+
var GUIDE_COPY = {
|
|
62831
|
+
empty: {
|
|
62832
|
+
eyebrow: "Waiting for a plan",
|
|
62833
|
+
title: "The storyboard has no frames yet",
|
|
62834
|
+
body: "Ask your agent to draft the story plan. Frames will appear here automatically."
|
|
62835
|
+
},
|
|
62836
|
+
"plan-review": {
|
|
62837
|
+
eyebrow: "Ready for review",
|
|
62838
|
+
title: "Review the story plan",
|
|
62839
|
+
body: "Check the sequence, scene direction, and voiceover before visual work begins. Leave frame comments, save them, then reply in your terminal or IDE agent chat."
|
|
62840
|
+
},
|
|
62841
|
+
"sketch-in-progress": {
|
|
62842
|
+
eyebrow: "Build in progress",
|
|
62843
|
+
title: "Visual sketches are in progress",
|
|
62844
|
+
body: "New posters appear automatically as your agent builds them. You can comment now; wait until no frames remain in Outline before approving the layouts."
|
|
62845
|
+
},
|
|
62846
|
+
"sketch-review": {
|
|
62847
|
+
eyebrow: "Ready for review",
|
|
62848
|
+
title: "Review the visual direction",
|
|
62849
|
+
body: "Check composition, hierarchy, and copy. Save frame comments, then reply in your terminal or IDE agent chat."
|
|
62850
|
+
},
|
|
62851
|
+
"animation-in-progress": {
|
|
62852
|
+
eyebrow: "Build in progress",
|
|
62853
|
+
title: "Animation is in progress",
|
|
62854
|
+
body: "The board refreshes as frames advance. Review completed frames now; the final review is ready when every frame is Animated."
|
|
62855
|
+
},
|
|
62856
|
+
"final-review": {
|
|
62857
|
+
eyebrow: "Ready for review",
|
|
62858
|
+
title: "Review motion and timing",
|
|
62859
|
+
body: "Every frame is animated. Open a frame in Preview to review it in the timeline, or leave frame comments for another revision."
|
|
62860
|
+
}
|
|
62861
|
+
};
|
|
62862
|
+
var REVIEW_ACTION_COPY = {
|
|
62863
|
+
empty: { body: "Add comments as previews arrive." },
|
|
62864
|
+
"plan-review": {
|
|
62865
|
+
body: "Add comments where you want changes. If everything looks right, approve this pass in agent chat.",
|
|
62866
|
+
approvalMessage: "Approve this storyboard plan and continue to visual sketches."
|
|
62867
|
+
},
|
|
62868
|
+
"sketch-in-progress": {
|
|
62869
|
+
body: "Add comments as previews arrive. You\u2019ll be prompted to approve when this pass is ready."
|
|
62870
|
+
},
|
|
62871
|
+
"sketch-review": {
|
|
62872
|
+
body: "Add comments where you want changes. If everything looks right, approve this pass in agent chat.",
|
|
62873
|
+
approvalMessage: "Approve these storyboard sketches and continue to animation."
|
|
62874
|
+
},
|
|
62875
|
+
"animation-in-progress": {
|
|
62876
|
+
body: "Add comments as previews arrive. You\u2019ll be prompted to approve when this pass is ready."
|
|
62877
|
+
},
|
|
62878
|
+
"final-review": {
|
|
62879
|
+
body: "Add comments where you want changes. If everything looks right, approve this pass in agent chat.",
|
|
62880
|
+
approvalMessage: "Approve this final storyboard review and continue to rendering."
|
|
62881
|
+
}
|
|
62882
|
+
};
|
|
62883
|
+
var REVIEW_STEP_STATES = {
|
|
62884
|
+
[-1]: {
|
|
62885
|
+
textClass: "text-emerald-400",
|
|
62886
|
+
numberClass: "border-emerald-700 bg-emerald-500/10",
|
|
62887
|
+
ariaCurrent: void 0,
|
|
62888
|
+
marker: () => "\u2713"
|
|
62889
|
+
},
|
|
62890
|
+
[0]: {
|
|
62891
|
+
textClass: "text-sky-300",
|
|
62892
|
+
numberClass: "border-sky-500 bg-sky-500/15",
|
|
62893
|
+
ariaCurrent: "step",
|
|
62894
|
+
marker: (number) => number
|
|
62895
|
+
},
|
|
62896
|
+
[1]: {
|
|
62897
|
+
textClass: "text-neutral-600",
|
|
62898
|
+
numberClass: "border-neutral-700",
|
|
62899
|
+
ariaCurrent: void 0,
|
|
62900
|
+
marker: (number) => number
|
|
62901
|
+
}
|
|
62902
|
+
};
|
|
62903
|
+
var REVIEW_STEP_SEPARATOR_CLASS = {
|
|
62904
|
+
1: "invisible",
|
|
62905
|
+
2: "",
|
|
62906
|
+
3: ""
|
|
62907
|
+
};
|
|
62908
|
+
function StoryboardReviewGuide({
|
|
62909
|
+
frames,
|
|
62910
|
+
draftCount,
|
|
62911
|
+
pendingCount,
|
|
62912
|
+
onFeedbackMessageCopied
|
|
62913
|
+
}) {
|
|
62914
|
+
const summary = deriveStoryboardReviewStage(frames);
|
|
62915
|
+
const copy = GUIDE_COPY[summary.stage];
|
|
62916
|
+
const handoffStep = deriveStoryboardHandoffStep(draftCount, pendingCount);
|
|
62917
|
+
const progress = progressLabel(summary);
|
|
62918
|
+
return /* @__PURE__ */ jsxs131("section", { className: "mt-5 rounded-lg border border-neutral-800 bg-neutral-900/60 px-4 py-3", children: [
|
|
62919
|
+
/* @__PURE__ */ jsxs131("div", { className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
62920
|
+
/* @__PURE__ */ jsxs131("div", { className: "max-w-3xl", children: [
|
|
62921
|
+
/* @__PURE__ */ jsx154("div", { className: "text-[10px] font-semibold uppercase tracking-wider text-sky-400", children: copy.eyebrow }),
|
|
62922
|
+
/* @__PURE__ */ jsx154("h2", { className: "mt-0.5 text-sm font-semibold text-neutral-100", children: copy.title }),
|
|
62923
|
+
/* @__PURE__ */ jsx154("p", { className: "mt-1 text-xs leading-relaxed text-neutral-400", children: copy.body })
|
|
62924
|
+
] }),
|
|
62925
|
+
summary.frameCount > 0 && /* @__PURE__ */ jsxs131("div", { className: "shrink-0", children: [
|
|
62926
|
+
/* @__PURE__ */ jsx154("div", { className: "mb-1.5 text-right text-[11px] font-medium text-neutral-300", children: progress }),
|
|
62927
|
+
/* @__PURE__ */ jsx154("div", { className: "flex flex-wrap justify-end gap-1.5", "aria-label": "Frame status summary", children: FRAME_STATUS_ORDER.map((status) => /* @__PURE__ */ jsxs131(
|
|
62928
|
+
"span",
|
|
62929
|
+
{
|
|
62930
|
+
className: `rounded px-2 py-1 text-[10px] font-medium ${FRAME_STATUS_META[status].chipClass}`,
|
|
62931
|
+
children: [
|
|
62932
|
+
summary.counts[status],
|
|
62933
|
+
" ",
|
|
62934
|
+
FRAME_STATUS_META[status].label
|
|
62935
|
+
]
|
|
62936
|
+
},
|
|
62937
|
+
status
|
|
62938
|
+
)) })
|
|
62939
|
+
] })
|
|
62940
|
+
] }),
|
|
62941
|
+
summary.frameCount > 0 && /* @__PURE__ */ jsxs131("div", { className: "mt-3 border-t border-neutral-800 pt-3", children: [
|
|
62942
|
+
/* @__PURE__ */ jsx154(ReviewSteps, { current: handoffStep }),
|
|
62943
|
+
/* @__PURE__ */ jsx154(
|
|
62944
|
+
NextAction,
|
|
62945
|
+
{
|
|
62946
|
+
stage: summary.stage,
|
|
62947
|
+
step: handoffStep,
|
|
62948
|
+
draftCount,
|
|
62949
|
+
onFeedbackMessageCopied
|
|
62950
|
+
}
|
|
62951
|
+
)
|
|
62952
|
+
] })
|
|
62953
|
+
] });
|
|
62954
|
+
}
|
|
62955
|
+
function ReviewSteps({ current }) {
|
|
62956
|
+
const steps = ["Review frames", "Save feedback", "Reply in agent chat"];
|
|
62957
|
+
return /* @__PURE__ */ jsx154("ol", { className: "hidden items-center gap-2 sm:flex", "aria-label": "Storyboard review workflow", children: steps.map((label, index) => /* @__PURE__ */ jsx154(
|
|
62958
|
+
ReviewStep,
|
|
62959
|
+
{
|
|
62960
|
+
label,
|
|
62961
|
+
number: index + 1,
|
|
62962
|
+
current
|
|
62963
|
+
},
|
|
62964
|
+
label
|
|
62965
|
+
)) });
|
|
62966
|
+
}
|
|
62967
|
+
function ReviewStep({
|
|
62968
|
+
label,
|
|
62969
|
+
number,
|
|
62970
|
+
current
|
|
62971
|
+
}) {
|
|
62972
|
+
const offset = Math.sign(number - current);
|
|
62973
|
+
const state = REVIEW_STEP_STATES[offset];
|
|
62974
|
+
return /* @__PURE__ */ jsxs131("li", { className: "flex items-center gap-2", children: [
|
|
62975
|
+
/* @__PURE__ */ jsx154(
|
|
62976
|
+
"span",
|
|
62613
62977
|
{
|
|
62614
|
-
|
|
62615
|
-
|
|
62616
|
-
"
|
|
62617
|
-
|
|
62618
|
-
|
|
62619
|
-
|
|
62620
|
-
|
|
62621
|
-
|
|
62622
|
-
|
|
62623
|
-
|
|
62978
|
+
className: `text-neutral-700 ${REVIEW_STEP_SEPARATOR_CLASS[number]}`,
|
|
62979
|
+
"aria-hidden": "true",
|
|
62980
|
+
children: "\u2192"
|
|
62981
|
+
}
|
|
62982
|
+
),
|
|
62983
|
+
/* @__PURE__ */ jsxs131(
|
|
62984
|
+
"span",
|
|
62985
|
+
{
|
|
62986
|
+
"aria-current": state.ariaCurrent,
|
|
62987
|
+
className: `flex items-center gap-1.5 text-[11px] font-medium ${state.textClass}`,
|
|
62988
|
+
children: [
|
|
62989
|
+
/* @__PURE__ */ jsx154(
|
|
62990
|
+
"span",
|
|
62991
|
+
{
|
|
62992
|
+
className: `flex h-5 w-5 items-center justify-center rounded-full border text-[10px] ${state.numberClass}`,
|
|
62993
|
+
children: state.marker(number)
|
|
62994
|
+
}
|
|
62995
|
+
),
|
|
62996
|
+
label
|
|
62997
|
+
]
|
|
62998
|
+
}
|
|
62999
|
+
)
|
|
63000
|
+
] });
|
|
63001
|
+
}
|
|
63002
|
+
function NextAction({
|
|
63003
|
+
stage,
|
|
63004
|
+
step,
|
|
63005
|
+
draftCount,
|
|
63006
|
+
onFeedbackMessageCopied
|
|
63007
|
+
}) {
|
|
63008
|
+
if (step === 3) {
|
|
63009
|
+
return /* @__PURE__ */ jsx154(AgentHandoffAction, { onFeedbackMessageCopied });
|
|
63010
|
+
}
|
|
63011
|
+
if (step === 2) return /* @__PURE__ */ jsx154(SaveFeedbackAction, { draftCount });
|
|
63012
|
+
return /* @__PURE__ */ jsx154(ReviewFramesAction, { stage });
|
|
63013
|
+
}
|
|
63014
|
+
function AgentHandoffAction({ onFeedbackMessageCopied }) {
|
|
63015
|
+
return /* @__PURE__ */ jsxs131("div", { className: "mt-3 flex flex-col gap-3 rounded-md border border-sky-900/70 bg-sky-950/20 px-3 py-2.5 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
63016
|
+
/* @__PURE__ */ jsxs131("div", { className: "max-w-3xl", children: [
|
|
63017
|
+
/* @__PURE__ */ jsx154("div", { className: "text-xs font-semibold text-sky-200", children: "Next: return to your agent chat" }),
|
|
63018
|
+
/* @__PURE__ */ jsx154("p", { className: "mt-0.5 text-[11px] text-neutral-400", children: "Feedback is saved, but the agent has not been notified. Paste this prompt in your terminal or IDE agent chat." })
|
|
63019
|
+
] }),
|
|
63020
|
+
/* @__PURE__ */ jsx154(
|
|
63021
|
+
AgentChatMessageButton,
|
|
63022
|
+
{
|
|
63023
|
+
message: APPLY_STORYBOARD_FEEDBACK_MESSAGE,
|
|
63024
|
+
onCopied: onFeedbackMessageCopied
|
|
63025
|
+
}
|
|
63026
|
+
)
|
|
63027
|
+
] });
|
|
63028
|
+
}
|
|
63029
|
+
function SaveFeedbackAction({ draftCount }) {
|
|
63030
|
+
return /* @__PURE__ */ jsx154("div", { className: "mt-3 rounded-md border border-neutral-800 bg-neutral-950/40 px-3 py-2.5", children: /* @__PURE__ */ jsxs131("div", { children: [
|
|
63031
|
+
/* @__PURE__ */ jsx154("div", { className: "text-xs font-semibold text-neutral-200", children: "Next: save your feedback" }),
|
|
63032
|
+
/* @__PURE__ */ jsxs131("p", { className: "mt-0.5 text-[11px] text-neutral-500", children: [
|
|
63033
|
+
draftCount,
|
|
63034
|
+
" frame",
|
|
63035
|
+
draftCount === 1 ? " has" : "s have",
|
|
63036
|
+
" feedback ready. Use Save & copy message above to prepare this batch for your agent."
|
|
63037
|
+
] })
|
|
63038
|
+
] }) });
|
|
63039
|
+
}
|
|
63040
|
+
function ReviewFramesAction({ stage }) {
|
|
63041
|
+
const copy = REVIEW_ACTION_COPY[stage];
|
|
63042
|
+
return /* @__PURE__ */ jsxs131("div", { className: "mt-3 flex flex-col gap-3 rounded-md border border-neutral-800 bg-neutral-950/40 px-3 py-2.5 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
63043
|
+
/* @__PURE__ */ jsxs131("div", { children: [
|
|
63044
|
+
/* @__PURE__ */ jsx154("div", { className: "text-xs font-semibold text-neutral-200", children: "Next: review the frames" }),
|
|
63045
|
+
/* @__PURE__ */ jsx154("p", { className: "mt-0.5 text-[11px] text-neutral-500", children: copy.body })
|
|
63046
|
+
] }),
|
|
63047
|
+
copy.approvalMessage && /* @__PURE__ */ jsx154(AgentChatMessageButton, { message: copy.approvalMessage, label: "Copy approval message" })
|
|
62624
63048
|
] });
|
|
62625
63049
|
}
|
|
63050
|
+
function progressLabel(summary) {
|
|
63051
|
+
if (summary.stage === "sketch-in-progress" || summary.stage === "sketch-review") {
|
|
63052
|
+
const ready = summary.frameCount - summary.counts.outline;
|
|
63053
|
+
return `${ready} of ${summary.frameCount} visual sketches ready`;
|
|
63054
|
+
}
|
|
63055
|
+
if (summary.stage === "animation-in-progress" || summary.stage === "final-review") {
|
|
63056
|
+
return `${summary.counts.animated} of ${summary.frameCount} animations ready`;
|
|
63057
|
+
}
|
|
63058
|
+
return `${summary.frameCount} plan frame${summary.frameCount === 1 ? "" : "s"} ready`;
|
|
63059
|
+
}
|
|
62626
63060
|
|
|
62627
63061
|
// src/components/storyboard/useFrameComments.ts
|
|
62628
|
-
import { useCallback as
|
|
63062
|
+
import { useCallback as useCallback141, useEffect as useEffect99, useMemo as useMemo48, useState as useState116 } from "react";
|
|
62629
63063
|
|
|
62630
63064
|
// src/components/storyboard/frameComments.ts
|
|
62631
63065
|
var FRAME_COMMENTS_PATH = ".hyperframes/frame-comments.json";
|
|
@@ -62687,32 +63121,34 @@ function buildCommentsFile(frames, drafts, previous, submittedAt) {
|
|
|
62687
63121
|
// src/components/storyboard/useFrameComments.ts
|
|
62688
63122
|
function useFrameComments(frames) {
|
|
62689
63123
|
const { writeProjectFile, readOptionalProjectFile } = useFileManagerContext();
|
|
62690
|
-
const [drafts, setDrafts] =
|
|
62691
|
-
const [submitState, setSubmitState] =
|
|
62692
|
-
const [
|
|
62693
|
-
const
|
|
63124
|
+
const [drafts, setDrafts] = useState116({});
|
|
63125
|
+
const [submitState, setSubmitState] = useState116("idle");
|
|
63126
|
+
const [submitError, setSubmitError] = useState116(null);
|
|
63127
|
+
const [pending, setPending] = useState116(null);
|
|
63128
|
+
const refreshPending = useCallback141(async () => {
|
|
62694
63129
|
try {
|
|
62695
63130
|
const parsed = parseCommentsFile(await readOptionalProjectFile(FRAME_COMMENTS_PATH));
|
|
62696
63131
|
setPending(parsed && parsed.comments.length > 0 ? parsed.comments : null);
|
|
62697
63132
|
} catch {
|
|
62698
63133
|
}
|
|
62699
63134
|
}, [readOptionalProjectFile]);
|
|
62700
|
-
|
|
63135
|
+
useEffect99(() => {
|
|
62701
63136
|
void refreshPending();
|
|
62702
63137
|
const onFocus = () => void refreshPending();
|
|
62703
63138
|
window.addEventListener("focus", onFocus);
|
|
62704
63139
|
return () => window.removeEventListener("focus", onFocus);
|
|
62705
63140
|
}, [refreshPending]);
|
|
62706
|
-
const setDraft =
|
|
63141
|
+
const setDraft = useCallback141((index, text) => {
|
|
62707
63142
|
setDrafts((prev) => ({ ...prev, [index]: text }));
|
|
62708
63143
|
}, []);
|
|
62709
63144
|
const draftCount = useMemo48(
|
|
62710
63145
|
() => Object.values(drafts).filter((text) => text.trim().length > 0).length,
|
|
62711
63146
|
[drafts]
|
|
62712
63147
|
);
|
|
62713
|
-
const submit =
|
|
62714
|
-
if (draftCount === 0 || submitState === "saving") return;
|
|
63148
|
+
const submit = useCallback141(async () => {
|
|
63149
|
+
if (draftCount === 0 || submitState === "saving") return false;
|
|
62715
63150
|
setSubmitState("saving");
|
|
63151
|
+
setSubmitError(null);
|
|
62716
63152
|
try {
|
|
62717
63153
|
const previous = parseCommentsFile(await readOptionalProjectFile(FRAME_COMMENTS_PATH));
|
|
62718
63154
|
const file = buildCommentsFile(frames, drafts, previous, (/* @__PURE__ */ new Date()).toISOString());
|
|
@@ -62720,16 +63156,28 @@ function useFrameComments(frames) {
|
|
|
62720
63156
|
`);
|
|
62721
63157
|
setDrafts({});
|
|
62722
63158
|
setPending(file.comments);
|
|
62723
|
-
|
|
63159
|
+
return true;
|
|
63160
|
+
} catch (err) {
|
|
63161
|
+
setSubmitError(err instanceof Error ? err.message : "Failed to submit comments");
|
|
63162
|
+
return false;
|
|
62724
63163
|
} finally {
|
|
62725
63164
|
setSubmitState("idle");
|
|
62726
63165
|
}
|
|
62727
63166
|
}, [draftCount, submitState, frames, drafts, readOptionalProjectFile, writeProjectFile]);
|
|
62728
|
-
return {
|
|
63167
|
+
return {
|
|
63168
|
+
drafts,
|
|
63169
|
+
setDraft,
|
|
63170
|
+
draftCount,
|
|
63171
|
+
submitState,
|
|
63172
|
+
submitError,
|
|
63173
|
+
submit,
|
|
63174
|
+
pending,
|
|
63175
|
+
refreshPending
|
|
63176
|
+
};
|
|
62729
63177
|
}
|
|
62730
63178
|
|
|
62731
63179
|
// src/components/storyboard/StoryboardLoaded.tsx
|
|
62732
|
-
import { jsx as
|
|
63180
|
+
import { Fragment as Fragment46, jsx as jsx155, jsxs as jsxs132 } from "react/jsx-runtime";
|
|
62733
63181
|
function clampIndex(index, count) {
|
|
62734
63182
|
return Math.max(1, Math.min(count, index));
|
|
62735
63183
|
}
|
|
@@ -62739,14 +63187,28 @@ function StoryboardLoaded({
|
|
|
62739
63187
|
reload,
|
|
62740
63188
|
onSelectComposition
|
|
62741
63189
|
}) {
|
|
62742
|
-
const [subView, setSubView] =
|
|
62743
|
-
const [sourceDirty, setSourceDirty] =
|
|
62744
|
-
const [focusedIndex, setFocusedIndex] =
|
|
63190
|
+
const [subView, setSubView] = useState117("board");
|
|
63191
|
+
const [sourceDirty, setSourceDirty] = useState117(false);
|
|
63192
|
+
const [focusedIndex, setFocusedIndex] = useState117(null);
|
|
63193
|
+
const [feedbackMessageCopied, setFeedbackMessageCopied] = useState117(false);
|
|
62745
63194
|
const comments = useFrameComments(data.frames);
|
|
62746
63195
|
const { refreshPending } = comments;
|
|
62747
|
-
|
|
63196
|
+
useEffect100(() => {
|
|
62748
63197
|
void refreshPending();
|
|
62749
63198
|
}, [data.signature, refreshPending]);
|
|
63199
|
+
useEffect100(() => {
|
|
63200
|
+
if (comments.draftCount > 0) setFeedbackMessageCopied(false);
|
|
63201
|
+
}, [comments.draftCount]);
|
|
63202
|
+
const saveFeedbackAndCopyMessage = async () => {
|
|
63203
|
+
const saved = await comments.submit();
|
|
63204
|
+
if (!saved) return;
|
|
63205
|
+
try {
|
|
63206
|
+
await navigator.clipboard.writeText(APPLY_STORYBOARD_FEEDBACK_MESSAGE);
|
|
63207
|
+
setFeedbackMessageCopied(true);
|
|
63208
|
+
} catch {
|
|
63209
|
+
setFeedbackMessageCopied(false);
|
|
63210
|
+
}
|
|
63211
|
+
};
|
|
62750
63212
|
const sourceFiles = useMemo49(() => {
|
|
62751
63213
|
const files = [{ path: data.path, label: data.path }];
|
|
62752
63214
|
if (data.script?.exists) files.push({ path: data.script.path, label: data.script.path });
|
|
@@ -62761,7 +63223,7 @@ function StoryboardLoaded({
|
|
|
62761
63223
|
};
|
|
62762
63224
|
const focusedFrame = focusedIndex != null ? data.frames.find((f) => f.index === focusedIndex) ?? null : null;
|
|
62763
63225
|
if (focusedFrame) {
|
|
62764
|
-
return /* @__PURE__ */
|
|
63226
|
+
return /* @__PURE__ */ jsx155(
|
|
62765
63227
|
StoryboardFrameFocus,
|
|
62766
63228
|
{
|
|
62767
63229
|
projectId,
|
|
@@ -62772,28 +63234,57 @@ function StoryboardLoaded({
|
|
|
62772
63234
|
onNavigate: (delta) => setFocusedIndex(clampIndex(focusedFrame.index + delta, data.frames.length)),
|
|
62773
63235
|
onSaved: reload,
|
|
62774
63236
|
onSelectComposition,
|
|
63237
|
+
scriptExists: Boolean(data.script?.exists),
|
|
63238
|
+
commentDraft: comments.drafts[focusedFrame.index] ?? "",
|
|
63239
|
+
onCommentDraftChange: (text) => comments.setDraft(focusedFrame.index, text),
|
|
63240
|
+
pendingComment: comments.pending?.find((entry) => entry.frame === focusedFrame.index)?.text ?? null,
|
|
63241
|
+
pendingCommentCount: comments.pending?.length ?? 0,
|
|
63242
|
+
commentDraftCount: comments.draftCount,
|
|
63243
|
+
commentsSubmitState: comments.submitState,
|
|
63244
|
+
commentsSubmitError: comments.submitError,
|
|
63245
|
+
feedbackMessageCopied,
|
|
63246
|
+
onFeedbackMessageCopied: () => setFeedbackMessageCopied(true),
|
|
63247
|
+
onSaveFeedback: () => void saveFeedbackAndCopyMessage(),
|
|
62775
63248
|
posterVersion: data.signature
|
|
62776
63249
|
},
|
|
62777
63250
|
focusedFrame.index
|
|
62778
63251
|
);
|
|
62779
63252
|
}
|
|
62780
|
-
return /* @__PURE__ */ jsxs132("div", { className: "flex flex-1 min-h-0 flex-col bg-neutral-950 text-neutral-200", children: [
|
|
62781
|
-
/* @__PURE__ */ jsxs132("div", { className: "flex items-center gap-3 border-b border-neutral-800 px-4 py-2", children: [
|
|
62782
|
-
/* @__PURE__ */
|
|
62783
|
-
subView === "board" && /* @__PURE__ */
|
|
63253
|
+
return /* @__PURE__ */ jsxs132("div", { className: "flex w-full max-w-[100vw] flex-1 min-h-0 min-w-0 flex-col overflow-hidden bg-neutral-950 text-neutral-200", children: [
|
|
63254
|
+
/* @__PURE__ */ jsxs132("div", { className: "flex flex-wrap items-center gap-3 border-b border-neutral-800 px-4 py-2", children: [
|
|
63255
|
+
/* @__PURE__ */ jsx155(SubViewToggle, { value: subView, onChange: changeSubView }),
|
|
63256
|
+
subView === "board" && /* @__PURE__ */ jsx155(
|
|
62784
63257
|
CommentsSubmitBar,
|
|
62785
63258
|
{
|
|
62786
63259
|
draftCount: comments.draftCount,
|
|
62787
63260
|
pendingCount: comments.pending?.length ?? 0,
|
|
62788
63261
|
submitState: comments.submitState,
|
|
62789
|
-
|
|
63262
|
+
submitError: comments.submitError,
|
|
63263
|
+
messageCopied: feedbackMessageCopied,
|
|
63264
|
+
onSave: () => void saveFeedbackAndCopyMessage(),
|
|
63265
|
+
onMessageCopied: () => setFeedbackMessageCopied(true)
|
|
62790
63266
|
}
|
|
62791
63267
|
)
|
|
62792
63268
|
] }),
|
|
62793
|
-
subView === "board" ? /* @__PURE__ */
|
|
62794
|
-
/* @__PURE__ */
|
|
62795
|
-
/* @__PURE__ */
|
|
62796
|
-
|
|
63269
|
+
subView === "board" ? /* @__PURE__ */ jsx155("div", { className: "flex-1 min-h-0 overflow-auto", children: /* @__PURE__ */ jsxs132("div", { className: "mx-auto max-w-[1400px] px-4 py-5 sm:px-8 sm:py-8", children: [
|
|
63270
|
+
/* @__PURE__ */ jsx155(StoryboardDirection, { globals: data.globals, frameCount: data.frames.length }),
|
|
63271
|
+
/* @__PURE__ */ jsx155(
|
|
63272
|
+
StoryboardReviewGuide,
|
|
63273
|
+
{
|
|
63274
|
+
frames: data.frames,
|
|
63275
|
+
draftCount: comments.draftCount,
|
|
63276
|
+
pendingCount: comments.pending?.length ?? 0,
|
|
63277
|
+
onFeedbackMessageCopied: () => setFeedbackMessageCopied(true)
|
|
63278
|
+
}
|
|
63279
|
+
),
|
|
63280
|
+
/* @__PURE__ */ jsx155(
|
|
63281
|
+
StoryboardWarnings,
|
|
63282
|
+
{
|
|
63283
|
+
warnings: data.warnings,
|
|
63284
|
+
onOpenSource: () => changeSubView("source")
|
|
63285
|
+
}
|
|
63286
|
+
),
|
|
63287
|
+
/* @__PURE__ */ jsx155(
|
|
62797
63288
|
StoryboardGrid,
|
|
62798
63289
|
{
|
|
62799
63290
|
projectId,
|
|
@@ -62805,8 +63296,8 @@ function StoryboardLoaded({
|
|
|
62805
63296
|
posterVersion: data.signature
|
|
62806
63297
|
}
|
|
62807
63298
|
),
|
|
62808
|
-
data.script && /* @__PURE__ */
|
|
62809
|
-
] }) }) : /* @__PURE__ */
|
|
63299
|
+
data.script && /* @__PURE__ */ jsx155(StoryboardScriptPanel, { script: data.script })
|
|
63300
|
+
] }) }) : /* @__PURE__ */ jsx155(
|
|
62810
63301
|
StoryboardSourceEditor,
|
|
62811
63302
|
{
|
|
62812
63303
|
files: sourceFiles,
|
|
@@ -62820,24 +63311,67 @@ function CommentsSubmitBar({
|
|
|
62820
63311
|
draftCount,
|
|
62821
63312
|
pendingCount,
|
|
62822
63313
|
submitState,
|
|
62823
|
-
|
|
62824
|
-
|
|
62825
|
-
|
|
62826
|
-
|
|
62827
|
-
|
|
62828
|
-
|
|
62829
|
-
|
|
62830
|
-
"
|
|
63314
|
+
submitError,
|
|
63315
|
+
messageCopied,
|
|
63316
|
+
onSave,
|
|
63317
|
+
onMessageCopied
|
|
63318
|
+
}) {
|
|
63319
|
+
return /* @__PURE__ */ jsxs132("div", { className: "ml-auto flex min-w-0 flex-1 flex-wrap items-center justify-end gap-2 sm:flex-none", children: [
|
|
63320
|
+
pendingCount > 0 && /* @__PURE__ */ jsxs132(Fragment46, { children: [
|
|
63321
|
+
/* @__PURE__ */ jsx155("span", { className: "text-xs text-sky-300", children: messageCopied ? "Feedback saved \xB7 Message copied \u2014 paste it in your terminal or IDE agent chat." : "Feedback saved \xB7 Agent not notified." }),
|
|
63322
|
+
/* @__PURE__ */ jsx155(
|
|
63323
|
+
AgentChatMessageButton,
|
|
63324
|
+
{
|
|
63325
|
+
message: APPLY_STORYBOARD_FEEDBACK_MESSAGE,
|
|
63326
|
+
label: messageCopied ? "Copy again" : "Copy prompt for agent",
|
|
63327
|
+
onCopied: onMessageCopied
|
|
63328
|
+
}
|
|
63329
|
+
)
|
|
62831
63330
|
] }),
|
|
62832
|
-
/* @__PURE__ */
|
|
63331
|
+
pendingCount === 0 && draftCount === 0 && /* @__PURE__ */ jsx155("span", { className: "text-xs text-neutral-500", children: "Add frame comments to request changes." }),
|
|
63332
|
+
submitError && /* @__PURE__ */ jsxs132("span", { className: "max-w-64 truncate text-xs text-red-400", title: submitError, children: [
|
|
63333
|
+
"Couldn\u2019t submit: ",
|
|
63334
|
+
submitError
|
|
63335
|
+
] }),
|
|
63336
|
+
draftCount > 0 && /* @__PURE__ */ jsxs132(
|
|
62833
63337
|
Button,
|
|
62834
63338
|
{
|
|
62835
63339
|
variant: "primary",
|
|
62836
63340
|
size: "sm",
|
|
62837
63341
|
loading: submitState === "saving",
|
|
62838
|
-
disabled:
|
|
62839
|
-
onClick:
|
|
62840
|
-
children:
|
|
63342
|
+
disabled: submitState === "saving",
|
|
63343
|
+
onClick: onSave,
|
|
63344
|
+
children: [
|
|
63345
|
+
"Save & copy message (",
|
|
63346
|
+
draftCount,
|
|
63347
|
+
")"
|
|
63348
|
+
]
|
|
63349
|
+
}
|
|
63350
|
+
)
|
|
63351
|
+
] });
|
|
63352
|
+
}
|
|
63353
|
+
function StoryboardWarnings({
|
|
63354
|
+
warnings,
|
|
63355
|
+
onOpenSource
|
|
63356
|
+
}) {
|
|
63357
|
+
if (warnings.length === 0) return null;
|
|
63358
|
+
return /* @__PURE__ */ jsxs132("details", { className: "mt-3 rounded-lg border border-amber-900/60 bg-amber-950/20 px-4 py-2 text-xs text-amber-200", children: [
|
|
63359
|
+
/* @__PURE__ */ jsxs132("summary", { className: "cursor-pointer font-medium", children: [
|
|
63360
|
+
warnings.length,
|
|
63361
|
+
" storyboard warning",
|
|
63362
|
+
warnings.length === 1 ? "" : "s"
|
|
63363
|
+
] }),
|
|
63364
|
+
/* @__PURE__ */ jsx155("ul", { className: "mt-2 space-y-1 text-amber-200/80", children: warnings.map((warning, index) => /* @__PURE__ */ jsxs132("li", { children: [
|
|
63365
|
+
warning.line ? `Line ${warning.line}: ` : "",
|
|
63366
|
+
warning.message
|
|
63367
|
+
] }, `${warning.line ?? "unknown"}-${index}`)) }),
|
|
63368
|
+
/* @__PURE__ */ jsx155(
|
|
63369
|
+
"button",
|
|
63370
|
+
{
|
|
63371
|
+
type: "button",
|
|
63372
|
+
onClick: onOpenSource,
|
|
63373
|
+
className: "mt-2 rounded text-amber-100 underline underline-offset-2 hover:text-white",
|
|
63374
|
+
children: "Open source to fix"
|
|
62841
63375
|
}
|
|
62842
63376
|
)
|
|
62843
63377
|
] });
|
|
@@ -62855,14 +63389,14 @@ function SubViewToggle({ value, onChange }) {
|
|
|
62855
63389
|
const next = SUB_VIEWS[(currentIndex + delta + SUB_VIEWS.length) % SUB_VIEWS.length];
|
|
62856
63390
|
if (next) onChange(next.value);
|
|
62857
63391
|
};
|
|
62858
|
-
return /* @__PURE__ */
|
|
63392
|
+
return /* @__PURE__ */ jsx155(
|
|
62859
63393
|
"div",
|
|
62860
63394
|
{
|
|
62861
63395
|
className: "flex items-center gap-0.5 rounded-md bg-neutral-900 p-0.5",
|
|
62862
63396
|
role: "tablist",
|
|
62863
63397
|
"aria-label": "Storyboard view",
|
|
62864
63398
|
onKeyDown: handleKeyDown,
|
|
62865
|
-
children: SUB_VIEWS.map((option) => /* @__PURE__ */
|
|
63399
|
+
children: SUB_VIEWS.map((option) => /* @__PURE__ */ jsx155(
|
|
62866
63400
|
"button",
|
|
62867
63401
|
{
|
|
62868
63402
|
type: "button",
|
|
@@ -62880,25 +63414,25 @@ function SubViewToggle({ value, onChange }) {
|
|
|
62880
63414
|
}
|
|
62881
63415
|
|
|
62882
63416
|
// src/components/storyboard/StoryboardView.tsx
|
|
62883
|
-
import { jsx as
|
|
63417
|
+
import { jsx as jsx156, jsxs as jsxs133 } from "react/jsx-runtime";
|
|
62884
63418
|
function StoryboardView({ projectId, onSelectComposition }) {
|
|
62885
63419
|
const { data, loading, error, reload } = useStoryboard(projectId);
|
|
62886
63420
|
useProjectSignaturePoll(projectId, data?.signature, reload);
|
|
62887
|
-
if (loading) return /* @__PURE__ */
|
|
63421
|
+
if (loading) return /* @__PURE__ */ jsx156(StoryboardFrame, { children: /* @__PURE__ */ jsx156(Message, { children: "Loading storyboard\u2026" }) });
|
|
62888
63422
|
if (error) {
|
|
62889
63423
|
return /* @__PURE__ */ jsxs133(StoryboardFrame, { children: [
|
|
62890
63424
|
/* @__PURE__ */ jsxs133(Message, { tone: "error", children: [
|
|
62891
63425
|
"Couldn\u2019t load the storyboard: ",
|
|
62892
63426
|
error
|
|
62893
63427
|
] }),
|
|
62894
|
-
/* @__PURE__ */
|
|
63428
|
+
/* @__PURE__ */ jsx156("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx156(Button, { size: "sm", variant: "secondary", onClick: reload, children: "Retry" }) })
|
|
62895
63429
|
] });
|
|
62896
63430
|
}
|
|
62897
|
-
if (!data) return /* @__PURE__ */
|
|
63431
|
+
if (!data) return /* @__PURE__ */ jsx156(StoryboardFrame, { children: null });
|
|
62898
63432
|
if (!data.exists) {
|
|
62899
|
-
return /* @__PURE__ */
|
|
63433
|
+
return /* @__PURE__ */ jsx156(StoryboardFrame, { children: /* @__PURE__ */ jsx156(EmptyState, { path: data.path }) });
|
|
62900
63434
|
}
|
|
62901
|
-
return /* @__PURE__ */
|
|
63435
|
+
return /* @__PURE__ */ jsx156(
|
|
62902
63436
|
StoryboardLoaded,
|
|
62903
63437
|
{
|
|
62904
63438
|
projectId,
|
|
@@ -62909,10 +63443,10 @@ function StoryboardView({ projectId, onSelectComposition }) {
|
|
|
62909
63443
|
);
|
|
62910
63444
|
}
|
|
62911
63445
|
function StoryboardFrame({ children }) {
|
|
62912
|
-
return /* @__PURE__ */
|
|
63446
|
+
return /* @__PURE__ */ jsx156("div", { className: "flex-1 min-h-0 overflow-auto bg-neutral-950 text-neutral-200", children: /* @__PURE__ */ jsx156("div", { className: "mx-auto max-w-[1400px] px-8 py-8", children }) });
|
|
62913
63447
|
}
|
|
62914
63448
|
function Message({ children, tone = "muted" }) {
|
|
62915
|
-
return /* @__PURE__ */
|
|
63449
|
+
return /* @__PURE__ */ jsx156(
|
|
62916
63450
|
"div",
|
|
62917
63451
|
{
|
|
62918
63452
|
className: `px-6 py-12 text-center text-sm ${tone === "error" ? "text-red-400" : "text-neutral-500"}`,
|
|
@@ -62945,7 +63479,7 @@ Add one \`## Frame N\` section per beat. Keep the arc tight.
|
|
|
62945
63479
|
Then run the review loop from the hyperframes-core skill (references/review-loop.md): present the plan as a proposal, offer wireframe sketches on this board, and build on the confirmed layouts.`;
|
|
62946
63480
|
}
|
|
62947
63481
|
function EmptyState({ path }) {
|
|
62948
|
-
const [copied, setCopied] =
|
|
63482
|
+
const [copied, setCopied] = useState118(false);
|
|
62949
63483
|
const prompt = handoffPrompt(path);
|
|
62950
63484
|
const onCopy = async () => {
|
|
62951
63485
|
if (await copyTextToClipboard(prompt)) {
|
|
@@ -62955,67 +63489,67 @@ function EmptyState({ path }) {
|
|
|
62955
63489
|
};
|
|
62956
63490
|
return /* @__PURE__ */ jsxs133("div", { children: [
|
|
62957
63491
|
/* @__PURE__ */ jsxs133("div", { className: "rounded-lg border border-dashed border-neutral-800 px-6 py-10 text-center", children: [
|
|
62958
|
-
/* @__PURE__ */
|
|
63492
|
+
/* @__PURE__ */ jsx156("h2", { className: "text-base font-semibold text-neutral-300", children: "No storyboard yet" }),
|
|
62959
63493
|
/* @__PURE__ */ jsxs133("p", { className: "mx-auto mt-2 max-w-md text-sm text-neutral-500", children: [
|
|
62960
63494
|
"Add a ",
|
|
62961
|
-
/* @__PURE__ */
|
|
63495
|
+
/* @__PURE__ */ jsx156("code", { className: "rounded bg-neutral-900 px-1 py-0.5 text-neutral-400", children: path }),
|
|
62962
63496
|
" ",
|
|
62963
63497
|
"at the project root to plan this video frame by frame. Hand this prompt to your coding agent to scaffold it."
|
|
62964
63498
|
] }),
|
|
62965
63499
|
/* @__PURE__ */ jsxs133("div", { className: "mx-auto mt-6 max-w-2xl overflow-hidden rounded-lg border border-neutral-800 bg-neutral-900 text-left", children: [
|
|
62966
63500
|
/* @__PURE__ */ jsxs133("div", { className: "flex items-center justify-between border-b border-neutral-800 px-3 py-2", children: [
|
|
62967
|
-
/* @__PURE__ */
|
|
62968
|
-
/* @__PURE__ */
|
|
63501
|
+
/* @__PURE__ */ jsx156("span", { className: "font-mono text-xs text-neutral-500", children: "Prompt for your agent" }),
|
|
63502
|
+
/* @__PURE__ */ jsx156(
|
|
62969
63503
|
Button,
|
|
62970
63504
|
{
|
|
62971
63505
|
size: "sm",
|
|
62972
63506
|
variant: "secondary",
|
|
62973
63507
|
onClick: onCopy,
|
|
62974
|
-
icon: copied ? /* @__PURE__ */
|
|
63508
|
+
icon: copied ? /* @__PURE__ */ jsx156(Check2, { size: 14 }) : /* @__PURE__ */ jsx156(Copy2, { size: 14 }),
|
|
62975
63509
|
children: copied ? "Copied" : "Copy prompt"
|
|
62976
63510
|
}
|
|
62977
63511
|
)
|
|
62978
63512
|
] }),
|
|
62979
|
-
/* @__PURE__ */
|
|
63513
|
+
/* @__PURE__ */ jsx156("pre", { className: "max-h-64 overflow-auto px-4 py-3 font-mono text-xs leading-relaxed text-neutral-400 whitespace-pre-wrap", children: prompt })
|
|
62980
63514
|
] })
|
|
62981
63515
|
] }),
|
|
62982
|
-
/* @__PURE__ */
|
|
63516
|
+
/* @__PURE__ */ jsx156(SkeletonPreview, {})
|
|
62983
63517
|
] });
|
|
62984
63518
|
}
|
|
62985
63519
|
function SkeletonPreview() {
|
|
62986
63520
|
return /* @__PURE__ */ jsxs133("div", { "aria-hidden": "true", className: "mt-10 select-none opacity-40", children: [
|
|
62987
|
-
/* @__PURE__ */
|
|
62988
|
-
/* @__PURE__ */
|
|
62989
|
-
/* @__PURE__ */
|
|
62990
|
-
/* @__PURE__ */
|
|
62991
|
-
/* @__PURE__ */
|
|
62992
|
-
/* @__PURE__ */
|
|
63521
|
+
/* @__PURE__ */ jsx156("div", { className: "mb-4 text-center text-xs uppercase tracking-wide text-neutral-600", children: "Preview" }),
|
|
63522
|
+
/* @__PURE__ */ jsx156("div", { className: "grid gap-x-6 gap-y-8 [grid-template-columns:repeat(auto-fill,minmax(300px,1fr))]", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsxs133("div", { className: "rounded-lg border border-neutral-800 bg-neutral-900/40 p-3", children: [
|
|
63523
|
+
/* @__PURE__ */ jsx156("div", { className: "aspect-video w-full rounded bg-neutral-800/60" }),
|
|
63524
|
+
/* @__PURE__ */ jsx156("div", { className: "mt-3 h-3 w-2/3 rounded bg-neutral-800/60" }),
|
|
63525
|
+
/* @__PURE__ */ jsx156("div", { className: "mt-2 h-2.5 w-full rounded bg-neutral-800/40" }),
|
|
63526
|
+
/* @__PURE__ */ jsx156("div", { className: "mt-1.5 h-2.5 w-4/5 rounded bg-neutral-800/40" })
|
|
62993
63527
|
] }, i)) })
|
|
62994
63528
|
] });
|
|
62995
63529
|
}
|
|
62996
63530
|
|
|
62997
63531
|
// src/components/StudioSplash.tsx
|
|
62998
|
-
import { jsx as
|
|
63532
|
+
import { jsx as jsx157, jsxs as jsxs134 } from "react/jsx-runtime";
|
|
62999
63533
|
function StudioSplash({ waiting }) {
|
|
63000
|
-
return /* @__PURE__ */
|
|
63001
|
-
/* @__PURE__ */
|
|
63534
|
+
return /* @__PURE__ */ jsx157("div", { className: "h-full w-full bg-neutral-950 flex items-center justify-center", children: waiting ? /* @__PURE__ */ jsxs134("div", { className: "flex flex-col items-center gap-3 text-center px-6", role: "status", children: [
|
|
63535
|
+
/* @__PURE__ */ jsx157("div", { className: "w-4 h-4 rounded-full border-2 border-neutral-700 border-t-neutral-500 animate-spin motion-reduce:animate-none" }),
|
|
63002
63536
|
/* @__PURE__ */ jsxs134("p", { className: "text-xs text-neutral-600", children: [
|
|
63003
63537
|
"Waiting for preview server\u2026 run",
|
|
63004
63538
|
" ",
|
|
63005
|
-
/* @__PURE__ */
|
|
63539
|
+
/* @__PURE__ */ jsx157("code", { className: "text-neutral-500 font-mono", children: "npm run dev" })
|
|
63006
63540
|
] })
|
|
63007
63541
|
] }) : /* @__PURE__ */ jsxs134("div", { className: "flex flex-col items-center gap-3 text-center px-6", role: "status", children: [
|
|
63008
|
-
/* @__PURE__ */
|
|
63009
|
-
/* @__PURE__ */
|
|
63542
|
+
/* @__PURE__ */ jsx157("div", { className: "w-4 h-4 rounded-full bg-studio-accent animate-pulse motion-reduce:animate-none" }),
|
|
63543
|
+
/* @__PURE__ */ jsx157("p", { className: "text-xs text-neutral-600", children: "Connecting to project\u2026" })
|
|
63010
63544
|
] }) });
|
|
63011
63545
|
}
|
|
63012
63546
|
|
|
63013
63547
|
// src/hooks/useServerConnection.ts
|
|
63014
|
-
import { useEffect as
|
|
63548
|
+
import { useEffect as useEffect101, useState as useState119 } from "react";
|
|
63015
63549
|
function useServerConnection() {
|
|
63016
|
-
const [projectId, setProjectId] =
|
|
63017
|
-
const [resolving, setResolving] =
|
|
63018
|
-
const [waitingForServer, setWaitingForServer] =
|
|
63550
|
+
const [projectId, setProjectId] = useState119(null);
|
|
63551
|
+
const [resolving, setResolving] = useState119(true);
|
|
63552
|
+
const [waitingForServer, setWaitingForServer] = useState119(false);
|
|
63019
63553
|
useMountEffect(() => {
|
|
63020
63554
|
const hashProjectId = parseProjectIdFromHash(window.location.hash);
|
|
63021
63555
|
let cancelled = false;
|
|
@@ -63052,7 +63586,7 @@ function useServerConnection() {
|
|
|
63052
63586
|
if (retryTimer !== null) clearTimeout(retryTimer);
|
|
63053
63587
|
};
|
|
63054
63588
|
});
|
|
63055
|
-
|
|
63589
|
+
useEffect101(() => {
|
|
63056
63590
|
const onHashChange = () => {
|
|
63057
63591
|
const next = parseProjectIdFromHash(window.location.hash);
|
|
63058
63592
|
if (next && next !== projectId) setProjectId(next);
|
|
@@ -63064,56 +63598,56 @@ function useServerConnection() {
|
|
|
63064
63598
|
}
|
|
63065
63599
|
|
|
63066
63600
|
// src/App.tsx
|
|
63067
|
-
import { jsx as
|
|
63601
|
+
import { jsx as jsx158, jsxs as jsxs135 } from "react/jsx-runtime";
|
|
63068
63602
|
function StudioApp() {
|
|
63069
63603
|
const { projectId, resolving, waitingForServer } = useServerConnection();
|
|
63070
|
-
const initialUrlStateRef =
|
|
63604
|
+
const initialUrlStateRef = useRef120(readStudioUrlStateFromWindow());
|
|
63071
63605
|
const viewModeValue = useViewModeState();
|
|
63072
|
-
|
|
63606
|
+
useEffect102(() => {
|
|
63073
63607
|
if (resolving || waitingForServer) return;
|
|
63074
63608
|
if (hasFiredSessionStart()) return;
|
|
63075
63609
|
markSessionStartFired();
|
|
63076
63610
|
trackStudioSessionStart({ has_project: projectId != null });
|
|
63077
63611
|
}, [projectId, resolving, waitingForServer]);
|
|
63078
|
-
const [activeCompPath, setActiveCompPath] =
|
|
63079
|
-
const [activeCompPathHydrated, setActiveCompPathHydrated] =
|
|
63612
|
+
const [activeCompPath, setActiveCompPath] = useState120(null);
|
|
63613
|
+
const [activeCompPathHydrated, setActiveCompPathHydrated] = useState120(
|
|
63080
63614
|
() => initialUrlStateRef.current.activeCompPath == null
|
|
63081
63615
|
);
|
|
63082
|
-
const [compIdToSrc, setCompIdToSrc] =
|
|
63083
|
-
const [previewIframe, setPreviewIframe] =
|
|
63084
|
-
const [compositionLoading, setCompositionLoading] =
|
|
63085
|
-
const [refreshKey, setRefreshKey] =
|
|
63616
|
+
const [compIdToSrc, setCompIdToSrc] = useState120(/* @__PURE__ */ new Map());
|
|
63617
|
+
const [previewIframe, setPreviewIframe] = useState120(null);
|
|
63618
|
+
const [compositionLoading, setCompositionLoading] = useState120(true);
|
|
63619
|
+
const [refreshKey, setRefreshKey] = useState120(0);
|
|
63086
63620
|
const [previewDocumentVersion, refreshPreviewDocumentVersion] = usePreviewDocumentVersion();
|
|
63087
|
-
const [blockPreview, setBlockPreview] =
|
|
63088
|
-
const previewIframeRef =
|
|
63089
|
-
const activeCompPathRef =
|
|
63621
|
+
const [blockPreview, setBlockPreview] = useState120(null);
|
|
63622
|
+
const previewIframeRef = useRef120(null);
|
|
63623
|
+
const activeCompPathRef = useRef120(activeCompPath);
|
|
63090
63624
|
activeCompPathRef.current = activeCompPath;
|
|
63091
|
-
const leftSidebarRef =
|
|
63625
|
+
const leftSidebarRef = useRef120(null);
|
|
63092
63626
|
const renderQueue = useRenderQueue(projectId);
|
|
63093
63627
|
const captionEditMode = useCaptionStore((s) => s.isEditMode);
|
|
63094
63628
|
const captionHasSelection = useCaptionStore((s) => s.selectedSegmentIds.size > 0);
|
|
63095
63629
|
const captionSync = useCaptionSync(projectId);
|
|
63096
63630
|
const timelineElements = usePlayerStore((s) => s.elements);
|
|
63097
63631
|
const setSelectedTimelineElementId = usePlayerStore((s) => s.setSelectedElementId);
|
|
63098
|
-
const
|
|
63632
|
+
const timelineDuration2 = usePlayerStore((s) => s.duration);
|
|
63099
63633
|
const isPlaying = usePlayerStore((s) => s.isPlaying);
|
|
63100
63634
|
const isMasterView = !activeCompPath || activeCompPath === "index.html";
|
|
63101
63635
|
const activePreviewUrl = activeCompPath ? `/api/projects/${projectId}/preview/comp/${activeCompPath}` : null;
|
|
63102
63636
|
const effectiveTimelineDuration = useMemo50(() => {
|
|
63103
63637
|
const maxEnd = timelineElements.length > 0 ? Math.max(...timelineElements.map((el) => el.start + el.duration)) : 0;
|
|
63104
|
-
return Math.max(
|
|
63105
|
-
}, [
|
|
63638
|
+
return Math.max(timelineDuration2, maxEnd);
|
|
63639
|
+
}, [timelineDuration2, timelineElements]);
|
|
63106
63640
|
const { toasts, showToast, dismissToast } = useToast();
|
|
63107
63641
|
const panelLayout = usePanelLayout({
|
|
63108
63642
|
rightCollapsed: initialUrlStateRef.current.rightCollapsed,
|
|
63109
63643
|
rightPanelTab: initialUrlStateRef.current.rightPanelTab
|
|
63110
63644
|
});
|
|
63111
63645
|
const editHistory = usePersistentEditHistory({ projectId });
|
|
63112
|
-
const domEditSaveTimestampRef =
|
|
63113
|
-
const handleDomZIndexReorderCommitRef =
|
|
63114
|
-
const pendingTimelineEditPathRef =
|
|
63115
|
-
const isGestureRecordingRef =
|
|
63116
|
-
const reloadPreview =
|
|
63646
|
+
const domEditSaveTimestampRef = useRef120(0);
|
|
63647
|
+
const handleDomZIndexReorderCommitRef = useRef120(null);
|
|
63648
|
+
const pendingTimelineEditPathRef = useRef120(/* @__PURE__ */ new Set());
|
|
63649
|
+
const isGestureRecordingRef = useRef120(false);
|
|
63650
|
+
const reloadPreview = useCallback142(() => setRefreshKey((k) => k + 1), []);
|
|
63117
63651
|
const fileManager = useFileManager({
|
|
63118
63652
|
projectId,
|
|
63119
63653
|
showToast,
|
|
@@ -63131,7 +63665,7 @@ function StudioApp() {
|
|
|
63131
63665
|
domEditSaveTimestampRef,
|
|
63132
63666
|
masterCompPath
|
|
63133
63667
|
);
|
|
63134
|
-
|
|
63668
|
+
useEffect102(() => {
|
|
63135
63669
|
if (activeCompPathHydrated) return;
|
|
63136
63670
|
if (!fileManager.fileTreeLoaded) return;
|
|
63137
63671
|
const nextCompPath = normalizeStudioCompositionPath(
|
|
@@ -63172,20 +63706,14 @@ function StudioApp() {
|
|
|
63172
63706
|
forceReloadSdkSession: sdkHandle.forceReload,
|
|
63173
63707
|
handleDomZIndexReorderCommitRef
|
|
63174
63708
|
});
|
|
63175
|
-
const handleTimelineElementsMove =
|
|
63709
|
+
const handleTimelineElementsMove = useCallback142(
|
|
63176
63710
|
async (edits, coalesceKey, operation = "timing", coalesceMs) => {
|
|
63177
63711
|
const deps = { handleTimelineGroupMove: timelineEditing.handleTimelineGroupMove };
|
|
63178
63712
|
await persistTimelineMoveEditsAtomically(edits, coalesceKey, operation, deps, coalesceMs);
|
|
63179
63713
|
},
|
|
63180
63714
|
[timelineEditing.handleTimelineGroupMove]
|
|
63181
63715
|
);
|
|
63182
|
-
const handleAddAssetAtPlayhead =
|
|
63183
|
-
(assetPath) => timelineEditing.handleTimelineAssetDrop(assetPath, {
|
|
63184
|
-
start: usePlayerStore.getState().currentTime,
|
|
63185
|
-
track: 0
|
|
63186
|
-
}),
|
|
63187
|
-
[timelineEditing]
|
|
63188
|
-
);
|
|
63716
|
+
const handleAddAssetAtPlayhead = useAddAssetAtPlayhead(timelineEditing.handleTimelineAssetDrop);
|
|
63189
63717
|
const {
|
|
63190
63718
|
activeBlockParams,
|
|
63191
63719
|
setActiveBlockParams,
|
|
@@ -63208,18 +63736,18 @@ function StudioApp() {
|
|
|
63208
63736
|
setRightCollapsed: panelLayout.setRightCollapsed,
|
|
63209
63737
|
setRightPanelTab: panelLayout.setRightPanelTab
|
|
63210
63738
|
});
|
|
63211
|
-
const clearDomSelectionRef =
|
|
63739
|
+
const clearDomSelectionRef = useRef120(() => {
|
|
63212
63740
|
});
|
|
63213
|
-
const domEditSelectionBridgeRef =
|
|
63214
|
-
const handleDomEditElementDeleteRef =
|
|
63741
|
+
const domEditSelectionBridgeRef = useRef120(null);
|
|
63742
|
+
const handleDomEditElementDeleteRef = useRef120(
|
|
63215
63743
|
async () => {
|
|
63216
63744
|
}
|
|
63217
63745
|
);
|
|
63218
63746
|
const domEditDeleteBridge = (s) => handleDomEditElementDeleteRef.current(s);
|
|
63219
|
-
const resetKeyframesRef =
|
|
63220
|
-
const deleteSelectedKeyframesRef =
|
|
63747
|
+
const resetKeyframesRef = useRef120(() => false);
|
|
63748
|
+
const deleteSelectedKeyframesRef = useRef120(() => {
|
|
63221
63749
|
});
|
|
63222
|
-
const invalidateGsapCacheRef =
|
|
63750
|
+
const invalidateGsapCacheRef = useRef120(() => {
|
|
63223
63751
|
});
|
|
63224
63752
|
const { handleCopy, handlePaste, handleCut } = useClipboard({
|
|
63225
63753
|
projectId,
|
|
@@ -63261,7 +63789,7 @@ function StudioApp() {
|
|
|
63261
63789
|
forceReloadSdkSession: sdkHandle.forceReload,
|
|
63262
63790
|
onToggleRecording: STUDIO_KEYFRAMES_ENABLED ? () => handleToggleRecordingRef.current() : void 0
|
|
63263
63791
|
});
|
|
63264
|
-
const sidebarTabRef =
|
|
63792
|
+
const sidebarTabRef = useRef120({
|
|
63265
63793
|
select: (t) => leftSidebarRef.current?.selectTab(t),
|
|
63266
63794
|
get: () => leftSidebarRef.current?.getTab() ?? "compositions"
|
|
63267
63795
|
});
|
|
@@ -63349,9 +63877,9 @@ function StudioApp() {
|
|
|
63349
63877
|
resetErrors: resetConsoleErrors
|
|
63350
63878
|
} = useConsoleErrorCapture(previewIframe);
|
|
63351
63879
|
const dragOverlay = useGlobalFileDrop(timelineEditing.handleTimelineFileDrop);
|
|
63352
|
-
const handleToggleRecordingRef =
|
|
63880
|
+
const handleToggleRecordingRef = useRef120(() => {
|
|
63353
63881
|
});
|
|
63354
|
-
const domEditSessionRef =
|
|
63882
|
+
const domEditSessionRef = useRef120(domEditSession);
|
|
63355
63883
|
domEditSessionRef.current = domEditSession;
|
|
63356
63884
|
const { gestureState, gestureRecording, handleToggleRecording } = useGestureCommit({
|
|
63357
63885
|
domEditSessionRef,
|
|
@@ -63361,7 +63889,7 @@ function StudioApp() {
|
|
|
63361
63889
|
});
|
|
63362
63890
|
handleToggleRecordingRef.current = handleToggleRecording;
|
|
63363
63891
|
const recordingToggle = STUDIO_KEYFRAMES_ENABLED ? handleToggleRecording : void 0;
|
|
63364
|
-
const canvasRectRef =
|
|
63892
|
+
const canvasRectRef = useRef120(null);
|
|
63365
63893
|
useLayoutEffect4(() => {
|
|
63366
63894
|
if (gestureState !== "recording" || !previewIframe) {
|
|
63367
63895
|
canvasRectRef.current = null;
|
|
@@ -63370,7 +63898,7 @@ function StudioApp() {
|
|
|
63370
63898
|
const r = previewIframe.getBoundingClientRect();
|
|
63371
63899
|
canvasRectRef.current = { left: r.left, top: r.top, width: r.width, height: r.height };
|
|
63372
63900
|
}, [gestureState, previewIframe]);
|
|
63373
|
-
const handlePreviewIframeRef =
|
|
63901
|
+
const handlePreviewIframeRef = useCallback142(
|
|
63374
63902
|
(iframe) => {
|
|
63375
63903
|
previewIframeRef.current = iframe;
|
|
63376
63904
|
setPreviewIframe(iframe);
|
|
@@ -63439,7 +63967,7 @@ function StudioApp() {
|
|
|
63439
63967
|
refreshPreviewDocumentVersion
|
|
63440
63968
|
});
|
|
63441
63969
|
const timelineToolbar = useMemo50(
|
|
63442
|
-
() => /* @__PURE__ */
|
|
63970
|
+
() => /* @__PURE__ */ jsx158(
|
|
63443
63971
|
TimelineToolbar,
|
|
63444
63972
|
{
|
|
63445
63973
|
domEditSession,
|
|
@@ -63449,8 +63977,8 @@ function StudioApp() {
|
|
|
63449
63977
|
[domEditSession, timelineEditing.handleTimelineElementSplit]
|
|
63450
63978
|
);
|
|
63451
63979
|
if (resolving || waitingForServer || !projectId)
|
|
63452
|
-
return /* @__PURE__ */
|
|
63453
|
-
return /* @__PURE__ */
|
|
63980
|
+
return /* @__PURE__ */ jsx158(StudioSplash, { waiting: waitingForServer });
|
|
63981
|
+
return /* @__PURE__ */ jsx158(StudioShellProvider, { value: studioCtxValue, children: /* @__PURE__ */ jsx158(StudioPlaybackProvider, { value: studioCtxValue, children: /* @__PURE__ */ jsx158(ViewModeProvider, { value: viewModeValue, children: /* @__PURE__ */ jsx158(PanelLayoutProvider, { value: panelLayout, children: /* @__PURE__ */ jsx158(FileManagerProvider, { value: fileManager, children: /* @__PURE__ */ jsx158(DomEditProvider, { value: domEditSession, children: /* @__PURE__ */ jsxs135(
|
|
63454
63982
|
"div",
|
|
63455
63983
|
{
|
|
63456
63984
|
className: "flex flex-col h-full w-full bg-neutral-950 relative",
|
|
@@ -63459,7 +63987,7 @@ function StudioApp() {
|
|
|
63459
63987
|
onDragLeave: dragOverlay.onDragLeave,
|
|
63460
63988
|
onDrop: dragOverlay.onDrop,
|
|
63461
63989
|
children: [
|
|
63462
|
-
/* @__PURE__ */
|
|
63990
|
+
/* @__PURE__ */ jsx158(
|
|
63463
63991
|
StudioHeader,
|
|
63464
63992
|
{
|
|
63465
63993
|
captureFrameHref: frameCapture.captureFrameHref,
|
|
@@ -63477,25 +64005,25 @@ function StudioApp() {
|
|
|
63477
64005
|
}
|
|
63478
64006
|
}
|
|
63479
64007
|
),
|
|
63480
|
-
previewPersistence.domEditSaveQueuePaused && /* @__PURE__ */
|
|
64008
|
+
previewPersistence.domEditSaveQueuePaused && /* @__PURE__ */ jsx158(
|
|
63481
64009
|
SaveQueuePausedBanner,
|
|
63482
64010
|
{
|
|
63483
64011
|
message: previewPersistence.domEditSaveQueuePaused,
|
|
63484
64012
|
onRetry: previewPersistence.resetDomEditSaveQueueBreaker
|
|
63485
64013
|
}
|
|
63486
64014
|
),
|
|
63487
|
-
viewModeValue.viewMode === "storyboard" && /* @__PURE__ */
|
|
64015
|
+
viewModeValue.viewMode === "storyboard" && /* @__PURE__ */ jsx158(
|
|
63488
64016
|
StoryboardView,
|
|
63489
64017
|
{
|
|
63490
64018
|
projectId,
|
|
63491
64019
|
onSelectComposition: handleSelectComposition
|
|
63492
64020
|
}
|
|
63493
64021
|
),
|
|
63494
|
-
/* @__PURE__ */
|
|
64022
|
+
/* @__PURE__ */ jsx158(
|
|
63495
64023
|
EditorShell,
|
|
63496
64024
|
{
|
|
63497
64025
|
hidden: viewModeValue.viewMode === "storyboard",
|
|
63498
|
-
left: /* @__PURE__ */
|
|
64026
|
+
left: /* @__PURE__ */ jsx158(
|
|
63499
64027
|
StudioLeftSidebar,
|
|
63500
64028
|
{
|
|
63501
64029
|
leftSidebarRef,
|
|
@@ -63509,7 +64037,7 @@ function StudioApp() {
|
|
|
63509
64037
|
onAddAssetToTimeline: handleAddAssetAtPlayhead
|
|
63510
64038
|
}
|
|
63511
64039
|
),
|
|
63512
|
-
right: panelLayout.rightCollapsed ? null : /* @__PURE__ */
|
|
64040
|
+
right: panelLayout.rightCollapsed ? null : /* @__PURE__ */ jsx158(
|
|
63513
64041
|
StudioRightPanel,
|
|
63514
64042
|
{
|
|
63515
64043
|
designPanelActive,
|
|
@@ -63523,6 +64051,7 @@ function StudioApp() {
|
|
|
63523
64051
|
onToggleRecording: recordingToggle,
|
|
63524
64052
|
sdkSession: sdkHandle.session,
|
|
63525
64053
|
publishSdkSession: sdkHandle.publish,
|
|
64054
|
+
forceReloadSdkSession: sdkHandle.forceReload,
|
|
63526
64055
|
reloadPreview,
|
|
63527
64056
|
domEditSaveTimestampRef,
|
|
63528
64057
|
recordEdit: editHistory.recordEdit,
|
|
@@ -63552,7 +64081,7 @@ function StudioApp() {
|
|
|
63552
64081
|
recordingState: gestureState,
|
|
63553
64082
|
onToggleRecording: recordingToggle,
|
|
63554
64083
|
blockPreview,
|
|
63555
|
-
gestureOverlay: gestureState === "recording" && previewIframe ? /* @__PURE__ */
|
|
64084
|
+
gestureOverlay: gestureState === "recording" && previewIframe ? /* @__PURE__ */ jsx158(
|
|
63556
64085
|
GestureTrailOverlay,
|
|
63557
64086
|
{
|
|
63558
64087
|
samples: gestureRecording.samplesRef.current,
|
|
@@ -63565,7 +64094,7 @@ function StudioApp() {
|
|
|
63565
64094
|
) : void 0
|
|
63566
64095
|
}
|
|
63567
64096
|
),
|
|
63568
|
-
/* @__PURE__ */
|
|
64097
|
+
/* @__PURE__ */ jsx158(
|
|
63569
64098
|
StudioOverlays,
|
|
63570
64099
|
{
|
|
63571
64100
|
projectId,
|
|
@@ -63587,32 +64116,32 @@ function StudioApp() {
|
|
|
63587
64116
|
}
|
|
63588
64117
|
|
|
63589
64118
|
// src/hooks/useElementPicker.ts
|
|
63590
|
-
import { useState as
|
|
64119
|
+
import { useState as useState121, useCallback as useCallback143, useRef as useRef121 } from "react";
|
|
63591
64120
|
function useElementPicker(iframeRef, options) {
|
|
63592
|
-
const [isPickMode, setIsPickMode] =
|
|
63593
|
-
const [pickedElement, setPickedElement] =
|
|
63594
|
-
const activeOverrideRef =
|
|
63595
|
-
const getActiveIframe =
|
|
64121
|
+
const [isPickMode, setIsPickMode] = useState121(false);
|
|
64122
|
+
const [pickedElement, setPickedElement] = useState121(null);
|
|
64123
|
+
const activeOverrideRef = useRef121(null);
|
|
64124
|
+
const getActiveIframe = useCallback143(() => {
|
|
63596
64125
|
return activeOverrideRef.current ?? iframeRef.current;
|
|
63597
64126
|
}, [iframeRef]);
|
|
63598
|
-
const setActiveIframe =
|
|
64127
|
+
const setActiveIframe = useCallback143((el) => {
|
|
63599
64128
|
activeOverrideRef.current = el;
|
|
63600
64129
|
}, []);
|
|
63601
|
-
const enablePick =
|
|
64130
|
+
const enablePick = useCallback143(() => {
|
|
63602
64131
|
try {
|
|
63603
64132
|
postRuntimeControlMessage(getActiveIframe()?.contentWindow, "enable-pick-mode");
|
|
63604
64133
|
setIsPickMode(true);
|
|
63605
64134
|
} catch {
|
|
63606
64135
|
}
|
|
63607
64136
|
}, [getActiveIframe]);
|
|
63608
|
-
const disablePick =
|
|
64137
|
+
const disablePick = useCallback143(() => {
|
|
63609
64138
|
try {
|
|
63610
64139
|
postRuntimeControlMessage(getActiveIframe()?.contentWindow, "disable-pick-mode");
|
|
63611
64140
|
} catch {
|
|
63612
64141
|
}
|
|
63613
64142
|
setIsPickMode(false);
|
|
63614
64143
|
}, [getActiveIframe]);
|
|
63615
|
-
const clearPick =
|
|
64144
|
+
const clearPick = useCallback143(() => {
|
|
63616
64145
|
setPickedElement(null);
|
|
63617
64146
|
}, []);
|
|
63618
64147
|
useMountEffect(() => {
|
|
@@ -63665,9 +64194,9 @@ function useElementPicker(iframeRef, options) {
|
|
|
63665
64194
|
window.addEventListener("message", handleMessage);
|
|
63666
64195
|
return () => window.removeEventListener("message", handleMessage);
|
|
63667
64196
|
});
|
|
63668
|
-
const optionsRef =
|
|
64197
|
+
const optionsRef = useRef121(options);
|
|
63669
64198
|
optionsRef.current = options;
|
|
63670
|
-
const syncToSource =
|
|
64199
|
+
const syncToSource = useCallback143(
|
|
63671
64200
|
(elementId, selector, op) => {
|
|
63672
64201
|
const opts = optionsRef.current;
|
|
63673
64202
|
if (!opts?.workspaceFiles || !opts.onSyncFiles || !elementId) return;
|
|
@@ -63683,7 +64212,7 @@ function useElementPicker(iframeRef, options) {
|
|
|
63683
64212
|
},
|
|
63684
64213
|
[]
|
|
63685
64214
|
);
|
|
63686
|
-
const setStyle =
|
|
64215
|
+
const setStyle = useCallback143(
|
|
63687
64216
|
(prop, value) => {
|
|
63688
64217
|
const activeIframe = getActiveIframe();
|
|
63689
64218
|
if (!pickedElement?.selector || !activeIframe) return;
|
|
@@ -63725,7 +64254,7 @@ function useElementPicker(iframeRef, options) {
|
|
|
63725
64254
|
},
|
|
63726
64255
|
[pickedElement, getActiveIframe, syncToSource]
|
|
63727
64256
|
);
|
|
63728
|
-
const setDataAttr =
|
|
64257
|
+
const setDataAttr = useCallback143(
|
|
63729
64258
|
(attr, value) => {
|
|
63730
64259
|
const activeIframe = getActiveIframe();
|
|
63731
64260
|
if (!pickedElement?.selector || !activeIframe) return;
|
|
@@ -63753,7 +64282,7 @@ function useElementPicker(iframeRef, options) {
|
|
|
63753
64282
|
},
|
|
63754
64283
|
[pickedElement, getActiveIframe, syncToSource]
|
|
63755
64284
|
);
|
|
63756
|
-
const setTextContent =
|
|
64285
|
+
const setTextContent = useCallback143(
|
|
63757
64286
|
(text) => {
|
|
63758
64287
|
const activeIframe = getActiveIframe();
|
|
63759
64288
|
if (!pickedElement?.selector || !activeIframe) return;
|
|
@@ -63776,7 +64305,7 @@ function useElementPicker(iframeRef, options) {
|
|
|
63776
64305
|
},
|
|
63777
64306
|
[pickedElement, getActiveIframe, syncToSource]
|
|
63778
64307
|
);
|
|
63779
|
-
const activeIframeRef =
|
|
64308
|
+
const activeIframeRef = useRef121(null);
|
|
63780
64309
|
activeIframeRef.current = getActiveIframe();
|
|
63781
64310
|
return {
|
|
63782
64311
|
isPickMode,
|