@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,195 @@
|
|
|
1
|
+
import type { AuthoringAdapter, EditorNode } from '@volter/project/adapter';
|
|
2
|
+
import { setAuthoringSelection } from './consumer-actions';
|
|
3
|
+
|
|
4
|
+
/** Session-only contents scope shared by hierarchy, viewport picking, and
|
|
5
|
+
* hotkeys. The adapter remains the source of hierarchy/ownership truth; this
|
|
6
|
+
* module only records which semantic boundary the user has opened. */
|
|
7
|
+
interface SelectionScopeState {
|
|
8
|
+
adapter: AuthoringAdapter;
|
|
9
|
+
stack: string[];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let state: SelectionScopeState | null = null;
|
|
13
|
+
const listeners = new Set<() => void>();
|
|
14
|
+
let version = 0;
|
|
15
|
+
|
|
16
|
+
function emit(): void {
|
|
17
|
+
version += 1;
|
|
18
|
+
for (const listener of listeners) listener();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isScopeNode(node: EditorNode | null): boolean {
|
|
22
|
+
return (
|
|
23
|
+
!!node && (node.role === 'component' || node.role === 'instance' || node.role === 'boundary')
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isDescendant(adapter: AuthoringAdapter, id: string, ancestorId: string): boolean {
|
|
28
|
+
let current: string | null = id;
|
|
29
|
+
let guard = 0;
|
|
30
|
+
while (current && guard++ < 1000) {
|
|
31
|
+
if (current === ancestorId) return true;
|
|
32
|
+
current = adapter.hierarchy.node(current)?.parentId ?? null;
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function subscribeSelectionScope(listener: () => void): () => void {
|
|
38
|
+
listeners.add(listener);
|
|
39
|
+
return () => listeners.delete(listener);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function selectionScopeVersion(): number {
|
|
43
|
+
return version;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Current boundary id for pick resolution. Deliberately adapter-agnostic:
|
|
47
|
+
* layered picking resolves through a composite's child adapter while the
|
|
48
|
+
* hierarchy owns the composite adapter that opened the scope. */
|
|
49
|
+
export function currentSelectionScopeId(): string | null {
|
|
50
|
+
return state?.stack.at(-1) ?? null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function selectionScopeStack(adapter: AuthoringAdapter): string[] {
|
|
54
|
+
if (state?.adapter !== adapter) return [];
|
|
55
|
+
const valid = state.stack.filter((id) => adapter.hierarchy.node(id) !== null);
|
|
56
|
+
if (valid.length !== state.stack.length) {
|
|
57
|
+
state = valid.length > 0 ? { adapter, stack: valid } : null;
|
|
58
|
+
}
|
|
59
|
+
return valid;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function enterSelectionScope(adapter: AuthoringAdapter, id: string): boolean {
|
|
63
|
+
const node = adapter.hierarchy.node(id);
|
|
64
|
+
if (!isScopeNode(node) || node!.childIds.length === 0) return false;
|
|
65
|
+
|
|
66
|
+
const current = state?.adapter === adapter ? state.stack : [];
|
|
67
|
+
const parentScope = current.at(-1);
|
|
68
|
+
if (parentScope && !isDescendant(adapter, id, parentScope)) return false;
|
|
69
|
+
if (parentScope === id) return false;
|
|
70
|
+
state = { adapter, stack: [...current, id] };
|
|
71
|
+
setAuthoringSelection(adapter, [id]);
|
|
72
|
+
emit();
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Navigate to an existing breadcrumb boundary, or null for the full Game. */
|
|
77
|
+
export function setSelectionScope(adapter: AuthoringAdapter, id: string | null): void {
|
|
78
|
+
if (id === null) {
|
|
79
|
+
if (state === null) return;
|
|
80
|
+
state = null;
|
|
81
|
+
emit();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const current = selectionScopeStack(adapter);
|
|
85
|
+
const index = current.indexOf(id);
|
|
86
|
+
if (index < 0) return;
|
|
87
|
+
state = { adapter, stack: current.slice(0, index + 1) };
|
|
88
|
+
setAuthoringSelection(adapter, [id]);
|
|
89
|
+
emit();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function exitSelectionScope(adapter: AuthoringAdapter): boolean {
|
|
93
|
+
if (state && state.adapter !== adapter) {
|
|
94
|
+
state = null;
|
|
95
|
+
emit();
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
const current = selectionScopeStack(adapter);
|
|
99
|
+
if (current.length === 0) return false;
|
|
100
|
+
const next = current.slice(0, -1);
|
|
101
|
+
state = next.length > 0 ? { adapter, stack: next } : null;
|
|
102
|
+
const selectionId = next.at(-1) ?? current[0]!;
|
|
103
|
+
setAuthoringSelection(adapter, [selectionId]);
|
|
104
|
+
emit();
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function enterSelectedScope(adapter: AuthoringAdapter): boolean {
|
|
109
|
+
const selected = adapter.selection?.get() ?? [];
|
|
110
|
+
return selected.length === 1 ? enterSelectionScope(adapter, selected[0]!) : false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Drill in ONE level (the viewport's double-click, Figma's own gesture): open
|
|
115
|
+
* `boundaryId`'s scope, then select whatever the SAME pointer resolves to now
|
|
116
|
+
* that the scope is open.
|
|
117
|
+
*
|
|
118
|
+
* `repick` is the caller's own pick — `layered-pick.ts` already passes
|
|
119
|
+
* `currentSelectionScopeId()` into `SelectionProvider.resolve`, and the
|
|
120
|
+
* adapter's resolve already answers with the next member down its own owner
|
|
121
|
+
* chain. So there is no second chain-walking rule here, and this module still
|
|
122
|
+
* knows nothing about how a surface picks. Repeat the gesture to keep
|
|
123
|
+
* descending; {@link exitSelectionScope} (Escape) walks back out.
|
|
124
|
+
*/
|
|
125
|
+
export function drillIntoSelectionScope(
|
|
126
|
+
adapter: AuthoringAdapter,
|
|
127
|
+
boundaryId: string,
|
|
128
|
+
repick: () => string | null,
|
|
129
|
+
): boolean {
|
|
130
|
+
if (!enterSelectionScope(adapter, boundaryId)) return false;
|
|
131
|
+
// `enterSelectionScope` already selected the boundary; a deeper member under
|
|
132
|
+
// the same pointer is what the gesture actually asked for. When the chain
|
|
133
|
+
// ends here the boundary stays selected — entering was still correct.
|
|
134
|
+
const deeper = repick();
|
|
135
|
+
if (deeper && deeper !== boundaryId) setAuthoringSelection(adapter, [deeper]);
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Figma's outside-click rule: a click that lands outside an open scope leaves
|
|
141
|
+
* it. Pops every entry whose boundary does not CONTAIN `id`, so the stack
|
|
142
|
+
* follows the click to the level that does; a `null` id (empty space) closes
|
|
143
|
+
* every scope.
|
|
144
|
+
*
|
|
145
|
+
* Selection stays the caller's to set — the pick that produced `id` was
|
|
146
|
+
* already resolved against the scope that was open (a chain without the scope
|
|
147
|
+
* in it resolves to its own outermost owner), so this only makes the stack
|
|
148
|
+
* agree with where the click landed.
|
|
149
|
+
*/
|
|
150
|
+
export function popSelectionScopesToContain(adapter: AuthoringAdapter, id: string | null): boolean {
|
|
151
|
+
const current = selectionScopeStack(adapter);
|
|
152
|
+
if (current.length === 0) return false;
|
|
153
|
+
let depth = 0;
|
|
154
|
+
while (id !== null && depth < current.length && isDescendant(adapter, id, current[depth]!)) {
|
|
155
|
+
depth += 1;
|
|
156
|
+
}
|
|
157
|
+
if (depth === current.length) return false;
|
|
158
|
+
state = depth > 0 ? { adapter, stack: current.slice(0, depth) } : null;
|
|
159
|
+
emit();
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* ONE click's answer, across the scope exit the click itself causes — the
|
|
165
|
+
* whole of the viewport's single-click resolution.
|
|
166
|
+
*
|
|
167
|
+
* A pick resolves against whatever scope is OPEN (`layered-pick.ts` hands
|
|
168
|
+
* `currentSelectionScopeId()` to the adapter's own resolve), so a click that
|
|
169
|
+
* leaves the innermost scope was resolved by a scope that is about to be
|
|
170
|
+
* wrong. With a one-deep stack that is invisible — popping lands at "no
|
|
171
|
+
* scope", which is what the stale answer already assumed. With a stack THREE
|
|
172
|
+
* deep it is visible: the stale resolve answers with the chain's outermost
|
|
173
|
+
* owner, one level shallower than the same click gives once the stack has
|
|
174
|
+
* followed it, so the user has to click twice to land where one click should
|
|
175
|
+
* have (reviewer, #1235).
|
|
176
|
+
*
|
|
177
|
+
* So: resolve, let {@link popSelectionScopesToContain} follow the hit, and
|
|
178
|
+
* re-resolve ONCE — only when the stack actually moved, because a click that
|
|
179
|
+
* stays inside the open scope has nothing to re-resolve against. The second
|
|
180
|
+
* answer needs no second pop: it is a member of the scope the first pop
|
|
181
|
+
* settled on.
|
|
182
|
+
*/
|
|
183
|
+
export function pickAcrossScopeExit(
|
|
184
|
+
adapter: AuthoringAdapter,
|
|
185
|
+
repick: () => string | null,
|
|
186
|
+
): string | null {
|
|
187
|
+
const hit = repick();
|
|
188
|
+
return popSelectionScopesToContain(adapter, hit) ? repick() : hit;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Test-only reset; production scope is intentionally session-local. */
|
|
192
|
+
export function _resetSelectionScopeForTest(): void {
|
|
193
|
+
state = null;
|
|
194
|
+
emit();
|
|
195
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format-neutral shell document operations.
|
|
3
|
+
*
|
|
4
|
+
* Save destination, save state, hierarchy rows and select-all are questions
|
|
5
|
+
* about a DOCUMENT, and the shell owns none. Answering them from store fields
|
|
6
|
+
* would bind the shell chrome — status bar, application menus, command relay,
|
|
7
|
+
* hotkeys — to one format; these helpers ask the ACTIVE
|
|
8
|
+
* {@link AuthoringAdapter} instead, so the same chrome works for a TSX/R3F
|
|
9
|
+
* world, a React root, and an ingested game alike.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { AuthoringAdapter, NodeCreationSite, WriteAnchorKind } from '@volter/project/adapter';
|
|
13
|
+
import type { ShellDocumentState } from '@volter/sdk/kit/shell-document-state';
|
|
14
|
+
import { forEachHierarchyNode } from '@volter/sdk/kit/hierarchy-walk';
|
|
15
|
+
import { getActiveAuthoring } from './active-adapter';
|
|
16
|
+
import { saveAuthoringDocument, setAuthoringSelection } from '@volter/sdk/kit/authoring/consumer-actions';
|
|
17
|
+
import { resolvePanelAuthoring } from './panel-authoring';
|
|
18
|
+
|
|
19
|
+
/** The authoring adapter owned by the active center document. This is the same
|
|
20
|
+
* resolution used by Hierarchy and Inspector; shell commands must not keep
|
|
21
|
+
* driving the scene adapter after an asset/source document becomes active. */
|
|
22
|
+
export function activeDocumentAuthoring(store: ShellDocumentState): AuthoringAdapter {
|
|
23
|
+
return resolvePanelAuthoring(store).adapter;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** One flattened hierarchy row — the wire shape `editor.hierarchy.inspect` reports. */
|
|
27
|
+
export interface ShellHierarchyRow {
|
|
28
|
+
id: string;
|
|
29
|
+
name: string;
|
|
30
|
+
childIds: string[];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The active adapter's hierarchy, flattened breadth-first to id/name/childIds
|
|
35
|
+
* rows. `[]` when the adapter owns no tree (the no-authoring floor).
|
|
36
|
+
*/
|
|
37
|
+
export function activeHierarchyRows(store: ShellDocumentState): ShellHierarchyRow[] {
|
|
38
|
+
const rows: ShellHierarchyRow[] = [];
|
|
39
|
+
forEachHierarchyNode(activeDocumentAuthoring(store).hierarchy, (node) => {
|
|
40
|
+
rows.push({ id: node.id, name: node.label, childIds: [...node.childIds] });
|
|
41
|
+
});
|
|
42
|
+
return rows;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The source path represented by an adapter's document node.
|
|
47
|
+
*
|
|
48
|
+
* Source-authored adapters persist edits immediately and intentionally expose
|
|
49
|
+
* no PersistenceProvider. Their hierarchy still owns an honest document node
|
|
50
|
+
* whose secondary label is the project-relative source path (`src/world.tsx`,
|
|
51
|
+
* for example). Prefer that source identity for document chrome instead of
|
|
52
|
+
* leaking a composite persistence fallback such as "(no persistable child)".
|
|
53
|
+
*/
|
|
54
|
+
export function authoringDocumentSourcePath(adapter: AuthoringAdapter): string | null {
|
|
55
|
+
let found: string | null = null;
|
|
56
|
+
forEachHierarchyNode(adapter.hierarchy, (node) => {
|
|
57
|
+
const sourcePath = node.secondaryLabel?.trim();
|
|
58
|
+
if (node.role !== 'document' || !sourcePath) return;
|
|
59
|
+
found = sourcePath;
|
|
60
|
+
return false; // the first document row answers; never walk the whole tree for it
|
|
61
|
+
});
|
|
62
|
+
return found;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The active source-authored document path, when its adapter exposes one. */
|
|
66
|
+
export function activeDocumentSourcePath(store: ShellDocumentState): string | null {
|
|
67
|
+
return authoringDocumentSourcePath(getActiveAuthoring(store));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The exact source filename represented by a project-relative path. */
|
|
71
|
+
export function sourceFileName(sourcePath: string | null | undefined): string | null {
|
|
72
|
+
const trimmed = sourcePath?.trim();
|
|
73
|
+
if (!trimmed) return null;
|
|
74
|
+
return trimmed.split(/[\\/]/).filter(Boolean).at(-1) ?? null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Where a save would land, straight from the active adapter's
|
|
79
|
+
* `PersistenceProvider`, or `null` when this adapter persists nothing.
|
|
80
|
+
*/
|
|
81
|
+
export function activeSaveDestination(store: ShellDocumentState): string | null {
|
|
82
|
+
const adapter = getActiveAuthoring(store);
|
|
83
|
+
return adapter.capabilities.persist ? (adapter.persistence?.destination ?? null) : null;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Whether the active adapter has unsaved edits.
|
|
88
|
+
*
|
|
89
|
+
* A source-backed adapter may be clean because it rolled a failed write back.
|
|
90
|
+
* Its provider still reports that failure until a later successful write
|
|
91
|
+
* clears the project-history error; clean and successful are not synonyms.
|
|
92
|
+
*/
|
|
93
|
+
export function activeSaveState(store: ShellDocumentState): 'saved' | 'unsaved' | 'failed' {
|
|
94
|
+
const persistence = getActiveAuthoring(store).persistence;
|
|
95
|
+
if (persistence?.lastError?.()) return 'failed';
|
|
96
|
+
return persistence?.isDirty() ? 'unsaved' : 'saved';
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** The active adapter's human-readable persistence failure, when any. */
|
|
100
|
+
export function activeSaveFailure(store: ShellDocumentState): string | null {
|
|
101
|
+
return getActiveAuthoring(store).persistence?.lastError?.() ?? null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* The creation-site anchor for the CURRENT selection, as the control
|
|
106
|
+
* API reports it (the editor's `status` command / the editor's `eval` command's `editor.status()`).
|
|
107
|
+
*
|
|
108
|
+
* `null` has one meaning and one only: there is nothing to ask about — no
|
|
109
|
+
* selection, or an active adapter that indexes no creation sites. Whenever the
|
|
110
|
+
* adapter DOES index them the answer is a record, anchored or reasoned; a
|
|
111
|
+
* silent blank for "we couldn't find it" is exactly what the honest-floor rule
|
|
112
|
+
* forbids.
|
|
113
|
+
*/
|
|
114
|
+
export function activeSelectionCreationSite(store: ShellDocumentState): NodeCreationSite | null {
|
|
115
|
+
const adapter = activeDocumentAuthoring(store);
|
|
116
|
+
const id = adapter.selection?.get()[0] ?? null;
|
|
117
|
+
if (!id) return null;
|
|
118
|
+
return adapter.truth?.resolve(id, 'position').site ?? null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The WRITE-side sibling of {@link activeSelectionCreationSite}: which lane
|
|
123
|
+
* would carry an edit to the current selection (`WriteAnchorKind`).
|
|
124
|
+
*
|
|
125
|
+
* Reported beside the anchor because the anchor alone cannot answer it — two
|
|
126
|
+
* subjects at the same kind of `file:line` can belong to different lanes with
|
|
127
|
+
* different correctness contracts. A caller sweeping the hierarchy for one
|
|
128
|
+
* subject per lane reads this per row; a probe's edit-write walk is that
|
|
129
|
+
* caller, and it is what makes the walk exhaustive over the kinds a world has
|
|
130
|
+
* instead of stopping at whichever row answered first.
|
|
131
|
+
*
|
|
132
|
+
* `null` on the same terms as the anchor: nothing selected, or an adapter that
|
|
133
|
+
* plans no distinguishable lanes.
|
|
134
|
+
*
|
|
135
|
+
* READ THROUGH THE SAME BINDING THE WRITE TAKES ({@link activeDocumentAuthoring},
|
|
136
|
+
* which is what `setActiveInspectionField` resolves too). A classifier reached
|
|
137
|
+
* through a different resolver than the writer is how a subject came to be
|
|
138
|
+
* reported in one lane while its edit travelled another.
|
|
139
|
+
*/
|
|
140
|
+
export function activeSelectionWriteAnchorKind(store: ShellDocumentState): WriteAnchorKind | null {
|
|
141
|
+
const adapter = activeDocumentAuthoring(store);
|
|
142
|
+
const id = adapter.selection?.get()[0] ?? null;
|
|
143
|
+
if (!id) return null;
|
|
144
|
+
return adapter.truth?.resolve(id, 'position').writeAnchorKind ?? null;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/** Current document-local selection, shared by UI actions and the control API. */
|
|
148
|
+
export function activeSelectionIds(store: ShellDocumentState): string[] {
|
|
149
|
+
return [...(activeDocumentAuthoring(store).selection?.get() ?? store.selectedEntityIds)];
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** Route selection through the active document's native adapter. */
|
|
153
|
+
export function selectAuthoringNodes(store: ShellDocumentState, ids: readonly string[]): void {
|
|
154
|
+
const adapter = activeDocumentAuthoring(store);
|
|
155
|
+
if (!setAuthoringSelection(adapter, ids)) store.selectMultiple([...ids]);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** Select every node the active adapter's hierarchy exposes. */
|
|
159
|
+
export function selectAllAuthoringNodes(store: ShellDocumentState): void {
|
|
160
|
+
selectAuthoringNodes(
|
|
161
|
+
store,
|
|
162
|
+
activeHierarchyRows(store).map((row) => row.id),
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/** Save through the active adapter's persistence provider (no-op when it has none). */
|
|
167
|
+
export async function saveActiveAuthoring(store: ShellDocumentState): Promise<void> {
|
|
168
|
+
await saveAuthoringDocument(getActiveAuthoring(store), 'the shell saved the active document');
|
|
169
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Board chrome — frame names and group names — is CONSTANT-SIZE client-space
|
|
3
|
+
* furniture floating over a board that zooms underneath it (the deliberate
|
|
4
|
+
* Figma-style choice: names stay readable at any scale). The authored gaps
|
|
5
|
+
* that chrome lives in DO shrink with zoom, so below some zoom a constant
|
|
6
|
+
* 26px frame-name stack no longer fits a 64-authored-px row gap and paints
|
|
7
|
+
* over the frames of the row above.
|
|
8
|
+
*
|
|
9
|
+
* This module owns the one rule that prevents that: **chrome degrades, frames
|
|
10
|
+
* never move**. Given the client-space room above a row of frames, it returns
|
|
11
|
+
* the scale/opacity/offset the chrome must adopt so its painted box always
|
|
12
|
+
* ends at or below whatever sits above it. Layout stays zoom-independent.
|
|
13
|
+
*
|
|
14
|
+
* Priority: a group name is the navigation anchor at overview zoom, so it is
|
|
15
|
+
* served FIRST out of the available room and therefore degrades LAST; the
|
|
16
|
+
* frame name gets whatever is left over.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export const FRAME_LABEL_HEIGHT = 20;
|
|
20
|
+
export const FRAME_LABEL_GAP = 6;
|
|
21
|
+
export const GROUP_LABEL_HEIGHT = 22;
|
|
22
|
+
export const GROUP_LABEL_GAP = 10;
|
|
23
|
+
|
|
24
|
+
/** Client px a frame name claims above its frame's top edge at scale 1. */
|
|
25
|
+
export const FRAME_LABEL_STACK = FRAME_LABEL_HEIGHT + FRAME_LABEL_GAP;
|
|
26
|
+
/** Client px a group name claims above the frame-name stack at scale 1. */
|
|
27
|
+
export const GROUP_LABEL_STACK = GROUP_LABEL_HEIGHT + GROUP_LABEL_GAP;
|
|
28
|
+
|
|
29
|
+
/** Below this scale a name starts fading; below the hide scale it is dropped
|
|
30
|
+
* entirely, because an unreadable sliver of text is noise, not information. */
|
|
31
|
+
const FRAME_FADE_FROM = 0.6;
|
|
32
|
+
const FRAME_HIDE_BELOW = 0.4;
|
|
33
|
+
const GROUP_FADE_FROM = 0.7;
|
|
34
|
+
const GROUP_HIDE_BELOW = 0.45;
|
|
35
|
+
|
|
36
|
+
export interface ChromePlacement {
|
|
37
|
+
/** Uniform scale, applied with `transform-origin` at the element's bottom-left. */
|
|
38
|
+
readonly scale: number;
|
|
39
|
+
/** 0..1; 0 only when `visible` is false. */
|
|
40
|
+
readonly opacity: number;
|
|
41
|
+
/** false → do not paint (and do not accept pointer events) at all. */
|
|
42
|
+
readonly visible: boolean;
|
|
43
|
+
/** Client px to subtract from the row's top edge to get the element's `top`.
|
|
44
|
+
* Accounts for the element's own unscaled height, since the scale pivots on
|
|
45
|
+
* its bottom edge. */
|
|
46
|
+
readonly offset: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface StoryChromePlacement {
|
|
50
|
+
readonly frame: ChromePlacement;
|
|
51
|
+
/** null when the row carries no group name. */
|
|
52
|
+
readonly group: ChromePlacement | null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function fade(scale: number, fadeFrom: number, hideBelow: number): [number, boolean] {
|
|
56
|
+
if (scale >= fadeFrom) return [1, true];
|
|
57
|
+
if (scale <= hideBelow) return [0, false];
|
|
58
|
+
return [(scale - hideBelow) / (fadeFrom - hideBelow), true];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Fit one frame row's chrome into the client-space `room` above it — the
|
|
63
|
+
* distance from the row's top edge to the bottom edge of the nearest frames
|
|
64
|
+
* above it (`Infinity` for the first row of the board, which has nothing
|
|
65
|
+
* above it to collide with).
|
|
66
|
+
*
|
|
67
|
+
* Invariant: the painted top of every returned placement is at or below
|
|
68
|
+
* `rowTop - room`, so chrome never paints over a frame that is not its own.
|
|
69
|
+
*/
|
|
70
|
+
export function placeStoryChrome(room: number, withGroupLabel: boolean): StoryChromePlacement {
|
|
71
|
+
const usable = Math.max(0, room);
|
|
72
|
+
const groupScale = withGroupLabel ? Math.min(1, usable / GROUP_LABEL_STACK) : 0;
|
|
73
|
+
const [groupOpacity, groupVisible] = fade(groupScale, GROUP_FADE_FROM, GROUP_HIDE_BELOW);
|
|
74
|
+
|
|
75
|
+
const frameRoom = Math.max(0, usable - GROUP_LABEL_STACK * groupScale);
|
|
76
|
+
const frameScale = Math.min(1, frameRoom / FRAME_LABEL_STACK);
|
|
77
|
+
const [frameOpacity, frameVisible] = fade(frameScale, FRAME_FADE_FROM, FRAME_HIDE_BELOW);
|
|
78
|
+
|
|
79
|
+
// A dropped frame name reserves nothing, which lets the group name settle
|
|
80
|
+
// closer to the frames instead of floating over an empty band.
|
|
81
|
+
const frameConsumed = frameVisible ? FRAME_LABEL_STACK * frameScale : 0;
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
frame: {
|
|
85
|
+
scale: frameScale,
|
|
86
|
+
opacity: frameOpacity,
|
|
87
|
+
visible: frameVisible,
|
|
88
|
+
offset: FRAME_LABEL_GAP * frameScale + FRAME_LABEL_HEIGHT,
|
|
89
|
+
},
|
|
90
|
+
group: withGroupLabel
|
|
91
|
+
? {
|
|
92
|
+
scale: groupScale,
|
|
93
|
+
opacity: groupOpacity,
|
|
94
|
+
visible: groupVisible,
|
|
95
|
+
offset: frameConsumed + GROUP_LABEL_GAP * groupScale + GROUP_LABEL_HEIGHT,
|
|
96
|
+
}
|
|
97
|
+
: null,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Paint one chrome element at the placement this module computed. */
|
|
102
|
+
export function applyStoryChrome(element: HTMLElement, placement: ChromePlacement): void {
|
|
103
|
+
element.style.transformOrigin = '0 100%';
|
|
104
|
+
element.style.transform = placement.scale >= 1 ? '' : `scale(${placement.scale})`;
|
|
105
|
+
element.style.opacity = placement.visible ? String(placement.opacity) : '0';
|
|
106
|
+
element.style.display = placement.visible ? '' : 'none';
|
|
107
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE BOARD SUBSTRATE'S PRESENTATION CONTRACT — types only, no runtime import
|
|
3
|
+
* of any kind, and that is the whole point.
|
|
4
|
+
*
|
|
5
|
+
* `react-story-board.ts` is THE board substrate and stays in the host: two
|
|
6
|
+
* host chrome files draw OVER it (`components/ReactCanvasControls.tsx`, the
|
|
7
|
+
* viewport strip; `components/RootSelectionOverlay.tsx`, the frame hit-test),
|
|
8
|
+
* which is a different question from how a board MOUNTS. But it used to
|
|
9
|
+
* compute its own layout by calling `stories/story-presentation.ts`, which
|
|
10
|
+
* imports `storybook/viewport` and `storybook/internal/csf` — so the one file
|
|
11
|
+
* the host genuinely owns dragged Storybook in behind it.
|
|
12
|
+
*
|
|
13
|
+
* The decoupling is an injected RESOLVER, not a dropped default: the board
|
|
14
|
+
* resolves a presentation per story, per viewport override, INSIDE its own
|
|
15
|
+
* layout pass ({@link StoryBoardPresentation.resolve}), so a caller cannot
|
|
16
|
+
* pre-compute the answers and hand over a table. The callers — `@volter/editor-game`'s
|
|
17
|
+
* design-time mount and the canvas 2D board — each supply an
|
|
18
|
+
* implementation; `stories/story-presentation.ts` is the one that exists,
|
|
19
|
+
* and it implements these types rather than declaring its own, the way
|
|
20
|
+
* `design-time-layers.ts` exports `LayerMountResult` for the mounts that fill
|
|
21
|
+
* it.
|
|
22
|
+
*
|
|
23
|
+
* Storybook's slash title/path model is the organization source behind every
|
|
24
|
+
* implementation there is today, but nothing here says so: these are a board's
|
|
25
|
+
* own vocabulary — sections, nodes, a cell size, a viewport choice.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/** How a frame's content sits inside its cell. */
|
|
29
|
+
export type StoryLayout = 'padded' | 'centered' | 'fullscreen';
|
|
30
|
+
|
|
31
|
+
/** One selectable frame size, in authored px. */
|
|
32
|
+
export interface StoryViewportChoice {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly label: string;
|
|
35
|
+
readonly width: number;
|
|
36
|
+
readonly height: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** What a presentation is resolved FROM — everything a board frame knows
|
|
40
|
+
* about its own story. */
|
|
41
|
+
export interface StoryPresentationInput {
|
|
42
|
+
readonly id: string;
|
|
43
|
+
readonly label: string;
|
|
44
|
+
readonly modulePath: string;
|
|
45
|
+
readonly title?: string | undefined;
|
|
46
|
+
readonly parameters?: Readonly<Record<string, unknown>> | undefined;
|
|
47
|
+
readonly globals?: Readonly<Record<string, unknown>> | undefined;
|
|
48
|
+
readonly viewportLocked?: boolean | undefined;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/** One component section: the frames that belong together on the board. */
|
|
52
|
+
export interface StoryPresentationSection {
|
|
53
|
+
readonly id: string;
|
|
54
|
+
readonly label: string;
|
|
55
|
+
readonly storyIds: readonly string[];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** One row of the navigation tree the hierarchy and the board share. */
|
|
59
|
+
export interface StoryPresentationTreeNode {
|
|
60
|
+
readonly id: string;
|
|
61
|
+
readonly label: string;
|
|
62
|
+
readonly role: 'folder' | 'component';
|
|
63
|
+
readonly kind: 'group' | 'component';
|
|
64
|
+
readonly parentId: string | null;
|
|
65
|
+
readonly childIds: readonly string[];
|
|
66
|
+
readonly secondaryLabel?: string;
|
|
67
|
+
readonly typeLabel: 'Category' | 'Folder' | 'Component';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The whole navigation index: how a set of stories is organized. */
|
|
71
|
+
export interface StoryPresentationIndex {
|
|
72
|
+
readonly sections: readonly StoryPresentationSection[];
|
|
73
|
+
readonly nodes: readonly StoryPresentationTreeNode[];
|
|
74
|
+
readonly rootIds: readonly string[];
|
|
75
|
+
readonly storyParentIds: ReadonlyMap<string, string>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** One frame's resolved cell. */
|
|
79
|
+
export interface ResolvedStoryPresentation {
|
|
80
|
+
readonly layout: StoryLayout;
|
|
81
|
+
readonly choices: readonly StoryViewportChoice[];
|
|
82
|
+
readonly selectedViewportId: string | null;
|
|
83
|
+
readonly locked: boolean;
|
|
84
|
+
readonly rotated: boolean;
|
|
85
|
+
readonly width: number;
|
|
86
|
+
readonly height: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* What a board is handed instead of an implementation: the index it lays out
|
|
91
|
+
* by, and the per-frame resolver it calls during that layout.
|
|
92
|
+
*/
|
|
93
|
+
export interface StoryBoardPresentation {
|
|
94
|
+
/** How this board's stories are organized into sections and tree rows. */
|
|
95
|
+
readonly index: StoryPresentationIndex;
|
|
96
|
+
/**
|
|
97
|
+
* This story's cell, right now. Called per story and again on every
|
|
98
|
+
* viewport/rotation override, which is why it is a function the board holds
|
|
99
|
+
* rather than a table it was given.
|
|
100
|
+
*
|
|
101
|
+
* `fallback` is the board's own default cell for a story that authored
|
|
102
|
+
* none; `sessionViewportId` is `undefined` for "whatever the story
|
|
103
|
+
* authored" and `null` for "explicitly none".
|
|
104
|
+
*/
|
|
105
|
+
readonly resolve: (
|
|
106
|
+
story: StoryPresentationInput,
|
|
107
|
+
fallback?: { readonly width: number; readonly height: number },
|
|
108
|
+
sessionViewportId?: string | null,
|
|
109
|
+
sessionRotated?: boolean,
|
|
110
|
+
) => ResolvedStoryPresentation;
|
|
111
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which declared world is the Three root this viewport paints, read from the composite's
|
|
3
|
+
* manifest kinds and capabilities only (no scene, no renderer), so kit panels can ask without
|
|
4
|
+
* importing the viewport.
|
|
5
|
+
*/
|
|
6
|
+
import { CompositeAuthoringAdapter } from '@volter/sdk/kit/authoring/composite-authoring-adapter';
|
|
7
|
+
import { isRootHidden } from '@volter/sdk/kit/authoring/world-session-state';
|
|
8
|
+
import type { ShellStore } from '@volter/sdk/kit/shell-store';
|
|
9
|
+
import { getActiveAuthoring } from './active-adapter';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The worldId of the ONE three world actually rendered in this viewport
|
|
13
|
+
* (`store.objectMap`'s contents), or `null` when the active adapter isn't a
|
|
14
|
+
* composite (single-world project — no world-group row/eye exists for it at
|
|
15
|
+
* all, so there is nothing to resolve) or declares no three world.
|
|
16
|
+
*
|
|
17
|
+
* Identifies the LIVE Three child by `capabilities.transform` — a transient
|
|
18
|
+
* Boundary adapter reports no transform capability until the R3F design
|
|
19
|
+
* session attaches. This reuses an existing, already-load-bearing signal
|
|
20
|
+
* instead of adding an `instanceof` check or parallel bookkeeping slot.
|
|
21
|
+
*/
|
|
22
|
+
export function resolveThreeViewportRootId(store: ShellStore): string | null {
|
|
23
|
+
const active = getActiveAuthoring(store);
|
|
24
|
+
if (!(active instanceof CompositeAuthoringAdapter)) return null;
|
|
25
|
+
const focused = active
|
|
26
|
+
.childAdapters()
|
|
27
|
+
.find((c) => c.kind === 'three' && c.adapter.capabilities.transform);
|
|
28
|
+
return focused?.worldId ?? null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Is a three surface currently SHOWING in the viewport? This is the single
|
|
33
|
+
* derived truth the 3D viewport chrome gates on (spec 28): the grid,
|
|
34
|
+
* orientation gizmo, transform toolstrip, camera readout, shading modes, and
|
|
35
|
+
* the transform gizmo itself are claims about what the user can do RIGHT NOW
|
|
36
|
+
* — showing them over a viewport with no visible 3D content is a false claim
|
|
37
|
+
* (same spirit as the adapter-reach rule: report what isn't there, never
|
|
38
|
+
* advertise it). The DOM half of the chrome (`RootSelectionOverlay`)
|
|
39
|
+
* already self-gates this way; this selector brings the pre-contract 3D
|
|
40
|
+
* chrome under the same rule.
|
|
41
|
+
*
|
|
42
|
+
* Truth table (deliberately conservative — every non-composite mode keeps
|
|
43
|
+
* today's behavior exactly):
|
|
44
|
+
* - active adapter is not a composite (single-world project, ingest):
|
|
45
|
+
* `true` — no world-group eyes exist there, so there is nothing to derive
|
|
46
|
+
* from.
|
|
47
|
+
* - composite with NO threejs-kind child at all (e.g. react-only
|
|
48
|
+
* multi-world manifest): `false` — no 3D content can EVER show.
|
|
49
|
+
* - composite whose three child is still a read-only Boundary
|
|
50
|
+
* (`resolveThreeViewportRootId` → null): `true` — this is reachable
|
|
51
|
+
* transiently while the R3F design session attaches; keep the chrome rather
|
|
52
|
+
* than flickering it around adapter-install timing.
|
|
53
|
+
* - composite with a live three world: `!isRootHidden(worldId)`
|
|
54
|
+
* — the eye is the "what we're showing" signal.
|
|
55
|
+
*
|
|
56
|
+
* Recompute-per-call like everything else in this module: callers read it on
|
|
57
|
+
* every store notify (`syncFromStore` / `the world root's stage` render), never cache
|
|
58
|
+
* it across notifies.
|
|
59
|
+
*/
|
|
60
|
+
export function isThreejsSurfaceVisible(store: ShellStore): boolean {
|
|
61
|
+
const active = getActiveAuthoring(store);
|
|
62
|
+
if (!(active instanceof CompositeAuthoringAdapter)) return true;
|
|
63
|
+
const children = active.childAdapters();
|
|
64
|
+
if (!children.some((c) => c.kind === 'three')) return false;
|
|
65
|
+
const threeRootId = resolveThreeViewportRootId(store);
|
|
66
|
+
return threeRootId === null ? true : !isRootHidden(threeRootId);
|
|
67
|
+
}
|