@volter/editor-core 0.5.57

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 (719) hide show
  1. package/BUNDLED_NOTICES +1527 -0
  2. package/LICENSE +686 -0
  3. package/LICENSE-APACHE +202 -0
  4. package/NOTICE +18 -0
  5. package/README.md +24 -0
  6. package/dist/build/chunk-JS4D4XZ3.js +175 -0
  7. package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
  8. package/dist/build/vite-plugin-product-contributions.js +100 -0
  9. package/dist/build/vite-plugin-product-contributions.js.map +7 -0
  10. package/dist/build/vite-plugin-shared-react.js +25 -0
  11. package/dist/build/vite-plugin-shared-react.js.map +7 -0
  12. package/dist/build/vite-plugin-shared-three.js +86 -0
  13. package/dist/build/vite-plugin-shared-three.js.map +7 -0
  14. package/dist/server/chunk-KMJC7AGO.js +98 -0
  15. package/dist/server/chunk-KMJC7AGO.js.map +7 -0
  16. package/dist/server/chunk-PSILUMGS.js +46 -0
  17. package/dist/server/chunk-PSILUMGS.js.map +7 -0
  18. package/dist/server/frame-proxy.js +255 -0
  19. package/dist/server/frame-proxy.js.map +7 -0
  20. package/dist/server/open-browser.js +53 -0
  21. package/dist/server/open-browser.js.map +7 -0
  22. package/dist/server/process-shutdown.js +127 -0
  23. package/dist/server/process-shutdown.js.map +7 -0
  24. package/dist/server/session-registry.js +141 -0
  25. package/dist/server/session-registry.js.map +7 -0
  26. package/dist/server/spawn-opener.js +11 -0
  27. package/dist/server/spawn-opener.js.map +7 -0
  28. package/dist/server/worktree-identity.js +11 -0
  29. package/dist/server/worktree-identity.js.map +7 -0
  30. package/dist-server/packaged.mjs +88816 -0
  31. package/package.json +118 -0
  32. package/scripts/build-plugins.mjs +14 -0
  33. package/scripts/build-server.mjs +26 -0
  34. package/scripts/build-session.mjs +9 -0
  35. package/server/account-credentials.ts +60 -0
  36. package/server/account-service.ts +1434 -0
  37. package/server/adapter-region-includes.ts +47 -0
  38. package/server/asset-catalog-v2.ts +175 -0
  39. package/server/asset-history-snapshots.ts +196 -0
  40. package/server/asset-ledger-store.ts +195 -0
  41. package/server/asset-library-routes.ts +1595 -0
  42. package/server/blender-wasm-artifact.ts +430 -0
  43. package/server/boot-timings.ts +106 -0
  44. package/server/canonical-path.ts +50 -0
  45. package/server/checkout-workspace-preflight.ts +349 -0
  46. package/server/cloud-asset-catalog.ts +158 -0
  47. package/server/coding-inference-launch.ts +237 -0
  48. package/server/collaboration-account-client.ts +202 -0
  49. package/server/collaboration-attribution.ts +122 -0
  50. package/server/collaboration-session.ts +934 -0
  51. package/server/comfyui-bridge.ts +248 -0
  52. package/server/console-ledger.ts +499 -0
  53. package/server/creation-site-transform.ts +304 -0
  54. package/server/creation-site-write.ts +648 -0
  55. package/server/data-file-serialize.ts +158 -0
  56. package/server/editor-brand-html.ts +72 -0
  57. package/server/editor-control-socket.ts +366 -0
  58. package/server/editor-server-options.ts +190 -0
  59. package/server/editor-server.ts +1483 -0
  60. package/server/editor-sse.ts +352 -0
  61. package/server/engine-provenance.ts +169 -0
  62. package/server/engine-source-restart.ts +117 -0
  63. package/server/frame-bridge.ts +115 -0
  64. package/server/frame-proxy.ts +490 -0
  65. package/server/frame-workbench.ts +259 -0
  66. package/server/frontend-handoff.ts +229 -0
  67. package/server/game-globals-shadow.ts +113 -0
  68. package/server/gameplay-session-retention.ts +149 -0
  69. package/server/gameplay-sessions.ts +123 -0
  70. package/server/generation-jobs.ts +201 -0
  71. package/server/generation-reconciler.ts +137 -0
  72. package/server/generative-execution-context.ts +59 -0
  73. package/server/git-workflow.ts +612 -0
  74. package/server/harness-chat-caller.ts +36 -0
  75. package/server/harness-chat-service.ts +1681 -0
  76. package/server/idle-shutdown.ts +170 -0
  77. package/server/js-profiling-policy.ts +52 -0
  78. package/server/launcher-settings.ts +84 -0
  79. package/server/local-asset-catalog.ts +410 -0
  80. package/server/managed-account-defaults.ts +22 -0
  81. package/server/mock-control-plane.ts +540 -0
  82. package/server/model-import-conversion.ts +345 -0
  83. package/server/native-credential-store.ts +162 -0
  84. package/server/open-browser.ts +118 -0
  85. package/server/packaged.ts +1192 -0
  86. package/server/play-stall.ts +126 -0
  87. package/server/process-shutdown.ts +218 -0
  88. package/server/product-presets.ts +55 -0
  89. package/server/project-build-artifact.ts +95 -0
  90. package/server/project-components.ts +100 -0
  91. package/server/project-dependency-invalidation.ts +114 -0
  92. package/server/project-file-scan.ts +235 -0
  93. package/server/project-hmr-files.ts +215 -0
  94. package/server/project-install-roots.ts +210 -0
  95. package/server/project-kinds.ts +71 -0
  96. package/server/project-mcp-servers.ts +82 -0
  97. package/server/project-module-freshness.ts +109 -0
  98. package/server/project-module-instance.ts +375 -0
  99. package/server/project-optimize-deps-entries.ts +827 -0
  100. package/server/project-output-writer.ts +679 -0
  101. package/server/project-package-origin.ts +63 -0
  102. package/server/project-root-surface.ts +831 -0
  103. package/server/project-scratch-path.ts +47 -0
  104. package/server/project-script-hmr.ts +619 -0
  105. package/server/project-serving-plugins.ts +236 -0
  106. package/server/project-tools.ts +653 -0
  107. package/server/project-validation.ts +250 -0
  108. package/server/project-verbs.ts +127 -0
  109. package/server/project-view.ts +52 -0
  110. package/server/project-watch.ts +1134 -0
  111. package/server/project-work-coordinator.ts +288 -0
  112. package/server/provider-credentials.ts +331 -0
  113. package/server/recent-projects-store.ts +98 -0
  114. package/server/redact-secrets.ts +71 -0
  115. package/server/repository-presence.ts +267 -0
  116. package/server/routes/account.ts +357 -0
  117. package/server/routes/agents.ts +60 -0
  118. package/server/routes/assets.ts +154 -0
  119. package/server/routes/build.ts +13 -0
  120. package/server/routes/collaboration.ts +595 -0
  121. package/server/routes/configurations.ts +419 -0
  122. package/server/routes/context.ts +264 -0
  123. package/server/routes/control-plane.ts +1811 -0
  124. package/server/routes/logs.ts +272 -0
  125. package/server/routes/project-identity.ts +302 -0
  126. package/server/routes/project-open.ts +429 -0
  127. package/server/routes/project-source.ts +686 -0
  128. package/server/routes/project-state.ts +383 -0
  129. package/server/routes/relay.ts +1029 -0
  130. package/server/routes/route-helpers.ts +29 -0
  131. package/server/routes/served-modules.ts +138 -0
  132. package/server/routes/session-tabs.ts +196 -0
  133. package/server/routes/settings.ts +121 -0
  134. package/server/routes/share-control.ts +486 -0
  135. package/server/routes/themes.ts +116 -0
  136. package/server/routes/tools.ts +230 -0
  137. package/server/routes/worktrees.ts +595 -0
  138. package/server/scoped-game-css.ts +461 -0
  139. package/server/server-utils.ts +1194 -0
  140. package/server/session-product.ts +112 -0
  141. package/server/session-registry.ts +230 -0
  142. package/server/share-claims.ts +138 -0
  143. package/server/share-host.ts +526 -0
  144. package/server/share-session-gateway.ts +1362 -0
  145. package/server/share-tunnel.ts +123 -0
  146. package/server/spawn-opener.ts +74 -0
  147. package/server/support/play/log-format.ts +76 -0
  148. package/server/support/play/session-record.ts +199 -0
  149. package/server/support/project/build-discipline.ts +718 -0
  150. package/server/support/project/inspection-node.ts +119 -0
  151. package/server/support/project/log-naming.ts +54 -0
  152. package/server/support/project/provenance.ts +290 -0
  153. package/server/support/project/run-name.ts +18 -0
  154. package/server/support/project/session-journal.ts +830 -0
  155. package/server/support/project/shared.ts +327 -0
  156. package/server/tab-bootstrap.ts +62 -0
  157. package/server/tab-heartbeat.ts +477 -0
  158. package/server/tab-lifecycle.ts +550 -0
  159. package/server/tab-presence.ts +1508 -0
  160. package/server/team-agent-mirror.ts +95 -0
  161. package/server/twin-auth.ts +138 -0
  162. package/server/vendored-lock-recorder.ts +968 -0
  163. package/server/worktree-identity.ts +121 -0
  164. package/server/worktree-management.ts +398 -0
  165. package/server/worktree-retention.d.mts +13 -0
  166. package/server/worktree-retention.mjs +205 -0
  167. package/src/EditorContext.tsx +169 -0
  168. package/src/account.ts +333 -0
  169. package/src/action-registry.ts +532 -0
  170. package/src/active-product.ts +74 -0
  171. package/src/active-project.ts +155 -0
  172. package/src/adapter-editor-config.ts +25 -0
  173. package/src/adapter-observation.ts +49 -0
  174. package/src/animation/stage-transport.ts +379 -0
  175. package/src/animation/three-clips-subject.ts +172 -0
  176. package/src/api/asset-library-wire.ts +45 -0
  177. package/src/api/assets.ts +365 -0
  178. package/src/api/base.ts +10 -0
  179. package/src/api/build.ts +99 -0
  180. package/src/api/git-wire.ts +56 -0
  181. package/src/api/logs.ts +92 -0
  182. package/src/api/project-identity.ts +74 -0
  183. package/src/api/project-open.ts +355 -0
  184. package/src/api/project-source.ts +162 -0
  185. package/src/api/project-state.ts +107 -0
  186. package/src/api/relay.ts +268 -0
  187. package/src/api/settings.ts +36 -0
  188. package/src/api/themes.ts +45 -0
  189. package/src/api/worktrees.ts +257 -0
  190. package/src/asset-compare-core.ts +171 -0
  191. package/src/asset-compare.ts +294 -0
  192. package/src/asset-editor-context.tsx +100 -0
  193. package/src/asset-events.ts +97 -0
  194. package/src/asset-inspector-actions.ts +87 -0
  195. package/src/asset-preview-framing.ts +357 -0
  196. package/src/asset-preview.ts +2802 -0
  197. package/src/asset-selection-viewer-registry.ts +113 -0
  198. package/src/asset-selection.ts +133 -0
  199. package/src/asset-workflow/asset-capabilities.ts +344 -0
  200. package/src/asset-workflow/asset-import-jobs.ts +106 -0
  201. package/src/asset-workflow/asset-ledger-backend.ts +126 -0
  202. package/src/asset-workflow/asset-ledger.ts +156 -0
  203. package/src/asset-workflow/asset-materialization-report.ts +140 -0
  204. package/src/asset-workflow/asset-pack-manifest.ts +320 -0
  205. package/src/asset-workflow/asset-types.ts +142 -0
  206. package/src/asset-workflow/asset-workflow-quality.ts +61 -0
  207. package/src/asset-workflow/audio-preview-player.ts +193 -0
  208. package/src/asset-workflow/audio-waveform.ts +22 -0
  209. package/src/asset-workflow/cloud-asset-client.ts +263 -0
  210. package/src/asset-workflow/folder-preview.ts +345 -0
  211. package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
  212. package/src/asset-workflow/image-view-scale.ts +32 -0
  213. package/src/asset-workflow/import-contract.ts +124 -0
  214. package/src/asset-workflow/ledger-write-lock.ts +244 -0
  215. package/src/asset-workflow/model-inspection.ts +818 -0
  216. package/src/asset-workflow/pixi-spritesheet.ts +197 -0
  217. package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
  218. package/src/asset-workflow/project-asset-commands.ts +23 -0
  219. package/src/asset-workflow/project-asset-health.ts +139 -0
  220. package/src/asset-workflow/project-asset-operations.ts +154 -0
  221. package/src/asset-workflow/project-asset-roots.ts +68 -0
  222. package/src/asset-workflow/project-content.ts +288 -0
  223. package/src/asset-workflow/project-source-index.ts +550 -0
  224. package/src/asset-workflow/thumbnail-system.ts +256 -0
  225. package/src/authoring/active-adapter.ts +199 -0
  226. package/src/authoring/active-systems.ts +422 -0
  227. package/src/authoring/adapter-key.ts +18 -0
  228. package/src/authoring/authoring-asset-url.ts +27 -0
  229. package/src/authoring/bootstrap-state.ts +49 -0
  230. package/src/authoring/boundary-authoring-adapter.ts +184 -0
  231. package/src/authoring/breakpoint-state.ts +43 -0
  232. package/src/authoring/canvas-scene-guides.ts +76 -0
  233. package/src/authoring/component-instance-root.ts +171 -0
  234. package/src/authoring/composite-authoring-adapter.ts +2110 -0
  235. package/src/authoring/consumer-actions.ts +520 -0
  236. package/src/authoring/css-numeric-style.ts +97 -0
  237. package/src/authoring/design-time-layers.ts +849 -0
  238. package/src/authoring/design-time-mount-registry.ts +235 -0
  239. package/src/authoring/design-time-settle.ts +343 -0
  240. package/src/authoring/edit-mode-authoring.ts +619 -0
  241. package/src/authoring/eyedropper-session.ts +60 -0
  242. package/src/authoring/instance-source-menu-register.ts +13 -0
  243. package/src/authoring/instance-source-menu.ts +135 -0
  244. package/src/authoring/layered-pick.ts +183 -0
  245. package/src/authoring/live-gesture-lock.ts +50 -0
  246. package/src/authoring/live-object-transform.ts +62 -0
  247. package/src/authoring/mount-failure-report.ts +154 -0
  248. package/src/authoring/mounted-root-subjects.ts +144 -0
  249. package/src/authoring/no-authoring-adapter.ts +55 -0
  250. package/src/authoring/null-inspection-subjects.tsx +75 -0
  251. package/src/authoring/object3d-document-persistence.ts +106 -0
  252. package/src/authoring/object3d-document-session-registry.ts +120 -0
  253. package/src/authoring/object3d-document-session.ts +1326 -0
  254. package/src/authoring/object3d-gesture-controller.ts +113 -0
  255. package/src/authoring/panel-authoring.ts +121 -0
  256. package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
  257. package/src/authoring/prefab-instance-section-model.ts +55 -0
  258. package/src/authoring/project-authoring-session.ts +105 -0
  259. package/src/authoring/provenance.ts +99 -0
  260. package/src/authoring/quarks-particle-systems.ts +19 -0
  261. package/src/authoring/react-canvas-navigation.ts +255 -0
  262. package/src/authoring/react-design-canvas-style.ts +20 -0
  263. package/src/authoring/react-story-board.ts +937 -0
  264. package/src/authoring/selection-scope.ts +195 -0
  265. package/src/authoring/shell-document-ops.ts +169 -0
  266. package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
  267. package/src/authoring/shell-viewport-policy.ts +48 -0
  268. package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
  269. package/src/authoring/stories-scope.ts +35 -0
  270. package/src/authoring/story-board-chrome-fit.ts +107 -0
  271. package/src/authoring/story-board-presentation.ts +111 -0
  272. package/src/authoring/three-projection-core.ts +226 -0
  273. package/src/authoring/viewport-pick-context.ts +40 -0
  274. package/src/authoring/viewport-raycast.ts +240 -0
  275. package/src/authoring/viewport-tool-context.ts +73 -0
  276. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  277. package/src/authoring/world-hidden-viewport.ts +152 -0
  278. package/src/authoring/world-pan-state.ts +198 -0
  279. package/src/authoring/world-session-state.ts +101 -0
  280. package/src/authoring/write-pipe.ts +173 -0
  281. package/src/availability-tick.ts +66 -0
  282. package/src/bitmap-label.ts +120 -0
  283. package/src/blender-tab-metrics.ts +161 -0
  284. package/src/board-open-actions.ts +20 -0
  285. package/src/boot-routing.ts +391 -0
  286. package/src/build-identity.ts +15 -0
  287. package/src/bytes-codec.ts +62 -0
  288. package/src/camera-authoring.ts +175 -0
  289. package/src/cancellation-reason.ts +58 -0
  290. package/src/canvas-preview-frames.ts +482 -0
  291. package/src/capture-camera-pose.ts +77 -0
  292. package/src/chrome-registry.ts +159 -0
  293. package/src/chrome-slot-registry.ts +91 -0
  294. package/src/collaboration-client.ts +264 -0
  295. package/src/collaboration-presence.ts +41 -0
  296. package/src/command-dispatch.ts +19 -0
  297. package/src/command-listener.ts +2743 -0
  298. package/src/command-registry.ts +70 -0
  299. package/src/component-board-registry.ts +205 -0
  300. package/src/component-states-registry.ts +200 -0
  301. package/src/components/AgentPresentationNotice.tsx +75 -0
  302. package/src/components/AlignToolbar.tsx +204 -0
  303. package/src/components/AppRoot.tsx +394 -0
  304. package/src/components/ApplicationMenus.tsx +415 -0
  305. package/src/components/AssetBrowser.tsx +2843 -0
  306. package/src/components/AssetEditorShell.tsx +216 -0
  307. package/src/components/AssetInspectorToolSection.tsx +124 -0
  308. package/src/components/BoardRulers.tsx +354 -0
  309. package/src/components/CameraInfo.tsx +81 -0
  310. package/src/components/CanvasSceneViewport.tsx +556 -0
  311. package/src/components/CapabilityCoverageSection.tsx +185 -0
  312. package/src/components/CenterDocuments.tsx +22 -0
  313. package/src/components/ChromeSlot.tsx +20 -0
  314. package/src/components/CodeView.tsx +470 -0
  315. package/src/components/CollaborationHeaderControl.css +74 -0
  316. package/src/components/CompactInspectorCard.tsx +190 -0
  317. package/src/components/CompactInspectorShell.tsx +39 -0
  318. package/src/components/ConsolePanel.css +55 -0
  319. package/src/components/ConsolePanel.tsx +270 -0
  320. package/src/components/DefaultEditorLayout.tsx +106 -0
  321. package/src/components/DocumentHeaderStrip.tsx +96 -0
  322. package/src/components/DocumentShelfRail.tsx +45 -0
  323. package/src/components/DocumentThumbnail.tsx +345 -0
  324. package/src/components/EditorLeaseGuard.tsx +372 -0
  325. package/src/components/ErrorBanner.tsx +123 -0
  326. package/src/components/FolderPreviewTile.tsx +159 -0
  327. package/src/components/GameHierarchy.tsx +3842 -0
  328. package/src/components/GameplaySessionTimeline.tsx +295 -0
  329. package/src/components/InspectionProjection.tsx +968 -0
  330. package/src/components/Inspector.tsx +233 -0
  331. package/src/components/InspectorCanvasPreview.tsx +35 -0
  332. package/src/components/InspectorFieldsSection.tsx +290 -0
  333. package/src/components/InspectorObjectPreview.tsx +57 -0
  334. package/src/components/InspectorStoriesSection.tsx +92 -0
  335. package/src/components/InspectorToolSection.tsx +96 -0
  336. package/src/components/InspectorTransformSection.tsx +245 -0
  337. package/src/components/LightExplorerPanel.tsx +433 -0
  338. package/src/components/MediaProperties.tsx +145 -0
  339. package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
  340. package/src/components/Object3DDocumentToolbar.css +100 -0
  341. package/src/components/Object3DDocumentToolbar.tsx +454 -0
  342. package/src/components/Object3DDocumentViewport.tsx +58 -0
  343. package/src/components/ProjectHeader.css +617 -0
  344. package/src/components/ProjectHeader.tsx +328 -0
  345. package/src/components/ProjectLayout.tsx +249 -0
  346. package/src/components/ReactCanvasControls.tsx +284 -0
  347. package/src/components/RootSelectionOverlay.tsx +3162 -0
  348. package/src/components/RootTextEditor.tsx +79 -0
  349. package/src/components/SaveStatus.tsx +70 -0
  350. package/src/components/StageHost.tsx +1954 -0
  351. package/src/components/StageOverlays.tsx +21 -0
  352. package/src/components/StartupErrorScreen.tsx +76 -0
  353. package/src/components/StartupLoadingScreen.tsx +65 -0
  354. package/src/components/StatsOverlay.tsx +78 -0
  355. package/src/components/SurfaceStateOverlay.tsx +24 -0
  356. package/src/components/ToolContributionSurfaces.tsx +65 -0
  357. package/src/components/ToolHost.tsx +370 -0
  358. package/src/components/ToolObject3DPreview.tsx +39 -0
  359. package/src/components/Toolbar.tsx +595 -0
  360. package/src/components/TransientHint.tsx +44 -0
  361. package/src/components/TransportStrip.tsx +174 -0
  362. package/src/components/VersionControlSection.tsx +470 -0
  363. package/src/components/VgaiLogo.css +83 -0
  364. package/src/components/VgaiLogo.tsx +35 -0
  365. package/src/components/ViewportControlsHint.tsx +60 -0
  366. package/src/components/ViewportFurniture.tsx +401 -0
  367. package/src/components/ViewportOverlay.tsx +145 -0
  368. package/src/components/ViewportOverlaysMenu.tsx +153 -0
  369. package/src/components/ViewportShadingMenu.tsx +300 -0
  370. package/src/components/ViewportViewMenu.tsx +101 -0
  371. package/src/components/WorkspaceDocumentSurface.tsx +204 -0
  372. package/src/components/WorkspaceUtilitySurface.tsx +22 -0
  373. package/src/components/WorktreeSwitcher.css +239 -0
  374. package/src/components/WorktreeSwitcher.tsx +890 -0
  375. package/src/components/account-documents.tsx +1162 -0
  376. package/src/components/asset-documents.tsx +812 -0
  377. package/src/components/asset-editor-persistence.ts +216 -0
  378. package/src/components/asset-selection-section.tsx +535 -0
  379. package/src/components/asset-thumbnails.tsx +312 -0
  380. package/src/components/asset-viewers/AudioViewer.tsx +201 -0
  381. package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
  382. package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
  383. package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  384. package/src/components/asset-viewers/ImageViewer.tsx +300 -0
  385. package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
  386. package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
  387. package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
  388. package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
  389. package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
  390. package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
  391. package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
  392. package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
  393. package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
  394. package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
  395. package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  396. package/src/components/asset-viewers/VideoViewer.tsx +101 -0
  397. package/src/components/asset-viewers/shader-source.ts +144 -0
  398. package/src/components/asset-workflow.css +731 -0
  399. package/src/components/board-guides.ts +150 -0
  400. package/src/components/compact-inspector.css +539 -0
  401. package/src/components/core-utilities.tsx +90 -0
  402. package/src/components/editor-notifications.css +40 -0
  403. package/src/components/engine-workspace.css +274 -0
  404. package/src/components/inspector-preview-section.tsx +238 -0
  405. package/src/components/inspector-property-grouping.ts +64 -0
  406. package/src/components/inspector-revert-label.ts +20 -0
  407. package/src/components/inspector-selection.ts +42 -0
  408. package/src/components/inspector-stories-gating.ts +171 -0
  409. package/src/components/inspector-transform-subject.ts +11 -0
  410. package/src/components/inspector-transform.ts +75 -0
  411. package/src/components/kind-documents.tsx +500 -0
  412. package/src/components/palette-action-publisher.tsx +140 -0
  413. package/src/components/primitives/DraftColorInput.tsx +74 -0
  414. package/src/components/product-shell.css +1829 -0
  415. package/src/components/project-tool-documents.tsx +410 -0
  416. package/src/components/scene-documents.tsx +223 -0
  417. package/src/components/stage-keyboard.tsx +37 -0
  418. package/src/components/stage-overlay-set.tsx +107 -0
  419. package/src/components/stage-presence-markers.ts +478 -0
  420. package/src/components/standard-viewport-dressing.ts +417 -0
  421. package/src/components/status-contributions.tsx +403 -0
  422. package/src/components/tool-documents.tsx +309 -0
  423. package/src/components/tool-schema-form.tsx +262 -0
  424. package/src/components/use-after-paint.ts +41 -0
  425. package/src/components/use-project-image-assets.ts +86 -0
  426. package/src/components/viewport-header-controls.css +90 -0
  427. package/src/components/viewport-surface-status.tsx +55 -0
  428. package/src/components/workspace-history.ts +32 -0
  429. package/src/components/workspace-static-panel-registry.tsx +152 -0
  430. package/src/components/workspace-surfaces.css +621 -0
  431. package/src/components/world-documents.tsx +586 -0
  432. package/src/components/world-overlay-gestures.ts +1694 -0
  433. package/src/composite-screenshot.ts +1641 -0
  434. package/src/console-sync.ts +131 -0
  435. package/src/constraint-helper.ts +338 -0
  436. package/src/content-entry-source-registry.ts +184 -0
  437. package/src/coverage/authoring-seam-evidence.ts +300 -0
  438. package/src/coverage/canvas-reveal.ts +192 -0
  439. package/src/coverage/design-time-surfaces.ts +101 -0
  440. package/src/coverage/live-seam-evidence.ts +11 -0
  441. package/src/coverage/ontology-invariants.ts +466 -0
  442. package/src/coverage/session-vitals.ts +501 -0
  443. package/src/coverage/system-seam-evidence.ts +72 -0
  444. package/src/crash-null-boundary.ts +36 -0
  445. package/src/creation-site-edit.ts +1479 -0
  446. package/src/creation-site-registry.ts +160 -0
  447. package/src/delegate-harness-registry.ts +143 -0
  448. package/src/document-context-registry.ts +177 -0
  449. package/src/document-open-registry.ts +200 -0
  450. package/src/document-preview-source.ts +20 -0
  451. package/src/document-renderer-session.ts +138 -0
  452. package/src/editor-api.ts +46 -0
  453. package/src/editor-chrome-capture.ts +139 -0
  454. package/src/editor-commands.ts +164 -0
  455. package/src/editor-console.ts +563 -0
  456. package/src/editor-current-view.ts +82 -0
  457. package/src/editor-document-probe.ts +881 -0
  458. package/src/editor-git-client.ts +115 -0
  459. package/src/editor-host-door.ts +462 -0
  460. package/src/editor-hotkeys.ts +842 -0
  461. package/src/editor-lease-view.ts +39 -0
  462. package/src/editor-lease.ts +415 -0
  463. package/src/editor-mode.ts +19 -0
  464. package/src/editor-notifications.ts +140 -0
  465. package/src/editor-presence.ts +563 -0
  466. package/src/editor-presentation-activity.ts +50 -0
  467. package/src/editor-presentation-notice.ts +42 -0
  468. package/src/editor-runtime.tsx +145 -0
  469. package/src/editor-server-response.ts +86 -0
  470. package/src/editor-session-attribution.ts +75 -0
  471. package/src/editor-session-mode.ts +54 -0
  472. package/src/editor-shell-store.ts +1304 -0
  473. package/src/editor-state-facets.ts +74 -0
  474. package/src/editor-styles.css +33 -0
  475. package/src/editor-view-presentation.ts +810 -0
  476. package/src/editor-viewport.ts +5302 -0
  477. package/src/entity-lod.ts +31 -0
  478. package/src/entity-object.ts +91 -0
  479. package/src/files/file-provider.ts +62 -0
  480. package/src/files/project-files.ts +264 -0
  481. package/src/finders/index.ts +136 -0
  482. package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
  483. package/src/frame/bridge.tsx +1408 -0
  484. package/src/frame/product.ts +77 -0
  485. package/src/gameplay-dom-recording.ts +319 -0
  486. package/src/gameplay-export-state.ts +14 -0
  487. package/src/gameplay-replay.ts +417 -0
  488. package/src/gameplay-session-time.ts +9 -0
  489. package/src/gameplay-sessions.ts +204 -0
  490. package/src/harness-chat-types.ts +253 -0
  491. package/src/hierarchy-component-marks.ts +298 -0
  492. package/src/hierarchy-drop.ts +91 -0
  493. package/src/hierarchy-expansion-state.ts +80 -0
  494. package/src/hierarchy-header-slot.ts +52 -0
  495. package/src/hierarchy-internals.ts +197 -0
  496. package/src/hierarchy-kind-icon.ts +217 -0
  497. package/src/hierarchy-mark-reader.ts +73 -0
  498. package/src/hierarchy-menu-registry.ts +67 -0
  499. package/src/hierarchy-node-rows.ts +307 -0
  500. package/src/hierarchy-panel-view.ts +280 -0
  501. package/src/hierarchy-projection.ts +76 -0
  502. package/src/hierarchy-row-cache.ts +243 -0
  503. package/src/hierarchy-row-model.ts +308 -0
  504. package/src/hierarchy-rows.ts +11 -0
  505. package/src/hierarchy-walk.ts +86 -0
  506. package/src/history/editor-session.ts +25 -0
  507. package/src/history/history-commands.ts +147 -0
  508. package/src/history/history-delegate.ts +163 -0
  509. package/src/history/history-limit-notices.ts +43 -0
  510. package/src/history/history-service.ts +1173 -0
  511. package/src/history/persistence-coordinator.ts +35 -0
  512. package/src/history/project-file-history.ts +386 -0
  513. package/src/history/project-root-history-backends.ts +139 -0
  514. package/src/history/resource-registry.ts +209 -0
  515. package/src/history/snapshot-store.ts +103 -0
  516. package/src/history/source-history-backend.ts +546 -0
  517. package/src/history/types.ts +124 -0
  518. package/src/hmr-registration-group.ts +67 -0
  519. package/src/hmr-stable-react-context.ts +23 -0
  520. package/src/hotkeys.ts +188 -0
  521. package/src/inference-diagnostics.ts +69 -0
  522. package/src/initial-project.ts +80 -0
  523. package/src/inspection/active-subject.ts +578 -0
  524. package/src/inspection/active-surface.ts +142 -0
  525. package/src/inspection/compose.ts +1064 -0
  526. package/src/inspection/display.ts +170 -0
  527. package/src/inspection/document-subject.ts +109 -0
  528. package/src/inspection/game-subject.ts +85 -0
  529. package/src/inspection/model.ts +542 -0
  530. package/src/inspection/null-subject.ts +115 -0
  531. package/src/inspection/serialize.ts +357 -0
  532. package/src/inspection/use-active-inspection.ts +180 -0
  533. package/src/inspector-presentation.ts +201 -0
  534. package/src/inspector-section-registry.ts +221 -0
  535. package/src/instance-source-actions.ts +163 -0
  536. package/src/instanced-presentation.ts +164 -0
  537. package/src/js-heap.ts +71 -0
  538. package/src/key-actions.ts +91 -0
  539. package/src/keymap-presets.ts +401 -0
  540. package/src/layout-policy.ts +31 -0
  541. package/src/learn-links.ts +73 -0
  542. package/src/light-explorer-model.ts +134 -0
  543. package/src/live-canvas-frame.ts +55 -0
  544. package/src/live-document.ts +279 -0
  545. package/src/live-module-source.ts +230 -0
  546. package/src/live-session-registry.ts +220 -0
  547. package/src/live-transition.ts +633 -0
  548. package/src/manifest-project.ts +107 -0
  549. package/src/model-thumbnail.ts +523 -0
  550. package/src/native-selection-style.ts +202 -0
  551. package/src/object3d-document-write-policy.ts +137 -0
  552. package/src/packaged-runtime.ts +108 -0
  553. package/src/palettes/maya.palette.json +57 -0
  554. package/src/palettes/substance.palette.json +57 -0
  555. package/src/pasteboard-module.ts +81 -0
  556. package/src/performance-profiler.ts +367 -0
  557. package/src/performance-sources.ts +69 -0
  558. package/src/play-boot-phase.ts +145 -0
  559. package/src/presentation-surface.ts +248 -0
  560. package/src/project-adapter.ts +1143 -0
  561. package/src/project-asset-refresh.ts +26 -0
  562. package/src/project-declaration-refresh.ts +31 -0
  563. package/src/project-local-state.ts +118 -0
  564. package/src/project-manager.ts +243 -0
  565. package/src/project-module-changes.ts +163 -0
  566. package/src/project-module-split.ts +266 -0
  567. package/src/project-provenance.ts +115 -0
  568. package/src/project-ready.ts +42 -0
  569. package/src/project-session-reset.ts +67 -0
  570. package/src/project-shape.ts +68 -0
  571. package/src/project-tool-discovery.ts +66 -0
  572. package/src/project-tools.ts +107 -0
  573. package/src/project-work-types.ts +149 -0
  574. package/src/projection/three.ts +898 -0
  575. package/src/projection/types.ts +44 -0
  576. package/src/readiness.ts +113 -0
  577. package/src/reflection-probe-helper.ts +142 -0
  578. package/src/reported-play-state.ts +90 -0
  579. package/src/resolve-relative-specifier.ts +33 -0
  580. package/src/scene-document-plan.ts +315 -0
  581. package/src/scene-framing.ts +315 -0
  582. package/src/scene-live-open.ts +210 -0
  583. package/src/scene-view-fog.ts +89 -0
  584. package/src/scoped-game-css.ts +152 -0
  585. package/src/session-orphan-record.ts +193 -0
  586. package/src/session-tombstone.ts +126 -0
  587. package/src/settings/settings-provider.ts +82 -0
  588. package/src/settings-store.ts +345 -0
  589. package/src/shared-view-restore.ts +42 -0
  590. package/src/shell-store-door.ts +45 -0
  591. package/src/source-conflict.ts +122 -0
  592. package/src/spatial-handle-visuals.ts +332 -0
  593. package/src/stage-context.ts +341 -0
  594. package/src/stage-store-registry.ts +63 -0
  595. package/src/stale-chunk-recovery.ts +34 -0
  596. package/src/state-report-deferral.ts +73 -0
  597. package/src/storage/host-files-storage.ts +97 -0
  598. package/src/storage/http-storage.ts +174 -0
  599. package/src/storage/index.ts +75 -0
  600. package/src/storage/mem-storage.ts +149 -0
  601. package/src/storage/path-lock.ts +44 -0
  602. package/src/storage/paths.ts +26 -0
  603. package/src/storage/types.ts +116 -0
  604. package/src/stories/StoryComponentThumbnail.tsx +184 -0
  605. package/src/stories/StoryPreviewMount.tsx +306 -0
  606. package/src/stories/component-content-source.tsx +106 -0
  607. package/src/stories/component-states-source.ts +78 -0
  608. package/src/stories/compose-project-stories.ts +255 -0
  609. package/src/stories/pixi-story-model.ts +30 -0
  610. package/src/stories/prefabs-finder.ts +54 -0
  611. package/src/stories/prefabs-from-stories.ts +182 -0
  612. package/src/stories/project-story-discovery.ts +78 -0
  613. package/src/stories/project-story-regions.ts +24 -0
  614. package/src/stories/story-actions.ts +54 -0
  615. package/src/stories/story-capture-command.ts +124 -0
  616. package/src/stories/story-capture.ts +584 -0
  617. package/src/stories/story-declared-medium.ts +126 -0
  618. package/src/stories/story-discovery.ts +176 -0
  619. package/src/stories/story-document-openers.ts +36 -0
  620. package/src/stories/story-dom-runtime.ts +78 -0
  621. package/src/stories/story-grouping.ts +111 -0
  622. package/src/stories/story-lane.ts +88 -0
  623. package/src/stories/story-mount-turn.ts +27 -0
  624. package/src/stories/story-opener.ts +260 -0
  625. package/src/stories/story-pixi-preview.ts +408 -0
  626. package/src/stories/story-presentation.ts +215 -0
  627. package/src/stories/story-registry.ts +517 -0
  628. package/src/stories/story-three-preview.ts +807 -0
  629. package/src/stories/three-story-model.ts +96 -0
  630. package/src/story-three-preview-runtime.ts +56 -0
  631. package/src/surface-keyboard.ts +112 -0
  632. package/src/surface-state.ts +124 -0
  633. package/src/tab-bootstrap.js +628 -0
  634. package/src/tab-census.ts +198 -0
  635. package/src/tab-lifecycle-client.ts +196 -0
  636. package/src/theme-library.ts +844 -0
  637. package/src/theme-preference.ts +378 -0
  638. package/src/theme.css +3437 -0
  639. package/src/three-viewport/bone-selection-highlight.ts +119 -0
  640. package/src/three-viewport/camera-fit.ts +41 -0
  641. package/src/three-viewport/interactive-renderer.ts +132 -0
  642. package/src/three-viewport/selection-brackets.ts +310 -0
  643. package/src/three-viewport/selection-outline.ts +183 -0
  644. package/src/three-viewport/skeleton-helper.ts +61 -0
  645. package/src/three-viewport/source-color.ts +167 -0
  646. package/src/three-viewport/studio-environment.ts +96 -0
  647. package/src/three-viewport-presentation.ts +23 -0
  648. package/src/tool-contribution-play.ts +74 -0
  649. package/src/tool-loader.ts +1798 -0
  650. package/src/transform-mode-request.ts +57 -0
  651. package/src/transient-hint.ts +78 -0
  652. package/src/trigger-volume-helper.ts +116 -0
  653. package/src/ui-source/adapter-region-includes.ts +241 -0
  654. package/src/ui-source/ensure-import.ts +132 -0
  655. package/src/ui-source/file-region-resolver.ts +302 -0
  656. package/src/ui-source/inspect.ts +775 -0
  657. package/src/ui-source/oid-transform.ts +1845 -0
  658. package/src/ui-source/plan-csf-story.ts +196 -0
  659. package/src/ui-source/plan-extract-component.ts +421 -0
  660. package/src/ui-source/plan-fork-component.ts +621 -0
  661. package/src/ui-source/plan-named-style.ts +95 -0
  662. package/src/ui-source/plan-source-edit.ts +353 -0
  663. package/src/ui-source/r3f-contract-resolver.ts +327 -0
  664. package/src/ui-source/r3f-diagnostic-index.ts +165 -0
  665. package/src/ui-source/r3f-environment-binding.ts +133 -0
  666. package/src/ui-source/r3f-joint-binding.ts +251 -0
  667. package/src/ui-source/r3f-lod-binding.ts +91 -0
  668. package/src/ui-source/r3f-particle-binding.ts +235 -0
  669. package/src/ui-source/r3f-physics-binding.ts +483 -0
  670. package/src/ui-source/r3f-project-contracts.ts +444 -0
  671. package/src/ui-source/relative-import-specifier.ts +34 -0
  672. package/src/ui-source/reparent-guard.ts +544 -0
  673. package/src/ui-source/source-edit-request.ts +97 -0
  674. package/src/ui-source/source-write-backend.ts +618 -0
  675. package/src/ui-source/syntactic-prop-specs.ts +296 -0
  676. package/src/ui-source/tier-source-write-backend.ts +279 -0
  677. package/src/ui-source/ts-ast.ts +171 -0
  678. package/src/ui-source/utility-class-support.ts +169 -0
  679. package/src/ui-source/write-component-default.ts +133 -0
  680. package/src/ui-source/writer.ts +1989 -0
  681. package/src/viewport-activation-timings.ts +840 -0
  682. package/src/viewport-authoring-policy.ts +186 -0
  683. package/src/viewport-controls-hint.ts +57 -0
  684. package/src/viewport-door.ts +237 -0
  685. package/src/viewport-shading-boundary.ts +12 -0
  686. package/src/vite-error-surface.ts +141 -0
  687. package/src/wait-until.ts +37 -0
  688. package/src/workspace-areas.ts +156 -0
  689. package/src/workspace-aux-commands.ts +11 -0
  690. package/src/workspace-available-documents.ts +127 -0
  691. package/src/workspace-core-utilities.ts +31 -0
  692. package/src/workspace-document-ids.ts +59 -0
  693. package/src/workspace-document-registry.ts +612 -0
  694. package/src/workspace-document-restore.ts +145 -0
  695. package/src/workspace-host-commands.ts +141 -0
  696. package/src/workspace-persistence-gate.ts +40 -0
  697. package/src/workspace-play-utilities.ts +44 -0
  698. package/src/workspace-presets.ts +425 -0
  699. package/src/workspace-regions.ts +294 -0
  700. package/src/workspace-state-persistence.ts +536 -0
  701. package/src/workspace-static-panels.ts +73 -0
  702. package/src/workspace-status-registry.ts +121 -0
  703. package/src/workspace-style.ts +239 -0
  704. package/src/workspace-utility-commands.ts +74 -0
  705. package/src/workspace-utility-registry.ts +263 -0
  706. package/src/workspace-viewport-rect.ts +97 -0
  707. package/src/world-adoption.ts +115 -0
  708. package/src/world-document-routing.ts +104 -0
  709. package/vite-plugin-creation-site-write.ts +184 -0
  710. package/vite-plugin-creation-site.ts +80 -0
  711. package/vite-plugin-game-static.ts +303 -0
  712. package/vite-plugin-module-doorways.ts +336 -0
  713. package/vite-plugin-product-contributions.ts +197 -0
  714. package/vite-plugin-project-game-static.ts +125 -0
  715. package/vite-plugin-project-jsx-js.ts +65 -0
  716. package/vite-plugin-project-root-absolute-assets.ts +359 -0
  717. package/vite-plugin-shared-react.ts +420 -0
  718. package/vite-plugin-shared-three.ts +203 -0
  719. package/vite-plugin-ui-oid.ts +2106 -0
