@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.
- package/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +38 -3
- package/package.json +510 -4
- package/src/account.ts +210 -0
- package/src/chrome.ts +88 -0
- package/src/client.ts +1646 -0
- package/src/commands.ts +66 -0
- package/src/contributions.ts +619 -0
- package/src/css-numeric-style.ts +97 -0
- package/src/document-probe.ts +282 -0
- package/src/editor-view.ts +225 -0
- package/src/extension.ts +40 -0
- package/src/generations.ts +178 -0
- package/src/host.ts +1157 -0
- package/src/http-transport.browser.ts +14 -0
- package/src/http-transport.node.ts +19 -0
- package/src/index.ts +131 -0
- package/src/kit/CapabilityCoverageSection.tsx +185 -0
- package/src/kit/account-client.ts +333 -0
- package/src/kit/action-registry.ts +317 -0
- package/src/kit/active-product.ts +76 -0
- package/src/kit/active-project.ts +155 -0
- package/src/kit/adapter-editor-config.ts +25 -0
- package/src/kit/adapter-module.ts +7 -0
- package/src/kit/adapter-observation.ts +49 -0
- package/src/kit/animation/animation-clock.ts +479 -0
- package/src/kit/animation/stage-transport.ts +385 -0
- package/src/kit/api/assets.ts +365 -0
- package/src/kit/api/project-open.ts +355 -0
- package/src/kit/api/project-source.ts +180 -0
- package/src/kit/api/project-state.ts +110 -0
- package/src/kit/api/relay.ts +270 -0
- package/src/kit/api/themes.ts +45 -0
- package/src/kit/api-asset-library-wire.ts +45 -0
- package/src/kit/api-base.ts +10 -0
- package/src/kit/api-build.ts +99 -0
- package/src/kit/api-git-wire.ts +56 -0
- package/src/kit/api-logs.ts +92 -0
- package/src/kit/api-project-identity.ts +74 -0
- package/src/kit/api-settings.ts +36 -0
- package/src/kit/api-worktrees.ts +205 -0
- package/src/kit/asset-capabilities.ts +344 -0
- package/src/kit/asset-compare-core.ts +171 -0
- package/src/kit/asset-editor-context.tsx +101 -0
- package/src/kit/asset-events.ts +96 -0
- package/src/kit/asset-inspector-actions.ts +87 -0
- package/src/kit/asset-selection-viewer-registry.ts +113 -0
- package/src/kit/asset-selection.ts +146 -0
- package/src/kit/asset-thumbnails.ts +25 -0
- package/src/kit/asset-viewers.ts +115 -0
- package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/kit/asset-workflow/asset-ledger.ts +156 -0
- package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/kit/asset-workflow/asset-types.ts +142 -0
- package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
- package/src/kit/asset-workflow/audio-waveform.ts +22 -0
- package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/kit/asset-workflow/image-view-scale.ts +31 -0
- package/src/kit/asset-workflow/import-contract.ts +124 -0
- package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
- package/src/kit/asset-workflow/project-content.ts +288 -0
- package/src/kit/asset-workflow/project-source-index.ts +545 -0
- package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
- package/src/kit/authoring/active-adapter.ts +200 -0
- package/src/kit/authoring/active-systems.ts +422 -0
- package/src/kit/authoring/adapter-key.ts +18 -0
- package/src/kit/authoring/authoring-asset-url.ts +27 -0
- package/src/kit/authoring/bootstrap-state.ts +49 -0
- package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
- package/src/kit/authoring/canvas-scene-guides.ts +84 -0
- package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
- package/src/kit/authoring/consumer-actions.ts +531 -0
- package/src/kit/authoring/design-time-layers.ts +852 -0
- package/src/kit/authoring/design-time-mount-registry.ts +244 -0
- package/src/kit/authoring/edit-mode-authoring.ts +637 -0
- package/src/kit/authoring/empty-project-authoring.ts +22 -0
- package/src/kit/authoring/instance-source-menu.ts +135 -0
- package/src/kit/authoring/layered-pick.ts +185 -0
- package/src/kit/authoring/mounted-root-subjects.ts +146 -0
- package/src/kit/authoring/no-authoring-adapter.ts +59 -0
- package/src/kit/authoring/object3d-document-persistence.ts +122 -0
- package/src/kit/authoring/panel-authoring.ts +121 -0
- package/src/kit/authoring/project-authoring-session.ts +105 -0
- package/src/kit/authoring/provenance.ts +99 -0
- package/src/kit/authoring/react-canvas-navigation.ts +259 -0
- package/src/kit/authoring/react-design-canvas-style.ts +20 -0
- package/src/kit/authoring/react-story-board.ts +917 -0
- package/src/kit/authoring/selection-scope.ts +195 -0
- package/src/kit/authoring/shell-document-ops.ts +169 -0
- package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
- package/src/kit/authoring/story-board-presentation.ts +111 -0
- package/src/kit/authoring/three-root.ts +67 -0
- package/src/kit/authoring/viewport-tool-context.ts +73 -0
- package/src/kit/authoring/viewport-tool-owner.ts +38 -0
- package/src/kit/authoring/world-session-state.ts +101 -0
- package/src/kit/authoring-seam-evidence.ts +300 -0
- package/src/kit/availability-tick.ts +66 -0
- package/src/kit/bitmap-label.ts +120 -0
- package/src/kit/boot-routing.ts +392 -0
- package/src/kit/breakpoint-state.ts +43 -0
- package/src/kit/build-identity.ts +16 -0
- package/src/kit/bytes-codec.ts +62 -0
- package/src/kit/cancellation-reason.ts +58 -0
- package/src/kit/canvas-frames.ts +88 -0
- package/src/kit/capture-camera-pose.ts +77 -0
- package/src/kit/capture-size.ts +88 -0
- package/src/kit/chrome-registry.ts +159 -0
- package/src/kit/chrome-slot-registry.ts +91 -0
- package/src/kit/collaboration-client.ts +264 -0
- package/src/kit/collaboration-presence.ts +41 -0
- package/src/kit/command-dispatch.ts +19 -0
- package/src/kit/command-listener.ts +2182 -0
- package/src/kit/command-registry.ts +71 -0
- package/src/kit/component-board-registry.ts +205 -0
- package/src/kit/component-states-registry.ts +199 -0
- package/src/kit/components/AlignToolbar.tsx +204 -0
- package/src/kit/components/ApplicationMenus.tsx +372 -0
- package/src/kit/components/AssetEditorShell.tsx +216 -0
- package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
- package/src/kit/components/BoardRulers.tsx +354 -0
- package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
- package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
- package/src/kit/components/ChromeSlot.tsx +20 -0
- package/src/kit/components/CodeView.tsx +470 -0
- package/src/kit/components/CompactInspectorShell.tsx +39 -0
- package/src/kit/components/ConsolePanel.tsx +273 -0
- package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
- package/src/kit/components/InspectionProjection.tsx +932 -0
- package/src/kit/components/Inspector.tsx +270 -0
- package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
- package/src/kit/components/InspectorFieldsSection.tsx +290 -0
- package/src/kit/components/InspectorStoriesSection.tsx +92 -0
- package/src/kit/components/InspectorToolSection.tsx +96 -0
- package/src/kit/components/InspectorTransformSection.tsx +245 -0
- package/src/kit/components/LightExplorerPanel.tsx +433 -0
- package/src/kit/components/MediaProperties.tsx +145 -0
- package/src/kit/components/ProjectHeader.tsx +328 -0
- package/src/kit/components/ReactCanvasControls.tsx +358 -0
- package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
- package/src/kit/components/RootTextEditor.tsx +79 -0
- package/src/kit/components/SaveStatus.tsx +70 -0
- package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
- package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
- package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
- package/src/kit/components/ToolHost.tsx +380 -0
- package/src/kit/components/Toolbar.tsx +811 -0
- package/src/kit/components/TransientHint.tsx +44 -0
- package/src/kit/components/VersionControlSection.tsx +470 -0
- package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
- package/src/kit/components/VolterLogo.tsx +18 -0
- package/src/kit/components/WorktreeSwitcher.tsx +712 -0
- package/src/kit/components/account-documents.tsx +1162 -0
- package/src/kit/components/asset-documents.tsx +794 -0
- package/src/kit/components/asset-editor-persistence.ts +216 -0
- package/src/kit/components/asset-selection-section.tsx +545 -0
- package/src/kit/components/asset-thumbnails.tsx +307 -0
- package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
- package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
- package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
- package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/kit/components/asset-viewers/shader-source.ts +144 -0
- package/src/kit/components/board-guides.ts +150 -0
- package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
- package/src/kit/components/canvas-temporary-pivot.ts +34 -0
- package/src/kit/components/core-utilities.tsx +94 -0
- package/src/kit/components/inspector-preview-section.tsx +223 -0
- package/src/kit/components/inspector-revert-label.ts +20 -0
- package/src/kit/components/inspector-selection.ts +42 -0
- package/src/kit/components/inspector-stories-gating.ts +171 -0
- package/src/kit/components/inspector-transform-subject.ts +11 -0
- package/src/kit/components/inspector-transform.ts +88 -0
- package/src/kit/components/kind-documents.tsx +544 -0
- package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
- package/src/kit/components/project-tool-documents.tsx +402 -0
- package/src/kit/components/scene-documents.tsx +221 -0
- package/src/kit/components/status-contributions.tsx +407 -0
- package/src/kit/components/tool-documents.tsx +302 -0
- package/src/kit/components/tool-schema-form.tsx +262 -0
- package/src/kit/components/use-after-paint.ts +41 -0
- package/src/kit/components/use-project-image-assets.ts +86 -0
- package/src/kit/components/workspace-history.ts +32 -0
- package/src/kit/components/world-documents.tsx +570 -0
- package/src/kit/components/world-overlay-gestures.ts +1939 -0
- package/src/kit/composite-screenshot.ts +2238 -0
- package/src/kit/content-entry-source-registry.ts +184 -0
- package/src/kit/contribution-surfaces.ts +48 -0
- package/src/kit/coverage/canvas-reveal.ts +192 -0
- package/src/kit/coverage/design-time-surfaces.ts +101 -0
- package/src/kit/coverage/ontology-invariants.ts +466 -0
- package/src/kit/coverage/session-vitals.ts +503 -0
- package/src/kit/crash-null-boundary.ts +36 -0
- package/src/kit/creation-site-edit.ts +1491 -0
- package/src/kit/creation-site-registry.ts +160 -0
- package/src/kit/delegate-harness-registry.ts +134 -0
- package/src/kit/document-areas.ts +70 -0
- package/src/kit/document-context-registry.ts +193 -0
- package/src/kit/document-open-registry.ts +200 -0
- package/src/kit/document-play-extension.ts +221 -0
- package/src/kit/document-preview-source.ts +20 -0
- package/src/kit/document-renderer-session.ts +138 -0
- package/src/kit/document-stage-sessions.ts +26 -0
- package/src/kit/document-viewports.ts +120 -0
- package/src/kit/editor-api.ts +46 -0
- package/src/kit/editor-chrome-capture.ts +136 -0
- package/src/kit/editor-commands.ts +176 -0
- package/src/kit/editor-console.ts +580 -0
- package/src/kit/editor-current-view.ts +56 -0
- package/src/kit/editor-document-probe.ts +1166 -0
- package/src/kit/editor-git-client.ts +115 -0
- package/src/kit/editor-hotkeys.ts +728 -0
- package/src/kit/editor-lease-view.ts +39 -0
- package/src/kit/editor-lease.ts +415 -0
- package/src/kit/editor-mode.ts +19 -0
- package/src/kit/editor-notifications.ts +140 -0
- package/src/kit/editor-presence.ts +563 -0
- package/src/kit/editor-presentation-activity.ts +58 -0
- package/src/kit/editor-presentation-notice.ts +42 -0
- package/src/kit/editor-runtime.tsx +147 -0
- package/src/kit/editor-server-response.ts +86 -0
- package/src/kit/editor-session-attribution.ts +85 -0
- package/src/kit/editor-session-mode.ts +54 -0
- package/src/kit/editor-state-facets.ts +74 -0
- package/src/kit/editor-view-presentation.ts +777 -0
- package/src/kit/environment-images.ts +58 -0
- package/src/kit/eyedropper-session.ts +60 -0
- package/src/kit/files/file-provider.ts +62 -0
- package/src/kit/files/project-files.ts +270 -0
- package/src/kit/finders/index.ts +137 -0
- package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/kit/frame/frame-parts.ts +30 -0
- package/src/kit/framed-document-capture.ts +34 -0
- package/src/kit/game-globals-prelude.ts +143 -0
- package/src/kit/game-surface-defaults.ts +33 -0
- package/src/kit/gameplay-dom-recording.ts +318 -0
- package/src/kit/gameplay-export-state.ts +14 -0
- package/src/kit/gameplay-replay.ts +417 -0
- package/src/kit/gameplay-session-time.ts +9 -0
- package/src/kit/gameplay-sessions.ts +204 -0
- package/src/kit/hierarchy-component-marks.ts +298 -0
- package/src/kit/hierarchy-internals.ts +197 -0
- package/src/kit/hierarchy-kind-icon.ts +217 -0
- package/src/kit/hierarchy-menu-registry.ts +67 -0
- package/src/kit/hierarchy-node-rows.ts +307 -0
- package/src/kit/hierarchy-panel-view.ts +280 -0
- package/src/kit/hierarchy-projection.ts +76 -0
- package/src/kit/hierarchy-row-media.ts +45 -0
- package/src/kit/hierarchy-row-model.ts +308 -0
- package/src/kit/hierarchy-rows.ts +11 -0
- package/src/kit/hierarchy-walk.ts +86 -0
- package/src/kit/history/editor-session.ts +25 -0
- package/src/kit/history/history-commands.ts +147 -0
- package/src/kit/history/history-delegate.ts +187 -0
- package/src/kit/history/history-limit-notices.ts +43 -0
- package/src/kit/history/history-service.ts +1189 -0
- package/src/kit/history/persistence-coordinator.ts +35 -0
- package/src/kit/history/project-file-history.ts +386 -0
- package/src/kit/history/project-root-history-backends.ts +139 -0
- package/src/kit/history/resource-registry.ts +209 -0
- package/src/kit/history/snapshot-store.ts +103 -0
- package/src/kit/history/source-history-backend.ts +546 -0
- package/src/kit/history-types.ts +124 -0
- package/src/kit/hmr-registration-group.ts +67 -0
- package/src/kit/hmr-stable-react-context.ts +23 -0
- package/src/kit/hotkeys.ts +190 -0
- package/src/kit/inference-diagnostics.ts +69 -0
- package/src/kit/initial-project.ts +80 -0
- package/src/kit/inspection/active-subject.ts +571 -0
- package/src/kit/inspection/active-surface.ts +142 -0
- package/src/kit/inspection/compose-subject.ts +1055 -0
- package/src/kit/inspection/compose.ts +7 -0
- package/src/kit/inspection/display.ts +171 -0
- package/src/kit/inspection/document-subject.ts +109 -0
- package/src/kit/inspection/game-subject.ts +85 -0
- package/src/kit/inspection/null-subject.ts +119 -0
- package/src/kit/inspection/serialize.ts +357 -0
- package/src/kit/inspection/use-active-inspection.ts +180 -0
- package/src/kit/inspection-model.ts +542 -0
- package/src/kit/inspection-node-media.ts +58 -0
- package/src/kit/inspector-presentation.ts +203 -0
- package/src/kit/inspector-property-grouping.ts +64 -0
- package/src/kit/inspector-section-registry.ts +221 -0
- package/src/kit/instance-source-actions.ts +163 -0
- package/src/kit/js-heap.ts +71 -0
- package/src/kit/key-actions.ts +91 -0
- package/src/kit/keymap-presets.ts +428 -0
- package/src/kit/layout-policy.ts +31 -0
- package/src/kit/light-explorer-model.ts +134 -0
- package/src/kit/live-canvas-frame.ts +55 -0
- package/src/kit/live-document.ts +296 -0
- package/src/kit/live-gesture-lock.ts +50 -0
- package/src/kit/live-seam-evidence.ts +11 -0
- package/src/kit/live-session-registry.ts +220 -0
- package/src/kit/live-transition.ts +391 -0
- package/src/kit/manifest-project.ts +107 -0
- package/src/kit/module-fetch-diagnosis.ts +192 -0
- package/src/kit/mount-failure-report.ts +154 -0
- package/src/kit/native-selection-style.ts +497 -0
- package/src/kit/object3d-document-write-policy.ts +137 -0
- package/src/kit/packaged-runtime.ts +108 -0
- package/src/kit/palettes/maya.palette.json +57 -0
- package/src/kit/palettes/substance.palette.json +57 -0
- package/src/kit/performance-profiler.ts +367 -0
- package/src/kit/performance-sources.ts +69 -0
- package/src/kit/photograph-notice.ts +141 -0
- package/src/kit/play-boot-phase.ts +166 -0
- package/src/kit/play-camera-flight.ts +35 -0
- package/src/kit/png-encode.worker.ts +26 -0
- package/src/kit/presentation-surface.ts +248 -0
- package/src/kit/product-command.ts +90 -0
- package/src/kit/project-adapter.ts +1140 -0
- package/src/kit/project-asset-refresh.ts +23 -0
- package/src/kit/project-asset-roots.ts +68 -0
- package/src/kit/project-local-state.ts +151 -0
- package/src/kit/project-manager.ts +243 -0
- package/src/kit/project-module-changes.ts +201 -0
- package/src/kit/project-module-split.ts +270 -0
- package/src/kit/project-play-layers.ts +25 -0
- package/src/kit/project-provenance.ts +115 -0
- package/src/kit/project-ready.ts +42 -0
- package/src/kit/project-shape.ts +68 -0
- package/src/kit/project-tools.ts +107 -0
- package/src/kit/projection-types.ts +44 -0
- package/src/kit/readiness.ts +113 -0
- package/src/kit/renderer-resource-counts.ts +27 -0
- package/src/kit/reported-play-state.ts +90 -0
- package/src/kit/resolve-contributed-command.ts +14 -0
- package/src/kit/resolve-relative-specifier.ts +33 -0
- package/src/kit/retained-document-states.ts +91 -0
- package/src/kit/scene-document-plan.ts +320 -0
- package/src/kit/scene-live-open.ts +210 -0
- package/src/kit/scoped-game-css.ts +152 -0
- package/src/kit/served-url.ts +5 -0
- package/src/kit/session-close.ts +17 -0
- package/src/kit/session-tombstone.ts +127 -0
- package/src/kit/settings/settings-provider.ts +82 -0
- package/src/kit/settings-store.ts +348 -0
- package/src/kit/shell-document-state.ts +27 -0
- package/src/kit/shell-store-door.ts +45 -0
- package/src/kit/shell-store.ts +722 -0
- package/src/kit/source-conflict.ts +122 -0
- package/src/kit/stage-context.ts +377 -0
- package/src/kit/stage-invalidation.ts +25 -0
- package/src/kit/stage-store-registry.ts +69 -0
- package/src/kit/startup-failure.ts +80 -0
- package/src/kit/state-report-deferral.ts +73 -0
- package/src/kit/storage/host-files-storage.ts +97 -0
- package/src/kit/storage/http-storage.ts +174 -0
- package/src/kit/storage/index.ts +75 -0
- package/src/kit/storage/mem-storage.ts +158 -0
- package/src/kit/storage/path-lock.ts +44 -0
- package/src/kit/storage/paths.ts +26 -0
- package/src/kit/storage-types.ts +127 -0
- package/src/kit/stories/StoryPreviewMount.tsx +306 -0
- package/src/kit/stories/compose-project-stories.ts +255 -0
- package/src/kit/stories/prefabs-finder.ts +54 -0
- package/src/kit/stories/prefabs-from-stories.ts +182 -0
- package/src/kit/stories/project-story-regions.ts +24 -0
- package/src/kit/stories/story-capture.ts +579 -0
- package/src/kit/stories/story-declared-medium.ts +126 -0
- package/src/kit/stories/story-discovery.ts +176 -0
- package/src/kit/stories/story-dom-runtime.ts +78 -0
- package/src/kit/stories/story-grouping.ts +111 -0
- package/src/kit/stories/story-mount-turn.ts +27 -0
- package/src/kit/stories/story-presentation.ts +215 -0
- package/src/kit/stories/story-preview-component.ts +7 -0
- package/src/kit/stories/story-registry.ts +530 -0
- package/src/kit/stories-scope.ts +35 -0
- package/src/kit/story-document-openers.ts +36 -0
- package/src/kit/story-thumbnails.ts +47 -0
- package/src/kit/surface-keyboard.ts +101 -0
- package/src/kit/surface-state.ts +135 -0
- package/src/kit/system-seam-evidence.ts +72 -0
- package/src/kit/tab-census.ts +202 -0
- package/src/kit/tab-lifecycle-client.ts +227 -0
- package/src/kit/theme-library.ts +897 -0
- package/src/kit/theme-preference.ts +429 -0
- package/src/kit/three-viewport-presentation.ts +23 -0
- package/src/kit/tool-contribution-play.ts +74 -0
- package/src/kit/tool-loader.ts +1918 -0
- package/src/kit/transform-mode-request.ts +66 -0
- package/src/kit/transient-hint.ts +78 -0
- package/src/kit/transport-strip.tsx +174 -0
- package/src/kit/ui-source/adapter-region-includes.ts +238 -0
- package/src/kit/ui-source/file-region-resolver.ts +302 -0
- package/src/kit/ui-source/inspect.ts +775 -0
- package/src/kit/ui-source/source-write-backend.ts +605 -0
- package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
- package/src/kit/user-local-state.ts +105 -0
- package/src/kit/viewport-activation-timings.ts +840 -0
- package/src/kit/viewport-editor-controls.ts +22 -0
- package/src/kit/viewport-presentation.ts +668 -0
- package/src/kit/viewport-surface-status.tsx +55 -0
- package/src/kit/wait-until.ts +37 -0
- package/src/kit/worker-call-metrics.ts +166 -0
- package/src/kit/workspace-areas.ts +191 -0
- package/src/kit/workspace-aux-commands.ts +11 -0
- package/src/kit/workspace-available-documents.ts +142 -0
- package/src/kit/workspace-core-utilities.ts +31 -0
- package/src/kit/workspace-document-ids.ts +59 -0
- package/src/kit/workspace-document-registry.ts +624 -0
- package/src/kit/workspace-document-restore.ts +146 -0
- package/src/kit/workspace-host-commands.ts +141 -0
- package/src/kit/workspace-persistence-gate.ts +40 -0
- package/src/kit/workspace-play-utilities.ts +44 -0
- package/src/kit/workspace-presets.ts +446 -0
- package/src/kit/workspace-regions.ts +276 -0
- package/src/kit/workspace-static-panels.ts +73 -0
- package/src/kit/workspace-status-registry.ts +121 -0
- package/src/kit/workspace-storage.ts +35 -0
- package/src/kit/workspace-style.ts +226 -0
- package/src/kit/workspace-utility-commands.ts +74 -0
- package/src/kit/workspace-utility-registry.ts +263 -0
- package/src/kit/world-adoption-event.ts +23 -0
- package/src/kit/world-adoption.ts +115 -0
- package/src/kit/world-canvas-viewport-state.ts +35 -0
- package/src/kit/world-document-routing.ts +104 -0
- package/src/kit/world-pan-state.ts +198 -0
- package/src/kit/write-pipe.ts +173 -0
- package/src/layout-arrangements.ts +5 -0
- package/src/layouts.tsx +108 -0
- package/src/looks.ts +16 -0
- package/src/project/output-roots.ts +73 -0
- package/src/project/tab-census.ts +155 -0
- package/src/project-tool-catalog.ts +104 -0
- package/src/selection.tsx +107 -0
- package/src/services.ts +18 -0
- package/src/session/build-report.ts +22 -0
- package/src/session/collaboration-types.ts +262 -0
- package/src/session/command-table.ts +327 -0
- package/src/session/discovery.ts +100 -0
- package/src/session/editor-brand.ts +48 -0
- package/src/session/editor-compatibility.ts +317 -0
- package/src/session/editor-control-lifecycle.ts +68 -0
- package/src/session/editor-control-protocol.ts +5 -0
- package/src/session/entrypoint-selection-readers.ts +66 -0
- package/src/session/entrypoint-selection-source.ts +120 -0
- package/src/session/game-css-scope.ts +30 -0
- package/src/session/hosted-attachment.ts +225 -0
- package/src/session/limited-view.ts +82 -0
- package/src/session/product-create.ts +24 -0
- package/src/session/product-locator.ts +478 -0
- package/src/session/project-module-url.ts +242 -0
- package/src/session/project-serving.ts +164 -0
- package/src/session/project-upgrade.ts +403 -0
- package/src/session/registry-format.ts +210 -0
- package/src/session/relative-path-guard.ts +56 -0
- package/src/session/scoped-game-css.ts +461 -0
- package/src/session/source-glob.ts +15 -0
- package/src/session/tool-contribution-convention.ts +123 -0
- package/src/session/workbench-locator.ts +712 -0
- package/src/session.ts +41 -0
- package/src/share.ts +160 -0
- package/src/source-analysis.ts +28 -0
- package/src/source-authoring.ts +439 -0
- package/src/tools/errors.ts +91 -0
- package/src/tools/provider-execution.ts +70 -0
- package/src/tools/registry.ts +341 -0
- package/src/tools/types.ts +159 -0
- package/src/transport.ts +100 -0
- package/src/types.ts +1693 -0
- package/src/views.ts +164 -0
- package/src/widgets/design-system.ts +93 -0
- package/src/widgets/editor-appearance.ts +151 -0
- package/src/widgets/editor-material.ts +83 -0
- package/src/widgets/icon-set-registry.ts +105 -0
- package/src/widgets/index.ts +71 -0
- package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
- package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
- package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
- package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
- package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
- package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
- package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
- package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
- package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
- package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
- package/src/widgets/inspector-widgets/color-utils.ts +201 -0
- package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
- package/src/widgets/inspector-widgets/index.ts +25 -0
- package/src/widgets/inspector-widgets/shared.tsx +140 -0
- package/src/widgets/interactive-edit-scope.ts +33 -0
- package/src/widgets/patterns/Dialog.tsx +140 -0
- package/src/widgets/patterns/Fields.tsx +44 -0
- package/src/widgets/patterns/List.tsx +25 -0
- package/src/widgets/patterns/StateSurface.tsx +40 -0
- package/src/widgets/patterns/Surfaces.tsx +122 -0
- package/src/widgets/patterns/Tabs.tsx +80 -0
- package/src/widgets/patterns/Toolbar.tsx +72 -0
- package/src/widgets/patterns/Tree.tsx +72 -0
- package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
- package/src/widgets/primitives/Button.tsx +62 -0
- package/src/widgets/primitives/ColorInput.tsx +78 -0
- package/src/widgets/primitives/DraftTextInput.tsx +63 -0
- package/src/widgets/primitives/EditorIcon.tsx +157 -0
- package/src/widgets/primitives/FormControls.tsx +88 -0
- package/src/widgets/primitives/HoverPreview.tsx +96 -0
- package/src/widgets/primitives/JsonInput.tsx +113 -0
- package/src/widgets/primitives/Layout.tsx +100 -0
- package/src/widgets/primitives/Menu.tsx +161 -0
- package/src/widgets/primitives/NumberInput.tsx +169 -0
- package/src/widgets/primitives/Panel.tsx +80 -0
- package/src/widgets/primitives/SectionHeader.tsx +77 -0
- package/src/widgets/primitives/Text.tsx +54 -0
- package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
- package/src/widgets/primitives/Tooltip.tsx +204 -0
- package/src/widgets/primitives/Vec3Input.tsx +70 -0
- package/src/widgets/primitives/banner-tones.ts +32 -0
- package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
- package/src/widgets/primitives/editor-icons.ts +254 -0
- package/src/widgets/primitives/panel-header-styles.ts +42 -0
- package/src/widgets/theme.ts +2841 -0
- package/src/widgets/z-index.ts +25 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AnchoredMenu,
|
|
3
|
+
EditorIcon,
|
|
4
|
+
editorIcons,
|
|
5
|
+
MenuItem,
|
|
6
|
+
MenuTrigger,
|
|
7
|
+
MenuSeparator as Separator,
|
|
8
|
+
} from '@volter/sdk/widgets';
|
|
9
|
+
import { type RefObject, useRef, useState, useSyncExternalStore } from 'react';
|
|
10
|
+
import { getActiveAuthoring } from '@volter/sdk/kit/authoring/active-adapter';
|
|
11
|
+
import { selectAllAuthoringNodes } from '@volter/sdk/kit/authoring/shell-document-ops';
|
|
12
|
+
import { useAvailabilitySelector } from '@volter/sdk/kit/availability-tick';
|
|
13
|
+
import {
|
|
14
|
+
contributedChromeVersion,
|
|
15
|
+
contributedDisabledFingerprint,
|
|
16
|
+
contributedMenuItems,
|
|
17
|
+
subscribeContributedChrome,
|
|
18
|
+
} from '@volter/sdk/kit/chrome-registry';
|
|
19
|
+
import { openCommandPalette } from '@volter/sdk/kit/editor-commands';
|
|
20
|
+
import { editorConsole } from '@volter/sdk/kit/editor-console';
|
|
21
|
+
import { currentEditorViewUrl } from '../editor-current-view';
|
|
22
|
+
import {
|
|
23
|
+
copySelection,
|
|
24
|
+
cutSelection,
|
|
25
|
+
deleteSelection,
|
|
26
|
+
duplicateSelection,
|
|
27
|
+
pasteSelection,
|
|
28
|
+
} from '@volter/sdk/kit/editor-hotkeys';
|
|
29
|
+
import { useEditorStore, useHistoryCommandSnapshot, useHistoryCommands } from '@volter/sdk/kit/editor-runtime';
|
|
30
|
+
import { editorKeymapsVersion, subscribeEditorKeymap } from '@volter/sdk/kit/keymap-presets';
|
|
31
|
+
import { getProjectTools, subscribeProjectTools } from '@volter/sdk/kit/project-tools';
|
|
32
|
+
import { getSurfaceToolContributions, subscribeToolContributions } from '@volter/sdk/kit/tool-loader';
|
|
33
|
+
import { openUndoHistory } from '@volter/sdk/kit/workspace-aux-commands';
|
|
34
|
+
import { CORE_WORKSPACE_UTILITIES } from '@volter/sdk/kit/workspace-core-utilities';
|
|
35
|
+
import {
|
|
36
|
+
showWorkspaceStaticPanel,
|
|
37
|
+
showWorkspaceUtility,
|
|
38
|
+
toggleWorkspaceFocus,
|
|
39
|
+
} from '@volter/sdk/kit/workspace-host-commands';
|
|
40
|
+
import {
|
|
41
|
+
activeEditorWorkspace,
|
|
42
|
+
editorWorkspaces,
|
|
43
|
+
editorWorkspacesVersion,
|
|
44
|
+
setEditorWorkspace,
|
|
45
|
+
subscribeEditorWorkspace,
|
|
46
|
+
subscribeEditorWorkspaces,
|
|
47
|
+
workspaceApplies,
|
|
48
|
+
} from '@volter/sdk/kit/workspace-presets';
|
|
49
|
+
import { subscribeWorkspaceStyles, workspaceStylesVersion } from '@volter/sdk/kit/workspace-style';
|
|
50
|
+
import { toggleConsoleUtility } from '@volter/sdk/kit/workspace-utility-commands';
|
|
51
|
+
import { openProjectToolsDocument } from '@volter/sdk/kit/components/project-tool-documents';
|
|
52
|
+
import { openToolDocument } from '@volter/sdk/kit/components/tool-documents';
|
|
53
|
+
|
|
54
|
+
type MenuId = 'edit' | 'view' | 'window' | 'debug' | 'tools' | 'help';
|
|
55
|
+
|
|
56
|
+
export function ApplicationMenus() {
|
|
57
|
+
const store = useEditorStore();
|
|
58
|
+
const activeAuthoring = getActiveAuthoring(store);
|
|
59
|
+
const structure = activeAuthoring.structure;
|
|
60
|
+
const clipboardIds = [...store.selectedEntityIds];
|
|
61
|
+
const selectedId = clipboardIds[0];
|
|
62
|
+
const pasteParentId = selectedId
|
|
63
|
+
? (activeAuthoring.hierarchy.node(selectedId)?.parentId ?? null)
|
|
64
|
+
: null;
|
|
65
|
+
const history = useHistoryCommands();
|
|
66
|
+
const historySnapshot = useHistoryCommandSnapshot();
|
|
67
|
+
// DOCUMENTS AND UTILITIES BOTH: this menu is the only door onto a project's
|
|
68
|
+
// `workspace.utility` drawer tab, which registers hidden by default.
|
|
69
|
+
const tools = useSyncExternalStore(
|
|
70
|
+
subscribeToolContributions,
|
|
71
|
+
getSurfaceToolContributions,
|
|
72
|
+
getSurfaceToolContributions,
|
|
73
|
+
);
|
|
74
|
+
// The three look registries: a package's workspace, keymap or style that
|
|
75
|
+
// registers after this menu mounted still lists (WORKBENCH.md §Contribution points).
|
|
76
|
+
useSyncExternalStore(subscribeEditorWorkspaces, editorWorkspacesVersion, editorWorkspacesVersion);
|
|
77
|
+
useSyncExternalStore(subscribeEditorKeymap, editorKeymapsVersion, editorKeymapsVersion);
|
|
78
|
+
useSyncExternalStore(subscribeWorkspaceStyles, workspaceStylesVersion, workspaceStylesVersion);
|
|
79
|
+
useSyncExternalStore(
|
|
80
|
+
subscribeContributedChrome,
|
|
81
|
+
contributedChromeVersion,
|
|
82
|
+
contributedChromeVersion,
|
|
83
|
+
);
|
|
84
|
+
/** A package's items at the end of a menu (`@volter/sdk/chrome`). */
|
|
85
|
+
const contributed = (menu: 'view' | 'window' | 'debug' | 'tools' | 'help') => {
|
|
86
|
+
const items = contributedMenuItems(menu);
|
|
87
|
+
if (items.length === 0) return null;
|
|
88
|
+
return (
|
|
89
|
+
<>
|
|
90
|
+
<Separator />
|
|
91
|
+
{items.map((item) => (
|
|
92
|
+
<MenuItem
|
|
93
|
+
key={item.id}
|
|
94
|
+
{...(item.testId ? { 'data-testid': item.testId } : {})}
|
|
95
|
+
disabled={item.disabled?.({}) ?? false}
|
|
96
|
+
onSelect={choose(() => item.execute({}))}
|
|
97
|
+
>
|
|
98
|
+
{typeof item.label === 'function' ? item.label() : item.label}
|
|
99
|
+
</MenuItem>
|
|
100
|
+
))}
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
104
|
+
const commands = useSyncExternalStore(subscribeProjectTools, getProjectTools, getProjectTools);
|
|
105
|
+
const workspace = useSyncExternalStore(
|
|
106
|
+
subscribeEditorWorkspace,
|
|
107
|
+
activeEditorWorkspace,
|
|
108
|
+
activeEditorWorkspace,
|
|
109
|
+
);
|
|
110
|
+
const [open, setOpen] = useState<MenuId | null>(null);
|
|
111
|
+
// A contributed item's `disabled` (and dynamic label) is asked at render,
|
|
112
|
+
// and the point promises it may follow session state — which needs
|
|
113
|
+
// SOMETHING to re-render the bar when that state moves. Sample the answers
|
|
114
|
+
// on the shared availability tick, but only while a menu is open: closed,
|
|
115
|
+
// this costs nothing; open, an item can go live or dead under the cursor.
|
|
116
|
+
useAvailabilitySelector(() => (open ? contributedDisabledFingerprint() : ''));
|
|
117
|
+
const rootRef = useRef<HTMLDivElement>(null);
|
|
118
|
+
// ONE STABLE REF PER MENU WORD, minted on first ask. `AnchoredMenu` measures
|
|
119
|
+
// this element every layout pass, so a fresh object per render would rebuild
|
|
120
|
+
// its placement callback on every one.
|
|
121
|
+
const anchorRefs = useRef<Record<string, RefObject<HTMLDivElement | null>>>({});
|
|
122
|
+
const anchorRef = (id: MenuId): RefObject<HTMLDivElement | null> =>
|
|
123
|
+
(anchorRefs.current[id] ??= { current: null });
|
|
124
|
+
|
|
125
|
+
// NO OUTSIDE-POINTER LISTENER OF ITS OWN. `AnchoredMenu` dismisses on a press outside the open
|
|
126
|
+
// menu and its trigger (`onDismiss` below), and the menu is PORTALED out of this bar: a listener
|
|
127
|
+
// asking whether the press was inside the bar answered no for the menu's own rows and closed it
|
|
128
|
+
// on `pointerdown`, before the row's `click`. Every Edit, View and Window item then did nothing
|
|
129
|
+
// for a person (measured 2026-09-28 with a real click on the browser-substrate page).
|
|
130
|
+
|
|
131
|
+
// A command that FAILS says so in the console, as the same verb over the wire does: a click
|
|
132
|
+
// that changed nothing and said nothing reads as a dead menu.
|
|
133
|
+
const choose = (action: () => unknown | Promise<unknown>) => () => {
|
|
134
|
+
setOpen(null);
|
|
135
|
+
Promise.resolve()
|
|
136
|
+
.then(action)
|
|
137
|
+
.catch((error: unknown) =>
|
|
138
|
+
editorConsole.error(
|
|
139
|
+
`The menu command failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
140
|
+
'editor',
|
|
141
|
+
),
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
const panels: Record<MenuId, React.ReactNode> = {
|
|
145
|
+
edit: (
|
|
146
|
+
<>
|
|
147
|
+
<MenuItem
|
|
148
|
+
disabled={historySnapshot.busy || !historySnapshot.canUndo}
|
|
149
|
+
onSelect={choose(() => history.undo())}
|
|
150
|
+
>
|
|
151
|
+
{historySnapshot.undoLabel ? `Undo ${historySnapshot.undoLabel}` : 'Undo'}
|
|
152
|
+
</MenuItem>
|
|
153
|
+
<MenuItem
|
|
154
|
+
disabled={historySnapshot.busy || !historySnapshot.canRedo}
|
|
155
|
+
onSelect={choose(() => history.redo())}
|
|
156
|
+
>
|
|
157
|
+
{historySnapshot.redoLabel ? `Redo ${historySnapshot.redoLabel}` : 'Redo'}
|
|
158
|
+
</MenuItem>
|
|
159
|
+
<Separator />
|
|
160
|
+
<MenuItem onSelect={choose(openUndoHistory)}>Undo History…</MenuItem>
|
|
161
|
+
<Separator />
|
|
162
|
+
<MenuItem
|
|
163
|
+
disabled={
|
|
164
|
+
clipboardIds.length === 0 ||
|
|
165
|
+
!structure?.cut ||
|
|
166
|
+
!(structure.canCopy?.(clipboardIds) ?? true)
|
|
167
|
+
}
|
|
168
|
+
onSelect={choose(() => cutSelection(store))}
|
|
169
|
+
>
|
|
170
|
+
Cut
|
|
171
|
+
</MenuItem>
|
|
172
|
+
<MenuItem
|
|
173
|
+
disabled={
|
|
174
|
+
clipboardIds.length === 0 ||
|
|
175
|
+
!structure?.copy ||
|
|
176
|
+
!(structure.canCopy?.(clipboardIds) ?? true)
|
|
177
|
+
}
|
|
178
|
+
onSelect={choose(() => copySelection(store))}
|
|
179
|
+
>
|
|
180
|
+
Copy
|
|
181
|
+
</MenuItem>
|
|
182
|
+
<MenuItem
|
|
183
|
+
disabled={!structure?.paste || !(structure.canPaste?.(pasteParentId) ?? true)}
|
|
184
|
+
onSelect={choose(() => pasteSelection(store))}
|
|
185
|
+
>
|
|
186
|
+
Paste
|
|
187
|
+
</MenuItem>
|
|
188
|
+
<Separator />
|
|
189
|
+
<MenuItem
|
|
190
|
+
disabled={store.selectedEntityIds.size === 0}
|
|
191
|
+
onSelect={choose(() => void duplicateSelection(store))}
|
|
192
|
+
>
|
|
193
|
+
Duplicate
|
|
194
|
+
</MenuItem>
|
|
195
|
+
<MenuItem
|
|
196
|
+
disabled={store.selectedEntityIds.size === 0}
|
|
197
|
+
onSelect={choose(() => void deleteSelection(store))}
|
|
198
|
+
>
|
|
199
|
+
Delete
|
|
200
|
+
</MenuItem>
|
|
201
|
+
<Separator />
|
|
202
|
+
<MenuItem onSelect={choose(() => selectAllAuthoringNodes(store))}>Select All</MenuItem>
|
|
203
|
+
<MenuItem
|
|
204
|
+
disabled={store.selectedEntityIds.size === 0}
|
|
205
|
+
onSelect={choose(() => store.select(null))}
|
|
206
|
+
>
|
|
207
|
+
Deselect All
|
|
208
|
+
</MenuItem>
|
|
209
|
+
</>
|
|
210
|
+
),
|
|
211
|
+
view: (
|
|
212
|
+
<>
|
|
213
|
+
<MenuItem onSelect={choose(() => openCommandPalette())}>Command Palette…</MenuItem>
|
|
214
|
+
<MenuItem
|
|
215
|
+
onSelect={choose(async () => {
|
|
216
|
+
const url = currentEditorViewUrl(store);
|
|
217
|
+
try {
|
|
218
|
+
await navigator.clipboard.writeText(url);
|
|
219
|
+
editorConsole.log('Copied a link to the current editor view.', 'editor');
|
|
220
|
+
} catch (error) {
|
|
221
|
+
editorConsole.error(
|
|
222
|
+
`Could not copy the editor view link: ${error instanceof Error ? error.message : String(error)}`,
|
|
223
|
+
'editor',
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
})}
|
|
227
|
+
>
|
|
228
|
+
Copy View Link
|
|
229
|
+
</MenuItem>
|
|
230
|
+
<Separator />
|
|
231
|
+
<MenuItem onSelect={choose(toggleWorkspaceFocus)}>Toggle Focus Mode</MenuItem>
|
|
232
|
+
{contributed('view')}
|
|
233
|
+
</>
|
|
234
|
+
),
|
|
235
|
+
window: (
|
|
236
|
+
<>
|
|
237
|
+
{/* NAMED WORKSPACES (ARCHITECTURE-CORE §Editor chrome). This run IS
|
|
238
|
+
`Window → Workspace` — the ruling's switching door, with the active
|
|
239
|
+
one checked. There is deliberately no persistent picker strip, and
|
|
240
|
+
nothing else in the editor calls `setEditorWorkspace`: switching
|
|
241
|
+
happens here, through the registered actions, or through
|
|
242
|
+
`editor.workspace(id)`. */}
|
|
243
|
+
{editorWorkspaces()
|
|
244
|
+
.filter((choice) => workspaceApplies(choice.id))
|
|
245
|
+
.map((choice) => (
|
|
246
|
+
<MenuItem
|
|
247
|
+
key={choice.id}
|
|
248
|
+
role="menuitemradio"
|
|
249
|
+
aria-checked={workspace === choice.id}
|
|
250
|
+
data-testid={`workspace-${choice.id}`}
|
|
251
|
+
title={choice.description}
|
|
252
|
+
onSelect={choose(() => setEditorWorkspace(choice.id))}
|
|
253
|
+
>
|
|
254
|
+
<EditorIcon
|
|
255
|
+
icon={editorIcons.status.success}
|
|
256
|
+
style={{ opacity: workspace === choice.id ? 1 : 0 }}
|
|
257
|
+
/>
|
|
258
|
+
Workspace: {choice.title}
|
|
259
|
+
</MenuItem>
|
|
260
|
+
))}
|
|
261
|
+
<Separator />
|
|
262
|
+
<MenuItem onSelect={choose(toggleConsoleUtility)}>Console</MenuItem>
|
|
263
|
+
<MenuItem
|
|
264
|
+
onSelect={choose(() => showWorkspaceUtility(CORE_WORKSPACE_UTILITIES.lightExplorer.id))}
|
|
265
|
+
>
|
|
266
|
+
Light Explorer
|
|
267
|
+
</MenuItem>
|
|
268
|
+
<MenuItem onSelect={choose(() => showWorkspaceStaticPanel('asset-library'))}>
|
|
269
|
+
Asset Library
|
|
270
|
+
</MenuItem>
|
|
271
|
+
<MenuItem onSelect={choose(() => showWorkspaceUtility('generations'))}>
|
|
272
|
+
Generations
|
|
273
|
+
</MenuItem>
|
|
274
|
+
{contributed('window')}
|
|
275
|
+
</>
|
|
276
|
+
),
|
|
277
|
+
debug: <>{contributed('debug')}</>,
|
|
278
|
+
tools: (
|
|
279
|
+
<>
|
|
280
|
+
<MenuItem onSelect={choose(() => openProjectToolsDocument())}>
|
|
281
|
+
Project Tools…
|
|
282
|
+
{commands.tools.length > 0 ? ` (${commands.tools.length})` : ''}
|
|
283
|
+
</MenuItem>
|
|
284
|
+
<Separator />
|
|
285
|
+
{tools.length ? (
|
|
286
|
+
tools.map((tool) => {
|
|
287
|
+
return (
|
|
288
|
+
<MenuItem
|
|
289
|
+
key={tool.id}
|
|
290
|
+
onSelect={choose(() => {
|
|
291
|
+
if (tool.point === 'workspace.document') openToolDocument(tool.id);
|
|
292
|
+
else showWorkspaceUtility(`tool:${tool.id}`);
|
|
293
|
+
})}
|
|
294
|
+
>
|
|
295
|
+
{tool.title}
|
|
296
|
+
</MenuItem>
|
|
297
|
+
);
|
|
298
|
+
})
|
|
299
|
+
) : (
|
|
300
|
+
<MenuItem disabled>No custom project tools</MenuItem>
|
|
301
|
+
)}
|
|
302
|
+
{contributed('tools')}
|
|
303
|
+
</>
|
|
304
|
+
),
|
|
305
|
+
// Help holds what packages contribute to it; with nothing contributed the
|
|
306
|
+
// bar shows no Help menu rather than an empty one.
|
|
307
|
+
help: contributedMenuItems('help').length > 0 ? contributed('help') : null,
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
return (
|
|
311
|
+
<div
|
|
312
|
+
ref={rootRef}
|
|
313
|
+
data-testid="app-menubar"
|
|
314
|
+
style={{ display: 'flex', alignItems: 'stretch', marginLeft: 'var(--volter-space-2)' }}
|
|
315
|
+
>
|
|
316
|
+
{(['edit', 'view', 'window', 'debug', 'tools', 'help'] as const)
|
|
317
|
+
.filter((id) => panels[id] !== null)
|
|
318
|
+
.map((id) => (
|
|
319
|
+
<div key={id} ref={anchorRef(id)} style={{ position: 'relative' }}>
|
|
320
|
+
<MenuTrigger
|
|
321
|
+
data-testid={`app-menu-${id}`}
|
|
322
|
+
aria-haspopup="menu"
|
|
323
|
+
aria-expanded={open === id}
|
|
324
|
+
onClick={() => setOpen((current) => (current === id ? null : id))}
|
|
325
|
+
onKeyDown={(event) => {
|
|
326
|
+
if (event.key !== 'ArrowDown') return;
|
|
327
|
+
event.preventDefault();
|
|
328
|
+
setOpen(id);
|
|
329
|
+
}}
|
|
330
|
+
onPointerEnter={() => {
|
|
331
|
+
if (open) setOpen(id);
|
|
332
|
+
}}
|
|
333
|
+
style={{ textTransform: 'capitalize' }}
|
|
334
|
+
>
|
|
335
|
+
{id}
|
|
336
|
+
</MenuTrigger>
|
|
337
|
+
{open === id && (
|
|
338
|
+
/* PORTALED, NOT `position: absolute`. These words live in the app's
|
|
339
|
+
title bar, and under the Code-OSS frame that bar is the workbench's
|
|
340
|
+
own `.part.titlebar` — 26 px tall with `overflow: hidden`, as are
|
|
341
|
+
`.titlebar-container` and our host slot inside it. An absolutely
|
|
342
|
+
positioned popup was laid out correctly (190x279, every item with a
|
|
343
|
+
box) and PAINTED one row: measured 2026-09-20 on U8's walk 3, where
|
|
344
|
+
the Window menu showed `Workspace: Model` and hid eleven items.
|
|
345
|
+
`AnchoredMenu` is the same primitive the toolbar, the telemetry
|
|
346
|
+
cluster and the Object3D toolbar already use for exactly this — it
|
|
347
|
+
measures the trigger, places the menu in viewport coordinates and
|
|
348
|
+
portals it to the theme root, which is outside every clip. */
|
|
349
|
+
<AnchoredMenu
|
|
350
|
+
anchorRef={anchorRef(id)}
|
|
351
|
+
dismissBoundaryRef={anchorRef(id)}
|
|
352
|
+
align="start"
|
|
353
|
+
gap={0}
|
|
354
|
+
clamp
|
|
355
|
+
autoFocusFirst
|
|
356
|
+
onDismiss={() => {
|
|
357
|
+
const trigger = rootRef.current?.querySelector<HTMLButtonElement>(
|
|
358
|
+
`[data-testid="app-menu-${id}"]`,
|
|
359
|
+
);
|
|
360
|
+
setOpen(null);
|
|
361
|
+
requestAnimationFrame(() => trigger?.focus());
|
|
362
|
+
}}
|
|
363
|
+
style={{ minWidth: 190 }}
|
|
364
|
+
>
|
|
365
|
+
{panels[id]}
|
|
366
|
+
</AnchoredMenu>
|
|
367
|
+
)}
|
|
368
|
+
</div>
|
|
369
|
+
))}
|
|
370
|
+
</div>
|
|
371
|
+
);
|
|
372
|
+
}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The asset document shell — the frame an open asset lives in, and NOTHING
|
|
3
|
+
* about how it is inspected.
|
|
4
|
+
*
|
|
5
|
+
* "What is an asset in three.js but a hierarchical group of other three.js
|
|
6
|
+
* assets" (owner, 2026-08-07). An asset document is the three paradigm scoped
|
|
7
|
+
* to a SUBTREE — Unity's prefab-isolation mode: same viewport, same hierarchy,
|
|
8
|
+
* same inspector box, only the root changed. So the ordinary inspector rides
|
|
9
|
+
* over an asset document exactly as it rides over the scene: the same box in
|
|
10
|
+
* the same corner, draggable, minimizable, expandable to the same column, with
|
|
11
|
+
* the same per-surface preference (`inspection/display.ts` resolves it for the
|
|
12
|
+
* `asset-lab` surface like any other). This shell renders none of it.
|
|
13
|
+
*
|
|
14
|
+
* What it owns is the two things that make the document a SUBJECT PRODUCER:
|
|
15
|
+
*
|
|
16
|
+
* - it activates the asset-editor context, which is what makes the active
|
|
17
|
+
* inspection surface `asset-lab` (`inspection/active-surface.ts`);
|
|
18
|
+
* - it registers the document's SELECTION CONTEXT and publishes the
|
|
19
|
+
* document's own subject description (`inspection/document-subject.ts`).
|
|
20
|
+
*
|
|
21
|
+
* The selection context is the load-bearing half, and every asset document
|
|
22
|
+
* registers one even with nothing to select. Registering it is how a document
|
|
23
|
+
* says "I am the subject": without it the Inspector falls back to the shared
|
|
24
|
+
* entity selection, and an image viewer would show whatever was picked in the
|
|
25
|
+
* scene before it was opened. A document with live authoring of its own (the
|
|
26
|
+
* Object3D editor) passes `selection` and its picked part flows through; a
|
|
27
|
+
* document without passes nothing and gets `{adapter: null, nodeId: null}`,
|
|
28
|
+
* which resolves to its own identity floor.
|
|
29
|
+
*
|
|
30
|
+
* The identity row is where that floor lives: even a document with no sections
|
|
31
|
+
* at all says what it is, what kind it is, and where it came from — and no
|
|
32
|
+
* section of its own stands in for that row, because identity is a property of
|
|
33
|
+
* the SUBJECT (`inspection/model.ts`).
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import { type ReactNode, useEffect, useRef } from 'react';
|
|
37
|
+
import { activateAssetEditorContext } from '../asset-editor-context';
|
|
38
|
+
import { publishDocumentInspectionSubject } from '../inspection/document-subject';
|
|
39
|
+
import type { InspectionSection } from '@volter/sdk/kit/inspection-model';
|
|
40
|
+
import type { NullInspectionSubject } from '../inspection/null-subject';
|
|
41
|
+
import {
|
|
42
|
+
registerWorkspaceDocumentSelection,
|
|
43
|
+
type WorkspaceDocumentSelection,
|
|
44
|
+
} from '@volter/sdk/kit/workspace-document-registry';
|
|
45
|
+
|
|
46
|
+
/** What a document with no authoring of its own selects: itself. */
|
|
47
|
+
const DOCUMENT_IS_THE_SUBJECT: WorkspaceDocumentSelection = { adapter: null, nodeId: null };
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The part of a document subject whose change can alter the Inspector's
|
|
51
|
+
* structure. Function identities deliberately stay out of this key: render
|
|
52
|
+
* functions and field IO are read through `descriptionRef` below, so a parent
|
|
53
|
+
* render updates them without feeding the Inspector's own notification back
|
|
54
|
+
* into another publication.
|
|
55
|
+
*/
|
|
56
|
+
function subjectPublicationKey(subject: NullInspectionSubject): string {
|
|
57
|
+
return JSON.stringify({
|
|
58
|
+
id: subject.id,
|
|
59
|
+
title: subject.title,
|
|
60
|
+
hint: subject.hint,
|
|
61
|
+
kindLabel: subject.kindLabel,
|
|
62
|
+
note: subject.note,
|
|
63
|
+
sections: subject.sections.map((section) => ({
|
|
64
|
+
id: section.id,
|
|
65
|
+
title: section.title,
|
|
66
|
+
order: section.order,
|
|
67
|
+
description: section.description,
|
|
68
|
+
defaultOpen: section.defaultOpen,
|
|
69
|
+
testId: section.testId,
|
|
70
|
+
keepMounted: section.keepMounted,
|
|
71
|
+
railGroup: section.railGroup,
|
|
72
|
+
bodyKind: section.body.kind,
|
|
73
|
+
})),
|
|
74
|
+
quickActions: subject.quickActions?.map((action) => ({
|
|
75
|
+
id: action.id,
|
|
76
|
+
title: action.title,
|
|
77
|
+
label: action.label,
|
|
78
|
+
placement: action.placement,
|
|
79
|
+
pressed: action.pressed,
|
|
80
|
+
disabled: action.disabled,
|
|
81
|
+
})),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The three optional props below are spelled `?: T | undefined` rather than
|
|
87
|
+
* `?: T`, because `AssetEditorShell` PASSES ITS OWN THROUGH: under
|
|
88
|
+
* `exactOptionalPropertyTypes` an explicit `undefined` is not the same as an
|
|
89
|
+
* absent key, so `sections={sections}` on a shell whose own `sections` is
|
|
90
|
+
* optional is a type error against `?: T`. Undefined is a value this component
|
|
91
|
+
* genuinely handles (`sections ?? []`, `status &&`, `selection?.()`) — the
|
|
92
|
+
* widened type says that, where a conditional spread at the one call site would
|
|
93
|
+
* only hide it.
|
|
94
|
+
*/
|
|
95
|
+
interface AssetEditorSubjectProps {
|
|
96
|
+
documentId: string;
|
|
97
|
+
active?: boolean;
|
|
98
|
+
type: string;
|
|
99
|
+
title: string;
|
|
100
|
+
/** This document's own inspection sections, for the subject it publishes
|
|
101
|
+
* when nothing inside it is picked. Identity (name/kind/provenance) is
|
|
102
|
+
* composed from `title`/`type`/`status` — a document always has one, even
|
|
103
|
+
* with no sections at all. */
|
|
104
|
+
sections?: readonly InspectionSection[] | undefined;
|
|
105
|
+
status?: string | undefined;
|
|
106
|
+
/** What is picked INSIDE this document, for a document with authoring of
|
|
107
|
+
* its own. Read on demand (the registry calls it), so it may close over
|
|
108
|
+
* live state that changes without re-registering. */
|
|
109
|
+
selection?: (() => WorkspaceDocumentSelection | null) | undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The non-visual half of an Asset Lab document. Kept separate from the frame
|
|
114
|
+
* so project-owned contribution UIs can publish the standard subject without
|
|
115
|
+
* sending React elements across the project/editor runtime boundary.
|
|
116
|
+
*/
|
|
117
|
+
export function AssetEditorSubject({
|
|
118
|
+
documentId,
|
|
119
|
+
active = true,
|
|
120
|
+
type,
|
|
121
|
+
title,
|
|
122
|
+
sections,
|
|
123
|
+
status,
|
|
124
|
+
selection,
|
|
125
|
+
}: AssetEditorSubjectProps) {
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (!active) return;
|
|
128
|
+
return activateAssetEditorContext({
|
|
129
|
+
documentId,
|
|
130
|
+
title,
|
|
131
|
+
type,
|
|
132
|
+
...(status ? { status } : {}),
|
|
133
|
+
});
|
|
134
|
+
}, [active, documentId, status, title, type]);
|
|
135
|
+
|
|
136
|
+
// ONE owner for this document's selection context (the registry keys by
|
|
137
|
+
// document id, so a second registrant would silently displace the first and
|
|
138
|
+
// take the entry with it on unmount). The ref keeps the registration stable
|
|
139
|
+
// while the provider it delegates to is free to change every render.
|
|
140
|
+
const selectionRef = useRef(selection);
|
|
141
|
+
selectionRef.current = selection;
|
|
142
|
+
useEffect(() => {
|
|
143
|
+
if (!active) return;
|
|
144
|
+
return registerWorkspaceDocumentSelection(
|
|
145
|
+
documentId,
|
|
146
|
+
() => selectionRef.current?.() ?? DOCUMENT_IS_THE_SUBJECT,
|
|
147
|
+
);
|
|
148
|
+
}, [active, documentId]);
|
|
149
|
+
|
|
150
|
+
// The document's subject DESCRIPTION — identity plus its own sections, in
|
|
151
|
+
// the same shape every surface's `describeSubject(null)` answer takes.
|
|
152
|
+
// The latest description is read on demand, so section IO closures remain
|
|
153
|
+
// live without publishing on every render. Publishing itself notifies the
|
|
154
|
+
// Inspector; doing it after every Inspector-driven parent render creates a
|
|
155
|
+
// notification -> render -> publication loop and React eventually throws
|
|
156
|
+
// "Maximum update depth exceeded" when an Object3D prefab opens.
|
|
157
|
+
const description: NullInspectionSubject = {
|
|
158
|
+
id: documentId,
|
|
159
|
+
title,
|
|
160
|
+
// `kindLabel` is what earns the composed identity ROW, and a document
|
|
161
|
+
// always names its kind: an Asset Lab document IS a thing with a name, a
|
|
162
|
+
// type and a provenance.
|
|
163
|
+
kindLabel: type,
|
|
164
|
+
...(status ? { note: { text: status, testId: 'asset-editor-status' } } : {}),
|
|
165
|
+
sections: sections ?? [],
|
|
166
|
+
};
|
|
167
|
+
const descriptionRef = useRef(description);
|
|
168
|
+
descriptionRef.current = description;
|
|
169
|
+
const publicationKey = subjectPublicationKey(description);
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
if (!active) return;
|
|
172
|
+
return publishDocumentInspectionSubject(documentId, () => descriptionRef.current);
|
|
173
|
+
}, [active, documentId, publicationKey]);
|
|
174
|
+
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function AssetEditorShell({
|
|
179
|
+
documentId,
|
|
180
|
+
active = true,
|
|
181
|
+
type,
|
|
182
|
+
title,
|
|
183
|
+
sections,
|
|
184
|
+
status,
|
|
185
|
+
fill = false,
|
|
186
|
+
selection,
|
|
187
|
+
children,
|
|
188
|
+
}: AssetEditorSubjectProps & {
|
|
189
|
+
/** The child owns the whole viewport box and clips itself (a 3D canvas),
|
|
190
|
+
* rather than flowing and scrolling inside it. */
|
|
191
|
+
fill?: boolean;
|
|
192
|
+
children: ReactNode;
|
|
193
|
+
}) {
|
|
194
|
+
return (
|
|
195
|
+
<section
|
|
196
|
+
className="volter-asset-editor"
|
|
197
|
+
data-testid={`asset-editor:${type}`}
|
|
198
|
+
aria-label={`${title} Asset Editor`}
|
|
199
|
+
>
|
|
200
|
+
<AssetEditorSubject
|
|
201
|
+
documentId={documentId}
|
|
202
|
+
active={active}
|
|
203
|
+
type={type}
|
|
204
|
+
title={title}
|
|
205
|
+
sections={sections}
|
|
206
|
+
status={status}
|
|
207
|
+
selection={selection}
|
|
208
|
+
/>
|
|
209
|
+
<main
|
|
210
|
+
className={`volter-asset-editor__viewport${fill ? ' volter-asset-editor__viewport--fill' : ''}`}
|
|
211
|
+
>
|
|
212
|
+
{children}
|
|
213
|
+
</main>
|
|
214
|
+
</section>
|
|
215
|
+
);
|
|
216
|
+
}
|