@volter/sdk 0.0.0-stage → 0.5.204

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 (523) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +20 -0
  3. package/README.md +38 -3
  4. package/package.json +510 -4
  5. package/src/account.ts +210 -0
  6. package/src/chrome.ts +88 -0
  7. package/src/client.ts +1646 -0
  8. package/src/commands.ts +66 -0
  9. package/src/contributions.ts +619 -0
  10. package/src/css-numeric-style.ts +97 -0
  11. package/src/document-probe.ts +282 -0
  12. package/src/editor-view.ts +225 -0
  13. package/src/extension.ts +40 -0
  14. package/src/generations.ts +178 -0
  15. package/src/host.ts +1157 -0
  16. package/src/http-transport.browser.ts +14 -0
  17. package/src/http-transport.node.ts +19 -0
  18. package/src/index.ts +131 -0
  19. package/src/kit/CapabilityCoverageSection.tsx +185 -0
  20. package/src/kit/account-client.ts +333 -0
  21. package/src/kit/action-registry.ts +317 -0
  22. package/src/kit/active-product.ts +76 -0
  23. package/src/kit/active-project.ts +155 -0
  24. package/src/kit/adapter-editor-config.ts +25 -0
  25. package/src/kit/adapter-module.ts +7 -0
  26. package/src/kit/adapter-observation.ts +49 -0
  27. package/src/kit/animation/animation-clock.ts +479 -0
  28. package/src/kit/animation/stage-transport.ts +385 -0
  29. package/src/kit/api/assets.ts +365 -0
  30. package/src/kit/api/project-open.ts +355 -0
  31. package/src/kit/api/project-source.ts +180 -0
  32. package/src/kit/api/project-state.ts +110 -0
  33. package/src/kit/api/relay.ts +270 -0
  34. package/src/kit/api/themes.ts +45 -0
  35. package/src/kit/api-asset-library-wire.ts +45 -0
  36. package/src/kit/api-base.ts +10 -0
  37. package/src/kit/api-build.ts +99 -0
  38. package/src/kit/api-git-wire.ts +56 -0
  39. package/src/kit/api-logs.ts +92 -0
  40. package/src/kit/api-project-identity.ts +74 -0
  41. package/src/kit/api-settings.ts +36 -0
  42. package/src/kit/api-worktrees.ts +205 -0
  43. package/src/kit/asset-capabilities.ts +344 -0
  44. package/src/kit/asset-compare-core.ts +171 -0
  45. package/src/kit/asset-editor-context.tsx +101 -0
  46. package/src/kit/asset-events.ts +96 -0
  47. package/src/kit/asset-inspector-actions.ts +87 -0
  48. package/src/kit/asset-selection-viewer-registry.ts +113 -0
  49. package/src/kit/asset-selection.ts +146 -0
  50. package/src/kit/asset-thumbnails.ts +25 -0
  51. package/src/kit/asset-viewers.ts +115 -0
  52. package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
  53. package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
  54. package/src/kit/asset-workflow/asset-ledger.ts +156 -0
  55. package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
  56. package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
  57. package/src/kit/asset-workflow/asset-types.ts +142 -0
  58. package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
  59. package/src/kit/asset-workflow/audio-waveform.ts +22 -0
  60. package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
  61. package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
  62. package/src/kit/asset-workflow/image-view-scale.ts +31 -0
  63. package/src/kit/asset-workflow/import-contract.ts +124 -0
  64. package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
  65. package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
  66. package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
  67. package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
  68. package/src/kit/asset-workflow/project-content.ts +288 -0
  69. package/src/kit/asset-workflow/project-source-index.ts +545 -0
  70. package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
  71. package/src/kit/authoring/active-adapter.ts +200 -0
  72. package/src/kit/authoring/active-systems.ts +422 -0
  73. package/src/kit/authoring/adapter-key.ts +18 -0
  74. package/src/kit/authoring/authoring-asset-url.ts +27 -0
  75. package/src/kit/authoring/bootstrap-state.ts +49 -0
  76. package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
  77. package/src/kit/authoring/canvas-scene-guides.ts +84 -0
  78. package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
  79. package/src/kit/authoring/consumer-actions.ts +531 -0
  80. package/src/kit/authoring/design-time-layers.ts +852 -0
  81. package/src/kit/authoring/design-time-mount-registry.ts +244 -0
  82. package/src/kit/authoring/edit-mode-authoring.ts +637 -0
  83. package/src/kit/authoring/empty-project-authoring.ts +22 -0
  84. package/src/kit/authoring/instance-source-menu.ts +135 -0
  85. package/src/kit/authoring/layered-pick.ts +185 -0
  86. package/src/kit/authoring/mounted-root-subjects.ts +146 -0
  87. package/src/kit/authoring/no-authoring-adapter.ts +59 -0
  88. package/src/kit/authoring/object3d-document-persistence.ts +122 -0
  89. package/src/kit/authoring/panel-authoring.ts +121 -0
  90. package/src/kit/authoring/project-authoring-session.ts +105 -0
  91. package/src/kit/authoring/provenance.ts +99 -0
  92. package/src/kit/authoring/react-canvas-navigation.ts +259 -0
  93. package/src/kit/authoring/react-design-canvas-style.ts +20 -0
  94. package/src/kit/authoring/react-story-board.ts +917 -0
  95. package/src/kit/authoring/selection-scope.ts +195 -0
  96. package/src/kit/authoring/shell-document-ops.ts +169 -0
  97. package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
  98. package/src/kit/authoring/story-board-presentation.ts +111 -0
  99. package/src/kit/authoring/three-root.ts +67 -0
  100. package/src/kit/authoring/viewport-tool-context.ts +73 -0
  101. package/src/kit/authoring/viewport-tool-owner.ts +38 -0
  102. package/src/kit/authoring/world-session-state.ts +101 -0
  103. package/src/kit/authoring-seam-evidence.ts +300 -0
  104. package/src/kit/availability-tick.ts +66 -0
  105. package/src/kit/bitmap-label.ts +120 -0
  106. package/src/kit/boot-routing.ts +392 -0
  107. package/src/kit/breakpoint-state.ts +43 -0
  108. package/src/kit/build-identity.ts +16 -0
  109. package/src/kit/bytes-codec.ts +62 -0
  110. package/src/kit/cancellation-reason.ts +58 -0
  111. package/src/kit/canvas-frames.ts +88 -0
  112. package/src/kit/capture-camera-pose.ts +77 -0
  113. package/src/kit/capture-size.ts +88 -0
  114. package/src/kit/chrome-registry.ts +159 -0
  115. package/src/kit/chrome-slot-registry.ts +91 -0
  116. package/src/kit/collaboration-client.ts +264 -0
  117. package/src/kit/collaboration-presence.ts +41 -0
  118. package/src/kit/command-dispatch.ts +19 -0
  119. package/src/kit/command-listener.ts +2182 -0
  120. package/src/kit/command-registry.ts +71 -0
  121. package/src/kit/component-board-registry.ts +205 -0
  122. package/src/kit/component-states-registry.ts +199 -0
  123. package/src/kit/components/AlignToolbar.tsx +204 -0
  124. package/src/kit/components/ApplicationMenus.tsx +372 -0
  125. package/src/kit/components/AssetEditorShell.tsx +216 -0
  126. package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
  127. package/src/kit/components/BoardRulers.tsx +354 -0
  128. package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
  129. package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
  130. package/src/kit/components/ChromeSlot.tsx +20 -0
  131. package/src/kit/components/CodeView.tsx +470 -0
  132. package/src/kit/components/CompactInspectorShell.tsx +39 -0
  133. package/src/kit/components/ConsolePanel.tsx +273 -0
  134. package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
  135. package/src/kit/components/InspectionProjection.tsx +932 -0
  136. package/src/kit/components/Inspector.tsx +270 -0
  137. package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
  138. package/src/kit/components/InspectorFieldsSection.tsx +290 -0
  139. package/src/kit/components/InspectorStoriesSection.tsx +92 -0
  140. package/src/kit/components/InspectorToolSection.tsx +96 -0
  141. package/src/kit/components/InspectorTransformSection.tsx +245 -0
  142. package/src/kit/components/LightExplorerPanel.tsx +433 -0
  143. package/src/kit/components/MediaProperties.tsx +145 -0
  144. package/src/kit/components/ProjectHeader.tsx +328 -0
  145. package/src/kit/components/ReactCanvasControls.tsx +358 -0
  146. package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
  147. package/src/kit/components/RootTextEditor.tsx +79 -0
  148. package/src/kit/components/SaveStatus.tsx +70 -0
  149. package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
  150. package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
  151. package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
  152. package/src/kit/components/ToolHost.tsx +380 -0
  153. package/src/kit/components/Toolbar.tsx +811 -0
  154. package/src/kit/components/TransientHint.tsx +44 -0
  155. package/src/kit/components/VersionControlSection.tsx +470 -0
  156. package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
  157. package/src/kit/components/VolterLogo.tsx +18 -0
  158. package/src/kit/components/WorktreeSwitcher.tsx +712 -0
  159. package/src/kit/components/account-documents.tsx +1162 -0
  160. package/src/kit/components/asset-documents.tsx +794 -0
  161. package/src/kit/components/asset-editor-persistence.ts +216 -0
  162. package/src/kit/components/asset-selection-section.tsx +545 -0
  163. package/src/kit/components/asset-thumbnails.tsx +307 -0
  164. package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
  165. package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  166. package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
  167. package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
  168. package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
  169. package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
  170. package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  171. package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
  172. package/src/kit/components/asset-viewers/shader-source.ts +144 -0
  173. package/src/kit/components/board-guides.ts +150 -0
  174. package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
  175. package/src/kit/components/canvas-temporary-pivot.ts +34 -0
  176. package/src/kit/components/core-utilities.tsx +94 -0
  177. package/src/kit/components/inspector-preview-section.tsx +223 -0
  178. package/src/kit/components/inspector-revert-label.ts +20 -0
  179. package/src/kit/components/inspector-selection.ts +42 -0
  180. package/src/kit/components/inspector-stories-gating.ts +171 -0
  181. package/src/kit/components/inspector-transform-subject.ts +11 -0
  182. package/src/kit/components/inspector-transform.ts +88 -0
  183. package/src/kit/components/kind-documents.tsx +544 -0
  184. package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
  185. package/src/kit/components/project-tool-documents.tsx +402 -0
  186. package/src/kit/components/scene-documents.tsx +221 -0
  187. package/src/kit/components/status-contributions.tsx +407 -0
  188. package/src/kit/components/tool-documents.tsx +302 -0
  189. package/src/kit/components/tool-schema-form.tsx +262 -0
  190. package/src/kit/components/use-after-paint.ts +41 -0
  191. package/src/kit/components/use-project-image-assets.ts +86 -0
  192. package/src/kit/components/workspace-history.ts +32 -0
  193. package/src/kit/components/world-documents.tsx +570 -0
  194. package/src/kit/components/world-overlay-gestures.ts +1939 -0
  195. package/src/kit/composite-screenshot.ts +2238 -0
  196. package/src/kit/content-entry-source-registry.ts +184 -0
  197. package/src/kit/contribution-surfaces.ts +48 -0
  198. package/src/kit/coverage/canvas-reveal.ts +192 -0
  199. package/src/kit/coverage/design-time-surfaces.ts +101 -0
  200. package/src/kit/coverage/ontology-invariants.ts +466 -0
  201. package/src/kit/coverage/session-vitals.ts +503 -0
  202. package/src/kit/crash-null-boundary.ts +36 -0
  203. package/src/kit/creation-site-edit.ts +1491 -0
  204. package/src/kit/creation-site-registry.ts +160 -0
  205. package/src/kit/delegate-harness-registry.ts +134 -0
  206. package/src/kit/document-areas.ts +70 -0
  207. package/src/kit/document-context-registry.ts +193 -0
  208. package/src/kit/document-open-registry.ts +200 -0
  209. package/src/kit/document-play-extension.ts +221 -0
  210. package/src/kit/document-preview-source.ts +20 -0
  211. package/src/kit/document-renderer-session.ts +138 -0
  212. package/src/kit/document-stage-sessions.ts +26 -0
  213. package/src/kit/document-viewports.ts +120 -0
  214. package/src/kit/editor-api.ts +46 -0
  215. package/src/kit/editor-chrome-capture.ts +136 -0
  216. package/src/kit/editor-commands.ts +176 -0
  217. package/src/kit/editor-console.ts +580 -0
  218. package/src/kit/editor-current-view.ts +56 -0
  219. package/src/kit/editor-document-probe.ts +1168 -0
  220. package/src/kit/editor-git-client.ts +115 -0
  221. package/src/kit/editor-hotkeys.ts +728 -0
  222. package/src/kit/editor-lease-view.ts +39 -0
  223. package/src/kit/editor-lease.ts +415 -0
  224. package/src/kit/editor-mode.ts +19 -0
  225. package/src/kit/editor-notifications.ts +140 -0
  226. package/src/kit/editor-presence.ts +563 -0
  227. package/src/kit/editor-presentation-activity.ts +58 -0
  228. package/src/kit/editor-presentation-notice.ts +42 -0
  229. package/src/kit/editor-runtime.tsx +147 -0
  230. package/src/kit/editor-server-response.ts +86 -0
  231. package/src/kit/editor-session-attribution.ts +85 -0
  232. package/src/kit/editor-session-mode.ts +54 -0
  233. package/src/kit/editor-state-facets.ts +74 -0
  234. package/src/kit/editor-view-presentation.ts +777 -0
  235. package/src/kit/environment-images.ts +58 -0
  236. package/src/kit/eyedropper-session.ts +60 -0
  237. package/src/kit/files/file-provider.ts +62 -0
  238. package/src/kit/files/project-files.ts +270 -0
  239. package/src/kit/finders/index.ts +137 -0
  240. package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
  241. package/src/kit/frame/frame-parts.ts +30 -0
  242. package/src/kit/framed-document-capture.ts +34 -0
  243. package/src/kit/game-globals-prelude.ts +143 -0
  244. package/src/kit/game-surface-defaults.ts +33 -0
  245. package/src/kit/gameplay-dom-recording.ts +318 -0
  246. package/src/kit/gameplay-export-state.ts +14 -0
  247. package/src/kit/gameplay-replay.ts +417 -0
  248. package/src/kit/gameplay-session-time.ts +9 -0
  249. package/src/kit/gameplay-sessions.ts +204 -0
  250. package/src/kit/hierarchy-component-marks.ts +298 -0
  251. package/src/kit/hierarchy-internals.ts +197 -0
  252. package/src/kit/hierarchy-kind-icon.ts +217 -0
  253. package/src/kit/hierarchy-menu-registry.ts +67 -0
  254. package/src/kit/hierarchy-node-rows.ts +307 -0
  255. package/src/kit/hierarchy-panel-view.ts +280 -0
  256. package/src/kit/hierarchy-projection.ts +76 -0
  257. package/src/kit/hierarchy-row-media.ts +45 -0
  258. package/src/kit/hierarchy-row-model.ts +308 -0
  259. package/src/kit/hierarchy-rows.ts +11 -0
  260. package/src/kit/hierarchy-walk.ts +86 -0
  261. package/src/kit/history/editor-session.ts +25 -0
  262. package/src/kit/history/history-commands.ts +147 -0
  263. package/src/kit/history/history-delegate.ts +187 -0
  264. package/src/kit/history/history-limit-notices.ts +43 -0
  265. package/src/kit/history/history-service.ts +1189 -0
  266. package/src/kit/history/persistence-coordinator.ts +35 -0
  267. package/src/kit/history/project-file-history.ts +386 -0
  268. package/src/kit/history/project-root-history-backends.ts +139 -0
  269. package/src/kit/history/resource-registry.ts +209 -0
  270. package/src/kit/history/snapshot-store.ts +103 -0
  271. package/src/kit/history/source-history-backend.ts +546 -0
  272. package/src/kit/history-types.ts +124 -0
  273. package/src/kit/hmr-registration-group.ts +67 -0
  274. package/src/kit/hmr-stable-react-context.ts +23 -0
  275. package/src/kit/hotkeys.ts +190 -0
  276. package/src/kit/inference-diagnostics.ts +69 -0
  277. package/src/kit/initial-project.ts +80 -0
  278. package/src/kit/inspection/active-subject.ts +571 -0
  279. package/src/kit/inspection/active-surface.ts +142 -0
  280. package/src/kit/inspection/compose-subject.ts +1055 -0
  281. package/src/kit/inspection/compose.ts +7 -0
  282. package/src/kit/inspection/display.ts +171 -0
  283. package/src/kit/inspection/document-subject.ts +109 -0
  284. package/src/kit/inspection/game-subject.ts +85 -0
  285. package/src/kit/inspection/null-subject.ts +119 -0
  286. package/src/kit/inspection/serialize.ts +357 -0
  287. package/src/kit/inspection/use-active-inspection.ts +180 -0
  288. package/src/kit/inspection-model.ts +542 -0
  289. package/src/kit/inspection-node-media.ts +58 -0
  290. package/src/kit/inspector-presentation.ts +203 -0
  291. package/src/kit/inspector-property-grouping.ts +64 -0
  292. package/src/kit/inspector-section-registry.ts +221 -0
  293. package/src/kit/instance-source-actions.ts +163 -0
  294. package/src/kit/js-heap.ts +71 -0
  295. package/src/kit/key-actions.ts +91 -0
  296. package/src/kit/keymap-presets.ts +428 -0
  297. package/src/kit/layout-policy.ts +31 -0
  298. package/src/kit/light-explorer-model.ts +134 -0
  299. package/src/kit/live-canvas-frame.ts +55 -0
  300. package/src/kit/live-document.ts +296 -0
  301. package/src/kit/live-gesture-lock.ts +50 -0
  302. package/src/kit/live-seam-evidence.ts +11 -0
  303. package/src/kit/live-session-registry.ts +220 -0
  304. package/src/kit/live-transition.ts +391 -0
  305. package/src/kit/manifest-project.ts +107 -0
  306. package/src/kit/module-fetch-diagnosis.ts +192 -0
  307. package/src/kit/mount-failure-report.ts +154 -0
  308. package/src/kit/native-selection-style.ts +497 -0
  309. package/src/kit/object3d-document-write-policy.ts +137 -0
  310. package/src/kit/packaged-runtime.ts +108 -0
  311. package/src/kit/palettes/maya.palette.json +57 -0
  312. package/src/kit/palettes/substance.palette.json +57 -0
  313. package/src/kit/performance-profiler.ts +367 -0
  314. package/src/kit/performance-sources.ts +69 -0
  315. package/src/kit/photograph-notice.ts +141 -0
  316. package/src/kit/play-boot-phase.ts +166 -0
  317. package/src/kit/play-camera-flight.ts +35 -0
  318. package/src/kit/png-encode.worker.ts +26 -0
  319. package/src/kit/presentation-surface.ts +248 -0
  320. package/src/kit/product-command.ts +90 -0
  321. package/src/kit/project-adapter.ts +1140 -0
  322. package/src/kit/project-asset-refresh.ts +23 -0
  323. package/src/kit/project-asset-roots.ts +68 -0
  324. package/src/kit/project-local-state.ts +151 -0
  325. package/src/kit/project-manager.ts +243 -0
  326. package/src/kit/project-module-changes.ts +201 -0
  327. package/src/kit/project-module-split.ts +270 -0
  328. package/src/kit/project-play-layers.ts +25 -0
  329. package/src/kit/project-provenance.ts +115 -0
  330. package/src/kit/project-ready.ts +42 -0
  331. package/src/kit/project-shape.ts +68 -0
  332. package/src/kit/project-tools.ts +107 -0
  333. package/src/kit/projection-types.ts +44 -0
  334. package/src/kit/readiness.ts +113 -0
  335. package/src/kit/renderer-resource-counts.ts +27 -0
  336. package/src/kit/reported-play-state.ts +90 -0
  337. package/src/kit/resolve-contributed-command.ts +14 -0
  338. package/src/kit/resolve-relative-specifier.ts +33 -0
  339. package/src/kit/retained-document-states.ts +91 -0
  340. package/src/kit/scene-document-plan.ts +320 -0
  341. package/src/kit/scene-live-open.ts +210 -0
  342. package/src/kit/scoped-game-css.ts +152 -0
  343. package/src/kit/served-url.ts +5 -0
  344. package/src/kit/session-close.ts +17 -0
  345. package/src/kit/session-tombstone.ts +127 -0
  346. package/src/kit/settings/settings-provider.ts +82 -0
  347. package/src/kit/settings-store.ts +348 -0
  348. package/src/kit/shell-document-state.ts +27 -0
  349. package/src/kit/shell-store-door.ts +45 -0
  350. package/src/kit/shell-store.ts +722 -0
  351. package/src/kit/source-conflict.ts +122 -0
  352. package/src/kit/stage-context.ts +377 -0
  353. package/src/kit/stage-invalidation.ts +25 -0
  354. package/src/kit/stage-store-registry.ts +69 -0
  355. package/src/kit/startup-failure.ts +80 -0
  356. package/src/kit/state-report-deferral.ts +73 -0
  357. package/src/kit/storage/host-files-storage.ts +97 -0
  358. package/src/kit/storage/http-storage.ts +174 -0
  359. package/src/kit/storage/index.ts +75 -0
  360. package/src/kit/storage/mem-storage.ts +158 -0
  361. package/src/kit/storage/path-lock.ts +44 -0
  362. package/src/kit/storage/paths.ts +26 -0
  363. package/src/kit/storage-types.ts +127 -0
  364. package/src/kit/stories/StoryPreviewMount.tsx +306 -0
  365. package/src/kit/stories/compose-project-stories.ts +255 -0
  366. package/src/kit/stories/prefabs-finder.ts +54 -0
  367. package/src/kit/stories/prefabs-from-stories.ts +182 -0
  368. package/src/kit/stories/project-story-regions.ts +24 -0
  369. package/src/kit/stories/story-capture.ts +579 -0
  370. package/src/kit/stories/story-declared-medium.ts +126 -0
  371. package/src/kit/stories/story-discovery.ts +176 -0
  372. package/src/kit/stories/story-dom-runtime.ts +78 -0
  373. package/src/kit/stories/story-grouping.ts +111 -0
  374. package/src/kit/stories/story-mount-turn.ts +27 -0
  375. package/src/kit/stories/story-presentation.ts +215 -0
  376. package/src/kit/stories/story-preview-component.ts +7 -0
  377. package/src/kit/stories/story-registry.ts +530 -0
  378. package/src/kit/stories-scope.ts +35 -0
  379. package/src/kit/story-document-openers.ts +36 -0
  380. package/src/kit/story-thumbnails.ts +47 -0
  381. package/src/kit/surface-keyboard.ts +101 -0
  382. package/src/kit/surface-state.ts +135 -0
  383. package/src/kit/system-seam-evidence.ts +72 -0
  384. package/src/kit/tab-census.ts +202 -0
  385. package/src/kit/tab-lifecycle-client.ts +227 -0
  386. package/src/kit/theme-library.ts +897 -0
  387. package/src/kit/theme-preference.ts +429 -0
  388. package/src/kit/three-viewport-presentation.ts +23 -0
  389. package/src/kit/tool-contribution-play.ts +74 -0
  390. package/src/kit/tool-loader.ts +1918 -0
  391. package/src/kit/transform-mode-request.ts +66 -0
  392. package/src/kit/transient-hint.ts +78 -0
  393. package/src/kit/transport-strip.tsx +174 -0
  394. package/src/kit/ui-source/adapter-region-includes.ts +238 -0
  395. package/src/kit/ui-source/file-region-resolver.ts +302 -0
  396. package/src/kit/ui-source/inspect.ts +775 -0
  397. package/src/kit/ui-source/source-write-backend.ts +605 -0
  398. package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
  399. package/src/kit/user-local-state.ts +105 -0
  400. package/src/kit/viewport-activation-timings.ts +840 -0
  401. package/src/kit/viewport-editor-controls.ts +22 -0
  402. package/src/kit/viewport-presentation.ts +668 -0
  403. package/src/kit/viewport-surface-status.tsx +55 -0
  404. package/src/kit/wait-until.ts +37 -0
  405. package/src/kit/worker-call-metrics.ts +166 -0
  406. package/src/kit/workspace-areas.ts +191 -0
  407. package/src/kit/workspace-aux-commands.ts +11 -0
  408. package/src/kit/workspace-available-documents.ts +142 -0
  409. package/src/kit/workspace-core-utilities.ts +31 -0
  410. package/src/kit/workspace-document-ids.ts +59 -0
  411. package/src/kit/workspace-document-registry.ts +624 -0
  412. package/src/kit/workspace-document-restore.ts +146 -0
  413. package/src/kit/workspace-host-commands.ts +141 -0
  414. package/src/kit/workspace-persistence-gate.ts +40 -0
  415. package/src/kit/workspace-play-utilities.ts +44 -0
  416. package/src/kit/workspace-presets.ts +446 -0
  417. package/src/kit/workspace-regions.ts +276 -0
  418. package/src/kit/workspace-static-panels.ts +73 -0
  419. package/src/kit/workspace-status-registry.ts +121 -0
  420. package/src/kit/workspace-storage.ts +35 -0
  421. package/src/kit/workspace-style.ts +226 -0
  422. package/src/kit/workspace-utility-commands.ts +74 -0
  423. package/src/kit/workspace-utility-registry.ts +263 -0
  424. package/src/kit/world-adoption-event.ts +23 -0
  425. package/src/kit/world-adoption.ts +115 -0
  426. package/src/kit/world-canvas-viewport-state.ts +35 -0
  427. package/src/kit/world-document-routing.ts +104 -0
  428. package/src/kit/world-pan-state.ts +198 -0
  429. package/src/kit/write-pipe.ts +173 -0
  430. package/src/layout-arrangements.ts +5 -0
  431. package/src/layouts.tsx +108 -0
  432. package/src/looks.ts +16 -0
  433. package/src/project/output-roots.ts +73 -0
  434. package/src/project/tab-census.ts +155 -0
  435. package/src/project-tool-catalog.ts +104 -0
  436. package/src/selection.tsx +107 -0
  437. package/src/services.ts +18 -0
  438. package/src/session/build-report.ts +22 -0
  439. package/src/session/collaboration-types.ts +262 -0
  440. package/src/session/command-table.ts +327 -0
  441. package/src/session/discovery.ts +100 -0
  442. package/src/session/editor-brand.ts +48 -0
  443. package/src/session/editor-compatibility.ts +329 -0
  444. package/src/session/editor-control-lifecycle.ts +68 -0
  445. package/src/session/editor-control-protocol.ts +5 -0
  446. package/src/session/entrypoint-selection-readers.ts +66 -0
  447. package/src/session/entrypoint-selection-source.ts +120 -0
  448. package/src/session/game-css-scope.ts +30 -0
  449. package/src/session/hosted-attachment.ts +225 -0
  450. package/src/session/limited-view.ts +82 -0
  451. package/src/session/product-create.ts +24 -0
  452. package/src/session/product-locator.ts +478 -0
  453. package/src/session/project-module-url.ts +242 -0
  454. package/src/session/project-serving.ts +164 -0
  455. package/src/session/project-upgrade.ts +669 -0
  456. package/src/session/registry-format.ts +210 -0
  457. package/src/session/relative-path-guard.ts +56 -0
  458. package/src/session/scoped-game-css.ts +461 -0
  459. package/src/session/source-glob.ts +15 -0
  460. package/src/session/tool-contribution-convention.ts +123 -0
  461. package/src/session/workbench-locator.ts +712 -0
  462. package/src/session.ts +41 -0
  463. package/src/share.ts +160 -0
  464. package/src/source-analysis.ts +28 -0
  465. package/src/source-authoring.ts +439 -0
  466. package/src/tools/errors.ts +91 -0
  467. package/src/tools/provider-execution.ts +70 -0
  468. package/src/tools/registry.ts +341 -0
  469. package/src/tools/types.ts +159 -0
  470. package/src/transport.ts +100 -0
  471. package/src/types.ts +1693 -0
  472. package/src/views.ts +164 -0
  473. package/src/widgets/design-system.ts +93 -0
  474. package/src/widgets/editor-appearance.ts +151 -0
  475. package/src/widgets/editor-material.ts +83 -0
  476. package/src/widgets/icon-set-registry.ts +105 -0
  477. package/src/widgets/index.ts +71 -0
  478. package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
  479. package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
  480. package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
  481. package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
  482. package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
  483. package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
  484. package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
  485. package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
  486. package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
  487. package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
  488. package/src/widgets/inspector-widgets/color-utils.ts +201 -0
  489. package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
  490. package/src/widgets/inspector-widgets/index.ts +25 -0
  491. package/src/widgets/inspector-widgets/shared.tsx +140 -0
  492. package/src/widgets/interactive-edit-scope.ts +33 -0
  493. package/src/widgets/patterns/Dialog.tsx +140 -0
  494. package/src/widgets/patterns/Fields.tsx +44 -0
  495. package/src/widgets/patterns/List.tsx +25 -0
  496. package/src/widgets/patterns/StateSurface.tsx +40 -0
  497. package/src/widgets/patterns/Surfaces.tsx +122 -0
  498. package/src/widgets/patterns/Tabs.tsx +80 -0
  499. package/src/widgets/patterns/Toolbar.tsx +72 -0
  500. package/src/widgets/patterns/Tree.tsx +72 -0
  501. package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
  502. package/src/widgets/primitives/Button.tsx +62 -0
  503. package/src/widgets/primitives/ColorInput.tsx +78 -0
  504. package/src/widgets/primitives/DraftTextInput.tsx +63 -0
  505. package/src/widgets/primitives/EditorIcon.tsx +157 -0
  506. package/src/widgets/primitives/FormControls.tsx +88 -0
  507. package/src/widgets/primitives/HoverPreview.tsx +96 -0
  508. package/src/widgets/primitives/JsonInput.tsx +113 -0
  509. package/src/widgets/primitives/Layout.tsx +100 -0
  510. package/src/widgets/primitives/Menu.tsx +161 -0
  511. package/src/widgets/primitives/NumberInput.tsx +169 -0
  512. package/src/widgets/primitives/Panel.tsx +80 -0
  513. package/src/widgets/primitives/SectionHeader.tsx +77 -0
  514. package/src/widgets/primitives/Text.tsx +54 -0
  515. package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
  516. package/src/widgets/primitives/Tooltip.tsx +204 -0
  517. package/src/widgets/primitives/Vec3Input.tsx +70 -0
  518. package/src/widgets/primitives/banner-tones.ts +32 -0
  519. package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
  520. package/src/widgets/primitives/editor-icons.ts +254 -0
  521. package/src/widgets/primitives/panel-header-styles.ts +42 -0
  522. package/src/widgets/theme.ts +2841 -0
  523. package/src/widgets/z-index.ts +25 -0
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Workspace history bridge (W3) — the session `HistoryService` handed to
3
+ * workspace-document content modules (`build-documents.tsx`) WITHOUT them
4
+ * importing `EditorContext`.
5
+ *
6
+ * Why not `useOptionalHistoryService()`: `EditorContext`'s import graph
7
+ * pulls the whole editor boot (initial-scene → engine renderer stack), which
8
+ * document-content modules must not drag into their own graph, and the
9
+ * headless jsdom tests that mount document content rely on the light graph.
10
+ * `DefaultEditorLayout` (which already lives on the heavy side) sets the
11
+ * live service here; content reads it at commit time. Null (e.g. in tests,
12
+ * or before the layout mounts) degrades to the raw POST/save write paths —
13
+ * the same degrade the old prop-less mounts had.
14
+ */
15
+
16
+ import type { HistoryService } from '@volter/sdk/kit/history/history-service';
17
+
18
+ let _history: HistoryService | null = null;
19
+
20
+ /** Set (or clear) the live session history service. Returns a cleanup that
21
+ * clears it only if it is still this service. */
22
+ export function setWorkspaceHistoryService(history: HistoryService | null): () => void {
23
+ _history = history;
24
+ return () => {
25
+ if (_history === history) _history = null;
26
+ };
27
+ }
28
+
29
+ /** The live session history service, or `null`. */
30
+ export function workspaceHistoryService(): HistoryService | null {
31
+ return _history;
32
+ }
@@ -0,0 +1,570 @@
1
+ import {
2
+ registerAvailableWorkspaceDocument,
3
+ unregisterAvailableWorkspaceDocument,
4
+ } from '@volter/sdk/kit/workspace-available-documents';
5
+ /**
6
+ * Edit-time center documents for a project, beside the native Three.js scene
7
+ * document. Runtime composition belongs to the Game document (which exists
8
+ * only while a runtime does); authoring pins the project-level component
9
+ * boards — one per registered medium, each installed and closed here on its
10
+ * own package's verdict (`component-board-registry.ts`). This module names no
11
+ * board and no medium.
12
+ *
13
+ * THE SCENE VIEWPORT IS FOR THE SCENE (owner, 2026-08-10). Every edit-time
14
+ * subject presents through a document of its own; nothing composites over the
15
+ * viewport while editing.
16
+ */
17
+
18
+ import type { AuthoringAdapter } from '@volter/project/adapter';
19
+ import { useEffect, useRef, useState, useSyncExternalStore } from 'react';
20
+ import { getActiveAuthoring } from '@volter/sdk/kit/authoring/active-adapter';
21
+ import { authoringAdapterKey } from '../authoring/adapter-key';
22
+ import type { CompositeAuthoringAdapter } from '@volter/sdk/kit/authoring/composite-authoring-adapter';
23
+ import {
24
+ type DesignTimeRootDescriptor,
25
+ designTimeRootDescriptors,
26
+ mountDesignTimeLayers,
27
+ } from '@volter/sdk/kit/authoring/design-time-layers';
28
+ import { INVALID_MANIFEST_SURFACE } from '@volter/sdk/kit/authoring/edit-mode-authoring';
29
+ import {
30
+ getMountFailureReports,
31
+ subscribeToMountFailures,
32
+ } from '@volter/sdk/kit/mount-failure-report';
33
+ import {
34
+ installCanvasSceneNavigation,
35
+ installReactCanvasNavigation,
36
+ } from '@volter/sdk/kit/authoring/react-canvas-navigation';
37
+ import {
38
+ REACT_DESIGN_CANVAS_COLOR,
39
+ REACT_DESIGN_CANVAS_DOT,
40
+ } from '@volter/sdk/kit/authoring/react-design-canvas-style';
41
+ import { resolveViewportToolContext } from '@volter/sdk/kit/authoring/viewport-tool-context';
42
+ import {
43
+ createRootViewController,
44
+ getRootPan,
45
+ sharedRootViewController,
46
+ subscribeRootPan,
47
+ } from '@volter/sdk/kit/world-pan-state';
48
+ import {
49
+ type ComponentBoard,
50
+ componentBoardForDocument,
51
+ componentBoardForMedium,
52
+ componentBoards,
53
+ subscribeComponentBoards,
54
+ } from '@volter/sdk/kit/component-board-registry';
55
+ import { BoundaryAuthoringAdapter } from '@volter/sdk/kit/authoring/boundary-authoring-adapter';
56
+ import { setActiveScope } from '@volter/sdk/kit/hotkeys';
57
+ import { liveDocumentHeld } from '@volter/sdk/kit/live-document';
58
+ import { readinessFacet, subscribeRootReadiness } from '@volter/sdk/kit/readiness';
59
+ import { explainSurface } from '@volter/sdk/kit/surface-state';
60
+ import { recordViewportFirstFrame } from '@volter/sdk/kit/viewport-activation-timings';
61
+ import {
62
+ CANVAS_SCENE_DOCUMENT_ID,
63
+ GAME_DOCUMENT_ID,
64
+ SCENE_DOCUMENT_ID,
65
+ } from '@volter/sdk/kit/workspace-document-ids';
66
+ import {
67
+ activateWorkspaceDocument,
68
+ activeWorkspaceDocumentId,
69
+ closeWorkspaceDocument,
70
+ openWorkspaceDocuments,
71
+ registerWorkspaceDocumentSelection,
72
+ type WorkspaceDocumentContentProps,
73
+ } from '@volter/sdk/kit/workspace-document-registry';
74
+ import {
75
+ registerRootDocumentGap,
76
+ registerRootDocumentRoute,
77
+ registerWorkspaceDocumentGap,
78
+ } from '../world-document-routing';
79
+ import { BoardRulers } from './BoardRulers';
80
+ import {
81
+ CANVAS_SCENE_BACKGROUND,
82
+ CanvasSceneBackdrop,
83
+ CanvasSceneControls,
84
+ } from '@volter/sdk/kit/components/CanvasSceneViewport';
85
+ import { ReactCanvasControls } from './ReactCanvasControls';
86
+ import { RootSelectionOverlay } from '@volter/sdk/kit/components/RootSelectionOverlay';
87
+ import { SurfaceStateOverlay } from '@volter/sdk/kit/components/SurfaceStateOverlay';
88
+ import type { ShellStore } from '@volter/sdk/kit/shell-store';
89
+
90
+ /** The canvas root's world document reads `Scene`, exactly like a three
91
+ * project's — THE SCENE VIEWPORT IS FOR THE SCENE, and a 2D world is a scene
92
+ * (owner, 2026-08-15: "why don't we have a 'scene'? it's a 2d scene of
93
+ * course"). A project has one medium's scene or the other, never both. */
94
+ const CANVAS_SCENE_TITLE = 'Scene';
95
+
96
+ export function RootDocumentContent({
97
+ active,
98
+ composite,
99
+ descriptor,
100
+ documentId,
101
+ store,
102
+ }: WorkspaceDocumentContentProps & {
103
+ composite: CompositeAuthoringAdapter;
104
+ descriptor: DesignTimeRootDescriptor;
105
+ store: ShellStore;
106
+ }) {
107
+ const containerRef = useRef<HTMLDivElement>(null);
108
+ const disposeMountRef = useRef<(() => void) | null>(null);
109
+ const [canvasSceneView] = useState(createRootViewController);
110
+ const isCanvasScene = descriptor.kind === 'canvas';
111
+ const documentView = isCanvasScene ? canvasSceneView : sharedRootViewController;
112
+ useSyncExternalStore(store.subscribe, store.getSnapshot);
113
+ const rootReadiness = useSyncExternalStore(subscribeRootReadiness, readinessFacet);
114
+ const mountFailures = useSyncExternalStore(subscribeToMountFailures, getMountFailureReports);
115
+ // The layer's own adapter, for a board that has no composite child to carry
116
+ // it — either a rootless board, or Dev (whose runtime root is deliberately
117
+ // not an authoring child). A board's presence is its package's verdict, not
118
+ // a fact about roots. The composite child stays the authority whenever
119
+ // there IS one.
120
+ const [mountedAdapter, setMountedAdapter] = useState<AuthoringAdapter | null>(null);
121
+ const documentAdapter =
122
+ composite.childAdapters().find((child) => child.worldId === descriptor.worldId)?.adapter ??
123
+ mountedAdapter ??
124
+ undefined;
125
+ const isBabylonScene = isCanvasScene && documentAdapter?.provenance?.label === 'babylon';
126
+ const nativeRoots = documentAdapter?.hierarchy.roots() ?? [];
127
+ const emptyRootIds = new Set(
128
+ documentAdapter?.rects?.emptyContainers?.().map((entry) => entry.id) ?? [],
129
+ );
130
+ const hasRenderableContent = nativeRoots.some((root) => !emptyRootIds.has(root.id));
131
+ const rootExplanation = explainSurface({
132
+ surface: isCanvasScene ? 'Scene' : descriptor.kind === 'dom' ? 'UI' : 'World',
133
+ rootIds: [descriptor.worldId],
134
+ // While the game PLAYS, this document's design mount is deliberately
135
+ // suspended — the wait is not progress and says so (surface-state.ts).
136
+ playSuspended:
137
+ store.playState !== 'stopped' &&
138
+ (!documentAdapter || documentAdapter.provenance?.source === 'boundary'),
139
+ phase:
140
+ !documentAdapter || documentAdapter.provenance?.source === 'boundary' ? 'loading' : 'ready',
141
+ content:
142
+ !documentAdapter || documentAdapter.provenance?.source === 'boundary'
143
+ ? 'unknown'
144
+ : hasRenderableContent
145
+ ? 'present'
146
+ : 'empty',
147
+ readiness: rootReadiness,
148
+ failures: mountFailures,
149
+ disclosure:
150
+ documentAdapter instanceof BoundaryAuthoringAdapter ? documentAdapter.disclosure : null,
151
+ });
152
+
153
+ // A world document owns the shared Hierarchy/Inspector context while it is
154
+ // the visible center subject. Publish only this document's child: the Game
155
+ // document is the composition-wide surface, while an authored root document
156
+ // must not leak sibling roots into its panels. The node id is read live from
157
+ // the same selection provider the canvas updates.
158
+ useEffect(() => {
159
+ if (!documentAdapter) return;
160
+ return registerWorkspaceDocumentSelection(documentId, () => ({
161
+ adapter: documentAdapter,
162
+ nodeId: [...store.selectedEntityIds].find((id) => documentAdapter.hierarchy.node(id)) ?? null,
163
+ }));
164
+ }, [composite, documentAdapter, documentId, store]);
165
+
166
+ useEffect(() => {
167
+ const container = containerRef.current;
168
+ if (!container) return;
169
+ if (isBabylonScene) return;
170
+ return isCanvasScene
171
+ ? installCanvasSceneNavigation(container, documentView)
172
+ : installReactCanvasNavigation(container, documentView);
173
+ }, [documentView, isBabylonScene, isCanvasScene]);
174
+
175
+ // An open document stays mounted. Defer the relatively expensive Pixi/React
176
+ // mount until the world is first visited, then retain it across tab changes
177
+ // so hierarchy identity, story selection, and source editing remain stable.
178
+ useEffect(() => {
179
+ if (!active) return;
180
+ const alreadyMounted = Boolean(disposeMountRef.current);
181
+ if (!alreadyMounted && containerRef.current) {
182
+ disposeMountRef.current = mountDesignTimeLayers(
183
+ containerRef.current,
184
+ composite,
185
+ store,
186
+ [descriptor],
187
+ (_worldId, adapter) => setMountedAdapter(adapter),
188
+ isCanvasScene ? { canvasSceneView } : undefined,
189
+ documentId,
190
+ );
191
+ return;
192
+ }
193
+ // Switch-back of a retained board: the next two frames are the first
194
+ // painted frames after the tab is in front. No remount, no WebGL.
195
+ let frames = 0;
196
+ let raf = 0;
197
+ const paint = (): void => {
198
+ frames += 1;
199
+ if (frames < 2) {
200
+ raf = requestAnimationFrame(paint);
201
+ return;
202
+ }
203
+ recordViewportFirstFrame(documentId);
204
+ };
205
+ raf = requestAnimationFrame(paint);
206
+ return () => cancelAnimationFrame(raf);
207
+ }, [active, canvasSceneView, composite, descriptor, documentId, isCanvasScene, store]);
208
+
209
+ // A MOUNTED LAYER'S STALENESS IS ITS MEDIUM'S STATEMENT, NOT THIS
210
+ // COMPONENT'S. This effect used to remount the whole stack whenever the
211
+ // project's story MEMBERSHIP changed (a story saved from the editor's own
212
+ // header, a hand-edited `.stories.tsx`), so a new frame appeared without an
213
+ // F5 — blind-walk beat 9. It was a rule about one medium spelled in a
214
+ // component that mounts two: a canvas world's `<Application>` was torn down
215
+ // and rebuilt every time an unrelated dom story was saved. It lives with
216
+ // the dom mount now, as `DesignTimeMount.reprojectWhen`
217
+ // (`@volter/editor-game`'s `reprojectWhenStoriesRepublish`), which the stack binds per
218
+ // medium and applies only to that medium's candidates
219
+ // (`design-time-layers.ts:717-742`) — and which re-projects rather than
220
+ // remounting, so the board no longer blinks through empty on the way.
221
+
222
+ useEffect(
223
+ () => () => {
224
+ disposeMountRef.current?.();
225
+ disposeMountRef.current = null;
226
+ },
227
+ [],
228
+ );
229
+
230
+ const selectedContext = resolveViewportToolContext(
231
+ getActiveAuthoring(store),
232
+ store.selectedEntityIds,
233
+ );
234
+ const context =
235
+ selectedContext?.worldId === descriptor.worldId
236
+ ? selectedContext
237
+ : documentAdapter?.rects
238
+ ? { worldId: descriptor.worldId, kind: 'dom' as const, adapter: documentAdapter }
239
+ : null;
240
+ return (
241
+ <div
242
+ ref={containerRef}
243
+ data-testid={`world-document:${descriptor.worldId}`}
244
+ data-volter-backdrop-color={
245
+ active
246
+ ? isBabylonScene
247
+ ? '#111827'
248
+ : isCanvasScene
249
+ ? CANVAS_SCENE_BACKGROUND
250
+ : REACT_DESIGN_CANVAS_COLOR
251
+ : undefined
252
+ }
253
+ data-volter-backdrop-policy={active ? 'dark-frost' : undefined}
254
+ onPointerDown={() => setActiveScope('viewport')}
255
+ style={{
256
+ // DOM component documents are Storybook/Figma-style boards. A Canvas
257
+ // root is instead a native 2D Scene with its own editor camera; both
258
+ // remain independent center documents rather than runtime layers.
259
+ position: 'absolute',
260
+ inset: 0,
261
+ overflow: 'hidden',
262
+ pointerEvents: 'auto',
263
+ backgroundColor: isBabylonScene
264
+ ? '#111827'
265
+ : isCanvasScene
266
+ ? CANVAS_SCENE_BACKGROUND
267
+ : REACT_DESIGN_CANVAS_COLOR,
268
+ touchAction: 'none',
269
+ }}
270
+ >
271
+ {isBabylonScene ? null : isCanvasScene ? (
272
+ <CanvasSceneBackdrop view={canvasSceneView} documentId={documentId} />
273
+ ) : (
274
+ <ReactDesignCanvasBackdrop />
275
+ )}
276
+ <RootSelectionOverlay
277
+ key={`selection:${authoringAdapterKey(documentAdapter)}`}
278
+ {...(documentAdapter ? { adapter: documentAdapter } : {})}
279
+ {...(isCanvasScene && !isBabylonScene
280
+ ? { view: canvasSceneView, transformModeAware: true, presentationId: documentId }
281
+ : {})}
282
+ />
283
+ <SurfaceStateOverlay
284
+ explanation={rootExplanation}
285
+ testId={`world-surface-status:${descriptor.worldId}`}
286
+ style={{ zIndex: 20 }}
287
+ />
288
+ {isBabylonScene ? null : isCanvasScene ? (
289
+ <CanvasSceneControls
290
+ key={`controls:${authoringAdapterKey(documentAdapter)}`}
291
+ active={active}
292
+ {...(documentAdapter ? { adapter: documentAdapter } : {})}
293
+ containerRef={containerRef}
294
+ view={canvasSceneView}
295
+ documentId={documentId}
296
+ />
297
+ ) : (
298
+ <>
299
+ <BoardRulers docId={descriptor.worldId} containerRef={containerRef} />
300
+ <ReactCanvasControls containerRef={containerRef} context={context} />
301
+ </>
302
+ )}
303
+ </div>
304
+ );
305
+ }
306
+
307
+ /** Infinite editor canvas behind React story frames. The dot origin follows
308
+ * the same world transform, making pan/zoom legible without implying that the
309
+ * runtime React layer owns any background at all. */
310
+ function ReactDesignCanvasBackdrop() {
311
+ const view = useSyncExternalStore(subscribeRootPan, getRootPan);
312
+ const spacing = Math.max(8, 24 * view.zoom);
313
+ const dotRadius = Math.max(0.7, Math.min(1.4, view.zoom));
314
+ return (
315
+ <div
316
+ data-testid="react-design-canvas-backdrop"
317
+ aria-hidden="true"
318
+ style={{
319
+ position: 'absolute',
320
+ inset: 0,
321
+ pointerEvents: 'none',
322
+ backgroundColor: REACT_DESIGN_CANVAS_COLOR,
323
+ backgroundImage: `radial-gradient(circle, ${REACT_DESIGN_CANVAS_DOT} ${dotRadius}px, transparent ${dotRadius}px)`,
324
+ backgroundPosition: `${view.x}px ${view.y}px`,
325
+ backgroundSize: `${spacing}px ${spacing}px`,
326
+ }}
327
+ />
328
+ );
329
+ }
330
+
331
+ /** Install the project's pinned center documents and map the three root to the
332
+ * native scene document. Returns the project/rebuild disposer; it closes only
333
+ * the documents installed by this call.
334
+ *
335
+ * ## A BOARD'S EXISTENCE IS ITS OWN PACKAGE'S VERDICT
336
+ *
337
+ * No board is decided here. A package registers one
338
+ * (`component-board-registry.ts`) and answers `presence()` for it; this
339
+ * installs and closes the registered set as those verdicts move, and asks the
340
+ * board itself why it is absent. Three statements used to be made here that
341
+ * are not the host's to make — that a project's boards are `dom`/`three`/
342
+ * `canvas`, that a board exists because the project has stories of that
343
+ * medium, and that "no board yet" is told from "no board ever" by a story
344
+ * DISCOVERY flag. The first is the registered set; the second is
345
+ * `presence()`; the third is `presence()` returning `null`.
346
+ *
347
+ * Everything else here is still root-derived where it is genuinely about a
348
+ * root: the `Scene` document and the document routes. A root whose own
349
+ * design surface IS a board — no separate document of its own — is routed at
350
+ * that board by matching the root descriptor's `kind` against the registered
351
+ * `medium`; the host compares two values it was handed and spells neither. */
352
+ export function installRootDocuments(
353
+ store: ShellStore,
354
+ composite: CompositeAuthoringAdapter,
355
+ ): () => void {
356
+ const previouslyActive = activeWorkspaceDocumentId();
357
+ const hasThreeRoot = composite
358
+ .childAdapters()
359
+ .some((child) => child.role === 'world' && child.kind === 'three');
360
+ // An UNPARSEABLE manifest installs one placeholder root and no three world.
361
+ // Closing the Scene document on it unmounted `the world root's stage` — the edit-mode
362
+ // rebuild OWNER — so the editor sat gutted ("No authoring adapter", no
363
+ // tabs, no canvas) and the manifest becoming valid again could remount
364
+ // nothing: measured 60 s after the fix, still gutted, only a second Play or
365
+ // a reload recovered (Opus verification, 2026-09-01). The project still
366
+ // declares a three root; its scene document stays, and the rebuild the
367
+ // recovery queues has an owner to drain into.
368
+ const manifestInvalid = composite
369
+ .childAdapters()
370
+ .some((child) => child.kind === INVALID_MANIFEST_SURFACE);
371
+ if (!hasThreeRoot && !manifestInvalid) {
372
+ closeWorkspaceDocument(SCENE_DOCUMENT_ID, { discardDirty: true });
373
+ }
374
+ const installedIds = new Set<string>();
375
+ const unregisterRoutes: Array<() => void> = [];
376
+ let disposed = false;
377
+
378
+ for (const child of composite.childAdapters()) {
379
+ if (child.role === 'world' && child.kind === 'three') {
380
+ unregisterRoutes.push(registerRootDocumentRoute(child.worldId, SCENE_DOCUMENT_ID));
381
+ }
382
+ }
383
+
384
+ const designTimeRoots = designTimeRootDescriptors(composite);
385
+
386
+ // THE CANVAS ROOT'S SCENE. A three project's scene is `the world root's stage`
387
+ // (`SCENE_DOCUMENT_ID`, owned by `syncCenterDocuments`); a canvas project's
388
+ // scene is this document, and a project has one or the other. Unlike the
389
+ // boards, it is ROOT-derived and not story-derived: it is a document OF that
390
+ // root's world, not a gallery of components.
391
+ const canvasRoot = designTimeRoots.find((root) => root.kind === 'canvas');
392
+ if (canvasRoot) {
393
+ unregisterRoutes.push(registerRootDocumentRoute(canvasRoot.worldId, CANVAS_SCENE_DOCUMENT_ID));
394
+ }
395
+
396
+ // A ROOT WHOSE DESIGN SURFACE IS A BOARD. A dom root has no document of its
397
+ // own: its surface is the project's UI board, so `activateRootDocument(id)`
398
+ // must reach that board and say why when it cannot. The pairing is the
399
+ // descriptor's `kind` against a registered `medium` — the host matches two
400
+ // values it was handed and names neither — and a root already routed at a
401
+ // Scene above keeps that route, because a world root's own document always
402
+ // wins over a gallery of its components.
403
+ //
404
+ // It is reconciled rather than registered once, for the reason every one of
405
+ // these registries has: the contribution pass that loads the packages is
406
+ // deferred behind the first viewport frame, so at project open NOTHING is
407
+ // registered yet.
408
+ const routedRoots = new Set(
409
+ [
410
+ ...composite
411
+ .childAdapters()
412
+ .filter((child) => child.role === 'world' && child.kind === 'three'),
413
+ ...(canvasRoot ? [canvasRoot] : []),
414
+ ].map((root) => root.worldId),
415
+ );
416
+ const boardRoutes = new Map<string, () => void>();
417
+ function reconcileBoardRoutes(): void {
418
+ for (const root of designTimeRoots) {
419
+ if (routedRoots.has(root.worldId) || boardRoutes.has(root.worldId)) continue;
420
+ const board = componentBoardForMedium(root.kind);
421
+ if (!board) continue;
422
+ const stopRoute = registerRootDocumentRoute(root.worldId, board.documentId);
423
+ // ...and the honest answer for the case that route CANNOT reach. A board
424
+ // exists only on its own package's verdict, so a root can route at a
425
+ // document that will never open in THIS project. Without this the ask
426
+ // waits out the whole registration window and then reports the generic
427
+ // "world document is not registered", which reads as a missing ROOT —
428
+ // the root is right there in the manifest, and the thing that is missing
429
+ // is its board. Live thunk, and `presence() === null` is what keeps it
430
+ // silent during boot: no verdict is never a No.
431
+ const stopGap = registerRootDocumentGap(root.worldId, () =>
432
+ board.presence() === 'absent'
433
+ ? `Root "${root.worldId}" has no document of its own: its design surface is the ` +
434
+ `project's ${board.title} board (${board.documentId}). ${board.absentReason()}`
435
+ : null,
436
+ );
437
+ boardRoutes.set(root.worldId, () => {
438
+ stopGap();
439
+ stopRoute();
440
+ });
441
+ }
442
+ }
443
+
444
+ // THE SAME GAP, asked the other way. `openWorkspaceView` names a DOCUMENT
445
+ // rather than a root, and `activateWorkspaceDocument`'s `false` carries the
446
+ // identical ambiguity plus one a root cannot have: the id may name nothing at
447
+ // all. Both were paid for with the full 10 s registration window and then a
448
+ // generic "not available" — long after the asking side gave up (MEASURED on
449
+ // this project: a bogus id timed out the relay at 5.6 s and left a
450
+ // `play-stall` error behind). This owner installs the project's workspace
451
+ // documents, so it is the one that can say why a document is absent — and
452
+ // for a BOARD it asks the board, which is the only party that knows.
453
+ unregisterRoutes.push(
454
+ registerWorkspaceDocumentGap((documentId) => {
455
+ const open = openWorkspaceDocuments();
456
+ if (open.some((document) => document.descriptor.id === documentId)) return null;
457
+ const board = componentBoardForDocument(documentId);
458
+ if (board) return board.presence() === 'absent' ? board.absentReason() : null;
459
+ return (
460
+ `No workspace document is named "${documentId}". Open in this session: ` +
461
+ `${open.map((document) => document.descriptor.id).join(', ') || '(none)'}. A component ` +
462
+ 'board is present only when the package that owns its medium says this project has one, ' +
463
+ 'so a board id can be absent for this project and present for another.'
464
+ );
465
+ }),
466
+ );
467
+
468
+ function openCanvasScene(descriptor: DesignTimeRootDescriptor): void {
469
+ const Content = (props: WorkspaceDocumentContentProps) => (
470
+ <RootDocumentContent {...props} composite={composite} descriptor={descriptor} store={store} />
471
+ );
472
+ registerAvailableWorkspaceDocument(
473
+ {
474
+ id: CANVAS_SCENE_DOCUMENT_ID,
475
+ title: CANVAS_SCENE_TITLE,
476
+ kind: 'world',
477
+ workspaceRole: 'authored-subject',
478
+ provenance: {
479
+ rootId: descriptor.worldId,
480
+ ...(descriptor.path ? { sourcePath: descriptor.path } : {}),
481
+ },
482
+ Content,
483
+ presentation: () => ({ kind: 'world', id: descriptor.worldId }),
484
+ },
485
+ { category: 'scene', default: !hasThreeRoot, rootId: descriptor.worldId },
486
+ );
487
+ }
488
+
489
+ /** Reserve the id BEFORE installing, so a second reconcile arriving while an
490
+ * asynchronous install is in flight does not start a second one; un-reserve
491
+ * if it fails, so the next verdict retries. Saying WHAT failed is the
492
+ * board's own job — only it knows what it was loading. */
493
+ function installBoard(board: ComponentBoard): void {
494
+ installedIds.add(board.documentId);
495
+ const unreserve = (): void => {
496
+ installedIds.delete(board.documentId);
497
+ };
498
+ try {
499
+ void Promise.resolve(board.install({ store, composite })).catch(unreserve);
500
+ } catch {
501
+ unreserve();
502
+ }
503
+ }
504
+
505
+ /** Bring the registered component boards in line with their own verdicts.
506
+ * Idempotent: `openWorkspaceDocument` is a no-op for a document already
507
+ * open, and `closeWorkspaceDocument` for one that is not.
508
+ *
509
+ * A board NEVER steals focus, which is why `install` is documented to open
510
+ * without activating: presence is answered ASYNCHRONOUSLY, so a board that
511
+ * arrives late would otherwise yank the author off whatever they were
512
+ * looking at (measured: the canvas root's `Scene` opened, then a board
513
+ * landed a second later and took the tab). The tail of this function still
514
+ * chooses the opening document. */
515
+ function reconcileBoards(): void {
516
+ if (disposed) return;
517
+ reconcileBoardRoutes();
518
+ for (const board of componentBoards()) {
519
+ const wanted = board.presence();
520
+ // `null` is "no verdict yet": neither install nor close. A census that
521
+ // has not run must not take a board away, and a board that has never
522
+ // been installed must not be conjured by silence.
523
+ if (wanted === null) continue;
524
+ const installed = installedIds.has(board.documentId);
525
+ if ((wanted === 'present') === installed) continue;
526
+ if (wanted === 'present') installBoard(board);
527
+ else {
528
+ unregisterAvailableWorkspaceDocument(board.documentId);
529
+ installedIds.delete(board.documentId);
530
+ }
531
+ }
532
+ }
533
+
534
+ // The canvas Scene is installed once, from the manifest — it does not
535
+ // participate in `reconcileBoards`' verdicts, because a world root's
536
+ // existence is not a question a board's package answers.
537
+ if (canvasRoot) {
538
+ openCanvasScene(canvasRoot);
539
+ installedIds.add(CANVAS_SCENE_DOCUMENT_ID);
540
+ }
541
+
542
+ reconcileBoards();
543
+ const unsubscribePresence = subscribeComponentBoards(reconcileBoards);
544
+
545
+ const firstInstalled = canvasRoot ? CANVAS_SCENE_DOCUMENT_ID : [...installedIds][0];
546
+ if (liveDocumentHeld()) {
547
+ // Play started before this project's documents installed: they open behind the game.
548
+ } else if (
549
+ !hasThreeRoot &&
550
+ firstInstalled !== undefined &&
551
+ (previouslyActive === null ||
552
+ previouslyActive === SCENE_DOCUMENT_ID ||
553
+ previouslyActive === GAME_DOCUMENT_ID)
554
+ ) {
555
+ activateWorkspaceDocument(firstInstalled);
556
+ } else if (previouslyActive) {
557
+ activateWorkspaceDocument(previouslyActive);
558
+ } else if (hasThreeRoot) {
559
+ activateWorkspaceDocument(SCENE_DOCUMENT_ID);
560
+ }
561
+
562
+ return () => {
563
+ disposed = true;
564
+ unsubscribePresence();
565
+ for (const unregister of unregisterRoutes) unregister();
566
+ for (const unregister of boardRoutes.values()) unregister();
567
+ boardRoutes.clear();
568
+ for (const id of installedIds) unregisterAvailableWorkspaceDocument(id);
569
+ };
570
+ }