@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,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inspector PRESENTATION — how the inspector box is physically laid out on the
|
|
3
|
+
* surface you are looking at. Three projections (`inspection/model.ts`'s
|
|
4
|
+
* `InspectionPresentation`):
|
|
5
|
+
*
|
|
6
|
+
* - `'column'` (the DEFAULT): the subject's full inspector as a slim vertical
|
|
7
|
+
* column — identity row, a section-icon strip that signposts what the
|
|
8
|
+
* subject has and jumps to a section, then every section stacked and
|
|
9
|
+
* collapsible. With agents doing most editing the inspector's daily job is
|
|
10
|
+
* looking, and an always-present slim column reads details with no
|
|
11
|
+
* discovery-dependent expand gesture (owner, 2026-08-19).
|
|
12
|
+
* - `'properties'`: the docked column with its sections TABBED — a vertical
|
|
13
|
+
* icon rail, one section body at a time. Blender's and Substance's
|
|
14
|
+
* properties editors are this shape; a workspace asks for it as data
|
|
15
|
+
* (`workspace-presets.ts`, `EditorWorkspaceRegions.inspector`).
|
|
16
|
+
* - `'card'`: the space-tight fallback the user opts into — a MINI card
|
|
17
|
+
* (preview, name, the same icon strip, the labeled open-for-edit) that
|
|
18
|
+
* collapses at the floor to a single-line PILL. Clicking any collapsed form
|
|
19
|
+
* restores the column.
|
|
20
|
+
*
|
|
21
|
+
* The resolution is per SURFACE, not global (W3): the affinity is the same
|
|
22
|
+
* narrow column everywhere, but the PREFERENCE is keyed by surface, so
|
|
23
|
+
* collapsing the scene's inspector to a card leaves the asset document's
|
|
24
|
+
* alone. `resolved = user override for THIS surface ?? the active workspace's
|
|
25
|
+
* choice ?? the subject's affinity`, where the affinity is
|
|
26
|
+
* `inspectionAffinityFor(kind)`. The expand/collapse affordances write the
|
|
27
|
+
* override for the surface they are on and no other.
|
|
28
|
+
*
|
|
29
|
+
* The layout host consumes the resolution physically (column present vs
|
|
30
|
+
* overlay card vs neither); `components/Inspector.tsx` consumes it visually
|
|
31
|
+
* (narrow column vs mini card). Overrides are persisted per-user in
|
|
32
|
+
* localStorage (same convenience-not-truth rationale as
|
|
33
|
+
* `workspace-state-persistence.ts`'s storage decision), global across projects
|
|
34
|
+
* like the theme preference — how you like your inspector is not a property of
|
|
35
|
+
* any one game.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import type { IconDefinition } from '@fortawesome/free-solid-svg-icons';
|
|
39
|
+
import type {
|
|
40
|
+
InspectionPresentation,
|
|
41
|
+
InspectionSection,
|
|
42
|
+
InspectionSurfaceKind,
|
|
43
|
+
} from './inspection/model';
|
|
44
|
+
|
|
45
|
+
/** What a user can ASK for — both projections, on any surface. */
|
|
46
|
+
export type InspectorPresentationOverride = InspectionPresentation;
|
|
47
|
+
|
|
48
|
+
const STORAGE_KEY = 'vgai-inspector-presentation-v2';
|
|
49
|
+
|
|
50
|
+
type OverrideMap = Partial<Record<InspectionSurfaceKind, InspectorPresentationOverride>>;
|
|
51
|
+
|
|
52
|
+
function storage(): Storage | null {
|
|
53
|
+
try {
|
|
54
|
+
return typeof window === 'undefined' ? null : window.localStorage;
|
|
55
|
+
} catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function isOverride(value: unknown): value is InspectorPresentationOverride {
|
|
61
|
+
return value === 'card' || value === 'column' || value === 'properties';
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function readPersisted(): OverrideMap {
|
|
65
|
+
const raw = storage()?.getItem(STORAGE_KEY);
|
|
66
|
+
if (!raw) return {};
|
|
67
|
+
try {
|
|
68
|
+
const parsed: unknown = JSON.parse(raw);
|
|
69
|
+
if (!parsed || typeof parsed !== 'object') return {};
|
|
70
|
+
const map: OverrideMap = {};
|
|
71
|
+
for (const [key, value] of Object.entries(parsed as Record<string, unknown>)) {
|
|
72
|
+
if (isOverride(value)) map[key as InspectionSurfaceKind] = value;
|
|
73
|
+
}
|
|
74
|
+
return map;
|
|
75
|
+
} catch {
|
|
76
|
+
return {};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let _overrides: OverrideMap | null = null;
|
|
81
|
+
let _version = 0;
|
|
82
|
+
const _listeners = new Set<() => void>();
|
|
83
|
+
|
|
84
|
+
function overrides(): OverrideMap {
|
|
85
|
+
if (_overrides === null) _overrides = readPersisted();
|
|
86
|
+
return _overrides;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** The user's stored preference for one surface, or `null` when they have
|
|
90
|
+
* never expressed one there. */
|
|
91
|
+
export function inspectorPresentationOverride(
|
|
92
|
+
surface: InspectionSurfaceKind,
|
|
93
|
+
): InspectorPresentationOverride | null {
|
|
94
|
+
return overrides()[surface] ?? null;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function setInspectorPresentationOverride(
|
|
98
|
+
surface: InspectionSurfaceKind,
|
|
99
|
+
value: InspectorPresentationOverride,
|
|
100
|
+
): void {
|
|
101
|
+
if (inspectorPresentationOverride(surface) === value) return;
|
|
102
|
+
_overrides = { ...overrides(), [surface]: value };
|
|
103
|
+
_version++;
|
|
104
|
+
try {
|
|
105
|
+
storage()?.setItem(STORAGE_KEY, JSON.stringify(_overrides));
|
|
106
|
+
} catch {
|
|
107
|
+
// Persistence is convenience; the in-memory preference is already applied.
|
|
108
|
+
}
|
|
109
|
+
for (const listener of _listeners) listener();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function subscribeInspectorPresentation(listener: () => void): () => void {
|
|
113
|
+
_listeners.add(listener);
|
|
114
|
+
return () => {
|
|
115
|
+
_listeners.delete(listener);
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Monotonic change counter — the `getSnapshot` for `useSyncExternalStore`. */
|
|
120
|
+
export function inspectorPresentationVersion(): number {
|
|
121
|
+
return _version;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// ---- Resolution (pure — headlessly testable) -----------------------------
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The resolver, whole: a surface's affinity, under the active WORKSPACE's
|
|
128
|
+
* choice (`workspace-regions.ts`; only the docked layouts — a workspace never
|
|
129
|
+
* collapses the inspector to a card), under whatever the user asked for ON
|
|
130
|
+
* THAT SURFACE. Every surface is overridable — an asset document expands to
|
|
131
|
+
* the column and collapses back exactly as a scene does, because an asset
|
|
132
|
+
* document is the same paradigm scoped to a subtree.
|
|
133
|
+
*/
|
|
134
|
+
export function resolveInspectorPresentation(
|
|
135
|
+
affinity: InspectionPresentation,
|
|
136
|
+
override: InspectorPresentationOverride | null,
|
|
137
|
+
workspaceDefault: 'column' | 'properties' | 'card' | null = null,
|
|
138
|
+
): InspectionPresentation {
|
|
139
|
+
return override ?? workspaceDefault ?? affinity;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function __resetInspectorPresentationForTest(): void {
|
|
143
|
+
_overrides = null;
|
|
144
|
+
_version = 0;
|
|
145
|
+
_listeners.clear();
|
|
146
|
+
try {
|
|
147
|
+
storage()?.removeItem(STORAGE_KEY);
|
|
148
|
+
} catch {
|
|
149
|
+
// ignore
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ---- Section-icon-strip derivation (pure — headlessly testable) -----------
|
|
154
|
+
|
|
155
|
+
/** One glyph on the section-icon strip — one SECTION of the composed
|
|
156
|
+
* {@link InspectionSubject}, and nothing else: the live preview, Transform,
|
|
157
|
+
* each property GROUP (Physics, Material, a component block…) and each
|
|
158
|
+
* matched contribution individually, never one lumped "everything else"
|
|
159
|
+
* entry. The strip signposts what the subject HAS and jumps to a section; it
|
|
160
|
+
* is not a tab that opens one section into a floating panel. */
|
|
161
|
+
export interface CompactInspectorTab {
|
|
162
|
+
/** The section's own id, which is the strip's jump target
|
|
163
|
+
* (`'preview'`, `'transform'`, `'properties'`, `` `group:<groupId>` ``,
|
|
164
|
+
* `'stories'`, a contribution's id). */
|
|
165
|
+
readonly id: string;
|
|
166
|
+
/** Tooltip / accessible name for the icon button. */
|
|
167
|
+
readonly title: string;
|
|
168
|
+
/** The section's own glyph. Required by the model, so every entry has one. */
|
|
169
|
+
readonly icon: IconDefinition;
|
|
170
|
+
/** The rail GROUP this section named (`InspectionSection.railGroup`), if
|
|
171
|
+
* any. The Properties rail draws a separator wherever it changes, the way
|
|
172
|
+
* `ED_buttons_tabs_list` inserts `BCONTEXT_SEPARATOR`
|
|
173
|
+
* (`space_buttons/space_buttons.cc:201-255`). */
|
|
174
|
+
readonly railGroup?: string | undefined;
|
|
175
|
+
/** This section is the tab the rail opens on when nothing has been chosen
|
|
176
|
+
* for the subject yet (`InspectionSection.railDefault`). */
|
|
177
|
+
readonly railDefault?: boolean | undefined;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* The section-icon strip for a subject: its sections, in their composed order,
|
|
182
|
+
* ONE FOR ONE. This is the whole function, and that is the point — "the row of
|
|
183
|
+
* buttons is what the sections are" (owner, 2026-08-07) is true by construction
|
|
184
|
+
* here, not by two renderers agreeing. A subject with no sections has no strip
|
|
185
|
+
* and shows its headline.
|
|
186
|
+
*
|
|
187
|
+
* The strip knows nothing about what any section CONTAINS; identity, title,
|
|
188
|
+
* icon and order all come off the model (`inspection/compose.ts`). There is
|
|
189
|
+
* no synthesized entry: the live preview is an ordinary section like the rest.
|
|
190
|
+
*/
|
|
191
|
+
export function compactInspectorTabs(subject: {
|
|
192
|
+
readonly sections: readonly InspectionSection[];
|
|
193
|
+
}): CompactInspectorTab[] {
|
|
194
|
+
return subject.sections.map((section) => ({
|
|
195
|
+
id: section.id,
|
|
196
|
+
title: section.title,
|
|
197
|
+
icon: section.icon,
|
|
198
|
+
...(section.railGroup === undefined ? {} : { railGroup: section.railGroup }),
|
|
199
|
+
...(section.railDefault === undefined ? {} : { railDefault: section.railDefault }),
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inspector section-contribution registry (C2) — the PERMANENT, sanctioned
|
|
3
|
+
* adapter-module seam for contributing rich React sections to the ONE
|
|
4
|
+
* inspector shell. A matched registration becomes a custom-bodied
|
|
5
|
+
* `InspectionSection` in the composed subject (`inspection/compose.ts`), which
|
|
6
|
+
* both inspector presentations then project. Mirrors `hierarchy-menu-registry.ts`'s
|
|
7
|
+
* `register(match, …)` / `get(ctx)` / `__resetForTest` pattern one-for-one —
|
|
8
|
+
* same "test the pure logic headlessly" convention (no jsdom in this repo's
|
|
9
|
+
* default `vitest.config.ts` `environment: 'node'`).
|
|
10
|
+
*
|
|
11
|
+
* A contribution CLAIMS the section it provides, by id. Claiming a built-in
|
|
12
|
+
* id (`transform`, `properties`, `stories`) replaces that built-in for a
|
|
13
|
+
* matched selection — a rich typed section stands in for the thin generic
|
|
14
|
+
* grid, and the shell never double-renders the same affordance. Replacement
|
|
15
|
+
* is positive space: the contribution says what it IS, never what it hides.
|
|
16
|
+
* The composer (`inspection/compose.ts`) is the one place that resolves it.
|
|
17
|
+
*
|
|
18
|
+
* The generic property grid (`PropertyDescriptor.group` →
|
|
19
|
+
* `inspector-property-grouping.ts`'s `groupProperties()` →
|
|
20
|
+
* `ingest-group-<id>` sub-sections) is one such claimable block: it and its
|
|
21
|
+
* groups are `PROPERTIES_SECTION_ID`'s channel (see that constant), so a
|
|
22
|
+
* contribution claiming `properties` presents the node's groups too.
|
|
23
|
+
*
|
|
24
|
+
* Engine stays React-free (D6): this module, every contribution, and every
|
|
25
|
+
* `Section` component live in the editor package only.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
import type { IconDefinition } from '@fortawesome/free-solid-svg-icons';
|
|
29
|
+
import type { AuthoringAdapter, EditorNode } from '@volter/editor-project/adapter';
|
|
30
|
+
import type { ComponentType } from 'react';
|
|
31
|
+
import type { InspectionSection } from './inspection/model';
|
|
32
|
+
|
|
33
|
+
export interface InspectorSectionProps {
|
|
34
|
+
readonly adapter: AuthoringAdapter;
|
|
35
|
+
/** Selected node id; `null` in the no-selection (environment) state. */
|
|
36
|
+
readonly nodeId: string | null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The composition a contribution is being matched INSIDE — the one fact
|
|
41
|
+
* `(node, adapter)` cannot carry.
|
|
42
|
+
*
|
|
43
|
+
* With nothing selected, `node` is `null` on every surface alike: an open
|
|
44
|
+
* Asset Lab document's empty state and the play surface's Game subject hand a
|
|
45
|
+
* matcher the identical two arguments, so a contribution matching `node ===
|
|
46
|
+
* null` matched both and leaked its sections into whichever empty state
|
|
47
|
+
* happened to be showing. `nullSubjectId` names the empty-state subject
|
|
48
|
+
* actually being composed (`inspection/null-subject.ts`), so a contribution
|
|
49
|
+
* scopes itself POSITIVELY to the subject it belongs to. `null` whenever a
|
|
50
|
+
* node IS selected — there is no empty-state subject in that composition.
|
|
51
|
+
*/
|
|
52
|
+
export interface InspectorSectionMatchContext {
|
|
53
|
+
readonly nullSubjectId: string | null;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** The context handed to a match that asks for none — a selected-node
|
|
57
|
+
* composition, and the honest default for a caller outside the shell. */
|
|
58
|
+
const NO_NULL_SUBJECT: InspectorSectionMatchContext = { nullSubjectId: null };
|
|
59
|
+
|
|
60
|
+
interface InspectorContributionBase {
|
|
61
|
+
/** `node` is `null` when nothing is selected (environment state); `context`
|
|
62
|
+
* says WHICH empty state that is. */
|
|
63
|
+
readonly match: (
|
|
64
|
+
node: EditorNode | null,
|
|
65
|
+
adapter: AuthoringAdapter,
|
|
66
|
+
context: InspectorSectionMatchContext,
|
|
67
|
+
) => boolean;
|
|
68
|
+
/**
|
|
69
|
+
* WHO SHIPPED THIS — the package (or project folder) whose module registered
|
|
70
|
+
* it (`tool-loader.ts`'s `LoadedToolContributionBase.owner`). It is what
|
|
71
|
+
* makes a document's OWNED Properties rail answerable: with
|
|
72
|
+
* `inspectorRail = 'owned'` the composer keeps the sections whose owner is
|
|
73
|
+
* the active document's own package and stands every other one down
|
|
74
|
+
* (`inspection/compose.ts`). Absent on a first-party registration made by
|
|
75
|
+
* the host itself, which is exactly the set an owned rail excludes.
|
|
76
|
+
*/
|
|
77
|
+
readonly owner?: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A SECTION'S GLYPH, static or resolved from the subject. Blender's Object
|
|
82
|
+
* Data tab is the case that needs the second shape: `buttons_context_compute`
|
|
83
|
+
* (`space_buttons/buttons_context.cc:795-810`) sets the tab's icon from
|
|
84
|
+
* `RNA_struct_ui_icon(ptr->type)`, so a mesh's mark and an armature's differ.
|
|
85
|
+
* `inspection/compose.ts` resolves it once, at composition.
|
|
86
|
+
*/
|
|
87
|
+
export type InspectorSectionIcon =
|
|
88
|
+
| IconDefinition
|
|
89
|
+
| ((node: EditorNode | null, adapter: AuthoringAdapter) => IconDefinition);
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* An adapter-side PRODUCER of subject data: it answers "what identified
|
|
93
|
+
* sections does this node have?" with a list, computed from the node itself.
|
|
94
|
+
*
|
|
95
|
+
* This is the shape an adapter with a rich, node-dependent inspector uses —
|
|
96
|
+
* the react/DOM adapter's Layout / Style / Position / Spacing / component-prop
|
|
97
|
+
* blocks are its descriptor GROUPS, so their identities (and how many there
|
|
98
|
+
* are) can only come from the node. Before it existed, that adapter
|
|
99
|
+
* contributed ONE section titled "React" whose body privately rendered all of
|
|
100
|
+
* them: one opaque tab on the card, one opaque block in the column, and
|
|
101
|
+
* nothing the model could name (owner, 2026-08-06 — "every section its own
|
|
102
|
+
* identified tab, no lumps").
|
|
103
|
+
*
|
|
104
|
+
* A produced section is an ordinary {@link InspectionSection}: it claims its
|
|
105
|
+
* id exactly like a static contribution does, so a produced `properties` or
|
|
106
|
+
* `group:<id>` section REPLACES the generic built-in of the same id.
|
|
107
|
+
*/
|
|
108
|
+
export interface InspectorSectionsProducer extends InspectorContributionBase {
|
|
109
|
+
readonly sections: (
|
|
110
|
+
node: EditorNode | null,
|
|
111
|
+
adapter: AuthoringAdapter,
|
|
112
|
+
) => readonly InspectionSection[];
|
|
113
|
+
/** Section ids this contribution claims even when it produces no section
|
|
114
|
+
* for them — e.g. an adapter that renders the descriptor channel itself
|
|
115
|
+
* and must stand the generic grid down even for a node with no loose
|
|
116
|
+
* fields. */
|
|
117
|
+
readonly claims?: readonly string[];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface InspectorSectionRegistration extends InspectorContributionBase {
|
|
121
|
+
/**
|
|
122
|
+
* The `InspectionSection` identity this contribution PROVIDES. A built-in
|
|
123
|
+
* id (`inspection/model.ts`'s `TRANSFORM_SECTION_ID`,
|
|
124
|
+
* `PROPERTIES_SECTION_ID`, `STORIES_SECTION_ID`) claims — and so replaces —
|
|
125
|
+
* that block; any other id is a section of its own. Ids are a contract: the
|
|
126
|
+
* compact card persists the active tab by id.
|
|
127
|
+
*/
|
|
128
|
+
readonly id: string;
|
|
129
|
+
/** Section title — the stacked header, and the compact card's tab tooltip. */
|
|
130
|
+
readonly title: string;
|
|
131
|
+
/** Section icon — the compact card's tab glyph, or a resolver of one
|
|
132
|
+
* ({@link InspectorSectionIcon}). */
|
|
133
|
+
readonly icon: InspectorSectionIcon;
|
|
134
|
+
/** The rail GROUP this section belongs to, where the Properties
|
|
135
|
+
* presentation draws separators between groups — Blender's
|
|
136
|
+
* `BCONTEXT_SEPARATOR` (`space_buttons.cc:201-255`). See
|
|
137
|
+
* `InspectionSection.railGroup`. */
|
|
138
|
+
readonly railGroup?: string | undefined;
|
|
139
|
+
/** This is the tab the Properties rail OPENS ON before a person has chosen
|
|
140
|
+
* one for the subject. See `InspectionSection.railDefault`. */
|
|
141
|
+
readonly railDefault?: boolean | undefined;
|
|
142
|
+
/** Display order on `InspectionSection.order`'s scale
|
|
143
|
+
* (`CONTRIBUTED_SECTION_ORDER` unless this section belongs elsewhere). */
|
|
144
|
+
readonly order: number;
|
|
145
|
+
/** The section's body: an opaque React block the model does not model. */
|
|
146
|
+
readonly Section: ComponentType<InspectorSectionProps>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** One registration: a single identified section, or a producer of them. */
|
|
150
|
+
export type InspectorSectionContribution = InspectorSectionRegistration | InspectorSectionsProducer;
|
|
151
|
+
|
|
152
|
+
/** Whether this registration produces its sections from the node. */
|
|
153
|
+
export function isSectionsProducer(
|
|
154
|
+
contribution: InspectorSectionContribution,
|
|
155
|
+
): contribution is InspectorSectionsProducer {
|
|
156
|
+
return 'sections' in contribution;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const registrations: InspectorSectionContribution[] = [];
|
|
160
|
+
|
|
161
|
+
// --- Change notification (W3) --------------- First-party registrations all
|
|
162
|
+
// happen at import time (main.tsx side effects), before React ever renders —
|
|
163
|
+
// nothing needed to observe them. W3's project inspector TOOLS register
|
|
164
|
+
// asynchronously (folder scan) and re-register on HMR, while a selection may
|
|
165
|
+
// already be showing — so the one inspector shell subscribes here
|
|
166
|
+
// (`useSyncExternalStore`-shaped, mirroring `tool-loader.ts`'s registry
|
|
167
|
+
// store) and re-renders on any (un)registration.
|
|
168
|
+
let _version = 0;
|
|
169
|
+
const _listeners = new Set<() => void>();
|
|
170
|
+
|
|
171
|
+
function notifyRegistryChanged(): void {
|
|
172
|
+
_version++;
|
|
173
|
+
for (const fn of _listeners) fn();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Subscribe to (un)registrations. Returns an unsubscribe function. */
|
|
177
|
+
export function subscribeInspectorSectionRegistry(fn: () => void): () => void {
|
|
178
|
+
_listeners.add(fn);
|
|
179
|
+
return () => {
|
|
180
|
+
_listeners.delete(fn);
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/** Monotonic change counter — the `getSnapshot` for `useSyncExternalStore`. */
|
|
185
|
+
export function inspectorSectionRegistryVersion(): number {
|
|
186
|
+
return _version;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Register a section contribution. `match` decides whether this contribution
|
|
191
|
+
* applies to a given selection (or the no-selection state); `Section` renders
|
|
192
|
+
* when it does. Returns an unregister function.
|
|
193
|
+
*/
|
|
194
|
+
export function registerInspectorSections(reg: InspectorSectionContribution): () => void {
|
|
195
|
+
registrations.push(reg);
|
|
196
|
+
notifyRegistryChanged();
|
|
197
|
+
return () => {
|
|
198
|
+
const idx = registrations.indexOf(reg);
|
|
199
|
+
if (idx >= 0) {
|
|
200
|
+
registrations.splice(idx, 1);
|
|
201
|
+
notifyRegistryChanged();
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Every contribution whose `match` applies to `node`/`adapter`, in registration
|
|
207
|
+
* order. `context` names the empty-state subject being composed; omitting it
|
|
208
|
+
* means there is none (a selected-node composition). */
|
|
209
|
+
export function matchedInspectorSections(
|
|
210
|
+
node: EditorNode | null,
|
|
211
|
+
adapter: AuthoringAdapter,
|
|
212
|
+
context: InspectorSectionMatchContext = NO_NULL_SUBJECT,
|
|
213
|
+
): InspectorSectionContribution[] {
|
|
214
|
+
return registrations.filter((r) => r.match(node, adapter, context));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Test-only reset (mirrors `__resetHierarchyMenuRegistryForTest`). */
|
|
218
|
+
export function __resetInspectorSectionRegistryForTest(): void {
|
|
219
|
+
registrations.length = 0;
|
|
220
|
+
notifyRegistryChanged();
|
|
221
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "enter the component".
|
|
3
|
+
*
|
|
4
|
+
* An instance row's two source destinations, and the sentences the editor says
|
|
5
|
+
* about them. Kept pure and adapter-free so the applicability mapping and the
|
|
6
|
+
* fallback wording are unit-testable without a DOM, a live source tree, or a
|
|
7
|
+
* mounted design session — the wiring that knows about adapters lives in
|
|
8
|
+
* `authoring/instance-source-menu.ts`.
|
|
9
|
+
*
|
|
10
|
+
* TWO DESTINATIONS, NOT ONE. Both come from the OID index, but from DIFFERENT
|
|
11
|
+
* entries of it, and conflating them is the mistake this module exists to
|
|
12
|
+
* prevent:
|
|
13
|
+
*
|
|
14
|
+
* - **callsite** — where the instance is USED (`<Enemy position={…} />` in the
|
|
15
|
+
* world file). This is `sourceLocation(id)`, because a component boundary's
|
|
16
|
+
* node id resolves through `userData.authoringInstance`, which the oid
|
|
17
|
+
* transform propagates INTO the component from its callsite.
|
|
18
|
+
* - **definition** — where the component is WRITTEN (the root `<group>` inside
|
|
19
|
+
* `Enemy.tsx`). That is the boundary object's OWN `userData.oid`, stamped by
|
|
20
|
+
* the same transform in the file the element literally appears in.
|
|
21
|
+
*
|
|
22
|
+
* WHY "OPEN" COPIES. There is no code-editing surface in the editor workspace
|
|
23
|
+
* the dev server exposes no launch-editor route (`/__editor/reveal` opens a
|
|
24
|
+
* FILE MANAGER at a path, with no line and no caller), and `launch-editor` is
|
|
25
|
+
* not in the dependency tree — adding a dependency for this was explicitly out
|
|
26
|
+
* of scope. So "open" degrades to copying the `file:line` locator and SAYING
|
|
27
|
+
* so, which is the same honest degradation `@vgai/dom/react-inspector-section.tsx`'s
|
|
28
|
+
* `SourceLocationRow` already ships for the identical problem. Never a silent
|
|
29
|
+
* no-op.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** The subset of an OID index entry these actions need (structurally satisfied
|
|
33
|
+
* by `OidEntry` without importing the ui-source module here). */
|
|
34
|
+
export interface SourceRef {
|
|
35
|
+
readonly file: string;
|
|
36
|
+
readonly line: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Which of an instance row's two source destinations an action addresses. */
|
|
40
|
+
export type InstanceSourceTarget = 'callsite' | 'definition';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The minimal adapter surface an instance-source action reads. Structurally
|
|
44
|
+
* satisfied by `R3fSourceAuthoringAdapter` (which owns both methods) and by
|
|
45
|
+
* any adapter that offers only `sourceLocation` — the definition item simply
|
|
46
|
+
* never applies there, which is the honest answer rather than a fabricated one.
|
|
47
|
+
*/
|
|
48
|
+
export interface InstanceSourceLocator {
|
|
49
|
+
readonly sourceLocation?: ((id: string) => SourceRef | undefined) | undefined;
|
|
50
|
+
readonly definitionLocation?: ((id: string) => SourceRef | undefined) | undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Menu capitalization follows the panel's existing Title Case idiom
|
|
54
|
+
* (`Rename`, `Duplicate`, `Group Selection`, `Select Parent`). */
|
|
55
|
+
export const INSTANCE_SOURCE_LABELS: Readonly<Record<InstanceSourceTarget, string>> = {
|
|
56
|
+
callsite: 'Go to Callsite',
|
|
57
|
+
definition: 'Open Component Source',
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/** Probe order — the menu lists the callsite first (it is the row's own line of
|
|
61
|
+
* source; the definition is one hop further away). */
|
|
62
|
+
const TARGETS: readonly InstanceSourceTarget[] = ['callsite', 'definition'];
|
|
63
|
+
|
|
64
|
+
/** `src/world.tsx:42` — the exact text an action copies, and the exact text the
|
|
65
|
+
* hint then quotes back. One formatter so the two can never disagree. */
|
|
66
|
+
export function formatSourceRef(ref: SourceRef): string {
|
|
67
|
+
return `${ref.file}:${ref.line}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Resolve one destination, or `null`. `null` covers every honest unavailability
|
|
72
|
+
* in one value: the adapter has no such accessor, the id is unknown to it, or
|
|
73
|
+
* the OID index has not landed / no longer contains that entry.
|
|
74
|
+
*/
|
|
75
|
+
export function locateInstanceSource(
|
|
76
|
+
locator: InstanceSourceLocator | null | undefined,
|
|
77
|
+
id: string,
|
|
78
|
+
target: InstanceSourceTarget,
|
|
79
|
+
): SourceRef | null {
|
|
80
|
+
if (!locator) return null;
|
|
81
|
+
const resolve = target === 'callsite' ? locator.sourceLocation : locator.definitionLocation;
|
|
82
|
+
return resolve?.call(locator, id) ?? null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* H3 applicability: which items a row earns. A row must BOTH be a component
|
|
87
|
+
* instance (`role: 'component'` — the same predicate H1's row identity uses)
|
|
88
|
+
* and have the destination actually resolve. A row with neither destination
|
|
89
|
+
* gets neither item; nothing is ever rendered disabled here, because the
|
|
90
|
+
* registry's items have no disabled state (`getHierarchyMenuItems` returns
|
|
91
|
+
* label/action/color only) and the panel's own idiom is to omit an item whose
|
|
92
|
+
* SUBJECT is absent, reserving disabled-with-reason for a present subject the
|
|
93
|
+
* adapter refuses.
|
|
94
|
+
*/
|
|
95
|
+
export function instanceSourceTargets(
|
|
96
|
+
node: { readonly role?: string | undefined } | null | undefined,
|
|
97
|
+
locator: InstanceSourceLocator | null | undefined,
|
|
98
|
+
id: string,
|
|
99
|
+
): InstanceSourceTarget[] {
|
|
100
|
+
if (node?.role !== 'component') return [];
|
|
101
|
+
return TARGETS.filter((target) => locateInstanceSource(locator, id, target) !== null);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ------------------------------------------------------------------ sentences
|
|
105
|
+
|
|
106
|
+
const SUBJECT: Readonly<Record<InstanceSourceTarget, string>> = {
|
|
107
|
+
callsite: 'callsite',
|
|
108
|
+
definition: 'component source',
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/** What was copied, verbatim, plus why that is all the editor can do. */
|
|
112
|
+
export function copiedSourceHint(target: InstanceSourceTarget, ref: SourceRef): string {
|
|
113
|
+
return (
|
|
114
|
+
`Copied the ${SUBJECT[target]} ${formatSourceRef(ref)} to the clipboard — ` +
|
|
115
|
+
'the editor has no code surface to open it in.'
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** The destination resolved when the menu was built and is gone by click time
|
|
120
|
+
* (a source edit or an HMR remount between the two). */
|
|
121
|
+
export function missingSourceHint(target: InstanceSourceTarget): string {
|
|
122
|
+
return `This row's ${SUBJECT[target]} is not in the source index — there is nothing to open.`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** The clipboard refused or is unavailable (insecure context, denied
|
|
126
|
+
* permission). The locator still travels in the sentence, so the action is
|
|
127
|
+
* never a dead end. */
|
|
128
|
+
export function clipboardRefusedHint(target: InstanceSourceTarget, ref: SourceRef): string {
|
|
129
|
+
return `Could not write to the clipboard. The ${SUBJECT[target]} is ${formatSourceRef(ref)}.`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ------------------------------------------------------------------ the action
|
|
133
|
+
|
|
134
|
+
/** Injected in tests; production uses the real clipboard. */
|
|
135
|
+
export type ClipboardWriter = (text: string) => Promise<void>;
|
|
136
|
+
|
|
137
|
+
const systemClipboard: ClipboardWriter = async (text) => {
|
|
138
|
+
const clipboard = navigator.clipboard;
|
|
139
|
+
if (!clipboard) throw new Error('no clipboard');
|
|
140
|
+
await clipboard.writeText(text);
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Run one instance-source action end to end and return the sentence it should
|
|
145
|
+
* say — ALWAYS a sentence, never silence, on every path (copied / index no
|
|
146
|
+
* longer has it / clipboard refused). The caller shows it; returning it instead
|
|
147
|
+
* of raising it keeps this function testable without the hint module's timers.
|
|
148
|
+
*/
|
|
149
|
+
export async function runInstanceSourceAction(
|
|
150
|
+
locator: InstanceSourceLocator | null | undefined,
|
|
151
|
+
id: string,
|
|
152
|
+
target: InstanceSourceTarget,
|
|
153
|
+
writeText: ClipboardWriter = systemClipboard,
|
|
154
|
+
): Promise<string> {
|
|
155
|
+
const ref = locateInstanceSource(locator, id, target);
|
|
156
|
+
if (!ref) return missingSourceHint(target);
|
|
157
|
+
try {
|
|
158
|
+
await writeText(formatSourceRef(ref));
|
|
159
|
+
} catch {
|
|
160
|
+
return clipboardRefusedHint(target, ref);
|
|
161
|
+
}
|
|
162
|
+
return copiedSourceHint(target, ref);
|
|
163
|
+
}
|