@forgeax/view 0.5.0-dev.13604.c415409c3b9d → 0.5.0-dev.13713.d28c4863d779

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 (280) hide show
  1. package/README.md +67 -9
  2. package/dist/build-revision.json +1 -1
  3. package/dist/modules/backend.mjs +34 -34
  4. package/dist/modules/browser.mjs +55 -49
  5. package/dist/modules/chunks/{chunk-EWSCJF77.mjs → chunk-2CMCY54A.mjs} +2 -2
  6. package/dist/modules/chunks/{chunk-M6S5YA6X.mjs → chunk-2RUKPDIE.mjs} +4 -4
  7. package/dist/modules/chunks/{chunk-M6S5YA6X.mjs.map → chunk-2RUKPDIE.mjs.map} +1 -1
  8. package/dist/modules/chunks/{chunk-DWT3TA6M.mjs → chunk-3FBX3P3H.mjs} +9 -8
  9. package/dist/modules/chunks/chunk-3FBX3P3H.mjs.map +7 -0
  10. package/dist/modules/chunks/{chunk-6KM24NH6.mjs → chunk-3Y5WN22T.mjs} +3 -3
  11. package/dist/modules/chunks/chunk-3Y5WN22T.mjs.map +7 -0
  12. package/dist/modules/chunks/{chunk-YFQGSDK3.mjs → chunk-45WL24XN.mjs} +2 -2
  13. package/dist/modules/chunks/{chunk-FMCHH5R4.mjs → chunk-4FYKRL46.mjs} +3 -3
  14. package/dist/modules/chunks/{chunk-VW2ZF3P4.mjs → chunk-4MJHVZMB.mjs} +6 -6
  15. package/dist/modules/chunks/{chunk-XQYF2P6M.mjs → chunk-5HVXQEO3.mjs} +7 -7
  16. package/dist/modules/chunks/{chunk-XMP4THLF.mjs → chunk-66LM6NO6.mjs} +4 -4
  17. package/dist/modules/chunks/{chunk-P4UPH74B.mjs → chunk-6C4OCCYB.mjs} +12 -12
  18. package/dist/modules/chunks/{chunk-P4UPH74B.mjs.map → chunk-6C4OCCYB.mjs.map} +1 -1
  19. package/dist/modules/chunks/{chunk-ZGOGO7SS.mjs → chunk-6J27SWMY.mjs} +1 -1
  20. package/dist/modules/chunks/{chunk-JK7K7RG3.mjs → chunk-6VK7HB4X.mjs} +4 -4
  21. package/dist/modules/chunks/{chunk-HRKW766Y.mjs → chunk-6WZZ7TIC.mjs} +2 -2
  22. package/dist/modules/chunks/{chunk-FICPCJKR.mjs → chunk-7DFCIN3T.mjs} +3 -3
  23. package/dist/modules/chunks/{chunk-FICPCJKR.mjs.map → chunk-7DFCIN3T.mjs.map} +1 -1
  24. package/dist/modules/chunks/{chunk-U64FRQKP.mjs → chunk-7MWZK7HS.mjs} +3 -3
  25. package/dist/modules/chunks/{chunk-F5RLQAPN.mjs → chunk-A7OGXJAV.mjs} +3 -3
  26. package/dist/modules/chunks/{chunk-QUFVUMSY.mjs → chunk-AUINYWZP.mjs} +2 -2
  27. package/dist/modules/chunks/{chunk-PZIAKZJC.mjs → chunk-B24VYGHV.mjs} +3 -3
  28. package/dist/modules/chunks/{chunk-SRYQLFBV.mjs → chunk-BIUWJROZ.mjs} +3 -3
  29. package/dist/modules/chunks/{chunk-SRYQLFBV.mjs.map → chunk-BIUWJROZ.mjs.map} +2 -2
  30. package/dist/modules/chunks/{chunk-X4NNZ5X6.mjs → chunk-C2AMOM7H.mjs} +3 -3
  31. package/dist/modules/chunks/{chunk-IZAHIOFU.mjs → chunk-C3WVSJZF.mjs} +6 -6
  32. package/dist/modules/chunks/{chunk-2Z5KEV6L.mjs → chunk-CAXCOZ7Y.mjs} +3 -3
  33. package/dist/modules/chunks/{chunk-HWZCLROY.mjs → chunk-CN6YN4HP.mjs} +251 -45
  34. package/dist/modules/chunks/chunk-CN6YN4HP.mjs.map +7 -0
  35. package/dist/modules/chunks/{chunk-B6QUJ33G.mjs → chunk-CXFQME65.mjs} +3 -3
  36. package/dist/modules/chunks/{chunk-IJPWKKIU.mjs → chunk-CYOLEAAY.mjs} +14 -13
  37. package/dist/modules/chunks/chunk-CYOLEAAY.mjs.map +7 -0
  38. package/dist/modules/chunks/{chunk-U6UMATPV.mjs → chunk-CYU3WWN6.mjs} +3 -3
  39. package/dist/modules/chunks/{chunk-AGVLPYVE.mjs → chunk-D2LZIQE2.mjs} +2 -2
  40. package/dist/modules/chunks/{chunk-5YTMN435.mjs → chunk-DC5JP46Y.mjs} +13 -3
  41. package/dist/modules/chunks/chunk-DC5JP46Y.mjs.map +7 -0
  42. package/dist/modules/chunks/{chunk-YNHEYXDG.mjs → chunk-DOU4MNMQ.mjs} +3 -3
  43. package/dist/modules/chunks/{chunk-ZIDEETK4.mjs → chunk-E4G4HDOC.mjs} +3 -3
  44. package/dist/modules/chunks/{chunk-ZHO2G4JR.mjs → chunk-EZAJ66NW.mjs} +3 -3
  45. package/dist/modules/chunks/{chunk-APD2EWSZ.mjs → chunk-FIWL6TQS.mjs} +2 -2
  46. package/dist/modules/chunks/{chunk-U5J7OTEB.mjs → chunk-FSSARTVM.mjs} +3 -3
  47. package/dist/modules/chunks/{chunk-47RJSHLM.mjs → chunk-FXXPWAXM.mjs} +3 -3
  48. package/dist/modules/chunks/{chunk-D2RCKG7Q.mjs → chunk-G2QCXN56.mjs} +6 -6
  49. package/dist/modules/chunks/{chunk-4T3D67CS.mjs → chunk-GRDCA6LD.mjs} +8 -8
  50. package/dist/modules/chunks/{chunk-4T3D67CS.mjs.map → chunk-GRDCA6LD.mjs.map} +1 -1
  51. package/dist/modules/chunks/{chunk-WVU3CQ62.mjs → chunk-GUVUL6D2.mjs} +3 -3
  52. package/dist/modules/chunks/{chunk-YLCJNKIW.mjs → chunk-I32EONBF.mjs} +70 -30
  53. package/dist/modules/chunks/chunk-I32EONBF.mjs.map +7 -0
  54. package/dist/modules/chunks/{chunk-E3PJGTLI.mjs → chunk-IGIELQZ2.mjs} +5 -5
  55. package/dist/modules/chunks/{chunk-5PHAXNFO.mjs → chunk-IMDR26Y3.mjs} +3 -3
  56. package/dist/modules/chunks/{chunk-55F55BQY.mjs → chunk-JVOHFCI4.mjs} +3 -3
  57. package/dist/modules/chunks/{chunk-6I7RY73G.mjs → chunk-KCM7ZCQ3.mjs} +5 -5
  58. package/dist/modules/chunks/chunk-KCM7ZCQ3.mjs.map +7 -0
  59. package/dist/modules/chunks/{chunk-K2QZRFLE.mjs → chunk-KJTMDFFX.mjs} +4 -4
  60. package/dist/modules/chunks/{chunk-KX2WU5Z6.mjs → chunk-KPLESRQY.mjs} +3 -3
  61. package/dist/modules/chunks/{chunk-PW5CE2Y6.mjs → chunk-KUOWDTI6.mjs} +2 -2
  62. package/dist/modules/chunks/chunk-L6IHUN7X.mjs +13 -0
  63. package/dist/modules/chunks/chunk-L6IHUN7X.mjs.map +7 -0
  64. package/dist/modules/chunks/{chunk-INTTYJVW.mjs → chunk-LBQ6DFMP.mjs} +2 -2
  65. package/dist/modules/chunks/{chunk-OKQ5RBKO.mjs → chunk-LVWHM3UN.mjs} +2 -2
  66. package/dist/modules/chunks/{chunk-D57DDEV2.mjs → chunk-MDQMARAN.mjs} +6 -6
  67. package/dist/modules/chunks/{chunk-D57DDEV2.mjs.map → chunk-MDQMARAN.mjs.map} +2 -2
  68. package/dist/modules/chunks/{chunk-STQPRNEO.mjs → chunk-MLXRIWJA.mjs} +2 -2
  69. package/dist/modules/chunks/{chunk-D25SR5FS.mjs → chunk-N2SH3JGI.mjs} +3 -3
  70. package/dist/modules/chunks/{chunk-KI4WGTWL.mjs → chunk-N7NXZ6R3.mjs} +4 -4
  71. package/dist/modules/chunks/{chunk-KI4WGTWL.mjs.map → chunk-N7NXZ6R3.mjs.map} +2 -2
  72. package/dist/modules/chunks/{chunk-7IGFAI5H.mjs → chunk-O5QX6H3U.mjs} +5 -5
  73. package/dist/modules/chunks/{chunk-5W7SC5D4.mjs → chunk-P2Y73QJJ.mjs} +11 -1
  74. package/dist/modules/chunks/{chunk-5W7SC5D4.mjs.map → chunk-P2Y73QJJ.mjs.map} +2 -2
  75. package/dist/modules/chunks/{chunk-FNRGLCZW.mjs → chunk-PCQNUFDL.mjs} +39 -13
  76. package/dist/modules/chunks/chunk-PCQNUFDL.mjs.map +7 -0
  77. package/dist/modules/chunks/{chunk-46UEGAXY.mjs → chunk-Q7M7VUOZ.mjs} +6 -6
  78. package/dist/modules/chunks/{chunk-XE6ITXHT.mjs → chunk-QB33CMEU.mjs} +2 -2
  79. package/dist/modules/chunks/{chunk-E3Z7GLFU.mjs → chunk-QJHQN6OD.mjs} +15 -4
  80. package/dist/modules/chunks/chunk-QJHQN6OD.mjs.map +7 -0
  81. package/dist/modules/chunks/{chunk-KAGFU64Y.mjs → chunk-QW2VT3XB.mjs} +2 -2
  82. package/dist/modules/chunks/{chunk-U5R6MVM4.mjs → chunk-RFTLGEB5.mjs} +2 -2
  83. package/dist/modules/chunks/{chunk-VKNIYV2W.mjs → chunk-RYYKMDNI.mjs} +202 -35
  84. package/dist/modules/chunks/chunk-RYYKMDNI.mjs.map +7 -0
  85. package/dist/modules/chunks/{chunk-P5XMFZY4.mjs → chunk-SFB5BDTB.mjs} +2 -2
  86. package/dist/modules/chunks/{chunk-4D3Q7K44.mjs → chunk-SNICHQJP.mjs} +2 -2
  87. package/dist/modules/chunks/{chunk-CX5WREJC.mjs → chunk-SPGFO2TA.mjs} +2 -2
  88. package/dist/modules/chunks/{chunk-H256DQT6.mjs → chunk-TMPTVIAP.mjs} +2 -2
  89. package/dist/modules/chunks/{chunk-OQXDADAS.mjs → chunk-UWJYROKS.mjs} +6 -6
  90. package/dist/modules/chunks/chunk-UWJYROKS.mjs.map +7 -0
  91. package/dist/modules/chunks/{chunk-TTRUYO7Q.mjs → chunk-UZH2664E.mjs} +3 -3
  92. package/dist/modules/chunks/{chunk-TTRUYO7Q.mjs.map → chunk-UZH2664E.mjs.map} +2 -2
  93. package/dist/modules/chunks/{chunk-CKYXAT7H.mjs → chunk-VC4OEPDH.mjs} +2 -2
  94. package/dist/modules/chunks/{chunk-RJVOH7G2.mjs → chunk-VKWEA6NG.mjs} +27 -27
  95. package/dist/modules/chunks/{chunk-LZ57Y73Z.mjs → chunk-VSJOW7J4.mjs} +9 -7
  96. package/dist/modules/chunks/chunk-VSJOW7J4.mjs.map +7 -0
  97. package/dist/modules/chunks/{chunk-PVP5YBNR.mjs → chunk-WFM434WJ.mjs} +2 -2
  98. package/dist/modules/chunks/{chunk-TXLD7JI5.mjs → chunk-WJNASQF2.mjs} +2 -2
  99. package/dist/modules/chunks/{chunk-357UOBAS.mjs → chunk-XUNDH3E7.mjs} +2 -2
  100. package/dist/modules/chunks/{chunk-PJFFCRRD.mjs → chunk-YDARD4EP.mjs} +2 -2
  101. package/dist/modules/chunks/{chunk-27XASYEH.mjs → chunk-YU3HRQX7.mjs} +17 -11
  102. package/dist/modules/chunks/chunk-YU3HRQX7.mjs.map +7 -0
  103. package/dist/modules/chunks/{chunk-EZSGDSCC.mjs → chunk-ZRE7BDDB.mjs} +30 -5
  104. package/dist/modules/chunks/chunk-ZRE7BDDB.mjs.map +7 -0
  105. package/dist/modules/cli-contributions.mjs +14 -14
  106. package/dist/modules/cli.mjs +5 -5
  107. package/dist/modules/command-executor.mjs +3 -3
  108. package/dist/modules/embedded.mjs +82 -42
  109. package/dist/modules/embedded.mjs.map +2 -2
  110. package/dist/modules/extension-bridge.mjs +4 -4
  111. package/dist/modules/frontend-root.mjs +46 -46
  112. package/dist/modules/index.mjs +71 -65
  113. package/dist/modules/index.mjs.map +1 -1
  114. package/dist/modules/pages/scene.mjs +5 -5
  115. package/dist/modules/plugin.mjs +35 -35
  116. package/dist/modules/plugins/asset/frontend.mjs +10 -10
  117. package/dist/modules/plugins/asset/identity.mjs +9 -9
  118. package/dist/modules/plugins/asset/ui.mjs +3 -3
  119. package/dist/modules/plugins/content-browser/frontend.mjs +3 -3
  120. package/dist/modules/plugins/content-browser/identity.mjs +2 -2
  121. package/dist/modules/plugins/content-browser/ui.mjs +3 -3
  122. package/dist/modules/plugins/display/api.mjs +1 -1
  123. package/dist/modules/plugins/display/backend.mjs +4 -4
  124. package/dist/modules/plugins/display/frontend.mjs +5 -5
  125. package/dist/modules/plugins/display/identity.mjs +2 -2
  126. package/dist/modules/plugins/display/ui.mjs +3 -3
  127. package/dist/modules/plugins/inspector/frontend.mjs +3 -3
  128. package/dist/modules/plugins/inspector/identity.mjs +2 -2
  129. package/dist/modules/plugins/inspector/ui.mjs +3 -3
  130. package/dist/modules/plugins/material/frontend.mjs +10 -10
  131. package/dist/modules/plugins/material/identity.mjs +9 -9
  132. package/dist/modules/plugins/material/ui.mjs +10 -10
  133. package/dist/modules/plugins/mesh/frontend.mjs +10 -10
  134. package/dist/modules/plugins/mesh/identity.mjs +9 -9
  135. package/dist/modules/plugins/mesh/ui.mjs +10 -10
  136. package/dist/modules/plugins/plugins/api.mjs +4 -4
  137. package/dist/modules/plugins/plugins/backend.mjs +7 -7
  138. package/dist/modules/plugins/plugins/cli.mjs +5 -5
  139. package/dist/modules/plugins/plugins/frontend.mjs +3 -3
  140. package/dist/modules/plugins/plugins/identity.mjs +2 -2
  141. package/dist/modules/plugins/plugins/runtime.mjs +6 -6
  142. package/dist/modules/plugins/plugins/ui/panel.mjs +3 -3
  143. package/dist/modules/plugins/plugins/ui.mjs +4 -4
  144. package/dist/modules/plugins/scene/frontend.mjs +5 -5
  145. package/dist/modules/plugins/scene/identity.mjs +2 -2
  146. package/dist/modules/plugins/scene-tree/frontend.mjs +3 -3
  147. package/dist/modules/plugins/scene-tree/identity.mjs +2 -2
  148. package/dist/modules/plugins/scene-tree/ui.mjs +3 -3
  149. package/dist/modules/plugins/texture/frontend.mjs +10 -10
  150. package/dist/modules/plugins/texture/identity.mjs +9 -9
  151. package/dist/modules/plugins/texture/ui.mjs +10 -10
  152. package/dist/modules/plugins/viewport/frontend.mjs +12 -12
  153. package/dist/modules/plugins/viewport/identity.mjs +2 -2
  154. package/dist/modules/plugins/viewport/presentation.mjs +4 -4
  155. package/dist/modules/plugins/viewport/schema.mjs +2 -2
  156. package/dist/modules/plugins/viewport/workspace-shell.mjs +9 -9
  157. package/dist/modules/product.mjs +35 -35
  158. package/dist/modules/shell/frontend.mjs +1 -1
  159. package/dist/modules/viewer/catalog/backend.mjs +31 -31
  160. package/dist/modules/viewer/catalog/frontend.mjs +42 -42
  161. package/dist/modules/viewer/catalog/shared.mjs +20 -20
  162. package/dist/modules/viewer/catalog.mjs +51 -51
  163. package/dist/modules/viewer/cli.mjs +10 -10
  164. package/dist/modules/viewer-host/frontend.mjs +48 -48
  165. package/dist/modules/viewer-host/page-registry.mjs +6 -6
  166. package/dist/modules/viewer-host.mjs +7 -7
  167. package/dist/modules/viewer.mjs +51 -51
  168. package/dist/modules/workspace/api.mjs +1 -1
  169. package/dist/modules/workspace/backend.mjs +10 -10
  170. package/dist/modules/workspace/broker.mjs +9 -9
  171. package/dist/modules/workspace/cli.mjs +2 -2
  172. package/dist/modules/workspace/client.mjs +3 -3
  173. package/dist/modules/workspace/command-error.mjs +2 -2
  174. package/dist/modules/workspace/contract.mjs +7 -1
  175. package/dist/modules/workspace/engine-adapter.mjs +3 -3
  176. package/dist/modules/workspace/extension-bridge.mjs +4 -4
  177. package/dist/modules/workspace/frontend-plugin.mjs +8 -8
  178. package/dist/modules/workspace/frontend.mjs +9 -9
  179. package/dist/modules/workspace/page-title.mjs +3 -3
  180. package/dist/modules/workspace/presentation.mjs +4 -4
  181. package/dist/modules/workspace/preview-surface.mjs +7 -7
  182. package/dist/modules/workspace/project-session.mjs +2 -2
  183. package/dist/modules/workspace/render-resize-sync.mjs +2 -2
  184. package/dist/modules/workspace/resident.mjs +4 -4
  185. package/dist/modules/workspace/resource-open.mjs +5 -5
  186. package/dist/modules/workspace/resource-page.mjs +8 -8
  187. package/dist/modules/workspace/tool-runtime.mjs +7 -5
  188. package/dist/modules/workspace/view-trace.mjs +3 -3
  189. package/dist/modules/workspace/workspace-recovery.mjs +4 -4
  190. package/dist/modules/workspace/workspace-state.mjs +2 -2
  191. package/dist/modules/workspace-frontend.mjs +8 -8
  192. package/dist/viewer/assets/{embedded-DXSSFAyM.js → embedded-BKEAtUD6.js} +2 -2
  193. package/dist/viewer/assets/{embedded-DXSSFAyM.js.map → embedded-BKEAtUD6.js.map} +1 -1
  194. package/dist/viewer/assets/main-BQrn6wsa.js +22 -0
  195. package/dist/viewer/assets/main-BQrn6wsa.js.map +1 -0
  196. package/dist/viewer/assets/{panels-lazy-DqCwhGd9.js → panels-lazy-C_Cs-76A.js} +2 -2
  197. package/dist/viewer/assets/{panels-lazy-DqCwhGd9.js.map → panels-lazy-C_Cs-76A.js.map} +1 -1
  198. package/dist/viewer/assets/panels-ui-DEDHJLuE.js +12 -0
  199. package/dist/viewer/assets/panels-ui-DEDHJLuE.js.map +1 -0
  200. package/dist/viewer/assets/style-CcYzhsIZ.css +2 -0
  201. package/dist/viewer/assets/{wgpu_wasm--oeqTwVY.js → wgpu_wasm-cNR5izZM.js} +126 -0
  202. package/dist/viewer/assets/{wgpu_wasm_bg-WoZ1YI1I.wasm → wgpu_wasm_bg-Dps0jNcQ.wasm} +0 -0
  203. package/dist/viewer/index.html +4 -4
  204. package/dist/viewer/panels.js +1 -1
  205. package/package.json +2 -2
  206. package/scripts/verify-runtime-content-engine.mjs +7 -4
  207. package/skills/forgeax-view-cli/SKILL.md +11 -0
  208. package/dist/modules/chunks/chunk-27XASYEH.mjs.map +0 -7
  209. package/dist/modules/chunks/chunk-5YTMN435.mjs.map +0 -7
  210. package/dist/modules/chunks/chunk-6I7RY73G.mjs.map +0 -7
  211. package/dist/modules/chunks/chunk-6KM24NH6.mjs.map +0 -7
  212. package/dist/modules/chunks/chunk-DWT3TA6M.mjs.map +0 -7
  213. package/dist/modules/chunks/chunk-E3Z7GLFU.mjs.map +0 -7
  214. package/dist/modules/chunks/chunk-EZSGDSCC.mjs.map +0 -7
  215. package/dist/modules/chunks/chunk-FNRGLCZW.mjs.map +0 -7
  216. package/dist/modules/chunks/chunk-HWZCLROY.mjs.map +0 -7
  217. package/dist/modules/chunks/chunk-IJPWKKIU.mjs.map +0 -7
  218. package/dist/modules/chunks/chunk-LZ57Y73Z.mjs.map +0 -7
  219. package/dist/modules/chunks/chunk-OQXDADAS.mjs.map +0 -7
  220. package/dist/modules/chunks/chunk-QELNKFSI.mjs +0 -10
  221. package/dist/modules/chunks/chunk-QELNKFSI.mjs.map +0 -7
  222. package/dist/modules/chunks/chunk-VKNIYV2W.mjs.map +0 -7
  223. package/dist/modules/chunks/chunk-YLCJNKIW.mjs.map +0 -7
  224. package/dist/viewer/assets/main-CI6ZQziX.js +0 -22
  225. package/dist/viewer/assets/main-CI6ZQziX.js.map +0 -1
  226. package/dist/viewer/assets/panels-ui-CfUtl68h.js +0 -12
  227. package/dist/viewer/assets/panels-ui-CfUtl68h.js.map +0 -1
  228. package/dist/viewer/assets/style-gOtSMZif.css +0 -2
  229. /package/dist/modules/chunks/{chunk-EWSCJF77.mjs.map → chunk-2CMCY54A.mjs.map} +0 -0
  230. /package/dist/modules/chunks/{chunk-YFQGSDK3.mjs.map → chunk-45WL24XN.mjs.map} +0 -0
  231. /package/dist/modules/chunks/{chunk-FMCHH5R4.mjs.map → chunk-4FYKRL46.mjs.map} +0 -0
  232. /package/dist/modules/chunks/{chunk-VW2ZF3P4.mjs.map → chunk-4MJHVZMB.mjs.map} +0 -0
  233. /package/dist/modules/chunks/{chunk-XQYF2P6M.mjs.map → chunk-5HVXQEO3.mjs.map} +0 -0
  234. /package/dist/modules/chunks/{chunk-XMP4THLF.mjs.map → chunk-66LM6NO6.mjs.map} +0 -0
  235. /package/dist/modules/chunks/{chunk-ZGOGO7SS.mjs.map → chunk-6J27SWMY.mjs.map} +0 -0
  236. /package/dist/modules/chunks/{chunk-JK7K7RG3.mjs.map → chunk-6VK7HB4X.mjs.map} +0 -0
  237. /package/dist/modules/chunks/{chunk-HRKW766Y.mjs.map → chunk-6WZZ7TIC.mjs.map} +0 -0
  238. /package/dist/modules/chunks/{chunk-U64FRQKP.mjs.map → chunk-7MWZK7HS.mjs.map} +0 -0
  239. /package/dist/modules/chunks/{chunk-F5RLQAPN.mjs.map → chunk-A7OGXJAV.mjs.map} +0 -0
  240. /package/dist/modules/chunks/{chunk-QUFVUMSY.mjs.map → chunk-AUINYWZP.mjs.map} +0 -0
  241. /package/dist/modules/chunks/{chunk-PZIAKZJC.mjs.map → chunk-B24VYGHV.mjs.map} +0 -0
  242. /package/dist/modules/chunks/{chunk-X4NNZ5X6.mjs.map → chunk-C2AMOM7H.mjs.map} +0 -0
  243. /package/dist/modules/chunks/{chunk-IZAHIOFU.mjs.map → chunk-C3WVSJZF.mjs.map} +0 -0
  244. /package/dist/modules/chunks/{chunk-2Z5KEV6L.mjs.map → chunk-CAXCOZ7Y.mjs.map} +0 -0
  245. /package/dist/modules/chunks/{chunk-B6QUJ33G.mjs.map → chunk-CXFQME65.mjs.map} +0 -0
  246. /package/dist/modules/chunks/{chunk-U6UMATPV.mjs.map → chunk-CYU3WWN6.mjs.map} +0 -0
  247. /package/dist/modules/chunks/{chunk-AGVLPYVE.mjs.map → chunk-D2LZIQE2.mjs.map} +0 -0
  248. /package/dist/modules/chunks/{chunk-YNHEYXDG.mjs.map → chunk-DOU4MNMQ.mjs.map} +0 -0
  249. /package/dist/modules/chunks/{chunk-ZIDEETK4.mjs.map → chunk-E4G4HDOC.mjs.map} +0 -0
  250. /package/dist/modules/chunks/{chunk-ZHO2G4JR.mjs.map → chunk-EZAJ66NW.mjs.map} +0 -0
  251. /package/dist/modules/chunks/{chunk-APD2EWSZ.mjs.map → chunk-FIWL6TQS.mjs.map} +0 -0
  252. /package/dist/modules/chunks/{chunk-U5J7OTEB.mjs.map → chunk-FSSARTVM.mjs.map} +0 -0
  253. /package/dist/modules/chunks/{chunk-47RJSHLM.mjs.map → chunk-FXXPWAXM.mjs.map} +0 -0
  254. /package/dist/modules/chunks/{chunk-D2RCKG7Q.mjs.map → chunk-G2QCXN56.mjs.map} +0 -0
  255. /package/dist/modules/chunks/{chunk-WVU3CQ62.mjs.map → chunk-GUVUL6D2.mjs.map} +0 -0
  256. /package/dist/modules/chunks/{chunk-E3PJGTLI.mjs.map → chunk-IGIELQZ2.mjs.map} +0 -0
  257. /package/dist/modules/chunks/{chunk-5PHAXNFO.mjs.map → chunk-IMDR26Y3.mjs.map} +0 -0
  258. /package/dist/modules/chunks/{chunk-55F55BQY.mjs.map → chunk-JVOHFCI4.mjs.map} +0 -0
  259. /package/dist/modules/chunks/{chunk-K2QZRFLE.mjs.map → chunk-KJTMDFFX.mjs.map} +0 -0
  260. /package/dist/modules/chunks/{chunk-KX2WU5Z6.mjs.map → chunk-KPLESRQY.mjs.map} +0 -0
  261. /package/dist/modules/chunks/{chunk-PW5CE2Y6.mjs.map → chunk-KUOWDTI6.mjs.map} +0 -0
  262. /package/dist/modules/chunks/{chunk-INTTYJVW.mjs.map → chunk-LBQ6DFMP.mjs.map} +0 -0
  263. /package/dist/modules/chunks/{chunk-OKQ5RBKO.mjs.map → chunk-LVWHM3UN.mjs.map} +0 -0
  264. /package/dist/modules/chunks/{chunk-STQPRNEO.mjs.map → chunk-MLXRIWJA.mjs.map} +0 -0
  265. /package/dist/modules/chunks/{chunk-D25SR5FS.mjs.map → chunk-N2SH3JGI.mjs.map} +0 -0
  266. /package/dist/modules/chunks/{chunk-7IGFAI5H.mjs.map → chunk-O5QX6H3U.mjs.map} +0 -0
  267. /package/dist/modules/chunks/{chunk-46UEGAXY.mjs.map → chunk-Q7M7VUOZ.mjs.map} +0 -0
  268. /package/dist/modules/chunks/{chunk-XE6ITXHT.mjs.map → chunk-QB33CMEU.mjs.map} +0 -0
  269. /package/dist/modules/chunks/{chunk-KAGFU64Y.mjs.map → chunk-QW2VT3XB.mjs.map} +0 -0
  270. /package/dist/modules/chunks/{chunk-U5R6MVM4.mjs.map → chunk-RFTLGEB5.mjs.map} +0 -0
  271. /package/dist/modules/chunks/{chunk-P5XMFZY4.mjs.map → chunk-SFB5BDTB.mjs.map} +0 -0
  272. /package/dist/modules/chunks/{chunk-4D3Q7K44.mjs.map → chunk-SNICHQJP.mjs.map} +0 -0
  273. /package/dist/modules/chunks/{chunk-CX5WREJC.mjs.map → chunk-SPGFO2TA.mjs.map} +0 -0
  274. /package/dist/modules/chunks/{chunk-H256DQT6.mjs.map → chunk-TMPTVIAP.mjs.map} +0 -0
  275. /package/dist/modules/chunks/{chunk-CKYXAT7H.mjs.map → chunk-VC4OEPDH.mjs.map} +0 -0
  276. /package/dist/modules/chunks/{chunk-RJVOH7G2.mjs.map → chunk-VKWEA6NG.mjs.map} +0 -0
  277. /package/dist/modules/chunks/{chunk-PVP5YBNR.mjs.map → chunk-WFM434WJ.mjs.map} +0 -0
  278. /package/dist/modules/chunks/{chunk-TXLD7JI5.mjs.map → chunk-WJNASQF2.mjs.map} +0 -0
  279. /package/dist/modules/chunks/{chunk-357UOBAS.mjs.map → chunk-XUNDH3E7.mjs.map} +0 -0
  280. /package/dist/modules/chunks/{chunk-PJFFCRRD.mjs.map → chunk-YDARD4EP.mjs.map} +0 -0
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  reopenWorkspaceProject
3
- } from "./chunk-K2QZRFLE.mjs";
3
+ } from "./chunk-KJTMDFFX.mjs";
4
4
  import {
5
5
  PAGE_TYPE
6
- } from "./chunk-H256DQT6.mjs";
6
+ } from "./chunk-TMPTVIAP.mjs";
7
7
  import {
8
8
  borrowSurface,
9
9
  keepSurfaceInContainer,
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-QW3ZY2AD.mjs";
12
12
  import {
13
13
  selectWorkspaceEditorSurfaceTarget
14
- } from "./chunk-ZIDEETK4.mjs";
14
+ } from "./chunk-E4G4HDOC.mjs";
15
15
  import {
16
16
  isViewTraceEnabled,
17
17
  traceInputAttach,
@@ -26,18 +26,18 @@ import {
26
26
  traceShellUpdate,
27
27
  traceSyncTargetSurfaces,
28
28
  traceView
29
- } from "./chunk-KAGFU64Y.mjs";
29
+ } from "./chunk-QW2VT3XB.mjs";
30
30
  import {
31
31
  reportWorkspaceCommandError,
32
32
  workspaceDiagnosticRecord
33
- } from "./chunk-U5R6MVM4.mjs";
33
+ } from "./chunk-RFTLGEB5.mjs";
34
34
  import {
35
35
  VIEW_DISPLAY_TAB_ID,
36
36
  VIEW_WORKSPACE_TAB_ID,
37
37
  cloneWorkspaceValue,
38
38
  requireWorkspaceString,
39
39
  workspaceUiFingerprint
40
- } from "./chunk-E3Z7GLFU.mjs";
40
+ } from "./chunk-QJHQN6OD.mjs";
41
41
  import {
42
42
  createWorkspaceId
43
43
  } from "./chunk-4XEXLHX4.mjs";
