@vgai/editor 0.2.0 → 0.4.0-canary.20260715.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 (430) hide show
  1. package/README.md +24 -0
  2. package/dist/assets/axe-C7YBtOuM.js +30 -0
  3. package/dist/assets/browserAll-DDtGGE48.js +1 -0
  4. package/dist/assets/create-runtime-DbTlBlKG.js +1 -0
  5. package/dist/assets/{game-BI111o5f.js → game-BE0r7DMI.js} +3 -3
  6. package/dist/assets/game-BdTHR2_X.js +1 -0
  7. package/dist/assets/{game-pt_1lQLv.js → game-C3iQGSqo.js} +1 -1
  8. package/dist/assets/game-CcHfYxjP.js +1 -0
  9. package/dist/assets/game-Cqzj_lpD.js +1 -0
  10. package/dist/assets/game-DSZdeCHu.js +1 -0
  11. package/dist/assets/game-Dch9sAPc.js +1 -0
  12. package/dist/assets/{game-xsOho_wg.js → game-SAFn90pA.js} +3 -3
  13. package/dist/assets/game-loop-DMIgSMV-.js +1 -0
  14. package/dist/assets/{game-source-CvidN7AB.js → game-source-Dk83w26t.js} +1 -1
  15. package/dist/assets/{index-Bp5cecD6.js → index-4idIsHHJ.js} +2 -2
  16. package/dist/assets/{index-DL7RcQ0n.js → index-C-LhOTBN.js} +1 -1
  17. package/dist/assets/{index-Cs8xwv3e.js → index-CDkxceqE.js} +1 -1
  18. package/dist/assets/index-CQEfi217.js +15412 -0
  19. package/dist/assets/index-Dvi-V0NE.css +1 -0
  20. package/dist/assets/ingest-siblings-s0P5I1Ub.js +1 -0
  21. package/dist/assets/mount-manifest-DXMOlF79.js +1 -0
  22. package/dist/assets/react-18-C9eHn8x1.js +1 -0
  23. package/dist/assets/webworkerAll-Fn0e-ouF.js +1 -0
  24. package/dist/assets/world-documents-GM0a9Kv7.js +1 -0
  25. package/dist/index.html +15 -13
  26. package/dist/ingest/racing-game/vgai.game.json +5 -4
  27. package/dist/ingest/simcity/vgai.game.json +5 -4
  28. package/dist/ingest/tanks/vgai.game.json +5 -4
  29. package/dist/project-scripts.bundle.js +3917 -0
  30. package/dist/scenes/untitled.vscn.json +2 -0
  31. package/dist-server/packaged.mjs +7697 -3435
  32. package/package.json +31 -4
  33. package/scripts/probe-reporter.ts +349 -0
  34. package/scripts/run-probe.ts +2260 -0
  35. package/server/asset-catalog-audit.ts +268 -0
  36. package/server/asset-catalog-v2.ts +146 -0
  37. package/server/asset-library-routes.ts +276 -58
  38. package/server/canonical-path.ts +1 -1
  39. package/server/dev.ts +148 -44
  40. package/server/editor-server.ts +888 -61
  41. package/server/editor-sse.ts +115 -4
  42. package/server/harness-chat-service.ts +796 -0
  43. package/server/local-asset-catalog.ts +157 -22
  44. package/server/packaged.ts +51 -21
  45. package/server/process-shutdown.ts +136 -0
  46. package/server/prod.ts +9 -6
  47. package/server/project-hmr-files.ts +41 -0
  48. package/server/project-operations.ts +343 -0
  49. package/server/project-optimize-deps-entries.ts +4 -4
  50. package/server/project-output-writer.ts +156 -0
  51. package/server/project-validation.ts +140 -0
  52. package/server/project-view.ts +8 -50
  53. package/server/server-utils.ts +75 -10
  54. package/server/session-registry.ts +12 -0
  55. package/src/EditorContext.tsx +107 -3
  56. package/src/action-registry.ts +115 -17
  57. package/src/adapter-resolver.ts +213 -478
  58. package/src/asset-events.ts +64 -1
  59. package/src/asset-preview.ts +906 -0
  60. package/src/asset-selection.ts +121 -0
  61. package/src/asset-workflow/asset-capabilities.ts +259 -0
  62. package/src/asset-workflow/asset-editor-errors.ts +46 -0
  63. package/src/asset-workflow/asset-import-pipeline.ts +176 -0
  64. package/src/asset-workflow/asset-library-query.ts +107 -0
  65. package/src/asset-workflow/asset-types.ts +192 -0
  66. package/src/asset-workflow/asset-workflow-quality.ts +65 -0
  67. package/src/asset-workflow/import-contract.ts +113 -0
  68. package/src/asset-workflow/model-conversion.ts +126 -0
  69. package/src/asset-workflow/model-inspection.ts +185 -0
  70. package/src/asset-workflow/project-asset-commands.ts +23 -0
  71. package/src/asset-workflow/project-asset-health.ts +153 -0
  72. package/src/asset-workflow/project-asset-operations.ts +119 -0
  73. package/src/asset-workflow/thumbnail-system.ts +172 -0
  74. package/src/authoring/active-systems.ts +15 -0
  75. package/src/authoring/boundary-authoring-adapter.ts +16 -5
  76. package/src/authoring/composite-authoring-adapter.ts +305 -124
  77. package/src/authoring/design-time-layers.ts +300 -117
  78. package/src/authoring/edit-mode-authoring.ts +278 -293
  79. package/src/authoring/embed-only-adapter.ts +4 -2
  80. package/src/authoring/first-party-hierarchy-menu.ts +7 -2
  81. package/src/authoring/first-party-inspector/AddSectionMenu.tsx +5 -12
  82. package/src/authoring/first-party-inspector/EnvironmentSection.tsx +53 -126
  83. package/src/authoring/first-party-inspector/HeaderSection.tsx +54 -65
  84. package/src/authoring/first-party-inspector/is-first-party-selection.ts +30 -11
  85. package/src/authoring/first-party-inspector/register.tsx +13 -2
  86. package/src/authoring/ingest-authoring-adapter.ts +142 -45
  87. package/src/authoring/mount-failure-report.ts +5 -5
  88. package/src/authoring/provenance.ts +41 -0
  89. package/src/authoring/react-dom-authoring-adapter.ts +92 -92
  90. package/src/authoring/react-inspector-section.tsx +489 -51
  91. package/src/authoring/react-world-authoring-adapter.ts +541 -306
  92. package/src/authoring/story-overlay.ts +1 -1
  93. package/src/authoring/story-types.ts +11 -0
  94. package/src/authoring/vgai-scene-authoring-adapter.ts +54 -25
  95. package/src/authoring/viewport-tool-context.ts +78 -0
  96. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  97. package/src/authoring/world-hidden-viewport.ts +186 -0
  98. package/src/authoring/world-pan-state.ts +33 -17
  99. package/src/authoring/world-session-state.ts +1 -1
  100. package/src/authoring/world2d-authoring-adapter.ts +109 -52
  101. package/src/availability-tick.ts +56 -0
  102. package/src/browser-play-entry.ts +5 -5
  103. package/src/browser-project-scripts.ts +1 -0
  104. package/src/build-identity.ts +15 -0
  105. package/src/command-listener.ts +893 -19
  106. package/src/components/AlignToolbar.tsx +74 -63
  107. package/src/components/AppRoot.tsx +193 -26
  108. package/src/components/ApplicationMenus.tsx +272 -0
  109. package/src/components/AssetBrowser.tsx +1450 -293
  110. package/src/components/AssetEditorShell.tsx +141 -0
  111. package/src/components/AssetImportDetails.tsx +218 -0
  112. package/src/components/AssetLibraryPanel.tsx +14 -0
  113. package/src/components/CameraInfo.tsx +11 -20
  114. package/src/components/CenterDocuments.tsx +585 -0
  115. package/src/components/CommandPalette.tsx +75 -30
  116. package/src/components/ConsolePanel.css +55 -0
  117. package/src/components/ConsolePanel.tsx +57 -112
  118. package/src/components/DebugConsolePanel.tsx +461 -0
  119. package/src/components/DebuggerPanel.tsx +165 -0
  120. package/src/components/DefaultEditorLayout.tsx +167 -231
  121. package/src/components/GameHierarchy.tsx +873 -290
  122. package/src/components/GamePerformanceOverlay.tsx +46 -0
  123. package/src/components/HarnessChatPanel.tsx +2352 -0
  124. package/src/components/HistoryPanel.tsx +226 -0
  125. package/src/components/Inspector.tsx +153 -99
  126. package/src/components/InspectorToolSection.tsx +6 -4
  127. package/src/components/MountFailureBanner.tsx +31 -48
  128. package/src/components/NetworkSection.tsx +25 -14
  129. package/src/components/OnlineAssetBrowser.tsx +794 -343
  130. package/src/components/OverlayReportBanner.tsx +38 -64
  131. package/src/components/PerformancePanel.tsx +206 -0
  132. package/src/components/PlayBar.tsx +93 -263
  133. package/src/components/PrefabSaveDialog.tsx +55 -127
  134. package/src/components/ProjectHeader.css +60 -0
  135. package/src/components/ProjectHeader.tsx +170 -105
  136. package/src/components/ProjectScreen.tsx +246 -184
  137. package/src/components/ReactCanvasControls.tsx +185 -0
  138. package/src/components/ResolutionPicker.tsx +85 -0
  139. package/src/components/RootActivateDialog.tsx +39 -68
  140. package/src/components/SaveDialog.tsx +55 -127
  141. package/src/components/SaveStatus.tsx +11 -29
  142. package/src/components/StartupLoadingScreen.tsx +96 -0
  143. package/src/components/StateWatchPanel.tsx +302 -0
  144. package/src/components/StatsOverlay.tsx +12 -5
  145. package/src/components/StatusBar.tsx +64 -0
  146. package/src/components/ThemeManagerDialog.css +89 -0
  147. package/src/components/ThemeManagerDialog.tsx +371 -0
  148. package/src/components/ToolHost.tsx +26 -15
  149. package/src/components/Toolbar.tsx +117 -214
  150. package/src/components/VgaiVoxelLogo.tsx +89 -0
  151. package/src/components/ViewportOverlay.tsx +97 -172
  152. package/src/components/ViewportPanel.tsx +130 -31
  153. package/src/components/WorkspaceDock.tsx +891 -0
  154. package/src/components/WorldSelectionOverlay.tsx +51 -63
  155. package/src/components/WorldTextEditor.tsx +9 -5
  156. package/src/components/asset-documents.tsx +390 -0
  157. package/src/components/asset-editor-persistence.ts +44 -0
  158. package/src/components/asset-selection-section.tsx +338 -0
  159. package/src/components/asset-viewers/AudioViewer.tsx +73 -21
  160. package/src/components/asset-viewers/GenericJsonViewer.tsx +26 -11
  161. package/src/components/asset-viewers/ImageViewer.tsx +43 -11
  162. package/src/components/asset-viewers/InputMapViewer.tsx +512 -134
  163. package/src/components/asset-viewers/MaterialAssetEditor.tsx +540 -0
  164. package/src/components/asset-viewers/ModelViewer.tsx +805 -121
  165. package/src/components/asset-viewers/OnlineAssetDetail.tsx +177 -60
  166. package/src/components/asset-viewers/SourceAssetViewer.tsx +121 -0
  167. package/src/components/asset-workflow.css +506 -0
  168. package/src/components/build-documents.tsx +696 -0
  169. package/src/components/core-utilities.tsx +75 -0
  170. package/src/components/data-documents.tsx +364 -0
  171. package/src/components/{DataPanel.tsx → data-editor.tsx} +138 -288
  172. package/src/components/debugger-panel-state.ts +57 -0
  173. package/src/components/inspector-widgets/AlignmentGrid.tsx +8 -14
  174. package/src/components/inspector-widgets/BorderEditor.tsx +41 -33
  175. package/src/components/inspector-widgets/ColorPicker.tsx +39 -39
  176. package/src/components/inspector-widgets/FontPicker.tsx +13 -21
  177. package/src/components/inspector-widgets/GradientEditor.tsx +11 -19
  178. package/src/components/inspector-widgets/ScrubbableInput.tsx +6 -3
  179. package/src/components/inspector-widgets/ShadowEditor.tsx +20 -33
  180. package/src/components/inspector-widgets/shared.tsx +90 -49
  181. package/src/components/inspectors/AnimationSection.tsx +39 -40
  182. package/src/components/inspectors/AudioSection.tsx +28 -39
  183. package/src/components/inspectors/BoneAttachmentSection.tsx +19 -24
  184. package/src/components/inspectors/CameraSection.tsx +14 -23
  185. package/src/components/inspectors/ComponentsSection.tsx +39 -43
  186. package/src/components/inspectors/JointsSection.tsx +34 -43
  187. package/src/components/inspectors/LightSection.tsx +90 -35
  188. package/src/components/inspectors/MaterialSection.tsx +137 -174
  189. package/src/components/inspectors/MeshSection.tsx +9 -17
  190. package/src/components/inspectors/NavigationSection.tsx +8 -15
  191. package/src/components/inspectors/ParticleSection.tsx +91 -76
  192. package/src/components/inspectors/PhysicsSection.tsx +42 -46
  193. package/src/components/inspectors/PostProcessingSection.tsx +28 -36
  194. package/src/components/inspectors/RenderingSection.tsx +12 -20
  195. package/src/components/inspectors/ShadowSection.tsx +7 -8
  196. package/src/components/inspectors/SplineSection.tsx +31 -42
  197. package/src/components/inspectors/TransformSection.tsx +14 -22
  198. package/src/components/patterns/Dialog.tsx +95 -0
  199. package/src/components/patterns/Fields.tsx +44 -0
  200. package/src/components/patterns/List.tsx +25 -0
  201. package/src/components/patterns/StateSurface.tsx +40 -0
  202. package/src/components/patterns/Surfaces.tsx +115 -0
  203. package/src/components/patterns/Tabs.tsx +80 -0
  204. package/src/components/patterns/Toolbar.tsx +51 -0
  205. package/src/components/patterns/Tree.tsx +72 -0
  206. package/src/components/primitives/Button.tsx +46 -0
  207. package/src/components/primitives/ColorInput.tsx +11 -47
  208. package/src/components/primitives/EditorIcon.tsx +99 -0
  209. package/src/components/primitives/FormControls.tsx +71 -0
  210. package/src/components/primitives/JsonInput.tsx +15 -2
  211. package/src/components/primitives/Layout.tsx +100 -0
  212. package/src/components/primitives/Menu.tsx +105 -0
  213. package/src/components/primitives/NumberInput.tsx +8 -35
  214. package/src/components/primitives/Panel.tsx +49 -44
  215. package/src/components/primitives/SectionHeader.tsx +10 -28
  216. package/src/components/primitives/Text.tsx +46 -0
  217. package/src/components/primitives/Tooltip.tsx +20 -12
  218. package/src/components/primitives/Vec3Input.tsx +3 -0
  219. package/src/components/primitives/banner-tones.ts +33 -0
  220. package/src/components/primitives/editor-icons.ts +102 -0
  221. package/src/components/primitives/panel-header-styles.ts +30 -0
  222. package/src/components/project-operation-documents.tsx +226 -0
  223. package/src/components/status-contributions.tsx +175 -0
  224. package/src/components/story-documents-register.ts +15 -0
  225. package/src/components/story-documents.tsx +1185 -0
  226. package/src/components/tool-documents.tsx +110 -0
  227. package/src/components/workspace-dock.css +293 -0
  228. package/src/components/workspace-history.ts +33 -0
  229. package/src/components/world-documents.tsx +145 -0
  230. package/src/components/xstate-documents.tsx +209 -0
  231. package/src/composite-screenshot.ts +248 -0
  232. package/src/design-system/index.ts +70 -0
  233. package/src/design-system-stories/Foundation.stories.tsx +183 -0
  234. package/src/design-system-stories/Patterns.stories.tsx +251 -0
  235. package/src/design-system-stories/Workspace.stories.tsx +538 -0
  236. package/src/doctor/report.ts +57 -13
  237. package/src/editor-api.ts +295 -31
  238. package/src/editor-compatibility.ts +200 -0
  239. package/src/editor-console.ts +35 -17
  240. package/src/editor-hotkeys.ts +85 -33
  241. package/src/editor-store.ts +538 -233
  242. package/src/editor-viewport.ts +160 -34
  243. package/src/entity-factory.ts +14 -3
  244. package/src/gizmo-registry.ts +21 -5
  245. package/src/harness-chat-editor-context.ts +37 -0
  246. package/src/harness-chat-indicator.ts +68 -0
  247. package/src/harness-chat-layout.ts +53 -0
  248. package/src/harness-chat-lifecycle.ts +170 -0
  249. package/src/harness-chat-reconnect.ts +85 -0
  250. package/src/harness-chat-types.ts +409 -0
  251. package/src/hierarchy-drop.ts +50 -0
  252. package/src/hierarchy-expansion-state.ts +100 -0
  253. package/src/hierarchy-menu-registry.ts +1 -1
  254. package/src/hierarchy-projection.ts +76 -0
  255. package/src/history/editor-session.ts +21 -0
  256. package/src/history/history-commands.ts +147 -0
  257. package/src/history/history-service.ts +904 -0
  258. package/src/history/json-history-resource.ts +165 -0
  259. package/src/history/persistence-coordinator.ts +35 -0
  260. package/src/history/project-file-history.ts +266 -0
  261. package/src/history/project-root-history-backends.ts +53 -0
  262. package/src/history/resource-registry.ts +209 -0
  263. package/src/history/snapshot-store.ts +108 -0
  264. package/src/history/source-history-backend.ts +374 -0
  265. package/src/history/types.ts +100 -0
  266. package/src/hmr-registration-group.ts +67 -0
  267. package/src/hmr-stable-react-context.ts +23 -0
  268. package/src/hosted-example.ts +12 -2
  269. package/src/hotkeys.ts +89 -18
  270. package/src/ingest/discovery-react.ts +9 -10
  271. package/src/ingest/discovery.ts +4 -4
  272. package/src/ingest/discovery2d.ts +5 -5
  273. package/src/ingest/games/bloom-composer/vgai.game.json +3 -3
  274. package/src/ingest/games/embed-bundle/vgai.game.json +3 -3
  275. package/src/ingest/games/games-fps/vgai.game.json +3 -3
  276. package/src/ingest/games/iframe-reachable/vgai.game.json +3 -3
  277. package/src/ingest/games/interactive-cubes/vgai.game.json +3 -3
  278. package/src/ingest/games/mismatched-three/vgai.game.json +3 -3
  279. package/src/ingest/games/own-three-bundled/vgai.game.json +3 -3
  280. package/src/ingest/games/pointerlock-maze/vgai.game.json +7 -4
  281. package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +3 -3
  282. package/src/ingest/games-2d/bunnymark/vgai.game.json +3 -3
  283. package/src/ingest/games-2d/flappy/vgai.game.json +3 -3
  284. package/src/ingest/games-2d/flappy-pixi/vgai.game.json +3 -3
  285. package/src/ingest/games-2d/puzzling-potions/vgai.game.json +3 -3
  286. package/src/ingest/games-2d/tilemap-camera/vgai.game.json +3 -3
  287. package/src/ingest/games-react/react-rpg/vgai.game.json +3 -3
  288. package/src/ingest/types.ts +1 -1
  289. package/src/ingest-mode.ts +47 -52
  290. package/src/ingest-siblings.ts +23 -33
  291. package/src/initial-scene.ts +1 -2
  292. package/src/main.tsx +16 -8
  293. package/src/manifest-project.ts +10 -12
  294. package/src/model-thumbnail.ts +261 -26
  295. package/src/module-mode.ts +44 -50
  296. package/src/play-log-events.ts +26 -0
  297. package/src/play-mode.ts +495 -401
  298. package/src/play-scene-adoption.ts +23 -0
  299. package/src/playground/main.ts +68 -24
  300. package/src/playwright-shim.ts +473 -0
  301. package/src/project-manager.ts +90 -10
  302. package/src/project-operations.ts +112 -0
  303. package/src/project-story-discovery.ts +25 -0
  304. package/src/project-tool-discovery.ts +43 -0
  305. package/src/scene-serializer.ts +0 -6
  306. package/src/scene-sync.ts +7 -2
  307. package/src/script-loader.ts +3 -3
  308. package/src/skeleton-helper.ts +57 -0
  309. package/src/storage/seed.ts +68 -8
  310. package/src/stories/StoryPreviewMount.tsx +265 -0
  311. package/src/stories/action-stories.fixture.tsx +44 -0
  312. package/src/stories/button-stories.fixture.tsx +50 -0
  313. package/src/stories/compose-project-stories.ts +182 -0
  314. package/src/stories/loader-stories.fixture.tsx +53 -0
  315. package/src/stories/story-discovery.ts +130 -0
  316. package/src/stories/story-registry.ts +146 -0
  317. package/src/theme-css.ts +1049 -0
  318. package/src/theme-library.ts +238 -0
  319. package/src/theme-preference.ts +130 -0
  320. package/src/theme.ts +527 -0
  321. package/src/tool-loader.ts +80 -24
  322. package/src/ui-source/inspect.ts +27 -4
  323. package/src/ui-source/source-write-backend.ts +83 -22
  324. package/src/widgets/index.ts +9 -18
  325. package/src/workspace-aux-commands.ts +11 -0
  326. package/src/workspace-dock-controller.ts +64 -0
  327. package/src/workspace-document-ids.ts +5 -0
  328. package/src/workspace-document-registry.ts +367 -0
  329. package/src/workspace-state-persistence.ts +455 -0
  330. package/src/workspace-status-registry.ts +110 -0
  331. package/src/workspace-utility-commands.ts +49 -0
  332. package/src/workspace-utility-registry.ts +161 -0
  333. package/src/world-document-routing.ts +16 -0
  334. package/src/xstate-inspect/XStateMachineInspector.tsx +544 -0
  335. package/src/xstate-inspect/character-animation-machine.fixture.ts +74 -0
  336. package/src/xstate-inspect/use-live-actor-state.ts +39 -0
  337. package/src/xstate-inspect/xstate-graph.ts +265 -0
  338. package/src/xstate-inspect/xstate-layout.ts +76 -0
  339. package/src/z-index.ts +26 -0
  340. package/template/.claude/skills/editor/SKILL.md +129 -90
  341. package/template/AGENTS.md +1110 -0
  342. package/template/CLAUDE.md +1 -512
  343. package/template/IDIOMS.md +50 -0
  344. package/template/check-idioms.ts +706 -0
  345. package/template/manifest-entry-modules-plugin.ts +53 -0
  346. package/template/package.json +13 -4
  347. package/template/public/scenes/default.scn2d.json +6 -0
  348. package/template/public/scenes/default.vscn.json +7 -1
  349. package/template/public/scenes/untitled.vscn.json +10 -0
  350. package/template/scripts/playtest.ts +40 -0
  351. package/template/server/loopback.ts +75 -0
  352. package/template/server/rooms/arena-room.ts +69 -1
  353. package/template/server/rooms/game-room.ts +68 -1
  354. package/template/src/data/README.md +9 -4
  355. package/template/src/data/data-ref.ts +35 -0
  356. package/template/src/data/tuning.schema.ts +1 -1
  357. package/template/src/main.ts +41 -62
  358. package/template/src/manifest-entry-modules.d.ts +3 -0
  359. package/template/src/operations/README.md +88 -0
  360. package/template/src/runtime/pixi-adapter.ts +24 -0
  361. package/template/src/scripts/components/data-spinner.ts +43 -2
  362. package/template/src/scripts/components/spin-lap-math.ts +27 -0
  363. package/template/src/tools/README.md +5 -3
  364. package/template/src/tools/example.tool.tsx +13 -7
  365. package/template/src/ui/Button.stories.tsx +66 -0
  366. package/template/src/ui/RebindPanel.tsx +2 -6
  367. package/template/src/ui/game.tsx +17 -0
  368. package/template/tests/acceptance/example.spec.ts +64 -0
  369. package/template/tests/logic/example.test.ts +31 -0
  370. package/template/tests/logic/room.test.ts +100 -0
  371. package/template/tests/tsconfig.json +30 -0
  372. package/template/validate-manifest.ts +5 -5
  373. package/template/validate-scenes.ts +50 -18
  374. package/template/vgai.game.json +20 -13
  375. package/template/vite.config.ts +77 -16
  376. package/vite-plugin-ui-oid.ts +261 -17
  377. package/dist/assets/CCDIKSolver-Dz-ysxZF.js +0 -1
  378. package/dist/assets/SelectionBox-BXsv_6aH.js +0 -1
  379. package/dist/assets/browser-project-scripts-DOru4L1x.js +0 -2
  380. package/dist/assets/browserAll-CEkWYlFk.js +0 -1
  381. package/dist/assets/create-runtime-DYIWr3va.js +0 -1
  382. package/dist/assets/data-asset-Bb9sIM7i.js +0 -5
  383. package/dist/assets/game-8SDZPPgH.js +0 -1
  384. package/dist/assets/game-CevorxyV.js +0 -1
  385. package/dist/assets/game-Di7XlywD.js +0 -1
  386. package/dist/assets/game-DjnCaw8R.js +0 -1
  387. package/dist/assets/game-Q9A0aXSV.js +0 -1
  388. package/dist/assets/index-CPVV6pjw.js +0 -1
  389. package/dist/assets/index-CpOnYyeD.js +0 -213
  390. package/dist/assets/index-Dr8H_6Rl.js +0 -1
  391. package/dist/assets/index-_bCaipUk.js +0 -13650
  392. package/dist/assets/ingest-siblings-Dz8eEqrV.js +0 -1
  393. package/dist/assets/mount-manifest-Bhk0ohsl.js +0 -1
  394. package/dist/assets/scene-query-BivAHhJu.js +0 -1
  395. package/dist/assets/webworkerAll-BLrH0F6F.js +0 -1
  396. package/dist/assets/xstate-animation-binding-1NGLmw6y.js +0 -1
  397. package/dist/assets/xstate.esm-BgUD33nl.js +0 -3
  398. package/src/authoring/scene-ui-layer.ts +0 -485
  399. package/src/authoring/ui-authoring-adapter.ts +0 -325
  400. package/src/authoring/ui-hierarchy-menu.ts +0 -40
  401. package/src/authoring/ui-inspector-sections.tsx +0 -156
  402. package/src/authoring/undo-timeline.ts +0 -145
  403. package/src/components/BottomPanel.tsx +0 -326
  404. package/src/components/BuildPanel.tsx +0 -455
  405. package/src/components/FolderTree.tsx +0 -179
  406. package/src/components/RightPanel.tsx +0 -166
  407. package/src/components/WorldContextMenu.tsx +0 -257
  408. package/src/components/asset-viewers/AssetViewer.tsx +0 -38
  409. package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +0 -129
  410. package/src/scene-ui-mode/active-scene-ui.ts +0 -58
  411. package/src/scene-ui-mode/scene-ui-palette-panel.tsx +0 -152
  412. package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +0 -29
  413. package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +0 -74
  414. package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +0 -49
  415. package/src/scene-ui-mode/ui-prefab-io.ts +0 -76
  416. package/src/ui-editor/inspector.tsx +0 -563
  417. package/src/ui-editor/node-ops.ts +0 -266
  418. package/src/ui-editor/overlay.tsx +0 -380
  419. package/src/ui-editor/palette.tsx +0 -114
  420. package/src/ui-editor/react-store.ts +0 -78
  421. package/src/ui-editor/timeline-panel.tsx +0 -443
  422. package/src/ui-editor/ui-edit-store.ts +0 -552
  423. package/src/ui-editor/ui-prefab.ts +0 -95
  424. package/template/project.json +0 -9
  425. package/template/src/scripts/main.ts +0 -94
  426. package/template/src/ui/DefaultHud.tsx +0 -40
  427. package/template/src/ui/game-state.tsx +0 -37
  428. package/template/src/ui/mount-default-hud.tsx +0 -19
  429. package/template/src/ui/mount-ui.ts +0 -15
  430. package/vite-plugin-react-world-provider.ts +0 -81
