@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,1123 @@
1
+ import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
+ import { useRef, useState, useMemo, useEffect, useCallback } from "react";
3
+ import { AstroIcon } from "../core/AstroIcon.js";
4
+ import { useTheme } from "../theme/ThemeProvider.js";
5
+ const STATUS_COLOR_MAP = {
6
+ normal: "#56f000",
7
+ // Green — Astro UXDS "Normal"
8
+ standby: "#2dccff",
9
+ // Cyan — Astro UXDS "Standby"
10
+ caution: "#fce83a",
11
+ // Yellow — Astro UXDS "Caution"
12
+ serious: "#ffb302",
13
+ // Orange — Astro UXDS "Serious"
14
+ critical: "#ff3838",
15
+ // Red — Astro UXDS "Critical"
16
+ off: "#a4abb6"
17
+ // Grey — Astro UXDS "Off"
18
+ };
19
+ const DEFAULT_TRACK_COLORS = [
20
+ "#2dccff",
21
+ "#3E3CFF",
22
+ "#9D70FF",
23
+ "#56f000",
24
+ "#fce83a",
25
+ "#ff7849",
26
+ "#2dd4bf",
27
+ "#ff3838"
28
+ ];
29
+ const WORLD_MAP_PATHS = [
30
+ // North America
31
+ "M-168,70 L-168,60 L-145,63 L-140,58 L-130,55 L-125,49 L-122,48 L-117,33 L-115,28 L-105,22 L-97,18 L-88,20 L-82,25 L-82,30 L-80,32 L-67,47 L-60,46 L-55,52 L-56,60 L-65,70 L-85,73 L-100,72 L-130,70 L-168,70",
32
+ // South America
33
+ "M-82,12 L-77,8 L-73,11 L-65,5 L-60,5 L-50,0 L-45,-5 L-43,-10 L-39,-15 L-38,-22 L-40,-25 L-43,-30 L-48,-33 L-50,-40 L-55,-48 L-57,-52 L-68,-55 L-73,-50 L-78,-42 L-80,-20 L-78,-5 L-82,12",
34
+ // Europe + Africa
35
+ "M-10,72 L-5,60 L-5,48 L0,44 L3,44 L5,48 L8,44 L3,37 L-5,35 L-17,28 L-17,15 L-8,10 L-4,5 L5,5 L10,2 L15,-3 L22,-12 L28,-22 L33,-30 L30,-35 L22,-35 L18,-27 L12,-20 L8,-10 L3,0 L-5,10 L-12,15 L-15,20 L-13,32 L-10,38 L0,48 L8,55 L15,58 L20,60 L25,65 L30,70 L-10,72",
36
+ // Asia
37
+ "M30,70 L40,65 L50,60 L60,55 L70,50 L80,45 L90,45 L100,40 L105,35 L110,30 L115,25 L120,30 L125,35 L130,40 L135,45 L140,50 L145,55 L150,60 L155,65 L160,68 L170,70 L180,70 L180,72 L30,72 L30,70",
38
+ // Australia
39
+ "M112,-12 L118,-14 L125,-15 L132,-13 L138,-15 L143,-17 L148,-20 L152,-23 L153,-28 L150,-33 L147,-37 L140,-38 L134,-36 L130,-33 L126,-30 L120,-30 L116,-28 L114,-24 L113,-18 L112,-12",
40
+ // Antarctica
41
+ "M-180,-72 L180,-72 L180,-90 L-180,-90 Z"
42
+ ];
43
+ function drawCoverageEllipse(ctx, centerLat, centerLon, radiusDeg, W, H, lonToX, latToY, numSegments = 72) {
44
+ const lat0 = centerLat * Math.PI / 180;
45
+ const lon0 = centerLon * Math.PI / 180;
46
+ const d = radiusDeg * Math.PI / 180;
47
+ const cx = lonToX(centerLon, W);
48
+ const cy = latToY(centerLat, H);
49
+ const pxPerDegLon = W / 360;
50
+ const pxPerDegLat = H / 180;
51
+ ctx.beginPath();
52
+ for (let i = 0; i <= numSegments; i++) {
53
+ const bearing = i / numSegments * 2 * Math.PI;
54
+ const sinLat = Math.sin(lat0) * Math.cos(d) + Math.cos(lat0) * Math.sin(d) * Math.cos(bearing);
55
+ const lat = Math.asin(Math.max(-1, Math.min(1, sinLat)));
56
+ const lon = lon0 + Math.atan2(
57
+ Math.sin(bearing) * Math.sin(d) * Math.cos(lat0),
58
+ Math.cos(d) - Math.sin(lat0) * sinLat
59
+ );
60
+ const pLatDeg = lat * 180 / Math.PI;
61
+ const pLonDeg = lon * 180 / Math.PI;
62
+ const dLon = pLonDeg - centerLon;
63
+ const dLat = pLatDeg - centerLat;
64
+ const px = cx + dLon * pxPerDegLon;
65
+ const py = cy - dLat * pxPerDegLat;
66
+ if (i === 0) ctx.moveTo(px, py);
67
+ else ctx.lineTo(px, py);
68
+ }
69
+ ctx.closePath();
70
+ }
71
+ function calculateTerminator(date, numPoints = 72) {
72
+ const dayOfYear = Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 864e5);
73
+ const declination = -23.44 * Math.cos(2 * Math.PI / 365 * (dayOfYear + 10));
74
+ const decRad = declination * Math.PI / 180;
75
+ const hourAngle = (date.getUTCHours() + date.getUTCMinutes() / 60) / 24 * 360 - 180;
76
+ const points = [];
77
+ for (let i = 0; i <= numPoints; i++) {
78
+ const latRad = (i / numPoints * 180 - 90) * (Math.PI / 180);
79
+ const cosH = -Math.tan(latRad) * Math.tan(decRad);
80
+ let lon;
81
+ if (cosH < -1) lon = hourAngle + 180;
82
+ else if (cosH > 1) lon = hourAngle;
83
+ else lon = hourAngle + Math.acos(cosH) * 180 / Math.PI;
84
+ while (lon > 180) lon -= 360;
85
+ while (lon < -180) lon += 360;
86
+ points.push({ lat: i / numPoints * 180 - 90, lon });
87
+ }
88
+ return points;
89
+ }
90
+ function GroundTrackMap({
91
+ groundTrack,
92
+ satellites = [],
93
+ groundStations = [],
94
+ accessMask,
95
+ teamPaths,
96
+ showTerminator = true,
97
+ showGrid = true,
98
+ showLegend = true,
99
+ showEquator = true,
100
+ showRecenterButton = false,
101
+ isLoading = false,
102
+ emptyMessage = "No orbital data available",
103
+ width = "100%",
104
+ height = "100%",
105
+ minHeight = "400px",
106
+ defaultCenter,
107
+ defaultZoom,
108
+ className = "",
109
+ onSatelliteClick,
110
+ onStationClick,
111
+ mapProvider = "leaflet",
112
+ tileUrl
113
+ }) {
114
+ const { tokens } = useTheme();
115
+ const canvasRef = useRef(null);
116
+ const containerRef = useRef(null);
117
+ const [tooltip, setTooltip] = useState(null);
118
+ const [_viewOffset, setViewOffset] = useState({ x: 0, y: 0 });
119
+ const allSatellites = useMemo(() => {
120
+ if (satellites.length > 0) return satellites;
121
+ if (teamPaths && teamPaths.length > 0) {
122
+ return teamPaths.map((tp, idx) => ({
123
+ id: `team-${idx}`,
124
+ name: tp.name,
125
+ color: tp.color,
126
+ status: "normal",
127
+ groundTrack: tp.positions.filter((p) => p.lat != null && p.lng != null).map((p) => ({
128
+ latitude: p.lat,
129
+ longitude: p.lng,
130
+ altitude: p.altitude ?? 0,
131
+ timestamp: p.time != null ? new Date(p.time * 1e3).toISOString() : (/* @__PURE__ */ new Date()).toISOString()
132
+ }))
133
+ }));
134
+ }
135
+ if (groundTrack && groundTrack.length > 0) {
136
+ return [{
137
+ id: "primary",
138
+ name: "Satellite",
139
+ groundTrack,
140
+ status: "normal",
141
+ accessMask
142
+ }];
143
+ }
144
+ return [];
145
+ }, [satellites, groundTrack, accessMask, teamPaths]);
146
+ const leafletDefaultCenter = useMemo(() => defaultCenter ?? [20, 0], [defaultCenter]);
147
+ const leafletDefaultZoom = useMemo(() => defaultZoom ?? 2, [defaultZoom]);
148
+ const [LeafletMap, setLeafletMap] = useState(null);
149
+ const [leafletFailed, setLeafletFailed] = useState(false);
150
+ useEffect(() => {
151
+ if (mapProvider !== "leaflet") return;
152
+ import("./GroundTrackMapLeaflet.js").then((m) => setLeafletMap(() => m.GroundTrackMapLeaflet)).catch((err) => {
153
+ console.warn('[GroundTrackMap] Leaflet backend failed to load. Install "leaflet" and ensure it is resolvable. Falling back to static canvas.', err);
154
+ setLeafletFailed(true);
155
+ });
156
+ }, [mapProvider]);
157
+ const handleRecenter = useCallback(() => {
158
+ setViewOffset({ x: 0, y: 0 });
159
+ }, []);
160
+ const COLORS = useMemo(() => ({
161
+ background: tokens.colors.background.base,
162
+ grid: tokens.colors.border.muted,
163
+ text: tokens.colors.text.secondary,
164
+ accent: tokens.colors.accent.primary,
165
+ land: "rgba(30, 40, 58, 0.92)",
166
+ ocean: tokens.colors.background.base,
167
+ night: "rgba(0, 10, 40, 0.35)",
168
+ equator: "rgba(88, 166, 255, 0.25)"
169
+ }), [tokens]);
170
+ const lonToX = useCallback((lon, w) => {
171
+ let normalizedLon = lon;
172
+ while (normalizedLon > 180) normalizedLon -= 360;
173
+ while (normalizedLon < -180) normalizedLon += 360;
174
+ return (normalizedLon + 180) / 360 * w;
175
+ }, []);
176
+ const latToY = useCallback((lat, h) => {
177
+ return (90 - lat) / 180 * h;
178
+ }, []);
179
+ const draw = useCallback(() => {
180
+ const canvas = canvasRef.current;
181
+ const container = containerRef.current;
182
+ if (!canvas || !container) return;
183
+ const ctx = canvas.getContext("2d");
184
+ if (!ctx) return;
185
+ const dpr = window.devicePixelRatio || 1;
186
+ const rect = container.getBoundingClientRect();
187
+ const W = rect.width;
188
+ const H = typeof height === "number" ? height : rect.height || 400;
189
+ canvas.width = W * dpr;
190
+ canvas.height = H * dpr;
191
+ canvas.style.width = `${W}px`;
192
+ canvas.style.height = `${H}px`;
193
+ ctx.scale(dpr, dpr);
194
+ ctx.fillStyle = COLORS.background;
195
+ ctx.fillRect(0, 0, W, H);
196
+ if (showTerminator) {
197
+ const terminator = calculateTerminator(/* @__PURE__ */ new Date());
198
+ ctx.fillStyle = COLORS.night;
199
+ ctx.beginPath();
200
+ ctx.moveTo(W, 0);
201
+ ctx.lineTo(W, H);
202
+ let prevRX = W;
203
+ for (let i = terminator.length - 1; i >= 0; i--) {
204
+ const x = lonToX(terminator[i].lon, W);
205
+ const y = latToY(terminator[i].lat, H);
206
+ if (Math.abs(x - prevRX) > W * 0.5 && i < terminator.length - 1) {
207
+ const edgeX = prevRX > W / 2 ? W : 0;
208
+ ctx.lineTo(edgeX, y);
209
+ ctx.closePath();
210
+ ctx.fill();
211
+ ctx.beginPath();
212
+ ctx.moveTo(W, y);
213
+ }
214
+ ctx.lineTo(x, y);
215
+ prevRX = x;
216
+ }
217
+ ctx.closePath();
218
+ ctx.fill();
219
+ const normLon = (l) => {
220
+ let r = l;
221
+ while (r > 180) r -= 360;
222
+ while (r < -180) r += 360;
223
+ return r;
224
+ };
225
+ ctx.beginPath();
226
+ ctx.moveTo(0, 0);
227
+ ctx.lineTo(0, H);
228
+ let prevLX = 0;
229
+ for (let i = terminator.length - 1; i >= 0; i--) {
230
+ const sunriseLon = normLon(terminator[i].lon - 180);
231
+ const x = lonToX(sunriseLon, W);
232
+ const y = latToY(terminator[i].lat, H);
233
+ if (Math.abs(x - prevLX) > W * 0.5 && i < terminator.length - 1) {
234
+ const edgeX = prevLX < W / 2 ? 0 : W;
235
+ ctx.lineTo(edgeX, y);
236
+ ctx.closePath();
237
+ ctx.fill();
238
+ ctx.beginPath();
239
+ ctx.moveTo(0, y);
240
+ }
241
+ ctx.lineTo(x, y);
242
+ prevLX = x;
243
+ }
244
+ ctx.closePath();
245
+ ctx.fill();
246
+ }
247
+ ctx.fillStyle = COLORS.land;
248
+ ctx.strokeStyle = "rgba(100, 120, 160, 0.25)";
249
+ ctx.lineWidth = 1;
250
+ for (const pathStr of WORLD_MAP_PATHS) {
251
+ const commands = pathStr.split(" ");
252
+ ctx.beginPath();
253
+ for (const cmd of commands) {
254
+ if (cmd.startsWith("M") || cmd.startsWith("L")) {
255
+ const coords = cmd.substring(1).split(",");
256
+ const lon = parseFloat(coords[0]);
257
+ const lat = parseFloat(coords[1]);
258
+ const x = lonToX(lon, W);
259
+ const y = latToY(lat, H);
260
+ if (cmd.startsWith("M")) ctx.moveTo(x, y);
261
+ else ctx.lineTo(x, y);
262
+ } else if (cmd === "Z") {
263
+ ctx.closePath();
264
+ }
265
+ }
266
+ ctx.fill();
267
+ ctx.stroke();
268
+ }
269
+ if (showGrid) {
270
+ ctx.strokeStyle = COLORS.grid;
271
+ ctx.lineWidth = 0.4;
272
+ for (let lon = -180; lon <= 180; lon += 30) {
273
+ const x = lonToX(lon, W);
274
+ ctx.beginPath();
275
+ ctx.moveTo(x, 0);
276
+ ctx.lineTo(x, H);
277
+ ctx.stroke();
278
+ }
279
+ for (let lat = -90; lat <= 90; lat += 30) {
280
+ const y = latToY(lat, H);
281
+ ctx.beginPath();
282
+ ctx.moveTo(0, y);
283
+ ctx.lineTo(W, y);
284
+ ctx.stroke();
285
+ }
286
+ }
287
+ if (showEquator) {
288
+ const eqY = latToY(0, H);
289
+ ctx.strokeStyle = COLORS.equator;
290
+ ctx.lineWidth = 1;
291
+ ctx.setLineDash([6, 4]);
292
+ ctx.beginPath();
293
+ ctx.moveTo(0, eqY);
294
+ ctx.lineTo(W, eqY);
295
+ ctx.stroke();
296
+ ctx.setLineDash([]);
297
+ }
298
+ for (const gs of groundStations) {
299
+ const enhanced = gs;
300
+ if (enhanced.showCoverage && enhanced.coverageRadius) {
301
+ const statusColor = STATUS_COLOR_MAP[enhanced.status || "standby"] || STATUS_COLOR_MAP.standby;
302
+ drawCoverageEllipse(ctx, gs.latitude, gs.longitude, enhanced.coverageRadius, W, H, lonToX, latToY);
303
+ ctx.fillStyle = `${statusColor}15`;
304
+ ctx.fill();
305
+ ctx.strokeStyle = `${statusColor}40`;
306
+ ctx.lineWidth = 1;
307
+ ctx.setLineDash([4, 3]);
308
+ ctx.stroke();
309
+ ctx.setLineDash([]);
310
+ }
311
+ }
312
+ for (const gs of groundStations) {
313
+ const enhanced = gs;
314
+ const x = lonToX(gs.longitude, W);
315
+ const y = latToY(gs.latitude, H);
316
+ const status = enhanced.status || "standby";
317
+ const statusColor = STATUS_COLOR_MAP[status] || STATUS_COLOR_MAP.standby;
318
+ const stationType = enhanced.type || "dish";
319
+ const iconSize = 20;
320
+ const halfIcon = iconSize / 2;
321
+ ctx.save();
322
+ ctx.translate(x, y);
323
+ ctx.beginPath();
324
+ ctx.arc(0, 0, halfIcon + 2, 0, Math.PI * 2);
325
+ ctx.fillStyle = `${statusColor}18`;
326
+ ctx.fill();
327
+ ctx.beginPath();
328
+ ctx.arc(0, 0, halfIcon, 0, Math.PI * 2);
329
+ ctx.fillStyle = "rgba(15, 23, 42, 0.85)";
330
+ ctx.fill();
331
+ ctx.strokeStyle = `${statusColor}66`;
332
+ ctx.lineWidth = 1.5;
333
+ ctx.stroke();
334
+ ctx.save();
335
+ const iconScale = iconSize / 24;
336
+ ctx.translate(-halfIcon, -halfIcon);
337
+ ctx.scale(iconScale, iconScale);
338
+ if (stationType === "dish" || stationType === "omni") {
339
+ ctx.strokeStyle = statusColor;
340
+ ctx.fillStyle = statusColor;
341
+ ctx.lineWidth = 2 / iconScale;
342
+ ctx.beginPath();
343
+ ctx.arc(12, 12, 10, Math.PI * 1.25, Math.PI * 1.75);
344
+ ctx.stroke();
345
+ ctx.beginPath();
346
+ ctx.arc(12, 12, 6.5, Math.PI * 1.2, Math.PI * 1.8);
347
+ ctx.stroke();
348
+ ctx.beginPath();
349
+ ctx.arc(12, 12, 3, Math.PI * 1.15, Math.PI * 1.85);
350
+ ctx.stroke();
351
+ ctx.beginPath();
352
+ ctx.arc(12, 12, 1.5, 0, Math.PI * 2);
353
+ ctx.fill();
354
+ ctx.lineWidth = 1.5 / iconScale;
355
+ ctx.beginPath();
356
+ ctx.moveTo(12, 14);
357
+ ctx.lineTo(12, 20);
358
+ ctx.stroke();
359
+ ctx.beginPath();
360
+ ctx.moveTo(8, 20);
361
+ ctx.lineTo(16, 20);
362
+ ctx.stroke();
363
+ } else if (stationType === "phased-array") {
364
+ ctx.strokeStyle = statusColor;
365
+ ctx.fillStyle = statusColor;
366
+ ctx.lineWidth = 1.5 / iconScale;
367
+ ctx.strokeRect(5, 4, 14, 12);
368
+ for (let gx = 8; gx <= 16; gx += 4) {
369
+ ctx.beginPath();
370
+ ctx.moveTo(gx, 4);
371
+ ctx.lineTo(gx, 16);
372
+ ctx.stroke();
373
+ }
374
+ for (let gy = 8; gy <= 12; gy += 4) {
375
+ ctx.beginPath();
376
+ ctx.moveTo(5, gy);
377
+ ctx.lineTo(19, gy);
378
+ ctx.stroke();
379
+ }
380
+ ctx.beginPath();
381
+ ctx.moveTo(12, 16);
382
+ ctx.lineTo(12, 21);
383
+ ctx.stroke();
384
+ ctx.beginPath();
385
+ ctx.moveTo(8, 21);
386
+ ctx.lineTo(16, 21);
387
+ ctx.stroke();
388
+ } else {
389
+ ctx.strokeStyle = statusColor;
390
+ ctx.fillStyle = statusColor;
391
+ ctx.lineWidth = 2 / iconScale;
392
+ ctx.beginPath();
393
+ ctx.arc(10, 12, 7, Math.PI * 0.8, Math.PI * 1.7);
394
+ ctx.stroke();
395
+ ctx.lineWidth = 1.5 / iconScale;
396
+ ctx.beginPath();
397
+ ctx.moveTo(10, 12);
398
+ ctx.lineTo(16, 6);
399
+ ctx.stroke();
400
+ ctx.lineWidth = 1.2 / iconScale;
401
+ ctx.beginPath();
402
+ ctx.arc(17, 5, 2.5, Math.PI * 1.2, Math.PI * 1.7);
403
+ ctx.stroke();
404
+ ctx.beginPath();
405
+ ctx.arc(17, 5, 4.5, Math.PI * 1.15, Math.PI * 1.75);
406
+ ctx.stroke();
407
+ ctx.lineWidth = 1.5 / iconScale;
408
+ ctx.beginPath();
409
+ ctx.moveTo(10, 14);
410
+ ctx.lineTo(10, 20);
411
+ ctx.stroke();
412
+ ctx.beginPath();
413
+ ctx.moveTo(6, 20);
414
+ ctx.lineTo(14, 20);
415
+ ctx.stroke();
416
+ }
417
+ ctx.restore();
418
+ const badgeX = -halfIcon + 1;
419
+ const badgeY = -halfIcon + 1;
420
+ const badgeSize = 7;
421
+ ctx.beginPath();
422
+ ctx.arc(badgeX, badgeY, badgeSize / 2 + 2, 0, Math.PI * 2);
423
+ ctx.fillStyle = "rgba(15, 23, 42, 0.9)";
424
+ ctx.fill();
425
+ ctx.fillStyle = statusColor;
426
+ ctx.strokeStyle = statusColor;
427
+ ctx.lineWidth = 1;
428
+ if (status === "normal") {
429
+ ctx.beginPath();
430
+ ctx.arc(badgeX, badgeY, badgeSize / 2, 0, Math.PI * 2);
431
+ ctx.fill();
432
+ } else if (status === "standby") {
433
+ ctx.beginPath();
434
+ ctx.arc(badgeX, badgeY, badgeSize / 2 - 0.5, 0, Math.PI * 2);
435
+ ctx.lineWidth = 2;
436
+ ctx.stroke();
437
+ } else if (status === "caution") {
438
+ const hs = badgeSize / 2;
439
+ ctx.fillRect(badgeX - hs, badgeY - hs, badgeSize, badgeSize);
440
+ } else if (status === "serious") {
441
+ const hs = badgeSize / 2;
442
+ ctx.beginPath();
443
+ ctx.moveTo(badgeX, badgeY - hs);
444
+ ctx.lineTo(badgeX + hs, badgeY);
445
+ ctx.lineTo(badgeX, badgeY + hs);
446
+ ctx.lineTo(badgeX - hs, badgeY);
447
+ ctx.closePath();
448
+ ctx.fill();
449
+ } else if (status === "critical") {
450
+ const hs = badgeSize / 2;
451
+ ctx.beginPath();
452
+ ctx.moveTo(badgeX, badgeY + hs);
453
+ ctx.lineTo(badgeX + hs, badgeY - hs);
454
+ ctx.lineTo(badgeX - hs, badgeY - hs);
455
+ ctx.closePath();
456
+ ctx.fill();
457
+ } else {
458
+ ctx.beginPath();
459
+ ctx.arc(badgeX, badgeY, badgeSize / 3, 0, Math.PI * 2);
460
+ ctx.fill();
461
+ }
462
+ ctx.restore();
463
+ ctx.fillStyle = COLORS.text;
464
+ ctx.font = '9px "Inter", system-ui, sans-serif';
465
+ ctx.textAlign = "center";
466
+ ctx.fillText(gs.name.length > 14 ? gs.name.slice(0, 14) + "…" : gs.name, x, y + halfIcon + 12);
467
+ }
468
+ allSatellites.forEach((sat, satIdx) => {
469
+ const track = sat.groundTrack;
470
+ if (!track || track.length === 0) return;
471
+ const trackColor = sat.color || DEFAULT_TRACK_COLORS[satIdx % DEFAULT_TRACK_COLORS.length];
472
+ const futureIdx = sat.futureTrackIndex ?? track.length;
473
+ ctx.strokeStyle = trackColor;
474
+ ctx.lineWidth = 2;
475
+ ctx.lineCap = "round";
476
+ ctx.lineJoin = "round";
477
+ ctx.setLineDash([]);
478
+ ctx.beginPath();
479
+ let prevX = lonToX(track[0].longitude, W);
480
+ let prevY = latToY(track[0].latitude, H);
481
+ ctx.moveTo(prevX, prevY);
482
+ for (let i = 1; i < Math.min(futureIdx, track.length); i++) {
483
+ const x = lonToX(track[i].longitude, W);
484
+ const y = latToY(track[i].latitude, H);
485
+ const crossesDateLine = Math.abs(x - prevX) > W / 2;
486
+ if (crossesDateLine) {
487
+ ctx.stroke();
488
+ ctx.beginPath();
489
+ ctx.moveTo(x, y);
490
+ } else {
491
+ ctx.lineTo(x, y);
492
+ }
493
+ prevX = x;
494
+ prevY = y;
495
+ }
496
+ ctx.stroke();
497
+ if (futureIdx < track.length) {
498
+ ctx.strokeStyle = `${trackColor}88`;
499
+ ctx.lineWidth = 1.5;
500
+ ctx.setLineDash([6, 4]);
501
+ ctx.beginPath();
502
+ ctx.moveTo(lonToX(track[futureIdx].longitude, W), latToY(track[futureIdx].latitude, H));
503
+ let fpx = lonToX(track[futureIdx].longitude, W);
504
+ for (let i = futureIdx + 1; i < track.length; i++) {
505
+ const x = lonToX(track[i].longitude, W);
506
+ const y = latToY(track[i].latitude, H);
507
+ if (Math.abs(x - fpx) > W / 2) {
508
+ ctx.stroke();
509
+ ctx.beginPath();
510
+ ctx.moveTo(x, y);
511
+ } else {
512
+ ctx.lineTo(x, y);
513
+ }
514
+ fpx = x;
515
+ }
516
+ ctx.stroke();
517
+ ctx.setLineDash([]);
518
+ }
519
+ if (sat.accessMask && sat.accessMask.some(Boolean)) {
520
+ ctx.strokeStyle = STATUS_COLOR_MAP.normal;
521
+ ctx.lineWidth = 3;
522
+ ctx.setLineDash([]);
523
+ ctx.beginPath();
524
+ let drawing = false;
525
+ let apx = lonToX(track[0].longitude, W);
526
+ for (let i = 0; i < track.length; i++) {
527
+ const x = lonToX(track[i].longitude, W);
528
+ const y = latToY(track[i].latitude, H);
529
+ const active = sat.accessMask[i];
530
+ const crossesDateLine = i > 0 && Math.abs(x - apx) > W / 2;
531
+ if (active && !crossesDateLine) {
532
+ if (!drawing) {
533
+ ctx.moveTo(x, y);
534
+ drawing = true;
535
+ } else ctx.lineTo(x, y);
536
+ } else {
537
+ if (drawing) {
538
+ ctx.stroke();
539
+ ctx.beginPath();
540
+ drawing = false;
541
+ }
542
+ }
543
+ apx = x;
544
+ }
545
+ if (drawing) ctx.stroke();
546
+ }
547
+ if (sat.passMarkers) {
548
+ for (const marker of sat.passMarkers) {
549
+ const mx = lonToX(marker.longitude, W);
550
+ const my = latToY(marker.latitude, H);
551
+ const markerColor = marker.type === "aos" ? STATUS_COLOR_MAP.normal : STATUS_COLOR_MAP.critical;
552
+ ctx.save();
553
+ ctx.translate(mx, my);
554
+ ctx.beginPath();
555
+ if (marker.type === "aos") {
556
+ ctx.moveTo(0, -6);
557
+ ctx.lineTo(4, 2);
558
+ ctx.lineTo(-4, 2);
559
+ } else {
560
+ ctx.moveTo(0, 6);
561
+ ctx.lineTo(4, -2);
562
+ ctx.lineTo(-4, -2);
563
+ }
564
+ ctx.closePath();
565
+ ctx.fillStyle = markerColor;
566
+ ctx.fill();
567
+ ctx.restore();
568
+ if (marker.label) {
569
+ ctx.fillStyle = markerColor;
570
+ ctx.font = '8px "Inter", system-ui, sans-serif';
571
+ ctx.textAlign = "center";
572
+ ctx.fillText(marker.label, mx, marker.type === "aos" ? my - 9 : my + 13);
573
+ }
574
+ }
575
+ }
576
+ if (sat.showFootprint && sat.footprintRadius) {
577
+ const lastPt = futureIdx > 0 ? track[Math.min(futureIdx - 1, track.length - 1)] : track[track.length - 1];
578
+ drawCoverageEllipse(ctx, lastPt.latitude, lastPt.longitude, sat.footprintRadius, W, H, lonToX, latToY);
579
+ ctx.fillStyle = `${trackColor}12`;
580
+ ctx.fill();
581
+ ctx.strokeStyle = `${trackColor}50`;
582
+ ctx.lineWidth = 1;
583
+ ctx.setLineDash([3, 3]);
584
+ ctx.stroke();
585
+ ctx.setLineDash([]);
586
+ }
587
+ const currentIdx = futureIdx > 0 ? Math.min(futureIdx - 1, track.length - 1) : track.length - 1;
588
+ const current = track[currentIdx];
589
+ const cx = lonToX(current.longitude, W);
590
+ const cy = latToY(current.latitude, H);
591
+ const satStatus = sat.status || "normal";
592
+ const statusColor = STATUS_COLOR_MAP[satStatus] || STATUS_COLOR_MAP.normal;
593
+ const satIconSize = 22;
594
+ const satHalf = satIconSize / 2;
595
+ ctx.beginPath();
596
+ ctx.arc(cx, cy, satHalf + 6, 0, Math.PI * 2);
597
+ ctx.fillStyle = `${statusColor}12`;
598
+ ctx.fill();
599
+ ctx.beginPath();
600
+ ctx.arc(cx, cy, satHalf + 3, 0, Math.PI * 2);
601
+ ctx.fillStyle = `${statusColor}20`;
602
+ ctx.fill();
603
+ ctx.save();
604
+ ctx.translate(cx, cy);
605
+ ctx.beginPath();
606
+ ctx.arc(0, 0, satHalf, 0, Math.PI * 2);
607
+ ctx.fillStyle = "rgba(15, 23, 42, 0.88)";
608
+ ctx.fill();
609
+ ctx.strokeStyle = `${statusColor}88`;
610
+ ctx.lineWidth = 1.5;
611
+ ctx.stroke();
612
+ ctx.fillStyle = statusColor;
613
+ const bw = 5, bh = 3.5;
614
+ ctx.beginPath();
615
+ ctx.moveTo(-bw / 2 + 0.5, -bh / 2);
616
+ ctx.lineTo(bw / 2 - 0.5, -bh / 2);
617
+ ctx.arcTo(bw / 2, -bh / 2, bw / 2, -bh / 2 + 0.5, 0.5);
618
+ ctx.lineTo(bw / 2, bh / 2 - 0.5);
619
+ ctx.arcTo(bw / 2, bh / 2, bw / 2 - 0.5, bh / 2, 0.5);
620
+ ctx.lineTo(-bw / 2 + 0.5, bh / 2);
621
+ ctx.arcTo(-bw / 2, bh / 2, -bw / 2, bh / 2 - 0.5, 0.5);
622
+ ctx.lineTo(-bw / 2, -bh / 2 + 0.5);
623
+ ctx.arcTo(-bw / 2, -bh / 2, -bw / 2 + 0.5, -bh / 2, 0.5);
624
+ ctx.closePath();
625
+ ctx.fill();
626
+ ctx.fillStyle = `${statusColor}BB`;
627
+ ctx.fillRect(-satHalf + 2, -2, 5, 4);
628
+ ctx.strokeStyle = `${statusColor}55`;
629
+ ctx.lineWidth = 0.5;
630
+ ctx.beginPath();
631
+ ctx.moveTo(-satHalf + 4.5, -2);
632
+ ctx.lineTo(-satHalf + 4.5, 2);
633
+ ctx.stroke();
634
+ ctx.fillStyle = `${statusColor}BB`;
635
+ ctx.fillRect(satHalf - 7, -2, 5, 4);
636
+ ctx.strokeStyle = `${statusColor}55`;
637
+ ctx.beginPath();
638
+ ctx.moveTo(satHalf - 4.5, -2);
639
+ ctx.lineTo(satHalf - 4.5, 2);
640
+ ctx.stroke();
641
+ ctx.strokeStyle = statusColor;
642
+ ctx.lineWidth = 1;
643
+ ctx.beginPath();
644
+ ctx.moveTo(-bw / 2, 0);
645
+ ctx.lineTo(-satHalf + 7, 0);
646
+ ctx.moveTo(bw / 2, 0);
647
+ ctx.lineTo(satHalf - 7, 0);
648
+ ctx.stroke();
649
+ const satBadgeX = -satHalf + 2;
650
+ const satBadgeY = -satHalf + 2;
651
+ const satBadgeSize = 7;
652
+ ctx.beginPath();
653
+ ctx.arc(satBadgeX, satBadgeY, satBadgeSize / 2 + 2, 0, Math.PI * 2);
654
+ ctx.fillStyle = "rgba(15, 23, 42, 0.9)";
655
+ ctx.fill();
656
+ ctx.fillStyle = statusColor;
657
+ ctx.strokeStyle = statusColor;
658
+ ctx.lineWidth = 1;
659
+ if (satStatus === "normal") {
660
+ ctx.beginPath();
661
+ ctx.arc(satBadgeX, satBadgeY, satBadgeSize / 2, 0, Math.PI * 2);
662
+ ctx.fill();
663
+ } else if (satStatus === "standby") {
664
+ ctx.beginPath();
665
+ ctx.arc(satBadgeX, satBadgeY, satBadgeSize / 2 - 0.5, 0, Math.PI * 2);
666
+ ctx.lineWidth = 2;
667
+ ctx.stroke();
668
+ } else if (satStatus === "caution") {
669
+ const hs = satBadgeSize / 2;
670
+ ctx.fillRect(satBadgeX - hs, satBadgeY - hs, satBadgeSize, satBadgeSize);
671
+ } else if (satStatus === "serious") {
672
+ const hs = satBadgeSize / 2;
673
+ ctx.beginPath();
674
+ ctx.moveTo(satBadgeX, satBadgeY - hs);
675
+ ctx.lineTo(satBadgeX + hs, satBadgeY);
676
+ ctx.lineTo(satBadgeX, satBadgeY + hs);
677
+ ctx.lineTo(satBadgeX - hs, satBadgeY);
678
+ ctx.closePath();
679
+ ctx.fill();
680
+ } else if (satStatus === "critical") {
681
+ const hs = satBadgeSize / 2;
682
+ ctx.beginPath();
683
+ ctx.moveTo(satBadgeX, satBadgeY + hs);
684
+ ctx.lineTo(satBadgeX + hs, satBadgeY - hs);
685
+ ctx.lineTo(satBadgeX - hs, satBadgeY - hs);
686
+ ctx.closePath();
687
+ ctx.fill();
688
+ } else {
689
+ ctx.beginPath();
690
+ ctx.arc(satBadgeX, satBadgeY, satBadgeSize / 3, 0, Math.PI * 2);
691
+ ctx.fill();
692
+ }
693
+ ctx.restore();
694
+ ctx.fillStyle = "#fff";
695
+ ctx.font = 'bold 10px "Inter", system-ui, sans-serif';
696
+ ctx.textAlign = "center";
697
+ ctx.fillText(sat.name, cx, cy - satHalf - 6);
698
+ });
699
+ if (showLegend && (allSatellites.length > 0 || groundStations.length > 0)) {
700
+ const legendX = 10;
701
+ const legendY = 10;
702
+ const lineHeight = 14;
703
+ const items = [];
704
+ allSatellites.forEach((sat, idx) => {
705
+ const c = sat.color || DEFAULT_TRACK_COLORS[idx % DEFAULT_TRACK_COLORS.length];
706
+ items.push({ color: c, label: sat.name });
707
+ });
708
+ if (groundStations.length > 0) {
709
+ items.push({ color: STATUS_COLOR_MAP.standby, label: `${groundStations.length} Ground Station${groundStations.length > 1 ? "s" : ""}` });
710
+ }
711
+ const maxLabelWidth = Math.max(...items.map((item) => ctx.measureText(item.label).width)) + 28;
712
+ const legendH = items.length * lineHeight + 10;
713
+ ctx.fillStyle = "rgba(0, 0, 0, 0.6)";
714
+ ctx.strokeStyle = "rgba(100, 116, 139, 0.3)";
715
+ ctx.lineWidth = 1;
716
+ const r = 4;
717
+ ctx.beginPath();
718
+ ctx.moveTo(legendX + r, legendY);
719
+ ctx.lineTo(legendX + maxLabelWidth - r, legendY);
720
+ ctx.arcTo(legendX + maxLabelWidth, legendY, legendX + maxLabelWidth, legendY + r, r);
721
+ ctx.lineTo(legendX + maxLabelWidth, legendY + legendH - r);
722
+ ctx.arcTo(legendX + maxLabelWidth, legendY + legendH, legendX + maxLabelWidth - r, legendY + legendH, r);
723
+ ctx.lineTo(legendX + r, legendY + legendH);
724
+ ctx.arcTo(legendX, legendY + legendH, legendX, legendY + legendH - r, r);
725
+ ctx.lineTo(legendX, legendY + r);
726
+ ctx.arcTo(legendX, legendY, legendX + r, legendY, r);
727
+ ctx.closePath();
728
+ ctx.fill();
729
+ ctx.stroke();
730
+ items.forEach((item, i) => {
731
+ const iy = legendY + 8 + i * lineHeight;
732
+ ctx.fillStyle = item.color;
733
+ ctx.beginPath();
734
+ ctx.arc(legendX + 10, iy + 3, 4, 0, Math.PI * 2);
735
+ ctx.fill();
736
+ ctx.fillStyle = "rgba(255, 255, 255, 0.85)";
737
+ ctx.font = '10px "Inter", system-ui, sans-serif';
738
+ ctx.textAlign = "left";
739
+ ctx.fillText(item.label, legendX + 20, iy + 7);
740
+ });
741
+ }
742
+ if (allSatellites.length === 0 && groundStations.length === 0) {
743
+ ctx.fillStyle = COLORS.text;
744
+ ctx.font = '12px "Inter", system-ui, sans-serif';
745
+ ctx.textAlign = "center";
746
+ ctx.fillText(emptyMessage, W / 2, H / 2);
747
+ }
748
+ }, [allSatellites, groundStations, height, showTerminator, showGrid, showLegend, showEquator, lonToX, latToY, COLORS, emptyMessage]);
749
+ const handleMouseMove = useCallback((e) => {
750
+ const canvas = canvasRef.current;
751
+ if (!canvas) return;
752
+ const rect = canvas.getBoundingClientRect();
753
+ const mx = e.clientX - rect.left;
754
+ const my = e.clientY - rect.top;
755
+ const W = rect.width;
756
+ const H = typeof height === "number" ? height : rect.height;
757
+ for (const sat of allSatellites) {
758
+ if (!sat.groundTrack.length) continue;
759
+ const futureIdx = sat.futureTrackIndex ?? sat.groundTrack.length;
760
+ const currentIdx = futureIdx > 0 ? Math.min(futureIdx - 1, sat.groundTrack.length - 1) : sat.groundTrack.length - 1;
761
+ const lastPt = sat.groundTrack[currentIdx];
762
+ const sx = lonToX(lastPt.longitude, W);
763
+ const sy = latToY(lastPt.latitude, H);
764
+ const dist = Math.sqrt((mx - sx) ** 2 + (my - sy) ** 2);
765
+ if (dist < 18) {
766
+ const satStatus = sat.status || "normal";
767
+ setTooltip({
768
+ x: e.clientX - rect.left + 15,
769
+ y: e.clientY - rect.top - 10,
770
+ type: "satellite",
771
+ name: sat.name,
772
+ status: satStatus,
773
+ statusColor: STATUS_COLOR_MAP[satStatus] || STATUS_COLOR_MAP.normal,
774
+ lat: lastPt.latitude,
775
+ lon: lastPt.longitude,
776
+ alt: lastPt.altitude,
777
+ trackColor: sat.color || DEFAULT_TRACK_COLORS[allSatellites.indexOf(sat) % DEFAULT_TRACK_COLORS.length],
778
+ hasFootprint: sat.showFootprint,
779
+ futurePoints: sat.groundTrack.length - futureIdx,
780
+ pastPoints: futureIdx
781
+ });
782
+ return;
783
+ }
784
+ }
785
+ for (const gs of groundStations) {
786
+ const gx = lonToX(gs.longitude, W);
787
+ const gy = latToY(gs.latitude, H);
788
+ const dist = Math.sqrt((mx - gx) ** 2 + (my - gy) ** 2);
789
+ if (dist < 16) {
790
+ const enhanced = gs;
791
+ const gsStatus = enhanced.status || "standby";
792
+ setTooltip({
793
+ x: e.clientX - rect.left + 15,
794
+ y: e.clientY - rect.top - 10,
795
+ type: "station",
796
+ name: gs.name,
797
+ status: gsStatus,
798
+ statusColor: STATUS_COLOR_MAP[gsStatus] || STATUS_COLOR_MAP.standby,
799
+ lat: gs.latitude,
800
+ lon: gs.longitude,
801
+ stationType: enhanced.type || "dish",
802
+ network: "network" in gs && gs.network ? String(gs.network) : void 0,
803
+ coverageRadius: enhanced.coverageRadius
804
+ });
805
+ return;
806
+ }
807
+ }
808
+ setTooltip(null);
809
+ }, [allSatellites, groundStations, height, lonToX, latToY]);
810
+ const handleClick = useCallback((e) => {
811
+ const canvas = canvasRef.current;
812
+ if (!canvas) return;
813
+ const rect = canvas.getBoundingClientRect();
814
+ const mx = e.clientX - rect.left;
815
+ const my = e.clientY - rect.top;
816
+ const W = rect.width;
817
+ const H = typeof height === "number" ? height : rect.height;
818
+ for (const sat of allSatellites) {
819
+ if (!sat.groundTrack.length) continue;
820
+ const futureIdx = sat.futureTrackIndex ?? sat.groundTrack.length;
821
+ const currentIdx = futureIdx > 0 ? Math.min(futureIdx - 1, sat.groundTrack.length - 1) : sat.groundTrack.length - 1;
822
+ const currentPt = sat.groundTrack[currentIdx];
823
+ const sx = lonToX(currentPt.longitude, W);
824
+ const sy = latToY(currentPt.latitude, H);
825
+ if (Math.sqrt((mx - sx) ** 2 + (my - sy) ** 2) < 15) {
826
+ onSatelliteClick == null ? void 0 : onSatelliteClick(sat.id);
827
+ return;
828
+ }
829
+ }
830
+ for (const gs of groundStations) {
831
+ const gx = lonToX(gs.longitude, W);
832
+ const gy = latToY(gs.latitude, H);
833
+ if (Math.sqrt((mx - gx) ** 2 + (my - gy) ** 2) < 12) {
834
+ onStationClick == null ? void 0 : onStationClick("id" in gs ? gs.id : gs.name);
835
+ return;
836
+ }
837
+ }
838
+ }, [allSatellites, groundStations, height, lonToX, latToY, onSatelliteClick, onStationClick]);
839
+ useEffect(() => {
840
+ draw();
841
+ window.addEventListener("resize", draw);
842
+ return () => window.removeEventListener("resize", draw);
843
+ }, [draw]);
844
+ const resolvedMinHeightForLeaflet = minHeight || (typeof height === "number" ? `${height}px` : "400px");
845
+ if (mapProvider === "leaflet") {
846
+ if (LeafletMap) {
847
+ return /* @__PURE__ */ jsx(
848
+ "div",
849
+ {
850
+ role: "img",
851
+ "aria-label": allSatellites.length > 0 || groundStations.length > 0 ? "Ground track map showing satellite tracks and ground stations" : "Ground track map",
852
+ style: {
853
+ display: "block",
854
+ width: width ?? "100%",
855
+ height: typeof height === "string" ? height : void 0,
856
+ minHeight: resolvedMinHeightForLeaflet
857
+ },
858
+ children: /* @__PURE__ */ jsx(
859
+ LeafletMap,
860
+ {
861
+ allSatellites,
862
+ groundStations,
863
+ showTerminator,
864
+ showGrid,
865
+ showLegend,
866
+ showEquator,
867
+ showRecenterButton,
868
+ defaultCenter: leafletDefaultCenter,
869
+ defaultZoom: leafletDefaultZoom,
870
+ height,
871
+ width,
872
+ minHeight,
873
+ emptyMessage,
874
+ tileUrl,
875
+ className,
876
+ onSatelliteClick,
877
+ onStationClick
878
+ }
879
+ )
880
+ }
881
+ );
882
+ }
883
+ if (!leafletFailed) {
884
+ return /* @__PURE__ */ jsx(
885
+ "div",
886
+ {
887
+ className: `zendir-ground-track-map ${className}`,
888
+ style: {
889
+ width,
890
+ height: typeof height === "string" ? height : void 0,
891
+ minHeight: resolvedMinHeightForLeaflet,
892
+ backgroundColor: tokens.colors.background.base,
893
+ borderRadius: 8,
894
+ display: "flex",
895
+ alignItems: "center",
896
+ justifyContent: "center"
897
+ },
898
+ children: /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.secondary, fontSize: 14 }, children: "Loading map…" })
899
+ }
900
+ );
901
+ }
902
+ }
903
+ const resolvedMinHeight = minHeight || (typeof height === "number" ? `${height}px` : "400px");
904
+ if (isLoading) {
905
+ return /* @__PURE__ */ jsx(
906
+ "div",
907
+ {
908
+ className: `zendir-ground-track-map ${className}`,
909
+ style: {
910
+ width,
911
+ minHeight: resolvedMinHeight,
912
+ backgroundColor: COLORS.background,
913
+ borderRadius: "8px",
914
+ display: "flex",
915
+ alignItems: "center",
916
+ justifyContent: "center"
917
+ },
918
+ children: /* @__PURE__ */ jsx("span", { style: { color: COLORS.text, fontSize: "14px", letterSpacing: "1px" }, children: "Loading…" })
919
+ }
920
+ );
921
+ }
922
+ return /* @__PURE__ */ jsxs(
923
+ "div",
924
+ {
925
+ ref: containerRef,
926
+ role: "img",
927
+ "aria-label": allSatellites.length > 0 || groundStations.length > 0 ? "Ground track map showing satellite tracks and ground stations" : "Ground track map",
928
+ className: `zendir-ground-track-map ${className}`,
929
+ style: { width, height: typeof height === "string" ? height : void 0, minHeight: resolvedMinHeight, backgroundColor: COLORS.background, borderRadius: "8px", overflow: "hidden", position: "relative" },
930
+ "data-map-backend": "canvas",
931
+ children: [
932
+ mapProvider === "leaflet" && leafletFailed && /* @__PURE__ */ jsxs(
933
+ "div",
934
+ {
935
+ style: {
936
+ position: "absolute",
937
+ bottom: 8,
938
+ left: 8,
939
+ zIndex: 100,
940
+ padding: "4px 8px",
941
+ background: "rgba(0,0,0,0.75)",
942
+ color: "#fce83a",
943
+ fontSize: 11,
944
+ borderRadius: 4
945
+ },
946
+ children: [
947
+ "Static view (install ",
948
+ /* @__PURE__ */ jsx("code", { style: { fontFamily: "monospace" }, children: "leaflet" }),
949
+ " for zoom/pan)"
950
+ ]
951
+ }
952
+ ),
953
+ showRecenterButton && /* @__PURE__ */ jsx(
954
+ "button",
955
+ {
956
+ type: "button",
957
+ onClick: handleRecenter,
958
+ title: "Recenter Map",
959
+ "aria-label": "Recenter map",
960
+ style: {
961
+ position: "absolute",
962
+ top: "8px",
963
+ right: "8px",
964
+ zIndex: 20,
965
+ background: "rgba(30, 41, 59, 0.85)",
966
+ border: "1px solid rgba(100, 116, 139, 0.4)",
967
+ borderRadius: "4px",
968
+ color: "#fff",
969
+ cursor: "pointer",
970
+ padding: "4px 8px",
971
+ fontSize: "12px",
972
+ lineHeight: "1",
973
+ display: "flex",
974
+ alignItems: "center",
975
+ gap: "4px"
976
+ },
977
+ children: /* @__PURE__ */ jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
978
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" }),
979
+ /* @__PURE__ */ jsx("path", { d: "M12 2v4M12 18v4M2 12h4M18 12h4" })
980
+ ] })
981
+ }
982
+ ),
983
+ /* @__PURE__ */ jsx(
984
+ "canvas",
985
+ {
986
+ ref: canvasRef,
987
+ style: { display: "block", cursor: tooltip ? "pointer" : "default" },
988
+ onMouseMove: handleMouseMove,
989
+ onMouseLeave: () => setTooltip(null),
990
+ onClick: handleClick
991
+ }
992
+ ),
993
+ tooltip && /* @__PURE__ */ jsxs(
994
+ "div",
995
+ {
996
+ style: {
997
+ position: "absolute",
998
+ left: tooltip.x,
999
+ top: tooltip.y,
1000
+ background: "rgba(15, 23, 42, 0.95)",
1001
+ backdropFilter: "blur(8px)",
1002
+ border: `1px solid ${tooltip.statusColor}40`,
1003
+ borderRadius: "8px",
1004
+ padding: 0,
1005
+ pointerEvents: "none",
1006
+ zIndex: 10,
1007
+ color: "rgba(255, 255, 255, 0.9)",
1008
+ fontSize: "11px",
1009
+ fontFamily: '"Inter", system-ui, sans-serif',
1010
+ lineHeight: "1.5",
1011
+ boxShadow: `0 4px 16px rgba(0, 0, 0, 0.5), 0 0 12px ${tooltip.statusColor}15`,
1012
+ minWidth: 180,
1013
+ overflow: "hidden"
1014
+ },
1015
+ children: [
1016
+ /* @__PURE__ */ jsxs("div", { style: {
1017
+ padding: "6px 10px",
1018
+ borderBottom: `1px solid ${tooltip.statusColor}25`,
1019
+ background: `${tooltip.statusColor}10`,
1020
+ display: "flex",
1021
+ alignItems: "center",
1022
+ gap: 6
1023
+ }, children: [
1024
+ /* @__PURE__ */ jsx("span", { style: {
1025
+ width: 8,
1026
+ height: 8,
1027
+ borderRadius: tooltip.status === "caution" ? 1 : "50%",
1028
+ background: tooltip.statusColor,
1029
+ display: "inline-block",
1030
+ flexShrink: 0,
1031
+ boxShadow: `0 0 4px ${tooltip.statusColor}88`
1032
+ } }),
1033
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 600, fontSize: 12 }, children: tooltip.name }),
1034
+ /* @__PURE__ */ jsx("span", { style: {
1035
+ marginLeft: "auto",
1036
+ fontSize: 9,
1037
+ fontWeight: 600,
1038
+ textTransform: "uppercase",
1039
+ color: tooltip.statusColor,
1040
+ letterSpacing: "0.5px"
1041
+ }, children: tooltip.status })
1042
+ ] }),
1043
+ /* @__PURE__ */ jsxs("div", { style: { padding: "6px 10px", display: "flex", flexDirection: "column", gap: 3 }, children: [
1044
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 2 }, children: [
1045
+ /* @__PURE__ */ jsx("span", { style: {
1046
+ fontSize: 9,
1047
+ fontWeight: 600,
1048
+ padding: "1px 5px",
1049
+ borderRadius: 3,
1050
+ textTransform: "uppercase",
1051
+ letterSpacing: "0.3px",
1052
+ background: tooltip.type === "satellite" ? "rgba(45, 204, 255, 0.15)" : "rgba(86, 240, 0, 0.15)",
1053
+ color: tooltip.type === "satellite" ? "#2dccff" : "#56f000"
1054
+ }, children: tooltip.type === "satellite" ? /* @__PURE__ */ jsxs(Fragment, { children: [
1055
+ /* @__PURE__ */ jsx(AstroIcon, { name: "satellite", size: "extra-small", label: "Satellite", style: { marginRight: 4, verticalAlign: "middle" } }),
1056
+ "Satellite"
1057
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1058
+ /* @__PURE__ */ jsx(AstroIcon, { name: "antenna", size: "extra-small", label: tooltip.stationType || "Ground station", style: { marginRight: 4, verticalAlign: "middle" } }),
1059
+ tooltip.stationType || "dish"
1060
+ ] }) }),
1061
+ tooltip.network && /* @__PURE__ */ jsx("span", { style: {
1062
+ fontSize: 9,
1063
+ padding: "1px 5px",
1064
+ borderRadius: 3,
1065
+ background: "rgba(157, 112, 255, 0.15)",
1066
+ color: "#9D70FF"
1067
+ }, children: tooltip.network })
1068
+ ] }),
1069
+ /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "52px 1fr", gap: "2px 8px", fontSize: 10 }, children: [
1070
+ /* @__PURE__ */ jsx("span", { style: { color: "rgba(255,255,255,0.5)" }, children: "Lat" }),
1071
+ /* @__PURE__ */ jsxs("span", { style: { fontFamily: '"Roboto Mono", monospace', fontWeight: 500 }, children: [
1072
+ tooltip.lat >= 0 ? "+" : "",
1073
+ tooltip.lat.toFixed(4),
1074
+ "°"
1075
+ ] }),
1076
+ /* @__PURE__ */ jsx("span", { style: { color: "rgba(255,255,255,0.5)" }, children: "Lon" }),
1077
+ /* @__PURE__ */ jsxs("span", { style: { fontFamily: '"Roboto Mono", monospace', fontWeight: 500 }, children: [
1078
+ tooltip.lon >= 0 ? "+" : "",
1079
+ tooltip.lon.toFixed(4),
1080
+ "°"
1081
+ ] }),
1082
+ tooltip.alt !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1083
+ /* @__PURE__ */ jsx("span", { style: { color: "rgba(255,255,255,0.5)" }, children: "Altitude" }),
1084
+ /* @__PURE__ */ jsxs("span", { style: { fontFamily: '"Roboto Mono", monospace', fontWeight: 500 }, children: [
1085
+ tooltip.alt.toFixed(1),
1086
+ " km"
1087
+ ] })
1088
+ ] }),
1089
+ tooltip.coverageRadius !== void 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
1090
+ /* @__PURE__ */ jsx("span", { style: { color: "rgba(255,255,255,0.5)" }, children: "Coverage" }),
1091
+ /* @__PURE__ */ jsxs("span", { style: { fontFamily: '"Roboto Mono", monospace', fontWeight: 500 }, children: [
1092
+ tooltip.coverageRadius.toFixed(1),
1093
+ "° radius"
1094
+ ] })
1095
+ ] })
1096
+ ] }),
1097
+ tooltip.type === "satellite" && (tooltip.pastPoints !== void 0 || tooltip.futurePoints !== void 0) && /* @__PURE__ */ jsxs("div", { style: { marginTop: 3, paddingTop: 3, borderTop: "1px solid rgba(255,255,255,0.08)", display: "flex", gap: 10, fontSize: 9 }, children: [
1098
+ tooltip.pastPoints !== void 0 && /* @__PURE__ */ jsxs("span", { children: [
1099
+ /* @__PURE__ */ jsx("span", { style: { color: tooltip.trackColor }, children: "━" }),
1100
+ " ",
1101
+ tooltip.pastPoints,
1102
+ " past pts"
1103
+ ] }),
1104
+ tooltip.futurePoints !== void 0 && tooltip.futurePoints > 0 && /* @__PURE__ */ jsxs("span", { children: [
1105
+ /* @__PURE__ */ jsx("span", { style: { color: `${tooltip.trackColor}88` }, children: "╌" }),
1106
+ " ",
1107
+ tooltip.futurePoints,
1108
+ " predicted"
1109
+ ] }),
1110
+ tooltip.hasFootprint && /* @__PURE__ */ jsx("span", { style: { color: "#9D70FF" }, children: "◎ Footprint" })
1111
+ ] })
1112
+ ] })
1113
+ ]
1114
+ }
1115
+ )
1116
+ ]
1117
+ }
1118
+ );
1119
+ }
1120
+ export {
1121
+ GroundTrackMap
1122
+ };
1123
+ //# sourceMappingURL=GroundTrackMap.js.map