@hyperframes/studio 0.8.50 → 0.8.53-desktop.0

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.
Files changed (330) hide show
  1. package/dist/assets/{hyperframes-player-CxxDxHTW.js → hyperframes-player-PTEnAHhg.js} +3 -3
  2. package/dist/assets/{index-DUAIWxkI.js → index--myXp8ui.js} +1 -1
  3. package/dist/assets/{index-Dt3qBI-9.js → index-BjslOS9g.js} +1 -1
  4. package/dist/assets/index-BnXZuIJD.css +1 -0
  5. package/dist/assets/index-CNyviK_l.js +390 -0
  6. package/dist/index.css +29 -0
  7. package/dist/index.css.map +1 -0
  8. package/dist/index.d.ts +825 -24
  9. package/dist/index.html +2 -2
  10. package/dist/index.js +8911 -9853
  11. package/dist/index.js.map +1 -1
  12. package/dist/styles/tailwind-preset.js.map +1 -1
  13. package/package.json +13 -12
  14. package/src/App.tsx +145 -163
  15. package/src/captions/components/CaptionAnimationPanel.tsx +4 -4
  16. package/src/captions/components/CaptionOverlay.sender.test.tsx +52 -0
  17. package/src/captions/components/CaptionOverlay.tsx +8 -4
  18. package/src/captions/components/CaptionOverlayUtils.ts +2 -3
  19. package/src/captions/components/CaptionPropertyPanel.tsx +3 -3
  20. package/src/captions/components/CaptionTimeline.tsx +1 -1
  21. package/src/captions/components/shared.tsx +2 -2
  22. package/src/components/AskAgentModal.tsx +5 -5
  23. package/src/components/EditorShell.selectionSync.test.tsx +9 -4
  24. package/src/components/EditorShell.tsx +59 -62
  25. package/src/components/ExternalFileConflictBanner.tsx +16 -16
  26. package/src/components/LintModal.tsx +6 -16
  27. package/src/components/MediaPreview.tsx +2 -2
  28. package/src/components/RightPanelTabs.test.tsx +151 -0
  29. package/src/components/RightPanelTabs.tsx +59 -0
  30. package/src/components/SaveQueuePausedBanner.tsx +2 -2
  31. package/src/components/StudioHeader.dom.test.tsx +181 -0
  32. package/src/components/StudioHeader.test.ts +0 -12
  33. package/src/components/StudioHeader.tsx +118 -221
  34. package/src/components/StudioLeftPanels.tsx +202 -0
  35. package/src/components/StudioOverlays.tsx +1 -1
  36. package/src/components/{StudioRightPanel.tsx → StudioRightPanels.tsx} +57 -194
  37. package/src/components/{StudioRightPanel.types.ts → StudioRightPanels.types.ts} +4 -3
  38. package/src/components/StudioToast.tsx +2 -2
  39. package/src/components/TimelineHistoryButtons.dom.test.tsx +117 -0
  40. package/src/components/TimelineHistoryButtons.tsx +54 -0
  41. package/src/components/TimelineToolbar.test.tsx +8 -0
  42. package/src/components/TimelineToolbar.tsx +8 -12
  43. package/src/components/dock/Dock.test.tsx +274 -0
  44. package/src/components/dock/Dock.tsx +291 -0
  45. package/src/components/dock/dock.css +28 -0
  46. package/src/components/dock/dockAccessibility.test.ts +166 -0
  47. package/src/components/dock/dockAccessibility.ts +98 -0
  48. package/src/components/dock/dockLayout.test.ts +134 -0
  49. package/src/components/dock/dockLayout.ts +105 -0
  50. package/src/components/dock/dockLayoutSchema.ts +66 -0
  51. package/src/components/dock/dockLayoutStore.test.ts +28 -0
  52. package/src/components/dock/dockLayoutStore.ts +108 -0
  53. package/src/components/dock/dockTestHarness.ts +11 -0
  54. package/src/components/dock/panelRegistry.ts +67 -0
  55. package/src/components/editor/AnimationCard.tsx +4 -4
  56. package/src/components/editor/AnimationCardParts.tsx +6 -6
  57. package/src/components/editor/BlockParamsPanel.tsx +4 -4
  58. package/src/components/editor/BorderRadiusEditor.tsx +1 -1
  59. package/src/components/editor/CanvasContextMenu.tsx +1 -1
  60. package/src/components/editor/ComputedTweenNotice.tsx +1 -1
  61. package/src/components/editor/DomEditOverlay.tsx +1 -1
  62. package/src/components/editor/EaseCurveSection.tsx +1 -1
  63. package/src/components/editor/EaseParamFields.tsx +5 -5
  64. package/src/components/editor/FileTree.tsx +4 -4
  65. package/src/components/editor/FileTreeIcons.tsx +1 -1
  66. package/src/components/editor/FileTreeNodes.tsx +13 -13
  67. package/src/components/editor/InlineTextToolbar.tsx +1 -1
  68. package/src/components/editor/InspectorHeaderActions.tsx +3 -3
  69. package/src/components/editor/KeyframeDiamond.tsx +1 -1
  70. package/src/components/editor/KeyframeEaseList.tsx +1 -1
  71. package/src/components/editor/LayersPanel.test.ts +97 -1
  72. package/src/components/editor/LayersPanel.tsx +7 -5
  73. package/src/components/editor/MarqueeOverlay.tsx +1 -1
  74. package/src/components/editor/OffCanvasIndicators.tsx +1 -1
  75. package/src/components/editor/PreviewGuides.tsx +1 -1
  76. package/src/components/editor/PromotableControl.tsx +2 -2
  77. package/src/components/editor/PropertyPanelEmptyState.tsx +7 -7
  78. package/src/components/editor/PropertyPanelFlatHeader.tsx +2 -2
  79. package/src/components/editor/SnapToolbar.test.tsx +0 -3
  80. package/src/components/editor/SnapToolbar.tsx +2 -2
  81. package/src/components/editor/TimelineFxPopover.tsx +1 -1
  82. package/src/components/editor/TopologyLens.test.tsx +28 -0
  83. package/src/components/editor/TopologyLens.tsx +7 -5
  84. package/src/components/editor/Transform3DCube.tsx +2 -2
  85. package/src/components/editor/audioFxRevealTarget.ts +1 -0
  86. package/src/components/editor/domEditing.test.ts +1 -1
  87. package/src/components/editor/domEditingAgentPrompt.test.ts +8 -6
  88. package/src/components/editor/domEditingAgentPrompt.ts +4 -3
  89. package/src/components/editor/propertyPanelColor.tsx +11 -11
  90. package/src/components/editor/propertyPanelColorCurveGraph.tsx +1 -1
  91. package/src/components/editor/propertyPanelColorGradingControls.tsx +7 -9
  92. package/src/components/editor/propertyPanelColorGradingSection.tsx +6 -6
  93. package/src/components/editor/propertyPanelColorGradingSlider.tsx +5 -5
  94. package/src/components/editor/propertyPanelColorWheels.tsx +1 -1
  95. package/src/components/editor/propertyPanelCommitField.tsx +1 -1
  96. package/src/components/editor/propertyPanelFill.tsx +4 -4
  97. package/src/components/editor/propertyPanelFlatColorGradingAccessory.tsx +3 -3
  98. package/src/components/editor/propertyPanelFlatColorGradingSection.tsx +7 -7
  99. package/src/components/editor/propertyPanelFlatEffectsSection.tsx +4 -4
  100. package/src/components/editor/propertyPanelFlatMediaSection.tsx +3 -3
  101. package/src/components/editor/propertyPanelFlatOverlaysSection.tsx +1 -1
  102. package/src/components/editor/propertyPanelFlatPrimitives.tsx +10 -10
  103. package/src/components/editor/propertyPanelFlatSelectRow.tsx +3 -3
  104. package/src/components/editor/propertyPanelFlatTextSection.test.tsx +8 -9
  105. package/src/components/editor/propertyPanelFlatTextSection.tsx +5 -5
  106. package/src/components/editor/propertyPanelFlatToggle.tsx +1 -1
  107. package/src/components/editor/propertyPanelFont.tsx +5 -5
  108. package/src/components/editor/propertyPanelFxCarveModule.tsx +1 -1
  109. package/src/components/editor/propertyPanelFxControls.test.tsx +1 -1
  110. package/src/components/editor/propertyPanelFxControls.tsx +6 -6
  111. package/src/components/editor/propertyPanelFxEqModule.tsx +2 -2
  112. package/src/components/editor/propertyPanelFxPresetStyle.ts +2 -2
  113. package/src/components/editor/propertyPanelGradingNumberField.tsx +1 -1
  114. package/src/components/editor/propertyPanelMediaSection.tsx +1 -1
  115. package/src/components/editor/propertyPanelPrimitives.tsx +7 -7
  116. package/src/components/editor/propertyPanelSections.tsx +8 -8
  117. package/src/components/editor/useColorGradingController.test.ts +38 -0
  118. package/src/components/editor/useColorGradingController.ts +9 -1
  119. package/src/components/editor/useColorGradingPreviews.test.ts +76 -0
  120. package/src/components/editor/useColorGradingPreviews.ts +11 -1
  121. package/src/components/editor/usePreviewCompositionRect.test.tsx +95 -0
  122. package/src/components/editor/usePreviewCompositionRect.ts +21 -0
  123. package/src/components/feedback/StudioFeedbackCard.tsx +7 -7
  124. package/src/components/feedback/feedbackTrigger.ts +0 -1
  125. package/src/components/nle/AssetPreviewOverlay.tsx +6 -2
  126. package/src/components/nle/CompositionBreadcrumb.tsx +3 -3
  127. package/src/components/nle/NLEContext.tsx +0 -43
  128. package/src/components/nle/NLEPreview.tsx +3 -3
  129. package/src/components/nle/PreviewOverlays.tsx +6 -6
  130. package/src/components/nle/PreviewPane.tsx +3 -3
  131. package/src/components/nle/TimelinePane.tsx +53 -67
  132. package/src/components/panels/SlideshowPanel.tsx +3 -3
  133. package/src/components/panels/SlideshowSubPanels.tsx +20 -17
  134. package/src/components/panels/VariablesBindElement.tsx +2 -2
  135. package/src/components/panels/VariablesDeclarationForm.tsx +2 -2
  136. package/src/components/panels/VariablesOtherCompositions.tsx +1 -1
  137. package/src/components/panels/VariablesPanel.tsx +4 -4
  138. package/src/components/panels/VariablesValueControls.tsx +2 -2
  139. package/src/components/pointerTargetSize.test.tsx +8 -0
  140. package/src/components/renders/FfmpegRequiredNotice.tsx +5 -5
  141. package/src/components/renders/RenderQueue.test.tsx +7 -0
  142. package/src/components/renders/RenderQueue.tsx +7 -7
  143. package/src/components/renders/RenderQueueItem.tsx +6 -6
  144. package/src/components/renders/RenderQueuePanel.tsx +1 -1
  145. package/src/components/sidebar/AssetCard.tsx +8 -8
  146. package/src/components/sidebar/AssetContextMenu.tsx +8 -8
  147. package/src/components/sidebar/AssetsTab.tsx +2 -2
  148. package/src/components/sidebar/AudioRow.tsx +6 -6
  149. package/src/components/sidebar/BlocksTab.tsx +6 -6
  150. package/src/components/sidebar/{LeftSidebar.masterComposition.test.tsx → CompositionsPanel.masterComposition.test.tsx} +6 -9
  151. package/src/components/sidebar/CompositionsPanel.tsx +15 -0
  152. package/src/components/sidebar/CompositionsTab.tsx +5 -5
  153. package/src/components/sidebar/GlobalAssetsView.tsx +1 -1
  154. package/src/components/sidebar/PromptPreviewModal.tsx +3 -3
  155. package/src/components/sidebar/SidebarLintButton.test.tsx +53 -0
  156. package/src/components/sidebar/SidebarLintButton.tsx +50 -0
  157. package/src/components/timelineToolbarStyles.ts +5 -0
  158. package/src/components/ui/Button.test.tsx +252 -0
  159. package/src/components/ui/Button.tsx +89 -126
  160. package/src/components/ui/IconButton.tsx +38 -0
  161. package/src/components/ui/Input.tsx +115 -0
  162. package/src/components/ui/Menu.test.tsx +374 -0
  163. package/src/components/ui/Menu.tsx +213 -0
  164. package/src/components/ui/NumberField.tsx +122 -0
  165. package/src/components/ui/Popover.tsx +74 -0
  166. package/src/components/ui/SearchInput.tsx +2 -2
  167. package/src/components/ui/Select.tsx +100 -0
  168. package/src/components/ui/Slider.tsx +153 -0
  169. package/src/components/ui/Tabs.test.tsx +98 -0
  170. package/src/components/ui/Tabs.tsx +71 -0
  171. package/src/components/ui/Toggle.tsx +63 -0
  172. package/src/components/ui/Tooltip.test.tsx +110 -0
  173. package/src/components/ui/Tooltip.tsx +38 -112
  174. package/src/components/ui/cn.test.ts +30 -0
  175. package/src/components/ui/cn.ts +25 -0
  176. package/src/components/ui/index.ts +29 -2
  177. package/src/components/ui/mountHost.testHelpers.ts +24 -0
  178. package/src/components/ui/valueControls.test.tsx +524 -0
  179. package/src/contexts/PanelLayoutContext.tsx +3 -57
  180. package/src/hooks/appHotkeysDispatch.ts +3 -4
  181. package/src/hooks/timelineEditPermission.ts +31 -0
  182. package/src/hooks/useAppHotkeys.previewForwarding.test.tsx +0 -2
  183. package/src/hooks/useAppHotkeys.test.ts +0 -1
  184. package/src/hooks/useAppHotkeys.textEditing.test.tsx +0 -3
  185. package/src/hooks/useAppHotkeys.ts +21 -84
  186. package/src/hooks/useCaptionDetection.sender.test.tsx +46 -0
  187. package/src/hooks/useCaptionDetection.ts +3 -1
  188. package/src/hooks/useDomEditPreviewSync.ts +4 -6
  189. package/src/hooks/useDomEditSession.ts +0 -7
  190. package/src/hooks/useDomEditWiring.ts +4 -9
  191. package/src/hooks/useEditHistoryActions.test.tsx +90 -0
  192. package/src/hooks/useEditHistoryActions.ts +106 -0
  193. package/src/hooks/useFileManager.ts +21 -123
  194. package/src/hooks/useLintModal.test.tsx +65 -0
  195. package/src/hooks/useLintModal.ts +3 -0
  196. package/src/hooks/usePanelLayout.test.ts +108 -296
  197. package/src/hooks/usePanelLayout.ts +50 -255
  198. package/src/hooks/usePersistentEditHistory.ts +1 -1
  199. package/src/hooks/useProjectFileWriter.ts +150 -0
  200. package/src/hooks/useRightPanelIntents.test.ts +181 -0
  201. package/src/hooks/useRightPanelIntents.ts +63 -0
  202. package/src/hooks/useSdkSession.lifecycle.test.tsx +49 -4
  203. package/src/hooks/useSdkSession.ts +43 -10
  204. package/src/hooks/useServerConnection.hashProject.test.tsx +94 -0
  205. package/src/hooks/useServerConnection.ts +43 -10
  206. package/src/hooks/useSlideshowTabState.test.ts +9 -31
  207. package/src/hooks/useSlideshowTabState.ts +6 -19
  208. package/src/hooks/useStudioContextValue.test.ts +6 -18
  209. package/src/hooks/useStudioContextValue.ts +5 -26
  210. package/src/hooks/useTimelineAssetDropOps.test.tsx +41 -1
  211. package/src/hooks/useTimelineAssetDropOps.ts +52 -11
  212. package/src/hooks/useTimelineDeleteOps.test.tsx +111 -0
  213. package/src/hooks/useTimelineEditing.test.tsx +322 -3
  214. package/src/hooks/useTimelineEditing.ts +103 -16
  215. package/src/hooks/useTimelineEditingTypes.ts +3 -0
  216. package/src/hooks/useTrackPendingTimelineEdit.test.tsx +62 -0
  217. package/src/hooks/useTrackPendingTimelineEdit.ts +22 -0
  218. package/src/hostMount.test.tsx +222 -0
  219. package/src/index.ts +87 -0
  220. package/src/main.tsx +9 -3
  221. package/src/player/components/AudioWaveform.tsx +1 -1
  222. package/src/player/components/AutomationSelectionMenu.tsx +3 -3
  223. package/src/player/components/ClipContextMenu.tsx +3 -3
  224. package/src/player/components/CompositionThumbnail.test.ts +0 -3
  225. package/src/player/components/CompositionThumbnail.tsx +3 -4
  226. package/src/player/components/EditModal.tsx +1 -1
  227. package/src/player/components/ImageThumbnail.tsx +1 -1
  228. package/src/player/components/KeyframeDiamondContextMenu.tsx +4 -4
  229. package/src/player/components/LayerDisclosureRow.tsx +2 -2
  230. package/src/player/components/PlayerControls.tsx +1 -1
  231. package/src/player/components/ShortcutsPanel.tsx +9 -9
  232. package/src/player/components/SpeedMenu.tsx +3 -5
  233. package/src/player/components/Timeline.tsx +3 -2
  234. package/src/player/components/TimelineCanvas.tsx +21 -14
  235. package/src/player/components/TimelineClip.tsx +0 -1
  236. package/src/player/components/TimelineDiamondConnectors.tsx +1 -1
  237. package/src/player/components/TimelineEmptyState.tsx +5 -5
  238. package/src/player/components/TimelineFxButton.tsx +6 -6
  239. package/src/player/components/TimelineGroupHeader.tsx +5 -5
  240. package/src/player/components/TimelineGroupLaneLabels.tsx +1 -1
  241. package/src/player/components/TimelineGroupRow.tsx +1 -1
  242. package/src/player/components/TimelineLanes.test.tsx +32 -0
  243. package/src/player/components/TimelineLanes.tsx +2 -5
  244. package/src/player/components/TimelineLayerGroupHeader.tsx +2 -2
  245. package/src/player/components/TimelineRuler.tsx +1 -1
  246. package/src/player/components/TimelineShortcutHint.tsx +1 -1
  247. package/src/player/components/TimelineTrackHeader.test.tsx +26 -5
  248. package/src/player/components/TimelineTrackHeader.tsx +2 -2
  249. package/src/player/components/TimelineTrackPlainHeader.tsx +3 -3
  250. package/src/player/components/TimelineTypes.ts +2 -1
  251. package/src/player/components/TrackGapContextMenu.tsx +1 -1
  252. package/src/player/components/VideoThumbnail.tsx +4 -2
  253. package/src/player/components/VolumeControl.tsx +2 -2
  254. package/src/player/components/timelineCallbacks.ts +8 -8
  255. package/src/player/components/timelineClipDragPreview.ts +51 -27
  256. package/src/player/components/timelineClipDragTypes.ts +3 -0
  257. package/src/player/components/timelineDragDrop.test.tsx +61 -1
  258. package/src/player/components/timelineDragDrop.ts +57 -15
  259. package/src/player/components/timelineLaneProps.ts +3 -0
  260. package/src/player/components/timelineSnapping.test.ts +27 -0
  261. package/src/player/components/timelineSnapping.ts +14 -1
  262. package/src/player/components/timelineTheme.test.ts +4 -4
  263. package/src/player/components/timelineTheme.ts +30 -30
  264. package/src/player/components/trackHeaderLabelRows.tsx +4 -4
  265. package/src/player/components/useTimelineClipDrag.resize.test.tsx +136 -2
  266. package/src/player/components/useTimelineClipDrag.ts +30 -3
  267. package/src/player/lib/describeClips.ts +3 -54
  268. package/src/player/lib/playbackShortcuts.ts +2 -0
  269. package/src/player/lib/timelinePerformanceDiagnostics.test.ts +3 -2
  270. package/src/player/lib/timelinePerformanceDiagnostics.ts +1 -1
  271. package/src/player/store/previewIframeStore.notify.test.tsx +75 -0
  272. package/src/player/store/previewIframeStore.test.tsx +29 -0
  273. package/src/player/store/previewIframeStore.ts +25 -0
  274. package/src/renderQueueExports.test.tsx +58 -0
  275. package/src/styles/classCandidates.test.ts +105 -0
  276. package/src/styles/classCandidates.ts +281 -0
  277. package/src/styles/hex-baseline.json +84 -0
  278. package/src/styles/hexRatchet.test.ts +201 -0
  279. package/src/styles/iconTokens.ts +20 -0
  280. package/src/styles/palette-reset.css +6 -0
  281. package/src/styles/studio.css +24 -21
  282. package/src/styles/styleSources.test.ts +20 -0
  283. package/src/styles/styleSources.ts +47 -0
  284. package/src/styles/tailwind-preset.shared.js +3 -0
  285. package/src/styles/theme.css +270 -0
  286. package/src/styles/theme.test.ts +183 -0
  287. package/src/styles/tokenGate.test.ts +109 -0
  288. package/src/utils/sourcePatcher.ts +1 -1
  289. package/src/utils/studioHelpers.test.ts +18 -0
  290. package/src/utils/studioHelpers.ts +11 -8
  291. package/src/utils/studioUiPreferences.test.ts +10 -16
  292. package/src/utils/studioUiPreferences.ts +7 -16
  293. package/src/utils/timelineDropTrackInsert.test.ts +134 -0
  294. package/src/utils/timelineDropTrackInsert.ts +83 -0
  295. package/src/utils/typingTarget.ts +4 -0
  296. package/dist/assets/index-n2ml4tUn.js +0 -442
  297. package/dist/assets/index-pO6p0H27.css +0 -1
  298. package/src/components/PanelTabButton.tsx +0 -31
  299. package/src/components/StudioLeftSidebar.tsx +0 -204
  300. package/src/components/nle/TimelineResizeDivider.tsx +0 -101
  301. package/src/components/sidebar/LeftSidebar.storage.test.ts +0 -28
  302. package/src/components/sidebar/LeftSidebar.tsx +0 -334
  303. package/src/components/storyboard/AgentChatMessageButton.test.tsx +0 -47
  304. package/src/components/storyboard/AgentChatMessageButton.tsx +0 -45
  305. package/src/components/storyboard/FramePoster.test.tsx +0 -61
  306. package/src/components/storyboard/FramePoster.tsx +0 -86
  307. package/src/components/storyboard/StoryboardDirection.tsx +0 -45
  308. package/src/components/storyboard/StoryboardFrameFocus.tsx +0 -412
  309. package/src/components/storyboard/StoryboardFrameTile.tsx +0 -117
  310. package/src/components/storyboard/StoryboardGrid.tsx +0 -55
  311. package/src/components/storyboard/StoryboardLoaded.tsx +0 -307
  312. package/src/components/storyboard/StoryboardReviewGuide.tsx +0 -300
  313. package/src/components/storyboard/StoryboardScriptPanel.tsx +0 -26
  314. package/src/components/storyboard/StoryboardSourceEditor.tsx +0 -231
  315. package/src/components/storyboard/StoryboardStatusLegend.tsx +0 -21
  316. package/src/components/storyboard/StoryboardView.tsx +0 -169
  317. package/src/components/storyboard/StoryboardViewModeGuard.test.tsx +0 -187
  318. package/src/components/storyboard/frameComments.test.ts +0 -95
  319. package/src/components/storyboard/frameComments.ts +0 -115
  320. package/src/components/storyboard/frameStatus.ts +0 -36
  321. package/src/components/storyboard/storyboardReviewStage.test.ts +0 -40
  322. package/src/components/storyboard/storyboardReviewStage.ts +0 -45
  323. package/src/components/storyboard/useFrameComments.ts +0 -98
  324. package/src/contexts/ViewModeContext.tsx +0 -142
  325. package/src/hooks/useInspectorSplitResize.ts +0 -51
  326. package/src/hooks/useProjectSignaturePoll.test.tsx +0 -135
  327. package/src/hooks/useProjectSignaturePoll.ts +0 -68
  328. package/src/hooks/useStoryboard.ts +0 -99
  329. package/src/utils/fitPanels.test.ts +0 -164
  330. package/src/utils/fitPanels.ts +0 -151
