@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,115 @@
1
+ /**
2
+ * WORLD-ADOPTION AMBIGUITY — the reader for what the capture trap decided, and
3
+ * for every world it saw afterwards and did not adopt.
4
+ *
5
+ * `@volter/editor-threejs/adapter/ingest/scene-capture` adopts a self-booting game's world on
6
+ * the first non-host render. That is a sound MEASURED default and a permanent,
7
+ * silent commitment: a splash scene, a shadow pre-pass or a render-to-texture
8
+ * warm-up that happens to draw first is adopted as the game forever, and the
9
+ * real world drawing one frame later reached nobody.
10
+ *
11
+ * This module does not change the decision (ARCHITECTURE-CORE §The editor
12
+ * protocol: a diagnostic diagnoses; it does not silently re-pick). It records
13
+ * the adoption's PROVENANCE — `declared` when the game's contract named the
14
+ * scene, `measured` when first-render-wins ran — and every distinct
15
+ * (scene, camera) pair seen after it, and publishes both as the `worldAdoption`
16
+ * facet of `/__editor/state`.
17
+ *
18
+ * Alternates are INFORMATION, not an error: a post-processing chain renders
19
+ * several pairs per frame by design. The facet says how many and which, and the
20
+ * `ambiguity` sentence exists so a reader chasing "the editor is showing the
21
+ * wrong scene" has one place that already knows there was a choice.
22
+ */
23
+
24
+ import type { WorldAdoptionEvent } from '@volter/sdk/kit/world-adoption-event';
25
+
26
+ export interface WorldAdoptionAlternate {
27
+ readonly sceneId: string;
28
+ readonly cameraId: string;
29
+ /** `false` ⇒ a SECOND renderer is drawing — the stronger signal that the
30
+ * adopted world may not be the one on screen. */
31
+ readonly sameRenderer: boolean;
32
+ readonly drawCount: number;
33
+ }
34
+
35
+ export interface WorldAdoption {
36
+ readonly rootId: string;
37
+ /** `declared` = the game's contract named this scene; `measured` = the trap's
38
+ * first-non-host-render default decided. */
39
+ readonly source: 'declared' | 'measured';
40
+ readonly sceneId: string;
41
+ readonly cameraId: string;
42
+ /** Distinct worlds seen AFTER the adopted one, capped by the trap's own
43
+ * `MAX_RECORDED_ALTERNATES`. */
44
+ readonly alternates: readonly WorldAdoptionAlternate[];
45
+ /** Present iff `alternates` is non-empty — the one sentence, spelled once. */
46
+ readonly ambiguity?: string;
47
+ }
48
+
49
+ /** RESOURCE OWNERSHIP: one entry per self-booting root, written through
50
+ * {@link worldAdoptionRecorder} by the mount that installed the capture trap,
51
+ * and dropped by that mount's teardown ({@link clearWorldAdoption}). */
52
+ const _adoptions = new Map<
53
+ string,
54
+ {
55
+ source: 'declared' | 'measured';
56
+ sceneId: string;
57
+ cameraId: string;
58
+ alternates: WorldAdoptionAlternate[];
59
+ }
60
+ >();
61
+
62
+ /**
63
+ * The `onWorldAdoption` handler a mount hands to `installSceneCapture`, bound
64
+ * to one root id. One door: the mount passes this straight through, so nothing
65
+ * in the editor transcribes the engine's event shape a second time.
66
+ */
67
+ export function worldAdoptionRecorder(rootId: string): (event: WorldAdoptionEvent) => void {
68
+ return (event) => {
69
+ if (event.phase === 'adopted') {
70
+ _adoptions.set(rootId, {
71
+ source: event.source,
72
+ sceneId: event.sceneId,
73
+ cameraId: event.cameraId,
74
+ alternates: [],
75
+ });
76
+ return;
77
+ }
78
+ // An alternate before an adoption cannot happen (the trap only reports one
79
+ // after it has committed), so a missing entry here means this root's
80
+ // adoption was already torn down — drop it rather than resurrect the root.
81
+ const entry = _adoptions.get(rootId);
82
+ if (!entry) return;
83
+ entry.alternates.push({
84
+ sceneId: event.sceneId,
85
+ cameraId: event.cameraId,
86
+ sameRenderer: event.sameRenderer,
87
+ drawCount: event.drawCount,
88
+ });
89
+ };
90
+ }
91
+
92
+ export function clearWorldAdoption(rootId: string): void {
93
+ _adoptions.delete(rootId);
94
+ }
95
+
96
+ export function worldAdoptionFacet(): readonly WorldAdoption[] {
97
+ return [..._adoptions].map(([rootId, entry]) => ({
98
+ rootId,
99
+ source: entry.source,
100
+ sceneId: entry.sceneId,
101
+ cameraId: entry.cameraId,
102
+ alternates: [...entry.alternates],
103
+ ...(entry.alternates.length > 0
104
+ ? {
105
+ ambiguity:
106
+ `"${rootId}" rendered ${entry.alternates.length} other world(s) after the one the ` +
107
+ `editor adopted (${entry.source}: ${entry.sceneId}). The adopted world is unchanged; ` +
108
+ 'if the editor is showing the wrong scene, one of these is it: ' +
109
+ entry.alternates
110
+ .map((alt) => `${alt.sceneId}${alt.sameRenderer ? '' : ' (a SECOND renderer)'}`)
111
+ .join(', '),
112
+ }
113
+ : {}),
114
+ }));
115
+ }
@@ -0,0 +1,35 @@
1
+ /** Session-only responsive canvas size for DOM-backed authoring roots. */
2
+ export interface RootCanvasViewport {
3
+ readonly width: number | null;
4
+ readonly height: number | null;
5
+ }
6
+
7
+ const FILL_VIEWPORT: RootCanvasViewport = { width: null, height: null };
8
+ let viewport: RootCanvasViewport = FILL_VIEWPORT;
9
+ const listeners = new Set<() => void>();
10
+
11
+ export function getRootCanvasViewport(): RootCanvasViewport {
12
+ return viewport;
13
+ }
14
+
15
+ export function setRootCanvasViewport(width: number | null, height: number | null): void {
16
+ const nextWidth = width === null ? null : Math.max(1, Math.round(width));
17
+ const nextHeight = height === null ? null : Math.max(1, Math.round(height));
18
+ if (viewport.width === nextWidth && viewport.height === nextHeight) return;
19
+ viewport = { width: nextWidth, height: nextHeight };
20
+ for (const listener of listeners) listener();
21
+ }
22
+
23
+ export function resetRootCanvasViewport(): void {
24
+ setRootCanvasViewport(null, null);
25
+ }
26
+
27
+ export function subscribeRootCanvasViewport(listener: () => void): () => void {
28
+ listeners.add(listener);
29
+ return () => listeners.delete(listener);
30
+ }
31
+
32
+ export function _resetRootCanvasViewportForTest(): void {
33
+ viewport = FILL_VIEWPORT;
34
+ listeners.clear();
35
+ }
@@ -0,0 +1,104 @@
1
+ import {
2
+ availableWorkspaceDocuments,
3
+ openAvailableWorkspaceDocument,
4
+ } from '@volter/sdk/kit/workspace-available-documents';
5
+ import { activateWorkspaceDocument } from '@volter/sdk/kit/workspace-document-registry';
6
+
7
+ const _documentIdByRoot = new Map<string, string>();
8
+
9
+ export function registerRootDocumentRoute(worldId: string, documentId: string): () => void {
10
+ _documentIdByRoot.set(worldId, documentId);
11
+ return () => {
12
+ if (_documentIdByRoot.get(worldId) === documentId) _documentIdByRoot.delete(worldId);
13
+ };
14
+ }
15
+
16
+ /** The edit-time document that owns a manifest world, or `null` when the
17
+ * session installed none. Read by the Edit tab row, whose `root-mount` scene
18
+ * entries NAME a standing document rather than adding one
19
+ * (`components/scene-documents.tsx`). */
20
+ export function rootDocumentId(worldId: string): string | null {
21
+ return (
22
+ _documentIdByRoot.get(worldId) ??
23
+ availableWorkspaceDocuments().find((document) => document.rootId === worldId)?.descriptor.id ??
24
+ null
25
+ );
26
+ }
27
+
28
+ /** Activate the edit-time document that owns a manifest world. */
29
+ export function activateRootDocument(worldId: string): boolean {
30
+ const documentId = rootDocumentId(worldId);
31
+ return documentId
32
+ ? openAvailableWorkspaceDocument(documentId) || activateWorkspaceDocument(documentId)
33
+ : false;
34
+ }
35
+
36
+ const _gapByRoot = new Map<string, () => string | null>();
37
+
38
+ /**
39
+ * Register the reason a root has NO document to activate — the DECIDED half of
40
+ * {@link activateRootDocument}'s `false`.
41
+ *
42
+ * A root's document is installed asynchronously, so `false` from
43
+ * `activateRootDocument` means one of two opposite things: "not yet" (boot in
44
+ * flight) or "never" (this session has settled that this root has no design
45
+ * surface of its own). Callers cannot tell them apart, so every caller waits
46
+ * out the full registration window even for an answer that was decided in the
47
+ * first second — long enough that the asking side has usually given up before
48
+ * the refusal is spoken.
49
+ *
50
+ * The `reason` is a THUNK, evaluated live at each ask, precisely so it can keep
51
+ * answering `null` while the document may still arrive and only speak once the
52
+ * question is settled. It is registered by whoever OWNS the decision — the
53
+ * presenter must never infer why a document is absent.
54
+ */
55
+ export function registerRootDocumentGap(worldId: string, reason: () => string | null): () => void {
56
+ _gapByRoot.set(worldId, reason);
57
+ return () => {
58
+ if (_gapByRoot.get(worldId) === reason) _gapByRoot.delete(worldId);
59
+ };
60
+ }
61
+
62
+ /** Why this root has no document to activate, when that is decided; `null`
63
+ * while one may still arrive. */
64
+ export function rootDocumentGap(worldId: string): string | null {
65
+ return _gapByRoot.get(worldId)?.() ?? null;
66
+ }
67
+
68
+ const _workspaceGaps = new Set<(documentId: string) => string | null>();
69
+
70
+ /**
71
+ * The same DECIDED half, for a workspace document asked for by id.
72
+ *
73
+ * `activateWorkspaceDocument` returns `false` with the identical ambiguity
74
+ * {@link registerRootDocumentGap} describes — "not yet" and "never" are one
75
+ * answer — and a workspace document has the further case a root cannot have:
76
+ * the id may name nothing at all. Both are the same question ("why is this
77
+ * document not here?"), so they share this mechanism rather than growing a
78
+ * second one; the arms differ only in their KEY, because a root is asked for
79
+ * by manifest id and a workspace document by document id.
80
+ *
81
+ * The resolver takes the requested id rather than being registered per id,
82
+ * because the ids that will never exist cannot be enumerated in advance — the
83
+ * owner answers for the whole namespace it installs into. Same thunk contract:
84
+ * `null` means "no verdict" (boot in flight, or not this owner's question),
85
+ * and the first owner to speak wins.
86
+ */
87
+ export function registerWorkspaceDocumentGap(
88
+ reason: (documentId: string) => string | null,
89
+ ): () => void {
90
+ _workspaceGaps.add(reason);
91
+ return () => {
92
+ _workspaceGaps.delete(reason);
93
+ };
94
+ }
95
+
96
+ /** Why this workspace document is not here, when that is decided; `null` while
97
+ * one may still arrive. */
98
+ export function workspaceDocumentGap(documentId: string): string | null {
99
+ for (const reason of _workspaceGaps) {
100
+ const answer = reason(documentId);
101
+ if (answer !== null) return answer;
102
+ }
103
+ return null;
104
+ }
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Shared DOM-world canvas transform (spec27 §8 "space-pan" row, D4 rebuild) — a
3
+ * module-level subscribable singleton (mirrors `eyedropper-session.ts`'s "bare
4
+ * singleton + own listener set" shape) holding the CURRENT SHARED pan + zoom
5
+ * applied, in LOCKSTEP, to both every design-time world-layer host
6
+ * (`design-time-layers.ts`'s `createLayerElement`-produced react/pixi layers)
7
+ * and `RootSelectionOverlay`'s visual-chrome wrapper. Its independent input
8
+ * sibling deliberately remains untransformed and covers the full viewport.
9
+ *
10
+ * SOUNDNESS (why lockstep preserves the "zero-correction" host-relative rect
11
+ * invariant `RootSelectionOverlay.tsx`'s own doc comment establishes):
12
+ * `RectProvider.rect(id)` is computed as `el.getBoundingClientRect()` MINUS
13
+ * the owning world's own root/host `getBoundingClientRect()`
14
+ * (`react-world-authoring-adapter.ts`'s `toHostRelative`/`hostRect` — `this
15
+ * .root` IS the exact layer div `createLayerElement` produces). A CSS
16
+ * `transform: translate()` applied directly to that host element shifts the
17
+ * host's OWN rendered rect AND every descendant's rendered rect by the
18
+ * IDENTICAL `(x, y)` delta — a rigid subtree translation — so the
19
+ * subtraction is invariant under pan: `rect(id)` returns the SAME
20
+ * host-relative numbers at any pan offset, unmodified, with no pan-awareness
21
+ * needed in `inspect.ts`'s geometry math or the overlay chrome consumers.
22
+ * Zoom scales both measured rectangles; `toHostRelative` divides their
23
+ * offsets and dimensions by the shared zoom before exposing authored-space
24
+ * geometry, while `RootSelectionOverlay.toHostLocal` performs the inverse
25
+ * for pointer gestures. `PickProvider.pick` needs no changes — it
26
+ * hit-tests real rendered rects against the real client cursor position,
27
+ * both of which already reflect the applied transform natively.
28
+ *
29
+ * Applying the exact SAME transform to `RootSelectionOverlay`'s own visual-
30
+ * chrome wrapper (a SIBLING of every world-layer host inside the SAME
31
+ * `the world root's stage` containerRef parent — see that file's own mount-site doc
32
+ * comment) shifts and scales the overlay by the identical transform — so
33
+ * drawing a chrome element at `rect(id)`'s authored coordinates lands it at the
34
+ * SAME screen position as the panned live element it describes. This is the
35
+ * entire "lockstep" contract: every consumer on both sides of the pan reads
36
+ * ONE shared value (`getRootPan()`) and applies it through the ONE shared
37
+ * pure helper (`panTransformValue`) — never two independently-computed
38
+ * transforms that could drift.
39
+ */
40
+
41
+ export interface RootPan {
42
+ readonly x: number;
43
+ readonly y: number;
44
+ readonly zoom: number;
45
+ }
46
+
47
+ const ZERO_PAN: RootPan = { x: 0, y: 0, zoom: 1 };
48
+
49
+ /**
50
+ * One document camera over a 2D authoring plane.
51
+ *
52
+ * DOM component boards still use the historical shared instance exported
53
+ * below. A native canvas Scene creates its own instance, because a scene
54
+ * camera and a component-board camera are different documents and must not
55
+ * inherit one another's pose merely because both happen to be 2D.
56
+ */
57
+ export interface RootViewController {
58
+ get(): RootPan;
59
+ setView(x: number, y: number, zoom: number): void;
60
+ setPan(x: number, y: number): void;
61
+ setZoom(zoom: number): void;
62
+ reset(): void;
63
+ subscribe(listener: () => void): () => void;
64
+ }
65
+
66
+ export function createRootViewController(initial: RootPan = ZERO_PAN): RootViewController {
67
+ let current: RootPan = initial;
68
+ const subscribers = new Set<() => void>();
69
+ const notifySubscribers = (): void => {
70
+ for (const listener of subscribers) listener();
71
+ };
72
+ return {
73
+ get: () => current,
74
+ setView: (x, y, zoom) => {
75
+ const nextZoom = Math.min(4, Math.max(0.1, zoom));
76
+ if (current.x === x && current.y === y && current.zoom === nextZoom) return;
77
+ current = { x, y, zoom: nextZoom };
78
+ notifySubscribers();
79
+ },
80
+ setPan: (x, y) => {
81
+ const nextZoom = current.zoom;
82
+ if (current.x === x && current.y === y) return;
83
+ current = { x, y, zoom: nextZoom };
84
+ notifySubscribers();
85
+ },
86
+ setZoom: (zoom) => {
87
+ const nextZoom = Math.min(4, Math.max(0.1, zoom));
88
+ if (current.zoom === nextZoom) return;
89
+ current = { x: current.x, y: current.y, zoom: nextZoom };
90
+ notifySubscribers();
91
+ },
92
+ reset: () => {
93
+ if (current.x === 0 && current.y === 0 && current.zoom === 1) return;
94
+ current = ZERO_PAN;
95
+ notifySubscribers();
96
+ },
97
+ subscribe: (listener) => {
98
+ subscribers.add(listener);
99
+ return () => subscribers.delete(listener);
100
+ },
101
+ };
102
+ }
103
+
104
+ let _pan: RootPan = ZERO_PAN;
105
+ const listeners = new Set<() => void>();
106
+
107
+ /** The historical DOM-board camera, exposed as a controller for generic
108
+ * navigation/overlay code. Existing function exports below remain the
109
+ * compatibility surface for board-specific callers. */
110
+ export const sharedRootViewController: RootViewController = {
111
+ get: () => getRootPan(),
112
+ setView: (x, y, zoom) => setRootView(x, y, zoom),
113
+ setPan: (x, y) => setRootPan(x, y),
114
+ setZoom: (zoom) => setRootZoom(zoom),
115
+ reset: () => resetRootPan(),
116
+ subscribe: (listener) => subscribeRootPan(listener),
117
+ };
118
+
119
+ function notify(): void {
120
+ for (const l of listeners) l();
121
+ }
122
+
123
+ /** The current shared canvas transform; x/y are CSS px and zoom is unitless. */
124
+ export function getRootPan(): RootPan {
125
+ return _pan;
126
+ }
127
+
128
+ /** Set the complete shared canvas transform in one subscriber notification. */
129
+ export function setRootView(x: number, y: number, zoom: number): void {
130
+ const nextZoom = Math.min(4, Math.max(0.1, zoom));
131
+ if (_pan.x === x && _pan.y === y && _pan.zoom === nextZoom) return;
132
+ _pan = { x, y, zoom: nextZoom };
133
+ notify();
134
+ }
135
+
136
+ /** Set the shared pan translate to an absolute `(x, y)`. */
137
+ export function setRootPan(x: number, y: number): void {
138
+ setRootView(x, y, _pan.zoom);
139
+ }
140
+
141
+ /** Set the shared canvas zoom while preserving its current pan. */
142
+ export function setRootZoom(zoom: number): void {
143
+ setRootView(_pan.x, _pan.y, zoom);
144
+ }
145
+
146
+ /** Set the shared pan translate by a RELATIVE `(dx, dy)` — a convenience
147
+ * wrapper over `setRootPan` (not used by `RootSelectionOverlay`'s own
148
+ * space-drag, which composes onto a captured drag-start snapshot instead —
149
+ * see its own doc comment — but kept here as the natural pure counterpart
150
+ * for any future incremental caller, e.g. a nudge-pan keybinding). */
151
+ export function panRootBy(dx: number, dy: number): void {
152
+ setRootPan(_pan.x + dx, _pan.y + dy);
153
+ }
154
+
155
+ /** Reset pan to `(0, 0)` and zoom to 100% — called on a world-layer remount (`design-time-
156
+ * layers.ts`'s `mountDesignTimeLayers`, invoked on initial edit-mode install
157
+ * AND every acknowledged edit-mode rebuild), so switching/reloading the active
158
+ * world set never leaves a stale pan offset applied over a DIFFERENT layer
159
+ * stack. A no-op (no `notify()`) when already at rest, so a fresh session
160
+ * never fires a spurious subscriber tick. */
161
+ export function resetRootPan(): void {
162
+ if (_pan.x === 0 && _pan.y === 0 && _pan.zoom === 1) return;
163
+ _pan = ZERO_PAN;
164
+ notify();
165
+ }
166
+
167
+ /** Subscribe to canvas-transform changes — both `design-time-layers.ts` (imperative DOM
168
+ * style writes) and `RootSelectionOverlay` (`useSyncExternalStore`) bind
169
+ * this so every lockstep mount point re-applies the SAME new value the
170
+ * instant it changes. */
171
+ export function subscribeRootPan(listener: () => void): () => void {
172
+ listeners.add(listener);
173
+ return () => listeners.delete(listener);
174
+ }
175
+
176
+ /**
177
+ * The ONE shared CSS `transform` value both visual lockstep mount points apply —
178
+ * pure, so a unit test can assert the world-layer host and the overlay
179
+ * wrapper are handed byte-identical strings for any given pan (the actual
180
+ * "lockstep" proof). `undefined` at rest `(0, 0)` so neither mount point ever
181
+ * carries a no-op `transform: translate(0px, 0px)` — keeps every pre-pan
182
+ * pixel-position snapshot (the full 27x suite, pinned at pan=0) byte-identical
183
+ * to its pre-this-feature output.
184
+ */
185
+ export function panTransformValue(pan: RootPan): string | undefined {
186
+ if (pan.x === 0 && pan.y === 0 && pan.zoom === 1) return undefined;
187
+ if (pan.zoom === 1) return `translate(${pan.x}px, ${pan.y}px)`;
188
+ if (pan.x === 0 && pan.y === 0) return `scale(${pan.zoom})`;
189
+ return `translate(${pan.x}px, ${pan.y}px) scale(${pan.zoom})`;
190
+ }
191
+
192
+ /** Test-only reset (mirrors `eyedropper-session.ts`'s/`world-session-
193
+ * state.ts`'s identical helpers) — drops pan + every subscriber so unit
194
+ * tests don't leak state across cases. */
195
+ export function _resetRootPanStateForTest(): void {
196
+ _pan = ZERO_PAN;
197
+ listeners.clear();
198
+ }
@@ -0,0 +1,173 @@
1
+ /**
2
+ * THE ONE PERSISTENCE PIPE — `resolve(anchor) → write(dialect) → record(recorder)`.
3
+ *
4
+ * Every authored write, from every lane, runs through {@link runWritePipe}.
5
+ * The lanes that used to be parallel stacks are now this pipe's PLUG POINTS:
6
+ * a lane supplies a resolution (which anchor this edit lands at), a dialect
7
+ * writer (the bytes), and a recorder (history), and the pipe supplies the
8
+ * ordering, the awaiting, and the ack.
9
+ *
10
+ * ## The three defects it exists for, all measured on the vendored racing game
11
+ *
12
+ * 1. **The ack was the ADAPTER'S blanket answer, not this edit's.** The
13
+ * composite joined only its persist-CAPABLE children, so a three-root edit
14
+ * acked the DOM root's destination with `persisted: true`. Here the ack is
15
+ * produced by the component that performed the write, about that write, and
16
+ * there is nowhere else for a caller to get one.
17
+ * 2. **The classifier and the writer were different components.** A subject the
18
+ * adapter classified `live-only` still wrote a real prop into the game's
19
+ * source, because the code answering `TruthProvider.resolve` was not
20
+ * the code performing the write. Here the anchor is resolved ONCE, and a
21
+ * `live-only` resolution has no `write` member at all — reaching a dialect
22
+ * writer from it is a type error, not a discipline.
23
+ * 3. **The write was fired un-awaited, so the ack raced the byte.** Here the
24
+ * pipe awaits the dialect writer and the recorder before it acks.
25
+ *
26
+ * ## Why `live-only` is a destination and not a failure
27
+ *
28
+ * `live-only` (and its play-mode sibling, ephemeral) is a real
29
+ * {@link WriteAnchorKind}: the edit lands on the running object for the session
30
+ * and nothing else, and the contract of that kind is that the surface SAYS SO.
31
+ * So the pipe's live-only branch still applies the edit — the caller has
32
+ * already done that, synchronously, which is what keeps an `endEdit(); undo()`
33
+ * sequence working — and answers `persisted: false` with the reason reported
34
+ * where a user can read it. What the pipe forbids is the inverse: naming a
35
+ * destination no byte reached.
36
+ */
37
+
38
+ import type { WriteAck, WriteAnchorKind } from '@volter/project/adapter';
39
+
40
+ export type { WriteAck } from '@volter/project/adapter';
41
+
42
+ /** What a surface reports when nothing this session does reaches a file. */
43
+ export const LIVE_ONLY_DESTINATION = 'live-only (not saved)';
44
+
45
+ /** What a play-mode adoption reports: edits are real, and die with the session. */
46
+ export const EPHEMERAL_DESTINATION = 'ephemeral (discarded on stop)';
47
+
48
+ /** What `CompositeAuthoringAdapter.persistence` reports when no child of the
49
+ * composition can persist at all. That provider answers the SAVE-status
50
+ * question ("where do this surface's saves go"), never the per-edit one — the
51
+ * pipe's ack is the only answer to that. */
52
+ export const NO_PERSISTABLE_CHILD_DESTINATION = '(no persistable child)';
53
+
54
+ /** The honest floor, as a value: no write was performed, and saying so is the
55
+ * whole point. Frozen because it is shared by every lane that has no write. */
56
+ export const LIVE_ONLY_ACK: WriteAck = Object.freeze({
57
+ destination: LIVE_ONLY_DESTINATION,
58
+ persisted: false,
59
+ });
60
+
61
+ /**
62
+ * A CLIPBOARD gesture reports itself by its WRITE, never by the clipboard half
63
+ * that already succeeded.
64
+ *
65
+ * `StructuralClipboardOutcome` (`@volter/project/adapter`) keeps `false` as the refusal
66
+ * channel and reserves the {@link WriteAck} for a SUCCESSFUL cut/paste. A cut
67
+ * whose removal reached no byte is a COPY: handing its `persisted: false` ack
68
+ * straight back is truthy, so every caller — `consumer-actions.ts`'s
69
+ * `clipboardStructureWrite`, which only shortcuts on `=== false`, and the
70
+ * composite's `cut`, which claims clipboard ownership on anything else — reads
71
+ * a refusal as a landed edit.
72
+ *
73
+ * ONE owner, because the four lanes each said this inline and one commit
74
+ * deleted all four collapses together while widening the return type.
75
+ */
76
+ export function clipboardOutcome(ack: WriteAck): false | WriteAck {
77
+ return ack.persisted ? ack : false;
78
+ }
79
+
80
+ /** An anchor kind that has somewhere to land. `live-only` is excluded BY THE
81
+ * TYPE, which is what makes "a live-only resolution cannot reach a writer" a
82
+ * compile-time fact rather than a convention. */
83
+ export type AnchoredWriteKind = Exclude<WriteAnchorKind, 'live-only'>;
84
+
85
+ /**
86
+ * Step 1's product: what THIS edit's anchor resolved to.
87
+ *
88
+ * The two arms are not "success" and "failure" — they are the two honest
89
+ * outcomes of asking where an edit lands. Only the `writer` arm carries a
90
+ * `write`, so a lane cannot accidentally write through a resolution that said
91
+ * there was nowhere to write.
92
+ */
93
+ export type WriteResolution =
94
+ | {
95
+ readonly reaches: 'writer';
96
+ /** Which lane carries it — the SAME fact `TruthProvider.resolve`
97
+ * must report for this subject, because both read this resolution. */
98
+ readonly anchorKind: AnchoredWriteKind;
99
+ /** Where the bytes go, in the dialect writer's own words. */
100
+ readonly destination: string;
101
+ /** Step 2 — the dialect writer, already bound to this edit. `true` ⇒ the
102
+ * bytes landed and the writer's own transaction carries both halves. */
103
+ readonly write: () => Promise<boolean>;
104
+ }
105
+ | {
106
+ readonly reaches: 'live-only';
107
+ /** {@link LIVE_ONLY_DESTINATION} or {@link EPHEMERAL_DESTINATION}. */
108
+ readonly destination: string;
109
+ /** Why there is nowhere to write — reported to the user by the lane's
110
+ * own reporter, never swallowed. */
111
+ readonly reason: string;
112
+ };
113
+
114
+ /** One edit, offered to the pipe. */
115
+ export interface PipedWrite {
116
+ /**
117
+ * Step 1 — resolve THIS edit's anchor. Called EXACTLY ONCE by the pipe, so
118
+ * the classification a caller reads and the route the write takes are the
119
+ * same object rather than two evaluations that can disagree.
120
+ */
121
+ resolve(): WriteResolution;
122
+ /**
123
+ * Step 3 — the recorder. Called exactly once, after the write step settled,
124
+ * with what actually happened. `persisted: true` ⇒ the dialect writer's own
125
+ * transaction already carries both the file and the live half, so the
126
+ * recorder skips its session journal rather than adding a second entry.
127
+ *
128
+ * This is where undo/redo integrates, and it is the ONLY place: a lane that
129
+ * journals outside the pipe forks history, which is what the pipe replaced.
130
+ */
131
+ record(persisted: boolean): void;
132
+ /**
133
+ * Show a live-only reason where the user can read it. Called only for the
134
+ * `live-only` arm, and only when the lane wants it said (an unarmed backend
135
+ * refusing on every frame of a game somebody is playing is noise, so lanes
136
+ * gate this themselves).
137
+ */
138
+ report?(reason: string): void;
139
+ }
140
+
141
+ /**
142
+ * RUN ONE EDIT THROUGH THE PIPE, and answer for it.
143
+ *
144
+ * The ordering is the contract: resolve, then write (awaited), then record
145
+ * (before the ack). A caller that awaits this ack has awaited the byte.
146
+ *
147
+ * A dialect writer that comes back `false` has already reported its own reason
148
+ * (that is its contract — every refusal names its gate), and the edit degrades
149
+ * to the live-only floor: the value is on the running object, the recorder
150
+ * journals it so it can be undone, and the ack says no byte moved.
151
+ */
152
+ export async function runWritePipe(edit: PipedWrite): Promise<WriteAck> {
153
+ const resolution = edit.resolve();
154
+ if (resolution.reaches === 'live-only') {
155
+ edit.report?.(resolution.reason);
156
+ edit.record(false);
157
+ return { destination: resolution.destination, persisted: false };
158
+ }
159
+ const persisted = await resolution.write();
160
+ edit.record(persisted);
161
+ return persisted
162
+ ? { destination: resolution.destination, persisted: true }
163
+ : { destination: LIVE_ONLY_DESTINATION, persisted: false };
164
+ }
165
+
166
+ /** Spell a live-only resolution — the one form, so no lane invents a second
167
+ * phrasing of "there is nowhere to write". */
168
+ export function resolvesLiveOnly(
169
+ reason: string,
170
+ destination: string = LIVE_ONLY_DESTINATION,
171
+ ): WriteResolution {
172
+ return { reaches: 'live-only', destination, reason };
173
+ }
@@ -0,0 +1,5 @@
1
+ import type { WorkspaceArrangement } from '@volter/project/adapter/workspace-arrangement';
2
+ export type { WorkspaceArrangement, WorkspaceAreaContribution } from '@volter/project/adapter/workspace-arrangement';
3
+
4
+ export const GameArrangement: WorkspaceArrangement = { id: 'game', title: 'Game' };
5
+ export const DesignArrangement: WorkspaceArrangement = { id: 'design', title: 'Design' };