@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,96 +1,32 @@
1
1
  import {
2
- faDesktop,
3
2
  faForwardStep,
4
3
  faHammer,
5
4
  faPause,
6
5
  faPlay,
6
+ faRotateRight,
7
7
  faStop,
8
8
  faVolumeHigh,
9
9
  faVolumeXmark,
10
10
  } from '@fortawesome/free-solid-svg-icons';
11
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
12
- import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react';
11
+ import { useCallback, useEffect, useState, useSyncExternalStore } from 'react';
12
+ import { Button, EditorIcon, IconButton, Inline, Text, ToolbarDivider } from '../design-system';
13
13
  import { useEditorStore } from '../EditorContext';
14
+ import { getEditorMode } from '../editor-mode';
14
15
  import { getIngestPlayControl, isIngestActive } from '../ingest-mode';
15
16
  import {
16
17
  enterPlayMode,
17
18
  exitPlayMode,
18
19
  getGameAudio,
20
+ getRestartRequiredReason,
19
21
  pausePlayMode,
20
22
  resumePlayMode,
21
23
  stepPlayMode,
24
+ subscribeRestartRequired,
22
25
  } from '../play-mode';
26
+ import { openBuildProfilesDocument } from './build-documents';
23
27
 
24
- export interface Resolution {
25
- label: string;
26
- width: number | null;
27
- height: number | null;
28
- }
29
-
30
- export const RESOLUTIONS: Resolution[] = [
31
- { label: 'Fill', width: null, height: null },
32
- { label: 'iPhone SE \u2014 375\u00d7667', width: 375, height: 667 },
33
- { label: 'iPhone 14 \u2014 390\u00d7844', width: 390, height: 844 },
34
- { label: 'iPhone 14 Pro Max \u2014 430\u00d7932', width: 430, height: 932 },
35
- { label: 'iPad Mini \u2014 768\u00d71024', width: 768, height: 1024 },
36
- { label: 'iPad Pro 11\u2033 \u2014 834\u00d71194', width: 834, height: 1194 },
37
- { label: 'Laptop \u2014 1366\u00d7768', width: 1366, height: 768 },
38
- { label: 'Desktop \u2014 1920\u00d71080', width: 1920, height: 1080 },
39
- ];
40
-
41
- const barStyle: React.CSSProperties = {
42
- position: 'absolute',
43
- top: 8,
44
- left: '50%',
45
- transform: 'translateX(-50%)',
46
- display: 'flex',
47
- alignItems: 'center',
48
- gap: 2,
49
- padding: '4px 6px',
50
- background: 'rgba(36, 36, 36, 0.9)',
51
- border: '1px solid #444',
52
- borderRadius: 6,
53
- backdropFilter: 'blur(8px)',
54
- zIndex: 100,
55
- pointerEvents: 'auto',
56
- };
57
-
58
- const btnBase: React.CSSProperties = {
59
- background: 'transparent',
60
- border: 'none',
61
- borderRadius: 4,
62
- padding: '4px 10px',
63
- cursor: 'pointer',
64
- color: '#c5c8ce',
65
- fontSize: 14,
66
- display: 'flex',
67
- alignItems: 'center',
68
- gap: 4,
69
- };
70
-
71
- const separator: React.CSSProperties = {
72
- width: 1,
73
- height: 18,
74
- background: '#555',
75
- margin: '0 2px',
76
- };
77
-
78
- const regimeStyle: React.CSSProperties = {
79
- fontSize: 11,
80
- color: '#9a9a9a',
81
- padding: '0 4px',
82
- whiteSpace: 'nowrap',
83
- };
28
+ export { type Resolution, ResolutionPicker } from './ResolutionPicker';
84
29
 