@@ -910,7 +910,7 @@ var ViewWorkspaceShell = class {
910
910
  try {
911
911
  const call = mode === "cold-cook" ? this.api.coldCookAssetSource : this.api.rebuildAssetSource;
912
912
  if (typeof call !== "function") {
913
- throw new Error(`Engine ${mode === "cold-cook" ? "asset-source.cold-cook" : "asset-source.rebuild"} is unavailable`);
913
+ throw new Error(`Engine ${mode === "cold-cook" ? "asset.source.cold-cook" : "asset.source.rebuild"} is unavailable`);
914
914
  }
915
915
  await call.call(this.api, guid, {
916
916
  projectId: this.state.project.id,
@@ -1626,4 +1626,4 @@ export {
1626
1626
  ViewWorkspaceInputController,
1627
1627
  ViewWorkspaceShell
1628
1628
  };
1629
- //# sourceMappingURL=chunk-4T3D67CS.mjs.map
1629
+ //# sourceMappingURL=chunk-GRDCA6LD.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../packages/view-plugin-viewport/src/workspace-shell.ts"],
4
- "sourcesContent": ["import type { EngineWorkspaceCameraResult, EngineWorkspacePresentation, EngineWorkspaceTarget } from '@forgeax/engine/app';\nimport type { ViewWorkspaceClient } from '@forgeax/view-workspace-core/client';\nimport type { WorkspaceTarget, WorkspaceState, WorkspaceAsset, WorkspaceInspection } from '@forgeax/view-workspace-core/contract';\nimport type { Dispose } from '@forgeax/view-workspace-core/frontend-contract';\n\ntype WorkspacePresentation = EngineWorkspacePresentation & { workspace?: EngineWorkspacePresentation; display?: EngineWorkspacePresentation };\ntype DisplayTarget = WorkspaceTarget & { surfaceId?: string; leaseId?: string };\ntype NavigationMode = 'look' | 'orbit' | 'pan' | 'dolly';\ntype CameraMotion = { type: NavigationMode | 'move'; mode?: string; yaw?: number; pitch?: number; x?: number; y?: number; amount?: number; distance?: number; pitchLimit?: number; velocity?: number[] };\ntype CameraSample = { type: 'key-down' | 'key-up'; mode?: never; code?: string; key: string } | { type: 'wheel'; mode: 'speed' | 'dolly'; deltaY: number } | { type: 'pointer-move'; mode: NavigationMode; movementX: number; movementY: number };\ntype CameraInteraction = EngineWorkspaceCameraResult & { interactionId: string; baseVersion: number };\nexport type WorkspaceInputOptions = {\n api: ViewWorkspaceClient; targetId: string; targetGeneration?: number; tabId?: string;\n interactionIdFactory?: () => string; shouldCapture?: (event: Event) => boolean;\n onError?: (error: unknown) => void; onFocusSelection?: () => unknown; onSpeedChange?: (speed: number) => void;\n window?: Window | typeof globalThis; document?: Document;\n};\ntype RemoveInput = ((reason?: string) => void) & { handlesAbort?: boolean };\ntype ShellState = WorkspaceState & { assets: readonly WorkspaceAsset[]; inspectorError: string | null; error: string | null; projectOpening: boolean; projectReconnecting: boolean };\ntype SurfaceEntry = { targetId: string | null; target: WorkspaceTarget | null; exactSurface: boolean; surfacePlacement: 'owner' | 'shell'; reacquire: boolean; surface: HTMLElement };\ntype PresentationEntry = { target: WorkspaceTarget; targetId: string; surface: HTMLElement; presentation: WorkspacePresentation; surfacePlacement: 'owner' | 'shell'; generation: number; remove?: Dispose; restore?: Dispose; ready?: boolean };\nexport type WorkspaceShellOptions = {\n document?: Document; window?: Window | typeof globalThis; mountId?: string; element?: HTMLElement;\n api?: ViewWorkspaceClient; presentation?: WorkspacePresentation; resourceBrowser?: boolean; presentationOnly?: boolean; inspectorPanel?: boolean;\n onNavigationSpeed?: (speed: number) => void; inputControllerFactory?: (options: WorkspaceInputOptions) => ViewWorkspaceInputController;\n};\nimport { reportWorkspaceCommandError, workspaceDiagnosticRecord } from '@forgeax/view-workspace-core/command-error';\nimport {\n VIEW_DISPLAY_TAB_ID,\n VIEW_WORKSPACE_TAB_ID,\n cloneWorkspaceValue,\n requireWorkspaceString,\n workspaceUiFingerprint,\n} from '@forgeax/view-workspace-core/contract';\nimport { createWorkspaceId } from '@forgeax/view-workspace-core/id';\nimport { reopenWorkspaceProject } from '@forgeax/view-workspace-core/workspace-recovery';\nimport { PAGE_TYPE } from './identity.ts';\nimport { selectWorkspaceEditorSurfaceTarget } from '@forgeax/view-workspace-core/resource-open';\nimport { borrowSurface, keepSurfaceInContainer, readSceneShell } from '@forgeax/view-workspace-core/adopt-surface';\nimport {\n isViewTraceEnabled,\n traceInputAttach,\n traceInputCaptureAbort,\n traceInputPointerDown,\n traceInputPointerLockExit,\n traceInputPointerMove,\n traceInputPointerUp,\n tracePresentationAttach,\n traceShellRegisterDomRoot,\n traceShellRender,\n traceShellUpdate,\n traceSyncTargetSurfaces,\n traceView,\n} from '@forgeax/view-workspace-core/view-trace';\n\nfunction sameTargetIdentity(left: DisplayTarget | null | undefined, right: DisplayTarget | null | undefined) {\n return left?.targetId === right?.targetId && left?.generation === right?.generation &&\n left?.surfaceId === right?.surfaceId && left?.leaseId === right?.leaseId;\n}\n\nfunction text(document: Document, value: unknown) {\n const node = document.createElement('span');\n node.textContent = String(value);\n return node;\n}\n\nfunction button(document: Document, label: string, onClick: () => unknown, { disabled = false } = {}) {\n const node = document.createElement('button');\n node.type = 'button';\n node.textContent = label;\n node.disabled = disabled;\n node.addEventListener?.('click', () => void Promise.resolve(onClick()).catch(() => {}));\n return node;\n}\n\nfunction safeError(error: unknown) {\n const failure = error !== null && typeof error === 'object' ? error as { message?: string; hint?: unknown } : undefined;\n const message = failure?.message ?? String(error);\n const hint = typeof failure?.hint === 'string' ? failure.hint.trim() : '';\n return hint && !message.includes(hint) ? `${message} (${hint})` : message;\n}\n\nfunction groupAssetsBySource(assets: readonly WorkspaceAsset[] | null | undefined) {\n const groups: { key: string; assets: WorkspaceAsset[] }[] = [];\n const index = new Map<string, { key: string; assets: WorkspaceAsset[] }>();\n for (const asset of assets ?? []) {\n const key = asset.sourcePath || asset.path || asset.kind || 'assets';\n let group = index.get(key);\n if (!group) {\n group = { key, assets: [] };\n index.set(key, group);\n groups.push(group);\n }\n group.assets.push(asset);\n }\n return groups;\n}\n\nfunction catalogDdcState(asset: WorkspaceAsset, inspection?: WorkspaceInspection | null) {\n if (inspection?.guid === asset?.guid && inspection.ddc?.state) return inspection.ddc.state;\n return asset?.ddc?.state;\n}\n\nfunction catalogReceipt(asset: WorkspaceAsset, inspection?: WorkspaceInspection | null) {\n if (inspection?.guid === asset?.guid && inspection.ddc?.receiptUrl) return inspection.ddc.receiptUrl;\n return asset?.cookReceiptUrl ?? asset?.ddc?.receiptUrl;\n}\n\n/** Viewport camera capture stays on the Editor page canvas, never a sibling tab preview. */\nexport function isViewportWorkspaceInputEvent(event: Event, { surface, host }: { surface?: HTMLElement; host?: HTMLElement | null } = {}) {\n const eventTarget = event?.target as Element | null;\n if (event?.defaultPrevented || !eventTarget || typeof eventTarget.closest !== 'function') return false;\n if (eventTarget.closest('button,input,a,select,textarea,[contenteditable=\"true\"],.fx-engine-fatal-banner')) return false;\n const page = (host ?? eventTarget).closest?.('[data-forgeax-view-dock-page]');\n if (page?.getAttribute?.('aria-hidden') === 'true') return false;\n if (surface) {\n const activePage = host?.ownerDocument?.documentElement?.dataset?.forgeaxViewActivePage;\n if (activePage !== undefined && activePage !== PAGE_TYPE) return false;\n if (surface.style?.visibility === 'hidden' || surface.style?.pointerEvents === 'none') return false;\n return eventTarget === surface || surface.contains?.(eventTarget) === true;\n }\n if (!eventTarget.closest('[data-forgeax-view-mount-host=\"viewport\"]')) return false;\n return Boolean(eventTarget.closest('[data-forgeax-view-workspace=\"preview\"]'));\n}\n\n/**\n * Bind the CLI display tab to the iframe allocated by BrowserPagePlatform.\n * The platform owns that node and its browsing context; the workspace only\n * changes visibility and input affordances. In particular, this adapter never\n * appends, reorders, or removes the iframe because moving a live iframe can\n * detach the exact Engine Frame held by the carrier.\n */\nexport function createBrowserPagePresentation({ document = globalThis.document }: { document?: Document } = {}): WorkspacePresentation {\n return Object.freeze<EngineWorkspacePresentation>({\n surfacePlacement: 'owner',\n createSurface({ target, document: suppliedDocument = document }: Partial<Parameters<NonNullable<EngineWorkspacePresentation['createSurface']>>[0]> = {}) {\n const displayTarget = workspaceDiagnosticRecord(target);\n const surfaceId = displayTarget.surfaceId;\n if (typeof surfaceId !== 'string' || surfaceId.length === 0) {\n throw new TypeError('Engine display target must expose its exact surfaceId');\n }\n const ownerDocument = suppliedDocument as Document;\n if (ownerDocument?.querySelectorAll === undefined) return null;\n const matches = [...ownerDocument.querySelectorAll<HTMLIFrameElement>('iframe[data-forgeax-view-surface=\"engine-target\"]')].filter(\n (element) =>\n element.dataset?.forgeaxViewSurface === 'engine-target' &&\n element.dataset?.forgeaxViewTargetId === String(displayTarget.targetId) &&\n element.dataset?.forgeaxViewLeaseId === String(displayTarget.leaseId) &&\n element.dataset?.forgeaxViewGeneration === String(displayTarget.generation) &&\n element.id === surfaceId,\n );\n if (matches.length > 1) {\n throw new Error(`multiple Engine display surfaces match ${surfaceId}`);\n }\n return matches[0] ?? null;\n },\n attach({ target, element: suppliedElement }: Partial<Parameters<NonNullable<EngineWorkspacePresentation['attach']>>[0]> = {}) {\n const element = workspaceDiagnosticRecord(suppliedElement);\n const dataset = workspaceDiagnosticRecord(element.dataset);\n const displayTarget = workspaceDiagnosticRecord(target);\n if (\n !suppliedElement ||\n typeof element.tagName !== 'string' || element.tagName.toLowerCase() !== 'iframe' ||\n element.id !== displayTarget.surfaceId ||\n dataset.forgeaxViewLeaseId !== String(displayTarget.leaseId) ||\n dataset.forgeaxViewGeneration !== String(displayTarget.generation)\n ) {\n throw new Error('Engine display surface identity does not match its target');\n }\n // Placement and lease cleanup stay with BrowserPagePlatform.\n return undefined;\n },\n });\n}\n\n/**\n * Browser-side continuous input boundary. Engine owns camera math and the\n * draft transaction; this object only samples DOM input and commits/aborts\n * through the workspace API. All event handlers consume rejected promises so\n * a blur, disconnect, or begin/finish race cannot become an unhandled error.\n */\nexport class ViewWorkspaceInputController {\n declare api: ViewWorkspaceClient;\n declare targetId: string;\n declare targetGeneration: number | undefined;\n declare tabId: string;\n declare interactionIdFactory: () => string;\n declare shouldCapture: (event: Event) => boolean;\n declare onError: (error: unknown) => void;\n declare onFocusSelection: () => unknown;\n declare onSpeedChange: (speed: number) => void;\n declare speed: number;\n declare held: Set<string>;\n declare shiftHeld: boolean;\n declare window: Window | typeof globalThis;\n declare document: Document;\n declare interaction: CameraInteraction | null;\n declare pending: Promise<void>;\n declare inputError: unknown;\n declare inputQueue: CameraMotion[];\n declare beginPromise: Promise<CameraInteraction | null> | null;\n declare finishPromise: Promise<void> | null;\n declare abortPromise?: Promise<void> | null;\n declare generation: number;\n declare cancelRequested: boolean;\n declare disposed: boolean;\n declare element: HTMLElement | null;\n declare bound: boolean;\n declare pointerLockEngaged: boolean;\n declare draining?: boolean;\n\n constructor({\n api,\n targetId,\n targetGeneration,\n tabId = VIEW_WORKSPACE_TAB_ID,\n interactionIdFactory = () => createWorkspaceId('interaction'),\n shouldCapture = () => true,\n onError = () => {},\n onFocusSelection = () => {},\n onSpeedChange = () => {},\n window = globalThis,\n document = globalThis.document,\n }: Partial<WorkspaceInputOptions> = {}) {\n if (!api) throw new TypeError('workspace input controller requires an API client');\n this.api = api;\n this.targetId = requireWorkspaceString(targetId, 'targetId');\n this.targetGeneration = targetGeneration;\n this.tabId = tabId;\n this.interactionIdFactory = interactionIdFactory;\n if (typeof this.interactionIdFactory !== 'function') {\n throw new TypeError('workspace input controller requires an interactionIdFactory');\n }\n this.shouldCapture = shouldCapture;\n this.onError = onError;\n this.onFocusSelection = onFocusSelection;\n this.onSpeedChange = onSpeedChange;\n this.speed = 4;\n this.held = new Set();\n this.shiftHeld = false;\n this.window = window;\n this.document = document;\n this.interaction = null;\n this.pending = Promise.resolve();\n this.inputError = null;\n this.inputQueue = [];\n this.beginPromise = null;\n this.finishPromise = null;\n this.generation = 0;\n this.cancelRequested = false;\n this.disposed = false;\n this.element = null;\n this.bound = false;\n // Pointer lock is an optional browser affordance. Keep a local bit so a\n // rejected request (or a browser that never grants lock to an overlay)\n // cannot be mistaken for a lock-loss transition and abort a valid\n // pointer transaction.\n this.pointerLockEngaged = false;\n }\n\n report(error: unknown) {\n if (error === undefined || error === null) return;\n this.inputError ??= error;\n try {\n this.onError(error);\n } catch {\n // Error presentation cannot change the Engine transaction.\n }\n }\n\n async begin(): Promise<CameraInteraction | null> {\n if (this.beginPromise) return this.beginPromise;\n if (this.interaction && !this.finishPromise && !this.abortPromise) return this.interaction;\n const abort = this.abortPromise;\n const finish = this.finishPromise;\n const queue = this.inputQueue;\n const generation = this.generation;\n this.cancelRequested = false;\n const begunPromise = (async () => {\n if (abort) await abort;\n if (finish) await finish;\n if (this.disposed) throw new Error('workspace input controller is disposed');\n const current = await this.api.getCamera({ targetId: this.targetId, targetGeneration: this.targetGeneration, tabId: this.tabId });\n if (this.disposed || generation !== this.generation || this.cancelRequested) {\n throw new Error('workspace input begin was cancelled');\n }\n const expectedVersion = current.version;\n if (typeof expectedVersion !== 'number' || !Number.isSafeInteger(expectedVersion) || expectedVersion < 0) {\n throw new TypeError('workspace camera begin requires getCamera().version');\n }\n const interactionId = this.interactionIdFactory();\n const begun = await this.api.beginCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n baseVersion: expectedVersion,\n interactionId,\n });\n // 0.1.33 begin returns { camera, version } only. Commit must use the\n // interactionId we sent and the version observed at begin.\n this.interaction = { ...begun, interactionId, baseVersion: expectedVersion };\n await this.flushInputQueue();\n if (this.cancelRequested || this.disposed || generation !== this.generation) {\n await this.api\n .abortCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId,\n reason: 'input-begin-cancelled',\n })\n .catch((error) => this.report(error));\n this.clearTransaction();\n throw new Error('workspace input begin was cancelled');\n }\n return this.interaction;\n })();\n this.beginPromise = begunPromise;\n try {\n return await begunPromise;\n } catch (error) {\n if (generation === this.generation && this.inputQueue === queue) this.clearTransaction();\n throw error;\n } finally {\n if (this.beginPromise === begunPromise) this.beginPromise = null;\n }\n }\n\n async flushInputQueue() {\n this.drainInputQueue();\n await this.pending;\n }\n\n enqueueUpdate(input: CameraMotion) {\n const previous = this.inputQueue.at(-1);\n if (previous?.type === input.type && previous.mode === input.mode &&\n ['look', 'orbit', 'pan', 'dolly'].includes(input.type)) {\n for (const key of ['yaw', 'pitch', 'x', 'y', 'amount'] as const) {\n if (input[key] !== undefined) previous[key] = (previous[key] ?? 0) + input[key];\n }\n } else if (this.inputQueue.length < 64) {\n this.inputQueue.push({ ...input });\n } else {\n this.report(new Error('Viewport input exceeded its bounded queue; gesture cancelled.'));\n void this.abort('input-overflow');\n return;\n }\n this.drainInputQueue();\n }\n\n drainInputQueue(interaction = this.interaction, queue = this.inputQueue) {\n if (this.finishPromise && queue === this.inputQueue) return;\n if (!interaction || this.draining) return;\n const generation = this.generation;\n this.draining = true;\n this.pending = Promise.resolve().then(async () => {\n while (queue.length) {\n if (\n generation !== this.generation ||\n this.cancelRequested ||\n this.disposed ||\n this.interaction !== interaction\n )\n return;\n const input = queue.shift();\n await this.api.updateCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId: interaction.interactionId,\n input,\n });\n if (generation !== this.generation || this.interaction !== interaction) return;\n }\n })\n .catch((error) => {\n if (generation !== this.generation || this.interaction !== interaction) return;\n this.inputError ??= error;\n this.report(error);\n })\n .finally(() => {\n this.draining = false;\n if (generation === this.generation && this.inputQueue.length) this.drainInputQueue();\n });\n }\n\n /** Current WASD/QE move sample; Shift multiplies speed like Unreal's fast-fly. */\n currentMoveInput(): CameraMotion {\n const axes = [Number(this.held.has('KeyD')) - Number(this.held.has('KeyA')),\n Number(this.held.has('KeyE')) - Number(this.held.has('KeyQ')),\n Number(this.held.has('KeyS')) - Number(this.held.has('KeyW'))];\n const length = Math.hypot(...axes) || 1;\n const boost = this.shiftHeld ? 3 : 1;\n return { type: 'move', velocity: axes.map(value => (value * this.speed * boost) / length) };\n }\n\n queueInput(input: CameraSample) {\n if (this.disposed || this.cancelRequested) return;\n const movement = () => this.currentMoveInput();\n let motion: CameraMotion;\n if (input.type === 'key-down' || input.type === 'key-up') {\n const code = input.code || 'Key' + String(input.key).toUpperCase();\n if (input.type === 'key-down') this.held.add(code);\n else this.held.delete(code);\n motion = movement();\n } else if (input.type === 'wheel' && input.mode === 'speed') {\n this.speed = Math.max(0.05, Math.min(1024, this.speed * Math.exp(-input.deltaY * 0.002)));\n this.onSpeedChange(this.speed);\n motion = movement();\n } else if (input.type === 'wheel' || input.mode === 'dolly') {\n motion = { type: 'dolly', amount: Math.max(-4, Math.min(4,\n (input.type === 'wheel' ? input.deltaY : ('movementY' in input ? input.movementY : 0) * 4) * 0.001)), distance: 5 };\n } else if (input.mode === 'pan') {\n motion = { type: 'pan', x: -(('movementX' in input ? input.movementX : 0)) * 0.002,\n y: (('movementY' in input ? input.movementY : 0)) * 0.002, distance: 5 };\n } else {\n motion = { type: input.mode === 'orbit' ? 'orbit' : 'look',\n yaw: -(('movementX' in input ? input.movementX : 0)) * 0.003, pitch: -(('movementY' in input ? input.movementY : 0)) * 0.003,\n pitchLimit: Math.PI / 2 - 0.01, distance: 5 };\n }\n this.enqueueUpdate(motion);\n }\n\n clearTransaction() {\n this.held.clear();\n this.interaction = null;\n this.pending = Promise.resolve();\n this.inputQueue = [];\n this.inputError = null;\n }\n\n async finish(): Promise<void> {\n if (this.finishPromise) {\n const finishing = this.finishPromise;\n return this.beginPromise ? finishing.then(() => this.finish()) : finishing;\n }\n const begin = this.beginPromise;\n this.beginPromise = null;\n const queue = this.inputQueue;\n this.inputQueue = [];\n this.held.clear();\n const generation = this.generation;\n let interaction;\n this.finishPromise = (async () => {\n try {\n if (begin) await begin;\n interaction = this.interaction;\n if (!interaction) return;\n await this.pending;\n this.drainInputQueue(interaction, queue);\n await this.pending;\n if (this.cancelRequested || this.disposed || generation !== this.generation) {\n await this.api.abortCamera({ targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId, interactionId: interaction.interactionId, reason: 'input-finish-cancelled' });\n return;\n }\n if (this.inputError) {\n const error = this.inputError;\n await this.api.abortCamera({ targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId, interactionId: interaction.interactionId, reason: 'input-update-failed' });\n throw error;\n }\n try {\n await this.api.commitCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId: interaction.interactionId,\n operationId: this.interactionIdFactory(),\n expectedVersion: interaction.baseVersion,\n });\n } catch (error) {\n await this.api\n .abortCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId: interaction.interactionId,\n reason: 'commit-failed',\n })\n .catch(() => {});\n throw error;\n }\n } finally {\n if (this.interaction === interaction) this.interaction = null;\n this.inputError = null;\n }\n })();\n try {\n return await this.finishPromise;\n } finally {\n this.finishPromise = null;\n }\n }\n\n async abort(reason = 'input-abort') {\n if (this.abortPromise) return this.abortPromise;\n ++this.generation;\n this.cancelRequested = true;\n const begin = this.beginPromise;\n this.abortPromise = (async () => {\n if (begin) await begin.catch(() => {});\n await this.pending;\n const interaction = this.interaction;\n try {\n if (interaction) {\n await this.api.abortCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId: interaction.interactionId,\n reason,\n });\n }\n } catch (error) {\n this.report(error);\n } finally {\n this.clearTransaction();\n }\n })();\n try { await this.abortPromise; }\n finally { this.abortPromise = null; }\n }\n\n async requestPointerLock() {\n if (typeof this.element?.requestPointerLock !== 'function') return;\n try {\n await Promise.resolve(this.element.requestPointerLock());\n } catch {\n // Pointer lock is an optional browser affordance. A browser can reject\n // it for an iframe, automation event, or missing user activation while\n // ordinary pointer/keyboard samples remain valid. Do not turn that\n // presentation limitation into an Engine transaction failure.\n }\n }\n\n trySetPointerCapture(element: HTMLElement | null, pointerId?: number) {\n if (pointerId === undefined || typeof element?.setPointerCapture !== 'function') return;\n try {\n element.setPointerCapture(pointerId);\n } catch {\n // Pointer capture is best-effort. The API interaction remains the\n // authority and can continue without this browser-local optimization.\n }\n }\n\n tryReleasePointerCapture(element: HTMLElement | null, pointerId?: number) {\n if (pointerId === undefined || typeof element?.releasePointerCapture !== 'function') return;\n try {\n element.releasePointerCapture(pointerId);\n } catch {\n // The pointer may already have been cancelled or released by the\n // browser; there is no Engine state to repair here.\n }\n }\n\n attach(element: HTMLElement): RemoveInput {\n if (!element || this.bound) return () => {};\n this.element = element;\n this.bound = true;\n this.onSpeedChange(this.speed);\n const previousTabIndex = element.getAttribute?.('tabindex');\n if (previousTabIndex == null) element.setAttribute?.('tabindex', '0');\n traceInputAttach(element, { targetId: this.targetId, tabId: this.tabId });\n let gesture: { button: number; mode: NavigationMode } | null = null;\n let selectionRequest: AbortController | undefined;\n let clickStart: { x: number; y: number } | undefined;\n let consumedClick = false;\n const held = this.held;\n const stop = () => {\n selectionRequest?.abort();\n gesture = null;\n held.clear();\n this.shiftHeld = false;\n if (this.document?.pointerLockElement === element) this.document.exitPointerLock?.();\n void this.finish().catch((error) => this.report(error));\n };\n const down = (event: PointerEvent) => {\n if (this.shouldCapture(event)) element.focus?.();\n const accepted = !gesture &&\n (event.button === 2 || event.button === 1 || (event.button === 0 && event.altKey)) &&\n this.shouldCapture(event);\n consumedClick = event.defaultPrevented === true || accepted;\n clickStart = { x: event.clientX, y: event.clientY };\n traceInputPointerDown(event, { accepted, element });\n if (accepted) {\n selectionRequest?.abort();\n event.preventDefault?.();\n gesture = {\n button: event.button,\n mode: event.button === 1 ? 'pan' : event.altKey ? (event.button === 0 ? 'orbit' : 'dolly') : 'look',\n };\n element.focus?.();\n void this.begin().catch((error) => this.report(error));\n this.trySetPointerCapture(element, event?.pointerId);\n void this.requestPointerLock();\n traceView('input', 'capture-engaged', {\n pointerId: event?.pointerId,\n pointerLockElement: globalThis.document?.pointerLockElement?.tagName,\n });\n }\n };\n const menu = (event: MouseEvent) => {\n if (!this.shouldCapture(event)) return;\n event.preventDefault?.();\n };\n const move = (event: PointerEvent) => {\n if (clickStart && Math.hypot(event.clientX - clickStart.x, event.clientY - clickStart.y) > 4) consumedClick = true;\n if (!gesture || (!this.interaction && !this.beginPromise)) return;\n traceInputPointerMove(event, {\n queued: true,\n queueDepth: this.inputQueue.length,\n inFlight: this.draining ? 1 : 0,\n });\n this.queueInput({\n type: 'pointer-move',\n mode: gesture.mode,\n movementX: Number(event.movementX ?? 0),\n movementY: Number(event.movementY ?? 0),\n });\n };\n const up = (event: PointerEvent) => {\n if (!gesture || event.button !== gesture.button) return;\n this.tryReleasePointerCapture(element, event?.pointerId);\n traceInputPointerUp(event, { element });\n stop();\n };\n const keydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && gesture) { stop(); return; }\n if (!this.shouldCapture(event) || event.repeat) return;\n if (!gesture && String(event.key).toLowerCase() === 'f') {\n event.preventDefault?.();\n void Promise.resolve().then(this.onFocusSelection).catch(error => this.report(error));\n return;\n }\n // Unreal-style: Shift only boosts speed while navigation keys are held.\n if (event.key === 'Shift') {\n this.shiftHeld = true;\n if (held.size) this.enqueueUpdate(this.currentMoveInput());\n return;\n }\n // WASD/QE move with or without the RMB look gesture.\n if (!['w', 'a', 's', 'd', 'q', 'e'].includes(String(event.key ?? '').toLowerCase())) return;\n event.preventDefault?.();\n held.add(event.code || event.key);\n if (!gesture) void this.begin().catch((error) => this.report(error));\n this.queueInput({ type: 'key-down', key: String(event.key ?? ''), code: String(event.code ?? '') });\n };\n const keyup = (event: KeyboardEvent) => {\n if (event.key === 'Shift') {\n this.shiftHeld = false;\n if (held.size) this.enqueueUpdate(this.currentMoveInput());\n return;\n }\n if (!held.delete(event.code || event.key)) return;\n if (!this.interaction && !this.beginPromise) return;\n event.preventDefault?.();\n this.queueInput({ type: 'key-up', key: String(event.key ?? ''), code: String(event.code ?? '') });\n // Bare keys own no pointer gesture: commit the camera transaction once\n // every navigation key is released instead of leaking an open draft.\n if (!gesture && held.size === 0) void this.finish().catch((error) => this.report(error));\n };\n const wheel = (event: WheelEvent) => {\n if (!this.shouldCapture(event) || this.finishPromise) return;\n selectionRequest?.abort();\n event.preventDefault?.();\n void this.begin().catch((error) => this.report(error));\n this.queueInput({ type: 'wheel', mode: gesture?.mode === 'look' ? 'speed' : 'dolly',\n deltaY: Number(event.deltaY ?? 0) * (event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? 800 : 1) });\n if (!gesture) void this.finish().catch((error) => this.report(error));\n };\n const abort = (reason = 'input-focus-lost') => {\n if (reason !== 'pointerlock-exit') traceInputCaptureAbort(reason);\n else traceView('input', 'abort', { reason });\n stop();\n };\n const pointerLockChange = () => {\n const locked = this.document?.pointerLockElement === element;\n traceView('input', 'pointerlockchange', {\n locked,\n pointerLockElement: this.document?.pointerLockElement?.tagName,\n engaged: this.pointerLockEngaged,\n });\n if (locked) this.pointerLockEngaged = true;\n if (this.pointerLockEngaged && !locked) {\n this.pointerLockEngaged = false;\n traceInputPointerLockExit({ locked, element });\n abort('pointerlock-exit');\n }\n };\n const click = (event: MouseEvent) => {\n const consumed = consumedClick;\n consumedClick = false;\n const dragged = clickStart && Math.hypot(event.clientX - clickStart.x, event.clientY - clickStart.y) > 4;\n clickStart = undefined;\n if (consumed || dragged) return;\n if (gesture || event.button !== 0 || event.altKey || !this.shouldCapture(event)) return;\n const canvas = element.tagName === 'CANVAS' ? element as HTMLCanvasElement : element.querySelector?.('canvas');\n if (!canvas || event.target !== canvas) return;\n const rect = canvas.getBoundingClientRect();\n if (!(rect.width > 0 && rect.height > 0 && canvas.width > 0 && canvas.height > 0)) return;\n selectionRequest?.abort();\n selectionRequest = new AbortController();\n // The shared client reports failures; a failed query never enters the camera transaction.\n void this.api.call('scene.pick', {\n targetId: this.targetId, targetGeneration: this.targetGeneration, tabId: this.tabId,\n x: (event.clientX - rect.left) * canvas.width / rect.width,\n y: (event.clientY - rect.top) * canvas.height / rect.height,\n }, { signal: selectionRequest.signal }).catch(() => {});\n };\n element.addEventListener?.('click', click);\n element.addEventListener?.('pointerdown', down);\n element.addEventListener?.('pointermove', move);\n element.addEventListener?.('pointerup', up);\n element.addEventListener?.('wheel', wheel, { passive: false });\n element.addEventListener?.('contextmenu', menu);\n const onPointerCancel = () => abort('pointercancel');\n const onWindowBlur = () => abort('window-blur');\n const onFocusOut = (event: FocusEvent) => { if (!element.contains?.(event.relatedTarget as Node | null)) abort('focusout'); };\n const onVisibilityChange = () => { if (this.document?.hidden) abort('visibilitychange'); };\n element.addEventListener?.('pointercancel', onPointerCancel);\n element.addEventListener?.('keydown', keydown);\n this.window?.addEventListener?.('keyup', keyup);\n this.window?.addEventListener?.('pointerup', up);\n this.window?.addEventListener?.('blur', onWindowBlur);\n this.window?.addEventListener?.('focusout', onFocusOut);\n this.document?.addEventListener?.('visibilitychange', onVisibilityChange);\n this.document?.addEventListener?.('pointerlockchange', pointerLockChange);\n const remove = (reason = 'input-detached') => {\n if (previousTabIndex == null) element.removeAttribute?.('tabindex');\n selectionRequest?.abort();\n element.removeEventListener?.('click', click);\n element.removeEventListener?.('pointerdown', down);\n element.removeEventListener?.('pointermove', move);\n element.removeEventListener?.('pointerup', up);\n element.removeEventListener?.('wheel', wheel);\n element.removeEventListener?.('contextmenu', menu);\n element.removeEventListener?.('pointercancel', onPointerCancel);\n element.removeEventListener?.('keydown', keydown);\n this.window?.removeEventListener?.('keyup', keyup);\n this.window?.removeEventListener?.('pointerup', up);\n this.window?.removeEventListener?.('blur', onWindowBlur);\n this.window?.removeEventListener?.('focusout', onFocusOut);\n this.document?.removeEventListener?.('visibilitychange', onVisibilityChange);\n this.document?.removeEventListener?.('pointerlockchange', pointerLockChange);\n this.pointerLockEngaged = false;\n if (reason !== 'input-disposed') {\n traceInputCaptureAbort(reason);\n void this.abort(reason).catch((error) => this.report(error));\n }\n this.element = null;\n this.bound = false;\n };\n remove.handlesAbort = true;\n return remove;\n }\n\n dispose() {\n this.disposed = true;\n return this.abort('input-disposed');\n }\n}\n\n/** Stable exact Engine surfaces; all state and controls use the workspace API.\n * Without a presentation adapter, retain an inert surface. Editor Play owns its\n * one iframe in a separate plugin; an arbitrary target URL never creates one.\n */\nexport class ViewWorkspaceShell {\n declare document: Document;\n declare window: Window | typeof globalThis;\n declare mountId: string;\n declare api: ViewWorkspaceClient | undefined;\n declare presentation: WorkspacePresentation | undefined;\n declare resourceBrowser: boolean;\n declare presentationOnly: boolean;\n declare inspectorPanel: boolean;\n declare inputControllerFactory: (options: WorkspaceInputOptions) => ViewWorkspaceInputController;\n declare onNavigationSpeed: (speed: number) => void;\n declare state: ShellState;\n declare element: HTMLElement | null;\n declare rootElement: HTMLElement | null;\n declare tabsElement: HTMLElement | null;\n declare projectElement: HTMLElement | null;\n declare assetsElement: HTMLElement | null;\n declare workbenchElement: HTMLElement | null;\n declare inspectorElement: HTMLElement | null;\n declare inspectorInfoElement: HTMLElement | null;\n declare inspectorFieldsElement: HTMLElement | null;\n declare inspectorActionsElement: HTMLElement | null;\n declare previewElement: HTMLElement | null;\n declare previewInfoElement: HTMLElement | null;\n declare errorElement: HTMLElement | null;\n declare targetContainer: HTMLElement | null;\n declare surface: HTMLElement | null;\n declare removeSubscription?: Dispose;\n declare removeDisconnect?: Dispose;\n declare removeInput?: RemoveInput;\n declare inputController?: ViewWorkspaceInputController;\n declare inputTargetId: string | null;\n declare inputTargetGeneration?: number;\n declare inputSurface?: HTMLElement;\n declare surfaceByTab: Map<string, SurfaceEntry>;\n declare presentationByTab: Map<string, PresentationEntry>;\n declare presentationPending: Map<string, { target: WorkspaceTarget; generation: number; surface: HTMLElement; task: Promise<void> }>;\n declare presentationQueueByTab: Map<string, Promise<void>>;\n declare presentationGenerationByTab: Map<string, number>;\n declare surfaceTargetId: string | null;\n declare presentedTargetId: string | null;\n declare removeSurfacePresentation?: Dispose;\n declare renderFingerprint: string;\n declare disposed: boolean;\n declare stopSceneAdopt?: Dispose;\n declare disposal?: Promise<void>;\n\n constructor({\n document = globalThis.document,\n window = globalThis,\n mountId = 'forgeax-view-workspace',\n element,\n api,\n presentation,\n resourceBrowser = false,\n presentationOnly = false,\n inspectorPanel = true,\n onNavigationSpeed = () => {},\n inputControllerFactory = (options) => new ViewWorkspaceInputController(options),\n }: WorkspaceShellOptions = {}) {\n this.document = document;\n this.window = window;\n this.mountId = mountId;\n this.api = api;\n this.presentation = presentation;\n this.resourceBrowser = resourceBrowser === true;\n this.presentationOnly = presentationOnly;\n this.inspectorPanel = inspectorPanel !== false;\n this.inputControllerFactory = inputControllerFactory;\n this.onNavigationSpeed = onNavigationSpeed;\n this.state = {\n selectedTabId: VIEW_WORKSPACE_TAB_ID,\n tabs: [],\n project: null,\n projectTarget: null,\n preview: null,\n assets: [],\n inspection: null,\n inspectorError: null,\n error: null,\n projectOpening: false,\n projectReconnecting: false,\n workspaceTargetLost: false,\n };\n this.element = null;\n this.rootElement = null;\n this.tabsElement = null;\n this.projectElement = null;\n this.assetsElement = null;\n this.workbenchElement = null;\n this.inspectorElement = null;\n this.inspectorInfoElement = null;\n this.inspectorFieldsElement = null;\n this.inspectorActionsElement = null;\n this.previewElement = null;\n this.previewInfoElement = null;\n this.errorElement = null;\n this.targetContainer = null;\n this.removeSubscription = undefined;\n this.removeDisconnect = undefined;\n this.removeInput = undefined;\n this.inputController = undefined;\n this.inputTargetId = null;\n this.surfaceByTab = new Map();\n this.presentationByTab = new Map();\n this.presentationPending = new Map();\n this.presentationQueueByTab = new Map();\n this.presentationGenerationByTab = new Map();\n this.surface = null;\n this.surfaceTargetId = null;\n this.presentedTargetId = null;\n this.removeSurfacePresentation = undefined;\n this.renderFingerprint = '';\n this.disposed = false;\n this.stopSceneAdopt = undefined;\n if (document?.createElement) {\n // Prefer the caller-supplied node. Dockview/ShadowRoot mounts are not\n // visible to document.getElementById, and falling back to a new body\n // section would orphan the exact Engine surface outside the View shell.\n this.element = element\n ?? document.getElementById?.(mountId)\n ?? document.createElement('section');\n this.element.id ||= mountId;\n this.element.dataset.forgeaxView = 'workspace';\n if (!this.element.parentNode) document.body?.append?.(this.element);\n this.render();\n }\n if (api) this.connect(api);\n }\n\n connect(api: ViewWorkspaceClient) {\n this.removeSubscription?.();\n this.removeDisconnect?.();\n this.api = api;\n this.disposed = false;\n this.removeSubscription = api.subscribe?.((state) => this.update(state));\n this.removeDisconnect = api.onDisconnect?.((error) => {\n this.detachInput('resident-disconnect');\n this.fail(error);\n });\n void Promise.resolve()\n .then(() => api.getState?.())\n .then((state) => this.update(state))\n .then(() => (this.state.project ? this.refreshAssets() : undefined))\n .catch((error) => this.fail(error));\n return this;\n }\n\n update(snapshot: WorkspaceState = {}) {\n if (this.disposed) return this.snapshot();\n const next = cloneWorkspaceValue(snapshot);\n if (\n next.selectedTabId !== undefined &&\n next.selectedTabId !== this.state.selectedTabId\n ) {\n this.detachInput('tab-selection');\n }\n this.state = {\n ...this.state,\n ...next,\n assets: Array.isArray(next.assets) ? next.assets : next.assets === null ? [] : this.state.assets,\n inspectorError: next.inspection ? null : this.state.inspectorError,\n projectOpening: next.project ? false : this.state.projectOpening,\n projectReconnecting: next.workspaceTargetLost === false ? false : this.state.projectReconnecting,\n workspaceTargetLost: next.workspaceTargetLost === true,\n error: next.project && !next.workspaceTargetLost ? null : this.state.error,\n };\n traceShellUpdate({\n selectedTabId: this.state.selectedTabId,\n cameraVersion: this.state.preview?.cameraVersion,\n previewTargetId: this.state.preview?.target?.targetId,\n });\n const fingerprint = workspaceUiFingerprint(this.state);\n this.render({ chromeChanged: fingerprint !== this.renderFingerprint });\n this.renderFingerprint = fingerprint;\n return this.snapshot();\n }\n\n snapshot() {\n return cloneWorkspaceValue(this.state);\n }\n\n fail(error: unknown) {\n this.state = {\n ...this.state,\n error: safeError(error),\n projectOpening: false,\n projectReconnecting: false,\n };\n if (this.presentationOnly) {\n reportWorkspaceCommandError(error, { operation: 'workspace' });\n }\n this.render();\n this.renderFingerprint = workspaceUiFingerprint(this.state);\n return this.snapshot();\n }\n\n async refreshAssets() {\n if (!this.api || !this.state.project) return;\n try {\n const result = await this.api.listAssets(this.state.project.id, { tabId: VIEW_WORKSPACE_TAB_ID });\n this.state.assets = result.assets ?? [];\n this.state.error = null;\n const fingerprint = workspaceUiFingerprint(this.state);\n this.render({ chromeChanged: fingerprint !== this.renderFingerprint });\n this.renderFingerprint = fingerprint;\n } catch (error) {\n this.fail(error);\n }\n }\n\n async openProject(root: string) {\n if (this.disposed) return this.snapshot();\n if (!this.api) {\n return this.fail(new Error('View workspace API is not connected'));\n }\n if (this.state.projectOpening) return this.snapshot();\n const path = typeof root === 'string' ? root.trim() : '';\n if (!path) {\n return this.fail(new Error('Project root is required'));\n }\n this.state = { ...this.state, error: null, projectOpening: true };\n this.render();\n try {\n const opened = await this.api.openProject(path, { tabId: VIEW_WORKSPACE_TAB_ID });\n if (opened?.project) this.update(opened);\n await this.refreshAssets();\n return this.snapshot();\n } catch (error) {\n return this.fail(error);\n } finally {\n this.state = { ...this.state, projectOpening: false };\n this.render();\n }\n }\n\n async reconnectProject() {\n if (this.disposed) return this.snapshot();\n if (!this.api) {\n return this.fail(new Error('View workspace API is not connected'));\n }\n if (this.state.projectReconnecting) return this.snapshot();\n this.state = { ...this.state, error: null, projectReconnecting: true };\n this.render();\n try {\n const opened = await reopenWorkspaceProject(this.api, { window: this.window });\n if (opened?.project) this.update(opened);\n await this.refreshAssets();\n return this.snapshot();\n } catch (error) {\n return this.fail(error);\n } finally {\n this.state = { ...this.state, projectReconnecting: false };\n this.render();\n }\n }\n\n async openAsset(guid: string) {\n try {\n await this.api!.openAsset(guid, { projectId: this.state.project?.id, tabId: VIEW_WORKSPACE_TAB_ID });\n } catch (error) {\n this.fail(error);\n }\n }\n\n async selectAsset(guid: string) {\n if (!this.api || !this.state.project) return;\n try {\n const inspected = await this.api.inspectAsset(guid, {\n projectId: this.state.project.id,\n tabId: VIEW_WORKSPACE_TAB_ID,\n });\n this.state.inspection = inspected.inspection ?? this.state.inspection;\n this.state.inspectorError = null;\n } catch (error) {\n this.state.inspectorError = safeError(error);\n this.render();\n }\n const asset =\n this.state.assets.find((candidate) => candidate.guid === guid) ?? this.state.inspection?.asset;\n if (this.resourceBrowser) {\n this.render();\n return;\n }\n if (asset?.previewable === false || this.state.preview?.asset?.guid === guid) {\n this.render();\n return;\n }\n await this.openAsset(guid);\n }\n\n async cookSelected(mode = 'rebuild') {\n const guid = this.state.inspection?.guid ?? this.state.preview?.asset?.guid;\n if (!this.api || !this.state.project || !guid) return;\n try {\n const call =\n mode === 'cold-cook' ? this.api.coldCookAssetSource : this.api.rebuildAssetSource;\n if (typeof call !== 'function') {\n throw new Error(`Engine ${mode === 'cold-cook' ? 'asset-source.cold-cook' : 'asset-source.rebuild'} is unavailable`);\n }\n await call.call(this.api, guid, {\n projectId: this.state.project.id,\n tabId: VIEW_WORKSPACE_TAB_ID,\n expectedRevision: this.state.inspection?.revision,\n });\n this.state.inspectorError = null;\n } catch (error) {\n this.state.inspectorError = safeError(error);\n this.render();\n throw error;\n }\n }\n\n async closeProject() {\n try {\n await this.api!.closeProject(this.state.project?.id, { tabId: VIEW_WORKSPACE_TAB_ID });\n } catch (error) {\n this.fail(error);\n }\n }\n\n async selectTab(tabId: string) {\n this.detachInput('tab-selection');\n try {\n await this.api!.selectTab(tabId);\n } catch (error) {\n this.fail(error);\n }\n }\n\n async closePreview() {\n await this.inputController?.abort('preview-close');\n try {\n await this.api!.closePreview({ targetId: this.state.preview?.target?.targetId, targetGeneration: this.state.preview?.target?.generation, tabId: VIEW_WORKSPACE_TAB_ID });\n } catch (error) {\n this.fail(error);\n }\n }\n\n replaceSurface(target: WorkspaceTarget | null) {\n this.ensureSurface(VIEW_WORKSPACE_TAB_ID, target);\n this.setActiveSurface();\n }\n\n attachSurfacePresentation(target: WorkspaceTarget) {\n const entry = this.surfaceByTab.get(VIEW_WORKSPACE_TAB_ID);\n this.attachTargetPresentation(VIEW_WORKSPACE_TAB_ID, target, entry?.surface);\n }\n\n targetForTab(tabId: string) {\n if (tabId === VIEW_WORKSPACE_TAB_ID) return selectWorkspaceEditorSurfaceTarget(this.state);\n const tab = (this.state.tabs ?? []).find((candidate) => candidate.tabId === tabId);\n if (!tab) return null;\n if (tab.target) {\n return {\n ...tab.target,\n targetId: String(tab.target.targetId ?? tab.targetId ?? ''),\n headed: tab.target.headed !== false,\n width: tab.target.width ?? tab.width ?? 1280,\n height: tab.target.height ?? tab.height ?? 720,\n };\n }\n if (tab.targetId === undefined || tab.targetId === null) return null;\n return {\n targetId: String(tab.targetId),\n headed: true,\n width: tab.width ?? 1280,\n height: tab.height ?? 720,\n };\n }\n\n presentationForTab(tabId: string) {\n const candidate = tabId === VIEW_DISPLAY_TAB_ID ? this.presentation?.display : this.presentation?.workspace;\n if (\n candidate &&\n (typeof candidate.attach === 'function' || typeof candidate.createSurface === 'function')\n )\n return candidate;\n return this.presentation;\n }\n\n presentationOwnsPlacement(presentation: WorkspacePresentation | undefined) {\n return presentation?.surfacePlacement === 'owner';\n }\n\n createPresentedSurface(tabId: string, target: WorkspaceTarget, presentationOverride?: WorkspacePresentation) {\n const presentation = presentationOverride ?? this.presentationForTab(tabId);\n if (typeof presentation?.createSurface !== 'function') return null;\n const surface = presentation.createSurface({\n tabId,\n target: target as EngineWorkspaceTarget,\n document: this.document,\n });\n if (surface === null || surface === undefined) return null;\n if (typeof surface !== 'object') {\n throw new TypeError('View target presentation createSurface must return a DOM element');\n }\n return surface as HTMLElement;\n }\n\n ensureSurface(tabId: string, target: WorkspaceTarget | null) {\n const targetId = target?.targetId === undefined ? null : String(target.targetId);\n const current = this.surfaceByTab.get(tabId);\n const presentation = this.presentationForTab(tabId);\n const surfacePlacement = this.presentationOwnsPlacement(presentation) ? 'owner' : 'shell';\n const exactIdentityMatches = sameTargetIdentity(current?.target, target);\n if (!targetId) {\n if (current) {\n // Keep an exact Engine surface as a short-lived tombstone while its\n // serialized detach is draining. A fast stop -> start can otherwise\n // acquire the same host surface before the old cleanup has restored\n // its origin, causing the old cleanup to delete the new origin map.\n // The next exact target reuses this entry and marks it for a queued\n // reacquisition after the old cleanup; inert surfaces can\n // still be discarded immediately.\n if (current.exactSurface) {\n if (current.targetId !== null) {\n current.targetId = null;\n current.target = null;\n current.reacquire = true;\n void this.detachTargetPresentation(tabId).catch((error) => this.fail(error));\n }\n } else {\n void this.detachTargetPresentation(tabId).catch((error) => this.fail(error));\n this.surfaceByTab.delete(tabId);\n }\n }\n return null;\n }\n if (\n current &&\n current.targetId === targetId &&\n (!current.exactSurface || exactIdentityMatches)\n ) {\n current.target = target;\n if (!current.exactSurface) {\n const width = target?.width ?? (current.surface as HTMLCanvasElement).width ?? 1280;\n const height = target?.height ?? (current.surface as HTMLCanvasElement).height ?? 720;\n if ((current.surface as HTMLCanvasElement).width !== width) (current.surface as HTMLCanvasElement).width = width;\n if ((current.surface as HTMLCanvasElement).height !== height) (current.surface as HTMLCanvasElement).height = height;\n }\n return current.surface;\n }\n // A host-provided exact surface is the Engine-owned presentation for this\n // tab, not a per-target canvas allocation. Keep its DOM identity stable\n // when the target identity is refreshed; the serialized presentation\n // lifecycle below still releases the old target before attaching the new\n // one. This also avoids calling createSurface while an earlier attachment\n // may still own the host surface.\n if (\n current &&\n current.exactSurface\n ) {\n current.targetId = targetId;\n current.target = target;\n current.reacquire = true;\n current.surfacePlacement = surfacePlacement;\n return current.surface;\n }\n if (current) {\n void this.detachTargetPresentation(tabId).catch((error) => this.fail(error));\n }\n if (!this.document?.createElement) return null;\n const presentedSurface = this.createPresentedSurface(tabId, target!, presentation);\n if ((surfacePlacement === 'owner' || typeof presentation?.createSurface === 'function') && presentedSurface === null) {\n // The display Fiber owns the only valid surface. During bootstrap it\n // may not exist yet; keep this tab surface-less and retry on a later\n // state/render transition instead of fabricating a second runtime node.\n this.surfaceByTab.delete(tabId);\n return null;\n }\n const surface = presentedSurface ?? this.document.createElement('canvas');\n const exactSurface = presentedSurface !== null;\n const resolvedSurfacePlacement = exactSurface && surfacePlacement === 'owner' ? 'owner' : 'shell';\n if (!exactSurface) {\n this.markSurface(surface, tabId, targetId);\n (surface as HTMLCanvasElement).width = target?.width ?? 1280;\n (surface as HTMLCanvasElement).height = target?.height ?? 720;\n }\n this.surfaceByTab.set(tabId, {\n targetId,\n target,\n exactSurface,\n surfacePlacement: resolvedSurfacePlacement,\n reacquire: false,\n surface,\n });\n return surface;\n }\n\n setActiveSurface() {\n const selected = this.surfaceByTab.get(this.state.selectedTabId ?? VIEW_WORKSPACE_TAB_ID);\n const active = selected?.targetId ? selected : null;\n this.surface = active?.surface ?? null;\n this.surfaceTargetId = active?.targetId ?? null;\n this.presentedTargetId = active?.targetId ?? null;\n }\n\n attachTargetPresentation(tabId: string, target: WorkspaceTarget | null, surface?: HTMLElement) {\n const presentation = this.presentationForTab(tabId);\n if (!target || !surface || (!presentation?.attach && !presentation?.createSurface)) return;\n const current = this.presentationByTab.get(tabId);\n if (current && sameTargetIdentity(current.target, target) && current.surface === surface &&\n current.generation === this.presentationGenerationByTab.get(tabId)) return;\n tracePresentationAttach(tabId, String(target.targetId), surface);\n const pending = this.presentationPending.get(tabId);\n if (pending && sameTargetIdentity(pending.target, target) && pending.surface === surface &&\n pending.generation === this.presentationGenerationByTab.get(tabId)) return;\n const generation = (this.presentationGenerationByTab.get(tabId) ?? 0) + 1;\n this.presentationGenerationByTab.set(tabId, generation);\n const task = this.enqueuePresentation(tabId, async () => {\n if (this.disposed || generation !== this.presentationGenerationByTab.get(tabId)) {\n await this.releaseUnattachedPresentation({ presentation, target, surface, tabId });\n return;\n }\n\n const previous = this.presentationByTab.get(tabId);\n if (previous) await this.releasePresentationEntry(tabId, previous);\n if (this.disposed || generation !== this.presentationGenerationByTab.get(tabId)) {\n await this.releaseUnattachedPresentation({ presentation, target, surface, tabId });\n return;\n }\n\n let attachSurface = surface;\n const surfaceEntry = this.surfaceByTab.get(tabId);\n if (surfaceEntry?.surface === surface && surfaceEntry.exactSurface && surfaceEntry.reacquire) {\n const refreshed = this.createPresentedSurface(tabId, target, presentation);\n if (refreshed !== null) {\n attachSurface = refreshed;\n surfaceEntry.surface = refreshed;\n surfaceEntry.reacquire = false;\n } else {\n // Do not reuse a released node when Engine cannot resolve the new identity.\n this.surfaceByTab.delete(tabId);\n this.setActiveSurface();\n return;\n }\n }\n // A previous Engine cleanup may have restored an exact surface to its\n // original parent. Adopt it only after that cleanup has completed, so a\n // stale cleanup can never move the new attachment out from underneath\n // the current tab.\n const restore = surfaceEntry?.exactSurface && surfaceEntry.surfacePlacement !== 'owner'\n ? borrowSurface(attachSurface, this.targetContainer!) : undefined;\n this.markSurface(attachSurface, tabId, target.targetId);\n this.adoptPresentationSurface(attachSurface, {\n external: surfaceEntry?.surfacePlacement === 'owner',\n });\n\n const entry: PresentationEntry = {\n target,\n targetId: String(target.targetId),\n surface: attachSurface,\n presentation,\n surfacePlacement: surfaceEntry?.surfacePlacement ?? 'shell',\n generation,\n remove: undefined,\n restore,\n };\n this.presentationByTab.set(tabId, entry);\n try {\n const remove = await presentation.attach?.({ target: target as EngineWorkspaceTarget, element: attachSurface, tabId });\n if (typeof remove === 'function') entry.remove = remove;\n if (\n this.presentationByTab.get(tabId) !== entry ||\n entry.generation !== this.presentationGenerationByTab.get(tabId) ||\n this.disposed\n ) {\n await this.releasePresentationEntry(tabId, entry);\n return;\n }\n entry.ready = true;\n this.setActiveSurface();\n this.render({ chromeChanged: false });\n } catch (error) {\n await this.releasePresentationEntry(tabId, entry).catch(() => {});\n // Keep this identity failed until an explicit target transition. Error\n // rendering must not recursively retry and re-adopt the returned node.\n entry.remove = () => {};\n entry.ready = false;\n this.presentationByTab.set(tabId, entry);\n throw error;\n }\n });\n const pendingEntry = { target, generation, surface, task };\n this.presentationPending.set(tabId, pendingEntry);\n void task.then(\n () => {\n if (this.presentationPending.get(tabId) === pendingEntry) this.presentationPending.delete(tabId);\n },\n (error) => {\n if (this.presentationPending.get(tabId) === pendingEntry) this.presentationPending.delete(tabId);\n this.fail(error);\n },\n );\n }\n\n markSurface(surface: HTMLElement, tabId: string, targetId: string) {\n surface.dataset.forgeaxViewTargetId = String(targetId);\n surface.dataset.forgeaxViewTabId = tabId;\n surface.dataset.forgeaxViewSurface = tabId === VIEW_DISPLAY_TAB_ID ? 'engine-target' : 'engine-canvas';\n surface.setAttribute?.('aria-label', `Engine target ${targetId}`);\n }\n\n enqueuePresentation(tabId: string, operation: () => Promise<void>) {\n const previous = this.presentationQueueByTab.get(tabId) ?? Promise.resolve();\n const task = previous.catch(() => {}).then(operation);\n this.presentationQueueByTab.set(tabId, task);\n void task.then(\n () => {\n if (this.presentationQueueByTab.get(tabId) === task) this.presentationQueueByTab.delete(tabId);\n },\n () => {\n if (this.presentationQueueByTab.get(tabId) === task) this.presentationQueueByTab.delete(tabId);\n },\n );\n return task;\n }\n\n async runPresentationCleanup(remove: void | Dispose) {\n if (typeof remove === 'function') await Promise.resolve(remove());\n }\n\n async releaseUnattachedPresentation({ presentation, target, surface, tabId }: { presentation: WorkspacePresentation; target: WorkspaceTarget; surface: HTMLElement; tabId: string }) {\n if (this.presentationByTab.get(tabId)?.surface === surface) return;\n if (typeof presentation?.detach === 'function') {\n await Promise.resolve(presentation.detach({ target: target as EngineWorkspaceTarget, element: surface, tabId })).catch(() => {});\n return;\n }\n if (typeof presentation?.attach === 'function') {\n const remove = await presentation.attach({ target: target as EngineWorkspaceTarget, element: surface, tabId });\n await this.runPresentationCleanup(remove);\n }\n }\n\n adoptPresentationSurface(surface: HTMLElement, { external = false } = {}) {\n if (external || !surface || !this.targetContainer) return;\n if (surface.parentNode !== this.targetContainer) this.targetContainer.append?.(surface);\n }\n\n async releasePresentationEntry(tabId: string, entry: PresentationEntry) {\n if (this.presentationByTab.get(tabId) === entry) this.presentationByTab.delete(tabId);\n entry.restore?.();\n let failure;\n if (entry.remove) {\n try {\n await this.runPresentationCleanup(entry.remove);\n } catch (error) {\n failure = error;\n }\n }\n if (!entry.remove || failure !== undefined) {\n try {\n await Promise.resolve(\n entry.presentation?.detach?.({ target: entry.target as EngineWorkspaceTarget, element: entry.surface, tabId }),\n );\n } catch (error) {\n failure ??= error;\n }\n }\n if (failure !== undefined) throw failure;\n }\n\n async detachTargetPresentation(tabId: string, { invalidate = true } = {}) {\n if (invalidate) {\n this.presentationGenerationByTab.set(\n tabId,\n (this.presentationGenerationByTab.get(tabId) ?? 0) + 1,\n );\n }\n return this.enqueuePresentation(tabId, async () => {\n const entry = this.presentationByTab.get(tabId);\n if (entry) await this.releasePresentationEntry(tabId, entry);\n });\n }\n\n ensureDom() {\n if (!this.element || !this.document) return false;\n if (this.rootElement) return true;\n\n const root = this.document.createElement('div');\n root.dataset.forgeaxViewWorkspace = 'root';\n this.rootElement = root;\n\n this.tabsElement = this.document.createElement('nav');\n this.tabsElement.dataset.forgeaxViewWorkspace = 'tabs';\n this.projectElement = this.document.createElement('div');\n this.projectElement.dataset.forgeaxViewWorkspace = 'project';\n this.workbenchElement = this.document.createElement('div');\n this.workbenchElement.dataset.forgeaxViewWorkspace = 'workbench';\n const rail = this.document.createElement('div');\n rail.dataset.forgeaxViewWorkspace = 'rail';\n this.assetsElement = this.document.createElement('ul');\n this.assetsElement.dataset.forgeaxViewWorkspace = 'assets';\n rail.append?.(this.assetsElement);\n this.previewElement = this.document.createElement('div');\n this.previewElement.dataset.forgeaxViewWorkspace = 'preview';\n this.previewInfoElement = this.document.createElement('div');\n this.previewInfoElement.dataset.forgeaxViewWorkspace = 'preview-info';\n this.targetContainer = this.document.createElement('div');\n this.targetContainer.dataset.forgeaxViewWorkspace = 'targets';\n if (this.targetContainer.style) this.targetContainer.style.position = 'relative';\n this.previewElement.append?.(...(this.presentationOnly ? [] : [this.previewInfoElement]), this.targetContainer);\n this.inspectorElement = this.document.createElement('aside');\n this.inspectorElement.dataset.forgeaxViewWorkspace = 'inspector';\n this.inspectorInfoElement = this.document.createElement('div');\n this.inspectorInfoElement.dataset.forgeaxViewWorkspace = 'inspector-info';\n this.inspectorFieldsElement = this.document.createElement('div');\n this.inspectorFieldsElement.dataset.forgeaxViewWorkspace = 'inspector-fields';\n this.inspectorActionsElement = this.document.createElement('div');\n this.inspectorActionsElement.dataset.forgeaxViewWorkspace = 'inspector-actions';\n this.inspectorElement.append?.(\n this.inspectorInfoElement,\n this.inspectorFieldsElement,\n this.inspectorActionsElement,\n );\n this.workbenchElement.append?.(\n ...(this.presentationOnly ? [] : [rail]),\n this.previewElement,\n ...(this.inspectorPanel ? [this.inspectorElement] : []),\n );\n if (!this.presentationOnly) {\n this.errorElement = this.document.createElement('div');\n this.errorElement.dataset.forgeaxViewWorkspace = 'error';\n this.errorElement.setAttribute?.('role', 'alert');\n }\n root.append?.(\n ...(this.presentationOnly ? [] : [this.tabsElement, this.projectElement]),\n this.workbenchElement,\n ...(this.errorElement ? [this.errorElement] : []),\n );\n if (root.parentNode !== this.element) this.element.append?.(root);\n this.stopSceneAdopt = keepSurfaceInContainer({\n document: this.document,\n getContainer: () => (this.disposed ? null : this.targetContainer),\n getSurface: () => readSceneShell(this.document),\n onPlace: (surface) => {\n if (!surface?.style) return;\n Object.assign(surface.style, {\n width: '100%',\n height: '100%',\n maxWidth: '100%',\n maxHeight: '100%',\n position: 'relative',\n transform: 'none',\n overflow: 'hidden',\n });\n },\n });\n traceShellRegisterDomRoot(root);\n return true;\n }\n\n syncTargetSurfaces() {\n const surfaces = this.targetContainer;\n if (!surfaces) return;\n let removed = 0;\n let reordered = 0;\n const desired: Element[] = [];\n for (const tabId of [VIEW_DISPLAY_TAB_ID, VIEW_WORKSPACE_TAB_ID]) {\n const entry = this.surfaceByTab.get(tabId);\n // An exact surface with no target is a detach-draining tombstone. It\n // must not be presented or reattached until the next target adopts it.\n if (!entry || !entry.targetId || !entry.target) continue;\n this.attachTargetPresentation(tabId, entry.target, entry.surface);\n const attached = this.presentationByTab.get(tabId);\n // Render cannot move an exact node ahead of the serialized cleanup.\n if (entry.exactSurface && (!attached?.ready || !sameTargetIdentity(attached.target, entry.target))) continue;\n const selected = this.state.selectedTabId === tabId &&\n !(tabId === VIEW_WORKSPACE_TAB_ID && this.state.targetBinding === 'play');\n // The borrowed CLI carrier stays active across tab changes. Workspace\n // previews can stop background rendering when their presentation is hidden.\n if (entry.exactSurface && tabId === VIEW_DISPLAY_TAB_ID) {\n if (entry.surface.hidden !== false) entry.surface.hidden = false;\n if (entry.surface.style) {\n const visibility = selected ? 'visible' : 'hidden';\n const pointerEvents = selected ? 'auto' : 'none';\n if (entry.surface.style.visibility !== visibility) entry.surface.style.visibility = visibility;\n if (entry.surface.style.pointerEvents !== pointerEvents) entry.surface.style.pointerEvents = pointerEvents;\n }\n } else {\n const hidden = !selected;\n if (entry.surface.hidden !== hidden) entry.surface.hidden = hidden;\n if (entry.surface.style) {\n const display = selected ? '' : 'none';\n if (entry.surface.style.display !== display) entry.surface.style.display = display;\n }\n }\n const selectedMark = selected ? 'true' : 'false';\n if (entry.surface.dataset.forgeaxViewSelected !== selectedMark) {\n entry.surface.dataset.forgeaxViewSelected = selectedMark;\n }\n if (entry.surfacePlacement !== 'owner') desired.push(entry.surface);\n }\n\n for (const child of [...(surfaces.children ?? [])]) {\n if (!desired.includes(child)) {\n if (child?.id === 'app-shell') continue;\n if ([...this.presentationByTab.values()].some(entry => entry.surface === child)) continue;\n child.remove?.();\n removed += 1;\n }\n }\n for (let index = 0; index < desired.length; index += 1) {\n const surface = desired[index];\n if (surfaces.children?.[index] === surface) continue;\n reordered += 1;\n const before = surfaces.children?.[index] ?? null;\n if (surfaces.insertBefore) surfaces.insertBefore(surface, before);\n else surfaces.append?.(surface);\n }\n traceSyncTargetSurfaces({ removed, reordered, desired: desired.length });\n }\n\n render({ chromeChanged = true } = {}) {\n if (this.disposed || !this.element || !this.document) return;\n const renderStarted = isViewTraceEnabled() ? performance.now() : 0;\n const workspaceTarget = this.targetForTab(VIEW_WORKSPACE_TAB_ID);\n const displayTarget = this.targetForTab(VIEW_DISPLAY_TAB_ID);\n this.ensureSurface(VIEW_WORKSPACE_TAB_ID, workspaceTarget);\n this.ensureSurface(VIEW_DISPLAY_TAB_ID, displayTarget);\n this.setActiveSurface();\n const nextTargetId = workspaceTarget?.targetId ?? null;\n const workspaceSurfaceEntry = this.surfaceByTab.get(VIEW_WORKSPACE_TAB_ID);\n if (nextTargetId !== this.inputTargetId || workspaceTarget?.generation !== this.inputTargetGeneration ||\n workspaceSurfaceEntry?.surface !== this.inputSurface) {\n this.detachInput('target-replaced');\n this.removeInput?.();\n this.removeInput = undefined;\n this.inputController = undefined;\n this.inputTargetId = nextTargetId;\n this.inputTargetGeneration = workspaceTarget?.generation;\n this.inputSurface = workspaceSurfaceEntry?.surface;\n }\n if (!this.ensureDom()) return;\n let domReplaceChildren = 0;\n const tabs = this.tabsElement;\n const project = this.projectElement;\n const assets = this.assetsElement;\n const previewInfo = this.previewInfoElement;\n const inspectorInfo = this.inspectorInfoElement;\n const inspectorFields = this.inspectorFieldsElement;\n const inspectorActions = this.inspectorActionsElement;\n const error = this.errorElement;\n if (chromeChanged) {\n if (tabs?.replaceChildren) {\n tabs.replaceChildren();\n domReplaceChildren += 1;\n }\n for (const tab of this.state.tabs ?? []) {\n tabs?.append?.(\n button(this.document, `${tab.kind}: ${tab.tabId}`, () => this.selectTab(tab.tabId), {\n disabled: tab.selected === true,\n }),\n );\n }\n if (project?.replaceChildren) {\n project.replaceChildren();\n domReplaceChildren += 1;\n }\n if (this.state.project) {\n project?.append?.(text(this.document, `Project: ${this.state.project.name ?? this.state.project.id}`));\n project?.append?.(button(this.document, 'Refresh assets', () => this.refreshAssets()));\n project?.append?.(button(this.document, 'Close project', () => this.closeProject()));\n } else {\n project?.append?.(\n text(this.document, 'Project opens from the View owner process.'),\n );\n }\n if (this.state.workspaceTargetLost && this.state.project?.root) {\n const reconnectLabel = this.state.projectReconnecting ? 'Reconnecting project\u2026' : 'Reconnect project';\n project?.append?.(\n button(this.document, reconnectLabel, () => this.reconnectProject(), {\n disabled: this.state.projectReconnecting === true,\n }),\n );\n }\n if (assets?.replaceChildren) {\n assets.replaceChildren();\n domReplaceChildren += 1;\n }\n for (const group of groupAssetsBySource(this.state.assets)) {\n const item = this.document.createElement('li');\n item.dataset.forgeaxViewWorkspace = 'asset-group';\n item.dataset.sourcePath = group.key;\n item.append?.(text(this.document, group.key));\n const members = this.document.createElement('ul');\n for (const asset of group.assets) {\n const member = this.document.createElement('li');\n member.dataset.forgeaxViewWorkspace = 'asset';\n member.dataset.guid = asset.guid;\n member.dataset.kind = asset.kind;\n if (asset.sourceKind) member.dataset.sourceKind = asset.sourceKind;\n const ddcState = catalogDdcState(asset, this.state.inspection);\n const receipt = catalogReceipt(asset, this.state.inspection);\n if (ddcState) member.dataset.ddcState = ddcState;\n if (receipt) member.dataset.cookReceiptUrl = receipt;\n const selected = this.state.inspection?.guid === asset.guid;\n const label = `${asset.name ?? asset.guid} (${asset.kind}${ddcState ? ` \u00B7 ${ddcState}` : ''})`;\n member.append?.(\n button(this.document, label, () => this.selectAsset(asset.guid), {\n disabled: selected,\n }),\n );\n members.append?.(member);\n }\n item.append?.(members);\n assets?.append?.(item);\n }\n if (previewInfo?.replaceChildren) {\n previewInfo.replaceChildren();\n domReplaceChildren += 1;\n }\n if (this.state.preview) {\n previewInfo?.append?.(\n text(this.document, `Target: ${this.state.preview.asset?.name ?? this.state.preview.asset?.guid ?? 'Game'}`),\n ...(this.state.preview.asset ? [button(this.document, 'Close preview', () => this.closePreview())] : []),\n );\n } else {\n previewInfo?.append?.(text(this.document, 'No asset preview open'));\n }\n if (inspectorInfo?.replaceChildren) {\n inspectorInfo.replaceChildren();\n domReplaceChildren += 1;\n }\n if (inspectorFields?.replaceChildren) {\n inspectorFields.replaceChildren();\n domReplaceChildren += 1;\n }\n if (inspectorActions?.replaceChildren) {\n inspectorActions.replaceChildren();\n domReplaceChildren += 1;\n }\n const inspection = this.state.inspection;\n if (this.state.inspectorError) {\n inspectorInfo?.append?.(text(this.document, `Inspector: ${this.state.inspectorError}`));\n } else if (inspection) {\n inspectorInfo?.append?.(\n text(\n this.document,\n `${inspection.asset?.name ?? inspection.guid} \u00B7 ${inspection.source?.kind ?? inspection.asset?.sourceKind ?? inspection.asset?.kind} \u00B7 ${inspection.source?.path ?? inspection.asset?.sourcePath ?? ''}${inspection.revision ? ` \u00B7 rev ${inspection.revision.slice(0, 12)}` : ''}${inspection.ddc?.receiptUrl ? ` \u00B7 ${inspection.ddc.receiptUrl}` : ''}`,\n ),\n );\n const meta = inspection.meta;\n if (meta) {\n const identity = this.document.createElement('div');\n identity.dataset.forgeaxViewWorkspace = 'pack-meta';\n identity.append?.(\n text(\n this.document,\n `${meta.packageId ?? ''} \u00B7 ${meta.importer ?? ''} \u00B7 ${meta.source ?? ''}`,\n ),\n );\n inspectorFields?.append?.(identity);\n for (const sub of (meta.subAssets as readonly { guid: string; kind: string; name?: string; sourceKey?: string }[] | undefined) ?? []) {\n const row = this.document.createElement('div');\n row.dataset.forgeaxViewWorkspace = 'sub-asset';\n row.dataset.guid = sub.guid;\n row.dataset.kind = sub.kind;\n row.append?.(text(this.document, `${sub.name ?? sub.sourceKey} (${sub.kind})`));\n inspectorFields?.append?.(row);\n }\n }\n inspectorActions?.append?.(\n button(this.document, 'Rebuild', () => this.cookSelected('rebuild')),\n button(this.document, 'Cold-cook', () => this.cookSelected('cold-cook')),\n );\n } else {\n inspectorInfo?.append?.(text(this.document, 'Select an asset to inspect Engine catalog and pack meta'));\n }\n }\n this.syncTargetSurfaces();\n const nextError = this.state.error ? `Error: ${this.state.error}` : '';\n const nextHidden = !this.state.error;\n if (error) {\n if (error.hidden !== nextHidden) error.hidden = nextHidden;\n if (error.textContent !== nextError) error.textContent = nextError;\n }\n const workspaceSurface = this.surfaceByTab.get(VIEW_WORKSPACE_TAB_ID)?.surface;\n if (\n nextTargetId &&\n workspaceSurface &&\n this.api &&\n this.removeInput === undefined &&\n (!workspaceSurfaceEntry?.exactSurface ||\n (this.presentationByTab.get(VIEW_WORKSPACE_TAB_ID)?.ready &&\n sameTargetIdentity(this.presentationByTab.get(VIEW_WORKSPACE_TAB_ID)?.target, workspaceTarget))) &&\n this.state.selectedTabId === VIEW_WORKSPACE_TAB_ID\n ) {\n this.inputController = this.inputControllerFactory({\n api: this.api,\n targetId: nextTargetId,\n targetGeneration: workspaceTarget?.generation,\n tabId: VIEW_WORKSPACE_TAB_ID,\n window: this.window,\n document: this.document,\n onError: (error) => this.fail(error),\n onSpeedChange: this.onNavigationSpeed,\n onFocusSelection: () => {\n const selected = this.state.sceneSelection;\n if (selected?.primary?.entityId) return this.api?.call('entity.focus', {\n entityId: selected.primary.entityId, targetId: nextTargetId, targetGeneration: workspaceTarget?.generation,\n });\n },\n shouldCapture: (event) => isViewportWorkspaceInputEvent(event, { surface: workspaceSurface, host: this.element }),\n });\n this.removeInput = this.inputController.attach(workspaceSurface);\n }\n traceShellRender({\n durationMs: renderStarted ? Math.round((performance.now() - renderStarted) * 100) / 100 : undefined,\n workspaceSurface: workspaceSurface?.dataset?.forgeaxViewSurface,\n exactSurface: this.surfaceByTab.get(VIEW_WORKSPACE_TAB_ID)?.exactSurface,\n inputBound: this.removeInput !== undefined,\n presentationOnly: this.presentationOnly,\n domReplaceChildren,\n tabCount: (this.state.tabs ?? []).length,\n assetCount: (this.state.assets ?? []).length,\n });\n }\n\n /** Detach local DOM listeners before a tab/target/disconnect transition. */\n detachInput(reason: string = 'input-detached') {\n const controller = this.inputController;\n const remove = this.removeInput;\n this.removeInput = undefined;\n this.inputController = undefined;\n if (remove) {\n remove(reason);\n }\n if (!remove?.handlesAbort) {\n void Promise.resolve(controller?.abort?.(reason)).catch((error) => this.fail(error));\n }\n }\n\n dispose() {\n if (this.disposal) return this.disposal;\n this.disposed = true;\n this.stopSceneAdopt?.();\n this.stopSceneAdopt = undefined;\n // Parent panels may disappear before asynchronous input/adapter cleanup.\n // Pending tasks see disposed and cannot adopt another borrowed node.\n for (const entry of this.presentationByTab.values()) entry.restore?.();\n this.disposal = this.finishDisposal();\n return this.disposal;\n }\n\n async finishDisposal() {\n const removeInput = this.removeInput;\n const inputController = this.inputController;\n this.removeInput = undefined;\n removeInput?.('input-disposed');\n const inputDisposal = inputController?.dispose?.().catch(() => {});\n this.inputController = undefined;\n this.removeSubscription?.();\n this.removeSubscription = undefined;\n this.removeDisconnect?.();\n this.removeDisconnect = undefined;\n const presentationTabs = new Set([\n ...this.surfaceByTab.keys(),\n ...this.presentationByTab.keys(),\n ...this.presentationPending.keys(),\n ...this.presentationQueueByTab.keys(),\n ]);\n for (const tabId of presentationTabs) {\n this.presentationGenerationByTab.set(\n tabId,\n (this.presentationGenerationByTab.get(tabId) ?? 0) + 1,\n );\n }\n await Promise.all([\n inputDisposal,\n ...[...presentationTabs].map((tabId) => this.detachTargetPresentation(tabId, { invalidate: false }).catch(() => {})),\n ]);\n this.presentationPending.clear();\n this.presentationQueueByTab.clear();\n this.presentationGenerationByTab.clear();\n this.surfaceByTab.clear();\n this.rootElement = null;\n this.targetContainer = null;\n this.removeSurfacePresentation = undefined;\n this.inputTargetId = null;\n this.surfaceTargetId = null;\n this.presentedTargetId = null;\n this.surface = null;\n this.element?.remove?.();\n this.element = null;\n }\n}\n\nexport { VIEW_DISPLAY_TAB_ID, VIEW_WORKSPACE_TAB_ID };\n"],
4
+ "sourcesContent": ["import type { EngineWorkspaceCameraResult, EngineWorkspacePresentation, EngineWorkspaceTarget } from '@forgeax/engine/app';\nimport type { ViewWorkspaceClient } from '@forgeax/view-workspace-core/client';\nimport type { WorkspaceTarget, WorkspaceState, WorkspaceAsset, WorkspaceInspection } from '@forgeax/view-workspace-core/contract';\nimport type { Dispose } from '@forgeax/view-workspace-core/frontend-contract';\n\ntype WorkspacePresentation = EngineWorkspacePresentation & { workspace?: EngineWorkspacePresentation; display?: EngineWorkspacePresentation };\ntype DisplayTarget = WorkspaceTarget & { surfaceId?: string; leaseId?: string };\ntype NavigationMode = 'look' | 'orbit' | 'pan' | 'dolly';\ntype CameraMotion = { type: NavigationMode | 'move'; mode?: string; yaw?: number; pitch?: number; x?: number; y?: number; amount?: number; distance?: number; pitchLimit?: number; velocity?: number[] };\ntype CameraSample = { type: 'key-down' | 'key-up'; mode?: never; code?: string; key: string } | { type: 'wheel'; mode: 'speed' | 'dolly'; deltaY: number } | { type: 'pointer-move'; mode: NavigationMode; movementX: number; movementY: number };\ntype CameraInteraction = EngineWorkspaceCameraResult & { interactionId: string; baseVersion: number };\nexport type WorkspaceInputOptions = {\n api: ViewWorkspaceClient; targetId: string; targetGeneration?: number; tabId?: string;\n interactionIdFactory?: () => string; shouldCapture?: (event: Event) => boolean;\n onError?: (error: unknown) => void; onFocusSelection?: () => unknown; onSpeedChange?: (speed: number) => void;\n window?: Window | typeof globalThis; document?: Document;\n};\ntype RemoveInput = ((reason?: string) => void) & { handlesAbort?: boolean };\ntype ShellState = WorkspaceState & { assets: readonly WorkspaceAsset[]; inspectorError: string | null; error: string | null; projectOpening: boolean; projectReconnecting: boolean };\ntype SurfaceEntry = { targetId: string | null; target: WorkspaceTarget | null; exactSurface: boolean; surfacePlacement: 'owner' | 'shell'; reacquire: boolean; surface: HTMLElement };\ntype PresentationEntry = { target: WorkspaceTarget; targetId: string; surface: HTMLElement; presentation: WorkspacePresentation; surfacePlacement: 'owner' | 'shell'; generation: number; remove?: Dispose; restore?: Dispose; ready?: boolean };\nexport type WorkspaceShellOptions = {\n document?: Document; window?: Window | typeof globalThis; mountId?: string; element?: HTMLElement;\n api?: ViewWorkspaceClient; presentation?: WorkspacePresentation; resourceBrowser?: boolean; presentationOnly?: boolean; inspectorPanel?: boolean;\n onNavigationSpeed?: (speed: number) => void; inputControllerFactory?: (options: WorkspaceInputOptions) => ViewWorkspaceInputController;\n};\nimport { reportWorkspaceCommandError, workspaceDiagnosticRecord } from '@forgeax/view-workspace-core/command-error';\nimport {\n VIEW_DISPLAY_TAB_ID,\n VIEW_WORKSPACE_TAB_ID,\n cloneWorkspaceValue,\n requireWorkspaceString,\n workspaceUiFingerprint,\n} from '@forgeax/view-workspace-core/contract';\nimport { createWorkspaceId } from '@forgeax/view-workspace-core/id';\nimport { reopenWorkspaceProject } from '@forgeax/view-workspace-core/workspace-recovery';\nimport { PAGE_TYPE } from './identity.ts';\nimport { selectWorkspaceEditorSurfaceTarget } from '@forgeax/view-workspace-core/resource-open';\nimport { borrowSurface, keepSurfaceInContainer, readSceneShell } from '@forgeax/view-workspace-core/adopt-surface';\nimport {\n isViewTraceEnabled,\n traceInputAttach,\n traceInputCaptureAbort,\n traceInputPointerDown,\n traceInputPointerLockExit,\n traceInputPointerMove,\n traceInputPointerUp,\n tracePresentationAttach,\n traceShellRegisterDomRoot,\n traceShellRender,\n traceShellUpdate,\n traceSyncTargetSurfaces,\n traceView,\n} from '@forgeax/view-workspace-core/view-trace';\n\nfunction sameTargetIdentity(left: DisplayTarget | null | undefined, right: DisplayTarget | null | undefined) {\n return left?.targetId === right?.targetId && left?.generation === right?.generation &&\n left?.surfaceId === right?.surfaceId && left?.leaseId === right?.leaseId;\n}\n\nfunction text(document: Document, value: unknown) {\n const node = document.createElement('span');\n node.textContent = String(value);\n return node;\n}\n\nfunction button(document: Document, label: string, onClick: () => unknown, { disabled = false } = {}) {\n const node = document.createElement('button');\n node.type = 'button';\n node.textContent = label;\n node.disabled = disabled;\n node.addEventListener?.('click', () => void Promise.resolve(onClick()).catch(() => {}));\n return node;\n}\n\nfunction safeError(error: unknown) {\n const failure = error !== null && typeof error === 'object' ? error as { message?: string; hint?: unknown } : undefined;\n const message = failure?.message ?? String(error);\n const hint = typeof failure?.hint === 'string' ? failure.hint.trim() : '';\n return hint && !message.includes(hint) ? `${message} (${hint})` : message;\n}\n\nfunction groupAssetsBySource(assets: readonly WorkspaceAsset[] | null | undefined) {\n const groups: { key: string; assets: WorkspaceAsset[] }[] = [];\n const index = new Map<string, { key: string; assets: WorkspaceAsset[] }>();\n for (const asset of assets ?? []) {\n const key = asset.sourcePath || asset.path || asset.kind || 'assets';\n let group = index.get(key);\n if (!group) {\n group = { key, assets: [] };\n index.set(key, group);\n groups.push(group);\n }\n group.assets.push(asset);\n }\n return groups;\n}\n\nfunction catalogDdcState(asset: WorkspaceAsset, inspection?: WorkspaceInspection | null) {\n if (inspection?.guid === asset?.guid && inspection.ddc?.state) return inspection.ddc.state;\n return asset?.ddc?.state;\n}\n\nfunction catalogReceipt(asset: WorkspaceAsset, inspection?: WorkspaceInspection | null) {\n if (inspection?.guid === asset?.guid && inspection.ddc?.receiptUrl) return inspection.ddc.receiptUrl;\n return asset?.cookReceiptUrl ?? asset?.ddc?.receiptUrl;\n}\n\n/** Viewport camera capture stays on the Editor page canvas, never a sibling tab preview. */\nexport function isViewportWorkspaceInputEvent(event: Event, { surface, host }: { surface?: HTMLElement; host?: HTMLElement | null } = {}) {\n const eventTarget = event?.target as Element | null;\n if (event?.defaultPrevented || !eventTarget || typeof eventTarget.closest !== 'function') return false;\n if (eventTarget.closest('button,input,a,select,textarea,[contenteditable=\"true\"],.fx-engine-fatal-banner')) return false;\n const page = (host ?? eventTarget).closest?.('[data-forgeax-view-dock-page]');\n if (page?.getAttribute?.('aria-hidden') === 'true') return false;\n if (surface) {\n const activePage = host?.ownerDocument?.documentElement?.dataset?.forgeaxViewActivePage;\n if (activePage !== undefined && activePage !== PAGE_TYPE) return false;\n if (surface.style?.visibility === 'hidden' || surface.style?.pointerEvents === 'none') return false;\n return eventTarget === surface || surface.contains?.(eventTarget) === true;\n }\n if (!eventTarget.closest('[data-forgeax-view-mount-host=\"viewport\"]')) return false;\n return Boolean(eventTarget.closest('[data-forgeax-view-workspace=\"preview\"]'));\n}\n\n/**\n * Bind the CLI display tab to the iframe allocated by BrowserPagePlatform.\n * The platform owns that node and its browsing context; the workspace only\n * changes visibility and input affordances. In particular, this adapter never\n * appends, reorders, or removes the iframe because moving a live iframe can\n * detach the exact Engine Frame held by the carrier.\n */\nexport function createBrowserPagePresentation({ document = globalThis.document }: { document?: Document } = {}): WorkspacePresentation {\n return Object.freeze<EngineWorkspacePresentation>({\n surfacePlacement: 'owner',\n createSurface({ target, document: suppliedDocument = document }: Partial<Parameters<NonNullable<EngineWorkspacePresentation['createSurface']>>[0]> = {}) {\n const displayTarget = workspaceDiagnosticRecord(target);\n const surfaceId = displayTarget.surfaceId;\n if (typeof surfaceId !== 'string' || surfaceId.length === 0) {\n throw new TypeError('Engine display target must expose its exact surfaceId');\n }\n const ownerDocument = suppliedDocument as Document;\n if (ownerDocument?.querySelectorAll === undefined) return null;\n const matches = [...ownerDocument.querySelectorAll<HTMLIFrameElement>('iframe[data-forgeax-view-surface=\"engine-target\"]')].filter(\n (element) =>\n element.dataset?.forgeaxViewSurface === 'engine-target' &&\n element.dataset?.forgeaxViewTargetId === String(displayTarget.targetId) &&\n element.dataset?.forgeaxViewLeaseId === String(displayTarget.leaseId) &&\n element.dataset?.forgeaxViewGeneration === String(displayTarget.generation) &&\n element.id === surfaceId,\n );\n if (matches.length > 1) {\n throw new Error(`multiple Engine display surfaces match ${surfaceId}`);\n }\n return matches[0] ?? null;\n },\n attach({ target, element: suppliedElement }: Partial<Parameters<NonNullable<EngineWorkspacePresentation['attach']>>[0]> = {}) {\n const element = workspaceDiagnosticRecord(suppliedElement);\n const dataset = workspaceDiagnosticRecord(element.dataset);\n const displayTarget = workspaceDiagnosticRecord(target);\n if (\n !suppliedElement ||\n typeof element.tagName !== 'string' || element.tagName.toLowerCase() !== 'iframe' ||\n element.id !== displayTarget.surfaceId ||\n dataset.forgeaxViewLeaseId !== String(displayTarget.leaseId) ||\n dataset.forgeaxViewGeneration !== String(displayTarget.generation)\n ) {\n throw new Error('Engine display surface identity does not match its target');\n }\n // Placement and lease cleanup stay with BrowserPagePlatform.\n return undefined;\n },\n });\n}\n\n/**\n * Browser-side continuous input boundary. Engine owns camera math and the\n * draft transaction; this object only samples DOM input and commits/aborts\n * through the workspace API. All event handlers consume rejected promises so\n * a blur, disconnect, or begin/finish race cannot become an unhandled error.\n */\nexport class ViewWorkspaceInputController {\n declare api: ViewWorkspaceClient;\n declare targetId: string;\n declare targetGeneration: number | undefined;\n declare tabId: string;\n declare interactionIdFactory: () => string;\n declare shouldCapture: (event: Event) => boolean;\n declare onError: (error: unknown) => void;\n declare onFocusSelection: () => unknown;\n declare onSpeedChange: (speed: number) => void;\n declare speed: number;\n declare held: Set<string>;\n declare shiftHeld: boolean;\n declare window: Window | typeof globalThis;\n declare document: Document;\n declare interaction: CameraInteraction | null;\n declare pending: Promise<void>;\n declare inputError: unknown;\n declare inputQueue: CameraMotion[];\n declare beginPromise: Promise<CameraInteraction | null> | null;\n declare finishPromise: Promise<void> | null;\n declare abortPromise?: Promise<void> | null;\n declare generation: number;\n declare cancelRequested: boolean;\n declare disposed: boolean;\n declare element: HTMLElement | null;\n declare bound: boolean;\n declare pointerLockEngaged: boolean;\n declare draining?: boolean;\n\n constructor({\n api,\n targetId,\n targetGeneration,\n tabId = VIEW_WORKSPACE_TAB_ID,\n interactionIdFactory = () => createWorkspaceId('interaction'),\n shouldCapture = () => true,\n onError = () => {},\n onFocusSelection = () => {},\n onSpeedChange = () => {},\n window = globalThis,\n document = globalThis.document,\n }: Partial<WorkspaceInputOptions> = {}) {\n if (!api) throw new TypeError('workspace input controller requires an API client');\n this.api = api;\n this.targetId = requireWorkspaceString(targetId, 'targetId');\n this.targetGeneration = targetGeneration;\n this.tabId = tabId;\n this.interactionIdFactory = interactionIdFactory;\n if (typeof this.interactionIdFactory !== 'function') {\n throw new TypeError('workspace input controller requires an interactionIdFactory');\n }\n this.shouldCapture = shouldCapture;\n this.onError = onError;\n this.onFocusSelection = onFocusSelection;\n this.onSpeedChange = onSpeedChange;\n this.speed = 4;\n this.held = new Set();\n this.shiftHeld = false;\n this.window = window;\n this.document = document;\n this.interaction = null;\n this.pending = Promise.resolve();\n this.inputError = null;\n this.inputQueue = [];\n this.beginPromise = null;\n this.finishPromise = null;\n this.generation = 0;\n this.cancelRequested = false;\n this.disposed = false;\n this.element = null;\n this.bound = false;\n // Pointer lock is an optional browser affordance. Keep a local bit so a\n // rejected request (or a browser that never grants lock to an overlay)\n // cannot be mistaken for a lock-loss transition and abort a valid\n // pointer transaction.\n this.pointerLockEngaged = false;\n }\n\n report(error: unknown) {\n if (error === undefined || error === null) return;\n this.inputError ??= error;\n try {\n this.onError(error);\n } catch {\n // Error presentation cannot change the Engine transaction.\n }\n }\n\n async begin(): Promise<CameraInteraction | null> {\n if (this.beginPromise) return this.beginPromise;\n if (this.interaction && !this.finishPromise && !this.abortPromise) return this.interaction;\n const abort = this.abortPromise;\n const finish = this.finishPromise;\n const queue = this.inputQueue;\n const generation = this.generation;\n this.cancelRequested = false;\n const begunPromise = (async () => {\n if (abort) await abort;\n if (finish) await finish;\n if (this.disposed) throw new Error('workspace input controller is disposed');\n const current = await this.api.getCamera({ targetId: this.targetId, targetGeneration: this.targetGeneration, tabId: this.tabId });\n if (this.disposed || generation !== this.generation || this.cancelRequested) {\n throw new Error('workspace input begin was cancelled');\n }\n const expectedVersion = current.version;\n if (typeof expectedVersion !== 'number' || !Number.isSafeInteger(expectedVersion) || expectedVersion < 0) {\n throw new TypeError('workspace camera begin requires getCamera().version');\n }\n const interactionId = this.interactionIdFactory();\n const begun = await this.api.beginCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n baseVersion: expectedVersion,\n interactionId,\n });\n // 0.1.33 begin returns { camera, version } only. Commit must use the\n // interactionId we sent and the version observed at begin.\n this.interaction = { ...begun, interactionId, baseVersion: expectedVersion };\n await this.flushInputQueue();\n if (this.cancelRequested || this.disposed || generation !== this.generation) {\n await this.api\n .abortCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId,\n reason: 'input-begin-cancelled',\n })\n .catch((error) => this.report(error));\n this.clearTransaction();\n throw new Error('workspace input begin was cancelled');\n }\n return this.interaction;\n })();\n this.beginPromise = begunPromise;\n try {\n return await begunPromise;\n } catch (error) {\n if (generation === this.generation && this.inputQueue === queue) this.clearTransaction();\n throw error;\n } finally {\n if (this.beginPromise === begunPromise) this.beginPromise = null;\n }\n }\n\n async flushInputQueue() {\n this.drainInputQueue();\n await this.pending;\n }\n\n enqueueUpdate(input: CameraMotion) {\n const previous = this.inputQueue.at(-1);\n if (previous?.type === input.type && previous.mode === input.mode &&\n ['look', 'orbit', 'pan', 'dolly'].includes(input.type)) {\n for (const key of ['yaw', 'pitch', 'x', 'y', 'amount'] as const) {\n if (input[key] !== undefined) previous[key] = (previous[key] ?? 0) + input[key];\n }\n } else if (this.inputQueue.length < 64) {\n this.inputQueue.push({ ...input });\n } else {\n this.report(new Error('Viewport input exceeded its bounded queue; gesture cancelled.'));\n void this.abort('input-overflow');\n return;\n }\n this.drainInputQueue();\n }\n\n drainInputQueue(interaction = this.interaction, queue = this.inputQueue) {\n if (this.finishPromise && queue === this.inputQueue) return;\n if (!interaction || this.draining) return;\n const generation = this.generation;\n this.draining = true;\n this.pending = Promise.resolve().then(async () => {\n while (queue.length) {\n if (\n generation !== this.generation ||\n this.cancelRequested ||\n this.disposed ||\n this.interaction !== interaction\n )\n return;\n const input = queue.shift();\n await this.api.updateCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId: interaction.interactionId,\n input,\n });\n if (generation !== this.generation || this.interaction !== interaction) return;\n }\n })\n .catch((error) => {\n if (generation !== this.generation || this.interaction !== interaction) return;\n this.inputError ??= error;\n this.report(error);\n })\n .finally(() => {\n this.draining = false;\n if (generation === this.generation && this.inputQueue.length) this.drainInputQueue();\n });\n }\n\n /** Current WASD/QE move sample; Shift multiplies speed like Unreal's fast-fly. */\n currentMoveInput(): CameraMotion {\n const axes = [Number(this.held.has('KeyD')) - Number(this.held.has('KeyA')),\n Number(this.held.has('KeyE')) - Number(this.held.has('KeyQ')),\n Number(this.held.has('KeyS')) - Number(this.held.has('KeyW'))];\n const length = Math.hypot(...axes) || 1;\n const boost = this.shiftHeld ? 3 : 1;\n return { type: 'move', velocity: axes.map(value => (value * this.speed * boost) / length) };\n }\n\n queueInput(input: CameraSample) {\n if (this.disposed || this.cancelRequested) return;\n const movement = () => this.currentMoveInput();\n let motion: CameraMotion;\n if (input.type === 'key-down' || input.type === 'key-up') {\n const code = input.code || 'Key' + String(input.key).toUpperCase();\n if (input.type === 'key-down') this.held.add(code);\n else this.held.delete(code);\n motion = movement();\n } else if (input.type === 'wheel' && input.mode === 'speed') {\n this.speed = Math.max(0.05, Math.min(1024, this.speed * Math.exp(-input.deltaY * 0.002)));\n this.onSpeedChange(this.speed);\n motion = movement();\n } else if (input.type === 'wheel' || input.mode === 'dolly') {\n motion = { type: 'dolly', amount: Math.max(-4, Math.min(4,\n (input.type === 'wheel' ? input.deltaY : ('movementY' in input ? input.movementY : 0) * 4) * 0.001)), distance: 5 };\n } else if (input.mode === 'pan') {\n motion = { type: 'pan', x: -(('movementX' in input ? input.movementX : 0)) * 0.002,\n y: (('movementY' in input ? input.movementY : 0)) * 0.002, distance: 5 };\n } else {\n motion = { type: input.mode === 'orbit' ? 'orbit' : 'look',\n yaw: -(('movementX' in input ? input.movementX : 0)) * 0.003, pitch: -(('movementY' in input ? input.movementY : 0)) * 0.003,\n pitchLimit: Math.PI / 2 - 0.01, distance: 5 };\n }\n this.enqueueUpdate(motion);\n }\n\n clearTransaction() {\n this.held.clear();\n this.interaction = null;\n this.pending = Promise.resolve();\n this.inputQueue = [];\n this.inputError = null;\n }\n\n async finish(): Promise<void> {\n if (this.finishPromise) {\n const finishing = this.finishPromise;\n return this.beginPromise ? finishing.then(() => this.finish()) : finishing;\n }\n const begin = this.beginPromise;\n this.beginPromise = null;\n const queue = this.inputQueue;\n this.inputQueue = [];\n this.held.clear();\n const generation = this.generation;\n let interaction;\n this.finishPromise = (async () => {\n try {\n if (begin) await begin;\n interaction = this.interaction;\n if (!interaction) return;\n await this.pending;\n this.drainInputQueue(interaction, queue);\n await this.pending;\n if (this.cancelRequested || this.disposed || generation !== this.generation) {\n await this.api.abortCamera({ targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId, interactionId: interaction.interactionId, reason: 'input-finish-cancelled' });\n return;\n }\n if (this.inputError) {\n const error = this.inputError;\n await this.api.abortCamera({ targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId, interactionId: interaction.interactionId, reason: 'input-update-failed' });\n throw error;\n }\n try {\n await this.api.commitCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId: interaction.interactionId,\n operationId: this.interactionIdFactory(),\n expectedVersion: interaction.baseVersion,\n });\n } catch (error) {\n await this.api\n .abortCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId: interaction.interactionId,\n reason: 'commit-failed',\n })\n .catch(() => {});\n throw error;\n }\n } finally {\n if (this.interaction === interaction) this.interaction = null;\n this.inputError = null;\n }\n })();\n try {\n return await this.finishPromise;\n } finally {\n this.finishPromise = null;\n }\n }\n\n async abort(reason = 'input-abort') {\n if (this.abortPromise) return this.abortPromise;\n ++this.generation;\n this.cancelRequested = true;\n const begin = this.beginPromise;\n this.abortPromise = (async () => {\n if (begin) await begin.catch(() => {});\n await this.pending;\n const interaction = this.interaction;\n try {\n if (interaction) {\n await this.api.abortCamera({\n targetId: this.targetId, targetGeneration: this.targetGeneration,\n tabId: this.tabId,\n interactionId: interaction.interactionId,\n reason,\n });\n }\n } catch (error) {\n this.report(error);\n } finally {\n this.clearTransaction();\n }\n })();\n try { await this.abortPromise; }\n finally { this.abortPromise = null; }\n }\n\n async requestPointerLock() {\n if (typeof this.element?.requestPointerLock !== 'function') return;\n try {\n await Promise.resolve(this.element.requestPointerLock());\n } catch {\n // Pointer lock is an optional browser affordance. A browser can reject\n // it for an iframe, automation event, or missing user activation while\n // ordinary pointer/keyboard samples remain valid. Do not turn that\n // presentation limitation into an Engine transaction failure.\n }\n }\n\n trySetPointerCapture(element: HTMLElement | null, pointerId?: number) {\n if (pointerId === undefined || typeof element?.setPointerCapture !== 'function') return;\n try {\n element.setPointerCapture(pointerId);\n } catch {\n // Pointer capture is best-effort. The API interaction remains the\n // authority and can continue without this browser-local optimization.\n }\n }\n\n tryReleasePointerCapture(element: HTMLElement | null, pointerId?: number) {\n if (pointerId === undefined || typeof element?.releasePointerCapture !== 'function') return;\n try {\n element.releasePointerCapture(pointerId);\n } catch {\n // The pointer may already have been cancelled or released by the\n // browser; there is no Engine state to repair here.\n }\n }\n\n attach(element: HTMLElement): RemoveInput {\n if (!element || this.bound) return () => {};\n this.element = element;\n this.bound = true;\n this.onSpeedChange(this.speed);\n const previousTabIndex = element.getAttribute?.('tabindex');\n if (previousTabIndex == null) element.setAttribute?.('tabindex', '0');\n traceInputAttach(element, { targetId: this.targetId, tabId: this.tabId });\n let gesture: { button: number; mode: NavigationMode } | null = null;\n let selectionRequest: AbortController | undefined;\n let clickStart: { x: number; y: number } | undefined;\n let consumedClick = false;\n const held = this.held;\n const stop = () => {\n selectionRequest?.abort();\n gesture = null;\n held.clear();\n this.shiftHeld = false;\n if (this.document?.pointerLockElement === element) this.document.exitPointerLock?.();\n void this.finish().catch((error) => this.report(error));\n };\n const down = (event: PointerEvent) => {\n if (this.shouldCapture(event)) element.focus?.();\n const accepted = !gesture &&\n (event.button === 2 || event.button === 1 || (event.button === 0 && event.altKey)) &&\n this.shouldCapture(event);\n consumedClick = event.defaultPrevented === true || accepted;\n clickStart = { x: event.clientX, y: event.clientY };\n traceInputPointerDown(event, { accepted, element });\n if (accepted) {\n selectionRequest?.abort();\n event.preventDefault?.();\n gesture = {\n button: event.button,\n mode: event.button === 1 ? 'pan' : event.altKey ? (event.button === 0 ? 'orbit' : 'dolly') : 'look',\n };\n element.focus?.();\n void this.begin().catch((error) => this.report(error));\n this.trySetPointerCapture(element, event?.pointerId);\n void this.requestPointerLock();\n traceView('input', 'capture-engaged', {\n pointerId: event?.pointerId,\n pointerLockElement: globalThis.document?.pointerLockElement?.tagName,\n });\n }\n };\n const menu = (event: MouseEvent) => {\n if (!this.shouldCapture(event)) return;\n event.preventDefault?.();\n };\n const move = (event: PointerEvent) => {\n if (clickStart && Math.hypot(event.clientX - clickStart.x, event.clientY - clickStart.y) > 4) consumedClick = true;\n if (!gesture || (!this.interaction && !this.beginPromise)) return;\n traceInputPointerMove(event, {\n queued: true,\n queueDepth: this.inputQueue.length,\n inFlight: this.draining ? 1 : 0,\n });\n this.queueInput({\n type: 'pointer-move',\n mode: gesture.mode,\n movementX: Number(event.movementX ?? 0),\n movementY: Number(event.movementY ?? 0),\n });\n };\n const up = (event: PointerEvent) => {\n if (!gesture || event.button !== gesture.button) return;\n this.tryReleasePointerCapture(element, event?.pointerId);\n traceInputPointerUp(event, { element });\n stop();\n };\n const keydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && gesture) { stop(); return; }\n if (!this.shouldCapture(event) || event.repeat) return;\n if (!gesture && String(event.key).toLowerCase() === 'f') {\n event.preventDefault?.();\n void Promise.resolve().then(this.onFocusSelection).catch(error => this.report(error));\n return;\n }\n // Unreal-style: Shift only boosts speed while navigation keys are held.\n if (event.key === 'Shift') {\n this.shiftHeld = true;\n if (held.size) this.enqueueUpdate(this.currentMoveInput());\n return;\n }\n // WASD/QE move with or without the RMB look gesture.\n if (!['w', 'a', 's', 'd', 'q', 'e'].includes(String(event.key ?? '').toLowerCase())) return;\n event.preventDefault?.();\n held.add(event.code || event.key);\n if (!gesture) void this.begin().catch((error) => this.report(error));\n this.queueInput({ type: 'key-down', key: String(event.key ?? ''), code: String(event.code ?? '') });\n };\n const keyup = (event: KeyboardEvent) => {\n if (event.key === 'Shift') {\n this.shiftHeld = false;\n if (held.size) this.enqueueUpdate(this.currentMoveInput());\n return;\n }\n if (!held.delete(event.code || event.key)) return;\n if (!this.interaction && !this.beginPromise) return;\n event.preventDefault?.();\n this.queueInput({ type: 'key-up', key: String(event.key ?? ''), code: String(event.code ?? '') });\n // Bare keys own no pointer gesture: commit the camera transaction once\n // every navigation key is released instead of leaking an open draft.\n if (!gesture && held.size === 0) void this.finish().catch((error) => this.report(error));\n };\n const wheel = (event: WheelEvent) => {\n if (!this.shouldCapture(event) || this.finishPromise) return;\n selectionRequest?.abort();\n event.preventDefault?.();\n void this.begin().catch((error) => this.report(error));\n this.queueInput({ type: 'wheel', mode: gesture?.mode === 'look' ? 'speed' : 'dolly',\n deltaY: Number(event.deltaY ?? 0) * (event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? 800 : 1) });\n if (!gesture) void this.finish().catch((error) => this.report(error));\n };\n const abort = (reason = 'input-focus-lost') => {\n if (reason !== 'pointerlock-exit') traceInputCaptureAbort(reason);\n else traceView('input', 'abort', { reason });\n stop();\n };\n const pointerLockChange = () => {\n const locked = this.document?.pointerLockElement === element;\n traceView('input', 'pointerlockchange', {\n locked,\n pointerLockElement: this.document?.pointerLockElement?.tagName,\n engaged: this.pointerLockEngaged,\n });\n if (locked) this.pointerLockEngaged = true;\n if (this.pointerLockEngaged && !locked) {\n this.pointerLockEngaged = false;\n traceInputPointerLockExit({ locked, element });\n abort('pointerlock-exit');\n }\n };\n const click = (event: MouseEvent) => {\n const consumed = consumedClick;\n consumedClick = false;\n const dragged = clickStart && Math.hypot(event.clientX - clickStart.x, event.clientY - clickStart.y) > 4;\n clickStart = undefined;\n if (consumed || dragged) return;\n if (gesture || event.button !== 0 || event.altKey || !this.shouldCapture(event)) return;\n const canvas = element.tagName === 'CANVAS' ? element as HTMLCanvasElement : element.querySelector?.('canvas');\n if (!canvas || event.target !== canvas) return;\n const rect = canvas.getBoundingClientRect();\n if (!(rect.width > 0 && rect.height > 0 && canvas.width > 0 && canvas.height > 0)) return;\n selectionRequest?.abort();\n selectionRequest = new AbortController();\n // The shared client reports failures; a failed query never enters the camera transaction.\n void this.api.call('scene.pick', {\n targetId: this.targetId, targetGeneration: this.targetGeneration, tabId: this.tabId,\n x: (event.clientX - rect.left) * canvas.width / rect.width,\n y: (event.clientY - rect.top) * canvas.height / rect.height,\n }, { signal: selectionRequest.signal }).catch(() => {});\n };\n element.addEventListener?.('click', click);\n element.addEventListener?.('pointerdown', down);\n element.addEventListener?.('pointermove', move);\n element.addEventListener?.('pointerup', up);\n element.addEventListener?.('wheel', wheel, { passive: false });\n element.addEventListener?.('contextmenu', menu);\n const onPointerCancel = () => abort('pointercancel');\n const onWindowBlur = () => abort('window-blur');\n const onFocusOut = (event: FocusEvent) => { if (!element.contains?.(event.relatedTarget as Node | null)) abort('focusout'); };\n const onVisibilityChange = () => { if (this.document?.hidden) abort('visibilitychange'); };\n element.addEventListener?.('pointercancel', onPointerCancel);\n element.addEventListener?.('keydown', keydown);\n this.window?.addEventListener?.('keyup', keyup);\n this.window?.addEventListener?.('pointerup', up);\n this.window?.addEventListener?.('blur', onWindowBlur);\n this.window?.addEventListener?.('focusout', onFocusOut);\n this.document?.addEventListener?.('visibilitychange', onVisibilityChange);\n this.document?.addEventListener?.('pointerlockchange', pointerLockChange);\n const remove = (reason = 'input-detached') => {\n if (previousTabIndex == null) element.removeAttribute?.('tabindex');\n selectionRequest?.abort();\n element.removeEventListener?.('click', click);\n element.removeEventListener?.('pointerdown', down);\n element.removeEventListener?.('pointermove', move);\n element.removeEventListener?.('pointerup', up);\n element.removeEventListener?.('wheel', wheel);\n element.removeEventListener?.('contextmenu', menu);\n element.removeEventListener?.('pointercancel', onPointerCancel);\n element.removeEventListener?.('keydown', keydown);\n this.window?.removeEventListener?.('keyup', keyup);\n this.window?.removeEventListener?.('pointerup', up);\n this.window?.removeEventListener?.('blur', onWindowBlur);\n this.window?.removeEventListener?.('focusout', onFocusOut);\n this.document?.removeEventListener?.('visibilitychange', onVisibilityChange);\n this.document?.removeEventListener?.('pointerlockchange', pointerLockChange);\n this.pointerLockEngaged = false;\n if (reason !== 'input-disposed') {\n traceInputCaptureAbort(reason);\n void this.abort(reason).catch((error) => this.report(error));\n }\n this.element = null;\n this.bound = false;\n };\n remove.handlesAbort = true;\n return remove;\n }\n\n dispose() {\n this.disposed = true;\n return this.abort('input-disposed');\n }\n}\n\n/** Stable exact Engine surfaces; all state and controls use the workspace API.\n * Without a presentation adapter, retain an inert surface. Editor Play owns its\n * one iframe in a separate plugin; an arbitrary target URL never creates one.\n */\nexport class ViewWorkspaceShell {\n declare document: Document;\n declare window: Window | typeof globalThis;\n declare mountId: string;\n declare api: ViewWorkspaceClient | undefined;\n declare presentation: WorkspacePresentation | undefined;\n declare resourceBrowser: boolean;\n declare presentationOnly: boolean;\n declare inspectorPanel: boolean;\n declare inputControllerFactory: (options: WorkspaceInputOptions) => ViewWorkspaceInputController;\n declare onNavigationSpeed: (speed: number) => void;\n declare state: ShellState;\n declare element: HTMLElement | null;\n declare rootElement: HTMLElement | null;\n declare tabsElement: HTMLElement | null;\n declare projectElement: HTMLElement | null;\n declare assetsElement: HTMLElement | null;\n declare workbenchElement: HTMLElement | null;\n declare inspectorElement: HTMLElement | null;\n declare inspectorInfoElement: HTMLElement | null;\n declare inspectorFieldsElement: HTMLElement | null;\n declare inspectorActionsElement: HTMLElement | null;\n declare previewElement: HTMLElement | null;\n declare previewInfoElement: HTMLElement | null;\n declare errorElement: HTMLElement | null;\n declare targetContainer: HTMLElement | null;\n declare surface: HTMLElement | null;\n declare removeSubscription?: Dispose;\n declare removeDisconnect?: Dispose;\n declare removeInput?: RemoveInput;\n declare inputController?: ViewWorkspaceInputController;\n declare inputTargetId: string | null;\n declare inputTargetGeneration?: number;\n declare inputSurface?: HTMLElement;\n declare surfaceByTab: Map<string, SurfaceEntry>;\n declare presentationByTab: Map<string, PresentationEntry>;\n declare presentationPending: Map<string, { target: WorkspaceTarget; generation: number; surface: HTMLElement; task: Promise<void> }>;\n declare presentationQueueByTab: Map<string, Promise<void>>;\n declare presentationGenerationByTab: Map<string, number>;\n declare surfaceTargetId: string | null;\n declare presentedTargetId: string | null;\n declare removeSurfacePresentation?: Dispose;\n declare renderFingerprint: string;\n declare disposed: boolean;\n declare stopSceneAdopt?: Dispose;\n declare disposal?: Promise<void>;\n\n constructor({\n document = globalThis.document,\n window = globalThis,\n mountId = 'forgeax-view-workspace',\n element,\n api,\n presentation,\n resourceBrowser = false,\n presentationOnly = false,\n inspectorPanel = true,\n onNavigationSpeed = () => {},\n inputControllerFactory = (options) => new ViewWorkspaceInputController(options),\n }: WorkspaceShellOptions = {}) {\n this.document = document;\n this.window = window;\n this.mountId = mountId;\n this.api = api;\n this.presentation = presentation;\n this.resourceBrowser = resourceBrowser === true;\n this.presentationOnly = presentationOnly;\n this.inspectorPanel = inspectorPanel !== false;\n this.inputControllerFactory = inputControllerFactory;\n this.onNavigationSpeed = onNavigationSpeed;\n this.state = {\n selectedTabId: VIEW_WORKSPACE_TAB_ID,\n tabs: [],\n project: null,\n projectTarget: null,\n preview: null,\n assets: [],\n inspection: null,\n inspectorError: null,\n error: null,\n projectOpening: false,\n projectReconnecting: false,\n workspaceTargetLost: false,\n };\n this.element = null;\n this.rootElement = null;\n this.tabsElement = null;\n this.projectElement = null;\n this.assetsElement = null;\n this.workbenchElement = null;\n this.inspectorElement = null;\n this.inspectorInfoElement = null;\n this.inspectorFieldsElement = null;\n this.inspectorActionsElement = null;\n this.previewElement = null;\n this.previewInfoElement = null;\n this.errorElement = null;\n this.targetContainer = null;\n this.removeSubscription = undefined;\n this.removeDisconnect = undefined;\n this.removeInput = undefined;\n this.inputController = undefined;\n this.inputTargetId = null;\n this.surfaceByTab = new Map();\n this.presentationByTab = new Map();\n this.presentationPending = new Map();\n this.presentationQueueByTab = new Map();\n this.presentationGenerationByTab = new Map();\n this.surface = null;\n this.surfaceTargetId = null;\n this.presentedTargetId = null;\n this.removeSurfacePresentation = undefined;\n this.renderFingerprint = '';\n this.disposed = false;\n this.stopSceneAdopt = undefined;\n if (document?.createElement) {\n // Prefer the caller-supplied node. Dockview/ShadowRoot mounts are not\n // visible to document.getElementById, and falling back to a new body\n // section would orphan the exact Engine surface outside the View shell.\n this.element = element\n ?? document.getElementById?.(mountId)\n ?? document.createElement('section');\n this.element.id ||= mountId;\n this.element.dataset.forgeaxView = 'workspace';\n if (!this.element.parentNode) document.body?.append?.(this.element);\n this.render();\n }\n if (api) this.connect(api);\n }\n\n connect(api: ViewWorkspaceClient) {\n this.removeSubscription?.();\n this.removeDisconnect?.();\n this.api = api;\n this.disposed = false;\n this.removeSubscription = api.subscribe?.((state) => this.update(state));\n this.removeDisconnect = api.onDisconnect?.((error) => {\n this.detachInput('resident-disconnect');\n this.fail(error);\n });\n void Promise.resolve()\n .then(() => api.getState?.())\n .then((state) => this.update(state))\n .then(() => (this.state.project ? this.refreshAssets() : undefined))\n .catch((error) => this.fail(error));\n return this;\n }\n\n update(snapshot: WorkspaceState = {}) {\n if (this.disposed) return this.snapshot();\n const next = cloneWorkspaceValue(snapshot);\n if (\n next.selectedTabId !== undefined &&\n next.selectedTabId !== this.state.selectedTabId\n ) {\n this.detachInput('tab-selection');\n }\n this.state = {\n ...this.state,\n ...next,\n assets: Array.isArray(next.assets) ? next.assets : next.assets === null ? [] : this.state.assets,\n inspectorError: next.inspection ? null : this.state.inspectorError,\n projectOpening: next.project ? false : this.state.projectOpening,\n projectReconnecting: next.workspaceTargetLost === false ? false : this.state.projectReconnecting,\n workspaceTargetLost: next.workspaceTargetLost === true,\n error: next.project && !next.workspaceTargetLost ? null : this.state.error,\n };\n traceShellUpdate({\n selectedTabId: this.state.selectedTabId,\n cameraVersion: this.state.preview?.cameraVersion,\n previewTargetId: this.state.preview?.target?.targetId,\n });\n const fingerprint = workspaceUiFingerprint(this.state);\n this.render({ chromeChanged: fingerprint !== this.renderFingerprint });\n this.renderFingerprint = fingerprint;\n return this.snapshot();\n }\n\n snapshot() {\n return cloneWorkspaceValue(this.state);\n }\n\n fail(error: unknown) {\n this.state = {\n ...this.state,\n error: safeError(error),\n projectOpening: false,\n projectReconnecting: false,\n };\n if (this.presentationOnly) {\n reportWorkspaceCommandError(error, { operation: 'workspace' });\n }\n this.render();\n this.renderFingerprint = workspaceUiFingerprint(this.state);\n return this.snapshot();\n }\n\n async refreshAssets() {\n if (!this.api || !this.state.project) return;\n try {\n const result = await this.api.listAssets(this.state.project.id, { tabId: VIEW_WORKSPACE_TAB_ID });\n this.state.assets = result.assets ?? [];\n this.state.error = null;\n const fingerprint = workspaceUiFingerprint(this.state);\n this.render({ chromeChanged: fingerprint !== this.renderFingerprint });\n this.renderFingerprint = fingerprint;\n } catch (error) {\n this.fail(error);\n }\n }\n\n async openProject(root: string) {\n if (this.disposed) return this.snapshot();\n if (!this.api) {\n return this.fail(new Error('View workspace API is not connected'));\n }\n if (this.state.projectOpening) return this.snapshot();\n const path = typeof root === 'string' ? root.trim() : '';\n if (!path) {\n return this.fail(new Error('Project root is required'));\n }\n this.state = { ...this.state, error: null, projectOpening: true };\n this.render();\n try {\n const opened = await this.api.openProject(path, { tabId: VIEW_WORKSPACE_TAB_ID });\n if (opened?.project) this.update(opened);\n await this.refreshAssets();\n return this.snapshot();\n } catch (error) {\n return this.fail(error);\n } finally {\n this.state = { ...this.state, projectOpening: false };\n this.render();\n }\n }\n\n async reconnectProject() {\n if (this.disposed) return this.snapshot();\n if (!this.api) {\n return this.fail(new Error('View workspace API is not connected'));\n }\n if (this.state.projectReconnecting) return this.snapshot();\n this.state = { ...this.state, error: null, projectReconnecting: true };\n this.render();\n try {\n const opened = await reopenWorkspaceProject(this.api, { window: this.window });\n if (opened?.project) this.update(opened);\n await this.refreshAssets();\n return this.snapshot();\n } catch (error) {\n return this.fail(error);\n } finally {\n this.state = { ...this.state, projectReconnecting: false };\n this.render();\n }\n }\n\n async openAsset(guid: string) {\n try {\n await this.api!.openAsset(guid, { projectId: this.state.project?.id, tabId: VIEW_WORKSPACE_TAB_ID });\n } catch (error) {\n this.fail(error);\n }\n }\n\n async selectAsset(guid: string) {\n if (!this.api || !this.state.project) return;\n try {\n const inspected = await this.api.inspectAsset(guid, {\n projectId: this.state.project.id,\n tabId: VIEW_WORKSPACE_TAB_ID,\n });\n this.state.inspection = inspected.inspection ?? this.state.inspection;\n this.state.inspectorError = null;\n } catch (error) {\n this.state.inspectorError = safeError(error);\n this.render();\n }\n const asset =\n this.state.assets.find((candidate) => candidate.guid === guid) ?? this.state.inspection?.asset;\n if (this.resourceBrowser) {\n this.render();\n return;\n }\n if (asset?.previewable === false || this.state.preview?.asset?.guid === guid) {\n this.render();\n return;\n }\n await this.openAsset(guid);\n }\n\n async cookSelected(mode = 'rebuild') {\n const guid = this.state.inspection?.guid ?? this.state.preview?.asset?.guid;\n if (!this.api || !this.state.project || !guid) return;\n try {\n const call =\n mode === 'cold-cook' ? this.api.coldCookAssetSource : this.api.rebuildAssetSource;\n if (typeof call !== 'function') {\n throw new Error(`Engine ${mode === 'cold-cook' ? 'asset.source.cold-cook' : 'asset.source.rebuild'} is unavailable`);\n }\n await call.call(this.api, guid, {\n projectId: this.state.project.id,\n tabId: VIEW_WORKSPACE_TAB_ID,\n expectedRevision: this.state.inspection?.revision,\n });\n this.state.inspectorError = null;\n } catch (error) {\n this.state.inspectorError = safeError(error);\n this.render();\n throw error;\n }\n }\n\n async closeProject() {\n try {\n await this.api!.closeProject(this.state.project?.id, { tabId: VIEW_WORKSPACE_TAB_ID });\n } catch (error) {\n this.fail(error);\n }\n }\n\n async selectTab(tabId: string) {\n this.detachInput('tab-selection');\n try {\n await this.api!.selectTab(tabId);\n } catch (error) {\n this.fail(error);\n }\n }\n\n async closePreview() {\n await this.inputController?.abort('preview-close');\n try {\n await this.api!.closePreview({ targetId: this.state.preview?.target?.targetId, targetGeneration: this.state.preview?.target?.generation, tabId: VIEW_WORKSPACE_TAB_ID });\n } catch (error) {\n this.fail(error);\n }\n }\n\n replaceSurface(target: WorkspaceTarget | null) {\n this.ensureSurface(VIEW_WORKSPACE_TAB_ID, target);\n this.setActiveSurface();\n }\n\n attachSurfacePresentation(target: WorkspaceTarget) {\n const entry = this.surfaceByTab.get(VIEW_WORKSPACE_TAB_ID);\n this.attachTargetPresentation(VIEW_WORKSPACE_TAB_ID, target, entry?.surface);\n }\n\n targetForTab(tabId: string) {\n if (tabId === VIEW_WORKSPACE_TAB_ID) return selectWorkspaceEditorSurfaceTarget(this.state);\n const tab = (this.state.tabs ?? []).find((candidate) => candidate.tabId === tabId);\n if (!tab) return null;\n if (tab.target) {\n return {\n ...tab.target,\n targetId: String(tab.target.targetId ?? tab.targetId ?? ''),\n headed: tab.target.headed !== false,\n width: tab.target.width ?? tab.width ?? 1280,\n height: tab.target.height ?? tab.height ?? 720,\n };\n }\n if (tab.targetId === undefined || tab.targetId === null) return null;\n return {\n targetId: String(tab.targetId),\n headed: true,\n width: tab.width ?? 1280,\n height: tab.height ?? 720,\n };\n }\n\n presentationForTab(tabId: string) {\n const candidate = tabId === VIEW_DISPLAY_TAB_ID ? this.presentation?.display : this.presentation?.workspace;\n if (\n candidate &&\n (typeof candidate.attach === 'function' || typeof candidate.createSurface === 'function')\n )\n return candidate;\n return this.presentation;\n }\n\n presentationOwnsPlacement(presentation: WorkspacePresentation | undefined) {\n return presentation?.surfacePlacement === 'owner';\n }\n\n createPresentedSurface(tabId: string, target: WorkspaceTarget, presentationOverride?: WorkspacePresentation) {\n const presentation = presentationOverride ?? this.presentationForTab(tabId);\n if (typeof presentation?.createSurface !== 'function') return null;\n const surface = presentation.createSurface({\n tabId,\n target: target as EngineWorkspaceTarget,\n document: this.document,\n });\n if (surface === null || surface === undefined) return null;\n if (typeof surface !== 'object') {\n throw new TypeError('View target presentation createSurface must return a DOM element');\n }\n return surface as HTMLElement;\n }\n\n ensureSurface(tabId: string, target: WorkspaceTarget | null) {\n const targetId = target?.targetId === undefined ? null : String(target.targetId);\n const current = this.surfaceByTab.get(tabId);\n const presentation = this.presentationForTab(tabId);\n const surfacePlacement = this.presentationOwnsPlacement(presentation) ? 'owner' : 'shell';\n const exactIdentityMatches = sameTargetIdentity(current?.target, target);\n if (!targetId) {\n if (current) {\n // Keep an exact Engine surface as a short-lived tombstone while its\n // serialized detach is draining. A fast stop -> start can otherwise\n // acquire the same host surface before the old cleanup has restored\n // its origin, causing the old cleanup to delete the new origin map.\n // The next exact target reuses this entry and marks it for a queued\n // reacquisition after the old cleanup; inert surfaces can\n // still be discarded immediately.\n if (current.exactSurface) {\n if (current.targetId !== null) {\n current.targetId = null;\n current.target = null;\n current.reacquire = true;\n void this.detachTargetPresentation(tabId).catch((error) => this.fail(error));\n }\n } else {\n void this.detachTargetPresentation(tabId).catch((error) => this.fail(error));\n this.surfaceByTab.delete(tabId);\n }\n }\n return null;\n }\n if (\n current &&\n current.targetId === targetId &&\n (!current.exactSurface || exactIdentityMatches)\n ) {\n current.target = target;\n if (!current.exactSurface) {\n const width = target?.width ?? (current.surface as HTMLCanvasElement).width ?? 1280;\n const height = target?.height ?? (current.surface as HTMLCanvasElement).height ?? 720;\n if ((current.surface as HTMLCanvasElement).width !== width) (current.surface as HTMLCanvasElement).width = width;\n if ((current.surface as HTMLCanvasElement).height !== height) (current.surface as HTMLCanvasElement).height = height;\n }\n return current.surface;\n }\n // A host-provided exact surface is the Engine-owned presentation for this\n // tab, not a per-target canvas allocation. Keep its DOM identity stable\n // when the target identity is refreshed; the serialized presentation\n // lifecycle below still releases the old target before attaching the new\n // one. This also avoids calling createSurface while an earlier attachment\n // may still own the host surface.\n if (\n current &&\n current.exactSurface\n ) {\n current.targetId = targetId;\n current.target = target;\n current.reacquire = true;\n current.surfacePlacement = surfacePlacement;\n return current.surface;\n }\n if (current) {\n void this.detachTargetPresentation(tabId).catch((error) => this.fail(error));\n }\n if (!this.document?.createElement) return null;\n const presentedSurface = this.createPresentedSurface(tabId, target!, presentation);\n if ((surfacePlacement === 'owner' || typeof presentation?.createSurface === 'function') && presentedSurface === null) {\n // The display Fiber owns the only valid surface. During bootstrap it\n // may not exist yet; keep this tab surface-less and retry on a later\n // state/render transition instead of fabricating a second runtime node.\n this.surfaceByTab.delete(tabId);\n return null;\n }\n const surface = presentedSurface ?? this.document.createElement('canvas');\n const exactSurface = presentedSurface !== null;\n const resolvedSurfacePlacement = exactSurface && surfacePlacement === 'owner' ? 'owner' : 'shell';\n if (!exactSurface) {\n this.markSurface(surface, tabId, targetId);\n (surface as HTMLCanvasElement).width = target?.width ?? 1280;\n (surface as HTMLCanvasElement).height = target?.height ?? 720;\n }\n this.surfaceByTab.set(tabId, {\n targetId,\n target,\n exactSurface,\n surfacePlacement: resolvedSurfacePlacement,\n reacquire: false,\n surface,\n });\n return surface;\n }\n\n setActiveSurface() {\n const selected = this.surfaceByTab.get(this.state.selectedTabId ?? VIEW_WORKSPACE_TAB_ID);\n const active = selected?.targetId ? selected : null;\n this.surface = active?.surface ?? null;\n this.surfaceTargetId = active?.targetId ?? null;\n this.presentedTargetId = active?.targetId ?? null;\n }\n\n attachTargetPresentation(tabId: string, target: WorkspaceTarget | null, surface?: HTMLElement) {\n const presentation = this.presentationForTab(tabId);\n if (!target || !surface || (!presentation?.attach && !presentation?.createSurface)) return;\n const current = this.presentationByTab.get(tabId);\n if (current && sameTargetIdentity(current.target, target) && current.surface === surface &&\n current.generation === this.presentationGenerationByTab.get(tabId)) return;\n tracePresentationAttach(tabId, String(target.targetId), surface);\n const pending = this.presentationPending.get(tabId);\n if (pending && sameTargetIdentity(pending.target, target) && pending.surface === surface &&\n pending.generation === this.presentationGenerationByTab.get(tabId)) return;\n const generation = (this.presentationGenerationByTab.get(tabId) ?? 0) + 1;\n this.presentationGenerationByTab.set(tabId, generation);\n const task = this.enqueuePresentation(tabId, async () => {\n if (this.disposed || generation !== this.presentationGenerationByTab.get(tabId)) {\n await this.releaseUnattachedPresentation({ presentation, target, surface, tabId });\n return;\n }\n\n const previous = this.presentationByTab.get(tabId);\n if (previous) await this.releasePresentationEntry(tabId, previous);\n if (this.disposed || generation !== this.presentationGenerationByTab.get(tabId)) {\n await this.releaseUnattachedPresentation({ presentation, target, surface, tabId });\n return;\n }\n\n let attachSurface = surface;\n const surfaceEntry = this.surfaceByTab.get(tabId);\n if (surfaceEntry?.surface === surface && surfaceEntry.exactSurface && surfaceEntry.reacquire) {\n const refreshed = this.createPresentedSurface(tabId, target, presentation);\n if (refreshed !== null) {\n attachSurface = refreshed;\n surfaceEntry.surface = refreshed;\n surfaceEntry.reacquire = false;\n } else {\n // Do not reuse a released node when Engine cannot resolve the new identity.\n this.surfaceByTab.delete(tabId);\n this.setActiveSurface();\n return;\n }\n }\n // A previous Engine cleanup may have restored an exact surface to its\n // original parent. Adopt it only after that cleanup has completed, so a\n // stale cleanup can never move the new attachment out from underneath\n // the current tab.\n const restore = surfaceEntry?.exactSurface && surfaceEntry.surfacePlacement !== 'owner'\n ? borrowSurface(attachSurface, this.targetContainer!) : undefined;\n this.markSurface(attachSurface, tabId, target.targetId);\n this.adoptPresentationSurface(attachSurface, {\n external: surfaceEntry?.surfacePlacement === 'owner',\n });\n\n const entry: PresentationEntry = {\n target,\n targetId: String(target.targetId),\n surface: attachSurface,\n presentation,\n surfacePlacement: surfaceEntry?.surfacePlacement ?? 'shell',\n generation,\n remove: undefined,\n restore,\n };\n this.presentationByTab.set(tabId, entry);\n try {\n const remove = await presentation.attach?.({ target: target as EngineWorkspaceTarget, element: attachSurface, tabId });\n if (typeof remove === 'function') entry.remove = remove;\n if (\n this.presentationByTab.get(tabId) !== entry ||\n entry.generation !== this.presentationGenerationByTab.get(tabId) ||\n this.disposed\n ) {\n await this.releasePresentationEntry(tabId, entry);\n return;\n }\n entry.ready = true;\n this.setActiveSurface();\n this.render({ chromeChanged: false });\n } catch (error) {\n await this.releasePresentationEntry(tabId, entry).catch(() => {});\n // Keep this identity failed until an explicit target transition. Error\n // rendering must not recursively retry and re-adopt the returned node.\n entry.remove = () => {};\n entry.ready = false;\n this.presentationByTab.set(tabId, entry);\n throw error;\n }\n });\n const pendingEntry = { target, generation, surface, task };\n this.presentationPending.set(tabId, pendingEntry);\n void task.then(\n () => {\n if (this.presentationPending.get(tabId) === pendingEntry) this.presentationPending.delete(tabId);\n },\n (error) => {\n if (this.presentationPending.get(tabId) === pendingEntry) this.presentationPending.delete(tabId);\n this.fail(error);\n },\n );\n }\n\n markSurface(surface: HTMLElement, tabId: string, targetId: string) {\n surface.dataset.forgeaxViewTargetId = String(targetId);\n surface.dataset.forgeaxViewTabId = tabId;\n surface.dataset.forgeaxViewSurface = tabId === VIEW_DISPLAY_TAB_ID ? 'engine-target' : 'engine-canvas';\n surface.setAttribute?.('aria-label', `Engine target ${targetId}`);\n }\n\n enqueuePresentation(tabId: string, operation: () => Promise<void>) {\n const previous = this.presentationQueueByTab.get(tabId) ?? Promise.resolve();\n const task = previous.catch(() => {}).then(operation);\n this.presentationQueueByTab.set(tabId, task);\n void task.then(\n () => {\n if (this.presentationQueueByTab.get(tabId) === task) this.presentationQueueByTab.delete(tabId);\n },\n () => {\n if (this.presentationQueueByTab.get(tabId) === task) this.presentationQueueByTab.delete(tabId);\n },\n );\n return task;\n }\n\n async runPresentationCleanup(remove: void | Dispose) {\n if (typeof remove === 'function') await Promise.resolve(remove());\n }\n\n async releaseUnattachedPresentation({ presentation, target, surface, tabId }: { presentation: WorkspacePresentation; target: WorkspaceTarget; surface: HTMLElement; tabId: string }) {\n if (this.presentationByTab.get(tabId)?.surface === surface) return;\n if (typeof presentation?.detach === 'function') {\n await Promise.resolve(presentation.detach({ target: target as EngineWorkspaceTarget, element: surface, tabId })).catch(() => {});\n return;\n }\n if (typeof presentation?.attach === 'function') {\n const remove = await presentation.attach({ target: target as EngineWorkspaceTarget, element: surface, tabId });\n await this.runPresentationCleanup(remove);\n }\n }\n\n adoptPresentationSurface(surface: HTMLElement, { external = false } = {}) {\n if (external || !surface || !this.targetContainer) return;\n if (surface.parentNode !== this.targetContainer) this.targetContainer.append?.(surface);\n }\n\n async releasePresentationEntry(tabId: string, entry: PresentationEntry) {\n if (this.presentationByTab.get(tabId) === entry) this.presentationByTab.delete(tabId);\n entry.restore?.();\n let failure;\n if (entry.remove) {\n try {\n await this.runPresentationCleanup(entry.remove);\n } catch (error) {\n failure = error;\n }\n }\n if (!entry.remove || failure !== undefined) {\n try {\n await Promise.resolve(\n entry.presentation?.detach?.({ target: entry.target as EngineWorkspaceTarget, element: entry.surface, tabId }),\n );\n } catch (error) {\n failure ??= error;\n }\n }\n if (failure !== undefined) throw failure;\n }\n\n async detachTargetPresentation(tabId: string, { invalidate = true } = {}) {\n if (invalidate) {\n this.presentationGenerationByTab.set(\n tabId,\n (this.presentationGenerationByTab.get(tabId) ?? 0) + 1,\n );\n }\n return this.enqueuePresentation(tabId, async () => {\n const entry = this.presentationByTab.get(tabId);\n if (entry) await this.releasePresentationEntry(tabId, entry);\n });\n }\n\n ensureDom() {\n if (!this.element || !this.document) return false;\n if (this.rootElement) return true;\n\n const root = this.document.createElement('div');\n root.dataset.forgeaxViewWorkspace = 'root';\n this.rootElement = root;\n\n this.tabsElement = this.document.createElement('nav');\n this.tabsElement.dataset.forgeaxViewWorkspace = 'tabs';\n this.projectElement = this.document.createElement('div');\n this.projectElement.dataset.forgeaxViewWorkspace = 'project';\n this.workbenchElement = this.document.createElement('div');\n this.workbenchElement.dataset.forgeaxViewWorkspace = 'workbench';\n const rail = this.document.createElement('div');\n rail.dataset.forgeaxViewWorkspace = 'rail';\n this.assetsElement = this.document.createElement('ul');\n this.assetsElement.dataset.forgeaxViewWorkspace = 'assets';\n rail.append?.(this.assetsElement);\n this.previewElement = this.document.createElement('div');\n this.previewElement.dataset.forgeaxViewWorkspace = 'preview';\n this.previewInfoElement = this.document.createElement('div');\n this.previewInfoElement.dataset.forgeaxViewWorkspace = 'preview-info';\n this.targetContainer = this.document.createElement('div');\n this.targetContainer.dataset.forgeaxViewWorkspace = 'targets';\n if (this.targetContainer.style) this.targetContainer.style.position = 'relative';\n this.previewElement.append?.(...(this.presentationOnly ? [] : [this.previewInfoElement]), this.targetContainer);\n this.inspectorElement = this.document.createElement('aside');\n this.inspectorElement.dataset.forgeaxViewWorkspace = 'inspector';\n this.inspectorInfoElement = this.document.createElement('div');\n this.inspectorInfoElement.dataset.forgeaxViewWorkspace = 'inspector-info';\n this.inspectorFieldsElement = this.document.createElement('div');\n this.inspectorFieldsElement.dataset.forgeaxViewWorkspace = 'inspector-fields';\n this.inspectorActionsElement = this.document.createElement('div');\n this.inspectorActionsElement.dataset.forgeaxViewWorkspace = 'inspector-actions';\n this.inspectorElement.append?.(\n this.inspectorInfoElement,\n this.inspectorFieldsElement,\n this.inspectorActionsElement,\n );\n this.workbenchElement.append?.(\n ...(this.presentationOnly ? [] : [rail]),\n this.previewElement,\n ...(this.inspectorPanel ? [this.inspectorElement] : []),\n );\n if (!this.presentationOnly) {\n this.errorElement = this.document.createElement('div');\n this.errorElement.dataset.forgeaxViewWorkspace = 'error';\n this.errorElement.setAttribute?.('role', 'alert');\n }\n root.append?.(\n ...(this.presentationOnly ? [] : [this.tabsElement, this.projectElement]),\n this.workbenchElement,\n ...(this.errorElement ? [this.errorElement] : []),\n );\n if (root.parentNode !== this.element) this.element.append?.(root);\n this.stopSceneAdopt = keepSurfaceInContainer({\n document: this.document,\n getContainer: () => (this.disposed ? null : this.targetContainer),\n getSurface: () => readSceneShell(this.document),\n onPlace: (surface) => {\n if (!surface?.style) return;\n Object.assign(surface.style, {\n width: '100%',\n height: '100%',\n maxWidth: '100%',\n maxHeight: '100%',\n position: 'relative',\n transform: 'none',\n overflow: 'hidden',\n });\n },\n });\n traceShellRegisterDomRoot(root);\n return true;\n }\n\n syncTargetSurfaces() {\n const surfaces = this.targetContainer;\n if (!surfaces) return;\n let removed = 0;\n let reordered = 0;\n const desired: Element[] = [];\n for (const tabId of [VIEW_DISPLAY_TAB_ID, VIEW_WORKSPACE_TAB_ID]) {\n const entry = this.surfaceByTab.get(tabId);\n // An exact surface with no target is a detach-draining tombstone. It\n // must not be presented or reattached until the next target adopts it.\n if (!entry || !entry.targetId || !entry.target) continue;\n this.attachTargetPresentation(tabId, entry.target, entry.surface);\n const attached = this.presentationByTab.get(tabId);\n // Render cannot move an exact node ahead of the serialized cleanup.\n if (entry.exactSurface && (!attached?.ready || !sameTargetIdentity(attached.target, entry.target))) continue;\n const selected = this.state.selectedTabId === tabId &&\n !(tabId === VIEW_WORKSPACE_TAB_ID && this.state.targetBinding === 'play');\n // The borrowed CLI carrier stays active across tab changes. Workspace\n // previews can stop background rendering when their presentation is hidden.\n if (entry.exactSurface && tabId === VIEW_DISPLAY_TAB_ID) {\n if (entry.surface.hidden !== false) entry.surface.hidden = false;\n if (entry.surface.style) {\n const visibility = selected ? 'visible' : 'hidden';\n const pointerEvents = selected ? 'auto' : 'none';\n if (entry.surface.style.visibility !== visibility) entry.surface.style.visibility = visibility;\n if (entry.surface.style.pointerEvents !== pointerEvents) entry.surface.style.pointerEvents = pointerEvents;\n }\n } else {\n const hidden = !selected;\n if (entry.surface.hidden !== hidden) entry.surface.hidden = hidden;\n if (entry.surface.style) {\n const display = selected ? '' : 'none';\n if (entry.surface.style.display !== display) entry.surface.style.display = display;\n }\n }\n const selectedMark = selected ? 'true' : 'false';\n if (entry.surface.dataset.forgeaxViewSelected !== selectedMark) {\n entry.surface.dataset.forgeaxViewSelected = selectedMark;\n }\n if (entry.surfacePlacement !== 'owner') desired.push(entry.surface);\n }\n\n for (const child of [...(surfaces.children ?? [])]) {\n if (!desired.includes(child)) {\n if (child?.id === 'app-shell') continue;\n if ([...this.presentationByTab.values()].some(entry => entry.surface === child)) continue;\n child.remove?.();\n removed += 1;\n }\n }\n for (let index = 0; index < desired.length; index += 1) {\n const surface = desired[index];\n if (surfaces.children?.[index] === surface) continue;\n reordered += 1;\n const before = surfaces.children?.[index] ?? null;\n if (surfaces.insertBefore) surfaces.insertBefore(surface, before);\n else surfaces.append?.(surface);\n }\n traceSyncTargetSurfaces({ removed, reordered, desired: desired.length });\n }\n\n render({ chromeChanged = true } = {}) {\n if (this.disposed || !this.element || !this.document) return;\n const renderStarted = isViewTraceEnabled() ? performance.now() : 0;\n const workspaceTarget = this.targetForTab(VIEW_WORKSPACE_TAB_ID);\n const displayTarget = this.targetForTab(VIEW_DISPLAY_TAB_ID);\n this.ensureSurface(VIEW_WORKSPACE_TAB_ID, workspaceTarget);\n this.ensureSurface(VIEW_DISPLAY_TAB_ID, displayTarget);\n this.setActiveSurface();\n const nextTargetId = workspaceTarget?.targetId ?? null;\n const workspaceSurfaceEntry = this.surfaceByTab.get(VIEW_WORKSPACE_TAB_ID);\n if (nextTargetId !== this.inputTargetId || workspaceTarget?.generation !== this.inputTargetGeneration ||\n workspaceSurfaceEntry?.surface !== this.inputSurface) {\n this.detachInput('target-replaced');\n this.removeInput?.();\n this.removeInput = undefined;\n this.inputController = undefined;\n this.inputTargetId = nextTargetId;\n this.inputTargetGeneration = workspaceTarget?.generation;\n this.inputSurface = workspaceSurfaceEntry?.surface;\n }\n if (!this.ensureDom()) return;\n let domReplaceChildren = 0;\n const tabs = this.tabsElement;\n const project = this.projectElement;\n const assets = this.assetsElement;\n const previewInfo = this.previewInfoElement;\n const inspectorInfo = this.inspectorInfoElement;\n const inspectorFields = this.inspectorFieldsElement;\n const inspectorActions = this.inspectorActionsElement;\n const error = this.errorElement;\n if (chromeChanged) {\n if (tabs?.replaceChildren) {\n tabs.replaceChildren();\n domReplaceChildren += 1;\n }\n for (const tab of this.state.tabs ?? []) {\n tabs?.append?.(\n button(this.document, `${tab.kind}: ${tab.tabId}`, () => this.selectTab(tab.tabId), {\n disabled: tab.selected === true,\n }),\n );\n }\n if (project?.replaceChildren) {\n project.replaceChildren();\n domReplaceChildren += 1;\n }\n if (this.state.project) {\n project?.append?.(text(this.document, `Project: ${this.state.project.name ?? this.state.project.id}`));\n project?.append?.(button(this.document, 'Refresh assets', () => this.refreshAssets()));\n project?.append?.(button(this.document, 'Close project', () => this.closeProject()));\n } else {\n project?.append?.(\n text(this.document, 'Project opens from the View owner process.'),\n );\n }\n if (this.state.workspaceTargetLost && this.state.project?.root) {\n const reconnectLabel = this.state.projectReconnecting ? 'Reconnecting project\u2026' : 'Reconnect project';\n project?.append?.(\n button(this.document, reconnectLabel, () => this.reconnectProject(), {\n disabled: this.state.projectReconnecting === true,\n }),\n );\n }\n if (assets?.replaceChildren) {\n assets.replaceChildren();\n domReplaceChildren += 1;\n }\n for (const group of groupAssetsBySource(this.state.assets)) {\n const item = this.document.createElement('li');\n item.dataset.forgeaxViewWorkspace = 'asset-group';\n item.dataset.sourcePath = group.key;\n item.append?.(text(this.document, group.key));\n const members = this.document.createElement('ul');\n for (const asset of group.assets) {\n const member = this.document.createElement('li');\n member.dataset.forgeaxViewWorkspace = 'asset';\n member.dataset.guid = asset.guid;\n member.dataset.kind = asset.kind;\n if (asset.sourceKind) member.dataset.sourceKind = asset.sourceKind;\n const ddcState = catalogDdcState(asset, this.state.inspection);\n const receipt = catalogReceipt(asset, this.state.inspection);\n if (ddcState) member.dataset.ddcState = ddcState;\n if (receipt) member.dataset.cookReceiptUrl = receipt;\n const selected = this.state.inspection?.guid === asset.guid;\n const label = `${asset.name ?? asset.guid} (${asset.kind}${ddcState ? ` \u00B7 ${ddcState}` : ''})`;\n member.append?.(\n button(this.document, label, () => this.selectAsset(asset.guid), {\n disabled: selected,\n }),\n );\n members.append?.(member);\n }\n item.append?.(members);\n assets?.append?.(item);\n }\n if (previewInfo?.replaceChildren) {\n previewInfo.replaceChildren();\n domReplaceChildren += 1;\n }\n if (this.state.preview) {\n previewInfo?.append?.(\n text(this.document, `Target: ${this.state.preview.asset?.name ?? this.state.preview.asset?.guid ?? 'Game'}`),\n ...(this.state.preview.asset ? [button(this.document, 'Close preview', () => this.closePreview())] : []),\n );\n } else {\n previewInfo?.append?.(text(this.document, 'No asset preview open'));\n }\n if (inspectorInfo?.replaceChildren) {\n inspectorInfo.replaceChildren();\n domReplaceChildren += 1;\n }\n if (inspectorFields?.replaceChildren) {\n inspectorFields.replaceChildren();\n domReplaceChildren += 1;\n }\n if (inspectorActions?.replaceChildren) {\n inspectorActions.replaceChildren();\n domReplaceChildren += 1;\n }\n const inspection = this.state.inspection;\n if (this.state.inspectorError) {\n inspectorInfo?.append?.(text(this.document, `Inspector: ${this.state.inspectorError}`));\n } else if (inspection) {\n inspectorInfo?.append?.(\n text(\n this.document,\n `${inspection.asset?.name ?? inspection.guid} \u00B7 ${inspection.source?.kind ?? inspection.asset?.sourceKind ?? inspection.asset?.kind} \u00B7 ${inspection.source?.path ?? inspection.asset?.sourcePath ?? ''}${inspection.revision ? ` \u00B7 rev ${inspection.revision.slice(0, 12)}` : ''}${inspection.ddc?.receiptUrl ? ` \u00B7 ${inspection.ddc.receiptUrl}` : ''}`,\n ),\n );\n const meta = inspection.meta;\n if (meta) {\n const identity = this.document.createElement('div');\n identity.dataset.forgeaxViewWorkspace = 'pack-meta';\n identity.append?.(\n text(\n this.document,\n `${meta.packageId ?? ''} \u00B7 ${meta.importer ?? ''} \u00B7 ${meta.source ?? ''}`,\n ),\n );\n inspectorFields?.append?.(identity);\n for (const sub of (meta.subAssets as readonly { guid: string; kind: string; name?: string; sourceKey?: string }[] | undefined) ?? []) {\n const row = this.document.createElement('div');\n row.dataset.forgeaxViewWorkspace = 'sub-asset';\n row.dataset.guid = sub.guid;\n row.dataset.kind = sub.kind;\n row.append?.(text(this.document, `${sub.name ?? sub.sourceKey} (${sub.kind})`));\n inspectorFields?.append?.(row);\n }\n }\n inspectorActions?.append?.(\n button(this.document, 'Rebuild', () => this.cookSelected('rebuild')),\n button(this.document, 'Cold-cook', () => this.cookSelected('cold-cook')),\n );\n } else {\n inspectorInfo?.append?.(text(this.document, 'Select an asset to inspect Engine catalog and pack meta'));\n }\n }\n this.syncTargetSurfaces();\n const nextError = this.state.error ? `Error: ${this.state.error}` : '';\n const nextHidden = !this.state.error;\n if (error) {\n if (error.hidden !== nextHidden) error.hidden = nextHidden;\n if (error.textContent !== nextError) error.textContent = nextError;\n }\n const workspaceSurface = this.surfaceByTab.get(VIEW_WORKSPACE_TAB_ID)?.surface;\n if (\n nextTargetId &&\n workspaceSurface &&\n this.api &&\n this.removeInput === undefined &&\n (!workspaceSurfaceEntry?.exactSurface ||\n (this.presentationByTab.get(VIEW_WORKSPACE_TAB_ID)?.ready &&\n sameTargetIdentity(this.presentationByTab.get(VIEW_WORKSPACE_TAB_ID)?.target, workspaceTarget))) &&\n this.state.selectedTabId === VIEW_WORKSPACE_TAB_ID\n ) {\n this.inputController = this.inputControllerFactory({\n api: this.api,\n targetId: nextTargetId,\n targetGeneration: workspaceTarget?.generation,\n tabId: VIEW_WORKSPACE_TAB_ID,\n window: this.window,\n document: this.document,\n onError: (error) => this.fail(error),\n onSpeedChange: this.onNavigationSpeed,\n onFocusSelection: () => {\n const selected = this.state.sceneSelection;\n if (selected?.primary?.entityId) return this.api?.call('entity.focus', {\n entityId: selected.primary.entityId, targetId: nextTargetId, targetGeneration: workspaceTarget?.generation,\n });\n },\n shouldCapture: (event) => isViewportWorkspaceInputEvent(event, { surface: workspaceSurface, host: this.element }),\n });\n this.removeInput = this.inputController.attach(workspaceSurface);\n }\n traceShellRender({\n durationMs: renderStarted ? Math.round((performance.now() - renderStarted) * 100) / 100 : undefined,\n workspaceSurface: workspaceSurface?.dataset?.forgeaxViewSurface,\n exactSurface: this.surfaceByTab.get(VIEW_WORKSPACE_TAB_ID)?.exactSurface,\n inputBound: this.removeInput !== undefined,\n presentationOnly: this.presentationOnly,\n domReplaceChildren,\n tabCount: (this.state.tabs ?? []).length,\n assetCount: (this.state.assets ?? []).length,\n });\n }\n\n /** Detach local DOM listeners before a tab/target/disconnect transition. */\n detachInput(reason: string = 'input-detached') {\n const controller = this.inputController;\n const remove = this.removeInput;\n this.removeInput = undefined;\n this.inputController = undefined;\n if (remove) {\n remove(reason);\n }\n if (!remove?.handlesAbort) {\n void Promise.resolve(controller?.abort?.(reason)).catch((error) => this.fail(error));\n }\n }\n\n dispose() {\n if (this.disposal) return this.disposal;\n this.disposed = true;\n this.stopSceneAdopt?.();\n this.stopSceneAdopt = undefined;\n // Parent panels may disappear before asynchronous input/adapter cleanup.\n // Pending tasks see disposed and cannot adopt another borrowed node.\n for (const entry of this.presentationByTab.values()) entry.restore?.();\n this.disposal = this.finishDisposal();\n return this.disposal;\n }\n\n async finishDisposal() {\n const removeInput = this.removeInput;\n const inputController = this.inputController;\n this.removeInput = undefined;\n removeInput?.('input-disposed');\n const inputDisposal = inputController?.dispose?.().catch(() => {});\n this.inputController = undefined;\n this.removeSubscription?.();\n this.removeSubscription = undefined;\n this.removeDisconnect?.();\n this.removeDisconnect = undefined;\n const presentationTabs = new Set([\n ...this.surfaceByTab.keys(),\n ...this.presentationByTab.keys(),\n ...this.presentationPending.keys(),\n ...this.presentationQueueByTab.keys(),\n ]);\n for (const tabId of presentationTabs) {\n this.presentationGenerationByTab.set(\n tabId,\n (this.presentationGenerationByTab.get(tabId) ?? 0) + 1,\n );\n }\n await Promise.all([\n inputDisposal,\n ...[...presentationTabs].map((tabId) => this.detachTargetPresentation(tabId, { invalidate: false }).catch(() => {})),\n ]);\n this.presentationPending.clear();\n this.presentationQueueByTab.clear();\n this.presentationGenerationByTab.clear();\n this.surfaceByTab.clear();\n this.rootElement = null;\n this.targetContainer = null;\n this.removeSurfacePresentation = undefined;\n this.inputTargetId = null;\n this.surfaceTargetId = null;\n this.presentedTargetId = null;\n this.surface = null;\n this.element?.remove?.();\n this.element = null;\n }\n}\n\nexport { VIEW_DISPLAY_TAB_ID, VIEW_WORKSPACE_TAB_ID };\n"],
5
5
  "mappings": "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",
6
6
  "names": ["error"]
7
7
  }
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createEditorPageTitleController
3
- } from "./chunk-CKYXAT7H.mjs";
3
+ } from "./chunk-VC4OEPDH.mjs";
4
4
  import {
5
5
  FRONTEND_PLUGIN_ID,
6
6
  PAGE_TYPE
7
- } from "./chunk-P5XMFZY4.mjs";
7
+ } from "./chunk-SFB5BDTB.mjs";
8
8
 
9
9
  // packages/view-plugin-scene/src/frontend.ts
10
10
  var frontend_default = {
@@ -37,4 +37,4 @@ var frontend_default = {
37
37
  export {
38
38
  frontend_default
39
39
  };
40
- //# sourceMappingURL=chunk-WVU3CQ62.mjs.map
40
+ //# sourceMappingURL=chunk-GUVUL6D2.mjs.map