@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,621 @@
1
+ /**
2
+ * `planComponentFork` — the PURE core of H7 "Fork Component…": two already-read
3
+ * source strings in, two exact edits out. No I/O, no hashing, no transport — the
4
+ * same split `plan-source-edit.ts` uses, and for the same reason (the dev server
5
+ * reads with `node:fs`; this module stays dependency-free so the plan is
6
+ * readable on its own).
7
+ *
8
+ * WHAT A FORK IS. H7's translation of Unity's Unpack into a source world:
9
+ * customizing ONE instance beyond the component's prop surface means COPYING the
10
+ * component and retargeting that callsite — never flattening the definition's
11
+ * JSX into the parent (a refactor no React developer performs, and the thing
12
+ * H7 rejects permanently). Mechanically: one new file plus one changed tag.
13
+ *
14
+ * WHY THE WHOLE MODULE IS COPIED. The copy has to COMPILE. A definition's
15
+ * dependencies are module-level: imports, helper functions, constants, types,
16
+ * the props interface. Copying the module wholesale carries all of them, and —
17
+ * because the copy lands as a SIBLING of the original — every relative import
18
+ * specifier inside it still resolves unchanged. Selective extraction (copy the
19
+ * function, chase what it references) is the scope-analysis machinery the
20
+ * reparent spec owns; this action deliberately does not have it. The price is
21
+ * that non-component exports are duplicated across the two modules. That is
22
+ * accepted for v1: nothing imports the new module except the one retargeted
23
+ * callsite, so a duplicate export is inert.
24
+ *
25
+ * WHY IT IS NOT "for this instance". The menu item is `Fork Component…`, not
26
+ * "Fork for this instance": a callsite that lives inside a component rendered
27
+ * many times retargets EVERY render of that callsite. One callsite is the unit
28
+ * of this edit, and one callsite is not always one on-screen object.
29
+ *
30
+ * REFUSALS ARE NAMED. Every rejection returns a sentence the author can act on
31
+ * (doctrine rule 2 — "refusal is visible and named"), and the planner refuses
32
+ * BEFORE anything is written; the caller writes only a plan it has in hand.
33
+ */
34
+
35
+ import ts from 'typescript';
36
+ import { lineColToOffset } from './oid-transform';
37
+ import { relativeImportSpecifier } from './relative-import-specifier';
38
+ import { hasModifier, parseAuthoringTsx } from './ts-ast';
39
+
40
+ /** A valid JS identifier — the gate the instance's `name` prop must pass to
41
+ * become the fork's component name. */
42
+ const IDENTIFIER_RE = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
43
+
44
+ /** `<Tag>Fork`, `<Tag>Fork2` … up to this suffix before the planner gives up. */
45
+ const MAX_FALLBACK_SUFFIX = 99;
46
+
47
+ const SOURCE_EXTENSION_RE = /\.(tsx|ts|jsx|js)$/;
48
+
49
+ export interface ForkComponentRequest {
50
+ /** The file the instance is USED in, and its current bytes. */
51
+ readonly callsiteFile: string;
52
+ readonly callsiteSource: string;
53
+ /** The callsite element's `OidEntry` position (1-based line, 0-based col). */
54
+ readonly callsiteLine: number;
55
+ readonly callsiteCol: number;
56
+ /** The file the component is WRITTEN in, and its current bytes. */
57
+ readonly definitionFile: string;
58
+ readonly definitionSource: string;
59
+ /** The component name as spelled AT THE CALLSITE (`OidEntry.tag`). */
60
+ readonly tag: string;
61
+ /** The instance's `name` prop — the preferred seed for the fork's name. */
62
+ readonly nameSeed?: string | undefined;
63
+ /**
64
+ * File NAMES (not paths) already in the definition file's directory. Two
65
+ * jobs: the cheap "is this export name taken" probe H7 asks for (a module's
66
+ * basename is a good enough proxy for the component it exports, and this
67
+ * planner is not allowed to read the directory itself), and the hard
68
+ * file-collision refusal.
69
+ */
70
+ readonly siblingFiles?: readonly string[] | undefined;
71
+ }
72
+
73
+ export interface ForkComponentPlan {
74
+ /** The forked component's name inside the copy, and at the retargeted tag. */
75
+ readonly newName: string;
76
+ /** `EnemyBravo.tsx` — the caller joins it onto the definition's directory. */
77
+ readonly newFileName: string;
78
+ /** The new module's path, normalized to forward slashes. */
79
+ readonly newFile: string;
80
+ /** The complete bytes of the new module (the copy, renamed). */
81
+ readonly newFileSource: string;
82
+ readonly callsiteFile: string;
83
+ readonly callsitePrevSource: string;
84
+ readonly callsiteNewSource: string;
85
+ /** The specifier written into the callsite's new import. */
86
+ readonly importSpecifier: string;
87
+ /** The component name as it was spelled at the callsite before the fork. */
88
+ readonly tag: string;
89
+ /** The history label for the CALLSITE edit (the new file is outside history). */
90
+ readonly historyLabel: string;
91
+ }
92
+
93
+ export type ForkComponentPlanResult =
94
+ | { readonly ok: true; readonly plan: ForkComponentPlan }
95
+ | { readonly ok: false; readonly reason: string };
96
+
97
+ function refuse(reason: string): ForkComponentPlanResult {
98
+ return { ok: false, reason };
99
+ }
100
+
101
+ // ------------------------------------------------------------------- paths
102
+
103
+ /** Forward-slash form; a Windows path from the OID index normalizes here. */
104
+ function normalizePath(path: string): string {
105
+ return path.replace(/\\/g, '/');
106
+ }
107
+
108
+ function directoryOf(path: string): string {
109
+ const clean = normalizePath(path);
110
+ const cut = clean.lastIndexOf('/');
111
+ return cut < 0 ? '' : clean.slice(0, cut);
112
+ }
113
+
114
+ /** `siblingOf('src/Enemy.tsx', 'Fork.tsx')` → `src/Fork.tsx`; a bare filename
115
+ * (no directory at all) stays bare rather than becoming root-absolute. */
116
+ function siblingOf(path: string, fileName: string): string {
117
+ const dir = directoryOf(path);
118
+ return dir ? `${dir}/${fileName}` : fileName;
119
+ }
120
+
121
+ // -------------------------------------------------------------- declarations
122
+
123
+ interface ComponentDeclaration {
124
+ readonly exported: boolean;
125
+ readonly isDefault: boolean;
126
+ }
127
+
128
+ /**
129
+ * The component's own declaration in its module — a function declaration or a
130
+ * `const` bound to an arrow/function expression, the same two shapes
131
+ * `oid-transform.ts`'s `componentDefinitions` recognizes as a component. A
132
+ * `memo(...)`/`forwardRef(...)` wrapper is deliberately NOT matched: the fork
133
+ * would have to guess where the name lives, and a named refusal beats a guess.
134
+ */
135
+ function declarationOf(sf: ts.SourceFile, name: string): ComponentDeclaration | null {
136
+ for (const statement of sf.statements) {
137
+ if (ts.isFunctionDeclaration(statement) && statement.name?.text === name && statement.body) {
138
+ return {
139
+ exported: hasModifier(statement, ts.SyntaxKind.ExportKeyword),
140
+ isDefault: hasModifier(statement, ts.SyntaxKind.DefaultKeyword),
141
+ };
142
+ }
143
+ if (!ts.isVariableStatement(statement)) continue;
144
+ for (const declaration of statement.declarationList.declarations) {
145
+ if (
146
+ ts.isIdentifier(declaration.name) &&
147
+ declaration.name.text === name &&
148
+ declaration.initializer &&
149
+ (ts.isArrowFunction(declaration.initializer) ||
150
+ ts.isFunctionExpression(declaration.initializer))
151
+ ) {
152
+ return {
153
+ exported: hasModifier(statement, ts.SyntaxKind.ExportKeyword),
154
+ isDefault: false,
155
+ };
156
+ }
157
+ }
158
+ }
159
+ return null;
160
+ }
161
+
162
+ /** How the copy will EXPORT the renamed component — which decides whether the
163
+ * callsite gets a named or a default import. `null` means it is not exported
164
+ * at all, which the fork refuses (the retargeted callsite could not import
165
+ * it). */
166
+ function exportFormOf(
167
+ sf: ts.SourceFile,
168
+ name: string,
169
+ declaration: ComponentDeclaration,
170
+ ): 'named' | 'default' | null {
171
+ if (declaration.isDefault) return 'default';
172
+ if (declaration.exported) return 'named';
173
+ for (const statement of sf.statements) {
174
+ const form = exportStatementForm(statement, name);
175
+ if (form) return form;
176
+ }
177
+ return null;
178
+ }
179
+
180
+ /** `export default Enemy;` / `export { Enemy }` / `export { Enemy as default }`. */
181
+ function exportStatementForm(statement: ts.Statement, name: string): 'named' | 'default' | null {
182
+ if (ts.isExportAssignment(statement)) {
183
+ const isDefault =
184
+ statement.isExportEquals !== true &&
185
+ ts.isIdentifier(statement.expression) &&
186
+ statement.expression.text === name;
187
+ return isDefault ? 'default' : null;
188
+ }
189
+ if (!ts.isExportDeclaration(statement) || statement.moduleSpecifier) return null;
190
+ const clause = statement.exportClause;
191
+ if (!clause || !ts.isNamedExports(clause)) return null;
192
+ for (const element of clause.elements) {
193
+ if ((element.propertyName ?? element.name).text !== name) continue;
194
+ return element.name.text === 'default' ? 'default' : 'named';
195
+ }
196
+ return null;
197
+ }
198
+
199
+ /** Every binding this module introduces at the top level — imports included.
200
+ * The fork's name must collide with none of them, in either file. */
201
+ function topLevelNames(sf: ts.SourceFile): Set<string> {
202
+ const names = new Set<string>();
203
+ for (const statement of sf.statements) {
204
+ for (const name of statementNames(statement)) names.add(name);
205
+ }
206
+ return names;
207
+ }
208
+
209
+ function statementNames(statement: ts.Statement): string[] {
210
+ if (ts.isImportDeclaration(statement)) return importedNames(statement);
211
+ if (ts.isVariableStatement(statement)) {
212
+ return statement.declarationList.declarations.flatMap((declaration) =>
213
+ boundNames(declaration.name),
214
+ );
215
+ }
216
+ if (!NAMED_DECLARATION_KINDS.has(statement.kind)) return [];
217
+ const named = (statement as { name?: ts.Identifier }).name;
218
+ return named ? [named.text] : [];
219
+ }
220
+
221
+ function boundNames(node: ts.BindingName): string[] {
222
+ if (ts.isIdentifier(node)) return [node.text];
223
+ return node.elements.flatMap((element) =>
224
+ ts.isBindingElement(element) ? boundNames(element.name) : [],
225
+ );
226
+ }
227
+
228
+ const NAMED_DECLARATION_KINDS: ReadonlySet<ts.SyntaxKind> = new Set([
229
+ ts.SyntaxKind.FunctionDeclaration,
230
+ ts.SyntaxKind.ClassDeclaration,
231
+ ts.SyntaxKind.InterfaceDeclaration,
232
+ ts.SyntaxKind.TypeAliasDeclaration,
233
+ ts.SyntaxKind.EnumDeclaration,
234
+ ]);
235
+
236
+ function importedNames(statement: ts.ImportDeclaration): string[] {
237
+ const clause = statement.importClause;
238
+ if (!clause) return [];
239
+ const names = clause.name ? [clause.name.text] : [];
240
+ const bindings = clause.namedBindings;
241
+ if (!bindings) return names;
242
+ if (ts.isNamespaceImport(bindings)) return [...names, bindings.name.text];
243
+ return [...names, ...bindings.elements.map((element) => element.name.text)];
244
+ }
245
+
246
+ /** The name the definition module actually declares for the tag spelled at the
247
+ * callsite. Usually the same string; an aliased (`import { Enemy as Foe }`) or
248
+ * default import makes them differ, and renaming the wrong one would produce a
249
+ * copy that does not compile. */
250
+ function resolveDeclaredName(
251
+ definitionSf: ts.SourceFile,
252
+ callsiteSf: ts.SourceFile,
253
+ tag: string,
254
+ ): string | null {
255
+ if (declarationOf(definitionSf, tag)) return tag;
256
+ const imported = importedOrigin(callsiteSf, tag);
257
+ if (!imported) return null;
258
+ const original = imported === 'default' ? defaultExportName(definitionSf) : imported;
259
+ return original && declarationOf(definitionSf, original) ? original : null;
260
+ }
261
+
262
+ /** What the callsite's `tag` binding is imported AS: the exporting module's own
263
+ * name for it, or the sentinel `'default'`. `null` when it is not imported. */
264
+ function importedOrigin(callsiteSf: ts.SourceFile, tag: string): string | null {
265
+ for (const statement of callsiteSf.statements) {
266
+ if (!ts.isImportDeclaration(statement) || !statement.importClause) continue;
267
+ const clause = statement.importClause;
268
+ if (clause.name?.text === tag) return 'default';
269
+ const bindings = clause.namedBindings;
270
+ if (!bindings || !ts.isNamedImports(bindings)) continue;
271
+ for (const element of bindings.elements) {
272
+ if (element.name.text === tag) return (element.propertyName ?? element.name).text;
273
+ }
274
+ }
275
+ return null;
276
+ }
277
+
278
+ function defaultExportName(sf: ts.SourceFile): string | null {
279
+ for (const statement of sf.statements) {
280
+ if (
281
+ ts.isFunctionDeclaration(statement) &&
282
+ statement.name &&
283
+ hasModifier(statement, ts.SyntaxKind.DefaultKeyword)
284
+ ) {
285
+ return statement.name.text;
286
+ }
287
+ if (
288
+ ts.isExportAssignment(statement) &&
289
+ statement.isExportEquals !== true &&
290
+ ts.isIdentifier(statement.expression)
291
+ ) {
292
+ return statement.expression.text;
293
+ }
294
+ }
295
+ return null;
296
+ }
297
+
298
+ // -------------------------------------------------------------------- naming
299
+
300
+ /** `patrol guard 2` → `PatrolGuard2`; `""`/`"2fast"` → `null` (not an
301
+ * identifier, so the caller falls back to `<Tag>Fork`). */
302
+ export function pascalCaseIdentifier(seed: string | undefined): string | null {
303
+ if (!seed) return null;
304
+ const parts = seed.split(/[^A-Za-z0-9]+/).filter(Boolean);
305
+ if (parts.length === 0) return null;
306
+ const joined = parts.map((part) => `${part.charAt(0).toUpperCase()}${part.slice(1)}`).join('');
307
+ if (!IDENTIFIER_RE.test(joined)) return null;
308
+ if (!/^[A-Z]/.test(joined)) return null;
309
+ return joined;
310
+ }
311
+
312
+ /**
313
+ * The fork's name: the instance's `name` prop when it is usable and free,
314
+ * otherwise `<Tag>Fork`, `<Tag>Fork2`, … `null` when even the fallback series
315
+ * is exhausted (99 forks of one component in one directory).
316
+ */
317
+ export function pickForkName(
318
+ tag: string,
319
+ seed: string | undefined,
320
+ taken: ReadonlySet<string>,
321
+ ): string | null {
322
+ const fromSeed = pascalCaseIdentifier(seed);
323
+ if (fromSeed && !taken.has(fromSeed)) return fromSeed;
324
+ for (let suffix = 1; suffix <= MAX_FALLBACK_SUFFIX; suffix += 1) {
325
+ const candidate = `${tag}Fork${suffix === 1 ? '' : suffix}`;
326
+ if (!taken.has(candidate)) return candidate;
327
+ }
328
+ return null;
329
+ }
330
+
331
+ // --------------------------------------------------------------- the rename
332
+
333
+ interface Replacement {
334
+ readonly start: number;
335
+ readonly end: number;
336
+ readonly text: string;
337
+ }
338
+
339
+ function applyReplacements(source: string, replacements: readonly Replacement[]): string {
340
+ let out = source;
341
+ for (const replacement of [...replacements].sort((a, b) => b.start - a.start)) {
342
+ out = out.slice(0, replacement.start) + replacement.text + out.slice(replacement.end);
343
+ }
344
+ return out;
345
+ }
346
+
347
+ /**
348
+ * Rename every reference to `name` in this module — AST-driven, never a regex.
349
+ *
350
+ * Renamed: the declaration, ordinary references, self-recursive JSX usage
351
+ * (`<Enemy>` inside `Enemy`'s own body), `export { Enemy }`, `export default
352
+ * Enemy`, type positions such as `typeof Enemy`. NOT renamed: anything that
353
+ * merely SPELLS the same text in a non-reference position — a property access
354
+ * (`registry.Enemy`), an object-literal key, a JSX attribute name, a
355
+ * destructuring property name, a member of a type. The props type
356
+ * (`EnemyProps`) is a different identifier and is deliberately untouched: H7
357
+ * renames the component, nothing else.
358
+ *
359
+ * A shorthand property (`{ Enemy }`) is EXPANDED to `{ Enemy: EnemyBravo }`
360
+ * rather than renamed, because renaming it silently changes the key.
361
+ *
362
+ * Known v1 limit, recorded rather than hidden: an inner scope that re-declares
363
+ * the same name would have its references renamed too. Detecting that needs a
364
+ * scope walk this action does not carry, and a component module shadowing its
365
+ * own component name is not a shape we have seen.
366
+ */
367
+ export function renameComponentInModule(
368
+ file: string,
369
+ source: string,
370
+ name: string,
371
+ newName: string,
372
+ ): string {
373
+ const sf = parseAuthoringTsx(file, source);
374
+ const replacements: Replacement[] = [];
375
+ const visit = (node: ts.Node): void => {
376
+ if (ts.isIdentifier(node) && node.text === name) {
377
+ const parent = node.parent as ts.Node | undefined;
378
+ if (parent && ts.isShorthandPropertyAssignment(parent) && parent.name === node) {
379
+ replacements.push({
380
+ start: node.getStart(sf),
381
+ end: node.getEnd(),
382
+ text: `${name}: ${newName}`,
383
+ });
384
+ } else if (isReferencePosition(node, parent)) {
385
+ replacements.push({ start: node.getStart(sf), end: node.getEnd(), text: newName });
386
+ }
387
+ }
388
+ ts.forEachChild(node, visit);
389
+ };
390
+ ts.forEachChild(sf, visit);
391
+ return applyReplacements(source, replacements);
392
+ }
393
+
394
+ /** Parents whose `name` child is a KEY, not a reference to a binding. */
395
+ const NAME_IS_A_KEY_KINDS: ReadonlySet<ts.SyntaxKind> = new Set([
396
+ ts.SyntaxKind.PropertyAccessExpression,
397
+ ts.SyntaxKind.PropertyAssignment,
398
+ ts.SyntaxKind.JsxAttribute,
399
+ ts.SyntaxKind.PropertySignature,
400
+ ts.SyntaxKind.PropertyDeclaration,
401
+ ts.SyntaxKind.MethodSignature,
402
+ ts.SyntaxKind.MethodDeclaration,
403
+ ts.SyntaxKind.EnumMember,
404
+ ]);
405
+
406
+ function isReferencePosition(node: ts.Identifier, parent: ts.Node | undefined): boolean {
407
+ if (!parent) return true;
408
+ if (ts.isQualifiedName(parent)) return parent.right !== node;
409
+ if (ts.isBindingElement(parent)) return parent.propertyName !== node;
410
+ if (!NAME_IS_A_KEY_KINDS.has(parent.kind)) return true;
411
+ return (parent as { name?: ts.Node }).name !== node;
412
+ }
413
+
414
+ // ------------------------------------------------------------ callsite edit
415
+
416
+ interface ImportStyle {
417
+ readonly quote: string;
418
+ readonly semi: boolean;
419
+ readonly extension: string;
420
+ /** Offset the new import statement is inserted at, and what follows it. */
421
+ readonly insertAt: number;
422
+ readonly leading: string;
423
+ readonly trailing: string;
424
+ }
425
+
426
+ /** Match the file's own import spelling rather than imposing one — the fork's
427
+ * line should be indistinguishable from the ones already there. */
428
+ function importStyleOf(sf: ts.SourceFile, source: string): ImportStyle {
429
+ const imports = sf.statements.filter(ts.isImportDeclaration);
430
+ const last = imports[imports.length - 1];
431
+ const first = imports[0];
432
+ let quote = "'";
433
+ let extension = '';
434
+ if (first) {
435
+ const specifierStart = first.moduleSpecifier.getStart(sf);
436
+ if (source[specifierStart] === '"') quote = '"';
437
+ }
438
+ for (const declaration of imports) {
439
+ if (!ts.isStringLiteral(declaration.moduleSpecifier)) continue;
440
+ const text = declaration.moduleSpecifier.text;
441
+ if (!text.startsWith('.')) continue;
442
+ const match = SOURCE_EXTENSION_RE.exec(text);
443
+ if (match) extension = match[0];
444
+ break;
445
+ }
446
+ const semi = last ? source.slice(0, last.getEnd()).trimEnd().endsWith(';') : true;
447
+ if (last) {
448
+ return { quote, semi, extension, insertAt: last.getEnd(), leading: '\n', trailing: '' };
449
+ }
450
+ // No imports at all: the file's very top is the only position that cannot
451
+ // detach a doc comment from the statement it documents.
452
+ return { quote, semi, extension, insertAt: 0, leading: '', trailing: '\n' };
453
+ }
454
+
455
+ function jsxAtOffset(
456
+ sf: ts.SourceFile,
457
+ offset: number,
458
+ ): ts.JsxOpeningElement | ts.JsxSelfClosingElement | null {
459
+ let found: ts.JsxOpeningElement | ts.JsxSelfClosingElement | null = null;
460
+ const visit = (node: ts.Node): void => {
461
+ if (found) return;
462
+ if (
463
+ (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) &&
464
+ node.getStart(sf) === offset
465
+ ) {
466
+ found = node;
467
+ return;
468
+ }
469
+ ts.forEachChild(node, visit);
470
+ };
471
+ ts.forEachChild(sf, visit);
472
+ return found;
473
+ }
474
+
475
+ // ------------------------------------------------------------------- the plan
476
+
477
+ /**
478
+ * The refusals that need no parsing at all: what the tag IS, and where the
479
+ * definition lives relative to the callsite.
480
+ *
481
+ * The same-file case is a real and deliberate limit. A component declared in the
482
+ * world file itself cannot be forked by copying its module, because the copy
483
+ * would carry the callsite too; extracting just the declaration is the selective
484
+ * scope analysis this action refuses to grow. So it says so, and names the fix.
485
+ */
486
+ function refusedByShape(tag: string, callsiteFile: string, definitionFile: string): string | null {
487
+ if (!/^[A-Z]/.test(tag)) {
488
+ return `<${tag}> is a native element, not a component instance — there is no definition to fork.`;
489
+ }
490
+ if (tag.includes('.')) {
491
+ return `<${tag}> is a namespaced tag; fork can only copy a component declared as a plain module export.`;
492
+ }
493
+ if (normalizePath(callsiteFile) === normalizePath(definitionFile)) {
494
+ return (
495
+ `<${tag}> is declared in the same file as this callsite. Fork copies the component's whole ` +
496
+ 'module, and copying this file would duplicate the callsite too — move the component into ' +
497
+ 'its own module first.'
498
+ );
499
+ }
500
+ return null;
501
+ }
502
+
503
+ /**
504
+ * Plan a fork: parse both files, validate everything, and return the exact
505
+ * bytes of BOTH edits. Nothing here writes; the caller writes the new file
506
+ * first and the callsite second (see the route handler), so a failure after the
507
+ * new file lands leaves an inert module nothing imports.
508
+ */
509
+ export function planComponentFork(request: ForkComponentRequest): ForkComponentPlanResult {
510
+ const { tag, callsiteFile, callsiteSource, definitionFile, definitionSource } = request;
511
+
512
+ const shapeRefusal = refusedByShape(tag, callsiteFile, definitionFile);
513
+ if (shapeRefusal) return refuse(shapeRefusal);
514
+
515
+ const callsiteSf = parseAuthoringTsx(callsiteFile, callsiteSource);
516
+ const definitionSf = parseAuthoringTsx(definitionFile, definitionSource);
517
+
518
+ // The callsite must still BE the tag the menu was built from. An index that
519
+ // is one edit stale would otherwise retarget an innocent neighbouring tag.
520
+ const offset = lineColToOffset(callsiteSource, request.callsiteLine, request.callsiteCol);
521
+ const opening = jsxAtOffset(callsiteSf, offset);
522
+ if (!opening || opening.tagName.getText(callsiteSf) !== tag) {
523
+ return refuse(
524
+ `The callsite at ${callsiteFile}:${request.callsiteLine} is no longer <${tag}> — the source ` +
525
+ 'changed under the editor. Reselect the instance and try again.',
526
+ );
527
+ }
528
+
529
+ const declaredName = resolveDeclaredName(definitionSf, callsiteSf, tag);
530
+ const declaration = declaredName ? declarationOf(definitionSf, declaredName) : null;
531
+ if (!declaredName || !declaration) {
532
+ return refuse(
533
+ `Could not find the declaration of <${tag}> in ${definitionFile}. Fork copies a component ` +
534
+ 'written as a function declaration or a const arrow function; this one is neither.',
535
+ );
536
+ }
537
+ const exportForm = exportFormOf(definitionSf, declaredName, declaration);
538
+ if (!exportForm) {
539
+ return refuse(
540
+ `<${tag}> is not exported from ${definitionFile}, so a forked copy could not be imported here.`,
541
+ );
542
+ }
543
+
544
+ const siblings = request.siblingFiles ?? [];
545
+ const taken = new Set<string>([
546
+ ...topLevelNames(callsiteSf),
547
+ ...topLevelNames(definitionSf),
548
+ // H7's "any export of the target directory's modules you can cheaply
549
+ // check": a module's basename is the proxy — this planner may not read a
550
+ // directory, and reading every sibling's exports is not cheap.
551
+ ...siblings.map((name) => name.replace(SOURCE_EXTENSION_RE, '')),
552
+ tag,
553
+ declaredName,
554
+ ]);
555
+ const newName = pickForkName(tag, request.nameSeed, taken);
556
+ if (!newName) {
557
+ return refuse(
558
+ `Could not find a free name for a fork of <${tag}> — every candidate through ` +
559
+ `${tag}Fork${MAX_FALLBACK_SUFFIX} is already taken.`,
560
+ );
561
+ }
562
+
563
+ const newFileName = `${newName}.tsx`;
564
+ const collision = siblings.find((name) => name.toLowerCase() === newFileName.toLowerCase());
565
+ if (collision) {
566
+ return refuse(
567
+ `${siblingOf(definitionFile, collision)} already exists — fork will not overwrite a file.`,
568
+ );
569
+ }
570
+
571
+ const newFile = siblingOf(definitionFile, newFileName);
572
+ const newFileSource = renameComponentInModule(newFile, definitionSource, declaredName, newName);
573
+
574
+ const style = importStyleOf(callsiteSf, callsiteSource);
575
+ const importSpecifier = relativeImportSpecifier(callsiteFile, newFile);
576
+ const clause = exportForm === 'default' ? newName : `{ ${newName} }`;
577
+ const importText = `import ${clause} from ${style.quote}${importSpecifier}${style.quote}${
578
+ style.semi ? ';' : ''
579
+ }`;
580
+
581
+ // The OLD import may now be unused. It is left alone ON PURPOSE: pruning an
582
+ // import is lint's job (Biome reports it, and the same component may still be
583
+ // used by another tag in this file), and a fork that silently deleted a line
584
+ // it was not asked about would be a second, invisible edit.
585
+ const replacements: Replacement[] = [
586
+ {
587
+ start: opening.tagName.getStart(callsiteSf),
588
+ end: opening.tagName.getEnd(),
589
+ text: newName,
590
+ },
591
+ {
592
+ start: style.insertAt,
593
+ end: style.insertAt,
594
+ text: `${style.leading}${importText}${style.trailing}`,
595
+ },
596
+ ];
597
+ const parent = opening.parent as ts.Node | undefined;
598
+ if (parent && ts.isJsxElement(parent) && parent.openingElement === opening) {
599
+ replacements.push({
600
+ start: parent.closingElement.tagName.getStart(callsiteSf),
601
+ end: parent.closingElement.tagName.getEnd(),
602
+ text: newName,
603
+ });
604
+ }
605
+
606
+ return {
607
+ ok: true,
608
+ plan: {
609
+ newName,
610
+ newFileName,
611
+ newFile,
612
+ newFileSource,
613
+ callsiteFile,
614
+ callsitePrevSource: callsiteSource,
615
+ callsiteNewSource: applyReplacements(callsiteSource, replacements),
616
+ importSpecifier,
617
+ tag,
618
+ historyLabel: `Fork ${tag} → ${newName}`,
619
+ },
620
+ };
621
+ }