@hyperframes/studio 0.7.99 → 0.7.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{hyperframes-player-BY5RLMBA.js → hyperframes-player-D0x4bQn-.js} +1 -1
- package/dist/assets/{index-DMSqmZM6.js → index-CVAZ9AJE.js} +200 -200
- package/dist/assets/{index-CQ07_DLG.js → index-Cy1eXOyE.js} +1 -1
- package/dist/assets/{index-DeXLAktv.js → index-F8iVj3EF.js} +1 -1
- package/dist/index.html +1 -1
- package/dist/index.js +440 -344
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/App.tsx +2 -2
- package/src/components/StudioHeader.test.ts +28 -0
- package/src/components/StudioHeader.tsx +21 -2
- package/src/components/StudioLeftSidebar.tsx +2 -2
- package/src/components/nle/NLEContext.tsx +16 -7
- package/src/components/nle/TimelineResizeDivider.tsx +4 -11
- package/src/contexts/PanelLayoutContext.tsx +6 -3
- package/src/hooks/gsapEditOutcome.ts +19 -1
- package/src/hooks/gsapResizeGeometrySweep.test.ts +289 -0
- package/src/hooks/gsapResizeIntercept.test.ts +2 -2
- package/src/hooks/gsapResizeIntercept.ts +37 -14
- package/src/hooks/gsapResizeMixedTween.test.ts +168 -0
- package/src/hooks/gsapResizeSweep.test.ts +274 -0
- package/src/hooks/useGsapAwareEditing.test.tsx +19 -2
- package/src/hooks/useGsapAwareEditing.ts +13 -5
- package/src/hooks/usePanelLayout.test.ts +117 -0
- package/src/hooks/usePanelLayout.ts +121 -39
- package/src/utils/fitPanels.test.ts +164 -0
- package/src/utils/fitPanels.ts +151 -0
package/dist/index.js
CHANGED
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
import { useCallback as useCallback50 } from "react";
|
|
33
33
|
|
|
34
34
|
// src/components/nle/PreviewPane.tsx
|
|
35
|
-
import { useCallback as
|
|
35
|
+
import { useCallback as useCallback34, useRef as useRef37, useSyncExternalStore as useSyncExternalStore3 } from "react";
|
|
36
36
|
|
|
37
37
|
// src/player/components/Player.tsx
|
|
38
38
|
import { forwardRef as forwardRef2, useEffect as useEffect3, useRef as useRef2, useState as useState2 } from "react";
|
|
@@ -21608,8 +21608,8 @@ import {
|
|
|
21608
21608
|
createContext as createContext5,
|
|
21609
21609
|
useContext as useContext5,
|
|
21610
21610
|
useState as useState23,
|
|
21611
|
-
useCallback as
|
|
21612
|
-
useRef as
|
|
21611
|
+
useCallback as useCallback32,
|
|
21612
|
+
useRef as useRef36,
|
|
21613
21613
|
useEffect as useEffect26
|
|
21614
21614
|
} from "react";
|
|
21615
21615
|
|
|
@@ -21710,94 +21710,57 @@ function useCompositionStack({
|
|
|
21710
21710
|
};
|
|
21711
21711
|
}
|
|
21712
21712
|
|
|
21713
|
-
// src/
|
|
21714
|
-
|
|
21715
|
-
|
|
21713
|
+
// src/utils/fitPanels.ts
|
|
21714
|
+
var MIN_PREVIEW_W = 360;
|
|
21715
|
+
var MIN_PREVIEW_H = 200;
|
|
21716
|
+
var MIN_LEFT = 200;
|
|
21717
|
+
var MIN_RIGHT = 280;
|
|
21718
|
+
var RAIL_W = 42;
|
|
21716
21719
|
var MIN_TIMELINE_H = 100;
|
|
21717
|
-
var
|
|
21718
|
-
|
|
21719
|
-
|
|
21720
|
-
|
|
21721
|
-
|
|
21722
|
-
|
|
21723
|
-
|
|
21724
|
-
|
|
21725
|
-
|
|
21726
|
-
|
|
21727
|
-
|
|
21728
|
-
|
|
21729
|
-
(
|
|
21730
|
-
|
|
21731
|
-
|
|
21732
|
-
|
|
21733
|
-
|
|
21734
|
-
|
|
21735
|
-
|
|
21736
|
-
|
|
21737
|
-
|
|
21738
|
-
|
|
21739
|
-
|
|
21740
|
-
|
|
21741
|
-
|
|
21742
|
-
|
|
21743
|
-
|
|
21744
|
-
|
|
21745
|
-
|
|
21746
|
-
|
|
21747
|
-
|
|
21748
|
-
|
|
21749
|
-
|
|
21750
|
-
|
|
21751
|
-
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21755
|
-
|
|
21756
|
-
|
|
21757
|
-
|
|
21758
|
-
|
|
21759
|
-
|
|
21760
|
-
|
|
21761
|
-
const containerH = containerRef.current?.getBoundingClientRect().height ?? Infinity;
|
|
21762
|
-
const delta = e.key === "ArrowUp" ? 16 : -16;
|
|
21763
|
-
setTimelineH((prev) => {
|
|
21764
|
-
const next = Math.max(MIN_TIMELINE_H, Math.min(containerH - MIN_PREVIEW_H, prev + delta));
|
|
21765
|
-
persistTimelineH(next);
|
|
21766
|
-
return next;
|
|
21767
|
-
});
|
|
21768
|
-
},
|
|
21769
|
-
[disabled, containerRef, setTimelineH, persistTimelineH]
|
|
21770
|
-
);
|
|
21771
|
-
return (
|
|
21772
|
-
// Horizontal resize divider: 3px visible seam (h-[3px]), 10px pointer-capture
|
|
21773
|
-
// zone via the absolutely-positioned inner hit area so the layout gap stays
|
|
21774
|
-
// at 3px while draggability is preserved over the full band.
|
|
21775
|
-
/* @__PURE__ */ jsxs37(
|
|
21776
|
-
"div",
|
|
21777
|
-
{
|
|
21778
|
-
role: "separator",
|
|
21779
|
-
"aria-orientation": "horizontal",
|
|
21780
|
-
"aria-label": "Resize timeline (arrow keys)",
|
|
21781
|
-
"aria-valuenow": Math.round(timelineH),
|
|
21782
|
-
"aria-valuemin": MIN_TIMELINE_H,
|
|
21783
|
-
"aria-valuemax": Math.round(
|
|
21784
|
-
(containerRef.current?.getBoundingClientRect().height ?? 600) - MIN_PREVIEW_H
|
|
21785
|
-
),
|
|
21786
|
-
tabIndex: 0,
|
|
21787
|
-
className: "group relative h-[3px] flex-shrink-0 cursor-row-resize z-10 outline-none focus-visible:bg-studio-accent/20",
|
|
21788
|
-
style: { touchAction: "none" },
|
|
21789
|
-
onPointerDown: handlePointerDown,
|
|
21790
|
-
onPointerMove: handlePointerMove,
|
|
21791
|
-
onPointerUp: handlePointerUp,
|
|
21792
|
-
onPointerCancel: handlePointerUp,
|
|
21793
|
-
onKeyDown: handleKeyDown,
|
|
21794
|
-
children: [
|
|
21795
|
-
/* @__PURE__ */ jsx49("div", { className: "absolute inset-x-0 -top-[4px] h-[10px]" }),
|
|
21796
|
-
/* @__PURE__ */ jsx49("div", { className: "h-[3px] w-full bg-transparent transition-colors group-hover:bg-white/12 group-active:bg-white/18 group-focus-visible:bg-studio-accent/60" })
|
|
21797
|
-
]
|
|
21798
|
-
}
|
|
21799
|
-
)
|
|
21800
|
-
);
|
|
21720
|
+
var PANEL_SEAM_W = 6;
|
|
21721
|
+
var PANEL_MAX_RATIO = 0.4;
|
|
21722
|
+
var RAIL_LEFT_BELOW = 860;
|
|
21723
|
+
var RAIL_RIGHT_BELOW = 700;
|
|
21724
|
+
function railsEngaged(viewportWidth) {
|
|
21725
|
+
return viewportWidth < RAIL_LEFT_BELOW;
|
|
21726
|
+
}
|
|
21727
|
+
function clamp5(value, min, max) {
|
|
21728
|
+
return Math.max(min, Math.min(max, value));
|
|
21729
|
+
}
|
|
21730
|
+
function defaultPanelWidths(viewportWidth) {
|
|
21731
|
+
return {
|
|
21732
|
+
left: Math.max(MIN_LEFT, Math.min(384, Math.round(viewportWidth * 0.257))),
|
|
21733
|
+
right: Math.max(MIN_RIGHT, Math.min(424, Math.round(viewportWidth * 0.284)))
|
|
21734
|
+
};
|
|
21735
|
+
}
|
|
21736
|
+
function fitPanelWidths(viewportWidth, preferred, reopened = { left: false, right: false }) {
|
|
21737
|
+
const vw = Number.isFinite(viewportWidth) ? Math.max(0, viewportWidth) : 0;
|
|
21738
|
+
if (vw <= 0) {
|
|
21739
|
+
return { ...preferred, preview: 0, autoCollapseLeft: false, autoCollapseRight: false };
|
|
21740
|
+
}
|
|
21741
|
+
const autoCollapseLeft = vw < RAIL_LEFT_BELOW && !reopened.left;
|
|
21742
|
+
const autoCollapseRight = vw < RAIL_RIGHT_BELOW && !reopened.right;
|
|
21743
|
+
const cap = Math.floor(vw * PANEL_MAX_RATIO);
|
|
21744
|
+
const leftFloor = autoCollapseLeft ? RAIL_W : MIN_LEFT;
|
|
21745
|
+
const rightFloor = autoCollapseRight ? 0 : MIN_RIGHT;
|
|
21746
|
+
let left = autoCollapseLeft ? RAIL_W : clamp5(preferred.left, MIN_LEFT, Math.max(MIN_LEFT, cap));
|
|
21747
|
+
let right = autoCollapseRight ? 0 : clamp5(preferred.right, MIN_RIGHT, Math.max(MIN_RIGHT, cap));
|
|
21748
|
+
const budget = vw - MIN_PREVIEW_W - PANEL_SEAM_W;
|
|
21749
|
+
if (left + right > budget) right = Math.max(rightFloor, budget - left);
|
|
21750
|
+
if (left + right > budget) left = Math.max(leftFloor, budget - right);
|
|
21751
|
+
return {
|
|
21752
|
+
left,
|
|
21753
|
+
right,
|
|
21754
|
+
preview: Math.max(0, vw - left - right - PANEL_SEAM_W),
|
|
21755
|
+
autoCollapseLeft,
|
|
21756
|
+
autoCollapseRight
|
|
21757
|
+
};
|
|
21758
|
+
}
|
|
21759
|
+
function fitTimelineHeight(containerHeight, preferred) {
|
|
21760
|
+
const h = Number.isFinite(containerHeight) ? containerHeight : 0;
|
|
21761
|
+
const wanted = Number.isFinite(preferred) ? preferred : MIN_TIMELINE_H;
|
|
21762
|
+
if (h <= 0) return Math.max(MIN_TIMELINE_H, wanted);
|
|
21763
|
+
return clamp5(wanted, MIN_TIMELINE_H, Math.max(MIN_TIMELINE_H, h - MIN_PREVIEW_H));
|
|
21801
21764
|
}
|
|
21802
21765
|
|
|
21803
21766
|
// src/utils/assetPreviewStore.ts
|
|
@@ -21810,7 +21773,7 @@ var useAssetPreviewStore = create4((set) => ({
|
|
|
21810
21773
|
}));
|
|
21811
21774
|
|
|
21812
21775
|
// src/components/nle/NLEContext.tsx
|
|
21813
|
-
import { jsx as
|
|
21776
|
+
import { jsx as jsx49 } from "react/jsx-runtime";
|
|
21814
21777
|
var DEFAULT_TIMELINE_H = 360;
|
|
21815
21778
|
function shouldDisableTimelineWhileCompositionLoading(compositionLoading) {
|
|
21816
21779
|
return compositionLoading;
|
|
@@ -21843,13 +21806,13 @@ function NLEProvider({
|
|
|
21843
21806
|
useAssetPreviewStore.getState().clearPreviewAsset();
|
|
21844
21807
|
}, [projectId]);
|
|
21845
21808
|
const [previewCompositionSize, setPreviewCompositionSize] = useState23(null);
|
|
21846
|
-
const prevRefreshKeyRef =
|
|
21809
|
+
const prevRefreshKeyRef = useRef36(refreshKey);
|
|
21847
21810
|
useEffect26(() => {
|
|
21848
21811
|
if (refreshKey === prevRefreshKeyRef.current) return;
|
|
21849
21812
|
prevRefreshKeyRef.current = refreshKey;
|
|
21850
21813
|
refreshPlayer();
|
|
21851
21814
|
}, [refreshKey, refreshPlayer]);
|
|
21852
|
-
const onIframeLoad =
|
|
21815
|
+
const onIframeLoad = useCallback32(() => {
|
|
21853
21816
|
baseOnIframeLoad();
|
|
21854
21817
|
ensureMotionPathPluginLoaded(iframeRef.current);
|
|
21855
21818
|
onIframeRef?.(iframeRef.current);
|
|
@@ -21867,7 +21830,7 @@ function NLEProvider({
|
|
|
21867
21830
|
onCompositionChange
|
|
21868
21831
|
});
|
|
21869
21832
|
const iframeRef_ = iframeRef;
|
|
21870
|
-
const handleDrillDown =
|
|
21833
|
+
const handleDrillDown = useCallback32(
|
|
21871
21834
|
(element) => {
|
|
21872
21835
|
if (!element.compositionSrc) return;
|
|
21873
21836
|
usePlayerStore.getState().setSelectedElementId(null);
|
|
@@ -21894,9 +21857,9 @@ function NLEProvider({
|
|
|
21894
21857
|
},
|
|
21895
21858
|
[compIdToSrc, drillDown, iframeRef_]
|
|
21896
21859
|
);
|
|
21897
|
-
const compIdToSrcRef =
|
|
21860
|
+
const compIdToSrcRef = useRef36(compIdToSrc);
|
|
21898
21861
|
compIdToSrcRef.current = compIdToSrc;
|
|
21899
|
-
const onCompIdToSrcChangeRef =
|
|
21862
|
+
const onCompIdToSrcChangeRef = useRef36(onCompIdToSrcChange);
|
|
21900
21863
|
onCompIdToSrcChangeRef.current = onCompIdToSrcChange;
|
|
21901
21864
|
useEffect26(() => {
|
|
21902
21865
|
const controller = new AbortController();
|
|
@@ -21967,19 +21930,26 @@ function NLEProvider({
|
|
|
21967
21930
|
const stored = readStudioUiPreferences().timelineHeight;
|
|
21968
21931
|
return stored !== void 0 && stored >= MIN_TIMELINE_H ? stored : DEFAULT_TIMELINE_H;
|
|
21969
21932
|
});
|
|
21970
|
-
const persistTimelineH =
|
|
21933
|
+
const persistTimelineH = useCallback32((height) => {
|
|
21971
21934
|
writeStudioUiPreferences({ timelineHeight: Math.round(height) });
|
|
21972
21935
|
}, []);
|
|
21973
|
-
const containerRef =
|
|
21936
|
+
const containerRef = useRef36(null);
|
|
21974
21937
|
useEffect26(() => {
|
|
21975
|
-
const
|
|
21976
|
-
if (!
|
|
21977
|
-
const
|
|
21978
|
-
|
|
21938
|
+
const element = containerRef.current;
|
|
21939
|
+
if (!element || typeof ResizeObserver === "undefined") return;
|
|
21940
|
+
const reconcile = () => {
|
|
21941
|
+
const containerH = element.getBoundingClientRect().height;
|
|
21942
|
+
if (!containerH) return;
|
|
21943
|
+
setTimelineH((prev) => fitTimelineHeight(containerH, prev));
|
|
21944
|
+
};
|
|
21945
|
+
reconcile();
|
|
21946
|
+
const observer = new ResizeObserver(reconcile);
|
|
21947
|
+
observer.observe(element);
|
|
21948
|
+
return () => observer.disconnect();
|
|
21979
21949
|
}, []);
|
|
21980
|
-
const hasLoadedOnceRef =
|
|
21950
|
+
const hasLoadedOnceRef = useRef36(false);
|
|
21981
21951
|
const [compositionLoading, setCompositionLoadingRaw] = useState23(true);
|
|
21982
|
-
const setCompositionLoading =
|
|
21952
|
+
const setCompositionLoading = useCallback32((loading) => {
|
|
21983
21953
|
if (!loading) hasLoadedOnceRef.current = true;
|
|
21984
21954
|
if (loading && hasLoadedOnceRef.current) return;
|
|
21985
21955
|
setCompositionLoadingRaw(loading);
|
|
@@ -21989,7 +21959,7 @@ function NLEProvider({
|
|
|
21989
21959
|
useEffect26(() => {
|
|
21990
21960
|
onCompositionLoadingChange?.(compositionLoading);
|
|
21991
21961
|
}, [compositionLoading, onCompositionLoadingChange]);
|
|
21992
|
-
const onIframeRefStable =
|
|
21962
|
+
const onIframeRefStable = useRef36(onIframeRef);
|
|
21993
21963
|
onIframeRefStable.current = onIframeRef;
|
|
21994
21964
|
useEffect26(() => {
|
|
21995
21965
|
onIframeRefStable.current?.(iframeRef.current);
|
|
@@ -22018,11 +21988,11 @@ function NLEProvider({
|
|
|
22018
21988
|
previewCompositionSize,
|
|
22019
21989
|
setPreviewCompositionSize
|
|
22020
21990
|
};
|
|
22021
|
-
return /* @__PURE__ */
|
|
21991
|
+
return /* @__PURE__ */ jsx49(NLEContext.Provider, { value, children });
|
|
22022
21992
|
}
|
|
22023
21993
|
|
|
22024
21994
|
// src/components/nle/AssetPreviewOverlay.tsx
|
|
22025
|
-
import { useEffect as useEffect27, useCallback as
|
|
21995
|
+
import { useEffect as useEffect27, useCallback as useCallback33 } from "react";
|
|
22026
21996
|
|
|
22027
21997
|
// src/utils/assetPreviewDismiss.ts
|
|
22028
21998
|
var TIME_EPSILON_S = 1e-6;
|
|
@@ -22033,7 +22003,7 @@ function shouldDismissAssetPreview(openedTime, snapshot) {
|
|
|
22033
22003
|
}
|
|
22034
22004
|
|
|
22035
22005
|
// src/components/nle/AssetPreviewOverlay.tsx
|
|
22036
|
-
import { jsx as
|
|
22006
|
+
import { jsx as jsx50, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
22037
22007
|
function basename(path) {
|
|
22038
22008
|
return path.split("/").pop() ?? path;
|
|
22039
22009
|
}
|
|
@@ -22048,10 +22018,10 @@ function AssetPreviewMedia({
|
|
|
22048
22018
|
name
|
|
22049
22019
|
}) {
|
|
22050
22020
|
if (kind === "image") {
|
|
22051
|
-
return /* @__PURE__ */
|
|
22021
|
+
return /* @__PURE__ */ jsx50("img", { src: serveUrl, alt: name, className: "max-w-full max-h-[40vh] rounded object-contain" });
|
|
22052
22022
|
}
|
|
22053
22023
|
if (kind === "video") {
|
|
22054
|
-
return /* @__PURE__ */
|
|
22024
|
+
return /* @__PURE__ */ jsx50(
|
|
22055
22025
|
"video",
|
|
22056
22026
|
{
|
|
22057
22027
|
src: serveUrl,
|
|
@@ -22063,8 +22033,8 @@ function AssetPreviewMedia({
|
|
|
22063
22033
|
}
|
|
22064
22034
|
);
|
|
22065
22035
|
}
|
|
22066
|
-
return /* @__PURE__ */
|
|
22067
|
-
/* @__PURE__ */
|
|
22036
|
+
return /* @__PURE__ */ jsxs37("div", { className: "flex flex-col items-center gap-3 px-6 py-4", children: [
|
|
22037
|
+
/* @__PURE__ */ jsxs37(
|
|
22068
22038
|
"svg",
|
|
22069
22039
|
{
|
|
22070
22040
|
width: "40",
|
|
@@ -22075,20 +22045,20 @@ function AssetPreviewMedia({
|
|
|
22075
22045
|
strokeWidth: "1.5",
|
|
22076
22046
|
className: "text-neutral-500",
|
|
22077
22047
|
children: [
|
|
22078
|
-
/* @__PURE__ */
|
|
22079
|
-
/* @__PURE__ */
|
|
22080
|
-
/* @__PURE__ */
|
|
22048
|
+
/* @__PURE__ */ jsx50("path", { d: "M9 18V5l12-2v13", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
22049
|
+
/* @__PURE__ */ jsx50("circle", { cx: "6", cy: "18", r: "3" }),
|
|
22050
|
+
/* @__PURE__ */ jsx50("circle", { cx: "18", cy: "16", r: "3" })
|
|
22081
22051
|
]
|
|
22082
22052
|
}
|
|
22083
22053
|
),
|
|
22084
|
-
/* @__PURE__ */
|
|
22054
|
+
/* @__PURE__ */ jsx50("audio", { src: serveUrl, controls: true, className: "w-64" })
|
|
22085
22055
|
] });
|
|
22086
22056
|
}
|
|
22087
22057
|
function AssetPreviewOverlay() {
|
|
22088
22058
|
const previewAsset = useAssetPreviewStore((s) => s.previewAsset);
|
|
22089
22059
|
const previewProjectId = useAssetPreviewStore((s) => s.previewProjectId);
|
|
22090
22060
|
const clearPreviewAsset = useAssetPreviewStore((s) => s.clearPreviewAsset);
|
|
22091
|
-
const handleKeyDown =
|
|
22061
|
+
const handleKeyDown = useCallback33(
|
|
22092
22062
|
(e) => {
|
|
22093
22063
|
if (e.key === "Escape") clearPreviewAsset();
|
|
22094
22064
|
},
|
|
@@ -22114,20 +22084,20 @@ function AssetPreviewOverlay() {
|
|
|
22114
22084
|
if (!previewAsset || !previewProjectId) return null;
|
|
22115
22085
|
const serveUrl = resolveMediaPreviewUrl(previewAsset, previewProjectId);
|
|
22116
22086
|
const name = basename(previewAsset);
|
|
22117
|
-
return /* @__PURE__ */
|
|
22087
|
+
return /* @__PURE__ */ jsx50(
|
|
22118
22088
|
"div",
|
|
22119
22089
|
{
|
|
22120
22090
|
className: "absolute inset-0 z-50 flex flex-col items-center justify-center bg-black/20",
|
|
22121
22091
|
onClick: clearPreviewAsset,
|
|
22122
22092
|
role: "dialog",
|
|
22123
22093
|
"aria-label": `Preview: ${name}`,
|
|
22124
|
-
children: /* @__PURE__ */
|
|
22094
|
+
children: /* @__PURE__ */ jsxs37(
|
|
22125
22095
|
"div",
|
|
22126
22096
|
{
|
|
22127
22097
|
className: "relative flex flex-col items-center gap-2 max-w-[58%] rounded-lg border border-neutral-800 bg-neutral-950/95 p-2 pt-8 shadow-2xl",
|
|
22128
22098
|
onClick: (e) => e.stopPropagation(),
|
|
22129
22099
|
children: [
|
|
22130
|
-
/* @__PURE__ */
|
|
22100
|
+
/* @__PURE__ */ jsx50(
|
|
22131
22101
|
"button",
|
|
22132
22102
|
{
|
|
22133
22103
|
className: "absolute top-2 right-2 w-6 h-6 rounded-full bg-neutral-800 hover:bg-neutral-700 text-neutral-300 hover:text-white flex items-center justify-center transition-colors z-10",
|
|
@@ -22136,7 +22106,7 @@ function AssetPreviewOverlay() {
|
|
|
22136
22106
|
clearPreviewAsset();
|
|
22137
22107
|
},
|
|
22138
22108
|
"aria-label": "Close preview",
|
|
22139
|
-
children: /* @__PURE__ */
|
|
22109
|
+
children: /* @__PURE__ */ jsxs37(
|
|
22140
22110
|
"svg",
|
|
22141
22111
|
{
|
|
22142
22112
|
width: "12",
|
|
@@ -22147,15 +22117,15 @@ function AssetPreviewOverlay() {
|
|
|
22147
22117
|
fill: "none",
|
|
22148
22118
|
strokeLinecap: "round",
|
|
22149
22119
|
children: [
|
|
22150
|
-
/* @__PURE__ */
|
|
22151
|
-
/* @__PURE__ */
|
|
22120
|
+
/* @__PURE__ */ jsx50("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
22121
|
+
/* @__PURE__ */ jsx50("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
22152
22122
|
]
|
|
22153
22123
|
}
|
|
22154
22124
|
)
|
|
22155
22125
|
}
|
|
22156
22126
|
),
|
|
22157
|
-
/* @__PURE__ */
|
|
22158
|
-
/* @__PURE__ */
|
|
22127
|
+
/* @__PURE__ */ jsx50(AssetPreviewMedia, { kind: resolveAssetKind(previewAsset), serveUrl, name }),
|
|
22128
|
+
/* @__PURE__ */ jsx50("span", { className: "text-[12px] text-neutral-400 truncate max-w-full px-2 text-center", children: name })
|
|
22159
22129
|
]
|
|
22160
22130
|
}
|
|
22161
22131
|
)
|
|
@@ -22164,7 +22134,7 @@ function AssetPreviewOverlay() {
|
|
|
22164
22134
|
}
|
|
22165
22135
|
|
|
22166
22136
|
// src/components/nle/PreviewPane.tsx
|
|
22167
|
-
import { jsx as
|
|
22137
|
+
import { jsx as jsx51, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
22168
22138
|
function subscribeFullscreen(cb) {
|
|
22169
22139
|
document.addEventListener("fullscreenchange", cb);
|
|
22170
22140
|
return () => document.removeEventListener("fullscreenchange", cb);
|
|
@@ -22199,8 +22169,8 @@ function PreviewPane({
|
|
|
22199
22169
|
previewCompositionSize,
|
|
22200
22170
|
setPreviewCompositionSize
|
|
22201
22171
|
} = useNLEContext();
|
|
22202
|
-
const stageRefForDrop =
|
|
22203
|
-
const handleStageRef =
|
|
22172
|
+
const stageRefForDrop = useRef37(null);
|
|
22173
|
+
const handleStageRef = useCallback34((ref) => {
|
|
22204
22174
|
stageRefForDrop.current = ref.current;
|
|
22205
22175
|
}, []);
|
|
22206
22176
|
const {
|
|
@@ -22215,10 +22185,10 @@ function PreviewPane({
|
|
|
22215
22185
|
stageRef: stageRefForDrop,
|
|
22216
22186
|
onBlockDrop: onPreviewBlockDrop
|
|
22217
22187
|
});
|
|
22218
|
-
const containerRef =
|
|
22188
|
+
const containerRef = useRef37(null);
|
|
22219
22189
|
const fullscreenElement = useSyncExternalStore3(subscribeFullscreen, getFullscreenElement);
|
|
22220
22190
|
const isFullscreen = fullscreenElement === containerRef.current && fullscreenElement != null;
|
|
22221
|
-
const toggleFullscreen =
|
|
22191
|
+
const toggleFullscreen = useCallback34(() => {
|
|
22222
22192
|
if (!containerRef.current) return;
|
|
22223
22193
|
if (document.fullscreenElement) {
|
|
22224
22194
|
void document.exitFullscreen();
|
|
@@ -22228,14 +22198,14 @@ function PreviewPane({
|
|
|
22228
22198
|
}, []);
|
|
22229
22199
|
const currentLevel = compositionStack[compositionStack.length - 1];
|
|
22230
22200
|
const directUrl = compositionStack.length > 1 ? currentLevel.previewUrl : void 0;
|
|
22231
|
-
return /* @__PURE__ */
|
|
22201
|
+
return /* @__PURE__ */ jsxs38(
|
|
22232
22202
|
"div",
|
|
22233
22203
|
{
|
|
22234
22204
|
ref: containerRef,
|
|
22235
22205
|
className: `flex-1 min-h-0 flex flex-col overflow-hidden bg-neutral-950 ${isFullscreen ? "" : "rounded-lg border border-neutral-800/50"}`,
|
|
22236
22206
|
"data-studio-fullscreen-target": "",
|
|
22237
22207
|
children: [
|
|
22238
|
-
/* @__PURE__ */
|
|
22208
|
+
/* @__PURE__ */ jsxs38(
|
|
22239
22209
|
"div",
|
|
22240
22210
|
{
|
|
22241
22211
|
className: "flex-1 min-h-0 relative overflow-hidden",
|
|
@@ -22246,8 +22216,8 @@ function PreviewPane({
|
|
|
22246
22216
|
onDragLeave: handlePreviewDragLeave,
|
|
22247
22217
|
onDrop: handlePreviewDrop,
|
|
22248
22218
|
children: [
|
|
22249
|
-
/* @__PURE__ */
|
|
22250
|
-
/* @__PURE__ */
|
|
22219
|
+
/* @__PURE__ */ jsxs38("div", { className: "absolute inset-0 overflow-hidden", children: [
|
|
22220
|
+
/* @__PURE__ */ jsx51(
|
|
22251
22221
|
NLEPreview,
|
|
22252
22222
|
{
|
|
22253
22223
|
projectId,
|
|
@@ -22261,16 +22231,16 @@ function PreviewPane({
|
|
|
22261
22231
|
onCompositionSizeChange: setPreviewCompositionSize
|
|
22262
22232
|
}
|
|
22263
22233
|
),
|
|
22264
|
-
previewDragOver && /* @__PURE__ */
|
|
22265
|
-
/* @__PURE__ */
|
|
22234
|
+
previewDragOver && /* @__PURE__ */ jsx51("div", { className: "absolute inset-2 z-40 rounded-lg border-2 border-dashed border-studio-accent/50 bg-studio-accent/[0.04] pointer-events-none" }),
|
|
22235
|
+
/* @__PURE__ */ jsx51(AssetPreviewOverlay, {})
|
|
22266
22236
|
] }),
|
|
22267
22237
|
!isFullscreen && previewOverlay
|
|
22268
22238
|
]
|
|
22269
22239
|
}
|
|
22270
22240
|
),
|
|
22271
|
-
/* @__PURE__ */
|
|
22272
|
-
!isFullscreen && compositionStack.length > 1 && /* @__PURE__ */
|
|
22273
|
-
/* @__PURE__ */
|
|
22241
|
+
/* @__PURE__ */ jsxs38("div", { className: "flex-shrink-0", children: [
|
|
22242
|
+
!isFullscreen && compositionStack.length > 1 && /* @__PURE__ */ jsx51(CompositionBreadcrumb, { stack: compositionStack, onNavigate: handleNavigateComposition }),
|
|
22243
|
+
/* @__PURE__ */ jsx51(
|
|
22274
22244
|
PlayerControls,
|
|
22275
22245
|
{
|
|
22276
22246
|
onTogglePlay: togglePlay,
|
|
@@ -22288,6 +22258,91 @@ function PreviewPane({
|
|
|
22288
22258
|
|
|
22289
22259
|
// src/components/nle/TimelinePane.tsx
|
|
22290
22260
|
import { useCallback as useCallback36 } from "react";
|
|
22261
|
+
|
|
22262
|
+
// src/components/nle/TimelineResizeDivider.tsx
|
|
22263
|
+
import { useCallback as useCallback35, useRef as useRef38 } from "react";
|
|
22264
|
+
import { jsx as jsx52, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
22265
|
+
function TimelineResizeDivider({
|
|
22266
|
+
timelineH,
|
|
22267
|
+
setTimelineH,
|
|
22268
|
+
persistTimelineH,
|
|
22269
|
+
containerRef,
|
|
22270
|
+
disabled
|
|
22271
|
+
}) {
|
|
22272
|
+
const isDragging = useRef38(false);
|
|
22273
|
+
const timelineHRef = useRef38(timelineH);
|
|
22274
|
+
timelineHRef.current = timelineH;
|
|
22275
|
+
const handlePointerDown = useCallback35(
|
|
22276
|
+
(e) => {
|
|
22277
|
+
if (disabled) return;
|
|
22278
|
+
e.preventDefault();
|
|
22279
|
+
isDragging.current = true;
|
|
22280
|
+
e.target.setPointerCapture(e.pointerId);
|
|
22281
|
+
},
|
|
22282
|
+
[disabled]
|
|
22283
|
+
);
|
|
22284
|
+
const handlePointerMove = useCallback35(
|
|
22285
|
+
(e) => {
|
|
22286
|
+
if (disabled) return;
|
|
22287
|
+
if (!isDragging.current || !containerRef.current) return;
|
|
22288
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
22289
|
+
const mouseY = e.clientY - rect.top;
|
|
22290
|
+
setTimelineH(fitTimelineHeight(rect.height, rect.height - mouseY));
|
|
22291
|
+
},
|
|
22292
|
+
[disabled, containerRef, setTimelineH]
|
|
22293
|
+
);
|
|
22294
|
+
const handlePointerUp = useCallback35(() => {
|
|
22295
|
+
if (isDragging.current) persistTimelineH(timelineHRef.current);
|
|
22296
|
+
isDragging.current = false;
|
|
22297
|
+
}, [persistTimelineH]);
|
|
22298
|
+
const handleKeyDown = useCallback35(
|
|
22299
|
+
(e) => {
|
|
22300
|
+
if (disabled) return;
|
|
22301
|
+
if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
|
|
22302
|
+
e.preventDefault();
|
|
22303
|
+
const containerH = containerRef.current?.getBoundingClientRect().height ?? 0;
|
|
22304
|
+
const delta = e.key === "ArrowUp" ? 16 : -16;
|
|
22305
|
+
setTimelineH((prev) => {
|
|
22306
|
+
const next = fitTimelineHeight(containerH, prev + delta);
|
|
22307
|
+
persistTimelineH(next);
|
|
22308
|
+
return next;
|
|
22309
|
+
});
|
|
22310
|
+
},
|
|
22311
|
+
[disabled, containerRef, setTimelineH, persistTimelineH]
|
|
22312
|
+
);
|
|
22313
|
+
return (
|
|
22314
|
+
// Horizontal resize divider: 3px visible seam (h-[3px]), 10px pointer-capture
|
|
22315
|
+
// zone via the absolutely-positioned inner hit area so the layout gap stays
|
|
22316
|
+
// at 3px while draggability is preserved over the full band.
|
|
22317
|
+
/* @__PURE__ */ jsxs39(
|
|
22318
|
+
"div",
|
|
22319
|
+
{
|
|
22320
|
+
role: "separator",
|
|
22321
|
+
"aria-orientation": "horizontal",
|
|
22322
|
+
"aria-label": "Resize timeline (arrow keys)",
|
|
22323
|
+
"aria-valuenow": Math.round(timelineH),
|
|
22324
|
+
"aria-valuemin": MIN_TIMELINE_H,
|
|
22325
|
+
"aria-valuemax": Math.round(
|
|
22326
|
+
(containerRef.current?.getBoundingClientRect().height ?? 600) - MIN_PREVIEW_H
|
|
22327
|
+
),
|
|
22328
|
+
tabIndex: 0,
|
|
22329
|
+
className: "group relative h-[3px] flex-shrink-0 cursor-row-resize z-10 outline-none focus-visible:bg-studio-accent/20",
|
|
22330
|
+
style: { touchAction: "none" },
|
|
22331
|
+
onPointerDown: handlePointerDown,
|
|
22332
|
+
onPointerMove: handlePointerMove,
|
|
22333
|
+
onPointerUp: handlePointerUp,
|
|
22334
|
+
onPointerCancel: handlePointerUp,
|
|
22335
|
+
onKeyDown: handleKeyDown,
|
|
22336
|
+
children: [
|
|
22337
|
+
/* @__PURE__ */ jsx52("div", { className: "absolute inset-x-0 -top-[4px] h-[10px]" }),
|
|
22338
|
+
/* @__PURE__ */ jsx52("div", { className: "h-[3px] w-full bg-transparent transition-colors group-hover:bg-white/12 group-active:bg-white/18 group-focus-visible:bg-studio-accent/60" })
|
|
22339
|
+
]
|
|
22340
|
+
}
|
|
22341
|
+
)
|
|
22342
|
+
);
|
|
22343
|
+
}
|
|
22344
|
+
|
|
22345
|
+
// src/components/nle/TimelinePane.tsx
|
|
22291
22346
|
import { Fragment as Fragment15, jsx as jsx53, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
22292
22347
|
function forwardRebasedTimelineMoveElements(edits, coalesceKey, operation, onMoveElements, coalesceMs) {
|
|
22293
22348
|
return onMoveElements(
|
|
@@ -33554,7 +33609,7 @@ var NOOP_EPSILON_PCT2 = 0.1;
|
|
|
33554
33609
|
var EPSILON_TIME = 1e-4;
|
|
33555
33610
|
var MIN_TWEEN_DURATION = 0.01;
|
|
33556
33611
|
var round33 = (n) => Math.round(n * 1e3) / 1e3;
|
|
33557
|
-
var
|
|
33612
|
+
var clamp6 = (n, lo, hi) => Math.max(lo, Math.min(hi, n));
|
|
33558
33613
|
function resolveFlatTweenBoundaryRetime(opts) {
|
|
33559
33614
|
const { keyframeCount, draggedTweenPct, tweenStart, tweenEnd, dropAbsTime } = opts;
|
|
33560
33615
|
if (keyframeCount > 0) return null;
|
|
@@ -33585,7 +33640,7 @@ function resolveKeyframeRetime(opts) {
|
|
|
33585
33640
|
});
|
|
33586
33641
|
if (flatBoundary) return flatBoundary;
|
|
33587
33642
|
if (dropAbsTime >= tweenStart - EPSILON_TIME && dropAbsTime <= tweenEnd + EPSILON_TIME) {
|
|
33588
|
-
const toTweenPct = round33(
|
|
33643
|
+
const toTweenPct = round33(clamp6((dropAbsTime - tweenStart) / tweenDuration * 100, 0, 100));
|
|
33589
33644
|
if (Math.abs(toTweenPct - draggedTweenPct) < NOOP_EPSILON_PCT2) return { kind: "noop" };
|
|
33590
33645
|
return { kind: "move", toTweenPct };
|
|
33591
33646
|
}
|
|
@@ -39622,7 +39677,7 @@ function hasCssWord(value, word) {
|
|
|
39622
39677
|
function parsePercentToken(value, fallback) {
|
|
39623
39678
|
if (!value?.endsWith("%")) return fallback;
|
|
39624
39679
|
const parsed = parseCssNumber(value.slice(0, -1));
|
|
39625
|
-
return parsed == null ? fallback :
|
|
39680
|
+
return parsed == null ? fallback : clamp7(parsed, 0, 100);
|
|
39626
39681
|
}
|
|
39627
39682
|
function parseAngleToken(value) {
|
|
39628
39683
|
const trimmed = value?.trim().toLowerCase();
|
|
@@ -39644,13 +39699,13 @@ function trailingPercentStart(value) {
|
|
|
39644
39699
|
if (start === 0 || !isWhitespace(withoutUnit[start - 1])) return null;
|
|
39645
39700
|
return start;
|
|
39646
39701
|
}
|
|
39647
|
-
function
|
|
39702
|
+
function clamp7(value, min, max) {
|
|
39648
39703
|
return Math.min(max, Math.max(min, value));
|
|
39649
39704
|
}
|
|
39650
39705
|
var round = roundToCenti;
|
|
39651
39706
|
function parsePercent(value, fallback) {
|
|
39652
39707
|
const parsed = parseCssNumber(value);
|
|
39653
|
-
return parsed == null ? fallback :
|
|
39708
|
+
return parsed == null ? fallback : clamp7(parsed, 0, 100);
|
|
39654
39709
|
}
|
|
39655
39710
|
function parseColorStop(raw) {
|
|
39656
39711
|
const trimmed = raw.trim();
|
|
@@ -39681,7 +39736,7 @@ function normalizeStops(stops) {
|
|
|
39681
39736
|
}));
|
|
39682
39737
|
return result.map((stop) => ({
|
|
39683
39738
|
color: stop.color,
|
|
39684
|
-
position: round(
|
|
39739
|
+
position: round(clamp7(stop.position, 0, 100))
|
|
39685
39740
|
}));
|
|
39686
39741
|
}
|
|
39687
39742
|
function splitGradientArgs(value) {
|
|
@@ -39844,7 +39899,7 @@ function formatHex(channel) {
|
|
|
39844
39899
|
return channel.toString(16).padStart(2, "0");
|
|
39845
39900
|
}
|
|
39846
39901
|
function interpolateGradientStopColor(model, position) {
|
|
39847
|
-
const clampedPosition =
|
|
39902
|
+
const clampedPosition = clamp7(position, 0, 100);
|
|
39848
39903
|
const sortedStops = [...model.stops].sort((a, b) => a.position - b.position);
|
|
39849
39904
|
const exact = sortedStops.find((stop) => Math.abs(stop.position - clampedPosition) < 1e-3);
|
|
39850
39905
|
if (exact) return exact.color;
|
|
@@ -39868,7 +39923,7 @@ function interpolateGradientStopColor(model, position) {
|
|
|
39868
39923
|
return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
|
|
39869
39924
|
}
|
|
39870
39925
|
function insertGradientStop(model, position) {
|
|
39871
|
-
const clampedPosition = round(
|
|
39926
|
+
const clampedPosition = round(clamp7(position, 0, 100));
|
|
39872
39927
|
const color = interpolateGradientStopColor(model, clampedPosition);
|
|
39873
39928
|
const nextStops = [...model.stops, { color, position: clampedPosition }].sort(
|
|
39874
39929
|
(a, b) => a.position - b.position
|
|
@@ -50734,7 +50789,7 @@ var FileTree = memo33(function FileTree2({
|
|
|
50734
50789
|
});
|
|
50735
50790
|
|
|
50736
50791
|
// src/App.tsx
|
|
50737
|
-
import { useState as useState133, useCallback as useCallback152, useRef as useRef142, useMemo as useMemo66, useEffect as
|
|
50792
|
+
import { useState as useState133, useCallback as useCallback152, useRef as useRef142, useMemo as useMemo66, useEffect as useEffect122, useLayoutEffect as useLayoutEffect9 } from "react";
|
|
50738
50793
|
|
|
50739
50794
|
// src/components/renders/useRenderQueue.ts
|
|
50740
50795
|
import { useState as useState77, useEffect as useEffect71, useCallback as useCallback65, useRef as useRef83, useMemo as useMemo46 } from "react";
|
|
@@ -52315,33 +52370,26 @@ function usePersistentEditHistory(options) {
|
|
|
52315
52370
|
}
|
|
52316
52371
|
|
|
52317
52372
|
// src/hooks/usePanelLayout.ts
|
|
52318
|
-
import { useState as useState82, useCallback as useCallback69, useRef as useRef90 } from "react";
|
|
52373
|
+
import { useState as useState82, useCallback as useCallback69, useRef as useRef90, useEffect as useEffect74 } from "react";
|
|
52374
|
+
var NO_OVERRIDE = { left: false, right: false };
|
|
52319
52375
|
function getInitialRightInspectorPanes(tab) {
|
|
52320
52376
|
if (tab === "layers") return { layers: true, design: false };
|
|
52321
52377
|
return { layers: false, design: true };
|
|
52322
52378
|
}
|
|
52323
|
-
function
|
|
52324
|
-
|
|
52379
|
+
function readViewportWidth() {
|
|
52380
|
+
return typeof window === "undefined" ? 1496 : window.innerWidth;
|
|
52381
|
+
}
|
|
52382
|
+
function getPreferredPanelWidths() {
|
|
52325
52383
|
const preferences = readStudioUiPreferences();
|
|
52326
|
-
const
|
|
52327
|
-
const rightDefault = Math.max(320, Math.min(424, Math.round(viewportWidth * 0.284)));
|
|
52384
|
+
const defaults = defaultPanelWidths(readViewportWidth());
|
|
52328
52385
|
return {
|
|
52329
|
-
left:
|
|
52330
|
-
|
|
52331
|
-
Math.min(Math.floor(viewportWidth * 0.5), preferences.leftWidth ?? leftDefault)
|
|
52332
|
-
),
|
|
52333
|
-
right: Math.max(160, Math.min(600, preferences.rightWidth ?? rightDefault))
|
|
52386
|
+
left: preferences.leftWidth ?? defaults.left,
|
|
52387
|
+
right: preferences.rightWidth ?? defaults.right
|
|
52334
52388
|
};
|
|
52335
52389
|
}
|
|
52336
|
-
function clampPanelWidth(side, width) {
|
|
52337
|
-
const max = side === "left" ? Math.floor(window.innerWidth * 0.5) : 600;
|
|
52338
|
-
return Math.max(160, Math.min(max, width));
|
|
52339
|
-
}
|
|
52340
52390
|
function usePanelLayout(initialState2) {
|
|
52341
|
-
const [
|
|
52342
|
-
const [
|
|
52343
|
-
const [rightWidth, setRightWidth] = useState82(initialPanelWidths.right);
|
|
52344
|
-
const panelWidthsRef = useRef90(initialPanelWidths);
|
|
52391
|
+
const [preferredWidths, setPreferredWidths] = useState82(getPreferredPanelWidths);
|
|
52392
|
+
const [viewportWidth, setViewportWidth] = useState82(readViewportWidth);
|
|
52345
52393
|
const [leftCollapsed, setLeftCollapsed] = useState82(
|
|
52346
52394
|
() => readStudioUiPreferences().leftCollapsed ?? false
|
|
52347
52395
|
);
|
|
@@ -52352,33 +52400,65 @@ function usePanelLayout(initialState2) {
|
|
|
52352
52400
|
const [rightInspectorPanes, setRightInspectorPanes] = useState82(
|
|
52353
52401
|
() => getInitialRightInspectorPanes(initialState2?.rightPanelTab)
|
|
52354
52402
|
);
|
|
52403
|
+
const [autoCollapseOverride, setAutoCollapseOverride] = useState82(NO_OVERRIDE);
|
|
52404
|
+
useEffect74(() => {
|
|
52405
|
+
if (typeof window === "undefined") return;
|
|
52406
|
+
const handleResize = () => {
|
|
52407
|
+
const width = window.innerWidth;
|
|
52408
|
+
setViewportWidth(width);
|
|
52409
|
+
if (!railsEngaged(width)) {
|
|
52410
|
+
setAutoCollapseOverride((prev) => prev.left || prev.right ? NO_OVERRIDE : prev);
|
|
52411
|
+
}
|
|
52412
|
+
};
|
|
52413
|
+
window.addEventListener("resize", handleResize);
|
|
52414
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
52415
|
+
}, []);
|
|
52416
|
+
const fitted = fitPanelWidths(viewportWidth, preferredWidths, autoCollapseOverride);
|
|
52417
|
+
const leftCollapsedByWidth = fitted.autoCollapseLeft;
|
|
52418
|
+
const rightCollapsedByWidth = fitted.autoCollapseRight;
|
|
52419
|
+
const fittedRef = useRef90(fitted);
|
|
52420
|
+
fittedRef.current = fitted;
|
|
52355
52421
|
const panelDragRef = useRef90(null);
|
|
52356
|
-
const
|
|
52357
|
-
|
|
52358
|
-
|
|
52359
|
-
|
|
52360
|
-
|
|
52422
|
+
const preferredRef = useRef90(preferredWidths);
|
|
52423
|
+
const setPreferred = useCallback69((side, width) => {
|
|
52424
|
+
const next = Math.max(0, Math.round(width));
|
|
52425
|
+
preferredRef.current = { ...preferredRef.current, [side]: next };
|
|
52426
|
+
setPreferredWidths(preferredRef.current);
|
|
52361
52427
|
return next;
|
|
52362
52428
|
}, []);
|
|
52429
|
+
const updatePanelWidth = useCallback69(
|
|
52430
|
+
(side, width) => {
|
|
52431
|
+
setPreferred(side, width);
|
|
52432
|
+
},
|
|
52433
|
+
[setPreferred]
|
|
52434
|
+
);
|
|
52363
52435
|
const commitPanelWidth = useCallback69(
|
|
52364
52436
|
(side, width) => {
|
|
52365
|
-
const
|
|
52366
|
-
|
|
52437
|
+
const candidate = { ...preferredRef.current, [side]: Math.max(0, Math.round(width)) };
|
|
52438
|
+
const settled = fitPanelWidths(readViewportWidth(), candidate)[side];
|
|
52439
|
+
setPreferred(side, settled);
|
|
52440
|
+
writeStudioUiPreferences(side === "left" ? { leftWidth: settled } : { rightWidth: settled });
|
|
52367
52441
|
},
|
|
52368
|
-
[
|
|
52442
|
+
[setPreferred]
|
|
52369
52443
|
);
|
|
52370
52444
|
const adjustPanelWidth = useCallback69(
|
|
52371
52445
|
(side, delta) => {
|
|
52372
|
-
commitPanelWidth(side,
|
|
52446
|
+
commitPanelWidth(side, preferredRef.current[side] + delta);
|
|
52373
52447
|
},
|
|
52374
52448
|
[commitPanelWidth]
|
|
52375
52449
|
);
|
|
52450
|
+
const effectiveLeftCollapsedRef = useRef90(false);
|
|
52451
|
+
effectiveLeftCollapsedRef.current = leftCollapsed || leftCollapsedByWidth;
|
|
52376
52452
|
const toggleLeftSidebar = useCallback69(() => {
|
|
52377
|
-
|
|
52378
|
-
|
|
52379
|
-
|
|
52380
|
-
|
|
52381
|
-
});
|
|
52453
|
+
const next = !effectiveLeftCollapsedRef.current;
|
|
52454
|
+
setLeftCollapsed(next);
|
|
52455
|
+
writeStudioUiPreferences({ leftCollapsed: next });
|
|
52456
|
+
trackStudioEvent("panel_toggle", { panel: "left_sidebar", collapsed: next });
|
|
52457
|
+
if (!next) setAutoCollapseOverride((prev) => ({ ...prev, left: true }));
|
|
52458
|
+
}, []);
|
|
52459
|
+
const setRightCollapsedWithOverride = useCallback69((collapsed) => {
|
|
52460
|
+
setRightCollapsed(collapsed);
|
|
52461
|
+
if (!collapsed) setAutoCollapseOverride((prev) => ({ ...prev, right: true }));
|
|
52382
52462
|
}, []);
|
|
52383
52463
|
const handlePanelResizeStart = useCallback69((side, e) => {
|
|
52384
52464
|
e.preventDefault();
|
|
@@ -52386,7 +52466,7 @@ function usePanelLayout(initialState2) {
|
|
|
52386
52466
|
panelDragRef.current = {
|
|
52387
52467
|
side,
|
|
52388
52468
|
startX: e.clientX,
|
|
52389
|
-
startW:
|
|
52469
|
+
startW: fittedRef.current[side]
|
|
52390
52470
|
};
|
|
52391
52471
|
}, []);
|
|
52392
52472
|
const handlePanelResizeMove = useCallback69(
|
|
@@ -52400,7 +52480,7 @@ function usePanelLayout(initialState2) {
|
|
|
52400
52480
|
);
|
|
52401
52481
|
const handlePanelResizeEnd = useCallback69(() => {
|
|
52402
52482
|
const side = panelDragRef.current?.side;
|
|
52403
|
-
if (side) commitPanelWidth(side,
|
|
52483
|
+
if (side) commitPanelWidth(side, preferredRef.current[side]);
|
|
52404
52484
|
panelDragRef.current = null;
|
|
52405
52485
|
}, [commitPanelWidth]);
|
|
52406
52486
|
const trackedSetRightPanelTab = useCallback69(
|
|
@@ -52426,13 +52506,22 @@ function usePanelLayout(initialState2) {
|
|
|
52426
52506
|
setRightInspectorPanes({ design: pane === "design", layers: pane === "layers" });
|
|
52427
52507
|
}, []);
|
|
52428
52508
|
return {
|
|
52429
|
-
leftWidth,
|
|
52430
|
-
rightWidth,
|
|
52509
|
+
leftWidth: fitted.left,
|
|
52510
|
+
rightWidth: fitted.right,
|
|
52431
52511
|
adjustPanelWidth,
|
|
52512
|
+
/**
|
|
52513
|
+
* User intent. Persisted to localStorage; never written by auto-collapse.
|
|
52514
|
+
* Deliberately read-only outside this hook: `toggleLeftSidebar` is the only
|
|
52515
|
+
* writer, so it cannot be flipped without also clearing the rail override
|
|
52516
|
+
* (which would open the sidebar and then immediately rail it again).
|
|
52517
|
+
*/
|
|
52432
52518
|
leftCollapsed,
|
|
52433
|
-
|
|
52519
|
+
/** User intent. Synced into the shareable URL; never written by auto-collapse. */
|
|
52434
52520
|
rightCollapsed,
|
|
52435
|
-
setRightCollapsed,
|
|
52521
|
+
setRightCollapsed: setRightCollapsedWithOverride,
|
|
52522
|
+
/** What the shell actually renders: intent OR the window forcing a rail. */
|
|
52523
|
+
effectiveLeftCollapsed: leftCollapsed || leftCollapsedByWidth,
|
|
52524
|
+
effectiveRightCollapsed: rightCollapsed || rightCollapsedByWidth,
|
|
52436
52525
|
rightPanelTab,
|
|
52437
52526
|
setRightPanelTab: trackedSetRightPanelTab,
|
|
52438
52527
|
rightInspectorPanes,
|
|
@@ -52483,13 +52572,13 @@ function createStudioWriteToken() {
|
|
|
52483
52572
|
}
|
|
52484
52573
|
|
|
52485
52574
|
// src/hooks/useFileTree.ts
|
|
52486
|
-
import { useState as useState83, useCallback as useCallback70, useEffect as
|
|
52575
|
+
import { useState as useState83, useCallback as useCallback70, useEffect as useEffect75, useMemo as useMemo48 } from "react";
|
|
52487
52576
|
function useFileTree({ projectId, projectIdRef }) {
|
|
52488
52577
|
const [projectDir, setProjectDir] = useState83(null);
|
|
52489
52578
|
const [fileTree, setFileTree] = useState83([]);
|
|
52490
52579
|
const [compositionPaths, setCompositionPaths] = useState83([]);
|
|
52491
52580
|
const [fileTreeLoaded, setFileTreeLoaded] = useState83(false);
|
|
52492
|
-
|
|
52581
|
+
useEffect75(() => {
|
|
52493
52582
|
if (!projectId) {
|
|
52494
52583
|
setFileTreeLoaded(false);
|
|
52495
52584
|
return;
|
|
@@ -53476,7 +53565,7 @@ function usePreviewPersistence({
|
|
|
53476
53565
|
}
|
|
53477
53566
|
|
|
53478
53567
|
// src/hooks/usePreviewDocumentVersion.ts
|
|
53479
|
-
import { useCallback as useCallback74, useEffect as
|
|
53568
|
+
import { useCallback as useCallback74, useEffect as useEffect76, useRef as useRef94, useState as useState86 } from "react";
|
|
53480
53569
|
function usePreviewDocumentVersion() {
|
|
53481
53570
|
const [previewDocumentVersion, setPreviewDocumentVersion] = useState86(0);
|
|
53482
53571
|
const refreshTimersRef = useRef94([]);
|
|
@@ -53489,7 +53578,7 @@ function usePreviewDocumentVersion() {
|
|
|
53489
53578
|
window.setTimeout(() => setPreviewDocumentVersion((v) => v + 1), 300)
|
|
53490
53579
|
);
|
|
53491
53580
|
}, []);
|
|
53492
|
-
|
|
53581
|
+
useEffect76(
|
|
53493
53582
|
() => () => {
|
|
53494
53583
|
for (const id of refreshTimersRef.current) clearTimeout(id);
|
|
53495
53584
|
},
|
|
@@ -55034,7 +55123,7 @@ function persistTimelineMoveEditsAtomically(edits, coalesceKey, operation, deps,
|
|
|
55034
55123
|
import { useCallback as useCallback102 } from "react";
|
|
55035
55124
|
|
|
55036
55125
|
// src/hooks/useAskAgentModal.ts
|
|
55037
|
-
import { useState as useState87, useCallback as useCallback80, useRef as useRef97, useEffect as
|
|
55126
|
+
import { useState as useState87, useCallback as useCallback80, useRef as useRef97, useEffect as useEffect77 } from "react";
|
|
55038
55127
|
function useAskAgentModal({
|
|
55039
55128
|
activeCompPath,
|
|
55040
55129
|
projectDir,
|
|
@@ -55115,13 +55204,13 @@ function useAskAgentModal({
|
|
|
55115
55204
|
showToast
|
|
55116
55205
|
]
|
|
55117
55206
|
);
|
|
55118
|
-
|
|
55207
|
+
useEffect77(() => {
|
|
55119
55208
|
setAgentPromptTagSnippet(void 0);
|
|
55120
55209
|
setAgentPromptSelectionContext(void 0);
|
|
55121
55210
|
setAgentModalAnchorPoint(null);
|
|
55122
55211
|
setCopiedAgentPrompt(false);
|
|
55123
55212
|
}, [domEditSelection]);
|
|
55124
|
-
|
|
55213
|
+
useEffect77(
|
|
55125
55214
|
() => () => {
|
|
55126
55215
|
if (copiedAgentTimerRef.current) clearTimeout(copiedAgentTimerRef.current);
|
|
55127
55216
|
},
|
|
@@ -55145,7 +55234,7 @@ function useAskAgentModal({
|
|
|
55145
55234
|
}
|
|
55146
55235
|
|
|
55147
55236
|
// src/hooks/useDomSelection.ts
|
|
55148
|
-
import { useState as useState88, useCallback as useCallback81, useRef as useRef98, useEffect as
|
|
55237
|
+
import { useState as useState88, useCallback as useCallback81, useRef as useRef98, useEffect as useEffect79 } from "react";
|
|
55149
55238
|
|
|
55150
55239
|
// src/utils/domEditHelpers.ts
|
|
55151
55240
|
function domEditSelectionsTargetSame(a, b) {
|
|
@@ -55178,7 +55267,7 @@ function seedDomEditGroupWithSelection(group, selection) {
|
|
|
55178
55267
|
}
|
|
55179
55268
|
|
|
55180
55269
|
// src/hooks/useStudioTestHooks.ts
|
|
55181
|
-
import { useEffect as
|
|
55270
|
+
import { useEffect as useEffect78 } from "react";
|
|
55182
55271
|
|
|
55183
55272
|
// src/player/lib/timelinePerformanceDiagnostics.ts
|
|
55184
55273
|
function readNonNegativeNumber(value) {
|
|
@@ -55261,7 +55350,7 @@ function useStudioTestHooks({
|
|
|
55261
55350
|
buildDomSelectionFromTarget,
|
|
55262
55351
|
applyDomSelection
|
|
55263
55352
|
}) {
|
|
55264
|
-
|
|
55353
|
+
useEffect78(() => {
|
|
55265
55354
|
if (!STUDIO_TEST_HOOKS_ENABLED || typeof window === "undefined") return;
|
|
55266
55355
|
const api = {
|
|
55267
55356
|
runtimeMode: STUDIO_RUNTIME_MODE,
|
|
@@ -55562,10 +55651,10 @@ function useDomSelection({
|
|
|
55562
55651
|
previewIframeRef
|
|
55563
55652
|
]
|
|
55564
55653
|
);
|
|
55565
|
-
|
|
55654
|
+
useEffect79(() => {
|
|
55566
55655
|
updateDomEditHoverSelection(null);
|
|
55567
55656
|
}, [activeCompPath, projectId, previewIframe, refreshKey, updateDomEditHoverSelection]);
|
|
55568
|
-
|
|
55657
|
+
useEffect79(() => {
|
|
55569
55658
|
const previous = compositionIdentityRef.current;
|
|
55570
55659
|
if (previous.activeCompPath === activeCompPath && previous.projectId === projectId) return;
|
|
55571
55660
|
compositionIdentityRef.current = { activeCompPath, projectId };
|
|
@@ -55573,7 +55662,7 @@ function useDomSelection({
|
|
|
55573
55662
|
setActiveGroupElementState(null);
|
|
55574
55663
|
applyDomSelection(null, { revealPanel: false });
|
|
55575
55664
|
}, [activeCompPath, projectId, applyDomSelection]);
|
|
55576
|
-
|
|
55665
|
+
useEffect79(() => {
|
|
55577
55666
|
if (!domEditHoverSelection) return;
|
|
55578
55667
|
const shouldClear = captionEditMode || domEditSelectionsTargetSame(domEditHoverSelection, domEditSelection) || domEditSelectionInGroup(domEditGroupSelections, domEditHoverSelection) || !domEditHoverSelection.element.isConnected;
|
|
55579
55668
|
if (shouldClear) updateDomEditHoverSelection(null);
|
|
@@ -55584,7 +55673,7 @@ function useDomSelection({
|
|
|
55584
55673
|
domEditGroupSelections,
|
|
55585
55674
|
updateDomEditHoverSelection
|
|
55586
55675
|
]);
|
|
55587
|
-
|
|
55676
|
+
useEffect79(() => {
|
|
55588
55677
|
if (!captionEditMode) return;
|
|
55589
55678
|
applyDomSelection(null, { revealPanel: false });
|
|
55590
55679
|
}, [applyDomSelection, captionEditMode]);
|
|
@@ -58330,7 +58419,7 @@ function useGsapKeyframeOps({
|
|
|
58330
58419
|
}
|
|
58331
58420
|
|
|
58332
58421
|
// src/hooks/useGsapPropertyDebounce.ts
|
|
58333
|
-
import { useCallback as useCallback92, useEffect as
|
|
58422
|
+
import { useCallback as useCallback92, useEffect as useEffect80, useRef as useRef103 } from "react";
|
|
58334
58423
|
import { parseGsapScriptAcorn } from "@hyperframes/core/gsap-parser-acorn";
|
|
58335
58424
|
var DEBOUNCE_MS = 150;
|
|
58336
58425
|
function mergeTweenProperties(sdkSession, animationId, edited, kind) {
|
|
@@ -58400,7 +58489,7 @@ function useGsapPropertyDebounce(commitMutationSafely, sdk) {
|
|
|
58400
58489
|
},
|
|
58401
58490
|
[flushPendingPropertyEdit]
|
|
58402
58491
|
);
|
|
58403
|
-
|
|
58492
|
+
useEffect80(() => {
|
|
58404
58493
|
return () => {
|
|
58405
58494
|
if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
|
|
58406
58495
|
void flushPendingPropertyEdit();
|
|
@@ -58941,10 +59030,10 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
|
|
|
58941
59030
|
}
|
|
58942
59031
|
|
|
58943
59032
|
// src/hooks/useDomEditWiring.ts
|
|
58944
|
-
import { useCallback as useCallback98, useEffect as
|
|
59033
|
+
import { useCallback as useCallback98, useEffect as useEffect82, useRef as useRef107 } from "react";
|
|
58945
59034
|
|
|
58946
59035
|
// src/hooks/useDomEditPreviewSync.ts
|
|
58947
|
-
import { useEffect as
|
|
59036
|
+
import { useEffect as useEffect81, useRef as useRef105 } from "react";
|
|
58948
59037
|
function useDomEditPreviewSync({
|
|
58949
59038
|
previewIframe,
|
|
58950
59039
|
activeCompPath,
|
|
@@ -58960,7 +59049,7 @@ function useDomEditPreviewSync({
|
|
|
58960
59049
|
getSidebarTab,
|
|
58961
59050
|
gsapCacheVersion
|
|
58962
59051
|
}) {
|
|
58963
|
-
|
|
59052
|
+
useEffect81(() => {
|
|
58964
59053
|
if (!previewIframe) return;
|
|
58965
59054
|
const syncSelectionFromDocument = async () => {
|
|
58966
59055
|
if (captionEditMode) return;
|
|
@@ -59012,7 +59101,7 @@ function useDomEditPreviewSync({
|
|
|
59012
59101
|
]);
|
|
59013
59102
|
const openSourceRef = useRef105(openSourceForSelection);
|
|
59014
59103
|
openSourceRef.current = openSourceForSelection;
|
|
59015
|
-
|
|
59104
|
+
useEffect81(
|
|
59016
59105
|
// fallow-ignore-next-line complexity
|
|
59017
59106
|
() => {
|
|
59018
59107
|
if (!domEditSelection || !openSourceRef.current || !getSidebarTab) return;
|
|
@@ -59449,7 +59538,7 @@ function useDomEditWiring({
|
|
|
59449
59538
|
},
|
|
59450
59539
|
[openSourceForSelection, selectSidebarTab]
|
|
59451
59540
|
);
|
|
59452
|
-
|
|
59541
|
+
useEffect82(() => {
|
|
59453
59542
|
if (!domEditSelection?.id) return;
|
|
59454
59543
|
const { selectedElementId, elements, setSelectedElementId } = usePlayerStore.getState();
|
|
59455
59544
|
const matchKey = elements.find(
|
|
@@ -59459,7 +59548,7 @@ function useDomEditWiring({
|
|
|
59459
59548
|
if (key2 && key2 !== selectedElementId) setSelectedElementId(key2);
|
|
59460
59549
|
}, [domEditSelection?.id]);
|
|
59461
59550
|
const prevRefreshKeyRef = useRef107(refreshKey);
|
|
59462
|
-
|
|
59551
|
+
useEffect82(() => {
|
|
59463
59552
|
if (refreshKey !== prevRefreshKeyRef.current) {
|
|
59464
59553
|
prevRefreshKeyRef.current = refreshKey;
|
|
59465
59554
|
bumpGsapCache();
|
|
@@ -59597,7 +59686,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
59597
59686
|
if (!anim || isInstantHold(anim)) {
|
|
59598
59687
|
const sel = selectorFromSelection(selection) ?? writeTargetSelector(selection);
|
|
59599
59688
|
if (!sel) return { status: "blocked", reason: "no-selector" };
|
|
59600
|
-
const sizeSet = anim ?? findSizeSetAnimation(workingAnimations, sel, selection.element);
|
|
59689
|
+
const sizeSet = resizeGroup === "size" ? anim ?? findSizeSetAnimation(workingAnimations, sel, selection.element) : findSizeSetAnimation(workingAnimations, sel, selection.element);
|
|
59601
59690
|
if (resizeGroup === "size") {
|
|
59602
59691
|
const animatedTween = pickClosestToPlayhead(
|
|
59603
59692
|
workingAnimations.filter((a) => !isInstantHold(a) && resolveTweenDuration(a) > 0)
|
|
@@ -59645,7 +59734,8 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
59645
59734
|
const liveScaleY = rawLiveScaleY > 0 ? rawLiveScaleY : 1;
|
|
59646
59735
|
const newScaleX = roundTo3(size.width * liveScaleX / cssW);
|
|
59647
59736
|
const newScaleY = roundTo3(size.height * liveScaleY / cssH);
|
|
59648
|
-
|
|
59737
|
+
const uniformDrift = Math.abs(newScaleX - newScaleY) * cssH;
|
|
59738
|
+
nonUniformScale = uniformDrift > 0.5;
|
|
59649
59739
|
useScaleLonghands = nonUniformScale || tweenUsesScaleLonghands(anim);
|
|
59650
59740
|
resizeProps = useScaleLonghands ? { scaleX: newScaleX, scaleY: newScaleY } : { scale: newScaleX };
|
|
59651
59741
|
logResize("intercept-route", {
|
|
@@ -59671,9 +59761,9 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
59671
59761
|
};
|
|
59672
59762
|
}
|
|
59673
59763
|
const finalizeScaleResizeCommit = async () => {
|
|
59674
|
-
if (!scaleDraftEl) return;
|
|
59764
|
+
if (!scaleDraftEl) return false;
|
|
59675
59765
|
clearStudioBoxSize(scaleDraftEl);
|
|
59676
|
-
if (!scaleDraftDropPoint || !selector) return;
|
|
59766
|
+
if (!scaleDraftDropPoint || !selector) return false;
|
|
59677
59767
|
if (committedScale) {
|
|
59678
59768
|
setElementGsapScale(scaleDraftEl, committedScale.x, committedScale.y);
|
|
59679
59769
|
}
|
|
@@ -59687,10 +59777,10 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
59687
59777
|
setElementGsapPosition(scaleDraftEl, base2.x, base2.y);
|
|
59688
59778
|
const post = scaleDraftEl.getBoundingClientRect();
|
|
59689
59779
|
const residual = { x: scaleDraftDropPoint.x - post.x, y: scaleDraftDropPoint.y - post.y };
|
|
59690
|
-
if (!Number.isFinite(residual.x) || !Number.isFinite(residual.y)) return;
|
|
59780
|
+
if (!Number.isFinite(residual.x) || !Number.isFinite(residual.y)) return false;
|
|
59691
59781
|
if (Math.abs(residual.x) < 0.5 && Math.abs(residual.y) < 0.5) {
|
|
59692
59782
|
logResize("scale-finalize", { skipped: "already-on-drop-point", residual, base: base2 });
|
|
59693
|
-
return;
|
|
59783
|
+
return true;
|
|
59694
59784
|
}
|
|
59695
59785
|
const corrected = {
|
|
59696
59786
|
x: Math.round(base2.x + residual.x),
|
|
@@ -59718,13 +59808,14 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
59718
59808
|
commitMutation,
|
|
59719
59809
|
fetchAnimations: fetchFallbackAnimations
|
|
59720
59810
|
});
|
|
59721
|
-
return;
|
|
59811
|
+
return true;
|
|
59722
59812
|
}
|
|
59723
59813
|
const existingSet = findExistingPositionWrite(currentAnimations, selector, selection.element);
|
|
59724
59814
|
await commitStaticGsapPosition(selection, delta, base2, selector, existingSet, {
|
|
59725
59815
|
commitMutation,
|
|
59726
59816
|
fetchAnimations: fetchFallbackAnimations
|
|
59727
59817
|
});
|
|
59818
|
+
return true;
|
|
59728
59819
|
};
|
|
59729
59820
|
if (!usePlayerStore.getState().autoKeyframeEnabled) {
|
|
59730
59821
|
if (activeKeyframePct != null) setActiveKeyframePct(null);
|
|
@@ -59737,8 +59828,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
59737
59828
|
{ commitMutation, fetchAnimations: fetchFallbackAnimations },
|
|
59738
59829
|
"Resize animation"
|
|
59739
59830
|
);
|
|
59740
|
-
await finalizeScaleResizeCommit();
|
|
59741
|
-
return { status: "persisted" };
|
|
59831
|
+
return { status: "persisted", ownsDragOffset: await finalizeScaleResizeCommit() };
|
|
59742
59832
|
}
|
|
59743
59833
|
const ct = usePlayerStore.getState().currentTime;
|
|
59744
59834
|
const ts = resolveTweenStart(anim);
|
|
@@ -59817,8 +59907,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
59817
59907
|
softReload: true
|
|
59818
59908
|
}
|
|
59819
59909
|
);
|
|
59820
|
-
await finalizeScaleResizeCommit();
|
|
59821
|
-
return { status: "persisted" };
|
|
59910
|
+
return { status: "persisted", ownsDragOffset: await finalizeScaleResizeCommit() };
|
|
59822
59911
|
}
|
|
59823
59912
|
const SIZE_PROPS = /* @__PURE__ */ new Set(["width", "height"]);
|
|
59824
59913
|
const backfillDefaults = {};
|
|
@@ -59837,8 +59926,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
|
|
|
59837
59926
|
},
|
|
59838
59927
|
{ label: `Resize (keyframe ${pct}%)`, softReload: true }
|
|
59839
59928
|
);
|
|
59840
|
-
await finalizeScaleResizeCommit();
|
|
59841
|
-
return { status: "persisted" };
|
|
59929
|
+
return { status: "persisted", ownsDragOffset: await finalizeScaleResizeCommit() };
|
|
59842
59930
|
}
|
|
59843
59931
|
|
|
59844
59932
|
// src/hooks/useAnimatedPropertyCommit.ts
|
|
@@ -60338,11 +60426,13 @@ function useGsapAwareEditing({
|
|
|
60338
60426
|
makeFetchFallback(selection)
|
|
60339
60427
|
);
|
|
60340
60428
|
assertGsapEditPersisted(outcome);
|
|
60429
|
+
const ownsDragOffset = outcome.status === "persisted" && outcome.ownsDragOffset === true;
|
|
60341
60430
|
logResize("intercept-handled", {
|
|
60342
60431
|
scaleRoute,
|
|
60343
|
-
|
|
60432
|
+
ownsDragOffset,
|
|
60433
|
+
willForwardOffset: !!(offset && !ownsDragOffset)
|
|
60344
60434
|
});
|
|
60345
|
-
if (offset && !
|
|
60435
|
+
if (offset && !ownsDragOffset) {
|
|
60346
60436
|
const dragOutcome = await tryGsapDragIntercept(
|
|
60347
60437
|
selection,
|
|
60348
60438
|
offset,
|
|
@@ -60353,7 +60443,7 @@ function useGsapAwareEditing({
|
|
|
60353
60443
|
);
|
|
60354
60444
|
assertGsapEditPersisted(dragOutcome);
|
|
60355
60445
|
}
|
|
60356
|
-
logResizeSettle(selection.element,
|
|
60446
|
+
logResizeSettle(selection.element, ownsDragOffset ? "gsap-scale" : "gsap-size");
|
|
60357
60447
|
return;
|
|
60358
60448
|
} catch (error) {
|
|
60359
60449
|
trackGsapInteractionFailure(error, selection, "resize", "Resize animated layer");
|
|
@@ -60491,7 +60581,7 @@ function useGsapAwareEditing({
|
|
|
60491
60581
|
}
|
|
60492
60582
|
|
|
60493
60583
|
// src/hooks/useStudioSelectionPublisher.ts
|
|
60494
|
-
import { useEffect as
|
|
60584
|
+
import { useEffect as useEffect83, useRef as useRef108 } from "react";
|
|
60495
60585
|
|
|
60496
60586
|
// src/utils/studioSelectionSnapshot.ts
|
|
60497
60587
|
function round34(value) {
|
|
@@ -60584,7 +60674,7 @@ function useStudioSelectionPublisher({
|
|
|
60584
60674
|
}) {
|
|
60585
60675
|
const lastSelectionRefreshKeyRef = useRef108(refreshKey);
|
|
60586
60676
|
const pendingSelectionRefreshKeyRef = useRef108(null);
|
|
60587
|
-
|
|
60677
|
+
useEffect83(() => {
|
|
60588
60678
|
if (!projectId) return;
|
|
60589
60679
|
const selection = domEditSelection?.element.isConnected ? buildStudioSelectionSnapshot({
|
|
60590
60680
|
projectId,
|
|
@@ -60595,13 +60685,13 @@ function useStudioSelectionPublisher({
|
|
|
60595
60685
|
void putSelection(projectId, selection, controller.signal).catch(reportSelectionPublishError);
|
|
60596
60686
|
return () => controller.abort();
|
|
60597
60687
|
}, [domEditSelection, projectId]);
|
|
60598
|
-
|
|
60688
|
+
useEffect83(() => {
|
|
60599
60689
|
if (!projectId) return;
|
|
60600
60690
|
return () => {
|
|
60601
60691
|
void putSelection(projectId, null).catch(reportSelectionPublishError);
|
|
60602
60692
|
};
|
|
60603
60693
|
}, [projectId]);
|
|
60604
|
-
|
|
60694
|
+
useEffect83(() => {
|
|
60605
60695
|
if (lastSelectionRefreshKeyRef.current === refreshKey) return;
|
|
60606
60696
|
lastSelectionRefreshKeyRef.current = refreshKey;
|
|
60607
60697
|
pendingSelectionRefreshKeyRef.current = domEditSelectionRef.current ? refreshKey : null;
|
|
@@ -60610,7 +60700,7 @@ function useStudioSelectionPublisher({
|
|
|
60610
60700
|
void putSelection(projectId, null, controller.signal).catch(reportSelectionPublishError);
|
|
60611
60701
|
return () => controller.abort();
|
|
60612
60702
|
}, [domEditSelectionRef, projectId, refreshKey]);
|
|
60613
|
-
|
|
60703
|
+
useEffect83(() => {
|
|
60614
60704
|
if (pendingSelectionRefreshKeyRef.current === null) return;
|
|
60615
60705
|
pendingSelectionRefreshKeyRef.current = null;
|
|
60616
60706
|
const selection = domEditSelectionRef.current;
|
|
@@ -61127,23 +61217,23 @@ function useDomEditSession({
|
|
|
61127
61217
|
}
|
|
61128
61218
|
|
|
61129
61219
|
// src/hooks/useSdkSelectionSync.ts
|
|
61130
|
-
import { useEffect as
|
|
61220
|
+
import { useEffect as useEffect84 } from "react";
|
|
61131
61221
|
function toHfIds(group, primary) {
|
|
61132
61222
|
const source = group.length > 0 ? group : primary ? [primary] : [];
|
|
61133
61223
|
return source.flatMap((s) => s.hfId ? [s.hfId] : []);
|
|
61134
61224
|
}
|
|
61135
61225
|
function useSdkSelectionSync(session, domEditSelection, domEditGroupSelections) {
|
|
61136
|
-
|
|
61226
|
+
useEffect84(() => {
|
|
61137
61227
|
if (!session) return;
|
|
61138
61228
|
session.setSelection(toHfIds(domEditGroupSelections, domEditSelection));
|
|
61139
61229
|
}, [session, domEditSelection, domEditGroupSelections]);
|
|
61140
61230
|
}
|
|
61141
61231
|
|
|
61142
61232
|
// src/hooks/useStudioSdkSessions.ts
|
|
61143
|
-
import { useEffect as
|
|
61233
|
+
import { useEffect as useEffect86 } from "react";
|
|
61144
61234
|
|
|
61145
61235
|
// src/hooks/useSdkSession.ts
|
|
61146
|
-
import { useState as useState89, useEffect as
|
|
61236
|
+
import { useState as useState89, useEffect as useEffect85, useCallback as useCallback103, useRef as useRef109 } from "react";
|
|
61147
61237
|
import { openComposition as openComposition3 } from "@hyperframes/sdk";
|
|
61148
61238
|
|
|
61149
61239
|
// src/hooks/externalFileReloadBus.ts
|
|
@@ -61203,13 +61293,13 @@ function useSdkSession(projectId, activeCompPath) {
|
|
|
61203
61293
|
const [reloadToken, setReloadToken] = useState89(0);
|
|
61204
61294
|
const reloadTokenRef = useRef109(reloadToken);
|
|
61205
61295
|
reloadTokenRef.current = reloadToken;
|
|
61206
|
-
|
|
61296
|
+
useEffect85(
|
|
61207
61297
|
() => addExternalFileReloadListener((changedPath) => {
|
|
61208
61298
|
if (changedPath === activeCompPathRef.current) setReloadToken((token) => token + 1);
|
|
61209
61299
|
}),
|
|
61210
61300
|
[]
|
|
61211
61301
|
);
|
|
61212
|
-
|
|
61302
|
+
useEffect85(() => {
|
|
61213
61303
|
const generation = ++generationRef.current;
|
|
61214
61304
|
let cancelled = false;
|
|
61215
61305
|
const previous = ownedSessionRef.current;
|
|
@@ -61293,7 +61383,7 @@ function useSdkSession(projectId, activeCompPath) {
|
|
|
61293
61383
|
function useStudioSdkSessions(projectId, activeCompPath, masterCompPath) {
|
|
61294
61384
|
const sdkHandle = useSdkSession(projectId, activeCompPath ?? masterCompPath);
|
|
61295
61385
|
const editFlowSdkSession = activeCompPath ? sdkHandle.session : null;
|
|
61296
|
-
|
|
61386
|
+
useEffect86(() => {
|
|
61297
61387
|
usePreviewVariablesStore.getState().setValues(null);
|
|
61298
61388
|
}, [projectId, activeCompPath]);
|
|
61299
61389
|
return { sdkHandle, editFlowSdkSession };
|
|
@@ -61401,7 +61491,7 @@ async function deleteExternalConflictSnapshot(projectId, filePath) {
|
|
|
61401
61491
|
}
|
|
61402
61492
|
|
|
61403
61493
|
// src/hooks/useExternalFileChangeCoordinator.ts
|
|
61404
|
-
import { useCallback as useCallback104, useEffect as
|
|
61494
|
+
import { useCallback as useCallback104, useEffect as useEffect87, useRef as useRef110, useState as useState90 } from "react";
|
|
61405
61495
|
function testHotAdapter() {
|
|
61406
61496
|
const value = globalThis.__HF_STUDIO_HOT_TEST_ADAPTER__;
|
|
61407
61497
|
if (!value || typeof value !== "object") return null;
|
|
@@ -61458,19 +61548,19 @@ function useExternalFileChangeCoordinator({
|
|
|
61458
61548
|
const blockedRef = useRef110(blocked);
|
|
61459
61549
|
const snapshotWriteTailRef = useRef110(Promise.resolve());
|
|
61460
61550
|
blockedRef.current = blocked;
|
|
61461
|
-
|
|
61551
|
+
useEffect87(() => {
|
|
61462
61552
|
mountedRef.current = true;
|
|
61463
61553
|
return () => {
|
|
61464
61554
|
mountedRef.current = false;
|
|
61465
61555
|
generationRef.current += 1;
|
|
61466
61556
|
};
|
|
61467
61557
|
}, []);
|
|
61468
|
-
|
|
61558
|
+
useEffect87(() => {
|
|
61469
61559
|
generationRef.current += 1;
|
|
61470
61560
|
setBlocked(null);
|
|
61471
61561
|
lastEventIdentityRef.current = null;
|
|
61472
61562
|
}, [projectId, activeCompPath]);
|
|
61473
|
-
|
|
61563
|
+
useEffect87(() => {
|
|
61474
61564
|
if (!projectId || !recoveryFilePath || !loadConflictSnapshot) return;
|
|
61475
61565
|
const generation = ++generationRef.current;
|
|
61476
61566
|
let cancelled = false;
|
|
@@ -61621,7 +61711,7 @@ function useExternalFileChangeCoordinator({
|
|
|
61621
61711
|
reloadAcceptedGeneration
|
|
61622
61712
|
]
|
|
61623
61713
|
);
|
|
61624
|
-
|
|
61714
|
+
useEffect87(() => {
|
|
61625
61715
|
const handler = (payload) => processChange(payload);
|
|
61626
61716
|
const adapter = testHotAdapter();
|
|
61627
61717
|
if (adapter) {
|
|
@@ -62087,7 +62177,7 @@ function useBlockHandlers({
|
|
|
62087
62177
|
}
|
|
62088
62178
|
|
|
62089
62179
|
// src/hooks/useAppHotkeys.ts
|
|
62090
|
-
import { useCallback as useCallback107, useEffect as
|
|
62180
|
+
import { useCallback as useCallback107, useEffect as useEffect88, useRef as useRef112 } from "react";
|
|
62091
62181
|
function iframeContentWindow(iframe) {
|
|
62092
62182
|
try {
|
|
62093
62183
|
return iframe?.contentWindow ?? null;
|
|
@@ -62380,7 +62470,7 @@ function useAppHotkeys({
|
|
|
62380
62470
|
}
|
|
62381
62471
|
if (!isEditableTarget(event.target)) dispatchPlainKey(event, key2, cb);
|
|
62382
62472
|
}, []);
|
|
62383
|
-
|
|
62473
|
+
useEffect88(() => {
|
|
62384
62474
|
window.addEventListener("keydown", handleAppKeyDown, true);
|
|
62385
62475
|
return () => window.removeEventListener("keydown", handleAppKeyDown, true);
|
|
62386
62476
|
}, [handleAppKeyDown]);
|
|
@@ -62398,7 +62488,7 @@ function useAppHotkeys({
|
|
|
62398
62488
|
},
|
|
62399
62489
|
[handleAppKeyDown]
|
|
62400
62490
|
);
|
|
62401
|
-
|
|
62491
|
+
useEffect88(
|
|
62402
62492
|
() => () => {
|
|
62403
62493
|
safeRemoveListener(
|
|
62404
62494
|
previewHotkeyWindowRef.current,
|
|
@@ -62439,7 +62529,7 @@ function useAppHotkeys({
|
|
|
62439
62529
|
},
|
|
62440
62530
|
[handleHistoryHotkey]
|
|
62441
62531
|
);
|
|
62442
|
-
|
|
62532
|
+
useEffect88(
|
|
62443
62533
|
() => () => {
|
|
62444
62534
|
previewHistoryCleanupRef.current?.();
|
|
62445
62535
|
previewHistoryCleanupRef.current = null;
|
|
@@ -62697,7 +62787,7 @@ function useClipboard({
|
|
|
62697
62787
|
}
|
|
62698
62788
|
|
|
62699
62789
|
// src/hooks/useCaptionDetection.ts
|
|
62700
|
-
import { useEffect as
|
|
62790
|
+
import { useEffect as useEffect89 } from "react";
|
|
62701
62791
|
|
|
62702
62792
|
// src/captions/types.ts
|
|
62703
62793
|
var DEFAULT_STYLE = {
|
|
@@ -62949,7 +63039,7 @@ function useCaptionDetection({
|
|
|
62949
63039
|
captionSync,
|
|
62950
63040
|
setRightCollapsed
|
|
62951
63041
|
}) {
|
|
62952
|
-
|
|
63042
|
+
useEffect89(() => {
|
|
62953
63043
|
if (!projectId) return;
|
|
62954
63044
|
let activating = false;
|
|
62955
63045
|
const tryActivateCaptions = () => {
|
|
@@ -63029,7 +63119,7 @@ function useCaptionDetection({
|
|
|
63029
63119
|
window.removeEventListener("message", handleMessage);
|
|
63030
63120
|
};
|
|
63031
63121
|
}, [activeCompPath, projectId, compIdToSrc, captionSync, previewIframeRef]);
|
|
63032
|
-
|
|
63122
|
+
useEffect89(() => {
|
|
63033
63123
|
if (captionEditMode) {
|
|
63034
63124
|
setRightCollapsed(!captionHasSelection);
|
|
63035
63125
|
}
|
|
@@ -63466,7 +63556,7 @@ function useRenderClipContent({
|
|
|
63466
63556
|
}
|
|
63467
63557
|
|
|
63468
63558
|
// src/hooks/useConsoleErrorCapture.ts
|
|
63469
|
-
import { useCallback as useCallback112, useEffect as
|
|
63559
|
+
import { useCallback as useCallback112, useEffect as useEffect90, useRef as useRef116, useState as useState93 } from "react";
|
|
63470
63560
|
function useConsoleErrorCapture(previewIframe) {
|
|
63471
63561
|
const [consoleErrors, setConsoleErrors] = useState93(null);
|
|
63472
63562
|
const consoleErrorsRef = useRef116([]);
|
|
@@ -63474,7 +63564,7 @@ function useConsoleErrorCapture(previewIframe) {
|
|
|
63474
63564
|
consoleErrorsRef.current = [];
|
|
63475
63565
|
setConsoleErrors(null);
|
|
63476
63566
|
}, []);
|
|
63477
|
-
|
|
63567
|
+
useEffect90(() => {
|
|
63478
63568
|
if (!previewIframe) return;
|
|
63479
63569
|
let patchedWin = null;
|
|
63480
63570
|
let origConsoleError = null;
|
|
@@ -63663,7 +63753,7 @@ function useFrameCapture({
|
|
|
63663
63753
|
}
|
|
63664
63754
|
|
|
63665
63755
|
// src/hooks/useLintModal.ts
|
|
63666
|
-
import { useState as useState95, useCallback as useCallback114, useEffect as
|
|
63756
|
+
import { useState as useState95, useCallback as useCallback114, useEffect as useEffect91, useRef as useRef118, useMemo as useMemo54 } from "react";
|
|
63667
63757
|
function parseFinding(f) {
|
|
63668
63758
|
return {
|
|
63669
63759
|
severity: f.severity === "error" ? "error" : "warning",
|
|
@@ -63705,7 +63795,7 @@ function useLintModal(projectId, refreshKey) {
|
|
|
63705
63795
|
);
|
|
63706
63796
|
const handleLint = useCallback114(() => runLint(), [runLint]);
|
|
63707
63797
|
const prevProjectIdRef = useRef118(projectId);
|
|
63708
|
-
|
|
63798
|
+
useEffect91(() => {
|
|
63709
63799
|
if (projectId !== prevProjectIdRef.current) {
|
|
63710
63800
|
autoLintRanRef.current = false;
|
|
63711
63801
|
prevProjectIdRef.current = projectId;
|
|
@@ -63714,7 +63804,7 @@ function useLintModal(projectId, refreshKey) {
|
|
|
63714
63804
|
autoLintRanRef.current = true;
|
|
63715
63805
|
void runLint({ background: true });
|
|
63716
63806
|
}, [projectId, runLint]);
|
|
63717
|
-
|
|
63807
|
+
useEffect91(() => {
|
|
63718
63808
|
if (!projectId || !refreshKey) return;
|
|
63719
63809
|
const timer = setTimeout(() => void runLint({ background: true }), 1e3);
|
|
63720
63810
|
return () => clearTimeout(timer);
|
|
@@ -63737,7 +63827,7 @@ function useLintModal(projectId, refreshKey) {
|
|
|
63737
63827
|
);
|
|
63738
63828
|
const findingsByElement = useMemo54(() => groupFindings((f) => f.elementId), [groupFindings]);
|
|
63739
63829
|
const findingsByFile = useMemo54(() => groupFindings((f) => f.file), [groupFindings]);
|
|
63740
|
-
|
|
63830
|
+
useEffect91(() => {
|
|
63741
63831
|
usePlayerStore.getState().setLintFindingsByElement(findingsByElement);
|
|
63742
63832
|
}, [findingsByElement]);
|
|
63743
63833
|
return {
|
|
@@ -63835,7 +63925,7 @@ function useCompositionContentLoader({
|
|
|
63835
63925
|
}
|
|
63836
63926
|
|
|
63837
63927
|
// src/hooks/useStudioUrlState.ts
|
|
63838
|
-
import { useCallback as useCallback117, useEffect as
|
|
63928
|
+
import { useCallback as useCallback117, useEffect as useEffect92, useRef as useRef120, useState as useState97 } from "react";
|
|
63839
63929
|
|
|
63840
63930
|
// src/utils/studioUrlState.ts
|
|
63841
63931
|
var VALID_TABS = ["layers", "design", "renders", "slideshow", "variables"];
|
|
@@ -64011,7 +64101,7 @@ function useStudioUrlState({
|
|
|
64011
64101
|
},
|
|
64012
64102
|
[activeCompPath, applyDomSelection, buildDomSelectionFromTarget, previewIframeRef]
|
|
64013
64103
|
);
|
|
64014
|
-
|
|
64104
|
+
useEffect92(() => {
|
|
64015
64105
|
if (!projectId || hydratedSeekRef.current || compositionLoading) return;
|
|
64016
64106
|
const nextTime = duration > 0 ? clampNumber(initialState2.currentTime ?? 0, 0, duration) : Math.max(0, initialState2.currentTime ?? 0);
|
|
64017
64107
|
usePlayerStore.getState().requestSeek(nextTime);
|
|
@@ -64019,7 +64109,7 @@ function useStudioUrlState({
|
|
|
64019
64109
|
hydratedSeekRef.current = true;
|
|
64020
64110
|
}, [projectId, compositionLoading, duration, initialState2.currentTime]);
|
|
64021
64111
|
const selectionHydrationTime = selectionHydrated ? 0 : currentTime;
|
|
64022
|
-
|
|
64112
|
+
useEffect92(() => {
|
|
64023
64113
|
if (!projectId || hydratedSelectionRef.current || compositionLoading) return;
|
|
64024
64114
|
if (!hydratedSeekRef.current) return;
|
|
64025
64115
|
const targetTime = initialState2.currentTime;
|
|
@@ -64046,7 +64136,7 @@ function useStudioUrlState({
|
|
|
64046
64136
|
projectId,
|
|
64047
64137
|
refreshKey
|
|
64048
64138
|
]);
|
|
64049
|
-
|
|
64139
|
+
useEffect92(() => {
|
|
64050
64140
|
if (hydratedInitialTimeRef.current) return;
|
|
64051
64141
|
const targetTime = stableTimeRef.current;
|
|
64052
64142
|
if (targetTime == null) {
|
|
@@ -64056,7 +64146,7 @@ function useStudioUrlState({
|
|
|
64056
64146
|
if (Math.abs(currentTime - targetTime) > 0.05) return;
|
|
64057
64147
|
hydratedInitialTimeRef.current = true;
|
|
64058
64148
|
}, [currentTime]);
|
|
64059
|
-
|
|
64149
|
+
useEffect92(() => {
|
|
64060
64150
|
if (!activeCompPathHydrated) return;
|
|
64061
64151
|
if (!hydratedSeekRef.current) return;
|
|
64062
64152
|
if (!hydratedInitialTimeRef.current) return;
|
|
@@ -64067,12 +64157,12 @@ function useStudioUrlState({
|
|
|
64067
64157
|
}, 200);
|
|
64068
64158
|
return () => window.clearTimeout(handle);
|
|
64069
64159
|
}, [activeCompPathHydrated, buildUrlState, currentTime, duration, isPlaying, projectId]);
|
|
64070
|
-
|
|
64160
|
+
useEffect92(() => {
|
|
64071
64161
|
if (!activeCompPathHydrated) return;
|
|
64072
64162
|
if (!projectId) return;
|
|
64073
64163
|
replaceHash(buildStudioHash(projectId, buildUrlState()));
|
|
64074
64164
|
}, [activeCompPathHydrated, buildUrlState, projectId]);
|
|
64075
|
-
|
|
64165
|
+
useEffect92(() => {
|
|
64076
64166
|
if (!projectId) return;
|
|
64077
64167
|
const onHashChange = () => {
|
|
64078
64168
|
if (parseProjectIdFromHash(window.location.hash) !== projectId) return;
|
|
@@ -64205,9 +64295,10 @@ function PanelLayoutProvider({
|
|
|
64205
64295
|
rightWidth,
|
|
64206
64296
|
adjustPanelWidth,
|
|
64207
64297
|
leftCollapsed,
|
|
64208
|
-
setLeftCollapsed,
|
|
64209
64298
|
rightCollapsed,
|
|
64210
64299
|
setRightCollapsed,
|
|
64300
|
+
effectiveLeftCollapsed,
|
|
64301
|
+
effectiveRightCollapsed,
|
|
64211
64302
|
rightPanelTab,
|
|
64212
64303
|
setRightPanelTab,
|
|
64213
64304
|
rightInspectorPanes,
|
|
@@ -64226,9 +64317,10 @@ function PanelLayoutProvider({
|
|
|
64226
64317
|
rightWidth,
|
|
64227
64318
|
adjustPanelWidth,
|
|
64228
64319
|
leftCollapsed,
|
|
64229
|
-
setLeftCollapsed,
|
|
64230
64320
|
rightCollapsed,
|
|
64231
64321
|
setRightCollapsed,
|
|
64322
|
+
effectiveLeftCollapsed,
|
|
64323
|
+
effectiveRightCollapsed,
|
|
64232
64324
|
rightPanelTab,
|
|
64233
64325
|
setRightPanelTab,
|
|
64234
64326
|
rightInspectorPanes,
|
|
@@ -64244,9 +64336,10 @@ function PanelLayoutProvider({
|
|
|
64244
64336
|
rightWidth,
|
|
64245
64337
|
adjustPanelWidth,
|
|
64246
64338
|
leftCollapsed,
|
|
64247
|
-
setLeftCollapsed,
|
|
64248
64339
|
rightCollapsed,
|
|
64249
64340
|
setRightCollapsed,
|
|
64341
|
+
effectiveLeftCollapsed,
|
|
64342
|
+
effectiveRightCollapsed,
|
|
64250
64343
|
rightPanelTab,
|
|
64251
64344
|
setRightPanelTab,
|
|
64252
64345
|
rightInspectorPanes,
|
|
@@ -64266,7 +64359,7 @@ import {
|
|
|
64266
64359
|
createContext as createContext9,
|
|
64267
64360
|
useCallback as useCallback119,
|
|
64268
64361
|
useContext as useContext9,
|
|
64269
|
-
useEffect as
|
|
64362
|
+
useEffect as useEffect93,
|
|
64270
64363
|
useMemo as useMemo57,
|
|
64271
64364
|
useRef as useRef122,
|
|
64272
64365
|
useState as useState99
|
|
@@ -64304,7 +64397,7 @@ function useViewModeState() {
|
|
|
64304
64397
|
}
|
|
64305
64398
|
return true;
|
|
64306
64399
|
}, []);
|
|
64307
|
-
|
|
64400
|
+
useEffect93(() => {
|
|
64308
64401
|
const onPopState = () => {
|
|
64309
64402
|
const mode = readViewModeFromUrl();
|
|
64310
64403
|
if (mode !== viewMode && !canSetViewMode(mode)) {
|
|
@@ -64586,6 +64679,9 @@ function ViewModeToggle() {
|
|
|
64586
64679
|
}
|
|
64587
64680
|
);
|
|
64588
64681
|
}
|
|
64682
|
+
function shouldOpenInspector(effectiveRightCollapsed, inspectorPanelActive) {
|
|
64683
|
+
return effectiveRightCollapsed || !inspectorPanelActive;
|
|
64684
|
+
}
|
|
64589
64685
|
function StudioHeader({
|
|
64590
64686
|
captureFrameHref,
|
|
64591
64687
|
captureFrameFilename,
|
|
@@ -64597,7 +64693,7 @@ function StudioHeader({
|
|
|
64597
64693
|
onExport
|
|
64598
64694
|
}) {
|
|
64599
64695
|
const { projectId, editHistory, handleUndo, handleRedo, renderQueue } = useStudioShellContext();
|
|
64600
|
-
const {
|
|
64696
|
+
const { effectiveRightCollapsed, setRightCollapsed, setRightPanelTab } = usePanelLayoutContext();
|
|
64601
64697
|
const isRendering = renderQueue.isRendering;
|
|
64602
64698
|
return /* @__PURE__ */ jsxs118("div", { className: "flex items-center justify-between h-10 px-3 bg-neutral-900 border-b border-neutral-800 flex-shrink-0", children: [
|
|
64603
64699
|
/* @__PURE__ */ jsxs118("div", { className: "flex items-center gap-3", children: [
|
|
@@ -64707,7 +64803,7 @@ function StudioHeader({
|
|
|
64707
64803
|
{
|
|
64708
64804
|
type: "button",
|
|
64709
64805
|
onClick: () => {
|
|
64710
|
-
if (
|
|
64806
|
+
if (shouldOpenInspector(effectiveRightCollapsed, inspectorPanelActive)) {
|
|
64711
64807
|
trackStudioEvent("panel_toggle", { panel: "inspector", collapsed: false });
|
|
64712
64808
|
setRightPanelTab("design");
|
|
64713
64809
|
setRightCollapsed(false);
|
|
@@ -64766,10 +64862,10 @@ function StudioHeader({
|
|
|
64766
64862
|
}
|
|
64767
64863
|
|
|
64768
64864
|
// src/hooks/useGestureCommit.ts
|
|
64769
|
-
import { useState as useState101, useCallback as useCallback121, useRef as useRef125, useEffect as
|
|
64865
|
+
import { useState as useState101, useCallback as useCallback121, useRef as useRef125, useEffect as useEffect95 } from "react";
|
|
64770
64866
|
|
|
64771
64867
|
// src/hooks/useGestureRecording.ts
|
|
64772
|
-
import { useCallback as useCallback120, useEffect as
|
|
64868
|
+
import { useCallback as useCallback120, useEffect as useEffect94, useRef as useRef124, useState as useState100 } from "react";
|
|
64773
64869
|
function readBasePosition(element, iframeEl) {
|
|
64774
64870
|
let baseOpacity = 1;
|
|
64775
64871
|
let baseScale = 1;
|
|
@@ -64918,7 +65014,7 @@ function useGestureRecording() {
|
|
|
64918
65014
|
const refs = useRef124(createRecordingRefs());
|
|
64919
65015
|
const samplesRef = useRef124(refs.current.samples);
|
|
64920
65016
|
const trailRef = useRef124(refs.current.trail);
|
|
64921
|
-
|
|
65017
|
+
useEffect94(() => {
|
|
64922
65018
|
const r = refs.current;
|
|
64923
65019
|
return () => {
|
|
64924
65020
|
isRecordingRef.current = false;
|
|
@@ -65301,7 +65397,7 @@ function useGestureCommit({
|
|
|
65301
65397
|
const recordingStartTimeRef = useRef125(0);
|
|
65302
65398
|
const commitInFlightRef = useRef125(false);
|
|
65303
65399
|
const capturedSelectionRef = useRef125(null);
|
|
65304
|
-
|
|
65400
|
+
useEffect95(() => () => clearInterval(recordingAutoStopRef.current), []);
|
|
65305
65401
|
const stopAndCommitRecording = useCallback121(async () => {
|
|
65306
65402
|
clearInterval(recordingAutoStopRef.current);
|
|
65307
65403
|
if (commitInFlightRef.current) {
|
|
@@ -65646,7 +65742,7 @@ import {
|
|
|
65646
65742
|
} from "react";
|
|
65647
65743
|
|
|
65648
65744
|
// src/components/sidebar/CompositionsTab.tsx
|
|
65649
|
-
import { memo as memo37, useCallback as useCallback122, useEffect as
|
|
65745
|
+
import { memo as memo37, useCallback as useCallback122, useEffect as useEffect96, useRef as useRef126, useState as useState102 } from "react";
|
|
65650
65746
|
import { jsx as jsx144, jsxs as jsxs120 } from "react/jsx-runtime";
|
|
65651
65747
|
var DEFAULT_PREVIEW_STAGE = { width: 1920, height: 1080 };
|
|
65652
65748
|
var CARD_W = 80;
|
|
@@ -65764,10 +65860,10 @@ function CompCard({
|
|
|
65764
65860
|
});
|
|
65765
65861
|
const thumbnailOffsetX = (CARD_W - stageSize.width * previewScale) / 2;
|
|
65766
65862
|
const thumbnailOffsetY = (CARD_H - stageSize.height * previewScale) / 2;
|
|
65767
|
-
|
|
65863
|
+
useEffect96(() => {
|
|
65768
65864
|
if (hovered) requestIframePlaybackSync(true);
|
|
65769
65865
|
}, [hovered, requestIframePlaybackSync]);
|
|
65770
|
-
|
|
65866
|
+
useEffect96(() => {
|
|
65771
65867
|
return () => {
|
|
65772
65868
|
if (hoverTimer.current) clearTimeout(hoverTimer.current);
|
|
65773
65869
|
if (syncTimer.current) clearTimeout(syncTimer.current);
|
|
@@ -65943,7 +66039,7 @@ var CompositionsTab = memo37(function CompositionsTab2({
|
|
|
65943
66039
|
});
|
|
65944
66040
|
|
|
65945
66041
|
// src/components/sidebar/AssetsTab.tsx
|
|
65946
|
-
import { memo as memo38, useState as useState107, useCallback as useCallback125, useRef as useRef129, useMemo as useMemo60, useEffect as
|
|
66042
|
+
import { memo as memo38, useState as useState107, useCallback as useCallback125, useRef as useRef129, useMemo as useMemo60, useEffect as useEffect101 } from "react";
|
|
65947
66043
|
|
|
65948
66044
|
// src/components/sidebar/assetHelpers.ts
|
|
65949
66045
|
function getCategory(path) {
|
|
@@ -65993,7 +66089,7 @@ var CATEGORY_LABELS = {
|
|
|
65993
66089
|
var FILTER_ORDER = ["audio", "images", "video", "fonts"];
|
|
65994
66090
|
|
|
65995
66091
|
// src/components/sidebar/AudioRow.tsx
|
|
65996
|
-
import { useState as useState103, useRef as useRef127, useEffect as
|
|
66092
|
+
import { useState as useState103, useRef as useRef127, useEffect as useEffect97, useCallback as useCallback123 } from "react";
|
|
65997
66093
|
|
|
65998
66094
|
// src/components/sidebar/AssetContextMenu.tsx
|
|
65999
66095
|
import { jsx as jsx145, jsxs as jsxs121 } from "react/jsx-runtime";
|
|
@@ -66168,14 +66264,14 @@ function AudioRow({
|
|
|
66168
66264
|
clearPreviewAsset
|
|
66169
66265
|
]
|
|
66170
66266
|
);
|
|
66171
|
-
|
|
66267
|
+
useEffect97(() => {
|
|
66172
66268
|
return () => {
|
|
66173
66269
|
cancelAnimationFrame(animRef.current);
|
|
66174
66270
|
audioRef.current?.pause();
|
|
66175
66271
|
actxRef.current?.close();
|
|
66176
66272
|
};
|
|
66177
66273
|
}, []);
|
|
66178
|
-
|
|
66274
|
+
useEffect97(() => {
|
|
66179
66275
|
if (playing) {
|
|
66180
66276
|
const barCount = 24;
|
|
66181
66277
|
const loop = () => {
|
|
@@ -66313,7 +66409,7 @@ function AudioRow({
|
|
|
66313
66409
|
}
|
|
66314
66410
|
|
|
66315
66411
|
// src/components/sidebar/GlobalAssetsView.tsx
|
|
66316
|
-
import { useEffect as
|
|
66412
|
+
import { useEffect as useEffect98, useMemo as useMemo59, useState as useState104 } from "react";
|
|
66317
66413
|
import { jsx as jsx147, jsxs as jsxs123 } from "react/jsx-runtime";
|
|
66318
66414
|
function globalAssetRows(records, query = "") {
|
|
66319
66415
|
const q = query.trim().toLowerCase();
|
|
@@ -66329,7 +66425,7 @@ function globalAssetRows(records, query = "") {
|
|
|
66329
66425
|
}
|
|
66330
66426
|
function GlobalAssetsView({ searchQuery }) {
|
|
66331
66427
|
const [records, setRecords] = useState104(null);
|
|
66332
|
-
|
|
66428
|
+
useEffect98(() => {
|
|
66333
66429
|
let cancelled = false;
|
|
66334
66430
|
fetch("/api/assets/global").then((r) => r.ok ? r.json() : { assets: [] }).then((d) => {
|
|
66335
66431
|
if (!cancelled) setRecords(Array.isArray(d.assets) ? d.assets : []);
|
|
@@ -66372,10 +66468,10 @@ function GlobalAssetsView({ searchQuery }) {
|
|
|
66372
66468
|
}
|
|
66373
66469
|
|
|
66374
66470
|
// src/components/sidebar/AssetCard.tsx
|
|
66375
|
-
import { useState as useState106, useEffect as
|
|
66471
|
+
import { useState as useState106, useEffect as useEffect100, useRef as useRef128, useCallback as useCallback124 } from "react";
|
|
66376
66472
|
|
|
66377
66473
|
// src/components/ui/VideoFrameThumbnail.tsx
|
|
66378
|
-
import { useState as useState105, useEffect as
|
|
66474
|
+
import { useState as useState105, useEffect as useEffect99 } from "react";
|
|
66379
66475
|
import { jsx as jsx148 } from "react/jsx-runtime";
|
|
66380
66476
|
function VideoFrameThumbnail({
|
|
66381
66477
|
src,
|
|
@@ -66383,7 +66479,7 @@ function VideoFrameThumbnail({
|
|
|
66383
66479
|
}) {
|
|
66384
66480
|
const [frame, setFrame] = useState105(null);
|
|
66385
66481
|
const [failed2, setFailed] = useState105(false);
|
|
66386
|
-
|
|
66482
|
+
useEffect99(() => {
|
|
66387
66483
|
setFailed(false);
|
|
66388
66484
|
const video = document.createElement("video");
|
|
66389
66485
|
video.crossOrigin = "anonymous";
|
|
@@ -66436,7 +66532,7 @@ function openAssetContextMenu(e, setContextMenu) {
|
|
|
66436
66532
|
}
|
|
66437
66533
|
function useProbedDuration(src, skip) {
|
|
66438
66534
|
const [duration, setDuration] = useState106(void 0);
|
|
66439
|
-
|
|
66535
|
+
useEffect100(() => {
|
|
66440
66536
|
if (skip) return;
|
|
66441
66537
|
let cancelled = false;
|
|
66442
66538
|
let retryTimer;
|
|
@@ -66709,7 +66805,7 @@ var AssetsTab = memo38(function AssetsTab2({
|
|
|
66709
66805
|
const [manifest, setManifest] = useState107(/* @__PURE__ */ new Map());
|
|
66710
66806
|
const manifest404Ref = useRef129(/* @__PURE__ */ new Set());
|
|
66711
66807
|
const assetsKey = assets.join("|");
|
|
66712
|
-
|
|
66808
|
+
useEffect101(() => {
|
|
66713
66809
|
if (manifest404Ref.current.has(projectId)) return;
|
|
66714
66810
|
let cancelled = false;
|
|
66715
66811
|
fetch(`/api/projects/${projectId}/preview/.media/manifest.jsonl`).then((r) => {
|
|
@@ -67028,7 +67124,7 @@ var AssetsTab = memo38(function AssetsTab2({
|
|
|
67028
67124
|
});
|
|
67029
67125
|
|
|
67030
67126
|
// src/components/sidebar/BlocksTab.tsx
|
|
67031
|
-
import { memo as memo39, useState as useState108, useCallback as useCallback126, useRef as useRef130, useEffect as
|
|
67127
|
+
import { memo as memo39, useState as useState108, useCallback as useCallback126, useRef as useRef130, useEffect as useEffect102 } from "react";
|
|
67032
67128
|
import { createPortal as createPortal7 } from "react-dom";
|
|
67033
67129
|
import { jsx as jsx151, jsxs as jsxs126 } from "react/jsx-runtime";
|
|
67034
67130
|
var BlocksTab = memo39(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
|
|
@@ -67257,7 +67353,7 @@ function BlockCard({
|
|
|
67257
67353
|
setHovered(false);
|
|
67258
67354
|
onPreview?.(null);
|
|
67259
67355
|
}, [onPreview]);
|
|
67260
|
-
|
|
67356
|
+
useEffect102(() => {
|
|
67261
67357
|
return () => {
|
|
67262
67358
|
if (hoverTimer.current) clearTimeout(hoverTimer.current);
|
|
67263
67359
|
};
|
|
@@ -67419,7 +67515,7 @@ function PromptPreviewModal({
|
|
|
67419
67515
|
const [value, setValue] = useState108(prompt);
|
|
67420
67516
|
const [copied, setCopied] = useState108(false);
|
|
67421
67517
|
const textareaRef = useRef130(null);
|
|
67422
|
-
|
|
67518
|
+
useEffect102(() => {
|
|
67423
67519
|
requestAnimationFrame(() => textareaRef.current?.focus());
|
|
67424
67520
|
}, []);
|
|
67425
67521
|
const handleCopy = useCallback126(() => {
|
|
@@ -67870,7 +67966,7 @@ function StudioLeftSidebar({
|
|
|
67870
67966
|
onAddCompositionToTimeline
|
|
67871
67967
|
}) {
|
|
67872
67968
|
const {
|
|
67873
|
-
|
|
67969
|
+
effectiveLeftCollapsed,
|
|
67874
67970
|
leftWidth,
|
|
67875
67971
|
adjustPanelWidth,
|
|
67876
67972
|
toggleLeftSidebar,
|
|
@@ -67903,7 +67999,7 @@ function StudioLeftSidebar({
|
|
|
67903
67999
|
},
|
|
67904
68000
|
[renderQueue, waitForPendingDomEditSaves]
|
|
67905
68001
|
);
|
|
67906
|
-
if (
|
|
68002
|
+
if (effectiveLeftCollapsed) {
|
|
67907
68003
|
return /* @__PURE__ */ jsx154("div", { className: "mr-0.5 flex w-10 flex-shrink-0 flex-col items-center rounded-lg border border-neutral-800/50 bg-neutral-950 pt-1", children: /* @__PURE__ */ jsx154(
|
|
67908
68004
|
"button",
|
|
67909
68005
|
{
|
|
@@ -68015,10 +68111,10 @@ function StudioLeftSidebar({
|
|
|
68015
68111
|
}
|
|
68016
68112
|
|
|
68017
68113
|
// src/components/StudioRightPanel.tsx
|
|
68018
|
-
import { useCallback as useCallback144, useEffect as
|
|
68114
|
+
import { useCallback as useCallback144, useEffect as useEffect109, useRef as useRef137 } from "react";
|
|
68019
68115
|
|
|
68020
68116
|
// src/components/editor/LayersPanel.tsx
|
|
68021
|
-
import { memo as memo41, useState as useState112, useCallback as useCallback130, useEffect as
|
|
68117
|
+
import { memo as memo41, useState as useState112, useCallback as useCallback130, useEffect as useEffect103, useRef as useRef133 } from "react";
|
|
68022
68118
|
|
|
68023
68119
|
// src/components/editor/useLayerDrag.ts
|
|
68024
68120
|
import { useRef as useRef132, useState as useState111, useCallback as useCallback129 } from "react";
|
|
@@ -68321,10 +68417,10 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
68321
68417
|
});
|
|
68322
68418
|
setLayers(sortLayersByZIndex(items));
|
|
68323
68419
|
}, [previewIframeRef, activeCompPath, isMasterView, activeGroupElement, setActiveGroupElement]);
|
|
68324
|
-
|
|
68420
|
+
useEffect103(() => {
|
|
68325
68421
|
collectLayers();
|
|
68326
68422
|
}, [collectLayers, refreshKey, zEditVersion]);
|
|
68327
|
-
|
|
68423
|
+
useEffect103(() => {
|
|
68328
68424
|
const iframe = previewIframeRef.current;
|
|
68329
68425
|
if (!iframe) return;
|
|
68330
68426
|
const handleLoad = () => {
|
|
@@ -68334,13 +68430,13 @@ var LayersPanel = memo41(function LayersPanel2() {
|
|
|
68334
68430
|
iframe.addEventListener("load", handleLoad);
|
|
68335
68431
|
return () => iframe.removeEventListener("load", handleLoad);
|
|
68336
68432
|
}, [previewIframeRef, collectLayers]);
|
|
68337
|
-
|
|
68433
|
+
useEffect103(() => {
|
|
68338
68434
|
if (!compositionLoading) {
|
|
68339
68435
|
const timer = setTimeout(collectLayers, 100);
|
|
68340
68436
|
return () => clearTimeout(timer);
|
|
68341
68437
|
}
|
|
68342
68438
|
}, [compositionLoading, collectLayers]);
|
|
68343
|
-
|
|
68439
|
+
useEffect103(() => {
|
|
68344
68440
|
const throttle = createRafThrottle(collectLayers, 100);
|
|
68345
68441
|
const unsubscribe = liveTime.subscribe(throttle.invoke);
|
|
68346
68442
|
return () => {
|
|
@@ -69186,7 +69282,7 @@ function ParamControl({
|
|
|
69186
69282
|
}
|
|
69187
69283
|
|
|
69188
69284
|
// src/components/renders/RenderQueue.tsx
|
|
69189
|
-
import { memo as memo46, useState as useState116, useRef as useRef134, useEffect as
|
|
69285
|
+
import { memo as memo46, useState as useState116, useRef as useRef134, useEffect as useEffect104, useLayoutEffect as useLayoutEffect8, useId as useId6 } from "react";
|
|
69190
69286
|
import { createPortal as createPortal8 } from "react-dom";
|
|
69191
69287
|
import { CANVAS_DIMENSIONS } from "@hyperframes/parsers";
|
|
69192
69288
|
|
|
@@ -69482,7 +69578,7 @@ function FormatInfoTooltip({ format }) {
|
|
|
69482
69578
|
const hide = () => {
|
|
69483
69579
|
timeoutRef.current = setTimeout(() => setOpen(false), 120);
|
|
69484
69580
|
};
|
|
69485
|
-
|
|
69581
|
+
useEffect104(() => () => clearTimeout(timeoutRef.current), []);
|
|
69486
69582
|
useLayoutEffect8(() => {
|
|
69487
69583
|
if (!open) return;
|
|
69488
69584
|
const el = triggerRef.current;
|
|
@@ -69496,7 +69592,7 @@ function FormatInfoTooltip({ format }) {
|
|
|
69496
69592
|
)
|
|
69497
69593
|
);
|
|
69498
69594
|
}, [open]);
|
|
69499
|
-
|
|
69595
|
+
useEffect104(() => {
|
|
69500
69596
|
if (!open) return;
|
|
69501
69597
|
const onKeyDown = (e) => {
|
|
69502
69598
|
if (e.key === "Escape") setOpen(false);
|
|
@@ -69708,7 +69804,7 @@ var RenderQueue = memo46(function RenderQueue2({
|
|
|
69708
69804
|
compositionDimensions
|
|
69709
69805
|
}) {
|
|
69710
69806
|
const listRef = useRef134(null);
|
|
69711
|
-
|
|
69807
|
+
useEffect104(() => {
|
|
69712
69808
|
if (listRef.current) {
|
|
69713
69809
|
listRef.current.scrollTo({ top: listRef.current.scrollHeight, behavior: "smooth" });
|
|
69714
69810
|
}
|
|
@@ -69816,7 +69912,7 @@ var RenderQueue = memo46(function RenderQueue2({
|
|
|
69816
69912
|
});
|
|
69817
69913
|
|
|
69818
69914
|
// src/components/panels/SlideshowPanel.tsx
|
|
69819
|
-
import { useState as useState118, useEffect as
|
|
69915
|
+
import { useState as useState118, useEffect as useEffect105, useCallback as useCallback136, useRef as useRef135 } from "react";
|
|
69820
69916
|
import { parseSlideshowManifest } from "@hyperframes/core/slideshow";
|
|
69821
69917
|
|
|
69822
69918
|
// src/components/panels/SlideshowSubPanels.tsx
|
|
@@ -70455,7 +70551,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
70455
70551
|
const { domEditSelection } = useDomEditSelectionContext();
|
|
70456
70552
|
const manifestRef = useRef135(manifest);
|
|
70457
70553
|
const notesCtrlRef = useRef135(makeSlideshowNotesController());
|
|
70458
|
-
|
|
70554
|
+
useEffect105(() => {
|
|
70459
70555
|
if (!compHtml) {
|
|
70460
70556
|
notesCtrlRef.current.flush();
|
|
70461
70557
|
setManifest({ slides: [] });
|
|
@@ -70489,7 +70585,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
70489
70585
|
},
|
|
70490
70586
|
[onPersistNotes]
|
|
70491
70587
|
);
|
|
70492
|
-
|
|
70588
|
+
useEffect105(() => {
|
|
70493
70589
|
const ctrl = notesCtrlRef.current;
|
|
70494
70590
|
return () => {
|
|
70495
70591
|
ctrl.flush();
|
|
@@ -70709,7 +70805,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
|
|
|
70709
70805
|
}
|
|
70710
70806
|
|
|
70711
70807
|
// src/components/panels/VariablesPanel.tsx
|
|
70712
|
-
import { memo as memo47, useCallback as useCallback140, useEffect as
|
|
70808
|
+
import { memo as memo47, useCallback as useCallback140, useEffect as useEffect107, useMemo as useMemo61, useState as useState122 } from "react";
|
|
70713
70809
|
|
|
70714
70810
|
// src/hooks/useVariablesPersist.ts
|
|
70715
70811
|
import { useCallback as useCallback137 } from "react";
|
|
@@ -70763,7 +70859,7 @@ function useVariablesPersist({
|
|
|
70763
70859
|
import { useCallback as useCallback139, useState as useState121 } from "react";
|
|
70764
70860
|
|
|
70765
70861
|
// src/hooks/useProjectCompositionVariables.ts
|
|
70766
|
-
import { useCallback as useCallback138, useEffect as
|
|
70862
|
+
import { useCallback as useCallback138, useEffect as useEffect106, useState as useState119 } from "react";
|
|
70767
70863
|
import { openComposition as openComposition4 } from "@hyperframes/sdk";
|
|
70768
70864
|
async function readGroup(path, readProjectFile) {
|
|
70769
70865
|
let content;
|
|
@@ -70787,7 +70883,7 @@ async function readGroup(path, readProjectFile) {
|
|
|
70787
70883
|
}
|
|
70788
70884
|
function useProjectCompositionVariables(fileTree, excludePath, readProjectFile, refreshKey) {
|
|
70789
70885
|
const [groups, setGroups] = useState119([]);
|
|
70790
|
-
|
|
70886
|
+
useEffect106(() => {
|
|
70791
70887
|
let cancelled = false;
|
|
70792
70888
|
const htmlFiles = fileTree.filter((p) => p.endsWith(".html") && p !== excludePath);
|
|
70793
70889
|
void (async () => {
|
|
@@ -71397,7 +71493,7 @@ var VariablesPanel = memo47(function VariablesPanel2({
|
|
|
71397
71493
|
const previewValues = usePreviewVariablesStore((s) => s.values);
|
|
71398
71494
|
const setPreviewValues = usePreviewVariablesStore((s) => s.setValues);
|
|
71399
71495
|
const [revision, setRevision] = useState122(0);
|
|
71400
|
-
|
|
71496
|
+
useEffect107(() => {
|
|
71401
71497
|
if (!sdkSession) return;
|
|
71402
71498
|
return sdkSession.on("change", () => setRevision((r) => r + 1));
|
|
71403
71499
|
}, [sdkSession]);
|
|
@@ -71767,7 +71863,7 @@ function useSlideshowPersist({
|
|
|
71767
71863
|
}
|
|
71768
71864
|
|
|
71769
71865
|
// src/hooks/useSlideshowTabState.ts
|
|
71770
|
-
import { useEffect as
|
|
71866
|
+
import { useEffect as useEffect108, useMemo as useMemo62 } from "react";
|
|
71771
71867
|
import { SLIDESHOW_ISLAND_TYPE as SLIDESHOW_ISLAND_TYPE2, slideshowIslandRegex as slideshowIslandRegex2 } from "@hyperframes/core/slideshow";
|
|
71772
71868
|
function useSlideshowTabState(params) {
|
|
71773
71869
|
const { editingFileContent, previewIframeRef, refreshKey, rightPanelTab, setRightPanelTab } = params;
|
|
@@ -71788,7 +71884,7 @@ function useSlideshowTabState(params) {
|
|
|
71788
71884
|
return [];
|
|
71789
71885
|
}
|
|
71790
71886
|
}, [previewIframeRef, rightPanelTab, refreshKey]);
|
|
71791
|
-
|
|
71887
|
+
useEffect108(() => {
|
|
71792
71888
|
if (rightPanelTab === "slideshow" && !isSlideshowComposition) {
|
|
71793
71889
|
setRightPanelTab("renders");
|
|
71794
71890
|
}
|
|
@@ -72226,7 +72322,7 @@ function StudioRightPanel({
|
|
|
72226
72322
|
handleInspectorSplitResizeEnd
|
|
72227
72323
|
} = useInspectorSplitResize();
|
|
72228
72324
|
const backgroundRemovalAbortRef = useRef137(null);
|
|
72229
|
-
|
|
72325
|
+
useEffect109(
|
|
72230
72326
|
() => () => {
|
|
72231
72327
|
backgroundRemovalAbortRef.current?.abort();
|
|
72232
72328
|
},
|
|
@@ -72594,7 +72690,7 @@ function StudioRightPanel({
|
|
|
72594
72690
|
}
|
|
72595
72691
|
|
|
72596
72692
|
// src/components/TimelineToolbar.tsx
|
|
72597
|
-
import { useEffect as
|
|
72693
|
+
import { useEffect as useEffect111, useRef as useRef138 } from "react";
|
|
72598
72694
|
import { Image as Image2, Magnet, MagnifyingGlassMinus, MagnifyingGlassPlus } from "@phosphor-icons/react";
|
|
72599
72695
|
|
|
72600
72696
|
// src/hooks/useEnableKeyframes.ts
|
|
@@ -72933,7 +73029,7 @@ function useEnableKeyframes(sessionRef) {
|
|
|
72933
73029
|
}
|
|
72934
73030
|
|
|
72935
73031
|
// src/hooks/useKeyframeKeyboard.ts
|
|
72936
|
-
import { useEffect as
|
|
73032
|
+
import { useEffect as useEffect110, useCallback as useCallback146 } from "react";
|
|
72937
73033
|
function isTextInput(el) {
|
|
72938
73034
|
if (!el) return false;
|
|
72939
73035
|
const tag = el.tagName;
|
|
@@ -73001,7 +73097,7 @@ function useKeyframeKeyboard({
|
|
|
73001
73097
|
onNudgeKeyframe
|
|
73002
73098
|
]
|
|
73003
73099
|
);
|
|
73004
|
-
|
|
73100
|
+
useEffect110(() => {
|
|
73005
73101
|
if (!enabled2) return;
|
|
73006
73102
|
window.addEventListener("keydown", handler, { capture: true });
|
|
73007
73103
|
return () => window.removeEventListener("keydown", handler, { capture: true });
|
|
@@ -73089,7 +73185,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
|
|
|
73089
73185
|
enabled: Boolean(onToggleKeyframe),
|
|
73090
73186
|
onAddKeyframe: onToggleKeyframe
|
|
73091
73187
|
});
|
|
73092
|
-
|
|
73188
|
+
useEffect111(() => {
|
|
73093
73189
|
const onKeyDown = (e) => {
|
|
73094
73190
|
if (e.key !== "n" && e.key !== "N") return;
|
|
73095
73191
|
if (e.metaKey || e.ctrlKey || e.altKey) return;
|
|
@@ -73367,7 +73463,7 @@ import { useState as useState131 } from "react";
|
|
|
73367
73463
|
import { Copy as Copy2, Check as Check2 } from "@phosphor-icons/react";
|
|
73368
73464
|
|
|
73369
73465
|
// src/hooks/useStoryboard.ts
|
|
73370
|
-
import { useCallback as useCallback147, useEffect as
|
|
73466
|
+
import { useCallback as useCallback147, useEffect as useEffect112, useRef as useRef139, useState as useState124 } from "react";
|
|
73371
73467
|
function useStoryboard(projectId) {
|
|
73372
73468
|
const [data, setData] = useState124(null);
|
|
73373
73469
|
const [loading, setLoading] = useState124(true);
|
|
@@ -73376,7 +73472,7 @@ function useStoryboard(projectId) {
|
|
|
73376
73472
|
const hasDataRef = useRef139(false);
|
|
73377
73473
|
const lastProjectRef = useRef139(null);
|
|
73378
73474
|
const reload = useCallback147(() => setReloadKey((k) => k + 1), []);
|
|
73379
|
-
|
|
73475
|
+
useEffect112(() => {
|
|
73380
73476
|
if (!projectId) return;
|
|
73381
73477
|
let cancelled = false;
|
|
73382
73478
|
if (lastProjectRef.current !== projectId) {
|
|
@@ -73408,7 +73504,7 @@ function useStoryboard(projectId) {
|
|
|
73408
73504
|
}
|
|
73409
73505
|
|
|
73410
73506
|
// src/hooks/useProjectSignaturePoll.ts
|
|
73411
|
-
import { useEffect as
|
|
73507
|
+
import { useEffect as useEffect113, useRef as useRef140 } from "react";
|
|
73412
73508
|
var POLL_INTERVAL_MS = 2e3;
|
|
73413
73509
|
async function fetchProjectSignature(projectId) {
|
|
73414
73510
|
try {
|
|
@@ -73425,7 +73521,7 @@ function useProjectSignaturePoll(projectId, currentSignature, onChange) {
|
|
|
73425
73521
|
const onChangeRef = useRef140(onChange);
|
|
73426
73522
|
signatureRef.current = currentSignature;
|
|
73427
73523
|
onChangeRef.current = onChange;
|
|
73428
|
-
|
|
73524
|
+
useEffect113(() => {
|
|
73429
73525
|
if (!projectId) return;
|
|
73430
73526
|
let disposed = false;
|
|
73431
73527
|
let inFlight = false;
|
|
@@ -73452,7 +73548,7 @@ function useProjectSignaturePoll(projectId, currentSignature, onChange) {
|
|
|
73452
73548
|
}
|
|
73453
73549
|
|
|
73454
73550
|
// src/components/storyboard/StoryboardLoaded.tsx
|
|
73455
|
-
import { useEffect as
|
|
73551
|
+
import { useEffect as useEffect119, useMemo as useMemo65, useState as useState130 } from "react";
|
|
73456
73552
|
|
|
73457
73553
|
// src/components/storyboard/StoryboardDirection.tsx
|
|
73458
73554
|
import { jsx as jsx172, jsxs as jsxs144 } from "react/jsx-runtime";
|
|
@@ -73475,7 +73571,7 @@ function StoryboardDirection({ globals, frameCount }) {
|
|
|
73475
73571
|
}
|
|
73476
73572
|
|
|
73477
73573
|
// src/components/storyboard/FramePoster.tsx
|
|
73478
|
-
import { useEffect as
|
|
73574
|
+
import { useEffect as useEffect114, useState as useState125 } from "react";
|
|
73479
73575
|
import { jsx as jsx173 } from "react/jsx-runtime";
|
|
73480
73576
|
function FramePoster({
|
|
73481
73577
|
projectId,
|
|
@@ -73486,7 +73582,7 @@ function FramePoster({
|
|
|
73486
73582
|
posterVersion
|
|
73487
73583
|
}) {
|
|
73488
73584
|
const [failed2, setFailed] = useState125(false);
|
|
73489
|
-
|
|
73585
|
+
useEffect114(() => setFailed(false), [src, seconds, posterVersion]);
|
|
73490
73586
|
if (failed2) {
|
|
73491
73587
|
return /* @__PURE__ */ jsx173("div", { className: "flex h-full w-full items-center justify-center text-[11px] text-neutral-600", children: "Preview unavailable" });
|
|
73492
73588
|
}
|
|
@@ -73685,7 +73781,7 @@ function StoryboardScriptPanel({ script }) {
|
|
|
73685
73781
|
}
|
|
73686
73782
|
|
|
73687
73783
|
// src/components/storyboard/StoryboardSourceEditor.tsx
|
|
73688
|
-
import { useCallback as useCallback148, useEffect as
|
|
73784
|
+
import { useCallback as useCallback148, useEffect as useEffect115, useMemo as useMemo63, useRef as useRef141, useState as useState126 } from "react";
|
|
73689
73785
|
import { marked } from "marked";
|
|
73690
73786
|
import DOMPurify from "dompurify";
|
|
73691
73787
|
import { jsx as jsx177, jsxs as jsxs147 } from "react/jsx-runtime";
|
|
@@ -73697,7 +73793,7 @@ function useEditableFile(path, onSaved) {
|
|
|
73697
73793
|
const [loading, setLoading] = useState126(true);
|
|
73698
73794
|
const [saving, setSaving] = useState126(false);
|
|
73699
73795
|
const [error, setError] = useState126(null);
|
|
73700
|
-
|
|
73796
|
+
useEffect115(() => {
|
|
73701
73797
|
if (!path) return;
|
|
73702
73798
|
let cancelled = false;
|
|
73703
73799
|
setLoading(true);
|
|
@@ -73735,7 +73831,7 @@ function hardenLinks(node) {
|
|
|
73735
73831
|
function useMarkdownPreview(source) {
|
|
73736
73832
|
const [debounced, setDebounced] = useState126(source);
|
|
73737
73833
|
const primed = useRef141(false);
|
|
73738
|
-
|
|
73834
|
+
useEffect115(() => {
|
|
73739
73835
|
if (!primed.current && source !== "") {
|
|
73740
73836
|
primed.current = true;
|
|
73741
73837
|
setDebounced(source);
|
|
@@ -73767,8 +73863,8 @@ function StoryboardSourceEditor({
|
|
|
73767
73863
|
const activePath = files.some((f) => f.path === selected) ? selected : files[0]?.path ?? "";
|
|
73768
73864
|
const file = useEditableFile(activePath, onSaved);
|
|
73769
73865
|
const previewHtml = useMarkdownPreview(file.content);
|
|
73770
|
-
|
|
73771
|
-
|
|
73866
|
+
useEffect115(() => onDirtyChange?.(file.dirty), [onDirtyChange, file.dirty]);
|
|
73867
|
+
useEffect115(() => {
|
|
73772
73868
|
if (!file.dirty) return;
|
|
73773
73869
|
const onBeforeUnload = (event) => {
|
|
73774
73870
|
event.preventDefault();
|
|
@@ -73840,11 +73936,11 @@ function StoryboardSourceEditor({
|
|
|
73840
73936
|
}
|
|
73841
73937
|
|
|
73842
73938
|
// src/components/storyboard/StoryboardFrameFocus.tsx
|
|
73843
|
-
import { useCallback as useCallback149, useEffect as
|
|
73939
|
+
import { useCallback as useCallback149, useEffect as useEffect117, useState as useState128 } from "react";
|
|
73844
73940
|
import { setFrameVoiceover } from "@hyperframes/core/storyboard";
|
|
73845
73941
|
|
|
73846
73942
|
// src/components/storyboard/AgentChatMessageButton.tsx
|
|
73847
|
-
import { useEffect as
|
|
73943
|
+
import { useEffect as useEffect116, useState as useState127 } from "react";
|
|
73848
73944
|
import { jsx as jsx178 } from "react/jsx-runtime";
|
|
73849
73945
|
var APPLY_STORYBOARD_FEEDBACK_MESSAGE = "Read the storyboard feedback I saved in .hyperframes/frame-comments.json and revise the frames.";
|
|
73850
73946
|
function AgentChatMessageButton({
|
|
@@ -73853,7 +73949,7 @@ function AgentChatMessageButton({
|
|
|
73853
73949
|
onCopied
|
|
73854
73950
|
}) {
|
|
73855
73951
|
const [copyState, setCopyState] = useState127("idle");
|
|
73856
|
-
|
|
73952
|
+
useEffect116(() => {
|
|
73857
73953
|
if (copyState !== "copied") return;
|
|
73858
73954
|
const timeout = window.setTimeout(() => setCopyState("again"), 3e3);
|
|
73859
73955
|
return () => window.clearTimeout(timeout);
|
|
@@ -73926,7 +74022,7 @@ function StoryboardFrameFocus({
|
|
|
73926
74022
|
const saved = await applyEdit((src) => setFrameVoiceover(src, frame.index, draft));
|
|
73927
74023
|
if (saved) setSavedVoiceover(draft);
|
|
73928
74024
|
}, [applyEdit, frame.index, draft]);
|
|
73929
|
-
|
|
74025
|
+
useEffect117(() => {
|
|
73930
74026
|
if (!dirty) return;
|
|
73931
74027
|
const onBeforeUnload = (e) => {
|
|
73932
74028
|
e.preventDefault();
|
|
@@ -73938,14 +74034,14 @@ function StoryboardFrameFocus({
|
|
|
73938
74034
|
() => !dirty || window.confirm("Discard unsaved voiceover changes?"),
|
|
73939
74035
|
[dirty]
|
|
73940
74036
|
);
|
|
73941
|
-
|
|
74037
|
+
useEffect117(() => registerViewModeGuard(confirmLeave), [confirmLeave, registerViewModeGuard]);
|
|
73942
74038
|
const handleBack = () => {
|
|
73943
74039
|
if (confirmLeave()) onBack();
|
|
73944
74040
|
};
|
|
73945
74041
|
const handleNavigate = (delta) => {
|
|
73946
74042
|
if (confirmLeave()) onNavigate(delta);
|
|
73947
74043
|
};
|
|
73948
|
-
|
|
74044
|
+
useEffect117(() => {
|
|
73949
74045
|
const onKey = (e) => {
|
|
73950
74046
|
const el = document.activeElement;
|
|
73951
74047
|
if (el instanceof HTMLTextAreaElement || el instanceof HTMLInputElement) return;
|
|
@@ -74417,7 +74513,7 @@ function progressLabel(summary) {
|
|
|
74417
74513
|
}
|
|
74418
74514
|
|
|
74419
74515
|
// src/components/storyboard/useFrameComments.ts
|
|
74420
|
-
import { useCallback as useCallback150, useEffect as
|
|
74516
|
+
import { useCallback as useCallback150, useEffect as useEffect118, useMemo as useMemo64, useState as useState129 } from "react";
|
|
74421
74517
|
|
|
74422
74518
|
// src/components/storyboard/frameComments.ts
|
|
74423
74519
|
var FRAME_COMMENTS_PATH = ".hyperframes/frame-comments.json";
|
|
@@ -74490,7 +74586,7 @@ function useFrameComments(frames) {
|
|
|
74490
74586
|
} catch {
|
|
74491
74587
|
}
|
|
74492
74588
|
}, [readOptionalProjectFile]);
|
|
74493
|
-
|
|
74589
|
+
useEffect118(() => {
|
|
74494
74590
|
void refreshPending();
|
|
74495
74591
|
const onFocus = () => void refreshPending();
|
|
74496
74592
|
window.addEventListener("focus", onFocus);
|
|
@@ -74551,10 +74647,10 @@ function StoryboardLoaded({
|
|
|
74551
74647
|
const [feedbackMessageCopied, setFeedbackMessageCopied] = useState130(false);
|
|
74552
74648
|
const comments = useFrameComments(data.frames);
|
|
74553
74649
|
const { refreshPending } = comments;
|
|
74554
|
-
|
|
74650
|
+
useEffect119(() => {
|
|
74555
74651
|
void refreshPending();
|
|
74556
74652
|
}, [data.signature, refreshPending]);
|
|
74557
|
-
|
|
74653
|
+
useEffect119(() => {
|
|
74558
74654
|
if (comments.draftCount > 0) setFeedbackMessageCopied(false);
|
|
74559
74655
|
}, [comments.draftCount]);
|
|
74560
74656
|
const saveFeedbackAndCopyMessage = async () => {
|
|
@@ -74903,7 +74999,7 @@ function StudioSplash({ waiting }) {
|
|
|
74903
74999
|
}
|
|
74904
75000
|
|
|
74905
75001
|
// src/hooks/useServerConnection.ts
|
|
74906
|
-
import { useEffect as
|
|
75002
|
+
import { useEffect as useEffect120, useState as useState132 } from "react";
|
|
74907
75003
|
function useServerConnection() {
|
|
74908
75004
|
const [projectId, setProjectId] = useState132(null);
|
|
74909
75005
|
const [resolving, setResolving] = useState132(true);
|
|
@@ -74944,7 +75040,7 @@ function useServerConnection() {
|
|
|
74944
75040
|
if (retryTimer !== null) clearTimeout(retryTimer);
|
|
74945
75041
|
};
|
|
74946
75042
|
});
|
|
74947
|
-
|
|
75043
|
+
useEffect120(() => {
|
|
74948
75044
|
const onHashChange = () => {
|
|
74949
75045
|
const next = parseProjectIdFromHash(window.location.hash);
|
|
74950
75046
|
if (next && next !== projectId) setProjectId(next);
|
|
@@ -74956,9 +75052,9 @@ function useServerConnection() {
|
|
|
74956
75052
|
}
|
|
74957
75053
|
|
|
74958
75054
|
// src/hooks/useStudioSessionStart.ts
|
|
74959
|
-
import { useEffect as
|
|
75055
|
+
import { useEffect as useEffect121 } from "react";
|
|
74960
75056
|
function useStudioSessionStart(projectId, resolving, waitingForServer) {
|
|
74961
|
-
|
|
75057
|
+
useEffect121(() => {
|
|
74962
75058
|
if (resolving || waitingForServer || hasFiredSessionStart()) return;
|
|
74963
75059
|
markSessionStartFired();
|
|
74964
75060
|
trackStudioSessionStart({ has_project: projectId != null });
|
|
@@ -75039,7 +75135,7 @@ function StudioApp() {
|
|
|
75039
75135
|
activeCompPath,
|
|
75040
75136
|
masterCompPath
|
|
75041
75137
|
);
|
|
75042
|
-
|
|
75138
|
+
useEffect122(() => {
|
|
75043
75139
|
if (activeCompPathHydrated) return;
|
|
75044
75140
|
if (!fileManager.fileTreeLoaded) return;
|
|
75045
75141
|
const nextCompPath = normalizeStudioCompositionPath(
|
|
@@ -75313,7 +75409,7 @@ function StudioApp() {
|
|
|
75313
75409
|
} = useInspectorState(
|
|
75314
75410
|
panelLayout.rightPanelTab,
|
|
75315
75411
|
panelLayout.rightInspectorPanes,
|
|
75316
|
-
panelLayout.
|
|
75412
|
+
panelLayout.effectiveRightCollapsed,
|
|
75317
75413
|
isPlaying,
|
|
75318
75414
|
domEditSession.domEditSelection,
|
|
75319
75415
|
gestureState === "recording"
|
|
@@ -75429,7 +75525,7 @@ function StudioApp() {
|
|
|
75429
75525
|
onAddCompositionToTimeline: handleAddCompositionAtPlayhead
|
|
75430
75526
|
}
|
|
75431
75527
|
),
|
|
75432
|
-
right: panelLayout.
|
|
75528
|
+
right: panelLayout.effectiveRightCollapsed ? null : /* @__PURE__ */ jsx184(
|
|
75433
75529
|
StudioRightPanel,
|
|
75434
75530
|
{
|
|
75435
75531
|
designPanelActive,
|