@volter/sdk 0.0.0-stage → 0.5.204
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +1168 -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 +329 -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 +669 -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,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* H2, third half — honest gizmo refusal.
|
|
3
|
+
*
|
|
4
|
+
* WHY THE TRIGGER IS TOOL ACTIVATION AND NOT DRAG-START. The design record
|
|
5
|
+
* says "attempting to drag a refused node shows a transient hint". Read
|
|
6
|
+
* against the code, a literal drag-start trigger is unreachable: a fully
|
|
7
|
+
* refused selection never gets a gizmo in the first place —
|
|
8
|
+
* `EditorViewport.syncFromStore` computes `selectedTransformWritable` and
|
|
9
|
+
* calls `this.detach()` (editor-viewport.ts, the `attach`/`detach` branch), so
|
|
10
|
+
* `TransformControls` fires no `dragging-changed`: there is nothing attached
|
|
11
|
+
* to drag. THAT detach is the exact spot where the silence lives.
|
|
12
|
+
*
|
|
13
|
+
* The earliest point at which the user has made a real, unambiguous attempt to
|
|
14
|
+
* transform — as opposed to merely selecting something — is therefore ARMING
|
|
15
|
+
* the move/rotate/scale tool (W/E/R, the toolbar's mode buttons, the command
|
|
16
|
+
* palette's Translate/Rotate/Scale Mode actions) while that refused selection
|
|
17
|
+
* is live. That is the second trigger the brief explicitly allows, and
|
|
18
|
+
* it is what this module implements. Every UI mode-switch call site routes
|
|
19
|
+
* through {@link requestTransformMode} instead of `store.setTransformMode`.
|
|
20
|
+
* (The programmatic `command-listener` path deliberately does not: an
|
|
21
|
+
* automated `set-transform-mode` command is not a user attempt, and a headless
|
|
22
|
+
* caller has no viewport to read a hint in.)
|
|
23
|
+
*
|
|
24
|
+
* The hint text is the adapter's own `reason`, verbatim — the same sentence
|
|
25
|
+
* the hierarchy lock tooltip and the inspector field show (doctrine rule 2).
|
|
26
|
+
* When an adapter refuses without giving a reason we show NOTHING rather than
|
|
27
|
+
* invent a sentence to paraphrase it with.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { resolvePanelAuthoring } from './authoring/panel-authoring';
|
|
31
|
+
import { stageDocument } from './stage-store-registry';
|
|
32
|
+
import { workspaceDocumentSelection } from './workspace-document-registry';
|
|
33
|
+
import type { TransformMode } from '@volter/sdk/kit/shell-store';
|
|
34
|
+
import type { ShellStore } from '@volter/sdk/kit/shell-store';
|
|
35
|
+
import { transformLockSummary } from '@volter/sdk/kit/hierarchy-row-model';
|
|
36
|
+
import { showTransientHint } from '@volter/sdk/kit/transient-hint';
|
|
37
|
+
|
|
38
|
+
/** Set the transform mode, and NAME the refusal if the live selection is one
|
|
39
|
+
* the active adapter will not write. */
|
|
40
|
+
export function requestTransformMode(store: ShellStore, mode: TransformMode): void {
|
|
41
|
+
store.setTransformMode(mode);
|
|
42
|
+
// Arming SELECT is not an attempt to transform anything — it is the tool
|
|
43
|
+
// that transforms nothing (`TransformMode`'s own note) — so the refusal
|
|
44
|
+
// below, whose whole trigger is "a real, unambiguous attempt to transform",
|
|
45
|
+
// has nothing to report about it.
|
|
46
|
+
if (mode === 'select') return;
|
|
47
|
+
const ids = [...store.selectedEntityIds];
|
|
48
|
+
if (ids.length === 0) return;
|
|
49
|
+
// The adapter of the document whose stage asked (a side-by-side document's header asks about
|
|
50
|
+
// its own), else the one the panels drive: a document stage's selection holds its document's
|
|
51
|
+
// ids, which the world's composite does not own.
|
|
52
|
+
const document = stageDocument(store);
|
|
53
|
+
const adapter =
|
|
54
|
+
(document === null ? null : workspaceDocumentSelection(document)?.adapter) ?? resolvePanelAuthoring(store).adapter;
|
|
55
|
+
const editability = adapter.transforms?.editability;
|
|
56
|
+
if (!editability) return;
|
|
57
|
+
let reason: string | undefined;
|
|
58
|
+
for (const id of ids) {
|
|
59
|
+
const summary = transformLockSummary((channel) => editability(id, channel));
|
|
60
|
+
// Anything movable in the selection means the gesture is not refused —
|
|
61
|
+
// the gizmo attaches and moves what it can.
|
|
62
|
+
if (!summary.locked) return;
|
|
63
|
+
reason ??= summary.reason;
|
|
64
|
+
}
|
|
65
|
+
if (reason) showTransientHint(reason);
|
|
66
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The editor's one transient, non-blocking hint channel (H2).
|
|
3
|
+
*
|
|
4
|
+
* There was no toast/notification/status-message mechanism in the editor when
|
|
5
|
+
* this landed (grepped: `toast`, `notification`, `statusMessage`, `hint` —
|
|
6
|
+
* only unrelated hits), so this is the minimal one. Deliberately: one hint at
|
|
7
|
+
* a time (a new one replaces the old), auto-dismissing, carrying nothing but
|
|
8
|
+
* a string it did not write. Blocking dialogs (`window.alert`/`prompt`) are
|
|
9
|
+
* banned in editor UI.
|
|
10
|
+
*
|
|
11
|
+
* Publisher lives here (plain module state, no React) so non-React callers —
|
|
12
|
+
* hotkeys, the action registry — can raise a hint without importing the
|
|
13
|
+
* component. `components/TransientHint.tsx` renders it.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const TRANSIENT_HINT_MS = 3000;
|
|
17
|
+
|
|
18
|
+
export interface TransientHint {
|
|
19
|
+
/** Monotonic — lets the renderer restart its animation on a repeat message. */
|
|
20
|
+
readonly id: number;
|
|
21
|
+
readonly message: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let current: TransientHint | null = null;
|
|
25
|
+
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
26
|
+
let nextId = 1;
|
|
27
|
+
const listeners = new Set<() => void>();
|
|
28
|
+
|
|
29
|
+
function emit(): void {
|
|
30
|
+
for (const listener of listeners) listener();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Show `message` for {@link TRANSIENT_HINT_MS}, replacing any live hint. */
|
|
34
|
+
export function showTransientHint(message: string): void {
|
|
35
|
+
current = { id: nextId++, message };
|
|
36
|
+
if (timer) clearTimeout(timer);
|
|
37
|
+
timer = setTimeout(() => {
|
|
38
|
+
current = null;
|
|
39
|
+
timer = null;
|
|
40
|
+
emit();
|
|
41
|
+
}, TRANSIENT_HINT_MS);
|
|
42
|
+
emit();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function dismissTransientHint(): void {
|
|
46
|
+
if (timer) clearTimeout(timer);
|
|
47
|
+
timer = null;
|
|
48
|
+
current = null;
|
|
49
|
+
emit();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const subscribeTransientHint = (listener: () => void): (() => void) => {
|
|
53
|
+
listeners.add(listener);
|
|
54
|
+
return () => {
|
|
55
|
+
listeners.delete(listener);
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const transientHint = (): TransientHint | null => current;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* A drag that ended with NOTHING accepting it says so.
|
|
63
|
+
*
|
|
64
|
+
* `dropEffect === 'none'` at `dragend` is the browser's own word that no drop
|
|
65
|
+
* target took the payload: the card was released over editor chrome (a tab
|
|
66
|
+
* strip, the toolbar, a console row) instead of the viewport or a hierarchy
|
|
67
|
+
* row. That used to be perfectly silent — no hint, no console line, nothing
|
|
68
|
+
* changed — and a verifier lost a whole round to it before checking
|
|
69
|
+
* `elementFromPoint` (2026-09-02). A human just sees "the drop did nothing".
|
|
70
|
+
*/
|
|
71
|
+
export function reportUnacceptedAssetDrop(event: { dataTransfer: DataTransfer | null }): void {
|
|
72
|
+
if (event.dataTransfer?.dropEffect !== 'none') return;
|
|
73
|
+
// Surface-neutral on purpose: the source cannot know whether the scene is
|
|
74
|
+
// three or canvas, and a 2D tester told 'the 3D view' would be misled.
|
|
75
|
+
showTransientHint(
|
|
76
|
+
'Nothing accepted that drop — release it over the scene view or a hierarchy row.',
|
|
77
|
+
);
|
|
78
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE TRANSPORT, DRAWN — the one look every stage gets over its own transport
|
|
3
|
+
* (WORK.md §The stage transport and the animation door, Step 5).
|
|
4
|
+
*
|
|
5
|
+
* It draws nothing until a subject is attached, so a stage with nothing to
|
|
6
|
+
* show at a time costs an empty render and no chrome. Blender's Timeline is a
|
|
7
|
+
* SECOND look over the same handle, not a replacement for this one: an origin
|
|
8
|
+
* decides which subjects attach, never which transport drives them.
|
|
9
|
+
*
|
|
10
|
+
* IT HOLDS NO TIME OF ITS OWN. Every value here is read from the snapshot on
|
|
11
|
+
* each notification — there is no local playhead state to drift, and no clock
|
|
12
|
+
* in this file. `validate-import-bans.mjs`'s `private-clocks` row scans this
|
|
13
|
+
* path for `requestAnimationFrame`/`performance.now` for exactly that reason.
|
|
14
|
+
*
|
|
15
|
+
* WHILE THE WORLD DRIVES (Play), it goes read-only and SAYS SO. A disabled
|
|
16
|
+
* button with no reason is the failure this avoids: the refusal the transport
|
|
17
|
+
* would throw is the sentence shown instead.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import {
|
|
21
|
+
EditorIcon,
|
|
22
|
+
editorIcons,
|
|
23
|
+
IconButton,
|
|
24
|
+
Text,
|
|
25
|
+
TextInput,
|
|
26
|
+
themeVars,
|
|
27
|
+
} from '@volter/sdk/widgets';
|
|
28
|
+
import { useCallback, useSyncExternalStore } from 'react';
|
|
29
|
+
import type { StageTransportHandle } from '../transport';
|
|
30
|
+
|
|
31
|
+
/** The speeds the strip offers. Not a free number field: a speed is a viewing
|
|
32
|
+
* choice with a few useful values, and a text box invites 0.37. */
|
|
33
|
+
const SPEEDS = [0.25, 0.5, 1, 2] as const;
|
|
34
|
+
|
|
35
|
+
function formatSeconds(seconds: number, fps: number): string {
|
|
36
|
+
const frame = Math.round(seconds * fps);
|
|
37
|
+
return `${seconds.toFixed(2)}s · f${frame}`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function TransportStrip({ transport }: { transport: StageTransportHandle | null }) {
|
|
41
|
+
const snapshot = useSyncExternalStore(
|
|
42
|
+
useCallback(
|
|
43
|
+
(listener: () => void) => (transport ? transport.subscribe(listener) : () => {}),
|
|
44
|
+
[transport],
|
|
45
|
+
),
|
|
46
|
+
useCallback(() => transport?.snapshot() ?? null, [transport]),
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (!transport || !snapshot || snapshot.activeSubject === null) return null;
|
|
50
|
+
|
|
51
|
+
const driven = snapshot.driver === 'world';
|
|
52
|
+
const playing = snapshot.playbackState === 'playing';
|
|
53
|
+
const { start, end, fps, loop } = snapshot.range;
|
|
54
|
+
const active = snapshot.subjects.find((s) => s.id === snapshot.activeSubject);
|
|
55
|
+
// Two different pickers, and they are not the same question: SUBJECTS are
|
|
56
|
+
// the several things this stage can show at a time, CLIPS are the several
|
|
57
|
+
// animations one subject has. A Blender action is a subject with no clips.
|
|
58
|
+
const subjects = snapshot.subjects.length > 1 ? snapshot.subjects : null;
|
|
59
|
+
const clips = transport.activeClips();
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<section
|
|
63
|
+
aria-label="Transport"
|
|
64
|
+
data-testid="stage-transport-strip"
|
|
65
|
+
style={{
|
|
66
|
+
display: 'flex',
|
|
67
|
+
alignItems: 'center',
|
|
68
|
+
gap: 'var(--volter-space-2)',
|
|
69
|
+
padding: 'var(--volter-space-1) var(--volter-space-3)',
|
|
70
|
+
borderTop: `var(--volter-stroke-resting) solid ${themeVars.boundary.default}`,
|
|
71
|
+
background: themeVars.surface.raised,
|
|
72
|
+
}}
|
|
73
|
+
>
|
|
74
|
+
<IconButton
|
|
75
|
+
size="compact"
|
|
76
|
+
aria-label={playing ? 'Pause' : 'Play'}
|
|
77
|
+
disabled={driven}
|
|
78
|
+
onClick={() => (playing ? transport.pause() : transport.play())}
|
|
79
|
+
>
|
|
80
|
+
<EditorIcon icon={playing ? editorIcons.transport.pause : editorIcons.transport.play} />
|
|
81
|
+
</IconButton>
|
|
82
|
+
<IconButton
|
|
83
|
+
size="compact"
|
|
84
|
+
aria-label="Stop"
|
|
85
|
+
disabled={driven}
|
|
86
|
+
onClick={() => transport.stop()}
|
|
87
|
+
>
|
|
88
|
+
<EditorIcon icon={editorIcons.transport.stop} />
|
|
89
|
+
</IconButton>
|
|
90
|
+
|
|
91
|
+
<TextInput
|
|
92
|
+
aria-label="Playhead"
|
|
93
|
+
type="range"
|
|
94
|
+
min={start}
|
|
95
|
+
max={end}
|
|
96
|
+
step={1 / fps}
|
|
97
|
+
value={snapshot.time}
|
|
98
|
+
disabled={driven}
|
|
99
|
+
onChange={(event) => transport.seek(Number(event.target.value))}
|
|
100
|
+
style={{ flex: 1 }}
|
|
101
|
+
/>
|
|
102
|
+
|
|
103
|
+
<Text as="span" variant="caption">
|
|
104
|
+
{formatSeconds(snapshot.time, fps)}
|
|
105
|
+
</Text>
|
|
106
|
+
|
|
107
|
+
{subjects ? (
|
|
108
|
+
<select
|
|
109
|
+
aria-label="Subject"
|
|
110
|
+
value={snapshot.activeSubject}
|
|
111
|
+
disabled={driven}
|
|
112
|
+
onChange={(event) => transport.setActiveSubject(event.target.value)}
|
|
113
|
+
>
|
|
114
|
+
{subjects.map((subject) => (
|
|
115
|
+
<option key={subject.id} value={subject.id}>
|
|
116
|
+
{subject.label}
|
|
117
|
+
</option>
|
|
118
|
+
))}
|
|
119
|
+
</select>
|
|
120
|
+
) : null}
|
|
121
|
+
|
|
122
|
+
{clips ? (
|
|
123
|
+
<select
|
|
124
|
+
aria-label="Clip"
|
|
125
|
+
disabled={driven}
|
|
126
|
+
onChange={(event) => transport.setActiveClip(event.target.value)}
|
|
127
|
+
>
|
|
128
|
+
{clips.map((clip) => (
|
|
129
|
+
<option key={clip.id} value={clip.id}>
|
|
130
|
+
{clip.label}
|
|
131
|
+
</option>
|
|
132
|
+
))}
|
|
133
|
+
</select>
|
|
134
|
+
) : null}
|
|
135
|
+
|
|
136
|
+
<label style={{ display: 'flex', alignItems: 'center', gap: 'var(--volter-space-1)' }}>
|
|
137
|
+
<input
|
|
138
|
+
type="checkbox"
|
|
139
|
+
checked={loop}
|
|
140
|
+
disabled={driven}
|
|
141
|
+
onChange={(event) => transport.setLoop(event.target.checked)}
|
|
142
|
+
/>
|
|
143
|
+
<Text as="span" variant="caption">
|
|
144
|
+
Loop
|
|
145
|
+
</Text>
|
|
146
|
+
</label>
|
|
147
|
+
|
|
148
|
+
<select
|
|
149
|
+
aria-label="Speed"
|
|
150
|
+
value={String(snapshot.timeScale)}
|
|
151
|
+
disabled={driven}
|
|
152
|
+
onChange={(event) => transport.setTimeScale(Number(event.target.value))}
|
|
153
|
+
>
|
|
154
|
+
{SPEEDS.map((speed) => (
|
|
155
|
+
<option key={speed} value={String(speed)}>
|
|
156
|
+
{speed}×
|
|
157
|
+
</option>
|
|
158
|
+
))}
|
|
159
|
+
</select>
|
|
160
|
+
|
|
161
|
+
{driven ? (
|
|
162
|
+
// The refusal the write verbs would throw, shown instead of a disabled
|
|
163
|
+
// control with no reason.
|
|
164
|
+
<Text as="span" variant="caption">
|
|
165
|
+
The world is driving time (Play); pause the game to scrub
|
|
166
|
+
</Text>
|
|
167
|
+
) : active ? (
|
|
168
|
+
<Text as="span" variant="caption">
|
|
169
|
+
{active.label}
|
|
170
|
+
</Text>
|
|
171
|
+
) : null}
|
|
172
|
+
</section>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A SYNCHRONOUS, source-only read of what a project's `editor/volter.adapter.ts`
|
|
5
|
+
* declares about which files belong to which SURFACE: each region's `include`
|
|
6
|
+
* globs, and the additional surfaces it `mounts` — stated either as parameters
|
|
7
|
+
* layered onto the `'manifest-roots'` rule (`regionIncludes`, what every
|
|
8
|
+
* first-party project uses) or inside an explicit `regions` list (the
|
|
9
|
+
* full-replacement form). Pure — the dev server adds
|
|
10
|
+
* the filesystem and a cache (`server/adapter-region-includes.ts`); the
|
|
11
|
+
* browser-hosted Content index reads the same file through its storage backend.
|
|
12
|
+
*
|
|
13
|
+
* WHY A STATIC READ AND NOT AN IMPORT. The adapter module's contract
|
|
14
|
+
* (`@volter/project/adapter/adapter-module`, ARCHITECTURE-CORE §The editor protocol) is
|
|
15
|
+
* that its TOP LEVEL is "a STATICALLY EVALUABLE BINDING TABLE, readable without
|
|
16
|
+
* booting the game" — plain data, closures only inside `observation[].answer`.
|
|
17
|
+
* This module takes the contract at its word for the one consumer that cannot
|
|
18
|
+
* take any other route: the OID stamping transform runs in a Vite `transform`
|
|
19
|
+
* hook, synchronously, per project `.tsx`, long before any browser-tier adapter
|
|
20
|
+
* load has happened (and in `vite build`, where none ever will). The same
|
|
21
|
+
* placement test ARCHITECTURE-CORE applies to manifest-vs-adapter fields —
|
|
22
|
+
* "readable WITHOUT EVALUATING ANY MODULE … e.g. Vite config time" — is what
|
|
23
|
+
* makes a static read of a statically-evaluable table the right instrument here
|
|
24
|
+
* rather than a second declaration home.
|
|
25
|
+
*
|
|
26
|
+
* It reads those properties and reads them literally. Anything it cannot read
|
|
27
|
+
* literally is reported as {@link AdapterRegionIncludes.unreadable} — never
|
|
28
|
+
* silently treated as "no includes", because a silently dropped declaration is
|
|
29
|
+
* indistinguishable from a declaration that worked, which is the whole failure
|
|
30
|
+
* class this rung exists to end. `packages/sdk/src/kit/project-adapter.ts` (the
|
|
31
|
+
* real loader, which IMPORTS the module) stays the validation authority: this
|
|
32
|
+
* read never accepts anything that loader would reject, it only declines to
|
|
33
|
+
* answer.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/** One ADDITIONAL mounted surface a region declares — see
|
|
37
|
+
* `@volter/project/adapter/adapter-module`'s `AdapterRegion.mounts`. */
|
|
38
|
+
export interface AdapterRegionMountDeclaration {
|
|
39
|
+
readonly surface: 'three' | 'canvas' | 'dom';
|
|
40
|
+
readonly include: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Region id -> the `include` globs it declares, and the additional surfaces it
|
|
44
|
+
* mounts. */
|
|
45
|
+
export interface AdapterRegionIncludes {
|
|
46
|
+
readonly byRegionId: ReadonlyMap<string, readonly string[]>;
|
|
47
|
+
/** Region id -> the surfaces it mounts BESIDE its manifest root's own
|
|
48
|
+
* adapter, each with the files that render on it. Read here for the same
|
|
49
|
+
* reason `include` is: it is the one place a root's second surface can be
|
|
50
|
+
* stated, and every OID/HMR/Content reader answers from the same table. */
|
|
51
|
+
readonly mountsByRegionId: ReadonlyMap<string, readonly AdapterRegionMountDeclaration[]>;
|
|
52
|
+
/**
|
|
53
|
+
* `true` when the file HAS a `regions` binding this static read could not
|
|
54
|
+
* evaluate (a spread, an imported constant, a computed value). The caller
|
|
55
|
+
* reports it; it never reads as "declares nothing".
|
|
56
|
+
*/
|
|
57
|
+
readonly unreadable: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const EMPTY_REGION_INCLUDES: AdapterRegionIncludes = {
|
|
61
|
+
byRegionId: new Map(),
|
|
62
|
+
mountsByRegionId: new Map(),
|
|
63
|
+
unreadable: false,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const UNREADABLE_REGION_INCLUDES: AdapterRegionIncludes = {
|
|
67
|
+
byRegionId: new Map(),
|
|
68
|
+
mountsByRegionId: new Map(),
|
|
69
|
+
unreadable: true,
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
function stringLiteralOf(node: ts.Node | undefined): string | undefined {
|
|
73
|
+
return node && ts.isStringLiteralLike(node) ? node.text : undefined;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function stringArrayOf(node: ts.Node | undefined): string[] | undefined {
|
|
77
|
+
if (!node || !ts.isArrayLiteralExpression(node)) return undefined;
|
|
78
|
+
const out: string[] = [];
|
|
79
|
+
for (const element of node.elements) {
|
|
80
|
+
const value = stringLiteralOf(element);
|
|
81
|
+
if (value === undefined) return undefined;
|
|
82
|
+
out.push(value);
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function propertyOf(object: ts.ObjectLiteralExpression, name: string): ts.Expression | undefined {
|
|
88
|
+
for (const member of object.properties) {
|
|
89
|
+
if (!ts.isPropertyAssignment(member)) continue;
|
|
90
|
+
const key = ts.isIdentifier(member.name)
|
|
91
|
+
? member.name.text
|
|
92
|
+
: (stringLiteralOf(member.name) ?? null);
|
|
93
|
+
if (key === name) return member.initializer;
|
|
94
|
+
}
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* What the module's default export gives this reader.
|
|
100
|
+
*
|
|
101
|
+
* The three outcomes are deliberately distinct, because two of them used to
|
|
102
|
+
* collapse into one and that collapse WAS a silent hole: `export default def`
|
|
103
|
+
* (a hoisted `const def = defineAdapter({…})`) and `defineAdapter(config)`
|
|
104
|
+
* both evaluate fine in `project-adapter.ts` — which validates the exported
|
|
105
|
+
* VALUE — while this reader saw "not a readable literal" and answered "no
|
|
106
|
+
* includes, nothing to report". The loader would honor an `include` this tier
|
|
107
|
+
* had silently dropped, which is exactly the disagreement the module docblock
|
|
108
|
+
* promises cannot happen. Both are now `'unreadable'`.
|
|
109
|
+
*/
|
|
110
|
+
type DefinitionRead =
|
|
111
|
+
/** A statically readable argument object (possibly with no `regions`). */
|
|
112
|
+
| { readonly kind: 'literal'; readonly literal: ts.ObjectLiteralExpression }
|
|
113
|
+
/** A zero-argument call — `nativeAdapter()`. The legitimate empty. */
|
|
114
|
+
| { readonly kind: 'empty' }
|
|
115
|
+
/** No default export at all: nothing here worth flagging; the loader is the
|
|
116
|
+
* validation authority and an absent adapter is the native default. */
|
|
117
|
+
| { readonly kind: 'absent' }
|
|
118
|
+
/** A default export this reader cannot evaluate but the loader can. */
|
|
119
|
+
| { readonly kind: 'unreadable' };
|
|
120
|
+
|
|
121
|
+
function readDefinition(source: ts.SourceFile): DefinitionRead {
|
|
122
|
+
for (const statement of source.statements) {
|
|
123
|
+
if (!ts.isExportAssignment(statement) || statement.isExportEquals) continue;
|
|
124
|
+
const call = statement.expression;
|
|
125
|
+
if (!ts.isCallExpression(call)) return { kind: 'unreadable' };
|
|
126
|
+
const arg = call.arguments[0];
|
|
127
|
+
if (arg === undefined) return { kind: 'empty' };
|
|
128
|
+
return ts.isObjectLiteralExpression(arg)
|
|
129
|
+
? { kind: 'literal', literal: arg }
|
|
130
|
+
: { kind: 'unreadable' };
|
|
131
|
+
}
|
|
132
|
+
return { kind: 'absent' };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Read `regions[].include` out of one adapter source. Pure — the fs half is
|
|
136
|
+
* `server/adapter-region-includes.ts`, so this is directly testable, and
|
|
137
|
+
* `adapter-region-includes-conformance.test.ts` pins it against what
|
|
138
|
+
* `parseAdapterDefinition` yields from EVALUATING the same source. */
|
|
139
|
+
export function parseAdapterRegionIncludes(code: string): AdapterRegionIncludes {
|
|
140
|
+
const source = ts.createSourceFile('editor/volter.adapter.ts', code, ts.ScriptTarget.Latest, true);
|
|
141
|
+
const definition = readDefinition(source);
|
|
142
|
+
if (definition.kind === 'unreadable') return UNREADABLE_REGION_INCLUDES;
|
|
143
|
+
if (definition.kind !== 'literal') return EMPTY_REGION_INCLUDES;
|
|
144
|
+
const regions = propertyOf(definition.literal, 'regions');
|
|
145
|
+
const overlay = propertyOf(definition.literal, 'regionIncludes');
|
|
146
|
+
const listed = regions !== undefined && !ts.isStringLiteralLike(regions);
|
|
147
|
+
// The two forms may not be combined — `defineAdapter` rejects that pairing by
|
|
148
|
+
// name, so the module never loads. This tier declines to answer rather than
|
|
149
|
+
// reporting half of an invalid table.
|
|
150
|
+
if (listed && overlay !== undefined) return UNREADABLE_REGION_INCLUDES;
|
|
151
|
+
// Absent, or the `'manifest-roots'` RULE: the derivation runs, and the
|
|
152
|
+
// declared PARAMETERS beside it are what a native project states (decision,
|
|
153
|
+
// 2026-08-17). Neither present is a real answer — pure reach — not a gap.
|
|
154
|
+
if (!listed) return overlay ? layeredIncludes(overlay) : EMPTY_REGION_INCLUDES;
|
|
155
|
+
if (!ts.isArrayLiteralExpression(regions)) return UNREADABLE_REGION_INCLUDES;
|
|
156
|
+
|
|
157
|
+
const byRegionId = new Map<string, readonly string[]>();
|
|
158
|
+
const mountsByRegionId = new Map<string, readonly AdapterRegionMountDeclaration[]>();
|
|
159
|
+
for (const element of regions.elements) {
|
|
160
|
+
if (!ts.isObjectLiteralExpression(element)) return UNREADABLE_REGION_INCLUDES;
|
|
161
|
+
const id = stringLiteralOf(propertyOf(element, 'id'));
|
|
162
|
+
if (id === undefined) return UNREADABLE_REGION_INCLUDES;
|
|
163
|
+
const include = propertyOf(element, 'include');
|
|
164
|
+
if (include !== undefined) {
|
|
165
|
+
const globs = stringArrayOf(include);
|
|
166
|
+
if (globs === undefined) return UNREADABLE_REGION_INCLUDES;
|
|
167
|
+
byRegionId.set(id, globs);
|
|
168
|
+
}
|
|
169
|
+
const mounts = propertyOf(element, 'mounts');
|
|
170
|
+
if (mounts === undefined) continue;
|
|
171
|
+
const declared = mountArrayOf(mounts);
|
|
172
|
+
if (declared === undefined) return UNREADABLE_REGION_INCLUDES;
|
|
173
|
+
mountsByRegionId.set(id, declared);
|
|
174
|
+
}
|
|
175
|
+
return { byRegionId, mountsByRegionId, unreadable: false };
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Read the LAYERED form: `regionIncludes`, the per-region parameters the
|
|
180
|
+
* `'manifest-roots'` rule takes (`@volter/project/adapter/adapter-module`'s
|
|
181
|
+
* {@link AdapterDefinition.regionIncludes}, decision 2026-08-17).
|
|
182
|
+
*
|
|
183
|
+
* Statically readable BY CONSTRUCTION — it is an object literal of object
|
|
184
|
+
* literals of string arrays, sitting beside the `regions` string in the same
|
|
185
|
+
* argument object — which is exactly why the decision put the parameters here
|
|
186
|
+
* rather than behind a builder call. Anything that is NOT that literal shape
|
|
187
|
+
* (a spread, an imported table, a computed key) is `unreadable`, on the same
|
|
188
|
+
* terms as every other shape this reader declines: the loader would honor it,
|
|
189
|
+
* so silence about it would be the drift this module exists to prevent.
|
|
190
|
+
*/
|
|
191
|
+
function layeredIncludes(node: ts.Expression): AdapterRegionIncludes {
|
|
192
|
+
if (!ts.isObjectLiteralExpression(node)) return UNREADABLE_REGION_INCLUDES;
|
|
193
|
+
const byRegionId = new Map<string, readonly string[]>();
|
|
194
|
+
const mountsByRegionId = new Map<string, readonly AdapterRegionMountDeclaration[]>();
|
|
195
|
+
for (const member of node.properties) {
|
|
196
|
+
if (!ts.isPropertyAssignment(member)) return UNREADABLE_REGION_INCLUDES;
|
|
197
|
+
const id = ts.isIdentifier(member.name) ? member.name.text : stringLiteralOf(member.name);
|
|
198
|
+
const overlay = overlayOf(member.initializer);
|
|
199
|
+
if (id === undefined || overlay === undefined) return UNREADABLE_REGION_INCLUDES;
|
|
200
|
+
if (overlay.include) byRegionId.set(id, overlay.include);
|
|
201
|
+
if (overlay.mounts) mountsByRegionId.set(id, overlay.mounts);
|
|
202
|
+
}
|
|
203
|
+
return { byRegionId, mountsByRegionId, unreadable: false };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** One `regionIncludes` entry, read literally. `undefined` for anything this
|
|
207
|
+
* reader cannot evaluate — never a partial answer. */
|
|
208
|
+
function overlayOf(
|
|
209
|
+
node: ts.Expression,
|
|
210
|
+
): { include?: string[]; mounts?: AdapterRegionMountDeclaration[] } | undefined {
|
|
211
|
+
if (!ts.isObjectLiteralExpression(node)) return undefined;
|
|
212
|
+
const includeNode = propertyOf(node, 'include');
|
|
213
|
+
const include = includeNode === undefined ? undefined : stringArrayOf(includeNode);
|
|
214
|
+
if (includeNode !== undefined && include === undefined) return undefined;
|
|
215
|
+
const mountsNode = propertyOf(node, 'mounts');
|
|
216
|
+
const mounts = mountsNode === undefined ? undefined : mountArrayOf(mountsNode);
|
|
217
|
+
if (mountsNode !== undefined && mounts === undefined) return undefined;
|
|
218
|
+
return { ...(include ? { include } : {}), ...(mounts ? { mounts } : {}) };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** Read a region's `mounts` array literally. `undefined` — not an empty list —
|
|
222
|
+
* for anything this reader cannot evaluate, so the caller reports it rather
|
|
223
|
+
* than silently dropping a surface the real loader will honor. */
|
|
224
|
+
function mountArrayOf(node: ts.Expression): AdapterRegionMountDeclaration[] | undefined {
|
|
225
|
+
if (!ts.isArrayLiteralExpression(node)) return undefined;
|
|
226
|
+
const out: AdapterRegionMountDeclaration[] = [];
|
|
227
|
+
for (const element of node.elements) {
|
|
228
|
+
if (!ts.isObjectLiteralExpression(element)) return undefined;
|
|
229
|
+
const surface = stringLiteralOf(propertyOf(element, 'surface'));
|
|
230
|
+
if (surface !== 'three' && surface !== 'canvas' && surface !== 'dom') return undefined;
|
|
231
|
+
const include = propertyOf(element, 'include');
|
|
232
|
+
if (include === undefined) return undefined;
|
|
233
|
+
const globs = stringArrayOf(include);
|
|
234
|
+
if (globs === undefined || globs.length === 0) return undefined;
|
|
235
|
+
out.push({ surface, include: globs });
|
|
236
|
+
}
|
|
237
|
+
return out;
|
|
238
|
+
}
|