@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,836 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { useRef, useEffect, useState, useCallback } from "react";
3
+ import { AstroIcon } from "../core/AstroIcon.js";
4
+ import { GroundTrackMap } from "../charts/GroundTrackMap.js";
5
+ import atmosphereVertexShader from "../../shaders/atmosphere.vert.js";
6
+ import atmosphereFragmentShader from "../../shaders/atmosphere.frag.js";
7
+ import starsVertexShader from "../../shaders/stars.vert.js";
8
+ import starsFragmentShader from "../../shaders/stars.frag.js";
9
+ import { loadThree } from "./threeLoader.js";
10
+ import { useTheme } from "../theme/ThemeProvider.js";
11
+ function checkWebGLCapabilities() {
12
+ try {
13
+ const canvas = document.createElement("canvas");
14
+ const gl2 = canvas.getContext("webgl2");
15
+ if (gl2) {
16
+ return {
17
+ available: true,
18
+ version: 2,
19
+ maxTextureSize: gl2.getParameter(gl2.MAX_TEXTURE_SIZE)
20
+ };
21
+ }
22
+ const gl = canvas.getContext("webgl");
23
+ if (gl) {
24
+ return {
25
+ available: true,
26
+ version: 1,
27
+ maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE)
28
+ };
29
+ }
30
+ } catch {
31
+ }
32
+ return { available: false, version: 0, maxTextureSize: 0 };
33
+ }
34
+ const EARTH_RADIUS = 3e3;
35
+ const EARTH_RADIUS_KM = 6371;
36
+ const KM_TO_SCENE = EARTH_RADIUS / EARTH_RADIUS_KM;
37
+ const DEG_TO_RAD = Math.PI / 180;
38
+ function latLonAltToCartesian(lat, lon, altKm = 0) {
39
+ const r = EARTH_RADIUS + altKm * KM_TO_SCENE;
40
+ const phi = (90 - lat) * DEG_TO_RAD;
41
+ const theta = (lon + 180) * DEG_TO_RAD;
42
+ const x = -r * Math.sin(phi) * Math.cos(theta);
43
+ const y = r * Math.cos(phi);
44
+ const z = r * Math.sin(phi) * Math.sin(theta);
45
+ return [x, y, z];
46
+ }
47
+ function EarthViewer({
48
+ spacecraft = [],
49
+ groundStations = [],
50
+ groundTrack = [],
51
+ selectedSpacecraftId,
52
+ width = "100%",
53
+ height = 400,
54
+ autoRotate = true,
55
+ showAtmosphere = true,
56
+ showOrbits = true,
57
+ showVisibilityCones = false,
58
+ onSpacecraftClick,
59
+ onGroundStationClick,
60
+ className = "",
61
+ focusTarget,
62
+ transitionDuration = 2e3,
63
+ autoOrbit = false
64
+ }) {
65
+ const { tokens: _tokens } = useTheme();
66
+ const containerRef = useRef(null);
67
+ const rendererRef = useRef(null);
68
+ const sceneRef = useRef(null);
69
+ const cameraRef = useRef(null);
70
+ const earthRef = useRef(null);
71
+ const controlsRef = useRef(null);
72
+ const raycasterRef = useRef(null);
73
+ const mouseRef = useRef(null);
74
+ const animationRef = useRef(null);
75
+ const starsMaterialRef = useRef(null);
76
+ const timeRef = useRef(0);
77
+ const isUserInteractingRef = useRef(false);
78
+ const focusTransitionRef = useRef(null);
79
+ const orbitAngleRef = useRef(0);
80
+ const lastFocusTargetRef = useRef(null);
81
+ const isAnimatingRef = useRef(false);
82
+ const autoRotateRef = useRef(autoRotate);
83
+ const autoOrbitRef = useRef(autoOrbit);
84
+ const focusTargetRef = useRef(focusTarget);
85
+ useEffect(() => {
86
+ autoRotateRef.current = autoRotate;
87
+ }, [autoRotate]);
88
+ useEffect(() => {
89
+ autoOrbitRef.current = autoOrbit;
90
+ }, [autoOrbit]);
91
+ useEffect(() => {
92
+ focusTargetRef.current = focusTarget;
93
+ }, [focusTarget]);
94
+ const [webglCapabilities] = useState(() => checkWebGLCapabilities());
95
+ const [isLoading, setIsLoading] = useState(true);
96
+ const [error, setError] = useState(null);
97
+ const [threeLoaded, setThreeLoaded] = useState(false);
98
+ const [THREE, setTHREE] = useState(null);
99
+ const [OrbitControlsClass, setOrbitControlsClass] = useState(null);
100
+ const [hoveredObject, setHoveredObject] = useState(null);
101
+ useEffect(() => {
102
+ if (!webglCapabilities.available) {
103
+ setIsLoading(false);
104
+ return;
105
+ }
106
+ loadThree().then(({ THREE: threeModule, OrbitControls: controls }) => {
107
+ setTHREE(threeModule);
108
+ setOrbitControlsClass(() => controls);
109
+ setThreeLoaded(true);
110
+ }).catch((err) => {
111
+ setError("Failed to load 3D library");
112
+ setIsLoading(false);
113
+ });
114
+ }, [webglCapabilities.available]);
115
+ const initScene = useCallback(() => {
116
+ if (!THREE || !containerRef.current || !OrbitControlsClass) return;
117
+ const container = containerRef.current;
118
+ const rect = container.getBoundingClientRect();
119
+ const w = rect.width;
120
+ const h = height;
121
+ const scene = new THREE.Scene();
122
+ sceneRef.current = scene;
123
+ const camera = new THREE.PerspectiveCamera(45, w / h, 0.1, 1e5);
124
+ camera.position.set(0, 0, 1e4);
125
+ cameraRef.current = camera;
126
+ const renderer = new THREE.WebGLRenderer({
127
+ antialias: true,
128
+ alpha: true,
129
+ powerPreference: "high-performance",
130
+ preserveDrawingBuffer: true
131
+ // Prevents flickering from buffer swaps
132
+ });
133
+ renderer.setSize(w, h);
134
+ renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
135
+ container.appendChild(renderer.domElement);
136
+ rendererRef.current = renderer;
137
+ const controls = new OrbitControlsClass(camera, renderer.domElement);
138
+ controls.enableDamping = true;
139
+ controls.dampingFactor = 0.05;
140
+ controls.minDistance = 4500;
141
+ controls.maxDistance = 2e4;
142
+ controls.enablePan = false;
143
+ let interactionTimer;
144
+ const handleControlStart = () => {
145
+ isUserInteractingRef.current = true;
146
+ };
147
+ const handleControlEnd = () => {
148
+ clearTimeout(interactionTimer);
149
+ interactionTimer = setTimeout(() => {
150
+ isUserInteractingRef.current = false;
151
+ }, 3e3);
152
+ };
153
+ controls.addEventListener("start", handleControlStart);
154
+ controls.addEventListener("end", handleControlEnd);
155
+ controlsRef.current = controls;
156
+ raycasterRef.current = new THREE.Raycaster();
157
+ mouseRef.current = new THREE.Vector2();
158
+ const earthGeometry = new THREE.SphereGeometry(EARTH_RADIUS, 64, 32);
159
+ const earthMaterial = new THREE.MeshPhongMaterial({
160
+ color: 2245802,
161
+ shininess: 10
162
+ });
163
+ const textureLoader = new THREE.TextureLoader();
164
+ textureLoader.load(
165
+ "/world.topo.jpg",
166
+ (texture) => {
167
+ texture.wrapS = THREE.RepeatWrapping;
168
+ texture.wrapT = THREE.ClampToEdgeWrapping;
169
+ texture.minFilter = THREE.LinearFilter;
170
+ texture.magFilter = THREE.LinearFilter;
171
+ texture.flipY = true;
172
+ earthMaterial.map = texture;
173
+ earthMaterial.needsUpdate = true;
174
+ setIsLoading(false);
175
+ },
176
+ void 0,
177
+ () => {
178
+ setIsLoading(false);
179
+ }
180
+ );
181
+ const earth = new THREE.Mesh(earthGeometry, earthMaterial);
182
+ earth.rotation.y = -Math.PI / 2 + Math.PI;
183
+ scene.add(earth);
184
+ earthRef.current = earth;
185
+ if (showAtmosphere) {
186
+ const atmosphereGeometry = new THREE.SphereGeometry(EARTH_RADIUS * 1.25, 24, 12);
187
+ const atmosphereMaterial = new THREE.ShaderMaterial({
188
+ vertexShader: atmosphereVertexShader,
189
+ fragmentShader: atmosphereFragmentShader,
190
+ blending: THREE.AdditiveBlending,
191
+ side: THREE.BackSide,
192
+ transparent: true,
193
+ depthWrite: false
194
+ });
195
+ const atmosphere = new THREE.Mesh(atmosphereGeometry, atmosphereMaterial);
196
+ atmosphere.rotation.y = -Math.PI / 2;
197
+ scene.add(atmosphere);
198
+ }
199
+ const starsCount = 5e3;
200
+ const starsGeometry = new THREE.BufferGeometry();
201
+ const starsPositions = new Float32Array(starsCount * 3);
202
+ const starsOpacities = new Float32Array(starsCount);
203
+ for (let i = 0; i < starsCount * 3; i += 3) {
204
+ const radius = 5e4 + Math.random() * 5e4;
205
+ const theta = Math.random() * Math.PI * 2;
206
+ const phi = Math.acos(2 * Math.random() - 1);
207
+ starsPositions[i] = radius * Math.sin(phi) * Math.cos(theta);
208
+ starsPositions[i + 1] = radius * Math.sin(phi) * Math.sin(theta);
209
+ starsPositions[i + 2] = radius * Math.cos(phi);
210
+ starsOpacities[i / 3] = Math.random();
211
+ }
212
+ starsGeometry.setAttribute("position", new THREE.BufferAttribute(starsPositions, 3));
213
+ starsGeometry.setAttribute("opacity", new THREE.BufferAttribute(starsOpacities, 1));
214
+ const starsMaterial = new THREE.ShaderMaterial({
215
+ uniforms: { time: { value: 0 } },
216
+ vertexShader: starsVertexShader,
217
+ fragmentShader: starsFragmentShader,
218
+ transparent: true,
219
+ depthWrite: false,
220
+ blending: THREE.AdditiveBlending
221
+ });
222
+ starsMaterialRef.current = starsMaterial;
223
+ const stars = new THREE.Points(starsGeometry, starsMaterial);
224
+ scene.add(stars);
225
+ const ambientLight = new THREE.AmbientLight(4210752, 0.6);
226
+ scene.add(ambientLight);
227
+ const sunLight = new THREE.DirectionalLight(16777215, 1.2);
228
+ sunLight.position.set(1e4, 5e3, 1e4);
229
+ scene.add(sunLight);
230
+ return () => {
231
+ clearTimeout(interactionTimer);
232
+ if (animationRef.current) {
233
+ cancelAnimationFrame(animationRef.current);
234
+ }
235
+ controls.removeEventListener("start", handleControlStart);
236
+ controls.removeEventListener("end", handleControlEnd);
237
+ controls.dispose();
238
+ renderer.dispose();
239
+ if (container.contains(renderer.domElement)) {
240
+ container.removeChild(renderer.domElement);
241
+ }
242
+ };
243
+ }, [THREE, OrbitControlsClass, height, showAtmosphere]);
244
+ const updateSceneObjects = useCallback(() => {
245
+ if (!THREE || !sceneRef.current) return;
246
+ const scene = sceneRef.current;
247
+ const toRemove = scene.children.filter(
248
+ (obj) => {
249
+ var _a, _b, _c, _d;
250
+ return ((_a = obj.userData) == null ? void 0 : _a.isSpacecraft) || ((_b = obj.userData) == null ? void 0 : _b.isGroundStation) || ((_c = obj.userData) == null ? void 0 : _c.isOrbit) || ((_d = obj.userData) == null ? void 0 : _d.isVisibilityCone);
251
+ }
252
+ );
253
+ toRemove.forEach((obj) => {
254
+ if (obj.geometry) obj.geometry.dispose();
255
+ if (obj.material) obj.material.dispose();
256
+ scene.remove(obj);
257
+ });
258
+ spacecraft.forEach((sc) => {
259
+ const [x, y, z] = latLonAltToCartesian(sc.latitude, sc.longitude, sc.altitude);
260
+ const isSelected = sc.id === selectedSpacecraftId;
261
+ const geometry = new THREE.SphereGeometry(isSelected ? 80 : 55, 12, 12);
262
+ const material = new THREE.MeshBasicMaterial({
263
+ color: isSelected ? 16766720 : 65416
264
+ });
265
+ const marker = new THREE.Mesh(geometry, material);
266
+ marker.position.set(x, y, z);
267
+ marker.userData = {
268
+ isSpacecraft: true,
269
+ spacecraftId: sc.id,
270
+ data: sc
271
+ };
272
+ scene.add(marker);
273
+ const glowGeometry = new THREE.RingGeometry(isSelected ? 100 : 80, isSelected ? 130 : 100, 16);
274
+ const glowMaterial = new THREE.MeshBasicMaterial({
275
+ color: isSelected ? 16766720 : 65416,
276
+ transparent: true,
277
+ opacity: 0.4,
278
+ side: THREE.DoubleSide
279
+ });
280
+ const glow = new THREE.Mesh(glowGeometry, glowMaterial);
281
+ glow.position.set(x, y, z);
282
+ glow.lookAt(0, 0, 0);
283
+ glow.userData = { isSpacecraft: true, isGlow: true };
284
+ scene.add(glow);
285
+ const lineGeometry = new THREE.BufferGeometry().setFromPoints([
286
+ new THREE.Vector3(0, 0, 0),
287
+ new THREE.Vector3(x, y, z)
288
+ ]);
289
+ const lineMaterial = new THREE.LineBasicMaterial({
290
+ color: isSelected ? 16766720 : 65416,
291
+ transparent: true,
292
+ opacity: 0.12
293
+ });
294
+ const line = new THREE.Line(lineGeometry, lineMaterial);
295
+ line.userData = { isSpacecraft: true, isLine: true };
296
+ scene.add(line);
297
+ });
298
+ groundStations.forEach((gs) => {
299
+ const [x, y, z] = latLonAltToCartesian(gs.latitude, gs.longitude, 0);
300
+ const geometry = new THREE.ConeGeometry(45, 90, 4);
301
+ const material = new THREE.MeshBasicMaterial({ color: 65535 });
302
+ const marker = new THREE.Mesh(geometry, material);
303
+ marker.position.set(x, y, z);
304
+ marker.lookAt(0, 0, 0);
305
+ marker.rotateX(Math.PI / 2);
306
+ marker.userData = {
307
+ isGroundStation: true,
308
+ stationId: gs.id,
309
+ data: gs
310
+ };
311
+ scene.add(marker);
312
+ const ringGeometry = new THREE.RingGeometry(55, 80, 16);
313
+ const ringMaterial = new THREE.MeshBasicMaterial({
314
+ color: 65535,
315
+ transparent: true,
316
+ opacity: 0.5,
317
+ side: THREE.DoubleSide
318
+ });
319
+ const ring = new THREE.Mesh(ringGeometry, ringMaterial);
320
+ ring.position.set(x, y, z);
321
+ ring.lookAt(0, 0, 0);
322
+ ring.userData = { isGroundStation: true, isRing: true };
323
+ scene.add(ring);
324
+ if (showVisibilityCones) {
325
+ const coneHeight = 1200;
326
+ const coneRadius = 600;
327
+ const coneGeometry = new THREE.ConeGeometry(coneRadius, coneHeight, 16, 1, true);
328
+ const coneMaterial = new THREE.MeshBasicMaterial({
329
+ color: 65535,
330
+ transparent: true,
331
+ opacity: 0.06,
332
+ side: THREE.DoubleSide
333
+ });
334
+ const cone = new THREE.Mesh(coneGeometry, coneMaterial);
335
+ cone.position.set(x, y, z);
336
+ cone.lookAt(0, 0, 0);
337
+ cone.rotateX(-Math.PI / 2);
338
+ cone.translateY(coneHeight / 2);
339
+ cone.userData = { isVisibilityCone: true };
340
+ scene.add(cone);
341
+ }
342
+ });
343
+ if (showOrbits && groundTrack.length > 1) {
344
+ const points = [];
345
+ groundTrack.forEach((pt, i) => {
346
+ const alt = pt.alt || (spacecraft.length > 0 ? spacecraft[0].altitude : 400);
347
+ const [x, y, z] = latLonAltToCartesian(pt.latitude, pt.longitude, alt);
348
+ if (i > 0) {
349
+ const prevPt = groundTrack[i - 1];
350
+ const lonDiff = Math.abs(pt.longitude - prevPt.longitude);
351
+ if (lonDiff > 180) {
352
+ if (points.length > 1) {
353
+ const lineGeometry = new THREE.BufferGeometry().setFromPoints(points);
354
+ const lineMaterial = new THREE.LineBasicMaterial({
355
+ color: 2282478,
356
+ transparent: true,
357
+ opacity: 0.7
358
+ });
359
+ const line = new THREE.Line(lineGeometry, lineMaterial);
360
+ line.userData = { isOrbit: true };
361
+ scene.add(line);
362
+ }
363
+ points.length = 0;
364
+ }
365
+ }
366
+ points.push(new THREE.Vector3(x, y, z));
367
+ });
368
+ if (points.length > 1) {
369
+ const lineGeometry = new THREE.BufferGeometry().setFromPoints(points);
370
+ const lineMaterial = new THREE.LineBasicMaterial({
371
+ color: 2282478,
372
+ transparent: true,
373
+ opacity: 0.7
374
+ });
375
+ const line = new THREE.Line(lineGeometry, lineMaterial);
376
+ line.userData = { isOrbit: true };
377
+ scene.add(line);
378
+ }
379
+ }
380
+ }, [THREE, spacecraft, groundStations, groundTrack, selectedSpacecraftId, showOrbits, showVisibilityCones]);
381
+ const handleMouseMove = useCallback((event) => {
382
+ if (!containerRef.current || !raycasterRef.current || !cameraRef.current || !sceneRef.current) return;
383
+ const rect = containerRef.current.getBoundingClientRect();
384
+ const x = (event.clientX - rect.left) / rect.width * 2 - 1;
385
+ const y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
386
+ mouseRef.current.set(x, y);
387
+ raycasterRef.current.setFromCamera(mouseRef.current, cameraRef.current);
388
+ const interactables = sceneRef.current.children.filter(
389
+ (obj) => {
390
+ var _a, _b, _c, _d, _e;
391
+ return ((_a = obj.userData) == null ? void 0 : _a.isSpacecraft) && !((_b = obj.userData) == null ? void 0 : _b.isGlow) && !((_c = obj.userData) == null ? void 0 : _c.isLine) || ((_d = obj.userData) == null ? void 0 : _d.isGroundStation) && !((_e = obj.userData) == null ? void 0 : _e.isRing);
392
+ }
393
+ );
394
+ const intersects = raycasterRef.current.intersectObjects(interactables);
395
+ if (intersects.length > 0) {
396
+ const hit = intersects[0].object;
397
+ const userData = hit.userData;
398
+ if (userData.isSpacecraft) {
399
+ const sc = userData.data;
400
+ setHoveredObject({
401
+ type: "spacecraft",
402
+ id: userData.spacecraftId,
403
+ name: (sc == null ? void 0 : sc.name) || userData.spacecraftId,
404
+ data: sc,
405
+ screenX: event.clientX - rect.left,
406
+ screenY: event.clientY - rect.top
407
+ });
408
+ } else if (userData.isGroundStation) {
409
+ const gs = userData.data;
410
+ setHoveredObject({
411
+ type: "groundStation",
412
+ id: userData.stationId,
413
+ name: (gs == null ? void 0 : gs.name) || userData.stationId,
414
+ data: gs,
415
+ screenX: event.clientX - rect.left,
416
+ screenY: event.clientY - rect.top
417
+ });
418
+ }
419
+ if (containerRef.current) {
420
+ containerRef.current.style.cursor = "pointer";
421
+ }
422
+ } else {
423
+ setHoveredObject(null);
424
+ if (containerRef.current) {
425
+ containerRef.current.style.cursor = "grab";
426
+ }
427
+ }
428
+ }, []);
429
+ const handleClick = useCallback((event) => {
430
+ if (!containerRef.current || !raycasterRef.current || !cameraRef.current || !sceneRef.current) return;
431
+ const rect = containerRef.current.getBoundingClientRect();
432
+ const x = (event.clientX - rect.left) / rect.width * 2 - 1;
433
+ const y = -((event.clientY - rect.top) / rect.height) * 2 + 1;
434
+ mouseRef.current.set(x, y);
435
+ raycasterRef.current.setFromCamera(mouseRef.current, cameraRef.current);
436
+ const interactables = sceneRef.current.children.filter(
437
+ (obj) => {
438
+ var _a, _b, _c, _d, _e;
439
+ return ((_a = obj.userData) == null ? void 0 : _a.isSpacecraft) && !((_b = obj.userData) == null ? void 0 : _b.isGlow) && !((_c = obj.userData) == null ? void 0 : _c.isLine) || ((_d = obj.userData) == null ? void 0 : _d.isGroundStation) && !((_e = obj.userData) == null ? void 0 : _e.isRing);
440
+ }
441
+ );
442
+ const intersects = raycasterRef.current.intersectObjects(interactables);
443
+ if (intersects.length > 0) {
444
+ const hit = intersects[0].object;
445
+ const userData = hit.userData;
446
+ if (userData.isSpacecraft && onSpacecraftClick) {
447
+ onSpacecraftClick(userData.data);
448
+ } else if (userData.isGroundStation && onGroundStationClick) {
449
+ onGroundStationClick(userData.data);
450
+ }
451
+ }
452
+ }, [onSpacecraftClick, onGroundStationClick]);
453
+ useEffect(() => {
454
+ if (!THREE || !cameraRef.current || !controlsRef.current || !focusTarget) return;
455
+ const targetKey = focusTarget.id || focusTarget.name || JSON.stringify(focusTarget);
456
+ const lastKey = lastFocusTargetRef.current ? lastFocusTargetRef.current.id || lastFocusTargetRef.current.name || JSON.stringify(lastFocusTargetRef.current) : null;
457
+ if (targetKey === lastKey) return;
458
+ lastFocusTargetRef.current = focusTarget;
459
+ const camera = cameraRef.current;
460
+ const controls = controlsRef.current;
461
+ let targetLat = 0;
462
+ let targetLon = 0;
463
+ let targetZoom = 2;
464
+ if (focusTarget.latitude !== void 0 && focusTarget.longitude !== void 0) {
465
+ targetLat = focusTarget.latitude;
466
+ targetLon = focusTarget.longitude;
467
+ targetZoom = focusTarget.zoom ?? 2;
468
+ } else if (focusTarget.type === "spacecraft" && focusTarget.id) {
469
+ const sc = spacecraft.find((s) => s.id === focusTarget.id);
470
+ if (sc) {
471
+ targetLat = sc.latitude;
472
+ targetLon = sc.longitude;
473
+ targetZoom = 2.5;
474
+ }
475
+ } else if (focusTarget.type === "groundStation" && focusTarget.id) {
476
+ const gs = groundStations.find((g) => g.id === focusTarget.id);
477
+ if (gs) {
478
+ targetLat = gs.latitude;
479
+ targetLon = gs.longitude;
480
+ targetZoom = 2;
481
+ }
482
+ } else if (focusTarget.type === "overview") {
483
+ targetLat = 0;
484
+ targetLon = 0;
485
+ targetZoom = 1;
486
+ }
487
+ const [targetX, targetY, targetZ] = latLonAltToCartesian(targetLat, targetLon, 0);
488
+ const baseDistance = 1e4;
489
+ const zoomFactor = 1 / targetZoom;
490
+ const cameraDistance = baseDistance * zoomFactor;
491
+ const offset = new THREE.Vector3(targetX, targetY, targetZ).normalize().multiplyScalar(cameraDistance);
492
+ const targetPos = [
493
+ targetX + offset.x,
494
+ targetY + offset.y,
495
+ targetZ + offset.z
496
+ ];
497
+ const startPos = [
498
+ camera.position.x,
499
+ camera.position.y,
500
+ camera.position.z
501
+ ];
502
+ const startTarget = [
503
+ controls.target.x,
504
+ controls.target.y,
505
+ controls.target.z
506
+ ];
507
+ const targetTarget = [targetX, targetY, targetZ];
508
+ focusTransitionRef.current = {
509
+ startTime: Date.now(),
510
+ startPos,
511
+ targetPos,
512
+ startTarget,
513
+ targetTarget,
514
+ duration: transitionDuration,
515
+ isActive: true
516
+ };
517
+ orbitAngleRef.current = 0;
518
+ }, [THREE, focusTarget, transitionDuration, spacecraft, groundStations]);
519
+ const animate = useCallback(() => {
520
+ var _a;
521
+ if (!isAnimatingRef.current) return;
522
+ if (!rendererRef.current || !sceneRef.current || !cameraRef.current) return;
523
+ const camera = cameraRef.current;
524
+ const controls = controlsRef.current;
525
+ if (focusTransitionRef.current && focusTransitionRef.current.isActive) {
526
+ const transition = focusTransitionRef.current;
527
+ const elapsed = Date.now() - transition.startTime;
528
+ const progress = Math.min(elapsed / transition.duration, 1);
529
+ const easeProgress = 1 - Math.pow(1 - progress, 3);
530
+ camera.position.x = transition.startPos[0] + (transition.targetPos[0] - transition.startPos[0]) * easeProgress;
531
+ camera.position.y = transition.startPos[1] + (transition.targetPos[1] - transition.startPos[1]) * easeProgress;
532
+ camera.position.z = transition.startPos[2] + (transition.targetPos[2] - transition.startPos[2]) * easeProgress;
533
+ controls.target.x = transition.startTarget[0] + (transition.targetTarget[0] - transition.startTarget[0]) * easeProgress;
534
+ controls.target.y = transition.startTarget[1] + (transition.targetTarget[1] - transition.startTarget[1]) * easeProgress;
535
+ controls.target.z = transition.startTarget[2] + (transition.targetTarget[2] - transition.startTarget[2]) * easeProgress;
536
+ if (progress >= 1) {
537
+ transition.isActive = false;
538
+ }
539
+ }
540
+ const currentFocusTarget = focusTargetRef.current;
541
+ const currentAutoOrbit = autoOrbitRef.current;
542
+ const currentAutoRotate = autoRotateRef.current;
543
+ if (currentAutoOrbit && currentFocusTarget && !((_a = focusTransitionRef.current) == null ? void 0 : _a.isActive) && !isUserInteractingRef.current) {
544
+ orbitAngleRef.current += 5e-3;
545
+ if (currentFocusTarget.latitude !== void 0 && currentFocusTarget.longitude !== void 0) {
546
+ const [targetX, targetY, targetZ] = latLonAltToCartesian(
547
+ currentFocusTarget.latitude,
548
+ currentFocusTarget.longitude,
549
+ 0
550
+ );
551
+ const baseDistance = 1e4 / (currentFocusTarget.zoom ?? 2);
552
+ const orbitRadius = baseDistance * 0.3;
553
+ camera.position.x = targetX + Math.cos(orbitAngleRef.current) * orbitRadius;
554
+ camera.position.y = targetY + Math.sin(orbitAngleRef.current * 0.5) * orbitRadius * 0.5;
555
+ camera.position.z = targetZ + Math.sin(orbitAngleRef.current) * orbitRadius;
556
+ controls.target.set(targetX, targetY, targetZ);
557
+ }
558
+ }
559
+ if (controls) {
560
+ controls.update();
561
+ }
562
+ timeRef.current += 0.01;
563
+ if (starsMaterialRef.current) {
564
+ starsMaterialRef.current.uniforms.time.value = timeRef.current;
565
+ }
566
+ if (currentAutoRotate && earthRef.current && !isUserInteractingRef.current && !currentAutoOrbit) {
567
+ earthRef.current.rotation.y += 6e-4;
568
+ }
569
+ rendererRef.current.render(sceneRef.current, camera);
570
+ animationRef.current = requestAnimationFrame(animate);
571
+ }, []);
572
+ useEffect(() => {
573
+ if (!threeLoaded || !webglCapabilities.available || !OrbitControlsClass) return;
574
+ isAnimatingRef.current = false;
575
+ if (animationRef.current) {
576
+ cancelAnimationFrame(animationRef.current);
577
+ animationRef.current = null;
578
+ }
579
+ const cleanup = initScene();
580
+ isAnimatingRef.current = true;
581
+ animate();
582
+ return () => {
583
+ isAnimatingRef.current = false;
584
+ if (animationRef.current) {
585
+ cancelAnimationFrame(animationRef.current);
586
+ animationRef.current = null;
587
+ }
588
+ cleanup == null ? void 0 : cleanup();
589
+ };
590
+ }, [threeLoaded, webglCapabilities.available, OrbitControlsClass, initScene, animate]);
591
+ useEffect(() => {
592
+ if (threeLoaded) {
593
+ updateSceneObjects();
594
+ }
595
+ }, [threeLoaded, updateSceneObjects]);
596
+ useEffect(() => {
597
+ const container = containerRef.current;
598
+ if (!container || !threeLoaded) return;
599
+ container.addEventListener("mousemove", handleMouseMove);
600
+ container.addEventListener("click", handleClick);
601
+ return () => {
602
+ container.removeEventListener("mousemove", handleMouseMove);
603
+ container.removeEventListener("click", handleClick);
604
+ };
605
+ }, [threeLoaded, handleMouseMove, handleClick]);
606
+ useEffect(() => {
607
+ const handleResize = () => {
608
+ if (!containerRef.current || !rendererRef.current || !cameraRef.current) return;
609
+ const rect = containerRef.current.getBoundingClientRect();
610
+ cameraRef.current.aspect = rect.width / height;
611
+ cameraRef.current.updateProjectionMatrix();
612
+ rendererRef.current.setSize(rect.width, height);
613
+ };
614
+ window.addEventListener("resize", handleResize);
615
+ return () => window.removeEventListener("resize", handleResize);
616
+ }, [height]);
617
+ if (!webglCapabilities.available || error) {
618
+ return /* @__PURE__ */ jsxs("div", { className: `zendir-earth-viewer fallback ${className}`, style: { position: "relative" }, children: [
619
+ /* @__PURE__ */ jsx(
620
+ GroundTrackMap,
621
+ {
622
+ groundTrack,
623
+ groundStations,
624
+ width,
625
+ height
626
+ }
627
+ ),
628
+ /* @__PURE__ */ jsx("div", { style: {
629
+ position: "absolute",
630
+ bottom: 8,
631
+ right: 8,
632
+ backgroundColor: "rgba(0,0,0,0.7)",
633
+ color: "#d1d5db",
634
+ padding: "4px 8px",
635
+ borderRadius: 4,
636
+ fontSize: 10
637
+ }, children: error || "2D Mode (WebGL unavailable)" })
638
+ ] });
639
+ }
640
+ return /* @__PURE__ */ jsxs(
641
+ "div",
642
+ {
643
+ className: `zendir-earth-viewer ${className}`,
644
+ style: {
645
+ width,
646
+ height,
647
+ position: "relative",
648
+ backgroundColor: "#030508",
649
+ borderRadius: 8,
650
+ overflow: "hidden",
651
+ cursor: "grab"
652
+ },
653
+ children: [
654
+ /* @__PURE__ */ jsx(
655
+ "div",
656
+ {
657
+ ref: containerRef,
658
+ style: { width: "100%", height: "100%" }
659
+ }
660
+ ),
661
+ isLoading && /* @__PURE__ */ jsx("div", { style: {
662
+ position: "absolute",
663
+ top: "50%",
664
+ left: "50%",
665
+ transform: "translate(-50%, -50%)",
666
+ color: "#22d3ee",
667
+ fontSize: 14,
668
+ fontFamily: "ui-monospace, monospace"
669
+ }, children: "Loading 3D Earth..." }),
670
+ !isLoading && /* @__PURE__ */ jsxs("div", { style: {
671
+ position: "absolute",
672
+ top: 8,
673
+ left: 8,
674
+ backgroundColor: "rgba(0,0,0,0.75)",
675
+ color: "#e4e4e7",
676
+ padding: "10px 14px",
677
+ borderRadius: 8,
678
+ fontSize: 11,
679
+ fontFamily: "ui-monospace, monospace",
680
+ display: "flex",
681
+ flexDirection: "column",
682
+ gap: 5,
683
+ backdropFilter: "blur(4px)"
684
+ }, children: [
685
+ spacecraft.length > 0 && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
686
+ /* @__PURE__ */ jsx("span", { style: { color: "#00ff88", fontSize: 14 }, children: "●" }),
687
+ /* @__PURE__ */ jsxs("span", { children: [
688
+ spacecraft.length,
689
+ " spacecraft"
690
+ ] })
691
+ ] }),
692
+ groundStations.length > 0 && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
693
+ /* @__PURE__ */ jsx("span", { style: { color: "#00ffff", fontSize: 12 }, children: "▲" }),
694
+ /* @__PURE__ */ jsxs("span", { children: [
695
+ groundStations.length,
696
+ " ground stations"
697
+ ] })
698
+ ] })
699
+ ] }),
700
+ !isLoading && /* @__PURE__ */ jsx("div", { style: {
701
+ position: "absolute",
702
+ bottom: 8,
703
+ right: 8,
704
+ backgroundColor: "rgba(0,0,0,0.6)",
705
+ color: "#b8bcc8",
706
+ padding: "5px 10px",
707
+ borderRadius: 6,
708
+ fontSize: 9,
709
+ fontFamily: "system-ui"
710
+ }, children: "Drag to rotate • Scroll to zoom" }),
711
+ hoveredObject && /* @__PURE__ */ jsxs(
712
+ "div",
713
+ {
714
+ style: {
715
+ position: "absolute",
716
+ left: Math.min(hoveredObject.screenX + 15, (typeof width === "number" ? width : 400) - 200),
717
+ top: Math.max(hoveredObject.screenY - 10, 10),
718
+ backgroundColor: "rgba(9, 9, 11, 0.95)",
719
+ color: "#e4e4e7",
720
+ padding: "12px 16px",
721
+ borderRadius: 10,
722
+ fontSize: 11,
723
+ fontFamily: "ui-monospace, monospace",
724
+ border: hoveredObject.type === "spacecraft" ? "1px solid #22c55e" : "1px solid #22d3ee",
725
+ boxShadow: "0 12px 40px rgba(0,0,0,0.6)",
726
+ pointerEvents: "none",
727
+ zIndex: 100,
728
+ minWidth: 180,
729
+ backdropFilter: "blur(8px)"
730
+ },
731
+ children: [
732
+ hoveredObject.type === "spacecraft" ? /* @__PURE__ */ jsxs(Fragment, { children: [
733
+ /* @__PURE__ */ jsxs("div", { style: { fontWeight: 500, marginBottom: 8, color: "#22c55e", fontSize: "0.8125rem", display: "flex", alignItems: "center", gap: 6 }, children: [
734
+ /* @__PURE__ */ jsx(AstroIcon, { name: "satellite", size: "small", label: "" }),
735
+ " ",
736
+ hoveredObject.name
737
+ ] }),
738
+ hoveredObject.data && /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: 4 }, children: [
739
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
740
+ /* @__PURE__ */ jsx("span", { style: {
741
+ color: "#b8bcc8"
742
+ /* WCAG: improved contrast */
743
+ }, children: "Latitude" }),
744
+ /* @__PURE__ */ jsxs("span", { children: [
745
+ hoveredObject.data.latitude.toFixed(3),
746
+ "°"
747
+ ] })
748
+ ] }),
749
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
750
+ /* @__PURE__ */ jsx("span", { style: {
751
+ color: "#b8bcc8"
752
+ /* WCAG: improved contrast */
753
+ }, children: "Longitude" }),
754
+ /* @__PURE__ */ jsxs("span", { children: [
755
+ hoveredObject.data.longitude.toFixed(3),
756
+ "°"
757
+ ] })
758
+ ] }),
759
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
760
+ /* @__PURE__ */ jsx("span", { style: {
761
+ color: "#b8bcc8"
762
+ /* WCAG: improved contrast */
763
+ }, children: "Altitude" }),
764
+ /* @__PURE__ */ jsxs("span", { style: { color: "#22d3ee" }, children: [
765
+ hoveredObject.data.altitude.toFixed(1),
766
+ " km"
767
+ ] })
768
+ ] }),
769
+ hoveredObject.data.velocity && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
770
+ /* @__PURE__ */ jsx("span", { style: {
771
+ color: "#b8bcc8"
772
+ /* WCAG: improved contrast */
773
+ }, children: "Velocity" }),
774
+ /* @__PURE__ */ jsxs("span", { children: [
775
+ (hoveredObject.data.velocity || 0).toFixed(3),
776
+ " km/s"
777
+ ] })
778
+ ] })
779
+ ] })
780
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
781
+ /* @__PURE__ */ jsxs("div", { style: { fontWeight: 500, marginBottom: 8, color: "#22d3ee", fontSize: "0.8125rem", display: "flex", alignItems: "center", gap: 6 }, children: [
782
+ /* @__PURE__ */ jsx(AstroIcon, { name: "antenna", size: "small", label: "" }),
783
+ " ",
784
+ hoveredObject.name
785
+ ] }),
786
+ hoveredObject.data && /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: 4 }, children: [
787
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
788
+ /* @__PURE__ */ jsx("span", { style: {
789
+ color: "#b8bcc8"
790
+ /* WCAG: improved contrast */
791
+ }, children: "Latitude" }),
792
+ /* @__PURE__ */ jsxs("span", { children: [
793
+ hoveredObject.data.latitude.toFixed(3),
794
+ "°"
795
+ ] })
796
+ ] }),
797
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
798
+ /* @__PURE__ */ jsx("span", { style: {
799
+ color: "#b8bcc8"
800
+ /* WCAG: improved contrast */
801
+ }, children: "Longitude" }),
802
+ /* @__PURE__ */ jsxs("span", { children: [
803
+ hoveredObject.data.longitude.toFixed(3),
804
+ "°"
805
+ ] })
806
+ ] }),
807
+ hoveredObject.data.minElevation !== void 0 && /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
808
+ /* @__PURE__ */ jsx("span", { style: {
809
+ color: "#b8bcc8"
810
+ /* WCAG: improved contrast */
811
+ }, children: "Min Elevation" }),
812
+ /* @__PURE__ */ jsxs("span", { children: [
813
+ hoveredObject.data.minElevation,
814
+ "°"
815
+ ] })
816
+ ] })
817
+ ] })
818
+ ] }),
819
+ /* @__PURE__ */ jsx("div", { style: {
820
+ marginTop: 8,
821
+ paddingTop: 8,
822
+ borderTop: "1px solid rgba(113,113,122,0.3)",
823
+ color: "#9ca3af",
824
+ fontSize: 9
825
+ }, children: "Click for details" })
826
+ ]
827
+ }
828
+ )
829
+ ]
830
+ }
831
+ );
832
+ }
833
+ export {
834
+ EarthViewer
835
+ };
836
+ //# sourceMappingURL=EarthViewer.js.map