@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,71 @@
1
+ /**
2
+ * THE JS HEAP READING — the editor's one browser-side memory signal, read by
3
+ * the tab census (`tab-census.ts`: the heartbeat's sample, the death line's
4
+ * quote) and by the Frame debugger's tile (`@volter/editor-game`). A browser
5
+ * property, not a scene property (M1 kept it out of the engine's
6
+ * render-memory on purpose), and Chromium-only: feature-detected, with the
7
+ * REASON returned when the global is absent — never a fabricated 0.
8
+ */
9
+ export interface JsHeapReading {
10
+ readonly usedBytes: number;
11
+ readonly totalBytes: number;
12
+ /**
13
+ * `jsHeapSizeLimit` — the CEILING this renderer process may allocate to,
14
+ * which is the only one of the three that says how close to a heap death
15
+ * the tab is (`totalBytes` is merely what it has claimed so far). Null when
16
+ * the browser exposes the other two and not this one; the tab census reads
17
+ * it, and reads null as null.
18
+ */
19
+ readonly limitBytes: number | null;
20
+ }
21
+
22
+ export interface JsHeapUnavailable {
23
+ /** The honest reason the reading is absent (printed to the user). */
24
+ readonly unavailable: string;
25
+ }
26
+
27
+ /** True when the reading is present (vs. the unavailable-reason branch). */
28
+ export function isJsHeapReading(
29
+ reading: JsHeapReading | JsHeapUnavailable,
30
+ ): reading is JsHeapReading {
31
+ return !('unavailable' in reading);
32
+ }
33
+
34
+ /**
35
+ * Read the JS heap via the Chromium-only `performance.memory` global — the one
36
+ * editor-side memory signal (M1 kept it OUT of the engine's render-memory on
37
+ * purpose: it is a browser property, not a scene property). Feature-detected:
38
+ * when the global is absent (Firefox/Safari, or a locked-down Chromium), the
39
+ * REASON is returned so the tile prints it, never a fabricated 0. `perf` is
40
+ * injectable so the test can drive both branches deterministically.
41
+ */
42
+ export function readJsHeap(
43
+ perf: Performance | undefined = globalThis.performance,
44
+ ): JsHeapReading | JsHeapUnavailable {
45
+ const memory = (
46
+ perf as unknown as
47
+ | {
48
+ memory?: {
49
+ usedJSHeapSize?: number;
50
+ totalJSHeapSize?: number;
51
+ jsHeapSizeLimit?: number;
52
+ };
53
+ }
54
+ | undefined
55
+ )?.memory;
56
+ if (
57
+ !memory ||
58
+ typeof memory.usedJSHeapSize !== 'number' ||
59
+ typeof memory.totalJSHeapSize !== 'number'
60
+ ) {
61
+ return {
62
+ unavailable:
63
+ 'performance.memory is unavailable — it is a non-standard Chromium-only API, not exposed by this browser.',
64
+ };
65
+ }
66
+ return {
67
+ usedBytes: memory.usedJSHeapSize,
68
+ totalBytes: memory.totalJSHeapSize,
69
+ limitBytes: typeof memory.jsHeapSizeLimit === 'number' ? memory.jsHeapSizeLimit : null,
70
+ };
71
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * THE EDITOR'S KEY ACTIONS — every action a chord can reach, as DATA.
3
+ *
4
+ * THERE IS ONE KEYBOARD AND IT IS VS CODE'S (ARCHITECTURE-CORE §The core is
5
+ * Code-OSS rule 3). The editor installs no `keydown` dispatcher of its own;
6
+ * what it publishes is this table, and the frame turns each entry into a
7
+ * `volter.<id>` command with a `when` clause over our panes' context keys
8
+ * (`scripts/workbench/generate-keymaps.mjs` writes one keybinding rule per
9
+ * (action, chord, keymap) into a built-in extension, read from this repo's own
10
+ * keymap tables — so a chord is written in ONE place whichever keyboard is
11
+ * driving).
12
+ *
13
+ * WHY, measured: with two listeners on one page, `1,1,1,2,2,2` typed into
14
+ * Monaco arrived as `,,,,,`, the file saved as `BoxGeometry(,,,,,)`, and a
15
+ * `Control+W` meant for the workbench opened Edit Mode's Inset tool.
16
+ *
17
+ * An action's BODY is written once, in `editor-hotkeys.ts`'s `bind()` call —
18
+ * the same call that fills this table also fills the binding row — so a
19
+ * handler cannot exist for one keyboard and not the other.
20
+ */ import type { EditorKeyActionId } from '@volter/sdk/looks';
21
+
22
+ export type KeyActionScope = 'stage' | 'panel' | 'global';
23
+
24
+ export interface KeyActionEntry {
25
+ readonly id: EditorKeyActionId;
26
+ /** Run the action. The event is the host dispatcher's; the frame has none. */
27
+ readonly run: (event?: KeyboardEvent) => void;
28
+ readonly scope: KeyActionScope;
29
+ /**
30
+ * The action's own runtime gate, where it can be asked without an event —
31
+ * the play-state and clipboard-ownership conditions. A gate that reads the
32
+ * EVENT (undo/redo's editable-target test) is not lifted here: under the
33
+ * frame the focus condition it approximates is a `when` clause, and under
34
+ * the host the dispatcher still applies its own `when`.
35
+ */
36
+ readonly enabled?: () => boolean;
37
+ }
38
+
39
+ const actions = new Map<EditorKeyActionId, KeyActionEntry>();
40
+ let actionsVersion = 0;
41
+ const actionListeners = new Set<() => void>();
42
+
43
+ function emitActions(): void {
44
+ actionsVersion++;
45
+ for (const listener of actionListeners) listener();
46
+ }
47
+
48
+ /**
49
+ * Record what one action DOES. Last registration wins: the shell and viewport
50
+ * binding sets rebuild on every keymap switch (`registerKeymapBindings`), and
51
+ * a rebuild re-registers the same ids with fresh closures over the same store.
52
+ * Returns the removal, which only fires if this entry is still the live one.
53
+ */
54
+ export function registerKeyAction(entry: KeyActionEntry): () => void {
55
+ actions.set(entry.id, entry);
56
+ emitActions();
57
+ return () => {
58
+ if (actions.get(entry.id) !== entry) return;
59
+ actions.delete(entry.id);
60
+ emitActions();
61
+ };
62
+ }
63
+
64
+ /** Every action the editor currently has a handler for. */
65
+ export function registeredKeyActions(): readonly KeyActionEntry[] {
66
+ return [...actions.values()];
67
+ }
68
+
69
+ export function keyActionsVersion(): number {
70
+ return actionsVersion;
71
+ }
72
+
73
+ export function subscribeKeyActions(listener: () => void): () => void {
74
+ actionListeners.add(listener);
75
+ return () => actionListeners.delete(listener);
76
+ }
77
+
78
+ /**
79
+ * Run one action by id — the frame's door. `false` means the editor has no
80
+ * handler for it right now (the viewport set is registered only while a three
81
+ * stage is mounted) or its own gate refused; the frame's command answers the
82
+ * same, so a keybinding that reaches a dead action is visible rather than
83
+ * silent.
84
+ */
85
+ export function invokeKeyAction(id: EditorKeyActionId): boolean {
86
+ const entry = actions.get(id);
87
+ if (!entry) return false;
88
+ if (entry.enabled && !entry.enabled()) return false;
89
+ entry.run();
90
+ return true;
91
+ }
@@ -0,0 +1,428 @@
1
+ import type { EditorKeyActionId, KeyChord, KeymapContribution, KeymapNavigation } from '@volter/sdk/looks';
2
+ import { editorConsole } from '@volter/sdk/kit/editor-console';
3
+ import {
4
+ adapterSettings,
5
+ projectSettings,
6
+ subscribeSettings,
7
+ updatePreferenceSettings,
8
+ updateProjectSettings,
9
+ userSettings,
10
+ } from './settings-store';
11
+
12
+ export type { EditorKeyActionId, KeyChord } from '@volter/sdk/looks';
13
+ /**
14
+ * KEYMAPS — the binding table behind every editor keyboard action.
15
+ *
16
+ * The ruling (docs/ARCHITECTURE-CORE.md §Editor chrome, the "Workspaces are
17
+ * task-named layout memories" bullet, final sentence): *"Keymaps are
18
+ * orthogonal to workspaces: a `keymap` setting selects the binding table
19
+ * (`volter` default; `blender` — G/R/S, A, Alt+A, `.` frame) through one
20
+ * indirection at the action-registry/hotkey seam."*
21
+ *
22
+ * ONE INDIRECTION means exactly this: nothing in the editor spells a literal
23
+ * key for a keyboard action any more. `editor-hotkeys.ts` builds its
24
+ * `HotkeyBinding`s from {@link keyChordsFor}, and every place that PRINTS a
25
+ * shortcut — the command palette (via `action-registry.ts`), the viewport
26
+ * toolstrip tooltips, the snap transient hint —
27
+ * renders {@link shortcutFor} over the same table. Switch the keymap and the
28
+ * chrome tells the truth on the next paint, with no reload.
29
+ *
30
+ * The two axes this module is deliberately NOT: it is not a workspace (that is
31
+ * `workspace-presets.ts` — layout, keyed per project) and not an appearance
32
+ * preference (`theme-preference.ts`). A keymap is a per-user input preference,
33
+ * persisted the way that module persists palette/material: one settings
34
+ * key, lazily read, written on change, broadcast to `useSyncExternalStore`
35
+ * subscribers, and simply falling back to the default when unreadable —
36
+ * nothing a user authored is at stake in a stored preference.
37
+ *
38
+ * WHAT THIS DOES NOT GOVERN — the boundary, stated once: this table is the
39
+ * EDITOR's own chrome bindings, consumed by `hotkeys.ts`'s single `keydown`
40
+ * dispatcher on the editor's window. Play-mode input isolation is a different
41
+ * mechanism entirely and is untouched by a keymap switch: the engine's
42
+ * realm gate, `gated-globals.ts`'s lexical
43
+ * `window`/`document` shadow over project modules decide whether GAME code
44
+ * hears a key. A game never reads this table, and no keymap entry can widen or
45
+ * narrow what a running game receives.
46
+ */
47
+
48
+ /** Any registered keymap's id: the editor's own `volter`, or one a package
49
+ * contributes (`@volter/sdk/looks`, `KeymapContribution`). */
50
+ export type EditorKeymapId = string;
51
+
52
+ export interface EditorKeymapDescriptor {
53
+ readonly id: EditorKeymapId;
54
+ readonly title: string;
55
+ readonly description: string;
56
+ }
57
+
58
+ /** The editor's OWN keymap, the one every project has. Every other keymap is
59
+ * a package's contribution (Blender's ships with `@volter/editor-blender`). */
60
+ const BUILT_IN_KEYMAPS: readonly EditorKeymapDescriptor[] = Object.freeze([
61
+ {
62
+ id: 'volter',
63
+ title: 'volter',
64
+ description: "The editor's own bindings: W/E/R gizmo modes, Ctrl+A select all, F frames.",
65
+ },
66
+ ] satisfies readonly EditorKeymapDescriptor[]);
67
+
68
+ interface ContributedKeymap {
69
+ readonly descriptor: EditorKeymapDescriptor;
70
+ readonly table: EditorKeymapTable;
71
+ readonly navigation: KeymapNavigation | null;
72
+ }
73
+ const contributedKeymaps = new Map<string, ContributedKeymap>();
74
+ let registryVersion = 0;
75
+
76
+ /** Built-ins first, then contributions in registration order — the switch
77
+ * surfaces (View menu, palette) enumerate this. */
78
+ export function editorKeymaps(): readonly EditorKeymapDescriptor[] {
79
+ return [
80
+ ...BUILT_IN_KEYMAPS,
81
+ ...[...contributedKeymaps.values()].map((entry) => entry.descriptor),
82
+ ];
83
+ }
84
+
85
+ export function editorKeymapsVersion(): number {
86
+ return registryVersion;
87
+ }
88
+
89
+ /**
90
+ * Register a package's keymap (`workspace.keymap` contribution). The table is
91
+ * the editor's own bindings with the contribution's chords over them, so a
92
+ * keymap declares only where it differs. Returns the unregister. A duplicate
93
+ * id throws — ids are the `keymap` setting's values.
94
+ */
95
+ export function registerContributedKeymap(contribution: KeymapContribution): () => void {
96
+ if (
97
+ BUILT_IN_KEYMAPS.some((entry) => entry.id === contribution.id) ||
98
+ contributedKeymaps.has(contribution.id)
99
+ )
100
+ throw new Error(
101
+ `registerContributedKeymap: keymap "${contribution.id}" is already registered.`,
102
+ );
103
+ const entry: ContributedKeymap = {
104
+ descriptor: {
105
+ id: contribution.id,
106
+ title: contribution.title,
107
+ description: contribution.description,
108
+ },
109
+ table: Object.freeze({ ...VOLTER_KEYMAP, ...contribution.bindings }) as EditorKeymapTable,
110
+ navigation: contribution.navigation ?? null,
111
+ };
112
+ contributedKeymaps.set(contribution.id, entry);
113
+ registryVersion++;
114
+ // A stored preference this contribution satisfies applies now, not on the
115
+ // next reload: the cache re-reads the setting against the wider registry.
116
+ cachedKeymap = null;
117
+ emit();
118
+ return () => {
119
+ if (contributedKeymaps.get(contribution.id) !== entry) return;
120
+ contributedKeymaps.delete(contribution.id);
121
+ registryVersion++;
122
+ cachedKeymap = null;
123
+ emit();
124
+ };
125
+ }
126
+
127
+ export function isEditorKeymapId(value: unknown): value is EditorKeymapId {
128
+ return (
129
+ typeof value === 'string' &&
130
+ (BUILT_IN_KEYMAPS.some((entry) => entry.id === value) || contributedKeymaps.has(value))
131
+ );
132
+ }
133
+
134
+ export type EditorKeymapTable = Readonly<Record<EditorKeyActionId, readonly KeyChord[]>>;
135
+
136
+ /**
137
+ * The volter table reproduces the bindings the editor shipped before keymaps
138
+ * existed, chord for chord. It is the regression bar: any change here is a
139
+ * change to the default editor, not to a keymap.
140
+ */
141
+ const VOLTER_KEYMAP: EditorKeymapTable = Object.freeze({
142
+ 'edit.undo': [{ key: 'z', mod: true }],
143
+ // Ctrl+Y mirrors Ctrl+Shift+Z (Windows convention).
144
+ 'edit.redo': [
145
+ { key: 'z', mod: true, shift: true },
146
+ { key: 'y', mod: true },
147
+ ],
148
+ 'edit.copy': [{ key: 'c', mod: true }],
149
+ 'edit.cut': [{ key: 'x', mod: true }],
150
+ 'edit.paste': [{ key: 'v', mod: true }],
151
+ 'edit.duplicate': [{ key: 'd', mod: true }],
152
+ 'edit.group': [{ key: 'g', mod: true }],
153
+ 'edit.wrap': [{ key: 'g', mod: true, alt: true }],
154
+ 'edit.unwrap': [{ key: 'g', mod: true, shift: true }],
155
+ 'edit.selectAll': [{ key: 'a', mod: true }],
156
+ // No dedicated chord: Escape is the volter deselect, and it carries the
157
+ // scope-exit semantics too (`edit.exitScopeOrDeselect`). An empty chord list
158
+ // registers no binding; the printed hint falls back to Escape's.
159
+ 'edit.deselectAll': [],
160
+ 'edit.save': [{ key: 's', mod: true }],
161
+ 'edit.delete': [{ key: 'delete' }, { key: 'backspace' }],
162
+ 'edit.enterScope': [{ key: 'enter' }],
163
+ 'edit.exitScopeOrDeselect': [{ key: 'escape' }],
164
+ 'edit.nudgeUp': [{ key: 'arrowup' }],
165
+ 'edit.nudgeUpCoarse': [{ key: 'arrowup', shift: true }],
166
+ 'edit.nudgeDown': [{ key: 'arrowdown' }],
167
+ 'edit.nudgeDownCoarse': [{ key: 'arrowdown', shift: true }],
168
+ 'edit.nudgeLeft': [{ key: 'arrowleft' }],
169
+ 'edit.nudgeLeftCoarse': [{ key: 'arrowleft', shift: true }],
170
+ 'edit.nudgeRight': [{ key: 'arrowright' }],
171
+ 'edit.nudgeRightCoarse': [{ key: 'arrowright', shift: true }],
172
+ 'view.resetPan': [{ key: '0', mod: true }],
173
+ 'view.commandPalette': [{ key: 'k', mod: true }],
174
+ 'view.toggleConsole': [{ key: '`' }],
175
+ 'view.focusMode': [{ key: 'f', mod: true, shift: true }],
176
+ // Blender's own workspace cycle keys, and free in this registry.
177
+ 'workspace.cycleNext': [{ key: 'pagedown', mod: true }],
178
+ 'workspace.cyclePrevious': [{ key: 'pageup', mod: true }],
179
+ // Q, beside W/E/R: Godot's 2D Select (its 4.7.1 shortcut `canvas_item_editor/select_mode`)
180
+ // and Unreal's Select both sit there. The Blender look keeps Select on Blender's own `W`.
181
+ 'transform.select': [{ key: 'q' }],
182
+ 'transform.combined': [{ key: 't' }],
183
+ 'transform.translate': [{ key: 'w' }],
184
+ 'transform.rotate': [{ key: 'e' }],
185
+ 'transform.scale': [{ key: 'r' }],
186
+ 'viewport.toggleSnap': [{ key: 's', shift: true }],
187
+ 'viewport.frameSelection': [{ key: 'f' }],
188
+ 'viewport.cyclePivot': [{ key: '.' }],
189
+ // A 2D view's Pan and Ruler modes, on Godot's own keys (its 4.7.1 shortcuts
190
+ // `canvas_item_editor/pan_mode` G and `ruler_mode` M).
191
+ 'canvas.panMode': [{ key: 'g' }],
192
+ 'canvas.rulerMode': [{ key: 'm' }],
193
+ // Godot's View › Grid › Toggle Grid, Command+' (its 4.7.1 menu shortcut).
194
+ 'canvas.toggleGrid': [{ key: "'", mod: true }],
195
+ 'viewport.vertexSnapHold': [{ key: 'v' }],
196
+ 'viewport.snapToFloor': [{ key: '', code: 'PageDown' }],
197
+ 'view.top': [{ key: '', code: 'Numpad7' }],
198
+ 'view.front': [{ key: '', code: 'Numpad1' }],
199
+ 'view.right': [{ key: '', code: 'Numpad3' }],
200
+ 'view.bottom': [],
201
+ 'view.back': [],
202
+ 'view.left': [],
203
+ 'view.orbitLeft': [],
204
+ 'view.orbitRight': [],
205
+ 'view.orbitUp': [],
206
+ 'view.orbitDown': [],
207
+ 'view.opposite': [],
208
+ 'view.rollLeft': [],
209
+ 'view.rollRight': [],
210
+ 'view.all': [],
211
+ 'view.zoomIn': [],
212
+ 'view.zoomOut': [],
213
+ 'view.perspective': [{ key: '', code: 'Numpad5' }],
214
+ 'view.projection': [],
215
+ 'view.camera': [{ key: '', code: 'Numpad0' }],
216
+ } satisfies EditorKeymapTable);
217
+
218
+ // ---------------------------------------------------------------------------
219
+ // The setting
220
+ // ---------------------------------------------------------------------------
221
+
222
+ export const DEFAULT_EDITOR_KEYMAP: EditorKeymapId = 'volter';
223
+
224
+ let cachedKeymap: EditorKeymapId | null = null;
225
+ let settingsSyncInstalled = false;
226
+ const listeners = new Set<() => void>();
227
+
228
+ function emit(): void {
229
+ for (const listener of listeners) listener();
230
+ }
231
+
232
+ /** The editor's own keymap ids — the ones that exist in every project. */
233
+ function isBuiltInKeymapId(value: unknown): boolean {
234
+ return typeof value === 'string' && BUILT_IN_KEYMAPS.some((entry) => entry.id === value);
235
+ }
236
+
237
+ /** What the PROJECT selects: its adapter's declaration, its own settings over it. */
238
+ function projectScopedKeymap(): unknown {
239
+ return projectSettings().keymap ?? adapterSettings().keymap;
240
+ }
241
+
242
+ /**
243
+ * A keymap a PACKAGE contributes is project-scoped: it exists only where that
244
+ * package is declared, so only the project may select it — its adapter
245
+ * (`editor: { keymap: blenderKeymap }`) or its own `.volter/settings.json`. The
246
+ * USER layer chooses among the editor's own, because a cross-project default
247
+ * naming a skew's bindings is how a models project's G/R/S reached a game
248
+ * project that merely happens to declare the same package.
249
+ */
250
+ function readStoredKeymap(): EditorKeymapId {
251
+ const scoped = projectScopedKeymap();
252
+ if (isEditorKeymapId(scoped)) return scoped;
253
+ const preferred = userSettings().keymap;
254
+ return isBuiltInKeymapId(preferred) ? (preferred as EditorKeymapId) : DEFAULT_EDITOR_KEYMAP;
255
+ }
256
+
257
+ const saidUnavailable = new Set<string>();
258
+ /**
259
+ * Say, once per id, that the STORED keymap is one nothing in this project
260
+ * contributes, so a models project opened without its Blender package
261
+ * explains the W/E/R it is showing. Called by the loader AFTER a contribution
262
+ * pass has registered what the project's packages ship — asked at boot it
263
+ * would warn about every keymap a package is about to contribute (measured
264
+ * 2026-09-17: "blender is not available" on a project whose mesh package
265
+ * registered it a moment later).
266
+ */
267
+ export function reportUnavailableKeymap(): void {
268
+ const stored = projectScopedKeymap();
269
+ if (typeof stored !== 'string' || stored === DEFAULT_EDITOR_KEYMAP) return;
270
+ if (isEditorKeymapId(stored) || saidUnavailable.has(stored)) return;
271
+ saidUnavailable.add(stored);
272
+ editorConsole.warn(
273
+ `Keymap "${stored}" is not available in this project: no declared package contributes it ` +
274
+ `(a package ships one as a \`workspace.keymap\` contribution). Using "${DEFAULT_EDITOR_KEYMAP}".`,
275
+ 'editor',
276
+ );
277
+ }
278
+
279
+ /** The setting is `keymap` in the settings layers (`settings-store.ts`); a
280
+ * load finishing or a project's own override becoming active must not leave
281
+ * this module's cache lying. Installed on first read so the module has no
282
+ * load-time side effect. */
283
+ function ensureSettingsSync(): void {
284
+ if (settingsSyncInstalled) return;
285
+ settingsSyncInstalled = true;
286
+ subscribeSettings(() => {
287
+ const next = readStoredKeymap();
288
+ if (next === cachedKeymap) return;
289
+ cachedKeymap = next;
290
+ emit();
291
+ });
292
+ }
293
+
294
+ /** Current keymap id (`useSyncExternalStore`-shaped snapshot). */
295
+ export function activeEditorKeymap(): EditorKeymapId {
296
+ ensureSettingsSync();
297
+ cachedKeymap ??= readStoredKeymap();
298
+ return cachedKeymap;
299
+ }
300
+
301
+ /**
302
+ * Switch keymaps. Live: every binding registration re-derives from the new
303
+ * table on this call (`editor-hotkeys.ts`) and every printed hint re-renders,
304
+ * so there is no reload and no restart. Choosing one of the editor's OWN
305
+ * keymaps writes where the key is declared; choosing a package's writes the
306
+ * PROJECT layer, because that is the only layer a contributed keymap is read
307
+ * from (see {@link readStoredKeymap}) — a gesture must land somewhere it wins.
308
+ */
309
+ export function setEditorKeymapPreference(id: EditorKeymapId): void {
310
+ if (activeEditorKeymap() === id) return;
311
+ cachedKeymap = id;
312
+ if (isBuiltInKeymapId(id)) updatePreferenceSettings({ keymap: id });
313
+ else updateProjectSettings({ keymap: id });
314
+ emit();
315
+ }
316
+
317
+ export function subscribeEditorKeymap(listener: () => void): () => void {
318
+ listeners.add(listener);
319
+ return () => listeners.delete(listener);
320
+ }
321
+
322
+ export function __resetEditorKeymapForTest(): void {
323
+ cachedKeymap = null;
324
+ listeners.clear();
325
+ }
326
+
327
+ // ---------------------------------------------------------------------------
328
+ // The one lookup
329
+ // ---------------------------------------------------------------------------
330
+
331
+ /** The active table's chords for one action. Empty means deliberately unbound. */
332
+ export function keyChordsFor(action: EditorKeyActionId): readonly KeyChord[] {
333
+ return keymapTable(activeEditorKeymap())[action];
334
+ }
335
+
336
+ /** The active keymap's viewport mouse (`KeymapContribution.navigation`), the editor's own when
337
+ * it states none: orbit on the right button. */
338
+ export function activeKeymapNavigation(): KeymapNavigation {
339
+ return contributedKeymaps.get(activeEditorKeymap())?.navigation ?? { orbit: 'right' };
340
+ }
341
+
342
+ /** A named table, for a surface that must show a keymap it is not running.
343
+ * An unregistered id answers the editor's own table. */
344
+ export function keymapTable(id: EditorKeymapId): EditorKeymapTable {
345
+ return contributedKeymaps.get(id)?.table ?? VOLTER_KEYMAP;
346
+ }
347
+
348
+ // ---------------------------------------------------------------------------
349
+ // Display
350
+ // ---------------------------------------------------------------------------
351
+
352
+ function isMacPlatform(): boolean {
353
+ return typeof navigator !== 'undefined' && navigator.platform.includes('Mac');
354
+ }
355
+
356
+ /** Named keys whose label is neither the raw `key` nor its uppercase form. */
357
+ const KEY_LABELS: Readonly<Record<string, string>> = {
358
+ delete: 'Del',
359
+ backspace: 'Backspace',
360
+ escape: 'Esc',
361
+ enter: 'Enter',
362
+ pagedown: 'PgDn',
363
+ pageup: 'PgUp',
364
+ arrowup: '↑',
365
+ arrowdown: '↓',
366
+ arrowleft: '←',
367
+ arrowright: '→',
368
+ ' ': 'Space',
369
+ tab: 'Tab',
370
+ };
371
+
372
+ const CODE_LABELS: Readonly<Record<string, string>> = {
373
+ Numpad0: 'Num0',
374
+ Numpad1: 'Num1',
375
+ Numpad2: 'Num2',
376
+ Numpad3: 'Num3',
377
+ Numpad4: 'Num4',
378
+ Numpad5: 'Num5',
379
+ Numpad6: 'Num6',
380
+ Numpad7: 'Num7',
381
+ Numpad8: 'Num8',
382
+ Numpad9: 'Num9',
383
+ NumpadDecimal: 'Num.',
384
+ PageDown: 'PgDn',
385
+ PageUp: 'PgUp',
386
+ End: 'End',
387
+ KeyG: 'G',
388
+ KeyH: 'H',
389
+ KeyJ: 'J',
390
+ KeyK: 'K',
391
+ };
392
+
393
+ function keyLabel(chord: KeyChord): string {
394
+ if (chord.code) return CODE_LABELS[chord.code] ?? chord.code;
395
+ return KEY_LABELS[chord.key] ?? (chord.key.length === 1 ? chord.key.toUpperCase() : chord.key);
396
+ }
397
+
398
+ /**
399
+ * Render one chord the way the editor's chrome has always rendered them —
400
+ * BOTH existing conventions preserved verbatim, because changing a printed
401
+ * string is a visible regression: a mod-prefixed chord reads `⌘⇧Z` / `Ctrl+⇧Z`
402
+ * (the command palette's shape), while a modless chord spells its modifiers
403
+ * out, `Shift+S` (the toolstrip's shape).
404
+ */
405
+ export function formatChord(chord: KeyChord): string {
406
+ const label = keyLabel(chord);
407
+ if (chord.mod) {
408
+ const mod = isMacPlatform() ? '⌘' : 'Ctrl+';
409
+ return `${chord.ctrl && isMacPlatform() ? '⌃' : ''}${mod}${chord.alt ? '⌥' : ''}${chord.shift ? '⇧' : ''}${label}`;
410
+ }
411
+ const parts: string[] = [];
412
+ if (chord.ctrl) parts.push('Ctrl');
413
+ if (chord.alt) parts.push('Alt');
414
+ if (chord.shift) parts.push('Shift');
415
+ parts.push(label);
416
+ return parts.join('+');
417
+ }
418
+
419
+ /**
420
+ * The printed hint for an action under the ACTIVE keymap — the first chord,
421
+ * which every table lists in "the one to teach" order. `undefined` when the
422
+ * action is deliberately unbound, so a caller can fall back or omit the hint
423
+ * rather than print a lie.
424
+ */
425
+ export function shortcutFor(action: EditorKeyActionId): string | undefined {
426
+ const chord = keyChordsFor(action)[0];
427
+ return chord ? formatChord(chord) : undefined;
428
+ }
@@ -0,0 +1,31 @@
1
+ /** Presentation chosen by mounted layout code. No game or website names live here. */
2
+ import type { WorkspaceArrangement } from '@volter/sdk/layout-arrangements';
3
+ import { activeProjectKey } from '@volter/sdk/kit/active-project';
4
+ export interface LayoutPolicy {
5
+ readonly immersivePlay?: boolean;
6
+ readonly playUtilities?: readonly string[];
7
+ readonly arrangement?: WorkspaceArrangement;
8
+ }
9
+ let owner: string | null = null;
10
+ let policy: LayoutPolicy | null = null;
11
+ const listeners = new Set<() => void>();
12
+ export function layoutPolicy(): LayoutPolicy | null {
13
+ return owner === activeProjectKey() ? policy : null;
14
+ }
15
+ export function subscribeLayoutPolicy(listener: () => void): () => void {
16
+ listeners.add(listener);
17
+ return () => {
18
+ listeners.delete(listener);
19
+ };
20
+ }
21
+ export function installLayoutPolicy(next: LayoutPolicy): () => void {
22
+ owner = activeProjectKey();
23
+ policy = next;
24
+ for (const listener of listeners) listener();
25
+ return () => {
26
+ if (policy !== next) return;
27
+ policy = null;
28
+ owner = null;
29
+ for (const listener of listeners) listener();
30
+ };
31
+ }