@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,76 @@
1
+ /**
2
+ * Project-authored hierarchy projection (D20).
3
+ *
4
+ * This is editor metadata, not runtime composition. `vgai.project.json.roots`
5
+ * declares adapter mounts; `vgai.project.json.authoring.hierarchy` only
6
+ * chooses how those roots are labelled and grouped in the authoring tree.
7
+ */
8
+
9
+ export interface HierarchyProjectionGroup {
10
+ readonly id: string;
11
+ readonly label: string;
12
+ readonly roots: readonly string[];
13
+ }
14
+
15
+ export interface HierarchyProjection {
16
+ readonly rootLabels?: Readonly<Record<string, string>>;
17
+ readonly groups?: readonly HierarchyProjectionGroup[];
18
+ }
19
+
20
+ function record(value: unknown): Record<string, unknown> | null {
21
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
22
+ ? (value as Record<string, unknown>)
23
+ : null;
24
+ }
25
+
26
+ /**
27
+ * Leniently read authoring metadata. Invalid entries are omitted so a typo in
28
+ * an optional projection can never make the game itself unopenable.
29
+ */
30
+ export function parseHierarchyProjection(value: unknown): HierarchyProjection | undefined {
31
+ const source = record(value);
32
+ if (!source) return undefined;
33
+
34
+ const labelsSource = record(source['rootLabels']);
35
+ const labelEntries = labelsSource
36
+ ? Object.entries(labelsSource).flatMap(([id, label]): Array<[string, string]> => {
37
+ const normalizedId = id.trim();
38
+ const normalizedLabel = typeof label === 'string' ? label.trim() : '';
39
+ return normalizedId && normalizedLabel ? [[normalizedId, normalizedLabel]] : [];
40
+ })
41
+ : [];
42
+ const rootLabels = labelEntries.length > 0 ? Object.fromEntries(labelEntries) : undefined;
43
+
44
+ const groupIds = new Set<string>();
45
+ const groupEntries = Array.isArray(source['groups'])
46
+ ? source['groups'].flatMap((candidate): HierarchyProjectionGroup[] => {
47
+ const group = record(candidate);
48
+ const id = typeof group?.['id'] === 'string' ? group['id'].trim() : '';
49
+ const label = typeof group?.['label'] === 'string' ? group['label'].trim() : '';
50
+ const roots = Array.isArray(group?.['roots'])
51
+ ? group['roots'].flatMap((root): string[] => {
52
+ const normalized = typeof root === 'string' ? root.trim() : '';
53
+ return normalized ? [normalized] : [];
54
+ })
55
+ : [];
56
+ if (!id || !label || roots.length === 0 || groupIds.has(id)) return [];
57
+ groupIds.add(id);
58
+ return [{ id, label, roots: [...new Set(roots)] }];
59
+ })
60
+ : [];
61
+ const groups = groupEntries.length > 0 ? groupEntries : undefined;
62
+
63
+ if (!rootLabels && !groups) return undefined;
64
+ return {
65
+ ...(rootLabels ? { rootLabels } : {}),
66
+ ...(groups ? { groups } : {}),
67
+ };
68
+ }
69
+
70
+ /** Read the projection from a raw `vgai.project.json` config object. */
71
+ export function hierarchyProjectionFromProjectConfig(
72
+ config: unknown,
73
+ ): HierarchyProjection | undefined {
74
+ const authoring = record(record(config)?.['authoring']);
75
+ return parseHierarchyProjection(authoring?.['hierarchy']);
76
+ }
@@ -0,0 +1,243 @@
1
+ /**
2
+ * What the hierarchy panel is allowed to REUSE between two renders, and the
3
+ * row index that makes a selection change cost `O(selection × depth)` instead
4
+ * of `O(nodes)`.
5
+ *
6
+ * THE DEFECT THIS EXISTS FOR (scale-speed baseline, 2026-08-19, 22 of 43
7
+ * offender rows): `GameHierarchySurface` re-renders on every store notify — it
8
+ * has to, because the highlight moves — and its render body rebuilds the whole
9
+ * row pipeline from `adapter.hierarchy`: one uncapped flatten of every node,
10
+ * the per-node first-open policy, a second capped flatten, and a per-row
11
+ * ancestor climb. On a 20 000-node world that is 100-430ms of main-thread
12
+ * block AFTER a `select` whose reply already went out in 3ms, and it is paid
13
+ * for a change that touched nothing the walk reads.
14
+ *
15
+ * The two slots below split that pipeline where its inputs actually split:
16
+ *
17
+ * - {@link HierarchyRowCache.structural} holds everything derived from the
18
+ * TREE alone. Its key carries the store's `contentVersion` and the
19
+ * adapter's structural notification epoch. The store version stands
20
+ * still for a selection-only notify and moves for every other mutation
21
+ * (see `EditorShellStore.contentVersion`) — including the adapter's own
22
+ * `notifyIngestEdit` on a live structural change, which is what makes a
23
+ * late-arriving subtree invalidate this on the tick it lands.
24
+ * - {@link HierarchyRowCache.collapsed} holds the FOLD projected onto the
25
+ * tree — the set of row paths that are collapsed right now. Deriving it
26
+ * scans every structural row, so it is `O(nodes)`; its inputs are the tree
27
+ * and the fold, and SELECTION IS NOT ONE OF THEM. It has its own slot
28
+ * because the browse view below keys on the reveal a selection opens, and
29
+ * folding that `O(nodes)` scan into the same slot made every click pay it.
30
+ * - {@link HierarchyRowCache.browse} holds the capped/collapsed/searched
31
+ * view. It keys on the structural value BY IDENTITY plus the fold, scope,
32
+ * search and reveal state — so a selection that reveals nothing new reuses
33
+ * it, and one that does reveal something rebuilds it.
34
+ *
35
+ * Each slot holds ONE entry. The panel renders one tree at a time, and a
36
+ * one-entry memo cannot leak: the moment the key moves, the old value is
37
+ * dropped. Keys are compared element-wise with `Object.is`, so every entry
38
+ * must be a primitive or a stable reference — never a freshly built object
39
+ * (a `Set`/`Map` built per render would never compare equal and would make
40
+ * the cache a pure cost). Signatures are the way to put a collection in a key.
41
+ */
42
+
43
+ import type { HierarchyNodeRow } from './hierarchy-node-rows';
44
+
45
+ /** Element-wise `Object.is` over two key tuples. */
46
+ function sameKey(a: readonly unknown[], b: readonly unknown[]): boolean {
47
+ if (a.length !== b.length) return false;
48
+ for (let i = 0; i < a.length; i += 1) if (!Object.is(a[i], b[i])) return false;
49
+ return true;
50
+ }
51
+
52
+ /** One memo slot: the last key it computed for, and the value it produced. */
53
+ class Slot<V> {
54
+ #key: readonly unknown[] | null = null;
55
+ #value: V | undefined;
56
+ /** How many times `compute` actually ran. Read by tests; never by product code. */
57
+ computeCount = 0;
58
+
59
+ get current(): V | undefined {
60
+ return this.#value;
61
+ }
62
+
63
+ read(key: readonly unknown[], compute: (previous: V | undefined) => V): V {
64
+ if (this.#key !== null && sameKey(this.#key, key)) return this.#value as V;
65
+ const value = compute(this.#value);
66
+ this.#key = key;
67
+ this.#value = value;
68
+ this.computeCount += 1;
69
+ return value;
70
+ }
71
+ }
72
+
73
+ /**
74
+ * The panel's two memo slots. Held in a `useRef` (never module state, so it
75
+ * cannot leak between editor sessions — the same stance `TransformLockCache`
76
+ * takes).
77
+ */
78
+ export class HierarchyRowCache<Structural, Browse, Collapsed = unknown> {
79
+ readonly #structural = new Slot<Structural>();
80
+ readonly #collapsed = new Slot<Collapsed>();
81
+ readonly #browse = new Slot<Browse>();
82
+ /**
83
+ * `useDeferredValue` can render 11, then speculatively render 10, then catch
84
+ * up to 12. A render-time one-slot memo must not let that backward key
85
+ * replace 11 as the predecessor for 12's exact structural delta.
86
+ */
87
+ #structuralAdapter: unknown;
88
+ #structuralVersion = Number.NEGATIVE_INFINITY;
89
+
90
+ /**
91
+ * The tree-only half. `key` must name the adapter identity, the store's
92
+ * `contentVersion`, and any adapter-owned structural notification epoch;
93
+ * nothing in it may move for a selection change.
94
+ */
95
+ structural(
96
+ key: readonly unknown[],
97
+ compute: (previous: Structural | undefined) => Structural,
98
+ ): Structural {
99
+ const [adapter, version] = key;
100
+ if (
101
+ adapter === this.#structuralAdapter &&
102
+ typeof version === 'number' &&
103
+ version < this.#structuralVersion &&
104
+ this.#structural.current !== undefined
105
+ ) {
106
+ return this.#structural.current;
107
+ }
108
+ const value = this.#structural.read(key, compute);
109
+ if (adapter !== this.#structuralAdapter) {
110
+ this.#structuralAdapter = adapter;
111
+ this.#structuralVersion = Number.NEGATIVE_INFINITY;
112
+ }
113
+ if (typeof version === 'number') {
114
+ this.#structuralVersion = Math.max(this.#structuralVersion, version);
115
+ }
116
+ return value;
117
+ }
118
+
119
+ /**
120
+ * The fold-only half. `key` must START with the structural value itself and
121
+ * carry the fold generation/scope — and, like {@link structural}, nothing a
122
+ * selection moves.
123
+ */
124
+ collapsed(
125
+ key: readonly unknown[],
126
+ compute: (previous: Collapsed | undefined) => Collapsed,
127
+ ): Collapsed {
128
+ return this.#collapsed.read(key, compute);
129
+ }
130
+
131
+ /**
132
+ * The capped/collapsed/searched half. `key` must START with the structural
133
+ * value itself, so a rebuilt tree can never be viewed through a stale
134
+ * browse result.
135
+ */
136
+ browse(key: readonly unknown[], compute: (previous: Browse | undefined) => Browse): Browse {
137
+ return this.#browse.read(key, compute);
138
+ }
139
+
140
+ /** How many times each slot re-derived. Test/instrumentation only. */
141
+ get counts(): { structural: number; collapsed: number; browse: number } {
142
+ return {
143
+ structural: this.#structural.computeCount,
144
+ collapsed: this.#collapsed.computeCount,
145
+ browse: this.#browse.computeCount,
146
+ };
147
+ }
148
+ }
149
+
150
+ // --------------------------------------------------------------- row index
151
+
152
+ /**
153
+ * Where every row sits, indexed both ways.
154
+ *
155
+ * Built once per structural walk and cached with it. Both selection-driven
156
+ * derivations below used to SCAN every row (and `selectedAncestorNodeIds`
157
+ * additionally built an N-entry `Map` of its own) on every render, which is
158
+ * `O(nodes)` work whose answer is about a handful of selected ids.
159
+ */
160
+ export interface RowPathIndex {
161
+ /** `pathKey` → node id, for every real (non-`more`) row. */
162
+ readonly nodeIdByPathKey: ReadonlyMap<string, string>;
163
+ /** node id → every `pathKey` that node is rendered at. A live tree can reach
164
+ * one id from more than one place; the flattener keeps the first, but the
165
+ * index keeps them all so nothing depends on which walk order found it. */
166
+ readonly pathKeysByNodeId: ReadonlyMap<string, readonly string[]>;
167
+ }
168
+
169
+ export function indexRowPaths(rows: readonly HierarchyNodeRow[]): RowPathIndex {
170
+ const nodeIdByPathKey = new Map<string, string>();
171
+ const pathKeysByNodeId = new Map<string, string[]>();
172
+ for (const row of rows) {
173
+ if (row.more) continue;
174
+ nodeIdByPathKey.set(row.pathKey, row.node.id);
175
+ const existing = pathKeysByNodeId.get(row.node.id);
176
+ if (existing) existing.push(row.pathKey);
177
+ else pathKeysByNodeId.set(row.node.id, [row.pathKey]);
178
+ }
179
+ return { nodeIdByPathKey, pathKeysByNodeId };
180
+ }
181
+
182
+ /** Every strict-ancestor path of `pathKey`, outermost first. */
183
+ export function ancestorPathKeys(pathKey: string): string[] {
184
+ const parts = pathKey.split('.');
185
+ const ancestors: string[] = [];
186
+ for (let i = 1; i < parts.length; i++) ancestors.push(parts.slice(0, i).join('.'));
187
+ return ancestors;
188
+ }
189
+
190
+ /** The node ids of every ancestor of every selected row — the branch selection
191
+ * reveal opens. `O(selection × depth)`. */
192
+ export function selectedAncestorNodeIds(
193
+ index: RowPathIndex,
194
+ selectedIds: ReadonlySet<string>,
195
+ ): Set<string> {
196
+ const ids = new Set<string>();
197
+ for (const selected of selectedIds) {
198
+ for (const pathKey of index.pathKeysByNodeId.get(selected) ?? []) {
199
+ for (const ancestor of ancestorPathKeys(pathKey)) {
200
+ const id = index.nodeIdByPathKey.get(ancestor);
201
+ if (id) ids.add(id);
202
+ }
203
+ }
204
+ }
205
+ return ids;
206
+ }
207
+
208
+ /** How many children each ancestor of a selected row must show for that row to
209
+ * survive the browse-view child cap. `O(selection × depth)`. */
210
+ export function selectedRevealCounts(
211
+ index: RowPathIndex,
212
+ selectedIds: ReadonlySet<string>,
213
+ ): Map<string, number> {
214
+ const revealed = new Map<string, number>();
215
+ for (const selected of selectedIds) {
216
+ for (const pathKey of index.pathKeysByNodeId.get(selected) ?? []) {
217
+ const parts = pathKey.split('.');
218
+ let parent = parts[0]!;
219
+ for (let i = 1; i < parts.length; i++) {
220
+ const childIndex = Number(parts[i]);
221
+ if (Number.isFinite(childIndex)) {
222
+ revealed.set(parent, Math.max(revealed.get(parent) ?? 0, childIndex + 1));
223
+ }
224
+ parent = `${parent}.${parts[i]}`;
225
+ }
226
+ }
227
+ }
228
+ return revealed;
229
+ }
230
+
231
+ /**
232
+ * A stable, order-independent string for a reveal map, so it can sit in a memo
233
+ * key that is compared with `Object.is`. Reveal maps are small (one entry per
234
+ * ancestor of a selected/expanded row), which is what makes a signature the
235
+ * right shape here rather than a version counter.
236
+ */
237
+ export function revealSignature(revealed: ReadonlyMap<string, number>): string {
238
+ if (revealed.size === 0) return '';
239
+ return [...revealed]
240
+ .sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0))
241
+ .map(([pathKey, count]) => `${pathKey}=${String(count)}`)
242
+ .join(',');
243
+ }
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Pure row-model math for the hierarchy panel.
3
+ *
4
+ * Four questions a row needs answered, all extracted here so they are unit
5
+ * testable without a DOM, an adapter session, or a live source tree:
6
+ *
7
+ * 1. **Is this row a component instance, and what is its type?** The
8
+ * adapter already computes `EditorNode.typeLabel`; the row just needs to
9
+ * know when to print it. Detached `#n` pockets deliberately carry no
10
+ * `typeLabel` — a pocket must not impersonate the `<Enemy>` that
11
+ * rendered it — so "has a typeLabel AND is a component row" is the whole
12
+ * rule and no special-casing of pockets is needed here.
13
+ * 2. **Is every transform channel refused, and with what sentence?**
14
+ * The adapter's `reason` is the ONE canonical text (doctrine rule 2): the
15
+ * hierarchy tooltip, the inspector field, and the gizmo-denial hint all
16
+ * show this exact string, never a paraphrase. So this module NEVER writes
17
+ * a reason of its own — it only forwards the adapter's.
18
+ * 3. **Does this row have authorability warnings, and what do they say?**
19
+ * Same rule as H2, one step stronger: the diagnostic message is written by
20
+ * the analyzer that found the problem and is shown VERBATIM. This module
21
+ * picks no wording, adds no severity of its own and truncates nothing — it
22
+ * counts and newline-joins.
23
+ * 4. **What may this row DO?** One predicate ({@link rowAffordances}) that
24
+ * every gate in the panel consults, instead of five copies of
25
+ * `!isStructural && !isInternal` drifting apart.
26
+ *
27
+ * Cost note: `R3fSourceAuthoringAdapter.editability` re-analyzes JSX
28
+ * attributes from cached source text on every call (string scan + parse). It
29
+ * is NOT free per render, which is why {@link transformLockSummary}
30
+ * short-circuits on the first WRITABLE channel (the overwhelmingly common
31
+ * case costs exactly one probe, not three) and why {@link TransformLockCache}
32
+ * exists at all.
33
+ */
34
+
35
+ import type { EditorNode, TransformChannel, TransformEditability } from '@volter/editor-project/adapter';
36
+
37
+ /** The three channels a lock glyph summarizes, in probe order. */
38
+ const CHANNELS: readonly TransformChannel[] = ['position', 'rotation', 'scale'];
39
+
40
+ // ------------------------------------------------------------------ H1
41
+
42
+ export interface RowIdentity {
43
+ /** The row's own name — unchanged, and still the ONLY thing search matches. */
44
+ readonly label: string;
45
+ /** The component type to print as a dim suffix, or null for a plain row. */
46
+ readonly typeSuffix: string | null;
47
+ }
48
+
49
+ /**
50
+ * H1 — `EnemyBravo ·Enemy`. A row earns the type suffix (and the instance
51
+ * accent tint that travels with it) only when it BOTH represents a component
52
+ * instance (`role: 'component'`) and the adapter told us its type.
53
+ */
54
+ export function rowIdentity(node: Pick<EditorNode, 'label' | 'role' | 'typeLabel'>): RowIdentity {
55
+ const isInstance = node.role === 'component' && !!node.typeLabel;
56
+ return { label: node.label, typeSuffix: isInstance ? node.typeLabel! : null };
57
+ }
58
+
59
+ // ------------------------------------------------------------------ H2
60
+
61
+ export interface TransformLockSummary {
62
+ /** True only when position, rotation AND scale are all refused. */
63
+ readonly locked: boolean;
64
+ /** The position channel's verbatim adapter reason (never rewritten here). */
65
+ readonly reason?: string;
66
+ }
67
+
68
+ /** Shared immutable "nothing to say" result — avoids per-row allocation. */
69
+ export const UNLOCKED: TransformLockSummary = { locked: false };
70
+
71
+ /** One channel probe. `undefined` means the adapter declares no editability
72
+ * opinion at all, which every consumer in this editor reads as writable
73
+ * (`editability?.(…)?.writable ?? true`). */
74
+ export type EditabilityProbe = (channel: TransformChannel) => TransformEditability | undefined;
75
+
76
+ /**
77
+ * H2 — collapse the three channels into one row-level verdict. Short-circuits
78
+ * on the first writable channel, so an ordinary movable row pays for ONE
79
+ * `editability` call.
80
+ *
81
+ * The surfaced reason is the POSITION channel's, matching the design record:
82
+ * per-channel detail stays inspector-only, and the row shows one sentence.
83
+ */
84
+ export function transformLockSummary(probe: EditabilityProbe): TransformLockSummary {
85
+ let positionReason: string | undefined;
86
+ for (const channel of CHANNELS) {
87
+ const verdict = probe(channel);
88
+ if (!verdict || verdict.writable) return UNLOCKED;
89
+ if (channel === 'position') positionReason = verdict.reason;
90
+ }
91
+ return positionReason === undefined ? { locked: true } : { locked: true, reason: positionReason };
92
+ }
93
+
94
+ /** The minimal adapter surface {@link TransformLockCache} needs — structurally
95
+ * satisfied by `AuthoringAdapter` without importing it. */
96
+ export interface EditabilitySource {
97
+ readonly transforms?:
98
+ | {
99
+ readonly editability?:
100
+ | ((id: string, channel: TransformChannel) => TransformEditability)
101
+ | undefined;
102
+ }
103
+ | undefined;
104
+ }
105
+
106
+ /**
107
+ * Memoized {@link transformLockSummary} per row id.
108
+ *
109
+ * INVALIDATION KEY: `(source identity, version)`. `version` is supplied by the
110
+ * caller and must be a monotonically increasing counter that advances whenever
111
+ * anything the adapter's `editability` reads could have changed. `GameHierarchy`
112
+ * passes `store.getSnapshot() + adapterVersion` — the shell store's `_version`
113
+ * (bumped by `_notify()`, which EVERY source-write path funnels through via
114
+ * `notifyIngestEdit()`) plus its own adapter-subscription counter. Both are
115
+ * monotone, so their sum is monotone, and a stale entry therefore cannot
116
+ * survive a source edit: the edit bumps `_version` before the re-render that
117
+ * would read the cache.
118
+ *
119
+ * The cache also clears on ADAPTER SWITCH (the `source !== this.source`
120
+ * check), so ids minted by one adapter can never answer for another's.
121
+ */
122
+ export class TransformLockCache {
123
+ private entries = new Map<string, TransformLockSummary>();
124
+ private source: EditabilitySource | null = null;
125
+ private version = Number.NaN;
126
+ /** Test-visible: how many times the adapter was actually probed. */
127
+ private computed = 0;
128
+
129
+ get computeCount(): number {
130
+ return this.computed;
131
+ }
132
+
133
+ summaryFor(source: EditabilitySource, version: number, id: string): TransformLockSummary {
134
+ if (this.source !== source || this.version !== version) {
135
+ this.entries.clear();
136
+ this.source = source;
137
+ this.version = version;
138
+ }
139
+ const cached = this.entries.get(id);
140
+ if (cached) return cached;
141
+ this.computed++;
142
+ const editability = source.transforms?.editability;
143
+ const summary = editability
144
+ ? transformLockSummary((channel) => editability(id, channel))
145
+ : UNLOCKED;
146
+ this.entries.set(id, summary);
147
+ return summary;
148
+ }
149
+ }
150
+
151
+ // ------------------------------------------------------------------ H6
152
+
153
+ /** What a row is allowed to do. Every field is a REFUSAL gate, never a
154
+ * capability claim: `true` means "this row model does not stand in the way",
155
+ * and the adapter's own provider/value probes still decide whether the
156
+ * affordance renders at all (a `document` row has no `name` path, so it never
157
+ * renames regardless of what this says). */
158
+ export interface RowAffordances {
159
+ /** Reparent-by-drag. */
160
+ readonly draggable: boolean;
161
+ /** Inline rename (double-click) and the Rename menu item. */
162
+ readonly renamable: boolean;
163
+ /** ANY write: create/duplicate/delete/group, the visibility eye, the lock
164
+ * toggle, the entity-asset save. One flag, because H6's rule is not
165
+ * per-operation — a revealed internal has no writable surface at all. */
166
+ readonly writable: boolean;
167
+ /** Whether the row's label participates in hierarchy search. */
168
+ readonly searchable: boolean;
169
+ }
170
+
171
+ const ORDINARY_ROW: RowAffordances = {
172
+ draggable: true,
173
+ renamable: true,
174
+ writable: true,
175
+ searchable: true,
176
+ };
177
+ const STRUCTURAL_ROW: RowAffordances = {
178
+ draggable: false,
179
+ renamable: false,
180
+ writable: true,
181
+ searchable: true,
182
+ };
183
+ /**
184
+ * H6 — a revealed internal. Non-writable BY CONSTRUCTION, not by policy: it is
185
+ * a rendered part of a component's output with no authored source identity, so
186
+ * there is nothing for a rename/reparent/delete to write to. Selection stays
187
+ * open (the id resolves, the inspector shows what it honestly can, and H2's
188
+ * lock-with-reason sentence explains the refusal); search is closed, because a
189
+ * `mixamorig:Spine` match across four enemies buries every real row.
190
+ */
191
+ const INTERNAL_ROW: RowAffordances = {
192
+ draggable: false,
193
+ renamable: false,
194
+ writable: false,
195
+ searchable: false,
196
+ };
197
+
198
+ /**
199
+ * The ONE gate for "may this row be written to / dragged / found by search".
200
+ *
201
+ * `structural` keeps its pre-H6 meaning exactly (world groups, organization
202
+ * rows, root-group members, and the `STRUCTURAL_ROLES` set): non-draggable,
203
+ * with its write items gated by the adapter probes the panel already runs.
204
+ * `internal` is the new, stronger state and it wins over everything.
205
+ */
206
+ export function rowAffordances(row: {
207
+ readonly structural: boolean;
208
+ readonly internal: boolean;
209
+ }): RowAffordances {
210
+ if (row.internal) return INTERNAL_ROW;
211
+ return row.structural ? STRUCTURAL_ROW : ORDINARY_ROW;
212
+ }
213
+
214
+ // ------------------------------------------------------------------ H5
215
+
216
+ /**
217
+ * The two fields a row badge needs from one diagnostic. Structurally satisfied
218
+ * by `R3fAuthoringDiagnostic` — declared narrowly here so the hierarchy never
219
+ * imports an R3F/ui-source type (the same contract-only rule H2's
220
+ * {@link EditabilitySource} and H3's `InstanceSourceLocator` follow).
221
+ */
222
+ export interface RowDiagnostic {
223
+ readonly code: string;
224
+ readonly message: string;
225
+ }
226
+
227
+ export interface RowWarningBadge {
228
+ /** How many diagnostics this row carries — always ≥ 1 when a badge exists. */
229
+ readonly count: number;
230
+ /** Every message, VERBATIM and newline-joined, in the order the adapter
231
+ * returned them. The badge's tooltip is this string and nothing else. */
232
+ readonly tooltip: string;
233
+ /** The codes, for the badge's `data-` attribute (a test can name the exact
234
+ * finding without matching on prose that is allowed to be reworded). */
235
+ readonly codes: readonly string[];
236
+ }
237
+
238
+ /**
239
+ * H5 — collapse a row's diagnostics into its badge, or `null` for the
240
+ * overwhelmingly common "nothing to warn about" row.
241
+ *
242
+ * The verbatim rule is the point: doctrine rule 2 says the analyzer's sentence
243
+ * is the ONE canonical text, so multiple findings are STACKED (newline-joined),
244
+ * never summarized into "3 problems" and never truncated. A row with two
245
+ * warnings shows both sentences.
246
+ */
247
+ export function rowWarningBadge(
248
+ diagnostics: readonly RowDiagnostic[] | undefined | null,
249
+ ): RowWarningBadge | null {
250
+ if (!diagnostics || diagnostics.length === 0) return null;
251
+ return {
252
+ count: diagnostics.length,
253
+ tooltip: diagnostics.map((diagnostic) => diagnostic.message).join('\n'),
254
+ codes: diagnostics.map((diagnostic) => diagnostic.code),
255
+ };
256
+ }
257
+
258
+ /** The minimal adapter surface {@link RowWarningCache} needs — structurally
259
+ * satisfied by `CompositeAuthoringAdapter`/`R3fSourceAuthoringAdapter` without
260
+ * importing either, and honestly absent on every adapter that runs no source
261
+ * analyzer (which then shows no badges, rather than fabricated ones). */
262
+ export interface RowDiagnosticsSource {
263
+ readonly diagnosticsFor?: ((id: string) => readonly RowDiagnostic[] | undefined) | undefined;
264
+ }
265
+
266
+ /**
267
+ * Memoized {@link rowWarningBadge} per row id, with the SAME invalidation
268
+ * contract as {@link TransformLockCache} — `(source identity, version)`, where
269
+ * `GameHierarchy` passes the same `store.getSnapshot() + adapterVersion` key to
270
+ * both.
271
+ *
272
+ * That key is exactly right for H5 and not by coincidence: diagnostics arrive
273
+ * on the OID index, and the R3F adapter's `refreshSourceState()` calls
274
+ * `store.notifyIngestEdit()` the moment a new index lands — which bumps the
275
+ * store `_version` that is half this key. So a fresh index invalidates these
276
+ * badges by construction, on the same tick, through the path every source-write
277
+ * and HMR remount already funnels through.
278
+ *
279
+ * Worth caching even though the adapter's own lookup is two map reads: on a
280
+ * composite it is a `route(id)` ownership walk, and the badge object plus its
281
+ * joined tooltip string would otherwise be reallocated for every row on every
282
+ * render.
283
+ */
284
+ export class RowWarningCache {
285
+ private entries = new Map<string, RowWarningBadge | null>();
286
+ private source: RowDiagnosticsSource | null = null;
287
+ private version = Number.NaN;
288
+ /** Test-visible: how many times the adapter was actually probed. */
289
+ private computed = 0;
290
+
291
+ get computeCount(): number {
292
+ return this.computed;
293
+ }
294
+
295
+ badgeFor(source: RowDiagnosticsSource, version: number, id: string): RowWarningBadge | null {
296
+ if (this.source !== source || this.version !== version) {
297
+ this.entries.clear();
298
+ this.source = source;
299
+ this.version = version;
300
+ }
301
+ const cached = this.entries.get(id);
302
+ if (cached !== undefined) return cached;
303
+ this.computed++;
304
+ const badge = source.diagnosticsFor ? rowWarningBadge(source.diagnosticsFor(id)) : null;
305
+ this.entries.set(id, badge);
306
+ return badge;
307
+ }
308
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Hierarchy child-cap constants.
3
+ *
4
+ * The hierarchy panel flattens the ADAPTER's `EditorNode` tree through
5
+ * `hierarchy-node-rows.ts`. This module holds only the two row-cap
6
+ * constants, shared with that flattener so every consumer caps identically.
7
+ */
8
+
9
+ /** Max children shown per parent before a "… N more" row (when capping is on). */
10
+ export const CHILD_CAP = 20;
11
+ export const MORE_ID_PREFIX = '__more__:';