@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,209 @@
1
+ import { themeVars } from '../design-system';
2
+ /**
3
+ * XState contributions (W3, docs/EDITOR-WORKSPACE-SHELL-TODO.md §4.3/§9 W3 —
4
+ * inventory row B6): the permanent bottom XSTATE tab and its demo-machine
5
+ * fallback are GONE from production UI. What replaces them, per §4.3's
6
+ * truthfulness rules:
7
+ *
8
+ * - a compact **State Machine** Inspector section that renders ONLY for a
9
+ * selected live entity whose object carries a real `bindXStateAnimation`
10
+ * binding (`_xstateAnimation` user-data, engine
11
+ * `animation/xstate-animation-binding.ts`) — active state(s) per layer,
12
+ * the machine's own id as its source identity, and an `Inspect Machine`
13
+ * action;
14
+ * - `Inspect Machine` opens the REAL machine inside the bottom Debugger.
15
+ * That instrument observes the live Game/Scene without replacing it;
16
+ * - an `Open State Machine: <id>` palette action per live registered
17
+ * machine (`listLiveMachines` scans the live object map for real
18
+ * bindings — the only truthful registry that exists today).
19
+ *
20
+ * NO fabricated hierarchy rows, NO demo machine anywhere: the shipped
21
+ * `character-animation-machine.fixture.ts` is now a TEST fixture only
22
+ * (`test/xstate-fixture-ban.test.ts` pins that), and every open path here
23
+ * requires an actual live binding — with none, nothing renders and nothing
24
+ * can be opened. The template project has no XState machine, so a template
25
+ * session shows no XState UI at all.
26
+ *
27
+ * `Open Source` (§4.3 mentions it MAY exist): deliberately NOT built —
28
+ * neither XState nor the binding carries a machine→source-file identity, and
29
+ * fabricating one (e.g. grepping for the machine id) would violate §4.3's
30
+ * "no ids decoded for magic words". When the engine grows a real
31
+ * machine→module provenance, the section is where it lands.
32
+ *
33
+ * Editing stays a code change: the graph view is inspect-only
34
+ * (docs/decisions/e4-xstate-authoring-boundary.md — its ownership decision
35
+ * is unchanged; only its bottom-dock placement is superseded, TODO §12).
36
+ */
37
+
38
+ import {
39
+ getXStateAnimationBindingsVersion,
40
+ subscribeXStateAnimationBindings,
41
+ type XStateAnimationBinding,
42
+ } from '@engine/animation/xstate-animation-binding';
43
+ import { getUserData } from '@engine/scene/user-data';
44
+ import { useSyncExternalStore } from 'react';
45
+ import type * as THREE from 'three';
46
+ import type { AnyStateMachine } from 'xstate';
47
+ import type { EditorAction } from '../action-registry';
48
+ import { Button } from '../design-system';
49
+ import { createHmrRegistrationGroup } from '../hmr-registration-group';
50
+ import { registerInspectorSections } from '../inspector-section-registry';
51
+ import { useLiveActorState } from '../xstate-inspect/use-live-actor-state';
52
+ import { openDebuggerPanel } from './debugger-panel-state';
53
+
54
+ /** The narrow store surface the XState contributions read: the live object
55
+ * map where real bindings live. */
56
+ export interface XStateInspectorStore {
57
+ readonly objectMap: Map<string, THREE.Object3D>;
58
+ }
59
+
60
+ let _store: XStateInspectorStore | null = null;
61
+ const registrationGroup = createHmrRegistrationGroup(import.meta.hot, 'xstate-inspector');
62
+
63
+ /** The selected entity's live binding, or `undefined` — the ONLY discovery
64
+ * path (§4.3: a machine is truthfully discoverable only through a live
65
+ * `bindXStateAnimation` binding). */
66
+ export function liveBindingFor(nodeId: string): XStateAnimationBinding | undefined {
67
+ const object = _store?.objectMap.get(nodeId);
68
+ return object ? getUserData(object, '_xstateAnimation') : undefined;
69
+ }
70
+
71
+ /**
72
+ * Wire the store and register the Inspector section (idempotent — the
73
+ * registration is permanent; `match` reads the CURRENT store, so with no
74
+ * configured store nothing ever matches). Returns a cleanup that clears the
75
+ * store reference (project switch / layout teardown).
76
+ */
77
+ export function configureXStateInspector(store: XStateInspectorStore): () => void {
78
+ _store = store;
79
+ registrationGroup.ensure((track) => {
80
+ track(
81
+ registerInspectorSections({
82
+ // §4.3 gating: matches ONLY a real node whose live object carries a
83
+ // real binding. Template entities (no machine) never match — the
84
+ // section must not render for them (unit-pinned).
85
+ match: (node) => node !== null && liveBindingFor(node.id) !== undefined,
86
+ Section: XStateMachineSection,
87
+ }),
88
+ );
89
+ });
90
+ return () => {
91
+ if (_store === store) _store = null;
92
+ };
93
+ }
94
+
95
+ /** Every live machine, by scanning the live object map for real bindings —
96
+ * the `Open State Machine…` command's truthful listing. */
97
+ export function listLiveMachines(): {
98
+ nodeId: string;
99
+ machineId: string;
100
+ label: string;
101
+ }[] {
102
+ if (!_store) return [];
103
+ const seen = new Set<XStateAnimationBinding>();
104
+ const out: { nodeId: string; machineId: string; label: string }[] = [];
105
+ for (const [nodeId, object] of _store.objectMap) {
106
+ const binding = getUserData(object, '_xstateAnimation');
107
+ if (!binding || seen.has(binding)) continue;
108
+ seen.add(binding);
109
+ const machine = binding.actor.logic as AnyStateMachine;
110
+ out.push({ nodeId, machineId: machine.id, label: object.name || nodeId });
111
+ }
112
+ return out;
113
+ }
114
+
115
+ /** `Open State Machine: <id>` palette actions — one per live machine; an
116
+ * empty list when none are live (never a demo entry). */
117
+ export function buildXStateMachineActions(): EditorAction[] {
118
+ return listLiveMachines().map((m) => ({
119
+ id: `xstate-machine:${m.machineId}:${m.nodeId}`,
120
+ label: `Open State Machine: ${m.machineId}`,
121
+ category: 'action' as const,
122
+ execute: () => void openXStateGraphDocument(m.nodeId),
123
+ }));
124
+ }
125
+
126
+ /** Open a live machine in the bottom Debugger while preserving the Game. */
127
+ export function openXStateGraphDocument(nodeId: string): boolean {
128
+ const binding = liveBindingFor(nodeId);
129
+ if (!_store || !binding) return false;
130
+ openDebuggerPanel('machines', nodeId);
131
+ return true;
132
+ }
133
+
134
+ /** Test-only reset — PAIR with `__resetInspectorSectionRegistryForTest`
135
+ * (clearing `_sectionRegistered` without clearing the section registry
136
+ * would double-register on the next configure). */
137
+ export function __resetXStateContributionsForTest(): void {
138
+ _store = null;
139
+ registrationGroup.reset();
140
+ }
141
+
142
+ // --- The compact Inspector section (§4.3) -----------------------------------
143
+
144
+ /** Registered via `configureXStateInspector` — renders ONLY when `match`
145
+ * found a real live binding for the selected node. */
146
+ export function XStateMachineSection({ nodeId }: { nodeId: string | null }) {
147
+ useSyncExternalStore(
148
+ subscribeXStateAnimationBindings,
149
+ getXStateAnimationBindingsVersion,
150
+ getXStateAnimationBindingsVersion,
151
+ );
152
+ const binding = nodeId ? liveBindingFor(nodeId) : undefined;
153
+ const machine = binding ? (binding.actor.logic as AnyStateMachine) : undefined;
154
+ // Follow live transitions (re-render per snapshot) — the layer readout
155
+ // below re-reads `getActiveLayers()` on each.
156
+ useLiveActorState(machine as AnyStateMachine, binding?.actor);
157
+ if (!binding || !machine || !nodeId) return null;
158
+ return (
159
+ <div
160
+ data-testid="inspector-xstate-section"
161
+ style={{
162
+ pointerEvents: 'auto',
163
+ padding: 8,
164
+ borderBottom: `1px solid ${themeVars.boundary.default}`,
165
+ }}
166
+ >
167
+ <div
168
+ style={{
169
+ fontSize: 11,
170
+ color: themeVars.content.dim,
171
+ textTransform: 'uppercase',
172
+ marginBottom: 4,
173
+ }}
174
+ >
175
+ State Machine
176
+ </div>
177
+ <div
178
+ style={{ fontSize: 11, color: themeVars.content.primary, fontWeight: 600, marginBottom: 2 }}
179
+ >
180
+ {machine.id}
181
+ </div>
182
+ <div style={{ fontSize: 10, color: themeVars.content.muted, marginBottom: 4 }}>
183
+ <span style={{ color: themeVars.semantic.success, fontWeight: 700 }}>●</span> Live —{' '}
184
+ {binding.getActiveLayers().map((layer, i) => (
185
+ <span key={layer.layer} data-testid={`xstate-section-layer-${layer.layer}`}>
186
+ {i > 0 && ' · '}
187
+ {layer.layer}:{' '}
188
+ <span
189
+ style={{ fontFamily: themeVars.typography.mono, color: themeVars.accent.default }}
190
+ >
191
+ {layer.stateId}
192
+ </span>
193
+ </span>
194
+ ))}
195
+ </div>
196
+ <div style={{ fontSize: 10, color: themeVars.content.dim, marginBottom: 6 }}>
197
+ Source: hand-authored XState TypeScript — inspect-only
198
+ (docs/decisions/e4-xstate-authoring-boundary.md).
199
+ </div>
200
+ <Button
201
+ size="compact"
202
+ data-testid="xstate-open-graph"
203
+ onClick={() => void openXStateGraphDocument(nodeId)}
204
+ >
205
+ Inspect Machine
206
+ </Button>
207
+ </div>
208
+ );
209
+ }
@@ -0,0 +1,248 @@
1
+ /**
2
+ * #146 — full-stack play screenshot: the game canvas(es) PLUS the DOM UI
3
+ * layers stacked over/beside them (React adapter roots,
4
+ * world layers), composited into one PNG. This is "what the game looks
5
+ * like" for agent eyes — a canvas-only capture of a game whose score/health
6
+ * lives in the HUD reads as a different (often emptier) game than the one
7
+ * the human is watching.
8
+ *
9
+ * How: each `<canvas>` child of the play container is drawn onto an
10
+ * offscreen 2D canvas at its on-screen rect (readable because every canvas
11
+ * the runtime mounts sets `preserveDrawingBuffer: true` — see
12
+ * `create-runtime.ts`), then the NON-canvas children are serialized into an
13
+ * SVG `<foreignObject>` and drawn on top. The foreignObject leg is faithful
14
+ * by construction: the HUD rule is inline-styles-only (CLAUDE.md), and
15
+ * react-world layers are engine-mounted with inline positioning — so a
16
+ * detached serialization loses no styling. The SVG rides a `data:` URL with
17
+ * no external references, which keeps the output canvas untainted (the same
18
+ * mechanism html-to-image libraries rely on).
19
+ *
20
+ * Editor chrome is deliberately OUT of scope (docs/SHARED-SESSION-SPEC.md —
21
+ * capturing it needs CDP, deferred as an opt-in niche).
22
+ */
23
+
24
+ export interface OverlaySvg {
25
+ svg: string;
26
+ /** How many non-canvas layers were serialized (0 ⇒ callers skip the leg). */
27
+ overlayCount: number;
28
+ }
29
+
30
+ /**
31
+ * Serialize the play container's NON-canvas children into a standalone SVG
32
+ * sized `width`×`height` (CSS pixels). Children are cloned into a neutral
33
+ * relatively-positioned wrapper — never the container itself, whose own
34
+ * styling comes from editor CSS classes that a detached serialization would
35
+ * silently drop. Returns null when there is nothing but canvases to show.
36
+ * Pure DOM (no rasterizing), so it's unit-testable under jsdom.
37
+ */
38
+ export function buildOverlaySvg(
39
+ container: HTMLElement,
40
+ width: number,
41
+ height: number,
42
+ ): OverlaySvg | null {
43
+ const overlays = Array.from(container.children).filter(
44
+ (el) => el.tagName.toLowerCase() !== 'canvas',
45
+ );
46
+ if (overlays.length === 0) return null;
47
+
48
+ const wrapper = container.ownerDocument.createElement('div');
49
+ wrapper.setAttribute('style', `position:relative;width:${width}px;height:${height}px;margin:0;`);
50
+ // Snapshot a stable DOM frame. CSS animations/transitions inside an SVG
51
+ // foreignObject can be rasterized while Chrome is between compositor
52
+ // layers, producing large opaque-black rectangles even though the live DOM
53
+ // is fine (reproduced by the 2048 dogfood run during a tile-pop frame).
54
+ // Disabling motion in the detached clone leaves the live game untouched
55
+ // and makes the captured evidence atomic.
56
+ const freezeMotion = container.ownerDocument.createElement('style');
57
+ freezeMotion.textContent =
58
+ '*,*::before,*::after{animation:none!important;transition:none!important;caret-color:transparent!important;' +
59
+ 'backdrop-filter:none!important;-webkit-backdrop-filter:none!important;}';
60
+ wrapper.appendChild(freezeMotion);
61
+ for (const el of overlays) {
62
+ const clone = el.cloneNode(true) as Element;
63
+ // A canvas nested INSIDE an overlay layer (react roots may render one)
64
+ // serializes as an empty box — strip it rather than ship a lying blank.
65
+ for (const nested of Array.from(clone.querySelectorAll('canvas'))) nested.remove();
66
+ wrapper.appendChild(clone);
67
+ }
68
+
69
+ const serialized = new XMLSerializer().serializeToString(wrapper);
70
+ const svg =
71
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">` +
72
+ `<foreignObject width="100%" height="100%">${serialized}</foreignObject></svg>`;
73
+ return { svg, overlayCount: overlays.length };
74
+ }
75
+
76
+ export interface CompositeCapture {
77
+ base64: string;
78
+ mimeType: 'image/png';
79
+ /** Honest capture provenance: how many canvases were drawn, and how many
80
+ * DOM layers rode the foreignObject leg. */
81
+ layers: { canvases: number; domOverlays: number };
82
+ }
83
+
84
+ /** Wait briefly for finite CSS/Web Animations to settle before serializing a
85
+ * DOM frame. Chromium can rasterize an actively animated foreignObject as
86
+ * opaque black compositor tiles; a settled frame is both more legible and
87
+ * closer to what a human sees after the interaction. Infinite ambience never
88
+ * blocks evidence capture, and the timeout keeps a broken animation from
89
+ * wedging the relay. */
90
+ export async function waitForFiniteMotion(container: HTMLElement, maxWaitMs = 350): Promise<void> {
91
+ if (typeof container.getAnimations !== 'function') return;
92
+ const animations = container.getAnimations({ subtree: true }).filter((animation) => {
93
+ const endTime = animation.effect?.getComputedTiming().endTime;
94
+ return typeof endTime === 'number' && Number.isFinite(endTime);
95
+ });
96
+ if (animations.length === 0) return;
97
+ await Promise.race([
98
+ Promise.allSettled(animations.map((animation) => animation.finished)),
99
+ new Promise<void>((resolve) => setTimeout(resolve, maxWaitMs)),
100
+ ]);
101
+ }
102
+
103
+ /** Cross two paint boundaries when the tab is rendering, but never depend on
104
+ * rAF firing: Chromium suspends it for hidden/background editor tabs, and a
105
+ * screenshot is specifically expected to work there. The timer is the
106
+ * bounded fallback, not an extra delay after a successful frame. */
107
+ export async function waitForPaint(container: HTMLElement, maxWaitMs = 75): Promise<void> {
108
+ const requestFrame = container.ownerDocument.defaultView?.requestAnimationFrame.bind(
109
+ container.ownerDocument.defaultView,
110
+ );
111
+ if (!requestFrame) return;
112
+ await new Promise<void>((resolve) => {
113
+ let settled = false;
114
+ const finish = () => {
115
+ if (settled) return;
116
+ settled = true;
117
+ clearTimeout(timeout);
118
+ resolve();
119
+ };
120
+ const timeout = setTimeout(finish, maxWaitMs);
121
+ requestFrame(() => requestFrame(finish));
122
+ });
123
+ }
124
+
125
+ /**
126
+ * Rasterize the full play container (canvases + DOM UI layers) to a PNG.
127
+ * Output is sized to the container's CSS rect — the same geometry the human
128
+ * sees. Throws on any rasterization failure; the caller
129
+ * (`handleBridgeScreenshot`) degrades to the canvas-only capture and marks
130
+ * the result honestly rather than failing the op.
131
+ */
132
+ export async function capturePlayComposite(container: HTMLElement): Promise<CompositeCapture> {
133
+ // Debug state can become observable just before React commits the matching
134
+ // DOM. Cross two paint boundaries first, then let newly-mounted finite
135
+ // transitions finish, then cross one more stable paint before cloning.
136
+ await waitForPaint(container);
137
+ // Chrome's foreignObject renderer can retain opaque-black compositor tiles
138
+ // for several frames after a React-only tree replaces an overlay (observed
139
+ // on an immediate game-over -> restart capture even after its 180ms tile
140
+ // animation reported finished). Give DOM-only roots one short compositor
141
+ // settle window; canvas-backed games do not use this fragile leg as their
142
+ // sole image and keep the faster path.
143
+ if (container.querySelectorAll('canvas').length === 0) {
144
+ await new Promise<void>((resolve) => setTimeout(resolve, 650));
145
+ }
146
+ await waitForFiniteMotion(container);
147
+ await waitForPaint(container);
148
+ return capturePlayCompositeAttempt(container, 2);
149
+ }
150
+
151
+ export function hasExcessTransparentPixels(
152
+ rgba: Uint8ClampedArray,
153
+ pixelCount: number,
154
+ limit = 0.03,
155
+ ): boolean {
156
+ if (pixelCount <= 0) return false;
157
+ let transparent = 0;
158
+ for (let alpha = 3; alpha < rgba.length; alpha += 4) {
159
+ if (rgba[alpha] === 0) transparent += 1;
160
+ }
161
+ return transparent / pixelCount > limit;
162
+ }
163
+
164
+ /** Chromium's foreignObject compositor sometimes fills a torn tile with
165
+ * fully-opaque black rather than transparency. Catch only a LARGE region of
166
+ * near-pure black; a legitimately dark game merely takes the bounded retry
167
+ * path and is still returned unchanged when it remains dark. */
168
+ export function hasExcessNearBlackPixels(
169
+ rgba: Uint8ClampedArray,
170
+ pixelCount: number,
171
+ limit = 0.08,
172
+ ): boolean {
173
+ if (pixelCount <= 0) return false;
174
+ let black = 0;
175
+ for (let offset = 0; offset < rgba.length; offset += 4) {
176
+ if (
177
+ rgba[offset]! <= 8 &&
178
+ rgba[offset + 1]! <= 8 &&
179
+ rgba[offset + 2]! <= 8 &&
180
+ rgba[offset + 3]! >= 250
181
+ ) {
182
+ black += 1;
183
+ }
184
+ }
185
+ return black / pixelCount > limit;
186
+ }
187
+
188
+ async function capturePlayCompositeAttempt(
189
+ container: HTMLElement,
190
+ retriesRemaining: number,
191
+ ): Promise<CompositeCapture> {
192
+ const rect = container.getBoundingClientRect();
193
+ const width = Math.max(1, Math.round(rect.width));
194
+ const height = Math.max(1, Math.round(rect.height));
195
+
196
+ const out = container.ownerDocument.createElement('canvas');
197
+ out.width = width;
198
+ out.height = height;
199
+ const ctx2d = out.getContext('2d');
200
+ if (!ctx2d) throw new Error('composite screenshot: no 2d canvas context');
201
+
202
+ const canvases = Array.from(container.querySelectorAll('canvas'));
203
+ for (const c of canvases) {
204
+ const r = c.getBoundingClientRect();
205
+ ctx2d.drawImage(c, r.left - rect.left, r.top - rect.top, r.width, r.height);
206
+ }
207
+
208
+ let domOverlays = 0;
209
+ const overlay = buildOverlaySvg(container, width, height);
210
+ if (overlay) {
211
+ const img = new Image();
212
+ img.src = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(overlay.svg)}`;
213
+ await img.decode();
214
+ ctx2d.drawImage(img, 0, 0, width, height);
215
+ domOverlays = overlay.overlayCount;
216
+ }
217
+
218
+ // A Chromium foreignObject can occasionally decode while React is between
219
+ // compositor frames, leaving large transparent rectangles in an otherwise
220
+ // opaque React-only game. Those pixels show up as black in the PNG. Detect
221
+ // that lying frame and retry after a real paint; rounded-corner edge pixels
222
+ // stay far below the 3% threshold. Canvas-backed games already have their
223
+ // canvas underneath, so this retry is specific to DOM-only captures.
224
+ if (canvases.length === 0 && domOverlays > 0 && retriesRemaining > 0) {
225
+ try {
226
+ const pixels = ctx2d.getImageData(0, 0, width, height);
227
+ if (
228
+ hasExcessTransparentPixels(pixels.data, width * height) ||
229
+ hasExcessNearBlackPixels(pixels.data, width * height)
230
+ ) {
231
+ await new Promise<void>((resolve) => setTimeout(resolve, 300));
232
+ await waitForPaint(container);
233
+ return capturePlayCompositeAttempt(container, retriesRemaining - 1);
234
+ }
235
+ } catch {
236
+ // If readback is unavailable, preserve the existing honest capture or
237
+ // let toDataURL surface the underlying taint below.
238
+ }
239
+ }
240
+
241
+ const dataUrl = out.toDataURL('image/png');
242
+ const comma = dataUrl.indexOf(',');
243
+ return {
244
+ base64: comma >= 0 ? dataUrl.slice(comma + 1) : dataUrl,
245
+ mimeType: 'image/png',
246
+ layers: { canvases: canvases.length, domOverlays },
247
+ };
248
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * The single internal editor design-system boundary.
3
+ *
4
+ * Product surfaces import from this module. Theme definitions, CSS recipes,
5
+ * primitives, and recurring patterns remain implementation details below it.
6
+ * Project-authored tools receive the same surface through `@editor/widgets`.
7
+ */
8
+
9
+ export * from '../components/patterns/Dialog';
10
+ export * from '../components/patterns/Fields';
11
+ export * from '../components/patterns/List';
12
+ export * from '../components/patterns/StateSurface';
13
+ export * from '../components/patterns/Surfaces';
14
+ export * from '../components/patterns/Tabs';
15
+ export * from '../components/patterns/Toolbar';
16
+ export * from '../components/patterns/Tree';
17
+ export * from '../components/primitives/Button';
18
+ export * from '../components/primitives/banner-tones';
19
+ export * from '../components/primitives/ColorInput';
20
+ export * from '../components/primitives/EditorIcon';
21
+ export { editorIcons } from '../components/primitives/editor-icons';
22
+ export * from '../components/primitives/FormControls';
23
+ export * from '../components/primitives/JsonInput';
24
+ export * from '../components/primitives/Layout';
25
+ export * from '../components/primitives/Menu';
26
+ export * from '../components/primitives/NumberInput';
27
+ export * from '../components/primitives/Panel';
28
+ export * from '../components/primitives/SectionHeader';
29
+ export * from '../components/primitives/Text';
30
+ export * from '../components/primitives/Tooltip';
31
+ export * from '../components/primitives/Vec3Input';
32
+
33
+ // Product surfaces consume runtime theme references through this boundary as
34
+ // they migrate away from direct `theme.ts` imports. Keeping the references
35
+ // here preserves custom-theme behavior without exposing design-system internals.
36
+ export {
37
+ accent,
38
+ accentMuted,
39
+ bg,
40
+ border,
41
+ chromeSize,
42
+ controlSize,
43
+ danger,
44
+ dangerFaint,
45
+ dangerMuted,
46
+ EDITOR_THEME_CLASS,
47
+ type EditorTheme,
48
+ type EditorThemeId,
49
+ type EditorThemeVariable,
50
+ editorThemes,
51
+ editorThemeVariables,
52
+ fontMono,
53
+ fontSans,
54
+ fontSize,
55
+ fontWeight,
56
+ graphiteDarkEditorTheme,
57
+ midnightHighContrastEditorTheme,
58
+ radius,
59
+ scrim,
60
+ shadow,
61
+ space,
62
+ strokeWidth,
63
+ success,
64
+ successMuted,
65
+ text,
66
+ themeVars,
67
+ warn,
68
+ warnMuted,
69
+ } from '../theme';
70
+ export { zIndex } from '../z-index';