@ifc-lite/viewer 1.17.3 → 1.17.4

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 (495) hide show
  1. package/.turbo/turbo-build.log +39 -30
  2. package/.turbo/turbo-typecheck.log +1 -1
  3. package/CHANGELOG.md +15 -0
  4. package/DESKTOP_CONTRACT_VERSION +1 -0
  5. package/dist/assets/arrow-CZ5kQ26f.js +20 -0
  6. package/dist/assets/basketViewActivator-BmnNtVfZ.js +1 -0
  7. package/dist/assets/{bcf-D5-QWGO9.js → bcf-DOG9_WPX.js} +1 -1
  8. package/dist/assets/{browser-CKs-FY1P.js → browser-C5TFR7sH.js} +1 -1
  9. package/dist/assets/cesium-ADbP7waU.css +1 -0
  10. package/dist/assets/cesium-DUOzBlqv.js +17817 -0
  11. package/dist/assets/{exporters-C_6J153K.js → exporters-ChAtBmlj.js} +2225 -1754
  12. package/dist/assets/geometry.worker-BQ0rzNo-.js +1 -0
  13. package/dist/assets/ifc-lite_bg-BX4E7TX8.wasm +0 -0
  14. package/dist/assets/{index-jhBr1wbn.js → index-Co8E2-FE.js} +28959 -24612
  15. package/dist/assets/index-DckuDqlv.css +1 -0
  16. package/dist/assets/{maplibre-gl-BpvwNKKy.js → maplibre-gl-CGLcoNXc.js} +1 -1
  17. package/dist/assets/native-bridge-BRvbckFQ.js +429 -0
  18. package/dist/assets/{sandbox-B79eavQ3.js → sandbox-DZiNLNMk.js} +5 -5
  19. package/dist/assets/{server-client-D3bUPJJc.js → server-client-BV8zHZ7Y.js} +4 -4
  20. package/dist/assets/tauri-core-stub-D8Fa-u43.js +1 -0
  21. package/dist/assets/tauri-dialog-stub-r7Wksg7o.js +1 -0
  22. package/dist/assets/tauri-fs-stub-BdeRC7aK.js +1 -0
  23. package/dist/assets/wasm-bridge-g01g7T9b.js +1 -0
  24. package/dist/assets/{zip-B-jFFAGa.js → zip-DBEtpeu6.js} +3 -3
  25. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_0.json +1 -0
  26. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_1.json +1 -0
  27. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_10.json +1 -0
  28. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_11.json +1 -0
  29. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_12.json +1 -0
  30. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_13.json +1 -0
  31. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_14.json +1 -0
  32. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_15.json +1 -0
  33. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_16.json +1 -0
  34. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_17.json +1 -0
  35. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_18.json +1 -0
  36. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_19.json +1 -0
  37. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_2.json +1 -0
  38. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_20.json +1 -0
  39. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_21.json +1 -0
  40. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_22.json +1 -0
  41. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_23.json +1 -0
  42. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_24.json +1 -0
  43. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_25.json +1 -0
  44. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_26.json +1 -0
  45. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_27.json +1 -0
  46. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_3.json +1 -0
  47. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_4.json +1 -0
  48. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_5.json +1 -0
  49. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_6.json +1 -0
  50. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_7.json +1 -0
  51. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_8.json +1 -0
  52. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_9.json +1 -0
  53. package/dist/cesium/Assets/Images/bing_maps_credit.png +0 -0
  54. package/dist/cesium/Assets/Images/cesium_credit.png +0 -0
  55. package/dist/cesium/Assets/Images/google_earth_credit.png +0 -0
  56. package/dist/cesium/Assets/Images/ion-credit.png +0 -0
  57. package/dist/cesium/Assets/Textures/LensFlare/DirtMask.jpg +0 -0
  58. package/dist/cesium/Assets/Textures/LensFlare/StarBurst.jpg +0 -0
  59. package/dist/cesium/Assets/Textures/NaturalEarthII/0/0/0.jpg +0 -0
  60. package/dist/cesium/Assets/Textures/NaturalEarthII/0/1/0.jpg +0 -0
  61. package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/0.jpg +0 -0
  62. package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/1.jpg +0 -0
  63. package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/0.jpg +0 -0
  64. package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/1.jpg +0 -0
  65. package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/0.jpg +0 -0
  66. package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/1.jpg +0 -0
  67. package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/0.jpg +0 -0
  68. package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/1.jpg +0 -0
  69. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/0.jpg +0 -0
  70. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/1.jpg +0 -0
  71. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/2.jpg +0 -0
  72. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/3.jpg +0 -0
  73. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/0.jpg +0 -0
  74. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/1.jpg +0 -0
  75. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/2.jpg +0 -0
  76. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/3.jpg +0 -0
  77. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/0.jpg +0 -0
  78. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/1.jpg +0 -0
  79. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/2.jpg +0 -0
  80. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/3.jpg +0 -0
  81. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/0.jpg +0 -0
  82. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/1.jpg +0 -0
  83. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/2.jpg +0 -0
  84. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/3.jpg +0 -0
  85. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/0.jpg +0 -0
  86. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/1.jpg +0 -0
  87. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/2.jpg +0 -0
  88. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/3.jpg +0 -0
  89. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/0.jpg +0 -0
  90. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/1.jpg +0 -0
  91. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/2.jpg +0 -0
  92. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/3.jpg +0 -0
  93. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/0.jpg +0 -0
  94. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/1.jpg +0 -0
  95. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/2.jpg +0 -0
  96. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/3.jpg +0 -0
  97. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/0.jpg +0 -0
  98. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/1.jpg +0 -0
  99. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/2.jpg +0 -0
  100. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/3.jpg +0 -0
  101. package/dist/cesium/Assets/Textures/NaturalEarthII/tilemapresource.xml +14 -0
  102. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mx.jpg +0 -0
  103. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_my.jpg +0 -0
  104. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mz.jpg +0 -0
  105. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_px.jpg +0 -0
  106. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_py.jpg +0 -0
  107. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_pz.jpg +0 -0
  108. package/dist/cesium/Assets/Textures/maki/airfield.png +0 -0
  109. package/dist/cesium/Assets/Textures/maki/airport.png +0 -0
  110. package/dist/cesium/Assets/Textures/maki/alcohol-shop.png +0 -0
  111. package/dist/cesium/Assets/Textures/maki/america-football.png +0 -0
  112. package/dist/cesium/Assets/Textures/maki/art-gallery.png +0 -0
  113. package/dist/cesium/Assets/Textures/maki/bakery.png +0 -0
  114. package/dist/cesium/Assets/Textures/maki/bank.png +0 -0
  115. package/dist/cesium/Assets/Textures/maki/bar.png +0 -0
  116. package/dist/cesium/Assets/Textures/maki/baseball.png +0 -0
  117. package/dist/cesium/Assets/Textures/maki/basketball.png +0 -0
  118. package/dist/cesium/Assets/Textures/maki/beer.png +0 -0
  119. package/dist/cesium/Assets/Textures/maki/bicycle.png +0 -0
  120. package/dist/cesium/Assets/Textures/maki/building.png +0 -0
  121. package/dist/cesium/Assets/Textures/maki/bus.png +0 -0
  122. package/dist/cesium/Assets/Textures/maki/cafe.png +0 -0
  123. package/dist/cesium/Assets/Textures/maki/camera.png +0 -0
  124. package/dist/cesium/Assets/Textures/maki/campsite.png +0 -0
  125. package/dist/cesium/Assets/Textures/maki/car.png +0 -0
  126. package/dist/cesium/Assets/Textures/maki/cemetery.png +0 -0
  127. package/dist/cesium/Assets/Textures/maki/cesium.png +0 -0
  128. package/dist/cesium/Assets/Textures/maki/chemist.png +0 -0
  129. package/dist/cesium/Assets/Textures/maki/cinema.png +0 -0
  130. package/dist/cesium/Assets/Textures/maki/circle-stroked.png +0 -0
  131. package/dist/cesium/Assets/Textures/maki/circle.png +0 -0
  132. package/dist/cesium/Assets/Textures/maki/city.png +0 -0
  133. package/dist/cesium/Assets/Textures/maki/clothing-store.png +0 -0
  134. package/dist/cesium/Assets/Textures/maki/college.png +0 -0
  135. package/dist/cesium/Assets/Textures/maki/commercial.png +0 -0
  136. package/dist/cesium/Assets/Textures/maki/cricket.png +0 -0
  137. package/dist/cesium/Assets/Textures/maki/cross.png +0 -0
  138. package/dist/cesium/Assets/Textures/maki/dam.png +0 -0
  139. package/dist/cesium/Assets/Textures/maki/danger.png +0 -0
  140. package/dist/cesium/Assets/Textures/maki/disability.png +0 -0
  141. package/dist/cesium/Assets/Textures/maki/dog-park.png +0 -0
  142. package/dist/cesium/Assets/Textures/maki/embassy.png +0 -0
  143. package/dist/cesium/Assets/Textures/maki/emergency-telephone.png +0 -0
  144. package/dist/cesium/Assets/Textures/maki/entrance.png +0 -0
  145. package/dist/cesium/Assets/Textures/maki/farm.png +0 -0
  146. package/dist/cesium/Assets/Textures/maki/fast-food.png +0 -0
  147. package/dist/cesium/Assets/Textures/maki/ferry.png +0 -0
  148. package/dist/cesium/Assets/Textures/maki/fire-station.png +0 -0
  149. package/dist/cesium/Assets/Textures/maki/fuel.png +0 -0
  150. package/dist/cesium/Assets/Textures/maki/garden.png +0 -0
  151. package/dist/cesium/Assets/Textures/maki/gift.png +0 -0
  152. package/dist/cesium/Assets/Textures/maki/golf.png +0 -0
  153. package/dist/cesium/Assets/Textures/maki/grocery.png +0 -0
  154. package/dist/cesium/Assets/Textures/maki/hairdresser.png +0 -0
  155. package/dist/cesium/Assets/Textures/maki/harbor.png +0 -0
  156. package/dist/cesium/Assets/Textures/maki/heart.png +0 -0
  157. package/dist/cesium/Assets/Textures/maki/heliport.png +0 -0
  158. package/dist/cesium/Assets/Textures/maki/hospital.png +0 -0
  159. package/dist/cesium/Assets/Textures/maki/ice-cream.png +0 -0
  160. package/dist/cesium/Assets/Textures/maki/industrial.png +0 -0
  161. package/dist/cesium/Assets/Textures/maki/land-use.png +0 -0
  162. package/dist/cesium/Assets/Textures/maki/laundry.png +0 -0
  163. package/dist/cesium/Assets/Textures/maki/library.png +0 -0
  164. package/dist/cesium/Assets/Textures/maki/lighthouse.png +0 -0
  165. package/dist/cesium/Assets/Textures/maki/lodging.png +0 -0
  166. package/dist/cesium/Assets/Textures/maki/logging.png +0 -0
  167. package/dist/cesium/Assets/Textures/maki/london-underground.png +0 -0
  168. package/dist/cesium/Assets/Textures/maki/marker-stroked.png +0 -0
  169. package/dist/cesium/Assets/Textures/maki/marker.png +0 -0
  170. package/dist/cesium/Assets/Textures/maki/minefield.png +0 -0
  171. package/dist/cesium/Assets/Textures/maki/mobilephone.png +0 -0
  172. package/dist/cesium/Assets/Textures/maki/monument.png +0 -0
  173. package/dist/cesium/Assets/Textures/maki/museum.png +0 -0
  174. package/dist/cesium/Assets/Textures/maki/music.png +0 -0
  175. package/dist/cesium/Assets/Textures/maki/oil-well.png +0 -0
  176. package/dist/cesium/Assets/Textures/maki/park.png +0 -0
  177. package/dist/cesium/Assets/Textures/maki/park2.png +0 -0
  178. package/dist/cesium/Assets/Textures/maki/parking-garage.png +0 -0
  179. package/dist/cesium/Assets/Textures/maki/parking.png +0 -0
  180. package/dist/cesium/Assets/Textures/maki/pharmacy.png +0 -0
  181. package/dist/cesium/Assets/Textures/maki/pitch.png +0 -0
  182. package/dist/cesium/Assets/Textures/maki/place-of-worship.png +0 -0
  183. package/dist/cesium/Assets/Textures/maki/playground.png +0 -0
  184. package/dist/cesium/Assets/Textures/maki/police.png +0 -0
  185. package/dist/cesium/Assets/Textures/maki/polling-place.png +0 -0
  186. package/dist/cesium/Assets/Textures/maki/post.png +0 -0
  187. package/dist/cesium/Assets/Textures/maki/prison.png +0 -0
  188. package/dist/cesium/Assets/Textures/maki/rail-above.png +0 -0
  189. package/dist/cesium/Assets/Textures/maki/rail-light.png +0 -0
  190. package/dist/cesium/Assets/Textures/maki/rail-metro.png +0 -0
  191. package/dist/cesium/Assets/Textures/maki/rail-underground.png +0 -0
  192. package/dist/cesium/Assets/Textures/maki/rail.png +0 -0
  193. package/dist/cesium/Assets/Textures/maki/religious-christian.png +0 -0
  194. package/dist/cesium/Assets/Textures/maki/religious-jewish.png +0 -0
  195. package/dist/cesium/Assets/Textures/maki/religious-muslim.png +0 -0
  196. package/dist/cesium/Assets/Textures/maki/restaurant.png +0 -0
  197. package/dist/cesium/Assets/Textures/maki/roadblock.png +0 -0
  198. package/dist/cesium/Assets/Textures/maki/rocket.png +0 -0
  199. package/dist/cesium/Assets/Textures/maki/school.png +0 -0
  200. package/dist/cesium/Assets/Textures/maki/scooter.png +0 -0
  201. package/dist/cesium/Assets/Textures/maki/shop.png +0 -0
  202. package/dist/cesium/Assets/Textures/maki/skiing.png +0 -0
  203. package/dist/cesium/Assets/Textures/maki/slaughterhouse.png +0 -0
  204. package/dist/cesium/Assets/Textures/maki/soccer.png +0 -0
  205. package/dist/cesium/Assets/Textures/maki/square-stroked.png +0 -0
  206. package/dist/cesium/Assets/Textures/maki/square.png +0 -0
  207. package/dist/cesium/Assets/Textures/maki/star-stroked.png +0 -0
  208. package/dist/cesium/Assets/Textures/maki/star.png +0 -0
  209. package/dist/cesium/Assets/Textures/maki/suitcase.png +0 -0
  210. package/dist/cesium/Assets/Textures/maki/swimming.png +0 -0
  211. package/dist/cesium/Assets/Textures/maki/telephone.png +0 -0
  212. package/dist/cesium/Assets/Textures/maki/tennis.png +0 -0
  213. package/dist/cesium/Assets/Textures/maki/theatre.png +0 -0
  214. package/dist/cesium/Assets/Textures/maki/toilets.png +0 -0
  215. package/dist/cesium/Assets/Textures/maki/town-hall.png +0 -0
  216. package/dist/cesium/Assets/Textures/maki/town.png +0 -0
  217. package/dist/cesium/Assets/Textures/maki/triangle-stroked.png +0 -0
  218. package/dist/cesium/Assets/Textures/maki/triangle.png +0 -0
  219. package/dist/cesium/Assets/Textures/maki/village.png +0 -0
  220. package/dist/cesium/Assets/Textures/maki/warehouse.png +0 -0
  221. package/dist/cesium/Assets/Textures/maki/waste-basket.png +0 -0
  222. package/dist/cesium/Assets/Textures/maki/water.png +0 -0
  223. package/dist/cesium/Assets/Textures/maki/wetland.png +0 -0
  224. package/dist/cesium/Assets/Textures/maki/zoo.png +0 -0
  225. package/dist/cesium/Assets/Textures/moonSmall.jpg +0 -0
  226. package/dist/cesium/Assets/Textures/pin.svg +1 -0
  227. package/dist/cesium/Assets/Textures/waterNormals.jpg +0 -0
  228. package/dist/cesium/Assets/Textures/waterNormalsSmall.jpg +0 -0
  229. package/dist/cesium/Assets/approximateTerrainHeights.json +1 -0
  230. package/dist/cesium/ThirdParty/Workers/package.json +1 -0
  231. package/dist/cesium/ThirdParty/Workers/zip-web-worker.js +1 -0
  232. package/dist/cesium/ThirdParty/basis_transcoder.wasm +0 -0
  233. package/dist/cesium/ThirdParty/draco_decoder.wasm +0 -0
  234. package/dist/cesium/ThirdParty/google-earth-dbroot-parser.js +1 -0
  235. package/dist/cesium/ThirdParty/wasm_splats_bg.wasm +0 -0
  236. package/dist/cesium/ThirdParty/zip-module.wasm +0 -0
  237. package/dist/cesium/Widgets/Animation/Animation.css +127 -0
  238. package/dist/cesium/Widgets/Animation/lighter.css +70 -0
  239. package/dist/cesium/Widgets/BaseLayerPicker/BaseLayerPicker.css +108 -0
  240. package/dist/cesium/Widgets/BaseLayerPicker/lighter.css +22 -0
  241. package/dist/cesium/Widgets/Cesium3DTilesInspector/Cesium3DTilesInspector.css +102 -0
  242. package/dist/cesium/Widgets/CesiumInspector/CesiumInspector.css +113 -0
  243. package/dist/cesium/Widgets/CesiumWidget/CesiumWidget.css +119 -0
  244. package/dist/cesium/Widgets/CesiumWidget/lighter.css +14 -0
  245. package/dist/cesium/Widgets/FullscreenButton/FullscreenButton.css +8 -0
  246. package/dist/cesium/Widgets/Geocoder/Geocoder.css +70 -0
  247. package/dist/cesium/Widgets/Geocoder/lighter.css +17 -0
  248. package/dist/cesium/Widgets/I3SBuildingSceneLayerExplorer/I3SBuildingSceneLayerExplorer.css +27 -0
  249. package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldHillshade.png +0 -0
  250. package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldImagery.png +0 -0
  251. package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldOcean.png +0 -0
  252. package/dist/cesium/Widgets/Images/ImageryProviders/azureAerial.png +0 -0
  253. package/dist/cesium/Widgets/Images/ImageryProviders/azureRoads.png +0 -0
  254. package/dist/cesium/Widgets/Images/ImageryProviders/bingAerial.png +0 -0
  255. package/dist/cesium/Widgets/Images/ImageryProviders/bingAerialLabels.png +0 -0
  256. package/dist/cesium/Widgets/Images/ImageryProviders/bingRoads.png +0 -0
  257. package/dist/cesium/Widgets/Images/ImageryProviders/blueMarble.png +0 -0
  258. package/dist/cesium/Widgets/Images/ImageryProviders/earthAtNight.png +0 -0
  259. package/dist/cesium/Widgets/Images/ImageryProviders/googleContour.png +0 -0
  260. package/dist/cesium/Widgets/Images/ImageryProviders/googleRoadmap.png +0 -0
  261. package/dist/cesium/Widgets/Images/ImageryProviders/googleSatellite.png +0 -0
  262. package/dist/cesium/Widgets/Images/ImageryProviders/googleSatelliteLabels.png +0 -0
  263. package/dist/cesium/Widgets/Images/ImageryProviders/mapQuestOpenStreetMap.png +0 -0
  264. package/dist/cesium/Widgets/Images/ImageryProviders/mapboxSatellite.png +0 -0
  265. package/dist/cesium/Widgets/Images/ImageryProviders/mapboxStreets.png +0 -0
  266. package/dist/cesium/Widgets/Images/ImageryProviders/mapboxTerrain.png +0 -0
  267. package/dist/cesium/Widgets/Images/ImageryProviders/naturalEarthII.png +0 -0
  268. package/dist/cesium/Widgets/Images/ImageryProviders/openStreetMap.png +0 -0
  269. package/dist/cesium/Widgets/Images/ImageryProviders/sentinel-2.png +0 -0
  270. package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmooth.png +0 -0
  271. package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmoothDark.png +0 -0
  272. package/dist/cesium/Widgets/Images/ImageryProviders/stamenToner.png +0 -0
  273. package/dist/cesium/Widgets/Images/ImageryProviders/stamenWatercolor.png +0 -0
  274. package/dist/cesium/Widgets/Images/NavigationHelp/Mouse.svg +84 -0
  275. package/dist/cesium/Widgets/Images/NavigationHelp/MouseLeft.svg +76 -0
  276. package/dist/cesium/Widgets/Images/NavigationHelp/MouseMiddle.svg +76 -0
  277. package/dist/cesium/Widgets/Images/NavigationHelp/MouseRight.svg +76 -0
  278. package/dist/cesium/Widgets/Images/NavigationHelp/Touch.svg +120 -0
  279. package/dist/cesium/Widgets/Images/NavigationHelp/TouchDrag.svg +129 -0
  280. package/dist/cesium/Widgets/Images/NavigationHelp/TouchRotate.svg +76 -0
  281. package/dist/cesium/Widgets/Images/NavigationHelp/TouchTilt.svg +135 -0
  282. package/dist/cesium/Widgets/Images/NavigationHelp/TouchZoom.svg +74 -0
  283. package/dist/cesium/Widgets/Images/TerrainProviders/CesiumWorldTerrain.png +0 -0
  284. package/dist/cesium/Widgets/Images/TerrainProviders/Ellipsoid.png +0 -0
  285. package/dist/cesium/Widgets/Images/TimelineIcons.png +0 -0
  286. package/dist/cesium/Widgets/Images/info-loading.gif +0 -0
  287. package/dist/cesium/Widgets/InfoBox/InfoBox.css +92 -0
  288. package/dist/cesium/Widgets/InfoBox/InfoBoxDescription.css +178 -0
  289. package/dist/cesium/Widgets/NavigationHelpButton/NavigationHelpButton.css +93 -0
  290. package/dist/cesium/Widgets/NavigationHelpButton/lighter.css +38 -0
  291. package/dist/cesium/Widgets/PerformanceWatchdog/PerformanceWatchdog.css +15 -0
  292. package/dist/cesium/Widgets/ProjectionPicker/ProjectionPicker.css +38 -0
  293. package/dist/cesium/Widgets/SceneModePicker/SceneModePicker.css +56 -0
  294. package/dist/cesium/Widgets/SelectionIndicator/SelectionIndicator.css +20 -0
  295. package/dist/cesium/Widgets/Timeline/Timeline.css +103 -0
  296. package/dist/cesium/Widgets/Timeline/lighter.css +23 -0
  297. package/dist/cesium/Widgets/VRButton/VRButton.css +8 -0
  298. package/dist/cesium/Widgets/Viewer/Viewer.css +107 -0
  299. package/dist/cesium/Widgets/VoxelInspector/VoxelInspector.css +16 -0
  300. package/dist/cesium/Widgets/lighter.css +237 -0
  301. package/dist/cesium/Widgets/lighterShared.css +46 -0
  302. package/dist/cesium/Widgets/shared.css +103 -0
  303. package/dist/cesium/Widgets/widgets.css +1342 -0
  304. package/dist/cesium/Workers/chunk-23ZQ2IVV.js +29 -0
  305. package/dist/cesium/Workers/chunk-2EQO3Q56.js +26 -0
  306. package/dist/cesium/Workers/chunk-2MJIIVP4.js +26 -0
  307. package/dist/cesium/Workers/chunk-2TE5NTVD.js +26 -0
  308. package/dist/cesium/Workers/chunk-2ZBHLJST.js +26 -0
  309. package/dist/cesium/Workers/chunk-5TJMAQVL.js +26 -0
  310. package/dist/cesium/Workers/chunk-6BD4U3VO.js +26 -0
  311. package/dist/cesium/Workers/chunk-7TVGLKQF.js +26 -0
  312. package/dist/cesium/Workers/chunk-BTSYJ5XU.js +26 -0
  313. package/dist/cesium/Workers/chunk-BXMEEOCS.js +63 -0
  314. package/dist/cesium/Workers/chunk-BYLCY7GP.js +29 -0
  315. package/dist/cesium/Workers/chunk-CTHM3W6I.js +26 -0
  316. package/dist/cesium/Workers/chunk-CUUSNIVQ.js +26 -0
  317. package/dist/cesium/Workers/chunk-E3JOOS3S.js +26 -0
  318. package/dist/cesium/Workers/chunk-E7KYDCM5.js +26 -0
  319. package/dist/cesium/Workers/chunk-EDVBB7SS.js +27 -0
  320. package/dist/cesium/Workers/chunk-EFBN7QNX.js +26 -0
  321. package/dist/cesium/Workers/chunk-EQ4YRVWL.js +26 -0
  322. package/dist/cesium/Workers/chunk-F6PRE7D6.js +26 -0
  323. package/dist/cesium/Workers/chunk-FC4ZZ65J.js +26 -0
  324. package/dist/cesium/Workers/chunk-FFBVWF2L.js +26 -0
  325. package/dist/cesium/Workers/chunk-GBAA6GVX.js +26 -0
  326. package/dist/cesium/Workers/chunk-ICALLYLG.js +26 -0
  327. package/dist/cesium/Workers/chunk-ILRYTWTP.js +26 -0
  328. package/dist/cesium/Workers/chunk-IRNLBSEJ.js +26 -0
  329. package/dist/cesium/Workers/chunk-IX4VMHEV.js +26 -0
  330. package/dist/cesium/Workers/chunk-L6QHHACZ.js +26 -0
  331. package/dist/cesium/Workers/chunk-LI2ZSORM.js +26 -0
  332. package/dist/cesium/Workers/chunk-LSLE2RL4.js +26 -0
  333. package/dist/cesium/Workers/chunk-M4HLDBCG.js +26 -0
  334. package/dist/cesium/Workers/chunk-MJHHSGEH.js +26 -0
  335. package/dist/cesium/Workers/chunk-NMVKML6W.js +26 -0
  336. package/dist/cesium/Workers/chunk-OCWJRAXS.js +26 -0
  337. package/dist/cesium/Workers/chunk-OIRKANTH.js +26 -0
  338. package/dist/cesium/Workers/chunk-OIT7J4IC.js +26 -0
  339. package/dist/cesium/Workers/chunk-OLZ3FYUM.js +26 -0
  340. package/dist/cesium/Workers/chunk-Q5BPHJQF.js +26 -0
  341. package/dist/cesium/Workers/chunk-QFM5DCMQ.js +26 -0
  342. package/dist/cesium/Workers/chunk-QKUIYMGC.js +28 -0
  343. package/dist/cesium/Workers/chunk-S44JILQT.js +26 -0
  344. package/dist/cesium/Workers/chunk-SLT4J352.js +26 -0
  345. package/dist/cesium/Workers/chunk-SQMIIXB7.js +26 -0
  346. package/dist/cesium/Workers/chunk-TJ4XLGBQ.js +26 -0
  347. package/dist/cesium/Workers/chunk-TNSUQXWK.js +27 -0
  348. package/dist/cesium/Workers/chunk-UBOGZS7F.js +26 -0
  349. package/dist/cesium/Workers/chunk-V3OSTMM6.js +26 -0
  350. package/dist/cesium/Workers/chunk-V7QEYVP3.js +26 -0
  351. package/dist/cesium/Workers/chunk-VUKYSU4H.js +26 -0
  352. package/dist/cesium/Workers/chunk-W37FE5GR.js +26 -0
  353. package/dist/cesium/Workers/chunk-WBOV35NL.js +26 -0
  354. package/dist/cesium/Workers/chunk-WPMZLB3Y.js +26 -0
  355. package/dist/cesium/Workers/chunk-WWWZVEEH.js +26 -0
  356. package/dist/cesium/Workers/chunk-XFIQ5DEQ.js +28 -0
  357. package/dist/cesium/Workers/chunk-XQHLGIO7.js +26 -0
  358. package/dist/cesium/Workers/chunk-XUSCFAVF.js +26 -0
  359. package/dist/cesium/Workers/chunk-YP7I5QBZ.js +26 -0
  360. package/dist/cesium/Workers/chunk-Z3QF2EHT.js +26 -0
  361. package/dist/cesium/Workers/combineGeometry.js +26 -0
  362. package/dist/cesium/Workers/createBoxGeometry.js +26 -0
  363. package/dist/cesium/Workers/createBoxOutlineGeometry.js +26 -0
  364. package/dist/cesium/Workers/createCircleGeometry.js +26 -0
  365. package/dist/cesium/Workers/createCircleOutlineGeometry.js +26 -0
  366. package/dist/cesium/Workers/createCoplanarPolygonGeometry.js +26 -0
  367. package/dist/cesium/Workers/createCoplanarPolygonOutlineGeometry.js +26 -0
  368. package/dist/cesium/Workers/createCorridorGeometry.js +26 -0
  369. package/dist/cesium/Workers/createCorridorOutlineGeometry.js +26 -0
  370. package/dist/cesium/Workers/createCylinderGeometry.js +26 -0
  371. package/dist/cesium/Workers/createCylinderOutlineGeometry.js +26 -0
  372. package/dist/cesium/Workers/createEllipseGeometry.js +26 -0
  373. package/dist/cesium/Workers/createEllipseOutlineGeometry.js +26 -0
  374. package/dist/cesium/Workers/createEllipsoidGeometry.js +26 -0
  375. package/dist/cesium/Workers/createEllipsoidOutlineGeometry.js +26 -0
  376. package/dist/cesium/Workers/createFrustumGeometry.js +26 -0
  377. package/dist/cesium/Workers/createFrustumOutlineGeometry.js +26 -0
  378. package/dist/cesium/Workers/createGeometry.js +26 -0
  379. package/dist/cesium/Workers/createGroundPolylineGeometry.js +26 -0
  380. package/dist/cesium/Workers/createPlaneGeometry.js +26 -0
  381. package/dist/cesium/Workers/createPlaneOutlineGeometry.js +26 -0
  382. package/dist/cesium/Workers/createPolygonGeometry.js +26 -0
  383. package/dist/cesium/Workers/createPolygonOutlineGeometry.js +26 -0
  384. package/dist/cesium/Workers/createPolylineGeometry.js +26 -0
  385. package/dist/cesium/Workers/createPolylineVolumeGeometry.js +26 -0
  386. package/dist/cesium/Workers/createPolylineVolumeOutlineGeometry.js +26 -0
  387. package/dist/cesium/Workers/createRectangleGeometry.js +26 -0
  388. package/dist/cesium/Workers/createRectangleOutlineGeometry.js +26 -0
  389. package/dist/cesium/Workers/createSimplePolylineGeometry.js +26 -0
  390. package/dist/cesium/Workers/createSphereGeometry.js +26 -0
  391. package/dist/cesium/Workers/createSphereOutlineGeometry.js +26 -0
  392. package/dist/cesium/Workers/createTaskProcessorWorker.js +26 -0
  393. package/dist/cesium/Workers/createVectorTileClampedPolylines.js +26 -0
  394. package/dist/cesium/Workers/createVectorTileGeometries.js +26 -0
  395. package/dist/cesium/Workers/createVectorTilePoints.js +26 -0
  396. package/dist/cesium/Workers/createVectorTilePolygons.js +26 -0
  397. package/dist/cesium/Workers/createVectorTilePolylines.js +26 -0
  398. package/dist/cesium/Workers/createVerticesFromCesium3DTilesTerrain.js +26 -0
  399. package/dist/cesium/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +26 -0
  400. package/dist/cesium/Workers/createVerticesFromHeightmap.js +26 -0
  401. package/dist/cesium/Workers/createVerticesFromQuantizedTerrainMesh.js +26 -0
  402. package/dist/cesium/Workers/createWallGeometry.js +26 -0
  403. package/dist/cesium/Workers/createWallOutlineGeometry.js +26 -0
  404. package/dist/cesium/Workers/decodeDraco.js +26 -0
  405. package/dist/cesium/Workers/decodeGoogleEarthEnterprisePacket.js +26 -0
  406. package/dist/cesium/Workers/decodeI3S.js +26 -0
  407. package/dist/cesium/Workers/gaussianSplatSorter.js +26 -0
  408. package/dist/cesium/Workers/gaussianSplatTextureGenerator.js +26 -0
  409. package/dist/cesium/Workers/incrementallyBuildTerrainPicker.js +26 -0
  410. package/dist/cesium/Workers/transcodeKTX2.js +56 -0
  411. package/dist/cesium/Workers/transferTypedArrayTest.js +26 -0
  412. package/dist/cesium/Workers/upsampleQuantizedTerrainMesh.js +26 -0
  413. package/dist/cesium/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +26 -0
  414. package/dist/index.html +10 -8
  415. package/package.json +15 -12
  416. package/src/App.tsx +1 -17
  417. package/src/components/viewer/BCFPanel.tsx +46 -4
  418. package/src/components/viewer/CesiumOverlay.tsx +672 -0
  419. package/src/components/viewer/CesiumSettingsDialog.tsx +100 -0
  420. package/src/components/viewer/ChatPanel.tsx +54 -16
  421. package/src/components/viewer/CommandPalette.tsx +6 -1
  422. package/src/components/viewer/DesktopEntitlementBanner.tsx +74 -0
  423. package/src/components/viewer/ExportChangesButton.tsx +6 -1
  424. package/src/components/viewer/ExportDialog.tsx +22 -6
  425. package/src/components/viewer/HierarchyPanel.tsx +196 -0
  426. package/src/components/viewer/IDSPanel.tsx +52 -3
  427. package/src/components/viewer/KeyboardShortcutsDialog.tsx +1 -1
  428. package/src/components/viewer/MainToolbar.tsx +353 -27
  429. package/src/components/viewer/PropertiesPanel.tsx +218 -79
  430. package/src/components/viewer/ScriptPanel.tsx +34 -8
  431. package/src/components/viewer/SettingsPage.tsx +430 -0
  432. package/src/components/viewer/StatusBar.tsx +17 -1
  433. package/src/components/viewer/UpgradePage.tsx +6 -4
  434. package/src/components/viewer/ViewerLayout.tsx +47 -6
  435. package/src/components/viewer/Viewport.tsx +49 -8
  436. package/src/components/viewer/ViewportContainer.tsx +280 -28
  437. package/src/components/viewer/ViewportOverlays.tsx +129 -27
  438. package/src/components/viewer/properties/GeoreferencingPanel.tsx +117 -5
  439. package/src/components/viewer/properties/LocationMap.tsx +458 -17
  440. package/src/components/viewer/selectionHandlers.ts +4 -3
  441. package/src/components/viewer/useAnimationLoop.ts +4 -0
  442. package/src/components/viewer/useGeometryStreaming.ts +127 -40
  443. package/src/components/viewer/useMouseControls.ts +4 -1
  444. package/src/hooks/ingest/viewerModelIngest.ts +275 -0
  445. package/src/hooks/useIDS.ts +1 -1
  446. package/src/hooks/useIfc.ts +7 -1
  447. package/src/hooks/useIfcCache.ts +28 -15
  448. package/src/hooks/useIfcFederation.ts +57 -225
  449. package/src/hooks/useIfcLoader.ts +1656 -130
  450. package/src/hooks/useIfcServer.ts +0 -69
  451. package/src/lib/desktop/ClerkDesktopEntitlementSync.tsx +175 -0
  452. package/src/lib/desktop/desktopEntitlementEvents.ts +39 -0
  453. package/src/lib/desktop-entitlement.ts +45 -0
  454. package/src/lib/desktop-product.ts +124 -0
  455. package/src/lib/geo/cesium-bridge.ts +310 -0
  456. package/src/lib/geo/reproject.ts +151 -25
  457. package/src/lib/recent-files.ts +2 -1
  458. package/src/services/analysis-extensions.ts +125 -0
  459. package/src/services/app-navigation.ts +13 -0
  460. package/src/services/bsdd.ts +53 -4
  461. package/src/services/cacheService.ts +1 -1
  462. package/src/services/desktop-cache.ts +43 -0
  463. package/src/services/desktop-export.ts +77 -0
  464. package/src/services/desktop-harness.ts +196 -0
  465. package/src/services/desktop-logger.ts +20 -0
  466. package/src/services/desktop-native-metadata.ts +207 -0
  467. package/src/services/desktop-panel-actions.ts +43 -0
  468. package/src/services/desktop-preferences.ts +44 -0
  469. package/src/services/file-dialog.ts +147 -0
  470. package/src/services/tauri-core-stub.ts +7 -0
  471. package/src/services/tauri-dialog-stub.ts +7 -0
  472. package/src/services/tauri-fs-stub.ts +7 -0
  473. package/src/store/index.ts +40 -2
  474. package/src/store/slices/cesiumSlice.ts +122 -0
  475. package/src/store/slices/chatSlice.ts +5 -1
  476. package/src/store/slices/dataSlice.ts +139 -28
  477. package/src/store/slices/desktopEntitlementSlice.ts +86 -0
  478. package/src/store/slices/loadingSlice.ts +14 -2
  479. package/src/store/slices/modelSlice.ts +58 -3
  480. package/src/store/types.ts +96 -2
  481. package/src/store.ts +1 -1
  482. package/src/utils/desktopModelSnapshot.ts +358 -0
  483. package/src/utils/ifcConfig.ts +6 -1
  484. package/src/utils/nativeSpatialDataStore.ts +250 -0
  485. package/src/utils/serverDataModel.ts +4 -0
  486. package/src/utils/spatialHierarchy.ts +10 -11
  487. package/vite.config.ts +24 -0
  488. package/dist/assets/arrow-DJf2ErbF.js +0 -20
  489. package/dist/assets/basketViewActivator-aojwdomq.js +0 -1
  490. package/dist/assets/desktop-cache-oPzaWXYE.js +0 -1
  491. package/dist/assets/geometry.worker-Nz9_YIqh.js +0 -1
  492. package/dist/assets/ifc-lite_bg-eSkBTizQ.wasm +0 -0
  493. package/dist/assets/index-pbE7itQS.css +0 -1
  494. package/dist/assets/native-bridge-DSIyEYXG.js +0 -113
  495. package/dist/assets/wasm-bridge-B0J07fZZ.js +0 -1
