@zendir/ui 0.1.8 → 0.1.9

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 (79) hide show
  1. package/dist/index.js +0 -137
  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/index.d.ts +0 -30
  6. package/dist/react/utils/index.js +0 -8
  7. package/dist/react/utils/index.js.map +1 -1
  8. package/dist/react.js +0 -137
  9. package/dist/react.js.map +1 -1
  10. package/package.json +1 -1
  11. package/dist/react/3d/EarthViewer.js +0 -836
  12. package/dist/react/3d/EarthViewer.js.map +0 -1
  13. package/dist/react/3d/SolarSystemViewer.js +0 -372
  14. package/dist/react/3d/SolarSystemViewer.js.map +0 -1
  15. package/dist/react/3d/ZenSpace3D.js +0 -1253
  16. package/dist/react/3d/ZenSpace3D.js.map +0 -1
  17. package/dist/react/3d/ZenSpace3DCesium.js +0 -186
  18. package/dist/react/3d/ZenSpace3DCesium.js.map +0 -1
  19. package/dist/react/3d/ZenSpace3DShaders.js +0 -94
  20. package/dist/react/3d/ZenSpace3DShaders.js.map +0 -1
  21. package/dist/react/3d/ZenSpace3DUtils.js +0 -213
  22. package/dist/react/3d/ZenSpace3DUtils.js.map +0 -1
  23. package/dist/react/3d/threeLoader.js +0 -18
  24. package/dist/react/3d/threeLoader.js.map +0 -1
  25. package/dist/react/cards/AccessCard.js +0 -410
  26. package/dist/react/cards/AccessCard.js.map +0 -1
  27. package/dist/react/cards/OrbitCard.js +0 -372
  28. package/dist/react/cards/OrbitCard.js.map +0 -1
  29. package/dist/react/cards/SpacecraftCard.js +0 -941
  30. package/dist/react/cards/SpacecraftCard.js.map +0 -1
  31. package/dist/react/cards/TelemetryCard.js +0 -742
  32. package/dist/react/cards/TelemetryCard.js.map +0 -1
  33. package/dist/react/cards/TelemetryStreamCard.js +0 -309
  34. package/dist/react/cards/TelemetryStreamCard.js.map +0 -1
  35. package/dist/react/charts/GroundTrackMap.js +0 -1123
  36. package/dist/react/charts/GroundTrackMap.js.map +0 -1
  37. package/dist/react/charts/GroundTrackMapLeaflet.js +0 -571
  38. package/dist/react/charts/GroundTrackMapLeaflet.js.map +0 -1
  39. package/dist/react/charts/groundTrackMapLeafletTiles.js +0 -11
  40. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +0 -1
  41. package/dist/react/charts/groundTrackMapLeafletUtils.js +0 -109
  42. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +0 -1
  43. package/dist/react/charts/unified/AstroChart.js +0 -1405
  44. package/dist/react/charts/unified/AstroChart.js.map +0 -1
  45. package/dist/react/charts/unified/PowerOverviewChart.js +0 -488
  46. package/dist/react/charts/unified/PowerOverviewChart.js.map +0 -1
  47. package/dist/react/charts/unified/domain.js +0 -3168
  48. package/dist/react/charts/unified/domain.js.map +0 -1
  49. package/dist/react/charts/unified/generators.js +0 -518
  50. package/dist/react/charts/unified/generators.js.map +0 -1
  51. package/dist/react/charts/unified/presets.js +0 -999
  52. package/dist/react/charts/unified/presets.js.map +0 -1
  53. package/dist/react/charts/unified/sync.js +0 -219
  54. package/dist/react/charts/unified/sync.js.map +0 -1
  55. package/dist/react/charts/unified/theme.js +0 -562
  56. package/dist/react/charts/unified/theme.js.map +0 -1
  57. package/dist/react/charts/unified/useChartStream.js +0 -226
  58. package/dist/react/charts/unified/useChartStream.js.map +0 -1
  59. package/dist/react/visualizations/EclipseTimerCard.js +0 -250
  60. package/dist/react/visualizations/EclipseTimerCard.js.map +0 -1
  61. package/dist/react/visualizations/LinkBudgetCard.js +0 -444
  62. package/dist/react/visualizations/LinkBudgetCard.js.map +0 -1
  63. package/dist/react/visualizations/NavBallCard.js +0 -243
  64. package/dist/react/visualizations/NavBallCard.js.map +0 -1
  65. package/dist/react/visualizations/PropulsionCard.js +0 -298
  66. package/dist/react/visualizations/PropulsionCard.js.map +0 -1
  67. package/dist/react/visualizations/SensorFootprintCard.js +0 -326
  68. package/dist/react/visualizations/SensorFootprintCard.js.map +0 -1
  69. package/dist/react/visualizations/ThermalHeatmapCard.js +0 -372
  70. package/dist/react/visualizations/ThermalHeatmapCard.js.map +0 -1
  71. package/dist/shaders/atmosphere.frag.js +0 -5
  72. package/dist/shaders/atmosphere.frag.js.map +0 -1
  73. package/dist/shaders/atmosphere.vert.js +0 -5
  74. package/dist/shaders/atmosphere.vert.js.map +0 -1
  75. package/dist/shaders/stars.frag.js +0 -5
  76. package/dist/shaders/stars.frag.js.map +0 -1
  77. package/dist/shaders/stars.vert.js +0 -5
  78. package/dist/shaders/stars.vert.js.map +0 -1
  79. package/dist/style.css +0 -143
