@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,497 @@
1
+ /**
2
+ * Theme-backed renderer selection ink shared by the native Three and Pixi
3
+ * views. CSS can consume `var(--volter-accent)` directly; WebGL cannot, so this
4
+ * module resolves the inherited token to the integer both renderers speak.
5
+ */
6
+
7
+ import { useMemo, useSyncExternalStore } from 'react';
8
+ import { EDITOR_THEME_CLASS, graphiteDarkEditorTheme, STAGE_WORD_MODES } from '@volter/sdk/widgets';
9
+
10
+ /** Import/SSR fallback: Graphite Dark's canonical blue accent. */
11
+ export const DEFAULT_NATIVE_SELECTION_COLOR = 0x579eff;
12
+
13
+ export interface NativeSelectionColors {
14
+ readonly visible: number;
15
+ readonly hidden: number;
16
+ /** The ACTIVE object's outline (`color.viewport.active`, Blender's lighter orange), or the
17
+ * selection's own when the palette names none. */
18
+ readonly active?: { readonly visible: number; readonly hidden: number };
19
+ /** THE OUTLINE'S FORM (`stage.outlineStyle`, `outlineWidth`, `outlineHidden`):
20
+ * `soft`, the editor's own blurred halo, or `crisp` at a width in device pixels; and whether
21
+ * the parts other objects hide are drawn too. Absent is the editor's own. */
22
+ readonly outline?: { readonly style: 'soft' | 'crisp'; readonly width: number | null; readonly hidden: boolean };
23
+ }
24
+
25
+ function rgbHex(red: number, green: number, blue: number): number {
26
+ return (red << 16) | (green << 8) | blue;
27
+ }
28
+
29
+ function parseNormalizedColor(value: string): number | null {
30
+ const hex = /^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.exec(value.trim())?.[1];
31
+ if (hex) {
32
+ const opaque = hex.length === 3 ? [...hex].map((digit) => `${digit}${digit}`).join('') : hex;
33
+ return Number.parseInt(opaque.slice(0, 6), 16);
34
+ }
35
+ const rgb =
36
+ /^rgba?\(\s*(\d+(?:\.\d+)?)\s*(?:,\s*|\s+)(\d+(?:\.\d+)?)\s*(?:,\s*|\s+)(\d+(?:\.\d+)?)/i.exec(
37
+ value.trim(),
38
+ );
39
+ if (!rgb) return null;
40
+ const channels = rgb.slice(1, 4).map((channel) => Math.round(Number(channel)));
41
+ if (channels.some((channel) => channel < 0 || channel > 255)) return null;
42
+ return rgbHex(channels[0]!, channels[1]!, channels[2]!);
43
+ }
44
+
45
+ /** Normalize any browser-valid CSS color (custom palettes may use HSL/names). */
46
+ function parseCssColor(value: string): number | null {
47
+ const direct = parseNormalizedColor(value);
48
+ if (direct !== null || typeof document === 'undefined') return direct;
49
+ if (typeof CSS !== 'undefined' && !CSS.supports('color', value)) return null;
50
+ const context = document.createElement('canvas').getContext('2d');
51
+ if (!context) return null;
52
+ context.fillStyle = '#010203';
53
+ context.fillStyle = value;
54
+ return parseNormalizedColor(String(context.fillStyle));
55
+ }
56
+
57
+ function themeRoot(element?: Element | null): Element | null {
58
+ if (typeof document === 'undefined') return null;
59
+ return (
60
+ element?.closest(`.${EDITOR_THEME_CLASS}`) ?? document.querySelector(`.${EDITOR_THEME_CLASS}`)
61
+ );
62
+ }
63
+
64
+ function dimColor(color: number): number {
65
+ const red = Math.round(((color >> 16) & 0xff) * 0.42);
66
+ const green = Math.round(((color >> 8) & 0xff) * 0.42);
67
+ const blue = Math.round((color & 0xff) * 0.42);
68
+ return rgbHex(red, green, blue);
69
+ }
70
+
71
+ /** Current palette accent, with a same-hue dim variant for occluded 3D edges. */
72
+ function themeToken(root: Element | null, name: string): string {
73
+ return root && typeof getComputedStyle !== 'undefined'
74
+ ? getComputedStyle(root).getPropertyValue(name).trim()
75
+ : '';
76
+ }
77
+
78
+ /**
79
+ * THE STAGE'S COLOURS ARE THE WORKBENCH'S FIRST. Under the Code-OSS frame each is a theme
80
+ * colour (`volter.viewport.*`, `volter.gizmo.*`, the frame's `volterColors.ts`) the look sets and a
81
+ * person's `workbench.colorCustomizations` override, emitted as `--vscode-<id>` with dots as
82
+ * dashes; the page's own token is what the look said, read where there is no workbench.
83
+ */
84
+ const WORKBENCH_COLOR: Readonly<Record<string, string>> = {
85
+ '--volter-viewport-background': '--vscode-volter-viewport-background',
86
+ '--volter-viewport-grid': '--vscode-volter-viewport-grid',
87
+ '--volter-viewport-axis-x': '--vscode-volter-viewport-axisX',
88
+ '--volter-viewport-axis-y': '--vscode-volter-viewport-axisY',
89
+ '--volter-viewport-axis-z': '--vscode-volter-viewport-axisZ',
90
+ '--volter-viewport-selection': '--vscode-volter-viewport-selection',
91
+ '--volter-viewport-active': '--vscode-volter-viewport-active',
92
+ '--volter-viewport-wire': '--vscode-volter-viewport-wire',
93
+ '--volter-gizmo-x': '--vscode-volter-gizmo-x',
94
+ '--volter-gizmo-y': '--vscode-volter-gizmo-y',
95
+ '--volter-gizmo-z': '--vscode-volter-gizmo-z',
96
+ '--volter-gizmo-navigation-x': '--vscode-volter-gizmo-navigationX',
97
+ '--volter-gizmo-navigation-y': '--vscode-volter-gizmo-navigationY',
98
+ '--volter-gizmo-navigation-z': '--vscode-volter-gizmo-navigationZ',
99
+ '--volter-gizmo-hover': '--vscode-volter-gizmo-hover',
100
+ '--volter-gizmo-drag': '--vscode-volter-gizmo-drag',
101
+ };
102
+
103
+ function stageColorToken(root: Element | null, name: string): string {
104
+ const workbench = WORKBENCH_COLOR[name];
105
+ return (workbench ? themeToken(root, workbench) : '') || themeToken(root, name);
106
+ }
107
+
108
+ /** The palette's selection colour: its viewport group's when it carries one
109
+ * (Blender's orange), the accent otherwise. */
110
+ export function nativeSelectionColors(element?: Element | null): NativeSelectionColors {
111
+ const root = themeRoot(element);
112
+ const raw = stageColorToken(root, '--volter-viewport-selection') || themeToken(root, '--volter-accent');
113
+ const visible =
114
+ parseCssColor(raw || graphiteDarkEditorTheme.color.accent.default) ??
115
+ DEFAULT_NATIVE_SELECTION_COLOR;
116
+ const active = parseCssColor(stageColorToken(root, '--volter-viewport-active'));
117
+ const style = themeToken(root, '--volter-viewport-outline-style');
118
+ const width = Number.parseFloat(themeToken(root, '--volter-viewport-outline-width'));
119
+ const hidden = themeToken(root, '--volter-viewport-outline-hidden');
120
+ return {
121
+ visible,
122
+ hidden: dimColor(visible),
123
+ ...(active === null ? {} : { active: { visible: active, hidden: dimColor(active) } }),
124
+ ...(style === '' && hidden === '' && !Number.isFinite(width)
125
+ ? {}
126
+ : {
127
+ outline: {
128
+ style: style === 'crisp' ? 'crisp' : 'soft',
129
+ width: Number.isFinite(width) && width > 0 ? width : null,
130
+ hidden: hidden !== 'false',
131
+ },
132
+ }),
133
+ };
134
+ }
135
+
136
+ /** The palette's VIEWPORT GROUP (`EditorTheme.color.viewport`), each member
137
+ * `null` when the palette carries none — the viewport keeps its own then. */
138
+ export interface NativeViewportLook {
139
+ readonly background: number | null;
140
+ readonly grid: number | null;
141
+ readonly axisX: number | null;
142
+ readonly axisY: number | null;
143
+ readonly axisZ: number | null;
144
+ /** `stage.axisLineWidth`, device px, or `null` for the editor's own. */
145
+ readonly axisLineWidth: number | null;
146
+ readonly active: number | null;
147
+ }
148
+
149
+ /**
150
+ * Whether the ACTIVE LOOK declares a `color.viewport` group at all — the
151
+ * question "is the backdrop the look's, or the editor's own?"
152
+ * (ARCHITECTURE-CORE §A model is data: a data subject opens in an isolation
153
+ * scene whose story is the studio, and the studio's backdrop is the editor's;
154
+ * a look that paints the viewport itself — Blender's flat grey — has already
155
+ * answered, and the studio must not paint over it).
156
+ *
157
+ * `background` alone is the whole test because the group is ALL-OR-NOTHING:
158
+ * `EditorTheme.color.viewport` makes every member required, and a palette
159
+ * DOCUMENT that carries a partial group is rejected by name at parse
160
+ * (`theme-library.ts`'s viewport reconstruction). So the group is present
161
+ * exactly when this token paints.
162
+ */
163
+ export function lookDeclaresViewportColors(element?: Element | null): boolean {
164
+ return nativeViewportLook(element).background !== null;
165
+ }
166
+
167
+ /** Whether the look paints its viewport LIGHT (relative luminance above one half). The ink that
168
+ * reads over a declared viewport is the palette's `content.onAccent` on a dark one (Blender's
169
+ * white over its grey) and its ordinary `content.primary` on a light one (ink over
170
+ * paper), where the on-accent ink is the same colour as the ground. */
171
+ export function lookPaintsLightViewport(element?: Element | null): boolean {
172
+ const background = nativeViewportLook(element).background;
173
+ if (background === null) return false;
174
+ const r = (background >> 16) & 0xff, g = (background >> 8) & 0xff, b = background & 0xff;
175
+ return (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255 > 0.5;
176
+ }
177
+
178
+ export function nativeViewportLook(element?: Element | null): NativeViewportLook {
179
+ const root = themeRoot(element);
180
+ const read = (name: string): number | null => {
181
+ const raw = stageColorToken(root, name);
182
+ return raw ? parseCssColor(raw) : null;
183
+ };
184
+ return {
185
+ background: read('--volter-viewport-background'),
186
+ grid: read('--volter-viewport-grid'),
187
+ axisX: read('--volter-viewport-axis-x'),
188
+ axisY: read('--volter-viewport-axis-y'),
189
+ axisZ: read('--volter-viewport-axis-z'),
190
+ axisLineWidth: (() => {
191
+ const raw = themeToken(root, '--volter-viewport-axis-line-width');
192
+ const value = raw ? Number.parseFloat(raw) : Number.NaN;
193
+ return Number.isFinite(value) ? value : null;
194
+ })(),
195
+ active: read('--volter-viewport-active'),
196
+ };
197
+ }
198
+
199
+ /** THE LOOK'S GIZMO COLOURS AND HIGHLIGHT (`EditorTheme.color.gizmo`, and
200
+ * `stage.gizmoOpacity`/`gizmoHighlightSaturation`/`gizmoHighlightValue`), each
201
+ * `null` when the look names none — the viewport keeps its own then. `axes` are X, Y, Z. */
202
+ export interface NativeGizmoLook {
203
+ readonly axes: readonly [number, number, number] | null;
204
+ /** The navigation gizmo's own X, Y, Z, or `null` to draw it in {@link axes}. */
205
+ readonly navigation: readonly [number, number, number] | null;
206
+ readonly hover: number | null;
207
+ readonly drag: number | null;
208
+ readonly opacity: number | null;
209
+ readonly arrowLength: number | null;
210
+ readonly arrowHead: number | null;
211
+ readonly ringWidth: number | null;
212
+ readonly navigationForm: 'balls' | 'godot' | 'cones' | 'triad';
213
+ /** The viewport's background, which the ball form mixes its colours toward by depth. */
214
+ readonly background: number | null;
215
+ readonly navigationSize: number | null;
216
+ readonly navigationCorner: 'top-right' | 'bottom-left';
217
+ readonly highlightSaturation: number | null;
218
+ readonly highlightValue: number | null;
219
+ }
220
+
221
+ export function nativeGizmoLook(element?: Element | null): NativeGizmoLook {
222
+ const root = themeRoot(element);
223
+ const color = (name: string): number | null => {
224
+ const raw = stageColorToken(root, name);
225
+ return raw ? parseCssColor(raw) : null;
226
+ };
227
+ const number = (name: string): number | null => {
228
+ const raw = themeToken(root, name);
229
+ if (!raw) return null;
230
+ const value = Number.parseFloat(raw);
231
+ return Number.isFinite(value) ? value : null;
232
+ };
233
+ const trio = (prefix: string): readonly [number, number, number] | null => {
234
+ const x = color(`${prefix}-x`);
235
+ const y = color(`${prefix}-y`);
236
+ const z = color(`${prefix}-z`);
237
+ return x !== null && y !== null && z !== null ? [x, y, z] : null;
238
+ };
239
+ return {
240
+ axes: trio('--volter-gizmo'),
241
+ navigation: trio('--volter-gizmo-navigation'),
242
+ hover: color('--volter-gizmo-hover'),
243
+ drag: color('--volter-gizmo-drag'),
244
+ opacity: number('--volter-viewport-gizmo-opacity'),
245
+ arrowLength: number('--volter-viewport-gizmo-arrow-length'),
246
+ arrowHead: number('--volter-viewport-gizmo-arrow-head'),
247
+ ringWidth: number('--volter-viewport-gizmo-ring-width'),
248
+ navigationSize: number('--volter-viewport-navigation-size'),
249
+ background: color('--volter-viewport-background'),
250
+ navigationForm: ((form) => (form === 'cones' || form === 'triad' || form === 'godot' ? form : 'balls'))(
251
+ themeToken(root, '--volter-viewport-navigation-gizmo'),
252
+ ),
253
+ navigationCorner:
254
+ themeToken(root, '--volter-viewport-navigation-corner') === 'bottom-left' ? 'bottom-left' : 'top-right',
255
+ highlightSaturation: number('--volter-viewport-gizmo-highlight-saturation'),
256
+ highlightValue: number('--volter-viewport-gizmo-highlight-value'),
257
+ };
258
+ }
259
+
260
+ /**
261
+ * THE LOOK'S TRANSFORM-GIZMO SIZE, in px per gizmo unit
262
+ * (`EditorTheme.stage.gizmoSize`), or `null` when the look names
263
+ * none — which is every look but Blender's, and means "keep three's own
264
+ * viewport-relative handle".
265
+ *
266
+ * Read off the emitted token for the same reason the colours above are: WebGL
267
+ * cannot consume a CSS variable, and the theme object reaching the viewport
268
+ * would be a second source for a value the stylesheet already carries.
269
+ * `editor-viewport.ts` is the one caller and it says what it does with the
270
+ * number; nothing here knows about three's units.
271
+ */
272
+ export function nativeViewportGizmoSize(element?: Element | null): number | null {
273
+ const raw = themeToken(themeRoot(element), '--volter-viewport-gizmo-size');
274
+ if (!raw) return null;
275
+ const value = Number.parseFloat(raw);
276
+ return Number.isFinite(value) && value > 0 ? value : null;
277
+ }
278
+
279
+ /** THE BOX-SELECT OUTLINE'S DASH the look states (`EditorTheme.stage.marqueeDash`), in device
280
+ * pixels, or `null` for the editor's own solid line. Its colours need no reader: the rectangle
281
+ * is DOM, so it paints `themeVars.viewport.marquee*` directly. */
282
+ export function nativeViewportMarqueeDash(element?: Element | null): number | null {
283
+ const value = Number.parseFloat(themeToken(themeRoot(element), '--volter-viewport-marquee-dash'));
284
+ return Number.isFinite(value) && value > 0 ? value : null;
285
+ }
286
+
287
+ /** THE FLOOR GRID'S LINES the look states (`EditorTheme.stage.gridLineWidth` and
288
+ * its siblings), in device pixels, with the editor's own hairline floor for any it leaves out:
289
+ * one level, one pixel, the major lines drawn like the minor. */
290
+ export function nativeViewportGrid(element?: Element | null): {
291
+ readonly lineWidth: number;
292
+ readonly majorWidth: number;
293
+ readonly majorContrast: number;
294
+ } {
295
+ const root = themeRoot(element);
296
+ const read = (name: string, fallback: number): number => {
297
+ const value = Number.parseFloat(themeToken(root, name) ?? '');
298
+ return Number.isFinite(value) && value > 0 ? value : fallback;
299
+ };
300
+ const lineWidth = read('--volter-viewport-grid-line-width', 1);
301
+ return {
302
+ lineWidth,
303
+ majorWidth: read('--volter-viewport-grid-major-width', lineWidth),
304
+ majorContrast: read('--volter-viewport-grid-major-contrast', 1),
305
+ };
306
+ }
307
+
308
+ /** HOW THE LOOK DRAWS THE SELECTION BOX MARK (`stage.selectionBox` and its width),
309
+ * with the editor's own corner brackets at 3 CSS px for what it leaves out. */
310
+ /** The selection wire's look: the palette's `viewport.wire` and `stage.wireOpacity`,
311
+ * each `null` for the editor's own (the selection colour at half opacity). */
312
+ export function nativeViewportWire(element?: Element | null): {
313
+ readonly color: number | null;
314
+ readonly opacity: number | null;
315
+ } {
316
+ const root = themeRoot(element);
317
+ const raw = stageColorToken(root, '--volter-viewport-wire');
318
+ const opacity = Number.parseFloat(themeToken(root, '--volter-viewport-wire-opacity'));
319
+ return {
320
+ color: raw ? parseCssColor(raw) : null,
321
+ opacity: Number.isFinite(opacity) ? opacity : null,
322
+ };
323
+ }
324
+
325
+ export function nativeViewportSelectionBox(element?: Element | null): {
326
+ readonly edges: boolean;
327
+ readonly lineWidth: number | null;
328
+ readonly frame: 'world' | 'object';
329
+ } {
330
+ const root = themeRoot(element);
331
+ const width = Number.parseFloat(themeToken(root, '--volter-viewport-selection-box-width'));
332
+ return {
333
+ edges: themeToken(root, '--volter-viewport-selection-box') === 'edges',
334
+ frame: themeToken(root, '--volter-viewport-selection-box-frame') === 'object' ? 'object' : 'world',
335
+ lineWidth: Number.isFinite(width) && width > 0 ? width : null,
336
+ };
337
+ }
338
+
339
+ /** THE STAGE'S OWN CHROME as the look places it (`StageContribution.chrome`), each member
340
+ * resolved to the editor's own arrangement where the look states none. */
341
+ export interface NativeViewportChrome {
342
+ readonly bar: 'none' | 'strip' | 'pills';
343
+ readonly viewName: 'text' | 'menu' | 'gizmo' | 'bar';
344
+ readonly tools: 'shelf' | 'bar-start' | 'bar-end';
345
+ readonly display: 'corner' | 'bar-start' | 'bar-end';
346
+ readonly transformControls: 'header' | 'bar';
347
+ }
348
+
349
+ /** The chrome's members as one string, a stable snapshot for `useSyncExternalStore`
350
+ * ({@link viewportChromeFromKey} reads it back). */
351
+ export function nativeViewportChromeKey(element?: Element | null): string {
352
+ const root = themeRoot(element);
353
+ return [
354
+ '--volter-viewport-chrome-bar',
355
+ '--volter-viewport-chrome-view-name',
356
+ '--volter-viewport-chrome-tools',
357
+ '--volter-viewport-chrome-display',
358
+ '--volter-viewport-chrome-transform-controls',
359
+ ]
360
+ .map((name) => themeToken(root, name))
361
+ .join('|');
362
+ }
363
+
364
+ export function viewportChromeFromKey(key: string): NativeViewportChrome {
365
+ const [bar, viewName, tools, display, transformControls] = key.split('|');
366
+ const bars = ['strip', 'pills'] as const;
367
+ const names = ['menu', 'gizmo', 'bar'] as const;
368
+ const places = ['bar-start', 'bar-end'] as const;
369
+ const pick = <T extends string>(value: string | undefined, members: readonly T[], fallback: T): T =>
370
+ members.includes(value as T) ? (value as T) : fallback;
371
+ return {
372
+ bar: pick(bar, bars, 'none'),
373
+ viewName: pick(viewName, names, 'text'),
374
+ tools: pick(tools, places, 'shelf'),
375
+ display: pick(display, places, 'corner'),
376
+ transformControls: transformControls === 'bar' ? 'bar' : 'header',
377
+ };
378
+ }
379
+
380
+ export function nativeViewportChrome(element?: Element | null): NativeViewportChrome {
381
+ return viewportChromeFromKey(nativeViewportChromeKey(element));
382
+ }
383
+
384
+ /** The key, read from the theme only when the theme changes: a stage's furniture re-renders on
385
+ * every camera move, and the tokens are computed style. */
386
+ let chromeKey: string | null = null;
387
+ function subscribeViewportChrome(listener: () => void): () => void {
388
+ return subscribeNativeSelectionTheme(null, () => {
389
+ chromeKey = nativeViewportChromeKey();
390
+ listener();
391
+ });
392
+ }
393
+ function viewportChromeSnapshot(): string {
394
+ chromeKey ??= nativeViewportChromeKey();
395
+ return chromeKey;
396
+ }
397
+
398
+ /** THE STAGE'S CONTROLS IN THE TARGET'S WORDS (`StageContribution.words`): a mode's name, or
399
+ * the helpers menu's, where the look names it; `undefined` keeps the editor's own. */
400
+ export interface NativeViewportWords {
401
+ readonly shading: Readonly<Partial<Record<string, string>>>;
402
+ readonly helpers: string | undefined;
403
+ }
404
+ let wordsKey: string | null = null;
405
+ function viewportWordsKeyNow(): string {
406
+ const root = themeRoot();
407
+ return JSON.stringify([
408
+ STAGE_WORD_MODES.map((mode) => themeToken(root, `--volter-viewport-word-${mode}`)),
409
+ themeToken(root, '--volter-viewport-word-helpers'),
410
+ ]);
411
+ }
412
+ function subscribeViewportWords(listener: () => void): () => void {
413
+ return subscribeNativeSelectionTheme(null, () => {
414
+ wordsKey = viewportWordsKeyNow();
415
+ listener();
416
+ });
417
+ }
418
+ function viewportWordsSnapshot(): string {
419
+ wordsKey ??= viewportWordsKeyNow();
420
+ return wordsKey;
421
+ }
422
+ /** The look's words for the stage's controls, following a change of look. */
423
+ export function useViewportWords(): NativeViewportWords {
424
+ const key = useSyncExternalStore(subscribeViewportWords, viewportWordsSnapshot, viewportWordsSnapshot);
425
+ return useMemo(() => {
426
+ const [modes, helpers] = JSON.parse(key) as [string[], string];
427
+ const shading: Record<string, string> = {};
428
+ STAGE_WORD_MODES.forEach((mode, index) => {
429
+ if (modes[index]) shading[mode] = modes[index];
430
+ });
431
+ return { shading, helpers: helpers || undefined };
432
+ }, [key]);
433
+ }
434
+
435
+ /** The look's stage chrome, following a change of look. */
436
+ export function useViewportChrome(): NativeViewportChrome {
437
+ const key = useSyncExternalStore(subscribeViewportChrome, viewportChromeSnapshot, viewportChromeSnapshot);
438
+ return useMemo(() => viewportChromeFromKey(key), [key]);
439
+ }
440
+
441
+ /**
442
+ * Observe the one theme root's inline token update. This includes saved theme
443
+ * changes and unsaved Theme Manager previews; neither renderer has to poll
444
+ * `getComputedStyle` on every frame.
445
+ */
446
+ export function subscribeNativeSelectionTheme(
447
+ element: Element | null | undefined,
448
+ listener: () => void,
449
+ ): () => void {
450
+ listener();
451
+ const root = themeRoot(element);
452
+ if (!root || typeof MutationObserver === 'undefined') return () => {};
453
+ const observer = new MutationObserver(listener);
454
+ observer.observe(root, { attributes: true, attributeFilter: ['style'] });
455
+ // AND THE WORKBENCH'S COLOURS, which the frame applies after the look's own tokens land and a
456
+ // person's customizations change without touching this root (`subscribeWorkbenchStageColors`).
457
+ const stopWorkbench = subscribeWorkbenchStageColors(root, listener);
458
+ return () => {
459
+ observer.disconnect();
460
+ stopWorkbench();
461
+ };
462
+ }
463
+
464
+ /**
465
+ * THE WORKBENCH'S STAGE COLOURS, watched once for every subscriber: Code-OSS writes them into a
466
+ * stylesheet in the document head, which changes for many other reasons (every stylesheet a
467
+ * module loads), so one observer reads the stage's colours once per change and wakes the
468
+ * subscribers only when they moved.
469
+ */
470
+ const workbenchListeners = new Set<() => void>();
471
+ let workbenchObserver: MutationObserver | null = null;
472
+ let workbenchSeen = '';
473
+
474
+ function subscribeWorkbenchStageColors(root: Element, listener: () => void): () => void {
475
+ const signature = () =>
476
+ Object.values(WORKBENCH_COLOR)
477
+ .map((name) => themeToken(root, name))
478
+ .join('|');
479
+ workbenchListeners.add(listener);
480
+ if (!workbenchObserver && typeof document !== 'undefined' && document.head) {
481
+ workbenchSeen = signature();
482
+ workbenchObserver = new MutationObserver(() => {
483
+ const next = signature();
484
+ if (next === workbenchSeen) return;
485
+ workbenchSeen = next;
486
+ for (const each of [...workbenchListeners]) each();
487
+ });
488
+ workbenchObserver.observe(document.head, { childList: true, subtree: true, characterData: true });
489
+ }
490
+ return () => {
491
+ workbenchListeners.delete(listener);
492
+ if (workbenchListeners.size === 0 && workbenchObserver) {
493
+ workbenchObserver.disconnect();
494
+ workbenchObserver = null;
495
+ }
496
+ };
497
+ }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * WHAT THE ASSET LAB 3D DOCUMENT ASKS THE SHELL — the one collaborator
3
+ * `StageHost.tsx` (with its toolbar) declares and the shell
4
+ * installs at boot.
5
+ *
6
+ * ARCHITECTURE-CORE §Editor chrome, "The viewport stack is separable": a
7
+ * surface below the shell never imports the shell's transport, a world
8
+ * authoring adapter, or project discovery. The 3D document was importing four
9
+ * modules to answer three questions —
10
+ *
11
+ * · where do this document's own bytes go? (`object3d-document-persistence`
12
+ * → project file history → the resource history backend)
13
+ * · how do I replace a whole SOURCE file? (`ui-source/tier-source-write-backend`
14
+ * for the tier's recorder + `history/source-history-backend` to run it)
15
+ * · where does a thumbnail framing get recorded? (`asset-workflow/thumbnail-system`
16
+ * to read `.volter/thumbnails.json` + `components/asset-editor-persistence`
17
+ * to write it, which reaches `editor-api.ts`)
18
+ *
19
+ * — and every one of those is TRANSPORT. Measured, those edges were 72 of the
20
+ * document's 213 files, all of them behind the server SDK barrel; the document
21
+ * itself only ever needed "hand these bytes to the project and tell me whether
22
+ * one moved".
23
+ *
24
+ * ## The default is the NO-SHELL answer, and it is deliberate
25
+ *
26
+ * {@link DEFAULT_OBJECT3D_DOCUMENT_WRITE_POLICY} is what a document mounted
27
+ * with no shell above it (a bounded host; a fixture) gets: there is no
28
+ * project to write to, so each member REFUSES by name rather than
29
+ * half-answering. Every call site here already renders a refusal — the
30
+ * document's error state, the toolbar's error banner — because the same
31
+ * refusal is what a read-only tier produced before this seam existed
32
+ * ("This editor tier cannot write project source").
33
+ *
34
+ * In the editor the shell policy is installed once by `EditorProvider`
35
+ * (`EditorContext.tsx`), beside the viewport policy and before any document
36
+ * mounts, so today's behaviour is unchanged.
37
+ */
38
+
39
+ import type {
40
+ Object3DDocumentPersistenceSession,
41
+ OpenObject3DDocumentPersistenceOptions,
42
+ } from './authoring/object3d-document-persistence';
43
+ import type { HistoryService } from '@volter/sdk/kit/history/history-service';
44
+
45
+ /** Re-exported from its declaration site so a consumer of this seam does not
46
+ * import the persistence module (which reaches project file history) for a
47
+ * type. `import type` is erased, so this costs the closure nothing. */
48
+ export type { Object3DDocumentPersistenceSession } from './authoring/object3d-document-persistence';
49
+
50
+ /** A whole-file SOURCE replacement — the document's animation binding and its
51
+ * single-module documents both write this way. */
52
+ export interface Object3DDocumentSourceReplacement {
53
+ readonly file: string;
54
+ readonly source: string;
55
+ readonly label: string;
56
+ }
57
+
58
+ /** The camera framing `.volter/thumbnails.json` records for one asset.
59
+ * `undefined` is the RESET — remove this asset's framing. */
60
+ export interface Object3DDocumentThumbnailFraming {
61
+ readonly position: [number, number, number];
62
+ readonly target: [number, number, number];
63
+ readonly fov?: number;
64
+ }
65
+
66
+ export interface Object3DDocumentWritePolicy {
67
+ /**
68
+ * Open the persistence baseline for a document that declares a binding.
69
+ * The session owns transaction ordering, checksum preflight and canonical
70
+ * undo/redo; the document only calls `commit`.
71
+ */
72
+ openPersistence<TDocument>(
73
+ options: OpenObject3DDocumentPersistenceOptions<TDocument>,
74
+ ): Promise<Object3DDocumentPersistenceSession<TDocument>>;
75
+ /**
76
+ * Replace a whole source file through the tier's recorder, in `history`.
77
+ * Resolves to whether a byte actually moved. The HISTORY lookup stays with
78
+ * the document (it holds the session's service already, and its two call
79
+ * sites word an absent one differently); what the shell owns here is the
80
+ * WRITE BACKEND — the thing a read-only tier does not have.
81
+ */
82
+ replaceSource(
83
+ history: HistoryService,
84
+ request: Object3DDocumentSourceReplacement,
85
+ ): Promise<boolean>;
86
+ /**
87
+ * Record (or clear, with `undefined`) this asset's thumbnail framing in the
88
+ * project's thumbnail manifest. Refuses loudly rather than rebuilding a
89
+ * manifest it could not read.
90
+ */
91
+ saveThumbnailFraming(
92
+ assetPath: string,
93
+ framing: Object3DDocumentThumbnailFraming | undefined,
94
+ ): Promise<void>;
95
+ }
96
+
97
+ /** The one refusal, worded for the member that raised it. Rejected rather than
98
+ * thrown so every member answers the same way; each call site is already
99
+ * inside the `await` of a try/catch that renders the message. */
100
+ function refuse<T>(what: string): Promise<T> {
101
+ return Promise.reject(new Error(`This editor tier cannot ${what}.`));
102
+ }
103
+
104
+ export const DEFAULT_OBJECT3D_DOCUMENT_WRITE_POLICY: Object3DDocumentWritePolicy = {
105
+ openPersistence: () => refuse('persist Asset Lab documents'),
106
+ // The exact wording a read-only tier produced when the document asked the
107
+ // tier recorder for a source-write backend and got none.
108
+ replaceSource: () => refuse('write project source'),
109
+ saveThumbnailFraming: () => refuse('write project thumbnail framing'),
110
+ };
111
+
112
+ let _policy: Object3DDocumentWritePolicy = DEFAULT_OBJECT3D_DOCUMENT_WRITE_POLICY;
113
+
114
+ /**
115
+ * Install the shell's composition. One owner, same rule as
116
+ * `installViewportAuthoringPolicy` and the store's `attachHistory`:
117
+ * re-installing the SAME policy is a no-op (React strict-mode double-invokes
118
+ * the provider body), a DIFFERENT one throws rather than letting two shells
119
+ * disagree about where a document's bytes go.
120
+ */
121
+ export function installObject3DDocumentWritePolicy(policy: Object3DDocumentWritePolicy): void {
122
+ if (_policy === policy) return;
123
+ if (_policy !== DEFAULT_OBJECT3D_DOCUMENT_WRITE_POLICY) {
124
+ throw new Error('An Object3D document write policy is already installed.');
125
+ }
126
+ _policy = policy;
127
+ }
128
+
129
+ /** The installed policy, or the no-shell default. */
130
+ export function object3DDocumentWritePolicy(): Object3DDocumentWritePolicy {
131
+ return _policy;
132
+ }
133
+
134
+ /** Test seam: drop the installed policy. */
135
+ export function __resetObject3DDocumentWritePolicyForTest(): void {
136
+ _policy = DEFAULT_OBJECT3D_DOCUMENT_WRITE_POLICY;
137
+ }