@dailies-studio/shot-editor 0.1.0 → 0.2.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 (432) hide show
  1. package/dist/.vite/manifest.json +382 -0
  2. package/dist/assets/AgentPanel-CQejLbiX.js +2 -0
  3. package/dist/assets/AgentPanel-DJEphah0.css +1 -0
  4. package/dist/assets/AgentQuestionDialog-BqkD0kXF.js +1 -0
  5. package/dist/assets/CodeStudio-Dv4ihHpz.js +23 -0
  6. package/dist/assets/CommentsPanel-B4yhhT1T.js +1 -0
  7. package/dist/assets/ComponentLibraryRail-Ch_dsAru.js +1 -0
  8. package/dist/assets/ComponentStage-BRhRotyH.js +1 -0
  9. package/dist/assets/CurvePane-BjFVabKX.css +1 -0
  10. package/dist/assets/CurvePane-R22WzllJ.js +1 -0
  11. package/dist/assets/ExportDialog-CWLQWTmG.js +2 -0
  12. package/dist/assets/FontPicker-DWKaYL7F.js +1 -0
  13. package/dist/assets/FontPicker-v0IOIArM.css +1 -0
  14. package/dist/assets/GenerateDrawer-Bh3SqDKt.js +2 -0
  15. package/dist/assets/InsertDrawer-Ce1fod1L.js +1 -0
  16. package/dist/assets/LibraryBrowser-D9sEGz5w.js +2 -0
  17. package/dist/assets/MakeItYoursSection-CMO4319_.js +2 -0
  18. package/dist/assets/MaterialGraphCanvas-BFzl4wWR.js +23 -0
  19. package/dist/assets/MaterialGraphCanvas-BIUD59ik.css +1 -0
  20. package/dist/assets/MaterialWorkspace-CqTWqaRA.js +14 -0
  21. package/dist/assets/PreferencesDialog-CBf9_OoD.js +1 -0
  22. package/dist/assets/PresetsSection-CUEaoCVU.js +1 -0
  23. package/dist/assets/SoundHistory-BeS8EW1h.js +1 -0
  24. package/dist/assets/SoundMode-BmcZru3i.js +3 -0
  25. package/dist/assets/StockSounds-DdAUGRYK.js +1 -0
  26. package/dist/assets/TemplateFieldSection-CaeXpLFo.js +1 -0
  27. package/dist/assets/VersionHistoryPanel-CxG6XhNP.js +1 -0
  28. package/dist/assets/board-B88EPuLO.css +1 -0
  29. package/dist/assets/board-CL-he7SL.js +3 -0
  30. package/dist/assets/components-0oOSPN0l.js +1 -0
  31. package/dist/assets/googleFontRanges-gp32wJMo.js +1 -0
  32. package/dist/assets/googleFonts-BNon6M7X.js +1 -0
  33. package/dist/assets/iconsAndAliases-DL7gXP5j.js +1863 -0
  34. package/dist/assets/index-4F5NQmI8.css +1 -0
  35. package/dist/assets/index-BGHQGV5z.js +117 -0
  36. package/dist/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
  37. package/dist/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
  38. package/dist/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
  39. package/dist/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
  40. package/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
  41. package/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
  42. package/dist/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
  43. package/dist/assets/libraryModel-CpIwfFha.js +1 -0
  44. package/dist/assets/lucide-6iK64tTB.js +9319 -0
  45. package/dist/assets/motionStamp-CH-Hew4E.js +1 -0
  46. package/dist/assets/takeMeasure-Tdg0TxEi.js +1 -0
  47. package/dist/assets/webmcp-BsB9gxWC.js +2 -0
  48. package/dist/index.html +34 -3
  49. package/package.json +12 -9
  50. package/src/addFamilies.ts +66 -0
  51. package/src/api.ts +1631 -55
  52. package/src/app/App.tsx +977 -198
  53. package/src/app/lazyPanel.tsx +137 -0
  54. package/src/app/lazySurfaces.tsx +203 -0
  55. package/src/audio/index.tsx +41 -10
  56. package/src/audio/meter.ts +485 -0
  57. package/src/audio/meterMath.ts +273 -0
  58. package/src/audio/meterStore.ts +155 -0
  59. package/src/audio/offlineMix.ts +289 -0
  60. package/src/audio/preview.ts +928 -118
  61. package/src/bridge.ts +15 -5
  62. package/src/bridgeTypes.ts +1611 -36
  63. package/src/channels.ts +17 -32
  64. package/src/fonts/googleFonts.ts +4 -0
  65. package/src/hostApi.ts +174 -0
  66. package/src/icons.tsx +770 -0
  67. package/src/layerWords.ts +61 -0
  68. package/src/main.tsx +56 -4
  69. package/src/panels/ResizeHandle.tsx +33 -43
  70. package/src/panels/agent/AgentDots.tsx +36 -0
  71. package/src/panels/agent/AgentPanel.tsx +119 -43
  72. package/src/panels/agent/AgentQuestionDialog.tsx +202 -0
  73. package/src/panels/agent/agent.css +113 -97
  74. package/src/panels/agent/agentGate.ts +35 -0
  75. package/src/panels/code/CodeDefaultsPanel.tsx +345 -0
  76. package/src/panels/code/CodeStudio.tsx +373 -0
  77. package/src/panels/code/FileTree.tsx +265 -0
  78. package/src/panels/code/codeBufferGuard.ts +52 -0
  79. package/src/panels/code/codeParts.tsx +321 -0
  80. package/src/panels/comments/CommentComposer.tsx +239 -0
  81. package/src/panels/comments/CommentThread.tsx +346 -0
  82. package/src/panels/comments/CommentsPanel.tsx +336 -0
  83. package/src/panels/comments/InboxButton.tsx +131 -0
  84. package/src/panels/comments/MentionMenu.tsx +98 -0
  85. package/src/panels/comments/parts.tsx +171 -0
  86. package/src/panels/export/ExportDialog.tsx +919 -96
  87. package/src/panels/export/ExportScrim.tsx +57 -0
  88. package/src/panels/files/AssetsTab.tsx +656 -0
  89. package/src/panels/files/FilePanel.tsx +1466 -216
  90. package/src/panels/files/LayerMarks.tsx +40 -0
  91. package/src/panels/files/LeftColumn.tsx +37 -0
  92. package/src/panels/files/McpSection.tsx +690 -47
  93. package/src/panels/files/MissingAssetsNotice.tsx +60 -0
  94. package/src/panels/files/assetDrag.ts +79 -0
  95. package/src/panels/files/resourceParts.tsx +255 -0
  96. package/src/panels/fonts/FontPicker.tsx +762 -0
  97. package/src/panels/fonts/faceCache.ts +207 -0
  98. package/src/panels/fonts/fontPicker.css +271 -0
  99. package/src/panels/fonts/pickerModel.ts +265 -0
  100. package/src/panels/fonts/pickerRequest.ts +46 -0
  101. package/src/panels/header/AccountAvatar.tsx +76 -0
  102. package/src/panels/header/AgentChip.tsx +77 -0
  103. package/src/panels/header/AppMenu.tsx +213 -0
  104. package/src/panels/header/Header.tsx +564 -84
  105. package/src/panels/header/HistoryControls.tsx +31 -5
  106. package/src/panels/header/PresenceStack.tsx +329 -0
  107. package/src/panels/header/ProjectTitle.tsx +232 -0
  108. package/src/panels/header/ShareButton.tsx +59 -0
  109. package/src/panels/header/StatusBadges.tsx +358 -27
  110. package/src/panels/header/SyncDeletedDialog.tsx +88 -0
  111. package/src/panels/header/ZoomControls.tsx +46 -15
  112. package/src/panels/header/agentHandoff.ts +52 -0
  113. package/src/panels/header/leave.ts +26 -0
  114. package/src/panels/help/HelpSection.tsx +189 -163
  115. package/src/panels/insert/InsertDrawer.tsx +723 -0
  116. package/src/panels/insert/iconSet.ts +109 -0
  117. package/src/panels/inspector/ExposeDot.tsx +117 -0
  118. package/src/panels/inspector/FramingRows.tsx +314 -44
  119. package/src/panels/inspector/InspectorFooter.tsx +91 -0
  120. package/src/panels/inspector/InspectorHead.tsx +425 -0
  121. package/src/panels/inspector/InspectorPanel.tsx +408 -124
  122. package/src/panels/inspector/KeyframeDot.tsx +373 -0
  123. package/src/panels/inspector/KeyframeSection.tsx +257 -0
  124. package/src/panels/inspector/MarkerSection.tsx +55 -11
  125. package/src/panels/inspector/ParamRow.tsx +84 -53
  126. package/src/panels/inspector/RightColumn.tsx +152 -0
  127. package/src/panels/inspector/TimeSection.tsx +866 -0
  128. package/src/panels/inspector/animate/EaseControl.tsx +244 -0
  129. package/src/panels/inspector/animate/PresetsSection.tsx +135 -0
  130. package/src/panels/inspector/animate/ShotSection.tsx +562 -48
  131. package/src/panels/inspector/design/AlignRow.tsx +95 -31
  132. package/src/panels/inspector/design/AppearanceSection.tsx +118 -9
  133. package/src/panels/inspector/design/ClonerSection.tsx +323 -62
  134. package/src/panels/inspector/design/ComponentSection.tsx +50 -43
  135. package/src/panels/inspector/design/CornerSection.tsx +45 -14
  136. package/src/panels/inspector/design/DefinitionProps.tsx +315 -0
  137. package/src/panels/inspector/design/DefinitionSection.tsx +136 -0
  138. package/src/panels/inspector/design/DeviceSection.tsx +210 -0
  139. package/src/panels/inspector/design/FillSection.tsx +83 -51
  140. package/src/panels/inspector/design/FontField.tsx +196 -0
  141. package/src/panels/inspector/design/HtmlSection.tsx +23 -12
  142. package/src/panels/inspector/design/InstanceSection.tsx +373 -154
  143. package/src/panels/inspector/design/MaskSection.tsx +84 -0
  144. package/src/panels/inspector/design/MaterialSection.tsx +177 -0
  145. package/src/panels/inspector/design/MediaSection.tsx +273 -120
  146. package/src/panels/inspector/design/MeshSection.tsx +910 -82
  147. package/src/panels/inspector/design/PaintRows.tsx +550 -0
  148. package/src/panels/inspector/design/PlateStyleSection.tsx +177 -0
  149. package/src/panels/inspector/design/ShadowSection.tsx +221 -48
  150. package/src/panels/inspector/design/SplineFollowSection.tsx +235 -0
  151. package/src/panels/inspector/design/StrokeSection.tsx +228 -43
  152. package/src/panels/inspector/design/TemplateFieldSection.tsx +57 -0
  153. package/src/panels/inspector/design/TransformSection.tsx +244 -50
  154. package/src/panels/inspector/design/TypographySection.tsx +679 -110
  155. package/src/panels/inspector/layout.ts +295 -0
  156. package/src/panels/inspector/propValue.ts +199 -0
  157. package/src/panels/inspector/scene/CameraSection.tsx +232 -22
  158. package/src/panels/inspector/scene/EffectsSection.tsx +722 -71
  159. package/src/panels/inspector/scene/MakeItYoursSection.tsx +180 -0
  160. package/src/panels/inspector/scene/SceneDocSection.tsx +191 -0
  161. package/src/panels/inspector/scene/SceneSection.tsx +219 -44
  162. package/src/panels/inspector/scene/TransitionSection.tsx +523 -72
  163. package/src/panels/inspector/storyboard/StoryboardReferenceSection.tsx +593 -0
  164. package/src/panels/inspector/storyboard/VideoStill.tsx +120 -0
  165. package/src/panels/inspector/timeModel.ts +190 -0
  166. package/src/panels/inspector/useDocWrite.ts +438 -146
  167. package/src/panels/library/LibraryBrowser.tsx +435 -0
  168. package/src/panels/library/LibraryGrid.tsx +190 -0
  169. package/src/panels/library/LibraryPreviewPanel.tsx +349 -0
  170. package/src/panels/library/LibraryRail.tsx +84 -0
  171. package/src/panels/library/LibrarySoundPanel.tsx +293 -0
  172. package/src/panels/library/SoundHistory.tsx +245 -0
  173. package/src/panels/library/StockSounds.tsx +390 -0
  174. package/src/panels/library/libraryModel.ts +147 -0
  175. package/src/panels/library/stockSearch.ts +77 -0
  176. package/src/panels/maskMarks.tsx +117 -0
  177. package/src/panels/material/MaterialCommentNode.tsx +54 -0
  178. package/src/panels/material/MaterialGraphCanvas.tsx +861 -0
  179. package/src/panels/material/MaterialGraphMenu.tsx +45 -0
  180. package/src/panels/material/MaterialGroupNode.tsx +56 -0
  181. package/src/panels/material/MaterialLibrary.tsx +253 -0
  182. package/src/panels/material/MaterialNode.tsx +453 -0
  183. package/src/panels/material/MaterialNodePalette.tsx +349 -0
  184. package/src/panels/material/MaterialParameterControls.tsx +525 -0
  185. package/src/panels/material/MaterialRerouteNode.tsx +42 -0
  186. package/src/panels/material/MaterialWorkspace.tsx +501 -0
  187. package/src/panels/material/NodePreview.tsx +70 -0
  188. package/src/panels/material/flowModel.ts +441 -0
  189. package/src/panels/material/parameterValues.ts +231 -0
  190. package/src/panels/material/previewScheduler.ts +235 -0
  191. package/src/panels/material/reactFlow.css +6 -0
  192. package/src/panels/material/socketGlyph.ts +85 -0
  193. package/src/panels/material/viewportMemory.ts +58 -0
  194. package/src/panels/preferences/PreferencesDialog.tsx +215 -0
  195. package/src/panels/share/ShareComponentDialog.tsx +247 -0
  196. package/src/panels/stage/StageMenu.tsx +35 -5
  197. package/src/panels/stage/StagePanel.tsx +338 -23
  198. package/src/panels/stage/cellSlots.tsx +70 -0
  199. package/src/panels/storyboard/BoardCanvas.tsx +739 -0
  200. package/src/panels/storyboard/BoardCursors.tsx +158 -0
  201. package/src/panels/storyboard/BoardDropDialog.tsx +161 -0
  202. package/src/panels/storyboard/BoardPlan.tsx +42 -0
  203. package/src/panels/storyboard/ComponentSheet.tsx +187 -0
  204. package/src/panels/storyboard/ComponentStage.tsx +235 -0
  205. package/src/panels/storyboard/MiniSketch.tsx +173 -0
  206. package/src/panels/storyboard/PartPicker.tsx +64 -0
  207. package/src/panels/storyboard/PlanPanel.tsx +617 -0
  208. package/src/panels/storyboard/ReferencePreview.tsx +217 -0
  209. package/src/panels/storyboard/ShotBrief.tsx +360 -0
  210. package/src/panels/storyboard/ShotCard.tsx +251 -0
  211. package/src/panels/storyboard/StagePreview.tsx +348 -0
  212. package/src/panels/storyboard/StillThumbs.tsx +162 -0
  213. package/src/panels/storyboard/StoryboardView.tsx +79 -0
  214. package/src/panels/storyboard/board.css +1065 -0
  215. package/src/panels/storyboard/board.ts +12 -0
  216. package/src/panels/storyboard/boardClipboard.ts +111 -0
  217. package/src/panels/storyboard/boardOrder.ts +68 -0
  218. package/src/panels/storyboard/boardRows.tsx +425 -0
  219. package/src/panels/storyboard/liveCap.ts +90 -0
  220. package/src/panels/storyboard/plan.css +295 -0
  221. package/src/panels/storyboard/posterCache.ts +133 -0
  222. package/src/panels/storyboard/shotboard/ComponentPicker.tsx +373 -0
  223. package/src/panels/storyboard/shotboard/ImagePicker.tsx +145 -0
  224. package/src/panels/storyboard/shotboard/ShotBoard.tsx +292 -0
  225. package/src/panels/storyboard/shotboard/SketchCanvas.tsx +443 -0
  226. package/src/panels/storyboard/shotboard/SketchInspector.tsx +471 -0
  227. package/src/panels/storyboard/shotboard/SketchItem.tsx +240 -0
  228. package/src/panels/storyboard/shotboard/SketchLayers.tsx +130 -0
  229. package/src/panels/storyboard/shotboard/SketchPlay.tsx +108 -0
  230. package/src/panels/storyboard/shotboard/SketchStrip.tsx +178 -0
  231. package/src/panels/storyboard/shotboard/SketchToolFooter.tsx +99 -0
  232. package/src/panels/storyboard/shotboard/sketch.css +1392 -0
  233. package/src/panels/storyboard/shotboard/sketchModel.ts +219 -0
  234. package/src/panels/storyboard/storyboardDrop.ts +164 -0
  235. package/src/panels/studio/ComponentLibraryRail.tsx +346 -0
  236. package/src/panels/studio/ComponentSidePanel.tsx +355 -0
  237. package/src/panels/studio/ComponentStudio.tsx +243 -0
  238. package/src/panels/studio/ComponentsHome.tsx +318 -0
  239. package/src/panels/studio/ComponentsPreview.tsx +179 -0
  240. package/src/panels/studio/EveryUse.tsx +244 -0
  241. package/src/panels/studio/ThisUsePanel.tsx +679 -0
  242. package/src/panels/studio/componentParts.tsx +341 -0
  243. package/src/panels/studio/components.ts +6 -0
  244. package/src/panels/studio/newCodeComponent.ts +66 -0
  245. package/src/panels/timeline/AudioFxButton.tsx +290 -0
  246. package/src/panels/timeline/AudioLane.tsx +674 -85
  247. package/src/panels/timeline/BlockRow.tsx +154 -85
  248. package/src/panels/timeline/ChannelRow.tsx +378 -129
  249. package/src/panels/timeline/CurvePane.tsx +508 -0
  250. package/src/panels/timeline/Filmstrip.tsx +361 -0
  251. package/src/panels/timeline/GenerateDrawer.tsx +407 -0
  252. package/src/panels/timeline/KeyStretch.tsx +115 -0
  253. package/src/panels/timeline/LifespanRow.tsx +730 -47
  254. package/src/panels/timeline/MarkerLane.tsx +46 -8
  255. package/src/panels/timeline/PlayButton.tsx +91 -0
  256. package/src/panels/timeline/PropertyPicker.tsx +254 -0
  257. package/src/panels/timeline/ShotRow.tsx +400 -0
  258. package/src/panels/timeline/SoundMode.tsx +1406 -0
  259. package/src/panels/timeline/TimelineDock.tsx +2338 -272
  260. package/src/panels/timeline/TransportVolume.tsx +163 -0
  261. package/src/panels/timeline/beatRuler.ts +74 -0
  262. package/src/panels/timeline/curveModel.ts +500 -0
  263. package/src/panels/timeline/duckUnderVoice.ts +68 -0
  264. package/src/panels/timeline/keyframeMenu.ts +138 -0
  265. package/src/panels/timeline/labelWidth.ts +49 -0
  266. package/src/panels/timeline/marquee.ts +155 -0
  267. package/src/panels/timeline/model.ts +1860 -199
  268. package/src/panels/timeline/snap.ts +125 -43
  269. package/src/panels/timeline/staggerPreview.tsx +92 -0
  270. package/src/panels/timeline/takeMeasure.ts +72 -0
  271. package/src/panels/timeline/useLive.ts +48 -0
  272. package/src/panels/timeline/viewport.ts +234 -0
  273. package/src/panels/toolbar/BackChip.tsx +116 -0
  274. package/src/panels/toolbar/CameraViewBar.tsx +118 -49
  275. package/src/panels/toolbar/CanvasBar.tsx +117 -0
  276. package/src/panels/toolbar/InsertButton.tsx +38 -0
  277. package/src/panels/toolbar/IsolationTrail.tsx +156 -0
  278. package/src/panels/toolbar/PanelToggles.tsx +86 -0
  279. package/src/panels/toolbar/ShadingBar.tsx +119 -26
  280. package/src/panels/toolbar/ToolDockBar.tsx +329 -80
  281. package/src/panels/toolbar/ToolFooter.tsx +102 -0
  282. package/src/panels/toolbar/ViewModeBar.tsx +247 -38
  283. package/src/panels/toolbar/WorkPlaneBar.tsx +94 -0
  284. package/src/panels/toolbar/useAddRows.tsx +326 -0
  285. package/src/panels/toolbar/useDismiss.ts +122 -0
  286. package/src/panels/versions/VersionHistoryPanel.tsx +274 -0
  287. package/src/panels/versions/versionModel.ts +103 -0
  288. package/src/panels/virtualWindow.ts +271 -0
  289. package/src/shotTokens.css +151 -60
  290. package/src/stage/FrustumGizmo.tsx +504 -84
  291. package/src/stage/GridPlane.tsx +225 -16
  292. package/src/stage/NodePreviews.tsx +628 -0
  293. package/src/stage/PerfHud.tsx +437 -47
  294. package/src/stage/SplitRenderer.tsx +816 -169
  295. package/src/stage/StageApp.tsx +4274 -486
  296. package/src/stage/StageRootBoundary.tsx +114 -0
  297. package/src/stage/StageTools.tsx +651 -151
  298. package/src/stage/TransformGizmo.tsx +696 -0
  299. package/src/stage/adaptivePresentation.ts +145 -0
  300. package/src/stage/bridgeClient.ts +2522 -41
  301. package/src/stage/exportWorker.ts +9 -0
  302. package/src/stage/feed.ts +305 -14
  303. package/src/stage/fontPreview.ts +176 -0
  304. package/src/stage/frustumGeometry.ts +319 -1
  305. package/src/stage/furnitureTokens.ts +33 -0
  306. package/src/stage/gizmoMath.ts +508 -16
  307. package/src/stage/gpuTimer.ts +276 -0
  308. package/src/stage/instanceModules.ts +194 -33
  309. package/src/stage/interactions/move.ts +24 -5
  310. package/src/stage/isolation.ts +291 -33
  311. package/src/stage/jsSelfProfiler.ts +325 -0
  312. package/src/stage/main.tsx +116 -16
  313. package/src/stage/modalState.ts +222 -23
  314. package/src/stage/moduleEpoch.ts +60 -0
  315. package/src/stage/motionPathStage.ts +279 -0
  316. package/src/stage/motionPreview.ts +74 -0
  317. package/src/stage/overlays/Overlays.tsx +1112 -159
  318. package/src/stage/overlays/Rulers.tsx +495 -0
  319. package/src/stage/panes.ts +159 -10
  320. package/src/stage/project.ts +68 -3
  321. package/src/stage/renderScaleController.ts +730 -0
  322. package/src/stage/rulers.ts +129 -0
  323. package/src/stage/sceneExtent.ts +75 -0
  324. package/src/stage/shading.ts +20 -0
  325. package/src/stage/splineStage.ts +632 -0
  326. package/src/stage/stagePerformanceTelemetry.ts +717 -0
  327. package/src/stage/stageTheme.ts +36 -0
  328. package/src/stage/stageWarmup.ts +11 -0
  329. package/src/stage/textAutoSize.ts +124 -0
  330. package/src/stage/tier1Export.ts +641 -0
  331. package/src/stage/tokenColor.ts +14 -9
  332. package/src/stage/view.ts +56 -9
  333. package/src/stage/workingView.ts +277 -33
  334. package/src/state/accountPrefs.ts +261 -0
  335. package/src/state/agentActions.ts +173 -15
  336. package/src/state/agentActivity.ts +198 -0
  337. package/src/state/agentQuestion.ts +239 -0
  338. package/src/state/bootOpen.ts +42 -0
  339. package/src/state/cameraVerbs.ts +139 -0
  340. package/src/state/clientId.ts +6 -1
  341. package/src/state/comments.ts +1099 -0
  342. package/src/state/context.tsx +19 -1
  343. package/src/state/editorPrefs.ts +220 -0
  344. package/src/state/errorReports.ts +121 -0
  345. package/src/state/fieldWrite.ts +161 -0
  346. package/src/state/fontRecents.ts +70 -0
  347. package/src/state/fonts.ts +656 -0
  348. package/src/state/graphClipboard.ts +414 -0
  349. package/src/state/imageThumbs.ts +216 -0
  350. package/src/state/insert.ts +444 -67
  351. package/src/state/isolationTrail.ts +92 -0
  352. package/src/state/keyMoves.ts +134 -0
  353. package/src/state/keyframeClipboard.ts +177 -0
  354. package/src/state/keymap.ts +1153 -117
  355. package/src/state/layoutPrefs.ts +272 -0
  356. package/src/state/layouts.ts +205 -0
  357. package/src/state/measureMedia.ts +167 -0
  358. package/src/state/menu.ts +2341 -28
  359. package/src/state/motionStamp.ts +7 -0
  360. package/src/state/panelSize.ts +375 -5
  361. package/src/state/pendingChanges.ts +119 -0
  362. package/src/state/playHold.ts +78 -0
  363. package/src/state/playbackPreparation.ts +562 -0
  364. package/src/state/posterCapture.ts +242 -0
  365. package/src/state/presence.ts +254 -0
  366. package/src/state/projectComponents.ts +160 -0
  367. package/src/state/renderEvents.ts +298 -18
  368. package/src/state/runtimeErrors.ts +46 -0
  369. package/src/state/selection.ts +12 -0
  370. package/src/state/shortcuts.ts +1606 -0
  371. package/src/state/sketchGuide.ts +51 -0
  372. package/src/state/splineRefs.ts +87 -0
  373. package/src/state/stageHealth.ts +259 -0
  374. package/src/state/stageWatchdog.ts +47 -0
  375. package/src/state/stillStage.ts +330 -0
  376. package/src/state/stillThumbs.ts +474 -0
  377. package/src/state/store.ts +23591 -2982
  378. package/src/state/storyboardModel.ts +528 -0
  379. package/src/state/sync.ts +1257 -0
  380. package/src/state/syncCache.ts +159 -0
  381. package/src/state/triangles.ts +13 -0
  382. package/src/state/types.ts +1698 -55
  383. package/src/state/unsavedGuard.ts +49 -0
  384. package/src/state/viewMode.ts +200 -0
  385. package/src/state/webmcp.ts +1128 -0
  386. package/src/state/workspace.ts +1147 -0
  387. package/src/styles/assets-tab.css +304 -0
  388. package/src/styles/canvas.css +545 -0
  389. package/src/styles/comments.css +1435 -0
  390. package/src/styles/controls.css +162 -0
  391. package/src/styles/dialogs.css +390 -0
  392. package/src/styles/insert-drawer.css +586 -0
  393. package/src/styles/inspector-board.css +207 -0
  394. package/src/styles/inspector-object.css +486 -0
  395. package/src/styles/inspector-shot.css +252 -0
  396. package/src/styles/inspector.css +360 -0
  397. package/src/styles/left-column.css +1628 -0
  398. package/src/styles/library-preview.css +575 -0
  399. package/src/styles/library.css +512 -0
  400. package/src/styles/modes/code.css +569 -0
  401. package/src/styles/modes/component.css +1561 -0
  402. package/src/styles/modes/material.css +1201 -0
  403. package/src/styles/modes/storyboard.css +518 -0
  404. package/src/styles/share-component.css +49 -0
  405. package/src/styles/shell.css +653 -0
  406. package/src/styles/shot-brief.css +360 -0
  407. package/src/styles/states.css +76 -0
  408. package/src/styles/sync.css +380 -0
  409. package/src/styles/timeline-graph.css +384 -0
  410. package/src/styles/timeline-meters.css +89 -0
  411. package/src/styles/timeline-rows.css +1959 -0
  412. package/src/styles/timeline-sound.css +1003 -0
  413. package/src/styles/timeline.css +754 -0
  414. package/src/styles/tool-footer.css +525 -0
  415. package/src/styles/topbar.css +886 -0
  416. package/src/styles/versions.css +262 -0
  417. package/src/styles.css +72 -2921
  418. package/src/tools.ts +108 -23
  419. package/dist/assets/index-B7notge7.css +0 -1
  420. package/dist/assets/index-BBE6Ta9L.js +0 -52
  421. package/src/panels/files/icons.tsx +0 -118
  422. package/src/panels/header/DocSwitcher.tsx +0 -85
  423. package/src/panels/header/TransportBar.tsx +0 -86
  424. package/src/panels/inspector/animate/BlockTiming.tsx +0 -341
  425. package/src/panels/inspector/animate/DuringBlocks.tsx +0 -85
  426. package/src/panels/inspector/animate/InOutPresets.tsx +0 -57
  427. package/src/panels/inspector/animate/ResolvedChannels.tsx +0 -150
  428. package/src/panels/inspector/animate/useBlocks.ts +0 -43
  429. package/src/panels/material/MaterialPicker.tsx +0 -172
  430. package/src/panels/timeline/SceneStrip.tsx +0 -145
  431. package/src/panels/toolbar/AddMenu.tsx +0 -230
  432. package/src/stage/MoveGizmo.tsx +0 -411
