@forgeax/view 0.5.0-dev.13619.c20ebf66cef4 → 0.5.0-dev.13739.664093158f99

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 (258) hide show
  1. package/README.md +19 -5
  2. package/dist/build-revision.json +1 -1
  3. package/dist/modules/backend.mjs +33 -33
  4. package/dist/modules/browser.mjs +49 -49
  5. package/dist/modules/chunks/{chunk-OS7BK3FO.mjs → chunk-2CMCY54A.mjs} +2 -2
  6. package/dist/modules/chunks/{chunk-NHNPQ3ZS.mjs → chunk-2RUKPDIE.mjs} +4 -4
  7. package/dist/modules/chunks/{chunk-NHNPQ3ZS.mjs.map → chunk-2RUKPDIE.mjs.map} +1 -1
  8. package/dist/modules/chunks/{chunk-CYQ7BITZ.mjs → chunk-3FBX3P3H.mjs} +6 -6
  9. package/dist/modules/chunks/{chunk-VD4QU7KY.mjs → chunk-45WL24XN.mjs} +2 -2
  10. package/dist/modules/chunks/{chunk-FSSKCXPL.mjs → chunk-4FYKRL46.mjs} +3 -3
  11. package/dist/modules/chunks/{chunk-Y4SFATAM.mjs → chunk-4MJHVZMB.mjs} +6 -6
  12. package/dist/modules/chunks/{chunk-D3ISMGT6.mjs → chunk-5HVXQEO3.mjs} +7 -7
  13. package/dist/modules/chunks/{chunk-J7QRK3FU.mjs → chunk-66LM6NO6.mjs} +4 -4
  14. package/dist/modules/chunks/{chunk-RGM4S2BE.mjs → chunk-6C4OCCYB.mjs} +12 -12
  15. package/dist/modules/chunks/{chunk-RGM4S2BE.mjs.map → chunk-6C4OCCYB.mjs.map} +1 -1
  16. package/dist/modules/chunks/{chunk-QNSUBUZF.mjs → chunk-6J27SWMY.mjs} +1 -1
  17. package/dist/modules/chunks/{chunk-QNJL265P.mjs → chunk-6VK7HB4X.mjs} +4 -4
  18. package/dist/modules/chunks/{chunk-AZHCKPUL.mjs → chunk-6WZZ7TIC.mjs} +2 -2
  19. package/dist/modules/chunks/{chunk-A22PJUZM.mjs → chunk-7DFCIN3T.mjs} +3 -3
  20. package/dist/modules/chunks/{chunk-A22PJUZM.mjs.map → chunk-7DFCIN3T.mjs.map} +1 -1
  21. package/dist/modules/chunks/{chunk-CVIF6DYH.mjs → chunk-7MWZK7HS.mjs} +3 -3
  22. package/dist/modules/chunks/{chunk-7YWMB7HV.mjs → chunk-A7OGXJAV.mjs} +3 -3
  23. package/dist/modules/chunks/{chunk-KOBAWLZL.mjs → chunk-AUINYWZP.mjs} +2 -2
  24. package/dist/modules/chunks/{chunk-R6MT6F3T.mjs → chunk-B24VYGHV.mjs} +3 -3
  25. package/dist/modules/chunks/{chunk-ZKFH7EMU.mjs → chunk-BIUWJROZ.mjs} +3 -3
  26. package/dist/modules/chunks/{chunk-ZKFH7EMU.mjs.map → chunk-BIUWJROZ.mjs.map} +2 -2
  27. package/dist/modules/chunks/{chunk-M66NDY35.mjs → chunk-C2AMOM7H.mjs} +3 -3
  28. package/dist/modules/chunks/{chunk-EOW4JGVV.mjs → chunk-C3WVSJZF.mjs} +6 -6
  29. package/dist/modules/chunks/{chunk-TFBSEYKW.mjs → chunk-CAXCOZ7Y.mjs} +3 -3
  30. package/dist/modules/chunks/{chunk-P27F2TZN.mjs → chunk-CN6YN4HP.mjs} +10 -10
  31. package/dist/modules/chunks/chunk-CN6YN4HP.mjs.map +7 -0
  32. package/dist/modules/chunks/{chunk-25PFC2DY.mjs → chunk-CXFQME65.mjs} +3 -3
  33. package/dist/modules/chunks/{chunk-VD3C4DYT.mjs → chunk-CYOLEAAY.mjs} +13 -13
  34. package/dist/modules/chunks/{chunk-VD3C4DYT.mjs.map → chunk-CYOLEAAY.mjs.map} +1 -1
  35. package/dist/modules/chunks/{chunk-P3ZW2T37.mjs → chunk-CYU3WWN6.mjs} +3 -3
  36. package/dist/modules/chunks/{chunk-SKZC6VTV.mjs → chunk-D2LZIQE2.mjs} +2 -2
  37. package/dist/modules/chunks/{chunk-QNUBIFAY.mjs → chunk-DC5JP46Y.mjs} +2 -2
  38. package/dist/modules/chunks/{chunk-7MQIGD6Q.mjs → chunk-DOU4MNMQ.mjs} +3 -3
  39. package/dist/modules/chunks/{chunk-JKDBKS7P.mjs → chunk-E4G4HDOC.mjs} +3 -3
  40. package/dist/modules/chunks/{chunk-XXJ32F5P.mjs → chunk-EZAJ66NW.mjs} +3 -3
  41. package/dist/modules/chunks/{chunk-5PZL6W3F.mjs → chunk-FIWL6TQS.mjs} +2 -2
  42. package/dist/modules/chunks/{chunk-K4C5WOTT.mjs → chunk-FSSARTVM.mjs} +3 -3
  43. package/dist/modules/chunks/{chunk-5HJ336VM.mjs → chunk-FXXPWAXM.mjs} +3 -3
  44. package/dist/modules/chunks/{chunk-43L37UYV.mjs → chunk-G2QCXN56.mjs} +6 -6
  45. package/dist/modules/chunks/{chunk-DJKXBCZH.mjs → chunk-GRDCA6LD.mjs} +8 -8
  46. package/dist/modules/chunks/{chunk-DJKXBCZH.mjs.map → chunk-GRDCA6LD.mjs.map} +1 -1
  47. package/dist/modules/chunks/{chunk-4ZI5DFBR.mjs → chunk-GUVUL6D2.mjs} +3 -3
  48. package/dist/modules/chunks/{chunk-MFEFV3YF.mjs → chunk-I32EONBF.mjs} +2 -2
  49. package/dist/modules/chunks/{chunk-DX4M6LZH.mjs → chunk-IGIELQZ2.mjs} +5 -5
  50. package/dist/modules/chunks/{chunk-U5LBMAG3.mjs → chunk-IMDR26Y3.mjs} +3 -3
  51. package/dist/modules/chunks/{chunk-MUBV2LNK.mjs → chunk-JVOHFCI4.mjs} +3 -3
  52. package/dist/modules/chunks/{chunk-CEB76QBE.mjs → chunk-KCM7ZCQ3.mjs} +5 -5
  53. package/dist/modules/chunks/chunk-KCM7ZCQ3.mjs.map +7 -0
  54. package/dist/modules/chunks/{chunk-TPLT4PBX.mjs → chunk-KJTMDFFX.mjs} +4 -4
  55. package/dist/modules/chunks/{chunk-WC6NGMGI.mjs → chunk-KPLESRQY.mjs} +3 -3
  56. package/dist/modules/chunks/{chunk-ZW7LLDOL.mjs → chunk-KUOWDTI6.mjs} +2 -2
  57. package/dist/modules/chunks/{chunk-BJTFQQQR.mjs → chunk-L6IHUN7X.mjs} +2 -2
  58. package/dist/modules/chunks/chunk-L6IHUN7X.mjs.map +7 -0
  59. package/dist/modules/chunks/{chunk-PHCUCHVL.mjs → chunk-LBQ6DFMP.mjs} +2 -2
  60. package/dist/modules/chunks/{chunk-DC3PU6SO.mjs → chunk-LVWHM3UN.mjs} +2 -2
  61. package/dist/modules/chunks/{chunk-JE4N575J.mjs → chunk-MDQMARAN.mjs} +6 -6
  62. package/dist/modules/chunks/{chunk-JE4N575J.mjs.map → chunk-MDQMARAN.mjs.map} +2 -2
  63. package/dist/modules/chunks/{chunk-NSPN5OQ5.mjs → chunk-MLXRIWJA.mjs} +2 -2
  64. package/dist/modules/chunks/{chunk-FVSDKOXR.mjs → chunk-N2SH3JGI.mjs} +3 -3
  65. package/dist/modules/chunks/{chunk-5WVRCLHN.mjs → chunk-N7NXZ6R3.mjs} +4 -4
  66. package/dist/modules/chunks/{chunk-5WVRCLHN.mjs.map → chunk-N7NXZ6R3.mjs.map} +2 -2
  67. package/dist/modules/chunks/{chunk-EW7VMNZA.mjs → chunk-O5QX6H3U.mjs} +5 -5
  68. package/dist/modules/chunks/{chunk-4RTL3LS3.mjs → chunk-PCQNUFDL.mjs} +7 -7
  69. package/dist/modules/chunks/chunk-PCQNUFDL.mjs.map +7 -0
  70. package/dist/modules/chunks/{chunk-V4SOFUJI.mjs → chunk-Q7M7VUOZ.mjs} +6 -6
  71. package/dist/modules/chunks/{chunk-NZ4N7AVG.mjs → chunk-QB33CMEU.mjs} +2 -2
  72. package/dist/modules/chunks/{chunk-QYJZ3SOV.mjs → chunk-QJHQN6OD.mjs} +5 -5
  73. package/dist/modules/chunks/chunk-QJHQN6OD.mjs.map +7 -0
  74. package/dist/modules/chunks/{chunk-OGFZB75B.mjs → chunk-QW2VT3XB.mjs} +2 -2
  75. package/dist/modules/chunks/{chunk-EQRDY5CQ.mjs → chunk-RFTLGEB5.mjs} +2 -2
  76. package/dist/modules/chunks/{chunk-CRPXFJ6K.mjs → chunk-RYYKMDNI.mjs} +3 -3
  77. package/dist/modules/chunks/{chunk-A7HXBQUG.mjs → chunk-SFB5BDTB.mjs} +2 -2
  78. package/dist/modules/chunks/{chunk-SSVRSFTX.mjs → chunk-SNICHQJP.mjs} +2 -2
  79. package/dist/modules/chunks/{chunk-KY2AWNDR.mjs → chunk-SPGFO2TA.mjs} +2 -2
  80. package/dist/modules/chunks/{chunk-XOZ5EMNY.mjs → chunk-TMPTVIAP.mjs} +2 -2
  81. package/dist/modules/chunks/{chunk-D3GX7HWI.mjs → chunk-UWJYROKS.mjs} +5 -5
  82. package/dist/modules/chunks/{chunk-AOD6XLJC.mjs → chunk-UZH2664E.mjs} +2 -2
  83. package/dist/modules/chunks/{chunk-ZRG7LDCA.mjs → chunk-VC4OEPDH.mjs} +2 -2
  84. package/dist/modules/chunks/{chunk-L24HPIQP.mjs → chunk-VKWEA6NG.mjs} +27 -27
  85. package/dist/modules/chunks/{chunk-5SHQXSSM.mjs → chunk-VSJOW7J4.mjs} +5 -5
  86. package/dist/modules/chunks/{chunk-5N5FDO5Y.mjs → chunk-WFM434WJ.mjs} +2 -2
  87. package/dist/modules/chunks/{chunk-QQP7ZGQD.mjs → chunk-WJNASQF2.mjs} +2 -2
  88. package/dist/modules/chunks/{chunk-FSYQ3LBQ.mjs → chunk-XUNDH3E7.mjs} +2 -2
  89. package/dist/modules/chunks/{chunk-LOVO3P2Q.mjs → chunk-YDARD4EP.mjs} +2 -2
  90. package/dist/modules/chunks/{chunk-LCVL3V5U.mjs → chunk-YU3HRQX7.mjs} +4 -4
  91. package/dist/modules/chunks/{chunk-M7XSCLYV.mjs → chunk-ZRE7BDDB.mjs} +15 -4
  92. package/dist/modules/chunks/chunk-ZRE7BDDB.mjs.map +7 -0
  93. package/dist/modules/cli-contributions.mjs +14 -14
  94. package/dist/modules/cli.mjs +5 -5
  95. package/dist/modules/command-executor.mjs +3 -3
  96. package/dist/modules/embedded.mjs +28 -28
  97. package/dist/modules/extension-bridge.mjs +4 -4
  98. package/dist/modules/frontend-root.mjs +46 -46
  99. package/dist/modules/index.mjs +64 -64
  100. package/dist/modules/pages/scene.mjs +5 -5
  101. package/dist/modules/plugin.mjs +34 -34
  102. package/dist/modules/plugins/asset/frontend.mjs +10 -10
  103. package/dist/modules/plugins/asset/identity.mjs +9 -9
  104. package/dist/modules/plugins/asset/ui.mjs +3 -3
  105. package/dist/modules/plugins/content-browser/frontend.mjs +3 -3
  106. package/dist/modules/plugins/content-browser/identity.mjs +2 -2
  107. package/dist/modules/plugins/content-browser/ui.mjs +3 -3
  108. package/dist/modules/plugins/display/backend.mjs +3 -3
  109. package/dist/modules/plugins/display/frontend.mjs +5 -5
  110. package/dist/modules/plugins/display/identity.mjs +2 -2
  111. package/dist/modules/plugins/display/ui.mjs +3 -3
  112. package/dist/modules/plugins/inspector/frontend.mjs +3 -3
  113. package/dist/modules/plugins/inspector/identity.mjs +2 -2
  114. package/dist/modules/plugins/inspector/ui.mjs +3 -3
  115. package/dist/modules/plugins/material/frontend.mjs +10 -10
  116. package/dist/modules/plugins/material/identity.mjs +9 -9
  117. package/dist/modules/plugins/material/ui.mjs +10 -10
  118. package/dist/modules/plugins/mesh/frontend.mjs +10 -10
  119. package/dist/modules/plugins/mesh/identity.mjs +9 -9
  120. package/dist/modules/plugins/mesh/ui.mjs +10 -10
  121. package/dist/modules/plugins/plugins/api.mjs +4 -4
  122. package/dist/modules/plugins/plugins/backend.mjs +7 -7
  123. package/dist/modules/plugins/plugins/cli.mjs +5 -5
  124. package/dist/modules/plugins/plugins/frontend.mjs +3 -3
  125. package/dist/modules/plugins/plugins/identity.mjs +2 -2
  126. package/dist/modules/plugins/plugins/runtime.mjs +6 -6
  127. package/dist/modules/plugins/plugins/ui/panel.mjs +3 -3
  128. package/dist/modules/plugins/plugins/ui.mjs +4 -4
  129. package/dist/modules/plugins/scene/frontend.mjs +5 -5
  130. package/dist/modules/plugins/scene/identity.mjs +2 -2
  131. package/dist/modules/plugins/scene-tree/frontend.mjs +3 -3
  132. package/dist/modules/plugins/scene-tree/identity.mjs +2 -2
  133. package/dist/modules/plugins/scene-tree/ui.mjs +3 -3
  134. package/dist/modules/plugins/texture/frontend.mjs +10 -10
  135. package/dist/modules/plugins/texture/identity.mjs +9 -9
  136. package/dist/modules/plugins/texture/ui.mjs +10 -10
  137. package/dist/modules/plugins/viewport/frontend.mjs +12 -12
  138. package/dist/modules/plugins/viewport/identity.mjs +2 -2
  139. package/dist/modules/plugins/viewport/presentation.mjs +4 -4
  140. package/dist/modules/plugins/viewport/schema.mjs +2 -2
  141. package/dist/modules/plugins/viewport/workspace-shell.mjs +9 -9
  142. package/dist/modules/product.mjs +34 -34
  143. package/dist/modules/shell/frontend.mjs +1 -1
  144. package/dist/modules/viewer/catalog/backend.mjs +30 -30
  145. package/dist/modules/viewer/catalog/frontend.mjs +42 -42
  146. package/dist/modules/viewer/catalog/shared.mjs +20 -20
  147. package/dist/modules/viewer/catalog.mjs +50 -50
  148. package/dist/modules/viewer/cli.mjs +10 -10
  149. package/dist/modules/viewer-host/frontend.mjs +48 -48
  150. package/dist/modules/viewer-host/page-registry.mjs +6 -6
  151. package/dist/modules/viewer-host.mjs +6 -6
  152. package/dist/modules/viewer.mjs +50 -50
  153. package/dist/modules/workspace/api.mjs +1 -1
  154. package/dist/modules/workspace/backend.mjs +10 -10
  155. package/dist/modules/workspace/broker.mjs +9 -9
  156. package/dist/modules/workspace/cli.mjs +2 -2
  157. package/dist/modules/workspace/client.mjs +3 -3
  158. package/dist/modules/workspace/command-error.mjs +2 -2
  159. package/dist/modules/workspace/contract.mjs +1 -1
  160. package/dist/modules/workspace/engine-adapter.mjs +3 -3
  161. package/dist/modules/workspace/extension-bridge.mjs +4 -4
  162. package/dist/modules/workspace/frontend-plugin.mjs +8 -8
  163. package/dist/modules/workspace/frontend.mjs +9 -9
  164. package/dist/modules/workspace/page-title.mjs +3 -3
  165. package/dist/modules/workspace/presentation.mjs +4 -4
  166. package/dist/modules/workspace/preview-surface.mjs +7 -7
  167. package/dist/modules/workspace/project-session.mjs +2 -2
  168. package/dist/modules/workspace/render-resize-sync.mjs +2 -2
  169. package/dist/modules/workspace/resident.mjs +4 -4
  170. package/dist/modules/workspace/resource-open.mjs +5 -5
  171. package/dist/modules/workspace/resource-page.mjs +8 -8
  172. package/dist/modules/workspace/tool-runtime.mjs +3 -3
  173. package/dist/modules/workspace/view-trace.mjs +3 -3
  174. package/dist/modules/workspace/workspace-recovery.mjs +4 -4
  175. package/dist/modules/workspace/workspace-state.mjs +2 -2
  176. package/dist/modules/workspace-frontend.mjs +8 -8
  177. package/dist/viewer/assets/{embedded-BZSPh0if.js → embedded-DRb0MUIg.js} +2 -2
  178. package/dist/viewer/assets/{embedded-BZSPh0if.js.map → embedded-DRb0MUIg.js.map} +1 -1
  179. package/dist/viewer/assets/{main-CmJEE-8D.js → main-CR_6HeJw.js} +5 -5
  180. package/dist/viewer/assets/main-CR_6HeJw.js.map +1 -0
  181. package/dist/viewer/assets/{panels-lazy-DqCwhGd9.js → panels-lazy-DdciEvKU.js} +19 -19
  182. package/dist/viewer/assets/{panels-lazy-DqCwhGd9.js.map → panels-lazy-DdciEvKU.js.map} +1 -1
  183. package/dist/viewer/assets/{panels-ui-Cm3As_jE.js → panels-ui-C7F0y3k-.js} +5 -5
  184. package/dist/viewer/assets/panels-ui-C7F0y3k-.js.map +1 -0
  185. package/dist/viewer/assets/{wgpu_wasm--oeqTwVY.js → wgpu_wasm-cNR5izZM.js} +126 -0
  186. package/dist/viewer/assets/{wgpu_wasm_bg-WoZ1YI1I.wasm → wgpu_wasm_bg-Dps0jNcQ.wasm} +0 -0
  187. package/dist/viewer/index.html +3 -3
  188. package/dist/viewer/panels.js +1 -1
  189. package/package.json +2 -2
  190. package/skills/forgeax-view-cli/SKILL.md +7 -0
  191. package/dist/modules/chunks/chunk-4RTL3LS3.mjs.map +0 -7
  192. package/dist/modules/chunks/chunk-BJTFQQQR.mjs.map +0 -7
  193. package/dist/modules/chunks/chunk-CEB76QBE.mjs.map +0 -7
  194. package/dist/modules/chunks/chunk-M7XSCLYV.mjs.map +0 -7
  195. package/dist/modules/chunks/chunk-P27F2TZN.mjs.map +0 -7
  196. package/dist/modules/chunks/chunk-QYJZ3SOV.mjs.map +0 -7
  197. package/dist/viewer/assets/main-CmJEE-8D.js.map +0 -1
  198. package/dist/viewer/assets/panels-ui-Cm3As_jE.js.map +0 -1
  199. /package/dist/modules/chunks/{chunk-OS7BK3FO.mjs.map → chunk-2CMCY54A.mjs.map} +0 -0
  200. /package/dist/modules/chunks/{chunk-CYQ7BITZ.mjs.map → chunk-3FBX3P3H.mjs.map} +0 -0
  201. /package/dist/modules/chunks/{chunk-VD4QU7KY.mjs.map → chunk-45WL24XN.mjs.map} +0 -0
  202. /package/dist/modules/chunks/{chunk-FSSKCXPL.mjs.map → chunk-4FYKRL46.mjs.map} +0 -0
  203. /package/dist/modules/chunks/{chunk-Y4SFATAM.mjs.map → chunk-4MJHVZMB.mjs.map} +0 -0
  204. /package/dist/modules/chunks/{chunk-D3ISMGT6.mjs.map → chunk-5HVXQEO3.mjs.map} +0 -0
  205. /package/dist/modules/chunks/{chunk-J7QRK3FU.mjs.map → chunk-66LM6NO6.mjs.map} +0 -0
  206. /package/dist/modules/chunks/{chunk-QNSUBUZF.mjs.map → chunk-6J27SWMY.mjs.map} +0 -0
  207. /package/dist/modules/chunks/{chunk-QNJL265P.mjs.map → chunk-6VK7HB4X.mjs.map} +0 -0
  208. /package/dist/modules/chunks/{chunk-AZHCKPUL.mjs.map → chunk-6WZZ7TIC.mjs.map} +0 -0
  209. /package/dist/modules/chunks/{chunk-CVIF6DYH.mjs.map → chunk-7MWZK7HS.mjs.map} +0 -0
  210. /package/dist/modules/chunks/{chunk-7YWMB7HV.mjs.map → chunk-A7OGXJAV.mjs.map} +0 -0
  211. /package/dist/modules/chunks/{chunk-KOBAWLZL.mjs.map → chunk-AUINYWZP.mjs.map} +0 -0
  212. /package/dist/modules/chunks/{chunk-R6MT6F3T.mjs.map → chunk-B24VYGHV.mjs.map} +0 -0
  213. /package/dist/modules/chunks/{chunk-M66NDY35.mjs.map → chunk-C2AMOM7H.mjs.map} +0 -0
  214. /package/dist/modules/chunks/{chunk-EOW4JGVV.mjs.map → chunk-C3WVSJZF.mjs.map} +0 -0
  215. /package/dist/modules/chunks/{chunk-TFBSEYKW.mjs.map → chunk-CAXCOZ7Y.mjs.map} +0 -0
  216. /package/dist/modules/chunks/{chunk-25PFC2DY.mjs.map → chunk-CXFQME65.mjs.map} +0 -0
  217. /package/dist/modules/chunks/{chunk-P3ZW2T37.mjs.map → chunk-CYU3WWN6.mjs.map} +0 -0
  218. /package/dist/modules/chunks/{chunk-SKZC6VTV.mjs.map → chunk-D2LZIQE2.mjs.map} +0 -0
  219. /package/dist/modules/chunks/{chunk-QNUBIFAY.mjs.map → chunk-DC5JP46Y.mjs.map} +0 -0
  220. /package/dist/modules/chunks/{chunk-7MQIGD6Q.mjs.map → chunk-DOU4MNMQ.mjs.map} +0 -0
  221. /package/dist/modules/chunks/{chunk-JKDBKS7P.mjs.map → chunk-E4G4HDOC.mjs.map} +0 -0
  222. /package/dist/modules/chunks/{chunk-XXJ32F5P.mjs.map → chunk-EZAJ66NW.mjs.map} +0 -0
  223. /package/dist/modules/chunks/{chunk-5PZL6W3F.mjs.map → chunk-FIWL6TQS.mjs.map} +0 -0
  224. /package/dist/modules/chunks/{chunk-K4C5WOTT.mjs.map → chunk-FSSARTVM.mjs.map} +0 -0
  225. /package/dist/modules/chunks/{chunk-5HJ336VM.mjs.map → chunk-FXXPWAXM.mjs.map} +0 -0
  226. /package/dist/modules/chunks/{chunk-43L37UYV.mjs.map → chunk-G2QCXN56.mjs.map} +0 -0
  227. /package/dist/modules/chunks/{chunk-4ZI5DFBR.mjs.map → chunk-GUVUL6D2.mjs.map} +0 -0
  228. /package/dist/modules/chunks/{chunk-MFEFV3YF.mjs.map → chunk-I32EONBF.mjs.map} +0 -0
  229. /package/dist/modules/chunks/{chunk-DX4M6LZH.mjs.map → chunk-IGIELQZ2.mjs.map} +0 -0
  230. /package/dist/modules/chunks/{chunk-U5LBMAG3.mjs.map → chunk-IMDR26Y3.mjs.map} +0 -0
  231. /package/dist/modules/chunks/{chunk-MUBV2LNK.mjs.map → chunk-JVOHFCI4.mjs.map} +0 -0
  232. /package/dist/modules/chunks/{chunk-TPLT4PBX.mjs.map → chunk-KJTMDFFX.mjs.map} +0 -0
  233. /package/dist/modules/chunks/{chunk-WC6NGMGI.mjs.map → chunk-KPLESRQY.mjs.map} +0 -0
  234. /package/dist/modules/chunks/{chunk-ZW7LLDOL.mjs.map → chunk-KUOWDTI6.mjs.map} +0 -0
  235. /package/dist/modules/chunks/{chunk-PHCUCHVL.mjs.map → chunk-LBQ6DFMP.mjs.map} +0 -0
  236. /package/dist/modules/chunks/{chunk-DC3PU6SO.mjs.map → chunk-LVWHM3UN.mjs.map} +0 -0
  237. /package/dist/modules/chunks/{chunk-NSPN5OQ5.mjs.map → chunk-MLXRIWJA.mjs.map} +0 -0
  238. /package/dist/modules/chunks/{chunk-FVSDKOXR.mjs.map → chunk-N2SH3JGI.mjs.map} +0 -0
  239. /package/dist/modules/chunks/{chunk-EW7VMNZA.mjs.map → chunk-O5QX6H3U.mjs.map} +0 -0
  240. /package/dist/modules/chunks/{chunk-V4SOFUJI.mjs.map → chunk-Q7M7VUOZ.mjs.map} +0 -0
  241. /package/dist/modules/chunks/{chunk-NZ4N7AVG.mjs.map → chunk-QB33CMEU.mjs.map} +0 -0
  242. /package/dist/modules/chunks/{chunk-OGFZB75B.mjs.map → chunk-QW2VT3XB.mjs.map} +0 -0
  243. /package/dist/modules/chunks/{chunk-EQRDY5CQ.mjs.map → chunk-RFTLGEB5.mjs.map} +0 -0
  244. /package/dist/modules/chunks/{chunk-CRPXFJ6K.mjs.map → chunk-RYYKMDNI.mjs.map} +0 -0
  245. /package/dist/modules/chunks/{chunk-A7HXBQUG.mjs.map → chunk-SFB5BDTB.mjs.map} +0 -0
  246. /package/dist/modules/chunks/{chunk-SSVRSFTX.mjs.map → chunk-SNICHQJP.mjs.map} +0 -0
  247. /package/dist/modules/chunks/{chunk-KY2AWNDR.mjs.map → chunk-SPGFO2TA.mjs.map} +0 -0
  248. /package/dist/modules/chunks/{chunk-XOZ5EMNY.mjs.map → chunk-TMPTVIAP.mjs.map} +0 -0
  249. /package/dist/modules/chunks/{chunk-D3GX7HWI.mjs.map → chunk-UWJYROKS.mjs.map} +0 -0
  250. /package/dist/modules/chunks/{chunk-AOD6XLJC.mjs.map → chunk-UZH2664E.mjs.map} +0 -0
  251. /package/dist/modules/chunks/{chunk-ZRG7LDCA.mjs.map → chunk-VC4OEPDH.mjs.map} +0 -0
  252. /package/dist/modules/chunks/{chunk-L24HPIQP.mjs.map → chunk-VKWEA6NG.mjs.map} +0 -0
  253. /package/dist/modules/chunks/{chunk-5SHQXSSM.mjs.map → chunk-VSJOW7J4.mjs.map} +0 -0
  254. /package/dist/modules/chunks/{chunk-5N5FDO5Y.mjs.map → chunk-WFM434WJ.mjs.map} +0 -0
  255. /package/dist/modules/chunks/{chunk-QQP7ZGQD.mjs.map → chunk-WJNASQF2.mjs.map} +0 -0
  256. /package/dist/modules/chunks/{chunk-FSYQ3LBQ.mjs.map → chunk-XUNDH3E7.mjs.map} +0 -0
  257. /package/dist/modules/chunks/{chunk-LOVO3P2Q.mjs.map → chunk-YDARD4EP.mjs.map} +0 -0
  258. /package/dist/modules/chunks/{chunk-LCVL3V5U.mjs.map → chunk-YU3HRQX7.mjs.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../packages/view-workspace-core/src/engine-adapter.ts"],
4
- "sourcesContent": ["import type { EngineWorkspaceProvider, EngineWorkspaceCameraInput, EngineWorkspacePreview } from '@forgeax/engine/app';\nimport type { WorkspaceAsset, WorkspaceProject } from './contract.ts';\nimport { workspaceDiagnosticRecord } from './command-error.ts';\ntype EngineAssetEntry = Partial<WorkspaceAsset> & { lifecycle?: string; state?: string; receiptUrl?: string };\ntype AssetAdapterInput = { project?: WorkspaceProject; root?: string; asset?: EngineAssetEntry; subject?: unknown; requestId?: string; sourcePath?: string; expectedRevision?: string; mode?: 'rebuild' | 'cold-cook' };\ntype CapabilityMethod = (...args: unknown[]) => unknown;\nimport { ViewWorkspaceError } from './contract.ts';\n\n/**\n * View binds the Engine public workspace / DevKit / ScriptablePack surfaces.\n * It does not invent inspectAsset, applyParams, cookAsset, or inspectDdc.\n *\n * Engine owners:\n * - catalog: `assetList` / `asset.list` / existing `listAssets` \u2192 PackEntry[]\n * - inspect: DevKit `assetInspect({ root, subject })` plus optional\n * ScriptablePack `inspect(sourcePath)` / gateway `inspect-meta`\n * - cook: ScriptablePack `rebuild(sourcePath, mode)` / gateway\n * `rebuild`|`cold-cook` / ToolClient `asset-source.rebuild`|`asset-source.cold-cook`\n */\nexport const VIEW_ENGINE_WORKSPACE_ADAPTER = Object.freeze({\n openProject: 'openProject({ root })',\n closeProject: 'closeProject({ project })',\n listAssets: 'assetList({ root }) | listAssets({ project })',\n openPreview: 'openPreview({ project, asset, width, height })',\n closePreview: 'preview.close()',\n resizePreview: 'preview.resize({ width, height })',\n getCamera: 'preview.getCamera()',\n beginCamera: 'preview.beginCameraInteraction({ interactionId, baseVersion, clientId })',\n updateCamera: 'preview.updateCameraDraft({ interactionId, input | camera })',\n commitCamera: 'preview.commitCamera({ interactionId, operationId, expectedVersion, camera })',\n abortCamera: 'preview.abortCamera({ interactionId, reason })',\n capture: 'preview.capture(options)',\n assetInspect: 'assetInspect({ root, subject })',\n packInspect: 'ScriptablePackAuthoringPort.inspect(sourcePath)',\n packRebuild: \"ScriptablePackAuthoringPort.rebuild(sourcePath, 'rebuild' | 'cold-cook')\",\n packGateway: \"gateway.execute({ kind: 'inspect-meta' | 'rebuild' | 'cold-cook', sourcePath, requestId, expectedRevision })\",\n packTools: \"ToolClient.run('asset-source.rebuild' | 'asset-source.cold-cook', args)\",\n});\n\nexport const VIEW_ENGINE_ASSET_SOURCE_TOOLS = Object.freeze({\n rebuild: 'asset-source.rebuild',\n 'cold-cook': 'asset-source.cold-cook',\n});\n\nfunction missing(name: string): never {\n throw new ViewWorkspaceError(\n 'view-engine-capability-unavailable',\n `Engine workspace capability ${name} to be installed`,\n 'Build and install the matching Engine workspace plugin before opening a project.',\n { capability: name },\n );\n}\n\nfunction method(source: unknown, names: readonly string[], name: string): CapabilityMethod;\nfunction method(source: unknown, names: readonly string[], name: string, options: { optional: true }): CapabilityMethod | undefined;\nfunction method(source: unknown, names: readonly string[], name: string, { optional = false }: { optional?: boolean } = {}) {\n const methods = workspaceDiagnosticRecord(source);\n for (const candidate of names) {\n if (typeof methods[candidate] === 'function') return (methods[candidate] as CapabilityMethod).bind(source);\n }\n return optional ? undefined : () => missing(name);\n}\n\nfunction asObject<T extends object = Record<string, unknown>>(value: unknown, name: string): T {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new ViewWorkspaceError(\n 'view-engine-invalid-result',\n `Engine ${name} to return an object`,\n 'Inspect the Engine workspace plugin result contract.',\n { capability: name },\n );\n }\n return value as T;\n}\n\nfunction previewMethod(preview: unknown, names: readonly string[], name: string) {\n // Engine's public shape puts operations on the outer preview. `handle` is\n // an opaque resource bundle and must never become a second operation\n // surface, otherwise a client can accidentally bypass the Engine contract.\n const methods = workspaceDiagnosticRecord(preview);\n for (const candidate of names) {\n if (typeof methods[candidate] === 'function') return (methods[candidate] as CapabilityMethod).bind(preview);\n }\n return () => missing(name);\n}\n\nfunction engineFailure(error: unknown, capability: string): never {\n if (error instanceof ViewWorkspaceError) throw error;\n const payload = error !== null && typeof error === 'object' ? workspaceDiagnosticRecord(error) : { message: String(error) };\n const message =\n typeof payload.message === 'string' && payload.message.trim() !== ''\n ? payload.message\n : String(error);\n const code =\n typeof payload.code === 'string' && payload.code.length > 0\n ? payload.code\n : 'view-engine-invalid-result';\n throw new ViewWorkspaceError(\n code,\n typeof payload.expected === 'string' ? payload.expected : message,\n typeof payload.hint === 'string' ? payload.hint : message,\n {\n capability,\n message,\n ...(typeof payload.name === 'string' ? { name: payload.name } : {}),\n ...(typeof payload.stack === 'string' ? { stack: payload.stack } : {}),\n ...(payload.detail !== null && typeof payload.detail === 'object' && !Array.isArray(payload.detail)\n ? payload.detail\n : payload.detail === undefined\n ? {}\n : { engineDetail: payload.detail }),\n ...(typeof payload.actual === 'string' ? { actual: payload.actual } : {}),\n },\n );\n}\n\nfunction unwrapEngineResult(result: unknown, capability: string): unknown {\n if (Array.isArray(result)) return result;\n if (result === undefined) return result;\n if (result !== null && typeof result === 'object') {\n const record = workspaceDiagnosticRecord(result);\n if ('ok' in result) {\n if (record.ok === true) return record.value;\n engineFailure(record.error ?? result, capability);\n }\n if (record.outcome === 'succeeded') return record.result;\n if (record.outcome === 'failed') engineFailure(record.failure ?? result, capability);\n }\n return result;\n}\n\nfunction projectCatalogDdc(entry: EngineAssetEntry | null | undefined) {\n if (!entry || typeof entry !== 'object') return undefined;\n if (entry.ddc !== null && typeof entry.ddc === 'object' && !Array.isArray(entry.ddc)) {\n return entry.ddc;\n }\n const receiptUrl =\n typeof entry.cookReceiptUrl === 'string'\n ? entry.cookReceiptUrl\n : typeof entry.receiptUrl === 'string'\n ? entry.receiptUrl\n : undefined;\n const packageUrl = typeof entry.packageUrl === 'string' ? entry.packageUrl : undefined;\n const state =\n typeof entry.lifecycle === 'string'\n ? entry.lifecycle\n : typeof entry.state === 'string'\n ? entry.state\n : undefined;\n if (receiptUrl === undefined && packageUrl === undefined && state === undefined) return undefined;\n return {\n ...(entry.guid === undefined ? {} : { guid: String(entry.guid) }),\n ...(state === undefined ? {} : { state }),\n ...(receiptUrl === undefined ? {} : { receiptUrl }),\n ...(packageUrl === undefined ? {} : { hint: packageUrl }),\n };\n}\n\nfunction packNamespace(source: Record<string, unknown>) {\n return workspaceDiagnosticRecord(source?.pack ?? source?.scriptablePack ?? source?.authoring ?? source?.assetSource);\n}\n\nfunction gatewayOf(source: Record<string, unknown>, pack: Record<string, unknown>) {\n const candidate = workspaceDiagnosticRecord(source?.gateway ?? pack?.gateway ?? source?.scriptablePackGateway ?? pack);\n return typeof candidate?.execute === 'function' ? candidate as { execute: (input: Record<string, unknown>) => unknown } : null;\n}\n\nfunction toolClientOf(source: Record<string, unknown>) {\n const candidate = workspaceDiagnosticRecord(source?.tools ?? source?.toolClient ?? source);\n return typeof candidate?.run === 'function' ? candidate as { run: (id: string, args: Record<string, unknown>) => unknown } : null;\n}\n\nfunction isPackTs(sourcePath: unknown): sourcePath is string {\n return typeof sourcePath === 'string' && sourcePath.endsWith('.pack.ts');\n}\n\n/**\n * Normalize the Engine public workspace capability into one call surface.\n * This function only adapts naming; all project, asset, target, scene and\n * camera behavior remains in the supplied Engine implementation.\n */\nexport function createEngineWorkspaceAdapter(engine: unknown) {\n const source = workspaceDiagnosticRecord(workspaceDiagnosticRecord(engine).workspace ?? engine);\n const projectSource = source?.project ?? source;\n const assetSource = source?.assets ?? source;\n const previewSource = source?.preview ?? source;\n const pack = packNamespace(source);\n const gateway = gatewayOf(source, pack);\n const tools = toolClientOf(source);\n\n const openProject = method(projectSource, ['openProject', 'open'], 'project.open');\n const closeProject = method(projectSource, ['closeProject', 'close'], 'project.close');\n const listAssets = method(\n assetSource,\n ['listAssets', 'list', 'assetList', 'asset.list'],\n 'assets.list',\n );\n const openPreview = method(previewSource, ['openPreview', 'openAsset', 'openScene', 'open'], 'asset.open');\n const assetInspect = method(\n assetSource,\n ['assetInspect', 'asset.inspect'],\n 'asset.inspect',\n { optional: true },\n );\n const packInspect = method(\n pack ?? {},\n ['inspect', 'inspectMeta'],\n 'asset-source.inspect-meta',\n { optional: true },\n );\n const packPreflight = method(pack ?? {}, ['preflight'], 'asset.preflight', { optional: true });\n const packRebuild = method(pack ?? {}, ['rebuild'], 'asset-source.rebuild', { optional: true });\n\n async function runTool(id: string, args: Record<string, unknown>, capability: string) {\n if (!tools) missing(capability);\n return unwrapEngineResult(await tools.run(id, args), capability);\n }\n\n async function inspectPackMeta(sourcePath: string | undefined, requestId?: string) {\n if (typeof sourcePath !== 'string' || sourcePath.length === 0) return undefined;\n if (packInspect) {\n return asObject(\n unwrapEngineResult(await packInspect(sourcePath), 'asset-source.inspect-meta'),\n 'asset-source.inspect-meta',\n );\n }\n if (gateway) {\n return asObject(\n unwrapEngineResult(\n await gateway.execute({\n kind: 'inspect-meta',\n sourcePath,\n requestId: requestId ?? 'view-inspect-meta',\n }),\n 'asset-source.inspect-meta',\n ),\n 'asset-source.inspect-meta',\n );\n }\n return undefined;\n }\n\n return Object.freeze({\n async openProject(input: Parameters<EngineWorkspaceProvider['openProject']>[0]) {\n return asObject(await openProject(input), 'project.open');\n },\n async closeProject(input: Parameters<EngineWorkspaceProvider['closeProject']>[0]) {\n return closeProject(input);\n },\n async listAssets(input: Parameters<EngineWorkspaceProvider['listAssets']>[0] & { root?: string }) {\n const result = unwrapEngineResult(\n await listAssets({\n ...input,\n root: input?.project?.root ?? input?.root,\n }),\n 'assets.list',\n );\n const entries = Array.isArray(result)\n ? result\n : Array.isArray(workspaceDiagnosticRecord(result).entries)\n ? workspaceDiagnosticRecord(result).entries\n : undefined;\n if (!Array.isArray(entries)) {\n throw new ViewWorkspaceError(\n 'view-engine-invalid-result',\n 'Engine assets.list to return an array',\n 'Inspect the Engine asset catalog plugin result.',\n { capability: 'assets.list' },\n );\n }\n return entries;\n },\n async openPreview(input: Parameters<EngineWorkspaceProvider['openPreview']>[0]) {\n let rawResult;\n try {\n rawResult = await openPreview(input);\n } catch (error) {\n const failure = workspaceDiagnosticRecord(error);\n const detail = workspaceDiagnosticRecord(failure.detail);\n if (\n failure.code === 'engine-workspace-preview-capability-unavailable' ||\n detail.code === 'engine-workspace-preview-capability-unavailable' ||\n /workspace preview (?:does not support asset kind|only supports SceneAsset)/i.test(typeof failure.message === 'string' ? failure.message : '')\n ) {\n const kind =\n typeof detail.kind === 'string' ? detail.kind : input.asset?.kind;\n throw new ViewWorkspaceError(\n 'view-workspace-asset-unsupported',\n `Engine asset.open to support asset kind ${kind}`,\n 'Use an Engine type-preview capability for this asset kind.',\n { kind },\n );\n }\n throw error;\n }\n const result = asObject(rawResult, 'asset.open');\n const target = asObject(result.target, 'asset.open target');\n if (typeof target.targetId !== 'string' && typeof target.targetId !== 'number') {\n throw new ViewWorkspaceError(\n 'view-engine-invalid-result',\n 'Engine asset.open to return a stable target.targetId',\n 'The Engine preview target must expose its identity for API routing.',\n { capability: 'asset.open' },\n );\n }\n const handle = result.handle ?? result.preview ?? result;\n return Object.freeze({\n ...result,\n target: Object.freeze({ ...target, targetId: String(target.targetId) }),\n handle,\n });\n },\n async closePreview(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const close = previewMethod(preview, ['close', 'dispose'], 'preview.close');\n return close(input);\n },\n async getCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const get = previewMethod(preview, ['getCamera', 'cameraGet'], 'camera.get');\n return get(input);\n },\n async beginCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const begin = previewMethod(preview, ['beginCameraInteraction', 'beginCamera'], 'camera.begin');\n return begin(input);\n },\n async updateCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const update = previewMethod(preview, ['updateCameraDraft', 'updateCamera'], 'camera.update');\n return update(input);\n },\n async commitCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const commit = previewMethod(preview, ['commitCamera', 'setCamera'], 'camera.commit');\n return commit(input);\n },\n async abortCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const abort = previewMethod(preview, ['abortCameraInteraction', 'abortCamera'], 'camera.abort');\n return abort(input);\n },\n async capture(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const capture = previewMethod(preview, ['capture'], 'preview.capture');\n return capture(input);\n },\n async resizePreview(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const resize = previewMethod(preview, ['resize', 'resizePreview', 'setRenderSize'], 'preview.resize');\n return resize(input);\n },\n async inspectAsset(input: AssetAdapterInput) {\n const asset = input?.asset ?? {};\n const root = input?.project?.root ?? input?.root;\n const subject = input?.subject ?? asset.guid;\n let entry = asset;\n if (assetInspect) {\n const inspected = unwrapEngineResult(\n await assetInspect({\n ...input,\n root,\n subject,\n }),\n 'asset.inspect',\n );\n entry = asObject<EngineAssetEntry>(inspected, 'asset.inspect');\n } else if (tools) {\n try {\n entry = asObject<EngineAssetEntry>(\n unwrapEngineResult(\n await tools.run('asset.inspect', { root, subject }),\n 'asset.inspect',\n ),\n 'asset.inspect',\n );\n } catch (error) {\n if (workspaceDiagnosticRecord(error).code === 'view-engine-capability-unavailable') throw error;\n if (!asset?.guid) throw error;\n }\n }\n const sourcePath = entry.sourcePath ?? asset.sourcePath;\n const packMeta = isPackTs(sourcePath) ? await inspectPackMeta(sourcePath, input?.requestId) : undefined;\n if (!entry?.guid && !asset?.guid) missing('asset.inspect');\n const revision = packMeta?.revision ?? entry.revision ?? asset.revision;\n return {\n guid: entry.guid ?? asset.guid,\n asset: { ...asset, ...entry },\n ...(sourcePath === undefined\n ? {}\n : {\n source: {\n path: sourcePath,\n ...(isPackTs(sourcePath) ? { kind: 'pack.ts' } : {}),\n ...(revision === undefined ? {} : { revision: String(revision) }),\n },\n }),\n ...(packMeta?.meta === undefined ? {} : { meta: packMeta.meta }),\n ...(revision === undefined ? {} : { revision: String(revision) }),\n ...(projectCatalogDdc({ ...asset, ...entry }) === undefined\n ? {}\n : { ddc: projectCatalogDdc({ ...asset, ...entry }) }),\n };\n },\n async rebuild(input: AssetAdapterInput) {\n const mode = input?.mode === 'cold-cook' ? 'cold-cook' : 'rebuild';\n const capability = VIEW_ENGINE_ASSET_SOURCE_TOOLS[mode];\n const sourcePath = input?.sourcePath ?? input?.asset?.sourcePath;\n const expectedRevision = input?.expectedRevision;\n const requestId = input?.requestId;\n const args = {\n ...(sourcePath === undefined ? {} : { sourcePath }),\n ...(input?.asset?.guid === undefined ? {} : { guid: input.asset.guid, ownerGuid: input.asset.guid }),\n ...(requestId === undefined ? {} : { requestId }),\n ...(expectedRevision === undefined ? {} : { expectedRevision }),\n };\n\n if (gateway && sourcePath) {\n return asObject(\n unwrapEngineResult(\n await gateway.execute({\n kind: mode,\n sourcePath,\n requestId: requestId ?? `view-${mode}`,\n ...(expectedRevision === undefined ? {} : { expectedRevision }),\n }),\n capability,\n ),\n capability,\n );\n }\n\n if (packRebuild && sourcePath) {\n if (packPreflight && expectedRevision !== undefined) {\n const preflight = asObject(\n unwrapEngineResult(await packPreflight(sourcePath), 'asset.preflight'),\n 'asset.preflight',\n );\n if (String(preflight.revision) !== String(expectedRevision)) {\n engineFailure(\n {\n code: 'pack-source-revision-conflict',\n expected: expectedRevision,\n actual: preflight.revision,\n hint: 'inspect the current source revision, then retry the build with a new requestId',\n detail: { sourcePath, requestId },\n },\n capability,\n );\n }\n }\n return asObject(\n unwrapEngineResult(await packRebuild(sourcePath, mode), capability),\n capability,\n );\n }\n\n if (tools) {\n return asObject(await runTool(capability, args, capability), capability);\n }\n missing(capability);\n },\n });\n}\n\nexport function isEngineWorkspaceAdapter(input: unknown) {\n const value = workspaceDiagnosticRecord(input);\n const assets = workspaceDiagnosticRecord(value?.assets ?? value);\n const preview = workspaceDiagnosticRecord(value?.preview ?? value);\n return Boolean(\n value &&\n typeof (value.openProject ?? value.open) === 'function' &&\n typeof (value.closeProject ?? value.close) === 'function' &&\n typeof (\n assets.listAssets ??\n assets.list ??\n assets.assetList ??\n assets['asset.list']\n ) === 'function' &&\n typeof (\n preview.openPreview ??\n preview.openAsset ??\n preview.openScene ??\n preview.open\n ) === 'function',\n );\n}\n"],
4
+ "sourcesContent": ["import type { EngineWorkspaceProvider, EngineWorkspaceCameraInput, EngineWorkspacePreview } from '@forgeax/engine/app';\nimport type { WorkspaceAsset, WorkspaceProject } from './contract.ts';\nimport { workspaceDiagnosticRecord } from './command-error.ts';\ntype EngineAssetEntry = Partial<WorkspaceAsset> & { lifecycle?: string; state?: string; receiptUrl?: string };\ntype AssetAdapterInput = { project?: WorkspaceProject; root?: string; asset?: EngineAssetEntry; subject?: unknown; requestId?: string; sourcePath?: string; expectedRevision?: string; mode?: 'rebuild' | 'cold-cook' };\ntype CapabilityMethod = (...args: unknown[]) => unknown;\nimport { ViewWorkspaceError } from './contract.ts';\n\n/**\n * View binds the Engine public workspace / DevKit / ScriptablePack surfaces.\n * It does not invent inspectAsset, applyParams, cookAsset, or inspectDdc.\n *\n * Engine owners:\n * - catalog: `assetList` / `asset.list` / existing `listAssets` \u2192 PackEntry[]\n * - inspect: DevKit `assetInspect({ root, subject })` plus optional\n * ScriptablePack `inspect(sourcePath)` / gateway `inspect-meta`\n * - cook: ScriptablePack `rebuild(sourcePath, mode)` / gateway\n * `rebuild`|`cold-cook` / ToolClient `asset.source.rebuild`|`asset.source.cold-cook`\n */\nexport const VIEW_ENGINE_WORKSPACE_ADAPTER = Object.freeze({\n openProject: 'openProject({ root })',\n closeProject: 'closeProject({ project })',\n listAssets: 'assetList({ root }) | listAssets({ project })',\n openPreview: 'openPreview({ project, asset, width, height })',\n closePreview: 'preview.close()',\n resizePreview: 'preview.resize({ width, height })',\n getCamera: 'preview.getCamera()',\n beginCamera: 'preview.beginCameraInteraction({ interactionId, baseVersion, clientId })',\n updateCamera: 'preview.updateCameraDraft({ interactionId, input | camera })',\n commitCamera: 'preview.commitCamera({ interactionId, operationId, expectedVersion, camera })',\n abortCamera: 'preview.abortCamera({ interactionId, reason })',\n capture: 'preview.capture(options)',\n assetInspect: 'assetInspect({ root, subject })',\n packInspect: 'ScriptablePackAuthoringPort.inspect(sourcePath)',\n packRebuild: \"ScriptablePackAuthoringPort.rebuild(sourcePath, 'rebuild' | 'cold-cook')\",\n packGateway: \"gateway.execute({ kind: 'inspect-meta' | 'rebuild' | 'cold-cook', sourcePath, requestId, expectedRevision })\",\n packTools: \"ToolClient.run('asset.source.rebuild' | 'asset.source.cold-cook', args)\",\n});\n\nexport const VIEW_ENGINE_ASSET_SOURCE_TOOLS = Object.freeze({\n rebuild: 'asset.source.rebuild',\n 'cold-cook': 'asset.source.cold-cook',\n});\n\nfunction missing(name: string): never {\n throw new ViewWorkspaceError(\n 'view-engine-capability-unavailable',\n `Engine workspace capability ${name} to be installed`,\n 'Build and install the matching Engine workspace plugin before opening a project.',\n { capability: name },\n );\n}\n\nfunction method(source: unknown, names: readonly string[], name: string): CapabilityMethod;\nfunction method(source: unknown, names: readonly string[], name: string, options: { optional: true }): CapabilityMethod | undefined;\nfunction method(source: unknown, names: readonly string[], name: string, { optional = false }: { optional?: boolean } = {}) {\n const methods = workspaceDiagnosticRecord(source);\n for (const candidate of names) {\n if (typeof methods[candidate] === 'function') return (methods[candidate] as CapabilityMethod).bind(source);\n }\n return optional ? undefined : () => missing(name);\n}\n\nfunction asObject<T extends object = Record<string, unknown>>(value: unknown, name: string): T {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new ViewWorkspaceError(\n 'view-engine-invalid-result',\n `Engine ${name} to return an object`,\n 'Inspect the Engine workspace plugin result contract.',\n { capability: name },\n );\n }\n return value as T;\n}\n\nfunction previewMethod(preview: unknown, names: readonly string[], name: string) {\n // Engine's public shape puts operations on the outer preview. `handle` is\n // an opaque resource bundle and must never become a second operation\n // surface, otherwise a client can accidentally bypass the Engine contract.\n const methods = workspaceDiagnosticRecord(preview);\n for (const candidate of names) {\n if (typeof methods[candidate] === 'function') return (methods[candidate] as CapabilityMethod).bind(preview);\n }\n return () => missing(name);\n}\n\nfunction engineFailure(error: unknown, capability: string): never {\n if (error instanceof ViewWorkspaceError) throw error;\n const payload = error !== null && typeof error === 'object' ? workspaceDiagnosticRecord(error) : { message: String(error) };\n const message =\n typeof payload.message === 'string' && payload.message.trim() !== ''\n ? payload.message\n : String(error);\n const code =\n typeof payload.code === 'string' && payload.code.length > 0\n ? payload.code\n : 'view-engine-invalid-result';\n throw new ViewWorkspaceError(\n code,\n typeof payload.expected === 'string' ? payload.expected : message,\n typeof payload.hint === 'string' ? payload.hint : message,\n {\n capability,\n message,\n ...(typeof payload.name === 'string' ? { name: payload.name } : {}),\n ...(typeof payload.stack === 'string' ? { stack: payload.stack } : {}),\n ...(payload.detail !== null && typeof payload.detail === 'object' && !Array.isArray(payload.detail)\n ? payload.detail\n : payload.detail === undefined\n ? {}\n : { engineDetail: payload.detail }),\n ...(typeof payload.actual === 'string' ? { actual: payload.actual } : {}),\n },\n );\n}\n\nfunction unwrapEngineResult(result: unknown, capability: string): unknown {\n if (Array.isArray(result)) return result;\n if (result === undefined) return result;\n if (result !== null && typeof result === 'object') {\n const record = workspaceDiagnosticRecord(result);\n if ('ok' in result) {\n if (record.ok === true) return record.value;\n engineFailure(record.error ?? result, capability);\n }\n if (record.outcome === 'succeeded') return record.result;\n if (record.outcome === 'failed') engineFailure(record.failure ?? result, capability);\n }\n return result;\n}\n\nfunction projectCatalogDdc(entry: EngineAssetEntry | null | undefined) {\n if (!entry || typeof entry !== 'object') return undefined;\n if (entry.ddc !== null && typeof entry.ddc === 'object' && !Array.isArray(entry.ddc)) {\n return entry.ddc;\n }\n const receiptUrl =\n typeof entry.cookReceiptUrl === 'string'\n ? entry.cookReceiptUrl\n : typeof entry.receiptUrl === 'string'\n ? entry.receiptUrl\n : undefined;\n const packageUrl = typeof entry.packageUrl === 'string' ? entry.packageUrl : undefined;\n const state =\n typeof entry.lifecycle === 'string'\n ? entry.lifecycle\n : typeof entry.state === 'string'\n ? entry.state\n : undefined;\n if (receiptUrl === undefined && packageUrl === undefined && state === undefined) return undefined;\n return {\n ...(entry.guid === undefined ? {} : { guid: String(entry.guid) }),\n ...(state === undefined ? {} : { state }),\n ...(receiptUrl === undefined ? {} : { receiptUrl }),\n ...(packageUrl === undefined ? {} : { hint: packageUrl }),\n };\n}\n\nfunction packNamespace(source: Record<string, unknown>) {\n return workspaceDiagnosticRecord(source?.pack ?? source?.scriptablePack ?? source?.authoring ?? source?.assetSource);\n}\n\nfunction gatewayOf(source: Record<string, unknown>, pack: Record<string, unknown>) {\n const candidate = workspaceDiagnosticRecord(source?.gateway ?? pack?.gateway ?? source?.scriptablePackGateway ?? pack);\n return typeof candidate?.execute === 'function' ? candidate as { execute: (input: Record<string, unknown>) => unknown } : null;\n}\n\nfunction toolClientOf(source: Record<string, unknown>) {\n const candidate = workspaceDiagnosticRecord(source?.tools ?? source?.toolClient ?? source);\n return typeof candidate?.run === 'function' ? candidate as { run: (id: string, args: Record<string, unknown>) => unknown } : null;\n}\n\nfunction isPackTs(sourcePath: unknown): sourcePath is string {\n return typeof sourcePath === 'string' && sourcePath.endsWith('.pack.ts');\n}\n\n/**\n * Normalize the Engine public workspace capability into one call surface.\n * This function only adapts naming; all project, asset, target, scene and\n * camera behavior remains in the supplied Engine implementation.\n */\nexport function createEngineWorkspaceAdapter(engine: unknown) {\n const source = workspaceDiagnosticRecord(workspaceDiagnosticRecord(engine).workspace ?? engine);\n const projectSource = source?.project ?? source;\n const assetSource = source?.assets ?? source;\n const previewSource = source?.preview ?? source;\n const pack = packNamespace(source);\n const gateway = gatewayOf(source, pack);\n const tools = toolClientOf(source);\n\n const openProject = method(projectSource, ['openProject', 'open'], 'project.open');\n const closeProject = method(projectSource, ['closeProject', 'close'], 'project.close');\n const listAssets = method(\n assetSource,\n ['listAssets', 'list', 'assetList', 'asset.list'],\n 'assets.list',\n );\n const openPreview = method(previewSource, ['openPreview', 'openAsset', 'openScene', 'open'], 'asset.open');\n const assetInspect = method(\n assetSource,\n ['assetInspect', 'asset.inspect'],\n 'asset.inspect',\n { optional: true },\n );\n const packInspect = method(\n pack ?? {},\n ['inspect', 'inspectMeta'],\n 'asset.source.inspect-meta',\n { optional: true },\n );\n const packPreflight = method(pack ?? {}, ['preflight'], 'asset.preflight', { optional: true });\n const packRebuild = method(pack ?? {}, ['rebuild'], 'asset.source.rebuild', { optional: true });\n\n async function runTool(id: string, args: Record<string, unknown>, capability: string) {\n if (!tools) missing(capability);\n return unwrapEngineResult(await tools.run(id, args), capability);\n }\n\n async function inspectPackMeta(sourcePath: string | undefined, requestId?: string) {\n if (typeof sourcePath !== 'string' || sourcePath.length === 0) return undefined;\n if (packInspect) {\n return asObject(\n unwrapEngineResult(await packInspect(sourcePath), 'asset.source.inspect-meta'),\n 'asset.source.inspect-meta',\n );\n }\n if (gateway) {\n return asObject(\n unwrapEngineResult(\n await gateway.execute({\n kind: 'inspect-meta',\n sourcePath,\n requestId: requestId ?? 'view-inspect-meta',\n }),\n 'asset.source.inspect-meta',\n ),\n 'asset.source.inspect-meta',\n );\n }\n return undefined;\n }\n\n return Object.freeze({\n async openProject(input: Parameters<EngineWorkspaceProvider['openProject']>[0]) {\n return asObject(await openProject(input), 'project.open');\n },\n async closeProject(input: Parameters<EngineWorkspaceProvider['closeProject']>[0]) {\n return closeProject(input);\n },\n async listAssets(input: Parameters<EngineWorkspaceProvider['listAssets']>[0] & { root?: string }) {\n const result = unwrapEngineResult(\n await listAssets({\n ...input,\n root: input?.project?.root ?? input?.root,\n }),\n 'assets.list',\n );\n const entries = Array.isArray(result)\n ? result\n : Array.isArray(workspaceDiagnosticRecord(result).entries)\n ? workspaceDiagnosticRecord(result).entries\n : undefined;\n if (!Array.isArray(entries)) {\n throw new ViewWorkspaceError(\n 'view-engine-invalid-result',\n 'Engine assets.list to return an array',\n 'Inspect the Engine asset catalog plugin result.',\n { capability: 'assets.list' },\n );\n }\n return entries;\n },\n async openPreview(input: Parameters<EngineWorkspaceProvider['openPreview']>[0]) {\n let rawResult;\n try {\n rawResult = await openPreview(input);\n } catch (error) {\n const failure = workspaceDiagnosticRecord(error);\n const detail = workspaceDiagnosticRecord(failure.detail);\n if (\n failure.code === 'engine-workspace-preview-capability-unavailable' ||\n detail.code === 'engine-workspace-preview-capability-unavailable' ||\n /workspace preview (?:does not support asset kind|only supports SceneAsset)/i.test(typeof failure.message === 'string' ? failure.message : '')\n ) {\n const kind =\n typeof detail.kind === 'string' ? detail.kind : input.asset?.kind;\n throw new ViewWorkspaceError(\n 'view-workspace-asset-unsupported',\n `Engine asset.open to support asset kind ${kind}`,\n 'Use an Engine type-preview capability for this asset kind.',\n { kind },\n );\n }\n throw error;\n }\n const result = asObject(rawResult, 'asset.open');\n const target = asObject(result.target, 'asset.open target');\n if (typeof target.targetId !== 'string' && typeof target.targetId !== 'number') {\n throw new ViewWorkspaceError(\n 'view-engine-invalid-result',\n 'Engine asset.open to return a stable target.targetId',\n 'The Engine preview target must expose its identity for API routing.',\n { capability: 'asset.open' },\n );\n }\n const handle = result.handle ?? result.preview ?? result;\n return Object.freeze({\n ...result,\n target: Object.freeze({ ...target, targetId: String(target.targetId) }),\n handle,\n });\n },\n async closePreview(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const close = previewMethod(preview, ['close', 'dispose'], 'preview.close');\n return close(input);\n },\n async getCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const get = previewMethod(preview, ['getCamera', 'cameraGet'], 'camera.get');\n return get(input);\n },\n async beginCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const begin = previewMethod(preview, ['beginCameraInteraction', 'beginCamera'], 'camera.begin');\n return begin(input);\n },\n async updateCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const update = previewMethod(preview, ['updateCameraDraft', 'updateCamera'], 'camera.update');\n return update(input);\n },\n async commitCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const commit = previewMethod(preview, ['commitCamera', 'setCamera'], 'camera.commit');\n return commit(input);\n },\n async abortCamera(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const abort = previewMethod(preview, ['abortCameraInteraction', 'abortCamera'], 'camera.abort');\n return abort(input);\n },\n async capture(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const capture = previewMethod(preview, ['capture'], 'preview.capture');\n return capture(input);\n },\n async resizePreview(preview: EngineWorkspacePreview, input: EngineWorkspaceCameraInput & { reason?: string; width?: number; height?: number }) {\n const resize = previewMethod(preview, ['resize', 'resizePreview', 'setRenderSize'], 'preview.resize');\n return resize(input);\n },\n async inspectAsset(input: AssetAdapterInput) {\n const asset = input?.asset ?? {};\n const root = input?.project?.root ?? input?.root;\n const subject = input?.subject ?? asset.guid;\n let entry = asset;\n if (assetInspect) {\n const inspected = unwrapEngineResult(\n await assetInspect({\n ...input,\n root,\n subject,\n }),\n 'asset.inspect',\n );\n entry = asObject<EngineAssetEntry>(inspected, 'asset.inspect');\n } else if (tools) {\n try {\n entry = asObject<EngineAssetEntry>(\n unwrapEngineResult(\n await tools.run('asset.inspect', { root, subject }),\n 'asset.inspect',\n ),\n 'asset.inspect',\n );\n } catch (error) {\n if (workspaceDiagnosticRecord(error).code === 'view-engine-capability-unavailable') throw error;\n if (!asset?.guid) throw error;\n }\n }\n const sourcePath = entry.sourcePath ?? asset.sourcePath;\n const packMeta = isPackTs(sourcePath) ? await inspectPackMeta(sourcePath, input?.requestId) : undefined;\n if (!entry?.guid && !asset?.guid) missing('asset.inspect');\n const revision = packMeta?.revision ?? entry.revision ?? asset.revision;\n return {\n guid: entry.guid ?? asset.guid,\n asset: { ...asset, ...entry },\n ...(sourcePath === undefined\n ? {}\n : {\n source: {\n path: sourcePath,\n ...(isPackTs(sourcePath) ? { kind: 'pack.ts' } : {}),\n ...(revision === undefined ? {} : { revision: String(revision) }),\n },\n }),\n ...(packMeta?.meta === undefined ? {} : { meta: packMeta.meta }),\n ...(revision === undefined ? {} : { revision: String(revision) }),\n ...(projectCatalogDdc({ ...asset, ...entry }) === undefined\n ? {}\n : { ddc: projectCatalogDdc({ ...asset, ...entry }) }),\n };\n },\n async rebuild(input: AssetAdapterInput) {\n const mode = input?.mode === 'cold-cook' ? 'cold-cook' : 'rebuild';\n const capability = VIEW_ENGINE_ASSET_SOURCE_TOOLS[mode];\n const sourcePath = input?.sourcePath ?? input?.asset?.sourcePath;\n const expectedRevision = input?.expectedRevision;\n const requestId = input?.requestId;\n const args = {\n ...(sourcePath === undefined ? {} : { sourcePath }),\n ...(input?.asset?.guid === undefined ? {} : { guid: input.asset.guid, ownerGuid: input.asset.guid }),\n ...(requestId === undefined ? {} : { requestId }),\n ...(expectedRevision === undefined ? {} : { expectedRevision }),\n };\n\n if (gateway && sourcePath) {\n return asObject(\n unwrapEngineResult(\n await gateway.execute({\n kind: mode,\n sourcePath,\n requestId: requestId ?? `view-${mode}`,\n ...(expectedRevision === undefined ? {} : { expectedRevision }),\n }),\n capability,\n ),\n capability,\n );\n }\n\n if (packRebuild && sourcePath) {\n if (packPreflight && expectedRevision !== undefined) {\n const preflight = asObject(\n unwrapEngineResult(await packPreflight(sourcePath), 'asset.preflight'),\n 'asset.preflight',\n );\n if (String(preflight.revision) !== String(expectedRevision)) {\n engineFailure(\n {\n code: 'pack-source-revision-conflict',\n expected: expectedRevision,\n actual: preflight.revision,\n hint: 'inspect the current source revision, then retry the build with a new requestId',\n detail: { sourcePath, requestId },\n },\n capability,\n );\n }\n }\n return asObject(\n unwrapEngineResult(await packRebuild(sourcePath, mode), capability),\n capability,\n );\n }\n\n if (tools) {\n return asObject(await runTool(capability, args, capability), capability);\n }\n missing(capability);\n },\n });\n}\n\nexport function isEngineWorkspaceAdapter(input: unknown) {\n const value = workspaceDiagnosticRecord(input);\n const assets = workspaceDiagnosticRecord(value?.assets ?? value);\n const preview = workspaceDiagnosticRecord(value?.preview ?? value);\n return Boolean(\n value &&\n typeof (value.openProject ?? value.open) === 'function' &&\n typeof (value.closeProject ?? value.close) === 'function' &&\n typeof (\n assets.listAssets ??\n assets.list ??\n assets.assetList ??\n assets['asset.list']\n ) === 'function' &&\n typeof (\n preview.openPreview ??\n preview.openAsset ??\n preview.openScene ??\n preview.open\n ) === 'function',\n );\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -17,4 +17,4 @@ var shell_default = {
17
17
  export {
18
18
  shell_default
19
19
  };
20
- //# sourceMappingURL=chunk-QNSUBUZF.mjs.map
20
+ //# sourceMappingURL=chunk-6J27SWMY.mjs.map
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  connectViewWorkspace
3
- } from "./chunk-K4C5WOTT.mjs";
3
+ } from "./chunk-FSSARTVM.mjs";
4
4
  import {
5
5
  workspaceDiagnosticRecord
6
- } from "./chunk-EQRDY5CQ.mjs";
6
+ } from "./chunk-RFTLGEB5.mjs";
7
7
  import {
8
8
  VIEW_WORKSPACE_OPERATIONS
9
- } from "./chunk-QYJZ3SOV.mjs";
9
+ } from "./chunk-QJHQN6OD.mjs";
10
10
 
