@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,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The human-facing projection of the ingest coverage report.
|
|
3
|
+
*
|
|
4
|
+
* The report is derived in `coverage/capability-coverage.ts`; this component never
|
|
5
|
+
* re-measures or reinterprets a seam. It only gives the same rows already
|
|
6
|
+
* exposed by `vgai status` and the console an Inspector-shaped reading: the
|
|
7
|
+
* measured fact first, then the consequence and the concrete fix for gaps.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
faChartSimple,
|
|
12
|
+
faCircleCheck,
|
|
13
|
+
faCircleExclamation,
|
|
14
|
+
faCircleInfo,
|
|
15
|
+
faCircleMinus,
|
|
16
|
+
} from '@fortawesome/free-solid-svg-icons';
|
|
17
|
+
import type { LiveCoverageReport, LiveCoverageRow } from '@volter/editor-sdk/host';
|
|
18
|
+
import { EditorIcon, SectionHeader, themeVars } from '@volter/editor-sdk/widgets';
|
|
19
|
+
import type { ReactNode } from 'react';
|
|
20
|
+
import type { InspectionSection } from '../inspection/model';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Human labels for the seams whose names are not self-describing — the contract
|
|
24
|
+
* declarations an ingested game makes.
|
|
25
|
+
*
|
|
26
|
+
* The `editor.*` and `system.*` families are deliberately NOT listed: those are
|
|
27
|
+
* generated from the `AuthoringAdapter` / `SystemAdapters` contracts, and a
|
|
28
|
+
* hand-written label map over a generated family is the same defect the
|
|
29
|
+
* generator exists to remove — the map would silently miss whichever seam
|
|
30
|
+
* nobody remembered, in the one surface a human reads. They are humanized from
|
|
31
|
+
* the seam name instead, which cannot go stale.
|
|
32
|
+
*/
|
|
33
|
+
const CONTRACT_SEAM_LABEL: Partial<Record<string, string>> = {
|
|
34
|
+
loop: 'Loop control',
|
|
35
|
+
'contract.root': 'DOM root',
|
|
36
|
+
'contract.lifecycle.start': 'Cold start',
|
|
37
|
+
'contract.lifecycle.pause': 'Pause / resume',
|
|
38
|
+
persistence: 'Source persistence',
|
|
39
|
+
systems: 'Commands and state',
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/** `editor.assetDrop` → "Asset drop"; `system.renderDebug` → "Render debug
|
|
43
|
+
* adapter". Presentation only — the seam name itself stays the id. */
|
|
44
|
+
function seamLabel(seam: string): string {
|
|
45
|
+
const explicit = CONTRACT_SEAM_LABEL[seam];
|
|
46
|
+
if (explicit) return explicit;
|
|
47
|
+
const [family, member] = seam.split('.');
|
|
48
|
+
const words = (member ?? seam).replace(/([a-z])([A-Z])/g, '$1 $2').toLowerCase();
|
|
49
|
+
const sentence = words.charAt(0).toUpperCase() + words.slice(1);
|
|
50
|
+
return family === 'system' ? `${sentence} adapter` : sentence;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const STATUS_ICON = {
|
|
54
|
+
ok: faCircleCheck,
|
|
55
|
+
gap: faCircleExclamation,
|
|
56
|
+
na: faCircleMinus,
|
|
57
|
+
info: faCircleInfo,
|
|
58
|
+
} as const;
|
|
59
|
+
|
|
60
|
+
const STATUS_COLOR = {
|
|
61
|
+
ok: themeVars.semantic.success,
|
|
62
|
+
gap: themeVars.semantic.warning,
|
|
63
|
+
na: themeVars.content.dim,
|
|
64
|
+
info: themeVars.content.dim,
|
|
65
|
+
} as const;
|
|
66
|
+
|
|
67
|
+
function CoverageRow({ row }: { readonly row: LiveCoverageRow }) {
|
|
68
|
+
return (
|
|
69
|
+
<div
|
|
70
|
+
data-testid={`ingest-coverage-row-${row.seam}`}
|
|
71
|
+
data-status={row.status}
|
|
72
|
+
style={{
|
|
73
|
+
display: 'grid',
|
|
74
|
+
gridTemplateColumns: '16px minmax(0, 1fr)',
|
|
75
|
+
gap: 7,
|
|
76
|
+
padding: '8px 10px',
|
|
77
|
+
borderTop: '1px solid var(--vgai-structural-divider)',
|
|
78
|
+
}}
|
|
79
|
+
>
|
|
80
|
+
<span style={{ color: STATUS_COLOR[row.status], paddingTop: 1 }}>
|
|
81
|
+
<EditorIcon icon={STATUS_ICON[row.status]} />
|
|
82
|
+
</span>
|
|
83
|
+
<div style={{ minWidth: 0 }}>
|
|
84
|
+
<div style={{ color: themeVars.content.primary, fontWeight: 600 }}>
|
|
85
|
+
{seamLabel(row.seam)}
|
|
86
|
+
</div>
|
|
87
|
+
<div
|
|
88
|
+
style={{
|
|
89
|
+
marginTop: 2,
|
|
90
|
+
color: themeVars.content.muted,
|
|
91
|
+
lineHeight: 1.4,
|
|
92
|
+
overflowWrap: 'anywhere',
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
{row.detail}
|
|
96
|
+
</div>
|
|
97
|
+
{row.missing && (
|
|
98
|
+
<div style={{ marginTop: 6, color: themeVars.content.muted, lineHeight: 1.4 }}>
|
|
99
|
+
<strong style={{ color: themeVars.semantic.warning }}>Missing:</strong> {row.missing}
|
|
100
|
+
</div>
|
|
101
|
+
)}
|
|
102
|
+
{row.fix && (
|
|
103
|
+
<div style={{ marginTop: 4, color: themeVars.content.dim, lineHeight: 1.4 }}>
|
|
104
|
+
<strong>Fix:</strong> {row.fix}
|
|
105
|
+
</div>
|
|
106
|
+
)}
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function CapabilityCoverageBody({ report }: { readonly report: LiveCoverageReport }) {
|
|
113
|
+
const { summary } = report;
|
|
114
|
+
return (
|
|
115
|
+
<div data-testid="ingest-coverage-report" style={{ fontSize: 'var(--vgai-font-base)' }}>
|
|
116
|
+
<div
|
|
117
|
+
style={{
|
|
118
|
+
display: 'flex',
|
|
119
|
+
flexWrap: 'wrap',
|
|
120
|
+
gap: 8,
|
|
121
|
+
padding: '7px 10px 9px',
|
|
122
|
+
color: themeVars.content.muted,
|
|
123
|
+
}}
|
|
124
|
+
>
|
|
125
|
+
<span
|
|
126
|
+
style={{
|
|
127
|
+
color: summary.gaps > 0 ? themeVars.semantic.warning : themeVars.semantic.success,
|
|
128
|
+
}}
|
|
129
|
+
>
|
|
130
|
+
{summary.gaps} {summary.gaps === 1 ? 'gap' : 'gaps'}
|
|
131
|
+
</span>
|
|
132
|
+
<span>{summary.ok} integrated</span>
|
|
133
|
+
<span>{summary.na} not applicable</span>
|
|
134
|
+
<span>{summary.info} informational</span>
|
|
135
|
+
</div>
|
|
136
|
+
{report.rows.map((row) => (
|
|
137
|
+
<CoverageRow key={row.seam} row={row} />
|
|
138
|
+
))}
|
|
139
|
+
</div>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** Add the report to an ordinary composed inspection subject. The stable id
|
|
144
|
+
* means the compact Inspector keeps the same tab open while measurements
|
|
145
|
+
* refresh; sorting keeps the projection content-agnostic. */
|
|
146
|
+
export function ingestCoverageSection(report: LiveCoverageReport): InspectionSection {
|
|
147
|
+
return {
|
|
148
|
+
id: 'ingest-coverage',
|
|
149
|
+
title: 'Ingest coverage',
|
|
150
|
+
icon: faChartSimple,
|
|
151
|
+
order: 9_000,
|
|
152
|
+
description: `${report.summary.gaps} gap${report.summary.gaps === 1 ? '' : 's'}`,
|
|
153
|
+
defaultOpen: true,
|
|
154
|
+
testId: 'ingest-coverage-section',
|
|
155
|
+
body: {
|
|
156
|
+
kind: 'custom',
|
|
157
|
+
render: (): ReactNode => <CapabilityCoverageBody report={report} />,
|
|
158
|
+
// `editor.inspect()` cannot render React. Publish exactly what this body
|
|
159
|
+
// displays so the agent and the human read the same report through the
|
|
160
|
+
// Inspector rather than forcing the agent back to a parallel status
|
|
161
|
+
// shape.
|
|
162
|
+
data: { summary: report.summary, rows: report.rows },
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/** The nothing-to-author Inspector has no composed subject/section list, so it uses
|
|
168
|
+
* the same section as a directly headed block instead of inventing a second
|
|
169
|
+
* presentation for the report. */
|
|
170
|
+
export function CapabilityCoverageBlock({ report }: { readonly report: LiveCoverageReport }) {
|
|
171
|
+
const section = ingestCoverageSection(report);
|
|
172
|
+
return (
|
|
173
|
+
<div data-testid={section.testId}>
|
|
174
|
+
<SectionHeader
|
|
175
|
+
label={section.title}
|
|
176
|
+
icon={section.icon}
|
|
177
|
+
description={section.description}
|
|
178
|
+
collapsible
|
|
179
|
+
defaultOpen
|
|
180
|
+
>
|
|
181
|
+
<CapabilityCoverageBody report={report} />
|
|
182
|
+
</SectionHeader>
|
|
183
|
+
</div>
|
|
184
|
+
);
|
|
185
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/** Session attachment for contributed center documents.
|
|
2
|
+
* Document owners register their own content and initial documents. The host
|
|
3
|
+
* does not synthesize a Scene tab or own a game's root evaluator.
|
|
4
|
+
*/
|
|
5
|
+
import { useEffect } from 'react';
|
|
6
|
+
import type { EditorShellStore } from '../editor-shell-store';
|
|
7
|
+
import { bindLiveDocument, syncLiveDocumentPlayState } from '../live-document';
|
|
8
|
+
import { closeAllWorkspaceDocuments } from '../workspace-document-registry';
|
|
9
|
+
|
|
10
|
+
export function useCenterDocuments(store: EditorShellStore): void {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
const unbind = bindLiveDocument({ onActivate: () => store.setActiveViewportTab('play') });
|
|
13
|
+
const sync = () => syncLiveDocumentPlayState(store.playState !== 'stopped');
|
|
14
|
+
sync();
|
|
15
|
+
const unsubscribe = store.subscribe(sync);
|
|
16
|
+
return () => {
|
|
17
|
+
unsubscribe();
|
|
18
|
+
unbind();
|
|
19
|
+
closeAllWorkspaceDocuments();
|
|
20
|
+
};
|
|
21
|
+
}, [store]);
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** Renders whatever a package registered for a chrome slot
|
|
2
|
+
* (`chrome-slot-registry.ts`), and nothing when nothing did. */
|
|
3
|
+
|
|
4
|
+
import { useSyncExternalStore } from 'react';
|
|
5
|
+
import {
|
|
6
|
+
chromeSlotFillers,
|
|
7
|
+
chromeSlotRegistryVersion,
|
|
8
|
+
subscribeChromeSlots,
|
|
9
|
+
} from '../chrome-slot-registry';
|
|
10
|
+
|
|
11
|
+
export function ChromeSlot({ slot }: { readonly slot: string }) {
|
|
12
|
+
useSyncExternalStore(subscribeChromeSlots, chromeSlotRegistryVersion, chromeSlotRegistryVersion);
|
|
13
|
+
return (
|
|
14
|
+
<>
|
|
15
|
+
{chromeSlotFillers(slot).map((filler) => (
|
|
16
|
+
<filler.Content key={filler.owner} />
|
|
17
|
+
))}
|
|
18
|
+
</>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
import { themeVars } from '@volter/editor-sdk/widgets';
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The editor's ONE read-only code display surface (CodeMirror 6).
|
|
6
|
+
*
|
|
7
|
+
* Every door that opens a project's own source text renders through this —
|
|
8
|
+
* `SourceAssetViewer`'s text route and the generic JSON viewer today. It is a
|
|
9
|
+
* VIEWER: `EditorState.readOnly` + `EditorView.editable(false)`, so nothing
|
|
10
|
+
* here ever writes a game's file. Doors that already own an editing surface
|
|
11
|
+
* keep theirs.
|
|
12
|
+
*
|
|
13
|
+
* ## Why the pieces are imported individually, not `codemirror`
|
|
14
|
+
*
|
|
15
|
+
* The `codemirror` meta-package exports exactly three things — `EditorView`,
|
|
16
|
+
* `basicSetup`, `minimalSetup` — and its own docblock says that the moment you
|
|
17
|
+
* want to configure precisely, you compose the sub-packages yourself. We do:
|
|
18
|
+
* `basicSetup` bundles autocompletion, close-brackets, undo history, lint and
|
|
19
|
+
* ACTIVE-LINE highlighting, all of which are either inert or wrong in a
|
|
20
|
+
* viewer, and it is explicitly not customizable.
|
|
21
|
+
*
|
|
22
|
+
* ## Why it is lazy
|
|
23
|
+
*
|
|
24
|
+
* CodeMirror + the JS/JSON grammars are ~400 kB of source that only a user who
|
|
25
|
+
* opens a source or JSON asset ever needs, so the whole kit sits behind a
|
|
26
|
+
* dynamic import (same reason `game-realm-page.ts` defers postcss). Until the
|
|
27
|
+
* chunk lands the raw text renders in a plain `<pre>`, so content is never
|
|
28
|
+
* withheld waiting on a network round trip — a long file is readable
|
|
29
|
+
* immediately and simply gains highlighting a beat later.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
export type CodeViewLanguage = 'typescript' | 'json' | 'text';
|
|
33
|
+
|
|
34
|
+
const LANGUAGE_BY_EXTENSION: Readonly<Record<string, CodeViewLanguage>> = {
|
|
35
|
+
ts: 'typescript',
|
|
36
|
+
tsx: 'typescript',
|
|
37
|
+
mts: 'typescript',
|
|
38
|
+
cts: 'typescript',
|
|
39
|
+
js: 'typescript',
|
|
40
|
+
jsx: 'typescript',
|
|
41
|
+
mjs: 'typescript',
|
|
42
|
+
cjs: 'typescript',
|
|
43
|
+
json: 'json',
|
|
44
|
+
jsonc: 'json',
|
|
45
|
+
json5: 'json',
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/** Language for a file path's extension; anything unrecognized reads as text. */
|
|
49
|
+
export function codeViewLanguage(path: string): CodeViewLanguage {
|
|
50
|
+
const name = path.split('/').pop() ?? path;
|
|
51
|
+
const dot = name.lastIndexOf('.');
|
|
52
|
+
if (dot < 0) return 'text';
|
|
53
|
+
return LANGUAGE_BY_EXTENSION[name.slice(dot + 1).toLowerCase()] ?? 'text';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
type CodeMirrorKit = {
|
|
57
|
+
readonly state: typeof import('@codemirror/state');
|
|
58
|
+
readonly view: typeof import('@codemirror/view');
|
|
59
|
+
readonly language: typeof import('@codemirror/language');
|
|
60
|
+
readonly search: typeof import('@codemirror/search');
|
|
61
|
+
readonly commands: typeof import('@codemirror/commands');
|
|
62
|
+
readonly javascript: typeof import('@codemirror/lang-javascript');
|
|
63
|
+
readonly json: typeof import('@codemirror/lang-json');
|
|
64
|
+
readonly oneDark: typeof import('@codemirror/theme-one-dark');
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
let kitPromise: Promise<CodeMirrorKit> | null = null;
|
|
68
|
+
|
|
69
|
+
/** Loads (once per session) the CodeMirror chunk shared by every code view. */
|
|
70
|
+
function loadCodeMirror(): Promise<CodeMirrorKit> {
|
|
71
|
+
kitPromise ??= Promise.all([
|
|
72
|
+
import('@codemirror/state'),
|
|
73
|
+
import('@codemirror/view'),
|
|
74
|
+
import('@codemirror/language'),
|
|
75
|
+
import('@codemirror/search'),
|
|
76
|
+
import('@codemirror/commands'),
|
|
77
|
+
import('@codemirror/lang-javascript'),
|
|
78
|
+
import('@codemirror/lang-json'),
|
|
79
|
+
import('@codemirror/theme-one-dark'),
|
|
80
|
+
]).then(([state, view, language, search, commands, javascript, json, oneDark]) => ({
|
|
81
|
+
state,
|
|
82
|
+
view,
|
|
83
|
+
language,
|
|
84
|
+
search,
|
|
85
|
+
commands,
|
|
86
|
+
javascript,
|
|
87
|
+
json,
|
|
88
|
+
oneDark,
|
|
89
|
+
}));
|
|
90
|
+
return kitPromise;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function cssLength(value: number | string): string {
|
|
94
|
+
return typeof value === 'number' ? `${value}px` : value;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Chrome drawn from the editor's OWN theme variables — every editor theme is
|
|
99
|
+
* dark, so one-dark supplies the token ramp (`oneDarkHighlightStyle`) while the
|
|
100
|
+
* surface, gutter, selection, and search-panel colors come from `themeVars` so
|
|
101
|
+
* the view sits inside a panel without announcing itself as foreign chrome.
|
|
102
|
+
* The background is deliberately transparent: the calling door owns its well.
|
|
103
|
+
*/
|
|
104
|
+
/**
|
|
105
|
+
* A PERCENTAGE `maxHeight` means "fill the box you are in".
|
|
106
|
+
*
|
|
107
|
+
* CodeMirror sizes itself to its content unless the editor element is given a
|
|
108
|
+
* definite height, so `max-height: 100%` on the scroller alone resolves against
|
|
109
|
+
* an auto-height ancestor and does nothing. A percentage therefore also puts a
|
|
110
|
+
* `height` on `.cm-editor` (and on the host element), which is CodeMirror's own
|
|
111
|
+
* documented spelling for a filling editor. A pixel `maxHeight` keeps the
|
|
112
|
+
* flow-to-content behaviour every existing caller relies on.
|
|
113
|
+
*/
|
|
114
|
+
function fillsItsBox(maxHeight: number | string | undefined): maxHeight is string {
|
|
115
|
+
return typeof maxHeight === 'string' && maxHeight.trim().endsWith('%');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Source updates are transactions, so their cue follows the same document. */
|
|
119
|
+
function changedSourceRange(previous: string, value: string) {
|
|
120
|
+
let from = 0;
|
|
121
|
+
while (from < previous.length && from < value.length && previous[from] === value[from]) from++;
|
|
122
|
+
let oldEnd = previous.length;
|
|
123
|
+
let newEnd = value.length;
|
|
124
|
+
while (oldEnd > from && newEnd > from && previous[oldEnd - 1] === value[newEnd - 1]) {
|
|
125
|
+
oldEnd--;
|
|
126
|
+
newEnd--;
|
|
127
|
+
}
|
|
128
|
+
return { from, oldEnd, newEnd };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const SOURCE_CHANGE_DURATION_MS = 1800;
|
|
132
|
+
const sourceChangeBackground = `color-mix(in srgb, ${themeVars.semantic.warning} 42%, transparent)`;
|
|
133
|
+
const sourceChangeLineBackground = `color-mix(in srgb, ${themeVars.semantic.warning} 18%, transparent)`;
|
|
134
|
+
|
|
135
|
+
function createChangeHighlight(kit: CodeMirrorKit) {
|
|
136
|
+
// Deleted text has no surviving range. Mark its boundary without coloring
|
|
137
|
+
// an unchanged neighbour or adding width to the source line.
|
|
138
|
+
class DeletionCue extends kit.view.WidgetType {
|
|
139
|
+
constructor(readonly revision: number) {
|
|
140
|
+
super();
|
|
141
|
+
}
|
|
142
|
+
eq(other: DeletionCue) {
|
|
143
|
+
return this.revision === other.revision;
|
|
144
|
+
}
|
|
145
|
+
toDOM() {
|
|
146
|
+
const element = document.createElement('span');
|
|
147
|
+
element.className = `cm-source-deletion cm-source-change cm-source-change-${this.revision % 2}`;
|
|
148
|
+
element.setAttribute('aria-hidden', 'true');
|
|
149
|
+
return element;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const mark = kit.state.StateEffect.define<{
|
|
153
|
+
from: number;
|
|
154
|
+
to: number;
|
|
155
|
+
revision: number;
|
|
156
|
+
} | null>();
|
|
157
|
+
const field = kit.state.StateField.define<import('@codemirror/view').DecorationSet>({
|
|
158
|
+
create: () => kit.view.Decoration.none,
|
|
159
|
+
update(decorations, transaction) {
|
|
160
|
+
let next = decorations.map(transaction.changes);
|
|
161
|
+
for (const effect of transaction.effects) {
|
|
162
|
+
if (!effect.is(mark)) continue;
|
|
163
|
+
if (!effect.value) {
|
|
164
|
+
next = kit.view.Decoration.none;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const { from, to, revision } = effect.value;
|
|
168
|
+
const decoration =
|
|
169
|
+
from === to
|
|
170
|
+
? kit.view.Decoration.widget({ widget: new DeletionCue(revision), side: -1 }).range(
|
|
171
|
+
from,
|
|
172
|
+
)
|
|
173
|
+
: kit.view.Decoration.mark({
|
|
174
|
+
class: `cm-source-change cm-source-change-${revision % 2}`,
|
|
175
|
+
}).range(from, to);
|
|
176
|
+
next = kit.view.Decoration.set([decoration]);
|
|
177
|
+
}
|
|
178
|
+
return next;
|
|
179
|
+
},
|
|
180
|
+
provide: (value) => kit.view.EditorView.decorations.from(value),
|
|
181
|
+
});
|
|
182
|
+
return { mark, field };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function codeViewTheme(
|
|
186
|
+
kit: CodeMirrorKit,
|
|
187
|
+
fontSize: number,
|
|
188
|
+
maxHeight: number | string | undefined,
|
|
189
|
+
) {
|
|
190
|
+
return kit.view.EditorView.theme(
|
|
191
|
+
{
|
|
192
|
+
'&': {
|
|
193
|
+
color: themeVars.content.primary,
|
|
194
|
+
backgroundColor: 'transparent',
|
|
195
|
+
fontSize: `${fontSize}px`,
|
|
196
|
+
...(fillsItsBox(maxHeight) ? { height: cssLength(maxHeight) } : {}),
|
|
197
|
+
},
|
|
198
|
+
'&.cm-focused': { outline: 'none' },
|
|
199
|
+
'.cm-content': {
|
|
200
|
+
fontFamily: themeVars.typography.mono,
|
|
201
|
+
padding: '2px 0',
|
|
202
|
+
caretColor: 'transparent',
|
|
203
|
+
},
|
|
204
|
+
'.cm-scroller': {
|
|
205
|
+
fontFamily: themeVars.typography.mono,
|
|
206
|
+
lineHeight: '1.5',
|
|
207
|
+
overflow: 'auto',
|
|
208
|
+
...(maxHeight === undefined ? {} : { maxHeight: cssLength(maxHeight) }),
|
|
209
|
+
},
|
|
210
|
+
'.cm-gutters': {
|
|
211
|
+
backgroundColor: 'transparent',
|
|
212
|
+
color: themeVars.content.dim,
|
|
213
|
+
border: 'none',
|
|
214
|
+
userSelect: 'none',
|
|
215
|
+
},
|
|
216
|
+
'.cm-lineNumbers .cm-gutterElement': { padding: '0 8px 0 4px', minWidth: '2ch' },
|
|
217
|
+
'.cm-content ::selection': { backgroundColor: themeVars.selection.background },
|
|
218
|
+
'.cm-panels': {
|
|
219
|
+
backgroundColor: themeVars.surface.raised,
|
|
220
|
+
color: themeVars.content.primary,
|
|
221
|
+
border: 'none',
|
|
222
|
+
fontFamily: themeVars.typography.sans,
|
|
223
|
+
},
|
|
224
|
+
'.cm-panels.cm-panels-top': { borderBottom: `1px solid ${themeVars.boundary.default}` },
|
|
225
|
+
'.cm-textfield': {
|
|
226
|
+
backgroundColor: themeVars.surface.inset,
|
|
227
|
+
color: themeVars.content.primary,
|
|
228
|
+
border: `1px solid ${themeVars.boundary.default}`,
|
|
229
|
+
borderRadius: themeVars.shape.small,
|
|
230
|
+
},
|
|
231
|
+
'.cm-button': {
|
|
232
|
+
backgroundColor: themeVars.surface.raised,
|
|
233
|
+
backgroundImage: 'none',
|
|
234
|
+
color: themeVars.content.primary,
|
|
235
|
+
border: `1px solid ${themeVars.boundary.default}`,
|
|
236
|
+
borderRadius: themeVars.shape.small,
|
|
237
|
+
},
|
|
238
|
+
'.cm-searchMatch': { backgroundColor: themeVars.accent.muted },
|
|
239
|
+
'.cm-searchMatch.cm-searchMatch-selected': {
|
|
240
|
+
backgroundColor: themeVars.accent.default,
|
|
241
|
+
color: themeVars.content.onAccent,
|
|
242
|
+
},
|
|
243
|
+
'.cm-source-change': {
|
|
244
|
+
backgroundColor: sourceChangeBackground,
|
|
245
|
+
borderRadius: '2px',
|
|
246
|
+
},
|
|
247
|
+
'.cm-line:has(.cm-source-change)': {
|
|
248
|
+
backgroundColor: sourceChangeLineBackground,
|
|
249
|
+
},
|
|
250
|
+
'.cm-source-change, .cm-line:has(.cm-source-change)': {
|
|
251
|
+
animationDuration: `${SOURCE_CHANGE_DURATION_MS}ms`,
|
|
252
|
+
animationTimingFunction: 'ease-out',
|
|
253
|
+
animationFillMode: 'forwards',
|
|
254
|
+
},
|
|
255
|
+
'.cm-source-deletion': {
|
|
256
|
+
display: 'inline-block',
|
|
257
|
+
width: '0',
|
|
258
|
+
position: 'relative',
|
|
259
|
+
},
|
|
260
|
+
'.cm-source-deletion::after': {
|
|
261
|
+
content: '""',
|
|
262
|
+
position: 'absolute',
|
|
263
|
+
left: '-2px',
|
|
264
|
+
bottom: '0',
|
|
265
|
+
width: '4px',
|
|
266
|
+
height: '1em',
|
|
267
|
+
backgroundColor: 'inherit',
|
|
268
|
+
borderRadius: '2px',
|
|
269
|
+
},
|
|
270
|
+
'.cm-source-change-0': { animationName: 'vgai-source-change-even' },
|
|
271
|
+
'.cm-source-change-1': { animationName: 'vgai-source-change-odd' },
|
|
272
|
+
'.cm-line:has(.cm-source-change-0)': { animationName: 'vgai-source-line-even' },
|
|
273
|
+
'.cm-line:has(.cm-source-change-1)': { animationName: 'vgai-source-line-odd' },
|
|
274
|
+
'@keyframes vgai-source-line-even': {
|
|
275
|
+
'0%, 40%': { backgroundColor: sourceChangeLineBackground },
|
|
276
|
+
'100%': { backgroundColor: 'transparent' },
|
|
277
|
+
},
|
|
278
|
+
'@keyframes vgai-source-line-odd': {
|
|
279
|
+
'0%, 40%': { backgroundColor: sourceChangeLineBackground },
|
|
280
|
+
'100%': { backgroundColor: 'transparent' },
|
|
281
|
+
},
|
|
282
|
+
'@keyframes vgai-source-change-even': {
|
|
283
|
+
'0%, 40%': { backgroundColor: sourceChangeBackground },
|
|
284
|
+
'100%': { backgroundColor: 'transparent' },
|
|
285
|
+
},
|
|
286
|
+
'@keyframes vgai-source-change-odd': {
|
|
287
|
+
'0%, 40%': { backgroundColor: sourceChangeBackground },
|
|
288
|
+
'100%': { backgroundColor: 'transparent' },
|
|
289
|
+
},
|
|
290
|
+
'@media (prefers-reduced-motion: reduce)': {
|
|
291
|
+
'.cm-source-change, .cm-line:has(.cm-source-change)': { animation: 'none' },
|
|
292
|
+
},
|
|
293
|
+
'.cm-matchingBracket, &.cm-focused .cm-matchingBracket': {
|
|
294
|
+
backgroundColor: themeVars.neutralOverlay.active,
|
|
295
|
+
outline: `1px solid ${themeVars.boundary.strong}`,
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
{ dark: true },
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function codeViewExtensions(
|
|
303
|
+
kit: CodeMirrorKit,
|
|
304
|
+
language: CodeViewLanguage,
|
|
305
|
+
fontSize: number,
|
|
306
|
+
maxHeight: number | string | undefined,
|
|
307
|
+
) {
|
|
308
|
+
const languageExtension =
|
|
309
|
+
language === 'typescript'
|
|
310
|
+
? [kit.javascript.javascript({ typescript: true, jsx: true })]
|
|
311
|
+
: language === 'json'
|
|
312
|
+
? [kit.json.json()]
|
|
313
|
+
: [];
|
|
314
|
+
return [
|
|
315
|
+
kit.view.lineNumbers(),
|
|
316
|
+
kit.view.highlightSpecialChars(),
|
|
317
|
+
kit.language.bracketMatching(),
|
|
318
|
+
kit.language.syntaxHighlighting(kit.oneDark.oneDarkHighlightStyle),
|
|
319
|
+
kit.search.search({ top: true }),
|
|
320
|
+
kit.view.keymap.of([...kit.commands.standardKeymap, ...kit.search.searchKeymap]),
|
|
321
|
+
kit.view.EditorView.lineWrapping,
|
|
322
|
+
// A viewer, twice over: the state refuses writes and the view is not
|
|
323
|
+
// editable. Selection and copy still work; `tabindex` keeps the view
|
|
324
|
+
// focusable so mod-f reaches the search keymap.
|
|
325
|
+
kit.state.EditorState.readOnly.of(true),
|
|
326
|
+
kit.view.EditorView.editable.of(false),
|
|
327
|
+
kit.view.EditorView.contentAttributes.of({ tabindex: '0' }),
|
|
328
|
+
...languageExtension,
|
|
329
|
+
codeViewTheme(kit, fontSize, maxHeight),
|
|
330
|
+
];
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
export function CodeView({
|
|
334
|
+
value,
|
|
335
|
+
language,
|
|
336
|
+
fontSize = 11,
|
|
337
|
+
maxHeight,
|
|
338
|
+
ariaLabel,
|
|
339
|
+
followChanges = false,
|
|
340
|
+
}: {
|
|
341
|
+
readonly value: string;
|
|
342
|
+
readonly language: CodeViewLanguage;
|
|
343
|
+
readonly fontSize?: number;
|
|
344
|
+
readonly maxHeight?: number | string;
|
|
345
|
+
readonly ariaLabel?: string;
|
|
346
|
+
/** Reveal externally changed source without taking keyboard focus. */
|
|
347
|
+
readonly followChanges?: boolean;
|
|
348
|
+
}) {
|
|
349
|
+
const hostRef = useRef<HTMLDivElement>(null);
|
|
350
|
+
const viewRef = useRef<import('@codemirror/view').EditorView | null>(null);
|
|
351
|
+
const highlightRef = useRef<ReturnType<typeof createChangeHighlight> | null>(null);
|
|
352
|
+
const highlightTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
353
|
+
const revisionRef = useRef(0);
|
|
354
|
+
const valueRef = useRef(value);
|
|
355
|
+
valueRef.current = value;
|
|
356
|
+
const [kit, setKit] = useState<CodeMirrorKit | null>(null);
|
|
357
|
+
const [loadFailed, setLoadFailed] = useState(false);
|
|
358
|
+
|
|
359
|
+
useEffect(() => {
|
|
360
|
+
let cancelled = false;
|
|
361
|
+
void loadCodeMirror().then(
|
|
362
|
+
(loaded) => {
|
|
363
|
+
if (!cancelled) setKit(loaded);
|
|
364
|
+
},
|
|
365
|
+
() => {
|
|
366
|
+
// A viewer that cannot load its highlighter still shows the code: the
|
|
367
|
+
// plain-text fallback below stays, and says why rather than pretending
|
|
368
|
+
// an unhighlighted file is the finished view.
|
|
369
|
+
if (!cancelled) setLoadFailed(true);
|
|
370
|
+
},
|
|
371
|
+
);
|
|
372
|
+
return () => {
|
|
373
|
+
cancelled = true;
|
|
374
|
+
};
|
|
375
|
+
}, []);
|
|
376
|
+
|
|
377
|
+
useEffect(() => {
|
|
378
|
+
const host = hostRef.current;
|
|
379
|
+
if (!host || !kit) return;
|
|
380
|
+
const highlight = createChangeHighlight(kit);
|
|
381
|
+
const view = new kit.view.EditorView({
|
|
382
|
+
parent: host,
|
|
383
|
+
state: kit.state.EditorState.create({
|
|
384
|
+
doc: valueRef.current,
|
|
385
|
+
extensions: [codeViewExtensions(kit, language, fontSize, maxHeight), highlight.field],
|
|
386
|
+
}),
|
|
387
|
+
});
|
|
388
|
+
viewRef.current = view;
|
|
389
|
+
highlightRef.current = highlight;
|
|
390
|
+
return () => {
|
|
391
|
+
if (highlightTimer.current !== null) clearTimeout(highlightTimer.current);
|
|
392
|
+
highlightTimer.current = null;
|
|
393
|
+
highlightRef.current = null;
|
|
394
|
+
viewRef.current = null;
|
|
395
|
+
view.destroy();
|
|
396
|
+
};
|
|
397
|
+
}, [kit, language, fontSize, maxHeight]);
|
|
398
|
+
|
|
399
|
+
useEffect(() => {
|
|
400
|
+
const view = viewRef.current;
|
|
401
|
+
if (!view) return;
|
|
402
|
+
// Use CodeMirror's line endings for both sides of the diff. Its document
|
|
403
|
+
// offsets do not include the extra carriage returns in Windows files.
|
|
404
|
+
const nextValue = view.state.toText(value).toString();
|
|
405
|
+
const previous = view.state.doc.toString();
|
|
406
|
+
if (previous === nextValue) return;
|
|
407
|
+
const { from, oldEnd, newEnd } = changedSourceRange(previous, nextValue);
|
|
408
|
+
const changes = view.state.changes({ from, to: oldEnd, insert: nextValue.slice(from, newEnd) });
|
|
409
|
+
const highlight = highlightRef.current;
|
|
410
|
+
const effects: import('@codemirror/state').StateEffect<unknown>[] = [];
|
|
411
|
+
if (followChanges && kit && highlight) {
|
|
412
|
+
const point = view.coordsAtPos(from);
|
|
413
|
+
const viewport = view.scrollDOM.getBoundingClientRect();
|
|
414
|
+
const visible =
|
|
415
|
+
point &&
|
|
416
|
+
point.top >= viewport.top &&
|
|
417
|
+
point.bottom <= viewport.bottom &&
|
|
418
|
+
point.left >= viewport.left &&
|
|
419
|
+
point.right <= viewport.right;
|
|
420
|
+
// Preserve the reading position explicitly for a visible edit, including
|
|
421
|
+
// when replacement text changes line wrapping. Reveal only unseen edits.
|
|
422
|
+
const scroll = visible
|
|
423
|
+
? view.scrollSnapshot().map(changes)
|
|
424
|
+
: kit.view.EditorView.scrollIntoView(from, { y: 'nearest', x: 'nearest' });
|
|
425
|
+
if (scroll) effects.push(scroll);
|
|
426
|
+
effects.push(highlight.mark.of({ from, to: newEnd, revision: ++revisionRef.current }));
|
|
427
|
+
} else if (highlight) {
|
|
428
|
+
effects.push(highlight.mark.of(null));
|
|
429
|
+
}
|
|
430
|
+
view.dispatch({ changes, effects });
|
|
431
|
+
if (highlightTimer.current !== null) clearTimeout(highlightTimer.current);
|
|
432
|
+
highlightTimer.current = null;
|
|
433
|
+
if (followChanges && highlight) {
|
|
434
|
+
highlightTimer.current = setTimeout(() => {
|
|
435
|
+
if (viewRef.current === view) view.dispatch({ effects: highlight.mark.of(null) });
|
|
436
|
+
highlightTimer.current = null;
|
|
437
|
+
}, SOURCE_CHANGE_DURATION_MS);
|
|
438
|
+
}
|
|
439
|
+
}, [value, followChanges, kit]);
|
|
440
|
+
|
|
441
|
+
const fill = fillsItsBox(maxHeight) ? { height: '100%', minHeight: 0 } : {};
|
|
442
|
+
if (!kit) {
|
|
443
|
+
return (
|
|
444
|
+
<div role="group" aria-label={ariaLabel} style={{ minWidth: 0, ...fill }}>
|
|
445
|
+
{loadFailed && (
|
|
446
|
+
<div style={{ color: themeVars.semantic.warning, fontSize: 10, marginBottom: 4 }}>
|
|
447
|
+
Syntax highlighting failed to load — showing plain text.
|
|
448
|
+
</div>
|
|
449
|
+
)}
|
|
450
|
+
<pre
|
|
451
|
+
style={{
|
|
452
|
+
margin: 0,
|
|
453
|
+
fontFamily: themeVars.typography.mono,
|
|
454
|
+
fontSize,
|
|
455
|
+
lineHeight: 1.5,
|
|
456
|
+
color: themeVars.content.primary,
|
|
457
|
+
whiteSpace: 'pre-wrap',
|
|
458
|
+
wordBreak: 'break-word',
|
|
459
|
+
overflow: 'auto',
|
|
460
|
+
...(maxHeight === undefined ? {} : { maxHeight: cssLength(maxHeight) }),
|
|
461
|
+
...(fillsItsBox(maxHeight) ? { height: cssLength(maxHeight) } : {}),
|
|
462
|
+
}}
|
|
463
|
+
>
|
|
464
|
+
{value}
|
|
465
|
+
</pre>
|
|
466
|
+
</div>
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
return <div ref={hostRef} role="group" aria-label={ariaLabel} style={{ minWidth: 0, ...fill }} />;
|
|
470
|
+
}
|