@zendir/ui 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/CHANGELOG.md +419 -386
  2. package/README.md +640 -631
  3. package/dist/_virtual/_rolldown/runtime.js +13 -0
  4. package/dist/index.js +17 -221
  5. package/dist/react/3d/CesiumCaptureSource.d.ts +0 -1
  6. package/dist/react/3d/CesiumCaptureSource.js +364 -283
  7. package/dist/react/3d/CesiumCaptureSource.js.map +1 -1
  8. package/dist/react/3d/ZenSpace3D.d.ts +2 -3
  9. package/dist/react/3d/ZenSpace3D.js +1681 -1237
  10. package/dist/react/3d/ZenSpace3D.js.map +1 -1
  11. package/dist/react/3d/ZenSpace3DCesium.d.ts +0 -1
  12. package/dist/react/3d/ZenSpace3DCesium.js +513 -560
  13. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -1
  14. package/dist/react/3d/ZenSpace3DShaders.js +61 -66
  15. package/dist/react/3d/ZenSpace3DShaders.js.map +1 -1
  16. package/dist/react/3d/ZenSpace3DTypes.d.ts +19 -20
  17. package/dist/react/3d/ZenSpace3DUtils.d.ts +0 -1
  18. package/dist/react/3d/ZenSpace3DUtils.js +37 -24
  19. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -1
  20. package/dist/react/3d/capturePngAnalysis.js +42 -36
  21. package/dist/react/3d/capturePngAnalysis.js.map +1 -1
  22. package/dist/react/3d/index.d.ts +3 -3
  23. package/dist/react/3d/index.js +5 -53
  24. package/dist/react/3d/threeLoader.d.ts +1 -1
  25. package/dist/react/3d/threeLoader.js +23 -18
  26. package/dist/react/3d/threeLoader.js.map +1 -1
  27. package/dist/react/astro/ClassificationBanner.d.ts +2 -3
  28. package/dist/react/astro/ClassificationBanner.js +95 -79
  29. package/dist/react/astro/ClassificationBanner.js.map +1 -1
  30. package/dist/react/astro/GlobalStatusBar.d.ts +0 -1
  31. package/dist/react/astro/GlobalStatusBar.js +157 -163
  32. package/dist/react/astro/GlobalStatusBar.js.map +1 -1
  33. package/dist/react/astro/MissionClock.d.ts +7 -8
  34. package/dist/react/astro/MissionClock.js +377 -400
  35. package/dist/react/astro/MissionClock.js.map +1 -1
  36. package/dist/react/astro/MonitoringIcon.d.ts +1 -2
  37. package/dist/react/astro/MonitoringIcon.js +422 -358
  38. package/dist/react/astro/MonitoringIcon.js.map +1 -1
  39. package/dist/react/astro/Notification.d.ts +1 -2
  40. package/dist/react/astro/Notification.js +229 -126
  41. package/dist/react/astro/Notification.js.map +1 -1
  42. package/dist/react/astro/Progress.d.ts +0 -1
  43. package/dist/react/astro/Progress.js +199 -141
  44. package/dist/react/astro/Progress.js.map +1 -1
  45. package/dist/react/astro/SimulationControls.d.ts +3 -4
  46. package/dist/react/astro/SimulationControls.js +596 -650
  47. package/dist/react/astro/SimulationControls.js.map +1 -1
  48. package/dist/react/astro/StatusIndicator.d.ts +0 -1
  49. package/dist/react/astro/StatusIndicator.js +236 -170
  50. package/dist/react/astro/StatusIndicator.js.map +1 -1
  51. package/dist/react/astro/UnifiedTimeline.d.ts +9 -10
  52. package/dist/react/astro/UnifiedTimeline.js +2345 -2392
  53. package/dist/react/astro/UnifiedTimeline.js.map +1 -1
  54. package/dist/react/astro/index.d.ts +5 -5
  55. package/dist/react/astro/index.js +1 -25
  56. package/dist/react/cards/AccessCard.d.ts +0 -1
  57. package/dist/react/cards/AccessCard.js +471 -405
  58. package/dist/react/cards/AccessCard.js.map +1 -1
  59. package/dist/react/cards/OrbitCard.d.ts +0 -1
  60. package/dist/react/cards/OrbitCard.js +487 -364
  61. package/dist/react/cards/OrbitCard.js.map +1 -1
  62. package/dist/react/cards/SpacecraftCard.d.ts +0 -1
  63. package/dist/react/cards/SpacecraftCard.js +813 -925
  64. package/dist/react/cards/SpacecraftCard.js.map +1 -1
  65. package/dist/react/cards/TelemetryCard.d.ts +0 -1
  66. package/dist/react/cards/TelemetryCard.js +1055 -732
  67. package/dist/react/cards/TelemetryCard.js.map +1 -1
  68. package/dist/react/cards/TelemetryStreamCard.d.ts +0 -1
  69. package/dist/react/cards/TelemetryStreamCard.js +323 -297
  70. package/dist/react/cards/TelemetryStreamCard.js.map +1 -1
  71. package/dist/react/cards/index.d.ts +1 -1
  72. package/dist/react/cards/index.js +1 -8
  73. package/dist/react/charts/GroundTrackMap.d.ts +6 -7
  74. package/dist/react/charts/GroundTrackMap.js +1377 -1256
  75. package/dist/react/charts/GroundTrackMap.js.map +1 -1
  76. package/dist/react/charts/GroundTrackMapLeaflet.d.ts +1 -2
  77. package/dist/react/charts/GroundTrackMapLeaflet.js +1065 -987
  78. package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -1
  79. package/dist/react/charts/groundTrackMapLeafletTiles.js +34 -25
  80. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -1
  81. package/dist/react/charts/groundTrackMapLeafletUtils.js +70 -61
  82. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -1
  83. package/dist/react/charts/index.d.ts +1 -1
  84. package/dist/react/charts/index.js +7 -100
  85. package/dist/react/charts/unified/AstroChart.d.ts +1 -2
  86. package/dist/react/charts/unified/AstroChart.js +1331 -1411
  87. package/dist/react/charts/unified/AstroChart.js.map +1 -1
  88. package/dist/react/charts/unified/PowerOverviewChart.d.ts +3 -3
  89. package/dist/react/charts/unified/PowerOverviewChart.js +495 -478
  90. package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -1
  91. package/dist/react/charts/unified/domain.d.ts +12 -13
  92. package/dist/react/charts/unified/domain.js +3999 -3145
  93. package/dist/react/charts/unified/domain.js.map +1 -1
  94. package/dist/react/charts/unified/generators.d.ts +3 -4
  95. package/dist/react/charts/unified/generators.js +561 -498
  96. package/dist/react/charts/unified/generators.js.map +1 -1
  97. package/dist/react/charts/unified/index.d.ts +1 -1
  98. package/dist/react/charts/unified/presets.d.ts +14 -15
  99. package/dist/react/charts/unified/presets.js +857 -994
  100. package/dist/react/charts/unified/presets.js.map +1 -1
  101. package/dist/react/charts/unified/sync.d.ts +2 -3
  102. package/dist/react/charts/unified/sync.js +229 -195
  103. package/dist/react/charts/unified/sync.js.map +1 -1
  104. package/dist/react/charts/unified/theme.d.ts +11 -12
  105. package/dist/react/charts/unified/theme.js +606 -642
  106. package/dist/react/charts/unified/theme.js.map +1 -1
  107. package/dist/react/charts/unified/types.d.ts +32 -33
  108. package/dist/react/charts/unified/useChartStream.d.ts +1 -2
  109. package/dist/react/charts/unified/useChartStream.js +203 -216
  110. package/dist/react/charts/unified/useChartStream.js.map +1 -1
  111. package/dist/react/chatgpt/AppCard.d.ts +1 -2
  112. package/dist/react/chatgpt/index.d.ts +7 -7
  113. package/dist/react/chatgpt/index.js +160 -139
  114. package/dist/react/chatgpt/index.js.map +1 -1
  115. package/dist/react/context/CategoryContext.d.ts +0 -1
  116. package/dist/react/context/CategoryContext.js +78 -29
  117. package/dist/react/context/CategoryContext.js.map +1 -1
  118. package/dist/react/context/DisplaySettingsContext.d.ts +1 -2
  119. package/dist/react/context/DisplaySettingsContext.js +205 -156
  120. package/dist/react/context/DisplaySettingsContext.js.map +1 -1
  121. package/dist/react/context/SpatialSelectionContext.d.ts +0 -1
  122. package/dist/react/context/SpatialSelectionContext.js +36 -7
  123. package/dist/react/context/SpatialSelectionContext.js.map +1 -1
  124. package/dist/react/core/data/DataTable.d.ts +3 -4
  125. package/dist/react/core/data/DataTable.js +473 -440
  126. package/dist/react/core/data/DataTable.js.map +1 -1
  127. package/dist/react/core/data/DataValue.d.ts +4 -5
  128. package/dist/react/core/data/DataValue.js +605 -571
  129. package/dist/react/core/data/DataValue.js.map +1 -1
  130. package/dist/react/core/data/propertyConfig.d.ts +1 -2
  131. package/dist/react/core/data/propertyConfig.js +446 -382
  132. package/dist/react/core/data/propertyConfig.js.map +1 -1
  133. package/dist/react/core/display/AstroIcon.d.ts +4 -5
  134. package/dist/react/core/display/AstroIcon.js +339 -429
  135. package/dist/react/core/display/AstroIcon.js.map +1 -1
  136. package/dist/react/core/display/Badge.d.ts +2 -3
  137. package/dist/react/core/display/Badge.js +131 -131
  138. package/dist/react/core/display/Badge.js.map +1 -1
  139. package/dist/react/core/display/CardHeader.d.ts +0 -1
  140. package/dist/react/core/display/CardHeader.js +398 -311
  141. package/dist/react/core/display/CardHeader.js.map +1 -1
  142. package/dist/react/core/display/Container.d.ts +2 -3
  143. package/dist/react/core/display/Container.js +640 -668
  144. package/dist/react/core/display/Container.js.map +1 -1
  145. package/dist/react/core/display/CopyButton.d.ts +1 -2
  146. package/dist/react/core/display/CopyButton.js +158 -101
  147. package/dist/react/core/display/CopyButton.js.map +1 -1
  148. package/dist/react/core/display/GlassCard.d.ts +3 -4
  149. package/dist/react/core/display/GlassCard.js +416 -369
  150. package/dist/react/core/display/GlassCard.js.map +1 -1
  151. package/dist/react/core/display/HeaderIconWithStatus.d.ts +0 -1
  152. package/dist/react/core/display/HeaderIconWithStatus.js +152 -152
  153. package/dist/react/core/display/HeaderIconWithStatus.js.map +1 -1
  154. package/dist/react/core/display/Icon.d.ts +2 -3
  155. package/dist/react/core/display/Icon.js +172 -143
  156. package/dist/react/core/display/Icon.js.map +1 -1
  157. package/dist/react/core/display/Typography.d.ts +24 -25
  158. package/dist/react/core/display/Typography.js +360 -178
  159. package/dist/react/core/display/Typography.js.map +1 -1
  160. package/dist/react/core/feedback/ConfirmDialog.d.ts +1 -2
  161. package/dist/react/core/feedback/ConfirmDialog.js +343 -304
  162. package/dist/react/core/feedback/ConfirmDialog.js.map +1 -1
  163. package/dist/react/core/feedback/Dialog.d.ts +2 -3
  164. package/dist/react/core/feedback/Dialog.js +189 -197
  165. package/dist/react/core/feedback/Dialog.js.map +1 -1
  166. package/dist/react/core/feedback/Toast.d.ts +2 -3
  167. package/dist/react/core/feedback/Toast.js +346 -207
  168. package/dist/react/core/feedback/Toast.js.map +1 -1
  169. package/dist/react/core/index.d.ts +26 -26
  170. package/dist/react/core/index.js +7 -119
  171. package/dist/react/core/inputs/Button.d.ts +2 -3
  172. package/dist/react/core/inputs/Button.js +281 -304
  173. package/dist/react/core/inputs/Button.js.map +1 -1
  174. package/dist/react/core/inputs/Checkbox.d.ts +2 -3
  175. package/dist/react/core/inputs/Checkbox.js +139 -127
  176. package/dist/react/core/inputs/Checkbox.js.map +1 -1
  177. package/dist/react/core/inputs/Input.d.ts +3 -4
  178. package/dist/react/core/inputs/Input.js +277 -285
  179. package/dist/react/core/inputs/Input.js.map +1 -1
  180. package/dist/react/core/inputs/LimitsBar.d.ts +1 -2
  181. package/dist/react/core/inputs/LimitsBar.js +271 -196
  182. package/dist/react/core/inputs/LimitsBar.js.map +1 -1
  183. package/dist/react/core/inputs/NumberInput.d.ts +2 -3
  184. package/dist/react/core/inputs/NumberInput.js +531 -503
  185. package/dist/react/core/inputs/NumberInput.js.map +1 -1
  186. package/dist/react/core/inputs/PinInput.d.ts +2 -3
  187. package/dist/react/core/inputs/PinInput.js +224 -207
  188. package/dist/react/core/inputs/PinInput.js.map +1 -1
  189. package/dist/react/core/inputs/Select.d.ts +1 -2
  190. package/dist/react/core/inputs/Select.js +298 -299
  191. package/dist/react/core/inputs/Select.js.map +1 -1
  192. package/dist/react/core/inputs/Toggle.d.ts +2 -3
  193. package/dist/react/core/inputs/Toggle.js +142 -148
  194. package/dist/react/core/inputs/Toggle.js.map +1 -1
  195. package/dist/react/core/layout/Box.d.ts +3 -4
  196. package/dist/react/core/layout/Box.js +118 -122
  197. package/dist/react/core/layout/Box.js.map +1 -1
  198. package/dist/react/core/layout/Center.d.ts +0 -1
  199. package/dist/react/core/layout/Center.js +45 -32
  200. package/dist/react/core/layout/Center.js.map +1 -1
  201. package/dist/react/core/layout/Divider.d.ts +1 -2
  202. package/dist/react/core/layout/Divider.js +112 -106
  203. package/dist/react/core/layout/Divider.js.map +1 -1
  204. package/dist/react/core/layout/Flex.d.ts +4 -5
  205. package/dist/react/core/layout/Flex.js +120 -124
  206. package/dist/react/core/layout/Flex.js.map +1 -1
  207. package/dist/react/core/layout/Grid.d.ts +5 -6
  208. package/dist/react/core/layout/Grid.js +131 -138
  209. package/dist/react/core/layout/Grid.js.map +1 -1
  210. package/dist/react/core/layout/Spacer.d.ts +0 -1
  211. package/dist/react/core/layout/Spacer.js +36 -29
  212. package/dist/react/core/layout/Spacer.js.map +1 -1
  213. package/dist/react/core/layout/Stack.d.ts +4 -5
  214. package/dist/react/core/layout/Stack.js +127 -70
  215. package/dist/react/core/layout/Stack.js.map +1 -1
  216. package/dist/react/core/layout/responsive.d.ts +1 -2
  217. package/dist/react/core/layout/responsive.js +25 -19
  218. package/dist/react/core/layout/responsive.js.map +1 -1
  219. package/dist/react/core/layout/useBreakpoint.d.ts +1 -1
  220. package/dist/react/core/layout/useBreakpoint.js +119 -66
  221. package/dist/react/core/layout/useBreakpoint.js.map +1 -1
  222. package/dist/react/core/navigation/AppBar.d.ts +1 -2
  223. package/dist/react/core/navigation/AppBar.js +827 -805
  224. package/dist/react/core/navigation/AppBar.js.map +1 -1
  225. package/dist/react/core/navigation/Pagination.d.ts +2 -3
  226. package/dist/react/core/navigation/Pagination.js +207 -187
  227. package/dist/react/core/navigation/Pagination.js.map +1 -1
  228. package/dist/react/core/navigation/SideNav.d.ts +5 -6
  229. package/dist/react/core/navigation/SideNav.js +855 -629
  230. package/dist/react/core/navigation/SideNav.js.map +1 -1
  231. package/dist/react/core/navigation/Tabs.d.ts +0 -1
  232. package/dist/react/core/navigation/Tabs.js +113 -119
  233. package/dist/react/core/navigation/Tabs.js.map +1 -1
  234. package/dist/react/core/overlays/Popover.d.ts +2 -3
  235. package/dist/react/core/overlays/Popover.js +303 -282
  236. package/dist/react/core/overlays/Popover.js.map +1 -1
  237. package/dist/react/core/overlays/SidePanel.d.ts +1 -2
  238. package/dist/react/core/overlays/SidePanel.js +217 -212
  239. package/dist/react/core/overlays/SidePanel.js.map +1 -1
  240. package/dist/react/core/overlays/Tooltip.d.ts +1 -2
  241. package/dist/react/core/overlays/Tooltip.js +170 -176
  242. package/dist/react/core/overlays/Tooltip.js.map +1 -1
  243. package/dist/react/core/widgets/ActivityPlanner.d.ts +0 -1
  244. package/dist/react/core/widgets/ActivityPlanner.js +855 -517
  245. package/dist/react/core/widgets/ActivityPlanner.js.map +1 -1
  246. package/dist/react/core/widgets/Capture.d.ts +2 -3
  247. package/dist/react/core/widgets/Capture.js +965 -779
  248. package/dist/react/core/widgets/Capture.js.map +1 -1
  249. package/dist/react/core/widgets/ChatPanel.d.ts +16 -17
  250. package/dist/react/core/widgets/ChatPanel.js +1734 -1034
  251. package/dist/react/core/widgets/ChatPanel.js.map +1 -1
  252. package/dist/react/core/widgets/ColorPickerPanel.d.ts +0 -1
  253. package/dist/react/core/widgets/ColorPickerPanel.js +298 -287
  254. package/dist/react/core/widgets/ColorPickerPanel.js.map +1 -1
  255. package/dist/react/core/widgets/CommandBuilder.d.ts +2 -3
  256. package/dist/react/core/widgets/CommandBuilder.js +624 -516
  257. package/dist/react/core/widgets/CommandBuilder.js.map +1 -1
  258. package/dist/react/core/widgets/ConnectionForm.d.ts +2 -3
  259. package/dist/react/core/widgets/ConnectionForm.js +528 -492
  260. package/dist/react/core/widgets/ConnectionForm.js.map +1 -1
  261. package/dist/react/core/widgets/FileExplorer.d.ts +3 -4
  262. package/dist/react/core/widgets/FileExplorer.js +617 -505
  263. package/dist/react/core/widgets/FileExplorer.js.map +1 -1
  264. package/dist/react/core/widgets/HexViewer.d.ts +2 -3
  265. package/dist/react/core/widgets/HexViewer.js +1353 -1091
  266. package/dist/react/core/widgets/HexViewer.js.map +1 -1
  267. package/dist/react/core/widgets/ImageFrame.d.ts +1 -2
  268. package/dist/react/core/widgets/ImageFrame.js +230 -193
  269. package/dist/react/core/widgets/ImageFrame.js.map +1 -1
  270. package/dist/react/core/widgets/ImageGallery.d.ts +2 -1
  271. package/dist/react/core/widgets/ImageGallery.js +380 -314
  272. package/dist/react/core/widgets/ImageGallery.js.map +1 -1
  273. package/dist/react/core/widgets/ImagePanel.d.ts +0 -1
  274. package/dist/react/core/widgets/ImagePanel.js +110 -101
  275. package/dist/react/core/widgets/ImagePanel.js.map +1 -1
  276. package/dist/react/core/widgets/LogViewer.d.ts +2 -3
  277. package/dist/react/core/widgets/LogViewer.js +711 -607
  278. package/dist/react/core/widgets/LogViewer.js.map +1 -1
  279. package/dist/react/core/widgets/MessageStream.d.ts +3 -4
  280. package/dist/react/core/widgets/MessageStream.js +514 -444
  281. package/dist/react/core/widgets/MessageStream.js.map +1 -1
  282. package/dist/react/core/widgets/MissionCalendar.d.ts +3 -4
  283. package/dist/react/core/widgets/MissionCalendar.js +1488 -1020
  284. package/dist/react/core/widgets/MissionCalendar.js.map +1 -1
  285. package/dist/react/core/widgets/PacketViewer.d.ts +2 -3
  286. package/dist/react/core/widgets/PacketViewer.js +550 -421
  287. package/dist/react/core/widgets/PacketViewer.js.map +1 -1
  288. package/dist/react/core/widgets/capture-placeholder.png.js +6 -5
  289. package/dist/react/core/widgets/capture-placeholder.png.js.map +1 -1
  290. package/dist/react/hooks/index.d.ts +5 -5
  291. package/dist/react/hooks/useAccessWindows.d.ts +0 -1
  292. package/dist/react/hooks/useCompactMode.d.ts +1 -1
  293. package/dist/react/hooks/useCompactMode.js +104 -58
  294. package/dist/react/hooks/useCompactMode.js.map +1 -1
  295. package/dist/react/hooks/useGroundTrackHistory.d.ts +0 -1
  296. package/dist/react/hooks/useSimulationScene.d.ts +1 -2
  297. package/dist/react/hooks/useSimulationScene.js +481 -374
  298. package/dist/react/hooks/useSimulationScene.js.map +1 -1
  299. package/dist/react/index.d.ts +3 -3
  300. package/dist/react/panels/LayerControlPanel.d.ts +1 -2
  301. package/dist/react/panels/LayerControlPanel.js +223 -180
  302. package/dist/react/panels/LayerControlPanel.js.map +1 -1
  303. package/dist/react/panels/ObjectInventoryPanel.d.ts +2 -3
  304. package/dist/react/panels/ObjectInventoryPanel.js +315 -250
  305. package/dist/react/panels/ObjectInventoryPanel.js.map +1 -1
  306. package/dist/react/panels/index.d.ts +1 -1
  307. package/dist/react/panels/index.js +1 -6
  308. package/dist/react/shared/ErrorBoundary.d.ts +1 -2
  309. package/dist/react/shared/ErrorBoundary.js +170 -139
  310. package/dist/react/shared/ErrorBoundary.js.map +1 -1
  311. package/dist/react/shared/Skeleton.d.ts +1 -2
  312. package/dist/react/shared/Skeleton.js +300 -301
  313. package/dist/react/shared/Skeleton.js.map +1 -1
  314. package/dist/react/theme/ThemeProvider.d.ts +2 -321
  315. package/dist/react/theme/ThemeProvider.js +313 -939
  316. package/dist/react/theme/ThemeProvider.js.map +1 -1
  317. package/dist/react/theme/cardAccent.d.ts +1 -2
  318. package/dist/react/theme/cardAccent.js +196 -126
  319. package/dist/react/theme/cardAccent.js.map +1 -1
  320. package/dist/react/theme/config.d.ts +0 -1
  321. package/dist/react/theme/config.js +47 -25
  322. package/dist/react/theme/config.js.map +1 -1
  323. package/dist/react/theme/index.d.ts +2 -2
  324. package/dist/react/theme/index.js +1 -16
  325. package/dist/react/theme/types.d.ts +332 -0
  326. package/dist/react/theme/types.js +39 -0
  327. package/dist/react/theme/types.js.map +1 -0
  328. package/dist/react/types.d.ts +8 -8
  329. package/dist/react/types.js +147 -47
  330. package/dist/react/types.js.map +1 -1
  331. package/dist/react/utils/categoryPalette.d.ts +0 -1
  332. package/dist/react/utils/categoryPalette.js +91 -102
  333. package/dist/react/utils/categoryPalette.js.map +1 -1
  334. package/dist/react/utils/index.d.ts +5 -5
  335. package/dist/react/utils/index.js +457 -371
  336. package/dist/react/utils/index.js.map +1 -1
  337. package/dist/react/visualizations/EclipseTimerCard.d.ts +0 -1
  338. package/dist/react/visualizations/LinkBudgetCard.d.ts +0 -1
  339. package/dist/react/visualizations/NavBallCard.d.ts +0 -1
  340. package/dist/react/visualizations/PropulsionCard.d.ts +1 -2
  341. package/dist/react/visualizations/SensorFootprintCard.d.ts +1 -2
  342. package/dist/react/visualizations/ThermalHeatmapCard.d.ts +0 -1
  343. package/dist/react/visualizations/index.d.ts +3 -3
  344. package/dist/react.d.ts +2 -1
  345. package/dist/react.js +17 -221
  346. package/dist/shaders/atmosphere.frag.js +6 -5
  347. package/dist/shaders/atmosphere.frag.js.map +1 -1
  348. package/dist/shaders/atmosphere.vert.js +6 -5
  349. package/dist/shaders/atmosphere.vert.js.map +1 -1
  350. package/dist/shaders/stars.frag.js +6 -5
  351. package/dist/shaders/stars.frag.js.map +1 -1
  352. package/dist/shaders/stars.vert.js +6 -5
  353. package/dist/shaders/stars.vert.js.map +1 -1
  354. package/dist/style.css +26 -3
  355. package/dist/tokens/core.d.ts +159 -0
  356. package/dist/tokens/core.js +144 -0
  357. package/dist/tokens/core.js.map +1 -0
  358. package/dist/tokens/css-vars.d.ts +213 -2
  359. package/dist/tokens/css-vars.js +590 -227
  360. package/dist/tokens/css-vars.js.map +1 -1
  361. package/dist/tokens/index.d.ts +31 -228
  362. package/dist/tokens/index.js +281 -366
  363. package/dist/tokens/index.js.map +1 -1
  364. package/dist/tokens/palettes/astro.d.ts +129 -0
  365. package/dist/tokens/palettes/astro.js +112 -0
  366. package/dist/tokens/palettes/astro.js.map +1 -0
  367. package/dist/tokens/palettes/index.d.ts +288 -0
  368. package/dist/tokens/palettes/index.js +35 -0
  369. package/dist/tokens/palettes/index.js.map +1 -0
  370. package/dist/tokens/palettes/tailwind.d.ts +324 -0
  371. package/dist/tokens/palettes/tailwind.js +201 -0
  372. package/dist/tokens/palettes/tailwind.js.map +1 -0
  373. package/dist/tokens/palettes/zendir.d.ts +126 -0
  374. package/dist/tokens/palettes/zendir.js +92 -0
  375. package/dist/tokens/palettes/zendir.js.map +1 -0
  376. package/dist/tokens/themes.d.ts +30 -0
  377. package/dist/tokens/themes.js +704 -0
  378. package/dist/tokens/themes.js.map +1 -0
  379. package/dist/tokens/tokens.css +533 -155
  380. package/dist/types/index.d.ts +2 -2
  381. package/package.json +310 -313
  382. package/dist/index.js.map +0 -1
  383. package/dist/react/3d/index.js.map +0 -1
  384. package/dist/react/astro/index.js.map +0 -1
  385. package/dist/react/cards/index.js.map +0 -1
  386. package/dist/react/charts/index.js.map +0 -1
  387. package/dist/react/core/index.js.map +0 -1
  388. package/dist/react/panels/index.js.map +0 -1
  389. package/dist/react/theme/astro-tokens.d.ts +0 -153
  390. package/dist/react/theme/index.js.map +0 -1
  391. package/dist/react.js.map +0 -1
