@vgai/editor 0.2.0 → 0.4.0-canary.20260715.1
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/README.md +24 -0
- package/dist/assets/axe-CyiTVRi6.js +30 -0
- package/dist/assets/browserAll-fGZ_P1P8.js +1 -0
- package/dist/assets/create-runtime-BzSHBTYw.js +1 -0
- package/dist/assets/game-DQ7YHNS8.js +1 -0
- package/dist/assets/game-DX6Obomf.js +1 -0
- package/dist/assets/game-DoUJj8vY.js +1 -0
- package/dist/assets/{game-xsOho_wg.js → game-HqybI_X7.js} +3 -3
- package/dist/assets/game-NUAnyPkS.js +1 -0
- package/dist/assets/game-ck_dNIE6.js +1 -0
- package/dist/assets/{game-pt_1lQLv.js → game-hIf5LD4E.js} +1 -1
- package/dist/assets/game-loop-o2CcBMFY.js +1 -0
- package/dist/assets/{game-source-CvidN7AB.js → game-source-C8HM7gbP.js} +1 -1
- package/dist/assets/{game-BI111o5f.js → game-uR_lv3Mp.js} +3 -3
- package/dist/assets/index-B-HA1uu3.js +15412 -0
- package/dist/assets/{index-Bp5cecD6.js → index-CSBAZwMx.js} +2 -2
- package/dist/assets/{index-DL7RcQ0n.js → index-CoSRCKPS.js} +1 -1
- package/dist/assets/{index-Cs8xwv3e.js → index-D93bBuUl.js} +1 -1
- package/dist/assets/index-bu01fqch.css +1 -0
- package/dist/assets/ingest-siblings-CCkkE2h7.js +1 -0
- package/dist/assets/mount-manifest-B2ECssU2.js +1 -0
- package/dist/assets/react-18-Bmj05S8J.js +1 -0
- package/dist/assets/webworkerAll-BC6gMOLZ.js +1 -0
- package/dist/assets/world-documents-DXPcAEA0.js +1 -0
- package/dist/index.html +15 -13
- package/dist/ingest/racing-game/vgai.game.json +5 -4
- package/dist/ingest/simcity/vgai.game.json +5 -4
- package/dist/ingest/tanks/vgai.game.json +5 -4
- package/dist/project-scripts.bundle.js +3917 -0
- package/dist/scenes/untitled.vscn.json +2 -0
- package/dist-server/packaged.mjs +7718 -3436
- package/package.json +31 -4
- package/scripts/probe-reporter.ts +349 -0
- package/scripts/run-probe.ts +2260 -0
- package/server/asset-catalog-audit.ts +268 -0
- package/server/asset-catalog-v2.ts +146 -0
- package/server/asset-library-routes.ts +276 -58
- package/server/canonical-path.ts +1 -1
- package/server/dev.ts +148 -44
- package/server/editor-server.ts +888 -61
- package/server/editor-sse.ts +115 -4
- package/server/harness-chat-service.ts +796 -0
- package/server/local-asset-catalog.ts +157 -22
- package/server/packaged.ts +71 -21
- package/server/process-shutdown.ts +136 -0
- package/server/prod.ts +9 -6
- package/server/project-hmr-files.ts +41 -0
- package/server/project-operations.ts +343 -0
- package/server/project-optimize-deps-entries.ts +4 -4
- package/server/project-output-writer.ts +156 -0
- package/server/project-validation.ts +140 -0
- package/server/project-view.ts +8 -50
- package/server/server-utils.ts +75 -10
- package/server/session-registry.ts +12 -0
- package/src/EditorContext.tsx +107 -3
- package/src/action-registry.ts +115 -17
- package/src/adapter-resolver.ts +213 -478
- package/src/asset-events.ts +64 -1
- package/src/asset-preview.ts +906 -0
- package/src/asset-selection.ts +121 -0
- package/src/asset-workflow/asset-capabilities.ts +259 -0
- package/src/asset-workflow/asset-editor-errors.ts +46 -0
- package/src/asset-workflow/asset-import-pipeline.ts +176 -0
- package/src/asset-workflow/asset-library-query.ts +107 -0
- package/src/asset-workflow/asset-types.ts +192 -0
- package/src/asset-workflow/asset-workflow-quality.ts +65 -0
- package/src/asset-workflow/import-contract.ts +113 -0
- package/src/asset-workflow/model-conversion.ts +126 -0
- package/src/asset-workflow/model-inspection.ts +185 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +153 -0
- package/src/asset-workflow/project-asset-operations.ts +119 -0
- package/src/asset-workflow/thumbnail-system.ts +172 -0
- package/src/authoring/active-systems.ts +15 -0
- package/src/authoring/boundary-authoring-adapter.ts +16 -5
- package/src/authoring/composite-authoring-adapter.ts +305 -124
- package/src/authoring/design-time-layers.ts +300 -117
- package/src/authoring/edit-mode-authoring.ts +278 -293
- package/src/authoring/embed-only-adapter.ts +4 -2
- package/src/authoring/first-party-hierarchy-menu.ts +7 -2
- package/src/authoring/first-party-inspector/AddSectionMenu.tsx +5 -12
- package/src/authoring/first-party-inspector/EnvironmentSection.tsx +53 -126
- package/src/authoring/first-party-inspector/HeaderSection.tsx +54 -65
- package/src/authoring/first-party-inspector/is-first-party-selection.ts +30 -11
- package/src/authoring/first-party-inspector/register.tsx +13 -2
- package/src/authoring/ingest-authoring-adapter.ts +142 -45
- package/src/authoring/mount-failure-report.ts +5 -5
- package/src/authoring/provenance.ts +41 -0
- package/src/authoring/react-dom-authoring-adapter.ts +92 -92
- package/src/authoring/react-inspector-section.tsx +489 -51
- package/src/authoring/react-world-authoring-adapter.ts +541 -306
- package/src/authoring/story-overlay.ts +1 -1
- package/src/authoring/story-types.ts +11 -0
- package/src/authoring/vgai-scene-authoring-adapter.ts +54 -25
- package/src/authoring/viewport-tool-context.ts +78 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +186 -0
- package/src/authoring/world-pan-state.ts +33 -17
- package/src/authoring/world-session-state.ts +1 -1
- package/src/authoring/world2d-authoring-adapter.ts +109 -52
- package/src/availability-tick.ts +56 -0
- package/src/browser-play-entry.ts +5 -5
- package/src/browser-project-scripts.ts +1 -0
- package/src/build-identity.ts +15 -0
- package/src/command-listener.ts +893 -19
- package/src/components/AlignToolbar.tsx +74 -63
- package/src/components/AppRoot.tsx +193 -26
- package/src/components/ApplicationMenus.tsx +272 -0
- package/src/components/AssetBrowser.tsx +1236 -296
- package/src/components/AssetEditorShell.tsx +141 -0
- package/src/components/AssetImportDetails.tsx +218 -0
- package/src/components/AssetLibraryPanel.tsx +14 -0
- package/src/components/CameraInfo.tsx +11 -20
- package/src/components/CenterDocuments.tsx +585 -0
- package/src/components/CommandPalette.tsx +75 -30
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +57 -112
- package/src/components/DebugConsolePanel.tsx +461 -0
- package/src/components/DebuggerPanel.tsx +165 -0
- package/src/components/DefaultEditorLayout.tsx +167 -231
- package/src/components/GameHierarchy.tsx +873 -290
- package/src/components/GamePerformanceOverlay.tsx +46 -0
- package/src/components/HarnessChatPanel.tsx +2352 -0
- package/src/components/HistoryPanel.tsx +226 -0
- package/src/components/Inspector.tsx +153 -99
- package/src/components/InspectorToolSection.tsx +6 -4
- package/src/components/MountFailureBanner.tsx +31 -48
- package/src/components/NetworkSection.tsx +25 -14
- package/src/components/OnlineAssetBrowser.tsx +1116 -344
- package/src/components/OverlayReportBanner.tsx +38 -64
- package/src/components/PerformancePanel.tsx +206 -0
- package/src/components/PlayBar.tsx +93 -263
- package/src/components/PrefabSaveDialog.tsx +55 -127
- package/src/components/ProjectHeader.css +60 -0
- package/src/components/ProjectHeader.tsx +170 -105
- package/src/components/ProjectScreen.tsx +246 -184
- package/src/components/ReactCanvasControls.tsx +185 -0
- package/src/components/ResolutionPicker.tsx +85 -0
- package/src/components/RootActivateDialog.tsx +39 -68
- package/src/components/SaveDialog.tsx +55 -127
- package/src/components/SaveStatus.tsx +11 -29
- package/src/components/StartupLoadingScreen.tsx +96 -0
- package/src/components/StateWatchPanel.tsx +302 -0
- package/src/components/StatsOverlay.tsx +12 -5
- package/src/components/StatusBar.tsx +64 -0
- package/src/components/ThemeManagerDialog.css +89 -0
- package/src/components/ThemeManagerDialog.tsx +371 -0
- package/src/components/ToolHost.tsx +26 -15
- package/src/components/Toolbar.tsx +117 -214
- package/src/components/VgaiVoxelLogo.tsx +89 -0
- package/src/components/ViewportOverlay.tsx +97 -172
- package/src/components/ViewportPanel.tsx +130 -31
- package/src/components/WorkspaceDock.tsx +891 -0
- package/src/components/WorldSelectionOverlay.tsx +51 -63
- package/src/components/WorldTextEditor.tsx +9 -5
- package/src/components/asset-documents.tsx +390 -0
- package/src/components/asset-editor-persistence.ts +44 -0
- package/src/components/asset-selection-section.tsx +338 -0
- package/src/components/asset-viewers/AudioViewer.tsx +73 -21
- package/src/components/asset-viewers/GenericJsonViewer.tsx +26 -11
- package/src/components/asset-viewers/ImageViewer.tsx +43 -11
- package/src/components/asset-viewers/InputMapViewer.tsx +512 -134
- package/src/components/asset-viewers/MaterialAssetEditor.tsx +540 -0
- package/src/components/asset-viewers/ModelViewer.tsx +805 -121
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +177 -60
- package/src/components/asset-viewers/SourceAssetViewer.tsx +121 -0
- package/src/components/asset-workflow.css +620 -0
- package/src/components/build-documents.tsx +696 -0
- package/src/components/core-utilities.tsx +75 -0
- package/src/components/data-documents.tsx +364 -0
- package/src/components/{DataPanel.tsx → data-editor.tsx} +138 -288
- package/src/components/debugger-panel-state.ts +57 -0
- package/src/components/inspector-widgets/AlignmentGrid.tsx +8 -14
- package/src/components/inspector-widgets/BorderEditor.tsx +41 -33
- package/src/components/inspector-widgets/ColorPicker.tsx +39 -39
- package/src/components/inspector-widgets/FontPicker.tsx +13 -21
- package/src/components/inspector-widgets/GradientEditor.tsx +11 -19
- package/src/components/inspector-widgets/ScrubbableInput.tsx +6 -3
- package/src/components/inspector-widgets/ShadowEditor.tsx +20 -33
- package/src/components/inspector-widgets/shared.tsx +90 -49
- package/src/components/inspectors/AnimationSection.tsx +39 -40
- package/src/components/inspectors/AudioSection.tsx +28 -39
- package/src/components/inspectors/BoneAttachmentSection.tsx +19 -24
- package/src/components/inspectors/CameraSection.tsx +14 -23
- package/src/components/inspectors/ComponentsSection.tsx +39 -43
- package/src/components/inspectors/JointsSection.tsx +34 -43
- package/src/components/inspectors/LightSection.tsx +90 -35
- package/src/components/inspectors/MaterialSection.tsx +137 -174
- package/src/components/inspectors/MeshSection.tsx +9 -17
- package/src/components/inspectors/NavigationSection.tsx +8 -15
- package/src/components/inspectors/ParticleSection.tsx +91 -76
- package/src/components/inspectors/PhysicsSection.tsx +42 -46
- package/src/components/inspectors/PostProcessingSection.tsx +28 -36
- package/src/components/inspectors/RenderingSection.tsx +12 -20
- package/src/components/inspectors/ShadowSection.tsx +7 -8
- package/src/components/inspectors/SplineSection.tsx +31 -42
- package/src/components/inspectors/TransformSection.tsx +14 -22
- package/src/components/patterns/Dialog.tsx +95 -0
- package/src/components/patterns/Fields.tsx +44 -0
- package/src/components/patterns/List.tsx +25 -0
- package/src/components/patterns/StateSurface.tsx +40 -0
- package/src/components/patterns/Surfaces.tsx +115 -0
- package/src/components/patterns/Tabs.tsx +80 -0
- package/src/components/patterns/Toolbar.tsx +51 -0
- package/src/components/patterns/Tree.tsx +72 -0
- package/src/components/primitives/Button.tsx +46 -0
- package/src/components/primitives/ColorInput.tsx +11 -47
- package/src/components/primitives/EditorIcon.tsx +99 -0
- package/src/components/primitives/FormControls.tsx +71 -0
- package/src/components/primitives/JsonInput.tsx +15 -2
- package/src/components/primitives/Layout.tsx +100 -0
- package/src/components/primitives/Menu.tsx +105 -0
- package/src/components/primitives/NumberInput.tsx +8 -35
- package/src/components/primitives/Panel.tsx +49 -44
- package/src/components/primitives/SectionHeader.tsx +10 -28
- package/src/components/primitives/Text.tsx +46 -0
- package/src/components/primitives/Tooltip.tsx +20 -12
- package/src/components/primitives/Vec3Input.tsx +3 -0
- package/src/components/primitives/banner-tones.ts +33 -0
- package/src/components/primitives/editor-icons.ts +102 -0
- package/src/components/primitives/panel-header-styles.ts +30 -0
- package/src/components/project-operation-documents.tsx +226 -0
- package/src/components/status-contributions.tsx +175 -0
- package/src/components/story-documents-register.ts +15 -0
- package/src/components/story-documents.tsx +1185 -0
- package/src/components/tool-documents.tsx +110 -0
- package/src/components/workspace-dock.css +293 -0
- package/src/components/workspace-history.ts +33 -0
- package/src/components/world-documents.tsx +145 -0
- package/src/components/xstate-documents.tsx +209 -0
- package/src/composite-screenshot.ts +248 -0
- package/src/design-system/index.ts +70 -0
- package/src/design-system-stories/Foundation.stories.tsx +183 -0
- package/src/design-system-stories/Patterns.stories.tsx +251 -0
- package/src/design-system-stories/Workspace.stories.tsx +538 -0
- package/src/doctor/report.ts +57 -13
- package/src/editor-api.ts +295 -31
- package/src/editor-compatibility.ts +200 -0
- package/src/editor-console.ts +35 -17
- package/src/editor-hotkeys.ts +85 -33
- package/src/editor-store.ts +538 -233
- package/src/editor-viewport.ts +160 -34
- package/src/entity-factory.ts +14 -3
- package/src/gizmo-registry.ts +21 -5
- package/src/harness-chat-editor-context.ts +37 -0
- package/src/harness-chat-indicator.ts +68 -0
- package/src/harness-chat-layout.ts +53 -0
- package/src/harness-chat-lifecycle.ts +170 -0
- package/src/harness-chat-reconnect.ts +85 -0
- package/src/harness-chat-types.ts +409 -0
- package/src/hierarchy-drop.ts +50 -0
- package/src/hierarchy-expansion-state.ts +100 -0
- package/src/hierarchy-menu-registry.ts +1 -1
- package/src/hierarchy-projection.ts +76 -0
- package/src/history/editor-session.ts +21 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-service.ts +904 -0
- package/src/history/json-history-resource.ts +165 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +266 -0
- package/src/history/project-root-history-backends.ts +53 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +108 -0
- package/src/history/source-history-backend.ts +374 -0
- package/src/history/types.ts +100 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hosted-example.ts +12 -2
- package/src/hotkeys.ts +89 -18
- package/src/ingest/discovery-react.ts +9 -10
- package/src/ingest/discovery.ts +4 -4
- package/src/ingest/discovery2d.ts +5 -5
- package/src/ingest/games/bloom-composer/vgai.game.json +3 -3
- package/src/ingest/games/embed-bundle/vgai.game.json +3 -3
- package/src/ingest/games/games-fps/vgai.game.json +3 -3
- package/src/ingest/games/iframe-reachable/vgai.game.json +3 -3
- package/src/ingest/games/interactive-cubes/vgai.game.json +3 -3
- package/src/ingest/games/mismatched-three/vgai.game.json +3 -3
- package/src/ingest/games/own-three-bundled/vgai.game.json +3 -3
- package/src/ingest/games/pointerlock-maze/vgai.game.json +7 -4
- package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +3 -3
- package/src/ingest/games-2d/bunnymark/vgai.game.json +3 -3
- package/src/ingest/games-2d/flappy/vgai.game.json +3 -3
- package/src/ingest/games-2d/flappy-pixi/vgai.game.json +3 -3
- package/src/ingest/games-2d/puzzling-potions/vgai.game.json +3 -3
- package/src/ingest/games-2d/tilemap-camera/vgai.game.json +3 -3
- package/src/ingest/games-react/react-rpg/vgai.game.json +3 -3
- package/src/ingest/types.ts +1 -1
- package/src/ingest-mode.ts +47 -52
- package/src/ingest-siblings.ts +23 -33
- package/src/initial-scene.ts +1 -2
- package/src/main.tsx +16 -8
- package/src/manifest-project.ts +10 -12
- package/src/model-thumbnail.ts +261 -26
- package/src/module-mode.ts +44 -50
- package/src/play-log-events.ts +26 -0
- package/src/play-mode.ts +495 -401
- package/src/play-scene-adoption.ts +23 -0
- package/src/playground/main.ts +68 -24
- package/src/playwright-shim.ts +473 -0
- package/src/project-manager.ts +90 -10
- package/src/project-operations.ts +112 -0
- package/src/project-story-discovery.ts +25 -0
- package/src/project-tool-discovery.ts +43 -0
- package/src/scene-serializer.ts +0 -6
- package/src/scene-sync.ts +7 -2
- package/src/script-loader.ts +3 -3
- package/src/skeleton-helper.ts +57 -0
- package/src/storage/seed.ts +68 -8
- package/src/stories/StoryPreviewMount.tsx +265 -0
- package/src/stories/action-stories.fixture.tsx +44 -0
- package/src/stories/button-stories.fixture.tsx +50 -0
- package/src/stories/compose-project-stories.ts +182 -0
- package/src/stories/loader-stories.fixture.tsx +53 -0
- package/src/stories/story-discovery.ts +130 -0
- package/src/stories/story-registry.ts +146 -0
- package/src/theme-css.ts +1049 -0
- package/src/theme-library.ts +238 -0
- package/src/theme-preference.ts +130 -0
- package/src/theme.ts +527 -0
- package/src/tool-loader.ts +80 -24
- package/src/ui-source/inspect.ts +27 -4
- package/src/ui-source/source-write-backend.ts +83 -22
- package/src/widgets/index.ts +9 -18
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-dock-controller.ts +64 -0
- package/src/workspace-document-ids.ts +5 -0
- package/src/workspace-document-registry.ts +367 -0
- package/src/workspace-state-persistence.ts +455 -0
- package/src/workspace-status-registry.ts +110 -0
- package/src/workspace-utility-commands.ts +49 -0
- package/src/workspace-utility-registry.ts +161 -0
- package/src/world-document-routing.ts +16 -0
- package/src/xstate-inspect/XStateMachineInspector.tsx +544 -0
- package/src/xstate-inspect/character-animation-machine.fixture.ts +74 -0
- package/src/xstate-inspect/use-live-actor-state.ts +39 -0
- package/src/xstate-inspect/xstate-graph.ts +265 -0
- package/src/xstate-inspect/xstate-layout.ts +76 -0
- package/src/z-index.ts +26 -0
- package/template/.claude/skills/editor/SKILL.md +129 -90
- package/template/AGENTS.md +1110 -0
- package/template/CLAUDE.md +1 -512
- package/template/IDIOMS.md +50 -0
- package/template/check-idioms.ts +706 -0
- package/template/manifest-entry-modules-plugin.ts +53 -0
- package/template/package.json +13 -4
- package/template/public/scenes/default.scn2d.json +6 -0
- package/template/public/scenes/default.vscn.json +7 -1
- package/template/public/scenes/untitled.vscn.json +10 -0
- package/template/scripts/playtest.ts +40 -0
- package/template/server/loopback.ts +75 -0
- package/template/server/rooms/arena-room.ts +69 -1
- package/template/server/rooms/game-room.ts +68 -1
- package/template/src/data/README.md +9 -4
- package/template/src/data/data-ref.ts +35 -0
- package/template/src/data/tuning.schema.ts +1 -1
- package/template/src/main.ts +41 -62
- package/template/src/manifest-entry-modules.d.ts +3 -0
- package/template/src/operations/README.md +88 -0
- package/template/src/runtime/pixi-adapter.ts +24 -0
- package/template/src/scripts/components/data-spinner.ts +43 -2
- package/template/src/scripts/components/spin-lap-math.ts +27 -0
- package/template/src/tools/README.md +5 -3
- package/template/src/tools/example.tool.tsx +13 -7
- package/template/src/ui/Button.stories.tsx +66 -0
- package/template/src/ui/RebindPanel.tsx +2 -6
- package/template/src/ui/game.tsx +17 -0
- package/template/tests/acceptance/example.spec.ts +64 -0
- package/template/tests/logic/example.test.ts +31 -0
- package/template/tests/logic/room.test.ts +100 -0
- package/template/tests/tsconfig.json +30 -0
- package/template/validate-manifest.ts +5 -5
- package/template/validate-scenes.ts +50 -18
- package/template/vgai.game.json +20 -13
- package/template/vite.config.ts +77 -16
- package/vite-plugin-ui-oid.ts +261 -17
- package/dist/assets/CCDIKSolver-Dz-ysxZF.js +0 -1
- package/dist/assets/SelectionBox-BXsv_6aH.js +0 -1
- package/dist/assets/browser-project-scripts-DOru4L1x.js +0 -2
- package/dist/assets/browserAll-CEkWYlFk.js +0 -1
- package/dist/assets/create-runtime-DYIWr3va.js +0 -1
- package/dist/assets/data-asset-Bb9sIM7i.js +0 -5
- package/dist/assets/game-8SDZPPgH.js +0 -1
- package/dist/assets/game-CevorxyV.js +0 -1
- package/dist/assets/game-Di7XlywD.js +0 -1
- package/dist/assets/game-DjnCaw8R.js +0 -1
- package/dist/assets/game-Q9A0aXSV.js +0 -1
- package/dist/assets/index-CPVV6pjw.js +0 -1
- package/dist/assets/index-CpOnYyeD.js +0 -213
- package/dist/assets/index-Dr8H_6Rl.js +0 -1
- package/dist/assets/index-_bCaipUk.js +0 -13650
- package/dist/assets/ingest-siblings-Dz8eEqrV.js +0 -1
- package/dist/assets/mount-manifest-Bhk0ohsl.js +0 -1
- package/dist/assets/scene-query-BivAHhJu.js +0 -1
- package/dist/assets/webworkerAll-BLrH0F6F.js +0 -1
- package/dist/assets/xstate-animation-binding-1NGLmw6y.js +0 -1
- package/dist/assets/xstate.esm-BgUD33nl.js +0 -3
- package/src/authoring/scene-ui-layer.ts +0 -485
- package/src/authoring/ui-authoring-adapter.ts +0 -325
- package/src/authoring/ui-hierarchy-menu.ts +0 -40
- package/src/authoring/ui-inspector-sections.tsx +0 -156
- package/src/authoring/undo-timeline.ts +0 -145
- package/src/components/BottomPanel.tsx +0 -326
- package/src/components/BuildPanel.tsx +0 -455
- package/src/components/FolderTree.tsx +0 -179
- package/src/components/RightPanel.tsx +0 -166
- package/src/components/WorldContextMenu.tsx +0 -257
- package/src/components/asset-viewers/AssetViewer.tsx +0 -38
- package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +0 -129
- package/src/scene-ui-mode/active-scene-ui.ts +0 -58
- package/src/scene-ui-mode/scene-ui-palette-panel.tsx +0 -152
- package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +0 -29
- package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +0 -74
- package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +0 -49
- package/src/scene-ui-mode/ui-prefab-io.ts +0 -76
- package/src/ui-editor/inspector.tsx +0 -563
- package/src/ui-editor/node-ops.ts +0 -266
- package/src/ui-editor/overlay.tsx +0 -380
- package/src/ui-editor/palette.tsx +0 -114
- package/src/ui-editor/react-store.ts +0 -78
- package/src/ui-editor/timeline-panel.tsx +0 -443
- package/src/ui-editor/ui-edit-store.ts +0 -552
- package/src/ui-editor/ui-prefab.ts +0 -95
- package/template/project.json +0 -9
- package/template/src/scripts/main.ts +0 -94
- package/template/src/ui/DefaultHud.tsx +0 -40
- package/template/src/ui/game-state.tsx +0 -37
- package/template/src/ui/mount-default-hud.tsx +0 -19
- package/template/src/ui/mount-ui.ts +0 -15
- package/vite-plugin-react-world-provider.ts +0 -81
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace DOCUMENT registry (W0, docs/EDITOR-WORKSPACE-SHELL-TODO.md §7/§7.1
|
|
3
|
+
* — the shell-contract slice of §9 W0). The missing central-document concept:
|
|
4
|
+
* every authored subject (Three scene, prefab, Game preview, React story,
|
|
5
|
+
* asset preview, data asset, Build Profiles — the real
|
|
6
|
+
* first-party implementers §7.1 names) becomes an OPEN DOCUMENT here, and
|
|
7
|
+
* the center workspace (W1) renders the open set as tabs. Live-observation
|
|
8
|
+
* instruments such as Profiler, State Watch, Network, and XState stay in the
|
|
9
|
+
* Debugger so they never replace the subject they observe.
|
|
10
|
+
*
|
|
11
|
+
* `components/WorkspaceDock.tsx` consumes this registry and maps open
|
|
12
|
+
* subjects to Dockview panels with always-mounted content.
|
|
13
|
+
* `components/CenterDocuments.tsx` opens the first two
|
|
14
|
+
* document implementers (active Three scene, Game preview) and bridges
|
|
15
|
+
* open/activate to the store's `activeViewportTab` (the T6.3 input-gate
|
|
16
|
+
* predicate). W2/W3 migrate the remaining surfaces listed in
|
|
17
|
+
* docs/workspace-shell/W0-INVENTORY.md.
|
|
18
|
+
*
|
|
19
|
+
* Idioms mirror `inspector-section-registry.ts` one-for-one: module-scope
|
|
20
|
+
* state, `useSyncExternalStore`-shaped subscribe + monotonic version,
|
|
21
|
+
* `__resetForTest`, pure-logic headless tests (no jsdom — `Content` /
|
|
22
|
+
* `Toolbar` are never rendered by the registry itself). The shell must not
|
|
23
|
+
* switch on implementation technology for placement (§7.3 / CLAUDE.md):
|
|
24
|
+
* `kind` here is SEMANTIC metadata (what the document is to the author, per
|
|
25
|
+
* §8's naming rules), never a technology dispatch key — kind-specific
|
|
26
|
+
* behavior lives inside each descriptor's own `Content`/`Toolbar`.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import type { AuthoringAdapter } from '@engine/adapter';
|
|
30
|
+
import type { ComponentType } from 'react';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Semantic document kinds — §7.1 "title, semantic kind, and optional
|
|
34
|
+
* source/provenance metadata". One entry per real first-party implementer
|
|
35
|
+
* §7.1 enumerates, plus `'tool'` for project-authored document-placement
|
|
36
|
+
* tools (§7.2). Extend the union when a new document kind genuinely ships;
|
|
37
|
+
* the registry itself never branches on it.
|
|
38
|
+
*/
|
|
39
|
+
export type WorkspaceDocumentKind =
|
|
40
|
+
| 'scene' // active Three scene (center document named for the scene, §5)
|
|
41
|
+
| 'prefab' // isolated prefab editor (§5.1)
|
|
42
|
+
| 'game' // the live player-facing Game preview (§8)
|
|
43
|
+
| 'world' // one manifest root's isolated edit-time authoring surface
|
|
44
|
+
| 'story' // React CSF story document (§4.2)
|
|
45
|
+
| 'asset' // model/image/audio/input-map/data-file viewer or editor (§5.1)
|
|
46
|
+
| 'data' // data asset form/table document (§5)
|
|
47
|
+
| 'content-browser' // optional thumbnail-heavy browser (§5)
|
|
48
|
+
| 'build-profiles' // build configuration (§8: 'Build Profiles')
|
|
49
|
+
| 'operation' // project-local validated tooling operation
|
|
50
|
+
| 'tool'; // project-authored document-placement tool (§7.2)
|
|
51
|
+
|
|
52
|
+
/** Where a document came from — §7.1 "optional source/provenance metadata".
|
|
53
|
+
* All fields optional: a Game preview has none; a scene has a `sourcePath`;
|
|
54
|
+
* a live XState graph may have only an `origin`. */
|
|
55
|
+
export interface WorkspaceDocumentProvenance {
|
|
56
|
+
/** Project-relative source file (e.g. `scenes/Default.vscn.json`). */
|
|
57
|
+
readonly sourcePath?: string;
|
|
58
|
+
/** Owning adapter root id (D20 — `docs/AUTHORING-ROOT-PROJECTION-DESIGN.md`). */
|
|
59
|
+
readonly rootId?: string;
|
|
60
|
+
/** Free-form origin for non-file documents (e.g. a live machine id). */
|
|
61
|
+
readonly origin?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Props the W1 host will pass to a document's `Content`/`Toolbar`. */
|
|
65
|
+
export interface WorkspaceDocumentContentProps {
|
|
66
|
+
/** The open document's stable id (== its descriptor's `id`). */
|
|
67
|
+
readonly documentId: string;
|
|
68
|
+
/** Whether this document is the active center tab. Hosts keep inactive
|
|
69
|
+
* documents MOUNTED where lifecycle requires it (W1 proof bar) — content
|
|
70
|
+
* uses this to gate work, not to exist. */
|
|
71
|
+
readonly active: boolean;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** §7.1 "optional selection/Inspector context": what the Inspector should
|
|
75
|
+
* treat as selected while this document is active. Shape matches
|
|
76
|
+
* `inspector-section-registry.ts`'s `InspectorSectionProps` inputs. */
|
|
77
|
+
export interface WorkspaceDocumentSelection {
|
|
78
|
+
readonly adapter: AuthoringAdapter;
|
|
79
|
+
/** Selected node id; `null` for the document/environment state. */
|
|
80
|
+
readonly nodeId: string | null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The §7.1 document contract. Descriptors are definitions (immutable by
|
|
85
|
+
* convention); per-open-document RUNTIME state (dirty) lives on
|
|
86
|
+
* {@link OpenWorkspaceDocument} and is mutated through the registry.
|
|
87
|
+
*/
|
|
88
|
+
export interface WorkspaceDocumentDescriptor {
|
|
89
|
+
/** Stable identity scoped to project/session (§7.1) — dedupe key: opening
|
|
90
|
+
* an id that is already open activates the existing document. */
|
|
91
|
+
readonly id: string;
|
|
92
|
+
/** Source-owned display title (§8 — `Default.vscn`, `Playing`, never a
|
|
93
|
+
* technology bucket like `Viewport`). */
|
|
94
|
+
readonly title: string;
|
|
95
|
+
readonly kind: WorkspaceDocumentKind;
|
|
96
|
+
readonly provenance?: WorkspaceDocumentProvenance;
|
|
97
|
+
/** React content host (§7.1). Never rendered by the registry itself. */
|
|
98
|
+
readonly Content: ComponentType<WorkspaceDocumentContentProps>;
|
|
99
|
+
/** Optional document-local toolbar contribution (§7.1; §4.1 "Document tabs
|
|
100
|
+
* and their local toolbar occupy only the center workspace"). */
|
|
101
|
+
readonly Toolbar?: ComponentType<WorkspaceDocumentContentProps>;
|
|
102
|
+
/** `false` pins the document (Scene/Game in W1). Default `true`. */
|
|
103
|
+
readonly closeable?: boolean;
|
|
104
|
+
/** Optional read-only state (§7.1). */
|
|
105
|
+
readonly readOnly?: boolean;
|
|
106
|
+
/** Optional inspect-only state (§7.1) for read-only authored resources. */
|
|
107
|
+
readonly inspectOnly?: boolean;
|
|
108
|
+
/** Optional selection/Inspector context while this document is active. */
|
|
109
|
+
readonly selection?: () => WorkspaceDocumentSelection | null;
|
|
110
|
+
/** Called when this document becomes the active document. */
|
|
111
|
+
readonly onActivate?: (documentId: string) => void;
|
|
112
|
+
/** Called when this document stops being the active document. */
|
|
113
|
+
readonly onDeactivate?: (documentId: string) => void;
|
|
114
|
+
/** Called when this document is removed from the workspace (close /
|
|
115
|
+
* close-all) — release adapters, mounts, subscriptions here. */
|
|
116
|
+
readonly onDispose?: (documentId: string) => void;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** One open document: its immutable descriptor + registry-owned state. */
|
|
120
|
+
export interface OpenWorkspaceDocument {
|
|
121
|
+
readonly descriptor: WorkspaceDocumentDescriptor;
|
|
122
|
+
/** §7.1 optional dirty state — set via {@link setWorkspaceDocumentDirty}. */
|
|
123
|
+
readonly dirty: boolean;
|
|
124
|
+
/** Live display title — initialized from `descriptor.title`, updated via
|
|
125
|
+
* {@link setWorkspaceDocumentTitle}. Registry-owned RUNTIME state (like
|
|
126
|
+
* `dirty`), because a document's source-owned name can change while it is
|
|
127
|
+
* open (W1: the scene document tracks the active scene's §8 name — e.g.
|
|
128
|
+
* the async initial-scene load lands after the document is opened, and a
|
|
129
|
+
* root activation switches the active `.vscn` in place). */
|
|
130
|
+
readonly title: string;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** A mounted document editor's live save callback. `true` means the write
|
|
134
|
+
* completed; `false` means validation/persistence rejected it and the caller
|
|
135
|
+
* must keep the document open. */
|
|
136
|
+
export type WorkspaceDocumentSaveHandler = () => boolean | Promise<boolean>;
|
|
137
|
+
|
|
138
|
+
// --- Module-scope state (mirrors inspector-section-registry.ts) -----------
|
|
139
|
+
|
|
140
|
+
let _open: OpenWorkspaceDocument[] = [];
|
|
141
|
+
let _activeId: string | null = null;
|
|
142
|
+
let _version = 0;
|
|
143
|
+
const _listeners = new Set<() => void>();
|
|
144
|
+
/** Ids currently mid-close (between the neighbor `setActive` and the
|
|
145
|
+
* filter+`onDispose` below) — see {@link closeWorkspaceDocument}'s
|
|
146
|
+
* re-entrancy guard. */
|
|
147
|
+
const _closingIds = new Set<string>();
|
|
148
|
+
const _saveHandlers = new Map<string, WorkspaceDocumentSaveHandler>();
|
|
149
|
+
|
|
150
|
+
function notifyChanged(): void {
|
|
151
|
+
_version++;
|
|
152
|
+
for (const fn of _listeners) fn();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/** Subscribe to any open/activate/close/dirty change. Returns unsubscribe. */
|
|
156
|
+
export function subscribeWorkspaceDocuments(fn: () => void): () => void {
|
|
157
|
+
_listeners.add(fn);
|
|
158
|
+
return () => {
|
|
159
|
+
_listeners.delete(fn);
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Monotonic change counter — the `getSnapshot` for `useSyncExternalStore`. */
|
|
164
|
+
export function workspaceDocumentRegistryVersion(): number {
|
|
165
|
+
return _version;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** The open documents, in open order (stable reference between changes). */
|
|
169
|
+
export function openWorkspaceDocuments(): readonly OpenWorkspaceDocument[] {
|
|
170
|
+
return _open;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/** The active document's id, or `null` when no document is open. */
|
|
174
|
+
export function activeWorkspaceDocumentId(): string | null {
|
|
175
|
+
return _activeId;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** The active open document, or `null`. */
|
|
179
|
+
export function activeWorkspaceDocument(): OpenWorkspaceDocument | null {
|
|
180
|
+
return _open.find((d) => d.descriptor.id === _activeId) ?? null;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function setActive(nextId: string | null): void {
|
|
184
|
+
if (nextId === _activeId) return;
|
|
185
|
+
const prev = _open.find((d) => d.descriptor.id === _activeId);
|
|
186
|
+
_activeId = nextId;
|
|
187
|
+
prev?.descriptor.onDeactivate?.(prev.descriptor.id);
|
|
188
|
+
const next = _open.find((d) => d.descriptor.id === nextId);
|
|
189
|
+
next?.descriptor.onActivate?.(next.descriptor.id);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Open a document (§7.1 open semantics): appends it to the open set and
|
|
194
|
+
* makes it active. If `descriptor.id` is ALREADY open, the existing document
|
|
195
|
+
* is activated and its original descriptor kept (stable identity — a
|
|
196
|
+
* re-open never silently swaps content). Returns the id.
|
|
197
|
+
*/
|
|
198
|
+
export function openWorkspaceDocument(descriptor: WorkspaceDocumentDescriptor): string {
|
|
199
|
+
const existing = _open.find((d) => d.descriptor.id === descriptor.id);
|
|
200
|
+
if (!existing) {
|
|
201
|
+
_open = [..._open, { descriptor, dirty: false, title: descriptor.title }];
|
|
202
|
+
setActive(descriptor.id);
|
|
203
|
+
notifyChanged();
|
|
204
|
+
return descriptor.id;
|
|
205
|
+
}
|
|
206
|
+
// Already open: only activating (or no-op if already active) — same guard
|
|
207
|
+
// as `activateWorkspaceDocument`, no version bump/notify without a change.
|
|
208
|
+
if (_activeId !== descriptor.id) {
|
|
209
|
+
setActive(descriptor.id);
|
|
210
|
+
notifyChanged();
|
|
211
|
+
}
|
|
212
|
+
return descriptor.id;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** Activate an open document. Returns `false` (no-op) for unknown ids. */
|
|
216
|
+
export function activateWorkspaceDocument(id: string): boolean {
|
|
217
|
+
if (!_open.some((d) => d.descriptor.id === id)) return false;
|
|
218
|
+
if (_activeId !== id) {
|
|
219
|
+
setActive(id);
|
|
220
|
+
notifyChanged();
|
|
221
|
+
}
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Close an open document: removes it (calling `onDeactivate` if it was
|
|
227
|
+
* active, then `onDispose`) and, when it was active, activates its left
|
|
228
|
+
* neighbor (else the right one, else none) — the standard tabbed-editor
|
|
229
|
+
* fallback. Returns `false` (no-op) for unknown ids. `closeable: false` is
|
|
230
|
+
* a HOST affordance rule (no × on the tab), not a registry invariant —
|
|
231
|
+
* programmatic close (project switch, W1 host teardown) must always work.
|
|
232
|
+
*
|
|
233
|
+
* Re-entrancy guard: the neighbor's `onActivate` (fired inside `setActive`
|
|
234
|
+
* below, while `closing` is still in `_open`) can synchronously bounce back
|
|
235
|
+
* into a close of the SAME id it is still closing — e.g. a store-notify
|
|
236
|
+
* subscriber re-derives its open set from `_open`, sees `closing` still
|
|
237
|
+
* present (the filter hasn't run yet), and calls `closeWorkspaceDocument`
|
|
238
|
+
* again for it. Without a guard that inner call would run the full close
|
|
239
|
+
* body a second time and fire `onDispose` twice for one close. `_closingIds`
|
|
240
|
+
* marks `id` in-flight for the duration of this call so the re-entrant call
|
|
241
|
+
* is a no-op (returns `false` immediately) — the outer call is the only one
|
|
242
|
+
* that ever filters `_open` / fires `onDispose`, and the pinned lifecycle
|
|
243
|
+
* order (onDeactivate → neighbor onActivate → onDispose) is unchanged.
|
|
244
|
+
*/
|
|
245
|
+
export function closeWorkspaceDocument(
|
|
246
|
+
id: string,
|
|
247
|
+
options: { discardDirty?: boolean } = {},
|
|
248
|
+
): boolean {
|
|
249
|
+
if (_closingIds.has(id)) return false;
|
|
250
|
+
const idx = _open.findIndex((d) => d.descriptor.id === id);
|
|
251
|
+
if (idx < 0) return false;
|
|
252
|
+
const closing = _open[idx] as OpenWorkspaceDocument;
|
|
253
|
+
// A close gesture is not authorization to destroy an authored draft. The
|
|
254
|
+
// Dockview tab presents Save / Discard / Cancel and calls back with the
|
|
255
|
+
// explicit discard flag only after the user chooses it. Project teardown
|
|
256
|
+
// uses closeAllWorkspaceDocuments(), whose lifecycle semantics are separate.
|
|
257
|
+
if (closing.dirty && !options.discardDirty) return false;
|
|
258
|
+
_closingIds.add(id);
|
|
259
|
+
try {
|
|
260
|
+
const wasActive = _activeId === id;
|
|
261
|
+
if (wasActive) {
|
|
262
|
+
// Left neighbor, else right, else none — computed on the PRE-removal
|
|
263
|
+
// array so the indices are the real tab neighbors.
|
|
264
|
+
const neighbor = idx > 0 ? _open[idx - 1] : (_open[idx + 1] ?? null);
|
|
265
|
+
// `closing` must still be in `_open` here: `setActive`'s `prev` lookup
|
|
266
|
+
// finds it by `_activeId` and fires its `onDeactivate` before the
|
|
267
|
+
// neighbor's `onActivate` — firing this AFTER filtering `_open` (the
|
|
268
|
+
// former bug) made the lookup miss and silently skip onDeactivate.
|
|
269
|
+
setActive(neighbor ? neighbor.descriptor.id : null);
|
|
270
|
+
}
|
|
271
|
+
_open = _open.filter((d) => d.descriptor.id !== id);
|
|
272
|
+
_saveHandlers.delete(id);
|
|
273
|
+
closing.descriptor.onDispose?.(id);
|
|
274
|
+
notifyChanged();
|
|
275
|
+
return true;
|
|
276
|
+
} finally {
|
|
277
|
+
_closingIds.delete(id);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/** Close every open document (project switch / host teardown): each gets its
|
|
282
|
+
* `onDeactivate` (active one only) + `onDispose`, in open order. */
|
|
283
|
+
export function closeAllWorkspaceDocuments(): void {
|
|
284
|
+
if (_open.length === 0 && _activeId === null) return;
|
|
285
|
+
const closing = _open;
|
|
286
|
+
// Fire onDeactivate for the active document WHILE it is still in `_open`
|
|
287
|
+
// (setActive's `prev` lookup needs to find it) — clearing `_open` first
|
|
288
|
+
// (the former bug) made the lookup miss and silently skip onDeactivate.
|
|
289
|
+
setActive(null);
|
|
290
|
+
_open = [];
|
|
291
|
+
_saveHandlers.clear();
|
|
292
|
+
for (const doc of closing) doc.descriptor.onDispose?.(doc.descriptor.id);
|
|
293
|
+
notifyChanged();
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** Install the save capability supplied by a mounted document editor. The
|
|
297
|
+
* returned cleanup cannot remove a newer handler installed for the same id. */
|
|
298
|
+
export function registerWorkspaceDocumentSaveHandler(
|
|
299
|
+
id: string,
|
|
300
|
+
handler: WorkspaceDocumentSaveHandler,
|
|
301
|
+
): () => void {
|
|
302
|
+
if (!_open.some((document) => document.descriptor.id === id)) return () => {};
|
|
303
|
+
_saveHandlers.set(id, handler);
|
|
304
|
+
return () => {
|
|
305
|
+
if (_saveHandlers.get(id) === handler) _saveHandlers.delete(id);
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** Save one open document. `null` means that document has no document-local
|
|
310
|
+
* save capability, so callers may preserve a legacy/fallback save path. */
|
|
311
|
+
export async function saveWorkspaceDocument(id: string): Promise<boolean | null> {
|
|
312
|
+
if (!_open.some((document) => document.descriptor.id === id)) return null;
|
|
313
|
+
const handler = _saveHandlers.get(id);
|
|
314
|
+
if (!handler) return null;
|
|
315
|
+
try {
|
|
316
|
+
return await handler();
|
|
317
|
+
} catch {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/** Save the active authored subject, or `null` when it has no local saver. */
|
|
323
|
+
export function saveActiveWorkspaceDocument(): Promise<boolean | null> {
|
|
324
|
+
return _activeId ? saveWorkspaceDocument(_activeId) : Promise.resolve(null);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** Set a document's dirty flag (§7.1 optional dirty state). Unknown ids and
|
|
328
|
+
* no-op transitions are ignored without notification. */
|
|
329
|
+
export function setWorkspaceDocumentDirty(id: string, dirty: boolean): void {
|
|
330
|
+
const idx = _open.findIndex((d) => d.descriptor.id === id);
|
|
331
|
+
if (idx < 0) return;
|
|
332
|
+
const doc = _open[idx] as OpenWorkspaceDocument;
|
|
333
|
+
if (doc.dirty === dirty) return;
|
|
334
|
+
_open = _open.map((d) => (d.descriptor.id === id ? { ...d, dirty } : d));
|
|
335
|
+
notifyChanged();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** Set a document's live display title (see {@link OpenWorkspaceDocument}).
|
|
339
|
+
* Unknown ids and no-op transitions are ignored without notification. */
|
|
340
|
+
export function setWorkspaceDocumentTitle(id: string, title: string): void {
|
|
341
|
+
const doc = _open.find((d) => d.descriptor.id === id);
|
|
342
|
+
if (!doc || doc.title === title) return;
|
|
343
|
+
_open = _open.map((d) => (d.descriptor.id === id ? { ...d, title } : d));
|
|
344
|
+
notifyChanged();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/** A document's selection/Inspector context (guarded: a throwing `selection`
|
|
348
|
+
* is treated as "no context" — same failure physics as tool-loader's match
|
|
349
|
+
* guard; the shell must never crash on a contribution). */
|
|
350
|
+
export function workspaceDocumentSelection(id: string): WorkspaceDocumentSelection | null {
|
|
351
|
+
const doc = _open.find((d) => d.descriptor.id === id);
|
|
352
|
+
if (!doc?.descriptor.selection) return null;
|
|
353
|
+
try {
|
|
354
|
+
return doc.descriptor.selection();
|
|
355
|
+
} catch {
|
|
356
|
+
return null;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/** Test-only reset (mirrors `__resetInspectorSectionRegistryForTest`) —
|
|
361
|
+
* drops all state WITHOUT firing lifecycle hooks. */
|
|
362
|
+
export function __resetWorkspaceDocumentRegistryForTest(): void {
|
|
363
|
+
_open = [];
|
|
364
|
+
_activeId = null;
|
|
365
|
+
_saveHandlers.clear();
|
|
366
|
+
notifyChanged();
|
|
367
|
+
}
|