@volter/sdk 0.0.0-stage → 0.5.204

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 (523) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +20 -0
  3. package/README.md +38 -3
  4. package/package.json +510 -4
  5. package/src/account.ts +210 -0
  6. package/src/chrome.ts +88 -0
  7. package/src/client.ts +1646 -0
  8. package/src/commands.ts +66 -0
  9. package/src/contributions.ts +619 -0
  10. package/src/css-numeric-style.ts +97 -0
  11. package/src/document-probe.ts +282 -0
  12. package/src/editor-view.ts +225 -0
  13. package/src/extension.ts +40 -0
  14. package/src/generations.ts +178 -0
  15. package/src/host.ts +1157 -0
  16. package/src/http-transport.browser.ts +14 -0
  17. package/src/http-transport.node.ts +19 -0
  18. package/src/index.ts +131 -0
  19. package/src/kit/CapabilityCoverageSection.tsx +185 -0
  20. package/src/kit/account-client.ts +333 -0
  21. package/src/kit/action-registry.ts +317 -0
  22. package/src/kit/active-product.ts +76 -0
  23. package/src/kit/active-project.ts +155 -0
  24. package/src/kit/adapter-editor-config.ts +25 -0
  25. package/src/kit/adapter-module.ts +7 -0
  26. package/src/kit/adapter-observation.ts +49 -0
  27. package/src/kit/animation/animation-clock.ts +479 -0
  28. package/src/kit/animation/stage-transport.ts +385 -0
  29. package/src/kit/api/assets.ts +365 -0
  30. package/src/kit/api/project-open.ts +355 -0
  31. package/src/kit/api/project-source.ts +180 -0
  32. package/src/kit/api/project-state.ts +110 -0
  33. package/src/kit/api/relay.ts +270 -0
  34. package/src/kit/api/themes.ts +45 -0
  35. package/src/kit/api-asset-library-wire.ts +45 -0
  36. package/src/kit/api-base.ts +10 -0
  37. package/src/kit/api-build.ts +99 -0
  38. package/src/kit/api-git-wire.ts +56 -0
  39. package/src/kit/api-logs.ts +92 -0
  40. package/src/kit/api-project-identity.ts +74 -0
  41. package/src/kit/api-settings.ts +36 -0
  42. package/src/kit/api-worktrees.ts +205 -0
  43. package/src/kit/asset-capabilities.ts +344 -0
  44. package/src/kit/asset-compare-core.ts +171 -0
  45. package/src/kit/asset-editor-context.tsx +101 -0
  46. package/src/kit/asset-events.ts +96 -0
  47. package/src/kit/asset-inspector-actions.ts +87 -0
  48. package/src/kit/asset-selection-viewer-registry.ts +113 -0
  49. package/src/kit/asset-selection.ts +146 -0
  50. package/src/kit/asset-thumbnails.ts +25 -0
  51. package/src/kit/asset-viewers.ts +115 -0
  52. package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
  53. package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
  54. package/src/kit/asset-workflow/asset-ledger.ts +156 -0
  55. package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
  56. package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
  57. package/src/kit/asset-workflow/asset-types.ts +142 -0
  58. package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
  59. package/src/kit/asset-workflow/audio-waveform.ts +22 -0
  60. package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
  61. package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
  62. package/src/kit/asset-workflow/image-view-scale.ts +31 -0
  63. package/src/kit/asset-workflow/import-contract.ts +124 -0
  64. package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
  65. package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
  66. package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
  67. package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
  68. package/src/kit/asset-workflow/project-content.ts +288 -0
  69. package/src/kit/asset-workflow/project-source-index.ts +545 -0
  70. package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
  71. package/src/kit/authoring/active-adapter.ts +200 -0
  72. package/src/kit/authoring/active-systems.ts +422 -0
  73. package/src/kit/authoring/adapter-key.ts +18 -0
  74. package/src/kit/authoring/authoring-asset-url.ts +27 -0
  75. package/src/kit/authoring/bootstrap-state.ts +49 -0
  76. package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
  77. package/src/kit/authoring/canvas-scene-guides.ts +84 -0
  78. package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
  79. package/src/kit/authoring/consumer-actions.ts +531 -0
  80. package/src/kit/authoring/design-time-layers.ts +852 -0
  81. package/src/kit/authoring/design-time-mount-registry.ts +244 -0
  82. package/src/kit/authoring/edit-mode-authoring.ts +637 -0
  83. package/src/kit/authoring/empty-project-authoring.ts +22 -0
  84. package/src/kit/authoring/instance-source-menu.ts +135 -0
  85. package/src/kit/authoring/layered-pick.ts +185 -0
  86. package/src/kit/authoring/mounted-root-subjects.ts +146 -0
  87. package/src/kit/authoring/no-authoring-adapter.ts +59 -0
  88. package/src/kit/authoring/object3d-document-persistence.ts +122 -0
  89. package/src/kit/authoring/panel-authoring.ts +121 -0
  90. package/src/kit/authoring/project-authoring-session.ts +105 -0
  91. package/src/kit/authoring/provenance.ts +99 -0
  92. package/src/kit/authoring/react-canvas-navigation.ts +259 -0
  93. package/src/kit/authoring/react-design-canvas-style.ts +20 -0
  94. package/src/kit/authoring/react-story-board.ts +917 -0
  95. package/src/kit/authoring/selection-scope.ts +195 -0
  96. package/src/kit/authoring/shell-document-ops.ts +169 -0
  97. package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
  98. package/src/kit/authoring/story-board-presentation.ts +111 -0
  99. package/src/kit/authoring/three-root.ts +67 -0
  100. package/src/kit/authoring/viewport-tool-context.ts +73 -0
  101. package/src/kit/authoring/viewport-tool-owner.ts +38 -0
  102. package/src/kit/authoring/world-session-state.ts +101 -0
  103. package/src/kit/authoring-seam-evidence.ts +300 -0
  104. package/src/kit/availability-tick.ts +66 -0
  105. package/src/kit/bitmap-label.ts +120 -0
  106. package/src/kit/boot-routing.ts +392 -0
  107. package/src/kit/breakpoint-state.ts +43 -0
  108. package/src/kit/build-identity.ts +16 -0
  109. package/src/kit/bytes-codec.ts +62 -0
  110. package/src/kit/cancellation-reason.ts +58 -0
  111. package/src/kit/canvas-frames.ts +88 -0
  112. package/src/kit/capture-camera-pose.ts +77 -0
  113. package/src/kit/capture-size.ts +88 -0
  114. package/src/kit/chrome-registry.ts +159 -0
  115. package/src/kit/chrome-slot-registry.ts +91 -0
  116. package/src/kit/collaboration-client.ts +264 -0
  117. package/src/kit/collaboration-presence.ts +41 -0
  118. package/src/kit/command-dispatch.ts +19 -0
  119. package/src/kit/command-listener.ts +2182 -0
  120. package/src/kit/command-registry.ts +71 -0
  121. package/src/kit/component-board-registry.ts +205 -0
  122. package/src/kit/component-states-registry.ts +199 -0
  123. package/src/kit/components/AlignToolbar.tsx +204 -0
  124. package/src/kit/components/ApplicationMenus.tsx +372 -0
  125. package/src/kit/components/AssetEditorShell.tsx +216 -0
  126. package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
  127. package/src/kit/components/BoardRulers.tsx +354 -0
  128. package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
  129. package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
  130. package/src/kit/components/ChromeSlot.tsx +20 -0
  131. package/src/kit/components/CodeView.tsx +470 -0
  132. package/src/kit/components/CompactInspectorShell.tsx +39 -0
  133. package/src/kit/components/ConsolePanel.tsx +273 -0
  134. package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
  135. package/src/kit/components/InspectionProjection.tsx +932 -0
  136. package/src/kit/components/Inspector.tsx +270 -0
  137. package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
  138. package/src/kit/components/InspectorFieldsSection.tsx +290 -0
  139. package/src/kit/components/InspectorStoriesSection.tsx +92 -0
  140. package/src/kit/components/InspectorToolSection.tsx +96 -0
  141. package/src/kit/components/InspectorTransformSection.tsx +245 -0
  142. package/src/kit/components/LightExplorerPanel.tsx +433 -0
  143. package/src/kit/components/MediaProperties.tsx +145 -0
  144. package/src/kit/components/ProjectHeader.tsx +328 -0
  145. package/src/kit/components/ReactCanvasControls.tsx +358 -0
  146. package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
  147. package/src/kit/components/RootTextEditor.tsx +79 -0
  148. package/src/kit/components/SaveStatus.tsx +70 -0
  149. package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
  150. package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
  151. package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
  152. package/src/kit/components/ToolHost.tsx +380 -0
  153. package/src/kit/components/Toolbar.tsx +811 -0
  154. package/src/kit/components/TransientHint.tsx +44 -0
  155. package/src/kit/components/VersionControlSection.tsx +470 -0
  156. package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
  157. package/src/kit/components/VolterLogo.tsx +18 -0
  158. package/src/kit/components/WorktreeSwitcher.tsx +712 -0
  159. package/src/kit/components/account-documents.tsx +1162 -0
  160. package/src/kit/components/asset-documents.tsx +794 -0
  161. package/src/kit/components/asset-editor-persistence.ts +216 -0
  162. package/src/kit/components/asset-selection-section.tsx +545 -0
  163. package/src/kit/components/asset-thumbnails.tsx +307 -0
  164. package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
  165. package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  166. package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
  167. package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
  168. package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
  169. package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
  170. package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  171. package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
  172. package/src/kit/components/asset-viewers/shader-source.ts +144 -0
  173. package/src/kit/components/board-guides.ts +150 -0
  174. package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
  175. package/src/kit/components/canvas-temporary-pivot.ts +34 -0
  176. package/src/kit/components/core-utilities.tsx +94 -0
  177. package/src/kit/components/inspector-preview-section.tsx +223 -0
  178. package/src/kit/components/inspector-revert-label.ts +20 -0
  179. package/src/kit/components/inspector-selection.ts +42 -0
  180. package/src/kit/components/inspector-stories-gating.ts +171 -0
  181. package/src/kit/components/inspector-transform-subject.ts +11 -0
  182. package/src/kit/components/inspector-transform.ts +88 -0
  183. package/src/kit/components/kind-documents.tsx +544 -0
  184. package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
  185. package/src/kit/components/project-tool-documents.tsx +402 -0
  186. package/src/kit/components/scene-documents.tsx +221 -0
  187. package/src/kit/components/status-contributions.tsx +407 -0
  188. package/src/kit/components/tool-documents.tsx +302 -0
  189. package/src/kit/components/tool-schema-form.tsx +262 -0
  190. package/src/kit/components/use-after-paint.ts +41 -0
  191. package/src/kit/components/use-project-image-assets.ts +86 -0
  192. package/src/kit/components/workspace-history.ts +32 -0
  193. package/src/kit/components/world-documents.tsx +570 -0
  194. package/src/kit/components/world-overlay-gestures.ts +1939 -0
  195. package/src/kit/composite-screenshot.ts +2238 -0
  196. package/src/kit/content-entry-source-registry.ts +184 -0
  197. package/src/kit/contribution-surfaces.ts +48 -0
  198. package/src/kit/coverage/canvas-reveal.ts +192 -0
  199. package/src/kit/coverage/design-time-surfaces.ts +101 -0
  200. package/src/kit/coverage/ontology-invariants.ts +466 -0
  201. package/src/kit/coverage/session-vitals.ts +503 -0
  202. package/src/kit/crash-null-boundary.ts +36 -0
  203. package/src/kit/creation-site-edit.ts +1491 -0
  204. package/src/kit/creation-site-registry.ts +160 -0
  205. package/src/kit/delegate-harness-registry.ts +134 -0
  206. package/src/kit/document-areas.ts +70 -0
  207. package/src/kit/document-context-registry.ts +193 -0
  208. package/src/kit/document-open-registry.ts +200 -0
  209. package/src/kit/document-play-extension.ts +221 -0
  210. package/src/kit/document-preview-source.ts +20 -0
  211. package/src/kit/document-renderer-session.ts +138 -0
  212. package/src/kit/document-stage-sessions.ts +26 -0
  213. package/src/kit/document-viewports.ts +120 -0
  214. package/src/kit/editor-api.ts +46 -0
  215. package/src/kit/editor-chrome-capture.ts +136 -0
  216. package/src/kit/editor-commands.ts +176 -0
  217. package/src/kit/editor-console.ts +580 -0
  218. package/src/kit/editor-current-view.ts +56 -0
  219. package/src/kit/editor-document-probe.ts +1168 -0
  220. package/src/kit/editor-git-client.ts +115 -0
  221. package/src/kit/editor-hotkeys.ts +728 -0
  222. package/src/kit/editor-lease-view.ts +39 -0
  223. package/src/kit/editor-lease.ts +415 -0
  224. package/src/kit/editor-mode.ts +19 -0
  225. package/src/kit/editor-notifications.ts +140 -0
  226. package/src/kit/editor-presence.ts +563 -0
  227. package/src/kit/editor-presentation-activity.ts +58 -0
  228. package/src/kit/editor-presentation-notice.ts +42 -0
  229. package/src/kit/editor-runtime.tsx +147 -0
  230. package/src/kit/editor-server-response.ts +86 -0
  231. package/src/kit/editor-session-attribution.ts +85 -0
  232. package/src/kit/editor-session-mode.ts +54 -0
  233. package/src/kit/editor-state-facets.ts +74 -0
  234. package/src/kit/editor-view-presentation.ts +777 -0
  235. package/src/kit/environment-images.ts +58 -0
  236. package/src/kit/eyedropper-session.ts +60 -0
  237. package/src/kit/files/file-provider.ts +62 -0
  238. package/src/kit/files/project-files.ts +270 -0
  239. package/src/kit/finders/index.ts +137 -0
  240. package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
  241. package/src/kit/frame/frame-parts.ts +30 -0
  242. package/src/kit/framed-document-capture.ts +34 -0
  243. package/src/kit/game-globals-prelude.ts +143 -0
  244. package/src/kit/game-surface-defaults.ts +33 -0
  245. package/src/kit/gameplay-dom-recording.ts +318 -0
  246. package/src/kit/gameplay-export-state.ts +14 -0
  247. package/src/kit/gameplay-replay.ts +417 -0
  248. package/src/kit/gameplay-session-time.ts +9 -0
  249. package/src/kit/gameplay-sessions.ts +204 -0
  250. package/src/kit/hierarchy-component-marks.ts +298 -0
  251. package/src/kit/hierarchy-internals.ts +197 -0
  252. package/src/kit/hierarchy-kind-icon.ts +217 -0
  253. package/src/kit/hierarchy-menu-registry.ts +67 -0
  254. package/src/kit/hierarchy-node-rows.ts +307 -0
  255. package/src/kit/hierarchy-panel-view.ts +280 -0
  256. package/src/kit/hierarchy-projection.ts +76 -0
  257. package/src/kit/hierarchy-row-media.ts +45 -0
  258. package/src/kit/hierarchy-row-model.ts +308 -0
  259. package/src/kit/hierarchy-rows.ts +11 -0
  260. package/src/kit/hierarchy-walk.ts +86 -0
  261. package/src/kit/history/editor-session.ts +25 -0
  262. package/src/kit/history/history-commands.ts +147 -0
  263. package/src/kit/history/history-delegate.ts +187 -0
  264. package/src/kit/history/history-limit-notices.ts +43 -0
  265. package/src/kit/history/history-service.ts +1189 -0
  266. package/src/kit/history/persistence-coordinator.ts +35 -0
  267. package/src/kit/history/project-file-history.ts +386 -0
  268. package/src/kit/history/project-root-history-backends.ts +139 -0
  269. package/src/kit/history/resource-registry.ts +209 -0
  270. package/src/kit/history/snapshot-store.ts +103 -0
  271. package/src/kit/history/source-history-backend.ts +546 -0
  272. package/src/kit/history-types.ts +124 -0
  273. package/src/kit/hmr-registration-group.ts +67 -0
  274. package/src/kit/hmr-stable-react-context.ts +23 -0
  275. package/src/kit/hotkeys.ts +190 -0
  276. package/src/kit/inference-diagnostics.ts +69 -0
  277. package/src/kit/initial-project.ts +80 -0
  278. package/src/kit/inspection/active-subject.ts +571 -0
  279. package/src/kit/inspection/active-surface.ts +142 -0
  280. package/src/kit/inspection/compose-subject.ts +1055 -0
  281. package/src/kit/inspection/compose.ts +7 -0
  282. package/src/kit/inspection/display.ts +171 -0
  283. package/src/kit/inspection/document-subject.ts +109 -0
  284. package/src/kit/inspection/game-subject.ts +85 -0
  285. package/src/kit/inspection/null-subject.ts +119 -0
  286. package/src/kit/inspection/serialize.ts +357 -0
  287. package/src/kit/inspection/use-active-inspection.ts +180 -0
  288. package/src/kit/inspection-model.ts +542 -0
  289. package/src/kit/inspection-node-media.ts +58 -0
  290. package/src/kit/inspector-presentation.ts +203 -0
  291. package/src/kit/inspector-property-grouping.ts +64 -0
  292. package/src/kit/inspector-section-registry.ts +221 -0
  293. package/src/kit/instance-source-actions.ts +163 -0
  294. package/src/kit/js-heap.ts +71 -0
  295. package/src/kit/key-actions.ts +91 -0
  296. package/src/kit/keymap-presets.ts +428 -0
  297. package/src/kit/layout-policy.ts +31 -0
  298. package/src/kit/light-explorer-model.ts +134 -0
  299. package/src/kit/live-canvas-frame.ts +55 -0
  300. package/src/kit/live-document.ts +296 -0
  301. package/src/kit/live-gesture-lock.ts +50 -0
  302. package/src/kit/live-seam-evidence.ts +11 -0
  303. package/src/kit/live-session-registry.ts +220 -0
  304. package/src/kit/live-transition.ts +391 -0
  305. package/src/kit/manifest-project.ts +107 -0
  306. package/src/kit/module-fetch-diagnosis.ts +192 -0
  307. package/src/kit/mount-failure-report.ts +154 -0
  308. package/src/kit/native-selection-style.ts +497 -0
  309. package/src/kit/object3d-document-write-policy.ts +137 -0
  310. package/src/kit/packaged-runtime.ts +108 -0
  311. package/src/kit/palettes/maya.palette.json +57 -0
  312. package/src/kit/palettes/substance.palette.json +57 -0
  313. package/src/kit/performance-profiler.ts +367 -0
  314. package/src/kit/performance-sources.ts +69 -0
  315. package/src/kit/photograph-notice.ts +141 -0
  316. package/src/kit/play-boot-phase.ts +166 -0
  317. package/src/kit/play-camera-flight.ts +35 -0
  318. package/src/kit/png-encode.worker.ts +26 -0
  319. package/src/kit/presentation-surface.ts +248 -0
  320. package/src/kit/product-command.ts +90 -0
  321. package/src/kit/project-adapter.ts +1140 -0
  322. package/src/kit/project-asset-refresh.ts +23 -0
  323. package/src/kit/project-asset-roots.ts +68 -0
  324. package/src/kit/project-local-state.ts +151 -0
  325. package/src/kit/project-manager.ts +243 -0
  326. package/src/kit/project-module-changes.ts +201 -0
  327. package/src/kit/project-module-split.ts +270 -0
  328. package/src/kit/project-play-layers.ts +25 -0
  329. package/src/kit/project-provenance.ts +115 -0
  330. package/src/kit/project-ready.ts +42 -0
  331. package/src/kit/project-shape.ts +68 -0
  332. package/src/kit/project-tools.ts +107 -0
  333. package/src/kit/projection-types.ts +44 -0
  334. package/src/kit/readiness.ts +113 -0
  335. package/src/kit/renderer-resource-counts.ts +27 -0
  336. package/src/kit/reported-play-state.ts +90 -0
  337. package/src/kit/resolve-contributed-command.ts +14 -0
  338. package/src/kit/resolve-relative-specifier.ts +33 -0
  339. package/src/kit/retained-document-states.ts +91 -0
  340. package/src/kit/scene-document-plan.ts +320 -0
  341. package/src/kit/scene-live-open.ts +210 -0
  342. package/src/kit/scoped-game-css.ts +152 -0
  343. package/src/kit/served-url.ts +5 -0
  344. package/src/kit/session-close.ts +17 -0
  345. package/src/kit/session-tombstone.ts +127 -0
  346. package/src/kit/settings/settings-provider.ts +82 -0
  347. package/src/kit/settings-store.ts +348 -0
  348. package/src/kit/shell-document-state.ts +27 -0
  349. package/src/kit/shell-store-door.ts +45 -0
  350. package/src/kit/shell-store.ts +722 -0
  351. package/src/kit/source-conflict.ts +122 -0
  352. package/src/kit/stage-context.ts +377 -0
  353. package/src/kit/stage-invalidation.ts +25 -0
  354. package/src/kit/stage-store-registry.ts +69 -0
  355. package/src/kit/startup-failure.ts +80 -0
  356. package/src/kit/state-report-deferral.ts +73 -0
  357. package/src/kit/storage/host-files-storage.ts +97 -0
  358. package/src/kit/storage/http-storage.ts +174 -0
  359. package/src/kit/storage/index.ts +75 -0
  360. package/src/kit/storage/mem-storage.ts +158 -0
  361. package/src/kit/storage/path-lock.ts +44 -0
  362. package/src/kit/storage/paths.ts +26 -0
  363. package/src/kit/storage-types.ts +127 -0
  364. package/src/kit/stories/StoryPreviewMount.tsx +306 -0
  365. package/src/kit/stories/compose-project-stories.ts +255 -0
  366. package/src/kit/stories/prefabs-finder.ts +54 -0
  367. package/src/kit/stories/prefabs-from-stories.ts +182 -0
  368. package/src/kit/stories/project-story-regions.ts +24 -0
  369. package/src/kit/stories/story-capture.ts +579 -0
  370. package/src/kit/stories/story-declared-medium.ts +126 -0
  371. package/src/kit/stories/story-discovery.ts +176 -0
  372. package/src/kit/stories/story-dom-runtime.ts +78 -0
  373. package/src/kit/stories/story-grouping.ts +111 -0
  374. package/src/kit/stories/story-mount-turn.ts +27 -0
  375. package/src/kit/stories/story-presentation.ts +215 -0
  376. package/src/kit/stories/story-preview-component.ts +7 -0
  377. package/src/kit/stories/story-registry.ts +530 -0
  378. package/src/kit/stories-scope.ts +35 -0
  379. package/src/kit/story-document-openers.ts +36 -0
  380. package/src/kit/story-thumbnails.ts +47 -0
  381. package/src/kit/surface-keyboard.ts +101 -0
  382. package/src/kit/surface-state.ts +135 -0
  383. package/src/kit/system-seam-evidence.ts +72 -0
  384. package/src/kit/tab-census.ts +202 -0
  385. package/src/kit/tab-lifecycle-client.ts +227 -0
  386. package/src/kit/theme-library.ts +897 -0
  387. package/src/kit/theme-preference.ts +429 -0
  388. package/src/kit/three-viewport-presentation.ts +23 -0
  389. package/src/kit/tool-contribution-play.ts +74 -0
  390. package/src/kit/tool-loader.ts +1918 -0
  391. package/src/kit/transform-mode-request.ts +66 -0
  392. package/src/kit/transient-hint.ts +78 -0
  393. package/src/kit/transport-strip.tsx +174 -0
  394. package/src/kit/ui-source/adapter-region-includes.ts +238 -0
  395. package/src/kit/ui-source/file-region-resolver.ts +302 -0
  396. package/src/kit/ui-source/inspect.ts +775 -0
  397. package/src/kit/ui-source/source-write-backend.ts +605 -0
  398. package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
  399. package/src/kit/user-local-state.ts +105 -0
  400. package/src/kit/viewport-activation-timings.ts +840 -0
  401. package/src/kit/viewport-editor-controls.ts +22 -0
  402. package/src/kit/viewport-presentation.ts +668 -0
  403. package/src/kit/viewport-surface-status.tsx +55 -0
  404. package/src/kit/wait-until.ts +37 -0
  405. package/src/kit/worker-call-metrics.ts +166 -0
  406. package/src/kit/workspace-areas.ts +191 -0
  407. package/src/kit/workspace-aux-commands.ts +11 -0
  408. package/src/kit/workspace-available-documents.ts +142 -0
  409. package/src/kit/workspace-core-utilities.ts +31 -0
  410. package/src/kit/workspace-document-ids.ts +59 -0
  411. package/src/kit/workspace-document-registry.ts +624 -0
  412. package/src/kit/workspace-document-restore.ts +146 -0
  413. package/src/kit/workspace-host-commands.ts +141 -0
  414. package/src/kit/workspace-persistence-gate.ts +40 -0
  415. package/src/kit/workspace-play-utilities.ts +44 -0
  416. package/src/kit/workspace-presets.ts +446 -0
  417. package/src/kit/workspace-regions.ts +276 -0
  418. package/src/kit/workspace-static-panels.ts +73 -0
  419. package/src/kit/workspace-status-registry.ts +121 -0
  420. package/src/kit/workspace-storage.ts +35 -0
  421. package/src/kit/workspace-style.ts +226 -0
  422. package/src/kit/workspace-utility-commands.ts +74 -0
  423. package/src/kit/workspace-utility-registry.ts +263 -0
  424. package/src/kit/world-adoption-event.ts +23 -0
  425. package/src/kit/world-adoption.ts +115 -0
  426. package/src/kit/world-canvas-viewport-state.ts +35 -0
  427. package/src/kit/world-document-routing.ts +104 -0
  428. package/src/kit/world-pan-state.ts +198 -0
  429. package/src/kit/write-pipe.ts +173 -0
  430. package/src/layout-arrangements.ts +5 -0
  431. package/src/layouts.tsx +108 -0
  432. package/src/looks.ts +16 -0
  433. package/src/project/output-roots.ts +73 -0
  434. package/src/project/tab-census.ts +155 -0
  435. package/src/project-tool-catalog.ts +104 -0
  436. package/src/selection.tsx +107 -0
  437. package/src/services.ts +18 -0
  438. package/src/session/build-report.ts +22 -0
  439. package/src/session/collaboration-types.ts +262 -0
  440. package/src/session/command-table.ts +327 -0
  441. package/src/session/discovery.ts +100 -0
  442. package/src/session/editor-brand.ts +48 -0
  443. package/src/session/editor-compatibility.ts +329 -0
  444. package/src/session/editor-control-lifecycle.ts +68 -0
  445. package/src/session/editor-control-protocol.ts +5 -0
  446. package/src/session/entrypoint-selection-readers.ts +66 -0
  447. package/src/session/entrypoint-selection-source.ts +120 -0
  448. package/src/session/game-css-scope.ts +30 -0
  449. package/src/session/hosted-attachment.ts +225 -0
  450. package/src/session/limited-view.ts +82 -0
  451. package/src/session/product-create.ts +24 -0
  452. package/src/session/product-locator.ts +478 -0
  453. package/src/session/project-module-url.ts +242 -0
  454. package/src/session/project-serving.ts +164 -0
  455. package/src/session/project-upgrade.ts +669 -0
  456. package/src/session/registry-format.ts +210 -0
  457. package/src/session/relative-path-guard.ts +56 -0
  458. package/src/session/scoped-game-css.ts +461 -0
  459. package/src/session/source-glob.ts +15 -0
  460. package/src/session/tool-contribution-convention.ts +123 -0
  461. package/src/session/workbench-locator.ts +712 -0
  462. package/src/session.ts +41 -0
  463. package/src/share.ts +160 -0
  464. package/src/source-analysis.ts +28 -0
  465. package/src/source-authoring.ts +439 -0
  466. package/src/tools/errors.ts +91 -0
  467. package/src/tools/provider-execution.ts +70 -0
  468. package/src/tools/registry.ts +341 -0
  469. package/src/tools/types.ts +159 -0
  470. package/src/transport.ts +100 -0
  471. package/src/types.ts +1693 -0
  472. package/src/views.ts +164 -0
  473. package/src/widgets/design-system.ts +93 -0
  474. package/src/widgets/editor-appearance.ts +151 -0
  475. package/src/widgets/editor-material.ts +83 -0
  476. package/src/widgets/icon-set-registry.ts +105 -0
  477. package/src/widgets/index.ts +71 -0
  478. package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
  479. package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
  480. package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
  481. package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
  482. package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
  483. package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
  484. package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
  485. package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
  486. package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
  487. package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
  488. package/src/widgets/inspector-widgets/color-utils.ts +201 -0
  489. package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
  490. package/src/widgets/inspector-widgets/index.ts +25 -0
  491. package/src/widgets/inspector-widgets/shared.tsx +140 -0
  492. package/src/widgets/interactive-edit-scope.ts +33 -0
  493. package/src/widgets/patterns/Dialog.tsx +140 -0
  494. package/src/widgets/patterns/Fields.tsx +44 -0
  495. package/src/widgets/patterns/List.tsx +25 -0
  496. package/src/widgets/patterns/StateSurface.tsx +40 -0
  497. package/src/widgets/patterns/Surfaces.tsx +122 -0
  498. package/src/widgets/patterns/Tabs.tsx +80 -0
  499. package/src/widgets/patterns/Toolbar.tsx +72 -0
  500. package/src/widgets/patterns/Tree.tsx +72 -0
  501. package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
  502. package/src/widgets/primitives/Button.tsx +62 -0
  503. package/src/widgets/primitives/ColorInput.tsx +78 -0
  504. package/src/widgets/primitives/DraftTextInput.tsx +63 -0
  505. package/src/widgets/primitives/EditorIcon.tsx +157 -0
  506. package/src/widgets/primitives/FormControls.tsx +88 -0
  507. package/src/widgets/primitives/HoverPreview.tsx +96 -0
  508. package/src/widgets/primitives/JsonInput.tsx +113 -0
  509. package/src/widgets/primitives/Layout.tsx +100 -0
  510. package/src/widgets/primitives/Menu.tsx +161 -0
  511. package/src/widgets/primitives/NumberInput.tsx +169 -0
  512. package/src/widgets/primitives/Panel.tsx +80 -0
  513. package/src/widgets/primitives/SectionHeader.tsx +77 -0
  514. package/src/widgets/primitives/Text.tsx +54 -0
  515. package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
  516. package/src/widgets/primitives/Tooltip.tsx +204 -0
  517. package/src/widgets/primitives/Vec3Input.tsx +70 -0
  518. package/src/widgets/primitives/banner-tones.ts +32 -0
  519. package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
  520. package/src/widgets/primitives/editor-icons.ts +254 -0
  521. package/src/widgets/primitives/panel-header-styles.ts +42 -0
  522. package/src/widgets/theme.ts +2841 -0
  523. package/src/widgets/z-index.ts +25 -0
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Backend-agnostic file interface for the editor.
3
+ *
4
+ * The editor and engine read/write project files through one `StorageBackend`
5
+ * and never learn which implementation is behind it — the session's own
6
+ * `/__editor/*` routes, the frame's file door over them, or the design
7
+ * system's in-memory fixture.
8
+ *
9
+ * Scope — this interface deliberately covers ONLY what reduces to file
10
+ * operations. Three editor concerns do not, and are handled elsewhere:
11
+ * - native folder dialogs / "reveal in OS file manager" → `HostCapabilities`
12
+ * - the `volter` CLI control channel (SSE + command RPC) → server-only, dropped
13
+ * in a pure-browser editor
14
+ * - `export` / packaging (spawns a build) → a client-side bundler in-browser
15
+ *
16
+ * `watch` is part of the interface but its semantics are backend-specific: a
17
+ * server backend reports real filesystem events (chokidar); a browser backend
18
+ * has no OS file-change notifications, so it derives events from its OWN writes
19
+ * (in a server-less editor the editor is the only writer — which is exactly the
20
+ * signal HMR needs).
21
+ *
22
+ * Paths are POSIX-style, project-root-relative, '/'-separated, no leading slash
23
+ * (e.g. `src/scripts/components/spin.ts`).
24
+ */
25
+
26
+ export type NodeType = 'file' | 'dir';
27
+
28
+ export interface Stat {
29
+ /** Normalized, root-relative path. */
30
+ path: string;
31
+ type: NodeType;
32
+ /** Byte length for files; 0 for directories. */
33
+ size: number;
34
+ /** Last-modified time, epoch ms (0 if the backend cannot report it). */
35
+ mtime: number;
36
+ }
37
+
38
+ export interface DirEntry {
39
+ /** Base name (no slashes). */
40
+ name: string;
41
+ /** Normalized, root-relative path. */
42
+ path: string;
43
+ type: NodeType;
44
+ /** Byte length for files (omitted for directories). */
45
+ size?: number;
46
+ /** Last-modified time, epoch ms (omitted if the backend cannot report it). */
47
+ mtime?: number;
48
+ }
49
+
50
+ export type WatchEventType = 'create' | 'update' | 'remove';
51
+
52
+ export interface WatchEvent {
53
+ type: WatchEventType;
54
+ /** Normalized, root-relative path of the affected node. */
55
+ path: string;
56
+ }
57
+
58
+ export type WatchCallback = (event: WatchEvent) => void;
59
+
60
+ /**
61
+ * The one file interface every storage backend implements. All methods take and
62
+ * return normalized, root-relative POSIX paths.
63
+ */
64
+ export interface StorageBackend {
65
+ /** Stable identifier for the active backend (for diagnostics/feature flags). */
66
+ readonly id: string;
67
+
68
+ /** Read a UTF-8 text file. Rejects if the path is missing or is a directory. */
69
+ read(path: string): Promise<string>;
70
+ /** Read raw bytes. Rejects if the path is missing or is a directory. */
71
+ readBytes(path: string): Promise<Uint8Array>;
72
+
73
+ /** Write a file, creating parent directories as needed. Emits a watch event. */
74
+ write(path: string, data: string | Uint8Array): Promise<void>;
75
+ /**
76
+ * Create a new file without replacing an existing one. Returns false when
77
+ * the path already exists. Browser handle APIs have no OS-level O_EXCL;
78
+ * HandleStorage serializes same-origin writers and rechecks at handle
79
+ * acquisition, while an external process may still win the final race.
80
+ */
81
+ writeIfAbsent(path: string, data: string | Uint8Array): Promise<boolean>;
82
+
83
+ /** Shallow directory listing. Rejects if the path is missing or is a file. */
84
+ list(dir: string): Promise<DirEntry[]>;
85
+
86
+ /** Stat a node, or resolve to `null` if it does not exist. */
87
+ stat(path: string): Promise<Stat | null>;
88
+
89
+ /** Convenience existence check. */
90
+ exists(path: string): Promise<boolean>;
91
+
92
+ /** Recursively create a directory (no-op if it already exists). */
93
+ mkdir(path: string): Promise<void>;
94
+
95
+ /** Recursively remove a file or directory (no-op if missing). Emits an event. */
96
+ remove(path: string): Promise<void>;
97
+
98
+ /** Subscribe to change events. Returns an unsubscribe function. */
99
+ watch(callback: WatchCallback): () => void;
100
+ }
101
+
102
+ /**
103
+ * Non-file host capabilities, kept separate from `StorageBackend` because they
104
+ * do not reduce to path operations. A backend may implement none of these.
105
+ */
106
+ export interface HostCapabilities {
107
+ /**
108
+ * Prompt the user to choose a project root and return a backend rooted there.
109
+ * Browser: `showDirectoryPicker()` (Chromium). Resolves to `null` if the user
110
+ * cancels. Absent entirely where unsupported.
111
+ */
112
+ pickProjectRoot?(): Promise<StorageBackend | null>;
113
+
114
+ /** Reveal a path in the OS file manager. Absent in the browser. */
115
+ reveal?(path: string): Promise<void>;
116
+ }
117
+
118
+ /**
119
+ * Is `backend` rooted at the project's `public/` folder rather than the project
120
+ * root? The session's HTTP tier (`http`) is, and so is the Code-OSS frame's
121
+ * file door (`frame:<tier>`), which is always the `public/` view. A reader of
122
+ * project-root files (`volter.project.json`, `.volter/`) reaches them through the
123
+ * dev server's own routes when this is true.
124
+ */
125
+ export function isPublicRootedBackend(backend: StorageBackend): boolean {
126
+ return backend.id === 'http' || backend.id.startsWith('frame:');
127
+ }
@@ -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/sdk/session/game-css-scope';
44
+ import { themeVars } from '@volter/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 '@volter/sdk/kit/project-manager';
49
+ import { ensureScopedGameStyles } from '@volter/sdk/kit/scoped-game-css';
50
+ import { resolveStoryDomRuntime } from '@volter/sdk/kit/stories/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
+ * (`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, the editor's `screenshot <file>.stories.tsx` command), 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
+ }