@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,235 @@
1
+ // THE ONE LIVE COMPONENT PREVIEW: the inspector lead of a selected component
2
+ // card, drawn by the SHOT STAGE, framed exactly as a Shot frames it.
3
+ //
4
+ // The stage itself (the second `/shot-stage.html`, the hosted epoch, the
5
+ // loop, the live budget and the poster) is `StagePreview`. This file builds
6
+ // the ONE-INSTANCE document it draws: the Project's size, fps and assets, one
7
+ // Shot, one instance layer the size of the frame. Nothing is saved.
8
+ //
9
+ // LOOPING, OR THE CARD'S FRAME. The preview loops over the component's length,
10
+ // at the Project's fps. A card that names a frame (the inspector's Frame row)
11
+ // shows that frame and holds it.
12
+ //
13
+ // IN BUDGET BY THE CARD'S ID, so a card that already holds that slot shares it
14
+ // rather than taking a second, and the poster is keyed by the component, its
15
+ // content hash and the card's props (posterCache.ts).
16
+ //
17
+ // A CODE COMPONENT OR A STUDIO DEFINITION. A card naming `def` draws a slim
18
+ // document of that definition's closure (`defClosureOf`), placed once with
19
+ // the card's props as its overrides, so an edit elsewhere in the Project
20
+ // never reloads the preview.
21
+ import { useMemo, useState } from "react";
22
+ import type { ReactNode } from "react";
23
+ import { canonicalJSON, fnv1a64 } from "@dailies-studio/contract";
24
+ import type { Contract, EmbedContractRef } from "@dailies-studio/contract";
25
+ import {
26
+ addComponentInstance,
27
+ componentPreviewDoc,
28
+ defClosureOf,
29
+ defDurationFrames,
30
+ previewBaseDoc,
31
+ previewBindingOf,
32
+ } from "@dailies-studio/shot/doc";
33
+ import type { DefClosure, Doc3D, ReferenceItem3D } from "@dailies-studio/shot/doc";
34
+ import { brandBackdrop } from "../../bridgeTypes.js";
35
+ import type { ShotComponentBackground } from "../../bridgeTypes.js";
36
+ import { posterKey } from "./posterCache.js";
37
+ import { StagePreview } from "./StagePreview.js";
38
+
39
+ type ComponentCard = Extract<ReferenceItem3D, { type: "component" }>;
40
+
41
+ /** How long a preview loops when the catalog names no length: two seconds. */
42
+ export const DEFAULT_LOOP_SECONDS = 2;
43
+
44
+ /**
45
+ * The one-instance document the preview stage draws. Pure, so the suite pins
46
+ * it without a stage.
47
+ *
48
+ * The CARD'S RAW PROPS, never harness-resolved paths: the stage maps an
49
+ * asset-kind value through `doc.assets` itself, so the Project's asset table
50
+ * rides along. The contract rides as the binding an instance layer would get
51
+ * (`contractBinding`), because without one the stage spreads raw contract
52
+ * keys as React prop names.
53
+ */
54
+ export function cardStageDoc(
55
+ doc: Pick<Doc3D, "size" | "fps" | "assets">,
56
+ item: ComponentCard,
57
+ binding: EmbedContractRef | undefined,
58
+ lengthFrames: number,
59
+ backdrop?: string,
60
+ ): Doc3D {
61
+ // The shot package's builder, which `preview_component` draws too.
62
+ return componentPreviewDoc(
63
+ doc,
64
+ { component: item.component ?? "", label: item.label, props: item.props, binding },
65
+ lengthFrames,
66
+ backdrop,
67
+ );
68
+ }
69
+
70
+ /**
71
+ * The one-instance document for a STUDIO DEFINITION's card: the closure's
72
+ * definitions, assets and material graphs, one placement of the definition at
73
+ * 1:1 in the middle of the Project's frame, the card's props as its
74
+ * overrides. Pure, like `cardStageDoc`. Null when the placement is refused.
75
+ */
76
+ export function defStageDoc(
77
+ doc: Pick<Doc3D, "size" | "fps">,
78
+ closure: DefClosure,
79
+ props: ComponentCard["props"],
80
+ lengthFrames: number,
81
+ backdrop?: string,
82
+ ): Doc3D | null {
83
+ const { sized, sceneId } = previewBaseDoc({ size: doc.size, fps: doc.fps, assets: closure.assets }, lengthFrames, backdrop);
84
+ const withDefs: Doc3D = {
85
+ ...sized,
86
+ components: { ...closure.nested, [closure.def.id]: closure.def },
87
+ ...(Object.keys(closure.materials).length === 0 ? {} : { materials: closure.materials }),
88
+ };
89
+ const placed = addComponentInstance(withDefs, sceneId, closure.def.id);
90
+ if (placed.instanceId === null) return null;
91
+ const scene = placed.doc.scenesById[sceneId]!;
92
+ const layer = scene.layersById[placed.instanceId];
93
+ if (layer?.kind !== "component") return null;
94
+ return {
95
+ ...placed.doc,
96
+ scenesById: {
97
+ ...placed.doc.scenesById,
98
+ [sceneId]: {
99
+ ...scene,
100
+ layersById: { ...scene.layersById, [layer.id]: { ...layer, component: { ...layer.component, overrides: props } } },
101
+ },
102
+ },
103
+ };
104
+ }
105
+
106
+ /** A closure's content as a hash: what the poster key and the stage document
107
+ * follow, so an unrelated edit leaves both alone. */
108
+ export function closureHash(closure: DefClosure | null): string {
109
+ if (closure === null) return "none";
110
+ try {
111
+ return fnv1a64(canonicalJSON(closure));
112
+ } catch {
113
+ return fnv1a64(JSON.stringify(closure));
114
+ }
115
+ }
116
+
117
+ /** Closures and their hashes, per document revision: a doc is immutable, so
118
+ * every card and the sheet that render one revision walk and hash each
119
+ * definition once, and the revision's entries go with it. */
120
+ const closures = new WeakMap<Doc3D, Map<string, { closure: DefClosure | null; hash: string }>>();
121
+
122
+ /** `defClosureOf` and its `closureHash`, memoized per document revision. */
123
+ export function closureFor(doc: Doc3D, defId: string): { closure: DefClosure | null; hash: string } {
124
+ let byDef = closures.get(doc);
125
+ if (byDef === undefined) {
126
+ byDef = new Map();
127
+ closures.set(doc, byDef);
128
+ }
129
+ let hit = byDef.get(defId);
130
+ if (hit === undefined) {
131
+ const closure = defClosureOf(doc, defId);
132
+ hit = { closure, hash: closureHash(closure) };
133
+ byDef.set(defId, hit);
134
+ }
135
+ return hit;
136
+ }
137
+
138
+ /** `value` as it was the last time `key` changed: derived state held across
139
+ * renders the React way (a set during render). */
140
+ function useStableBy<T>(value: T, key: string): T {
141
+ const [held, setHeld] = useState({ key, value });
142
+ if (held.key !== key) {
143
+ setHeld({ key, value });
144
+ return value;
145
+ }
146
+ return held.value;
147
+ }
148
+
149
+ /**
150
+ * The preview's ground as a colour (bridge v45): dark is the desk token,
151
+ * light the paper token, brand the Project's first brand colour or else dark.
152
+ * Read off the chrome's own tokens, since the card document is a plain Shot.
153
+ */
154
+ export function cardBackdrop(background: ShotComponentBackground, doc: Pick<Doc3D, "resources"> | null): string {
155
+ const token = (name: string, fallback: string): string =>
156
+ typeof document === "undefined"
157
+ ? fallback
158
+ : getComputedStyle(document.documentElement).getPropertyValue(name).trim() || fallback;
159
+ const desk = token("--surface-sunken", "#080808");
160
+ if (background === "light") return token("--paper-97", "#f5f5f8");
161
+ if (background === "brand") return brandBackdrop(doc) ?? desk;
162
+ return desk;
163
+ }
164
+
165
+ /**
166
+ * THE BINDING A PLACED INSTANCE WOULD CARRY, `store.bindingFor`'s rule: the
167
+ * server's availability decides import or snapshot. Null when there is no
168
+ * contract, or when it cannot be frozen (a snapshot refuses a contract whose
169
+ * hashes do not describe its keys): the preview then draws with raw props
170
+ * rather than throwing inside a render and taking the inspector down.
171
+ */
172
+ export function contractBinding(
173
+ contract: Contract | undefined,
174
+ availability: "sibling" | "colocated" | "inferred" | undefined,
175
+ ): EmbedContractRef | undefined {
176
+ return contract === undefined ? undefined : previewBindingOf({ availability: availability ?? "inferred", contract });
177
+ }
178
+
179
+ export function ComponentStage(props: {
180
+ doc: Doc3D;
181
+ item: ComponentCard;
182
+ contract: Contract | undefined;
183
+ /** The registry row's verdict: import the contract, or freeze it. */
184
+ availability: "sibling" | "colocated" | "inferred" | undefined;
185
+ /** The shipped item's length, when the catalog says; else two seconds. */
186
+ lengthFrames: number | undefined;
187
+ /** The ground behind the component (bridge v45). Omitted keeps the Shot's. */
188
+ background?: ShotComponentBackground;
189
+ /** Loops over this many frames instead of the component's length. */
190
+ loopFrames?: number;
191
+ /** Whether the stage may go live. False shows the poster (default true). */
192
+ live?: boolean;
193
+ /** What shows while the stage is not live and no poster is cached yet. */
194
+ fallback?: ReactNode;
195
+ }) {
196
+ const { doc, item, contract, availability } = props;
197
+ const fps = doc.fps.num / doc.fps.den;
198
+ // A STUDIO DEFINITION'S closure, held while its content is the same.
199
+ const defId = item.component === undefined ? item.def : undefined;
200
+ const own = defId === undefined ? null : closureFor(doc, defId);
201
+ const freshClosure = own?.closure ?? null;
202
+ const contentHash = own === null ? (contract?.contractHash ?? item.contractHash ?? "none") : own.hash;
203
+ const closure = useStableBy(freshClosure, contentHash);
204
+ const ownLength = closure === null ? props.lengthFrames : defDurationFrames(closure.def);
205
+ const length = Math.max(1, Math.round(props.loopFrames ?? ownLength ?? DEFAULT_LOOP_SECONDS * fps));
206
+ const backdrop = props.background === undefined ? undefined : cardBackdrop(props.background, doc);
207
+ const binding = useMemo(() => contractBinding(contract, availability), [contract, availability]);
208
+ // KEYED ON WHAT THE CARD DOCUMENT READS, never on `doc` itself: every edit
209
+ // anywhere in the Project is a new `doc`, and a new stage document reloads
210
+ // the preview.
211
+ const { width, height } = doc.size;
212
+ const { num, den } = doc.fps;
213
+ const assets = doc.assets;
214
+ const stageDoc = useMemo(
215
+ () =>
216
+ closure !== null
217
+ ? defStageDoc({ size: { width, height }, fps: { num, den } }, closure, item.props, length, backdrop)
218
+ : cardStageDoc({ size: { width, height }, fps: { num, den }, assets }, item, binding, length, backdrop),
219
+ [width, height, num, den, assets, item, closure, binding, length, backdrop],
220
+ );
221
+ const size = useMemo(() => ({ width, height }), [width, height]);
222
+ return (
223
+ <StagePreview
224
+ doc={stageDoc}
225
+ size={size}
226
+ lengthFrames={length}
227
+ {...(item.frame === undefined ? {} : { frame: item.frame })}
228
+ {...(props.live === undefined ? {} : { live: props.live })}
229
+ slotKey={item.id}
230
+ posterKey={posterKey(item.component ?? item.def ?? item.id, contentHash, item.props)}
231
+ title={`Preview of ${item.label}`}
232
+ fallback={props.fallback}
233
+ />
234
+ );
235
+ }
@@ -0,0 +1,173 @@
1
+ // A SKETCH, SMALL (Paper SB1 card pictures, SB2 strip thumbs, the Brief's
2
+ // thumbs): the board's shot cards and any thumbnail of a sketch. It only
3
+ // draws: no selection, no handles, no pointer.
4
+ //
5
+ // THE STAGE'S PICTURE FIRST. Its caller passes `picture`, the sketch as the
6
+ // still stage draws it (state/stillThumbs.ts, `useSketchThumbs`: brand font,
7
+ // components and all, the same picture the agent's screenshot_shot
8
+ // `{sketch}` returns). Once it is ready it fills the box. Until then, and when
9
+ // it failed, the sketch is drawn in the DOM, below.
10
+ //
11
+ // ONE BOX, ANY WIDTH. Items sit in percentages of the Project's size (layer
12
+ // units: design px, origin at the centre, +y down), and type sizes in `cqw`
13
+ // of the box, so the same markup is right at 128 or at 346 wide and nothing
14
+ // measures. Back to front, as stored: a later item draws on top.
15
+ //
16
+ // ref an image card's picture (`useImageThumb`), a video's poster, a
17
+ // component's name tile, or "Missing" for a card that is gone
18
+ // text the words at their role's size (`SKETCH_TEXT_SIZE`)
19
+ // box the light sketch fill with its edge, dark, or the accent; the
20
+ // label in its corner
21
+ // arrow one SVG line with an open head, its label over the head
22
+ import type { CSSProperties } from "react";
23
+ import { SKETCH_TEXT_SIZE, sketchCardOf } from "@dailies-studio/shot/doc";
24
+ import type { Doc3D, SketchItem3D, SketchRef3D, StoryboardSketch3D } from "@dailies-studio/shot/doc";
25
+ import { useImageThumb } from "../../state/imageThumbs.js";
26
+ import type { StillThumb } from "../../state/stillThumbs.js";
27
+ import { MediaPoster } from "./ReferencePreview.js";
28
+
29
+ const assetUrl = (path: string): string => `/studio/assets/${encodeURIComponent(path)}`;
30
+
31
+ /** A box label's size, design px: the stage's label size (sketch.ts). */
32
+ const LABEL_SIZE = 24;
33
+ /** The open head's arm, design px. */
34
+ const ARROW_HEAD = 36;
35
+
36
+ export function MiniSketch(props: {
37
+ doc: Doc3D;
38
+ sketch: StoryboardSketch3D;
39
+ /** The longest side the pictures inside are fetched for, CSS px. */
40
+ width: number;
41
+ className?: string;
42
+ /** The sketch as the still stage draws it; shown once ready. */
43
+ picture?: StillThumb | null;
44
+ }) {
45
+ const { doc, sketch } = props;
46
+ const { width: w, height: h } = doc.size;
47
+ const arrows = sketch.items.filter((item) => item.kind === "arrow");
48
+ const box = {
49
+ className: `mini-sketch${props.className === undefined ? "" : ` ${props.className}`}`,
50
+ "data-ground": sketch.ground ?? "paper",
51
+ "data-testid": "mini-sketch",
52
+ style: { aspectRatio: `${w} / ${h}` },
53
+ "aria-hidden": true,
54
+ } as const;
55
+ if (props.picture?.status === "ready") {
56
+ return (
57
+ <div {...box} data-picture="stage">
58
+ <img className="mini-sketch-picture" src={props.picture.url} alt="" draggable={false} />
59
+ </div>
60
+ );
61
+ }
62
+ return (
63
+ <div {...box} data-picture="dom">
64
+ {sketch.items.map((item) =>
65
+ item.kind === "arrow" ? null : <MiniItem key={item.id} doc={doc} item={item} width={props.width} />,
66
+ )}
67
+ {arrows.length === 0 ? null : (
68
+ <svg className="mini-sketch-arrows" viewBox={`${-w / 2} ${-h / 2} ${w} ${h}`} preserveAspectRatio="none">
69
+ {arrows.map((item) => (item.kind === "arrow" ? <path key={item.id} d={arrowPath(item.from, item.to)} /> : null))}
70
+ </svg>
71
+ )}
72
+ {arrows.map((item) =>
73
+ item.kind !== "arrow" || item.label === undefined ? null : (
74
+ <span key={`${item.id}-label`} className="mini-sketch-label is-arrow" style={labelAt(doc, item.to)}>
75
+ {item.label}
76
+ </span>
77
+ ),
78
+ )}
79
+ </div>
80
+ );
81
+ }
82
+
83
+ /** The arrow's line and its open head, in design px. */
84
+ export function arrowPath(from: readonly [number, number], to: readonly [number, number]): string {
85
+ const angle = Math.atan2(to[1] - from[1], to[0] - from[0]);
86
+ const arm = (turn: number): string =>
87
+ `${to[0] - ARROW_HEAD * Math.cos(angle + turn)} ${to[1] - ARROW_HEAD * Math.sin(angle + turn)}`;
88
+ return `M ${from[0]} ${from[1]} L ${to[0]} ${to[1]} M ${arm(Math.PI / 6)} L ${to[0]} ${to[1]} L ${arm(-Math.PI / 6)}`;
89
+ }
90
+
91
+ /** An item's box as percentages of the sketch: position is its centre. */
92
+ export function boxStyle(doc: Doc3D, position: readonly [number, number], size: readonly [number, number]): CSSProperties {
93
+ const { width: w, height: h } = doc.size;
94
+ return {
95
+ left: `${((position[0] - size[0] / 2) / w + 0.5) * 100}%`,
96
+ top: `${((position[1] - size[1] / 2) / h + 0.5) * 100}%`,
97
+ width: `${(size[0] / w) * 100}%`,
98
+ height: `${(size[1] / h) * 100}%`,
99
+ };
100
+ }
101
+
102
+ /** Type of `px` design px, as a share of the box's width. */
103
+ const typeSize = (doc: Doc3D, px: number): string => `${(px / doc.size.width) * 100}cqw`;
104
+
105
+ /** An arrow's label, centred over its head. */
106
+ const labelAt = (doc: Doc3D, to: readonly [number, number]): CSSProperties => ({
107
+ left: `${(to[0] / doc.size.width + 0.5) * 100}%`,
108
+ top: `${((to[1] - 40) / doc.size.height + 0.5) * 100}%`,
109
+ fontSize: typeSize(doc, LABEL_SIZE),
110
+ });
111
+
112
+ function MiniItem({ doc, item, width }: { doc: Doc3D; item: Exclude<SketchItem3D, { kind: "arrow" }>; width: number }) {
113
+ const box = boxStyle(doc, item.position, item.size);
114
+ if (item.kind === "text") {
115
+ return (
116
+ <span
117
+ className={`mini-sketch-text is-${item.role}`}
118
+ data-align={item.align ?? "start"}
119
+ style={{ ...box, fontSize: typeSize(doc, SKETCH_TEXT_SIZE[item.role]) }}
120
+ >
121
+ {item.text}
122
+ </span>
123
+ );
124
+ }
125
+ if (item.kind === "box") {
126
+ return (
127
+ <span className="mini-sketch-box" data-tone={item.tone ?? "light"} style={box}>
128
+ {item.label === undefined ? null : (
129
+ <span className="mini-sketch-label" style={{ fontSize: typeSize(doc, LABEL_SIZE) }}>
130
+ {item.label}
131
+ </span>
132
+ )}
133
+ </span>
134
+ );
135
+ }
136
+ return <MiniRef doc={doc} item={item} style={box} px={(item.size[0] / doc.size.width) * width} />;
137
+ }
138
+
139
+ function MiniRef({ doc, item, style, px }: { doc: Doc3D; item: SketchRef3D; style: CSSProperties; px: number }) {
140
+ const card = sketchCardOf(doc, item);
141
+ const asset = card?.type === "asset" ? doc.assets[card.asset] : undefined;
142
+ const image = asset?.kind === "image" ? asset : undefined;
143
+ const thumb = useImageThumb(image === undefined ? "" : assetUrl(image.path), image?.hash ?? "", px);
144
+ const fit = item.fit ?? "cover";
145
+ if (image !== undefined) {
146
+ return (
147
+ <span className="mini-sketch-ref" style={style}>
148
+ {thumb === null ? null : <img src={thumb} alt="" draggable={false} style={{ objectFit: fit }} />}
149
+ </span>
150
+ );
151
+ }
152
+ if (asset?.kind === "video" && card?.type === "asset") {
153
+ const at = card.frame === undefined ? null : (card.frame * doc.fps.den) / doc.fps.num;
154
+ return (
155
+ <span className="mini-sketch-ref" style={style}>
156
+ <MediaPoster className="mini-sketch-media" src={assetUrl(asset.path)} atSeconds={at} />
157
+ </span>
158
+ );
159
+ }
160
+ const name =
161
+ card === undefined
162
+ ? "Missing"
163
+ : card.type === "component"
164
+ ? ((card.def === undefined ? undefined : doc.components?.[card.def]?.name) ?? card.label)
165
+ : card.label;
166
+ return (
167
+ <span className={`mini-sketch-ref is-tile${card === undefined ? " is-missing" : ""}`} style={style}>
168
+ <span className="mini-sketch-label" style={{ fontSize: typeSize(doc, LABEL_SIZE) }}>
169
+ {name}
170
+ </span>
171
+ </span>
172
+ );
173
+ }
@@ -0,0 +1,64 @@
1
+ // ATTACHED TO WHICH PART: the one control a Group, a card and the card's own
2
+ // chip on the canvas all need, in one place.
3
+ //
4
+ // A COMBOBOX, by the house line written at `scene/TransitionSection.tsx`: four
5
+ // options or fewer is a segmented control, a list that grows wants the filter
6
+ // box. Parts are author-created and unbounded, and their labels are unbounded
7
+ // prose in a 252px row.
8
+ //
9
+ // It replaced `<select className="insp-select">`, and that class matched NO
10
+ // rule anywhere in the repo, so the element fell back to user-agent styling
11
+ // with three visible consequences: the OS dropdown arrow instead of the
12
+ // painted chevron (`.select { appearance: none }`), no `max-width: 100%`, and
13
+ // no `min-width: 0` from the in-pill flattener. A native select's automatic
14
+ // minimum size is its longest option, so one long part label pushed the whole
15
+ // inspector into a horizontal scrollbar. The comment over `.select` in
16
+ // `shot-editor/styles.css` is that same failure's earlier postmortem.
17
+ //
18
+ // An UNKNOWN part id is shown rather than silently read as "none": a document
19
+ // can name a part this board no longer has, and a picker that displayed the
20
+ // placeholder would rewrite the binding on the next unrelated edit. Same
21
+ // courtesy `TransitionSection` pays an unknown preset.
22
+ import { Combobox } from "@dailies-studio/ui";
23
+ import type { ComboboxOption } from "@dailies-studio/ui";
24
+ import type { StoryboardPart3D } from "@dailies-studio/shot/doc";
25
+
26
+ /** The empty value IS "no part". `Combobox` shows the placeholder for it, so
27
+ * the trigger reads the none-label without a sentinel id that could ever be
28
+ * mistaken for one. */
29
+ const NONE = "";
30
+
31
+ export function PartPicker(props: {
32
+ parts: readonly StoryboardPart3D[];
33
+ value: string | null;
34
+ /** What "no part" is called here: a group becomes plain, a card unassigned.
35
+ * Choosing it IS the unlink, which is why no menu puts an Unlink button
36
+ * beside a picker whose empty value already says so. */
37
+ noneLabel: string;
38
+ ariaLabel: string;
39
+ onChange: (part: string | null) => void;
40
+ /** Open on mount and take focus: for the card chip, which SWAPS itself for
41
+ * this control on a press and would otherwise drop focus to `<body>`. */
42
+ autoOpen?: boolean;
43
+ /** Dismissed without choosing, so a swapping caller can put its own control
44
+ * back rather than leaving a closed picker in its place. */
45
+ onClose?: () => void;
46
+ }) {
47
+ const known = props.value !== null && props.parts.some((part) => part.id === props.value);
48
+ const options: ComboboxOption[] = [
49
+ { value: NONE, label: props.noneLabel },
50
+ ...props.parts.map((part) => ({ value: part.id, label: part.label })),
51
+ ...(props.value !== null && !known ? [{ value: props.value, label: `${props.value} (unknown)` }] : []),
52
+ ];
53
+ return (
54
+ <Combobox
55
+ options={options}
56
+ value={props.value ?? NONE}
57
+ ariaLabel={props.ariaLabel}
58
+ placeholder={props.noneLabel}
59
+ onChange={(value) => props.onChange(value === NONE ? null : value)}
60
+ {...(props.autoOpen === undefined ? {} : { autoOpen: props.autoOpen })}
61
+ {...(props.onClose === undefined ? {} : { onClose: props.onClose })}
62
+ />
63
+ );
64
+ }