@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
@@ -6,39 +6,66 @@
6
6
  // ponytail: uniform radius only; add the per-corner expander when a template
7
7
  // needs one.
8
8
  import { InspectorRow, InspectorSection, NumberField } from "@dailies-studio/ui";
9
- import type { CornerRadius } from "@dailies-studio/shot/doc";
10
- import { useSelectionValue, useSelectionWrite } from "../useDocWrite.js";
9
+ import { KeyframeDot } from "../KeyframeDot.js";
10
+ import type { CornerRadius, Layer3D, LayerPaint } from "@dailies-studio/shot/doc";
11
+ import { useSelectedLayers, useSelectionScrub, useSelectionValue, useSelectionWrite } from "../useDocWrite.js";
12
+
13
+ /** The four corners this section's one field writes, in the schema's own key
14
+ * order — which is also the order codegen prints them in. */
15
+ const RADIUS_PATHS = ["paint.radius.tl", "paint.radius.tr", "paint.radius.br", "paint.radius.bl"] as const;
16
+ /** The same four, as the diamond's tooltip names what it keys together. */
17
+ const RADIUS_PARTS = ["Top left", "top right", "bottom right", "bottom left"] as const;
11
18
 
12
19
  export function CornerSection() {
13
20
  const write = useSelectionWrite();
14
21
  const radius = useSelectionValue((layer) => uniformOf(layer.paint.radius));
22
+ // Mixed INSIDE one layer too: an edit writes one value to all four corners,
23
+ // so a layer with per-corner radii reads Mixed before that flattens it.
24
+ const cornersDiffer = useSelectedLayers().some((layer) => !isUniform(layer.paint.radius));
25
+ // ONE builder for the typed value and the drag, because a capture is handed a
26
+ // layer out of the gesture's BASE document: a drag that re-derived the corner
27
+ // from what the panel last rendered would compound its own moves.
28
+ const scrub = useSelectionScrub((layer, raw) => withRadius(layer, raw as number));
15
29
 
16
30
  return (
17
- <InspectorSection title="Corner" persistKey="shot:corner">
31
+ <InspectorSection className="insp-object" title="Corner" persistKey="shot:corner">
32
+ {/* ONE diamond for FOUR paths: the control writes all four corners, so it
33
+ has one value and one keyframe gesture, and no expose pin (a pin
34
+ publishes one target, and one corner is not what this row edits).
35
+ See KeyframeDot. */}
18
36
  <InspectorRow>
19
37
  <NumberField
20
38
  value={radius.value ?? 0}
21
- mixed={radius.mixed}
39
+ mixed={radius.mixed || cornersDiffer}
22
40
  label="Radius"
23
41
  ariaLabel="Corner radius"
24
42
  unit="px"
25
43
  min={0}
44
+ // No upper limit: a big enough radius is a pill shape.
26
45
  step={1}
27
- onCommit={(next) =>
28
- write((layer) => ({
29
- ...layer,
30
- paint:
31
- next <= 0
32
- ? withoutRadius(layer.paint)
33
- : { ...layer.paint, radius: { tl: next, tr: next, br: next, bl: next } },
34
- }))
35
- }
46
+ trailing={<KeyframeDot path={RADIUS_PATHS} label="Radius" parts={RADIUS_PARTS} />}
47
+ onCommit={(next) => write((layer) => withRadius(layer, next))}
48
+ onScrubStart={scrub.start}
49
+ onScrub={scrub.move}
50
+ onScrubEnd={scrub.end}
36
51
  />
37
52
  </InspectorRow>
38
53
  </InspectorSection>
39
54
  );
40
55
  }
41
56
 
57
+ /** 0 or less DELETES the key rather than storing a zero radius: absent already
58
+ * means square corners, and codegen prints the block by key order. */
59
+ function withRadius(layer: Layer3D, next: number): Layer3D {
60
+ return {
61
+ ...layer,
62
+ paint:
63
+ next <= 0
64
+ ? withoutRadius(layer.paint)
65
+ : { ...layer.paint, radius: { tl: next, tr: next, br: next, bl: next } },
66
+ } as Layer3D;
67
+ }
68
+
42
69
  /** The largest corner, so a document with mixed corners reads as the shape the
43
70
  * author sees rather than as zero. */
