@hyperframes/studio 0.8.50 → 0.8.51

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 (215) hide show
  1. package/dist/assets/{hyperframes-player-CxxDxHTW.js → hyperframes-player-Cn_PpHqP.js} +3 -3
  2. package/dist/assets/index-C05SNrvY.js +360 -0
  3. package/dist/assets/{index-DUAIWxkI.js → index-CPS3Cvj8.js} +1 -1
  4. package/dist/assets/{index-Dt3qBI-9.js → index-Clrb11lj.js} +1 -1
  5. package/dist/assets/index-DUR9qzQM.css +1 -0
  6. package/dist/index.d.ts +18 -13
  7. package/dist/index.html +2 -2
  8. package/dist/index.js +1867 -3335
  9. package/dist/index.js.map +1 -1
  10. package/dist/styles/tailwind-preset.js.map +1 -1
  11. package/package.json +11 -12
  12. package/src/App.tsx +128 -141
  13. package/src/captions/components/CaptionAnimationPanel.tsx +4 -4
  14. package/src/captions/components/CaptionOverlayUtils.ts +2 -3
  15. package/src/captions/components/CaptionPropertyPanel.tsx +3 -3
  16. package/src/captions/components/CaptionTimeline.tsx +1 -1
  17. package/src/captions/components/shared.tsx +2 -2
  18. package/src/components/AskAgentModal.tsx +5 -5
  19. package/src/components/EditorShell.tsx +4 -7
  20. package/src/components/ExternalFileConflictBanner.tsx +16 -16
  21. package/src/components/LintModal.tsx +6 -16
  22. package/src/components/MediaPreview.tsx +2 -2
  23. package/src/components/SaveQueuePausedBanner.tsx +2 -2
  24. package/src/components/StudioHeader.tsx +2 -62
  25. package/src/components/StudioLeftSidebar.tsx +7 -4
  26. package/src/components/StudioOverlays.tsx +1 -1
  27. package/src/components/StudioRightPanel.tsx +4 -4
  28. package/src/components/StudioToast.tsx +2 -2
  29. package/src/components/TimelineToolbar.tsx +7 -7
  30. package/src/components/dock/Dock.test.tsx +192 -0
  31. package/src/components/dock/Dock.tsx +264 -0
  32. package/src/components/dock/dock.css +23 -0
  33. package/src/components/dock/dockLayout.ts +58 -0
  34. package/src/components/dock/dockLayoutSchema.ts +66 -0
  35. package/src/components/dock/dockLayoutStore.ts +91 -0
  36. package/src/components/dock/panelRegistry.ts +67 -0
  37. package/src/components/editor/AnimationCard.tsx +4 -4
  38. package/src/components/editor/AnimationCardParts.tsx +6 -6
  39. package/src/components/editor/BlockParamsPanel.tsx +4 -4
  40. package/src/components/editor/BorderRadiusEditor.tsx +1 -1
  41. package/src/components/editor/CanvasContextMenu.tsx +1 -1
  42. package/src/components/editor/ComputedTweenNotice.tsx +1 -1
  43. package/src/components/editor/DomEditOverlay.tsx +1 -1
  44. package/src/components/editor/EaseCurveSection.tsx +1 -1
  45. package/src/components/editor/EaseParamFields.tsx +5 -5
  46. package/src/components/editor/FileTree.tsx +4 -4
  47. package/src/components/editor/FileTreeIcons.tsx +1 -1
  48. package/src/components/editor/FileTreeNodes.tsx +13 -13
  49. package/src/components/editor/InlineTextToolbar.tsx +1 -1
  50. package/src/components/editor/InspectorHeaderActions.tsx +3 -3
  51. package/src/components/editor/KeyframeDiamond.tsx +1 -1
  52. package/src/components/editor/KeyframeEaseList.tsx +1 -1
  53. package/src/components/editor/LayersPanel.tsx +3 -3
  54. package/src/components/editor/MarqueeOverlay.tsx +1 -1
  55. package/src/components/editor/OffCanvasIndicators.tsx +1 -1
  56. package/src/components/editor/PromotableControl.tsx +2 -2
  57. package/src/components/editor/PropertyPanelEmptyState.tsx +7 -7
  58. package/src/components/editor/PropertyPanelFlatHeader.tsx +2 -2
  59. package/src/components/editor/SnapToolbar.tsx +2 -2
  60. package/src/components/editor/TimelineFxPopover.tsx +1 -1
  61. package/src/components/editor/TopologyLens.tsx +4 -4
  62. package/src/components/editor/Transform3DCube.tsx +2 -2
  63. package/src/components/editor/audioFxRevealTarget.ts +1 -0
  64. package/src/components/editor/domEditing.test.ts +1 -1
  65. package/src/components/editor/domEditingAgentPrompt.test.ts +8 -6
  66. package/src/components/editor/domEditingAgentPrompt.ts +4 -3
  67. package/src/components/editor/propertyPanelColor.tsx +11 -11
  68. package/src/components/editor/propertyPanelColorCurveGraph.tsx +1 -1
  69. package/src/components/editor/propertyPanelColorGradingControls.tsx +7 -9
  70. package/src/components/editor/propertyPanelColorGradingSection.tsx +6 -6
  71. package/src/components/editor/propertyPanelColorGradingSlider.tsx +5 -5
  72. package/src/components/editor/propertyPanelColorWheels.tsx +1 -1
  73. package/src/components/editor/propertyPanelCommitField.tsx +1 -1
  74. package/src/components/editor/propertyPanelFill.tsx +4 -4
  75. package/src/components/editor/propertyPanelFlatColorGradingAccessory.tsx +3 -3
  76. package/src/components/editor/propertyPanelFlatColorGradingSection.tsx +7 -7
  77. package/src/components/editor/propertyPanelFlatEffectsSection.tsx +4 -4
  78. package/src/components/editor/propertyPanelFlatMediaSection.tsx +3 -3
  79. package/src/components/editor/propertyPanelFlatOverlaysSection.tsx +1 -1
  80. package/src/components/editor/propertyPanelFlatPrimitives.tsx +10 -10
  81. package/src/components/editor/propertyPanelFlatSelectRow.tsx +3 -3
  82. package/src/components/editor/propertyPanelFlatTextSection.test.tsx +8 -9
  83. package/src/components/editor/propertyPanelFlatTextSection.tsx +5 -5
  84. package/src/components/editor/propertyPanelFlatToggle.tsx +1 -1
  85. package/src/components/editor/propertyPanelFont.tsx +5 -5
  86. package/src/components/editor/propertyPanelFxCarveModule.tsx +1 -1
  87. package/src/components/editor/propertyPanelFxControls.test.tsx +1 -1
  88. package/src/components/editor/propertyPanelFxControls.tsx +6 -6
  89. package/src/components/editor/propertyPanelFxEqModule.tsx +2 -2
  90. package/src/components/editor/propertyPanelFxPresetStyle.ts +2 -2
  91. package/src/components/editor/propertyPanelGradingNumberField.tsx +1 -1
  92. package/src/components/editor/propertyPanelMediaSection.tsx +1 -1
  93. package/src/components/editor/propertyPanelPrimitives.tsx +7 -7
  94. package/src/components/editor/propertyPanelSections.tsx +8 -8
  95. package/src/components/feedback/StudioFeedbackCard.tsx +7 -7
  96. package/src/components/feedback/feedbackTrigger.ts +0 -1
  97. package/src/components/nle/AssetPreviewOverlay.tsx +6 -2
  98. package/src/components/nle/CompositionBreadcrumb.tsx +3 -3
  99. package/src/components/nle/NLEPreview.tsx +3 -3
  100. package/src/components/nle/PreviewOverlays.tsx +6 -6
  101. package/src/components/nle/PreviewPane.tsx +2 -2
  102. package/src/components/nle/TimelinePane.tsx +3 -3
  103. package/src/components/nle/TimelineResizeDivider.tsx +2 -2
  104. package/src/components/panels/SlideshowPanel.tsx +2 -2
  105. package/src/components/panels/SlideshowSubPanels.tsx +20 -17
  106. package/src/components/panels/VariablesBindElement.tsx +2 -2
  107. package/src/components/panels/VariablesDeclarationForm.tsx +2 -2
  108. package/src/components/panels/VariablesOtherCompositions.tsx +1 -1
  109. package/src/components/panels/VariablesPanel.tsx +3 -3
  110. package/src/components/panels/VariablesValueControls.tsx +2 -2
  111. package/src/components/renders/FfmpegRequiredNotice.tsx +5 -5
  112. package/src/components/renders/RenderQueue.test.tsx +7 -0
  113. package/src/components/renders/RenderQueue.tsx +6 -6
  114. package/src/components/renders/RenderQueueItem.tsx +6 -6
  115. package/src/components/sidebar/AssetCard.tsx +8 -8
  116. package/src/components/sidebar/AssetContextMenu.tsx +8 -8
  117. package/src/components/sidebar/AssetsTab.tsx +2 -2
  118. package/src/components/sidebar/AudioRow.tsx +6 -6
  119. package/src/components/sidebar/BlocksTab.tsx +6 -6
  120. package/src/components/sidebar/CompositionsTab.tsx +5 -5
  121. package/src/components/sidebar/GlobalAssetsView.tsx +1 -1
  122. package/src/components/sidebar/LeftSidebar.lintBadge.test.tsx +58 -0
  123. package/src/components/sidebar/LeftSidebar.tsx +19 -5
  124. package/src/components/sidebar/PromptPreviewModal.tsx +3 -3
  125. package/src/components/ui/Button.test.tsx +60 -0
  126. package/src/components/ui/Button.tsx +4 -4
  127. package/src/components/ui/SearchInput.tsx +2 -2
  128. package/src/components/ui/Tooltip.tsx +1 -1
  129. package/src/hooks/useAppHotkeys.ts +1 -1
  130. package/src/hooks/useLintModal.test.tsx +65 -0
  131. package/src/hooks/useLintModal.ts +3 -0
  132. package/src/hooks/useSdkSession.lifecycle.test.tsx +49 -4
  133. package/src/hooks/useSdkSession.ts +43 -10
  134. package/src/hooks/useTimelineAssetDropOps.test.tsx +41 -1
  135. package/src/hooks/useTimelineAssetDropOps.ts +52 -11
  136. package/src/main.tsx +9 -3
  137. package/src/player/components/AudioWaveform.tsx +1 -1
  138. package/src/player/components/AutomationSelectionMenu.tsx +2 -2
  139. package/src/player/components/ClipContextMenu.tsx +3 -3
  140. package/src/player/components/CompositionThumbnail.test.ts +0 -3
  141. package/src/player/components/CompositionThumbnail.tsx +3 -4
  142. package/src/player/components/EditModal.tsx +1 -1
  143. package/src/player/components/ImageThumbnail.tsx +1 -1
  144. package/src/player/components/KeyframeDiamondContextMenu.tsx +4 -4
  145. package/src/player/components/LayerDisclosureRow.tsx +2 -2
  146. package/src/player/components/PlayerControls.tsx +1 -1
  147. package/src/player/components/ShortcutsPanel.tsx +9 -9
  148. package/src/player/components/SpeedMenu.tsx +3 -5
  149. package/src/player/components/Timeline.tsx +2 -1
  150. package/src/player/components/TimelineCanvas.tsx +17 -10
  151. package/src/player/components/TimelineDiamondConnectors.tsx +1 -1
  152. package/src/player/components/TimelineEmptyState.tsx +5 -5
  153. package/src/player/components/TimelineFxButton.tsx +6 -6
  154. package/src/player/components/TimelineGroupHeader.tsx +5 -5
  155. package/src/player/components/TimelineGroupLaneLabels.tsx +1 -1
  156. package/src/player/components/TimelineGroupRow.tsx +1 -1
  157. package/src/player/components/TimelineLanes.test.tsx +32 -0
  158. package/src/player/components/TimelineLanes.tsx +2 -5
  159. package/src/player/components/TimelineLayerGroupHeader.tsx +2 -2
  160. package/src/player/components/TimelineRuler.tsx +1 -1
  161. package/src/player/components/TimelineShortcutHint.tsx +1 -1
  162. package/src/player/components/TimelineTrackHeader.tsx +1 -1
  163. package/src/player/components/TimelineTrackPlainHeader.tsx +3 -3
  164. package/src/player/components/TimelineTypes.ts +2 -1
  165. package/src/player/components/TrackGapContextMenu.tsx +1 -1
  166. package/src/player/components/VideoThumbnail.tsx +4 -2
  167. package/src/player/components/VolumeControl.tsx +2 -2
  168. package/src/player/components/timelineCallbacks.ts +8 -8
  169. package/src/player/components/timelineClipDragPreview.ts +51 -27
  170. package/src/player/components/timelineClipDragTypes.ts +3 -0
  171. package/src/player/components/timelineDragDrop.test.tsx +61 -1
  172. package/src/player/components/timelineDragDrop.ts +57 -15
  173. package/src/player/components/timelineLaneProps.ts +3 -0
  174. package/src/player/components/timelineSnapping.test.ts +27 -0
  175. package/src/player/components/timelineSnapping.ts +14 -1
  176. package/src/player/components/trackHeaderLabelRows.tsx +4 -4
  177. package/src/player/components/useTimelineClipDrag.resize.test.tsx +136 -2
  178. package/src/player/components/useTimelineClipDrag.ts +30 -3
  179. package/src/player/lib/describeClips.ts +3 -54
  180. package/src/styles/iconTokens.ts +20 -0
  181. package/src/styles/palette-reset.css +6 -0
  182. package/src/styles/studio.css +24 -21
  183. package/src/styles/tailwind-preset.shared.js +3 -0
  184. package/src/styles/theme.css +213 -0
  185. package/src/styles/theme.test.ts +196 -0
  186. package/src/utils/studioUiPreferences.ts +7 -0
  187. package/src/utils/timelineDropTrackInsert.test.ts +134 -0
  188. package/src/utils/timelineDropTrackInsert.ts +83 -0
  189. package/dist/assets/index-n2ml4tUn.js +0 -442
  190. package/dist/assets/index-pO6p0H27.css +0 -1
  191. package/src/components/storyboard/AgentChatMessageButton.test.tsx +0 -47
  192. package/src/components/storyboard/AgentChatMessageButton.tsx +0 -45
  193. package/src/components/storyboard/FramePoster.test.tsx +0 -61
  194. package/src/components/storyboard/FramePoster.tsx +0 -86
  195. package/src/components/storyboard/StoryboardDirection.tsx +0 -45
  196. package/src/components/storyboard/StoryboardFrameFocus.tsx +0 -412
  197. package/src/components/storyboard/StoryboardFrameTile.tsx +0 -117
  198. package/src/components/storyboard/StoryboardGrid.tsx +0 -55
  199. package/src/components/storyboard/StoryboardLoaded.tsx +0 -307
  200. package/src/components/storyboard/StoryboardReviewGuide.tsx +0 -300
  201. package/src/components/storyboard/StoryboardScriptPanel.tsx +0 -26
  202. package/src/components/storyboard/StoryboardSourceEditor.tsx +0 -231
  203. package/src/components/storyboard/StoryboardStatusLegend.tsx +0 -21
  204. package/src/components/storyboard/StoryboardView.tsx +0 -169
  205. package/src/components/storyboard/StoryboardViewModeGuard.test.tsx +0 -187
  206. package/src/components/storyboard/frameComments.test.ts +0 -95
  207. package/src/components/storyboard/frameComments.ts +0 -115
  208. package/src/components/storyboard/frameStatus.ts +0 -36
  209. package/src/components/storyboard/storyboardReviewStage.test.ts +0 -40
  210. package/src/components/storyboard/storyboardReviewStage.ts +0 -45
  211. package/src/components/storyboard/useFrameComments.ts +0 -98
  212. package/src/contexts/ViewModeContext.tsx +0 -142
  213. package/src/hooks/useProjectSignaturePoll.test.tsx +0 -135
  214. package/src/hooks/useProjectSignaturePoll.ts +0 -68
  215. package/src/hooks/useStoryboard.ts +0 -99
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/styles/tailwind-preset.shared.js","../../src/styles/tailwind-preset.ts"],"sourcesContent":["const studioPreset = {\n theme: {\n extend: {\n colors: {\n studio: {\n bg: \"#0a0a0a\",\n surface: \"#141414\",\n border: \"#262626\",\n text: \"#e5e5e5\",\n muted: \"#737373\",\n accent: \"#3CE6AC\",\n },\n panel: {\n bg: \"#0C0C0E\",\n // Open inspector-section body — slightly lighter than headers (bg)\n // so the recessed scrollable region reads distinct.\n \"bg-inset\": \"#121214\",\n input: \"#161618\",\n surface: \"#18181B\",\n hover: \"#27272A\",\n border: \"#1E1E1E\",\n \"border-input\": \"#27272A\",\n hairline: \"#1A1A1C\",\n \"text-0\": \"#FAFAFA\",\n \"text-1\": \"#E4E4E7\",\n \"text-2\": \"#A1A1AA\",\n \"text-3\": \"#71717A\",\n \"text-4\": \"#52525B\",\n \"text-5\": \"#3F3F46\",\n accent: \"#3CE6AC\",\n danger: \"#EF4444\",\n media: \"#00E3FF\",\n container: \"#F5A623\",\n },\n },\n },\n },\n plugins: [],\n};\n\nexport default studioPreset;\n","import studioPreset from \"./tailwind-preset.shared.js\";\n\nexport default studioPreset;\n"],"mappings":";;;AAAA,IAAM,eAAe;AAAA,EACnB,OAAO;AAAA,IACL,QAAQ;AAAA,MACN,QAAQ;AAAA,QACN,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,QACA,OAAO;AAAA,UACL,IAAI;AAAA;AAAA;AAAA,UAGJ,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,SAAS;AAAA,UACT,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,SAAS,CAAC;AACZ;AAEA,IAAO,iCAAQ;;;ACtCf,IAAO,0BAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/styles/tailwind-preset.shared.js","../../src/styles/tailwind-preset.ts"],"sourcesContent":["/** @deprecated Superseded by `src/styles/theme.css` (published as\n * `@hyperframes/studio/theme.css`); kept one more major for Tailwind v3\n * consumers. Values are byte-identical; theme.test.ts fails if they drift. */\nconst studioPreset = {\n theme: {\n extend: {\n colors: {\n studio: {\n bg: \"#0a0a0a\",\n surface: \"#141414\",\n border: \"#262626\",\n text: \"#e5e5e5\",\n muted: \"#737373\",\n accent: \"#3CE6AC\",\n },\n panel: {\n bg: \"#0C0C0E\",\n // Open inspector-section body — slightly lighter than headers (bg)\n // so the recessed scrollable region reads distinct.\n \"bg-inset\": \"#121214\",\n input: \"#161618\",\n surface: \"#18181B\",\n hover: \"#27272A\",\n border: \"#1E1E1E\",\n \"border-input\": \"#27272A\",\n hairline: \"#1A1A1C\",\n \"text-0\": \"#FAFAFA\",\n \"text-1\": \"#E4E4E7\",\n \"text-2\": \"#A1A1AA\",\n \"text-3\": \"#71717A\",\n \"text-4\": \"#52525B\",\n \"text-5\": \"#3F3F46\",\n accent: \"#3CE6AC\",\n danger: \"#EF4444\",\n media: \"#00E3FF\",\n container: \"#F5A623\",\n },\n },\n },\n },\n plugins: [],\n};\n\nexport default studioPreset;\n","import studioPreset from \"./tailwind-preset.shared.js\";\n\nexport default studioPreset;\n"],"mappings":";;;AAGA,IAAM,eAAe;AAAA,EACnB,OAAO;AAAA,IACL,QAAQ;AAAA,MACN,QAAQ;AAAA,QACN,QAAQ;AAAA,UACN,IAAI;AAAA,UACJ,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,QACA,OAAO;AAAA,UACL,IAAI;AAAA;AAAA;AAAA,UAGJ,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,SAAS;AAAA,UACT,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,gBAAgB;AAAA,UAChB,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,UAAU;AAAA,UACV,QAAQ;AAAA,UACR,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,SAAS,CAAC;AACZ;AAEA,IAAO,iCAAQ;;;ACzCf,IAAO,0BAAQ;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperframes/studio",
3
- "version": "0.8.50",
3
+ "version": "0.8.51",
4
4
  "description": "",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,6 +23,7 @@
23
23
  "import": "./dist/styles/tailwind-preset.js",
24
24
  "types": "./dist/styles/tailwind-preset.d.ts"
25
25
  },
26
+ "./theme.css": "./src/styles/theme.css",
26
27
  "./package.json": "./package.json"
27
28
  },
28
29
  "publishConfig": {
@@ -44,32 +45,30 @@
44
45
  "@phosphor-icons/react": "^2.1.10",
45
46
  "@tanstack/react-virtual": "^3.14.6",
46
47
  "bpm-detective": "^2.0.5",
47
- "dompurify": "^3.2.4",
48
+ "dockview-react": "8.3.1",
48
49
  "gsap": "^3.13.0",
49
- "marked": "^14.1.4",
50
50
  "mediabunny": "^1.45.3",
51
- "@hyperframes/player": "0.8.50",
52
- "@hyperframes/core": "0.8.50",
53
- "@hyperframes/studio-server": "0.8.50",
54
- "@hyperframes/sdk": "0.8.50",
55
- "@hyperframes/parsers": "0.8.50"
51
+ "@hyperframes/core": "0.8.51",
52
+ "@hyperframes/player": "0.8.51",
53
+ "@hyperframes/studio-server": "0.8.51",
54
+ "@hyperframes/sdk": "0.8.51",
55
+ "@hyperframes/parsers": "0.8.51"
56
56
  },
57
57
  "devDependencies": {
58
+ "@tailwindcss/vite": "^4.3.3",
58
59
  "@types/react": "19",
59
60
  "@types/react-dom": "19",
60
61
  "@vitejs/plugin-react": "^4.0.0",
61
- "autoprefixer": "^10.4.0",
62
62
  "chokidar": "^4.0.3",
63
63
  "fake-indexeddb": "^6.2.5",
64
- "postcss": "^8.4.0",
65
64
  "puppeteer-core": "^25.2.1",
66
- "tailwindcss": "^3.4.0",
65
+ "tailwindcss": "^4.3.3",
67
66
  "tsup": "^8.0.0",
68
67
  "typescript": "^5.0.0",
69
68
  "vite": "^6.4.2",
70
69
  "vitest": "^4.1.11",
71
70
  "zustand": "^5.0.0",
72
- "@hyperframes/producer": "0.8.50"
71
+ "@hyperframes/producer": "0.8.51"
73
72
  },
74
73
  "peerDependencies": {
75
74
  "react": "19",
package/src/App.tsx CHANGED
@@ -53,8 +53,6 @@ import { StudioRightPanel } from "./components/StudioRightPanel";
53
53
  import { TimelineToolbar } from "./components/TimelineToolbar";
54
54
  import { StudioPlaybackProvider, StudioShellProvider } from "./contexts/StudioContext";
55
55
  import { PanelLayoutProvider } from "./contexts/PanelLayoutContext";
56
- import { ViewModeProvider, useViewModeState } from "./contexts/ViewModeContext";
57
- import { StoryboardView } from "./components/storyboard/StoryboardView";
58
56
  import { FileManagerProvider } from "./contexts/FileManagerContext";
59
57
  import { DomEditProvider } from "./contexts/DomEditContext";
60
58
  import { StudioSplash } from "./components/StudioSplash";
@@ -68,7 +66,6 @@ const getTimelineSelectionSet = () => usePlayerStore.getState().selectedElementI
68
66
  export function StudioApp() {
69
67
  const { projectId, resolving, waitingForServer } = useServerConnection();
70
68
  const initialUrlStateRef = useRef(readStudioUrlStateFromWindow());
71
- const viewModeValue = useViewModeState();
72
69
  useStudioSessionStart(projectId, resolving, waitingForServer);
73
70
  const [compIdToSrc, setCompIdToSrc] = useState<Map<string, string>>(new Map());
74
71
  const [previewIframe, setPreviewIframe] = useState<HTMLIFrameElement | null>(null);
@@ -327,10 +324,8 @@ export function StudioApp() {
327
324
  effectiveTimelineDuration,
328
325
  });
329
326
  const compositionDimensions = useCompositionDimensions(previewIframeRef);
330
- const { lintModal, linting, handleLint, closeLintModal, findingsByFile } = useLintModal(
331
- projectId,
332
- refreshKey,
333
- );
327
+ const { lintModal, linting, handleLint, closeLintModal, findingsByFile, hasLintError } =
328
+ useLintModal(projectId, refreshKey);
334
329
  const frameCapture = useFrameCapture({
335
330
  projectId,
336
331
  activeCompPath,
@@ -441,144 +436,136 @@ export function StudioApp() {
441
436
  return (
442
437
  <StudioShellProvider value={studioCtxValue}>
443
438
  <StudioPlaybackProvider value={studioCtxValue}>
444
- <ViewModeProvider value={viewModeValue}>
445
- <PanelLayoutProvider value={panelLayout}>
446
- <FileManagerProvider value={fileManager}>
447
- <DomEditProvider value={domEditSession}>
448
- <div
449
- className="flex flex-col h-full w-full bg-neutral-950 relative"
450
- onDragOver={fileDrop.onDragOver}
451
- onDrop={fileDrop.onDrop}
452
- >
453
- <StudioHeader
454
- captureFrameHref={frameCapture.captureFrameHref}
455
- captureFrameFilename={frameCapture.captureFrameFilename}
456
- handleCaptureFrameClick={frameCapture.handleCaptureFrameClick}
457
- refreshCaptureFrameTime={frameCapture.refreshCaptureFrameTime}
458
- capturing={frameCapture.capturing}
459
- inspectorButtonActive={inspectorButtonActive}
460
- inspectorPanelActive={inspectorPanelActive}
461
- onExport={() => {
462
- void (async () => {
463
- await previewPersistence.waitForPendingDomEditSaves();
464
- await renderQueue.startRender(undefined);
465
- })();
466
- }}
439
+ <PanelLayoutProvider value={panelLayout}>
440
+ <FileManagerProvider value={fileManager}>
441
+ <DomEditProvider value={domEditSession}>
442
+ <div
443
+ className="flex flex-col h-full w-full bg-neutral-950 relative"
444
+ onDragOver={fileDrop.onDragOver}
445
+ onDrop={fileDrop.onDrop}
446
+ >
447
+ <StudioHeader
448
+ captureFrameHref={frameCapture.captureFrameHref}
449
+ captureFrameFilename={frameCapture.captureFrameFilename}
450
+ handleCaptureFrameClick={frameCapture.handleCaptureFrameClick}
451
+ refreshCaptureFrameTime={frameCapture.refreshCaptureFrameTime}
452
+ capturing={frameCapture.capturing}
453
+ inspectorButtonActive={inspectorButtonActive}
454
+ inspectorPanelActive={inspectorPanelActive}
455
+ onExport={() => {
456
+ void (async () => {
457
+ await previewPersistence.waitForPendingDomEditSaves();
458
+ await renderQueue.startRender(undefined);
459
+ })();
460
+ }}
461
+ />
462
+ {previewPersistence.domEditSaveQueuePaused && !externalFileChanges.blocked && (
463
+ <SaveQueuePausedBanner
464
+ message={previewPersistence.domEditSaveQueuePaused}
465
+ onRetry={previewPersistence.resetDomEditSaveQueueBreaker}
467
466
  />
468
- {previewPersistence.domEditSaveQueuePaused && !externalFileChanges.blocked && (
469
- <SaveQueuePausedBanner
470
- message={previewPersistence.domEditSaveQueuePaused}
471
- onRetry={previewPersistence.resetDomEditSaveQueueBreaker}
472
- />
473
- )}
474
- <ExternalFileConflictBanner coordinator={externalFileChanges} />
475
- {viewModeValue.viewMode === "storyboard" && (
476
- <StoryboardView
477
- projectId={projectId}
467
+ )}
468
+ <ExternalFileConflictBanner coordinator={externalFileChanges} />
469
+ <EditorShell
470
+ left={
471
+ <StudioLeftSidebar
472
+ leftSidebarRef={leftSidebarRef}
478
473
  onSelectComposition={handleSelectComposition}
474
+ onAddBlock={handleAddBlock}
475
+ onPreviewBlock={setBlockPreview}
476
+ onLint={handleLint}
477
+ linting={linting}
478
+ lintFindingCount={lintModal?.length ?? findingsByFile.size}
479
+ lintFindingsByFile={findingsByFile}
480
+ lintHasError={hasLintError}
481
+ onAddAssetToTimeline={handleAddAssetAtPlayhead}
482
+ onAddCompositionToTimeline={handleAddCompositionAtPlayhead}
479
483
  />
480
- )}
481
- <EditorShell
482
- hidden={viewModeValue.viewMode === "storyboard"}
483
- left={
484
- <StudioLeftSidebar
485
- leftSidebarRef={leftSidebarRef}
486
- onSelectComposition={handleSelectComposition}
487
- onAddBlock={handleAddBlock}
488
- onPreviewBlock={setBlockPreview}
489
- onLint={handleLint}
490
- linting={linting}
491
- lintFindingCount={lintModal?.length ?? findingsByFile.size}
492
- lintFindingsByFile={findingsByFile}
493
- onAddAssetToTimeline={handleAddAssetAtPlayhead}
494
- onAddCompositionToTimeline={handleAddCompositionAtPlayhead}
484
+ }
485
+ right={
486
+ panelLayout.effectiveRightCollapsed ? null : (
487
+ <StudioRightPanel
488
+ designPanelActive={designPanelActive}
489
+ activeBlockParams={activeBlockParams}
490
+ onCloseBlockParams={() => {
491
+ setActiveBlockParams(null);
492
+ panelLayout.setRightPanelTab("design");
493
+ }}
494
+ recordingState={gestureState}
495
+ recordingDuration={gestureRecording.recordingDuration}
496
+ onToggleRecording={handleToggleRecording}
497
+ sdkSession={sdkHandle.session}
498
+ publishSdkSession={sdkHandle.publish}
499
+ forceReloadSdkSession={sdkHandle.forceReload}
500
+ reloadPreview={reloadPreview}
501
+ recordEdit={editHistory.recordEdit}
502
+ onToggleElementHidden={timelineEditing.handleToggleElementHidden}
503
+ onAutoGroupCarveSources={timelineEditing.handleAutoGroupCarveSources}
504
+ onAddMediaOverlay={handleAddMediaOverlay}
495
505
  />
496
- }
497
- right={
498
- panelLayout.effectiveRightCollapsed ? null : (
499
- <StudioRightPanel
500
- designPanelActive={designPanelActive}
501
- activeBlockParams={activeBlockParams}
502
- onCloseBlockParams={() => {
503
- setActiveBlockParams(null);
504
- panelLayout.setRightPanelTab("design");
505
- }}
506
- recordingState={gestureState}
507
- recordingDuration={gestureRecording.recordingDuration}
508
- onToggleRecording={handleToggleRecording}
509
- sdkSession={sdkHandle.session}
510
- publishSdkSession={sdkHandle.publish}
511
- forceReloadSdkSession={sdkHandle.forceReload}
512
- reloadPreview={reloadPreview}
513
- recordEdit={editHistory.recordEdit}
514
- onToggleElementHidden={timelineEditing.handleToggleElementHidden}
515
- onAutoGroupCarveSources={timelineEditing.handleAutoGroupCarveSources}
516
- onAddMediaOverlay={handleAddMediaOverlay}
517
- />
518
- )
519
- }
520
- timelineToolbar={timelineToolbar}
521
- renderClipContent={renderClipContent}
522
- handleTimelineElementDelete={timelineEditing.handleTimelineElementDelete}
523
- handleTimelineAssetDrop={timelineEditing.handleTimelineAssetDrop}
524
- handleTimelineBlockDrop={handleTimelineBlockDrop}
525
- handleTimelineCompositionDrop={timelineEditing.handleTimelineCompositionDrop}
526
- handlePreviewBlockDrop={handlePreviewBlockDrop}
527
- handleTimelineFileDrop={timelineEditing.handleTimelineFileDrop}
528
- handleTimelineElementMove={timelineEditing.handleTimelineElementMove}
529
- handleTimelineElementsMove={handleTimelineElementsMove}
530
- handleTimelineElementResize={timelineEditing.handleTimelineElementResize}
531
- handleTimelineGroupResize={timelineEditing.handleTimelineGroupResize}
532
- handleToggleTrackHidden={timelineEditing.handleToggleTrackHidden}
533
- setAudioGroupAttribute={timelineEditing.setAudioGroupAttribute}
534
- handleGroupClips={timelineEditing.handleAutoGroupCarveSources}
535
- setElementFxAttribute={timelineEditing.setElementFxAttribute}
536
- handleBlockedTimelineEdit={timelineEditing.handleBlockedTimelineEdit}
537
- handleTimelineElementSplit={timelineEditing.handleTimelineElementSplit}
538
- handleRazorSplit={timelineEditing.handleRazorSplit}
539
- handleRazorSplitAll={timelineEditing.handleRazorSplitAll}
540
- onCopyClip={handleCopy}
541
- onPasteClip={handlePaste}
542
- onDuplicateClip={handleDuplicate}
543
- canPasteClip={canPaste}
544
- setCompIdToSrc={setCompIdToSrc}
545
- setCompositionLoading={setCompositionLoading}
546
- shouldShowMotionPath={shouldShowMotionPath}
547
- shouldShowSelectedDomBounds={shouldShowSelectedDomBounds}
548
- isGestureRecording={gestureState === "recording"}
549
- recordingState={gestureState}
550
- onToggleRecording={handleToggleRecording}
551
- blockPreview={blockPreview}
552
- gestureOverlay={
553
- gestureState === "recording" && previewIframe ? (
554
- <GestureTrailOverlay
555
- samples={gestureRecording.samplesRef.current}
556
- sampleCount={gestureRecording.samplesRef.current.length}
557
- trail={gestureRecording.trailRef.current}
558
- canvasRect={canvasRectRef.current!}
559
- compositionSize={compositionDimensions ?? undefined}
560
- mode="recording"
561
- />
562
- ) : undefined
563
- }
564
- />
565
- <StudioOverlays
566
- projectId={projectId}
567
- projectDir={fileManager.projectDir}
568
- lintModal={lintModal}
569
- closeLintModal={closeLintModal}
570
- consoleErrors={consoleErrors}
571
- clearConsoleErrors={() => setConsoleErrors(null)}
572
- domEditSession={domEditSession}
573
- activeCompPath={activeCompPath}
574
- toasts={toasts}
575
- dismissToast={dismissToast}
576
- />
577
- </div>
578
- </DomEditProvider>
579
- </FileManagerProvider>
580
- </PanelLayoutProvider>
581
- </ViewModeProvider>
506
+ )
507
+ }
508
+ timelineToolbar={timelineToolbar}
509
+ renderClipContent={renderClipContent}
510
+ handleTimelineElementDelete={timelineEditing.handleTimelineElementDelete}
511
+ handleTimelineAssetDrop={timelineEditing.handleTimelineAssetDrop}
512
+ handleTimelineBlockDrop={handleTimelineBlockDrop}
513
+ handleTimelineCompositionDrop={timelineEditing.handleTimelineCompositionDrop}
514
+ handlePreviewBlockDrop={handlePreviewBlockDrop}
515
+ handleTimelineFileDrop={timelineEditing.handleTimelineFileDrop}
516
+ handleTimelineElementMove={timelineEditing.handleTimelineElementMove}
517
+ handleTimelineElementsMove={handleTimelineElementsMove}
518
+ handleTimelineElementResize={timelineEditing.handleTimelineElementResize}
519
+ handleTimelineGroupResize={timelineEditing.handleTimelineGroupResize}
520
+ handleToggleTrackHidden={timelineEditing.handleToggleTrackHidden}
521
+ setAudioGroupAttribute={timelineEditing.setAudioGroupAttribute}
522
+ handleGroupClips={timelineEditing.handleAutoGroupCarveSources}
523
+ setElementFxAttribute={timelineEditing.setElementFxAttribute}
524
+ handleBlockedTimelineEdit={timelineEditing.handleBlockedTimelineEdit}
525
+ handleTimelineElementSplit={timelineEditing.handleTimelineElementSplit}
526
+ handleRazorSplit={timelineEditing.handleRazorSplit}
527
+ handleRazorSplitAll={timelineEditing.handleRazorSplitAll}
528
+ onCopyClip={handleCopy}
529
+ onPasteClip={handlePaste}
530
+ onDuplicateClip={handleDuplicate}
531
+ canPasteClip={canPaste}
532
+ setCompIdToSrc={setCompIdToSrc}
533
+ setCompositionLoading={setCompositionLoading}
534
+ shouldShowMotionPath={shouldShowMotionPath}
535
+ shouldShowSelectedDomBounds={shouldShowSelectedDomBounds}
536
+ isGestureRecording={gestureState === "recording"}
537
+ recordingState={gestureState}
538
+ onToggleRecording={handleToggleRecording}
539
+ blockPreview={blockPreview}
540
+ gestureOverlay={
541
+ gestureState === "recording" && previewIframe ? (
542
+ <GestureTrailOverlay
543
+ samples={gestureRecording.samplesRef.current}
544
+ sampleCount={gestureRecording.samplesRef.current.length}
545
+ trail={gestureRecording.trailRef.current}
546
+ canvasRect={canvasRectRef.current!}
547
+ compositionSize={compositionDimensions ?? undefined}
548
+ mode="recording"
549
+ />
550
+ ) : undefined
551
+ }
552
+ />
553
+ <StudioOverlays
554
+ projectId={projectId}
555
+ projectDir={fileManager.projectDir}
556
+ lintModal={lintModal}
557
+ closeLintModal={closeLintModal}
558
+ consoleErrors={consoleErrors}
559
+ clearConsoleErrors={() => setConsoleErrors(null)}
560
+ domEditSession={domEditSession}
561
+ activeCompPath={activeCompPath}
562
+ toasts={toasts}
563
+ dismissToast={dismissToast}
564
+ />
565
+ </div>
566
+ </DomEditProvider>
567
+ </FileManagerProvider>
568
+ </PanelLayoutProvider>
582
569
  </StudioPlaybackProvider>
583
570
  </StudioShellProvider>
584
571
  );
@@ -171,7 +171,7 @@ function AnimationPhase({
171
171
  }}
172
172
  className="flex-1 accent-studio-accent disabled:opacity-40"
173
173
  />
174
- <span className="text-2xs text-neutral-400 font-mono w-8 text-right flex-shrink-0">
174
+ <span className="text-2xs text-neutral-400 font-mono w-8 text-right shrink-0">
175
175
  {intensity.toFixed(2)}
176
176
  </span>
177
177
  </div>
@@ -249,7 +249,7 @@ export const CaptionAnimationPanel = memo(function CaptionAnimationPanel() {
249
249
  return (
250
250
  <div className="flex flex-col h-full min-h-0">
251
251
  {gated && (
252
- <div className="flex-shrink-0 mx-3 mt-2 px-2 py-1.5 rounded border border-amber-500/30 bg-amber-500/10">
252
+ <div className="shrink-0 mx-3 mt-2 px-2 py-1.5 rounded-sm border border-amber-500/30 bg-amber-500/10">
253
253
  <p className="text-2xs text-amber-300/90 leading-snug">
254
254
  Animation editing isn&apos;t applied to playback or saved yet, so these controls are
255
255
  disabled.
@@ -286,13 +286,13 @@ export const CaptionAnimationPanel = memo(function CaptionAnimationPanel() {
286
286
  </div>
287
287
 
288
288
  {/* Footer */}
289
- <div className="flex-shrink-0 px-3 py-2 border-t border-neutral-800">
289
+ <div className="shrink-0 px-3 py-2 border-t border-neutral-800">
290
290
  <button
291
291
  type="button"
292
292
  onClick={handleApplyToAll}
293
293
  disabled={gated}
294
294
  title={gated ? "Disabled until animation editing is applied to playback" : undefined}
295
- className="w-full py-1.5 rounded border border-neutral-700 text-2xs text-neutral-300 hover:border-studio-accent/50 hover:text-studio-accent transition-colors disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:border-neutral-700 disabled:hover:text-neutral-300"
295
+ className="w-full py-1.5 rounded-sm border border-neutral-700 text-2xs text-neutral-300 hover:border-studio-accent/50 hover:text-studio-accent transition-colors disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:border-neutral-700 disabled:hover:text-neutral-300"
296
296
  >
297
297
  Apply to all groups
298
298
  </button>
@@ -221,9 +221,8 @@ export function registerCaptionIframe(ref: React.RefObject<HTMLIFrameElement | n
221
221
 
222
222
  /**
223
223
  * True when the caption preview iframe is mounted AND visible. The caption
224
- * store's isEditMode stays true while the preview is merely hidden (e.g.
225
- * storyboard view), so hotkeys must not route ⌘Z to the caption stack unless
226
- * the user can actually see the captions the undo would change.
224
+ * store's isEditMode stays true while the preview is merely hidden, so hotkeys must not
225
+ * route ⌘Z to the caption stack unless the user can see the captions the undo would change.
227
226
  */
228
227
  export function isCaptionPreviewVisible(): boolean {
229
228
  const iframe = registeredIframe?.current;
@@ -213,7 +213,7 @@ export const CaptionPropertyPanel = memo(function CaptionPropertyPanel({
213
213
  return (
214
214
  <div className="flex flex-col h-full min-h-0">
215
215
  {/* Header */}
216
- <div className="px-3 py-2 border-b border-neutral-800 flex-shrink-0">
216
+ <div className="px-3 py-2 border-b border-neutral-800 shrink-0">
217
217
  <div className="flex items-center justify-between mb-1.5">
218
218
  <span className="text-2xs text-neutral-500">{countLabel}</span>
219
219
  </div>
@@ -225,7 +225,7 @@ export const CaptionPropertyPanel = memo(function CaptionPropertyPanel({
225
225
  aria-selected={activeTab === "style"}
226
226
  onClick={() => setActiveTab("style")}
227
227
  className={[
228
- "flex-1 py-0.5 rounded text-2xs font-medium transition-colors",
228
+ "flex-1 py-0.5 rounded-sm text-2xs font-medium transition-colors",
229
229
  activeTab === "style"
230
230
  ? "bg-studio-accent/20 text-studio-accent border border-studio-accent/50"
231
231
  : "text-neutral-500 border border-neutral-800 hover:text-neutral-300 hover:border-neutral-600",
@@ -239,7 +239,7 @@ export const CaptionPropertyPanel = memo(function CaptionPropertyPanel({
239
239
  aria-selected={activeTab === "animation"}
240
240
  onClick={() => setActiveTab("animation")}
241
241
  className={[
242
- "flex-1 py-0.5 rounded text-2xs font-medium transition-colors",
242
+ "flex-1 py-0.5 rounded-sm text-2xs font-medium transition-colors",
243
243
  activeTab === "animation"
244
244
  ? "bg-studio-accent/20 text-studio-accent border border-studio-accent/50"
245
245
  : "text-neutral-500 border border-neutral-800 hover:text-neutral-300 hover:border-neutral-600",
@@ -109,7 +109,7 @@ export const CaptionTimeline = memo(function CaptionTimeline({
109
109
  tabIndex={0}
110
110
  aria-label={`Caption word "${seg.text}"`}
111
111
  aria-pressed={isSelected}
112
- className={`absolute top-1 bottom-1 rounded flex items-center overflow-hidden cursor-pointer focus-visible:ring-1 focus-visible:ring-white outline-none${
112
+ className={`absolute top-1 bottom-1 rounded flex items-center overflow-hidden cursor-pointer focus-visible:ring-1 focus-visible:ring-white outline-hidden${
113
113
  isSelected ? " ring-1 ring-white/50 z-10" : ""
114
114
  }`}
115
115
  style={{
@@ -2,7 +2,7 @@ import type React from "react";
2
2
  import { useEffect, useRef, useState } from "react";
3
3
 
4
4
  export const inputCls =
5
- "w-full bg-neutral-900 border border-neutral-800 rounded px-1.5 py-0.5 text-2xs text-neutral-200 font-mono outline-none focus:border-studio-accent disabled:opacity-40 disabled:cursor-not-allowed";
5
+ "w-full bg-neutral-900 border border-neutral-800 rounded-sm px-1.5 py-0.5 text-2xs text-neutral-200 font-mono outline-hidden focus:border-studio-accent disabled:opacity-40 disabled:cursor-not-allowed";
6
6
 
7
7
  export function Section({ label, children }: { label: string; children: React.ReactNode }) {
8
8
  return (
@@ -20,7 +20,7 @@ export function Section({ label, children }: { label: string; children: React.Re
20
20
  export function Row({ label, children }: { label: string; children: React.ReactNode }) {
21
21
  return (
22
22
  <div className="flex items-center gap-2">
23
- <span className="text-2xs text-neutral-600 w-14 text-right flex-shrink-0">{label}</span>
23
+ <span className="text-2xs text-neutral-600 w-14 text-right shrink-0">{label}</span>
24
24
  <div className="flex-1 min-w-0">{children}</div>
25
25
  </div>
26
26
  );
@@ -66,8 +66,8 @@ export function AskAgentModal({
66
66
  <div
67
67
  className={
68
68
  anchorPoint
69
- ? "hf-backdrop-in fixed inset-0 z-[100] bg-black/60 backdrop-blur-sm"
70
- : "hf-backdrop-in fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-sm"
69
+ ? "hf-backdrop-in fixed inset-0 z-100 bg-black/60 backdrop-blur-xs"
70
+ : "hf-backdrop-in fixed inset-0 z-100 flex items-center justify-center bg-black/60 backdrop-blur-xs"
71
71
  }
72
72
  onClick={requestClose}
73
73
  >
@@ -77,7 +77,7 @@ export function AskAgentModal({
77
77
  aria-modal="true"
78
78
  aria-label="Copy prompt to AI agent"
79
79
  tabIndex={-1}
80
- className={`w-[480px] rounded-2xl border border-neutral-800 bg-neutral-950 shadow-2xl outline-none ${
80
+ className={`w-[480px] rounded-2xl border border-neutral-800 bg-neutral-950 shadow-2xl outline-hidden ${
81
81
  anchorPoint ? "fixed" : ""
82
82
  }`}
83
83
  style={modalPositionStyle}
@@ -112,7 +112,7 @@ export function AskAgentModal({
112
112
  <div className="px-5 py-4 space-y-3">
113
113
  <textarea
114
114
  ref={inputRef}
115
- className="w-full h-24 px-3 py-2 rounded-lg border border-neutral-800 bg-neutral-900/60 text-sm text-neutral-200 placeholder-neutral-600 resize-none focus:outline-none focus:border-studio-accent/60 focus:ring-1 focus:ring-studio-accent/30"
115
+ className="w-full h-24 px-3 py-2 rounded-lg border border-neutral-800 bg-neutral-900/60 text-sm text-neutral-200 placeholder-neutral-600 resize-none focus:outline-hidden focus:border-studio-accent/60 focus:ring-1 focus:ring-studio-accent/30"
116
116
  placeholder="Describe what you want to change…"
117
117
  value={value}
118
118
  onChange={(e) => setValue(e.target.value)}
@@ -127,7 +127,7 @@ export function AskAgentModal({
127
127
  <summary className="text-[11px] text-neutral-500 cursor-pointer select-none hover:text-neutral-400">
128
128
  Context included in prompt
129
129
  </summary>
130
- <pre className="mt-2 max-h-40 overflow-auto rounded-lg bg-neutral-900/80 px-3 py-2 text-[11px] leading-relaxed text-neutral-500 whitespace-pre-wrap break-words border border-neutral-800/50">
130
+ <pre className="mt-2 max-h-40 overflow-auto rounded-lg bg-neutral-900/80 px-3 py-2 text-[11px] leading-relaxed text-neutral-500 whitespace-pre-wrap wrap-break-word border border-neutral-800/50">
131
131
  {contextPreview}
132
132
  </pre>
133
133
  </details>
@@ -16,12 +16,12 @@ import type { BlockPreviewInfo } from "./sidebar/BlocksTab";
16
16
  import type { GestureRecordingState } from "./editor/GestureRecordControl";
17
17
  import { useTimelineSelectionPreviewSync } from "../hooks/useTimelineSelectionPreviewSync";
18
18
  import { StudioAgentTools } from "../webmcp/StudioAgentTools";
19
+ import type { TimelineDropPlacement } from "../player/components/timelineCallbacks";
19
20
 
20
21
  type RenderClipContent = (
21
22
  element: TimelineElement,
22
23
  style: { clip: string; label: string },
23
24
  ) => ReactNode;
24
- type TimelineDropPlacement = Pick<TimelineElement, "start" | "track">;
25
25
 
26
26
  // The seven move/resize/split/razor handlers come from TimelineEditCallbackDeps
27
27
  // (shared with useTimelineEditCallbacks); the rest are drop + wiring props.
@@ -30,8 +30,6 @@ export interface EditorShellProps extends TimelineEditCallbackDeps {
30
30
  left: ReactNode;
31
31
  /** Right panel (inspector/design) or null when collapsed, in the top row. */
32
32
  right: ReactNode;
33
- /** Hide the whole shell (e.g. while the storyboard view is active). */
34
- hidden?: boolean;
35
33
  timelineToolbar: ReactNode;
36
34
  renderClipContent: RenderClipContent;
37
35
  handleTimelineElementDelete: (element: TimelineElement) => Promise<void> | void;
@@ -76,7 +74,6 @@ export interface EditorShellProps extends TimelineEditCallbackDeps {
76
74
  export function EditorShell({
77
75
  left,
78
76
  right,
79
- hidden,
80
77
  timelineToolbar,
81
78
  renderClipContent,
82
79
  handleTimelineElementDelete,
@@ -157,7 +154,7 @@ export function EditorShell({
157
154
  });
158
155
 
159
156
  return (
160
- <div className={`flex flex-col flex-1 min-h-0${hidden ? " hidden" : ""}`}>
157
+ <div className="flex flex-col flex-1 min-h-0">
161
158
  <TimelineEditProvider value={timelineEditCallbacks}>
162
159
  <NLEProvider
163
160
  projectId={projectId}
@@ -279,7 +276,7 @@ function EditorShellBody({
279
276
  ref={containerRef}
280
277
  // Shell canvas is a step LIGHTER than the near-black panel cards so the
281
278
  // gaps between panels read as visible seams (CapCut-style).
282
- className="flex flex-col flex-1 min-h-0 bg-[#18181B]"
279
+ className="flex flex-col flex-1 min-h-0 bg-panel-surface"
283
280
  onKeyDown={handleKeyDown}
284
281
  tabIndex={-1}
285
282
  >
@@ -316,7 +313,7 @@ function EditorShellBody({
316
313
  onSelectTimelineElement={onSelectTimelineElement}
317
314
  timelineFooter={
318
315
  captionEditMode ? (
319
- <div className="border-t border-neutral-800/30 flex-shrink-0" style={{ height: 60 }}>
316
+ <div className="border-t border-neutral-800/30 shrink-0" style={{ height: 60 }}>
320
317
  <div className="flex items-center gap-1.5 px-2 py-0.5">
321
318
  <span className="text-[9px] font-medium text-neutral-500 uppercase tracking-wider">
322
319
  Captions