@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
@@ -1,8 +1,7 @@
1
1
  import type { SceneCamera } from '@engine/scene/scene-types';
2
+ import { NumberInput, SectionHeader, Select, Tooltip } from '../../design-system';
2
3
  import { useEditorStore } from '../../EditorContext';
3
- import { NumberInput } from '../primitives/NumberInput';
4
- import { SectionHeader } from '../primitives/SectionHeader';
5
- import { Tooltip } from '../primitives/Tooltip';
4
+ import { fieldLabelStyle, mixedStyle } from '../inspector-widgets/shared';
6
5
  import type { SectionProps } from './multi-edit-utils';
7
6
  import { commonNum, commonStr } from './multi-edit-utils';
8
7
 
@@ -28,24 +27,16 @@ export function CameraSection({ entities, ids }: SectionProps) {
28
27
  <SectionHeader label="Camera">
29
28
  <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
30
29
  <div>
31
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Type</div>
32
- <select
30
+ <div style={fieldLabelStyle}>Type</div>
31
+ <Select
32
+ className="vgai-select"
33
33
  value={camType ?? ''}
34
34
  onChange={(e) => update({ type: e.target.value as SceneCamera['type'] })}
35
- style={{
36
- width: '100%',
37
- background: '#1e1e1e',
38
- color: camType === null ? '#666' : '#c5c8ce',
39
- fontStyle: camType === null ? 'italic' : 'normal',
40
- border: '1px solid #333',
41
- borderRadius: 2,
42
- padding: '3px 4px',
43
- fontSize: 12,
44
- }}
35
+ style={{ width: '100%', ...mixedStyle(camType === null) }}
45
36
  >
46
37
  {camType === null && (
47
38
  <option value="" disabled>
48
- (mixed)
39
+ —
49
40
  </option>
50
41
  )}
51
42
  {cameraTypes.map((t) => (
@@ -53,12 +44,12 @@ export function CameraSection({ entities, ids }: SectionProps) {
53
44
  {t}
54
45
  </option>
55
46
  ))}
56
- </select>
47
+ </Select>
57
48
  </div>
58
49
  {camType === 'perspective' && (
59
50
  <div>
60
51
  <Tooltip text="Vertical field of view in degrees" position="right">
61
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>FOV (deg)</div>
52
+ <div style={fieldLabelStyle}>FOV (deg)</div>
62
53
  </Tooltip>
63
54
  <NumberInput
64
55
  value={commonNum(entities, (e) => e.camera?.fov ?? 60)}
@@ -69,7 +60,7 @@ export function CameraSection({ entities, ids }: SectionProps) {
69
60
  )}
70
61
  {camType === 'orthographic' && (
71
62
  <div>
72
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Ortho Size</div>
63
+ <div style={fieldLabelStyle}>Ortho Size</div>
73
64
  <NumberInput
74
65
  value={commonNum(entities, (e) => e.camera?.orthoSize ?? 5)}
75
66
  onChange={(v) => update({ orthoSize: v })}
@@ -79,23 +70,23 @@ export function CameraSection({ entities, ids }: SectionProps) {
79
70
  )}
80
71
  <div>
81
72
  <Tooltip text="Nearest visible distance" position="right">
82
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Near</div>
73
+ <div style={fieldLabelStyle}>Near</div>
83
74
  </Tooltip>
84
75
  <NumberInput value={near} onChange={(v) => update({ near: v })} step={0.1} />
85
76
  </div>
86
77
  <div>
87
78
  <Tooltip text="Farthest visible distance" position="right">
88
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Far</div>
79
+ <div style={fieldLabelStyle}>Far</div>
89
80
  </Tooltip>
90
81
  <NumberInput value={far} onChange={(v) => update({ far: v })} step={10} />
91
82
  </div>
92
83
  <div style={{ display: 'flex', gap: 6 }}>
93
84
  <div style={{ flex: 1 }}>
94
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Width</div>
85
+ <div style={fieldLabelStyle}>Width</div>
95
86
  <NumberInput value={width} onChange={(v) => update({ width: v })} step={1} />
96
87
  </div>
97
88
  <div style={{ flex: 1 }}>
98
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Height</div>
89
+ <div style={fieldLabelStyle}>Height</div>
99
90
  <NumberInput value={height} onChange={(v) => update({ height: v })} step={1} />
100
91
  </div>
101
92
  </div>
@@ -1,32 +1,30 @@
1
1
  import type { SceneEntity } from '@engine/scene/scene-types';
2
+ import {
3
+ Button,
4
+ Checkbox,
5
+ ColorInput,
6
+ JsonInput,
7
+ NumberInput,
8
+ SectionHeader,
9
+ Select,
10
+ TextInput,
11
+ Tooltip,
12
+ themeVars,
13
+ Vec3Input,
14
+ } from '../../design-system';
2
15
  import { useEditorStore } from '../../EditorContext';
3
16
  import { getLoadedComponents } from '../../script-loader';
4
- import { ColorInput } from '../primitives/ColorInput';
5
- import { JsonInput } from '../primitives/JsonInput';
6
- import { NumberInput } from '../primitives/NumberInput';
7
- import { SectionHeader } from '../primitives/SectionHeader';
8
- import { Tooltip } from '../primitives/Tooltip';
9
- import { Vec3Input } from '../primitives/Vec3Input';
17
+ import { LABEL_COL_WIDTH } from '../inspector-widgets/shared';
10
18
  import type { SectionProps } from './multi-edit-utils';
11
19
  import { type FieldDescriptor, introspectSchema } from './zod-fields';
12
20
 
13
21
  type ComponentMap = NonNullable<SceneEntity['components']>;
14
22
  type ComponentData = Record<string, unknown>;
15
23
 
16
- const inputStyle: React.CSSProperties = {
17
- flex: 1,
18
- background: '#1e1e1e',
19
- color: '#c5c8ce',
20
- border: '1px solid #333',
21
- borderRadius: 2,
22
- padding: '2px 4px',
23
- fontSize: 12,
24
- };
25
-
26
24
  const labelStyle: React.CSSProperties = {
27
25
  fontSize: 11,
28
- color: '#8c8c8c',
29
- width: 70,
26
+ color: themeVars.content.muted,
27
+ width: LABEL_COL_WIDTH,
30
28
  flexShrink: 0,
31
29
  };
32
30
 
@@ -93,24 +91,19 @@ export function ComponentsSection({ entities }: SectionProps) {
93
91
  marginBottom: 4,
94
92
  }}
95
93
  >
96
- <span style={{ fontSize: 11, fontWeight: 600, color: '#b0b0b0' }}>{compName}</span>
97
- <button
94
+ <span style={{ fontSize: 11, fontWeight: 600, color: themeVars.content.primary }}>
95
+ {compName}
96
+ </span>
97
+ <Button
98
98
  type="button"
99
99
  title="Remove component"
100
100
  data-testid={`component-remove-${compName}`}
101
101
  onClick={() => removeComponent(compName)}
102
- style={{
103
- background: 'transparent',
104
- border: 'none',
105
- color: '#777',
106
- cursor: 'pointer',
107
- fontSize: 12,
108
- lineHeight: 1,
109
- padding: 0,
110
- }}
102
+ variant="ghost"
103
+ size="compact"
111
104
  >
112
105
  ×
113
- </button>
106
+ </Button>
114
107
  </div>
115
108
 
116
109
  {fields
@@ -121,13 +114,14 @@ export function ComponentsSection({ entities }: SectionProps) {
121
114
  })}
122
115
 
123
116
  {addable.length > 0 && (
124
- <select
117
+ <Select
118
+ className="vgai-select"
125
119
  data-testid="component-add"
126
120
  value=""
127
121
  onChange={(e) => {
128
122
  if (e.target.value) addComponent(e.target.value);
129
123
  }}
130
- style={{ ...inputStyle, cursor: 'pointer' }}
124
+ style={{ width: '100%' }}
131
125
  >
132
126
  <option value="">+ Add component…</option>
133
127
  {addable.map((name) => (
@@ -135,7 +129,7 @@ export function ComponentsSection({ entities }: SectionProps) {
135
129
  {name}
136
130
  </option>
137
131
  ))}
138
- </select>
132
+ </Select>
139
133
  )}
140
134
  </div>
141
135
  </SectionHeader>
@@ -241,8 +235,8 @@ function renderWidget(
241
235
  );
242
236
  case 'boolean':
243
237
  return (
244
- <input
245
- type="checkbox"
238
+ <Checkbox
239
+ className="vgai-checkbox"
246
240
  data-testid={testId}
247
241
  checked={Boolean(value)}
248
242
  onChange={(e) => setField(compName, f.name, e.target.checked)}
@@ -270,18 +264,19 @@ function renderWidget(
270
264
  case 'enum':
271
265
  case 'select':
272
266
  return (
273
- <select
267
+ <Select
268
+ className="vgai-select"
274
269
  data-testid={testId}
275
270
  value={value == null ? '' : String(value)}
276
271
  onChange={(e) => setField(compName, f.name, e.target.value)}
277
- style={{ ...inputStyle, cursor: 'pointer' }}
272
+ style={{ width: '100%' }}
278
273
  >
279
274
  {(f.options ?? []).map((opt) => (
280
275
  <option key={opt} value={opt}>
281
276
  {opt}
282
277
  </option>
283
278
  ))}
284
- </select>
279
+ </Select>
285
280
  );
286
281
  default:
287
282
  return (
@@ -313,8 +308,8 @@ function RawInput({
313
308
  const id = testId ?? fieldTestId(compName, fieldKey);
314
309
  if (typeof value === 'boolean') {
315
310
  return (
316
- <input
317
- type="checkbox"
311
+ <Checkbox
312
+ className="vgai-checkbox"
318
313
  data-testid={id}
319
314
  checked={value}
320
315
  onChange={(e) => setField(compName, fieldKey, e.target.checked)}
@@ -333,14 +328,15 @@ function RawInput({
333
328
  <JsonInput
334
329
  value={value}
335
330
  onCommit={(v) => setField(compName, fieldKey, v)}
336
- style={inputStyle}
331
+ style={{ width: '100%' }}
337
332
  />
338
333
  </div>
339
334
  );
340
335
  }
341
336
  const display = value === null || value === undefined ? '' : String(value);
342
337
  return (
343
- <input
338
+ <TextInput
339
+ className="vgai-input"
344
340
  data-testid={id}
345
341
  value={display}
346
342
  onChange={(e) => {
@@ -352,7 +348,7 @@ function RawInput({
352
348
  setField(compName, fieldKey, raw);
353
349
  }
354
350
  }}
355
- style={inputStyle}
351
+ style={{ width: '100%' }}
356
352
  />
357
353
  );
358
354
  }
@@ -1,31 +1,20 @@
1
1
  import type { SceneEntity, SceneJoint } from '@engine/scene/scene-types';
2
+ import {
3
+ Button,
4
+ NumberInput,
5
+ SectionHeader,
6
+ Select,
7
+ themeVars,
8
+ Vec3Input,
9
+ } from '../../design-system';
2
10
  import { useEditorStore } from '../../EditorContext';
3
- import { NumberInput } from '../primitives/NumberInput';
4
- import { SectionHeader } from '../primitives/SectionHeader';
5
- import { Vec3Input } from '../primitives/Vec3Input';
11
+ import { fieldLabelStyle } from '../inspector-widgets/shared';
6
12
  import type { SectionProps } from './multi-edit-utils';
7
13
 
8
14
  const jointTypes: SceneJoint['type'][] = ['fixed', 'revolute', 'prismatic', 'spherical', 'spring'];
9
15
 
10
- const labelStyle: React.CSSProperties = { fontSize: 10, color: '#8c8c8c', marginBottom: 2 };
11
- const selectStyle: React.CSSProperties = {
12
- width: '100%',
13
- background: '#1e1e1e',
14
- color: '#c5c8ce',
15
- border: '1px solid #333',
16
- borderRadius: 2,
17
- padding: '3px 4px',
18
- fontSize: 12,
19
- };
20
- const btnStyle: React.CSSProperties = {
21
- background: '#333',
22
- color: '#c5c8ce',
23
- border: '1px solid #444',
24
- borderRadius: 3,
25
- padding: '2px 6px',
26
- cursor: 'pointer',
27
- fontSize: 10,
28
- };
16
+ const labelStyle: React.CSSProperties = fieldLabelStyle;
17
+ // Shared compact chrome button (I-8/I-10) — the old per-file literal.
29
18
 
30
19
  export function JointsSection({ entities }: SectionProps) {
31
20
  const store = useEditorStore();
@@ -75,12 +64,12 @@ export function JointsSection({ entities }: SectionProps) {
75
64
  />
76
65
  ))}
77
66
  {physicsEntities.length > 0 && (
78
- <button type="button" style={btnStyle} onClick={addJoint}>
67
+ <Button type="button" size="compact" onClick={addJoint}>
79
68
  + Add Joint
80
- </button>
69
+ </Button>
81
70
  )}
82
71
  {physicsEntities.length === 0 && joints.length === 0 && (
83
- <div style={{ fontSize: 10, color: '#666', fontStyle: 'italic' }}>
72
+ <div style={{ fontSize: 10, color: themeVars.content.dim, fontStyle: 'italic' }}>
84
73
  No other physics entities to connect to.
85
74
  </div>
86
75
  )}
@@ -111,9 +100,9 @@ function JointEntry({
111
100
  return (
112
101
  <div
113
102
  style={{
114
- background: '#1a1a1a',
115
- border: '1px solid #333',
116
- borderRadius: 3,
103
+ background: themeVars.surface.shell,
104
+ border: `1px solid ${themeVars.boundary.default}`,
105
+ borderRadius: themeVars.shape.small,
117
106
  padding: 6,
118
107
  display: 'flex',
119
108
  flexDirection: 'column',
@@ -122,38 +111,40 @@ function JointEntry({
122
111
  >
123
112
  {/* Header */}
124
113
  <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
125
- <span style={{ fontSize: 10, color: '#8c8c8c', fontWeight: 600 }}>#{index}</span>
126
- <select
114
+ <span style={{ fontSize: 10, color: themeVars.content.muted, fontWeight: 600 }}>
115
+ #{index}
116
+ </span>
117
+ <Select
118
+ className="vgai-select"
127
119
  value={joint.type}
128
120
  onChange={(e) => onUpdate({ type: e.target.value as SceneJoint['type'] })}
129
- style={{ ...selectStyle, flex: 1 }}
121
+ style={{ flex: 1 }}
130
122
  >
131
123
  {jointTypes.map((t) => (
132
124
  <option key={t} value={t}>
133
125
  {t}
134
126
  </option>
135
127
  ))}
136
- </select>
137
- <button
128
+ </Select>
129
+ <Button
138
130
  type="button"
131
+ variant="danger"
132
+ size="compact"
133
+ aria-label="Remove joint"
139
134
  onClick={onRemove}
140
- style={{
141
- ...btnStyle,
142
- color: '#F53352',
143
- padding: '1px 4px',
144
- }}
145
135
  >
146
- x
147
- </button>
136
+ ×
137
+ </Button>
148
138
  </div>
149
139
 
150
140
  {/* Target */}
151
141
  <div>
152
142
  <div style={labelStyle}>Target ({targetName})</div>
153
- <select
143
+ <Select
144
+ className="vgai-select"
154
145
  value={joint.target}
155
146
  onChange={(e) => onUpdate({ target: e.target.value })}
156
- style={selectStyle}
147
+ style={{ width: '100%' }}
157
148
  >
158
149
  {physicsEntities.map((e) => (
159
150
  <option key={e.id} value={e.id!}>
@@ -163,7 +154,7 @@ function JointEntry({
163
154
  {!physicsEntities.find((e) => e.id === joint.target) && (
164
155
  <option value={joint.target}>(missing: {joint.target.slice(0, 8)}...)</option>
165
156
  )}
166
- </select>
157
+ </Select>
167
158
  </div>
168
159
 
169
160
  {/* Anchors */}
@@ -1,13 +1,37 @@
1
1
  import type { SceneLight } from '@engine/scene/scene-types';
2
+ import { ColorInput, NumberInput, SectionHeader, Select, Tooltip } from '../../design-system';
2
3
  import { useEditorStore } from '../../EditorContext';
3
- import { ColorInput } from '../primitives/ColorInput';
4
- import { NumberInput } from '../primitives/NumberInput';
5
- import { SectionHeader } from '../primitives/SectionHeader';
6
- import { Tooltip } from '../primitives/Tooltip';
4
+ import { fieldLabelStyle, mixedStyle } from '../inspector-widgets/shared';
7
5
  import type { SectionProps } from './multi-edit-utils';
8
6
  import { commonNum, commonStr } from './multi-edit-utils';
9
7
 
10
- const lightTypes: SceneLight['type'][] = ['directional', 'point', 'spot', 'hemisphere'];
8
+ const lightTypes: SceneLight['type'][] = ['directional', 'point', 'spot', 'hemisphere', 'area'];
9
+
10
+ function intensityPresentation(type: SceneLight['type'] | null): {
11
+ label: string;
12
+ step: number;
13
+ help: string;
14
+ } {
15
+ if (type === 'point' || type === 'spot') {
16
+ return {
17
+ label: 'Intensity (cd)',
18
+ step: 10,
19
+ help: 'Native Three.js candela with distance decay. Values near 1 are candle-scale; emissive materials do not illuminate nearby objects.',
20
+ };
21
+ }
22
+ if (type === 'area') {
23
+ return {
24
+ label: 'Intensity (nit)',
25
+ step: 1,
26
+ help: 'Native Three.js RectAreaLight luminance in nit.',
27
+ };
28
+ }
29
+ return {
30
+ label: 'Intensity',
31
+ step: 0.1,
32
+ help: 'Native Three.js scene-light intensity.',
33
+ };
34
+ }
11
35
 
12
36
  export function LightSection({ entities, ids }: SectionProps) {
13
37
  const store = useEditorStore();
@@ -16,6 +40,7 @@ export function LightSection({ entities, ids }: SectionProps) {
16
40
  const lightType = commonStr(entities, (e) => e.light?.type);
17
41
  const color = commonStr(entities, (e) => e.light?.color ?? '#ffffff');
18
42
  const intensity = commonNum(entities, (e) => e.light?.intensity ?? 1);
43
+ const intensityUi = intensityPresentation(lightType as SceneLight['type'] | null);
19
44
 
20
45
  const update = (partial: Partial<SceneLight>) => {
21
46
  store.batchMutate(ids, (entity) => {
@@ -27,24 +52,16 @@ export function LightSection({ entities, ids }: SectionProps) {
27
52
  <SectionHeader label="Light">
28
53
  <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
29
54
  <div>
30
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Type</div>
31
- <select
55
+ <div style={fieldLabelStyle}>Type</div>
56
+ <Select
57
+ className="vgai-select"
32
58
  value={lightType ?? ''}
33
59
  onChange={(e) => update({ type: e.target.value as SceneLight['type'] })}
34
- style={{
35
- width: '100%',
36
- background: '#1e1e1e',
37
- color: lightType === null ? '#666' : '#c5c8ce',
38
- fontStyle: lightType === null ? 'italic' : 'normal',
39
- border: '1px solid #333',
40
- borderRadius: 2,
41
- padding: '3px 4px',
42
- fontSize: 12,
43
- }}
60
+ style={{ width: '100%', ...mixedStyle(lightType === null) }}
44
61
  >
45
62
  {lightType === null && (
46
63
  <option value="" disabled>
47
- (mixed)
64
+ —
48
65
  </option>
49
66
  )}
50
67
  {lightTypes.map((t) => (
@@ -52,19 +69,25 @@ export function LightSection({ entities, ids }: SectionProps) {
52
69
  {t}
53
70
  </option>
54
71
  ))}
55
- </select>
72
+ </Select>
56
73
  </div>
57
74
  <div>
58
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Color</div>
75
+ <div style={fieldLabelStyle}>Color</div>
59
76
  <ColorInput value={color} onChange={(v) => update({ color: v })} />
60
77
  </div>
61
78
  <div>
62
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Intensity</div>
63
- <NumberInput value={intensity} onChange={(v) => update({ intensity: v })} step={0.1} />
79
+ <Tooltip text={intensityUi.help} position="right">
80
+ <div style={fieldLabelStyle}>{intensityUi.label}</div>
81
+ </Tooltip>
82
+ <NumberInput
83
+ value={intensity}
84
+ onChange={(v) => update({ intensity: v })}
85
+ step={intensityUi.step}
86
+ />
64
87
  </div>
65
88
  {lightType === 'hemisphere' && (
66
89
  <div>
67
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Ground Color</div>
90
+ <div style={fieldLabelStyle}>Ground Color</div>
68
91
  <ColorInput
69
92
  value={commonStr(entities, (e) => e.light?.groundColor ?? '#000000')}
70
93
  onChange={(v) => update({ groundColor: v })}
@@ -72,22 +95,54 @@ export function LightSection({ entities, ids }: SectionProps) {
72
95
  </div>
73
96
  )}
74
97
  {(lightType === 'point' || lightType === 'spot') && (
75
- <div>
76
- <Tooltip text="Falloff distance (0 = infinite)" position="right">
77
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Distance</div>
78
- </Tooltip>
79
- <NumberInput
80
- value={commonNum(entities, (e) => e.light?.distance ?? 0)}
81
- onChange={(v) => update({ distance: v })}
82
- step={1}
83
- />
84
- </div>
98
+ <>
99
+ <div>
100
+ <Tooltip text="Falloff distance (0 = infinite)" position="right">
101
+ <div style={fieldLabelStyle}>Distance</div>
102
+ </Tooltip>
103
+ <NumberInput
104
+ value={commonNum(entities, (e) => e.light?.distance ?? 0)}
105
+ onChange={(v) => update({ distance: v })}
106
+ step={1}
107
+ />
108
+ </div>
109
+ <div>
110
+ <Tooltip text="Distance-decay exponent; 2 is inverse-square" position="right">
111
+ <div style={fieldLabelStyle}>Decay</div>
112
+ </Tooltip>
113
+ <NumberInput
114
+ value={commonNum(entities, (e) => e.light?.decay ?? 2)}
115
+ onChange={(v) => update({ decay: v })}
116
+ step={0.1}
117
+ />
118
+ </div>
119
+ </>
120
+ )}
121
+ {lightType === 'area' && (
122
+ <>
123
+ <div>
124
+ <div style={fieldLabelStyle}>Width</div>
125
+ <NumberInput
126
+ value={commonNum(entities, (e) => e.light?.width ?? 10)}
127
+ onChange={(v) => update({ width: v })}
128
+ step={0.1}
129
+ />
130
+ </div>
131
+ <div>
132
+ <div style={fieldLabelStyle}>Height</div>
133
+ <NumberInput
134
+ value={commonNum(entities, (e) => e.light?.height ?? 10)}
135
+ onChange={(v) => update({ height: v })}
136
+ step={0.1}
137
+ />
138
+ </div>
139
+ </>
85
140
  )}
86
141
  {lightType === 'spot' && (
87
142
  <>
88
143
  <div>
89
144
  <Tooltip text="Spotlight cone angle" position="right">
90
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Angle (deg)</div>
145
+ <div style={fieldLabelStyle}>Angle (deg)</div>
91
146
  </Tooltip>
92
147
  <NumberInput
93
148
  value={commonNum(
@@ -100,7 +155,7 @@ export function LightSection({ entities, ids }: SectionProps) {
100
155
  </div>
101
156
  <div>
102
157
  <Tooltip text="Soft edge falloff (0–1)" position="right">
103
- <div style={{ fontSize: 10, color: '#8c8c8c', marginBottom: 2 }}>Penumbra</div>
158
+ <div style={fieldLabelStyle}>Penumbra</div>
104
159
  </Tooltip>
105
160
  <NumberInput
106
161
  value={commonNum(entities, (e) => e.light?.penumbra ?? 0)}