@vgai/editor 0.2.0 → 0.4.0-canary.20260715.0

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.
Files changed (430) hide show
  1. package/README.md +24 -0
  2. package/dist/assets/axe-C7YBtOuM.js +30 -0
  3. package/dist/assets/browserAll-DDtGGE48.js +1 -0
  4. package/dist/assets/create-runtime-DbTlBlKG.js +1 -0
  5. package/dist/assets/{game-BI111o5f.js → game-BE0r7DMI.js} +3 -3
  6. package/dist/assets/game-BdTHR2_X.js +1 -0
  7. package/dist/assets/{game-pt_1lQLv.js → game-C3iQGSqo.js} +1 -1
  8. package/dist/assets/game-CcHfYxjP.js +1 -0
  9. package/dist/assets/game-Cqzj_lpD.js +1 -0
  10. package/dist/assets/game-DSZdeCHu.js +1 -0
  11. package/dist/assets/game-Dch9sAPc.js +1 -0
  12. package/dist/assets/{game-xsOho_wg.js → game-SAFn90pA.js} +3 -3
  13. package/dist/assets/game-loop-DMIgSMV-.js +1 -0
  14. package/dist/assets/{game-source-CvidN7AB.js → game-source-Dk83w26t.js} +1 -1
  15. package/dist/assets/{index-Bp5cecD6.js → index-4idIsHHJ.js} +2 -2
  16. package/dist/assets/{index-DL7RcQ0n.js → index-C-LhOTBN.js} +1 -1
  17. package/dist/assets/{index-Cs8xwv3e.js → index-CDkxceqE.js} +1 -1
  18. package/dist/assets/index-CQEfi217.js +15412 -0
  19. package/dist/assets/index-Dvi-V0NE.css +1 -0
  20. package/dist/assets/ingest-siblings-s0P5I1Ub.js +1 -0
  21. package/dist/assets/mount-manifest-DXMOlF79.js +1 -0
  22. package/dist/assets/react-18-C9eHn8x1.js +1 -0
  23. package/dist/assets/webworkerAll-Fn0e-ouF.js +1 -0
  24. package/dist/assets/world-documents-GM0a9Kv7.js +1 -0
  25. package/dist/index.html +15 -13
  26. package/dist/ingest/racing-game/vgai.game.json +5 -4
  27. package/dist/ingest/simcity/vgai.game.json +5 -4
  28. package/dist/ingest/tanks/vgai.game.json +5 -4
  29. package/dist/project-scripts.bundle.js +3917 -0
  30. package/dist/scenes/untitled.vscn.json +2 -0
  31. package/dist-server/packaged.mjs +7697 -3435
  32. package/package.json +31 -4
  33. package/scripts/probe-reporter.ts +349 -0
  34. package/scripts/run-probe.ts +2260 -0
  35. package/server/asset-catalog-audit.ts +268 -0
  36. package/server/asset-catalog-v2.ts +146 -0
  37. package/server/asset-library-routes.ts +276 -58
  38. package/server/canonical-path.ts +1 -1
  39. package/server/dev.ts +148 -44
  40. package/server/editor-server.ts +888 -61
  41. package/server/editor-sse.ts +115 -4
  42. package/server/harness-chat-service.ts +796 -0
  43. package/server/local-asset-catalog.ts +157 -22
  44. package/server/packaged.ts +51 -21
  45. package/server/process-shutdown.ts +136 -0
  46. package/server/prod.ts +9 -6
  47. package/server/project-hmr-files.ts +41 -0
  48. package/server/project-operations.ts +343 -0
  49. package/server/project-optimize-deps-entries.ts +4 -4
  50. package/server/project-output-writer.ts +156 -0
  51. package/server/project-validation.ts +140 -0
  52. package/server/project-view.ts +8 -50
  53. package/server/server-utils.ts +75 -10
  54. package/server/session-registry.ts +12 -0
  55. package/src/EditorContext.tsx +107 -3
  56. package/src/action-registry.ts +115 -17
  57. package/src/adapter-resolver.ts +213 -478
  58. package/src/asset-events.ts +64 -1
  59. package/src/asset-preview.ts +906 -0
  60. package/src/asset-selection.ts +121 -0
  61. package/src/asset-workflow/asset-capabilities.ts +259 -0
  62. package/src/asset-workflow/asset-editor-errors.ts +46 -0
  63. package/src/asset-workflow/asset-import-pipeline.ts +176 -0
  64. package/src/asset-workflow/asset-library-query.ts +107 -0
  65. package/src/asset-workflow/asset-types.ts +192 -0
  66. package/src/asset-workflow/asset-workflow-quality.ts +65 -0
  67. package/src/asset-workflow/import-contract.ts +113 -0
  68. package/src/asset-workflow/model-conversion.ts +126 -0
  69. package/src/asset-workflow/model-inspection.ts +185 -0
  70. package/src/asset-workflow/project-asset-commands.ts +23 -0
  71. package/src/asset-workflow/project-asset-health.ts +153 -0
  72. package/src/asset-workflow/project-asset-operations.ts +119 -0
  73. package/src/asset-workflow/thumbnail-system.ts +172 -0
  74. package/src/authoring/active-systems.ts +15 -0
  75. package/src/authoring/boundary-authoring-adapter.ts +16 -5
  76. package/src/authoring/composite-authoring-adapter.ts +305 -124
  77. package/src/authoring/design-time-layers.ts +300 -117
  78. package/src/authoring/edit-mode-authoring.ts +278 -293
  79. package/src/authoring/embed-only-adapter.ts +4 -2
  80. package/src/authoring/first-party-hierarchy-menu.ts +7 -2
  81. package/src/authoring/first-party-inspector/AddSectionMenu.tsx +5 -12
  82. package/src/authoring/first-party-inspector/EnvironmentSection.tsx +53 -126
  83. package/src/authoring/first-party-inspector/HeaderSection.tsx +54 -65
  84. package/src/authoring/first-party-inspector/is-first-party-selection.ts +30 -11
  85. package/src/authoring/first-party-inspector/register.tsx +13 -2
  86. package/src/authoring/ingest-authoring-adapter.ts +142 -45
  87. package/src/authoring/mount-failure-report.ts +5 -5
  88. package/src/authoring/provenance.ts +41 -0
  89. package/src/authoring/react-dom-authoring-adapter.ts +92 -92
  90. package/src/authoring/react-inspector-section.tsx +489 -51
  91. package/src/authoring/react-world-authoring-adapter.ts +541 -306
  92. package/src/authoring/story-overlay.ts +1 -1
  93. package/src/authoring/story-types.ts +11 -0
  94. package/src/authoring/vgai-scene-authoring-adapter.ts +54 -25
  95. package/src/authoring/viewport-tool-context.ts +78 -0
  96. package/src/authoring/world-canvas-viewport-state.ts +35 -0
  97. package/src/authoring/world-hidden-viewport.ts +186 -0
  98. package/src/authoring/world-pan-state.ts +33 -17
  99. package/src/authoring/world-session-state.ts +1 -1
  100. package/src/authoring/world2d-authoring-adapter.ts +109 -52
  101. package/src/availability-tick.ts +56 -0
  102. package/src/browser-play-entry.ts +5 -5
  103. package/src/browser-project-scripts.ts +1 -0
  104. package/src/build-identity.ts +15 -0
  105. package/src/command-listener.ts +893 -19
  106. package/src/components/AlignToolbar.tsx +74 -63
  107. package/src/components/AppRoot.tsx +193 -26
  108. package/src/components/ApplicationMenus.tsx +272 -0
  109. package/src/components/AssetBrowser.tsx +1450 -293
  110. package/src/components/AssetEditorShell.tsx +141 -0
  111. package/src/components/AssetImportDetails.tsx +218 -0
  112. package/src/components/AssetLibraryPanel.tsx +14 -0
  113. package/src/components/CameraInfo.tsx +11 -20
  114. package/src/components/CenterDocuments.tsx +585 -0
  115. package/src/components/CommandPalette.tsx +75 -30
  116. package/src/components/ConsolePanel.css +55 -0
  117. package/src/components/ConsolePanel.tsx +57 -112
  118. package/src/components/DebugConsolePanel.tsx +461 -0
  119. package/src/components/DebuggerPanel.tsx +165 -0
  120. package/src/components/DefaultEditorLayout.tsx +167 -231
  121. package/src/components/GameHierarchy.tsx +873 -290
  122. package/src/components/GamePerformanceOverlay.tsx +46 -0
  123. package/src/components/HarnessChatPanel.tsx +2352 -0
  124. package/src/components/HistoryPanel.tsx +226 -0
  125. package/src/components/Inspector.tsx +153 -99
  126. package/src/components/InspectorToolSection.tsx +6 -4
  127. package/src/components/MountFailureBanner.tsx +31 -48
  128. package/src/components/NetworkSection.tsx +25 -14
  129. package/src/components/OnlineAssetBrowser.tsx +794 -343
  130. package/src/components/OverlayReportBanner.tsx +38 -64
  131. package/src/components/PerformancePanel.tsx +206 -0
  132. package/src/components/PlayBar.tsx +93 -263
  133. package/src/components/PrefabSaveDialog.tsx +55 -127
  134. package/src/components/ProjectHeader.css +60 -0
  135. package/src/components/ProjectHeader.tsx +170 -105
  136. package/src/components/ProjectScreen.tsx +246 -184
  137. package/src/components/ReactCanvasControls.tsx +185 -0
  138. package/src/components/ResolutionPicker.tsx +85 -0
  139. package/src/components/RootActivateDialog.tsx +39 -68
  140. package/src/components/SaveDialog.tsx +55 -127
  141. package/src/components/SaveStatus.tsx +11 -29
  142. package/src/components/StartupLoadingScreen.tsx +96 -0
  143. package/src/components/StateWatchPanel.tsx +302 -0
  144. package/src/components/StatsOverlay.tsx +12 -5
  145. package/src/components/StatusBar.tsx +64 -0
  146. package/src/components/ThemeManagerDialog.css +89 -0
  147. package/src/components/ThemeManagerDialog.tsx +371 -0
  148. package/src/components/ToolHost.tsx +26 -15
  149. package/src/components/Toolbar.tsx +117 -214
  150. package/src/components/VgaiVoxelLogo.tsx +89 -0
  151. package/src/components/ViewportOverlay.tsx +97 -172
  152. package/src/components/ViewportPanel.tsx +130 -31
  153. package/src/components/WorkspaceDock.tsx +891 -0
  154. package/src/components/WorldSelectionOverlay.tsx +51 -63
  155. package/src/components/WorldTextEditor.tsx +9 -5
  156. package/src/components/asset-documents.tsx +390 -0
  157. package/src/components/asset-editor-persistence.ts +44 -0
  158. package/src/components/asset-selection-section.tsx +338 -0
  159. package/src/components/asset-viewers/AudioViewer.tsx +73 -21
  160. package/src/components/asset-viewers/GenericJsonViewer.tsx +26 -11
  161. package/src/components/asset-viewers/ImageViewer.tsx +43 -11
  162. package/src/components/asset-viewers/InputMapViewer.tsx +512 -134
  163. package/src/components/asset-viewers/MaterialAssetEditor.tsx +540 -0
  164. package/src/components/asset-viewers/ModelViewer.tsx +805 -121
  165. package/src/components/asset-viewers/OnlineAssetDetail.tsx +177 -60
  166. package/src/components/asset-viewers/SourceAssetViewer.tsx +121 -0
  167. package/src/components/asset-workflow.css +506 -0
  168. package/src/components/build-documents.tsx +696 -0
  169. package/src/components/core-utilities.tsx +75 -0
  170. package/src/components/data-documents.tsx +364 -0
  171. package/src/components/{DataPanel.tsx → data-editor.tsx} +138 -288
  172. package/src/components/debugger-panel-state.ts +57 -0
  173. package/src/components/inspector-widgets/AlignmentGrid.tsx +8 -14
  174. package/src/components/inspector-widgets/BorderEditor.tsx +41 -33
  175. package/src/components/inspector-widgets/ColorPicker.tsx +39 -39
  176. package/src/components/inspector-widgets/FontPicker.tsx +13 -21
  177. package/src/components/inspector-widgets/GradientEditor.tsx +11 -19
  178. package/src/components/inspector-widgets/ScrubbableInput.tsx +6 -3
  179. package/src/components/inspector-widgets/ShadowEditor.tsx +20 -33
  180. package/src/components/inspector-widgets/shared.tsx +90 -49
  181. package/src/components/inspectors/AnimationSection.tsx +39 -40
  182. package/src/components/inspectors/AudioSection.tsx +28 -39
  183. package/src/components/inspectors/BoneAttachmentSection.tsx +19 -24
  184. package/src/components/inspectors/CameraSection.tsx +14 -23
  185. package/src/components/inspectors/ComponentsSection.tsx +39 -43
  186. package/src/components/inspectors/JointsSection.tsx +34 -43
  187. package/src/components/inspectors/LightSection.tsx +90 -35
  188. package/src/components/inspectors/MaterialSection.tsx +137 -174
  189. package/src/components/inspectors/MeshSection.tsx +9 -17
  190. package/src/components/inspectors/NavigationSection.tsx +8 -15
  191. package/src/components/inspectors/ParticleSection.tsx +91 -76
  192. package/src/components/inspectors/PhysicsSection.tsx +42 -46
  193. package/src/components/inspectors/PostProcessingSection.tsx +28 -36
  194. package/src/components/inspectors/RenderingSection.tsx +12 -20
  195. package/src/components/inspectors/ShadowSection.tsx +7 -8
  196. package/src/components/inspectors/SplineSection.tsx +31 -42
  197. package/src/components/inspectors/TransformSection.tsx +14 -22
  198. package/src/components/patterns/Dialog.tsx +95 -0
  199. package/src/components/patterns/Fields.tsx +44 -0
  200. package/src/components/patterns/List.tsx +25 -0
  201. package/src/components/patterns/StateSurface.tsx +40 -0
  202. package/src/components/patterns/Surfaces.tsx +115 -0
  203. package/src/components/patterns/Tabs.tsx +80 -0
  204. package/src/components/patterns/Toolbar.tsx +51 -0
  205. package/src/components/patterns/Tree.tsx +72 -0
  206. package/src/components/primitives/Button.tsx +46 -0
  207. package/src/components/primitives/ColorInput.tsx +11 -47
  208. package/src/components/primitives/EditorIcon.tsx +99 -0
  209. package/src/components/primitives/FormControls.tsx +71 -0
  210. package/src/components/primitives/JsonInput.tsx +15 -2
  211. package/src/components/primitives/Layout.tsx +100 -0
  212. package/src/components/primitives/Menu.tsx +105 -0
  213. package/src/components/primitives/NumberInput.tsx +8 -35
  214. package/src/components/primitives/Panel.tsx +49 -44
  215. package/src/components/primitives/SectionHeader.tsx +10 -28
  216. package/src/components/primitives/Text.tsx +46 -0
  217. package/src/components/primitives/Tooltip.tsx +20 -12
  218. package/src/components/primitives/Vec3Input.tsx +3 -0
  219. package/src/components/primitives/banner-tones.ts +33 -0
  220. package/src/components/primitives/editor-icons.ts +102 -0
  221. package/src/components/primitives/panel-header-styles.ts +30 -0
  222. package/src/components/project-operation-documents.tsx +226 -0
  223. package/src/components/status-contributions.tsx +175 -0
  224. package/src/components/story-documents-register.ts +15 -0
  225. package/src/components/story-documents.tsx +1185 -0
  226. package/src/components/tool-documents.tsx +110 -0
  227. package/src/components/workspace-dock.css +293 -0
  228. package/src/components/workspace-history.ts +33 -0
  229. package/src/components/world-documents.tsx +145 -0
  230. package/src/components/xstate-documents.tsx +209 -0
  231. package/src/composite-screenshot.ts +248 -0
  232. package/src/design-system/index.ts +70 -0
  233. package/src/design-system-stories/Foundation.stories.tsx +183 -0
  234. package/src/design-system-stories/Patterns.stories.tsx +251 -0
  235. package/src/design-system-stories/Workspace.stories.tsx +538 -0
  236. package/src/doctor/report.ts +57 -13
  237. package/src/editor-api.ts +295 -31
  238. package/src/editor-compatibility.ts +200 -0
  239. package/src/editor-console.ts +35 -17
  240. package/src/editor-hotkeys.ts +85 -33
  241. package/src/editor-store.ts +538 -233
  242. package/src/editor-viewport.ts +160 -34
  243. package/src/entity-factory.ts +14 -3
  244. package/src/gizmo-registry.ts +21 -5
  245. package/src/harness-chat-editor-context.ts +37 -0
  246. package/src/harness-chat-indicator.ts +68 -0
  247. package/src/harness-chat-layout.ts +53 -0
  248. package/src/harness-chat-lifecycle.ts +170 -0
  249. package/src/harness-chat-reconnect.ts +85 -0
  250. package/src/harness-chat-types.ts +409 -0
  251. package/src/hierarchy-drop.ts +50 -0
  252. package/src/hierarchy-expansion-state.ts +100 -0
  253. package/src/hierarchy-menu-registry.ts +1 -1
  254. package/src/hierarchy-projection.ts +76 -0
  255. package/src/history/editor-session.ts +21 -0
  256. package/src/history/history-commands.ts +147 -0
  257. package/src/history/history-service.ts +904 -0
  258. package/src/history/json-history-resource.ts +165 -0
  259. package/src/history/persistence-coordinator.ts +35 -0
  260. package/src/history/project-file-history.ts +266 -0
  261. package/src/history/project-root-history-backends.ts +53 -0
  262. package/src/history/resource-registry.ts +209 -0
  263. package/src/history/snapshot-store.ts +108 -0
  264. package/src/history/source-history-backend.ts +374 -0
  265. package/src/history/types.ts +100 -0
  266. package/src/hmr-registration-group.ts +67 -0
  267. package/src/hmr-stable-react-context.ts +23 -0
  268. package/src/hosted-example.ts +12 -2
  269. package/src/hotkeys.ts +89 -18
  270. package/src/ingest/discovery-react.ts +9 -10
  271. package/src/ingest/discovery.ts +4 -4
  272. package/src/ingest/discovery2d.ts +5 -5
  273. package/src/ingest/games/bloom-composer/vgai.game.json +3 -3
  274. package/src/ingest/games/embed-bundle/vgai.game.json +3 -3
  275. package/src/ingest/games/games-fps/vgai.game.json +3 -3
  276. package/src/ingest/games/iframe-reachable/vgai.game.json +3 -3
  277. package/src/ingest/games/interactive-cubes/vgai.game.json +3 -3
  278. package/src/ingest/games/mismatched-three/vgai.game.json +3 -3
  279. package/src/ingest/games/own-three-bundled/vgai.game.json +3 -3
  280. package/src/ingest/games/pointerlock-maze/vgai.game.json +7 -4
  281. package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +3 -3
  282. package/src/ingest/games-2d/bunnymark/vgai.game.json +3 -3
  283. package/src/ingest/games-2d/flappy/vgai.game.json +3 -3
  284. package/src/ingest/games-2d/flappy-pixi/vgai.game.json +3 -3
  285. package/src/ingest/games-2d/puzzling-potions/vgai.game.json +3 -3
  286. package/src/ingest/games-2d/tilemap-camera/vgai.game.json +3 -3
  287. package/src/ingest/games-react/react-rpg/vgai.game.json +3 -3
  288. package/src/ingest/types.ts +1 -1
  289. package/src/ingest-mode.ts +47 -52
  290. package/src/ingest-siblings.ts +23 -33
  291. package/src/initial-scene.ts +1 -2
  292. package/src/main.tsx +16 -8
  293. package/src/manifest-project.ts +10 -12
  294. package/src/model-thumbnail.ts +261 -26
  295. package/src/module-mode.ts +44 -50
  296. package/src/play-log-events.ts +26 -0
  297. package/src/play-mode.ts +495 -401
  298. package/src/play-scene-adoption.ts +23 -0
  299. package/src/playground/main.ts +68 -24
  300. package/src/playwright-shim.ts +473 -0
  301. package/src/project-manager.ts +90 -10
  302. package/src/project-operations.ts +112 -0
  303. package/src/project-story-discovery.ts +25 -0
  304. package/src/project-tool-discovery.ts +43 -0
  305. package/src/scene-serializer.ts +0 -6
  306. package/src/scene-sync.ts +7 -2
  307. package/src/script-loader.ts +3 -3
  308. package/src/skeleton-helper.ts +57 -0
  309. package/src/storage/seed.ts +68 -8
  310. package/src/stories/StoryPreviewMount.tsx +265 -0
  311. package/src/stories/action-stories.fixture.tsx +44 -0
  312. package/src/stories/button-stories.fixture.tsx +50 -0
  313. package/src/stories/compose-project-stories.ts +182 -0
  314. package/src/stories/loader-stories.fixture.tsx +53 -0
  315. package/src/stories/story-discovery.ts +130 -0
  316. package/src/stories/story-registry.ts +146 -0
  317. package/src/theme-css.ts +1049 -0
  318. package/src/theme-library.ts +238 -0
  319. package/src/theme-preference.ts +130 -0
  320. package/src/theme.ts +527 -0
  321. package/src/tool-loader.ts +80 -24
  322. package/src/ui-source/inspect.ts +27 -4
  323. package/src/ui-source/source-write-backend.ts +83 -22
  324. package/src/widgets/index.ts +9 -18
  325. package/src/workspace-aux-commands.ts +11 -0
  326. package/src/workspace-dock-controller.ts +64 -0
  327. package/src/workspace-document-ids.ts +5 -0
  328. package/src/workspace-document-registry.ts +367 -0
  329. package/src/workspace-state-persistence.ts +455 -0
  330. package/src/workspace-status-registry.ts +110 -0
  331. package/src/workspace-utility-commands.ts +49 -0
  332. package/src/workspace-utility-registry.ts +161 -0
  333. package/src/world-document-routing.ts +16 -0
  334. package/src/xstate-inspect/XStateMachineInspector.tsx +544 -0
  335. package/src/xstate-inspect/character-animation-machine.fixture.ts +74 -0
  336. package/src/xstate-inspect/use-live-actor-state.ts +39 -0
  337. package/src/xstate-inspect/xstate-graph.ts +265 -0
  338. package/src/xstate-inspect/xstate-layout.ts +76 -0
  339. package/src/z-index.ts +26 -0
  340. package/template/.claude/skills/editor/SKILL.md +129 -90
  341. package/template/AGENTS.md +1110 -0
  342. package/template/CLAUDE.md +1 -512
  343. package/template/IDIOMS.md +50 -0
  344. package/template/check-idioms.ts +706 -0
  345. package/template/manifest-entry-modules-plugin.ts +53 -0
  346. package/template/package.json +13 -4
  347. package/template/public/scenes/default.scn2d.json +6 -0
  348. package/template/public/scenes/default.vscn.json +7 -1
  349. package/template/public/scenes/untitled.vscn.json +10 -0
  350. package/template/scripts/playtest.ts +40 -0
  351. package/template/server/loopback.ts +75 -0
  352. package/template/server/rooms/arena-room.ts +69 -1
  353. package/template/server/rooms/game-room.ts +68 -1
  354. package/template/src/data/README.md +9 -4
  355. package/template/src/data/data-ref.ts +35 -0
  356. package/template/src/data/tuning.schema.ts +1 -1
  357. package/template/src/main.ts +41 -62
  358. package/template/src/manifest-entry-modules.d.ts +3 -0
  359. package/template/src/operations/README.md +88 -0
  360. package/template/src/runtime/pixi-adapter.ts +24 -0
  361. package/template/src/scripts/components/data-spinner.ts +43 -2
  362. package/template/src/scripts/components/spin-lap-math.ts +27 -0
  363. package/template/src/tools/README.md +5 -3
  364. package/template/src/tools/example.tool.tsx +13 -7
  365. package/template/src/ui/Button.stories.tsx +66 -0
  366. package/template/src/ui/RebindPanel.tsx +2 -6
  367. package/template/src/ui/game.tsx +17 -0
  368. package/template/tests/acceptance/example.spec.ts +64 -0
  369. package/template/tests/logic/example.test.ts +31 -0
  370. package/template/tests/logic/room.test.ts +100 -0
  371. package/template/tests/tsconfig.json +30 -0
  372. package/template/validate-manifest.ts +5 -5
  373. package/template/validate-scenes.ts +50 -18
  374. package/template/vgai.game.json +20 -13
  375. package/template/vite.config.ts +77 -16
  376. package/vite-plugin-ui-oid.ts +261 -17
  377. package/dist/assets/CCDIKSolver-Dz-ysxZF.js +0 -1
  378. package/dist/assets/SelectionBox-BXsv_6aH.js +0 -1
  379. package/dist/assets/browser-project-scripts-DOru4L1x.js +0 -2
  380. package/dist/assets/browserAll-CEkWYlFk.js +0 -1
  381. package/dist/assets/create-runtime-DYIWr3va.js +0 -1
  382. package/dist/assets/data-asset-Bb9sIM7i.js +0 -5
  383. package/dist/assets/game-8SDZPPgH.js +0 -1
  384. package/dist/assets/game-CevorxyV.js +0 -1
  385. package/dist/assets/game-Di7XlywD.js +0 -1
  386. package/dist/assets/game-DjnCaw8R.js +0 -1
  387. package/dist/assets/game-Q9A0aXSV.js +0 -1
  388. package/dist/assets/index-CPVV6pjw.js +0 -1
  389. package/dist/assets/index-CpOnYyeD.js +0 -213
  390. package/dist/assets/index-Dr8H_6Rl.js +0 -1
  391. package/dist/assets/index-_bCaipUk.js +0 -13650
  392. package/dist/assets/ingest-siblings-Dz8eEqrV.js +0 -1
  393. package/dist/assets/mount-manifest-Bhk0ohsl.js +0 -1
  394. package/dist/assets/scene-query-BivAHhJu.js +0 -1
  395. package/dist/assets/webworkerAll-BLrH0F6F.js +0 -1
  396. package/dist/assets/xstate-animation-binding-1NGLmw6y.js +0 -1
  397. package/dist/assets/xstate.esm-BgUD33nl.js +0 -3
  398. package/src/authoring/scene-ui-layer.ts +0 -485
  399. package/src/authoring/ui-authoring-adapter.ts +0 -325
  400. package/src/authoring/ui-hierarchy-menu.ts +0 -40
  401. package/src/authoring/ui-inspector-sections.tsx +0 -156
  402. package/src/authoring/undo-timeline.ts +0 -145
  403. package/src/components/BottomPanel.tsx +0 -326
  404. package/src/components/BuildPanel.tsx +0 -455
  405. package/src/components/FolderTree.tsx +0 -179
  406. package/src/components/RightPanel.tsx +0 -166
  407. package/src/components/WorldContextMenu.tsx +0 -257
  408. package/src/components/asset-viewers/AssetViewer.tsx +0 -38
  409. package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +0 -129
  410. package/src/scene-ui-mode/active-scene-ui.ts +0 -58
  411. package/src/scene-ui-mode/scene-ui-palette-panel.tsx +0 -152
  412. package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +0 -29
  413. package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +0 -74
  414. package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +0 -49
  415. package/src/scene-ui-mode/ui-prefab-io.ts +0 -76
  416. package/src/ui-editor/inspector.tsx +0 -563
  417. package/src/ui-editor/node-ops.ts +0 -266
  418. package/src/ui-editor/overlay.tsx +0 -380
  419. package/src/ui-editor/palette.tsx +0 -114
  420. package/src/ui-editor/react-store.ts +0 -78
  421. package/src/ui-editor/timeline-panel.tsx +0 -443
  422. package/src/ui-editor/ui-edit-store.ts +0 -552
  423. package/src/ui-editor/ui-prefab.ts +0 -95
  424. package/template/project.json +0 -9
  425. package/template/src/scripts/main.ts +0 -94
  426. package/template/src/ui/DefaultHud.tsx +0 -40
  427. package/template/src/ui/game-state.tsx +0 -37
  428. package/template/src/ui/mount-default-hud.tsx +0 -19
  429. package/template/src/ui/mount-ui.ts +0 -15
  430. package/vite-plugin-react-world-provider.ts +0 -81
