@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,9 @@
1
+ // The shot stage's encode worker file: spawned by tier1Export.ts, served
2
+ // through the project's Vite with mediabunny pinned to the studio's copy
3
+ // (cli/src/pins.ts) — the same treatment the motion harness's worker gets.
4
+ // The whole worker lives in @dailies-studio/shot/tier1; this file exists
5
+ // because a Worker needs a URL of its own.
6
+ import { bootExportWorker } from "@dailies-studio/shot/tier1/workerEntry";
7
+ import type { WorkerScope } from "@dailies-studio/shot/tier1";
8
+
9
+ bootExportWorker(self as unknown as WorkerScope);
package/src/stage/feed.ts CHANGED
@@ -26,11 +26,60 @@
26
26
  // COORDINATES ARE PANE-LOCAL CSS px, from the pane's top-left. `paneAt` returns
27
27
  // exactly that pairing, so the caller passes through what it was handed and
28
28
  // there is no second place where a pane origin gets subtracted.
29
- import type { Camera, Matrix4, Ray } from "three";
30
- import type { GestureKind, ResizeHandle } from "@dailies-studio/shot/doc";
29
+ import type { Camera, Matrix4, Ray, Vector3 } from "three";
30
+ import type { CameraGate, GestureKind, ResizeHandle } from "@dailies-studio/shot/doc";
31
31
  import type { StagePane } from "./panes.js";
32
32
  import type { GizmoGrab } from "./gizmoMath.js";
33
33
  import type { LayerFrame, ScreenQuad, WorldQuad } from "./project.js";
34
+ import type { ShotPeerSelection } from "../bridgeTypes.js";
35
+ import type { ScreenMotionPath } from "./motionPathStage.js";
36
+ import type { Vec3 } from "@dailies-studio/engine";
37
+
38
+ /** Another person's selected layer in one pane (bridge v43). `tag` on the
39
+ * first of their layers only; `ring` when this author selected it too, so
40
+ * theirs draws around ours instead of under it (page 21). */
41
+ export interface PeerQuad {
42
+ quad: ScreenQuad;
43
+ name: string;
44
+ color: string;
45
+ tag: boolean;
46
+ ring: boolean;
47
+ }
48
+
49
+ /** Other people's selections projected into one pane. */
50
+ export function projectPeers(
51
+ peers: readonly ShotPeerSelection[],
52
+ quadFor: (pane: StagePane, layerId: string) => ScreenQuad | null,
53
+ pane: StagePane,
54
+ mine: readonly string[],
55
+ ): PeerQuad[] {
56
+ if (peers.length === 0) return [];
57
+ const own = new Set(mine);
58
+ const out: PeerQuad[] = [];
59
+ for (const peer of peers) {
60
+ let tag = true;
61
+ for (const id of peer.ids) {
62
+ const quad = quadFor(pane, id);
63
+ if (quad === null) continue;
64
+ out.push({ quad, name: peer.name, color: peer.color, tag, ring: own.has(id) });
65
+ tag = false;
66
+ }
67
+ }
68
+ return out;
69
+ }
70
+
71
+ /** A failed layer's outline in one pane, and the name its placeholder says. */
72
+ export interface FailedQuad {
73
+ quad: ScreenQuad;
74
+ label: string;
75
+ }
76
+
77
+ /** A selected mask's outline in one pane (gap 7). `round` for an ellipse
78
+ * mask, whose outline is the ellipse inscribed in its quad. */
79
+ export interface MaskQuad {
80
+ quad: ScreenQuad;
81
+ round: boolean;
82
+ }
34
83
 
35
84
  /** What a press on the current selection turned out to be. */
