@volter/sdk 0.0.0-stage → 0.5.204

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (523) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +20 -0
  3. package/README.md +38 -3
  4. package/package.json +510 -4
  5. package/src/account.ts +210 -0
  6. package/src/chrome.ts +88 -0
  7. package/src/client.ts +1646 -0
  8. package/src/commands.ts +66 -0
  9. package/src/contributions.ts +619 -0
  10. package/src/css-numeric-style.ts +97 -0
  11. package/src/document-probe.ts +282 -0
  12. package/src/editor-view.ts +225 -0
  13. package/src/extension.ts +40 -0
  14. package/src/generations.ts +178 -0
  15. package/src/host.ts +1157 -0
  16. package/src/http-transport.browser.ts +14 -0
  17. package/src/http-transport.node.ts +19 -0
  18. package/src/index.ts +131 -0
  19. package/src/kit/CapabilityCoverageSection.tsx +185 -0
  20. package/src/kit/account-client.ts +333 -0
  21. package/src/kit/action-registry.ts +317 -0
  22. package/src/kit/active-product.ts +76 -0
  23. package/src/kit/active-project.ts +155 -0
  24. package/src/kit/adapter-editor-config.ts +25 -0
  25. package/src/kit/adapter-module.ts +7 -0
  26. package/src/kit/adapter-observation.ts +49 -0
  27. package/src/kit/animation/animation-clock.ts +479 -0
  28. package/src/kit/animation/stage-transport.ts +385 -0
  29. package/src/kit/api/assets.ts +365 -0
  30. package/src/kit/api/project-open.ts +355 -0
  31. package/src/kit/api/project-source.ts +180 -0
  32. package/src/kit/api/project-state.ts +110 -0
  33. package/src/kit/api/relay.ts +270 -0
  34. package/src/kit/api/themes.ts +45 -0
  35. package/src/kit/api-asset-library-wire.ts +45 -0
  36. package/src/kit/api-base.ts +10 -0
  37. package/src/kit/api-build.ts +99 -0
  38. package/src/kit/api-git-wire.ts +56 -0
  39. package/src/kit/api-logs.ts +92 -0
  40. package/src/kit/api-project-identity.ts +74 -0
  41. package/src/kit/api-settings.ts +36 -0
  42. package/src/kit/api-worktrees.ts +205 -0
  43. package/src/kit/asset-capabilities.ts +344 -0
  44. package/src/kit/asset-compare-core.ts +171 -0
  45. package/src/kit/asset-editor-context.tsx +101 -0
  46. package/src/kit/asset-events.ts +96 -0
  47. package/src/kit/asset-inspector-actions.ts +87 -0
  48. package/src/kit/asset-selection-viewer-registry.ts +113 -0
  49. package/src/kit/asset-selection.ts +146 -0
  50. package/src/kit/asset-thumbnails.ts +25 -0
  51. package/src/kit/asset-viewers.ts +115 -0
  52. package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
  53. package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
  54. package/src/kit/asset-workflow/asset-ledger.ts +156 -0
  55. package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
  56. package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
  57. package/src/kit/asset-workflow/asset-types.ts +142 -0
  58. package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
  59. package/src/kit/asset-workflow/audio-waveform.ts +22 -0
  60. package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
  61. package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
  62. package/src/kit/asset-workflow/image-view-scale.ts +31 -0
  63. package/src/kit/asset-workflow/import-contract.ts +124 -0
  64. package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
  65. package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
  66. package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
  67. package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
  68. package/src/kit/asset-workflow/project-content.ts +288 -0
  69. package/src/kit/asset-workflow/project-source-index.ts +545 -0
  70. package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
  71. package/src/kit/authoring/active-adapter.ts +200 -0
  72. package/src/kit/authoring/active-systems.ts +422 -0
  73. package/src/kit/authoring/adapter-key.ts +18 -0
  74. package/src/kit/authoring/authoring-asset-url.ts +27 -0
  75. package/src/kit/authoring/bootstrap-state.ts +49 -0
  76. package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
  77. package/src/kit/authoring/canvas-scene-guides.ts +84 -0
  78. package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
  79. package/src/kit/authoring/consumer-actions.ts +531 -0
  80. package/src/kit/authoring/design-time-layers.ts +852 -0
  81. package/src/kit/authoring/design-time-mount-registry.ts +244 -0
  82. package/src/kit/authoring/edit-mode-authoring.ts +637 -0
  83. package/src/kit/authoring/empty-project-authoring.ts +22 -0
  84. package/src/kit/authoring/instance-source-menu.ts +135 -0
  85. package/src/kit/authoring/layered-pick.ts +185 -0
  86. package/src/kit/authoring/mounted-root-subjects.ts +146 -0
  87. package/src/kit/authoring/no-authoring-adapter.ts +59 -0
  88. package/src/kit/authoring/object3d-document-persistence.ts +122 -0
  89. package/src/kit/authoring/panel-authoring.ts +121 -0
  90. package/src/kit/authoring/project-authoring-session.ts +105 -0
  91. package/src/kit/authoring/provenance.ts +99 -0
  92. package/src/kit/authoring/react-canvas-navigation.ts +259 -0
  93. package/src/kit/authoring/react-design-canvas-style.ts +20 -0
  94. package/src/kit/authoring/react-story-board.ts +917 -0
  95. package/src/kit/authoring/selection-scope.ts +195 -0
  96. package/src/kit/authoring/shell-document-ops.ts +169 -0
  97. package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
  98. package/src/kit/authoring/story-board-presentation.ts +111 -0
  99. package/src/kit/authoring/three-root.ts +67 -0
  100. package/src/kit/authoring/viewport-tool-context.ts +73 -0
  101. package/src/kit/authoring/viewport-tool-owner.ts +38 -0
  102. package/src/kit/authoring/world-session-state.ts +101 -0
  103. package/src/kit/authoring-seam-evidence.ts +300 -0
  104. package/src/kit/availability-tick.ts +66 -0
  105. package/src/kit/bitmap-label.ts +120 -0
  106. package/src/kit/boot-routing.ts +392 -0
  107. package/src/kit/breakpoint-state.ts +43 -0
  108. package/src/kit/build-identity.ts +16 -0
  109. package/src/kit/bytes-codec.ts +62 -0
  110. package/src/kit/cancellation-reason.ts +58 -0
  111. package/src/kit/canvas-frames.ts +88 -0
  112. package/src/kit/capture-camera-pose.ts +77 -0
  113. package/src/kit/capture-size.ts +88 -0
  114. package/src/kit/chrome-registry.ts +159 -0
  115. package/src/kit/chrome-slot-registry.ts +91 -0
  116. package/src/kit/collaboration-client.ts +264 -0
  117. package/src/kit/collaboration-presence.ts +41 -0
  118. package/src/kit/command-dispatch.ts +19 -0
  119. package/src/kit/command-listener.ts +2182 -0
  120. package/src/kit/command-registry.ts +71 -0
  121. package/src/kit/component-board-registry.ts +205 -0
  122. package/src/kit/component-states-registry.ts +199 -0
  123. package/src/kit/components/AlignToolbar.tsx +204 -0
  124. package/src/kit/components/ApplicationMenus.tsx +372 -0
  125. package/src/kit/components/AssetEditorShell.tsx +216 -0
  126. package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
  127. package/src/kit/components/BoardRulers.tsx +354 -0
  128. package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
  129. package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
  130. package/src/kit/components/ChromeSlot.tsx +20 -0
  131. package/src/kit/components/CodeView.tsx +470 -0
  132. package/src/kit/components/CompactInspectorShell.tsx +39 -0
  133. package/src/kit/components/ConsolePanel.tsx +273 -0
  134. package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
  135. package/src/kit/components/InspectionProjection.tsx +932 -0
  136. package/src/kit/components/Inspector.tsx +270 -0
  137. package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
  138. package/src/kit/components/InspectorFieldsSection.tsx +290 -0
  139. package/src/kit/components/InspectorStoriesSection.tsx +92 -0
  140. package/src/kit/components/InspectorToolSection.tsx +96 -0
  141. package/src/kit/components/InspectorTransformSection.tsx +245 -0
  142. package/src/kit/components/LightExplorerPanel.tsx +433 -0
  143. package/src/kit/components/MediaProperties.tsx +145 -0
  144. package/src/kit/components/ProjectHeader.tsx +328 -0
  145. package/src/kit/components/ReactCanvasControls.tsx +358 -0
  146. package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
  147. package/src/kit/components/RootTextEditor.tsx +79 -0
  148. package/src/kit/components/SaveStatus.tsx +70 -0
  149. package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
  150. package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
  151. package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
  152. package/src/kit/components/ToolHost.tsx +380 -0
  153. package/src/kit/components/Toolbar.tsx +811 -0
  154. package/src/kit/components/TransientHint.tsx +44 -0
  155. package/src/kit/components/VersionControlSection.tsx +470 -0
  156. package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
  157. package/src/kit/components/VolterLogo.tsx +18 -0
  158. package/src/kit/components/WorktreeSwitcher.tsx +712 -0
  159. package/src/kit/components/account-documents.tsx +1162 -0
  160. package/src/kit/components/asset-documents.tsx +794 -0
  161. package/src/kit/components/asset-editor-persistence.ts +216 -0
  162. package/src/kit/components/asset-selection-section.tsx +545 -0
  163. package/src/kit/components/asset-thumbnails.tsx +307 -0
  164. package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
  165. package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
  166. package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
  167. package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
  168. package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
  169. package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
  170. package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
  171. package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
  172. package/src/kit/components/asset-viewers/shader-source.ts +144 -0
  173. package/src/kit/components/board-guides.ts +150 -0
  174. package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
  175. package/src/kit/components/canvas-temporary-pivot.ts +34 -0
  176. package/src/kit/components/core-utilities.tsx +94 -0
  177. package/src/kit/components/inspector-preview-section.tsx +223 -0
  178. package/src/kit/components/inspector-revert-label.ts +20 -0
  179. package/src/kit/components/inspector-selection.ts +42 -0
  180. package/src/kit/components/inspector-stories-gating.ts +171 -0
  181. package/src/kit/components/inspector-transform-subject.ts +11 -0
  182. package/src/kit/components/inspector-transform.ts +88 -0
  183. package/src/kit/components/kind-documents.tsx +544 -0
  184. package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
  185. package/src/kit/components/project-tool-documents.tsx +402 -0
  186. package/src/kit/components/scene-documents.tsx +221 -0
  187. package/src/kit/components/status-contributions.tsx +407 -0
  188. package/src/kit/components/tool-documents.tsx +302 -0
  189. package/src/kit/components/tool-schema-form.tsx +262 -0
  190. package/src/kit/components/use-after-paint.ts +41 -0
  191. package/src/kit/components/use-project-image-assets.ts +86 -0
  192. package/src/kit/components/workspace-history.ts +32 -0
  193. package/src/kit/components/world-documents.tsx +570 -0
  194. package/src/kit/components/world-overlay-gestures.ts +1939 -0
  195. package/src/kit/composite-screenshot.ts +2238 -0
  196. package/src/kit/content-entry-source-registry.ts +184 -0
  197. package/src/kit/contribution-surfaces.ts +48 -0
  198. package/src/kit/coverage/canvas-reveal.ts +192 -0
  199. package/src/kit/coverage/design-time-surfaces.ts +101 -0
  200. package/src/kit/coverage/ontology-invariants.ts +466 -0
  201. package/src/kit/coverage/session-vitals.ts +503 -0
  202. package/src/kit/crash-null-boundary.ts +36 -0
  203. package/src/kit/creation-site-edit.ts +1491 -0
  204. package/src/kit/creation-site-registry.ts +160 -0
  205. package/src/kit/delegate-harness-registry.ts +134 -0
  206. package/src/kit/document-areas.ts +70 -0
  207. package/src/kit/document-context-registry.ts +193 -0
  208. package/src/kit/document-open-registry.ts +200 -0
  209. package/src/kit/document-play-extension.ts +221 -0
  210. package/src/kit/document-preview-source.ts +20 -0
  211. package/src/kit/document-renderer-session.ts +138 -0
  212. package/src/kit/document-stage-sessions.ts +26 -0
  213. package/src/kit/document-viewports.ts +120 -0
  214. package/src/kit/editor-api.ts +46 -0
  215. package/src/kit/editor-chrome-capture.ts +136 -0
  216. package/src/kit/editor-commands.ts +176 -0
  217. package/src/kit/editor-console.ts +580 -0
  218. package/src/kit/editor-current-view.ts +56 -0
  219. package/src/kit/editor-document-probe.ts +1168 -0
  220. package/src/kit/editor-git-client.ts +115 -0
  221. package/src/kit/editor-hotkeys.ts +728 -0
  222. package/src/kit/editor-lease-view.ts +39 -0
  223. package/src/kit/editor-lease.ts +415 -0
  224. package/src/kit/editor-mode.ts +19 -0
  225. package/src/kit/editor-notifications.ts +140 -0
  226. package/src/kit/editor-presence.ts +563 -0
  227. package/src/kit/editor-presentation-activity.ts +58 -0
  228. package/src/kit/editor-presentation-notice.ts +42 -0
  229. package/src/kit/editor-runtime.tsx +147 -0
  230. package/src/kit/editor-server-response.ts +86 -0
  231. package/src/kit/editor-session-attribution.ts +85 -0
  232. package/src/kit/editor-session-mode.ts +54 -0
  233. package/src/kit/editor-state-facets.ts +74 -0
  234. package/src/kit/editor-view-presentation.ts +777 -0
  235. package/src/kit/environment-images.ts +58 -0
  236. package/src/kit/eyedropper-session.ts +60 -0
  237. package/src/kit/files/file-provider.ts +62 -0
  238. package/src/kit/files/project-files.ts +270 -0
  239. package/src/kit/finders/index.ts +137 -0
  240. package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
  241. package/src/kit/frame/frame-parts.ts +30 -0
  242. package/src/kit/framed-document-capture.ts +34 -0
  243. package/src/kit/game-globals-prelude.ts +143 -0
  244. package/src/kit/game-surface-defaults.ts +33 -0
  245. package/src/kit/gameplay-dom-recording.ts +318 -0
  246. package/src/kit/gameplay-export-state.ts +14 -0
  247. package/src/kit/gameplay-replay.ts +417 -0
  248. package/src/kit/gameplay-session-time.ts +9 -0
  249. package/src/kit/gameplay-sessions.ts +204 -0
  250. package/src/kit/hierarchy-component-marks.ts +298 -0
  251. package/src/kit/hierarchy-internals.ts +197 -0
  252. package/src/kit/hierarchy-kind-icon.ts +217 -0
  253. package/src/kit/hierarchy-menu-registry.ts +67 -0
  254. package/src/kit/hierarchy-node-rows.ts +307 -0
  255. package/src/kit/hierarchy-panel-view.ts +280 -0
  256. package/src/kit/hierarchy-projection.ts +76 -0
  257. package/src/kit/hierarchy-row-media.ts +45 -0
  258. package/src/kit/hierarchy-row-model.ts +308 -0
  259. package/src/kit/hierarchy-rows.ts +11 -0
  260. package/src/kit/hierarchy-walk.ts +86 -0
  261. package/src/kit/history/editor-session.ts +25 -0
  262. package/src/kit/history/history-commands.ts +147 -0
  263. package/src/kit/history/history-delegate.ts +187 -0
  264. package/src/kit/history/history-limit-notices.ts +43 -0
  265. package/src/kit/history/history-service.ts +1189 -0
  266. package/src/kit/history/persistence-coordinator.ts +35 -0
  267. package/src/kit/history/project-file-history.ts +386 -0
  268. package/src/kit/history/project-root-history-backends.ts +139 -0
  269. package/src/kit/history/resource-registry.ts +209 -0
  270. package/src/kit/history/snapshot-store.ts +103 -0
  271. package/src/kit/history/source-history-backend.ts +546 -0
  272. package/src/kit/history-types.ts +124 -0
  273. package/src/kit/hmr-registration-group.ts +67 -0
  274. package/src/kit/hmr-stable-react-context.ts +23 -0
  275. package/src/kit/hotkeys.ts +190 -0
  276. package/src/kit/inference-diagnostics.ts +69 -0
  277. package/src/kit/initial-project.ts +80 -0
  278. package/src/kit/inspection/active-subject.ts +571 -0
  279. package/src/kit/inspection/active-surface.ts +142 -0
  280. package/src/kit/inspection/compose-subject.ts +1055 -0
  281. package/src/kit/inspection/compose.ts +7 -0
  282. package/src/kit/inspection/display.ts +171 -0
  283. package/src/kit/inspection/document-subject.ts +109 -0
  284. package/src/kit/inspection/game-subject.ts +85 -0
  285. package/src/kit/inspection/null-subject.ts +119 -0
  286. package/src/kit/inspection/serialize.ts +357 -0
  287. package/src/kit/inspection/use-active-inspection.ts +180 -0
  288. package/src/kit/inspection-model.ts +542 -0
  289. package/src/kit/inspection-node-media.ts +58 -0
  290. package/src/kit/inspector-presentation.ts +203 -0
  291. package/src/kit/inspector-property-grouping.ts +64 -0
  292. package/src/kit/inspector-section-registry.ts +221 -0
  293. package/src/kit/instance-source-actions.ts +163 -0
  294. package/src/kit/js-heap.ts +71 -0
  295. package/src/kit/key-actions.ts +91 -0
  296. package/src/kit/keymap-presets.ts +428 -0
  297. package/src/kit/layout-policy.ts +31 -0
  298. package/src/kit/light-explorer-model.ts +134 -0
  299. package/src/kit/live-canvas-frame.ts +55 -0
  300. package/src/kit/live-document.ts +296 -0
  301. package/src/kit/live-gesture-lock.ts +50 -0
  302. package/src/kit/live-seam-evidence.ts +11 -0
  303. package/src/kit/live-session-registry.ts +220 -0
  304. package/src/kit/live-transition.ts +391 -0
  305. package/src/kit/manifest-project.ts +107 -0
  306. package/src/kit/module-fetch-diagnosis.ts +192 -0
  307. package/src/kit/mount-failure-report.ts +154 -0
  308. package/src/kit/native-selection-style.ts +497 -0
  309. package/src/kit/object3d-document-write-policy.ts +137 -0
  310. package/src/kit/packaged-runtime.ts +108 -0
  311. package/src/kit/palettes/maya.palette.json +57 -0
  312. package/src/kit/palettes/substance.palette.json +57 -0
  313. package/src/kit/performance-profiler.ts +367 -0
  314. package/src/kit/performance-sources.ts +69 -0
  315. package/src/kit/photograph-notice.ts +141 -0
  316. package/src/kit/play-boot-phase.ts +166 -0
  317. package/src/kit/play-camera-flight.ts +35 -0
  318. package/src/kit/png-encode.worker.ts +26 -0
  319. package/src/kit/presentation-surface.ts +248 -0
  320. package/src/kit/product-command.ts +90 -0
  321. package/src/kit/project-adapter.ts +1140 -0
  322. package/src/kit/project-asset-refresh.ts +23 -0
  323. package/src/kit/project-asset-roots.ts +68 -0
  324. package/src/kit/project-local-state.ts +151 -0
  325. package/src/kit/project-manager.ts +243 -0
  326. package/src/kit/project-module-changes.ts +201 -0
  327. package/src/kit/project-module-split.ts +270 -0
  328. package/src/kit/project-play-layers.ts +25 -0
  329. package/src/kit/project-provenance.ts +115 -0
  330. package/src/kit/project-ready.ts +42 -0
  331. package/src/kit/project-shape.ts +68 -0
  332. package/src/kit/project-tools.ts +107 -0
  333. package/src/kit/projection-types.ts +44 -0
  334. package/src/kit/readiness.ts +113 -0
  335. package/src/kit/renderer-resource-counts.ts +27 -0
  336. package/src/kit/reported-play-state.ts +90 -0
  337. package/src/kit/resolve-contributed-command.ts +14 -0
  338. package/src/kit/resolve-relative-specifier.ts +33 -0
  339. package/src/kit/retained-document-states.ts +91 -0
  340. package/src/kit/scene-document-plan.ts +320 -0
  341. package/src/kit/scene-live-open.ts +210 -0
  342. package/src/kit/scoped-game-css.ts +152 -0
  343. package/src/kit/served-url.ts +5 -0
  344. package/src/kit/session-close.ts +17 -0
  345. package/src/kit/session-tombstone.ts +127 -0
  346. package/src/kit/settings/settings-provider.ts +82 -0
  347. package/src/kit/settings-store.ts +348 -0
  348. package/src/kit/shell-document-state.ts +27 -0
  349. package/src/kit/shell-store-door.ts +45 -0
  350. package/src/kit/shell-store.ts +722 -0
  351. package/src/kit/source-conflict.ts +122 -0
  352. package/src/kit/stage-context.ts +377 -0
  353. package/src/kit/stage-invalidation.ts +25 -0
  354. package/src/kit/stage-store-registry.ts +69 -0
  355. package/src/kit/startup-failure.ts +80 -0
  356. package/src/kit/state-report-deferral.ts +73 -0
  357. package/src/kit/storage/host-files-storage.ts +97 -0
  358. package/src/kit/storage/http-storage.ts +174 -0
  359. package/src/kit/storage/index.ts +75 -0
  360. package/src/kit/storage/mem-storage.ts +158 -0
  361. package/src/kit/storage/path-lock.ts +44 -0
  362. package/src/kit/storage/paths.ts +26 -0
  363. package/src/kit/storage-types.ts +127 -0
  364. package/src/kit/stories/StoryPreviewMount.tsx +306 -0
  365. package/src/kit/stories/compose-project-stories.ts +255 -0
  366. package/src/kit/stories/prefabs-finder.ts +54 -0
  367. package/src/kit/stories/prefabs-from-stories.ts +182 -0
  368. package/src/kit/stories/project-story-regions.ts +24 -0
  369. package/src/kit/stories/story-capture.ts +579 -0
  370. package/src/kit/stories/story-declared-medium.ts +126 -0
  371. package/src/kit/stories/story-discovery.ts +176 -0
  372. package/src/kit/stories/story-dom-runtime.ts +78 -0
  373. package/src/kit/stories/story-grouping.ts +111 -0
  374. package/src/kit/stories/story-mount-turn.ts +27 -0
  375. package/src/kit/stories/story-presentation.ts +215 -0
  376. package/src/kit/stories/story-preview-component.ts +7 -0
  377. package/src/kit/stories/story-registry.ts +530 -0
  378. package/src/kit/stories-scope.ts +35 -0
  379. package/src/kit/story-document-openers.ts +36 -0
  380. package/src/kit/story-thumbnails.ts +47 -0
  381. package/src/kit/surface-keyboard.ts +101 -0
  382. package/src/kit/surface-state.ts +135 -0
  383. package/src/kit/system-seam-evidence.ts +72 -0
  384. package/src/kit/tab-census.ts +202 -0
  385. package/src/kit/tab-lifecycle-client.ts +227 -0
  386. package/src/kit/theme-library.ts +897 -0
  387. package/src/kit/theme-preference.ts +429 -0
  388. package/src/kit/three-viewport-presentation.ts +23 -0
  389. package/src/kit/tool-contribution-play.ts +74 -0
  390. package/src/kit/tool-loader.ts +1918 -0
  391. package/src/kit/transform-mode-request.ts +66 -0
  392. package/src/kit/transient-hint.ts +78 -0
  393. package/src/kit/transport-strip.tsx +174 -0
  394. package/src/kit/ui-source/adapter-region-includes.ts +238 -0
  395. package/src/kit/ui-source/file-region-resolver.ts +302 -0
  396. package/src/kit/ui-source/inspect.ts +775 -0
  397. package/src/kit/ui-source/source-write-backend.ts +605 -0
  398. package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
  399. package/src/kit/user-local-state.ts +105 -0
  400. package/src/kit/viewport-activation-timings.ts +840 -0
  401. package/src/kit/viewport-editor-controls.ts +22 -0
  402. package/src/kit/viewport-presentation.ts +668 -0
  403. package/src/kit/viewport-surface-status.tsx +55 -0
  404. package/src/kit/wait-until.ts +37 -0
  405. package/src/kit/worker-call-metrics.ts +166 -0
  406. package/src/kit/workspace-areas.ts +191 -0
  407. package/src/kit/workspace-aux-commands.ts +11 -0
  408. package/src/kit/workspace-available-documents.ts +142 -0
  409. package/src/kit/workspace-core-utilities.ts +31 -0
  410. package/src/kit/workspace-document-ids.ts +59 -0
  411. package/src/kit/workspace-document-registry.ts +624 -0
  412. package/src/kit/workspace-document-restore.ts +146 -0
  413. package/src/kit/workspace-host-commands.ts +141 -0
  414. package/src/kit/workspace-persistence-gate.ts +40 -0
  415. package/src/kit/workspace-play-utilities.ts +44 -0
  416. package/src/kit/workspace-presets.ts +446 -0
  417. package/src/kit/workspace-regions.ts +276 -0
  418. package/src/kit/workspace-static-panels.ts +73 -0
  419. package/src/kit/workspace-status-registry.ts +121 -0
  420. package/src/kit/workspace-storage.ts +35 -0
  421. package/src/kit/workspace-style.ts +226 -0
  422. package/src/kit/workspace-utility-commands.ts +74 -0
  423. package/src/kit/workspace-utility-registry.ts +263 -0
  424. package/src/kit/world-adoption-event.ts +23 -0
  425. package/src/kit/world-adoption.ts +115 -0
  426. package/src/kit/world-canvas-viewport-state.ts +35 -0
  427. package/src/kit/world-document-routing.ts +104 -0
  428. package/src/kit/world-pan-state.ts +198 -0
  429. package/src/kit/write-pipe.ts +173 -0
  430. package/src/layout-arrangements.ts +5 -0
  431. package/src/layouts.tsx +108 -0
  432. package/src/looks.ts +16 -0
  433. package/src/project/output-roots.ts +73 -0
  434. package/src/project/tab-census.ts +155 -0
  435. package/src/project-tool-catalog.ts +104 -0
  436. package/src/selection.tsx +107 -0
  437. package/src/services.ts +18 -0
  438. package/src/session/build-report.ts +22 -0
  439. package/src/session/collaboration-types.ts +262 -0
  440. package/src/session/command-table.ts +327 -0
  441. package/src/session/discovery.ts +100 -0
  442. package/src/session/editor-brand.ts +48 -0
  443. package/src/session/editor-compatibility.ts +329 -0
  444. package/src/session/editor-control-lifecycle.ts +68 -0
  445. package/src/session/editor-control-protocol.ts +5 -0
  446. package/src/session/entrypoint-selection-readers.ts +66 -0
  447. package/src/session/entrypoint-selection-source.ts +120 -0
  448. package/src/session/game-css-scope.ts +30 -0
  449. package/src/session/hosted-attachment.ts +225 -0
  450. package/src/session/limited-view.ts +82 -0
  451. package/src/session/product-create.ts +24 -0
  452. package/src/session/product-locator.ts +478 -0
  453. package/src/session/project-module-url.ts +242 -0
  454. package/src/session/project-serving.ts +164 -0
  455. package/src/session/project-upgrade.ts +669 -0
  456. package/src/session/registry-format.ts +210 -0
  457. package/src/session/relative-path-guard.ts +56 -0
  458. package/src/session/scoped-game-css.ts +461 -0
  459. package/src/session/source-glob.ts +15 -0
  460. package/src/session/tool-contribution-convention.ts +123 -0
  461. package/src/session/workbench-locator.ts +712 -0
  462. package/src/session.ts +41 -0
  463. package/src/share.ts +160 -0
  464. package/src/source-analysis.ts +28 -0
  465. package/src/source-authoring.ts +439 -0
  466. package/src/tools/errors.ts +91 -0
  467. package/src/tools/provider-execution.ts +70 -0
  468. package/src/tools/registry.ts +341 -0
  469. package/src/tools/types.ts +159 -0
  470. package/src/transport.ts +100 -0
  471. package/src/types.ts +1693 -0
  472. package/src/views.ts +164 -0
  473. package/src/widgets/design-system.ts +93 -0
  474. package/src/widgets/editor-appearance.ts +151 -0
  475. package/src/widgets/editor-material.ts +83 -0
  476. package/src/widgets/icon-set-registry.ts +105 -0
  477. package/src/widgets/index.ts +71 -0
  478. package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
  479. package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
  480. package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
  481. package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
  482. package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
  483. package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
  484. package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
  485. package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
  486. package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
  487. package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
  488. package/src/widgets/inspector-widgets/color-utils.ts +201 -0
  489. package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
  490. package/src/widgets/inspector-widgets/index.ts +25 -0
  491. package/src/widgets/inspector-widgets/shared.tsx +140 -0
  492. package/src/widgets/interactive-edit-scope.ts +33 -0
  493. package/src/widgets/patterns/Dialog.tsx +140 -0
  494. package/src/widgets/patterns/Fields.tsx +44 -0
  495. package/src/widgets/patterns/List.tsx +25 -0
  496. package/src/widgets/patterns/StateSurface.tsx +40 -0
  497. package/src/widgets/patterns/Surfaces.tsx +122 -0
  498. package/src/widgets/patterns/Tabs.tsx +80 -0
  499. package/src/widgets/patterns/Toolbar.tsx +72 -0
  500. package/src/widgets/patterns/Tree.tsx +72 -0
  501. package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
  502. package/src/widgets/primitives/Button.tsx +62 -0
  503. package/src/widgets/primitives/ColorInput.tsx +78 -0
  504. package/src/widgets/primitives/DraftTextInput.tsx +63 -0
  505. package/src/widgets/primitives/EditorIcon.tsx +157 -0
  506. package/src/widgets/primitives/FormControls.tsx +88 -0
  507. package/src/widgets/primitives/HoverPreview.tsx +96 -0
  508. package/src/widgets/primitives/JsonInput.tsx +113 -0
  509. package/src/widgets/primitives/Layout.tsx +100 -0
  510. package/src/widgets/primitives/Menu.tsx +161 -0
  511. package/src/widgets/primitives/NumberInput.tsx +169 -0
  512. package/src/widgets/primitives/Panel.tsx +80 -0
  513. package/src/widgets/primitives/SectionHeader.tsx +77 -0
  514. package/src/widgets/primitives/Text.tsx +54 -0
  515. package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
  516. package/src/widgets/primitives/Tooltip.tsx +204 -0
  517. package/src/widgets/primitives/Vec3Input.tsx +70 -0
  518. package/src/widgets/primitives/banner-tones.ts +32 -0
  519. package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
  520. package/src/widgets/primitives/editor-icons.ts +254 -0
  521. package/src/widgets/primitives/panel-header-styles.ts +42 -0
  522. package/src/widgets/theme.ts +2841 -0
  523. package/src/widgets/z-index.ts +25 -0