11
11
  // src/cli.ts
12
12
  import { randomUUID } from "node:crypto";
@@ -227,4 +227,4 @@ if (isDirectInvocation()) {
227
227
  export {
228
228
  runViewWorkspaceCli
229
229
  };
230
- //# sourceMappingURL=chunk-QNJL265P.mjs.map
230
+ //# sourceMappingURL=chunk-6VK7HB4X.mjs.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VIEW_PAGE_TYPES
3
- } from "./chunk-QYJZ3SOV.mjs";
3
+ } from "./chunk-QJHQN6OD.mjs";
4
4
  import {
5
5
  __export
6
6
  } from "./chunk-FLGC65SR.mjs";
@@ -39,4 +39,4 @@ export {
39
39
  TITLE_I18N_KEY,
40
40
  identity_exports
41
41
  };
42
- //# sourceMappingURL=chunk-AZHCKPUL.mjs.map
42
+ //# sourceMappingURL=chunk-6WZZ7TIC.mjs.map
@@ -21,11 +21,11 @@ import {
21
21
  import {
22
22
  createWorkspaceObservation,
23
23
  createWorkspaceStateReader
24
- } from "./chunk-QQP7ZGQD.mjs";
24
+ } from "./chunk-WJNASQF2.mjs";
25
25
  import {
26
26
  VIEW_WORKSPACE_TAB_ID,
27
27
  jsonUnchanged
28
- } from "./chunk-QYJZ3SOV.mjs";
28
+ } from "./chunk-QJHQN6OD.mjs";
29
29
 