@@ -1,742 +1,1065 @@
1
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { memo, useState, useMemo } from "react";
3
1
  import { useTheme } from "../theme/ThemeProvider.js";
4
- import { StatusIndicator } from "../astro/StatusIndicator.js";
5
- import { DataValue } from "../core/data/DataValue.js";
6
- import { getPropertyConfig } from "../core/data/propertyConfig.js";
2
+ import { Icon } from "../core/display/Icon.js";
3
+ import { classNames, deriveBatteryStatus, formatTime, getStatusColor, normalizeStatus, safeNumber } from "../utils/index.js";
7
4
  import { AstroIcon } from "../core/display/AstroIcon.js";
8
- import { CardHeader } from "../core/display/CardHeader.js";
9
5
  import { HeaderIconWithStatus } from "../core/display/HeaderIconWithStatus.js";
10
- import { Icon } from "../core/display/Icon.js";
6
+ import { CardHeader } from "../core/display/CardHeader.js";
7
+ import { getPropertyConfig } from "../core/data/propertyConfig.js";
8
+ import { DataValue } from "../core/data/DataValue.js";
11
9
  import { useCardBorderStyle } from "../context/DisplaySettingsContext.js";
12
- import { classNames, getStatusColor, formatTime, safeNumber, normalizeStatus, deriveBatteryStatus } from "../utils/index.js";
13
10
  import { useCompactMode } from "../hooks/useCompactMode.js";
