@volter/editor-core 0.5.57
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/BUNDLED_NOTICES +1527 -0
- package/LICENSE +686 -0
- package/LICENSE-APACHE +202 -0
- package/NOTICE +18 -0
- package/README.md +24 -0
- package/dist/build/chunk-JS4D4XZ3.js +175 -0
- package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
- package/dist/build/vite-plugin-product-contributions.js +100 -0
- package/dist/build/vite-plugin-product-contributions.js.map +7 -0
- package/dist/build/vite-plugin-shared-react.js +25 -0
- package/dist/build/vite-plugin-shared-react.js.map +7 -0
- package/dist/build/vite-plugin-shared-three.js +86 -0
- package/dist/build/vite-plugin-shared-three.js.map +7 -0
- package/dist/server/chunk-KMJC7AGO.js +98 -0
- package/dist/server/chunk-KMJC7AGO.js.map +7 -0
- package/dist/server/chunk-PSILUMGS.js +46 -0
- package/dist/server/chunk-PSILUMGS.js.map +7 -0
- package/dist/server/frame-proxy.js +255 -0
- package/dist/server/frame-proxy.js.map +7 -0
- package/dist/server/open-browser.js +53 -0
- package/dist/server/open-browser.js.map +7 -0
- package/dist/server/process-shutdown.js +127 -0
- package/dist/server/process-shutdown.js.map +7 -0
- package/dist/server/session-registry.js +141 -0
- package/dist/server/session-registry.js.map +7 -0
- package/dist/server/spawn-opener.js +11 -0
- package/dist/server/spawn-opener.js.map +7 -0
- package/dist/server/worktree-identity.js +11 -0
- package/dist/server/worktree-identity.js.map +7 -0
- package/dist-server/packaged.mjs +88816 -0
- package/package.json +118 -0
- package/scripts/build-plugins.mjs +14 -0
- package/scripts/build-server.mjs +26 -0
- package/scripts/build-session.mjs +9 -0
- package/server/account-credentials.ts +60 -0
- package/server/account-service.ts +1434 -0
- package/server/adapter-region-includes.ts +47 -0
- package/server/asset-catalog-v2.ts +175 -0
- package/server/asset-history-snapshots.ts +196 -0
- package/server/asset-ledger-store.ts +195 -0
- package/server/asset-library-routes.ts +1595 -0
- package/server/blender-wasm-artifact.ts +430 -0
- package/server/boot-timings.ts +106 -0
- package/server/canonical-path.ts +50 -0
- package/server/checkout-workspace-preflight.ts +349 -0
- package/server/cloud-asset-catalog.ts +158 -0
- package/server/coding-inference-launch.ts +237 -0
- package/server/collaboration-account-client.ts +202 -0
- package/server/collaboration-attribution.ts +122 -0
- package/server/collaboration-session.ts +934 -0
- package/server/comfyui-bridge.ts +248 -0
- package/server/console-ledger.ts +499 -0
- package/server/creation-site-transform.ts +304 -0
- package/server/creation-site-write.ts +648 -0
- package/server/data-file-serialize.ts +158 -0
- package/server/editor-brand-html.ts +72 -0
- package/server/editor-control-socket.ts +366 -0
- package/server/editor-server-options.ts +190 -0
- package/server/editor-server.ts +1483 -0
- package/server/editor-sse.ts +352 -0
- package/server/engine-provenance.ts +169 -0
- package/server/engine-source-restart.ts +117 -0
- package/server/frame-bridge.ts +115 -0
- package/server/frame-proxy.ts +490 -0
- package/server/frame-workbench.ts +259 -0
- package/server/frontend-handoff.ts +229 -0
- package/server/game-globals-shadow.ts +113 -0
- package/server/gameplay-session-retention.ts +149 -0
- package/server/gameplay-sessions.ts +123 -0
- package/server/generation-jobs.ts +201 -0
- package/server/generation-reconciler.ts +137 -0
- package/server/generative-execution-context.ts +59 -0
- package/server/git-workflow.ts +612 -0
- package/server/harness-chat-caller.ts +36 -0
- package/server/harness-chat-service.ts +1681 -0
- package/server/idle-shutdown.ts +170 -0
- package/server/js-profiling-policy.ts +52 -0
- package/server/launcher-settings.ts +84 -0
- package/server/local-asset-catalog.ts +410 -0
- package/server/managed-account-defaults.ts +22 -0
- package/server/mock-control-plane.ts +540 -0
- package/server/model-import-conversion.ts +345 -0
- package/server/native-credential-store.ts +162 -0
- package/server/open-browser.ts +118 -0
- package/server/packaged.ts +1192 -0
- package/server/play-stall.ts +126 -0
- package/server/process-shutdown.ts +218 -0
- package/server/product-presets.ts +55 -0
- package/server/project-build-artifact.ts +95 -0
- package/server/project-components.ts +100 -0
- package/server/project-dependency-invalidation.ts +114 -0
- package/server/project-file-scan.ts +235 -0
- package/server/project-hmr-files.ts +215 -0
- package/server/project-install-roots.ts +210 -0
- package/server/project-kinds.ts +71 -0
- package/server/project-mcp-servers.ts +82 -0
- package/server/project-module-freshness.ts +109 -0
- package/server/project-module-instance.ts +375 -0
- package/server/project-optimize-deps-entries.ts +827 -0
- package/server/project-output-writer.ts +679 -0
- package/server/project-package-origin.ts +63 -0
- package/server/project-root-surface.ts +831 -0
- package/server/project-scratch-path.ts +47 -0
- package/server/project-script-hmr.ts +619 -0
- package/server/project-serving-plugins.ts +236 -0
- package/server/project-tools.ts +653 -0
- package/server/project-validation.ts +250 -0
- package/server/project-verbs.ts +127 -0
- package/server/project-view.ts +52 -0
- package/server/project-watch.ts +1134 -0
- package/server/project-work-coordinator.ts +288 -0
- package/server/provider-credentials.ts +331 -0
- package/server/recent-projects-store.ts +98 -0
- package/server/redact-secrets.ts +71 -0
- package/server/repository-presence.ts +267 -0
- package/server/routes/account.ts +357 -0
- package/server/routes/agents.ts +60 -0
- package/server/routes/assets.ts +154 -0
- package/server/routes/build.ts +13 -0
- package/server/routes/collaboration.ts +595 -0
- package/server/routes/configurations.ts +419 -0
- package/server/routes/context.ts +264 -0
- package/server/routes/control-plane.ts +1811 -0
- package/server/routes/logs.ts +272 -0
- package/server/routes/project-identity.ts +302 -0
- package/server/routes/project-open.ts +429 -0
- package/server/routes/project-source.ts +686 -0
- package/server/routes/project-state.ts +383 -0
- package/server/routes/relay.ts +1029 -0
- package/server/routes/route-helpers.ts +29 -0
- package/server/routes/served-modules.ts +138 -0
- package/server/routes/session-tabs.ts +196 -0
- package/server/routes/settings.ts +121 -0
- package/server/routes/share-control.ts +486 -0
- package/server/routes/themes.ts +116 -0
- package/server/routes/tools.ts +230 -0
- package/server/routes/worktrees.ts +595 -0
- package/server/scoped-game-css.ts +461 -0
- package/server/server-utils.ts +1194 -0
- package/server/session-product.ts +112 -0
- package/server/session-registry.ts +230 -0
- package/server/share-claims.ts +138 -0
- package/server/share-host.ts +526 -0
- package/server/share-session-gateway.ts +1362 -0
- package/server/share-tunnel.ts +123 -0
- package/server/spawn-opener.ts +74 -0
- package/server/support/play/log-format.ts +76 -0
- package/server/support/play/session-record.ts +199 -0
- package/server/support/project/build-discipline.ts +718 -0
- package/server/support/project/inspection-node.ts +119 -0
- package/server/support/project/log-naming.ts +54 -0
- package/server/support/project/provenance.ts +290 -0
- package/server/support/project/run-name.ts +18 -0
- package/server/support/project/session-journal.ts +830 -0
- package/server/support/project/shared.ts +327 -0
- package/server/tab-bootstrap.ts +62 -0
- package/server/tab-heartbeat.ts +477 -0
- package/server/tab-lifecycle.ts +550 -0
- package/server/tab-presence.ts +1508 -0
- package/server/team-agent-mirror.ts +95 -0
- package/server/twin-auth.ts +138 -0
- package/server/vendored-lock-recorder.ts +968 -0
- package/server/worktree-identity.ts +121 -0
- package/server/worktree-management.ts +398 -0
- package/server/worktree-retention.d.mts +13 -0
- package/server/worktree-retention.mjs +205 -0
- package/src/EditorContext.tsx +169 -0
- package/src/account.ts +333 -0
- package/src/action-registry.ts +532 -0
- package/src/active-product.ts +74 -0
- package/src/active-project.ts +155 -0
- package/src/adapter-editor-config.ts +25 -0
- package/src/adapter-observation.ts +49 -0
- package/src/animation/stage-transport.ts +379 -0
- package/src/animation/three-clips-subject.ts +172 -0
- package/src/api/asset-library-wire.ts +45 -0
- package/src/api/assets.ts +365 -0
- package/src/api/base.ts +10 -0
- package/src/api/build.ts +99 -0
- package/src/api/git-wire.ts +56 -0
- package/src/api/logs.ts +92 -0
- package/src/api/project-identity.ts +74 -0
- package/src/api/project-open.ts +355 -0
- package/src/api/project-source.ts +162 -0
- package/src/api/project-state.ts +107 -0
- package/src/api/relay.ts +268 -0
- package/src/api/settings.ts +36 -0
- package/src/api/themes.ts +45 -0
- package/src/api/worktrees.ts +257 -0
- package/src/asset-compare-core.ts +171 -0
- package/src/asset-compare.ts +294 -0
- package/src/asset-editor-context.tsx +100 -0
- package/src/asset-events.ts +97 -0
- package/src/asset-inspector-actions.ts +87 -0
- package/src/asset-preview-framing.ts +357 -0
- package/src/asset-preview.ts +2802 -0
- package/src/asset-selection-viewer-registry.ts +113 -0
- package/src/asset-selection.ts +133 -0
- package/src/asset-workflow/asset-capabilities.ts +344 -0
- package/src/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/asset-workflow/asset-ledger.ts +156 -0
- package/src/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/asset-workflow/asset-types.ts +142 -0
- package/src/asset-workflow/asset-workflow-quality.ts +61 -0
- package/src/asset-workflow/audio-preview-player.ts +193 -0
- package/src/asset-workflow/audio-waveform.ts +22 -0
- package/src/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/asset-workflow/folder-preview.ts +345 -0
- package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/asset-workflow/image-view-scale.ts +32 -0
- package/src/asset-workflow/import-contract.ts +124 -0
- package/src/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/asset-workflow/model-inspection.ts +818 -0
- package/src/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +139 -0
- package/src/asset-workflow/project-asset-operations.ts +154 -0
- package/src/asset-workflow/project-asset-roots.ts +68 -0
- package/src/asset-workflow/project-content.ts +288 -0
- package/src/asset-workflow/project-source-index.ts +550 -0
- package/src/asset-workflow/thumbnail-system.ts +256 -0
- package/src/authoring/active-adapter.ts +199 -0
- package/src/authoring/active-systems.ts +422 -0
- package/src/authoring/adapter-key.ts +18 -0
- package/src/authoring/authoring-asset-url.ts +27 -0
- package/src/authoring/bootstrap-state.ts +49 -0
- package/src/authoring/boundary-authoring-adapter.ts +184 -0
- package/src/authoring/breakpoint-state.ts +43 -0
- package/src/authoring/canvas-scene-guides.ts +76 -0
- package/src/authoring/component-instance-root.ts +171 -0
- package/src/authoring/composite-authoring-adapter.ts +2110 -0
- package/src/authoring/consumer-actions.ts +520 -0
- package/src/authoring/css-numeric-style.ts +97 -0
- package/src/authoring/design-time-layers.ts +849 -0
- package/src/authoring/design-time-mount-registry.ts +235 -0
- package/src/authoring/design-time-settle.ts +343 -0
- package/src/authoring/edit-mode-authoring.ts +619 -0
- package/src/authoring/eyedropper-session.ts +60 -0
- package/src/authoring/instance-source-menu-register.ts +13 -0
- package/src/authoring/instance-source-menu.ts +135 -0
- package/src/authoring/layered-pick.ts +183 -0
- package/src/authoring/live-gesture-lock.ts +50 -0
- package/src/authoring/live-object-transform.ts +62 -0
- package/src/authoring/mount-failure-report.ts +154 -0
- package/src/authoring/mounted-root-subjects.ts +144 -0
- package/src/authoring/no-authoring-adapter.ts +55 -0
- package/src/authoring/null-inspection-subjects.tsx +75 -0
- package/src/authoring/object3d-document-persistence.ts +106 -0
- package/src/authoring/object3d-document-session-registry.ts +120 -0
- package/src/authoring/object3d-document-session.ts +1326 -0
- package/src/authoring/object3d-gesture-controller.ts +113 -0
- package/src/authoring/panel-authoring.ts +121 -0
- package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
- package/src/authoring/prefab-instance-section-model.ts +55 -0
- package/src/authoring/project-authoring-session.ts +105 -0
- package/src/authoring/provenance.ts +99 -0
- package/src/authoring/quarks-particle-systems.ts +19 -0
- package/src/authoring/react-canvas-navigation.ts +255 -0
- package/src/authoring/react-design-canvas-style.ts +20 -0
- package/src/authoring/react-story-board.ts +937 -0
- package/src/authoring/selection-scope.ts +195 -0
- package/src/authoring/shell-document-ops.ts +169 -0
- package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
- package/src/authoring/shell-viewport-policy.ts +48 -0
- package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
- package/src/authoring/stories-scope.ts +35 -0
- package/src/authoring/story-board-chrome-fit.ts +107 -0
- package/src/authoring/story-board-presentation.ts +111 -0
- package/src/authoring/three-projection-core.ts +226 -0
- package/src/authoring/viewport-pick-context.ts +40 -0
- package/src/authoring/viewport-raycast.ts +240 -0
- package/src/authoring/viewport-tool-context.ts +73 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +152 -0
- package/src/authoring/world-pan-state.ts +198 -0
- package/src/authoring/world-session-state.ts +101 -0
- package/src/authoring/write-pipe.ts +173 -0
- package/src/availability-tick.ts +66 -0
- package/src/bitmap-label.ts +120 -0
- package/src/blender-tab-metrics.ts +161 -0
- package/src/board-open-actions.ts +20 -0
- package/src/boot-routing.ts +391 -0
- package/src/build-identity.ts +15 -0
- package/src/bytes-codec.ts +62 -0
- package/src/camera-authoring.ts +175 -0
- package/src/cancellation-reason.ts +58 -0
- package/src/canvas-preview-frames.ts +482 -0
- package/src/capture-camera-pose.ts +77 -0
- package/src/chrome-registry.ts +159 -0
- package/src/chrome-slot-registry.ts +91 -0
- package/src/collaboration-client.ts +264 -0
- package/src/collaboration-presence.ts +41 -0
- package/src/command-dispatch.ts +19 -0
- package/src/command-listener.ts +2743 -0
- package/src/command-registry.ts +70 -0
- package/src/component-board-registry.ts +205 -0
- package/src/component-states-registry.ts +200 -0
- package/src/components/AgentPresentationNotice.tsx +75 -0
- package/src/components/AlignToolbar.tsx +204 -0
- package/src/components/AppRoot.tsx +394 -0
- package/src/components/ApplicationMenus.tsx +415 -0
- package/src/components/AssetBrowser.tsx +2843 -0
- package/src/components/AssetEditorShell.tsx +216 -0
- package/src/components/AssetInspectorToolSection.tsx +124 -0
- package/src/components/BoardRulers.tsx +354 -0
- package/src/components/CameraInfo.tsx +81 -0
- package/src/components/CanvasSceneViewport.tsx +556 -0
- package/src/components/CapabilityCoverageSection.tsx +185 -0
- package/src/components/CenterDocuments.tsx +22 -0
- package/src/components/ChromeSlot.tsx +20 -0
- package/src/components/CodeView.tsx +470 -0
- package/src/components/CollaborationHeaderControl.css +74 -0
- package/src/components/CompactInspectorCard.tsx +190 -0
- package/src/components/CompactInspectorShell.tsx +39 -0
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +270 -0
- package/src/components/DefaultEditorLayout.tsx +106 -0
- package/src/components/DocumentHeaderStrip.tsx +96 -0
- package/src/components/DocumentShelfRail.tsx +45 -0
- package/src/components/DocumentThumbnail.tsx +345 -0
- package/src/components/EditorLeaseGuard.tsx +372 -0
- package/src/components/ErrorBanner.tsx +123 -0
- package/src/components/FolderPreviewTile.tsx +159 -0
- package/src/components/GameHierarchy.tsx +3842 -0
- package/src/components/GameplaySessionTimeline.tsx +295 -0
- package/src/components/InspectionProjection.tsx +968 -0
- package/src/components/Inspector.tsx +233 -0
- package/src/components/InspectorCanvasPreview.tsx +35 -0
- package/src/components/InspectorFieldsSection.tsx +290 -0
- package/src/components/InspectorObjectPreview.tsx +57 -0
- package/src/components/InspectorStoriesSection.tsx +92 -0
- package/src/components/InspectorToolSection.tsx +96 -0
- package/src/components/InspectorTransformSection.tsx +245 -0
- package/src/components/LightExplorerPanel.tsx +433 -0
- package/src/components/MediaProperties.tsx +145 -0
- package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
- package/src/components/Object3DDocumentToolbar.css +100 -0
- package/src/components/Object3DDocumentToolbar.tsx +454 -0
- package/src/components/Object3DDocumentViewport.tsx +58 -0
- package/src/components/ProjectHeader.css +617 -0
- package/src/components/ProjectHeader.tsx +328 -0
- package/src/components/ProjectLayout.tsx +249 -0
- package/src/components/ReactCanvasControls.tsx +284 -0
- package/src/components/RootSelectionOverlay.tsx +3162 -0
- package/src/components/RootTextEditor.tsx +79 -0
- package/src/components/SaveStatus.tsx +70 -0
- package/src/components/StageHost.tsx +1954 -0
- package/src/components/StageOverlays.tsx +21 -0
- package/src/components/StartupErrorScreen.tsx +76 -0
- package/src/components/StartupLoadingScreen.tsx +65 -0
- package/src/components/StatsOverlay.tsx +78 -0
- package/src/components/SurfaceStateOverlay.tsx +24 -0
- package/src/components/ToolContributionSurfaces.tsx +65 -0
- package/src/components/ToolHost.tsx +370 -0
- package/src/components/ToolObject3DPreview.tsx +39 -0
- package/src/components/Toolbar.tsx +595 -0
- package/src/components/TransientHint.tsx +44 -0
- package/src/components/TransportStrip.tsx +174 -0
- package/src/components/VersionControlSection.tsx +470 -0
- package/src/components/VgaiLogo.css +83 -0
- package/src/components/VgaiLogo.tsx +35 -0
- package/src/components/ViewportControlsHint.tsx +60 -0
- package/src/components/ViewportFurniture.tsx +401 -0
- package/src/components/ViewportOverlay.tsx +145 -0
- package/src/components/ViewportOverlaysMenu.tsx +153 -0
- package/src/components/ViewportShadingMenu.tsx +300 -0
- package/src/components/ViewportViewMenu.tsx +101 -0
- package/src/components/WorkspaceDocumentSurface.tsx +204 -0
- package/src/components/WorkspaceUtilitySurface.tsx +22 -0
- package/src/components/WorktreeSwitcher.css +239 -0
- package/src/components/WorktreeSwitcher.tsx +890 -0
- package/src/components/account-documents.tsx +1162 -0
- package/src/components/asset-documents.tsx +812 -0
- package/src/components/asset-editor-persistence.ts +216 -0
- package/src/components/asset-selection-section.tsx +535 -0
- package/src/components/asset-thumbnails.tsx +312 -0
- package/src/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
- package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
- package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
- package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
- package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
- package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
- package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
- package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
- package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
- package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
- package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/components/asset-viewers/shader-source.ts +144 -0
- package/src/components/asset-workflow.css +731 -0
- package/src/components/board-guides.ts +150 -0
- package/src/components/compact-inspector.css +539 -0
- package/src/components/core-utilities.tsx +90 -0
- package/src/components/editor-notifications.css +40 -0
- package/src/components/engine-workspace.css +274 -0
- package/src/components/inspector-preview-section.tsx +238 -0
- package/src/components/inspector-property-grouping.ts +64 -0
- package/src/components/inspector-revert-label.ts +20 -0
- package/src/components/inspector-selection.ts +42 -0
- package/src/components/inspector-stories-gating.ts +171 -0
- package/src/components/inspector-transform-subject.ts +11 -0
- package/src/components/inspector-transform.ts +75 -0
- package/src/components/kind-documents.tsx +500 -0
- package/src/components/palette-action-publisher.tsx +140 -0
- package/src/components/primitives/DraftColorInput.tsx +74 -0
- package/src/components/product-shell.css +1829 -0
- package/src/components/project-tool-documents.tsx +410 -0
- package/src/components/scene-documents.tsx +223 -0
- package/src/components/stage-keyboard.tsx +37 -0
- package/src/components/stage-overlay-set.tsx +107 -0
- package/src/components/stage-presence-markers.ts +478 -0
- package/src/components/standard-viewport-dressing.ts +417 -0
- package/src/components/status-contributions.tsx +403 -0
- package/src/components/tool-documents.tsx +309 -0
- package/src/components/tool-schema-form.tsx +262 -0
- package/src/components/use-after-paint.ts +41 -0
- package/src/components/use-project-image-assets.ts +86 -0
- package/src/components/viewport-header-controls.css +90 -0
- package/src/components/viewport-surface-status.tsx +55 -0
- package/src/components/workspace-history.ts +32 -0
- package/src/components/workspace-static-panel-registry.tsx +152 -0
- package/src/components/workspace-surfaces.css +621 -0
- package/src/components/world-documents.tsx +586 -0
- package/src/components/world-overlay-gestures.ts +1694 -0
- package/src/composite-screenshot.ts +1641 -0
- package/src/console-sync.ts +131 -0
- package/src/constraint-helper.ts +338 -0
- package/src/content-entry-source-registry.ts +184 -0
- package/src/coverage/authoring-seam-evidence.ts +300 -0
- package/src/coverage/canvas-reveal.ts +192 -0
- package/src/coverage/design-time-surfaces.ts +101 -0
- package/src/coverage/live-seam-evidence.ts +11 -0
- package/src/coverage/ontology-invariants.ts +466 -0
- package/src/coverage/session-vitals.ts +501 -0
- package/src/coverage/system-seam-evidence.ts +72 -0
- package/src/crash-null-boundary.ts +36 -0
- package/src/creation-site-edit.ts +1479 -0
- package/src/creation-site-registry.ts +160 -0
- package/src/delegate-harness-registry.ts +143 -0
- package/src/document-context-registry.ts +177 -0
- package/src/document-open-registry.ts +200 -0
- package/src/document-preview-source.ts +20 -0
- package/src/document-renderer-session.ts +138 -0
- package/src/editor-api.ts +46 -0
- package/src/editor-chrome-capture.ts +139 -0
- package/src/editor-commands.ts +164 -0
- package/src/editor-console.ts +563 -0
- package/src/editor-current-view.ts +82 -0
- package/src/editor-document-probe.ts +881 -0
- package/src/editor-git-client.ts +115 -0
- package/src/editor-host-door.ts +462 -0
- package/src/editor-hotkeys.ts +842 -0
- package/src/editor-lease-view.ts +39 -0
- package/src/editor-lease.ts +415 -0
- package/src/editor-mode.ts +19 -0
- package/src/editor-notifications.ts +140 -0
- package/src/editor-presence.ts +563 -0
- package/src/editor-presentation-activity.ts +50 -0
- package/src/editor-presentation-notice.ts +42 -0
- package/src/editor-runtime.tsx +145 -0
- package/src/editor-server-response.ts +86 -0
- package/src/editor-session-attribution.ts +75 -0
- package/src/editor-session-mode.ts +54 -0
- package/src/editor-shell-store.ts +1304 -0
- package/src/editor-state-facets.ts +74 -0
- package/src/editor-styles.css +33 -0
- package/src/editor-view-presentation.ts +810 -0
- package/src/editor-viewport.ts +5302 -0
- package/src/entity-lod.ts +31 -0
- package/src/entity-object.ts +91 -0
- package/src/files/file-provider.ts +62 -0
- package/src/files/project-files.ts +264 -0
- package/src/finders/index.ts +136 -0
- package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/frame/bridge.tsx +1408 -0
- package/src/frame/product.ts +77 -0
- package/src/gameplay-dom-recording.ts +319 -0
- package/src/gameplay-export-state.ts +14 -0
- package/src/gameplay-replay.ts +417 -0
- package/src/gameplay-session-time.ts +9 -0
- package/src/gameplay-sessions.ts +204 -0
- package/src/harness-chat-types.ts +253 -0
- package/src/hierarchy-component-marks.ts +298 -0
- package/src/hierarchy-drop.ts +91 -0
- package/src/hierarchy-expansion-state.ts +80 -0
- package/src/hierarchy-header-slot.ts +52 -0
- package/src/hierarchy-internals.ts +197 -0
- package/src/hierarchy-kind-icon.ts +217 -0
- package/src/hierarchy-mark-reader.ts +73 -0
- package/src/hierarchy-menu-registry.ts +67 -0
- package/src/hierarchy-node-rows.ts +307 -0
- package/src/hierarchy-panel-view.ts +280 -0
- package/src/hierarchy-projection.ts +76 -0
- package/src/hierarchy-row-cache.ts +243 -0
- package/src/hierarchy-row-model.ts +308 -0
- package/src/hierarchy-rows.ts +11 -0
- package/src/hierarchy-walk.ts +86 -0
- package/src/history/editor-session.ts +25 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-delegate.ts +163 -0
- package/src/history/history-limit-notices.ts +43 -0
- package/src/history/history-service.ts +1173 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +386 -0
- package/src/history/project-root-history-backends.ts +139 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +103 -0
- package/src/history/source-history-backend.ts +546 -0
- package/src/history/types.ts +124 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hotkeys.ts +188 -0
- package/src/inference-diagnostics.ts +69 -0
- package/src/initial-project.ts +80 -0
- package/src/inspection/active-subject.ts +578 -0
- package/src/inspection/active-surface.ts +142 -0
- package/src/inspection/compose.ts +1064 -0
- package/src/inspection/display.ts +170 -0
- package/src/inspection/document-subject.ts +109 -0
- package/src/inspection/game-subject.ts +85 -0
- package/src/inspection/model.ts +542 -0
- package/src/inspection/null-subject.ts +115 -0
- package/src/inspection/serialize.ts +357 -0
- package/src/inspection/use-active-inspection.ts +180 -0
- package/src/inspector-presentation.ts +201 -0
- package/src/inspector-section-registry.ts +221 -0
- package/src/instance-source-actions.ts +163 -0
- package/src/instanced-presentation.ts +164 -0
- package/src/js-heap.ts +71 -0
- package/src/key-actions.ts +91 -0
- package/src/keymap-presets.ts +401 -0
- package/src/layout-policy.ts +31 -0
- package/src/learn-links.ts +73 -0
- package/src/light-explorer-model.ts +134 -0
- package/src/live-canvas-frame.ts +55 -0
- package/src/live-document.ts +279 -0
- package/src/live-module-source.ts +230 -0
- package/src/live-session-registry.ts +220 -0
- package/src/live-transition.ts +633 -0
- package/src/manifest-project.ts +107 -0
- package/src/model-thumbnail.ts +523 -0
- package/src/native-selection-style.ts +202 -0
- package/src/object3d-document-write-policy.ts +137 -0
- package/src/packaged-runtime.ts +108 -0
- package/src/palettes/maya.palette.json +57 -0
- package/src/palettes/substance.palette.json +57 -0
- package/src/pasteboard-module.ts +81 -0
- package/src/performance-profiler.ts +367 -0
- package/src/performance-sources.ts +69 -0
- package/src/play-boot-phase.ts +145 -0
- package/src/presentation-surface.ts +248 -0
- package/src/project-adapter.ts +1143 -0
- package/src/project-asset-refresh.ts +26 -0
- package/src/project-declaration-refresh.ts +31 -0
- package/src/project-local-state.ts +118 -0
- package/src/project-manager.ts +243 -0
- package/src/project-module-changes.ts +163 -0
- package/src/project-module-split.ts +266 -0
- package/src/project-provenance.ts +115 -0
- package/src/project-ready.ts +42 -0
- package/src/project-session-reset.ts +67 -0
- package/src/project-shape.ts +68 -0
- package/src/project-tool-discovery.ts +66 -0
- package/src/project-tools.ts +107 -0
- package/src/project-work-types.ts +149 -0
- package/src/projection/three.ts +898 -0
- package/src/projection/types.ts +44 -0
- package/src/readiness.ts +113 -0
- package/src/reflection-probe-helper.ts +142 -0
- package/src/reported-play-state.ts +90 -0
- package/src/resolve-relative-specifier.ts +33 -0
- package/src/scene-document-plan.ts +315 -0
- package/src/scene-framing.ts +315 -0
- package/src/scene-live-open.ts +210 -0
- package/src/scene-view-fog.ts +89 -0
- package/src/scoped-game-css.ts +152 -0
- package/src/session-orphan-record.ts +193 -0
- package/src/session-tombstone.ts +126 -0
- package/src/settings/settings-provider.ts +82 -0
- package/src/settings-store.ts +345 -0
- package/src/shared-view-restore.ts +42 -0
- package/src/shell-store-door.ts +45 -0
- package/src/source-conflict.ts +122 -0
- package/src/spatial-handle-visuals.ts +332 -0
- package/src/stage-context.ts +341 -0
- package/src/stage-store-registry.ts +63 -0
- package/src/stale-chunk-recovery.ts +34 -0
- package/src/state-report-deferral.ts +73 -0
- package/src/storage/host-files-storage.ts +97 -0
- package/src/storage/http-storage.ts +174 -0
- package/src/storage/index.ts +75 -0
- package/src/storage/mem-storage.ts +149 -0
- package/src/storage/path-lock.ts +44 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/types.ts +116 -0
- package/src/stories/StoryComponentThumbnail.tsx +184 -0
- package/src/stories/StoryPreviewMount.tsx +306 -0
- package/src/stories/component-content-source.tsx +106 -0
- package/src/stories/component-states-source.ts +78 -0
- package/src/stories/compose-project-stories.ts +255 -0
- package/src/stories/pixi-story-model.ts +30 -0
- package/src/stories/prefabs-finder.ts +54 -0
- package/src/stories/prefabs-from-stories.ts +182 -0
- package/src/stories/project-story-discovery.ts +78 -0
- package/src/stories/project-story-regions.ts +24 -0
- package/src/stories/story-actions.ts +54 -0
- package/src/stories/story-capture-command.ts +124 -0
- package/src/stories/story-capture.ts +584 -0
- package/src/stories/story-declared-medium.ts +126 -0
- package/src/stories/story-discovery.ts +176 -0
- package/src/stories/story-document-openers.ts +36 -0
- package/src/stories/story-dom-runtime.ts +78 -0
- package/src/stories/story-grouping.ts +111 -0
- package/src/stories/story-lane.ts +88 -0
- package/src/stories/story-mount-turn.ts +27 -0
- package/src/stories/story-opener.ts +260 -0
- package/src/stories/story-pixi-preview.ts +408 -0
- package/src/stories/story-presentation.ts +215 -0
- package/src/stories/story-registry.ts +517 -0
- package/src/stories/story-three-preview.ts +807 -0
- package/src/stories/three-story-model.ts +96 -0
- package/src/story-three-preview-runtime.ts +56 -0
- package/src/surface-keyboard.ts +112 -0
- package/src/surface-state.ts +124 -0
- package/src/tab-bootstrap.js +628 -0
- package/src/tab-census.ts +198 -0
- package/src/tab-lifecycle-client.ts +196 -0
- package/src/theme-library.ts +844 -0
- package/src/theme-preference.ts +378 -0
- package/src/theme.css +3437 -0
- package/src/three-viewport/bone-selection-highlight.ts +119 -0
- package/src/three-viewport/camera-fit.ts +41 -0
- package/src/three-viewport/interactive-renderer.ts +132 -0
- package/src/three-viewport/selection-brackets.ts +310 -0
- package/src/three-viewport/selection-outline.ts +183 -0
- package/src/three-viewport/skeleton-helper.ts +61 -0
- package/src/three-viewport/source-color.ts +167 -0
- package/src/three-viewport/studio-environment.ts +96 -0
- package/src/three-viewport-presentation.ts +23 -0
- package/src/tool-contribution-play.ts +74 -0
- package/src/tool-loader.ts +1798 -0
- package/src/transform-mode-request.ts +57 -0
- package/src/transient-hint.ts +78 -0
- package/src/trigger-volume-helper.ts +116 -0
- package/src/ui-source/adapter-region-includes.ts +241 -0
- package/src/ui-source/ensure-import.ts +132 -0
- package/src/ui-source/file-region-resolver.ts +302 -0
- package/src/ui-source/inspect.ts +775 -0
- package/src/ui-source/oid-transform.ts +1845 -0
- package/src/ui-source/plan-csf-story.ts +196 -0
- package/src/ui-source/plan-extract-component.ts +421 -0
- package/src/ui-source/plan-fork-component.ts +621 -0
- package/src/ui-source/plan-named-style.ts +95 -0
- package/src/ui-source/plan-source-edit.ts +353 -0
- package/src/ui-source/r3f-contract-resolver.ts +327 -0
- package/src/ui-source/r3f-diagnostic-index.ts +165 -0
- package/src/ui-source/r3f-environment-binding.ts +133 -0
- package/src/ui-source/r3f-joint-binding.ts +251 -0
- package/src/ui-source/r3f-lod-binding.ts +91 -0
- package/src/ui-source/r3f-particle-binding.ts +235 -0
- package/src/ui-source/r3f-physics-binding.ts +483 -0
- package/src/ui-source/r3f-project-contracts.ts +444 -0
- package/src/ui-source/relative-import-specifier.ts +34 -0
- package/src/ui-source/reparent-guard.ts +544 -0
- package/src/ui-source/source-edit-request.ts +97 -0
- package/src/ui-source/source-write-backend.ts +618 -0
- package/src/ui-source/syntactic-prop-specs.ts +296 -0
- package/src/ui-source/tier-source-write-backend.ts +279 -0
- package/src/ui-source/ts-ast.ts +171 -0
- package/src/ui-source/utility-class-support.ts +169 -0
- package/src/ui-source/write-component-default.ts +133 -0
- package/src/ui-source/writer.ts +1989 -0
- package/src/viewport-activation-timings.ts +840 -0
- package/src/viewport-authoring-policy.ts +186 -0
- package/src/viewport-controls-hint.ts +57 -0
- package/src/viewport-door.ts +237 -0
- package/src/viewport-shading-boundary.ts +12 -0
- package/src/vite-error-surface.ts +141 -0
- package/src/wait-until.ts +37 -0
- package/src/workspace-areas.ts +156 -0
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-available-documents.ts +127 -0
- package/src/workspace-core-utilities.ts +31 -0
- package/src/workspace-document-ids.ts +59 -0
- package/src/workspace-document-registry.ts +612 -0
- package/src/workspace-document-restore.ts +145 -0
- package/src/workspace-host-commands.ts +141 -0
- package/src/workspace-persistence-gate.ts +40 -0
- package/src/workspace-play-utilities.ts +44 -0
- package/src/workspace-presets.ts +425 -0
- package/src/workspace-regions.ts +294 -0
- package/src/workspace-state-persistence.ts +536 -0
- package/src/workspace-static-panels.ts +73 -0
- package/src/workspace-status-registry.ts +121 -0
- package/src/workspace-style.ts +239 -0
- package/src/workspace-utility-commands.ts +74 -0
- package/src/workspace-utility-registry.ts +263 -0
- package/src/workspace-viewport-rect.ts +97 -0
- package/src/world-adoption.ts +115 -0
- package/src/world-document-routing.ts +104 -0
- package/vite-plugin-creation-site-write.ts +184 -0
- package/vite-plugin-creation-site.ts +80 -0
- package/vite-plugin-game-static.ts +303 -0
- package/vite-plugin-module-doorways.ts +336 -0
- package/vite-plugin-product-contributions.ts +197 -0
- package/vite-plugin-project-game-static.ts +125 -0
- package/vite-plugin-project-jsx-js.ts +65 -0
- package/vite-plugin-project-root-absolute-assets.ts +359 -0
- package/vite-plugin-shared-react.ts +420 -0
- package/vite-plugin-shared-three.ts +203 -0
- package/vite-plugin-ui-oid.ts +2106 -0
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
import {
|
|
2
|
+
faArrowDown,
|
|
3
|
+
type faArrowsUpDownLeftRight,
|
|
4
|
+
faBullseye,
|
|
5
|
+
faCaretDown,
|
|
6
|
+
faCheck,
|
|
7
|
+
faCircleDot,
|
|
8
|
+
faCrosshairs,
|
|
9
|
+
faCube,
|
|
10
|
+
faGlobe,
|
|
11
|
+
faMagnet,
|
|
12
|
+
} from '@fortawesome/free-solid-svg-icons';
|
|
13
|
+
import type { StageTransformDoor, StageTransformKind } from '@volter/editor-sdk/contributions';
|
|
14
|
+
import {
|
|
15
|
+
AnchoredMenu,
|
|
16
|
+
Button,
|
|
17
|
+
Checkbox,
|
|
18
|
+
EditorIcon,
|
|
19
|
+
EditorPopover,
|
|
20
|
+
EditorToolbar,
|
|
21
|
+
editorIcons,
|
|
22
|
+
FloatingToolbar,
|
|
23
|
+
IconButton,
|
|
24
|
+
Inline,
|
|
25
|
+
Keycap,
|
|
26
|
+
MenuItem,
|
|
27
|
+
SplitButtonGroup,
|
|
28
|
+
Stack,
|
|
29
|
+
Text,
|
|
30
|
+
TextInput,
|
|
31
|
+
Tooltip,
|
|
32
|
+
} from '@volter/editor-sdk/widgets';
|
|
33
|
+
import { useEffect, useRef, useState, useSyncExternalStore } from 'react';
|
|
34
|
+
import { useEditorStore } from '../editor-runtime';
|
|
35
|
+
import type { EditorShellStore, GizmoAnchor, PivotMode } from '../editor-shell-store';
|
|
36
|
+
import {
|
|
37
|
+
activeEditorKeymap,
|
|
38
|
+
type EditorKeyActionId,
|
|
39
|
+
shortcutFor,
|
|
40
|
+
subscribeEditorKeymap,
|
|
41
|
+
} from '../keymap-presets';
|
|
42
|
+
import { requestTransformMode } from '../transform-mode-request';
|
|
43
|
+
|
|
44
|
+
/** WHETHER IT IS LIT AND WHAT IT ARMS ARE THE STAGE'S ANSWER, not this
|
|
45
|
+
* button's: the gizmo arm reads `store.transformMode`, a modal door reads its
|
|
46
|
+
* own `armed()` (see `stageTransformDriver` in `stage-context.ts`). */
|
|
47
|
+
function ModeButton({
|
|
48
|
+
active,
|
|
49
|
+
onArm,
|
|
50
|
+
faIcon,
|
|
51
|
+
action,
|
|
52
|
+
label,
|
|
53
|
+
}: {
|
|
54
|
+
active: boolean;
|
|
55
|
+
onArm: () => void;
|
|
56
|
+
faIcon: typeof faArrowsUpDownLeftRight;
|
|
57
|
+
/** The LOGICAL action — its printed key comes from the active keymap. */
|
|
58
|
+
action: EditorKeyActionId;
|
|
59
|
+
label: string;
|
|
60
|
+
}) {
|
|
61
|
+
return (
|
|
62
|
+
<Tooltip text={label} hotkey={shortcutFor(action)}>
|
|
63
|
+
<IconButton
|
|
64
|
+
aria-label={label}
|
|
65
|
+
aria-pressed={active}
|
|
66
|
+
shape="segment"
|
|
67
|
+
size="comfortable"
|
|
68
|
+
onClick={onArm}
|
|
69
|
+
>
|
|
70
|
+
<EditorIcon icon={faIcon} size="md" />
|
|
71
|
+
</IconButton>
|
|
72
|
+
</Tooltip>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function SnapButton({
|
|
77
|
+
store,
|
|
78
|
+
dimensions = '3d',
|
|
79
|
+
size = 'comfortable',
|
|
80
|
+
variant = 'ghost',
|
|
81
|
+
}: {
|
|
82
|
+
store: EditorShellStore;
|
|
83
|
+
dimensions?: '2d' | '3d';
|
|
84
|
+
size?: 'compact' | 'default' | 'comfortable';
|
|
85
|
+
variant?: 'ghost' | 'secondary';
|
|
86
|
+
}) {
|
|
87
|
+
const [popoverOpen, setPopoverOpen] = useState(false);
|
|
88
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
89
|
+
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (!popoverOpen) return;
|
|
92
|
+
const handler = (event: MouseEvent) => {
|
|
93
|
+
if (ref.current && !ref.current.contains(event.target as Node)) setPopoverOpen(false);
|
|
94
|
+
};
|
|
95
|
+
document.addEventListener('mousedown', handler);
|
|
96
|
+
return () => document.removeEventListener('mousedown', handler);
|
|
97
|
+
}, [popoverOpen]);
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<div ref={ref} className="vgai-viewport-popover-anchor">
|
|
101
|
+
<SplitButtonGroup>
|
|
102
|
+
<Tooltip text="Toggle Snap" hotkey={shortcutFor('viewport.toggleSnap')}>
|
|
103
|
+
<IconButton
|
|
104
|
+
aria-label="Toggle snap"
|
|
105
|
+
aria-pressed={store.snapEnabled}
|
|
106
|
+
variant={variant}
|
|
107
|
+
size={size}
|
|
108
|
+
onClick={() => store.toggleSnap()}
|
|
109
|
+
>
|
|
110
|
+
<EditorIcon icon={faMagnet} size="md" />
|
|
111
|
+
</IconButton>
|
|
112
|
+
</Tooltip>
|
|
113
|
+
<Tooltip text="Snap Settings">
|
|
114
|
+
<IconButton
|
|
115
|
+
aria-label="Snap settings"
|
|
116
|
+
// A trigger that opens an anchored SETTINGS popover is a menu
|
|
117
|
+
// button, and `theme.css` reads that off the ARIA rather than a
|
|
118
|
+
// marker attribute — the same honest `dialog` the `Studio v`
|
|
119
|
+
// trigger declares. Blender's snap group is exactly this two-tone
|
|
120
|
+
// split: the magnet half in the pushbutton colour, this half in
|
|
121
|
+
// the menu well (measured native 2x `modeling.png` y=62, the
|
|
122
|
+
// toggle x 1411..1445 at #535353 and the dropdown x 1448..1507 at
|
|
123
|
+
// #272727, one 1 CSS px #3c3c3c divider between them).
|
|
124
|
+
aria-haspopup="dialog"
|
|
125
|
+
aria-expanded={popoverOpen}
|
|
126
|
+
variant={variant}
|
|
127
|
+
size={size}
|
|
128
|
+
onClick={() => setPopoverOpen(!popoverOpen)}
|
|
129
|
+
>
|
|
130
|
+
<EditorIcon icon={faCaretDown} size="xs" />
|
|
131
|
+
</IconButton>
|
|
132
|
+
</Tooltip>
|
|
133
|
+
</SplitButtonGroup>
|
|
134
|
+
{popoverOpen && (
|
|
135
|
+
<EditorPopover className="vgai-snap-popover">
|
|
136
|
+
<Stack gap={2}>
|
|
137
|
+
<Text variant="caption" tone="muted">
|
|
138
|
+
Translate
|
|
139
|
+
</Text>
|
|
140
|
+
<TextInput
|
|
141
|
+
type="number"
|
|
142
|
+
value={store.snapValues.translate}
|
|
143
|
+
step={0.25}
|
|
144
|
+
min={0.01}
|
|
145
|
+
onChange={(event) =>
|
|
146
|
+
store.setSnapValues({ translate: Number(event.target.value) || 1 })
|
|
147
|
+
}
|
|
148
|
+
/>
|
|
149
|
+
<Text variant="caption" tone="muted">
|
|
150
|
+
Rotate (deg)
|
|
151
|
+
</Text>
|
|
152
|
+
<TextInput
|
|
153
|
+
type="number"
|
|
154
|
+
value={store.snapValues.rotate}
|
|
155
|
+
step={5}
|
|
156
|
+
min={1}
|
|
157
|
+
onChange={(event) =>
|
|
158
|
+
store.setSnapValues({ rotate: Number(event.target.value) || 15 })
|
|
159
|
+
}
|
|
160
|
+
/>
|
|
161
|
+
<Text variant="caption" tone="muted">
|
|
162
|
+
Scale
|
|
163
|
+
</Text>
|
|
164
|
+
<TextInput
|
|
165
|
+
type="number"
|
|
166
|
+
value={store.snapValues.scale}
|
|
167
|
+
step={0.05}
|
|
168
|
+
min={0.01}
|
|
169
|
+
onChange={(event) =>
|
|
170
|
+
store.setSnapValues({ scale: Number(event.target.value) || 0.25 })
|
|
171
|
+
}
|
|
172
|
+
/>
|
|
173
|
+
{dimensions === '3d' && (
|
|
174
|
+
<>
|
|
175
|
+
<Inline gap={2} align="center" onClick={() => store.toggleSnapToSurface()}>
|
|
176
|
+
<Checkbox checked={store.snapToSurface} readOnly />
|
|
177
|
+
<Text>Snap to Surface</Text>
|
|
178
|
+
</Inline>
|
|
179
|
+
<Text variant="caption" tone="dim">
|
|
180
|
+
Hold <Keycap>Ctrl</Keycap> while dragging to snap once ·{' '}
|
|
181
|
+
<Keycap>{shortcutFor('viewport.toggleSnap')}</Keycap> toggles
|
|
182
|
+
</Text>
|
|
183
|
+
<Text variant="caption" tone="dim">
|
|
184
|
+
Hold <Keycap>{shortcutFor('viewport.vertexSnapHold')}</Keycap> during translate
|
|
185
|
+
for vertex snap
|
|
186
|
+
</Text>
|
|
187
|
+
</>
|
|
188
|
+
)}
|
|
189
|
+
</Stack>
|
|
190
|
+
</EditorPopover>
|
|
191
|
+
)}
|
|
192
|
+
</div>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const pivotLabels: Record<PivotMode, string> = {
|
|
197
|
+
'active-element': 'Active Element',
|
|
198
|
+
'median-point': 'Median Point',
|
|
199
|
+
'individual-origins': 'Individual Origins',
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
function PivotButton({ store }: { store: EditorShellStore }) {
|
|
203
|
+
const modes: PivotMode[] = ['active-element', 'median-point', 'individual-origins'];
|
|
204
|
+
const label = `Pivot: ${pivotLabels[store.pivotMode]}`;
|
|
205
|
+
return (
|
|
206
|
+
<Tooltip text={label} hotkey={shortcutFor('viewport.cyclePivot')}>
|
|
207
|
+
<IconButton
|
|
208
|
+
aria-label={label}
|
|
209
|
+
aria-pressed={store.pivotMode !== 'active-element'}
|
|
210
|
+
variant="secondary"
|
|
211
|
+
onClick={() => {
|
|
212
|
+
const index = modes.indexOf(store.pivotMode);
|
|
213
|
+
store.setPivotMode(modes[(index + 1) % modes.length]!);
|
|
214
|
+
}}
|
|
215
|
+
>
|
|
216
|
+
<EditorIcon icon={faCrosshairs} size="md" />
|
|
217
|
+
</IconButton>
|
|
218
|
+
</Tooltip>
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const anchorLabels: Record<GizmoAnchor, string> = {
|
|
223
|
+
auto: 'Auto',
|
|
224
|
+
pivot: 'Pivot',
|
|
225
|
+
center: 'Center',
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* WHERE the gizmo is drawn — the standard DCC pivot/centre affordance, cycled
|
|
230
|
+
* the way its `PivotButton` neighbour cycles its own three states.
|
|
231
|
+
*
|
|
232
|
+
* `Auto` leads because the right answer is a property of the SUBJECT: an
|
|
233
|
+
* ordinary node's pivot already sits in its content and nothing moves, while a
|
|
234
|
+
* world-anchored instanced system's sits at (0,0,0) with everything visible
|
|
235
|
+
* somewhere else (`instanced-presentation.ts`). The two explicit states are the
|
|
236
|
+
* override, in both directions.
|
|
237
|
+
*/
|
|
238
|
+
function AnchorButton({ store }: { store: EditorShellStore }) {
|
|
239
|
+
const modes: GizmoAnchor[] = ['auto', 'pivot', 'center'];
|
|
240
|
+
const label = `Anchor: ${anchorLabels[store.gizmoAnchor]}`;
|
|
241
|
+
return (
|
|
242
|
+
<Tooltip text={label}>
|
|
243
|
+
<IconButton
|
|
244
|
+
aria-label={label}
|
|
245
|
+
aria-pressed={store.gizmoAnchor !== 'auto'}
|
|
246
|
+
variant="secondary"
|
|
247
|
+
onClick={() => {
|
|
248
|
+
const index = modes.indexOf(store.gizmoAnchor);
|
|
249
|
+
store.setGizmoAnchor(modes[(index + 1) % modes.length]!);
|
|
250
|
+
}}
|
|
251
|
+
>
|
|
252
|
+
<EditorIcon icon={store.gizmoAnchor === 'center' ? faCircleDot : faBullseye} size="md" />
|
|
253
|
+
</IconButton>
|
|
254
|
+
</Tooltip>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function TransformOptionsButton({ store }: { store: EditorShellStore }) {
|
|
259
|
+
const [open, setOpen] = useState(false);
|
|
260
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
261
|
+
useEffect(() => {
|
|
262
|
+
if (!open) return;
|
|
263
|
+
const close = (event: MouseEvent) => {
|
|
264
|
+
if (!ref.current?.contains(event.target as Node)) setOpen(false);
|
|
265
|
+
};
|
|
266
|
+
document.addEventListener('mousedown', close);
|
|
267
|
+
return () => document.removeEventListener('mousedown', close);
|
|
268
|
+
}, [open]);
|
|
269
|
+
return (
|
|
270
|
+
<div ref={ref} className="vgai-viewport-popover-anchor">
|
|
271
|
+
<Tooltip text="Transform options">
|
|
272
|
+
<IconButton
|
|
273
|
+
aria-label="Transform options"
|
|
274
|
+
// Same reading as the snap group's dropdown half: an anchored
|
|
275
|
+
// settings popover is a menu button, and this is where Blender's
|
|
276
|
+
// proportional-editing dropdown sits in the row.
|
|
277
|
+
aria-haspopup="dialog"
|
|
278
|
+
aria-expanded={open}
|
|
279
|
+
variant="secondary"
|
|
280
|
+
onClick={() => setOpen((value) => !value)}
|
|
281
|
+
>
|
|
282
|
+
<EditorIcon icon={faArrowDown} size="md" />
|
|
283
|
+
</IconButton>
|
|
284
|
+
</Tooltip>
|
|
285
|
+
{open ? (
|
|
286
|
+
<EditorPopover style={{ minWidth: 240 }}>
|
|
287
|
+
<Stack gap={3}>
|
|
288
|
+
<Button
|
|
289
|
+
size="compact"
|
|
290
|
+
variant="ghost"
|
|
291
|
+
onClick={() => {
|
|
292
|
+
store.snapSelectionToFloor();
|
|
293
|
+
setOpen(false);
|
|
294
|
+
}}
|
|
295
|
+
>
|
|
296
|
+
Snap Selection to Floor <Keycap>{shortcutFor('viewport.snapToFloor')}</Keycap>
|
|
297
|
+
</Button>
|
|
298
|
+
<Inline
|
|
299
|
+
gap={2}
|
|
300
|
+
align="center"
|
|
301
|
+
onClick={() => store.togglePreserveChildrenTransform()}
|
|
302
|
+
style={{ cursor: 'pointer' }}
|
|
303
|
+
>
|
|
304
|
+
<Checkbox checked={store.preserveChildrenTransform} readOnly />
|
|
305
|
+
<Text>Preserve Children Transform</Text>
|
|
306
|
+
</Inline>
|
|
307
|
+
<Text variant="caption" tone="dim">
|
|
308
|
+
Keep source-writable children fixed in world space while their parent moves.
|
|
309
|
+
</Text>
|
|
310
|
+
</Stack>
|
|
311
|
+
</EditorPopover>
|
|
312
|
+
) : null}
|
|
313
|
+
</div>
|
|
314
|
+
);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* THE TRANSFORM ORIENTATION control, transcribed from the frame rather than
|
|
319
|
+
* inferred: Blender's is a LABELLED DROPDOWN, not a cycling toggle. Measured on
|
|
320
|
+
* the native 2x `modeling.png` at row y=70 — the well runs x 1170..1323 (a
|
|
321
|
+
* 1 px #3c3c3c border at each end, #272727 fill between), i.e. 77 CSS px wide,
|
|
322
|
+
* because it carries an orientation glyph, the word `Global`, and a chevron at
|
|
323
|
+
* x 1304..1316 (13x8 device px, 6.5x4 CSS, peak 216). Ours was a 20 px
|
|
324
|
+
* icon-only button that cycled on click, which is also why the widget-colour
|
|
325
|
+
* rule painted it the #535353 pushbutton where the frame shows the menu well:
|
|
326
|
+
* the colour was agreeing with what the control DID.
|
|
327
|
+
*
|
|
328
|
+
* The STORE's vocabulary is unchanged and stays three.js's (`world`/`local`);
|
|
329
|
+
* only the printed word is the reference's, because `Global` is what this
|
|
330
|
+
* control is called in the frame this skew is transcribing.
|
|
331
|
+
*/
|
|
332
|
+
function TransformOrientationButton({ store }: { store: EditorShellStore }) {
|
|
333
|
+
const [open, setOpen] = useState(false);
|
|
334
|
+
const triggerRef = useRef<HTMLButtonElement>(null);
|
|
335
|
+
const label = store.transformSpace === 'world' ? 'Global' : 'Local';
|
|
336
|
+
return (
|
|
337
|
+
<div className="vgai-viewport-popover-anchor">
|
|
338
|
+
<Tooltip text={`Transform orientation: ${label}`}>
|
|
339
|
+
<Button
|
|
340
|
+
ref={triggerRef}
|
|
341
|
+
type="button"
|
|
342
|
+
size="compact"
|
|
343
|
+
variant="secondary"
|
|
344
|
+
aria-label={`Transform orientation: ${label}`}
|
|
345
|
+
aria-haspopup="menu"
|
|
346
|
+
aria-expanded={open}
|
|
347
|
+
onClick={() => setOpen((value) => !value)}
|
|
348
|
+
className="vgai-transform-orientation-trigger"
|
|
349
|
+
>
|
|
350
|
+
<EditorIcon icon={store.transformSpace === 'world' ? faGlobe : faCube} size="sm" />
|
|
351
|
+
<span>{label}</span>
|
|
352
|
+
<EditorIcon icon={faCaretDown} size="xs" />
|
|
353
|
+
</Button>
|
|
354
|
+
</Tooltip>
|
|
355
|
+
{open && (
|
|
356
|
+
<AnchoredMenu
|
|
357
|
+
anchorRef={triggerRef}
|
|
358
|
+
align="start"
|
|
359
|
+
clamp
|
|
360
|
+
aria-label="Transform orientation"
|
|
361
|
+
onDismiss={() => setOpen(false)}
|
|
362
|
+
>
|
|
363
|
+
{(['world', 'local'] as const).map((space) => (
|
|
364
|
+
<MenuItem
|
|
365
|
+
key={space}
|
|
366
|
+
role="menuitemradio"
|
|
367
|
+
aria-checked={store.transformSpace === space}
|
|
368
|
+
onSelect={() => {
|
|
369
|
+
store.setTransformSpace(space);
|
|
370
|
+
setOpen(false);
|
|
371
|
+
}}
|
|
372
|
+
>
|
|
373
|
+
<span className="vgai-menu-check">
|
|
374
|
+
{store.transformSpace === space && <EditorIcon icon={faCheck} size="xs" />}
|
|
375
|
+
</span>
|
|
376
|
+
{space === 'world' ? 'Global' : 'Local'}
|
|
377
|
+
</MenuItem>
|
|
378
|
+
))}
|
|
379
|
+
</AnchoredMenu>
|
|
380
|
+
)}
|
|
381
|
+
</div>
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* THE VIEWPORT HEADER'S TRANSFORM CONTROLS — orientation, pivot, snap and the
|
|
387
|
+
* transform options, drawn in the document's header beside the host's 3D
|
|
388
|
+
* controls (`DocumentHeaderStrip`).
|
|
389
|
+
*
|
|
390
|
+
* WHY HERE AND NOT ON THE SHELF: a control is placed by the panel that owns its
|
|
391
|
+
* job in the reference. In Blender's 3D viewport these four are HEADER
|
|
392
|
+
* controls — transform orientation, transform pivot point, snapping with its
|
|
393
|
+
* dropdown, proportional editing — and the tool shelf (T) holds tools only.
|
|
394
|
+
* They rode the `ToolStrip` here until 2026-09-18, and the magnet is what
|
|
395
|
+
* showed it: a horizontal `SplitButtonGroup` inside a rail one tool wide spent
|
|
396
|
+
* two boxes and hung a half-width caret off the column.
|
|
397
|
+
*
|
|
398
|
+
* THE GROUPING IS TRANSCRIBED, measured on the native 2x `modeling.png`
|
|
399
|
+
* (row y=62, x in device px): Blender lays four separate WELLS with 12 device
|
|
400
|
+
* px (6 CSS px) of bare header between them — orientation x 1171..1322 (76 CSS
|
|
401
|
+
* px, it carries the "Global" label), pivot x 1335..1396 (31), snap
|
|
402
|
+
* x 1409..1510 (51), proportional editing x 1523..1624 (51). The last two are
|
|
403
|
+
* SPLIT: a toggle segment in the pushbutton colour (#535353) then a one-pixel
|
|
404
|
+
* #3c3c3c divider then an icon+caret dropdown in the menu-well colour
|
|
405
|
+
* (#272727) — exactly the `SplitButtonGroup` shape the magnet already had, in
|
|
406
|
+
* the row where it lays out. Each well is 40 device px tall (20 CSS px, the
|
|
407
|
+
* density's control height) inside a 54-device-px header band.
|
|
408
|
+
*
|
|
409
|
+
* Each control is `secondary`, so the estate's widget-colour rule paints it:
|
|
410
|
+
* a toggle takes the pushbutton class and a popover trigger the menu well,
|
|
411
|
+
* read off the trigger's own ARIA (`theme.css`, "A MENU BUTTON"). They drew as
|
|
412
|
+
* ghost icons floating on the header band before that — measured beside the
|
|
413
|
+
* frame at 4x, every one of Blender's carries a well.
|
|
414
|
+
*
|
|
415
|
+
* Three readings where ours differs from the frame, kept as they are because
|
|
416
|
+
* this unit moves placement and not shape: Blender's orientation is a labelled
|
|
417
|
+
* dropdown (`Global v`) where ours cycles world/local on click — so ours takes
|
|
418
|
+
* the pushbutton #535353 where the frame shows the #272727 menu well, which is
|
|
419
|
+
* the colour rule agreeing with what the control DOES; its pivot is one
|
|
420
|
+
* dropdown where we carry two cycling toggles — pivot MODE and gizmo ANCHOR,
|
|
421
|
+
* sharing one well because they are one job (where the gizmo sits), which is
|
|
422
|
+
* how Blender groups them; and our toggles are 20x20 against the frame's 31
|
|
423
|
+
* for pivot, because a cycling toggle carries no caret.
|
|
424
|
+
*/
|
|
425
|
+
export function TransformHeaderControls({ store: stage }: { store?: EditorShellStore } = {}) {
|
|
426
|
+
// THE STAGE'S OWN STORE, when the caller knows it. Every stage owns an
|
|
427
|
+
// `EditorShellStore` (`stage-store-registry.ts`) and these four configure
|
|
428
|
+
// the gizmo in THAT stage's viewport, so writing the shell's from over a
|
|
429
|
+
// document stage set a value nothing on screen reads — MEASURED 2026-09-19
|
|
430
|
+
// on a prefab story: with the shell at `rotate`, the story's stage kept
|
|
431
|
+
// drawing the default COMBINED gizmo, and two captures a mode apart were
|
|
432
|
+
// byte-identical. The world root's stage runs on the shell store itself, so
|
|
433
|
+
// the Scene document is unchanged either way.
|
|
434
|
+
const shell = useEditorStore();
|
|
435
|
+
const store = stage ?? shell;
|
|
436
|
+
useSyncExternalStore(store.subscribe, store.getShellSnapshot ?? store.getSnapshot);
|
|
437
|
+
useSyncExternalStore(subscribeEditorKeymap, activeEditorKeymap, activeEditorKeymap);
|
|
438
|
+
return (
|
|
439
|
+
<EditorToolbar
|
|
440
|
+
compact
|
|
441
|
+
label="Transform controls"
|
|
442
|
+
data-testid="transform-header-controls"
|
|
443
|
+
className="vgai-transform-header-controls"
|
|
444
|
+
>
|
|
445
|
+
<TransformOrientationButton store={store} />
|
|
446
|
+
<SplitButtonGroup>
|
|
447
|
+
<PivotButton store={store} />
|
|
448
|
+
<AnchorButton store={store} />
|
|
449
|
+
</SplitButtonGroup>
|
|
450
|
+
<SnapButton store={store} size="default" variant="secondary" />
|
|
451
|
+
<TransformOptionsButton store={store} />
|
|
452
|
+
</EditorToolbar>
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* THE TOOL SHELF'S STRIP — tools, and nothing else (Blender's T shelf). The
|
|
458
|
+
* four header controls that used to trail it live in
|
|
459
|
+
* {@link TransformHeaderControls} now; the 2D canvas surface keeps its snap
|
|
460
|
+
* control inline because this strip lays out as a ROW over that stage (see
|
|
461
|
+
* `.vgai-viewport-toolbar-left` in `workspace-dock.css`) and that surface has
|
|
462
|
+
* no Blender analogue to place it against.
|
|
463
|
+
*
|
|
464
|
+
* THESE FOUR ARE BLENDER'S OWN SECOND TOOLBAR GROUP, and the order is its
|
|
465
|
+
* order. Measured 2026-09-19 on `modeling-edit-none.png`: the Edit Mode
|
|
466
|
+
* toolbar's 21 buttons run in five groups of 2 / 4 / 2 / 1 / 12, and group 2
|
|
467
|
+
* is exactly Move, Rotate, Scale, Transform — the same four verbs this strip
|
|
468
|
+
* has always carried, under Font Awesome drawings and with the combined tool
|
|
469
|
+
* FIRST. So the answer to "do the host's navigation buttons belong at the top
|
|
470
|
+
* of a Blender toolbar at all" is yes and they were already right; what was
|
|
471
|
+
* wrong was the order (Transform leads in Blender's list only as the LAST
|
|
472
|
+
* member, the all-handles fallback after the three single-channel tools) and
|
|
473
|
+
* two of the glyphs (`editorIcons.tool`'s docblock says which and why).
|
|
474
|
+
* BLENDER'S GROUP 1 IS SELECT BOX AND THE 3D CURSOR, and as of 2026-09-21 the
|
|
475
|
+
* FIRST of the two is drawn above them while the second is still not. The
|
|
476
|
+
* earlier note here said neither was, and its reason was right at the time:
|
|
477
|
+
* neither had anything behind it once the Edit Mesh document was deleted (the
|
|
478
|
+
* 21-row table that said what each of the twenty-one does is in git,
|
|
479
|
+
* `packages/mesh/contributions/mesh-edit-document.tsx` before 2026-09-19).
|
|
480
|
+
* Select Box has something behind it NOW — `TransformMode`'s `'select'`, the
|
|
481
|
+
* state in which no transform gizmo is drawn at all, which is what Blender's
|
|
482
|
+
* viewport opens in (`gizmo-select-box.png`; the look states it through
|
|
483
|
+
* `workspace-regions.ts`'s `shelfTool`). The 3D cursor still has nothing
|
|
484
|
+
* behind it and is still not drawn; adding the button before the cursor exists
|
|
485
|
+
* would be exactly the inert control the paragraph below removes.
|
|
486
|
+
*
|
|
487
|
+
* WHAT THEY DRIVE IS THE STAGE'S ANSWER, in two parts.
|
|
488
|
+
*
|
|
489
|
+
* `store` — WHICH STAGE'S GIZMO. Every stage owns an `EditorShellStore`
|
|
490
|
+
* (`stage-store-registry.ts`), and these four write `transformMode`, which
|
|
491
|
+
* that stage's `EditorViewport` reads. Writing the SHELL's from over a
|
|
492
|
+
* document stage set a value nothing on screen read: MEASURED 2026-09-19 on
|
|
493
|
+
* a prefab story with its subject selected, the shell store at `rotate`, the
|
|
494
|
+
* stage still drawing the default COMBINED gizmo, and two `capture-active-
|
|
495
|
+
* document` frames a mode apart BYTE-IDENTICAL. That, not a missing gizmo,
|
|
496
|
+
* is why these four were inert over a document stage. The world root's stage
|
|
497
|
+
* runs on the shell store itself, so the Scene document is unchanged.
|
|
498
|
+
*
|
|
499
|
+
* `door` — a stage that transforms MODALLY instead (a Model document's
|
|
500
|
+
* `G`/`R`/`S`, `registerStageTransform` in `@volter/editor-sdk/contributions`,
|
|
501
|
+
* whose note carries that measurement). Then the three single-channel tools
|
|
502
|
+
* arm it and the all-handles tool is NOT DRAWN: Blender's fourth is a gizmo
|
|
503
|
+
* and a modal transform has no twin for it, so drawing it would be the inert
|
|
504
|
+
* control this seam exists to remove. `stageTransformDriver`
|
|
505
|
+
* (`stage-context.ts`) is what chooses between the two.
|
|
506
|
+
*/
|
|
507
|
+
const NO_DOOR_SUBSCRIBE = () => () => {};
|
|
508
|
+
const NO_DOOR_ARMED = () => null;
|
|
509
|
+
|
|
510
|
+
export function ToolStrip({
|
|
511
|
+
dimensions = '3d',
|
|
512
|
+
door,
|
|
513
|
+
store: stage,
|
|
514
|
+
}: {
|
|
515
|
+
dimensions?: '2d' | '3d';
|
|
516
|
+
door?: StageTransformDoor;
|
|
517
|
+
store?: EditorShellStore;
|
|
518
|
+
} = {}) {
|
|
519
|
+
const shell = useEditorStore();
|
|
520
|
+
const store = stage ?? shell;
|
|
521
|
+
useSyncExternalStore(store.subscribe, store.getShellSnapshot ?? store.getSnapshot);
|
|
522
|
+
// Every hint below is rendered from the active keymap; a live switch must
|
|
523
|
+
// repaint the strip rather than leave it advertising the other table.
|
|
524
|
+
useSyncExternalStore(subscribeEditorKeymap, activeEditorKeymap, activeEditorKeymap);
|
|
525
|
+
// A modal transform's lit state is the DOOR's, and it changes without the
|
|
526
|
+
// shell store moving at all — the same `useSyncExternalStore` pair every
|
|
527
|
+
// out-of-tree panel uses, with the mesh document's own null-session shape
|
|
528
|
+
// for the gizmo arm (hooks cannot be conditional).
|
|
529
|
+
const armed = useSyncExternalStore(
|
|
530
|
+
door?.subscribe ?? NO_DOOR_SUBSCRIBE,
|
|
531
|
+
door?.armed ?? NO_DOOR_ARMED,
|
|
532
|
+
door?.armed ?? NO_DOOR_ARMED,
|
|
533
|
+
);
|
|
534
|
+
const single = [
|
|
535
|
+
{
|
|
536
|
+
mode: 'translate',
|
|
537
|
+
faIcon: editorIcons.tool.move,
|
|
538
|
+
action: 'transform.translate',
|
|
539
|
+
label: 'Move',
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
mode: 'rotate',
|
|
543
|
+
faIcon: editorIcons.tool.rotate,
|
|
544
|
+
action: 'transform.rotate',
|
|
545
|
+
label: 'Rotate',
|
|
546
|
+
},
|
|
547
|
+
{ mode: 'scale', faIcon: editorIcons.tool.scale, action: 'transform.scale', label: 'Scale' },
|
|
548
|
+
] as const satisfies readonly {
|
|
549
|
+
mode: StageTransformKind;
|
|
550
|
+
faIcon: typeof faArrowsUpDownLeftRight;
|
|
551
|
+
action: EditorKeyActionId;
|
|
552
|
+
label: string;
|
|
553
|
+
}[];
|
|
554
|
+
return (
|
|
555
|
+
<FloatingToolbar
|
|
556
|
+
label="Transform tools"
|
|
557
|
+
data-testid={dimensions === '2d' ? 'canvas-2d-toolstrip' : 'threejs-toolstrip'}
|
|
558
|
+
className="vgai-viewport-toolbar vgai-viewport-toolbar-left"
|
|
559
|
+
>
|
|
560
|
+
{/* SELECT BOX, first — Blender's own group 1 (see the docblock). It is
|
|
561
|
+
not offered over a MODAL door: `door.begin` takes a transform kind
|
|
562
|
+
and a modal transform has no "arm nothing" member, so the button
|
|
563
|
+
would have nothing to call. */}
|
|
564
|
+
{door ? null : (
|
|
565
|
+
<ModeButton
|
|
566
|
+
faIcon={editorIcons.tool.select}
|
|
567
|
+
action="transform.select"
|
|
568
|
+
label="Select"
|
|
569
|
+
active={store.transformMode === 'select'}
|
|
570
|
+
onArm={() => requestTransformMode(store, 'select')}
|
|
571
|
+
/>
|
|
572
|
+
)}
|
|
573
|
+
{single.map((tool) => (
|
|
574
|
+
<ModeButton
|
|
575
|
+
key={tool.mode}
|
|
576
|
+
faIcon={tool.faIcon}
|
|
577
|
+
action={tool.action}
|
|
578
|
+
label={tool.label}
|
|
579
|
+
active={door ? armed === tool.mode : store.transformMode === tool.mode}
|
|
580
|
+
onArm={() => (door ? door.begin(tool.mode) : requestTransformMode(store, tool.mode))}
|
|
581
|
+
/>
|
|
582
|
+
))}
|
|
583
|
+
{door ? null : (
|
|
584
|
+
<ModeButton
|
|
585
|
+
faIcon={editorIcons.tool.transform}
|
|
586
|
+
action="transform.combined"
|
|
587
|
+
label="Transform (all handles)"
|
|
588
|
+
active={store.transformMode === 'combined'}
|
|
589
|
+
onArm={() => requestTransformMode(store, 'combined')}
|
|
590
|
+
/>
|
|
591
|
+
)}
|
|
592
|
+
{dimensions === '2d' ? <SnapButton store={store} dimensions="2d" /> : null}
|
|
593
|
+
</FloatingToolbar>
|
|
594
|
+
);
|
|
595
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders the editor's transient hint (see `../transient-hint.ts` for the
|
|
3
|
+
* publisher and the rationale). Mounted once, near the bottom of the viewport;
|
|
4
|
+
* absent from the DOM entirely when there is nothing to say.
|
|
5
|
+
*
|
|
6
|
+
* `role="status"` + `aria-live="polite"` so a refusal is announced, not just
|
|
7
|
+
* drawn — this exists BECAUSE the refusal used to be silent.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { space, themeVars, zIndex } from '@volter/editor-sdk/widgets';
|
|
11
|
+
import { useSyncExternalStore } from 'react';
|
|
12
|
+
import { subscribeTransientHint, transientHint } from '../transient-hint';
|
|
13
|
+
|
|
14
|
+
export function TransientHintOverlay() {
|
|
15
|
+
const hint = useSyncExternalStore(subscribeTransientHint, transientHint, transientHint);
|
|
16
|
+
if (!hint) return null;
|
|
17
|
+
return (
|
|
18
|
+
<div
|
|
19
|
+
key={hint.id}
|
|
20
|
+
role="status"
|
|
21
|
+
aria-live="polite"
|
|
22
|
+
data-testid="transient-hint"
|
|
23
|
+
style={{
|
|
24
|
+
position: 'absolute',
|
|
25
|
+
left: '50%',
|
|
26
|
+
bottom: space[6],
|
|
27
|
+
transform: 'translateX(-50%)',
|
|
28
|
+
maxWidth: 'min(440px, 80%)',
|
|
29
|
+
padding: `${space[3]}px ${space[5]}px`,
|
|
30
|
+
borderRadius: themeVars.shape.medium,
|
|
31
|
+
border: `1px solid ${themeVars.boundary.strong}`,
|
|
32
|
+
background: themeVars.surface.overlay,
|
|
33
|
+
color: themeVars.content.primary,
|
|
34
|
+
fontSize: 'var(--vgai-font-base)',
|
|
35
|
+
lineHeight: 1.4,
|
|
36
|
+
textAlign: 'center',
|
|
37
|
+
pointerEvents: 'none',
|
|
38
|
+
zIndex: zIndex.toast,
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
{hint.message}
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
}
|