30
30
  // packages/view-plugin-scene-tree/src/ui/mount.tsx
31
31
  import { createRoot } from "react-dom/client";
@@ -919,4 +919,4 @@ async function mountSceneTreePanel(props) {
919
919
  export {
920
920
  mountSceneTreePanel
921
921
  };
922
- //# sourceMappingURL=chunk-A22PJUZM.mjs.map
922
+ //# sourceMappingURL=chunk-7DFCIN3T.mjs.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../packages/view-plugin-scene-tree/src/ui/mount.tsx", "../../../packages/view-plugin-scene-tree/src/ui/SceneTreePanel.tsx", "../../../packages/view-plugin-scene-tree/src/i18n/useTranslation.ts", "../../../packages/view-plugin-scene-tree/src/hierarchy-filters.ts", "../../../packages/view-plugin-scene-tree/src/hierarchy.ts", "../../../packages/view-plugin-scene-tree/src/ui/scene-tree.css"],
4
- "sourcesContent": ["import type { ComponentProps } from 'react';\nimport '@forgeax/view-components/styles.css';\nimport { OverlayRootProvider } from '@forgeax/view-components';\nimport '../i18n/index.ts';\nimport { createRoot } from 'react-dom/client';\nimport { SceneTreePanel } from './SceneTreePanel';\nimport './scene-tree.css';\n\nexport async function mountSceneTreePanel(props: ComponentProps<typeof SceneTreePanel> & { mountElement: HTMLElement; overlayRoot?: HTMLElement }) {\n if (!props.mountElement) throw new TypeError('mountSceneTreePanel requires mountElement');\n const root = createRoot(props.mountElement);\n root.render(\n <OverlayRootProvider root={props.overlayRoot ?? props.mountElement}>\n <SceneTreePanel client={props.client} />\n </OverlayRootProvider>,\n );\n return async () => root.unmount();\n}\n", "import type { WorkspaceState } from '@forgeax/view-workspace-core/contract';\nimport {\n Box,\n Braces,\n Camera,\n ChevronDown,\n ChevronRight,\n CircleUserRound,\n Crosshair,\n Filter,\n Folder,\n Layers,\n Lightbulb,\n Maximize2,\n Minimize2,\n Settings,\n X,\n} from 'lucide-react';\nimport {\n Checkbox,\n EmptyState,\n useOverlayRoot,\n FloatingMenu,\n IconButton,\n PanelHeader,\n SearchField,\n Toolbar,\n useWorkspaceClientConnected,\n type AnchorRect,\n} from '@forgeax/view-components';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type MouseEvent,\n type ReactNode,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useTranslation } from '../i18n/useTranslation';\nimport { SCENE_TREE_ACTIONS } from '../schema.ts';\nimport type { ViewWorkspaceClient } from '@forgeax/view-workspace-core/client';\nimport { VIEW_WORKSPACE_TAB_ID, jsonUnchanged } from '@forgeax/view-workspace-core/contract';\nimport { createWorkspaceObservation, createWorkspaceStateReader } from '@forgeax/view-workspace-core/workspace-state';\nimport {\n entityMatchesSceneTreeFilters,\n hierarchyTypeCategory,\n} from '../hierarchy-filters.ts';\nimport {\n HIERARCHY_SCENE_FOLDER_ID,\n isSceneRootRow,\n sceneTreeComponentFilters,\n normalizeSceneTreeRows,\n type HierarchyRow,\n} from '../hierarchy.ts';\n\ntype SceneTreeFilterOption = {\n id: string;\n label?: string;\n count?: number;\n};\n\ntype SceneSelectionClient = Pick<\n ViewWorkspaceClient,\n 'subscribe' | 'getState' | 'selectSceneEntity' | 'clearSceneSelection' | 'getSceneTree' | 'call' | 'onDisconnect' | 'transport'\n>;\n\ntype WorkspacePreviewSnapshot = WorkspaceState;\n\ntype MenuItem =\n | { kind: 'title'; label: string; icon?: ReactNode }\n | { kind: 'separator' }\n | {\n kind: 'item';\n id: string;\n label: string;\n icon?: ReactNode;\n shortcut?: string;\n disabled?: boolean;\n danger?: boolean;\n forge?: boolean;\n children?: MenuItem[];\n action?: () => void;\n };\ntype MenuState = { x: number; y: number; items: MenuItem[] } | null;\n\nfunction rowComponentNames(row: HierarchyRow) {\n if (Array.isArray(row.componentNames) && row.componentNames.length > 0) {\n return row.componentNames;\n }\n return row.typeKey ? [String(row.typeKey)] : [];\n}\n\nfunction rowType(row: HierarchyRow) {\n if (isSceneRootRow(row)) return 'scene';\n if (row.kind === 'folder') return 'group';\n const primary = rowComponentNames(row).find((name) => name !== 'Transform') ?? row.typeKey;\n if (!primary) return 'mesh';\n return hierarchyTypeCategory(String(primary));\n}\n\nfunction filterOptionIcon(id: string) {\n switch (hierarchyTypeCategory(id)) {\n case 'camera': return <Camera size={14} />;\n case 'light': return <Lightbulb size={14} />;\n case 'character': return <CircleUserRound size={14} />;\n case 'group': return <Layers size={14} />;\n default: return <Box size={14} />;\n }\n}\n\nfunction RowIcon({ row }: { row: HierarchyRow }) {\n if (isSceneRootRow(row)) return <Folder size={15} />;\n if (row.kind === 'folder') return <Layers size={15} />;\n if (row.typeKey === 'directionalLight') return <Lightbulb size={15} />;\n if (row.typeKey === 'camera') return <Camera size={15} />;\n if (row.name === 'Player') return <CircleUserRound size={15} />;\n return <Box size={15} />;\n}\n\nfunction HierarchyContextMenu({ state, close }: { state: Exclude<MenuState, null>; close: () => void }) {\n const overlayRoot = useOverlayRoot();\n const [submenu, setSubmenu] = useState<string | null>(null);\n useEffect(() => {\n const dismiss = () => close();\n const escape = (event: KeyboardEvent) => event.key === 'Escape' && close();\n window.addEventListener('pointerdown', dismiss);\n window.addEventListener('keydown', escape);\n return () => {\n window.removeEventListener('pointerdown', dismiss);\n window.removeEventListener('keydown', escape);\n };\n }, [close]);\n const renderItems = (items: MenuItem[], nested = false) => (\n <div className={nested ? 'hier-context-submenu' : 'hier-context-menu'}>\n {items.map((item, index) => {\n if (item.kind === 'separator') return <i className=\"hier-context-separator\" key={`sep-${index}`} />;\n if (item.kind === 'title') return <div className=\"hier-context-title\" key={`title-${index}`}>{item.icon}{item.label}</div>;\n return (\n <div className=\"hier-context-item-wrap\" key={item.id} onPointerEnter={() => item.children && setSubmenu(item.id)}>\n <button\n type=\"button\"\n role=\"menuitem\"\n data-operation={item.id}\n data-danger={item.danger || undefined}\n data-forge={item.forge || undefined}\n disabled={item.disabled}\n onClick={() => {\n if (item.children) {\n setSubmenu(submenu === item.id ? null : item.id);\n return;\n }\n item.action?.();\n close();\n }}\n >\n <span className=\"hier-context-icon\">{item.icon}</span>\n <span>{item.label}</span>\n {item.shortcut ? <kbd>{item.shortcut}</kbd> : null}\n {item.children ? <ChevronRight size={12} /> : null}\n </button>\n {item.children && submenu === item.id ? renderItems(item.children, true) : null}\n </div>\n );\n })}\n </div>\n );\n return createPortal(\n <div\n className=\"hier-context-position\"\n data-action={SCENE_TREE_ACTIONS.showContextMenu}\n role=\"menu\"\n style={{\n left: Math.max(8, Math.min(state.x, window.innerWidth - 260)),\n top: Math.max(8, Math.min(state.y, window.innerHeight - 420)),\n }}\n onPointerDown={(event) => event.stopPropagation()}\n onContextMenu={(event) => event.preventDefault()}\n >\n {renderItems(state.items)}\n </div>,\n overlayRoot ?? document.body,\n );\n}\n\nfunction highlighted(value: string, query: string) {\n const index = value.toLowerCase().indexOf(query.toLowerCase());\n if (!query || index < 0) return value;\n return <>{value.slice(0, index)}<mark className=\"hl\">{value.slice(index, index + query.length)}</mark>{value.slice(index + query.length)}</>;\n}\n\nexport function SceneTreePanel(props: { client?: SceneSelectionClient }) {\n if (!props.client) {\n return (\n <EmptyState\n title=\"Scene hierarchy unavailable\"\n description=\"Connect to the View workspace API to load the Engine scene tree.\"\n />\n );\n }\n return <SceneTreeLivePanel client={props.client} />;\n}\n\nfunction useEngineSceneRows(\n client: SceneSelectionClient,\n workspace: WorkspacePreviewSnapshot | null,\n connected: boolean,\n reader: ReturnType<typeof createWorkspaceStateReader>,\n) {\n const [projection, setProjection] = useState<{ key: string; rows: HierarchyRow[]; failed: boolean; hasMore: boolean } | null>(null);\n const [pageCount, setPageCount] = useState(1);\n const target = workspace?.preview?.target;\n const projectId = workspace?.project?.id;\n const key = `${target?.targetId}:${target?.generation}`;\n const current = projection?.key === key ? projection : null;\n const rows = current?.rows ?? [];\n\n useEffect(() => { setPageCount(1); }, [target?.targetId, target?.generation]);\n\n useEffect(() => {\n if (!connected || !target?.targetId || !projectId) {\n if (!connected) return;\n setProjection(null);\n return;\n }\n const observation = createWorkspaceObservation(reader, (current: WorkspacePreviewSnapshot | null) =>\n current?.project?.id === projectId &&\n current?.preview?.target?.targetId === target.targetId &&\n current?.preview?.target?.generation === target.generation);\n const { signal } = observation;\n let timer: ReturnType<typeof setTimeout>;\n const refresh = async () => {\n if (signal.aborted) return;\n let retryDelay = 500;\n try {\n const binding = {\n tabId: VIEW_WORKSPACE_TAB_ID, projectId, targetId: target.targetId,\n targetGeneration: target.generation, signal,\n };\n const result = await client.getSceneTree({ ...binding, limit: 1000 });\n if (signal.aborted) return;\n const nodes = [...(result.nodes ?? [])];\n let nextOffset = result.nextOffset;\n for (let page = 1; page < pageCount && nextOffset !== null && nextOffset !== undefined; page++) {\n const next = await client.getSceneTree({ ...binding, offset: nextOffset, revision: String(result.revision), limit: 1000 });\n if (signal.aborted) return;\n nodes.push(...next.nodes);\n nextOffset = next.nextOffset;\n }\n if (signal.aborted) return;\n setProjection((current) => {\n const next = { key, rows: normalizeSceneTreeRows({ ...result, nodes }), hasMore: nextOffset !== null && nextOffset !== undefined, failed: false };\n if (\n current?.key === next.key &&\n current.failed === next.failed &&\n current.hasMore === next.hasMore &&\n jsonUnchanged(current.rows, next.rows)\n ) return current;\n return next;\n });\n } catch {\n if (signal.aborted) return;\n setProjection((current) => {\n if (current?.key === key && current.failed && !current.hasMore && current.rows.length === 0) return current;\n return { key, rows: [], hasMore: false, failed: true };\n });\n retryDelay = 1500;\n }\n if (!signal.aborted) {\n timer = setTimeout(refresh, retryDelay);\n }\n };\n void refresh();\n return () => { observation.dispose(); clearTimeout(timer); };\n // Include the published snapshot: React may batch A -> B -> A into one\n // render after the observation for A has already been revoked.\n }, [client, connected, projectId, target?.targetId, target?.generation, pageCount, key, reader, workspace]);\n\n return { rows, filterOptions: sceneTreeComponentFilters(rows), failed: current?.failed ?? false, hasMore: current?.hasMore ?? false, loadMore: () => setPageCount(value => value + 1) };\n}\n\nfunction SceneTreeLivePanel({ client }: { client: SceneSelectionClient }) {\n const { t } = useTranslation();\n const reader = useMemo(() => createWorkspaceStateReader(client), [client]);\n const workspace = useSyncExternalStore(\n reader.subscribe,\n () => reader.getSnapshot() as WorkspacePreviewSnapshot | null,\n () => reader.getSnapshot() as WorkspacePreviewSnapshot | null,\n );\n const connected = useWorkspaceClientConnected(client);\n const { rows, filterOptions, failed, hasMore, loadMore } = useEngineSceneRows(client, workspace, connected, reader);\n\n if (!workspace?.preview?.target?.targetId) {\n return (\n <EmptyState\n title={t('sceneTree.unavailable')}\n description=\"Open a scene preview from the Content Browser to load the Engine hierarchy.\"\n />\n );\n }\n if (failed) {\n return (\n <EmptyState\n title={t('sceneTree.unavailable')}\n description={t('sceneTree.loadErrorDescription')}\n />\n );\n }\n if (rows.length === 0) return <EmptyState title=\"Loading hierarchy\" description=\"Reading the selected Engine target.\" />;\n return <>\n {hasMore && <button type=\"button\" onClick={loadMore}>Showing {Math.max(0, rows.length - 1)} entities. Load more</button>}\n <SceneTreeRowsPanel key={`${workspace.preview?.target?.targetId}:${workspace.preview?.target?.generation}`}\n client={client} rows={rows} filterOptions={filterOptions} />\n </>;\n}\n\nfunction SceneTreeRowsPanel({\n client,\n rows,\n filterOptions,\n}: {\n client: SceneSelectionClient;\n rows: HierarchyRow[];\n filterOptions: SceneTreeFilterOption[];\n}) {\n const { t } = useTranslation();\n const reader = useMemo(() => createWorkspaceStateReader(client), [client]);\n const workspace = useSyncExternalStore(\n reader.subscribe,\n () => reader.getSnapshot() as (WorkspacePreviewSnapshot & { sceneSelection?: { primary?: { entityId: string } | null } | null }) | null,\n () => reader.getSnapshot() as (WorkspacePreviewSnapshot & { sceneSelection?: { primary?: { entityId: string } | null } | null }) | null,\n );\n const externalEntityId = workspace?.sceneSelection?.primary?.entityId ?? null;\n const sceneIdentity = workspace?.preview?.asset?.guid ?? workspace?.preview?.target?.targetId ?? null;\n const rowLabel = useCallback(\n (row: HierarchyRow) => (isSceneRootRow(row) ? t('sceneTree.sceneRoot') : row.name),\n [t],\n );\n const typeLabelFor = useCallback(\n (row: HierarchyRow) => {\n if (row.kind === 'folder') return t('sceneTree.types.folder');\n if (row.typeKey) {\n const key = `sceneTree.types.${row.typeKey}`;\n const label = t(key);\n return label === key ? t('sceneTree.types.entity') : label;\n }\n return '';\n },\n [t],\n );\n const componentTypeLabel = useCallback((id: string) => {\n const key = `sceneTree.types.${id}`;\n const label = t(key);\n return label === key ? id : label;\n }, [t]);\n const resolvedFilterOptions = useMemo(\n () => filterOptions.map((option) => ({\n ...option,\n label: option.label ?? componentTypeLabel(option.id),\n })),\n [componentTypeLabel, filterOptions],\n );\n const [query, setQuery] = useState('');\n const [filters, setFilters] = useState(new Set<string>());\n const [expanded, setExpanded] = useState(() => new Set(\n rows.filter((row) => row.expanded || isSceneRootRow(row)).map((row) => row.id),\n ));\n const [columns, setColumns] = useState({ type: true, id: false });\n const [headerMenu, setHeaderMenu] = useState<'filter' | 'settings' | null>(null);\n const [headerMenuAnchor, setHeaderMenuAnchor] = useState<AnchorRect | null>(null);\n const filterButtonRef = useRef<HTMLButtonElement>(null);\n const settingsButtonRef = useRef<HTMLButtonElement>(null);\n const [contextMenu, setContextMenu] = useState<MenuState>(null);\n const [selected, setSelected] = useState(new Set<string>());\n const [anchor, setAnchor] = useState<string | null>(null);\n\n useEffect(() => {\n setExpanded((current) => {\n if (current.has(HIERARCHY_SCENE_FOLDER_ID)) return current;\n const next = new Set(current);\n next.add(HIERARCHY_SCENE_FOLDER_ID);\n return next;\n });\n }, [sceneIdentity]);\n\n useEffect(() => {\n if (externalEntityId && rows.some((row) => row.id === externalEntityId)) {\n setSelected(new Set([externalEntityId]));\n setAnchor(externalEntityId);\n } else if (!externalEntityId) {\n setSelected(new Set());\n setAnchor(null);\n }\n }, [externalEntityId, rows]);\n\n useEffect(() => {\n const allowed = new Set(resolvedFilterOptions.map((option) => option.id));\n setFilters((current) => {\n if (current.size === 0) return current;\n const next = new Set([...current].filter((id) => allowed.has(id)));\n return next.size === current.size ? current : next;\n });\n }, [resolvedFilterOptions]);\n\n const publishSceneSelection = (row: HierarchyRow) => {\n if (row.kind !== 'entity') return;\n const target = workspace?.preview?.target;\n if (!target?.targetId) return;\n void client.selectSceneEntity(row.id, {\n label: row.name,\n tabId: VIEW_WORKSPACE_TAB_ID,\n targetId: target.targetId,\n targetGeneration: target.generation,\n }).catch(() => {});\n };\n\n const clearSceneSelection = () => {\n setSelected(new Set());\n setAnchor(null);\n const target = workspace?.preview?.target;\n if (!target?.targetId) return;\n void client.clearSceneSelection({\n tabId: VIEW_WORKSPACE_TAB_ID,\n targetId: target.targetId,\n targetGeneration: target.generation,\n }).catch(() => {});\n };\n\n const visibleRows = useMemo(() => {\n const text = query.trim().toLowerCase();\n const filtering = text.length > 0 || filters.size > 0;\n if (filtering) {\n return rows.filter((row) => {\n const names = rowComponentNames(row);\n const typeText = typeLabelFor(row).toLowerCase();\n const componentText = names.join(' ').toLowerCase();\n const textMatch = !text\n || rowLabel(row).toLowerCase().includes(text)\n || typeText.includes(text)\n || componentText.includes(text);\n const typeMatch = entityMatchesSceneTreeFilters(names, filters);\n return !isSceneRootRow(row) && textMatch && typeMatch;\n }).map((row) => ({ ...row, depth: 0 }));\n }\n const collapsedDepths: number[] = [];\n return rows.filter((row) => {\n while (collapsedDepths.length && collapsedDepths.at(-1)! >= row.depth) collapsedDepths.pop();\n const hiddenByParent = collapsedDepths.length > 0;\n if (row.hasChildren && !expanded.has(row.id)) collapsedDepths.push(row.depth);\n return !hiddenByParent;\n });\n }, [expanded, filters, query, rowLabel, rows, typeLabelFor]);\n\n const selectRow = (row: HierarchyRow, event: MouseEvent) => {\n if (row.kind === 'folder') {\n setExpanded((current) => {\n const next = new Set(current);\n if (next.has(row.id)) next.delete(row.id); else next.add(row.id);\n return next;\n });\n return;\n }\n const ordered = visibleRows.filter((entry) => entry.kind === 'entity').map((entry) => entry.id);\n let next: Set<string>;\n if (event.shiftKey && anchor) {\n const from = ordered.indexOf(anchor);\n const to = ordered.indexOf(row.id);\n next = from < 0 || to < 0\n ? new Set([row.id])\n : new Set(ordered.slice(Math.min(from, to), Math.max(from, to) + 1));\n } else if (event.ctrlKey || event.metaKey) {\n next = new Set(selected);\n if (next.has(row.id)) next.delete(row.id); else next.add(row.id);\n } else {\n next = new Set([row.id]);\n }\n if (next.size === 0) {\n clearSceneSelection();\n return;\n }\n const primary = next.has(row.id)\n ? row\n : rows.find((entry) => entry.kind === 'entity' && next.has(entry.id));\n if (!primary) {\n clearSceneSelection();\n return;\n }\n setSelected(next);\n setAnchor(primary.id);\n publishSceneSelection(primary);\n };\n const showContext = (event: MouseEvent, items: MenuItem[]) => {\n event.preventDefault();\n event.stopPropagation();\n setHeaderMenu(null);\n setContextMenu({ x: event.clientX, y: event.clientY, items });\n };\n const blankMenu = useCallback((): MenuItem[] => [\n { kind: 'title', label: t('sceneTree.readOnlyTitle') },\n { kind: 'item', id: 'clear-filter', label: t('sceneTree.menu.clearSearchAndFilters'), icon: <X size={14} />, disabled: !query && filters.size === 0, action: () => { setQuery(''); setFilters(new Set()); } },\n { kind: 'item', id: 'focus', label: t('sceneTree.menu.focusSelection'), icon: <Crosshair size={14} />, shortcut: 'F', disabled: selected.size === 0, action: () => {} },\n ], [filters.size, query, selected.size, t]);\n const rowMenu = useCallback((row: HierarchyRow): MenuItem[] => [\n { kind: 'title', label: rowLabel(row), icon: <RowIcon row={row} /> },\n { kind: 'item', id: 'copy-json', label: t('sceneTree.menu.copyJson'), icon: <Braces size={14} />, action: () => void navigator.clipboard?.writeText(JSON.stringify(row, null, 2)) },\n { kind: 'item', id: 'focus', label: t('sceneTree.menu.focusInViewport'), icon: <Crosshair size={14} />, shortcut: 'F', disabled: !workspace?.preview || isSceneRootRow(row), action: () => { const target = workspace?.preview?.target; if (target) void client?.call('entity.focus', { entityId: row.id, targetId: target.targetId, targetGeneration: target.generation }); } },\n ], [rowLabel, t, client, workspace?.preview]);\n useEffect(() => {\n if (!headerMenu) setHeaderMenuAnchor(null);\n }, [headerMenu]);\n\n const openHeaderMenu = (kind: 'filter' | 'settings') => {\n if (headerMenu === kind) {\n setHeaderMenu(null);\n return;\n }\n const ref = kind === 'filter' ? filterButtonRef : settingsButtonRef;\n const rect = ref.current?.getBoundingClientRect();\n if (rect) setHeaderMenuAnchor(rect);\n setHeaderMenu(kind);\n };\n\n const toggleTypeFilter = (filterId: string) => {\n setFilters((current) => {\n const next = new Set(current);\n if (next.has(filterId)) next.delete(filterId);\n else next.add(filterId);\n return next;\n });\n };\n\n return (\n <div\n className=\"panel outliner-panel\"\n data-testid=\"panel-hierarchy\"\n data-view-readonly=\"true\"\n role=\"tree\"\n tabIndex={0}\n onKeyDown={(event) => {\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'a') {\n event.preventDefault();\n setSelected(new Set(rows.filter((row) => row.kind === 'entity').map((row) => row.id)));\n }\n }}\n >\n <PanelHeader\n className=\"fx-hier-toolbar\"\n data-testid=\"hier-toolbar\"\n start={(\n <Toolbar>\n <IconButton\n ref={filterButtonRef}\n className={filters.size ? 'active' : undefined}\n label={t('sceneTree.filterByType')}\n icon={<Filter size={14} />}\n size=\"compact\"\n onClick={() => openHeaderMenu('filter')}\n />\n </Toolbar>\n )}\n center={(\n <SearchField\n className=\"fx-hier-search\"\n data-testid=\"hier-search\"\n data-action={SCENE_TREE_ACTIONS.search}\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n onClear={() => setQuery('')}\n placeholder={t('sceneTree.searchPlaceholder')}\n label={t('sceneTree.searchLabel')}\n />\n )}\n end={(\n <Toolbar>\n <IconButton\n ref={settingsButtonRef}\n label={t('sceneTree.displaySettings')}\n icon={<Settings size={14} />}\n size=\"compact\"\n onClick={() => openHeaderMenu('settings')}\n />\n </Toolbar>\n )}\n />\n <div className=\"ol-colhead\" data-testid=\"hier-colhead\">\n <span className=\"ch-caret\" aria-hidden />\n <span className=\"ch-name sortable\">{t('sceneTree.columnName')}</span>\n {columns.type ? <span className=\"ch-type sortable col-type\">{t('sceneTree.columnType')}</span> : null}\n {columns.id ? <span className=\"ch-id sortable col-id\">{t('sceneTree.columnId')}</span> : null}\n </div>\n <div\n className=\"ol-body\"\n data-testid=\"hier-root-dropzone\"\n onClick={(event) => {\n if (event.target === event.currentTarget) clearSceneSelection();\n }}\n onContextMenu={(event) => {\n if (!(event.target as HTMLElement).closest('.tn')) showContext(event, blankMenu());\n }}\n >\n {visibleRows.length === 0 ? (\n <EmptyState\n className=\"hier-no-match\"\n title={t('sceneTree.noMatchTitle')}\n description={t('sceneTree.noMatchDescription')}\n />\n ) : visibleRows.map((row) => {\n const isSelected = selected.has(row.id);\n const isHidden = row.hidden === true;\n const isExpanded = expanded.has(row.id);\n return (\n <div\n key={row.id}\n className={`tn k-${rowType(row)}${isSelected ? ' sel' : ''}${isHidden ? ' dim' : ''}`}\n data-testid={isSceneRootRow(row) ? 'hier-row-scene-folder' : `hier-row-${row.id}`}\n data-action={SCENE_TREE_ACTIONS.select}\n style={{ paddingLeft: `calc(var(--fx-ref-space-8) + ${row.depth} * var(--hier-indent-step, calc(var(--fx-ref-space-12) + var(--fx-ref-space-2))))` }}\n role=\"treeitem\"\n aria-selected={isSelected}\n tabIndex={isSelected ? 0 : -1}\n onClick={(event) => selectRow(row, event)}\n onContextMenu={(event) => {\n if (!selected.has(row.id)) {\n setSelected(new Set([row.id]));\n if (row.kind === 'entity') publishSceneSelection(row);\n }\n showContext(event, isSceneRootRow(row) ? blankMenu() : rowMenu(row));\n }}\n >\n <button\n type=\"button\"\n className=\"caret\"\n data-action={SCENE_TREE_ACTIONS.toggleExpanded}\n disabled={!row.hasChildren}\n tabIndex={-1}\n onClick={(event) => {\n event.stopPropagation();\n if (!row.hasChildren) return;\n setExpanded((current) => {\n const next = new Set(current);\n if (next.has(row.id)) next.delete(row.id);\n else next.add(row.id);\n return next;\n });\n }}\n >\n {row.hasChildren ? (isExpanded ? <ChevronDown size={12} /> : <ChevronRight size={12} />) : null}\n </button>\n <span className=\"ico\"><RowIcon row={row} /></span>\n <span className=\"name-cell\">\n <span className=\"nm\">{highlighted(rowLabel(row), query)}</span>\n </span>\n {columns.type ? <span className=\"cell type col-type\"><span className=\"kind\">{typeLabelFor(row)}</span></span> : null}\n {columns.id ? <span className=\"cell id col-id\">{isSceneRootRow(row) ? '' : `#${row.id}`}</span> : null}\n </div>\n );\n })}\n </div>\n <FloatingMenu\n open={Boolean(headerMenuAnchor && headerMenu === 'filter')}\n anchorRect={headerMenuAnchor}\n onClose={() => setHeaderMenu(null)}\n ignorePointerWithin={[filterButtonRef]}\n className=\"hier-filter-menu\"\n containerProps={{ onPointerDown: (event) => event.stopPropagation() }}\n >\n <div className=\"hier-filter-menu-body\">\n <div className=\"hier-filter-section\">{t('sceneTree.filterByType')}</div>\n {resolvedFilterOptions.map((filter) => {\n const active = filters.has(filter.id);\n return (\n <button\n type=\"button\"\n className=\"hier-filter-option\"\n data-active={active ? 'true' : 'false'}\n key={filter.id}\n onClick={() => toggleTypeFilter(filter.id)}\n >\n <Checkbox\n checked={active}\n onChange={() => toggleTypeFilter(filter.id)}\n tabIndex={-1}\n hideLabel\n label={filter.label}\n className=\"hier-filter-check\"\n />\n <span className=\"hier-filter-option-icon\" aria-hidden>{filterOptionIcon(filter.id)}</span>\n {filter.label}\n </button>\n );\n })}\n <div className=\"hier-filter-separator\" />\n <button\n type=\"button\"\n className=\"hier-filter-option hier-filter-clear\"\n disabled={filters.size === 0}\n onClick={() => setFilters(new Set())}\n >\n {t('sceneTree.clearFilters')}\n </button>\n </div>\n </FloatingMenu>\n <FloatingMenu\n open={Boolean(headerMenuAnchor && headerMenu === 'settings')}\n anchorRect={headerMenuAnchor}\n onClose={() => setHeaderMenu(null)}\n ignorePointerWithin={[settingsButtonRef]}\n className=\"hier-filter-menu\"\n containerProps={{ onPointerDown: (event) => event.stopPropagation() }}\n >\n <div className=\"hier-filter-menu-body hierarchy-header-menu-settings\">\n <div className=\"hier-filter-section\">{t('sceneTree.columns')}</div>\n {(['type', 'id'] as const).map((column) => {\n const label = column === 'type'\n ? t('sceneTree.columnType')\n : t('sceneTree.columnId');\n const checked = columns[column];\n const toggle = () => setColumns((current) => ({ ...current, [column]: !current[column] }));\n return (\n <button\n type=\"button\"\n className=\"hier-filter-option\"\n data-action={SCENE_TREE_ACTIONS.toggleColumn}\n data-active={checked ? 'true' : 'false'}\n key={column}\n onClick={toggle}\n >\n <Checkbox\n checked={checked}\n onChange={toggle}\n tabIndex={-1}\n hideLabel\n label={label}\n className=\"hier-filter-check\"\n />\n {label}\n </button>\n );\n })}\n <div className=\"hier-filter-separator\" />\n <button\n type=\"button\"\n className=\"hier-filter-option hier-filter-action\"\n data-action={SCENE_TREE_ACTIONS.expandAll}\n onClick={() => setExpanded(new Set(rows.filter((row) => row.hasChildren).map((row) => row.id)))}\n >\n <Maximize2 size={14} className=\"hier-filter-option-icon\" />\n {t('sceneTree.expandAll')}\n </button>\n <button\n type=\"button\"\n className=\"hier-filter-option hier-filter-action\"\n data-action={SCENE_TREE_ACTIONS.collapseAll}\n onClick={() => setExpanded(new Set(rows.filter(isSceneRootRow).map((row) => row.id)))}\n >\n <Minimize2 size={14} className=\"hier-filter-option-icon\" />\n {t('sceneTree.collapseAll')}\n </button>\n </div>\n </FloatingMenu>\n {contextMenu ? <HierarchyContextMenu state={contextMenu} close={() => setContextMenu(null)} /> : null}\n </div>\n );\n}\n", "import { useCallback, useSyncExternalStore } from 'react';\n\nimport { getLocale, subscribeLocale, t as translate } from './index.ts';\n\nexport function useTranslation() {\n const locale = useSyncExternalStore(subscribeLocale, getLocale, getLocale);\n const t = useCallback(\n (key: string, vars?: Record<string, string | number>) => translate(key, vars),\n [locale],\n );\n return { t, locale };\n}\n", "/**\n * Scene-tree type filters mirror forgeax-editor hierarchy filter options:\n * option ids are component schema names from the Engine host, not UI enums.\n */\n\nconst CATEGORY_RULES = [\n { test: /Camera/, category: 'camera' },\n { test: /Light/, category: 'light' },\n { test: /Character|Controller/, category: 'character' },\n { test: /PlayerStart/, category: 'start' },\n { test: /Spawner/, category: 'spawner' },\n { test: /Mesh/, category: 'mesh' },\n];\n\nfunction categoryRank(category: string) {\n const index = CATEGORY_RULES.findIndex((rule) => rule.category === category);\n return index === -1 ? CATEGORY_RULES.length : index;\n}\n\n/** @param {string} id */\nexport function hierarchyTypeCategory(id: string) {\n if (id === 'group') return 'group';\n if (id === 'entity') return 'entity';\n for (const rule of CATEGORY_RULES) {\n if (rule.test.test(id)) return rule.category;\n }\n return 'generic';\n}\n\n/** @param {string} a @param {string} b */\nexport function compareComponentFilterIds(a: string, b: string) {\n const ra = categoryRank(hierarchyTypeCategory(a));\n const rb = categoryRank(hierarchyTypeCategory(b));\n return ra - rb || a.localeCompare(b);\n}\n\n/**\n * @param {readonly string[]} componentNames\n * @param {ReadonlySet<string>} activeFilters\n */\nexport function entityMatchesSceneTreeFilters(componentNames: readonly string[], activeFilters: ReadonlySet<string>) {\n if (activeFilters.size === 0) return true;\n return componentNames.some((name) => activeFilters.has(name));\n}\n\n/**\n * Build filter options from a component schema name list and optional counts.\n * View derives these options from the loaded entity component identities.\n *\n * @param {readonly string[]} schemaNames\n * @param {ReadonlyMap<string, number>} [counts]\n */\nexport function buildSceneTreeFilterOptions(schemaNames: readonly string[], counts: ReadonlyMap<string, number> = new Map()) {\n const seen = new Set();\n const options = [];\n for (const name of schemaNames) {\n const id = String(name);\n if (!id || seen.has(id)) continue;\n seen.add(id);\n const count = counts.get(id);\n options.push({\n id,\n ...(count === undefined ? {} : { count }),\n });\n }\n options.sort((left, right) => compareComponentFilterIds(left.id, right.id));\n return options;\n}\n", "export type SceneEntityTypeKey = 'mesh' | 'directionalLight' | 'sky' | 'folder' | 'entity' | 'playerStart' | 'camera';\nexport type HierarchyRow = { id: string; name: string; typeKey?: SceneEntityTypeKey; componentNames?: string[]; depth: number; kind: 'folder' | 'entity'; virtual?: boolean; hidden?: boolean; hasChildren?: boolean; expanded?: boolean };\ntype EntityNode = { entityId?: string; entity?: number; name?: string; parentId?: string; componentNames?: string[] };\nimport { buildSceneTreeFilterOptions } from './hierarchy-filters.ts';\n\n/**\n * Normalize Engine `scene-tree.get` payloads into panel rows.\n * View does not author hierarchy; it only projects the latest Engine response.\n */\n\n/**\n * @param {unknown} result\n * @returns {Array<Record<string, unknown>>}\n */\nfunction projectEntityRows(result: unknown): HierarchyRow[] {\n if (!result || typeof result !== 'object') return [];\n const nodes = 'nodes' in result ? result.nodes : undefined;\n if (!Array.isArray(nodes)) return [];\n const rows: HierarchyRow[] = [];\n const seen = new Set();\n const flat = nodes.filter((node): node is EntityNode => node != null && typeof node === 'object');\n const byId = new Map(flat.map(node => [String(node.entityId), node]));\n const children = new Map<string, EntityNode[]>();\n for (const node of flat) {\n if (node.parentId && byId.has(node.parentId)) {\n const siblings = children.get(node.parentId) ?? [];\n siblings.push(node);\n children.set(node.parentId, siblings);\n }\n }\n const visit = (root: EntityNode) => {\n const stack = [{ node: root, depth: 0 }];\n while (stack.length) {\n const { node, depth } = stack.pop()!;\n const id = String(node.entityId ?? '');\n if (!id || seen.has(id)) continue;\n seen.add(id);\n const descendants = children.get(id) ?? [];\n const componentNames = Array.isArray(node.componentNames) ? node.componentNames.filter(name => typeof name === 'string') : [];\n const typeKey = componentNames.includes('Camera') ? 'camera'\n : componentNames.includes('DirectionalLight') ? 'directionalLight'\n : componentNames.includes('MeshFilter') ? 'mesh' : 'entity';\n rows.push({ id, componentNames, name: String(node.name ?? (node.entity === undefined ? id : `Entity ${node.entity}`)), typeKey,\n depth,\n kind: 'entity',\n ...(descendants.length ? { hasChildren: true, expanded: depth < 1 } : {}) });\n for (let i = descendants.length - 1; i >= 0; i--) stack.push({ node: descendants[i], depth: depth + 1 });\n }\n };\n for (const node of flat) if (!node.parentId || !byId.has(node.parentId)) visit(node);\n // Preserve discoverability for cyclic or partial parent projections.\n for (const node of flat) visit(node);\n return rows;\n}\n\n/** Counts describe the loaded rows; Engine owns only component identities. */\nexport function sceneTreeComponentFilters(rows: readonly HierarchyRow[]) {\n const counts = new Map();\n for (const row of rows) for (const name of row.componentNames ?? []) counts.set(name, (counts.get(name) ?? 0) + 1);\n return buildSceneTreeFilterOptions([...counts.keys()], counts);\n}\n\n/** This grouping row belongs only to View and is never sent as an entity reference. */\nexport const HIERARCHY_SCENE_FOLDER_ID = 'hierarchy:scene-root';\nexport function isSceneRootRow(row: HierarchyRow) { return row?.id === HIERARCHY_SCENE_FOLDER_ID; }\nexport function wrapWithVirtualSceneRoot(rows: HierarchyRow[]): HierarchyRow[] {\n if (rows.some(isSceneRootRow)) return rows.map(row => isSceneRootRow(row) ? { ...row, virtual: true } : row);\n return [{ id: HIERARCHY_SCENE_FOLDER_ID, name: 'Scene', typeKey: 'folder', depth: 0,\n kind: 'folder', virtual: true, hasChildren: rows.length > 0, expanded: true },\n ...rows.map(row => ({ ...row, depth: row.depth + 1 }))];\n}\nexport function normalizeSceneTreeRows(result: unknown) { return wrapWithVirtualSceneRoot(projectEntityRows(result)); }\nexport function normalizeSceneTreeResponse(result: unknown) {\n const rows = normalizeSceneTreeRows(result);\n return { rows, filterOptions: sceneTreeComponentFilters(rows) };\n}\n", "\n const css = \"/* packages/view-plugin-scene-tree/src/ui/scene-tree.css */\\n.outliner-panel {\\n --hier-w-caret: calc(var(--fx-ref-space-12) + var(--fx-ref-space-2));\\n --hier-w-type: calc(var(--fx-ref-space-48) + var(--fx-ref-space-16) + var(--fx-ref-space-4));\\n --hier-w-id: calc(var(--fx-ref-space-48) + var(--fx-ref-space-24));\\n --hier-indent-step: calc(var(--fx-ref-space-12) + var(--fx-ref-space-2));\\n display: flex;\\n flex-direction: column;\\n container-type: inline-size;\\n width: 100%;\\n height: 100%;\\n min-height: 0;\\n overflow: hidden;\\n position: relative;\\n background: var(--fx-color-surface-sidebar);\\n color: var(--fx-color-text-primary);\\n font: var(--fx-type-compact-font-weight) var(--fx-type-compact-font-size) / var(--fx-type-compact-line-height) var(--fx-type-compact-font-family);\\n}\\n.outliner-panel * {\\n box-sizing: border-box;\\n}\\n.outliner-panel button,\\n.outliner-panel input {\\n font: inherit;\\n}\\n.fx-hier-toolbar {\\n flex: 0 0 auto;\\n gap: var(--fx-ref-space-6);\\n padding: var(--fx-ref-space-6) var(--fx-ref-space-8);\\n background: var(--fx-color-surface-sidebar);\\n}\\n.fx-hier-toolbar > .fx-panel-header__slot:nth-child(2) {\\n flex: 1;\\n}\\n.fx-hier-search {\\n flex: 1;\\n width: 100%;\\n min-width: 0;\\n}\\n.fx-hier-search .fx-input {\\n height: var(--fx-component-control-height-compact);\\n}\\n.outliner-panel .fx-button--icon.active {\\n border-color: var(--fx-color-brand-accent);\\n background: var(--fx-color-brand-soft);\\n color: var(--fx-color-brand-text);\\n}\\n.hier-filter-menu-body {\\n min-width: 220px;\\n padding: var(--fx-ref-space-4);\\n border: var(--fx-border-width) solid var(--fx-color-border-default);\\n border-radius: var(--fx-radius-popover);\\n background: var(--fx-color-surface-raised);\\n box-shadow: var(--fx-shadow-floating);\\n}\\n.hier-filter-section {\\n padding: var(--fx-ref-space-6) var(--fx-ref-space-8) var(--fx-ref-space-4);\\n color: var(--fx-color-text-muted);\\n font-size: var(--fx-type-caption-font-size);\\n font-weight: var(--fx-ref-font-weight-600);\\n letter-spacing: var(--fx-type-caption-letter-spacing);\\n text-transform: uppercase;\\n}\\n.hier-filter-separator {\\n height: var(--fx-border-width);\\n margin: var(--fx-ref-space-4) 0;\\n background: var(--fx-color-border-subtle);\\n}\\n.hier-filter-option {\\n display: flex;\\n align-items: center;\\n gap: var(--fx-ref-space-8);\\n width: 100%;\\n min-height: var(--fx-component-editor-row-height);\\n padding: var(--fx-ref-space-4) var(--fx-ref-space-8);\\n border: 0;\\n border-radius: var(--fx-radius-control);\\n background: transparent;\\n color: var(--fx-color-text-secondary);\\n font: inherit;\\n text-align: left;\\n cursor: pointer;\\n}\\n.hier-filter-option:hover:not(:disabled) {\\n background: var(--fx-color-surface-hover);\\n color: var(--fx-color-text-primary);\\n}\\n.hier-filter-option:disabled {\\n color: var(--fx-color-text-disabled);\\n cursor: default;\\n}\\n.hier-filter-option-icon {\\n display: grid;\\n flex: 0 0 14px;\\n place-items: center;\\n width: 14px;\\n color: var(--fx-color-text-muted);\\n}\\n.hier-filter-check {\\n flex: 0 0 var(--fx-component-choice-size);\\n pointer-events: none;\\n}\\n.hier-filter-check.fx-choice {\\n align-items: center;\\n gap: 0;\\n min-height: 0;\\n margin: 0;\\n}\\n.hier-filter-check .fx-choice__text {\\n display: none;\\n}\\n.hier-filter-clear {\\n justify-content: flex-start;\\n color: var(--fx-color-text-muted);\\n}\\n.ol-colhead {\\n display: flex;\\n align-items: center;\\n min-height: var(--fx-component-editor-row-height);\\n padding: var(--fx-ref-space-4) var(--fx-ref-space-8);\\n border-bottom: var(--fx-border-width) solid var(--fx-color-border-subtle);\\n color: var(--fx-color-text-muted);\\n font: var(--fx-type-caption-font-weight) var(--fx-type-caption-font-size) / var(--fx-type-caption-line-height) var(--fx-type-code-font-family);\\n letter-spacing: var(--fx-type-caption-letter-spacing);\\n text-transform: uppercase;\\n}\\n.ch-caret {\\n width: var(--hier-w-caret);\\n flex: 0 0 auto;\\n}\\n.ch-name {\\n flex: 1;\\n min-width: var(--fx-ref-space-16);\\n}\\n.ch-type {\\n width: var(--hier-w-type);\\n flex: 0 0 auto;\\n}\\n.ch-id {\\n width: var(--hier-w-id);\\n flex: 0 0 auto;\\n}\\n.ol-body {\\n flex: 1;\\n min-height: 0;\\n overflow: auto;\\n padding: var(--fx-ref-space-4) 0 var(--fx-ref-space-8);\\n}\\n.tn {\\n display: flex;\\n align-items: center;\\n min-height: var(--fx-component-editor-row-height);\\n padding-right: var(--fx-ref-space-8);\\n border: 0;\\n border-left: var(--fx-border-focus-width) solid transparent;\\n color: var(--fx-color-text-secondary);\\n white-space: nowrap;\\n cursor: default;\\n user-select: none;\\n}\\n.tn:hover {\\n background: var(--fx-color-surface-hover);\\n color: var(--fx-color-text-primary);\\n}\\n.tn.sel {\\n border-left-color: var(--fx-color-selection-indicator);\\n background: var(--fx-color-selection-bg);\\n color: var(--fx-color-selection-fg);\\n}\\n.tn.dim {\\n opacity: 0.45;\\n}\\n.tn .caret {\\n display: grid;\\n place-items: center;\\n width: var(--hier-w-caret);\\n height: var(--fx-ref-space-16);\\n flex: 0 0 auto;\\n padding: 0;\\n border: 0;\\n background: transparent;\\n color: var(--fx-color-text-muted);\\n}\\n.tn .caret:disabled {\\n opacity: 0;\\n pointer-events: none;\\n}\\n.tn .ico {\\n display: grid;\\n place-items: center;\\n width: calc(var(--fx-ref-space-16) + var(--fx-ref-space-2));\\n flex: 0 0 auto;\\n color: var(--fx-color-text-muted);\\n}\\n.tn .name-cell {\\n display: flex;\\n align-items: center;\\n flex: 1;\\n min-width: 0;\\n gap: var(--fx-ref-space-4);\\n overflow: hidden;\\n}\\n.tn .nm {\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n.tn.k-folder .nm,\\n.tn.k-grp .nm {\\n color: var(--fx-color-text-muted);\\n}\\n.tn .cell {\\n overflow: hidden;\\n color: var(--fx-color-text-muted);\\n font: var(--fx-type-caption-font-weight) var(--fx-type-caption-font-size) / var(--fx-type-caption-line-height) var(--fx-type-code-font-family);\\n text-overflow: ellipsis;\\n}\\n.tn .cell.type {\\n width: var(--hier-w-type);\\n}\\n.tn .cell.id {\\n width: var(--hier-w-id);\\n}\\n.tn .kind {\\n color: var(--fx-color-text-secondary);\\n}\\n.tn.k-light .ico {\\n color: var(--fx-color-status-warning-fg);\\n}\\n.tn.k-camera .ico {\\n color: var(--fx-color-status-info-fg);\\n}\\n.tn.k-character .ico {\\n color: var(--fx-color-brand-text);\\n}\\n.tn.k-scene .ico,\\n.tn.k-group .ico,\\n.tn.k-folder .ico {\\n color: var(--fx-color-text-muted);\\n}\\n.tn.pdim {\\n opacity: 0.68;\\n}\\n.tn.drop-inside {\\n background: var(--fx-color-brand-soft);\\n outline: var(--fx-border-width) solid var(--fx-color-brand-accent);\\n outline-offset: calc(-1 * var(--fx-border-width));\\n}\\n.tn.drop-before::before,\\n.tn.drop-after::after {\\n content: \\\"\\\";\\n position: absolute;\\n z-index: var(--fx-layer-sticky);\\n right: var(--fx-ref-space-4);\\n left: var(--fx-ref-space-4);\\n height: var(--fx-ref-space-2);\\n background: var(--fx-color-brand-accent);\\n box-shadow: var(--fx-shadow-subtle);\\n}\\n.tn {\\n position: relative;\\n}\\n.tn.drop-before::before {\\n top: calc(-1 * var(--fx-border-width));\\n}\\n.tn.drop-after::after {\\n bottom: calc(-1 * var(--fx-border-width));\\n}\\n.hier-inline-rename {\\n width: 100%;\\n min-width: 0;\\n height: var(--fx-component-control-height-compact);\\n padding: var(--fx-ref-space-2) var(--fx-ref-space-4);\\n border: var(--fx-border-width) solid var(--fx-color-border-focus);\\n border-radius: var(--fx-ref-radius-4);\\n outline: 0;\\n background: var(--fx-color-surface-inset);\\n color: var(--fx-color-text-primary);\\n}\\n.hier-no-match {\\n padding: var(--fx-ref-space-8) var(--fx-ref-space-12);\\n}\\n.outliner-panel .hl {\\n border-radius: var(--fx-ref-radius-4);\\n background: var(--fx-color-brand-soft);\\n color: var(--fx-color-text-primary);\\n}\\n.outliner-panel .muted {\\n color: var(--fx-color-text-muted);\\n}\\n@container (max-width: 195px) {\\n .outliner-panel .col-type {\\n display: none;\\n }\\n}\\n@container (max-width: 280px) {\\n .outliner-panel .col-id {\\n display: none;\\n }\\n}\\n.hier-context-position {\\n position: fixed;\\n z-index: var(--fx-layer-tooltip);\\n color: var(--fx-color-text-secondary);\\n font: var(--fx-type-ui-font-weight) var(--fx-type-ui-font-size) / var(--fx-type-ui-line-height) var(--fx-type-ui-font-family);\\n}\\n.hier-context-menu,\\n.hier-context-submenu {\\n box-sizing: border-box;\\n display: flex;\\n flex-direction: column;\\n min-width: var(--fx-component-menu-min-width);\\n max-height: calc(100vh - var(--fx-ref-space-16));\\n padding: var(--fx-ref-space-6);\\n overflow: visible;\\n border: var(--fx-border-width) solid var(--fx-color-border-default);\\n border-radius: var(--fx-radius-popover);\\n background: var(--fx-color-surface-raised);\\n box-shadow: var(--fx-shadow-floating);\\n}\\n.hier-context-submenu {\\n position: absolute;\\n top: calc(-1 * var(--fx-ref-space-6));\\n left: calc(100% - var(--fx-ref-space-2));\\n min-width: var(--fx-component-panel-config-min-width);\\n}\\n.hier-context-title {\\n display: flex;\\n align-items: center;\\n gap: var(--fx-ref-space-6);\\n padding: var(--fx-ref-space-6) var(--fx-ref-space-8);\\n color: var(--fx-color-text-muted);\\n font: var(--fx-type-caption-font-weight) var(--fx-type-caption-font-size) / var(--fx-type-caption-line-height) var(--fx-type-code-font-family);\\n}\\n.hier-context-item-wrap {\\n position: relative;\\n}\\n.hier-context-item-wrap > button {\\n box-sizing: border-box;\\n display: flex;\\n align-items: center;\\n gap: var(--fx-ref-space-8);\\n width: 100%;\\n min-height: var(--fx-component-menu-row-height);\\n padding: var(--fx-ref-space-6) var(--fx-ref-space-8);\\n border: 0;\\n border-radius: var(--fx-radius-control);\\n background: transparent;\\n color: inherit;\\n font: inherit;\\n text-align: left;\\n cursor: pointer;\\n}\\n.hier-context-item-wrap > button:hover:not(:disabled) {\\n background: var(--fx-color-surface-hover);\\n color: var(--fx-color-text-primary);\\n}\\n.hier-context-item-wrap > button:disabled {\\n opacity: 0.38;\\n cursor: default;\\n}\\n.hier-context-item-wrap > button[data-danger=true] {\\n color: var(--fx-color-status-error-fg);\\n}\\n.hier-context-item-wrap > button[data-forge=true] .hier-context-icon {\\n color: var(--fx-color-brand-text);\\n}\\n.hier-context-icon {\\n display: grid;\\n place-items: center;\\n width: var(--fx-component-control-icon-size);\\n flex: 0 0 var(--fx-component-control-icon-size);\\n color: var(--fx-color-text-muted);\\n}\\n.hier-context-item-wrap > button > span:nth-child(2) {\\n flex: 1;\\n}\\n.hier-context-item-wrap kbd {\\n color: var(--fx-color-text-muted);\\n font: var(--fx-type-caption-font-weight) var(--fx-type-caption-font-size) / var(--fx-type-caption-line-height) var(--fx-type-code-font-family);\\n}\\n.hier-context-separator {\\n display: block;\\n height: var(--fx-border-width);\\n margin: var(--fx-ref-space-6);\\n background: var(--fx-color-border-subtle);\\n}\\n\";\n if (typeof document !== 'undefined' && !document.querySelector('style[data-forgeax-css=\"a9fd1866464288a4a4b490686e0c4225551e378d64dcb6499d18061c7e908e0d\"]')) {\n const style = document.createElement('style');\n style.dataset.forgeaxCss = \"a9fd1866464288a4a4b490686e0c4225551e378d64dcb6499d18061c7e908e0d\";\n style.textContent = css;\n document.head.append(style);\n }\n export default css;\n "],
4
+ "sourcesContent": ["import type { ComponentProps } from 'react';\nimport '@forgeax/view-components/styles.css';\nimport { OverlayRootProvider } from '@forgeax/view-components';\nimport '../i18n/index.ts';\nimport { createRoot } from 'react-dom/client';\nimport { SceneTreePanel } from './SceneTreePanel';\nimport './scene-tree.css';\n\nexport async function mountSceneTreePanel(props: ComponentProps<typeof SceneTreePanel> & { mountElement: HTMLElement; overlayRoot?: HTMLElement }) {\n if (!props.mountElement) throw new TypeError('mountSceneTreePanel requires mountElement');\n const root = createRoot(props.mountElement);\n root.render(\n <OverlayRootProvider root={props.overlayRoot ?? props.mountElement}>\n <SceneTreePanel client={props.client} />\n </OverlayRootProvider>,\n );\n return async () => root.unmount();\n}\n", "import type { WorkspaceState } from '@forgeax/view-workspace-core/contract';\nimport {\n Box,\n Braces,\n Camera,\n ChevronDown,\n ChevronRight,\n CircleUserRound,\n Crosshair,\n Filter,\n Folder,\n Layers,\n Lightbulb,\n Maximize2,\n Minimize2,\n Settings,\n X,\n} from 'lucide-react';\nimport {\n Checkbox,\n EmptyState,\n useOverlayRoot,\n FloatingMenu,\n IconButton,\n PanelHeader,\n SearchField,\n Toolbar,\n useWorkspaceClientConnected,\n type AnchorRect,\n} from '@forgeax/view-components';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n type MouseEvent,\n type ReactNode,\n} from 'react';\nimport { createPortal } from 'react-dom';\n\nimport { useTranslation } from '../i18n/useTranslation';\nimport { SCENE_TREE_ACTIONS } from '../schema.ts';\nimport type { ViewWorkspaceClient } from '@forgeax/view-workspace-core/client';\nimport { VIEW_WORKSPACE_TAB_ID, jsonUnchanged } from '@forgeax/view-workspace-core/contract';\nimport { createWorkspaceObservation, createWorkspaceStateReader } from '@forgeax/view-workspace-core/workspace-state';\nimport {\n entityMatchesSceneTreeFilters,\n hierarchyTypeCategory,\n} from '../hierarchy-filters.ts';\nimport {\n HIERARCHY_SCENE_FOLDER_ID,\n isSceneRootRow,\n sceneTreeComponentFilters,\n normalizeSceneTreeRows,\n type HierarchyRow,\n} from '../hierarchy.ts';\n\ntype SceneTreeFilterOption = {\n id: string;\n label?: string;\n count?: number;\n};\n\ntype SceneSelectionClient = Pick<\n ViewWorkspaceClient,\n 'subscribe' | 'getState' | 'selectSceneEntity' | 'clearSceneSelection' | 'getSceneTree' | 'call' | 'onDisconnect' | 'transport'\n>;\n\ntype WorkspacePreviewSnapshot = WorkspaceState;\n\ntype MenuItem =\n | { kind: 'title'; label: string; icon?: ReactNode }\n | { kind: 'separator' }\n | {\n kind: 'item';\n id: string;\n label: string;\n icon?: ReactNode;\n shortcut?: string;\n disabled?: boolean;\n danger?: boolean;\n forge?: boolean;\n children?: MenuItem[];\n action?: () => void;\n };\ntype MenuState = { x: number; y: number; items: MenuItem[] } | null;\n\nfunction rowComponentNames(row: HierarchyRow) {\n if (Array.isArray(row.componentNames) && row.componentNames.length > 0) {\n return row.componentNames;\n }\n return row.typeKey ? [String(row.typeKey)] : [];\n}\n\nfunction rowType(row: HierarchyRow) {\n if (isSceneRootRow(row)) return 'scene';\n if (row.kind === 'folder') return 'group';\n const primary = rowComponentNames(row).find((name) => name !== 'Transform') ?? row.typeKey;\n if (!primary) return 'mesh';\n return hierarchyTypeCategory(String(primary));\n}\n\nfunction filterOptionIcon(id: string) {\n switch (hierarchyTypeCategory(id)) {\n case 'camera': return <Camera size={14} />;\n case 'light': return <Lightbulb size={14} />;\n case 'character': return <CircleUserRound size={14} />;\n case 'group': return <Layers size={14} />;\n default: return <Box size={14} />;\n }\n}\n\nfunction RowIcon({ row }: { row: HierarchyRow }) {\n if (isSceneRootRow(row)) return <Folder size={15} />;\n if (row.kind === 'folder') return <Layers size={15} />;\n if (row.typeKey === 'directionalLight') return <Lightbulb size={15} />;\n if (row.typeKey === 'camera') return <Camera size={15} />;\n if (row.name === 'Player') return <CircleUserRound size={15} />;\n return <Box size={15} />;\n}\n\nfunction HierarchyContextMenu({ state, close }: { state: Exclude<MenuState, null>; close: () => void }) {\n const overlayRoot = useOverlayRoot();\n const [submenu, setSubmenu] = useState<string | null>(null);\n useEffect(() => {\n const dismiss = () => close();\n const escape = (event: KeyboardEvent) => event.key === 'Escape' && close();\n window.addEventListener('pointerdown', dismiss);\n window.addEventListener('keydown', escape);\n return () => {\n window.removeEventListener('pointerdown', dismiss);\n window.removeEventListener('keydown', escape);\n };\n }, [close]);\n const renderItems = (items: MenuItem[], nested = false) => (\n <div className={nested ? 'hier-context-submenu' : 'hier-context-menu'}>\n {items.map((item, index) => {\n if (item.kind === 'separator') return <i className=\"hier-context-separator\" key={`sep-${index}`} />;\n if (item.kind === 'title') return <div className=\"hier-context-title\" key={`title-${index}`}>{item.icon}{item.label}</div>;\n return (\n <div className=\"hier-context-item-wrap\" key={item.id} onPointerEnter={() => item.children && setSubmenu(item.id)}>\n <button\n type=\"button\"\n role=\"menuitem\"\n data-operation={item.id}\n data-danger={item.danger || undefined}\n data-forge={item.forge || undefined}\n disabled={item.disabled}\n onClick={() => {\n if (item.children) {\n setSubmenu(submenu === item.id ? null : item.id);\n return;\n }\n item.action?.();\n close();\n }}\n >\n <span className=\"hier-context-icon\">{item.icon}</span>\n <span>{item.label}</span>\n {item.shortcut ? <kbd>{item.shortcut}</kbd> : null}\n {item.children ? <ChevronRight size={12} /> : null}\n </button>\n {item.children && submenu === item.id ? renderItems(item.children, true) : null}\n </div>\n );\n })}\n </div>\n );\n return createPortal(\n <div\n className=\"hier-context-position\"\n data-action={SCENE_TREE_ACTIONS.showContextMenu}\n role=\"menu\"\n style={{\n left: Math.max(8, Math.min(state.x, window.innerWidth - 260)),\n top: Math.max(8, Math.min(state.y, window.innerHeight - 420)),\n }}\n onPointerDown={(event) => event.stopPropagation()}\n onContextMenu={(event) => event.preventDefault()}\n >\n {renderItems(state.items)}\n </div>,\n overlayRoot ?? document.body,\n );\n}\n\nfunction highlighted(value: string, query: string) {\n const index = value.toLowerCase().indexOf(query.toLowerCase());\n if (!query || index < 0) return value;\n return <>{value.slice(0, index)}<mark className=\"hl\">{value.slice(index, index + query.length)}</mark>{value.slice(index + query.length)}</>;\n}\n\nexport function SceneTreePanel(props: { client?: SceneSelectionClient }) {\n if (!props.client) {\n return (\n <EmptyState\n title=\"Scene hierarchy unavailable\"\n description=\"Connect to the View workspace API to load the Engine scene tree.\"\n />\n );\n }\n return <SceneTreeLivePanel client={props.client} />;\n}\n\nfunction useEngineSceneRows(\n client: SceneSelectionClient,\n workspace: WorkspacePreviewSnapshot | null,\n connected: boolean,\n reader: ReturnType<typeof createWorkspaceStateReader>,\n) {\n const [projection, setProjection] = useState<{ key: string; rows: HierarchyRow[]; failed: boolean; hasMore: boolean } | null>(null);\n const [pageCount, setPageCount] = useState(1);\n const target = workspace?.preview?.target;\n const projectId = workspace?.project?.id;\n const key = `${target?.targetId}:${target?.generation}`;\n const current = projection?.key === key ? projection : null;\n const rows = current?.rows ?? [];\n\n useEffect(() => { setPageCount(1); }, [target?.targetId, target?.generation]);\n\n useEffect(() => {\n if (!connected || !target?.targetId || !projectId) {\n if (!connected) return;\n setProjection(null);\n return;\n }\n const observation = createWorkspaceObservation(reader, (current: WorkspacePreviewSnapshot | null) =>\n current?.project?.id === projectId &&\n current?.preview?.target?.targetId === target.targetId &&\n current?.preview?.target?.generation === target.generation);\n const { signal } = observation;\n let timer: ReturnType<typeof setTimeout>;\n const refresh = async () => {\n if (signal.aborted) return;\n let retryDelay = 500;\n try {\n const binding = {\n tabId: VIEW_WORKSPACE_TAB_ID, projectId, targetId: target.targetId,\n targetGeneration: target.generation, signal,\n };\n const result = await client.getSceneTree({ ...binding, limit: 1000 });\n if (signal.aborted) return;\n const nodes = [...(result.nodes ?? [])];\n let nextOffset = result.nextOffset;\n for (let page = 1; page < pageCount && nextOffset !== null && nextOffset !== undefined; page++) {\n const next = await client.getSceneTree({ ...binding, offset: nextOffset, revision: String(result.revision), limit: 1000 });\n if (signal.aborted) return;\n nodes.push(...next.nodes);\n nextOffset = next.nextOffset;\n }\n if (signal.aborted) return;\n setProjection((current) => {\n const next = { key, rows: normalizeSceneTreeRows({ ...result, nodes }), hasMore: nextOffset !== null && nextOffset !== undefined, failed: false };\n if (\n current?.key === next.key &&\n current.failed === next.failed &&\n current.hasMore === next.hasMore &&\n jsonUnchanged(current.rows, next.rows)\n ) return current;\n return next;\n });\n } catch {\n if (signal.aborted) return;\n setProjection((current) => {\n if (current?.key === key && current.failed && !current.hasMore && current.rows.length === 0) return current;\n return { key, rows: [], hasMore: false, failed: true };\n });\n retryDelay = 1500;\n }\n if (!signal.aborted) {\n timer = setTimeout(refresh, retryDelay);\n }\n };\n void refresh();\n return () => { observation.dispose(); clearTimeout(timer); };\n // Include the published snapshot: React may batch A -> B -> A into one\n // render after the observation for A has already been revoked.\n }, [client, connected, projectId, target?.targetId, target?.generation, pageCount, key, reader, workspace]);\n\n return { rows, filterOptions: sceneTreeComponentFilters(rows), failed: current?.failed ?? false, hasMore: current?.hasMore ?? false, loadMore: () => setPageCount(value => value + 1) };\n}\n\nfunction SceneTreeLivePanel({ client }: { client: SceneSelectionClient }) {\n const { t } = useTranslation();\n const reader = useMemo(() => createWorkspaceStateReader(client), [client]);\n const workspace = useSyncExternalStore(\n reader.subscribe,\n () => reader.getSnapshot() as WorkspacePreviewSnapshot | null,\n () => reader.getSnapshot() as WorkspacePreviewSnapshot | null,\n );\n const connected = useWorkspaceClientConnected(client);\n const { rows, filterOptions, failed, hasMore, loadMore } = useEngineSceneRows(client, workspace, connected, reader);\n\n if (!workspace?.preview?.target?.targetId) {\n return (\n <EmptyState\n title={t('sceneTree.unavailable')}\n description=\"Open a scene preview from the Content Browser to load the Engine hierarchy.\"\n />\n );\n }\n if (failed) {\n return (\n <EmptyState\n title={t('sceneTree.unavailable')}\n description={t('sceneTree.loadErrorDescription')}\n />\n );\n }\n if (rows.length === 0) return <EmptyState title=\"Loading hierarchy\" description=\"Reading the selected Engine target.\" />;\n return <>\n {hasMore && <button type=\"button\" onClick={loadMore}>Showing {Math.max(0, rows.length - 1)} entities. Load more</button>}\n <SceneTreeRowsPanel key={`${workspace.preview?.target?.targetId}:${workspace.preview?.target?.generation}`}\n client={client} rows={rows} filterOptions={filterOptions} />\n </>;\n}\n\nfunction SceneTreeRowsPanel({\n client,\n rows,\n filterOptions,\n}: {\n client: SceneSelectionClient;\n rows: HierarchyRow[];\n filterOptions: SceneTreeFilterOption[];\n}) {\n const { t } = useTranslation();\n const reader = useMemo(() => createWorkspaceStateReader(client), [client]);\n const workspace = useSyncExternalStore(\n reader.subscribe,\n () => reader.getSnapshot() as (WorkspacePreviewSnapshot & { sceneSelection?: { primary?: { entityId: string } | null } | null }) | null,\n () => reader.getSnapshot() as (WorkspacePreviewSnapshot & { sceneSelection?: { primary?: { entityId: string } | null } | null }) | null,\n );\n const externalEntityId = workspace?.sceneSelection?.primary?.entityId ?? null;\n const sceneIdentity = workspace?.preview?.asset?.guid ?? workspace?.preview?.target?.targetId ?? null;\n const rowLabel = useCallback(\n (row: HierarchyRow) => (isSceneRootRow(row) ? t('sceneTree.sceneRoot') : row.name),\n [t],\n );\n const typeLabelFor = useCallback(\n (row: HierarchyRow) => {\n if (row.kind === 'folder') return t('sceneTree.types.folder');\n if (row.typeKey) {\n const key = `sceneTree.types.${row.typeKey}`;\n const label = t(key);\n return label === key ? t('sceneTree.types.entity') : label;\n }\n return '';\n },\n [t],\n );\n const componentTypeLabel = useCallback((id: string) => {\n const key = `sceneTree.types.${id}`;\n const label = t(key);\n return label === key ? id : label;\n }, [t]);\n const resolvedFilterOptions = useMemo(\n () => filterOptions.map((option) => ({\n ...option,\n label: option.label ?? componentTypeLabel(option.id),\n })),\n [componentTypeLabel, filterOptions],\n );\n const [query, setQuery] = useState('');\n const [filters, setFilters] = useState(new Set<string>());\n const [expanded, setExpanded] = useState(() => new Set(\n rows.filter((row) => row.expanded || isSceneRootRow(row)).map((row) => row.id),\n ));\n const [columns, setColumns] = useState({ type: true, id: false });\n const [headerMenu, setHeaderMenu] = useState<'filter' | 'settings' | null>(null);\n const [headerMenuAnchor, setHeaderMenuAnchor] = useState<AnchorRect | null>(null);\n const filterButtonRef = useRef<HTMLButtonElement>(null);\n const settingsButtonRef = useRef<HTMLButtonElement>(null);\n const [contextMenu, setContextMenu] = useState<MenuState>(null);\n const [selected, setSelected] = useState(new Set<string>());\n const [anchor, setAnchor] = useState<string | null>(null);\n\n useEffect(() => {\n setExpanded((current) => {\n if (current.has(HIERARCHY_SCENE_FOLDER_ID)) return current;\n const next = new Set(current);\n next.add(HIERARCHY_SCENE_FOLDER_ID);\n return next;\n });\n }, [sceneIdentity]);\n\n useEffect(() => {\n if (externalEntityId && rows.some((row) => row.id === externalEntityId)) {\n setSelected(new Set([externalEntityId]));\n setAnchor(externalEntityId);\n } else if (!externalEntityId) {\n setSelected(new Set());\n setAnchor(null);\n }\n }, [externalEntityId, rows]);\n\n useEffect(() => {\n const allowed = new Set(resolvedFilterOptions.map((option) => option.id));\n setFilters((current) => {\n if (current.size === 0) return current;\n const next = new Set([...current].filter((id) => allowed.has(id)));\n return next.size === current.size ? current : next;\n });\n }, [resolvedFilterOptions]);\n\n const publishSceneSelection = (row: HierarchyRow) => {\n if (row.kind !== 'entity') return;\n const target = workspace?.preview?.target;\n if (!target?.targetId) return;\n void client.selectSceneEntity(row.id, {\n label: row.name,\n tabId: VIEW_WORKSPACE_TAB_ID,\n targetId: target.targetId,\n targetGeneration: target.generation,\n }).catch(() => {});\n };\n\n const clearSceneSelection = () => {\n setSelected(new Set());\n setAnchor(null);\n const target = workspace?.preview?.target;\n if (!target?.targetId) return;\n void client.clearSceneSelection({\n tabId: VIEW_WORKSPACE_TAB_ID,\n targetId: target.targetId,\n targetGeneration: target.generation,\n }).catch(() => {});\n };\n\n const visibleRows = useMemo(() => {\n const text = query.trim().toLowerCase();\n const filtering = text.length > 0 || filters.size > 0;\n if (filtering) {\n return rows.filter((row) => {\n const names = rowComponentNames(row);\n const typeText = typeLabelFor(row).toLowerCase();\n const componentText = names.join(' ').toLowerCase();\n const textMatch = !text\n || rowLabel(row).toLowerCase().includes(text)\n || typeText.includes(text)\n || componentText.includes(text);\n const typeMatch = entityMatchesSceneTreeFilters(names, filters);\n return !isSceneRootRow(row) && textMatch && typeMatch;\n }).map((row) => ({ ...row, depth: 0 }));\n }\n const collapsedDepths: number[] = [];\n return rows.filter((row) => {\n while (collapsedDepths.length && collapsedDepths.at(-1)! >= row.depth) collapsedDepths.pop();\n const hiddenByParent = collapsedDepths.length > 0;\n if (row.hasChildren && !expanded.has(row.id)) collapsedDepths.push(row.depth);\n return !hiddenByParent;\n });\n }, [expanded, filters, query, rowLabel, rows, typeLabelFor]);\n\n const selectRow = (row: HierarchyRow, event: MouseEvent) => {\n if (row.kind === 'folder') {\n setExpanded((current) => {\n const next = new Set(current);\n if (next.has(row.id)) next.delete(row.id); else next.add(row.id);\n return next;\n });\n return;\n }\n const ordered = visibleRows.filter((entry) => entry.kind === 'entity').map((entry) => entry.id);\n let next: Set<string>;\n if (event.shiftKey && anchor) {\n const from = ordered.indexOf(anchor);\n const to = ordered.indexOf(row.id);\n next = from < 0 || to < 0\n ? new Set([row.id])\n : new Set(ordered.slice(Math.min(from, to), Math.max(from, to) + 1));\n } else if (event.ctrlKey || event.metaKey) {\n next = new Set(selected);\n if (next.has(row.id)) next.delete(row.id); else next.add(row.id);\n } else {\n next = new Set([row.id]);\n }\n if (next.size === 0) {\n clearSceneSelection();\n return;\n }\n const primary = next.has(row.id)\n ? row\n : rows.find((entry) => entry.kind === 'entity' && next.has(entry.id));\n if (!primary) {\n clearSceneSelection();\n return;\n }\n setSelected(next);\n setAnchor(primary.id);\n publishSceneSelection(primary);\n };\n const showContext = (event: MouseEvent, items: MenuItem[]) => {\n event.preventDefault();\n event.stopPropagation();\n setHeaderMenu(null);\n setContextMenu({ x: event.clientX, y: event.clientY, items });\n };\n const blankMenu = useCallback((): MenuItem[] => [\n { kind: 'title', label: t('sceneTree.readOnlyTitle') },\n { kind: 'item', id: 'clear-filter', label: t('sceneTree.menu.clearSearchAndFilters'), icon: <X size={14} />, disabled: !query && filters.size === 0, action: () => { setQuery(''); setFilters(new Set()); } },\n { kind: 'item', id: 'focus', label: t('sceneTree.menu.focusSelection'), icon: <Crosshair size={14} />, shortcut: 'F', disabled: selected.size === 0, action: () => {} },\n ], [filters.size, query, selected.size, t]);\n const rowMenu = useCallback((row: HierarchyRow): MenuItem[] => [\n { kind: 'title', label: rowLabel(row), icon: <RowIcon row={row} /> },\n { kind: 'item', id: 'copy-json', label: t('sceneTree.menu.copyJson'), icon: <Braces size={14} />, action: () => void navigator.clipboard?.writeText(JSON.stringify(row, null, 2)) },\n { kind: 'item', id: 'focus', label: t('sceneTree.menu.focusInViewport'), icon: <Crosshair size={14} />, shortcut: 'F', disabled: !workspace?.preview || isSceneRootRow(row), action: () => { const target = workspace?.preview?.target; if (target) void client?.call('entity.focus', { entityId: row.id, targetId: target.targetId, targetGeneration: target.generation }); } },\n ], [rowLabel, t, client, workspace?.preview]);\n useEffect(() => {\n if (!headerMenu) setHeaderMenuAnchor(null);\n }, [headerMenu]);\n\n const openHeaderMenu = (kind: 'filter' | 'settings') => {\n if (headerMenu === kind) {\n setHeaderMenu(null);\n return;\n }\n const ref = kind === 'filter' ? filterButtonRef : settingsButtonRef;\n const rect = ref.current?.getBoundingClientRect();\n if (rect) setHeaderMenuAnchor(rect);\n setHeaderMenu(kind);\n };\n\n const toggleTypeFilter = (filterId: string) => {\n setFilters((current) => {\n const next = new Set(current);\n if (next.has(filterId)) next.delete(filterId);\n else next.add(filterId);\n return next;\n });\n };\n\n return (\n <div\n className=\"panel outliner-panel\"\n data-testid=\"panel-hierarchy\"\n data-view-readonly=\"true\"\n role=\"tree\"\n tabIndex={0}\n onKeyDown={(event) => {\n if ((event.ctrlKey || event.metaKey) && event.key.toLowerCase() === 'a') {\n event.preventDefault();\n setSelected(new Set(rows.filter((row) => row.kind === 'entity').map((row) => row.id)));\n }\n }}\n >\n <PanelHeader\n className=\"fx-hier-toolbar\"\n data-testid=\"hier-toolbar\"\n start={(\n <Toolbar>\n <IconButton\n ref={filterButtonRef}\n className={filters.size ? 'active' : undefined}\n label={t('sceneTree.filterByType')}\n icon={<Filter size={14} />}\n size=\"compact\"\n onClick={() => openHeaderMenu('filter')}\n />\n </Toolbar>\n )}\n center={(\n <SearchField\n className=\"fx-hier-search\"\n data-testid=\"hier-search\"\n data-action={SCENE_TREE_ACTIONS.search}\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n onClear={() => setQuery('')}\n placeholder={t('sceneTree.searchPlaceholder')}\n label={t('sceneTree.searchLabel')}\n />\n )}\n end={(\n <Toolbar>\n <IconButton\n ref={settingsButtonRef}\n label={t('sceneTree.displaySettings')}\n icon={<Settings size={14} />}\n size=\"compact\"\n onClick={() => openHeaderMenu('settings')}\n />\n </Toolbar>\n )}\n />\n <div className=\"ol-colhead\" data-testid=\"hier-colhead\">\n <span className=\"ch-caret\" aria-hidden />\n <span className=\"ch-name sortable\">{t('sceneTree.columnName')}</span>\n {columns.type ? <span className=\"ch-type sortable col-type\">{t('sceneTree.columnType')}</span> : null}\n {columns.id ? <span className=\"ch-id sortable col-id\">{t('sceneTree.columnId')}</span> : null}\n </div>\n <div\n className=\"ol-body\"\n data-testid=\"hier-root-dropzone\"\n onClick={(event) => {\n if (event.target === event.currentTarget) clearSceneSelection();\n }}\n onContextMenu={(event) => {\n if (!(event.target as HTMLElement).closest('.tn')) showContext(event, blankMenu());\n }}\n >\n {visibleRows.length === 0 ? (\n <EmptyState\n className=\"hier-no-match\"\n title={t('sceneTree.noMatchTitle')}\n description={t('sceneTree.noMatchDescription')}\n />\n ) : visibleRows.map((row) => {\n const isSelected = selected.has(row.id);\n const isHidden = row.hidden === true;\n const isExpanded = expanded.has(row.id);\n return (\n <div\n key={row.id}\n className={`tn k-${rowType(row)}${isSelected ? ' sel' : ''}${isHidden ? ' dim' : ''}`}\n data-testid={isSceneRootRow(row) ? 'hier-row-scene-folder' : `hier-row-${row.id}`}\n data-action={SCENE_TREE_ACTIONS.select}\n style={{ paddingLeft: `calc(var(--fx-ref-space-8) + ${row.depth} * var(--hier-indent-step, calc(var(--fx-ref-space-12) + var(--fx-ref-space-2))))` }}\n role=\"treeitem\"\n aria-selected={isSelected}\n tabIndex={isSelected ? 0 : -1}\n onClick={(event) => selectRow(row, event)}\n onContextMenu={(event) => {\n if (!selected.has(row.id)) {\n setSelected(new Set([row.id]));\n if (row.kind === 'entity') publishSceneSelection(row);\n }\n showContext(event, isSceneRootRow(row) ? blankMenu() : rowMenu(row));\n }}\n >\n <button\n type=\"button\"\n className=\"caret\"\n data-action={SCENE_TREE_ACTIONS.toggleExpanded}\n disabled={!row.hasChildren}\n tabIndex={-1}\n onClick={(event) => {\n event.stopPropagation();\n if (!row.hasChildren) return;\n setExpanded((current) => {\n const next = new Set(current);\n if (next.has(row.id)) next.delete(row.id);\n else next.add(row.id);\n return next;\n });\n }}\n >\n {row.hasChildren ? (isExpanded ? <ChevronDown size={12} /> : <ChevronRight size={12} />) : null}\n </button>\n <span className=\"ico\"><RowIcon row={row} /></span>\n <span className=\"name-cell\">\n <span className=\"nm\">{highlighted(rowLabel(row), query)}</span>\n </span>\n {columns.type ? <span className=\"cell type col-type\"><span className=\"kind\">{typeLabelFor(row)}</span></span> : null}\n {columns.id ? <span className=\"cell id col-id\">{isSceneRootRow(row) ? '' : `#${row.id}`}</span> : null}\n </div>\n );\n })}\n </div>\n <FloatingMenu\n open={Boolean(headerMenuAnchor && headerMenu === 'filter')}\n anchorRect={headerMenuAnchor}\n onClose={() => setHeaderMenu(null)}\n ignorePointerWithin={[filterButtonRef]}\n className=\"hier-filter-menu\"\n containerProps={{ onPointerDown: (event) => event.stopPropagation() }}\n >\n <div className=\"hier-filter-menu-body\">\n <div className=\"hier-filter-section\">{t('sceneTree.filterByType')}</div>\n {resolvedFilterOptions.map((filter) => {\n const active = filters.has(filter.id);\n return (\n <button\n type=\"button\"\n className=\"hier-filter-option\"\n data-active={active ? 'true' : 'false'}\n key={filter.id}\n onClick={() => toggleTypeFilter(filter.id)}\n >\n <Checkbox\n checked={active}\n onChange={() => toggleTypeFilter(filter.id)}\n tabIndex={-1}\n hideLabel\n label={filter.label}\n className=\"hier-filter-check\"\n />\n <span className=\"hier-filter-option-icon\" aria-hidden>{filterOptionIcon(filter.id)}</span>\n {filter.label}\n </button>\n );\n })}\n <div className=\"hier-filter-separator\" />\n <button\n type=\"button\"\n className=\"hier-filter-option hier-filter-clear\"\n disabled={filters.size === 0}\n onClick={() => setFilters(new Set())}\n >\n {t('sceneTree.clearFilters')}\n </button>\n </div>\n </FloatingMenu>\n <FloatingMenu\n open={Boolean(headerMenuAnchor && headerMenu === 'settings')}\n anchorRect={headerMenuAnchor}\n onClose={() => setHeaderMenu(null)}\n ignorePointerWithin={[settingsButtonRef]}\n className=\"hier-filter-menu\"\n containerProps={{ onPointerDown: (event) => event.stopPropagation() }}\n >\n <div className=\"hier-filter-menu-body hierarchy-header-menu-settings\">\n <div className=\"hier-filter-section\">{t('sceneTree.columns')}</div>\n {(['type', 'id'] as const).map((column) => {\n const label = column === 'type'\n ? t('sceneTree.columnType')\n : t('sceneTree.columnId');\n const checked = columns[column];\n const toggle = () => setColumns((current) => ({ ...current, [column]: !current[column] }));\n return (\n <button\n type=\"button\"\n className=\"hier-filter-option\"\n data-action={SCENE_TREE_ACTIONS.toggleColumn}\n data-active={checked ? 'true' : 'false'}\n key={column}\n onClick={toggle}\n >\n <Checkbox\n checked={checked}\n onChange={toggle}\n tabIndex={-1}\n hideLabel\n label={label}\n className=\"hier-filter-check\"\n />\n {label}\n </button>\n );\n })}\n <div className=\"hier-filter-separator\" />\n <button\n type=\"button\"\n className=\"hier-filter-option hier-filter-action\"\n data-action={SCENE_TREE_ACTIONS.expandAll}\n onClick={() => setExpanded(new Set(rows.filter((row) => row.hasChildren).map((row) => row.id)))}\n >\n <Maximize2 size={14} className=\"hier-filter-option-icon\" />\n {t('sceneTree.expandAll')}\n </button>\n <button\n type=\"button\"\n className=\"hier-filter-option hier-filter-action\"\n data-action={SCENE_TREE_ACTIONS.collapseAll}\n onClick={() => setExpanded(new Set(rows.filter(isSceneRootRow).map((row) => row.id)))}\n >\n <Minimize2 size={14} className=\"hier-filter-option-icon\" />\n {t('sceneTree.collapseAll')}\n </button>\n </div>\n </FloatingMenu>\n {contextMenu ? <HierarchyContextMenu state={contextMenu} close={() => setContextMenu(null)} /> : null}\n </div>\n );\n}\n", "import { useCallback, useSyncExternalStore } from 'react';\n\nimport { getLocale, subscribeLocale, t as translate } from './index.ts';\n\nexport function useTranslation() {\n const locale = useSyncExternalStore(subscribeLocale, getLocale, getLocale);\n const t = useCallback(\n (key: string, vars?: Record<string, string | number>) => translate(key, vars),\n [locale],\n );\n return { t, locale };\n}\n", "/**\n * Scene-tree type filters mirror forgeax-editor hierarchy filter options:\n * option ids are component schema names from the Engine host, not UI enums.\n */\n\nconst CATEGORY_RULES = [\n { test: /Camera/, category: 'camera' },\n { test: /Light/, category: 'light' },\n { test: /Character|Controller/, category: 'character' },\n { test: /PlayerStart/, category: 'start' },\n { test: /Spawner/, category: 'spawner' },\n { test: /Mesh/, category: 'mesh' },\n];\n\nfunction categoryRank(category: string) {\n const index = CATEGORY_RULES.findIndex((rule) => rule.category === category);\n return index === -1 ? CATEGORY_RULES.length : index;\n}\n\n/** @param {string} id */\nexport function hierarchyTypeCategory(id: string) {\n if (id === 'group') return 'group';\n if (id === 'entity') return 'entity';\n for (const rule of CATEGORY_RULES) {\n if (rule.test.test(id)) return rule.category;\n }\n return 'generic';\n}\n\n/** @param {string} a @param {string} b */\nexport function compareComponentFilterIds(a: string, b: string) {\n const ra = categoryRank(hierarchyTypeCategory(a));\n const rb = categoryRank(hierarchyTypeCategory(b));\n return ra - rb || a.localeCompare(b);\n}\n\n/**\n * @param {readonly string[]} componentNames\n * @param {ReadonlySet<string>} activeFilters\n */\nexport function entityMatchesSceneTreeFilters(componentNames: readonly string[], activeFilters: ReadonlySet<string>) {\n if (activeFilters.size === 0) return true;\n return componentNames.some((name) => activeFilters.has(name));\n}\n\n/**\n * Build filter options from a component schema name list and optional counts.\n * View derives these options from the loaded entity component identities.\n *\n * @param {readonly string[]} schemaNames\n * @param {ReadonlyMap<string, number>} [counts]\n */\nexport function buildSceneTreeFilterOptions(schemaNames: readonly string[], counts: ReadonlyMap<string, number> = new Map()) {\n const seen = new Set();\n const options = [];\n for (const name of schemaNames) {\n const id = String(name);\n if (!id || seen.has(id)) continue;\n seen.add(id);\n const count = counts.get(id);\n options.push({\n id,\n ...(count === undefined ? {} : { count }),\n });\n }\n options.sort((left, right) => compareComponentFilterIds(left.id, right.id));\n return options;\n}\n", "export type SceneEntityTypeKey = 'mesh' | 'directionalLight' | 'sky' | 'folder' | 'entity' | 'playerStart' | 'camera';\nexport type HierarchyRow = { id: string; name: string; typeKey?: SceneEntityTypeKey; componentNames?: string[]; depth: number; kind: 'folder' | 'entity'; virtual?: boolean; hidden?: boolean; hasChildren?: boolean; expanded?: boolean };\ntype EntityNode = { entityId?: string; entity?: number; name?: string; parentId?: string; componentNames?: string[] };\nimport { buildSceneTreeFilterOptions } from './hierarchy-filters.ts';\n\n/**\n * Normalize Engine `scene.tree.get` payloads into panel rows.\n * View does not author hierarchy; it only projects the latest Engine response.\n */\n\n/**\n * @param {unknown} result\n * @returns {Array<Record<string, unknown>>}\n */\nfunction projectEntityRows(result: unknown): HierarchyRow[] {\n if (!result || typeof result !== 'object') return [];\n const nodes = 'nodes' in result ? result.nodes : undefined;\n if (!Array.isArray(nodes)) return [];\n const rows: HierarchyRow[] = [];\n const seen = new Set();\n const flat = nodes.filter((node): node is EntityNode => node != null && typeof node === 'object');\n const byId = new Map(flat.map(node => [String(node.entityId), node]));\n const children = new Map<string, EntityNode[]>();\n for (const node of flat) {\n if (node.parentId && byId.has(node.parentId)) {\n const siblings = children.get(node.parentId) ?? [];\n siblings.push(node);\n children.set(node.parentId, siblings);\n }\n }\n const visit = (root: EntityNode) => {\n const stack = [{ node: root, depth: 0 }];\n while (stack.length) {\n const { node, depth } = stack.pop()!;\n const id = String(node.entityId ?? '');\n if (!id || seen.has(id)) continue;\n seen.add(id);\n const descendants = children.get(id) ?? [];\n const componentNames = Array.isArray(node.componentNames) ? node.componentNames.filter(name => typeof name === 'string') : [];\n const typeKey = componentNames.includes('Camera') ? 'camera'\n : componentNames.includes('DirectionalLight') ? 'directionalLight'\n : componentNames.includes('MeshFilter') ? 'mesh' : 'entity';\n rows.push({ id, componentNames, name: String(node.name ?? (node.entity === undefined ? id : `Entity ${node.entity}`)), typeKey,\n depth,\n kind: 'entity',\n ...(descendants.length ? { hasChildren: true, expanded: depth < 1 } : {}) });\n for (let i = descendants.length - 1; i >= 0; i--) stack.push({ node: descendants[i], depth: depth + 1 });\n }\n };\n for (const node of flat) if (!node.parentId || !byId.has(node.parentId)) visit(node);\n // Preserve discoverability for cyclic or partial parent projections.\n for (const node of flat) visit(node);\n return rows;\n}\n\n/** Counts describe the loaded rows; Engine owns only component identities. */\nexport function sceneTreeComponentFilters(rows: readonly HierarchyRow[]) {\n const counts = new Map();\n for (const row of rows) for (const name of row.componentNames ?? []) counts.set(name, (counts.get(name) ?? 0) + 1);\n return buildSceneTreeFilterOptions([...counts.keys()], counts);\n}\n\n/** This grouping row belongs only to View and is never sent as an entity reference. */\nexport const HIERARCHY_SCENE_FOLDER_ID = 'hierarchy:scene-root';\nexport function isSceneRootRow(row: HierarchyRow) { return row?.id === HIERARCHY_SCENE_FOLDER_ID; }\nexport function wrapWithVirtualSceneRoot(rows: HierarchyRow[]): HierarchyRow[] {\n if (rows.some(isSceneRootRow)) return rows.map(row => isSceneRootRow(row) ? { ...row, virtual: true } : row);\n return [{ id: HIERARCHY_SCENE_FOLDER_ID, name: 'Scene', typeKey: 'folder', depth: 0,\n kind: 'folder', virtual: true, hasChildren: rows.length > 0, expanded: true },\n ...rows.map(row => ({ ...row, depth: row.depth + 1 }))];\n}\nexport function normalizeSceneTreeRows(result: unknown) { return wrapWithVirtualSceneRoot(projectEntityRows(result)); }\nexport function normalizeSceneTreeResponse(result: unknown) {\n const rows = normalizeSceneTreeRows(result);\n return { rows, filterOptions: sceneTreeComponentFilters(rows) };\n}\n", "\n const css = \"/* packages/view-plugin-scene-tree/src/ui/scene-tree.css */\\n.outliner-panel {\\n --hier-w-caret: calc(var(--fx-ref-space-12) + var(--fx-ref-space-2));\\n --hier-w-type: calc(var(--fx-ref-space-48) + var(--fx-ref-space-16) + var(--fx-ref-space-4));\\n --hier-w-id: calc(var(--fx-ref-space-48) + var(--fx-ref-space-24));\\n --hier-indent-step: calc(var(--fx-ref-space-12) + var(--fx-ref-space-2));\\n display: flex;\\n flex-direction: column;\\n container-type: inline-size;\\n width: 100%;\\n height: 100%;\\n min-height: 0;\\n overflow: hidden;\\n position: relative;\\n background: var(--fx-color-surface-sidebar);\\n color: var(--fx-color-text-primary);\\n font: var(--fx-type-compact-font-weight) var(--fx-type-compact-font-size) / var(--fx-type-compact-line-height) var(--fx-type-compact-font-family);\\n}\\n.outliner-panel * {\\n box-sizing: border-box;\\n}\\n.outliner-panel button,\\n.outliner-panel input {\\n font: inherit;\\n}\\n.fx-hier-toolbar {\\n flex: 0 0 auto;\\n gap: var(--fx-ref-space-6);\\n padding: var(--fx-ref-space-6) var(--fx-ref-space-8);\\n background: var(--fx-color-surface-sidebar);\\n}\\n.fx-hier-toolbar > .fx-panel-header__slot:nth-child(2) {\\n flex: 1;\\n}\\n.fx-hier-search {\\n flex: 1;\\n width: 100%;\\n min-width: 0;\\n}\\n.fx-hier-search .fx-input {\\n height: var(--fx-component-control-height-compact);\\n}\\n.outliner-panel .fx-button--icon.active {\\n border-color: var(--fx-color-brand-accent);\\n background: var(--fx-color-brand-soft);\\n color: var(--fx-color-brand-text);\\n}\\n.hier-filter-menu-body {\\n min-width: 220px;\\n padding: var(--fx-ref-space-4);\\n border: var(--fx-border-width) solid var(--fx-color-border-default);\\n border-radius: var(--fx-radius-popover);\\n background: var(--fx-color-surface-raised);\\n box-shadow: var(--fx-shadow-floating);\\n}\\n.hier-filter-section {\\n padding: var(--fx-ref-space-6) var(--fx-ref-space-8) var(--fx-ref-space-4);\\n color: var(--fx-color-text-muted);\\n font-size: var(--fx-type-caption-font-size);\\n font-weight: var(--fx-ref-font-weight-600);\\n letter-spacing: var(--fx-type-caption-letter-spacing);\\n text-transform: uppercase;\\n}\\n.hier-filter-separator {\\n height: var(--fx-border-width);\\n margin: var(--fx-ref-space-4) 0;\\n background: var(--fx-color-border-subtle);\\n}\\n.hier-filter-option {\\n display: flex;\\n align-items: center;\\n gap: var(--fx-ref-space-8);\\n width: 100%;\\n min-height: var(--fx-component-editor-row-height);\\n padding: var(--fx-ref-space-4) var(--fx-ref-space-8);\\n border: 0;\\n border-radius: var(--fx-radius-control);\\n background: transparent;\\n color: var(--fx-color-text-secondary);\\n font: inherit;\\n text-align: left;\\n cursor: pointer;\\n}\\n.hier-filter-option:hover:not(:disabled) {\\n background: var(--fx-color-surface-hover);\\n color: var(--fx-color-text-primary);\\n}\\n.hier-filter-option:disabled {\\n color: var(--fx-color-text-disabled);\\n cursor: default;\\n}\\n.hier-filter-option-icon {\\n display: grid;\\n flex: 0 0 14px;\\n place-items: center;\\n width: 14px;\\n color: var(--fx-color-text-muted);\\n}\\n.hier-filter-check {\\n flex: 0 0 var(--fx-component-choice-size);\\n pointer-events: none;\\n}\\n.hier-filter-check.fx-choice {\\n align-items: center;\\n gap: 0;\\n min-height: 0;\\n margin: 0;\\n}\\n.hier-filter-check .fx-choice__text {\\n display: none;\\n}\\n.hier-filter-clear {\\n justify-content: flex-start;\\n color: var(--fx-color-text-muted);\\n}\\n.ol-colhead {\\n display: flex;\\n align-items: center;\\n min-height: var(--fx-component-editor-row-height);\\n padding: var(--fx-ref-space-4) var(--fx-ref-space-8);\\n border-bottom: var(--fx-border-width) solid var(--fx-color-border-subtle);\\n color: var(--fx-color-text-muted);\\n font: var(--fx-type-caption-font-weight) var(--fx-type-caption-font-size) / var(--fx-type-caption-line-height) var(--fx-type-code-font-family);\\n letter-spacing: var(--fx-type-caption-letter-spacing);\\n text-transform: uppercase;\\n}\\n.ch-caret {\\n width: var(--hier-w-caret);\\n flex: 0 0 auto;\\n}\\n.ch-name {\\n flex: 1;\\n min-width: var(--fx-ref-space-16);\\n}\\n.ch-type {\\n width: var(--hier-w-type);\\n flex: 0 0 auto;\\n}\\n.ch-id {\\n width: var(--hier-w-id);\\n flex: 0 0 auto;\\n}\\n.ol-body {\\n flex: 1;\\n min-height: 0;\\n overflow: auto;\\n padding: var(--fx-ref-space-4) 0 var(--fx-ref-space-8);\\n}\\n.tn {\\n display: flex;\\n align-items: center;\\n min-height: var(--fx-component-editor-row-height);\\n padding-right: var(--fx-ref-space-8);\\n border: 0;\\n border-left: var(--fx-border-focus-width) solid transparent;\\n color: var(--fx-color-text-secondary);\\n white-space: nowrap;\\n cursor: default;\\n user-select: none;\\n}\\n.tn:hover {\\n background: var(--fx-color-surface-hover);\\n color: var(--fx-color-text-primary);\\n}\\n.tn.sel {\\n border-left-color: var(--fx-color-selection-indicator);\\n background: var(--fx-color-selection-bg);\\n color: var(--fx-color-selection-fg);\\n}\\n.tn.dim {\\n opacity: 0.45;\\n}\\n.tn .caret {\\n display: grid;\\n place-items: center;\\n width: var(--hier-w-caret);\\n height: var(--fx-ref-space-16);\\n flex: 0 0 auto;\\n padding: 0;\\n border: 0;\\n background: transparent;\\n color: var(--fx-color-text-muted);\\n}\\n.tn .caret:disabled {\\n opacity: 0;\\n pointer-events: none;\\n}\\n.tn .ico {\\n display: grid;\\n place-items: center;\\n width: calc(var(--fx-ref-space-16) + var(--fx-ref-space-2));\\n flex: 0 0 auto;\\n color: var(--fx-color-text-muted);\\n}\\n.tn .name-cell {\\n display: flex;\\n align-items: center;\\n flex: 1;\\n min-width: 0;\\n gap: var(--fx-ref-space-4);\\n overflow: hidden;\\n}\\n.tn .nm {\\n overflow: hidden;\\n text-overflow: ellipsis;\\n white-space: nowrap;\\n}\\n.tn.k-folder .nm,\\n.tn.k-grp .nm {\\n color: var(--fx-color-text-muted);\\n}\\n.tn .cell {\\n overflow: hidden;\\n color: var(--fx-color-text-muted);\\n font: var(--fx-type-caption-font-weight) var(--fx-type-caption-font-size) / var(--fx-type-caption-line-height) var(--fx-type-code-font-family);\\n text-overflow: ellipsis;\\n}\\n.tn .cell.type {\\n width: var(--hier-w-type);\\n}\\n.tn .cell.id {\\n width: var(--hier-w-id);\\n}\\n.tn .kind {\\n color: var(--fx-color-text-secondary);\\n}\\n.tn.k-light .ico {\\n color: var(--fx-color-status-warning-fg);\\n}\\n.tn.k-camera .ico {\\n color: var(--fx-color-status-info-fg);\\n}\\n.tn.k-character .ico {\\n color: var(--fx-color-brand-text);\\n}\\n.tn.k-scene .ico,\\n.tn.k-group .ico,\\n.tn.k-folder .ico {\\n color: var(--fx-color-text-muted);\\n}\\n.tn.pdim {\\n opacity: 0.68;\\n}\\n.tn.drop-inside {\\n background: var(--fx-color-brand-soft);\\n outline: var(--fx-border-width) solid var(--fx-color-brand-accent);\\n outline-offset: calc(-1 * var(--fx-border-width));\\n}\\n.tn.drop-before::before,\\n.tn.drop-after::after {\\n content: \\\"\\\";\\n position: absolute;\\n z-index: var(--fx-layer-sticky);\\n right: var(--fx-ref-space-4);\\n left: var(--fx-ref-space-4);\\n height: var(--fx-ref-space-2);\\n background: var(--fx-color-brand-accent);\\n box-shadow: var(--fx-shadow-subtle);\\n}\\n.tn {\\n position: relative;\\n}\\n.tn.drop-before::before {\\n top: calc(-1 * var(--fx-border-width));\\n}\\n.tn.drop-after::after {\\n bottom: calc(-1 * var(--fx-border-width));\\n}\\n.hier-inline-rename {\\n width: 100%;\\n min-width: 0;\\n height: var(--fx-component-control-height-compact);\\n padding: var(--fx-ref-space-2) var(--fx-ref-space-4);\\n border: var(--fx-border-width) solid var(--fx-color-border-focus);\\n border-radius: var(--fx-ref-radius-4);\\n outline: 0;\\n background: var(--fx-color-surface-inset);\\n color: var(--fx-color-text-primary);\\n}\\n.hier-no-match {\\n padding: var(--fx-ref-space-8) var(--fx-ref-space-12);\\n}\\n.outliner-panel .hl {\\n border-radius: var(--fx-ref-radius-4);\\n background: var(--fx-color-brand-soft);\\n color: var(--fx-color-text-primary);\\n}\\n.outliner-panel .muted {\\n color: var(--fx-color-text-muted);\\n}\\n@container (max-width: 195px) {\\n .outliner-panel .col-type {\\n display: none;\\n }\\n}\\n@container (max-width: 280px) {\\n .outliner-panel .col-id {\\n display: none;\\n }\\n}\\n.hier-context-position {\\n position: fixed;\\n z-index: var(--fx-layer-tooltip);\\n color: var(--fx-color-text-secondary);\\n font: var(--fx-type-ui-font-weight) var(--fx-type-ui-font-size) / var(--fx-type-ui-line-height) var(--fx-type-ui-font-family);\\n}\\n.hier-context-menu,\\n.hier-context-submenu {\\n box-sizing: border-box;\\n display: flex;\\n flex-direction: column;\\n min-width: var(--fx-component-menu-min-width);\\n max-height: calc(100vh - var(--fx-ref-space-16));\\n padding: var(--fx-ref-space-6);\\n overflow: visible;\\n border: var(--fx-border-width) solid var(--fx-color-border-default);\\n border-radius: var(--fx-radius-popover);\\n background: var(--fx-color-surface-raised);\\n box-shadow: var(--fx-shadow-floating);\\n}\\n.hier-context-submenu {\\n position: absolute;\\n top: calc(-1 * var(--fx-ref-space-6));\\n left: calc(100% - var(--fx-ref-space-2));\\n min-width: var(--fx-component-panel-config-min-width);\\n}\\n.hier-context-title {\\n display: flex;\\n align-items: center;\\n gap: var(--fx-ref-space-6);\\n padding: var(--fx-ref-space-6) var(--fx-ref-space-8);\\n color: var(--fx-color-text-muted);\\n font: var(--fx-type-caption-font-weight) var(--fx-type-caption-font-size) / var(--fx-type-caption-line-height) var(--fx-type-code-font-family);\\n}\\n.hier-context-item-wrap {\\n position: relative;\\n}\\n.hier-context-item-wrap > button {\\n box-sizing: border-box;\\n display: flex;\\n align-items: center;\\n gap: var(--fx-ref-space-8);\\n width: 100%;\\n min-height: var(--fx-component-menu-row-height);\\n padding: var(--fx-ref-space-6) var(--fx-ref-space-8);\\n border: 0;\\n border-radius: var(--fx-radius-control);\\n background: transparent;\\n color: inherit;\\n font: inherit;\\n text-align: left;\\n cursor: pointer;\\n}\\n.hier-context-item-wrap > button:hover:not(:disabled) {\\n background: var(--fx-color-surface-hover);\\n color: var(--fx-color-text-primary);\\n}\\n.hier-context-item-wrap > button:disabled {\\n opacity: 0.38;\\n cursor: default;\\n}\\n.hier-context-item-wrap > button[data-danger=true] {\\n color: var(--fx-color-status-error-fg);\\n}\\n.hier-context-item-wrap > button[data-forge=true] .hier-context-icon {\\n color: var(--fx-color-brand-text);\\n}\\n.hier-context-icon {\\n display: grid;\\n place-items: center;\\n width: var(--fx-component-control-icon-size);\\n flex: 0 0 var(--fx-component-control-icon-size);\\n color: var(--fx-color-text-muted);\\n}\\n.hier-context-item-wrap > button > span:nth-child(2) {\\n flex: 1;\\n}\\n.hier-context-item-wrap kbd {\\n color: var(--fx-color-text-muted);\\n font: var(--fx-type-caption-font-weight) var(--fx-type-caption-font-size) / var(--fx-type-caption-line-height) var(--fx-type-code-font-family);\\n}\\n.hier-context-separator {\\n display: block;\\n height: var(--fx-border-width);\\n margin: var(--fx-ref-space-6);\\n background: var(--fx-color-border-subtle);\\n}\\n\";\n if (typeof document !== 'undefined' && !document.querySelector('style[data-forgeax-css=\"a9fd1866464288a4a4b490686e0c4225551e378d64dcb6499d18061c7e908e0d\"]')) {\n const style = document.createElement('style');\n style.dataset.forgeaxCss = \"a9fd1866464288a4a4b490686e0c4225551e378d64dcb6499d18061c7e908e0d\";\n style.textContent = css;\n document.head.append(style);\n }\n export default css;\n "],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,SAAS,kBAAkB;;;ACH3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAaP;AAAA,EACE,eAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,wBAAAC;AAAA,OAGK;AACP,SAAS,oBAAoB;;;ACxC7B,SAAS,aAAa,4BAA4B;AAI3C,SAAS,iBAAiB;AAC/B,QAAM,SAAS,qBAAqB,iBAAiB,WAAW,SAAS;AACzE,QAAMC,KAAI;AAAA,IACR,CAAC,KAAa,SAA2C,EAAU,KAAK,IAAI;AAAA,IAC5E,CAAC,MAAM;AAAA,EACT;AACA,SAAO,EAAE,GAAAA,IAAG,OAAO;AACrB;;;ACNA,IAAM,iBAAiB;AAAA,EACrB,EAAE,MAAM,UAAU,UAAU,SAAS;AAAA,EACrC,EAAE,MAAM,SAAS,UAAU,QAAQ;AAAA,EACnC,EAAE,MAAM,wBAAwB,UAAU,YAAY;AAAA,EACtD,EAAE,MAAM,eAAe,UAAU,QAAQ;AAAA,EACzC,EAAE,MAAM,WAAW,UAAU,UAAU;AAAA,EACvC,EAAE,MAAM,QAAQ,UAAU,OAAO;AACnC;AAEA,SAAS,aAAa,UAAkB;AACtC,QAAM,QAAQ,eAAe,UAAU,CAAC,SAAS,KAAK,aAAa,QAAQ;AAC3E,SAAO,UAAU,KAAK,eAAe,SAAS;AAChD;AAGO,SAAS,sBAAsB,IAAY;AAChD,MAAI,OAAO,QAAS,QAAO;AAC3B,MAAI,OAAO,SAAU,QAAO;AAC5B,aAAW,QAAQ,gBAAgB;AACjC,QAAI,KAAK,KAAK,KAAK,EAAE,EAAG,QAAO,KAAK;AAAA,EACtC;AACA,SAAO;AACT;AAGO,SAAS,0BAA0B,GAAW,GAAW;AAC9D,QAAM,KAAK,aAAa,sBAAsB,CAAC,CAAC;AAChD,QAAM,KAAK,aAAa,sBAAsB,CAAC,CAAC;AAChD,SAAO,KAAK,MAAM,EAAE,cAAc,CAAC;AACrC;AAMO,SAAS,8BAA8B,gBAAmC,eAAoC;AACnH,MAAI,cAAc,SAAS,EAAG,QAAO;AACrC,SAAO,eAAe,KAAK,CAAC,SAAS,cAAc,IAAI,IAAI,CAAC;AAC9D;AASO,SAAS,4BAA4B,aAAgC,SAAsC,oBAAI,IAAI,GAAG;AAC3H,QAAM,OAAO,oBAAI,IAAI;AACrB,QAAM,UAAU,CAAC;AACjB,aAAW,QAAQ,aAAa;AAC9B,UAAM,KAAK,OAAO,IAAI;AACtB,QAAI,CAAC,MAAM,KAAK,IAAI,EAAE,EAAG;AACzB,SAAK,IAAI,EAAE;AACX,UAAM,QAAQ,OAAO,IAAI,EAAE;AAC3B,YAAQ,KAAK;AAAA,MACX;AAAA,MACA,GAAI,UAAU,SAAY,CAAC,IAAI,EAAE,MAAM;AAAA,IACzC,CAAC;AAAA,EACH;AACA,UAAQ,KAAK,CAAC,MAAM,UAAU,0BAA0B,KAAK,IAAI,MAAM,EAAE,CAAC;AAC1E,SAAO;AACT;;;ACrDA,SAAS,kBAAkB,QAAiC;AAC1D,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO,CAAC;AACnD,QAAM,QAAQ,WAAW,SAAS,OAAO,QAAQ;AACjD,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,QAAM,OAAuB,CAAC;AAC9B,QAAM,OAAO,oBAAI,IAAI;AACrB,QAAM,OAAO,MAAM,OAAO,CAAC,SAA6B,QAAQ,QAAQ,OAAO,SAAS,QAAQ;AAChG,QAAM,OAAO,IAAI,IAAI,KAAK,IAAI,UAAQ,CAAC,OAAO,KAAK,QAAQ,GAAG,IAAI,CAAC,CAAC;AACpE,QAAM,WAAW,oBAAI,IAA0B;AAC/C,aAAW,QAAQ,MAAM;AACvB,QAAI,KAAK,YAAY,KAAK,IAAI,KAAK,QAAQ,GAAG;AAC5C,YAAM,WAAW,SAAS,IAAI,KAAK,QAAQ,KAAK,CAAC;AACjD,eAAS,KAAK,IAAI;AAClB,eAAS,IAAI,KAAK,UAAU,QAAQ;AAAA,IACtC;AAAA,EACF;AACA,QAAM,QAAQ,CAAC,SAAqB;AAClC,UAAM,QAAQ,CAAC,EAAE,MAAM,MAAM,OAAO,EAAE,CAAC;AACvC,WAAO,MAAM,QAAQ;AACnB,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,IAAI;AAClC,YAAM,KAAK,OAAO,KAAK,YAAY,EAAE;AACrC,UAAI,CAAC,MAAM,KAAK,IAAI,EAAE,EAAG;AACzB,WAAK,IAAI,EAAE;AACX,YAAM,cAAc,SAAS,IAAI,EAAE,KAAK,CAAC;AACzC,YAAM,iBAAiB,MAAM,QAAQ,KAAK,cAAc,IAAI,KAAK,eAAe,OAAO,UAAQ,OAAO,SAAS,QAAQ,IAAI,CAAC;AAC5H,YAAM,UAAU,eAAe,SAAS,QAAQ,IAAI,WAChD,eAAe,SAAS,kBAAkB,IAAI,qBAC9C,eAAe,SAAS,YAAY,IAAI,SAAS;AACrD,WAAK,KAAK;AAAA,QAAE;AAAA,QAAI;AAAA,QAAgB,MAAM,OAAO,KAAK,SAAS,KAAK,WAAW,SAAY,KAAK,UAAU,KAAK,MAAM,GAAG;AAAA,QAAG;AAAA,QACrH;AAAA,QACA,MAAM;AAAA,QACN,GAAI,YAAY,SAAS,EAAE,aAAa,MAAM,UAAU,QAAQ,EAAE,IAAI,CAAC;AAAA,MAAG,CAAC;AAC7E,eAAS,IAAI,YAAY,SAAS,GAAG,KAAK,GAAG,IAAK,OAAM,KAAK,EAAE,MAAM,YAAY,CAAC,GAAG,OAAO,QAAQ,EAAE,CAAC;AAAA,IACzG;AAAA,EACF;AACA,aAAW,QAAQ,KAAM,KAAI,CAAC,KAAK,YAAY,CAAC,KAAK,IAAI,KAAK,QAAQ,EAAG,OAAM,IAAI;AAEnF,aAAW,QAAQ,KAAM,OAAM,IAAI;AACnC,SAAO;AACT;AAGO,SAAS,0BAA0B,MAA+B;AACvE,QAAM,SAAS,oBAAI,IAAI;AACvB,aAAW,OAAO,KAAM,YAAW,QAAQ,IAAI,kBAAkB,CAAC,EAAG,QAAO,IAAI,OAAO,OAAO,IAAI,IAAI,KAAK,KAAK,CAAC;AACjH,SAAO,4BAA4B,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,MAAM;AAC/D;AAGO,IAAM,4BAA4B;AAClC,SAAS,eAAe,KAAmB;AAAE,SAAO,KAAK,OAAO;AAA2B;AAC3F,SAAS,yBAAyB,MAAsC;AAC7E,MAAI,KAAK,KAAK,cAAc,EAAG,QAAO,KAAK,IAAI,SAAO,eAAe,GAAG,IAAI,EAAE,GAAG,KAAK,SAAS,KAAK,IAAI,GAAG;AAC3G,SAAO;AAAA,IAAC;AAAA,MAAE,IAAI;AAAA,MAA2B,MAAM;AAAA,MAAS,SAAS;AAAA,MAAU,OAAO;AAAA,MAChF,MAAM;AAAA,MAAU,SAAS;AAAA,MAAM,aAAa,KAAK,SAAS;AAAA,MAAG,UAAU;AAAA,IAAK;AAAA,IAC5E,GAAG,KAAK,IAAI,UAAQ,EAAE,GAAG,KAAK,OAAO,IAAI,QAAQ,EAAE,EAAE;AAAA,EAAC;AAC1D;AACO,SAAS,uBAAuB,QAAiB;AAAE,SAAO,yBAAyB,kBAAkB,MAAM,CAAC;AAAG;;;AHmC5F,SAqFjB,UArFiB,KAkCgB,YAlChB;AAjB1B,SAAS,kBAAkB,KAAmB;AAC5C,MAAI,MAAM,QAAQ,IAAI,cAAc,KAAK,IAAI,eAAe,SAAS,GAAG;AACtE,WAAO,IAAI;AAAA,EACb;AACA,SAAO,IAAI,UAAU,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;AAChD;AAEA,SAAS,QAAQ,KAAmB;AAClC,MAAI,eAAe,GAAG,EAAG,QAAO;AAChC,MAAI,IAAI,SAAS,SAAU,QAAO;AAClC,QAAM,UAAU,kBAAkB,GAAG,EAAE,KAAK,CAAC,SAAS,SAAS,WAAW,KAAK,IAAI;AACnF,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,sBAAsB,OAAO,OAAO,CAAC;AAC9C;AAEA,SAAS,iBAAiB,IAAY;AACpC,UAAQ,sBAAsB,EAAE,GAAG;AAAA,IACjC,KAAK;AAAU,aAAO,oBAAC,UAAO,MAAM,IAAI;AAAA,IACxC,KAAK;AAAS,aAAO,oBAAC,aAAU,MAAM,IAAI;AAAA,IAC1C,KAAK;AAAa,aAAO,oBAAC,mBAAgB,MAAM,IAAI;AAAA,IACpD,KAAK;AAAS,aAAO,oBAAC,UAAO,MAAM,IAAI;AAAA,IACvC;AAAS,aAAO,oBAAC,OAAI,MAAM,IAAI;AAAA,EACjC;AACF;AAEA,SAAS,QAAQ,EAAE,IAAI,GAA0B;AAC/C,MAAI,eAAe,GAAG,EAAG,QAAO,oBAAC,UAAO,MAAM,IAAI;AAClD,MAAI,IAAI,SAAS,SAAU,QAAO,oBAAC,UAAO,MAAM,IAAI;AACpD,MAAI,IAAI,YAAY,mBAAoB,QAAO,oBAAC,aAAU,MAAM,IAAI;AACpE,MAAI,IAAI,YAAY,SAAU,QAAO,oBAAC,UAAO,MAAM,IAAI;AACvD,MAAI,IAAI,SAAS,SAAU,QAAO,oBAAC,mBAAgB,MAAM,IAAI;AAC7D,SAAO,oBAAC,OAAI,MAAM,IAAI;AACxB;AAEA,SAAS,qBAAqB,EAAE,OAAO,MAAM,GAA2D;AACtG,QAAM,cAAc,eAAe;AACnC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAwB,IAAI;AAC1D,YAAU,MAAM;AACd,UAAM,UAAU,MAAM,MAAM;AAC5B,UAAM,SAAS,CAAC,UAAyB,MAAM,QAAQ,YAAY,MAAM;AACzE,WAAO,iBAAiB,eAAe,OAAO;AAC9C,WAAO,iBAAiB,WAAW,MAAM;AACzC,WAAO,MAAM;AACX,aAAO,oBAAoB,eAAe,OAAO;AACjD,aAAO,oBAAoB,WAAW,MAAM;AAAA,IAC9C;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AACV,QAAM,cAAc,CAAC,OAAmB,SAAS,UAC/C,oBAAC,SAAI,WAAW,SAAS,yBAAyB,qBAC/C,gBAAM,IAAI,CAAC,MAAM,UAAU;AAC1B,QAAI,KAAK,SAAS,YAAa,QAAO,oBAAC,OAAE,WAAU,4BAA8B,OAAO,KAAK,EAAI;AACjG,QAAI,KAAK,SAAS,QAAS,QAAO,qBAAC,SAAI,WAAU,sBAA6C;AAAA,WAAK;AAAA,MAAM,KAAK;AAAA,SAAnC,SAAS,KAAK,EAA2B;AACpH,WACE,qBAAC,SAAI,WAAU,0BAAuC,gBAAgB,MAAM,KAAK,YAAY,WAAW,KAAK,EAAE,GAC7G;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,kBAAgB,KAAK;AAAA,UACrB,eAAa,KAAK,UAAU;AAAA,UAC5B,cAAY,KAAK,SAAS;AAAA,UAC1B,UAAU,KAAK;AAAA,UACf,SAAS,MAAM;AACb,gBAAI,KAAK,UAAU;AACjB,yBAAW,YAAY,KAAK,KAAK,OAAO,KAAK,EAAE;AAC/C;AAAA,YACF;AACA,iBAAK,SAAS;AACd,kBAAM;AAAA,UACR;AAAA,UAEA;AAAA,gCAAC,UAAK,WAAU,qBAAqB,eAAK,MAAK;AAAA,YAC/C,oBAAC,UAAM,eAAK,OAAM;AAAA,YACjB,KAAK,WAAW,oBAAC,SAAK,eAAK,UAAS,IAAS;AAAA,YAC7C,KAAK,WAAW,oBAAC,gBAAa,MAAM,IAAI,IAAK;AAAA;AAAA;AAAA,MAChD;AAAA,MACC,KAAK,YAAY,YAAY,KAAK,KAAK,YAAY,KAAK,UAAU,IAAI,IAAI;AAAA,SAtBhC,KAAK,EAuBlD;AAAA,EAEJ,CAAC,GACH;AAEF,SAAO;AAAA,IACL;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,eAAa,mBAAmB;AAAA,QAChC,MAAK;AAAA,QACL,OAAO;AAAA,UACL,MAAM,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,GAAG,OAAO,aAAa,GAAG,CAAC;AAAA,UAC5D,KAAK,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,GAAG,OAAO,cAAc,GAAG,CAAC;AAAA,QAC9D;AAAA,QACA,eAAe,CAAC,UAAU,MAAM,gBAAgB;AAAA,QAChD,eAAe,CAAC,UAAU,MAAM,eAAe;AAAA,QAE9C,sBAAY,MAAM,KAAK;AAAA;AAAA,IAC1B;AAAA,IACA,eAAe,SAAS;AAAA,EAC1B;AACF;AAEA,SAAS,YAAY,OAAe,OAAe;AACjD,QAAM,QAAQ,MAAM,YAAY,EAAE,QAAQ,MAAM,YAAY,CAAC;AAC7D,MAAI,CAAC,SAAS,QAAQ,EAAG,QAAO;AAChC,SAAO,iCAAG;AAAA,UAAM,MAAM,GAAG,KAAK;AAAA,IAAE,oBAAC,UAAK,WAAU,MAAM,gBAAM,MAAM,OAAO,QAAQ,MAAM,MAAM,GAAE;AAAA,IAAQ,MAAM,MAAM,QAAQ,MAAM,MAAM;AAAA,KAAE;AAC3I;AAEO,SAAS,eAAe,OAA0C;AACvE,MAAI,CAAC,MAAM,QAAQ;AACjB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAM;AAAA,QACN,aAAY;AAAA;AAAA,IACd;AAAA,EAEJ;AACA,SAAO,oBAAC,sBAAmB,QAAQ,MAAM,QAAQ;AACnD;AAEA,SAAS,mBACP,QACA,WACA,WACA,QACA;AACA,QAAM,CAAC,YAAY,aAAa,IAAI,SAA0F,IAAI;AAClI,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,CAAC;AAC5C,QAAM,SAAS,WAAW,SAAS;AACnC,QAAM,YAAY,WAAW,SAAS;AACtC,QAAM,MAAM,GAAG,QAAQ,QAAQ,IAAI,QAAQ,UAAU;AACrD,QAAM,UAAU,YAAY,QAAQ,MAAM,aAAa;AACvD,QAAM,OAAO,SAAS,QAAQ,CAAC;AAE/B,YAAU,MAAM;AAAE,iBAAa,CAAC;AAAA,EAAG,GAAG,CAAC,QAAQ,UAAU,QAAQ,UAAU,CAAC;AAE5E,YAAU,MAAM;AACd,QAAI,CAAC,aAAa,CAAC,QAAQ,YAAY,CAAC,WAAW;AACjD,UAAI,CAAC,UAAW;AAChB,oBAAc,IAAI;AAClB;AAAA,IACF;AACA,UAAM,cAAc,2BAA2B,QAAQ,CAACC,aACtDA,UAAS,SAAS,OAAO,aACzBA,UAAS,SAAS,QAAQ,aAAa,OAAO,YAC9CA,UAAS,SAAS,QAAQ,eAAe,OAAO,UAAU;AAC5D,UAAM,EAAE,OAAO,IAAI;AACnB,QAAI;AACJ,UAAM,UAAU,YAAY;AAC1B,UAAI,OAAO,QAAS;AACpB,UAAI,aAAa;AACjB,UAAI;AACF,cAAM,UAAU;AAAA,UACd,OAAO;AAAA,UAAuB;AAAA,UAAW,UAAU,OAAO;AAAA,UAC1D,kBAAkB,OAAO;AAAA,UAAY;AAAA,QACvC;AACA,cAAM,SAAS,MAAM,OAAO,aAAa,EAAE,GAAG,SAAS,OAAO,IAAK,CAAC;AACpE,YAAI,OAAO,QAAS;AACpB,cAAM,QAAQ,CAAC,GAAI,OAAO,SAAS,CAAC,CAAE;AACtC,YAAI,aAAa,OAAO;AACxB,iBAAS,OAAO,GAAG,OAAO,aAAa,eAAe,QAAQ,eAAe,QAAW,QAAQ;AAC9F,gBAAM,OAAO,MAAM,OAAO,aAAa,EAAE,GAAG,SAAS,QAAQ,YAAY,UAAU,OAAO,OAAO,QAAQ,GAAG,OAAO,IAAK,CAAC;AACzH,cAAI,OAAO,QAAS;AACpB,gBAAM,KAAK,GAAG,KAAK,KAAK;AACxB,uBAAa,KAAK;AAAA,QACpB;AACA,YAAI,OAAO,QAAS;AACpB,sBAAc,CAACA,aAAY;AACzB,gBAAM,OAAO,EAAE,KAAK,MAAM,uBAAuB,EAAE,GAAG,QAAQ,MAAM,CAAC,GAAG,SAAS,eAAe,QAAQ,eAAe,QAAW,QAAQ,MAAM;AAChJ,cACEA,UAAS,QAAQ,KAAK,OACtBA,SAAQ,WAAW,KAAK,UACxBA,SAAQ,YAAY,KAAK,WACzB,cAAcA,SAAQ,MAAM,KAAK,IAAI,EACrC,QAAOA;AACT,iBAAO;AAAA,QACT,CAAC;AAAA,MACH,QAAQ;AACN,YAAI,OAAO,QAAS;AACpB,sBAAc,CAACA,aAAY;AACzB,cAAIA,UAAS,QAAQ,OAAOA,SAAQ,UAAU,CAACA,SAAQ,WAAWA,SAAQ,KAAK,WAAW,EAAG,QAAOA;AACpG,iBAAO,EAAE,KAAK,MAAM,CAAC,GAAG,SAAS,OAAO,QAAQ,KAAK;AAAA,QACvD,CAAC;AACD,qBAAa;AAAA,MACf;AACA,UAAI,CAAC,OAAO,SAAS;AACnB,gBAAQ,WAAW,SAAS,UAAU;AAAA,MACxC;AAAA,IACF;AACA,SAAK,QAAQ;AACb,WAAO,MAAM;AAAE,kBAAY,QAAQ;AAAG,mBAAa,KAAK;AAAA,IAAG;AAAA,EAG7D,GAAG,CAAC,QAAQ,WAAW,WAAW,QAAQ,UAAU,QAAQ,YAAY,WAAW,KAAK,QAAQ,SAAS,CAAC;AAE1G,SAAO,EAAE,MAAM,eAAe,0BAA0B,IAAI,GAAG,QAAQ,SAAS,UAAU,OAAO,SAAS,SAAS,WAAW,OAAO,UAAU,MAAM,aAAa,WAAS,QAAQ,CAAC,EAAE;AACxL;AAEA,SAAS,mBAAmB,EAAE,OAAO,GAAqC;AACxE,QAAM,EAAE,GAAAC,GAAE,IAAI,eAAe;AAC7B,QAAM,SAAS,QAAQ,MAAM,2BAA2B,MAAM,GAAG,CAAC,MAAM,CAAC;AACzE,QAAM,YAAYC;AAAA,IAChB,OAAO;AAAA,IACP,MAAM,OAAO,YAAY;AAAA,IACzB,MAAM,OAAO,YAAY;AAAA,EAC3B;AACA,QAAM,YAAY,4BAA4B,MAAM;AACpD,QAAM,EAAE,MAAM,eAAe,QAAQ,SAAS,SAAS,IAAI,mBAAmB,QAAQ,WAAW,WAAW,MAAM;AAElH,MAAI,CAAC,WAAW,SAAS,QAAQ,UAAU;AACzC,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAOD,GAAE,uBAAuB;AAAA,QAChC,aAAY;AAAA;AAAA,IACd;AAAA,EAEJ;AACA,MAAI,QAAQ;AACV,WACE;AAAA,MAAC;AAAA;AAAA,QACC,OAAOA,GAAE,uBAAuB;AAAA,QAChC,aAAaA,GAAE,gCAAgC;AAAA;AAAA,IACjD;AAAA,EAEJ;AACA,MAAI,KAAK,WAAW,EAAG,QAAO,oBAAC,cAAW,OAAM,qBAAoB,aAAY,uCAAsC;AACtH,SAAO,iCACJ;AAAA,eAAW,qBAAC,YAAO,MAAK,UAAS,SAAS,UAAU;AAAA;AAAA,MAAS,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC;AAAA,MAAE;AAAA,OAAoB;AAAA,IAC/G;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QAAgB;AAAA,QAAY;AAAA;AAAA,MADL,GAAG,UAAU,SAAS,QAAQ,QAAQ,IAAI,UAAU,SAAS,QAAQ,UAAU;AAAA,IAC5C;AAAA,KAC9D;AACF;AAEA,SAAS,mBAAmB;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,QAAM,EAAE,GAAAA,GAAE,IAAI,eAAe;AAC7B,QAAM,SAAS,QAAQ,MAAM,2BAA2B,MAAM,GAAG,CAAC,MAAM,CAAC;AACzE,QAAM,YAAYC;AAAA,IAChB,OAAO;AAAA,IACP,MAAM,OAAO,YAAY;AAAA,IACzB,MAAM,OAAO,YAAY;AAAA,EAC3B;AACA,QAAM,mBAAmB,WAAW,gBAAgB,SAAS,YAAY;AACzE,QAAM,gBAAgB,WAAW,SAAS,OAAO,QAAQ,WAAW,SAAS,QAAQ,YAAY;AACjG,QAAM,WAAWC;AAAA,IACf,CAAC,QAAuB,eAAe,GAAG,IAAIF,GAAE,qBAAqB,IAAI,IAAI;AAAA,IAC7E,CAACA,EAAC;AAAA,EACJ;AACA,QAAM,eAAeE;AAAA,IACnB,CAAC,QAAsB;AACrB,UAAI,IAAI,SAAS,SAAU,QAAOF,GAAE,wBAAwB;AAC5D,UAAI,IAAI,SAAS;AACf,cAAM,MAAM,mBAAmB,IAAI,OAAO;AAC1C,cAAM,QAAQA,GAAE,GAAG;AACnB,eAAO,UAAU,MAAMA,GAAE,wBAAwB,IAAI;AAAA,MACvD;AACA,aAAO;AAAA,IACT;AAAA,IACA,CAACA,EAAC;AAAA,EACJ;AACA,QAAM,qBAAqBE,aAAY,CAAC,OAAe;AACrD,UAAM,MAAM,mBAAmB,EAAE;AACjC,UAAM,QAAQF,GAAE,GAAG;AACnB,WAAO,UAAU,MAAM,KAAK;AAAA,EAC9B,GAAG,CAACA,EAAC,CAAC;AACN,QAAM,wBAAwB;AAAA,IAC5B,MAAM,cAAc,IAAI,CAAC,YAAY;AAAA,MACnC,GAAG;AAAA,MACH,OAAO,OAAO,SAAS,mBAAmB,OAAO,EAAE;AAAA,IACrD,EAAE;AAAA,IACF,CAAC,oBAAoB,aAAa;AAAA,EACpC;AACA,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,oBAAI,IAAY,CAAC;AACxD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,MAAM,IAAI;AAAA,IACjD,KAAK,OAAO,CAAC,QAAQ,IAAI,YAAY,eAAe,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;AAAA,EAC/E,CAAC;AACD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,EAAE,MAAM,MAAM,IAAI,MAAM,CAAC;AAChE,QAAM,CAAC,YAAY,aAAa,IAAI,SAAuC,IAAI;AAC/E,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAA4B,IAAI;AAChF,QAAM,kBAAkB,OAA0B,IAAI;AACtD,QAAM,oBAAoB,OAA0B,IAAI;AACxD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAoB,IAAI;AAC9D,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,oBAAI,IAAY,CAAC;AAC1D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAwB,IAAI;AAExD,YAAU,MAAM;AACd,gBAAY,CAAC,YAAY;AACvB,UAAI,QAAQ,IAAI,yBAAyB,EAAG,QAAO;AACnD,YAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,WAAK,IAAI,yBAAyB;AAClC,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,aAAa,CAAC;AAElB,YAAU,MAAM;AACd,QAAI,oBAAoB,KAAK,KAAK,CAAC,QAAQ,IAAI,OAAO,gBAAgB,GAAG;AACvE,kBAAY,oBAAI,IAAI,CAAC,gBAAgB,CAAC,CAAC;AACvC,gBAAU,gBAAgB;AAAA,IAC5B,WAAW,CAAC,kBAAkB;AAC5B,kBAAY,oBAAI,IAAI,CAAC;AACrB,gBAAU,IAAI;AAAA,IAChB;AAAA,EACF,GAAG,CAAC,kBAAkB,IAAI,CAAC;AAE3B,YAAU,MAAM;AACd,UAAM,UAAU,IAAI,IAAI,sBAAsB,IAAI,CAAC,WAAW,OAAO,EAAE,CAAC;AACxE,eAAW,CAAC,YAAY;AACtB,UAAI,QAAQ,SAAS,EAAG,QAAO;AAC/B,YAAM,OAAO,IAAI,IAAI,CAAC,GAAG,OAAO,EAAE,OAAO,CAAC,OAAO,QAAQ,IAAI,EAAE,CAAC,CAAC;AACjE,aAAO,KAAK,SAAS,QAAQ,OAAO,UAAU;AAAA,IAChD,CAAC;AAAA,EACH,GAAG,CAAC,qBAAqB,CAAC;AAE1B,QAAM,wBAAwB,CAAC,QAAsB;AACnD,QAAI,IAAI,SAAS,SAAU;AAC3B,UAAM,SAAS,WAAW,SAAS;AACnC,QAAI,CAAC,QAAQ,SAAU;AACvB,SAAK,OAAO,kBAAkB,IAAI,IAAI;AAAA,MACpC,OAAO,IAAI;AAAA,MACX,OAAO;AAAA,MACP,UAAU,OAAO;AAAA,MACjB,kBAAkB,OAAO;AAAA,IAC3B,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACnB;AAEA,QAAM,sBAAsB,MAAM;AAChC,gBAAY,oBAAI,IAAI,CAAC;AACrB,cAAU,IAAI;AACd,UAAM,SAAS,WAAW,SAAS;AACnC,QAAI,CAAC,QAAQ,SAAU;AACvB,SAAK,OAAO,oBAAoB;AAAA,MAC9B,OAAO;AAAA,MACP,UAAU,OAAO;AAAA,MACjB,kBAAkB,OAAO;AAAA,IAC3B,CAAC,EAAE,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACnB;AAEA,QAAM,cAAc,QAAQ,MAAM;AAChC,UAAM,OAAO,MAAM,KAAK,EAAE,YAAY;AACtC,UAAM,YAAY,KAAK,SAAS,KAAK,QAAQ,OAAO;AACpD,QAAI,WAAW;AACb,aAAO,KAAK,OAAO,CAAC,QAAQ;AAC1B,cAAM,QAAQ,kBAAkB,GAAG;AACnC,cAAM,WAAW,aAAa,GAAG,EAAE,YAAY;AAC/C,cAAM,gBAAgB,MAAM,KAAK,GAAG,EAAE,YAAY;AAClD,cAAM,YAAY,CAAC,QACd,SAAS,GAAG,EAAE,YAAY,EAAE,SAAS,IAAI,KACzC,SAAS,SAAS,IAAI,KACtB,cAAc,SAAS,IAAI;AAChC,cAAM,YAAY,8BAA8B,OAAO,OAAO;AAC9D,eAAO,CAAC,eAAe,GAAG,KAAK,aAAa;AAAA,MAC9C,CAAC,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,KAAK,OAAO,EAAE,EAAE;AAAA,IACxC;AACA,UAAM,kBAA4B,CAAC;AACnC,WAAO,KAAK,OAAO,CAAC,QAAQ;AAC1B,aAAO,gBAAgB,UAAU,gBAAgB,GAAG,EAAE,KAAM,IAAI,MAAO,iBAAgB,IAAI;AAC3F,YAAM,iBAAiB,gBAAgB,SAAS;AAChD,UAAI,IAAI,eAAe,CAAC,SAAS,IAAI,IAAI,EAAE,EAAG,iBAAgB,KAAK,IAAI,KAAK;AAC5E,aAAO,CAAC;AAAA,IACV,CAAC;AAAA,EACH,GAAG,CAAC,UAAU,SAAS,OAAO,UAAU,MAAM,YAAY,CAAC;AAE3D,QAAM,YAAY,CAAC,KAAmB,UAAsB;AAC1D,QAAI,IAAI,SAAS,UAAU;AACzB,kBAAY,CAAC,YAAY;AACvB,cAAMG,QAAO,IAAI,IAAI,OAAO;AAC5B,YAAIA,MAAK,IAAI,IAAI,EAAE,EAAG,CAAAA,MAAK,OAAO,IAAI,EAAE;AAAA,YAAQ,CAAAA,MAAK,IAAI,IAAI,EAAE;AAC/D,eAAOA;AAAA,MACT,CAAC;AACD;AAAA,IACF;AACA,UAAM,UAAU,YAAY,OAAO,CAAC,UAAU,MAAM,SAAS,QAAQ,EAAE,IAAI,CAAC,UAAU,MAAM,EAAE;AAC9F,QAAI;AACJ,QAAI,MAAM,YAAY,QAAQ;AAC5B,YAAM,OAAO,QAAQ,QAAQ,MAAM;AACnC,YAAM,KAAK,QAAQ,QAAQ,IAAI,EAAE;AACjC,aAAO,OAAO,KAAK,KAAK,IACpB,oBAAI,IAAI,CAAC,IAAI,EAAE,CAAC,IAChB,IAAI,IAAI,QAAQ,MAAM,KAAK,IAAI,MAAM,EAAE,GAAG,KAAK,IAAI,MAAM,EAAE,IAAI,CAAC,CAAC;AAAA,IACvE,WAAW,MAAM,WAAW,MAAM,SAAS;AACzC,aAAO,IAAI,IAAI,QAAQ;AACvB,UAAI,KAAK,IAAI,IAAI,EAAE,EAAG,MAAK,OAAO,IAAI,EAAE;AAAA,UAAQ,MAAK,IAAI,IAAI,EAAE;AAAA,IACjE,OAAO;AACL,aAAO,oBAAI,IAAI,CAAC,IAAI,EAAE,CAAC;AAAA,IACzB;AACA,QAAI,KAAK,SAAS,GAAG;AACnB,0BAAoB;AACpB;AAAA,IACF;AACA,UAAM,UAAU,KAAK,IAAI,IAAI,EAAE,IAC3B,MACA,KAAK,KAAK,CAAC,UAAU,MAAM,SAAS,YAAY,KAAK,IAAI,MAAM,EAAE,CAAC;AACtE,QAAI,CAAC,SAAS;AACZ,0BAAoB;AACpB;AAAA,IACF;AACA,gBAAY,IAAI;AAChB,cAAU,QAAQ,EAAE;AACpB,0BAAsB,OAAO;AAAA,EAC/B;AACA,QAAM,cAAc,CAAC,OAAmB,UAAsB;AAC5D,UAAM,eAAe;AACrB,UAAM,gBAAgB;AACtB,kBAAc,IAAI;AAClB,mBAAe,EAAE,GAAG,MAAM,SAAS,GAAG,MAAM,SAAS,MAAM,CAAC;AAAA,EAC9D;AACA,QAAM,YAAYD,aAAY,MAAkB;AAAA,IAC9C,EAAE,MAAM,SAAS,OAAOF,GAAE,yBAAyB,EAAE;AAAA,IACrD,EAAE,MAAM,QAAQ,IAAI,gBAAgB,OAAOA,GAAE,sCAAsC,GAAG,MAAM,oBAAC,KAAE,MAAM,IAAI,GAAI,UAAU,CAAC,SAAS,QAAQ,SAAS,GAAG,QAAQ,MAAM;AAAE,eAAS,EAAE;AAAG,iBAAW,oBAAI,IAAI,CAAC;AAAA,IAAG,EAAE;AAAA,IAC5M,EAAE,MAAM,QAAQ,IAAI,SAAS,OAAOA,GAAE,+BAA+B,GAAG,MAAM,oBAAC,aAAU,MAAM,IAAI,GAAI,UAAU,KAAK,UAAU,SAAS,SAAS,GAAG,QAAQ,MAAM;AAAA,IAAC,EAAE;AAAA,EACxK,GAAG,CAAC,QAAQ,MAAM,OAAO,SAAS,MAAMA,EAAC,CAAC;AAC1C,QAAM,UAAUE,aAAY,CAAC,QAAkC;AAAA,IAC7D,EAAE,MAAM,SAAS,OAAO,SAAS,GAAG,GAAG,MAAM,oBAAC,WAAQ,KAAU,EAAG;AAAA,IACnE,EAAE,MAAM,QAAQ,IAAI,aAAa,OAAOF,GAAE,yBAAyB,GAAG,MAAM,oBAAC,UAAO,MAAM,IAAI,GAAI,QAAQ,MAAM,KAAK,UAAU,WAAW,UAAU,KAAK,UAAU,KAAK,MAAM,CAAC,CAAC,EAAE;AAAA,IAClL,EAAE,MAAM,QAAQ,IAAI,SAAS,OAAOA,GAAE,gCAAgC,GAAG,MAAM,oBAAC,aAAU,MAAM,IAAI,GAAI,UAAU,KAAK,UAAU,CAAC,WAAW,WAAW,eAAe,GAAG,GAAG,QAAQ,MAAM;AAAE,YAAM,SAAS,WAAW,SAAS;AAAQ,UAAI,OAAQ,MAAK,QAAQ,KAAK,gBAAgB,EAAE,UAAU,IAAI,IAAI,UAAU,OAAO,UAAU,kBAAkB,OAAO,WAAW,CAAC;AAAA,IAAG,EAAE;AAAA,EACjX,GAAG,CAAC,UAAUA,IAAG,QAAQ,WAAW,OAAO,CAAC;AAC5C,YAAU,MAAM;AACd,QAAI,CAAC,WAAY,qBAAoB,IAAI;AAAA,EAC3C,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,iBAAiB,CAAC,SAAgC;AACtD,QAAI,eAAe,MAAM;AACvB,oBAAc,IAAI;AAClB;AAAA,IACF;AACA,UAAM,MAAM,SAAS,WAAW,kBAAkB;AAClD,UAAM,OAAO,IAAI,SAAS,sBAAsB;AAChD,QAAI,KAAM,qBAAoB,IAAI;AAClC,kBAAc,IAAI;AAAA,EACpB;AAEA,QAAM,mBAAmB,CAAC,aAAqB;AAC7C,eAAW,CAAC,YAAY;AACtB,YAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,UAAI,KAAK,IAAI,QAAQ,EAAG,MAAK,OAAO,QAAQ;AAAA,UACvC,MAAK,IAAI,QAAQ;AACtB,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,eAAY;AAAA,MACZ,sBAAmB;AAAA,MACnB,MAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW,CAAC,UAAU;AACpB,aAAK,MAAM,WAAW,MAAM,YAAY,MAAM,IAAI,YAAY,MAAM,KAAK;AACvE,gBAAM,eAAe;AACrB,sBAAY,IAAI,IAAI,KAAK,OAAO,CAAC,QAAQ,IAAI,SAAS,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AAAA,QACvF;AAAA,MACF;AAAA,MAEA;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,eAAY;AAAA,YACZ,OACE,oBAAC,WACC;AAAA,cAAC;AAAA;AAAA,gBACC,KAAK;AAAA,gBACL,WAAW,QAAQ,OAAO,WAAW;AAAA,gBACrC,OAAOA,GAAE,wBAAwB;AAAA,gBACjC,MAAM,oBAAC,UAAO,MAAM,IAAI;AAAA,gBACxB,MAAK;AAAA,gBACL,SAAS,MAAM,eAAe,QAAQ;AAAA;AAAA,YACxC,GACF;AAAA,YAEF,QACE;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,eAAY;AAAA,gBACZ,eAAa,mBAAmB;AAAA,gBAChC,OAAO;AAAA,gBACP,UAAU,CAAC,UAAU,SAAS,MAAM,OAAO,KAAK;AAAA,gBAChD,SAAS,MAAM,SAAS,EAAE;AAAA,gBAC1B,aAAaA,GAAE,6BAA6B;AAAA,gBAC5C,OAAOA,GAAE,uBAAuB;AAAA;AAAA,YAClC;AAAA,YAEF,KACE,oBAAC,WACC;AAAA,cAAC;AAAA;AAAA,gBACC,KAAK;AAAA,gBACL,OAAOA,GAAE,2BAA2B;AAAA,gBACpC,MAAM,oBAAC,YAAS,MAAM,IAAI;AAAA,gBAC1B,MAAK;AAAA,gBACL,SAAS,MAAM,eAAe,UAAU;AAAA;AAAA,YAC1C,GACF;AAAA;AAAA,QAEJ;AAAA,QACA,qBAAC,SAAI,WAAU,cAAa,eAAY,gBACtC;AAAA,8BAAC,UAAK,WAAU,YAAW,eAAW,MAAC;AAAA,UACvC,oBAAC,UAAK,WAAU,oBAAoB,UAAAA,GAAE,sBAAsB,GAAE;AAAA,UAC7D,QAAQ,OAAO,oBAAC,UAAK,WAAU,6BAA6B,UAAAA,GAAE,sBAAsB,GAAE,IAAU;AAAA,UAChG,QAAQ,KAAK,oBAAC,UAAK,WAAU,yBAAyB,UAAAA,GAAE,oBAAoB,GAAE,IAAU;AAAA,WAC3F;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,eAAY;AAAA,YACZ,SAAS,CAAC,UAAU;AAClB,kBAAI,MAAM,WAAW,MAAM,cAAe,qBAAoB;AAAA,YAChE;AAAA,YACA,eAAe,CAAC,UAAU;AACxB,kBAAI,CAAE,MAAM,OAAuB,QAAQ,KAAK,EAAG,aAAY,OAAO,UAAU,CAAC;AAAA,YACnF;AAAA,YAEC,sBAAY,WAAW,IACtB;AAAA,cAAC;AAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAOA,GAAE,wBAAwB;AAAA,gBACjC,aAAaA,GAAE,8BAA8B;AAAA;AAAA,YAC/C,IACE,YAAY,IAAI,CAAC,QAAQ;AAC3B,oBAAM,aAAa,SAAS,IAAI,IAAI,EAAE;AACtC,oBAAM,WAAW,IAAI,WAAW;AAChC,oBAAM,aAAa,SAAS,IAAI,IAAI,EAAE;AACtC,qBACE;AAAA,gBAAC;AAAA;AAAA,kBAEC,WAAW,QAAQ,QAAQ,GAAG,CAAC,GAAG,aAAa,SAAS,EAAE,GAAG,WAAW,SAAS,EAAE;AAAA,kBACnF,eAAa,eAAe,GAAG,IAAI,0BAA0B,YAAY,IAAI,EAAE;AAAA,kBAC/E,eAAa,mBAAmB;AAAA,kBAChC,OAAO,EAAE,aAAa,gCAAgC,IAAI,KAAK,oFAAoF;AAAA,kBACnJ,MAAK;AAAA,kBACL,iBAAe;AAAA,kBACf,UAAU,aAAa,IAAI;AAAA,kBAC3B,SAAS,CAAC,UAAU,UAAU,KAAK,KAAK;AAAA,kBACxC,eAAe,CAAC,UAAU;AACxB,wBAAI,CAAC,SAAS,IAAI,IAAI,EAAE,GAAG;AACzB,kCAAY,oBAAI,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAC7B,0BAAI,IAAI,SAAS,SAAU,uBAAsB,GAAG;AAAA,oBACtD;AACA,gCAAY,OAAO,eAAe,GAAG,IAAI,UAAU,IAAI,QAAQ,GAAG,CAAC;AAAA,kBACrE;AAAA,kBAEA;AAAA;AAAA,sBAAC;AAAA;AAAA,wBACC,MAAK;AAAA,wBACL,WAAU;AAAA,wBACV,eAAa,mBAAmB;AAAA,wBAChC,UAAU,CAAC,IAAI;AAAA,wBACf,UAAU;AAAA,wBACV,SAAS,CAAC,UAAU;AAClB,gCAAM,gBAAgB;AACtB,8BAAI,CAAC,IAAI,YAAa;AACtB,sCAAY,CAAC,YAAY;AACvB,kCAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,gCAAI,KAAK,IAAI,IAAI,EAAE,EAAG,MAAK,OAAO,IAAI,EAAE;AAAA,gCACnC,MAAK,IAAI,IAAI,EAAE;AACpB,mCAAO;AAAA,0BACT,CAAC;AAAA,wBACH;AAAA,wBAEC,cAAI,cAAe,aAAa,oBAAC,eAAY,MAAM,IAAI,IAAK,oBAAC,gBAAa,MAAM,IAAI,IAAM;AAAA;AAAA,oBAC7F;AAAA,oBACA,oBAAC,UAAK,WAAU,OAAM,8BAAC,WAAQ,KAAU,GAAE;AAAA,oBAC3C,oBAAC,UAAK,WAAU,aACd,8BAAC,UAAK,WAAU,MAAM,sBAAY,SAAS,GAAG,GAAG,KAAK,GAAE,GAC1D;AAAA,oBACC,QAAQ,OAAO,oBAAC,UAAK,WAAU,sBAAqB,8BAAC,UAAK,WAAU,QAAQ,uBAAa,GAAG,GAAE,GAAO,IAAU;AAAA,oBAC/G,QAAQ,KAAK,oBAAC,UAAK,WAAU,kBAAkB,yBAAe,GAAG,IAAI,KAAK,IAAI,IAAI,EAAE,IAAG,IAAU;AAAA;AAAA;AAAA,gBAzC7F,IAAI;AAAA,cA0CX;AAAA,YAEJ,CAAC;AAAA;AAAA,QACH;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,QAAQ,oBAAoB,eAAe,QAAQ;AAAA,YACzD,YAAY;AAAA,YACZ,SAAS,MAAM,cAAc,IAAI;AAAA,YACjC,qBAAqB,CAAC,eAAe;AAAA,YACrC,WAAU;AAAA,YACV,gBAAgB,EAAE,eAAe,CAAC,UAAU,MAAM,gBAAgB,EAAE;AAAA,YAEpE,+BAAC,SAAI,WAAU,yBACb;AAAA,kCAAC,SAAI,WAAU,uBAAuB,UAAAA,GAAE,wBAAwB,GAAE;AAAA,cACjE,sBAAsB,IAAI,CAAC,WAAW;AACrC,sBAAM,SAAS,QAAQ,IAAI,OAAO,EAAE;AACpC,uBACE;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,WAAU;AAAA,oBACV,eAAa,SAAS,SAAS;AAAA,oBAE/B,SAAS,MAAM,iBAAiB,OAAO,EAAE;AAAA,oBAEzC;AAAA;AAAA,wBAAC;AAAA;AAAA,0BACC,SAAS;AAAA,0BACT,UAAU,MAAM,iBAAiB,OAAO,EAAE;AAAA,0BAC1C,UAAU;AAAA,0BACV,WAAS;AAAA,0BACT,OAAO,OAAO;AAAA,0BACd,WAAU;AAAA;AAAA,sBACZ;AAAA,sBACA,oBAAC,UAAK,WAAU,2BAA0B,eAAW,MAAE,2BAAiB,OAAO,EAAE,GAAE;AAAA,sBAClF,OAAO;AAAA;AAAA;AAAA,kBAZH,OAAO;AAAA,gBAad;AAAA,cAEJ,CAAC;AAAA,cACD,oBAAC,SAAI,WAAU,yBAAwB;AAAA,cACvC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAU;AAAA,kBACV,UAAU,QAAQ,SAAS;AAAA,kBAC3B,SAAS,MAAM,WAAW,oBAAI,IAAI,CAAC;AAAA,kBAElC,UAAAA,GAAE,wBAAwB;AAAA;AAAA,cAC7B;AAAA,eACF;AAAA;AAAA,QACF;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,MAAM,QAAQ,oBAAoB,eAAe,UAAU;AAAA,YAC3D,YAAY;AAAA,YACZ,SAAS,MAAM,cAAc,IAAI;AAAA,YACjC,qBAAqB,CAAC,iBAAiB;AAAA,YACvC,WAAU;AAAA,YACV,gBAAgB,EAAE,eAAe,CAAC,UAAU,MAAM,gBAAgB,EAAE;AAAA,YAEpE,+BAAC,SAAI,WAAU,wDACb;AAAA,kCAAC,SAAI,WAAU,uBAAuB,UAAAA,GAAE,mBAAmB,GAAE;AAAA,cAC3D,CAAC,QAAQ,IAAI,EAAY,IAAI,CAAC,WAAW;AACzC,sBAAM,QAAQ,WAAW,SACrBA,GAAE,sBAAsB,IACxBA,GAAE,oBAAoB;AAC1B,sBAAM,UAAU,QAAQ,MAAM;AAC9B,sBAAM,SAAS,MAAM,WAAW,CAAC,aAAa,EAAE,GAAG,SAAS,CAAC,MAAM,GAAG,CAAC,QAAQ,MAAM,EAAE,EAAE;AACzF,uBACE;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,WAAU;AAAA,oBACV,eAAa,mBAAmB;AAAA,oBAChC,eAAa,UAAU,SAAS;AAAA,oBAEhC,SAAS;AAAA,oBAET;AAAA;AAAA,wBAAC;AAAA;AAAA,0BACC;AAAA,0BACA,UAAU;AAAA,0BACV,UAAU;AAAA,0BACV,WAAS;AAAA,0BACT;AAAA,0BACA,WAAU;AAAA;AAAA,sBACZ;AAAA,sBACC;AAAA;AAAA;AAAA,kBAXI;AAAA,gBAYP;AAAA,cAEJ,CAAC;AAAA,cACD,oBAAC,SAAI,WAAU,yBAAwB;AAAA,cACvC;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAU;AAAA,kBACV,eAAa,mBAAmB;AAAA,kBAChC,SAAS,MAAM,YAAY,IAAI,IAAI,KAAK,OAAO,CAAC,QAAQ,IAAI,WAAW,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AAAA,kBAE9F;AAAA,wCAAC,aAAU,MAAM,IAAI,WAAU,2BAA0B;AAAA,oBACxDA,GAAE,qBAAqB;AAAA;AAAA;AAAA,cAC1B;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAU;AAAA,kBACV,eAAa,mBAAmB;AAAA,kBAChC,SAAS,MAAM,YAAY,IAAI,IAAI,KAAK,OAAO,cAAc,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;AAAA,kBAEpF;AAAA,wCAAC,aAAU,MAAM,IAAI,WAAU,2BAA0B;AAAA,oBACxDA,GAAE,uBAAuB;AAAA;AAAA;AAAA,cAC5B;AAAA,eACF;AAAA;AAAA,QACF;AAAA,QACC,cAAc,oBAAC,wBAAqB,OAAO,aAAa,OAAO,MAAM,eAAe,IAAI,GAAG,IAAK;AAAA;AAAA;AAAA,EACnG;AAEJ;;;AI7vBU,IAAM,MAAM;AACZ,IAAI,OAAO,aAAa,eAAe,CAAC,SAAS,cAAc,4FAA4F,GAAG;AAC5J,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,QAAQ,aAAa;AAC3B,QAAM,cAAc;AACpB,WAAS,KAAK,OAAO,KAAK;AAC5B;;;ALMJ,gBAAAI,YAAA;AALN,eAAsB,oBAAoB,OAAyG;AACjJ,MAAI,CAAC,MAAM,aAAc,OAAM,IAAI,UAAU,2CAA2C;AACxF,QAAM,OAAO,WAAW,MAAM,YAAY;AAC1C,OAAK;AAAA,IACH,gBAAAA,KAAC,uBAAoB,MAAM,MAAM,eAAe,MAAM,cACpD,0BAAAA,KAAC,kBAAe,QAAQ,MAAM,QAAQ,GACxC;AAAA,EACF;AACA,SAAO,YAAY,KAAK,QAAQ;AAClC;",
6
6
  "names": ["useCallback", "useSyncExternalStore", "t", "current", "t", "useSyncExternalStore", "useCallback", "next", "jsx"]
7
7
  }
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  FRONTEND_PLUGIN_ID,
3
3
  identity_exports