@@ -1,11 +1,10 @@
1
- import { useRef, type MouseEvent } from "react";
2
- import { RotateCcw, RotateCw, Camera } from "../icons/SystemIcons";
3
- import { getHistoryShortcutLabel } from "../utils/studioHelpers";
1
+ import type { MouseEvent } from "react";
2
+ import { Camera } from "../icons/SystemIcons";
4
3
  import { useStudioShellContext } from "../contexts/StudioContext";
5
4
  import { usePanelLayoutContext } from "../contexts/PanelLayoutContext";
6
- import { useViewMode, type StudioViewMode } from "../contexts/ViewModeContext";
7
5
  import { trackStudioEvent } from "../utils/studioTelemetry";
8
- import { Tooltip } from "./ui";
6
+ import { Button, buttonBase, buttonSizes, buttonVariants, cn, Tooltip } from "./ui";
7
+ import { Dock } from "./dock/Dock";
9
8
 
10
9
  export interface StudioHeaderProps {
11
10
  captureFrameHref: string;
@@ -41,8 +40,8 @@ function HyperframesLogo() {
41
40
  y2="37.482"
42
41
  gradientUnits="userSpaceOnUse"
43
42
  >
44
- <stop stopColor="#06E3FA" />
45
- <stop offset="1" stopColor="#4FDB5E" />
43
+ <stop stopColor="var(--color-brand-gradient-from)" />
44
+ <stop offset="1" stopColor="var(--color-brand-gradient-to)" />
46
45
  </linearGradient>
47
46
  <linearGradient
48
47
  id="hf-g1"
@@ -52,8 +51,8 @@ function HyperframesLogo() {
52
51
  y2="6.303"
53
52
  gradientUnits="userSpaceOnUse"
54
53
  >
55
- <stop stopColor="#06E3FA" />
56
- <stop offset="1" stopColor="#4FDB5E" />
54
+ <stop stopColor="var(--color-brand-gradient-from)" />
55
+ <stop offset="1" stopColor="var(--color-brand-gradient-to)" />
57
56
  </linearGradient>
58
57
  </defs>
59
58
  {/* heygen label */}
@@ -139,76 +138,18 @@ function HyperframesLogo() {
139
138
  );
140
139
  }
141
140
 
142
- const VIEW_MODE_OPTIONS: Array<{ mode: StudioViewMode; label: string }> = [
143
- { mode: "storyboard", label: "Storyboard" },
144
- { mode: "timeline", label: "Preview" },
145
- ];
146
-
147
- /** Segmented control switching the main stage between storyboard and preview. */
148
- export function ViewModeToggle() {
149
- const { viewMode, setViewMode } = useViewMode();
150
- const tabRefs = useRef<Array<HTMLButtonElement | null>>([]);
151
-
152
- const selectMode = (mode: StudioViewMode) => {
153
- if (mode === viewMode) return;
154
- if (setViewMode(mode)) trackStudioEvent("view_mode_toggle", { mode });
155
- };
156
-
157
- // Complete APG tabs pattern: roving tabIndex + arrow-key navigation.
158
- const handleKeyDown = (e: React.KeyboardEvent, index: number) => {
159
- if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return;
160
- e.preventDefault();
161
- const dir = e.key === "ArrowLeft" ? -1 : 1;
162
- const next = (index + dir + VIEW_MODE_OPTIONS.length) % VIEW_MODE_OPTIONS.length;
163
- tabRefs.current[next]?.focus();
164
- selectMode(VIEW_MODE_OPTIONS[next].mode);
165
- };
166
-
167
- return (
168
- <div
169
- className="flex items-center gap-0.5 rounded-md bg-neutral-800 p-0.5"
170
- role="tablist"
171
- aria-label="Studio view"
172
- >
173
- {VIEW_MODE_OPTIONS.map(({ mode, label }, index) => {
174
- const active = viewMode === mode;
175
- return (
176
- <button
177
- key={mode}
178
- ref={(el) => {
179
- tabRefs.current[index] = el;
180
- }}
181
- type="button"
182
- role="tab"
183
- aria-selected={active}
184
- tabIndex={active ? 0 : -1}
185
- onClick={() => selectMode(mode)}
186
- onKeyDown={(e) => handleKeyDown(e, index)}
187
- className={`rounded px-3 py-1 text-[11px] font-medium transition-colors active:scale-[0.98] outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-studio-accent ${
188
- active ? "bg-neutral-200 text-neutral-900" : "text-neutral-400 hover:text-neutral-200"
189
- }`}
190
- >
191
- {label}
192
- </button>
193
- );
194
- })}
195
- </div>
196
- );
197
- }
198
-
199
141
  /**
200
142
  * Does the header's Inspector button open the panel, or close it?
201
143
  *
202
- * Takes the EFFECTIVE collapse state, so a panel the window has railed away
203
- * counts as closed even though the user's stored intent still says open. The
204
- * argument name is the guard: passing raw intent here is the bug this exists
205
- * to keep out.
144
+ * The dock has no separate "railed by window width" state (it shrinks panels,
145
+ * never auto-hides the group), so `rightCollapsed` here is already the state
146
+ * that decides whether the panel is actually showing.
206
147
  */
207
148
  export function shouldOpenInspector(
208
- effectiveRightCollapsed: boolean,
149
+ rightCollapsed: boolean,
209
150
  inspectorPanelActive: boolean,
210
151
  ): boolean {
211
- return effectiveRightCollapsed || !inspectorPanelActive;
152
+ return rightCollapsed || !inspectorPanelActive;
212
153
  }
213
154
 
214
155
  // fallow-ignore-next-line complexity
@@ -222,165 +163,121 @@ export function StudioHeader({
222
163
  inspectorPanelActive,
223
164
  onExport,
224
165
  }: StudioHeaderProps) {
225
- const { projectId, editHistory, handleUndo, handleRedo, renderQueue } = useStudioShellContext();
226
- // effectiveRightCollapsed, not the raw intent: in the auto-railed state the
227
- // intent is still "open" while the panel is hidden, so branching on intent
228
- // made this button write rightCollapsed=true — and that value is synced into
229
- // the shareable Studio URL, so a dead click would rewrite a link.
230
- const { effectiveRightCollapsed, setRightCollapsed, setRightPanelTab } = usePanelLayoutContext();
166
+ const { projectId, renderQueue } = useStudioShellContext();
167
+ const { rightCollapsed, setRightCollapsed, setRightPanelTab } = usePanelLayoutContext();
231
168
  const isRendering = renderQueue.isRendering;
232
169
  const ffmpegMissing = renderQueue.ffmpegMissing;
233
170
 
234
171
  return (
235
- <div className="flex items-center justify-between h-10 px-3 bg-neutral-900 border-b border-neutral-800 flex-shrink-0">
172
+ <div className="flex items-center justify-between h-10 px-3 bg-surface border-b border-border-strong shrink-0">
236
173
  {/* Left: logo + project name */}
237
174
  <div className="flex items-center gap-3">
238
175
  <HyperframesLogo />
239
- <span className="text-neutral-700 select-none" aria-hidden="true">
176
+ <span className="text-text-5 select-none" aria-hidden="true">
240
177
  |
241
178
  </span>
242
- <span className="text-[11px] font-medium text-neutral-300">{projectId}</span>
179
+ <span className="text-step-11 font-medium text-text-1">{projectId}</span>
243
180
  </div>
244
- {/* Center: storyboard / preview toggle */}
245
- <ViewModeToggle />
246
181
  {/* Right: toolbar buttons */}
247
- <div className="flex items-center gap-1.5">
248
- <Tooltip
249
- label={
250
- editHistory.undoLabel
251
- ? `Undo ${editHistory.undoLabel} (${getHistoryShortcutLabel("undo")})`
252
- : `Undo (${getHistoryShortcutLabel("undo")})`
253
- }
254
- side="bottom"
255
- >
256
- <button
257
- type="button"
258
- onClick={() => {
259
- trackStudioEvent("toolbar_action", { action: "undo" });
260
- void handleUndo();
261
- }}
262
- disabled={!editHistory.canUndo}
263
- className={`h-7 w-7 flex items-center justify-center rounded-md transition-colors active:scale-[0.98] ${
264
- editHistory.canUndo
265
- ? "text-neutral-400 hover:text-neutral-200 hover:bg-neutral-800"
266
- : "text-neutral-700 cursor-default"
267
- }`}
268
- aria-label="Undo"
269
- >
270
- <RotateCcw size={14} />
271
- </button>
272
- </Tooltip>
273
- <Tooltip
274
- label={
275
- editHistory.redoLabel
276
- ? `Redo ${editHistory.redoLabel} (${getHistoryShortcutLabel("redo")})`
277
- : `Redo (${getHistoryShortcutLabel("redo")})`
278
- }
279
- side="bottom"
280
- >
281
- <button
282
- type="button"
283
- onClick={() => {
284
- trackStudioEvent("toolbar_action", { action: "redo" });
285
- void handleRedo();
286
- }}
287
- disabled={!editHistory.canRedo}
288
- className={`h-7 w-7 flex items-center justify-center rounded-md transition-colors active:scale-[0.98] ${
289
- editHistory.canRedo
290
- ? "text-neutral-400 hover:text-neutral-200 hover:bg-neutral-800"
291
- : "text-neutral-700 cursor-default"
292
- }`}
293
- aria-label="Redo"
294
- >
295
- <RotateCw size={14} />
296
- </button>
297
- </Tooltip>
298
- <Tooltip label={capturing ? "Capturing frame…" : "Capture current frame"} side="bottom">
299
- <a
300
- href={captureFrameHref}
301
- download={captureFrameFilename}
302
- onClick={(e) => {
303
- if (capturing) {
304
- e.preventDefault();
305
- return;
306
- }
307
- trackStudioEvent("toolbar_action", { action: "capture_frame" });
308
- handleCaptureFrameClick(e);
309
- }}
310
- onFocus={refreshCaptureFrameTime}
311
- onPointerDown={refreshCaptureFrameTime}
312
- aria-disabled={capturing || undefined}
313
- className={`h-7 flex items-center gap-1.5 px-2.5 rounded-md text-[11px] font-medium transition-colors ${
314
- capturing
315
- ? "text-neutral-600 cursor-default"
316
- : "text-neutral-400 hover:text-neutral-200 hover:bg-neutral-800 active:scale-[0.98]"
317
- }`}
318
- aria-label={capturing ? "Capturing frame" : "Capture current frame"}
319
- >
320
- {capturing ? (
321
- <svg
322
- className="animate-spin motion-reduce:animate-none h-3.5 w-3.5"
323
- viewBox="0 0 24 24"
324
- fill="none"
325
- aria-hidden="true"
326
- >
327
- <circle
328
- className="opacity-25"
329
- cx="12"
330
- cy="12"
331
- r="10"
182
+ <div className="flex items-center gap-3">
183
+ <div className="flex h-ctl items-center divide-x divide-border-strong overflow-hidden rounded-md border border-border-strong bg-bg-2">
184
+ <Tooltip label={capturing ? "Capturing frame…" : "Capture current frame"} side="bottom">
185
+ {/* A real download link, so it wears Button's recipe rather than being
186
+ one: `download` on an <a> is what saves the frame, and no <button>
187
+ can do that. `enabled:` never matches a link, so the ghost
188
+ variant's hover look is repeated unprefixed here. */}
189
+ <a
190
+ href={captureFrameHref}
191
+ download={captureFrameFilename}
192
+ onClick={(e) => {
193
+ if (capturing) {
194
+ e.preventDefault();
195
+ return;
196
+ }
197
+ trackStudioEvent("toolbar_action", { action: "capture_frame" });
198
+ handleCaptureFrameClick(e);
199
+ }}
200
+ onFocus={refreshCaptureFrameTime}
201
+ onPointerDown={refreshCaptureFrameTime}
202
+ aria-disabled={capturing || undefined}
203
+ className={cn(
204
+ buttonBase,
205
+ buttonVariants.ghost,
206
+ buttonSizes.md,
207
+ "h-full rounded-none max-[1000px]:px-2",
208
+ capturing
209
+ ? "text-text-4 cursor-default"
210
+ : "hover:bg-hover hover:text-text-0 active:scale-[0.98]",
211
+ )}
212
+ aria-label={capturing ? "Capturing frame" : "Capture current frame"}
213
+ >
214
+ {capturing ? (
215
+ <svg
216
+ className="animate-spin motion-reduce:animate-none h-3.5 w-3.5"
217
+ viewBox="0 0 24 24"
218
+ fill="none"
219
+ aria-hidden="true"
220
+ >
221
+ <circle
222
+ className="opacity-25"
223
+ cx="12"
224
+ cy="12"
225
+ r="10"
226
+ stroke="currentColor"
227
+ strokeWidth="4"
228
+ />
229
+ <path
230
+ className="opacity-75"
231
+ fill="currentColor"
232
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
233
+ />
234
+ </svg>
235
+ ) : (
236
+ <Camera size={14} />
237
+ )}
238
+ <span className="max-[1000px]:hidden">{capturing ? "Capturing…" : "Capture"}</span>
239
+ </a>
240
+ </Tooltip>
241
+ <Tooltip label="Inspector" side="bottom">
242
+ <Button
243
+ variant="ghost"
244
+ aria-label="Inspector"
245
+ aria-pressed={inspectorButtonActive}
246
+ className={cn(
247
+ "h-full rounded-none",
248
+ inspectorButtonActive && "bg-hover text-accent enabled:hover:text-accent",
249
+ )}
250
+ icon={
251
+ <svg
252
+ width="12"
253
+ height="12"
254
+ viewBox="0 0 24 24"
255
+ fill="none"
332
256
  stroke="currentColor"
333
- strokeWidth="4"
334
- />
335
- <path
336
- className="opacity-75"
337
- fill="currentColor"
338
- d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
339
- />
340
- </svg>
341
- ) : (
342
- <Camera size={14} />
343
- )}
344
- <span>{capturing ? "Capturing…" : "Capture"}</span>
345
- </a>
346
- </Tooltip>
347
- <Tooltip label="Inspector" side="bottom">
348
- <button
349
- type="button"
350
- onClick={() => {
351
- if (shouldOpenInspector(effectiveRightCollapsed, inspectorPanelActive)) {
352
- trackStudioEvent("panel_toggle", { panel: "inspector", collapsed: false });
353
- setRightPanelTab("design");
354
- setRightCollapsed(false);
355
- return;
257
+ strokeWidth="2"
258
+ >
259
+ <circle cx="12" cy="12" r="10" />
260
+ <polygon points="10 8 16 12 10 16" fill="currentColor" stroke="none" />
261
+ </svg>
356
262
  }
357
- trackStudioEvent("panel_toggle", { panel: "inspector", collapsed: true });
358
- // Keep the current selection when collapsing the Inspector — closing
359
- // the panel shouldn't deselect the element.
360
- setRightCollapsed(true);
361
- }}
362
- aria-pressed={inspectorButtonActive}
363
- className={`h-7 flex items-center gap-1.5 px-2.5 rounded-md text-[11px] font-medium border transition-colors active:scale-[0.98] ${
364
- inspectorButtonActive
365
- ? "text-studio-accent bg-studio-accent/10 border-studio-accent/30"
366
- : "text-neutral-500 hover:text-neutral-300 hover:bg-neutral-800 border-transparent"
367
- }`}
368
- aria-label="Inspector"
369
- >
370
- <svg
371
- width="12"
372
- height="12"
373
- viewBox="0 0 24 24"
374
- fill="none"
375
- stroke="currentColor"
376
- strokeWidth="2"
263
+ onClick={() => {
264
+ if (shouldOpenInspector(rightCollapsed, inspectorPanelActive)) {
265
+ trackStudioEvent("panel_toggle", { panel: "inspector", collapsed: false });
266
+ setRightPanelTab("design");
267
+ setRightCollapsed(false);
268
+ return;
269
+ }
270
+ trackStudioEvent("panel_toggle", { panel: "inspector", collapsed: true });
271
+ // Keep the current selection when collapsing the Inspector — closing
272
+ // the panel shouldn't deselect the element.
273
+ setRightCollapsed(true);
274
+ }}
377
275
  >
378
- <circle cx="12" cy="12" r="10" />
379
- <polygon points="10 8 16 12 10 16" fill="currentColor" stroke="none" />
380
- </svg>
381
- Inspector
382
- </button>
383
- </Tooltip>
276
+ Inspector
277
+ </Button>
278
+ </Tooltip>
279
+ </div>
280
+ <Dock.WindowMenu />
384
281
  <Tooltip
385
282
  label={
386
283
  ffmpegMissing
@@ -391,8 +288,9 @@ export function StudioHeader({
391
288
  }
392
289
  side="bottom"
393
290
  >
394
- <button
395
- type="button"
291
+ <Button
292
+ variant="primary"
293
+ data-testid="header-export"
396
294
  disabled={isRendering}
397
295
  onClick={() => {
398
296
  if (isRendering) return;
@@ -406,10 +304,9 @@ export function StudioHeader({
406
304
  if (ffmpegMissing) return;
407
305
  onExport?.();
408
306
  }}
409
- className="h-7 flex items-center gap-1.5 px-3 rounded-md text-[11px] font-semibold bg-studio-accent text-[#09090B] enabled:hover:brightness-110 transition-[filter,transform] enabled:active:scale-[0.98] disabled:opacity-50 disabled:cursor-not-allowed"
410
307
  >
411
308
  {isRendering ? "Rendering…" : "Export"}
412
- </button>
309
+ </Button>
413
310
  </Tooltip>
414
311
  </div>
415
312
  </div>
@@ -0,0 +1,202 @@
1
+ import { useCallback, type ReactNode } from "react";
2
+ import { SourceEditor } from "./editor/SourceEditor";
3
+ import { FileTree } from "./editor/FileTree";
4
+ import { MediaPreview } from "./MediaPreview";
5
+ import { AssetsTab } from "./sidebar/AssetsTab";
6
+ import { BlocksTab, type BlockPreviewInfo } from "./sidebar/BlocksTab";
7
+ import { CompositionsPanel } from "./sidebar/CompositionsPanel";
8
+ import { SidebarLintButton } from "./sidebar/SidebarLintButton";
9
+ import { Dock } from "./dock/Dock";
10
+ import { useDockLayoutStore } from "./dock/dockLayoutStore";
11
+ import { isMediaFile } from "../utils/mediaTypes";
12
+ import { useStudioShellContext } from "../contexts/StudioContext";
13
+ import { useFileManagerContext } from "../contexts/FileManagerContext";
14
+ import { getPersistedRenderSettings } from "./renders/renderSettings";
15
+
16
+ interface StudioLeftPanelsProps {
17
+ onSelectComposition: (comp: string) => void;
18
+ onAddBlock: (blockName: string) => void;
19
+ onPreviewBlock?: (preview: BlockPreviewInfo | null) => void;
20
+ onLint: () => void;
21
+ linting: boolean;
22
+ lintFindingCount?: number;
23
+ lintHasError?: boolean;
24
+ lintFindingsByFile?: Map<string, { count: number; messages: string[] }>;
25
+ onAddAssetToTimeline?: (path: string) => void;
26
+ onAddCompositionToTimeline?: (path: string) => void;
27
+ }
28
+
29
+ function PanelColumn({ footer, children }: { footer: ReactNode; children: ReactNode }) {
30
+ return (
31
+ <div className="flex h-full min-h-0 flex-col overflow-hidden bg-neutral-950">
32
+ <div className="flex min-h-0 flex-1 flex-col">{children}</div>
33
+ {footer}
34
+ </div>
35
+ );
36
+ }
37
+
38
+ // fallow-ignore-next-line complexity
39
+ export function StudioLeftPanels({
40
+ onSelectComposition,
41
+ onAddBlock,
42
+ onPreviewBlock,
43
+ onLint,
44
+ linting,
45
+ lintFindingCount,
46
+ lintHasError,
47
+ lintFindingsByFile,
48
+ onAddAssetToTimeline,
49
+ onAddCompositionToTimeline,
50
+ }: StudioLeftPanelsProps) {
51
+ const { projectId, renderQueue, waitForPendingDomEditSaves } = useStudioShellContext();
52
+ const {
53
+ compositions,
54
+ assets,
55
+ editingFile,
56
+ fileTree,
57
+ revealSourceOffset,
58
+ handleFileSelect,
59
+ handleCreateFile,
60
+ handleCreateFolder,
61
+ handleDeleteFile,
62
+ handleRenameFile,
63
+ handleDuplicateFile,
64
+ handleMoveFile,
65
+ handleImportFiles,
66
+ handleContentChange,
67
+ } = useFileManagerContext();
68
+
69
+ const handleRenderComposition = useCallback(
70
+ async (comp: string) => {
71
+ // startRender refuses without an encoder and reports why as a row in the
72
+ // Renders panel, which may be closed or behind another tab: bring it up.
73
+ if (renderQueue.ffmpegMissing) {
74
+ useDockLayoutStore.getState().activatePanel("renders");
75
+ return;
76
+ }
77
+ await waitForPendingDomEditSaves();
78
+ const { format, quality, fps } = getPersistedRenderSettings();
79
+ await renderQueue.startRender({ composition: comp, format, quality, fps });
80
+ },
81
+ [renderQueue, waitForPendingDomEditSaves],
82
+ );
83
+
84
+ const importFiles = async (files: FileList, dir?: string) => {
85
+ await handleImportFiles(files, dir);
86
+ };
87
+ const lintButton = (
88
+ <SidebarLintButton
89
+ onLint={onLint}
90
+ linting={linting}
91
+ findingCount={lintFindingCount}
92
+ hasError={lintHasError}
93
+ />
94
+ );
95
+
96
+ return (
97
+ <>
98
+ <Dock.Panel id="compositions">
99
+ <PanelColumn footer={lintButton}>
100
+ <CompositionsPanel
101
+ projectId={projectId}
102
+ compositions={compositions}
103
+ activeComposition={editingFile?.path ?? null}
104
+ onSelect={onSelectComposition}
105
+ onAddToTimeline={onAddCompositionToTimeline}
106
+ onRenderComposition={handleRenderComposition}
107
+ isRendering={renderQueue.isRendering}
108
+ lintFindingsByFile={lintFindingsByFile}
109
+ />
110
+ </PanelColumn>
111
+ </Dock.Panel>
112
+ <Dock.Panel id="assets">
113
+ <PanelColumn footer={lintButton}>
114
+ <AssetsTab
115
+ projectId={projectId}
116
+ assets={assets}
117
+ onImport={importFiles}
118
+ onDelete={handleDeleteFile}
119
+ onRename={handleRenameFile}
120
+ onAddAssetToTimeline={onAddAssetToTimeline}
121
+ />
122
+ </PanelColumn>
123
+ </Dock.Panel>
124
+ <Dock.Panel id="code">
125
+ <PanelColumn footer={lintButton}>
126
+ <div className="flex min-h-0 flex-1">
127
+ {fileTree.length > 0 && (
128
+ <div className="w-[160px] shrink-0 border-r border-neutral-800 overflow-y-auto">
129
+ <FileTree
130
+ files={fileTree}
131
+ activeFile={editingFile?.path ?? null}
132
+ onSelectFile={handleFileSelect}
133
+ onCreateFile={handleCreateFile}
134
+ onCreateFolder={handleCreateFolder}
135
+ onDeleteFile={handleDeleteFile}
136
+ onRenameFile={handleRenameFile}
137
+ onDuplicateFile={handleDuplicateFile}
138
+ onMoveFile={handleMoveFile}
139
+ onImportFiles={importFiles}
140
+ lintFindingsByFile={lintFindingsByFile}
141
+ />
142
+ </div>
143
+ )}
144
+ <div className="flex-1 overflow-hidden min-w-0">
145
+ <CodeBody
146
+ projectId={projectId}
147
+ editingFile={editingFile}
148
+ revealOffset={revealSourceOffset}
149
+ onChange={handleContentChange}
150
+ />
151
+ </div>
152
+ </div>
153
+ </PanelColumn>
154
+ </Dock.Panel>
155
+ <Dock.Panel id="catalog">
156
+ <PanelColumn footer={lintButton}>
157
+ <BlocksTab onAddBlock={onAddBlock} onPreviewBlock={onPreviewBlock} />
158
+ </PanelColumn>
159
+ </Dock.Panel>
160
+ </>
161
+ );
162
+ }
163
+
164
+ function CodeBody({
165
+ projectId,
166
+ editingFile,
167
+ revealOffset,
168
+ onChange,
169
+ }: {
170
+ projectId: string;
171
+ editingFile: { path: string; content: string | null } | null;
172
+ revealOffset: React.ComponentProps<typeof SourceEditor>["revealOffset"];
173
+ onChange: (content: string) => void;
174
+ }) {
175
+ if (!editingFile) {
176
+ return (
177
+ <div className="flex items-center justify-center h-full text-neutral-600 text-sm">
178
+ Select a file to edit
179
+ </div>
180
+ );
181
+ }
182
+ if (isMediaFile(editingFile.path)) {
183
+ return <MediaPreview projectId={projectId} filePath={editingFile.path} />;
184
+ }
185
+ // Never mount the editor on unloaded content: a keystroke would autosave an
186
+ // empty document over the real file.
187
+ if (editingFile.content == null) {
188
+ return (
189
+ <div className="flex h-full items-center justify-center text-[11px] text-neutral-600">
190
+ Loading {editingFile.path}…
191
+ </div>
192
+ );
193
+ }
194
+ return (
195
+ <SourceEditor
196
+ content={editingFile.content}
197
+ filePath={editingFile.path}
198
+ onChange={onChange}
199
+ revealOffset={revealOffset}
200
+ />
201
+ );
202
+ }
@@ -77,7 +77,7 @@ export function StudioOverlays({
77
77
  )}
78
78
  {/* One bottom-right stack so the feedback card and toasts queue instead
79
79
  of covering each other. Empty when nothing is showing. */}
80
- <div className="absolute bottom-6 right-6 z-[91] flex flex-col items-end gap-2">
80
+ <div className="absolute bottom-6 right-6 z-91 flex flex-col items-end gap-2">
81
81
  {toasts.map((toast) => (
82
82
  <StudioToast
83
83
  key={toast.id}