@volter/sdk 0.0.0-stage → 0.5.203

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 +1166 -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 +317 -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 +403 -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,530 @@
1
+ /**
2
+ * Story registry (C3, spec §9) — the story sibling of `tool-loader.ts`'s
3
+ * registry half: ties `story-discovery.ts` (find modules) and
4
+ * `compose-project-stories.ts` (portable-mount one loaded module) together
5
+ * into a live, `useSyncExternalStore`-shaped list consumed by React design-time
6
+ * world mounting and its document/story hierarchy.
7
+ *
8
+ * Same discipline as the tool registry: discovery is a live rescan (never a
9
+ * cached manifest, D3), re-run on project open/change and on the server's
10
+ * `story-files-changed` SSE broadcast (a new/removed `*.stories.tsx`).
11
+ * Per-module failures (a module that fails to import, or fails to compose)
12
+ * are collected alongside successes rather than dropped — the panel shows a
13
+ * broken module's error inline, naming the module (spec §9 "errors identify
14
+ * the source module"), instead of silently omitting it.
15
+ */
16
+
17
+ import { sortStoriesV7 } from 'storybook/internal/preview-api';
18
+ import type { Addon_StorySortParameterV7, IndexEntry } from 'storybook/internal/types';
19
+ import { activeProjectKey } from '@volter/sdk/kit/active-project';
20
+ import { editorConsole } from '@volter/sdk/kit/editor-console';
21
+ import {
22
+ describeModuleFetch,
23
+ diagnoseModuleFetch,
24
+ failedImportEntry,
25
+ } from '@volter/sdk/kit/module-fetch-diagnosis';
26
+ import {
27
+ recordStoryDiscoveryTiming,
28
+ waitForFirstViewportFrame,
29
+ } from '@volter/sdk/kit/viewport-activation-timings';
30
+ import {
31
+ type ComposedProjectStory,
32
+ composeProjectStories,
33
+ ensureProjectAnnotations,
34
+ } from './compose-project-stories';
35
+ import { getProjectStoryRegions } from '@volter/sdk/kit/stories/project-story-regions';
36
+ import { declaredStoryMedium } from '@volter/sdk/kit/stories/story-declared-medium';
37
+ import { deriveStoryGroupPath, formatStoryGroupPath } from './story-grouping';
38
+
39
+ /** One composed portable CSF story of the open project, carrying the source
40
+ * module it came from. A story belongs to the PROJECT, not to a root: the
41
+ * design-time board is the project's component gallery, and which root a
42
+ * story previews is DERIVED from the component its CSF meta renders
43
+ * ({@link pickComponentPreviewStory}). No story args/decorators/loaders are
44
+ * copied or reinterpreted. */
45
+ export interface ProjectPreviewStory extends ComposedProjectStory {
46
+ readonly modulePath: string;
47
+ }
48
+
49
+ import { discoverProjectStories, loadProjectPreviewAnnotations } from './story-discovery';
50
+
51
+ /** One discovered module's outcome after load + compose. */
52
+ export type ProjectStoryModule =
53
+ | { modulePath: string; ok: true; stories: ComposedProjectStory[] }
54
+ | { modulePath: string; ok: false; error: string };
55
+
56
+ interface StoryDiscoveryProjectLike {
57
+ rootPath: string;
58
+ }
59
+
60
+ let _modules: ProjectStoryModule[] = [];
61
+ let _ready = false;
62
+ let _refreshGeneration = 0;
63
+ let _registryProjectKey: string | null = null;
64
+ const _requestedModules = new Map<string, Promise<void>>();
65
+ const _listeners = new Set<() => void>();
66
+
67
+ function adoptRegistryProject(): void {
68
+ const key = activeProjectKey();
69
+ if (_registryProjectKey === key) return;
70
+ _registryProjectKey = key;
71
+ _refreshGeneration++;
72
+ _requestedModules.clear();
73
+ publish([], false);
74
+ }
75
+
76
+ /** Current story modules (stable reference between refreshes). */
77
+ export function getProjectStoryModules(): ProjectStoryModule[] {
78
+ return _modules;
79
+ }
80
+
81
+ /** True only after the current project's discovery pass has published. An
82
+ * empty ready registry is a real "no stories" answer; an empty unready one is
83
+ * boot in flight and must never be graded as a missing component surface. */
84
+ export function projectStoriesReady(): boolean {
85
+ return _ready;
86
+ }
87
+
88
+ /** Subscribe to story-registry changes. Returns an unsubscribe function. */
89
+ export function subscribeProjectStoryModules(fn: () => void): () => void {
90
+ _listeners.add(fn);
91
+ return () => _listeners.delete(fn);
92
+ }
93
+
94
+ /**
95
+ * Resolve once the registry is READY — which is not the same as awaiting your
96
+ * own {@link refreshProjectStories}.
97
+ *
98
+ * A refresh that a LATER refresh supersedes returns EARLY, by design (a
99
+ * second concurrent pass aborts the first), and it returns with `_modules`
100
+ * still emptied by `_ready = false`. A caller that only awaited its own call
101
+ * therefore reads an empty registry and cannot tell it from "this project has
102
+ * no stories" — measured 2026-09-18 on a `full` scaffold, where the boot
103
+ * document restore raced the discovery lifecycle's own pass and dropped the
104
+ * open story document as a failed verification.
105
+ *
106
+ * Deliberately unbounded: every path that clears `_ready` is a refresh that
107
+ * publishes ready again when it finishes, succeeded or failed, and the
108
+ * workspace restore that calls this is itself time-boxed by the host
109
+ * (`workspace-state-persistence.ts`'s `RESTORE_TIMEOUT_MS` bounds when
110
+ * write-through installs, never the restore). A number here would be an
111
+ * invented tolerance over a condition that already resolves itself.
112
+ */
113
+ export function whenProjectStoriesReady(): Promise<void> {
114
+ if (_ready) return Promise.resolve();
115
+ return new Promise((resolve) => {
116
+ const stop = subscribeProjectStoryModules(() => {
117
+ if (!_ready) return;
118
+ stop();
119
+ resolve();
120
+ });
121
+ });
122
+ }
123
+
124
+ function volterParameters(story: ComposedProjectStory): Record<string, unknown> | null {
125
+ const value = story.parameters['volter'];
126
+ return value && typeof value === 'object' ? (value as Record<string, unknown>) : null;
127
+ }
128
+
129
+ /** Every composed story the project declares, in discovery/export order —
130
+ * the whole membership of the React design-time board and of the hierarchy's
131
+ * story documents. Deliberately unfiltered: the board is the project's
132
+ * component gallery, so a story earns its place by existing, and only the
133
+ * root's own default preview is derived from a component
134
+ * ({@link getComponentPreviewStory}). */
135
+ export function getProjectPreviewStories(): ProjectPreviewStory[] {
136
+ const out: ProjectPreviewStory[] = [];
137
+ for (const module_ of _modules) {
138
+ if (!module_.ok) continue;
139
+ for (const story of module_.stories) {
140
+ out.push({ ...story, modulePath: module_.modulePath });
141
+ }
142
+ }
143
+ const storySort = out
144
+ .map((story) => {
145
+ const options = story.parameters['options'];
146
+ return options && typeof options === 'object'
147
+ ? (options as Record<string, unknown>)['storySort']
148
+ : undefined;
149
+ })
150
+ .find((value) => value !== undefined) as Addon_StorySortParameterV7 | undefined;
151
+ if (!storySort) return out;
152
+
153
+ const byId = new Map(out.map((story) => [story.id, story]));
154
+ const entries: IndexEntry[] = out.map((story) => ({
155
+ type: 'story',
156
+ subtype: 'story',
157
+ id: story.id,
158
+ name: story.label,
159
+ title:
160
+ story.title ?? formatStoryGroupPath(deriveStoryGroupPath({ modulePath: story.modulePath })),
161
+ importPath: story.modulePath,
162
+ tags: [...(story.tags ?? [])],
163
+ }));
164
+ return sortStoriesV7(entries, storySort, [...new Set(out.map((story) => story.modulePath))])
165
+ .map((entry) => byId.get(entry.id))
166
+ .filter((story): story is ProjectPreviewStory => story !== undefined);
167
+ }
168
+
169
+ /** Whether a CSF module declares this story as its component's default:
170
+ * `parameters.volter.default === true` on the story itself, or a
171
+ * `volter.defaultStory` naming it (a meta-level parameter, which Storybook
172
+ * composes down onto every story in the module). */
173
+ export function isDeclaredDefaultStory(story: ComposedProjectStory): boolean {
174
+ const volter = volterParameters(story);
175
+ if (!volter) return false;
176
+ if (volter['default'] === true) return true;
177
+ return typeof volter['defaultStory'] === 'string' && volter['defaultStory'] === story.name;
178
+ }
179
+
180
+ /** The directory portion of a project-relative source path, normalized. */
181
+ function sourceDir(path: string): string {
182
+ const normalized = path.replaceAll('\\', '/').replace(/^\.\//, '');
183
+ const slash = normalized.lastIndexOf('/');
184
+ return slash >= 0 ? normalized.slice(0, slash) : '';
185
+ }
186
+
187
+ /**
188
+ * Choose the best composed story for one component, joined on
189
+ * `meta.component`'s name (the registry's own `componentName`) — pure over a
190
+ * module list so it is unit-testable without the live registry. This is THE
191
+ * story↔component join: a `three` prefab's own declaration and
192
+ * THUMBNAIL (mounted off-screen by `story-three-preview.ts`; no live instance
193
+ * or referenced asset substitutes for it) and a React root's composed default
194
+ * preview (`design-time-layers.ts`, joined against the root entry's
195
+ * default-exported component) both go through it.
196
+ *
197
+ * `componentPath` (the component's own source file) disambiguates the known
198
+ * weak spot of a name-only join: two files can export a same-named component,
199
+ * so a story is PREFERRED when its module sits in the same source directory as
200
+ * the component. Within the chosen set, a story the module declares as the
201
+ * default ({@link isDeclaredDefaultStory}) wins; otherwise discovery order.
202
+ */
203
+ export function pickComponentPreviewStory(
204
+ modules: readonly ProjectStoryModule[],
205
+ componentName: string,
206
+ componentPath?: string,
207
+ ): ProjectPreviewStory | null {
208
+ const pool = componentPreviewStories(modules, componentName, componentPath);
209
+ return pool.find(isDeclaredDefaultStory) ?? pool[0] ?? null;
210
+ }
211
+
212
+ /**
213
+ * Every portable state declared for one component. The same source-directory
214
+ * preference as {@link pickComponentPreviewStory} disambiguates equal export
215
+ * names without hiding sibling stories from the component's Inspector.
216
+ */
217
+ export function componentPreviewStories(
218
+ modules: readonly ProjectStoryModule[],
219
+ componentName: string,
220
+ componentPath?: string,
221
+ ): ProjectPreviewStory[] {
222
+ const matches: ProjectPreviewStory[] = [];
223
+ for (const module_ of modules) {
224
+ if (!module_.ok) continue;
225
+ for (const story of module_.stories) {
226
+ if (story.componentName === componentName) {
227
+ matches.push({ ...story, modulePath: module_.modulePath });
228
+ }
229
+ }
230
+ }
231
+ if (matches.length === 0) return [];
232
+ const sameDir = componentPath
233
+ ? matches.filter((story) => sourceDir(story.modulePath) === sourceDir(componentPath))
234
+ : [];
235
+ return sameDir.length > 0 ? sameDir : matches;
236
+ }
237
+
238
+ /** {@link pickComponentPreviewStory} over the LIVE registry — what the content
239
+ * gallery calls to find a prefab's thumbnail story, and what
240
+ * `design-time-layers.ts` calls to find a React root's composed default
241
+ * preview from the root entry's own component. */
242
+ export function getComponentPreviewStory(
243
+ componentName: string,
244
+ componentPath?: string,
245
+ ): ProjectPreviewStory | null {
246
+ return pickComponentPreviewStory(_modules, componentName, componentPath);
247
+ }
248
+
249
+ /** Live-registry form of {@link componentPreviewStories}. */
250
+ export function getComponentPreviewStories(
251
+ componentName: string,
252
+ componentPath?: string,
253
+ ): ProjectPreviewStory[] {
254
+ return componentPreviewStories(_modules, componentName, componentPath);
255
+ }
256
+
257
+ function publish(next: ProjectStoryModule[], ready: boolean): void {
258
+ _modules = next;
259
+ _ready = ready;
260
+ for (const fn of _listeners) fn();
261
+ }
262
+
263
+ interface TimedStoryModule {
264
+ readonly result: ProjectStoryModule;
265
+ readonly loadMs: number;
266
+ readonly composeMs: number;
267
+ }
268
+
269
+ async function loadStoryModule({
270
+ modulePath,
271
+ load,
272
+ }: {
273
+ readonly modulePath: string;
274
+ readonly load: () => Promise<unknown>;
275
+ }): Promise<TimedStoryModule> {
276
+ const loadStartedAtMs = Date.now();
277
+ let mod: unknown;
278
+ try {
279
+ mod = await load();
280
+ } catch (err) {
281
+ const entry = failedImportEntry(String(err instanceof Error ? err.message : err));
282
+ if (entry) {
283
+ void diagnoseModuleFetch(entry).then((diagnosis) =>
284
+ editorConsole.error(`[stories] ${modulePath}: ${describeModuleFetch(diagnosis)}`, 'authoring'),
285
+ );
286
+ }
287
+ return {
288
+ result: {
289
+ modulePath,
290
+ ok: false,
291
+ error: `[stories] failed to load ${modulePath} — ${String(err instanceof Error ? err.message : err)}`,
292
+ },
293
+ loadMs: Date.now() - loadStartedAtMs,
294
+ composeMs: 0,
295
+ };
296
+ }
297
+ const loadMs = Date.now() - loadStartedAtMs;
298
+ const composeStartedAtMs = Date.now();
299
+ const result = await composeProjectStories(modulePath, mod);
300
+ return {
301
+ result: result.ok
302
+ ? { modulePath, ok: true, stories: result.stories }
303
+ : { modulePath, ok: false, error: result.error },
304
+ loadMs,
305
+ composeMs: Date.now() - composeStartedAtMs,
306
+ };
307
+ }
308
+
309
+ /** Open one explicit story without evaluating every other project example.
310
+ * Full discovery still owns catalog completeness; this only publishes the
311
+ * requested module into that same registry, without marking it complete. */
312
+ export function ensureProjectStoryModule(
313
+ project: StoryDiscoveryProjectLike | null,
314
+ modulePath: string,
315
+ ): Promise<void> {
316
+ adoptRegistryProject();
317
+ const projectKey = activeProjectKey();
318
+ const key = `${projectKey}\n${modulePath}`;
319
+ const existing = _requestedModules.get(key);
320
+ if (existing) return existing;
321
+ const pending = loadRequestedStoryModule(project, projectKey, modulePath).finally(() => {
322
+ if (_requestedModules.get(key) === pending) _requestedModules.delete(key);
323
+ });
324
+ _requestedModules.set(key, pending);
325
+ return pending;
326
+ }
327
+
328
+ async function loadRequestedStoryModule(
329
+ project: StoryDiscoveryProjectLike | null,
330
+ projectKey: string,
331
+ modulePath: string,
332
+ ): Promise<void> {
333
+ while (activeProjectKey() === projectKey) {
334
+ // A published composition is immediately usable. The document subscribes
335
+ // to subsequent source refreshes; opening never waits on unrelated modules.
336
+ const prior = _modules.find((module_) => module_.modulePath === modulePath);
337
+ if (prior?.ok) return;
338
+ const generation = _refreshGeneration;
339
+ const current = () => activeProjectKey() === projectKey && generation === _refreshGeneration;
340
+ const annotations = await loadProjectPreviewAnnotations(project);
341
+ if (!current()) continue;
342
+ await ensureProjectAnnotations(annotations);
343
+ if (!current()) continue;
344
+ const discovered = await discoverProjectStories(project);
345
+ if (!current()) continue;
346
+ const requested = discovered.find((module_) => module_.modulePath === modulePath);
347
+ if (!requested) throw new Error(`Story module not found: ${modulePath}`);
348
+ const { result } = await loadStoryModule(requested);
349
+ if (!current()) continue;
350
+ // Full discovery can publish this module while its demanded load runs.
351
+ // That publication owns the row; a slower request must not replace it.
352
+ const published = _modules.find((module_) => module_.modulePath === modulePath);
353
+ if (published && published !== prior) {
354
+ if (!published.ok) throw new Error(published.error);
355
+ return;
356
+ }
357
+ publish([..._modules.filter((module_) => module_.modulePath !== modulePath), result], _ready);
358
+ if (!result.ok) throw new Error(result.error);
359
+ return;
360
+ }
361
+ throw new Error(`Project changed while opening story: ${modulePath}`);
362
+ }
363
+
364
+ /** Let the first visible editor work finish before evaluating story modules
365
+ * whose medium cannot be known from the project's declared regions. Those
366
+ * modules commonly hold dense DOM kits; loading them eagerly made a 3D board
367
+ * wait on code it cannot display. Storybook uses the same broad architecture:
368
+ * index first, evaluate a story module only when its surface needs it. */
369
+ async function waitForStoryImportIdle(): Promise<void> {
370
+ // `requestIdleCallback` only means the browser main thread is momentarily
371
+ // idle; it fired while the first Scene was still driving ~1,000 Vite module
372
+ // requests and pulled the data-grid story graph into that same
373
+ // queue. Wait for an authored frame first. The timeout preserves recovery
374
+ // for a genuinely broken viewport without making background stories part
375
+ // of the ordinary startup path.
376
+ await Promise.race([
377
+ waitForFirstViewportFrame(),
378
+ new Promise<void>((resolve) => setTimeout(resolve, 5_000)),
379
+ ]);
380
+ await new Promise<void>((resolve) => {
381
+ const idle = globalThis.requestIdleCallback;
382
+ if (typeof idle === 'function') {
383
+ idle(() => resolve(), { timeout: 2_000 });
384
+ return;
385
+ }
386
+ setTimeout(resolve, 0);
387
+ });
388
+ }
389
+
390
+ /**
391
+ * Re-run the whole discovery + load + compose pass. Never throws: a broken
392
+ * module (import failure, or a `composeProjectStories` failure) becomes an
393
+ * `{ ok: false, error }` entry naming the module, and every other module
394
+ * still loads — the same "one bad file never takes the rest down" physics
395
+ * `refreshProjectTools` uses.
396
+ *
397
+ * Applies the project's `.storybook/preview.ts(x)` annotations (if the
398
+ * project has one — `loadProjectPreviewAnnotations`) via
399
+ * `ensureProjectAnnotations` before composing anything, exactly once per
400
+ * session. `explicitPreviewAnnotations` is a test/caller override — pass it
401
+ * to skip the `/@fs/` discovery and thread a fixture's annotations directly.
402
+ */
403
+ export async function refreshProjectStories(
404
+ project: StoryDiscoveryProjectLike | null,
405
+ explicitPreviewAnnotations?: unknown,
406
+ options: {
407
+ readonly deferUndeclared?: boolean;
408
+ /**
409
+ * The source paths a CONTENT write changed, when that is what triggered
410
+ * this refresh. With it, a story module whose bundled closure holds none
411
+ * of them keeps its published result instead of being re-evaluated, and
412
+ * the modules that do reload go ONE AT A TIME with a frame between them:
413
+ * re-bundling all ten of a project's story modules at once, on the main
414
+ * thread, beside the world's own remount, is what held the editor at 7–12
415
+ * FPS for seconds after every prefab drop (three human passes; profiled
416
+ * 2026-09-03). Boot and explicit refreshes pass nothing and load in
417
+ * parallel, as before.
418
+ */
419
+ readonly changedPaths?: ReadonlySet<string>;
420
+ } = {},
421
+ ): Promise<void> {
422
+ adoptRegistryProject();
423
+ const generation = ++_refreshGeneration;
424
+ const projectKey = activeProjectKey();
425
+ const current = () => generation === _refreshGeneration && projectKey === activeProjectKey();
426
+ const loadAll = async (
427
+ list: readonly { readonly modulePath: string; readonly load: () => Promise<unknown> }[],
428
+ ): Promise<TimedStoryModule[]> => {
429
+ if (!options.changedPaths) return Promise.all(list.map(loadStoryModule));
430
+ // A write-driven refresh loads one module per frame instead: the reload
431
+ // itself is a module-cache hit, but COMPOSING every story on one turn
432
+ // beside the world's own remount is what held the editor at 7-12 FPS
433
+ // after a prefab drop.
434
+ const out: TimedStoryModule[] = [];
435
+ for (const item of list) {
436
+ out.push(await loadStoryModule(item));
437
+ // Give the viewport a frame between modules.
438
+ await new Promise((resolve) => setTimeout(resolve, 16));
439
+ if (!current()) break;
440
+ }
441
+ return out;
442
+ };
443
+ _ready = false;
444
+ for (const fn of _listeners) fn();
445
+ const startedAtMs = Date.now();
446
+ const previewStartedAtMs = Date.now();
447
+ const previewAnnotations =
448
+ explicitPreviewAnnotations ?? (await loadProjectPreviewAnnotations(project));
449
+ if (!current()) return;
450
+ const previewAnnotationsMs = Date.now() - previewStartedAtMs;
451
+ const annotationsStartedAtMs = Date.now();
452
+ await ensureProjectAnnotations(previewAnnotations);
453
+ if (!current()) return;
454
+ const runtimeAnnotationsMs = Date.now() - annotationsStartedAtMs;
455
+
456
+ const scanStartedAtMs = Date.now();
457
+ const discovered = await discoverProjectStories(project);
458
+ if (!current()) return;
459
+ const fileScanMs = Date.now() - scanStartedAtMs;
460
+ // Module evaluation is independent; only STORY MOUNTING is serialized
461
+ // (`story-mount-turn.ts`) because loaders may mutate shared preview state.
462
+ // Loading every CSF module one after another made editor boot scale with the
463
+ // SUM of Vite transforms and network round trips (measured at 16s for the
464
+ // template and 23s for third-person). Preserve discovery order by mapping
465
+ // `Promise.all` over the ordered input rather than pushing as jobs finish.
466
+ const regions = getProjectStoryRegions();
467
+ const deferred = options.deferUndeclared
468
+ ? discovered.filter(
469
+ ({ modulePath }) => declaredStoryMedium({ modulePath, regions }).via === 'undeclared',
470
+ )
471
+ : [];
472
+ const deferredPaths = new Set(deferred.map(({ modulePath }) => modulePath));
473
+ const immediate = discovered.filter(({ modulePath }) => !deferredPaths.has(modulePath));
474
+ const modulesStartedAtMs = Date.now();
475
+ const immediateLoaded = await loadAll(immediate);
476
+ const moduleLoadAndComposeMs = Date.now() - modulesStartedAtMs;
477
+ const immediateResults = immediateLoaded.map(({ result }) => result);
478
+ if (!current()) return;
479
+
480
+ // Publish the declared surfaces as soon as they are usable. The registry is
481
+ // deliberately not "ready" until the background tail has also landed, so
482
+ // acceptance/coverage cannot mistake a partial index for the final answer.
483
+ const immediateByPath = new Map(
484
+ [
485
+ // A demanded story may already be open while the catalog evaluates its
486
+ // immediate set. Keep that row (and other last-good deferred rows) until
487
+ // their replacements arrive; a partial catalog must not remove them.
488
+ ..._modules.filter(({ modulePath }) => deferredPaths.has(modulePath)),
489
+ ...immediateResults,
490
+ ].map((result) => [result.modulePath, result]),
491
+ );
492
+ publish(
493
+ discovered
494
+ .map(({ modulePath }) => immediateByPath.get(modulePath))
495
+ .filter((result): result is ProjectStoryModule => result !== undefined),
496
+ deferred.length === 0,
497
+ );
498
+ recordStoryDiscoveryTiming({
499
+ ms: Date.now() - startedAtMs,
500
+ completedAtMs: Date.now(),
501
+ moduleCount: immediateResults.length,
502
+ storyCount: immediateResults.reduce(
503
+ (count, module_) => count + (module_.ok ? module_.stories.length : 0),
504
+ 0,
505
+ ),
506
+ previewAnnotationsMs,
507
+ runtimeAnnotationsMs,
508
+ fileScanMs,
509
+ moduleLoadAndComposeMs,
510
+ modules: immediateLoaded.map(({ result, loadMs, composeMs }) => ({
511
+ modulePath: result.modulePath,
512
+ loadMs,
513
+ composeMs,
514
+ ok: result.ok,
515
+ })),
516
+ });
517
+ if (deferred.length === 0) return;
518
+
519
+ await waitForStoryImportIdle();
520
+ if (!current()) return;
521
+ const deferredResults = (await loadAll(deferred)).map(({ result }) => result);
522
+ if (!current()) return;
523
+ const resultByPath = new Map(
524
+ [...immediateResults, ...deferredResults].map((result) => [result.modulePath, result]),
525
+ );
526
+ const next = discovered
527
+ .map(({ modulePath }) => resultByPath.get(modulePath))
528
+ .filter((result): result is ProjectStoryModule => result !== undefined);
529
+ publish(next, true);
530
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The `StoriesProvider` node-id protocol's one reserved value.
3
+ *
4
+ * `storiesFor`/`active`/`apply` all take a node id. The EMPTY id is not a node:
5
+ * it is the WORLD-LEVEL question — "list YOUR stories", asked with no node in
6
+ * hand. A world-level provider (contract scenes, a react root's portable CSF)
7
+ * ignores the node id and answers its whole list; a node-scoped provider (the
8
+ * binding `component-states-registry.ts` hands an adapter) has no node here
9
+ * and answers nothing. That
10
+ * difference is the ONE derivation of "which scope is this provider?" in the
11
+ * editor — `components/inspector-stories-gating.ts`'s
12
+ * `resolveWorldStoriesInput`/`resolveNodeScopedStories` are its two readings
13
+ * and must not grow a third.
14
+ *
15
+ * Because it is a PROBE, the answer to it must be a property of the provider,
16
+ * never of session state: an implementer whose empty-id answer depends on what
17
+ * the user last clicked makes its own scope flip under the shell mid-session.
18
+ * Implementers that special-case the empty id import this constant rather than
19
+ * spelling `''`, so the protocol has one definition and the probe and the
20
+ * answer can never drift apart.
21
+ *
22
+ * It lives here (a leaf module importing nothing) rather than beside the gating
23
+ * probe because the providers in this directory answer it, and
24
+ * `components/inspector-stories-gating.ts` value-imports two of them
25
+ * (`ReactRootAuthoringAdapter`, `CompositeAuthoringAdapter`) — so a back-import
26
+ * from an adapter would be a runtime cycle.
27
+ *
28
+ * Nor does it belong in the engine beside `StoriesProvider`. `@volter/project/adapter`,
29
+ * the barrel every consumer imports that type through, is deliberately
30
+ * TYPE-ONLY (P-6) and may not re-export a value; and reaching past it to
31
+ * `@volter/project/adapter/authoring` (which does carry values) would publish an
32
+ * EDITOR-only protocol constant as a public engine entry point, since the
33
+ * engine's export map is the wildcard `"./*"`.
34
+ */
35
+ export const WORLD_SCOPE_NODE_ID = '';
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The ADDRESSES a portable CSF story opens under, and the request shape that
3
+ * carries one — the story kind's half of `document-open-registry.ts`.
4
+ *
5
+ * It lives here, in the host's story estate (the registry, discovery, the
6
+ * declared medium, the arg descriptors, the three mount), and NOT in the
7
+ * documents, because the documents are a contribution: `@volter/editor-game` registers
8
+ * openers for these ids, the host asks for them, and neither side imports the
9
+ * other. A build that does not carry that package simply has no opener, which
10
+ * every call site already handles — `null` is the same answer an undeclared
11
+ * medium has always given.
12
+ *
13
+ * Three ids, because a story opens on three genuinely different surfaces and
14
+ * the CHOICE between them is made in three different places: by the story's
15
+ * declared medium (`story-opener.ts`'s `story` opener), by the owning component's
16
+ * surface (the Content grid), and by the caller asking for Docs explicitly.
17
+ */
18
+
19
+ /** A story rendered on the Object3D document surface — the turntable. */
20
+ export const THREE_STORY_DOCUMENT_OPENER = 'story:three';
21
+ /** A story rendered in its own isolated DOM/canvas preview root. */
22
+ export const ISOLATED_STORY_DOCUMENT_OPENER = 'story:isolated';
23
+ /** The Storybook Docs companion for one story. */
24
+ export const STORY_DOCS_DOCUMENT_OPENER = 'story:docs';
25
+
26
+ export interface StoryDocumentOpenRequest {
27
+ /** Project-relative CSF module path. */
28
+ readonly modulePath: string;
29
+ /** The story's authored export name. */
30
+ readonly storyName: string;
31
+ /** Tab title; the export name when absent. */
32
+ readonly title?: string;
33
+ /** Whether opening also FOCUSES the tab. A click-through opens and focuses;
34
+ * the Edit tab row offers a standing tab instead and passes `false`. */
35
+ readonly activate?: boolean;
36
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * A STORY'S THUMBNAIL, CAPTURED BY THE MEDIUM ITS COMPONENT RENDERS IN — a
3
+ * three.js prefab story is mounted in an offscreen R3F stage, a canvas story in
4
+ * an offscreen Pixi application. The kit's component content asks here by the
5
+ * story's surface and keeps the component's icon where no medium registered.
6
+ */
7
+ import type { AssetPreviewCameraChoice, AssetPreviewPose } from '../types';
8
+
9
+ export interface StoryThumbnailOptions {
10
+ readonly width: number;
11
+ readonly height: number;
12
+ readonly props?: Record<string, unknown>;
13
+ readonly layout?: 'fullscreen' | 'padded' | 'centered';
14
+ /** A free capture camera, where the medium frames its subject itself. */
15
+ readonly camera?: AssetPreviewCameraChoice;
16
+ /** A clip pose for the subject. */
17
+ readonly pose?: AssetPreviewPose;
18
+ }
19
+
20
+ /**
21
+ * The medium's refusal of a story that is not its own (an R3F leg handed a DOM
22
+ * story): the caller tries the next leg, and says nothing, because the refusal
23
+ * is a classification rather than a failure.
24
+ */
25
+ export class StoryMediumMismatch extends Error {
26
+ override readonly name = 'StoryMediumMismatch';
27
+ }
28
+
29
+ export function isStoryMediumMismatch(error: unknown): boolean {
30
+ return error instanceof Error && error.name === 'StoryMediumMismatch';
31
+ }
32
+
33
+ export type StoryThumbnailCapture = (component: unknown, options: StoryThumbnailOptions) => Promise<string>;
34
+
35
+ const captures = new Map<string, StoryThumbnailCapture>();
36
+
37
+ /** Register the capture for one surface (`three`, `canvas`). Returns the removal. */
38
+ export function registerStoryThumbnailCapture(surface: string, capture: StoryThumbnailCapture): () => void {
39
+ captures.set(surface, capture);
40
+ return () => {
41
+ if (captures.get(surface) === capture) captures.delete(surface);
42
+ };
43
+ }
44
+
45
+ export function storyThumbnailCapture(surface: string): StoryThumbnailCapture | null {
46
+ return captures.get(surface) ?? null;
47
+ }