@zendir/ui 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +640 -631
  3. package/dist/_virtual/_rolldown/runtime.js +13 -0
  4. package/dist/index.js +17 -221
  5. package/dist/react/3d/CesiumCaptureSource.d.ts +0 -1
  6. package/dist/react/3d/CesiumCaptureSource.js +364 -283
  7. package/dist/react/3d/CesiumCaptureSource.js.map +1 -1
  8. package/dist/react/3d/ZenSpace3D.d.ts +2 -3
  9. package/dist/react/3d/ZenSpace3D.js +1681 -1237
  10. package/dist/react/3d/ZenSpace3D.js.map +1 -1
  11. package/dist/react/3d/ZenSpace3DCesium.d.ts +0 -1
  12. package/dist/react/3d/ZenSpace3DCesium.js +513 -560
  13. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -1
  14. package/dist/react/3d/ZenSpace3DShaders.js +61 -66
  15. package/dist/react/3d/ZenSpace3DShaders.js.map +1 -1
  16. package/dist/react/3d/ZenSpace3DTypes.d.ts +19 -20
  17. package/dist/react/3d/ZenSpace3DUtils.d.ts +0 -1
  18. package/dist/react/3d/ZenSpace3DUtils.js +37 -24
  19. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -1
  20. package/dist/react/3d/capturePngAnalysis.js +42 -36
  21. package/dist/react/3d/capturePngAnalysis.js.map +1 -1
  22. package/dist/react/3d/index.d.ts +3 -3
  23. package/dist/react/3d/index.js +5 -53
  24. package/dist/react/3d/threeLoader.d.ts +1 -1
  25. package/dist/react/3d/threeLoader.js +23 -18
  26. package/dist/react/3d/threeLoader.js.map +1 -1
  27. package/dist/react/astro/ClassificationBanner.d.ts +2 -3
  28. package/dist/react/astro/ClassificationBanner.js +95 -79
  29. package/dist/react/astro/ClassificationBanner.js.map +1 -1
  30. package/dist/react/astro/GlobalStatusBar.d.ts +0 -1
  31. package/dist/react/astro/GlobalStatusBar.js +157 -163
  32. package/dist/react/astro/GlobalStatusBar.js.map +1 -1
  33. package/dist/react/astro/MissionClock.d.ts +7 -8
  34. package/dist/react/astro/MissionClock.js +377 -400
  35. package/dist/react/astro/MissionClock.js.map +1 -1
  36. package/dist/react/astro/MonitoringIcon.d.ts +1 -2
  37. package/dist/react/astro/MonitoringIcon.js +422 -358
  38. package/dist/react/astro/MonitoringIcon.js.map +1 -1
  39. package/dist/react/astro/Notification.d.ts +1 -2
  40. package/dist/react/astro/Notification.js +229 -126
  41. package/dist/react/astro/Notification.js.map +1 -1
  42. package/dist/react/astro/Progress.d.ts +0 -1
  43. package/dist/react/astro/Progress.js +199 -141
  44. package/dist/react/astro/Progress.js.map +1 -1
  45. package/dist/react/astro/SimulationControls.d.ts +3 -4
  46. package/dist/react/astro/SimulationControls.js +596 -650
  47. package/dist/react/astro/SimulationControls.js.map +1 -1
  48. package/dist/react/astro/StatusIndicator.d.ts +0 -1
  49. package/dist/react/astro/StatusIndicator.js +236 -170
  50. package/dist/react/astro/StatusIndicator.js.map +1 -1
  51. package/dist/react/astro/UnifiedTimeline.d.ts +9 -10
  52. package/dist/react/astro/UnifiedTimeline.js +2345 -2392
  53. package/dist/react/astro/UnifiedTimeline.js.map +1 -1
  54. package/dist/react/astro/index.d.ts +5 -5
  55. package/dist/react/astro/index.js +1 -25
  56. package/dist/react/cards/AccessCard.d.ts +0 -1
  57. package/dist/react/cards/AccessCard.js +471 -405
  58. package/dist/react/cards/AccessCard.js.map +1 -1
  59. package/dist/react/cards/OrbitCard.d.ts +0 -1
  60. package/dist/react/cards/OrbitCard.js +487 -364
  61. package/dist/react/cards/OrbitCard.js.map +1 -1
  62. package/dist/react/cards/SpacecraftCard.d.ts +0 -1
  63. package/dist/react/cards/SpacecraftCard.js +813 -925
  64. package/dist/react/cards/SpacecraftCard.js.map +1 -1
  65. package/dist/react/cards/TelemetryCard.d.ts +0 -1
  66. package/dist/react/cards/TelemetryCard.js +1055 -732
  67. package/dist/react/cards/TelemetryCard.js.map +1 -1
  68. package/dist/react/cards/TelemetryStreamCard.d.ts +0 -1
  69. package/dist/react/cards/TelemetryStreamCard.js +323 -297
  70. package/dist/react/cards/TelemetryStreamCard.js.map +1 -1
  71. package/dist/react/cards/index.d.ts +1 -1
  72. package/dist/react/cards/index.js +1 -8
  73. package/dist/react/charts/GroundTrackMap.d.ts +6 -7
  74. package/dist/react/charts/GroundTrackMap.js +1377 -1256
  75. package/dist/react/charts/GroundTrackMap.js.map +1 -1
  76. package/dist/react/charts/GroundTrackMapLeaflet.d.ts +1 -2
  77. package/dist/react/charts/GroundTrackMapLeaflet.js +1065 -987
  78. package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -1
  79. package/dist/react/charts/groundTrackMapLeafletTiles.js +34 -25
  80. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -1
  81. package/dist/react/charts/groundTrackMapLeafletUtils.js +70 -61
  82. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -1
  83. package/dist/react/charts/index.d.ts +1 -1
  84. package/dist/react/charts/index.js +7 -100
  85. package/dist/react/charts/unified/AstroChart.d.ts +1 -2
  86. package/dist/react/charts/unified/AstroChart.js +1331 -1411
  87. package/dist/react/charts/unified/AstroChart.js.map +1 -1
  88. package/dist/react/charts/unified/PowerOverviewChart.d.ts +3 -3
  89. package/dist/react/charts/unified/PowerOverviewChart.js +495 -478
  90. package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -1
  91. package/dist/react/charts/unified/domain.d.ts +12 -13
  92. package/dist/react/charts/unified/domain.js +3999 -3145
  93. package/dist/react/charts/unified/domain.js.map +1 -1
  94. package/dist/react/charts/unified/generators.d.ts +3 -4
  95. package/dist/react/charts/unified/generators.js +561 -498
  96. package/dist/react/charts/unified/generators.js.map +1 -1
  97. package/dist/react/charts/unified/index.d.ts +1 -1
  98. package/dist/react/charts/unified/presets.d.ts +14 -15
  99. package/dist/react/charts/unified/presets.js +857 -994
  100. package/dist/react/charts/unified/presets.js.map +1 -1
  101. package/dist/react/charts/unified/sync.d.ts +2 -3
  102. package/dist/react/charts/unified/sync.js +229 -195
  103. package/dist/react/charts/unified/sync.js.map +1 -1
  104. package/dist/react/charts/unified/theme.d.ts +11 -12
  105. package/dist/react/charts/unified/theme.js +606 -642
  106. package/dist/react/charts/unified/theme.js.map +1 -1
  107. package/dist/react/charts/unified/types.d.ts +32 -33
  108. package/dist/react/charts/unified/useChartStream.d.ts +1 -2
  109. package/dist/react/charts/unified/useChartStream.js +203 -216
  110. package/dist/react/charts/unified/useChartStream.js.map +1 -1
  111. package/dist/react/chatgpt/AppCard.d.ts +1 -2
  112. package/dist/react/chatgpt/index.d.ts +7 -7
  113. package/dist/react/chatgpt/index.js +160 -139
  114. package/dist/react/chatgpt/index.js.map +1 -1
  115. package/dist/react/context/CategoryContext.d.ts +0 -1
  116. package/dist/react/context/CategoryContext.js +78 -29
  117. package/dist/react/context/CategoryContext.js.map +1 -1
  118. package/dist/react/context/DisplaySettingsContext.d.ts +1 -2
  119. package/dist/react/context/DisplaySettingsContext.js +205 -156
  120. package/dist/react/context/DisplaySettingsContext.js.map +1 -1
  121. package/dist/react/context/SpatialSelectionContext.d.ts +0 -1
  122. package/dist/react/context/SpatialSelectionContext.js +36 -7
  123. package/dist/react/context/SpatialSelectionContext.js.map +1 -1
  124. package/dist/react/core/data/DataTable.d.ts +3 -4
  125. package/dist/react/core/data/DataTable.js +473 -440
  126. package/dist/react/core/data/DataTable.js.map +1 -1
  127. package/dist/react/core/data/DataValue.d.ts +4 -5
  128. package/dist/react/core/data/DataValue.js +605 -538
  129. package/dist/react/core/data/DataValue.js.map +1 -1
  130. package/dist/react/core/data/propertyConfig.d.ts +1 -2
  131. package/dist/react/core/data/propertyConfig.js +446 -382
  132. package/dist/react/core/data/propertyConfig.js.map +1 -1
  133. package/dist/react/core/display/AstroIcon.d.ts +4 -5
  134. package/dist/react/core/display/AstroIcon.js +339 -429
  135. package/dist/react/core/display/AstroIcon.js.map +1 -1
  136. package/dist/react/core/display/Badge.d.ts +2 -3
  137. package/dist/react/core/display/Badge.js +131 -131
  138. package/dist/react/core/display/Badge.js.map +1 -1
  139. package/dist/react/core/display/CardHeader.d.ts +0 -1
  140. package/dist/react/core/display/CardHeader.js +398 -311
  141. package/dist/react/core/display/CardHeader.js.map +1 -1
  142. package/dist/react/core/display/Container.d.ts +2 -3
  143. package/dist/react/core/display/Container.js +640 -668
  144. package/dist/react/core/display/Container.js.map +1 -1
  145. package/dist/react/core/display/CopyButton.d.ts +1 -2
  146. package/dist/react/core/display/CopyButton.js +158 -101
  147. package/dist/react/core/display/CopyButton.js.map +1 -1
  148. package/dist/react/core/display/GlassCard.d.ts +3 -4
  149. package/dist/react/core/display/GlassCard.js +416 -369
  150. package/dist/react/core/display/GlassCard.js.map +1 -1
  151. package/dist/react/core/display/HeaderIconWithStatus.d.ts +0 -1
  152. package/dist/react/core/display/HeaderIconWithStatus.js +152 -152
  153. package/dist/react/core/display/HeaderIconWithStatus.js.map +1 -1
  154. package/dist/react/core/display/Icon.d.ts +2 -3
  155. package/dist/react/core/display/Icon.js +172 -143
  156. package/dist/react/core/display/Icon.js.map +1 -1
  157. package/dist/react/core/display/Typography.d.ts +24 -25
  158. package/dist/react/core/display/Typography.js +360 -178
  159. package/dist/react/core/display/Typography.js.map +1 -1
  160. package/dist/react/core/feedback/ConfirmDialog.d.ts +1 -2
  161. package/dist/react/core/feedback/ConfirmDialog.js +343 -304
  162. package/dist/react/core/feedback/ConfirmDialog.js.map +1 -1
  163. package/dist/react/core/feedback/Dialog.d.ts +2 -3
  164. package/dist/react/core/feedback/Dialog.js +189 -197
  165. package/dist/react/core/feedback/Dialog.js.map +1 -1
  166. package/dist/react/core/feedback/Toast.d.ts +2 -3
  167. package/dist/react/core/feedback/Toast.js +346 -207
  168. package/dist/react/core/feedback/Toast.js.map +1 -1
  169. package/dist/react/core/index.d.ts +26 -26
  170. package/dist/react/core/index.js +7 -119
  171. package/dist/react/core/inputs/Button.d.ts +2 -3
  172. package/dist/react/core/inputs/Button.js +281 -304
  173. package/dist/react/core/inputs/Button.js.map +1 -1
  174. package/dist/react/core/inputs/Checkbox.d.ts +2 -3
  175. package/dist/react/core/inputs/Checkbox.js +139 -127
  176. package/dist/react/core/inputs/Checkbox.js.map +1 -1
  177. package/dist/react/core/inputs/Input.d.ts +3 -4
  178. package/dist/react/core/inputs/Input.js +277 -285
  179. package/dist/react/core/inputs/Input.js.map +1 -1
  180. package/dist/react/core/inputs/LimitsBar.d.ts +1 -2
  181. package/dist/react/core/inputs/LimitsBar.js +271 -196
  182. package/dist/react/core/inputs/LimitsBar.js.map +1 -1
  183. package/dist/react/core/inputs/NumberInput.d.ts +2 -3
  184. package/dist/react/core/inputs/NumberInput.js +531 -503
  185. package/dist/react/core/inputs/NumberInput.js.map +1 -1
  186. package/dist/react/core/inputs/PinInput.d.ts +2 -3
  187. package/dist/react/core/inputs/PinInput.js +224 -207
  188. package/dist/react/core/inputs/PinInput.js.map +1 -1
  189. package/dist/react/core/inputs/Select.d.ts +1 -2
  190. package/dist/react/core/inputs/Select.js +298 -299
  191. package/dist/react/core/inputs/Select.js.map +1 -1
  192. package/dist/react/core/inputs/Toggle.d.ts +2 -3
  193. package/dist/react/core/inputs/Toggle.js +142 -148
  194. package/dist/react/core/inputs/Toggle.js.map +1 -1
  195. package/dist/react/core/layout/Box.d.ts +3 -4
  196. package/dist/react/core/layout/Box.js +118 -122
  197. package/dist/react/core/layout/Box.js.map +1 -1
  198. package/dist/react/core/layout/Center.d.ts +0 -1
  199. package/dist/react/core/layout/Center.js +45 -32
  200. package/dist/react/core/layout/Center.js.map +1 -1
  201. package/dist/react/core/layout/Divider.d.ts +1 -2
  202. package/dist/react/core/layout/Divider.js +112 -106
  203. package/dist/react/core/layout/Divider.js.map +1 -1
  204. package/dist/react/core/layout/Flex.d.ts +4 -5
  205. package/dist/react/core/layout/Flex.js +120 -124
  206. package/dist/react/core/layout/Flex.js.map +1 -1
  207. package/dist/react/core/layout/Grid.d.ts +5 -6
  208. package/dist/react/core/layout/Grid.js +131 -138
  209. package/dist/react/core/layout/Grid.js.map +1 -1
  210. package/dist/react/core/layout/Spacer.d.ts +0 -1
  211. package/dist/react/core/layout/Spacer.js +36 -29
  212. package/dist/react/core/layout/Spacer.js.map +1 -1
  213. package/dist/react/core/layout/Stack.d.ts +4 -5
  214. package/dist/react/core/layout/Stack.js +127 -70
  215. package/dist/react/core/layout/Stack.js.map +1 -1
  216. package/dist/react/core/layout/responsive.d.ts +1 -2
  217. package/dist/react/core/layout/responsive.js +25 -19
  218. package/dist/react/core/layout/responsive.js.map +1 -1
  219. package/dist/react/core/layout/useBreakpoint.d.ts +1 -1
  220. package/dist/react/core/layout/useBreakpoint.js +119 -66
  221. package/dist/react/core/layout/useBreakpoint.js.map +1 -1
  222. package/dist/react/core/navigation/AppBar.d.ts +1 -2
  223. package/dist/react/core/navigation/AppBar.js +827 -805
  224. package/dist/react/core/navigation/AppBar.js.map +1 -1
  225. package/dist/react/core/navigation/Pagination.d.ts +2 -3
  226. package/dist/react/core/navigation/Pagination.js +207 -187
  227. package/dist/react/core/navigation/Pagination.js.map +1 -1
  228. package/dist/react/core/navigation/SideNav.d.ts +11 -5
  229. package/dist/react/core/navigation/SideNav.js +857 -602
  230. package/dist/react/core/navigation/SideNav.js.map +1 -1
  231. package/dist/react/core/navigation/Tabs.d.ts +0 -1
  232. package/dist/react/core/navigation/Tabs.js +113 -119
  233. package/dist/react/core/navigation/Tabs.js.map +1 -1
  234. package/dist/react/core/overlays/Popover.d.ts +2 -3
  235. package/dist/react/core/overlays/Popover.js +303 -282
  236. package/dist/react/core/overlays/Popover.js.map +1 -1
  237. package/dist/react/core/overlays/SidePanel.d.ts +1 -2
  238. package/dist/react/core/overlays/SidePanel.js +217 -212
  239. package/dist/react/core/overlays/SidePanel.js.map +1 -1
  240. package/dist/react/core/overlays/Tooltip.d.ts +1 -2
  241. package/dist/react/core/overlays/Tooltip.js +170 -176
  242. package/dist/react/core/overlays/Tooltip.js.map +1 -1
  243. package/dist/react/core/widgets/ActivityPlanner.d.ts +0 -1
  244. package/dist/react/core/widgets/ActivityPlanner.js +855 -517
  245. package/dist/react/core/widgets/ActivityPlanner.js.map +1 -1
  246. package/dist/react/core/widgets/Capture.d.ts +2 -3
  247. package/dist/react/core/widgets/Capture.js +965 -779
  248. package/dist/react/core/widgets/Capture.js.map +1 -1
  249. package/dist/react/core/widgets/ChatPanel.d.ts +16 -17
  250. package/dist/react/core/widgets/ChatPanel.js +1734 -1034
  251. package/dist/react/core/widgets/ChatPanel.js.map +1 -1
  252. package/dist/react/core/widgets/ColorPickerPanel.d.ts +0 -1
  253. package/dist/react/core/widgets/ColorPickerPanel.js +298 -287
  254. package/dist/react/core/widgets/ColorPickerPanel.js.map +1 -1
  255. package/dist/react/core/widgets/CommandBuilder.d.ts +2 -3
  256. package/dist/react/core/widgets/CommandBuilder.js +624 -516
  257. package/dist/react/core/widgets/CommandBuilder.js.map +1 -1
  258. package/dist/react/core/widgets/ConnectionForm.d.ts +2 -3
  259. package/dist/react/core/widgets/ConnectionForm.js +528 -492
  260. package/dist/react/core/widgets/ConnectionForm.js.map +1 -1
  261. package/dist/react/core/widgets/FileExplorer.d.ts +3 -4
  262. package/dist/react/core/widgets/FileExplorer.js +617 -505
  263. package/dist/react/core/widgets/FileExplorer.js.map +1 -1
  264. package/dist/react/core/widgets/HexViewer.d.ts +2 -3
  265. package/dist/react/core/widgets/HexViewer.js +1353 -1091
  266. package/dist/react/core/widgets/HexViewer.js.map +1 -1
  267. package/dist/react/core/widgets/ImageFrame.d.ts +1 -2
  268. package/dist/react/core/widgets/ImageFrame.js +230 -193
  269. package/dist/react/core/widgets/ImageFrame.js.map +1 -1
  270. package/dist/react/core/widgets/ImageGallery.d.ts +2 -1
  271. package/dist/react/core/widgets/ImageGallery.js +380 -314
  272. package/dist/react/core/widgets/ImageGallery.js.map +1 -1
  273. package/dist/react/core/widgets/ImagePanel.d.ts +0 -1
  274. package/dist/react/core/widgets/ImagePanel.js +110 -101
  275. package/dist/react/core/widgets/ImagePanel.js.map +1 -1
  276. package/dist/react/core/widgets/LogViewer.d.ts +2 -3
  277. package/dist/react/core/widgets/LogViewer.js +711 -607
  278. package/dist/react/core/widgets/LogViewer.js.map +1 -1
  279. package/dist/react/core/widgets/MessageStream.d.ts +3 -4
  280. package/dist/react/core/widgets/MessageStream.js +514 -444
  281. package/dist/react/core/widgets/MessageStream.js.map +1 -1
  282. package/dist/react/core/widgets/MissionCalendar.d.ts +3 -4
  283. package/dist/react/core/widgets/MissionCalendar.js +1488 -1020
  284. package/dist/react/core/widgets/MissionCalendar.js.map +1 -1
  285. package/dist/react/core/widgets/PacketViewer.d.ts +2 -3
  286. package/dist/react/core/widgets/PacketViewer.js +550 -421
  287. package/dist/react/core/widgets/PacketViewer.js.map +1 -1
  288. package/dist/react/core/widgets/capture-placeholder.png.js +6 -5
  289. package/dist/react/core/widgets/capture-placeholder.png.js.map +1 -1
  290. package/dist/react/hooks/index.d.ts +5 -5
  291. package/dist/react/hooks/useAccessWindows.d.ts +0 -1
  292. package/dist/react/hooks/useCompactMode.d.ts +1 -1
  293. package/dist/react/hooks/useCompactMode.js +104 -58
  294. package/dist/react/hooks/useCompactMode.js.map +1 -1
  295. package/dist/react/hooks/useGroundTrackHistory.d.ts +0 -1
  296. package/dist/react/hooks/useSimulationScene.d.ts +1 -2
  297. package/dist/react/hooks/useSimulationScene.js +481 -374
  298. package/dist/react/hooks/useSimulationScene.js.map +1 -1
  299. package/dist/react/index.d.ts +3 -3
  300. package/dist/react/panels/LayerControlPanel.d.ts +1 -2
  301. package/dist/react/panels/LayerControlPanel.js +223 -180
  302. package/dist/react/panels/LayerControlPanel.js.map +1 -1
  303. package/dist/react/panels/ObjectInventoryPanel.d.ts +2 -3
  304. package/dist/react/panels/ObjectInventoryPanel.js +315 -250
  305. package/dist/react/panels/ObjectInventoryPanel.js.map +1 -1
  306. package/dist/react/panels/index.d.ts +1 -1
  307. package/dist/react/panels/index.js +1 -6
  308. package/dist/react/shared/ErrorBoundary.d.ts +1 -2
  309. package/dist/react/shared/ErrorBoundary.js +170 -139
  310. package/dist/react/shared/ErrorBoundary.js.map +1 -1
  311. package/dist/react/shared/Skeleton.d.ts +1 -2
  312. package/dist/react/shared/Skeleton.js +300 -301
  313. package/dist/react/shared/Skeleton.js.map +1 -1
  314. package/dist/react/theme/ThemeProvider.d.ts +2 -321
  315. package/dist/react/theme/ThemeProvider.js +312 -939
  316. package/dist/react/theme/ThemeProvider.js.map +1 -1
  317. package/dist/react/theme/cardAccent.d.ts +1 -2
  318. package/dist/react/theme/cardAccent.js +196 -126
  319. package/dist/react/theme/cardAccent.js.map +1 -1
  320. package/dist/react/theme/config.d.ts +0 -1
  321. package/dist/react/theme/config.js +47 -25
  322. package/dist/react/theme/config.js.map +1 -1
  323. package/dist/react/theme/index.d.ts +2 -2
  324. package/dist/react/theme/index.js +1 -16
  325. package/dist/react/theme/types.d.ts +332 -0
  326. package/dist/react/theme/types.js +39 -0
  327. package/dist/react/theme/types.js.map +1 -0
  328. package/dist/react/types.d.ts +8 -8
  329. package/dist/react/types.js +147 -47
  330. package/dist/react/types.js.map +1 -1
  331. package/dist/react/utils/categoryPalette.d.ts +0 -1
  332. package/dist/react/utils/categoryPalette.js +91 -102
  333. package/dist/react/utils/categoryPalette.js.map +1 -1
  334. package/dist/react/utils/index.d.ts +5 -5
  335. package/dist/react/utils/index.js +457 -371
  336. package/dist/react/utils/index.js.map +1 -1
  337. package/dist/react/visualizations/EclipseTimerCard.d.ts +0 -1
  338. package/dist/react/visualizations/LinkBudgetCard.d.ts +0 -1
  339. package/dist/react/visualizations/NavBallCard.d.ts +0 -1
  340. package/dist/react/visualizations/PropulsionCard.d.ts +1 -2
  341. package/dist/react/visualizations/SensorFootprintCard.d.ts +1 -2
  342. package/dist/react/visualizations/ThermalHeatmapCard.d.ts +0 -1
  343. package/dist/react/visualizations/index.d.ts +3 -3
  344. package/dist/react.d.ts +2 -1
  345. package/dist/react.js +17 -221
  346. package/dist/shaders/atmosphere.frag.js +6 -5
  347. package/dist/shaders/atmosphere.frag.js.map +1 -1
  348. package/dist/shaders/atmosphere.vert.js +6 -5
  349. package/dist/shaders/atmosphere.vert.js.map +1 -1
  350. package/dist/shaders/stars.frag.js +6 -5
  351. package/dist/shaders/stars.frag.js.map +1 -1
  352. package/dist/shaders/stars.vert.js +6 -5
  353. package/dist/shaders/stars.vert.js.map +1 -1
  354. package/dist/style.css +217 -194
  355. package/dist/tokens/core.d.ts +159 -0
  356. package/dist/tokens/core.js +144 -0
  357. package/dist/tokens/core.js.map +1 -0
  358. package/dist/tokens/css-vars.d.ts +213 -2
  359. package/dist/tokens/css-vars.js +590 -227
  360. package/dist/tokens/css-vars.js.map +1 -1
  361. package/dist/tokens/index.d.ts +31 -228
  362. package/dist/tokens/index.js +281 -366
  363. package/dist/tokens/index.js.map +1 -1
  364. package/dist/tokens/palettes/astro.d.ts +129 -0
  365. package/dist/tokens/palettes/astro.js +112 -0
  366. package/dist/tokens/palettes/astro.js.map +1 -0
  367. package/dist/tokens/palettes/index.d.ts +288 -0
  368. package/dist/tokens/palettes/index.js +35 -0
  369. package/dist/tokens/palettes/index.js.map +1 -0
  370. package/dist/tokens/palettes/tailwind.d.ts +324 -0
  371. package/dist/tokens/palettes/tailwind.js +201 -0
  372. package/dist/tokens/palettes/tailwind.js.map +1 -0
  373. package/dist/tokens/palettes/zendir.d.ts +126 -0
  374. package/dist/tokens/palettes/zendir.js +92 -0
  375. package/dist/tokens/palettes/zendir.js.map +1 -0
  376. package/dist/tokens/themes.d.ts +30 -0
  377. package/dist/tokens/themes.js +704 -0
  378. package/dist/tokens/themes.js.map +1 -0
  379. package/dist/tokens/tokens.css +419 -41
  380. package/dist/types/index.d.ts +2 -2
  381. package/package.json +310 -313
  382. package/dist/index.js.map +0 -1
  383. package/dist/react/3d/index.js.map +0 -1
  384. package/dist/react/astro/index.js.map +0 -1
  385. package/dist/react/cards/index.js.map +0 -1
  386. package/dist/react/charts/index.js.map +0 -1
  387. package/dist/react/core/index.js.map +0 -1
  388. package/dist/react/panels/index.js.map +0 -1
  389. package/dist/react/theme/astro-tokens.d.ts +0 -153
  390. package/dist/react/theme/index.js.map +0 -1
  391. package/dist/react.js.map +0 -1
