@zendir/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (359) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE +21 -0
  3. package/README.md +589 -0
  4. package/dist/index.d.ts +8 -0
  5. package/dist/index.js +421 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/react/3d/EarthViewer.d.ts +46 -0
  8. package/dist/react/3d/EarthViewer.js +836 -0
  9. package/dist/react/3d/EarthViewer.js.map +1 -0
  10. package/dist/react/3d/SolarSystemViewer.d.ts +43 -0
  11. package/dist/react/3d/SolarSystemViewer.js +372 -0
  12. package/dist/react/3d/SolarSystemViewer.js.map +1 -0
  13. package/dist/react/3d/ZenSpace3D.d.ts +16 -0
  14. package/dist/react/3d/ZenSpace3D.js +1253 -0
  15. package/dist/react/3d/ZenSpace3D.js.map +1 -0
  16. package/dist/react/3d/ZenSpace3DCesium.d.ts +9 -0
  17. package/dist/react/3d/ZenSpace3DCesium.js +186 -0
  18. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -0
  19. package/dist/react/3d/ZenSpace3DShaders.d.ts +78 -0
  20. package/dist/react/3d/ZenSpace3DShaders.js +94 -0
  21. package/dist/react/3d/ZenSpace3DShaders.js.map +1 -0
  22. package/dist/react/3d/ZenSpace3DTypes.d.ts +614 -0
  23. package/dist/react/3d/ZenSpace3DUtils.d.ts +183 -0
  24. package/dist/react/3d/ZenSpace3DUtils.js +213 -0
  25. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -0
  26. package/dist/react/3d/index.d.ts +23 -0
  27. package/dist/react/3d/threeLoader.d.ts +22 -0
  28. package/dist/react/3d/threeLoader.js +18 -0
  29. package/dist/react/3d/threeLoader.js.map +1 -0
  30. package/dist/react/astro/ClassificationBanner.d.ts +25 -0
  31. package/dist/react/astro/ClassificationBanner.js +83 -0
  32. package/dist/react/astro/ClassificationBanner.js.map +1 -0
  33. package/dist/react/astro/GlobalStatusBar.d.ts +42 -0
  34. package/dist/react/astro/GlobalStatusBar.js +165 -0
  35. package/dist/react/astro/GlobalStatusBar.js.map +1 -0
  36. package/dist/react/astro/MissionClock.d.ts +169 -0
  37. package/dist/react/astro/MissionClock.js +411 -0
  38. package/dist/react/astro/MissionClock.js.map +1 -0
  39. package/dist/react/astro/MonitoringIcon.d.ts +60 -0
  40. package/dist/react/astro/MonitoringIcon.js +369 -0
  41. package/dist/react/astro/MonitoringIcon.js.map +1 -0
  42. package/dist/react/astro/Notification.d.ts +42 -0
  43. package/dist/react/astro/Notification.js +156 -0
  44. package/dist/react/astro/Notification.js.map +1 -0
  45. package/dist/react/astro/Progress.d.ts +39 -0
  46. package/dist/react/astro/Progress.js +149 -0
  47. package/dist/react/astro/Progress.js.map +1 -0
  48. package/dist/react/astro/SimulationControls.d.ts +136 -0
  49. package/dist/react/astro/SimulationControls.js +668 -0
  50. package/dist/react/astro/SimulationControls.js.map +1 -0
  51. package/dist/react/astro/StatusIndicator.d.ts +34 -0
  52. package/dist/react/astro/StatusIndicator.js +189 -0
  53. package/dist/react/astro/StatusIndicator.js.map +1 -0
  54. package/dist/react/astro/UnifiedTimeline.d.ts +106 -0
  55. package/dist/react/astro/UnifiedTimeline.js +1768 -0
  56. package/dist/react/astro/UnifiedTimeline.js.map +1 -0
  57. package/dist/react/astro/index.d.ts +63 -0
  58. package/dist/react/cards/AccessCard.d.ts +37 -0
  59. package/dist/react/cards/AccessCard.js +410 -0
  60. package/dist/react/cards/AccessCard.js.map +1 -0
  61. package/dist/react/cards/OrbitCard.d.ts +31 -0
  62. package/dist/react/cards/OrbitCard.js +372 -0
  63. package/dist/react/cards/OrbitCard.js.map +1 -0
  64. package/dist/react/cards/SpacecraftCard.d.ts +54 -0
  65. package/dist/react/cards/SpacecraftCard.js +941 -0
  66. package/dist/react/cards/SpacecraftCard.js.map +1 -0
  67. package/dist/react/cards/TelemetryCard.d.ts +40 -0
  68. package/dist/react/cards/TelemetryCard.js +742 -0
  69. package/dist/react/cards/TelemetryCard.js.map +1 -0
  70. package/dist/react/cards/TelemetryStreamCard.d.ts +59 -0
  71. package/dist/react/cards/TelemetryStreamCard.js +309 -0
  72. package/dist/react/cards/TelemetryStreamCard.js.map +1 -0
  73. package/dist/react/cards/index.d.ts +13 -0
  74. package/dist/react/charts/GroundTrackMap.d.ts +112 -0
  75. package/dist/react/charts/GroundTrackMap.js +1123 -0
  76. package/dist/react/charts/GroundTrackMap.js.map +1 -0
  77. package/dist/react/charts/GroundTrackMapLeaflet.d.ts +26 -0
  78. package/dist/react/charts/GroundTrackMapLeaflet.js +571 -0
  79. package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -0
  80. package/dist/react/charts/groundTrackMapLeafletTiles.d.ts +22 -0
  81. package/dist/react/charts/groundTrackMapLeafletTiles.js +11 -0
  82. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -0
  83. package/dist/react/charts/groundTrackMapLeafletUtils.d.ts +24 -0
  84. package/dist/react/charts/groundTrackMapLeafletUtils.js +109 -0
  85. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -0
  86. package/dist/react/charts/index.d.ts +10 -0
  87. package/dist/react/charts/unified/AstroChart.d.ts +24 -0
  88. package/dist/react/charts/unified/AstroChart.js +1405 -0
  89. package/dist/react/charts/unified/AstroChart.js.map +1 -0
  90. package/dist/react/charts/unified/PowerOverviewChart.d.ts +73 -0
  91. package/dist/react/charts/unified/PowerOverviewChart.js +488 -0
  92. package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -0
  93. package/dist/react/charts/unified/domain.d.ts +845 -0
  94. package/dist/react/charts/unified/domain.js +3168 -0
  95. package/dist/react/charts/unified/domain.js.map +1 -0
  96. package/dist/react/charts/unified/generators.d.ts +276 -0
  97. package/dist/react/charts/unified/generators.js +518 -0
  98. package/dist/react/charts/unified/generators.js.map +1 -0
  99. package/dist/react/charts/unified/index.d.ts +55 -0
  100. package/dist/react/charts/unified/presets.d.ts +290 -0
  101. package/dist/react/charts/unified/presets.js +999 -0
  102. package/dist/react/charts/unified/presets.js.map +1 -0
  103. package/dist/react/charts/unified/sync.d.ts +69 -0
  104. package/dist/react/charts/unified/sync.js +219 -0
  105. package/dist/react/charts/unified/sync.js.map +1 -0
  106. package/dist/react/charts/unified/theme.d.ts +447 -0
  107. package/dist/react/charts/unified/theme.js +562 -0
  108. package/dist/react/charts/unified/theme.js.map +1 -0
  109. package/dist/react/charts/unified/types.d.ts +826 -0
  110. package/dist/react/charts/unified/useChartStream.d.ts +58 -0
  111. package/dist/react/charts/unified/useChartStream.js +226 -0
  112. package/dist/react/charts/unified/useChartStream.js.map +1 -0
  113. package/dist/react/chatgpt/AppCard.d.ts +59 -0
  114. package/dist/react/chatgpt/AppCard.js +306 -0
  115. package/dist/react/chatgpt/AppCard.js.map +1 -0
  116. package/dist/react/chatgpt/ChatGPTCard.d.ts +6 -0
  117. package/dist/react/chatgpt/index.d.ts +167 -0
  118. package/dist/react/chatgpt/index.js +166 -0
  119. package/dist/react/chatgpt/index.js.map +1 -0
  120. package/dist/react/context/DisplaySettingsContext.d.ts +107 -0
  121. package/dist/react/context/DisplaySettingsContext.js +169 -0
  122. package/dist/react/context/DisplaySettingsContext.js.map +1 -0
  123. package/dist/react/context/index.d.ts +5 -0
  124. package/dist/react/core/ActivityPlanner.d.ts +45 -0
  125. package/dist/react/core/ActivityPlanner.js +532 -0
  126. package/dist/react/core/ActivityPlanner.js.map +1 -0
  127. package/dist/react/core/AppBar.d.ts +71 -0
  128. package/dist/react/core/AppBar.js +817 -0
  129. package/dist/react/core/AppBar.js.map +1 -0
  130. package/dist/react/core/AstroIcon.d.ts +84 -0
  131. package/dist/react/core/AstroIcon.js +1243 -0
  132. package/dist/react/core/AstroIcon.js.map +1 -0
  133. package/dist/react/core/Badge.d.ts +27 -0
  134. package/dist/react/core/Badge.js +134 -0
  135. package/dist/react/core/Badge.js.map +1 -0
  136. package/dist/react/core/Button.d.ts +26 -0
  137. package/dist/react/core/Button.js +306 -0
  138. package/dist/react/core/Button.js.map +1 -0
  139. package/dist/react/core/CardHeader.d.ts +34 -0
  140. package/dist/react/core/CardHeader.js +316 -0
  141. package/dist/react/core/CardHeader.js.map +1 -0
  142. package/dist/react/core/ChatPanel.d.ts +627 -0
  143. package/dist/react/core/ChatPanel.js +1144 -0
  144. package/dist/react/core/ChatPanel.js.map +1 -0
  145. package/dist/react/core/Checkbox.d.ts +26 -0
  146. package/dist/react/core/Checkbox.js +130 -0
  147. package/dist/react/core/Checkbox.js.map +1 -0
  148. package/dist/react/core/ColorPickerPanel.d.ts +25 -0
  149. package/dist/react/core/ColorPickerPanel.js +293 -0
  150. package/dist/react/core/ColorPickerPanel.js.map +1 -0
  151. package/dist/react/core/CommandBuilder.d.ts +74 -0
  152. package/dist/react/core/CommandBuilder.js +518 -0
  153. package/dist/react/core/CommandBuilder.js.map +1 -0
  154. package/dist/react/core/ConfirmDialog.d.ts +45 -0
  155. package/dist/react/core/ConfirmDialog.js +315 -0
  156. package/dist/react/core/ConfirmDialog.js.map +1 -0
  157. package/dist/react/core/ConnectionForm.d.ts +57 -0
  158. package/dist/react/core/ConnectionForm.js +496 -0
  159. package/dist/react/core/ConnectionForm.js.map +1 -0
  160. package/dist/react/core/Container.d.ts +51 -0
  161. package/dist/react/core/Container.js +670 -0
  162. package/dist/react/core/Container.js.map +1 -0
  163. package/dist/react/core/CopyButton.d.ts +39 -0
  164. package/dist/react/core/CopyButton.js +105 -0
  165. package/dist/react/core/CopyButton.js.map +1 -0
  166. package/dist/react/core/DataTable.d.ts +113 -0
  167. package/dist/react/core/DataTable.js +446 -0
  168. package/dist/react/core/DataTable.js.map +1 -0
  169. package/dist/react/core/DataValue.d.ts +64 -0
  170. package/dist/react/core/DataValue.js +545 -0
  171. package/dist/react/core/DataValue.js.map +1 -0
  172. package/dist/react/core/Dialog.d.ts +32 -0
  173. package/dist/react/core/Dialog.js +201 -0
  174. package/dist/react/core/Dialog.js.map +1 -0
  175. package/dist/react/core/FileExplorer.d.ts +65 -0
  176. package/dist/react/core/FileExplorer.js +520 -0
  177. package/dist/react/core/FileExplorer.js.map +1 -0
  178. package/dist/react/core/GlassCard.d.ts +129 -0
  179. package/dist/react/core/GlassCard.js +375 -0
  180. package/dist/react/core/GlassCard.js.map +1 -0
  181. package/dist/react/core/HeaderIconWithStatus.d.ts +39 -0
  182. package/dist/react/core/HeaderIconWithStatus.js +157 -0
  183. package/dist/react/core/HeaderIconWithStatus.js.map +1 -0
  184. package/dist/react/core/HexViewer.d.ts +143 -0
  185. package/dist/react/core/HexViewer.js +1106 -0
  186. package/dist/react/core/HexViewer.js.map +1 -0
  187. package/dist/react/core/Icon.d.ts +32 -0
  188. package/dist/react/core/Icon.js +142 -0
  189. package/dist/react/core/Icon.js.map +1 -0
  190. package/dist/react/core/ImageGallery.d.ts +41 -0
  191. package/dist/react/core/ImageGallery.js +320 -0
  192. package/dist/react/core/ImageGallery.js.map +1 -0
  193. package/dist/react/core/Input.d.ts +38 -0
  194. package/dist/react/core/Input.js +288 -0
  195. package/dist/react/core/Input.js.map +1 -0
  196. package/dist/react/core/LimitsBar.d.ts +51 -0
  197. package/dist/react/core/LimitsBar.js +200 -0
  198. package/dist/react/core/LimitsBar.js.map +1 -0
  199. package/dist/react/core/LogViewer.d.ts +61 -0
  200. package/dist/react/core/LogViewer.js +599 -0
  201. package/dist/react/core/LogViewer.js.map +1 -0
  202. package/dist/react/core/MessageStream.d.ts +58 -0
  203. package/dist/react/core/MessageStream.js +455 -0
  204. package/dist/react/core/MessageStream.js.map +1 -0
  205. package/dist/react/core/MissionCalendar.d.ts +81 -0
  206. package/dist/react/core/MissionCalendar.js +1049 -0
  207. package/dist/react/core/MissionCalendar.js.map +1 -0
  208. package/dist/react/core/NumberInput.d.ts +85 -0
  209. package/dist/react/core/NumberInput.js +507 -0
  210. package/dist/react/core/NumberInput.js.map +1 -0
  211. package/dist/react/core/PacketViewer.d.ts +73 -0
  212. package/dist/react/core/PacketViewer.js +431 -0
  213. package/dist/react/core/PacketViewer.js.map +1 -0
  214. package/dist/react/core/Pagination.d.ts +30 -0
  215. package/dist/react/core/Pagination.js +190 -0
  216. package/dist/react/core/Pagination.js.map +1 -0
  217. package/dist/react/core/PinInput.d.ts +41 -0
  218. package/dist/react/core/PinInput.js +210 -0
  219. package/dist/react/core/PinInput.js.map +1 -0
  220. package/dist/react/core/Popover.d.ts +55 -0
  221. package/dist/react/core/Popover.js +288 -0
  222. package/dist/react/core/Popover.js.map +1 -0
  223. package/dist/react/core/Select.d.ts +42 -0
  224. package/dist/react/core/Select.js +303 -0
  225. package/dist/react/core/Select.js.map +1 -0
  226. package/dist/react/core/SideNav.d.ts +103 -0
  227. package/dist/react/core/SideNav.js +551 -0
  228. package/dist/react/core/SideNav.js.map +1 -0
  229. package/dist/react/core/SidePanel.d.ts +33 -0
  230. package/dist/react/core/SidePanel.js +199 -0
  231. package/dist/react/core/SidePanel.js.map +1 -0
  232. package/dist/react/core/Tabs.d.ts +47 -0
  233. package/dist/react/core/Tabs.js +129 -0
  234. package/dist/react/core/Tabs.js.map +1 -0
  235. package/dist/react/core/Toast.d.ts +56 -0
  236. package/dist/react/core/Toast.js +229 -0
  237. package/dist/react/core/Toast.js.map +1 -0
  238. package/dist/react/core/Toggle.d.ts +22 -0
  239. package/dist/react/core/Toggle.js +151 -0
  240. package/dist/react/core/Toggle.js.map +1 -0
  241. package/dist/react/core/Tooltip.d.ts +19 -0
  242. package/dist/react/core/Tooltip.js +179 -0
  243. package/dist/react/core/Tooltip.js.map +1 -0
  244. package/dist/react/core/Typography.d.ts +127 -0
  245. package/dist/react/core/Typography.js +187 -0
  246. package/dist/react/core/Typography.js.map +1 -0
  247. package/dist/react/core/index.d.ts +108 -0
  248. package/dist/react/core/layout/Box.d.ts +77 -0
  249. package/dist/react/core/layout/Box.js +126 -0
  250. package/dist/react/core/layout/Box.js.map +1 -0
  251. package/dist/react/core/layout/Center.d.ts +20 -0
  252. package/dist/react/core/layout/Center.js +34 -0
  253. package/dist/react/core/layout/Center.js.map +1 -0
  254. package/dist/react/core/layout/Divider.d.ts +16 -0
  255. package/dist/react/core/layout/Divider.js +108 -0
  256. package/dist/react/core/layout/Divider.js.map +1 -0
  257. package/dist/react/core/layout/Flex.d.ts +30 -0
  258. package/dist/react/core/layout/Flex.js +128 -0
  259. package/dist/react/core/layout/Flex.js.map +1 -0
  260. package/dist/react/core/layout/Grid.d.ts +36 -0
  261. package/dist/react/core/layout/Grid.js +142 -0
  262. package/dist/react/core/layout/Grid.js.map +1 -0
  263. package/dist/react/core/layout/Spacer.d.ts +8 -0
  264. package/dist/react/core/layout/Spacer.js +31 -0
  265. package/dist/react/core/layout/Spacer.js.map +1 -0
  266. package/dist/react/core/layout/Stack.d.ts +54 -0
  267. package/dist/react/core/layout/Stack.js +74 -0
  268. package/dist/react/core/layout/Stack.js.map +1 -0
  269. package/dist/react/core/layout/index.d.ts +38 -0
  270. package/dist/react/core/layout/responsive.d.ts +23 -0
  271. package/dist/react/core/layout/responsive.js +26 -0
  272. package/dist/react/core/layout/responsive.js.map +1 -0
  273. package/dist/react/core/layout/useBreakpoint.d.ts +77 -0
  274. package/dist/react/core/layout/useBreakpoint.js +73 -0
  275. package/dist/react/core/layout/useBreakpoint.js.map +1 -0
  276. package/dist/react/core/propertyConfig.d.ts +443 -0
  277. package/dist/react/core/propertyConfig.js +399 -0
  278. package/dist/react/core/propertyConfig.js.map +1 -0
  279. package/dist/react/hooks/index.d.ts +21 -0
  280. package/dist/react/hooks/useAccessWindows.d.ts +66 -0
  281. package/dist/react/hooks/useCompactMode.d.ts +82 -0
  282. package/dist/react/hooks/useCompactMode.js +62 -0
  283. package/dist/react/hooks/useCompactMode.js.map +1 -0
  284. package/dist/react/hooks/useLiveSelection.d.ts +57 -0
  285. package/dist/react/hooks/useSimulationPlayback.d.ts +97 -0
  286. package/dist/react/hooks/useSimulationTime.d.ts +61 -0
  287. package/dist/react/hooks/useSpacecraftPosition.d.ts +50 -0
  288. package/dist/react/hooks/useSpacecraftPosition.js +89 -0
  289. package/dist/react/hooks/useSpacecraftPosition.js.map +1 -0
  290. package/dist/react/hooks/useTelemetry.d.ts +55 -0
  291. package/dist/react/hooks/useTelemetry.js +73 -0
  292. package/dist/react/hooks/useTelemetry.js.map +1 -0
  293. package/dist/react/hooks/useZendirSession.d.ts +109 -0
  294. package/dist/react/hooks/useZendirSession.js +148 -0
  295. package/dist/react/hooks/useZendirSession.js.map +1 -0
  296. package/dist/react/index.d.ts +74 -0
  297. package/dist/react/shared/ErrorBoundary.d.ts +63 -0
  298. package/dist/react/shared/ErrorBoundary.js +142 -0
  299. package/dist/react/shared/ErrorBoundary.js.map +1 -0
  300. package/dist/react/shared/Skeleton.d.ts +110 -0
  301. package/dist/react/shared/Skeleton.js +324 -0
  302. package/dist/react/shared/Skeleton.js.map +1 -0
  303. package/dist/react/shared/index.d.ts +12 -0
  304. package/dist/react/theme/ThemeProvider.d.ts +385 -0
  305. package/dist/react/theme/ThemeProvider.js +1096 -0
  306. package/dist/react/theme/ThemeProvider.js.map +1 -0
  307. package/dist/react/theme/astro-tokens.d.ts +153 -0
  308. package/dist/react/theme/cardAccent.d.ts +75 -0
  309. package/dist/react/theme/cardAccent.js +137 -0
  310. package/dist/react/theme/cardAccent.js.map +1 -0
  311. package/dist/react/theme/config.d.ts +39 -0
  312. package/dist/react/theme/index.d.ts +9 -0
  313. package/dist/react/types.d.ts +360 -0
  314. package/dist/react/types.js +58 -0
  315. package/dist/react/types.js.map +1 -0
  316. package/dist/react/utils/index.d.ts +247 -0
  317. package/dist/react/utils/index.js +423 -0
  318. package/dist/react/utils/index.js.map +1 -0
  319. package/dist/react/visualizations/EclipseTimerCard.d.ts +17 -0
  320. package/dist/react/visualizations/EclipseTimerCard.js +250 -0
  321. package/dist/react/visualizations/EclipseTimerCard.js.map +1 -0
  322. package/dist/react/visualizations/LinkBudgetCard.d.ts +50 -0
  323. package/dist/react/visualizations/LinkBudgetCard.js +444 -0
  324. package/dist/react/visualizations/LinkBudgetCard.js.map +1 -0
  325. package/dist/react/visualizations/NavBallCard.d.ts +17 -0
  326. package/dist/react/visualizations/NavBallCard.js +243 -0
  327. package/dist/react/visualizations/NavBallCard.js.map +1 -0
  328. package/dist/react/visualizations/PropulsionCard.d.ts +37 -0
  329. package/dist/react/visualizations/PropulsionCard.js +298 -0
  330. package/dist/react/visualizations/PropulsionCard.js.map +1 -0
  331. package/dist/react/visualizations/SensorFootprintCard.d.ts +33 -0
  332. package/dist/react/visualizations/SensorFootprintCard.js +326 -0
  333. package/dist/react/visualizations/SensorFootprintCard.js.map +1 -0
  334. package/dist/react/visualizations/ThermalHeatmapCard.d.ts +38 -0
  335. package/dist/react/visualizations/ThermalHeatmapCard.js +372 -0
  336. package/dist/react/visualizations/ThermalHeatmapCard.js.map +1 -0
  337. package/dist/react/visualizations/index.d.ts +17 -0
  338. package/dist/react.d.ts +1 -0
  339. package/dist/react.js +421 -0
  340. package/dist/react.js.map +1 -0
  341. package/dist/shaders/atmosphere.frag.js +5 -0
  342. package/dist/shaders/atmosphere.frag.js.map +1 -0
  343. package/dist/shaders/atmosphere.vert.js +5 -0
  344. package/dist/shaders/atmosphere.vert.js.map +1 -0
  345. package/dist/shaders/stars.frag.js +5 -0
  346. package/dist/shaders/stars.frag.js.map +1 -0
  347. package/dist/shaders/stars.vert.js +5 -0
  348. package/dist/shaders/stars.vert.js.map +1 -0
  349. package/dist/style.css +143 -0
  350. package/dist/tokens/index.d.ts +296 -0
  351. package/dist/tokens/index.js +263 -0
  352. package/dist/tokens/index.js.map +1 -0
  353. package/dist/tokens/tokens.css +155 -0
  354. package/dist/types/index.d.ts +23 -0
  355. package/dist/types.d.ts +1 -0
  356. package/dist/types.js +2 -0
  357. package/dist/types.js.map +1 -0
  358. package/package.json +220 -0
  359. package/sdk-stub.js +22 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SimulationControls.js","sources":["../../../src/react/astro/SimulationControls.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - SimulationControls Component\r\n * \r\n * Space operations simulation playback controls following Astro UX patterns.\r\n * Provides play/pause/stop/step controls for simulation time management.\r\n * \r\n * Features:\r\n * - Play/Pause toggle with visual state feedback\r\n * - Stop (reset) functionality\r\n * - Step forward/backward controls\r\n * - Time scale (playback rate) adjustment\r\n * - Simulation time display integration\r\n * - AOS/LOS timer integration\r\n * - Keyboard accessibility\r\n * - AstroUXDS compliant styling\r\n * \r\n * Space Operations Terminology:\r\n * - SIM: Simulation mode indicator\r\n * - MET: Mission Elapsed Time\r\n * - Epoch: Simulation start time (t=0)\r\n * - Time Scale: Playback speed multiplier\r\n * \r\n * @example\r\n * ```tsx\r\n * import { SimulationControls } from '@zendir/ui/react';\r\n * \r\n * <SimulationControls\r\n * isPlaying={isPlaying}\r\n * onPlay={handlePlay}\r\n * onPause={handlePause}\r\n * onStop={handleStop}\r\n * timeScale={1}\r\n * onTimeScaleChange={setTimeScale}\r\n * currentTime={simulationTime}\r\n * epoch={epoch}\r\n * />\r\n * ```\r\n */\r\n\r\nimport React, { memo, useState, useCallback, useMemo } from 'react';\r\nimport { useTheme } from '../theme';\r\nimport { classNames, tabularNumsStyle, safeAccentText } from '../utils';\r\nimport { AstroIcon } from '../core/AstroIcon';\r\nimport { Tooltip } from '../core/Tooltip';\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\nexport type SimulationState = 'stopped' | 'playing' | 'paused';\r\n\r\nexport interface SimulationControlsProps {\r\n /** Current simulation state */\r\n state?: SimulationState;\r\n /** Whether simulation is playing (alternative to state) */\r\n isPlaying?: boolean;\r\n /** Whether simulation is paused (used with isPlaying for 3-state) */\r\n isPaused?: boolean;\r\n \r\n // === Playback Callbacks ===\r\n /** Called when play is triggered */\r\n onPlay?: () => void;\r\n /** Called when pause is triggered */\r\n onPause?: () => void;\r\n /** Called when stop (reset) is triggered */\r\n onStop?: () => void;\r\n /** Called when step forward is triggered */\r\n onStepForward?: () => void;\r\n /** Called when step backward is triggered */\r\n onStepBackward?: () => void;\r\n \r\n // === Time Display ===\r\n /** Current simulation time */\r\n currentTime?: Date | string;\r\n /** Simulation epoch (t=0) */\r\n epoch?: Date | string;\r\n /** Current elapsed seconds from epoch */\r\n elapsedSeconds?: number;\r\n /** Show elapsed time display */\r\n showElapsedTime?: boolean;\r\n /** Show current time display */\r\n showCurrentTime?: boolean;\r\n /** Show date in time display */\r\n showDate?: boolean;\r\n \r\n // === Time Scale ===\r\n /** Current time scale factor (1 = realtime) */\r\n timeScale?: number;\r\n /** Callback when time scale changes */\r\n onTimeScaleChange?: (scale: number) => void;\r\n /** Available time scale presets */\r\n timeScalePresets?: number[];\r\n /** Show time scale controls */\r\n showTimeScale?: boolean;\r\n \r\n // === Step Size ===\r\n /** Step size in seconds */\r\n stepSize?: number;\r\n /** Callback when step size changes */\r\n onStepSizeChange?: (size: number) => void;\r\n /** Available step size presets in seconds */\r\n stepSizePresets?: number[];\r\n /** Show step controls */\r\n showStepControls?: boolean;\r\n \r\n // === Appearance ===\r\n /** Compact display mode */\r\n compact?: boolean;\r\n /** Small size variant */\r\n small?: boolean;\r\n /** Custom className */\r\n className?: string;\r\n /** Disabled state */\r\n disabled?: boolean;\r\n /** Show simulation status indicator */\r\n showStatus?: boolean;\r\n /** Custom label for simulation mode */\r\n label?: string;\r\n}\r\n\r\n// ============================================================================\r\n// Constants\r\n// ============================================================================\r\n\r\nconst DEFAULT_TIME_SCALE_PRESETS = [0.1, 0.25, 0.5, 1, 2, 5, 10, 60, 3600];\r\nconst DEFAULT_STEP_SIZE_PRESETS = [1, 5, 10, 30, 60, 300, 600, 3600];\r\n\r\n// ============================================================================\r\n// Utility Functions\r\n// ============================================================================\r\n\r\n/**\r\n * Format elapsed time as DD:HH:MM:SS\r\n */\r\nfunction formatElapsedTime(seconds: number): string {\r\n const absSeconds = Math.abs(seconds);\r\n const days = Math.floor(absSeconds / 86400);\r\n const hours = Math.floor((absSeconds % 86400) / 3600);\r\n const mins = Math.floor((absSeconds % 3600) / 60);\r\n const secs = Math.floor(absSeconds % 60);\r\n \r\n const sign = seconds < 0 ? '-' : '';\r\n \r\n if (days > 0) {\r\n return `${sign}${days}:${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\r\n }\r\n return `${sign}${hours.toString().padStart(2, '0')}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\r\n}\r\n\r\n/**\r\n * Format time scale for display\r\n */\r\nfunction formatTimeScale(scale: number): string {\r\n if (scale >= 3600) return `${scale / 3600}h/s`;\r\n if (scale >= 60) return `${scale / 60}m/s`;\r\n if (scale === 1) return '1×';\r\n if (scale < 1) return `${scale}×`;\r\n return `${scale}×`;\r\n}\r\n\r\n/**\r\n * Format step size for display\r\n */\r\nfunction formatStepSize(seconds: number): string {\r\n if (seconds >= 3600) return `${seconds / 3600}h`;\r\n if (seconds >= 60) return `${seconds / 60}m`;\r\n return `${seconds}s`;\r\n}\r\n\r\n/**\r\n * Format time for display\r\n */\r\nfunction formatTimeDisplay(date: Date): string {\r\n const hours = date.getUTCHours().toString().padStart(2, '0');\r\n const mins = date.getUTCMinutes().toString().padStart(2, '0');\r\n const secs = date.getUTCSeconds().toString().padStart(2, '0');\r\n return `${hours}:${mins}:${secs}`;\r\n}\r\n\r\n/**\r\n * Format date for display\r\n */\r\nfunction formatDateDisplay(date: Date): string {\r\n const year = date.getUTCFullYear();\r\n const month = (date.getUTCMonth() + 1).toString().padStart(2, '0');\r\n const day = date.getUTCDate().toString().padStart(2, '0');\r\n return `${year}-${month}-${day}`;\r\n}\r\n\r\n// ============================================================================\r\n// Sub-components\r\n// ============================================================================\r\n\r\ninterface ControlButtonProps {\r\n icon: string;\r\n label: string;\r\n onClick?: () => void;\r\n active?: boolean;\r\n disabled?: boolean;\r\n danger?: boolean;\r\n tokens: ReturnType<typeof useTheme>['tokens'];\r\n small?: boolean;\r\n}\r\n\r\nconst ControlButton = memo(function ControlButton({\r\n icon,\r\n label,\r\n onClick,\r\n active = false,\r\n disabled = false,\r\n danger = false,\r\n tokens,\r\n small = false,\r\n}: ControlButtonProps) {\r\n const size = small ? 28 : 32;\r\n const iconSize = small ? 14 : 16;\r\n \r\n const baseColor = danger \r\n ? tokens.colors.status.critical \r\n : active \r\n ? tokens.colors.status.normal \r\n : tokens.colors.text.primary;\r\n \r\n const bgColor = active \r\n ? `${tokens.colors.status.normal}25`\r\n : 'rgba(255,255,255,0.08)';\r\n \r\n return (\r\n <Tooltip content={label} placement=\"bottom\">\r\n <button\r\n onClick={onClick}\r\n disabled={disabled}\r\n aria-label={label}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n width: size,\r\n height: size,\r\n padding: 0,\r\n border: 'none',\r\n borderRadius: tokens.borderRadius.md,\r\n backgroundColor: disabled ? 'rgba(255,255,255,0.03)' : bgColor,\r\n color: disabled ? tokens.colors.text.tertiary : baseColor,\r\n cursor: disabled ? 'not-allowed' : 'pointer',\r\n transition: 'all 0.15s ease',\r\n opacity: disabled ? 0.5 : 1,\r\n }}\r\n onMouseEnter={(e) => {\r\n if (!disabled) {\r\n e.currentTarget.style.backgroundColor = active \r\n ? `${tokens.colors.status.normal}35`\r\n : 'rgba(255,255,255,0.15)';\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (!disabled) {\r\n e.currentTarget.style.backgroundColor = bgColor;\r\n }\r\n }}\r\n >\r\n <AstroIcon \r\n name={icon as any} \r\n size={iconSize} \r\n color={disabled ? tokens.colors.text.tertiary : baseColor}\r\n />\r\n </button>\r\n </Tooltip>\r\n );\r\n});\r\n\r\ninterface TimeScaleSelectorProps {\r\n value: number;\r\n presets: number[];\r\n onChange?: (scale: number) => void;\r\n disabled?: boolean;\r\n tokens: ReturnType<typeof useTheme>['tokens'];\r\n small?: boolean;\r\n}\r\n\r\nconst TimeScaleSelector = memo(function TimeScaleSelector({\r\n value,\r\n presets,\r\n onChange,\r\n disabled = false,\r\n tokens,\r\n small = false,\r\n}: TimeScaleSelectorProps) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n \r\n return (\r\n <div style={{ position: 'relative' }}>\r\n <Tooltip content=\"Time Scale / Playback Speed\" placement=\"bottom\">\r\n <button\r\n onClick={() => !disabled && setIsOpen(!isOpen)}\r\n disabled={disabled}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 4,\r\n padding: small ? '4px 8px' : '6px 10px',\r\n border: 'none',\r\n borderRadius: tokens.borderRadius.sm,\r\n backgroundColor: 'rgba(255,255,255,0.08)',\r\n color: value !== 1 ? tokens.colors.status.caution : tokens.colors.text.secondary,\r\n fontSize: small ? tokens.typography.fontSize.xxs : '0.6875rem', // 10px/11px in rem\r\n fontWeight: 700, // AstroUXDS bold for time display (critical info)\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n cursor: disabled ? 'not-allowed' : 'pointer',\r\n transition: 'all 0.15s ease',\r\n opacity: disabled ? 0.5 : 1,\r\n ...tabularNumsStyle,\r\n }}\r\n >\r\n <AstroIcon name=\"fast-forward\" size={small ? 10 : 12} color=\"inherit\" />\r\n {formatTimeScale(value)}\r\n </button>\r\n </Tooltip>\r\n \r\n {isOpen && !disabled && (\r\n <>\r\n <div \r\n style={{ \r\n position: 'fixed', \r\n inset: 0, \r\n zIndex: 99 \r\n }} \r\n onClick={() => setIsOpen(false)} \r\n />\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: '100%',\r\n left: '50%',\r\n transform: 'translateX(-50%)',\r\n marginTop: 4,\r\n padding: 4,\r\n backgroundColor: tokens.colors.background.elevated,\r\n border: `1px solid ${tokens.colors.border.default}`,\r\n borderRadius: tokens.borderRadius.md,\r\n boxShadow: tokens.shadows.lg,\r\n zIndex: 100,\r\n minWidth: 80,\r\n }}\r\n >\r\n {presets.map((scale) => (\r\n <button\r\n key={scale}\r\n onClick={() => {\r\n onChange?.(scale);\r\n setIsOpen(false);\r\n }}\r\n style={{\r\n display: 'block',\r\n width: '100%',\r\n padding: '6px 12px',\r\n border: 'none',\r\n borderRadius: tokens.borderRadius.sm,\r\n backgroundColor: value === scale ? tokens.colors.accent.primary : 'transparent',\r\n color: value === scale ? '#ffffff' : tokens.colors.text.secondary,\r\n fontSize: '0.6875rem', // 11px in rem\r\n fontWeight: value === scale ? 500 : 400, // AstroUXDS: 500 (medium) not 600\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n textAlign: 'center',\r\n cursor: 'pointer',\r\n transition: 'all 0.1s ease',\r\n ...tabularNumsStyle,\r\n }}\r\n onMouseEnter={(e) => {\r\n if (value !== scale) {\r\n e.currentTarget.style.backgroundColor = 'rgba(255,255,255,0.1)';\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = value === scale \r\n ? tokens.colors.accent.primary \r\n : 'transparent';\r\n }}\r\n >\r\n {formatTimeScale(scale)}\r\n </button>\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\ninterface SimulationTimeDisplayProps {\r\n currentTime?: Date;\r\n elapsedSeconds?: number;\r\n showElapsed?: boolean;\r\n showCurrent?: boolean;\r\n showDate?: boolean;\r\n isPlaying?: boolean;\r\n tokens: ReturnType<typeof useTheme>['tokens'];\r\n small?: boolean;\r\n}\r\n\r\nconst SimulationTimeDisplay = memo(function SimulationTimeDisplay({\r\n currentTime,\r\n elapsedSeconds,\r\n showElapsed = true,\r\n showCurrent = true,\r\n showDate = false,\r\n isPlaying = false,\r\n tokens,\r\n small = false,\r\n}: SimulationTimeDisplayProps) {\r\n return (\r\n <div\r\n style={{\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n gap: 2,\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n }}\r\n >\r\n {showDate && currentTime && (\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n color: tokens.colors.text.tertiary,\r\n ...tabularNumsStyle,\r\n }}\r\n >\r\n {formatDateDisplay(currentTime)}\r\n </span>\r\n )}\r\n \r\n {showCurrent && currentTime && (\r\n <span\r\n style={{\r\n fontSize: small ? tokens.typography.fontSize.lg : tokens.typography.fontSize.xl,\r\n fontWeight: tokens.typography.fontWeight.bold, // Bold (700) to match MissionClock\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n color: tokens.colors.text.primary,\r\n ...tabularNumsStyle,\r\n }}\r\n >\r\n {formatTimeDisplay(currentTime)}\r\n </span>\r\n )}\r\n \r\n {showElapsed && elapsedSeconds !== undefined && (\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n color: tokens.colors.status.caution,\r\n ...tabularNumsStyle,\r\n }}\r\n >\r\n T{elapsedSeconds >= 0 ? '+' : ''}{formatElapsedTime(elapsedSeconds)}\r\n </span>\r\n )}\r\n \r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n color: isPlaying ? safeAccentText(tokens.colors.accent.primary) : tokens.colors.status.standby,\r\n textTransform: 'uppercase',\r\n letterSpacing: tokens.typography.letterSpacing.wide,\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 4,\r\n }}\r\n >\r\n {isPlaying && (\r\n <span\r\n style={{\r\n width: 6,\r\n height: 6,\r\n borderRadius: '50%',\r\n backgroundColor: tokens.colors.accent.primary,\r\n animation: 'pulse 1.5s ease-in-out infinite',\r\n }}\r\n />\r\n )}\r\n SIM\r\n </span>\r\n </div>\r\n );\r\n});\r\n\r\n// ============================================================================\r\n// Main Component\r\n// ============================================================================\r\n\r\n/**\r\n * SimulationControls - Playback controls for space simulation\r\n * \r\n * Provides comprehensive simulation time control following Astro UX patterns.\r\n * Designed for mission control and space operations applications.\r\n * \r\n * @example\r\n * ```tsx\r\n * // Basic usage\r\n * <SimulationControls\r\n * isPlaying={isPlaying}\r\n * onPlay={() => setIsPlaying(true)}\r\n * onPause={() => setIsPlaying(false)}\r\n * onStop={handleReset}\r\n * />\r\n * \r\n * // Full featured\r\n * <SimulationControls\r\n * isPlaying={isPlaying}\r\n * onPlay={handlePlay}\r\n * onPause={handlePause}\r\n * onStop={handleStop}\r\n * onStepForward={handleStepForward}\r\n * onStepBackward={handleStepBackward}\r\n * currentTime={simulationTime}\r\n * epoch={epoch}\r\n * elapsedSeconds={elapsed}\r\n * timeScale={timeScale}\r\n * onTimeScaleChange={setTimeScale}\r\n * showTimeScale\r\n * showStepControls\r\n * showElapsedTime\r\n * />\r\n * \r\n * // In AppBar center slot\r\n * <AppBar\r\n * appName=\"Mission Control\"\r\n * centerSlot={\r\n * <SimulationControls\r\n * compact\r\n * isPlaying={isPlaying}\r\n * onPlay={handlePlay}\r\n * onPause={handlePause}\r\n * currentTime={simTime}\r\n * />\r\n * }\r\n * />\r\n * ```\r\n */\r\nexport const SimulationControls = memo(function SimulationControls({\r\n state,\r\n isPlaying: isPlayingProp,\r\n isPaused,\r\n onPlay,\r\n onPause,\r\n onStop,\r\n onStepForward,\r\n onStepBackward,\r\n currentTime: currentTimeProp,\r\n epoch,\r\n elapsedSeconds: elapsedSecondsProp,\r\n showElapsedTime = true,\r\n showCurrentTime = true,\r\n showDate = true,\r\n timeScale = 1,\r\n onTimeScaleChange,\r\n timeScalePresets = DEFAULT_TIME_SCALE_PRESETS,\r\n showTimeScale = true,\r\n stepSize = 60,\r\n onStepSizeChange: _onStepSizeChange,\r\n stepSizePresets: _stepSizePresets = DEFAULT_STEP_SIZE_PRESETS,\r\n showStepControls = true,\r\n compact = false,\r\n small = false,\r\n className = '',\r\n disabled = false,\r\n showStatus = true,\r\n label,\r\n}: SimulationControlsProps): React.ReactElement {\r\n const { tokens, theme } = useTheme();\r\n const isTransparentTheme = theme === 'transparent' || theme === 'transparent-bold' || theme === 'transparent-minimal';\r\n \r\n // Derive playing state from props\r\n const isPlaying = useMemo(() => {\r\n if (state) return state === 'playing';\r\n return isPlayingProp ?? false;\r\n }, [state, isPlayingProp]);\r\n \r\n const isStopped = useMemo(() => {\r\n if (state) return state === 'stopped';\r\n return !isPlayingProp && !isPaused;\r\n }, [state, isPlayingProp, isPaused]);\r\n \r\n // Parse current time\r\n const currentTime = useMemo(() => {\r\n if (!currentTimeProp) return undefined;\r\n return typeof currentTimeProp === 'string' ? new Date(currentTimeProp) : currentTimeProp;\r\n }, [currentTimeProp]);\r\n \r\n // Calculate elapsed seconds\r\n const elapsedSeconds = useMemo(() => {\r\n if (elapsedSecondsProp !== undefined) return elapsedSecondsProp;\r\n if (currentTime && epoch) {\r\n const epochDate = typeof epoch === 'string' ? new Date(epoch) : epoch;\r\n return (currentTime.getTime() - epochDate.getTime()) / 1000;\r\n }\r\n return undefined;\r\n }, [elapsedSecondsProp, currentTime, epoch]);\r\n \r\n // Handle play/pause toggle\r\n const handlePlayPause = useCallback(() => {\r\n if (isPlaying) {\r\n onPause?.();\r\n } else {\r\n onPlay?.();\r\n }\r\n }, [isPlaying, onPlay, onPause]);\r\n \r\n // Handle keyboard shortcuts\r\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\r\n if (disabled) return;\r\n \r\n switch (e.key) {\r\n case ' ':\r\n e.preventDefault();\r\n handlePlayPause();\r\n break;\r\n case 'Escape':\r\n e.preventDefault();\r\n onStop?.();\r\n break;\r\n case 'ArrowRight':\r\n e.preventDefault();\r\n onStepForward?.();\r\n break;\r\n case 'ArrowLeft':\r\n e.preventDefault();\r\n onStepBackward?.();\r\n break;\r\n }\r\n }, [disabled, handlePlayPause, onStop, onStepForward, onStepBackward]);\r\n \r\n return (\r\n <div\r\n className={classNames('zendir-simulation-controls', className)}\r\n role=\"group\"\r\n aria-label={label || 'Simulation Controls'}\r\n onKeyDown={handleKeyDown}\r\n tabIndex={0}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: compact ? tokens.spacing.sm : tokens.spacing.md,\r\n padding: compact \r\n ? `${tokens.spacing.xs} ${tokens.spacing.sm}`\r\n : `${tokens.spacing.sm} ${tokens.spacing.md}`,\r\n backgroundColor: isTransparentTheme \r\n ? 'rgba(0,0,0,0.3)' \r\n : tokens.colors.background.surface,\r\n ...(isTransparentTheme && { \r\n backdropFilter: 'blur(12px)', \r\n WebkitBackdropFilter: 'blur(12px)' as const \r\n }),\r\n ...(tokens.colors.border.cardStyle ?? { border: `1px solid ${tokens.colors.border.muted}` }),\r\n borderRadius: tokens.borderRadius.lg,\r\n outline: 'none',\r\n transition: tokens.animation.fast,\r\n }}\r\n >\r\n {/* Time Display (if showing time) */}\r\n {(showCurrentTime || showElapsedTime) && !compact && (\r\n <SimulationTimeDisplay\r\n currentTime={currentTime}\r\n elapsedSeconds={elapsedSeconds}\r\n showElapsed={showElapsedTime}\r\n showCurrent={showCurrentTime}\r\n showDate={showDate}\r\n isPlaying={isPlaying}\r\n tokens={tokens}\r\n small={small}\r\n />\r\n )}\r\n \r\n {/* Compact time display */}\r\n {compact && currentTime && (\r\n <div\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 8,\r\n }}\r\n >\r\n {showDate && (\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n color: tokens.colors.text.tertiary,\r\n ...tabularNumsStyle,\r\n }}\r\n >\r\n {formatDateDisplay(currentTime)}\r\n </span>\r\n )}\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.lg,\r\n fontWeight: tokens.typography.fontWeight.bold, // Bold (700) to match MissionClock\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n color: tokens.colors.text.primary,\r\n ...tabularNumsStyle,\r\n }}\r\n >\r\n {formatTimeDisplay(currentTime)}\r\n </span>\r\n {showStatus && (\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n color: isPlaying ? safeAccentText(tokens.colors.accent.primary) : tokens.colors.status.standby,\r\n textTransform: 'uppercase',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 4,\r\n }}\r\n >\r\n {isPlaying && (\r\n <span\r\n style={{\r\n width: 6,\r\n height: 6,\r\n borderRadius: '50%',\r\n backgroundColor: tokens.colors.accent.primary,\r\n }}\r\n />\r\n )}\r\n SIM\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n \r\n {/* Separator */}\r\n {((showCurrentTime || showElapsedTime) || (compact && currentTime)) && (\r\n <div\r\n style={{\r\n width: 1,\r\n height: 24,\r\n backgroundColor: tokens.colors.border.muted,\r\n }}\r\n />\r\n )}\r\n \r\n {/* Transport Controls */}\r\n <div\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 4,\r\n }}\r\n >\r\n {/* Step Backward */}\r\n {showStepControls && (\r\n <ControlButton\r\n icon=\"skip-previous\"\r\n label={`Step backward ${formatStepSize(stepSize)}`}\r\n onClick={onStepBackward}\r\n disabled={disabled || !onStepBackward}\r\n tokens={tokens}\r\n small={small}\r\n />\r\n )}\r\n \r\n {/* Stop */}\r\n <ControlButton\r\n icon=\"stop\"\r\n label=\"Stop / Reset\"\r\n onClick={onStop}\r\n disabled={disabled || !onStop}\r\n danger={!isStopped}\r\n tokens={tokens}\r\n small={small}\r\n />\r\n \r\n {/* Play/Pause */}\r\n <Tooltip content={isPlaying ? 'Pause (Space)' : 'Play (Space)'} placement=\"bottom\">\r\n <button\r\n onClick={handlePlayPause}\r\n disabled={disabled}\r\n aria-label={isPlaying ? 'Pause simulation' : 'Play simulation'}\r\n style={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n width: small ? 36 : 44,\r\n height: small ? 36 : 44,\r\n padding: 0,\r\n border: isPlaying ? `2px solid ${tokens.colors.accent.primary}` : 'none',\r\n borderRadius: '50%',\r\n // Use accent primary for both states - playing has outline style\r\n backgroundColor: isPlaying \r\n ? 'rgba(138, 43, 226, 0.15)' // Subtle purple fill when playing\r\n : tokens.colors.accent.primary,\r\n color: isPlaying ? safeAccentText(tokens.colors.accent.primary) : '#ffffff',\r\n cursor: disabled ? 'not-allowed' : 'pointer',\r\n transition: 'all 0.15s ease',\r\n opacity: disabled ? 0.5 : 1,\r\n boxShadow: isPlaying \r\n ? `0 0 16px ${tokens.colors.accent.primary}50`\r\n : `0 0 8px ${tokens.colors.accent.primary}40`,\r\n }}\r\n onMouseEnter={(e) => {\r\n if (!disabled) {\r\n e.currentTarget.style.transform = 'scale(1.05)';\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.transform = 'scale(1)';\r\n }}\r\n >\r\n <AstroIcon \r\n name={isPlaying ? 'pause' : 'play-arrow'} \r\n size={small ? 18 : 22} \r\n color={isPlaying ? tokens.colors.accent.primary : '#ffffff'}\r\n />\r\n </button>\r\n </Tooltip>\r\n \r\n {/* Step Forward */}\r\n {showStepControls && (\r\n <ControlButton\r\n icon=\"skip-next\"\r\n label={`Step forward ${formatStepSize(stepSize)}`}\r\n onClick={onStepForward}\r\n disabled={disabled || !onStepForward}\r\n tokens={tokens}\r\n small={small}\r\n />\r\n )}\r\n </div>\r\n \r\n {/* Time Scale */}\r\n {showTimeScale && (\r\n <>\r\n <div\r\n style={{\r\n width: 1,\r\n height: 24,\r\n backgroundColor: tokens.colors.border.muted,\r\n }}\r\n />\r\n <TimeScaleSelector\r\n value={timeScale}\r\n presets={timeScalePresets}\r\n onChange={onTimeScaleChange}\r\n disabled={disabled || !onTimeScaleChange}\r\n tokens={tokens}\r\n small={small}\r\n />\r\n </>\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\n// ============================================================================\r\n// Convenience Components\r\n// ============================================================================\r\n\r\n/**\r\n * MiniSimulationControls - Ultra-compact controls for AppBar\r\n */\r\nexport interface MiniSimulationControlsProps {\r\n isPlaying?: boolean;\r\n onPlay?: () => void;\r\n onPause?: () => void;\r\n onStop?: () => void;\r\n timeScale?: number;\r\n onTimeScaleChange?: (scale: number) => void;\r\n disabled?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport const MiniSimulationControls = memo(function MiniSimulationControls({\r\n isPlaying = false,\r\n onPlay,\r\n onPause,\r\n onStop,\r\n timeScale = 1,\r\n onTimeScaleChange,\r\n disabled = false,\r\n className = '',\r\n}: MiniSimulationControlsProps): React.ReactElement {\r\n return (\r\n <SimulationControls\r\n isPlaying={isPlaying}\r\n onPlay={onPlay}\r\n onPause={onPause}\r\n onStop={onStop}\r\n timeScale={timeScale}\r\n onTimeScaleChange={onTimeScaleChange}\r\n disabled={disabled}\r\n compact\r\n small\r\n showCurrentTime={false}\r\n showElapsedTime={false}\r\n showDate={false}\r\n showStepControls={false}\r\n showTimeScale={Boolean(onTimeScaleChange)}\r\n className={className}\r\n />\r\n );\r\n});\r\n\r\n/**\r\n * SimulationControlsWithClock - Controls combined with MissionClock\r\n */\r\nexport interface SimulationControlsWithClockProps extends Omit<SimulationControlsProps, 'showCurrentTime' | 'showElapsedTime'> {\r\n /** Clock format */\r\n clockFormat?: '12h' | '24h';\r\n /** Timezone label */\r\n timezone?: string;\r\n}\r\n\r\nexport const SimulationControlsWithClock = memo(function SimulationControlsWithClock({\r\n clockFormat: _clockFormat = '24h',\r\n timezone = 'SIM',\r\n ...props\r\n}: SimulationControlsWithClockProps): React.ReactElement {\r\n return (\r\n <SimulationControls\r\n {...props}\r\n showCurrentTime\r\n showElapsedTime\r\n showDate\r\n label={`Simulation Controls - ${timezone}`}\r\n />\r\n );\r\n});\r\n\r\nexport default SimulationControls;\r\n"],"names":["ControlButton","TimeScaleSelector","SimulationTimeDisplay","SimulationControls","MiniSimulationControls","SimulationControlsWithClock"],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import { default as React } from 'react';
2
+ import { StatusLevel } from '../utils';
3
+
4
+ export type StatusVariant = StatusLevel;
5
+ export interface StatusIndicatorProps {
6
+ /** Status variant - determines color and shape */
7
+ status: StatusVariant;
8
+ /** Status label text */
9
+ label?: string;
10
+ /** Smaller size variant */
11
+ small?: boolean;
12
+ /** Show pulse animation for active states */
13
+ pulse?: boolean;
14
+ /** Show border (required for light theme per Astro UX) */
15
+ bordered?: boolean;
16
+ /** Custom className */
17
+ className?: string;
18
+ /** Click handler */
19
+ onClick?: () => void;
20
+ }
21
+ /**
22
+ * StatusIndicator - Pure React status component
23
+ *
24
+ * Displays standardized status symbols following Astro UX design patterns.
25
+ * Uses dual-coding (color + shape) for WCAG 2.1 AA accessibility compliance.
26
+ *
27
+ * @example
28
+ * ```tsx
29
+ * <StatusIndicator status="normal" label="Power System" />
30
+ * <StatusIndicator status="caution" label="Battery Low" />
31
+ * <StatusIndicator status="critical" label="Comm Loss" pulse />
32
+ * ```
33
+ */
34
+ export declare const StatusIndicator: React.NamedExoticComponent<StatusIndicatorProps>;
@@ -0,0 +1,189 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { memo } from "react";
3
+ import { classNames } from "../utils/index.js";
4
+ import { useTheme } from "../theme/ThemeProvider.js";
5
+ const STATUS_COLORS_DARK = {
6
+ off: "#a4abb6",
7
+ standby: "#2dccff",
8
+ normal: "#56f000",
9
+ caution: "#fce83a",
10
+ serious: "#ffb302",
11
+ critical: "#ff3838"
12
+ };
13
+ const STATUS_COLORS_LIGHT_FILL = {
14
+ off: "#7b8089",
15
+ standby: "#64d9ff",
16
+ normal: "#00e200",
17
+ caution: "#fad800",
18
+ serious: "#ffaf3d",
19
+ critical: "#ff2a04"
20
+ };
21
+ const STATUS_COLORS_LIGHT_BORDER = {
22
+ off: "#3c3e42",
23
+ standby: "#285766",
24
+ normal: "#005a00",
25
+ caution: "#645600",
26
+ serious: "#664618",
27
+ critical: "#661102"
28
+ };
29
+ const STATUS_ARIA_LABELS = {
30
+ off: "Status: Off",
31
+ standby: "Status: Standby",
32
+ normal: "Status: Normal",
33
+ caution: "Status: Caution",
34
+ serious: "Status: Serious",
35
+ critical: "Status: Critical"
36
+ };
37
+ const renderStatusShape = (status, size, fillColor, borderColor) => {
38
+ const hasBorder = !!borderColor;
39
+ const strokeWidth = hasBorder ? 1.5 : 0;
40
+ switch (status) {
41
+ case "off":
42
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: hasBorder ? 2.5 : 3, fill: fillColor, stroke: borderColor, strokeWidth }) });
43
+ case "standby":
44
+ return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 12 12", width: size, height: size, children: [
45
+ /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "3.5", fill: "none", stroke: fillColor, strokeWidth: "2" }),
46
+ hasBorder && /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "4.75", fill: "none", stroke: borderColor, strokeWidth })
47
+ ] });
48
+ case "normal":
49
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: hasBorder ? 4.5 : 5, fill: fillColor, stroke: borderColor, strokeWidth }) });
50
+ case "caution":
51
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx(
52
+ "rect",
53
+ {
54
+ x: hasBorder ? 1.5 : 1,
55
+ y: hasBorder ? 1.5 : 1,
56
+ width: hasBorder ? 9 : 10,
57
+ height: hasBorder ? 9 : 10,
58
+ fill: fillColor,
59
+ stroke: borderColor,
60
+ strokeWidth
61
+ }
62
+ ) });
63
+ case "serious":
64
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx(
65
+ "polygon",
66
+ {
67
+ points: "6,1 11,6 6,11 1,6",
68
+ fill: fillColor,
69
+ stroke: borderColor,
70
+ strokeWidth
71
+ }
72
+ ) });
73
+ case "critical":
74
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx(
75
+ "polygon",
76
+ {
77
+ points: "6,11 1,2 11,2",
78
+ fill: fillColor,
79
+ stroke: borderColor,
80
+ strokeWidth
81
+ }
82
+ ) });
83
+ default:
84
+ return null;
85
+ }
86
+ };
87
+ const StatusIndicator = memo(function StatusIndicator2({
88
+ status,
89
+ label,
90
+ small = false,
91
+ pulse = false,
92
+ bordered,
93
+ className = "",
94
+ onClick
95
+ }) {
96
+ const { tokens, mode } = useTheme();
97
+ const isLightTheme = mode === "light";
98
+ const showBorder = bordered ?? isLightTheme;
99
+ const fillColor = isLightTheme ? STATUS_COLORS_LIGHT_FILL[status] : tokens.colors.status[status] || STATUS_COLORS_DARK[status];
100
+ const borderColor = showBorder ? STATUS_COLORS_LIGHT_BORDER[status] : void 0;
101
+ const size = small ? 10 : 14;
102
+ const shouldPulse = pulse || status === "critical";
103
+ const isCircle = status === "off" || status === "standby" || status === "normal";
104
+ const handleKeyDown = (e) => {
105
+ if (onClick && (e.key === "Enter" || e.key === " ")) {
106
+ e.preventDefault();
107
+ onClick();
108
+ }
109
+ };
110
+ return /* @__PURE__ */ jsxs(
111
+ "div",
112
+ {
113
+ className: classNames("zendir-status-indicator", className),
114
+ onClick,
115
+ onKeyDown: onClick ? handleKeyDown : void 0,
116
+ tabIndex: onClick ? 0 : void 0,
117
+ role: "status",
118
+ "aria-label": `${STATUS_ARIA_LABELS[status]}${label ? `: ${label}` : ""}`,
119
+ style: {
120
+ display: "inline-flex",
121
+ alignItems: "center",
122
+ gap: small ? 4 : 6,
123
+ cursor: onClick ? "pointer" : "default",
124
+ outline: "none"
125
+ },
126
+ children: [
127
+ /* @__PURE__ */ jsxs(
128
+ "span",
129
+ {
130
+ style: {
131
+ position: "relative",
132
+ display: "inline-flex",
133
+ alignItems: "center",
134
+ justifyContent: "center",
135
+ width: size,
136
+ height: size,
137
+ flexShrink: 0
138
+ },
139
+ children: [
140
+ shouldPulse && /* @__PURE__ */ jsx(
141
+ "span",
142
+ {
143
+ style: {
144
+ position: "absolute",
145
+ inset: -3,
146
+ borderRadius: isCircle ? "50%" : 0,
147
+ backgroundColor: fillColor,
148
+ opacity: 0.3,
149
+ animation: "statusPulse 2s ease-out infinite"
150
+ }
151
+ }
152
+ ),
153
+ renderStatusShape(status, size, fillColor, borderColor)
154
+ ]
155
+ }
156
+ ),
157
+ label && /* @__PURE__ */ jsx(
158
+ "span",
159
+ {
160
+ style: {
161
+ fontSize: small ? tokens.typography.fontSize.xs : tokens.typography.fontSize.sm,
162
+ fontWeight: tokens.typography.fontWeight.medium,
163
+ color: "inherit",
164
+ whiteSpace: "nowrap",
165
+ letterSpacing: tokens.typography.letterSpacing.normal
166
+ },
167
+ children: label
168
+ }
169
+ ),
170
+ /* @__PURE__ */ jsx("style", { children: `
171
+ @keyframes statusPulse {
172
+ 0% { transform: scale(1); opacity: 0.3; }
173
+ 50% { transform: scale(1.5); opacity: 0; }
174
+ 100% { transform: scale(1); opacity: 0; }
175
+ }
176
+ @media (prefers-reduced-motion: reduce) {
177
+ .zendir-status-indicator span[style*="statusPulse"] {
178
+ animation: none !important;
179
+ }
180
+ }
181
+ ` })
182
+ ]
183
+ }
184
+ );
185
+ });
186
+ export {
187
+ StatusIndicator
188
+ };
189
+ //# sourceMappingURL=StatusIndicator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusIndicator.js","sources":["../../../src/react/astro/StatusIndicator.tsx"],"sourcesContent":["/**\n * @zendir/ui - StatusIndicator Component (Pure React)\n * \n * Displays status symbols following Astro UX Design System patterns.\n * Uses the same 6-level status system: off, standby, normal, caution, serious, critical.\n * \n * Shapes per Astro UX (https://www.astrouxds.com/patterns/status-system/):\n * - Off: Circle (grey)\n * - Standby: Ring (cyan)\n * - Normal: Circle (green)\n * - Caution: Square (yellow)\n * - Serious: Diamond (orange)\n * - Critical: Triangle pointing down (red)\n * \n * Features:\n * - Dual coding (color + shape) for accessibility (WCAG 2.1 AA)\n * - Animated pulse for active states\n * - Light theme border support\n * - Theme-connected via useTheme()\n * - Keyboard accessible\n * - Screen reader support\n */\n\nimport React, { memo } from 'react';\nimport { useTheme } from '../theme';\nimport { classNames, type StatusLevel } from '../utils';\n\nexport type StatusVariant = StatusLevel;\n\nexport interface StatusIndicatorProps {\n /** Status variant - determines color and shape */\n status: StatusVariant;\n /** Status label text */\n label?: string;\n /** Smaller size variant */\n small?: boolean;\n /** Show pulse animation for active states */\n pulse?: boolean;\n /** Show border (required for light theme per Astro UX) */\n bordered?: boolean;\n /** Custom className */\n className?: string;\n /** Click handler */\n onClick?: () => void;\n}\n\n/**\n * Astro UX Status Colors (Dark Theme)\n * https://www.astrouxds.com/patterns/status-system/\n */\nconst STATUS_COLORS_DARK: Record<StatusVariant, string> = {\n off: '#a4abb6',\n standby: '#2dccff',\n normal: '#56f000',\n caution: '#fce83a',\n serious: '#ffb302',\n critical: '#ff3838',\n};\n\n/**\n * Astro UX Status Colors (Light Theme - Fill)\n * Requires border for WCAG AA compliance\n */\nconst STATUS_COLORS_LIGHT_FILL: Record<StatusVariant, string> = {\n off: '#7b8089',\n standby: '#64d9ff',\n normal: '#00e200',\n caution: '#fad800',\n serious: '#ffaf3d',\n critical: '#ff2a04',\n};\n\n/**\n * Astro UX Status Colors (Light Theme - Border)\n * Required for light backgrounds per Astro UX\n */\nconst STATUS_COLORS_LIGHT_BORDER: Record<StatusVariant, string> = {\n off: '#3c3e42',\n standby: '#285766',\n normal: '#005a00',\n caution: '#645600',\n serious: '#664618',\n critical: '#661102',\n};\n\nconst STATUS_ARIA_LABELS: Record<StatusVariant, string> = {\n off: 'Status: Off',\n standby: 'Status: Standby',\n normal: 'Status: Normal',\n caution: 'Status: Caution',\n serious: 'Status: Serious',\n critical: 'Status: Critical',\n};\n\n/**\n * Render Astro-compliant status shape\n * Shapes per https://www.astrouxds.com/patterns/status-system/\n */\nconst renderStatusShape = (\n status: StatusVariant,\n size: number,\n fillColor: string,\n borderColor?: string,\n): React.ReactNode => {\n const hasBorder = !!borderColor;\n const strokeWidth = hasBorder ? 1.5 : 0;\n \n switch (status) {\n // Small filled circle: off\n case 'off':\n return (\n <svg viewBox=\"0 0 12 12\" width={size} height={size}>\n <circle cx=\"6\" cy=\"6\" r={hasBorder ? 2.5 : 3} fill={fillColor} stroke={borderColor} strokeWidth={strokeWidth} />\n </svg>\n );\n \n // Ring (donut): standby\n case 'standby':\n return (\n <svg viewBox=\"0 0 12 12\" width={size} height={size}>\n <circle cx=\"6\" cy=\"6\" r=\"3.5\" fill=\"none\" stroke={fillColor} strokeWidth=\"2\" />\n {hasBorder && <circle cx=\"6\" cy=\"6\" r=\"4.75\" fill=\"none\" stroke={borderColor} strokeWidth={strokeWidth} />}\n </svg>\n );\n \n // Filled circle: normal\n case 'normal':\n return (\n <svg viewBox=\"0 0 12 12\" width={size} height={size}>\n <circle cx=\"6\" cy=\"6\" r={hasBorder ? 4.5 : 5} fill={fillColor} stroke={borderColor} strokeWidth={strokeWidth} />\n </svg>\n );\n \n // Square shape: caution\n case 'caution':\n return (\n <svg viewBox=\"0 0 12 12\" width={size} height={size}>\n <rect\n x={hasBorder ? 1.5 : 1}\n y={hasBorder ? 1.5 : 1}\n width={hasBorder ? 9 : 10}\n height={hasBorder ? 9 : 10}\n fill={fillColor}\n stroke={borderColor}\n strokeWidth={strokeWidth}\n />\n </svg>\n );\n \n // Diamond shape: serious (rotated square)\n case 'serious':\n return (\n <svg viewBox=\"0 0 12 12\" width={size} height={size}>\n <polygon\n points=\"6,1 11,6 6,11 1,6\"\n fill={fillColor}\n stroke={borderColor}\n strokeWidth={strokeWidth}\n />\n </svg>\n );\n \n // Triangle pointing down: critical\n case 'critical':\n return (\n <svg viewBox=\"0 0 12 12\" width={size} height={size}>\n <polygon\n points=\"6,11 1,2 11,2\"\n fill={fillColor}\n stroke={borderColor}\n strokeWidth={strokeWidth}\n />\n </svg>\n );\n \n default:\n return null;\n }\n};\n\n/**\n * StatusIndicator - Pure React status component\n * \n * Displays standardized status symbols following Astro UX design patterns.\n * Uses dual-coding (color + shape) for WCAG 2.1 AA accessibility compliance.\n * \n * @example\n * ```tsx\n * <StatusIndicator status=\"normal\" label=\"Power System\" />\n * <StatusIndicator status=\"caution\" label=\"Battery Low\" />\n * <StatusIndicator status=\"critical\" label=\"Comm Loss\" pulse />\n * ```\n */\nexport const StatusIndicator = memo(function StatusIndicator({\n status,\n label,\n small = false,\n pulse = false,\n bordered,\n className = '',\n onClick,\n}: StatusIndicatorProps): React.ReactElement {\n const { tokens, mode } = useTheme();\n \n // Determine if we need borders (light theme or explicitly requested)\n const isLightTheme = mode === 'light';\n const showBorder = bordered ?? isLightTheme;\n \n // Get colors from theme or use Astro defaults\n const fillColor = isLightTheme \n ? STATUS_COLORS_LIGHT_FILL[status]\n : (tokens.colors.status[status] || STATUS_COLORS_DARK[status]);\n const borderColor = showBorder ? STATUS_COLORS_LIGHT_BORDER[status] : undefined;\n \n const size = small ? 10 : 14;\n const shouldPulse = pulse || status === 'critical';\n const isCircle = status === 'off' || status === 'standby' || status === 'normal';\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (onClick && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n onClick();\n }\n };\n\n return (\n <div\n className={classNames('zendir-status-indicator', className)}\n onClick={onClick}\n onKeyDown={onClick ? handleKeyDown : undefined}\n tabIndex={onClick ? 0 : undefined}\n role=\"status\"\n aria-label={`${STATUS_ARIA_LABELS[status]}${label ? `: ${label}` : ''}`}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: small ? 4 : 6,\n cursor: onClick ? 'pointer' : 'default',\n outline: 'none',\n }}\n >\n {/* Status symbol with dual-coding */}\n <span\n style={{\n position: 'relative',\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: size,\n height: size,\n flexShrink: 0,\n }}\n >\n {/* Pulse animation ring */}\n {shouldPulse && (\n <span\n style={{\n position: 'absolute',\n inset: -3,\n borderRadius: isCircle ? '50%' : 0,\n backgroundColor: fillColor,\n opacity: 0.3,\n animation: 'statusPulse 2s ease-out infinite',\n }}\n />\n )}\n \n {/* Astro-compliant status shape */}\n {renderStatusShape(status, size, fillColor, borderColor)}\n </span>\n\n {/* Label with theme typography */}\n {label && (\n <span\n style={{\n fontSize: small ? tokens.typography.fontSize.xs : tokens.typography.fontSize.sm,\n fontWeight: tokens.typography.fontWeight.medium,\n color: 'inherit',\n whiteSpace: 'nowrap',\n letterSpacing: tokens.typography.letterSpacing.normal,\n }}\n >\n {label}\n </span>\n )}\n\n {/* Keyframe animation — paused when prefers-reduced-motion is active */}\n <style>{`\n @keyframes statusPulse {\n 0% { transform: scale(1); opacity: 0.3; }\n 50% { transform: scale(1.5); opacity: 0; }\n 100% { transform: scale(1); opacity: 0; }\n }\n @media (prefers-reduced-motion: reduce) {\n .zendir-status-indicator span[style*=\"statusPulse\"] {\n animation: none !important;\n }\n }\n `}</style>\n </div>\n );\n});\n"],"names":["StatusIndicator"],"mappings":"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"}
@@ -0,0 +1,106 @@
1
+ import { default as React } from 'react';
2
+
3
+ export type TimelineViewMode = 'list' | 'chart' | 'scatter';
4
+ export interface TimelineEvent {
5
+ /** Unique identifier */
6
+ id: string;
7
+ /** Event title */
8
+ title: string;
9
+ /** Start time */
10
+ start: Date;
11
+ /** End time (optional for point events) */
12
+ end?: Date;
13
+ /** Track/category this event belongs to */
14
+ track?: string;
15
+ /** Status for coloring */
16
+ status?: 'off' | 'standby' | 'normal' | 'caution' | 'serious' | 'critical';
17
+ /** Badge text */
18
+ badge?: string;
19
+ /** Badge variant - uses AstroUXDS status terms */
20
+ badgeVariant?: 'default' | 'primary' | 'normal' | 'caution' | 'serious' | 'critical';
21
+ /** Subtitle/description */
22
+ subtitle?: string;
23
+ /** Additional timestamps to display in list view */
24
+ timestamps?: {
25
+ label: string;
26
+ value: string;
27
+ status?: 'normal' | 'standby' | 'caution' | 'serious' | 'critical' | 'off';
28
+ }[];
29
+ /** Arguments/metadata */
30
+ arguments?: Record<string, string | number | boolean>;
31
+ /** Custom metadata */
32
+ metadata?: Record<string, unknown>;
33
+ }
34
+ export interface TimelineTrackDef {
35
+ /** Track identifier */
36
+ id: string;
37
+ /** Display label */
38
+ label: string;
39
+ /** Track height in pixels */
40
+ height?: number;
41
+ }
42
+ export type TimeFormat = 'relative' | 'absolute' | 'utc';
43
+ export interface TimelineFilter {
44
+ /** Filter by track IDs */
45
+ tracks?: string[];
46
+ /** Filter by status */
47
+ status?: TimelineEvent['status'][];
48
+ /** Search query */
49
+ search?: string;
50
+ }
51
+ export interface UnifiedTimelineProps {
52
+ /** Timeline title */
53
+ title?: string;
54
+ /** Events to display */
55
+ events: TimelineEvent[];
56
+ /** Track definitions for chart view */
57
+ tracks?: TimelineTrackDef[];
58
+ /** Start time for chart view (auto-calculated if not provided) */
59
+ start?: Date;
60
+ /** End time for chart view (auto-calculated if not provided) */
61
+ end?: Date;
62
+ /** Default view mode */
63
+ defaultView?: TimelineViewMode;
64
+ /** Controlled view mode */
65
+ viewMode?: TimelineViewMode;
66
+ /** View mode change handler */
67
+ onViewModeChange?: (mode: TimelineViewMode) => void;
68
+ /** Event click handler */
69
+ onEventClick?: (event: TimelineEvent) => void;
70
+ /** Show view toggle */
71
+ showViewToggle?: boolean;
72
+ /** Max height for scrollable container */
73
+ maxHeight?: string | number;
74
+ /** Track height for chart view */
75
+ trackHeight?: number;
76
+ /** Custom className */
77
+ className?: string;
78
+ /** Time format for axis labels */
79
+ timeFormat?: TimeFormat;
80
+ /** Enable zoom controls */
81
+ zoomable?: boolean;
82
+ /** Initial zoom level (1 = 100%) */
83
+ initialZoom?: number;
84
+ /** Show filter controls */
85
+ showFilters?: boolean;
86
+ /** Controlled filter state */
87
+ filter?: TimelineFilter;
88
+ /** Filter change handler */
89
+ onFilterChange?: (filter: TimelineFilter) => void;
90
+ /** Show event count badge */
91
+ showCount?: boolean;
92
+ /** Loading state */
93
+ loading?: boolean;
94
+ /** Reference time for relative format (defaults to start of range) */
95
+ referenceTime?: Date;
96
+ /** Show playhead indicator at current time */
97
+ showPlayhead?: boolean;
98
+ /** Custom playhead time (for simulation mode) */
99
+ playheadTime?: Date;
100
+ /** Callback when playhead time changes (for interactive playhead) */
101
+ onPlayheadChange?: (time: Date) => void;
102
+ /** Show day markers at midnight */
103
+ showDayMarkers?: boolean;
104
+ }
105
+ export declare const UnifiedTimeline: React.NamedExoticComponent<UnifiedTimelineProps>;
106
+ export default UnifiedTimeline;