4
- } from "./chunk-M66NDY35.mjs";
4
+ } from "./chunk-C2AMOM7H.mjs";
5
5
  import {
6
6
  applyResourcePagePlugin
7
- } from "./chunk-WC6NGMGI.mjs";
7
+ } from "./chunk-KPLESRQY.mjs";
8
8
 
9
9
  // packages/view-plugin-mesh/src/frontend.ts
10
10
  var VIEW_MESH_FRONTEND_PLUGIN_ID = FRONTEND_PLUGIN_ID;
@@ -22,4 +22,4 @@ export {
22
22
  viewMeshFrontendPlugin,
23
23
  frontend_default
24
24
  };
25
- //# sourceMappingURL=chunk-CVIF6DYH.mjs.map
25
+ //# sourceMappingURL=chunk-7MWZK7HS.mjs.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  mountRunObserver
3
- } from "./chunk-PHCUCHVL.mjs";
3
+ } from "./chunk-LBQ6DFMP.mjs";
4
4
  import {
5
5
  DISPLAY_SURFACE_ID,
6
6
  DISPLAY_TARGET_ROLE,
@@ -9,7 +9,7 @@ import {
9
9
  PAGE_TYPE,
10
10
  VIEW_STATUS_SERVICE,
11
11
  VIEW_STATUS_TOPIC
12
- } from "./chunk-SKZC6VTV.mjs";
12
+ } from "./chunk-D2LZIQE2.mjs";
13
13
 
