@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,326 +0,0 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- import { memo, useRef, useMemo, useEffect } from "react";
3
- import { AstroIcon } from "../core/AstroIcon.js";
4
- import { classNames } from "../utils/index.js";
5
- import { useTheme } from "../theme/ThemeProvider.js";
6
- const SensorFootprintCard = memo(function SensorFootprintCard2({
7
- sensor,
8
- latitude,
9
- longitude,
10
- altitudeKm,
11
- headingDegrees = 0,
12
- compact = false,
13
- loading = false,
14
- className = ""
15
- }) {
16
- const { tokens, theme } = useTheme();
17
- const isTransparentTheme = theme === "transparent" || theme === "transparent-bold" || theme === "transparent-minimal";
18
- const cardBg = isTransparentTheme ? "transparent" : tokens.colors.background.surface;
19
- const cardGlass = isTransparentTheme ? {
20
- backdropFilter: "blur(12px)",
21
- WebkitBackdropFilter: "blur(12px)"
22
- } : {};
23
- const canvasRef = useRef(null);
24
- const statusColors = useMemo(
25
- () => ({
26
- standby: tokens.colors.status.standby,
27
- off: tokens.colors.status.off,
28
- caution: tokens.colors.status.caution
29
- }),
30
- [tokens]
31
- );
32
- const safeAltitude = altitudeKm ?? 400;
33
- const footprint = useMemo(() => {
34
- const fov = (sensor == null ? void 0 : sensor.fovDegrees) ?? 30;
35
- const alongFov = (sensor == null ? void 0 : sensor.alongTrackFovDegrees) ?? fov;
36
- const halfFovRad = fov / 2 * (Math.PI / 180);
37
- const alongHalfFovRad = alongFov / 2 * (Math.PI / 180);
38
- const crossTrackKm = 2 * safeAltitude * Math.tan(halfFovRad);
39
- const alongTrackKm = 2 * safeAltitude * Math.tan(alongHalfFovRad);
40
- const areaKm2 = crossTrackKm * alongTrackKm;
41
- const swathWidthKm = crossTrackKm;
42
- return { crossTrackKm, alongTrackKm, areaKm2, swathWidthKm };
43
- }, [sensor == null ? void 0 : sensor.fovDegrees, sensor == null ? void 0 : sensor.alongTrackFovDegrees, safeAltitude]);
44
- useEffect(() => {
45
- if (loading || !sensor) return;
46
- const canvas = canvasRef.current;
47
- if (!canvas) return;
48
- const ctx = canvas.getContext("2d");
49
- if (!ctx) return;
50
- const w = canvas.width;
51
- const h = canvas.height;
52
- ctx.fillStyle = tokens.colors.background.base;
53
- ctx.fillRect(0, 0, w, h);
54
- ctx.strokeStyle = tokens.colors.border.muted;
55
- ctx.lineWidth = 0.5;
56
- for (let x = 0; x <= w; x += w / 8) {
57
- ctx.beginPath();
58
- ctx.moveTo(x, 0);
59
- ctx.lineTo(x, h);
60
- ctx.stroke();
61
- }
62
- for (let y = 0; y <= h; y += h / 6) {
63
- ctx.beginPath();
64
- ctx.moveTo(0, y);
65
- ctx.lineTo(w, y);
66
- ctx.stroke();
67
- }
68
- const cx = w / 2;
69
- const cy = h / 2;
70
- const scaleKmPerPixel = 1e3 / Math.min(w, h);
71
- const halfWidth = footprint.crossTrackKm / 2 / scaleKmPerPixel;
72
- const halfHeight = footprint.alongTrackKm / 2 / scaleKmPerPixel;
73
- ctx.save();
74
- ctx.translate(cx, cy);
75
- ctx.rotate(headingDegrees * Math.PI / 180);
76
- ctx.fillStyle = sensor.isActive ? `${statusColors.standby}20` : `${statusColors.off}15`;
77
- ctx.beginPath();
78
- ctx.ellipse(0, 0, halfWidth, halfHeight, 0, 0, 2 * Math.PI);
79
- ctx.fill();
80
- ctx.strokeStyle = sensor.isActive ? statusColors.standby : statusColors.off;
81
- ctx.lineWidth = 2;
82
- ctx.setLineDash(sensor.isActive ? [] : [5, 5]);
83
- ctx.stroke();
84
- ctx.setLineDash([]);
85
- ctx.strokeStyle = `${tokens.colors.text.primary}40`;
86
- ctx.lineWidth = 1;
87
- ctx.beginPath();
88
- ctx.moveTo(-halfWidth, 0);
89
- ctx.lineTo(halfWidth, 0);
90
- ctx.stroke();
91
- ctx.beginPath();
92
- ctx.moveTo(0, -halfHeight);
93
- ctx.lineTo(0, halfHeight);
94
- ctx.stroke();
95
- ctx.restore();
96
- ctx.fillStyle = tokens.colors.status.caution;
97
- ctx.beginPath();
98
- ctx.arc(cx, cy, 4, 0, 2 * Math.PI);
99
- ctx.fill();
100
- ctx.save();
101
- ctx.translate(cx, cy);
102
- ctx.rotate(headingDegrees * Math.PI / 180);
103
- ctx.fillStyle = tokens.colors.status.caution;
104
- ctx.beginPath();
105
- ctx.moveTo(0, -8);
106
- ctx.lineTo(3, -4);
107
- ctx.lineTo(-3, -4);
108
- ctx.closePath();
109
- ctx.fill();
110
- ctx.restore();
111
- const scaleBarLength = 100;
112
- const scaleBarPixels = scaleBarLength / scaleKmPerPixel;
113
- ctx.fillStyle = tokens.colors.text.tertiary;
114
- ctx.fillRect(10, h - 20, scaleBarPixels, 3);
115
- ctx.font = "10px monospace";
116
- ctx.fillText(`${scaleBarLength} km`, 10, h - 8);
117
- }, [loading, sensor, tokens, footprint, headingDegrees, statusColors]);
118
- if (loading) {
119
- return /* @__PURE__ */ jsxs(
120
- "div",
121
- {
122
- className: classNames("zendir-sensor-footprint-card", "loading", className),
123
- role: "article",
124
- "aria-busy": "true",
125
- "aria-label": "Loading sensor data",
126
- style: {
127
- backgroundColor: cardBg,
128
- ...cardGlass,
129
- border: "none",
130
- borderRadius: tokens.borderRadius.lg,
131
- padding: tokens.spacing.md,
132
- minHeight: 200
133
- },
134
- children: [
135
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 16 }, children: [
136
- /* @__PURE__ */ jsx("div", { style: { height: 24, width: "50%", backgroundColor: "rgba(255,255,255,0.1)", borderRadius: 4 } }),
137
- /* @__PURE__ */ jsx("div", { style: { height: 24, width: 60, backgroundColor: "rgba(255,255,255,0.1)", borderRadius: 4 } })
138
- ] }),
139
- /* @__PURE__ */ jsx("div", { style: { height: 120, backgroundColor: "rgba(255,255,255,0.06)", borderRadius: 8 } })
140
- ]
141
- }
142
- );
143
- }
144
- if (!sensor) {
145
- return /* @__PURE__ */ jsxs(
146
- "div",
147
- {
148
- className: classNames("zendir-sensor-footprint-card", "empty", className),
149
- role: "article",
150
- "aria-label": "No sensor data",
151
- style: {
152
- backgroundColor: cardBg,
153
- ...cardGlass,
154
- border: "none",
155
- borderRadius: tokens.borderRadius.lg,
156
- padding: tokens.spacing.lg,
157
- textAlign: "center",
158
- color: tokens.colors.text.tertiary
159
- },
160
- children: [
161
- /* @__PURE__ */ jsx(AstroIcon, { name: "camera", size: "normal", label: "", style: { opacity: 0.5 } }),
162
- /* @__PURE__ */ jsx("p", { style: { margin: "8px 0 0 0", fontSize: tokens.typography.body[2].fontSize }, children: "No sensor data available" })
163
- ]
164
- }
165
- );
166
- }
167
- const getSensorIconName = (type) => {
168
- switch (type) {
169
- case "camera":
170
- return "camera";
171
- case "radar":
172
- return "antenna";
173
- case "lidar":
174
- return "flash-on";
175
- case "spectrometer":
176
- return "filter";
177
- default:
178
- return "image";
179
- }
180
- };
181
- const formatArea = (km2) => {
182
- if (km2 >= 1e6) return `${(km2 / 1e6).toFixed(1)}M km²`;
183
- if (km2 >= 1e3) return `${(km2 / 1e3).toFixed(1)}k km²`;
184
- return `${km2.toFixed(0)} km²`;
185
- };
186
- const canvasSize = compact ? 120 : 180;
187
- const cardStyle = {
188
- backgroundColor: cardBg,
189
- ...isTransparentTheme && { backdropFilter: "blur(12px)", WebkitBackdropFilter: "blur(12px)" },
190
- border: "none",
191
- borderRadius: tokens.borderRadius.lg,
192
- padding: tokens.spacing.md,
193
- fontFamily: tokens.typography.fontFamily.primary,
194
- color: tokens.colors.text.primary
195
- };
196
- return /* @__PURE__ */ jsxs("div", { className, style: cardStyle, children: [
197
- !compact && /* @__PURE__ */ jsxs("div", { style: {
198
- display: "flex",
199
- alignItems: "center",
200
- justifyContent: "space-between",
201
- marginBottom: tokens.spacing.md
202
- }, children: [
203
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: tokens.spacing.sm }, children: [
204
- /* @__PURE__ */ jsx(AstroIcon, { name: getSensorIconName(sensor.type), size: "small", label: sensor.type, style: { fontSize: tokens.typography.fontSize.lg } }),
205
- /* @__PURE__ */ jsxs("div", { children: [
206
- /* @__PURE__ */ jsx("h3", { style: {
207
- fontWeight: tokens.typography.fontWeight.semibold,
208
- color: tokens.colors.text.primary,
209
- fontSize: tokens.typography.fontSize.md,
210
- margin: 0
211
- }, children: sensor.name }),
212
- /* @__PURE__ */ jsxs("p", { style: {
213
- color: tokens.colors.text.tertiary,
214
- fontSize: tokens.typography.fontSize.xs,
215
- margin: 0,
216
- marginTop: tokens.spacing.xs
217
- }, children: [
218
- "FOV: ",
219
- sensor.fovDegrees,
220
- "°"
221
- ] })
222
- ] })
223
- ] }),
224
- /* @__PURE__ */ jsx("span", { style: {
225
- padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,
226
- borderRadius: tokens.borderRadius.sm,
227
- fontSize: tokens.typography.fontSize.xxs,
228
- // 0.625rem / 10px (AstroUXDS compact)
229
- fontWeight: tokens.typography.fontWeight.bold,
230
- letterSpacing: "0.5px",
231
- backgroundColor: sensor.isActive ? `${statusColors.standby}20` : `${statusColors.off}20`,
232
- color: sensor.isActive ? statusColors.standby : statusColors.off
233
- }, children: sensor.isActive ? "Active" : "Standby" })
234
- ] }),
235
- /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx(
236
- "canvas",
237
- {
238
- ref: canvasRef,
239
- width: canvasSize,
240
- height: canvasSize,
241
- style: { borderRadius: tokens.borderRadius.md }
242
- }
243
- ) }),
244
- /* @__PURE__ */ jsxs("div", { style: {
245
- display: "grid",
246
- gridTemplateColumns: "repeat(2, 1fr)",
247
- gap: tokens.spacing.sm,
248
- marginTop: tokens.spacing.md,
249
- fontSize: compact ? "10px" : tokens.typography.fontSize.xs
250
- }, children: [
251
- /* @__PURE__ */ jsxs("div", { style: {
252
- backgroundColor: tokens.colors.background.base,
253
- borderRadius: tokens.borderRadius.md,
254
- padding: tokens.spacing.sm,
255
- textAlign: "center"
256
- }, children: [
257
- /* @__PURE__ */ jsxs("div", { style: {
258
- color: statusColors.standby,
259
- fontWeight: tokens.typography.fontWeight.bold,
260
- fontFamily: tokens.typography.fontFamily.mono,
261
- fontVariantNumeric: "tabular-nums"
262
- }, children: [
263
- footprint.swathWidthKm.toFixed(0),
264
- " km"
265
- ] }),
266
- /* @__PURE__ */ jsx("div", { style: { color: tokens.colors.text.tertiary }, children: "Swath width" })
267
- ] }),
268
- /* @__PURE__ */ jsxs("div", { style: {
269
- backgroundColor: tokens.colors.background.base,
270
- borderRadius: tokens.borderRadius.md,
271
- padding: tokens.spacing.sm,
272
- textAlign: "center"
273
- }, children: [
274
- /* @__PURE__ */ jsx("div", { style: {
275
- color: statusColors.standby,
276
- fontWeight: tokens.typography.fontWeight.bold,
277
- fontFamily: tokens.typography.fontFamily.mono,
278
- fontVariantNumeric: "tabular-nums"
279
- }, children: formatArea(footprint.areaKm2) }),
280
- /* @__PURE__ */ jsx("div", { style: { color: tokens.colors.text.tertiary }, children: "Coverage" })
281
- ] })
282
- ] }),
283
- !compact && /* @__PURE__ */ jsxs("div", { style: {
284
- marginTop: tokens.spacing.md,
285
- paddingTop: tokens.spacing.md,
286
- borderTop: `1px solid ${tokens.colors.border.muted}`,
287
- fontSize: tokens.typography.fontSize.xs
288
- }, children: [
289
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between" }, children: [
290
- /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "Nadir point" }),
291
- /* @__PURE__ */ jsxs("span", { style: {
292
- fontFamily: tokens.typography.fontFamily.mono,
293
- color: tokens.colors.text.secondary,
294
- fontVariantNumeric: "tabular-nums"
295
- }, children: [
296
- Math.abs(latitude ?? 0).toFixed(2),
297
- "°",
298
- (latitude ?? 0) >= 0 ? "N" : "S",
299
- ",",
300
- Math.abs(longitude ?? 0).toFixed(2),
301
- "°",
302
- (longitude ?? 0) >= 0 ? "E" : "W"
303
- ] })
304
- ] }),
305
- /* @__PURE__ */ jsxs("div", { style: {
306
- display: "flex",
307
- justifyContent: "space-between",
308
- marginTop: tokens.spacing.xs
309
- }, children: [
310
- /* @__PURE__ */ jsx("span", { style: { color: tokens.colors.text.tertiary }, children: "Altitude" }),
311
- /* @__PURE__ */ jsxs("span", { style: {
312
- fontFamily: tokens.typography.fontFamily.mono,
313
- color: tokens.colors.text.secondary,
314
- fontVariantNumeric: "tabular-nums"
315
- }, children: [
316
- (altitudeKm ?? 0).toFixed(1),
317
- " km"
318
- ] })
319
- ] })
320
- ] })
321
- ] });
322
- });
323
- export {
324
- SensorFootprintCard
325
- };
326
- //# sourceMappingURL=SensorFootprintCard.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SensorFootprintCard.js","sources":["../../../src/react/visualizations/SensorFootprintCard.tsx"],"sourcesContent":["/**\n * @zendir/ui - SensorFootprintCard Component\n * \n * Camera/Sensor Field of View visualization showing ground footprint.\n * \n * Features:\n * - Full null-safety with graceful fallbacks\n * - Canvas-based footprint visualization\n * - Coverage area calculations\n * - Loading and empty states\n */\n\nimport React, { memo, useMemo, useRef, useEffect } from 'react';\nimport { useTheme } from '../theme';\nimport { AstroIcon, type AstroIconName } from '../core/AstroIcon';\nimport { classNames } from '../utils';\n\nexport interface FootprintSensorConfig {\n id: string;\n name: string;\n /** Field of view in degrees (cross-track) */\n fovDegrees: number;\n /** Along-track field of view in degrees */\n alongTrackFovDegrees?: number;\n /** Sensor type */\n type: 'camera' | 'radar' | 'lidar' | 'spectrometer' | string;\n /** Whether sensor is active */\n isActive: boolean;\n}\n\nexport interface SensorFootprintCardProps {\n /** Sensor configuration */\n sensor?: FootprintSensorConfig;\n /** Current spacecraft latitude */\n latitude?: number;\n /** Current spacecraft longitude */\n longitude?: number;\n /** Current altitude in km */\n altitudeKm?: number;\n /** Current heading/track angle in degrees */\n headingDegrees?: number;\n /** Compact mode */\n compact?: boolean;\n /** Loading state */\n loading?: boolean;\n /** Custom class name */\n className?: string;\n}\n\nexport const SensorFootprintCard = memo(function SensorFootprintCard({\n sensor,\n latitude,\n longitude,\n altitudeKm,\n headingDegrees = 0,\n compact = false,\n loading = false,\n className = '',\n}: SensorFootprintCardProps): React.ReactElement {\n const { tokens, theme } = useTheme();\n const isTransparentTheme = theme === 'transparent' || theme === 'transparent-bold' || theme === 'transparent-minimal';\n const cardBg = isTransparentTheme ? 'transparent' : tokens.colors.background.surface;\n const cardGlass = isTransparentTheme ? {\n backdropFilter: 'blur(12px)' as const,\n WebkitBackdropFilter: 'blur(12px)' as const,\n } : {};\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const statusColors = useMemo(\n () => ({\n standby: tokens.colors.status.standby,\n off: tokens.colors.status.off,\n caution: tokens.colors.status.caution,\n }),\n [tokens],\n );\n\n const safeAltitude = altitudeKm ?? 400;\n const footprint = useMemo(() => {\n const fov = sensor?.fovDegrees ?? 30;\n const alongFov = sensor?.alongTrackFovDegrees ?? fov;\n const halfFovRad = (fov / 2) * (Math.PI / 180);\n const alongHalfFovRad = (alongFov / 2) * (Math.PI / 180);\n const crossTrackKm = 2 * safeAltitude * Math.tan(halfFovRad);\n const alongTrackKm = 2 * safeAltitude * Math.tan(alongHalfFovRad);\n const areaKm2 = crossTrackKm * alongTrackKm;\n const swathWidthKm = crossTrackKm;\n return { crossTrackKm, alongTrackKm, areaKm2, swathWidthKm };\n }, [sensor?.fovDegrees, sensor?.alongTrackFovDegrees, safeAltitude]);\n\n useEffect(() => {\n if (loading || !sensor) return;\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n const w = canvas.width;\n const h = canvas.height;\n ctx.fillStyle = tokens.colors.background.base;\n ctx.fillRect(0, 0, w, h);\n ctx.strokeStyle = tokens.colors.border.muted;\n ctx.lineWidth = 0.5;\n for (let x = 0; x <= w; x += w / 8) {\n ctx.beginPath();\n ctx.moveTo(x, 0);\n ctx.lineTo(x, h);\n ctx.stroke();\n }\n for (let y = 0; y <= h; y += h / 6) {\n ctx.beginPath();\n ctx.moveTo(0, y);\n ctx.lineTo(w, y);\n ctx.stroke();\n }\n const cx = w / 2;\n const cy = h / 2;\n const scaleKmPerPixel = 1000 / Math.min(w, h);\n const halfWidth = (footprint.crossTrackKm / 2) / scaleKmPerPixel;\n const halfHeight = (footprint.alongTrackKm / 2) / scaleKmPerPixel;\n ctx.save();\n ctx.translate(cx, cy);\n ctx.rotate(headingDegrees * Math.PI / 180);\n ctx.fillStyle = sensor.isActive\n ? `${statusColors.standby}20`\n : `${statusColors.off}15`;\n ctx.beginPath();\n ctx.ellipse(0, 0, halfWidth, halfHeight, 0, 0, 2 * Math.PI);\n ctx.fill();\n ctx.strokeStyle = sensor.isActive ? statusColors.standby : statusColors.off;\n ctx.lineWidth = 2;\n ctx.setLineDash(sensor.isActive ? [] : [5, 5]);\n ctx.stroke();\n ctx.setLineDash([]);\n ctx.strokeStyle = `${tokens.colors.text.primary}40`;\n ctx.lineWidth = 1;\n ctx.beginPath();\n ctx.moveTo(-halfWidth, 0);\n ctx.lineTo(halfWidth, 0);\n ctx.stroke();\n ctx.beginPath();\n ctx.moveTo(0, -halfHeight);\n ctx.lineTo(0, halfHeight);\n ctx.stroke();\n ctx.restore();\n ctx.fillStyle = tokens.colors.status.caution;\n ctx.beginPath();\n ctx.arc(cx, cy, 4, 0, 2 * Math.PI);\n ctx.fill();\n ctx.save();\n ctx.translate(cx, cy);\n ctx.rotate(headingDegrees * Math.PI / 180);\n ctx.fillStyle = tokens.colors.status.caution;\n ctx.beginPath();\n ctx.moveTo(0, -8);\n ctx.lineTo(3, -4);\n ctx.lineTo(-3, -4);\n ctx.closePath();\n ctx.fill();\n ctx.restore();\n const scaleBarLength = 100;\n const scaleBarPixels = scaleBarLength / scaleKmPerPixel;\n ctx.fillStyle = tokens.colors.text.tertiary;\n ctx.fillRect(10, h - 20, scaleBarPixels, 3);\n ctx.font = '10px monospace';\n ctx.fillText(`${scaleBarLength} km`, 10, h - 8);\n }, [loading, sensor, tokens, footprint, headingDegrees, statusColors]);\n\n // Loading state\n if (loading) {\n return (\n <div\n className={classNames('zendir-sensor-footprint-card', 'loading', className)}\n role=\"article\"\n aria-busy=\"true\"\n aria-label=\"Loading sensor data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n border: 'none',\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n minHeight: 200,\n }}\n >\n <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>\n <div style={{ height: 24, width: '50%', backgroundColor: 'rgba(255,255,255,0.1)', borderRadius: 4 }} />\n <div style={{ height: 24, width: 60, backgroundColor: 'rgba(255,255,255,0.1)', borderRadius: 4 }} />\n </div>\n <div style={{ height: 120, backgroundColor: 'rgba(255,255,255,0.06)', borderRadius: 8 }} />\n </div>\n );\n }\n\n // Empty state\n if (!sensor) {\n return (\n <div\n className={classNames('zendir-sensor-footprint-card', 'empty', className)}\n role=\"article\"\n aria-label=\"No sensor data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n border: 'none',\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.lg,\n textAlign: 'center',\n color: tokens.colors.text.tertiary,\n }}\n >\n <AstroIcon name=\"camera\" size=\"normal\" label=\"\" style={{ opacity: 0.5 }} />\n <p style={{ margin: '8px 0 0 0', fontSize: tokens.typography.body[2].fontSize }}>No sensor data available</p>\n </div>\n );\n }\n \n // Sensor type icon (AstroIcon)\n const getSensorIconName = (type: string): AstroIconName => {\n switch (type) {\n case 'camera': return 'camera';\n case 'radar': return 'antenna';\n case 'lidar': return 'flash-on';\n case 'spectrometer': return 'filter';\n default: return 'image';\n }\n };\n\n // Format area (Astro: tabular numbers)\n const formatArea = (km2: number): string => {\n if (km2 >= 1e6) return `${(km2 / 1e6).toFixed(1)}M km²`;\n if (km2 >= 1e3) return `${(km2 / 1e3).toFixed(1)}k km²`;\n return `${km2.toFixed(0)} km²`;\n };\n\n const canvasSize = compact ? 120 : 180;\n\n // Astro UX compliant card styling\n const cardStyle: React.CSSProperties = {\n backgroundColor: cardBg,\n ...(isTransparentTheme && { backdropFilter: 'blur(12px)' as const, WebkitBackdropFilter: 'blur(12px)' as const }),\n border: 'none',\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.primary,\n };\n\n return (\n <div className={className} style={cardStyle}>\n {!compact && (\n <div style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: tokens.spacing.md,\n }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: tokens.spacing.sm }}>\n <AstroIcon name={getSensorIconName(sensor.type)} size=\"small\" label={sensor.type} style={{ fontSize: tokens.typography.fontSize.lg }} />\n <div>\n {/* Astro: Sentence-case labels */}\n <h3 style={{ \n fontWeight: tokens.typography.fontWeight.semibold, \n color: tokens.colors.text.primary, \n fontSize: tokens.typography.fontSize.md,\n margin: 0,\n }}>\n {sensor.name}\n </h3>\n <p style={{ \n color: tokens.colors.text.tertiary, \n fontSize: tokens.typography.fontSize.xs,\n margin: 0,\n marginTop: tokens.spacing.xs,\n }}>\n FOV: {sensor.fovDegrees}°\n </p>\n </div>\n </div>\n {/* Status badge - Astro style (sentence case per Tier 3) */}\n <span style={{\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\n borderRadius: tokens.borderRadius.sm,\n fontSize: tokens.typography.fontSize.xxs, // 0.625rem / 10px (AstroUXDS compact)\n fontWeight: tokens.typography.fontWeight.bold,\n letterSpacing: '0.5px',\n backgroundColor: sensor.isActive \n ? `${statusColors.standby}20` \n : `${statusColors.off}20`,\n color: sensor.isActive \n ? statusColors.standby \n : statusColors.off,\n }}>\n {sensor.isActive ? 'Active' : 'Standby'}\n </span>\n </div>\n )}\n\n {/* Canvas visualization */}\n <div style={{ display: 'flex', justifyContent: 'center' }}>\n <canvas \n ref={canvasRef}\n width={canvasSize}\n height={canvasSize}\n style={{ borderRadius: tokens.borderRadius.md }}\n />\n </div>\n\n {/* Metrics - Astro: Sentence-case, tabular numbers */}\n <div style={{\n display: 'grid',\n gridTemplateColumns: 'repeat(2, 1fr)',\n gap: tokens.spacing.sm,\n marginTop: tokens.spacing.md,\n fontSize: compact ? '10px' : tokens.typography.fontSize.xs,\n }}>\n <div style={{\n backgroundColor: tokens.colors.background.base,\n borderRadius: tokens.borderRadius.md,\n padding: tokens.spacing.sm,\n textAlign: 'center',\n }}>\n <div style={{ \n color: statusColors.standby, \n fontWeight: tokens.typography.fontWeight.bold,\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: 'tabular-nums',\n }}>\n {footprint.swathWidthKm.toFixed(0)} km\n </div>\n <div style={{ color: tokens.colors.text.tertiary }}>Swath width</div>\n </div>\n <div style={{\n backgroundColor: tokens.colors.background.base,\n borderRadius: tokens.borderRadius.md,\n padding: tokens.spacing.sm,\n textAlign: 'center',\n }}>\n <div style={{ \n color: statusColors.standby, \n fontWeight: tokens.typography.fontWeight.bold,\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: 'tabular-nums',\n }}>\n {formatArea(footprint.areaKm2)}\n </div>\n <div style={{ color: tokens.colors.text.tertiary }}>Coverage</div>\n </div>\n </div>\n\n {/* Position info - Astro: Sentence-case, tabular numbers */}\n {!compact && (\n <div style={{\n marginTop: tokens.spacing.md,\n paddingTop: tokens.spacing.md,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n fontSize: tokens.typography.fontSize.xs,\n }}>\n <div style={{ display: 'flex', justifyContent: 'space-between' }}>\n <span style={{ color: tokens.colors.text.tertiary }}>Nadir point</span>\n <span style={{ \n fontFamily: tokens.typography.fontFamily.mono, \n color: tokens.colors.text.secondary,\n fontVariantNumeric: 'tabular-nums',\n }}>\n {Math.abs(latitude ?? 0).toFixed(2)}°{(latitude ?? 0) >= 0 ? 'N' : 'S'}, \n {Math.abs(longitude ?? 0).toFixed(2)}°{(longitude ?? 0) >= 0 ? 'E' : 'W'}\n </span>\n </div>\n <div style={{ \n display: 'flex', \n justifyContent: 'space-between', \n marginTop: tokens.spacing.xs,\n }}>\n <span style={{ color: tokens.colors.text.tertiary }}>Altitude</span>\n <span style={{ \n fontFamily: tokens.typography.fontFamily.mono, \n color: tokens.colors.text.secondary,\n fontVariantNumeric: 'tabular-nums',\n }}>\n {(altitudeKm ?? 0).toFixed(1)} km\n </span>\n </div>\n </div>\n )}\n </div>\n );\n});\n\n\n\n\n"],"names":["SensorFootprintCard"],"mappings":"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"}