@zendir/ui 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/CHANGELOG.md +419 -386
  2. package/README.md +640 -631
  3. package/dist/_virtual/_rolldown/runtime.js +13 -0
  4. package/dist/index.js +17 -221
  5. package/dist/react/3d/CesiumCaptureSource.d.ts +0 -1
  6. package/dist/react/3d/CesiumCaptureSource.js +364 -283
  7. package/dist/react/3d/CesiumCaptureSource.js.map +1 -1
  8. package/dist/react/3d/ZenSpace3D.d.ts +2 -3
  9. package/dist/react/3d/ZenSpace3D.js +1681 -1237
  10. package/dist/react/3d/ZenSpace3D.js.map +1 -1
  11. package/dist/react/3d/ZenSpace3DCesium.d.ts +0 -1
  12. package/dist/react/3d/ZenSpace3DCesium.js +513 -560
  13. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -1
  14. package/dist/react/3d/ZenSpace3DShaders.js +61 -66
  15. package/dist/react/3d/ZenSpace3DShaders.js.map +1 -1
  16. package/dist/react/3d/ZenSpace3DTypes.d.ts +19 -20
  17. package/dist/react/3d/ZenSpace3DUtils.d.ts +0 -1
  18. package/dist/react/3d/ZenSpace3DUtils.js +37 -24
  19. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -1
  20. package/dist/react/3d/capturePngAnalysis.js +42 -36
  21. package/dist/react/3d/capturePngAnalysis.js.map +1 -1
  22. package/dist/react/3d/index.d.ts +3 -3
  23. package/dist/react/3d/index.js +5 -53
  24. package/dist/react/3d/threeLoader.d.ts +1 -1
  25. package/dist/react/3d/threeLoader.js +23 -18
  26. package/dist/react/3d/threeLoader.js.map +1 -1
  27. package/dist/react/astro/ClassificationBanner.d.ts +2 -3
  28. package/dist/react/astro/ClassificationBanner.js +95 -79
  29. package/dist/react/astro/ClassificationBanner.js.map +1 -1
  30. package/dist/react/astro/GlobalStatusBar.d.ts +0 -1
  31. package/dist/react/astro/GlobalStatusBar.js +157 -163
  32. package/dist/react/astro/GlobalStatusBar.js.map +1 -1
  33. package/dist/react/astro/MissionClock.d.ts +7 -8
  34. package/dist/react/astro/MissionClock.js +377 -400
  35. package/dist/react/astro/MissionClock.js.map +1 -1
  36. package/dist/react/astro/MonitoringIcon.d.ts +1 -2
  37. package/dist/react/astro/MonitoringIcon.js +422 -358
  38. package/dist/react/astro/MonitoringIcon.js.map +1 -1
  39. package/dist/react/astro/Notification.d.ts +1 -2
  40. package/dist/react/astro/Notification.js +229 -126
  41. package/dist/react/astro/Notification.js.map +1 -1
  42. package/dist/react/astro/Progress.d.ts +0 -1
  43. package/dist/react/astro/Progress.js +199 -141
  44. package/dist/react/astro/Progress.js.map +1 -1
  45. package/dist/react/astro/SimulationControls.d.ts +3 -4
  46. package/dist/react/astro/SimulationControls.js +596 -650
  47. package/dist/react/astro/SimulationControls.js.map +1 -1
  48. package/dist/react/astro/StatusIndicator.d.ts +0 -1
  49. package/dist/react/astro/StatusIndicator.js +236 -170
  50. package/dist/react/astro/StatusIndicator.js.map +1 -1
  51. package/dist/react/astro/UnifiedTimeline.d.ts +9 -10
  52. package/dist/react/astro/UnifiedTimeline.js +2345 -2392
  53. package/dist/react/astro/UnifiedTimeline.js.map +1 -1
  54. package/dist/react/astro/index.d.ts +5 -5
  55. package/dist/react/astro/index.js +1 -25
  56. package/dist/react/cards/AccessCard.d.ts +0 -1
  57. package/dist/react/cards/AccessCard.js +471 -405
  58. package/dist/react/cards/AccessCard.js.map +1 -1
  59. package/dist/react/cards/OrbitCard.d.ts +0 -1
  60. package/dist/react/cards/OrbitCard.js +487 -364
  61. package/dist/react/cards/OrbitCard.js.map +1 -1
  62. package/dist/react/cards/SpacecraftCard.d.ts +0 -1
  63. package/dist/react/cards/SpacecraftCard.js +813 -925
  64. package/dist/react/cards/SpacecraftCard.js.map +1 -1
  65. package/dist/react/cards/TelemetryCard.d.ts +0 -1
  66. package/dist/react/cards/TelemetryCard.js +1055 -732
  67. package/dist/react/cards/TelemetryCard.js.map +1 -1
  68. package/dist/react/cards/TelemetryStreamCard.d.ts +0 -1
  69. package/dist/react/cards/TelemetryStreamCard.js +323 -297
  70. package/dist/react/cards/TelemetryStreamCard.js.map +1 -1
  71. package/dist/react/cards/index.d.ts +1 -1
  72. package/dist/react/cards/index.js +1 -8
  73. package/dist/react/charts/GroundTrackMap.d.ts +6 -7
  74. package/dist/react/charts/GroundTrackMap.js +1377 -1256
  75. package/dist/react/charts/GroundTrackMap.js.map +1 -1
  76. package/dist/react/charts/GroundTrackMapLeaflet.d.ts +1 -2
  77. package/dist/react/charts/GroundTrackMapLeaflet.js +1065 -987
  78. package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -1
  79. package/dist/react/charts/groundTrackMapLeafletTiles.js +34 -25
  80. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -1
  81. package/dist/react/charts/groundTrackMapLeafletUtils.js +70 -61
  82. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -1
  83. package/dist/react/charts/index.d.ts +1 -1
  84. package/dist/react/charts/index.js +7 -100
  85. package/dist/react/charts/unified/AstroChart.d.ts +1 -2
  86. package/dist/react/charts/unified/AstroChart.js +1331 -1411
  87. package/dist/react/charts/unified/AstroChart.js.map +1 -1
  88. package/dist/react/charts/unified/PowerOverviewChart.d.ts +3 -3
  89. package/dist/react/charts/unified/PowerOverviewChart.js +495 -478
  90. package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -1
  91. package/dist/react/charts/unified/domain.d.ts +12 -13
  92. package/dist/react/charts/unified/domain.js +3999 -3145
  93. package/dist/react/charts/unified/domain.js.map +1 -1
  94. package/dist/react/charts/unified/generators.d.ts +3 -4
  95. package/dist/react/charts/unified/generators.js +561 -498
  96. package/dist/react/charts/unified/generators.js.map +1 -1
  97. package/dist/react/charts/unified/index.d.ts +1 -1
  98. package/dist/react/charts/unified/presets.d.ts +14 -15
  99. package/dist/react/charts/unified/presets.js +857 -994
  100. package/dist/react/charts/unified/presets.js.map +1 -1
  101. package/dist/react/charts/unified/sync.d.ts +2 -3
  102. package/dist/react/charts/unified/sync.js +229 -195
  103. package/dist/react/charts/unified/sync.js.map +1 -1
  104. package/dist/react/charts/unified/theme.d.ts +11 -12
  105. package/dist/react/charts/unified/theme.js +606 -642
  106. package/dist/react/charts/unified/theme.js.map +1 -1
  107. package/dist/react/charts/unified/types.d.ts +32 -33
  108. package/dist/react/charts/unified/useChartStream.d.ts +1 -2
  109. package/dist/react/charts/unified/useChartStream.js +203 -216
  110. package/dist/react/charts/unified/useChartStream.js.map +1 -1
  111. package/dist/react/chatgpt/AppCard.d.ts +1 -2
  112. package/dist/react/chatgpt/index.d.ts +7 -7
  113. package/dist/react/chatgpt/index.js +160 -139
  114. package/dist/react/chatgpt/index.js.map +1 -1
  115. package/dist/react/context/CategoryContext.d.ts +0 -1
  116. package/dist/react/context/CategoryContext.js +78 -29
  117. package/dist/react/context/CategoryContext.js.map +1 -1
  118. package/dist/react/context/DisplaySettingsContext.d.ts +1 -2
  119. package/dist/react/context/DisplaySettingsContext.js +205 -156
  120. package/dist/react/context/DisplaySettingsContext.js.map +1 -1
  121. package/dist/react/context/SpatialSelectionContext.d.ts +0 -1
  122. package/dist/react/context/SpatialSelectionContext.js +36 -7
  123. package/dist/react/context/SpatialSelectionContext.js.map +1 -1
  124. package/dist/react/core/data/DataTable.d.ts +3 -4
  125. package/dist/react/core/data/DataTable.js +473 -440
  126. package/dist/react/core/data/DataTable.js.map +1 -1
  127. package/dist/react/core/data/DataValue.d.ts +4 -5
  128. package/dist/react/core/data/DataValue.js +605 -571
  129. package/dist/react/core/data/DataValue.js.map +1 -1
  130. package/dist/react/core/data/propertyConfig.d.ts +1 -2
  131. package/dist/react/core/data/propertyConfig.js +446 -382
  132. package/dist/react/core/data/propertyConfig.js.map +1 -1
  133. package/dist/react/core/display/AstroIcon.d.ts +4 -5
  134. package/dist/react/core/display/AstroIcon.js +339 -429
  135. package/dist/react/core/display/AstroIcon.js.map +1 -1
  136. package/dist/react/core/display/Badge.d.ts +2 -3
  137. package/dist/react/core/display/Badge.js +131 -131
  138. package/dist/react/core/display/Badge.js.map +1 -1
  139. package/dist/react/core/display/CardHeader.d.ts +0 -1
  140. package/dist/react/core/display/CardHeader.js +398 -311
  141. package/dist/react/core/display/CardHeader.js.map +1 -1
  142. package/dist/react/core/display/Container.d.ts +2 -3
  143. package/dist/react/core/display/Container.js +640 -668
  144. package/dist/react/core/display/Container.js.map +1 -1
  145. package/dist/react/core/display/CopyButton.d.ts +1 -2
  146. package/dist/react/core/display/CopyButton.js +158 -101
  147. package/dist/react/core/display/CopyButton.js.map +1 -1
  148. package/dist/react/core/display/GlassCard.d.ts +3 -4
  149. package/dist/react/core/display/GlassCard.js +416 -369
  150. package/dist/react/core/display/GlassCard.js.map +1 -1
  151. package/dist/react/core/display/HeaderIconWithStatus.d.ts +0 -1
  152. package/dist/react/core/display/HeaderIconWithStatus.js +152 -152
  153. package/dist/react/core/display/HeaderIconWithStatus.js.map +1 -1
  154. package/dist/react/core/display/Icon.d.ts +2 -3
  155. package/dist/react/core/display/Icon.js +172 -143
  156. package/dist/react/core/display/Icon.js.map +1 -1
  157. package/dist/react/core/display/Typography.d.ts +24 -25
  158. package/dist/react/core/display/Typography.js +360 -178
  159. package/dist/react/core/display/Typography.js.map +1 -1
  160. package/dist/react/core/feedback/ConfirmDialog.d.ts +1 -2
  161. package/dist/react/core/feedback/ConfirmDialog.js +343 -304
  162. package/dist/react/core/feedback/ConfirmDialog.js.map +1 -1
  163. package/dist/react/core/feedback/Dialog.d.ts +2 -3
  164. package/dist/react/core/feedback/Dialog.js +189 -197
  165. package/dist/react/core/feedback/Dialog.js.map +1 -1
  166. package/dist/react/core/feedback/Toast.d.ts +2 -3
  167. package/dist/react/core/feedback/Toast.js +346 -207
  168. package/dist/react/core/feedback/Toast.js.map +1 -1
  169. package/dist/react/core/index.d.ts +26 -26
  170. package/dist/react/core/index.js +7 -119
  171. package/dist/react/core/inputs/Button.d.ts +2 -3
  172. package/dist/react/core/inputs/Button.js +281 -304
  173. package/dist/react/core/inputs/Button.js.map +1 -1
  174. package/dist/react/core/inputs/Checkbox.d.ts +2 -3
  175. package/dist/react/core/inputs/Checkbox.js +139 -127
  176. package/dist/react/core/inputs/Checkbox.js.map +1 -1
  177. package/dist/react/core/inputs/Input.d.ts +3 -4
  178. package/dist/react/core/inputs/Input.js +277 -285
  179. package/dist/react/core/inputs/Input.js.map +1 -1
  180. package/dist/react/core/inputs/LimitsBar.d.ts +1 -2
  181. package/dist/react/core/inputs/LimitsBar.js +271 -196
  182. package/dist/react/core/inputs/LimitsBar.js.map +1 -1
  183. package/dist/react/core/inputs/NumberInput.d.ts +2 -3
  184. package/dist/react/core/inputs/NumberInput.js +531 -503
  185. package/dist/react/core/inputs/NumberInput.js.map +1 -1
  186. package/dist/react/core/inputs/PinInput.d.ts +2 -3
  187. package/dist/react/core/inputs/PinInput.js +224 -207
  188. package/dist/react/core/inputs/PinInput.js.map +1 -1
  189. package/dist/react/core/inputs/Select.d.ts +1 -2
  190. package/dist/react/core/inputs/Select.js +298 -299
  191. package/dist/react/core/inputs/Select.js.map +1 -1
  192. package/dist/react/core/inputs/Toggle.d.ts +2 -3
  193. package/dist/react/core/inputs/Toggle.js +142 -148
  194. package/dist/react/core/inputs/Toggle.js.map +1 -1
  195. package/dist/react/core/layout/Box.d.ts +3 -4
  196. package/dist/react/core/layout/Box.js +118 -122
  197. package/dist/react/core/layout/Box.js.map +1 -1
  198. package/dist/react/core/layout/Center.d.ts +0 -1
  199. package/dist/react/core/layout/Center.js +45 -32
  200. package/dist/react/core/layout/Center.js.map +1 -1
  201. package/dist/react/core/layout/Divider.d.ts +1 -2
  202. package/dist/react/core/layout/Divider.js +112 -106
  203. package/dist/react/core/layout/Divider.js.map +1 -1
  204. package/dist/react/core/layout/Flex.d.ts +4 -5
  205. package/dist/react/core/layout/Flex.js +120 -124
  206. package/dist/react/core/layout/Flex.js.map +1 -1
  207. package/dist/react/core/layout/Grid.d.ts +5 -6
  208. package/dist/react/core/layout/Grid.js +131 -138
  209. package/dist/react/core/layout/Grid.js.map +1 -1
  210. package/dist/react/core/layout/Spacer.d.ts +0 -1
  211. package/dist/react/core/layout/Spacer.js +36 -29
  212. package/dist/react/core/layout/Spacer.js.map +1 -1
  213. package/dist/react/core/layout/Stack.d.ts +4 -5
  214. package/dist/react/core/layout/Stack.js +127 -70
  215. package/dist/react/core/layout/Stack.js.map +1 -1
  216. package/dist/react/core/layout/responsive.d.ts +1 -2
  217. package/dist/react/core/layout/responsive.js +25 -19
  218. package/dist/react/core/layout/responsive.js.map +1 -1
  219. package/dist/react/core/layout/useBreakpoint.d.ts +1 -1
  220. package/dist/react/core/layout/useBreakpoint.js +119 -66
  221. package/dist/react/core/layout/useBreakpoint.js.map +1 -1
  222. package/dist/react/core/navigation/AppBar.d.ts +1 -2
  223. package/dist/react/core/navigation/AppBar.js +827 -805
  224. package/dist/react/core/navigation/AppBar.js.map +1 -1
  225. package/dist/react/core/navigation/Pagination.d.ts +2 -3
  226. package/dist/react/core/navigation/Pagination.js +207 -187
  227. package/dist/react/core/navigation/Pagination.js.map +1 -1
  228. package/dist/react/core/navigation/SideNav.d.ts +5 -6
  229. package/dist/react/core/navigation/SideNav.js +855 -629
  230. package/dist/react/core/navigation/SideNav.js.map +1 -1
  231. package/dist/react/core/navigation/Tabs.d.ts +0 -1
  232. package/dist/react/core/navigation/Tabs.js +113 -119
  233. package/dist/react/core/navigation/Tabs.js.map +1 -1
  234. package/dist/react/core/overlays/Popover.d.ts +2 -3
  235. package/dist/react/core/overlays/Popover.js +303 -282
  236. package/dist/react/core/overlays/Popover.js.map +1 -1
  237. package/dist/react/core/overlays/SidePanel.d.ts +1 -2
  238. package/dist/react/core/overlays/SidePanel.js +217 -212
  239. package/dist/react/core/overlays/SidePanel.js.map +1 -1
  240. package/dist/react/core/overlays/Tooltip.d.ts +1 -2
  241. package/dist/react/core/overlays/Tooltip.js +170 -176
  242. package/dist/react/core/overlays/Tooltip.js.map +1 -1
  243. package/dist/react/core/widgets/ActivityPlanner.d.ts +0 -1
  244. package/dist/react/core/widgets/ActivityPlanner.js +855 -517
  245. package/dist/react/core/widgets/ActivityPlanner.js.map +1 -1
  246. package/dist/react/core/widgets/Capture.d.ts +2 -3
  247. package/dist/react/core/widgets/Capture.js +965 -779
  248. package/dist/react/core/widgets/Capture.js.map +1 -1
  249. package/dist/react/core/widgets/ChatPanel.d.ts +16 -17
  250. package/dist/react/core/widgets/ChatPanel.js +1734 -1034
  251. package/dist/react/core/widgets/ChatPanel.js.map +1 -1
  252. package/dist/react/core/widgets/ColorPickerPanel.d.ts +0 -1
  253. package/dist/react/core/widgets/ColorPickerPanel.js +298 -287
  254. package/dist/react/core/widgets/ColorPickerPanel.js.map +1 -1
  255. package/dist/react/core/widgets/CommandBuilder.d.ts +2 -3
  256. package/dist/react/core/widgets/CommandBuilder.js +624 -516
  257. package/dist/react/core/widgets/CommandBuilder.js.map +1 -1
  258. package/dist/react/core/widgets/ConnectionForm.d.ts +2 -3
  259. package/dist/react/core/widgets/ConnectionForm.js +528 -492
  260. package/dist/react/core/widgets/ConnectionForm.js.map +1 -1
  261. package/dist/react/core/widgets/FileExplorer.d.ts +3 -4
  262. package/dist/react/core/widgets/FileExplorer.js +617 -505
  263. package/dist/react/core/widgets/FileExplorer.js.map +1 -1
  264. package/dist/react/core/widgets/HexViewer.d.ts +2 -3
  265. package/dist/react/core/widgets/HexViewer.js +1353 -1091
  266. package/dist/react/core/widgets/HexViewer.js.map +1 -1
  267. package/dist/react/core/widgets/ImageFrame.d.ts +1 -2
  268. package/dist/react/core/widgets/ImageFrame.js +230 -193
  269. package/dist/react/core/widgets/ImageFrame.js.map +1 -1
  270. package/dist/react/core/widgets/ImageGallery.d.ts +2 -1
  271. package/dist/react/core/widgets/ImageGallery.js +380 -314
  272. package/dist/react/core/widgets/ImageGallery.js.map +1 -1
  273. package/dist/react/core/widgets/ImagePanel.d.ts +0 -1
  274. package/dist/react/core/widgets/ImagePanel.js +110 -101
  275. package/dist/react/core/widgets/ImagePanel.js.map +1 -1
  276. package/dist/react/core/widgets/LogViewer.d.ts +2 -3
  277. package/dist/react/core/widgets/LogViewer.js +711 -607
  278. package/dist/react/core/widgets/LogViewer.js.map +1 -1
  279. package/dist/react/core/widgets/MessageStream.d.ts +3 -4
  280. package/dist/react/core/widgets/MessageStream.js +514 -444
  281. package/dist/react/core/widgets/MessageStream.js.map +1 -1
  282. package/dist/react/core/widgets/MissionCalendar.d.ts +3 -4
  283. package/dist/react/core/widgets/MissionCalendar.js +1488 -1020
  284. package/dist/react/core/widgets/MissionCalendar.js.map +1 -1
  285. package/dist/react/core/widgets/PacketViewer.d.ts +2 -3
  286. package/dist/react/core/widgets/PacketViewer.js +550 -421
  287. package/dist/react/core/widgets/PacketViewer.js.map +1 -1
  288. package/dist/react/core/widgets/capture-placeholder.png.js +6 -5
  289. package/dist/react/core/widgets/capture-placeholder.png.js.map +1 -1
  290. package/dist/react/hooks/index.d.ts +5 -5
  291. package/dist/react/hooks/useAccessWindows.d.ts +0 -1
  292. package/dist/react/hooks/useCompactMode.d.ts +1 -1
  293. package/dist/react/hooks/useCompactMode.js +104 -58
  294. package/dist/react/hooks/useCompactMode.js.map +1 -1
  295. package/dist/react/hooks/useGroundTrackHistory.d.ts +0 -1
  296. package/dist/react/hooks/useSimulationScene.d.ts +1 -2
  297. package/dist/react/hooks/useSimulationScene.js +481 -374
  298. package/dist/react/hooks/useSimulationScene.js.map +1 -1
  299. package/dist/react/index.d.ts +3 -3
  300. package/dist/react/panels/LayerControlPanel.d.ts +1 -2
  301. package/dist/react/panels/LayerControlPanel.js +223 -180
  302. package/dist/react/panels/LayerControlPanel.js.map +1 -1
  303. package/dist/react/panels/ObjectInventoryPanel.d.ts +2 -3
  304. package/dist/react/panels/ObjectInventoryPanel.js +315 -250
  305. package/dist/react/panels/ObjectInventoryPanel.js.map +1 -1
  306. package/dist/react/panels/index.d.ts +1 -1
  307. package/dist/react/panels/index.js +1 -6
  308. package/dist/react/shared/ErrorBoundary.d.ts +1 -2
  309. package/dist/react/shared/ErrorBoundary.js +170 -139
  310. package/dist/react/shared/ErrorBoundary.js.map +1 -1
  311. package/dist/react/shared/Skeleton.d.ts +1 -2
  312. package/dist/react/shared/Skeleton.js +300 -301
  313. package/dist/react/shared/Skeleton.js.map +1 -1
  314. package/dist/react/theme/ThemeProvider.d.ts +2 -321
  315. package/dist/react/theme/ThemeProvider.js +313 -939
  316. package/dist/react/theme/ThemeProvider.js.map +1 -1
  317. package/dist/react/theme/cardAccent.d.ts +1 -2
  318. package/dist/react/theme/cardAccent.js +196 -126
  319. package/dist/react/theme/cardAccent.js.map +1 -1
  320. package/dist/react/theme/config.d.ts +0 -1
  321. package/dist/react/theme/config.js +47 -25
  322. package/dist/react/theme/config.js.map +1 -1
  323. package/dist/react/theme/index.d.ts +2 -2
  324. package/dist/react/theme/index.js +1 -16
  325. package/dist/react/theme/types.d.ts +332 -0
  326. package/dist/react/theme/types.js +39 -0
  327. package/dist/react/theme/types.js.map +1 -0
  328. package/dist/react/types.d.ts +8 -8
  329. package/dist/react/types.js +147 -47
  330. package/dist/react/types.js.map +1 -1
  331. package/dist/react/utils/categoryPalette.d.ts +0 -1
  332. package/dist/react/utils/categoryPalette.js +91 -102
  333. package/dist/react/utils/categoryPalette.js.map +1 -1
  334. package/dist/react/utils/index.d.ts +5 -5
  335. package/dist/react/utils/index.js +457 -371
  336. package/dist/react/utils/index.js.map +1 -1
  337. package/dist/react/visualizations/EclipseTimerCard.d.ts +0 -1
  338. package/dist/react/visualizations/LinkBudgetCard.d.ts +0 -1
  339. package/dist/react/visualizations/NavBallCard.d.ts +0 -1
  340. package/dist/react/visualizations/PropulsionCard.d.ts +1 -2
  341. package/dist/react/visualizations/SensorFootprintCard.d.ts +1 -2
  342. package/dist/react/visualizations/ThermalHeatmapCard.d.ts +0 -1
  343. package/dist/react/visualizations/index.d.ts +3 -3
  344. package/dist/react.d.ts +2 -1
  345. package/dist/react.js +17 -221
  346. package/dist/shaders/atmosphere.frag.js +6 -5
  347. package/dist/shaders/atmosphere.frag.js.map +1 -1
  348. package/dist/shaders/atmosphere.vert.js +6 -5
  349. package/dist/shaders/atmosphere.vert.js.map +1 -1
  350. package/dist/shaders/stars.frag.js +6 -5
  351. package/dist/shaders/stars.frag.js.map +1 -1
  352. package/dist/shaders/stars.vert.js +6 -5
  353. package/dist/shaders/stars.vert.js.map +1 -1
  354. package/dist/style.css +26 -3
  355. package/dist/tokens/core.d.ts +159 -0
  356. package/dist/tokens/core.js +144 -0
  357. package/dist/tokens/core.js.map +1 -0
  358. package/dist/tokens/css-vars.d.ts +213 -2
  359. package/dist/tokens/css-vars.js +590 -227
  360. package/dist/tokens/css-vars.js.map +1 -1
  361. package/dist/tokens/index.d.ts +31 -228
  362. package/dist/tokens/index.js +281 -366
  363. package/dist/tokens/index.js.map +1 -1
  364. package/dist/tokens/palettes/astro.d.ts +129 -0
  365. package/dist/tokens/palettes/astro.js +112 -0
  366. package/dist/tokens/palettes/astro.js.map +1 -0
  367. package/dist/tokens/palettes/index.d.ts +288 -0
  368. package/dist/tokens/palettes/index.js +35 -0
  369. package/dist/tokens/palettes/index.js.map +1 -0
  370. package/dist/tokens/palettes/tailwind.d.ts +324 -0
  371. package/dist/tokens/palettes/tailwind.js +201 -0
  372. package/dist/tokens/palettes/tailwind.js.map +1 -0
  373. package/dist/tokens/palettes/zendir.d.ts +126 -0
  374. package/dist/tokens/palettes/zendir.js +92 -0
  375. package/dist/tokens/palettes/zendir.js.map +1 -0
  376. package/dist/tokens/themes.d.ts +30 -0
  377. package/dist/tokens/themes.js +704 -0
  378. package/dist/tokens/themes.js.map +1 -0
  379. package/dist/tokens/tokens.css +533 -155
  380. package/dist/types/index.d.ts +2 -2
  381. package/package.json +310 -313
  382. package/dist/index.js.map +0 -1
  383. package/dist/react/3d/index.js.map +0 -1
  384. package/dist/react/astro/index.js.map +0 -1
  385. package/dist/react/cards/index.js.map +0 -1
  386. package/dist/react/charts/index.js.map +0 -1
  387. package/dist/react/core/index.js.map +0 -1
  388. package/dist/react/panels/index.js.map +0 -1
  389. package/dist/react/theme/astro-tokens.d.ts +0 -153
  390. package/dist/react/theme/index.js.map +0 -1
  391. package/dist/react.js.map +0 -1