@@ -1,941 +0,0 @@
1
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { memo, useMemo, useCallback } from "react";
3
- import { Icon } from "../core/Icon.js";
4
- import { CardHeader } from "../core/CardHeader.js";
5
- import { HeaderIconWithStatus } from "../core/HeaderIconWithStatus.js";
6
- import { useCardBorderStyle } from "../context/DisplaySettingsContext.js";
7
- import { safeAccentText, getStatusColor, classNames, formatCoordinate, formatAltitude, formatVelocity, formatTime, safeNumber, formatPercentage } from "../utils/index.js";
8
- import { useTheme } from "../theme/ThemeProvider.js";
9
- import { useCompactMode } from "../hooks/useCompactMode.js";
10
- function getOrbitTypeColor(orbitType, accentColor) {
11
- const colors = {
12
- LEO: "#3E3CFF",
13
- // Zendir Electric - Low Earth Orbit
14
- MEO: "#3548C0",
15
- // Zendir Prussian Blue Light - Medium Earth Orbit
16
- GEO: "#9D70FF",
17
- // Zendir Purple - Geostationary
18
- HEO: "#1B2DA0",
19
- // Zendir Prussian Blue - Highly Elliptical
20
- SSO: "#B48DFF",
21
- // Zendir Purple Light - Sun-Synchronous
22
- POLAR: "#6B69FF"
23
- // Zendir Electric Light - Polar
24
- };
25
- return colors[(orbitType == null ? void 0 : orbitType.toUpperCase()) ?? ""] ?? accentColor;
26
- }
27
- function deriveHealthStatus(spacecraftStatus, telemetryStatus) {
28
- if (telemetryStatus) {
29
- const validStatuses = ["off", "standby", "normal", "caution", "serious", "critical"];
30
- const normalized = telemetryStatus.toLowerCase();
31
- if (validStatuses.includes(normalized)) {
32
- return normalized;
33
- }
34
- switch (normalized) {
35
- case "healthy":
36
- case "nominal":
37
- case "operational":
38
- return "normal";
39
- case "warning":
40
- case "degraded":
41
- return "caution";
42
- case "failed":
43
- case "error":
44
- return "critical";
45
- case "idle":
46
- return "standby";
47
- }
48
- }
49
- return spacecraftStatus ?? "off";
50
- }
51
- const SpacecraftCard = memo(function SpacecraftCard2({
52
- spacecraft,
53
- telemetry,
54
- showOrbit = false,
55
- showTelemetry = false,
56
- loading = false,
57
- onClick,
58
- className = "",
59
- compact = false,
60
- defaultExpanded = false,
61
- onPinChange
62
- }) {
63
- var _a, _b, _c;
64
- const { tokens, theme, prefersReducedMotion } = useTheme();
65
- const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
66
- const isBoldVariant = theme === "transparent-bold";
67
- const isMinimalVariant = theme === "transparent-minimal";
68
- const useGlassMode = isBoldVariant || isMinimalVariant;
69
- const glassAccentColor = tokens.colors.accent.primary;
70
- const glassAccentMuted = `${glassAccentColor}66`;
71
- const accentTextColor = useMemo(() => safeAccentText(tokens.colors.accent.primary), [tokens.colors.accent.primary]);
72
- const cardBg = isTransparentTheme ? "transparent" : tokens.colors.background.surface;
73
- const cardGlass = isTransparentTheme ? {
74
- backdropFilter: "blur(12px)",
75
- WebkitBackdropFilter: "blur(12px)"
76
- } : {};
77
- const cardBorderStyle = useCardBorderStyle(tokens, isTransparentTheme);
78
- const glassContainerStyle = useGlassMode ? {
79
- backgroundColor: "rgba(10, 15, 25, 0.35)",
80
- backdropFilter: "blur(12px)",
81
- WebkitBackdropFilter: "blur(12px)",
82
- border: `1px solid ${glassAccentMuted}`,
83
- borderTop: isBoldVariant ? `2px solid ${glassAccentColor}` : `1px solid ${glassAccentColor}`
84
- } : {};
85
- const { expanded, isPinned, isHovered: _isHovered, handlers: compactHandlers, transitionDuration: _compactTransition } = useCompactMode({
86
- compact,
87
- defaultExpanded,
88
- onPinChange
89
- });
90
- const animationDuration = prefersReducedMotion ? 0 : 250;
91
- const animationEasing = "cubic-bezier(0.4, 0, 0.2, 1)";
92
- useCallback(() => {
93
- if (onClick && spacecraft) {
94
- onClick(spacecraft);
95
- }
96
- }, [onClick, spacecraft]);
97
- const handleKeyDown = useCallback(
98
- (e) => {
99
- if (onClick && spacecraft && (e.key === "Enter" || e.key === " ")) {
100
- e.preventDefault();
101
- onClick(spacecraft);
102
- }
103
- },
104
- [onClick, spacecraft]
105
- );
106
- const orbitColor = useMemo(
107
- () => getOrbitTypeColor(spacecraft == null ? void 0 : spacecraft.orbitType, tokens.colors.accent.primary),
108
- [spacecraft == null ? void 0 : spacecraft.orbitType, tokens.colors.accent.primary]
109
- );
110
- const healthStatus = useMemo(
111
- () => {
112
- var _a2;
113
- return deriveHealthStatus(spacecraft == null ? void 0 : spacecraft.status, (_a2 = telemetry == null ? void 0 : telemetry.health) == null ? void 0 : _a2.status);
114
- },
115
- [spacecraft == null ? void 0 : spacecraft.status, (_a = telemetry == null ? void 0 : telemetry.health) == null ? void 0 : _a.status]
116
- );
117
- const statusColor = useMemo(() => getStatusColor(healthStatus), [healthStatus]);
118
- const transitionDuration = prefersReducedMotion ? "0ms" : "200ms";
119
- const combinedClickHandler = useCallback(() => {
120
- if (compact) {
121
- compactHandlers.onClick();
122
- }
123
- if (onClick && spacecraft) {
124
- onClick(spacecraft);
125
- }
126
- }, [compact, compactHandlers, onClick, spacecraft]);
127
- if (loading) {
128
- return /* @__PURE__ */ jsxs(
129
- "div",
130
- {
131
- className: classNames("zendir-spacecraft-card", "loading", className),
132
- role: "article",
133
- "aria-busy": "true",
134
- "aria-label": "Loading spacecraft data",
135
- style: {
136
- backgroundColor: cardBg,
137
- ...cardGlass,
138
- ...cardBorderStyle,
139
- borderRadius: tokens.borderRadius.lg,
140
- padding: tokens.spacing.md,
141
- minHeight: 180
142
- },
143
- children: [
144
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 12, marginBottom: 16 }, children: [
145
- /* @__PURE__ */ jsx(
146
- "div",
147
- {
148
- style: {
149
- width: 32,
150
- height: 32,
151
- borderRadius: "50%",
152
- backgroundColor: "rgba(255,255,255,0.1)",
153
- animation: "pulse 1.5s ease-in-out infinite"
154
- }
155
- }
156
- ),
157
- /* @__PURE__ */ jsx("div", { style: { flex: 1 }, children: /* @__PURE__ */ jsx(
158
- "div",
159
- {
160
- style: {
161
- height: 16,
162
- width: "60%",
163
- backgroundColor: "rgba(255,255,255,0.1)",
164
- borderRadius: 4,
165
- animation: "pulse 1.5s ease-in-out infinite"
166
- }
167
- }
168
- ) })
169
- ] }),
170
- /* @__PURE__ */ jsx(
171
- "div",
172
- {
173
- style: {
174
- display: "grid",
175
- gridTemplateColumns: "repeat(2, 1fr)",
176
- gap: 12
177
- },
178
- children: [1, 2, 3, 4].map((i) => /* @__PURE__ */ jsxs("div", { children: [
179
- /* @__PURE__ */ jsx(
180
- "div",
181
- {
182
- style: {
183
- height: 10,
184
- width: "40%",
185
- backgroundColor: "rgba(255,255,255,0.08)",
186
- borderRadius: 2,
187
- marginBottom: 4
188
- }
189
- }
190
- ),
191
- /* @__PURE__ */ jsx(
192
- "div",
193
- {
194
- style: {
195
- height: 14,
196
- width: "70%",
197
- backgroundColor: "rgba(255,255,255,0.1)",
198
- borderRadius: 2
199
- }
200
- }
201
- )
202
- ] }, i))
203
- }
204
- ),
205
- /* @__PURE__ */ jsx("style", { children: `
206
- @keyframes pulse {
207
- 0%, 100% { opacity: 1; }
208
- 50% { opacity: 0.5; }
209
- }
210
- ` })
211
- ]
212
- }
213
- );
214
- }
215
- if (!spacecraft) {
216
- return /* @__PURE__ */ jsxs(
217
- "div",
218
- {
219
- className: classNames("zendir-spacecraft-card", "empty", className),
220
- role: "article",
221
- "aria-label": "No spacecraft data",
222
- style: {
223
- backgroundColor: cardBg,
224
- ...cardGlass,
225
- ...tokens.colors.border.cardStyleDashed ?? {},
226
- borderRadius: tokens.borderRadius.lg,
227
- padding: tokens.spacing.lg,
228
- textAlign: "center",
229
- color: tokens.colors.text.tertiary
230
- },
231
- children: [
232
- /* @__PURE__ */ jsx(
233
- "svg",
234
- {
235
- width: "32",
236
- height: "32",
237
- viewBox: "0 0 24 24",
238
- fill: "none",
239
- stroke: "currentColor",
240
- strokeWidth: "1.5",
241
- style: { marginBottom: 8, opacity: 0.5 },
242
- children: /* @__PURE__ */ jsx("path", { d: "M13 2L3 14h9l-1 8 10-12h-9l1-8z" })
243
- }
244
- ),
245
- /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: tokens.typography.body[2].fontSize }, children: "No spacecraft data available" })
246
- ]
247
- }
248
- );
249
- }
250
- const CompactMetric = ({
251
- icon,
252
- label,
253
- value,
254
- color
255
- }) => /* @__PURE__ */ jsxs("div", { style: {
256
- display: "flex",
257
- alignItems: "center",
258
- gap: 3,
259
- padding: `2px 0`
260
- }, children: [
261
- /* @__PURE__ */ jsx(Icon, { name: icon, size: 12, color: color ?? tokens.colors.text.secondary }),
262
- /* @__PURE__ */ jsx("span", { style: {
263
- fontSize: tokens.typography.fontSize.micro,
264
- // 0.5625rem / 9px (AstroUXDS micro)
265
- fontWeight: tokens.typography.fontWeight.medium,
266
- fontFamily: tokens.typography.fontFamily.primary,
267
- // Roboto - Astro UX compliant
268
- color: tokens.colors.text.tertiary,
269
- textTransform: "uppercase",
270
- minWidth: 8
271
- }, children: label.charAt(0) }),
272
- /* @__PURE__ */ jsx("span", { style: {
273
- fontVariantNumeric: "tabular-nums",
274
- fontFamily: tokens.typography.fontFamily.mono,
275
- fontSize: tokens.typography.fontSize.xs,
276
- color: color ?? tokens.colors.text.primary,
277
- fontWeight: tokens.typography.fontWeight.medium
278
- }, children: value })
279
- ] });
280
- const renderCompactContent = () => {
281
- var _a2;
282
- const power = ((_a2 = telemetry == null ? void 0 : telemetry.subsystems) == null ? void 0 : _a2.power) ?? (telemetry == null ? void 0 : telemetry.power);
283
- const batteryLevel = power == null ? void 0 : power.batteryLevel;
284
- const batteryStatusLocal = batteryLevel !== void 0 ? batteryLevel > 50 ? "normal" : batteryLevel > 20 ? "caution" : "critical" : "off";
285
- const statusColor2 = getStatusColor(healthStatus);
286
- return /* @__PURE__ */ jsxs(Fragment, { children: [
287
- /* @__PURE__ */ jsxs("div", { style: {
288
- display: "flex",
289
- alignItems: "center",
290
- justifyContent: "space-between",
291
- marginBottom: tokens.spacing.xs,
292
- paddingBottom: tokens.spacing.xs,
293
- borderBottom: useGlassMode ? "none" : `1px solid ${tokens.colors.border.muted}`,
294
- position: "relative",
295
- zIndex: 1
296
- }, children: [
297
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.xs, flex: 1, minWidth: 0 }, children: [
298
- /* @__PURE__ */ jsx(
299
- HeaderIconWithStatus,
300
- {
301
- icon: "satellite-transmit",
302
- size: 18,
303
- status: healthStatus,
304
- statusColor: statusColor2
305
- }
306
- ),
307
- /* @__PURE__ */ jsx("span", { style: {
308
- fontWeight: tokens.typography.fontWeight.semibold,
309
- fontSize: tokens.typography.fontSize.sm,
310
- fontFamily: tokens.typography.fontFamily.primary,
311
- color: useGlassMode ? glassAccentColor : void 0,
312
- textShadow: useGlassMode ? `0 0 16px ${glassAccentMuted}` : void 0,
313
- whiteSpace: "nowrap",
314
- overflow: "hidden",
315
- textOverflow: "ellipsis"
316
- }, children: (spacecraft.name ?? spacecraft.id ?? "Unknown").split(" ")[0] }),
317
- useGlassMode && /* @__PURE__ */ jsx("div", { style: {
318
- flex: 1,
319
- height: isBoldVariant ? "2px" : "1px",
320
- minWidth: 20,
321
- background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`,
322
- boxShadow: isBoldVariant ? `0 0 8px ${glassAccentMuted}` : void 0
323
- } })
324
- ] }),
325
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.xs, flexShrink: 0 }, children: [
326
- /* @__PURE__ */ jsx(
327
- "span",
328
- {
329
- style: {
330
- backgroundColor: `${orbitColor}20`,
331
- color: orbitColor,
332
- padding: `1px 6px`,
333
- borderRadius: tokens.borderRadius.sm,
334
- fontSize: tokens.typography.fontSize.xxs,
335
- // 0.625rem / 10px (AstroUXDS compact)
336
- fontWeight: tokens.typography.fontWeight.medium,
337
- fontFamily: tokens.typography.fontFamily.primary
338
- },
339
- children: spacecraft.orbitType ?? "—"
340
- }
341
- ),
342
- isPinned && /* @__PURE__ */ jsx(Icon, { name: "lock", size: 10, color: tokens.colors.accent.primary })
343
- ] })
344
- ] }),
345
- /* @__PURE__ */ jsxs("div", { style: {
346
- display: "grid",
347
- gridTemplateColumns: "repeat(3, 1fr)",
348
- gap: `${tokens.spacing.xs} ${tokens.spacing.sm}`
349
- }, children: [
350
- /* @__PURE__ */ jsx(
351
- CompactMetric,
352
- {
353
- icon: "location",
354
- label: "Latitude",
355
- value: formatCoordinate(spacecraft.latitude, "lat")
356
- }
357
- ),
358
- /* @__PURE__ */ jsx(
359
- CompactMetric,
360
- {
361
- icon: "location",
362
- label: "Longitude",
363
- value: formatCoordinate(spacecraft.longitude, "lon")
364
- }
365
- ),
366
- /* @__PURE__ */ jsx(
367
- CompactMetric,
368
- {
369
- icon: "orbit",
370
- label: "Altitude",
371
- value: formatAltitude(spacecraft.altitude),
372
- color: orbitColor
373
- }
374
- ),
375
- spacecraft.velocity !== void 0 && /* @__PURE__ */ jsx(
376
- CompactMetric,
377
- {
378
- icon: "rocket",
379
- label: "Velocity",
380
- value: formatVelocity(spacecraft.velocity)
381
- }
382
- ),
383
- batteryLevel !== void 0 && /* @__PURE__ */ jsx(
384
- CompactMetric,
385
- {
386
- icon: "battery",
387
- label: "Battery",
388
- value: formatPercentage(batteryLevel),
389
- color: getStatusColor(batteryStatusLocal)
390
- }
391
- ),
392
- spacecraft.inclination !== void 0 && /* @__PURE__ */ jsx(
393
- CompactMetric,
394
- {
395
- icon: "orbit",
396
- label: "Inclination",
397
- value: `${safeNumber(spacecraft.inclination, 1)}°`
398
- }
399
- )
400
- ] })
401
- ] });
402
- };
403
- if (compact) {
404
- return /* @__PURE__ */ jsxs(
405
- "article",
406
- {
407
- className: classNames("zendir-spacecraft-card", "compact", expanded ? "expanded" : "", className),
408
- ...compactHandlers,
409
- "aria-label": `Spacecraft: ${spacecraft.name ?? spacecraft.id}${expanded ? "" : " (compact)"}`,
410
- style: {
411
- position: "relative",
412
- overflow: "hidden",
413
- // Use glass container style for bold/minimal themes
414
- ...useGlassMode ? glassContainerStyle : {
415
- backgroundColor: cardBg,
416
- ...cardGlass,
417
- ...cardBorderStyle
418
- },
419
- borderRadius: tokens.borderRadius.lg,
420
- padding: expanded ? tokens.spacing.md : tokens.spacing.sm,
421
- fontFamily: tokens.typography.fontFamily.primary,
422
- color: tokens.colors.text.primary,
423
- fontSize: expanded ? tokens.typography.fontSize.base : tokens.typography.fontSize.sm,
424
- cursor: "pointer",
425
- transition: `all ${animationDuration}ms ${animationEasing}`,
426
- boxShadow: expanded ? `0 12px 40px rgba(0,0,0,0.4), 0 0 0 1px ${orbitColor}30` : "none",
427
- zIndex: expanded ? 50 : 1
428
- },
429
- children: [
430
- useGlassMode && /* @__PURE__ */ jsx(
431
- "div",
432
- {
433
- style: {
434
- position: "absolute",
435
- inset: 0,
436
- background: "linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)",
437
- pointerEvents: "none",
438
- zIndex: 0
439
- }
440
- }
441
- ),
442
- expanded ? (
443
- // Full expanded content
444
- /* @__PURE__ */ jsxs(Fragment, { children: [
445
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.sm, marginBottom: tokens.spacing.md }, children: [
446
- /* @__PURE__ */ jsx(
447
- HeaderIconWithStatus,
448
- {
449
- icon: "satellite-transmit",
450
- size: 24,
451
- status: healthStatus
452
- }
453
- ),
454
- /* @__PURE__ */ jsxs("div", { style: { flex: 1, minWidth: 0 }, children: [
455
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
456
- /* @__PURE__ */ jsx(
457
- "h3",
458
- {
459
- style: {
460
- margin: 0,
461
- fontSize: tokens.typography.fontSize.md,
462
- fontWeight: tokens.typography.fontWeight.semibold,
463
- lineHeight: 1.2
464
- },
465
- children: spacecraft.name ?? spacecraft.id
466
- }
467
- ),
468
- isPinned && /* @__PURE__ */ jsx(Icon, { name: "lock", size: 12, color: tokens.colors.accent.primary })
469
- ] }),
470
- spacecraft.id && spacecraft.name && /* @__PURE__ */ jsx(
471
- "span",
472
- {
473
- style: {
474
- fontSize: tokens.typography.fontSize.xs,
475
- color: tokens.colors.text.tertiary
476
- },
477
- children: spacecraft.id
478
- }
479
- )
480
- ] }),
481
- /* @__PURE__ */ jsx(
482
- "span",
483
- {
484
- style: {
485
- backgroundColor: `${orbitColor}20`,
486
- color: orbitColor,
487
- padding: `4px 8px`,
488
- borderRadius: tokens.borderRadius.sm,
489
- fontSize: tokens.typography.fontSize.xs,
490
- fontWeight: tokens.typography.fontWeight.medium,
491
- flexShrink: 0
492
- },
493
- children: spacecraft.orbitType ?? "Unknown"
494
- }
495
- )
496
- ] }),
497
- /* @__PURE__ */ jsxs(
498
- "div",
499
- {
500
- style: {
501
- display: "grid",
502
- gridTemplateColumns: "repeat(2, 1fr)",
503
- gap: tokens.spacing.sm,
504
- marginBottom: tokens.spacing.md
505
- },
506
- children: [
507
- /* @__PURE__ */ jsxs("div", { children: [
508
- /* @__PURE__ */ jsx(
509
- "span",
510
- {
511
- style: {
512
- display: "block",
513
- fontSize: tokens.typography.fontSize.xs,
514
- color: tokens.colors.text.tertiary,
515
- marginBottom: 2
516
- },
517
- children: "Latitude"
518
- }
519
- ),
520
- /* @__PURE__ */ jsx(
521
- "span",
522
- {
523
- style: {
524
- fontSize: tokens.typography.fontSize.md,
525
- fontWeight: tokens.typography.fontWeight.medium,
526
- fontVariantNumeric: "tabular-nums",
527
- fontFamily: tokens.typography.fontFamily.mono
528
- },
529
- children: formatCoordinate(spacecraft.latitude, "lat")
530
- }
531
- )
532
- ] }),
533
- /* @__PURE__ */ jsxs("div", { children: [
534
- /* @__PURE__ */ jsx(
535
- "span",
536
- {
537
- style: {
538
- display: "block",
539
- fontSize: tokens.typography.fontSize.xs,
540
- color: tokens.colors.text.tertiary,
541
- marginBottom: 2
542
- },
543
- children: "Longitude"
544
- }
545
- ),
546
- /* @__PURE__ */ jsx(
547
- "span",
548
- {
549
- style: {
550
- fontSize: tokens.typography.fontSize.md,
551
- fontWeight: tokens.typography.fontWeight.medium,
552
- fontVariantNumeric: "tabular-nums",
553
- fontFamily: tokens.typography.fontFamily.mono
554
- },
555
- children: formatCoordinate(spacecraft.longitude, "lon")
556
- }
557
- )
558
- ] }),
559
- /* @__PURE__ */ jsxs("div", { children: [
560
- /* @__PURE__ */ jsx(
561
- "span",
562
- {
563
- style: {
564
- display: "block",
565
- fontSize: tokens.typography.fontSize.xs,
566
- color: tokens.colors.text.tertiary,
567
- marginBottom: 2
568
- },
569
- children: "Altitude"
570
- }
571
- ),
572
- /* @__PURE__ */ jsx(
573
- "span",
574
- {
575
- style: {
576
- fontSize: tokens.typography.fontSize.md,
577
- fontWeight: tokens.typography.fontWeight.medium,
578
- fontVariantNumeric: "tabular-nums",
579
- fontFamily: tokens.typography.fontFamily.mono,
580
- color: orbitColor
581
- },
582
- children: formatAltitude(spacecraft.altitude)
583
- }
584
- )
585
- ] }),
586
- /* @__PURE__ */ jsxs("div", { children: [
587
- /* @__PURE__ */ jsx(
588
- "span",
589
- {
590
- style: {
591
- display: "block",
592
- fontSize: tokens.typography.fontSize.xs,
593
- color: tokens.colors.text.tertiary,
594
- marginBottom: 2
595
- },
596
- children: "Velocity"
597
- }
598
- ),
599
- /* @__PURE__ */ jsx(
600
- "span",
601
- {
602
- style: {
603
- fontSize: tokens.typography.fontSize.md,
604
- fontWeight: tokens.typography.fontWeight.medium,
605
- fontVariantNumeric: "tabular-nums",
606
- fontFamily: tokens.typography.fontFamily.mono
607
- },
608
- children: formatVelocity(spacecraft.velocity)
609
- }
610
- )
611
- ] })
612
- ]
613
- }
614
- ),
615
- spacecraft.timestamp && /* @__PURE__ */ jsx(
616
- "time",
617
- {
618
- dateTime: spacecraft.timestamp,
619
- style: {
620
- display: "block",
621
- fontSize: tokens.typography.fontSize.xs,
622
- color: tokens.colors.text.tertiary,
623
- fontVariantNumeric: "tabular-nums"
624
- },
625
- children: formatTime(spacecraft.timestamp)
626
- }
627
- )
628
- ] })
629
- ) : (
630
- // Compact content
631
- renderCompactContent()
632
- )
633
- ]
634
- }
635
- );
636
- }
637
- return /* @__PURE__ */ jsxs(
638
- "article",
639
- {
640
- className: classNames("zendir-spacecraft-card", compact ? "expanded" : "", className),
641
- onClick: compact || onClick ? combinedClickHandler : void 0,
642
- onKeyDown: onClick ? handleKeyDown : compactHandlers.onKeyDown,
643
- tabIndex: onClick || compact ? 0 : void 0,
644
- role: compact ? compactHandlers.role : "article",
645
- "aria-expanded": compact ? compactHandlers["aria-expanded"] : void 0,
646
- "aria-label": `Spacecraft: ${spacecraft.name ?? spacecraft.id}`,
647
- style: {
648
- position: "relative",
649
- overflow: "hidden",
650
- ...useGlassMode ? glassContainerStyle : {
651
- backgroundColor: cardBg,
652
- ...cardGlass,
653
- ...cardBorderStyle
654
- },
655
- borderRadius: tokens.borderRadius.lg,
656
- padding: tokens.spacing.md,
657
- fontFamily: tokens.typography.fontFamily.primary,
658
- color: tokens.colors.text.primary,
659
- cursor: onClick || compact ? "pointer" : "default",
660
- transition: `all ${transitionDuration} ease-out`,
661
- outline: "none"
662
- },
663
- onMouseEnter: (e) => {
664
- if (compact) compactHandlers.onMouseEnter();
665
- if (onClick) {
666
- e.currentTarget.style.borderColor = tokens.colors.border.focus;
667
- e.currentTarget.style.boxShadow = tokens.shadows.md;
668
- e.currentTarget.style.transform = prefersReducedMotion ? "none" : "translateY(-2px)";
669
- }
670
- },
671
- onMouseLeave: (e) => {
672
- if (compact) compactHandlers.onMouseLeave();
673
- if (onClick) {
674
- e.currentTarget.style.borderColor = tokens.colors.border.muted;
675
- e.currentTarget.style.boxShadow = "none";
676
- e.currentTarget.style.transform = "none";
677
- }
678
- },
679
- onFocus: (e) => {
680
- e.currentTarget.style.outline = `2px solid ${tokens.colors.border.focus}`;
681
- e.currentTarget.style.outlineOffset = "2px";
682
- },
683
- onBlur: (e) => {
684
- e.currentTarget.style.outline = "none";
685
- },
686
- children: [
687
- useGlassMode && /* @__PURE__ */ jsx(
688
- "div",
689
- {
690
- style: {
691
- position: "absolute",
692
- inset: 0,
693
- background: "linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)",
694
- pointerEvents: "none",
695
- zIndex: 0
696
- }
697
- }
698
- ),
699
- /* @__PURE__ */ jsx(
700
- CardHeader,
701
- {
702
- icon: "satellite-transmit",
703
- title: spacecraft.name ?? spacecraft.id ?? "Unknown",
704
- subtitle: spacecraft.id && spacecraft.name ? spacecraft.id : void 0,
705
- status: healthStatus,
706
- badge: spacecraft.orbitType ?? "Unknown",
707
- badgeColor: orbitColor,
708
- isPinned: compact && isPinned
709
- }
710
- ),
711
- /* @__PURE__ */ jsxs(
712
- "div",
713
- {
714
- style: {
715
- display: "grid",
716
- gridTemplateColumns: "repeat(2, 1fr)",
717
- gap: tokens.spacing.sm
718
- },
719
- children: [
720
- /* @__PURE__ */ jsx(DataCell, { label: "Latitude", value: formatCoordinate(spacecraft.latitude, "lat"), tokens, highlightColor: accentTextColor }),
721
- /* @__PURE__ */ jsx(DataCell, { label: "Longitude", value: formatCoordinate(spacecraft.longitude, "lon"), tokens, highlightColor: accentTextColor }),
722
- /* @__PURE__ */ jsx(DataCell, { label: "Altitude", value: formatAltitude(spacecraft.altitude), highlight: true, tokens, highlightColor: accentTextColor }),
723
- /* @__PURE__ */ jsx(DataCell, { label: "Velocity", value: formatVelocity(spacecraft.velocity), tokens, highlightColor: accentTextColor })
724
- ]
725
- }
726
- ),
727
- showOrbit && spacecraft.inclination !== void 0 && /* @__PURE__ */ jsx(
728
- "div",
729
- {
730
- style: {
731
- marginTop: tokens.spacing.md,
732
- paddingTop: tokens.spacing.md,
733
- borderTop: `1px solid ${tokens.colors.border.muted}`
734
- },
735
- children: /* @__PURE__ */ jsx(
736
- DataCell,
737
- {
738
- label: "Inclination",
739
- value: `${safeNumber(spacecraft.inclination, 1)}°`,
740
- inline: true,
741
- tokens
742
- }
743
- )
744
- }
745
- ),
746
- showTelemetry && telemetry && /* @__PURE__ */ jsxs(
747
- "div",
748
- {
749
- style: {
750
- marginTop: tokens.spacing.md,
751
- paddingTop: tokens.spacing.md,
752
- borderTop: `1px solid ${tokens.colors.border.muted}`
753
- },
754
- children: [
755
- /* @__PURE__ */ jsxs(
756
- "div",
757
- {
758
- style: {
759
- display: "flex",
760
- alignItems: "center",
761
- gap: tokens.spacing.sm,
762
- marginBottom: tokens.spacing.sm
763
- },
764
- children: [
765
- /* @__PURE__ */ jsx(
766
- "span",
767
- {
768
- "aria-hidden": "true",
769
- style: {
770
- width: 10,
771
- height: 10,
772
- borderRadius: "50%",
773
- backgroundColor: statusColor,
774
- boxShadow: `0 0 8px ${statusColor}60`
775
- }
776
- }
777
- ),
778
- /* @__PURE__ */ jsx(
779
- "span",
780
- {
781
- style: {
782
- fontSize: tokens.typography.fontSize.xs,
783
- fontWeight: tokens.typography.fontWeight.medium,
784
- color: statusColor,
785
- textTransform: "capitalize"
786
- },
787
- children: ((_b = telemetry.health) == null ? void 0 : _b.status) ?? "Unknown"
788
- }
789
- )
790
- ]
791
- }
792
- ),
793
- ((_c = telemetry.power) == null ? void 0 : _c.batteryLevel) !== void 0 && /* @__PURE__ */ jsxs("div", { children: [
794
- /* @__PURE__ */ jsxs(
795
- "div",
796
- {
797
- style: {
798
- display: "flex",
799
- justifyContent: "space-between",
800
- marginBottom: 4,
801
- fontSize: tokens.typography.fontSize.xs
802
- },
803
- children: [
804
- /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "Battery" }),
805
- /* @__PURE__ */ jsx(
806
- "span",
807
- {
808
- style: {
809
- fontFamily: tokens.typography.fontFamily.mono,
810
- fontVariantNumeric: "tabular-nums"
811
- },
812
- children: formatPercentage(telemetry.power.batteryLevel, false, 0)
813
- }
814
- )
815
- ]
816
- }
817
- ),
818
- /* @__PURE__ */ jsx(
819
- "div",
820
- {
821
- style: {
822
- height: 4,
823
- backgroundColor: tokens.colors.border.muted,
824
- borderRadius: 2,
825
- overflow: "hidden"
826
- },
827
- children: /* @__PURE__ */ jsx(
828
- "div",
829
- {
830
- role: "progressbar",
831
- "aria-valuenow": telemetry.power.batteryLevel,
832
- "aria-valuemin": 0,
833
- "aria-valuemax": 100,
834
- "aria-label": "Battery level",
835
- style: {
836
- height: "100%",
837
- width: `${Math.min(100, Math.max(0, telemetry.power.batteryLevel))}%`,
838
- backgroundColor: telemetry.power.batteryLevel > 30 ? tokens.colors.status.normal : tokens.colors.status.critical,
839
- borderRadius: 2,
840
- transition: `width ${transitionDuration} ease-out`
841
- }
842
- }
843
- )
844
- }
845
- )
846
- ] })
847
- ]
848
- }
849
- ),
850
- spacecraft.timestamp && /* @__PURE__ */ jsx(
851
- "footer",
852
- {
853
- style: {
854
- marginTop: tokens.spacing.md,
855
- paddingTop: tokens.spacing.sm,
856
- borderTop: `1px solid ${tokens.colors.border.muted}`,
857
- fontSize: tokens.typography.fontSize.xs,
858
- color: tokens.colors.text.tertiary,
859
- textAlign: "right"
860
- },
861
- children: /* @__PURE__ */ jsxs("time", { dateTime: spacecraft.timestamp, children: [
862
- formatTime(spacecraft.timestamp),
863
- " UTC"
864
- ] })
865
- }
866
- )
867
- ]
868
- }
869
- );
870
- });
871
- const DataCell = memo(function DataCell2({
872
- label,
873
- value,
874
- highlight = false,
875
- inline = false,
876
- tokens,
877
- highlightColor
878
- }) {
879
- if (inline) {
880
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
881
- /* @__PURE__ */ jsx(
882
- "span",
883
- {
884
- style: {
885
- fontSize: tokens.typography.fontSize.xs,
886
- color: tokens.colors.text.secondary,
887
- // WCAG AA compliant
888
- fontWeight: tokens.typography.fontWeight.medium
889
- },
890
- children: label
891
- }
892
- ),
893
- /* @__PURE__ */ jsx(
894
- "span",
895
- {
896
- style: {
897
- fontSize: tokens.typography.fontSize.sm,
898
- fontFamily: tokens.typography.fontFamily.mono,
899
- fontVariantNumeric: "tabular-nums",
900
- color: tokens.colors.text.primary
901
- },
902
- children: value
903
- }
904
- )
905
- ] });
906
- }
907
- return /* @__PURE__ */ jsxs("div", { children: [
908
- /* @__PURE__ */ jsx(
909
- "span",
910
- {
911
- style: {
912
- display: "block",
913
- fontSize: tokens.typography.fontSize.xs,
914
- color: tokens.colors.text.secondary,
915
- // WCAG AA compliant
916
- fontWeight: tokens.typography.fontWeight.medium,
917
- marginBottom: 2
918
- },
919
- children: label
920
- }
921
- ),
922
- /* @__PURE__ */ jsx(
923
- "span",
924
- {
925
- style: {
926
- display: "block",
927
- fontSize: tokens.typography.fontSize.sm,
928
- fontFamily: tokens.typography.fontFamily.mono,
929
- fontVariantNumeric: "tabular-nums",
930
- color: highlight ? highlightColor ?? safeAccentText(tokens.colors.accent.primary) : tokens.colors.text.primary,
931
- fontWeight: tokens.typography.fontWeight.medium
932
- },
933
- children: value
934
- }
935
- )
936
- ] });
937
- });
938
- export {
939
- SpacecraftCard
940
- };
941
- //# sourceMappingURL=SpacecraftCard.js.map