@zendir/ui 0.1.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 (359) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +589 -0
  4. package/dist/index.d.ts +8 -0
  5. package/dist/index.js +421 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/react/3d/EarthViewer.d.ts +46 -0
  8. package/dist/react/3d/EarthViewer.js +836 -0
  9. package/dist/react/3d/EarthViewer.js.map +1 -0
  10. package/dist/react/3d/SolarSystemViewer.d.ts +43 -0
  11. package/dist/react/3d/SolarSystemViewer.js +372 -0
  12. package/dist/react/3d/SolarSystemViewer.js.map +1 -0
  13. package/dist/react/3d/ZenSpace3D.d.ts +16 -0
  14. package/dist/react/3d/ZenSpace3D.js +1253 -0
  15. package/dist/react/3d/ZenSpace3D.js.map +1 -0
  16. package/dist/react/3d/ZenSpace3DCesium.d.ts +9 -0
  17. package/dist/react/3d/ZenSpace3DCesium.js +186 -0
  18. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -0
  19. package/dist/react/3d/ZenSpace3DShaders.d.ts +78 -0
  20. package/dist/react/3d/ZenSpace3DShaders.js +94 -0
  21. package/dist/react/3d/ZenSpace3DShaders.js.map +1 -0
  22. package/dist/react/3d/ZenSpace3DTypes.d.ts +614 -0
  23. package/dist/react/3d/ZenSpace3DUtils.d.ts +183 -0
  24. package/dist/react/3d/ZenSpace3DUtils.js +213 -0
  25. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -0
  26. package/dist/react/3d/index.d.ts +23 -0
  27. package/dist/react/3d/threeLoader.d.ts +22 -0
  28. package/dist/react/3d/threeLoader.js +18 -0
  29. package/dist/react/3d/threeLoader.js.map +1 -0
  30. package/dist/react/astro/ClassificationBanner.d.ts +25 -0
  31. package/dist/react/astro/ClassificationBanner.js +83 -0
  32. package/dist/react/astro/ClassificationBanner.js.map +1 -0
  33. package/dist/react/astro/GlobalStatusBar.d.ts +42 -0
  34. package/dist/react/astro/GlobalStatusBar.js +165 -0
  35. package/dist/react/astro/GlobalStatusBar.js.map +1 -0
  36. package/dist/react/astro/MissionClock.d.ts +169 -0
  37. package/dist/react/astro/MissionClock.js +411 -0
  38. package/dist/react/astro/MissionClock.js.map +1 -0
  39. package/dist/react/astro/MonitoringIcon.d.ts +60 -0
  40. package/dist/react/astro/MonitoringIcon.js +369 -0
  41. package/dist/react/astro/MonitoringIcon.js.map +1 -0
  42. package/dist/react/astro/Notification.d.ts +42 -0
  43. package/dist/react/astro/Notification.js +156 -0
  44. package/dist/react/astro/Notification.js.map +1 -0
  45. package/dist/react/astro/Progress.d.ts +39 -0
  46. package/dist/react/astro/Progress.js +149 -0
  47. package/dist/react/astro/Progress.js.map +1 -0
  48. package/dist/react/astro/SimulationControls.d.ts +136 -0
  49. package/dist/react/astro/SimulationControls.js +668 -0
  50. package/dist/react/astro/SimulationControls.js.map +1 -0
  51. package/dist/react/astro/StatusIndicator.d.ts +34 -0
  52. package/dist/react/astro/StatusIndicator.js +189 -0
  53. package/dist/react/astro/StatusIndicator.js.map +1 -0
  54. package/dist/react/astro/UnifiedTimeline.d.ts +106 -0
  55. package/dist/react/astro/UnifiedTimeline.js +1768 -0
  56. package/dist/react/astro/UnifiedTimeline.js.map +1 -0
  57. package/dist/react/astro/index.d.ts +63 -0
  58. package/dist/react/cards/AccessCard.d.ts +37 -0
  59. package/dist/react/cards/AccessCard.js +410 -0
  60. package/dist/react/cards/AccessCard.js.map +1 -0
  61. package/dist/react/cards/OrbitCard.d.ts +31 -0
  62. package/dist/react/cards/OrbitCard.js +372 -0
  63. package/dist/react/cards/OrbitCard.js.map +1 -0
  64. package/dist/react/cards/SpacecraftCard.d.ts +54 -0
  65. package/dist/react/cards/SpacecraftCard.js +941 -0
  66. package/dist/react/cards/SpacecraftCard.js.map +1 -0
  67. package/dist/react/cards/TelemetryCard.d.ts +40 -0
  68. package/dist/react/cards/TelemetryCard.js +742 -0
  69. package/dist/react/cards/TelemetryCard.js.map +1 -0
  70. package/dist/react/cards/TelemetryStreamCard.d.ts +59 -0
  71. package/dist/react/cards/TelemetryStreamCard.js +309 -0
  72. package/dist/react/cards/TelemetryStreamCard.js.map +1 -0
  73. package/dist/react/cards/index.d.ts +13 -0
  74. package/dist/react/charts/GroundTrackMap.d.ts +112 -0
  75. package/dist/react/charts/GroundTrackMap.js +1123 -0
  76. package/dist/react/charts/GroundTrackMap.js.map +1 -0
  77. package/dist/react/charts/GroundTrackMapLeaflet.d.ts +26 -0
  78. package/dist/react/charts/GroundTrackMapLeaflet.js +571 -0
  79. package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -0
  80. package/dist/react/charts/groundTrackMapLeafletTiles.d.ts +22 -0
  81. package/dist/react/charts/groundTrackMapLeafletTiles.js +11 -0
  82. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -0
  83. package/dist/react/charts/groundTrackMapLeafletUtils.d.ts +24 -0
  84. package/dist/react/charts/groundTrackMapLeafletUtils.js +109 -0
  85. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -0
  86. package/dist/react/charts/index.d.ts +10 -0
  87. package/dist/react/charts/unified/AstroChart.d.ts +24 -0
  88. package/dist/react/charts/unified/AstroChart.js +1405 -0
  89. package/dist/react/charts/unified/AstroChart.js.map +1 -0
  90. package/dist/react/charts/unified/PowerOverviewChart.d.ts +73 -0
  91. package/dist/react/charts/unified/PowerOverviewChart.js +488 -0
  92. package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -0
  93. package/dist/react/charts/unified/domain.d.ts +845 -0
  94. package/dist/react/charts/unified/domain.js +3168 -0
  95. package/dist/react/charts/unified/domain.js.map +1 -0
  96. package/dist/react/charts/unified/generators.d.ts +276 -0
  97. package/dist/react/charts/unified/generators.js +518 -0
  98. package/dist/react/charts/unified/generators.js.map +1 -0
  99. package/dist/react/charts/unified/index.d.ts +55 -0
  100. package/dist/react/charts/unified/presets.d.ts +290 -0
  101. package/dist/react/charts/unified/presets.js +999 -0
  102. package/dist/react/charts/unified/presets.js.map +1 -0
  103. package/dist/react/charts/unified/sync.d.ts +69 -0
  104. package/dist/react/charts/unified/sync.js +219 -0
  105. package/dist/react/charts/unified/sync.js.map +1 -0
  106. package/dist/react/charts/unified/theme.d.ts +447 -0
  107. package/dist/react/charts/unified/theme.js +562 -0
  108. package/dist/react/charts/unified/theme.js.map +1 -0
  109. package/dist/react/charts/unified/types.d.ts +826 -0
  110. package/dist/react/charts/unified/useChartStream.d.ts +58 -0
  111. package/dist/react/charts/unified/useChartStream.js +226 -0
  112. package/dist/react/charts/unified/useChartStream.js.map +1 -0
  113. package/dist/react/chatgpt/AppCard.d.ts +59 -0
  114. package/dist/react/chatgpt/AppCard.js +306 -0
  115. package/dist/react/chatgpt/AppCard.js.map +1 -0
  116. package/dist/react/chatgpt/ChatGPTCard.d.ts +6 -0
  117. package/dist/react/chatgpt/index.d.ts +167 -0
  118. package/dist/react/chatgpt/index.js +166 -0
  119. package/dist/react/chatgpt/index.js.map +1 -0
  120. package/dist/react/context/DisplaySettingsContext.d.ts +107 -0
  121. package/dist/react/context/DisplaySettingsContext.js +169 -0
  122. package/dist/react/context/DisplaySettingsContext.js.map +1 -0
  123. package/dist/react/context/index.d.ts +5 -0
  124. package/dist/react/core/ActivityPlanner.d.ts +45 -0
  125. package/dist/react/core/ActivityPlanner.js +532 -0
  126. package/dist/react/core/ActivityPlanner.js.map +1 -0
  127. package/dist/react/core/AppBar.d.ts +71 -0
  128. package/dist/react/core/AppBar.js +817 -0
  129. package/dist/react/core/AppBar.js.map +1 -0
  130. package/dist/react/core/AstroIcon.d.ts +84 -0
  131. package/dist/react/core/AstroIcon.js +1243 -0
  132. package/dist/react/core/AstroIcon.js.map +1 -0
  133. package/dist/react/core/Badge.d.ts +27 -0
  134. package/dist/react/core/Badge.js +134 -0
  135. package/dist/react/core/Badge.js.map +1 -0
  136. package/dist/react/core/Button.d.ts +26 -0
  137. package/dist/react/core/Button.js +306 -0
  138. package/dist/react/core/Button.js.map +1 -0
  139. package/dist/react/core/CardHeader.d.ts +34 -0
  140. package/dist/react/core/CardHeader.js +316 -0
  141. package/dist/react/core/CardHeader.js.map +1 -0
  142. package/dist/react/core/ChatPanel.d.ts +627 -0
  143. package/dist/react/core/ChatPanel.js +1144 -0
  144. package/dist/react/core/ChatPanel.js.map +1 -0
  145. package/dist/react/core/Checkbox.d.ts +26 -0
  146. package/dist/react/core/Checkbox.js +130 -0
  147. package/dist/react/core/Checkbox.js.map +1 -0
  148. package/dist/react/core/ColorPickerPanel.d.ts +25 -0
  149. package/dist/react/core/ColorPickerPanel.js +293 -0
  150. package/dist/react/core/ColorPickerPanel.js.map +1 -0
  151. package/dist/react/core/CommandBuilder.d.ts +74 -0
  152. package/dist/react/core/CommandBuilder.js +518 -0
  153. package/dist/react/core/CommandBuilder.js.map +1 -0
  154. package/dist/react/core/ConfirmDialog.d.ts +45 -0
  155. package/dist/react/core/ConfirmDialog.js +315 -0
  156. package/dist/react/core/ConfirmDialog.js.map +1 -0
  157. package/dist/react/core/ConnectionForm.d.ts +57 -0
  158. package/dist/react/core/ConnectionForm.js +496 -0
  159. package/dist/react/core/ConnectionForm.js.map +1 -0
  160. package/dist/react/core/Container.d.ts +51 -0
  161. package/dist/react/core/Container.js +670 -0
  162. package/dist/react/core/Container.js.map +1 -0
  163. package/dist/react/core/CopyButton.d.ts +39 -0
  164. package/dist/react/core/CopyButton.js +105 -0
  165. package/dist/react/core/CopyButton.js.map +1 -0
  166. package/dist/react/core/DataTable.d.ts +113 -0
  167. package/dist/react/core/DataTable.js +446 -0
  168. package/dist/react/core/DataTable.js.map +1 -0
  169. package/dist/react/core/DataValue.d.ts +64 -0
  170. package/dist/react/core/DataValue.js +545 -0
  171. package/dist/react/core/DataValue.js.map +1 -0
  172. package/dist/react/core/Dialog.d.ts +32 -0
  173. package/dist/react/core/Dialog.js +201 -0
  174. package/dist/react/core/Dialog.js.map +1 -0
  175. package/dist/react/core/FileExplorer.d.ts +65 -0
  176. package/dist/react/core/FileExplorer.js +520 -0
  177. package/dist/react/core/FileExplorer.js.map +1 -0
  178. package/dist/react/core/GlassCard.d.ts +129 -0
  179. package/dist/react/core/GlassCard.js +375 -0
  180. package/dist/react/core/GlassCard.js.map +1 -0
  181. package/dist/react/core/HeaderIconWithStatus.d.ts +39 -0
  182. package/dist/react/core/HeaderIconWithStatus.js +157 -0
  183. package/dist/react/core/HeaderIconWithStatus.js.map +1 -0
  184. package/dist/react/core/HexViewer.d.ts +143 -0
  185. package/dist/react/core/HexViewer.js +1106 -0
  186. package/dist/react/core/HexViewer.js.map +1 -0
  187. package/dist/react/core/Icon.d.ts +32 -0
  188. package/dist/react/core/Icon.js +142 -0
  189. package/dist/react/core/Icon.js.map +1 -0
  190. package/dist/react/core/ImageGallery.d.ts +41 -0
  191. package/dist/react/core/ImageGallery.js +320 -0
  192. package/dist/react/core/ImageGallery.js.map +1 -0
  193. package/dist/react/core/Input.d.ts +38 -0
  194. package/dist/react/core/Input.js +288 -0
  195. package/dist/react/core/Input.js.map +1 -0
  196. package/dist/react/core/LimitsBar.d.ts +51 -0
  197. package/dist/react/core/LimitsBar.js +200 -0
  198. package/dist/react/core/LimitsBar.js.map +1 -0
  199. package/dist/react/core/LogViewer.d.ts +61 -0
  200. package/dist/react/core/LogViewer.js +599 -0
  201. package/dist/react/core/LogViewer.js.map +1 -0
  202. package/dist/react/core/MessageStream.d.ts +58 -0
  203. package/dist/react/core/MessageStream.js +455 -0
  204. package/dist/react/core/MessageStream.js.map +1 -0
  205. package/dist/react/core/MissionCalendar.d.ts +81 -0
  206. package/dist/react/core/MissionCalendar.js +1049 -0
  207. package/dist/react/core/MissionCalendar.js.map +1 -0
  208. package/dist/react/core/NumberInput.d.ts +85 -0
  209. package/dist/react/core/NumberInput.js +507 -0
  210. package/dist/react/core/NumberInput.js.map +1 -0
  211. package/dist/react/core/PacketViewer.d.ts +73 -0
  212. package/dist/react/core/PacketViewer.js +431 -0
  213. package/dist/react/core/PacketViewer.js.map +1 -0
  214. package/dist/react/core/Pagination.d.ts +30 -0
  215. package/dist/react/core/Pagination.js +190 -0
  216. package/dist/react/core/Pagination.js.map +1 -0
  217. package/dist/react/core/PinInput.d.ts +41 -0
  218. package/dist/react/core/PinInput.js +210 -0
  219. package/dist/react/core/PinInput.js.map +1 -0
  220. package/dist/react/core/Popover.d.ts +55 -0
  221. package/dist/react/core/Popover.js +288 -0
  222. package/dist/react/core/Popover.js.map +1 -0
  223. package/dist/react/core/Select.d.ts +42 -0
  224. package/dist/react/core/Select.js +303 -0
  225. package/dist/react/core/Select.js.map +1 -0
  226. package/dist/react/core/SideNav.d.ts +103 -0
  227. package/dist/react/core/SideNav.js +551 -0
  228. package/dist/react/core/SideNav.js.map +1 -0
  229. package/dist/react/core/SidePanel.d.ts +33 -0
  230. package/dist/react/core/SidePanel.js +199 -0
  231. package/dist/react/core/SidePanel.js.map +1 -0
  232. package/dist/react/core/Tabs.d.ts +47 -0
  233. package/dist/react/core/Tabs.js +129 -0
  234. package/dist/react/core/Tabs.js.map +1 -0
  235. package/dist/react/core/Toast.d.ts +56 -0
  236. package/dist/react/core/Toast.js +229 -0
  237. package/dist/react/core/Toast.js.map +1 -0
  238. package/dist/react/core/Toggle.d.ts +22 -0
  239. package/dist/react/core/Toggle.js +151 -0
  240. package/dist/react/core/Toggle.js.map +1 -0
  241. package/dist/react/core/Tooltip.d.ts +19 -0
  242. package/dist/react/core/Tooltip.js +179 -0
  243. package/dist/react/core/Tooltip.js.map +1 -0
  244. package/dist/react/core/Typography.d.ts +127 -0
  245. package/dist/react/core/Typography.js +187 -0
  246. package/dist/react/core/Typography.js.map +1 -0
  247. package/dist/react/core/index.d.ts +108 -0
  248. package/dist/react/core/layout/Box.d.ts +77 -0
  249. package/dist/react/core/layout/Box.js +126 -0
  250. package/dist/react/core/layout/Box.js.map +1 -0
  251. package/dist/react/core/layout/Center.d.ts +20 -0
  252. package/dist/react/core/layout/Center.js +34 -0
  253. package/dist/react/core/layout/Center.js.map +1 -0
  254. package/dist/react/core/layout/Divider.d.ts +16 -0
  255. package/dist/react/core/layout/Divider.js +108 -0
  256. package/dist/react/core/layout/Divider.js.map +1 -0
  257. package/dist/react/core/layout/Flex.d.ts +30 -0
  258. package/dist/react/core/layout/Flex.js +128 -0
  259. package/dist/react/core/layout/Flex.js.map +1 -0
  260. package/dist/react/core/layout/Grid.d.ts +36 -0
  261. package/dist/react/core/layout/Grid.js +142 -0
  262. package/dist/react/core/layout/Grid.js.map +1 -0
  263. package/dist/react/core/layout/Spacer.d.ts +8 -0
  264. package/dist/react/core/layout/Spacer.js +31 -0
  265. package/dist/react/core/layout/Spacer.js.map +1 -0
  266. package/dist/react/core/layout/Stack.d.ts +54 -0
  267. package/dist/react/core/layout/Stack.js +74 -0
  268. package/dist/react/core/layout/Stack.js.map +1 -0
  269. package/dist/react/core/layout/index.d.ts +38 -0
  270. package/dist/react/core/layout/responsive.d.ts +23 -0
  271. package/dist/react/core/layout/responsive.js +26 -0
  272. package/dist/react/core/layout/responsive.js.map +1 -0
  273. package/dist/react/core/layout/useBreakpoint.d.ts +77 -0
  274. package/dist/react/core/layout/useBreakpoint.js +73 -0
  275. package/dist/react/core/layout/useBreakpoint.js.map +1 -0
  276. package/dist/react/core/propertyConfig.d.ts +443 -0
  277. package/dist/react/core/propertyConfig.js +399 -0
  278. package/dist/react/core/propertyConfig.js.map +1 -0
  279. package/dist/react/hooks/index.d.ts +21 -0
  280. package/dist/react/hooks/useAccessWindows.d.ts +66 -0
  281. package/dist/react/hooks/useCompactMode.d.ts +82 -0
  282. package/dist/react/hooks/useCompactMode.js +62 -0
  283. package/dist/react/hooks/useCompactMode.js.map +1 -0
  284. package/dist/react/hooks/useLiveSelection.d.ts +57 -0
  285. package/dist/react/hooks/useSimulationPlayback.d.ts +97 -0
  286. package/dist/react/hooks/useSimulationTime.d.ts +61 -0
  287. package/dist/react/hooks/useSpacecraftPosition.d.ts +50 -0
  288. package/dist/react/hooks/useSpacecraftPosition.js +89 -0
  289. package/dist/react/hooks/useSpacecraftPosition.js.map +1 -0
  290. package/dist/react/hooks/useTelemetry.d.ts +55 -0
  291. package/dist/react/hooks/useTelemetry.js +73 -0
  292. package/dist/react/hooks/useTelemetry.js.map +1 -0
  293. package/dist/react/hooks/useZendirSession.d.ts +109 -0
  294. package/dist/react/hooks/useZendirSession.js +148 -0
  295. package/dist/react/hooks/useZendirSession.js.map +1 -0
  296. package/dist/react/index.d.ts +74 -0
  297. package/dist/react/shared/ErrorBoundary.d.ts +63 -0
  298. package/dist/react/shared/ErrorBoundary.js +142 -0
  299. package/dist/react/shared/ErrorBoundary.js.map +1 -0
  300. package/dist/react/shared/Skeleton.d.ts +110 -0
  301. package/dist/react/shared/Skeleton.js +324 -0
  302. package/dist/react/shared/Skeleton.js.map +1 -0
  303. package/dist/react/shared/index.d.ts +12 -0
  304. package/dist/react/theme/ThemeProvider.d.ts +385 -0
  305. package/dist/react/theme/ThemeProvider.js +1096 -0
  306. package/dist/react/theme/ThemeProvider.js.map +1 -0
  307. package/dist/react/theme/astro-tokens.d.ts +153 -0
  308. package/dist/react/theme/cardAccent.d.ts +75 -0
  309. package/dist/react/theme/cardAccent.js +137 -0
  310. package/dist/react/theme/cardAccent.js.map +1 -0
  311. package/dist/react/theme/config.d.ts +39 -0
  312. package/dist/react/theme/index.d.ts +9 -0
  313. package/dist/react/types.d.ts +360 -0
  314. package/dist/react/types.js +58 -0
  315. package/dist/react/types.js.map +1 -0
  316. package/dist/react/utils/index.d.ts +247 -0
  317. package/dist/react/utils/index.js +423 -0
  318. package/dist/react/utils/index.js.map +1 -0
  319. package/dist/react/visualizations/EclipseTimerCard.d.ts +17 -0
  320. package/dist/react/visualizations/EclipseTimerCard.js +250 -0
  321. package/dist/react/visualizations/EclipseTimerCard.js.map +1 -0
  322. package/dist/react/visualizations/LinkBudgetCard.d.ts +50 -0
  323. package/dist/react/visualizations/LinkBudgetCard.js +444 -0
  324. package/dist/react/visualizations/LinkBudgetCard.js.map +1 -0
  325. package/dist/react/visualizations/NavBallCard.d.ts +17 -0
  326. package/dist/react/visualizations/NavBallCard.js +243 -0
  327. package/dist/react/visualizations/NavBallCard.js.map +1 -0
  328. package/dist/react/visualizations/PropulsionCard.d.ts +37 -0
  329. package/dist/react/visualizations/PropulsionCard.js +298 -0
  330. package/dist/react/visualizations/PropulsionCard.js.map +1 -0
  331. package/dist/react/visualizations/SensorFootprintCard.d.ts +33 -0
  332. package/dist/react/visualizations/SensorFootprintCard.js +326 -0
  333. package/dist/react/visualizations/SensorFootprintCard.js.map +1 -0
  334. package/dist/react/visualizations/ThermalHeatmapCard.d.ts +38 -0
  335. package/dist/react/visualizations/ThermalHeatmapCard.js +372 -0
  336. package/dist/react/visualizations/ThermalHeatmapCard.js.map +1 -0
  337. package/dist/react/visualizations/index.d.ts +17 -0
  338. package/dist/react.d.ts +1 -0
  339. package/dist/react.js +421 -0
  340. package/dist/react.js.map +1 -0
  341. package/dist/shaders/atmosphere.frag.js +5 -0
  342. package/dist/shaders/atmosphere.frag.js.map +1 -0
  343. package/dist/shaders/atmosphere.vert.js +5 -0
  344. package/dist/shaders/atmosphere.vert.js.map +1 -0
  345. package/dist/shaders/stars.frag.js +5 -0
  346. package/dist/shaders/stars.frag.js.map +1 -0
  347. package/dist/shaders/stars.vert.js +5 -0
  348. package/dist/shaders/stars.vert.js.map +1 -0
  349. package/dist/style.css +143 -0
  350. package/dist/tokens/index.d.ts +296 -0
  351. package/dist/tokens/index.js +263 -0
  352. package/dist/tokens/index.js.map +1 -0
  353. package/dist/tokens/tokens.css +155 -0
  354. package/dist/types/index.d.ts +23 -0
  355. package/dist/types.d.ts +1 -0
  356. package/dist/types.js +2 -0
  357. package/dist/types.js.map +1 -0
  358. package/package.json +220 -0
  359. package/sdk-stub.js +22 -0