@@ -1,1433 +1,1353 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- import { memo, forwardRef, useRef, useMemo, useCallback, useImperativeHandle, useEffect, useState } from "react";
3
- import ReactEChartsCore from "echarts-for-react/lib/core";
4
- import * as echarts from "echarts/core";
5
- import { LineChart, BarChart, PieChart, ScatterChart, RadarChart, GaugeChart, HeatmapChart, CandlestickChart, BoxplotChart, TreemapChart, SunburstChart, FunnelChart, SankeyChart, CustomChart, GraphChart, ParallelChart } from "echarts/charts";
6
- import { GridComponent, TooltipComponent, TitleComponent, LegendComponent, DataZoomComponent, ToolboxComponent, MarkLineComponent, MarkAreaComponent, MarkPointComponent, VisualMapComponent, BrushComponent, PolarComponent, RadarComponent, GeoComponent, ParallelComponent } from "echarts/components";
7
- import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
8
1
  import { useTheme } from "../../theme/ThemeProvider.js";
9
2
  import { AstroIcon } from "../../core/display/AstroIcon.js";
10
3
  import { HeaderIconWithStatus } from "../../core/display/HeaderIconWithStatus.js";
11
4
  import { useCardBorderStyle } from "../../context/DisplaySettingsContext.js";
12
- import { createAstroEChartsTheme, getSeriesColor, createAreaGradient } from "./theme.js";
13
- const STATUS_SHAPES = {
14
- off: (size, color) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "5", fill: color }) }),
15
- standby: (size, color) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "5", fill: color }) }),
16
- normal: (size, color) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "5", fill: color }) }),
17
- caution: (size, color) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx("rect", { x: "1", y: "1", width: "10", height: "10", fill: color }) }),
18
- serious: (size, color) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx("polygon", { points: "6,1 11,6 6,11 1,6", fill: color }) }),
19
- critical: (size, color) => /* @__PURE__ */ jsx("svg", { viewBox: "0 0 12 12", width: size, height: size, children: /* @__PURE__ */ jsx("polygon", { points: "6,11 1,2 11,2", fill: color }) })
5
+ import { createAreaGradient, createAstroEChartsTheme, getSeriesColor } from "./theme.js";
6
+ import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import ReactEChartsCore from "echarts-for-react/lib/core";
9
+ import * as echarts from "echarts/core";
10
+ import { BarChart, BoxplotChart, CandlestickChart, CustomChart, FunnelChart, GaugeChart, GraphChart, HeatmapChart, LineChart, ParallelChart, PieChart, RadarChart, SankeyChart, ScatterChart, SunburstChart, TreemapChart } from "echarts/charts";
11
+ import { BrushComponent, DataZoomComponent, GeoComponent, GridComponent, LegendComponent, MarkAreaComponent, MarkLineComponent, MarkPointComponent, ParallelComponent, PolarComponent, RadarComponent, TitleComponent, ToolboxComponent, TooltipComponent, VisualMapComponent } from "echarts/components";
12
+ import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
13
+ //#region src/react/charts/unified/AstroChart.tsx
14
+ /**
15
+ * @zendir/ui - AstroChart Component
16
+ *
17
+ * Enterprise-grade unified charting component built on ECharts.
18
+ * Follows AstroUXD design patterns with full theme integration.
19
+ *
20
+ * Features:
21
+ * - 15+ chart types
22
+ * - Real-time streaming support
23
+ * - Zoom, pan, brush selection
24
+ * - Annotations (thresholds, regions)
25
+ * - Export (PNG, SVG, CSV)
26
+ * - Crosshair sync across charts
27
+ * - Full accessibility support
28
+ * - Dark/light theme support
29
+ */
30
+ var STATUS_SHAPES = {
31
+ off: (size, color) => /* @__PURE__ */ jsx("svg", {
32
+ viewBox: "0 0 12 12",
33
+ width: size,
34
+ height: size,
35
+ children: /* @__PURE__ */ jsx("circle", {
36
+ cx: "6",
37
+ cy: "6",
38
+ r: "5",
39
+ fill: color
40
+ })
41
+ }),
42
+ standby: (size, color) => /* @__PURE__ */ jsx("svg", {
43
+ viewBox: "0 0 12 12",
44
+ width: size,
45
+ height: size,
46
+ children: /* @__PURE__ */ jsx("circle", {
47
+ cx: "6",
48
+ cy: "6",
49
+ r: "5",
50
+ fill: color
51
+ })
52
+ }),
53
+ normal: (size, color) => /* @__PURE__ */ jsx("svg", {
54
+ viewBox: "0 0 12 12",
55
+ width: size,
56
+ height: size,
57
+ children: /* @__PURE__ */ jsx("circle", {
58
+ cx: "6",
59
+ cy: "6",
60
+ r: "5",
61
+ fill: color
62
+ })
63
+ }),
64
+ caution: (size, color) => /* @__PURE__ */ jsx("svg", {
65
+ viewBox: "0 0 12 12",
66
+ width: size,
67
+ height: size,
68
+ children: /* @__PURE__ */ jsx("rect", {
69
+ x: "1",
70
+ y: "1",
71
+ width: "10",
72
+ height: "10",
73
+ fill: color
74
+ })
75
+ }),
76
+ serious: (size, color) => /* @__PURE__ */ jsx("svg", {
77
+ viewBox: "0 0 12 12",
78
+ width: size,
79
+ height: size,
80
+ children: /* @__PURE__ */ jsx("polygon", {
81
+ points: "6,1 11,6 6,11 1,6",
82
+ fill: color
83
+ })
84
+ }),
85
+ critical: (size, color) => /* @__PURE__ */ jsx("svg", {
86
+ viewBox: "0 0 12 12",
87
+ width: size,
88
+ height: size,
89
+ children: /* @__PURE__ */ jsx("polygon", {
90
+ points: "6,11 1,2 11,2",
91
+ fill: color
92
+ })
93
+ })
20
94
  };
