@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,1768 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { memo, useState, useCallback, useMemo, useRef } from "react";
3
+ import { classNames, safeAccentText } from "../utils/index.js";
4
+ import { Icon } from "../core/Icon.js";
5
+ import { Badge } from "../core/Badge.js";
6
+ import { Tooltip } from "../core/Tooltip.js";
7
+ import { useTheme } from "../theme/ThemeProvider.js";
8
+ function TimelineStatusMarker({
9
+ status,
10
+ fillColor,
11
+ size = 12
12
+ }) {
13
+ const effectiveStatus = status ?? "normal";
14
+ const glow = `${fillColor}60`;
15
+ switch (effectiveStatus) {
16
+ case "off":
17
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, style: { flexShrink: 0, filter: `drop-shadow(0 0 4px ${glow})` }, children: /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "3", fill: fillColor }) });
18
+ case "standby":
19
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, style: { flexShrink: 0, filter: `drop-shadow(0 0 4px ${glow})` }, children: /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "3.5", fill: "none", stroke: fillColor, strokeWidth: "2" }) });
20
+ case "normal":
21
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, style: { flexShrink: 0, filter: `drop-shadow(0 0 4px ${glow})` }, children: /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "5", fill: fillColor }) });
22
+ case "caution":
23
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, style: { flexShrink: 0, filter: `drop-shadow(0 0 4px ${glow})` }, children: /* @__PURE__ */ jsx("rect", { x: "1", y: "1", width: "10", height: "10", fill: fillColor }) });
24
+ case "serious":
25
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, style: { flexShrink: 0, filter: `drop-shadow(0 0 4px ${glow})` }, children: /* @__PURE__ */ jsx("polygon", { points: "6,1 11,6 6,11 1,6", fill: fillColor }) });
26
+ case "critical":
27
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, style: { flexShrink: 0, filter: `drop-shadow(0 0 4px ${glow})` }, children: /* @__PURE__ */ jsx("polygon", { points: "6,11 1,2 11,2", fill: fillColor }) });
28
+ default:
29
+ return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, style: { flexShrink: 0, filter: `drop-shadow(0 0 4px ${glow})` }, children: /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "5", fill: fillColor }) });
30
+ }
31
+ }
32
+ const EventListItem = memo(function EventListItem2({
33
+ event,
34
+ isLast,
35
+ onEventClick
36
+ }) {
37
+ const { tokens } = useTheme();
38
+ const [expanded, setExpanded] = useState(false);
39
+ const [hovered, setHovered] = useState(false);
40
+ const hasArguments = event.arguments && Object.keys(event.arguments).length > 0;
41
+ const argumentCount = hasArguments ? Object.keys(event.arguments).length : 0;
42
+ const timestamps = event.timestamps || [
43
+ { label: "Time", value: event.start.toLocaleString(), status: event.status }
44
+ ];
45
+ const displayStatus = event.badgeVariant && event.badgeVariant !== "default" && event.badgeVariant !== "primary" ? event.badgeVariant : event.status ?? "normal";
46
+ const markerColor = tokens.colors.status[displayStatus];
47
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "16px" }, children: [
48
+ /* @__PURE__ */ jsxs(
49
+ "div",
50
+ {
51
+ style: {
52
+ display: "flex",
53
+ flexDirection: "column",
54
+ alignItems: "center",
55
+ width: "20px",
56
+ flexShrink: 0
57
+ },
58
+ children: [
59
+ /* @__PURE__ */ jsx("div", { style: { marginTop: "8px" }, children: /* @__PURE__ */ jsx(TimelineStatusMarker, { status: displayStatus, fillColor: markerColor, size: 12 }) }),
60
+ !isLast && /* @__PURE__ */ jsx(
61
+ "div",
62
+ {
63
+ style: {
64
+ width: "2px",
65
+ flex: 1,
66
+ backgroundColor: `${tokens.colors.accent.primary}30`,
67
+ marginTop: "4px"
68
+ }
69
+ }
70
+ )
71
+ ]
72
+ }
73
+ ),
74
+ /* @__PURE__ */ jsxs(
75
+ "div",
76
+ {
77
+ onMouseEnter: () => setHovered(true),
78
+ onMouseLeave: () => setHovered(false),
79
+ onClick: () => onEventClick == null ? void 0 : onEventClick(event),
80
+ style: {
81
+ flex: 1,
82
+ marginBottom: "16px",
83
+ padding: "16px 20px",
84
+ backgroundColor: tokens.colors.background.surface,
85
+ border: `1px solid ${hovered ? tokens.colors.accent.primary : tokens.colors.border.muted}`,
86
+ borderRadius: tokens.borderRadius.lg,
87
+ cursor: onEventClick ? "pointer" : "default",
88
+ transition: "all 200ms cubic-bezier(0.4, 0, 0.2, 1)",
89
+ boxShadow: hovered ? `0 4px 20px ${tokens.colors.accent.primary}15, 0 0 0 1px ${tokens.colors.accent.primary}20` : "none"
90
+ },
91
+ children: [
92
+ /* @__PURE__ */ jsxs(
93
+ "div",
94
+ {
95
+ style: {
96
+ display: "flex",
97
+ alignItems: "center",
98
+ justifyContent: "space-between",
99
+ marginBottom: timestamps.length ? "12px" : 0
100
+ },
101
+ children: [
102
+ /* @__PURE__ */ jsx(
103
+ "h4",
104
+ {
105
+ style: {
106
+ margin: 0,
107
+ fontSize: "0.875rem",
108
+ fontWeight: 500,
109
+ // AstroUXDS medium (was 600)
110
+ color: tokens.colors.text.primary,
111
+ letterSpacing: "0.02em",
112
+ textTransform: "uppercase"
113
+ },
114
+ children: event.title
115
+ }
116
+ ),
117
+ event.badge && /* @__PURE__ */ jsx(
118
+ Badge,
119
+ {
120
+ variant: displayStatus === "caution" || displayStatus === "serious" ? "filled" : "outline",
121
+ size: "small",
122
+ status: displayStatus === "critical" ? "critical" : displayStatus === "serious" ? "serious" : displayStatus === "caution" ? "caution" : displayStatus === "normal" ? "normal" : void 0,
123
+ children: event.badge
124
+ }
125
+ )
126
+ ]
127
+ }
128
+ ),
129
+ event.subtitle && /* @__PURE__ */ jsx(
130
+ "p",
131
+ {
132
+ style: {
133
+ margin: "0 0 12px 0",
134
+ fontSize: "0.8125rem",
135
+ color: tokens.colors.text.secondary
136
+ },
137
+ children: event.subtitle
138
+ }
139
+ ),
140
+ timestamps.length > 0 && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: timestamps.map((ts, index) => /* @__PURE__ */ jsxs(
141
+ "div",
142
+ {
143
+ style: {
144
+ display: "flex",
145
+ alignItems: "center",
146
+ justifyContent: "space-between",
147
+ fontSize: "0.8125rem"
148
+ },
149
+ children: [
150
+ /* @__PURE__ */ jsxs(
151
+ "span",
152
+ {
153
+ style: {
154
+ display: "flex",
155
+ alignItems: "center",
156
+ gap: "8px",
157
+ color: tokens.colors.text.secondary
158
+ },
159
+ children: [
160
+ /* @__PURE__ */ jsx(
161
+ TimelineStatusMarker,
162
+ {
163
+ status: ts.status ?? "normal",
164
+ fillColor: ts.status ? tokens.colors.status[ts.status] : tokens.colors.accent.primary,
165
+ size: 6
166
+ }
167
+ ),
168
+ ts.label
169
+ ]
170
+ }
171
+ ),
172
+ /* @__PURE__ */ jsx(
173
+ "span",
174
+ {
175
+ style: {
176
+ fontFamily: tokens.typography.fontFamily.mono,
177
+ color: tokens.colors.text.primary,
178
+ fontWeight: 500
179
+ },
180
+ children: ts.value
181
+ }
182
+ )
183
+ ]
184
+ },
185
+ index
186
+ )) }),
187
+ hasArguments && /* @__PURE__ */ jsxs(Fragment, { children: [
188
+ /* @__PURE__ */ jsxs(
189
+ "button",
190
+ {
191
+ type: "button",
192
+ onClick: (e) => {
193
+ e.stopPropagation();
194
+ setExpanded(!expanded);
195
+ },
196
+ style: {
197
+ display: "flex",
198
+ alignItems: "center",
199
+ gap: "6px",
200
+ marginTop: "12px",
201
+ padding: 0,
202
+ background: "none",
203
+ border: "none",
204
+ color: tokens.colors.text.secondary,
205
+ fontSize: "0.75rem",
206
+ cursor: "pointer",
207
+ transition: "color 150ms ease"
208
+ },
209
+ onMouseEnter: (e) => e.currentTarget.style.color = tokens.colors.accent.primary,
210
+ onMouseLeave: (e) => e.currentTarget.style.color = tokens.colors.text.secondary,
211
+ children: [
212
+ /* @__PURE__ */ jsx(
213
+ "svg",
214
+ {
215
+ width: "10",
216
+ height: "10",
217
+ viewBox: "0 0 24 24",
218
+ fill: "currentColor",
219
+ style: {
220
+ transform: expanded ? "rotate(90deg)" : "rotate(0deg)",
221
+ transition: "transform 150ms ease"
222
+ },
223
+ children: /* @__PURE__ */ jsx("path", { d: "M8 5v14l11-7z" })
224
+ }
225
+ ),
226
+ expanded ? "Hide" : "Show",
227
+ " Arguments (",
228
+ argumentCount,
229
+ ")"
230
+ ]
231
+ }
232
+ ),
233
+ expanded && /* @__PURE__ */ jsxs(
234
+ "div",
235
+ {
236
+ style: {
237
+ marginTop: "12px",
238
+ borderTop: `1px solid ${tokens.colors.border.muted}`,
239
+ paddingTop: "12px",
240
+ animation: "zendir-expand 200ms ease-out"
241
+ },
242
+ children: [
243
+ /* @__PURE__ */ jsx("style", { children: `@keyframes zendir-expand { from { opacity: 0; transform: translateY(-8px); } to { opacity: 1; transform: translateY(0); } }` }),
244
+ Object.entries(event.arguments).map(([key, value]) => /* @__PURE__ */ jsxs(
245
+ "div",
246
+ {
247
+ style: {
248
+ display: "flex",
249
+ alignItems: "center",
250
+ justifyContent: "space-between",
251
+ padding: "8px 12px",
252
+ marginBottom: "4px",
253
+ backgroundColor: tokens.colors.background.elevated,
254
+ borderRadius: tokens.borderRadius.md,
255
+ fontSize: "0.8125rem"
256
+ },
257
+ children: [
258
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.secondary }, children: key }),
259
+ /* @__PURE__ */ jsx(
260
+ "span",
261
+ {
262
+ style: {
263
+ fontFamily: tokens.typography.fontFamily.mono,
264
+ color: typeof value === "boolean" ? value ? tokens.colors.status.normal : tokens.colors.text.tertiary : tokens.colors.text.primary,
265
+ fontWeight: 500
266
+ },
267
+ children: String(value)
268
+ }
269
+ )
270
+ ]
271
+ },
272
+ key
273
+ ))
274
+ ]
275
+ }
276
+ )
277
+ ] })
278
+ ]
279
+ }
280
+ )
281
+ ] });
282
+ });
283
+ const ChartView = memo(function ChartView2({
284
+ events,
285
+ tracks,
286
+ start,
287
+ end,
288
+ trackHeight,
289
+ onEventClick,
290
+ zoom,
291
+ showPlayhead = true,
292
+ playheadTime,
293
+ onPlayheadChange: _onPlayheadChange,
294
+ showDayMarkers = true
295
+ }) {
296
+ const { tokens, theme } = useTheme();
297
+ const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
298
+ const [hoveredEvent, setHoveredEvent] = useState(null);
299
+ const [tooltipPos, setTooltipPos] = useState(null);
300
+ const scrollContainerRef = useRef(null);
301
+ const totalDuration = end.getTime() - start.getTime();
302
+ const trackLabelWidth = 130;
303
+ const timeLabels = useMemo(() => {
304
+ const labels = [];
305
+ const baseLabelCount = 6;
306
+ const labelCount = Math.round(baseLabelCount * zoom);
307
+ for (let i = 0; i <= labelCount; i++) {
308
+ const percent = i / labelCount * 100;
309
+ const time = new Date(start.getTime() + totalDuration * percent / 100);
310
+ labels.push({ time, percent });
311
+ }
312
+ return labels;
313
+ }, [start, totalDuration, zoom]);
314
+ const eventsByTrack = useMemo(() => {
315
+ const grouped = {};
316
+ tracks.forEach((track) => {
317
+ grouped[track.id] = events.filter((e) => e.track === track.id);
318
+ });
319
+ const unassigned = events.filter((e) => !e.track);
320
+ if (unassigned.length > 0 && tracks.length > 0) {
321
+ grouped[tracks[0].id] = [...grouped[tracks[0].id] || [], ...unassigned];
322
+ }
323
+ return grouped;
324
+ }, [events, tracks]);
325
+ const eventOverlaps = useMemo(() => {
326
+ const overlaps = {};
327
+ Object.entries(eventsByTrack).forEach(([_trackId, trackEvents]) => {
328
+ const sorted = [...trackEvents].sort((a, b) => a.start.getTime() - b.start.getTime());
329
+ sorted.forEach((event) => {
330
+ const eventStart = event.start.getTime();
331
+ const eventEnd = (event.end || new Date(eventStart + 3e5)).getTime();
332
+ const overlapping = sorted.filter((other) => {
333
+ if (other.id === event.id) return false;
334
+ const otherStart = other.start.getTime();
335
+ const otherEnd = (other.end || new Date(otherStart + 3e5)).getTime();
336
+ return eventStart < otherEnd && eventEnd > otherStart;
337
+ });
338
+ let stackIndex = 0;
339
+ if (overlapping.length > 0) {
340
+ const usedIndices = overlapping.filter((o) => overlaps[o.id] !== void 0).map((o) => overlaps[o.id].stackIndex);
341
+ while (usedIndices.includes(stackIndex)) {
342
+ stackIndex++;
343
+ }
344
+ }
345
+ overlaps[event.id] = {
346
+ stackIndex,
347
+ overlapCount: overlapping.length,
348
+ overlappingIds: overlapping.map((o) => o.id)
349
+ };
350
+ });
351
+ });
352
+ return overlaps;
353
+ }, [eventsByTrack]);
354
+ const dayMarkers = useMemo(() => {
355
+ const markers = [];
356
+ const current = new Date(start);
357
+ current.setUTCHours(0, 0, 0, 0);
358
+ if (current.getTime() < start.getTime()) {
359
+ current.setUTCDate(current.getUTCDate() + 1);
360
+ }
361
+ while (current.getTime() <= end.getTime()) {
362
+ const percent = (current.getTime() - start.getTime()) / totalDuration * 100;
363
+ if (percent >= 0 && percent <= 100) {
364
+ markers.push({ time: new Date(current), percent });
365
+ }
366
+ current.setUTCDate(current.getUTCDate() + 1);
367
+ }
368
+ return markers;
369
+ }, [start, end, totalDuration]);
370
+ const formatTime = (date, showSeconds = false) => {
371
+ const options = {
372
+ hour: "2-digit",
373
+ minute: "2-digit",
374
+ ...showSeconds && { second: "2-digit" }
375
+ };
376
+ return date.toLocaleTimeString([], options);
377
+ };
378
+ const formatDuration = (ms) => {
379
+ const totalSeconds = Math.floor(ms / 1e3);
380
+ const hours = Math.floor(totalSeconds / 3600);
381
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
382
+ const seconds = totalSeconds % 60;
383
+ if (hours > 0) return `${hours}h ${minutes}m`;
384
+ if (minutes > 0) return `${minutes}m ${seconds}s`;
385
+ return `${seconds}s`;
386
+ };
387
+ const formatUTC = (date) => {
388
+ return date.toISOString().replace("T", " ").substring(0, 19) + " UTC";
389
+ };
390
+ const getEventPosition = (event) => {
391
+ const eventStart = event.start.getTime();
392
+ const eventEnd = (event.end || new Date(eventStart + 3e5)).getTime();
393
+ const leftPercent = (eventStart - start.getTime()) / totalDuration * 100;
394
+ const widthPercent = (eventEnd - eventStart) / totalDuration * 100;
395
+ return {
396
+ left: `${Math.max(0, Math.min(100, leftPercent))}%`,
397
+ width: `${Math.max(2, Math.min(100 - leftPercent, widthPercent))}%`
398
+ };
399
+ };
400
+ const getStatusColor = (status) => {
401
+ if (!status) return tokens.colors.accent.primary;
402
+ return tokens.colors.status[status] || tokens.colors.accent.primary;
403
+ };
404
+ const getStatusLabel = (status) => {
405
+ const labels = {
406
+ normal: "Normal",
407
+ standby: "Standby",
408
+ caution: "Caution",
409
+ serious: "Serious",
410
+ critical: "Critical",
411
+ off: "Off"
412
+ };
413
+ return labels[status || ""] || "Unknown";
414
+ };
415
+ const currentPlayheadTime = playheadTime || /* @__PURE__ */ new Date();
416
+ const now = currentPlayheadTime.getTime();
417
+ const playheadPercent = showPlayhead && now >= start.getTime() && now <= end.getTime() ? (now - start.getTime()) / totalDuration * 100 : null;
418
+ const hoveredEventData = hoveredEvent ? events.find((e) => e.id === hoveredEvent) : null;
419
+ return /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
420
+ /* @__PURE__ */ jsx(
421
+ "div",
422
+ {
423
+ ref: scrollContainerRef,
424
+ className: "zendir-timeline-scroll",
425
+ style: {
426
+ overflowX: "auto",
427
+ overflowY: "hidden",
428
+ position: "relative"
429
+ },
430
+ children: /* @__PURE__ */ jsxs(
431
+ "div",
432
+ {
433
+ style: {
434
+ width: `${zoom * 100}%`,
435
+ minWidth: "100%",
436
+ position: "relative"
437
+ },
438
+ children: [
439
+ /* @__PURE__ */ jsxs(
440
+ "div",
441
+ {
442
+ style: {
443
+ display: "flex",
444
+ height: 32,
445
+ borderBottom: `1px solid ${tokens.colors.accent.primary}20`,
446
+ position: "sticky",
447
+ top: 0,
448
+ zIndex: 20,
449
+ backgroundColor: isTransparentTheme ? "transparent" : tokens.colors.background.surface,
450
+ ...isTransparentTheme && { backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)" }
451
+ },
452
+ children: [
453
+ /* @__PURE__ */ jsx(
454
+ "div",
455
+ {
456
+ style: {
457
+ width: trackLabelWidth,
458
+ flexShrink: 0,
459
+ position: "sticky",
460
+ left: 0,
461
+ zIndex: 25,
462
+ backgroundColor: isTransparentTheme ? "transparent" : tokens.colors.background.surface,
463
+ ...isTransparentTheme && { backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)" },
464
+ borderRight: `1px solid ${tokens.colors.border.muted}30`,
465
+ display: "flex",
466
+ alignItems: "center",
467
+ paddingLeft: 12,
468
+ fontSize: "0.625rem",
469
+ fontWeight: 500,
470
+ // AstroUXDS medium (was 600)
471
+ color: tokens.colors.text.tertiary,
472
+ textTransform: "uppercase",
473
+ letterSpacing: "0.08em"
474
+ },
475
+ children: "Tracks"
476
+ }
477
+ ),
478
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1, position: "relative" }, children: [
479
+ showDayMarkers && dayMarkers.map((marker, index) => /* @__PURE__ */ jsx(
480
+ "div",
481
+ {
482
+ style: {
483
+ position: "absolute",
484
+ left: `${marker.percent}%`,
485
+ top: 0,
486
+ height: "100%",
487
+ display: "flex",
488
+ flexDirection: "column",
489
+ alignItems: "center",
490
+ zIndex: 5
491
+ },
492
+ children: /* @__PURE__ */ jsx(
493
+ "span",
494
+ {
495
+ style: {
496
+ fontSize: "0.5rem",
497
+ color: tokens.colors.status.caution,
498
+ fontFamily: tokens.typography.fontFamily.mono,
499
+ whiteSpace: "nowrap",
500
+ backgroundColor: `${tokens.colors.status.caution}20`,
501
+ padding: "1px 4px",
502
+ borderRadius: 2,
503
+ marginTop: 2
504
+ },
505
+ children: marker.time.toLocaleDateString([], { month: "short", day: "numeric" })
506
+ }
507
+ )
508
+ },
509
+ `day-${index}`
510
+ )),
511
+ timeLabels.map((label, index) => /* @__PURE__ */ jsx(
512
+ "span",
513
+ {
514
+ style: {
515
+ position: "absolute",
516
+ left: `${label.percent}%`,
517
+ transform: "translateX(-50%)",
518
+ top: 8,
519
+ fontSize: "0.6875rem",
520
+ color: tokens.colors.text.tertiary,
521
+ fontFamily: tokens.typography.fontFamily.mono,
522
+ whiteSpace: "nowrap"
523
+ },
524
+ children: formatTime(label.time)
525
+ },
526
+ index
527
+ ))
528
+ ] })
529
+ ]
530
+ }
531
+ ),
532
+ tracks.map((track) => /* @__PURE__ */ jsxs(
533
+ "div",
534
+ {
535
+ "aria-label": track.label,
536
+ style: {
537
+ display: "flex",
538
+ height: track.height || trackHeight,
539
+ borderBottom: `1px solid ${tokens.colors.accent.primary}10`
540
+ },
541
+ children: [
542
+ /* @__PURE__ */ jsx(
543
+ "div",
544
+ {
545
+ style: {
546
+ width: trackLabelWidth,
547
+ flexShrink: 0,
548
+ position: "sticky",
549
+ left: 0,
550
+ zIndex: 15,
551
+ display: "flex",
552
+ alignItems: "center",
553
+ paddingLeft: 12,
554
+ fontSize: "0.6875rem",
555
+ fontWeight: 500,
556
+ // AstroUXDS medium (was 600)
557
+ color: tokens.colors.text.secondary,
558
+ textTransform: "uppercase",
559
+ letterSpacing: "0.05em",
560
+ backgroundColor: isTransparentTheme ? "transparent" : tokens.colors.background.surface,
561
+ ...isTransparentTheme && { backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)" },
562
+ borderRight: `1px solid ${tokens.colors.border.muted}30`,
563
+ boxShadow: "2px 0 8px rgba(0,0,0,0.15)"
564
+ },
565
+ children: track.label
566
+ }
567
+ ),
568
+ /* @__PURE__ */ jsxs(
569
+ "div",
570
+ {
571
+ style: {
572
+ flex: 1,
573
+ position: "relative",
574
+ height: "100%"
575
+ },
576
+ children: [
577
+ showDayMarkers && dayMarkers.map((marker, index) => /* @__PURE__ */ jsx(
578
+ "div",
579
+ {
580
+ style: {
581
+ position: "absolute",
582
+ left: `${marker.percent}%`,
583
+ top: 0,
584
+ bottom: 0,
585
+ width: 1,
586
+ backgroundColor: `${tokens.colors.status.caution}25`,
587
+ zIndex: 1,
588
+ pointerEvents: "none"
589
+ }
590
+ },
591
+ `day-line-${index}`
592
+ )),
593
+ (eventsByTrack[track.id] || []).map((event) => {
594
+ const { left, width } = getEventPosition(event);
595
+ const color = getStatusColor(event.status);
596
+ const isHovered = hoveredEvent === event.id;
597
+ const overlap = eventOverlaps[event.id];
598
+ const hasOverlap = overlap && overlap.overlapCount > 0;
599
+ const cardHeight = hasOverlap ? 28 : 36;
600
+ const stackOffset = overlap ? overlap.stackIndex * 30 : 0;
601
+ const baseTop = ((track.height || trackHeight) - cardHeight) / 2;
602
+ return /* @__PURE__ */ jsxs(
603
+ "button",
604
+ {
605
+ type: "button",
606
+ onClick: () => onEventClick == null ? void 0 : onEventClick(event),
607
+ onMouseEnter: (e) => {
608
+ setHoveredEvent(event.id);
609
+ const rect = e.currentTarget.getBoundingClientRect();
610
+ setTooltipPos({ x: rect.left + rect.width / 2, y: rect.top - 8 });
611
+ },
612
+ onMouseLeave: () => {
613
+ setHoveredEvent(null);
614
+ setTooltipPos(null);
615
+ },
616
+ className: "zendir-timeline-region",
617
+ style: {
618
+ position: "absolute",
619
+ left,
620
+ width,
621
+ minWidth: 50,
622
+ height: cardHeight,
623
+ top: Math.min(baseTop + stackOffset, (track.height || trackHeight) - cardHeight - 4),
624
+ backgroundColor: "rgba(11, 26, 40, 0.95)",
625
+ border: `1px solid ${isHovered ? color : `${tokens.colors.accent.primary}30`}`,
626
+ borderRadius: "4px",
627
+ cursor: onEventClick ? "pointer" : "default",
628
+ display: "flex",
629
+ alignItems: "center",
630
+ overflow: "hidden",
631
+ zIndex: isHovered ? 100 : 1,
632
+ boxShadow: isHovered ? `0 8px 24px rgba(0, 0, 0, 0.5), 0 0 0 1px ${color}60` : "0 2px 6px rgba(0, 0, 0, 0.25)",
633
+ transition: "all 150ms cubic-bezier(0.4, 0, 0.2, 1)",
634
+ transform: isHovered ? "translateY(-3px) scale(1.02)" : "none"
635
+ },
636
+ children: [
637
+ /* @__PURE__ */ jsx(
638
+ "div",
639
+ {
640
+ style: {
641
+ width: 4,
642
+ height: "100%",
643
+ backgroundColor: color,
644
+ flexShrink: 0,
645
+ borderRadius: "2px 0 0 2px"
646
+ }
647
+ }
648
+ ),
649
+ /* @__PURE__ */ jsxs(
650
+ "div",
651
+ {
652
+ style: {
653
+ flex: 1,
654
+ padding: "4px 8px",
655
+ overflow: "hidden",
656
+ minWidth: 0
657
+ },
658
+ children: [
659
+ /* @__PURE__ */ jsx(
660
+ "div",
661
+ {
662
+ style: {
663
+ display: "flex",
664
+ alignItems: "center",
665
+ gap: 4
666
+ },
667
+ children: /* @__PURE__ */ jsx(
668
+ "span",
669
+ {
670
+ style: {
671
+ fontSize: "0.6875rem",
672
+ fontWeight: 500,
673
+ // AstroUXDS medium (was 600)
674
+ color: "#fff",
675
+ whiteSpace: "nowrap",
676
+ overflow: "hidden",
677
+ textOverflow: "ellipsis"
678
+ },
679
+ children: event.title
680
+ }
681
+ )
682
+ }
683
+ ),
684
+ event.subtitle && !hasOverlap && /* @__PURE__ */ jsx(
685
+ "div",
686
+ {
687
+ style: {
688
+ fontSize: "0.5625rem",
689
+ color: "rgba(255, 255, 255, 0.5)",
690
+ whiteSpace: "nowrap",
691
+ overflow: "hidden",
692
+ textOverflow: "ellipsis",
693
+ marginTop: 1
694
+ },
695
+ children: event.subtitle
696
+ }
697
+ )
698
+ ]
699
+ }
700
+ ),
701
+ hasOverlap && overlap.stackIndex === 0 && /* @__PURE__ */ jsxs(
702
+ "div",
703
+ {
704
+ style: {
705
+ position: "absolute",
706
+ top: -6,
707
+ right: -6,
708
+ minWidth: 18,
709
+ height: 18,
710
+ backgroundColor: tokens.colors.status.caution,
711
+ borderRadius: 9,
712
+ display: "flex",
713
+ alignItems: "center",
714
+ justifyContent: "center",
715
+ fontSize: "0.625rem",
716
+ fontWeight: 700,
717
+ color: "#000",
718
+ boxShadow: "0 2px 6px rgba(0, 0, 0, 0.3)",
719
+ zIndex: 10
720
+ },
721
+ title: `${overlap.overlapCount + 1} overlapping events`,
722
+ children: [
723
+ "+",
724
+ overlap.overlapCount
725
+ ]
726
+ }
727
+ )
728
+ ]
729
+ },
730
+ event.id
731
+ );
732
+ })
733
+ ]
734
+ }
735
+ )
736
+ ]
737
+ },
738
+ track.id
739
+ )),
740
+ playheadPercent !== null && /* @__PURE__ */ jsxs(
741
+ "div",
742
+ {
743
+ style: {
744
+ position: "absolute",
745
+ top: 28,
746
+ bottom: 0,
747
+ left: `calc(${trackLabelWidth}px + ${playheadPercent}% * (100% - ${trackLabelWidth}px) / 100)`,
748
+ width: 2,
749
+ backgroundColor: tokens.colors.accent.primary,
750
+ boxShadow: `0 0 12px ${tokens.colors.accent.primary}`,
751
+ zIndex: 20,
752
+ pointerEvents: "none"
753
+ },
754
+ children: [
755
+ /* @__PURE__ */ jsx(
756
+ "div",
757
+ {
758
+ style: {
759
+ position: "absolute",
760
+ top: -6,
761
+ left: -5,
762
+ width: 12,
763
+ height: 12,
764
+ backgroundColor: tokens.colors.accent.primary,
765
+ borderRadius: 2,
766
+ transform: "rotate(45deg)",
767
+ boxShadow: `0 0 8px ${tokens.colors.accent.primary}`
768
+ }
769
+ }
770
+ ),
771
+ /* @__PURE__ */ jsx(
772
+ "div",
773
+ {
774
+ style: {
775
+ position: "absolute",
776
+ top: -22,
777
+ left: "50%",
778
+ transform: "translateX(-50%)",
779
+ backgroundColor: tokens.colors.accent.primary,
780
+ color: tokens.colors.background.base,
781
+ fontSize: "0.5625rem",
782
+ fontWeight: 500,
783
+ // AstroUXDS medium (was 600)
784
+ fontFamily: tokens.typography.fontFamily.mono,
785
+ padding: "2px 6px",
786
+ borderRadius: 3,
787
+ whiteSpace: "nowrap",
788
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.3)"
789
+ },
790
+ children: formatTime(currentPlayheadTime, true)
791
+ }
792
+ )
793
+ ]
794
+ }
795
+ )
796
+ ]
797
+ }
798
+ )
799
+ }
800
+ ),
801
+ hoveredEventData && tooltipPos && /* @__PURE__ */ jsxs(
802
+ "div",
803
+ {
804
+ style: {
805
+ position: "fixed",
806
+ left: tooltipPos.x,
807
+ top: tooltipPos.y,
808
+ transform: "translate(-50%, -100%)",
809
+ zIndex: 1e3,
810
+ pointerEvents: "none",
811
+ animation: "zendir-tooltip-appear 150ms ease"
812
+ },
813
+ children: [
814
+ /* @__PURE__ */ jsxs(
815
+ "div",
816
+ {
817
+ style: {
818
+ backgroundColor: "rgba(15, 23, 42, 0.98)",
819
+ border: `1px solid ${getStatusColor(hoveredEventData.status)}50`,
820
+ borderRadius: tokens.borderRadius.md,
821
+ padding: "12px 16px",
822
+ minWidth: 220,
823
+ maxWidth: 320,
824
+ boxShadow: `0 12px 40px rgba(0, 0, 0, 0.5), 0 0 0 1px ${getStatusColor(hoveredEventData.status)}30`,
825
+ backdropFilter: "blur(12px)"
826
+ },
827
+ children: [
828
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }, children: [
829
+ /* @__PURE__ */ jsx(
830
+ TimelineStatusMarker,
831
+ {
832
+ status: hoveredEventData.status,
833
+ fillColor: getStatusColor(hoveredEventData.status),
834
+ size: 10
835
+ }
836
+ ),
837
+ /* @__PURE__ */ jsx(
838
+ "span",
839
+ {
840
+ style: {
841
+ fontSize: "0.75rem",
842
+ fontWeight: 500,
843
+ // AstroUXDS medium (was 600)
844
+ color: getStatusColor(hoveredEventData.status),
845
+ textTransform: "uppercase",
846
+ letterSpacing: "0.05em"
847
+ },
848
+ children: getStatusLabel(hoveredEventData.status)
849
+ }
850
+ ),
851
+ hoveredEventData.badge && /* @__PURE__ */ jsx(
852
+ "span",
853
+ {
854
+ style: {
855
+ marginLeft: "auto",
856
+ fontSize: "0.625rem",
857
+ fontWeight: 500,
858
+ // AstroUXDS medium (was 600)
859
+ padding: "2px 6px",
860
+ borderRadius: tokens.borderRadius.sm,
861
+ backgroundColor: `${getStatusColor(hoveredEventData.status)}20`,
862
+ color: getStatusColor(hoveredEventData.status)
863
+ },
864
+ children: hoveredEventData.badge
865
+ }
866
+ )
867
+ ] }),
868
+ /* @__PURE__ */ jsx(
869
+ "div",
870
+ {
871
+ style: {
872
+ fontSize: "0.875rem",
873
+ fontWeight: 500,
874
+ // AstroUXDS medium (was 600)
875
+ color: "#fff",
876
+ marginBottom: 4
877
+ },
878
+ children: hoveredEventData.title
879
+ }
880
+ ),
881
+ hoveredEventData.subtitle && /* @__PURE__ */ jsx(
882
+ "div",
883
+ {
884
+ style: {
885
+ fontSize: "0.75rem",
886
+ color: "rgba(255, 255, 255, 0.6)",
887
+ marginBottom: 12
888
+ },
889
+ children: hoveredEventData.subtitle
890
+ }
891
+ ),
892
+ /* @__PURE__ */ jsxs(
893
+ "div",
894
+ {
895
+ style: {
896
+ display: "grid",
897
+ gridTemplateColumns: "auto 1fr",
898
+ gap: "6px 12px",
899
+ fontSize: "0.6875rem",
900
+ borderTop: `1px solid ${tokens.colors.border.muted}30`,
901
+ paddingTop: 10
902
+ },
903
+ children: [
904
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "Start:" }),
905
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.primary, fontFamily: tokens.typography.fontFamily.mono }, children: formatTime(hoveredEventData.start, true) }),
906
+ hoveredEventData.end && /* @__PURE__ */ jsxs(Fragment, { children: [
907
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "End:" }),
908
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.primary, fontFamily: tokens.typography.fontFamily.mono }, children: formatTime(hoveredEventData.end, true) }),
909
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "Duration:" }),
910
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.accent.secondary, fontWeight: 500 }, children: formatDuration(hoveredEventData.end.getTime() - hoveredEventData.start.getTime()) })
911
+ ] }),
912
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "UTC:" }),
913
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.secondary, fontFamily: tokens.typography.fontFamily.mono, fontSize: "0.625rem" }, children: formatUTC(hoveredEventData.start) })
914
+ ]
915
+ }
916
+ ),
917
+ onEventClick && /* @__PURE__ */ jsx(
918
+ "div",
919
+ {
920
+ style: {
921
+ marginTop: 10,
922
+ paddingTop: 8,
923
+ borderTop: `1px solid ${tokens.colors.border.muted}20`,
924
+ fontSize: "0.625rem",
925
+ color: tokens.colors.text.tertiary,
926
+ textAlign: "center"
927
+ },
928
+ children: "Click for details"
929
+ }
930
+ )
931
+ ]
932
+ }
933
+ ),
934
+ /* @__PURE__ */ jsx(
935
+ "div",
936
+ {
937
+ style: {
938
+ position: "absolute",
939
+ bottom: -6,
940
+ left: "50%",
941
+ transform: "translateX(-50%) rotate(45deg)",
942
+ width: 12,
943
+ height: 12,
944
+ backgroundColor: "rgba(15, 23, 42, 0.98)",
945
+ borderRight: `1px solid ${getStatusColor(hoveredEventData.status)}50`,
946
+ borderBottom: `1px solid ${getStatusColor(hoveredEventData.status)}50`
947
+ }
948
+ }
949
+ )
950
+ ]
951
+ }
952
+ ),
953
+ /* @__PURE__ */ jsx("style", { children: `
954
+ .zendir-timeline-region:hover {
955
+ z-index: 100 !important;
956
+ }
957
+ .zendir-timeline-region:focus {
958
+ outline: 2px solid ${tokens.colors.accent.primary};
959
+ outline-offset: 2px;
960
+ }
961
+ .zendir-timeline-scroll::-webkit-scrollbar {
962
+ height: 8px;
963
+ }
964
+ .zendir-timeline-scroll::-webkit-scrollbar-track {
965
+ background: ${tokens.colors.background.elevated};
966
+ border-radius: 4px;
967
+ }
968
+ .zendir-timeline-scroll::-webkit-scrollbar-thumb {
969
+ background: ${tokens.colors.accent.primary}40;
970
+ border-radius: 4px;
971
+ }
972
+ .zendir-timeline-scroll::-webkit-scrollbar-thumb:hover {
973
+ background: ${tokens.colors.accent.primary}60;
974
+ }
975
+ @keyframes zendir-tooltip-appear {
976
+ from {
977
+ opacity: 0;
978
+ transform: translate(-50%, -100%) translateY(8px);
979
+ }
980
+ to {
981
+ opacity: 1;
982
+ transform: translate(-50%, -100%) translateY(0);
983
+ }
984
+ }
985
+ ` })
986
+ ] });
987
+ });
988
+ const ScatterView = memo(function ScatterView2({
989
+ events,
990
+ tracks,
991
+ start,
992
+ end,
993
+ trackHeight,
994
+ onEventClick,
995
+ timeFormat = "relative",
996
+ referenceTime,
997
+ zoom = 1
998
+ }) {
999
+ const { tokens } = useTheme();
1000
+ const [hoveredEvent, setHoveredEvent] = useState(null);
1001
+ const [tooltipPosition, setTooltipPosition] = useState(null);
1002
+ const totalDuration = end.getTime() - start.getTime();
1003
+ const trackLabelWidth = 140;
1004
+ const refTime = referenceTime || start;
1005
+ const formatTimeLabel = useCallback((date) => {
1006
+ if (timeFormat === "relative") {
1007
+ const diff = date.getTime() - refTime.getTime();
1008
+ const totalSeconds = Math.floor(Math.abs(diff) / 1e3);
1009
+ const hours = Math.floor(totalSeconds / 3600);
1010
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
1011
+ const seconds = totalSeconds % 60;
1012
+ if (hours > 0) {
1013
+ return `${hours}h ${minutes}m`;
1014
+ }
1015
+ return `${minutes}m ${seconds}s`;
1016
+ } else if (timeFormat === "utc") {
1017
+ return date.toISOString().slice(11, 19) + " UTC";
1018
+ }
1019
+ return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
1020
+ }, [timeFormat, refTime]);
1021
+ const timeLabels = useMemo(() => {
1022
+ const labels = [];
1023
+ const baseLabelCount = 8;
1024
+ const labelCount = Math.round(baseLabelCount * zoom);
1025
+ for (let i = 0; i <= labelCount; i++) {
1026
+ const percent = i / labelCount * 100;
1027
+ const time = new Date(start.getTime() + totalDuration * percent / 100);
1028
+ labels.push({ time, percent });
1029
+ }
1030
+ return labels;
1031
+ }, [start, totalDuration, zoom]);
1032
+ const eventsByTrack = useMemo(() => {
1033
+ const grouped = {};
1034
+ tracks.forEach((track) => {
1035
+ grouped[track.id] = events.filter((e) => e.track === track.id);
1036
+ });
1037
+ const unassigned = events.filter((e) => !e.track);
1038
+ if (unassigned.length > 0 && tracks.length > 0) {
1039
+ grouped[tracks[0].id] = [...grouped[tracks[0].id] || [], ...unassigned];
1040
+ }
1041
+ return grouped;
1042
+ }, [events, tracks]);
1043
+ const getEventPosition = (event) => {
1044
+ const eventTime = event.start.getTime();
1045
+ return (eventTime - start.getTime()) / totalDuration * 100;
1046
+ };
1047
+ const getStatusColor = (status) => {
1048
+ if (!status) return tokens.colors.accent.primary;
1049
+ return tokens.colors.status[status] || tokens.colors.accent.primary;
1050
+ };
1051
+ const hoveredEventData = events.find((e) => e.id === hoveredEvent);
1052
+ return /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
1053
+ /* @__PURE__ */ jsxs(
1054
+ "div",
1055
+ {
1056
+ style: {
1057
+ width: `${zoom * 100}%`,
1058
+ minWidth: "100%",
1059
+ position: "relative"
1060
+ },
1061
+ children: [
1062
+ /* @__PURE__ */ jsx(
1063
+ "div",
1064
+ {
1065
+ style: {
1066
+ position: "relative",
1067
+ height: 32,
1068
+ marginLeft: trackLabelWidth,
1069
+ borderBottom: `1px solid ${tokens.colors.accent.primary}15`
1070
+ },
1071
+ children: timeLabels.map((label, index) => /* @__PURE__ */ jsx(
1072
+ "span",
1073
+ {
1074
+ style: {
1075
+ position: "absolute",
1076
+ left: `${label.percent}%`,
1077
+ transform: "translateX(-50%)",
1078
+ top: 8,
1079
+ fontSize: "0.6875rem",
1080
+ color: tokens.colors.text.tertiary,
1081
+ fontFamily: tokens.typography.fontFamily.mono,
1082
+ whiteSpace: "nowrap",
1083
+ fontWeight: 500
1084
+ },
1085
+ children: formatTimeLabel(label.time)
1086
+ },
1087
+ index
1088
+ ))
1089
+ }
1090
+ ),
1091
+ tracks.map((track, trackIndex) => /* @__PURE__ */ jsxs(
1092
+ "div",
1093
+ {
1094
+ style: {
1095
+ position: "relative",
1096
+ display: "flex",
1097
+ alignItems: "center",
1098
+ height: track.height || trackHeight,
1099
+ borderBottom: trackIndex < tracks.length - 1 ? `1px solid ${tokens.colors.border.muted}20` : "none"
1100
+ },
1101
+ children: [
1102
+ /* @__PURE__ */ jsx(
1103
+ "div",
1104
+ {
1105
+ style: {
1106
+ width: trackLabelWidth,
1107
+ flexShrink: 0,
1108
+ padding: "0 16px",
1109
+ fontSize: "0.8125rem",
1110
+ fontWeight: 500,
1111
+ // AstroUXDS medium (was 600)
1112
+ color: tokens.colors.text.primary
1113
+ },
1114
+ children: track.label
1115
+ }
1116
+ ),
1117
+ /* @__PURE__ */ jsxs(
1118
+ "div",
1119
+ {
1120
+ style: {
1121
+ flex: 1,
1122
+ position: "relative",
1123
+ height: "100%",
1124
+ display: "flex",
1125
+ alignItems: "center"
1126
+ },
1127
+ children: [
1128
+ /* @__PURE__ */ jsx(
1129
+ "div",
1130
+ {
1131
+ style: {
1132
+ position: "absolute",
1133
+ left: 0,
1134
+ right: 0,
1135
+ height: 1,
1136
+ backgroundColor: tokens.colors.border.muted,
1137
+ opacity: 0.3
1138
+ }
1139
+ }
1140
+ ),
1141
+ (eventsByTrack[track.id] || []).map((event) => {
1142
+ const leftPercent = getEventPosition(event);
1143
+ const color = getStatusColor(event.status);
1144
+ const isHovered = hoveredEvent === event.id;
1145
+ const dotSize = isHovered ? 16 : 12;
1146
+ const effectiveStatus = event.status ?? "normal";
1147
+ return /* @__PURE__ */ jsx(
1148
+ "button",
1149
+ {
1150
+ type: "button",
1151
+ onClick: () => onEventClick == null ? void 0 : onEventClick(event),
1152
+ onMouseEnter: (e) => {
1153
+ setHoveredEvent(event.id);
1154
+ const rect = e.currentTarget.getBoundingClientRect();
1155
+ setTooltipPosition({ x: rect.left + rect.width / 2, y: rect.top });
1156
+ },
1157
+ onMouseLeave: () => {
1158
+ setHoveredEvent(null);
1159
+ setTooltipPosition(null);
1160
+ },
1161
+ style: {
1162
+ position: "absolute",
1163
+ left: `${leftPercent}%`,
1164
+ transform: "translateX(-50%)",
1165
+ width: dotSize,
1166
+ height: dotSize,
1167
+ padding: 0,
1168
+ background: "none",
1169
+ border: "none",
1170
+ cursor: "pointer",
1171
+ transition: "all 200ms cubic-bezier(0.34, 1.56, 0.64, 1)",
1172
+ zIndex: isHovered ? 20 : 1,
1173
+ lineHeight: 0
1174
+ },
1175
+ "aria-label": event.title,
1176
+ children: /* @__PURE__ */ jsx(TimelineStatusMarker, { status: effectiveStatus, fillColor: color, size: dotSize })
1177
+ },
1178
+ event.id
1179
+ );
1180
+ })
1181
+ ]
1182
+ }
1183
+ )
1184
+ ]
1185
+ },
1186
+ track.id
1187
+ ))
1188
+ ]
1189
+ }
1190
+ ),
1191
+ hoveredEventData && tooltipPosition && /* @__PURE__ */ jsxs(
1192
+ "div",
1193
+ {
1194
+ className: "zendir-scatter-tooltip",
1195
+ style: {
1196
+ position: "fixed",
1197
+ left: tooltipPosition.x,
1198
+ top: tooltipPosition.y - 12,
1199
+ transform: "translate(-50%, -100%)",
1200
+ backgroundColor: "rgba(11, 26, 40, 0.98)",
1201
+ border: `1px solid ${tokens.colors.accent.primary}40`,
1202
+ borderRadius: tokens.borderRadius.lg,
1203
+ padding: "12px 16px",
1204
+ minWidth: 200,
1205
+ maxWidth: 320,
1206
+ zIndex: 1e3,
1207
+ boxShadow: `0 12px 40px rgba(0, 0, 0, 0.5), 0 0 0 1px ${tokens.colors.accent.primary}20`,
1208
+ backdropFilter: "blur(12px)",
1209
+ animation: "zendir-tooltip-in 150ms cubic-bezier(0.34, 1.56, 0.64, 1)"
1210
+ },
1211
+ children: [
1212
+ /* @__PURE__ */ jsx(
1213
+ "div",
1214
+ {
1215
+ style: {
1216
+ position: "absolute",
1217
+ bottom: -6,
1218
+ left: "50%",
1219
+ transform: "translateX(-50%) rotate(45deg)",
1220
+ width: 12,
1221
+ height: 12,
1222
+ backgroundColor: "rgba(11, 26, 40, 0.98)",
1223
+ borderRight: `1px solid ${tokens.colors.accent.primary}40`,
1224
+ borderBottom: `1px solid ${tokens.colors.accent.primary}40`
1225
+ }
1226
+ }
1227
+ ),
1228
+ hoveredEventData.status && /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }, children: [
1229
+ /* @__PURE__ */ jsx(
1230
+ TimelineStatusMarker,
1231
+ {
1232
+ status: hoveredEventData.status,
1233
+ fillColor: getStatusColor(hoveredEventData.status),
1234
+ size: 10
1235
+ }
1236
+ ),
1237
+ /* @__PURE__ */ jsx(
1238
+ "span",
1239
+ {
1240
+ style: {
1241
+ fontSize: "0.75rem",
1242
+ fontWeight: 500,
1243
+ color: getStatusColor(hoveredEventData.status),
1244
+ textTransform: "uppercase",
1245
+ letterSpacing: "0.05em"
1246
+ },
1247
+ children: hoveredEventData.status
1248
+ }
1249
+ ),
1250
+ hoveredEventData.badge && /* @__PURE__ */ jsx(
1251
+ "span",
1252
+ {
1253
+ style: {
1254
+ marginLeft: "auto",
1255
+ fontSize: "0.625rem",
1256
+ fontWeight: 500,
1257
+ padding: "2px 6px",
1258
+ borderRadius: tokens.borderRadius.sm,
1259
+ backgroundColor: `${getStatusColor(hoveredEventData.status)}20`,
1260
+ color: getStatusColor(hoveredEventData.status)
1261
+ },
1262
+ children: hoveredEventData.badge
1263
+ }
1264
+ )
1265
+ ] }),
1266
+ /* @__PURE__ */ jsx(
1267
+ "div",
1268
+ {
1269
+ style: {
1270
+ fontSize: "0.875rem",
1271
+ fontWeight: 500,
1272
+ color: "#fff",
1273
+ marginBottom: 8
1274
+ },
1275
+ children: hoveredEventData.title
1276
+ }
1277
+ ),
1278
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
1279
+ /* @__PURE__ */ jsxs(
1280
+ "div",
1281
+ {
1282
+ style: {
1283
+ display: "flex",
1284
+ justifyContent: "space-between",
1285
+ fontSize: "0.75rem"
1286
+ },
1287
+ children: [
1288
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "Time:" }),
1289
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.secondary, fontFamily: tokens.typography.fontFamily.mono }, children: formatTimeLabel(hoveredEventData.start) })
1290
+ ]
1291
+ }
1292
+ ),
1293
+ hoveredEventData.badge && /* @__PURE__ */ jsxs(
1294
+ "div",
1295
+ {
1296
+ style: {
1297
+ display: "flex",
1298
+ justifyContent: "space-between",
1299
+ fontSize: "0.75rem"
1300
+ },
1301
+ children: [
1302
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "Trigger:" }),
1303
+ /* @__PURE__ */ jsx("span", { style: { color: safeAccentText(tokens.colors.accent.primary), fontWeight: 500 }, children: hoveredEventData.badge })
1304
+ ]
1305
+ }
1306
+ ),
1307
+ /* @__PURE__ */ jsxs(
1308
+ "div",
1309
+ {
1310
+ style: {
1311
+ display: "flex",
1312
+ justifyContent: "space-between",
1313
+ fontSize: "0.75rem"
1314
+ },
1315
+ children: [
1316
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "UTC:" }),
1317
+ /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.secondary, fontFamily: tokens.typography.fontFamily.mono }, children: hoveredEventData.start.toISOString().replace("T", " ").slice(0, 19) })
1318
+ ]
1319
+ }
1320
+ ),
1321
+ hoveredEventData.subtitle && /* @__PURE__ */ jsx(
1322
+ "div",
1323
+ {
1324
+ style: {
1325
+ marginTop: 4,
1326
+ paddingTop: 8,
1327
+ borderTop: `1px solid ${tokens.colors.border.muted}`,
1328
+ fontSize: "0.75rem",
1329
+ color: tokens.colors.text.secondary
1330
+ },
1331
+ children: hoveredEventData.subtitle
1332
+ }
1333
+ )
1334
+ ] })
1335
+ ]
1336
+ }
1337
+ ),
1338
+ /* @__PURE__ */ jsx("style", { children: `
1339
+ @keyframes zendir-tooltip-in {
1340
+ from {
1341
+ opacity: 0;
1342
+ transform: translate(-50%, -100%) scale(0.95);
1343
+ }
1344
+ to {
1345
+ opacity: 1;
1346
+ transform: translate(-50%, -100%) scale(1);
1347
+ }
1348
+ }
1349
+ .zendir-scatter-tooltip::before {
1350
+ content: '';
1351
+ position: absolute;
1352
+ inset: 0;
1353
+ border-radius: inherit;
1354
+ background: linear-gradient(135deg, rgba(139, 92, 246, 0.1) 0%, transparent 50%);
1355
+ pointer-events: none;
1356
+ }
1357
+ ` })
1358
+ ] });
1359
+ });
1360
+ const UnifiedTimeline = memo(function UnifiedTimeline2({
1361
+ title = "Timeline",
1362
+ events,
1363
+ tracks = [],
1364
+ start: propStart,
1365
+ end: propEnd,
1366
+ defaultView = "chart",
1367
+ viewMode: controlledViewMode,
1368
+ onViewModeChange,
1369
+ onEventClick,
1370
+ showViewToggle = true,
1371
+ maxHeight,
1372
+ trackHeight = 56,
1373
+ className = "",
1374
+ timeFormat = "absolute",
1375
+ zoomable = false,
1376
+ initialZoom = 1,
1377
+ showFilters: _showFilters = false,
1378
+ filter: _filter,
1379
+ onFilterChange: _onFilterChange,
1380
+ showCount: _showCount = true,
1381
+ loading = false,
1382
+ referenceTime,
1383
+ showPlayhead = true,
1384
+ playheadTime,
1385
+ onPlayheadChange: _onPlayheadChangeTimeline,
1386
+ showDayMarkers = true
1387
+ }) {
1388
+ const { tokens, theme } = useTheme();
1389
+ const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
1390
+ const [internalViewMode, setInternalViewMode] = useState(defaultView);
1391
+ const [zoom, setZoom] = useState(initialZoom);
1392
+ const [_internalFilter, _setInternalFilter] = useState({});
1393
+ const viewMode = controlledViewMode ?? internalViewMode;
1394
+ const handleViewModeChange = useCallback((mode) => {
1395
+ setInternalViewMode(mode);
1396
+ onViewModeChange == null ? void 0 : onViewModeChange(mode);
1397
+ }, [onViewModeChange]);
1398
+ const { start, end } = useMemo(() => {
1399
+ if (propStart && propEnd) {
1400
+ return { start: propStart, end: propEnd };
1401
+ }
1402
+ if (events.length === 0) {
1403
+ const now = /* @__PURE__ */ new Date();
1404
+ return {
1405
+ start: new Date(now.getTime() - 36e5),
1406
+ end: new Date(now.getTime() + 36e5)
1407
+ };
1408
+ }
1409
+ let minTime = events[0].start.getTime();
1410
+ let maxTime = events[0].start.getTime();
1411
+ events.forEach((event) => {
1412
+ minTime = Math.min(minTime, event.start.getTime());
1413
+ maxTime = Math.max(maxTime, (event.end || event.start).getTime());
1414
+ });
1415
+ const duration = maxTime - minTime;
1416
+ const padding = duration * 0.1;
1417
+ return {
1418
+ start: new Date(minTime - padding),
1419
+ end: new Date(maxTime + padding)
1420
+ };
1421
+ }, [events, propStart, propEnd]);
1422
+ const effectiveTracks = useMemo(() => {
1423
+ if (tracks.length > 0) return tracks;
1424
+ const trackSet = /* @__PURE__ */ new Set();
1425
+ events.forEach((event) => {
1426
+ if (event.track) trackSet.add(event.track);
1427
+ });
1428
+ if (trackSet.size === 0) {
1429
+ return [{ id: "default", label: "Events", height: trackHeight }];
1430
+ }
1431
+ return Array.from(trackSet).map((id) => ({
1432
+ id,
1433
+ label: id,
1434
+ height: trackHeight
1435
+ }));
1436
+ }, [events, tracks, trackHeight]);
1437
+ const sortedEvents = useMemo(() => {
1438
+ return [...events].sort((a, b) => b.start.getTime() - a.start.getTime());
1439
+ }, [events]);
1440
+ return /* @__PURE__ */ jsxs(
1441
+ "div",
1442
+ {
1443
+ className: classNames("zendir-unified-timeline", className),
1444
+ style: {
1445
+ backgroundColor: isTransparentTheme ? "transparent" : tokens.colors.background.surface,
1446
+ ...isTransparentTheme && { backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)" },
1447
+ ...tokens.colors.border.cardStyle ?? { border: `1px solid ${tokens.colors.border.muted}` },
1448
+ borderRadius: tokens.borderRadius.lg,
1449
+ overflow: "hidden"
1450
+ },
1451
+ children: [
1452
+ /* @__PURE__ */ jsxs(
1453
+ "div",
1454
+ {
1455
+ style: {
1456
+ display: "flex",
1457
+ alignItems: "center",
1458
+ justifyContent: "space-between",
1459
+ padding: "16px 20px",
1460
+ borderBottom: `1px solid ${tokens.colors.border.muted}`
1461
+ },
1462
+ children: [
1463
+ /* @__PURE__ */ jsxs(
1464
+ "h3",
1465
+ {
1466
+ style: {
1467
+ margin: 0,
1468
+ fontSize: "1rem",
1469
+ fontWeight: 500,
1470
+ // AstroUXDS medium (was 600)
1471
+ color: tokens.colors.text.primary
1472
+ },
1473
+ children: [
1474
+ title,
1475
+ " (",
1476
+ events.length,
1477
+ ")"
1478
+ ]
1479
+ }
1480
+ ),
1481
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12 }, children: [
1482
+ zoomable && (viewMode === "chart" || viewMode === "scatter") && /* @__PURE__ */ jsxs(
1483
+ "div",
1484
+ {
1485
+ style: {
1486
+ display: "flex",
1487
+ alignItems: "center",
1488
+ gap: 4,
1489
+ paddingRight: 12,
1490
+ borderRight: `1px solid ${tokens.colors.border.muted}`
1491
+ },
1492
+ children: [
1493
+ /* @__PURE__ */ jsx(Tooltip, { content: "Zoom out", children: /* @__PURE__ */ jsx(
1494
+ "button",
1495
+ {
1496
+ type: "button",
1497
+ "aria-label": "Zoom out",
1498
+ onClick: () => setZoom(Math.max(zoom - 0.5, 1)),
1499
+ disabled: zoom <= 1,
1500
+ style: {
1501
+ width: 28,
1502
+ height: 28,
1503
+ display: "flex",
1504
+ alignItems: "center",
1505
+ justifyContent: "center",
1506
+ backgroundColor: zoom <= 1 ? "transparent" : tokens.colors.background.elevated,
1507
+ border: `1px solid ${tokens.colors.border.muted}`,
1508
+ borderRadius: tokens.borderRadius.sm,
1509
+ color: zoom <= 1 ? tokens.colors.text.tertiary : tokens.colors.text.primary,
1510
+ cursor: zoom <= 1 ? "not-allowed" : "pointer",
1511
+ fontSize: "1rem",
1512
+ fontWeight: 500,
1513
+ // AstroUXDS medium (was 600)
1514
+ opacity: zoom <= 1 ? 0.5 : 1
1515
+ },
1516
+ children: "−"
1517
+ }
1518
+ ) }),
1519
+ /* @__PURE__ */ jsxs(
1520
+ "span",
1521
+ {
1522
+ style: {
1523
+ minWidth: 40,
1524
+ textAlign: "center",
1525
+ fontSize: "0.75rem",
1526
+ fontFamily: tokens.typography.fontFamily.mono,
1527
+ color: tokens.colors.text.secondary
1528
+ },
1529
+ children: [
1530
+ Math.round(zoom * 100),
1531
+ "%"
1532
+ ]
1533
+ }
1534
+ ),
1535
+ /* @__PURE__ */ jsx(Tooltip, { content: "Zoom in", children: /* @__PURE__ */ jsx(
1536
+ "button",
1537
+ {
1538
+ type: "button",
1539
+ "aria-label": "Zoom in",
1540
+ onClick: () => setZoom(Math.min(zoom + 0.5, 4)),
1541
+ disabled: zoom >= 4,
1542
+ style: {
1543
+ width: 28,
1544
+ height: 28,
1545
+ display: "flex",
1546
+ alignItems: "center",
1547
+ justifyContent: "center",
1548
+ backgroundColor: zoom >= 4 ? "transparent" : tokens.colors.background.elevated,
1549
+ border: `1px solid ${tokens.colors.border.muted}`,
1550
+ borderRadius: tokens.borderRadius.sm,
1551
+ color: zoom >= 4 ? tokens.colors.text.tertiary : tokens.colors.text.primary,
1552
+ cursor: zoom >= 4 ? "not-allowed" : "pointer",
1553
+ fontSize: "1rem",
1554
+ fontWeight: 500,
1555
+ // AstroUXDS medium (was 600)
1556
+ opacity: zoom >= 4 ? 0.5 : 1
1557
+ },
1558
+ children: "+"
1559
+ }
1560
+ ) }),
1561
+ /* @__PURE__ */ jsx(Tooltip, { content: "Reset zoom", children: /* @__PURE__ */ jsx(
1562
+ "button",
1563
+ {
1564
+ type: "button",
1565
+ "aria-label": "Reset zoom",
1566
+ onClick: () => setZoom(1),
1567
+ style: {
1568
+ height: 28,
1569
+ padding: "0 10px",
1570
+ display: "flex",
1571
+ alignItems: "center",
1572
+ justifyContent: "center",
1573
+ backgroundColor: tokens.colors.background.elevated,
1574
+ border: `1px solid ${tokens.colors.border.muted}`,
1575
+ borderRadius: tokens.borderRadius.sm,
1576
+ color: tokens.colors.text.secondary,
1577
+ cursor: "pointer",
1578
+ fontSize: "0.6875rem",
1579
+ fontWeight: 500
1580
+ },
1581
+ children: "FIT"
1582
+ }
1583
+ ) })
1584
+ ]
1585
+ }
1586
+ ),
1587
+ showViewToggle && /* @__PURE__ */ jsx(
1588
+ "div",
1589
+ {
1590
+ style: {
1591
+ display: "flex",
1592
+ gap: "2px",
1593
+ backgroundColor: isTransparentTheme ? "transparent" : tokens.colors.background.elevated,
1594
+ ...isTransparentTheme && { backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)" },
1595
+ padding: "4px",
1596
+ borderRadius: tokens.borderRadius.lg
1597
+ },
1598
+ children: ["chart", "list", "scatter"].map((mode) => {
1599
+ const isActive = viewMode === mode;
1600
+ const icons = {
1601
+ chart: "chart",
1602
+ list: "list",
1603
+ scatter: "timeline"
1604
+ };
1605
+ const labels = {
1606
+ chart: "Gantt Chart",
1607
+ list: "List View",
1608
+ scatter: "Scatter View"
1609
+ };
1610
+ return /* @__PURE__ */ jsx(Tooltip, { content: labels[mode], children: /* @__PURE__ */ jsx(
1611
+ "button",
1612
+ {
1613
+ type: "button",
1614
+ "aria-label": labels[mode],
1615
+ onClick: () => handleViewModeChange(mode),
1616
+ style: {
1617
+ display: "flex",
1618
+ alignItems: "center",
1619
+ justifyContent: "center",
1620
+ width: "32px",
1621
+ height: "32px",
1622
+ backgroundColor: isActive ? tokens.colors.accent.primary : "transparent",
1623
+ border: "none",
1624
+ borderRadius: tokens.borderRadius.md,
1625
+ color: isActive ? "#ffffff" : tokens.colors.text.secondary,
1626
+ cursor: "pointer",
1627
+ transition: "all 200ms cubic-bezier(0.4, 0, 0.2, 1)",
1628
+ transform: isActive ? "scale(1)" : "scale(0.95)",
1629
+ boxShadow: isActive ? `0 2px 8px ${tokens.colors.accent.primary}40` : "none"
1630
+ },
1631
+ onMouseEnter: (e) => {
1632
+ if (!isActive) {
1633
+ e.currentTarget.style.backgroundColor = `${tokens.colors.accent.primary}20`;
1634
+ e.currentTarget.style.transform = "scale(1)";
1635
+ }
1636
+ },
1637
+ onMouseLeave: (e) => {
1638
+ if (!isActive) {
1639
+ e.currentTarget.style.backgroundColor = "transparent";
1640
+ e.currentTarget.style.transform = "scale(0.95)";
1641
+ }
1642
+ },
1643
+ children: /* @__PURE__ */ jsx(Icon, { name: icons[mode], size: 16 })
1644
+ }
1645
+ ) }, mode);
1646
+ })
1647
+ }
1648
+ )
1649
+ ] })
1650
+ ]
1651
+ }
1652
+ ),
1653
+ loading && /* @__PURE__ */ jsx(
1654
+ "div",
1655
+ {
1656
+ style: {
1657
+ position: "absolute",
1658
+ inset: 0,
1659
+ display: "flex",
1660
+ alignItems: "center",
1661
+ justifyContent: "center",
1662
+ backgroundColor: `${tokens.colors.background.overlay}80`,
1663
+ backdropFilter: "blur(4px)",
1664
+ zIndex: 100
1665
+ },
1666
+ children: /* @__PURE__ */ jsx(
1667
+ "div",
1668
+ {
1669
+ style: {
1670
+ width: 40,
1671
+ height: 40,
1672
+ border: `3px solid ${tokens.colors.border.muted}`,
1673
+ borderTopColor: tokens.colors.accent.primary,
1674
+ borderRadius: "50%",
1675
+ animation: "zendir-spin 1s linear infinite"
1676
+ }
1677
+ }
1678
+ )
1679
+ }
1680
+ ),
1681
+ /* @__PURE__ */ jsx(
1682
+ "div",
1683
+ {
1684
+ style: {
1685
+ padding: viewMode === "list" ? "16px 20px" : "16px",
1686
+ maxHeight,
1687
+ overflowY: maxHeight ? "auto" : void 0,
1688
+ overflowX: viewMode !== "list" ? "auto" : void 0
1689
+ },
1690
+ children: events.length === 0 ? /* @__PURE__ */ jsxs(
1691
+ "div",
1692
+ {
1693
+ style: {
1694
+ display: "flex",
1695
+ flexDirection: "column",
1696
+ alignItems: "center",
1697
+ justifyContent: "center",
1698
+ padding: "48px 0",
1699
+ color: tokens.colors.text.tertiary,
1700
+ gap: "12px"
1701
+ },
1702
+ children: [
1703
+ /* @__PURE__ */ jsx(Icon, { name: "clock", size: 32 }),
1704
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "0.875rem" }, children: "No events to display" })
1705
+ ]
1706
+ }
1707
+ ) : viewMode === "list" ? (
1708
+ // List View
1709
+ sortedEvents.map((event, index) => /* @__PURE__ */ jsx(
1710
+ EventListItem,
1711
+ {
1712
+ event,
1713
+ isLast: index === sortedEvents.length - 1,
1714
+ onEventClick
1715
+ },
1716
+ event.id
1717
+ ))
1718
+ ) : viewMode === "scatter" ? (
1719
+ // Scatter View (Dots on timeline) - uses same zoom as chart
1720
+ /* @__PURE__ */ jsx(
1721
+ ScatterView,
1722
+ {
1723
+ events,
1724
+ tracks: effectiveTracks,
1725
+ start,
1726
+ end,
1727
+ trackHeight,
1728
+ onEventClick,
1729
+ timeFormat,
1730
+ referenceTime: referenceTime || start,
1731
+ zoom
1732
+ }
1733
+ )
1734
+ ) : (
1735
+ // Chart View (Gantt)
1736
+ /* @__PURE__ */ jsx(
1737
+ ChartView,
1738
+ {
1739
+ events,
1740
+ tracks: effectiveTracks,
1741
+ start,
1742
+ end,
1743
+ trackHeight,
1744
+ onEventClick,
1745
+ zoom,
1746
+ showPlayhead,
1747
+ playheadTime,
1748
+ onPlayheadChange: _onPlayheadChangeTimeline,
1749
+ showDayMarkers
1750
+ }
1751
+ )
1752
+ )
1753
+ }
1754
+ ),
1755
+ /* @__PURE__ */ jsx("style", { children: `
1756
+ @keyframes zendir-spin {
1757
+ from { transform: rotate(0deg); }
1758
+ to { transform: rotate(360deg); }
1759
+ }
1760
+ ` })
1761
+ ]
1762
+ }
1763
+ );
1764
+ });
1765
+ export {
1766
+ UnifiedTimeline
1767
+ };
1768
+ //# sourceMappingURL=UnifiedTimeline.js.map