@ifc-lite/viewer 1.17.2 → 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 (520) hide show
  1. package/.turbo/turbo-build.log +34 -24
  2. package/.turbo/turbo-typecheck.log +1 -42
  3. package/CHANGELOG.md +24 -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-DOG9_WPX.js +281 -0
  8. package/dist/assets/{browser-BDShTXzi.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/drawing-2d-gWfpdfYe.js +257 -0
  12. package/dist/assets/epsg-index.generated-BjJrt_0S.js +1 -0
  13. package/dist/assets/exporters-ChAtBmlj.js +80367 -0
  14. package/dist/assets/geometry.worker-BQ0rzNo-.js +1 -0
  15. package/dist/assets/ids-B4jTqB1O.js +1 -0
  16. package/dist/assets/ifc-lite_bg-BX4E7TX8.wasm +0 -0
  17. package/dist/assets/index-Co8E2-FE.js +106013 -0
  18. package/dist/assets/index-DckuDqlv.css +1 -0
  19. package/dist/assets/lens-CSASnhAL.js +1 -0
  20. package/dist/assets/maplibre-gl-CGLcoNXc.js +811 -0
  21. package/dist/assets/native-bridge-BRvbckFQ.js +429 -0
  22. package/dist/assets/{arrow2-bb-jcVEo.js → parquet-CEXmQNRO.js} +2 -2
  23. package/dist/assets/sandbox-DZiNLNMk.js +5933 -0
  24. package/dist/assets/server-client-BV8zHZ7Y.js +626 -0
  25. package/dist/assets/tauri-core-stub-D8Fa-u43.js +1 -0
  26. package/dist/assets/tauri-dialog-stub-r7Wksg7o.js +1 -0
  27. package/dist/assets/tauri-fs-stub-BdeRC7aK.js +1 -0
  28. package/dist/assets/wasm-bridge-g01g7T9b.js +1 -0
  29. package/dist/assets/zip-DBEtpeu6.js +12 -0
  30. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_0.json +1 -0
  31. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_1.json +1 -0
  32. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_10.json +1 -0
  33. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_11.json +1 -0
  34. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_12.json +1 -0
  35. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_13.json +1 -0
  36. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_14.json +1 -0
  37. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_15.json +1 -0
  38. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_16.json +1 -0
  39. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_17.json +1 -0
  40. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_18.json +1 -0
  41. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_19.json +1 -0
  42. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_2.json +1 -0
  43. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_20.json +1 -0
  44. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_21.json +1 -0
  45. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_22.json +1 -0
  46. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_23.json +1 -0
  47. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_24.json +1 -0
  48. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_25.json +1 -0
  49. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_26.json +1 -0
  50. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_27.json +1 -0
  51. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_3.json +1 -0
  52. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_4.json +1 -0
  53. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_5.json +1 -0
  54. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_6.json +1 -0
  55. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_7.json +1 -0
  56. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_8.json +1 -0
  57. package/dist/cesium/Assets/IAU2006_XYS/IAU2006_XYS_9.json +1 -0
  58. package/dist/cesium/Assets/Images/bing_maps_credit.png +0 -0
  59. package/dist/cesium/Assets/Images/cesium_credit.png +0 -0
  60. package/dist/cesium/Assets/Images/google_earth_credit.png +0 -0
  61. package/dist/cesium/Assets/Images/ion-credit.png +0 -0
  62. package/dist/cesium/Assets/Textures/LensFlare/DirtMask.jpg +0 -0
  63. package/dist/cesium/Assets/Textures/LensFlare/StarBurst.jpg +0 -0
  64. package/dist/cesium/Assets/Textures/NaturalEarthII/0/0/0.jpg +0 -0
  65. package/dist/cesium/Assets/Textures/NaturalEarthII/0/1/0.jpg +0 -0
  66. package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/0.jpg +0 -0
  67. package/dist/cesium/Assets/Textures/NaturalEarthII/1/0/1.jpg +0 -0
  68. package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/0.jpg +0 -0
  69. package/dist/cesium/Assets/Textures/NaturalEarthII/1/1/1.jpg +0 -0
  70. package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/0.jpg +0 -0
  71. package/dist/cesium/Assets/Textures/NaturalEarthII/1/2/1.jpg +0 -0
  72. package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/0.jpg +0 -0
  73. package/dist/cesium/Assets/Textures/NaturalEarthII/1/3/1.jpg +0 -0
  74. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/0.jpg +0 -0
  75. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/1.jpg +0 -0
  76. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/2.jpg +0 -0
  77. package/dist/cesium/Assets/Textures/NaturalEarthII/2/0/3.jpg +0 -0
  78. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/0.jpg +0 -0
  79. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/1.jpg +0 -0
  80. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/2.jpg +0 -0
  81. package/dist/cesium/Assets/Textures/NaturalEarthII/2/1/3.jpg +0 -0
  82. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/0.jpg +0 -0
  83. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/1.jpg +0 -0
  84. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/2.jpg +0 -0
  85. package/dist/cesium/Assets/Textures/NaturalEarthII/2/2/3.jpg +0 -0
  86. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/0.jpg +0 -0
  87. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/1.jpg +0 -0
  88. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/2.jpg +0 -0
  89. package/dist/cesium/Assets/Textures/NaturalEarthII/2/3/3.jpg +0 -0
  90. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/0.jpg +0 -0
  91. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/1.jpg +0 -0
  92. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/2.jpg +0 -0
  93. package/dist/cesium/Assets/Textures/NaturalEarthII/2/4/3.jpg +0 -0
  94. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/0.jpg +0 -0
  95. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/1.jpg +0 -0
  96. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/2.jpg +0 -0
  97. package/dist/cesium/Assets/Textures/NaturalEarthII/2/5/3.jpg +0 -0
  98. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/0.jpg +0 -0
  99. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/1.jpg +0 -0
  100. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/2.jpg +0 -0
  101. package/dist/cesium/Assets/Textures/NaturalEarthII/2/6/3.jpg +0 -0
  102. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/0.jpg +0 -0
  103. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/1.jpg +0 -0
  104. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/2.jpg +0 -0
  105. package/dist/cesium/Assets/Textures/NaturalEarthII/2/7/3.jpg +0 -0
  106. package/dist/cesium/Assets/Textures/NaturalEarthII/tilemapresource.xml +14 -0
  107. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mx.jpg +0 -0
  108. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_my.jpg +0 -0
  109. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_mz.jpg +0 -0
  110. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_px.jpg +0 -0
  111. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_py.jpg +0 -0
  112. package/dist/cesium/Assets/Textures/SkyBox/tycho2t3_80_pz.jpg +0 -0
  113. package/dist/cesium/Assets/Textures/maki/airfield.png +0 -0
  114. package/dist/cesium/Assets/Textures/maki/airport.png +0 -0
  115. package/dist/cesium/Assets/Textures/maki/alcohol-shop.png +0 -0
  116. package/dist/cesium/Assets/Textures/maki/america-football.png +0 -0
  117. package/dist/cesium/Assets/Textures/maki/art-gallery.png +0 -0
  118. package/dist/cesium/Assets/Textures/maki/bakery.png +0 -0
  119. package/dist/cesium/Assets/Textures/maki/bank.png +0 -0
  120. package/dist/cesium/Assets/Textures/maki/bar.png +0 -0
  121. package/dist/cesium/Assets/Textures/maki/baseball.png +0 -0
  122. package/dist/cesium/Assets/Textures/maki/basketball.png +0 -0
  123. package/dist/cesium/Assets/Textures/maki/beer.png +0 -0
  124. package/dist/cesium/Assets/Textures/maki/bicycle.png +0 -0
  125. package/dist/cesium/Assets/Textures/maki/building.png +0 -0
  126. package/dist/cesium/Assets/Textures/maki/bus.png +0 -0
  127. package/dist/cesium/Assets/Textures/maki/cafe.png +0 -0
  128. package/dist/cesium/Assets/Textures/maki/camera.png +0 -0
  129. package/dist/cesium/Assets/Textures/maki/campsite.png +0 -0
  130. package/dist/cesium/Assets/Textures/maki/car.png +0 -0
  131. package/dist/cesium/Assets/Textures/maki/cemetery.png +0 -0
  132. package/dist/cesium/Assets/Textures/maki/cesium.png +0 -0
  133. package/dist/cesium/Assets/Textures/maki/chemist.png +0 -0
  134. package/dist/cesium/Assets/Textures/maki/cinema.png +0 -0
  135. package/dist/cesium/Assets/Textures/maki/circle-stroked.png +0 -0
  136. package/dist/cesium/Assets/Textures/maki/circle.png +0 -0
  137. package/dist/cesium/Assets/Textures/maki/city.png +0 -0
  138. package/dist/cesium/Assets/Textures/maki/clothing-store.png +0 -0
  139. package/dist/cesium/Assets/Textures/maki/college.png +0 -0
  140. package/dist/cesium/Assets/Textures/maki/commercial.png +0 -0
  141. package/dist/cesium/Assets/Textures/maki/cricket.png +0 -0
  142. package/dist/cesium/Assets/Textures/maki/cross.png +0 -0
  143. package/dist/cesium/Assets/Textures/maki/dam.png +0 -0
  144. package/dist/cesium/Assets/Textures/maki/danger.png +0 -0
  145. package/dist/cesium/Assets/Textures/maki/disability.png +0 -0
  146. package/dist/cesium/Assets/Textures/maki/dog-park.png +0 -0
  147. package/dist/cesium/Assets/Textures/maki/embassy.png +0 -0
  148. package/dist/cesium/Assets/Textures/maki/emergency-telephone.png +0 -0
  149. package/dist/cesium/Assets/Textures/maki/entrance.png +0 -0
  150. package/dist/cesium/Assets/Textures/maki/farm.png +0 -0
  151. package/dist/cesium/Assets/Textures/maki/fast-food.png +0 -0
  152. package/dist/cesium/Assets/Textures/maki/ferry.png +0 -0
  153. package/dist/cesium/Assets/Textures/maki/fire-station.png +0 -0
  154. package/dist/cesium/Assets/Textures/maki/fuel.png +0 -0
  155. package/dist/cesium/Assets/Textures/maki/garden.png +0 -0
  156. package/dist/cesium/Assets/Textures/maki/gift.png +0 -0
  157. package/dist/cesium/Assets/Textures/maki/golf.png +0 -0
  158. package/dist/cesium/Assets/Textures/maki/grocery.png +0 -0
  159. package/dist/cesium/Assets/Textures/maki/hairdresser.png +0 -0
  160. package/dist/cesium/Assets/Textures/maki/harbor.png +0 -0
  161. package/dist/cesium/Assets/Textures/maki/heart.png +0 -0
  162. package/dist/cesium/Assets/Textures/maki/heliport.png +0 -0
  163. package/dist/cesium/Assets/Textures/maki/hospital.png +0 -0
  164. package/dist/cesium/Assets/Textures/maki/ice-cream.png +0 -0
  165. package/dist/cesium/Assets/Textures/maki/industrial.png +0 -0
  166. package/dist/cesium/Assets/Textures/maki/land-use.png +0 -0
  167. package/dist/cesium/Assets/Textures/maki/laundry.png +0 -0
  168. package/dist/cesium/Assets/Textures/maki/library.png +0 -0
  169. package/dist/cesium/Assets/Textures/maki/lighthouse.png +0 -0
  170. package/dist/cesium/Assets/Textures/maki/lodging.png +0 -0
  171. package/dist/cesium/Assets/Textures/maki/logging.png +0 -0
  172. package/dist/cesium/Assets/Textures/maki/london-underground.png +0 -0
  173. package/dist/cesium/Assets/Textures/maki/marker-stroked.png +0 -0
  174. package/dist/cesium/Assets/Textures/maki/marker.png +0 -0
  175. package/dist/cesium/Assets/Textures/maki/minefield.png +0 -0
  176. package/dist/cesium/Assets/Textures/maki/mobilephone.png +0 -0
  177. package/dist/cesium/Assets/Textures/maki/monument.png +0 -0
  178. package/dist/cesium/Assets/Textures/maki/museum.png +0 -0
  179. package/dist/cesium/Assets/Textures/maki/music.png +0 -0
  180. package/dist/cesium/Assets/Textures/maki/oil-well.png +0 -0
  181. package/dist/cesium/Assets/Textures/maki/park.png +0 -0
  182. package/dist/cesium/Assets/Textures/maki/park2.png +0 -0
  183. package/dist/cesium/Assets/Textures/maki/parking-garage.png +0 -0
  184. package/dist/cesium/Assets/Textures/maki/parking.png +0 -0
  185. package/dist/cesium/Assets/Textures/maki/pharmacy.png +0 -0
  186. package/dist/cesium/Assets/Textures/maki/pitch.png +0 -0
  187. package/dist/cesium/Assets/Textures/maki/place-of-worship.png +0 -0
  188. package/dist/cesium/Assets/Textures/maki/playground.png +0 -0
  189. package/dist/cesium/Assets/Textures/maki/police.png +0 -0
  190. package/dist/cesium/Assets/Textures/maki/polling-place.png +0 -0
  191. package/dist/cesium/Assets/Textures/maki/post.png +0 -0
  192. package/dist/cesium/Assets/Textures/maki/prison.png +0 -0
  193. package/dist/cesium/Assets/Textures/maki/rail-above.png +0 -0
  194. package/dist/cesium/Assets/Textures/maki/rail-light.png +0 -0
  195. package/dist/cesium/Assets/Textures/maki/rail-metro.png +0 -0
  196. package/dist/cesium/Assets/Textures/maki/rail-underground.png +0 -0
  197. package/dist/cesium/Assets/Textures/maki/rail.png +0 -0
  198. package/dist/cesium/Assets/Textures/maki/religious-christian.png +0 -0
  199. package/dist/cesium/Assets/Textures/maki/religious-jewish.png +0 -0
  200. package/dist/cesium/Assets/Textures/maki/religious-muslim.png +0 -0
  201. package/dist/cesium/Assets/Textures/maki/restaurant.png +0 -0
  202. package/dist/cesium/Assets/Textures/maki/roadblock.png +0 -0
  203. package/dist/cesium/Assets/Textures/maki/rocket.png +0 -0
  204. package/dist/cesium/Assets/Textures/maki/school.png +0 -0
  205. package/dist/cesium/Assets/Textures/maki/scooter.png +0 -0
  206. package/dist/cesium/Assets/Textures/maki/shop.png +0 -0
  207. package/dist/cesium/Assets/Textures/maki/skiing.png +0 -0
  208. package/dist/cesium/Assets/Textures/maki/slaughterhouse.png +0 -0
  209. package/dist/cesium/Assets/Textures/maki/soccer.png +0 -0
  210. package/dist/cesium/Assets/Textures/maki/square-stroked.png +0 -0
  211. package/dist/cesium/Assets/Textures/maki/square.png +0 -0
  212. package/dist/cesium/Assets/Textures/maki/star-stroked.png +0 -0
  213. package/dist/cesium/Assets/Textures/maki/star.png +0 -0
  214. package/dist/cesium/Assets/Textures/maki/suitcase.png +0 -0
  215. package/dist/cesium/Assets/Textures/maki/swimming.png +0 -0
  216. package/dist/cesium/Assets/Textures/maki/telephone.png +0 -0
  217. package/dist/cesium/Assets/Textures/maki/tennis.png +0 -0
  218. package/dist/cesium/Assets/Textures/maki/theatre.png +0 -0
  219. package/dist/cesium/Assets/Textures/maki/toilets.png +0 -0
  220. package/dist/cesium/Assets/Textures/maki/town-hall.png +0 -0
  221. package/dist/cesium/Assets/Textures/maki/town.png +0 -0
  222. package/dist/cesium/Assets/Textures/maki/triangle-stroked.png +0 -0
  223. package/dist/cesium/Assets/Textures/maki/triangle.png +0 -0
  224. package/dist/cesium/Assets/Textures/maki/village.png +0 -0
  225. package/dist/cesium/Assets/Textures/maki/warehouse.png +0 -0
  226. package/dist/cesium/Assets/Textures/maki/waste-basket.png +0 -0
  227. package/dist/cesium/Assets/Textures/maki/water.png +0 -0
  228. package/dist/cesium/Assets/Textures/maki/wetland.png +0 -0
  229. package/dist/cesium/Assets/Textures/maki/zoo.png +0 -0
  230. package/dist/cesium/Assets/Textures/moonSmall.jpg +0 -0
  231. package/dist/cesium/Assets/Textures/pin.svg +1 -0
  232. package/dist/cesium/Assets/Textures/waterNormals.jpg +0 -0
  233. package/dist/cesium/Assets/Textures/waterNormalsSmall.jpg +0 -0
  234. package/dist/cesium/Assets/approximateTerrainHeights.json +1 -0
  235. package/dist/cesium/ThirdParty/Workers/package.json +1 -0
  236. package/dist/cesium/ThirdParty/Workers/zip-web-worker.js +1 -0
  237. package/dist/cesium/ThirdParty/basis_transcoder.wasm +0 -0
  238. package/dist/cesium/ThirdParty/draco_decoder.wasm +0 -0
  239. package/dist/cesium/ThirdParty/google-earth-dbroot-parser.js +1 -0
  240. package/dist/cesium/ThirdParty/wasm_splats_bg.wasm +0 -0
  241. package/dist/cesium/ThirdParty/zip-module.wasm +0 -0
  242. package/dist/cesium/Widgets/Animation/Animation.css +127 -0
  243. package/dist/cesium/Widgets/Animation/lighter.css +70 -0
  244. package/dist/cesium/Widgets/BaseLayerPicker/BaseLayerPicker.css +108 -0
  245. package/dist/cesium/Widgets/BaseLayerPicker/lighter.css +22 -0
  246. package/dist/cesium/Widgets/Cesium3DTilesInspector/Cesium3DTilesInspector.css +102 -0
  247. package/dist/cesium/Widgets/CesiumInspector/CesiumInspector.css +113 -0
  248. package/dist/cesium/Widgets/CesiumWidget/CesiumWidget.css +119 -0
  249. package/dist/cesium/Widgets/CesiumWidget/lighter.css +14 -0
  250. package/dist/cesium/Widgets/FullscreenButton/FullscreenButton.css +8 -0
  251. package/dist/cesium/Widgets/Geocoder/Geocoder.css +70 -0
  252. package/dist/cesium/Widgets/Geocoder/lighter.css +17 -0
  253. package/dist/cesium/Widgets/I3SBuildingSceneLayerExplorer/I3SBuildingSceneLayerExplorer.css +27 -0
  254. package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldHillshade.png +0 -0
  255. package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldImagery.png +0 -0
  256. package/dist/cesium/Widgets/Images/ImageryProviders/ArcGisMapServiceWorldOcean.png +0 -0
  257. package/dist/cesium/Widgets/Images/ImageryProviders/azureAerial.png +0 -0
  258. package/dist/cesium/Widgets/Images/ImageryProviders/azureRoads.png +0 -0
  259. package/dist/cesium/Widgets/Images/ImageryProviders/bingAerial.png +0 -0
  260. package/dist/cesium/Widgets/Images/ImageryProviders/bingAerialLabels.png +0 -0
  261. package/dist/cesium/Widgets/Images/ImageryProviders/bingRoads.png +0 -0
  262. package/dist/cesium/Widgets/Images/ImageryProviders/blueMarble.png +0 -0
  263. package/dist/cesium/Widgets/Images/ImageryProviders/earthAtNight.png +0 -0
  264. package/dist/cesium/Widgets/Images/ImageryProviders/googleContour.png +0 -0
  265. package/dist/cesium/Widgets/Images/ImageryProviders/googleRoadmap.png +0 -0
  266. package/dist/cesium/Widgets/Images/ImageryProviders/googleSatellite.png +0 -0
  267. package/dist/cesium/Widgets/Images/ImageryProviders/googleSatelliteLabels.png +0 -0
  268. package/dist/cesium/Widgets/Images/ImageryProviders/mapQuestOpenStreetMap.png +0 -0
  269. package/dist/cesium/Widgets/Images/ImageryProviders/mapboxSatellite.png +0 -0
  270. package/dist/cesium/Widgets/Images/ImageryProviders/mapboxStreets.png +0 -0
  271. package/dist/cesium/Widgets/Images/ImageryProviders/mapboxTerrain.png +0 -0
  272. package/dist/cesium/Widgets/Images/ImageryProviders/naturalEarthII.png +0 -0
  273. package/dist/cesium/Widgets/Images/ImageryProviders/openStreetMap.png +0 -0
  274. package/dist/cesium/Widgets/Images/ImageryProviders/sentinel-2.png +0 -0
  275. package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmooth.png +0 -0
  276. package/dist/cesium/Widgets/Images/ImageryProviders/stadiaAlidadeSmoothDark.png +0 -0
  277. package/dist/cesium/Widgets/Images/ImageryProviders/stamenToner.png +0 -0
  278. package/dist/cesium/Widgets/Images/ImageryProviders/stamenWatercolor.png +0 -0
  279. package/dist/cesium/Widgets/Images/NavigationHelp/Mouse.svg +84 -0
  280. package/dist/cesium/Widgets/Images/NavigationHelp/MouseLeft.svg +76 -0
  281. package/dist/cesium/Widgets/Images/NavigationHelp/MouseMiddle.svg +76 -0
  282. package/dist/cesium/Widgets/Images/NavigationHelp/MouseRight.svg +76 -0
  283. package/dist/cesium/Widgets/Images/NavigationHelp/Touch.svg +120 -0
  284. package/dist/cesium/Widgets/Images/NavigationHelp/TouchDrag.svg +129 -0
  285. package/dist/cesium/Widgets/Images/NavigationHelp/TouchRotate.svg +76 -0
  286. package/dist/cesium/Widgets/Images/NavigationHelp/TouchTilt.svg +135 -0
  287. package/dist/cesium/Widgets/Images/NavigationHelp/TouchZoom.svg +74 -0
  288. package/dist/cesium/Widgets/Images/TerrainProviders/CesiumWorldTerrain.png +0 -0
  289. package/dist/cesium/Widgets/Images/TerrainProviders/Ellipsoid.png +0 -0
  290. package/dist/cesium/Widgets/Images/TimelineIcons.png +0 -0
  291. package/dist/cesium/Widgets/Images/info-loading.gif +0 -0
  292. package/dist/cesium/Widgets/InfoBox/InfoBox.css +92 -0
  293. package/dist/cesium/Widgets/InfoBox/InfoBoxDescription.css +178 -0
  294. package/dist/cesium/Widgets/NavigationHelpButton/NavigationHelpButton.css +93 -0
  295. package/dist/cesium/Widgets/NavigationHelpButton/lighter.css +38 -0
  296. package/dist/cesium/Widgets/PerformanceWatchdog/PerformanceWatchdog.css +15 -0
  297. package/dist/cesium/Widgets/ProjectionPicker/ProjectionPicker.css +38 -0
  298. package/dist/cesium/Widgets/SceneModePicker/SceneModePicker.css +56 -0
  299. package/dist/cesium/Widgets/SelectionIndicator/SelectionIndicator.css +20 -0
  300. package/dist/cesium/Widgets/Timeline/Timeline.css +103 -0
  301. package/dist/cesium/Widgets/Timeline/lighter.css +23 -0
  302. package/dist/cesium/Widgets/VRButton/VRButton.css +8 -0
  303. package/dist/cesium/Widgets/Viewer/Viewer.css +107 -0
  304. package/dist/cesium/Widgets/VoxelInspector/VoxelInspector.css +16 -0
  305. package/dist/cesium/Widgets/lighter.css +237 -0
  306. package/dist/cesium/Widgets/lighterShared.css +46 -0
  307. package/dist/cesium/Widgets/shared.css +103 -0
  308. package/dist/cesium/Widgets/widgets.css +1342 -0
  309. package/dist/cesium/Workers/chunk-23ZQ2IVV.js +29 -0
  310. package/dist/cesium/Workers/chunk-2EQO3Q56.js +26 -0
  311. package/dist/cesium/Workers/chunk-2MJIIVP4.js +26 -0
  312. package/dist/cesium/Workers/chunk-2TE5NTVD.js +26 -0
  313. package/dist/cesium/Workers/chunk-2ZBHLJST.js +26 -0
  314. package/dist/cesium/Workers/chunk-5TJMAQVL.js +26 -0
  315. package/dist/cesium/Workers/chunk-6BD4U3VO.js +26 -0
  316. package/dist/cesium/Workers/chunk-7TVGLKQF.js +26 -0
  317. package/dist/cesium/Workers/chunk-BTSYJ5XU.js +26 -0
  318. package/dist/cesium/Workers/chunk-BXMEEOCS.js +63 -0
  319. package/dist/cesium/Workers/chunk-BYLCY7GP.js +29 -0
  320. package/dist/cesium/Workers/chunk-CTHM3W6I.js +26 -0
  321. package/dist/cesium/Workers/chunk-CUUSNIVQ.js +26 -0
  322. package/dist/cesium/Workers/chunk-E3JOOS3S.js +26 -0
  323. package/dist/cesium/Workers/chunk-E7KYDCM5.js +26 -0
  324. package/dist/cesium/Workers/chunk-EDVBB7SS.js +27 -0
  325. package/dist/cesium/Workers/chunk-EFBN7QNX.js +26 -0
  326. package/dist/cesium/Workers/chunk-EQ4YRVWL.js +26 -0
  327. package/dist/cesium/Workers/chunk-F6PRE7D6.js +26 -0
  328. package/dist/cesium/Workers/chunk-FC4ZZ65J.js +26 -0
  329. package/dist/cesium/Workers/chunk-FFBVWF2L.js +26 -0
  330. package/dist/cesium/Workers/chunk-GBAA6GVX.js +26 -0
  331. package/dist/cesium/Workers/chunk-ICALLYLG.js +26 -0
  332. package/dist/cesium/Workers/chunk-ILRYTWTP.js +26 -0
  333. package/dist/cesium/Workers/chunk-IRNLBSEJ.js +26 -0
  334. package/dist/cesium/Workers/chunk-IX4VMHEV.js +26 -0
  335. package/dist/cesium/Workers/chunk-L6QHHACZ.js +26 -0
  336. package/dist/cesium/Workers/chunk-LI2ZSORM.js +26 -0
  337. package/dist/cesium/Workers/chunk-LSLE2RL4.js +26 -0
  338. package/dist/cesium/Workers/chunk-M4HLDBCG.js +26 -0
  339. package/dist/cesium/Workers/chunk-MJHHSGEH.js +26 -0
  340. package/dist/cesium/Workers/chunk-NMVKML6W.js +26 -0
  341. package/dist/cesium/Workers/chunk-OCWJRAXS.js +26 -0
  342. package/dist/cesium/Workers/chunk-OIRKANTH.js +26 -0
  343. package/dist/cesium/Workers/chunk-OIT7J4IC.js +26 -0
  344. package/dist/cesium/Workers/chunk-OLZ3FYUM.js +26 -0
  345. package/dist/cesium/Workers/chunk-Q5BPHJQF.js +26 -0
  346. package/dist/cesium/Workers/chunk-QFM5DCMQ.js +26 -0
  347. package/dist/cesium/Workers/chunk-QKUIYMGC.js +28 -0
  348. package/dist/cesium/Workers/chunk-S44JILQT.js +26 -0
  349. package/dist/cesium/Workers/chunk-SLT4J352.js +26 -0
  350. package/dist/cesium/Workers/chunk-SQMIIXB7.js +26 -0
  351. package/dist/cesium/Workers/chunk-TJ4XLGBQ.js +26 -0
  352. package/dist/cesium/Workers/chunk-TNSUQXWK.js +27 -0
  353. package/dist/cesium/Workers/chunk-UBOGZS7F.js +26 -0
  354. package/dist/cesium/Workers/chunk-V3OSTMM6.js +26 -0
  355. package/dist/cesium/Workers/chunk-V7QEYVP3.js +26 -0
  356. package/dist/cesium/Workers/chunk-VUKYSU4H.js +26 -0
  357. package/dist/cesium/Workers/chunk-W37FE5GR.js +26 -0
  358. package/dist/cesium/Workers/chunk-WBOV35NL.js +26 -0
  359. package/dist/cesium/Workers/chunk-WPMZLB3Y.js +26 -0
  360. package/dist/cesium/Workers/chunk-WWWZVEEH.js +26 -0
  361. package/dist/cesium/Workers/chunk-XFIQ5DEQ.js +28 -0
  362. package/dist/cesium/Workers/chunk-XQHLGIO7.js +26 -0
  363. package/dist/cesium/Workers/chunk-XUSCFAVF.js +26 -0
  364. package/dist/cesium/Workers/chunk-YP7I5QBZ.js +26 -0
  365. package/dist/cesium/Workers/chunk-Z3QF2EHT.js +26 -0
  366. package/dist/cesium/Workers/combineGeometry.js +26 -0
  367. package/dist/cesium/Workers/createBoxGeometry.js +26 -0
  368. package/dist/cesium/Workers/createBoxOutlineGeometry.js +26 -0
  369. package/dist/cesium/Workers/createCircleGeometry.js +26 -0
  370. package/dist/cesium/Workers/createCircleOutlineGeometry.js +26 -0
  371. package/dist/cesium/Workers/createCoplanarPolygonGeometry.js +26 -0
  372. package/dist/cesium/Workers/createCoplanarPolygonOutlineGeometry.js +26 -0
  373. package/dist/cesium/Workers/createCorridorGeometry.js +26 -0
  374. package/dist/cesium/Workers/createCorridorOutlineGeometry.js +26 -0
  375. package/dist/cesium/Workers/createCylinderGeometry.js +26 -0
  376. package/dist/cesium/Workers/createCylinderOutlineGeometry.js +26 -0
  377. package/dist/cesium/Workers/createEllipseGeometry.js +26 -0
  378. package/dist/cesium/Workers/createEllipseOutlineGeometry.js +26 -0
  379. package/dist/cesium/Workers/createEllipsoidGeometry.js +26 -0
  380. package/dist/cesium/Workers/createEllipsoidOutlineGeometry.js +26 -0
  381. package/dist/cesium/Workers/createFrustumGeometry.js +26 -0
  382. package/dist/cesium/Workers/createFrustumOutlineGeometry.js +26 -0
  383. package/dist/cesium/Workers/createGeometry.js +26 -0
  384. package/dist/cesium/Workers/createGroundPolylineGeometry.js +26 -0
  385. package/dist/cesium/Workers/createPlaneGeometry.js +26 -0
  386. package/dist/cesium/Workers/createPlaneOutlineGeometry.js +26 -0
  387. package/dist/cesium/Workers/createPolygonGeometry.js +26 -0
  388. package/dist/cesium/Workers/createPolygonOutlineGeometry.js +26 -0
  389. package/dist/cesium/Workers/createPolylineGeometry.js +26 -0
  390. package/dist/cesium/Workers/createPolylineVolumeGeometry.js +26 -0
  391. package/dist/cesium/Workers/createPolylineVolumeOutlineGeometry.js +26 -0
  392. package/dist/cesium/Workers/createRectangleGeometry.js +26 -0
  393. package/dist/cesium/Workers/createRectangleOutlineGeometry.js +26 -0
  394. package/dist/cesium/Workers/createSimplePolylineGeometry.js +26 -0
  395. package/dist/cesium/Workers/createSphereGeometry.js +26 -0
  396. package/dist/cesium/Workers/createSphereOutlineGeometry.js +26 -0
  397. package/dist/cesium/Workers/createTaskProcessorWorker.js +26 -0
  398. package/dist/cesium/Workers/createVectorTileClampedPolylines.js +26 -0
  399. package/dist/cesium/Workers/createVectorTileGeometries.js +26 -0
  400. package/dist/cesium/Workers/createVectorTilePoints.js +26 -0
  401. package/dist/cesium/Workers/createVectorTilePolygons.js +26 -0
  402. package/dist/cesium/Workers/createVectorTilePolylines.js +26 -0
  403. package/dist/cesium/Workers/createVerticesFromCesium3DTilesTerrain.js +26 -0
  404. package/dist/cesium/Workers/createVerticesFromGoogleEarthEnterpriseBuffer.js +26 -0
  405. package/dist/cesium/Workers/createVerticesFromHeightmap.js +26 -0
  406. package/dist/cesium/Workers/createVerticesFromQuantizedTerrainMesh.js +26 -0
  407. package/dist/cesium/Workers/createWallGeometry.js +26 -0
  408. package/dist/cesium/Workers/createWallOutlineGeometry.js +26 -0
  409. package/dist/cesium/Workers/decodeDraco.js +26 -0
  410. package/dist/cesium/Workers/decodeGoogleEarthEnterprisePacket.js +26 -0
  411. package/dist/cesium/Workers/decodeI3S.js +26 -0
  412. package/dist/cesium/Workers/gaussianSplatSorter.js +26 -0
  413. package/dist/cesium/Workers/gaussianSplatTextureGenerator.js +26 -0
  414. package/dist/cesium/Workers/incrementallyBuildTerrainPicker.js +26 -0
  415. package/dist/cesium/Workers/transcodeKTX2.js +56 -0
  416. package/dist/cesium/Workers/transferTypedArrayTest.js +26 -0
  417. package/dist/cesium/Workers/upsampleQuantizedTerrainMesh.js +26 -0
  418. package/dist/cesium/Workers/upsampleVerticesFromCesium3DTilesTerrain.js +26 -0
  419. package/dist/index.html +13 -2
  420. package/package.json +27 -19
  421. package/src/App.tsx +1 -17
  422. package/src/components/viewer/BCFPanel.tsx +46 -4
  423. package/src/components/viewer/CesiumOverlay.tsx +672 -0
  424. package/src/components/viewer/CesiumSettingsDialog.tsx +100 -0
  425. package/src/components/viewer/ChatPanel.tsx +54 -16
  426. package/src/components/viewer/CommandPalette.tsx +6 -1
  427. package/src/components/viewer/DesktopEntitlementBanner.tsx +74 -0
  428. package/src/components/viewer/ExportChangesButton.tsx +24 -4
  429. package/src/components/viewer/ExportDialog.tsx +38 -9
  430. package/src/components/viewer/HierarchyPanel.tsx +202 -6
  431. package/src/components/viewer/IDSPanel.tsx +52 -3
  432. package/src/components/viewer/KeyboardShortcutsDialog.tsx +1 -1
  433. package/src/components/viewer/MainToolbar.tsx +353 -27
  434. package/src/components/viewer/PropertiesPanel.tsx +306 -131
  435. package/src/components/viewer/ScriptPanel.tsx +34 -8
  436. package/src/components/viewer/Section2DPanel.tsx +3 -2
  437. package/src/components/viewer/SettingsPage.tsx +430 -0
  438. package/src/components/viewer/StatusBar.tsx +17 -1
  439. package/src/components/viewer/UpgradePage.tsx +6 -4
  440. package/src/components/viewer/ViewerLayout.tsx +47 -6
  441. package/src/components/viewer/Viewport.tsx +49 -8
  442. package/src/components/viewer/ViewportContainer.tsx +285 -32
  443. package/src/components/viewer/ViewportOverlays.tsx +129 -27
  444. package/src/components/viewer/hierarchy/treeDataBuilder.ts +2 -1
  445. package/src/components/viewer/properties/EpsgLookupDialog.tsx +418 -0
  446. package/src/components/viewer/properties/GeoreferencingPanel.tsx +703 -0
  447. package/src/components/viewer/properties/LocationMap.tsx +730 -0
  448. package/src/components/viewer/properties/ModelMetadataPanel.tsx +3 -70
  449. package/src/components/viewer/selectionHandlers.ts +4 -3
  450. package/src/components/viewer/useAnimationLoop.ts +4 -0
  451. package/src/components/viewer/useGeometryStreaming.ts +127 -40
  452. package/src/components/viewer/useMouseControls.ts +4 -1
  453. package/src/hooks/bcfIdLookup.ts +13 -11
  454. package/src/hooks/ids/idsColorSystem.ts +3 -8
  455. package/src/hooks/ingest/viewerModelIngest.ts +275 -0
  456. package/src/hooks/useIDS.ts +32 -17
  457. package/src/hooks/useIfc.ts +7 -1
  458. package/src/hooks/useIfcCache.ts +28 -15
  459. package/src/hooks/useIfcFederation.ts +59 -227
  460. package/src/hooks/useIfcLoader.ts +1656 -130
  461. package/src/hooks/useIfcServer.ts +0 -69
  462. package/src/lib/desktop/ClerkDesktopEntitlementSync.tsx +175 -0
  463. package/src/lib/desktop/desktopEntitlementEvents.ts +39 -0
  464. package/src/lib/desktop-entitlement.ts +45 -0
  465. package/src/lib/desktop-product.ts +124 -0
  466. package/src/lib/geo/cesium-bridge.ts +310 -0
  467. package/src/lib/geo/kmz-exporter.ts +112 -0
  468. package/src/lib/geo/reproject.ts +370 -0
  469. package/src/lib/lens/adapter.ts +3 -1
  470. package/src/lib/recent-files.ts +2 -1
  471. package/src/main.tsx +1 -0
  472. package/src/sdk/adapters/export-adapter.ts +14 -1
  473. package/src/sdk/adapters/viewer-adapter.ts +5 -9
  474. package/src/sdk/adapters/visibility-adapter.ts +6 -9
  475. package/src/services/analysis-extensions.ts +125 -0
  476. package/src/services/app-navigation.ts +13 -0
  477. package/src/services/bsdd.ts +53 -4
  478. package/src/services/cacheService.ts +1 -1
  479. package/src/services/desktop-cache.ts +43 -0
  480. package/src/services/desktop-export.ts +77 -0
  481. package/src/services/desktop-harness.ts +196 -0
  482. package/src/services/desktop-logger.ts +20 -0
  483. package/src/services/desktop-native-metadata.ts +207 -0
  484. package/src/services/desktop-panel-actions.ts +43 -0
  485. package/src/services/desktop-preferences.ts +44 -0
  486. package/src/services/file-dialog.ts +147 -0
  487. package/src/services/tauri-core-stub.ts +7 -0
  488. package/src/services/tauri-dialog-stub.ts +7 -0
  489. package/src/services/tauri-fs-stub.ts +7 -0
  490. package/src/store/basketVisibleSet.ts +3 -4
  491. package/src/store/globalId.ts +79 -0
  492. package/src/store/index.ts +41 -2
  493. package/src/store/slices/cesiumSlice.ts +122 -0
  494. package/src/store/slices/chatSlice.ts +5 -1
  495. package/src/store/slices/dataSlice.ts +139 -28
  496. package/src/store/slices/desktopEntitlementSlice.ts +86 -0
  497. package/src/store/slices/loadingSlice.ts +14 -2
  498. package/src/store/slices/modelSlice.ts +58 -3
  499. package/src/store/slices/mutationSlice.ts +178 -0
  500. package/src/store/slices/pinboardSlice.ts +4 -8
  501. package/src/store/types.ts +96 -2
  502. package/src/store.ts +1 -1
  503. package/src/utils/desktopModelSnapshot.ts +358 -0
  504. package/src/utils/ifcConfig.ts +6 -1
  505. package/src/utils/nativeSpatialDataStore.ts +250 -0
  506. package/src/utils/serverDataModel.ts +4 -0
  507. package/src/utils/spatialHierarchy.ts +10 -11
  508. package/vite.config.ts +41 -0
  509. package/dist/assets/Arrow.dom-BhOg9lpn.js +0 -20
  510. package/dist/assets/arrow2_bg-BlXl-cSQ.js +0 -1
  511. package/dist/assets/basketViewActivator-BRG5DBmM.js +0 -1
  512. package/dist/assets/desktop-cache-oPzaWXYE.js +0 -1
  513. package/dist/assets/geometry.worker-kgiT_Qhh.js +0 -1
  514. package/dist/assets/ifc-lite_bg-FNRmpSvM.wasm +0 -0
  515. package/dist/assets/index-B1Ecw4AU.js +0 -189756
  516. package/dist/assets/index-Ba4eoTe7.css +0 -1
  517. package/dist/assets/index-CrgYBjTn.js +0 -229
  518. package/dist/assets/module-6F3E5H7Y-tx0BadV3.js +0 -6
  519. package/dist/assets/native-bridge-Crsb7TKz.js +0 -111
  520. package/dist/assets/wasm-bridge-mJUhb7uk.js +0 -1
@@ -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>
@@ -22,6 +22,7 @@ import {
22
22
  DropdownMenuTrigger,
23
23
  } from '@/components/ui/dropdown-menu';
24
24
  import { useViewerStore } from '@/store';
25
+ import { toGlobalIdFromModels } from '@/store/globalId';
25
26
  import { useIfc } from '@/hooks/useIfc';
26
27
  import { GraphicOverrideEngine } from '@ifc-lite/drawing-2d';
27
28
  import { type GeometryResult } from '@ifc-lite/geometry';
@@ -224,7 +225,7 @@ export function Section2DPanel({
224
225
  const model = models.get(modelId);
225
226
  if (model && model.idOffset !== undefined) {
226
227
  for (const localId of localHiddenIds) {
227
- globalHiddenIds.add(localId + model.idOffset);
228
+ globalHiddenIds.add(toGlobalIdFromModels(models, model.id, localId));
228
229
  }
229
230
  }
230
231
  }
@@ -245,7 +246,7 @@ export function Section2DPanel({
245
246
  const model = models.get(modelId);
246
247
  if (model && model.idOffset !== undefined) {
247
248
  for (const localId of localIsolatedIds) {
248
- globalIsolatedIds.add(localId + model.idOffset);
249
+ globalIsolatedIds.add(toGlobalIdFromModels(models, model.id, localId));
249
250
  }
250
251
  }
251
252
  }
@@ -0,0 +1,430 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+
5
+ import { SignInButton, SignedIn, SignedOut, UserButton, useAuth, useUser } from '@clerk/clerk-react';
6
+ import {
7
+ ArrowLeft,
8
+ Bot,
9
+ Check,
10
+ Clock3,
11
+ Cloud,
12
+ CreditCard,
13
+ FolderOpen,
14
+ LayoutPanelTop,
15
+ Lock,
16
+ RefreshCw,
17
+ Settings2,
18
+ ShieldCheck,
19
+ WifiOff,
20
+ } from 'lucide-react';
21
+ import { useEffect, useMemo, useState } from 'react';
22
+ import { Badge } from '@/components/ui/badge';
23
+ import { Button } from '@/components/ui/button';
24
+ import { Switch } from '@/components/ui/switch';
25
+ import { toast } from '@/components/ui/toast';
26
+ import { useViewerStore } from '@/store';
27
+ import {
28
+ buildDesktopUpgradeUrl,
29
+ getDesktopFeatureCatalog,
30
+ getDesktopPlanSummary,
31
+ getDesktopPlanTier,
32
+ hasDesktopPro,
33
+ isDesktopBillingEnforced,
34
+ type DesktopEntitlement,
35
+ } from '@/lib/desktop-product';
36
+ import { isClerkConfigured } from '@/lib/llm/clerk-auth';
37
+ import { navigateToPath } from '@/services/app-navigation';
38
+ import { requestDesktopEntitlementRefresh } from '@/lib/desktop/desktopEntitlementEvents';
39
+ import {
40
+ getDesktopPreferences,
41
+ subscribeDesktopPreferences,
42
+ updateDesktopPreferences,
43
+ } from '@/services/desktop-preferences';
44
+
45
+ export function SettingsPage() {
46
+ const clerkEnabled = isClerkConfigured();
47
+ const desktopEntitlement = useViewerStore((s) => s.desktopEntitlement);
48
+ const chatUsage = useViewerStore((s) => s.chatUsage);
49
+ const [preferences, setPreferences] = useState(() => getDesktopPreferences());
50
+ const [isRefreshingAccount, setIsRefreshingAccount] = useState(false);
51
+ const returnTo = (() => {
52
+ const params = new URLSearchParams(window.location.search);
53
+ const candidate = params.get('returnTo');
54
+ return candidate && candidate.startsWith('/') ? candidate : '/';
55
+ })();
56
+ useEffect(() => subscribeDesktopPreferences(() => {
57
+ setPreferences(getDesktopPreferences());
58
+ }), []);
59
+
60
+ const updatePreference = (updates: Partial<typeof preferences>) => {
61
+ setPreferences(updateDesktopPreferences(updates));
62
+ };
63
+ const planTier = getDesktopPlanTier(desktopEntitlement);
64
+ const planSummary = getDesktopPlanSummary(desktopEntitlement, chatUsage);
65
+ const featureCatalog = getDesktopFeatureCatalog(desktopEntitlement);
66
+ const canRestoreWorkspace = hasDesktopPro(desktopEntitlement);
67
+ const usageSummary = useMemo(() => {
68
+ if (!chatUsage) {
69
+ return null;
70
+ }
71
+ const resetLabel = chatUsage.resetAt
72
+ ? new Date(chatUsage.resetAt * 1000).toLocaleDateString()
73
+ : 'Unknown';
74
+ const unit = chatUsage.type === 'credits' ? 'credits' : 'requests';
75
+ return `${chatUsage.used}/${chatUsage.limit} ${unit} used. Resets ${resetLabel}.`;
76
+ }, [chatUsage]);
77
+
78
+ const handleRefreshAccount = async () => {
79
+ setIsRefreshingAccount(true);
80
+ try {
81
+ await requestDesktopEntitlementRefresh();
82
+ toast.success('Account status refreshed');
83
+ } catch (error) {
84
+ const message = error instanceof Error ? error.message : 'Could not refresh account status';
85
+ toast.error(message);
86
+ } finally {
87
+ setIsRefreshingAccount(false);
88
+ }
89
+ };
90
+
91
+ return (
92
+ <div className="min-h-screen bg-background text-foreground">
93
+ <div className="mx-auto w-full max-w-4xl px-6 py-8">
94
+ <div className="mb-6 flex items-center justify-between">
95
+ <Button variant="ghost" size="sm" onClick={() => navigateToPath(returnTo, { replace: true })}>
96
+ <ArrowLeft className="mr-2 h-4 w-4" />
97
+ Back to Viewer
98
+ </Button>
99
+ </div>
100
+
101
+ <div className="space-y-6">
102
+ <section className="rounded-lg border bg-card p-6 shadow-sm">
103
+ <div className="mb-5 flex items-center gap-3">
104
+ <ShieldCheck className="h-5 w-5" />
105
+ <div>
106
+ <h1 className="text-2xl font-semibold">Desktop Account</h1>
107
+ <p className="text-sm text-muted-foreground">
108
+ App-wide entitlement, trial state, offline grace, and AI usage limits.
109
+ </p>
110
+ </div>
111
+ </div>
112
+
113
+ <div className="mb-5 flex flex-wrap items-center gap-2">
114
+ <StatusBadge entitlement={desktopEntitlement} />
115
+ <Badge variant={hasDesktopPro(desktopEntitlement) ? 'default' : 'secondary'}>
116
+ {planTier === 'pro' ? 'Desktop Pro' : 'Desktop Free'}
117
+ </Badge>
118
+ <Badge variant="outline">
119
+ Source: {desktopEntitlement.source.replace('_', ' ')}
120
+ </Badge>
121
+ </div>
122
+
123
+ <div className="mb-5 grid gap-3 md:grid-cols-2">
124
+ <InfoCard
125
+ title="Plan Summary"
126
+ body={planSummary}
127
+ icon={<CreditCard className="h-4 w-4" />}
128
+ />
129
+ <InfoCard
130
+ title="AI Usage"
131
+ body={usageSummary ?? 'No AI usage data yet. Pro usage appears after the first synced usage snapshot.'}
132
+ icon={<Bot className="h-4 w-4" />}
133
+ />
134
+ <InfoCard
135
+ title="Last Validated"
136
+ body={formatTimestamp(desktopEntitlement.validatedAt)}
137
+ icon={<Clock3 className="h-4 w-4" />}
138
+ />
139
+ <InfoCard
140
+ title="Offline Grace"
141
+ body={formatOfflineGrace(desktopEntitlement)}
142
+ icon={<WifiOff className="h-4 w-4" />}
143
+ />
144
+ </div>
145
+
146
+ {clerkEnabled ? (
147
+ <div className="flex flex-wrap gap-3">
148
+ <Button
149
+ variant="outline"
150
+ onClick={() => void handleRefreshAccount()}
151
+ disabled={isRefreshingAccount}
152
+ >
153
+ <RefreshCw className={`mr-2 h-4 w-4 ${isRefreshingAccount ? 'animate-spin' : ''}`} />
154
+ Refresh Account Status
155
+ </Button>
156
+ {!hasDesktopPro(desktopEntitlement) ? (
157
+ <Button onClick={() => navigateToPath(buildDesktopUpgradeUrl('/settings'))}>
158
+ Upgrade to Pro
159
+ </Button>
160
+ ) : null}
161
+ </div>
162
+ ) : null}
163
+ </section>
164
+
165
+ <section className="rounded-lg border bg-card p-6 shadow-sm">
166
+ <div className="mb-5 flex items-center gap-3">
167
+ <Settings2 className="h-5 w-5" />
168
+ <div>
169
+ <h1 className="text-2xl font-semibold">Desktop Settings</h1>
170
+ <p className="text-sm text-muted-foreground">
171
+ Local preferences for startup behavior and account access.
172
+ </p>
173
+ </div>
174
+ </div>
175
+
176
+ <div className="space-y-5">
177
+ <div className="flex items-start justify-between gap-4 rounded-md border p-4">
178
+ <div className="space-y-1">
179
+ <div className="flex items-center gap-2 font-medium">
180
+ <FolderOpen className="h-4 w-4" />
181
+ Reopen last model on launch
182
+ </div>
183
+ <p className="text-sm text-muted-foreground">
184
+ Automatically load the most recently used IFC file when the desktop app starts.
185
+ </p>
186
+ </div>
187
+ <Switch
188
+ checked={preferences.reopenLastModelOnLaunch}
189
+ onCheckedChange={(checked) => updatePreference({ reopenLastModelOnLaunch: checked })}
190
+ />
191
+ </div>
192
+
193
+ <div className="flex items-start justify-between gap-4 rounded-md border p-4">
194
+ <div className="space-y-1">
195
+ <div className="flex items-center gap-2 font-medium">
196
+ <LayoutPanelTop className="h-4 w-4" />
197
+ Restore workspace layout
198
+ </div>
199
+ <p className="text-sm text-muted-foreground">
200
+ Restore panel visibility, camera view, sectioning, and other saved workspace state on launch. Desktop Pro feature.
201
+ </p>
202
+ </div>
203
+ <Switch
204
+ checked={preferences.restoreWorkspaceLayoutOnLaunch}
205
+ disabled={!canRestoreWorkspace}
206
+ onCheckedChange={(checked) => updatePreference({ restoreWorkspaceLayoutOnLaunch: checked })}
207
+ />
208
+ </div>
209
+ {!canRestoreWorkspace && (
210
+ <div className="rounded-md border border-dashed p-4 text-sm text-muted-foreground">
211
+ Workspace restore is included with Desktop Pro. Reopening the last model remains available on Free.
212
+ <div className="mt-3">
213
+ <Button size="sm" onClick={() => navigateToPath(buildDesktopUpgradeUrl('/settings'))}>
214
+ Upgrade to Desktop Pro
215
+ </Button>
216
+ </div>
217
+ </div>
218
+ )}
219
+ </div>
220
+ </section>
221
+
222
+ <section className="rounded-lg border bg-card p-6 shadow-sm">
223
+ <div className="mb-5 flex items-center gap-3">
224
+ <CreditCard className="h-5 w-5" />
225
+ <div>
226
+ <h2 className="text-xl font-semibold">Billing & Features</h2>
227
+ <p className="text-sm text-muted-foreground">
228
+ Desktop billing is app-wide. The viewer stays available on Free, while Pro unlocks advanced desktop features and full AI access.
229
+ </p>
230
+ </div>
231
+ </div>
232
+
233
+ <div className="mb-5 rounded-md border p-4">
234
+ <div className="flex items-center justify-between gap-4">
235
+ <div>
236
+ <div className="font-medium capitalize">{planTier} plan</div>
237
+ <p className="text-sm text-muted-foreground">{planSummary}</p>
238
+ <p className="text-sm text-muted-foreground">
239
+ Desktop caches the latest validated plan locally and stores the auth bearer in native secure storage when available.
240
+ </p>
241
+ </div>
242
+ {isDesktopBillingEnforced() && !hasDesktopPro(desktopEntitlement) && (
243
+ <Button onClick={() => navigateToPath(buildDesktopUpgradeUrl('/settings'))}>
244
+ Upgrade to Pro
245
+ </Button>
246
+ )}
247
+ </div>
248
+ </div>
249
+
250
+ <div className="mb-5 grid gap-3">
251
+ {featureCatalog.map((feature) => (
252
+ <div key={feature.key} className="flex items-start justify-between gap-4 rounded-md border p-4">
253
+ <div>
254
+ <div className="font-medium">{feature.label}</div>
255
+ <p className="text-sm text-muted-foreground">{feature.description}</p>
256
+ </div>
257
+ <div className="flex items-center gap-2 text-sm">
258
+ {feature.enabled ? (
259
+ <>
260
+ <Check className="h-4 w-4 text-emerald-500" />
261
+ Included
262
+ </>
263
+ ) : (
264
+ <>
265
+ <Lock className="h-4 w-4 text-amber-500" />
266
+ Pro
267
+ </>
268
+ )}
269
+ </div>
270
+ </div>
271
+ ))}
272
+ </div>
273
+
274
+ {!clerkEnabled ? (
275
+ <div className="rounded-md border border-dashed p-4 text-sm text-muted-foreground">
276
+ Auth and billing are not configured in this build. Set `VITE_CLERK_PUBLISHABLE_KEY` to enable sign-in and subscription flows.
277
+ </div>
278
+ ) : (
279
+ <SettingsAccountSection desktopEntitlement={desktopEntitlement} />
280
+ )}
281
+ </section>
282
+
283
+ <section className="rounded-lg border bg-card p-6 shadow-sm">
284
+ <div className="mb-5 flex items-center gap-3">
285
+ <Cloud className="h-5 w-5" />
286
+ <div>
287
+ <h2 className="text-xl font-semibold">Privacy & Network</h2>
288
+ <p className="text-sm text-muted-foreground">
289
+ Local IFC viewing remains available offline. Connected services degrade individually instead of blocking the desktop viewer.
290
+ </p>
291
+ </div>
292
+ </div>
293
+
294
+ <div className="grid gap-3 md:grid-cols-2">
295
+ <InfoCard
296
+ title="Always Local"
297
+ body="Model loading, hierarchy, properties, navigation, measurement, and core viewing stay on your machine."
298
+ icon={<ShieldCheck className="h-4 w-4" />}
299
+ />
300
+ <InfoCard
301
+ title="Needs Network"
302
+ body="Cloud AI assistant, billing sync, and live bSDD lookups require network access. Cached Pro can continue during offline grace."
303
+ icon={<Cloud className="h-4 w-4" />}
304
+ />
305
+ </div>
306
+ </section>
307
+ </div>
308
+ </div>
309
+ </div>
310
+ );
311
+ }
312
+
313
+ function formatTimestamp(value: number | null): string {
314
+ if (!value) {
315
+ return 'Not validated yet';
316
+ }
317
+ return new Date(value).toLocaleString();
318
+ }
319
+
320
+ function formatOfflineGrace(entitlement: DesktopEntitlement): string {
321
+ if (!entitlement.graceUntil) {
322
+ return 'No offline grace cached yet';
323
+ }
324
+ const remainingDays = Math.max(0, Math.ceil((entitlement.graceUntil - Date.now()) / (24 * 60 * 60 * 1000)));
325
+ return `${new Date(entitlement.graceUntil).toLocaleString()}${remainingDays > 0 ? ` (${remainingDays} day${remainingDays === 1 ? '' : 's'} left)` : ''}`;
326
+ }
327
+
328
+ function describeDesktopStatus(entitlement: DesktopEntitlement): string {
329
+ switch (entitlement.status) {
330
+ case 'trial':
331
+ return entitlement.trialEndsAt
332
+ ? `Trial active until ${new Date(entitlement.trialEndsAt).toLocaleDateString()}`
333
+ : 'Trial active';
334
+ case 'grace_offline':
335
+ return entitlement.graceUntil
336
+ ? `Offline grace until ${new Date(entitlement.graceUntil).toLocaleDateString()}`
337
+ : 'Offline grace active';
338
+ case 'expired':
339
+ return 'Subscription expired';
340
+ case 'active':
341
+ return 'Subscription active';
342
+ case 'signed_out':
343
+ return 'Signed out';
344
+ case 'anonymous':
345
+ return 'Auth unavailable in this build';
346
+ default:
347
+ return entitlement.status;
348
+ }
349
+ }
350
+
351
+ function getStatusBadgeVariant(entitlement: DesktopEntitlement): 'default' | 'secondary' | 'destructive' | 'outline' {
352
+ switch (entitlement.status) {
353
+ case 'active':
354
+ case 'trial':
355
+ return 'default';
356
+ case 'grace_offline':
357
+ return 'secondary';
358
+ case 'expired':
359
+ return 'destructive';
360
+ default:
361
+ return 'outline';
362
+ }
363
+ }
364
+
365
+ function StatusBadge({ entitlement }: { entitlement: DesktopEntitlement }) {
366
+ return (
367
+ <Badge variant={getStatusBadgeVariant(entitlement)}>
368
+ {describeDesktopStatus(entitlement)}
369
+ </Badge>
370
+ );
371
+ }
372
+
373
+ function InfoCard({ title, body, icon }: { title: string; body: string; icon: React.ReactNode }) {
374
+ return (
375
+ <div className="rounded-md border p-4">
376
+ <div className="mb-2 flex items-center gap-2 text-sm font-medium">
377
+ {icon}
378
+ {title}
379
+ </div>
380
+ <p className="text-sm text-muted-foreground">{body}</p>
381
+ </div>
382
+ );
383
+ }
384
+
385
+ function SettingsAccountSection({ desktopEntitlement }: { desktopEntitlement: DesktopEntitlement }) {
386
+ const { isSignedIn } = useAuth();
387
+ const { user } = useUser();
388
+ const hasPro = hasDesktopPro(desktopEntitlement);
389
+ const statusLabel = describeDesktopStatus(desktopEntitlement);
390
+
391
+ return (
392
+ <div className="space-y-4">
393
+ <SignedOut>
394
+ <div className="rounded-md border p-4">
395
+ <p className="mb-3 text-sm text-muted-foreground">
396
+ Sign in to sync your desktop plan, subscription status, and AI usage limits across web and desktop.
397
+ </p>
398
+ <SignInButton mode="modal" forceRedirectUrl="/settings" fallbackRedirectUrl="/settings">
399
+ <Button>Sign in</Button>
400
+ </SignInButton>
401
+ </div>
402
+ </SignedOut>
403
+
404
+ <SignedIn>
405
+ <div className="flex items-center justify-between gap-4 rounded-md border p-4">
406
+ <div>
407
+ <div className="font-medium">
408
+ {user?.primaryEmailAddress?.emailAddress ?? user?.username ?? 'Signed in'}
409
+ </div>
410
+ <p className="text-sm text-muted-foreground">
411
+ Plan: {hasPro ? 'Pro' : 'Free'}
412
+ </p>
413
+ <p className="text-sm text-muted-foreground">
414
+ Status: {statusLabel}
415
+ </p>
416
+ <p className="text-sm text-muted-foreground">
417
+ Last validated: {formatTimestamp(desktopEntitlement.validatedAt)}
418
+ </p>
419
+ </div>
420
+ <div className="flex items-center gap-3">
421
+ <UserButton afterSignOutUrl="/" />
422
+ <Button onClick={() => navigateToPath(buildDesktopUpgradeUrl('/settings'))}>
423
+ {isSignedIn && hasPro ? 'Manage Plan' : 'Upgrade to Pro'}
424
+ </Button>
425
+ </div>
426
+ </div>
427
+ </SignedIn>
428
+ </div>
429
+ );
430
+ }
@@ -60,8 +60,24 @@ export function StatusBar() {
60
60
  if (!geometryResult) {
61
61
  return { elements: 0, triangles: 0 };
62
62
  }
63
+ // Count actual entities: for color-merged meshes, count unique entity IDs
64
+ let elements = 0;
65
+ const meshes = geometryResult.meshes;
66
+ if (meshes) {
67
+ for (let i = 0; i < meshes.length; i++) {
68
+ const m = meshes[i] as { entityIds?: Uint32Array };
69
+ if (m.entityIds && m.entityIds.length > 0) {
70
+ // Count unique entity IDs in this merged mesh
71
+ const seen = new Set<number>();
72
+ for (let j = 0; j < m.entityIds.length; j++) seen.add(m.entityIds[j]);
73
+ elements += seen.size;
74
+ } else {
75
+ elements += 1;
76
+ }
77
+ }
78
+ }
63
79
  return {
64
- elements: geometryResult.meshes?.length ?? 0,
80
+ elements,
65
81
  triangles: geometryResult.totalTriangles ?? 0,
66
82
  };
67
83
  }, [geometryResult]);
@@ -7,9 +7,12 @@ import { useEffect, useMemo } from 'react';
7
7
  import { ArrowLeft } from 'lucide-react';
8
8
  import { Button } from '@/components/ui/button';
9
9
  import { useViewerStore } from '@/store';
10
+ import { hasDesktopPro } from '@/lib/desktop-product';
11
+ import { navigateToPath } from '@/services/app-navigation';
10
12
 
11
13
  export function UpgradePage() {
12
- const hasPro = useViewerStore((s) => s.chatHasPro);
14
+ const desktopEntitlement = useViewerStore((s) => s.desktopEntitlement);
15
+ const hasPro = hasDesktopPro(desktopEntitlement);
13
16
  const returnTo = useMemo(() => {
14
17
  const params = new URLSearchParams(window.location.search);
15
18
  const candidate = params.get('returnTo');
@@ -17,8 +20,7 @@ export function UpgradePage() {
17
20
  }, []);
18
21
 
19
22
  const navigateBack = () => {
20
- window.history.replaceState({}, '', returnTo);
21
- window.dispatchEvent(new PopStateEvent('popstate'));
23
+ navigateToPath(returnTo, { replace: true });
22
24
  };
23
25
 
24
26
  // Automatically return to the previous app view once upgrade is active.
@@ -43,7 +45,7 @@ export function UpgradePage() {
43
45
  <div className="rounded-lg border bg-card p-6 shadow-sm">
44
46
  <h1 className="text-2xl font-semibold">Upgrade to Pro</h1>
45
47
  <p className="mt-2 text-sm text-muted-foreground">
46
- Free includes daily limited access to free models. Pro unlocks paid models and monthly credits.
48
+ Free keeps the core desktop viewer available. Pro unlocks advanced desktop features, plus the AI assistant with the same monthly limits and routing used on web.
47
49
  </p>
48
50
 
49
51
  <div className="mt-6">