@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,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One portable-CSF thumbnail — the CSF lane's answer to "what does this
|
|
3
|
+
* component look like?", the picture behind every registered content entry,
|
|
4
|
+
* which is what the Content grid paints and what the Inspector's component
|
|
5
|
+
* preview shows (`content-entry-source-registry.ts`). Surface chooses the
|
|
6
|
+
* native renderer; the story remains the sole preview authority for both Three
|
|
7
|
+
* and Pixi prefabs.
|
|
8
|
+
*
|
|
9
|
+
* It was `components/StoryComponentThumbnail.tsx`, imported by name from three
|
|
10
|
+
* host surfaces. All three ask a registered SOURCE now, so this module has
|
|
11
|
+
* exactly one importer — `component-content-source.tsx`, beside it.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { useEffect, useState } from 'react';
|
|
15
|
+
import type { ProjectComponentEntry } from '../asset-workflow/project-content';
|
|
16
|
+
import { TypedAssetThumbnail } from '../components/asset-thumbnails';
|
|
17
|
+
import { waitForFirstViewportFrame } from '../viewport-activation-timings';
|
|
18
|
+
import type { PixiStoryThumbnailOptions } from './story-pixi-preview';
|
|
19
|
+
import type { ProjectPreviewStory } from './story-registry';
|
|
20
|
+
import type { StoryPreviewComponent } from './story-three-preview';
|
|
21
|
+
import { threeStoryThumbnailKey } from './three-story-model';
|
|
22
|
+
|
|
23
|
+
const previewCache = new Map<string, string>();
|
|
24
|
+
const previewPending = new Map<string, Promise<string>>();
|
|
25
|
+
const storyComponentIdentities = new WeakMap<StoryPreviewComponent, number>();
|
|
26
|
+
let previewTail = Promise.resolve();
|
|
27
|
+
let initialPreviewTurn: Promise<void> | null = null;
|
|
28
|
+
let nextStoryComponentIdentity = 1;
|
|
29
|
+
|
|
30
|
+
function supportsStoryCapture(): boolean {
|
|
31
|
+
return (
|
|
32
|
+
typeof WebGLRenderingContext !== 'undefined' &&
|
|
33
|
+
typeof navigator !== 'undefined' &&
|
|
34
|
+
!navigator.userAgent.toLowerCase().includes('jsdom')
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Keep GPU-backed card generation behind the authored viewport the user is
|
|
39
|
+
* waiting to see. A visible Content grid can mount many cards in the shell's
|
|
40
|
+
* first React commit; starting their off-screen renderers immediately made
|
|
41
|
+
* those thumbnails win the first WebGL context and delayed Scene by seconds. */
|
|
42
|
+
async function waitForInitialPreviewTurnInner(): Promise<void> {
|
|
43
|
+
await Promise.race([
|
|
44
|
+
waitForFirstViewportFrame(),
|
|
45
|
+
new Promise<void>((resolve) => setTimeout(resolve, 5_000)),
|
|
46
|
+
]);
|
|
47
|
+
// `recordViewportFirstFrame` runs immediately after issuing the draw, before
|
|
48
|
+
// the browser has necessarily composited it. Cross two animation frames so
|
|
49
|
+
// at least one paint can land before an off-screen thumbnail asks the GPU to
|
|
50
|
+
// create another renderer. Hidden tabs get a bounded timer fallback.
|
|
51
|
+
await Promise.race([
|
|
52
|
+
new Promise<void>((resolve) =>
|
|
53
|
+
requestAnimationFrame(() => requestAnimationFrame(() => resolve())),
|
|
54
|
+
),
|
|
55
|
+
new Promise<void>((resolve) => setTimeout(resolve, 250)),
|
|
56
|
+
]);
|
|
57
|
+
// Give pointer/automation tasks a turn after that paint. An idle callback can
|
|
58
|
+
// legally run before an external observer is scheduled; without this small
|
|
59
|
+
// grace period a software WebGL thumbnail context began immediately after
|
|
60
|
+
// Scene's first draw and made an already-visible cube appear two seconds
|
|
61
|
+
// late to the person (and to the editor's own control client).
|
|
62
|
+
await new Promise<void>((resolve) => setTimeout(resolve, 750));
|
|
63
|
+
await new Promise<void>((resolve) => {
|
|
64
|
+
const idle = globalThis.requestIdleCallback;
|
|
65
|
+
if (typeof idle === 'function') {
|
|
66
|
+
idle(() => resolve(), { timeout: 2_000 });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
setTimeout(resolve, 0);
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function waitForInitialPreviewTurn(): Promise<void> {
|
|
74
|
+
initialPreviewTurn ??= waitForInitialPreviewTurnInner();
|
|
75
|
+
return initialPreviewTurn;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function storyComponentIdentity(component: StoryPreviewComponent): number {
|
|
79
|
+
const existing = storyComponentIdentities.get(component);
|
|
80
|
+
if (existing !== undefined) return existing;
|
|
81
|
+
const identity = nextStoryComponentIdentity++;
|
|
82
|
+
storyComponentIdentities.set(component, identity);
|
|
83
|
+
return identity;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function requestPreview(
|
|
87
|
+
key: string,
|
|
88
|
+
surface: ProjectComponentEntry['surface'],
|
|
89
|
+
story: ProjectPreviewStory,
|
|
90
|
+
size: { readonly width: number; readonly height: number },
|
|
91
|
+
): Promise<string> {
|
|
92
|
+
const cached = previewCache.get(key);
|
|
93
|
+
if (cached) return Promise.resolve(cached);
|
|
94
|
+
const pending = previewPending.get(key);
|
|
95
|
+
if (pending) return pending;
|
|
96
|
+
const request = previewTail.then(async () => {
|
|
97
|
+
// Only the first off-screen renderer waits behind the opening viewport.
|
|
98
|
+
// `previewTail` already serializes all later GPU work; charging the paint
|
|
99
|
+
// grace to every card would make a full Content grid reveal one thumbnail
|
|
100
|
+
// every 750ms even after Scene is settled.
|
|
101
|
+
await waitForInitialPreviewTurn();
|
|
102
|
+
const declaredLayout = story.parameters['layout'];
|
|
103
|
+
const layout: PixiStoryThumbnailOptions['layout'] =
|
|
104
|
+
declaredLayout === 'fullscreen' ||
|
|
105
|
+
declaredLayout === 'padded' ||
|
|
106
|
+
declaredLayout === 'centered'
|
|
107
|
+
? declaredLayout
|
|
108
|
+
: 'padded';
|
|
109
|
+
const options = { ...size, props: story.args, layout };
|
|
110
|
+
if (surface === 'canvas') {
|
|
111
|
+
const { capturePixiStoryThumbnail } = await import('./story-pixi-preview');
|
|
112
|
+
return capturePixiStoryThumbnail(story.Component as StoryPreviewComponent, options);
|
|
113
|
+
}
|
|
114
|
+
const { captureStoryComponentThumbnail } = await import('./story-three-preview');
|
|
115
|
+
return captureStoryComponentThumbnail(story.Component as StoryPreviewComponent, options);
|
|
116
|
+
});
|
|
117
|
+
previewTail = request.then(
|
|
118
|
+
() => undefined,
|
|
119
|
+
() => undefined,
|
|
120
|
+
);
|
|
121
|
+
previewPending.set(key, request);
|
|
122
|
+
void request.then(
|
|
123
|
+
(url) => {
|
|
124
|
+
previewCache.set(key, url);
|
|
125
|
+
previewPending.delete(key);
|
|
126
|
+
},
|
|
127
|
+
() => previewPending.delete(key),
|
|
128
|
+
);
|
|
129
|
+
return request;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function StoryComponentThumbnail({
|
|
133
|
+
component,
|
|
134
|
+
story,
|
|
135
|
+
previewRevision,
|
|
136
|
+
width = 128,
|
|
137
|
+
height = 96,
|
|
138
|
+
}: {
|
|
139
|
+
component: Pick<ProjectComponentEntry, 'name' | 'path' | 'surface'>;
|
|
140
|
+
story: ProjectPreviewStory;
|
|
141
|
+
previewRevision: number;
|
|
142
|
+
/** Requested capture size. Content cards use 128×96; square Inspector
|
|
143
|
+
* previews request a square so the native subject is never cropped merely
|
|
144
|
+
* to fit different chrome. */
|
|
145
|
+
width?: number;
|
|
146
|
+
height?: number;
|
|
147
|
+
}) {
|
|
148
|
+
const StoryComponent = story.Component as StoryPreviewComponent;
|
|
149
|
+
// HMR replaces the composed component even when the story id/args stay the
|
|
150
|
+
// same. Include that native function identity so the Inspector cannot keep
|
|
151
|
+
// displaying the old capture after the source changed.
|
|
152
|
+
const key = `${component.surface}:${component.path}:${threeStoryThumbnailKey(story.id, story.args)}:${storyComponentIdentity(StoryComponent)}:${previewRevision}:${width}x${height}`;
|
|
153
|
+
const [url, setUrl] = useState(() => previewCache.get(key));
|
|
154
|
+
const [captureFailed, setCaptureFailed] = useState(false);
|
|
155
|
+
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
let cancelled = false;
|
|
158
|
+
setCaptureFailed(false);
|
|
159
|
+
setUrl(previewCache.get(key));
|
|
160
|
+
if (!supportsStoryCapture()) return;
|
|
161
|
+
void requestPreview(key, component.surface, story, { width, height }).then(
|
|
162
|
+
(nextUrl) => {
|
|
163
|
+
if (!cancelled) setUrl(nextUrl);
|
|
164
|
+
},
|
|
165
|
+
() => {
|
|
166
|
+
if (!cancelled) setCaptureFailed(true);
|
|
167
|
+
},
|
|
168
|
+
);
|
|
169
|
+
return () => {
|
|
170
|
+
cancelled = true;
|
|
171
|
+
};
|
|
172
|
+
}, [component.surface, height, key, story, width]);
|
|
173
|
+
|
|
174
|
+
return url ? (
|
|
175
|
+
<img src={url} alt={`${component.name} preview`} className="vgai-component-thumbnail" />
|
|
176
|
+
) : (
|
|
177
|
+
<span
|
|
178
|
+
className="vgai-component-thumbnail-fallback"
|
|
179
|
+
data-component-preview={captureFailed ? 'failed' : 'capturing-story'}
|
|
180
|
+
>
|
|
181
|
+
<TypedAssetThumbnail kind="component" name={component.name} />
|
|
182
|
+
</span>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Isolated story preview mount — C3 (spec §9 "A story may be opened in an
|
|
3
|
+
* isolated editor preview"). Renders one composed story (`ComposedProjectStory`
|
|
4
|
+
* from `compose-project-stories.ts`) into a SEPARATE `react-dom/client` root,
|
|
5
|
+
* not a child of the editor's own React tree: the preview container div is
|
|
6
|
+
* handed to its own `createRoot`, so a story's own React version/context/
|
|
7
|
+
* error state can never leak into (or be affected by) the editor shell's
|
|
8
|
+
* tree — the same isolation a Storybook iframe gives you, achieved here with
|
|
9
|
+
* a dedicated root instead (this editor has no existing iframe-preview
|
|
10
|
+
* pattern to reuse — see the module doc comment on `StoriesPanel.tsx`).
|
|
11
|
+
*
|
|
12
|
+
* Error handling (spec §9 "Errors identify the source module and story
|
|
13
|
+
* export"): a story that throws while rendering is caught by
|
|
14
|
+
* `StoryPreviewErrorBoundary` (mirrors `ToolHost.tsx`'s `ToolErrorBoundary`)
|
|
15
|
+
* and reported with BOTH the module path and the story export name — one
|
|
16
|
+
* throwing story never takes down the panel or another story's preview.
|
|
17
|
+
*
|
|
18
|
+
* Play functions (spec §9 "supported play functions mount... optional but
|
|
19
|
+
* nice"): `runPlay` below calls the composed story's own `.play()` (Storybook
|
|
20
|
+
* populates it via `composeStories` when the CSF export declares one) inside
|
|
21
|
+
* the SAME error containment, so a throwing play function reports the same
|
|
22
|
+
* module+export naming instead of crashing the preview. `play()` is called
|
|
23
|
+
* with `{ canvasElement }` set to the isolated preview root's own container —
|
|
24
|
+
* without it, Storybook's portable-story `play()` defaults `canvasElement` to
|
|
25
|
+
* `document.body` (confirmed in `storybook/dist/preview-api/index.cjs`'s
|
|
26
|
+
* `composeStory`: `g.canvasElement ??= globalThis?.document?.body`), which
|
|
27
|
+
* would let a story's play() query/interact with the ENTIRE page instead of
|
|
28
|
+
* just its own isolated preview.
|
|
29
|
+
*
|
|
30
|
+
* Loaders (spec §9 "loaders ... mount through Storybook portable-story
|
|
31
|
+
* APIs"): a composed story only runs its `loaders` when `.load()` is
|
|
32
|
+
* explicitly awaited before render. Confirmed directly in Storybook 9's own
|
|
33
|
+
* `composeStory` (`storybook/dist/preview-api/index.cjs`): the render
|
|
34
|
+
* function reads a module-closure variable (`x`) for `loaded` data, and that
|
|
35
|
+
* variable is populated ONLY inside `load: async () => { ...; f.loaded =
|
|
36
|
+
* await c.applyLoaders(f); ...; x = f; }` — i.e. `applyLoaders` (which runs
|
|
37
|
+
* every `loaders` entry) never runs unless `.load()` itself runs first.
|
|
38
|
+
* Rendering the composed component directly (no `.load()`) leaves `loaded`
|
|
39
|
+
* as `{}`. `mountIsolatedStory` below is therefore async and awaits
|
|
40
|
+
* `StoryComponent.load()` before calling `root.render(...)`.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
import { markGameCssScope } from '@volter/editor-sdk/session/game-css-scope';
|
|
44
|
+
import { themeVars } from '@volter/editor-sdk/widgets';
|
|
45
|
+
import { Component, type ErrorInfo, type ReactNode } from 'react';
|
|
46
|
+
import type { Root } from 'react-dom/client';
|
|
47
|
+
import type { ComposedStoryFn } from 'storybook/internal/types';
|
|
48
|
+
import { getCurrentProject } from '../project-manager';
|
|
49
|
+
import { ensureScopedGameStyles } from '../scoped-game-css';
|
|
50
|
+
import { resolveStoryDomRuntime } from './story-dom-runtime';
|
|
51
|
+
|
|
52
|
+
interface StoryPreviewErrorBoundaryProps {
|
|
53
|
+
modulePath: string;
|
|
54
|
+
storyName: string;
|
|
55
|
+
children: ReactNode;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface StoryPreviewErrorBoundaryState {
|
|
59
|
+
error: Error | null;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Crash containment for one mounted story — names both the source module
|
|
63
|
+
* AND the story export in the fallback UI and the console, per spec §9. */
|
|
64
|
+
export class StoryPreviewErrorBoundary extends Component<
|
|
65
|
+
StoryPreviewErrorBoundaryProps,
|
|
66
|
+
StoryPreviewErrorBoundaryState
|
|
67
|
+
> {
|
|
68
|
+
override state: StoryPreviewErrorBoundaryState = { error: null };
|
|
69
|
+
|
|
70
|
+
static getDerivedStateFromError(error: Error): StoryPreviewErrorBoundaryState {
|
|
71
|
+
return { error };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
override componentDidCatch(error: Error, info: ErrorInfo): void {
|
|
75
|
+
// biome-ignore lint/suspicious/noConsole: deliberate, greppable — a crashed story preview must be diagnosable from the console (spec §9 "errors identify the source module and story export"), mirroring ToolHost.tsx's ToolErrorBoundary
|
|
76
|
+
console.error(
|
|
77
|
+
`[stories] ${this.props.modulePath} — story "${this.props.storyName}" crashed while rendering:`,
|
|
78
|
+
error,
|
|
79
|
+
info.componentStack,
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
override render(): ReactNode {
|
|
84
|
+
if (this.state.error) {
|
|
85
|
+
return (
|
|
86
|
+
<div style={{ padding: 12, fontSize: 12, color: themeVars.semantic.danger, maxWidth: 640 }}>
|
|
87
|
+
<div style={{ fontWeight: 600, marginBottom: 4 }}>
|
|
88
|
+
Story crashed: <code>{this.props.modulePath}</code> — export{' '}
|
|
89
|
+
<code>{this.props.storyName}</code>
|
|
90
|
+
</div>
|
|
91
|
+
<div style={{ whiteSpace: 'pre-wrap' }}>{String(this.state.error)}</div>
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
return this.props.children;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** One container's isolated root plus a generation counter — see
|
|
100
|
+
* `mountIsolatedStory` below for why the counter (not just the `Root`
|
|
101
|
+
* object's identity) is what a stale `unmount()` must check. `root` is
|
|
102
|
+
* `undefined` for the brief window between a mount call CLAIMING a
|
|
103
|
+
* generation (synchronously) and that same call's `await
|
|
104
|
+
* StoryComponent.load()` resolving — no `Root` exists yet for a container
|
|
105
|
+
* that has never been rendered into before (the very first mount), so the
|
|
106
|
+
* reservation itself can't supply one. */
|
|
107
|
+
interface ContainerMount {
|
|
108
|
+
root: Root | undefined;
|
|
109
|
+
generation: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// One isolated `react-dom/client` root per container, reused across repeated
|
|
113
|
+
// `mountIsolatedStory` calls (e.g. a story switch: `StoriesPanel.tsx`'s
|
|
114
|
+
// `StoryPreviewHost` effect re-fires for the SAME DOM node with a new
|
|
115
|
+
// `StoryComponent`). Calling `createRoot` twice on the SAME node is a hard
|
|
116
|
+
// react-dom warning ("already been passed to createRoot() before") — this
|
|
117
|
+
// map is the guard: a second `mountIsolatedStory` on the same container
|
|
118
|
+
// `.render()`s onto the EXISTING root instead of creating a new one, exactly
|
|
119
|
+
// react-dom's own documented fix for that warning.
|
|
120
|
+
const mountsByContainer = new WeakMap<HTMLElement, ContainerMount>();
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Mount one composed story into `container` via its OWN `createRoot` —
|
|
124
|
+
* isolated from whatever React root `container` itself lives inside.
|
|
125
|
+
* Returns an `unmount` the caller runs on cleanup (e.g. story switch or
|
|
126
|
+
* panel close) — same lifecycle discipline every other editor mount point
|
|
127
|
+
* (`XStateMachineInspector.test.tsx`'s harness, `ToolHost`) uses. Safe to
|
|
128
|
+
* call again on the same `container` before a previous `unmount()` has
|
|
129
|
+
* landed (see `mountsByContainer` above) — the isolated root is reused, and
|
|
130
|
+
* `unmount()` (below) removes it from the container entirely rather than
|
|
131
|
+
* merely clearing its content, so callers who intend a REAL teardown (panel
|
|
132
|
+
* close) still get one.
|
|
133
|
+
*
|
|
134
|
+
* Async: awaits `StoryComponent.load()` (runs the story's `loaders`, per the
|
|
135
|
+
* module doc comment above) BEFORE the first render. The generation counter
|
|
136
|
+
* is claimed SYNCHRONOUSLY (before the `await`), exactly like the sync
|
|
137
|
+
* version did — so a second `mountIsolatedStory` call on the same container
|
|
138
|
+
* (e.g. the user switches stories again while this one's `.load()` is still
|
|
139
|
+
* in flight) still bumps the generation immediately and makes it visible to
|
|
140
|
+
* this in-flight call. After the await, this call re-reads the container's
|
|
141
|
+
* CURRENT generation and bails out (never creates/renders a root, never
|
|
142
|
+
* touches `mountsByContainer`) if it's no longer the current one — so a
|
|
143
|
+
* stale `.load()` resolving late can never win a render race against a
|
|
144
|
+
* newer story switch, even though nothing was mounted yet for it to
|
|
145
|
+
* unmount.
|
|
146
|
+
*/
|
|
147
|
+
export async function mountIsolatedStory(
|
|
148
|
+
container: HTMLElement,
|
|
149
|
+
modulePath: string,
|
|
150
|
+
storyName: string,
|
|
151
|
+
StoryComponent: ComposedStoryFn,
|
|
152
|
+
// W2 (story documents): optional per-mount prop overrides. Portable
|
|
153
|
+
// stories are plain React components whose composed args are DEFAULTS —
|
|
154
|
+
// Storybook's own documented portable-story contract lets a caller pass
|
|
155
|
+
// partial props over them (`<Story label="…" />`). The story-document
|
|
156
|
+
// Inspector's editable args and its action-logging spies ride this;
|
|
157
|
+
// omitted (every pre-W2 caller) the render is byte-identical to before.
|
|
158
|
+
overrideProps?: Record<string, unknown>,
|
|
159
|
+
): Promise<{ root: Root; unmount: () => void } | null> {
|
|
160
|
+
const existing = mountsByContainer.get(container);
|
|
161
|
+
// Bumped on EVERY mount, including a reuse of the same `Root` object (a
|
|
162
|
+
// story switch) — this is the piece a same-root reuse needs that plain
|
|
163
|
+
// `Root`-identity checking (an earlier version of this function) doesn't
|
|
164
|
+
// give you: reusing the root means two DIFFERENT stories' mounts can share
|
|
165
|
+
// the exact same `Root` instance, so a stale `unmount()` comparing
|
|
166
|
+
// `Root`s would see "yes, that's still the registered root" and tear down
|
|
167
|
+
// the NEWER story's render a moment after it landed. Comparing the
|
|
168
|
+
// generation this specific `mountIsolatedStory` call captured against the
|
|
169
|
+
// container's CURRENT generation instead correctly recognizes "a newer
|
|
170
|
+
// mount has since claimed this container" even when the root itself
|
|
171
|
+
// didn't change. Claimed HERE, synchronously, before the `load()` await
|
|
172
|
+
// below — so a newer call arriving while this one awaits sees (and bumps
|
|
173
|
+
// past) this generation immediately, rather than racing to claim the same
|
|
174
|
+
// number once both awaits resolve.
|
|
175
|
+
const generation = (existing?.generation ?? 0) + 1;
|
|
176
|
+
mountsByContainer.set(container, { root: existing?.root, generation });
|
|
177
|
+
|
|
178
|
+
// THE STORY'S OWN PAGE CSS, if its project has any. A story of a foreign
|
|
179
|
+
// game's HUD component is a plain React component whose entire layout lives
|
|
180
|
+
// in that game's page-level stylesheet — without it the card renders real
|
|
181
|
+
// DOM with zero layout, which reads as wreckage rather than as a component.
|
|
182
|
+
// This is the ONE seam every story surface passes through (the UI board's
|
|
183
|
+
// cards, the story documents, `vgai screenshot <file>.stories.tsx`), so
|
|
184
|
+
// marking the container here styles all of them; the sheet itself is
|
|
185
|
+
// installed once per project, never per card (`scoped-game-css.ts`).
|
|
186
|
+
// Deliberately awaited BEFORE the first render so a card never flashes
|
|
187
|
+
// unstyled, and deliberately non-fatal: a project with no declared
|
|
188
|
+
// stylesheet mounts exactly as it did before.
|
|
189
|
+
markGameCssScope(container);
|
|
190
|
+
const currentProject = getCurrentProject();
|
|
191
|
+
if (currentProject) await ensureScopedGameStyles(currentProject.rootPath);
|
|
192
|
+
|
|
193
|
+
// Loaders (spec §9): must run — and their `loaded` data become part of the
|
|
194
|
+
// composed story's render-time context — before the story is ever
|
|
195
|
+
// rendered. See the module doc comment for why this can't be skipped.
|
|
196
|
+
await StoryComponent.load();
|
|
197
|
+
|
|
198
|
+
// WHICH graph's react-dom mounts the story is the packaged-runtime seam
|
|
199
|
+
// (`story-dom-runtime.ts`): the CSF component's hooks resolve against the
|
|
200
|
+
// project's react, so the mounting `createRoot` must come from that same
|
|
201
|
+
// graph or the render dies on "Invalid hook call". Resolved BEFORE the
|
|
202
|
+
// generation re-check below, so the stale-call guard covers every await
|
|
203
|
+
// this call performs. (The error-boundary wrapper stays this bundle's own
|
|
204
|
+
// React deliberately: it is a class component — no hooks, no dispatcher —
|
|
205
|
+
// and React elements are cross-instance by design via Symbol.for.)
|
|
206
|
+
const { createRoot, flushSync } = await resolveStoryDomRuntime();
|
|
207
|
+
|
|
208
|
+
// Re-check AFTER the await: if a newer `mountIsolatedStory` call (story
|
|
209
|
+
// switch) has since claimed this container, its generation will have
|
|
210
|
+
// moved past `generation` above — this stale call must not create a root
|
|
211
|
+
// or render into a container a newer story already owns (or is about to).
|
|
212
|
+
const afterLoad = mountsByContainer.get(container);
|
|
213
|
+
if (!afterLoad || afterLoad.generation !== generation) return null;
|
|
214
|
+
|
|
215
|
+
const root = existing?.root ?? createRoot(container);
|
|
216
|
+
mountsByContainer.set(container, { root, generation });
|
|
217
|
+
|
|
218
|
+
// A resolved mount is a COMMITTED mount. The UI/2D boards await this
|
|
219
|
+
// function before announcing their document ready, and Doctor photographs
|
|
220
|
+
// that document immediately afterward. Leaving `root.render()` on React's
|
|
221
|
+
// scheduler produced a perfectly plausible empty board: its synchronous
|
|
222
|
+
// frame chrome existed, but every authored story was still absent. Use the
|
|
223
|
+
// `flushSync` from the SAME project-owned React graph as `createRoot` (the
|
|
224
|
+
// ordinary React design-time entry mount has the identical contract in
|
|
225
|
+
// `design-time-layers.ts`). This is not capture-specific waiting: every
|
|
226
|
+
// caller now receives the honest lifecycle guarantee its return value
|
|
227
|
+
// implies.
|
|
228
|
+
flushSync(() => {
|
|
229
|
+
root.render(
|
|
230
|
+
<StoryPreviewErrorBoundary modulePath={modulePath} storyName={storyName}>
|
|
231
|
+
{/* `ComposedStoryFn` is a callable React function component
|
|
232
|
+
(Storybook's portable-story contract) — its own composed
|
|
233
|
+
args/decorators are already baked in by `composeStories`;
|
|
234
|
+
`overrideProps` (when given) override individual args per that same
|
|
235
|
+
contract. */}
|
|
236
|
+
<StoryComponent {...(overrideProps ?? {})} />
|
|
237
|
+
</StoryPreviewErrorBoundary>,
|
|
238
|
+
);
|
|
239
|
+
});
|
|
240
|
+
return {
|
|
241
|
+
root,
|
|
242
|
+
// Deferred to a microtask, deliberately NOT called synchronously:
|
|
243
|
+
// `unmount` is returned as `StoryPreviewHost`'s effect cleanup, and
|
|
244
|
+
// React runs an effect's cleanup SYNCHRONOUSLY as part of its own
|
|
245
|
+
// render/commit pass whenever the OUTER tree unmounts (e.g. the whole
|
|
246
|
+
// Stories panel closing). React tracks "is any root currently
|
|
247
|
+
// rendering" as a single GLOBAL flag for the whole call stack
|
|
248
|
+
// (`executionContext`, react-dom-client.development.js) — so calling
|
|
249
|
+
// THIS (independent, inner) root's `.unmount()` synchronously from
|
|
250
|
+
// inside that outer pass trips "Attempted to synchronously unmount a
|
|
251
|
+
// root while React was already rendering" even though the inner root
|
|
252
|
+
// itself has nothing in flight. Queuing the call for the next microtask
|
|
253
|
+
// runs it once the outer commit has fully finished and cleared that
|
|
254
|
+
// flag, which is the documented fix for exactly this nested-root
|
|
255
|
+
// pattern (no functional delay — the isolated root is still torn down
|
|
256
|
+
// effectively immediately).
|
|
257
|
+
unmount: () => {
|
|
258
|
+
queueMicrotask(() => {
|
|
259
|
+
// Only the mount that's STILL the container's current generation
|
|
260
|
+
// actually tears the root down — see the `generation` doc comment
|
|
261
|
+
// above for why this can't just compare `Root` identity.
|
|
262
|
+
const current = mountsByContainer.get(container);
|
|
263
|
+
if (!current || current.generation !== generation || !current.root) return;
|
|
264
|
+
mountsByContainer.delete(container);
|
|
265
|
+
current.root.unmount();
|
|
266
|
+
});
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Run a composed story's `.play()` if it declared one, inside the same
|
|
273
|
+
* module+export-naming error containment as render crashes. Returns whether
|
|
274
|
+
* a play function existed and ran ok — the caller (`StoriesPanel`) uses this
|
|
275
|
+
* to show a "no play function" state distinctly from a failure.
|
|
276
|
+
*
|
|
277
|
+
* `canvasElement` is passed through to `.play({ canvasElement })` — the
|
|
278
|
+
* composed story's own `play` accepts `Partial<StoryContext>` (confirmed in
|
|
279
|
+
* `storybook/dist/types/index.d.ts`: `play?: (context?: Partial<StoryContext<...>>)
|
|
280
|
+
* => Promise<void>`, and `StoryContext.canvasElement: TRenderer['canvasElement']`).
|
|
281
|
+
* Without it, Storybook's `composeStory` defaults `canvasElement` to
|
|
282
|
+
* `globalThis.document.body` (`storybook/dist/preview-api/index.cjs`:
|
|
283
|
+
* `g.canvasElement ??= globalThis?.document?.body`), which would let a
|
|
284
|
+
* story's play() query/interact with the WHOLE page instead of just its own
|
|
285
|
+
* isolated preview root.
|
|
286
|
+
*/
|
|
287
|
+
export async function runStoryPlay(
|
|
288
|
+
modulePath: string,
|
|
289
|
+
storyName: string,
|
|
290
|
+
StoryComponent: ComposedStoryFn,
|
|
291
|
+
canvasElement: HTMLElement,
|
|
292
|
+
): Promise<{ ran: boolean; error?: string }> {
|
|
293
|
+
if (typeof StoryComponent.play !== 'function') return { ran: false };
|
|
294
|
+
try {
|
|
295
|
+
await StoryComponent.play({ canvasElement });
|
|
296
|
+
return { ran: true };
|
|
297
|
+
} catch (err) {
|
|
298
|
+
const message = String(err instanceof Error ? err.message : err);
|
|
299
|
+
// biome-ignore lint/suspicious/noConsole: deliberate, greppable — a throwing play() must be diagnosable from the console, same naming discipline as a render crash
|
|
300
|
+
console.error(`[stories] ${modulePath} — story "${storyName}"'s play() threw:`, err);
|
|
301
|
+
return {
|
|
302
|
+
ran: true,
|
|
303
|
+
error: `[stories] ${modulePath} — story "${storyName}"'s play() failed: ${message}`,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "COMPONENTS WITH A REGISTERED PREVIEW STORY" — this package's filler for the
|
|
3
|
+
* host's Content scope (`@editor/content-entry-source-registry`).
|
|
4
|
+
*
|
|
5
|
+
* A registered portable story is the explicit prefab declaration and its
|
|
6
|
+
* preview authority: source shape alone cannot distinguish a reusable prefab
|
|
7
|
+
* from scene composition or implementation detail, so a component with no
|
|
8
|
+
* colocated story is not a Content entry at all. That rule used to be spelled
|
|
9
|
+
* in `components/AssetBrowser.tsx` — the host's own Content browser knowing
|
|
10
|
+
* what CSF is — and it is the reason the story registry, and through it
|
|
11
|
+
* Storybook, was in every editor boot.
|
|
12
|
+
*
|
|
13
|
+
* WHAT MOVED WITH IT, verbatim:
|
|
14
|
+
* - the admission rule (`pickComponentPreviewStory`, and the surface focus:
|
|
15
|
+
* DOM stories live on their design board, world prefabs stay scoped to the
|
|
16
|
+
* surface that can consume them);
|
|
17
|
+
* - the picture (`StoryComponentThumbnail`);
|
|
18
|
+
* - the open verb — a `three` prefab mounts as an `Object3D`, so it opens as
|
|
19
|
+
* its TURNTABLE (`story:three`, the same document the `3D Components`
|
|
20
|
+
* board's exhibits open on); anything else opens on the isolated story
|
|
21
|
+
* document (`story:isolated`). Both are ADDRESSES
|
|
22
|
+
* (`@editor/document-open-registry`): the documents themselves are
|
|
23
|
+
* `@vgai/game`'s, and a build without it opens neither.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import type {
|
|
27
|
+
ContentComponentRef,
|
|
28
|
+
ContentEntry,
|
|
29
|
+
ContentEntrySource,
|
|
30
|
+
ContentEntrySourceContext,
|
|
31
|
+
ContentEntryThumbnailProps,
|
|
32
|
+
} from '../content-entry-source-registry';
|
|
33
|
+
import { openRegisteredDocument } from '../document-open-registry';
|
|
34
|
+
import type { WorkspaceStateStore } from '../workspace-document-restore';
|
|
35
|
+
import { StoryComponentThumbnail } from './StoryComponentThumbnail';
|
|
36
|
+
import {
|
|
37
|
+
ISOLATED_STORY_DOCUMENT_OPENER,
|
|
38
|
+
THREE_STORY_DOCUMENT_OPENER,
|
|
39
|
+
} from './story-document-openers';
|
|
40
|
+
import {
|
|
41
|
+
getProjectStoryModules,
|
|
42
|
+
type ProjectPreviewStory,
|
|
43
|
+
pickComponentPreviewStory,
|
|
44
|
+
subscribeProjectStoryModules,
|
|
45
|
+
} from './story-registry';
|
|
46
|
+
|
|
47
|
+
/** What this source carries on each row: the story that admitted the
|
|
48
|
+
* component, which is also its picture and its open address. */
|
|
49
|
+
type StoryContentDetail = ProjectPreviewStory;
|
|
50
|
+
|
|
51
|
+
function belongsInFocusedContent(
|
|
52
|
+
component: ContentComponentRef,
|
|
53
|
+
surface: ContentEntrySourceContext['surface'],
|
|
54
|
+
): boolean {
|
|
55
|
+
if (component.surface === 'dom') return false;
|
|
56
|
+
return surface === null || component.surface === surface;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function StoryContentThumbnail({
|
|
60
|
+
entry,
|
|
61
|
+
previewRevision,
|
|
62
|
+
width,
|
|
63
|
+
height,
|
|
64
|
+
}: ContentEntryThumbnailProps) {
|
|
65
|
+
const story = entry.detail as StoryContentDetail;
|
|
66
|
+
return (
|
|
67
|
+
<StoryComponentThumbnail
|
|
68
|
+
component={entry.component}
|
|
69
|
+
story={story}
|
|
70
|
+
previewRevision={previewRevision}
|
|
71
|
+
{...(width === undefined ? {} : { width })}
|
|
72
|
+
{...(height === undefined ? {} : { height })}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const STORY_CONTENT_SOURCE_ID = 'story';
|
|
78
|
+
|
|
79
|
+
export const storyComponentContentSource: ContentEntrySource = {
|
|
80
|
+
id: STORY_CONTENT_SOURCE_ID,
|
|
81
|
+
owner: './component-content-source',
|
|
82
|
+
entries(context): readonly ContentEntry[] {
|
|
83
|
+
const modules = getProjectStoryModules();
|
|
84
|
+
const out: ContentEntry[] = [];
|
|
85
|
+
for (const component of context.components) {
|
|
86
|
+
if (!belongsInFocusedContent(component, context.surface)) continue;
|
|
87
|
+
const story = pickComponentPreviewStory(modules, component.name, component.path);
|
|
88
|
+
if (!story) continue;
|
|
89
|
+
out.push({ id: `${component.path}:${component.name}`, component, detail: story });
|
|
90
|
+
}
|
|
91
|
+
return out;
|
|
92
|
+
},
|
|
93
|
+
subscribe: subscribeProjectStoryModules,
|
|
94
|
+
Thumbnail: StoryContentThumbnail,
|
|
95
|
+
open(store: WorkspaceStateStore, entry: ContentEntry, title: string): void {
|
|
96
|
+
const story = entry.detail as StoryContentDetail;
|
|
97
|
+
const three = entry.component.surface === 'three';
|
|
98
|
+
openRegisteredDocument(
|
|
99
|
+
three ? THREE_STORY_DOCUMENT_OPENER : ISOLATED_STORY_DOCUMENT_OPENER,
|
|
100
|
+
store,
|
|
101
|
+
three
|
|
102
|
+
? { modulePath: story.modulePath, storyName: story.name, title }
|
|
103
|
+
: { modulePath: story.modulePath, storyName: story.name },
|
|
104
|
+
);
|
|
105
|
+
},
|
|
106
|
+
};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PORTABLE CSF AS A COMPONENT'S NAMED STATES — the source
|
|
3
|
+
* `component-states-registry.ts` is filled with, registered by
|
|
4
|
+
* `story-lane.ts`.
|
|
5
|
+
*
|
|
6
|
+
* It was `authoring/project-three-stories.ts`, two nearly identical
|
|
7
|
+
* factory functions that three host adapters CONSTRUCTED inside their own
|
|
8
|
+
* constructors. The measurement said the two differed by exactly one thing —
|
|
9
|
+
* which document a state opens in — so this is ONE source that dispatches on
|
|
10
|
+
* the asking adapter's surface, the same way the story opener's own readiness
|
|
11
|
+
* does.
|
|
12
|
+
*
|
|
13
|
+
* IT DOES NOT MOUNT A SECOND PREVIEW DIALECT. Applying a state opens the
|
|
14
|
+
* document that already exists for that surface: the Object3D turntable for a
|
|
15
|
+
* three subject (whose portable Storybook component mounts as an Object3D on
|
|
16
|
+
* the standard Asset Lab viewport), and the ordinary isolated story document
|
|
17
|
+
* for a canvas one (whose renderer can mount `@pixi/react` content). The
|
|
18
|
+
* adapter supplies the component identity; the CSF registry owns
|
|
19
|
+
* discovery and association.
|
|
20
|
+
*
|
|
21
|
+
* A `dom` subject is deliberately not an arm: a React world's own states come
|
|
22
|
+
* from `@vgai/dom`'s adapter, which publishes its own `StoriesProvider`
|
|
23
|
+
* against the board it mounts. This source answers for the two surfaces whose
|
|
24
|
+
* adapters used to construct the CSF provider by hand.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import type {
|
|
28
|
+
ComponentStatesContext,
|
|
29
|
+
ComponentStatesRef,
|
|
30
|
+
ComponentStatesSource,
|
|
31
|
+
} from '../component-states-registry';
|
|
32
|
+
import { openRegisteredDocument } from '../document-open-registry';
|
|
33
|
+
import { editorConsole } from '../editor-console';
|
|
34
|
+
import {
|
|
35
|
+
ISOLATED_STORY_DOCUMENT_OPENER,
|
|
36
|
+
THREE_STORY_DOCUMENT_OPENER,
|
|
37
|
+
} from './story-document-openers';
|
|
38
|
+
import { getComponentPreviewStories, type ProjectPreviewStory } from './story-registry';
|
|
39
|
+
|
|
40
|
+
function storiesFor(component: ComponentStatesRef): ProjectPreviewStory[] {
|
|
41
|
+
return getComponentPreviewStories(component.name, component.sourcePath);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const componentStatesSource: ComponentStatesSource = {
|
|
45
|
+
id: 'portable-csf',
|
|
46
|
+
owner: './component-states',
|
|
47
|
+
statesFor: (component, context) =>
|
|
48
|
+
context.surface === 'dom'
|
|
49
|
+
? []
|
|
50
|
+
: storiesFor(component).map((story) => ({ id: story.id, label: story.label })),
|
|
51
|
+
apply: (component, stateId, context: ComponentStatesContext) => {
|
|
52
|
+
const story = storiesFor(component).find((candidate) => candidate.id === stateId);
|
|
53
|
+
if (!story) return;
|
|
54
|
+
if (context.surface === 'three') {
|
|
55
|
+
openRegisteredDocument(THREE_STORY_DOCUMENT_OPENER, context.store, {
|
|
56
|
+
modulePath: story.modulePath,
|
|
57
|
+
storyName: story.name,
|
|
58
|
+
title: story.label,
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (context.surface === 'canvas') {
|
|
63
|
+
openRegisteredDocument(ISOLATED_STORY_DOCUMENT_OPENER, context.store, {
|
|
64
|
+
modulePath: story.modulePath,
|
|
65
|
+
storyName: story.name,
|
|
66
|
+
});
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// `statesFor` never named a state for this surface, so nothing should ever
|
|
70
|
+
// reach here; say so rather than silently doing nothing, because a new
|
|
71
|
+
// surface arriving is exactly how this would go quiet.
|
|
72
|
+
editorConsole.warn(
|
|
73
|
+
`[portable-csf] no story document is registered for the "${context.surface}" surface, ` +
|
|
74
|
+
`so state "${stateId}" of "${component.name}" could not be opened.`,
|
|
75
|
+
'authoring',
|
|
76
|
+
);
|
|
77
|
+
},
|
|
78
|
+
};
|