@hyperframes/studio 0.7.59 → 0.7.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/hyperframes-player-Xvx2hkrc.js +459 -0
- package/dist/assets/{index-CrkAdJkb.js → index-2mxh_HSy.js} +201 -201
- package/dist/assets/{index-B995FG46.js → index-BCpoiv9S.js} +1 -1
- package/dist/assets/index-BhWig0mx.css +1 -0
- package/dist/assets/{index-FvzmPhfG.js → index-D-uFclFj.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/index.js +1441 -770
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/App.tsx +4 -9
- package/src/components/DesignPanelPromoteProvider.tsx +27 -1
- package/src/components/StudioHeader.tsx +2 -3
- package/src/components/StudioRightPanel.tsx +47 -28
- package/src/components/editor/PromotableControl.tsx +4 -2
- package/src/components/editor/PropertyPanel.tsx +151 -149
- package/src/components/editor/PropertyPanelFlat.tsx +44 -42
- package/src/components/editor/manualEditingAvailability.test.ts +6 -6
- package/src/components/editor/manualEditingAvailability.ts +5 -3
- package/src/components/editor/propertyPanelFlatColorGradingSection.tsx +2 -2
- package/src/components/editor/propertyPanelFlatMotionSection.tsx +1 -1
- package/src/components/editor/propertyPanelFlatPrimitives.test.tsx +10 -0
- package/src/components/editor/propertyPanelFlatPrimitives.tsx +3 -2
- package/src/components/editor/propertyPanelFlatSelectRow.tsx +7 -1
- package/src/components/editor/propertyPanelFlatStyleHelpers.ts +0 -13
- package/src/components/editor/propertyPanelFlatStyleSections.test.tsx +21 -9
- package/src/components/editor/propertyPanelFlatStyleSections.tsx +15 -32
- package/src/components/editor/propertyPanelFlatTextSection.tsx +3 -3
- package/src/components/editor/propertyPanelInputCoverage.test.tsx +14 -0
- package/src/components/editor/propertyPanelPrimitives.tsx +9 -1
- package/src/components/storyboard/AgentChatMessageButton.test.tsx +47 -0
- package/src/components/storyboard/AgentChatMessageButton.tsx +45 -0
- package/src/components/storyboard/StoryboardFrameFocus.tsx +189 -66
- package/src/components/storyboard/StoryboardLoaded.tsx +121 -23
- package/src/components/storyboard/StoryboardReviewGuide.tsx +300 -0
- package/src/components/storyboard/StoryboardViewModeGuard.test.tsx +170 -0
- package/src/components/storyboard/storyboardReviewStage.test.ts +40 -0
- package/src/components/storyboard/storyboardReviewStage.ts +45 -0
- package/src/components/storyboard/useFrameComments.ts +22 -6
- package/src/contexts/FileManagerContext.tsx +3 -0
- package/src/contexts/PanelLayoutContext.tsx +3 -0
- package/src/contexts/ViewModeContext.tsx +60 -7
- package/src/hooks/timelineEditingHelpers.ts +2 -2
- package/src/hooks/useAddAssetAtPlayhead.test.ts +44 -0
- package/src/hooks/useAddAssetAtPlayhead.ts +21 -0
- package/src/hooks/useDomEditCommits.test.tsx +41 -1
- package/src/hooks/useDomEditCommits.ts +2 -2
- package/src/hooks/useDomEditSession.ts +1 -1
- package/src/hooks/useEditorSave.ts +1 -1
- package/src/hooks/useFileManager.projectOwnership.test.tsx +14 -3
- package/src/hooks/useFileManager.ts +76 -12
- package/src/hooks/usePanelLayout.test.ts +118 -0
- package/src/hooks/usePanelLayout.ts +24 -1
- package/src/hooks/usePreviewPersistence.ts +4 -1
- package/src/hooks/useRazorSplit.history.test.tsx +12 -4
- package/src/hooks/useRazorSplit.test.tsx +88 -0
- package/src/hooks/useRazorSplit.testHelpers.ts +3 -2
- package/src/hooks/useRazorSplit.ts +50 -16
- package/src/hooks/useSlideshowTabState.test.ts +96 -0
- package/src/hooks/useSlideshowTabState.ts +61 -0
- package/src/hooks/useTimelineEditing.ts +2 -0
- package/src/hooks/useTimelineEditingTypes.ts +2 -1
- package/src/hooks/useTimelineGroupEditing.ts +1 -1
- package/src/player/lib/playbackTypes.ts +7 -0
- package/src/player/lib/runtimeProtocol.test.ts +6 -1
- package/src/player/lib/timelineDOM.ts +8 -11
- package/src/player/lib/timelineIframeHelpers.ts +153 -107
- package/src/utils/domEditSaveQueue.test.ts +19 -0
- package/src/utils/domEditSaveQueue.ts +2 -1
- package/src/utils/sdkCutover.test.ts +21 -5
- package/src/utils/sdkEditTransaction.ts +5 -4
- package/src/utils/studioFileHistory.ts +6 -4
- package/src/utils/studioFileVersion.test.ts +36 -0
- package/src/utils/studioFileVersion.ts +23 -0
- package/src/utils/studioSaveDiagnostics.test.ts +18 -0
- package/src/utils/studioSaveDiagnostics.ts +21 -0
- package/dist/assets/hyperframes-player-Bm07FLkl.js +0 -459
- package/dist/assets/index-Dj5p8U_A.css +0 -1
- package/src/components/editor/propertyPanelFlatStyleHelpers.test.ts +0 -23
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/studio",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.61",
|
|
4
4
|
"description": "",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"gsap": "^3.13.0",
|
|
47
47
|
"marked": "^14.1.4",
|
|
48
48
|
"mediabunny": "^1.45.3",
|
|
49
|
-
"@hyperframes/core": "0.7.
|
|
50
|
-
"@hyperframes/
|
|
51
|
-
"@hyperframes/
|
|
52
|
-
"@hyperframes/
|
|
53
|
-
"@hyperframes/
|
|
49
|
+
"@hyperframes/core": "0.7.61",
|
|
50
|
+
"@hyperframes/parsers": "0.7.61",
|
|
51
|
+
"@hyperframes/player": "0.7.61",
|
|
52
|
+
"@hyperframes/sdk": "0.7.61",
|
|
53
|
+
"@hyperframes/studio-server": "0.7.61"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/react": "19",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"vite": "^6.4.2",
|
|
66
66
|
"vitest": "^3.2.4",
|
|
67
67
|
"zustand": "^5.0.0",
|
|
68
|
-
"@hyperframes/producer": "0.7.
|
|
68
|
+
"@hyperframes/producer": "0.7.61"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
71
|
"react": "19",
|
package/src/App.tsx
CHANGED
|
@@ -23,6 +23,7 @@ import { useDomEditSession } from "./hooks/useDomEditSession";
|
|
|
23
23
|
import { useSdkSelectionSync } from "./hooks/useSdkSelectionSync";
|
|
24
24
|
import { useStudioSdkSessions } from "./hooks/useStudioSdkSessions";
|
|
25
25
|
import { useBlockHandlers } from "./hooks/useBlockHandlers";
|
|
26
|
+
import { useAddAssetAtPlayhead } from "./hooks/useAddAssetAtPlayhead";
|
|
26
27
|
import { useAppHotkeys } from "./hooks/useAppHotkeys";
|
|
27
28
|
import { useClipboard } from "./hooks/useClipboard";
|
|
28
29
|
import { deleteSelectedKeyframes } from "./hooks/timelineEditingHelpers";
|
|
@@ -64,7 +65,6 @@ import {
|
|
|
64
65
|
} from "./utils/studioUrlState";
|
|
65
66
|
import { trackStudioSessionStart } from "./telemetry/events";
|
|
66
67
|
import { hasFiredSessionStart, markSessionStartFired } from "./telemetry/config";
|
|
67
|
-
|
|
68
68
|
type CanvasRect = { left: number; top: number; width: number; height: number };
|
|
69
69
|
// fallow-ignore-next-line complexity
|
|
70
70
|
export function StudioApp() {
|
|
@@ -166,6 +166,7 @@ export function StudioApp() {
|
|
|
166
166
|
timelineElements,
|
|
167
167
|
showToast,
|
|
168
168
|
writeProjectFile: fileManager.writeProjectFile,
|
|
169
|
+
observeProjectFileVersion: fileManager.observeProjectFileVersion,
|
|
169
170
|
recordEdit: editHistory.recordEdit,
|
|
170
171
|
domEditSaveTimestampRef,
|
|
171
172
|
reloadPreview,
|
|
@@ -195,14 +196,7 @@ export function StudioApp() {
|
|
|
195
196
|
},
|
|
196
197
|
[timelineEditing.handleTimelineGroupMove],
|
|
197
198
|
);
|
|
198
|
-
const handleAddAssetAtPlayhead =
|
|
199
|
-
(assetPath: string) =>
|
|
200
|
-
timelineEditing.handleTimelineAssetDrop(assetPath, {
|
|
201
|
-
start: usePlayerStore.getState().currentTime,
|
|
202
|
-
track: 0,
|
|
203
|
-
}),
|
|
204
|
-
[timelineEditing],
|
|
205
|
-
);
|
|
199
|
+
const handleAddAssetAtPlayhead = useAddAssetAtPlayhead(timelineEditing.handleTimelineAssetDrop);
|
|
206
200
|
const {
|
|
207
201
|
activeBlockParams,
|
|
208
202
|
setActiveBlockParams,
|
|
@@ -533,6 +527,7 @@ export function StudioApp() {
|
|
|
533
527
|
onToggleRecording={recordingToggle}
|
|
534
528
|
sdkSession={sdkHandle.session}
|
|
535
529
|
publishSdkSession={sdkHandle.publish}
|
|
530
|
+
forceReloadSdkSession={sdkHandle.forceReload}
|
|
536
531
|
reloadPreview={reloadPreview}
|
|
537
532
|
domEditSaveTimestampRef={domEditSaveTimestampRef}
|
|
538
533
|
recordEdit={editHistory.recordEdit}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { useCallback, type ReactNode } from "react";
|
|
13
|
+
import type { Composition } from "@hyperframes/sdk";
|
|
13
14
|
import type { DomEditSelection } from "./editor/domEditingTypes";
|
|
14
15
|
import { useSdkSession } from "../hooks/useSdkSession";
|
|
15
16
|
import { useVariablesPersist, type UseVariablesPersistParams } from "../hooks/useVariablesPersist";
|
|
@@ -24,6 +25,7 @@ export function DesignPanelPromoteProvider({
|
|
|
24
25
|
projectId,
|
|
25
26
|
activeCompPath,
|
|
26
27
|
showToast,
|
|
28
|
+
forceReloadSharedSdkSession,
|
|
27
29
|
children,
|
|
28
30
|
...persistDeps
|
|
29
31
|
}: PersistDeps & {
|
|
@@ -31,16 +33,40 @@ export function DesignPanelPromoteProvider({
|
|
|
31
33
|
projectId: string | null;
|
|
32
34
|
activeCompPath: string | null;
|
|
33
35
|
showToast: (message: string, tone?: "error" | "info") => void;
|
|
36
|
+
/**
|
|
37
|
+
* Forces the app's SHARED SDK session (Variables tab, Slideshow, etc.) to
|
|
38
|
+
* re-open from disk. This provider opens its OWN session, separate from
|
|
39
|
+
* that shared one, so a persist through it never fires the shared session's
|
|
40
|
+
* own "change" event. When the target happens to be the same file the
|
|
41
|
+
* shared session already has open, that session is left holding stale
|
|
42
|
+
* in-memory content after a successful persist — worse, the self-write-echo
|
|
43
|
+
* registry that would normally reload it on the next file-change
|
|
44
|
+
* notification is keyed by file path only (not by session instance), so it
|
|
45
|
+
* mistakes this provider's write for its own echo and stays stale
|
|
46
|
+
* indefinitely. Called unconditionally (not gated on targetPath matching
|
|
47
|
+
* activeCompPath): re-opening a file that didn't change is a harmless
|
|
48
|
+
* no-op re-parse, cheaper than the bug class a subtly-wrong path guard
|
|
49
|
+
* could reintroduce.
|
|
50
|
+
*/
|
|
51
|
+
forceReloadSharedSdkSession?: () => void;
|
|
34
52
|
children: ReactNode;
|
|
35
53
|
}) {
|
|
36
54
|
const targetPath = selection?.sourceFile || activeCompPath || "index.html";
|
|
37
55
|
const handle = useSdkSession(projectId, targetPath, persistDeps.domEditSaveTimestampRef);
|
|
38
|
-
const
|
|
56
|
+
const rawPersist = useVariablesPersist({
|
|
39
57
|
...persistDeps,
|
|
40
58
|
sdkSession: handle.session,
|
|
41
59
|
publishSdkSession: handle.publish,
|
|
42
60
|
activeCompPath: targetPath,
|
|
43
61
|
});
|
|
62
|
+
const persist = useCallback(
|
|
63
|
+
async (label: string, mutate: (session: Composition) => void) => {
|
|
64
|
+
const committed = await rawPersist(label, mutate);
|
|
65
|
+
if (committed) forceReloadSharedSdkSession?.();
|
|
66
|
+
return committed;
|
|
67
|
+
},
|
|
68
|
+
[rawPersist, forceReloadSharedSdkSession],
|
|
69
|
+
);
|
|
44
70
|
const handlePersistError = useCallback(
|
|
45
71
|
(error: unknown) => showToast(getStudioSaveErrorMessage(error), "error"),
|
|
46
72
|
[showToast],
|
|
@@ -149,14 +149,13 @@ const VIEW_MODE_OPTIONS: Array<{ mode: StudioViewMode; label: string }> = [
|
|
|
149
149
|
];
|
|
150
150
|
|
|
151
151
|
/** Segmented control switching the main stage between storyboard and preview. */
|
|
152
|
-
function ViewModeToggle() {
|
|
152
|
+
export function ViewModeToggle() {
|
|
153
153
|
const { viewMode, setViewMode } = useViewMode();
|
|
154
154
|
const tabRefs = useRef<Array<HTMLButtonElement | null>>([]);
|
|
155
155
|
|
|
156
156
|
const selectMode = (mode: StudioViewMode) => {
|
|
157
157
|
if (mode === viewMode) return;
|
|
158
|
-
trackStudioEvent("view_mode_toggle", { mode });
|
|
159
|
-
setViewMode(mode);
|
|
158
|
+
if (setViewMode(mode)) trackStudioEvent("view_mode_toggle", { mode });
|
|
160
159
|
};
|
|
161
160
|
|
|
162
161
|
// Complete APG tabs pattern: roving tabIndex + arrow-key navigation.
|
|
@@ -1,21 +1,23 @@
|
|
|
1
|
-
import { useCallback, useEffect,
|
|
1
|
+
import { useCallback, useEffect, useRef, type MutableRefObject } from "react";
|
|
2
2
|
import { PropertyPanel } from "./editor/PropertyPanel";
|
|
3
3
|
import { LayersPanel } from "./editor/LayersPanel";
|
|
4
4
|
import { CaptionPropertyPanel } from "../captions/components/CaptionPropertyPanel";
|
|
5
5
|
import { BlockParamsPanel } from "./editor/BlockParamsPanel";
|
|
6
6
|
import { RenderQueue } from "./renders/RenderQueue";
|
|
7
7
|
import { SlideshowPanel } from "./panels/SlideshowPanel";
|
|
8
|
-
import type { SceneInfo } from "./panels/SlideshowPanel";
|
|
9
8
|
import { VariablesPanel } from "./panels/VariablesPanel";
|
|
10
9
|
import { PanelTabButton } from "./PanelTabButton";
|
|
11
10
|
import { usePreviewVariablesStore } from "../hooks/previewVariablesStore";
|
|
12
11
|
import type { RenderJob } from "./renders/useRenderQueue";
|
|
13
12
|
import type { BlockParam } from "@hyperframes/core/registry";
|
|
14
|
-
import
|
|
15
|
-
|
|
13
|
+
import {
|
|
14
|
+
STUDIO_FLAT_INSPECTOR_ENABLED,
|
|
15
|
+
STUDIO_INSPECTOR_PANELS_ENABLED,
|
|
16
|
+
} from "./editor/manualEditingAvailability";
|
|
16
17
|
import type { Composition } from "@hyperframes/sdk";
|
|
17
18
|
import type { EditHistoryKind } from "../utils/editHistory";
|
|
18
19
|
import { useSlideshowPersist, type UseSlideshowPersistParams } from "../hooks/useSlideshowPersist";
|
|
20
|
+
import { useSlideshowTabState } from "../hooks/useSlideshowTabState";
|
|
19
21
|
import { DesignPanelPromoteProvider } from "./DesignPanelPromoteProvider";
|
|
20
22
|
|
|
21
23
|
import { useStudioPlaybackContext, useStudioShellContext } from "../contexts/StudioContext";
|
|
@@ -48,6 +50,19 @@ export interface StudioRightPanelProps {
|
|
|
48
50
|
/** Dependencies for the Slideshow persist callback, threaded from App.tsx. */
|
|
49
51
|
sdkSession: Composition | null;
|
|
50
52
|
publishSdkSession: NonNullable<UseSlideshowPersistParams["publishSdkSession"]>;
|
|
53
|
+
/**
|
|
54
|
+
* Forces THIS `sdkSession` to re-open from disk. DesignPanelPromoteProvider
|
|
55
|
+
* opens its own separate SDK session scoped to the selected element's own
|
|
56
|
+
* file (needed so promoting inside a sub-composition binds a variable there,
|
|
57
|
+
* not on the host) — for a top-level selection that's the SAME file this
|
|
58
|
+
* session already has open, so a write through that other session leaves
|
|
59
|
+
* this one holding stale in-memory content. The self-write-echo registry
|
|
60
|
+
* that normally suppresses redundant reloads is keyed by file path only, not
|
|
61
|
+
* by session instance, so it wrongly treats the sibling session's write as
|
|
62
|
+
* "our own echo" and never reloads on its own — this must be called
|
|
63
|
+
* explicitly after such a write.
|
|
64
|
+
*/
|
|
65
|
+
forceReloadSdkSession?: () => void;
|
|
51
66
|
reloadPreview: () => void;
|
|
52
67
|
domEditSaveTimestampRef: MutableRefObject<number>;
|
|
53
68
|
recordEdit: (entry: {
|
|
@@ -68,6 +83,7 @@ export function StudioRightPanel({
|
|
|
68
83
|
onToggleRecording,
|
|
69
84
|
sdkSession,
|
|
70
85
|
publishSdkSession,
|
|
86
|
+
forceReloadSdkSession,
|
|
71
87
|
reloadPreview,
|
|
72
88
|
domEditSaveTimestampRef,
|
|
73
89
|
recordEdit,
|
|
@@ -80,6 +96,7 @@ export function StudioRightPanel({
|
|
|
80
96
|
setRightPanelTab,
|
|
81
97
|
rightInspectorPanes,
|
|
82
98
|
toggleRightInspectorPane,
|
|
99
|
+
setExclusiveRightInspectorPane,
|
|
83
100
|
handlePanelResizeStart,
|
|
84
101
|
handlePanelResizeMove,
|
|
85
102
|
handlePanelResizeEnd,
|
|
@@ -150,6 +167,7 @@ export function StudioRightPanel({
|
|
|
150
167
|
readProjectFile,
|
|
151
168
|
writeProjectFile,
|
|
152
169
|
fileTree,
|
|
170
|
+
editingFile,
|
|
153
171
|
} = useFileManagerContext();
|
|
154
172
|
|
|
155
173
|
// Discrete ops (toggle, reorder, add/delete, hotspot): persist immediately,
|
|
@@ -198,22 +216,13 @@ export function StudioRightPanel({
|
|
|
198
216
|
const renderJobs = renderQueue.jobs as RenderJob[];
|
|
199
217
|
const inspectorTabActive = rightPanelTab === "design" || rightPanelTab === "layers";
|
|
200
218
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
label: s.label,
|
|
209
|
-
start: s.start,
|
|
210
|
-
duration: s.duration,
|
|
211
|
-
}));
|
|
212
|
-
} catch {
|
|
213
|
-
return [];
|
|
214
|
-
}
|
|
215
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
216
|
-
}, [previewIframeRef, rightPanelTab, refreshKey]);
|
|
219
|
+
const { isSlideshowComposition, slideshowScenes } = useSlideshowTabState({
|
|
220
|
+
editingFileContent: editingFile?.content,
|
|
221
|
+
previewIframeRef,
|
|
222
|
+
refreshKey,
|
|
223
|
+
rightPanelTab,
|
|
224
|
+
setRightPanelTab,
|
|
225
|
+
});
|
|
217
226
|
const designPaneOpen = inspectorTabActive && rightInspectorPanes.design && designPanelActive;
|
|
218
227
|
const layersPaneOpen =
|
|
219
228
|
inspectorTabActive && rightInspectorPanes.layers && STUDIO_INSPECTOR_PANELS_ENABLED;
|
|
@@ -223,6 +232,13 @@ export function StudioRightPanel({
|
|
|
223
232
|
setRightPanelTab(pane);
|
|
224
233
|
return;
|
|
225
234
|
}
|
|
235
|
+
// Flat inspector: Layers always renders full-height by itself (see the
|
|
236
|
+
// render branch below), so the two panes are mutually exclusive here —
|
|
237
|
+
// otherwise both tabs could show "active" while only one actually shows.
|
|
238
|
+
if (STUDIO_FLAT_INSPECTOR_ENABLED) {
|
|
239
|
+
setExclusiveRightInspectorPane(pane);
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
226
242
|
toggleRightInspectorPane(pane);
|
|
227
243
|
};
|
|
228
244
|
|
|
@@ -325,6 +341,7 @@ export function StudioRightPanel({
|
|
|
325
341
|
recordEdit={recordEdit}
|
|
326
342
|
reloadPreview={reloadPreview}
|
|
327
343
|
domEditSaveTimestampRef={domEditSaveTimestampRef}
|
|
344
|
+
forceReloadSharedSdkSession={forceReloadSdkSession}
|
|
328
345
|
>
|
|
329
346
|
<PropertyPanel
|
|
330
347
|
projectId={projectId}
|
|
@@ -480,12 +497,14 @@ export function StudioRightPanel({
|
|
|
480
497
|
active={rightPanelTab === "renders"}
|
|
481
498
|
onClick={() => setRightPanelTab("renders")}
|
|
482
499
|
/>
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
500
|
+
{isSlideshowComposition && (
|
|
501
|
+
<PanelTabButton
|
|
502
|
+
label="Slideshow"
|
|
503
|
+
tooltip="Slideshow branching editor"
|
|
504
|
+
active={rightPanelTab === "slideshow"}
|
|
505
|
+
onClick={() => setRightPanelTab("slideshow")}
|
|
506
|
+
/>
|
|
507
|
+
)}
|
|
489
508
|
<PanelTabButton
|
|
490
509
|
label="Variables"
|
|
491
510
|
tooltip="Template variables — declare, preview with values"
|
|
@@ -502,7 +521,7 @@ export function StudioRightPanel({
|
|
|
502
521
|
compositionPath={activeBlockParams.compositionPath}
|
|
503
522
|
onClose={onCloseBlockParams ?? (() => {})}
|
|
504
523
|
/>
|
|
505
|
-
) : rightPanelTab === "slideshow" ? (
|
|
524
|
+
) : rightPanelTab === "slideshow" && isSlideshowComposition ? (
|
|
506
525
|
<SlideshowPanel
|
|
507
526
|
scenes={slideshowScenes}
|
|
508
527
|
onPersist={onPersistSlideshow}
|
|
@@ -516,7 +535,7 @@ export function StudioRightPanel({
|
|
|
516
535
|
domEditSaveTimestampRef={domEditSaveTimestampRef}
|
|
517
536
|
recordEdit={recordEdit}
|
|
518
537
|
/>
|
|
519
|
-
) : layersPaneOpen && designPaneOpen ? (
|
|
538
|
+
) : layersPaneOpen && designPaneOpen && !STUDIO_FLAT_INSPECTOR_ENABLED ? (
|
|
520
539
|
<div ref={splitContainerRef} className="flex h-full min-h-0 min-w-0 flex-col">
|
|
521
540
|
<div
|
|
522
541
|
className="min-h-[120px] overflow-hidden"
|
|
@@ -81,7 +81,9 @@ export function PromotableControl({
|
|
|
81
81
|
{rendered}
|
|
82
82
|
{bound && (
|
|
83
83
|
<span
|
|
84
|
-
|
|
84
|
+
// Sits above the row (not on top of top-0) so it clears a value that
|
|
85
|
+
// renders flush to the row's right edge, e.g. flat Font/Color rows.
|
|
86
|
+
className="pointer-events-none absolute -top-2 right-1.5 z-10 inline-flex max-w-[60%] items-center gap-1 truncate rounded bg-studio-accent/20 px-1 py-px font-mono text-[8px] font-medium text-studio-accent"
|
|
85
87
|
title={`Bound to variable "${promote.boundId}"`}
|
|
86
88
|
>
|
|
87
89
|
◆ {promote.boundId}
|
|
@@ -95,7 +97,7 @@ export function PromotableControl({
|
|
|
95
97
|
e.stopPropagation();
|
|
96
98
|
promote.promote();
|
|
97
99
|
}}
|
|
98
|
-
className="absolute right-1.5
|
|
100
|
+
className="absolute -top-2 right-1.5 z-10 inline-flex items-center gap-1 rounded bg-neutral-800/80 px-1 py-px font-mono text-[8px] font-medium text-neutral-400 opacity-70 transition-colors hover:bg-studio-accent/20 hover:text-studio-accent hover:opacity-100"
|
|
99
101
|
>
|
|
100
102
|
◇ var
|
|
101
103
|
</button>
|