@@ -0,0 +1,318 @@
1
+ // ALL COMPONENTS (C5): the Components home, in the canvas cell while no
2
+ // component is open. Every component this Project has, then the ones every
3
+ // Project of the workspace offers, as cards:
4
+ //
5
+ // THIS PROJECT its Studio-made definitions, then the code files made for
6
+ // it, then the code components it uses (`componentsListOf`),
7
+ // and the dashed New card
8
+ // YOUR LIBRARY code made for no Project, Dailies Library installs, and
9
+ // what someone added with "In your library"
10
+ // (`libraryComponentsOf`)
11
+ //
12
+ // A card is a poster at rest and a live loop on hover or focus, through the
13
+ // board's one live preview (`ComponentStage`, with its poster cache and its
14
+ // `LIVE_CAP` budget), so a wall of cards costs pictures, not documents. A card
15
+ // the stage cannot draw (a dom component, or a library definition whose body
16
+ // lives in another Project) shows its kind's icon instead.
17
+ //
18
+ // The search is the canvas bar's (ComponentsPreview.tsx), and it filters the
19
+ // left column's list too, so one field filters both.
20
+ //
21
+ // An MCP agent writing a component's file shows its dots on that card
22
+ // (state/agentActivity.ts), so its work appears as it happens.
23
+ import { useEffect, useMemo, useState } from "react";
24
+ import type { ReactNode } from "react";
25
+ import { IconCode } from "@dailies-studio/ui";
26
+ import { componentUsesOf } from "@dailies-studio/shot/doc";
27
+ import type { Doc3D, ReferenceItem3D } from "@dailies-studio/shot/doc";
28
+ import { CUBE_ICON } from "../../icons.js";
29
+ import { useShotEditor, useStore } from "../../state/context.js";
30
+ import { componentsListOf, libraryComponentsOf, libraryEntryName, libraryHomeLabel } from "../../state/workspace.js";
31
+ import type { ComponentsListRow } from "../../state/workspace.js";
32
+ import { useCodeBufferGuard } from "../code/codeBufferGuard.js";
33
+ import { ComponentStage } from "../storyboard/ComponentStage.js";
34
+ import { workspaceRowTitle } from "./ComponentLibraryRail.js";
35
+ import { agentWriting } from "../../state/agentActivity.js";
36
+ import { AgentDots, useAgentActivity } from "../agent/AgentDots.js";
37
+
38
+ type CardItem = Extract<ReferenceItem3D, { type: "component" }>;
39
+
40
+ /** The two sections' rows, filtered by the search, and their full counts for
41
+ * the bar's "N in this project · M in your library". */
42
+ export function useHomeRows(doc: Doc3D, query: string) {
43
+ const library = useShotEditor((s) => s.library);
44
+ const workspace = useShotEditor((s) => s.workspaceComponents);
45
+ const homes = useShotEditor((s) => s.componentHomes);
46
+ const rows = useMemo(() => componentsListOf(doc, library), [doc, library]);
47
+ const mine = useMemo(
48
+ () => libraryComponentsOf(doc, library, workspace, homes, rows),
49
+ [doc, library, workspace, homes, rows],
50
+ );
51
+ const needle = query.trim().toLowerCase();
52
+ const matches = (name: string): boolean => needle.length === 0 || name.toLowerCase().includes(needle);
53
+ return {
54
+ project: rows.filter((r) => matches(r.name)),
55
+ library: mine.filter((entry) => matches(libraryEntryName(entry))),
56
+ projectCount: rows.length,
57
+ libraryCount: mine.length,
58
+ };
59
+ }
60
+
61
+ export function ComponentsHome(props: { doc: Doc3D; query: string }) {
62
+ const store = useStore();
63
+ const readOnly = useShotEditor((s) => s.readOnly);
64
+ const { guard, dialog } = useCodeBufferGuard();
65
+ const rows = useHomeRows(props.doc, props.query);
66
+ // ONE WALK of the document for every card's where line.
67
+ const uses = useMemo(() => componentUsesOf(props.doc), [props.doc]);
68
+ const usedIn = (row: ComponentsListRow): number =>
69
+ uses.filter((u) => (row.sel.kind === "studio" ? u.def === row.sel.def : u.component === row.sel.module)).length;
70
+ const searching = props.query.trim().length > 0;
71
+ const activity = useAgentActivity();
72
+ const library = useShotEditor((s) => s.library);
73
+ /** The agent writing a code row's file, if one is. */
74
+ const writerOf = (module: string | null): string | null => {
75
+ const rel = module === null ? null : (library.find((r) => r.id === module)?.rel ?? null);
76
+ return agentWriting(activity, rel, module)?.name ?? null;
77
+ };
78
+
79
+ // Your library reads the workspace list and its homes once per visit, and
80
+ // the store reads them again as other Projects' writes arrive (`rereadHomes`).
81
+ useEffect(() => {
82
+ void store.refreshWorkspaceComponents();
83
+ }, [store]);
84
+
85
+ return (
86
+ <div className="components-home" data-testid="components-home">
87
+ {dialog}
88
+ <section className="components-home-section" aria-label="This project">
89
+ <h2 className="components-section-title">This project</h2>
90
+ <div className="components-home-grid" data-testid="components-home-project">
91
+ {rows.project.map((r) => {
92
+ const sel = r.sel;
93
+ const n = usedIn(r);
94
+ const writer = writerOf(sel.kind === "code" ? sel.module : null);
95
+ return (
96
+ <HomeCard
97
+ key={sel.kind === "studio" ? sel.def : sel.module}
98
+ kind={sel.kind}
99
+ name={r.name}
100
+ writer={writer}
101
+ where={
102
+ r.refusal ??
103
+ (writer !== null ? `${writer} is writing it` : n === 0 ? "Not used yet" : `Used in ${n} ${n === 1 ? "place" : "places"}`)
104
+ }
105
+ title={r.refusal ?? `Open ${r.name}`}
106
+ refused={r.refusal !== null}
107
+ stage={(live) => (r.refusal === null ? <ProjectStage doc={props.doc} row={r} live={live} /> : null)}
108
+ onOpen={() => {
109
+ if (r.refusal !== null) {
110
+ store.reportError(r.refusal);
111
+ return;
112
+ }
113
+ void store.selectComponent(sel);
114
+ }}
115
+ />
116
+ );
117
+ })}
118
+ {searching ? null : <NewCard readOnly={readOnly} />}
119
+ </div>
120
+ {searching && rows.project.length === 0 ? (
121
+ <p className="insp-empty">No component in this project matches “{props.query.trim()}”.</p>
122
+ ) : null}
123
+ </section>
124
+ <section className="components-home-section" aria-label="Your library">
125
+ <h2 className="components-section-title">Your library</h2>
126
+ {rows.library.length === 0 ? (
127
+ <p className="insp-empty">
128
+ {searching
129
+ ? `No component in your library matches “${props.query.trim()}”.`
130
+ : "Code made for no Project, Dailies Library installs and components you add to your library show here."}
131
+ </p>
132
+ ) : (
133
+ <div className="components-home-grid" data-testid="components-home-library">
134
+ {rows.library.map((entry) => {
135
+ if (entry.kind === "studio") {
136
+ const c = entry.component;
137
+ return (
138
+ <HomeCard
139
+ key={c.id}
140
+ kind="studio"
141
+ name={c.name}
142
+ where={libraryHomeLabel(entry)}
143
+ title={workspaceRowTitle(entry)}
144
+ refused={false}
145
+ stage={() => null}
146
+ onOpen={() => {
147
+ if (readOnly) return;
148
+ guard(() => void store.addLibraryComponent(c.id));
149
+ }}
150
+ />
151
+ );
152
+ }
153
+ const { module, refusal } = entry;
154
+ return (
155
+ <HomeCard
156
+ key={module}
157
+ kind="code"
158
+ name={entry.name}
159
+ where={libraryHomeLabel(entry)}
160
+ title={refusal ?? workspaceRowTitle(entry)}
161
+ refused={refusal !== null}
162
+ stage={(live) =>
163
+ refusal === null ? <LibraryStage doc={props.doc} module={module} name={entry.name} live={live} /> : null
164
+ }
165
+ onOpen={() => {
166
+ if (refusal !== null) {
167
+ store.reportError(refusal);
168
+ return;
169
+ }
170
+ // OPENED, NOTHING MORE: no record and no membership. It
171
+ // stays where it lists until someone ticks a box.
172
+ guard(() => void store.openCodeComponent(module));
173
+ }}
174
+ />
175
+ );
176
+ })}
177
+ </div>
178
+ )}
179
+ </section>
180
+ </div>
181
+ );
182
+ }
183
+
184
+ /** One card: the picture, then the name, the kind badge and the where line.
185
+ * The picture goes live while the pointer or focus is on the card. */
186
+ function HomeCard(props: {
187
+ kind: "studio" | "code";
188
+ name: string;
189
+ where: string;
190
+ title: string;
191
+ refused: boolean;
192
+ /** The agent writing it, whose dots the card shows. */
193
+ writer?: string | null;
194
+ stage: (live: boolean) => ReactNode;
195
+ onOpen: () => void;
196
+ }) {
197
+ const [hot, setHot] = useState(false);
198
+ const icon = (
199
+ <span className="components-home-icon" aria-hidden="true">
200
+ {props.kind === "code" ? <IconCode /> : CUBE_ICON}
201
+ </span>
202
+ );
203
+ return (
204
+ <button
205
+ type="button"
206
+ className="components-home-card"
207
+ data-testid="components-home-card"
208
+ aria-disabled={props.refused || undefined}
209
+ title={props.title}
210
+ onClick={props.onOpen}
211
+ onPointerEnter={() => setHot(true)}
212
+ onPointerLeave={() => setHot(false)}
213
+ onFocus={() => setHot(true)}
214
+ onBlur={() => setHot(false)}
215
+ >
216
+ <span className="components-home-poster">{props.stage(hot) ?? icon}</span>
217
+ <span className="components-home-foot">
218
+ <span className="components-home-name">{props.name}</span>
219
+ {props.writer === null || props.writer === undefined ? null : <AgentDots label={`${props.writer} is writing ${props.name}`} />}
220
+ <span className="components-item-kind">{props.kind === "code" ? "CODE" : "3D"}</span>
221
+ </span>
222
+ <span className="components-home-where">{props.where}</span>
223
+ </button>
224
+ );
225
+ }
226
+
227
+ /** A card of this Project: a definition's closure, or a three code component. */
228
+ function ProjectStage(props: { doc: Doc3D; row: ComponentsListRow; live: boolean }) {
229
+ const { sel, name } = props.row;
230
+ const module = sel.kind === "code" ? sel.module : null;
231
+ const item = useMemo<CardItem>(
232
+ () =>
233
+ sel.kind === "studio"
234
+ ? { type: "component", id: `home:${sel.def}`, label: name, def: sel.def, props: {} }
235
+ : { type: "component", id: `home:${sel.module}`, label: name, component: sel.module, props: {} },
236
+ [sel, name],
237
+ );
238
+ return <CodeAwareStage doc={props.doc} item={item} module={module} live={props.live} />;
239
+ }
240
+
241
+ /** A Your library code card. A library definition's body lives in its home
242
+ * Project until Use here copies it in, so its card keeps the icon and never
243
+ * comes here. */
244
+ function LibraryStage(props: { doc: Doc3D; module: string; name: string; live: boolean }) {
245
+ const { module, name } = props;
246
+ const item = useMemo<CardItem>(
247
+ () => ({ type: "component", id: `home:${module}`, label: name, component: module, props: {} }),
248
+ [module, name],
249
+ );
250
+ return <CodeAwareStage doc={props.doc} item={item} module={module} live={props.live} />;
251
+ }
252
+
253
+ /** The board's preview, with what a code component needs: its registry row,
254
+ * its contract (loaded once the card goes live) and the catalog's length. */
255
+ function CodeAwareStage(props: { doc: Doc3D; item: CardItem; module: string | null; live: boolean }) {
256
+ const store = useStore();
257
+ const { module, live } = props;
258
+ const row = useShotEditor((s) => (module === null ? undefined : s.library.find((r) => r.id === module)));
259
+ const contract = useShotEditor((s) => (module === null ? undefined : s.contracts[module]));
260
+ const lengthFrames = useShotEditor((s) =>
261
+ module === null ? undefined : s.libraryCatalog.find((r) => r.installedAs === module)?.lengthFrames,
262
+ );
263
+ useEffect(() => {
264
+ if (live && module !== null) void store.loadContract(module);
265
+ }, [live, module, store]);
266
+ if (module !== null && row?.host !== "three") return null;
267
+ return (
268
+ <ComponentStage
269
+ doc={props.doc}
270
+ item={props.item}
271
+ contract={contract}
272
+ availability={row?.contractAvailability}
273
+ lengthFrames={lengthFrames}
274
+ live={live}
275
+ fallback={
276
+ <span className="components-home-icon" aria-hidden="true">
277
+ {module === null ? CUBE_ICON : <IconCode />}
278
+ </span>
279
+ }
280
+ />
281
+ );
282
+ }
283
+
284
+ /** The dashed card: a new component, Studio-made or code. It opens in
285
+ * Components, never in a Shot. */
286
+ function NewCard(props: { readOnly: boolean }) {
287
+ const store = useStore();
288
+ const { guard, dialog } = useCodeBufferGuard();
289
+ return (
290
+ <div className="components-home-card is-new" data-testid="components-home-new">
291
+ {dialog}
292
+ <span className="components-home-new-title">New component</span>
293
+ <span className="components-home-where">Studio-made or code</span>
294
+ <span className="components-home-new-verbs">
295
+ <button
296
+ type="button"
297
+ className="btn"
298
+ data-testid="components-home-new-studio"
299
+ disabled={props.readOnly}
300
+ title="A Studio-made component, built from layers"
301
+ onClick={() => guard(() => store.createEmptyComponent("Component"))}
302
+ >
303
+ Studio-made
304
+ </button>
305
+ <button
306
+ type="button"
307
+ className="btn"
308
+ data-testid="components-home-new-code"
309
+ disabled={props.readOnly}
310
+ title="A code component from the three starter"
311
+ onClick={() => guard(() => void store.newCodeComponent("Component"))}
312
+ >
313
+ Code
314
+ </button>
315
+ </span>
316
+ </div>
317
+ );
318
+ }
@@ -0,0 +1,179 @@
1
+ // COMPONENTS, ON ITS HOME AND ITS PREVIEW TAB.
2
+ //
3
+ // The Components workspace (`workspaceOf`) is every component of the Project,
4
+ // standalone, never inside a Shot. With nothing open it is the home, All
5
+ // components (C5). With a component open it has two tabs: Edit is the studio
6
+ // that edits it (ComponentStudio.tsx for a definition, CodeStudio.tsx for
7
+ // code); Preview is this file, the same cells with the studio taken out.
8
+ //
9
+ // LEFT which component (ComponentLibraryRail.tsx), both kinds
10
+ // CENTRE the home's cards (ComponentsHome.tsx), or the subject as a HOLE
11
+ // onto the stage with the loop transport (`PreviewTransport`), or
12
+ // Every use (C4) while the crumb's "used in N places" has it open
13
+ // BAR the way back (Back to Shot when a Shot door opened it, C7), then
14
+ // the home's count, search and New, or the breadcrumb, Preview |
15
+ // Edit and the zoom
16
+ //
17
+ // No timeline on this tab (`componentsHideTimeline`): the transport under the
18
+ // stage is the clock.
19
+ //
20
+ // The subject stays in the stage's component context across the tab swap, so
21
+ // the hole is the same render the studio shows, and code buffers survive it.
22
+ import { useEffect, useRef, useState } from "react";
23
+ import { instanceExportOf } from "@dailies-studio/shot/doc";
24
+ import type { Doc3D } from "@dailies-studio/shot/doc";
25
+ import { useShotEditor, useStore } from "../../state/context.js";
26
+ import { usesViewOf, workspaceOf } from "../../state/workspace.js";
27
+ import { useCodeBufferGuard } from "../code/codeBufferGuard.js";
28
+ import { InCell } from "../stage/cellSlots.js";
29
+ import { ComponentLibraryRail } from "./ComponentLibraryRail.js";
30
+ import { ComponentsTabSwitch, StudioZoom } from "./ComponentStudio.js";
31
+ import { ComponentCrumb, ComponentsBack, PreviewTransport } from "./componentParts.js";
32
+ import { ComponentsHome, useHomeRows } from "./ComponentsHome.js";
33
+ import { EveryUse } from "./EveryUse.js";
34
+
35
+ export function ComponentsPreview() {
36
+ const store = useStore();
37
+ const doc = useShotEditor((s) => s.doc);
38
+ const editingDef = useShotEditor((s) => s.editingDef);
39
+ const codeComponent = useShotEditor((s) => s.codeComponent);
40
+ const library = useShotEditor((s) => s.library);
41
+ const usesOpen = useShotEditor((s) => usesViewOf(s) !== null);
42
+ // THIS FILE'S CELLS: Components with nothing open (the home), or with a
43
+ // subject on the Preview tab.
44
+ const shown = useShotEditor(
45
+ (s) =>
46
+ workspaceOf(s) === "components" &&
47
+ (s.componentsTab === "preview" || (s.codeComponent === null && s.editingDef === null)),
48
+ );
49
+ // Leaving drops a code component's buffers, so unsaved text asks first.
50
+ const { guard, dialog } = useCodeBufferGuard();
51
+ // ONE SEARCH for the home's cards and the left column's list. On the home
52
+ // its field is the bar's, and the column draws none.
53
+ const [query, setQuery] = useState("");
54
+
55
+ // AN ESCAPE FOR CODE ON THIS TAB: the keymap's code rung hands it here
56
+ // (`codeBackRequest`), as it does to CodeStudio on the Edit tab. A request
57
+ // made while this tab is not up is marked seen, so swapping tabs never
58
+ // answers a stale one.
59
+ const backRequest = useShotEditor((s) => s.codeBackRequest);
60
+ const seen = useRef<object | null>(null);
61
+ useEffect(() => {
62
+ if (backRequest === seen.current) return;
63
+ seen.current = backRequest;
64
+ if (!shown || backRequest === null || store.getState().codeComponent === null) return;
65
+ guard(() => (store.getState().componentsOrigin !== null ? void store.backToShot() : store.leaveComponents()));
66
+ }, [shown, backRequest, guard, store]);
67
+
68
+ if (!shown || doc === null) return null;
69
+
70
+ const def = editingDef === null ? undefined : doc.components?.[editingDef];
71
+ const subject =
72
+ codeComponent !== null
73
+ ? { kind: "code" as const, module: codeComponent }
74
+ : def !== undefined
75
+ ? { kind: "studio" as const, def: def.id }
76
+ : null;
77
+ const name =
78
+ codeComponent !== null
79
+ ? (library.find((r) => r.id === codeComponent)?.name ?? instanceExportOf(codeComponent))
80
+ : (def?.name ?? "Components");
81
+
82
+ return (
83
+ <>
84
+ {dialog}
85
+ <InCell name="left">
86
+ <ComponentLibraryRail doc={doc} current={subject} query={query} onQuery={setQuery} />
87
+ </InCell>
88
+
89
+ <InCell name="centre">
90
+ {subject === null ? (
91
+ <ComponentsHome doc={doc} query={query} />
92
+ ) : usesOpen ? (
93
+ <EveryUse />
94
+ ) : (
95
+ // THE COMPONENT ITSELF, a hole like the studios' (`.stage-window`):
96
+ // no paint, no pointer, so a drag on the subject orbits the stage.
97
+ // The transport under it paints and takes its own pointer.
98
+ <>
99
+ <div className="stage-window components-preview-hole" aria-hidden="true" data-testid="components-preview-hole" />
100
+ <PreviewTransport />
101
+ </>
102
+ )}
103
+ </InCell>
104
+
105
+ <InCell name="bar">
106
+ <div className="component-studio-bar" role="group" aria-label={name} data-testid="components-preview">
107
+ <ComponentsBack testId="components-back" guard={guard} />
108
+ {subject === null ? (
109
+ <HomeBar query={query} onQuery={setQuery} />
110
+ ) : (
111
+ <ComponentCrumb
112
+ sel={subject}
113
+ name={
114
+ <span className="component-studio-name is-label" title={name}>
115
+ {name}
116
+ </span>
117
+ }
118
+ />
119
+ )}
120
+ {subject === null ? null : (
121
+ <div className="component-studio-tools">
122
+ <ComponentsTabSwitch />
123
+ <StudioZoom />
124
+ </div>
125
+ )}
126
+ </div>
127
+ </InCell>
128
+
129
+ </>
130
+ );
131
+ }
132
+
133
+ /** The home's bar (C5): "All components", the two counts, the search and
134
+ * New component. New makes an empty master and opens it here, on its Edit
135
+ * tab, never in a Shot. */
136
+ function HomeBar(props: { query: string; onQuery: (q: string) => void }) {
137
+ const store = useStore();
138
+ const doc = useShotEditor((s) => s.doc);
139
+ const readOnly = useShotEditor((s) => s.readOnly);
140
+ if (doc === null) return null;
141
+ return (
142
+ <>
143
+ <span className="component-studio-name is-label">All components</span>
144
+ <HomeCounts doc={doc} />
145
+ <div className="component-studio-tools">
146
+ <label className="components-home-search">
147
+ <input
148
+ type="search"
149
+ value={props.query}
150
+ placeholder="Search components"
151
+ aria-label="Search components"
152
+ data-testid="components-home-search"
153
+ onChange={(e) => props.onQuery(e.target.value)}
154
+ />
155
+ </label>
156
+ <button
157
+ type="button"
158
+ className="btn is-primary"
159
+ data-testid="components-new"
160
+ disabled={readOnly}
161
+ title="A new Studio-made component, opened here"
162
+ onClick={() => store.createEmptyComponent("Component")}
163
+ >
164
+ + New component
165
+ </button>
166
+ </div>
167
+ </>
168
+ );
169
+ }
170
+
171
+ function HomeCounts(props: { doc: Doc3D }) {
172
+ const rows = useHomeRows(props.doc, "");
173
+ return (
174
+ <span className="components-home-counts" data-testid="components-home-counts">
175
+ {rows.projectCount} in this project · {rows.libraryCount} in your library
176
+ </span>
177
+ );
178
+ }
179
+