@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,216 @@
1
+ /**
2
+ * The asset document shell — the frame an open asset lives in, and NOTHING
3
+ * about how it is inspected.
4
+ *
5
+ * "What is an asset in three.js but a hierarchical group of other three.js
6
+ * assets" (owner, 2026-08-07). An asset document is the three paradigm scoped
7
+ * to a SUBTREE — Unity's prefab-isolation mode: same viewport, same hierarchy,
8
+ * same inspector box, only the root changed. So the ordinary inspector rides
9
+ * over an asset document exactly as it rides over the scene: the same box in
10
+ * the same corner, draggable, minimizable, expandable to the same column, with
11
+ * the same per-surface preference (`inspection/display.ts` resolves it for the
12
+ * `asset-lab` surface like any other). This shell renders none of it.
13
+ *
14
+ * What it owns is the two things that make the document a SUBJECT PRODUCER:
15
+ *
16
+ * - it activates the asset-editor context, which is what makes the active
17
+ * inspection surface `asset-lab` (`inspection/active-surface.ts`);
18
+ * - it registers the document's SELECTION CONTEXT and publishes the
19
+ * document's own subject description (`inspection/document-subject.ts`).
20
+ *
21
+ * The selection context is the load-bearing half, and every asset document
22
+ * registers one even with nothing to select. Registering it is how a document
23
+ * says "I am the subject": without it the Inspector falls back to the shared
24
+ * entity selection, and an image viewer would show whatever was picked in the
25
+ * scene before it was opened. A document with live authoring of its own (the
26
+ * Object3D editor) passes `selection` and its picked part flows through; a
27
+ * document without passes nothing and gets `{adapter: null, nodeId: null}`,
28
+ * which resolves to its own identity floor.
29
+ *
30
+ * The identity row is where that floor lives: even a document with no sections
31
+ * at all says what it is, what kind it is, and where it came from — and no
32
+ * section of its own stands in for that row, because identity is a property of
33
+ * the SUBJECT (`inspection/model.ts`).
34
+ */
35
+
36
+ import { type ReactNode, useEffect, useRef } from 'react';
37
+ import { activateAssetEditorContext } from '../asset-editor-context';
38
+ import { publishDocumentInspectionSubject } from '../inspection/document-subject';
39
+ import type { InspectionSection } from '../inspection/model';
40
+ import type { NullInspectionSubject } from '../inspection/null-subject';
41
+ import {
42
+ registerWorkspaceDocumentSelection,
43
+ type WorkspaceDocumentSelection,
44
+ } from '../workspace-document-registry';
45
+
46
+ /** What a document with no authoring of its own selects: itself. */
47
+ const DOCUMENT_IS_THE_SUBJECT: WorkspaceDocumentSelection = { adapter: null, nodeId: null };
48
+
49
+ /**
50
+ * The part of a document subject whose change can alter the Inspector's
51
+ * structure. Function identities deliberately stay out of this key: render
52
+ * functions and field IO are read through `descriptionRef` below, so a parent
53
+ * render updates them without feeding the Inspector's own notification back
54
+ * into another publication.
55
+ */
56
+ function subjectPublicationKey(subject: NullInspectionSubject): string {
57
+ return JSON.stringify({
58
+ id: subject.id,
59
+ title: subject.title,
60
+ hint: subject.hint,
61
+ kindLabel: subject.kindLabel,
62
+ note: subject.note,
63
+ sections: subject.sections.map((section) => ({
64
+ id: section.id,
65
+ title: section.title,
66
+ order: section.order,
67
+ description: section.description,
68
+ defaultOpen: section.defaultOpen,
69
+ testId: section.testId,
70
+ keepMounted: section.keepMounted,
71
+ railGroup: section.railGroup,
72
+ bodyKind: section.body.kind,
73
+ })),
74
+ quickActions: subject.quickActions?.map((action) => ({
75
+ id: action.id,
76
+ title: action.title,
77
+ label: action.label,
78
+ placement: action.placement,
79
+ pressed: action.pressed,
80
+ disabled: action.disabled,
81
+ })),
82
+ });
83
+ }
84
+
85
+ /**
86
+ * The three optional props below are spelled `?: T | undefined` rather than
87
+ * `?: T`, because `AssetEditorShell` PASSES ITS OWN THROUGH: under
88
+ * `exactOptionalPropertyTypes` an explicit `undefined` is not the same as an
89
+ * absent key, so `sections={sections}` on a shell whose own `sections` is
90
+ * optional is a type error against `?: T`. Undefined is a value this component
91
+ * genuinely handles (`sections ?? []`, `status &&`, `selection?.()`) — the
92
+ * widened type says that, where a conditional spread at the one call site would
93
+ * only hide it.
94
+ */
95
+ interface AssetEditorSubjectProps {
96
+ documentId: string;
97
+ active?: boolean;
98
+ type: string;
99
+ title: string;
100
+ /** This document's own inspection sections, for the subject it publishes
101
+ * when nothing inside it is picked. Identity (name/kind/provenance) is
102
+ * composed from `title`/`type`/`status` — a document always has one, even
103
+ * with no sections at all. */
104
+ sections?: readonly InspectionSection[] | undefined;
105
+ status?: string | undefined;
106
+ /** What is picked INSIDE this document, for a document with authoring of
107
+ * its own. Read on demand (the registry calls it), so it may close over
108
+ * live state that changes without re-registering. */
109
+ selection?: (() => WorkspaceDocumentSelection | null) | undefined;
110
+ }
111
+
112
+ /**
113
+ * The non-visual half of an Asset Lab document. Kept separate from the frame
114
+ * so project-owned contribution UIs can publish the standard subject without
115
+ * sending React elements across the project/editor runtime boundary.
116
+ */
117
+ export function AssetEditorSubject({
118
+ documentId,
119
+ active = true,
120
+ type,
121
+ title,
122
+ sections,
123
+ status,
124
+ selection,
125
+ }: AssetEditorSubjectProps) {
126
+ useEffect(() => {
127
+ if (!active) return;
128
+ return activateAssetEditorContext({
129
+ documentId,
130
+ title,
131
+ type,
132
+ ...(status ? { status } : {}),
133
+ });
134
+ }, [active, documentId, status, title, type]);
135
+
136
+ // ONE owner for this document's selection context (the registry keys by
137
+ // document id, so a second registrant would silently displace the first and
138
+ // take the entry with it on unmount). The ref keeps the registration stable
139
+ // while the provider it delegates to is free to change every render.
140
+ const selectionRef = useRef(selection);
141
+ selectionRef.current = selection;
142
+ useEffect(() => {
143
+ if (!active) return;
144
+ return registerWorkspaceDocumentSelection(
145
+ documentId,
146
+ () => selectionRef.current?.() ?? DOCUMENT_IS_THE_SUBJECT,
147
+ );
148
+ }, [active, documentId]);
149
+
150
+ // The document's subject DESCRIPTION — identity plus its own sections, in
151
+ // the same shape every surface's `describeSubject(null)` answer takes.
152
+ // The latest description is read on demand, so section IO closures remain
153
+ // live without publishing on every render. Publishing itself notifies the
154
+ // Inspector; doing it after every Inspector-driven parent render creates a
155
+ // notification -> render -> publication loop and React eventually throws
156
+ // "Maximum update depth exceeded" when an Object3D prefab opens.
157
+ const description: NullInspectionSubject = {
158
+ id: documentId,
159
+ title,
160
+ // `kindLabel` is what earns the composed identity ROW, and a document
161
+ // always names its kind: an Asset Lab document IS a thing with a name, a
162
+ // type and a provenance.
163
+ kindLabel: type,
164
+ ...(status ? { note: { text: status, testId: 'asset-editor-status' } } : {}),
165
+ sections: sections ?? [],
166
+ };
167
+ const descriptionRef = useRef(description);
168
+ descriptionRef.current = description;
169
+ const publicationKey = subjectPublicationKey(description);
170
+ useEffect(() => {
171
+ if (!active) return;
172
+ return publishDocumentInspectionSubject(documentId, () => descriptionRef.current);
173
+ }, [active, documentId, publicationKey]);
174
+
175
+ return null;
176
+ }
177
+
178
+ export function AssetEditorShell({
179
+ documentId,
180
+ active = true,
181
+ type,
182
+ title,
183
+ sections,
184
+ status,
185
+ fill = false,
186
+ selection,
187
+ children,
188
+ }: AssetEditorSubjectProps & {
189
+ /** The child owns the whole viewport box and clips itself (a 3D canvas),
190
+ * rather than flowing and scrolling inside it. */
191
+ fill?: boolean;
192
+ children: ReactNode;
193
+ }) {
194
+ return (
195
+ <section
196
+ className="vgai-asset-editor"
197
+ data-testid={`asset-editor:${type}`}
198
+ aria-label={`${title} Asset Editor`}
199
+ >
200
+ <AssetEditorSubject
201
+ documentId={documentId}
202
+ active={active}
203
+ type={type}
204
+ title={title}
205
+ sections={sections}
206
+ status={status}
207
+ selection={selection}
208
+ />
209
+ <main
210
+ className={`vgai-asset-editor__viewport${fill ? ' vgai-asset-editor__viewport--fill' : ''}`}
211
+ >
212
+ {children}
213
+ </main>
214
+ </section>
215
+ );
216
+ }
@@ -0,0 +1,124 @@
1
+ import type {
2
+ ToolAssetInspectorAction,
3
+ ToolAssetInspectorContributionProps,
4
+ ToolContributionAsset,
5
+ } from '@volter/editor-sdk/contributions';
6
+ import { EditorIcon, editorIcons, groupLabelStyle } from '@volter/editor-sdk/widgets';
7
+ import { type ComponentType, useCallback, useEffect, useRef, useSyncExternalStore } from 'react';
8
+ import { accountVersion, contributionAccount, subscribeAccount } from '../account';
9
+ import { clearAssetInspectorActions, setAssetInspectorActions } from '../asset-inspector-actions';
10
+ import {
11
+ assetSelectionVersion,
12
+ getSelectedAsset,
13
+ subscribeAssetSelection,
14
+ } from '../asset-selection';
15
+ import { notify } from '../editor-notifications';
16
+ import { beginPageWork } from '../play-boot-phase';
17
+ import type { ProjectToolCatalogEntry } from '../project-tools';
18
+ import {
19
+ subscribeToolContributionPlay,
20
+ toolContributionPlay,
21
+ toolContributionPlayKey,
22
+ } from '../tool-contribution-play';
23
+ import { getToolContributionClient } from '../tool-loader';
24
+ import { toolContributionSurfaces } from './ToolContributionSurfaces';
25
+ import { ToolErrorBoundary } from './ToolHost';
26
+
27
+ function selectedAsset(): ToolContributionAsset | null {
28
+ const asset = getSelectedAsset();
29
+ if (!asset) return null;
30
+ return {
31
+ path: asset.path,
32
+ name: asset.name,
33
+ kind: asset.kind,
34
+ origin: asset.origin ?? 'project',
35
+ ...(asset.sourcePath ? { sourcePath: asset.sourcePath } : {}),
36
+ };
37
+ }
38
+
39
+ /** Publish this section's verbs while it is mounted, and forget them when it
40
+ * goes away — a list that outlived its section would be a verb the human
41
+ * can no longer see (`asset-inspector-actions.ts`). */
42
+ function useAssetInspectorActions(
43
+ id: string,
44
+ assetPath: string | null,
45
+ ): (actions: readonly ToolAssetInspectorAction[]) => void {
46
+ useEffect(() => () => clearAssetInspectorActions(id), [id]);
47
+ return useCallback(
48
+ (actions: readonly ToolAssetInspectorAction[]) => {
49
+ if (assetPath === null) return;
50
+ setAssetInspectorActions(id, assetPath, actions);
51
+ },
52
+ [id, assetPath],
53
+ );
54
+ }
55
+
56
+ export function AssetInspectorToolSection({
57
+ id,
58
+ title,
59
+ file,
60
+ tool,
61
+ Component,
62
+ }: {
63
+ id: string;
64
+ title: string;
65
+ file: string;
66
+ tool?: ProjectToolCatalogEntry | undefined;
67
+ Component: ComponentType<ToolAssetInspectorContributionProps>;
68
+ }) {
69
+ useSyncExternalStore(subscribeAssetSelection, assetSelectionVersion);
70
+ useSyncExternalStore(subscribeAccount, accountVersion, accountVersion);
71
+ useSyncExternalStore(
72
+ subscribeToolContributionPlay,
73
+ toolContributionPlayKey,
74
+ toolContributionPlayKey,
75
+ );
76
+ const asset = selectedAsset();
77
+ const setActions = useAssetInspectorActions(id, asset?.path ?? null);
78
+ // The same two host doors ToolHost hands every other contribution: a
79
+ // notice card keyed by title, and the main-thread work announcement. This
80
+ // section assembled its own props and had neither, so a model probe that
81
+ // spun the page for 45 s stalled every command with no phase named
82
+ // (2026-09-06).
83
+ const endWorkRef = useRef<(() => void) | null>(null);
84
+ const work = useCallback((label: string | null) => {
85
+ endWorkRef.current?.();
86
+ endWorkRef.current =
87
+ label === null ? null : beginPageWork(`building ${label.replace(/^building /, '')}`);
88
+ }, []);
89
+ useEffect(() => () => endWorkRef.current?.(), []);
90
+ const notifyCard = useCallback(
91
+ (notice: { tone: 'info' | 'warning' | 'error'; title: string; detail?: string }) =>
92
+ notify({
93
+ ...notice,
94
+ id: `contribution:${id}:${notice.title}`,
95
+ ...(notice.tone === 'warning' ? { fades: true } : {}),
96
+ }),
97
+ [id],
98
+ );
99
+ return (
100
+ <div
101
+ data-testid={`asset-inspector-tool-${id}`}
102
+ style={{ padding: 8, borderTop: '1px solid var(--vgai-structural-divider)', marginTop: 4 }}
103
+ >
104
+ <div style={{ ...groupLabelStyle, marginBottom: 4 }}>
105
+ <EditorIcon icon={editorIcons.tool.extension} tone="muted" style={{ marginRight: 4 }} />
106
+ {title}
107
+ </div>
108
+ <ToolErrorBoundary file={file}>
109
+ <Component
110
+ {...(tool ? { tool } : {})}
111
+ contributionId={id.slice(id.lastIndexOf(':') + 1)}
112
+ client={getToolContributionClient()}
113
+ surfaces={toolContributionSurfaces}
114
+ account={contributionAccount()}
115
+ play={toolContributionPlay()}
116
+ asset={asset}
117
+ setActions={setActions}
118
+ notify={notifyCard}
119
+ work={work}
120
+ />
121
+ </ToolErrorBoundary>
122
+ </div>
123
+ );
124
+ }
@@ -0,0 +1,354 @@
1
+ /**
2
+ * RULERS + PERSISTENT GUIDES on the DOM component board (design ledger:
3
+ * snapping/guides). Figma's gesture grammar: drag OFF the top ruler to place
4
+ * a horizontal guide, off the left ruler for a vertical one; drag a guide to
5
+ * move it; drop it back on its ruler (or double-click it) to delete. Guides
6
+ * live in BOARD coordinates and persist per project+document
7
+ * (`board-guides.ts`); rendering maps them through the live pan/zoom.
8
+ */
9
+
10
+ import { THEME } from '@volter/editor-sdk/widgets';
11
+ import { type ReactElement, useEffect, useRef, useState, useSyncExternalStore } from 'react';
12
+ import {
13
+ activeBreakpoint,
14
+ setActiveBreakpoint,
15
+ subscribeBreakpoint,
16
+ } from '../authoring/breakpoint-state';
17
+ import { getRootPan, subscribeRootPan } from '../authoring/world-pan-state';
18
+ import {
19
+ addBoardGuide,
20
+ type BoardGuide,
21
+ boardGuides,
22
+ moveBoardGuide,
23
+ registerBoardGuideTransform,
24
+ removeBoardGuide,
25
+ subscribeBoardGuides,
26
+ } from './board-guides';
27
+
28
+ const RULER = 16;
29
+ const GUIDE_COLOR = 'rgba(255, 82, 82, 0.9)';
30
+ const RULER_BG = 'rgba(18, 22, 26, 0.92)';
31
+ const TICK_COLOR = 'rgba(255, 255, 255, 0.28)';
32
+
33
+ /** A round tick step that keeps labels ~≥60px apart at the current zoom. */
34
+ function tickStep(zoom: number): number {
35
+ const steps = [10, 25, 50, 100, 250, 500, 1000, 2500, 5000];
36
+ return steps.find((s) => s * zoom >= 60) ?? 10000;
37
+ }
38
+
39
+ function formatTick(v: number): string {
40
+ return Math.abs(v) >= 1000 ? `${v / 1000}k` : String(v);
41
+ }
42
+
43
+ interface DragState {
44
+ kind: 'place' | 'move';
45
+ axis: BoardGuide['axis'];
46
+ id: string | null;
47
+ /** Container-local pointer coordinate along the guide's axis. */
48
+ at: number;
49
+ }
50
+
51
+ export function BoardRulers({
52
+ docId,
53
+ containerRef,
54
+ }: {
55
+ docId: string;
56
+ containerRef: React.RefObject<HTMLDivElement | null>;
57
+ }): ReactElement {
58
+ const view = useSyncExternalStore(subscribeRootPan, getRootPan);
59
+ const guides = useSyncExternalStore(subscribeBoardGuides, () => boardGuides(docId));
60
+ const [drag, setDrag] = useState<DragState | null>(null);
61
+ const layerRef = useRef<HTMLDivElement | null>(null);
62
+
63
+ // Register the live board transform so gesture overlays can convert guide
64
+ // coordinates into their own space (see board-guides.ts). Re-measured on
65
+ // every pan/zoom/guide change; a pure window resize between pans can leave
66
+ // it briefly stale, which only softens snapping — never breaks a write.
67
+ useEffect(() => {
68
+ const el = containerRef.current;
69
+ if (!el) return;
70
+ const rect = el.getBoundingClientRect();
71
+ registerBoardGuideTransform(docId, {
72
+ originX: rect.left,
73
+ originY: rect.top,
74
+ panX: view.x,
75
+ panY: view.y,
76
+ zoom: view.zoom,
77
+ });
78
+ return () => registerBoardGuideTransform(docId, null);
79
+ }, [docId, containerRef, view.x, view.y, view.zoom]);
80
+
81
+ const toBoard = (local: number, axis: BoardGuide['axis']): number =>
82
+ Math.round((local - (axis === 'x' ? view.x : view.y)) / view.zoom);
83
+ const toLocal = (value: number, axis: BoardGuide['axis']): number =>
84
+ (axis === 'x' ? view.x : view.y) + value * view.zoom;
85
+
86
+ const localPoint = (e: { clientX: number; clientY: number }): { x: number; y: number } => {
87
+ const rect = containerRef.current?.getBoundingClientRect();
88
+ return rect ? { x: e.clientX - rect.left, y: e.clientY - rect.top } : { x: 0, y: 0 };
89
+ };
90
+
91
+ const beginPlace = (axis: BoardGuide['axis']) => (e: React.PointerEvent) => {
92
+ e.preventDefault();
93
+ (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
94
+ const p = localPoint(e);
95
+ setDrag({ kind: 'place', axis, id: null, at: axis === 'x' ? p.x : p.y });
96
+ };
97
+
98
+ const beginMove = (guide: BoardGuide) => (e: React.PointerEvent) => {
99
+ e.preventDefault();
100
+ e.stopPropagation();
101
+ (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);
102
+ const p = localPoint(e);
103
+ setDrag({ kind: 'move', axis: guide.axis, id: guide.id, at: guide.axis === 'x' ? p.x : p.y });
104
+ };
105
+
106
+ const onDragMove = (e: React.PointerEvent): void => {
107
+ if (!drag) return;
108
+ const p = localPoint(e);
109
+ const at = drag.axis === 'x' ? p.x : p.y;
110
+ setDrag({ ...drag, at });
111
+ if (drag.kind === 'move' && drag.id) moveBoardGuide(docId, drag.id, toBoard(at, drag.axis));
112
+ };
113
+
114
+ const onDragEnd = (e: React.PointerEvent): void => {
115
+ if (!drag) return;
116
+ const p = localPoint(e);
117
+ const at = drag.axis === 'x' ? p.x : p.y;
118
+ const overRuler = at <= RULER;
119
+ if (drag.kind === 'place') {
120
+ if (!overRuler) addBoardGuide(docId, drag.axis, toBoard(at, drag.axis));
121
+ } else if (drag.id) {
122
+ if (overRuler) removeBoardGuide(docId, drag.id);
123
+ else moveBoardGuide(docId, drag.id, toBoard(at, drag.axis));
124
+ }
125
+ setDrag(null);
126
+ };
127
+
128
+ // Visible tick range along one axis.
129
+ const ticks = (axis: BoardGuide['axis']): number[] => {
130
+ const el = containerRef.current;
131
+ const extent = el ? (axis === 'x' ? el.clientWidth : el.clientHeight) : 0;
132
+ const step = tickStep(view.zoom);
133
+ const first = Math.ceil(toBoard(RULER, axis) / step) * step;
134
+ const last = toBoard(extent, axis);
135
+ const out: number[] = [];
136
+ for (let v = first; v <= last && out.length < 200; v += step) out.push(v);
137
+ return out;
138
+ };
139
+
140
+ const rulerStyle: React.CSSProperties = {
141
+ position: 'absolute',
142
+ background: RULER_BG,
143
+ zIndex: 61,
144
+ userSelect: 'none',
145
+ touchAction: 'none',
146
+ overflow: 'hidden',
147
+ };
148
+
149
+ return (
150
+ <div
151
+ ref={layerRef}
152
+ data-testid="board-rulers"
153
+ style={{ position: 'absolute', inset: 0, pointerEvents: 'none', zIndex: 60 }}
154
+ onPointerMove={onDragMove}
155
+ onPointerUp={onDragEnd}
156
+ >
157
+ {/* Placed guides. */}
158
+ {guides.map((guide) => {
159
+ const local = toLocal(guide.value, guide.axis);
160
+ const vertical = guide.axis === 'x';
161
+ return (
162
+ <div
163
+ key={guide.id}
164
+ data-testid={`board-guide-${guide.axis}-${guide.value}`}
165
+ title={`${guide.axis} = ${guide.value} — drag to move, drop on the ruler or double-click to remove`}
166
+ onPointerDown={beginMove(guide)}
167
+ onPointerMove={onDragMove}
168
+ onPointerUp={onDragEnd}
169
+ onDoubleClick={() => removeBoardGuide(docId, guide.id)}
170
+ style={{
171
+ position: 'absolute',
172
+ pointerEvents: 'auto',
173
+ cursor: vertical ? 'col-resize' : 'row-resize',
174
+ zIndex: 60,
175
+ ...(vertical
176
+ ? { left: local - 2, top: 0, bottom: 0, width: 5 }
177
+ : { top: local - 2, left: 0, right: 0, height: 5 }),
178
+ }}
179
+ >
180
+ <div
181
+ style={{
182
+ position: 'absolute',
183
+ background: GUIDE_COLOR,
184
+ ...(vertical
185
+ ? { left: 2, top: 0, bottom: 0, width: 1 }
186
+ : { top: 2, left: 0, right: 0, height: 1 }),
187
+ }}
188
+ />
189
+ </div>
190
+ );
191
+ })}
192
+ {/* Placement/move preview line. */}
193
+ {drag && (
194
+ <div
195
+ style={{
196
+ position: 'absolute',
197
+ background: GUIDE_COLOR,
198
+ zIndex: 62,
199
+ ...(drag.axis === 'x'
200
+ ? { left: drag.at, top: 0, bottom: 0, width: 1 }
201
+ : { top: drag.at, left: 0, right: 0, height: 1 }),
202
+ }}
203
+ >
204
+ <span
205
+ style={{
206
+ position: 'absolute',
207
+ ...(drag.axis === 'x' ? { top: RULER + 4, left: 4 } : { left: RULER + 4, top: 4 }),
208
+ fontSize: 9,
209
+ fontFamily: 'ui-monospace, monospace',
210
+ color: GUIDE_COLOR,
211
+ background: RULER_BG,
212
+ padding: '1px 3px',
213
+ borderRadius: 3,
214
+ whiteSpace: 'nowrap',
215
+ }}
216
+ >
217
+ {toBoard(drag.at, drag.axis)}
218
+ </span>
219
+ </div>
220
+ )}
221
+ {/* Top ruler — places HORIZONTAL guides? No: Figma grammar — the top
222
+ ruler measures X, and dragging DOWN from it places a horizontal
223
+ guide; the left ruler measures Y and places vertical guides. We
224
+ follow the measurement axis for ticks and Figma's pull direction
225
+ for placement. */}
226
+ <div
227
+ data-testid="board-ruler-top"
228
+ onPointerDown={beginPlace('y')}
229
+ style={{
230
+ ...rulerStyle,
231
+ top: 0,
232
+ left: RULER,
233
+ right: 0,
234
+ height: RULER,
235
+ cursor: 'row-resize',
236
+ pointerEvents: 'auto',
237
+ }}
238
+ >
239
+ {ticks('x').map((v) => (
240
+ <span
241
+ key={v}
242
+ style={{
243
+ position: 'absolute',
244
+ left: toLocal(v, 'x'),
245
+ bottom: 0,
246
+ borderLeft: `1px solid ${TICK_COLOR}`,
247
+ height: 5,
248
+ }}
249
+ >
250
+ <span
251
+ style={{
252
+ position: 'absolute',
253
+ left: 2,
254
+ bottom: 3,
255
+ fontSize: 8,
256
+ color: TICK_COLOR,
257
+ fontFamily: 'ui-monospace, monospace',
258
+ }}
259
+ >
260
+ {formatTick(v)}
261
+ </span>
262
+ </span>
263
+ ))}
264
+ </div>
265
+ {/* Left ruler. */}
266
+ <div
267
+ data-testid="board-ruler-left"
268
+ onPointerDown={beginPlace('x')}
269
+ style={{
270
+ ...rulerStyle,
271
+ top: RULER,
272
+ left: 0,
273
+ bottom: 0,
274
+ width: RULER,
275
+ cursor: 'col-resize',
276
+ pointerEvents: 'auto',
277
+ }}
278
+ >
279
+ {ticks('y').map((v) => (
280
+ <span
281
+ key={v}
282
+ style={{
283
+ position: 'absolute',
284
+ top: toLocal(v, 'y'),
285
+ right: 0,
286
+ borderTop: `1px solid ${TICK_COLOR}`,
287
+ width: 5,
288
+ }}
289
+ >
290
+ <span
291
+ style={{
292
+ position: 'absolute',
293
+ top: 1,
294
+ right: 3,
295
+ fontSize: 8,
296
+ color: TICK_COLOR,
297
+ fontFamily: 'ui-monospace, monospace',
298
+ writingMode: 'vertical-rl',
299
+ }}
300
+ >
301
+ {formatTick(v)}
302
+ </span>
303
+ </span>
304
+ ))}
305
+ </div>
306
+ <BreakpointArmedPill />
307
+ {/* Corner square. */}
308
+ <div
309
+ style={{
310
+ ...rulerStyle,
311
+ top: 0,
312
+ left: 0,
313
+ width: RULER,
314
+ height: RULER,
315
+ borderRight: `1px solid ${THEME.border}`,
316
+ borderBottom: `1px solid ${THEME.border}`,
317
+ }}
318
+ />
319
+ </div>
320
+ );
321
+ }
322
+
323
+ /** The armed-BREAKPOINT cue on the board itself (blind-walk friction: the
324
+ * breakpoint select is sticky, and with the inspector scrolled elsewhere the
325
+ * only sign that edits were scoped — and frames were previewing narrow —
326
+ * was a dropdown nobody was looking at). One pill, click to disarm. */
327
+ function BreakpointArmedPill(): ReactElement | null {
328
+ const bp = useSyncExternalStore(subscribeBreakpoint, activeBreakpoint);
329
+ if (!bp) return null;
330
+ return (
331
+ <button
332
+ type="button"
333
+ data-testid="board-breakpoint-pill"
334
+ title="Style edits are scoped to this breakpoint — click to return to Base"
335
+ onClick={() => setActiveBreakpoint(null)}
336
+ style={{
337
+ position: 'absolute',
338
+ top: RULER + 8,
339
+ right: 12,
340
+ zIndex: 62,
341
+ pointerEvents: 'auto',
342
+ background: 'rgba(18, 22, 26, 0.92)',
343
+ color: THEME.accent,
344
+ border: `1px solid ${THEME.accent}`,
345
+ borderRadius: 999,
346
+ fontSize: 10,
347
+ padding: '3px 10px',
348
+ cursor: 'pointer',
349
+ }}
350
+ >
351
+ @ {bp} · editing this breakpoint — click to clear
352
+ </button>
353
+ );
354
+ }