11
+ import { StatusIndicator } from "../astro/StatusIndicator.js";
12
+ import { memo, useMemo, useState } from "react";
13
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
+ //#region src/react/cards/TelemetryCard.tsx
15
+ /**
16
+ * @zendir/ui - TelemetryCard Component
17
+ *
18
+ * Enterprise-grade spacecraft telemetry data card.
19
+ *
20
+ * AstroUXDS Compliance:
21
+ * - Status colors used semantically (battery level, health status)
22
+ * - Dual-coded status indicators (color + shape via StatusIndicator)
23
+ * - Zendir accent colors for non-status elements (icons, decorative)
24
+ * - Tabular numbers with fontVariantNumeric for data display
25
+ * - Sentence-case labels per Tier 3 compliance
26
+ *
27
+ * Features:
28
+ * - Full null-safety with graceful fallbacks
29
+ * - WCAG 2.1 AA accessibility
30
+ * - Subsystem toggles (power, attitude, comms)
31
+ * - Anomaly alerts
32
+ * - Loading and empty states
33
+ */
34
+ /**
35
+ * Get health status level
36
+ * Uses normalizeStatus utility to convert SDK terms to StatusLevel
37
+ */
14
38
  function getHealthStatus(healthStatus) {
15
- return normalizeStatus(healthStatus);
39
+ return normalizeStatus(healthStatus);
16
40
  }
41
+ /**
42
+ * Get battery status based on level
43
+ * @deprecated Use deriveBatteryStatus from utils instead
44
+ */
17
45
  function getBatteryStatus(level) {
18
- return deriveBatteryStatus(level);
46
+ return deriveBatteryStatus(level);
19
47
  }
