@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,196 @@
1
+ /**
2
+ * CSF STORY WRITES — the planner behind "save these args as a story",
3
+ * rename, and delete (the design ledger's CSF-writing order: stories are
4
+ * discovered, composed, framed and switched, and until this nothing WROTE
5
+ * one except Extract Component's emitted file).
6
+ *
7
+ * Pure text surgery over the module source, in the repo's writer idiom
8
+ * (`plan-extract-component.ts` is the emit-shape precedent): every refusal
9
+ * is a named sentence, and nothing here parses with a full AST — a CSF
10
+ * story export is a top-level `export const <Name>` with a braced
11
+ * initializer, and balanced-brace scanning over that shape is the whole
12
+ * grammar this file needs. Anything outside the shape refuses rather than
13
+ * guessing.
14
+ *
15
+ * IT STAYS IN THE HOST, and the reason is the same one unit 6 recorded for the
16
+ * harness and generation estates: its caller is the SERVER tier
17
+ * (`vite-plugin-ui-oid.ts`'s `POST /__ui-source/csf-story`), and the
18
+ * contribution points are page-side only — there is no server-side `.service`
19
+ * or route point for a package to register a handler into. It was moved out
20
+ * once and came straight back when the probe refused to boot: a grep over
21
+ * `src` and `server` had reported zero importers, and the one importer is a
22
+ * file at the package ROOT. (CLAUDE.md: never conclude "dead code" from a
23
+ * search that returned zero.)
24
+ */
25
+
26
+ /** One planned edit: the whole next source, or the refusal. */
27
+ export type CsfStoryPlan =
28
+ | { ok: true; nextSource: string; summary: string }
29
+ | { ok: false; reason: string };
30
+
31
+ const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
32
+
33
+ /** Find `export const <name>` at top level; returns [start, endAfterSemi]. */
34
+ function findStoryExport(source: string, name: string): [number, number] | null {
35
+ const re = new RegExp(`^export const ${name}\\b`, 'm');
36
+ const m = re.exec(source);
37
+ if (!m) return null;
38
+ const eq = source.indexOf('=', m.index);
39
+ if (eq < 0) return null;
40
+ // Balanced scan from the first brace after `=` (a story initializer is an
41
+ // object literal; a non-object initializer refuses at the caller).
42
+ const braceStart = source.indexOf('{', eq);
43
+ if (braceStart < 0) return null;
44
+ let depth = 0;
45
+ for (let i = braceStart; i < source.length; i++) {
46
+ const ch = source[i];
47
+ if (ch === '{') depth++;
48
+ else if (ch === '}') {
49
+ depth--;
50
+ if (depth === 0) {
51
+ let end = i + 1;
52
+ if (source[end] === ';') end++;
53
+ if (source[end] === '\n') end++;
54
+ return [m.index, end];
55
+ }
56
+ }
57
+ }
58
+ return null;
59
+ }
60
+
61
+ /** The file's story TYPE annotation, when it declares the common alias
62
+ * (`type Story = StoryObj<…>`); an un-annotated export is valid CSF, so
63
+ * absence simply drops the annotation. */
64
+ function storyTypeAlias(source: string): string | null {
65
+ const m = /^(?:export )?type (\w+) = StoryObj\b/m.exec(source);
66
+ return m?.[1] ?? null;
67
+ }
68
+
69
+ /** Serialize args to a JS object literal. JSON-shaped values only — a
70
+ * function/symbol/undefined arg refuses BY KEY, because emitting source
71
+ * that silently drops an arg would author a different story than the one
72
+ * on screen. */
73
+ function serializeArgs(
74
+ args: Readonly<Record<string, unknown>>,
75
+ ): CsfStoryPlan | { literal: string } {
76
+ const unserializable = Object.entries(args)
77
+ .filter(([, value]) => {
78
+ if (value === null || value === undefined) return value === undefined;
79
+ const t = typeof value;
80
+ if (t === 'function' || t === 'symbol' || t === 'bigint') return true;
81
+ try {
82
+ return JSON.stringify(value) === undefined;
83
+ } catch {
84
+ return true;
85
+ }
86
+ })
87
+ .map(([key]) => key);
88
+ if (unserializable.length > 0) {
89
+ return {
90
+ ok: false,
91
+ reason:
92
+ `args ${unserializable.join(', ')} cannot be written as literals (function/symbol/` +
93
+ 'undefined values have no CSF source form) — set them in the story file by hand',
94
+ };
95
+ }
96
+ const body = Object.entries(args)
97
+ .map(([key, value]) => {
98
+ const keyText = IDENTIFIER.test(key) ? key : JSON.stringify(key);
99
+ return ` ${keyText}: ${JSON.stringify(value)},`;
100
+ })
101
+ .join('\n');
102
+ return { literal: body.length > 0 ? `{\n${body}\n }` : '{}' };
103
+ }
104
+
105
+ /** Append `export const <name>(: Alias)? = { args: {…} };` to the module. */
106
+ export function planSaveStory(
107
+ source: string,
108
+ name: string,
109
+ args: Readonly<Record<string, unknown>>,
110
+ ): CsfStoryPlan {
111
+ if (!IDENTIFIER.test(name)) {
112
+ return { ok: false, reason: `'${name}' is not a valid story export name (identifier)` };
113
+ }
114
+ if (findStoryExport(source, name) || new RegExp(`^export const ${name}\\b`, 'm').test(source)) {
115
+ return { ok: false, reason: `a story named '${name}' already exists in this file` };
116
+ }
117
+ const serialized = serializeArgs(args);
118
+ if ('ok' in serialized) return serialized;
119
+ const alias = storyTypeAlias(source);
120
+ const annotation = alias ? `: ${alias}` : '';
121
+ const argsPart = serialized.literal === '{}' ? '' : `\n args: ${serialized.literal},\n`;
122
+ const block = `\nexport const ${name}${annotation} = {${argsPart}};\n`;
123
+ const nextSource = source.endsWith('\n') ? source + block.slice(1) : source + block;
124
+ return { ok: true, nextSource, summary: `story '${name}' appended` };
125
+ }
126
+
127
+ /**
128
+ * Rename the export. Only the DECLARATION and `defaultStory: '<old>'`
129
+ * references move; any other in-file use of the identifier refuses by name
130
+ * (a broad textual rename would rewrite code this planner cannot see the
131
+ * meaning of).
132
+ */
133
+ export function planRenameStory(source: string, oldName: string, newName: string): CsfStoryPlan {
134
+ if (!IDENTIFIER.test(newName)) {
135
+ return { ok: false, reason: `'${newName}' is not a valid story export name (identifier)` };
136
+ }
137
+ const span = findStoryExport(source, oldName);
138
+ if (!span) return { ok: false, reason: `no story export named '${oldName}' in this file` };
139
+ if (new RegExp(`^export const ${newName}\\b`, 'm').test(source)) {
140
+ return { ok: false, reason: `a story named '${newName}' already exists in this file` };
141
+ }
142
+ const outside = source.slice(0, span[0]) + source.slice(span[1]);
143
+ const otherUses = [...outside.matchAll(new RegExp(`\\b${oldName}\\b`, 'g'))].filter((m) => {
144
+ // string references to the story NAME (defaultStory: 'Old') are renamed
145
+ // too; bare identifier uses are the refusal.
146
+ const before = outside.slice(Math.max(0, (m.index ?? 0) - 1), m.index);
147
+ const after = outside.slice(
148
+ (m.index ?? 0) + oldName.length,
149
+ (m.index ?? 0) + oldName.length + 1,
150
+ );
151
+ const quoted = (before === "'" && after === "'") || (before === '"' && after === '"');
152
+ return !quoted;
153
+ });
154
+ if (otherUses.length > 0) {
155
+ return {
156
+ ok: false,
157
+ reason:
158
+ `'${oldName}' is referenced ${otherUses.length} more time(s) in this file beyond its ` +
159
+ 'declaration — rename it in source, where those uses are visible',
160
+ };
161
+ }
162
+ let nextSource =
163
+ source.slice(0, span[0]) +
164
+ source.slice(span[0], span[1]).replace(`export const ${oldName}`, `export const ${newName}`) +
165
+ source.slice(span[1]);
166
+ nextSource = nextSource
167
+ .replaceAll(`defaultStory: '${oldName}'`, `defaultStory: '${newName}'`)
168
+ .replaceAll(`defaultStory: "${oldName}"`, `defaultStory: "${newName}"`);
169
+ return { ok: true, nextSource, summary: `story '${oldName}' renamed to '${newName}'` };
170
+ }
171
+
172
+ /** Remove the export block. The LAST story refuses (an empty CSF file fails
173
+ * composition — delete the file instead), and a `defaultStory` reference
174
+ * refuses by name rather than leaving a dangling default. */
175
+ export function planDeleteStory(source: string, name: string): CsfStoryPlan {
176
+ const span = findStoryExport(source, name);
177
+ if (!span) return { ok: false, reason: `no story export named '${name}' in this file` };
178
+ const outside = source.slice(0, span[0]) + source.slice(span[1]);
179
+ if (!/^export const \w+/m.test(outside)) {
180
+ return {
181
+ ok: false,
182
+ reason:
183
+ `'${name}' is the last story in this file — an empty CSF file fails composition; ` +
184
+ 'delete the file instead',
185
+ };
186
+ }
187
+ if (outside.includes(`defaultStory: '${name}'`) || outside.includes(`defaultStory: "${name}"`)) {
188
+ return {
189
+ ok: false,
190
+ reason:
191
+ `'${name}' is this file's declared defaultStory — point vgai.defaultStory at another ` +
192
+ 'story first',
193
+ };
194
+ }
195
+ return { ok: true, nextSource: outside, summary: `story '${name}' deleted` };
196
+ }
@@ -0,0 +1,421 @@
1
+ /**
2
+ * `planComponentExtraction` — the PURE core of "Extract Component…": one
3
+ * already-read source string in, THREE exact artifacts out — a new component
4
+ * module, a portable CSF story beside it, and the callsite edit that replaces
5
+ * the extracted subtree with an instance. No I/O, no hashing, no transport —
6
+ * the same split `plan-fork-component.ts` uses, and for the same reason (the
7
+ * dev server reads with `node:fs`; this module stays dependency-free so it is
8
+ * probeable headlessly).
9
+ *
10
+ * WHAT AN EXTRACTION IS. The inverse of pasting inline: a subtree an author
11
+ * assembled in place becomes a reusable component under `src/prefabs/` — the
12
+ * scene/component/prefab taxonomy the template teaches — with a story so the
13
+ * component board can mount it in isolation, and the original site becomes an
14
+ * ordinary instance. There is deliberately NO parallel prefab format: the
15
+ * output is a plain component file plus plain portable CSF, both of which a
16
+ * developer could have written by hand (WORK.md's own constraint).
17
+ *
18
+ * IMPORTS TRAVEL; EVERYTHING ELSE REFUSES BY NAME. The subtree's free
19
+ * identifiers (`referencedIdentifiers`, the reparent guard's R1 machinery)
20
+ * are classified by where they bind:
21
+ *
22
+ * - an IMPORT binding travels — the new module gets its own import
23
+ * statement, with relative specifiers re-resolved from the new file's
24
+ * location;
25
+ * - a module-level declaration (a `const`/function in the world file)
26
+ * REFUSES, naming the declaration and its line — chasing and copying
27
+ * module locals is scope creep this planner deliberately does not have
28
+ * (the fork records the same boundary), and a silent copy would fork the
29
+ * value's identity;
30
+ * - a binding inside an enclosing function (a hook result, a mapped
31
+ * variable, a prop) REFUSES with the owning function's name — the same
32
+ * sentence shape R1 gives a reparent that would break lexical capture;
33
+ * - an unresolved name (a global — `Math`) is fine as-is.
34
+ *
35
+ * INSERTION SEMANTICS. When the extracted root is an INTRINSIC element
36
+ * (`<mesh>`, `<group>`), its `name`/`position`/`rotation`/`scale` attributes
37
+ * are LIFTED to the new callsite and the component's root spreads
38
+ * `{...props}` (typed `ThreeElements['<tag>']`, the template HeroBox's own
39
+ * shape) — placement belongs to the instance, so a second drop of the same
40
+ * prefab does not land inside the first. A component-tag root is carried
41
+ * verbatim with no lift and no props parameter: its prop surface is its own.
42
+ *
43
+ * REFUSALS ARE NAMED — every rejection returns a sentence the author can act
44
+ * on, and the planner refuses before anything is written.
45
+ */
46
+
47
+ import ts from 'typescript';
48
+ import { lineColToOffset } from './oid-transform';
49
+ import { relativeImportSpecifier } from './relative-import-specifier';
50
+ import {
51
+ bindingScopeOf,
52
+ type JsxElementNode,
53
+ jsxElementAt,
54
+ owningFunctionName,
55
+ referencedIdentifiers,
56
+ } from './reparent-guard';
57
+ import { parseAuthoringTsx } from './ts-ast';
58
+
59
+ const IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
60
+ const MAX_FALLBACK_SUFFIX = 99;
61
+ const LIFTED_ATTRS = ['name', 'position', 'rotation', 'scale'] as const;
62
+
63
+ export interface ExtractComponentRequest {
64
+ /** The file the subtree lives in, and its current bytes. */
65
+ readonly sourceFile: string;
66
+ readonly source: string;
67
+ /** The element's `OidEntry` position (1-based line, 0-based col). */
68
+ readonly line: number;
69
+ readonly col: number;
70
+ /** The preferred component name (the author's, or an instance `name`). */
71
+ readonly nameSeed?: string | undefined;
72
+ /** Project-relative directory the new files land in (`src/prefabs`). */
73
+ readonly prefabDir: string;
74
+ /** File NAMES already in that directory — collision refusals + name fallback. */
75
+ readonly siblingFiles?: readonly string[] | undefined;
76
+ }
77
+
78
+ export interface ExtractComponentPlan {
79
+ readonly newName: string;
80
+ /** `Lantern.tsx` / `Lantern.stories.tsx` — caller joins onto `prefabDir`. */
81
+ readonly componentFileName: string;
82
+ readonly storyFileName: string;
83
+ /** Project-relative paths, forward slashes. */
84
+ readonly componentFile: string;
85
+ readonly storyFile: string;
86
+ /** Complete bytes of the two new modules. */
87
+ readonly componentSource: string;
88
+ readonly storySource: string;
89
+ readonly callsiteFile: string;
90
+ readonly callsitePrevSource: string;
91
+ readonly callsiteNewSource: string;
92
+ /** The specifier the callsite's new import uses. */
93
+ readonly importSpecifier: string;
94
+ /** The extracted root's tag, for hints. */
95
+ readonly tag: string;
96
+ /** History label for the CALLSITE edit (the new files are outside history). */
97
+ readonly historyLabel: string;
98
+ }
99
+
100
+ export type ExtractComponentPlanResult =
101
+ | { readonly ok: true; readonly plan: ExtractComponentPlan }
102
+ | { readonly ok: false; readonly reason: string };
103
+
104
+ function refuse(reason: string): ExtractComponentPlanResult {
105
+ return { ok: false, reason };
106
+ }
107
+
108
+ // ------------------------------------------------------------------- paths
109
+
110
+ function normalizePath(path: string): string {
111
+ return path.replace(/\\/g, '/');
112
+ }
113
+
114
+ function directoryOf(path: string): string {
115
+ const clean = normalizePath(path);
116
+ const cut = clean.lastIndexOf('/');
117
+ return cut < 0 ? '' : clean.slice(0, cut);
118
+ }
119
+
120
+ /** Resolve `./x`/`../x` against a directory, collapsing the dot segments. */
121
+ function resolveRelative(fromDir: string, specifier: string): string {
122
+ const parts = [...fromDir.split('/').filter(Boolean)];
123
+ for (const segment of normalizePath(specifier).split('/')) {
124
+ if (segment === '' || segment === '.') continue;
125
+ if (segment === '..') parts.pop();
126
+ else parts.push(segment);
127
+ }
128
+ return parts.join('/');
129
+ }
130
+
131
+ // ------------------------------------------------------------------- naming
132
+
133
+ function pascalCase(seed: string): string {
134
+ const words = seed.match(/[A-Za-z0-9]+/g) ?? [];
135
+ const joined = words.map((w) => w[0]!.toUpperCase() + w.slice(1)).join('');
136
+ return /^[0-9]/.test(joined) ? '' : joined;
137
+ }
138
+
139
+ /** The component name: the seed PascalCased when usable, else `Extracted<Tag>`,
140
+ * suffixed past any sibling module already claiming the basename. */
141
+ function pickName(
142
+ seed: string | undefined,
143
+ tag: string,
144
+ siblingFiles: readonly string[],
145
+ ): string | null {
146
+ const taken = new Set(
147
+ siblingFiles.map((f) => f.replace(/\.(stories\.)?(tsx|ts|jsx|js)$/, '').toLowerCase()),
148
+ );
149
+ const base =
150
+ (seed && IDENTIFIER_RE.test(pascalCase(seed)) && pascalCase(seed)) ||
151
+ (/^[A-Z]/.test(tag) && IDENTIFIER_RE.test(tag) && `${tag}Part`) ||
152
+ `Extracted${pascalCase(tag) || 'Node'}`;
153
+ if (!taken.has(base.toLowerCase())) return base;
154
+ for (let i = 2; i <= MAX_FALLBACK_SUFFIX; i++) {
155
+ if (!taken.has(`${base}${i}`.toLowerCase())) return `${base}${i}`;
156
+ }
157
+ return null;
158
+ }
159
+
160
+ // ------------------------------------------------------------ import carrying
161
+
162
+ /** The import statement binding `name` in `sf`, rebuilt for a module living at
163
+ * `newFile` — or `null` when `name` is not import-bound. Only the bindings the
164
+ * subtree actually uses are carried, so an import of five names carries one. */
165
+ function carriedImportFor(
166
+ sf: ts.SourceFile,
167
+ name: string,
168
+ callsiteFile: string,
169
+ newFile: string,
170
+ ): { specifier: string; piece: 'default' | 'namespace' | 'named' } | null {
171
+ for (const statement of sf.statements) {
172
+ if (!ts.isImportDeclaration(statement) || !statement.importClause) continue;
173
+ if (!ts.isStringLiteral(statement.moduleSpecifier)) continue;
174
+ const clause = statement.importClause;
175
+ let piece: 'default' | 'namespace' | 'named' | null = null;
176
+ if (clause.name?.text === name) piece = 'default';
177
+ const bindings = clause.namedBindings;
178
+ if (bindings && ts.isNamespaceImport(bindings) && bindings.name.text === name) {
179
+ piece = 'namespace';
180
+ } else if (bindings && ts.isNamedImports(bindings)) {
181
+ if (bindings.elements.some((e) => e.name.text === name)) piece = 'named';
182
+ }
183
+ if (!piece) continue;
184
+ let specifier = statement.moduleSpecifier.text;
185
+ if (specifier.startsWith('.')) {
186
+ const absolute = resolveRelative(directoryOf(callsiteFile), specifier);
187
+ specifier = relativeImportSpecifier(newFile, absolute);
188
+ }
189
+ return { specifier, piece };
190
+ }
191
+ return null;
192
+ }
193
+
194
+ // --------------------------------------------------------------- subtree text
195
+
196
+ function openingTagOf(node: JsxElementNode): ts.JsxOpeningElement | ts.JsxSelfClosingElement {
197
+ return ts.isJsxElement(node) ? node.openingElement : node;
198
+ }
199
+
200
+ /** Dedent by the root's own line indent, then re-indent for the return body. */
201
+ function reindent(text: string, originalIndent: string, newIndent: string): string {
202
+ return text
203
+ .split('\n')
204
+ .map((line, i) => {
205
+ if (i === 0) return `${newIndent}${line}`;
206
+ const stripped = line.startsWith(originalIndent) ? line.slice(originalIndent.length) : line;
207
+ return stripped.trim() === '' ? '' : `${newIndent}${stripped}`;
208
+ })
209
+ .join('\n');
210
+ }
211
+
212
+ // -------------------------------------------------------------------- plan
213
+
214
+ export function planComponentExtraction(
215
+ request: ExtractComponentRequest,
216
+ ): ExtractComponentPlanResult {
217
+ const source = request.source;
218
+ const sf = parseAuthoringTsx(request.sourceFile, source);
219
+ const offset = lineColToOffset(source, request.line, request.col);
220
+ const element = jsxElementAt(sf, offset);
221
+ if (!element) {
222
+ return refuse(
223
+ `${request.sourceFile}:${request.line} no longer holds a JSX element — ` +
224
+ 'the file changed since the hierarchy was indexed.',
225
+ );
226
+ }
227
+ const opening = openingTagOf(element);
228
+ const tag = opening.tagName.getText(sf);
229
+
230
+ // R1 over the whole subtree: classify every free identifier.
231
+ const carried = new Map<
232
+ string,
233
+ { specifier: string; piece: 'default' | 'namespace' | 'named' }
234
+ >();
235
+ for (const [name, site] of referencedIdentifiers(element)) {
236
+ const scope = bindingScopeOf(name, element);
237
+ if (scope === null) continue; // a global — travels as-is
238
+ if (ts.isSourceFile(scope)) {
239
+ const asImport = carriedImportFor(
240
+ sf,
241
+ name,
242
+ normalizePath(request.sourceFile),
243
+ `${request.prefabDir}/x.tsx`,
244
+ );
245
+ if (asImport) {
246
+ carried.set(name, asImport);
247
+ continue;
248
+ }
249
+ const line = sf.getLineAndCharacterOfPosition(site.getStart(sf)).line + 1;
250
+ return refuse(
251
+ `the subtree references \`${name}\` (line ${line}), declared in this module — ` +
252
+ 'extraction only carries imports; move the declaration to its own module first, ' +
253
+ 'or inline the value.',
254
+ );
255
+ }
256
+ return refuse(
257
+ `the subtree references \`${name}\`, bound inside ${owningFunctionName(element, sf)} — ` +
258
+ 'a value local to the enclosing component cannot travel to a new file. ' +
259
+ 'Inline it or lift it to a prop first.',
260
+ );
261
+ }
262
+
263
+ // Name + collision.
264
+ const siblings = request.siblingFiles ?? [];
265
+ const attrs = opening.attributes.properties;
266
+ const authoredName = attrs.find(
267
+ (p): p is ts.JsxAttribute =>
268
+ ts.isJsxAttribute(p) &&
269
+ ts.isIdentifier(p.name) &&
270
+ p.name.text === 'name' &&
271
+ !!p.initializer &&
272
+ ts.isStringLiteral(p.initializer),
273
+ );
274
+ const newName = pickName(
275
+ request.nameSeed ?? (authoredName?.initializer as ts.StringLiteral | undefined)?.text,
276
+ tag,
277
+ siblings,
278
+ );
279
+ if (!newName) return refuse('every candidate component name is taken in the prefab folder.');
280
+
281
+ const componentFileName = `${newName}.tsx`;
282
+ const storyFileName = `${newName}.stories.tsx`;
283
+ const componentFile = `${request.prefabDir}/${componentFileName}`;
284
+ const storyFile = `${request.prefabDir}/${storyFileName}`;
285
+ const collision = siblings.find(
286
+ (f) =>
287
+ f.toLowerCase() === componentFileName.toLowerCase() ||
288
+ f.toLowerCase() === storyFileName.toLowerCase(),
289
+ );
290
+ if (collision) {
291
+ return refuse(
292
+ `${request.prefabDir}/${collision} already exists — extraction will not overwrite.`,
293
+ );
294
+ }
295
+
296
+ // Root-attribute lift (intrinsic roots only): placement belongs to the instance.
297
+ const intrinsicRoot = /^[a-z]/.test(tag);
298
+ const lifted: string[] = [];
299
+ let rootTagWithoutLifted: { start: number; end: number; text: string } | null = null;
300
+ if (intrinsicRoot) {
301
+ const removals: Array<{ start: number; end: number }> = [];
302
+ for (const property of attrs) {
303
+ if (!ts.isJsxAttribute(property) || !ts.isIdentifier(property.name)) continue;
304
+ if (!(LIFTED_ATTRS as readonly string[]).includes(property.name.text)) continue;
305
+ lifted.push(property.getText(sf));
306
+ removals.push({ start: property.getStart(sf), end: property.getEnd() });
307
+ }
308
+ const tagStart = opening.getStart(sf);
309
+ const tagEnd = opening.getEnd();
310
+ let text = '';
311
+ let cursor = tagStart;
312
+ for (const removal of removals.sort((a, b) => a.start - b.start)) {
313
+ // Take the span before the attr, trimming the whitespace that preceded it.
314
+ text += source.slice(cursor, removal.start).replace(/[ \t\n]+$/, ' ');
315
+ cursor = removal.end;
316
+ }
317
+ text += source.slice(cursor, tagEnd);
318
+ // Consecutive removals each left one space behind; collapse the run (only
319
+ // single-line runs — a multi-line attribute list keeps its own layout).
320
+ text = text.replace(/[ \t]{2,}/g, ' ').replace(/[ \t]+>/g, '>');
321
+ // Spread the instance's props last, so a callsite override wins.
322
+ const closer = ts.isJsxSelfClosingElement(opening) ? /\s*\/>$/ : />$/;
323
+ text = text.replace(
324
+ closer,
325
+ ts.isJsxSelfClosingElement(opening) ? ' {...props} />' : ' {...props}>',
326
+ );
327
+ rootTagWithoutLifted = { start: tagStart, end: tagEnd, text };
328
+ }
329
+
330
+ // The component module.
331
+ const elementStart = element.getStart(sf);
332
+ const elementEnd = element.getEnd();
333
+ const lineStart = source.lastIndexOf('\n', elementStart - 1) + 1;
334
+ const indent = /^[ \t]*/.exec(source.slice(lineStart, elementStart))?.[0] ?? '';
335
+ let subtree = source.slice(elementStart, elementEnd);
336
+ if (rootTagWithoutLifted) {
337
+ subtree = rootTagWithoutLifted.text + source.slice(rootTagWithoutLifted.end, elementEnd);
338
+ }
339
+ const body = reindent(subtree, indent, ' ');
340
+
341
+ const importLines = new Map<
342
+ string,
343
+ { defaults: string[]; named: string[]; namespaces: string[] }
344
+ >();
345
+ for (const [name, entry] of carried) {
346
+ const bucket = importLines.get(entry.specifier) ?? { defaults: [], named: [], namespaces: [] };
347
+ if (entry.piece === 'default') bucket.defaults.push(name);
348
+ else if (entry.piece === 'namespace') bucket.namespaces.push(name);
349
+ else bucket.named.push(name);
350
+ importLines.set(entry.specifier, bucket);
351
+ }
352
+ const imports: string[] = [];
353
+ if (intrinsicRoot) {
354
+ imports.push(`import type { ThreeElements } from '@react-three/fiber';`);
355
+ }
356
+ for (const [specifier, bucket] of [...importLines.entries()].sort()) {
357
+ for (const namespace of bucket.namespaces) {
358
+ imports.push(`import * as ${namespace} from '${specifier}';`);
359
+ }
360
+ const pieces: string[] = [];
361
+ if (bucket.defaults.length > 0) pieces.push(bucket.defaults[0]!);
362
+ if (bucket.named.length > 0) pieces.push(`{ ${bucket.named.sort().join(', ')} }`);
363
+ if (pieces.length > 0) imports.push(`import ${pieces.join(', ')} from '${specifier}';`);
364
+ }
365
+
366
+ const componentSourceFinal = `${imports.length > 0 ? `${imports.join('\n')}\n\n` : ''}export function ${newName}(${intrinsicRoot ? `props: ThreeElements['${tag}']` : ''}) {
367
+ return (
368
+ ${body}
369
+ );
370
+ }
371
+ `;
372
+
373
+ // The story (the template HeroBox story, transcribed).
374
+ const title = newName.replace(/([a-z0-9])([A-Z])/g, '$1 $2');
375
+ const storySource = `import type { Meta, StoryObj } from '@storybook/react';
376
+ import { ${newName} } from './${newName}';
377
+
378
+ const meta = {
379
+ title: '${title}',
380
+ component: ${newName},
381
+ } satisfies Meta<typeof ${newName}>;
382
+
383
+ export default meta;
384
+
385
+ type Story = StoryObj<typeof meta>;
386
+
387
+ export const Default: Story = {
388
+ parameters: { vgai: { default: true } },
389
+ };
390
+ `;
391
+
392
+ // The callsite: the subtree becomes an instance, and the import arrives.
393
+ const importSpecifier = relativeImportSpecifier(normalizePath(request.sourceFile), componentFile);
394
+ const instanceAttrs = lifted.length > 0 ? ` ${lifted.join(' ')}` : '';
395
+ const instance = `<${newName}${instanceAttrs} />`;
396
+ let callsiteNewSource = source.slice(0, elementStart) + instance + source.slice(elementEnd);
397
+ const importStatement = `import { ${newName} } from '${importSpecifier}';\n`;
398
+ const lastImport = [...sf.statements].reverse().find(ts.isImportDeclaration);
399
+ const importAt = lastImport ? lastImport.getEnd() + 1 : 0;
400
+ callsiteNewSource =
401
+ callsiteNewSource.slice(0, importAt) + importStatement + callsiteNewSource.slice(importAt);
402
+
403
+ return {
404
+ ok: true,
405
+ plan: {
406
+ newName,
407
+ componentFileName,
408
+ storyFileName,
409
+ componentFile,
410
+ storyFile,
411
+ componentSource: componentSourceFinal,
412
+ storySource,
413
+ callsiteFile: normalizePath(request.sourceFile),
414
+ callsitePrevSource: source,
415
+ callsiteNewSource,
416
+ importSpecifier,
417
+ tag,
418
+ historyLabel: `Extract ${newName}`,
419
+ },
420
+ };
421
+ }