@@ -29,6 +29,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip
29
29
  import { useViewerStore } from '@/store';
30
30
  import { toGlobalIdFromModels } from '@/store/globalId';
31
31
  import { useIfc } from '@/hooks/useIfc';
32
+ import { getNativeEntityDetails } from '@/services/desktop-native-metadata';
32
33
  import { configureMutationView } from '@/utils/configureMutationView';
33
34
  import { IfcQuery } from '@ifc-lite/query';
34
35
  import { MutablePropertyView } from '@ifc-lite/mutations';
@@ -103,7 +104,7 @@ export function PropertiesPanel() {
103
104
  const m = models.get(selectedEntity.modelId);
104
105
  if (m) {
105
106
  return {
106
- modelQuery: new IfcQuery(m.ifcDataStore),
107
+ modelQuery: m.nativeMetadata ? null : (m.ifcDataStore ? new IfcQuery(m.ifcDataStore) : null),
107
108
  model: m,
108
109
  };
109
110
  }
@@ -123,7 +124,7 @@ export function PropertiesPanel() {
123
124
 
124
125
  // Ensure mutation view exists for editing - creates it on-demand if needed
125
126
  useEffect(() => {
126
- if (!model || !selectedEntity || selectedEntity.modelId === 'legacy') return;
127
+ if (!model || !model.ifcDataStore || !selectedEntity || selectedEntity.modelId === 'legacy') return;
127
128
 
128
129
  const modelId = selectedEntity.modelId;
129
130
  let mutationView = getMutationView(modelId);
@@ -142,10 +143,38 @@ export function PropertiesPanel() {
142
143
  const [copied, setCopied] = useState(false);
143
144
  const [coordCopied, setCoordCopied] = useState<string | null>(null);
144
145
  const [coordOpen, setCoordOpen] = useState(false);
146
+ const [nativeDetails, setNativeDetails] = useState<import('@/store/types').NativeMetadataEntityDetails | null>(null);
147
+ const [nativeDetailsState, setNativeDetailsState] = useState<'idle' | 'loading' | 'error'>('idle');
145
148
 
146
149
  // Edit mode toggle - allows inline property editing
147
150
  const [editMode, setEditMode] = useState(false);
148
151
 
152
+ useEffect(() => {
153
+ if (!selectedEntity || !model?.nativeMetadata) {
154
+ setNativeDetails(null);
155
+ setNativeDetailsState('idle');
156
+ return;
157
+ }
158
+ let cancelled = false;
159
+ setNativeDetailsState('loading');
160
+ void getNativeEntityDetails(model.nativeMetadata.cacheKey, selectedEntity.expressId)
161
+ .then((details) => {
162
+ if (!cancelled) {
163
+ setNativeDetails(details);
164
+ setNativeDetailsState('idle');
165
+ }
166
+ })
167
+ .catch(() => {
168
+ if (!cancelled) {
169
+ setNativeDetails(null);
170
+ setNativeDetailsState('error');
171
+ }
172
+ });
173
+ return () => {
174
+ cancelled = true;
175
+ };
176
+ }, [selectedEntity, model?.nativeMetadata]);
177
+
149
178
  const copyToClipboard = useCallback((text: string) => {
150
179
  navigator.clipboard.writeText(text);
151
180
  setCopied(true);
@@ -747,6 +776,114 @@ export function PropertiesPanel() {
747
776
  return names;
748
777
  }, [attributes]);
749
778
 
779
+ const isNativeLazySelection = Boolean(selectedEntity && model?.nativeMetadata);
780
+
781
+ useEffect(() => {
782
+ if (isNativeLazySelection && editMode) {
783
+ setEditMode(false);
784
+ }
785
+ }, [isNativeLazySelection, editMode]);
786
+
787
+ const nativeSpatialInfo = useMemo(() => {
788
+ if (!nativeDetails?.spatial?.storeyName) return null;
789
+ return {
790
+ storeyId: nativeDetails.spatial.storeyId ?? undefined,
791
+ storeyName: nativeDetails.spatial.storeyName,
792
+ elevation: nativeDetails.spatial.elevation ?? undefined,
793
+ height: nativeDetails.spatial.height ?? undefined,
794
+ };
795
+ }, [nativeDetails]);
796
+
797
+ const nativeOccurrenceProperties = useMemo<PropertySet[]>(() => {
798
+ if (!nativeDetails) return [];
799
+ return nativeDetails.properties.map((pset) => ({
800
+ name: pset.name,
801
+ properties: pset.properties.map((property) => ({
802
+ name: property.name,
803
+ value: property.value,
804
+ isMutated: false,
805
+ })),
806
+ isNewPset: false,
807
+ source: 'instance' as const,
808
+ }));
809
+ }, [nativeDetails]);
810
+
811
+ const nativeQuantities = useMemo<QuantitySet[]>(() => {
812
+ if (!nativeDetails) return [];
813
+ return nativeDetails.quantities.map((qset) => ({
814
+ name: qset.name,
815
+ quantities: qset.quantities.map((quantity) => ({
816
+ name: quantity.name,
817
+ value: quantity.value,
818
+ type: quantity.type ?? 0,
819
+ })),
820
+ }));
821
+ }, [nativeDetails]);
822
+
823
+ const renderedEntityType = isNativeLazySelection
824
+ ? (nativeDetails?.summary.type ?? 'Loading...')
825
+ : (entityNode?.type ?? 'Unknown');
826
+ const renderedEntityName = isNativeLazySelection
827
+ ? (nativeDetails?.summary.name ?? `#${selectedEntity?.expressId ?? ''}`)
828
+ : entityNode?.name;
829
+ const renderedEntityGlobalId = isNativeLazySelection
830
+ ? (nativeDetails?.summary.globalId ?? null)
831
+ : entityNode?.globalId;
832
+ const renderedEntityDescription = isNativeLazySelection ? undefined : entityNode?.description;
833
+ const renderedEntityObjectType = isNativeLazySelection ? undefined : entityNode?.objectType;
834
+ const renderedSpatialInfo = isNativeLazySelection ? nativeSpatialInfo : spatialInfo;
835
+ const renderedOccurrenceProperties = isNativeLazySelection ? nativeOccurrenceProperties : occurrenceProperties;
836
+ const renderedInheritedTypeProperties = isNativeLazySelection ? [] : inheritedTypeProperties;
837
+ const renderedMergedProperties = isNativeLazySelection
838
+ ? nativeOccurrenceProperties
839
+ : mergedProperties;
840
+ const renderedQuantities = isNativeLazySelection ? nativeQuantities : quantities;
841
+ const renderedAttributes = isNativeLazySelection ? [] : attributes;
842
+ const renderedClassifications = isNativeLazySelection ? [] : classifications;
843
+ const renderedMaterialInfo = isNativeLazySelection ? null : materialInfo;
844
+ const renderedDocuments = isNativeLazySelection ? [] : documents;
845
+ const renderedEntityRelationships = isNativeLazySelection ? null : entityRelationships;
846
+ const renderedGeoref = isNativeLazySelection ? null : georef;
847
+ const renderedSpatialContainment = isNativeLazySelection ? null : spatialContainment;
848
+ const renderedTypeProperties = isNativeLazySelection
849
+ ? (nativeDetails?.typeSummary
850
+ ? {
851
+ typeName: nativeDetails.typeSummary.name,
852
+ typeId: nativeDetails.typeSummary.expressId,
853
+ psets: [] as PropertySet[],
854
+ }
855
+ : null)
856
+ : typeProperties;
857
+ const renderedTypeEditImpact = isNativeLazySelection ? null : typeEditImpact;
858
+ const renderedIsTypeEntity = isNativeLazySelection
859
+ ? ((nativeDetails?.summary.type ?? '').endsWith('Type'))
860
+ : isTypeEntity;
861
+ const renderedExistingProps = useMemo(() => {
862
+ const keys = new Set<string>();
863
+ for (const pset of renderedMergedProperties) {
864
+ for (const prop of pset.properties) {
865
+ keys.add(`${pset.name}:${prop.name}`);
866
+ }
867
+ }
868
+ return keys;
869
+ }, [renderedMergedProperties]);
870
+ const renderedExistingQuants = useMemo(() => {
871
+ const keys = new Set<string>();
872
+ for (const qset of renderedQuantities) {
873
+ for (const q of qset.quantities) {
874
+ keys.add(`${qset.name}:${q.name}`);
875
+ }
876
+ }
877
+ return keys;
878
+ }, [renderedQuantities]);
879
+ const renderedExistingAttributeNames = useMemo(() => {
880
+ const names = new Set<string>();
881
+ for (const attr of renderedAttributes) {
882
+ if (attr.value) names.add(attr.name);
883
+ }
884
+ return names;
885
+ }, [renderedAttributes]);
886
+
750
887
  // Model metadata display (when clicking top-level model in hierarchy)
751
888
  if (selectedModelId) {
752
889
  const selectedModel = models.get(selectedModelId);
@@ -766,7 +903,7 @@ export function PropertiesPanel() {
766
903
  );
767
904
  }
768
905
 
769
- if (!selectedEntityId || !modelQuery || !entityNode) {
906
+ if (!selectedEntityId || (!isNativeLazySelection && (!modelQuery || !entityNode))) {
770
907
  // Show model metadata when a single legacy model is loaded and nothing selected
771
908
  if (ifcDataStore && models.size === 0 && geometryResult) {
772
909
  const legacyModel: FederatedModel = {
@@ -803,11 +940,11 @@ export function PropertiesPanel() {
803
940
  }
804
941
 
805
942
  // These are safe to access after the early return check (entityNode is confirmed non-null above)
806
- const entityType = entityNode.type;
807
- const entityName = entityNode.name;
808
- const entityGlobalId = entityNode.globalId;
809
- const entityDescription = entityNode.description;
810
- const entityObjectType = entityNode.objectType;
943
+ const entityType = renderedEntityType;
944
+ const entityName = renderedEntityName;
945
+ const entityGlobalId = renderedEntityGlobalId;
946
+ const entityDescription = renderedEntityDescription;
947
+ const entityObjectType = renderedEntityObjectType;
811
948
 
812
949
  return (
813
950
  <div className="h-full flex flex-col border-l-2 border-zinc-200 dark:border-zinc-800 bg-white dark:bg-black">
@@ -823,10 +960,10 @@ export function PropertiesPanel() {
823
960
  </h3>
824
961
  <p className="text-xs font-mono text-zinc-500 dark:text-zinc-400">{entityType}</p>
825
962
  {/* Show associated type entity for occurrences */}
826
- {!isTypeEntity && typeProperties && (
827
- <p className="text-[11px] font-mono text-indigo-500 dark:text-indigo-400 truncate" title={`${activeDataStore?.entities.getTypeName(typeProperties.typeId) || 'Type'}: ${typeProperties.typeName}`}>
963
+ {!renderedIsTypeEntity && renderedTypeProperties && (
964
+ <p className="text-[11px] font-mono text-indigo-500 dark:text-indigo-400 truncate" title={`${activeDataStore?.entities.getTypeName(renderedTypeProperties.typeId) || 'Type'}: ${renderedTypeProperties.typeName}`}>
828
965
  <Building2 className="inline h-3 w-3 mr-1 -mt-0.5" />
829
- {activeDataStore?.entities.getTypeName(typeProperties.typeId) || 'Type'}: {typeProperties.typeName}
966
+ {activeDataStore?.entities.getTypeName(renderedTypeProperties.typeId) || 'Type'}: {renderedTypeProperties.typeName}
830
967
  </p>
831
968
  )}
832
969
  </div>
@@ -872,19 +1009,21 @@ export function PropertiesPanel() {
872
1009
  </TooltipContent>
873
1010
  </Tooltip>
874
1011
  {/* Edit mode toggle */}
875
- <Tooltip>
876
- <TooltipTrigger asChild>
877
- <Button
878
- variant={editMode ? 'default' : 'ghost'}
879
- size="icon-xs"
880
- className={`rounded-none ${editMode ? 'bg-purple-600 hover:bg-purple-700 text-white' : 'hover:bg-zinc-200 dark:hover:bg-zinc-700'}`}
881
- onClick={() => setEditMode(!editMode)}
882
- >
883
- <PenLine className="h-3.5 w-3.5" />
884
- </Button>
885
- </TooltipTrigger>
886
- <TooltipContent>{editMode ? 'Exit Edit Mode' : 'Edit Properties'}</TooltipContent>
887
- </Tooltip>
1012
+ {!isNativeLazySelection && (
1013
+ <Tooltip>
1014
+ <TooltipTrigger asChild>
1015
+ <Button
1016
+ variant={editMode ? 'default' : 'ghost'}
1017
+ size="icon-xs"
1018
+ className={`rounded-none ${editMode ? 'bg-purple-600 hover:bg-purple-700 text-white' : 'hover:bg-zinc-200 dark:hover:bg-zinc-700'}`}
1019
+ onClick={() => setEditMode(!editMode)}
1020
+ >
1021
+ <PenLine className="h-3.5 w-3.5" />
1022
+ </Button>
1023
+ </TooltipTrigger>
1024
+ <TooltipContent>{editMode ? 'Exit Edit Mode' : 'Edit Properties'}</TooltipContent>
1025
+ </Tooltip>
1026
+ )}
888
1027
  </div>
889
1028
  </div>
890
1029
 
@@ -918,34 +1057,34 @@ export function PropertiesPanel() {
918
1057
  )}
919
1058
 
920
1059
  {/* Spatial Location */}
921
- {spatialInfo && (
1060
+ {renderedSpatialInfo && (
922
1061
  <div className="flex items-center gap-2 text-xs border border-emerald-500/30 bg-emerald-50/50 dark:bg-emerald-900/10 px-2 py-1.5 text-emerald-800 dark:text-emerald-400 min-w-0">
923
1062
  <Layers className="h-3.5 w-3.5 shrink-0" />
924
- <span className="font-bold uppercase tracking-wide truncate min-w-0 flex-1">{spatialInfo.storeyName}</span>
1063
+ <span className="font-bold uppercase tracking-wide truncate min-w-0 flex-1">{renderedSpatialInfo.storeyName}</span>
925
1064
  <div className="flex items-center gap-1.5 shrink-0">
926
- {spatialInfo.elevation !== undefined && (
1065
+ {renderedSpatialInfo.elevation !== undefined && (
927
1066
  <Tooltip>
928
1067
  <TooltipTrigger asChild>
929
1068
  <span className="text-emerald-600/70 dark:text-emerald-500/70 font-mono whitespace-nowrap">
930
- {spatialInfo.elevation >= 0 ? '+' : ''}{spatialInfo.elevation.toFixed(2)}m
1069
+ {renderedSpatialInfo.elevation >= 0 ? '+' : ''}{renderedSpatialInfo.elevation.toFixed(2)}m
931
1070
  </span>
932
1071
  </TooltipTrigger>
933
1072
  <TooltipContent>
934
- <p className="text-xs">Elevation: {spatialInfo.elevation >= 0 ? '+' : ''}{spatialInfo.elevation.toFixed(2)}m from ground</p>
1073
+ <p className="text-xs">Elevation: {renderedSpatialInfo.elevation >= 0 ? '+' : ''}{renderedSpatialInfo.elevation.toFixed(2)}m from ground</p>
935
1074
  </TooltipContent>
936
1075
  </Tooltip>
937
1076
  )}
938
- {spatialInfo.height !== undefined && (
1077
+ {renderedSpatialInfo.height !== undefined && (
939
1078
  <Tooltip>
940
1079
  <TooltipTrigger asChild>
941
1080
  <span className="flex items-center gap-1 text-emerald-500/60 dark:text-emerald-400/60 font-mono text-[10px] whitespace-nowrap">
942
1081
  <ArrowUpDown className="h-2.5 w-2.5 shrink-0" />
943
- <span className="hidden sm:inline">{spatialInfo.height.toFixed(2)}m</span>
944
- <span className="sm:hidden">{spatialInfo.height.toFixed(1)}m</span>
1082
+ <span className="hidden sm:inline">{renderedSpatialInfo.height.toFixed(2)}m</span>
1083
+ <span className="sm:hidden">{renderedSpatialInfo.height.toFixed(1)}m</span>
945
1084
  </span>
946
1085
  </TooltipTrigger>
947
1086
  <TooltipContent>
948
- <p className="text-xs">Height: {spatialInfo.height.toFixed(2)}m to next storey</p>
1087
+ <p className="text-xs">Height: {renderedSpatialInfo.height.toFixed(2)}m to next storey</p>
949
1088
  </TooltipContent>
950
1089
  </Tooltip>
951
1090
  )}
@@ -954,7 +1093,7 @@ export function PropertiesPanel() {
954
1093
  )}
955
1094
 
956
1095
  {/* World coordinates + Georeferencing — single consolidated section */}
957
- {(entityCoordinates || georef || editMode) && (
1096
+ {(entityCoordinates || renderedGeoref || editMode) && (
958
1097
  <Collapsible open={coordOpen} onOpenChange={setCoordOpen}>
959
1098
  <CollapsibleTrigger className="flex items-center gap-2 w-full text-xs border border-teal-500/30 px-2 py-1.5 text-teal-800 dark:text-teal-400 min-w-0 text-left group/coord">
960
1099
  <Crosshair className="h-3.5 w-3.5 shrink-0" />
@@ -968,8 +1107,8 @@ export function PropertiesPanel() {
968
1107
  <CoordVal axis="Z" value={entityCoordinates.worldZup.center.z} />
969
1108
  </span>
970
1109
  )}
971
- {georef?.projectedCRS?.name && (
972
- <span className="font-mono text-[9px] text-teal-500/60 shrink-0">{georef.projectedCRS.name}</span>
1110
+ {renderedGeoref?.projectedCRS?.name && (
1111
+ <span className="font-mono text-[9px] text-teal-500/60 shrink-0">{renderedGeoref.projectedCRS.name}</span>
973
1112
  )}
974
1113
  <span className="text-[9px] text-teal-500/0 group-hover/coord:text-teal-500/40 transition-colors shrink-0">details</span>
975
1114
  </>
@@ -1010,7 +1149,7 @@ export function PropertiesPanel() {
1010
1149
  </div>
1011
1150
  )}
1012
1151
  <GeoreferencingPanel
1013
- georef={georef}
1152
+ georef={renderedGeoref}
1014
1153
  modelId={selectedEntity?.modelId === 'legacy' ? '__legacy__' : (model?.id ?? selectedEntity?.modelId)}
1015
1154
  enableEditing
1016
1155
  schemaVersion={activeDataStore?.schemaVersion}
@@ -1031,17 +1170,17 @@ export function PropertiesPanel() {
1031
1170
  </div>
1032
1171
 
1033
1172
  {/* IFC Attributes */}
1034
- {attributes.length > 0 && (
1173
+ {renderedAttributes.length > 0 && (
1035
1174
  <Collapsible defaultOpen className="border-b">
1036
1175
  <CollapsibleTrigger className="flex items-center gap-2 w-full p-3 hover:bg-muted/50 text-left">
1037
1176
  <Tag className="h-4 w-4 text-muted-foreground" />
1038
1177
  <span className="font-medium text-sm">Attributes</span>
1039
1178
  {editMode && <PenLine className="h-3 w-3 text-purple-500 ml-1" />}
1040
- <span className="text-xs text-muted-foreground ml-auto">{attributes.length}</span>
1179
+ <span className="text-xs text-muted-foreground ml-auto">{renderedAttributes.length}</span>
1041
1180
  </CollapsibleTrigger>
1042
1181
  <CollapsibleContent>
1043
1182
  <div className="divide-y border-t">
1044
- {attributes.map((attr) => (
1183
+ {renderedAttributes.map((attr) => (
1045
1184
  <div key={attr.name} className="grid grid-cols-[minmax(80px,1fr)_minmax(0,2fr)] gap-2 px-3 py-1.5 text-sm">
1046
1185
  <span className="text-muted-foreground truncate" title={attr.name}>{attr.name}</span>
1047
1186
  {editMode && selectedEntity ? (
@@ -1066,16 +1205,16 @@ export function PropertiesPanel() {
1066
1205
  )}
1067
1206
 
1068
1207
  {/* Spatial Containment - for spatial containers (Project, Site, Building, Storey) */}
1069
- {spatialContainment && (
1208
+ {renderedSpatialContainment && (
1070
1209
  <Collapsible defaultOpen className="border-b">
1071
1210
  <CollapsibleTrigger className="flex items-center gap-2 w-full p-3 hover:bg-muted/50 text-left">
1072
1211
  <Layers className="h-4 w-4 text-emerald-600" />
1073
1212
  <span className="font-medium text-sm">Structure</span>
1074
- <span className="text-xs text-muted-foreground ml-auto">{spatialContainment.length}</span>
1213
+ <span className="text-xs text-muted-foreground ml-auto">{renderedSpatialContainment.length}</span>
1075
1214
  </CollapsibleTrigger>
1076
1215
  <CollapsibleContent>
1077
1216
  <div className="divide-y border-t">
1078
- {spatialContainment.map((item) => (
1217
+ {renderedSpatialContainment.map((item) => (
1079
1218
  <div key={item.label} className="grid grid-cols-[minmax(80px,1fr)_minmax(0,2fr)] gap-2 px-3 py-1.5 text-sm">
1080
1219
  <span className="text-muted-foreground truncate" title={item.label}>{item.label}</span>
1081
1220
  <span className="font-medium font-mono">{item.value}</span>
@@ -1118,26 +1257,26 @@ export function PropertiesPanel() {
1118
1257
  <ScrollArea className="flex-1 bg-white dark:bg-black">
1119
1258
  <TabsContent value="properties" className="m-0 p-3 overflow-hidden">
1120
1259
  {/* Edit toolbar - only shown when edit mode is active */}
1121
- {editMode && selectedEntity && (
1260
+ {editMode && selectedEntity && !isNativeLazySelection && (
1122
1261
  <EditToolbar
1123
1262
  modelId={selectedEntity.modelId}
1124
1263
  entityId={selectedEntity.expressId}
1125
1264
  entityType={entityType}
1126
- existingPsets={mergedProperties.map(p => p.name)}
1127
- existingQtos={quantities.map(q => q.name)}
1265
+ existingPsets={renderedMergedProperties.map(p => p.name)}
1266
+ existingQtos={renderedQuantities.map(q => q.name)}
1128
1267
  schemaVersion={activeDataStore?.schemaVersion}
1129
1268
  />
1130
1269
  )}
1131
- {mergedProperties.length === 0 && classifications.length === 0 && !materialInfo && documents.length === 0 ? (
1270
+ {renderedMergedProperties.length === 0 && renderedClassifications.length === 0 && !renderedMaterialInfo && renderedDocuments.length === 0 ? (
1132
1271
  <p className="text-sm text-zinc-500 dark:text-zinc-500 text-center py-8 font-mono">No property sets</p>
1133
1272
  ) : (
1134
1273
  <div className="space-y-3 w-full overflow-hidden">
1135
1274
  {/* Occurrence/Type Properties (based on whether entity itself is a type) */}
1136
- {occurrenceProperties.length > 0 && (
1275
+ {renderedOccurrenceProperties.length > 0 && (
1137
1276
  <>
1138
- {(isTypeEntity || (typeProperties && typeProperties.psets.length > 0)) && (
1277
+ {(renderedIsTypeEntity || (renderedTypeProperties && renderedTypeProperties.psets.length > 0)) && (
1139
1278
  <div className="flex items-center gap-2 px-1 pb-0.5 text-[11px] text-zinc-500 dark:text-zinc-400 uppercase tracking-wider font-semibold">
1140
- {isTypeEntity ? (
1279
+ {renderedIsTypeEntity ? (
1141
1280
  <>
1142
1281
  <Building2 className="h-3 w-3 shrink-0 text-indigo-500" />
1143
1282
  Type Properties:
@@ -1145,83 +1284,83 @@ export function PropertiesPanel() {
1145
1284
  ) : 'Occurrence Properties:'}
1146
1285
  </div>
1147
1286
  )}
1148
- {occurrenceProperties.map((pset: PropertySet) => (
1287
+ {renderedOccurrenceProperties.map((pset: PropertySet) => (
1149
1288
  <PropertySetCard
1150
1289
  key={`occ-${pset.name}`}
1151
1290
  pset={pset}
1152
1291
  modelId={selectedEntity?.modelId}
1153
1292
  entityId={selectedEntity?.expressId}
1154
- enableEditing={editMode}
1155
- isTypeProperty={isTypeEntity}
1156
- typeEditScope={isTypeEntity ? typeEditImpact ?? undefined : undefined}
1293
+ enableEditing={editMode && !isNativeLazySelection}
1294
+ isTypeProperty={renderedIsTypeEntity}
1295
+ typeEditScope={renderedIsTypeEntity ? renderedTypeEditImpact ?? undefined : undefined}
1157
1296
  />
1158
1297
  ))}
1159
1298
  </>
1160
1299
  )}
1161
1300
 
1162
1301
  {/* Inherited Type Properties */}
1163
- {inheritedTypeProperties.length > 0 && typeProperties && (
1302
+ {renderedInheritedTypeProperties.length > 0 && renderedTypeProperties && (
1164
1303
  <>
1165
- {occurrenceProperties.length > 0 && (
1304
+ {renderedOccurrenceProperties.length > 0 && (
1166
1305
  <div className="border-t border-indigo-200 dark:border-indigo-800/50 pt-2 mt-2" />
1167
1306
  )}
1168
1307
  <div className="flex items-center gap-2 px-1 pb-0.5 text-[11px] text-indigo-600/70 dark:text-indigo-400/60 uppercase tracking-wider font-semibold">
1169
1308
  <Building2 className="h-3 w-3 shrink-0" />
1170
- <span className="truncate">Type Properties ({typeProperties.typeName})</span>
1309
+ <span className="truncate">Type Properties ({renderedTypeProperties.typeName})</span>
1171
1310
  </div>
1172
- {inheritedTypeProperties.map((pset: PropertySet) => (
1311
+ {renderedInheritedTypeProperties.map((pset: PropertySet) => (
1173
1312
  <PropertySetCard
1174
1313
  key={`type-${pset.name}`}
1175
1314
  pset={pset}
1176
1315
  modelId={selectedEntity?.modelId}
1177
- entityId={typeProperties.typeId}
1178
- enableEditing={editMode}
1316
+ entityId={renderedTypeProperties.typeId}
1317
+ enableEditing={editMode && !isNativeLazySelection}
1179
1318
  isTypeProperty
1180
- typeEditScope={typeEditImpact?.mode === 'inherited' ? typeEditImpact : undefined}
1319
+ typeEditScope={renderedTypeEditImpact?.mode === 'inherited' ? renderedTypeEditImpact : undefined}
1181
1320
  />
1182
1321
  ))}
1183
1322
  </>
1184
1323
  )}
1185
1324
 
1186
1325
  {/* Classifications */}
1187
- {classifications.length > 0 && (
1326
+ {renderedClassifications.length > 0 && (
1188
1327
  <>
1189
- {mergedProperties.length > 0 && (
1328
+ {renderedMergedProperties.length > 0 && (
1190
1329
  <div className="border-t border-zinc-200 dark:border-zinc-800 pt-2 mt-2" />
1191
1330
  )}
1192
- {classifications.map((classification, i) => (
1331
+ {renderedClassifications.map((classification, i) => (
1193
1332
  <ClassificationCard key={`class-${i}`} classification={classification} />
1194
1333
  ))}
1195
1334
  </>
1196
1335
  )}
1197
1336
 
1198
1337
  {/* Materials */}
1199
- {materialInfo && (
1338
+ {renderedMaterialInfo && (
1200
1339
  <>
1201
- {(mergedProperties.length > 0 || classifications.length > 0) && (
1340
+ {(renderedMergedProperties.length > 0 || renderedClassifications.length > 0) && (
1202
1341
  <div className="border-t border-zinc-200 dark:border-zinc-800 pt-2 mt-2" />
1203
1342
  )}
1204
- <MaterialCard material={materialInfo} />
1343
+ <MaterialCard material={renderedMaterialInfo} />
1205
1344
  </>
1206
1345
  )}
1207
1346
 
1208
1347
  {/* Documents */}
1209
- {documents.length > 0 && (
1348
+ {renderedDocuments.length > 0 && (
1210
1349
  <>
1211
- {(mergedProperties.length > 0 || classifications.length > 0 || materialInfo) && (
1350
+ {(renderedMergedProperties.length > 0 || renderedClassifications.length > 0 || renderedMaterialInfo) && (
1212
1351
  <div className="border-t border-zinc-200 dark:border-zinc-800 pt-2 mt-2" />
1213
1352
  )}
1214
- {documents.map((doc, i) => (
1353
+ {renderedDocuments.map((doc, i) => (
1215
1354
  <DocumentCard key={`doc-${i}`} document={doc} />
1216
1355
  ))}
1217
1356
  </>
1218
1357
  )}
1219
1358
 
1220
1359
  {/* Relationships */}
1221
- {entityRelationships && (
1360
+ {renderedEntityRelationships && (
1222
1361
  <>
1223
1362
  <div className="border-t border-zinc-200 dark:border-zinc-800 pt-2 mt-2" />
1224
- <RelationshipsCard relationships={entityRelationships} />
1363
+ <RelationshipsCard relationships={renderedEntityRelationships} />
1225
1364
  </>
1226
1365
  )}
1227
1366
  </div>
@@ -1229,11 +1368,11 @@ export function PropertiesPanel() {
1229
1368
  </TabsContent>
1230
1369
 
1231
1370
  <TabsContent value="quantities" className="m-0 p-3 overflow-hidden">
1232
- {quantities.length === 0 ? (
1371
+ {renderedQuantities.length === 0 ? (
1233
1372
  <p className="text-sm text-zinc-500 dark:text-zinc-500 text-center py-8 font-mono">No quantities</p>
1234
1373
  ) : (
1235
1374
  <div className="space-y-3 w-full overflow-hidden">
1236
- {quantities.map((qset: QuantitySet) => (
1375
+ {renderedQuantities.map((qset: QuantitySet) => (
1237
1376
  <QuantitySetCard key={qset.name} qset={qset} />
1238
1377
  ))}
1239
1378
  </div>
@@ -1246,11 +1385,11 @@ export function PropertiesPanel() {
1246
1385
  entityType={entityType}
1247
1386
  modelId={selectedEntity.modelId}
1248
1387
  entityId={selectedEntity.expressId}
1249
- existingPsets={mergedProperties.map(p => p.name)}
1250
- existingProps={existingProps}
1251
- existingQsets={quantities.map(q => q.name)}
1252
- existingQuants={existingQuants}
1253
- existingAttributes={existingAttributeNames}
1388
+ existingPsets={renderedMergedProperties.map(p => p.name)}
1389
+ existingProps={renderedExistingProps}
1390
+ existingQsets={renderedQuantities.map(q => q.name)}
1391
+ existingQuants={renderedExistingQuants}
1392
+ existingAttributes={renderedExistingAttributeNames}
1254
1393
  />
1255
1394
  )}
1256
1395
  </TabsContent>
@@ -48,10 +48,13 @@ import {
48
48
  DialogDescription,
49
49
  } from '@/components/ui/dialog';
50
50
  import { ScrollArea } from '@/components/ui/scroll-area';
51
+ import { toast } from '@/components/ui/toast';
52
+ import { buildDesktopUpgradeUrl, hasDesktopFeatureAccess } from '@/lib/desktop-product';
51
53
  import { cn, formatDuration } from '@/lib/utils';
52
54
  import { useViewerStore } from '@/store';
53
55
  import { useSandbox } from '@/hooks/useSandbox';
54
56
  import { SCRIPT_TEMPLATES } from '@/lib/scripts/templates';
57
+ import { navigateToPath } from '@/services/app-navigation';
55
58
  import { CodeEditor } from './CodeEditor';
56
59
  import { ChatPanel } from './ChatPanel';
57
60
  import type { LogEntry } from '@/store/slices/scriptSlice';
@@ -141,6 +144,8 @@ export function ScriptPanel({ onClose }: ScriptPanelProps) {
141
144
  const [outputCollapsed, setOutputCollapsed] = useState(false);
142
145
  const chatPanelVisible = useViewerStore((s) => s.chatPanelVisible);
143
146
  const setChatPanelVisible = useViewerStore((s) => s.setChatPanelVisible);
147
+ const desktopEntitlement = useViewerStore((s) => s.desktopEntitlement);
148
+ const canUseAiAssistant = hasDesktopFeatureAccess(desktopEntitlement, 'ai_assistant');
144
149
 
145
150
  // Chat panel width (px) — resizable via drag handle
146
151
  const [chatWidth, setChatWidth] = useState(380);
@@ -150,14 +155,27 @@ export function ScriptPanel({ onClose }: ScriptPanelProps) {
150
155
  // Open chat by default when script panel mounts
151
156
  useEffect(() => {
152
157
  try {
153
- if (localStorage.getItem('ifc-lite-chat-panel-visible') === null) {
158
+ if (canUseAiAssistant && localStorage.getItem('ifc-lite-chat-panel-visible') === null) {
154
159
  setChatPanelVisible(true);
155
160
  }
156
161
  } catch {
157
- setChatPanelVisible(true);
162
+ if (canUseAiAssistant) {
163
+ setChatPanelVisible(true);
164
+ }
158
165
  }
159
166
  return () => { cleanupChatDragRef.current?.(); };
160
- }, [setChatPanelVisible]);
167
+ }, [canUseAiAssistant, setChatPanelVisible]);
168
+
169
+ useEffect(() => {
170
+ if (!canUseAiAssistant && chatPanelVisible) {
171
+ setChatPanelVisible(false);
172
+ }
173
+ }, [canUseAiAssistant, chatPanelVisible, setChatPanelVisible]);
174
+
175
+ const promptAiUpgrade = useCallback(() => {
176
+ toast.info('AI assistant is available with Desktop Pro');
177
+ navigateToPath(buildDesktopUpgradeUrl());
178
+ }, []);
161
179
 
162
180
  const handleChatResizeStart = useCallback((e: React.MouseEvent) => {
163
181
  e.preventDefault();
@@ -223,6 +241,10 @@ export function ScriptPanel({ onClose }: ScriptPanelProps) {
223
241
 
224
242
  const handleFixWithLlm = useCallback(() => {
225
243
  if (!lastError) return;
244
+ if (!canUseAiAssistant) {
245
+ promptAiUpgrade();
246
+ return;
247
+ }
226
248
  setChatPanelVisible(true);
227
249
  const state = useViewerStore.getState();
228
250
  queueChatRepairRequest({
@@ -230,11 +252,15 @@ export function ScriptPanel({ onClose }: ScriptPanelProps) {
230
252
  diagnostics: state.scriptLastDiagnostics,
231
253
  reason: lastError.startsWith('Preflight validation failed:') ? 'preflight' : 'runtime',
232
254
  });
233
- }, [lastError, queueChatRepairRequest, setChatPanelVisible]);
255
+ }, [canUseAiAssistant, lastError, promptAiUpgrade, queueChatRepairRequest, setChatPanelVisible]);
234
256
 
235
257
  const toggleChat = useCallback(() => {
258
+ if (!canUseAiAssistant) {
259
+ promptAiUpgrade();
260
+ return;
261
+ }
236
262
  setChatPanelVisible(!chatPanelVisible);
237
- }, [chatPanelVisible, setChatPanelVisible]);
263
+ }, [canUseAiAssistant, chatPanelVisible, promptAiUpgrade, setChatPanelVisible]);
238
264
 
239
265
  return (
240
266
  <div className="h-full flex bg-background">
@@ -289,12 +315,12 @@ export function ScriptPanel({ onClose }: ScriptPanelProps) {
289
315
  variant={chatPanelVisible ? 'default' : 'ghost'}
290
316
  size="icon-xs"
291
317
  onClick={toggleChat}
292
- className={cn(chatPanelVisible && 'bg-blue-500 hover:bg-blue-600 text-white')}
318
+ className={cn(canUseAiAssistant && chatPanelVisible && 'bg-blue-500 hover:bg-blue-600 text-white')}
293
319
  >
294
320
  <Bot className="h-3.5 w-3.5" />
295
321
  </Button>
296
322
  </TooltipTrigger>
297
- <TooltipContent>{chatPanelVisible ? 'Hide AI Chat' : 'Show AI Chat'}</TooltipContent>
323
+ <TooltipContent>{canUseAiAssistant ? (chatPanelVisible ? 'Hide AI Chat' : 'Show AI Chat') : 'Desktop Pro required for AI Chat'}</TooltipContent>
298
324
  </Tooltip>
299
325
 
300
326
  {onClose && (
@@ -460,7 +486,7 @@ export function ScriptPanel({ onClose }: ScriptPanelProps) {
460
486
  className="h-6 px-2 text-xs border-destructive/40 text-destructive bg-transparent hover:bg-destructive/10"
461
487
  onClick={handleFixWithLlm}
462
488
  >
463
- Fix with LLM
489
+ {canUseAiAssistant ? 'Fix with LLM' : 'Upgrade for AI Fix'}
464
490
  </Button>
465
491
  </div>
466
492
  </div>