@@ -0,0 +1,110 @@
1
+ import { themeVars } from '../design-system';
2
+ /**
3
+ * Project-tool DOCUMENTS (W3, docs/EDITOR-WORKSPACE-SHELL-TODO.md §7.2/§9 W3
4
+ * — inventory rows B12/T2-behavior/T3): a `placement: 'document'` project
5
+ * tool (including every legacy `'dock'` tool — the W0 alias rule,
6
+ * docs/workspace-shell/W0-INVENTORY.md §2) opens as a CENTER workspace
7
+ * document (kind `'tool'`, title = the tool's own declared title per §8),
8
+ * hosted in the same error-boundaried `ToolHost` the bottom ⚙ tabs used.
9
+ * `placement: 'utility'` tools stay in the bottom area — registered in the
10
+ * workspace-utility registry by the tool-loader itself (see
11
+ * `tool-loader.ts`'s publish step). The ⚙ dock-tab row is gone.
12
+ *
13
+ * Open gesture: one `Open Tool: <title>` command-palette action per
14
+ * discovered document tool (`buildToolActions`) — the fixed-layout menu the
15
+ * ⚙ row used to be, now a searchable command. The template's `Tuning`
16
+ * example tool is the live proof.
17
+ *
18
+ * HMR/lifecycle: the document's CONTENT reads the LIVE tool store — an HMR
19
+ * reload bumps the tool's `version`, which re-keys the mount (fresh
20
+ * component + cleared error boundary, the same physics the dock tabs had);
21
+ * a deleted tool file leaves an honest "no longer available" message in any
22
+ * open document (discovery is the folder scan, D3).
23
+ */
24
+
25
+ import { useSyncExternalStore } from 'react';
26
+ import type { EditorAction } from '../action-registry';
27
+ import { getDocumentTools, getGlobalTools, subscribeGlobalTools } from '../tool-loader';
28
+ import {
29
+ openWorkspaceDocument,
30
+ type WorkspaceDocumentContentProps,
31
+ } from '../workspace-document-registry';
32
+ import { ToolHost } from './ToolHost';
33
+
34
+ /** The narrow store surface tool documents need (T6.3 tab hand-off). */
35
+ export interface ToolDocumentStore {
36
+ setActiveViewportTab(tab: 'scene' | 'game'): void;
37
+ }
38
+
39
+ /** Stable §7.1 identity for one project tool's document. */
40
+ export function toolDocumentId(toolId: string): string {
41
+ return `tool:${toolId}`;
42
+ }
43
+
44
+ /**
45
+ * Open (or activate) the center document for one document-placement project
46
+ * tool. Returns `false` (opens nothing) when no discovered document tool
47
+ * carries that id — no fabricated documents for deleted/renamed tools.
48
+ */
49
+ export function openToolDocument(store: ToolDocumentStore, toolId: string): boolean {
50
+ const tool = getDocumentTools().find((t) => t.id === toolId);
51
+ if (!tool) return false;
52
+ openWorkspaceDocument({
53
+ id: toolDocumentId(toolId),
54
+ // §8: the tool's own declared title (`Tuning`), never a tech bucket.
55
+ title: tool.title,
56
+ kind: 'tool',
57
+ provenance: { sourcePath: tool.file },
58
+ Content: ToolDocumentContent,
59
+ closeable: true,
60
+ onActivate: () => store.setActiveViewportTab('scene'),
61
+ });
62
+ return true;
63
+ }
64
+
65
+ /** `Open Tool: <title>` palette actions — one per discovered document tool
66
+ * (the B12 discovery gesture). */
67
+ export function buildToolActions(store: ToolDocumentStore): EditorAction[] {
68
+ return getDocumentTools().map((t) => ({
69
+ id: `tool-doc:${t.id}`,
70
+ label: `Open Tool: ${t.title}`,
71
+ category: 'action' as const,
72
+ execute: () => void openToolDocument(store, t.id),
73
+ }));
74
+ }
75
+
76
+ /** Content host: resolves the LIVE tool by id on every render (HMR re-key,
77
+ * honest deleted-tool state). */
78
+ export function ToolDocumentContent({ documentId }: WorkspaceDocumentContentProps) {
79
+ useSyncExternalStore(subscribeGlobalTools, getGlobalTools);
80
+ const toolId = documentId.startsWith('tool:') ? documentId.slice('tool:'.length) : documentId;
81
+ const tool = getDocumentTools().find((t) => t.id === toolId);
82
+ if (!tool) {
83
+ return (
84
+ <div
85
+ style={{ padding: 12, fontSize: 12, color: themeVars.content.muted, pointerEvents: 'auto' }}
86
+ >
87
+ This tool is no longer available (its `src/tools/` file was deleted or renamed) — close this
88
+ document.
89
+ </div>
90
+ );
91
+ }
92
+ return (
93
+ <div
94
+ key={`${tool.id}:${tool.version}`}
95
+ data-testid={`tool-document:${tool.id}`}
96
+ style={{
97
+ flex: 1,
98
+ minHeight: 0,
99
+ display: 'flex',
100
+ flexDirection: 'column',
101
+ pointerEvents: 'auto',
102
+ // B-11: the editor-provided baseline breathing room every hosted
103
+ // surface's content root has by convention (carried from the dock).
104
+ padding: 12,
105
+ }}
106
+ >
107
+ <ToolHost tool={tool} />
108
+ </div>
109
+ );
110
+ }
@@ -0,0 +1,293 @@
1
+ .dockview-theme-vgai {
2
+ --dv-group-view-background-color: var(--vgai-bg-1);
3
+ --dv-tabs-and-actions-container-background-color: var(--vgai-bg-2);
4
+ --dv-activegroup-visiblepanel-tab-background-color: transparent;
5
+ --dv-activegroup-hiddenpanel-tab-background-color: transparent;
6
+ --dv-inactivegroup-visiblepanel-tab-background-color: transparent;
7
+ --dv-inactivegroup-hiddenpanel-tab-background-color: transparent;
8
+ --dv-activegroup-visiblepanel-tab-color: var(--vgai-text-1);
9
+ --dv-activegroup-hiddenpanel-tab-color: var(--vgai-text-2);
10
+ --dv-inactivegroup-visiblepanel-tab-color: var(--vgai-text-2);
11
+ --dv-inactivegroup-hiddenpanel-tab-color: var(--vgai-text-3);
12
+ --dv-tab-divider-color: var(--vgai-border-1);
13
+ /* The sash paints the separator so the 1px line is centered inside its
14
+ larger 4px hit target instead of sitting on one panel edge. */
15
+ --dv-separator-border: transparent;
16
+ --dv-paneview-header-border-color: var(--vgai-border-1);
17
+ --dv-paneview-active-outline-color: var(--vgai-accent);
18
+ --dv-tabs-and-actions-container-height: var(--vgai-panel-header-height);
19
+ --dv-tabs-and-actions-container-font-size: var(--vgai-font-md);
20
+ --dv-tab-font-size: var(--vgai-font-md);
21
+ --dv-icon-hover-background-color: var(--vgai-bg-3);
22
+ --dv-drag-over-background-color: var(--vgai-accent-muted);
23
+ --dv-drag-over-border-color: var(--vgai-accent);
24
+ --dv-sash-color: transparent;
25
+ --dv-active-sash-color: transparent;
26
+ --dv-active-sash-transition-delay: 0s;
27
+ --dv-active-sash-transition-duration: 0.1s;
28
+ --dv-floating-border: var(--vgai-stroke-resting) solid var(--vgai-border-2);
29
+ --dv-floating-box-shadow: var(--vgai-shadow-lg);
30
+ --dv-floating-titlebar-height: 20px;
31
+ --dv-border-radius: 0;
32
+ --dv-tab-border-radius: 0;
33
+ --dv-tab-margin: 0;
34
+ --dv-spacing-padding: 0;
35
+ --dv-scrollbar-background-color: color-mix(in srgb, var(--vgai-content-primary) 28%, transparent);
36
+ font-family: var(--vgai-font-sans);
37
+ }
38
+
39
+ .vgai-workspace-dock {
40
+ position: relative;
41
+ flex: 1;
42
+ min-width: 0;
43
+ min-height: 0;
44
+ pointer-events: auto;
45
+ overflow: hidden;
46
+ background: var(--vgai-bg-1);
47
+ }
48
+
49
+ .vgai-workspace-dock > .dockview-theme-vgai {
50
+ width: 100%;
51
+ height: 100%;
52
+ }
53
+
54
+ .vgai-dock-panel,
55
+ .vgai-dock-document,
56
+ .vgai-dock-document-content {
57
+ min-width: 0;
58
+ min-height: 0;
59
+ width: 100%;
60
+ height: 100%;
61
+ }
62
+
63
+ .vgai-dock-panel,
64
+ .vgai-dock-document,
65
+ .vgai-dock-document-content {
66
+ display: flex;
67
+ flex-direction: column;
68
+ overflow: hidden;
69
+ background: var(--vgai-bg-1);
70
+ pointer-events: auto;
71
+ }
72
+
73
+ .vgai-dock-document-toolbar {
74
+ flex: 0 0 auto;
75
+ min-height: var(--vgai-local-toolbar-height);
76
+ border-bottom: var(--vgai-stroke-resting) solid var(--vgai-border-1);
77
+ background: var(--vgai-bg-1);
78
+ pointer-events: auto;
79
+ }
80
+
81
+ .vgai-dock-empty {
82
+ padding: var(--vgai-space-6);
83
+ color: var(--vgai-text-3);
84
+ background: var(--vgai-bg-1);
85
+ }
86
+
87
+ .vgai-dock-tab {
88
+ display: flex;
89
+ align-items: center;
90
+ height: 100%;
91
+ min-width: 0;
92
+ }
93
+
94
+ .vgai-dock-tab > .dv-default-tab {
95
+ min-width: 0;
96
+ }
97
+
98
+ /* Runtime/world surfaces and file-backed resource documents are different
99
+ navigation families. The adjacent-family selector makes the seam follow
100
+ the actual Dockview rail when the user moves tabs. */
101
+ .dockview-theme-vgai .dv-tab:has(.vgai-dock-tab[data-document-family="world"])
102
+ + .dv-tab:has(.vgai-dock-tab[data-document-family="resource"])
103
+ .vgai-dock-tab {
104
+ position: relative;
105
+ margin-left: var(--vgai-space-4);
106
+ }
107
+
108
+ .dockview-theme-vgai
109
+ .dv-tab:has(.vgai-dock-tab[data-document-family="world"])
110
+ + .dv-tab:has(.vgai-dock-tab[data-document-family="resource"])
111
+ .vgai-dock-tab::before {
112
+ position: absolute;
113
+ top: 50%;
114
+ left: calc(-1 * var(--vgai-space-3));
115
+ width: var(--vgai-stroke-resting);
116
+ height: 16px;
117
+ background: var(--vgai-border-2);
118
+ content: "";
119
+ transform: translateY(-50%);
120
+ pointer-events: none;
121
+ }
122
+
123
+ .dockview-theme-vgai .dv-tab {
124
+ padding: 0 10px;
125
+ border-radius: 0;
126
+ font-weight: 400;
127
+ transition:
128
+ background-color 80ms ease,
129
+ color 80ms ease;
130
+ }
131
+
132
+ .dockview-theme-vgai .dv-tabs-and-actions-container {
133
+ border-bottom: var(--vgai-stroke-resting) solid var(--vgai-border-1);
134
+ }
135
+
136
+ .dockview-theme-vgai .dv-tab.dv-inactive-tab:hover {
137
+ color: var(--vgai-text-1);
138
+ background: var(--vgai-bg-3);
139
+ }
140
+
141
+ .dockview-theme-vgai .dv-tabs-and-actions-container:not(.dv-single-tab) .dv-tabs-container {
142
+ gap: 2px;
143
+ padding: 0 3px;
144
+ }
145
+
146
+ /* Dockview's default separators make the rail resemble stock library tabs.
147
+ The editor uses whitespace and one active marker instead. */
148
+ .dockview-theme-vgai .dv-tabs-container.dv-horizontal .dv-tab:not(:first-child)::before {
149
+ display: none;
150
+ }
151
+
152
+ /* Dockview intentionally removes all padding in full-width single-tab mode.
153
+ Keep the full-width hit target, but restore the label inset and make the
154
+ result read as a panel heading rather than one enormous selected tab. */
155
+ .dockview-theme-vgai .dv-tabs-and-actions-container.dv-single-tab.dv-full-width-single-tab
156
+ .dv-tabs-container
157
+ .dv-tab {
158
+ margin: 0;
159
+ padding: 0 12px;
160
+ border-radius: 0;
161
+ font-weight: 600;
162
+ letter-spacing: 0.01em;
163
+ }
164
+
165
+ .vgai-dock-tab-dirty {
166
+ width: 6px;
167
+ height: 6px;
168
+ margin-right: 6px;
169
+ flex: 0 0 auto;
170
+ border-radius: 50%;
171
+ background: var(--vgai-warn);
172
+ }
173
+
174
+ .vgai-dock-tab-unsaved {
175
+ gap: 4px;
176
+ padding: 0 5px 0 8px;
177
+ color: var(--vgai-text-1);
178
+ background: var(--vgai-warn-muted);
179
+ }
180
+
181
+ .vgai-dock-tab-unsaved-label {
182
+ margin-right: 2px;
183
+ color: var(--vgai-warn);
184
+ font-weight: 600;
185
+ }
186
+
187
+ .vgai-dock-tab-unsaved button {
188
+ height: 20px;
189
+ padding: 0 5px;
190
+ border: var(--vgai-stroke-resting) solid var(--vgai-border-2);
191
+ border-radius: 3px;
192
+ color: var(--vgai-text-1);
193
+ background: var(--vgai-bg-2);
194
+ font: inherit;
195
+ cursor: pointer;
196
+ }
197
+
198
+ .vgai-dock-tab-unsaved button:hover:not(:disabled),
199
+ .vgai-dock-tab-unsaved button:focus-visible {
200
+ border-color: var(--vgai-accent);
201
+ color: var(--vgai-content-primary);
202
+ }
203
+
204
+ .vgai-dock-tab-unsaved button:disabled {
205
+ opacity: 0.6;
206
+ cursor: default;
207
+ }
208
+
209
+ .vgai-dock-tab-badge {
210
+ min-width: 14px;
211
+ height: 14px;
212
+ margin-right: 5px;
213
+ padding: 0 3px;
214
+ border-radius: 7px;
215
+ font-size: 9px;
216
+ line-height: 14px;
217
+ text-align: center;
218
+ color: var(--vgai-bg-0);
219
+ background: var(--vgai-text-2);
220
+ }
221
+
222
+ .vgai-dock-tab-badge-warn {
223
+ background: var(--vgai-warn);
224
+ }
225
+
226
+ .vgai-dock-tab-badge-error {
227
+ background: var(--vgai-danger);
228
+ }
229
+
230
+ .dockview-theme-vgai .dv-tabs-container .dv-tab.dv-active-tab {
231
+ box-shadow: none;
232
+ font-weight: 500;
233
+ }
234
+
235
+ .dockview-theme-vgai
236
+ .dv-tabs-and-actions-container:not(.dv-single-tab)
237
+ .dv-tabs-container
238
+ .dv-tab.dv-active-tab::before {
239
+ position: absolute;
240
+ right: 10px;
241
+ bottom: 0;
242
+ left: 10px;
243
+ display: block;
244
+ width: auto;
245
+ height: var(--vgai-stroke-active);
246
+ border-radius: 2px 2px 0 0;
247
+ background: var(--vgai-accent);
248
+ content: "";
249
+ }
250
+
251
+ .dockview-theme-vgai .dv-split-view-container.dv-horizontal > .dv-sash-container > .dv-sash {
252
+ background: linear-gradient(
253
+ to right,
254
+ transparent 1.5px,
255
+ var(--vgai-border-1) 1.5px 2.5px,
256
+ transparent 2.5px
257
+ );
258
+ }
259
+
260
+ .dockview-theme-vgai .dv-split-view-container.dv-vertical > .dv-sash-container > .dv-sash {
261
+ background: linear-gradient(
262
+ to bottom,
263
+ transparent 1.5px,
264
+ var(--vgai-border-1) 1.5px 2.5px,
265
+ transparent 2.5px
266
+ );
267
+ }
268
+
269
+ .dockview-theme-vgai .dv-split-view-container.dv-horizontal > .dv-sash-container > .dv-sash:hover,
270
+ .dockview-theme-vgai
271
+ .dv-split-view-container.dv-horizontal
272
+ > .dv-sash-container
273
+ > .dv-sash.dv-active {
274
+ background: linear-gradient(
275
+ to right,
276
+ transparent 1px,
277
+ var(--vgai-accent) 1px 3px,
278
+ transparent 3px
279
+ );
280
+ }
281
+
282
+ .dockview-theme-vgai .dv-split-view-container.dv-vertical > .dv-sash-container > .dv-sash:hover,
283
+ .dockview-theme-vgai
284
+ .dv-split-view-container.dv-vertical
285
+ > .dv-sash-container
286
+ > .dv-sash.dv-active {
287
+ background: linear-gradient(
288
+ to bottom,
289
+ transparent 1px,
290
+ var(--vgai-accent) 1px 3px,
291
+ transparent 3px
292
+ );
293
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Workspace history bridge (W3) — the session `HistoryService` handed to
3
+ * workspace-document content modules (`data-documents.tsx`,
4
+ * `build-documents.tsx`) WITHOUT them 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 — the old
9
+ * `DataPanel` took `history` as a PROP for exactly this reason, and the
10
+ * headless jsdom tests that mount document content rely on the light graph.
11
+ * `DefaultEditorLayout` (which already lives on the heavy side) sets the
12
+ * live service here; content reads it at commit time. Null (e.g. in tests,
13
+ * or before the layout mounts) degrades to the raw POST/save write paths —
14
+ * the same degrade the old prop-less mounts had.
15
+ */
16
+
17
+ import type { HistoryService } from '../history/history-service';
18
+
19
+ let _history: HistoryService | null = null;
20
+
21
+ /** Set (or clear) the live session history service. Returns a cleanup that
22
+ * clears it only if it is still this service. */
23
+ export function setWorkspaceHistoryService(history: HistoryService | null): () => void {
24
+ _history = history;
25
+ return () => {
26
+ if (_history === history) _history = null;
27
+ };
28
+ }
29
+
30
+ /** The live session history service, or `null`. */
31
+ export function workspaceHistoryService(): HistoryService | null {
32
+ return _history;
33
+ }
@@ -0,0 +1,145 @@
1
+ import { themeVars } from '../design-system';
2
+ /**
3
+ * Edit-time documents for manifest worlds that do not use the editor's
4
+ * native Three.js scene renderer. Runtime composition belongs to Game;
5
+ * authoring gives each React/Pixi world its own full-bleed center document.
6
+ */
7
+
8
+ import { useEffect, useRef, useSyncExternalStore } from 'react';
9
+ import { getActiveAuthoring } from '../authoring/active-adapter';
10
+ import type { CompositeAuthoringAdapter } from '../authoring/composite-authoring-adapter';
11
+ import {
12
+ type DesignTimeWorldDescriptor,
13
+ designTimeWorldDescriptors,
14
+ mountDesignTimeLayers,
15
+ } from '../authoring/design-time-layers';
16
+ import { resolveViewportToolContext } from '../authoring/viewport-tool-context';
17
+ import type { EditorStore } from '../editor-store';
18
+ import { SCENE_DOCUMENT_ID } from '../workspace-document-ids';
19
+ import {
20
+ activateWorkspaceDocument,
21
+ activeWorkspaceDocumentId,
22
+ closeWorkspaceDocument,
23
+ openWorkspaceDocument,
24
+ type WorkspaceDocumentContentProps,
25
+ } from '../workspace-document-registry';
26
+ import { registerWorldDocumentRoute } from '../world-document-routing';
27
+ import { ReactCanvasControls } from './ReactCanvasControls';
28
+ import { WorldSelectionOverlay } from './WorldSelectionOverlay';
29
+
30
+ export function worldDocumentId(worldId: string): string {
31
+ return `workspace:world:${worldId}`;
32
+ }
33
+
34
+ function WorldDocumentContent({
35
+ active,
36
+ composite,
37
+ descriptor,
38
+ store,
39
+ }: WorkspaceDocumentContentProps & {
40
+ composite: CompositeAuthoringAdapter;
41
+ descriptor: DesignTimeWorldDescriptor;
42
+ store: EditorStore;
43
+ }) {
44
+ const containerRef = useRef<HTMLDivElement>(null);
45
+ const disposeMountRef = useRef<(() => void) | null>(null);
46
+ useSyncExternalStore(store.subscribe, store.getSnapshot);
47
+
48
+ // Dockview keeps documents warm. Defer the relatively expensive Pixi/React
49
+ // mount until the world is first visited, then retain it across tab changes
50
+ // so hierarchy identity, story selection, and source editing remain stable.
51
+ useEffect(() => {
52
+ if (!active || disposeMountRef.current || !containerRef.current) return;
53
+ disposeMountRef.current = mountDesignTimeLayers(containerRef.current, composite, store, [
54
+ descriptor,
55
+ ]);
56
+ }, [active, composite, descriptor, store]);
57
+
58
+ useEffect(
59
+ () => () => {
60
+ disposeMountRef.current?.();
61
+ disposeMountRef.current = null;
62
+ },
63
+ [],
64
+ );
65
+
66
+ const selectedContext = resolveViewportToolContext(
67
+ getActiveAuthoring(store),
68
+ store.selectedEntityIds,
69
+ );
70
+ const context = selectedContext?.worldId === descriptor.worldId ? selectedContext : null;
71
+
72
+ return (
73
+ <div
74
+ ref={containerRef}
75
+ data-testid={`world-document:${descriptor.worldId}`}
76
+ style={{
77
+ position: 'absolute',
78
+ inset: 0,
79
+ overflow: 'hidden',
80
+ pointerEvents: 'auto',
81
+ backgroundColor: themeVars.surface.raised,
82
+ backgroundImage:
83
+ `linear-gradient(45deg, ${themeVars.surface.chrome} 25%, transparent 25%, transparent 75%, ${themeVars.surface.chrome} 75%), ` +
84
+ `linear-gradient(45deg, ${themeVars.surface.chrome} 25%, transparent 25%, transparent 75%, ${themeVars.surface.chrome} 75%)`,
85
+ backgroundPosition: '0 0, 8px 8px',
86
+ backgroundSize: '16px 16px',
87
+ }}
88
+ >
89
+ <WorldSelectionOverlay />
90
+ <ReactCanvasControls containerRef={containerRef} context={context} />
91
+ </div>
92
+ );
93
+ }
94
+
95
+ /** Install one pinned document per non-Three manifest world and map every
96
+ * Three world to the native scene document. Returns the project/rebuild
97
+ * disposer; it closes only the documents installed by this call. */
98
+ export function installWorldDocuments(
99
+ store: EditorStore,
100
+ composite: CompositeAuthoringAdapter,
101
+ ): () => void {
102
+ const previouslyActive = activeWorkspaceDocumentId();
103
+ const installedIds: string[] = [];
104
+ const unregisterRoutes: Array<() => void> = [];
105
+
106
+ for (const child of composite.childAdapters()) {
107
+ if (child.role === 'world' && child.kind === 'threejs') {
108
+ unregisterRoutes.push(registerWorldDocumentRoute(child.worldId, SCENE_DOCUMENT_ID));
109
+ }
110
+ }
111
+
112
+ for (const descriptor of designTimeWorldDescriptors(composite)) {
113
+ const id = worldDocumentId(descriptor.worldId);
114
+ unregisterRoutes.push(registerWorldDocumentRoute(descriptor.worldId, id));
115
+ installedIds.push(id);
116
+ const Content = (props: WorkspaceDocumentContentProps) => (
117
+ <WorldDocumentContent
118
+ {...props}
119
+ composite={composite}
120
+ descriptor={descriptor}
121
+ store={store}
122
+ />
123
+ );
124
+ openWorkspaceDocument({
125
+ id,
126
+ title: descriptor.worldId,
127
+ kind: 'world',
128
+ provenance: {
129
+ rootId: descriptor.worldId,
130
+ ...(descriptor.path ? { sourcePath: descriptor.path } : {}),
131
+ },
132
+ Content,
133
+ closeable: false,
134
+ onActivate: () => store.setActiveViewportTab('scene'),
135
+ });
136
+ }
137
+
138
+ if (previouslyActive) activateWorkspaceDocument(previouslyActive);
139
+ else activateWorkspaceDocument(SCENE_DOCUMENT_ID);
140
+
141
+ return () => {
142
+ for (const unregister of unregisterRoutes) unregister();
143
+ for (const id of installedIds) closeWorkspaceDocument(id, { discardDirty: true });
144
+ };
145
+ }