@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,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE LIVE SESSIONS — what is running in this tab, registered by whoever
|
|
3
|
+
* mounts it (WORK.md §Play leaves the host, P1). The host never names Play,
|
|
4
|
+
* ingest or the module lane; it asks this registry "is anything live?",
|
|
5
|
+
* "is the editor playing?", "which element holds instance X?", and "stop
|
|
6
|
+
* everything" — the questions `editor-session-mode.ts`,
|
|
7
|
+
* `project-session-reset.ts`, `EditorLeaseGuard.tsx`,
|
|
8
|
+
* `RootSelectionOverlay.tsx` and `editor-view-presentation.ts` asked
|
|
9
|
+
* `play-mode.ts` by name until 2026-09-17. A package registers through
|
|
10
|
+
* `@volter/sdk/host`'s `live` member; the host's own lanes register
|
|
11
|
+
* here directly until they move.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type {
|
|
15
|
+
LiveCommand,
|
|
16
|
+
LiveCommandResult,
|
|
17
|
+
LiveCoverageReport,
|
|
18
|
+
LiveRemountArgs,
|
|
19
|
+
LiveRunWindow,
|
|
20
|
+
LiveSceneTable,
|
|
21
|
+
LiveSession,
|
|
22
|
+
} from '@volter/sdk/host';
|
|
23
|
+
|
|
24
|
+
interface Registered {
|
|
25
|
+
readonly session: LiveSession;
|
|
26
|
+
readonly seq: number;
|
|
27
|
+
}
|
|
28
|
+
let registered: Registered[] = [];
|
|
29
|
+
let seq = 0;
|
|
30
|
+
let version = 0;
|
|
31
|
+
const listeners = new Set<() => void>();
|
|
32
|
+
function notify(): void {
|
|
33
|
+
version++;
|
|
34
|
+
for (const listener of listeners) listener();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** A lane's own state moved (restart-required, its run window). */
|
|
38
|
+
export function notifyLiveSessionsChanged(): void {
|
|
39
|
+
notify();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Every registered lane, in `stop` order. */
|
|
43
|
+
export function liveSessions(): readonly LiveSession[] {
|
|
44
|
+
return ordered();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** The newest run across lanes: the greatest `startedAt` any lane reports. */
|
|
48
|
+
export function liveRunWindow(): LiveRunWindow | null {
|
|
49
|
+
let newest: LiveRunWindow | null = null;
|
|
50
|
+
for (const { session } of registered) {
|
|
51
|
+
const startedAt = session.startedAt?.() ?? null;
|
|
52
|
+
if (startedAt === null) continue;
|
|
53
|
+
if (!newest || startedAt > newest.startedAt)
|
|
54
|
+
newest = { startedAt, endedAt: session.endedAt?.() ?? null };
|
|
55
|
+
}
|
|
56
|
+
return newest;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function liveRestartRequired(): string | null {
|
|
60
|
+
for (const { session } of registered) {
|
|
61
|
+
const reason = session.restartRequired?.() ?? null;
|
|
62
|
+
if (reason !== null) return reason;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Re-enter the lane that reports a restart is required, else the first
|
|
68
|
+
* running lane that can restart. */
|
|
69
|
+
export function restartLiveSession(): void {
|
|
70
|
+
const stale = ordered().find((session) => (session.restartRequired?.() ?? null) !== null);
|
|
71
|
+
const target = stale ?? ordered().find((session) => session.mounted() && session.restart);
|
|
72
|
+
target?.restart?.();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** The canvas a mounted lane's own render pass draws, or null. */
|
|
76
|
+
export function liveFrameCanvas(): HTMLCanvasElement | null {
|
|
77
|
+
for (const session of ordered()) {
|
|
78
|
+
if (!session.mounted()) continue;
|
|
79
|
+
const canvas = session.frameCanvas?.() ?? null;
|
|
80
|
+
if (canvas) return canvas;
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The pixels of `canvas` from the lane whose render pass owns it; null when
|
|
86
|
+
* no mounted lane claims that canvas. */
|
|
87
|
+
export function snapshotLiveFrame(
|
|
88
|
+
canvas: HTMLCanvasElement,
|
|
89
|
+
): Promise<CanvasImageSource | null> | null {
|
|
90
|
+
for (const session of ordered()) {
|
|
91
|
+
if (!session.mounted() || !session.snapshotFrame) continue;
|
|
92
|
+
if (session.frameCanvas?.() === canvas) return session.snapshotFrame();
|
|
93
|
+
}
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** The first mounted lane's own answer to `cmd`, or null when none claims it. */
|
|
98
|
+
export function dispatchLiveCommand(cmd: LiveCommand): LiveCommandResult | null {
|
|
99
|
+
for (const session of ordered()) {
|
|
100
|
+
if (!session.mounted() || !session.command) continue;
|
|
101
|
+
const answered = session.command(cmd);
|
|
102
|
+
if (answered) return answered;
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* The running lane's scene entries, or null.
|
|
109
|
+
*
|
|
110
|
+
* The shape check is STRUCTURAL and stays here rather than importing a lane's
|
|
111
|
+
* own type guard (it imported the ingest lane's `isContractScenesStories`,
|
|
112
|
+
* by name, until 2026-09-18, and with it the whole `window.volterGame` contract
|
|
113
|
+
* — an INGEST vocabulary inside the registry every lane registers through).
|
|
114
|
+
* `LiveSceneTable` is a declaration, and a lane is foreign code: the
|
|
115
|
+
* host checks that the declaration is honoured before handing the table to the
|
|
116
|
+
* `open` verb, and names no lane doing it.
|
|
117
|
+
*/
|
|
118
|
+
export function liveScenes(): LiveSceneTable | null {
|
|
119
|
+
for (const session of ordered()) {
|
|
120
|
+
if (!session.mounted()) continue;
|
|
121
|
+
const scenes = session.scenes?.() ?? null;
|
|
122
|
+
if (scenes && typeof scenes.goToScene === 'function') return scenes;
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** The native surface the mounted lane's content draws on, or null. */
|
|
128
|
+
export function liveSurface(): 'three' | 'canvas' | 'dom' | null {
|
|
129
|
+
for (const session of ordered()) {
|
|
130
|
+
if (!session.mounted()) continue;
|
|
131
|
+
const surface = session.surface?.() ?? null;
|
|
132
|
+
if (surface) return surface;
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/** The mounted lane's own coverage report, or null when none grades itself. */
|
|
138
|
+
export function liveCoverage(): LiveCoverageReport | null {
|
|
139
|
+
for (const session of ordered()) {
|
|
140
|
+
if (!session.mounted()) continue;
|
|
141
|
+
const report = session.coverage?.() ?? null;
|
|
142
|
+
if (report) return report;
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Why authoring is off for the mounted lane's content, or null. */
|
|
148
|
+
export function liveAuthoringRefusal(): string | null {
|
|
149
|
+
for (const session of ordered()) {
|
|
150
|
+
if (!session.mounted()) continue;
|
|
151
|
+
const reason = session.authoringRefusal?.() ?? null;
|
|
152
|
+
if (reason !== null) return reason;
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Ask the running lane to re-mount with an authored selection; null when
|
|
158
|
+
* no running lane can. */
|
|
159
|
+
export function remountLiveSelection(
|
|
160
|
+
args: LiveRemountArgs,
|
|
161
|
+
): Promise<{ ok: true } | { ok: false; error: string }> | null {
|
|
162
|
+
const target = ordered().find((session) => session.mounted() && session.remount);
|
|
163
|
+
return target?.remount?.(args) ?? null;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Register a lane. `stop` order follows `priority` (low first), then
|
|
167
|
+
* registration: a normal stop tears down Play before ingest. */
|
|
168
|
+
export function registerLiveSession(session: LiveSession): () => void {
|
|
169
|
+
if (registered.some((entry) => entry.session.id === session.id))
|
|
170
|
+
throw new Error(`live session "${session.id}" is already registered.`);
|
|
171
|
+
const entry: Registered = { session, seq: seq++ };
|
|
172
|
+
registered = [...registered, entry];
|
|
173
|
+
notify();
|
|
174
|
+
return () => {
|
|
175
|
+
registered = registered.filter((other) => other !== entry);
|
|
176
|
+
notify();
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function ordered(): readonly LiveSession[] {
|
|
181
|
+
return [...registered]
|
|
182
|
+
.sort((a, b) => (a.session.priority ?? 0) - (b.session.priority ?? 0) || a.seq - b.seq)
|
|
183
|
+
.map((entry) => entry.session);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** A real game owns a canvas: Play, an ingested game, an auto-mounted module world. */
|
|
187
|
+
export function anyLiveSessionMounted(): boolean {
|
|
188
|
+
return ordered().some((session) => session.mounted());
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** The editor is in PLAY: somebody asked the host to run content. A held
|
|
192
|
+
* (paused-at-design-time) mount is not playing. */
|
|
193
|
+
export function anyLiveSessionPlaying(): boolean {
|
|
194
|
+
return ordered().some((session) => session.playing());
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/** Stop every lane, in priority order; each stop is idempotent and a no-op
|
|
198
|
+
* when its lane runs nothing. */
|
|
199
|
+
export function stopAllLiveSessions(): void {
|
|
200
|
+
for (const session of ordered()) session.stop();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/** The element holding a live instance — the primary when `id` is omitted —
|
|
204
|
+
* from whichever lane holds it. */
|
|
205
|
+
export function liveInstanceContainer(id?: string): HTMLElement | null {
|
|
206
|
+
for (const session of ordered()) {
|
|
207
|
+
const container = session.instanceContainer(id);
|
|
208
|
+
if (container) return container;
|
|
209
|
+
}
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function subscribeLiveSessions(listener: () => void): () => void {
|
|
214
|
+
listeners.add(listener);
|
|
215
|
+
return () => listeners.delete(listener);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function liveSessionsVersion(): number {
|
|
219
|
+
return version;
|
|
220
|
+
}
|
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE LIVE TRANSITION — the immersive Liquid Glass hand-off between
|
|
3
|
+
* authoring chrome and the running game, the host's side of
|
|
4
|
+
* `host.viewport.transition` (WORK.md §Play leaves the host, P3). A lane
|
|
5
|
+
* says when it starts (`beginLiveTransition`), when it is ready and when it
|
|
6
|
+
* ends; the host decides whether the presentation is immersive and resolves
|
|
7
|
+
* the flight target from the authored scene.
|
|
8
|
+
*
|
|
9
|
+
* On Play: the chrome dissolves, the editor viewport camera flies along a
|
|
10
|
+
* Catmull-Rom spline from the preview pose to the AUTHORED game camera's
|
|
11
|
+
* pose, and when both the flight has landed and the game runtime is ready the
|
|
12
|
+
* Scene document cross-fades into the Game document. On Stop everything
|
|
13
|
+
* reverses: camera snaps back to the pre-play preview pose and the chrome
|
|
14
|
+
* re-materializes. `prefers-reduced-motion` collapses the whole choreography
|
|
15
|
+
* to instant state changes with the same end state.
|
|
16
|
+
*
|
|
17
|
+
* Layering: this module owns TIMING, and it touches no layout at all. The
|
|
18
|
+
* camera flight is the Three integration's (`@volter/sdk/kit/play-camera-flight`,
|
|
19
|
+
* registered by `@volter/editor-threejs`'s `play-camera-flight.ts`). The LAYOUT HOST registers `hideChrome`/`showChrome` through
|
|
20
|
+
* {@link installPlayTransitionDock} — under the Code-OSS frame those are the
|
|
21
|
+
* workbench's own parts going away and coming back (`frame/bridge.tsx`'s
|
|
22
|
+
* `setImmersive`), which is the same inversion `workspace-host-commands.ts`
|
|
23
|
+
* uses for semantic commands. Workspace persistence is suppressed for the
|
|
24
|
+
* whole immersive play session (`setWorkspacePersistenceSuppressed`) so a
|
|
25
|
+
* play-time open set can never overwrite the user's own. A non-immersive play
|
|
26
|
+
* never enters this controller: it keeps the ordinary workspace visible.
|
|
27
|
+
*
|
|
28
|
+
* The pure parts — the durations, the phase reducer — are plain functions
|
|
29
|
+
* with no DOM.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { layoutPolicy } from './layout-policy';
|
|
33
|
+
import { effectiveSettings } from '@volter/sdk/kit/settings-store';
|
|
34
|
+
import { type LiveCameraLookup, playCameraFlight } from '@volter/sdk/kit/play-camera-flight';
|
|
35
|
+
import { setWorkspacePersistenceSuppressed } from './workspace-persistence-gate';
|
|
36
|
+
|
|
37
|
+
/** Full-bleed play is the MOUNTED LAYOUT's own declaration
|
|
38
|
+
* (`WorkspaceLayoutPolicy.immersivePlay` — `GameLayout` is the shipped
|
|
39
|
+
* instance); no appearance axis implies it. */
|
|
40
|
+
export function usesImmersivePlayPresentation(): boolean {
|
|
41
|
+
return (layoutPolicy()?.immersivePlay ?? false) && !effectiveSettings().play?.keepPanelsVisible;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Pure transition phase reducer
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
export type PlayTransitionPhase =
|
|
53
|
+
| 'idle'
|
|
54
|
+
/** Dissolve + flight running concurrently. */
|
|
55
|
+
| 'entering'
|
|
56
|
+
/** Flight landed but the game runtime is still booting — hold the pose. */
|
|
57
|
+
| 'holding'
|
|
58
|
+
/** Both done — Scene → Game opacity cross-fade in progress. */
|
|
59
|
+
| 'crossfade'
|
|
60
|
+
/** Hand-off complete; game owns the screen until stop. */
|
|
61
|
+
| 'playing';
|
|
62
|
+
|
|
63
|
+
export type PlayTransitionEvent =
|
|
64
|
+
| 'start'
|
|
65
|
+
| 'start-reduced'
|
|
66
|
+
| 'flight-done'
|
|
67
|
+
| 'game-ready'
|
|
68
|
+
| 'crossfade-done'
|
|
69
|
+
| 'stop';
|
|
70
|
+
|
|
71
|
+
export interface PlayTransitionState {
|
|
72
|
+
readonly phase: PlayTransitionPhase;
|
|
73
|
+
readonly flightDone: boolean;
|
|
74
|
+
readonly gameReady: boolean;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const IDLE_TRANSITION_STATE: PlayTransitionState = {
|
|
78
|
+
phase: 'idle',
|
|
79
|
+
flightDone: false,
|
|
80
|
+
gameReady: false,
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
function reduceEnteringPhase(
|
|
84
|
+
state: PlayTransitionState,
|
|
85
|
+
event: PlayTransitionEvent,
|
|
86
|
+
): PlayTransitionState {
|
|
87
|
+
const flightDone = state.flightDone || event === 'flight-done';
|
|
88
|
+
const gameReady = state.gameReady || event === 'game-ready';
|
|
89
|
+
if (flightDone && gameReady) return { phase: 'crossfade', flightDone, gameReady };
|
|
90
|
+
if (flightDone) return { phase: 'holding', flightDone, gameReady };
|
|
91
|
+
return { ...state, flightDone, gameReady };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Pure phase reducer — every timing side effect lives in the controller. */
|
|
95
|
+
export function reducePlayTransition(
|
|
96
|
+
state: PlayTransitionState,
|
|
97
|
+
event: PlayTransitionEvent,
|
|
98
|
+
): PlayTransitionState {
|
|
99
|
+
if (event === 'stop') return IDLE_TRANSITION_STATE;
|
|
100
|
+
switch (state.phase) {
|
|
101
|
+
case 'idle':
|
|
102
|
+
if (event === 'start') return { phase: 'entering', flightDone: false, gameReady: false };
|
|
103
|
+
if (event === 'start-reduced') return { phase: 'playing', flightDone: true, gameReady: true };
|
|
104
|
+
return state;
|
|
105
|
+
case 'entering':
|
|
106
|
+
return reduceEnteringPhase(state, event);
|
|
107
|
+
case 'holding':
|
|
108
|
+
if (event === 'game-ready') return { ...state, phase: 'crossfade', gameReady: true };
|
|
109
|
+
return state;
|
|
110
|
+
case 'crossfade':
|
|
111
|
+
if (event === 'crossfade-done') return { ...state, phase: 'playing' };
|
|
112
|
+
return state;
|
|
113
|
+
case 'playing':
|
|
114
|
+
return state;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
// Pure edge-reveal machine (macOS auto-hide semantics)
|
|
120
|
+
//
|
|
121
|
+
// GLOBAL reveal (owner decision, 2026-07-20): dwelling at ANY screen edge
|
|
122
|
+
// reveals ALL the play chrome together — header, hierarchy, inspector,
|
|
123
|
+
// assets, bottom bar — and it all retracts together once the pointer leaves
|
|
124
|
+
// both the hot zones and every revealed surface. Per-edge independent
|
|
125
|
+
// reveals (the original design) made the chrome feel unpredictable and
|
|
126
|
+
// forced users to hunt each panel at its own edge.
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
// ---------------------------------------------------------------------------
|
|
130
|
+
// Controller — DOM / viewport integration seams
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* THE TRANSITION'S DURATIONS, owned here and read by the stylesheet.
|
|
135
|
+
*
|
|
136
|
+
* Every one of these is a JS timer AND a CSS animation: the phase machine
|
|
137
|
+
* schedules the next step off the constant while `workspace-surfaces.css`
|
|
138
|
+
* animates the pixels, so a mismatch is not a cosmetic drift — it advances the machine
|
|
139
|
+
* before the frames land (a half-dissolved chrome snapped away mid-fade) or
|
|
140
|
+
* holds it after they do. They used to be typed twice, with three comments here
|
|
141
|
+
* saying "must match the CSS", which is a hand-maintained equality across two
|
|
142
|
+
* files and no checker.
|
|
143
|
+
*
|
|
144
|
+
* They are published as custom properties by
|
|
145
|
+
* {@link publishPlayTransitionDurations}, from {@link installPlayTransitionDock}
|
|
146
|
+
* — which is also what makes an unpublished property unreachable rather than a
|
|
147
|
+
* silent failure: nothing ever adds `volter-play-chrome-exit`,
|
|
148
|
+
* `volter-play-chrome-enter` or `volter-play-crossfade` except this module, and
|
|
149
|
+
* this module cannot act before the host is installed.
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
/** Chrome dissolve. CSS: `--volter-play-dissolve-duration`. */
|
|
153
|
+
export const PLAY_DISSOLVE_MS = 450;
|
|
154
|
+
/** Fast, unstaggered re-materialization after a reveal request. CSS:
|
|
155
|
+
* `--volter-play-materialize-duration`. */
|
|
156
|
+
export const PLAY_MATERIALIZE_MS = 220;
|
|
157
|
+
/** Per-element stagger step, published as `--volter-play-stagger`. */
|
|
158
|
+
export const PLAY_DISSOLVE_STAGGER_MS = 50;
|
|
159
|
+
/** Scene→Game opacity cross-fade. CSS: `--volter-play-crossfade-duration`. */
|
|
160
|
+
export const PLAY_CROSSFADE_MS = 250;
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Hand the three durations above to the stylesheet. On the document element,
|
|
164
|
+
* so they inherit everywhere the play classes can land — a host may park a
|
|
165
|
+
* surface in a top-level overlay outside the root it handed us.
|
|
166
|
+
*/
|
|
167
|
+
function publishPlayTransitionDurations(root: HTMLElement): void {
|
|
168
|
+
root.style.setProperty('--volter-play-dissolve-duration', `${PLAY_DISSOLVE_MS}ms`);
|
|
169
|
+
root.style.setProperty('--volter-play-materialize-duration', `${PLAY_MATERIALIZE_MS}ms`);
|
|
170
|
+
root.style.setProperty('--volter-play-crossfade-duration', `${PLAY_CROSSFADE_MS}ms`);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** What the LAYOUT HOST registers: chrome hide/show plus the root element the
|
|
174
|
+
* flight/cross-fade CSS classes land on. Whatever draws the chrome stays
|
|
175
|
+
* behind this seam — under the frame it is the workbench's own parts. */
|
|
176
|
+
export interface PlayTransitionDockHooks {
|
|
177
|
+
root: HTMLElement;
|
|
178
|
+
hideChrome(animate: boolean): void;
|
|
179
|
+
showChrome(animate: boolean): void;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** The narrow viewport surface the flight needs (the world root's stage registers the
|
|
183
|
+
* real EditorViewport; unit tests pass a fake). */
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
let _dock: PlayTransitionDockHooks | null = null;
|
|
187
|
+
|
|
188
|
+
export function installPlayTransitionDock(hooks: PlayTransitionDockHooks): () => void {
|
|
189
|
+
_dock = hooks;
|
|
190
|
+
if (typeof document !== 'undefined') publishPlayTransitionDurations(document.documentElement);
|
|
191
|
+
return () => {
|
|
192
|
+
if (_dock === hooks) _dock = null;
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function prefersReducedMotion(): boolean {
|
|
197
|
+
return (
|
|
198
|
+
typeof window !== 'undefined' &&
|
|
199
|
+
(window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false)
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
interface ActiveTransition {
|
|
210
|
+
state: PlayTransitionState;
|
|
211
|
+
reducedMotion: boolean;
|
|
212
|
+
/** The viewport is flying (`kit/play-camera-flight`): a viewport and an authored camera existed. */
|
|
213
|
+
flying: boolean;
|
|
214
|
+
timeouts: Set<ReturnType<typeof setTimeout>>;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let _active: ActiveTransition | null = null;
|
|
218
|
+
|
|
219
|
+
/** Current phase (exported for tests/e2e via the debug handle below). */
|
|
220
|
+
export function playTransitionPhase(): PlayTransitionPhase {
|
|
221
|
+
return _active?.state.phase ?? 'idle';
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// --- Settle listeners --------------------------------------------------------
|
|
225
|
+
|
|
226
|
+
const _settleListeners = new Set<() => void>();
|
|
227
|
+
|
|
228
|
+
function flushSettleListeners(): void {
|
|
229
|
+
if (_settleListeners.size === 0) return;
|
|
230
|
+
const fns = [..._settleListeners];
|
|
231
|
+
_settleListeners.clear();
|
|
232
|
+
for (const fn of fns) fn();
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Run `fn` once the play-entry transition SETTLES — the cross-fade completed
|
|
237
|
+
* (phase 'playing') or the transition tore down early (Stop/Escape/boot
|
|
238
|
+
* failure) — or immediately when no transition is in flight. One-shot.
|
|
239
|
+
*
|
|
240
|
+
* This is the hand-off point for work that must NOT happen while the flight
|
|
241
|
+
* still renders the editor viewport: the R3F design session keeps its adopted
|
|
242
|
+
* fiber scene alive under the flight (suspending at the playState flip made
|
|
243
|
+
* the whole screen flash the placeholder scene's clear color) and suspends
|
|
244
|
+
* here instead. Settle can mean "play never happened" as well as "play is
|
|
245
|
+
* fully on screen" — callbacks must re-check store state.
|
|
246
|
+
*/
|
|
247
|
+
export function onPlayTransitionSettled(fn: () => void): void {
|
|
248
|
+
if (!_active || _active.state.phase === 'playing') {
|
|
249
|
+
fn();
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
_settleListeners.add(fn);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function later(active: ActiveTransition, ms: number, fn: () => void): void {
|
|
256
|
+
const handle = setTimeout(() => {
|
|
257
|
+
active.timeouts.delete(handle);
|
|
258
|
+
fn();
|
|
259
|
+
}, ms);
|
|
260
|
+
active.timeouts.add(handle);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
function dispatch(event: PlayTransitionEvent): void {
|
|
265
|
+
const active = _active;
|
|
266
|
+
if (!active) return;
|
|
267
|
+
const prev = active.state;
|
|
268
|
+
const next = reducePlayTransition(prev, event);
|
|
269
|
+
if (next === prev) return;
|
|
270
|
+
active.state = next;
|
|
271
|
+
if (next.phase === 'crossfade' && prev.phase !== 'crossfade') {
|
|
272
|
+
_dock?.root.classList.add('volter-play-crossfade');
|
|
273
|
+
later(active, PLAY_CROSSFADE_MS + 30, () => dispatch('crossfade-done'));
|
|
274
|
+
}
|
|
275
|
+
if (next.phase === 'playing' && prev.phase !== 'playing') {
|
|
276
|
+
_dock?.root.classList.remove('volter-play-flight', 'volter-play-crossfade');
|
|
277
|
+
if (active.flying) playCameraFlight()?.settle();
|
|
278
|
+
flushSettleListeners();
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Begin the play-entry transition. Called by `play-mode.ts` immediately
|
|
285
|
+
* before `setPlayState('playing')`. Never blocks play — all choreography is
|
|
286
|
+
* fire-and-forget alongside the runtime boot. Safe no-op degradation when no
|
|
287
|
+
* dock/viewport is registered (headless unit-test stores).
|
|
288
|
+
*/
|
|
289
|
+
export interface PlayEntryTransitionOptions {
|
|
290
|
+
readonly immersive: boolean;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* A lane is starting: call BEFORE the session flips to playing. The mounted
|
|
295
|
+
* layout chooses immersive Play; when
|
|
296
|
+
* immersive, the authored camera MUST be resolved here, before playState
|
|
297
|
+
* changes — the R3F design session then suspends and removes its drei camera
|
|
298
|
+
* from the store. Every exit path funnels through `endPlayTransition`.
|
|
299
|
+
*/
|
|
300
|
+
export function beginLiveTransition(): void {
|
|
301
|
+
beginPlayEntryTransition({ immersive: usesImmersivePlayPresentation() });
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function beginPlayEntryTransition(options: PlayEntryTransitionOptions): void {
|
|
305
|
+
if (_active) endPlayTransition();
|
|
306
|
+
// Non-immersive play has no transition state, persistence gate, camera
|
|
307
|
+
// flight, or chrome mutation at all.
|
|
308
|
+
if (!options.immersive) return;
|
|
309
|
+
const reducedMotion = prefersReducedMotion();
|
|
310
|
+
setWorkspacePersistenceSuppressed(true);
|
|
311
|
+
const active: ActiveTransition = {
|
|
312
|
+
state: IDLE_TRANSITION_STATE,
|
|
313
|
+
reducedMotion,
|
|
314
|
+
flying: false,
|
|
315
|
+
timeouts: new Set(),
|
|
316
|
+
};
|
|
317
|
+
_active = active;
|
|
318
|
+
_dock?.hideChrome(!reducedMotion);
|
|
319
|
+
|
|
320
|
+
if (reducedMotion) {
|
|
321
|
+
dispatch('start-reduced');
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
dispatch('start');
|
|
325
|
+
|
|
326
|
+
// The flight resolves the authored camera NOW, before playState changes (the R3F design
|
|
327
|
+
// session then suspends and removes its drei camera from the store).
|
|
328
|
+
active.flying = playCameraFlight()?.begin(() => { if (_active === active) dispatch('flight-done'); }) ?? false;
|
|
329
|
+
if (!active.flying) {
|
|
330
|
+
// No authored camera (or headless): dissolve still runs, no flight.
|
|
331
|
+
dispatch('flight-done');
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
_dock?.root.classList.add('volter-play-flight');
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Reconcile an already-running session with appearance-axis changes. Moving
|
|
339
|
+
* away from an immersive presentation must restore the chrome immediately;
|
|
340
|
+
* moving into one mid-session deliberately does not replay entry
|
|
341
|
+
* choreography.
|
|
342
|
+
*/
|
|
343
|
+
export function reconcilePlayPresentationPolicy(isPlaying: boolean, immersive: boolean): void {
|
|
344
|
+
if (!isPlaying || !immersive) endPlayTransition();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* The game runtime finished its async boot (play-mode's ack point).
|
|
349
|
+
* `getLiveCamera` gives the flight its final convergence target — the game's
|
|
350
|
+
* actual render camera — so the cross-fade is pixel-continuous even when game
|
|
351
|
+
* code repositions the camera during boot.
|
|
352
|
+
*/
|
|
353
|
+
export function notifyPlayTransitionGameReady(getLiveCamera?: LiveCameraLookup): void {
|
|
354
|
+
const active = _active;
|
|
355
|
+
if (!active) return;
|
|
356
|
+
if (active.flying && getLiveCamera) playCameraFlight()?.track(getLiveCamera);
|
|
357
|
+
dispatch('game-ready');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Tear the transition down (Stop/Escape/boot failure — any exit path).
|
|
365
|
+
* Restores the pre-play camera pose, re-materializes the chrome, and
|
|
366
|
+
* re-enables layout persistence. Idempotent.
|
|
367
|
+
*/
|
|
368
|
+
export function endPlayTransition(): void {
|
|
369
|
+
const active = _active;
|
|
370
|
+
if (!active) return;
|
|
371
|
+
_active = null;
|
|
372
|
+
for (const handle of active.timeouts) clearTimeout(handle);
|
|
373
|
+
active.timeouts.clear();
|
|
374
|
+
// Early teardown is also "settled" — deferred hand-off work (see
|
|
375
|
+
// onPlayTransitionSettled) must run, and its store-state guards decide
|
|
376
|
+
// whether there is anything left to do.
|
|
377
|
+
flushSettleListeners();
|
|
378
|
+
_dock?.root.classList.remove('volter-play-flight', 'volter-play-crossfade');
|
|
379
|
+
|
|
380
|
+
if (active.flying) playCameraFlight()?.end();
|
|
381
|
+
|
|
382
|
+
_dock?.showChrome(!prefersReducedMotion());
|
|
383
|
+
setWorkspacePersistenceSuppressed(false);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Dev/e2e handle: lets specs observe the transition phase deterministically.
|
|
387
|
+
if (typeof window !== 'undefined' && (import.meta as ImportMeta & { env?: { DEV?: boolean } }).env?.DEV) {
|
|
388
|
+
(window as unknown as Record<string, unknown>)['__volterPlayTransition'] = {
|
|
389
|
+
phase: playTransitionPhase,
|
|
390
|
+
};
|
|
391
|
+
}
|