@@ -0,0 +1,204 @@
1
+ /**
2
+ * AlignToolbar — spec 27 §6 D4.b multi-select align/distribute toolbar:
3
+ * shown when ≥2 world nodes are selected (align) / ≥3 (distribute), floating
4
+ * above the selection's union bounding box. `RootSelectionOverlay.tsx`
5
+ * decides WHEN this renders (its own `computeMultiSelectionAlign` capability
6
+ * gate — every selected id must resolve both a rect AND an owning
7
+ * `boxEdit`); this component owns only the button UI + routing a click
8
+ * through the contract.
9
+ *
10
+ * Rule zero (spec §0): this file talks ONLY to the `AuthoringAdapter`
11
+ * contract, via the SAME owner-routing helper (`boxEditForId`) the B2/B3
12
+ * gesture code already uses — no store reach-in, no `THREE.`, no
13
+ * `elementFromPoint`. The align/distribute MATH itself is the pure,
14
+ * independently-tested `computeAlignTargets`/`computeDistributeTargets` in
15
+ * `world-overlay-gestures.ts` — this file only maps their output onto a
16
+ * `begin`/`apply`/`end` bracket per node (spec:301 "one undo step each").
17
+ */
18
+
19
+ import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
20
+ import {
21
+ faAlignCenter,
22
+ faAlignLeft,
23
+ faAlignRight,
24
+ faGripLines,
25
+ faGripLinesVertical,
26
+ } from '@fortawesome/free-solid-svg-icons';
27
+ import {
28
+ EditorIcon,
29
+ FloatingToolbar,
30
+ IconButton,
31
+ ToolbarDivider,
32
+ zIndex,
33
+ } from '@volter/editor-sdk/widgets';
34
+ import type { AuthoringAdapter } from '@volter/editor-project/adapter';
35
+ import {
36
+ type AlignEntry,
37
+ type AlignOp,
38
+ type AlignTarget,
39
+ boxEditForId,
40
+ computeAlignTargets,
41
+ computeDistributeTargets,
42
+ type DistributeAxis,
43
+ type RectLike,
44
+ unionRect,
45
+ } from './world-overlay-gestures';
46
+
47
+ export interface AlignToolbarProps {
48
+ adapter: AuthoringAdapter;
49
+ /** The current selection's id+rect pairs — already capability-checked by
50
+ * the caller (every id here has a resolvable owner `boxEdit`). */
51
+ entries: readonly AlignEntry[];
52
+ }
53
+
54
+ /** Route every {@link AlignTarget} through its owning `boxEdit`
55
+ * (begin/apply/end — one undo step per node, per B1/D-1) — the ONE place
56
+ * align/distribute clicks touch the adapter contract. Targets whose owner
57
+ * has no `boxEdit` (shouldn't happen given the caller's capability gate,
58
+ * but honest regardless — see `boxEditForId`'s own `null` contract) are
59
+ * silently skipped rather than throwing. */
60
+ function commitAlignTargets(adapter: AuthoringAdapter, targets: readonly AlignTarget[]): void {
61
+ for (const t of targets) {
62
+ const boxEdit = boxEditForId(adapter, t.id);
63
+ if (!boxEdit) continue;
64
+ const patch: Record<string, number> = {};
65
+ if (t.x !== undefined) patch['x'] = t.x;
66
+ if (t.y !== undefined) patch['y'] = t.y;
67
+ if (Object.keys(patch).length === 0) continue;
68
+ boxEdit.begin(t.id);
69
+ boxEdit.apply(t.id, patch);
70
+ boxEdit.end(t.id);
71
+ }
72
+ }
73
+
74
+ /**
75
+ * L-7 — every other icon in this rail is a FontAwesome glyph; this toolbar
76
+ * was the one holdout still rendering raw Unicode math symbols (`⊢`, `⊣⊢`,
77
+ * `⊤`, `⇔`, …), which clash in weight/centering with the FA icon language
78
+ * used everywhere else. FontAwesome Free's solid set has no dedicated
79
+ * object-bbox align/distribute icons (only the 4 paragraph-align glyphs;
80
+ * verified — no `faDistribute*`/`faAlignTop`/etc. exist in
81
+ * `@fortawesome/free-solid-svg-icons`), so the vertical variants reuse the
82
+ * horizontal align glyphs rotated 90° (`rotate` below) — the same technique
83
+ * several icon sets use to derive a vertical-align glyph from a horizontal
84
+ * one — and distribute reuses the evenly-spaced-bars grip glyphs. Still a
85
+ * strict style-only swap: same meaning, same button size, one consistent
86
+ * icon family instead of a second, unrelated glyph language.
87
+ */
88
+ const ALIGN_BUTTONS: ReadonlyArray<{
89
+ op: AlignOp;
90
+ testId: string;
91
+ label: string;
92
+ icon: IconDefinition;
93
+ rotate?: boolean;
94
+ }> = [
95
+ { op: 'left', testId: 'align-left', label: 'Align left', icon: faAlignLeft },
96
+ { op: 'hcenter', testId: 'align-hcenter', label: 'Align horizontal center', icon: faAlignCenter },
97
+ { op: 'right', testId: 'align-right', label: 'Align right', icon: faAlignRight },
98
+ { op: 'top', testId: 'align-top', label: 'Align top', icon: faAlignLeft, rotate: true },
99
+ {
100
+ op: 'vcenter',
101
+ testId: 'align-vcenter',
102
+ label: 'Align vertical center',
103
+ icon: faAlignCenter,
104
+ rotate: true,
105
+ },
106
+ { op: 'bottom', testId: 'align-bottom', label: 'Align bottom', icon: faAlignRight, rotate: true },
107
+ ];
108
+
109
+ const DISTRIBUTE_BUTTONS: ReadonlyArray<{
110
+ axis: DistributeAxis;
111
+ testId: string;
112
+ label: string;
113
+ icon: IconDefinition;
114
+ }> = [
115
+ {
116
+ axis: 'horizontal',
117
+ testId: 'distribute-horizontal',
118
+ label: 'Distribute horizontally',
119
+ icon: faGripLinesVertical,
120
+ },
121
+ {
122
+ axis: 'vertical',
123
+ testId: 'distribute-vertical',
124
+ label: 'Distribute vertically',
125
+ icon: faGripLines,
126
+ },
127
+ ];
128
+
129
+ /** Where the toolbar floats: centered above `bbox`, clamped so it never
130
+ * renders with a negative `top` (a selection near the host's own top edge
131
+ * still gets a visible toolbar, pinned just under the selection instead of
132
+ * off-screen above it). Pure; exported mainly for the e2e/visual read, not
133
+ * itself independently unit-tested (position is presentation, not the
134
+ * align/distribute MATH this task's acceptance criteria target). */
135
+ function toolbarPosition(bbox: RectLike): { left: number; top: number } {
136
+ const height = 30;
137
+ const margin = 8;
138
+ const top = bbox.y - height - margin;
139
+ return { left: bbox.x, top: top < 0 ? bbox.y + bbox.height + margin : top };
140
+ }
141
+
142
+ export function AlignToolbar({ adapter, entries }: AlignToolbarProps): React.ReactNode {
143
+ if (entries.length < 2) return null;
144
+ const bbox = unionRect(entries.map((e) => e.rect));
145
+ if (!bbox) return null;
146
+ const { left, top } = toolbarPosition(bbox);
147
+ const canDistribute = entries.length >= 3;
148
+
149
+ return (
150
+ // U6a (P6 glass-native chrome): the one floating tool cluster that still
151
+ // hand-rolled an opaque chrome slab — now the shared `FloatingToolbar`
152
+ // island (var-driven `--vgai-island-*` material, refraction-upgradable
153
+ // via `vgai-glass-island`; treatment-less themes emit the pre-P6 recipe
154
+ // through the same vars). Geometry/placement stays inline.
155
+ <FloatingToolbar
156
+ label="Align and distribute"
157
+ data-testid="align-toolbar"
158
+ style={{
159
+ position: 'absolute',
160
+ left,
161
+ top,
162
+ zIndex: zIndex.overlayLow,
163
+ gap: 2,
164
+ padding: 3,
165
+ }}
166
+ >
167
+ {ALIGN_BUTTONS.map(({ op, testId, label, icon, rotate }) => (
168
+ <IconButton
169
+ key={op}
170
+ data-testid={testId}
171
+ title={label}
172
+ aria-label={label}
173
+ variant="ghost"
174
+ size="compact"
175
+ onClick={() => commitAlignTargets(adapter, computeAlignTargets(entries, op))}
176
+ >
177
+ <EditorIcon
178
+ icon={icon}
179
+ aria-hidden="true"
180
+ style={rotate ? { transform: 'rotate(90deg)' } : undefined}
181
+ />
182
+ </IconButton>
183
+ ))}
184
+ {canDistribute && (
185
+ <>
186
+ <ToolbarDivider />
187
+ {DISTRIBUTE_BUTTONS.map(({ axis, testId, label, icon }) => (
188
+ <IconButton
189
+ key={axis}
190
+ data-testid={testId}
191
+ title={label}
192
+ aria-label={label}
193
+ variant="ghost"
194
+ size="compact"
195
+ onClick={() => commitAlignTargets(adapter, computeDistributeTargets(entries, axis))}
196
+ >
197
+ <EditorIcon icon={icon} aria-hidden="true" />
198
+ </IconButton>
199
+ ))}
200
+ </>
201
+ )}
202
+ </FloatingToolbar>
203
+ );
204
+ }
@@ -0,0 +1,394 @@
1
+ /**
2
+ * AppRoot — the editor's own tree, and what it shows before the project is
3
+ * readable: a loading surface while detection runs, a startup ERROR surface
4
+ * when it definitively fails, the editor when it succeeds. Only a DEFINITE bad
5
+ * answer counts as a failure — "the server has not answered yet" keeps asking
6
+ * (`decideProjectDetectionRecovery`), because a tab that is merely still
7
+ * booting must never settle into a terminal screen with no listener on it.
8
+ *
9
+ * THERE IS NO PROJECT PICKER. A session serves ONE project — `vgai edit <dir>`
10
+ * is how you choose it, and the workbench's own Open Folder is how you leave —
11
+ * so a page that has no project has nothing to offer but the sentence saying
12
+ * so. The picker, its New Project wizard, its `?create-from=` deep link and
13
+ * the "Switch Project…" route back to it are all gone with the standalone
14
+ * page they lived on.
15
+ *
16
+ * This component also holds the page's SESSION PRESENCE: one SSE connection
17
+ * for the lifetime of the page, whatever surface is on screen, plus a report
18
+ * of WHICH surface that is. Presence belongs at the root because the fact it
19
+ * asserts — this page is attached to this session — is true at the root, not
20
+ * inside the editor.
21
+ *
22
+ * Key principle: No Three.js, no EditorShellStore, no RAF loop until a project
23
+ * is readable.
24
+ */
25
+
26
+ import { editorDocumentTitle } from '@volter/editor-sdk/session/editor-brand';
27
+ import {
28
+ ProjectCompatibilityError,
29
+ type StartupRecovery,
30
+ } from '@volter/editor-sdk/session/editor-compatibility';
31
+ import { Component, type ErrorInfo, type ReactNode, useEffect, useState } from 'react';
32
+ import { startAccountActivity } from '../account';
33
+ import {
34
+ decideProjectDetectionRecovery,
35
+ ProjectDetectionTimeoutError,
36
+ ServerProjectDetectionError,
37
+ type ServerProjectFailureReport,
38
+ } from '../boot-routing';
39
+ import { EditorProvider } from '../EditorContext';
40
+ import { editorConsole } from '../editor-console';
41
+ import { connectTabPresence, reportTabRoute } from '../editor-presence';
42
+ import { type ActiveProject, detectProject } from '../project-manager';
43
+ import { onTabAdopt } from '../tab-lifecycle-client';
44
+ import { DefaultEditorLayout } from './DefaultEditorLayout';
45
+ import { EditorLeaseGuard } from './EditorLeaseGuard';
46
+ import { StartupErrorScreen } from './StartupErrorScreen';
47
+ import { StartupLoadingScreen } from './StartupLoadingScreen';
48
+
49
+ type State =
50
+ | {
51
+ status: 'detecting';
52
+ /** When the CURRENT run of attempts began, or null while the first
53
+ * attempt is still in flight — an instant boot must not flash a
54
+ * "we're waiting" surface it will never need. */
55
+ waitingSince: number | null;
56
+ /** The last failed attempt's message, shown verbatim while we re-ask. */
57
+ lastError?: string;
58
+ }
59
+ | { status: 'no-project'; returnProject?: ActiveProject }
60
+ | {
61
+ status: 'error';
62
+ message: string;
63
+ recovery?: StartupRecovery;
64
+ report?: ServerProjectFailureReport;
65
+ }
66
+ | { status: 'ready'; project: ActiveProject };
67
+
68
+ interface EditorRuntimeBoundaryProps {
69
+ readonly children: ReactNode;
70
+ }
71
+
72
+ /**
73
+ * Keep the application-level EditorProvider alive when editor chrome throws.
74
+ * The provider owns the command listener, so letting an unwrapped descendant
75
+ * error unmount it leaves a still-beating tab that can no longer answer
76
+ * `vgai status`, `play`, or recovery commands. The fallback is deliberately a
77
+ * normal startup-error surface inside the provider: Retry re-renders the
78
+ * chrome; Project Browser remains reachable; the listener never goes away.
79
+ */
80
+ class EditorRuntimeBoundary extends Component<
81
+ EditorRuntimeBoundaryProps,
82
+ { readonly error: Error | null }
83
+ > {
84
+ override state: { readonly error: Error | null } = { error: null };
85
+
86
+ static getDerivedStateFromError(error: Error): { readonly error: Error } {
87
+ return { error };
88
+ }
89
+
90
+ override componentDidCatch(error: Error, info: ErrorInfo): void {
91
+ editorConsole.error(
92
+ `Editor chrome crashed while the command listener stayed attached: ${error.message}\n${info.componentStack ?? ''}`,
93
+ 'editor',
94
+ );
95
+ }
96
+
97
+ override render(): ReactNode {
98
+ if (!this.state.error) return this.props.children;
99
+ return (
100
+ <StartupErrorScreen
101
+ error={{ message: `The editor surface crashed: ${this.state.error.message}` }}
102
+ onRetry={() => this.setState({ error: null })}
103
+ />
104
+ );
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Every surface this app can show, wrapped so the supervised lease
110
+ * (`EditorLeaseGuard` / `editor-lease.ts`) is mounted on ALL of them.
111
+ *
112
+ * It used to be mounted on exactly one — a child of `EditorRuntimeBoundary`
113
+ * inside the `ready` branch — which put the watchdog in the only place a
114
+ * failing server tends not to leave the user. A server that dies while the
115
+ * launcher is up, or that takes the boot probe down with it onto the error
116
+ * screen, or that makes some piece of chrome throw and so trips the boundary
117
+ * into replacing its children (the watchdog among them, permanently), produced
118
+ * a page with no supervision at all: fully rendered, perfectly healthy-looking,
119
+ * and never going to say otherwise. The surfaces a dead server actually
120
+ * produces were the ones not watching for it.
121
+ *
122
+ * Being OUTSIDE the boundary is half the point and not an accident of
123
+ * nesting: the guard's whole job is to survive the failures that break the
124
+ * editor, so it must not be something the editor's own crash can unmount. It
125
+ * needs no context and mounts nothing but a portal, so there is nothing for it
126
+ * to be inside of.
127
+ */
128
+ function EditorSurface({ children }: { readonly children: ReactNode }) {
129
+ return (
130
+ <>
131
+ {children}
132
+ <EditorLeaseGuard />
133
+ </>
134
+ );
135
+ }
136
+
137
+ function startupFailure(error: unknown): Extract<State, { status: 'error' }> {
138
+ const message = error instanceof Error ? error.message : String(error);
139
+ if (error instanceof ProjectCompatibilityError) {
140
+ return { status: 'error', message, recovery: error.recovery };
141
+ }
142
+ // A boot probe that failed carries the server's own answer — the served
143
+ // path and the verbatim error — so the surface can name both instead of
144
+ // flattening them into one sentence.
145
+ if (error instanceof ServerProjectDetectionError) {
146
+ return { status: 'error', message, report: error.report };
147
+ }
148
+ return { status: 'error', message };
149
+ }
150
+
151
+ /**
152
+ * How long ONE detection attempt waits before giving up on that attempt.
153
+ *
154
+ * This is a pacing deadline, never a verdict (`decideProjectDetectionRecovery`).
155
+ * Project detection is normally a pair of local fetches and finishes almost
156
+ * immediately, but on the FIRST boot of a fresh checkout — Vite transforming
157
+ * the editor graph cold — it legitimately takes far longer, and the previous
158
+ * code turned that elapsed deadline into a terminal error screen on an
159
+ * otherwise perfectly healthy tab. Abandoning an attempt is still worth doing:
160
+ * a request lost under a cold boot's connection pressure never settles, and
161
+ * re-asking is how it gets un-stuck.
162
+ */
163
+ export const PROJECT_DETECTION_TIMEOUT_MS = 8_000;
164
+
165
+ export function detectProjectWithTimeout(
166
+ detect: () => Promise<ActiveProject | null> = detectProject,
167
+ timeoutMs = PROJECT_DETECTION_TIMEOUT_MS,
168
+ ): Promise<ActiveProject | null> {
169
+ return new Promise((resolve, reject) => {
170
+ const timeout = window.setTimeout(() => {
171
+ reject(new ProjectDetectionTimeoutError(timeoutMs));
172
+ }, timeoutMs);
173
+ detect().then(
174
+ (project) => {
175
+ window.clearTimeout(timeout);
176
+ resolve(project);
177
+ },
178
+ (error: unknown) => {
179
+ window.clearTimeout(timeout);
180
+ reject(error);
181
+ },
182
+ );
183
+ });
184
+ }
185
+
186
+ /** Read + shape-check the `?create-from=` deep-link param (G4). Returns the
187
+ * candidate id, or null when absent/malformed. Ids share the example-folder
188
+ * shape (`hosted-example.ts`'s gate); a malformed value is treated as absent
189
+ * at the routing layer — the WIZARD still opens (the user's intent to create
190
+ * was explicit), with a non-blocking unknown-id notice. */
191
+ export function createFromParam(search: string): string | null {
192
+ const raw = new URLSearchParams(search).get('create-from');
193
+ if (raw === null) return null;
194
+ return raw.trim() || null;
195
+ }
196
+
197
+ /** Attempts before a still-retrying detection reports itself to the console. */
198
+ const PROJECT_DETECTION_REPORT_AFTER = 3;
199
+
200
+ export function AppRoot() {
201
+ const [state, setState] = useState<State>({ status: 'detecting', waitingSince: null });
202
+ const [detectionAttempt, setDetectionAttempt] = useState(0);
203
+
204
+ // Account is product-global. Keep its session current on the Welcome /
205
+ // Project Browser just as in the project editor; project selection must not
206
+ // be a prerequisite for identity or billing management.
207
+ useEffect(() => startAccountActivity(), []);
208
+
209
+ // Session presence for the LIFE OF THE PAGE (see the module docstring): the
210
+ // tab bijection counts tabs, and a tab is a tab on every surface.
211
+ useEffect(() => connectTabPresence(), []);
212
+
213
+ // `tab-adopt`: this tab is the session's one tab but is not on the project.
214
+ // Re-run detection rather than opening a second tab — the same work the
215
+ // Retry button does, which is exactly what adoption means here.
216
+ useEffect(() => onTabAdopt(() => setDetectionAttempt((attempt) => attempt + 1)), []);
217
+
218
+ // Detection RUNS UNTIL IT GETS AN ANSWER. A failure that means "the server
219
+ // has not answered yet" schedules another ask (backoff in boot-routing) and
220
+ // keeps the boot surface up, saying how long it has been waiting; only a
221
+ // definite bad answer lands on the terminal error surface. The alternative —
222
+ // one attempt, one deadline, one verdict — put a healthy tab (beating,
223
+ // echoing, socket up) on a dead-end screen with no command listener for the
224
+ // entire cold first boot of a fresh checkout.
225
+ useEffect(() => {
226
+ let cancelled = false;
227
+ let retryTimer: number | undefined;
228
+ let failures = 0;
229
+ const startedAt = Date.now();
230
+ setState({ status: 'detecting', waitingSince: null });
231
+
232
+ const ask = () => {
233
+ detectProjectWithTimeout().then(
234
+ (project) => {
235
+ if (cancelled) return;
236
+ if (project) {
237
+ setState({ status: 'ready', project });
238
+ } else {
239
+ setState({ status: 'no-project' });
240
+ }
241
+ },
242
+ (error: unknown) => {
243
+ if (cancelled) return;
244
+ failures += 1;
245
+ const recovery = decideProjectDetectionRecovery(error, failures);
246
+ if (recovery.kind === 'terminal') {
247
+ const failure = startupFailure(error);
248
+ // A TERMINAL failure renders `StartupErrorScreen` in the tab and,
249
+ // until now, nothing else: the tab beat, reported `no-project`,
250
+ // attached no command listener, and every session door read that
251
+ // as a healthy cold boot (`vgai status`: "commandListener not
252
+ // attached"). Measured 2026-09-17 on two sessions at once — a
253
+ // project pinned below the editor's engine, and an editor server
254
+ // older than the project it served — both invisible for an hour.
255
+ // The console is server-held, so this reaches `vgai status` and
256
+ // `vgai console` whether or not anyone looks at the tab.
257
+ const command =
258
+ failure.recovery && 'command' in failure.recovery ? failure.recovery.command : null;
259
+ editorConsole.error(
260
+ `Startup failed: ${failure.message}${command ? ` Run: ${command}` : ''}`,
261
+ 'editor',
262
+ );
263
+ setState(failure);
264
+ return;
265
+ }
266
+ const reason = error instanceof Error ? error.message : String(error);
267
+ // A RETRY THAT NEVER SUCCEEDS IS INVISIBLE FROM OUTSIDE. The boot
268
+ // surface says how long it has been waiting, on screen; every other
269
+ // door -- `vgai status`, the session journal -- sees only
270
+ // `route: unknown` and a tab with no command listener, which is also
271
+ // what a healthy cold boot looks like. A project pinned to an older
272
+ // engine than the editor throws here on EVERY attempt, and the tab
273
+ // then waits for something that cannot change, silently.
274
+ //
275
+ // So the reason goes to the editor console, which the server holds
276
+ // and `vgai console` prints whether or not this page ever mounts.
277
+ // Once, on the attempt the patient loop stops being patient about.
278
+ if (failures === PROJECT_DETECTION_REPORT_AFTER) {
279
+ editorConsole.error(
280
+ `Project detection has failed ${failures} times and is still retrying: ${reason}`,
281
+ 'editor',
282
+ );
283
+ }
284
+ setState({
285
+ status: 'detecting',
286
+ waitingSince: startedAt,
287
+ lastError: reason,
288
+ });
289
+ retryTimer = window.setTimeout(ask, recovery.delayMs);
290
+ },
291
+ );
292
+ };
293
+ ask();
294
+
295
+ return () => {
296
+ cancelled = true;
297
+ if (retryTimer !== undefined) window.clearTimeout(retryTimer);
298
+ };
299
+ }, [detectionAttempt]);
300
+
301
+ // The waiting clock. Only ticks once detection has actually failed at least
302
+ // once, so an ordinary boot never mounts an interval at all.
303
+ const waitingSince = state.status === 'detecting' ? state.waitingSince : null;
304
+ const [waitedSeconds, setWaitedSeconds] = useState(0);
305
+ useEffect(() => {
306
+ if (waitingSince === null) {
307
+ setWaitedSeconds(0);
308
+ return;
309
+ }
310
+ const tick = () =>
311
+ setWaitedSeconds(Math.max(0, Math.round((Date.now() - waitingSince) / 1000)));
312
+ tick();
313
+ const interval = window.setInterval(tick, 1_000);
314
+ return () => window.clearInterval(interval);
315
+ }, [waitingSince]);
316
+
317
+ // Which surface this tab is showing, reported from the ONE place that
318
+ // decides it. `detecting` says nothing: a booting tab is on its way to the
319
+ // project, and the server reads an unreported route exactly that way. That
320
+ // stays true through the patient retry loop — a tab still asking is still on
321
+ // its way, so `vgai edit` refocuses it rather than opening a second one, and
322
+ // the vocabulary is unchanged.
323
+ useEffect(() => {
324
+ if (state.status === 'detecting') return;
325
+ reportTabRoute(state.status === 'ready' ? 'project' : 'no-project');
326
+ }, [state.status]);
327
+
328
+ const titleSubject =
329
+ state.status === 'ready'
330
+ ? state.project.config.name
331
+ : state.status === 'error'
332
+ ? "Couldn't open project"
333
+ : null;
334
+ useEffect(() => {
335
+ document.title = editorDocumentTitle(titleSubject);
336
+ }, [titleSubject]);
337
+
338
+ if (state.status === 'detecting') {
339
+ return (
340
+ <EditorSurface>
341
+ <StartupLoadingScreen
342
+ wait={
343
+ state.waitingSince === null
344
+ ? undefined
345
+ : { seconds: waitedSeconds, detail: state.lastError }
346
+ }
347
+ />
348
+ </EditorSurface>
349
+ );
350
+ }
351
+
352
+ if (state.status === 'no-project') {
353
+ // A SESSION SERVES ONE PROJECT and this page has none — the folder the
354
+ // workbench opened is not one. There is nothing to pick from here: say
355
+ // which door opens a project and stop.
356
+ return (
357
+ <EditorSurface>
358
+ <StartupErrorScreen
359
+ error={{
360
+ message:
361
+ 'This window has no vgai project open. A session serves one project: open a folder ' +
362
+ 'that carries a vgai.project.json, or start one from a terminal — `volter-editor edit <folder>`.',
363
+ }}
364
+ onRetry={() => setDetectionAttempt((attempt) => attempt + 1)}
365
+ />
366
+ </EditorSurface>
367
+ );
368
+ }
369
+
370
+ if (state.status === 'error') {
371
+ return (
372
+ <EditorSurface>
373
+ <StartupErrorScreen
374
+ error={{
375
+ message: state.message,
376
+ ...(state.recovery ? { recovery: state.recovery } : {}),
377
+ }}
378
+ report={state.report}
379
+ onRetry={() => setDetectionAttempt((attempt) => attempt + 1)}
380
+ />
381
+ </EditorSurface>
382
+ );
383
+ }
384
+
385
+ return (
386
+ <EditorSurface>
387
+ <EditorProvider>
388
+ <EditorRuntimeBoundary>
389
+ <DefaultEditorLayout />
390
+ </EditorRuntimeBoundary>
391
+ </EditorProvider>
392
+ </EditorSurface>
393
+ );
394
+ }