44
71
  function uniformOf(radius: CornerRadius | undefined): number {
@@ -46,7 +73,11 @@ function uniformOf(radius: CornerRadius | undefined): number {
46
73
  return Math.max(radius.tl, radius.tr, radius.br, radius.bl);
47
74
  }
48
75
 
49
- function withoutRadius(paint: { radius?: CornerRadius }): typeof paint {
76
+ function isUniform(radius: CornerRadius | undefined): boolean {
77
+ return radius === undefined || (radius.tl === radius.tr && radius.tr === radius.br && radius.br === radius.bl);
78
+ }
79
+
80
+ function withoutRadius(paint: LayerPaint): LayerPaint {
50
81
  const { radius: _drop, ...rest } = paint;
51
82
  return rest;
52
83
  }
@@ -0,0 +1,315 @@
1
+ // THE PROPS PLAYGROUND: a definition's published surface, LIVE.
2
+ //
3
+ // The ledger this replaces listed the props and let you rename or retire them,
4
+ // which meant the one panel naming a component's controls was the one place
5
+ // they could not be turned. An author had to place an instance to find out what
6
+ // their own component's Colour prop did.
7
+ //
8
+ // So every row is now the control itself, and it is deliberately the SAME row
9
+ // as the instance panel's: one `PropRow` over the control the prop's target
10
+ // describes (`exposedRowOf`: a published 0..1 opacity is a bounded field, a
11
+ // published enum keeps its options, a published text keeps its line breaks),
12
+ // with one drag bracket per row. What differs is only the subject: there the
13
+ // value belongs to a placement, here it belongs to the definition.
14
+ //
15
+ // ── WHAT A ROW READS, AND WHY IT IS NOT `prop.default` ──────────────────
16
+ //
17
+ // The interior layer is the RUNTIME truth: `applyOverrides` skips a prop no
18
+ // instance overrides, so an un-overridden placement renders the layer's own
19
+ // stored value. `prop.default` is a mirror, kept in step by `setExposedValue`
20
+ // writing both halves in one transaction, and it drifts the moment the
21
+ // published field is edited anywhere else (the layer's own section, a stage
22
+ // drag, an agent's `update_layer`). This panel reads the layer, else what the
23
+ // definition draws there (`exposedMasterValue`), so it can never show a number
24
+ // the stage disagrees with.
25
+ //
26
+ // ── TRY FIRST, SAVE ON PURPOSE ──────────────────────────────────────────
27
+ //
28
+ // With "Apply to all instances" off (the default) a turn is only TRIED:
29
+ // `playComponentProp` holds it and the stage draws it the way a placement's
30
+ // overrides are drawn. The document is untouched until the box is ticked,
31
+ // which saves what was tried in one undo step (`setComponentApplyAll`).
32
+ //
33
+ // THE HEAD'S RESET DROPS WHAT IS TRIED, and nothing else, so it is drawn
34
+ // only while Apply is off. With Apply on, a turn writes the master itself:
35
+ // nothing is ever tried, no row differs from the master, and undo takes a
36
+ // turn back, so a Reset there could never be pressed. One there once put
37
+ // each prop back to its published `default`, and that only ever did anything
38
+ // where the default had drifted: it wrote the stale value back over the
39
+ // author's later edit.
40
+ //
41
+ // ── ONE IMPLEMENTATION, TWO FACES ───────────────────────────────────────
42
+ //
43
+ // The inspector renders this for a definition on both faces (the Studio face
44
+ // and the Layers face with nothing selected). A second copy would be two
45
+ // widget vocabularies over one document field.
46
+ import { IconClose, IconDots, InspectorSection, PropRow, useContextMenu, useLocked, usePrompt } from "@dailies-studio/ui";
47
+ import type { PromptRequest, PropControlAsset } from "@dailies-studio/ui";
48
+ import { controlLabel } from "@dailies-studio/contract";
49
+ import { exposedMasterValue, readAtPath, setExposedValue } from "@dailies-studio/shot/doc";
50
+ import type { ComponentDef3D, ExposedProp3D } from "@dailies-studio/shot/doc";
51
+ import type { Value } from "@dailies-studio/engine";
52
+ import { useMemo, useRef } from "react";
53
+ import { useShotEditor, useStore } from "../../../state/context.js";
54
+ import { ApplyAllToggle } from "../../studio/componentParts.js";
55
+ import { coercePropValue, exposedRowOf, masterRowValue, projectAssetsOf, propEditOf, shownPropValue } from "../propValue.js";
56
+ import { useScrub } from "../useDocWrite.js";
57
+
58
+ export function DefinitionProps({ def }: { def: ComponentDef3D }) {
59
+ // ONE dialog for the whole section, not one per row: `usePrompt` mounts a
60
+ // `PromptDialog`, and a definition with a dozen props would otherwise mount a
61
+ // dozen of them to show at most one.
62
+ const { prompt, dialog } = usePrompt();
63
+ const store = useStore();
64
+ const viewer = useShotEditor((s) => s.readOnly);
65
+ const saving = useShotEditor((s) => s.componentApplyAll) && !viewer;
66
+ const tried = useShotEditor((s) => Object.keys(s.componentPlay).length);
67
+ const assetTable = useShotEditor((s) => s.doc?.assets);
68
+ const assets = useMemo(() => projectAssetsOf(assetTable), [assetTable]);
69
+ // RESET: drop every tried value. Only while Apply is off (see the header).
70
+ const reset = saving ? null : (
71
+ <button
72
+ type="button"
73
+ className="props-head-reset"
74
+ data-testid="definition-props-reset"
75
+ disabled={tried === 0}
76
+ title={tried === 0 ? "Nothing tried" : "Drop every tried value"}
77
+ onClick={(e) => {
78
+ e.stopPropagation();
79
+ store.resetComponentPlay();
80
+ }}
81
+ >
82
+ Reset
83
+ </button>
84
+ );
85
+ return (
86
+ <InspectorSection className="insp-object" title="Properties" persistKey="shot:definition-exposed" action={reset}>
87
+ {dialog}
88
+ {def.exposed.length === 0 ? null : <ApplyAllToggle disabled={viewer} disabledReason="View only" />}
89
+ {def.exposed.length === 0 ? (
90
+ // NAMES THE ONE WAY IN. An empty panel that only says it is empty is a
91
+ // dead end, and the affordance it points at is not on this face: the
92
+ // pin sits beside the keyframe diamond, inside a field box of the layer
93
+ // that owns the field, on the Layers face.
94
+ <p className="insp-empty">
95
+ Nothing published yet. Open the <strong>Edit</strong> tab, select a layer, and press the pin
96
+ inside any property&apos;s field to publish it. Every instance can then override it.
97
+ </p>
98
+ ) : (
99
+ def.exposed.map((prop) => (
100
+ <ExposedPropRow key={prop.key} def={def} prop={prop} prompt={prompt} saving={saving} assets={assets} />
101
+ ))
102
+ )}
103
+ </InspectorSection>
104
+ );
105
+ }
106
+
107
+ /**
108
+ * One published property: turn it, relabel it, retire it.
109
+ *
110
+ * A component and not inline JSX because the drag bracket is a HOOK and there
111
+ * is one gesture per prop. A colour picker's SV square, its hue bar, its alpha
112
+ * bar and a range field's slider route a drag ENTIRELY through `scrub.move`
113
+ * and never call `commit` while the pointer is down, so a row wired to the
114
+ * typed half alone has a control whose thumb moves and whose document does not.
115
+ */
116
+ function ExposedPropRow({
117
+ def,
118
+ prop,
119
+ prompt,
120
+ saving,
121
+ assets,
122
+ }: {
123
+ def: ComponentDef3D;
124
+ prop: ExposedProp3D;
125
+ prompt: (req: PromptRequest) => Promise<string | null>;
126
+ /** "Apply to all instances" is on: turns write the definition. Off = tried. */
127
+ saving: boolean;
128
+ assets: readonly PropControlAsset[];
129
+ }) {
130
+ const store = useStore();
131
+ const materials = useShotEditor((s) => s.doc?.materials);
132
+ const contracts = useShotEditor((s) => s.contracts);
133
+ const tried = useShotEditor((s) => s.componentPlay[prop.key]);
134
+ // The row's verbs are plain buttons in its label column (PropRow's
135
+ // `actions`), so they take the panel's lock here: a read-only row's control
136
+ // is locked by the row itself, and its retire must stay live (it is how an
137
+ // orphan or an undescribed prop is fixed).
138
+ const locked = useLocked();
139
+ const menu = useContextMenu();
140
+ const defId = def.id;
141
+ const row = exposedRowOf(prop, def, materials, contracts);
142
+ const { spec } = row;
143
+ const label = controlLabel(spec);
144
+ const layer = def.layersById[prop.target.layer];
145
+ // What the row shows untried: the layer's own value (what an un-overridden
146
+ // placement renders, shown as it is stored, malformed or not), else what
147
+ // the definition draws there (`exposedMasterValue`: a derived value, a
148
+ // graph parameter's or a contract prop's default), never the published
149
+ // `default`, which drifts from the layer.
150
+ const live = layer === undefined ? undefined : (readAtPath(layer, prop.target.path) as Value | undefined);
151
+ const fallback = live ?? masterRowValue(spec, exposedMasterValue(def, prop, { materials, contracts }));
152
+
153
+ // Re-read from the document it is HANDED, never from a value closed over at
154
+ // render: every capture re-derives from the gesture's base, so a builder that
155
+ // remembered would re-apply the whole drag on top of itself per pointer event.
156
+ // A value the target cannot hold writes nothing.
157
+ const saveScrub = useScrub((next, raw) => {
158
+ const value = coercePropValue(spec, raw);
159
+ return value === null ? next : setExposedValue(next, defId, prop.key, value);
160
+ });
161
+ // TRYING: every move IS the edit, so a cancelled gesture puts back the
162
+ // value it started from.
163
+ const before = useRef<Value | undefined>(undefined);
164
+ const scrub = saving
165
+ ? saveScrub
166
+ : {
167
+ start: () => {
168
+ before.current = tried;
169
+ },
170
+ move: (raw: unknown) => {
171
+ const value = coercePropValue(spec, raw);
172
+ if (value !== null) store.playComponentProp(prop.key, value);
173
+ },
174
+ end: (commit: boolean) => {
175
+ if (!commit) store.playComponentProp(prop.key, before.current ?? null);
176
+ },
177
+ };
178
+ const commit = (raw: unknown): void => {
179
+ const edit = propEditOf(spec, raw, fallback);
180
+ if (edit.kind === "refused") {
181
+ store.reportError(edit.reason);
182
+ return;
183
+ }
184
+ // "No asset" over a value that is already none: drop what is tried, and
185
+ // the saved value (none) shows again.
186
+ if (edit.kind === "clear") {
187
+ if (!saving) store.playComponentProp(prop.key, null);
188
+ return;
189
+ }
190
+ if (saving) store.setExposedPropValue(defId, prop.key, edit.value);
191
+ else store.playComponentProp(prop.key, edit.value);
192
+ };
193
+
194
+ // THE ROW'S VERBS LIVE IN ITS LABEL COLUMN (PropRow's `actions`), as ONE
195
+ // "More" that opens Rename… and Stop publishing. A verb never changes the
196
+ // control's width, and it is drawn once per row: as a box's accessory it
197
+ // was drawn in every box of a vector, and two of them took a third-width
198
+ // box's prefix and unit at the default width and spilled past its edge at
199
+ // the 264px floor. In the label column a vector's three boxes keep their
200
+ // whole width for the value. Rename is a PROMPT rather than an inline field
201
+ // for the same reason the component's own name is: it is a rare edit, and a
202
+ // permanently mounted input costs a row its readability every time it is
203
+ // not being used.
204
+ const retire = (): void => store.deleteExposedProp(defId, prop.key);
205
+ const rename = (): void => {
206
+ void prompt({
207
+ title: "Rename property",
208
+ label: "Name",
209
+ initialValue: prop.label,
210
+ confirmLabel: "Rename",
211
+ }).then((next) => {
212
+ if (next !== null && next !== "") store.renameExposedProp(defId, prop.key, next);
213
+ });
214
+ };
215
+ const more = (
216
+ <button
217
+ type="button"
218
+ className="insp-key"
219
+ aria-label={`More for ${label}`}
220
+ aria-haspopup="menu"
221
+ aria-expanded={menu.menu !== null}
222
+ title="Rename or stop publishing"
223
+ disabled={locked}
224
+ onClick={(e) => {
225
+ const at = e.currentTarget.getBoundingClientRect();
226
+ menu.open({ x: at.left, y: at.bottom }, [
227
+ {
228
+ kind: "action",
229
+ id: "rename",
230
+ label: "Rename…",
231
+ title: "The key instances override by does not change",
232
+ onSelect: rename,
233
+ },
234
+ {
235
+ kind: "action",
236
+ id: "retire",
237
+ label: "Stop publishing",
238
+ danger: true,
239
+ title: "Instance overrides stay stored",
240
+ onSelect: retire,
241
+ },
242
+ ]);
243
+ }}
244
+ >
245
+ <IconDots />
246
+ </button>
247
+ );
248
+ // An orphan's one verb, pressed directly: there is nothing else to choose.
249
+ const remove = (
250
+ <button
251
+ type="button"
252
+ className="insp-key is-danger"
253
+ aria-label={`Stop publishing ${label}`}
254
+ title="Stop publishing: instance overrides stay stored"
255
+ disabled={locked}
256
+ onClick={retire}
257
+ >
258
+ <IconClose />
259
+ </button>
260
+ );
261
+ // The key is override identity, not a caption, so it rides the label's
262
+ // tooltip beside the target it writes rather than taking the line the
263
+ // author reads.
264
+ const where = `Key ${prop.key} · ${layer?.label ?? prop.target.layer} · ${prop.target.path}`;
265
+
266
+ if (layer === undefined) {
267
+ // AN ORPHAN, said plainly. `setExposedValue` and `applyOverrides` both skip
268
+ // a prop whose target is gone, so a live control here would be a widget
269
+ // that writes nothing, and the save gate names this prop anyway. The value
270
+ // it last held stays on screen, read-only, and retire is the only verb
271
+ // left, so it is the only one offered. Nothing can be tried on it, so
272
+ // its dot lane stays empty, but it is reserved: without it the label
273
+ // started 10px left of every live row's above and below it.
274
+ return (
275
+ <PropRow
276
+ spec={spec}
277
+ value={shownPropValue(spec, prop.default)}
278
+ commit={() => {}}
279
+ scrub={saveScrub}
280
+ readOnly
281
+ changed={false}
282
+ actions={remove}
283
+ description={where}
284
+ error="Its layer is gone, so nothing drives this any more."
285
+ assets={assets}
286
+ rowProps={{ "data-definition-prop": prop.key }}
287
+ />
288
+ );
289
+ }
290
+
291
+ return (
292
+ <>
293
+ <PropRow
294
+ spec={spec}
295
+ value={shownPropValue(spec, tried ?? fallback)}
296
+ commit={commit}
297
+ scrub={scrub}
298
+ // THE BLUE DOT: a value tried here, not saved.
299
+ changed={tried !== undefined}
300
+ changedLabel="Tried, not saved"
301
+ dotProps={{ "data-tried": prop.key }}
302
+ {...(row.undescribed ? { readOnly: true } : {})}
303
+ {...(row.opaqueColor ? { opaqueColor: true } : {})}
304
+ actions={more}
305
+ description={where}
306
+ assets={assets}
307
+ // A hook for the row, not a style: nothing restyles a published
308
+ // prop's row, which is the house PropRow.
309
+ rowProps={{ "data-definition-prop": prop.key }}
310
+ />
311
+ {/* The menu the row's More opens, once per row, beside it. */}
312
+ {menu.menu}
313
+ </>
314
+ );
315
+ }
@@ -0,0 +1,136 @@
1
+ // The open DEFINITION itself — the component context's control panel when
2
+ // nothing inside it is selected (unify P2), and the Component Studio's whole
3
+ // right rail. The def-level twin of SceneSection: what it publishes and how
4
+ // big it is. The mo1 read: this is the module's own
5
+ // property sheet.
6
+ //
7
+ // ── THE ORDER IS THE QUESTION AN AUTHOR ASKS ────────────────────────────
8
+ //
9
+ // Properties first, then the canvas. It used to run the other
10
+ // way, which put the definition's WIDTH above the surface every instance of it
11
+ // is driven through — right while the panel was a ledger nobody could turn, and
12
+ // wrong the moment the props became live controls (`DefinitionProps`). The two
13
+ // faces share this component, so the order is one decision rather than two.
14
+ //
15
+ // EXPOSED PROPS are created by the agent's `expose_prop` and by the chrome's
16
+ // own pin (`inspector/ExposeDot.tsx`, inside a row's field box beside the
17
+ // keyframe diamond, on the layers face). Everything after that is
18
+ // `DefinitionProps`: the value, the label and the retire, all respecting the
19
+ // key-is-identity rule (a rename never touches the key, a delete leaves stored
20
+ // overrides quarantined in place).
21
+ import { InspectorRow, InspectorSection, NumberField, TextField } from "@dailies-studio/ui";
22
+ import type { ScrubHandlers } from "@dailies-studio/ui";
23
+ import {
24
+ componentDefsOf,
25
+ defDurationFrames,
26
+ instancesOf,
27
+ setComponentDuration,
28
+ setComponentSize,
29
+ } from "@dailies-studio/shot/doc";
30
+ import type { Doc3D } from "@dailies-studio/shot/doc";
31
+ import { useShotEditor, useStore } from "../../../state/context.js";
32
+ import { useScrub } from "../useDocWrite.js";
33
+ import { DefinitionProps } from "./DefinitionProps.js";
34
+
35
+ /** A whole, positive number of pixels or frames, the floor these fields keep. */
36
+ const whole = (n: number): number => Math.max(1, Math.round(n));
37
+
38
+ /** One canvas side, written into the definition the drag is HANDED (a scrub
39
+ * re-derives every move from its base), the other side kept as it is there. */
40
+ function sizeWrite(defId: string, axis: 0 | 1): (doc: Doc3D, raw: unknown) => Doc3D {
41
+ return (doc, raw) => {
42
+ const def = componentDefsOf(doc)[defId];
43
+ if (def === undefined || typeof raw !== "number" || !Number.isFinite(raw)) return doc;
44
+ const size: [number, number] = [def.size[0], def.size[1]];
45
+ size[axis] = whole(raw);
46
+ return setComponentSize(doc, defId, size);
47
+ };
48
+ }
49
+
50
+ /** A NumberField's drag half, from the store's scrub trio. */
51
+ function dragOf(scrub: ScrubHandlers): {
52
+ onScrubStart: () => void;
53
+ onScrub: (value: number) => void;
54
+ onScrubEnd: (commit: boolean) => void;
55
+ } {
56
+ return { onScrubStart: scrub.start, onScrub: scrub.move, onScrubEnd: scrub.end };
57
+ }
58
+
59
+ export function DefinitionSection() {
60
+ const store = useStore();
61
+ const doc = useShotEditor((s) => s.doc);
62
+ const editingDef = useShotEditor((s) => s.editingDef);
63
+ const def = editingDef === null ? undefined : doc?.components?.[editingDef];
64
+ const defId = def?.id ?? "";
65
+ // THE DRAG HALVES: a drag on W, H or Frames moves the definition while the
66
+ // pointer is down, one undo entry, instead of waiting for the release.
67
+ const width = useScrub(sizeWrite(defId, 0));
68
+ const height = useScrub(sizeWrite(defId, 1));
69
+ const frames = useScrub((next, raw) =>
70
+ typeof raw === "number" && Number.isFinite(raw) ? setComponentDuration(next, defId, whole(raw)) : next,
71
+ );
72
+ if (doc === null || def === undefined) return null;
73
+
74
+ const placed = instancesOf(doc, def.id).length;
75
+
76
+ return (
77
+ <>
78
+ <DefinitionProps key={def.id} def={def} />
79
+
80
+ <InspectorSection className="insp-object" title="Component" persistKey="shot:definition" collapsible={false}>
81
+ <InspectorRow label="Name">
82
+ <TextField
83
+ value={def.name}
84
+ ariaLabel="Component name"
85
+ onCommit={(name) => store.renameComponent(def.id, name)}
86
+ />
87
+ </InspectorRow>
88
+ {/* THE CANVAS, a W | H pair like the Transform section's: two field
89
+ boxes side by side, each named inside, rather than two fields
90
+ flattened into one labelled pill. */}
91
+ <InspectorRow>
92
+ <div className="insp-vec">
93
+ <NumberField
94
+ value={def.size[0]}
95
+ label="W"
96
+ ariaLabel="Component width"
97
+ unit="px"
98
+ min={1}
99
+ step={1}
100
+ onCommit={(w) => store.setComponentSize(def.id, [whole(w), def.size[1]])}
101
+ {...dragOf(width)}
102
+ />
103
+ <NumberField
104
+ value={def.size[1]}
105
+ label="H"
106
+ ariaLabel="Component height"
107
+ unit="px"
108
+ min={1}
109
+ step={1}
110
+ onCommit={(h) => store.setComponentSize(def.id, [def.size[0], whole(h)])}
111
+ {...dragOf(height)}
112
+ />
113
+ </div>
114
+ </InspectorRow>
115
+ <InspectorRow>
116
+ <NumberField
117
+ value={defDurationFrames(def)}
118
+ label="Frames"
119
+ ariaLabel="Component duration"
120
+ min={1}
121
+ step={1}
122
+ onCommit={(f) => store.setComponentDuration(def.id, Math.round(f))}
123
+ {...dragOf(frames)}
124
+ />
125
+ </InspectorRow>
126
+ <p className="insp-note">
127
+ {placed === 0
128
+ ? "Not placed yet. Use it in a shot or add it to the storyboard."
129
+ : placed === 1
130
+ ? "Placed once. Edits here reach it."
131
+ : `Placed ${placed} times. Edits here reach all of them.`}
132
+ </p>
133
+ </InspectorSection>
134
+ </>
135
+ );
136
+ }