@@ -0,0 +1,3168 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { memo, forwardRef, useMemo, useState, useEffect } from "react";
3
+ import { AstroChart } from "./AstroChart.js";
4
+ import { ASTRO_DATA_VIZ_COLORS, ZENDIR_BRAND_COLORS, STATUS_COLORS } from "./theme.js";
5
+ import { useTheme } from "../../theme/ThemeProvider.js";
6
+ let _echartsGlReady = false;
7
+ let _echartsGlPromise = null;
8
+ function _loadEchartsGl() {
9
+ if (!_echartsGlPromise) {
10
+ _echartsGlPromise = import("echarts-gl").then(() => {
11
+ _echartsGlReady = true;
12
+ return true;
13
+ }).catch((err) => {
14
+ console.warn("[zendir-ui] echarts-gl failed to load — 3D charts will not render:", err);
15
+ return false;
16
+ });
17
+ }
18
+ return _echartsGlPromise;
19
+ }
20
+ _loadEchartsGl();
21
+ function useEchartsGlReady() {
22
+ const [ready, setReady] = useState(_echartsGlReady);
23
+ useEffect(() => {
24
+ if (!_echartsGlReady) {
25
+ _loadEchartsGl().then((ok) => {
26
+ if (ok) setReady(true);
27
+ });
28
+ }
29
+ }, []);
30
+ return ready;
31
+ }
32
+ const SOFT_STATUS_COLORS = {
33
+ normal: "#6ed86e",
34
+ caution: "#ffd54f",
35
+ critical: "#e57373",
36
+ standby: "#4fc3f7"
37
+ };
38
+ function useChartTooltipStyle() {
39
+ const { tokens, mode } = useTheme();
40
+ const isDark = mode === "dark";
41
+ return {
42
+ backgroundColor: isDark ? "rgba(15, 23, 42, 0.95)" : "rgba(255, 255, 255, 0.95)",
43
+ borderColor: isDark ? "rgba(100, 116, 139, 0.4)" : "rgba(100, 116, 139, 0.3)",
44
+ textStyle: {
45
+ color: tokens.colors.text.primary,
46
+ fontSize: 12
47
+ }
48
+ };
49
+ }
50
+ function useChartLegendStyle() {
51
+ const { tokens } = useTheme();
52
+ return {
53
+ textStyle: {
54
+ color: tokens.colors.text.secondary
55
+ }
56
+ };
57
+ }
58
+ function useChartVisualMapStyle() {
59
+ const { tokens } = useTheme();
60
+ return {
61
+ textStyle: {
62
+ color: tokens.colors.text.tertiary
63
+ },
64
+ // Allow drag selection on the visualMap bar
65
+ calculable: true,
66
+ // Enable hover linking - when hovering on visualMap, highlight only that range
67
+ hoverLink: true,
68
+ // Non-hovered regions get faded opacity (not invisible, just light)
69
+ outOfRange: {
70
+ color: "rgba(128, 128, 128, 0.12)",
71
+ // Very light gray with low opacity
72
+ opacity: 0.15
73
+ // Also reduce opacity for 3D elements
74
+ },
75
+ // Handle styles for the interactive bar (the draggable endpoints)
76
+ handleStyle: {
77
+ borderColor: tokens.colors.accent.primary,
78
+ color: tokens.colors.accent.primary
79
+ },
80
+ // Indicator style when hovering
81
+ indicatorStyle: {
82
+ borderColor: "#fff"
83
+ },
84
+ // Smooth transition when highlighting
85
+ realtime: true
86
+ };
87
+ }
88
+ const PowerChart = memo(forwardRef(
89
+ function PowerChart2({
90
+ data = [],
91
+ title = "Power system",
92
+ showLegend = true,
93
+ width = "100%",
94
+ height = 250,
95
+ showEclipse = true,
96
+ loading = false,
97
+ enableZoom = false,
98
+ className = "",
99
+ export: exportOptions,
100
+ infoTooltip,
101
+ // Icon/status props
102
+ icon,
103
+ iconStatus,
104
+ statusMessage
105
+ }, ref) {
106
+ const { series, annotations } = useMemo(() => {
107
+ const solarSeries = {
108
+ id: "solar",
109
+ name: "Solar",
110
+ type: "line",
111
+ data: data.map((d) => ({ x: d.time, y: d.solarPower })),
112
+ color: SOFT_STATUS_COLORS.standby,
113
+ // Cyan for solar
114
+ yAxisIndex: 0,
115
+ smooth: true,
116
+ symbol: { type: "none" }
117
+ };
118
+ const batterySeries = {
119
+ id: "battery",
120
+ name: "Battery",
121
+ type: "line",
122
+ data: data.map((d) => ({ x: d.time, y: d.batteryPercent })),
123
+ color: SOFT_STATUS_COLORS.normal,
124
+ // Green for battery
125
+ yAxisIndex: 1,
126
+ smooth: true,
127
+ symbol: { type: "none" }
128
+ };
129
+ const netPowerSeries = {
130
+ id: "netPower",
131
+ name: "Net",
132
+ type: "line",
133
+ data: data.map((d) => ({ x: d.time, y: d.netPower })),
134
+ color: ZENDIR_BRAND_COLORS.electric,
135
+ // Zendir Electric
136
+ yAxisIndex: 0,
137
+ smooth: true,
138
+ symbol: { type: "none" }
139
+ };
140
+ const consumptionSeries = {
141
+ id: "consumption",
142
+ name: "Load",
143
+ type: "line",
144
+ data: data.map((d) => ({ x: d.time, y: d.consumption })),
145
+ color: SOFT_STATUS_COLORS.critical,
146
+ // Red for consumption
147
+ yAxisIndex: 0,
148
+ lineStyle: { type: "dashed", width: 1.5 },
149
+ smooth: true,
150
+ symbol: { type: "none" }
151
+ };
152
+ const eclipseAreas = { data: [] };
153
+ if (showEclipse) {
154
+ let inEclipse = false;
155
+ let eclipseStart = 0;
156
+ data.forEach((d, _i) => {
157
+ if (d.eclipse && !inEclipse) {
158
+ inEclipse = true;
159
+ eclipseStart = d.time;
160
+ } else if (!d.eclipse && inEclipse) {
161
+ inEclipse = false;
162
+ eclipseAreas.data.push([
163
+ { xAxis: eclipseStart, name: "Eclipse" },
164
+ { xAxis: d.time }
165
+ ]);
166
+ }
167
+ });
168
+ if (inEclipse && data.length > 0) {
169
+ eclipseAreas.data.push([
170
+ { xAxis: eclipseStart, name: "Eclipse" },
171
+ { xAxis: data[data.length - 1].time }
172
+ ]);
173
+ }
174
+ eclipseAreas.itemStyle = {
175
+ color: `${STATUS_COLORS.critical}15`
176
+ };
177
+ }
178
+ return {
179
+ series: [solarSeries, batterySeries, netPowerSeries, consumptionSeries],
180
+ annotations: showEclipse && eclipseAreas.data.length > 0 ? { markAreas: eclipseAreas } : void 0
181
+ };
182
+ }, [data, showEclipse]);
183
+ const tooltipConfig = useMemo(() => ({
184
+ trigger: "axis",
185
+ crosshair: "x",
186
+ formatter: (params) => {
187
+ var _a;
188
+ const p = Array.isArray(params) ? params : [];
189
+ if (p.length === 0) return "";
190
+ const axisVal = p[0].axisValue ?? p[0].value;
191
+ const time = typeof axisVal === "number" ? axisVal : axisVal instanceof Date ? axisVal.getTime() : Number(axisVal);
192
+ const inEclipse = ((_a = annotations == null ? void 0 : annotations.markAreas) == null ? void 0 : _a.data) ? annotations.markAreas.data.some(
193
+ (pair) => {
194
+ const start = pair[0].xAxis ?? 0;
195
+ const end = pair[1].xAxis ?? 0;
196
+ return time >= start && time <= end;
197
+ }
198
+ ) : false;
199
+ const lines = p.map(
200
+ (item) => `${item.marker ?? ""} ${item.seriesName ?? ""}: ${item.value ?? ""}`
201
+ );
202
+ if (inEclipse) lines.push("◐ Eclipse — spacecraft in shadow; solar panels off");
203
+ return lines.join("<br/>");
204
+ }
205
+ }), [annotations]);
206
+ return /* @__PURE__ */ jsx(
207
+ AstroChart,
208
+ {
209
+ ref,
210
+ type: "line",
211
+ title,
212
+ series,
213
+ width,
214
+ height,
215
+ loading,
216
+ className,
217
+ icon,
218
+ iconStatus,
219
+ statusMessage,
220
+ xAxis: { type: "time", name: "" },
221
+ yAxis: [
222
+ {
223
+ name: "Power [W]",
224
+ position: "left",
225
+ min: 0
226
+ },
227
+ {
228
+ name: "Battery [%]",
229
+ position: "right",
230
+ min: 0,
231
+ max: 100
232
+ }
233
+ ],
234
+ tooltip: tooltipConfig,
235
+ legend: { show: showLegend, position: "bottom" },
236
+ zoom: enableZoom ? { enabled: true, type: "inside", axis: "x" } : void 0,
237
+ annotations,
238
+ export: exportOptions,
239
+ infoTooltip
240
+ }
241
+ );
242
+ }
243
+ ));
244
+ const AttitudeChart = memo(forwardRef(
245
+ function AttitudeChart2({
246
+ data = [],
247
+ title = "Attitude control",
248
+ showLegend = true,
249
+ width = "100%",
250
+ height = 200,
251
+ loading = false,
252
+ enableZoom = false,
253
+ showError = true,
254
+ showAngularVelocity = true,
255
+ className = "",
256
+ export: exportOptions,
257
+ infoTooltip,
258
+ // Icon/status props
259
+ icon,
260
+ iconStatus,
261
+ statusMessage
262
+ }, ref) {
263
+ const series = useMemo(() => {
264
+ const result = [
265
+ {
266
+ id: "roll",
267
+ name: "Roll",
268
+ type: "line",
269
+ data: data.map((d) => ({ x: d.time, y: d.roll })),
270
+ color: SOFT_STATUS_COLORS.critical,
271
+ // Red
272
+ smooth: true,
273
+ symbol: { type: "none" }
274
+ },
275
+ {
276
+ id: "pitch",
277
+ name: "Pitch",
278
+ type: "line",
279
+ data: data.map((d) => ({ x: d.time, y: d.pitch })),
280
+ color: SOFT_STATUS_COLORS.normal,
281
+ // Green
282
+ smooth: true,
283
+ symbol: { type: "none" }
284
+ },
285
+ {
286
+ id: "yaw",
287
+ name: "Yaw",
288
+ type: "line",
289
+ data: data.map((d) => ({ x: d.time, y: d.yaw })),
290
+ color: ZENDIR_BRAND_COLORS.electric,
291
+ // Zendir Electric
292
+ smooth: true,
293
+ symbol: { type: "none" }
294
+ }
295
+ ];
296
+ if (showError && data.some((d) => d.pointingError !== void 0)) {
297
+ result.push({
298
+ id: "error",
299
+ name: "Error",
300
+ type: "line",
301
+ data: data.filter((d) => d.pointingError !== void 0).map((d) => ({ x: d.time, y: d.pointingError })),
302
+ color: SOFT_STATUS_COLORS.caution,
303
+ // Yellow (status color)
304
+ smooth: true,
305
+ symbol: { type: "none" },
306
+ lineStyle: { width: 1.5 }
307
+ });
308
+ }
309
+ if (showAngularVelocity && data.some((d) => d.angularVelocity !== void 0)) {
310
+ result.push({
311
+ id: "angVel",
312
+ name: "ω",
313
+ type: "line",
314
+ data: data.filter((d) => d.angularVelocity !== void 0).map((d) => ({ x: d.time, y: d.angularVelocity })),
315
+ color: ZENDIR_BRAND_COLORS.purple,
316
+ // Zendir Purple
317
+ smooth: true,
318
+ symbol: { type: "none" },
319
+ lineStyle: { type: "dashed", width: 1 }
320
+ });
321
+ }
322
+ return result;
323
+ }, [data, showError, showAngularVelocity]);
324
+ return /* @__PURE__ */ jsx(
325
+ AstroChart,
326
+ {
327
+ ref,
328
+ type: "line",
329
+ title,
330
+ series,
331
+ width,
332
+ height,
333
+ loading,
334
+ className,
335
+ icon,
336
+ iconStatus,
337
+ statusMessage,
338
+ xAxis: { type: "time", name: "" },
339
+ yAxis: {
340
+ name: "Attitude [deg]"
341
+ // Center zero line
342
+ },
343
+ tooltip: { trigger: "axis", crosshair: "x" },
344
+ legend: { show: showLegend, position: "bottom" },
345
+ zoom: enableZoom ? { enabled: true, type: "inside", axis: "x" } : void 0,
346
+ annotations: {
347
+ markLines: {
348
+ data: [{ yAxis: 0, label: "", lineStyle: { type: "solid", width: 1 } }]
349
+ }
350
+ },
351
+ export: exportOptions,
352
+ infoTooltip
353
+ }
354
+ );
355
+ }
356
+ ));
357
+ const ThermalHeatmapChart = memo(forwardRef(
358
+ function ThermalHeatmapChart2({
359
+ data = [],
360
+ zones = [],
361
+ title = "Thermal zones",
362
+ width = "100%",
363
+ height = 300,
364
+ range = [-40, 80],
365
+ loading = false,
366
+ className = "",
367
+ export: exportOptions,
368
+ infoTooltip
369
+ }, ref) {
370
+ const { series, timeLabels } = useMemo(() => {
371
+ const timeLabels2 = data.map(
372
+ (d) => new Date(d.time).toLocaleTimeString([], {
373
+ hour: "2-digit",
374
+ minute: "2-digit",
375
+ hour12: false
376
+ })
377
+ );
378
+ const heatmapData = [];
379
+ data.forEach((d, timeIdx) => {
380
+ zones.forEach((zone, zoneIdx) => {
381
+ const temp = d.zones[zone] ?? 0;
382
+ heatmapData.push([timeIdx, zoneIdx, temp]);
383
+ });
384
+ });
385
+ return {
386
+ series: [{
387
+ id: "thermal",
388
+ name: "Temperature",
389
+ type: "heatmap",
390
+ data: heatmapData
391
+ }],
392
+ timeLabels: timeLabels2
393
+ };
394
+ }, [data, zones]);
395
+ return /* @__PURE__ */ jsx(
396
+ AstroChart,
397
+ {
398
+ ref,
399
+ type: "heatmap",
400
+ title,
401
+ series,
402
+ width,
403
+ height,
404
+ loading,
405
+ className,
406
+ xAxis: { type: "category" },
407
+ yAxis: { type: "category" },
408
+ tooltip: { trigger: "item" },
409
+ echartsOptions: {
410
+ xAxis: { data: timeLabels },
411
+ yAxis: { data: zones },
412
+ visualMap: {
413
+ min: range[0],
414
+ max: range[1],
415
+ calculable: true,
416
+ orient: "vertical",
417
+ right: 10,
418
+ top: "center",
419
+ // Enable hover linking - highlight only hovered range
420
+ hoverLink: true,
421
+ // Non-hovered regions get faded opacity
422
+ outOfRange: {
423
+ color: "rgba(128, 128, 128, 0.12)",
424
+ opacity: 0.15
425
+ },
426
+ // Thermal gradient (cold → hot) - Original high-contrast palette
427
+ // Multi-hue gradient for clear temperature differentiation
428
+ inRange: {
429
+ color: [
430
+ "#313695",
431
+ // Deep blue (very cold)
432
+ "#4575b4",
433
+ // Blue
434
+ "#74add1",
435
+ // Light blue
436
+ "#abd9e9",
437
+ // Pale blue
438
+ "#e0f3f8",
439
+ // Very pale blue
440
+ "#ffffbf",
441
+ // Pale yellow (neutral)
442
+ "#fee090",
443
+ // Light orange
444
+ "#fdae61",
445
+ // Orange
446
+ "#f46d43",
447
+ // Red-orange
448
+ "#d73027",
449
+ // Red
450
+ "#a50026"
451
+ // Dark red (very hot)
452
+ ]
453
+ }
454
+ },
455
+ series: [{
456
+ type: "heatmap",
457
+ data: series[0].data,
458
+ label: { show: true, formatter: (p) => Array.isArray(p.value) && typeof p.value[2] === "number" ? `${p.value[2]}°` : "" },
459
+ emphasis: {
460
+ itemStyle: {
461
+ shadowBlur: 10,
462
+ shadowColor: "rgba(0, 0, 0, 0.5)"
463
+ }
464
+ }
465
+ }]
466
+ },
467
+ export: exportOptions,
468
+ infoTooltip
469
+ }
470
+ );
471
+ }
472
+ ));
473
+ const LinkBudgetChart = memo(forwardRef(
474
+ function LinkBudgetChart2({
475
+ data = [],
476
+ title = "Link budget",
477
+ showLegend = true,
478
+ width = "100%",
479
+ height = 200,
480
+ marginThreshold = 3,
481
+ loading = false,
482
+ className = "",
483
+ export: exportOptions,
484
+ infoTooltip
485
+ }, ref) {
486
+ const series = useMemo(() => [
487
+ {
488
+ id: "signal",
489
+ name: "Signal",
490
+ type: "area",
491
+ data: data.map((d) => ({ x: d.time, y: d.signalStrength })),
492
+ color: SOFT_STATUS_COLORS.normal,
493
+ smooth: true,
494
+ symbol: { type: "none" },
495
+ areaStyle: { opacity: 0.2 }
496
+ },
497
+ {
498
+ id: "noise",
499
+ name: "Noise floor",
500
+ type: "line",
501
+ data: data.map((d) => ({ x: d.time, y: d.noiseFloor })),
502
+ color: SOFT_STATUS_COLORS.critical,
503
+ smooth: true,
504
+ symbol: { type: "none" },
505
+ lineStyle: { type: "dashed", width: 1 }
506
+ },
507
+ {
508
+ id: "margin",
509
+ name: "Margin",
510
+ type: "line",
511
+ data: data.map((d) => ({ x: d.time, y: d.margin })),
512
+ color: SOFT_STATUS_COLORS.standby,
513
+ yAxisIndex: 1,
514
+ smooth: true,
515
+ symbol: { type: "none" }
516
+ }
517
+ ], [data]);
518
+ return /* @__PURE__ */ jsx(
519
+ AstroChart,
520
+ {
521
+ ref,
522
+ type: "line",
523
+ title,
524
+ series,
525
+ width,
526
+ height,
527
+ loading,
528
+ className,
529
+ xAxis: { type: "time" },
530
+ yAxis: [
531
+ { name: "dBm", position: "left" },
532
+ { name: "Margin [dB]", position: "right", min: 0 }
533
+ ],
534
+ tooltip: { trigger: "axis", crosshair: "x" },
535
+ legend: { show: showLegend, position: "bottom" },
536
+ annotations: {
537
+ markLines: {
538
+ data: [
539
+ {
540
+ yAxis: marginThreshold,
541
+ label: `Min margin (${marginThreshold} dB)`,
542
+ color: SOFT_STATUS_COLORS.caution,
543
+ lineStyle: { type: "dashed" }
544
+ }
545
+ ]
546
+ }
547
+ },
548
+ export: exportOptions,
549
+ infoTooltip
550
+ }
551
+ );
552
+ }
553
+ ));
554
+ const SubsystemGauge = memo(forwardRef(
555
+ function SubsystemGauge2({
556
+ value,
557
+ name,
558
+ unit = "%",
559
+ width = 200,
560
+ height = 200,
561
+ thresholds = { caution: 70, critical: 90 },
562
+ loading = false,
563
+ className = "",
564
+ export: exportOptions,
565
+ infoTooltip
566
+ }, ref) {
567
+ const clampedValue = Math.max(0, Math.min(100, value));
568
+ const widthPx = typeof width === "number" ? width : height;
569
+ const gaugeSize = Math.max(110, Math.min(widthPx, height));
570
+ const arcWidth = Math.max(8, Math.round(gaugeSize * 0.085));
571
+ const valueFontSize = Math.max(18, Math.round(gaugeSize * 0.17));
572
+ const titleFontSize = Math.max(10, Math.round(gaugeSize * 0.085));
573
+ const compactGauge = gaugeSize < 150;
574
+ const centerY = compactGauge ? "53%" : "55%";
575
+ const detailY = compactGauge ? "10%" : "15%";
576
+ const titleY = compactGauge ? "78%" : "84%";
577
+ const unitSuffix = (unit == null ? void 0 : unit.trim()) ?? "";
578
+ const longUnit = unitSuffix.length > 4;
579
+ const getValueColor = () => {
580
+ if (thresholds.critical && clampedValue >= thresholds.critical) return SOFT_STATUS_COLORS.critical;
581
+ if (thresholds.caution && clampedValue >= thresholds.caution) return SOFT_STATUS_COLORS.caution;
582
+ return SOFT_STATUS_COLORS.normal;
583
+ };
584
+ return /* @__PURE__ */ jsx(
585
+ AstroChart,
586
+ {
587
+ ref,
588
+ type: "gauge",
589
+ series: [],
590
+ width,
591
+ height,
592
+ loading,
593
+ className,
594
+ echartsOptions: {
595
+ series: [{
596
+ type: "gauge",
597
+ min: 0,
598
+ max: 100,
599
+ startAngle: 200,
600
+ endAngle: -20,
601
+ radius: "90%",
602
+ center: ["50%", centerY],
603
+ // Modern minimal track
604
+ axisLine: {
605
+ lineStyle: {
606
+ width: arcWidth,
607
+ color: [[1, "rgba(100, 116, 139, 0.15)"]]
608
+ // Subtle track
609
+ }
610
+ },
611
+ // Hide all traditional gauge elements
612
+ axisTick: { show: false },
613
+ splitLine: { show: false },
614
+ axisLabel: { show: false },
615
+ pointer: { show: false },
616
+ // No pointer for modern look
617
+ // Progress arc with gradient
618
+ progress: {
619
+ show: true,
620
+ width: arcWidth,
621
+ roundCap: true,
622
+ itemStyle: {
623
+ color: {
624
+ type: "linear",
625
+ x: 0,
626
+ y: 0,
627
+ x2: 1,
628
+ y2: 0,
629
+ colorStops: [
630
+ { offset: 0, color: "rgba(100, 200, 200, 0.6)" },
631
+ { offset: 1, color: getValueColor() }
632
+ ]
633
+ },
634
+ shadowColor: getValueColor(),
635
+ shadowBlur: 8
636
+ }
637
+ },
638
+ // Clean title below
639
+ title: {
640
+ show: true,
641
+ offsetCenter: [0, titleY],
642
+ fontSize: titleFontSize,
643
+ fontWeight: 500,
644
+ color: "rgba(255, 255, 255, 0.7)"
645
+ },
646
+ // Modern centered value
647
+ detail: {
648
+ valueAnimation: true,
649
+ formatter: (currentValue) => {
650
+ const rounded = Math.round(currentValue);
651
+ if (!unitSuffix) return `${rounded}`;
652
+ if (longUnit) return `${rounded}
653
+ {unit|${unitSuffix}}`;
654
+ return `${rounded}${unitSuffix}`;
655
+ },
656
+ fontSize: valueFontSize,
657
+ fontWeight: 700,
658
+ // AstroUXDS bold for gauge values
659
+ lineHeight: Math.round(valueFontSize * 1.05),
660
+ offsetCenter: [0, detailY],
661
+ color: getValueColor(),
662
+ rich: {
663
+ unit: {
664
+ color: "rgba(255, 255, 255, 0.75)",
665
+ fontSize: Math.max(10, Math.round(valueFontSize * 0.5)),
666
+ fontWeight: 500,
667
+ lineHeight: Math.round(valueFontSize * 0.8)
668
+ }
669
+ }
670
+ },
671
+ data: [{ value: clampedValue, name }]
672
+ }]
673
+ },
674
+ export: exportOptions,
675
+ infoTooltip
676
+ }
677
+ );
678
+ }
679
+ ));
680
+ const OrbitChart = memo(forwardRef(
681
+ function OrbitChart2({
682
+ data = [],
683
+ title = "Polar Projection",
684
+ referenceAltitude,
685
+ width = 300,
686
+ height = 300,
687
+ loading = false,
688
+ className = "",
689
+ export: exportOptions,
690
+ infoTooltip
691
+ }, ref) {
692
+ return /* @__PURE__ */ jsx(
693
+ AstroChart,
694
+ {
695
+ ref,
696
+ type: "scatter",
697
+ title,
698
+ series: [],
699
+ width,
700
+ height,
701
+ loading,
702
+ className,
703
+ echartsOptions: {
704
+ polar: {
705
+ radius: ["0%", "75%"],
706
+ center: ["50%", "50%"]
707
+ },
708
+ angleAxis: {
709
+ type: "value",
710
+ min: 0,
711
+ max: 360,
712
+ startAngle: 90,
713
+ interval: 30,
714
+ axisLine: { show: false },
715
+ axisTick: { show: false },
716
+ splitLine: {
717
+ show: true,
718
+ lineStyle: {
719
+ color: "rgba(100, 116, 139, 0.15)",
720
+ type: "dashed"
721
+ }
722
+ },
723
+ axisLabel: {
724
+ fontSize: 9,
725
+ color: "rgba(255, 255, 255, 0.4)",
726
+ formatter: (value) => value === 0 ? "" : `${value}°`
727
+ }
728
+ },
729
+ radiusAxis: {
730
+ min: referenceAltitude ? referenceAltitude * 0.9 : "dataMin",
731
+ max: referenceAltitude ? referenceAltitude * 1.1 : "dataMax",
732
+ axisLine: { show: false },
733
+ axisTick: { show: false },
734
+ axisLabel: { show: false },
735
+ splitLine: {
736
+ show: true,
737
+ lineStyle: {
738
+ color: "rgba(100, 116, 139, 0.2)",
739
+ type: "dashed"
740
+ }
741
+ }
742
+ },
743
+ series: [{
744
+ type: "scatter",
745
+ name: "Position",
746
+ coordinateSystem: "polar",
747
+ data: data.map((d) => [d.altitude, d.angle]),
748
+ symbolSize: 8,
749
+ itemStyle: {
750
+ color: ZENDIR_BRAND_COLORS.electric,
751
+ // Zendir Electric
752
+ shadowColor: ZENDIR_BRAND_COLORS.electric,
753
+ shadowBlur: 6
754
+ }
755
+ }]
756
+ },
757
+ export: exportOptions,
758
+ infoTooltip
759
+ }
760
+ );
761
+ }
762
+ ));
763
+ const ContactWindowChart = memo(forwardRef(
764
+ function ContactWindowChart2({
765
+ data = [],
766
+ title = "Contact windows",
767
+ timeRange,
768
+ width = "100%",
769
+ height = 200,
770
+ loading = false,
771
+ enableZoom = true,
772
+ className = "",
773
+ export: exportOptions,
774
+ infoTooltip
775
+ }, ref) {
776
+ const { categories, ganttData } = useMemo(() => {
777
+ const cats = data.map((d) => d.name);
778
+ const items = [];
779
+ data.forEach((station, stationIdx) => {
780
+ station.windows.forEach((w) => {
781
+ w.signalQuality === "poor" ? STATUS_COLORS.critical : w.signalQuality === "marginal" ? STATUS_COLORS.caution : STATUS_COLORS.normal;
782
+ items.push({
783
+ name: station.name,
784
+ value: [stationIdx, w.start, w.end, w.label]
785
+ });
786
+ });
787
+ });
788
+ return { categories: cats, ganttData: items };
789
+ }, [data]);
790
+ const series = [{
791
+ id: "contacts",
792
+ name: "Contacts",
793
+ type: "bar",
794
+ data: []
795
+ }];
796
+ return /* @__PURE__ */ jsx(
797
+ AstroChart,
798
+ {
799
+ ref,
800
+ type: "bar",
801
+ title,
802
+ series,
803
+ width,
804
+ height,
805
+ loading,
806
+ className,
807
+ zoom: enableZoom ? { enabled: true, type: "inside", axis: "x" } : void 0,
808
+ echartsOptions: {
809
+ tooltip: {
810
+ trigger: "item",
811
+ formatter: (params) => {
812
+ const p = params;
813
+ const [, start, end, label] = p.value;
814
+ const duration = ((end - start) / 6e4).toFixed(1);
815
+ return `${label || "Contact"}<br/>Duration: ${duration} min`;
816
+ }
817
+ },
818
+ grid: { left: 100, right: 20, top: 40, bottom: 40 },
819
+ xAxis: {
820
+ type: "time",
821
+ min: timeRange == null ? void 0 : timeRange[0],
822
+ max: timeRange == null ? void 0 : timeRange[1]
823
+ },
824
+ yAxis: {
825
+ type: "category",
826
+ data: categories
827
+ },
828
+ series: [{
829
+ type: "custom",
830
+ renderItem: (_params, api) => {
831
+ const a = api;
832
+ const catIdx = a.value(0);
833
+ const start = a.coord([a.value(1), catIdx]);
834
+ const end = a.coord([a.value(2), catIdx]);
835
+ const height2 = a.size([0, 1])[1] * 0.6;
836
+ return {
837
+ type: "rect",
838
+ shape: {
839
+ x: start[0],
840
+ y: start[1] - height2 / 2,
841
+ width: end[0] - start[0],
842
+ height: height2
843
+ },
844
+ style: {
845
+ fill: STATUS_COLORS.normal,
846
+ stroke: STATUS_COLORS.standby
847
+ }
848
+ };
849
+ },
850
+ encode: { x: [1, 2], y: 0 },
851
+ data: ganttData
852
+ }]
853
+ },
854
+ export: exportOptions,
855
+ infoTooltip
856
+ }
857
+ );
858
+ }
859
+ ));
860
+ const SpectrumChart = memo(forwardRef(
861
+ function SpectrumChart2({
862
+ data = [],
863
+ title = "RF spectrum",
864
+ frequencyRange,
865
+ powerRange,
866
+ noiseFloor,
867
+ width = "100%",
868
+ height = 200,
869
+ loading = false,
870
+ className = "",
871
+ export: exportOptions,
872
+ infoTooltip
873
+ }, ref) {
874
+ const series = useMemo(() => [{
875
+ id: "spectrum",
876
+ name: "Power",
877
+ type: "area",
878
+ data: data.map((d) => ({ x: d.frequency, y: d.power })),
879
+ color: ZENDIR_BRAND_COLORS.electric,
880
+ // Zendir Electric
881
+ smooth: false,
882
+ areaStyle: { opacity: 0.3 },
883
+ symbol: { type: "none" }
884
+ }], [data]);
885
+ return /* @__PURE__ */ jsx(
886
+ AstroChart,
887
+ {
888
+ ref,
889
+ type: "area",
890
+ title,
891
+ series,
892
+ width,
893
+ height,
894
+ loading,
895
+ className,
896
+ xAxis: {
897
+ type: "value",
898
+ name: "Frequency",
899
+ min: frequencyRange == null ? void 0 : frequencyRange[0],
900
+ max: frequencyRange == null ? void 0 : frequencyRange[1]
901
+ },
902
+ yAxis: {
903
+ type: "value",
904
+ name: "dBm",
905
+ min: powerRange == null ? void 0 : powerRange[0],
906
+ max: powerRange == null ? void 0 : powerRange[1]
907
+ },
908
+ tooltip: { trigger: "axis", crosshair: "x" },
909
+ annotations: noiseFloor !== void 0 ? {
910
+ markLines: {
911
+ data: [{
912
+ yAxis: noiseFloor,
913
+ label: `Noise floor (${noiseFloor} dBm)`,
914
+ color: SOFT_STATUS_COLORS.caution,
915
+ lineStyle: { type: "dashed" }
916
+ }]
917
+ }
918
+ } : void 0,
919
+ export: exportOptions,
920
+ infoTooltip
921
+ }
922
+ );
923
+ }
924
+ ));
925
+ const ManeuverBudgetChart = memo(forwardRef(
926
+ function ManeuverBudgetChart2({
927
+ data = [],
928
+ title = "Delta-V budget",
929
+ totalBudget,
930
+ width = "100%",
931
+ height = 200,
932
+ loading = false,
933
+ className = "",
934
+ export: exportOptions,
935
+ infoTooltip
936
+ }, ref) {
937
+ const series = useMemo(() => {
938
+ const typeColors = {
939
+ executed: STATUS_COLORS.normal,
940
+ // Green (completed)
941
+ planned: STATUS_COLORS.standby,
942
+ // Cyan (scheduled)
943
+ remaining: ZENDIR_BRAND_COLORS.electric,
944
+ // Zendir Electric
945
+ margin: ZENDIR_BRAND_COLORS.purple
946
+ // Zendir Purple
947
+ };
948
+ return [{
949
+ id: "deltaV",
950
+ name: "Delta-V",
951
+ type: "bar",
952
+ data: data.map((d) => ({
953
+ x: d.name,
954
+ y: d.deltaV,
955
+ meta: { type: d.type, color: typeColors[d.type] || STATUS_COLORS.standby }
956
+ }))
957
+ }];
958
+ }, [data]);
959
+ return /* @__PURE__ */ jsx(
960
+ AstroChart,
961
+ {
962
+ ref,
963
+ type: "bar",
964
+ title,
965
+ subtitle: totalBudget ? `Total: ${totalBudget} m/s` : void 0,
966
+ series,
967
+ width,
968
+ height,
969
+ loading,
970
+ className,
971
+ xAxis: { type: "category" },
972
+ yAxis: { type: "value", name: "m/s" },
973
+ tooltip: { trigger: "axis" },
974
+ echartsOptions: {
975
+ series: [{
976
+ type: "bar",
977
+ data: data.map((d) => ({
978
+ value: d.deltaV,
979
+ name: d.name,
980
+ itemStyle: {
981
+ color: d.type === "executed" ? STATUS_COLORS.normal : d.type === "planned" ? STATUS_COLORS.standby : d.type === "remaining" ? ZENDIR_BRAND_COLORS.electric : ZENDIR_BRAND_COLORS.purple
982
+ }
983
+ }))
984
+ }]
985
+ },
986
+ export: exportOptions,
987
+ infoTooltip
988
+ }
989
+ );
990
+ }
991
+ ));
992
+ const EclipseTimelineChart = memo(forwardRef(
993
+ function EclipseTimelineChart2({
994
+ data = [],
995
+ title = "Eclipse timeline",
996
+ timeRange,
997
+ width = "100%",
998
+ height = 100,
999
+ loading = false,
1000
+ enableZoom = true,
1001
+ className = "",
1002
+ export: exportOptions,
1003
+ infoTooltip
1004
+ }, ref) {
1005
+ const series = [{
1006
+ id: "eclipse",
1007
+ name: "Eclipse",
1008
+ type: "bar",
1009
+ data: []
1010
+ }];
1011
+ const typeColors = {
1012
+ umbra: ZENDIR_BRAND_COLORS.prussianBlue,
1013
+ // Deep Zendir blue
1014
+ penumbra: ZENDIR_BRAND_COLORS.electricDark,
1015
+ // Dark electric
1016
+ sunlight: STATUS_COLORS.caution
1017
+ // Standard yellow for sunlight
1018
+ };
1019
+ return /* @__PURE__ */ jsx(
1020
+ AstroChart,
1021
+ {
1022
+ ref,
1023
+ type: "bar",
1024
+ title,
1025
+ series,
1026
+ width,
1027
+ height,
1028
+ loading,
1029
+ className,
1030
+ zoom: enableZoom ? { enabled: true, type: "inside", axis: "x" } : void 0,
1031
+ echartsOptions: {
1032
+ tooltip: {
1033
+ trigger: "item",
1034
+ formatter: (params) => {
1035
+ const p = params;
1036
+ const [start, end, eclipseType] = p.data.value;
1037
+ const duration = ((end - start) / 6e4).toFixed(1);
1038
+ return `${eclipseType.charAt(0).toUpperCase() + eclipseType.slice(1)}<br/>Duration: ${duration} min`;
1039
+ }
1040
+ },
1041
+ grid: { left: 60, right: 20, top: 30, bottom: 30 },
1042
+ xAxis: {
1043
+ type: "time",
1044
+ min: timeRange == null ? void 0 : timeRange[0],
1045
+ max: timeRange == null ? void 0 : timeRange[1]
1046
+ },
1047
+ yAxis: {
1048
+ type: "category",
1049
+ data: [""],
1050
+ show: false
1051
+ },
1052
+ series: [{
1053
+ type: "custom",
1054
+ renderItem: (_params, api) => {
1055
+ const a = api;
1056
+ const start = a.coord([a.value(0), 0]);
1057
+ const end = a.coord([a.value(1), 0]);
1058
+ const eclipseType = a.value(2);
1059
+ const h = 30;
1060
+ return {
1061
+ type: "rect",
1062
+ shape: {
1063
+ x: start[0],
1064
+ y: start[1] - h / 2,
1065
+ width: Math.max(end[0] - start[0], 2),
1066
+ height: h
1067
+ },
1068
+ style: {
1069
+ fill: typeColors[eclipseType] || typeColors.sunlight
1070
+ }
1071
+ };
1072
+ },
1073
+ encode: { x: [0, 1] },
1074
+ data: data.map((d) => ({ value: [d.start, d.end, d.type] }))
1075
+ }]
1076
+ },
1077
+ export: exportOptions,
1078
+ infoTooltip
1079
+ }
1080
+ );
1081
+ }
1082
+ ));
1083
+ const RoseDiagram = memo(forwardRef(
1084
+ function RoseDiagram2({
1085
+ data = [],
1086
+ title = "Rose Diagram",
1087
+ width = "100%",
1088
+ height = 400,
1089
+ bins = 16,
1090
+ loading = false,
1091
+ className = "",
1092
+ export: exportOptions,
1093
+ infoTooltip
1094
+ }, ref) {
1095
+ const binData = useMemo(() => {
1096
+ const binSize = 360 / bins;
1097
+ const binCounts = new Array(bins).fill(0);
1098
+ data.forEach((d) => {
1099
+ const normalizedAngle = (d.direction % 360 + 360) % 360;
1100
+ const binIndex = Math.floor(normalizedAngle / binSize);
1101
+ binCounts[binIndex] += d.magnitude;
1102
+ });
1103
+ return binCounts.map((count, i) => ({
1104
+ name: `${(i * binSize).toFixed(0)}°`,
1105
+ value: count
1106
+ }));
1107
+ }, [data, bins]);
1108
+ return /* @__PURE__ */ jsx(
1109
+ AstroChart,
1110
+ {
1111
+ ref,
1112
+ type: "bar",
1113
+ series: [],
1114
+ title,
1115
+ width,
1116
+ height,
1117
+ loading,
1118
+ className,
1119
+ echartsOptions: {
1120
+ polar: {
1121
+ radius: ["10%", "70%"],
1122
+ center: ["50%", "50%"]
1123
+ },
1124
+ angleAxis: {
1125
+ type: "category",
1126
+ data: binData.map((d) => d.name),
1127
+ startAngle: 90,
1128
+ boundaryGap: true,
1129
+ axisLine: { show: false },
1130
+ axisTick: { show: false },
1131
+ axisLabel: {
1132
+ fontSize: 9,
1133
+ color: "rgba(255, 255, 255, 0.5)",
1134
+ margin: 8
1135
+ },
1136
+ splitLine: {
1137
+ show: true,
1138
+ lineStyle: {
1139
+ color: "rgba(100, 116, 139, 0.12)",
1140
+ type: "dashed"
1141
+ }
1142
+ }
1143
+ },
1144
+ radiusAxis: {
1145
+ min: 0,
1146
+ axisLine: { show: false },
1147
+ axisTick: { show: false },
1148
+ axisLabel: { show: false },
1149
+ splitLine: {
1150
+ show: true,
1151
+ lineStyle: {
1152
+ color: "rgba(100, 116, 139, 0.15)",
1153
+ type: "dashed"
1154
+ }
1155
+ }
1156
+ },
1157
+ tooltip: {
1158
+ trigger: "item",
1159
+ backgroundColor: "rgba(20, 30, 48, 0.95)",
1160
+ borderColor: "rgba(100, 116, 139, 0.3)",
1161
+ textStyle: { color: "rgba(255, 255, 255, 0.87)" }
1162
+ // High contrast white
1163
+ },
1164
+ series: [{
1165
+ type: "bar",
1166
+ data: binData.map((d) => d.value),
1167
+ coordinateSystem: "polar",
1168
+ roundCap: true,
1169
+ itemStyle: {
1170
+ // Zendir Electric → Purple gradient
1171
+ color: {
1172
+ type: "linear",
1173
+ x: 0,
1174
+ y: 0,
1175
+ x2: 1,
1176
+ y2: 0,
1177
+ colorStops: [
1178
+ { offset: 0, color: ZENDIR_BRAND_COLORS.electric },
1179
+ // #3E3CFF
1180
+ { offset: 1, color: ZENDIR_BRAND_COLORS.purple }
1181
+ // #9D70FF
1182
+ ]
1183
+ },
1184
+ shadowColor: ZENDIR_BRAND_COLORS.purple,
1185
+ shadowBlur: 4
1186
+ }
1187
+ }]
1188
+ },
1189
+ export: exportOptions,
1190
+ infoTooltip
1191
+ }
1192
+ );
1193
+ }
1194
+ ));
1195
+ const ORBIT_COLOR_MAP = {
1196
+ // Human-made objects: Zendir Purple/Blue shades
1197
+ spacecraft: "#3E3CFF",
1198
+ // Zendir Electric
1199
+ satellite: "#9D70FF",
1200
+ // Zendir Purple
1201
+ station: "#3548C0",
1202
+ // Zendir Prussian Blue Light
1203
+ probe: "#1B2DA0",
1204
+ // Zendir Prussian Blue
1205
+ // Natural objects: Realistic colors
1206
+ planet: "#5BC0DE",
1207
+ // Teal-blue (default)
1208
+ // Debris/Asteroids: Brown/Gray shades
1209
+ asteroid: "#8B7355",
1210
+ // Warm brown
1211
+ debris: "#6B6B6B",
1212
+ // Gray
1213
+ // Comets: Brown with icy tones
1214
+ comet: "#5C4033"
1215
+ // Dark brown
1216
+ };
1217
+ const ORBIT_TYPE_LABELS = {
1218
+ spacecraft: "Spacecraft",
1219
+ satellite: "Satellite",
1220
+ station: "Space Station",
1221
+ probe: "Deep Space Probe",
1222
+ planet: "Planet",
1223
+ asteroid: "Asteroid",
1224
+ debris: "Debris",
1225
+ comet: "Comet"
1226
+ };
1227
+ const HeliocentricOrbitPlot = memo(forwardRef(
1228
+ function HeliocentricOrbitPlot2({
1229
+ data = [],
1230
+ title = "Heliocentric Orbit",
1231
+ width = "100%",
1232
+ height = 500,
1233
+ showGrid = true,
1234
+ enableZoom = true,
1235
+ showLabels = true,
1236
+ mode = "2d",
1237
+ loading = false,
1238
+ className = "",
1239
+ export: exportOptions,
1240
+ infoTooltip,
1241
+ onBodyClick: _onBodyClick
1242
+ }, ref) {
1243
+ const { tokens, mode: themeMode } = useTheme();
1244
+ const tooltipStyle = useChartTooltipStyle();
1245
+ useChartLegendStyle();
1246
+ const labelPrimary = tokens.colors.text.primary;
1247
+ const labelSecondary = tokens.colors.text.secondary;
1248
+ tokens.colors.text.tertiary;
1249
+ const labelBg = themeMode === "dark" ? "rgba(15, 23, 42, 0.72)" : "rgba(255, 255, 255, 0.9)";
1250
+ const bodyDataMap = useMemo(() => {
1251
+ const map = /* @__PURE__ */ new Map();
1252
+ data.forEach((body) => map.set(body.name, body));
1253
+ return map;
1254
+ }, [data]);
1255
+ const echarts2DOptions = useMemo(() => {
1256
+ const seriesArray = [];
1257
+ data.forEach((body, idx) => {
1258
+ const bodyColor = body.color || ORBIT_COLOR_MAP[body.type || "spacecraft"] || ASTRO_DATA_VIZ_COLORS.mixed[idx % ASTRO_DATA_VIZ_COLORS.mixed.length];
1259
+ const typeLabel = ORBIT_TYPE_LABELS[body.type || "spacecraft"] || "Object";
1260
+ if (body.orbitPath && body.orbitPath.length > 0) {
1261
+ const orbitRadius = body.semiMajorAxis || Math.max(...body.orbitPath.map((p) => Math.sqrt(p.x * p.x + p.y * p.y)));
1262
+ seriesArray.push({
1263
+ type: "line",
1264
+ name: `${body.name} Orbit`,
1265
+ data: body.orbitPath.map((p) => [p.x, p.y, body.name, typeLabel, orbitRadius, body.period, body.inclination]),
1266
+ lineStyle: {
1267
+ color: bodyColor,
1268
+ type: "dashed",
1269
+ width: 1.5,
1270
+ opacity: 0.6
1271
+ },
1272
+ symbol: "none",
1273
+ silent: false,
1274
+ emphasis: {
1275
+ lineStyle: {
1276
+ width: 3.5,
1277
+ opacity: 1,
1278
+ shadowBlur: 8,
1279
+ shadowColor: bodyColor
1280
+ }
1281
+ },
1282
+ z: 1
1283
+ });
1284
+ }
1285
+ seriesArray.push({
1286
+ type: "scatter",
1287
+ name: body.name,
1288
+ symbolSize: body.size || (body.type === "planet" ? 20 : 12),
1289
+ data: [[body.x, body.y, body.z || 0, body.type, typeLabel, body.description, body.semiMajorAxis, body.period]],
1290
+ itemStyle: {
1291
+ color: bodyColor,
1292
+ shadowColor: bodyColor,
1293
+ shadowBlur: body.type === "planet" ? 10 : 5
1294
+ },
1295
+ label: {
1296
+ show: showLabels,
1297
+ position: "top",
1298
+ formatter: body.name,
1299
+ fontSize: 11,
1300
+ color: labelSecondary,
1301
+ textBorderColor: "transparent",
1302
+ textBorderWidth: 0
1303
+ },
1304
+ emphasis: {
1305
+ scale: 1.6,
1306
+ itemStyle: {
1307
+ shadowBlur: 20
1308
+ },
1309
+ label: {
1310
+ show: true,
1311
+ fontWeight: "bold",
1312
+ fontSize: 12,
1313
+ color: labelPrimary
1314
+ }
1315
+ },
1316
+ z: 10
1317
+ });
1318
+ });
1319
+ return {
1320
+ tooltip: {
1321
+ trigger: "item",
1322
+ ...tooltipStyle,
1323
+ borderWidth: 1,
1324
+ padding: [12, 16],
1325
+ formatter: (params) => {
1326
+ const seriesName = params.seriesName || "";
1327
+ if (params.seriesType === "line") {
1328
+ const [_x, _y, bodyName, typeLabel, orbitRadius, period, inclination] = params.value || [];
1329
+ const bodyInfo = bodyDataMap.get(bodyName);
1330
+ let html = `<div style="font-weight:600;font-size:13px;margin-bottom:6px;color:#3E3CFF">${seriesName}</div>`;
1331
+ html += `<div style="color:rgba(255,255,255,0.5);font-size:10px;margin-bottom:8px;text-transform:uppercase;letter-spacing:0.5px">${typeLabel || "Orbital Path"}</div>`;
1332
+ html += `<div style="border-top:1px solid rgba(100,116,139,0.3);padding-top:8px">`;
1333
+ if (orbitRadius) {
1334
+ html += `<div style="display:flex;justify-content:space-between;margin-bottom:4px"><span style="color:rgba(255,255,255,0.6)">Semi-major axis:</span><span style="font-family:monospace">${orbitRadius.toFixed(3)} AU</span></div>`;
1335
+ }
1336
+ if (period) {
1337
+ html += `<div style="display:flex;justify-content:space-between;margin-bottom:4px"><span style="color:rgba(255,255,255,0.6)">Orbital period:</span><span style="font-family:monospace">${period.toFixed(1)} days</span></div>`;
1338
+ }
1339
+ if (inclination !== void 0) {
1340
+ html += `<div style="display:flex;justify-content:space-between;margin-bottom:4px"><span style="color:rgba(255,255,255,0.6)">Inclination:</span><span style="font-family:monospace">${inclination.toFixed(1)}°</span></div>`;
1341
+ }
1342
+ if (bodyInfo == null ? void 0 : bodyInfo.description) {
1343
+ html += `<div style="margin-top:6px;color:rgba(255,255,255,0.7);font-style:italic;font-size:11px">${bodyInfo.description}</div>`;
1344
+ }
1345
+ html += `</div>`;
1346
+ return html;
1347
+ }
1348
+ if (params.seriesType === "scatter") {
1349
+ const [x, y, z, _bodyType, typeLabel, description, sma, period] = params.value;
1350
+ const distance = Math.sqrt(x * x + y * y + (z || 0) * (z || 0));
1351
+ let html = `<div style="font-weight:600;font-size:13px;margin-bottom:4px">${seriesName}</div>`;
1352
+ html += `<div style="color:rgba(255,255,255,0.5);font-size:10px;margin-bottom:8px;text-transform:uppercase;letter-spacing:0.5px">${typeLabel || "Object"}</div>`;
1353
+ html += `<div style="border-top:1px solid rgba(100,116,139,0.3);padding-top:8px">`;
1354
+ html += `<div style="display:flex;justify-content:space-between;margin-bottom:3px"><span style="color:rgba(255,255,255,0.6)">X:</span><span style="font-family:monospace">${x.toFixed(3)} AU</span></div>`;
1355
+ html += `<div style="display:flex;justify-content:space-between;margin-bottom:3px"><span style="color:rgba(255,255,255,0.6)">Y:</span><span style="font-family:monospace">${y.toFixed(3)} AU</span></div>`;
1356
+ if (z !== 0 && z !== void 0) {
1357
+ html += `<div style="display:flex;justify-content:space-between;margin-bottom:3px"><span style="color:rgba(255,255,255,0.6)">Z:</span><span style="font-family:monospace">${z.toFixed(3)} AU</span></div>`;
1358
+ }
1359
+ html += `<div style="display:flex;justify-content:space-between;margin-bottom:3px;border-top:1px solid rgba(100,116,139,0.2);padding-top:6px;margin-top:4px"><span style="color:rgba(255,255,255,0.6)">Distance from Sun:</span><span style="font-family:monospace;color:#5BC0DE">${distance.toFixed(3)} AU</span></div>`;
1360
+ if (sma) {
1361
+ html += `<div style="display:flex;justify-content:space-between;margin-bottom:3px"><span style="color:rgba(255,255,255,0.6)">Semi-major axis:</span><span style="font-family:monospace">${sma.toFixed(3)} AU</span></div>`;
1362
+ }
1363
+ if (period) {
1364
+ html += `<div style="display:flex;justify-content:space-between;margin-bottom:3px"><span style="color:rgba(255,255,255,0.6)">Period:</span><span style="font-family:monospace">${period.toFixed(1)} days</span></div>`;
1365
+ }
1366
+ if (description) {
1367
+ html += `<div style="margin-top:8px;color:rgba(255,255,255,0.7);font-style:italic;font-size:11px;max-width:200px">${description}</div>`;
1368
+ }
1369
+ html += `</div>`;
1370
+ return html;
1371
+ }
1372
+ return seriesName;
1373
+ }
1374
+ },
1375
+ toolbox: {
1376
+ show: enableZoom,
1377
+ right: 20,
1378
+ top: 10,
1379
+ feature: {
1380
+ dataZoom: { show: true, title: { zoom: "Zoom", back: "Reset" } },
1381
+ restore: { show: true, title: "Reset" }
1382
+ },
1383
+ iconStyle: { borderColor: "rgba(255, 255, 255, 0.5)" }
1384
+ },
1385
+ dataZoom: enableZoom ? [
1386
+ { type: "inside", xAxisIndex: 0, filterMode: "none" },
1387
+ { type: "inside", yAxisIndex: 0, filterMode: "none" }
1388
+ ] : void 0,
1389
+ grid: {
1390
+ containLabel: true,
1391
+ left: 60,
1392
+ right: enableZoom ? 80 : 40,
1393
+ top: 60,
1394
+ bottom: 60
1395
+ },
1396
+ xAxis: {
1397
+ type: "value",
1398
+ name: "X (AU)",
1399
+ nameLocation: "middle",
1400
+ nameGap: 30,
1401
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1402
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.15)" } },
1403
+ axisLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.3)" } },
1404
+ axisLabel: { color: "rgba(255, 255, 255, 0.5)" }
1405
+ },
1406
+ yAxis: {
1407
+ type: "value",
1408
+ name: "Y (AU)",
1409
+ nameLocation: "middle",
1410
+ nameGap: 40,
1411
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1412
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.15)" } },
1413
+ axisLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.3)" } },
1414
+ axisLabel: { color: "rgba(255, 255, 255, 0.5)" }
1415
+ },
1416
+ animation: true,
1417
+ animationDuration: 300,
1418
+ series: seriesArray
1419
+ };
1420
+ }, [data, showGrid, enableZoom, showLabels, bodyDataMap, tooltipStyle]);
1421
+ const echarts3DOptions = useMemo(() => {
1422
+ const seriesArray = [];
1423
+ data.forEach((body, idx) => {
1424
+ const bodyColor = body.color || ORBIT_COLOR_MAP[body.type || "spacecraft"] || ASTRO_DATA_VIZ_COLORS.mixed[idx % ASTRO_DATA_VIZ_COLORS.mixed.length];
1425
+ const typeLabel = ORBIT_TYPE_LABELS[body.type || "spacecraft"] || "Object";
1426
+ if (body.orbitPath && body.orbitPath.length > 0) {
1427
+ const orbitData = body.orbitPath.map((p) => [p.x, p.y, p.z || 0]);
1428
+ if (orbitData.length > 2) {
1429
+ orbitData.push(orbitData[0]);
1430
+ }
1431
+ seriesArray.push({
1432
+ type: "line3D",
1433
+ name: `${body.name} Orbit`,
1434
+ coordinateSystem: "cartesian3D",
1435
+ data: orbitData,
1436
+ lineStyle: {
1437
+ color: bodyColor,
1438
+ width: 1.5,
1439
+ opacity: 0.6
1440
+ },
1441
+ silent: false
1442
+ });
1443
+ }
1444
+ seriesArray.push({
1445
+ type: "scatter3D",
1446
+ name: body.name,
1447
+ coordinateSystem: "cartesian3D",
1448
+ data: [{
1449
+ name: body.name,
1450
+ value: [body.x, body.y, body.z || 0],
1451
+ itemStyle: { color: bodyColor },
1452
+ typeLabel,
1453
+ description: body.description
1454
+ }],
1455
+ symbolSize: body.size || (body.type === "planet" ? 16 : 10),
1456
+ itemStyle: { color: bodyColor },
1457
+ label: {
1458
+ show: showLabels,
1459
+ formatter: body.name,
1460
+ textStyle: {
1461
+ color: labelPrimary,
1462
+ fontSize: 11,
1463
+ backgroundColor: labelBg,
1464
+ padding: [2, 4],
1465
+ borderRadius: 2
1466
+ }
1467
+ },
1468
+ emphasis: {
1469
+ itemStyle: { opacity: 1 },
1470
+ label: { show: true }
1471
+ }
1472
+ });
1473
+ });
1474
+ return {
1475
+ tooltip: {
1476
+ show: true,
1477
+ ...tooltipStyle,
1478
+ formatter: (params) => {
1479
+ const d = params.data || {};
1480
+ const seriesName = params.seriesName || "";
1481
+ if (params.seriesType === "line3D") {
1482
+ return `<div style="font-weight:600">${seriesName}</div>`;
1483
+ }
1484
+ const [x, y, z] = d.value || params.value || [0, 0, 0];
1485
+ const distance = Math.sqrt(x * x + y * y + z * z);
1486
+ let html = `<div style="font-weight:600;font-size:13px;margin-bottom:4px">${d.name || seriesName}</div>`;
1487
+ html += `<div style="color:rgba(255,255,255,0.5);font-size:10px;margin-bottom:8px;text-transform:uppercase">${d.typeLabel || "Object"}</div>`;
1488
+ html += `<div style="border-top:1px solid rgba(100,116,139,0.3);padding-top:8px">`;
1489
+ html += `<div>X: <span style="font-family:monospace">${x.toFixed(3)}</span> AU</div>`;
1490
+ html += `<div>Y: <span style="font-family:monospace">${y.toFixed(3)}</span> AU</div>`;
1491
+ html += `<div>Z: <span style="font-family:monospace">${z.toFixed(3)}</span> AU</div>`;
1492
+ html += `<div style="margin-top:4px;color:#5BC0DE">Distance: <span style="font-family:monospace">${distance.toFixed(3)}</span> AU</div>`;
1493
+ if (d.description) {
1494
+ html += `<div style="margin-top:6px;color:rgba(255,255,255,0.7);font-style:italic;font-size:11px">${d.description}</div>`;
1495
+ }
1496
+ html += `</div>`;
1497
+ return html;
1498
+ }
1499
+ },
1500
+ grid3D: {
1501
+ boxWidth: 200,
1502
+ boxHeight: 60,
1503
+ boxDepth: 200,
1504
+ viewControl: {
1505
+ autoRotate: false,
1506
+ autoRotateAfterStill: 5,
1507
+ autoRotateSpeed: 5,
1508
+ distance: 280,
1509
+ alpha: 20,
1510
+ beta: 40,
1511
+ rotateSensitivity: 2,
1512
+ zoomSensitivity: 1.5,
1513
+ panSensitivity: 1
1514
+ },
1515
+ light: {
1516
+ main: { intensity: 1.2, shadow: false },
1517
+ ambient: { intensity: 0.4 }
1518
+ },
1519
+ postEffect: {
1520
+ enable: true,
1521
+ bloom: { enable: true, intensity: 0.05 }
1522
+ }
1523
+ },
1524
+ xAxis3D: {
1525
+ type: "value",
1526
+ name: "X (AU)",
1527
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1528
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1529
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)", formatter: (v) => v.toFixed(1) },
1530
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } }
1531
+ },
1532
+ yAxis3D: {
1533
+ type: "value",
1534
+ name: "Y (AU)",
1535
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1536
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1537
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)", formatter: (v) => v.toFixed(1) },
1538
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } }
1539
+ },
1540
+ zAxis3D: {
1541
+ type: "value",
1542
+ name: "Z (AU)",
1543
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1544
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1545
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)", formatter: (v) => v.toFixed(1) },
1546
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } }
1547
+ },
1548
+ series: seriesArray
1549
+ };
1550
+ }, [data, showGrid, showLabels]);
1551
+ const echartsOptions = mode === "3d" ? echarts3DOptions : echarts2DOptions;
1552
+ return /* @__PURE__ */ jsx(
1553
+ AstroChart,
1554
+ {
1555
+ ref,
1556
+ type: "scatter",
1557
+ series: [],
1558
+ title,
1559
+ width,
1560
+ height,
1561
+ loading,
1562
+ className,
1563
+ echartsOptions,
1564
+ export: exportOptions,
1565
+ infoTooltip
1566
+ }
1567
+ );
1568
+ }
1569
+ ));
1570
+ const Scatter3DChart = memo(forwardRef(
1571
+ function Scatter3DChart2({
1572
+ data = [],
1573
+ title,
1574
+ width = "100%",
1575
+ height = 500,
1576
+ showGrid = true,
1577
+ xAxisLabel = "X",
1578
+ yAxisLabel = "Y",
1579
+ zAxisLabel = "Z",
1580
+ autoRotate = false,
1581
+ loading = false,
1582
+ className = "",
1583
+ export: exportOptions,
1584
+ infoTooltip
1585
+ }, ref) {
1586
+ const glReady = useEchartsGlReady();
1587
+ const tooltipStyle = useChartTooltipStyle();
1588
+ const legendStyle = useChartLegendStyle();
1589
+ const echartsOptions = useMemo(() => {
1590
+ const seriesArray = data.map((series, idx) => ({
1591
+ type: "scatter3D",
1592
+ name: series.name,
1593
+ data: series.data.map((p) => ({
1594
+ name: p.label || series.name,
1595
+ value: [p.x, p.y, p.z],
1596
+ itemStyle: p.color ? { color: p.color } : void 0,
1597
+ meta: p.meta
1598
+ })),
1599
+ symbolSize: typeof series.symbolSize === "number" ? series.symbolSize : 12,
1600
+ itemStyle: {
1601
+ color: series.color || ASTRO_DATA_VIZ_COLORS.mixed[idx % ASTRO_DATA_VIZ_COLORS.mixed.length]
1602
+ },
1603
+ label: {
1604
+ show: false
1605
+ },
1606
+ emphasis: {
1607
+ itemStyle: { opacity: 1 },
1608
+ label: { show: true, formatter: (params) => {
1609
+ var _a;
1610
+ return ((_a = params.data) == null ? void 0 : _a.name) || "";
1611
+ } }
1612
+ }
1613
+ }));
1614
+ return {
1615
+ tooltip: {
1616
+ show: true,
1617
+ ...tooltipStyle,
1618
+ formatter: (params) => {
1619
+ const d = params.data || {};
1620
+ const [x, y, z] = d.value || [0, 0, 0];
1621
+ let html = `<div style="font-weight:600;font-size:13px;margin-bottom:4px">${d.name || params.seriesName}</div>`;
1622
+ html += `<div>${xAxisLabel}: <span style="font-family:monospace">${x.toFixed(2)}</span></div>`;
1623
+ html += `<div>${yAxisLabel}: <span style="font-family:monospace">${y.toFixed(2)}</span></div>`;
1624
+ html += `<div>${zAxisLabel}: <span style="font-family:monospace">${z.toFixed(2)}</span></div>`;
1625
+ return html;
1626
+ }
1627
+ },
1628
+ legend: {
1629
+ show: data.length > 1,
1630
+ top: 10,
1631
+ ...legendStyle
1632
+ },
1633
+ grid3D: {
1634
+ boxWidth: 100,
1635
+ boxHeight: 100,
1636
+ boxDepth: 100,
1637
+ viewControl: {
1638
+ autoRotate,
1639
+ autoRotateSpeed: 5,
1640
+ distance: 200,
1641
+ alpha: 25,
1642
+ beta: 45,
1643
+ rotateSensitivity: 2,
1644
+ zoomSensitivity: 1.5
1645
+ },
1646
+ light: {
1647
+ main: { intensity: 1.2, shadow: false },
1648
+ ambient: { intensity: 0.4 }
1649
+ },
1650
+ postEffect: {
1651
+ enable: true,
1652
+ bloom: { enable: true, intensity: 0.05 }
1653
+ }
1654
+ },
1655
+ xAxis3D: {
1656
+ type: "value",
1657
+ name: xAxisLabel,
1658
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1659
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1660
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)" },
1661
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } }
1662
+ },
1663
+ yAxis3D: {
1664
+ type: "value",
1665
+ name: yAxisLabel,
1666
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1667
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1668
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)" },
1669
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } }
1670
+ },
1671
+ zAxis3D: {
1672
+ type: "value",
1673
+ name: zAxisLabel,
1674
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1675
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1676
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)" },
1677
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } }
1678
+ },
1679
+ series: seriesArray
1680
+ };
1681
+ }, [data, showGrid, xAxisLabel, yAxisLabel, zAxisLabel, autoRotate, tooltipStyle, legendStyle]);
1682
+ if (!glReady) return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading: true, className });
1683
+ return /* @__PURE__ */ jsx(
1684
+ AstroChart,
1685
+ {
1686
+ ref,
1687
+ type: "scatter",
1688
+ series: [],
1689
+ title,
1690
+ width,
1691
+ height,
1692
+ loading,
1693
+ className,
1694
+ echartsOptions,
1695
+ export: exportOptions,
1696
+ infoTooltip
1697
+ }
1698
+ );
1699
+ }
1700
+ ));
1701
+ const Bar3DChart = memo(forwardRef(
1702
+ function Bar3DChart2({
1703
+ data = [],
1704
+ title,
1705
+ width = "100%",
1706
+ height = 500,
1707
+ xCategories = [],
1708
+ yCategories = [],
1709
+ xAxisLabel = "X",
1710
+ yAxisLabel = "Y",
1711
+ zAxisLabel = "Value",
1712
+ shading = "lambert",
1713
+ autoRotate = false,
1714
+ loading = false,
1715
+ className = "",
1716
+ export: exportOptions,
1717
+ infoTooltip
1718
+ }, ref) {
1719
+ const glReady = useEchartsGlReady();
1720
+ const tooltipStyle = useChartTooltipStyle();
1721
+ const visualMapStyle = useChartVisualMapStyle();
1722
+ const { tokens } = useTheme();
1723
+ const labelPrimary = tokens.colors.text.primary;
1724
+ const labelSecondary = tokens.colors.text.secondary;
1725
+ const labelTertiary = tokens.colors.text.tertiary;
1726
+ const derivedXCategories = xCategories || [...new Set(data.map((d) => String(d.x)))];
1727
+ const derivedYCategories = yCategories || [...new Set(data.map((d) => String(d.y)))];
1728
+ const echartsOptions = useMemo(() => {
1729
+ const seriesData = data.map((d) => {
1730
+ const xIdx = derivedXCategories.indexOf(String(d.x));
1731
+ const yIdx = derivedYCategories.indexOf(String(d.y));
1732
+ return {
1733
+ value: [xIdx, yIdx, d.z],
1734
+ name: d.label || `${d.x} - ${d.y}`,
1735
+ itemStyle: d.color ? { color: d.color } : void 0
1736
+ };
1737
+ });
1738
+ const maxZ = Math.max(...data.map((d) => d.z), 1);
1739
+ return {
1740
+ tooltip: {
1741
+ show: true,
1742
+ ...tooltipStyle,
1743
+ formatter: (params) => {
1744
+ const d = params.data || {};
1745
+ const [xIdx, yIdx, z] = d.value || [0, 0, 0];
1746
+ const xLabel = derivedXCategories[xIdx] || xIdx;
1747
+ const yLabel = derivedYCategories[yIdx] || yIdx;
1748
+ let html = `<div style="font-weight:600;font-size:13px;margin-bottom:4px">${d.name || ""}</div>`;
1749
+ html += `<div>${xAxisLabel}: ${xLabel}</div>`;
1750
+ html += `<div>${yAxisLabel}: ${yLabel}</div>`;
1751
+ html += `<div style="color:#3E3CFF">${zAxisLabel}: <span style="font-family:monospace">${z.toFixed(2)}</span></div>`;
1752
+ return html;
1753
+ }
1754
+ },
1755
+ visualMap: {
1756
+ show: true,
1757
+ min: 0,
1758
+ max: maxZ,
1759
+ inRange: {
1760
+ color: ["#3E3CFF", "#9D70FF", "#22d3ee", "#56f000"]
1761
+ },
1762
+ ...visualMapStyle,
1763
+ right: 10,
1764
+ top: "center"
1765
+ },
1766
+ grid3D: {
1767
+ boxWidth: 100,
1768
+ boxHeight: 80,
1769
+ boxDepth: 100,
1770
+ viewControl: {
1771
+ autoRotate,
1772
+ autoRotateSpeed: 3,
1773
+ distance: 250,
1774
+ alpha: 25,
1775
+ beta: 45,
1776
+ rotateSensitivity: 2,
1777
+ zoomSensitivity: 1.5
1778
+ },
1779
+ light: {
1780
+ main: { intensity: 1.1, shadow: true, shadowQuality: "medium" },
1781
+ ambient: { intensity: 0.4 }
1782
+ }
1783
+ },
1784
+ xAxis3D: {
1785
+ type: "category",
1786
+ name: xAxisLabel,
1787
+ data: derivedXCategories,
1788
+ nameTextStyle: { color: labelSecondary },
1789
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1790
+ axisLabel: { color: labelSecondary, fontSize: 10 }
1791
+ },
1792
+ yAxis3D: {
1793
+ type: "category",
1794
+ name: yAxisLabel,
1795
+ data: derivedYCategories,
1796
+ nameTextStyle: { color: labelSecondary },
1797
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1798
+ axisLabel: { color: labelSecondary, fontSize: 10 }
1799
+ },
1800
+ zAxis3D: {
1801
+ type: "value",
1802
+ name: zAxisLabel,
1803
+ nameTextStyle: { color: labelSecondary },
1804
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1805
+ axisLabel: { color: labelTertiary }
1806
+ },
1807
+ series: [{
1808
+ type: "bar3D",
1809
+ data: seriesData,
1810
+ shading,
1811
+ barSize: 15,
1812
+ bevelSize: 0.1,
1813
+ label: {
1814
+ show: false
1815
+ },
1816
+ emphasis: {
1817
+ label: {
1818
+ show: true,
1819
+ formatter: (params) => {
1820
+ var _a;
1821
+ return ((_a = params.data) == null ? void 0 : _a.name) || "";
1822
+ },
1823
+ textStyle: { color: labelPrimary, fontSize: 11 }
1824
+ }
1825
+ }
1826
+ }]
1827
+ };
1828
+ }, [data, derivedXCategories, derivedYCategories, xAxisLabel, yAxisLabel, zAxisLabel, shading, autoRotate, tooltipStyle, visualMapStyle, labelPrimary, labelSecondary, labelTertiary]);
1829
+ if (!glReady) return /* @__PURE__ */ jsx(AstroChart, { ref, type: "bar", series: [], title, width, height, loading: true, className });
1830
+ return /* @__PURE__ */ jsx(
1831
+ AstroChart,
1832
+ {
1833
+ ref,
1834
+ type: "bar",
1835
+ series: [],
1836
+ title,
1837
+ width,
1838
+ height,
1839
+ loading,
1840
+ className,
1841
+ echartsOptions,
1842
+ export: exportOptions,
1843
+ infoTooltip
1844
+ }
1845
+ );
1846
+ }
1847
+ ));
1848
+ const Surface3DChart = memo(forwardRef(
1849
+ function Surface3DChart2({
1850
+ data = { data: [] },
1851
+ title,
1852
+ width = "100%",
1853
+ height = 500,
1854
+ xAxisLabel = "X",
1855
+ yAxisLabel = "Y",
1856
+ zAxisLabel = "Z",
1857
+ shading = "realistic",
1858
+ autoRotate = false,
1859
+ loading = false,
1860
+ className = "",
1861
+ export: exportOptions,
1862
+ infoTooltip
1863
+ }, ref) {
1864
+ const glReady = useEchartsGlReady();
1865
+ const tooltipStyle = useChartTooltipStyle();
1866
+ const visualMapStyle = useChartVisualMapStyle();
1867
+ const echartsOptions = useMemo(() => {
1868
+ var _a;
1869
+ const surfaceData = [];
1870
+ const rows = data.data.length;
1871
+ const cols = rows > 0 ? data.data[0].length : 0;
1872
+ for (let i = 0; i < rows; i++) {
1873
+ for (let j = 0; j < cols; j++) {
1874
+ const x = data.xRange ? data.xRange[0] + (data.xRange[1] - data.xRange[0]) * (i / (rows - 1 || 1)) : i;
1875
+ const y = data.yRange ? data.yRange[0] + (data.yRange[1] - data.yRange[0]) * (j / (cols - 1 || 1)) : j;
1876
+ surfaceData.push([x, y, data.data[i][j]]);
1877
+ }
1878
+ }
1879
+ const allZ = data.data.flat();
1880
+ const minZ = Math.min(...allZ);
1881
+ const maxZ = Math.max(...allZ);
1882
+ const colorRange = data.colorMap === "thermal" ? ["#0d0887", "#6a00a8", "#b12a90", "#e16462", "#fca636", "#f0f921"] : data.colorMap === "viridis" ? ["#440154", "#414487", "#2a788e", "#22a884", "#7ad151", "#fde725"] : ((_a = data.colorStops) == null ? void 0 : _a.map((s) => s.color)) || ["#1B2DA0", "#3E3CFF", "#9D70FF", "#22d3ee", "#56f000"];
1883
+ return {
1884
+ tooltip: {
1885
+ show: true,
1886
+ ...tooltipStyle
1887
+ },
1888
+ visualMap: {
1889
+ show: true,
1890
+ min: minZ,
1891
+ max: maxZ,
1892
+ inRange: { color: colorRange },
1893
+ ...visualMapStyle,
1894
+ right: 10,
1895
+ top: "center"
1896
+ },
1897
+ grid3D: {
1898
+ boxWidth: 100,
1899
+ boxHeight: 60,
1900
+ boxDepth: 100,
1901
+ viewControl: {
1902
+ autoRotate,
1903
+ autoRotateSpeed: 3,
1904
+ distance: 220,
1905
+ alpha: 30,
1906
+ beta: 45,
1907
+ rotateSensitivity: 2,
1908
+ zoomSensitivity: 1.5
1909
+ },
1910
+ light: {
1911
+ main: { intensity: 1.2, shadow: true, shadowQuality: "medium" },
1912
+ ambient: { intensity: 0.5 }
1913
+ },
1914
+ postEffect: {
1915
+ enable: true,
1916
+ SSAO: { enable: true, radius: 2 }
1917
+ }
1918
+ },
1919
+ xAxis3D: {
1920
+ type: "value",
1921
+ name: xAxisLabel,
1922
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1923
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1924
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)" }
1925
+ },
1926
+ yAxis3D: {
1927
+ type: "value",
1928
+ name: yAxisLabel,
1929
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1930
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1931
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)" }
1932
+ },
1933
+ zAxis3D: {
1934
+ type: "value",
1935
+ name: zAxisLabel,
1936
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
1937
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
1938
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)" }
1939
+ },
1940
+ series: [{
1941
+ type: "surface",
1942
+ data: surfaceData,
1943
+ shading,
1944
+ wireframe: data.wireframe ? {
1945
+ show: true,
1946
+ lineStyle: { color: "rgba(255, 255, 255, 0.2)", width: 0.5 }
1947
+ } : { show: false }
1948
+ }]
1949
+ };
1950
+ }, [data, xAxisLabel, yAxisLabel, zAxisLabel, shading, autoRotate, tooltipStyle, visualMapStyle]);
1951
+ if (!glReady) return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading: true, className });
1952
+ return /* @__PURE__ */ jsx(
1953
+ AstroChart,
1954
+ {
1955
+ ref,
1956
+ type: "scatter",
1957
+ series: [],
1958
+ title,
1959
+ width,
1960
+ height,
1961
+ loading,
1962
+ className,
1963
+ echartsOptions,
1964
+ export: exportOptions,
1965
+ infoTooltip
1966
+ }
1967
+ );
1968
+ }
1969
+ ));
1970
+ const Lines3DChart = memo(forwardRef(
1971
+ function Lines3DChart2({
1972
+ data = [],
1973
+ title,
1974
+ width = "100%",
1975
+ height = 500,
1976
+ showGrid = true,
1977
+ xAxisLabel = "X",
1978
+ yAxisLabel = "Y",
1979
+ zAxisLabel = "Z",
1980
+ showFlowEffect = false,
1981
+ autoRotate = false,
1982
+ loading = false,
1983
+ className = "",
1984
+ export: exportOptions,
1985
+ infoTooltip
1986
+ }, ref) {
1987
+ const { tokens, mode } = useTheme();
1988
+ const tooltipStyle = useChartTooltipStyle();
1989
+ const legendStyle = useChartLegendStyle();
1990
+ tokens.colors.text.primary;
1991
+ tokens.colors.text.secondary;
1992
+ tokens.colors.text.tertiary;
1993
+ const echartsOptions = useMemo(() => {
1994
+ const seriesArray = [];
1995
+ data.forEach((line, idx) => {
1996
+ const lineColor = line.color || ASTRO_DATA_VIZ_COLORS.mixed[idx % ASTRO_DATA_VIZ_COLORS.mixed.length];
1997
+ seriesArray.push({
1998
+ type: "line3D",
1999
+ name: line.name,
2000
+ coordinateSystem: "cartesian3D",
2001
+ data: line.path.map((p) => [p.x, p.y, p.z]),
2002
+ lineStyle: {
2003
+ color: lineColor,
2004
+ width: line.lineWidth || 2,
2005
+ type: line.lineStyle || "solid",
2006
+ opacity: 0.8
2007
+ }
2008
+ });
2009
+ if (line.showEndpoints) {
2010
+ seriesArray.push({
2011
+ type: "scatter3D",
2012
+ name: `${line.name} Points`,
2013
+ coordinateSystem: "cartesian3D",
2014
+ data: [
2015
+ { value: [line.path[0].x, line.path[0].y, line.path[0].z], name: "Start" },
2016
+ { value: [line.path[line.path.length - 1].x, line.path[line.path.length - 1].y, line.path[line.path.length - 1].z], name: "End" }
2017
+ ],
2018
+ symbolSize: 8,
2019
+ itemStyle: { color: lineColor }
2020
+ });
2021
+ }
2022
+ });
2023
+ return {
2024
+ tooltip: {
2025
+ show: true,
2026
+ ...tooltipStyle,
2027
+ formatter: (params) => {
2028
+ const d = params.data || {};
2029
+ if (params.seriesType === "line3D") {
2030
+ return `<div style="font-weight:600">${params.seriesName}</div>`;
2031
+ }
2032
+ const [x, y, z] = d.value || [0, 0, 0];
2033
+ return `<div style="font-weight:600">${d.name || params.seriesName}</div>
2034
+ <div>${xAxisLabel}: ${x.toFixed(2)}</div>
2035
+ <div>${yAxisLabel}: ${y.toFixed(2)}</div>
2036
+ <div>${zAxisLabel}: ${z.toFixed(2)}</div>`;
2037
+ }
2038
+ },
2039
+ legend: {
2040
+ show: data.length > 1,
2041
+ top: 10,
2042
+ ...legendStyle
2043
+ },
2044
+ grid3D: {
2045
+ boxWidth: 100,
2046
+ boxHeight: 100,
2047
+ boxDepth: 100,
2048
+ viewControl: {
2049
+ autoRotate,
2050
+ autoRotateSpeed: 3,
2051
+ distance: 200,
2052
+ alpha: 25,
2053
+ beta: 45,
2054
+ rotateSensitivity: 2,
2055
+ zoomSensitivity: 1.5
2056
+ },
2057
+ light: {
2058
+ main: { intensity: 1.2, shadow: false },
2059
+ ambient: { intensity: 0.4 }
2060
+ },
2061
+ postEffect: {
2062
+ enable: true,
2063
+ bloom: { enable: showFlowEffect, intensity: 0.1 }
2064
+ }
2065
+ },
2066
+ xAxis3D: {
2067
+ type: "value",
2068
+ name: xAxisLabel,
2069
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
2070
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
2071
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)" },
2072
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } }
2073
+ },
2074
+ yAxis3D: {
2075
+ type: "value",
2076
+ name: yAxisLabel,
2077
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
2078
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
2079
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)" },
2080
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } }
2081
+ },
2082
+ zAxis3D: {
2083
+ type: "value",
2084
+ name: zAxisLabel,
2085
+ nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" },
2086
+ axisLine: { lineStyle: { color: "rgba(100, 116, 139, 0.4)" } },
2087
+ axisLabel: { color: "rgba(255, 255, 255, 0.4)" },
2088
+ splitLine: { show: showGrid, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } }
2089
+ },
2090
+ series: seriesArray
2091
+ };
2092
+ }, [data, showGrid, xAxisLabel, yAxisLabel, zAxisLabel, showFlowEffect, autoRotate, tooltipStyle, legendStyle]);
2093
+ return /* @__PURE__ */ jsx(
2094
+ AstroChart,
2095
+ {
2096
+ ref,
2097
+ type: "scatter",
2098
+ series: [],
2099
+ title,
2100
+ width,
2101
+ height,
2102
+ loading,
2103
+ className,
2104
+ echartsOptions,
2105
+ export: exportOptions,
2106
+ infoTooltip
2107
+ }
2108
+ );
2109
+ }
2110
+ ));
2111
+ const SphericalRadar3DChart = memo(forwardRef(
2112
+ function SphericalRadar3DChart2({
2113
+ data = [],
2114
+ title,
2115
+ width = "100%",
2116
+ height = 500,
2117
+ maxRange = 1e3,
2118
+ showRangeRings = true,
2119
+ autoRotate = false,
2120
+ loading = false,
2121
+ className = "",
2122
+ export: exportOptions,
2123
+ infoTooltip
2124
+ }, ref) {
2125
+ const glReady = useEchartsGlReady();
2126
+ const tooltipStyle = useChartTooltipStyle();
2127
+ useChartLegendStyle();
2128
+ const categoryColors = {
2129
+ satellite: "#56f000",
2130
+ debris: "#ff3838",
2131
+ unknown: "#fce83a",
2132
+ friendly: "#3E3CFF",
2133
+ hostile: "#ff3838"
2134
+ };
2135
+ const echartsOptions = useMemo(() => {
2136
+ const scatterData = data.map((obj) => {
2137
+ const azRad = obj.azimuth * Math.PI / 180;
2138
+ const elRad = obj.elevation * Math.PI / 180;
2139
+ const r = obj.range / maxRange * 100;
2140
+ return {
2141
+ name: obj.name,
2142
+ value: [
2143
+ r * Math.cos(elRad) * Math.sin(azRad),
2144
+ r * Math.sin(elRad),
2145
+ r * Math.cos(elRad) * Math.cos(azRad)
2146
+ ],
2147
+ itemStyle: { color: obj.color || categoryColors[obj.category || "unknown"] },
2148
+ symbolSize: obj.size || 12,
2149
+ category: obj.category,
2150
+ azimuth: obj.azimuth,
2151
+ elevation: obj.elevation,
2152
+ range: obj.range
2153
+ };
2154
+ });
2155
+ const rangeRings = [];
2156
+ if (showRangeRings) {
2157
+ [0.25, 0.5, 0.75, 1].forEach((fraction) => {
2158
+ const r = fraction * 100;
2159
+ const ringPoints = Array.from({ length: 73 }, (_, i) => {
2160
+ const angle = i / 72 * Math.PI * 2;
2161
+ return [r * Math.sin(angle), 0, r * Math.cos(angle)];
2162
+ });
2163
+ rangeRings.push({
2164
+ type: "line3D",
2165
+ coordinateSystem: "cartesian3D",
2166
+ data: ringPoints,
2167
+ lineStyle: { color: "rgba(100, 116, 139, 0.3)", width: 1 },
2168
+ silent: true
2169
+ });
2170
+ });
2171
+ }
2172
+ return {
2173
+ tooltip: {
2174
+ show: true,
2175
+ ...tooltipStyle,
2176
+ formatter: (params) => {
2177
+ var _a, _b, _c;
2178
+ const d = params.data || {};
2179
+ let html = `<div style="font-weight:600;font-size:13px;margin-bottom:4px">${d.name}</div>`;
2180
+ html += `<div style="color:rgba(255,255,255,0.5);text-transform:uppercase;font-size:10px;margin-bottom:6px">${d.category || "Unknown"}</div>`;
2181
+ html += `<div>Azimuth: <span style="font-family:monospace">${(_a = d.azimuth) == null ? void 0 : _a.toFixed(1)}°</span></div>`;
2182
+ html += `<div>Elevation: <span style="font-family:monospace">${(_b = d.elevation) == null ? void 0 : _b.toFixed(1)}°</span></div>`;
2183
+ html += `<div style="color:#22d3ee">Range: <span style="font-family:monospace">${(_c = d.range) == null ? void 0 : _c.toFixed(1)} km</span></div>`;
2184
+ return html;
2185
+ }
2186
+ },
2187
+ grid3D: {
2188
+ boxWidth: 100,
2189
+ boxHeight: 50,
2190
+ boxDepth: 100,
2191
+ viewControl: {
2192
+ autoRotate,
2193
+ autoRotateSpeed: 2,
2194
+ distance: 250,
2195
+ alpha: 25,
2196
+ beta: 45,
2197
+ rotateSensitivity: 2,
2198
+ zoomSensitivity: 1.5
2199
+ },
2200
+ light: {
2201
+ main: { intensity: 1.2, shadow: false },
2202
+ ambient: { intensity: 0.5 }
2203
+ },
2204
+ postEffect: { enable: true, bloom: { enable: true, intensity: 0.05 } }
2205
+ },
2206
+ xAxis3D: { type: "value", name: "East", min: -100, max: 100, axisLabel: { show: false }, splitLine: { show: false } },
2207
+ yAxis3D: { type: "value", name: "Up", min: -50, max: 100, axisLabel: { show: false }, splitLine: { show: false } },
2208
+ zAxis3D: { type: "value", name: "North", min: -100, max: 100, axisLabel: { show: false }, splitLine: { show: false } },
2209
+ series: [...rangeRings, { type: "scatter3D", coordinateSystem: "cartesian3D", data: scatterData, symbolSize: 12 }]
2210
+ };
2211
+ }, [data, maxRange, showRangeRings, autoRotate, categoryColors, tooltipStyle]);
2212
+ if (!glReady) return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading: true, className });
2213
+ return /* @__PURE__ */ jsx(
2214
+ AstroChart,
2215
+ {
2216
+ ref,
2217
+ type: "scatter",
2218
+ series: [],
2219
+ title,
2220
+ width,
2221
+ height,
2222
+ loading,
2223
+ className,
2224
+ echartsOptions,
2225
+ export: exportOptions,
2226
+ infoTooltip
2227
+ }
2228
+ );
2229
+ }
2230
+ ));
2231
+ const TransferOrbit3DChart = memo(forwardRef(
2232
+ function TransferOrbit3DChart2({
2233
+ segments = [],
2234
+ waypoints = [],
2235
+ referenceOrbits = [],
2236
+ title,
2237
+ width = "100%",
2238
+ height = 550,
2239
+ showDeltaV = true,
2240
+ autoRotate = false,
2241
+ loading = false,
2242
+ className = "",
2243
+ export: exportOptions,
2244
+ infoTooltip
2245
+ }, ref) {
2246
+ const glReady = useEchartsGlReady();
2247
+ const tooltipStyle = useChartTooltipStyle();
2248
+ const legendStyle = useChartLegendStyle();
2249
+ const { tokens, mode } = useTheme();
2250
+ const labelPrimary = tokens.colors.text.primary;
2251
+ const labelSecondary = tokens.colors.text.secondary;
2252
+ const labelTertiary = tokens.colors.text.tertiary;
2253
+ const labelBg = mode === "dark" ? "rgba(15, 23, 42, 0.72)" : "rgba(255, 255, 255, 0.9)";
2254
+ const segmentColors = { coast: "#9D70FF", burn: "#ff3838", "gravity-assist": "#22d3ee", spiral: "#56f000" };
2255
+ const waypointColors = { departure: "#3E3CFF", arrival: "#56f000", flyby: "#22d3ee", node: "#fce83a", burn: "#ff3838" };
2256
+ const echartsOptions = useMemo(() => {
2257
+ const seriesArray = [];
2258
+ referenceOrbits.forEach((orbit) => {
2259
+ seriesArray.push({
2260
+ type: "line3D",
2261
+ name: orbit.name,
2262
+ coordinateSystem: "cartesian3D",
2263
+ data: orbit.path.map((p) => [p.x, p.y, p.z]),
2264
+ lineStyle: { color: orbit.color || "rgba(100, 116, 139, 0.3)", width: 1, type: "dashed" },
2265
+ silent: true
2266
+ });
2267
+ });
2268
+ segments.forEach((segment, idx) => {
2269
+ const color = segment.color || segmentColors[segment.type] || ASTRO_DATA_VIZ_COLORS.mixed[idx % ASTRO_DATA_VIZ_COLORS.mixed.length];
2270
+ seriesArray.push({
2271
+ type: "line3D",
2272
+ name: segment.name,
2273
+ coordinateSystem: "cartesian3D",
2274
+ data: segment.path.map((p) => [p.x, p.y, p.z]),
2275
+ lineStyle: { color, width: segment.type === "burn" ? 4 : 2 }
2276
+ });
2277
+ });
2278
+ if (waypoints.length > 0) {
2279
+ seriesArray.push({
2280
+ type: "scatter3D",
2281
+ name: "Waypoints",
2282
+ coordinateSystem: "cartesian3D",
2283
+ data: waypoints.map((wp) => ({
2284
+ name: wp.name,
2285
+ value: [wp.position.x, wp.position.y, wp.position.z],
2286
+ itemStyle: { color: waypointColors[wp.type] || "#fff" },
2287
+ symbolSize: wp.type === "burn" ? 14 : 18,
2288
+ deltaV: wp.deltaV,
2289
+ tof: wp.tof,
2290
+ waypointType: wp.type
2291
+ })),
2292
+ label: { show: true, formatter: (p) => {
2293
+ var _a;
2294
+ return (_a = p.data) == null ? void 0 : _a.name;
2295
+ }, textStyle: { color: labelPrimary, fontSize: 11, backgroundColor: labelBg, padding: [2, 4] } }
2296
+ });
2297
+ }
2298
+ const totalDeltaV = segments.reduce((sum, s) => sum + (s.deltaV || 0), 0) + waypoints.reduce((sum, w) => sum + (w.deltaV || 0), 0);
2299
+ return {
2300
+ tooltip: {
2301
+ show: true,
2302
+ ...tooltipStyle,
2303
+ formatter: (params) => {
2304
+ const d = params.data || {};
2305
+ if (params.seriesType === "line3D") {
2306
+ const seg = segments.find((s) => s.name === params.seriesName);
2307
+ return `<div style="font-weight:600">${params.seriesName}</div>${(seg == null ? void 0 : seg.deltaV) ? `<div style="color:#ff3838">ΔV: ${seg.deltaV.toFixed(2)} km/s</div>` : ""}`;
2308
+ }
2309
+ return `<div style="font-weight:600;margin-bottom:4px">${d.name}</div>${d.deltaV ? `<div style="color:#ff3838">ΔV: ${d.deltaV.toFixed(2)} km/s</div>` : ""}${d.tof ? `<div>TOF: ${d.tof.toFixed(0)} days</div>` : ""}`;
2310
+ }
2311
+ },
2312
+ legend: { show: true, top: 10, ...legendStyle },
2313
+ graphic: showDeltaV && totalDeltaV > 0 ? [{ type: "text", right: 20, top: 20, style: { text: `Total ΔV: ${totalDeltaV.toFixed(2)} km/s`, fill: "#ff3838", fontSize: 14, fontWeight: "bold" } }] : void 0,
2314
+ grid3D: { boxWidth: 150, boxHeight: 80, boxDepth: 150, viewControl: { autoRotate, autoRotateSpeed: 2, distance: 280, alpha: 20, beta: 40 }, light: { main: { intensity: 1.2 }, ambient: { intensity: 0.4 } }, postEffect: { enable: true, bloom: { enable: true, intensity: 0.08 } } },
2315
+ xAxis3D: { type: "value", name: "X (AU)", nameTextStyle: { color: labelSecondary }, axisLabel: { color: labelTertiary, formatter: (v) => v.toFixed(1) }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2316
+ yAxis3D: { type: "value", name: "Z (AU)", nameTextStyle: { color: labelSecondary }, axisLabel: { color: labelTertiary, formatter: (v) => v.toFixed(1) }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2317
+ zAxis3D: { type: "value", name: "Y (AU)", nameTextStyle: { color: labelSecondary }, axisLabel: { color: labelTertiary, formatter: (v) => v.toFixed(1) }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2318
+ series: seriesArray
2319
+ };
2320
+ }, [segments, waypoints, referenceOrbits, showDeltaV, autoRotate, segmentColors, waypointColors, tooltipStyle, legendStyle, labelPrimary, labelSecondary, labelTertiary, labelBg]);
2321
+ if (!glReady) return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading: true, className });
2322
+ return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading, className, echartsOptions, export: exportOptions, infoTooltip });
2323
+ }
2324
+ ));
2325
+ const AttitudeHistory3DChart = memo(forwardRef(
2326
+ function AttitudeHistory3DChart2({
2327
+ data = [],
2328
+ title,
2329
+ width = "100%",
2330
+ height = 500,
2331
+ mode = "euler",
2332
+ showModeTransitions = true,
2333
+ autoRotate = false,
2334
+ loading = false,
2335
+ className = "",
2336
+ export: exportOptions,
2337
+ infoTooltip
2338
+ }, ref) {
2339
+ const glReady = useEchartsGlReady();
2340
+ const tooltipStyle = useChartTooltipStyle();
2341
+ const legendStyle = useChartLegendStyle();
2342
+ const echartsOptions = useMemo(() => {
2343
+ const seriesArray = [];
2344
+ if (mode === "euler" && data.length > 0) {
2345
+ const pathData = data.filter((d) => d.euler).map((d) => [d.euler.roll, d.euler.pitch, d.euler.yaw]);
2346
+ seriesArray.push({ type: "line3D", name: "Attitude Path", coordinateSystem: "cartesian3D", data: pathData, lineStyle: { color: "#3E3CFF", width: 2 } });
2347
+ if (pathData.length > 0) {
2348
+ seriesArray.push({ type: "scatter3D", name: "Start/End", coordinateSystem: "cartesian3D", data: [
2349
+ { value: pathData[0], name: "Start", itemStyle: { color: "#56f000" } },
2350
+ { value: pathData[pathData.length - 1], name: "End", itemStyle: { color: "#ff3838" } }
2351
+ ], symbolSize: 14 });
2352
+ }
2353
+ if (showModeTransitions) {
2354
+ const transitions = data.filter((d, i) => i > 0 && d.mode !== data[i - 1].mode && d.euler);
2355
+ if (transitions.length > 0) {
2356
+ seriesArray.push({ type: "scatter3D", name: "Mode Changes", coordinateSystem: "cartesian3D", data: transitions.map((d) => ({ value: [d.euler.roll, d.euler.pitch, d.euler.yaw], name: d.mode, itemStyle: { color: "#fce83a" } })), symbolSize: 10, symbol: "diamond" });
2357
+ }
2358
+ }
2359
+ }
2360
+ return {
2361
+ tooltip: {
2362
+ show: true,
2363
+ ...tooltipStyle,
2364
+ formatter: (params) => {
2365
+ const d = params.data || {};
2366
+ const [roll, pitch, yaw] = d.value || [0, 0, 0];
2367
+ return `<div style="font-weight:600;margin-bottom:4px">${d.name || params.seriesName}</div><div>Roll: ${roll.toFixed(2)}°</div><div>Pitch: ${pitch.toFixed(2)}°</div><div>Yaw: ${yaw.toFixed(2)}°</div>`;
2368
+ }
2369
+ },
2370
+ legend: { show: true, top: 10, ...legendStyle },
2371
+ grid3D: { boxWidth: 100, boxHeight: 100, boxDepth: 100, viewControl: { autoRotate, distance: 220, alpha: 25, beta: 45 }, light: { main: { intensity: 1.2 }, ambient: { intensity: 0.4 } } },
2372
+ xAxis3D: { type: "value", name: "Roll (°)", nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" }, axisLabel: { color: "rgba(255, 255, 255, 0.4)" }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2373
+ yAxis3D: { type: "value", name: "Pitch (°)", nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" }, axisLabel: { color: "rgba(255, 255, 255, 0.4)" }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2374
+ zAxis3D: { type: "value", name: "Yaw (°)", nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" }, axisLabel: { color: "rgba(255, 255, 255, 0.4)" }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2375
+ series: seriesArray
2376
+ };
2377
+ }, [data, mode, showModeTransitions, autoRotate, tooltipStyle, legendStyle]);
2378
+ if (!glReady) return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading: true, className });
2379
+ return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading, className, echartsOptions, export: exportOptions, infoTooltip });
2380
+ }
2381
+ ));
2382
+ const ConjunctionAssessment3DChart = memo(forwardRef(
2383
+ function ConjunctionAssessment3DChart2({
2384
+ events = [],
2385
+ primaryOrbit = [],
2386
+ title,
2387
+ width = "100%",
2388
+ height = 550,
2389
+ showUncertainty = true,
2390
+ warningThreshold = 5,
2391
+ criticalThreshold = 1,
2392
+ autoRotate = false,
2393
+ loading = false,
2394
+ className = "",
2395
+ export: exportOptions,
2396
+ infoTooltip
2397
+ }, ref) {
2398
+ const glReady = useEchartsGlReady();
2399
+ const tooltipStyle = useChartTooltipStyle();
2400
+ const legendStyle = useChartLegendStyle();
2401
+ const { tokens, mode } = useTheme();
2402
+ tokens.colors.text.primary;
2403
+ tokens.colors.text.secondary;
2404
+ tokens.colors.text.tertiary;
2405
+ const echartsOptions = useMemo(() => {
2406
+ const seriesArray = [];
2407
+ if (primaryOrbit && primaryOrbit.length > 0) {
2408
+ seriesArray.push({ type: "line3D", name: "Primary Orbit", coordinateSystem: "cartesian3D", data: primaryOrbit.map((p) => [p.x, p.y, p.z]), lineStyle: { color: "#3E3CFF", width: 2 } });
2409
+ }
2410
+ const eventData = events.map((evt) => {
2411
+ const color = evt.missDistance < criticalThreshold ? "#ff3838" : evt.missDistance < warningThreshold ? "#fce83a" : "#56f000";
2412
+ return { name: `${evt.primary} × ${evt.secondary}`, value: [evt.position.x, evt.position.y, evt.position.z], itemStyle: { color }, symbolSize: Math.max(8, Math.min(24, 30 - evt.missDistance * 3)), ...evt };
2413
+ });
2414
+ seriesArray.push({ type: "scatter3D", name: "Conjunctions", coordinateSystem: "cartesian3D", data: eventData, symbol: "circle", emphasis: { itemStyle: { borderColor: "#fff", borderWidth: 2 } } });
2415
+ if (showUncertainty) {
2416
+ events.filter((e) => e.uncertainty).forEach((evt) => {
2417
+ const { x, y, z } = evt.position;
2418
+ const { rx, ry, rz } = evt.uncertainty;
2419
+ seriesArray.push({ type: "line3D", coordinateSystem: "cartesian3D", data: [[x - rx, y, z], [x + rx, y, z]], lineStyle: { color: "rgba(255, 255, 255, 0.3)", width: 1 }, silent: true });
2420
+ seriesArray.push({ type: "line3D", coordinateSystem: "cartesian3D", data: [[x, y - ry, z], [x, y + ry, z]], lineStyle: { color: "rgba(255, 255, 255, 0.3)", width: 1 }, silent: true });
2421
+ seriesArray.push({ type: "line3D", coordinateSystem: "cartesian3D", data: [[x, y, z - rz], [x, y, z + rz]], lineStyle: { color: "rgba(255, 255, 255, 0.3)", width: 1 }, silent: true });
2422
+ });
2423
+ }
2424
+ return {
2425
+ tooltip: {
2426
+ show: true,
2427
+ ...tooltipStyle,
2428
+ formatter: (params) => {
2429
+ var _a;
2430
+ const d = params.data || {};
2431
+ if (params.seriesType === "line3D") return "";
2432
+ const mdColor = d.missDistance < criticalThreshold ? "#ff3838" : d.missDistance < warningThreshold ? "#fce83a" : "#56f000";
2433
+ return `<div style="font-weight:600;margin-bottom:4px">${d.name}</div><div style="color:${mdColor}">Miss Distance: ${(_a = d.missDistance) == null ? void 0 : _a.toFixed(3)} km</div>${d.probability !== void 0 ? `<div>Probability: ${(d.probability * 100).toExponential(2)}%</div>` : ""}${d.relativeVelocity ? `<div>Rel. Velocity: ${d.relativeVelocity.toFixed(2)} km/s</div>` : ""}`;
2434
+ }
2435
+ },
2436
+ legend: { show: true, top: 10, ...legendStyle },
2437
+ grid3D: { boxWidth: 100, boxHeight: 100, boxDepth: 100, viewControl: { autoRotate, distance: 220, alpha: 25, beta: 45 }, light: { main: { intensity: 1.2 }, ambient: { intensity: 0.4 } }, postEffect: { enable: true, bloom: { enable: true, intensity: 0.05 } } },
2438
+ xAxis3D: { type: "value", name: "X (km)", nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" }, axisLabel: { color: "rgba(255, 255, 255, 0.4)" }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2439
+ yAxis3D: { type: "value", name: "Y (km)", nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" }, axisLabel: { color: "rgba(255, 255, 255, 0.4)" }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2440
+ zAxis3D: { type: "value", name: "Z (km)", nameTextStyle: { color: "rgba(255, 255, 255, 0.5)" }, axisLabel: { color: "rgba(255, 255, 255, 0.4)" }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2441
+ series: seriesArray
2442
+ };
2443
+ }, [events, primaryOrbit, showUncertainty, warningThreshold, criticalThreshold, autoRotate, tooltipStyle, legendStyle]);
2444
+ if (!glReady) return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading: true, className });
2445
+ return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading, className, echartsOptions, export: exportOptions, infoTooltip });
2446
+ }
2447
+ ));
2448
+ const LaunchCorridor3DChart = memo(forwardRef(
2449
+ function LaunchCorridor3DChart2({
2450
+ data = { corridors: [] },
2451
+ title,
2452
+ width = "100%",
2453
+ height = 550,
2454
+ showTrajectory = true,
2455
+ autoRotate = false,
2456
+ loading = false,
2457
+ className = "",
2458
+ export: exportOptions,
2459
+ infoTooltip
2460
+ }, ref) {
2461
+ const glReady = useEchartsGlReady();
2462
+ const { tokens, mode } = useTheme();
2463
+ const tooltipStyle = useChartTooltipStyle();
2464
+ const labelPrimary = tokens.colors.text.primary;
2465
+ const labelSecondary = tokens.colors.text.secondary;
2466
+ const labelTertiary = tokens.colors.text.tertiary;
2467
+ const labelBg = mode === "dark" ? "rgba(15, 23, 42, 0.72)" : "rgba(255, 255, 255, 0.9)";
2468
+ const legendStyle = useChartLegendStyle();
2469
+ const corridorColors = { nominal: "rgba(86, 240, 0, 0.4)", abort: "rgba(255, 179, 2, 0.4)", safety: "rgba(34, 211, 238, 0.4)", exclusion: "rgba(255, 56, 56, 0.4)" };
2470
+ const echartsOptions = useMemo(() => {
2471
+ const seriesArray = [];
2472
+ const latLonTo3D = (lat, lon, alt) => [lon, alt * 0.1, lat];
2473
+ data.corridors.forEach((corridor) => {
2474
+ const color = corridor.color || corridorColors[corridor.type] || "rgba(100, 116, 139, 0.4)";
2475
+ const lowerPath = corridor.groundFootprint.map((p) => latLonTo3D(p.lat, p.lon, corridor.altitudeRange[0]));
2476
+ if (lowerPath.length > 0) lowerPath.push(lowerPath[0]);
2477
+ seriesArray.push({ type: "line3D", name: `${corridor.name} (floor)`, coordinateSystem: "cartesian3D", data: lowerPath, lineStyle: { color, width: 2 } });
2478
+ const upperPath = corridor.groundFootprint.map((p) => latLonTo3D(p.lat, p.lon, corridor.altitudeRange[1]));
2479
+ if (upperPath.length > 0) upperPath.push(upperPath[0]);
2480
+ seriesArray.push({ type: "line3D", name: `${corridor.name} (ceiling)`, coordinateSystem: "cartesian3D", data: upperPath, lineStyle: { color, width: 2, type: "dashed" } });
2481
+ });
2482
+ if (showTrajectory && data.trajectory && data.trajectory.length > 0) {
2483
+ seriesArray.push({ type: "line3D", name: "Trajectory", coordinateSystem: "cartesian3D", data: data.trajectory.map((p) => latLonTo3D(p.lat, p.lon, p.altitude)), lineStyle: { color: "#fff", width: 3 } });
2484
+ }
2485
+ if (data.events && data.events.length > 0) {
2486
+ seriesArray.push({ type: "scatter3D", name: "Events", coordinateSystem: "cartesian3D", data: data.events.map((e) => ({ name: e.name, value: latLonTo3D(e.lat, e.lon, e.altitude), itemStyle: { color: "#fce83a" }, altitude: e.altitude, time: e.time })), symbolSize: 12, symbol: "diamond", label: { show: true, formatter: (p) => {
2487
+ var _a;
2488
+ return (_a = p.data) == null ? void 0 : _a.name;
2489
+ }, textStyle: { color: labelPrimary, fontSize: 10, backgroundColor: labelBg, padding: [2, 4] } } });
2490
+ }
2491
+ return {
2492
+ tooltip: {
2493
+ show: true,
2494
+ ...tooltipStyle,
2495
+ formatter: (params) => {
2496
+ const d = params.data || {};
2497
+ if (params.seriesType === "line3D") return `<div style="font-weight:600">${params.seriesName}</div>`;
2498
+ return `<div style="font-weight:600;margin-bottom:4px">${d.name}</div>${d.altitude ? `<div>Altitude: ${d.altitude.toFixed(1)} km</div>` : ""}${d.time ? `<div>T+: ${d.time.toFixed(0)}s</div>` : ""}`;
2499
+ }
2500
+ },
2501
+ legend: { show: true, top: 10, ...legendStyle },
2502
+ grid3D: { boxWidth: 150, boxHeight: 60, boxDepth: 100, viewControl: { autoRotate, distance: 280, alpha: 30, beta: 30 }, light: { main: { intensity: 1.2 }, ambient: { intensity: 0.4 } } },
2503
+ xAxis3D: { type: "value", name: "Longitude (°)", nameTextStyle: { color: labelSecondary }, axisLabel: { color: labelTertiary }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2504
+ yAxis3D: { type: "value", name: "Altitude (km)", nameTextStyle: { color: labelSecondary }, axisLabel: { color: labelTertiary }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2505
+ zAxis3D: { type: "value", name: "Latitude (°)", nameTextStyle: { color: labelSecondary }, axisLabel: { color: labelTertiary }, splitLine: { show: true, lineStyle: { color: "rgba(100, 116, 139, 0.1)" } } },
2506
+ series: seriesArray
2507
+ };
2508
+ }, [data, showTrajectory, autoRotate, corridorColors, tooltipStyle, legendStyle, labelPrimary, labelSecondary, labelTertiary, labelBg]);
2509
+ if (!glReady) return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading: true, className });
2510
+ return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading, className, echartsOptions, export: exportOptions, infoTooltip });
2511
+ }
2512
+ ));
2513
+ const AntennaPattern3DChart = memo(forwardRef(
2514
+ function AntennaPattern3DChart2({
2515
+ patterns = [],
2516
+ title,
2517
+ width = "100%",
2518
+ height = 500,
2519
+ minGain = -20,
2520
+ autoRotate = true,
2521
+ loading = false,
2522
+ className = "",
2523
+ export: exportOptions,
2524
+ infoTooltip
2525
+ }, ref) {
2526
+ const glReady = useEchartsGlReady();
2527
+ const { tokens } = useTheme();
2528
+ const tooltipStyle = useChartTooltipStyle();
2529
+ tokens.colors.text.primary;
2530
+ tokens.colors.text.secondary;
2531
+ const legendStyle = useChartLegendStyle();
2532
+ const echartsOptions = useMemo(() => {
2533
+ const seriesArray = [];
2534
+ patterns.forEach((pattern, pIdx) => {
2535
+ const color = pattern.color || ASTRO_DATA_VIZ_COLORS.mixed[pIdx % ASTRO_DATA_VIZ_COLORS.mixed.length];
2536
+ const maxGain = Math.max(...pattern.pattern.map((p) => p.gain), 0);
2537
+ const surfaceData = pattern.pattern.filter((p) => p.gain >= minGain).map((p) => {
2538
+ const thetaRad = p.theta * Math.PI / 180;
2539
+ const phiRad = p.phi * Math.PI / 180;
2540
+ const r = Math.max(0, (p.gain - minGain) / (maxGain - minGain) * 80 + 20);
2541
+ return { value: [r * Math.sin(thetaRad) * Math.cos(phiRad), r * Math.cos(thetaRad), r * Math.sin(thetaRad) * Math.sin(phiRad)], gain: p.gain, itemStyle: { color, opacity: 0.7 } };
2542
+ });
2543
+ seriesArray.push({ type: "scatter3D", name: pattern.name, coordinateSystem: "cartesian3D", data: surfaceData, symbolSize: 4 });
2544
+ if (pattern.boresight) {
2545
+ const thetaRad = pattern.boresight.theta * Math.PI / 180;
2546
+ const phiRad = pattern.boresight.phi * Math.PI / 180;
2547
+ seriesArray.push({ type: "line3D", name: `${pattern.name} Boresight`, coordinateSystem: "cartesian3D", data: [[0, 0, 0], [100 * Math.sin(thetaRad) * Math.cos(phiRad), 100 * Math.cos(thetaRad), 100 * Math.sin(thetaRad) * Math.sin(phiRad)]], lineStyle: { color: "#fff", width: 2 } });
2548
+ }
2549
+ });
2550
+ return {
2551
+ tooltip: {
2552
+ show: true,
2553
+ ...tooltipStyle,
2554
+ formatter: (params) => {
2555
+ const d = params.data || {};
2556
+ return `<div style="font-weight:600;margin-bottom:4px">${params.seriesName}</div>${d.gain !== void 0 ? `<div style="color:#22d3ee">Gain: ${d.gain.toFixed(1)} dBi</div>` : ""}`;
2557
+ }
2558
+ },
2559
+ legend: { show: patterns.length > 1, top: 10, ...legendStyle },
2560
+ grid3D: { boxWidth: 100, boxHeight: 100, boxDepth: 100, viewControl: { autoRotate, autoRotateSpeed: 3, distance: 220, alpha: 20, beta: 45 }, light: { main: { intensity: 1.2 }, ambient: { intensity: 0.5 } }, postEffect: { enable: true, bloom: { enable: true, intensity: 0.08 } } },
2561
+ xAxis3D: { type: "value", name: "X", min: -100, max: 100, axisLabel: { show: false }, splitLine: { show: false } },
2562
+ yAxis3D: { type: "value", name: "Z", min: -100, max: 100, axisLabel: { show: false }, splitLine: { show: false } },
2563
+ zAxis3D: { type: "value", name: "Y", min: -100, max: 100, axisLabel: { show: false }, splitLine: { show: false } },
2564
+ series: seriesArray
2565
+ };
2566
+ }, [patterns, minGain, autoRotate, tooltipStyle, legendStyle]);
2567
+ if (!glReady) return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading: true, className });
2568
+ return /* @__PURE__ */ jsx(AstroChart, { ref, type: "scatter", series: [], title, width, height, loading, className, echartsOptions, export: exportOptions, infoTooltip });
2569
+ }
2570
+ ));
2571
+ const WaterfallChart = memo(forwardRef(
2572
+ function WaterfallChart2({
2573
+ data = [],
2574
+ title = "RF Spectrum Waterfall",
2575
+ centerFrequency: _centerFrequency,
2576
+ bandwidth: _bandwidth,
2577
+ fftBins = 512,
2578
+ colorMap = "viridis",
2579
+ powerRange = [-120, -60],
2580
+ timeWindow = 60,
2581
+ markers: _markers = [],
2582
+ showSpectrum: _showSpectrum = true,
2583
+ width = "100%",
2584
+ height = 400,
2585
+ loading = false,
2586
+ className = "",
2587
+ export: exportOptions,
2588
+ infoTooltip
2589
+ }, ref) {
2590
+ const { tokens } = useTheme();
2591
+ const tooltipStyle = useChartTooltipStyle();
2592
+ tokens.colors.text.primary;
2593
+ tokens.colors.text.secondary;
2594
+ const colorMaps = {
2595
+ viridis: ["#440154", "#482777", "#3e4989", "#31688e", "#26828e", "#1f9e89", "#35b779", "#6ece58", "#b5de2b", "#fde725"],
2596
+ plasma: ["#0d0887", "#46039f", "#7201a8", "#9c179e", "#bd3786", "#d8576b", "#ed7953", "#fb9f3a", "#fdca26", "#f0f921"],
2597
+ inferno: ["#000004", "#1b0c41", "#4a0c6b", "#781c6d", "#a52c60", "#cf4446", "#ed6925", "#fb9b06", "#f7d13d", "#fcffa4"],
2598
+ magma: ["#000004", "#180f3d", "#440f76", "#721f81", "#9e2f7f", "#cd4071", "#f1605d", "#fd9668", "#feca8d", "#fcfdbf"]
2599
+ };
2600
+ const echartsOptions = useMemo(() => {
2601
+ if (!data.length) return {};
2602
+ const heatmapData = [];
2603
+ const timeLabels = [];
2604
+ const freqLabels = [];
2605
+ const firstPoint = data[0];
2606
+ const freqMin = Math.min(...firstPoint.frequencies);
2607
+ const freqMax = Math.max(...firstPoint.frequencies);
2608
+ const freqStep = (freqMax - freqMin) / (fftBins - 1);
2609
+ for (let i = 0; i < fftBins; i++) {
2610
+ const freq = freqMin + i * freqStep;
2611
+ freqLabels.push((freq / 1e6).toFixed(2));
2612
+ }
2613
+ data.slice(-timeWindow).forEach((point, tIdx) => {
2614
+ const time = point.time instanceof Date ? point.time : new Date(point.time);
2615
+ timeLabels.push(time.toLocaleTimeString());
2616
+ point.powers.forEach((power, fIdx) => {
2617
+ if (fIdx < fftBins) {
2618
+ heatmapData.push([fIdx, tIdx, power]);
2619
+ }
2620
+ });
2621
+ });
2622
+ return {
2623
+ tooltip: {
2624
+ show: true,
2625
+ ...tooltipStyle,
2626
+ formatter: (params) => {
2627
+ if (Array.isArray(params)) return "";
2628
+ const [fIdx, tIdx, power] = params.data || [];
2629
+ const freq = freqLabels[fIdx] || "N/A";
2630
+ const time = timeLabels[tIdx] || "N/A";
2631
+ return `<div style="font-weight:600">Spectrum</div>
2632
+ <div>Frequency: ${freq} MHz</div>
2633
+ <div>Time: ${time}</div>
2634
+ <div>Power: ${(power == null ? void 0 : power.toFixed(1)) ?? "N/A"} dBm</div>`;
2635
+ }
2636
+ },
2637
+ grid: { left: 60, right: 40, top: 40, bottom: 60 },
2638
+ xAxis: { type: "category", data: freqLabels, name: "Frequency (MHz)", nameLocation: "middle", nameGap: 35 },
2639
+ yAxis: { type: "category", data: timeLabels, name: "Time", nameLocation: "middle", nameGap: 45 },
2640
+ visualMap: {
2641
+ min: powerRange[0],
2642
+ max: powerRange[1],
2643
+ calculable: true,
2644
+ orient: "horizontal",
2645
+ left: "center",
2646
+ bottom: 0,
2647
+ // Enable hover linking - highlight only hovered range
2648
+ hoverLink: true,
2649
+ // Non-hovered regions get faded opacity
2650
+ outOfRange: {
2651
+ color: "rgba(128, 128, 128, 0.12)",
2652
+ opacity: 0.15
2653
+ },
2654
+ inRange: { color: colorMaps[colorMap] || colorMaps.viridis },
2655
+ text: [`${powerRange[1]} dBm`, `${powerRange[0]} dBm`],
2656
+ textStyle: { color: "rgba(255, 255, 255, 0.7)" }
2657
+ },
2658
+ series: [{
2659
+ type: "heatmap",
2660
+ data: heatmapData,
2661
+ emphasis: { itemStyle: { borderColor: "#fff", borderWidth: 1 } }
2662
+ }]
2663
+ };
2664
+ }, [data, fftBins, colorMap, powerRange, timeWindow, tooltipStyle]);
2665
+ return /* @__PURE__ */ jsx(
2666
+ AstroChart,
2667
+ {
2668
+ ref,
2669
+ type: "heatmap",
2670
+ series: [],
2671
+ title,
2672
+ width,
2673
+ height,
2674
+ loading,
2675
+ className,
2676
+ echartsOptions,
2677
+ export: exportOptions,
2678
+ infoTooltip
2679
+ }
2680
+ );
2681
+ }
2682
+ ));
2683
+ const DopplerTrackChart = memo(forwardRef(
2684
+ function DopplerTrackChart2({
2685
+ predicted = [],
2686
+ measured = [],
2687
+ carrierFrequency: _carrierFrequency,
2688
+ passInfo,
2689
+ showResiduals = false,
2690
+ showElevation = true,
2691
+ title,
2692
+ width = "100%",
2693
+ height = 300,
2694
+ loading = false,
2695
+ className = "",
2696
+ export: exportOptions,
2697
+ infoTooltip
2698
+ }, ref) {
2699
+ const tooltipStyle = useChartTooltipStyle();
2700
+ const chartTitle = title || (passInfo ? `Doppler Track – ${passInfo.name}` : "Doppler Track");
2701
+ const echartsOptions = useMemo(() => {
2702
+ const series = [];
2703
+ if (predicted.length > 0) {
2704
+ series.push({
2705
+ name: "Predicted",
2706
+ type: "line",
2707
+ data: predicted.map((p) => {
2708
+ const time = p.time instanceof Date ? p.time.getTime() : p.time;
2709
+ return [time, p.dopplerShift];
2710
+ }),
2711
+ lineStyle: { color: ASTRO_DATA_VIZ_COLORS.mixed[0], width: 2 },
2712
+ symbol: "none",
2713
+ smooth: true
2714
+ });
2715
+ }
2716
+ if (measured.length > 0) {
2717
+ series.push({
2718
+ name: "Measured",
2719
+ type: "scatter",
2720
+ data: measured.map((p) => {
2721
+ const time = p.time instanceof Date ? p.time.getTime() : p.time;
2722
+ return [time, p.dopplerShift];
2723
+ }),
2724
+ itemStyle: { color: ASTRO_DATA_VIZ_COLORS.mixed[2] },
2725
+ symbolSize: 4
2726
+ });
2727
+ }
2728
+ if (showElevation && predicted.some((p) => p.elevation !== void 0)) {
2729
+ series.push({
2730
+ name: "Elevation",
2731
+ type: "line",
2732
+ yAxisIndex: 1,
2733
+ data: predicted.filter((p) => p.elevation !== void 0).map((p) => {
2734
+ const time = p.time instanceof Date ? p.time.getTime() : p.time;
2735
+ return [time, p.elevation];
2736
+ }),
2737
+ lineStyle: { color: SOFT_STATUS_COLORS.normal, width: 1, type: "dashed" },
2738
+ symbol: "none",
2739
+ areaStyle: { color: `${STATUS_COLORS.normal}20` }
2740
+ });
2741
+ }
2742
+ return {
2743
+ tooltip: {
2744
+ show: true,
2745
+ trigger: "axis",
2746
+ ...tooltipStyle,
2747
+ formatter: (params) => {
2748
+ if (!Array.isArray(params) || params.length === 0) return "";
2749
+ const firstParam = params[0];
2750
+ const time = new Date(firstParam.data[0]).toLocaleTimeString();
2751
+ let html = `<div style="font-weight:600;margin-bottom:4px">${time}</div>`;
2752
+ params.forEach((p) => {
2753
+ var _a;
2754
+ const value = p.seriesName === "Elevation" ? `${(_a = p.data[1]) == null ? void 0 : _a.toFixed(1)}°` : `${(p.data[1] / 1e3).toFixed(2)} kHz`;
2755
+ html += `<div>${p.marker} ${p.seriesName}: ${value}</div>`;
2756
+ });
2757
+ return html;
2758
+ }
2759
+ },
2760
+ legend: { show: true, top: 10 },
2761
+ grid: { left: 60, right: 60, top: 50, bottom: 40 },
2762
+ xAxis: { type: "time", name: "Time" },
2763
+ yAxis: [
2764
+ { type: "value", name: "Doppler (kHz)", axisLabel: { formatter: (v) => (v / 1e3).toFixed(1) } },
2765
+ { type: "value", name: "Elevation (°)", position: "right", min: 0, max: 90, show: showElevation }
2766
+ ],
2767
+ series
2768
+ };
2769
+ }, [predicted, measured, showResiduals, showElevation, tooltipStyle]);
2770
+ return /* @__PURE__ */ jsx(
2771
+ AstroChart,
2772
+ {
2773
+ ref,
2774
+ type: "line",
2775
+ title: chartTitle,
2776
+ series: [],
2777
+ width,
2778
+ height,
2779
+ loading,
2780
+ className,
2781
+ echartsOptions,
2782
+ export: exportOptions,
2783
+ infoTooltip
2784
+ }
2785
+ );
2786
+ }
2787
+ ));
2788
+ const LinkMarginChart = memo(forwardRef(
2789
+ function LinkMarginChart2({
2790
+ data = [],
2791
+ minMargin,
2792
+ mode = "both",
2793
+ showRainFade: _showRainFade = false,
2794
+ title = "Link Margin vs Elevation",
2795
+ width = "100%",
2796
+ height = 250,
2797
+ loading = false,
2798
+ className = "",
2799
+ export: exportOptions,
2800
+ infoTooltip
2801
+ }, ref) {
2802
+ const series = [];
2803
+ if ((mode === "uplink" || mode === "both") && data.some((d) => d.uplinkMargin !== void 0)) {
2804
+ series.push({
2805
+ id: "uplink",
2806
+ name: "Uplink Margin",
2807
+ data: data.filter((d) => d.uplinkMargin !== void 0).map((d) => ({ x: d.elevation, y: d.uplinkMargin })),
2808
+ color: ASTRO_DATA_VIZ_COLORS.mixed[0]
2809
+ });
2810
+ }
2811
+ if ((mode === "downlink" || mode === "both") && data.some((d) => d.downlinkMargin !== void 0)) {
2812
+ series.push({
2813
+ id: "downlink",
2814
+ name: "Downlink Margin",
2815
+ data: data.filter((d) => d.downlinkMargin !== void 0).map((d) => ({ x: d.elevation, y: d.downlinkMargin })),
2816
+ color: ASTRO_DATA_VIZ_COLORS.mixed[2]
2817
+ });
2818
+ }
2819
+ const annotations = {
2820
+ markLines: {
2821
+ data: [{
2822
+ yAxis: minMargin,
2823
+ label: `Min Margin (${minMargin} dB)`,
2824
+ color: SOFT_STATUS_COLORS.caution,
2825
+ lineStyle: { type: "dashed" }
2826
+ }]
2827
+ },
2828
+ markAreas: {
2829
+ data: [[
2830
+ { yAxis: 0, name: "Insufficient Margin" },
2831
+ { yAxis: minMargin }
2832
+ ]],
2833
+ itemStyle: { color: `${STATUS_COLORS.critical}15` }
2834
+ }
2835
+ };
2836
+ return /* @__PURE__ */ jsx(
2837
+ AstroChart,
2838
+ {
2839
+ ref,
2840
+ type: "line",
2841
+ title,
2842
+ series,
2843
+ width,
2844
+ height,
2845
+ loading,
2846
+ className,
2847
+ xAxis: { type: "value", name: "Elevation (°)", min: 0, max: 90 },
2848
+ yAxis: { type: "value", name: "Margin (dB)" },
2849
+ tooltip: { trigger: "axis", crosshair: "x" },
2850
+ legend: { show: mode === "both", position: "bottom" },
2851
+ annotations,
2852
+ export: exportOptions,
2853
+ infoTooltip
2854
+ }
2855
+ );
2856
+ }
2857
+ ));
2858
+ const ConstellationCoverageChart = memo(forwardRef(
2859
+ function ConstellationCoverageChart2({
2860
+ data = { coverage: [], latitudes: [], longitudes: [] },
2861
+ title = "Constellation Coverage",
2862
+ metricLabel = "Coverage",
2863
+ metricUnit = "%",
2864
+ colorMap = "viridis",
2865
+ valueRange,
2866
+ satellites = [],
2867
+ groundStations = [],
2868
+ width = "100%",
2869
+ height = 400,
2870
+ loading = false,
2871
+ className = "",
2872
+ export: exportOptions,
2873
+ infoTooltip
2874
+ }, ref) {
2875
+ const { tokens } = useTheme();
2876
+ const tooltipStyle = useChartTooltipStyle();
2877
+ const labelPrimary = tokens.colors.text.primary;
2878
+ const labelSecondary = tokens.colors.text.secondary;
2879
+ const colorMaps = {
2880
+ viridis: ["#440154", "#482777", "#3e4989", "#31688e", "#26828e", "#1f9e89", "#35b779", "#6ece58", "#b5de2b", "#fde725"],
2881
+ jet: ["#00007f", "#0000ff", "#007fff", "#00ffff", "#7fff7f", "#ffff00", "#ff7f00", "#ff0000", "#7f0000"],
2882
+ plasma: ["#0d0887", "#46039f", "#7201a8", "#9c179e", "#bd3786", "#d8576b", "#ed7953", "#fb9f3a", "#fdca26", "#f0f921"],
2883
+ thermal: ["#000000", "#1a0a2e", "#3d1551", "#6b1d6a", "#a12568", "#d3405c", "#eb6841", "#f5a623", "#f7dc6f", "#ffffff"]
2884
+ };
2885
+ const echartsOptions = useMemo(() => {
2886
+ if (!data.coverage.length || !data.latitudes.length || !data.longitudes.length) return {};
2887
+ const heatmapData = [];
2888
+ let minVal = Infinity;
2889
+ let maxVal = -Infinity;
2890
+ data.latitudes.forEach((_, latIdx) => {
2891
+ data.longitudes.forEach((_2, lonIdx) => {
2892
+ var _a;
2893
+ const val = ((_a = data.coverage[latIdx]) == null ? void 0 : _a[lonIdx]) ?? 0;
2894
+ heatmapData.push([lonIdx, latIdx, val]);
2895
+ if (val < minVal) minVal = val;
2896
+ if (val > maxVal) maxVal = val;
2897
+ });
2898
+ });
2899
+ const range = valueRange || [minVal, maxVal];
2900
+ const lonLabels = data.longitudes.map((v) => `${v.toFixed(0)}°`);
2901
+ const latLabels = data.latitudes.map((v) => `${v.toFixed(0)}°`);
2902
+ const seriesArray = [
2903
+ {
2904
+ type: "heatmap",
2905
+ data: heatmapData,
2906
+ emphasis: { itemStyle: { borderColor: "#fff", borderWidth: 1 } },
2907
+ progressive: 5e3
2908
+ }
2909
+ ];
2910
+ if (satellites.length > 0) {
2911
+ seriesArray.push({
2912
+ type: "scatter",
2913
+ name: "Satellites",
2914
+ coordinateSystem: "cartesian2d",
2915
+ data: satellites.map((sat) => {
2916
+ const lonIdx = data.longitudes.findIndex((v) => Math.abs(v - sat.lon) < data.longitudes[1] - data.longitudes[0]);
2917
+ const latIdx = data.latitudes.findIndex((v) => Math.abs(v - sat.lat) < data.latitudes[1] - data.latitudes[0]);
2918
+ return { value: [lonIdx >= 0 ? lonIdx : 0, latIdx >= 0 ? latIdx : 0], name: sat.name, itemStyle: { color: sat.color || "#fff" } };
2919
+ }),
2920
+ symbolSize: 8,
2921
+ symbol: "triangle",
2922
+ z: 10,
2923
+ label: { show: true, formatter: (p) => {
2924
+ var _a;
2925
+ return ((_a = p.data) == null ? void 0 : _a.name) || "";
2926
+ }, position: "top", color: labelPrimary, fontSize: 9 }
2927
+ });
2928
+ }
2929
+ if (groundStations.length > 0) {
2930
+ seriesArray.push({
2931
+ type: "scatter",
2932
+ name: "Ground Stations",
2933
+ coordinateSystem: "cartesian2d",
2934
+ data: groundStations.map((gs) => {
2935
+ const lonIdx = data.longitudes.findIndex((v) => Math.abs(v - gs.lon) < data.longitudes[1] - data.longitudes[0]);
2936
+ const latIdx = data.latitudes.findIndex((v) => Math.abs(v - gs.lat) < data.latitudes[1] - data.latitudes[0]);
2937
+ return { value: [lonIdx >= 0 ? lonIdx : 0, latIdx >= 0 ? latIdx : 0], name: gs.name };
2938
+ }),
2939
+ symbolSize: 10,
2940
+ symbol: "diamond",
2941
+ itemStyle: { color: ASTRO_DATA_VIZ_COLORS.mixed[2] },
2942
+ z: 10,
2943
+ label: { show: true, formatter: (p) => {
2944
+ var _a;
2945
+ return ((_a = p.data) == null ? void 0 : _a.name) || "";
2946
+ }, position: "bottom", color: labelSecondary, fontSize: 9 }
2947
+ });
2948
+ }
2949
+ return {
2950
+ tooltip: {
2951
+ show: true,
2952
+ ...tooltipStyle,
2953
+ formatter: (params) => {
2954
+ if (Array.isArray(params)) return "";
2955
+ const d = params.data;
2956
+ if (params.seriesType === "scatter") return `<div style="font-weight:600">${(d == null ? void 0 : d.name) || ""}</div>`;
2957
+ const [lonIdx, latIdx, val] = d || [];
2958
+ const lon = data.longitudes[lonIdx] ?? "N/A";
2959
+ const lat = data.latitudes[latIdx] ?? "N/A";
2960
+ return `<div style="font-weight:600">${metricLabel}</div>
2961
+ <div>Lat: ${typeof lat === "number" ? lat.toFixed(1) : lat}°</div>
2962
+ <div>Lon: ${typeof lon === "number" ? lon.toFixed(1) : lon}°</div>
2963
+ <div>${metricLabel}: ${(val == null ? void 0 : val.toFixed(1)) ?? "N/A"} ${metricUnit}</div>`;
2964
+ }
2965
+ },
2966
+ grid: { left: 60, right: 50, top: 40, bottom: 80 },
2967
+ xAxis: { type: "category", data: lonLabels, name: "Longitude", nameLocation: "middle", nameGap: 30, axisLabel: { interval: Math.floor(lonLabels.length / 12) } },
2968
+ yAxis: { type: "category", data: latLabels, name: "Latitude", nameLocation: "middle", nameGap: 40, axisLabel: { interval: Math.floor(latLabels.length / 6) } },
2969
+ visualMap: {
2970
+ min: range[0],
2971
+ max: range[1],
2972
+ calculable: true,
2973
+ orient: "horizontal",
2974
+ left: "center",
2975
+ bottom: 0,
2976
+ hoverLink: true,
2977
+ outOfRange: { color: "rgba(128, 128, 128, 0.12)", opacity: 0.15 },
2978
+ inRange: { color: colorMaps[colorMap] || colorMaps.viridis },
2979
+ text: [`${range[1]} ${metricUnit}`, `${range[0]} ${metricUnit}`],
2980
+ textStyle: { color: labelSecondary }
2981
+ },
2982
+ series: seriesArray
2983
+ };
2984
+ }, [data, satellites, groundStations, colorMap, valueRange, metricLabel, metricUnit, tooltipStyle, labelPrimary, labelSecondary]);
2985
+ return /* @__PURE__ */ jsx(
2986
+ AstroChart,
2987
+ {
2988
+ ref,
2989
+ type: "heatmap",
2990
+ series: [],
2991
+ title,
2992
+ width,
2993
+ height,
2994
+ loading,
2995
+ className,
2996
+ echartsOptions,
2997
+ export: exportOptions,
2998
+ infoTooltip
2999
+ }
3000
+ );
3001
+ }
3002
+ ));
3003
+ const ConjunctionChart = memo(forwardRef(
3004
+ function ConjunctionChart2({
3005
+ events = [],
3006
+ timeRange,
3007
+ warningThreshold = 5,
3008
+ criticalThreshold = 1,
3009
+ minProbability: _minProbability,
3010
+ showProbability = true,
3011
+ title = "Conjunction Assessment",
3012
+ width = "100%",
3013
+ height = 350,
3014
+ loading = false,
3015
+ className = "",
3016
+ export: exportOptions,
3017
+ infoTooltip
3018
+ }, ref) {
3019
+ const tooltipStyle = useChartTooltipStyle();
3020
+ const echartsOptions = useMemo(() => {
3021
+ if (!events.length) return {};
3022
+ const sorted = [...events].sort((a, b) => a.tca - b.tca);
3023
+ const missData = sorted.map((evt) => {
3024
+ const color = evt.missDistance < criticalThreshold ? STATUS_COLORS.critical : evt.missDistance < warningThreshold ? STATUS_COLORS.caution : STATUS_COLORS.normal;
3025
+ return {
3026
+ value: [evt.tca, evt.missDistance],
3027
+ itemStyle: { color },
3028
+ symbolSize: Math.max(6, Math.min(20, 22 - evt.missDistance * 2)),
3029
+ ...evt
3030
+ };
3031
+ });
3032
+ const seriesArray = [
3033
+ {
3034
+ name: "Miss Distance",
3035
+ type: "scatter",
3036
+ data: missData,
3037
+ symbolSize: (val) => val.symbolSize || 10,
3038
+ z: 10
3039
+ }
3040
+ ];
3041
+ if (showProbability && sorted.some((e) => e.probability !== void 0)) {
3042
+ seriesArray.push({
3043
+ name: "Probability (Pc)",
3044
+ type: "bar",
3045
+ yAxisIndex: 1,
3046
+ data: sorted.map((evt) => ({
3047
+ value: [evt.tca, evt.probability ?? 0],
3048
+ itemStyle: {
3049
+ color: (evt.probability ?? 0) > 1e-4 ? `${STATUS_COLORS.critical}99` : (evt.probability ?? 0) > 1e-6 ? `${STATUS_COLORS.caution}99` : `${STATUS_COLORS.normal}60`
3050
+ }
3051
+ })),
3052
+ barWidth: 8,
3053
+ z: 5
3054
+ });
3055
+ }
3056
+ return {
3057
+ tooltip: {
3058
+ show: true,
3059
+ trigger: "item",
3060
+ ...tooltipStyle,
3061
+ formatter: (params) => {
3062
+ var _a, _b, _c;
3063
+ const d = params.data || {};
3064
+ if (params.seriesName === "Probability (Pc)") {
3065
+ return `<div>Pc: ${(((_a = d.value) == null ? void 0 : _a[1]) ?? 0).toExponential(2)}</div>`;
3066
+ }
3067
+ const mdColor = d.missDistance < criticalThreshold ? STATUS_COLORS.critical : d.missDistance < warningThreshold ? STATUS_COLORS.caution : STATUS_COLORS.normal;
3068
+ const tca = new Date(((_b = d.value) == null ? void 0 : _b[0]) ?? d.tca);
3069
+ return `<div style="font-weight:600;margin-bottom:4px">${d.primary} × ${d.secondary}</div>
3070
+ <div>TCA: ${tca.toLocaleString()}</div>
3071
+ <div style="color:${mdColor}">Miss Distance: ${(_c = d.missDistance) == null ? void 0 : _c.toFixed(3)} km</div>
3072
+ ${d.probability !== void 0 ? `<div>Pc: ${(d.probability * 100).toExponential(2)}%</div>` : ""}
3073
+ ${d.relativeVelocity ? `<div>Rel. Velocity: ${d.relativeVelocity.toFixed(2)} km/s</div>` : ""}`;
3074
+ }
3075
+ },
3076
+ legend: { show: showProbability, top: 10 },
3077
+ grid: { left: 60, right: showProbability ? 80 : 40, top: 50, bottom: 40 },
3078
+ xAxis: {
3079
+ type: "time",
3080
+ name: "Time of Closest Approach",
3081
+ ...timeRange ? { min: timeRange[0], max: timeRange[1] } : {}
3082
+ },
3083
+ yAxis: [
3084
+ {
3085
+ type: "value",
3086
+ name: "Miss Distance (km)",
3087
+ min: 0,
3088
+ splitLine: { lineStyle: { color: "rgba(100, 116, 139, 0.15)" } }
3089
+ },
3090
+ {
3091
+ type: "log",
3092
+ name: showProbability ? "Probability" : void 0,
3093
+ position: "right",
3094
+ show: showProbability,
3095
+ min: 1e-10,
3096
+ max: 1,
3097
+ axisLabel: { formatter: (v) => v.toExponential(0) },
3098
+ splitLine: { show: false }
3099
+ }
3100
+ ],
3101
+ // Threshold marklines
3102
+ series: seriesArray.map((s, i) => ({
3103
+ ...s,
3104
+ ...i === 0 ? {
3105
+ markLine: {
3106
+ silent: true,
3107
+ data: [
3108
+ { yAxis: criticalThreshold, label: { formatter: `Critical (${criticalThreshold} km)`, color: STATUS_COLORS.critical }, lineStyle: { color: SOFT_STATUS_COLORS.critical, type: "dashed", width: 1 } },
3109
+ { yAxis: warningThreshold, label: { formatter: `Warning (${warningThreshold} km)`, color: STATUS_COLORS.caution }, lineStyle: { color: SOFT_STATUS_COLORS.caution, type: "dashed", width: 1 } }
3110
+ ]
3111
+ },
3112
+ markArea: {
3113
+ silent: true,
3114
+ data: [[{ yAxis: 0 }, { yAxis: criticalThreshold }]],
3115
+ itemStyle: { color: `${STATUS_COLORS.critical}10` }
3116
+ }
3117
+ } : {}
3118
+ }))
3119
+ };
3120
+ }, [events, timeRange, warningThreshold, criticalThreshold, showProbability, tooltipStyle]);
3121
+ return /* @__PURE__ */ jsx(
3122
+ AstroChart,
3123
+ {
3124
+ ref,
3125
+ type: "scatter",
3126
+ series: [],
3127
+ title,
3128
+ width,
3129
+ height,
3130
+ loading,
3131
+ className,
3132
+ echartsOptions,
3133
+ export: exportOptions,
3134
+ infoTooltip
3135
+ }
3136
+ );
3137
+ }
3138
+ ));
3139
+ export {
3140
+ AntennaPattern3DChart,
3141
+ AttitudeChart,
3142
+ AttitudeHistory3DChart,
3143
+ Bar3DChart,
3144
+ ConjunctionAssessment3DChart,
3145
+ ConjunctionChart,
3146
+ ConstellationCoverageChart,
3147
+ ContactWindowChart,
3148
+ DopplerTrackChart,
3149
+ EclipseTimelineChart,
3150
+ HeliocentricOrbitPlot,
3151
+ LaunchCorridor3DChart,
3152
+ Lines3DChart,
3153
+ LinkBudgetChart,
3154
+ LinkMarginChart,
3155
+ ManeuverBudgetChart,
3156
+ OrbitChart,
3157
+ PowerChart,
3158
+ RoseDiagram,
3159
+ Scatter3DChart,
3160
+ SpectrumChart,
3161
+ SphericalRadar3DChart,
3162
+ SubsystemGauge,
3163
+ Surface3DChart,
3164
+ ThermalHeatmapChart,
3165
+ TransferOrbit3DChart,
3166
+ WaterfallChart
3167
+ };
3168
+ //# sourceMappingURL=domain.js.map