@volter/sdk 0.0.0-stage → 0.5.204
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/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +38 -3
- package/package.json +510 -4
- package/src/account.ts +210 -0
- package/src/chrome.ts +88 -0
- package/src/client.ts +1646 -0
- package/src/commands.ts +66 -0
- package/src/contributions.ts +619 -0
- package/src/css-numeric-style.ts +97 -0
- package/src/document-probe.ts +282 -0
- package/src/editor-view.ts +225 -0
- package/src/extension.ts +40 -0
- package/src/generations.ts +178 -0
- package/src/host.ts +1157 -0
- package/src/http-transport.browser.ts +14 -0
- package/src/http-transport.node.ts +19 -0
- package/src/index.ts +131 -0
- package/src/kit/CapabilityCoverageSection.tsx +185 -0
- package/src/kit/account-client.ts +333 -0
- package/src/kit/action-registry.ts +317 -0
- package/src/kit/active-product.ts +76 -0
- package/src/kit/active-project.ts +155 -0
- package/src/kit/adapter-editor-config.ts +25 -0
- package/src/kit/adapter-module.ts +7 -0
- package/src/kit/adapter-observation.ts +49 -0
- package/src/kit/animation/animation-clock.ts +479 -0
- package/src/kit/animation/stage-transport.ts +385 -0
- package/src/kit/api/assets.ts +365 -0
- package/src/kit/api/project-open.ts +355 -0
- package/src/kit/api/project-source.ts +180 -0
- package/src/kit/api/project-state.ts +110 -0
- package/src/kit/api/relay.ts +270 -0
- package/src/kit/api/themes.ts +45 -0
- package/src/kit/api-asset-library-wire.ts +45 -0
- package/src/kit/api-base.ts +10 -0
- package/src/kit/api-build.ts +99 -0
- package/src/kit/api-git-wire.ts +56 -0
- package/src/kit/api-logs.ts +92 -0
- package/src/kit/api-project-identity.ts +74 -0
- package/src/kit/api-settings.ts +36 -0
- package/src/kit/api-worktrees.ts +205 -0
- package/src/kit/asset-capabilities.ts +344 -0
- package/src/kit/asset-compare-core.ts +171 -0
- package/src/kit/asset-editor-context.tsx +101 -0
- package/src/kit/asset-events.ts +96 -0
- package/src/kit/asset-inspector-actions.ts +87 -0
- package/src/kit/asset-selection-viewer-registry.ts +113 -0
- package/src/kit/asset-selection.ts +146 -0
- package/src/kit/asset-thumbnails.ts +25 -0
- package/src/kit/asset-viewers.ts +115 -0
- package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/kit/asset-workflow/asset-ledger.ts +156 -0
- package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/kit/asset-workflow/asset-types.ts +142 -0
- package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
- package/src/kit/asset-workflow/audio-waveform.ts +22 -0
- package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/kit/asset-workflow/image-view-scale.ts +31 -0
- package/src/kit/asset-workflow/import-contract.ts +124 -0
- package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
- package/src/kit/asset-workflow/project-content.ts +288 -0
- package/src/kit/asset-workflow/project-source-index.ts +545 -0
- package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
- package/src/kit/authoring/active-adapter.ts +200 -0
- package/src/kit/authoring/active-systems.ts +422 -0
- package/src/kit/authoring/adapter-key.ts +18 -0
- package/src/kit/authoring/authoring-asset-url.ts +27 -0
- package/src/kit/authoring/bootstrap-state.ts +49 -0
- package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
- package/src/kit/authoring/canvas-scene-guides.ts +84 -0
- package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
- package/src/kit/authoring/consumer-actions.ts +531 -0
- package/src/kit/authoring/design-time-layers.ts +852 -0
- package/src/kit/authoring/design-time-mount-registry.ts +244 -0
- package/src/kit/authoring/edit-mode-authoring.ts +637 -0
- package/src/kit/authoring/empty-project-authoring.ts +22 -0
- package/src/kit/authoring/instance-source-menu.ts +135 -0
- package/src/kit/authoring/layered-pick.ts +185 -0
- package/src/kit/authoring/mounted-root-subjects.ts +146 -0
- package/src/kit/authoring/no-authoring-adapter.ts +59 -0
- package/src/kit/authoring/object3d-document-persistence.ts +122 -0
- package/src/kit/authoring/panel-authoring.ts +121 -0
- package/src/kit/authoring/project-authoring-session.ts +105 -0
- package/src/kit/authoring/provenance.ts +99 -0
- package/src/kit/authoring/react-canvas-navigation.ts +259 -0
- package/src/kit/authoring/react-design-canvas-style.ts +20 -0
- package/src/kit/authoring/react-story-board.ts +917 -0
- package/src/kit/authoring/selection-scope.ts +195 -0
- package/src/kit/authoring/shell-document-ops.ts +169 -0
- package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
- package/src/kit/authoring/story-board-presentation.ts +111 -0
- package/src/kit/authoring/three-root.ts +67 -0
- package/src/kit/authoring/viewport-tool-context.ts +73 -0
- package/src/kit/authoring/viewport-tool-owner.ts +38 -0
- package/src/kit/authoring/world-session-state.ts +101 -0
- package/src/kit/authoring-seam-evidence.ts +300 -0
- package/src/kit/availability-tick.ts +66 -0
- package/src/kit/bitmap-label.ts +120 -0
- package/src/kit/boot-routing.ts +392 -0
- package/src/kit/breakpoint-state.ts +43 -0
- package/src/kit/build-identity.ts +16 -0
- package/src/kit/bytes-codec.ts +62 -0
- package/src/kit/cancellation-reason.ts +58 -0
- package/src/kit/canvas-frames.ts +88 -0
- package/src/kit/capture-camera-pose.ts +77 -0
- package/src/kit/capture-size.ts +88 -0
- package/src/kit/chrome-registry.ts +159 -0
- package/src/kit/chrome-slot-registry.ts +91 -0
- package/src/kit/collaboration-client.ts +264 -0
- package/src/kit/collaboration-presence.ts +41 -0
- package/src/kit/command-dispatch.ts +19 -0
- package/src/kit/command-listener.ts +2182 -0
- package/src/kit/command-registry.ts +71 -0
- package/src/kit/component-board-registry.ts +205 -0
- package/src/kit/component-states-registry.ts +199 -0
- package/src/kit/components/AlignToolbar.tsx +204 -0
- package/src/kit/components/ApplicationMenus.tsx +372 -0
- package/src/kit/components/AssetEditorShell.tsx +216 -0
- package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
- package/src/kit/components/BoardRulers.tsx +354 -0
- package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
- package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
- package/src/kit/components/ChromeSlot.tsx +20 -0
- package/src/kit/components/CodeView.tsx +470 -0
- package/src/kit/components/CompactInspectorShell.tsx +39 -0
- package/src/kit/components/ConsolePanel.tsx +273 -0
- package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
- package/src/kit/components/InspectionProjection.tsx +932 -0
- package/src/kit/components/Inspector.tsx +270 -0
- package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
- package/src/kit/components/InspectorFieldsSection.tsx +290 -0
- package/src/kit/components/InspectorStoriesSection.tsx +92 -0
- package/src/kit/components/InspectorToolSection.tsx +96 -0
- package/src/kit/components/InspectorTransformSection.tsx +245 -0
- package/src/kit/components/LightExplorerPanel.tsx +433 -0
- package/src/kit/components/MediaProperties.tsx +145 -0
- package/src/kit/components/ProjectHeader.tsx +328 -0
- package/src/kit/components/ReactCanvasControls.tsx +358 -0
- package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
- package/src/kit/components/RootTextEditor.tsx +79 -0
- package/src/kit/components/SaveStatus.tsx +70 -0
- package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
- package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
- package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
- package/src/kit/components/ToolHost.tsx +380 -0
- package/src/kit/components/Toolbar.tsx +811 -0
- package/src/kit/components/TransientHint.tsx +44 -0
- package/src/kit/components/VersionControlSection.tsx +470 -0
- package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
- package/src/kit/components/VolterLogo.tsx +18 -0
- package/src/kit/components/WorktreeSwitcher.tsx +712 -0
- package/src/kit/components/account-documents.tsx +1162 -0
- package/src/kit/components/asset-documents.tsx +794 -0
- package/src/kit/components/asset-editor-persistence.ts +216 -0
- package/src/kit/components/asset-selection-section.tsx +545 -0
- package/src/kit/components/asset-thumbnails.tsx +307 -0
- package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
- package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
- package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
- package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/kit/components/asset-viewers/shader-source.ts +144 -0
- package/src/kit/components/board-guides.ts +150 -0
- package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
- package/src/kit/components/canvas-temporary-pivot.ts +34 -0
- package/src/kit/components/core-utilities.tsx +94 -0
- package/src/kit/components/inspector-preview-section.tsx +223 -0
- package/src/kit/components/inspector-revert-label.ts +20 -0
- package/src/kit/components/inspector-selection.ts +42 -0
- package/src/kit/components/inspector-stories-gating.ts +171 -0
- package/src/kit/components/inspector-transform-subject.ts +11 -0
- package/src/kit/components/inspector-transform.ts +88 -0
- package/src/kit/components/kind-documents.tsx +544 -0
- package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
- package/src/kit/components/project-tool-documents.tsx +402 -0
- package/src/kit/components/scene-documents.tsx +221 -0
- package/src/kit/components/status-contributions.tsx +407 -0
- package/src/kit/components/tool-documents.tsx +302 -0
- package/src/kit/components/tool-schema-form.tsx +262 -0
- package/src/kit/components/use-after-paint.ts +41 -0
- package/src/kit/components/use-project-image-assets.ts +86 -0
- package/src/kit/components/workspace-history.ts +32 -0
- package/src/kit/components/world-documents.tsx +570 -0
- package/src/kit/components/world-overlay-gestures.ts +1939 -0
- package/src/kit/composite-screenshot.ts +2238 -0
- package/src/kit/content-entry-source-registry.ts +184 -0
- package/src/kit/contribution-surfaces.ts +48 -0
- package/src/kit/coverage/canvas-reveal.ts +192 -0
- package/src/kit/coverage/design-time-surfaces.ts +101 -0
- package/src/kit/coverage/ontology-invariants.ts +466 -0
- package/src/kit/coverage/session-vitals.ts +503 -0
- package/src/kit/crash-null-boundary.ts +36 -0
- package/src/kit/creation-site-edit.ts +1491 -0
- package/src/kit/creation-site-registry.ts +160 -0
- package/src/kit/delegate-harness-registry.ts +134 -0
- package/src/kit/document-areas.ts +70 -0
- package/src/kit/document-context-registry.ts +193 -0
- package/src/kit/document-open-registry.ts +200 -0
- package/src/kit/document-play-extension.ts +221 -0
- package/src/kit/document-preview-source.ts +20 -0
- package/src/kit/document-renderer-session.ts +138 -0
- package/src/kit/document-stage-sessions.ts +26 -0
- package/src/kit/document-viewports.ts +120 -0
- package/src/kit/editor-api.ts +46 -0
- package/src/kit/editor-chrome-capture.ts +136 -0
- package/src/kit/editor-commands.ts +176 -0
- package/src/kit/editor-console.ts +580 -0
- package/src/kit/editor-current-view.ts +56 -0
- package/src/kit/editor-document-probe.ts +1168 -0
- package/src/kit/editor-git-client.ts +115 -0
- package/src/kit/editor-hotkeys.ts +728 -0
- package/src/kit/editor-lease-view.ts +39 -0
- package/src/kit/editor-lease.ts +415 -0
- package/src/kit/editor-mode.ts +19 -0
- package/src/kit/editor-notifications.ts +140 -0
- package/src/kit/editor-presence.ts +563 -0
- package/src/kit/editor-presentation-activity.ts +58 -0
- package/src/kit/editor-presentation-notice.ts +42 -0
- package/src/kit/editor-runtime.tsx +147 -0
- package/src/kit/editor-server-response.ts +86 -0
- package/src/kit/editor-session-attribution.ts +85 -0
- package/src/kit/editor-session-mode.ts +54 -0
- package/src/kit/editor-state-facets.ts +74 -0
- package/src/kit/editor-view-presentation.ts +777 -0
- package/src/kit/environment-images.ts +58 -0
- package/src/kit/eyedropper-session.ts +60 -0
- package/src/kit/files/file-provider.ts +62 -0
- package/src/kit/files/project-files.ts +270 -0
- package/src/kit/finders/index.ts +137 -0
- package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/kit/frame/frame-parts.ts +30 -0
- package/src/kit/framed-document-capture.ts +34 -0
- package/src/kit/game-globals-prelude.ts +143 -0
- package/src/kit/game-surface-defaults.ts +33 -0
- package/src/kit/gameplay-dom-recording.ts +318 -0
- package/src/kit/gameplay-export-state.ts +14 -0
- package/src/kit/gameplay-replay.ts +417 -0
- package/src/kit/gameplay-session-time.ts +9 -0
- package/src/kit/gameplay-sessions.ts +204 -0
- package/src/kit/hierarchy-component-marks.ts +298 -0
- package/src/kit/hierarchy-internals.ts +197 -0
- package/src/kit/hierarchy-kind-icon.ts +217 -0
- package/src/kit/hierarchy-menu-registry.ts +67 -0
- package/src/kit/hierarchy-node-rows.ts +307 -0
- package/src/kit/hierarchy-panel-view.ts +280 -0
- package/src/kit/hierarchy-projection.ts +76 -0
- package/src/kit/hierarchy-row-media.ts +45 -0
- package/src/kit/hierarchy-row-model.ts +308 -0
- package/src/kit/hierarchy-rows.ts +11 -0
- package/src/kit/hierarchy-walk.ts +86 -0
- package/src/kit/history/editor-session.ts +25 -0
- package/src/kit/history/history-commands.ts +147 -0
- package/src/kit/history/history-delegate.ts +187 -0
- package/src/kit/history/history-limit-notices.ts +43 -0
- package/src/kit/history/history-service.ts +1189 -0
- package/src/kit/history/persistence-coordinator.ts +35 -0
- package/src/kit/history/project-file-history.ts +386 -0
- package/src/kit/history/project-root-history-backends.ts +139 -0
- package/src/kit/history/resource-registry.ts +209 -0
- package/src/kit/history/snapshot-store.ts +103 -0
- package/src/kit/history/source-history-backend.ts +546 -0
- package/src/kit/history-types.ts +124 -0
- package/src/kit/hmr-registration-group.ts +67 -0
- package/src/kit/hmr-stable-react-context.ts +23 -0
- package/src/kit/hotkeys.ts +190 -0
- package/src/kit/inference-diagnostics.ts +69 -0
- package/src/kit/initial-project.ts +80 -0
- package/src/kit/inspection/active-subject.ts +571 -0
- package/src/kit/inspection/active-surface.ts +142 -0
- package/src/kit/inspection/compose-subject.ts +1055 -0
- package/src/kit/inspection/compose.ts +7 -0
- package/src/kit/inspection/display.ts +171 -0
- package/src/kit/inspection/document-subject.ts +109 -0
- package/src/kit/inspection/game-subject.ts +85 -0
- package/src/kit/inspection/null-subject.ts +119 -0
- package/src/kit/inspection/serialize.ts +357 -0
- package/src/kit/inspection/use-active-inspection.ts +180 -0
- package/src/kit/inspection-model.ts +542 -0
- package/src/kit/inspection-node-media.ts +58 -0
- package/src/kit/inspector-presentation.ts +203 -0
- package/src/kit/inspector-property-grouping.ts +64 -0
- package/src/kit/inspector-section-registry.ts +221 -0
- package/src/kit/instance-source-actions.ts +163 -0
- package/src/kit/js-heap.ts +71 -0
- package/src/kit/key-actions.ts +91 -0
- package/src/kit/keymap-presets.ts +428 -0
- package/src/kit/layout-policy.ts +31 -0
- package/src/kit/light-explorer-model.ts +134 -0
- package/src/kit/live-canvas-frame.ts +55 -0
- package/src/kit/live-document.ts +296 -0
- package/src/kit/live-gesture-lock.ts +50 -0
- package/src/kit/live-seam-evidence.ts +11 -0
- package/src/kit/live-session-registry.ts +220 -0
- package/src/kit/live-transition.ts +391 -0
- package/src/kit/manifest-project.ts +107 -0
- package/src/kit/module-fetch-diagnosis.ts +192 -0
- package/src/kit/mount-failure-report.ts +154 -0
- package/src/kit/native-selection-style.ts +497 -0
- package/src/kit/object3d-document-write-policy.ts +137 -0
- package/src/kit/packaged-runtime.ts +108 -0
- package/src/kit/palettes/maya.palette.json +57 -0
- package/src/kit/palettes/substance.palette.json +57 -0
- package/src/kit/performance-profiler.ts +367 -0
- package/src/kit/performance-sources.ts +69 -0
- package/src/kit/photograph-notice.ts +141 -0
- package/src/kit/play-boot-phase.ts +166 -0
- package/src/kit/play-camera-flight.ts +35 -0
- package/src/kit/png-encode.worker.ts +26 -0
- package/src/kit/presentation-surface.ts +248 -0
- package/src/kit/product-command.ts +90 -0
- package/src/kit/project-adapter.ts +1140 -0
- package/src/kit/project-asset-refresh.ts +23 -0
- package/src/kit/project-asset-roots.ts +68 -0
- package/src/kit/project-local-state.ts +151 -0
- package/src/kit/project-manager.ts +243 -0
- package/src/kit/project-module-changes.ts +201 -0
- package/src/kit/project-module-split.ts +270 -0
- package/src/kit/project-play-layers.ts +25 -0
- package/src/kit/project-provenance.ts +115 -0
- package/src/kit/project-ready.ts +42 -0
- package/src/kit/project-shape.ts +68 -0
- package/src/kit/project-tools.ts +107 -0
- package/src/kit/projection-types.ts +44 -0
- package/src/kit/readiness.ts +113 -0
- package/src/kit/renderer-resource-counts.ts +27 -0
- package/src/kit/reported-play-state.ts +90 -0
- package/src/kit/resolve-contributed-command.ts +14 -0
- package/src/kit/resolve-relative-specifier.ts +33 -0
- package/src/kit/retained-document-states.ts +91 -0
- package/src/kit/scene-document-plan.ts +320 -0
- package/src/kit/scene-live-open.ts +210 -0
- package/src/kit/scoped-game-css.ts +152 -0
- package/src/kit/served-url.ts +5 -0
- package/src/kit/session-close.ts +17 -0
- package/src/kit/session-tombstone.ts +127 -0
- package/src/kit/settings/settings-provider.ts +82 -0
- package/src/kit/settings-store.ts +348 -0
- package/src/kit/shell-document-state.ts +27 -0
- package/src/kit/shell-store-door.ts +45 -0
- package/src/kit/shell-store.ts +722 -0
- package/src/kit/source-conflict.ts +122 -0
- package/src/kit/stage-context.ts +377 -0
- package/src/kit/stage-invalidation.ts +25 -0
- package/src/kit/stage-store-registry.ts +69 -0
- package/src/kit/startup-failure.ts +80 -0
- package/src/kit/state-report-deferral.ts +73 -0
- package/src/kit/storage/host-files-storage.ts +97 -0
- package/src/kit/storage/http-storage.ts +174 -0
- package/src/kit/storage/index.ts +75 -0
- package/src/kit/storage/mem-storage.ts +158 -0
- package/src/kit/storage/path-lock.ts +44 -0
- package/src/kit/storage/paths.ts +26 -0
- package/src/kit/storage-types.ts +127 -0
- package/src/kit/stories/StoryPreviewMount.tsx +306 -0
- package/src/kit/stories/compose-project-stories.ts +255 -0
- package/src/kit/stories/prefabs-finder.ts +54 -0
- package/src/kit/stories/prefabs-from-stories.ts +182 -0
- package/src/kit/stories/project-story-regions.ts +24 -0
- package/src/kit/stories/story-capture.ts +579 -0
- package/src/kit/stories/story-declared-medium.ts +126 -0
- package/src/kit/stories/story-discovery.ts +176 -0
- package/src/kit/stories/story-dom-runtime.ts +78 -0
- package/src/kit/stories/story-grouping.ts +111 -0
- package/src/kit/stories/story-mount-turn.ts +27 -0
- package/src/kit/stories/story-presentation.ts +215 -0
- package/src/kit/stories/story-preview-component.ts +7 -0
- package/src/kit/stories/story-registry.ts +530 -0
- package/src/kit/stories-scope.ts +35 -0
- package/src/kit/story-document-openers.ts +36 -0
- package/src/kit/story-thumbnails.ts +47 -0
- package/src/kit/surface-keyboard.ts +101 -0
- package/src/kit/surface-state.ts +135 -0
- package/src/kit/system-seam-evidence.ts +72 -0
- package/src/kit/tab-census.ts +202 -0
- package/src/kit/tab-lifecycle-client.ts +227 -0
- package/src/kit/theme-library.ts +897 -0
- package/src/kit/theme-preference.ts +429 -0
- package/src/kit/three-viewport-presentation.ts +23 -0
- package/src/kit/tool-contribution-play.ts +74 -0
- package/src/kit/tool-loader.ts +1918 -0
- package/src/kit/transform-mode-request.ts +66 -0
- package/src/kit/transient-hint.ts +78 -0
- package/src/kit/transport-strip.tsx +174 -0
- package/src/kit/ui-source/adapter-region-includes.ts +238 -0
- package/src/kit/ui-source/file-region-resolver.ts +302 -0
- package/src/kit/ui-source/inspect.ts +775 -0
- package/src/kit/ui-source/source-write-backend.ts +605 -0
- package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
- package/src/kit/user-local-state.ts +105 -0
- package/src/kit/viewport-activation-timings.ts +840 -0
- package/src/kit/viewport-editor-controls.ts +22 -0
- package/src/kit/viewport-presentation.ts +668 -0
- package/src/kit/viewport-surface-status.tsx +55 -0
- package/src/kit/wait-until.ts +37 -0
- package/src/kit/worker-call-metrics.ts +166 -0
- package/src/kit/workspace-areas.ts +191 -0
- package/src/kit/workspace-aux-commands.ts +11 -0
- package/src/kit/workspace-available-documents.ts +142 -0
- package/src/kit/workspace-core-utilities.ts +31 -0
- package/src/kit/workspace-document-ids.ts +59 -0
- package/src/kit/workspace-document-registry.ts +624 -0
- package/src/kit/workspace-document-restore.ts +146 -0
- package/src/kit/workspace-host-commands.ts +141 -0
- package/src/kit/workspace-persistence-gate.ts +40 -0
- package/src/kit/workspace-play-utilities.ts +44 -0
- package/src/kit/workspace-presets.ts +446 -0
- package/src/kit/workspace-regions.ts +276 -0
- package/src/kit/workspace-static-panels.ts +73 -0
- package/src/kit/workspace-status-registry.ts +121 -0
- package/src/kit/workspace-storage.ts +35 -0
- package/src/kit/workspace-style.ts +226 -0
- package/src/kit/workspace-utility-commands.ts +74 -0
- package/src/kit/workspace-utility-registry.ts +263 -0
- package/src/kit/world-adoption-event.ts +23 -0
- package/src/kit/world-adoption.ts +115 -0
- package/src/kit/world-canvas-viewport-state.ts +35 -0
- package/src/kit/world-document-routing.ts +104 -0
- package/src/kit/world-pan-state.ts +198 -0
- package/src/kit/write-pipe.ts +173 -0
- package/src/layout-arrangements.ts +5 -0
- package/src/layouts.tsx +108 -0
- package/src/looks.ts +16 -0
- package/src/project/output-roots.ts +73 -0
- package/src/project/tab-census.ts +155 -0
- package/src/project-tool-catalog.ts +104 -0
- package/src/selection.tsx +107 -0
- package/src/services.ts +18 -0
- package/src/session/build-report.ts +22 -0
- package/src/session/collaboration-types.ts +262 -0
- package/src/session/command-table.ts +327 -0
- package/src/session/discovery.ts +100 -0
- package/src/session/editor-brand.ts +48 -0
- package/src/session/editor-compatibility.ts +329 -0
- package/src/session/editor-control-lifecycle.ts +68 -0
- package/src/session/editor-control-protocol.ts +5 -0
- package/src/session/entrypoint-selection-readers.ts +66 -0
- package/src/session/entrypoint-selection-source.ts +120 -0
- package/src/session/game-css-scope.ts +30 -0
- package/src/session/hosted-attachment.ts +225 -0
- package/src/session/limited-view.ts +82 -0
- package/src/session/product-create.ts +24 -0
- package/src/session/product-locator.ts +478 -0
- package/src/session/project-module-url.ts +242 -0
- package/src/session/project-serving.ts +164 -0
- package/src/session/project-upgrade.ts +669 -0
- package/src/session/registry-format.ts +210 -0
- package/src/session/relative-path-guard.ts +56 -0
- package/src/session/scoped-game-css.ts +461 -0
- package/src/session/source-glob.ts +15 -0
- package/src/session/tool-contribution-convention.ts +123 -0
- package/src/session/workbench-locator.ts +712 -0
- package/src/session.ts +41 -0
- package/src/share.ts +160 -0
- package/src/source-analysis.ts +28 -0
- package/src/source-authoring.ts +439 -0
- package/src/tools/errors.ts +91 -0
- package/src/tools/provider-execution.ts +70 -0
- package/src/tools/registry.ts +341 -0
- package/src/tools/types.ts +159 -0
- package/src/transport.ts +100 -0
- package/src/types.ts +1693 -0
- package/src/views.ts +164 -0
- package/src/widgets/design-system.ts +93 -0
- package/src/widgets/editor-appearance.ts +151 -0
- package/src/widgets/editor-material.ts +83 -0
- package/src/widgets/icon-set-registry.ts +105 -0
- package/src/widgets/index.ts +71 -0
- package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
- package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
- package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
- package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
- package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
- package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
- package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
- package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
- package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
- package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
- package/src/widgets/inspector-widgets/color-utils.ts +201 -0
- package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
- package/src/widgets/inspector-widgets/index.ts +25 -0
- package/src/widgets/inspector-widgets/shared.tsx +140 -0
- package/src/widgets/interactive-edit-scope.ts +33 -0
- package/src/widgets/patterns/Dialog.tsx +140 -0
- package/src/widgets/patterns/Fields.tsx +44 -0
- package/src/widgets/patterns/List.tsx +25 -0
- package/src/widgets/patterns/StateSurface.tsx +40 -0
- package/src/widgets/patterns/Surfaces.tsx +122 -0
- package/src/widgets/patterns/Tabs.tsx +80 -0
- package/src/widgets/patterns/Toolbar.tsx +72 -0
- package/src/widgets/patterns/Tree.tsx +72 -0
- package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
- package/src/widgets/primitives/Button.tsx +62 -0
- package/src/widgets/primitives/ColorInput.tsx +78 -0
- package/src/widgets/primitives/DraftTextInput.tsx +63 -0
- package/src/widgets/primitives/EditorIcon.tsx +157 -0
- package/src/widgets/primitives/FormControls.tsx +88 -0
- package/src/widgets/primitives/HoverPreview.tsx +96 -0
- package/src/widgets/primitives/JsonInput.tsx +113 -0
- package/src/widgets/primitives/Layout.tsx +100 -0
- package/src/widgets/primitives/Menu.tsx +161 -0
- package/src/widgets/primitives/NumberInput.tsx +169 -0
- package/src/widgets/primitives/Panel.tsx +80 -0
- package/src/widgets/primitives/SectionHeader.tsx +77 -0
- package/src/widgets/primitives/Text.tsx +54 -0
- package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
- package/src/widgets/primitives/Tooltip.tsx +204 -0
- package/src/widgets/primitives/Vec3Input.tsx +70 -0
- package/src/widgets/primitives/banner-tones.ts +32 -0
- package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
- package/src/widgets/primitives/editor-icons.ts +254 -0
- package/src/widgets/primitives/panel-header-styles.ts +42 -0
- package/src/widgets/theme.ts +2841 -0
- package/src/widgets/z-index.ts +25 -0
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Story registry (C3, spec §9) — the story sibling of `tool-loader.ts`'s
|
|
3
|
+
* registry half: ties `story-discovery.ts` (find modules) and
|
|
4
|
+
* `compose-project-stories.ts` (portable-mount one loaded module) together
|
|
5
|
+
* into a live, `useSyncExternalStore`-shaped list consumed by React design-time
|
|
6
|
+
* world mounting and its document/story hierarchy.
|
|
7
|
+
*
|
|
8
|
+
* Same discipline as the tool registry: discovery is a live rescan (never a
|
|
9
|
+
* cached manifest, D3), re-run on project open/change and on the server's
|
|
10
|
+
* `story-files-changed` SSE broadcast (a new/removed `*.stories.tsx`).
|
|
11
|
+
* Per-module failures (a module that fails to import, or fails to compose)
|
|
12
|
+
* are collected alongside successes rather than dropped — the panel shows a
|
|
13
|
+
* broken module's error inline, naming the module (spec §9 "errors identify
|
|
14
|
+
* the source module"), instead of silently omitting it.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { sortStoriesV7 } from 'storybook/internal/preview-api';
|
|
18
|
+
import type { Addon_StorySortParameterV7, IndexEntry } from 'storybook/internal/types';
|
|
19
|
+
import { activeProjectKey } from '@volter/sdk/kit/active-project';
|
|
20
|
+
import { editorConsole } from '@volter/sdk/kit/editor-console';
|
|
21
|
+
import {
|
|
22
|
+
describeModuleFetch,
|
|
23
|
+
diagnoseModuleFetch,
|
|
24
|
+
failedImportEntry,
|
|
25
|
+
} from '@volter/sdk/kit/module-fetch-diagnosis';
|
|
26
|
+
import {
|
|
27
|
+
recordStoryDiscoveryTiming,
|
|
28
|
+
waitForFirstViewportFrame,
|
|
29
|
+
} from '@volter/sdk/kit/viewport-activation-timings';
|
|
30
|
+
import {
|
|
31
|
+
type ComposedProjectStory,
|
|
32
|
+
composeProjectStories,
|
|
33
|
+
ensureProjectAnnotations,
|
|
34
|
+
} from './compose-project-stories';
|
|
35
|
+
import { getProjectStoryRegions } from '@volter/sdk/kit/stories/project-story-regions';
|
|
36
|
+
import { declaredStoryMedium } from '@volter/sdk/kit/stories/story-declared-medium';
|
|
37
|
+
import { deriveStoryGroupPath, formatStoryGroupPath } from './story-grouping';
|
|
38
|
+
|
|
39
|
+
/** One composed portable CSF story of the open project, carrying the source
|
|
40
|
+
* module it came from. A story belongs to the PROJECT, not to a root: the
|
|
41
|
+
* design-time board is the project's component gallery, and which root a
|
|
42
|
+
* story previews is DERIVED from the component its CSF meta renders
|
|
43
|
+
* ({@link pickComponentPreviewStory}). No story args/decorators/loaders are
|
|
44
|
+
* copied or reinterpreted. */
|
|
45
|
+
export interface ProjectPreviewStory extends ComposedProjectStory {
|
|
46
|
+
readonly modulePath: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
import { discoverProjectStories, loadProjectPreviewAnnotations } from './story-discovery';
|
|
50
|
+
|
|
51
|
+
/** One discovered module's outcome after load + compose. */
|
|
52
|
+
export type ProjectStoryModule =
|
|
53
|
+
| { modulePath: string; ok: true; stories: ComposedProjectStory[] }
|
|
54
|
+
| { modulePath: string; ok: false; error: string };
|
|
55
|
+
|
|
56
|
+
interface StoryDiscoveryProjectLike {
|
|
57
|
+
rootPath: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let _modules: ProjectStoryModule[] = [];
|
|
61
|
+
let _ready = false;
|
|
62
|
+
let _refreshGeneration = 0;
|
|
63
|
+
let _registryProjectKey: string | null = null;
|
|
64
|
+
const _requestedModules = new Map<string, Promise<void>>();
|
|
65
|
+
const _listeners = new Set<() => void>();
|
|
66
|
+
|
|
67
|
+
function adoptRegistryProject(): void {
|
|
68
|
+
const key = activeProjectKey();
|
|
69
|
+
if (_registryProjectKey === key) return;
|
|
70
|
+
_registryProjectKey = key;
|
|
71
|
+
_refreshGeneration++;
|
|
72
|
+
_requestedModules.clear();
|
|
73
|
+
publish([], false);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** Current story modules (stable reference between refreshes). */
|
|
77
|
+
export function getProjectStoryModules(): ProjectStoryModule[] {
|
|
78
|
+
return _modules;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** True only after the current project's discovery pass has published. An
|
|
82
|
+
* empty ready registry is a real "no stories" answer; an empty unready one is
|
|
83
|
+
* boot in flight and must never be graded as a missing component surface. */
|
|
84
|
+
export function projectStoriesReady(): boolean {
|
|
85
|
+
return _ready;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Subscribe to story-registry changes. Returns an unsubscribe function. */
|
|
89
|
+
export function subscribeProjectStoryModules(fn: () => void): () => void {
|
|
90
|
+
_listeners.add(fn);
|
|
91
|
+
return () => _listeners.delete(fn);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Resolve once the registry is READY — which is not the same as awaiting your
|
|
96
|
+
* own {@link refreshProjectStories}.
|
|
97
|
+
*
|
|
98
|
+
* A refresh that a LATER refresh supersedes returns EARLY, by design (a
|
|
99
|
+
* second concurrent pass aborts the first), and it returns with `_modules`
|
|
100
|
+
* still emptied by `_ready = false`. A caller that only awaited its own call
|
|
101
|
+
* therefore reads an empty registry and cannot tell it from "this project has
|
|
102
|
+
* no stories" — measured 2026-09-18 on a `full` scaffold, where the boot
|
|
103
|
+
* document restore raced the discovery lifecycle's own pass and dropped the
|
|
104
|
+
* open story document as a failed verification.
|
|
105
|
+
*
|
|
106
|
+
* Deliberately unbounded: every path that clears `_ready` is a refresh that
|
|
107
|
+
* publishes ready again when it finishes, succeeded or failed, and the
|
|
108
|
+
* workspace restore that calls this is itself time-boxed by the host
|
|
109
|
+
* (`workspace-state-persistence.ts`'s `RESTORE_TIMEOUT_MS` bounds when
|
|
110
|
+
* write-through installs, never the restore). A number here would be an
|
|
111
|
+
* invented tolerance over a condition that already resolves itself.
|
|
112
|
+
*/
|
|
113
|
+
export function whenProjectStoriesReady(): Promise<void> {
|
|
114
|
+
if (_ready) return Promise.resolve();
|
|
115
|
+
return new Promise((resolve) => {
|
|
116
|
+
const stop = subscribeProjectStoryModules(() => {
|
|
117
|
+
if (!_ready) return;
|
|
118
|
+
stop();
|
|
119
|
+
resolve();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function volterParameters(story: ComposedProjectStory): Record<string, unknown> | null {
|
|
125
|
+
const value = story.parameters['volter'];
|
|
126
|
+
return value && typeof value === 'object' ? (value as Record<string, unknown>) : null;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** Every composed story the project declares, in discovery/export order —
|
|
130
|
+
* the whole membership of the React design-time board and of the hierarchy's
|
|
131
|
+
* story documents. Deliberately unfiltered: the board is the project's
|
|
132
|
+
* component gallery, so a story earns its place by existing, and only the
|
|
133
|
+
* root's own default preview is derived from a component
|
|
134
|
+
* ({@link getComponentPreviewStory}). */
|
|
135
|
+
export function getProjectPreviewStories(): ProjectPreviewStory[] {
|
|
136
|
+
const out: ProjectPreviewStory[] = [];
|
|
137
|
+
for (const module_ of _modules) {
|
|
138
|
+
if (!module_.ok) continue;
|
|
139
|
+
for (const story of module_.stories) {
|
|
140
|
+
out.push({ ...story, modulePath: module_.modulePath });
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const storySort = out
|
|
144
|
+
.map((story) => {
|
|
145
|
+
const options = story.parameters['options'];
|
|
146
|
+
return options && typeof options === 'object'
|
|
147
|
+
? (options as Record<string, unknown>)['storySort']
|
|
148
|
+
: undefined;
|
|
149
|
+
})
|
|
150
|
+
.find((value) => value !== undefined) as Addon_StorySortParameterV7 | undefined;
|
|
151
|
+
if (!storySort) return out;
|
|
152
|
+
|
|
153
|
+
const byId = new Map(out.map((story) => [story.id, story]));
|
|
154
|
+
const entries: IndexEntry[] = out.map((story) => ({
|
|
155
|
+
type: 'story',
|
|
156
|
+
subtype: 'story',
|
|
157
|
+
id: story.id,
|
|
158
|
+
name: story.label,
|
|
159
|
+
title:
|
|
160
|
+
story.title ?? formatStoryGroupPath(deriveStoryGroupPath({ modulePath: story.modulePath })),
|
|
161
|
+
importPath: story.modulePath,
|
|
162
|
+
tags: [...(story.tags ?? [])],
|
|
163
|
+
}));
|
|
164
|
+
return sortStoriesV7(entries, storySort, [...new Set(out.map((story) => story.modulePath))])
|
|
165
|
+
.map((entry) => byId.get(entry.id))
|
|
166
|
+
.filter((story): story is ProjectPreviewStory => story !== undefined);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Whether a CSF module declares this story as its component's default:
|
|
170
|
+
* `parameters.volter.default === true` on the story itself, or a
|
|
171
|
+
* `volter.defaultStory` naming it (a meta-level parameter, which Storybook
|
|
172
|
+
* composes down onto every story in the module). */
|
|
173
|
+
export function isDeclaredDefaultStory(story: ComposedProjectStory): boolean {
|
|
174
|
+
const volter = volterParameters(story);
|
|
175
|
+
if (!volter) return false;
|
|
176
|
+
if (volter['default'] === true) return true;
|
|
177
|
+
return typeof volter['defaultStory'] === 'string' && volter['defaultStory'] === story.name;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** The directory portion of a project-relative source path, normalized. */
|
|
181
|
+
function sourceDir(path: string): string {
|
|
182
|
+
const normalized = path.replaceAll('\\', '/').replace(/^\.\//, '');
|
|
183
|
+
const slash = normalized.lastIndexOf('/');
|
|
184
|
+
return slash >= 0 ? normalized.slice(0, slash) : '';
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Choose the best composed story for one component, joined on
|
|
189
|
+
* `meta.component`'s name (the registry's own `componentName`) — pure over a
|
|
190
|
+
* module list so it is unit-testable without the live registry. This is THE
|
|
191
|
+
* story↔component join: a `three` prefab's own declaration and
|
|
192
|
+
* THUMBNAIL (mounted off-screen by `story-three-preview.ts`; no live instance
|
|
193
|
+
* or referenced asset substitutes for it) and a React root's composed default
|
|
194
|
+
* preview (`design-time-layers.ts`, joined against the root entry's
|
|
195
|
+
* default-exported component) both go through it.
|
|
196
|
+
*
|
|
197
|
+
* `componentPath` (the component's own source file) disambiguates the known
|
|
198
|
+
* weak spot of a name-only join: two files can export a same-named component,
|
|
199
|
+
* so a story is PREFERRED when its module sits in the same source directory as
|
|
200
|
+
* the component. Within the chosen set, a story the module declares as the
|
|
201
|
+
* default ({@link isDeclaredDefaultStory}) wins; otherwise discovery order.
|
|
202
|
+
*/
|
|
203
|
+
export function pickComponentPreviewStory(
|
|
204
|
+
modules: readonly ProjectStoryModule[],
|
|
205
|
+
componentName: string,
|
|
206
|
+
componentPath?: string,
|
|
207
|
+
): ProjectPreviewStory | null {
|
|
208
|
+
const pool = componentPreviewStories(modules, componentName, componentPath);
|
|
209
|
+
return pool.find(isDeclaredDefaultStory) ?? pool[0] ?? null;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Every portable state declared for one component. The same source-directory
|
|
214
|
+
* preference as {@link pickComponentPreviewStory} disambiguates equal export
|
|
215
|
+
* names without hiding sibling stories from the component's Inspector.
|
|
216
|
+
*/
|
|
217
|
+
export function componentPreviewStories(
|
|
218
|
+
modules: readonly ProjectStoryModule[],
|
|
219
|
+
componentName: string,
|
|
220
|
+
componentPath?: string,
|
|
221
|
+
): ProjectPreviewStory[] {
|
|
222
|
+
const matches: ProjectPreviewStory[] = [];
|
|
223
|
+
for (const module_ of modules) {
|
|
224
|
+
if (!module_.ok) continue;
|
|
225
|
+
for (const story of module_.stories) {
|
|
226
|
+
if (story.componentName === componentName) {
|
|
227
|
+
matches.push({ ...story, modulePath: module_.modulePath });
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (matches.length === 0) return [];
|
|
232
|
+
const sameDir = componentPath
|
|
233
|
+
? matches.filter((story) => sourceDir(story.modulePath) === sourceDir(componentPath))
|
|
234
|
+
: [];
|
|
235
|
+
return sameDir.length > 0 ? sameDir : matches;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/** {@link pickComponentPreviewStory} over the LIVE registry — what the content
|
|
239
|
+
* gallery calls to find a prefab's thumbnail story, and what
|
|
240
|
+
* `design-time-layers.ts` calls to find a React root's composed default
|
|
241
|
+
* preview from the root entry's own component. */
|
|
242
|
+
export function getComponentPreviewStory(
|
|
243
|
+
componentName: string,
|
|
244
|
+
componentPath?: string,
|
|
245
|
+
): ProjectPreviewStory | null {
|
|
246
|
+
return pickComponentPreviewStory(_modules, componentName, componentPath);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/** Live-registry form of {@link componentPreviewStories}. */
|
|
250
|
+
export function getComponentPreviewStories(
|
|
251
|
+
componentName: string,
|
|
252
|
+
componentPath?: string,
|
|
253
|
+
): ProjectPreviewStory[] {
|
|
254
|
+
return componentPreviewStories(_modules, componentName, componentPath);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function publish(next: ProjectStoryModule[], ready: boolean): void {
|
|
258
|
+
_modules = next;
|
|
259
|
+
_ready = ready;
|
|
260
|
+
for (const fn of _listeners) fn();
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
interface TimedStoryModule {
|
|
264
|
+
readonly result: ProjectStoryModule;
|
|
265
|
+
readonly loadMs: number;
|
|
266
|
+
readonly composeMs: number;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async function loadStoryModule({
|
|
270
|
+
modulePath,
|
|
271
|
+
load,
|
|
272
|
+
}: {
|
|
273
|
+
readonly modulePath: string;
|
|
274
|
+
readonly load: () => Promise<unknown>;
|
|
275
|
+
}): Promise<TimedStoryModule> {
|
|
276
|
+
const loadStartedAtMs = Date.now();
|
|
277
|
+
let mod: unknown;
|
|
278
|
+
try {
|
|
279
|
+
mod = await load();
|
|
280
|
+
} catch (err) {
|
|
281
|
+
const entry = failedImportEntry(String(err instanceof Error ? err.message : err));
|
|
282
|
+
if (entry) {
|
|
283
|
+
void diagnoseModuleFetch(entry).then((diagnosis) =>
|
|
284
|
+
editorConsole.error(`[stories] ${modulePath}: ${describeModuleFetch(diagnosis)}`, 'authoring'),
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
result: {
|
|
289
|
+
modulePath,
|
|
290
|
+
ok: false,
|
|
291
|
+
error: `[stories] failed to load ${modulePath} — ${String(err instanceof Error ? err.message : err)}`,
|
|
292
|
+
},
|
|
293
|
+
loadMs: Date.now() - loadStartedAtMs,
|
|
294
|
+
composeMs: 0,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
const loadMs = Date.now() - loadStartedAtMs;
|
|
298
|
+
const composeStartedAtMs = Date.now();
|
|
299
|
+
const result = await composeProjectStories(modulePath, mod);
|
|
300
|
+
return {
|
|
301
|
+
result: result.ok
|
|
302
|
+
? { modulePath, ok: true, stories: result.stories }
|
|
303
|
+
: { modulePath, ok: false, error: result.error },
|
|
304
|
+
loadMs,
|
|
305
|
+
composeMs: Date.now() - composeStartedAtMs,
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/** Open one explicit story without evaluating every other project example.
|
|
310
|
+
* Full discovery still owns catalog completeness; this only publishes the
|
|
311
|
+
* requested module into that same registry, without marking it complete. */
|
|
312
|
+
export function ensureProjectStoryModule(
|
|
313
|
+
project: StoryDiscoveryProjectLike | null,
|
|
314
|
+
modulePath: string,
|
|
315
|
+
): Promise<void> {
|
|
316
|
+
adoptRegistryProject();
|
|
317
|
+
const projectKey = activeProjectKey();
|
|
318
|
+
const key = `${projectKey}\n${modulePath}`;
|
|
319
|
+
const existing = _requestedModules.get(key);
|
|
320
|
+
if (existing) return existing;
|
|
321
|
+
const pending = loadRequestedStoryModule(project, projectKey, modulePath).finally(() => {
|
|
322
|
+
if (_requestedModules.get(key) === pending) _requestedModules.delete(key);
|
|
323
|
+
});
|
|
324
|
+
_requestedModules.set(key, pending);
|
|
325
|
+
return pending;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
async function loadRequestedStoryModule(
|
|
329
|
+
project: StoryDiscoveryProjectLike | null,
|
|
330
|
+
projectKey: string,
|
|
331
|
+
modulePath: string,
|
|
332
|
+
): Promise<void> {
|
|
333
|
+
while (activeProjectKey() === projectKey) {
|
|
334
|
+
// A published composition is immediately usable. The document subscribes
|
|
335
|
+
// to subsequent source refreshes; opening never waits on unrelated modules.
|
|
336
|
+
const prior = _modules.find((module_) => module_.modulePath === modulePath);
|
|
337
|
+
if (prior?.ok) return;
|
|
338
|
+
const generation = _refreshGeneration;
|
|
339
|
+
const current = () => activeProjectKey() === projectKey && generation === _refreshGeneration;
|
|
340
|
+
const annotations = await loadProjectPreviewAnnotations(project);
|
|
341
|
+
if (!current()) continue;
|
|
342
|
+
await ensureProjectAnnotations(annotations);
|
|
343
|
+
if (!current()) continue;
|
|
344
|
+
const discovered = await discoverProjectStories(project);
|
|
345
|
+
if (!current()) continue;
|
|
346
|
+
const requested = discovered.find((module_) => module_.modulePath === modulePath);
|
|
347
|
+
if (!requested) throw new Error(`Story module not found: ${modulePath}`);
|
|
348
|
+
const { result } = await loadStoryModule(requested);
|
|
349
|
+
if (!current()) continue;
|
|
350
|
+
// Full discovery can publish this module while its demanded load runs.
|
|
351
|
+
// That publication owns the row; a slower request must not replace it.
|
|
352
|
+
const published = _modules.find((module_) => module_.modulePath === modulePath);
|
|
353
|
+
if (published && published !== prior) {
|
|
354
|
+
if (!published.ok) throw new Error(published.error);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
publish([..._modules.filter((module_) => module_.modulePath !== modulePath), result], _ready);
|
|
358
|
+
if (!result.ok) throw new Error(result.error);
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
throw new Error(`Project changed while opening story: ${modulePath}`);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** Let the first visible editor work finish before evaluating story modules
|
|
365
|
+
* whose medium cannot be known from the project's declared regions. Those
|
|
366
|
+
* modules commonly hold dense DOM kits; loading them eagerly made a 3D board
|
|
367
|
+
* wait on code it cannot display. Storybook uses the same broad architecture:
|
|
368
|
+
* index first, evaluate a story module only when its surface needs it. */
|
|
369
|
+
async function waitForStoryImportIdle(): Promise<void> {
|
|
370
|
+
// `requestIdleCallback` only means the browser main thread is momentarily
|
|
371
|
+
// idle; it fired while the first Scene was still driving ~1,000 Vite module
|
|
372
|
+
// requests and pulled the data-grid story graph into that same
|
|
373
|
+
// queue. Wait for an authored frame first. The timeout preserves recovery
|
|
374
|
+
// for a genuinely broken viewport without making background stories part
|
|
375
|
+
// of the ordinary startup path.
|
|
376
|
+
await Promise.race([
|
|
377
|
+
waitForFirstViewportFrame(),
|
|
378
|
+
new Promise<void>((resolve) => setTimeout(resolve, 5_000)),
|
|
379
|
+
]);
|
|
380
|
+
await new Promise<void>((resolve) => {
|
|
381
|
+
const idle = globalThis.requestIdleCallback;
|
|
382
|
+
if (typeof idle === 'function') {
|
|
383
|
+
idle(() => resolve(), { timeout: 2_000 });
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
setTimeout(resolve, 0);
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Re-run the whole discovery + load + compose pass. Never throws: a broken
|
|
392
|
+
* module (import failure, or a `composeProjectStories` failure) becomes an
|
|
393
|
+
* `{ ok: false, error }` entry naming the module, and every other module
|
|
394
|
+
* still loads — the same "one bad file never takes the rest down" physics
|
|
395
|
+
* `refreshProjectTools` uses.
|
|
396
|
+
*
|
|
397
|
+
* Applies the project's `.storybook/preview.ts(x)` annotations (if the
|
|
398
|
+
* project has one — `loadProjectPreviewAnnotations`) via
|
|
399
|
+
* `ensureProjectAnnotations` before composing anything, exactly once per
|
|
400
|
+
* session. `explicitPreviewAnnotations` is a test/caller override — pass it
|
|
401
|
+
* to skip the `/@fs/` discovery and thread a fixture's annotations directly.
|
|
402
|
+
*/
|
|
403
|
+
export async function refreshProjectStories(
|
|
404
|
+
project: StoryDiscoveryProjectLike | null,
|
|
405
|
+
explicitPreviewAnnotations?: unknown,
|
|
406
|
+
options: {
|
|
407
|
+
readonly deferUndeclared?: boolean;
|
|
408
|
+
/**
|
|
409
|
+
* The source paths a CONTENT write changed, when that is what triggered
|
|
410
|
+
* this refresh. With it, a story module whose bundled closure holds none
|
|
411
|
+
* of them keeps its published result instead of being re-evaluated, and
|
|
412
|
+
* the modules that do reload go ONE AT A TIME with a frame between them:
|
|
413
|
+
* re-bundling all ten of a project's story modules at once, on the main
|
|
414
|
+
* thread, beside the world's own remount, is what held the editor at 7–12
|
|
415
|
+
* FPS for seconds after every prefab drop (three human passes; profiled
|
|
416
|
+
* 2026-09-03). Boot and explicit refreshes pass nothing and load in
|
|
417
|
+
* parallel, as before.
|
|
418
|
+
*/
|
|
419
|
+
readonly changedPaths?: ReadonlySet<string>;
|
|
420
|
+
} = {},
|
|
421
|
+
): Promise<void> {
|
|
422
|
+
adoptRegistryProject();
|
|
423
|
+
const generation = ++_refreshGeneration;
|
|
424
|
+
const projectKey = activeProjectKey();
|
|
425
|
+
const current = () => generation === _refreshGeneration && projectKey === activeProjectKey();
|
|
426
|
+
const loadAll = async (
|
|
427
|
+
list: readonly { readonly modulePath: string; readonly load: () => Promise<unknown> }[],
|
|
428
|
+
): Promise<TimedStoryModule[]> => {
|
|
429
|
+
if (!options.changedPaths) return Promise.all(list.map(loadStoryModule));
|
|
430
|
+
// A write-driven refresh loads one module per frame instead: the reload
|
|
431
|
+
// itself is a module-cache hit, but COMPOSING every story on one turn
|
|
432
|
+
// beside the world's own remount is what held the editor at 7-12 FPS
|
|
433
|
+
// after a prefab drop.
|
|
434
|
+
const out: TimedStoryModule[] = [];
|
|
435
|
+
for (const item of list) {
|
|
436
|
+
out.push(await loadStoryModule(item));
|
|
437
|
+
// Give the viewport a frame between modules.
|
|
438
|
+
await new Promise((resolve) => setTimeout(resolve, 16));
|
|
439
|
+
if (!current()) break;
|
|
440
|
+
}
|
|
441
|
+
return out;
|
|
442
|
+
};
|
|
443
|
+
_ready = false;
|
|
444
|
+
for (const fn of _listeners) fn();
|
|
445
|
+
const startedAtMs = Date.now();
|
|
446
|
+
const previewStartedAtMs = Date.now();
|
|
447
|
+
const previewAnnotations =
|
|
448
|
+
explicitPreviewAnnotations ?? (await loadProjectPreviewAnnotations(project));
|
|
449
|
+
if (!current()) return;
|
|
450
|
+
const previewAnnotationsMs = Date.now() - previewStartedAtMs;
|
|
451
|
+
const annotationsStartedAtMs = Date.now();
|
|
452
|
+
await ensureProjectAnnotations(previewAnnotations);
|
|
453
|
+
if (!current()) return;
|
|
454
|
+
const runtimeAnnotationsMs = Date.now() - annotationsStartedAtMs;
|
|
455
|
+
|
|
456
|
+
const scanStartedAtMs = Date.now();
|
|
457
|
+
const discovered = await discoverProjectStories(project);
|
|
458
|
+
if (!current()) return;
|
|
459
|
+
const fileScanMs = Date.now() - scanStartedAtMs;
|
|
460
|
+
// Module evaluation is independent; only STORY MOUNTING is serialized
|
|
461
|
+
// (`story-mount-turn.ts`) because loaders may mutate shared preview state.
|
|
462
|
+
// Loading every CSF module one after another made editor boot scale with the
|
|
463
|
+
// SUM of Vite transforms and network round trips (measured at 16s for the
|
|
464
|
+
// template and 23s for third-person). Preserve discovery order by mapping
|
|
465
|
+
// `Promise.all` over the ordered input rather than pushing as jobs finish.
|
|
466
|
+
const regions = getProjectStoryRegions();
|
|
467
|
+
const deferred = options.deferUndeclared
|
|
468
|
+
? discovered.filter(
|
|
469
|
+
({ modulePath }) => declaredStoryMedium({ modulePath, regions }).via === 'undeclared',
|
|
470
|
+
)
|
|
471
|
+
: [];
|
|
472
|
+
const deferredPaths = new Set(deferred.map(({ modulePath }) => modulePath));
|
|
473
|
+
const immediate = discovered.filter(({ modulePath }) => !deferredPaths.has(modulePath));
|
|
474
|
+
const modulesStartedAtMs = Date.now();
|
|
475
|
+
const immediateLoaded = await loadAll(immediate);
|
|
476
|
+
const moduleLoadAndComposeMs = Date.now() - modulesStartedAtMs;
|
|
477
|
+
const immediateResults = immediateLoaded.map(({ result }) => result);
|
|
478
|
+
if (!current()) return;
|
|
479
|
+
|
|
480
|
+
// Publish the declared surfaces as soon as they are usable. The registry is
|
|
481
|
+
// deliberately not "ready" until the background tail has also landed, so
|
|
482
|
+
// acceptance/coverage cannot mistake a partial index for the final answer.
|
|
483
|
+
const immediateByPath = new Map(
|
|
484
|
+
[
|
|
485
|
+
// A demanded story may already be open while the catalog evaluates its
|
|
486
|
+
// immediate set. Keep that row (and other last-good deferred rows) until
|
|
487
|
+
// their replacements arrive; a partial catalog must not remove them.
|
|
488
|
+
..._modules.filter(({ modulePath }) => deferredPaths.has(modulePath)),
|
|
489
|
+
...immediateResults,
|
|
490
|
+
].map((result) => [result.modulePath, result]),
|
|
491
|
+
);
|
|
492
|
+
publish(
|
|
493
|
+
discovered
|
|
494
|
+
.map(({ modulePath }) => immediateByPath.get(modulePath))
|
|
495
|
+
.filter((result): result is ProjectStoryModule => result !== undefined),
|
|
496
|
+
deferred.length === 0,
|
|
497
|
+
);
|
|
498
|
+
recordStoryDiscoveryTiming({
|
|
499
|
+
ms: Date.now() - startedAtMs,
|
|
500
|
+
completedAtMs: Date.now(),
|
|
501
|
+
moduleCount: immediateResults.length,
|
|
502
|
+
storyCount: immediateResults.reduce(
|
|
503
|
+
(count, module_) => count + (module_.ok ? module_.stories.length : 0),
|
|
504
|
+
0,
|
|
505
|
+
),
|
|
506
|
+
previewAnnotationsMs,
|
|
507
|
+
runtimeAnnotationsMs,
|
|
508
|
+
fileScanMs,
|
|
509
|
+
moduleLoadAndComposeMs,
|
|
510
|
+
modules: immediateLoaded.map(({ result, loadMs, composeMs }) => ({
|
|
511
|
+
modulePath: result.modulePath,
|
|
512
|
+
loadMs,
|
|
513
|
+
composeMs,
|
|
514
|
+
ok: result.ok,
|
|
515
|
+
})),
|
|
516
|
+
});
|
|
517
|
+
if (deferred.length === 0) return;
|
|
518
|
+
|
|
519
|
+
await waitForStoryImportIdle();
|
|
520
|
+
if (!current()) return;
|
|
521
|
+
const deferredResults = (await loadAll(deferred)).map(({ result }) => result);
|
|
522
|
+
if (!current()) return;
|
|
523
|
+
const resultByPath = new Map(
|
|
524
|
+
[...immediateResults, ...deferredResults].map((result) => [result.modulePath, result]),
|
|
525
|
+
);
|
|
526
|
+
const next = discovered
|
|
527
|
+
.map(({ modulePath }) => resultByPath.get(modulePath))
|
|
528
|
+
.filter((result): result is ProjectStoryModule => result !== undefined);
|
|
529
|
+
publish(next, true);
|
|
530
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `StoriesProvider` node-id protocol's one reserved value.
|
|
3
|
+
*
|
|
4
|
+
* `storiesFor`/`active`/`apply` all take a node id. The EMPTY id is not a node:
|
|
5
|
+
* it is the WORLD-LEVEL question — "list YOUR stories", asked with no node in
|
|
6
|
+
* hand. A world-level provider (contract scenes, a react root's portable CSF)
|
|
7
|
+
* ignores the node id and answers its whole list; a node-scoped provider (the
|
|
8
|
+
* binding `component-states-registry.ts` hands an adapter) has no node here
|
|
9
|
+
* and answers nothing. That
|
|
10
|
+
* difference is the ONE derivation of "which scope is this provider?" in the
|
|
11
|
+
* editor — `components/inspector-stories-gating.ts`'s
|
|
12
|
+
* `resolveWorldStoriesInput`/`resolveNodeScopedStories` are its two readings
|
|
13
|
+
* and must not grow a third.
|
|
14
|
+
*
|
|
15
|
+
* Because it is a PROBE, the answer to it must be a property of the provider,
|
|
16
|
+
* never of session state: an implementer whose empty-id answer depends on what
|
|
17
|
+
* the user last clicked makes its own scope flip under the shell mid-session.
|
|
18
|
+
* Implementers that special-case the empty id import this constant rather than
|
|
19
|
+
* spelling `''`, so the protocol has one definition and the probe and the
|
|
20
|
+
* answer can never drift apart.
|
|
21
|
+
*
|
|
22
|
+
* It lives here (a leaf module importing nothing) rather than beside the gating
|
|
23
|
+
* probe because the providers in this directory answer it, and
|
|
24
|
+
* `components/inspector-stories-gating.ts` value-imports two of them
|
|
25
|
+
* (`ReactRootAuthoringAdapter`, `CompositeAuthoringAdapter`) — so a back-import
|
|
26
|
+
* from an adapter would be a runtime cycle.
|
|
27
|
+
*
|
|
28
|
+
* Nor does it belong in the engine beside `StoriesProvider`. `@volter/project/adapter`,
|
|
29
|
+
* the barrel every consumer imports that type through, is deliberately
|
|
30
|
+
* TYPE-ONLY (P-6) and may not re-export a value; and reaching past it to
|
|
31
|
+
* `@volter/project/adapter/authoring` (which does carry values) would publish an
|
|
32
|
+
* EDITOR-only protocol constant as a public engine entry point, since the
|
|
33
|
+
* engine's export map is the wildcard `"./*"`.
|
|
34
|
+
*/
|
|
35
|
+
export const WORLD_SCOPE_NODE_ID = '';
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ADDRESSES a portable CSF story opens under, and the request shape that
|
|
3
|
+
* carries one — the story kind's half of `document-open-registry.ts`.
|
|
4
|
+
*
|
|
5
|
+
* It lives here, in the host's story estate (the registry, discovery, the
|
|
6
|
+
* declared medium, the arg descriptors, the three mount), and NOT in the
|
|
7
|
+
* documents, because the documents are a contribution: `@volter/editor-game` registers
|
|
8
|
+
* openers for these ids, the host asks for them, and neither side imports the
|
|
9
|
+
* other. A build that does not carry that package simply has no opener, which
|
|
10
|
+
* every call site already handles — `null` is the same answer an undeclared
|
|
11
|
+
* medium has always given.
|
|
12
|
+
*
|
|
13
|
+
* Three ids, because a story opens on three genuinely different surfaces and
|
|
14
|
+
* the CHOICE between them is made in three different places: by the story's
|
|
15
|
+
* declared medium (`story-opener.ts`'s `story` opener), by the owning component's
|
|
16
|
+
* surface (the Content grid), and by the caller asking for Docs explicitly.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** A story rendered on the Object3D document surface — the turntable. */
|
|
20
|
+
export const THREE_STORY_DOCUMENT_OPENER = 'story:three';
|
|
21
|
+
/** A story rendered in its own isolated DOM/canvas preview root. */
|
|
22
|
+
export const ISOLATED_STORY_DOCUMENT_OPENER = 'story:isolated';
|
|
23
|
+
/** The Storybook Docs companion for one story. */
|
|
24
|
+
export const STORY_DOCS_DOCUMENT_OPENER = 'story:docs';
|
|
25
|
+
|
|
26
|
+
export interface StoryDocumentOpenRequest {
|
|
27
|
+
/** Project-relative CSF module path. */
|
|
28
|
+
readonly modulePath: string;
|
|
29
|
+
/** The story's authored export name. */
|
|
30
|
+
readonly storyName: string;
|
|
31
|
+
/** Tab title; the export name when absent. */
|
|
32
|
+
readonly title?: string;
|
|
33
|
+
/** Whether opening also FOCUSES the tab. A click-through opens and focuses;
|
|
34
|
+
* the Edit tab row offers a standing tab instead and passes `false`. */
|
|
35
|
+
readonly activate?: boolean;
|
|
36
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A STORY'S THUMBNAIL, CAPTURED BY THE MEDIUM ITS COMPONENT RENDERS IN — a
|
|
3
|
+
* three.js prefab story is mounted in an offscreen R3F stage, a canvas story in
|
|
4
|
+
* an offscreen Pixi application. The kit's component content asks here by the
|
|
5
|
+
* story's surface and keeps the component's icon where no medium registered.
|
|
6
|
+
*/
|
|
7
|
+
import type { AssetPreviewCameraChoice, AssetPreviewPose } from '../types';
|
|
8
|
+
|
|
9
|
+
export interface StoryThumbnailOptions {
|
|
10
|
+
readonly width: number;
|
|
11
|
+
readonly height: number;
|
|
12
|
+
readonly props?: Record<string, unknown>;
|
|
13
|
+
readonly layout?: 'fullscreen' | 'padded' | 'centered';
|
|
14
|
+
/** A free capture camera, where the medium frames its subject itself. */
|
|
15
|
+
readonly camera?: AssetPreviewCameraChoice;
|
|
16
|
+
/** A clip pose for the subject. */
|
|
17
|
+
readonly pose?: AssetPreviewPose;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The medium's refusal of a story that is not its own (an R3F leg handed a DOM
|
|
22
|
+
* story): the caller tries the next leg, and says nothing, because the refusal
|
|
23
|
+
* is a classification rather than a failure.
|
|
24
|
+
*/
|
|
25
|
+
export class StoryMediumMismatch extends Error {
|
|
26
|
+
override readonly name = 'StoryMediumMismatch';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function isStoryMediumMismatch(error: unknown): boolean {
|
|
30
|
+
return error instanceof Error && error.name === 'StoryMediumMismatch';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type StoryThumbnailCapture = (component: unknown, options: StoryThumbnailOptions) => Promise<string>;
|
|
34
|
+
|
|
35
|
+
const captures = new Map<string, StoryThumbnailCapture>();
|
|
36
|
+
|
|
37
|
+
/** Register the capture for one surface (`three`, `canvas`). Returns the removal. */
|
|
38
|
+
export function registerStoryThumbnailCapture(surface: string, capture: StoryThumbnailCapture): () => void {
|
|
39
|
+
captures.set(surface, capture);
|
|
40
|
+
return () => {
|
|
41
|
+
if (captures.get(surface) === capture) captures.delete(surface);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function storyThumbnailCapture(surface: string): StoryThumbnailCapture | null {
|
|
46
|
+
return captures.get(surface) ?? null;
|
|
47
|
+
}
|