21
- const STATUS_LABELS = {
22
- off: "Off",
23
- standby: "Standby",
24
- normal: "Normal",
25
- caution: "Caution",
26
- serious: "Serious",
27
- critical: "Critical"
95
+ /**
96
+ * Astro UX Status Labels
97
+ * Follows Astro UXDS naming conventions
98
+ * https://www.astrouxds.com/patterns/status-system/
99
+ */
100
+ var STATUS_LABELS = {
101
+ off: "Off",
102
+ standby: "Standby",
103
+ normal: "Normal",
104
+ caution: "Caution",
105
+ serious: "Serious",
106
+ critical: "Critical"
28
107
  };
108
+ /** Slug for safe filenames: lowercase, alphanumeric and hyphens only */
29
109
  function slug(str) {
30
- return str.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
110
+ return str.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
31
111
  }
112
+ /** Build base export name from title, series names, and chart type */
32
113
  function derivedExportBaseName(title, seriesNames, chartType) {
33
- const parts = ["zendir"];
34
- if (title) parts.push(slug(title));
35
- else parts.push("chart");
36
- const seriesSlug = seriesNames.slice(0, 4).map(slug).filter(Boolean).join("-");
37
- if (seriesSlug) parts.push(seriesSlug);
38
- parts.push(slug(chartType));
39
- return parts.join("-") || "zendir-chart";
114
+ const parts = ["zendir"];
115
+ if (title) parts.push(slug(title));
116
+ else parts.push("chart");
117
+ const seriesSlug = seriesNames.slice(0, 4).map(slug).filter(Boolean).join("-");
118
+ if (seriesSlug) parts.push(seriesSlug);
119
+ parts.push(slug(chartType));
120
+ return parts.join("-") || "zendir-chart";
40
121
  }
41
122
  echarts.use([
42
- LineChart,
43
- BarChart,
44
- PieChart,
45
- ScatterChart,
46
- RadarChart,
47
- GaugeChart,
48
- HeatmapChart,
49
- CandlestickChart,
50
- BoxplotChart,
51
- TreemapChart,
52
- SunburstChart,
53
- FunnelChart,
54
- SankeyChart,
55
- CustomChart,
56
- GraphChart,
57
- ParallelChart,
58
- GridComponent,
59
- TooltipComponent,
60
- TitleComponent,
61
- LegendComponent,
62
- DataZoomComponent,
63
- ToolboxComponent,
64
- MarkLineComponent,
65
- MarkAreaComponent,
66
- MarkPointComponent,
67
- VisualMapComponent,
68
- BrushComponent,
69
- PolarComponent,
70
- RadarComponent,
71
- GeoComponent,
72
- ParallelComponent,
73
- CanvasRenderer,
74
- SVGRenderer
123
+ LineChart,
124
+ BarChart,
125
+ PieChart,
126
+ ScatterChart,
127
+ RadarChart,
128
+ GaugeChart,
129
+ HeatmapChart,
130
+ CandlestickChart,
131
+ BoxplotChart,
132
+ TreemapChart,
133
+ SunburstChart,
134
+ FunnelChart,
135
+ SankeyChart,
136
+ CustomChart,
137
+ GraphChart,
138
+ ParallelChart,
139
+ GridComponent,
140
+ TooltipComponent,
141
+ TitleComponent,
142
+ LegendComponent,
143
+ DataZoomComponent,
144
+ ToolboxComponent,
145
+ MarkLineComponent,
146
+ MarkAreaComponent,
147
+ MarkPointComponent,
148
+ VisualMapComponent,
149
+ BrushComponent,
150
+ PolarComponent,
151
+ RadarComponent,
152
+ GeoComponent,
153
+ ParallelComponent,
154
+ CanvasRenderer,
155
+ SVGRenderer
75
156
  ]);
76
157
  function transformSeriesToECharts(series, chartType, theme) {
77
- return series.map((s, index) => {
78
- var _a, _b, _c, _d, _e;
79
- const seriesType = s.type || chartType;
80
- const color = s.color || getSeriesColor(index);
81
- const baseSeries = {
82
- id: s.id,
83
- name: s.name,
84
- type: mapChartType(seriesType),
85
- data: transformData(s.data, seriesType),
86
- yAxisIndex: s.yAxisIndex || 0,
87
- showSymbol: seriesType === "scatter" || ((_a = s.symbol) == null ? void 0 : _a.type) !== "none",
88
- smooth: s.smooth ?? (seriesType === "line" || seriesType === "area")
89
- };
90
- if (seriesType === "line" || seriesType === "area") {
91
- baseSeries.lineStyle = {
92
- width: ((_b = s.lineStyle) == null ? void 0 : _b.width) ?? 2,
93
- type: ((_c = s.lineStyle) == null ? void 0 : _c.type) ?? "solid",
94
- opacity: ((_d = s.lineStyle) == null ? void 0 : _d.opacity) ?? 1
95
- };
96
- baseSeries.itemStyle = { color };
97
- if (seriesType === "area") {
98
- baseSeries.areaStyle = s.areaStyle || {
99
- opacity: 0.3,
100
- color: createAreaGradient(color)
101
- };
102
- }
103
- if (s.symbol) {
104
- baseSeries.symbol = s.symbol.type || "circle";
105
- baseSeries.symbolSize = s.symbol.size || 6;
106
- }
107
- }
108
- if (seriesType === "bar") {
109
- baseSeries.itemStyle = {
110
- color,
111
- borderRadius: [4, 4, 0, 0]
112
- };
113
- if (s.stack) {
114
- baseSeries.stack = s.stack;
115
- }
116
- }
117
- if (seriesType === "pie" || seriesType === "donut") {
118
- baseSeries.radius = seriesType === "donut" ? ["40%", "70%"] : "70%";
119
- baseSeries.label = {
120
- show: true,
121
- formatter: "{b}: {d}%",
122
- color: theme.textStyle.color,
123
- textBorderWidth: 0,
124
- textBorderColor: "transparent"
125
- };
126
- baseSeries.emphasis = {
127
- itemStyle: {
128
- shadowBlur: 10,
129
- shadowOffsetX: 0,
130
- shadowColor: "rgba(0, 0, 0, 0.5)"
131
- }
132
- };
133
- }
134
- if (seriesType === "scatter") {
135
- baseSeries.symbolSize = ((_e = s.symbol) == null ? void 0 : _e.size) || 10;
136
- baseSeries.itemStyle = { color };
137
- }
138
- if (seriesType === "gauge") {
139
- baseSeries.detail = {
140
- formatter: "{value}%",
141
- fontSize: 20,
142
- color: theme.textStyle.color
143
- };
144
- baseSeries.axisLine = {
145
- lineStyle: {
146
- width: 10,
147
- color: [
148
- [0.3, theme.color[1]],
149
- // Green
150
- [0.7, theme.color[3]],
151
- // Yellow
152
- [1, theme.color[2]]
153
- // Red
154
- ]
155
- }
156
- };
157
- }
158
- return baseSeries;
159
- });
158
+ return series.map((s, index) => {
159
+ const seriesType = s.type || chartType;
160
+ const color = s.color || getSeriesColor(index);
161
+ const baseSeries = {
162
+ id: s.id,
163
+ name: s.name,
164
+ type: mapChartType(seriesType),
165
+ data: transformData(s.data, seriesType),
166
+ yAxisIndex: s.yAxisIndex || 0,
167
+ showSymbol: seriesType === "scatter" || s.symbol?.type !== "none",
168
+ smooth: s.smooth ?? (seriesType === "line" || seriesType === "area")
169
+ };
170
+ if (seriesType === "line" || seriesType === "area") {
171
+ baseSeries.lineStyle = {
172
+ width: s.lineStyle?.width ?? 2,
173
+ type: s.lineStyle?.type ?? "solid",
174
+ opacity: s.lineStyle?.opacity ?? 1
175
+ };
176
+ baseSeries.itemStyle = { color };
177
+ if (seriesType === "area") baseSeries.areaStyle = s.areaStyle || {
178
+ opacity: .3,
179
+ color: createAreaGradient(color)
180
+ };
181
+ if (s.symbol) {
182
+ baseSeries.symbol = s.symbol.type || "circle";
183
+ baseSeries.symbolSize = s.symbol.size || 6;
184
+ }
185
+ }
186
+ if (seriesType === "bar") {
187
+ baseSeries.itemStyle = {
188
+ color,
189
+ borderRadius: [
190
+ 4,
191
+ 4,
192
+ 0,
193
+ 0
194
+ ]
195
+ };
196
+ if (s.stack) baseSeries.stack = s.stack;
197
+ }
198
+ if (seriesType === "pie" || seriesType === "donut") {
199
+ baseSeries.radius = seriesType === "donut" ? ["40%", "70%"] : "70%";
200
+ baseSeries.label = {
201
+ show: true,
202
+ formatter: "{b}: {d}%",
203
+ color: theme.textStyle.color,
204
+ textBorderWidth: 0,
205
+ textBorderColor: "transparent"
206
+ };
207
+ baseSeries.emphasis = { itemStyle: {
208
+ shadowBlur: 10,
209
+ shadowOffsetX: 0,
210
+ shadowColor: "rgba(0, 0, 0, 0.5)"
211
+ } };
212
+ }
213
+ if (seriesType === "scatter") {
214
+ baseSeries.symbolSize = s.symbol?.size || 10;
215
+ baseSeries.itemStyle = { color };
216
+ }
217
+ if (seriesType === "gauge") {
218
+ baseSeries.detail = {
219
+ formatter: "{value}%",
220
+ fontSize: 20,
221
+ color: theme.textStyle.color
222
+ };
223
+ baseSeries.axisLine = { lineStyle: {
224
+ width: 10,
225
+ color: [
226
+ [.3, theme.color[1]],
227
+ [.7, theme.color[3]],
228
+ [1, theme.color[2]]
229
+ ]
230
+ } };
231
+ }
232
+ return baseSeries;
233
+ });
160
234
  }
161
235
  function mapChartType(type) {
162
- switch (type) {
163
- case "area":
164
- return "line";
165
- case "donut":
166
- return "pie";
167
- default:
168
- return type;
169
- }
236
+ switch (type) {
237
+ case "area": return "line";
238
+ case "donut": return "pie";
239
+ default: return type;
240
+ }
170
241
  }
171
242
  function transformData(data, type) {
172
- if (!data || data.length === 0) return [];
173
- if (typeof data[0] === "number") {
174
- return data;
175
- }
176
- if (Array.isArray(data[0])) {
177
- return data;
178
- }
179
- const firstItem = data[0];
180
- if ("time" in firstItem) {
181
- return data.map((d) => [d.time, d.value]);
182
- }
183
- if (type === "pie" || type === "donut") {
184
- return data.map((d) => ({
185
- name: String(d.x),
186
- value: d.y,
187
- // Apply color via itemStyle if specified
188
- ...d.color ? { itemStyle: { color: d.color } } : {},
189
- // Preserve any additional metadata
190
- ...d.meta || {}
191
- }));
192
- }
193
- if (type === "scatter") {
194
- return data.map((d) => ({
195
- value: [d.x, d.y],
196
- ...d.color ? { itemStyle: { color: d.color } } : {},
197
- ...d.label ? { name: d.label } : {}
198
- }));
199
- }
200
- return data.map((d) => [d.x, d.y]);
243
+ if (!data || data.length === 0) return [];
244
+ if (typeof data[0] === "number") return data;
245
+ if (Array.isArray(data[0])) return data;
246
+ if ("time" in data[0]) return data.map((d) => [d.time, d.value]);
247
+ if (type === "pie" || type === "donut") return data.map((d) => ({
248
+ name: String(d.x),
249
+ value: d.y,
250
+ ...d.color ? { itemStyle: { color: d.color } } : {},
251
+ ...d.meta || {}
252
+ }));
253
+ if (type === "scatter") return data.map((d) => ({
254
+ value: [d.x, d.y],
255
+ ...d.color ? { itemStyle: { color: d.color } } : {},
256
+ ...d.label ? { name: d.label } : {}
257
+ }));
258
+ return data.map((d) => [d.x, d.y]);
201
259
  }
202
260
  function buildEChartsOptions(props, theme, hideTitle = false) {
203
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
204
- const {
205
- type,
206
- series,
207
- title,
208
- subtitle,
209
- xAxis,
210
- yAxis,
211
- tooltip,
212
- legend,
213
- zoom,
214
- annotations,
215
- loading,
216
- compactAxes = true
217
- // Default: hide axis names for more chart space
218
- } = props;
219
- const showEChartsTitle = title && !hideTitle;
220
- const isPolar = type === "radar";
221
- const isPie = type === "pie" || type === "donut";
222
- const isGauge = type === "gauge";
223
- const isSankey = type === "sankey";
224
- const isTreemap = type === "treemap" || type === "sunburst";
225
- const isGraph = ((_a = props.echartsOptions) == null ? void 0 : _a.series) && Array.isArray(props.echartsOptions.series) && props.echartsOptions.series.some((s) => (s == null ? void 0 : s.type) === "graph");
226
- const is3D = !!(((_b = props.echartsOptions) == null ? void 0 : _b.grid3D) || ((_c = props.echartsOptions) == null ? void 0 : _c.xAxis3D) || ((_d = props.echartsOptions) == null ? void 0 : _d.globe) || ((_e = props.echartsOptions) == null ? void 0 : _e.series) && Array.isArray(props.echartsOptions.series) && props.echartsOptions.series.some((s) => {
227
- const seriesType = (s == null ? void 0 : s.type) || "";
228
- return seriesType.includes("3D") || seriesType.includes("3d");
229
- }));
230
- const needsGrid = !isPolar && !isPie && !isGauge && !isSankey && !isTreemap && !isGraph && !is3D && !props.hideAxes;
231
- const hasTitle = hideTitle ? true : !!title;
232
- const hasSubtitle = hideTitle ? false : !!subtitle;
233
- const legendPosition = (legend == null ? void 0 : legend.position) ?? "bottom";
234
- const legendAtTop = legendPosition === "top";
235
- const legendAtBottom = legendPosition === "bottom";
236
- const showLegend = (legend == null ? void 0 : legend.show) !== false;
237
- const options = {
238
- // Title - positioned to avoid legend overlap (hidden when using custom header)
239
- title: showEChartsTitle ? {
240
- text: title,
241
- subtext: subtitle,
242
- left: "center",
243
- top: legendAtTop && showLegend ? 35 : 10,
244
- textStyle: { ...theme.title.textStyle, fontWeight: theme.title.textStyle.fontWeight ?? "normal" },
245
- subtextStyle: theme.title.subtextStyle
246
- } : void 0,
247
- // Tooltip with improved contrast
248
- // When compactAxes is true, axis names are shown in the axisPointer label on hover
249
- tooltip: (tooltip == null ? void 0 : tooltip.enabled) !== false ? {
250
- trigger: (tooltip == null ? void 0 : tooltip.trigger) || (isPie ? "item" : "axis"),
251
- axisPointer: {
252
- type: (tooltip == null ? void 0 : tooltip.crosshair) === true || (tooltip == null ? void 0 : tooltip.crosshair) === "both" ? "cross" : "line",
253
- lineStyle: theme.axisPointer.lineStyle,
254
- crossStyle: theme.axisPointer.crossStyle,
255
- // Show axis value labels on hover (includes axis name context)
256
- label: compactAxes ? {
257
- show: true,
258
- backgroundColor: theme.tooltip.backgroundColor,
259
- borderColor: theme.tooltip.borderColor,
260
- color: theme.tooltip.textStyle.color,
261
- fontSize: 11,
262
- padding: [4, 8],
263
- // Add axis name prefix to the label when in compact mode
264
- formatter: (params) => {
265
- var _a2;
266
- const axisName = params.axisDimension === "x" ? xAxis == null ? void 0 : xAxis.name : Array.isArray(yAxis) ? (_a2 = yAxis[params.axisIndex]) == null ? void 0 : _a2.name : yAxis == null ? void 0 : yAxis.name;
267
- const value = typeof params.value === "number" ? params.value.toLocaleString() : params.value;
268
- return axisName ? `${axisName}: ${value}` : String(value);
269
- }
270
- } : void 0
271
- },
272
- backgroundColor: theme.tooltip.backgroundColor,
273
- borderColor: theme.tooltip.borderColor,
274
- borderWidth: theme.tooltip.borderWidth,
275
- textStyle: {
276
- ...theme.tooltip.textStyle,
277
- fontSize: 14
278
- // AstroUXDS minimum 14pt
279
- },
280
- extraCssText: theme.tooltip.extraCssText,
281
- confine: (tooltip == null ? void 0 : tooltip.confine) ?? true,
282
- formatter: tooltip == null ? void 0 : tooltip.formatter
283
- } : void 0,
284
- // Legend - ultra-compact styling for maximum chart space
285
- legend: showLegend ? {
286
- show: true,
287
- type: "scroll",
288
- orient: (legend == null ? void 0 : legend.orient) || "horizontal",
289
- left: (legend == null ? void 0 : legend.position) === "left" ? "left" : (legend == null ? void 0 : legend.position) === "right" ? "right" : "center",
290
- top: legendAtTop ? 4 : void 0,
291
- bottom: legendAtBottom ? 2 : void 0,
292
- padding: [2, 6],
293
- itemGap: 8,
294
- itemWidth: 12,
295
- itemHeight: 6,
296
- textStyle: {
297
- ...theme.legend.textStyle,
298
- fontSize: 10
299
- // Ultra-compact for maximum chart space
300
- },
301
- inactiveColor: theme.legend.inactiveColor,
302
- selectedMode: (legend == null ? void 0 : legend.interactive) !== false
303
- } : { show: false },
304
- // Grid - minimal spacing for maximum chart plotting area
305
- // When compactAxes is true, axis names are hidden so we need minimal padding
306
- // containLabel: true ensures axis tick labels don't get cut off
307
- // Extra space only needed for slider zoom (inside zoom is invisible)
308
- grid: needsGrid ? {
309
- left: compactAxes ? 8 : 40,
310
- right: Array.isArray(yAxis) && yAxis.length > 1 ? compactAxes ? 8 : 40 : 8,
311
- top: hasTitle ? hasSubtitle ? 50 : 36 : legendAtTop && showLegend ? 26 : 4,
312
- bottom: (legendAtBottom && showLegend ? 26 : 16) + ((zoom == null ? void 0 : zoom.type) === "slider" || (zoom == null ? void 0 : zoom.type) === "both" ? 26 : 0),
313
- containLabel: true
314
- } : void 0,
315
- // X Axis - compact font sizes for more chart space
316
- // In compact mode, hide axis name (shown in tooltip instead)
317
- xAxis: needsGrid ? {
318
- type: (xAxis == null ? void 0 : xAxis.type) || "time",
319
- name: compactAxes ? void 0 : xAxis == null ? void 0 : xAxis.name,
320
- nameLocation: (xAxis == null ? void 0 : xAxis.nameLocation) || "middle",
321
- nameGap: 18,
322
- nameTextStyle: {
323
- ...theme.xAxis.nameTextStyle,
324
- fontSize: 10,
325
- // Ultra-compact for maximum chart space
326
- fontWeight: 500
327
- },
328
- min: xAxis == null ? void 0 : xAxis.min,
329
- max: xAxis == null ? void 0 : xAxis.max,
330
- axisLine: {
331
- show: (xAxis == null ? void 0 : xAxis.showLine) !== false,
332
- lineStyle: theme.xAxis.axisLine.lineStyle
333
- },
334
- axisTick: {
335
- lineStyle: theme.xAxis.axisTick.lineStyle
336
- },
337
- axisLabel: {
338
- ...theme.xAxis.axisLabel,
339
- fontSize: 10,
340
- // Ultra-compact for maximum chart space
341
- formatter: xAxis == null ? void 0 : xAxis.labelFormatter,
342
- // Prevent label overlap - auto-hide overlapping labels
343
- hideOverlap: true,
344
- // Rotate labels slightly if needed for better fit
345
- rotate: 0,
346
- // Show fewer labels when space is tight
347
- interval: "auto"
348
- },
349
- splitLine: {
350
- show: (xAxis == null ? void 0 : xAxis.showGrid) !== false,
351
- lineStyle: { ...theme.xAxis.splitLine.lineStyle, type: theme.xAxis.splitLine.lineStyle.type ?? "solid" }
352
- },
353
- inverse: xAxis == null ? void 0 : xAxis.inverse
354
- } : void 0,
355
- // Y Axis - ultra-compact font sizes for maximum chart space
356
- // In compact mode, hide axis name (shown in tooltip instead)
357
- yAxis: needsGrid ? (Array.isArray(yAxis) ? yAxis : [yAxis || {}]).map((axis, i) => ({
358
- type: (axis == null ? void 0 : axis.type) || "value",
359
- name: compactAxes ? void 0 : axis == null ? void 0 : axis.name,
360
- nameLocation: (axis == null ? void 0 : axis.nameLocation) || "middle",
361
- nameGap: 28,
362
- nameTextStyle: {
363
- ...theme.yAxis.nameTextStyle,
364
- fontSize: 10,
365
- // Ultra-compact for maximum chart space
366
- fontWeight: 500
367
- },
368
- position: (axis == null ? void 0 : axis.position) || (i === 0 ? "left" : "right"),
369
- min: axis == null ? void 0 : axis.min,
370
- max: axis == null ? void 0 : axis.max,
371
- splitNumber: axis == null ? void 0 : axis.splitNumber,
372
- axisLine: {
373
- show: (axis == null ? void 0 : axis.showLine) !== false,
374
- lineStyle: theme.yAxis.axisLine.lineStyle
375
- },
376
- axisTick: {
377
- lineStyle: theme.yAxis.axisTick.lineStyle
378
- },
379
- axisLabel: {
380
- ...theme.yAxis.axisLabel,
381
- fontSize: 10,
382
- // Ultra-compact for maximum chart space
383
- formatter: (axis == null ? void 0 : axis.labelFormatter) ? axis.labelFormatter : (axis == null ? void 0 : axis.unit) ? (v) => `${v}${axis.unit}` : void 0
384
- },
385
- splitLine: {
386
- show: (axis == null ? void 0 : axis.showGrid) !== false,
387
- lineStyle: theme.yAxis.splitLine.lineStyle
388
- },
389
- inverse: axis == null ? void 0 : axis.inverse
390
- })) : void 0,
391
- // Radar (for radar charts) - transparent background for glassmorphic look
392
- radar: isPolar ? {
393
- indicator: ((_g = (_f = series[0]) == null ? void 0 : _f.data) == null ? void 0 : _g.map((d) => {
394
- const point = d;
395
- return {
396
- name: point.label || point.category || String(point.x),
397
- max: 100
398
- };
399
- })) || [],
400
- splitArea: {
401
- show: true,
402
- areaStyle: {
403
- color: ["transparent", "transparent", "transparent", "transparent", "transparent"]
404
- }
405
- },
406
- splitLine: {
407
- lineStyle: {
408
- color: theme.xAxis.splitLine.lineStyle.color,
409
- opacity: 0.4
410
- }
411
- },
412
- axisLine: {
413
- lineStyle: {
414
- color: theme.xAxis.axisLine.lineStyle.color,
415
- opacity: 0.4
416
- }
417
- },
418
- axisName: {
419
- color: theme.xAxis.axisLabel.color,
420
- fontSize: 12
421
- }
422
- } : void 0,
423
- // Data Zoom - inside zoom enabled by default for mouse wheel/pinch
424
- // Use zoom={{ enabled: false }} to disable, or zoom={{ type: 'slider' }} for slider
425
- dataZoom: (zoom == null ? void 0 : zoom.enabled) === false ? void 0 : [
426
- // Inside zoom (mouse wheel / pinch) - ENABLED BY DEFAULT
427
- ...(zoom == null ? void 0 : zoom.type) === "inside" || (zoom == null ? void 0 : zoom.type) === "both" || !(zoom == null ? void 0 : zoom.type) ? [{
428
- type: "inside",
429
- xAxisIndex: (zoom == null ? void 0 : zoom.axis) === "x" || (zoom == null ? void 0 : zoom.axis) === "both" || !(zoom == null ? void 0 : zoom.axis) ? 0 : void 0,
430
- yAxisIndex: (zoom == null ? void 0 : zoom.axis) === "y" || (zoom == null ? void 0 : zoom.axis) === "both" ? 0 : void 0,
431
- start: (zoom == null ? void 0 : zoom.start) ?? 0,
432
- end: (zoom == null ? void 0 : zoom.end) ?? 100,
433
- minSpan: zoom == null ? void 0 : zoom.minSpan,
434
- maxSpan: zoom == null ? void 0 : zoom.maxSpan,
435
- // Smooth zoom animation
436
- throttle: 50
437
- }] : [],
438
- // Slider zoom (only when explicitly requested)
439
- ...(zoom == null ? void 0 : zoom.type) === "slider" || (zoom == null ? void 0 : zoom.type) === "both" ? [{
440
- type: "slider",
441
- show: true,
442
- xAxisIndex: (zoom == null ? void 0 : zoom.axis) === "x" || (zoom == null ? void 0 : zoom.axis) === "both" ? 0 : void 0,
443
- yAxisIndex: (zoom == null ? void 0 : zoom.axis) === "y" || (zoom == null ? void 0 : zoom.axis) === "both" ? 0 : void 0,
444
- start: (zoom == null ? void 0 : zoom.start) ?? 0,
445
- end: (zoom == null ? void 0 : zoom.end) ?? 100,
446
- minSpan: zoom == null ? void 0 : zoom.minSpan,
447
- maxSpan: zoom == null ? void 0 : zoom.maxSpan,
448
- backgroundColor: theme.dataZoom.backgroundColor,
449
- borderColor: theme.dataZoom.borderColor,
450
- fillerColor: theme.dataZoom.fillerColor,
451
- handleStyle: { color: theme.dataZoom.handleColor },
452
- textStyle: theme.dataZoom.textStyle,
453
- height: 25,
454
- bottom: 10
455
- }] : []
456
- ],
457
- // Toolbox (export) – always use custom dropdown for consistent UI
458
- toolbox: ((_h = props.export) == null ? void 0 : _h.enabled) ? (() => {
459
- var _a2;
460
- return {
461
- show: false,
462
- // Hide ECharts toolbox, use custom export button instead
463
- right: 20,
464
- top: 10,
465
- feature: {
466
- dataView: ((_a2 = props.export.formats) == null ? void 0 : _a2.includes("json")) ? {
467
- show: true,
468
- readOnly: true
469
- } : void 0
470
- },
471
- iconStyle: {
472
- borderColor: theme.textStyle.color
473
- }
474
- };
475
- })() : void 0,
476
- // Series
477
- series: transformSeriesToECharts(series, type, theme),
478
- // Animation
479
- animation: !loading,
480
- animationDuration: 300,
481
- animationEasing: "cubicOut"
482
- };
483
- if ((annotations == null ? void 0 : annotations.markLines) && options.series) {
484
- const seriesArray = options.series;
485
- if (seriesArray.length > 0) {
486
- seriesArray[0].markLine = {
487
- silent: true,
488
- symbol: "none",
489
- data: annotations.markLines.data.map((line) => {
490
- var _a2, _b2;
491
- return {
492
- ...line,
493
- lineStyle: {
494
- color: line.color || theme.color[2],
495
- type: ((_a2 = line.lineStyle) == null ? void 0 : _a2.type) || "dashed",
496
- width: ((_b2 = line.lineStyle) == null ? void 0 : _b2.width) || 1
497
- },
498
- label: {
499
- show: !!line.label,
500
- formatter: line.label,
501
- position: "middle",
502
- // center of line so label doesn't overlap y-axis at bottom
503
- distance: 8,
504
- color: theme.textStyle.color,
505
- fontWeight: 600,
506
- fontSize: 11,
507
- textBorderWidth: 0,
508
- textBorderColor: "transparent",
509
- backgroundColor: theme.tooltip.backgroundColor,
510
- borderColor: line.color || theme.color[2],
511
- borderWidth: 1,
512
- borderRadius: 4,
513
- padding: [2, 6]
514
- }
515
- };
516
- })
517
- };
518
- }
519
- }
520
- if ((annotations == null ? void 0 : annotations.markAreas) && options.series) {
521
- const seriesArray = options.series;
522
- const axisLabelColor = ((_j = (_i = theme.xAxis) == null ? void 0 : _i.axisLabel) == null ? void 0 : _j.color) ?? ((_k = theme.textStyle) == null ? void 0 : _k.color) ?? "#94a3b8";
523
- const fadedColor = axisLabelColor.startsWith("rgba") ? axisLabelColor : `${axisLabelColor}cc`;
524
- const defaultLabelStyle = {
525
- show: true,
526
- color: fadedColor,
527
- fontSize: 11,
528
- fontWeight: "500",
529
- textBorderWidth: 0,
530
- textBorderColor: "transparent",
531
- formatter: (params) => {
532
- const name = ((params == null ? void 0 : params.name) ?? "") || (typeof (params == null ? void 0 : params.value) === "string" ? params.value : "");
533
- if (!name) return "";
534
- const icon = name.toLowerCase().includes("eclipse") ? "◐ " : "";
535
- return icon ? `${icon}${name}` : name;
536
- }
537
- };
538
- if (seriesArray.length > 0) {
539
- seriesArray[0].markArea = {
540
- silent: true,
541
- data: annotations.markAreas.data.map((pair) => {
542
- const [start, end] = pair;
543
- return [
544
- { ...start, label: { ...defaultLabelStyle, formatter: defaultLabelStyle.formatter } },
545
- end
546
- ];
547
- }),
548
- itemStyle: annotations.markAreas.itemStyle
549
- };
550
- }
551
- }
552
- if (props.echartsOptions) {
553
- return mergeOptions(options, props.echartsOptions);
554
- }
555
- return options;
261
+ const { type, series, title, subtitle, xAxis, yAxis, tooltip, legend, zoom, annotations, loading, compactAxes = true } = props;
262
+ const showEChartsTitle = title && !hideTitle;
263
+ const isPolar = type === "radar";
264
+ const isPie = type === "pie" || type === "donut";
265
+ const isGauge = type === "gauge";
266
+ const isSankey = type === "sankey";
267
+ const isTreemap = type === "treemap" || type === "sunburst";
268
+ const isGraph = props.echartsOptions?.series && Array.isArray(props.echartsOptions.series) && props.echartsOptions.series.some((s) => s?.type === "graph");
269
+ const is3D = !!(props.echartsOptions?.grid3D || props.echartsOptions?.xAxis3D || props.echartsOptions?.globe || props.echartsOptions?.series && Array.isArray(props.echartsOptions.series) && props.echartsOptions.series.some((s) => {
270
+ const seriesType = s?.type || "";
271
+ return seriesType.includes("3D") || seriesType.includes("3d");
272
+ }));
273
+ const needsGrid = !isPolar && !isPie && !isGauge && !isSankey && !isTreemap && !isGraph && !is3D && !props.hideAxes;
274
+ const hasTitle = hideTitle ? true : !!title;
275
+ const hasSubtitle = hideTitle ? false : !!subtitle;
276
+ const legendPosition = legend?.position ?? "bottom";
277
+ const legendAtTop = legendPosition === "top";
278
+ const legendAtBottom = legendPosition === "bottom";
279
+ const showLegend = legend?.show !== false;
280
+ const options = {
281
+ title: showEChartsTitle ? {
282
+ text: title,
283
+ subtext: subtitle,
284
+ left: "center",
285
+ top: legendAtTop && showLegend ? 35 : 10,
286
+ textStyle: {
287
+ ...theme.title.textStyle,
288
+ fontWeight: theme.title.textStyle.fontWeight ?? "normal"
289
+ },
290
+ subtextStyle: theme.title.subtextStyle
291
+ } : void 0,
292
+ tooltip: tooltip?.enabled !== false ? {
293
+ trigger: tooltip?.trigger || (isPie ? "item" : "axis"),
294
+ axisPointer: {
295
+ type: tooltip?.crosshair === true || tooltip?.crosshair === "both" ? "cross" : "line",
296
+ lineStyle: theme.axisPointer.lineStyle,
297
+ crossStyle: theme.axisPointer.crossStyle,
298
+ label: compactAxes ? {
299
+ show: true,
300
+ backgroundColor: theme.tooltip.backgroundColor,
301
+ borderColor: theme.tooltip.borderColor,
302
+ color: theme.tooltip.textStyle.color,
303
+ fontSize: 11,
304
+ padding: [4, 8],
305
+ formatter: (params) => {
306
+ const axisName = params.axisDimension === "x" ? xAxis?.name : Array.isArray(yAxis) ? yAxis[params.axisIndex]?.name : yAxis?.name;
307
+ const value = typeof params.value === "number" ? params.value.toLocaleString() : params.value;
308
+ return axisName ? `${axisName}: ${value}` : String(value);
309
+ }
310
+ } : void 0
311
+ },
312
+ backgroundColor: theme.tooltip.backgroundColor,
313
+ borderColor: theme.tooltip.borderColor,
314
+ borderWidth: theme.tooltip.borderWidth,
315
+ textStyle: {
316
+ ...theme.tooltip.textStyle,
317
+ fontSize: 14
318
+ },
319
+ extraCssText: theme.tooltip.extraCssText,
320
+ confine: tooltip?.confine ?? true,
321
+ formatter: tooltip?.formatter
322
+ } : void 0,
323
+ legend: showLegend ? {
324
+ show: true,
325
+ type: "scroll",
326
+ orient: legend?.orient || "horizontal",
327
+ left: legend?.position === "left" ? "left" : legend?.position === "right" ? "right" : "center",
328
+ top: legendAtTop ? 4 : void 0,
329
+ bottom: legendAtBottom ? 2 : void 0,
330
+ padding: [2, 6],
331
+ itemGap: 8,
332
+ itemWidth: 12,
333
+ itemHeight: 6,
334
+ textStyle: {
335
+ ...theme.legend.textStyle,
336
+ fontSize: 10
337
+ },
338
+ inactiveColor: theme.legend.inactiveColor,
339
+ selectedMode: legend?.interactive !== false
340
+ } : { show: false },
341
+ grid: needsGrid ? {
342
+ left: compactAxes ? 8 : 40,
343
+ right: Array.isArray(yAxis) && yAxis.length > 1 ? compactAxes ? 8 : 40 : 8,
344
+ top: hasTitle ? hasSubtitle ? 50 : 36 : legendAtTop && showLegend ? 26 : 4,
345
+ bottom: (legendAtBottom && showLegend ? 26 : 16) + (zoom?.type === "slider" || zoom?.type === "both" ? 26 : 0),
346
+ containLabel: true
347
+ } : void 0,
348
+ xAxis: needsGrid ? {
349
+ type: xAxis?.type || "time",
350
+ name: compactAxes ? void 0 : xAxis?.name,
351
+ nameLocation: xAxis?.nameLocation || "middle",
352
+ nameGap: 18,
353
+ nameTextStyle: {
354
+ ...theme.xAxis.nameTextStyle,
355
+ fontSize: 10,
356
+ fontWeight: 500
357
+ },
358
+ min: xAxis?.min,
359
+ max: xAxis?.max,
360
+ axisLine: {
361
+ show: xAxis?.showLine !== false,
362
+ lineStyle: theme.xAxis.axisLine.lineStyle
363
+ },
364
+ axisTick: { lineStyle: theme.xAxis.axisTick.lineStyle },
365
+ axisLabel: {
366
+ ...theme.xAxis.axisLabel,
367
+ fontSize: 10,
368
+ formatter: xAxis?.labelFormatter,
369
+ hideOverlap: true,
370
+ rotate: 0,
371
+ interval: "auto"
372
+ },
373
+ splitLine: {
374
+ show: xAxis?.showGrid !== false,
375
+ lineStyle: {
376
+ ...theme.xAxis.splitLine.lineStyle,
377
+ type: theme.xAxis.splitLine.lineStyle.type ?? "solid"
378
+ }
379
+ },
380
+ inverse: xAxis?.inverse
381
+ } : void 0,
382
+ yAxis: needsGrid ? (Array.isArray(yAxis) ? yAxis : [yAxis || {}]).map((axis, i) => ({
383
+ type: axis?.type || "value",
384
+ name: compactAxes ? void 0 : axis?.name,
385
+ nameLocation: axis?.nameLocation || "middle",
386
+ nameGap: 28,
387
+ nameTextStyle: {
388
+ ...theme.yAxis.nameTextStyle,
389
+ fontSize: 10,
390
+ fontWeight: 500
391
+ },
392
+ position: axis?.position || (i === 0 ? "left" : "right"),
393
+ min: axis?.min,
394
+ max: axis?.max,
395
+ splitNumber: axis?.splitNumber,
396
+ axisLine: {
397
+ show: axis?.showLine !== false,
398
+ lineStyle: theme.yAxis.axisLine.lineStyle
399
+ },
400
+ axisTick: { lineStyle: theme.yAxis.axisTick.lineStyle },
401
+ axisLabel: {
402
+ ...theme.yAxis.axisLabel,
403
+ fontSize: 10,
404
+ formatter: axis?.labelFormatter ? axis.labelFormatter : axis?.unit ? (v) => `${v}${axis.unit}` : void 0
405
+ },
406
+ splitLine: {
407
+ show: axis?.showGrid !== false,
408
+ lineStyle: theme.yAxis.splitLine.lineStyle
409
+ },
410
+ inverse: axis?.inverse
411
+ })) : void 0,
412
+ radar: isPolar ? {
413
+ indicator: series[0]?.data?.map((d) => {
414
+ const point = d;
415
+ return {
416
+ name: point.label || point.category || String(point.x),
417
+ max: 100
418
+ };
419
+ }) || [],
420
+ splitArea: {
421
+ show: true,
422
+ areaStyle: { color: [
423
+ "transparent",
424
+ "transparent",
425
+ "transparent",
426
+ "transparent",
427
+ "transparent"
428
+ ] }
429
+ },
430
+ splitLine: { lineStyle: {
431
+ color: theme.xAxis.splitLine.lineStyle.color,
432
+ opacity: .4
433
+ } },
434
+ axisLine: { lineStyle: {
435
+ color: theme.xAxis.axisLine.lineStyle.color,
436
+ opacity: .4
437
+ } },
438
+ axisName: {
439
+ color: theme.xAxis.axisLabel.color,
440
+ fontSize: 12
441
+ }
442
+ } : void 0,
443
+ dataZoom: zoom?.enabled === false ? void 0 : [...zoom?.type === "inside" || zoom?.type === "both" || !zoom?.type ? [{
444
+ type: "inside",
445
+ xAxisIndex: zoom?.axis === "x" || zoom?.axis === "both" || !zoom?.axis ? 0 : void 0,
446
+ yAxisIndex: zoom?.axis === "y" || zoom?.axis === "both" ? 0 : void 0,
447
+ start: zoom?.start ?? 0,
448
+ end: zoom?.end ?? 100,
449
+ minSpan: zoom?.minSpan,
450
+ maxSpan: zoom?.maxSpan,
451
+ throttle: 50
452
+ }] : [], ...zoom?.type === "slider" || zoom?.type === "both" ? [{
453
+ type: "slider",
454
+ show: true,
455
+ xAxisIndex: zoom?.axis === "x" || zoom?.axis === "both" ? 0 : void 0,
456
+ yAxisIndex: zoom?.axis === "y" || zoom?.axis === "both" ? 0 : void 0,
457
+ start: zoom?.start ?? 0,
458
+ end: zoom?.end ?? 100,
459
+ minSpan: zoom?.minSpan,
460
+ maxSpan: zoom?.maxSpan,
461
+ backgroundColor: theme.dataZoom.backgroundColor,
462
+ borderColor: theme.dataZoom.borderColor,
463
+ fillerColor: theme.dataZoom.fillerColor,
464
+ handleStyle: { color: theme.dataZoom.handleColor },
465
+ textStyle: theme.dataZoom.textStyle,
466
+ height: 25,
467
+ bottom: 10
468
+ }] : []],
469
+ toolbox: props.export?.enabled ? (() => {
470
+ return {
471
+ show: false,
472
+ right: 20,
473
+ top: 10,
474
+ feature: { dataView: props.export.formats?.includes("json") ? {
475
+ show: true,
476
+ readOnly: true
477
+ } : void 0 },
478
+ iconStyle: { borderColor: theme.textStyle.color }
479
+ };
480
+ })() : void 0,
481
+ series: transformSeriesToECharts(series, type, theme),
482
+ animation: !loading,
483
+ animationDuration: 300,
484
+ animationEasing: "cubicOut"
485
+ };
486
+ if (annotations?.markLines && options.series) {
487
+ const seriesArray = options.series;
488
+ if (seriesArray.length > 0) seriesArray[0].markLine = {
489
+ silent: true,
490
+ symbol: "none",
491
+ data: annotations.markLines.data.map((line) => ({
492
+ ...line,
493
+ lineStyle: {
494
+ color: line.color || theme.color[2],
495
+ type: line.lineStyle?.type || "dashed",
496
+ width: line.lineStyle?.width || 1
497
+ },
498
+ label: {
499
+ show: !!line.label,
500
+ formatter: line.label,
501
+ position: "middle",
502
+ distance: 8,
503
+ color: theme.textStyle.color,
504
+ fontWeight: 600,
505
+ fontSize: 11,
506
+ textBorderWidth: 0,
507
+ textBorderColor: "transparent",
508
+ backgroundColor: theme.tooltip.backgroundColor,
509
+ borderColor: line.color || theme.color[2],
510
+ borderWidth: 1,
511
+ borderRadius: 4,
512
+ padding: [2, 6]
513
+ }
514
+ }))
515
+ };
516
+ }
517
+ if (annotations?.markAreas && options.series) {
518
+ const seriesArray = options.series;
519
+ const axisLabelColor = theme.xAxis?.axisLabel?.color ?? theme.textStyle?.color ?? "#94a3b8";
520
+ const defaultLabelStyle = {
521
+ show: true,
522
+ color: axisLabelColor.startsWith("rgba") ? axisLabelColor : `${axisLabelColor}cc`,
523
+ fontSize: 11,
524
+ fontWeight: "500",
525
+ textBorderWidth: 0,
526
+ textBorderColor: "transparent",
527
+ formatter: (params) => {
528
+ const name = (params?.name ?? "") || (typeof params?.value === "string" ? params.value : "");
529
+ if (!name) return "";
530
+ const icon = name.toLowerCase().includes("eclipse") ? "◐ " : "";
531
+ return icon ? `${icon}${name}` : name;
532
+ }
533
+ };
534
+ if (seriesArray.length > 0) seriesArray[0].markArea = {
535
+ silent: true,
536
+ data: annotations.markAreas.data.map((pair) => {
537
+ const [start, end] = pair;
538
+ return [{
539
+ ...start,
540
+ label: {
541
+ ...defaultLabelStyle,
542
+ formatter: defaultLabelStyle.formatter
543
+ }
544
+ }, end];
545
+ }),
546
+ itemStyle: annotations.markAreas.itemStyle
547
+ };
548
+ }
549
+ if (props.echartsOptions) return mergeOptions(options, props.echartsOptions);
550
+ return options;
556
551
  }
557
552
  function mergeOptions(base, custom) {
558
- let mergedSeries = base.series;
559
- if (custom.series) {
560
- const baseSeries = base.series || [];
561
- const customSeries = custom.series;
562
- const allBaseSeriesEmpty = baseSeries.length === 0 || baseSeries.every((s) => {
563
- if (!s) return true;
564
- if (!s.data) return true;
565
- if (Array.isArray(s.data) && s.data.length === 0) return true;
566
- return false;
567
- });
568
- const baseLen = baseSeries.length;
569
- const customLen = customSeries.length;
570
- if (baseLen === 1 && customLen === 1) {
571
- const b = baseSeries[0];
572
- const c = customSeries[0];
573
- if ((b == null ? void 0 : b.type) === "gauge" && (c == null ? void 0 : c.type) === "gauge") {
574
- mergedSeries = customSeries;
575
- } else if (allBaseSeriesEmpty) {
576
- mergedSeries = customSeries;
577
- } else {
578
- mergedSeries = [...baseSeries, ...customSeries];
579
- }
580
- } else if (allBaseSeriesEmpty) {
581
- mergedSeries = customSeries;
582
- } else {
583
- mergedSeries = [...baseSeries, ...customSeries];
584
- }
585
- }
586
- return {
587
- ...base,
588
- ...custom,
589
- series: mergedSeries
590
- };
553
+ let mergedSeries = base.series;
554
+ if (custom.series) {
555
+ const baseSeries = base.series || [];
556
+ const customSeries = custom.series;
557
+ const allBaseSeriesEmpty = baseSeries.length === 0 || baseSeries.every((s) => {
558
+ if (!s) return true;
559
+ if (!s.data) return true;
560
+ if (Array.isArray(s.data) && s.data.length === 0) return true;
561
+ return false;
562
+ });
563
+ const baseLen = baseSeries.length;
564
+ const customLen = customSeries.length;
565
+ if (baseLen === 1 && customLen === 1) {
566
+ const b = baseSeries[0];
567
+ const c = customSeries[0];
568
+ if (b?.type === "gauge" && c?.type === "gauge") mergedSeries = customSeries;
569
+ else if (allBaseSeriesEmpty) mergedSeries = customSeries;
570
+ else mergedSeries = [...baseSeries, ...customSeries];
571
+ } else if (allBaseSeriesEmpty) mergedSeries = customSeries;
572
+ else mergedSeries = [...baseSeries, ...customSeries];
573
+ }
574
+ return {
575
+ ...base,
576
+ ...custom,
577
+ series: mergedSeries
578
+ };
591
579
  }
592
- const AstroChart = memo(forwardRef(
593
- function AstroChart2(props, ref) {
594
- var _a, _b, _c, _d, _e, _f, _g;
595
- const {
596
- width = "100%",
597
- height = 400,
598
- loading = false,
599
- emptyMessage = "No data available",
600
- className = "",
601
- style,
602
- ariaLabel,
603
- onChartReady,
604
- onClick,
605
- onHover,
606
- onZoomChange,
607
- onBrushSelect,
608
- realTime,
609
- series = [],
610
- infoTooltip,
611
- // Header icon/status system
612
- icon,
613
- iconStatus,
614
- statusMessage,
615
- showStatusBadge = false
616
- } = props;
617
- const chartRef = useRef(null);
618
- const { tokens, mode, theme: themeVariant } = useTheme();
619
- const isTransparentTheme = themeVariant === "transparent" || themeVariant === "transparent-bold" || themeVariant === "transparent-minimal";
620
- const isBoldVariant = themeVariant === "transparent-bold";
621
- const isMinimalVariant = themeVariant === "transparent-minimal";
622
- const cardBorderStyle = useCardBorderStyle(tokens, isTransparentTheme);
623
- const glassAccentColor = tokens.colors.accent.primary;
624
- const glassAccentMuted = `${glassAccentColor}66`;
625
- const headingConfig = ((_b = (_a = tokens.layout) == null ? void 0 : _a.card) == null ? void 0 : _b.heading) ?? {
626
- iconSize: 20,
627
- iconSizeCompact: 16,
628
- titleFontSize: "1.125rem",
629
- titleFontSizeChart: "0.875rem",
630
- titleFontWeight: 500,
631
- gap: 8
632
- };
633
- const chartTitleFontSize = headingConfig.titleFontSizeChart ?? headingConfig.titleFontSize;
634
- const theme = useMemo(
635
- () => createAstroEChartsTheme(tokens, mode, themeVariant),
636
- [tokens, mode, themeVariant]
637
- );
638
- const hideEChartsTitle = !!(icon || props.title);
639
- const options = useMemo(
640
- () => buildEChartsOptions(props, theme, hideEChartsTitle),
641
- [props, theme, hideEChartsTitle]
642
- );
643
- const getChart = useCallback(() => {
644
- var _a2;
645
- return (_a2 = chartRef.current) == null ? void 0 : _a2.getEchartsInstance();
646
- }, []);
647
- const getExportFileName = useCallback((extension, includeTimestamp = true) => {
648
- var _a2, _b2;
649
- const context = {
650
- title: props.title,
651
- subtitle: props.subtitle,
652
- seriesNames: series.map((s) => s.name),
653
- chartType: props.type
654
- };
655
- let base;
656
- if ((_a2 = props.export) == null ? void 0 : _a2.getExportFileName) {
657
- base = props.export.getExportFileName(context);
658
- } else if ((_b2 = props.export) == null ? void 0 : _b2.fileName) {
659
- base = props.export.fileName;
660
- } else {
661
- base = derivedExportBaseName(props.title, context.seriesNames, props.type);
662
- }
663
- if (includeTimestamp) {
664
- const d = /* @__PURE__ */ new Date();
665
- const ts = d.toISOString().slice(0, 19).replace(/[-T:]/g, "").replace(/(\d{8})(\d{6})/, "$1-$2");
666
- base = `${base}-${ts}`;
667
- }
668
- if (extension) base = `${base}.${extension.replace(/^\./, "")}`;
669
- return base;
670
- }, [props.title, props.subtitle, props.type, props.export, series]);
671
- useImperativeHandle(ref, () => ({
672
- getChart,
673
- resize: () => {
674
- var _a2;
675
- return (_a2 = getChart()) == null ? void 0 : _a2.resize();
676
- },
677
- getExportFileName,
678
- exportImage: (type = "png", pixelRatio = 2) => {
679
- const chart = getChart();
680
- if (!chart) return void 0;
681
- const imgType = type === "jpg" ? "jpeg" : type;
682
- return chart.getDataURL({
683
- type: imgType,
684
- pixelRatio,
685
- backgroundColor: "transparent"
686
- });
687
- },
688
- exportCSV: () => {
689
- var _a2, _b2;
690
- const rows = [];
691
- const headers = ["Index", ...series.map((s) => s.name)];
692
- rows.push(headers.join(","));
693
- const maxLen = Math.max(...series.map((s) => {
694
- var _a3;
695
- return ((_a3 = s.data) == null ? void 0 : _a3.length) || 0;
696
- }));
697
- for (let i = 0; i < maxLen; i++) {
698
- const row = [i.toString()];
699
- for (const s of series) {
700
- const data = s.data;
701
- const value = data == null ? void 0 : data[i];
702
- if (typeof value === "number") {
703
- row.push(value.toString());
704
- } else if (Array.isArray(value)) {
705
- row.push(((_a2 = value[1]) == null ? void 0 : _a2.toString()) || "");
706
- } else if (value && typeof value === "object") {
707
- const point = value;
708
- row.push(((_b2 = "value" in point ? point.value : point.y) == null ? void 0 : _b2.toString()) || "");
709
- } else {
710
- row.push("");
711
- }
712
- }
713
- rows.push(row.join(","));
714
- }
715
- return rows.join("\n");
716
- },
717
- appendData: (seriesIndex, data) => {
718
- var _a2;
719
- const chart = getChart();
720
- if (!chart) return;
721
- const option = chart.getOption();
722
- const seriesOpt = (_a2 = option.series) == null ? void 0 : _a2[seriesIndex];
723
- if (!seriesOpt) return;
724
- const currentData = [...seriesOpt.data || []];
725
- const newPoint = "time" in data ? [data.time, data.value] : [data.x, data.y];
726
- currentData.push(newPoint);
727
- const maxPoints = (realTime == null ? void 0 : realTime.maxPoints) || 1e3;
728
- while (currentData.length > maxPoints) {
729
- currentData.shift();
730
- }
731
- chart.setOption({
732
- series: [{
733
- data: currentData
734
- }]
735
- }, {
736
- replaceMerge: ["series"]
737
- });
738
- },
739
- clearData: () => {
740
- const chart = getChart();
741
- if (!chart) return;
742
- chart.setOption({
743
- series: series.map(() => ({ data: [] }))
744
- });
745
- },
746
- dispatchAction: (action) => {
747
- var _a2;
748
- (_a2 = getChart()) == null ? void 0 : _a2.dispatchAction(action);
749
- }
750
- }), [getChart, series, realTime]);
751
- const userZoomRef = useRef(null);
752
- const programmaticRef = useRef(false);
753
- const handleEvents = useMemo(() => {
754
- const events = {};
755
- if (onClick) {
756
- events.click = (params) => {
757
- onClick(params);
758
- };
759
- }
760
- if (onHover) {
761
- events.mouseover = (params) => {
762
- onHover(params);
763
- };
764
- }
765
- events.datazoom = (params) => {
766
- var _a2;
767
- if (programmaticRef.current) {
768
- programmaticRef.current = false;
769
- return;
770
- }
771
- const p = params;
772
- const b = (_a2 = p.batch) == null ? void 0 : _a2[0];
773
- const start = (b == null ? void 0 : b.start) ?? p.start ?? 0;
774
- const end = (b == null ? void 0 : b.end) ?? p.end ?? 100;
775
- const startValue = (b == null ? void 0 : b.startValue) ?? p.startValue;
776
- const endValue = (b == null ? void 0 : b.endValue) ?? p.endValue;
777
- const isFullRange = start <= 0 && end >= 100;
778
- userZoomRef.current = isFullRange ? null : { start, end, startValue, endValue };
779
- if (onZoomChange) onZoomChange({ start, end });
780
- };
781
- if (onBrushSelect) {
782
- events.brushselected = (params) => {
783
- onBrushSelect(params);
784
- };
785
- }
786
- return events;
787
- }, [onClick, onHover, onZoomChange, onBrushSelect]);
788
- useEffect(() => {
789
- const saved = userZoomRef.current;
790
- if (!saved) return;
791
- const chart = getChart();
792
- if (!chart || typeof chart.isDisposed === "function" && chart.isDisposed()) return;
793
- const hasAbsolute = saved.startValue !== void 0 && saved.endValue !== void 0;
794
- programmaticRef.current = true;
795
- try {
796
- chart.dispatchAction(hasAbsolute ? { type: "dataZoom", startValue: saved.startValue, endValue: saved.endValue } : { type: "dataZoom", start: saved.start, end: saved.end });
797
- } catch {
798
- programmaticRef.current = false;
799
- }
800
- }, [options, getChart]);
801
- const handleChartReady = useCallback((chart) => {
802
- onChartReady == null ? void 0 : onChartReady(chart);
803
- }, [onChartReady]);
804
- const exportFormats = ((_c = props.export) == null ? void 0 : _c.formats) ?? ["png"];
805
- const useCustomExportDropdown = (_d = props.export) == null ? void 0 : _d.enabled;
806
- const [exportMenuOpen, setExportMenuOpen] = useState(false);
807
- const exportMenuRef = useRef(null);
808
- const [infoTooltipOpen, setInfoTooltipOpen] = useState(false);
809
- const infoTooltipRef = useRef(null);
810
- useEffect(() => {
811
- if (!infoTooltip || !infoTooltipOpen) return;
812
- const handleClickOutside = (e) => {
813
- if (infoTooltipRef.current && !infoTooltipRef.current.contains(e.target)) {
814
- setInfoTooltipOpen(false);
815
- }
816
- };
817
- document.addEventListener("mousedown", handleClickOutside);
818
- return () => document.removeEventListener("mousedown", handleClickOutside);
819
- }, [infoTooltip, infoTooltipOpen]);
820
- useEffect(() => {
821
- if (!useCustomExportDropdown || !exportMenuOpen) return;
822
- const handleClickOutside = (e) => {
823
- if (exportMenuRef.current && !exportMenuRef.current.contains(e.target)) {
824
- setExportMenuOpen(false);
825
- }
826
- };
827
- document.addEventListener("mousedown", handleClickOutside);
828
- return () => document.removeEventListener("mousedown", handleClickOutside);
829
- }, [useCustomExportDropdown, exportMenuOpen]);
830
- const handleExportFormat = useCallback((format) => {
831
- var _a2, _b2, _c2, _d2;
832
- const chart = getChart();
833
- if (format === "csv") {
834
- const rows = [];
835
- const headers = ["Index", ...series.map((s) => s.name)];
836
- rows.push(headers.join(","));
837
- const maxLen = Math.max(...series.map((s) => {
838
- var _a3;
839
- return ((_a3 = s.data) == null ? void 0 : _a3.length) || 0;
840
- }));
841
- for (let i = 0; i < maxLen; i++) {
842
- const row = [i.toString()];
843
- for (const s of series) {
844
- const data = s.data;
845
- const value = data == null ? void 0 : data[i];
846
- if (typeof value === "number") row.push(value.toString());
847
- else if (Array.isArray(value)) row.push(((_a2 = value[1]) == null ? void 0 : _a2.toString()) || "");
848
- else if (value && typeof value === "object") {
849
- const point = value;
850
- row.push(((_b2 = "value" in point ? point.value : point.y) == null ? void 0 : _b2.toString()) || "");
851
- } else row.push("");
852
- }
853
- rows.push(row.join(","));
854
- }
855
- const csv = rows.join("\n");
856
- const filename = getExportFileName("csv", true);
857
- const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
858
- const url = URL.createObjectURL(blob);
859
- const a = document.createElement("a");
860
- a.href = url;
861
- a.download = filename;
862
- a.click();
863
- URL.revokeObjectURL(url);
864
- } else if (chart) {
865
- const imgType = format === "jpeg" ? "jpeg" : format;
866
- const dataUrl = chart.getDataURL({
867
- type: imgType,
868
- pixelRatio: ((_c2 = props.export) == null ? void 0 : _c2.pixelRatio) || 2,
869
- backgroundColor: ((_d2 = props.export) == null ? void 0 : _d2.backgroundColor) || "transparent"
870
- });
871
- if (dataUrl) {
872
- const ext = format === "jpeg" ? "jpg" : format;
873
- const filename = getExportFileName(ext, true);
874
- const a = document.createElement("a");
875
- a.href = dataUrl;
876
- a.download = filename;
877
- a.click();
878
- }
879
- }
880
- setExportMenuOpen(false);
881
- }, [getChart, series, getExportFileName, (_e = props.export) == null ? void 0 : _e.pixelRatio, (_f = props.export) == null ? void 0 : _f.backgroundColor]);
882
- useEffect(() => {
883
- var _a2;
884
- const chart = getChart();
885
- if (!chart) return;
886
- let mounted = true;
887
- const resizeObserver = new ResizeObserver(() => {
888
- if (!mounted) return;
889
- try {
890
- chart.resize();
891
- } catch {
892
- }
893
- });
894
- const container = (_a2 = chartRef.current) == null ? void 0 : _a2.ele;
895
- if (container) {
896
- resizeObserver.observe(container);
897
- }
898
- return () => {
899
- mounted = false;
900
- resizeObserver.disconnect();
901
- };
902
- }, [getChart]);
903
- const needs3DCanvas = useMemo(() => {
904
- const eo = props.echartsOptions;
905
- if (!eo) return false;
906
- if (eo.grid3D || eo.xAxis3D || eo.yAxis3D || eo.zAxis3D || eo.globe || eo.geo3D) return true;
907
- if (Array.isArray(eo.series)) {
908
- return eo.series.some((s) => {
909
- const t = (s == null ? void 0 : s.type) || "";
910
- return t.includes("3D") || t.includes("3d") || t === "scatter3D" || t === "bar3D" || t === "surface" || t === "lines3D";
911
- });
912
- }
913
- return false;
914
- }, [props.echartsOptions]);
915
- const hasSeriesData = series.some((s) => s.data && s.data.length > 0);
916
- const hasEchartsOptionsSeries = ((_g = props.echartsOptions) == null ? void 0 : _g.series) && (Array.isArray(props.echartsOptions.series) ? props.echartsOptions.series.length > 0 : props.echartsOptions.series !== void 0);
917
- const hasData = hasSeriesData || hasEchartsOptionsSeries;
918
- const getStatusColor = (status) => {
919
- var _a2, _b2, _c2, _d2, _e2, _f2;
920
- switch (status) {
921
- case "critical":
922
- return ((_a2 = tokens.colors.status) == null ? void 0 : _a2.critical) || "#ff3838";
923
- case "serious":
924
- return ((_b2 = tokens.colors.status) == null ? void 0 : _b2.serious) || "#ffb302";
925
- case "caution":
926
- return ((_c2 = tokens.colors.status) == null ? void 0 : _c2.caution) || "#fce83a";
927
- case "normal":
928
- return ((_d2 = tokens.colors.status) == null ? void 0 : _d2.normal) || "#56f000";
929
- case "standby":
930
- return ((_e2 = tokens.colors.status) == null ? void 0 : _e2.standby) || "#2dccff";
931
- case "off":
932
- return ((_f2 = tokens.colors.status) == null ? void 0 : _f2.off) || "#a4abb6";
933
- default:
934
- return tokens.colors.text.secondary;
935
- }
936
- };
937
- const hasHeader = !!(icon || props.title);
938
- const useGlassMode = isBoldVariant || isMinimalVariant;
939
- const containerStyle = {
940
- width: typeof width === "number" ? `${width}px` : width,
941
- height: typeof height === "number" ? `${height}px` : height,
942
- borderRadius: tokens.borderRadius.lg,
943
- padding: tokens.spacing.sm,
944
- position: "relative",
945
- overflow: "hidden",
946
- // Glass mode styling for bold/minimal (matching Container)
947
- ...useGlassMode ? {
948
- backgroundColor: "rgba(10, 15, 25, 0.35)",
949
- backdropFilter: "blur(12px)",
950
- WebkitBackdropFilter: "blur(12px)",
951
- border: `1px solid ${glassAccentMuted}`,
952
- borderTop: isBoldVariant ? `2px solid ${glassAccentColor}` : `1px solid ${glassAccentColor}`,
953
- transition: "all 0.3s ease-out, box-shadow 0.3s ease-out"
954
- } : isTransparentTheme ? {
955
- // Regular transparent (glass) theme — match top cards (ISS): transparent + blur
956
- backgroundColor: "transparent",
957
- backdropFilter: "blur(12px)",
958
- WebkitBackdropFilter: "blur(12px)",
959
- ...cardBorderStyle
960
- } : {
961
- // Non-transparent themes — use same border as Container (muted) so chart doesn't stand out
962
- backgroundColor: tokens.colors.background.surface,
963
- border: `1px solid ${tokens.colors.border.muted}`
964
- },
965
- ...style
966
- };
967
- const glassGradient = useGlassMode ? `linear-gradient(135deg, ${glassAccentColor}10 0%, ${glassAccentColor}03 100%)` : void 0;
968
- if (!hasData && !loading) {
969
- return /* @__PURE__ */ jsxs(
970
- "div",
971
- {
972
- className: `astro-chart astro-chart--empty ${className}`,
973
- style: containerStyle,
974
- role: "group",
975
- "aria-roledescription": "chart",
976
- "aria-label": ariaLabel || "Empty chart",
977
- children: [
978
- useGlassMode && glassGradient && /* @__PURE__ */ jsx(
979
- "div",
980
- {
981
- style: {
982
- position: "absolute",
983
- inset: 0,
984
- background: glassGradient,
985
- pointerEvents: "none",
986
- zIndex: 0
987
- }
988
- }
989
- ),
990
- /* @__PURE__ */ jsx("div", { style: {
991
- display: "flex",
992
- alignItems: "center",
993
- justifyContent: "center",
994
- height: "100%",
995
- color: tokens.colors.text.secondary,
996
- fontFamily: tokens.typography.fontFamily.primary,
997
- fontSize: tokens.typography.fontSize.sm,
998
- position: "relative",
999
- zIndex: 1
1000
- }, children: emptyMessage })
1001
- ]
1002
- }
1003
- );
1004
- }
1005
- const exportImageFormats = exportFormats.filter((f) => ["png", "jpeg", "jpg", "svg"].includes(f));
1006
- const hasCsv = exportFormats.includes("csv");
1007
- return /* @__PURE__ */ jsxs(
1008
- "div",
1009
- {
1010
- className: `astro-chart ${className}`,
1011
- style: containerStyle,
1012
- role: "group",
1013
- "aria-roledescription": "chart",
1014
- "aria-label": ariaLabel || props.title || "Chart",
1015
- children: [
1016
- useGlassMode && glassGradient && /* @__PURE__ */ jsx(
1017
- "div",
1018
- {
1019
- style: {
1020
- position: "absolute",
1021
- inset: 0,
1022
- background: glassGradient,
1023
- pointerEvents: "none",
1024
- zIndex: 0
1025
- }
1026
- }
1027
- ),
1028
- hasHeader && isBoldVariant && /* @__PURE__ */ jsxs("div", { style: { position: "relative", zIndex: 1 }, children: [
1029
- /* @__PURE__ */ jsx("div", { style: {
1030
- display: "flex",
1031
- alignItems: "center",
1032
- justifyContent: "space-between",
1033
- padding: `12px ${tokens.spacing.sm} 0`
1034
- }, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: headingConfig.gap }, children: [
1035
- icon && iconStatus && /* @__PURE__ */ jsx(
1036
- HeaderIconWithStatus,
1037
- {
1038
- icon,
1039
- size: headingConfig.iconSize,
1040
- status: iconStatus,
1041
- statusColor: getStatusColor(iconStatus)
1042
- }
1043
- ),
1044
- icon && !iconStatus && /* @__PURE__ */ jsx(
1045
- AstroIcon,
1046
- {
1047
- name: icon,
1048
- size: headingConfig.iconSize,
1049
- color: glassAccentColor
1050
- }
1051
- ),
1052
- props.title && /* @__PURE__ */ jsx("h3", { style: {
1053
- margin: 0,
1054
- fontSize: chartTitleFontSize,
1055
- fontWeight: headingConfig.titleFontWeight,
1056
- color: glassAccentColor,
1057
- letterSpacing: "0.5px",
1058
- textShadow: `0 0 20px ${glassAccentMuted}`
1059
- }, children: props.title })
1060
- ] }) }),
1061
- /* @__PURE__ */ jsxs("div", { style: {
1062
- display: "flex",
1063
- alignItems: "center",
1064
- gap: "8px",
1065
- padding: `10px ${tokens.spacing.sm} 0`,
1066
- marginBottom: tokens.spacing.xs
1067
- }, children: [
1068
- /* @__PURE__ */ jsx("div", { style: {
1069
- flex: 1,
1070
- height: "2px",
1071
- background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 50%, transparent 100%)`,
1072
- boxShadow: `0 0 8px ${glassAccentMuted}`
1073
- } }),
1074
- showStatusBadge && iconStatus && /* @__PURE__ */ jsxs("span", { style: {
1075
- display: "inline-flex",
1076
- alignItems: "center",
1077
- gap: "4px",
1078
- padding: "2px 8px",
1079
- fontSize: "0.625rem",
1080
- // 10px in rem
1081
- fontWeight: 500,
1082
- // AstroUXDS medium (not 600)
1083
- letterSpacing: "0.05em",
1084
- color: getStatusColor(iconStatus),
1085
- backgroundColor: `${getStatusColor(iconStatus)}20`,
1086
- border: `1px solid ${getStatusColor(iconStatus)}40`,
1087
- borderRadius: "3px",
1088
- whiteSpace: "nowrap"
1089
- }, children: [
1090
- STATUS_SHAPES[iconStatus](6, getStatusColor(iconStatus)),
1091
- STATUS_LABELS[iconStatus]
1092
- ] })
1093
- ] })
1094
- ] }),
1095
- hasHeader && isMinimalVariant && /* @__PURE__ */ jsxs("div", { style: {
1096
- display: "flex",
1097
- alignItems: "center",
1098
- padding: `${tokens.spacing.xs} ${tokens.spacing.sm} 0`,
1099
- marginBottom: tokens.spacing.xs,
1100
- position: "relative",
1101
- zIndex: 1
1102
- }, children: [
1103
- icon && iconStatus && /* @__PURE__ */ jsx(
1104
- HeaderIconWithStatus,
1105
- {
1106
- icon,
1107
- size: headingConfig.iconSizeCompact,
1108
- status: iconStatus,
1109
- statusColor: getStatusColor(iconStatus),
1110
- style: { marginRight: tokens.spacing.sm }
1111
- }
1112
- ),
1113
- icon && !iconStatus && /* @__PURE__ */ jsx(
1114
- AstroIcon,
1115
- {
1116
- name: icon,
1117
- size: headingConfig.iconSizeCompact,
1118
- color: glassAccentColor,
1119
- style: { marginRight: tokens.spacing.sm }
1120
- }
1121
- ),
1122
- props.title && /* @__PURE__ */ jsx("h3", { style: {
1123
- margin: 0,
1124
- fontSize: chartTitleFontSize,
1125
- fontWeight: headingConfig.titleFontWeight,
1126
- color: glassAccentColor,
1127
- textShadow: `0 0 16px ${glassAccentMuted}`,
1128
- letterSpacing: "0.02em",
1129
- whiteSpace: "nowrap",
1130
- marginRight: "12px"
1131
- }, children: props.title }),
1132
- /* @__PURE__ */ jsxs("div", { style: {
1133
- flex: 1,
1134
- display: "flex",
1135
- alignItems: "center",
1136
- gap: headingConfig.gap,
1137
- minWidth: 40
1138
- }, children: [
1139
- /* @__PURE__ */ jsx("div", { style: {
1140
- flex: 1,
1141
- height: "1px",
1142
- background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`
1143
- } }),
1144
- showStatusBadge && iconStatus && /* @__PURE__ */ jsxs("span", { style: {
1145
- display: "inline-flex",
1146
- alignItems: "center",
1147
- gap: "3px",
1148
- padding: "1px 6px",
1149
- fontSize: "0.5625rem",
1150
- // 9px in rem (micro)
1151
- fontWeight: 500,
1152
- // AstroUXDS medium (not 600)
1153
- letterSpacing: "0.05em",
1154
- color: getStatusColor(iconStatus),
1155
- backgroundColor: `${getStatusColor(iconStatus)}15`,
1156
- border: `1px solid ${getStatusColor(iconStatus)}30`,
1157
- borderRadius: "2px",
1158
- whiteSpace: "nowrap"
1159
- }, children: [
1160
- STATUS_SHAPES[iconStatus](5, getStatusColor(iconStatus)),
1161
- STATUS_LABELS[iconStatus]
1162
- ] })
1163
- ] })
1164
- ] }),
1165
- hasHeader && isTransparentTheme && !useGlassMode && /* @__PURE__ */ jsxs(
1166
- "div",
1167
- {
1168
- title: statusMessage,
1169
- style: {
1170
- position: "absolute",
1171
- top: 6,
1172
- left: 8,
1173
- display: "flex",
1174
- alignItems: "center",
1175
- gap: headingConfig.gap,
1176
- zIndex: 10
1177
- },
1178
- children: [
1179
- icon && iconStatus && /* @__PURE__ */ jsx(
1180
- HeaderIconWithStatus,
1181
- {
1182
- icon,
1183
- size: headingConfig.iconSizeCompact,
1184
- status: iconStatus,
1185
- statusColor: getStatusColor(iconStatus)
1186
- }
1187
- ),
1188
- icon && !iconStatus && /* @__PURE__ */ jsx(
1189
- AstroIcon,
1190
- {
1191
- name: icon,
1192
- size: headingConfig.iconSizeCompact,
1193
- color: tokens.colors.text.tertiary
1194
- }
1195
- ),
1196
- props.title && /* @__PURE__ */ jsx("span", { style: {
1197
- fontSize: chartTitleFontSize,
1198
- fontWeight: headingConfig.titleFontWeight,
1199
- color: tokens.colors.text.primary
1200
- }, children: props.title })
1201
- ]
1202
- }
1203
- ),
1204
- hasHeader && !isTransparentTheme && /* @__PURE__ */ jsxs(
1205
- "div",
1206
- {
1207
- title: statusMessage,
1208
- style: {
1209
- position: "absolute",
1210
- top: 6,
1211
- left: 8,
1212
- display: "flex",
1213
- alignItems: "center",
1214
- gap: headingConfig.gap,
1215
- zIndex: 10
1216
- },
1217
- children: [
1218
- icon && iconStatus && /* @__PURE__ */ jsx(
1219
- HeaderIconWithStatus,
1220
- {
1221
- icon,
1222
- size: headingConfig.iconSizeCompact,
1223
- status: iconStatus,
1224
- statusColor: getStatusColor(iconStatus)
1225
- }
1226
- ),
1227
- icon && !iconStatus && /* @__PURE__ */ jsx(
1228
- AstroIcon,
1229
- {
1230
- name: icon,
1231
- size: headingConfig.iconSizeCompact,
1232
- color: tokens.colors.text.tertiary
1233
- }
1234
- ),
1235
- props.title && /* @__PURE__ */ jsx("span", { style: {
1236
- fontSize: chartTitleFontSize,
1237
- fontWeight: headingConfig.titleFontWeight,
1238
- color: tokens.colors.text.primary
1239
- }, children: props.title })
1240
- ]
1241
- }
1242
- ),
1243
- /* @__PURE__ */ jsx(
1244
- ReactEChartsCore,
1245
- {
1246
- ref: chartRef,
1247
- echarts,
1248
- option: options,
1249
- opts: {
1250
- renderer: props.renderer ?? (needs3DCanvas ? "canvas" : "svg"),
1251
- ...(props.renderer === "canvas" || needs3DCanvas) && typeof window !== "undefined" && { devicePixelRatio: window.devicePixelRatio || 1 }
1252
- },
1253
- style: { width: "100%", height: "100%" },
1254
- notMerge: true,
1255
- lazyUpdate: true,
1256
- showLoading: loading,
1257
- loadingOption: {
1258
- text: "Loading...",
1259
- color: tokens.colors.accent.primary,
1260
- textColor: tokens.colors.text.primary,
1261
- maskColor: isTransparentTheme ? "rgba(10, 15, 25, 0.6)" : `${tokens.colors.background.surface}80`
1262
- },
1263
- onEvents: handleEvents,
1264
- onChartReady: handleChartReady
1265
- }
1266
- ),
1267
- /* @__PURE__ */ jsxs("div", { style: {
1268
- position: "absolute",
1269
- right: 8,
1270
- top: 6,
1271
- zIndex: 10,
1272
- display: "flex",
1273
- alignItems: "center",
1274
- gap: 4
1275
- }, children: [
1276
- infoTooltip && /* @__PURE__ */ jsxs("div", { ref: infoTooltipRef, style: { position: "relative" }, children: [
1277
- /* @__PURE__ */ jsx(
1278
- "button",
1279
- {
1280
- type: "button",
1281
- onClick: () => setInfoTooltipOpen((v) => !v),
1282
- "aria-label": "Chart information",
1283
- "aria-expanded": infoTooltipOpen,
1284
- style: {
1285
- display: "flex",
1286
- alignItems: "center",
1287
- justifyContent: "center",
1288
- width: 20,
1289
- height: 20,
1290
- padding: 4,
1291
- border: `1px solid ${tokens.colors.border.default}`,
1292
- borderRadius: "50%",
1293
- background: infoTooltipOpen ? tokens.colors.accent.primary : isTransparentTheme ? "rgba(10, 15, 25, 0.5)" : tokens.colors.background.surface,
1294
- color: infoTooltipOpen ? tokens.colors.background.base : tokens.colors.text.secondary,
1295
- cursor: "pointer",
1296
- transition: "all 0.15s ease"
1297
- },
1298
- children: infoTooltip.icon || /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" }) })
1299
- }
1300
- ),
1301
- infoTooltipOpen && /* @__PURE__ */ jsx(
1302
- "div",
1303
- {
1304
- role: "tooltip",
1305
- style: {
1306
- position: "absolute",
1307
- right: 0,
1308
- top: "100%",
1309
- marginTop: 8,
1310
- minWidth: 200,
1311
- maxWidth: infoTooltip.maxWidth || 300,
1312
- padding: "12px 16px",
1313
- background: isTransparentTheme ? "rgba(10, 15, 25, 0.85)" : tokens.colors.background.surface,
1314
- backdropFilter: isTransparentTheme ? "blur(12px)" : void 0,
1315
- border: `1px solid ${tokens.colors.border.default}`,
1316
- borderRadius: tokens.borderRadius.md,
1317
- boxShadow: "0 4px 16px rgba(0,0,0,0.25)",
1318
- color: tokens.colors.text.primary,
1319
- fontFamily: tokens.typography.fontFamily.primary,
1320
- fontSize: tokens.typography.fontSize.sm,
1321
- lineHeight: 1.5,
1322
- zIndex: 20
1323
- },
1324
- children: infoTooltip.content
1325
- }
1326
- )
1327
- ] }),
1328
- useCustomExportDropdown && /* @__PURE__ */ jsxs("div", { ref: exportMenuRef, style: { position: "relative" }, children: [
1329
- /* @__PURE__ */ jsx(
1330
- "button",
1331
- {
1332
- type: "button",
1333
- onClick: () => setExportMenuOpen((v) => !v),
1334
- "aria-haspopup": "true",
1335
- "aria-expanded": exportMenuOpen,
1336
- "aria-label": "Save chart as",
1337
- style: {
1338
- display: "flex",
1339
- alignItems: "center",
1340
- justifyContent: "center",
1341
- width: 20,
1342
- height: 20,
1343
- padding: 4,
1344
- border: `1px solid ${tokens.colors.border.default}`,
1345
- borderRadius: "50%",
1346
- background: isTransparentTheme ? "rgba(10, 15, 25, 0.5)" : tokens.colors.background.surface,
1347
- color: tokens.colors.text.secondary,
1348
- cursor: "pointer",
1349
- transition: "all 0.15s ease"
1350
- },
1351
- children: /* @__PURE__ */ jsxs("svg", { width: "10", height: "10", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
1352
- /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1353
- /* @__PURE__ */ jsx("polyline", { points: "7 10 12 15 17 10" }),
1354
- /* @__PURE__ */ jsx("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
1355
- ] })
1356
- }
1357
- ),
1358
- exportMenuOpen && /* @__PURE__ */ jsxs(
1359
- "div",
1360
- {
1361
- role: "menu",
1362
- style: {
1363
- position: "absolute",
1364
- right: 0,
1365
- top: "100%",
1366
- marginTop: 4,
1367
- minWidth: 120,
1368
- padding: 4,
1369
- background: tokens.colors.background.surface,
1370
- border: `1px solid ${tokens.colors.border.default}`,
1371
- borderRadius: tokens.borderRadius.md,
1372
- boxShadow: "0 4px 12px rgba(0,0,0,0.2)"
1373
- },
1374
- children: [
1375
- exportImageFormats.map((f) => /* @__PURE__ */ jsx(
1376
- "button",
1377
- {
1378
- type: "button",
1379
- role: "menuitem",
1380
- onClick: () => handleExportFormat(f === "jpg" ? "jpeg" : f),
1381
- style: {
1382
- display: "block",
1383
- width: "100%",
1384
- padding: "8px 12px",
1385
- border: "none",
1386
- borderRadius: tokens.borderRadius.sm,
1387
- background: "transparent",
1388
- color: tokens.colors.text.primary,
1389
- fontFamily: tokens.typography.fontFamily.primary,
1390
- fontSize: tokens.typography.fontSize.sm,
1391
- textAlign: "left",
1392
- cursor: "pointer"
1393
- },
1394
- children: f.toUpperCase()
1395
- },
1396
- f
1397
- )),
1398
- hasCsv && /* @__PURE__ */ jsx(
1399
- "button",
1400
- {
1401
- type: "button",
1402
- role: "menuitem",
1403
- onClick: () => handleExportFormat("csv"),
1404
- style: {
1405
- display: "block",
1406
- width: "100%",
1407
- padding: "8px 12px",
1408
- border: "none",
1409
- borderRadius: tokens.borderRadius.sm,
1410
- background: "transparent",
1411
- color: tokens.colors.text.primary,
1412
- fontFamily: tokens.typography.fontFamily.primary,
1413
- fontSize: tokens.typography.fontSize.sm,
1414
- textAlign: "left",
1415
- cursor: "pointer"
1416
- },
1417
- children: "CSV"
1418
- }
1419
- )
1420
- ]
1421
- }
1422
- )
1423
- ] })
1424
- ] })
1425
- ]
1426
- }
1427
- );
1428
- }
1429
- ));
1430
- export {
1431
- AstroChart
1432
- };
1433
- //# sourceMappingURL=AstroChart.js.map
580
+ var AstroChart = memo(forwardRef(function AstroChart(props, ref) {
581
+ const { width = "100%", height = 400, loading = false, emptyMessage = "No data available", className = "", style, ariaLabel, onChartReady, onClick, onHover, onZoomChange, onBrushSelect, realTime, series = [], infoTooltip, icon, iconStatus, statusMessage, showStatusBadge = false } = props;
582
+ const chartRef = useRef(null);
583
+ const { tokens, mode, theme: themeVariant } = useTheme();
584
+ const isTransparentTheme = themeVariant === "transparent" || themeVariant === "transparent-bold" || themeVariant === "transparent-minimal";
585
+ const isBoldVariant = themeVariant === "transparent-bold";
586
+ const isMinimalVariant = themeVariant === "transparent-minimal";
587
+ const cardBorderStyle = useCardBorderStyle(tokens, isTransparentTheme);
588
+ const glassAccentColor = tokens.colors.accent.primary;
589
+ const glassAccentMuted = `${glassAccentColor}66`;
590
+ const headingConfig = tokens.layout?.card?.heading ?? {
591
+ iconSize: 20,
592
+ iconSizeCompact: 16,
593
+ titleFontSize: "1.125rem",
594
+ titleFontSizeChart: "0.875rem",
595
+ titleFontWeight: 500,
596
+ gap: 8
597
+ };
598
+ const chartTitleFontSize = headingConfig.titleFontSizeChart ?? headingConfig.titleFontSize;
599
+ const theme = useMemo(() => createAstroEChartsTheme(tokens, mode, themeVariant), [
600
+ tokens,
601
+ mode,
602
+ themeVariant
603
+ ]);
604
+ const hideEChartsTitle = !!(icon || props.title);
605
+ const options = useMemo(() => buildEChartsOptions(props, theme, hideEChartsTitle), [
606
+ props,
607
+ theme,
608
+ hideEChartsTitle
609
+ ]);
610
+ const getChart = useCallback(() => {
611
+ return chartRef.current?.getEchartsInstance();
612
+ }, []);
613
+ const getExportFileName = useCallback((extension, includeTimestamp = true) => {
614
+ const context = {
615
+ title: props.title,
616
+ subtitle: props.subtitle,
617
+ seriesNames: series.map((s) => s.name),
618
+ chartType: props.type
619
+ };
620
+ let base;
621
+ if (props.export?.getExportFileName) base = props.export.getExportFileName(context);
622
+ else if (props.export?.fileName) base = props.export.fileName;
623
+ else base = derivedExportBaseName(props.title, context.seriesNames, props.type);
624
+ if (includeTimestamp) {
625
+ const ts = (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace(/[-T:]/g, "").replace(/(\d{8})(\d{6})/, "$1-$2");
626
+ base = `${base}-${ts}`;
627
+ }
628
+ if (extension) base = `${base}.${extension.replace(/^\./, "")}`;
629
+ return base;
630
+ }, [
631
+ props.title,
632
+ props.subtitle,
633
+ props.type,
634
+ props.export,
635
+ series
636
+ ]);
637
+ useImperativeHandle(ref, () => ({
638
+ getChart,
639
+ resize: () => getChart()?.resize(),
640
+ getExportFileName,
641
+ exportImage: (type = "png", pixelRatio = 2) => {
642
+ const chart = getChart();
643
+ if (!chart) return void 0;
644
+ const imgType = type === "jpg" ? "jpeg" : type;
645
+ return chart.getDataURL({
646
+ type: imgType,
647
+ pixelRatio,
648
+ backgroundColor: "transparent"
649
+ });
650
+ },
651
+ exportCSV: () => {
652
+ const rows = [];
653
+ const headers = ["Index", ...series.map((s) => s.name)];
654
+ rows.push(headers.join(","));
655
+ const maxLen = Math.max(...series.map((s) => s.data?.length || 0));
656
+ for (let i = 0; i < maxLen; i++) {
657
+ const row = [i.toString()];
658
+ for (const s of series) {
659
+ const value = s.data?.[i];
660
+ if (typeof value === "number") row.push(value.toString());
661
+ else if (Array.isArray(value)) row.push(value[1]?.toString() || "");
662
+ else if (value && typeof value === "object") {
663
+ const point = value;
664
+ row.push(("value" in point ? point.value : point.y)?.toString() || "");
665
+ } else row.push("");
666
+ }
667
+ rows.push(row.join(","));
668
+ }
669
+ return rows.join("\n");
670
+ },
671
+ appendData: (seriesIndex, data) => {
672
+ const chart = getChart();
673
+ if (!chart) return;
674
+ const seriesOpt = chart.getOption().series?.[seriesIndex];
675
+ if (!seriesOpt) return;
676
+ const currentData = [...seriesOpt.data || []];
677
+ const newPoint = "time" in data ? [data.time, data.value] : [data.x, data.y];
678
+ currentData.push(newPoint);
679
+ const maxPoints = realTime?.maxPoints || 1e3;
680
+ while (currentData.length > maxPoints) currentData.shift();
681
+ chart.setOption({ series: [{ data: currentData }] }, { replaceMerge: ["series"] });
682
+ },
683
+ clearData: () => {
684
+ const chart = getChart();
685
+ if (!chart) return;
686
+ chart.setOption({ series: series.map(() => ({ data: [] })) });
687
+ },
688
+ dispatchAction: (action) => {
689
+ getChart()?.dispatchAction(action);
690
+ }
691
+ }), [
692
+ getChart,
693
+ series,
694
+ realTime
695
+ ]);
696
+ const userZoomRef = useRef(null);
697
+ const programmaticRef = useRef(false);
698
+ const handleEvents = useMemo(() => {
699
+ const events = {};
700
+ if (onClick) events.click = (params) => {
701
+ onClick(params);
702
+ };
703
+ if (onHover) events.mouseover = (params) => {
704
+ onHover(params);
705
+ };
706
+ events.datazoom = (params) => {
707
+ if (programmaticRef.current) {
708
+ programmaticRef.current = false;
709
+ return;
710
+ }
711
+ const p = params;
712
+ const b = p.batch?.[0];
713
+ const start = b?.start ?? p.start ?? 0;
714
+ const end = b?.end ?? p.end ?? 100;
715
+ const startValue = b?.startValue ?? p.startValue;
716
+ const endValue = b?.endValue ?? p.endValue;
717
+ userZoomRef.current = start <= 0 && end >= 100 ? null : {
718
+ start,
719
+ end,
720
+ startValue,
721
+ endValue
722
+ };
723
+ if (onZoomChange) onZoomChange({
724
+ start,
725
+ end
726
+ });
727
+ };
728
+ if (onBrushSelect) events.brushselected = (params) => {
729
+ onBrushSelect(params);
730
+ };
731
+ return events;
732
+ }, [
733
+ onClick,
734
+ onHover,
735
+ onZoomChange,
736
+ onBrushSelect
737
+ ]);
738
+ useEffect(() => {
739
+ const saved = userZoomRef.current;
740
+ if (!saved) return;
741
+ const chart = getChart();
742
+ if (!chart || typeof chart.isDisposed === "function" && chart.isDisposed()) return;
743
+ const hasAbsolute = saved.startValue !== void 0 && saved.endValue !== void 0;
744
+ programmaticRef.current = true;
745
+ try {
746
+ chart.dispatchAction(hasAbsolute ? {
747
+ type: "dataZoom",
748
+ startValue: saved.startValue,
749
+ endValue: saved.endValue
750
+ } : {
751
+ type: "dataZoom",
752
+ start: saved.start,
753
+ end: saved.end
754
+ });
755
+ } catch {
756
+ programmaticRef.current = false;
757
+ }
758
+ }, [options, getChart]);
759
+ const handleChartReady = useCallback((chart) => {
760
+ onChartReady?.(chart);
761
+ }, [onChartReady]);
762
+ const exportFormats = props.export?.formats ?? ["png"];
763
+ const useCustomExportDropdown = props.export?.enabled;
764
+ const [exportMenuOpen, setExportMenuOpen] = useState(false);
765
+ const exportMenuRef = useRef(null);
766
+ const [infoTooltipOpen, setInfoTooltipOpen] = useState(false);
767
+ const infoTooltipRef = useRef(null);
768
+ useEffect(() => {
769
+ if (!infoTooltip || !infoTooltipOpen) return;
770
+ const handleClickOutside = (e) => {
771
+ if (infoTooltipRef.current && !infoTooltipRef.current.contains(e.target)) setInfoTooltipOpen(false);
772
+ };
773
+ document.addEventListener("mousedown", handleClickOutside);
774
+ return () => document.removeEventListener("mousedown", handleClickOutside);
775
+ }, [infoTooltip, infoTooltipOpen]);
776
+ useEffect(() => {
777
+ if (!useCustomExportDropdown || !exportMenuOpen) return;
778
+ const handleClickOutside = (e) => {
779
+ if (exportMenuRef.current && !exportMenuRef.current.contains(e.target)) setExportMenuOpen(false);
780
+ };
781
+ document.addEventListener("mousedown", handleClickOutside);
782
+ return () => document.removeEventListener("mousedown", handleClickOutside);
783
+ }, [useCustomExportDropdown, exportMenuOpen]);
784
+ const handleExportFormat = useCallback((format) => {
785
+ const chart = getChart();
786
+ if (format === "csv") {
787
+ const rows = [];
788
+ const headers = ["Index", ...series.map((s) => s.name)];
789
+ rows.push(headers.join(","));
790
+ const maxLen = Math.max(...series.map((s) => s.data?.length || 0));
791
+ for (let i = 0; i < maxLen; i++) {
792
+ const row = [i.toString()];
793
+ for (const s of series) {
794
+ const value = s.data?.[i];
795
+ if (typeof value === "number") row.push(value.toString());
796
+ else if (Array.isArray(value)) row.push(value[1]?.toString() || "");
797
+ else if (value && typeof value === "object") {
798
+ const point = value;
799
+ row.push(("value" in point ? point.value : point.y)?.toString() || "");
800
+ } else row.push("");
801
+ }
802
+ rows.push(row.join(","));
803
+ }
804
+ const csv = rows.join("\n");
805
+ const filename = getExportFileName("csv", true);
806
+ const blob = new Blob([csv], { type: "text/csv;charset=utf-8" });
807
+ const url = URL.createObjectURL(blob);
808
+ const a = document.createElement("a");
809
+ a.href = url;
810
+ a.download = filename;
811
+ a.click();
812
+ URL.revokeObjectURL(url);
813
+ } else if (chart) {
814
+ const imgType = format === "jpeg" ? "jpeg" : format;
815
+ const dataUrl = chart.getDataURL({
816
+ type: imgType,
817
+ pixelRatio: props.export?.pixelRatio || 2,
818
+ backgroundColor: props.export?.backgroundColor || "transparent"
819
+ });
820
+ if (dataUrl) {
821
+ const filename = getExportFileName(format === "jpeg" ? "jpg" : format, true);
822
+ const a = document.createElement("a");
823
+ a.href = dataUrl;
824
+ a.download = filename;
825
+ a.click();
826
+ }
827
+ }
828
+ setExportMenuOpen(false);
829
+ }, [
830
+ getChart,
831
+ series,
832
+ getExportFileName,
833
+ props.export?.pixelRatio,
834
+ props.export?.backgroundColor
835
+ ]);
836
+ useEffect(() => {
837
+ const chart = getChart();
838
+ if (!chart) return;
839
+ let mounted = true;
840
+ const resizeObserver = new ResizeObserver(() => {
841
+ if (!mounted) return;
842
+ try {
843
+ chart.resize();
844
+ } catch {}
845
+ });
846
+ const container = chartRef.current?.ele;
847
+ if (container) resizeObserver.observe(container);
848
+ return () => {
849
+ mounted = false;
850
+ resizeObserver.disconnect();
851
+ };
852
+ }, [getChart]);
853
+ const needs3DCanvas = useMemo(() => {
854
+ const eo = props.echartsOptions;
855
+ if (!eo) return false;
856
+ if (eo.grid3D || eo.xAxis3D || eo.yAxis3D || eo.zAxis3D || eo.globe || eo.geo3D) return true;
857
+ if (Array.isArray(eo.series)) return eo.series.some((s) => {
858
+ const t = s?.type || "";
859
+ return t.includes("3D") || t.includes("3d") || t === "scatter3D" || t === "bar3D" || t === "surface" || t === "lines3D";
860
+ });
861
+ return false;
862
+ }, [props.echartsOptions]);
863
+ const hasSeriesData = series.some((s) => s.data && s.data.length > 0);
864
+ const hasEchartsOptionsSeries = props.echartsOptions?.series && (Array.isArray(props.echartsOptions.series) ? props.echartsOptions.series.length > 0 : props.echartsOptions.series !== void 0);
865
+ const hasData = hasSeriesData || hasEchartsOptionsSeries;
866
+ const getStatusColor = (status) => {
867
+ switch (status) {
868
+ case "critical": return tokens.colors.status?.critical || "#ff3838";
869
+ case "serious": return tokens.colors.status?.serious || "#ffb302";
870
+ case "caution": return tokens.colors.status?.caution || "#fce83a";
871
+ case "normal": return tokens.colors.status?.normal || "#56f000";
872
+ case "standby": return tokens.colors.status?.standby || "#2dccff";
873
+ case "off": return tokens.colors.status?.off || "#a4abb6";
874
+ default: return tokens.colors.text.secondary;
875
+ }
876
+ };
877
+ const hasHeader = !!(icon || props.title);
878
+ const useGlassMode = isBoldVariant || isMinimalVariant;
879
+ const containerStyle = {
880
+ width: typeof width === "number" ? `${width}px` : width,
881
+ height: typeof height === "number" ? `${height}px` : height,
882
+ borderRadius: tokens.borderRadius.lg,
883
+ padding: tokens.spacing.sm,
884
+ position: "relative",
885
+ overflow: "hidden",
886
+ ...useGlassMode ? {
887
+ backgroundColor: "rgba(10, 15, 25, 0.35)",
888
+ backdropFilter: "blur(12px)",
889
+ WebkitBackdropFilter: "blur(12px)",
890
+ border: `1px solid ${glassAccentMuted}`,
891
+ borderTop: isBoldVariant ? `2px solid ${glassAccentColor}` : `1px solid ${glassAccentColor}`,
892
+ transition: "all 0.3s ease-out, box-shadow 0.3s ease-out"
893
+ } : isTransparentTheme ? {
894
+ backgroundColor: "transparent",
895
+ backdropFilter: "blur(12px)",
896
+ WebkitBackdropFilter: "blur(12px)",
897
+ ...cardBorderStyle
898
+ } : {
899
+ backgroundColor: tokens.colors.background.surface,
900
+ border: `1px solid ${tokens.colors.border.muted}`
901
+ },
902
+ ...style
903
+ };
904
+ const glassGradient = useGlassMode ? `linear-gradient(135deg, ${glassAccentColor}10 0%, ${glassAccentColor}03 100%)` : void 0;
905
+ if (!hasData && !loading) return /* @__PURE__ */ jsxs("div", {
906
+ className: `astro-chart astro-chart--empty ${className}`,
907
+ style: containerStyle,
908
+ role: "group",
909
+ "aria-roledescription": "chart",
910
+ "aria-label": ariaLabel || "Empty chart",
911
+ children: [useGlassMode && glassGradient && /* @__PURE__ */ jsx("div", { style: {
912
+ position: "absolute",
913
+ inset: 0,
914
+ background: glassGradient,
915
+ pointerEvents: "none",
916
+ zIndex: 0
917
+ } }), /* @__PURE__ */ jsx("div", {
918
+ style: {
919
+ display: "flex",
920
+ alignItems: "center",
921
+ justifyContent: "center",
922
+ height: "100%",
923
+ color: tokens.colors.text.secondary,
924
+ fontFamily: tokens.typography.fontFamily.primary,
925
+ fontSize: tokens.typography.fontSize.sm,
926
+ position: "relative",
927
+ zIndex: 1
928
+ },
929
+ children: emptyMessage
930
+ })]
931
+ });
932
+ const exportImageFormats = exportFormats.filter((f) => [
933
+ "png",
934
+ "jpeg",
935
+ "jpg",
936
+ "svg"
937
+ ].includes(f));
938
+ const hasCsv = exportFormats.includes("csv");
939
+ return /* @__PURE__ */ jsxs("div", {
940
+ className: `astro-chart ${className}`,
941
+ style: containerStyle,
942
+ role: "group",
943
+ "aria-roledescription": "chart",
944
+ "aria-label": ariaLabel || props.title || "Chart",
945
+ children: [
946
+ useGlassMode && glassGradient && /* @__PURE__ */ jsx("div", { style: {
947
+ position: "absolute",
948
+ inset: 0,
949
+ background: glassGradient,
950
+ pointerEvents: "none",
951
+ zIndex: 0
952
+ } }),
953
+ hasHeader && isBoldVariant && /* @__PURE__ */ jsxs("div", {
954
+ style: {
955
+ position: "relative",
956
+ zIndex: 1
957
+ },
958
+ children: [/* @__PURE__ */ jsx("div", {
959
+ style: {
960
+ display: "flex",
961
+ alignItems: "center",
962
+ justifyContent: "space-between",
963
+ padding: `12px ${tokens.spacing.sm} 0`
964
+ },
965
+ children: /* @__PURE__ */ jsxs("div", {
966
+ style: {
967
+ display: "flex",
968
+ alignItems: "center",
969
+ gap: headingConfig.gap
970
+ },
971
+ children: [
972
+ icon && iconStatus && /* @__PURE__ */ jsx(HeaderIconWithStatus, {
973
+ icon,
974
+ size: headingConfig.iconSize,
975
+ status: iconStatus,
976
+ statusColor: getStatusColor(iconStatus)
977
+ }),
978
+ icon && !iconStatus && /* @__PURE__ */ jsx(AstroIcon, {
979
+ name: icon,
980
+ size: headingConfig.iconSize,
981
+ color: glassAccentColor
982
+ }),
983
+ props.title && /* @__PURE__ */ jsx("h3", {
984
+ style: {
985
+ margin: 0,
986
+ fontSize: chartTitleFontSize,
987
+ fontWeight: headingConfig.titleFontWeight,
988
+ color: glassAccentColor,
989
+ letterSpacing: "0.5px",
990
+ textShadow: `0 0 20px ${glassAccentMuted}`
991
+ },
992
+ children: props.title
993
+ })
994
+ ]
995
+ })
996
+ }), /* @__PURE__ */ jsxs("div", {
997
+ style: {
998
+ display: "flex",
999
+ alignItems: "center",
1000
+ gap: "8px",
1001
+ padding: `10px ${tokens.spacing.sm} 0`,
1002
+ marginBottom: tokens.spacing.xs
1003
+ },
1004
+ children: [/* @__PURE__ */ jsx("div", { style: {
1005
+ flex: 1,
1006
+ height: "2px",
1007
+ background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 50%, transparent 100%)`,
1008
+ boxShadow: `0 0 8px ${glassAccentMuted}`
1009
+ } }), showStatusBadge && iconStatus && /* @__PURE__ */ jsxs("span", {
1010
+ style: {
1011
+ display: "inline-flex",
1012
+ alignItems: "center",
1013
+ gap: "4px",
1014
+ padding: "2px 8px",
1015
+ fontSize: "0.625rem",
1016
+ fontWeight: 500,
1017
+ letterSpacing: "0.05em",
1018
+ color: getStatusColor(iconStatus),
1019
+ backgroundColor: `${getStatusColor(iconStatus)}20`,
1020
+ border: `1px solid ${getStatusColor(iconStatus)}40`,
1021
+ borderRadius: "3px",
1022
+ whiteSpace: "nowrap"
1023
+ },
1024
+ children: [STATUS_SHAPES[iconStatus](6, getStatusColor(iconStatus)), STATUS_LABELS[iconStatus]]
1025
+ })]
1026
+ })]
1027
+ }),
1028
+ hasHeader && isMinimalVariant && /* @__PURE__ */ jsxs("div", {
1029
+ style: {
1030
+ display: "flex",
1031
+ alignItems: "center",
1032
+ padding: `${tokens.spacing.xs} ${tokens.spacing.sm} 0`,
1033
+ marginBottom: tokens.spacing.xs,
1034
+ position: "relative",
1035
+ zIndex: 1
1036
+ },
1037
+ children: [
1038
+ icon && iconStatus && /* @__PURE__ */ jsx(HeaderIconWithStatus, {
1039
+ icon,
1040
+ size: headingConfig.iconSizeCompact,
1041
+ status: iconStatus,
1042
+ statusColor: getStatusColor(iconStatus),
1043
+ style: { marginRight: tokens.spacing.sm }
1044
+ }),
1045
+ icon && !iconStatus && /* @__PURE__ */ jsx(AstroIcon, {
1046
+ name: icon,
1047
+ size: headingConfig.iconSizeCompact,
1048
+ color: glassAccentColor,
1049
+ style: { marginRight: tokens.spacing.sm }
1050
+ }),
1051
+ props.title && /* @__PURE__ */ jsx("h3", {
1052
+ style: {
1053
+ margin: 0,
1054
+ fontSize: chartTitleFontSize,
1055
+ fontWeight: headingConfig.titleFontWeight,
1056
+ color: glassAccentColor,
1057
+ textShadow: `0 0 16px ${glassAccentMuted}`,
1058
+ letterSpacing: "0.02em",
1059
+ whiteSpace: "nowrap",
1060
+ marginRight: "12px"
1061
+ },
1062
+ children: props.title
1063
+ }),
1064
+ /* @__PURE__ */ jsxs("div", {
1065
+ style: {
1066
+ flex: 1,
1067
+ display: "flex",
1068
+ alignItems: "center",
1069
+ gap: headingConfig.gap,
1070
+ minWidth: 40
1071
+ },
1072
+ children: [/* @__PURE__ */ jsx("div", { style: {
1073
+ flex: 1,
1074
+ height: "1px",
1075
+ background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`
1076
+ } }), showStatusBadge && iconStatus && /* @__PURE__ */ jsxs("span", {
1077
+ style: {
1078
+ display: "inline-flex",
1079
+ alignItems: "center",
1080
+ gap: "3px",
1081
+ padding: "1px 6px",
1082
+ fontSize: "0.5625rem",
1083
+ fontWeight: 500,
1084
+ letterSpacing: "0.05em",
1085
+ color: getStatusColor(iconStatus),
1086
+ backgroundColor: `${getStatusColor(iconStatus)}15`,
1087
+ border: `1px solid ${getStatusColor(iconStatus)}30`,
1088
+ borderRadius: "2px",
1089
+ whiteSpace: "nowrap"
1090
+ },
1091
+ children: [STATUS_SHAPES[iconStatus](5, getStatusColor(iconStatus)), STATUS_LABELS[iconStatus]]
1092
+ })]
1093
+ })
1094
+ ]
1095
+ }),
1096
+ hasHeader && isTransparentTheme && !useGlassMode && /* @__PURE__ */ jsxs("div", {
1097
+ title: statusMessage,
1098
+ style: {
1099
+ position: "absolute",
1100
+ top: 6,
1101
+ left: 8,
1102
+ display: "flex",
1103
+ alignItems: "center",
1104
+ gap: headingConfig.gap,
1105
+ zIndex: 10
1106
+ },
1107
+ children: [
1108
+ icon && iconStatus && /* @__PURE__ */ jsx(HeaderIconWithStatus, {
1109
+ icon,
1110
+ size: headingConfig.iconSizeCompact,
1111
+ status: iconStatus,
1112
+ statusColor: getStatusColor(iconStatus)
1113
+ }),
1114
+ icon && !iconStatus && /* @__PURE__ */ jsx(AstroIcon, {
1115
+ name: icon,
1116
+ size: headingConfig.iconSizeCompact,
1117
+ color: tokens.colors.text.tertiary
1118
+ }),
1119
+ props.title && /* @__PURE__ */ jsx("span", {
1120
+ style: {
1121
+ fontSize: chartTitleFontSize,
1122
+ fontWeight: headingConfig.titleFontWeight,
1123
+ color: tokens.colors.text.primary
1124
+ },
1125
+ children: props.title
1126
+ })
1127
+ ]
1128
+ }),
1129
+ hasHeader && !isTransparentTheme && /* @__PURE__ */ jsxs("div", {
1130
+ title: statusMessage,
1131
+ style: {
1132
+ position: "absolute",
1133
+ top: 6,
1134
+ left: 8,
1135
+ display: "flex",
1136
+ alignItems: "center",
1137
+ gap: headingConfig.gap,
1138
+ zIndex: 10
1139
+ },
1140
+ children: [
1141
+ icon && iconStatus && /* @__PURE__ */ jsx(HeaderIconWithStatus, {
1142
+ icon,
1143
+ size: headingConfig.iconSizeCompact,
1144
+ status: iconStatus,
1145
+ statusColor: getStatusColor(iconStatus)
1146
+ }),
1147
+ icon && !iconStatus && /* @__PURE__ */ jsx(AstroIcon, {
1148
+ name: icon,
1149
+ size: headingConfig.iconSizeCompact,
1150
+ color: tokens.colors.text.tertiary
1151
+ }),
1152
+ props.title && /* @__PURE__ */ jsx("span", {
1153
+ style: {
1154
+ fontSize: chartTitleFontSize,
1155
+ fontWeight: headingConfig.titleFontWeight,
1156
+ color: tokens.colors.text.primary
1157
+ },
1158
+ children: props.title
1159
+ })
1160
+ ]
1161
+ }),
1162
+ /* @__PURE__ */ jsx(ReactEChartsCore, {
1163
+ ref: chartRef,
1164
+ echarts,
1165
+ option: options,
1166
+ opts: {
1167
+ renderer: props.renderer ?? (needs3DCanvas ? "canvas" : "svg"),
1168
+ ...(props.renderer === "canvas" || needs3DCanvas) && typeof window !== "undefined" && { devicePixelRatio: window.devicePixelRatio || 1 }
1169
+ },
1170
+ style: {
1171
+ width: "100%",
1172
+ height: "100%"
1173
+ },
1174
+ notMerge: true,
1175
+ lazyUpdate: true,
1176
+ showLoading: loading,
1177
+ loadingOption: {
1178
+ text: "Loading...",
1179
+ color: tokens.colors.accent.primary,
1180
+ textColor: tokens.colors.text.primary,
1181
+ maskColor: isTransparentTheme ? "rgba(10, 15, 25, 0.6)" : tokens.colors.background.overlay
1182
+ },
1183
+ onEvents: handleEvents,
1184
+ onChartReady: handleChartReady
1185
+ }),
1186
+ /* @__PURE__ */ jsxs("div", {
1187
+ style: {
1188
+ position: "absolute",
1189
+ right: 8,
1190
+ top: 6,
1191
+ zIndex: 10,
1192
+ display: "flex",
1193
+ alignItems: "center",
1194
+ gap: 4
1195
+ },
1196
+ children: [infoTooltip && /* @__PURE__ */ jsxs("div", {
1197
+ ref: infoTooltipRef,
1198
+ style: { position: "relative" },
1199
+ children: [/* @__PURE__ */ jsx("button", {
1200
+ type: "button",
1201
+ onClick: () => setInfoTooltipOpen((v) => !v),
1202
+ "aria-label": "Chart information",
1203
+ "aria-expanded": infoTooltipOpen,
1204
+ style: {
1205
+ display: "flex",
1206
+ alignItems: "center",
1207
+ justifyContent: "center",
1208
+ width: 20,
1209
+ height: 20,
1210
+ padding: 4,
1211
+ border: `1px solid ${tokens.colors.border.default}`,
1212
+ borderRadius: "50%",
1213
+ background: infoTooltipOpen ? tokens.colors.accent.primary : isTransparentTheme ? "rgba(10, 15, 25, 0.5)" : tokens.colors.background.surface,
1214
+ color: infoTooltipOpen ? tokens.colors.background.base : tokens.colors.text.secondary,
1215
+ cursor: "pointer",
1216
+ transition: "all 0.15s ease"
1217
+ },
1218
+ children: infoTooltip.icon || /* @__PURE__ */ jsx("svg", {
1219
+ width: "10",
1220
+ height: "10",
1221
+ viewBox: "0 0 24 24",
1222
+ fill: "currentColor",
1223
+ "aria-hidden": "true",
1224
+ children: /* @__PURE__ */ jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z" })
1225
+ })
1226
+ }), infoTooltipOpen && /* @__PURE__ */ jsx("div", {
1227
+ role: "tooltip",
1228
+ style: {
1229
+ position: "absolute",
1230
+ right: 0,
1231
+ top: "100%",
1232
+ marginTop: 8,
1233
+ minWidth: 200,
1234
+ maxWidth: infoTooltip.maxWidth || 300,
1235
+ padding: "12px 16px",
1236
+ background: isTransparentTheme ? "rgba(10, 15, 25, 0.85)" : tokens.colors.background.surface,
1237
+ backdropFilter: isTransparentTheme ? "blur(12px)" : void 0,
1238
+ border: `1px solid ${tokens.colors.border.default}`,
1239
+ borderRadius: tokens.borderRadius.md,
1240
+ boxShadow: "0 4px 16px rgba(0,0,0,0.25)",
1241
+ color: tokens.colors.text.primary,
1242
+ fontFamily: tokens.typography.fontFamily.primary,
1243
+ fontSize: tokens.typography.fontSize.sm,
1244
+ lineHeight: 1.5,
1245
+ zIndex: 20
1246
+ },
1247
+ children: infoTooltip.content
1248
+ })]
1249
+ }), useCustomExportDropdown && /* @__PURE__ */ jsxs("div", {
1250
+ ref: exportMenuRef,
1251
+ style: { position: "relative" },
1252
+ children: [/* @__PURE__ */ jsx("button", {
1253
+ type: "button",
1254
+ onClick: () => setExportMenuOpen((v) => !v),
1255
+ "aria-haspopup": "true",
1256
+ "aria-expanded": exportMenuOpen,
1257
+ "aria-label": "Save chart as",
1258
+ style: {
1259
+ display: "flex",
1260
+ alignItems: "center",
1261
+ justifyContent: "center",
1262
+ width: 20,
1263
+ height: 20,
1264
+ padding: 4,
1265
+ border: `1px solid ${tokens.colors.border.default}`,
1266
+ borderRadius: "50%",
1267
+ background: isTransparentTheme ? "rgba(10, 15, 25, 0.5)" : tokens.colors.background.surface,
1268
+ color: tokens.colors.text.secondary,
1269
+ cursor: "pointer",
1270
+ transition: "all 0.15s ease"
1271
+ },
1272
+ children: /* @__PURE__ */ jsxs("svg", {
1273
+ width: "10",
1274
+ height: "10",
1275
+ viewBox: "0 0 24 24",
1276
+ fill: "none",
1277
+ stroke: "currentColor",
1278
+ strokeWidth: "2",
1279
+ strokeLinecap: "round",
1280
+ strokeLinejoin: "round",
1281
+ "aria-hidden": "true",
1282
+ children: [
1283
+ /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1284
+ /* @__PURE__ */ jsx("polyline", { points: "7 10 12 15 17 10" }),
1285
+ /* @__PURE__ */ jsx("line", {
1286
+ x1: "12",
1287
+ y1: "15",
1288
+ x2: "12",
1289
+ y2: "3"
1290
+ })
1291
+ ]
1292
+ })
1293
+ }), exportMenuOpen && /* @__PURE__ */ jsxs("div", {
1294
+ role: "menu",
1295
+ style: {
1296
+ position: "absolute",
1297
+ right: 0,
1298
+ top: "100%",
1299
+ marginTop: 4,
1300
+ minWidth: 120,
1301
+ padding: 4,
1302
+ background: tokens.colors.background.surface,
1303
+ border: `1px solid ${tokens.colors.border.default}`,
1304
+ borderRadius: tokens.borderRadius.md,
1305
+ boxShadow: "0 4px 12px rgba(0,0,0,0.2)"
1306
+ },
1307
+ children: [exportImageFormats.map((f) => /* @__PURE__ */ jsx("button", {
1308
+ type: "button",
1309
+ role: "menuitem",
1310
+ onClick: () => handleExportFormat(f === "jpg" ? "jpeg" : f),
1311
+ style: {
1312
+ display: "block",
1313
+ width: "100%",
1314
+ padding: "8px 12px",
1315
+ border: "none",
1316
+ borderRadius: tokens.borderRadius.sm,
1317
+ background: "transparent",
1318
+ color: tokens.colors.text.primary,
1319
+ fontFamily: tokens.typography.fontFamily.primary,
1320
+ fontSize: tokens.typography.fontSize.sm,
1321
+ textAlign: "left",
1322
+ cursor: "pointer"
1323
+ },
1324
+ children: f.toUpperCase()
1325
+ }, f)), hasCsv && /* @__PURE__ */ jsx("button", {
1326
+ type: "button",
1327
+ role: "menuitem",
1328
+ onClick: () => handleExportFormat("csv"),
1329
+ style: {
1330
+ display: "block",
1331
+ width: "100%",
1332
+ padding: "8px 12px",
1333
+ border: "none",
1334
+ borderRadius: tokens.borderRadius.sm,
1335
+ background: "transparent",
1336
+ color: tokens.colors.text.primary,
1337
+ fontFamily: tokens.typography.fontFamily.primary,
1338
+ fontSize: tokens.typography.fontSize.sm,
1339
+ textAlign: "left",
1340
+ cursor: "pointer"
1341
+ },
1342
+ children: "CSV"
1343
+ })]
1344
+ })]
1345
+ })]
1346
+ })
1347
+ ]
1348
+ });
1349
+ }));
1350
+ //#endregion
1351
+ export { AstroChart, AstroChart as default };
1352
+
1353
+ //# sourceMappingURL=AstroChart.js.map