@@ -1,401 +1,508 @@
1
- import { useState, useRef, useCallback, useEffect } from "react";
2
- const PLACEHOLDER_SCENECRAFT_POSITION = { x: 6771, y: 0, z: 0 };
3
- const TICK_RETRY = {
4
- maxRetries: 2,
5
- initialDelayMs: 500,
6
- maxDelayMs: 1500
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ //#region src/react/hooks/useSimulationScene.ts
3
+ /**
4
+ * @zendir/ui - useSimulationScene Hook
5
+ *
6
+ * Bridge between a `zendir-ts` `ZendirClient` and the `ZenSpace3D`
7
+ * Cesium component. On mount the hook calls `getSimulationStructure`
8
+ * to bucket simulation objects (spacecraft / ground stations) and then
9
+ * polls each spacecraft's `Position_BN_N` on a fixed interval, emitting
10
+ * ZenSpace3D-shaped state.
11
+ *
12
+ * Ground stations are resolved once per structure load (lat/lon is
13
+ * static — no ECI polling).
14
+ *
15
+ * Structure JSON may use `ID`/`id` and `Type`/`type` interchangeably;
16
+ * the walker accepts common variants. Call `refresh()` to re-fetch the
17
+ * structure (e.g. on a consumer-owned timer) so newly spawned objects
18
+ * appear without remounting.
19
+ *
20
+ * `referenceDate` is the wall-clock instant of the last successful tick
21
+ * — pass it to `<ZenSpace3D referenceTime={...} />` so ECI/J2000
22
+ * positions rotate to ECEF at the engine's "now".
23
+ *
24
+ * OPTIONAL DEPENDENCY: requires a `zendir-ts` client instance. The
25
+ * client is passed in to avoid coupling this hook to a specific
26
+ * session-management strategy (the consumer app owns sessions).
27
+ */
28
+ /**
29
+ * Non-zero ECI placeholder (km) used until the first `Position_BN_N`
30
+ * poll lands. The 3D viewer expects ECI / J2000 km positions; the
31
+ * origin (0,0,0) sits at Earth's centre and would crash Cesium's
32
+ * `Cartesian3.normalize` with "normalized result is not a number".
33
+ *
34
+ * Value: ~400 km altitude on the +X axis (vernal-equinox direction).
35
+ * Renders just above the equator and is invisible after one tick.
36
+ */
37
+ var PLACEHOLDER_SCENECRAFT_POSITION = {
38
+ x: 6771,
39
+ y: 0,
40
+ z: 0
7
41
  };
8
- const DEFAULT_POLL_MS = 2e3;
9
- const M_TO_KM = 1 / 1e3;
42
+ /**
43
+ * Per-tick retry config for the position-polling loop.
44
+ *
45
+ * The SDK defaults `getProperties` to `engineWarmup` (24 retries /
46
+ * ~3.6 min). That budget is right for a one-shot mount call, but
47
+ * disastrous for a 2-second polling tick — a single warmup blip would
48
+ * stall every subsequent tick (skip-if-busy guard) for minutes, freezing
49
+ * the viewer. We override with a tight 2-attempt budget that rides
50
+ * through quick blips (~1.5 s total) but cedes to the next tick fast.
51
+ */
52
+ var TICK_RETRY = {
53
+ maxRetries: 2,
54
+ initialDelayMs: 500,
55
+ maxDelayMs: 1500
56
+ };
57
+ var DEFAULT_POLL_MS = 2e3;
58
+ var M_TO_KM = 1 / 1e3;
10
59
  function useSimulationScene(options) {
11
- const {
12
- client,
13
- containerId,
14
- simulationId,
15
- pollIntervalMs = DEFAULT_POLL_MS,
16
- enabled = true
17
- } = options;
18
- const [satellites, setSatellites] = useState([]);
19
- const [groundStations, setGroundStations] = useState([]);
20
- const [celestialBodies, setCelestialBodies] = useState([]);
21
- const [objects, setObjects] = useState([]);
22
- const [isLoading, setIsLoading] = useState(true);
23
- const [error, setError] = useState(null);
24
- const [referenceDate, setReferenceDate] = useState(() => /* @__PURE__ */ new Date());
25
- const [structureDiag, setStructureDiag] = useState(null);
26
- const [positionTickDiag, setPositionTickDiag] = useState(null);
27
- const spacecraftIdsRef = useRef([]);
28
- const celestialBodyIdsRef = useRef([]);
29
- const celestialBodyNamesRef = useRef([]);
30
- const intervalRef = useRef(null);
31
- const abortRef = useRef(null);
32
- const tickInFlightRef = useRef(false);
33
- const positionPropsRef = useRef(null);
34
- const tickPositions = useCallback(
35
- async (signal) => {
36
- if (!client) return;
37
- const ids = spacecraftIdsRef.current;
38
- if (ids.length === 0) return;
39
- if (tickInFlightRef.current) return;
40
- tickInFlightRef.current = true;
41
- try {
42
- const propsToFetch = positionPropsRef.current;
43
- const useFallbackAll = !propsToFetch || propsToFetch.length === 0;
44
- const updates = await Promise.allSettled(
45
- ids.map(
46
- (id) => useFallbackAll ? (
47
- // `retry: TICK_RETRY` overrides the SDK's engineWarmup default
48
- // for this one call. See the TICK_RETRY definition above for
49
- // the rationale (avoid a stuck tick stalling the viewer).
50
- client.getAllProperties(id, containerId, { signal, retry: TICK_RETRY })
51
- ) : client.getProperties(id, propsToFetch, containerId, {
52
- signal,
53
- retry: TICK_RETRY
54
- })
55
- )
56
- );
57
- if (signal.aborted) return;
58
- let parsedOk = 0;
59
- let parseFailed = 0;
60
- let requestFailed = 0;
61
- let firstResponseKeys = [];
62
- let firstResponseSample = "";
63
- for (let i = 0; i < ids.length; i++) {
64
- const result = updates[i];
65
- if (result.status !== "fulfilled") {
66
- requestFailed += 1;
67
- continue;
68
- }
69
- if (i === 0) {
70
- const v = result.value;
71
- if (v && typeof v === "object") firstResponseKeys = Object.keys(v);
72
- try {
73
- const json = JSON.stringify(v);
74
- firstResponseSample = json.length > 200 ? `${json.slice(0, 200)}…` : json;
75
- } catch {
76
- firstResponseSample = String(v);
77
- }
78
- }
79
- if (parsePositionVelocity(result.value)) parsedOk += 1;
80
- else parseFailed += 1;
81
- }
82
- setPositionTickDiag({
83
- attemptedAt: /* @__PURE__ */ new Date(),
84
- requested: ids.length,
85
- parsedOk,
86
- parseFailed,
87
- requestFailed,
88
- requestedProps: useFallbackAll ? null : propsToFetch,
89
- firstResponseKeys,
90
- firstResponseSample
91
- });
92
- setSatellites((prev) => {
93
- if (prev.length === 0) return prev;
94
- const next = prev.slice();
95
- for (let i = 0; i < ids.length; i++) {
96
- const result = updates[i];
97
- if (result.status !== "fulfilled") continue;
98
- const idx = next.findIndex((sc) => sc.id === ids[i]);
99
- if (idx < 0) continue;
100
- const parsed = parsePositionVelocity(result.value);
101
- if (!parsed) continue;
102
- next[idx] = { ...next[idx], position: parsed.position, velocity: parsed.velocity };
103
- }
104
- return next;
105
- });
106
- const celIds = celestialBodyIdsRef.current;
107
- if (celIds.length > 0) {
108
- const celResults = await Promise.allSettled(
109
- celIds.map(
110
- (id) => client.getProperties(id, ["Position", "IsCentralBody"], containerId, {
111
- signal,
112
- retry: TICK_RETRY
113
- })
114
- )
115
- );
116
- if (signal.aborted) return;
117
- const next = [];
118
- for (let i = 0; i < celIds.length; i++) {
119
- const result = celResults[i];
120
- if (result.status !== "fulfilled") continue;
121
- const raw = result.value;
122
- const obj = raw && typeof raw === "object" ? raw : null;
123
- if (!obj) continue;
124
- if (obj.IsCentralBody === true) continue;
125
- const posVec = parseVec3(obj.Position);
126
- if (!posVec) continue;
127
- const positionKm = scaleVec(posVec, M_TO_KM);
128
- const id = celIds[i];
129
- const name = celestialBodyNamesRef.current[i] ?? `CelestialBody ${shortId(id)}`;
130
- next.push({ id, name, position: positionKm });
131
- }
132
- setCelestialBodies(next);
133
- }
134
- } catch {
135
- } finally {
136
- tickInFlightRef.current = false;
137
- if (!signal.aborted) {
138
- setReferenceDate(/* @__PURE__ */ new Date());
139
- }
140
- }
141
- },
142
- [client, containerId]
143
- );
144
- const loadStructure = useCallback(
145
- async (signal) => {
146
- if (!client) return;
147
- setIsLoading(true);
148
- setError(null);
149
- try {
150
- const structure = await client.getSimulationStructure(simulationId, containerId, { signal });
151
- if (signal.aborted) return;
152
- setStructureDiag({
153
- topLevelKeys: Object.keys(structure),
154
- rawObjectCount: Array.isArray(structure.Objects) ? structure.Objects.length : Array.isArray(structure.objects) ? structure.objects.length : -1,
155
- rawSystemCount: Array.isArray(structure.Systems) ? structure.Systems.length : Array.isArray(structure.systems) ? structure.systems.length : -1
156
- });
157
- const buckets = bucketStructure(structure);
158
- spacecraftIdsRef.current = buckets.spacecraft.map((s) => s.id);
159
- celestialBodyIdsRef.current = buckets.celestialBodyIds;
160
- celestialBodyNamesRef.current = buckets.celestialBodyNames;
161
- setSatellites(buckets.spacecraft);
162
- setObjects(buckets.objects);
163
- if (buckets.spacecraft.length > 0) {
164
- try {
165
- const probeId = buckets.spacecraft[0].id;
166
- const all = await client.getAllProperties(probeId, containerId, { signal });
167
- if (signal.aborted) return;
168
- positionPropsRef.current = detectPositionPropertyNames(all);
169
- } catch {
170
- positionPropsRef.current = null;
171
- }
172
- } else {
173
- positionPropsRef.current = null;
174
- }
175
- const stationResults = await Promise.allSettled(
176
- buckets.groundStationIds.map(
177
- (id) => client.getAllProperties(id, containerId, { signal })
178
- )
179
- );
180
- if (signal.aborted) return;
181
- const stations = [];
182
- for (let i = 0; i < buckets.groundStationIds.length; i++) {
183
- const result = stationResults[i];
184
- const id = buckets.groundStationIds[i];
185
- const fallbackName = buckets.groundStationNames[i] ?? shortId(id);
186
- if (result.status !== "fulfilled") {
187
- stations.push({ id, name: fallbackName, latitude: 0, longitude: 0 });
188
- continue;
189
- }
190
- stations.push(toGroundStation(id, fallbackName, result.value));
191
- }
192
- setGroundStations(stations);
193
- setIsLoading(false);
194
- if (spacecraftIdsRef.current.length > 0) {
195
- await tickPositions(signal);
196
- }
197
- } catch (err) {
198
- if (signal.aborted) return;
199
- setError(err instanceof Error ? err.message : "Failed to load simulation structure");
200
- setIsLoading(false);
201
- }
202
- },
203
- [client, containerId, simulationId, tickPositions]
204
- );
205
- useEffect(() => {
206
- if (!client || !containerId || !simulationId) {
207
- setIsLoading(false);
208
- return;
209
- }
210
- const controller = new AbortController();
211
- abortRef.current = controller;
212
- void loadStructure(controller.signal);
213
- return () => {
214
- controller.abort();
215
- if (abortRef.current === controller) abortRef.current = null;
216
- };
217
- }, [client, containerId, simulationId, loadStructure]);
218
- useEffect(() => {
219
- if (!enabled || !client || error) {
220
- if (intervalRef.current) {
221
- clearInterval(intervalRef.current);
222
- intervalRef.current = null;
223
- }
224
- return;
225
- }
226
- const interval = setInterval(() => {
227
- const controller = new AbortController();
228
- void tickPositions(controller.signal).catch(() => void 0);
229
- }, pollIntervalMs);
230
- intervalRef.current = interval;
231
- return () => {
232
- clearInterval(interval);
233
- if (intervalRef.current === interval) intervalRef.current = null;
234
- };
235
- }, [client, enabled, error, pollIntervalMs, tickPositions]);
236
- const refresh = useCallback(async () => {
237
- const controller = new AbortController();
238
- await loadStructure(controller.signal);
239
- }, [loadStructure]);
240
- return {
241
- satellites,
242
- groundStations,
243
- celestialBodies,
244
- objects,
245
- isLoading,
246
- error,
247
- refresh,
248
- referenceDate,
249
- structureDiag,
250
- positionTickDiag
251
- };
60
+ const { client, containerId, simulationId, pollIntervalMs = DEFAULT_POLL_MS, enabled = true } = options;
61
+ const [satellites, setSatellites] = useState([]);
62
+ const [groundStations, setGroundStations] = useState([]);
63
+ const [celestialBodies, setCelestialBodies] = useState([]);
64
+ const [objects, setObjects] = useState([]);
65
+ const [isLoading, setIsLoading] = useState(true);
66
+ const [error, setError] = useState(null);
67
+ const [referenceDate, setReferenceDate] = useState(() => /* @__PURE__ */ new Date());
68
+ const [structureDiag, setStructureDiag] = useState(null);
69
+ const [positionTickDiag, setPositionTickDiag] = useState(null);
70
+ const spacecraftIdsRef = useRef([]);
71
+ const celestialBodyIdsRef = useRef([]);
72
+ const celestialBodyNamesRef = useRef([]);
73
+ const intervalRef = useRef(null);
74
+ const abortRef = useRef(null);
75
+ const tickInFlightRef = useRef(false);
76
+ const positionPropsRef = useRef(null);
77
+ const tickPositions = useCallback(async (signal) => {
78
+ if (!client) return;
79
+ const ids = spacecraftIdsRef.current;
80
+ if (ids.length === 0) return;
81
+ if (tickInFlightRef.current) return;
82
+ tickInFlightRef.current = true;
83
+ try {
84
+ const propsToFetch = positionPropsRef.current;
85
+ const useFallbackAll = !propsToFetch || propsToFetch.length === 0;
86
+ const updates = await Promise.allSettled(ids.map((id) => useFallbackAll ? client.getAllProperties(id, containerId, {
87
+ signal,
88
+ retry: TICK_RETRY
89
+ }) : client.getProperties(id, propsToFetch, containerId, {
90
+ signal,
91
+ retry: TICK_RETRY
92
+ })));
93
+ if (signal.aborted) return;
94
+ let parsedOk = 0;
95
+ let parseFailed = 0;
96
+ let requestFailed = 0;
97
+ let firstResponseKeys = [];
98
+ let firstResponseSample = "";
99
+ for (let i = 0; i < ids.length; i++) {
100
+ const result = updates[i];
101
+ if (result.status !== "fulfilled") {
102
+ requestFailed += 1;
103
+ continue;
104
+ }
105
+ if (i === 0) {
106
+ const v = result.value;
107
+ if (v && typeof v === "object") firstResponseKeys = Object.keys(v);
108
+ try {
109
+ const json = JSON.stringify(v);
110
+ firstResponseSample = json.length > 200 ? `${json.slice(0, 200)}…` : json;
111
+ } catch {
112
+ firstResponseSample = String(v);
113
+ }
114
+ }
115
+ if (parsePositionVelocity(result.value)) parsedOk += 1;
116
+ else parseFailed += 1;
117
+ }
118
+ setPositionTickDiag({
119
+ attemptedAt: /* @__PURE__ */ new Date(),
120
+ requested: ids.length,
121
+ parsedOk,
122
+ parseFailed,
123
+ requestFailed,
124
+ requestedProps: useFallbackAll ? null : propsToFetch,
125
+ firstResponseKeys,
126
+ firstResponseSample
127
+ });
128
+ setSatellites((prev) => {
129
+ if (prev.length === 0) return prev;
130
+ const next = prev.slice();
131
+ for (let i = 0; i < ids.length; i++) {
132
+ const result = updates[i];
133
+ if (result.status !== "fulfilled") continue;
134
+ const idx = next.findIndex((sc) => sc.id === ids[i]);
135
+ if (idx < 0) continue;
136
+ const parsed = parsePositionVelocity(result.value);
137
+ if (!parsed) continue;
138
+ next[idx] = {
139
+ ...next[idx],
140
+ position: parsed.position,
141
+ velocity: parsed.velocity
142
+ };
143
+ }
144
+ return next;
145
+ });
146
+ const celIds = celestialBodyIdsRef.current;
147
+ if (celIds.length > 0) {
148
+ const celResults = await Promise.allSettled(celIds.map((id) => client.getProperties(id, ["Position", "IsCentralBody"], containerId, {
149
+ signal,
150
+ retry: TICK_RETRY
151
+ })));
152
+ if (signal.aborted) return;
153
+ const next = [];
154
+ for (let i = 0; i < celIds.length; i++) {
155
+ const result = celResults[i];
156
+ if (result.status !== "fulfilled") continue;
157
+ const raw = result.value;
158
+ const obj = raw && typeof raw === "object" ? raw : null;
159
+ if (!obj) continue;
160
+ if (obj.IsCentralBody === true) continue;
161
+ const posVec = parseVec3(obj.Position);
162
+ if (!posVec) continue;
163
+ const positionKm = scaleVec(posVec, M_TO_KM);
164
+ const id = celIds[i];
165
+ const name = celestialBodyNamesRef.current[i] ?? `CelestialBody ${shortId(id)}`;
166
+ next.push({
167
+ id,
168
+ name,
169
+ position: positionKm
170
+ });
171
+ }
172
+ setCelestialBodies(next);
173
+ }
174
+ } catch {} finally {
175
+ tickInFlightRef.current = false;
176
+ if (!signal.aborted) setReferenceDate(/* @__PURE__ */ new Date());
177
+ }
178
+ }, [client, containerId]);
179
+ const loadStructure = useCallback(async (signal) => {
180
+ if (!client) return;
181
+ setIsLoading(true);
182
+ setError(null);
183
+ try {
184
+ const structure = await client.getSimulationStructure(simulationId, containerId, { signal });
185
+ if (signal.aborted) return;
186
+ setStructureDiag({
187
+ topLevelKeys: Object.keys(structure),
188
+ rawObjectCount: Array.isArray(structure.Objects) ? structure.Objects.length : Array.isArray(structure.objects) ? structure.objects.length : -1,
189
+ rawSystemCount: Array.isArray(structure.Systems) ? structure.Systems.length : Array.isArray(structure.systems) ? structure.systems.length : -1
190
+ });
191
+ const buckets = bucketStructure(structure);
192
+ spacecraftIdsRef.current = buckets.spacecraft.map((s) => s.id);
193
+ celestialBodyIdsRef.current = buckets.celestialBodyIds;
194
+ celestialBodyNamesRef.current = buckets.celestialBodyNames;
195
+ setSatellites(buckets.spacecraft);
196
+ setObjects(buckets.objects);
197
+ if (buckets.spacecraft.length > 0) try {
198
+ const probeId = buckets.spacecraft[0].id;
199
+ const all = await client.getAllProperties(probeId, containerId, { signal });
200
+ if (signal.aborted) return;
201
+ positionPropsRef.current = detectPositionPropertyNames(all);
202
+ } catch {
203
+ positionPropsRef.current = null;
204
+ }
205
+ else positionPropsRef.current = null;
206
+ const stationResults = await Promise.allSettled(buckets.groundStationIds.map((id) => client.getAllProperties(id, containerId, { signal })));
207
+ if (signal.aborted) return;
208
+ const stations = [];
209
+ for (let i = 0; i < buckets.groundStationIds.length; i++) {
210
+ const result = stationResults[i];
211
+ const id = buckets.groundStationIds[i];
212
+ const fallbackName = buckets.groundStationNames[i] ?? shortId(id);
213
+ if (result.status !== "fulfilled") {
214
+ stations.push({
215
+ id,
216
+ name: fallbackName,
217
+ latitude: 0,
218
+ longitude: 0
219
+ });
220
+ continue;
221
+ }
222
+ stations.push(toGroundStation(id, fallbackName, result.value));
223
+ }
224
+ setGroundStations(stations);
225
+ setIsLoading(false);
226
+ if (spacecraftIdsRef.current.length > 0) await tickPositions(signal);
227
+ } catch (err) {
228
+ if (signal.aborted) return;
229
+ setError(err instanceof Error ? err.message : "Failed to load simulation structure");
230
+ setIsLoading(false);
231
+ }
232
+ }, [
233
+ client,
234
+ containerId,
235
+ simulationId,
236
+ tickPositions
237
+ ]);
238
+ useEffect(() => {
239
+ if (!client || !containerId || !simulationId) {
240
+ setIsLoading(false);
241
+ return;
242
+ }
243
+ const controller = new AbortController();
244
+ abortRef.current = controller;
245
+ loadStructure(controller.signal);
246
+ return () => {
247
+ controller.abort();
248
+ if (abortRef.current === controller) abortRef.current = null;
249
+ };
250
+ }, [
251
+ client,
252
+ containerId,
253
+ simulationId,
254
+ loadStructure
255
+ ]);
256
+ useEffect(() => {
257
+ if (!enabled || !client || error) {
258
+ if (intervalRef.current) {
259
+ clearInterval(intervalRef.current);
260
+ intervalRef.current = null;
261
+ }
262
+ return;
263
+ }
264
+ const interval = setInterval(() => {
265
+ const controller = new AbortController();
266
+ tickPositions(controller.signal).catch(() => void 0);
267
+ }, pollIntervalMs);
268
+ intervalRef.current = interval;
269
+ return () => {
270
+ clearInterval(interval);
271
+ if (intervalRef.current === interval) intervalRef.current = null;
272
+ };
273
+ }, [
274
+ client,
275
+ enabled,
276
+ error,
277
+ pollIntervalMs,
278
+ tickPositions
279
+ ]);
280
+ return {
281
+ satellites,
282
+ groundStations,
283
+ celestialBodies,
284
+ objects,
285
+ isLoading,
286
+ error,
287
+ refresh: useCallback(async () => {
288
+ const controller = new AbortController();
289
+ await loadStructure(controller.signal);
290
+ }, [loadStructure]),
291
+ referenceDate,
292
+ structureDiag,
293
+ positionTickDiag
294
+ };
252
295
  }
296
+ /**
297
+ * First non-empty string among PascalCase / camelCase keys for one logical field.
298
+ */
253
299
  function firstStringField(obj, keys) {
254
- for (const key of keys) {
255
- const v = obj[key];
256
- if (typeof v === "string" && v.length > 0) return v;
257
- }
258
- return void 0;
300
+ for (const key of keys) {
301
+ const v = obj[key];
302
+ if (typeof v === "string" && v.length > 0) return v;
303
+ }
259
304
  }
305
+ /**
306
+ * Walk a `GetSimulationStructure` response and bucket objects by Type.
307
+ *
308
+ * Tolerant of:
309
+ * - PascalCase (`Objects`, `Systems`, `Children`) and camelCase
310
+ * (`objects`, `systems`, `children`) — the engine has shipped both.
311
+ * - Objects nested at the top level, inside Systems children, or under
312
+ * any depth of `Children` / `children` arrays.
313
+ */
260
314
  function bucketStructure(structure) {
261
- const out = {
262
- spacecraft: [],
263
- groundStationIds: [],
264
- groundStationNames: [],
265
- celestialBodyIds: [],
266
- celestialBodyNames: [],
267
- objects: []
268
- };
269
- const topObjects = pickArray(structure, ["Objects", "objects"]);
270
- for (const obj of topObjects) walkObject(obj, out);
271
- const topSystems = pickArray(structure, ["Systems", "systems"]);
272
- for (const sys of topSystems) walkObject(sys, out);
273
- return out;
315
+ const out = {
316
+ spacecraft: [],
317
+ groundStationIds: [],
318
+ groundStationNames: [],
319
+ celestialBodyIds: [],
320
+ celestialBodyNames: [],
321
+ objects: []
322
+ };
323
+ const topObjects = pickArray(structure, ["Objects", "objects"]);
324
+ for (const obj of topObjects) walkObject(obj, out);
325
+ const topSystems = pickArray(structure, ["Systems", "systems"]);
326
+ for (const sys of topSystems) walkObject(sys, out);
327
+ return out;
274
328
  }
329
+ /**
330
+ * Return the first non-empty array found under any of `keys` on `obj`.
331
+ * Allows the caller to tolerate PascalCase / camelCase top-level array keys
332
+ * without duplicating logic at every call site.
333
+ */
275
334
  function pickArray(obj, keys) {
276
- for (const key of keys) {
277
- const v = obj[key];
278
- if (Array.isArray(v) && v.length > 0) return v;
279
- }
280
- for (const key of keys) {
281
- const v = obj[key];
282
- if (Array.isArray(v)) return v;
283
- }
284
- return [];
335
+ for (const key of keys) {
336
+ const v = obj[key];
337
+ if (Array.isArray(v) && v.length > 0) return v;
338
+ }
339
+ for (const key of keys) {
340
+ const v = obj[key];
341
+ if (Array.isArray(v)) return v;
342
+ }
343
+ return [];
285
344
  }
286
345
  function walkObject(node, out) {
287
- if (!node || typeof node !== "object") return;
288
- const obj = node;
289
- const id = firstStringField(obj, ["ID", "id", "Id"]);
290
- const type = firstStringField(obj, ["Type", "type"]);
291
- const name = firstStringField(obj, ["Name", "name"]);
292
- if (id && type) {
293
- if (type === "Spacecraft" || type.endsWith(".Spacecraft")) {
294
- upsertObjectSummary(out, {
295
- id,
296
- name: name ?? `Spacecraft ${shortId(id)}`,
297
- kind: "spacecraft"
298
- });
299
- out.spacecraft.push({
300
- id,
301
- name: name ?? `Spacecraft ${shortId(id)}`,
302
- category: "satellite",
303
- position: { ...PLACEHOLDER_SCENECRAFT_POSITION },
304
- visualRadius: 50
305
- });
306
- } else if (type === "GroundStation" || type.endsWith(".GroundStation")) {
307
- upsertObjectSummary(out, {
308
- id,
309
- name: name ?? `GroundStation ${shortId(id)}`,
310
- kind: "groundStation"
311
- });
312
- out.groundStationIds.push(id);
313
- out.groundStationNames.push(name);
314
- } else if (type === "CelestialBody" || type.endsWith(".CelestialBody")) {
315
- upsertObjectSummary(out, {
316
- id,
317
- name: name ?? `CelestialBody ${shortId(id)}`,
318
- kind: "celestialBody"
319
- });
320
- out.celestialBodyIds.push(id);
321
- out.celestialBodyNames.push(name);
322
- }
323
- }
324
- const children = pickArray(obj, ["Children", "children"]);
325
- for (const child of children) walkObject(child, out);
346
+ if (!node || typeof node !== "object") return;
347
+ const obj = node;
348
+ const id = firstStringField(obj, [
349
+ "ID",
350
+ "id",
351
+ "Id"
352
+ ]);
353
+ const type = firstStringField(obj, ["Type", "type"]);
354
+ const name = firstStringField(obj, ["Name", "name"]);
355
+ if (id && type) {
356
+ if (type === "Spacecraft" || type.endsWith(".Spacecraft")) {
357
+ upsertObjectSummary(out, {
358
+ id,
359
+ name: name ?? `Spacecraft ${shortId(id)}`,
360
+ kind: "spacecraft"
361
+ });
362
+ out.spacecraft.push({
363
+ id,
364
+ name: name ?? `Spacecraft ${shortId(id)}`,
365
+ category: "satellite",
366
+ position: { ...PLACEHOLDER_SCENECRAFT_POSITION },
367
+ visualRadius: 50
368
+ });
369
+ } else if (type === "GroundStation" || type.endsWith(".GroundStation")) {
370
+ upsertObjectSummary(out, {
371
+ id,
372
+ name: name ?? `GroundStation ${shortId(id)}`,
373
+ kind: "groundStation"
374
+ });
375
+ out.groundStationIds.push(id);
376
+ out.groundStationNames.push(name);
377
+ } else if (type === "CelestialBody" || type.endsWith(".CelestialBody")) {
378
+ upsertObjectSummary(out, {
379
+ id,
380
+ name: name ?? `CelestialBody ${shortId(id)}`,
381
+ kind: "celestialBody"
382
+ });
383
+ out.celestialBodyIds.push(id);
384
+ out.celestialBodyNames.push(name);
385
+ }
386
+ }
387
+ const children = pickArray(obj, ["Children", "children"]);
388
+ for (const child of children) walkObject(child, out);
326
389
  }
327
390
  function upsertObjectSummary(out, next) {
328
- const idx = out.objects.findIndex((o) => o.id === next.id);
329
- if (idx >= 0) {
330
- out.objects[idx] = next;
331
- return;
332
- }
333
- out.objects.push(next);
391
+ const idx = out.objects.findIndex((o) => o.id === next.id);
392
+ if (idx >= 0) {
393
+ out.objects[idx] = next;
394
+ return;
395
+ }
396
+ out.objects.push(next);
334
397
  }
398
+ /**
399
+ * Inspect a `getAllProperties` response and return the position property name
400
+ * this engine exposes on a spacecraft.
401
+ *
402
+ * Only position is probed — velocity is intentionally excluded. The engine's
403
+ * `/get` endpoint validates names more strictly than `getAllProperties`, and
404
+ * `Velocity_BN_N` exists in the probe response but triggers a 400 when passed
405
+ * to `getProperties`. Since velocity is optional (only position is used for
406
+ * rendering), we never request it in the polling tick.
407
+ *
408
+ * Returns at most one name — the first position candidate whose value parses
409
+ * as a 3-vector in the probe response.
410
+ */
335
411
  function detectPositionPropertyNames(props) {
336
- const positionCandidates = ["Position_BN_N", "Position", "r_BN_N", "r_N"];
337
- for (const name of positionCandidates) {
338
- if (name in props && parseVec3(props[name]) !== null) {
339
- return [name];
340
- }
341
- }
342
- return [];
412
+ for (const name of [
413
+ "Position_BN_N",
414
+ "Position",
415
+ "r_BN_N",
416
+ "r_N"
417
+ ]) if (name in props && parseVec3(props[name]) !== null) return [name];
418
+ return [];
343
419
  }
420
+ /**
421
+ * Engines have shipped two property-naming conventions for spacecraft state:
422
+ *
423
+ * - Basilisk-style ECI: `Position_BN_N`, `Velocity_BN_N` (m, m/s)
424
+ * - Shorter form: `Position`, `Velocity` (m, m/s)
425
+ *
426
+ * Both are in metres. ZenSpace3D's `Vector3D` is documented as km / km/s,
427
+ * so we scale by 1e-3. The first key that produces a parseable 3-vector wins.
428
+ */
344
429
  function parsePositionVelocity(raw) {
345
- if (!raw || typeof raw !== "object") return null;
346
- const obj = raw;
347
- const position = parseVec3(obj.Position_BN_N) ?? parseVec3(obj.Position) ?? parseVec3(obj.position);
348
- if (!position) return null;
349
- if (position.x === 0 && position.y === 0 && position.z === 0) return null;
350
- const velocity = parseVec3(obj.Velocity_BN_N) ?? parseVec3(obj.Velocity) ?? parseVec3(obj.velocity);
351
- return {
352
- position: scaleVec(position, M_TO_KM),
353
- velocity: velocity ? scaleVec(velocity, M_TO_KM) : void 0
354
- };
430
+ if (!raw || typeof raw !== "object") return null;
431
+ const obj = raw;
432
+ const position = parseVec3(obj.Position_BN_N) ?? parseVec3(obj.Position) ?? parseVec3(obj.position);
433
+ if (!position) return null;
434
+ if (position.x === 0 && position.y === 0 && position.z === 0) return null;
435
+ const velocity = parseVec3(obj.Velocity_BN_N) ?? parseVec3(obj.Velocity) ?? parseVec3(obj.velocity);
436
+ return {
437
+ position: scaleVec(position, M_TO_KM),
438
+ velocity: velocity ? scaleVec(velocity, M_TO_KM) : void 0
439
+ };
355
440
  }
441
+ /**
442
+ * Accepts the engine's two known shapes for a 3-vector property:
443
+ * either a `[x, y, z]` array or an object with `X/Y/Z` keys (the
444
+ * gateway's JSON normalizer flips between the two depending on how
445
+ * the property is declared in the model).
446
+ */
356
447
  function parseVec3(raw) {
357
- if (Array.isArray(raw) && raw.length >= 3) {
358
- const [x, y, z] = raw;
359
- if (typeof x === "number" && typeof y === "number" && typeof z === "number") {
360
- return { x, y, z };
361
- }
362
- }
363
- if (raw && typeof raw === "object") {
364
- const obj = raw;
365
- const x = obj.X ?? obj.x;
366
- const y = obj.Y ?? obj.y;
367
- const z = obj.Z ?? obj.z;
368
- if (typeof x === "number" && typeof y === "number" && typeof z === "number") {
369
- return { x, y, z };
370
- }
371
- }
372
- return null;
448
+ if (Array.isArray(raw) && raw.length >= 3) {
449
+ const [x, y, z] = raw;
450
+ if (typeof x === "number" && typeof y === "number" && typeof z === "number") return {
451
+ x,
452
+ y,
453
+ z
454
+ };
455
+ }
456
+ if (raw && typeof raw === "object") {
457
+ const obj = raw;
458
+ const x = obj.X ?? obj.x;
459
+ const y = obj.Y ?? obj.y;
460
+ const z = obj.Z ?? obj.z;
461
+ if (typeof x === "number" && typeof y === "number" && typeof z === "number") return {
462
+ x,
463
+ y,
464
+ z
465
+ };
466
+ }
467
+ return null;
373
468
  }
374
469
  function scaleVec(v, k) {
375
- return { x: v.x * k, y: v.y * k, z: v.z * k };
470
+ return {
471
+ x: v.x * k,
472
+ y: v.y * k,
473
+ z: v.z * k
474
+ };
376
475
  }
377
476
  function toGroundStation(id, fallbackName, props) {
378
- const name = firstStringField(props, ["Name"]) ?? fallbackName;
379
- const latitude = pickNumber(props, ["Latitude", "latitude"]) ?? 0;
380
- const longitude = pickNumber(props, ["Longitude", "longitude"]) ?? 0;
381
- const elevation = pickNumber(props, ["Altitude", "altitude", "Elevation"]);
382
- const minElevation = pickNumber(props, ["MinElevation", "MinimumElevation"]);
383
- const station = { id, name, latitude, longitude };
384
- if (elevation !== void 0) station.elevation = elevation;
385
- if (minElevation !== void 0) station.minElevation = minElevation;
386
- return station;
477
+ const name = firstStringField(props, ["Name"]) ?? fallbackName;
478
+ const latitude = pickNumber(props, ["Latitude", "latitude"]) ?? 0;
479
+ const longitude = pickNumber(props, ["Longitude", "longitude"]) ?? 0;
480
+ const elevation = pickNumber(props, [
481
+ "Altitude",
482
+ "altitude",
483
+ "Elevation"
484
+ ]);
485
+ const minElevation = pickNumber(props, ["MinElevation", "MinimumElevation"]);
486
+ const station = {
487
+ id,
488
+ name,
489
+ latitude,
490
+ longitude
491
+ };
492
+ if (elevation !== void 0) station.elevation = elevation;
493
+ if (minElevation !== void 0) station.minElevation = minElevation;
494
+ return station;
387
495
  }
388
496
  function pickNumber(obj, keys) {
389
- for (const key of keys) {
390
- const v = obj[key];
391
- if (typeof v === "number" && Number.isFinite(v)) return v;
392
- }
393
- return void 0;
497
+ for (const key of keys) {
498
+ const v = obj[key];
499
+ if (typeof v === "number" && Number.isFinite(v)) return v;
500
+ }
394
501
  }
395
502
  function shortId(id) {
396
- return id.length > 8 ? id.slice(0, 8) : id;
503
+ return id.length > 8 ? id.slice(0, 8) : id;
397
504
  }
398
- export {
399
- useSimulationScene
400
- };
401
- //# sourceMappingURL=useSimulationScene.js.map
505
+ //#endregion
506
+ export { useSimulationScene as default, useSimulationScene };
507
+
508
+ //# sourceMappingURL=useSimulationScene.js.map