14
14
  // packages/view-plugin-display/src/status.ts
15
15
  var ViewDisplayStatus = class {
@@ -146,4 +146,4 @@ export {
146
146
  ViewDisplayStatus,
147
147
  frontend_default
148
148
  };
149
- //# sourceMappingURL=chunk-7YWMB7HV.mjs.map
149
+ //# sourceMappingURL=chunk-A7OGXJAV.mjs.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VIEW_PAGE_TYPES
3
- } from "./chunk-QYJZ3SOV.mjs";
3
+ } from "./chunk-QJHQN6OD.mjs";
4
4
  import {
5
5
  __export
6
6
  } from "./chunk-FLGC65SR.mjs";
@@ -39,4 +39,4 @@ export {
39
39
  TITLE_I18N_KEY,
40
40
  identity_exports
41
41
  };
42
- //# sourceMappingURL=chunk-KOBAWLZL.mjs.map
42
+ //# sourceMappingURL=chunk-AUINYWZP.mjs.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  RESOURCE_PREVIEW_LAYOUT,
3
3
  RESOURCE_PROPERTIES_LAYOUT
4
- } from "./chunk-WC6NGMGI.mjs";
4
+ } from "./chunk-KPLESRQY.mjs";
5
5
  import {
6
6
  VIEW_PAGE_TYPES
7
- } from "./chunk-QYJZ3SOV.mjs";
7
+ } from "./chunk-QJHQN6OD.mjs";
8
8
  import {
9
9
  __export
10
10
  } from "./chunk-FLGC65SR.mjs";
@@ -83,4 +83,4 @@ export {
83
83
  TITLE_I18N_KEY,
84
84
  identity_exports
85
85
  };
86
- //# sourceMappingURL=chunk-R6MT6F3T.mjs.map
86
+ //# sourceMappingURL=chunk-B24VYGHV.mjs.map