@@ -0,0 +1,220 @@
1
+ /**
2
+ * THE LIVE SESSIONS — what is running in this tab, registered by whoever
3
+ * mounts it (WORK.md §Play leaves the host, P1). The host never names Play,
4
+ * ingest or the module lane; it asks this registry "is anything live?",
5
+ * "is the editor playing?", "which element holds instance X?", and "stop
6
+ * everything" — the questions `editor-session-mode.ts`,
7
+ * `project-session-reset.ts`, `EditorLeaseGuard.tsx`,
8
+ * `RootSelectionOverlay.tsx` and `editor-view-presentation.ts` asked
9
+ * `play-mode.ts` by name until 2026-09-17. A package registers through
10
+ * `@volter/sdk/host`'s `live` member; the host's own lanes register
11
+ * here directly until they move.
12
+ */
13
+
14
+ import type {
15
+ LiveCommand,
16
+ LiveCommandResult,
17
+ LiveCoverageReport,
18
+ LiveRemountArgs,
19
+ LiveRunWindow,
20
+ LiveSceneTable,
21
+ LiveSession,
22
+ } from '@volter/sdk/host';
23
+
24
+ interface Registered {
25
+ readonly session: LiveSession;
26
+ readonly seq: number;
27
+ }
28
+ let registered: Registered[] = [];
29
+ let seq = 0;
30
+ let version = 0;
31
+ const listeners = new Set<() => void>();
32
+ function notify(): void {
33
+ version++;
34
+ for (const listener of listeners) listener();
35
+ }
36
+
37
+ /** A lane's own state moved (restart-required, its run window). */
38
+ export function notifyLiveSessionsChanged(): void {
39
+ notify();
40
+ }
41
+
42
+ /** Every registered lane, in `stop` order. */
43
+ export function liveSessions(): readonly LiveSession[] {
44
+ return ordered();
45
+ }
46
+
47
+ /** The newest run across lanes: the greatest `startedAt` any lane reports. */
48
+ export function liveRunWindow(): LiveRunWindow | null {
49
+ let newest: LiveRunWindow | null = null;
50
+ for (const { session } of registered) {
51
+ const startedAt = session.startedAt?.() ?? null;
52
+ if (startedAt === null) continue;
53
+ if (!newest || startedAt > newest.startedAt)
54
+ newest = { startedAt, endedAt: session.endedAt?.() ?? null };
55
+ }
56
+ return newest;
57
+ }
58
+
59
+ export function liveRestartRequired(): string | null {
60
+ for (const { session } of registered) {
61
+ const reason = session.restartRequired?.() ?? null;
62
+ if (reason !== null) return reason;
63
+ }
64
+ return null;
65
+ }
66
+
67
+ /** Re-enter the lane that reports a restart is required, else the first
68
+ * running lane that can restart. */
69
+ export function restartLiveSession(): void {
70
+ const stale = ordered().find((session) => (session.restartRequired?.() ?? null) !== null);
71
+ const target = stale ?? ordered().find((session) => session.mounted() && session.restart);
72
+ target?.restart?.();
73
+ }
74
+
75
+ /** The canvas a mounted lane's own render pass draws, or null. */
76
+ export function liveFrameCanvas(): HTMLCanvasElement | null {
77
+ for (const session of ordered()) {
78
+ if (!session.mounted()) continue;
79
+ const canvas = session.frameCanvas?.() ?? null;
80
+ if (canvas) return canvas;
81
+ }
82
+ return null;
83
+ }
84
+
85
+ /** The pixels of `canvas` from the lane whose render pass owns it; null when
86
+ * no mounted lane claims that canvas. */
87
+ export function snapshotLiveFrame(
88
+ canvas: HTMLCanvasElement,
89
+ ): Promise<CanvasImageSource | null> | null {
90
+ for (const session of ordered()) {
91
+ if (!session.mounted() || !session.snapshotFrame) continue;
92
+ if (session.frameCanvas?.() === canvas) return session.snapshotFrame();
93
+ }
94
+ return null;
95
+ }
96
+
97
+ /** The first mounted lane's own answer to `cmd`, or null when none claims it. */
98
+ export function dispatchLiveCommand(cmd: LiveCommand): LiveCommandResult | null {
99
+ for (const session of ordered()) {
100
+ if (!session.mounted() || !session.command) continue;
101
+ const answered = session.command(cmd);
102
+ if (answered) return answered;
103
+ }
104
+ return null;
105
+ }
106
+
107
+ /**
108
+ * The running lane's scene entries, or null.
109
+ *
110
+ * The shape check is STRUCTURAL and stays here rather than importing a lane's
111
+ * own type guard (it imported the ingest lane's `isContractScenesStories`,
112
+ * by name, until 2026-09-18, and with it the whole `window.volterGame` contract
113
+ * — an INGEST vocabulary inside the registry every lane registers through).
114
+ * `LiveSceneTable` is a declaration, and a lane is foreign code: the
115
+ * host checks that the declaration is honoured before handing the table to the
116
+ * `open` verb, and names no lane doing it.
117
+ */
118
+ export function liveScenes(): LiveSceneTable | null {
119
+ for (const session of ordered()) {
120
+ if (!session.mounted()) continue;
121
+ const scenes = session.scenes?.() ?? null;
122
+ if (scenes && typeof scenes.goToScene === 'function') return scenes;
123
+ }
124
+ return null;
125
+ }
126
+
127
+ /** The native surface the mounted lane's content draws on, or null. */
128
+ export function liveSurface(): 'three' | 'canvas' | 'dom' | null {
129
+ for (const session of ordered()) {
130
+ if (!session.mounted()) continue;
131
+ const surface = session.surface?.() ?? null;
132
+ if (surface) return surface;
133
+ }
134
+ return null;
135
+ }
136
+
137
+ /** The mounted lane's own coverage report, or null when none grades itself. */
138
+ export function liveCoverage(): LiveCoverageReport | null {
139
+ for (const session of ordered()) {
140
+ if (!session.mounted()) continue;
141
+ const report = session.coverage?.() ?? null;
142
+ if (report) return report;
143
+ }
144
+ return null;
145
+ }
146
+
147
+ /** Why authoring is off for the mounted lane's content, or null. */
148
+ export function liveAuthoringRefusal(): string | null {
149
+ for (const session of ordered()) {
150
+ if (!session.mounted()) continue;
151
+ const reason = session.authoringRefusal?.() ?? null;
152
+ if (reason !== null) return reason;
153
+ }
154
+ return null;
155
+ }
156
+
157
+ /** Ask the running lane to re-mount with an authored selection; null when
158
+ * no running lane can. */
159
+ export function remountLiveSelection(
160
+ args: LiveRemountArgs,
161
+ ): Promise<{ ok: true } | { ok: false; error: string }> | null {
162
+ const target = ordered().find((session) => session.mounted() && session.remount);
163
+ return target?.remount?.(args) ?? null;
164
+ }
165
+
166
+ /** Register a lane. `stop` order follows `priority` (low first), then
167
+ * registration: a normal stop tears down Play before ingest. */
168
+ export function registerLiveSession(session: LiveSession): () => void {
169
+ if (registered.some((entry) => entry.session.id === session.id))
170
+ throw new Error(`live session "${session.id}" is already registered.`);
171
+ const entry: Registered = { session, seq: seq++ };
172
+ registered = [...registered, entry];
173
+ notify();
174
+ return () => {
175
+ registered = registered.filter((other) => other !== entry);
176
+ notify();
177
+ };
178
+ }
179
+
180
+ function ordered(): readonly LiveSession[] {
181
+ return [...registered]
182
+ .sort((a, b) => (a.session.priority ?? 0) - (b.session.priority ?? 0) || a.seq - b.seq)
183
+ .map((entry) => entry.session);
184
+ }
185
+
186
+ /** A real game owns a canvas: Play, an ingested game, an auto-mounted module world. */
187
+ export function anyLiveSessionMounted(): boolean {
188
+ return ordered().some((session) => session.mounted());
189
+ }
190
+
191
+ /** The editor is in PLAY: somebody asked the host to run content. A held
192
+ * (paused-at-design-time) mount is not playing. */
193
+ export function anyLiveSessionPlaying(): boolean {
194
+ return ordered().some((session) => session.playing());
195
+ }
196
+
197
+ /** Stop every lane, in priority order; each stop is idempotent and a no-op
198
+ * when its lane runs nothing. */
199
+ export function stopAllLiveSessions(): void {
200
+ for (const session of ordered()) session.stop();
201
+ }
202
+
203
+ /** The element holding a live instance — the primary when `id` is omitted —
204
+ * from whichever lane holds it. */
205
+ export function liveInstanceContainer(id?: string): HTMLElement | null {
206
+ for (const session of ordered()) {
207
+ const container = session.instanceContainer(id);
208
+ if (container) return container;
209
+ }
210
+ return null;
211
+ }
212
+
213
+ export function subscribeLiveSessions(listener: () => void): () => void {
214
+ listeners.add(listener);
215
+ return () => listeners.delete(listener);
216
+ }
217
+
218
+ export function liveSessionsVersion(): number {
219
+ return version;
220
+ }
@@ -0,0 +1,391 @@
1
+ /**
2
+ * THE LIVE TRANSITION — the immersive Liquid Glass hand-off between
3
+ * authoring chrome and the running game, the host's side of
4
+ * `host.viewport.transition` (WORK.md §Play leaves the host, P3). A lane
5
+ * says when it starts (`beginLiveTransition`), when it is ready and when it
6
+ * ends; the host decides whether the presentation is immersive and resolves
7
+ * the flight target from the authored scene.
8
+ *
9
+ * On Play: the chrome dissolves, the editor viewport camera flies along a
10
+ * Catmull-Rom spline from the preview pose to the AUTHORED game camera's
11
+ * pose, and when both the flight has landed and the game runtime is ready the
12
+ * Scene document cross-fades into the Game document. On Stop everything
13
+ * reverses: camera snaps back to the pre-play preview pose and the chrome
14
+ * re-materializes. `prefers-reduced-motion` collapses the whole choreography
15
+ * to instant state changes with the same end state.
16
+ *
17
+ * Layering: this module owns TIMING, and it touches no layout at all. The
18
+ * camera flight is the Three integration's (`@volter/sdk/kit/play-camera-flight`,
19
+ * registered by `@volter/editor-threejs`'s `play-camera-flight.ts`). The LAYOUT HOST registers `hideChrome`/`showChrome` through
20
+ * {@link installPlayTransitionDock} — under the Code-OSS frame those are the
21
+ * workbench's own parts going away and coming back (`frame/bridge.tsx`'s
22
+ * `setImmersive`), which is the same inversion `workspace-host-commands.ts`
23
+ * uses for semantic commands. Workspace persistence is suppressed for the
24
+ * whole immersive play session (`setWorkspacePersistenceSuppressed`) so a
25
+ * play-time open set can never overwrite the user's own. A non-immersive play
26
+ * never enters this controller: it keeps the ordinary workspace visible.
27
+ *
28
+ * The pure parts — the durations, the phase reducer — are plain functions
29
+ * with no DOM.
30
+ */
31
+
32
+ import { layoutPolicy } from './layout-policy';
33
+ import { effectiveSettings } from '@volter/sdk/kit/settings-store';
34
+ import { type LiveCameraLookup, playCameraFlight } from '@volter/sdk/kit/play-camera-flight';
35
+ import { setWorkspacePersistenceSuppressed } from './workspace-persistence-gate';
36
+
37
+ /** Full-bleed play is the MOUNTED LAYOUT's own declaration
38
+ * (`WorkspaceLayoutPolicy.immersivePlay` — `GameLayout` is the shipped
39
+ * instance); no appearance axis implies it. */
40
+ export function usesImmersivePlayPresentation(): boolean {
41
+ return (layoutPolicy()?.immersivePlay ?? false) && !effectiveSettings().play?.keepPanelsVisible;
42
+ }
43
+
44
+
45
+
46
+
47
+
48
+ // ---------------------------------------------------------------------------
49
+ // Pure transition phase reducer
50
+ // ---------------------------------------------------------------------------
51
+
52
+ export type PlayTransitionPhase =
53
+ | 'idle'
54
+ /** Dissolve + flight running concurrently. */
55
+ | 'entering'
56
+ /** Flight landed but the game runtime is still booting — hold the pose. */
57
+ | 'holding'
58
+ /** Both done — Scene → Game opacity cross-fade in progress. */
59
+ | 'crossfade'
60
+ /** Hand-off complete; game owns the screen until stop. */
61
+ | 'playing';
62
+
63
+ export type PlayTransitionEvent =
64
+ | 'start'
65
+ | 'start-reduced'
66
+ | 'flight-done'
67
+ | 'game-ready'
68
+ | 'crossfade-done'
69
+ | 'stop';
70
+
71
+ export interface PlayTransitionState {
72
+ readonly phase: PlayTransitionPhase;
73
+ readonly flightDone: boolean;
74
+ readonly gameReady: boolean;
75
+ }
76
+
77
+ export const IDLE_TRANSITION_STATE: PlayTransitionState = {
78
+ phase: 'idle',
79
+ flightDone: false,
80
+ gameReady: false,
81
+ };
82
+
83
+ function reduceEnteringPhase(
84
+ state: PlayTransitionState,
85
+ event: PlayTransitionEvent,
86
+ ): PlayTransitionState {
87
+ const flightDone = state.flightDone || event === 'flight-done';
88
+ const gameReady = state.gameReady || event === 'game-ready';
89
+ if (flightDone && gameReady) return { phase: 'crossfade', flightDone, gameReady };
90
+ if (flightDone) return { phase: 'holding', flightDone, gameReady };
91
+ return { ...state, flightDone, gameReady };
92
+ }
93
+
94
+ /** Pure phase reducer — every timing side effect lives in the controller. */
95
+ export function reducePlayTransition(
96
+ state: PlayTransitionState,
97
+ event: PlayTransitionEvent,
98
+ ): PlayTransitionState {
99
+ if (event === 'stop') return IDLE_TRANSITION_STATE;
100
+ switch (state.phase) {
101
+ case 'idle':
102
+ if (event === 'start') return { phase: 'entering', flightDone: false, gameReady: false };
103
+ if (event === 'start-reduced') return { phase: 'playing', flightDone: true, gameReady: true };
104
+ return state;
105
+ case 'entering':
106
+ return reduceEnteringPhase(state, event);
107
+ case 'holding':
108
+ if (event === 'game-ready') return { ...state, phase: 'crossfade', gameReady: true };
109
+ return state;
110
+ case 'crossfade':
111
+ if (event === 'crossfade-done') return { ...state, phase: 'playing' };
112
+ return state;
113
+ case 'playing':
114
+ return state;
115
+ }
116
+ }
117
+
118
+ // ---------------------------------------------------------------------------
119
+ // Pure edge-reveal machine (macOS auto-hide semantics)
120
+ //
121
+ // GLOBAL reveal (owner decision, 2026-07-20): dwelling at ANY screen edge
122
+ // reveals ALL the play chrome together — header, hierarchy, inspector,
123
+ // assets, bottom bar — and it all retracts together once the pointer leaves
124
+ // both the hot zones and every revealed surface. Per-edge independent
125
+ // reveals (the original design) made the chrome feel unpredictable and
126
+ // forced users to hunt each panel at its own edge.
127
+ // ---------------------------------------------------------------------------
128
+
129
+ // ---------------------------------------------------------------------------
130
+ // Controller — DOM / viewport integration seams
131
+ // ---------------------------------------------------------------------------
132
+
133
+ /**
134
+ * THE TRANSITION'S DURATIONS, owned here and read by the stylesheet.
135
+ *
136
+ * Every one of these is a JS timer AND a CSS animation: the phase machine
137
+ * schedules the next step off the constant while `workspace-surfaces.css`
138
+ * animates the pixels, so a mismatch is not a cosmetic drift — it advances the machine
139
+ * before the frames land (a half-dissolved chrome snapped away mid-fade) or
140
+ * holds it after they do. They used to be typed twice, with three comments here
141
+ * saying "must match the CSS", which is a hand-maintained equality across two
142
+ * files and no checker.
143
+ *
144
+ * They are published as custom properties by
145
+ * {@link publishPlayTransitionDurations}, from {@link installPlayTransitionDock}
146
+ * — which is also what makes an unpublished property unreachable rather than a
147
+ * silent failure: nothing ever adds `volter-play-chrome-exit`,
148
+ * `volter-play-chrome-enter` or `volter-play-crossfade` except this module, and
149
+ * this module cannot act before the host is installed.
150
+ */
151
+
152
+ /** Chrome dissolve. CSS: `--volter-play-dissolve-duration`. */
153
+ export const PLAY_DISSOLVE_MS = 450;
154
+ /** Fast, unstaggered re-materialization after a reveal request. CSS:
155
+ * `--volter-play-materialize-duration`. */
156
+ export const PLAY_MATERIALIZE_MS = 220;
157
+ /** Per-element stagger step, published as `--volter-play-stagger`. */
158
+ export const PLAY_DISSOLVE_STAGGER_MS = 50;
159
+ /** Scene→Game opacity cross-fade. CSS: `--volter-play-crossfade-duration`. */
160
+ export const PLAY_CROSSFADE_MS = 250;
161
+
162
+ /**
163
+ * Hand the three durations above to the stylesheet. On the document element,
164
+ * so they inherit everywhere the play classes can land — a host may park a
165
+ * surface in a top-level overlay outside the root it handed us.
166
+ */
167
+ function publishPlayTransitionDurations(root: HTMLElement): void {
168
+ root.style.setProperty('--volter-play-dissolve-duration', `${PLAY_DISSOLVE_MS}ms`);
169
+ root.style.setProperty('--volter-play-materialize-duration', `${PLAY_MATERIALIZE_MS}ms`);
170
+ root.style.setProperty('--volter-play-crossfade-duration', `${PLAY_CROSSFADE_MS}ms`);
171
+ }
172
+
173
+ /** What the LAYOUT HOST registers: chrome hide/show plus the root element the
174
+ * flight/cross-fade CSS classes land on. Whatever draws the chrome stays
175
+ * behind this seam — under the frame it is the workbench's own parts. */
176
+ export interface PlayTransitionDockHooks {
177
+ root: HTMLElement;
178
+ hideChrome(animate: boolean): void;
179
+ showChrome(animate: boolean): void;
180
+ }
181
+
182
+ /** The narrow viewport surface the flight needs (the world root's stage registers the
183
+ * real EditorViewport; unit tests pass a fake). */
184
+
185
+
186
+ let _dock: PlayTransitionDockHooks | null = null;
187
+
188
+ export function installPlayTransitionDock(hooks: PlayTransitionDockHooks): () => void {
189
+ _dock = hooks;
190
+ if (typeof document !== 'undefined') publishPlayTransitionDurations(document.documentElement);
191
+ return () => {
192
+ if (_dock === hooks) _dock = null;
193
+ };
194
+ }
195
+
196
+ export function prefersReducedMotion(): boolean {
197
+ return (
198
+ typeof window !== 'undefined' &&
199
+ (window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false)
200
+ );
201
+ }
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+ interface ActiveTransition {
210
+ state: PlayTransitionState;
211
+ reducedMotion: boolean;
212
+ /** The viewport is flying (`kit/play-camera-flight`): a viewport and an authored camera existed. */
213
+ flying: boolean;
214
+ timeouts: Set<ReturnType<typeof setTimeout>>;
215
+ }
216
+
217
+ let _active: ActiveTransition | null = null;
218
+
219
+ /** Current phase (exported for tests/e2e via the debug handle below). */
220
+ export function playTransitionPhase(): PlayTransitionPhase {
221
+ return _active?.state.phase ?? 'idle';
222
+ }
223
+
224
+ // --- Settle listeners --------------------------------------------------------
225
+
226
+ const _settleListeners = new Set<() => void>();
227
+
228
+ function flushSettleListeners(): void {
229
+ if (_settleListeners.size === 0) return;
230
+ const fns = [..._settleListeners];
231
+ _settleListeners.clear();
232
+ for (const fn of fns) fn();
233
+ }
234
+
235
+ /**
236
+ * Run `fn` once the play-entry transition SETTLES — the cross-fade completed
237
+ * (phase 'playing') or the transition tore down early (Stop/Escape/boot
238
+ * failure) — or immediately when no transition is in flight. One-shot.
239
+ *
240
+ * This is the hand-off point for work that must NOT happen while the flight
241
+ * still renders the editor viewport: the R3F design session keeps its adopted
242
+ * fiber scene alive under the flight (suspending at the playState flip made
243
+ * the whole screen flash the placeholder scene's clear color) and suspends
244
+ * here instead. Settle can mean "play never happened" as well as "play is
245
+ * fully on screen" — callbacks must re-check store state.
246
+ */
247
+ export function onPlayTransitionSettled(fn: () => void): void {
248
+ if (!_active || _active.state.phase === 'playing') {
249
+ fn();
250
+ return;
251
+ }
252
+ _settleListeners.add(fn);
253
+ }
254
+
255
+ function later(active: ActiveTransition, ms: number, fn: () => void): void {
256
+ const handle = setTimeout(() => {
257
+ active.timeouts.delete(handle);
258
+ fn();
259
+ }, ms);
260
+ active.timeouts.add(handle);
261
+ }
262
+
263
+
264
+ function dispatch(event: PlayTransitionEvent): void {
265
+ const active = _active;
266
+ if (!active) return;
267
+ const prev = active.state;
268
+ const next = reducePlayTransition(prev, event);
269
+ if (next === prev) return;
270
+ active.state = next;
271
+ if (next.phase === 'crossfade' && prev.phase !== 'crossfade') {
272
+ _dock?.root.classList.add('volter-play-crossfade');
273
+ later(active, PLAY_CROSSFADE_MS + 30, () => dispatch('crossfade-done'));
274
+ }
275
+ if (next.phase === 'playing' && prev.phase !== 'playing') {
276
+ _dock?.root.classList.remove('volter-play-flight', 'volter-play-crossfade');
277
+ if (active.flying) playCameraFlight()?.settle();
278
+ flushSettleListeners();
279
+ }
280
+ }
281
+
282
+
283
+ /**
284
+ * Begin the play-entry transition. Called by `play-mode.ts` immediately
285
+ * before `setPlayState('playing')`. Never blocks play — all choreography is
286
+ * fire-and-forget alongside the runtime boot. Safe no-op degradation when no
287
+ * dock/viewport is registered (headless unit-test stores).
288
+ */
289
+ export interface PlayEntryTransitionOptions {
290
+ readonly immersive: boolean;
291
+ }
292
+
293
+ /**
294
+ * A lane is starting: call BEFORE the session flips to playing. The mounted
295
+ * layout chooses immersive Play; when
296
+ * immersive, the authored camera MUST be resolved here, before playState
297
+ * changes — the R3F design session then suspends and removes its drei camera
298
+ * from the store. Every exit path funnels through `endPlayTransition`.
299
+ */
300
+ export function beginLiveTransition(): void {
301
+ beginPlayEntryTransition({ immersive: usesImmersivePlayPresentation() });
302
+ }
303
+
304
+ export function beginPlayEntryTransition(options: PlayEntryTransitionOptions): void {
305
+ if (_active) endPlayTransition();
306
+ // Non-immersive play has no transition state, persistence gate, camera
307
+ // flight, or chrome mutation at all.
308
+ if (!options.immersive) return;
309
+ const reducedMotion = prefersReducedMotion();
310
+ setWorkspacePersistenceSuppressed(true);
311
+ const active: ActiveTransition = {
312
+ state: IDLE_TRANSITION_STATE,
313
+ reducedMotion,
314
+ flying: false,
315
+ timeouts: new Set(),
316
+ };
317
+ _active = active;
318
+ _dock?.hideChrome(!reducedMotion);
319
+
320
+ if (reducedMotion) {
321
+ dispatch('start-reduced');
322
+ return;
323
+ }
324
+ dispatch('start');
325
+
326
+ // The flight resolves the authored camera NOW, before playState changes (the R3F design
327
+ // session then suspends and removes its drei camera from the store).
328
+ active.flying = playCameraFlight()?.begin(() => { if (_active === active) dispatch('flight-done'); }) ?? false;
329
+ if (!active.flying) {
330
+ // No authored camera (or headless): dissolve still runs, no flight.
331
+ dispatch('flight-done');
332
+ return;
333
+ }
334
+ _dock?.root.classList.add('volter-play-flight');
335
+ }
336
+
337
+ /**
338
+ * Reconcile an already-running session with appearance-axis changes. Moving
339
+ * away from an immersive presentation must restore the chrome immediately;
340
+ * moving into one mid-session deliberately does not replay entry
341
+ * choreography.
342
+ */
343
+ export function reconcilePlayPresentationPolicy(isPlaying: boolean, immersive: boolean): void {
344
+ if (!isPlaying || !immersive) endPlayTransition();
345
+ }
346
+
347
+ /**
348
+ * The game runtime finished its async boot (play-mode's ack point).
349
+ * `getLiveCamera` gives the flight its final convergence target — the game's
350
+ * actual render camera — so the cross-fade is pixel-continuous even when game
351
+ * code repositions the camera during boot.
352
+ */
353
+ export function notifyPlayTransitionGameReady(getLiveCamera?: LiveCameraLookup): void {
354
+ const active = _active;
355
+ if (!active) return;
356
+ if (active.flying && getLiveCamera) playCameraFlight()?.track(getLiveCamera);
357
+ dispatch('game-ready');
358
+ }
359
+
360
+
361
+
362
+
363
+ /**
364
+ * Tear the transition down (Stop/Escape/boot failure — any exit path).
365
+ * Restores the pre-play camera pose, re-materializes the chrome, and
366
+ * re-enables layout persistence. Idempotent.
367
+ */
368
+ export function endPlayTransition(): void {
369
+ const active = _active;
370
+ if (!active) return;
371
+ _active = null;
372
+ for (const handle of active.timeouts) clearTimeout(handle);
373
+ active.timeouts.clear();
374
+ // Early teardown is also "settled" — deferred hand-off work (see
375
+ // onPlayTransitionSettled) must run, and its store-state guards decide
376
+ // whether there is anything left to do.
377
+ flushSettleListeners();
378
+ _dock?.root.classList.remove('volter-play-flight', 'volter-play-crossfade');
379
+
380
+ if (active.flying) playCameraFlight()?.end();
381
+
382
+ _dock?.showChrome(!prefersReducedMotion());
383
+ setWorkspacePersistenceSuppressed(false);
384
+ }
385
+
386
+ // Dev/e2e handle: lets specs observe the transition phase deterministically.
387
+ if (typeof window !== 'undefined' && (import.meta as ImportMeta & { env?: { DEV?: boolean } }).env?.DEV) {
388
+ (window as unknown as Record<string, unknown>)['__volterPlayTransition'] = {
389
+ phase: playTransitionPhase,
390
+ };
391
+ }