@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,141 @@
1
+ /**
2
+ * A PHOTOGRAPH IS SEEN WHERE IT WAS TAKEN. Owner, 2026-09-28: "when a screenshot is takem in
3
+ * blender, let's show that image in the corner for a little time (like how it happens on macosx)
4
+ * and let's also do the 'camera flash'".
5
+ *
6
+ * So every photograph of the active document (the capture door an agent's
7
+ * `get_viewport_screenshot`, the CLI's `screenshot` and `editor.captureActiveDocument` share)
8
+ * flashes the document's box white and slides the picture into the page's bottom-right corner
9
+ * for a few seconds, the way macOS shows a screenshot it has just taken. Clicking the picture
10
+ * puts it away.
11
+ *
12
+ * Both elements sit OUTSIDE the document's box, in its theme root: a capture photographs the
13
+ * document, so a second photograph taken while the first is still showing cannot contain it.
14
+ * They start only after the capture resolved, so the photograph never holds its own flash.
15
+ *
16
+ * The editor-chrome capture (`cyclotron capture`) shows it too. Its `page` region photographs the
17
+ * whole page, corner included, so it puts away what is showing first (`withdrawPhotograph`). A
18
+ * capture can be named (`cyclotron capture --name "aim up"`); the name is the picture's caption,
19
+ * so a person watching knows what each one was for.
20
+ */
21
+
22
+ import { activeDocumentContainer } from '@volter/sdk/kit/editor-document-probe';
23
+ import { activeWorkspaceDocumentId } from '@volter/sdk/kit/workspace-document-registry';
24
+
25
+ /** How long the picture stays in the corner; macOS keeps its own for about five seconds. */
26
+ const SHOWN_MS = 5_000;
27
+ const FLASH_MS = 350;
28
+ const SLIDE_MS = 240;
29
+
30
+ let showing: HTMLElement | null = null;
31
+ let flashing: HTMLElement | null = null;
32
+
33
+ /** Take the corner picture and the flash off the page at once, before the page is photographed. */
34
+ export function withdrawPhotograph(): void {
35
+ showing?.remove();
36
+ showing = null;
37
+ flashing?.remove();
38
+ flashing = null;
39
+ }
40
+
41
+ export function announcePhotograph(base64: string, name?: string): void {
42
+ if (typeof document === 'undefined') return;
43
+ const id = activeWorkspaceDocumentId();
44
+ const box = id === null ? null : activeDocumentContainer(id);
45
+ const root =
46
+ box?.closest<HTMLElement>('.volter-editor-theme') ??
47
+ document.querySelector<HTMLElement>('.volter-editor-theme') ??
48
+ document.body;
49
+ const still = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;
50
+
51
+ if (box && !still) {
52
+ const rect = box.getBoundingClientRect();
53
+ const flash = document.createElement('div');
54
+ flash.dataset['testid'] = 'photograph-flash';
55
+ Object.assign(flash.style, {
56
+ position: 'fixed',
57
+ left: `${rect.left}px`,
58
+ top: `${rect.top}px`,
59
+ width: `${rect.width}px`,
60
+ height: `${rect.height}px`,
61
+ background: '#ffffff',
62
+ pointerEvents: 'none',
63
+ zIndex: 'var(--volter-z-toast)',
64
+ });
65
+ flashing?.remove();
66
+ flashing = flash;
67
+ root.append(flash);
68
+ flash
69
+ .animate([{ opacity: 0.85 }, { opacity: 0 }], { duration: FLASH_MS, easing: 'ease-out' })
70
+ .finished.finally(() => {
71
+ flash.remove();
72
+ if (flashing === flash) flashing = null;
73
+ });
74
+ }
75
+
76
+ showing?.remove();
77
+ const card = document.createElement('button');
78
+ card.type = 'button';
79
+ card.dataset['testid'] = 'photograph-notice';
80
+ card.title = `${name ? `${name}: photograph` : 'Photograph'} taken. Click to put it away.`;
81
+ card.setAttribute('aria-label', name ? `Photograph taken: ${name}` : 'Photograph taken');
82
+ Object.assign(card.style, {
83
+ position: 'fixed',
84
+ right: 'var(--volter-space-4)',
85
+ bottom: '40px',
86
+ width: '220px',
87
+ padding: '0',
88
+ border: '1px solid var(--volter-selection-border)',
89
+ borderRadius: 'var(--volter-radius-md)',
90
+ background: 'var(--volter-surface-raised)',
91
+ boxShadow: 'var(--volter-shadow-lg)',
92
+ overflow: 'hidden',
93
+ cursor: 'pointer',
94
+ zIndex: 'var(--volter-z-toast)',
95
+ });
96
+ const image = document.createElement('img');
97
+ image.src = `data:image/png;base64,${base64}`;
98
+ image.alt = 'The photograph just taken of the document';
99
+ Object.assign(image.style, { display: 'block', width: '100%', height: 'auto' });
100
+ card.append(image);
101
+ if (name) {
102
+ const caption = document.createElement('div');
103
+ caption.dataset['testid'] = 'photograph-name';
104
+ caption.textContent = name;
105
+ Object.assign(caption.style, {
106
+ padding: 'var(--volter-space-1) var(--volter-space-2)',
107
+ font: 'var(--volter-font-ui-sm, 12px system-ui)',
108
+ color: 'var(--volter-text)',
109
+ textAlign: 'left',
110
+ whiteSpace: 'nowrap',
111
+ overflow: 'hidden',
112
+ textOverflow: 'ellipsis',
113
+ });
114
+ card.append(caption);
115
+ }
116
+ root.append(card);
117
+ showing = card;
118
+
119
+ const away = () => {
120
+ if (showing === card) showing = null;
121
+ if (!card.isConnected) return;
122
+ if (still) {
123
+ card.remove();
124
+ return;
125
+ }
126
+ card
127
+ .animate([{ transform: 'translateX(0)' }, { transform: 'translateX(130%)' }], {
128
+ duration: SLIDE_MS,
129
+ easing: 'ease-in',
130
+ fill: 'forwards',
131
+ })
132
+ .finished.finally(() => card.remove());
133
+ };
134
+ card.addEventListener('click', away, { once: true });
135
+ if (!still)
136
+ card.animate([{ transform: 'translateX(130%)' }, { transform: 'translateX(0)' }], {
137
+ duration: SLIDE_MS,
138
+ easing: 'ease-out',
139
+ });
140
+ window.setTimeout(away, SHOWN_MS);
141
+ }
@@ -0,0 +1,166 @@
1
+ /**
2
+ * WHAT PLAY WAS DOING WHEN IT STOPPED ANSWERING.
3
+ *
4
+ * ## The measurement this exists for
5
+ *
6
+ * 2026-08-20, `packages/editor/scripts/scale-harness` at N=20000 on the canvas
7
+ * lane. the editor's `play` command burned its whole 120s budget and was refused with
8
+ *
9
+ * Command timed out — the tab is present (last heartbeat 0.8s ago) and
10
+ * did not respond.
11
+ *
12
+ * then `screenshot` (15s) and `stop` (30s) were refused with the same sentence.
13
+ * Every one of those statements was TRUE and none of them was the answer: the
14
+ * heartbeat is a WORKER, so it kept beating at 0.4s while the page's main
15
+ * thread sat inside one 199.5-second synchronous block. Four consecutive runs,
16
+ * three silent timeouts each, against a session every reader called healthy.
17
+ *
18
+ * The defect the fix closed was a quadratic name derivation
19
+ * (`@volter/editor-game/runtime/pixi/authoring`). The defect THIS closes is that nothing anywhere
20
+ * could say which of play's eight steps the page was in — the relay knows only
21
+ * that it asked, the tab table knows only that the tab exists, and the page
22
+ * itself, being wedged, is the one party that cannot speak.
23
+ *
24
+ * ## The mechanism
25
+ *
26
+ * A phase is published BEFORE its work starts, on the control channel, as its
27
+ * own tiny message — never folded into the state snapshot, which is the
28
+ * expensive derivation a wedged page cannot produce and which is exactly the
29
+ * thing that goes silent. So the server always holds the phase the page was
30
+ * ENTERING when it went quiet, and the relay's refusal can name it.
31
+ *
32
+ * This module is the page's half and is deliberately pure apart from one
33
+ * injected reporter: the latch, the phase vocabulary, and the sentence are all
34
+ * unit-testable without a browser.
35
+ */
36
+
37
+ /**
38
+ * The steps of a play boot, in the order `play-mode.ts` runs them.
39
+ *
40
+ * The vocabulary is shared with `play-boot-stall.ts`: the three network-shaped
41
+ * steps it already guards use the SAME wording here, so the hidden-tab stall
42
+ * message and a stuck-play refusal cannot describe the same step differently.
43
+ * The steps that guard does not wrap — the runtime mount and the authoring
44
+ * install, which must never be abandoned mid-flight — are the ones that had no
45
+ * name at all, and they are where the 199.5s block was measured.
46
+ */
47
+ export const PLAY_BOOT_PHASES = [
48
+ 'waiting for the editor to bind Play',
49
+ 'waiting for the project bootstrap to settle',
50
+ 'starting the play log session',
51
+ 'opening the Game document',
52
+ 'fetching the project manifest',
53
+ "resolving the project's root entries",
54
+ 'mounting the runtime roots',
55
+ 'installing play authoring for each root',
56
+ 'binding the editor to the running game',
57
+ ] as const;
58
+
59
+ export type PlayBootPhase = (typeof PLAY_BOOT_PHASES)[number];
60
+
61
+ /** The page's standing answer to "what is play doing right now". */
62
+ /** Any main-thread work the page announces before starting it: a play boot
63
+ * step, or a document's `building src/models/x.ts`. */
64
+ export type PagePhase = string;
65
+
66
+ export interface PlayBootPhaseState {
67
+ /** The phase being ENTERED, or `null` once the boot settled either way. */
68
+ readonly phase: PagePhase | null;
69
+ /** Epoch ms the page entered it (or left the last one). */
70
+ readonly at: number;
71
+ /** This play attempt's ordinal, so a stale report is recognizable as stale. */
72
+ readonly run: number;
73
+ }
74
+
75
+ let _state: PlayBootPhaseState = { phase: null, at: 0, run: 0 };
76
+ let _base = _state;
77
+ const work = new Map<symbol, { phase: string; at: number }>();
78
+ let _report: ((state: PlayBootPhaseState) => void) | null = null;
79
+
80
+ /**
81
+ * Install the upstream reporter. Wired once at editor boot; left unset in
82
+ * tests, where the latch is read directly.
83
+ */
84
+ export function setPlayBootPhaseReporter(
85
+ report: ((state: PlayBootPhaseState) => void) | null,
86
+ ): void {
87
+ _report = report;
88
+ // A document may have entered work before the command listener attached.
89
+ publish(_state);
90
+ }
91
+
92
+ function publish(next: PlayBootPhaseState): void {
93
+ _state = next;
94
+ // A reporter that throws must never break a play boot — the phase is
95
+ // diagnostics, and diagnostics that can fail the thing they describe are
96
+ // worse than none.
97
+ try {
98
+ _report?.(next);
99
+ } catch {
100
+ /* the boot continues; the reader loses one phase line */
101
+ }
102
+ }
103
+
104
+ function publishCurrent(): void {
105
+ const current = [...work.values()].at(-1);
106
+ const next = current ? { ...current, run: _base.run } : _base;
107
+ if (next.phase === _state.phase && next.at === _state.at && next.run === _state.run) return;
108
+ publish(next);
109
+ }
110
+
111
+ /** Begin a play attempt. Returns its run ordinal. */
112
+ export function beginPlayBoot(now: number = Date.now()): number {
113
+ _base = { phase: null, at: now, run: _base.run + 1 };
114
+ publishCurrent();
115
+ return _state.run;
116
+ }
117
+
118
+ /** Enter one phase. Called BEFORE the phase's work, never after it. */
119
+ export function markPlayBootPhase(phase: PlayBootPhase, now: number = Date.now()): void {
120
+ _base = { phase, at: now, run: _base.run };
121
+ publishCurrent();
122
+ }
123
+
124
+ /**
125
+ * The boot settled — started, failed, or was superseded. Clearing the phase is
126
+ * what makes a LATER stuck command ("stop", "screenshot") report honestly that
127
+ * play was not booting rather than blaming the last phase of a boot that
128
+ * finished minutes ago.
129
+ */
130
+ export function endPlayBoot(now: number = Date.now()): void {
131
+ _base = { phase: null, at: now, run: _base.run };
132
+ publishCurrent();
133
+ }
134
+
135
+ /**
136
+ * Announce main-thread work that is NOT a play boot — a model document about
137
+ * to run a module's `build()` — so a command that times out while the page is
138
+ * inside it is refused by name ("the page is still inside building
139
+ * src/models/mushroom.ts") instead of "never answered". A blind session on a
140
+ * swapped box read the generic refusal as its own module hanging and bisected
141
+ * a parameter for five minutes (2026-09-06). Returns an idempotent end call.
142
+ * Overlapping work has distinct tokens, even with identical labels: a late
143
+ * completion must not erase a newer call, or leave a completed child blamed.
144
+ * Labels name operations only, never model contents, scripts or credentials.
145
+ */
146
+ export function beginPageWork(label: string, now: number = Date.now()): () => void {
147
+ const token = Symbol();
148
+ work.set(token, { phase: label.slice(0, 160), at: now });
149
+ publishCurrent();
150
+ return () => {
151
+ if (!work.delete(token)) return;
152
+ publishCurrent();
153
+ };
154
+ }
155
+
156
+ export function currentPlayBootPhase(): PlayBootPhaseState {
157
+ return _state;
158
+ }
159
+
160
+ /** Test-only reset — drops the latch and the reporter. */
161
+ export function __resetPlayBootPhaseForTest(): void {
162
+ _state = { phase: null, at: 0, run: 0 };
163
+ _base = _state;
164
+ work.clear();
165
+ _report = null;
166
+ }
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The camera half of Play's immersive entry (`host.viewport.transition`): the viewport flies from
3
+ * its preview pose to the authored game camera while the chrome dissolves, converges on the
4
+ * game's live camera once it boots, and restores the preview pose when Play ends. The kit's
5
+ * transition owns the phases and the chrome; the Three integration registers the flight.
6
+ */
7
+ import type { EditorHostLiveTransition } from '../host';
8
+
9
+ /** The game's live render camera, handed over when its runtime is ready. */
10
+ export type LiveCameraLookup = NonNullable<Parameters<EditorHostLiveTransition['ready']>[0]>;
11
+
12
+ export interface PlayCameraFlight {
13
+ /** Resolve the authored camera and start flying; `false` when there is nothing to fly to (no
14
+ * viewport, no authored camera). `onLanded` runs once, when the flight reaches its target. */
15
+ begin(onLanded: () => void): boolean;
16
+ /** Converge on the game's live camera from now on. */
17
+ track(liveCamera: LiveCameraLookup): void;
18
+ /** The game is on screen: stop driving the camera and leave orbit usable at the landed pose. */
19
+ settle(): void;
20
+ /** Play ended: restore the pose the viewport had before the flight. */
21
+ end(): void;
22
+ }
23
+
24
+ let registered: PlayCameraFlight | null = null;
25
+
26
+ export function registerPlayCameraFlight(flight: PlayCameraFlight): () => void {
27
+ registered = flight;
28
+ return () => {
29
+ if (registered === flight) registered = null;
30
+ };
31
+ }
32
+
33
+ export function playCameraFlight(): PlayCameraFlight | null {
34
+ return registered;
35
+ }
@@ -0,0 +1,26 @@
1
+ /** One owned screenshot bitmap; encode away from the live document's frame loop. */
2
+ const worker = self as unknown as {
3
+ onmessage: ((event: MessageEvent<ImageBitmap>) => void) | null;
4
+ postMessage(message: unknown): void;
5
+ close(): void;
6
+ };
7
+
8
+ worker.onmessage = async ({ data: bitmap }) => {
9
+ const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);
10
+ try {
11
+ const context = canvas.getContext('2d');
12
+ if (!context) throw new Error('PNG encoding has no 2d canvas context');
13
+ context.drawImage(bitmap, 0, 0);
14
+ const blob = await canvas.convertToBlob({ type: 'image/png' });
15
+ worker.postMessage({ blob });
16
+ } catch (error) {
17
+ worker.postMessage({ error: error instanceof Error ? error.message : String(error) });
18
+ } finally {
19
+ bitmap.close();
20
+ canvas.width = 0;
21
+ canvas.height = 0;
22
+ worker.close();
23
+ }
24
+ };
25
+
26
+ export {};
@@ -0,0 +1,248 @@
1
+ /**
2
+ * THE DECLARED PRESENTATION SURFACE — the one door for "what is this game
3
+ * presented on, and which element carries its pixels".
4
+ *
5
+ * ARCHITECTURE-CORE §The editor protocol, "Zero inference": read a declaration,
6
+ * walk ground truth, or diagnose declared-vs-measured drift — never guess a
7
+ * fact the game's author (or, here, the HOST'S OWN MOUNT) already stated. Three
8
+ * capture-side readers were guessing:
9
+ *
10
+ * · `composite-screenshot.ts` counted `<canvas>` children to decide whether
11
+ * the subject is a DOM-only medium and therefore needs the compositor
12
+ * settle window;
13
+ * · `play-mode.ts`'s `getPlayCanvas` took the FIRST `<canvas>` in DOM order
14
+ * as "the game canvas" — a guess about authoring order that a game with a
15
+ * minimap, an offscreen buffer, or a 2D overlay quietly loses;
16
+ * · `command-listener.ts`'s screenshot staleness gate skipped itself when no
17
+ * canvas was found, i.e. inferred "React-only root" from a DOM absence.
18
+ *
19
+ * Every one of those facts is DECLARED somewhere already:
20
+ *
21
+ * · the MEDIUM is the adapter's region table (`project-adapter.ts`) — a
22
+ * region's `surface` is a first-party statement about what the host hands
23
+ * that root;
24
+ * · a HOST-MOUNTED root's canvas is stamped with its root id by the mount
25
+ * that created it (`create-runtime.ts`, `data-volter-root-id`);
26
+ * · a SELF-BOOTING game's canvas is its own, so its contract declares it
27
+ * (`window.volterGame.presentation`), and the ingest mount records it here.
28
+ *
29
+ * The measured answers all remain, because a game that declares nothing must
30
+ * keep working — but they are REPORTED as measured (`source`), so "nobody
31
+ * stated this" is a visible fact instead of an invisible default.
32
+ */
33
+
34
+ import {
35
+ type AdapterRegion,
36
+ type AdapterRegionBasis,
37
+ NATIVE_REGION_BASIS,
38
+ } from '@volter/project/adapter/adapter-module';
39
+
40
+ /** Where an answer came from. `none` = there is no answer at all, which is
41
+ * deliberately distinct from a measured one. */
42
+ export type PresentationSource = 'declared' | 'measured' | 'none';
43
+
44
+ /** What the game is presented ON. `unknown` means no adapter table has loaded
45
+ * yet — "nobody looked", never "it has no canvas". */
46
+ export type PresentationMedium = 'canvas' | 'dom' | 'unknown';
47
+
48
+ export interface PresentationSurfaceReading {
49
+ /** The element carrying the game's pixels, or `null` for a DOM-only game (or
50
+ * before anything mounted). */
51
+ readonly canvas: HTMLCanvasElement | null;
52
+ /** How {@link canvas} was answered. */
53
+ readonly source: PresentationSource;
54
+ /** The root the surface belongs to, when the answer named one. */
55
+ readonly rootId: string | null;
56
+ /** What the ADAPTER declares this project is presented on. */
57
+ readonly medium: PresentationMedium;
58
+ }
59
+
60
+ /** The host stamp `create-runtime.ts` writes on every surface it mounts. */
61
+ const ROOT_ID_ATTRIBUTE = 'data-volter-root-id';
62
+
63
+ /**
64
+ * Presentation elements a SELF-BOOTING game owns, keyed by root id — the
65
+ * ingest mount records one per mounted game and drops it on teardown. Most are
66
+ * canvases; CSS3DRenderer truthfully contributes a DOM element and `canvas: null`.
67
+ *
68
+ * RESOURCE OWNERSHIP: the ingest mount path that recorded an entry
69
+ * (`authoring/ingest-root-adapter.ts`) is the only party that clears it, in its
70
+ * own teardown. Nothing else writes this map, and a stale entry cannot outlive
71
+ * its mount, because the reading below also requires the canvas to still be
72
+ * inside the container it is asked about.
73
+ */
74
+ const _selfBooting = new Map<
75
+ string,
76
+ {
77
+ element: HTMLElement;
78
+ canvas: HTMLCanvasElement | null;
79
+ source: 'declared' | 'measured';
80
+ }
81
+ >();
82
+
83
+ /**
84
+ * Record the element a self-booting game presents on.
85
+ *
86
+ * `source` is the honesty: `declared` when the game's own contract named it
87
+ * (`window.volterGame.presentation`), `measured` when the host took the captured
88
+ * renderer's `domElement` — which is a real measurement off the render trap,
89
+ * not a DOM-order guess, but still not a statement by the game.
90
+ */
91
+ export function recordPresentationSurface(
92
+ rootId: string,
93
+ element: HTMLElement,
94
+ source: 'declared' | 'measured',
95
+ ): void {
96
+ const canvas = element.tagName === 'CANVAS' ? (element as HTMLCanvasElement) : null;
97
+ _selfBooting.set(rootId, { element, canvas, source });
98
+ }
99
+
100
+ /** Drop one mount's recorded surface — what its teardown calls. */
101
+ export function clearPresentationSurface(rootId: string): void {
102
+ _selfBooting.delete(rootId);
103
+ }
104
+
105
+ /** Test seam: drop every recorded surface and the published region table. */
106
+ export function __resetPresentationSurfacesForTest(): void {
107
+ _selfBooting.clear();
108
+ _regions = [];
109
+ }
110
+
111
+ /**
112
+ * The loaded adapter's regions, PUSHED here by their one owner rather than
113
+ * pulled from it.
114
+ *
115
+ * `project-adapter.ts` publishes the resolved table and calls this from the
116
+ * same `publish`, so there is still exactly one place regions are decided. The
117
+ * direction matters: this module is read from inside the ingest mount and from
118
+ * `play-mode.ts`, and importing the adapter loader would drag its whole
119
+ * transitive graph (editor API, project manager, story registry, the ingest
120
+ * registry) into both. A one-line push keeps this module dependency-free apart
121
+ * from an engine TYPE — which is also what makes it testable without standing
122
+ * up a project.
123
+ */
124
+ let _regions: readonly AdapterRegion[] = [];
125
+
126
+ export function setPresentationRegions(regions: readonly AdapterRegion[]): void {
127
+ _regions = regions;
128
+ }
129
+
130
+ /** The adapter's regions — the manifest allows at most one per medium. */
131
+ function contentRegions(): readonly AdapterRegion[] {
132
+ return _regions;
133
+ }
134
+
135
+ /**
136
+ * The world basis the loaded adapter declares for `surface`'s CONTENT region —
137
+ * "which way is up in this game, and where is its ground". The gizmo viewport's
138
+ * ground-plane raycast (asset drop, nav probe) reads it instead of the `y = 0`
139
+ * constant it used to compile in (ARCHITECTURE-CORE §The editor protocol,
140
+ * "Zero inference").
141
+ *
142
+ * It lives HERE, on the pushed region table, and not on the loader that fills
143
+ * it, for the same reason {@link presentationSurface} does: the viewport is a
144
+ * surface below the shell, and importing `project-adapter.ts` to ask one
145
+ * question about one region drags the whole loader graph (editor API, project
146
+ * manager, story registry, the ingest registry) into it — measured at 121 files
147
+ * for a two-line read. The push already delivered the answer; this is the
148
+ * reader beside it.
149
+ *
150
+ * Before the first load, and for a region that declares no basis, the answer is
151
+ * {@link NATIVE_REGION_BASIS} — the declared native default, which
152
+ * `regionsFromManifestRoots` publishes outright.
153
+ */
154
+ export function presentationRegionBasis(surface: AdapterRegion['surface']): AdapterRegionBasis {
155
+ return _regions.find((entry) => entry.surface === surface)?.basis ?? NATIVE_REGION_BASIS;
156
+ }
157
+
158
+ /**
159
+ * What the ADAPTER declares this project is presented on.
160
+ *
161
+ * `three` and `canvas` regions are handed a canvas by the host; a `dom` region
162
+ * is handed a DOM container. A project with both is `canvas` — the canvas is
163
+ * where the game's pixels are, and the HUD rides over it.
164
+ */
165
+ function presentationMedium(container: HTMLElement | null): PresentationMedium {
166
+ const regions = contentRegions();
167
+ if (regions.length === 0) return 'unknown';
168
+ return regions.some((region) => {
169
+ if (region.surface === 'dom') return false;
170
+ const measured = _selfBooting.get(region.id);
171
+ return (
172
+ !measured || measured.canvas !== null || !container || !holds(container, measured.element)
173
+ );
174
+ })
175
+ ? 'canvas'
176
+ : 'dom';
177
+ }
178
+
179
+ /**
180
+ * A container is only queryable if it really is an element.
181
+ *
182
+ * The play container reaches here from several routes, and the relay's own
183
+ * harnesses hand in stand-ins that implement exactly the members the old reader
184
+ * touched. Every DOM read below is therefore capability-checked rather than
185
+ * assumed: a container that cannot answer a question contributes nothing to the
186
+ * reading, which lands on `source: 'none'` — the honest answer, and the one that
187
+ * leaves each caller's own degrade path (the canvas-only capture leg, the
188
+ * screenshot's named refusal) exactly where it was.
189
+ */
190
+ function holds(container: HTMLElement, element: HTMLElement): boolean {
191
+ return typeof container.contains === 'function' && container.contains(element);
192
+ }
193
+
194
+ /** The declared-canvas legs, in precedence order, or `null` when none answers. */
195
+ function declaredCanvas(
196
+ container: HTMLElement,
197
+ ): { canvas: HTMLCanvasElement; rootId: string } | null {
198
+ // 1. A self-booting game's own declaration wins outright.
199
+ for (const [rootId, entry] of _selfBooting) {
200
+ if (entry.canvas && entry.source === 'declared' && holds(container, entry.canvas)) {
201
+ return { canvas: entry.canvas, rootId };
202
+ }
203
+ }
204
+ // 2. A host-mounted root's canvas carries the id of the root it presents —
205
+ // stamped by the mount that made it, so this is a read, not a search for
206
+ // something canvas-shaped.
207
+ const stamped =
208
+ typeof container.querySelectorAll === 'function'
209
+ ? Array.from(container.querySelectorAll<HTMLCanvasElement>(`canvas[${ROOT_ID_ATTRIBUTE}]`))
210
+ : [];
211
+ for (const region of contentRegions()) {
212
+ if (region.surface === 'dom') continue;
213
+ const match = stamped.find((canvas) => canvas.dataset['volterRootId'] === region.id);
214
+ if (match) return { canvas: match, rootId: region.id };
215
+ }
216
+ return null;
217
+ }
218
+
219
+ /**
220
+ * Resolve the presentation surface inside `container`.
221
+ *
222
+ * Declaration first, measured fallback SECOND AND LABELLED. The fallback is
223
+ * still first-canvas-in-DOM-order — deliberately unchanged, because a game that
224
+ * declares nothing must behave exactly as it did — but it now arrives as
225
+ * `source: 'measured'` wherever it is reported, so the guess is legible.
226
+ */
227
+ export function presentationSurface(container: HTMLElement | null): PresentationSurfaceReading {
228
+ const medium = presentationMedium(container);
229
+ if (!container) return { canvas: null, source: 'none', rootId: null, medium };
230
+ const declared = declaredCanvas(container);
231
+ if (declared) {
232
+ return { canvas: declared.canvas, source: 'declared', rootId: declared.rootId, medium };
233
+ }
234
+ // A self-booting game whose contract declared nothing: the host's own
235
+ // measurement (the captured renderer's element) still beats a DOM sweep.
236
+ for (const [rootId, entry] of _selfBooting) {
237
+ if (entry.canvas && holds(container, entry.canvas)) {
238
+ return { canvas: entry.canvas, source: 'measured', rootId, medium };
239
+ }
240
+ if (holds(container, entry.element)) {
241
+ return { canvas: null, source: entry.source, rootId, medium };
242
+ }
243
+ }
244
+ const first =
245
+ typeof container.querySelector === 'function' ? container.querySelector('canvas') : null;
246
+ if (first) return { canvas: first, source: 'measured', rootId: null, medium };
247
+ return { canvas: null, source: 'none', rootId: null, medium };
248
+ }