@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,184 @@
1
+ /**
2
+ * One portable-CSF thumbnail — the CSF lane's answer to "what does this
3
+ * component look like?", the picture behind every registered content entry,
4
+ * which is what the Content grid paints and what the Inspector's component
5
+ * preview shows (`content-entry-source-registry.ts`). Surface chooses the
6
+ * native renderer; the story remains the sole preview authority for both Three
7
+ * and Pixi prefabs.
8
+ *
9
+ * It was `components/StoryComponentThumbnail.tsx`, imported by name from three
10
+ * host surfaces. All three ask a registered SOURCE now, so this module has
11
+ * exactly one importer — `component-content-source.tsx`, beside it.
12
+ */
13
+
14
+ import { useEffect, useState } from 'react';
15
+ import type { ProjectComponentEntry } from '../asset-workflow/project-content';
16
+ import { TypedAssetThumbnail } from '../components/asset-thumbnails';
17
+ import { waitForFirstViewportFrame } from '../viewport-activation-timings';
18
+ import type { PixiStoryThumbnailOptions } from './story-pixi-preview';
19
+ import type { ProjectPreviewStory } from './story-registry';
20
+ import type { StoryPreviewComponent } from './story-three-preview';
21
+ import { threeStoryThumbnailKey } from './three-story-model';
22
+
23
+ const previewCache = new Map<string, string>();
24
+ const previewPending = new Map<string, Promise<string>>();
25
+ const storyComponentIdentities = new WeakMap<StoryPreviewComponent, number>();
26
+ let previewTail = Promise.resolve();
27
+ let initialPreviewTurn: Promise<void> | null = null;
28
+ let nextStoryComponentIdentity = 1;
29
+
30
+ function supportsStoryCapture(): boolean {
31
+ return (
32
+ typeof WebGLRenderingContext !== 'undefined' &&
33
+ typeof navigator !== 'undefined' &&
34
+ !navigator.userAgent.toLowerCase().includes('jsdom')
35
+ );
36
+ }
37
+
38
+ /** Keep GPU-backed card generation behind the authored viewport the user is
39
+ * waiting to see. A visible Content grid can mount many cards in the shell's
40
+ * first React commit; starting their off-screen renderers immediately made
41
+ * those thumbnails win the first WebGL context and delayed Scene by seconds. */
42
+ async function waitForInitialPreviewTurnInner(): Promise<void> {
43
+ await Promise.race([
44
+ waitForFirstViewportFrame(),
45
+ new Promise<void>((resolve) => setTimeout(resolve, 5_000)),
46
+ ]);
47
+ // `recordViewportFirstFrame` runs immediately after issuing the draw, before
48
+ // the browser has necessarily composited it. Cross two animation frames so
49
+ // at least one paint can land before an off-screen thumbnail asks the GPU to
50
+ // create another renderer. Hidden tabs get a bounded timer fallback.
51
+ await Promise.race([
52
+ new Promise<void>((resolve) =>
53
+ requestAnimationFrame(() => requestAnimationFrame(() => resolve())),
54
+ ),
55
+ new Promise<void>((resolve) => setTimeout(resolve, 250)),
56
+ ]);
57
+ // Give pointer/automation tasks a turn after that paint. An idle callback can
58
+ // legally run before an external observer is scheduled; without this small
59
+ // grace period a software WebGL thumbnail context began immediately after
60
+ // Scene's first draw and made an already-visible cube appear two seconds
61
+ // late to the person (and to the editor's own control client).
62
+ await new Promise<void>((resolve) => setTimeout(resolve, 750));
63
+ await new Promise<void>((resolve) => {
64
+ const idle = globalThis.requestIdleCallback;
65
+ if (typeof idle === 'function') {
66
+ idle(() => resolve(), { timeout: 2_000 });
67
+ return;
68
+ }
69
+ setTimeout(resolve, 0);
70
+ });
71
+ }
72
+
73
+ function waitForInitialPreviewTurn(): Promise<void> {
74
+ initialPreviewTurn ??= waitForInitialPreviewTurnInner();
75
+ return initialPreviewTurn;
76
+ }
77
+
78
+ function storyComponentIdentity(component: StoryPreviewComponent): number {
79
+ const existing = storyComponentIdentities.get(component);
80
+ if (existing !== undefined) return existing;
81
+ const identity = nextStoryComponentIdentity++;
82
+ storyComponentIdentities.set(component, identity);
83
+ return identity;
84
+ }
85
+
86
+ function requestPreview(
87
+ key: string,
88
+ surface: ProjectComponentEntry['surface'],
89
+ story: ProjectPreviewStory,
90
+ size: { readonly width: number; readonly height: number },
91
+ ): Promise<string> {
92
+ const cached = previewCache.get(key);
93
+ if (cached) return Promise.resolve(cached);
94
+ const pending = previewPending.get(key);
95
+ if (pending) return pending;
96
+ const request = previewTail.then(async () => {
97
+ // Only the first off-screen renderer waits behind the opening viewport.
98
+ // `previewTail` already serializes all later GPU work; charging the paint
99
+ // grace to every card would make a full Content grid reveal one thumbnail
100
+ // every 750ms even after Scene is settled.
101
+ await waitForInitialPreviewTurn();
102
+ const declaredLayout = story.parameters['layout'];
103
+ const layout: PixiStoryThumbnailOptions['layout'] =
104
+ declaredLayout === 'fullscreen' ||
105
+ declaredLayout === 'padded' ||
106
+ declaredLayout === 'centered'
107
+ ? declaredLayout
108
+ : 'padded';
109
+ const options = { ...size, props: story.args, layout };
110
+ if (surface === 'canvas') {
111
+ const { capturePixiStoryThumbnail } = await import('./story-pixi-preview');
112
+ return capturePixiStoryThumbnail(story.Component as StoryPreviewComponent, options);
113
+ }
114
+ const { captureStoryComponentThumbnail } = await import('./story-three-preview');
115
+ return captureStoryComponentThumbnail(story.Component as StoryPreviewComponent, options);
116
+ });
117
+ previewTail = request.then(
118
+ () => undefined,
119
+ () => undefined,
120
+ );
121
+ previewPending.set(key, request);
122
+ void request.then(
123
+ (url) => {
124
+ previewCache.set(key, url);
125
+ previewPending.delete(key);
126
+ },
127
+ () => previewPending.delete(key),
128
+ );
129
+ return request;
130
+ }
131
+
132
+ export function StoryComponentThumbnail({
133
+ component,
134
+ story,
135
+ previewRevision,
136
+ width = 128,
137
+ height = 96,
138
+ }: {
139
+ component: Pick<ProjectComponentEntry, 'name' | 'path' | 'surface'>;
140
+ story: ProjectPreviewStory;
141
+ previewRevision: number;
142
+ /** Requested capture size. Content cards use 128×96; square Inspector
143
+ * previews request a square so the native subject is never cropped merely
144
+ * to fit different chrome. */
145
+ width?: number;
146
+ height?: number;
147
+ }) {
148
+ const StoryComponent = story.Component as StoryPreviewComponent;
149
+ // HMR replaces the composed component even when the story id/args stay the
150
+ // same. Include that native function identity so the Inspector cannot keep
151
+ // displaying the old capture after the source changed.
152
+ const key = `${component.surface}:${component.path}:${threeStoryThumbnailKey(story.id, story.args)}:${storyComponentIdentity(StoryComponent)}:${previewRevision}:${width}x${height}`;
153
+ const [url, setUrl] = useState(() => previewCache.get(key));
154
+ const [captureFailed, setCaptureFailed] = useState(false);
155
+
156
+ useEffect(() => {
157
+ let cancelled = false;
158
+ setCaptureFailed(false);
159
+ setUrl(previewCache.get(key));
160
+ if (!supportsStoryCapture()) return;
161
+ void requestPreview(key, component.surface, story, { width, height }).then(
162
+ (nextUrl) => {
163
+ if (!cancelled) setUrl(nextUrl);
164
+ },
165
+ () => {
166
+ if (!cancelled) setCaptureFailed(true);
167
+ },
168
+ );
169
+ return () => {
170
+ cancelled = true;
171
+ };
172
+ }, [component.surface, height, key, story, width]);
173
+
174
+ return url ? (
175
+ <img src={url} alt={`${component.name} preview`} className="vgai-component-thumbnail" />
176
+ ) : (
177
+ <span
178
+ className="vgai-component-thumbnail-fallback"
179
+ data-component-preview={captureFailed ? 'failed' : 'capturing-story'}
180
+ >
181
+ <TypedAssetThumbnail kind="component" name={component.name} />
182
+ </span>
183
+ );
184
+ }
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Isolated story preview mount — C3 (spec §9 "A story may be opened in an
3
+ * isolated editor preview"). Renders one composed story (`ComposedProjectStory`
4
+ * from `compose-project-stories.ts`) into a SEPARATE `react-dom/client` root,
5
+ * not a child of the editor's own React tree: the preview container div is
6
+ * handed to its own `createRoot`, so a story's own React version/context/
7
+ * error state can never leak into (or be affected by) the editor shell's
8
+ * tree — the same isolation a Storybook iframe gives you, achieved here with
9
+ * a dedicated root instead (this editor has no existing iframe-preview
10
+ * pattern to reuse — see the module doc comment on `StoriesPanel.tsx`).
11
+ *
12
+ * Error handling (spec §9 "Errors identify the source module and story
13
+ * export"): a story that throws while rendering is caught by
14
+ * `StoryPreviewErrorBoundary` (mirrors `ToolHost.tsx`'s `ToolErrorBoundary`)
15
+ * and reported with BOTH the module path and the story export name — one
16
+ * throwing story never takes down the panel or another story's preview.
17
+ *
18
+ * Play functions (spec §9 "supported play functions mount... optional but
19
+ * nice"): `runPlay` below calls the composed story's own `.play()` (Storybook
20
+ * populates it via `composeStories` when the CSF export declares one) inside
21
+ * the SAME error containment, so a throwing play function reports the same
22
+ * module+export naming instead of crashing the preview. `play()` is called
23
+ * with `{ canvasElement }` set to the isolated preview root's own container —
24
+ * without it, Storybook's portable-story `play()` defaults `canvasElement` to
25
+ * `document.body` (confirmed in `storybook/dist/preview-api/index.cjs`'s
26
+ * `composeStory`: `g.canvasElement ??= globalThis?.document?.body`), which
27
+ * would let a story's play() query/interact with the ENTIRE page instead of
28
+ * just its own isolated preview.
29
+ *
30
+ * Loaders (spec §9 "loaders ... mount through Storybook portable-story
31
+ * APIs"): a composed story only runs its `loaders` when `.load()` is
32
+ * explicitly awaited before render. Confirmed directly in Storybook 9's own
33
+ * `composeStory` (`storybook/dist/preview-api/index.cjs`): the render
34
+ * function reads a module-closure variable (`x`) for `loaded` data, and that
35
+ * variable is populated ONLY inside `load: async () => { ...; f.loaded =
36
+ * await c.applyLoaders(f); ...; x = f; }` — i.e. `applyLoaders` (which runs
37
+ * every `loaders` entry) never runs unless `.load()` itself runs first.
38
+ * Rendering the composed component directly (no `.load()`) leaves `loaded`
39
+ * as `{}`. `mountIsolatedStory` below is therefore async and awaits
40
+ * `StoryComponent.load()` before calling `root.render(...)`.
41
+ */
42
+
43
+ import { markGameCssScope } from '@volter/editor-sdk/session/game-css-scope';
44
+ import { themeVars } from '@volter/editor-sdk/widgets';
45
+ import { Component, type ErrorInfo, type ReactNode } from 'react';
46
+ import type { Root } from 'react-dom/client';
47
+ import type { ComposedStoryFn } from 'storybook/internal/types';
48
+ import { getCurrentProject } from '../project-manager';
49
+ import { ensureScopedGameStyles } from '../scoped-game-css';
50
+ import { resolveStoryDomRuntime } from './story-dom-runtime';
51
+
52
+ interface StoryPreviewErrorBoundaryProps {
53
+ modulePath: string;
54
+ storyName: string;
55
+ children: ReactNode;
56
+ }
57
+
58
+ interface StoryPreviewErrorBoundaryState {
59
+ error: Error | null;
60
+ }
61
+
62
+ /** Crash containment for one mounted story — names both the source module
63
+ * AND the story export in the fallback UI and the console, per spec §9. */
64
+ export class StoryPreviewErrorBoundary extends Component<
65
+ StoryPreviewErrorBoundaryProps,
66
+ StoryPreviewErrorBoundaryState
67
+ > {
68
+ override state: StoryPreviewErrorBoundaryState = { error: null };
69
+
70
+ static getDerivedStateFromError(error: Error): StoryPreviewErrorBoundaryState {
71
+ return { error };
72
+ }
73
+
74
+ override componentDidCatch(error: Error, info: ErrorInfo): void {
75
+ // biome-ignore lint/suspicious/noConsole: deliberate, greppable — a crashed story preview must be diagnosable from the console (spec §9 "errors identify the source module and story export"), mirroring ToolHost.tsx's ToolErrorBoundary
76
+ console.error(
77
+ `[stories] ${this.props.modulePath} — story "${this.props.storyName}" crashed while rendering:`,
78
+ error,
79
+ info.componentStack,
80
+ );
81
+ }
82
+
83
+ override render(): ReactNode {
84
+ if (this.state.error) {
85
+ return (
86
+ <div style={{ padding: 12, fontSize: 12, color: themeVars.semantic.danger, maxWidth: 640 }}>
87
+ <div style={{ fontWeight: 600, marginBottom: 4 }}>
88
+ Story crashed: <code>{this.props.modulePath}</code> — export{' '}
89
+ <code>{this.props.storyName}</code>
90
+ </div>
91
+ <div style={{ whiteSpace: 'pre-wrap' }}>{String(this.state.error)}</div>
92
+ </div>
93
+ );
94
+ }
95
+ return this.props.children;
96
+ }
97
+ }
98
+
99
+ /** One container's isolated root plus a generation counter — see
100
+ * `mountIsolatedStory` below for why the counter (not just the `Root`
101
+ * object's identity) is what a stale `unmount()` must check. `root` is
102
+ * `undefined` for the brief window between a mount call CLAIMING a
103
+ * generation (synchronously) and that same call's `await
104
+ * StoryComponent.load()` resolving — no `Root` exists yet for a container
105
+ * that has never been rendered into before (the very first mount), so the
106
+ * reservation itself can't supply one. */
107
+ interface ContainerMount {
108
+ root: Root | undefined;
109
+ generation: number;
110
+ }
111
+
112
+ // One isolated `react-dom/client` root per container, reused across repeated
113
+ // `mountIsolatedStory` calls (e.g. a story switch: `StoriesPanel.tsx`'s
114
+ // `StoryPreviewHost` effect re-fires for the SAME DOM node with a new
115
+ // `StoryComponent`). Calling `createRoot` twice on the SAME node is a hard
116
+ // react-dom warning ("already been passed to createRoot() before") — this
117
+ // map is the guard: a second `mountIsolatedStory` on the same container
118
+ // `.render()`s onto the EXISTING root instead of creating a new one, exactly
119
+ // react-dom's own documented fix for that warning.
120
+ const mountsByContainer = new WeakMap<HTMLElement, ContainerMount>();
121
+
122
+ /**
123
+ * Mount one composed story into `container` via its OWN `createRoot` —
124
+ * isolated from whatever React root `container` itself lives inside.
125
+ * Returns an `unmount` the caller runs on cleanup (e.g. story switch or
126
+ * panel close) — same lifecycle discipline every other editor mount point
127
+ * (`XStateMachineInspector.test.tsx`'s harness, `ToolHost`) uses. Safe to
128
+ * call again on the same `container` before a previous `unmount()` has
129
+ * landed (see `mountsByContainer` above) — the isolated root is reused, and
130
+ * `unmount()` (below) removes it from the container entirely rather than
131
+ * merely clearing its content, so callers who intend a REAL teardown (panel
132
+ * close) still get one.
133
+ *
134
+ * Async: awaits `StoryComponent.load()` (runs the story's `loaders`, per the
135
+ * module doc comment above) BEFORE the first render. The generation counter
136
+ * is claimed SYNCHRONOUSLY (before the `await`), exactly like the sync
137
+ * version did — so a second `mountIsolatedStory` call on the same container
138
+ * (e.g. the user switches stories again while this one's `.load()` is still
139
+ * in flight) still bumps the generation immediately and makes it visible to
140
+ * this in-flight call. After the await, this call re-reads the container's
141
+ * CURRENT generation and bails out (never creates/renders a root, never
142
+ * touches `mountsByContainer`) if it's no longer the current one — so a
143
+ * stale `.load()` resolving late can never win a render race against a
144
+ * newer story switch, even though nothing was mounted yet for it to
145
+ * unmount.
146
+ */
147
+ export async function mountIsolatedStory(
148
+ container: HTMLElement,
149
+ modulePath: string,
150
+ storyName: string,
151
+ StoryComponent: ComposedStoryFn,
152
+ // W2 (story documents): optional per-mount prop overrides. Portable
153
+ // stories are plain React components whose composed args are DEFAULTS —
154
+ // Storybook's own documented portable-story contract lets a caller pass
155
+ // partial props over them (`<Story label="…" />`). The story-document
156
+ // Inspector's editable args and its action-logging spies ride this;
157
+ // omitted (every pre-W2 caller) the render is byte-identical to before.
158
+ overrideProps?: Record<string, unknown>,
159
+ ): Promise<{ root: Root; unmount: () => void } | null> {
160
+ const existing = mountsByContainer.get(container);
161
+ // Bumped on EVERY mount, including a reuse of the same `Root` object (a
162
+ // story switch) — this is the piece a same-root reuse needs that plain
163
+ // `Root`-identity checking (an earlier version of this function) doesn't
164
+ // give you: reusing the root means two DIFFERENT stories' mounts can share
165
+ // the exact same `Root` instance, so a stale `unmount()` comparing
166
+ // `Root`s would see "yes, that's still the registered root" and tear down
167
+ // the NEWER story's render a moment after it landed. Comparing the
168
+ // generation this specific `mountIsolatedStory` call captured against the
169
+ // container's CURRENT generation instead correctly recognizes "a newer
170
+ // mount has since claimed this container" even when the root itself
171
+ // didn't change. Claimed HERE, synchronously, before the `load()` await
172
+ // below — so a newer call arriving while this one awaits sees (and bumps
173
+ // past) this generation immediately, rather than racing to claim the same
174
+ // number once both awaits resolve.
175
+ const generation = (existing?.generation ?? 0) + 1;
176
+ mountsByContainer.set(container, { root: existing?.root, generation });
177
+
178
+ // THE STORY'S OWN PAGE CSS, if its project has any. A story of a foreign
179
+ // game's HUD component is a plain React component whose entire layout lives
180
+ // in that game's page-level stylesheet — without it the card renders real
181
+ // DOM with zero layout, which reads as wreckage rather than as a component.
182
+ // This is the ONE seam every story surface passes through (the UI board's
183
+ // cards, the story documents, `vgai screenshot <file>.stories.tsx`), so
184
+ // marking the container here styles all of them; the sheet itself is
185
+ // installed once per project, never per card (`scoped-game-css.ts`).
186
+ // Deliberately awaited BEFORE the first render so a card never flashes
187
+ // unstyled, and deliberately non-fatal: a project with no declared
188
+ // stylesheet mounts exactly as it did before.
189
+ markGameCssScope(container);
190
+ const currentProject = getCurrentProject();
191
+ if (currentProject) await ensureScopedGameStyles(currentProject.rootPath);
192
+
193
+ // Loaders (spec §9): must run — and their `loaded` data become part of the
194
+ // composed story's render-time context — before the story is ever
195
+ // rendered. See the module doc comment for why this can't be skipped.
196
+ await StoryComponent.load();
197
+
198
+ // WHICH graph's react-dom mounts the story is the packaged-runtime seam
199
+ // (`story-dom-runtime.ts`): the CSF component's hooks resolve against the
200
+ // project's react, so the mounting `createRoot` must come from that same
201
+ // graph or the render dies on "Invalid hook call". Resolved BEFORE the
202
+ // generation re-check below, so the stale-call guard covers every await
203
+ // this call performs. (The error-boundary wrapper stays this bundle's own
204
+ // React deliberately: it is a class component — no hooks, no dispatcher —
205
+ // and React elements are cross-instance by design via Symbol.for.)
206
+ const { createRoot, flushSync } = await resolveStoryDomRuntime();
207
+
208
+ // Re-check AFTER the await: if a newer `mountIsolatedStory` call (story
209
+ // switch) has since claimed this container, its generation will have
210
+ // moved past `generation` above — this stale call must not create a root
211
+ // or render into a container a newer story already owns (or is about to).
212
+ const afterLoad = mountsByContainer.get(container);
213
+ if (!afterLoad || afterLoad.generation !== generation) return null;
214
+
215
+ const root = existing?.root ?? createRoot(container);
216
+ mountsByContainer.set(container, { root, generation });
217
+
218
+ // A resolved mount is a COMMITTED mount. The UI/2D boards await this
219
+ // function before announcing their document ready, and Doctor photographs
220
+ // that document immediately afterward. Leaving `root.render()` on React's
221
+ // scheduler produced a perfectly plausible empty board: its synchronous
222
+ // frame chrome existed, but every authored story was still absent. Use the
223
+ // `flushSync` from the SAME project-owned React graph as `createRoot` (the
224
+ // ordinary React design-time entry mount has the identical contract in
225
+ // `design-time-layers.ts`). This is not capture-specific waiting: every
226
+ // caller now receives the honest lifecycle guarantee its return value
227
+ // implies.
228
+ flushSync(() => {
229
+ root.render(
230
+ <StoryPreviewErrorBoundary modulePath={modulePath} storyName={storyName}>
231
+ {/* `ComposedStoryFn` is a callable React function component
232
+ (Storybook's portable-story contract) — its own composed
233
+ args/decorators are already baked in by `composeStories`;
234
+ `overrideProps` (when given) override individual args per that same
235
+ contract. */}
236
+ <StoryComponent {...(overrideProps ?? {})} />
237
+ </StoryPreviewErrorBoundary>,
238
+ );
239
+ });
240
+ return {
241
+ root,
242
+ // Deferred to a microtask, deliberately NOT called synchronously:
243
+ // `unmount` is returned as `StoryPreviewHost`'s effect cleanup, and
244
+ // React runs an effect's cleanup SYNCHRONOUSLY as part of its own
245
+ // render/commit pass whenever the OUTER tree unmounts (e.g. the whole
246
+ // Stories panel closing). React tracks "is any root currently
247
+ // rendering" as a single GLOBAL flag for the whole call stack
248
+ // (`executionContext`, react-dom-client.development.js) — so calling
249
+ // THIS (independent, inner) root's `.unmount()` synchronously from
250
+ // inside that outer pass trips "Attempted to synchronously unmount a
251
+ // root while React was already rendering" even though the inner root
252
+ // itself has nothing in flight. Queuing the call for the next microtask
253
+ // runs it once the outer commit has fully finished and cleared that
254
+ // flag, which is the documented fix for exactly this nested-root
255
+ // pattern (no functional delay — the isolated root is still torn down
256
+ // effectively immediately).
257
+ unmount: () => {
258
+ queueMicrotask(() => {
259
+ // Only the mount that's STILL the container's current generation
260
+ // actually tears the root down — see the `generation` doc comment
261
+ // above for why this can't just compare `Root` identity.
262
+ const current = mountsByContainer.get(container);
263
+ if (!current || current.generation !== generation || !current.root) return;
264
+ mountsByContainer.delete(container);
265
+ current.root.unmount();
266
+ });
267
+ },
268
+ };
269
+ }
270
+
271
+ /**
272
+ * Run a composed story's `.play()` if it declared one, inside the same
273
+ * module+export-naming error containment as render crashes. Returns whether
274
+ * a play function existed and ran ok — the caller (`StoriesPanel`) uses this
275
+ * to show a "no play function" state distinctly from a failure.
276
+ *
277
+ * `canvasElement` is passed through to `.play({ canvasElement })` — the
278
+ * composed story's own `play` accepts `Partial<StoryContext>` (confirmed in
279
+ * `storybook/dist/types/index.d.ts`: `play?: (context?: Partial<StoryContext<...>>)
280
+ * => Promise<void>`, and `StoryContext.canvasElement: TRenderer['canvasElement']`).
281
+ * Without it, Storybook's `composeStory` defaults `canvasElement` to
282
+ * `globalThis.document.body` (`storybook/dist/preview-api/index.cjs`:
283
+ * `g.canvasElement ??= globalThis?.document?.body`), which would let a
284
+ * story's play() query/interact with the WHOLE page instead of just its own
285
+ * isolated preview root.
286
+ */
287
+ export async function runStoryPlay(
288
+ modulePath: string,
289
+ storyName: string,
290
+ StoryComponent: ComposedStoryFn,
291
+ canvasElement: HTMLElement,
292
+ ): Promise<{ ran: boolean; error?: string }> {
293
+ if (typeof StoryComponent.play !== 'function') return { ran: false };
294
+ try {
295
+ await StoryComponent.play({ canvasElement });
296
+ return { ran: true };
297
+ } catch (err) {
298
+ const message = String(err instanceof Error ? err.message : err);
299
+ // biome-ignore lint/suspicious/noConsole: deliberate, greppable — a throwing play() must be diagnosable from the console, same naming discipline as a render crash
300
+ console.error(`[stories] ${modulePath} — story "${storyName}"'s play() threw:`, err);
301
+ return {
302
+ ran: true,
303
+ error: `[stories] ${modulePath} — story "${storyName}"'s play() failed: ${message}`,
304
+ };
305
+ }
306
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * "COMPONENTS WITH A REGISTERED PREVIEW STORY" — this package's filler for the
3
+ * host's Content scope (`@editor/content-entry-source-registry`).
4
+ *
5
+ * A registered portable story is the explicit prefab declaration and its
6
+ * preview authority: source shape alone cannot distinguish a reusable prefab
7
+ * from scene composition or implementation detail, so a component with no
8
+ * colocated story is not a Content entry at all. That rule used to be spelled
9
+ * in `components/AssetBrowser.tsx` — the host's own Content browser knowing
10
+ * what CSF is — and it is the reason the story registry, and through it
11
+ * Storybook, was in every editor boot.
12
+ *
13
+ * WHAT MOVED WITH IT, verbatim:
14
+ * - the admission rule (`pickComponentPreviewStory`, and the surface focus:
15
+ * DOM stories live on their design board, world prefabs stay scoped to the
16
+ * surface that can consume them);
17
+ * - the picture (`StoryComponentThumbnail`);
18
+ * - the open verb — a `three` prefab mounts as an `Object3D`, so it opens as
19
+ * its TURNTABLE (`story:three`, the same document the `3D Components`
20
+ * board's exhibits open on); anything else opens on the isolated story
21
+ * document (`story:isolated`). Both are ADDRESSES
22
+ * (`@editor/document-open-registry`): the documents themselves are
23
+ * `@vgai/game`'s, and a build without it opens neither.
24
+ */
25
+
26
+ import type {
27
+ ContentComponentRef,
28
+ ContentEntry,
29
+ ContentEntrySource,
30
+ ContentEntrySourceContext,
31
+ ContentEntryThumbnailProps,
32
+ } from '../content-entry-source-registry';
33
+ import { openRegisteredDocument } from '../document-open-registry';
34
+ import type { WorkspaceStateStore } from '../workspace-document-restore';
35
+ import { StoryComponentThumbnail } from './StoryComponentThumbnail';
36
+ import {
37
+ ISOLATED_STORY_DOCUMENT_OPENER,
38
+ THREE_STORY_DOCUMENT_OPENER,
39
+ } from './story-document-openers';
40
+ import {
41
+ getProjectStoryModules,
42
+ type ProjectPreviewStory,
43
+ pickComponentPreviewStory,
44
+ subscribeProjectStoryModules,
45
+ } from './story-registry';
46
+
47
+ /** What this source carries on each row: the story that admitted the
48
+ * component, which is also its picture and its open address. */
49
+ type StoryContentDetail = ProjectPreviewStory;
50
+
51
+ function belongsInFocusedContent(
52
+ component: ContentComponentRef,
53
+ surface: ContentEntrySourceContext['surface'],
54
+ ): boolean {
55
+ if (component.surface === 'dom') return false;
56
+ return surface === null || component.surface === surface;
57
+ }
58
+
59
+ function StoryContentThumbnail({
60
+ entry,
61
+ previewRevision,
62
+ width,
63
+ height,
64
+ }: ContentEntryThumbnailProps) {
65
+ const story = entry.detail as StoryContentDetail;
66
+ return (
67
+ <StoryComponentThumbnail
68
+ component={entry.component}
69
+ story={story}
70
+ previewRevision={previewRevision}
71
+ {...(width === undefined ? {} : { width })}
72
+ {...(height === undefined ? {} : { height })}
73
+ />
74
+ );
75
+ }
76
+
77
+ export const STORY_CONTENT_SOURCE_ID = 'story';
78
+
79
+ export const storyComponentContentSource: ContentEntrySource = {
80
+ id: STORY_CONTENT_SOURCE_ID,
81
+ owner: './component-content-source',
82
+ entries(context): readonly ContentEntry[] {
83
+ const modules = getProjectStoryModules();
84
+ const out: ContentEntry[] = [];
85
+ for (const component of context.components) {
86
+ if (!belongsInFocusedContent(component, context.surface)) continue;
87
+ const story = pickComponentPreviewStory(modules, component.name, component.path);
88
+ if (!story) continue;
89
+ out.push({ id: `${component.path}:${component.name}`, component, detail: story });
90
+ }
91
+ return out;
92
+ },
93
+ subscribe: subscribeProjectStoryModules,
94
+ Thumbnail: StoryContentThumbnail,
95
+ open(store: WorkspaceStateStore, entry: ContentEntry, title: string): void {
96
+ const story = entry.detail as StoryContentDetail;
97
+ const three = entry.component.surface === 'three';
98
+ openRegisteredDocument(
99
+ three ? THREE_STORY_DOCUMENT_OPENER : ISOLATED_STORY_DOCUMENT_OPENER,
100
+ store,
101
+ three
102
+ ? { modulePath: story.modulePath, storyName: story.name, title }
103
+ : { modulePath: story.modulePath, storyName: story.name },
104
+ );
105
+ },
106
+ };
@@ -0,0 +1,78 @@
1
+ /**
2
+ * PORTABLE CSF AS A COMPONENT'S NAMED STATES — the source
3
+ * `component-states-registry.ts` is filled with, registered by
4
+ * `story-lane.ts`.
5
+ *
6
+ * It was `authoring/project-three-stories.ts`, two nearly identical
7
+ * factory functions that three host adapters CONSTRUCTED inside their own
8
+ * constructors. The measurement said the two differed by exactly one thing —
9
+ * which document a state opens in — so this is ONE source that dispatches on
10
+ * the asking adapter's surface, the same way the story opener's own readiness
11
+ * does.
12
+ *
13
+ * IT DOES NOT MOUNT A SECOND PREVIEW DIALECT. Applying a state opens the
14
+ * document that already exists for that surface: the Object3D turntable for a
15
+ * three subject (whose portable Storybook component mounts as an Object3D on
16
+ * the standard Asset Lab viewport), and the ordinary isolated story document
17
+ * for a canvas one (whose renderer can mount `@pixi/react` content). The
18
+ * adapter supplies the component identity; the CSF registry owns
19
+ * discovery and association.
20
+ *
21
+ * A `dom` subject is deliberately not an arm: a React world's own states come
22
+ * from `@vgai/dom`'s adapter, which publishes its own `StoriesProvider`
23
+ * against the board it mounts. This source answers for the two surfaces whose
24
+ * adapters used to construct the CSF provider by hand.
25
+ */
26
+
27
+ import type {
28
+ ComponentStatesContext,
29
+ ComponentStatesRef,
30
+ ComponentStatesSource,
31
+ } from '../component-states-registry';
32
+ import { openRegisteredDocument } from '../document-open-registry';
33
+ import { editorConsole } from '../editor-console';
34
+ import {
35
+ ISOLATED_STORY_DOCUMENT_OPENER,
36
+ THREE_STORY_DOCUMENT_OPENER,
37
+ } from './story-document-openers';
38
+ import { getComponentPreviewStories, type ProjectPreviewStory } from './story-registry';
39
+
40
+ function storiesFor(component: ComponentStatesRef): ProjectPreviewStory[] {
41
+ return getComponentPreviewStories(component.name, component.sourcePath);
42
+ }
43
+
44
+ export const componentStatesSource: ComponentStatesSource = {
45
+ id: 'portable-csf',
46
+ owner: './component-states',
47
+ statesFor: (component, context) =>
48
+ context.surface === 'dom'
49
+ ? []
50
+ : storiesFor(component).map((story) => ({ id: story.id, label: story.label })),
51
+ apply: (component, stateId, context: ComponentStatesContext) => {
52
+ const story = storiesFor(component).find((candidate) => candidate.id === stateId);
53
+ if (!story) return;
54
+ if (context.surface === 'three') {
55
+ openRegisteredDocument(THREE_STORY_DOCUMENT_OPENER, context.store, {
56
+ modulePath: story.modulePath,
57
+ storyName: story.name,
58
+ title: story.label,
59
+ });
60
+ return;
61
+ }
62
+ if (context.surface === 'canvas') {
63
+ openRegisteredDocument(ISOLATED_STORY_DOCUMENT_OPENER, context.store, {
64
+ modulePath: story.modulePath,
65
+ storyName: story.name,
66
+ });
67
+ return;
68
+ }
69
+ // `statesFor` never named a state for this surface, so nothing should ever
70
+ // reach here; say so rather than silently doing nothing, because a new
71
+ // surface arriving is exactly how this would go quiet.
72
+ editorConsole.warn(
73
+ `[portable-csf] no story document is registered for the "${context.surface}" surface, ` +
74
+ `so state "${stateId}" of "${component.name}" could not be opened.`,
75
+ 'authoring',
76
+ );
77
+ },
78
+ };