36
85
  export interface Grab {
@@ -87,9 +136,16 @@ export interface StageFeed {
87
136
  * the graph's SHAPE — the matrices inside it are live references, so motion
88
137
  * needs no invalidation and neither does a seek that only moves things. What
89
138
  * it cannot see is membership, and membership changes for a reason no
90
- * document value predicts: a GLB or an instance module resolves and suspense
91
- * commits a subtree that was not there a frame ago. This counter is that
92
- * event, and it is what lets the walk be memoised across an orbit.
139
+ * document value predicts: a GLB resolves and suspense commits a subtree that
140
+ * was not there a frame ago. This counter is that event, and it is what lets
141
+ * the walk be memoised across an orbit.
142
+ *
143
+ * It moves on a layer group mounting or going (`onLayerGraph`) and on a
144
+ * model reporting (`pushMeshStats`), and on NOTHING ELSE: not on a cut,
145
+ * which only re-parents a resident Shot's group, and not on what a code
146
+ * component renders under its mounted layer (its module landing, its own
147
+ * Suspense, a child it draws on a prop). A walk that needs those (the
148
+ * inside-out shells) walks per draw.
93
149
  */
94
150
  sceneEpoch: number;
95
151
  /**
@@ -104,6 +160,13 @@ export interface StageFeed {
104
160
  * quad re-renders one SVG and zero canvases.
105
161
  */
106
162
  onOverlay: (() => void) | null;
163
+ /** True while the pen holds points. Its preview is projected through
164
+ * `paneAt` at render time, so the in-canvas half then also calls
165
+ * `onOverlay` when the frame pane's camera moves (`cameraPose`, the last
166
+ * projection and view matrices it saw), with no pointer move to cause it:
167
+ * the Shot camera, or inside a definition its working camera. */
168
+ penLive: boolean;
169
+ cameraPose: number[] | null;
107
170
  /** The CURRENT selection, in the order both quad arrays are parallel to. One
108
171
  * list for both panes: the selection is one selection, only its projection
109
172
  * differs. */
@@ -113,6 +176,8 @@ export interface StageFeed {
113
176
  * overlay drawn from last layout's numbers is worse than no overlay. */
114
177
  quadsCamera: ScreenQuad[];
115
178
  quadsWorking: ScreenQuad[];
179
+ /** Non-rendering spline drivers remain visible as working-pane guides. */
180
+ splineGuidesWorking: Array<{ id: string; pts: readonly number[]; selected: boolean }>;
116
181
  /** Parallel to `ids`: is each selected layer locked? Written here rather than
117
182
  * looked up by the overlay because `collectFrames` is the one place that
118
183
  * already knows, and a second lookup could disagree with the `grabAt` that
@@ -150,6 +215,15 @@ export interface StageFeed {
150
215
  * raycasting, projection, `renderBins` — takes the base class already.
151
216
  */
152
217
  workingCamera: Camera | null;
218
+ /**
219
+ * Pose and return the working camera for the current committed view.
220
+ *
221
+ * The normal caller is StageTools' priority-0 frame callback. SplitRenderer
222
+ * also calls it from ClockDriver's compile barrier, before that callback has
223
+ * run, so the programs compiled for a new view are the ones its first draw
224
+ * will actually use.
225
+ */
226
+ prepareWorkingCamera: (() => Camera | null) | null;
153
227
  /** Ray-pick at a point in the pane's own CSS px. Front-most first, where
154
228
  * "front-most" is paint order in the camera pane and nearest in the working
155
229
  * one. Null until the canvas exists; empty for a pane that is not on
@@ -169,6 +243,71 @@ export interface StageFeed {
169
243
  * selects. A second walk here would be that bug.
170
244
  */
171
245
  hoverQuad: ((pane: StagePane, x: number, y: number) => ScreenQuad | null) | null;
246
+ /**
247
+ * The layer the CHROME is pointing at — a timeline row under the cursor — or
248
+ * null. Written imperatively by the bridge's `hoverLayer` sink, NEVER
249
+ * through React state: under `frameloop="never"` every stage commit is a GL
250
+ * draw, and a row-hover must cost one SVG leaf repaint and zero draws.
251
+ */
252
+ hintId: string | null;
253
+ /**
254
+ * `hintId`'s outline, projected per pane. Kept fresh two ways, and both are
255
+ * needed: the sink seeds it at write time (an idle stage runs no frame
256
+ * between the hover and the paint), and `StageTools`' frame run re-projects
257
+ * it (a camera move slides the outline with the layer).
258
+ */
259
+ hintCamera: ScreenQuad | null;
260
+ hintWorking: ScreenQuad | null;
261
+ /**
262
+ * The layers of the pieces the runtime isolated (pieceFailures.ts), and the
263
+ * one line the overlay says about them, or null with nothing failed. Written
264
+ * imperatively by StageApp's `onPieceFailures` sink, like `hintId`: a
265
+ * failure arrives from inside the apply pass, and a stage commit there would
266
+ * be a second GL draw for a line of SVG.
267
+ */
268
+ failedIds: readonly string[];
269
+ /** Each failed layer's Layers panel label, for the placeholder's line. */
270
+ failedLabels: ReadonlyMap<string, string>;
271
+ failureText: string | null;
272
+ /**
273
+ * `failedIds`' outlines, projected per pane by `StageTools`' frame run, so
274
+ * the placeholder follows its layer through a camera move. A layer the
275
+ * runtime left out entirely has no group to outline; the bar names it.
276
+ */
277
+ failedCamera: FailedQuad[];
278
+ failedWorking: FailedQuad[];
279
+ /**
280
+ * THE MASK OF A SELECTED MASK GROUP (gap 7, Paper page 25): the dashed
281
+ * outline of the matte that cuts what the author selected, per pane. A mask
282
+ * that is itself selected has its selection outline instead. Projected by
283
+ * `StageTools`' frame run from the selection and the document, so it needs
284
+ * no bridge message.
285
+ */
286
+ maskCamera: MaskQuad[];
287
+ maskWorking: MaskQuad[];
288
+ /**
289
+ * OTHER PEOPLE'S SELECTIONS (bridge v43), as the chrome pushed them, and
290
+ * their outlines projected per pane by the same frame run, so a peer's
291
+ * outline follows its layer through a camera move. Paint only.
292
+ */
293
+ peerSel: readonly ShotPeerSelection[];
294
+ peersCamera: PeerQuad[];
295
+ peersWorking: PeerQuad[];
296
+ /**
297
+ * The layer the open Studio comment is pinned to (bridge v45, S5), and its
298
+ * outline in the camera pane, projected by the same frame run that projects
299
+ * `failedIds`, so the dashed ring rides the layer. Written by StageApp; null with no
300
+ * open pin on a layer in view.
301
+ */
302
+ pinLayerId: string | null;
303
+ pinLayerCamera: ScreenQuad | null;
304
+ /**
305
+ * Project ONE layer's outline in a pane, by id. `hoverQuad`'s sibling —
306
+ * same closure family, registered by `StageTools` per frame run and
307
+ * pull-based, so it stays answerable while the stage is idle. The hover
308
+ * sink is its one caller.
309
+ */
310
+ quadForLayer: ((pane: StagePane, layerId: string) => ScreenQuad | null) | null;
172
311
  /** Marquee, in the same coordinates. */
173
312
  pickRect:
174
313
  | ((pane: StagePane, rect: { x0: number; y0: number; x1: number; y1: number }) => string[])
@@ -183,6 +322,13 @@ export interface StageFeed {
183
322
  * no ray, and answering with the other pane's would silently drag the layer
184
323
  * along a plane the author is not looking at. */
185
324
  rayAt: ((pane: StagePane, x: number, y: number) => Ray | null) | null;
325
+ /** `rayAt`'s inverse for the z = 0 design plane: a design point (centre
326
+ * origin, y down) into the pane's own CSS px, through the camera that pane
327
+ * renders. Null where `rayAt` is. */
328
+ paneAt: ((pane: StagePane, design: readonly [number, number]) => [number, number] | null) | null;
329
+ /** A WORLD point into the pane's own CSS px. No near-plane clip, so only for
330
+ * points known to be in front of the camera (a dragged dot's guide). */
331
+ worldToPane: ((pane: StagePane, world: Vector3) => [number, number] | null) | null;
186
332
  /**
187
333
  * Did a press in the WORKING pane land on the shot camera's frustum gizmo,
188
334
  * and on which part?
@@ -191,32 +337,140 @@ export interface StageFeed {
191
337
  * frustum gizmo IS the camera pane's camera, drawn as an object. It cannot
192
338
  * appear inside the view it represents.
193
339
  */
194
- frustumHit: ((x: number, y: number) => "body" | "apex" | null) | null;
340
+ frustumHit: ((x: number, y: number) => "body" | "frame" | null) | null;
341
+ /**
342
+ * Did a press in the WORKING pane land on a waypoint of the PATH MOVE under
343
+ * the playhead, and on which one?
344
+ *
345
+ * No pane argument and no shot id, for `frustumHit`'s reasons: the marks are
346
+ * drawn in the working pane alone, and the move they belong to is the one the
347
+ * camera is currently in — the same rule the frustum itself follows. Null when
348
+ * the playhead is not inside a path move, so a press falls straight through to
349
+ * the frustum and then to the orbit.
350
+ */
351
+ waypointHit: ((x: number, y: number) => number | null) | null;
352
+ /** Which waypoint the pointer is over, or null. `hoverFrustum`'s twin,
353
+ * written by the pointer lane and read in the frame loop. */
354
+ hoverWaypoint: number | null;
355
+ /**
356
+ * The selected layers' motion paths (gap 3), per pane, projected by
357
+ * `StageTools` in the frame pass. Empty when the `motionPaths` pref is off
358
+ * or the stage is playing, watching, exporting or in another gesture.
359
+ */
360
+ motionPathsCamera: readonly ScreenMotionPath[];
361
+ motionPathsWorking: readonly ScreenMotionPath[];
362
+ /** The motion path key dot under a point in a pane, or null. Registered by
363
+ * `StageTools` beside the paths it answers for. */
364
+ pathKeyHit: ((pane: StagePane, x: number, y: number) => PathKeyRef | null) | null;
365
+ /** The selected dot's Bezier handle tip under a point (schema v40), or null.
366
+ * Asked before `pathKeyHit`: a handle drawn over a dot is the one shown. */
367
+ pathHandleHit: ((pane: StagePane, x: number, y: number) => PathHandleRef | null) | null;
368
+ /** A key dot's world point and its layer's parent `matrixWorld` (copies),
369
+ * for the drag's plane and its world-to-parent delta. Null when the key
370
+ * is not drawn this frame. */
371
+ pathKeyAnchor: ((layerId: string, keyId: string) => PathKeyAnchor | null) | null;
372
+ /** The dot, or the selected dot's handle (with its `part`), the pointer is
373
+ * over. Written by the pointer lane. */
374
+ hoverPathKey: PathKeyRef | PathHandleRef | null;
375
+ /** The dot or handle being dragged, so it keeps its hover ring under the cursor. */
376
+ activePathKey: PathKeyRef | PathHandleRef | null;
377
+ /** The dot last pressed: the one whose Bezier handles show. Stage-local,
378
+ * cleared by the frame pass once that key is no longer drawn. */
379
+ selectedPathKey: PathKeyRef | null;
195
380
  /**
196
- * Did a press in the WORKING pane land on one of the selection's three drag
197
- * arms, and on which?
381
+ * Did a press in the WORKING pane land on one of the transform gizmo's
382
+ * handles, and on which?
198
383
  *
199
384
  * No pane argument, for `frustumHit`'s reason: the gizmo is drawn in the
200
385
  * working pane alone (the camera pane has resize handles, which the working
201
386
  * pane deliberately does not — see `grabAt`).
202
387
  *
203
- * The answer carries the arm's ORIGIN AND DIRECTION as a snapshot rather
388
+ * The answer carries the handle's ORIGIN AND DIRECTION as a snapshot rather
204
389
  * than a live reference: the gizmo re-centres on the selection every frame,
205
390
  * and an axis line that moved with the layer being dragged along it would
206
391
  * chase its own translation.
207
392
  */
208
393
  gizmoHit: ((x: number, y: number) => GizmoGrab | null) | null;
209
394
  /**
210
- * The arm the pointer is over, or null.
395
+ * The handle the pointer is over, or null.
211
396
  *
212
397
  * WRITTEN BY THE POINTER LANE, READ INSIDE THE FRAME LOOP, which is what
213
- * keeps a hover off React entirely: `MoveGizmo` already runs at priority 0
214
- * and re-colours a material there, so highlighting costs one uniform write
398
+ * keeps a hover off React entirely: `TransformGizmo` already runs at priority
399
+ * 0 and re-colours a material there, so highlighting costs one uniform write
215
400
  * per frame and zero renders. Blender's gizmos highlight under the cursor and
216
401
  * ours did not, which is the difference between "is this grabbable" being
217
402
  * obvious and being something the author finds out by trying.
218
403
  */
219
- hoverArm: GizmoGrab["axis"] | null;
404
+ hoverHandle: GizmoGrab["handle"] | null;
405
+ /**
406
+ * The handle a drag is currently HELD BY, or null.
407
+ *
408
+ * Its twin above, on the other side of the press. Blender dims the rest of
409
+ * the widget once a transform is running, and the reason is not decoration:
410
+ * the handles are drawn on top of the thing being moved, so a full-strength
411
+ * gizmo is three more lines crossing exactly the geometry the author is
412
+ * trying to judge. Written by the pointer lane at the press and cleared at
413
+ * the release, read by the draw pass.
414
+ */
415
+ activeHandle: GizmoGrab["handle"] | null;
416
+ /**
417
+ * Which part of the shot camera's gizmo the pointer is over, or null.
418
+ *
419
+ * `hoverArm`'s twin, written and read the same way and for the same reason:
420
+ * the camera BODY and the framed rectangle's border are the two camera grips
421
+ * there are (both pan), and neither of them said anything back until the
422
+ * author pressed.
423
+ */
424
+ hoverFrustum: "body" | "frame" | null;
425
+ /**
426
+ * Is a component driving the render camera this frame, off the rig?
427
+ *
428
+ * Written by `FrustumGizmo`, which reads the camera after every writer, and
429
+ * read by `TransformGizmo` one frame later: a driven camera has no rig to
430
+ * hang arms on, and dragging the rig would move nothing the picture shows.
431
+ */
432
+ cameraDriven: boolean;
433
+ /**
434
+ * The driven camera's WORLD: where the component's content is and how big,
435
+ * in world units, or null while the document's rig draws. Written by
436
+ * `FrustumGizmo` (the claim's extent, or the live bounds it measured), read
437
+ * by the working pane's fitter so Home frames the component's world rather
438
+ * than an empty canvas thousands of units away.
439
+ */
440
+ cameraWorld: { centre: readonly [number, number, number]; extent: number } | null;
441
+ /**
442
+ * What a camera write would do at the playhead (bridge v29), mirrored from
443
+ * the chrome for the frame loops: the gizmo dims when it is not `free`, and
444
+ * the pointer lane refuses the press with the gate's own sentence rather
445
+ * than after the drag. Null when no document is open.
446
+ */
447
+ cameraGate: CameraGate | null;
448
+ }
449
+
450
+ /** One key on one layer's Position track. */
451
+ export interface PathKeyRef {
452
+ layerId: string;
453
+ keyId: string;
454
+ }
455
+
456
+ /** One of a key's two Bezier handles (schema v40). */
457
+ export interface PathHandleRef extends PathKeyRef {
458
+ part: "in" | "out";
459
+ }
460
+
461
+ export interface PathKeyAnchor {
462
+ world: Vector3;
463
+ parent: Matrix4;
464
+ /** The key's frame, in its track's own frames. */
465
+ frame: number;
466
+ /** Where the dot is drawn, parent-local design px (+y down). */
467
+ point: Vec3;
468
+ /** The keys either side of it, for ctrl's snap. */
469
+ neighbours: Vec3[];
470
+ /** Its Bezier handles as the sampler reads them, offsets from `point`.
471
+ * Absent off the bezier arm and on the side no segment uses. */
472
+ spatialIn?: Vec3;
473
+ spatialOut?: Vec3;
220
474
  }
221
475
 
222
476
  export function createStageFeed(): StageFeed {
@@ -224,20 +478,57 @@ export function createStageFeed(): StageFeed {
224
478
  version: 0,
225
479
  sceneEpoch: 0,
226
480
  onOverlay: null,
481
+ penLive: false,
482
+ cameraPose: null,
227
483
  ids: [],
228
484
  quadsCamera: [],
229
485
  quadsWorking: [],
486
+ splineGuidesWorking: [],
230
487
  locked: [],
231
488
  union: null,
232
489
  frames: null,
233
490
  workingCamera: null,
491
+ prepareWorkingCamera: null,
234
492
  pick: null,
235
493
  hoverQuad: null,
494
+ hintId: null,
495
+ hintCamera: null,
496
+ hintWorking: null,
497
+ failedIds: [],
498
+ failedLabels: new Map(),
499
+ failureText: null,
500
+ failedCamera: [],
501
+ failedWorking: [],
502
+ maskCamera: [],
503
+ maskWorking: [],
504
+ peerSel: [],
505
+ peersCamera: [],
506
+ peersWorking: [],
507
+ pinLayerId: null,
508
+ pinLayerCamera: null,
509
+ quadForLayer: null,
236
510
  pickRect: null,
237
511
  grabAt: null,
238
512
  rayAt: null,
513
+ paneAt: null,
514
+ worldToPane: null,
239
515
  frustumHit: null,
516
+ waypointHit: null,
517
+ hoverWaypoint: null,
518
+ motionPathsCamera: [],
519
+ motionPathsWorking: [],
520
+ pathKeyHit: null,
521
+ pathHandleHit: null,
522
+ pathKeyAnchor: null,
523
+ hoverPathKey: null,
524
+ activePathKey: null,
525
+ selectedPathKey: null,
240
526
  gizmoHit: null,
241
- hoverArm: null,
527
+ hoverHandle: null,
528
+ activeHandle: null,
529
+ hoverFrustum: null,
530
+ cameraDriven: false,
531
+ cameraWorld: null,
532
+ cameraGate: null,
242
533
  };
243
534
  }
@@ -0,0 +1,176 @@
1
+ // THE FONT PREVIEW (bridge v50): the font picker's hovered or arrowed-to family
2
+ // drawn on some text layers, without a document write.
3
+ //
4
+ // Two halves. `fontPreviewDoc` derives the document the RUNTIME draws, and only
5
+ // the runtime: every other reader on the stage (picking, the overlays, the
6
+ // inline editor, the auto-width measure the store writes, stills, coverage,
7
+ // health and every export) keeps the real one. `createFontPreviewFaces` loads
8
+ // the preview's files under ONE private family per preview, and adds them to
9
+ // the page's font set only once they have loaded: a face still loading would
10
+ // hold `document.fonts.ready`, which the runtime's own font claim awaits. A
11
+ // face that fails reports nothing; the layers keep the fallback.
12
+ import { browserFontPlatform } from "@dailies-studio/shot";
13
+ import type { FontPlatform } from "@dailies-studio/shot";
14
+ import { FONT_SUBSETS_MAX, quoteFontFamily, unicodeRangeProblem } from "@dailies-studio/shot/doc";
15
+ import type { Doc3D, Layer3D, TextLayer3D } from "@dailies-studio/shot/doc";
16
+ import type { ShotFontPreview, ShotFontPreviewFace } from "../bridgeTypes.js";
17
+
18
+ /** The most files one preview loads: a whole face set (`fontAsset` plus
19
+ * `FONT_SUBSETS_MAX` subsets). */
20
+ export const MAX_FONT_PREVIEW_FACES = FONT_SUBSETS_MAX + 1;
21
+
22
+ const FALLBACKS = new Set(["sans-serif", "serif", "monospace", "cursive"]);
23
+
24
+ /** What the stage holds: the preview as sanitized, and the private family its
25
+ * faces registered under once they landed. Null before that, and for good
26
+ * when no face loads: the layers draw the display family and the fallback. */
27
+ export interface StageFontPreview extends ShotFontPreview {
28
+ face: string | null;
29
+ }
30
+
31
+ /**
32
+ * A preview the stage can draw, or null for none. A boundary like
33
+ * `sanitizeSketchGuide`: the family becomes a CSS string in `ctx.font`, so it is
34
+ * one line of at most 100 characters; a fallback that is not one of the four
35
+ * generic families is `sans-serif`; a weight range off 1..1000 or backwards is
36
+ * `[1, 1000]`; a face with no url or a range `unicodeRangeProblem` refuses is
37
+ * dropped, and at most `MAX_FONT_PREVIEW_FACES` are kept. No container or no
38
+ * layer id is no preview.
39
+ */
40
+ export function sanitizeFontPreview(raw: ShotFontPreview | null): ShotFontPreview | null {
41
+ if (raw === null || typeof raw !== "object") return null;
42
+ const { containerId, layerIds, family, fallback, style, weightRange, faces } = raw;
43
+ if (typeof containerId !== "string" || containerId.length === 0 || !Array.isArray(layerIds)) return null;
44
+ const ids = [...new Set((layerIds as unknown[]).filter((id): id is string => typeof id === "string" && id.length > 0))];
45
+ if (ids.length === 0) return null;
46
+ const weight = (n: unknown): n is number => typeof n === "number" && Number.isFinite(n) && n >= 1 && n <= 1000;
47
+ const [min, max] = Array.isArray(weightRange) ? weightRange : [];
48
+ const kept = (Array.isArray(faces) ? faces : []).flatMap((face: Partial<ShotFontPreviewFace> | null): ShotFontPreviewFace[] => {
49
+ if (face === null || typeof face !== "object" || typeof face.url !== "string" || face.url.length === 0) return [];
50
+ if (face.unicodeRange === undefined) return [{ url: face.url }];
51
+ return unicodeRangeProblem(face.unicodeRange) === null ? [{ url: face.url, unicodeRange: face.unicodeRange }] : [];
52
+ });
53
+ return {
54
+ containerId,
55
+ layerIds: ids,
56
+ family: typeof family === "string" ? family.replace(/[\s\p{Cc}]+/gu, " ").trim().slice(0, 100) : "",
57
+ fallback: typeof fallback === "string" && FALLBACKS.has(fallback) ? fallback : "sans-serif",
58
+ style: style === "italic" ? "italic" : "normal",
59
+ weightRange: weight(min) && weight(max) && min <= max ? [min, max] : [1, 1000],
60
+ faces: kept.slice(0, MAX_FONT_PREVIEW_FACES),
61
+ };
62
+ }
63
+
64
+ /**
65
+ * The document the runtime draws while `preview` shows. In its container (a
66
+ * scene, else a definition), each listed text layer loses `fontAsset` and
67
+ * `fontSubsets` and draws the preview's private family (once its faces landed),
68
+ * then the display family, then the generic fallback, in the preview's style
69
+ * (upright is the key absent) and at its own weight, on the canvas engine (a
70
+ * glyph layer bakes `fontAsset`, and has none here). Naming the private family
71
+ * only once it landed is what re-rasters exactly these layers then: the style
72
+ * is part of a text raster's key.
73
+ *
74
+ * Every box keeps its stored size and place, auto-width ones included: picking
75
+ * and the overlays read layer frames off the runtime's scene graph, so a box
76
+ * moved here would move them off the real document. Every other object keeps
77
+ * its identity, `assets` included (the runtime's texture cache is keyed on
78
+ * it), and `doc` itself comes back when no listed id is a text layer of that
79
+ * container.
80
+ */
81
+ export function fontPreviewDoc(doc: Doc3D, preview: StageFontPreview): Doc3D {
82
+ const scene = doc.scenesById[preview.containerId];
83
+ const def = scene === undefined ? doc.components?.[preview.containerId] : undefined;
84
+ const home = scene ?? def;
85
+ if (home === undefined) return doc;
86
+ const fontFamily = [preview.face, preview.family]
87
+ .filter((name): name is string => name !== null && name.length > 0)
88
+ .map(quoteFontFamily)
89
+ .concat(preview.fallback)
90
+ .join(", ");
91
+ let layersById: Record<string, Layer3D> | null = null;
92
+ for (const id of preview.layerIds) {
93
+ const layer = home.layersById[id];
94
+ if (layer?.kind !== "text") continue;
95
+ const { fontAsset: _asset, fontSubsets: _subsets, fontStyle: _slant, ...style } = layer.text.style;
96
+ const { engine: _engine, ...text } = layer.text;
97
+ const shown: TextLayer3D = {
98
+ ...layer,
99
+ text: { ...text, style: { ...style, fontFamily, ...(preview.style === "italic" ? { fontStyle: "italic" as const } : {}) } },
100
+ };
101
+ (layersById ??= { ...home.layersById })[id] = shown;
102
+ }
103
+ if (layersById === null) return doc;
104
+ return scene !== undefined
105
+ ? { ...doc, scenesById: { ...doc.scenesById, [preview.containerId]: { ...scene, layersById } } }
106
+ : { ...doc, components: { ...doc.components, [preview.containerId]: { ...def!, layersById } } };
107
+ }
108
+
109
+ type PreviewFace = ReturnType<FontPlatform["createFace"]>;
110
+
111
+ export interface FontPreviewFaces {
112
+ /**
113
+ * Load `preview`'s faces under a new private family (`dailies-preview-<n>`),
114
+ * deleting the last preview's from the page's font set, or only delete them
115
+ * for null. The same files, style and weight range again keep the faces and
116
+ * family they have. Answers the family when this preview's faces are already
117
+ * in, else null; `onLanded` hears it once they land.
118
+ */
119
+ show(preview: ShotFontPreview | null): string | null;
120
+ }
121
+
122
+ /**
123
+ * The preview's faces. Each file loads on its own (`FontFace.load`) and joins
124
+ * the font set once every file has settled; the ones that failed are left out,
125
+ * and when none loads nothing happens at all. `onLanded` never hears a preview
126
+ * that was replaced or cleared meanwhile. `platformOf` is read only when a
127
+ * preview has faces to load (the test seam; a stage without the CSS Font
128
+ * Loading API answers null and draws the fallback).
129
+ */
130
+ export function createFontPreviewFaces(
131
+ onLanded: (family: string) => void,
132
+ platformOf: () => FontPlatform | null = () => browserFontPlatform(),
133
+ ): FontPreviewFaces {
134
+ let made = 0;
135
+ let current: { key: string; family: string; fonts: FontPlatform["fonts"]; added: PreviewFace[]; landed: boolean } | null =
136
+ null;
137
+ return {
138
+ show(preview) {
139
+ const key = preview === null ? "" : JSON.stringify([preview.faces, preview.style, preview.weightRange]);
140
+ if (current !== null && current.key === key) return current.landed ? current.family : null;
141
+ if (current !== null) for (const face of current.added) current.fonts.delete(face);
142
+ current = null;
143
+ if (preview === null || preview.faces.length === 0) return null;
144
+ const platform = platformOf();
145
+ if (platform === null) return null;
146
+ made += 1;
147
+ const entry = { key, family: `dailies-preview-${made}`, fonts: platform.fonts, added: [] as PreviewFace[], landed: false };
148
+ current = entry;
149
+ const descriptors = { weight: `${preview.weightRange[0]} ${preview.weightRange[1]}`, style: preview.style };
150
+ let faces: PreviewFace[];
151
+ let loads: Promise<unknown>[];
152
+ try {
153
+ faces = preview.faces.map((face) =>
154
+ platform.createFace(
155
+ entry.family,
156
+ `url(${JSON.stringify(face.url)})`,
157
+ face.unicodeRange === undefined ? descriptors : { ...descriptors, unicodeRange: face.unicodeRange },
158
+ ),
159
+ );
160
+ loads = faces.map((face) => face.load());
161
+ } catch {
162
+ // Reports nothing, like a load that fails: the layers keep the fallback.
163
+ return null;
164
+ }
165
+ void Promise.allSettled(loads).then((settled) => {
166
+ if (current !== entry) return;
167
+ entry.added = faces.filter((_, index) => settled[index]!.status === "fulfilled");
168
+ if (entry.added.length === 0) return;
169
+ for (const face of entry.added) entry.fonts.add(face);
170
+ entry.landed = true;
171
+ onLanded(entry.family);
172
+ });
173
+ return null;
174
+ },
175
+ };
176
+ }