@volter/sdk 0.0.0-stage → 0.5.203
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +38 -3
- package/package.json +510 -4
- package/src/account.ts +210 -0
- package/src/chrome.ts +88 -0
- package/src/client.ts +1646 -0
- package/src/commands.ts +66 -0
- package/src/contributions.ts +619 -0
- package/src/css-numeric-style.ts +97 -0
- package/src/document-probe.ts +282 -0
- package/src/editor-view.ts +225 -0
- package/src/extension.ts +40 -0
- package/src/generations.ts +178 -0
- package/src/host.ts +1157 -0
- package/src/http-transport.browser.ts +14 -0
- package/src/http-transport.node.ts +19 -0
- package/src/index.ts +131 -0
- package/src/kit/CapabilityCoverageSection.tsx +185 -0
- package/src/kit/account-client.ts +333 -0
- package/src/kit/action-registry.ts +317 -0
- package/src/kit/active-product.ts +76 -0
- package/src/kit/active-project.ts +155 -0
- package/src/kit/adapter-editor-config.ts +25 -0
- package/src/kit/adapter-module.ts +7 -0
- package/src/kit/adapter-observation.ts +49 -0
- package/src/kit/animation/animation-clock.ts +479 -0
- package/src/kit/animation/stage-transport.ts +385 -0
- package/src/kit/api/assets.ts +365 -0
- package/src/kit/api/project-open.ts +355 -0
- package/src/kit/api/project-source.ts +180 -0
- package/src/kit/api/project-state.ts +110 -0
- package/src/kit/api/relay.ts +270 -0
- package/src/kit/api/themes.ts +45 -0
- package/src/kit/api-asset-library-wire.ts +45 -0
- package/src/kit/api-base.ts +10 -0
- package/src/kit/api-build.ts +99 -0
- package/src/kit/api-git-wire.ts +56 -0
- package/src/kit/api-logs.ts +92 -0
- package/src/kit/api-project-identity.ts +74 -0
- package/src/kit/api-settings.ts +36 -0
- package/src/kit/api-worktrees.ts +205 -0
- package/src/kit/asset-capabilities.ts +344 -0
- package/src/kit/asset-compare-core.ts +171 -0
- package/src/kit/asset-editor-context.tsx +101 -0
- package/src/kit/asset-events.ts +96 -0
- package/src/kit/asset-inspector-actions.ts +87 -0
- package/src/kit/asset-selection-viewer-registry.ts +113 -0
- package/src/kit/asset-selection.ts +146 -0
- package/src/kit/asset-thumbnails.ts +25 -0
- package/src/kit/asset-viewers.ts +115 -0
- package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/kit/asset-workflow/asset-ledger.ts +156 -0
- package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/kit/asset-workflow/asset-types.ts +142 -0
- package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
- package/src/kit/asset-workflow/audio-waveform.ts +22 -0
- package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/kit/asset-workflow/image-view-scale.ts +31 -0
- package/src/kit/asset-workflow/import-contract.ts +124 -0
- package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
- package/src/kit/asset-workflow/project-content.ts +288 -0
- package/src/kit/asset-workflow/project-source-index.ts +545 -0
- package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
- package/src/kit/authoring/active-adapter.ts +200 -0
- package/src/kit/authoring/active-systems.ts +422 -0
- package/src/kit/authoring/adapter-key.ts +18 -0
- package/src/kit/authoring/authoring-asset-url.ts +27 -0
- package/src/kit/authoring/bootstrap-state.ts +49 -0
- package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
- package/src/kit/authoring/canvas-scene-guides.ts +84 -0
- package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
- package/src/kit/authoring/consumer-actions.ts +531 -0
- package/src/kit/authoring/design-time-layers.ts +852 -0
- package/src/kit/authoring/design-time-mount-registry.ts +244 -0
- package/src/kit/authoring/edit-mode-authoring.ts +637 -0
- package/src/kit/authoring/empty-project-authoring.ts +22 -0
- package/src/kit/authoring/instance-source-menu.ts +135 -0
- package/src/kit/authoring/layered-pick.ts +185 -0
- package/src/kit/authoring/mounted-root-subjects.ts +146 -0
- package/src/kit/authoring/no-authoring-adapter.ts +59 -0
- package/src/kit/authoring/object3d-document-persistence.ts +122 -0
- package/src/kit/authoring/panel-authoring.ts +121 -0
- package/src/kit/authoring/project-authoring-session.ts +105 -0
- package/src/kit/authoring/provenance.ts +99 -0
- package/src/kit/authoring/react-canvas-navigation.ts +259 -0
- package/src/kit/authoring/react-design-canvas-style.ts +20 -0
- package/src/kit/authoring/react-story-board.ts +917 -0
- package/src/kit/authoring/selection-scope.ts +195 -0
- package/src/kit/authoring/shell-document-ops.ts +169 -0
- package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
- package/src/kit/authoring/story-board-presentation.ts +111 -0
- package/src/kit/authoring/three-root.ts +67 -0
- package/src/kit/authoring/viewport-tool-context.ts +73 -0
- package/src/kit/authoring/viewport-tool-owner.ts +38 -0
- package/src/kit/authoring/world-session-state.ts +101 -0
- package/src/kit/authoring-seam-evidence.ts +300 -0
- package/src/kit/availability-tick.ts +66 -0
- package/src/kit/bitmap-label.ts +120 -0
- package/src/kit/boot-routing.ts +392 -0
- package/src/kit/breakpoint-state.ts +43 -0
- package/src/kit/build-identity.ts +16 -0
- package/src/kit/bytes-codec.ts +62 -0
- package/src/kit/cancellation-reason.ts +58 -0
- package/src/kit/canvas-frames.ts +88 -0
- package/src/kit/capture-camera-pose.ts +77 -0
- package/src/kit/capture-size.ts +88 -0
- package/src/kit/chrome-registry.ts +159 -0
- package/src/kit/chrome-slot-registry.ts +91 -0
- package/src/kit/collaboration-client.ts +264 -0
- package/src/kit/collaboration-presence.ts +41 -0
- package/src/kit/command-dispatch.ts +19 -0
- package/src/kit/command-listener.ts +2182 -0
- package/src/kit/command-registry.ts +71 -0
- package/src/kit/component-board-registry.ts +205 -0
- package/src/kit/component-states-registry.ts +199 -0
- package/src/kit/components/AlignToolbar.tsx +204 -0
- package/src/kit/components/ApplicationMenus.tsx +372 -0
- package/src/kit/components/AssetEditorShell.tsx +216 -0
- package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
- package/src/kit/components/BoardRulers.tsx +354 -0
- package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
- package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
- package/src/kit/components/ChromeSlot.tsx +20 -0
- package/src/kit/components/CodeView.tsx +470 -0
- package/src/kit/components/CompactInspectorShell.tsx +39 -0
- package/src/kit/components/ConsolePanel.tsx +273 -0
- package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
- package/src/kit/components/InspectionProjection.tsx +932 -0
- package/src/kit/components/Inspector.tsx +270 -0
- package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
- package/src/kit/components/InspectorFieldsSection.tsx +290 -0
- package/src/kit/components/InspectorStoriesSection.tsx +92 -0
- package/src/kit/components/InspectorToolSection.tsx +96 -0
- package/src/kit/components/InspectorTransformSection.tsx +245 -0
- package/src/kit/components/LightExplorerPanel.tsx +433 -0
- package/src/kit/components/MediaProperties.tsx +145 -0
- package/src/kit/components/ProjectHeader.tsx +328 -0
- package/src/kit/components/ReactCanvasControls.tsx +358 -0
- package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
- package/src/kit/components/RootTextEditor.tsx +79 -0
- package/src/kit/components/SaveStatus.tsx +70 -0
- package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
- package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
- package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
- package/src/kit/components/ToolHost.tsx +380 -0
- package/src/kit/components/Toolbar.tsx +811 -0
- package/src/kit/components/TransientHint.tsx +44 -0
- package/src/kit/components/VersionControlSection.tsx +470 -0
- package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
- package/src/kit/components/VolterLogo.tsx +18 -0
- package/src/kit/components/WorktreeSwitcher.tsx +712 -0
- package/src/kit/components/account-documents.tsx +1162 -0
- package/src/kit/components/asset-documents.tsx +794 -0
- package/src/kit/components/asset-editor-persistence.ts +216 -0
- package/src/kit/components/asset-selection-section.tsx +545 -0
- package/src/kit/components/asset-thumbnails.tsx +307 -0
- package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
- package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
- package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
- package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/kit/components/asset-viewers/shader-source.ts +144 -0
- package/src/kit/components/board-guides.ts +150 -0
- package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
- package/src/kit/components/canvas-temporary-pivot.ts +34 -0
- package/src/kit/components/core-utilities.tsx +94 -0
- package/src/kit/components/inspector-preview-section.tsx +223 -0
- package/src/kit/components/inspector-revert-label.ts +20 -0
- package/src/kit/components/inspector-selection.ts +42 -0
- package/src/kit/components/inspector-stories-gating.ts +171 -0
- package/src/kit/components/inspector-transform-subject.ts +11 -0
- package/src/kit/components/inspector-transform.ts +88 -0
- package/src/kit/components/kind-documents.tsx +544 -0
- package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
- package/src/kit/components/project-tool-documents.tsx +402 -0
- package/src/kit/components/scene-documents.tsx +221 -0
- package/src/kit/components/status-contributions.tsx +407 -0
- package/src/kit/components/tool-documents.tsx +302 -0
- package/src/kit/components/tool-schema-form.tsx +262 -0
- package/src/kit/components/use-after-paint.ts +41 -0
- package/src/kit/components/use-project-image-assets.ts +86 -0
- package/src/kit/components/workspace-history.ts +32 -0
- package/src/kit/components/world-documents.tsx +570 -0
- package/src/kit/components/world-overlay-gestures.ts +1939 -0
- package/src/kit/composite-screenshot.ts +2238 -0
- package/src/kit/content-entry-source-registry.ts +184 -0
- package/src/kit/contribution-surfaces.ts +48 -0
- package/src/kit/coverage/canvas-reveal.ts +192 -0
- package/src/kit/coverage/design-time-surfaces.ts +101 -0
- package/src/kit/coverage/ontology-invariants.ts +466 -0
- package/src/kit/coverage/session-vitals.ts +503 -0
- package/src/kit/crash-null-boundary.ts +36 -0
- package/src/kit/creation-site-edit.ts +1491 -0
- package/src/kit/creation-site-registry.ts +160 -0
- package/src/kit/delegate-harness-registry.ts +134 -0
- package/src/kit/document-areas.ts +70 -0
- package/src/kit/document-context-registry.ts +193 -0
- package/src/kit/document-open-registry.ts +200 -0
- package/src/kit/document-play-extension.ts +221 -0
- package/src/kit/document-preview-source.ts +20 -0
- package/src/kit/document-renderer-session.ts +138 -0
- package/src/kit/document-stage-sessions.ts +26 -0
- package/src/kit/document-viewports.ts +120 -0
- package/src/kit/editor-api.ts +46 -0
- package/src/kit/editor-chrome-capture.ts +136 -0
- package/src/kit/editor-commands.ts +176 -0
- package/src/kit/editor-console.ts +580 -0
- package/src/kit/editor-current-view.ts +56 -0
- package/src/kit/editor-document-probe.ts +1166 -0
- package/src/kit/editor-git-client.ts +115 -0
- package/src/kit/editor-hotkeys.ts +728 -0
- package/src/kit/editor-lease-view.ts +39 -0
- package/src/kit/editor-lease.ts +415 -0
- package/src/kit/editor-mode.ts +19 -0
- package/src/kit/editor-notifications.ts +140 -0
- package/src/kit/editor-presence.ts +563 -0
- package/src/kit/editor-presentation-activity.ts +58 -0
- package/src/kit/editor-presentation-notice.ts +42 -0
- package/src/kit/editor-runtime.tsx +147 -0
- package/src/kit/editor-server-response.ts +86 -0
- package/src/kit/editor-session-attribution.ts +85 -0
- package/src/kit/editor-session-mode.ts +54 -0
- package/src/kit/editor-state-facets.ts +74 -0
- package/src/kit/editor-view-presentation.ts +777 -0
- package/src/kit/environment-images.ts +58 -0
- package/src/kit/eyedropper-session.ts +60 -0
- package/src/kit/files/file-provider.ts +62 -0
- package/src/kit/files/project-files.ts +270 -0
- package/src/kit/finders/index.ts +137 -0
- package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/kit/frame/frame-parts.ts +30 -0
- package/src/kit/framed-document-capture.ts +34 -0
- package/src/kit/game-globals-prelude.ts +143 -0
- package/src/kit/game-surface-defaults.ts +33 -0
- package/src/kit/gameplay-dom-recording.ts +318 -0
- package/src/kit/gameplay-export-state.ts +14 -0
- package/src/kit/gameplay-replay.ts +417 -0
- package/src/kit/gameplay-session-time.ts +9 -0
- package/src/kit/gameplay-sessions.ts +204 -0
- package/src/kit/hierarchy-component-marks.ts +298 -0
- package/src/kit/hierarchy-internals.ts +197 -0
- package/src/kit/hierarchy-kind-icon.ts +217 -0
- package/src/kit/hierarchy-menu-registry.ts +67 -0
- package/src/kit/hierarchy-node-rows.ts +307 -0
- package/src/kit/hierarchy-panel-view.ts +280 -0
- package/src/kit/hierarchy-projection.ts +76 -0
- package/src/kit/hierarchy-row-media.ts +45 -0
- package/src/kit/hierarchy-row-model.ts +308 -0
- package/src/kit/hierarchy-rows.ts +11 -0
- package/src/kit/hierarchy-walk.ts +86 -0
- package/src/kit/history/editor-session.ts +25 -0
- package/src/kit/history/history-commands.ts +147 -0
- package/src/kit/history/history-delegate.ts +187 -0
- package/src/kit/history/history-limit-notices.ts +43 -0
- package/src/kit/history/history-service.ts +1189 -0
- package/src/kit/history/persistence-coordinator.ts +35 -0
- package/src/kit/history/project-file-history.ts +386 -0
- package/src/kit/history/project-root-history-backends.ts +139 -0
- package/src/kit/history/resource-registry.ts +209 -0
- package/src/kit/history/snapshot-store.ts +103 -0
- package/src/kit/history/source-history-backend.ts +546 -0
- package/src/kit/history-types.ts +124 -0
- package/src/kit/hmr-registration-group.ts +67 -0
- package/src/kit/hmr-stable-react-context.ts +23 -0
- package/src/kit/hotkeys.ts +190 -0
- package/src/kit/inference-diagnostics.ts +69 -0
- package/src/kit/initial-project.ts +80 -0
- package/src/kit/inspection/active-subject.ts +571 -0
- package/src/kit/inspection/active-surface.ts +142 -0
- package/src/kit/inspection/compose-subject.ts +1055 -0
- package/src/kit/inspection/compose.ts +7 -0
- package/src/kit/inspection/display.ts +171 -0
- package/src/kit/inspection/document-subject.ts +109 -0
- package/src/kit/inspection/game-subject.ts +85 -0
- package/src/kit/inspection/null-subject.ts +119 -0
- package/src/kit/inspection/serialize.ts +357 -0
- package/src/kit/inspection/use-active-inspection.ts +180 -0
- package/src/kit/inspection-model.ts +542 -0
- package/src/kit/inspection-node-media.ts +58 -0
- package/src/kit/inspector-presentation.ts +203 -0
- package/src/kit/inspector-property-grouping.ts +64 -0
- package/src/kit/inspector-section-registry.ts +221 -0
- package/src/kit/instance-source-actions.ts +163 -0
- package/src/kit/js-heap.ts +71 -0
- package/src/kit/key-actions.ts +91 -0
- package/src/kit/keymap-presets.ts +428 -0
- package/src/kit/layout-policy.ts +31 -0
- package/src/kit/light-explorer-model.ts +134 -0
- package/src/kit/live-canvas-frame.ts +55 -0
- package/src/kit/live-document.ts +296 -0
- package/src/kit/live-gesture-lock.ts +50 -0
- package/src/kit/live-seam-evidence.ts +11 -0
- package/src/kit/live-session-registry.ts +220 -0
- package/src/kit/live-transition.ts +391 -0
- package/src/kit/manifest-project.ts +107 -0
- package/src/kit/module-fetch-diagnosis.ts +192 -0
- package/src/kit/mount-failure-report.ts +154 -0
- package/src/kit/native-selection-style.ts +497 -0
- package/src/kit/object3d-document-write-policy.ts +137 -0
- package/src/kit/packaged-runtime.ts +108 -0
- package/src/kit/palettes/maya.palette.json +57 -0
- package/src/kit/palettes/substance.palette.json +57 -0
- package/src/kit/performance-profiler.ts +367 -0
- package/src/kit/performance-sources.ts +69 -0
- package/src/kit/photograph-notice.ts +141 -0
- package/src/kit/play-boot-phase.ts +166 -0
- package/src/kit/play-camera-flight.ts +35 -0
- package/src/kit/png-encode.worker.ts +26 -0
- package/src/kit/presentation-surface.ts +248 -0
- package/src/kit/product-command.ts +90 -0
- package/src/kit/project-adapter.ts +1140 -0
- package/src/kit/project-asset-refresh.ts +23 -0
- package/src/kit/project-asset-roots.ts +68 -0
- package/src/kit/project-local-state.ts +151 -0
- package/src/kit/project-manager.ts +243 -0
- package/src/kit/project-module-changes.ts +201 -0
- package/src/kit/project-module-split.ts +270 -0
- package/src/kit/project-play-layers.ts +25 -0
- package/src/kit/project-provenance.ts +115 -0
- package/src/kit/project-ready.ts +42 -0
- package/src/kit/project-shape.ts +68 -0
- package/src/kit/project-tools.ts +107 -0
- package/src/kit/projection-types.ts +44 -0
- package/src/kit/readiness.ts +113 -0
- package/src/kit/renderer-resource-counts.ts +27 -0
- package/src/kit/reported-play-state.ts +90 -0
- package/src/kit/resolve-contributed-command.ts +14 -0
- package/src/kit/resolve-relative-specifier.ts +33 -0
- package/src/kit/retained-document-states.ts +91 -0
- package/src/kit/scene-document-plan.ts +320 -0
- package/src/kit/scene-live-open.ts +210 -0
- package/src/kit/scoped-game-css.ts +152 -0
- package/src/kit/served-url.ts +5 -0
- package/src/kit/session-close.ts +17 -0
- package/src/kit/session-tombstone.ts +127 -0
- package/src/kit/settings/settings-provider.ts +82 -0
- package/src/kit/settings-store.ts +348 -0
- package/src/kit/shell-document-state.ts +27 -0
- package/src/kit/shell-store-door.ts +45 -0
- package/src/kit/shell-store.ts +722 -0
- package/src/kit/source-conflict.ts +122 -0
- package/src/kit/stage-context.ts +377 -0
- package/src/kit/stage-invalidation.ts +25 -0
- package/src/kit/stage-store-registry.ts +69 -0
- package/src/kit/startup-failure.ts +80 -0
- package/src/kit/state-report-deferral.ts +73 -0
- package/src/kit/storage/host-files-storage.ts +97 -0
- package/src/kit/storage/http-storage.ts +174 -0
- package/src/kit/storage/index.ts +75 -0
- package/src/kit/storage/mem-storage.ts +158 -0
- package/src/kit/storage/path-lock.ts +44 -0
- package/src/kit/storage/paths.ts +26 -0
- package/src/kit/storage-types.ts +127 -0
- package/src/kit/stories/StoryPreviewMount.tsx +306 -0
- package/src/kit/stories/compose-project-stories.ts +255 -0
- package/src/kit/stories/prefabs-finder.ts +54 -0
- package/src/kit/stories/prefabs-from-stories.ts +182 -0
- package/src/kit/stories/project-story-regions.ts +24 -0
- package/src/kit/stories/story-capture.ts +579 -0
- package/src/kit/stories/story-declared-medium.ts +126 -0
- package/src/kit/stories/story-discovery.ts +176 -0
- package/src/kit/stories/story-dom-runtime.ts +78 -0
- package/src/kit/stories/story-grouping.ts +111 -0
- package/src/kit/stories/story-mount-turn.ts +27 -0
- package/src/kit/stories/story-presentation.ts +215 -0
- package/src/kit/stories/story-preview-component.ts +7 -0
- package/src/kit/stories/story-registry.ts +530 -0
- package/src/kit/stories-scope.ts +35 -0
- package/src/kit/story-document-openers.ts +36 -0
- package/src/kit/story-thumbnails.ts +47 -0
- package/src/kit/surface-keyboard.ts +101 -0
- package/src/kit/surface-state.ts +135 -0
- package/src/kit/system-seam-evidence.ts +72 -0
- package/src/kit/tab-census.ts +202 -0
- package/src/kit/tab-lifecycle-client.ts +227 -0
- package/src/kit/theme-library.ts +897 -0
- package/src/kit/theme-preference.ts +429 -0
- package/src/kit/three-viewport-presentation.ts +23 -0
- package/src/kit/tool-contribution-play.ts +74 -0
- package/src/kit/tool-loader.ts +1918 -0
- package/src/kit/transform-mode-request.ts +66 -0
- package/src/kit/transient-hint.ts +78 -0
- package/src/kit/transport-strip.tsx +174 -0
- package/src/kit/ui-source/adapter-region-includes.ts +238 -0
- package/src/kit/ui-source/file-region-resolver.ts +302 -0
- package/src/kit/ui-source/inspect.ts +775 -0
- package/src/kit/ui-source/source-write-backend.ts +605 -0
- package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
- package/src/kit/user-local-state.ts +105 -0
- package/src/kit/viewport-activation-timings.ts +840 -0
- package/src/kit/viewport-editor-controls.ts +22 -0
- package/src/kit/viewport-presentation.ts +668 -0
- package/src/kit/viewport-surface-status.tsx +55 -0
- package/src/kit/wait-until.ts +37 -0
- package/src/kit/worker-call-metrics.ts +166 -0
- package/src/kit/workspace-areas.ts +191 -0
- package/src/kit/workspace-aux-commands.ts +11 -0
- package/src/kit/workspace-available-documents.ts +142 -0
- package/src/kit/workspace-core-utilities.ts +31 -0
- package/src/kit/workspace-document-ids.ts +59 -0
- package/src/kit/workspace-document-registry.ts +624 -0
- package/src/kit/workspace-document-restore.ts +146 -0
- package/src/kit/workspace-host-commands.ts +141 -0
- package/src/kit/workspace-persistence-gate.ts +40 -0
- package/src/kit/workspace-play-utilities.ts +44 -0
- package/src/kit/workspace-presets.ts +446 -0
- package/src/kit/workspace-regions.ts +276 -0
- package/src/kit/workspace-static-panels.ts +73 -0
- package/src/kit/workspace-status-registry.ts +121 -0
- package/src/kit/workspace-storage.ts +35 -0
- package/src/kit/workspace-style.ts +226 -0
- package/src/kit/workspace-utility-commands.ts +74 -0
- package/src/kit/workspace-utility-registry.ts +263 -0
- package/src/kit/world-adoption-event.ts +23 -0
- package/src/kit/world-adoption.ts +115 -0
- package/src/kit/world-canvas-viewport-state.ts +35 -0
- package/src/kit/world-document-routing.ts +104 -0
- package/src/kit/world-pan-state.ts +198 -0
- package/src/kit/write-pipe.ts +173 -0
- package/src/layout-arrangements.ts +5 -0
- package/src/layouts.tsx +108 -0
- package/src/looks.ts +16 -0
- package/src/project/output-roots.ts +73 -0
- package/src/project/tab-census.ts +155 -0
- package/src/project-tool-catalog.ts +104 -0
- package/src/selection.tsx +107 -0
- package/src/services.ts +18 -0
- package/src/session/build-report.ts +22 -0
- package/src/session/collaboration-types.ts +262 -0
- package/src/session/command-table.ts +327 -0
- package/src/session/discovery.ts +100 -0
- package/src/session/editor-brand.ts +48 -0
- package/src/session/editor-compatibility.ts +317 -0
- package/src/session/editor-control-lifecycle.ts +68 -0
- package/src/session/editor-control-protocol.ts +5 -0
- package/src/session/entrypoint-selection-readers.ts +66 -0
- package/src/session/entrypoint-selection-source.ts +120 -0
- package/src/session/game-css-scope.ts +30 -0
- package/src/session/hosted-attachment.ts +225 -0
- package/src/session/limited-view.ts +82 -0
- package/src/session/product-create.ts +24 -0
- package/src/session/product-locator.ts +478 -0
- package/src/session/project-module-url.ts +242 -0
- package/src/session/project-serving.ts +164 -0
- package/src/session/project-upgrade.ts +403 -0
- package/src/session/registry-format.ts +210 -0
- package/src/session/relative-path-guard.ts +56 -0
- package/src/session/scoped-game-css.ts +461 -0
- package/src/session/source-glob.ts +15 -0
- package/src/session/tool-contribution-convention.ts +123 -0
- package/src/session/workbench-locator.ts +712 -0
- package/src/session.ts +41 -0
- package/src/share.ts +160 -0
- package/src/source-analysis.ts +28 -0
- package/src/source-authoring.ts +439 -0
- package/src/tools/errors.ts +91 -0
- package/src/tools/provider-execution.ts +70 -0
- package/src/tools/registry.ts +341 -0
- package/src/tools/types.ts +159 -0
- package/src/transport.ts +100 -0
- package/src/types.ts +1693 -0
- package/src/views.ts +164 -0
- package/src/widgets/design-system.ts +93 -0
- package/src/widgets/editor-appearance.ts +151 -0
- package/src/widgets/editor-material.ts +83 -0
- package/src/widgets/icon-set-registry.ts +105 -0
- package/src/widgets/index.ts +71 -0
- package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
- package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
- package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
- package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
- package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
- package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
- package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
- package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
- package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
- package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
- package/src/widgets/inspector-widgets/color-utils.ts +201 -0
- package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
- package/src/widgets/inspector-widgets/index.ts +25 -0
- package/src/widgets/inspector-widgets/shared.tsx +140 -0
- package/src/widgets/interactive-edit-scope.ts +33 -0
- package/src/widgets/patterns/Dialog.tsx +140 -0
- package/src/widgets/patterns/Fields.tsx +44 -0
- package/src/widgets/patterns/List.tsx +25 -0
- package/src/widgets/patterns/StateSurface.tsx +40 -0
- package/src/widgets/patterns/Surfaces.tsx +122 -0
- package/src/widgets/patterns/Tabs.tsx +80 -0
- package/src/widgets/patterns/Toolbar.tsx +72 -0
- package/src/widgets/patterns/Tree.tsx +72 -0
- package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
- package/src/widgets/primitives/Button.tsx +62 -0
- package/src/widgets/primitives/ColorInput.tsx +78 -0
- package/src/widgets/primitives/DraftTextInput.tsx +63 -0
- package/src/widgets/primitives/EditorIcon.tsx +157 -0
- package/src/widgets/primitives/FormControls.tsx +88 -0
- package/src/widgets/primitives/HoverPreview.tsx +96 -0
- package/src/widgets/primitives/JsonInput.tsx +113 -0
- package/src/widgets/primitives/Layout.tsx +100 -0
- package/src/widgets/primitives/Menu.tsx +161 -0
- package/src/widgets/primitives/NumberInput.tsx +169 -0
- package/src/widgets/primitives/Panel.tsx +80 -0
- package/src/widgets/primitives/SectionHeader.tsx +77 -0
- package/src/widgets/primitives/Text.tsx +54 -0
- package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
- package/src/widgets/primitives/Tooltip.tsx +204 -0
- package/src/widgets/primitives/Vec3Input.tsx +70 -0
- package/src/widgets/primitives/banner-tones.ts +32 -0
- package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
- package/src/widgets/primitives/editor-icons.ts +254 -0
- package/src/widgets/primitives/panel-header-styles.ts +42 -0
- package/src/widgets/theme.ts +2841 -0
- package/src/widgets/z-index.ts +25 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Divider,
|
|
3
|
+
EditorIcon,
|
|
4
|
+
editorIcons,
|
|
5
|
+
Inline,
|
|
6
|
+
Menu,
|
|
7
|
+
MenuItem,
|
|
8
|
+
MenuSeparator,
|
|
9
|
+
MenuTrigger,
|
|
10
|
+
Text,
|
|
11
|
+
} from '@volter/sdk/widgets';
|
|
12
|
+
import {
|
|
13
|
+
type ReactNode,
|
|
14
|
+
useEffect,
|
|
15
|
+
useReducer,
|
|
16
|
+
useRef,
|
|
17
|
+
useState,
|
|
18
|
+
useSyncExternalStore,
|
|
19
|
+
} from 'react';
|
|
20
|
+
import { activeProduct } from '@volter/sdk/kit/active-product';
|
|
21
|
+
import { BUNDLED_EDITOR_VERSION } from '../build-identity';
|
|
22
|
+
import {
|
|
23
|
+
contributedChromeVersion,
|
|
24
|
+
contributedHeaderItems,
|
|
25
|
+
subscribeContributedChrome,
|
|
26
|
+
} from '@volter/sdk/kit/chrome-registry';
|
|
27
|
+
import { revealInFinder } from '@volter/sdk/kit/editor-api';
|
|
28
|
+
import { getCurrentProject, onProjectChange } from '@volter/sdk/kit/project-manager';
|
|
29
|
+
import {
|
|
30
|
+
activeEditorWorkspace,
|
|
31
|
+
editorWorkspaces,
|
|
32
|
+
editorWorkspacesVersion,
|
|
33
|
+
setEditorWorkspace,
|
|
34
|
+
subscribeEditorWorkspace,
|
|
35
|
+
subscribeEditorWorkspaces,
|
|
36
|
+
workspaceApplies,
|
|
37
|
+
} from '@volter/sdk/kit/workspace-presets';
|
|
38
|
+
import {
|
|
39
|
+
activeChromeRegions,
|
|
40
|
+
chromeRegionsVersion,
|
|
41
|
+
subscribeChromeRegions,
|
|
42
|
+
} from '@volter/sdk/kit/workspace-regions';
|
|
43
|
+
import { ApplicationMenus } from './ApplicationMenus';
|
|
44
|
+
import { ChromeSlot } from './ChromeSlot';
|
|
45
|
+
import { WorktreeSwitcher } from './WorktreeSwitcher';
|
|
46
|
+
|
|
47
|
+
export function ProjectHeader({
|
|
48
|
+
transport,
|
|
49
|
+
}: {
|
|
50
|
+
/** Controlled production transport for bounded hosts; the application
|
|
51
|
+
* defaults to the connected PlayBar. */
|
|
52
|
+
transport?: ReactNode | undefined;
|
|
53
|
+
}) {
|
|
54
|
+
const [, forceUpdate] = useReducer((x: number) => x + 1, 0);
|
|
55
|
+
useEffect(() => onProjectChange(forceUpdate), []);
|
|
56
|
+
const [menuOpen, setMenuOpen] = useState(false);
|
|
57
|
+
const menuRef = useRef<HTMLDivElement>(null);
|
|
58
|
+
|
|
59
|
+
const project = getCurrentProject();
|
|
60
|
+
const projectName = project?.config.name ?? 'No Project';
|
|
61
|
+
const projectVersion = project?.config.version ?? null;
|
|
62
|
+
const engineVersion = project?.config.engine.version ?? null;
|
|
63
|
+
const manifestVersion = project?.config.manifestVersion ?? null;
|
|
64
|
+
const projectPath = project?.rootPath ?? '';
|
|
65
|
+
// Close menu on outside click
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!menuOpen) return;
|
|
68
|
+
const handler = (e: MouseEvent) => {
|
|
69
|
+
if (menuRef.current && !menuRef.current.contains(e.target as Node)) {
|
|
70
|
+
setMenuOpen(false);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
document.addEventListener('mousedown', handler);
|
|
74
|
+
return () => document.removeEventListener('mousedown', handler);
|
|
75
|
+
}, [menuOpen]);
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<header className="volter-project-header">
|
|
79
|
+
{/* W5 (W4-reviewer candidate — transport narrow-width overlap guard):
|
|
80
|
+
the header is now THREE flex columns — name (shrinkable, ellipsized)
|
|
81
|
+
| transport (fixed) | right spacer — replacing the W4 absolute
|
|
82
|
+
centering, which let the transport cluster overlap the project name
|
|
83
|
+
at narrow widths. Equal-flex side columns keep the transport
|
|
84
|
+
visually centered whenever space allows; flex items cannot overlap
|
|
85
|
+
when it doesn't. */}
|
|
86
|
+
{/* Project name — clickable dropdown trigger. The cluster wrapper is
|
|
87
|
+
layout-neutral under bars chrome and becomes the LEFT glass island
|
|
88
|
+
under islands chrome (P6-U3); the dropdown Menu stays a SIBLING of
|
|
89
|
+
the island so the island's backdrop-filter never captures it. */}
|
|
90
|
+
{activeProduct()?.nativeMenus ? (
|
|
91
|
+
<div className="volter-project-header-left" />
|
|
92
|
+
) : (
|
|
93
|
+
<div ref={menuRef} className="volter-project-header-left">
|
|
94
|
+
<div className="volter-project-header-cluster volter-chrome-island volter-glass-island">
|
|
95
|
+
{/* THE LEADING ITEM IS A BARE GLYPH, and that is transcription, not
|
|
96
|
+
economy. Blender opens its top bar with an app mark whose INK
|
|
97
|
+
starts at the band's own inset and whose click opens a MENU —
|
|
98
|
+
the mark IS the app menu's trigger. Measured on `topbar.png` at
|
|
99
|
+
native 2x: device x 12..43, i.e. CSS 6.0..21.5 — 16.0 wide, 13.0
|
|
100
|
+
tall — and the first menu word's ink follows at CSS 32.0. (The
|
|
101
|
+
whole-frame read's "32 CSS px app mark" was that 32-DEVICE-px
|
|
102
|
+
width read as CSS, and its "menu words start at 60" followed
|
|
103
|
+
from it; the frame says 16 and 32.)
|
|
104
|
+
|
|
105
|
+
Ours used to spend 67 px here on a padded pill drawing the
|
|
106
|
+
project NAME, which ellipsized to `prob…` at 1728 even for an
|
|
107
|
+
eight-character name, and the switcher beside it another 204.
|
|
108
|
+
The project's identity is not lost by the glyph: it is the
|
|
109
|
+
browser TAB's title (`AppRoot.tsx` writes `document.title` from
|
|
110
|
+
the project name — the tab strip IS our OS title bar, the place
|
|
111
|
+
Blender puts the file name), this button's tooltip and
|
|
112
|
+
accessible name, and the first row of the menu it opens. */}
|
|
113
|
+
<MenuTrigger
|
|
114
|
+
data-testid="project-menu-trigger"
|
|
115
|
+
aria-label={`${projectName} project menu`}
|
|
116
|
+
title={projectPath ? `${projectName} — ${projectPath}` : projectName}
|
|
117
|
+
onClick={() => setMenuOpen((v) => !v)}
|
|
118
|
+
onKeyDown={(event) => {
|
|
119
|
+
if (event.key !== 'ArrowDown') return;
|
|
120
|
+
event.preventDefault();
|
|
121
|
+
setMenuOpen(true);
|
|
122
|
+
}}
|
|
123
|
+
className="volter-project-trigger"
|
|
124
|
+
>
|
|
125
|
+
<EditorIcon icon={editorIcons.content.project} />
|
|
126
|
+
{/* The name stays in the DOM at zero pixels: the accessible name
|
|
127
|
+
above is a LABEL, this is the element's CONTENT, and it is what
|
|
128
|
+
`data-project` has always carried for the tooling that reads
|
|
129
|
+
which project a session has open. */}
|
|
130
|
+
<Text
|
|
131
|
+
data-testid="project-name"
|
|
132
|
+
data-project={projectName}
|
|
133
|
+
data-project-version={projectVersion ?? undefined}
|
|
134
|
+
variant="label"
|
|
135
|
+
className="volter-sr-only"
|
|
136
|
+
>
|
|
137
|
+
{projectName}
|
|
138
|
+
</Text>
|
|
139
|
+
</MenuTrigger>
|
|
140
|
+
<WorktreeSwitcher />
|
|
141
|
+
<Inline onPointerDown={() => setMenuOpen(false)} className="volter-project-app-menus">
|
|
142
|
+
<ApplicationMenus />
|
|
143
|
+
</Inline>
|
|
144
|
+
</div>
|
|
145
|
+
<WorkspaceTabs />
|
|
146
|
+
|
|
147
|
+
{menuOpen && (
|
|
148
|
+
<Menu
|
|
149
|
+
autoFocusFirst
|
|
150
|
+
onDismiss={() => {
|
|
151
|
+
const trigger = menuRef.current?.querySelector<HTMLButtonElement>(
|
|
152
|
+
'[data-testid="project-menu-trigger"]',
|
|
153
|
+
);
|
|
154
|
+
setMenuOpen(false);
|
|
155
|
+
requestAnimationFrame(() => trigger?.focus());
|
|
156
|
+
}}
|
|
157
|
+
className="volter-project-menu"
|
|
158
|
+
>
|
|
159
|
+
{/* IDENTITY'S READABLE HOME. The trigger is a glyph, so the name
|
|
160
|
+
is the first thing this menu says — the row Blender's OS title
|
|
161
|
+
bar carries and a browser window does not. */}
|
|
162
|
+
<Text
|
|
163
|
+
data-testid="project-menu-name"
|
|
164
|
+
title={projectName}
|
|
165
|
+
variant="label"
|
|
166
|
+
truncate
|
|
167
|
+
className="volter-project-menu-name"
|
|
168
|
+
>
|
|
169
|
+
{projectName}
|
|
170
|
+
</Text>
|
|
171
|
+
{projectPath && (
|
|
172
|
+
<Text
|
|
173
|
+
data-testid="project-menu-path"
|
|
174
|
+
title={projectPath}
|
|
175
|
+
variant="caption"
|
|
176
|
+
tone="dim"
|
|
177
|
+
selectable
|
|
178
|
+
truncate
|
|
179
|
+
className="volter-project-path"
|
|
180
|
+
>
|
|
181
|
+
{projectPath}
|
|
182
|
+
</Text>
|
|
183
|
+
)}
|
|
184
|
+
{projectVersion && engineVersion && manifestVersion !== null && (
|
|
185
|
+
<>
|
|
186
|
+
{projectPath && <MenuSeparator />}
|
|
187
|
+
<div data-testid="project-version-summary" className="volter-project-versions">
|
|
188
|
+
<span>Editor</span>
|
|
189
|
+
<Text variant="code" tone="muted">
|
|
190
|
+
v{BUNDLED_EDITOR_VERSION}
|
|
191
|
+
</Text>
|
|
192
|
+
<span>Project</span>
|
|
193
|
+
<Text variant="code" tone="muted">
|
|
194
|
+
v{projectVersion}
|
|
195
|
+
</Text>
|
|
196
|
+
<span>Engine</span>
|
|
197
|
+
<Text variant="code" tone="muted">
|
|
198
|
+
v{engineVersion}
|
|
199
|
+
</Text>
|
|
200
|
+
<span>Format</span>
|
|
201
|
+
<Text variant="code" tone="muted">
|
|
202
|
+
v{manifestVersion}
|
|
203
|
+
</Text>
|
|
204
|
+
</div>
|
|
205
|
+
<MenuSeparator />
|
|
206
|
+
</>
|
|
207
|
+
)}
|
|
208
|
+
{projectPath && (
|
|
209
|
+
<MenuItem
|
|
210
|
+
onSelect={() => {
|
|
211
|
+
setMenuOpen(false);
|
|
212
|
+
revealInFinder(projectPath);
|
|
213
|
+
}}
|
|
214
|
+
>
|
|
215
|
+
Show in Finder
|
|
216
|
+
</MenuItem>
|
|
217
|
+
)}
|
|
218
|
+
<MenuItem
|
|
219
|
+
data-testid="project-menu-history"
|
|
220
|
+
onSelect={() => {
|
|
221
|
+
setMenuOpen(false);
|
|
222
|
+
window.dispatchEvent(new CustomEvent('editor:show-history-tab'));
|
|
223
|
+
}}
|
|
224
|
+
>
|
|
225
|
+
{/* §8 naming: `Undo History`, never plain `History` (git/version
|
|
226
|
+
confusion). */}
|
|
227
|
+
Undo History…
|
|
228
|
+
</MenuItem>
|
|
229
|
+
</Menu>
|
|
230
|
+
)}
|
|
231
|
+
</div>
|
|
232
|
+
)}
|
|
233
|
+
{/* W4 (§4.1/§9 W4, inventory row V4 + the recorded always-visible-
|
|
234
|
+
transport work item): the global TRANSPORT cluster lives in the
|
|
235
|
+
command bar — reachable regardless of which center document is
|
|
236
|
+
active (asset/story docs used to hide play/pause/stop entirely).
|
|
237
|
+
Centered in the row, matching the §4.1 mock's `> || >`. */}
|
|
238
|
+
<Inline
|
|
239
|
+
data-testid="header-transport"
|
|
240
|
+
className="volter-project-transport volter-chrome-island volter-glass-island"
|
|
241
|
+
align="center"
|
|
242
|
+
>
|
|
243
|
+
{transport ?? <ProjectTransport />}
|
|
244
|
+
</Inline>
|
|
245
|
+
{/* Conversation entry moved to the global bottom shell row. Keep this
|
|
246
|
+
equal-width spacer so transport remains visually centered. */}
|
|
247
|
+
<Inline className="volter-project-header-right" justify="end" align="center">
|
|
248
|
+
{/* WHO IS IN THIS SESSION. A chrome slot, not a component: the host
|
|
249
|
+
owns the place and a package owns what sits there
|
|
250
|
+
(`chrome-slot-registry.ts`). the collaboration package fills it; a
|
|
251
|
+
build without that package renders nothing here, which is the
|
|
252
|
+
honest answer for an editor nobody else is in. */}
|
|
253
|
+
<ChromeSlot slot="header-trailing" />
|
|
254
|
+
</Inline>
|
|
255
|
+
{/* SaveStatus moved OUT of this command header (H3): status is status,
|
|
256
|
+
not a command — it renders in the W4 status bar
|
|
257
|
+
(`status-contributions.tsx`). */}
|
|
258
|
+
</header>
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* The WORKSPACE TAB STRIP — Blender's top bar, shown only when the active
|
|
264
|
+
* chrome regions say so (`workspaceTabs`, a workspace's region or the person's;
|
|
265
|
+
* Blender's workspaces turn it on). A click is the explicit act the workspace
|
|
266
|
+
* ruling requires (`workspace-presets.ts`); the strip derives nothing.
|
|
267
|
+
*/
|
|
268
|
+
function WorkspaceTabs() {
|
|
269
|
+
useSyncExternalStore(subscribeChromeRegions, chromeRegionsVersion, chromeRegionsVersion);
|
|
270
|
+
useSyncExternalStore(subscribeEditorWorkspaces, editorWorkspacesVersion, editorWorkspacesVersion);
|
|
271
|
+
const active = useSyncExternalStore(
|
|
272
|
+
subscribeEditorWorkspace,
|
|
273
|
+
activeEditorWorkspace,
|
|
274
|
+
activeEditorWorkspace,
|
|
275
|
+
);
|
|
276
|
+
if (activeChromeRegions().workspaceTabs !== 'shown') return null;
|
|
277
|
+
const workspaces = editorWorkspaces().filter((entry) => workspaceApplies(entry.id));
|
|
278
|
+
return (
|
|
279
|
+
<>
|
|
280
|
+
{/* Blender closes its menu words with a 1x20 rule before the workspace
|
|
281
|
+
tabs begin (measured `topbar.png`, halved: a #2e2e2e rule sitting 16px
|
|
282
|
+
past `Help`'s ink). Without it the two regions read as one
|
|
283
|
+
undifferentiated run of words, which is what ours did. It belongs to
|
|
284
|
+
the strip, so it appears and disappears with it. */}
|
|
285
|
+
<Divider orientation="vertical" className="volter-project-menu-rule" />
|
|
286
|
+
<div
|
|
287
|
+
role="tablist"
|
|
288
|
+
aria-label="Workspaces"
|
|
289
|
+
data-testid="workspace-tabs"
|
|
290
|
+
className="volter-workspace-tabs"
|
|
291
|
+
>
|
|
292
|
+
{workspaces.map((entry) => (
|
|
293
|
+
<button
|
|
294
|
+
key={entry.id}
|
|
295
|
+
type="button"
|
|
296
|
+
role="tab"
|
|
297
|
+
aria-selected={entry.id === active}
|
|
298
|
+
title={entry.description}
|
|
299
|
+
className="volter-workspace-tab"
|
|
300
|
+
onClick={() => setEditorWorkspace(entry.id)}
|
|
301
|
+
>
|
|
302
|
+
{entry.title}
|
|
303
|
+
</button>
|
|
304
|
+
))}
|
|
305
|
+
</div>
|
|
306
|
+
</>
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** The global transport cluster: whatever the project's packages contribute
|
|
311
|
+
* to the header (`@volter/sdk/chrome`, `.header`) — the Play transport
|
|
312
|
+
* ships with `@volter/editor-game`; a folder of models contributes nothing here. */
|
|
313
|
+
function ProjectTransport() {
|
|
314
|
+
useSyncExternalStore(
|
|
315
|
+
subscribeContributedChrome,
|
|
316
|
+
contributedChromeVersion,
|
|
317
|
+
contributedChromeVersion,
|
|
318
|
+
);
|
|
319
|
+
const items = contributedHeaderItems();
|
|
320
|
+
if (items.length === 0) return null;
|
|
321
|
+
return (
|
|
322
|
+
<>
|
|
323
|
+
{items.map(({ id, Component }) => (
|
|
324
|
+
<Component key={id} documentId="" />
|
|
325
|
+
))}
|
|
326
|
+
</>
|
|
327
|
+
);
|
|
328
|
+
}
|
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import {
|
|
2
|
+
faExpand,
|
|
3
|
+
faMagnifyingGlassMinus,
|
|
4
|
+
faMagnifyingGlassPlus,
|
|
5
|
+
faRotate,
|
|
6
|
+
} from '@fortawesome/free-solid-svg-icons';
|
|
7
|
+
import {
|
|
8
|
+
AnchoredMenu,
|
|
9
|
+
Button,
|
|
10
|
+
EditorIcon,
|
|
11
|
+
FloatingToolbar,
|
|
12
|
+
IconButton,
|
|
13
|
+
MenuItem,
|
|
14
|
+
MenuSeparator,
|
|
15
|
+
Select,
|
|
16
|
+
TextInput,
|
|
17
|
+
} from '@volter/sdk/widgets';
|
|
18
|
+
import { type RefObject, useCallback, useRef, useState, useSyncExternalStore } from 'react';
|
|
19
|
+
import {
|
|
20
|
+
fitReactStoryBoard,
|
|
21
|
+
getReactStoryBoardViewport,
|
|
22
|
+
type ReactStoryBoardViewportState,
|
|
23
|
+
setActiveReactStoryBoardViewport,
|
|
24
|
+
subscribeReactStoryBoardViewport,
|
|
25
|
+
toggleActiveReactStoryBoardViewportRotation,
|
|
26
|
+
} from '@volter/sdk/kit/authoring/react-story-board';
|
|
27
|
+
import type { ViewportToolContext } from '@volter/sdk/kit/authoring/viewport-tool-context';
|
|
28
|
+
import {
|
|
29
|
+
getRootCanvasViewport,
|
|
30
|
+
setRootCanvasViewport,
|
|
31
|
+
subscribeRootCanvasViewport,
|
|
32
|
+
} from '@volter/sdk/kit/world-canvas-viewport-state';
|
|
33
|
+
import {
|
|
34
|
+
getRootPan,
|
|
35
|
+
panTransformValue,
|
|
36
|
+
setRootView,
|
|
37
|
+
subscribeRootPan,
|
|
38
|
+
} from '@volter/sdk/kit/world-pan-state';
|
|
39
|
+
import { useEditorStore } from '@volter/sdk/kit/editor-runtime';
|
|
40
|
+
|
|
41
|
+
const VIEWPORT_PRESETS = {
|
|
42
|
+
fill: null,
|
|
43
|
+
desktop: { width: 1440, height: 900 },
|
|
44
|
+
tablet: { width: 768, height: 1024 },
|
|
45
|
+
mobile: { width: 390, height: 844 },
|
|
46
|
+
} as const;
|
|
47
|
+
|
|
48
|
+
function ResponsiveViewportControls({
|
|
49
|
+
boardViewport,
|
|
50
|
+
containerRef,
|
|
51
|
+
selectViewport,
|
|
52
|
+
viewportValue,
|
|
53
|
+
}: {
|
|
54
|
+
boardViewport: ReactStoryBoardViewportState | null;
|
|
55
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
56
|
+
selectViewport(preset: string): void;
|
|
57
|
+
viewportValue: string;
|
|
58
|
+
}) {
|
|
59
|
+
return (
|
|
60
|
+
<>
|
|
61
|
+
<Select
|
|
62
|
+
aria-label="Responsive viewport"
|
|
63
|
+
title={
|
|
64
|
+
boardViewport?.locked
|
|
65
|
+
? 'Viewport is locked by this story’s globals.viewport'
|
|
66
|
+
: 'Responsive viewport'
|
|
67
|
+
}
|
|
68
|
+
value={viewportValue}
|
|
69
|
+
disabled={boardViewport?.locked === true}
|
|
70
|
+
onChange={(event) => selectViewport(event.target.value)}
|
|
71
|
+
className="volter-react-viewport-select"
|
|
72
|
+
>
|
|
73
|
+
<option value="fill">Responsive</option>
|
|
74
|
+
{boardViewport ? (
|
|
75
|
+
boardViewport.choices.map((choice) => (
|
|
76
|
+
<option key={choice.id} value={choice.id}>
|
|
77
|
+
{choice.label} · {choice.width}×{choice.height}
|
|
78
|
+
</option>
|
|
79
|
+
))
|
|
80
|
+
) : (
|
|
81
|
+
<>
|
|
82
|
+
<option value="desktop">Desktop · 1440×900</option>
|
|
83
|
+
<option value="tablet">Tablet · 768×1024</option>
|
|
84
|
+
<option value="mobile">Mobile · 390×844</option>
|
|
85
|
+
</>
|
|
86
|
+
)}
|
|
87
|
+
</Select>
|
|
88
|
+
{boardViewport && (
|
|
89
|
+
<IconButton
|
|
90
|
+
aria-label="Rotate viewport"
|
|
91
|
+
title={
|
|
92
|
+
boardViewport.locked
|
|
93
|
+
? 'Viewport is locked by this story’s globals.viewport'
|
|
94
|
+
: 'Rotate viewport'
|
|
95
|
+
}
|
|
96
|
+
size="comfortable"
|
|
97
|
+
disabled={boardViewport.locked}
|
|
98
|
+
onClick={() => toggleActiveReactStoryBoardViewportRotation(containerRef.current)}
|
|
99
|
+
>
|
|
100
|
+
<EditorIcon icon={faRotate} size="md" />
|
|
101
|
+
</IconButton>
|
|
102
|
+
)}
|
|
103
|
+
</>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function ReactCanvasControls({
|
|
108
|
+
containerRef,
|
|
109
|
+
context,
|
|
110
|
+
boardOnly = false,
|
|
111
|
+
}: {
|
|
112
|
+
containerRef: RefObject<HTMLDivElement | null>;
|
|
113
|
+
context: ViewportToolContext | null;
|
|
114
|
+
/** Fixed-pixel component boards need only the common Figma-style camera
|
|
115
|
+
* controls. Responsive presets and entity framing belong to DOM authoring. */
|
|
116
|
+
boardOnly?: boolean;
|
|
117
|
+
}) {
|
|
118
|
+
const store = useEditorStore();
|
|
119
|
+
useSyncExternalStore(store.subscribe, store.getSnapshot);
|
|
120
|
+
const view = useSyncExternalStore(subscribeRootPan, getRootPan);
|
|
121
|
+
const viewport = useSyncExternalStore(subscribeRootCanvasViewport, getRootCanvasViewport);
|
|
122
|
+
const boardViewport = useSyncExternalStore(
|
|
123
|
+
subscribeReactStoryBoardViewport,
|
|
124
|
+
() => getReactStoryBoardViewport(containerRef.current),
|
|
125
|
+
() => null,
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
const zoomAroundCenter = useCallback(
|
|
129
|
+
(requestedZoom: number) => {
|
|
130
|
+
const container = containerRef.current;
|
|
131
|
+
if (!container) return;
|
|
132
|
+
const zoom = Math.min(4, Math.max(0.1, requestedZoom));
|
|
133
|
+
const cx = container.clientWidth / 2;
|
|
134
|
+
const cy = container.clientHeight / 2;
|
|
135
|
+
const worldX = (cx - view.x) / view.zoom;
|
|
136
|
+
const worldY = (cy - view.y) / view.zoom;
|
|
137
|
+
setRootView(cx - worldX * zoom, cy - worldY * zoom, zoom);
|
|
138
|
+
},
|
|
139
|
+
[containerRef, view],
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const zoomToSelection = useCallback(() => {
|
|
143
|
+
const container = containerRef.current;
|
|
144
|
+
const selectedId = [...store.selectedEntityIds].at(-1);
|
|
145
|
+
if (!container || !selectedId) return;
|
|
146
|
+
const rect = context?.adapter.rects?.rect(selectedId);
|
|
147
|
+
if (!rect || rect.width <= 0 || rect.height <= 0) return;
|
|
148
|
+
const availableWidth = Math.max(1, container.clientWidth - 96);
|
|
149
|
+
const availableHeight = Math.max(1, container.clientHeight - 96);
|
|
150
|
+
const zoom = Math.min(
|
|
151
|
+
4,
|
|
152
|
+
Math.max(0.1, Math.min(availableWidth / rect.width, availableHeight / rect.height)),
|
|
153
|
+
);
|
|
154
|
+
setRootView(
|
|
155
|
+
container.clientWidth / 2 - (rect.x + rect.width / 2) * zoom,
|
|
156
|
+
container.clientHeight / 2 - (rect.y + rect.height / 2) * zoom,
|
|
157
|
+
zoom,
|
|
158
|
+
);
|
|
159
|
+
}, [containerRef, context, store]);
|
|
160
|
+
|
|
161
|
+
const selectViewport = useCallback(
|
|
162
|
+
(preset: string) => {
|
|
163
|
+
const container = containerRef.current;
|
|
164
|
+
if (boardViewport) {
|
|
165
|
+
setActiveReactStoryBoardViewport(container, preset === 'fill' ? null : preset);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const size = VIEWPORT_PRESETS[preset as keyof typeof VIEWPORT_PRESETS];
|
|
169
|
+
if (!container || size === null) {
|
|
170
|
+
setRootCanvasViewport(null, null);
|
|
171
|
+
setRootView(0, 0, 1);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
setRootCanvasViewport(size.width, size.height);
|
|
175
|
+
const zoom = Math.min(
|
|
176
|
+
1,
|
|
177
|
+
Math.max(
|
|
178
|
+
0.1,
|
|
179
|
+
Math.min(
|
|
180
|
+
(container.clientWidth - 96) / size.width,
|
|
181
|
+
(container.clientHeight - 96) / size.height,
|
|
182
|
+
),
|
|
183
|
+
),
|
|
184
|
+
);
|
|
185
|
+
setRootView(
|
|
186
|
+
(container.clientWidth - size.width * zoom) / 2,
|
|
187
|
+
(container.clientHeight - size.height * zoom) / 2,
|
|
188
|
+
zoom,
|
|
189
|
+
);
|
|
190
|
+
},
|
|
191
|
+
[boardViewport, containerRef],
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
const fitBoard = useCallback(() => {
|
|
195
|
+
const container = containerRef.current;
|
|
196
|
+
if (container) fitReactStoryBoard(container);
|
|
197
|
+
}, [containerRef]);
|
|
198
|
+
|
|
199
|
+
const hasStoryBoard = boardViewport !== null;
|
|
200
|
+
const hasDomAuthoring = context?.kind === 'dom' && Boolean(context.adapter.rects);
|
|
201
|
+
if (boardOnly ? !hasStoryBoard : !hasDomAuthoring) return null;
|
|
202
|
+
|
|
203
|
+
const viewportValue = boardViewport
|
|
204
|
+
? (boardViewport.selectedViewportId ?? 'fill')
|
|
205
|
+
: (Object.entries(VIEWPORT_PRESETS).find(([, size]) =>
|
|
206
|
+
size === null
|
|
207
|
+
? viewport.width === null
|
|
208
|
+
: size.width === viewport.width && size.height === viewport.height,
|
|
209
|
+
)?.[0] ?? 'fill');
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
<>
|
|
213
|
+
{!hasStoryBoard && viewport.width !== null && viewport.height !== null && (
|
|
214
|
+
<div
|
|
215
|
+
data-testid="react-canvas-device-frame"
|
|
216
|
+
style={{
|
|
217
|
+
position: 'absolute',
|
|
218
|
+
left: 0,
|
|
219
|
+
top: 0,
|
|
220
|
+
zIndex: 0,
|
|
221
|
+
width: viewport.width,
|
|
222
|
+
height: viewport.height,
|
|
223
|
+
transform: panTransformValue(view),
|
|
224
|
+
transformOrigin: '0 0',
|
|
225
|
+
pointerEvents: 'none',
|
|
226
|
+
background: '#fff',
|
|
227
|
+
boxShadow: '0 0 0 1px #ffffff40, 0 8px 30px #0009',
|
|
228
|
+
}}
|
|
229
|
+
/>
|
|
230
|
+
)}
|
|
231
|
+
<FloatingToolbar
|
|
232
|
+
label={boardOnly ? '2D component board view' : 'React canvas view'}
|
|
233
|
+
data-testid={boardOnly ? 'canvas-board-zoom-controls' : 'react-canvas-zoom-controls'}
|
|
234
|
+
{...(boardOnly ? { 'data-board-zoom': '' } : {})}
|
|
235
|
+
data-volter-canvas-navigation-ignore="true"
|
|
236
|
+
className="volter-react-canvas-controls"
|
|
237
|
+
>
|
|
238
|
+
{!boardOnly && (
|
|
239
|
+
<ResponsiveViewportControls
|
|
240
|
+
boardViewport={boardViewport}
|
|
241
|
+
containerRef={containerRef}
|
|
242
|
+
selectViewport={selectViewport}
|
|
243
|
+
viewportValue={viewportValue}
|
|
244
|
+
/>
|
|
245
|
+
)}
|
|
246
|
+
{hasStoryBoard && (
|
|
247
|
+
<Button
|
|
248
|
+
variant="ghost"
|
|
249
|
+
aria-label="Fit story board"
|
|
250
|
+
title="Fit all stories"
|
|
251
|
+
size="comfortable"
|
|
252
|
+
onClick={fitBoard}
|
|
253
|
+
>
|
|
254
|
+
Fit board
|
|
255
|
+
</Button>
|
|
256
|
+
)}
|
|
257
|
+
<IconButton
|
|
258
|
+
aria-label="Zoom out"
|
|
259
|
+
title="Zoom out"
|
|
260
|
+
size="comfortable"
|
|
261
|
+
onClick={() => zoomAroundCenter(view.zoom / 1.2)}
|
|
262
|
+
>
|
|
263
|
+
<EditorIcon icon={faMagnifyingGlassMinus} size="md" />
|
|
264
|
+
</IconButton>
|
|
265
|
+
<ZoomMenu
|
|
266
|
+
zoom={view.zoom}
|
|
267
|
+
zoomTo={zoomAroundCenter}
|
|
268
|
+
{...(hasStoryBoard ? { fit: fitBoard } : {})}
|
|
269
|
+
{...(!boardOnly && store.selectedEntityIds.size > 0 ? { toSelection: zoomToSelection } : {})}
|
|
270
|
+
/>
|
|
271
|
+
<IconButton
|
|
272
|
+
aria-label="Zoom in"
|
|
273
|
+
title="Zoom in"
|
|
274
|
+
size="comfortable"
|
|
275
|
+
onClick={() => zoomAroundCenter(view.zoom * 1.2)}
|
|
276
|
+
>
|
|
277
|
+
<EditorIcon icon={faMagnifyingGlassPlus} size="md" />
|
|
278
|
+
</IconButton>
|
|
279
|
+
{!boardOnly && (
|
|
280
|
+
<IconButton
|
|
281
|
+
aria-label="Zoom to selection"
|
|
282
|
+
title="Zoom to selection"
|
|
283
|
+
size="comfortable"
|
|
284
|
+
onClick={zoomToSelection}
|
|
285
|
+
>
|
|
286
|
+
<EditorIcon icon={faExpand} size="md" />
|
|
287
|
+
</IconButton>
|
|
288
|
+
)}
|
|
289
|
+
</FloatingToolbar>
|
|
290
|
+
</>
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Figma's zoom menu, opened from the zoom percentage: the zoom typed as a percentage, Zoom in and
|
|
296
|
+
* out, Zoom to fit, 50%, 100% and 200%, and Zoom to selection when there is one.
|
|
297
|
+
*/
|
|
298
|
+
function ZoomMenu({
|
|
299
|
+
zoom,
|
|
300
|
+
zoomTo,
|
|
301
|
+
fit,
|
|
302
|
+
toSelection,
|
|
303
|
+
}: {
|
|
304
|
+
zoom: number;
|
|
305
|
+
zoomTo: (zoom: number) => void;
|
|
306
|
+
fit?: () => void;
|
|
307
|
+
toSelection?: () => void;
|
|
308
|
+
}) {
|
|
309
|
+
const [open, setOpen] = useState(false);
|
|
310
|
+
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
311
|
+
const act = (run: () => void) => () => {
|
|
312
|
+
run();
|
|
313
|
+
setOpen(false);
|
|
314
|
+
};
|
|
315
|
+
return (
|
|
316
|
+
<>
|
|
317
|
+
<Button
|
|
318
|
+
ref={triggerRef}
|
|
319
|
+
variant="ghost"
|
|
320
|
+
aria-label="Zoom"
|
|
321
|
+
aria-haspopup="menu"
|
|
322
|
+
aria-expanded={open}
|
|
323
|
+
title="Zoom"
|
|
324
|
+
size="comfortable"
|
|
325
|
+
onClick={() => setOpen(!open)}
|
|
326
|
+
>
|
|
327
|
+
{Math.round(zoom * 100)}%
|
|
328
|
+
</Button>
|
|
329
|
+
{open && (
|
|
330
|
+
<AnchoredMenu anchorRef={triggerRef} align="end" clamp aria-label="Zoom" onDismiss={() => setOpen(false)}>
|
|
331
|
+
<div style={{ padding: '4px 8px' }}>
|
|
332
|
+
<TextInput
|
|
333
|
+
aria-label="Zoom percentage"
|
|
334
|
+
defaultValue={String(Math.round(zoom * 100))}
|
|
335
|
+
onKeyDown={(event) => {
|
|
336
|
+
if (event.key !== 'Enter') return;
|
|
337
|
+
const percent = Number.parseFloat(event.currentTarget.value);
|
|
338
|
+
if (Number.isFinite(percent) && percent > 0) {
|
|
339
|
+
zoomTo(percent / 100);
|
|
340
|
+
setOpen(false);
|
|
341
|
+
}
|
|
342
|
+
}}
|
|
343
|
+
/>
|
|
344
|
+
</div>
|
|
345
|
+
<MenuSeparator />
|
|
346
|
+
<MenuItem onSelect={act(() => zoomTo(zoom * 1.2))}>Zoom in</MenuItem>
|
|
347
|
+
<MenuItem onSelect={act(() => zoomTo(zoom / 1.2))}>Zoom out</MenuItem>
|
|
348
|
+
{fit ? <MenuItem onSelect={act(fit)}>Zoom to fit</MenuItem> : null}
|
|
349
|
+
{toSelection ? <MenuItem onSelect={act(toSelection)}>Zoom to selection</MenuItem> : null}
|
|
350
|
+
<MenuSeparator />
|
|
351
|
+
{[0.5, 1, 2].map((preset) => (
|
|
352
|
+
<MenuItem key={preset} onSelect={act(() => zoomTo(preset))}>{`Zoom to ${preset * 100}%`}</MenuItem>
|
|
353
|
+
))}
|
|
354
|
+
</AnchoredMenu>
|
|
355
|
+
)}
|
|
356
|
+
</>
|
|
357
|
+
);
|
|
358
|
+
}
|