@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 @@
1
+ {"version":3,"file":"GroundTrackMapLeaflet.js","sources":["../../../src/react/charts/GroundTrackMapLeaflet.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - GroundTrackMap Leaflet Provider\r\n *\r\n * Leaflet-based 2D world map for ground tracks, stations, and terminator.\r\n * Uses Zendir hybrid theme; all interactions enabled (zoom, scroll, drag, etc.).\r\n * Import leaflet-zendir.css when using this component.\r\n */\r\n\r\nimport React, { useRef, useEffect, useCallback, useMemo, useState } from 'react';\r\nimport { useTheme } from '../theme';\r\nimport type { GroundStation } from '../types';\r\nimport type { SatelliteTrack, GroundStationEnhanced, SROGroundStation } from './GroundTrackMap';\r\n\r\n// Optional Leaflet — consumer must install leaflet when using mapProvider=\"leaflet\"\r\nimport L from 'leaflet';\r\nimport 'leaflet/dist/leaflet.css';\r\nimport './leaflet-zendir.css';\r\nimport {\r\n splitPolylineAtAntimeridian,\r\n segmentsWithWorldCopies,\r\n geodesicCirclePoints,\r\n splitRingAtAntimeridian,\r\n} from './groundTrackMapLeafletUtils';\r\nimport {\r\n DEFAULT_TILE,\r\n FALLBACK_TILE,\r\n TILE_ERROR_THRESHOLD,\r\n CARTO_ATTRIBUTION,\r\n OSM_ATTRIBUTION,\r\n} from './groundTrackMapLeafletTiles';\r\n\r\nconst STATUS_COLOR_MAP: Record<string, string> = {\r\n normal: '#56f000',\r\n standby: '#2dccff',\r\n caution: '#fce83a',\r\n serious: '#ffb302',\r\n critical: '#ff3838',\r\n off: '#a4abb6',\r\n};\r\n\r\nconst DEFAULT_TRACK_COLORS = [\r\n '#2dccff', '#3E3CFF', '#9D70FF', '#56f000', '#fce83a', '#ff7849', '#2dd4bf', '#ff3838',\r\n];\r\n\r\n// =============================================================================\r\n// Icon helpers — produce L.DivIcon with inline SVG (no external assets needed)\r\n// =============================================================================\r\n\r\n/** Satellite spacecraft icon with solar panels, matching Astro UXDS style. */\r\nfunction createSatDivIcon(statusColor: string, trackColor: string): L.DivIcon {\r\n // Status badge shape (Astro UXDS spec)\r\n const badge = statusColor === '#56f000'\r\n ? `<circle cx=\"7\" cy=\"7\" r=\"3\" fill=\"${statusColor}\"/>` // normal: filled dot\r\n : statusColor === '#2dccff'\r\n ? `<circle cx=\"7\" cy=\"7\" r=\"2.5\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1.5\"/>` // standby: ring\r\n : statusColor === '#fce83a'\r\n ? `<rect x=\"4.5\" y=\"4.5\" width=\"5\" height=\"5\" fill=\"${statusColor}\"/>` // caution: square\r\n : statusColor === '#ffb302'\r\n ? `<polygon points=\"7,3.5 10.5,7 7,10.5 3.5,7\" fill=\"${statusColor}\"/>` // serious: diamond (Astro UXDS)\r\n : statusColor === '#ff3838'\r\n ? `<polygon points=\"7,10 4,4 10,4\" fill=\"${statusColor}\"/>` // critical: triangle down\r\n : `<circle cx=\"7\" cy=\"7\" r=\"2\" fill=\"${statusColor}\"/>`; // off: small dot\r\n\r\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"34\" height=\"34\" viewBox=\"0 0 34 34\">\r\n <!-- Glow ring -->\r\n <circle cx=\"17\" cy=\"17\" r=\"15\" fill=\"${statusColor}\" fill-opacity=\"0.12\"/>\r\n <!-- Main body circle -->\r\n <circle cx=\"17\" cy=\"17\" r=\"11\" fill=\"#0d1323\" stroke=\"${trackColor}\" stroke-width=\"1.5\"/>\r\n <!-- Left solar panel -->\r\n <rect x=\"2\" y=\"15\" width=\"9\" height=\"4\" rx=\"0.5\" fill=\"${trackColor}\" fill-opacity=\"0.75\"/>\r\n <line x1=\"5.5\" y1=\"15\" x2=\"5.5\" y2=\"19\" stroke=\"${trackColor}\" stroke-width=\"0.5\" stroke-opacity=\"0.45\"/>\r\n <!-- Connector left -->\r\n <line x1=\"11\" y1=\"17\" x2=\"13\" y2=\"17\" stroke=\"${trackColor}\" stroke-width=\"1.2\"/>\r\n <!-- Satellite bus body -->\r\n <rect x=\"13\" y=\"14.5\" width=\"8\" height=\"5\" rx=\"1\" fill=\"${statusColor}\"/>\r\n <!-- Connector right -->\r\n <line x1=\"21\" y1=\"17\" x2=\"23\" y2=\"17\" stroke=\"${trackColor}\" stroke-width=\"1.2\"/>\r\n <!-- Right solar panel -->\r\n <rect x=\"23\" y=\"15\" width=\"9\" height=\"4\" rx=\"0.5\" fill=\"${trackColor}\" fill-opacity=\"0.75\"/>\r\n <line x1=\"26.5\" y1=\"15\" x2=\"26.5\" y2=\"19\" stroke=\"${trackColor}\" stroke-width=\"0.5\" stroke-opacity=\"0.45\"/>\r\n <!-- Status badge (top-left) -->\r\n <circle cx=\"7\" cy=\"7\" r=\"5.5\" fill=\"#0d1323\"/>\r\n ${badge}\r\n </svg>`;\r\n\r\n return L.divIcon({\r\n html: svg,\r\n className: 'zendir-sat-icon',\r\n iconSize: [34, 34] as unknown as L.PointExpression,\r\n iconAnchor: [17, 17] as unknown as L.PointExpression,\r\n tooltipAnchor: [0, -18] as unknown as L.PointExpression,\r\n });\r\n}\r\n\r\n/** Ground station icon — dish/antenna shape, matching Astro UXDS style. */\r\nfunction createStationDivIcon(statusColor: string, type: string, status: string): L.DivIcon {\r\n // Status badge\r\n const badge = status === 'normal'\r\n ? `<circle cx=\"5\" cy=\"5\" r=\"2.5\" fill=\"${statusColor}\"/>`\r\n : status === 'standby'\r\n ? `<circle cx=\"5\" cy=\"5\" r=\"2\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1.2\"/>`\r\n : status === 'caution'\r\n ? `<rect x=\"3\" y=\"3\" width=\"4\" height=\"4\" fill=\"${statusColor}\"/>`\r\n : status === 'serious'\r\n ? `<polygon points=\"5,2.5 7.5,5 5,7.5 2.5,5\" fill=\"${statusColor}\"/>`\r\n : status === 'critical'\r\n ? `<polygon points=\"5,7.5 2.5,2.5 7.5,2.5\" fill=\"${statusColor}\"/>`\r\n : `<circle cx=\"5\" cy=\"5\" r=\"1.5\" fill=\"${statusColor}\"/>`;\r\n\r\n let iconInner = '';\r\n if (type === 'phased-array') {\r\n // Grid pattern (phased array)\r\n iconInner = `\r\n <rect x=\"9\" y=\"7\" width=\"10\" height=\"8\" rx=\"0.5\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1.2\"/>\r\n <line x1=\"12\" y1=\"7\" x2=\"12\" y2=\"15\" stroke=\"${statusColor}\" stroke-width=\"0.7\"/>\r\n <line x1=\"15\" y1=\"7\" x2=\"15\" y2=\"15\" stroke=\"${statusColor}\" stroke-width=\"0.7\"/>\r\n <line x1=\"9\" y1=\"10\" x2=\"19\" y2=\"10\" stroke=\"${statusColor}\" stroke-width=\"0.7\"/>\r\n <line x1=\"9\" y1=\"13\" x2=\"19\" y2=\"13\" stroke=\"${statusColor}\" stroke-width=\"0.7\"/>\r\n <line x1=\"14\" y1=\"15\" x2=\"14\" y2=\"20\" stroke=\"${statusColor}\" stroke-width=\"1.2\"/>\r\n <line x1=\"11\" y1=\"20\" x2=\"17\" y2=\"20\" stroke=\"${statusColor}\" stroke-width=\"1.2\"/>`;\r\n } else if (type === 'relay') {\r\n // Relay dish with signal arcs\r\n iconInner = `\r\n <path d=\"M 8 16 a 7 7 0 0 1 7 -7\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\r\n <path d=\"M 8 16 m 2 -2 a 5 5 0 0 1 5 -5\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1.2\" stroke-linecap=\"round\"/>\r\n <line x1=\"14\" y1=\"16\" x2=\"14\" y2=\"21\" stroke=\"${statusColor}\" stroke-width=\"1.2\"/>\r\n <line x1=\"11\" y1=\"21\" x2=\"17\" y2=\"21\" stroke=\"${statusColor}\" stroke-width=\"1.2\"/>\r\n <path d=\"M 16 8 a 3 3 0 0 1 0 4\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1.2\" stroke-linecap=\"round\"/>\r\n <path d=\"M 17.5 6.5 a 5 5 0 0 1 0 7\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1\" stroke-linecap=\"round\"/>`;\r\n } else {\r\n // Default: dish antenna with concentric arcs (Astro UXDS antenna pattern)\r\n iconInner = `\r\n <path d=\"M 14 14 m -7 0 a 7 7 0 0 1 7 -7\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\r\n <path d=\"M 14 14 m -5 0 a 5 5 0 0 1 5 -5\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\r\n <path d=\"M 14 14 m -3 0 a 3 3 0 0 1 3 -3\" fill=\"none\" stroke=\"${statusColor}\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\r\n <circle cx=\"14\" cy=\"14\" r=\"1.5\" fill=\"${statusColor}\"/>\r\n <line x1=\"14\" y1=\"15\" x2=\"14\" y2=\"21\" stroke=\"${statusColor}\" stroke-width=\"1.2\"/>\r\n <line x1=\"11\" y1=\"21\" x2=\"17\" y2=\"21\" stroke=\"${statusColor}\" stroke-width=\"1.2\"/>`;\r\n }\r\n\r\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"28\" height=\"28\" viewBox=\"0 0 28 28\">\r\n <!-- Glow ring -->\r\n <circle cx=\"14\" cy=\"14\" r=\"13\" fill=\"${statusColor}\" fill-opacity=\"0.1\"/>\r\n <!-- Background -->\r\n <circle cx=\"14\" cy=\"14\" r=\"11\" fill=\"#0d1323\" stroke=\"${statusColor}\" stroke-width=\"1.2\" stroke-opacity=\"0.7\"/>\r\n ${iconInner}\r\n <!-- Status badge (top-left) -->\r\n <circle cx=\"5\" cy=\"5\" r=\"5\" fill=\"#0d1323\"/>\r\n ${badge}\r\n </svg>`;\r\n\r\n return L.divIcon({\r\n html: svg,\r\n className: 'zendir-station-icon',\r\n iconSize: [28, 28] as unknown as L.PointExpression,\r\n iconAnchor: [14, 14] as unknown as L.PointExpression,\r\n tooltipAnchor: [0, -14] as unknown as L.PointExpression,\r\n });\r\n}\r\n\r\n/**\r\n * Compute the sunset terminator with CONTINUOUS (unwrapped) longitudes.\r\n * Keeping lons continuous avoids antimeridian discontinuities that break\r\n * polygon construction in Leaflet. Each world-copy offset shifts the\r\n * entire polygon, so no single polygon ever straddles ±180.\r\n */\r\nfunction calculateTerminatorContinuous(date: Date, numPoints: number = 72): Array<[number, number]> {\r\n const dayOfYear = Math.floor((date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000);\r\n const declination = -23.44 * Math.cos((2 * Math.PI / 365) * (dayOfYear + 10));\r\n const decRad = (declination * Math.PI) / 180;\r\n const hourAngle = ((date.getUTCHours() + date.getUTCMinutes() / 60) / 24) * 360 - 180;\r\n\r\n const points: Array<[number, number]> = [];\r\n let prevLon: number | null = null;\r\n for (let i = 0; i <= numPoints; i++) {\r\n const latRad = ((i / numPoints) * 180 - 90) * (Math.PI / 180);\r\n const cosH = -Math.tan(latRad) * Math.tan(decRad);\r\n let lon: number;\r\n if (cosH < -1) lon = hourAngle + 180;\r\n else if (cosH > 1) lon = hourAngle;\r\n else lon = hourAngle + (Math.acos(cosH) * 180) / Math.PI;\r\n\r\n if (prevLon != null) {\r\n while (lon - prevLon > 180) lon -= 360;\r\n while (lon - prevLon < -180) lon += 360;\r\n }\r\n prevLon = lon;\r\n points.push([(i / numPoints) * 180 - 90, lon]);\r\n }\r\n return points;\r\n}\r\n\r\n/**\r\n * Build a single night-side polygon from the continuous sunset terminator.\r\n *\r\n * Night = area between the sunset terminator (going east) and the sunrise\r\n * terminator (sunset − 180°). The polygon traces:\r\n * sunset (lat −90 → +90) → sunrise reversed (lat +90 → −90)\r\n *\r\n * Because longitudes are continuous (unwrapped), the polygon never crosses\r\n * the antimeridian internally — no splitting needed.\r\n */\r\nfunction buildNightPolygon(sunsetTerminator: Array<[number, number]>): [number, number][] {\r\n if (!sunsetTerminator.length) return [];\r\n const sunrise = sunsetTerminator.map(([lat, lon]) => [lat, lon - 180] as [number, number]);\r\n return [...sunsetTerminator, ...[...sunrise].reverse()];\r\n}\r\n\r\nexport type GroundStationMapItem = GroundStation | GroundStationEnhanced | SROGroundStation;\r\n\r\nexport interface GroundTrackMapLeafletProps {\r\n allSatellites: SatelliteTrack[];\r\n groundStations: GroundStationMapItem[];\r\n showTerminator?: boolean;\r\n showGrid?: boolean;\r\n showLegend?: boolean;\r\n showEquator?: boolean;\r\n showRecenterButton?: boolean;\r\n defaultCenter?: [number, number];\r\n defaultZoom?: number;\r\n height?: number | string;\r\n width?: number | string;\r\n minHeight?: string;\r\n emptyMessage?: string;\r\n tileUrl?: string;\r\n className?: string;\r\n onSatelliteClick?: (id: string) => void;\r\n onStationClick?: (id: string) => void;\r\n}\r\n\r\nexport function GroundTrackMapLeaflet({\r\n allSatellites,\r\n groundStations,\r\n showTerminator = true,\r\n showGrid = false,\r\n showLegend = true,\r\n showEquator = false,\r\n showRecenterButton = true,\r\n defaultCenter = [20, 0],\r\n defaultZoom = 2,\r\n height = '100%',\r\n width = '100%',\r\n minHeight = '400px',\r\n emptyMessage = 'No orbital data available',\r\n tileUrl = DEFAULT_TILE,\r\n className = '',\r\n onSatelliteClick,\r\n onStationClick,\r\n}: GroundTrackMapLeafletProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const mapRef = useRef<L.Map | null>(null);\r\n const tileLayerRef = useRef<L.TileLayer | null>(null);\r\n const overlayGroupRef = useRef<L.LayerGroup | null>(null);\r\n const controlsRef = useRef<L.Control[]>([]);\r\n const [ready, setReady] = useState(false);\r\n\r\n const clearLayers = useCallback(() => {\r\n const map = mapRef.current;\r\n if (!map) return;\r\n overlayGroupRef.current?.clearLayers();\r\n controlsRef.current.forEach((ctrl) => map.removeControl(ctrl));\r\n controlsRef.current = [];\r\n }, []);\r\n\r\n const addLayer = useCallback((layer: L.Layer) => {\r\n overlayGroupRef.current?.addLayer(layer);\r\n }, []);\r\n\r\n // Create map once on mount (or when tileUrl changes). Intentionally not depending on\r\n // defaultCenter/defaultZoom so animated updates do not recreate the map (no flicker/zoom reset).\r\n useEffect(() => {\r\n // eslint-disable-next-line react-hooks/exhaustive-deps -- defaultCenter/defaultZoom used only for initial view\r\n const el = containerRef.current;\r\n if (!el) return;\r\n\r\n const center: L.LatLngExpression = defaultCenter ?? [20, 0];\r\n const zoom = defaultZoom ?? 2;\r\n\r\n const map = L.map(el, {\r\n center,\r\n zoom,\r\n zoomControl: false,\r\n scrollWheelZoom: true,\r\n doubleClickZoom: true,\r\n touchZoom: true,\r\n boxZoom: true,\r\n keyboard: true,\r\n dragging: true,\r\n attributionControl: true,\r\n maxBounds: [[-90, -540], [90, 540]],\r\n maxBoundsViscosity: 1.0,\r\n });\r\n\r\n L.control.zoom({ position: 'topright' }).addTo(map);\r\n\r\n map.attributionControl.setPrefix('');\r\n\r\n const isCartoTiles = tileUrl.includes('cartocdn');\r\n if (isCartoTiles) {\r\n map.attributionControl.addAttribution(CARTO_ATTRIBUTION);\r\n }\r\n\r\n const tileOptions: L.TileLayerOptions = {\r\n maxZoom: 19,\r\n subdomains: isCartoTiles ? 'abcd' : 'abc',\r\n // crossOrigin avoids tainted-canvas errors when Leaflet tries to read tile pixels\r\n crossOrigin: true,\r\n };\r\n\r\n const tile = L.tileLayer(tileUrl, tileOptions);\r\n tile.addTo(map);\r\n tileLayerRef.current = tile;\r\n\r\n // When primary tiles fail (network, CORS, rate limit), switch to fallback immediately.\r\n // TILE_ERROR_THRESHOLD = 1 so the first error triggers the switch — no visible black period.\r\n let hasSwitchedToFallback = false;\r\n const onTileError = () => {\r\n if (hasSwitchedToFallback) return;\r\n hasSwitchedToFallback = true;\r\n tile.off('tileerror', onTileError);\r\n tile.remove();\r\n if (isCartoTiles) {\r\n map.attributionControl.removeAttribution(CARTO_ATTRIBUTION);\r\n map.attributionControl.addAttribution(OSM_ATTRIBUTION);\r\n }\r\n const fallback = L.tileLayer(FALLBACK_TILE, {\r\n maxZoom: 19,\r\n subdomains: 'abc',\r\n crossOrigin: true,\r\n });\r\n fallback.addTo(map);\r\n tileLayerRef.current = fallback;\r\n };\r\n tile.on('tileerror', onTileError);\r\n\r\n const overlayGroup = L.layerGroup();\r\n overlayGroup.addTo(map);\r\n overlayGroupRef.current = overlayGroup;\r\n\r\n mapRef.current = map;\r\n setReady(true);\r\n\r\n const onSize = () => {\r\n map.invalidateSize({ animate: false });\r\n };\r\n // Immediate RAF + two deferred calls cover: first paint, CSS transitions, flex layout settle\r\n const raf = requestAnimationFrame(onSize);\r\n const t1 = setTimeout(onSize, 150);\r\n const t2 = setTimeout(onSize, 500);\r\n\r\n return () => {\r\n clearTimeout(t1);\r\n clearTimeout(t2);\r\n cancelAnimationFrame(raf);\r\n clearLayers();\r\n tileLayerRef.current = null;\r\n map.remove();\r\n mapRef.current = null;\r\n overlayGroupRef.current = null;\r\n };\r\n }, [tileUrl, clearLayers]);\r\n\r\n useEffect(() => {\r\n if (!ready || !mapRef.current) return;\r\n const map = mapRef.current;\r\n clearLayers();\r\n\r\n if (showTerminator) {\r\n const sunsetTerminator = calculateTerminatorContinuous(new Date());\r\n const nightPoly = buildNightPolygon(sunsetTerminator);\r\n\r\n if (nightPoly.length > 2) {\r\n [0, 360, -360].forEach((offset) => {\r\n const shifted = nightPoly.map(([lat, lon]) => [lat, lon + offset] as [number, number]);\r\n addLayer(L.polygon(shifted, {\r\n color: 'transparent',\r\n fillColor: '#00060f',\r\n fillOpacity: 0.35,\r\n interactive: false,\r\n }));\r\n });\r\n }\r\n\r\n // Terminator boundary lines (sunset + sunrise, subtle)\r\n const sunriseTerminator = sunsetTerminator.map(([lat, lon]) => [lat, lon - 180] as [number, number]);\r\n [sunsetTerminator, sunriseTerminator].forEach((line) => {\r\n [0, 360, -360].forEach((offset) => {\r\n const shifted = line.map(([lat, lon]) => [lat, lon + offset] as [number, number]);\r\n addLayer(L.polyline(shifted, {\r\n color: 'rgba(88, 166, 255, 0.22)',\r\n weight: 1,\r\n interactive: false,\r\n }));\r\n });\r\n });\r\n }\r\n\r\n if (showGrid) {\r\n const gridStyle = { color: 'rgba(157, 112, 255, 0.12)', weight: 0.5, interactive: false };\r\n [-360, 0, 360].forEach((offset) => {\r\n for (let lon = -180; lon <= 180; lon += 30) {\r\n const l = lon + offset;\r\n addLayer(L.polyline([[90, l], [-90, l]], gridStyle));\r\n }\r\n for (let lat = -90; lat <= 90; lat += 30) {\r\n addLayer(L.polyline([[lat, -180 + offset], [lat, 180 + offset]], gridStyle));\r\n }\r\n });\r\n }\r\n\r\n if (showEquator) {\r\n [-360, 0, 360].forEach((offset) => {\r\n addLayer(L.polyline([[0, -180 + offset], [0, 180 + offset]], {\r\n color: 'rgba(88, 166, 255, 0.25)',\r\n weight: 1,\r\n dashArray: '6, 4',\r\n interactive: false,\r\n }));\r\n });\r\n }\r\n\r\n groundStations.forEach((gs) => {\r\n const status = ('status' in gs ? gs.status : undefined) ?? 'standby';\r\n const statusColor = STATUS_COLOR_MAP[status] || STATUS_COLOR_MAP.standby;\r\n const stationType = ('type' in gs ? (gs as { type?: string }).type : undefined) ?? 'dish';\r\n const radius = 'coverageRadius' in gs ? gs.coverageRadius : undefined;\r\n const showCoverage = 'showCoverage' in gs ? gs.showCoverage : false;\r\n if (radius != null && radius > 0 && showCoverage) {\r\n const ring = geodesicCirclePoints(gs.latitude, gs.longitude, radius, 64);\r\n const rings = splitRingAtAntimeridian(ring);\r\n [0, 360, -360].forEach((offset) => {\r\n rings.forEach((r) => {\r\n const shifted = r.map(([lat, lon]) => [lat, lon + offset] as [number, number]);\r\n addLayer(L.polygon(shifted, {\r\n color: `${statusColor}55`,\r\n fillColor: statusColor,\r\n fillOpacity: 0.1,\r\n weight: 1,\r\n dashArray: '4, 3',\r\n interactive: false,\r\n }));\r\n });\r\n });\r\n }\r\n\r\n const gsIcon = createStationDivIcon(statusColor, stationType, status);\r\n const marker = L.marker([gs.latitude, gs.longitude], { icon: gsIcon });\r\n addLayer(marker);\r\n const statusLabel = status !== 'standby' ? ` · ${status}` : '';\r\n marker.bindTooltip(\r\n `<strong>${gs.name}</strong>${statusLabel}${'network' in gs && gs.network ? `<br/><span style=\"opacity:0.7\">${gs.network}</span>` : ''}`,\r\n { permanent: false, direction: 'top', className: 'zendir-leaflet-tooltip' }\r\n );\r\n marker.on('click', () => {\r\n onStationClick?.('id' in gs ? String(gs.id) : gs.name);\r\n });\r\n });\r\n\r\n allSatellites.forEach((sat, satIdx) => {\r\n const track = sat.groundTrack;\r\n if (!track || track.length === 0) return;\r\n\r\n const color = sat.color || DEFAULT_TRACK_COLORS[satIdx % DEFAULT_TRACK_COLORS.length];\r\n const futureIdx = sat.futureTrackIndex ?? track.length;\r\n\r\n const pastLatLngs = track\r\n .slice(0, futureIdx)\r\n .map((p) => [p.latitude, p.longitude] as [number, number]);\r\n segmentsWithWorldCopies(splitPolylineAtAntimeridian(pastLatLngs)).forEach((seg) => {\r\n if (seg.length >= 2) {\r\n addLayer(L.polyline(seg, { color, weight: 2.5, opacity: 1 }));\r\n }\r\n });\r\n\r\n if (futureIdx < track.length) {\r\n const futureLatLngs = track\r\n .slice(futureIdx)\r\n .map((p) => [p.latitude, p.longitude] as [number, number]);\r\n segmentsWithWorldCopies(splitPolylineAtAntimeridian(futureLatLngs)).forEach((seg) => {\r\n if (seg.length >= 2) {\r\n addLayer(L.polyline(seg, { color, weight: 1.5, opacity: 0.5, dashArray: '6, 4' }));\r\n }\r\n });\r\n }\r\n\r\n // Access mask segments (contact passes) — solid green overlay on track\r\n if (sat.accessMask && sat.accessMask.some(Boolean)) {\r\n let segment: [number, number][] = [];\r\n for (let i = 0; i < track.length; i++) {\r\n if (sat.accessMask[i]) {\r\n segment.push([track[i].latitude, track[i].longitude]);\r\n } else if (segment.length >= 2) {\r\n segmentsWithWorldCopies(splitPolylineAtAntimeridian(segment)).forEach((seg) => {\r\n if (seg.length >= 2) {\r\n addLayer(L.polyline(seg, { color: STATUS_COLOR_MAP.normal, weight: 4, opacity: 0.9 }));\r\n }\r\n });\r\n segment = [];\r\n } else {\r\n segment = [];\r\n }\r\n }\r\n if (segment.length >= 2) {\r\n segmentsWithWorldCopies(splitPolylineAtAntimeridian(segment)).forEach((seg) => {\r\n if (seg.length >= 2) {\r\n addLayer(L.polyline(seg, { color: STATUS_COLOR_MAP.normal, weight: 4, opacity: 0.9 }));\r\n }\r\n });\r\n }\r\n }\r\n\r\n if (sat.passMarkers && sat.passMarkers.length > 0) {\r\n sat.passMarkers.forEach((pm) => {\r\n const isAos = pm.type === 'aos';\r\n const pmColor = isAos ? '#56f000' : '#ff3838';\r\n const pmMarker = L.circleMarker([pm.latitude, pm.longitude], {\r\n radius: 5,\r\n fillColor: pmColor,\r\n color: `${pmColor}cc`,\r\n weight: 1.5,\r\n fillOpacity: 0.9,\r\n });\r\n addLayer(pmMarker);\r\n pmMarker.bindTooltip(`${pm.type.toUpperCase()}${pm.label ? ` – ${pm.label}` : ''}`, {\r\n permanent: false,\r\n direction: 'top',\r\n className: 'zendir-leaflet-tooltip',\r\n });\r\n });\r\n }\r\n\r\n if (sat.showFootprint && sat.footprintRadius) {\r\n const lastIdx = futureIdx > 0 ? Math.min(futureIdx - 1, track.length - 1) : track.length - 1;\r\n const last = track[lastIdx];\r\n const ring = geodesicCirclePoints(last.latitude, last.longitude, sat.footprintRadius, 64);\r\n const rings = splitRingAtAntimeridian(ring);\r\n [0, 360, -360].forEach((offset) => {\r\n rings.forEach((r) => {\r\n const shifted = r.map(([lat, lon]) => [lat, lon + offset] as [number, number]);\r\n addLayer(L.polygon(shifted, {\r\n color: `${color}70`,\r\n fillColor: color,\r\n fillOpacity: 0.1,\r\n weight: 1,\r\n dashArray: '3, 3',\r\n interactive: false,\r\n }));\r\n });\r\n });\r\n }\r\n\r\n const currentIdx = futureIdx > 0 ? Math.min(futureIdx - 1, track.length - 1) : track.length - 1;\r\n const current = track[currentIdx];\r\n const statusColor = STATUS_COLOR_MAP[sat.status || 'normal'] || STATUS_COLOR_MAP.normal;\r\n\r\n const satIcon = createSatDivIcon(statusColor, color);\r\n const satMarker = L.marker([current.latitude, current.longitude], { icon: satIcon });\r\n addLayer(satMarker);\r\n satMarker.bindTooltip(\r\n `<strong style=\"color:${color}\">${sat.name}</strong><br/>` +\r\n `Lat ${current.latitude.toFixed(3)}° &nbsp; Lon ${current.longitude.toFixed(3)}°` +\r\n (current.altitude != null ? `<br/>Alt ${current.altitude.toFixed(1)} km` : '') +\r\n (sat.status ? `<br/><span style=\"color:${statusColor}\">${sat.status.toUpperCase()}</span>` : ''),\r\n { permanent: false, direction: 'top', className: 'zendir-leaflet-tooltip' }\r\n );\r\n satMarker.on('click', () => onSatelliteClick?.(sat.id));\r\n });\r\n\r\n if (showLegend && (allSatellites.length > 0 || groundStations.length > 0)) {\r\n const Legend = L.Control.extend({\r\n onAdd() {\r\n const div = L.DomUtil.create('div', 'leaflet-legend-zendir');\r\n div.style.cssText = `\r\n padding: 8px 12px; background: rgba(15,21,32,0.9); border: 1px solid rgba(157,112,255,0.2);\r\n border-radius: 8px; color: #e4e0f0; font-size: 11px; font-family: Roboto, sans-serif;\r\n `;\r\n allSatellites.forEach((s, i) => {\r\n const c = s.color || DEFAULT_TRACK_COLORS[i % DEFAULT_TRACK_COLORS.length];\r\n const row = document.createElement('div');\r\n row.style.cssText = 'display: flex; align-items: center; gap: 6px; margin: 2px 0;';\r\n const swatch = document.createElement('span');\r\n swatch.style.cssText = `width:8px;height:8px;border-radius:50%;background:${c};`;\r\n const label = document.createElement('span');\r\n label.textContent = s.name;\r\n row.appendChild(swatch);\r\n row.appendChild(label);\r\n div.appendChild(row);\r\n });\r\n if (groundStations.length > 0) {\r\n const row = document.createElement('div');\r\n row.style.cssText = 'display: flex; align-items: center; gap: 6px; margin: 2px 0; margin-top: 6px;';\r\n const swatch = document.createElement('span');\r\n swatch.style.cssText = 'width:8px;height:8px;border-radius:50%;background:#2dccff;';\r\n const label = document.createElement('span');\r\n label.textContent = `${groundStations.length} Ground Station${groundStations.length > 1 ? 's' : ''}`;\r\n row.appendChild(swatch);\r\n row.appendChild(label);\r\n div.appendChild(row);\r\n }\r\n return div;\r\n },\r\n });\r\n const legend = new Legend({ position: 'topleft' });\r\n legend.addTo(map);\r\n controlsRef.current.push(legend);\r\n }\r\n\r\n }, [\r\n ready,\r\n allSatellites,\r\n groundStations,\r\n showTerminator,\r\n showGrid,\r\n showEquator,\r\n showLegend,\r\n tokens.colors.text.secondary,\r\n addLayer,\r\n clearLayers,\r\n onSatelliteClick,\r\n onStationClick,\r\n ]);\r\n\r\n const handleRecenter = useCallback(() => {\r\n const map = mapRef.current;\r\n if (!map) return;\r\n const points: L.LatLngExpression[] = [];\r\n allSatellites.forEach((s) => {\r\n s.groundTrack.forEach((p) => points.push([p.latitude, p.longitude]));\r\n });\r\n groundStations.forEach((gs) => points.push([gs.latitude, gs.longitude]));\r\n if (points.length > 0) {\r\n const bounds = L.latLngBounds(points);\r\n map.fitBounds(bounds, { padding: [40, 40], maxZoom: 8 });\r\n } else {\r\n map.setView(defaultCenter, defaultZoom);\r\n }\r\n }, [allSatellites, groundStations, defaultCenter, defaultZoom]);\r\n\r\n const resolvedMinHeight = minHeight || (typeof height === 'number' ? `${height}px` : '400px');\r\n\r\n const isEmpty = allSatellites.length === 0 && groundStations.length === 0;\r\n\r\n return (\r\n <div\r\n className={`zendir-ground-track-map zendir-ground-track-map-leaflet ${className}`}\r\n data-map-backend=\"leaflet\"\r\n style={{\r\n width,\r\n height,\r\n minHeight: resolvedMinHeight,\r\n backgroundColor: tokens.colors.background.base,\r\n borderRadius: 8,\r\n overflow: 'hidden',\r\n position: 'relative',\r\n }}\r\n >\r\n <div\r\n ref={containerRef}\r\n style={{ width: '100%', height: '100%', minHeight: resolvedMinHeight }}\r\n />\r\n {isEmpty && (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n left: '50%',\r\n top: '50%',\r\n transform: 'translate(-50%, -50%)',\r\n color: tokens.colors.text.secondary,\r\n fontSize: 14,\r\n pointerEvents: 'none',\r\n }}\r\n >\r\n {emptyMessage}\r\n </div>\r\n )}\r\n {showRecenterButton && (\r\n <button\r\n type=\"button\"\r\n onClick={handleRecenter}\r\n title=\"Recenter map\"\r\n aria-label=\"Recenter map\"\r\n style={{\r\n position: 'absolute',\r\n top: 8,\r\n right: 50,\r\n zIndex: 1000,\r\n background: 'rgba(24, 29, 46, 0.9)',\r\n border: '1px solid rgba(157, 112, 255, 0.25)',\r\n borderRadius: 6,\r\n color: '#e4e0f0',\r\n cursor: 'pointer',\r\n padding: '6px 10px',\r\n fontSize: 12,\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 4,\r\n }}\r\n >\r\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\r\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\r\n <path d=\"M12 2v4M12 18v4M2 12h4M18 12h4\" />\r\n </svg>\r\n Recenter\r\n </button>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nexport default GroundTrackMapLeaflet;\r\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Tile layer URLs and settings for GroundTrackMapLeaflet.
3
+ *
4
+ * Primary: CARTO dark basemap (good looking, free, no key needed).
5
+ * - URL uses the current basemaps.cartocdn.com path (no /rastertiles/ prefix).
6
+ * - {r} is empty on standard displays, '@2x' on HiDPI — handled by {r} token.
7
+ * - subdomains: 'abcd' (four CARTO CDN shards).
8
+ *
9
+ * Fallback: OSM — always reliable, used when CARTO tiles fail.
10
+ */
11
+ /** Primary basemap: CARTO dark with labels. */
12
+ export declare const DEFAULT_TILE = "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png";
13
+ export declare const CARTO_ATTRIBUTION = "&copy; <a href=\"https://carto.com/attribution\" target=\"_blank\" rel=\"noopener noreferrer\">CARTO</a>";
14
+ /** Fallback when primary tiles fail to avoid black tiles. */
15
+ export declare const FALLBACK_TILE = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
16
+ export declare const OSM_ATTRIBUTION = "&copy; <a href=\"https://www.openstreetmap.org/copyright\" target=\"_blank\" rel=\"noopener noreferrer\">OpenStreetMap contributors</a>";
17
+ /**
18
+ * After this many consecutive tile errors, switch to the fallback layer.
19
+ * Set to 1 so we bail out immediately on the first network failure instead
20
+ * of waiting for several timeouts (which shows a black map for ~5 seconds).
21
+ */
22
+ export declare const TILE_ERROR_THRESHOLD = 1;
@@ -0,0 +1,11 @@
1
+ const DEFAULT_TILE = "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png";
2
+ const CARTO_ATTRIBUTION = '&copy; <a href="https://carto.com/attribution" target="_blank" rel="noopener noreferrer">CARTO</a>';
3
+ const FALLBACK_TILE = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
4
+ const OSM_ATTRIBUTION = '&copy; <a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap contributors</a>';
5
+ export {
6
+ CARTO_ATTRIBUTION,
7
+ DEFAULT_TILE,
8
+ FALLBACK_TILE,
9
+ OSM_ATTRIBUTION
10
+ };
11
+ //# sourceMappingURL=groundTrackMapLeafletTiles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groundTrackMapLeafletTiles.js","sources":["../../../src/react/charts/groundTrackMapLeafletTiles.ts"],"sourcesContent":["/**\r\n * Tile layer URLs and settings for GroundTrackMapLeaflet.\r\n *\r\n * Primary: CARTO dark basemap (good looking, free, no key needed).\r\n * - URL uses the current basemaps.cartocdn.com path (no /rastertiles/ prefix).\r\n * - {r} is empty on standard displays, '@2x' on HiDPI — handled by {r} token.\r\n * - subdomains: 'abcd' (four CARTO CDN shards).\r\n *\r\n * Fallback: OSM — always reliable, used when CARTO tiles fail.\r\n */\r\n\r\n/** Primary basemap: CARTO dark with labels. */\r\nexport const DEFAULT_TILE =\r\n 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png';\r\n\r\nexport const CARTO_ATTRIBUTION =\r\n '&copy; <a href=\"https://carto.com/attribution\" target=\"_blank\" rel=\"noopener noreferrer\">CARTO</a>';\r\n\r\n/** Fallback when primary tiles fail to avoid black tiles. */\r\nexport const FALLBACK_TILE = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';\r\n\r\nexport const OSM_ATTRIBUTION =\r\n '&copy; <a href=\"https://www.openstreetmap.org/copyright\" target=\"_blank\" rel=\"noopener noreferrer\">OpenStreetMap contributors</a>';\r\n\r\n/**\r\n * After this many consecutive tile errors, switch to the fallback layer.\r\n * Set to 1 so we bail out immediately on the first network failure instead\r\n * of waiting for several timeouts (which shows a black map for ~5 seconds).\r\n */\r\nexport const TILE_ERROR_THRESHOLD = 1;\r\n"],"names":[],"mappings":"AAYO,MAAM,eACX;AAEK,MAAM,oBACX;AAGK,MAAM,gBAAgB;AAEtB,MAAM,kBACX;"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Pure geometry helpers for GroundTrackMapLeaflet.
3
+ * Used for antimeridian splitting, geodesic circles, and world copies.
4
+ * Longitudes are normalized to [-180, 180] where required.
5
+ */
6
+ /** Normalize longitude to [-180, 180]. */
7
+ export declare function wrapLon(lon: number): number;
8
+ /** Normalize an array of [lat, lon] so all longitudes are in [-180, 180]. */
9
+ export declare function normalizeLatLngs(points: [number, number][]): [number, number][];
10
+ /**
11
+ * Split a polyline at the antimeridian (±180°).
12
+ * Input points should be normalized (wrapLon) so crossing is detected correctly.
13
+ * No segment will contain consecutive points with |dLon| > 180 (avoids vertical line at date line).
14
+ */
15
+ export declare function splitPolylineAtAntimeridian(points: [number, number][]): [number, number][][];
16
+ /** Return each segment plus world copies at lon ± 360. */
17
+ export declare function segmentsWithWorldCopies(segments: [number, number][][]): [number, number][][];
18
+ /** Geodesic circle as lat/lon polygon (for coverage that looks correct at all latitudes). */
19
+ export declare function geodesicCirclePoints(centerLat: number, centerLon: number, radiusDeg: number, numPoints?: number): [number, number][];
20
+ /**
21
+ * Split a closed ring (e.g. geodesic circle) at ±180° so each part can be drawn without wrapping.
22
+ * Returns one ring if the circle does not cross the date line, or two closed rings (east/west) if it does.
23
+ */
24
+ export declare function splitRingAtAntimeridian(ring: [number, number][]): [number, number][][];
@@ -0,0 +1,109 @@
1
+ function wrapLon(lon) {
2
+ let l = lon;
3
+ while (l > 180) l -= 360;
4
+ while (l < -180) l += 360;
5
+ return l;
6
+ }
7
+ function normalizeLatLngs(points) {
8
+ return points.map(([lat, lon]) => [lat, wrapLon(lon)]);
9
+ }
10
+ function splitPolylineAtAntimeridian(points) {
11
+ if (points.length < 2) return points.length ? [points] : [];
12
+ const normalized = normalizeLatLngs(points);
13
+ const segments = [];
14
+ let current = [[...normalized[0]]];
15
+ for (let i = 1; i < normalized.length; i++) {
16
+ const prev = normalized[i - 1];
17
+ const curr = [...normalized[i]];
18
+ const dLon = curr[1] - prev[1];
19
+ if (Math.abs(dLon) > 180) {
20
+ const edgeLon = dLon > 0 ? -180 : 180;
21
+ const unwrappedCurr = dLon > 0 ? curr[1] - 360 : curr[1] + 360;
22
+ const t = (edgeLon - prev[1]) / (unwrappedCurr - prev[1]);
23
+ const latEdge = prev[0] + t * (curr[0] - prev[0]);
24
+ current.push([latEdge, edgeLon]);
25
+ segments.push(current);
26
+ const otherEdge = edgeLon === 180 ? -180 : 180;
27
+ current = [[latEdge, otherEdge], curr];
28
+ } else {
29
+ current.push(curr);
30
+ }
31
+ }
32
+ segments.push(current);
33
+ return segments;
34
+ }
35
+ function segmentsWithWorldCopies(segments) {
36
+ const out = [];
37
+ for (const seg of segments) {
38
+ out.push(seg);
39
+ out.push(seg.map(([lat, lon]) => [lat, lon + 360]));
40
+ out.push(seg.map(([lat, lon]) => [lat, lon - 360]));
41
+ }
42
+ return out;
43
+ }
44
+ function geodesicCirclePoints(centerLat, centerLon, radiusDeg, numPoints = 64) {
45
+ const lat0 = centerLat * Math.PI / 180;
46
+ const lon0 = centerLon * Math.PI / 180;
47
+ const d = radiusDeg * Math.PI / 180;
48
+ const points = [];
49
+ for (let i = 0; i <= numPoints; i++) {
50
+ const bearing = i / numPoints * 2 * Math.PI;
51
+ const sinLat = Math.sin(lat0) * Math.cos(d) + Math.cos(lat0) * Math.sin(d) * Math.cos(bearing);
52
+ const lat = Math.asin(Math.max(-1, Math.min(1, sinLat)));
53
+ const lon = lon0 + Math.atan2(
54
+ Math.sin(bearing) * Math.sin(d) * Math.cos(lat0),
55
+ Math.cos(d) - Math.sin(lat0) * sinLat
56
+ );
57
+ let lonDeg = lon * 180 / Math.PI;
58
+ lonDeg = wrapLon(lonDeg);
59
+ points.push([lat * 180 / Math.PI, lonDeg]);
60
+ }
61
+ return points;
62
+ }
63
+ function splitRingAtAntimeridian(ring) {
64
+ if (ring.length < 3) return ring.length ? [ring] : [];
65
+ const pts = ring.map(([lat, lon]) => [lat, wrapLon(lon)]);
66
+ const segments = [];
67
+ let current = [pts[0]];
68
+ let latAt180 = null;
69
+ let latAtNeg180 = null;
70
+ for (let i = 1; i <= pts.length; i++) {
71
+ const prev = pts[i - 1];
72
+ const curr = i < pts.length ? pts[i] : pts[0];
73
+ const dLon = curr[1] - prev[1];
74
+ if (Math.abs(dLon) > 180) {
75
+ const edgeLon = dLon > 0 ? -180 : 180;
76
+ const unwrappedCurr = dLon > 0 ? curr[1] - 360 : curr[1] + 360;
77
+ const t = (edgeLon - prev[1]) / (unwrappedCurr - prev[1]);
78
+ const latEdge = prev[0] + t * (curr[0] - prev[0]);
79
+ current.push([latEdge, edgeLon]);
80
+ segments.push(current);
81
+ if (edgeLon === 180) latAt180 = latEdge;
82
+ else latAtNeg180 = latEdge;
83
+ const otherEdge = edgeLon === 180 ? -180 : 180;
84
+ current = [[latEdge, otherEdge]];
85
+ } else {
86
+ if (i < pts.length) current.push(curr);
87
+ }
88
+ }
89
+ if (current.length > 0) segments.push(current);
90
+ if (segments.length <= 1) return segments.length ? [segments[0]] : [ring];
91
+ const lat1 = latAt180 ?? latAtNeg180 ?? 0;
92
+ const lat2 = latAtNeg180 ?? latAt180 ?? 0;
93
+ const rings = [];
94
+ for (const seg of segments) {
95
+ const lastLon = seg[seg.length - 1][1];
96
+ if (lastLon === 180) rings.push([...seg, [lat2, 180]]);
97
+ else rings.push([...seg, [lat1, -180]]);
98
+ }
99
+ return rings;
100
+ }
101
+ export {
102
+ geodesicCirclePoints,
103
+ normalizeLatLngs,
104
+ segmentsWithWorldCopies,
105
+ splitPolylineAtAntimeridian,
106
+ splitRingAtAntimeridian,
107
+ wrapLon
108
+ };
109
+ //# sourceMappingURL=groundTrackMapLeafletUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groundTrackMapLeafletUtils.js","sources":["../../../src/react/charts/groundTrackMapLeafletUtils.ts"],"sourcesContent":["/**\r\n * Pure geometry helpers for GroundTrackMapLeaflet.\r\n * Used for antimeridian splitting, geodesic circles, and world copies.\r\n * Longitudes are normalized to [-180, 180] where required.\r\n */\r\n\r\n/** Normalize longitude to [-180, 180]. */\r\nexport function wrapLon(lon: number): number {\r\n let l = lon;\r\n while (l > 180) l -= 360;\r\n while (l < -180) l += 360;\r\n return l;\r\n}\r\n\r\n/** Normalize an array of [lat, lon] so all longitudes are in [-180, 180]. */\r\nexport function normalizeLatLngs(points: [number, number][]): [number, number][] {\r\n return points.map(([lat, lon]) => [lat, wrapLon(lon)] as [number, number]);\r\n}\r\n\r\n/**\r\n * Split a polyline at the antimeridian (±180°).\r\n * Input points should be normalized (wrapLon) so crossing is detected correctly.\r\n * No segment will contain consecutive points with |dLon| > 180 (avoids vertical line at date line).\r\n */\r\nexport function splitPolylineAtAntimeridian(points: [number, number][]): [number, number][][] {\r\n if (points.length < 2) return points.length ? [points] : [];\r\n const normalized = normalizeLatLngs(points);\r\n const segments: [number, number][][] = [];\r\n let current: [number, number][] = [[...normalized[0]]];\r\n for (let i = 1; i < normalized.length; i++) {\r\n const prev = normalized[i - 1];\r\n const curr: [number, number] = [...normalized[i]];\r\n const dLon = curr[1] - prev[1];\r\n if (Math.abs(dLon) > 180) {\r\n const edgeLon = dLon > 0 ? -180 : 180;\r\n // Unwrap curr to get correct interpolation across the dateline\r\n const unwrappedCurr = dLon > 0 ? curr[1] - 360 : curr[1] + 360;\r\n const t = (edgeLon - prev[1]) / (unwrappedCurr - prev[1]);\r\n const latEdge = prev[0] + t * (curr[0] - prev[0]);\r\n current.push([latEdge, edgeLon]);\r\n segments.push(current);\r\n const otherEdge = edgeLon === 180 ? -180 : 180;\r\n current = [[latEdge, otherEdge], curr];\r\n } else {\r\n current.push(curr);\r\n }\r\n }\r\n segments.push(current);\r\n return segments;\r\n}\r\n\r\n/** Return each segment plus world copies at lon ± 360. */\r\nexport function segmentsWithWorldCopies(segments: [number, number][][]): [number, number][][] {\r\n const out: [number, number][][] = [];\r\n for (const seg of segments) {\r\n out.push(seg);\r\n out.push(seg.map(([lat, lon]) => [lat, lon + 360] as [number, number]));\r\n out.push(seg.map(([lat, lon]) => [lat, lon - 360] as [number, number]));\r\n }\r\n return out;\r\n}\r\n\r\n/** Geodesic circle as lat/lon polygon (for coverage that looks correct at all latitudes). */\r\nexport function geodesicCirclePoints(\r\n centerLat: number,\r\n centerLon: number,\r\n radiusDeg: number,\r\n numPoints: number = 64,\r\n): [number, number][] {\r\n const lat0 = (centerLat * Math.PI) / 180;\r\n const lon0 = (centerLon * Math.PI) / 180;\r\n const d = (radiusDeg * Math.PI) / 180;\r\n const points: [number, number][] = [];\r\n for (let i = 0; i <= numPoints; i++) {\r\n const bearing = (i / numPoints) * 2 * Math.PI;\r\n const sinLat = Math.sin(lat0) * Math.cos(d) + Math.cos(lat0) * Math.sin(d) * Math.cos(bearing);\r\n const lat = Math.asin(Math.max(-1, Math.min(1, sinLat)));\r\n const lon = lon0 + Math.atan2(\r\n Math.sin(bearing) * Math.sin(d) * Math.cos(lat0),\r\n Math.cos(d) - Math.sin(lat0) * sinLat,\r\n );\r\n let lonDeg = (lon * 180) / Math.PI;\r\n lonDeg = wrapLon(lonDeg);\r\n points.push([(lat * 180) / Math.PI, lonDeg]);\r\n }\r\n return points;\r\n}\r\n\r\n/**\r\n * Split a closed ring (e.g. geodesic circle) at ±180° so each part can be drawn without wrapping.\r\n * Returns one ring if the circle does not cross the date line, or two closed rings (east/west) if it does.\r\n */\r\nexport function splitRingAtAntimeridian(ring: [number, number][]): [number, number][][] {\r\n if (ring.length < 3) return ring.length ? [ring] : [];\r\n const pts = ring.map(([lat, lon]) => [lat, wrapLon(lon)] as [number, number]);\r\n const segments: [number, number][][] = [];\r\n let current: [number, number][] = [pts[0]];\r\n let latAt180: number | null = null;\r\n let latAtNeg180: number | null = null;\r\n\r\n for (let i = 1; i <= pts.length; i++) {\r\n const prev = pts[i - 1];\r\n const curr = i < pts.length ? pts[i] : pts[0];\r\n const dLon = curr[1] - prev[1];\r\n if (Math.abs(dLon) > 180) {\r\n // Must match splitPolylineAtAntimeridian: dLon > 0 → crossing from west to east → exit at -180\r\n const edgeLon = dLon > 0 ? -180 : 180;\r\n // Unwrap curr to get correct interpolation across the dateline\r\n const unwrappedCurr = dLon > 0 ? curr[1] - 360 : curr[1] + 360;\r\n const t = (edgeLon - prev[1]) / (unwrappedCurr - prev[1]);\r\n const latEdge = prev[0] + t * (curr[0] - prev[0]);\r\n current.push([latEdge, edgeLon]);\r\n segments.push(current);\r\n if (edgeLon === 180) latAt180 = latEdge;\r\n else latAtNeg180 = latEdge;\r\n const otherEdge = edgeLon === 180 ? -180 : 180;\r\n current = [[latEdge, otherEdge]];\r\n } else {\r\n if (i < pts.length) current.push(curr);\r\n }\r\n }\r\n if (current.length > 0) segments.push(current);\r\n\r\n if (segments.length <= 1) return segments.length ? [segments[0]] : [ring];\r\n\r\n const lat1 = latAt180 ?? latAtNeg180 ?? 0;\r\n const lat2 = latAtNeg180 ?? latAt180 ?? 0;\r\n const rings: [number, number][][] = [];\r\n for (const seg of segments) {\r\n const lastLon = seg[seg.length - 1][1];\r\n if (lastLon === 180) rings.push([...seg, [lat2, 180]]);\r\n else rings.push([...seg, [lat1, -180]]);\r\n }\r\n return rings;\r\n}\r\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @zendir/ui - Chart Components
3
+ *
4
+ * Unified ECharts-based charting system with AstroUXD compliance.
5
+ */
6
+ export { AstroChart, LineChart, AreaChart, BarChart, ScatterChart, PieChart, DonutChart, GaugeChart, RadarChart, HeatmapChart, TimeSeriesChart, DualAxisChart, StackedAreaChart, StackedBarChart, BubbleChart, HistogramChart, SankeyChart, TreemapChart, SunburstChart, ParallelChart, CandlestickChart, GraphChart, BoxPlotChart, PowerChart, AttitudeChart, ThermalHeatmapChart, LinkBudgetChart, SubsystemGauge, OrbitChart, ContactWindowChart, SpectrumChart, ManeuverBudgetChart, EclipseTimelineChart, RoseDiagram, HeliocentricOrbitPlot, Scatter3DChart, Bar3DChart, Surface3DChart, Lines3DChart, SphericalRadar3DChart, TransferOrbit3DChart, AttitudeHistory3DChart, ConjunctionAssessment3DChart, LaunchCorridor3DChart, AntennaPattern3DChart, WaterfallChart, DopplerTrackChart, LinkMarginChart, ConstellationCoverageChart, ConjunctionChart, generatePowerData, generateAttitudeData, generateDopplerData, generateWaterfallData, generateContactWindows, generateHeliocentricOrbits, generateSpectrum, generateEclipseTimeline, generateConstellationCoverage, generateConjunctionEvents, PowerOverviewChart, generateSamplePowerData, createAstroEChartsTheme, ASTRO_DATA_VIZ_COLORS, OFFICIAL_ASTRO_DATA_VIZ_COLORS, STATUS_COLORS, ZENDIR_BRAND_COLORS, getStatusColor, getSeriesColor, getPaletteForDataType, createAreaGradient, formatTimeLabel, formatValueWithUnit, calculateAxisBounds, useChartStream, useWebSocketStream, useChartSync, dispatchToGroup, syncZoomRange, resetGroupZoom, showGroupTooltip, hideGroupTooltip, getGroupCharts, exportGroupAsImages, exportGroupAsCSV, } from './unified';
7
+ export type { AstroChartHandle, AstroChartProps, ChartType, ChartTheme, DataPoint, TimeSeriesPoint, SeriesData, LineStyleOptions, AreaStyleOptions, GradientOptions, SymbolOptions, AxisOptions, ZoomOptions, TooltipOptions, LegendOptions, BrushOptions, MarkLineOptions, MarkAreaOptions, AnnotationOptions, RealTimeOptions, ExportOptions, ChartEventParams, ZoomEventParams, BrushEventParams, PowerChartData, AttitudeChartData, ThermalChartData, LinkBudgetChartData, TelemetryStreamPoint, ContactWindowData, SpectrumDataPoint, ManeuverBudgetData, EclipseTimelineData, BubbleDataPoint, RoseDiagramData, HeliocentricOrbitData, ExportFileNameContext, Data3DPoint, Scatter3DData, Bar3DData, Surface3DData, Lines3DData, LineChartProps, AreaChartProps, BarChartProps, ScatterChartProps, PieChartProps, GaugeChartProps, RadarChartProps, HeatmapChartProps, TimeSeriesChartProps, DualAxisChartProps, BubbleChartProps, HistogramChartProps, SankeyChartProps, TreemapChartProps, TreemapDataNode, SunburstChartProps, SunburstDataNode, ParallelChartProps, ParallelAxisDef, CandlestickChartProps, CandlestickDataPoint, GraphChartProps, GraphNode, GraphLink, GraphCategory, // Domain Props Types
8
+ PowerChartProps, AttitudeChartProps, ThermalHeatmapChartProps, LinkBudgetChartProps, SubsystemGaugeProps, OrbitChartProps, ContactWindowChartProps, SpectrumChartProps, ManeuverBudgetChartProps, EclipseTimelineChartProps, RoseDiagramProps, HeliocentricOrbitProps, Scatter3DChartProps, Bar3DChartProps, Surface3DChartProps, Lines3DChartProps, SphericalRadar3DChartProps, SphericalRadar3DData, TransferOrbit3DChartProps, TransferOrbitSegment, TransferOrbitWaypoint, AttitudeHistory3DChartProps, AttitudeHistoryPoint, ConjunctionAssessment3DChartProps, ConjunctionEvent, LaunchCorridor3DChartProps, LaunchCorridorData, AntennaPattern3DChartProps, AntennaPattern3DData, WaterfallChartProps, DopplerTrackChartProps, LinkMarginChartProps, ConstellationCoverageChartProps, ConjunctionChartProps, WaterfallDataPoint, WaterfallSignalMarker, DopplerTrackPoint, SatellitePassInfo, LinkMarginPoint, CoverageGridData, PowerGeneratorConfig, AttitudeGeneratorConfig, DopplerGeneratorConfig, WaterfallGeneratorConfig, ContactGeneratorConfig, HeliocentricGeneratorConfig, SpectrumGeneratorConfig, EclipseGeneratorConfig, CoverageGeneratorConfig, ConjunctionGeneratorConfig, PowerOverviewChartProps, PowerTimelinePoint, PowerEvent, PowerState, OperationalMode, EventType, PowerEventType, StreamOptions, StreamController, WebSocketStreamOptions, WebSocketStreamController, UseChartSyncOptions, EChartsTheme, } from './unified';
9
+ export { GroundTrackMap } from './GroundTrackMap';
10
+ export type { GroundTrackMapProps, SatelliteTrack, GroundStationEnhanced, TeamPath, SROGroundStation } from './GroundTrackMap';
@@ -0,0 +1,24 @@
1
+ import { default as React } from 'react';
2
+ import { ECharts } from 'echarts';
3
+ import { AstroChartProps, DataPoint, TimeSeriesPoint } from './types';
4
+
5
+ export interface AstroChartHandle {
6
+ /** Get ECharts instance */
7
+ getChart: () => ECharts | undefined;
8
+ /** Resize chart */
9
+ resize: () => void;
10
+ /** Export as image (png, jpeg, svg) */
11
+ exportImage: (type?: 'png' | 'jpeg' | 'jpg' | 'svg', pixelRatio?: number) => string | undefined;
12
+ /** Export data as CSV */
13
+ exportCSV: () => string;
14
+ /** Suggested export filename from title, series names, and chart type (with optional extension and timestamp) */
15
+ getExportFileName: (extension?: string, includeTimestamp?: boolean) => string;
16
+ /** Append data for real-time updates */
17
+ appendData: (seriesIndex: number, data: DataPoint | TimeSeriesPoint) => void;
18
+ /** Clear all data */
19
+ clearData: () => void;
20
+ /** Dispatch action */
21
+ dispatchAction: (action: unknown) => void;
22
+ }
23
+ export declare const AstroChart: React.MemoExoticComponent<React.ForwardRefExoticComponent<AstroChartProps & React.RefAttributes<AstroChartHandle>>>;
24
+ export default AstroChart;