85
- /**
86
- * Wave 20 — names the active play-edit persistence regime (the previously
87
- * invisible ephemeral-vs-overlay split, docs/MULTI-WORLD-DESIGN.md §1.F /
88
- * MASTER-ARCHITECTURE-REVIEW §7.4 gap 4): a single-world session's edits are
89
- * discarded on stop; a multi-world (≥2) session's edits survive via per-world
90
- * overlays. Read-only reflection of `store.playEditRegime` (set by
91
- * play-mode.ts from the SAME decision that picks the real persistence
92
- * provider) — absent whenever that regime is null (not playing).
93
- */
94
30
  function SaveRegimeIndicator({ regime }: { regime: 'ephemeral' | 'overlay' | null }) {
95
31
  if (!regime) return null;
96
32
  const label =
@@ -98,21 +34,22 @@ function SaveRegimeIndicator({ regime }: { regime: 'ephemeral' | 'overlay' | nul
98
34
  ? 'Play edits: saved per world (overlay)'
99
35
  : 'Play edits: discarded on stop';
100
36
  return (
101
- <span data-testid="play-edit-regime" style={regimeStyle} title={label}>
37
+ <Text data-testid="play-edit-regime" variant="caption" tone="muted" title={label}>
102
38
  {label}
103
- </span>
39
+ </Text>
104
40
  );
105
41
  }
106
42
 
107
43
  const MUTE_KEY = 'editor:muted';
108
44
 
109
- function MuteButton() {
45
+ export function MuteButton() {
110
46
  const [muted, setMuted] = useState(() => localStorage.getItem(MUTE_KEY) === '1');
111
47
 
112
48
  useEffect(() => {
113
- if (!muted) return;
114
- const audio = getGameAudio();
115
- if (audio) audio.masterGain.gain.value = 0;
49
+ if (muted) {
50
+ const audio = getGameAudio();
51
+ if (audio) audio.masterGain.gain.value = 0;
52
+ }
116
53
  });
117
54
 
118
55
  const toggle = useCallback(() => {
@@ -125,232 +62,125 @@ function MuteButton() {
125
62
  }, [muted]);
126
63
 
127
64
  return (
128
- <button
129
- style={{ ...btnBase, fontSize: 12 }}
65
+ <IconButton
66
+ aria-label={muted ? 'Unmute game audio' : 'Mute game audio'}
67
+ aria-pressed={muted}
68
+ size="comfortable"
130
69
  onClick={toggle}
131
70
  title={muted ? 'Unmute game audio' : 'Mute game audio'}
132
71
  >
133
- <FontAwesomeIcon icon={muted ? faVolumeXmark : faVolumeHigh} />
134
- </button>
72
+ <EditorIcon icon={muted ? faVolumeXmark : faVolumeHigh} size="md" />
73
+ </IconButton>
135
74
  );
136
75
  }
137
76
 
138
- function ResolutionPicker({
139
- resolution,
140
- onResolutionChange,
141
- scale,
77
+ function TransportButton({
78
+ label,
79
+ icon,
80
+ onClick,
81
+ title = label,
142
82
  }: {
143
- resolution: Resolution;
144
- onResolutionChange: (r: Resolution) => void;
145
- scale: number;
83
+ label: string;
84
+ icon: typeof faPlay;
85
+ onClick: () => void;
86
+ title?: string;
146
87
  }) {
147
- const [open, setOpen] = useState(false);
148
- const ref = useRef<HTMLDivElement>(null);
149
-
150
- // Close on outside click
151
- useEffect(() => {
152
- if (!open) return;
153
- const handler = (e: MouseEvent) => {
154
- if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);
155
- };
156
- document.addEventListener('mousedown', handler);
157
- return () => document.removeEventListener('mousedown', handler);
158
- }, [open]);
159
-
160
- const isFill = resolution.width === null;
161
- const label = isFill ? 'Fill' : `${resolution.width}\u00d7${resolution.height}`;
162
-
163
88
  return (
164
- <div ref={ref} style={{ position: 'relative' }}>
165
- <button
166
- style={{ ...btnBase, fontSize: 11, fontFamily: 'monospace', gap: 5 }}
167
- onClick={() => setOpen((v) => !v)}
168
- title="Change game resolution"
169
- >
170
- <FontAwesomeIcon icon={faDesktop} style={{ fontSize: 11 }} />
171
- <span>{label}</span>
172
- {!isFill && scale < 1 && <span style={{ color: '#888' }}>{Math.round(scale * 100)}%</span>}
173
- </button>
174
- {open && (
175
- <div
176
- style={{
177
- position: 'absolute',
178
- top: '100%',
179
- right: 0,
180
- marginTop: 4,
181
- background: '#252526',
182
- border: '1px solid #444',
183
- borderRadius: 4,
184
- overflow: 'hidden',
185
- minWidth: 200,
186
- zIndex: 200,
187
- }}
188
- >
189
- {RESOLUTIONS.map((res) => (
190
- <button
191
- key={res.label}
192
- type="button"
193
- style={{
194
- display: 'block',
195
- width: '100%',
196
- textAlign: 'left',
197
- padding: '6px 12px',
198
- border: 'none',
199
- background: res.label === resolution.label ? '#37373d' : 'transparent',
200
- color: res.label === resolution.label ? '#fff' : '#ccc',
201
- fontSize: 12,
202
- cursor: 'pointer',
203
- fontFamily: 'inherit',
204
- }}
205
- onMouseEnter={(e) => {
206
- (e.target as HTMLElement).style.background = '#3c3c3c';
207
- }}
208
- onMouseLeave={(e) => {
209
- (e.target as HTMLElement).style.background =
210
- res.label === resolution.label ? '#37373d' : 'transparent';
211
- }}
212
- onClick={() => {
213
- onResolutionChange(res);
214
- setOpen(false);
215
- }}
216
- >
217
- {res.label}
218
- </button>
219
- ))}
220
- </div>
221
- )}
222
- </div>
89
+ <IconButton aria-label={label} size="comfortable" onClick={onClick} title={title}>
90
+ <EditorIcon icon={icon} size="md" />
91
+ </IconButton>
223
92
  );
224
93
  }
225
94
 
226
- interface PlayBarProps {
227
- resolution?: Resolution;
228
- onResolutionChange?: (r: Resolution) => void;
229
- scale?: number;
230
- }
231
-
232
- export function PlayBar({ resolution, onResolutionChange, scale }: PlayBarProps) {
95
+ /** Global transport. Resolution and mute stay in the active Game/story document toolbar. */
96
+ export function PlayBar() {
233
97
  const store = useEditorStore();
234
98
  useSyncExternalStore(store.subscribe, store.getSnapshot);
235
99
  const state = store.playState;
236
- const showRes = resolution && onResolutionChange;
100
+ const restartReason = useSyncExternalStore(
101
+ subscribeRestartRequired,
102
+ getRestartRequiredReason,
103
+ getRestartRequiredReason,
104
+ );
105
+ const restartButton = (
106
+ <Button
107
+ variant={restartReason ? 'primary' : 'ghost'}
108
+ size="comfortable"
109
+ data-testid="restart-game"
110
+ onClick={() => void enterPlayMode()}
111
+ title={
112
+ restartReason ??
113
+ 'Restart game (dispose and remount every root without reloading the editor)'
114
+ }
115
+ >
116
+ <EditorIcon icon={faRotateRight} size="md" />
117
+ Restart Game
118
+ </Button>
119
+ );
237
120
  // F17/F21: ingest sessions get a real play surface instead of a silent
238
121
  // no-op. Mounts are cold (getIngestPlayControl's doc comment); ▶ starts or
239
122
  // resumes the ingested game's own loop/session, ⏸ freezes it.
240
123
  const [, forceIngestRender] = useState(0);
241
124
  const ingest = isIngestActive() ? getIngestPlayControl() : null;
242
125
  if (ingest) {
243
- const playing = ingest.playing;
244
126
  return (
245
- <div style={barStyle}>
246
- {playing ? (
247
- <button
248
- style={btnBase}
249
- onClick={() => {
250
- ingest.pause();
251
- forceIngestRender((n) => n + 1);
252
- }}
253
- title="Pause ingested game (freezes its own loop)"
254
- >
255
- <FontAwesomeIcon icon={faPause} />
256
- </button>
257
- ) : (
258
- <button
259
- style={btnBase}
260
- onClick={() => {
261
- ingest.play();
262
- forceIngestRender((n) => n + 1);
263
- }}
264
- title="Run ingested game (starts/resumes its own loop and session)"
265
- >
266
- <FontAwesomeIcon icon={faPlay} />
267
- </button>
268
- )}
269
- </div>
127
+ <Inline className="vgai-playbar" gap={2} align="center">
128
+ <TransportButton
129
+ label={ingest.playing ? 'Pause ingested game' : 'Run ingested game'}
130
+ icon={ingest.playing ? faPause : faPlay}
131
+ onClick={() => {
132
+ if (ingest.playing) ingest.pause();
133
+ else ingest.play();
134
+ forceIngestRender((value) => value + 1);
135
+ }}
136
+ />
137
+ </Inline>
270
138
  );
271
139
  }
272
140
 
273
141
  if (state === 'stopped') {
274
142
  return (
275
- <div style={barStyle}>
276
- <button style={btnBase} onClick={() => enterPlayMode()} title="Play (run game)">
277
- <FontAwesomeIcon icon={faPlay} />
278
- </button>
279
- <div style={separator} />
280
- <button
281
- style={{ ...btnBase, fontSize: 12 }}
282
- onClick={() => window.dispatchEvent(new CustomEvent('editor:show-build-tab'))}
283
- title="Build project"
284
- >
285
- <FontAwesomeIcon icon={faHammer} />
286
- </button>
287
- {showRes && (
143
+ <Inline className="vgai-playbar" gap={2} align="center">
144
+ <TransportButton
145
+ label="Play"
146
+ title="Play (run game)"
147
+ icon={faPlay}
148
+ onClick={() => void enterPlayMode()}
149
+ />
150
+ {getEditorMode() === 'server' && (
288
151
  <>
289
- <div style={separator} />
290
- <ResolutionPicker
291
- resolution={resolution}
292
- onResolutionChange={onResolutionChange}
293
- scale={scale ?? 1}
152
+ <ToolbarDivider />
153
+ <TransportButton
154
+ label="Build project"
155
+ icon={faHammer}
156
+ onClick={() => openBuildProfilesDocument(store)}
294
157
  />
295
158
  </>
296
159
  )}
297
- </div>
160
+ </Inline>
298
161
  );
299
162
  }
300
163
 
301
164
  if (state === 'playing') {
302
165
  return (
303
- <div style={barStyle}>
304
- <button style={btnBase} onClick={() => pausePlayMode()} title="Pause">
305
- <FontAwesomeIcon icon={faPause} />
306
- </button>
307
- <button style={btnBase} onClick={() => exitPlayMode()} title="Stop (Escape)">
308
- <FontAwesomeIcon icon={faStop} />
309
- </button>
310
- <div style={separator} />
311
- <MuteButton />
312
- <div style={separator} />
166
+ <Inline className="vgai-playbar" gap={2} align="center">
167
+ <TransportButton label="Pause" icon={faPause} onClick={() => pausePlayMode()} />
168
+ <TransportButton label="Stop" icon={faStop} onClick={() => exitPlayMode()} />
169
+ {restartButton}
170
+ <ToolbarDivider />
313
171
  <SaveRegimeIndicator regime={store.playEditRegime} />
314
- {showRes && (
315
- <>
316
- <div style={separator} />
317
- <ResolutionPicker
318
- resolution={resolution}
319
- onResolutionChange={onResolutionChange}
320
- scale={scale ?? 1}
321
- />
322
- </>
323
- )}
324
- </div>
172
+ </Inline>
325
173
  );
326
174
  }
327
175
 
328
- // paused
329
176
  return (
330
- <div style={barStyle}>
331
- <button style={btnBase} onClick={() => resumePlayMode()} title="Resume">
332
- <FontAwesomeIcon icon={faPlay} />
333
- </button>
334
- <button style={btnBase} onClick={() => stepPlayMode()} title="Step one frame">
335
- <FontAwesomeIcon icon={faForwardStep} />
336
- </button>
337
- <button style={btnBase} onClick={() => exitPlayMode()} title="Stop (Escape)">
338
- <FontAwesomeIcon icon={faStop} />
339
- </button>
340
- <div style={separator} />
341
- <MuteButton />
342
- <div style={separator} />
177
+ <Inline className="vgai-playbar" gap={2} align="center">
178
+ <TransportButton label="Resume" icon={faPlay} onClick={() => resumePlayMode()} />
179
+ {restartButton}
180
+ <TransportButton label="Step one frame" icon={faForwardStep} onClick={() => stepPlayMode()} />
181
+ <TransportButton label="Stop" icon={faStop} onClick={() => exitPlayMode()} />
182
+ <ToolbarDivider />
343
183
  <SaveRegimeIndicator regime={store.playEditRegime} />
344
- {showRes && (
345
- <>
346
- <div style={separator} />
347
- <ResolutionPicker
348
- resolution={resolution}
349
- onResolutionChange={onResolutionChange}
350
- scale={scale ?? 1}
351
- />
352
- </>
353
- )}
354
- </div>
184
+ </Inline>
355
185
  );
356
186
  }
@@ -1,4 +1,18 @@
1
1
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import {
3
+ Button,
4
+ Dialog,
5
+ DialogBody,
6
+ DialogField,
7
+ DialogFieldLabel,
8
+ DialogFooter,
9
+ DialogHeader,
10
+ JoinedField,
11
+ JoinedFieldSuffix,
12
+ Stack,
13
+ Text,
14
+ TextInput,
15
+ } from '../design-system';
2
16
 
3
17
  interface PrefabSaveDialogProps {
4
18
  defaultName: string;
@@ -63,139 +77,53 @@ export function PrefabSaveDialog({
63
77
  [handleSubmit, onCancel],
64
78
  );
65
79
 
66
- const inputStyle: React.CSSProperties = {
67
- width: '100%',
68
- background: '#1e1e1e',
69
- border: '1px solid #444',
70
- borderRadius: 3,
71
- color: '#c5c8ce',
72
- fontSize: 12,
73
- padding: '6px 8px',
74
- outline: 'none',
75
- boxSizing: 'border-box',
76
- };
77
-
78
- const labelStyle: React.CSSProperties = {
79
- fontSize: 11,
80
- color: '#8c8c8c',
81
- marginBottom: 4,
82
- };
83
-
84
80
  return (
85
- <div
86
- style={{
87
- position: 'fixed',
88
- inset: 0,
89
- background: 'rgba(0,0,0,0.5)',
90
- display: 'flex',
91
- alignItems: 'center',
92
- justifyContent: 'center',
93
- zIndex: 10000,
94
- pointerEvents: 'auto',
95
- }}
96
- onClick={onCancel}
97
- onKeyDown={handleKeyDown}
98
- >
99
- <div
100
- style={{
101
- background: '#2c2c2c',
102
- border: '1px solid #444',
103
- borderRadius: 8,
104
- padding: 20,
105
- minWidth: 360,
106
- boxShadow: '0 8px 32px rgba(0,0,0,0.6)',
107
- }}
108
- onClick={(e) => e.stopPropagation()}
109
- >
110
- <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 16, color: '#c5c8ce' }}>
111
- {title}
112
- </div>
113
-
114
- <div style={{ marginBottom: 12 }}>
115
- <div style={labelStyle}>Folder</div>
116
- <input
117
- type="text"
118
- value={folder}
119
- onChange={(e) => setFolder(e.target.value)}
120
- onKeyDown={handleKeyDown}
121
- placeholder={defaultFolder}
122
- style={inputStyle}
123
- />
124
- </div>
125
-
126
- <div style={{ marginBottom: 16 }}>
127
- <div style={labelStyle}>Prefab name</div>
128
- <div style={{ display: 'flex', alignItems: 'center', gap: 0 }}>
129
- <input
130
- ref={inputRef}
131
- type="text"
132
- value={filename}
133
- onChange={(e) => setFilename(e.target.value)}
81
+ <Dialog labelledBy="save-prefab-dialog-title" onDismiss={onCancel} onKeyDown={handleKeyDown}>
82
+ <DialogHeader titleId="save-prefab-dialog-title" title={title} />
83
+ <DialogBody>
84
+ <Stack gap={6}>
85
+ <DialogField htmlFor="save-prefab-folder">
86
+ <DialogFieldLabel>Folder</DialogFieldLabel>
87
+ <TextInput
88
+ id="save-prefab-folder"
89
+ value={folder}
90
+ onChange={(e) => setFolder(e.target.value)}
134
91
  onKeyDown={handleKeyDown}
135
- placeholder="my-prefab"
136
- style={{ ...inputStyle, borderTopRightRadius: 0, borderBottomRightRadius: 0 }}
92
+ placeholder={defaultFolder}
137
93
  />
138
- <span
139
- style={{
140
- background: '#333',
141
- border: '1px solid #444',
142
- borderLeft: 'none',
143
- borderTopRightRadius: 3,
144
- borderBottomRightRadius: 3,
145
- padding: '6px 8px',
146
- fontSize: 12,
147
- color: '#666',
148
- whiteSpace: 'nowrap',
149
- }}
150
- >
151
- .{extension}
152
- </span>
153
- </div>
154
- </div>
155
-
156
- <div style={{ fontSize: 11, color: '#666', marginBottom: 16 }}>
94
+ </DialogField>
95
+ <DialogField htmlFor="save-prefab-filename">
96
+ <DialogFieldLabel>Prefab name</DialogFieldLabel>
97
+ <JoinedField>
98
+ <TextInput
99
+ ref={inputRef}
100
+ id="save-prefab-filename"
101
+ value={filename}
102
+ onChange={(e) => setFilename(e.target.value)}
103
+ onKeyDown={handleKeyDown}
104
+ placeholder="my-prefab"
105
+ />
106
+ <JoinedFieldSuffix>.{extension}</JoinedFieldSuffix>
107
+ </JoinedField>
108
+ </DialogField>
109
+ </Stack>
110
+ <Text as="p" tone="dim">
157
111
  Will save to:{' '}
158
- <span style={{ color: '#8c8c8c' }}>
112
+ <Text tone="muted">
159
113
  {folder.trim().replace(/^\/+|\/+$/g, '')}
160
114
  {folder.trim() ? '/' : ''}
161
115
  {filename.trim() || '...'}.{extension}
162
- </span>
163
- </div>
164
-
165
- <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
166
- <button
167
- type="button"
168
- onClick={onCancel}
169
- style={{
170
- background: '#333',
171
- color: '#c5c8ce',
172
- border: '1px solid #444',
173
- borderRadius: 4,
174
- padding: '6px 16px',
175
- cursor: 'pointer',
176
- fontSize: 12,
177
- }}
178
- >
179
- Cancel
180
- </button>
181
- <button
182
- type="button"
183
- onClick={handleSubmit}
184
- style={{
185
- background: '#3b82f6',
186
- color: '#fff',
187
- border: '1px solid #60a5fa',
188
- borderRadius: 4,
189
- padding: '6px 16px',
190
- cursor: 'pointer',
191
- fontSize: 12,
192
- fontWeight: 600,
193
- }}
194
- >
195
- Save Prefab
196
- </button>
197
- </div>
198
- </div>
199
- </div>
116
+ </Text>
117
+ </Text>
118
+ </DialogBody>
119
+ <DialogFooter>
120
+ <Button variant="ghost" size="comfortable" onClick={onCancel}>
121
+ Cancel
122
+ </Button>
123
+ <Button variant="primary" size="comfortable" onClick={handleSubmit}>
124
+ Save Prefab
125
+ </Button>
126
+ </DialogFooter>
127
+ </Dialog>
200
128
  );
201
129
  }