@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,775 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Live-DOM inspection helpers (Cap 1 of the React visual-edit parity port). These are
|
|
3
|
+
* `../../../visual-edit/preload.ts`'s inspection FUNCTIONS ported as DIRECT-CALL helpers.
|
|
4
|
+
*
|
|
5
|
+
* The no-iframe adaptation (see the parity spec): visual-edit injects `preload.ts` into
|
|
6
|
+
* an iframe and inspects the target app across a `postMessage` bridge. vgai mounts React
|
|
7
|
+
* roots as DOM layers in the SAME document and `ReactRootAuthoringAdapter` already holds
|
|
8
|
+
* the live root — so these run against the live element directly, no iframe/bridge.
|
|
9
|
+
*
|
|
10
|
+
* Headless-testable: none of these reach for a DOM global unconditionally. Fiber reads
|
|
11
|
+
* work on any object carrying a `__reactFiber$…` key (a plain fixture satisfies it).
|
|
12
|
+
* `getComputedStyles` takes a resolver (defaulting to `window.getComputedStyle` in a real
|
|
13
|
+
* browser, or the element's inline `.style` under vitest's `node` env — no jsdom).
|
|
14
|
+
* `getMatchedCssRules` takes its stylesheet list (defaulting to `document.styleSheets`).
|
|
15
|
+
*
|
|
16
|
+
* C4 (spec §9) fiber-access contract: `__reactFiber$…`/`__reactInternalInstance$…` are
|
|
17
|
+
* React's OWN internal instance keys — never a documented, versioned public API (the
|
|
18
|
+
* exact prefix has changed across React major versions, and nothing guarantees it won't
|
|
19
|
+
* again). `findFiber` therefore treats a missing/renamed key as an ORDINARY, expected
|
|
20
|
+
* outcome, not an error: it returns `null` rather than throwing, and every caller
|
|
21
|
+
* (`getReactComponentName`, `getCallSiteOid`, `readFiberProps`, `getComponentProps`) is
|
|
22
|
+
* `null`-safe from there. The one caller-visible fallback this enables is
|
|
23
|
+
* `getEffectiveOid`: call-site OID (from the fiber) when available, else the element's
|
|
24
|
+
* own `data-oid` DOM attribute — i.e. inspection degrades to DOM-only (oid/selection
|
|
25
|
+
* still work; component-name/props enrichment silently disappears) instead of failing.
|
|
26
|
+
* Covered by `ui-source-inspect.test.ts`'s "no fiber" case (a plain DOM-shaped fixture
|
|
27
|
+
* with no `__reactFiber$…` key at all, simulating both "fiber absent" and "key renamed").
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
import { warnGuessedFromText } from '../inference-diagnostics';
|
|
31
|
+
|
|
32
|
+
const OID_ATTR = 'data-oid';
|
|
33
|
+
|
|
34
|
+
/** The ~70 most-edited CSS properties visual-edit's `getComputedStyles` captures (:73). */
|
|
35
|
+
export const COMPUTED_STYLE_PROPS: readonly string[] = [
|
|
36
|
+
'width',
|
|
37
|
+
'height',
|
|
38
|
+
'minWidth',
|
|
39
|
+
'minHeight',
|
|
40
|
+
'maxWidth',
|
|
41
|
+
'maxHeight',
|
|
42
|
+
'margin',
|
|
43
|
+
'marginTop',
|
|
44
|
+
'marginRight',
|
|
45
|
+
'marginBottom',
|
|
46
|
+
'marginLeft',
|
|
47
|
+
'padding',
|
|
48
|
+
'paddingTop',
|
|
49
|
+
'paddingRight',
|
|
50
|
+
'paddingBottom',
|
|
51
|
+
'paddingLeft',
|
|
52
|
+
'display',
|
|
53
|
+
'flexDirection',
|
|
54
|
+
'flexWrap',
|
|
55
|
+
'justifyContent',
|
|
56
|
+
'alignItems',
|
|
57
|
+
'gap',
|
|
58
|
+
'flexGrow',
|
|
59
|
+
'flexShrink',
|
|
60
|
+
'flexBasis',
|
|
61
|
+
'alignSelf',
|
|
62
|
+
'position',
|
|
63
|
+
'top',
|
|
64
|
+
'right',
|
|
65
|
+
'bottom',
|
|
66
|
+
'left',
|
|
67
|
+
'backgroundColor',
|
|
68
|
+
'backgroundImage',
|
|
69
|
+
'color',
|
|
70
|
+
'fontSize',
|
|
71
|
+
'fontWeight',
|
|
72
|
+
'fontFamily',
|
|
73
|
+
'borderRadius',
|
|
74
|
+
'borderTopLeftRadius',
|
|
75
|
+
'borderTopRightRadius',
|
|
76
|
+
'borderBottomLeftRadius',
|
|
77
|
+
'borderBottomRightRadius',
|
|
78
|
+
'border',
|
|
79
|
+
'borderWidth',
|
|
80
|
+
'borderColor',
|
|
81
|
+
'borderStyle',
|
|
82
|
+
'borderTopWidth',
|
|
83
|
+
'borderRightWidth',
|
|
84
|
+
'borderBottomWidth',
|
|
85
|
+
'borderLeftWidth',
|
|
86
|
+
'borderTopStyle',
|
|
87
|
+
'borderRightStyle',
|
|
88
|
+
'borderBottomStyle',
|
|
89
|
+
'borderLeftStyle',
|
|
90
|
+
'borderTopColor',
|
|
91
|
+
'borderRightColor',
|
|
92
|
+
'borderBottomColor',
|
|
93
|
+
'borderLeftColor',
|
|
94
|
+
'opacity',
|
|
95
|
+
'overflow',
|
|
96
|
+
'zIndex',
|
|
97
|
+
'transform',
|
|
98
|
+
'mixBlendMode',
|
|
99
|
+
'filter',
|
|
100
|
+
'backdropFilter',
|
|
101
|
+
'textShadow',
|
|
102
|
+
'boxShadow',
|
|
103
|
+
'textAlign',
|
|
104
|
+
'lineHeight',
|
|
105
|
+
'letterSpacing',
|
|
106
|
+
'textTransform',
|
|
107
|
+
'textDecoration',
|
|
108
|
+
'whiteSpace',
|
|
109
|
+
'wordWrap',
|
|
110
|
+
'cursor',
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
/** camelCase CSS prop -> kebab-case (`fontSize` -> `font-size`). */
|
|
114
|
+
export function camelToKebab(prop: string): string {
|
|
115
|
+
return prop.replace(/([A-Z])/g, '-$1').toLowerCase();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** kebab-case CSS prop -> camelCase (`font-size` -> `fontSize`). */
|
|
119
|
+
export function kebabToCamel(prop: string): string {
|
|
120
|
+
return prop.replace(/-([a-z])/g, (_, c: string) => c.toUpperCase());
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** The minimal shape a resolved computed-style value source needs. A real
|
|
124
|
+
* `CSSStyleDeclaration` satisfies this structurally. */
|
|
125
|
+
export interface ComputedStyleLike {
|
|
126
|
+
getPropertyValue(prop: string): string;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Resolves an element to a `getPropertyValue`-capable style source (kebab keys). */
|
|
130
|
+
export type ComputedStyleResolver = (el: unknown) => ComputedStyleLike;
|
|
131
|
+
|
|
132
|
+
/** Read one inline style property off an element's `.style` of either shape (a real
|
|
133
|
+
* `CSSStyleDeclaration` or a plain-object test fixture) — the same read
|
|
134
|
+
* `react-world-authoring-adapter.ts` uses. */
|
|
135
|
+
function inlineStyleProp(style: unknown, prop: string): unknown {
|
|
136
|
+
return style ? (style as Record<string, unknown>)[prop] : undefined;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* The default resolver: real `window.getComputedStyle` in a browser (so CLASS-styled
|
|
141
|
+
* and CSS-file-styled properties resolve, fixing the "class-styled props show blank"
|
|
142
|
+
* bug), or — under vitest's `node` env (no `window`) — a shim reading the element's
|
|
143
|
+
* inline `.style` object, so headless fixtures keep working unchanged.
|
|
144
|
+
*/
|
|
145
|
+
export const browserOrInlineResolver: ComputedStyleResolver = (el) => {
|
|
146
|
+
const w = (globalThis as { window?: { getComputedStyle?: (e: unknown) => ComputedStyleLike } })
|
|
147
|
+
.window;
|
|
148
|
+
if (w?.getComputedStyle) return w.getComputedStyle(el);
|
|
149
|
+
const style = (el as { style?: unknown }).style;
|
|
150
|
+
return { getPropertyValue: (k: string) => String(inlineStyleProp(style, kebabToCamel(k)) ?? '') };
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Capture the commonly-edited computed styles of an element as a camelCase-keyed record
|
|
155
|
+
* (visual-edit `getComputedStyles` :73). The resolver is injectable for headless tests;
|
|
156
|
+
* the default resolves against the live browser DOM (or inline style under `node`).
|
|
157
|
+
*/
|
|
158
|
+
export function getComputedStyles(
|
|
159
|
+
el: unknown,
|
|
160
|
+
resolve: ComputedStyleResolver = browserOrInlineResolver,
|
|
161
|
+
): Record<string, string> {
|
|
162
|
+
const cs = resolve(el);
|
|
163
|
+
const result: Record<string, string> = {};
|
|
164
|
+
for (const p of COMPUTED_STYLE_PROPS) result[p] = cs.getPropertyValue(camelToKebab(p));
|
|
165
|
+
return result;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Read a single computed style property (camelCase), via the same resolver. */
|
|
169
|
+
export function getComputedStyleValue(
|
|
170
|
+
el: unknown,
|
|
171
|
+
prop: string,
|
|
172
|
+
resolve: ComputedStyleResolver = browserOrInlineResolver,
|
|
173
|
+
): string {
|
|
174
|
+
return resolve(el).getPropertyValue(camelToKebab(prop));
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// --- React fiber inspection (visual-edit preload.ts :110/:134/:158) ---
|
|
178
|
+
|
|
179
|
+
/** A minimal fiber node shape — enough for the reads below (`preload.ts` uses `any`). */
|
|
180
|
+
interface FiberLike {
|
|
181
|
+
return?: FiberLike | null;
|
|
182
|
+
type?: unknown;
|
|
183
|
+
memoizedProps?: Record<string, unknown> | null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Find the React fiber attached to a DOM element (React 18+ `__reactFiber$…`, older
|
|
187
|
+
* `__reactInternalInstance$…`). Works on any object carrying such a key — a plain
|
|
188
|
+
* fixture with `{ __reactFiber$x: {...} }` satisfies it headlessly. */
|
|
189
|
+
export function findFiber(el: unknown): FiberLike | null {
|
|
190
|
+
if (!el || typeof el !== 'object') return null;
|
|
191
|
+
const key = Object.keys(el as object).find(
|
|
192
|
+
(k) => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$'),
|
|
193
|
+
);
|
|
194
|
+
if (!key) return null;
|
|
195
|
+
return ((el as Record<string, unknown>)[key] as FiberLike) ?? null;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** The parent fiber IF this element is the ROOT element of a function component
|
|
199
|
+
* (`fiber.return` points straight at the component fiber). Else null. */
|
|
200
|
+
function componentParentFiber(el: unknown): FiberLike | null {
|
|
201
|
+
const fiber = findFiber(el);
|
|
202
|
+
if (!fiber?.return) return null;
|
|
203
|
+
const parent = fiber.return;
|
|
204
|
+
return parent.type && typeof parent.type === 'function' ? parent : null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Nearest component name for an element that is a component's root element
|
|
208
|
+
* (visual-edit `getReactComponentName` :110). */
|
|
209
|
+
export function getReactComponentName(el: unknown): string | null {
|
|
210
|
+
const parent = componentParentFiber(el);
|
|
211
|
+
if (!parent) return null;
|
|
212
|
+
const type = parent.type as { displayName?: string; name?: string };
|
|
213
|
+
return type.displayName || type.name || null;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** The call-site `data-oid` prop passed to a component root (`<StatCard data-oid="x"/>`)
|
|
217
|
+
* read off the component fiber's props (visual-edit `getCallSiteOid` :134). */
|
|
218
|
+
export function getCallSiteOid(el: unknown): string | null {
|
|
219
|
+
const parent = componentParentFiber(el);
|
|
220
|
+
if (!parent) return null;
|
|
221
|
+
const v = parent.memoizedProps?.[OID_ATTR];
|
|
222
|
+
return typeof v === 'string' ? v : null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** Call-site OID for component roots, else the element's own `data-oid`
|
|
226
|
+
* (visual-edit `getEffectiveOid` :148). */
|
|
227
|
+
export function getEffectiveOid(el: { getAttribute?(name: string): string | null }): string | null {
|
|
228
|
+
return getCallSiteOid(el) ?? el.getAttribute?.(OID_ATTR) ?? null;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** Primitive (string/number/boolean) props of a component root, stringified
|
|
232
|
+
* (visual-edit `readFiberProps` :158). Skips children/key/ref/data-oid/style/className
|
|
233
|
+
* and any non-primitive value. Returns null when there are none. */
|
|
234
|
+
export function readFiberProps(el: unknown): Record<string, string> | null {
|
|
235
|
+
const parent = componentParentFiber(el);
|
|
236
|
+
if (!parent) return null;
|
|
237
|
+
const props = parent.memoizedProps;
|
|
238
|
+
if (!props || typeof props !== 'object') return null;
|
|
239
|
+
|
|
240
|
+
const SKIP = new Set(['children', 'key', 'ref', OID_ATTR, 'style', 'className']);
|
|
241
|
+
const result: Record<string, string> = {};
|
|
242
|
+
for (const [key, value] of Object.entries(props)) {
|
|
243
|
+
if (SKIP.has(key)) continue;
|
|
244
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
245
|
+
result[key] = String(value);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** The component's call-site OID + its editable primitive props, or null if the element
|
|
252
|
+
* is not a component root with props (visual-edit `getComponentProps` :463). Cap 4 feeds
|
|
253
|
+
* the Props inspector section from this. */
|
|
254
|
+
export function getComponentProps(
|
|
255
|
+
el: { getAttribute?(name: string): string | null } & unknown,
|
|
256
|
+
): { callSiteOid: string; props: Record<string, string> } | null {
|
|
257
|
+
const callSiteOid = getCallSiteOid(el);
|
|
258
|
+
if (!callSiteOid) return null;
|
|
259
|
+
const props = readFiberProps(el);
|
|
260
|
+
if (!props) return null;
|
|
261
|
+
return { callSiteOid, props };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// --- Matched CSS rules (visual-edit preload.ts getMatchedCssRules :473) ---
|
|
265
|
+
|
|
266
|
+
export interface MatchedCssRule {
|
|
267
|
+
selectorText: string;
|
|
268
|
+
properties: Record<string, string>;
|
|
269
|
+
/** The source file the owning `<style>`/`<link>` traces to (via `data-vite-dev-id`). */
|
|
270
|
+
sourceFile: string;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** The minimal element shape needed to trace matched rules — `matches(selector)`. */
|
|
274
|
+
export interface MatchableElement {
|
|
275
|
+
matches(selector: string): boolean;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** A structural stand-in for a `CSSStyleRule` (headless-testable). */
|
|
279
|
+
export interface StyleRuleLike {
|
|
280
|
+
selectorText: string;
|
|
281
|
+
style: { length: number; getPropertyValue(prop: string): string; [index: number]: string };
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** A structural stand-in for a `CSSStyleSheet` + its owner node. */
|
|
285
|
+
export interface StyleSheetLike {
|
|
286
|
+
ownerNode?: { id?: string; getAttribute?(name: string): string | null } | null;
|
|
287
|
+
cssRules: ArrayLike<unknown>;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** The id of visual-edit's own preview `<style>` tag — skipped when tracing rules. */
|
|
291
|
+
const PREVIEW_STYLE_TAG_ID = '__visual-edit-preview-styles';
|
|
292
|
+
|
|
293
|
+
/** Is this rule a style rule (vs `@media`/`@keyframes`)? Uses `CSSStyleRule` when the DOM
|
|
294
|
+
* provides it, else a structural check so headless fixtures work. */
|
|
295
|
+
function isStyleRule(rule: unknown): rule is StyleRuleLike {
|
|
296
|
+
const CSR = (globalThis as { CSSStyleRule?: unknown }).CSSStyleRule;
|
|
297
|
+
if (typeof CSR === 'function') return rule instanceof (CSR as new () => unknown);
|
|
298
|
+
const r = rule as Partial<StyleRuleLike>;
|
|
299
|
+
return !!r && typeof r.selectorText === 'string' && !!r.style;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** Read every declared property off a style rule's declaration block. */
|
|
303
|
+
function readRuleProperties(rule: StyleRuleLike): Record<string, string> {
|
|
304
|
+
const properties: Record<string, string> = {};
|
|
305
|
+
for (let i = 0; i < rule.style.length; i++) {
|
|
306
|
+
const prop = rule.style[i] as string;
|
|
307
|
+
properties[prop] = rule.style.getPropertyValue(prop);
|
|
308
|
+
}
|
|
309
|
+
return properties;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Trace the CSS rules from first-party stylesheets that MATCH an element, keyed back to
|
|
314
|
+
* their source file via the owner node's `data-vite-dev-id` (visual-edit
|
|
315
|
+
* `getMatchedCssRules` :473). Only rules from a stylesheet with a `data-vite-dev-id`
|
|
316
|
+
* (i.e. a real source file Vite is serving) are returned — Cap 2 edits those files.
|
|
317
|
+
* Sheets default to `document.styleSheets`; injectable for headless tests.
|
|
318
|
+
*/
|
|
319
|
+
/**
|
|
320
|
+
* Walk every STYLE rule of every first-party stylesheet (one with a
|
|
321
|
+
* `data-vite-dev-id` — a real source file Vite is serving), DESCENDING grouping
|
|
322
|
+
* rules. Descent is the load-bearing half: the dev server wraps a project
|
|
323
|
+
* stylesheet's whole body in `@scope ([data-vgai-game-styles]) { … }`
|
|
324
|
+
* (server/scoped-game-css.ts), so in the served CSSOM every project rule is a
|
|
325
|
+
* grouping-rule CHILD — a top-level-only walk sees none of them, which is
|
|
326
|
+
* exactly why the Cap-2 cascade route never fired for scoped game CSS. A
|
|
327
|
+
* `@media` group is only entered when its condition currently HOLDS
|
|
328
|
+
* (`matchMedia`): a rule inside a non-matching breakpoint is not in cascade
|
|
329
|
+
* and must not be offered as an edit target.
|
|
330
|
+
*/
|
|
331
|
+
function visitFirstPartyStyleRules(
|
|
332
|
+
sheets: Iterable<StyleSheetLike>,
|
|
333
|
+
visit: (rule: StyleRuleLike, sourceFile: string) => void,
|
|
334
|
+
): void {
|
|
335
|
+
const mm = (globalThis as { matchMedia?: (q: string) => { matches: boolean } }).matchMedia;
|
|
336
|
+
const walk = (rules: ArrayLike<unknown>, sourceFile: string): void => {
|
|
337
|
+
for (const rule of Array.from(rules)) {
|
|
338
|
+
if (isStyleRule(rule)) {
|
|
339
|
+
visit(rule, sourceFile);
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
const group = rule as {
|
|
343
|
+
cssRules?: ArrayLike<unknown>;
|
|
344
|
+
media?: { mediaText?: string };
|
|
345
|
+
containerQuery?: unknown;
|
|
346
|
+
cssText?: string;
|
|
347
|
+
};
|
|
348
|
+
if (!group.cssRules) continue;
|
|
349
|
+
const mediaText = group.media?.mediaText;
|
|
350
|
+
if (typeof mediaText === 'string' && mm && !mm(mediaText).matches) continue;
|
|
351
|
+
// A @container group is a BREAKPOINT scope (the serve-time responsive
|
|
352
|
+
// preview rewrites width @media into these). Whether it applies depends
|
|
353
|
+
// on each frame's own size — unanswerable from this element-independent
|
|
354
|
+
// walk — and offering its rules as silent cascade targets would route a
|
|
355
|
+
// BASE edit into a breakpoint. Breakpoint writes take the explicit
|
|
356
|
+
// media-scoped door instead.
|
|
357
|
+
if (
|
|
358
|
+
typeof group.containerQuery === 'string' ||
|
|
359
|
+
group.cssText?.trimStart().startsWith('@container')
|
|
360
|
+
)
|
|
361
|
+
continue;
|
|
362
|
+
walk(group.cssRules, sourceFile);
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
for (const sheet of sheets) {
|
|
366
|
+
const owner = sheet.ownerNode;
|
|
367
|
+
if (owner?.id === PREVIEW_STYLE_TAG_ID) continue;
|
|
368
|
+
const sourceFile = owner?.getAttribute?.('data-vite-dev-id') ?? null;
|
|
369
|
+
if (!sourceFile) continue;
|
|
370
|
+
try {
|
|
371
|
+
walk(sheet.cssRules, sourceFile);
|
|
372
|
+
} catch {
|
|
373
|
+
// Cross-origin stylesheet — its `cssRules` throws; skip it (same as visual-edit).
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/** Where a named style (a single-class rule `.name`) is declared, if any
|
|
379
|
+
* first-party stylesheet declares one — the fact that decides APPLY (the
|
|
380
|
+
* class exists, add the token) vs CREATE (write a new rule). Later sheets
|
|
381
|
+
* win, matching cascade order. */
|
|
382
|
+
export function findClassRuleSource(
|
|
383
|
+
className: string,
|
|
384
|
+
sheets: Iterable<StyleSheetLike> = (
|
|
385
|
+
globalThis as { document?: { styleSheets?: Iterable<StyleSheetLike> } }
|
|
386
|
+
).document?.styleSheets ?? [],
|
|
387
|
+
): { sourceFile: string } | null {
|
|
388
|
+
let found: { sourceFile: string } | null = null;
|
|
389
|
+
visitFirstPartyStyleRules(sheets, (rule, sourceFile) => {
|
|
390
|
+
if (rule.selectorText.trim() === `.${className}`) found = { sourceFile };
|
|
391
|
+
});
|
|
392
|
+
return found;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** The distinct first-party stylesheet source files currently serving CSS, in
|
|
396
|
+
* document order — the candidate homes for a NEW named-style rule when no
|
|
397
|
+
* matched rule already names one. */
|
|
398
|
+
export function firstPartyStylesheetFiles(
|
|
399
|
+
sheets: Iterable<StyleSheetLike> = (
|
|
400
|
+
globalThis as { document?: { styleSheets?: Iterable<StyleSheetLike> } }
|
|
401
|
+
).document?.styleSheets ?? [],
|
|
402
|
+
): string[] {
|
|
403
|
+
const files: string[] = [];
|
|
404
|
+
for (const sheet of sheets) {
|
|
405
|
+
const owner = sheet.ownerNode;
|
|
406
|
+
if (owner?.id === PREVIEW_STYLE_TAG_ID) continue;
|
|
407
|
+
const sourceFile = owner?.getAttribute?.('data-vite-dev-id') ?? null;
|
|
408
|
+
if (!sourceFile) continue;
|
|
409
|
+
const clean = sourceFile.split('?')[0] ?? sourceFile;
|
|
410
|
+
if (clean.endsWith('.css') && !files.includes(sourceFile)) files.push(sourceFile);
|
|
411
|
+
}
|
|
412
|
+
return files;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export function getMatchedCssRules(
|
|
416
|
+
el: MatchableElement,
|
|
417
|
+
sheets: Iterable<StyleSheetLike> = (
|
|
418
|
+
globalThis as { document?: { styleSheets?: Iterable<StyleSheetLike> } }
|
|
419
|
+
).document?.styleSheets ?? [],
|
|
420
|
+
): MatchedCssRule[] {
|
|
421
|
+
const matched: MatchedCssRule[] = [];
|
|
422
|
+
visitFirstPartyStyleRules(sheets, (rule, sourceFile) => {
|
|
423
|
+
if (el.matches(rule.selectorText)) {
|
|
424
|
+
matched.push({
|
|
425
|
+
selectorText: rule.selectorText,
|
|
426
|
+
properties: readRuleProperties(rule),
|
|
427
|
+
sourceFile,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
return matched;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// --- Design tokens (visual-edit preload.ts getDesignTokens :506) — Cap 7 ---
|
|
435
|
+
|
|
436
|
+
export interface DesignToken {
|
|
437
|
+
name: string;
|
|
438
|
+
value: string;
|
|
439
|
+
category: 'color' | 'spacing' | 'other';
|
|
440
|
+
/**
|
|
441
|
+
* WHERE the token is declared, when a project stylesheet rule declares it —
|
|
442
|
+
* the write address `writeCss(file, selector, --name, value)` targets, which
|
|
443
|
+
* is what upgrades the token's inspector row from read-only to editable. A
|
|
444
|
+
* token with no declaration trace (set inline on `:root` by script — e.g. a
|
|
445
|
+
* theme data module mirroring itself, or an inherited host style) stays
|
|
446
|
+
* read-only, and its EDIT door is the declaring source itself.
|
|
447
|
+
*/
|
|
448
|
+
declaredIn?: { sourceFile: string; selector: string };
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Trace `:root`-scope custom-property DECLARATIONS to their stylesheet
|
|
453
|
+
* source (`data-vite-dev-id`, the same trace {@link getMatchedCssRules}
|
|
454
|
+
* uses). Later declarations win, matching the cascade for equal-specificity
|
|
455
|
+
* `:root` rules. Rules under `[data-theme]`/media scopes are deliberately
|
|
456
|
+
* NOT the base declaration — modes override the base; the base row is what
|
|
457
|
+
* a token edit writes.
|
|
458
|
+
*/
|
|
459
|
+
export function traceTokenDeclarations(
|
|
460
|
+
sheets: Iterable<StyleSheetLike> = (
|
|
461
|
+
globalThis as { document?: { styleSheets?: Iterable<StyleSheetLike> } }
|
|
462
|
+
).document?.styleSheets ?? [],
|
|
463
|
+
): Map<string, { sourceFile: string; selector: string }> {
|
|
464
|
+
const out = new Map<string, { sourceFile: string; selector: string }>();
|
|
465
|
+
const visit = (rule: unknown, sourceFile: string, inScope: boolean): void => {
|
|
466
|
+
if (isStyleRule(rule)) {
|
|
467
|
+
const selector = rule.selectorText;
|
|
468
|
+
// The dev server rewrites a project stylesheet's `:root { … }` into
|
|
469
|
+
// `@scope ([data-vgai-game-styles]) { :scope { … } }` (measured), so a
|
|
470
|
+
// scope-wrapped `:scope` IS a `:root` declaration — and the recorded
|
|
471
|
+
// write address is the SOURCE's `:root`, because the css writer edits
|
|
472
|
+
// source text, not the served rewrite.
|
|
473
|
+
const scopeBase = inScope && /(^|,)\s*:scope\s*($|,)/.test(selector);
|
|
474
|
+
const rootBase =
|
|
475
|
+
/(^|,)\s*(:root|html)\s*($|,)/.test(selector) && !selector.includes('[data-theme');
|
|
476
|
+
if (!scopeBase && !rootBase) return;
|
|
477
|
+
for (let i = 0; i < rule.style.length; i++) {
|
|
478
|
+
const prop = rule.style[i]!;
|
|
479
|
+
if (!prop.startsWith('--')) continue;
|
|
480
|
+
out.set(prop, { sourceFile, selector: scopeBase ? ':root' : selector });
|
|
481
|
+
}
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
const group = rule as { cssRules?: ArrayLike<unknown>; cssText?: string };
|
|
485
|
+
if (!group.cssRules) return;
|
|
486
|
+
const scoped = inScope || Boolean(group.cssText?.trimStart().startsWith('@scope'));
|
|
487
|
+
for (const child of Array.from(group.cssRules)) visit(child, sourceFile, scoped);
|
|
488
|
+
};
|
|
489
|
+
for (const sheet of sheets) {
|
|
490
|
+
const owner = sheet.ownerNode;
|
|
491
|
+
if (owner?.id === PREVIEW_STYLE_TAG_ID) continue;
|
|
492
|
+
const sourceFile = owner?.getAttribute?.('data-vite-dev-id') ?? null;
|
|
493
|
+
if (!sourceFile) continue;
|
|
494
|
+
try {
|
|
495
|
+
for (const rule of Array.from(sheet.cssRules)) visit(rule, sourceFile, false);
|
|
496
|
+
} catch {
|
|
497
|
+
// Cross-origin stylesheet — its `cssRules` throws; skip it.
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return out;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Enumerate the `:root` CSS custom properties (design tokens) resolved on the document
|
|
505
|
+
* root, classified color/spacing/other (visual-edit `getDesignTokens` :506). Captures
|
|
506
|
+
* Tailwind v4 `@theme`/`oklch` vars; skips Tailwind internal `--tw-*`, Font
|
|
507
|
+
* Awesome internals, and the editor chrome's reserved `--vgai-*` namespace.
|
|
508
|
+
* The latter is infrastructure inherited from the editor host, never authored
|
|
509
|
+
* game data. The computed declaration is injectable for headless tests
|
|
510
|
+
* (defaults to the live `:root`).
|
|
511
|
+
*/
|
|
512
|
+
export function getDesignTokens(
|
|
513
|
+
computed: (ComputedStyleLike & ArrayLike<string>) | undefined = readRootComputed(),
|
|
514
|
+
): DesignToken[] {
|
|
515
|
+
if (!computed) return [];
|
|
516
|
+
const tokens: DesignToken[] = [];
|
|
517
|
+
const seen = new Set<string>();
|
|
518
|
+
for (let i = 0; i < computed.length; i++) {
|
|
519
|
+
const name = computed[i] as string;
|
|
520
|
+
if (
|
|
521
|
+
!name.startsWith('--') ||
|
|
522
|
+
name.startsWith('--tw-') ||
|
|
523
|
+
name.startsWith('--fa-') ||
|
|
524
|
+
name.startsWith('--vgai-') ||
|
|
525
|
+
// Code-OSS theme tokens inherit into game roots but belong to the host.
|
|
526
|
+
name.startsWith('--vscode-') ||
|
|
527
|
+
name === '--chat-input-control-height' ||
|
|
528
|
+
// The `--dv-*` chrome variables inherit from the editor shell into
|
|
529
|
+
// every game-CSS scope root, so a board's token read sees them
|
|
530
|
+
// (measured: 15 heuristic warnings per board open). Editor chrome, not
|
|
531
|
+
// game data — same exclusion as `--vgai-*`.
|
|
532
|
+
name.startsWith('--dv-') ||
|
|
533
|
+
seen.has(name)
|
|
534
|
+
)
|
|
535
|
+
continue;
|
|
536
|
+
seen.add(name);
|
|
537
|
+
const value = computed.getPropertyValue(name).trim();
|
|
538
|
+
if (!value) continue;
|
|
539
|
+
tokens.push({ name, value, category: classifyToken(name, value) });
|
|
540
|
+
}
|
|
541
|
+
const declarations = traceTokenDeclarations();
|
|
542
|
+
// The indexed loop above only lists custom properties the SUPPLIED style
|
|
543
|
+
// declares directly — an element inside a game-CSS scope RESOLVES its
|
|
544
|
+
// inherited tokens (`getPropertyValue`) but does not ITERATE them
|
|
545
|
+
// (measured). The declaration trace supplies the missing names, so scoped
|
|
546
|
+
// game tokens enumerate wherever the caller's element can resolve them.
|
|
547
|
+
for (const name of declarations.keys()) {
|
|
548
|
+
if (seen.has(name) || name.startsWith('--tw-') || name.startsWith('--fa-')) continue;
|
|
549
|
+
if (
|
|
550
|
+
name.startsWith('--vgai-') ||
|
|
551
|
+
name.startsWith('--dv-') ||
|
|
552
|
+
name.startsWith('--vscode-') ||
|
|
553
|
+
name === '--chat-input-control-height'
|
|
554
|
+
)
|
|
555
|
+
continue;
|
|
556
|
+
seen.add(name);
|
|
557
|
+
const value = computed.getPropertyValue(name).trim();
|
|
558
|
+
if (!value) continue;
|
|
559
|
+
tokens.push({ name, value, category: classifyToken(name, value) });
|
|
560
|
+
}
|
|
561
|
+
// Best-effort declaration trace — a token with no traced rule simply has no
|
|
562
|
+
// `declaredIn`, which the inspector renders as read-only (see the field).
|
|
563
|
+
for (const token of tokens) {
|
|
564
|
+
const declared = declarations.get(token.name);
|
|
565
|
+
if (declared) token.declaredIn = declared;
|
|
566
|
+
}
|
|
567
|
+
return tokens;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
const COLOR_VALUE_RE = /^(#[0-9a-f]{3,8}|rgba?\(|hsla?\(|oklch\()/i;
|
|
571
|
+
const SPACING_NAME_RE = /spacing|gap|margin|padding|radius|size|width|height/i;
|
|
572
|
+
|
|
573
|
+
const COLOR_NAME_RE = /color/i;
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Classify a design token by its name + value (visual-edit `getDesignTokens`
|
|
577
|
+
* :524), in two rungs.
|
|
578
|
+
*
|
|
579
|
+
* The VALUE is ground truth: `oklch(…)`/`#rrggbb` IS a color, whatever the
|
|
580
|
+
* token is called. Only when the value settles nothing does the NAME decide —
|
|
581
|
+
* and that rung is a guess about someone else's naming convention
|
|
582
|
+
* (`--brand-colorway` is not a color; `--icon-size: 2` is not spacing if it is
|
|
583
|
+
* a count). The guess still stands, because a swatch for `--accent: red` is
|
|
584
|
+
* better than a text box; it is just no longer silent
|
|
585
|
+
* (ARCHITECTURE-CORE §The editor protocol, "Zero inference").
|
|
586
|
+
*
|
|
587
|
+
* `other` is not a guess — it is the honest "nothing said", and reports nothing.
|
|
588
|
+
*/
|
|
589
|
+
function classifyToken(name: string, value: string): DesignToken['category'] {
|
|
590
|
+
if (COLOR_VALUE_RE.test(value)) return 'color';
|
|
591
|
+
if (COLOR_NAME_RE.test(name)) {
|
|
592
|
+
warnGuessedFromText(':root', name, 'color');
|
|
593
|
+
return 'color';
|
|
594
|
+
}
|
|
595
|
+
if (SPACING_NAME_RE.test(name) && /^\d/.test(value)) {
|
|
596
|
+
warnGuessedFromText(':root', name, 'spacing');
|
|
597
|
+
return 'spacing';
|
|
598
|
+
}
|
|
599
|
+
return 'other';
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// --- Cap 8: UX-polish helpers (visual-edit preload.ts getElementsInRect :635 /
|
|
603
|
+
// getSnapTargets :592 / getEmptyContainers :563 / getColorAtPoint :667 /
|
|
604
|
+
// getAvailableFonts :677). Ported as pure/injectable direct-call helpers. ---
|
|
605
|
+
|
|
606
|
+
export interface Rect {
|
|
607
|
+
x: number;
|
|
608
|
+
y: number;
|
|
609
|
+
width: number;
|
|
610
|
+
height: number;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
/** Axis-aligned rectangle intersection test (edges from x/y/width/height). */
|
|
614
|
+
export function rectsIntersect(a: Rect, b: Rect): boolean {
|
|
615
|
+
if (a.x + a.width < b.x || a.x > b.x + b.width) return false;
|
|
616
|
+
if (a.y + a.height < b.y || a.y > b.y + b.height) return false;
|
|
617
|
+
return true;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/** A marquee candidate: an OID-tagged element's rect + the oids of its OID-tagged
|
|
621
|
+
* descendants (for the deepest-element filter). */
|
|
622
|
+
export interface MarqueeCandidate {
|
|
623
|
+
oid: string;
|
|
624
|
+
rect: Rect;
|
|
625
|
+
descendantOids: string[];
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Marquee-select: the OID elements intersecting `rect`, filtered to the DEEPEST matches —
|
|
630
|
+
* an element is dropped if any of its OID descendants also matched (visual-edit
|
|
631
|
+
* `getElementsInRect` :635). Zero-area candidates are ignored. Pure; the browser wrapper
|
|
632
|
+
* builds candidates from `document.querySelectorAll('[data-oid]')`.
|
|
633
|
+
*/
|
|
634
|
+
export function getElementsInRect(
|
|
635
|
+
rect: Rect,
|
|
636
|
+
candidates: readonly MarqueeCandidate[],
|
|
637
|
+
): { oid: string; rect: Rect }[] {
|
|
638
|
+
const hit = candidates.filter(
|
|
639
|
+
(c) => (c.rect.width > 0 || c.rect.height > 0) && rectsIntersect(c.rect, rect),
|
|
640
|
+
);
|
|
641
|
+
const hitOids = new Set(hit.map((c) => c.oid));
|
|
642
|
+
return hit
|
|
643
|
+
.filter((c) => !c.descendantOids.some((d) => d !== c.oid && hitOids.has(d)))
|
|
644
|
+
.map((c) => ({ oid: c.oid, rect: c.rect }));
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/** Per-side padding of a container (px). */
|
|
648
|
+
export interface Padding {
|
|
649
|
+
top: number;
|
|
650
|
+
right: number;
|
|
651
|
+
bottom: number;
|
|
652
|
+
left: number;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Snap targets for dragging a child: the parent's PADDING box + its other children's rects
|
|
657
|
+
* (visual-edit `getSnapTargets` :592). Pure geometry.
|
|
658
|
+
*/
|
|
659
|
+
export function computeSnapTargets(
|
|
660
|
+
parentRect: Rect,
|
|
661
|
+
padding: Padding,
|
|
662
|
+
siblingRects: readonly Rect[],
|
|
663
|
+
): { paddingBox: Rect; siblingRects: Rect[] } {
|
|
664
|
+
return {
|
|
665
|
+
paddingBox: {
|
|
666
|
+
x: parentRect.x + padding.left,
|
|
667
|
+
y: parentRect.y + padding.top,
|
|
668
|
+
width: parentRect.width - padding.left - padding.right,
|
|
669
|
+
height: parentRect.height - padding.top - padding.bottom,
|
|
670
|
+
},
|
|
671
|
+
siblingRects: siblingRects.filter((r) => r.width > 0 && r.height > 0),
|
|
672
|
+
};
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
/** An empty-container candidate (an OID element with no visible children/text). */
|
|
676
|
+
export interface EmptyCandidate {
|
|
677
|
+
oid: string;
|
|
678
|
+
rect: Rect;
|
|
679
|
+
displayName: string;
|
|
680
|
+
hasVisibleChildren: boolean;
|
|
681
|
+
hasText: boolean;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
/**
|
|
685
|
+
* Empty-container hint targets: OID elements with no visible children, no text, and a
|
|
686
|
+
* collapsed dimension (< 8px) — shown as a placeholder so an empty flex/grid container is
|
|
687
|
+
* still selectable (visual-edit `getEmptyContainers` :563). The placeholder rect is grown
|
|
688
|
+
* to a minimum tappable size AROUND the measured box. Keeping the measured center fixed is
|
|
689
|
+
* load-bearing: a zero-width/height flex item denotes a line/point, and growing only toward
|
|
690
|
+
* the bottom-right makes the grey dashed hint appear displaced from that authored position.
|
|
691
|
+
*/
|
|
692
|
+
export function findEmptyContainers(
|
|
693
|
+
candidates: readonly EmptyCandidate[],
|
|
694
|
+
): { oid: string; rect: Rect; displayName: string }[] {
|
|
695
|
+
const out: { oid: string; rect: Rect; displayName: string }[] = [];
|
|
696
|
+
for (const c of candidates) {
|
|
697
|
+
if (c.hasVisibleChildren || c.hasText) continue;
|
|
698
|
+
if (c.rect.width >= 8 && c.rect.height >= 8) continue;
|
|
699
|
+
const width = Math.max(c.rect.width, 40);
|
|
700
|
+
const height = Math.max(c.rect.height, 24);
|
|
701
|
+
out.push({
|
|
702
|
+
oid: c.oid,
|
|
703
|
+
displayName: c.displayName,
|
|
704
|
+
rect: {
|
|
705
|
+
x: c.rect.x - (width - c.rect.width) / 2,
|
|
706
|
+
y: c.rect.y - (height - c.rect.height) / 2,
|
|
707
|
+
width,
|
|
708
|
+
height,
|
|
709
|
+
},
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
return out;
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
const TRANSPARENT_BG = new Set(['', 'transparent', 'rgba(0, 0, 0, 0)']);
|
|
716
|
+
|
|
717
|
+
/** Is a computed background color effectively transparent? */
|
|
718
|
+
export function isTransparentBackground(bg: string): boolean {
|
|
719
|
+
return TRANSPARENT_BG.has(bg);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Eyedropper: the effective background color at a point — the first non-transparent
|
|
724
|
+
* background walking from the hit element up its ancestor chain, else `#fff` (visual-edit
|
|
725
|
+
* `getColorAtPoint` :667 / `getEffectiveBackground` :63). `bgChain` is hit-element-first.
|
|
726
|
+
*/
|
|
727
|
+
export function effectiveColorFromChain(bgChain: readonly string[]): string {
|
|
728
|
+
for (const bg of bgChain) if (!isTransparentBackground(bg)) return bg;
|
|
729
|
+
return '#fff';
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
const WEB_SAFE_FONTS = [
|
|
733
|
+
'Arial',
|
|
734
|
+
'Helvetica',
|
|
735
|
+
'Times New Roman',
|
|
736
|
+
'Georgia',
|
|
737
|
+
'Verdana',
|
|
738
|
+
'Courier New',
|
|
739
|
+
'Impact',
|
|
740
|
+
'Trebuchet MS',
|
|
741
|
+
'Palatino Linotype',
|
|
742
|
+
'Lucida Console',
|
|
743
|
+
'monospace',
|
|
744
|
+
'sans-serif',
|
|
745
|
+
'serif',
|
|
746
|
+
];
|
|
747
|
+
|
|
748
|
+
/** The available font families: the loaded fonts (quotes stripped) merged with the
|
|
749
|
+
* web-safe fallbacks, de-duped and sorted (visual-edit `getAvailableFonts` :677). */
|
|
750
|
+
export function mergeFonts(loaded: readonly string[] = []): string[] {
|
|
751
|
+
const fonts = new Set<string>();
|
|
752
|
+
for (const f of loaded) fonts.add(f.replace(/^["']|["']$/g, ''));
|
|
753
|
+
for (const f of WEB_SAFE_FONTS) fonts.add(f);
|
|
754
|
+
return [...fonts].sort((a, b) => a.localeCompare(b));
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/** Browser wrapper: enumerate `document.fonts` families merged with the web-safe list.
|
|
758
|
+
* Returns just the web-safe list under a headless (no `document.fonts`) environment. */
|
|
759
|
+
export function getAvailableFonts(): string[] {
|
|
760
|
+
const g = globalThis as { document?: { fonts?: Iterable<{ family: string }> } };
|
|
761
|
+
const loaded: string[] = [];
|
|
762
|
+
const docFonts = g.document?.fonts;
|
|
763
|
+
if (docFonts) for (const f of docFonts) loaded.push(f.family);
|
|
764
|
+
return mergeFonts(loaded);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
function readRootComputed(): (ComputedStyleLike & ArrayLike<string>) | undefined {
|
|
768
|
+
const g = globalThis as {
|
|
769
|
+
window?: { getComputedStyle?: (e: unknown) => ComputedStyleLike & ArrayLike<string> };
|
|
770
|
+
document?: { documentElement?: unknown };
|
|
771
|
+
};
|
|
772
|
+
const root = g.document?.documentElement;
|
|
773
|
+
if (!root || !g.window?.getComputedStyle) return undefined;
|
|
774
|
+
return g.window.getComputedStyle(root);
|
|
775
|
+
}
|