@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,309 @@
|
|
|
1
|
+
import { themeVars } from '@volter/editor-sdk/widgets';
|
|
2
|
+
/**
|
|
3
|
+
* Project-tool DOCUMENTS (W3 — inventory rows B12/T2-behavior/T3): a
|
|
4
|
+
* `placement: 'document'` project tool (including every legacy `'dock'` tool
|
|
5
|
+
* — the W0 alias rule) opens as a CENTER workspace document (kind `'tool'`,
|
|
6
|
+
* title = the tool's own declared title per §8), hosted in the same
|
|
7
|
+
* error-boundaried `ToolHost` the bottom ⚙ tabs used. `placement: 'utility'`
|
|
8
|
+
* tools stay in the bottom area — rendered as sections of the ONE Dev
|
|
9
|
+
* utility (`components/DevPanel.tsx`), never as tabs of their own.
|
|
10
|
+
* The ⚙ dock-tab row is gone.
|
|
11
|
+
*
|
|
12
|
+
* Open gesture: one `Open Tool: <title>` command-palette action per
|
|
13
|
+
* discovered document tool (`buildToolActions`) — the fixed-layout menu the
|
|
14
|
+
* ⚙ row used to be, now a searchable command.
|
|
15
|
+
*
|
|
16
|
+
* HMR/lifecycle: the document's CONTENT reads the LIVE tool store — an HMR
|
|
17
|
+
* reload bumps the tool's `version`, which re-keys the mount (fresh
|
|
18
|
+
* component + cleared error boundary, the same physics the dock tabs had);
|
|
19
|
+
* a deleted tool file leaves an honest "no longer available" message in any
|
|
20
|
+
* open document (discovery is the folder scan, D3).
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { type ComponentType, useSyncExternalStore } from 'react';
|
|
24
|
+
import type { EditorAction } from '../action-registry';
|
|
25
|
+
import {
|
|
26
|
+
awaitAnnouncedObject3DDocumentSession,
|
|
27
|
+
waitForContributedDocumentMount,
|
|
28
|
+
} from '../document-context-registry';
|
|
29
|
+
import { registerDocumentOpener } from '../document-open-registry';
|
|
30
|
+
import type { ViewportTab } from '../editor-shell-store';
|
|
31
|
+
import {
|
|
32
|
+
contributionFailureHint,
|
|
33
|
+
getDocumentToolContributions,
|
|
34
|
+
getGlobalToolContributions,
|
|
35
|
+
refreshProjectToolContributions,
|
|
36
|
+
subscribeToolContributions,
|
|
37
|
+
} from '../tool-loader';
|
|
38
|
+
import {
|
|
39
|
+
closeWorkspaceDocument,
|
|
40
|
+
type OpenWorkspaceDocumentOptions,
|
|
41
|
+
openWorkspaceDocument,
|
|
42
|
+
openWorkspaceDocuments,
|
|
43
|
+
type WorkspaceDocumentContentProps,
|
|
44
|
+
} from '../workspace-document-registry';
|
|
45
|
+
import { registerWorkspaceDocumentRestorer } from '../workspace-document-restore';
|
|
46
|
+
import { ToolHost } from './ToolHost';
|
|
47
|
+
|
|
48
|
+
/** The narrow store surface tool documents need (T6.3 tab hand-off). */
|
|
49
|
+
export interface ToolDocumentStore {
|
|
50
|
+
setActiveViewportTab(tab: ViewportTab): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Stable §7.1 identity for one project tool's document. */
|
|
54
|
+
export function toolDocumentId(toolId: string): string {
|
|
55
|
+
return `tool:${toolId}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** Resolve either the canonical tool-qualified id or one unambiguous package-local id. */
|
|
59
|
+
export function resolveToolDocumentContributionId(id: string): string | null {
|
|
60
|
+
const contributions = getDocumentToolContributions();
|
|
61
|
+
const exact = contributions.find((item) => item.id === id);
|
|
62
|
+
if (exact) return exact.id;
|
|
63
|
+
// Ids are no longer tool-prefixed, so an exact match above is the only
|
|
64
|
+
// lookup left — there is no local-vs-qualified form to reconcile.
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Open (or activate) the center document for one document-placement project
|
|
70
|
+
* tool. Returns `false` (opens nothing) when no discovered document tool
|
|
71
|
+
* carries that id — no fabricated documents for deleted/renamed tools.
|
|
72
|
+
*/
|
|
73
|
+
export function openToolDocument(
|
|
74
|
+
store: ToolDocumentStore | null,
|
|
75
|
+
toolId: string,
|
|
76
|
+
options: OpenWorkspaceDocumentOptions = {},
|
|
77
|
+
/** THE WORKSPACE AREA this document fills, when a workspace's own `areas`
|
|
78
|
+
* list is what opened it (`WorkspaceDocumentDescriptor.area`). Absent for
|
|
79
|
+
* every other opener, which is what keeps an ordinary tool document a
|
|
80
|
+
* centre tab. */
|
|
81
|
+
area?: string,
|
|
82
|
+
): boolean {
|
|
83
|
+
const resolvedId = resolveToolDocumentContributionId(toolId);
|
|
84
|
+
const contribution = getDocumentToolContributions().find((item) => item.id === resolvedId);
|
|
85
|
+
if (!contribution) return false;
|
|
86
|
+
openWorkspaceDocument(
|
|
87
|
+
{
|
|
88
|
+
id: toolDocumentId(contribution.id),
|
|
89
|
+
...(area === undefined ? {} : { area }),
|
|
90
|
+
// §8: the tool's own declared title, never a tech bucket.
|
|
91
|
+
title: contribution.title,
|
|
92
|
+
kind: 'tool-contribution',
|
|
93
|
+
workspaceRole: 'workspace-reference',
|
|
94
|
+
provenance: {
|
|
95
|
+
sourcePath: contribution.file,
|
|
96
|
+
origin: contribution.tool?.name ?? contribution.file,
|
|
97
|
+
},
|
|
98
|
+
Content: ToolDocumentContent,
|
|
99
|
+
// The contribution's header rides the host's own strip — the region the
|
|
100
|
+
// Game and Story documents already use — so a project document gets the
|
|
101
|
+
// same header anatomy as a built-in, drawn by the host.
|
|
102
|
+
...(contribution.Toolbar ? { Toolbar: ToolDocumentToolbar } : {}),
|
|
103
|
+
...(contribution.Shelf ? { Shelf: ToolDocumentShelf } : {}),
|
|
104
|
+
// A STANDING document is a place in the project, not an errand — pinned
|
|
105
|
+
// like the `3D`/`UI`/`Dev` boards. See `GlobalToolContribution.standing`.
|
|
106
|
+
// AN AREA DOCUMENT IS PINNED TOO, and for a stronger reason: it is not
|
|
107
|
+
// a tab at all, it IS the workspace's second editor group, and a close
|
|
108
|
+
// affordance on it would offer to empty a group nothing refills.
|
|
109
|
+
closeable: area === undefined && !contribution.standing,
|
|
110
|
+
presentation: () => ({ kind: 'tool', id: contribution.id }),
|
|
111
|
+
// AN AREA DOCUMENT DOES NOT PERSIST ITSELF. The WORKSPACE reopens it,
|
|
112
|
+
// from its own `areas` list, and it does so knowing the area id — a
|
|
113
|
+
// restorer running first would reopen the same contribution with NO
|
|
114
|
+
// area and strand it as a centre tab beside the model. `undefined` is
|
|
115
|
+
// the descriptor's own documented opt-out for "something else
|
|
116
|
+
// re-derives this at boot", which is exactly the case here.
|
|
117
|
+
...(area === undefined ? { persist: () => ({ contributionId: contribution.id }) } : {}),
|
|
118
|
+
...(store ? { onActivate: () => store.setActiveViewportTab('edit') } : {}),
|
|
119
|
+
},
|
|
120
|
+
options,
|
|
121
|
+
);
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Reopen a persisted tool document. `openToolDocument` is self-verifying —
|
|
126
|
+
* a deleted or renamed contribution opens nothing and answers `false`, so
|
|
127
|
+
* the stale panel is reconciled away. No `prepare`: the discovery pass this
|
|
128
|
+
* kind used to await for itself is now the restore's own first step, run for
|
|
129
|
+
* EVERY record because a package owns its restorer as well as its documents
|
|
130
|
+
* (`workspace-state-persistence.ts`, "contributions load first"). Keeping
|
|
131
|
+
* both ran the pass twice per boot — three reports of each unimplemented
|
|
132
|
+
* stub instead of one, measured on a `full` scaffold 2026-09-18. */
|
|
133
|
+
registerWorkspaceDocumentRestorer({
|
|
134
|
+
kind: 'tool-contribution',
|
|
135
|
+
owner: 'tool-documents',
|
|
136
|
+
restore: ({ state, store }) => {
|
|
137
|
+
const record = state as { contributionId?: unknown } | null | undefined;
|
|
138
|
+
const contributionId =
|
|
139
|
+
typeof record?.contributionId === 'string' ? record.contributionId : null;
|
|
140
|
+
return contributionId !== null && openToolDocument(store, contributionId);
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* THE `tool` ADDRESS (`document-open-registry.ts`) — the other half of the
|
|
146
|
+
* `presentation()` above, so the presenter reaches a contributed document
|
|
147
|
+
* without importing this module. Registered at module load, the shape
|
|
148
|
+
* `packages/game/src/story-documents/three-story-documents.tsx:239` uses.
|
|
149
|
+
*
|
|
150
|
+
* SETTLING is the discovery pass this kind opens out of. A cold Vite graph can
|
|
151
|
+
* register the project catalog before its document contribution modules finish
|
|
152
|
+
* loading, and an explicit address is durable intent, so the owning pass is
|
|
153
|
+
* DRIVEN rather than raced with a timeout — what the presenter did by hand.
|
|
154
|
+
* "Not registered" then has two causes that need different fixes (no such
|
|
155
|
+
* contribution exists, or one exists and its module threw on import) and
|
|
156
|
+
* `contributionFailureHint` is what tells them apart; a generic refusal used to
|
|
157
|
+
* send the reader hunting for a missing file that was on disk all along, so
|
|
158
|
+
* this address refuses in its own words.
|
|
159
|
+
*/
|
|
160
|
+
registerDocumentOpener<{ readonly id: string }>({
|
|
161
|
+
id: 'tool',
|
|
162
|
+
owner: 'tool-documents',
|
|
163
|
+
open: (store, request) => {
|
|
164
|
+
// Resolve FIRST: `openToolDocument` resolves the same way and the document
|
|
165
|
+
// id is built from what it found, so the resolution is the answer.
|
|
166
|
+
const resolvedId = resolveToolDocumentContributionId(request.id);
|
|
167
|
+
if (resolvedId === null) return null;
|
|
168
|
+
return openToolDocument(store, resolvedId) ? toolDocumentId(resolvedId) : null;
|
|
169
|
+
},
|
|
170
|
+
settle: async (request) => {
|
|
171
|
+
await refreshProjectToolContributions();
|
|
172
|
+
if (resolveToolDocumentContributionId(request.id) !== null) return;
|
|
173
|
+
throw new Error(
|
|
174
|
+
`Tool document is not registered: ${request.id}.${contributionFailureHint(request.id)}`,
|
|
175
|
+
);
|
|
176
|
+
},
|
|
177
|
+
/**
|
|
178
|
+
* THE KIND'S OWN READINESS — a contributed document is ready to be driven
|
|
179
|
+
* once its React root has committed and, if that root mounted a stage, once
|
|
180
|
+
* the stage has registered its Object3D session. The presenter used to hold
|
|
181
|
+
* this rule for this address by name (`editor-view-presentation.ts`'s
|
|
182
|
+
* `kind === 'tool' || 'asset'`); it belongs here, where the contribution the
|
|
183
|
+
* host mounted is what answers.
|
|
184
|
+
*/
|
|
185
|
+
ready: async (documentId) => {
|
|
186
|
+
await waitForContributedDocumentMount(documentId);
|
|
187
|
+
await awaitAnnouncedObject3DDocumentSession(documentId);
|
|
188
|
+
},
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Open every STANDING document contribution, and keep that set in step with
|
|
193
|
+
* discovery: a capability added mid-session brings its tab with it, and a
|
|
194
|
+
* capability whose source is deleted takes its tab away rather than leaving a
|
|
195
|
+
* pinned panel nothing backs.
|
|
196
|
+
*
|
|
197
|
+
* Returns the teardown for the subscription (it does not close the documents —
|
|
198
|
+
* the project-open path owns that, the same way it owns the boards).
|
|
199
|
+
*/
|
|
200
|
+
export function installStandingToolDocuments(store: ToolDocumentStore): () => void {
|
|
201
|
+
const opened = new Set<string>();
|
|
202
|
+
const reconcile = () => {
|
|
203
|
+
const standing = getDocumentToolContributions().filter((item) => item.standing);
|
|
204
|
+
const live = new Set(standing.map((item) => item.id));
|
|
205
|
+
for (const id of opened) {
|
|
206
|
+
if (live.has(id)) continue;
|
|
207
|
+
closeWorkspaceDocument(toolDocumentId(id), { discardDirty: true });
|
|
208
|
+
opened.delete(id);
|
|
209
|
+
}
|
|
210
|
+
for (const item of standing) {
|
|
211
|
+
if (opened.has(item.id)) continue;
|
|
212
|
+
if (openToolDocument(store, item.id, { activate: false })) opened.add(item.id);
|
|
213
|
+
}
|
|
214
|
+
// EVERY open tool document takes its slots afresh on discovery change,
|
|
215
|
+
// standing or not: a module re-evaluated on save may have gained or lost
|
|
216
|
+
// its `Toolbar`, and `openWorkspaceDocument` on an open id is what
|
|
217
|
+
// refreshes the descriptor's mount slots (see the registry).
|
|
218
|
+
const open = new Set(openWorkspaceDocuments().map((d) => d.descriptor.id));
|
|
219
|
+
for (const item of getDocumentToolContributions()) {
|
|
220
|
+
if (!open.has(toolDocumentId(item.id))) continue;
|
|
221
|
+
openToolDocument(store, item.id, { activate: false });
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
reconcile();
|
|
225
|
+
return subscribeToolContributions(reconcile);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** `Open Tool: <title>` palette actions — one per discovered document tool
|
|
229
|
+
* (the B12 discovery gesture). A standing document is always open, so its
|
|
230
|
+
* action ACTIVATES the tab rather than teaching a way to summon it. */
|
|
231
|
+
export function buildToolActions(store: ToolDocumentStore): EditorAction[] {
|
|
232
|
+
return getDocumentToolContributions().map((t) => ({
|
|
233
|
+
id: `tool-doc:${t.id}`,
|
|
234
|
+
label: t.standing ? `Show ${t.title}` : `Open Tool: ${t.title}`,
|
|
235
|
+
category: 'action' as const,
|
|
236
|
+
execute: () => void openToolDocument(store, t.id),
|
|
237
|
+
}));
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Content host: resolves the LIVE tool by id on every render (HMR re-key,
|
|
241
|
+
* honest deleted-tool state). */
|
|
242
|
+
/** The header strip's contents for a tool document: the contribution's own
|
|
243
|
+
* `Toolbar`, mounted through the same host so it reads the same props. */
|
|
244
|
+
export function ToolDocumentToolbar({ documentId, active }: WorkspaceDocumentContentProps) {
|
|
245
|
+
useSyncExternalStore(subscribeToolContributions, getGlobalToolContributions);
|
|
246
|
+
const toolId = documentId.startsWith('tool:') ? documentId.slice('tool:'.length) : documentId;
|
|
247
|
+
const contribution = getDocumentToolContributions().find((item) => item.id === toolId);
|
|
248
|
+
if (!contribution?.Toolbar) return null;
|
|
249
|
+
return (
|
|
250
|
+
<ToolHost
|
|
251
|
+
key={`${contribution.id}:${contribution.version}:toolbar`}
|
|
252
|
+
contribution={contribution}
|
|
253
|
+
Component={contribution.Toolbar as unknown as ComponentType<Record<string, unknown>>}
|
|
254
|
+
documentId={documentId}
|
|
255
|
+
active={active}
|
|
256
|
+
/>
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** The shelf rail's contents for a tool document: the contribution's own
|
|
261
|
+
* `Shelf`, mounted through the same host so it reads the same props. */
|
|
262
|
+
export function ToolDocumentShelf({ documentId, active }: WorkspaceDocumentContentProps) {
|
|
263
|
+
useSyncExternalStore(subscribeToolContributions, getGlobalToolContributions);
|
|
264
|
+
const toolId = documentId.startsWith('tool:') ? documentId.slice('tool:'.length) : documentId;
|
|
265
|
+
const contribution = getDocumentToolContributions().find((item) => item.id === toolId);
|
|
266
|
+
if (!contribution?.Shelf) return null;
|
|
267
|
+
return (
|
|
268
|
+
<ToolHost
|
|
269
|
+
key={`${contribution.id}:${contribution.version}:shelf`}
|
|
270
|
+
contribution={contribution}
|
|
271
|
+
Component={contribution.Shelf as unknown as ComponentType<Record<string, unknown>>}
|
|
272
|
+
documentId={documentId}
|
|
273
|
+
active={active}
|
|
274
|
+
/>
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export function ToolDocumentContent({ documentId, active }: WorkspaceDocumentContentProps) {
|
|
279
|
+
useSyncExternalStore(subscribeToolContributions, getGlobalToolContributions);
|
|
280
|
+
const toolId = documentId.startsWith('tool:') ? documentId.slice('tool:'.length) : documentId;
|
|
281
|
+
const contribution = getDocumentToolContributions().find((item) => item.id === toolId);
|
|
282
|
+
if (!contribution) {
|
|
283
|
+
return (
|
|
284
|
+
<div
|
|
285
|
+
style={{ padding: 12, fontSize: 12, color: themeVars.content.muted, pointerEvents: 'auto' }}
|
|
286
|
+
>
|
|
287
|
+
This tool contribution is no longer registered — close this document.
|
|
288
|
+
</div>
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
return (
|
|
292
|
+
<div
|
|
293
|
+
key={`${contribution.id}:${contribution.version}`}
|
|
294
|
+
data-testid={`tool-document:${contribution.id}`}
|
|
295
|
+
style={{
|
|
296
|
+
flex: 1,
|
|
297
|
+
minHeight: 0,
|
|
298
|
+
display: 'flex',
|
|
299
|
+
flexDirection: 'column',
|
|
300
|
+
pointerEvents: 'auto',
|
|
301
|
+
// B-11: the editor-provided baseline breathing room every hosted
|
|
302
|
+
// surface's content root has by convention (carried from the dock).
|
|
303
|
+
padding: 12,
|
|
304
|
+
}}
|
|
305
|
+
>
|
|
306
|
+
<ToolHost contribution={contribution} documentId={documentId} active={active} />
|
|
307
|
+
</div>
|
|
308
|
+
);
|
|
309
|
+
}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { Checkbox, Select, TextInput, text } from '@volter/editor-sdk/widgets';
|
|
2
|
+
import type { CSSProperties } from 'react';
|
|
3
|
+
|
|
4
|
+
type JsonSchema = Record<string, unknown>;
|
|
5
|
+
|
|
6
|
+
function schemaRecord(value: unknown): JsonSchema {
|
|
7
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? (value as JsonSchema) : {};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function schemaType(schema: JsonSchema): string | undefined {
|
|
11
|
+
const type = schema['type'];
|
|
12
|
+
if (typeof type === 'string') return type;
|
|
13
|
+
if (Array.isArray(type)) return type.find((item): item is string => item !== 'null');
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function defaultValueForSchema(value: unknown): unknown {
|
|
18
|
+
const schema = schemaRecord(value);
|
|
19
|
+
if ('default' in schema) return structuredClone(schema['default']);
|
|
20
|
+
const type = schemaType(schema);
|
|
21
|
+
if (type === 'object' || schema['properties']) {
|
|
22
|
+
const result: Record<string, unknown> = {};
|
|
23
|
+
for (const [key, child] of Object.entries(schemaRecord(schema['properties']))) {
|
|
24
|
+
const childSchema = schemaRecord(child);
|
|
25
|
+
if (
|
|
26
|
+
'default' in childSchema ||
|
|
27
|
+
(Array.isArray(schema['required']) && schema['required'].includes(key))
|
|
28
|
+
) {
|
|
29
|
+
result[key] = defaultValueForSchema(childSchema);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
if (type === 'array') return [];
|
|
35
|
+
if (type === 'boolean') return false;
|
|
36
|
+
if (type === 'number' || type === 'integer') return Number(schema['minimum'] ?? 0);
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function humanize(value: string): string {
|
|
41
|
+
return value
|
|
42
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
|
|
43
|
+
.replace(/[-_]/g, ' ')
|
|
44
|
+
.replace(/^./, (letter) => letter.toUpperCase());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: this is the deliberately small JSON-Schema widget dispatch; each primitive type remains native HTML.
|
|
48
|
+
function PrimitiveField({
|
|
49
|
+
name,
|
|
50
|
+
schema,
|
|
51
|
+
value,
|
|
52
|
+
required,
|
|
53
|
+
onChange,
|
|
54
|
+
}: {
|
|
55
|
+
name: string;
|
|
56
|
+
schema: JsonSchema;
|
|
57
|
+
value: unknown;
|
|
58
|
+
required: boolean;
|
|
59
|
+
onChange(value: unknown): void;
|
|
60
|
+
}) {
|
|
61
|
+
const type = schemaType(schema);
|
|
62
|
+
const description = typeof schema['description'] === 'string' ? schema['description'] : null;
|
|
63
|
+
const choices = Array.isArray(schema['enum']) ? schema['enum'] : null;
|
|
64
|
+
const id = `tool-field:${name}`;
|
|
65
|
+
|
|
66
|
+
if (type === 'boolean') {
|
|
67
|
+
return (
|
|
68
|
+
<label style={{ ...fieldStyle, gridTemplateColumns: '18px minmax(0, 1fr)' }}>
|
|
69
|
+
<Checkbox
|
|
70
|
+
id={id}
|
|
71
|
+
checked={value === true}
|
|
72
|
+
onChange={(event) => onChange(event.target.checked)}
|
|
73
|
+
/>
|
|
74
|
+
<span>
|
|
75
|
+
<span style={fieldLabelStyle}>{humanize(name)}</span>
|
|
76
|
+
{description && <span style={descriptionStyle}>{description}</span>}
|
|
77
|
+
</span>
|
|
78
|
+
</label>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const label = (
|
|
83
|
+
<span style={fieldLabelStyle}>
|
|
84
|
+
{humanize(name)} {!required && <span style={optionalStyle}>optional</span>}
|
|
85
|
+
</span>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
if (choices) {
|
|
89
|
+
return (
|
|
90
|
+
<label style={fieldStyle} htmlFor={id}>
|
|
91
|
+
{label}
|
|
92
|
+
<Select
|
|
93
|
+
id={id}
|
|
94
|
+
value={String(value ?? '')}
|
|
95
|
+
onChange={(event) => onChange(event.target.value)}
|
|
96
|
+
style={controlLayoutStyle}
|
|
97
|
+
>
|
|
98
|
+
{!required && <option value="">Not set</option>}
|
|
99
|
+
{choices.map((choice) => (
|
|
100
|
+
<option key={String(choice)} value={String(choice)}>
|
|
101
|
+
{String(choice)}
|
|
102
|
+
</option>
|
|
103
|
+
))}
|
|
104
|
+
</Select>
|
|
105
|
+
{description && <span style={descriptionStyle}>{description}</span>}
|
|
106
|
+
</label>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (type === 'number' || type === 'integer') {
|
|
111
|
+
return (
|
|
112
|
+
<label style={fieldStyle} htmlFor={id}>
|
|
113
|
+
{label}
|
|
114
|
+
<TextInput
|
|
115
|
+
id={id}
|
|
116
|
+
type="number"
|
|
117
|
+
value={typeof value === 'number' ? value : ''}
|
|
118
|
+
min={typeof schema['minimum'] === 'number' ? schema['minimum'] : undefined}
|
|
119
|
+
max={typeof schema['maximum'] === 'number' ? schema['maximum'] : undefined}
|
|
120
|
+
step={type === 'integer' ? 1 : 'any'}
|
|
121
|
+
onChange={(event) =>
|
|
122
|
+
onChange(event.target.value === '' ? undefined : Number(event.target.value))
|
|
123
|
+
}
|
|
124
|
+
style={controlLayoutStyle}
|
|
125
|
+
/>
|
|
126
|
+
{description && <span style={descriptionStyle}>{description}</span>}
|
|
127
|
+
</label>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (type === 'array' && schemaType(schemaRecord(schema['items'])) === 'string') {
|
|
132
|
+
return (
|
|
133
|
+
<label style={fieldStyle} htmlFor={id}>
|
|
134
|
+
{label}
|
|
135
|
+
<TextInput
|
|
136
|
+
id={id}
|
|
137
|
+
value={Array.isArray(value) ? value.join(', ') : ''}
|
|
138
|
+
onChange={(event) =>
|
|
139
|
+
onChange(
|
|
140
|
+
event.target.value
|
|
141
|
+
.split(',')
|
|
142
|
+
.map((item) => item.trim())
|
|
143
|
+
.filter(Boolean),
|
|
144
|
+
)
|
|
145
|
+
}
|
|
146
|
+
placeholder="Comma-separated values"
|
|
147
|
+
style={controlLayoutStyle}
|
|
148
|
+
/>
|
|
149
|
+
{description && <span style={descriptionStyle}>{description}</span>}
|
|
150
|
+
</label>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<label style={fieldStyle} htmlFor={id}>
|
|
156
|
+
{label}
|
|
157
|
+
<TextInput
|
|
158
|
+
id={id}
|
|
159
|
+
value={typeof value === 'string' ? value : ''}
|
|
160
|
+
onChange={(event) => onChange(event.target.value || (required ? '' : undefined))}
|
|
161
|
+
style={controlLayoutStyle}
|
|
162
|
+
/>
|
|
163
|
+
{description && <span style={descriptionStyle}>{description}</span>}
|
|
164
|
+
</label>
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function ObjectFields({
|
|
169
|
+
schema,
|
|
170
|
+
value,
|
|
171
|
+
onChange,
|
|
172
|
+
path = '',
|
|
173
|
+
}: {
|
|
174
|
+
schema: JsonSchema;
|
|
175
|
+
value: Record<string, unknown>;
|
|
176
|
+
onChange(value: Record<string, unknown>): void;
|
|
177
|
+
path?: string;
|
|
178
|
+
}) {
|
|
179
|
+
const properties = schemaRecord(schema['properties']);
|
|
180
|
+
const required = new Set(Array.isArray(schema['required']) ? schema['required'] : []);
|
|
181
|
+
return (
|
|
182
|
+
<div style={{ display: 'grid', gap: 14 }}>
|
|
183
|
+
{Object.entries(properties).map(([key, child]) => {
|
|
184
|
+
const childSchema = schemaRecord(child);
|
|
185
|
+
const childType = schemaType(childSchema);
|
|
186
|
+
const update = (next: unknown) => {
|
|
187
|
+
const copy = { ...value };
|
|
188
|
+
if (next === undefined) delete copy[key];
|
|
189
|
+
else copy[key] = next;
|
|
190
|
+
onChange(copy);
|
|
191
|
+
};
|
|
192
|
+
if (childType === 'object' || childSchema['properties']) {
|
|
193
|
+
return (
|
|
194
|
+
<fieldset key={key} style={fieldsetStyle}>
|
|
195
|
+
<legend style={legendStyle}>{humanize(key)}</legend>
|
|
196
|
+
{typeof childSchema['description'] === 'string' && (
|
|
197
|
+
<p style={{ ...descriptionStyle, marginTop: 0 }}>{childSchema['description']}</p>
|
|
198
|
+
)}
|
|
199
|
+
<ObjectFields
|
|
200
|
+
schema={childSchema}
|
|
201
|
+
value={schemaRecord(value[key])}
|
|
202
|
+
onChange={update}
|
|
203
|
+
path={path ? `${path}.${key}` : key}
|
|
204
|
+
/>
|
|
205
|
+
</fieldset>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
return (
|
|
209
|
+
<PrimitiveField
|
|
210
|
+
key={key}
|
|
211
|
+
name={path ? `${path}.${key}` : key}
|
|
212
|
+
schema={childSchema}
|
|
213
|
+
value={value[key]}
|
|
214
|
+
required={required.has(key)}
|
|
215
|
+
onChange={update}
|
|
216
|
+
/>
|
|
217
|
+
);
|
|
218
|
+
})}
|
|
219
|
+
</div>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function ToolSchemaForm({
|
|
224
|
+
schema: schemaValue,
|
|
225
|
+
value,
|
|
226
|
+
onChange,
|
|
227
|
+
}: {
|
|
228
|
+
schema: unknown;
|
|
229
|
+
value: Record<string, unknown>;
|
|
230
|
+
onChange(value: Record<string, unknown>): void;
|
|
231
|
+
}) {
|
|
232
|
+
const schema = schemaRecord(schemaValue);
|
|
233
|
+
if (!schema['properties']) {
|
|
234
|
+
return <div style={descriptionStyle}>This schema has no form-compatible fields.</div>;
|
|
235
|
+
}
|
|
236
|
+
return <ObjectFields schema={schema} value={value} onChange={onChange} />;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const fieldStyle: CSSProperties = { display: 'grid', gap: 5 };
|
|
240
|
+
const fieldLabelStyle: CSSProperties = {
|
|
241
|
+
color: text[1],
|
|
242
|
+
fontWeight: 600,
|
|
243
|
+
fontSize: 'var(--vgai-font-sm)',
|
|
244
|
+
};
|
|
245
|
+
const optionalStyle: CSSProperties = { color: text[3], fontWeight: 400, marginLeft: 5 };
|
|
246
|
+
const descriptionStyle: CSSProperties = {
|
|
247
|
+
display: 'block',
|
|
248
|
+
color: text[2],
|
|
249
|
+
fontSize: 'var(--vgai-font-sm)',
|
|
250
|
+
lineHeight: 1.4,
|
|
251
|
+
};
|
|
252
|
+
const controlLayoutStyle: CSSProperties = {
|
|
253
|
+
boxSizing: 'border-box',
|
|
254
|
+
width: '100%',
|
|
255
|
+
};
|
|
256
|
+
const fieldsetStyle: CSSProperties = {
|
|
257
|
+
margin: 0,
|
|
258
|
+
padding: 14,
|
|
259
|
+
border: '1px solid var(--vgai-boundary-default)',
|
|
260
|
+
borderRadius: 'var(--vgai-radius-md)',
|
|
261
|
+
};
|
|
262
|
+
const legendStyle: CSSProperties = { padding: '0 6px', color: text[1], fontWeight: 600 };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Mount this AFTER the browser has painted the commit that asked for it."
|
|
3
|
+
*
|
|
4
|
+
* The inspector's live preview is the case this exists for: its mount effect
|
|
5
|
+
* builds a scene snapshot and draws the first frame, and React runs that effect
|
|
6
|
+
* in the SAME task as the selection commit — so the card, the name and the
|
|
7
|
+
* preview all appeared together, whenever the preview was finally done. Gating
|
|
8
|
+
* the heavy child on this hook lets the commit paint first; the picture arrives
|
|
9
|
+
* in a later frame and nothing is waiting on it.
|
|
10
|
+
*
|
|
11
|
+
* Two frames, not one: the first `requestAnimationFrame` callback runs BEFORE
|
|
12
|
+
* the paint of the commit that scheduled it, so only the second is past it.
|
|
13
|
+
* `startTransition` is the wrong tool here — the work is not React rendering,
|
|
14
|
+
* it is a `useEffect` doing GL work, which a transition does not defer.
|
|
15
|
+
*
|
|
16
|
+
* `key` identifies what is being waited for (a subject id, a preview key). It
|
|
17
|
+
* matters because these hosts are RE-RENDERED rather than remounted as the
|
|
18
|
+
* selection changes: comparing against the key that became ready is what makes
|
|
19
|
+
* the next subject wait again instead of inheriting the last one's readiness.
|
|
20
|
+
*
|
|
21
|
+
* Callers put the gate where their PLACEHOLDER is — the mini card's preview
|
|
22
|
+
* shows its quiet kind glyph, the section body shows its empty box — which is
|
|
23
|
+
* why this is a hook and not a wrapper component with one built-in fallback.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { useEffect, useState } from 'react';
|
|
27
|
+
|
|
28
|
+
export function useAfterPaint(key: string): boolean {
|
|
29
|
+
const [readyKey, setReadyKey] = useState<string | null>(null);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
let second = 0;
|
|
32
|
+
const first = requestAnimationFrame(() => {
|
|
33
|
+
second = requestAnimationFrame(() => setReadyKey(key));
|
|
34
|
+
});
|
|
35
|
+
return () => {
|
|
36
|
+
cancelAnimationFrame(first);
|
|
37
|
+
cancelAnimationFrame(second);
|
|
38
|
+
};
|
|
39
|
+
}, [key]);
|
|
40
|
+
return readyKey === key;
|
|
41
|
+
}
|