20
- const TelemetryCard = memo(function TelemetryCard2({
21
- telemetry,
22
- spacecraftName,
23
- showPower = true,
24
- showAttitude = true,
25
- showComms = true,
26
- loading = false,
27
- className = "",
28
- compact = false,
29
- defaultExpanded = false,
30
- onPinChange
31
- }) {
32
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
33
- const { tokens, theme, prefersReducedMotion } = useTheme();
34
- const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
35
- const isBoldVariant = theme === "transparent-bold";
36
- const isMinimalVariant = theme === "transparent-minimal";
37
- const useGlassMode = isBoldVariant || isMinimalVariant;
38
- const glassAccentColor = tokens.colors.accent.primary;
39
- const glassAccentMuted = `${glassAccentColor}66`;
40
- const cardBg = isTransparentTheme ? "transparent" : tokens.colors.background.surface;
41
- const cardGlass = isTransparentTheme ? {
42
- backdropFilter: "blur(12px)",
43
- WebkitBackdropFilter: "blur(12px)"
44
- } : {};
45
- const cardBorderStyle = useCardBorderStyle(tokens, isTransparentTheme);
46
- const glassContainerStyle = useGlassMode ? {
47
- backgroundColor: "rgba(10, 15, 25, 0.35)",
48
- backdropFilter: "blur(12px)",
49
- WebkitBackdropFilter: "blur(12px)",
50
- border: `1px solid ${glassAccentMuted}`,
51
- borderTop: isBoldVariant ? `2px solid ${glassAccentColor}` : `1px solid ${glassAccentColor}`
52
- } : {};
53
- const { expanded, isPinned, isHovered: _isHovered, handlers, transitionDuration: compactTransition } = useCompactMode({
54
- compact,
55
- defaultExpanded,
56
- onPinChange
57
- });
58
- const [_isAnimating, _setIsAnimating] = useState(false);
59
- const animationDuration = prefersReducedMotion ? 0 : 250;
60
- const animationEasing = "cubic-bezier(0.4, 0, 0.2, 1)";
61
- const healthStatus = useMemo(
62
- () => {
63
- var _a2;
64
- return getHealthStatus((_a2 = telemetry == null ? void 0 : telemetry.health) == null ? void 0 : _a2.status);
65
- },
66
- [(_a = telemetry == null ? void 0 : telemetry.health) == null ? void 0 : _a.status]
67
- );
68
- const batteryStatus = useMemo(
69
- () => {
70
- var _a2;
71
- return getBatteryStatus((_a2 = telemetry == null ? void 0 : telemetry.power) == null ? void 0 : _a2.batteryLevel);
72
- },
73
- [(_b = telemetry == null ? void 0 : telemetry.power) == null ? void 0 : _b.batteryLevel]
74
- );
75
- const transitionDuration = prefersReducedMotion ? "0ms" : "200ms";
76
- if (loading) {
77
- return /* @__PURE__ */ jsxs(
78
- "div",
79
- {
80
- className: classNames("zendir-telemetry-card", "loading", className),
81
- role: "article",
82
- "aria-busy": "true",
83
- "aria-label": "Loading telemetry data",
84
- style: {
85
- backgroundColor: cardBg,
86
- ...cardGlass,
87
- ...cardBorderStyle,
88
- borderRadius: tokens.borderRadius.lg,
89
- padding: tokens.spacing.md,
90
- minHeight: 200
91
- },
92
- children: [
93
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 16 }, children: [
94
- /* @__PURE__ */ jsx(
95
- "div",
96
- {
97
- style: {
98
- width: 24,
99
- height: 24,
100
- borderRadius: 4,
101
- backgroundColor: "rgba(255,255,255,0.1)"
102
- }
103
- }
104
- ),
105
- /* @__PURE__ */ jsx(
106
- "div",
107
- {
108
- style: {
109
- height: 16,
110
- width: "40%",
111
- backgroundColor: "rgba(255,255,255,0.1)",
112
- borderRadius: 4
113
- }
114
- }
115
- )
116
- ] }),
117
- [1, 2, 3].map((i) => /* @__PURE__ */ jsxs("div", { style: { marginBottom: 16 }, children: [
118
- /* @__PURE__ */ jsx(
119
- "div",
120
- {
121
- style: {
122
- height: 12,
123
- width: "30%",
124
- backgroundColor: "rgba(255,255,255,0.08)",
125
- borderRadius: 2,
126
- marginBottom: 8
127
- }
128
- }
129
- ),
130
- /* @__PURE__ */ jsx(
131
- "div",
132
- {
133
- style: {
134
- display: "grid",
135
- gridTemplateColumns: "repeat(2, 1fr)",
136
- gap: 8
137
- },
138
- children: [1, 2, 3, 4].map((j) => /* @__PURE__ */ jsx(
139
- "div",
140
- {
141
- style: {
142
- height: 32,
143
- backgroundColor: "rgba(255,255,255,0.06)",
144
- borderRadius: 4
145
- }
146
- },
147
- j
148
- ))
149
- }
150
- )
151
- ] }, i))
152
- ]
153
- }
154
- );
155
- }
156
- if (!telemetry) {
157
- return /* @__PURE__ */ jsxs(
158
- "div",
159
- {
160
- className: classNames("zendir-telemetry-card", "empty", className),
161
- role: "article",
162
- "aria-label": "No telemetry data",
163
- style: {
164
- backgroundColor: cardBg,
165
- ...cardGlass,
166
- ...tokens.colors.border.cardStyleDashed ?? {},
167
- borderRadius: tokens.borderRadius.lg,
168
- padding: tokens.spacing.lg,
169
- textAlign: "center",
170
- color: tokens.colors.text.tertiary
171
- },
172
- children: [
173
- /* @__PURE__ */ jsx(AstroIcon, { name: "antenna", size: "normal", label: "", style: { opacity: 0.5 } }),
174
- /* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0 0", fontSize: tokens.typography.body[2].fontSize }, children: "No telemetry data available" })
175
- ]
176
- }
177
- );
178
- }
179
- const sectionStyle = {
180
- marginBottom: tokens.spacing.md,
181
- paddingBottom: tokens.spacing.md,
182
- borderBottom: `1px solid ${tokens.colors.border.muted}`
183
- };
184
- const iconColumnWidth = 20;
185
- const iconGap = tokens.spacing.sm;
186
- const rowGap = tokens.spacing.smd;
187
- const sectionGridColumns = `${iconColumnWidth}px 1fr ${iconColumnWidth}px 1fr`;
188
- const CompactMetric = ({
189
- icon,
190
- label,
191
- value,
192
- color,
193
- astroIcon
194
- }) => /* @__PURE__ */ jsxs("div", { style: {
195
- display: "flex",
196
- alignItems: "center",
197
- gap: 3,
198
- padding: `2px 0`
199
- }, children: [
200
- astroIcon ? /* @__PURE__ */ jsx(AstroIcon, { name: astroIcon, size: 12, color: color ?? tokens.colors.text.secondary }) : icon ? /* @__PURE__ */ jsx(Icon, { name: icon, size: 12, color: color ?? tokens.colors.text.secondary }) : null,
201
- /* @__PURE__ */ jsx("span", { style: {
202
- fontSize: tokens.typography.fontSize.micro,
203
- // 0.5625rem / 9px (AstroUXDS micro)
204
- fontWeight: tokens.typography.fontWeight.medium,
205
- fontFamily: tokens.typography.fontFamily.primary,
206
- // Public Sans Roboto fallback → system stack
207
- color: tokens.colors.text.tertiary,
208
- textTransform: "uppercase",
209
- minWidth: 8
210
- }, children: label.charAt(0) }),
211
- /* @__PURE__ */ jsx("span", { style: {
212
- fontVariantNumeric: "tabular-nums",
213
- fontFamily: tokens.typography.fontFamily.mono,
214
- fontSize: tokens.typography.fontSize.xs,
215
- color: color ?? tokens.colors.text.primary,
216
- fontWeight: tokens.typography.fontWeight.medium
217
- }, children: value })
218
- ] });
219
- const renderCompactContent = () => {
220
- var _a2, _b2, _c2, _d2;
221
- const power = (telemetry == null ? void 0 : telemetry.power) ?? ((_a2 = telemetry == null ? void 0 : telemetry.subsystems) == null ? void 0 : _a2.power);
222
- const attitude = (telemetry == null ? void 0 : telemetry.attitude) ?? ((_b2 = telemetry == null ? void 0 : telemetry.subsystems) == null ? void 0 : _b2.attitude);
223
- const comms = (telemetry == null ? void 0 : telemetry.communications) ?? ((_c2 = telemetry == null ? void 0 : telemetry.subsystems) == null ? void 0 : _c2.comms);
224
- const thermal = (_d2 = telemetry == null ? void 0 : telemetry.subsystems) == null ? void 0 : _d2.thermal;
225
- const compactStatusColor = getStatusColor(healthStatus);
226
- return /* @__PURE__ */ jsxs(Fragment, { children: [
227
- /* @__PURE__ */ jsxs("div", { style: {
228
- display: "flex",
229
- alignItems: "center",
230
- justifyContent: "space-between",
231
- marginBottom: tokens.spacing.xs,
232
- paddingBottom: tokens.spacing.xs,
233
- borderBottom: useGlassMode ? "none" : `1px solid ${tokens.colors.border.muted}`,
234
- position: "relative",
235
- zIndex: 1
236
- }, children: [
237
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.sm, minWidth: 0, flex: 1 }, children: [
238
- /* @__PURE__ */ jsx(
239
- HeaderIconWithStatus,
240
- {
241
- icon: "antenna-receive",
242
- size: 20,
243
- status: healthStatus,
244
- statusColor: compactStatusColor
245
- }
246
- ),
247
- /* @__PURE__ */ jsx("span", { style: {
248
- fontWeight: tokens.typography.fontWeight.semibold,
249
- fontSize: tokens.typography.fontSize.sm,
250
- fontFamily: tokens.typography.fontFamily.primary,
251
- color: useGlassMode ? glassAccentColor : void 0,
252
- textShadow: useGlassMode ? `0 0 16px ${glassAccentMuted}` : void 0,
253
- whiteSpace: "nowrap",
254
- overflow: "hidden",
255
- textOverflow: "ellipsis",
256
- minWidth: 0
257
- }, children: spacecraftName ? spacecraftName.split(" ")[0] : "Telemetry" }),
258
- useGlassMode && /* @__PURE__ */ jsx("div", { style: {
259
- flex: 1,
260
- height: isBoldVariant ? "2px" : "1px",
261
- minWidth: 20,
262
- background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`,
263
- boxShadow: isBoldVariant ? `0 0 8px ${glassAccentMuted}` : void 0
264
- } })
265
- ] }),
266
- /* @__PURE__ */ jsx("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.xs, flexShrink: 0 }, children: isPinned && /* @__PURE__ */ jsx(Icon, { name: "lock", size: 10, color: tokens.colors.accent.primary }) })
267
- ] }),
268
- /* @__PURE__ */ jsxs("div", { style: {
269
- display: "grid",
270
- gridTemplateColumns: "repeat(3, 1fr)",
271
- gap: `${tokens.spacing.xs} ${tokens.spacing.sm}`
272
- }, children: [
273
- showPower && power && /* @__PURE__ */ jsxs(Fragment, { children: [
274
- power.batteryLevel !== void 0 && /* @__PURE__ */ jsx(
275
- CompactMetric,
276
- {
277
- icon: "battery",
278
- label: "Battery",
279
- value: `${safeNumber(power.batteryLevel, 0)}%`,
280
- color: getStatusColor(batteryStatus)
281
- }
282
- ),
283
- (power.solarGeneration ?? power.solarArrayOutput) !== void 0 && /* @__PURE__ */ jsx(
284
- CompactMetric,
285
- {
286
- astroIcon: "solar",
287
- label: "Solar",
288
- value: `${safeNumber(power.solarGeneration ?? power.solarArrayOutput, 1)}W`,
289
- color: tokens.colors.status.standby
290
- }
291
- ),
292
- power.voltage !== void 0 && /* @__PURE__ */ jsx(
293
- CompactMetric,
294
- {
295
- astroIcon: "propulsion-power",
296
- label: "Voltage",
297
- value: `${safeNumber(power.voltage, 1)}V`
298
- }
299
- )
300
- ] }),
301
- showAttitude && attitude && /* @__PURE__ */ jsxs(Fragment, { children: [
302
- attitude.pointingError !== void 0 && /* @__PURE__ */ jsx(
303
- CompactMetric,
304
- {
305
- astroIcon: "explore",
306
- label: "Pointing",
307
- value: `${safeNumber(attitude.pointingError, 2)}°`
308
- }
309
- ),
310
- attitude.targetMode && /* @__PURE__ */ jsx(
311
- CompactMetric,
312
- {
313
- astroIcon: "explore",
314
- label: "Mode",
315
- value: attitude.targetMode
316
- }
317
- )
318
- ] }),
319
- thermal && /* @__PURE__ */ jsx(Fragment, { children: thermal.cpuTemp !== void 0 && /* @__PURE__ */ jsx(
320
- CompactMetric,
321
- {
322
- icon: "thermometer",
323
- label: "CPU",
324
- value: `${safeNumber(thermal.cpuTemp, 0)}°C`,
325
- color: thermal.cpuTemp > 50 ? tokens.colors.status.caution : void 0
326
- }
327
- ) }),
328
- showComms && comms && /* @__PURE__ */ jsxs(Fragment, { children: [
329
- comms.signalStrength !== void 0 && /* @__PURE__ */ jsx(
330
- CompactMetric,
331
- {
332
- astroIcon: "antenna",
333
- label: "Signal",
334
- value: `${safeNumber(comms.signalStrength, 0)}%`
335
- }
336
- ),
337
- (comms.downlinkRate ?? comms.dataRate) !== void 0 && /* @__PURE__ */ jsx(
338
- CompactMetric,
339
- {
340
- astroIcon: "antenna-transmit",
341
- label: "Rate",
342
- value: `${safeNumber(comms.downlinkRate ?? comms.dataRate, 0)}Mb`
343
- }
344
- ),
345
- comms.transmitterStatus && /* @__PURE__ */ jsx(
346
- CompactMetric,
347
- {
348
- astroIcon: "antenna-receive",
349
- label: "TX",
350
- value: comms.transmitterStatus === "transmitting" ? "ON" : "OFF",
351
- color: comms.transmitterStatus === "transmitting" ? tokens.colors.status.normal : tokens.colors.status.off
352
- }
353
- )
354
- ] })
355
- ] })
356
- ] });
357
- };
358
- if (compact) {
359
- return /* @__PURE__ */ jsxs(
360
- "article",
361
- {
362
- className: classNames("zendir-telemetry-card", "compact", expanded ? "expanded" : "", className),
363
- ...handlers,
364
- "aria-label": spacecraftName ? `${spacecraftName} Telemetry${expanded ? "" : " (compact)"}` : "Telemetry Data",
365
- style: {
366
- position: "relative",
367
- overflow: "hidden",
368
- // Use glass container style for bold/minimal themes
369
- ...useGlassMode ? glassContainerStyle : {
370
- backgroundColor: cardBg,
371
- ...cardGlass,
372
- ...cardBorderStyle
373
- },
374
- borderRadius: tokens.borderRadius.lg,
375
- padding: expanded ? tokens.spacing.md : tokens.spacing.sm,
376
- fontFamily: tokens.typography.fontFamily.primary,
377
- color: tokens.colors.text.primary,
378
- fontSize: expanded ? tokens.typography.fontSize.base : tokens.typography.fontSize.sm,
379
- cursor: "pointer",
380
- transition: `all ${animationDuration}ms ${animationEasing}`,
381
- boxShadow: expanded ? `0 12px 40px rgba(0,0,0,0.4), 0 0 0 1px ${tokens.colors.accent.primary}30` : "none",
382
- zIndex: expanded ? 50 : 1
383
- },
384
- children: [
385
- useGlassMode && /* @__PURE__ */ jsx(
386
- "div",
387
- {
388
- style: {
389
- position: "absolute",
390
- inset: 0,
391
- background: "linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)",
392
- pointerEvents: "none",
393
- zIndex: 0
394
- }
395
- }
396
- ),
397
- expanded ? (
398
- // Full expanded content - resolve data with fallbacks like compact view
399
- (() => {
400
- var _a2, _b2, _c2, _d2, _e2, _f2;
401
- const power = (telemetry == null ? void 0 : telemetry.power) ?? ((_a2 = telemetry == null ? void 0 : telemetry.subsystems) == null ? void 0 : _a2.power);
402
- const attitude = (telemetry == null ? void 0 : telemetry.attitude) ?? ((_b2 = telemetry == null ? void 0 : telemetry.subsystems) == null ? void 0 : _b2.attitude);
403
- const comms = (telemetry == null ? void 0 : telemetry.communications) ?? ((_c2 = telemetry == null ? void 0 : telemetry.subsystems) == null ? void 0 : _c2.comms);
404
- return /* @__PURE__ */ jsxs(Fragment, { children: [
405
- /* @__PURE__ */ jsxs(
406
- "header",
407
- {
408
- style: {
409
- display: "flex",
410
- justifyContent: "space-between",
411
- alignItems: "center",
412
- marginBottom: tokens.spacing.md
413
- },
414
- children: [
415
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.sm }, children: [
416
- /* @__PURE__ */ jsx(
417
- HeaderIconWithStatus,
418
- {
419
- icon: "antenna-receive",
420
- size: 24,
421
- status: healthStatus
422
- }
423
- ),
424
- /* @__PURE__ */ jsx(
425
- "h3",
426
- {
427
- style: {
428
- margin: 0,
429
- fontSize: tokens.typography.fontSize.md,
430
- fontWeight: tokens.typography.fontWeight.semibold
431
- },
432
- children: spacecraftName ? `${spacecraftName} Telemetry` : "Telemetry"
433
- }
434
- ),
435
- isPinned && /* @__PURE__ */ jsx(Icon, { name: "lock", size: 12, color: tokens.colors.accent.primary, style: { marginLeft: 4 } })
436
- ] }),
437
- /* @__PURE__ */ jsx(StatusIndicator, { status: healthStatus, label: healthStatus, small: true })
438
- ]
439
- }
440
- ),
441
- showPower && /* @__PURE__ */ jsxs("section", { style: sectionStyle, "aria-label": "Power subsystem", children: [
442
- /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: sectionGridColumns, gap: `${rowGap} ${iconGap}`, alignItems: "center" }, children: [
443
- /* @__PURE__ */ jsx(AstroIcon, { name: "propulsion-power", size: 12, color: tokens.colors.text.tertiary }),
444
- /* @__PURE__ */ jsx("h4", { style: { margin: 0, gridColumn: "2 / -1", fontSize: tokens.typography.fontSize.xs, fontWeight: tokens.typography.fontWeight.medium, color: tokens.colors.text.secondary }, children: "Power" }),
445
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("battery").icon, size: 16, color: getStatusColor(batteryStatus) }),
446
- /* @__PURE__ */ jsx(DataValue, { property: "battery", value: power == null ? void 0 : power.batteryLevel, size: "sm", variant: "card", showIcon: false }),
447
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("voltage").icon, size: 16, color: tokens.colors.text.tertiary }),
448
- /* @__PURE__ */ jsx(DataValue, { property: "voltage", value: power == null ? void 0 : power.voltage, size: "sm", variant: "card", showIcon: false }),
449
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("solarPower").icon, size: 16, color: tokens.colors.text.tertiary }),
450
- /* @__PURE__ */ jsx(DataValue, { property: "solarPower", value: (power == null ? void 0 : power.solarGeneration) ?? (power == null ? void 0 : power.solarArrayOutput), size: "sm", variant: "card", status: "standby", showIcon: false }),
451
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("load").icon, size: 16, color: tokens.colors.text.tertiary }),
452
- /* @__PURE__ */ jsx(DataValue, { property: "load", value: power == null ? void 0 : power.consumption, size: "sm", variant: "card", showIcon: false })
453
- ] }),
454
- /* @__PURE__ */ jsx(
455
- "div",
456
- {
457
- style: {
458
- marginTop: tokens.spacing.sm,
459
- height: 4,
460
- backgroundColor: tokens.colors.border.muted,
461
- borderRadius: 2,
462
- overflow: "hidden"
463
- },
464
- children: /* @__PURE__ */ jsx(
465
- "div",
466
- {
467
- role: "progressbar",
468
- "aria-valuenow": (power == null ? void 0 : power.batteryLevel) ?? 0,
469
- "aria-valuemin": 0,
470
- "aria-valuemax": 100,
471
- "aria-label": "Battery level",
472
- style: {
473
- height: "100%",
474
- width: `${Math.min(100, Math.max(0, (power == null ? void 0 : power.batteryLevel) ?? 0))}%`,
475
- backgroundColor: getStatusColor(batteryStatus),
476
- borderRadius: 2,
477
- transition: `width ${transitionDuration} ease-out`
478
- }
479
- }
480
- )
481
- }
482
- )
483
- ] }),
484
- showAttitude && /* @__PURE__ */ jsx("section", { style: sectionStyle, "aria-label": "Attitude subsystem", children: /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: sectionGridColumns, gap: `${rowGap} ${iconGap}`, alignItems: "center" }, children: [
485
- /* @__PURE__ */ jsx(AstroIcon, { name: "explore", size: 12, color: tokens.colors.text.tertiary }),
486
- /* @__PURE__ */ jsx("h4", { style: { margin: 0, gridColumn: "2 / -1", fontSize: tokens.typography.fontSize.xs, fontWeight: tokens.typography.fontWeight.medium, color: tokens.colors.text.secondary }, children: "Attitude" }),
487
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("roll").icon, size: 16, color: tokens.colors.text.tertiary }),
488
- /* @__PURE__ */ jsx(DataValue, { property: "roll", value: ((_d2 = attitude == null ? void 0 : attitude.eulerAngles) == null ? void 0 : _d2.roll) ?? (attitude == null ? void 0 : attitude.pointingError), size: "sm", variant: "card", showStatus: false, showIcon: false }),
489
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("pitch").icon, size: 16, color: tokens.colors.text.tertiary }),
490
- /* @__PURE__ */ jsx(DataValue, { property: "pitch", value: (_e2 = attitude == null ? void 0 : attitude.eulerAngles) == null ? void 0 : _e2.pitch, size: "sm", variant: "card", showStatus: false, showIcon: false }),
491
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("yaw").icon, size: 16, color: tokens.colors.text.tertiary }),
492
- /* @__PURE__ */ jsx(DataValue, { property: "yaw", value: (_f2 = attitude == null ? void 0 : attitude.eulerAngles) == null ? void 0 : _f2.yaw, size: "sm", variant: "card", showStatus: false, showIcon: false }),
493
- /* @__PURE__ */ jsx(AstroIcon, { name: "explore", size: 16, color: tokens.colors.text.tertiary }),
494
- /* @__PURE__ */ jsx(DataValue, { label: "Mode", icon: "explore", value: (attitude == null ? void 0 : attitude.targetMode) ?? "--", size: "sm", variant: "card", showStatus: false, showIcon: false })
495
- ] }) }),
496
- showComms && /* @__PURE__ */ jsx("section", { style: { marginBottom: tokens.spacing.sm }, "aria-label": "Communications subsystem", children: /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: sectionGridColumns, gap: `${rowGap} ${iconGap}`, alignItems: "center" }, children: [
497
- /* @__PURE__ */ jsx(AstroIcon, { name: "antenna", size: 12, color: tokens.colors.text.tertiary }),
498
- /* @__PURE__ */ jsx("h4", { style: { margin: 0, gridColumn: "2 / -1", fontSize: tokens.typography.fontSize.xs, fontWeight: tokens.typography.fontWeight.medium, color: tokens.colors.text.secondary }, children: "Communications" }),
499
- /* @__PURE__ */ jsx(AstroIcon, { name: "antenna-transmit", size: 16, color: tokens.colors.text.tertiary }),
500
- /* @__PURE__ */ jsx(DataValue, { label: "Status", icon: "antenna-transmit", value: (comms == null ? void 0 : comms.transmitterStatus) ?? (comms == null ? void 0 : comms.status) ?? "--", size: "sm", variant: "card", showStatus: false, showIcon: false }),
501
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("signalStrength").icon, size: 16, color: tokens.colors.text.tertiary }),
502
- /* @__PURE__ */ jsx(DataValue, { property: "signalStrength", value: comms == null ? void 0 : comms.signalStrength, size: "sm", variant: "card", showStatus: false, showIcon: false }),
503
- /* @__PURE__ */ jsx(AstroIcon, { name: "antenna-receive", size: 16, color: tokens.colors.text.tertiary }),
504
- /* @__PURE__ */ jsx(DataValue, { label: "Transmitted", icon: "antenna-receive", value: (comms == null ? void 0 : comms.packetsTransmitted) ?? (comms == null ? void 0 : comms.dataRate) ?? "--", size: "sm", variant: "card", showStatus: false, showIcon: false }),
505
- /* @__PURE__ */ jsx("span", { style: { gridColumn: "4 / -1" } })
506
- ] }) }),
507
- (telemetry == null ? void 0 : telemetry.timestamp) && /* @__PURE__ */ jsx(
508
- "time",
509
- {
510
- dateTime: telemetry.timestamp,
511
- style: {
512
- display: "block",
513
- fontSize: tokens.typography.fontSize.xs,
514
- color: tokens.colors.text.tertiary,
515
- marginTop: tokens.spacing.sm,
516
- fontVariantNumeric: "tabular-nums"
517
- },
518
- children: formatTime(telemetry.timestamp)
519
- }
520
- )
521
- ] });
522
- })()
523
- ) : (
524
- // Compact content
525
- renderCompactContent()
526
- )
527
- ]
528
- }
529
- );
530
- }
531
- return /* @__PURE__ */ jsxs(
532
- "article",
533
- {
534
- className: classNames("zendir-telemetry-card", compact ? "expanded" : "", className),
535
- ...compact ? handlers : {},
536
- role: compact ? handlers.role : "article",
537
- tabIndex: compact ? handlers.tabIndex : void 0,
538
- "aria-expanded": compact ? handlers["aria-expanded"] : void 0,
539
- "aria-label": spacecraftName ? `${spacecraftName} Telemetry` : "Telemetry Data",
540
- style: {
541
- position: "relative",
542
- overflow: "hidden",
543
- ...useGlassMode ? glassContainerStyle : {
544
- backgroundColor: cardBg,
545
- ...cardGlass,
546
- ...cardBorderStyle
547
- },
548
- borderRadius: tokens.borderRadius.lg,
549
- padding: tokens.spacing.md,
550
- fontFamily: tokens.typography.fontFamily.primary,
551
- color: tokens.colors.text.primary,
552
- fontSize: tokens.typography.fontSize.sm,
553
- cursor: compact ? "pointer" : void 0,
554
- transition: compact ? `all ${compactTransition} ease-out` : void 0
555
- },
556
- children: [
557
- useGlassMode && /* @__PURE__ */ jsx(
558
- "div",
559
- {
560
- style: {
561
- position: "absolute",
562
- inset: 0,
563
- background: "linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)",
564
- pointerEvents: "none",
565
- zIndex: 0
566
- }
567
- }
568
- ),
569
- /* @__PURE__ */ jsx(
570
- CardHeader,
571
- {
572
- icon: "antenna-receive",
573
- title: spacecraftName ? `${spacecraftName} Telemetry` : "Telemetry",
574
- status: healthStatus,
575
- isPinned: compact && isPinned
576
- }
577
- ),
578
- showPower && /* @__PURE__ */ jsxs("section", { style: sectionStyle, "aria-label": "Power subsystem", children: [
579
- /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: sectionGridColumns, gap: `${rowGap} ${iconGap}`, alignItems: "center" }, children: [
580
- /* @__PURE__ */ jsx(AstroIcon, { name: "propulsion-power", size: 12, color: tokens.colors.text.tertiary }),
581
- /* @__PURE__ */ jsx("h4", { style: { margin: 0, gridColumn: "2 / -1", fontSize: tokens.typography.fontSize.xs, fontWeight: tokens.typography.fontWeight.medium, color: tokens.colors.text.secondary }, children: "Power" }),
582
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("battery").icon, size: 16, color: getStatusColor(batteryStatus) }),
583
- /* @__PURE__ */ jsx(DataValue, { property: "battery", value: (_c = telemetry.power) == null ? void 0 : _c.batteryLevel, size: "sm", variant: "card", showIcon: false }),
584
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("voltage").icon, size: 16, color: tokens.colors.text.tertiary }),
585
- /* @__PURE__ */ jsx(DataValue, { property: "voltage", value: (_d = telemetry.power) == null ? void 0 : _d.voltage, size: "sm", variant: "card", showIcon: false }),
586
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("solarPower").icon, size: 16, color: tokens.colors.text.tertiary }),
587
- /* @__PURE__ */ jsx(DataValue, { property: "solarPower", value: (_e = telemetry.power) == null ? void 0 : _e.solarGeneration, size: "sm", variant: "card", status: "standby", showIcon: false }),
588
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("load").icon, size: 16, color: tokens.colors.text.tertiary }),
589
- /* @__PURE__ */ jsx(DataValue, { property: "load", value: (_f = telemetry.power) == null ? void 0 : _f.consumption, size: "sm", variant: "card", showIcon: false })
590
- ] }),
591
- /* @__PURE__ */ jsx(
592
- "div",
593
- {
594
- style: {
595
- marginTop: tokens.spacing.sm,
596
- height: 4,
597
- backgroundColor: tokens.colors.border.muted,
598
- borderRadius: 2,
599
- overflow: "hidden"
600
- },
601
- children: /* @__PURE__ */ jsx(
602
- "div",
603
- {
604
- role: "progressbar",
605
- "aria-valuenow": ((_g = telemetry.power) == null ? void 0 : _g.batteryLevel) ?? 0,
606
- "aria-valuemin": 0,
607
- "aria-valuemax": 100,
608
- "aria-label": "Battery level",
609
- style: {
610
- height: "100%",
611
- width: `${Math.min(100, Math.max(0, ((_h = telemetry.power) == null ? void 0 : _h.batteryLevel) ?? 0))}%`,
612
- backgroundColor: getStatusColor(batteryStatus),
613
- borderRadius: 2,
614
- transition: `width ${transitionDuration} ease-out`
615
- }
616
- }
617
- )
618
- }
619
- )
620
- ] }),
621
- showAttitude && /* @__PURE__ */ jsxs("section", { style: sectionStyle, "aria-label": "Attitude subsystem", children: [
622
- /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: sectionGridColumns, gap: `${rowGap} ${iconGap}`, alignItems: "center" }, children: [
623
- /* @__PURE__ */ jsx(AstroIcon, { name: "explore", size: 12, color: tokens.colors.text.tertiary }),
624
- /* @__PURE__ */ jsx("h4", { style: { margin: 0, gridColumn: "2 / -1", fontSize: tokens.typography.fontSize.xs, fontWeight: tokens.typography.fontWeight.medium, color: tokens.colors.text.secondary }, children: "Attitude" }),
625
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("roll").icon, size: 16, color: tokens.colors.text.tertiary }),
626
- /* @__PURE__ */ jsx(DataValue, { property: "roll", value: (_j = (_i = telemetry.attitude) == null ? void 0 : _i.eulerAngles) == null ? void 0 : _j.roll, size: "sm", variant: "card", showStatus: false, showIcon: false }),
627
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("pitch").icon, size: 16, color: tokens.colors.text.tertiary }),
628
- /* @__PURE__ */ jsx(DataValue, { property: "pitch", value: (_l = (_k = telemetry.attitude) == null ? void 0 : _k.eulerAngles) == null ? void 0 : _l.pitch, size: "sm", variant: "card", showStatus: false, showIcon: false }),
629
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("yaw").icon, size: 16, color: tokens.colors.text.tertiary }),
630
- /* @__PURE__ */ jsx(DataValue, { property: "yaw", value: (_n = (_m = telemetry.attitude) == null ? void 0 : _m.eulerAngles) == null ? void 0 : _n.yaw, size: "sm", variant: "card", showStatus: false, showIcon: false }),
631
- /* @__PURE__ */ jsx(AstroIcon, { name: "explore", size: 16, color: tokens.colors.text.tertiary }),
632
- /* @__PURE__ */ jsx(DataValue, { label: "Mode", icon: "explore", value: ((_o = telemetry.attitude) == null ? void 0 : _o.targetMode) ?? "--", size: "sm", variant: "card", showStatus: false, showIcon: false })
633
- ] }),
634
- ((_p = telemetry.attitude) == null ? void 0 : _p.pointingError) !== void 0 && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: iconGap, marginTop: tokens.spacing.sm }, children: [
635
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("pointingError").icon, size: 16, color: tokens.colors.text.tertiary }),
636
- /* @__PURE__ */ jsx(DataValue, { property: "pointingError", value: telemetry.attitude.pointingError, size: "sm", variant: "inline", showIcon: false })
637
- ] })
638
- ] }),
639
- showComms && /* @__PURE__ */ jsx("section", { style: { marginBottom: tokens.spacing.md }, "aria-label": "Communications subsystem", children: /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: sectionGridColumns, gap: `${rowGap} ${iconGap}`, alignItems: "center" }, children: [
640
- /* @__PURE__ */ jsx(AstroIcon, { name: "antenna", size: 12, color: tokens.colors.text.tertiary }),
641
- /* @__PURE__ */ jsx("h4", { style: { margin: 0, gridColumn: "2 / -1", fontSize: tokens.typography.fontSize.xs, fontWeight: tokens.typography.fontWeight.medium, color: tokens.colors.text.secondary }, children: "Communications" }),
642
- /* @__PURE__ */ jsx(AstroIcon, { name: "antenna-transmit", size: 16, color: tokens.colors.text.tertiary }),
643
- /* @__PURE__ */ jsx(
644
- DataValue,
645
- {
646
- label: "Status",
647
- icon: "antenna-transmit",
648
- value: ((_q = telemetry.communications) == null ? void 0 : _q.transmitterStatus) ?? "--",
649
- size: "sm",
650
- variant: "card",
651
- showIcon: false,
652
- status: ((_r = telemetry.communications) == null ? void 0 : _r.transmitterStatus) === "transmitting" ? "normal" : ((_s = telemetry.communications) == null ? void 0 : _s.transmitterStatus) === "error" ? "critical" : "off"
653
- }
654
- ),
655
- /* @__PURE__ */ jsx(AstroIcon, { name: getPropertyConfig("queue").icon, size: 16, color: tokens.colors.text.tertiary }),
656
- /* @__PURE__ */ jsx(DataValue, { property: "queue", value: (_t = telemetry.communications) == null ? void 0 : _t.packetsQueued, size: "sm", variant: "card", showIcon: false }),
657
- /* @__PURE__ */ jsx(AstroIcon, { name: "antenna-receive", size: 16, color: tokens.colors.text.tertiary }),
658
- /* @__PURE__ */ jsx(
659
- DataValue,
660
- {
661
- label: "Transmitted",
662
- icon: "antenna-receive",
663
- value: safeNumber((((_u = telemetry.communications) == null ? void 0 : _u.bytesTransmitted) ?? 0) / 1024, 1),
664
- unit: "KB",
665
- size: "sm",
666
- variant: "card",
667
- showStatus: false,
668
- showIcon: false
669
- }
670
- ),
671
- /* @__PURE__ */ jsx("span", { style: { gridColumn: "4 / -1" } })
672
- ] }) }),
673
- ((_v = telemetry.health) == null ? void 0 : _v.anomalies) && telemetry.health.anomalies.length > 0 && /* @__PURE__ */ jsxs(
674
- "div",
675
- {
676
- role: "alert",
677
- style: {
678
- backgroundColor: `${tokens.colors.status.critical}15`,
679
- border: `1px solid ${tokens.colors.status.critical}40`,
680
- borderRadius: tokens.borderRadius.md,
681
- padding: tokens.spacing.sm,
682
- marginTop: tokens.spacing.md
683
- },
684
- children: [
685
- /* @__PURE__ */ jsxs(
686
- "h4",
687
- {
688
- style: {
689
- margin: `0 0 ${tokens.spacing.xs} 0`,
690
- fontSize: tokens.typography.fontSize.xs,
691
- fontWeight: tokens.typography.fontWeight.medium,
692
- color: tokens.colors.status.critical,
693
- display: "flex",
694
- alignItems: "center",
695
- gap: 4
696
- },
697
- children: [
698
- "⚠️ Anomalies (",
699
- telemetry.health.anomalies.length,
700
- ")"
701
- ]
702
- }
703
- ),
704
- /* @__PURE__ */ jsx("ul", { style: { margin: 0, paddingLeft: 16 }, children: telemetry.health.anomalies.map((anomaly, idx) => /* @__PURE__ */ jsx(
705
- "li",
706
- {
707
- style: {
708
- fontSize: tokens.typography.fontSize.xs,
709
- color: tokens.colors.status.critical,
710
- marginTop: 2
711
- },
712
- children: typeof anomaly === "object" && anomaly !== null && "message" in anomaly ? anomaly.message : String(anomaly)
713
- },
714
- idx
715
- )) })
716
- ]
717
- }
718
- ),
719
- /* @__PURE__ */ jsx(
720
- "footer",
721
- {
722
- style: {
723
- marginTop: tokens.spacing.md,
724
- fontSize: tokens.typography.fontSize.xs,
725
- color: tokens.colors.text.secondary,
726
- // WCAG AA compliant - 4.5:1 contrast
727
- textAlign: "right"
728
- },
729
- children: /* @__PURE__ */ jsxs("time", { dateTime: telemetry.timestamp, children: [
730
- formatTime(telemetry.timestamp),
731
- " UTC"
732
- ] })
733
- }
734
- )
735
- ]
736
- }
737
- );
48
+ /**
49
+ * TelemetryCard - Displays spacecraft telemetry data
50
+ *
51
+ * @example
52
+ * ```tsx
53
+ * <TelemetryCard
54
+ * telemetry={telemetryData}
55
+ * spacecraftName="ISS"
56
+ * showPower
57
+ * showAttitude
58
+ * showComms
59
+ * />
60
+ * ```
61
+ */
62
+ var TelemetryCard = memo(function TelemetryCard({ telemetry, spacecraftName, showPower = true, showAttitude = true, showComms = true, loading = false, className = "", compact = false, defaultExpanded = false, onPinChange }) {
63
+ const { tokens, theme, prefersReducedMotion } = useTheme();
64
+ const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
65
+ const isBoldVariant = theme === "transparent-bold";
66
+ const useGlassMode = isBoldVariant || theme === "transparent-minimal";
67
+ const glassAccentColor = tokens.colors.accent.primary;
68
+ const glassAccentMuted = `${glassAccentColor}66`;
69
+ const cardBg = isTransparentTheme ? "transparent" : tokens.colors.background.surface;
70
+ const cardGlass = isTransparentTheme ? {
71
+ backdropFilter: "blur(12px)",
72
+ WebkitBackdropFilter: "blur(12px)"
73
+ } : {};
74
+ const cardBorderStyle = useCardBorderStyle(tokens, isTransparentTheme);
75
+ const glassContainerStyle = useGlassMode ? {
76
+ backgroundColor: "rgba(10, 15, 25, 0.35)",
77
+ backdropFilter: "blur(12px)",
78
+ WebkitBackdropFilter: "blur(12px)",
79
+ border: `1px solid ${glassAccentMuted}`,
80
+ borderTop: isBoldVariant ? `2px solid ${glassAccentColor}` : `1px solid ${glassAccentColor}`
81
+ } : {};
82
+ const { expanded, isPinned, isHovered: _isHovered, handlers, transitionDuration: compactTransition } = useCompactMode({
83
+ compact,
84
+ defaultExpanded,
85
+ onPinChange
86
+ });
87
+ const [_isAnimating, _setIsAnimating] = useState(false);
88
+ const animationDuration = prefersReducedMotion ? 0 : 250;
89
+ const animationEasing = "cubic-bezier(0.4, 0, 0.2, 1)";
90
+ const healthStatus = useMemo(() => getHealthStatus(telemetry?.health?.status), [telemetry?.health?.status]);
91
+ const batteryStatus = useMemo(() => getBatteryStatus(telemetry?.power?.batteryLevel), [telemetry?.power?.batteryLevel]);
92
+ const transitionDuration = prefersReducedMotion ? "0ms" : "200ms";
93
+ if (loading) return /* @__PURE__ */ jsxs("div", {
94
+ className: classNames("zendir-telemetry-card", "loading", className),
95
+ role: "article",
96
+ "aria-busy": "true",
97
+ "aria-label": "Loading telemetry data",
98
+ style: {
99
+ backgroundColor: cardBg,
100
+ ...cardGlass,
101
+ ...cardBorderStyle,
102
+ borderRadius: tokens.borderRadius.lg,
103
+ padding: tokens.spacing.md,
104
+ minHeight: 200
105
+ },
106
+ children: [/* @__PURE__ */ jsxs("div", {
107
+ style: {
108
+ display: "flex",
109
+ alignItems: "center",
110
+ gap: 8,
111
+ marginBottom: 16
112
+ },
113
+ children: [/* @__PURE__ */ jsx("div", { style: {
114
+ width: 24,
115
+ height: 24,
116
+ borderRadius: 4,
117
+ backgroundColor: "rgba(255,255,255,0.1)"
118
+ } }), /* @__PURE__ */ jsx("div", { style: {
119
+ height: 16,
120
+ width: "40%",
121
+ backgroundColor: "rgba(255,255,255,0.1)",
122
+ borderRadius: 4
123
+ } })]
124
+ }), [
125
+ 1,
126
+ 2,
127
+ 3
128
+ ].map((i) => /* @__PURE__ */ jsxs("div", {
129
+ style: { marginBottom: 16 },
130
+ children: [/* @__PURE__ */ jsx("div", { style: {
131
+ height: 12,
132
+ width: "30%",
133
+ backgroundColor: "rgba(255,255,255,0.08)",
134
+ borderRadius: 2,
135
+ marginBottom: 8
136
+ } }), /* @__PURE__ */ jsx("div", {
137
+ style: {
138
+ display: "grid",
139
+ gridTemplateColumns: "repeat(2, 1fr)",
140
+ gap: 8
141
+ },
142
+ children: [
143
+ 1,
144
+ 2,
145
+ 3,
146
+ 4
147
+ ].map((j) => /* @__PURE__ */ jsx("div", { style: {
148
+ height: 32,
149
+ backgroundColor: "rgba(255,255,255,0.06)",
150
+ borderRadius: 4
151
+ } }, j))
152
+ })]
153
+ }, i))]
154
+ });
155
+ if (!telemetry) return /* @__PURE__ */ jsxs("div", {
156
+ className: classNames("zendir-telemetry-card", "empty", className),
157
+ role: "article",
158
+ "aria-label": "No telemetry data",
159
+ style: {
160
+ backgroundColor: cardBg,
161
+ ...cardGlass,
162
+ ...tokens.colors.border.cardStyleDashed ?? {},
163
+ borderRadius: tokens.borderRadius.lg,
164
+ padding: tokens.spacing.lg,
165
+ textAlign: "center",
166
+ color: tokens.colors.text.tertiary
167
+ },
168
+ children: [/* @__PURE__ */ jsx(AstroIcon, {
169
+ name: "antenna",
170
+ size: "normal",
171
+ label: "",
172
+ style: { opacity: .5 }
173
+ }), /* @__PURE__ */ jsx("p", {
174
+ style: {
175
+ margin: "8px 0 0 0",
176
+ fontSize: tokens.typography.body[2].fontSize
177
+ },
178
+ children: "No telemetry data available"
179
+ })]
180
+ });
181
+ const sectionStyle = {
182
+ marginBottom: tokens.spacing.md,
183
+ paddingBottom: tokens.spacing.md,
184
+ borderBottom: `1px solid ${tokens.colors.border.muted}`
185
+ };
186
+ /** Fixed width so all section and metric icons align on one vertical line */
187
+ const iconColumnWidth = 20;
188
+ const iconGap = tokens.spacing.sm;
189
+ const rowGap = tokens.spacing.smd;
190
+ const sectionGridColumns = `${iconColumnWidth}px 1fr ${iconColumnWidth}px 1fr`;
191
+ const CompactMetric = ({ icon, label, value, color, astroIcon }) => /* @__PURE__ */ jsxs("div", {
192
+ style: {
193
+ display: "flex",
194
+ alignItems: "center",
195
+ gap: 3,
196
+ padding: `2px 0`
197
+ },
198
+ children: [
199
+ astroIcon ? /* @__PURE__ */ jsx(AstroIcon, {
200
+ name: astroIcon,
201
+ size: 12,
202
+ color: color ?? tokens.colors.text.secondary
203
+ }) : icon ? /* @__PURE__ */ jsx(Icon, {
204
+ name: icon,
205
+ size: 12,
206
+ color: color ?? tokens.colors.text.secondary
207
+ }) : null,
208
+ /* @__PURE__ */ jsx("span", {
209
+ style: {
210
+ fontSize: tokens.typography.fontSize.micro,
211
+ fontWeight: tokens.typography.fontWeight.medium,
212
+ fontFamily: tokens.typography.fontFamily.primary,
213
+ color: tokens.colors.text.tertiary,
214
+ textTransform: "uppercase",
215
+ minWidth: 8
216
+ },
217
+ children: label.charAt(0)
218
+ }),
219
+ /* @__PURE__ */ jsx("span", {
220
+ style: {
221
+ fontVariantNumeric: "tabular-nums",
222
+ fontFamily: tokens.typography.fontFamily.mono,
223
+ fontSize: tokens.typography.fontSize.xs,
224
+ color: color ?? tokens.colors.text.primary,
225
+ fontWeight: tokens.typography.fontWeight.medium
226
+ },
227
+ children: value
228
+ })
229
+ ]
230
+ });
231
+ const renderCompactContent = () => {
232
+ const power = telemetry?.power ?? telemetry?.subsystems?.power;
233
+ const attitude = telemetry?.attitude ?? telemetry?.subsystems?.attitude;
234
+ const comms = telemetry?.communications ?? telemetry?.subsystems?.comms;
235
+ const thermal = telemetry?.subsystems?.thermal;
236
+ const compactStatusColor = getStatusColor(healthStatus);
237
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
238
+ style: {
239
+ display: "flex",
240
+ alignItems: "center",
241
+ justifyContent: "space-between",
242
+ marginBottom: tokens.spacing.xs,
243
+ paddingBottom: tokens.spacing.xs,
244
+ borderBottom: useGlassMode ? "none" : `1px solid ${tokens.colors.border.muted}`,
245
+ position: "relative",
246
+ zIndex: 1
247
+ },
248
+ children: [/* @__PURE__ */ jsxs("div", {
249
+ style: {
250
+ display: "flex",
251
+ alignItems: "center",
252
+ gap: tokens.spacing.sm,
253
+ minWidth: 0,
254
+ flex: 1
255
+ },
256
+ children: [
257
+ /* @__PURE__ */ jsx(HeaderIconWithStatus, {
258
+ icon: "antenna-receive",
259
+ size: 20,
260
+ status: healthStatus,
261
+ statusColor: compactStatusColor
262
+ }),
263
+ /* @__PURE__ */ jsx("span", {
264
+ style: {
265
+ fontWeight: tokens.typography.fontWeight.semibold,
266
+ fontSize: tokens.typography.fontSize.sm,
267
+ fontFamily: tokens.typography.fontFamily.primary,
268
+ color: useGlassMode ? glassAccentColor : void 0,
269
+ textShadow: useGlassMode ? `0 0 16px ${glassAccentMuted}` : void 0,
270
+ whiteSpace: "nowrap",
271
+ overflow: "hidden",
272
+ textOverflow: "ellipsis",
273
+ minWidth: 0
274
+ },
275
+ children: spacecraftName ? spacecraftName.split(" ")[0] : "Telemetry"
276
+ }),
277
+ useGlassMode && /* @__PURE__ */ jsx("div", { style: {
278
+ flex: 1,
279
+ height: isBoldVariant ? "2px" : "1px",
280
+ minWidth: 20,
281
+ background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`,
282
+ boxShadow: isBoldVariant ? `0 0 8px ${glassAccentMuted}` : void 0
283
+ } })
284
+ ]
285
+ }), /* @__PURE__ */ jsx("div", {
286
+ style: {
287
+ display: "flex",
288
+ alignItems: "center",
289
+ gap: tokens.spacing.xs,
290
+ flexShrink: 0
291
+ },
292
+ children: isPinned && /* @__PURE__ */ jsx(Icon, {
293
+ name: "lock",
294
+ size: 10,
295
+ color: tokens.colors.accent.primary
296
+ })
297
+ })]
298
+ }), /* @__PURE__ */ jsxs("div", {
299
+ style: {
300
+ display: "grid",
301
+ gridTemplateColumns: "repeat(3, 1fr)",
302
+ gap: `${tokens.spacing.xs} ${tokens.spacing.sm}`
303
+ },
304
+ children: [
305
+ showPower && power && /* @__PURE__ */ jsxs(Fragment, { children: [
306
+ power.batteryLevel !== void 0 && /* @__PURE__ */ jsx(CompactMetric, {
307
+ icon: "battery",
308
+ label: "Battery",
309
+ value: `${safeNumber(power.batteryLevel, 0)}%`,
310
+ color: getStatusColor(batteryStatus)
311
+ }),
312
+ (power.solarGeneration ?? power.solarArrayOutput) !== void 0 && /* @__PURE__ */ jsx(CompactMetric, {
313
+ astroIcon: "solar",
314
+ label: "Solar",
315
+ value: `${safeNumber(power.solarGeneration ?? power.solarArrayOutput, 1)}W`,
316
+ color: tokens.colors.status.standby
317
+ }),
318
+ power.voltage !== void 0 && /* @__PURE__ */ jsx(CompactMetric, {
319
+ astroIcon: "propulsion-power",
320
+ label: "Voltage",
321
+ value: `${safeNumber(power.voltage, 1)}V`
322
+ })
323
+ ] }),
324
+ showAttitude && attitude && /* @__PURE__ */ jsxs(Fragment, { children: [attitude.pointingError !== void 0 && /* @__PURE__ */ jsx(CompactMetric, {
325
+ astroIcon: "explore",
326
+ label: "Pointing",
327
+ value: `${safeNumber(attitude.pointingError, 2)}°`
328
+ }), attitude.targetMode && /* @__PURE__ */ jsx(CompactMetric, {
329
+ astroIcon: "explore",
330
+ label: "Mode",
331
+ value: attitude.targetMode
332
+ })] }),
333
+ thermal && /* @__PURE__ */ jsx(Fragment, { children: thermal.cpuTemp !== void 0 && /* @__PURE__ */ jsx(CompactMetric, {
334
+ icon: "thermometer",
335
+ label: "CPU",
336
+ value: `${safeNumber(thermal.cpuTemp, 0)}°C`,
337
+ color: thermal.cpuTemp > 50 ? tokens.colors.status.caution : void 0
338
+ }) }),
339
+ showComms && comms && /* @__PURE__ */ jsxs(Fragment, { children: [
340
+ comms.signalStrength !== void 0 && /* @__PURE__ */ jsx(CompactMetric, {
341
+ astroIcon: "antenna",
342
+ label: "Signal",
343
+ value: `${safeNumber(comms.signalStrength, 0)}%`
344
+ }),
345
+ (comms.downlinkRate ?? comms.dataRate) !== void 0 && /* @__PURE__ */ jsx(CompactMetric, {
346
+ astroIcon: "antenna-transmit",
347
+ label: "Rate",
348
+ value: `${safeNumber(comms.downlinkRate ?? comms.dataRate, 0)}Mb`
349
+ }),
350
+ comms.transmitterStatus && /* @__PURE__ */ jsx(CompactMetric, {
351
+ astroIcon: "antenna-receive",
352
+ label: "TX",
353
+ value: comms.transmitterStatus === "transmitting" ? "ON" : "OFF",
354
+ color: comms.transmitterStatus === "transmitting" ? tokens.colors.status.normal : tokens.colors.status.off
355
+ })
356
+ ] })
357
+ ]
358
+ })] });
359
+ };
360
+ if (compact) return /* @__PURE__ */ jsxs("article", {
361
+ className: classNames("zendir-telemetry-card", "compact", expanded ? "expanded" : "", className),
362
+ ...handlers,
363
+ "aria-label": spacecraftName ? `${spacecraftName} Telemetry${expanded ? "" : " (compact)"}` : "Telemetry Data",
364
+ style: {
365
+ position: "relative",
366
+ overflow: "hidden",
367
+ ...useGlassMode ? glassContainerStyle : {
368
+ backgroundColor: cardBg,
369
+ ...cardGlass,
370
+ ...cardBorderStyle
371
+ },
372
+ borderRadius: tokens.borderRadius.lg,
373
+ padding: expanded ? tokens.spacing.md : tokens.spacing.sm,
374
+ fontFamily: tokens.typography.fontFamily.primary,
375
+ color: tokens.colors.text.primary,
376
+ fontSize: expanded ? tokens.typography.fontSize.base : tokens.typography.fontSize.sm,
377
+ cursor: "pointer",
378
+ transition: `all ${animationDuration}ms ${animationEasing}`,
379
+ boxShadow: expanded ? `0 12px 40px rgba(0,0,0,0.4), 0 0 0 1px ${tokens.colors.accent.primary}30` : "none",
380
+ zIndex: expanded ? 50 : 1
381
+ },
382
+ children: [useGlassMode && /* @__PURE__ */ jsx("div", { style: {
383
+ position: "absolute",
384
+ inset: 0,
385
+ background: "linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)",
386
+ pointerEvents: "none",
387
+ zIndex: 0
388
+ } }), expanded ? (() => {
389
+ const power = telemetry?.power ?? telemetry?.subsystems?.power;
390
+ const attitude = telemetry?.attitude ?? telemetry?.subsystems?.attitude;
391
+ const comms = telemetry?.communications ?? telemetry?.subsystems?.comms;
392
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
393
+ /* @__PURE__ */ jsxs("header", {
394
+ style: {
395
+ display: "flex",
396
+ justifyContent: "space-between",
397
+ alignItems: "center",
398
+ marginBottom: tokens.spacing.md
399
+ },
400
+ children: [/* @__PURE__ */ jsxs("div", {
401
+ style: {
402
+ display: "flex",
403
+ alignItems: "center",
404
+ gap: tokens.spacing.sm
405
+ },
406
+ children: [
407
+ /* @__PURE__ */ jsx(HeaderIconWithStatus, {
408
+ icon: "antenna-receive",
409
+ size: 24,
410
+ status: healthStatus
411
+ }),
412
+ /* @__PURE__ */ jsx("h3", {
413
+ style: {
414
+ margin: 0,
415
+ fontSize: tokens.typography.fontSize.md,
416
+ fontWeight: tokens.typography.fontWeight.semibold
417
+ },
418
+ children: spacecraftName ? `${spacecraftName} Telemetry` : "Telemetry"
419
+ }),
420
+ isPinned && /* @__PURE__ */ jsx(Icon, {
421
+ name: "lock",
422
+ size: 12,
423
+ color: tokens.colors.accent.primary,
424
+ style: { marginLeft: 4 }
425
+ })
426
+ ]
427
+ }), /* @__PURE__ */ jsx(StatusIndicator, {
428
+ status: healthStatus,
429
+ label: healthStatus,
430
+ small: true
431
+ })]
432
+ }),
433
+ showPower && /* @__PURE__ */ jsxs("section", {
434
+ style: sectionStyle,
435
+ "aria-label": "Power subsystem",
436
+ children: [/* @__PURE__ */ jsxs("div", {
437
+ style: {
438
+ display: "grid",
439
+ gridTemplateColumns: sectionGridColumns,
440
+ gap: `${rowGap} ${iconGap}`,
441
+ alignItems: "center"
442
+ },
443
+ children: [
444
+ /* @__PURE__ */ jsx(AstroIcon, {
445
+ name: "propulsion-power",
446
+ size: 12,
447
+ color: tokens.colors.text.tertiary
448
+ }),
449
+ /* @__PURE__ */ jsx("h4", {
450
+ style: {
451
+ margin: 0,
452
+ gridColumn: "2 / -1",
453
+ fontSize: tokens.typography.fontSize.xs,
454
+ fontWeight: tokens.typography.fontWeight.medium,
455
+ color: tokens.colors.text.secondary
456
+ },
457
+ children: "Power"
458
+ }),
459
+ /* @__PURE__ */ jsx(AstroIcon, {
460
+ name: getPropertyConfig("battery").icon,
461
+ size: 16,
462
+ color: getStatusColor(batteryStatus)
463
+ }),
464
+ /* @__PURE__ */ jsx(DataValue, {
465
+ property: "battery",
466
+ value: power?.batteryLevel,
467
+ size: "sm",
468
+ variant: "card",
469
+ showIcon: false
470
+ }),
471
+ /* @__PURE__ */ jsx(AstroIcon, {
472
+ name: getPropertyConfig("voltage").icon,
473
+ size: 16,
474
+ color: tokens.colors.text.tertiary
475
+ }),
476
+ /* @__PURE__ */ jsx(DataValue, {
477
+ property: "voltage",
478
+ value: power?.voltage,
479
+ size: "sm",
480
+ variant: "card",
481
+ showIcon: false
482
+ }),
483
+ /* @__PURE__ */ jsx(AstroIcon, {
484
+ name: getPropertyConfig("solarPower").icon,
485
+ size: 16,
486
+ color: tokens.colors.text.tertiary
487
+ }),
488
+ /* @__PURE__ */ jsx(DataValue, {
489
+ property: "solarPower",
490
+ value: power?.solarGeneration ?? power?.solarArrayOutput,
491
+ size: "sm",
492
+ variant: "card",
493
+ status: "standby",
494
+ showIcon: false
495
+ }),
496
+ /* @__PURE__ */ jsx(AstroIcon, {
497
+ name: getPropertyConfig("load").icon,
498
+ size: 16,
499
+ color: tokens.colors.text.tertiary
500
+ }),
501
+ /* @__PURE__ */ jsx(DataValue, {
502
+ property: "load",
503
+ value: power?.consumption,
504
+ size: "sm",
505
+ variant: "card",
506
+ showIcon: false
507
+ })
508
+ ]
509
+ }), /* @__PURE__ */ jsx("div", {
510
+ style: {
511
+ marginTop: tokens.spacing.sm,
512
+ height: 4,
513
+ backgroundColor: tokens.colors.border.muted,
514
+ borderRadius: 2,
515
+ overflow: "hidden"
516
+ },
517
+ children: /* @__PURE__ */ jsx("div", {
518
+ role: "progressbar",
519
+ "aria-valuenow": power?.batteryLevel ?? 0,
520
+ "aria-valuemin": 0,
521
+ "aria-valuemax": 100,
522
+ "aria-label": "Battery level",
523
+ style: {
524
+ height: "100%",
525
+ width: `${Math.min(100, Math.max(0, power?.batteryLevel ?? 0))}%`,
526
+ backgroundColor: getStatusColor(batteryStatus),
527
+ borderRadius: 2,
528
+ transition: `width ${transitionDuration} ease-out`
529
+ }
530
+ })
531
+ })]
532
+ }),
533
+ showAttitude && /* @__PURE__ */ jsx("section", {
534
+ style: sectionStyle,
535
+ "aria-label": "Attitude subsystem",
536
+ children: /* @__PURE__ */ jsxs("div", {
537
+ style: {
538
+ display: "grid",
539
+ gridTemplateColumns: sectionGridColumns,
540
+ gap: `${rowGap} ${iconGap}`,
541
+ alignItems: "center"
542
+ },
543
+ children: [
544
+ /* @__PURE__ */ jsx(AstroIcon, {
545
+ name: "explore",
546
+ size: 12,
547
+ color: tokens.colors.text.tertiary
548
+ }),
549
+ /* @__PURE__ */ jsx("h4", {
550
+ style: {
551
+ margin: 0,
552
+ gridColumn: "2 / -1",
553
+ fontSize: tokens.typography.fontSize.xs,
554
+ fontWeight: tokens.typography.fontWeight.medium,
555
+ color: tokens.colors.text.secondary
556
+ },
557
+ children: "Attitude"
558
+ }),
559
+ /* @__PURE__ */ jsx(AstroIcon, {
560
+ name: getPropertyConfig("roll").icon,
561
+ size: 16,
562
+ color: tokens.colors.text.tertiary
563
+ }),
564
+ /* @__PURE__ */ jsx(DataValue, {
565
+ property: "roll",
566
+ value: attitude?.eulerAngles?.roll ?? attitude?.pointingError,
567
+ size: "sm",
568
+ variant: "card",
569
+ showStatus: false,
570
+ showIcon: false
571
+ }),
572
+ /* @__PURE__ */ jsx(AstroIcon, {
573
+ name: getPropertyConfig("pitch").icon,
574
+ size: 16,
575
+ color: tokens.colors.text.tertiary
576
+ }),
577
+ /* @__PURE__ */ jsx(DataValue, {
578
+ property: "pitch",
579
+ value: attitude?.eulerAngles?.pitch,
580
+ size: "sm",
581
+ variant: "card",
582
+ showStatus: false,
583
+ showIcon: false
584
+ }),
585
+ /* @__PURE__ */ jsx(AstroIcon, {
586
+ name: getPropertyConfig("yaw").icon,
587
+ size: 16,
588
+ color: tokens.colors.text.tertiary
589
+ }),
590
+ /* @__PURE__ */ jsx(DataValue, {
591
+ property: "yaw",
592
+ value: attitude?.eulerAngles?.yaw,
593
+ size: "sm",
594
+ variant: "card",
595
+ showStatus: false,
596
+ showIcon: false
597
+ }),
598
+ /* @__PURE__ */ jsx(AstroIcon, {
599
+ name: "explore",
600
+ size: 16,
601
+ color: tokens.colors.text.tertiary
602
+ }),
603
+ /* @__PURE__ */ jsx(DataValue, {
604
+ label: "Mode",
605
+ icon: "explore",
606
+ value: attitude?.targetMode ?? "--",
607
+ size: "sm",
608
+ variant: "card",
609
+ showStatus: false,
610
+ showIcon: false
611
+ })
612
+ ]
613
+ })
614
+ }),
615
+ showComms && /* @__PURE__ */ jsx("section", {
616
+ style: { marginBottom: tokens.spacing.sm },
617
+ "aria-label": "Communications subsystem",
618
+ children: /* @__PURE__ */ jsxs("div", {
619
+ style: {
620
+ display: "grid",
621
+ gridTemplateColumns: sectionGridColumns,
622
+ gap: `${rowGap} ${iconGap}`,
623
+ alignItems: "center"
624
+ },
625
+ children: [
626
+ /* @__PURE__ */ jsx(AstroIcon, {
627
+ name: "antenna",
628
+ size: 12,
629
+ color: tokens.colors.text.tertiary
630
+ }),
631
+ /* @__PURE__ */ jsx("h4", {
632
+ style: {
633
+ margin: 0,
634
+ gridColumn: "2 / -1",
635
+ fontSize: tokens.typography.fontSize.xs,
636
+ fontWeight: tokens.typography.fontWeight.medium,
637
+ color: tokens.colors.text.secondary
638
+ },
639
+ children: "Communications"
640
+ }),
641
+ /* @__PURE__ */ jsx(AstroIcon, {
642
+ name: "antenna-transmit",
643
+ size: 16,
644
+ color: tokens.colors.text.tertiary
645
+ }),
646
+ /* @__PURE__ */ jsx(DataValue, {
647
+ label: "Status",
648
+ icon: "antenna-transmit",
649
+ value: comms?.transmitterStatus ?? comms?.status ?? "--",
650
+ size: "sm",
651
+ variant: "card",
652
+ showStatus: false,
653
+ showIcon: false
654
+ }),
655
+ /* @__PURE__ */ jsx(AstroIcon, {
656
+ name: getPropertyConfig("signalStrength").icon,
657
+ size: 16,
658
+ color: tokens.colors.text.tertiary
659
+ }),
660
+ /* @__PURE__ */ jsx(DataValue, {
661
+ property: "signalStrength",
662
+ value: comms?.signalStrength,
663
+ size: "sm",
664
+ variant: "card",
665
+ showStatus: false,
666
+ showIcon: false
667
+ }),
668
+ /* @__PURE__ */ jsx(AstroIcon, {
669
+ name: "antenna-receive",
670
+ size: 16,
671
+ color: tokens.colors.text.tertiary
672
+ }),
673
+ /* @__PURE__ */ jsx(DataValue, {
674
+ label: "Transmitted",
675
+ icon: "antenna-receive",
676
+ value: comms?.packetsTransmitted ?? comms?.dataRate ?? "--",
677
+ size: "sm",
678
+ variant: "card",
679
+ showStatus: false,
680
+ showIcon: false
681
+ }),
682
+ /* @__PURE__ */ jsx("span", { style: { gridColumn: "4 / -1" } })
683
+ ]
684
+ })
685
+ }),
686
+ telemetry?.timestamp && /* @__PURE__ */ jsx("time", {
687
+ dateTime: telemetry.timestamp,
688
+ style: {
689
+ display: "block",
690
+ fontSize: tokens.typography.fontSize.xs,
691
+ color: tokens.colors.text.tertiary,
692
+ marginTop: tokens.spacing.sm,
693
+ fontVariantNumeric: "tabular-nums"
694
+ },
695
+ children: formatTime(telemetry.timestamp)
696
+ })
697
+ ] });
698
+ })() : renderCompactContent()]
699
+ });
700
+ return /* @__PURE__ */ jsxs("article", {
701
+ className: classNames("zendir-telemetry-card", compact ? "expanded" : "", className),
702
+ ...compact ? handlers : {},
703
+ role: compact ? handlers.role : "article",
704
+ tabIndex: compact ? handlers.tabIndex : void 0,
705
+ "aria-expanded": compact ? handlers["aria-expanded"] : void 0,
706
+ "aria-label": spacecraftName ? `${spacecraftName} Telemetry` : "Telemetry Data",
707
+ style: {
708
+ position: "relative",
709
+ overflow: "hidden",
710
+ ...useGlassMode ? glassContainerStyle : {
711
+ backgroundColor: cardBg,
712
+ ...cardGlass,
713
+ ...cardBorderStyle
714
+ },
715
+ borderRadius: tokens.borderRadius.lg,
716
+ padding: tokens.spacing.md,
717
+ fontFamily: tokens.typography.fontFamily.primary,
718
+ color: tokens.colors.text.primary,
719
+ fontSize: tokens.typography.fontSize.sm,
720
+ cursor: compact ? "pointer" : void 0,
721
+ transition: compact ? `all ${compactTransition} ease-out` : void 0
722
+ },
723
+ children: [
724
+ useGlassMode && /* @__PURE__ */ jsx("div", { style: {
725
+ position: "absolute",
726
+ inset: 0,
727
+ background: "linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)",
728
+ pointerEvents: "none",
729
+ zIndex: 0
730
+ } }),
731
+ /* @__PURE__ */ jsx(CardHeader, {
732
+ icon: "antenna-receive",
733
+ title: spacecraftName ? `${spacecraftName} Telemetry` : "Telemetry",
734
+ status: healthStatus,
735
+ isPinned: compact && isPinned
736
+ }),
737
+ showPower && /* @__PURE__ */ jsxs("section", {
738
+ style: sectionStyle,
739
+ "aria-label": "Power subsystem",
740
+ children: [/* @__PURE__ */ jsxs("div", {
741
+ style: {
742
+ display: "grid",
743
+ gridTemplateColumns: sectionGridColumns,
744
+ gap: `${rowGap} ${iconGap}`,
745
+ alignItems: "center"
746
+ },
747
+ children: [
748
+ /* @__PURE__ */ jsx(AstroIcon, {
749
+ name: "propulsion-power",
750
+ size: 12,
751
+ color: tokens.colors.text.tertiary
752
+ }),
753
+ /* @__PURE__ */ jsx("h4", {
754
+ style: {
755
+ margin: 0,
756
+ gridColumn: "2 / -1",
757
+ fontSize: tokens.typography.fontSize.xs,
758
+ fontWeight: tokens.typography.fontWeight.medium,
759
+ color: tokens.colors.text.secondary
760
+ },
761
+ children: "Power"
762
+ }),
763
+ /* @__PURE__ */ jsx(AstroIcon, {
764
+ name: getPropertyConfig("battery").icon,
765
+ size: 16,
766
+ color: getStatusColor(batteryStatus)
767
+ }),
768
+ /* @__PURE__ */ jsx(DataValue, {
769
+ property: "battery",
770
+ value: telemetry.power?.batteryLevel,
771
+ size: "sm",
772
+ variant: "card",
773
+ showIcon: false
774
+ }),
775
+ /* @__PURE__ */ jsx(AstroIcon, {
776
+ name: getPropertyConfig("voltage").icon,
777
+ size: 16,
778
+ color: tokens.colors.text.tertiary
779
+ }),
780
+ /* @__PURE__ */ jsx(DataValue, {
781
+ property: "voltage",
782
+ value: telemetry.power?.voltage,
783
+ size: "sm",
784
+ variant: "card",
785
+ showIcon: false
786
+ }),
787
+ /* @__PURE__ */ jsx(AstroIcon, {
788
+ name: getPropertyConfig("solarPower").icon,
789
+ size: 16,
790
+ color: tokens.colors.text.tertiary
791
+ }),
792
+ /* @__PURE__ */ jsx(DataValue, {
793
+ property: "solarPower",
794
+ value: telemetry.power?.solarGeneration,
795
+ size: "sm",
796
+ variant: "card",
797
+ status: "standby",
798
+ showIcon: false
799
+ }),
800
+ /* @__PURE__ */ jsx(AstroIcon, {
801
+ name: getPropertyConfig("load").icon,
802
+ size: 16,
803
+ color: tokens.colors.text.tertiary
804
+ }),
805
+ /* @__PURE__ */ jsx(DataValue, {
806
+ property: "load",
807
+ value: telemetry.power?.consumption,
808
+ size: "sm",
809
+ variant: "card",
810
+ showIcon: false
811
+ })
812
+ ]
813
+ }), /* @__PURE__ */ jsx("div", {
814
+ style: {
815
+ marginTop: tokens.spacing.sm,
816
+ height: 4,
817
+ backgroundColor: tokens.colors.border.muted,
818
+ borderRadius: 2,
819
+ overflow: "hidden"
820
+ },
821
+ children: /* @__PURE__ */ jsx("div", {
822
+ role: "progressbar",
823
+ "aria-valuenow": telemetry.power?.batteryLevel ?? 0,
824
+ "aria-valuemin": 0,
825
+ "aria-valuemax": 100,
826
+ "aria-label": "Battery level",
827
+ style: {
828
+ height: "100%",
829
+ width: `${Math.min(100, Math.max(0, telemetry.power?.batteryLevel ?? 0))}%`,
830
+ backgroundColor: getStatusColor(batteryStatus),
831
+ borderRadius: 2,
832
+ transition: `width ${transitionDuration} ease-out`
833
+ }
834
+ })
835
+ })]
836
+ }),
837
+ showAttitude && /* @__PURE__ */ jsxs("section", {
838
+ style: sectionStyle,
839
+ "aria-label": "Attitude subsystem",
840
+ children: [/* @__PURE__ */ jsxs("div", {
841
+ style: {
842
+ display: "grid",
843
+ gridTemplateColumns: sectionGridColumns,
844
+ gap: `${rowGap} ${iconGap}`,
845
+ alignItems: "center"
846
+ },
847
+ children: [
848
+ /* @__PURE__ */ jsx(AstroIcon, {
849
+ name: "explore",
850
+ size: 12,
851
+ color: tokens.colors.text.tertiary
852
+ }),
853
+ /* @__PURE__ */ jsx("h4", {
854
+ style: {
855
+ margin: 0,
856
+ gridColumn: "2 / -1",
857
+ fontSize: tokens.typography.fontSize.xs,
858
+ fontWeight: tokens.typography.fontWeight.medium,
859
+ color: tokens.colors.text.secondary
860
+ },
861
+ children: "Attitude"
862
+ }),
863
+ /* @__PURE__ */ jsx(AstroIcon, {
864
+ name: getPropertyConfig("roll").icon,
865
+ size: 16,
866
+ color: tokens.colors.text.tertiary
867
+ }),
868
+ /* @__PURE__ */ jsx(DataValue, {
869
+ property: "roll",
870
+ value: telemetry.attitude?.eulerAngles?.roll,
871
+ size: "sm",
872
+ variant: "card",
873
+ showStatus: false,
874
+ showIcon: false
875
+ }),
876
+ /* @__PURE__ */ jsx(AstroIcon, {
877
+ name: getPropertyConfig("pitch").icon,
878
+ size: 16,
879
+ color: tokens.colors.text.tertiary
880
+ }),
881
+ /* @__PURE__ */ jsx(DataValue, {
882
+ property: "pitch",
883
+ value: telemetry.attitude?.eulerAngles?.pitch,
884
+ size: "sm",
885
+ variant: "card",
886
+ showStatus: false,
887
+ showIcon: false
888
+ }),
889
+ /* @__PURE__ */ jsx(AstroIcon, {
890
+ name: getPropertyConfig("yaw").icon,
891
+ size: 16,
892
+ color: tokens.colors.text.tertiary
893
+ }),
894
+ /* @__PURE__ */ jsx(DataValue, {
895
+ property: "yaw",
896
+ value: telemetry.attitude?.eulerAngles?.yaw,
897
+ size: "sm",
898
+ variant: "card",
899
+ showStatus: false,
900
+ showIcon: false
901
+ }),
902
+ /* @__PURE__ */ jsx(AstroIcon, {
903
+ name: "explore",
904
+ size: 16,
905
+ color: tokens.colors.text.tertiary
906
+ }),
907
+ /* @__PURE__ */ jsx(DataValue, {
908
+ label: "Mode",
909
+ icon: "explore",
910
+ value: telemetry.attitude?.targetMode ?? "--",
911
+ size: "sm",
912
+ variant: "card",
913
+ showStatus: false,
914
+ showIcon: false
915
+ })
916
+ ]
917
+ }), telemetry.attitude?.pointingError !== void 0 && /* @__PURE__ */ jsxs("div", {
918
+ style: {
919
+ display: "flex",
920
+ alignItems: "center",
921
+ gap: iconGap,
922
+ marginTop: tokens.spacing.sm
923
+ },
924
+ children: [/* @__PURE__ */ jsx(AstroIcon, {
925
+ name: getPropertyConfig("pointingError").icon,
926
+ size: 16,
927
+ color: tokens.colors.text.tertiary
928
+ }), /* @__PURE__ */ jsx(DataValue, {
929
+ property: "pointingError",
930
+ value: telemetry.attitude.pointingError,
931
+ size: "sm",
932
+ variant: "inline",
933
+ showIcon: false
934
+ })]
935
+ })]
936
+ }),
937
+ showComms && /* @__PURE__ */ jsx("section", {
938
+ style: { marginBottom: tokens.spacing.md },
939
+ "aria-label": "Communications subsystem",
940
+ children: /* @__PURE__ */ jsxs("div", {
941
+ style: {
942
+ display: "grid",
943
+ gridTemplateColumns: sectionGridColumns,
944
+ gap: `${rowGap} ${iconGap}`,
945
+ alignItems: "center"
946
+ },
947
+ children: [
948
+ /* @__PURE__ */ jsx(AstroIcon, {
949
+ name: "antenna",
950
+ size: 12,
951
+ color: tokens.colors.text.tertiary
952
+ }),
953
+ /* @__PURE__ */ jsx("h4", {
954
+ style: {
955
+ margin: 0,
956
+ gridColumn: "2 / -1",
957
+ fontSize: tokens.typography.fontSize.xs,
958
+ fontWeight: tokens.typography.fontWeight.medium,
959
+ color: tokens.colors.text.secondary
960
+ },
961
+ children: "Communications"
962
+ }),
963
+ /* @__PURE__ */ jsx(AstroIcon, {
964
+ name: "antenna-transmit",
965
+ size: 16,
966
+ color: tokens.colors.text.tertiary
967
+ }),
968
+ /* @__PURE__ */ jsx(DataValue, {
969
+ label: "Status",
970
+ icon: "antenna-transmit",
971
+ value: telemetry.communications?.transmitterStatus ?? "--",
972
+ size: "sm",
973
+ variant: "card",
974
+ showIcon: false,
975
+ status: telemetry.communications?.transmitterStatus === "transmitting" ? "normal" : telemetry.communications?.transmitterStatus === "error" ? "critical" : "off"
976
+ }),
977
+ /* @__PURE__ */ jsx(AstroIcon, {
978
+ name: getPropertyConfig("queue").icon,
979
+ size: 16,
980
+ color: tokens.colors.text.tertiary
981
+ }),
982
+ /* @__PURE__ */ jsx(DataValue, {
983
+ property: "queue",
984
+ value: telemetry.communications?.packetsQueued,
985
+ size: "sm",
986
+ variant: "card",
987
+ showIcon: false
988
+ }),
989
+ /* @__PURE__ */ jsx(AstroIcon, {
990
+ name: "antenna-receive",
991
+ size: 16,
992
+ color: tokens.colors.text.tertiary
993
+ }),
994
+ /* @__PURE__ */ jsx(DataValue, {
995
+ label: "Transmitted",
996
+ icon: "antenna-receive",
997
+ value: safeNumber((telemetry.communications?.bytesTransmitted ?? 0) / 1024, 1),
998
+ unit: "KB",
999
+ size: "sm",
1000
+ variant: "card",
1001
+ showStatus: false,
1002
+ showIcon: false
1003
+ }),
1004
+ /* @__PURE__ */ jsx("span", { style: { gridColumn: "4 / -1" } })
1005
+ ]
1006
+ })
1007
+ }),
1008
+ telemetry.health?.anomalies && telemetry.health.anomalies.length > 0 && /* @__PURE__ */ jsxs("div", {
1009
+ role: "alert",
1010
+ style: {
1011
+ backgroundColor: `${tokens.colors.status.critical}15`,
1012
+ border: `1px solid ${tokens.colors.status.critical}40`,
1013
+ borderRadius: tokens.borderRadius.md,
1014
+ padding: tokens.spacing.sm,
1015
+ marginTop: tokens.spacing.md
1016
+ },
1017
+ children: [/* @__PURE__ */ jsxs("h4", {
1018
+ style: {
1019
+ margin: `0 0 ${tokens.spacing.xs} 0`,
1020
+ fontSize: tokens.typography.fontSize.xs,
1021
+ fontWeight: tokens.typography.fontWeight.medium,
1022
+ color: tokens.colors.status.critical,
1023
+ display: "flex",
1024
+ alignItems: "center",
1025
+ gap: 4
1026
+ },
1027
+ children: [
1028
+ "⚠️ Anomalies (",
1029
+ telemetry.health.anomalies.length,
1030
+ ")"
1031
+ ]
1032
+ }), /* @__PURE__ */ jsx("ul", {
1033
+ style: {
1034
+ margin: 0,
1035
+ paddingLeft: 16
1036
+ },
1037
+ children: telemetry.health.anomalies.map((anomaly, idx) => /* @__PURE__ */ jsx("li", {
1038
+ style: {
1039
+ fontSize: tokens.typography.fontSize.xs,
1040
+ color: tokens.colors.status.critical,
1041
+ marginTop: 2
1042
+ },
1043
+ children: typeof anomaly === "object" && anomaly !== null && "message" in anomaly ? anomaly.message : String(anomaly)
1044
+ }, idx))
1045
+ })]
1046
+ }),
1047
+ /* @__PURE__ */ jsx("footer", {
1048
+ style: {
1049
+ marginTop: tokens.spacing.md,
1050
+ fontSize: tokens.typography.fontSize.xs,
1051
+ color: tokens.colors.text.secondary,
1052
+ textAlign: "right"
1053
+ },
1054
+ children: /* @__PURE__ */ jsxs("time", {
1055
+ dateTime: telemetry.timestamp,
1056
+ children: [formatTime(telemetry.timestamp), " UTC"]
1057
+ })
1058
+ })
1059
+ ]
1060
+ });
738
1061
  });
739
- export {
740
- TelemetryCard
741
- };
742
- //# sourceMappingURL=TelemetryCard.js.map
1062
+ //#endregion
1063
+ export { TelemetryCard };
1064
+
1065
+ //# sourceMappingURL=TelemetryCard.js.map