@@ -0,0 +1,338 @@
1
+ /**
2
+ * §5.1 asset-selection Inspector section (W2, docs/EDITOR-WORKSPACE-SHELL-
3
+ * TODO.md — inventory row R6's "single-click selects → Inspector
4
+ * preview/metadata" half). Registered through the EXISTING
5
+ * `inspector-section-registry.ts` seam (§7 "inspector-section registry —
6
+ * already exists; retain/generalize"): the section matches whenever an asset
7
+ * is single-click-selected in the browser (`asset-selection.ts`), for any
8
+ * adapter and any (or no) entity selection — the Inspector stays contextual
9
+ * and is never REPLACED by a viewer (§10 acceptance #3); the full viewer
10
+ * lives in a center document (`asset-documents.tsx`, double-click/Enter).
11
+ *
12
+ * Per the §5.1 table, compact metadata only: image dimensions/format/size,
13
+ * model thumbnail + size (the summary reuses the existing
14
+ * `model-thumbnail.ts` renderer), audio duration/format, input-map binding
15
+ * summary (reusing `InputMapViewer`'s exported validation), and plain
16
+ * name/path/size for the rest. This module registers itself at import time
17
+ * (same side-effect idiom as `authoring/first-party-inspector/register.tsx`,
18
+ * imported from `main.tsx` FIRST so the asset section renders above other
19
+ * matched sections).
20
+ */
21
+
22
+ import { resolveUrl } from '@engine/loader';
23
+ import { MaterialFileSchema } from '@engine/scene/schema/material';
24
+ import { useEffect, useState } from 'react';
25
+ import { getSelectedAsset, type SelectedAsset } from '../asset-selection';
26
+ import { assetDocumentKind } from '../asset-workflow/asset-capabilities';
27
+ import { PROJECT_ASSET_COMMANDS } from '../asset-workflow/project-asset-commands';
28
+ import { Button, bg, border, radius, text } from '../design-system';
29
+ import { registerInspectorSections } from '../inspector-section-registry';
30
+ import { getModelThumbnailRenderer } from '../model-thumbnail';
31
+ import { validateInputMapForViewer } from './asset-viewers/InputMapViewer';
32
+
33
+ const labelStyle: React.CSSProperties = { fontSize: 11, color: text[3], marginBottom: 2 };
34
+ const valueStyle: React.CSSProperties = { fontSize: 11, color: text[1], wordBreak: 'break-all' };
35
+
36
+ function formatSize(bytes: number): string {
37
+ if (bytes < 1024) return `${bytes} B`;
38
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
39
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
40
+ }
41
+
42
+ function MetaRow({ label, value }: { label: string; value: string }) {
43
+ return (
44
+ <div>
45
+ <div style={labelStyle}>{label}</div>
46
+ <div style={valueStyle}>{value}</div>
47
+ </div>
48
+ );
49
+ }
50
+
51
+ /** Compact image preview + natural dimensions (§5.1 "dimensions, format, size"). */
52
+ function ImageSummary({ asset }: { asset: SelectedAsset }) {
53
+ const [dims, setDims] = useState<{ w: number; h: number } | null>(null);
54
+ return (
55
+ <>
56
+ <div
57
+ style={{
58
+ background: bg.inset,
59
+ borderRadius: radius.sm,
60
+ padding: 6,
61
+ display: 'flex',
62
+ justifyContent: 'center',
63
+ }}
64
+ >
65
+ <img
66
+ src={asset.path}
67
+ alt={asset.name}
68
+ style={{ maxWidth: '100%', maxHeight: 96, objectFit: 'contain' }}
69
+ onLoad={(e) =>
70
+ setDims({ w: e.currentTarget.naturalWidth, h: e.currentTarget.naturalHeight })
71
+ }
72
+ />
73
+ </div>
74
+ {dims && <MetaRow label="Dimensions" value={`${dims.w} × ${dims.h}`} />}
75
+ </>
76
+ );
77
+ }
78
+
79
+ /** Compact model summary: the shared offscreen thumbnail (existing
80
+ * `model-thumbnail.ts` renderer — no second loader path). */
81
+ function ModelSummary({ asset }: { asset: SelectedAsset }) {
82
+ const [src, setSrc] = useState<string | null>(null);
83
+ const [failed, setFailed] = useState(false);
84
+ useEffect(() => {
85
+ let cancelled = false;
86
+ setSrc(null);
87
+ setFailed(false);
88
+ getModelThumbnailRenderer()
89
+ .render(asset.path)
90
+ .then((dataUrl) => {
91
+ if (!cancelled) setSrc(dataUrl);
92
+ })
93
+ .catch(() => {
94
+ if (!cancelled) setFailed(true);
95
+ });
96
+ return () => {
97
+ cancelled = true;
98
+ };
99
+ }, [asset.path]);
100
+ return (
101
+ <div
102
+ style={{
103
+ background: bg.inset,
104
+ borderRadius: radius.sm,
105
+ padding: 6,
106
+ display: 'flex',
107
+ justifyContent: 'center',
108
+ minHeight: 72,
109
+ alignItems: 'center',
110
+ }}
111
+ >
112
+ {src ? (
113
+ <img src={src} alt={asset.name} style={{ maxWidth: 96, maxHeight: 96 }} />
114
+ ) : (
115
+ <span style={{ fontSize: 11, color: text[3] }}>{failed ? 'No preview' : 'Loading…'}</span>
116
+ )}
117
+ </div>
118
+ );
119
+ }
120
+
121
+ /** Audio duration via metadata-only load (§5.1 "duration, format"). */
122
+ function AudioSummary({ asset }: { asset: SelectedAsset }) {
123
+ const [duration, setDuration] = useState<number | null>(null);
124
+ const label =
125
+ duration === null
126
+ ? null
127
+ : `${Math.floor(duration / 60)}:${Math.floor(duration % 60)
128
+ .toString()
129
+ .padStart(2, '0')}`;
130
+ return (
131
+ <>
132
+ {/* Metadata probe only — no playback UI here (the audio DOCUMENT owns playback). */}
133
+ <audio
134
+ muted
135
+ src={asset.path}
136
+ preload="metadata"
137
+ style={{ display: 'none' }}
138
+ onLoadedMetadata={(e) => setDuration(e.currentTarget.duration)}
139
+ />
140
+ {label && <MetaRow label="Duration" value={label} />}
141
+ </>
142
+ );
143
+ }
144
+
145
+ /** Input-map binding summary through the SAME schema validation the full
146
+ * viewer uses (`validateInputMapForViewer`) — counts, never a re-parse. */
147
+ function InputMapSummary({ asset }: { asset: SelectedAsset }) {
148
+ const [summary, setSummary] = useState<string | null>(null);
149
+ useEffect(() => {
150
+ let cancelled = false;
151
+ setSummary(null);
152
+ fetch(resolveUrl(asset.path))
153
+ .then((r) => r.json())
154
+ .then((json) => {
155
+ if (cancelled) return;
156
+ const result = validateInputMapForViewer(json);
157
+ if (!result.ok) {
158
+ setSummary('Invalid input map (runtime will reject it)');
159
+ return;
160
+ }
161
+ const actions = Object.entries(result.data.actions ?? {});
162
+ const bindings = actions.reduce((n, [, a]) => n + a.bindings.length, 0);
163
+ setSummary(`${actions.length} action(s), ${bindings} binding(s)`);
164
+ })
165
+ .catch(() => {
166
+ if (!cancelled) setSummary('Failed to load file');
167
+ });
168
+ return () => {
169
+ cancelled = true;
170
+ };
171
+ }, [asset.path]);
172
+ return summary ? <MetaRow label="Bindings" value={summary} /> : null;
173
+ }
174
+
175
+ /** Shared-material compact properties; the full schema editor stays in the center document. */
176
+ function MaterialSummary({ asset }: { asset: SelectedAsset }) {
177
+ const [summary, setSummary] = useState<
178
+ { type: string; color: string } | { error: string } | null
179
+ >(null);
180
+ useEffect(() => {
181
+ let cancelled = false;
182
+ setSummary(null);
183
+ fetch(resolveUrl(asset.path), { cache: 'no-store' })
184
+ .then((response) => response.json())
185
+ .then((json) => {
186
+ if (cancelled) return;
187
+ const result = MaterialFileSchema.safeParse(json);
188
+ setSummary(
189
+ result.success
190
+ ? { type: result.data.material.type, color: result.data.material.color ?? '#ffffff' }
191
+ : { error: 'Invalid material (runtime will reject it)' },
192
+ );
193
+ })
194
+ .catch(() => {
195
+ if (!cancelled) setSummary({ error: 'Failed to load material' });
196
+ });
197
+ return () => {
198
+ cancelled = true;
199
+ };
200
+ }, [asset.path]);
201
+ if (!summary) return null;
202
+ if ('error' in summary) return <MetaRow label="Material" value={summary.error} />;
203
+ return (
204
+ <>
205
+ <MetaRow label="Material type" value={summary.type} />
206
+ <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
207
+ <span style={{ ...labelStyle, marginBottom: 0 }}>Base color</span>
208
+ <span
209
+ title={summary.color}
210
+ style={{
211
+ width: 14,
212
+ height: 14,
213
+ borderRadius: radius.sm,
214
+ background: summary.color,
215
+ border: `1px solid ${border[2]}`,
216
+ }}
217
+ />
218
+ <span style={valueStyle}>{summary.color}</span>
219
+ </div>
220
+ </>
221
+ );
222
+ }
223
+
224
+ /** The registered section body — renders ONLY while an asset is selected
225
+ * (the registration's `match` gates on the same store read). */
226
+ export function AssetSelectionSection() {
227
+ const asset = getSelectedAsset();
228
+ if (!asset) return null;
229
+ const ext = asset.name.includes('.') ? (asset.name.split('.').pop() ?? '') : '';
230
+ return (
231
+ <div
232
+ data-testid="inspector-asset-selection"
233
+ style={{
234
+ pointerEvents: 'auto',
235
+ padding: 8,
236
+ borderBottom: `1px solid ${border[1]}`,
237
+ display: 'flex',
238
+ flexDirection: 'column',
239
+ gap: 6,
240
+ }}
241
+ >
242
+ <div style={{ ...labelStyle, marginBottom: 0, textTransform: 'uppercase' }}>Asset</div>
243
+ {/* §8: source-owned name, as authored. */}
244
+ <div style={{ fontWeight: 600, fontSize: 12, color: text[1], wordBreak: 'break-all' }}>
245
+ {asset.name}
246
+ </div>
247
+ {asset.kind === 'image' && <ImageSummary asset={asset} />}
248
+ {asset.kind === 'model' && <ModelSummary asset={asset} />}
249
+ {asset.kind === 'audio' && <AudioSummary asset={asset} />}
250
+ {asset.kind === 'material' && <MaterialSummary asset={asset} />}
251
+ {asset.kind === 'json' && asset.path.split(/[?#]/, 1)[0]!.endsWith('.inputmap.json') && (
252
+ <InputMapSummary asset={asset} />
253
+ )}
254
+ <MetaRow label="Path" value={asset.path} />
255
+ {asset.selectionCount && asset.selectionCount > 1 && (
256
+ <MetaRow label="Selection" value={`${asset.selectionCount} assets`} />
257
+ )}
258
+ {ext && <MetaRow label="Format" value={ext.toUpperCase()} />}
259
+ {asset.sizeBytes !== undefined && (
260
+ <MetaRow label="Size" value={formatSize(asset.sizeBytes)} />
261
+ )}
262
+ {asset.capabilities && (
263
+ <>
264
+ <MetaRow
265
+ label="Runtime readiness"
266
+ value={
267
+ asset.capabilities.runtimeReady ? 'Runtime-ready' : 'Import or conversion required'
268
+ }
269
+ />
270
+ <MetaRow
271
+ label="Preview"
272
+ value={asset.capabilities.previewable ? 'Available' : 'Unsupported'}
273
+ />
274
+ <MetaRow
275
+ label="Placement"
276
+ value={asset.capabilities.placeable ? 'Placeable' : 'Not placeable'}
277
+ />
278
+ <MetaRow label="Editor" value={assetDocumentKind(asset.capabilities) ?? 'No editor'} />
279
+ </>
280
+ )}
281
+ {asset.health && <MetaRow label="Health" value={asset.health} />}
282
+ {asset.healthCodes && <MetaRow label="Issues" value={asset.healthCodes.join(', ')} />}
283
+ {asset.dependencies && (
284
+ <MetaRow label="Dependencies" value={asset.dependencies.join(', ') || 'None'} />
285
+ )}
286
+ {asset.references && (
287
+ <MetaRow
288
+ label="References"
289
+ value={
290
+ asset.references
291
+ .map((reference) => `${reference.ownerPath} ${reference.jsonPath}`)
292
+ .join(', ') || 'None'
293
+ }
294
+ />
295
+ )}
296
+ {asset.sourcePath && <MetaRow label="Imported from" value={asset.sourcePath} />}
297
+ <div style={{ display: 'flex', gap: 6 }}>
298
+ <Button
299
+ type="button"
300
+ data-command-id={PROJECT_ASSET_COMMANDS.open.id}
301
+ onClick={() =>
302
+ window.dispatchEvent(
303
+ new CustomEvent('editor:open-project-asset', { detail: { path: asset.path } }),
304
+ )
305
+ }
306
+ >
307
+ Open
308
+ </Button>
309
+ <Button
310
+ type="button"
311
+ data-command-id={PROJECT_ASSET_COMMANDS.reimport.id}
312
+ disabled={!asset.sourcePath}
313
+ title={asset.sourcePath ? 'Run the saved import recipe again' : 'No import recipe'}
314
+ onClick={() =>
315
+ window.dispatchEvent(
316
+ new CustomEvent('editor:reimport-project-asset', { detail: { path: asset.path } }),
317
+ )
318
+ }
319
+ >
320
+ Reimport
321
+ </Button>
322
+ </div>
323
+ <div style={{ fontSize: 10, color: text[3] }}>
324
+ Double-click (or press Enter) in the asset browser to open the full viewer.
325
+ </div>
326
+ </div>
327
+ );
328
+ }
329
+
330
+ // Import-time registration (side-effect module, loaded by `main.tsx` before
331
+ // the other inspector contributions so this section renders first when an
332
+ // asset is selected). `match` ignores node/adapter deliberately: §5.1's
333
+ // asset selection is browser state, orthogonal to entity selection — the
334
+ // Inspector re-renders on asset-selection changes via its own subscription.
335
+ registerInspectorSections({
336
+ match: () => getSelectedAsset() !== null,
337
+ Section: AssetSelectionSection,
338
+ });
@@ -1,15 +1,10 @@
1
1
  import { useEffect, useRef, useState } from 'react';
2
- import { SectionHeader } from '../primitives/SectionHeader';
2
+ import { Button, Checkbox, RangeInput, SectionHeader, themeVars } from '../../design-system';
3
3
 
4
- const labelStyle: React.CSSProperties = { fontSize: 11, color: '#8c8c8c', marginBottom: 2 };
5
- const btnStyle: React.CSSProperties = {
6
- background: '#333',
7
- color: '#c5c8ce',
8
- border: '1px solid #444',
9
- borderRadius: 3,
10
- padding: '4px 16px',
11
- cursor: 'pointer',
4
+ const labelStyle: React.CSSProperties = {
12
5
  fontSize: 11,
6
+ color: themeVars.content.dim,
7
+ marginBottom: 2,
13
8
  };
14
9
 
15
10
  export function AudioViewer({ assetPath }: { assetPath: string }) {
@@ -17,6 +12,8 @@ export function AudioViewer({ assetPath }: { assetPath: string }) {
17
12
  const [playing, setPlaying] = useState(false);
18
13
  const [duration, setDuration] = useState<number | null>(null);
19
14
  const [currentTime, setCurrentTime] = useState(0);
15
+ const [loop, setLoop] = useState(false);
16
+ const [volume, setVolume] = useState(1);
20
17
  const fileName = assetPath.split('/').pop() ?? assetPath;
21
18
  const ext = assetPath.split('.').pop()?.toUpperCase() ?? '';
22
19
 
@@ -46,15 +43,22 @@ export function AudioViewer({ assetPath }: { assetPath: string }) {
46
43
 
47
44
  return (
48
45
  <div style={{ padding: 8, display: 'flex', flexDirection: 'column', gap: 8 }}>
49
- <div style={{ fontWeight: 600, fontSize: 12, color: '#c5c8ce', wordBreak: 'break-all' }}>
46
+ <div
47
+ style={{
48
+ fontWeight: 600,
49
+ fontSize: 12,
50
+ color: themeVars.content.primary,
51
+ wordBreak: 'break-all',
52
+ }}
53
+ >
50
54
  {fileName}
51
55
  </div>
52
56
  {/* Player */}
53
57
  <div
54
58
  style={{
55
59
  width: '100%',
56
- background: '#1e1e1e',
57
- borderRadius: 4,
60
+ background: themeVars.surface.inset,
61
+ borderRadius: themeVars.shape.small,
58
62
  display: 'flex',
59
63
  alignItems: 'center',
60
64
  justifyContent: 'center',
@@ -65,6 +69,8 @@ export function AudioViewer({ assetPath }: { assetPath: string }) {
65
69
  >
66
70
  {/* Audio icon */}
67
71
  <svg viewBox="0 0 24 24" width={48} height={48}>
72
+ {/* #34d399 = the asset-category audio green (AssetBrowser's assetIconColors)
73
+ — a deliberate category-palette literal, not chrome. */}
68
74
  <rect x="3" y="3" width="18" height="18" rx="2" fill="#34d399" />
69
75
  <path
70
76
  d="M9 8l4-2v12l-4-2H7V10h2zm6 1v6m2-5v4"
@@ -76,7 +82,14 @@ export function AudioViewer({ assetPath }: { assetPath: string }) {
76
82
  </svg>
77
83
  {/* Progress */}
78
84
  {duration != null && (
79
- <div style={{ width: '100%', fontSize: 10, color: '#8c8c8c', textAlign: 'center' }}>
85
+ <div
86
+ style={{
87
+ width: '100%',
88
+ fontSize: 10,
89
+ color: themeVars.content.muted,
90
+ textAlign: 'center',
91
+ }}
92
+ >
80
93
  {formatTime(currentTime)} / {formatTime(duration)}
81
94
  </div>
82
95
  )}
@@ -86,8 +99,8 @@ export function AudioViewer({ assetPath }: { assetPath: string }) {
86
99
  style={{
87
100
  width: '100%',
88
101
  height: 4,
89
- background: '#333',
90
- borderRadius: 2,
102
+ background: themeVars.surface.raised,
103
+ borderRadius: themeVars.shape.small,
91
104
  cursor: 'pointer',
92
105
  position: 'relative',
93
106
  }}
@@ -103,19 +116,56 @@ export function AudioViewer({ assetPath }: { assetPath: string }) {
103
116
  style={{
104
117
  width: `${(currentTime / duration) * 100}%`,
105
118
  height: '100%',
119
+ // Same category-audio green as the icon above.
106
120
  background: '#34d399',
107
- borderRadius: 2,
121
+ borderRadius: themeVars.shape.small,
108
122
  }}
109
123
  />
110
124
  </div>
111
125
  )}
112
- <button type="button" onClick={togglePlay} style={btnStyle}>
126
+ <Button type="button" variant="secondary" size="comfortable" onClick={togglePlay}>
113
127
  {playing ? 'Pause' : 'Play'}
114
- </button>
128
+ </Button>
129
+ <div
130
+ role="img"
131
+ aria-label="Audio waveform"
132
+ style={{ width: '100%', height: 36, display: 'flex', alignItems: 'center', gap: 2 }}
133
+ >
134
+ {Array.from({ length: 48 }, (_, index) => (
135
+ <i
136
+ key={index}
137
+ style={{
138
+ flex: 1,
139
+ height: `${20 + ((index * 37) % 75)}%`,
140
+ background: '#34d399',
141
+ opacity: index / 48 <= currentTime / (duration || 1) ? 1 : 0.3,
142
+ }}
143
+ />
144
+ ))}
145
+ </div>
146
+ <label style={{ fontSize: 11, color: themeVars.content.muted }}>
147
+ <Checkbox checked={loop} onChange={(event) => setLoop(event.target.checked)} /> Loop
148
+ </label>
149
+ <label style={{ fontSize: 11, color: themeVars.content.muted }}>
150
+ Volume{' '}
151
+ <RangeInput
152
+ aria-label="Audio volume"
153
+ min="0"
154
+ max="1"
155
+ step="0.05"
156
+ value={volume}
157
+ onChange={(event) => {
158
+ const value = Number(event.target.value);
159
+ setVolume(value);
160
+ if (audioRef.current) audioRef.current.volume = value;
161
+ }}
162
+ />
163
+ </label>
115
164
  </div>
116
165
  <audio
117
166
  ref={audioRef}
118
167
  src={assetPath}
168
+ loop={loop}
119
169
  onLoadedMetadata={() => {
120
170
  if (audioRef.current) setDuration(audioRef.current.duration);
121
171
  }}
@@ -128,19 +178,21 @@ export function AudioViewer({ assetPath }: { assetPath: string }) {
128
178
  <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
129
179
  <div>
130
180
  <div style={labelStyle}>Path</div>
131
- <div style={{ fontSize: 11, color: '#c5c8ce', wordBreak: 'break-all' }}>
181
+ <div style={{ fontSize: 11, color: themeVars.content.primary, wordBreak: 'break-all' }}>
132
182
  {assetPath}
133
183
  </div>
134
184
  </div>
135
185
  {duration != null && (
136
186
  <div>
137
187
  <div style={labelStyle}>Duration</div>
138
- <div style={{ fontSize: 11, color: '#c5c8ce' }}>{formatTime(duration)}</div>
188
+ <div style={{ fontSize: 11, color: themeVars.content.primary }}>
189
+ {formatTime(duration)}
190
+ </div>
139
191
  </div>
140
192
  )}
141
193
  <div>
142
194
  <div style={labelStyle}>Format</div>
143
- <div style={{ fontSize: 11, color: '#c5c8ce' }}>{ext}</div>
195
+ <div style={{ fontSize: 11, color: themeVars.content.primary }}>{ext}</div>
144
196
  </div>
145
197
  </div>
146
198
  </SectionHeader>
@@ -1,8 +1,12 @@
1
1
  import { resolveUrl } from '@engine/loader';
2
2
  import { useEffect, useState } from 'react';
3
- import { SectionHeader } from '../primitives/SectionHeader';
3
+ import { SectionHeader, themeVars } from '../../design-system';
4
4
 
5
- const labelStyle: React.CSSProperties = { fontSize: 11, color: '#8c8c8c', marginBottom: 2 };
5
+ const labelStyle: React.CSSProperties = {
6
+ fontSize: 11,
7
+ color: themeVars.content.muted,
8
+ marginBottom: 2,
9
+ };
6
10
 
7
11
  export function GenericJsonViewer({ assetPath }: { assetPath: string }) {
8
12
  const [content, setContent] = useState<string | null>(null);
@@ -34,32 +38,41 @@ export function GenericJsonViewer({ assetPath }: { assetPath: string }) {
34
38
 
35
39
  return (
36
40
  <div style={{ padding: 8, display: 'flex', flexDirection: 'column', gap: 8 }}>
37
- <div style={{ fontWeight: 600, fontSize: 12, color: '#c5c8ce', wordBreak: 'break-all' }}>
41
+ <div
42
+ style={{
43
+ fontWeight: 600,
44
+ fontSize: 12,
45
+ color: themeVars.content.primary,
46
+ wordBreak: 'break-all',
47
+ }}
48
+ >
38
49
  {fileName}
39
50
  </div>
40
51
  <div
41
52
  style={{
42
- background: '#1e1e1e',
43
- borderRadius: 4,
53
+ background: themeVars.surface.inset,
54
+ borderRadius: themeVars.shape.small,
44
55
  padding: 8,
45
56
  overflow: 'auto',
46
- scrollbarWidth: 'none',
47
57
  maxHeight: 500,
48
58
  }}
49
59
  >
50
60
  {error ? (
51
- <span style={{ color: '#F53352', fontSize: 11 }}>Failed to load file</span>
61
+ <span style={{ color: themeVars.semantic.danger, fontSize: 11 }}>
62
+ Failed to load file
63
+ </span>
52
64
  ) : content === null ? (
53
- <span style={{ color: '#8c8c8c', fontSize: 11 }}>Loading...</span>
65
+ <span style={{ color: themeVars.content.muted, fontSize: 11 }}>Loading...</span>
54
66
  ) : (
55
67
  <pre
56
68
  style={{
57
69
  margin: 0,
58
70
  fontSize: 10,
59
- color: '#c5c8ce',
71
+ color: themeVars.content.primary,
60
72
  whiteSpace: 'pre-wrap',
61
73
  wordBreak: 'break-all',
62
- fontFamily: 'monospace',
74
+ // B-6: the one editor mono stack (was bare 'monospace').
75
+ fontFamily: themeVars.typography.mono,
63
76
  }}
64
77
  >
65
78
  {content}
@@ -69,7 +82,9 @@ export function GenericJsonViewer({ assetPath }: { assetPath: string }) {
69
82
  <SectionHeader label="Info" defaultOpen={false}>
70
83
  <div>
71
84
  <div style={labelStyle}>Path</div>
72
- <div style={{ fontSize: 11, color: '#c5c8ce', wordBreak: 'break-all' }}>{assetPath}</div>
85
+ <div style={{ fontSize: 11, color: themeVars.content.primary, wordBreak: 'break-all' }}>
86
+ {assetPath}
87
+ </div>
73
88
  </div>
74
89
  </SectionHeader>
75
90
  </div>