@zendir/ui 0.1.8 → 0.1.10

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