@zendir/ui 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (116) hide show
  1. package/CHANGELOG.md +419 -406
  2. package/dist/react/3d/CesiumCaptureSource.js.map +1 -1
  3. package/dist/react/3d/ZenSpace3D.js.map +1 -1
  4. package/dist/react/3d/ZenSpace3DCesium.js.map +1 -1
  5. package/dist/react/3d/ZenSpace3DShaders.js.map +1 -1
  6. package/dist/react/3d/ZenSpace3DUtils.js.map +1 -1
  7. package/dist/react/3d/capturePngAnalysis.js.map +1 -1
  8. package/dist/react/3d/threeLoader.js.map +1 -1
  9. package/dist/react/astro/ClassificationBanner.js.map +1 -1
  10. package/dist/react/astro/GlobalStatusBar.js.map +1 -1
  11. package/dist/react/astro/MissionClock.js.map +1 -1
  12. package/dist/react/astro/MonitoringIcon.js.map +1 -1
  13. package/dist/react/astro/Notification.js.map +1 -1
  14. package/dist/react/astro/Progress.js.map +1 -1
  15. package/dist/react/astro/SimulationControls.js.map +1 -1
  16. package/dist/react/astro/StatusIndicator.js.map +1 -1
  17. package/dist/react/astro/UnifiedTimeline.js.map +1 -1
  18. package/dist/react/cards/AccessCard.js.map +1 -1
  19. package/dist/react/cards/OrbitCard.js.map +1 -1
  20. package/dist/react/cards/SpacecraftCard.js.map +1 -1
  21. package/dist/react/cards/TelemetryCard.js.map +1 -1
  22. package/dist/react/cards/TelemetryStreamCard.js.map +1 -1
  23. package/dist/react/charts/GroundTrackMap.js.map +1 -1
  24. package/dist/react/charts/GroundTrackMapLeaflet.js.map +1 -1
  25. package/dist/react/charts/groundTrackMapLeafletTiles.js.map +1 -1
  26. package/dist/react/charts/groundTrackMapLeafletUtils.js.map +1 -1
  27. package/dist/react/charts/unified/AstroChart.js.map +1 -1
  28. package/dist/react/charts/unified/PowerOverviewChart.js.map +1 -1
  29. package/dist/react/charts/unified/domain.js.map +1 -1
  30. package/dist/react/charts/unified/generators.js.map +1 -1
  31. package/dist/react/charts/unified/presets.js.map +1 -1
  32. package/dist/react/charts/unified/sync.js.map +1 -1
  33. package/dist/react/charts/unified/theme.js.map +1 -1
  34. package/dist/react/charts/unified/useChartStream.js.map +1 -1
  35. package/dist/react/chatgpt/index.js.map +1 -1
  36. package/dist/react/context/CategoryContext.js.map +1 -1
  37. package/dist/react/context/DisplaySettingsContext.js.map +1 -1
  38. package/dist/react/context/SpatialSelectionContext.js.map +1 -1
  39. package/dist/react/core/data/DataTable.js.map +1 -1
  40. package/dist/react/core/data/DataValue.js.map +1 -1
  41. package/dist/react/core/data/propertyConfig.js.map +1 -1
  42. package/dist/react/core/display/AstroIcon.js.map +1 -1
  43. package/dist/react/core/display/Badge.js.map +1 -1
  44. package/dist/react/core/display/CardHeader.js.map +1 -1
  45. package/dist/react/core/display/Container.js.map +1 -1
  46. package/dist/react/core/display/CopyButton.js.map +1 -1
  47. package/dist/react/core/display/GlassCard.js.map +1 -1
  48. package/dist/react/core/display/HeaderIconWithStatus.js.map +1 -1
  49. package/dist/react/core/display/Icon.js.map +1 -1
  50. package/dist/react/core/display/Typography.js.map +1 -1
  51. package/dist/react/core/feedback/ConfirmDialog.js.map +1 -1
  52. package/dist/react/core/feedback/Dialog.js.map +1 -1
  53. package/dist/react/core/feedback/Toast.js.map +1 -1
  54. package/dist/react/core/inputs/Button.js.map +1 -1
  55. package/dist/react/core/inputs/Checkbox.js.map +1 -1
  56. package/dist/react/core/inputs/Input.js.map +1 -1
  57. package/dist/react/core/inputs/LimitsBar.js.map +1 -1
  58. package/dist/react/core/inputs/NumberInput.js.map +1 -1
  59. package/dist/react/core/inputs/PinInput.js.map +1 -1
  60. package/dist/react/core/inputs/Select.js.map +1 -1
  61. package/dist/react/core/inputs/Toggle.js.map +1 -1
  62. package/dist/react/core/layout/Box.js.map +1 -1
  63. package/dist/react/core/layout/Center.js.map +1 -1
  64. package/dist/react/core/layout/Divider.js.map +1 -1
  65. package/dist/react/core/layout/Flex.js.map +1 -1
  66. package/dist/react/core/layout/Grid.js.map +1 -1
  67. package/dist/react/core/layout/Spacer.js.map +1 -1
  68. package/dist/react/core/layout/Stack.js.map +1 -1
  69. package/dist/react/core/layout/responsive.js.map +1 -1
  70. package/dist/react/core/layout/useBreakpoint.js.map +1 -1
  71. package/dist/react/core/navigation/AppBar.js.map +1 -1
  72. package/dist/react/core/navigation/Pagination.js.map +1 -1
  73. package/dist/react/core/navigation/SideNav.js.map +1 -1
  74. package/dist/react/core/navigation/Tabs.js.map +1 -1
  75. package/dist/react/core/overlays/Popover.js.map +1 -1
  76. package/dist/react/core/overlays/SidePanel.js.map +1 -1
  77. package/dist/react/core/overlays/Tooltip.js.map +1 -1
  78. package/dist/react/core/widgets/ActivityPlanner.js.map +1 -1
  79. package/dist/react/core/widgets/Capture.js.map +1 -1
  80. package/dist/react/core/widgets/ChatPanel.js.map +1 -1
  81. package/dist/react/core/widgets/ColorPickerPanel.js.map +1 -1
  82. package/dist/react/core/widgets/CommandBuilder.js.map +1 -1
  83. package/dist/react/core/widgets/ConnectionForm.js.map +1 -1
  84. package/dist/react/core/widgets/FileExplorer.js.map +1 -1
  85. package/dist/react/core/widgets/HexViewer.js.map +1 -1
  86. package/dist/react/core/widgets/ImageFrame.js.map +1 -1
  87. package/dist/react/core/widgets/ImageGallery.js.map +1 -1
  88. package/dist/react/core/widgets/ImagePanel.js.map +1 -1
  89. package/dist/react/core/widgets/LogViewer.js.map +1 -1
  90. package/dist/react/core/widgets/MessageStream.js.map +1 -1
  91. package/dist/react/core/widgets/MissionCalendar.js.map +1 -1
  92. package/dist/react/core/widgets/PacketViewer.js.map +1 -1
  93. package/dist/react/hooks/useCompactMode.js.map +1 -1
  94. package/dist/react/hooks/useSimulationScene.js.map +1 -1
  95. package/dist/react/panels/LayerControlPanel.js.map +1 -1
  96. package/dist/react/panels/ObjectInventoryPanel.js.map +1 -1
  97. package/dist/react/shared/ErrorBoundary.js.map +1 -1
  98. package/dist/react/shared/Skeleton.js.map +1 -1
  99. package/dist/react/theme/ThemeProvider.js +2 -1
  100. package/dist/react/theme/ThemeProvider.js.map +1 -1
  101. package/dist/react/theme/cardAccent.js.map +1 -1
  102. package/dist/react/theme/config.js.map +1 -1
  103. package/dist/react/theme/types.js.map +1 -1
  104. package/dist/react/types.js.map +1 -1
  105. package/dist/react/utils/categoryPalette.js.map +1 -1
  106. package/dist/react/utils/index.js.map +1 -1
  107. package/dist/style.css +216 -216
  108. package/dist/tokens/core.js.map +1 -1
  109. package/dist/tokens/index.js.map +1 -1
  110. package/dist/tokens/palettes/astro.js.map +1 -1
  111. package/dist/tokens/palettes/index.js.map +1 -1
  112. package/dist/tokens/palettes/tailwind.js.map +1 -1
  113. package/dist/tokens/palettes/zendir.js.map +1 -1
  114. package/dist/tokens/themes.js.map +1 -1
  115. package/dist/tokens/tokens.css +533 -533
  116. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"AccessCard.js","names":[],"sources":["../../../src/react/cards/AccessCard.tsx"],"sourcesContent":["/**\n * @zendir/ui - AccessCard Component\n *\n * Enterprise-grade access/link status card between spacecraft and ground station.\n *\n * AstroUXDS Compliance:\n * - Status colors used semantically for link/signal status\n * - Normal (green) = accessible, Off (grey) = no contact\n * - Signal strength uses status gradient (normal → caution → serious → critical)\n * - Zendir accent colors for decorative elements\n * - Tabular numbers for time/data display\n *\n * Features:\n * - Full null-safety with graceful fallbacks\n * - WCAG 2.1 AA accessibility\n * - Link budget display\n * - Upcoming pass windows\n * - Loading and empty states\n */\n\nimport React, { memo, useMemo } from \"react\";\nimport type { AccessData, AccessWindow } from \"../types\";\nimport { useTheme } from \"../theme\";\nimport { Icon } from \"../core/display/Icon\";\nimport { CardHeader } from \"../core/display/CardHeader\";\nimport { useCompactMode } from \"../hooks\";\nimport {\n safeNumber,\n formatDuration,\n formatTime,\n formatDataRate,\n formatDecibels,\n formatDegrees,\n classNames,\n getStatusColor,\n safeAccentText,\n type StatusLevel,\n} from \"../utils\";\n\nexport interface AccessCardProps {\n /** Current access data */\n access?: AccessData;\n /** Ground station name */\n groundStationName: string;\n /** Spacecraft name */\n spacecraftName?: string;\n /** Next access windows */\n upcomingWindows?: AccessWindow[];\n /** Loading state */\n loading?: boolean;\n /** Custom className */\n className?: string;\n /** Enable compact mode - shows condensed view that expands on hover/click */\n compact?: boolean;\n /** Start expanded when in compact mode (pinned state) */\n defaultExpanded?: boolean;\n /** Callback when pin state changes in compact mode */\n onPinChange?: (isPinned: boolean) => void;\n}\n\n/**\n * AccessCard - Displays spacecraft-ground station link status\n *\n * @example\n * ```tsx\n * <AccessCard\n * access={accessData}\n * groundStationName=\"Goldstone\"\n * spacecraftName=\"ISS\"\n * upcomingWindows={windows}\n * />\n * ```\n */\nexport const AccessCard = memo(function AccessCard({\n access,\n groundStationName,\n spacecraftName,\n upcomingWindows = [],\n loading = false,\n className = \"\",\n compact = false,\n defaultExpanded = false,\n onPinChange,\n}: AccessCardProps): React.ReactElement {\n const { tokens, theme, prefersReducedMotion } = useTheme();\n const isTransparentTheme =\n theme === \"transparent\" ||\n theme === \"transparent-bold\" ||\n theme === \"transparent-minimal\";\n const isBoldVariant = theme === \"transparent-bold\";\n const isMinimalVariant = theme === \"transparent-minimal\";\n const useGlassMode = isBoldVariant || isMinimalVariant;\n\n // Glass accent colors for bold/minimal themes (matching Container/AstroChart)\n const glassAccentColor = tokens.colors.accent.primary;\n const glassAccentMuted = `${glassAccentColor}66`;\n\n // Use transparent background with blur for transparent themes (matching Timeline)\n const cardBg = isTransparentTheme\n ? \"transparent\"\n : tokens.colors.background.surface;\n const cardGlass = isTransparentTheme\n ? {\n backdropFilter: \"blur(12px)\" as const,\n WebkitBackdropFilter: \"blur(12px)\" as const,\n }\n : {};\n\n // Glass mode container style (matching Container/AstroChart for bold/minimal)\n const glassContainerStyle: React.CSSProperties = useGlassMode\n ? {\n backgroundColor: \"rgba(10, 15, 25, 0.35)\",\n backdropFilter: \"blur(12px)\",\n WebkitBackdropFilter: \"blur(12px)\",\n border: `1px solid ${glassAccentMuted}`,\n borderTop: isBoldVariant\n ? `2px solid ${glassAccentColor}`\n : `1px solid ${glassAccentColor}`,\n }\n : {};\n\n // Compact mode state management\n const { expanded, isPinned, handlers, transitionDuration } = useCompactMode({\n compact,\n defaultExpanded,\n onPinChange,\n });\n\n // Computed status\n const isAccessible = access?.isAccessible ?? false;\n const statusLevel: StatusLevel = isAccessible ? \"normal\" : \"off\";\n const statusColor = getStatusColor(statusLevel);\n\n const signalStatus = useMemo((): StatusLevel => {\n const signal = access?.signalStrength;\n if (signal === undefined || signal === null) return \"off\";\n if (signal > 70) return \"normal\";\n if (signal > 40) return \"caution\";\n if (signal > 20) return \"serious\";\n return \"critical\";\n }, [access?.signalStrength]);\n\n // Loading state\n if (loading) {\n return (\n <div\n className={classNames(\"zendir-access-card\", \"loading\", className)}\n role=\"article\"\n aria-busy=\"true\"\n aria-label=\"Loading access data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n ...(tokens.colors.border.cardStyle ?? {}),\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n minHeight: 180,\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n marginBottom: 16,\n }}\n >\n <div\n style={{\n height: 24,\n width: \"40%\",\n backgroundColor: \"rgba(255,255,255,0.1)\",\n borderRadius: 4,\n }}\n />\n <div\n style={{\n height: 24,\n width: 60,\n backgroundColor: \"rgba(255,255,255,0.1)\",\n borderRadius: 4,\n }}\n />\n </div>\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(2, 1fr)\",\n gap: 12,\n }}\n >\n {[1, 2, 3, 4].map((i) => (\n <div\n key={i}\n style={{\n height: 40,\n backgroundColor: \"rgba(255,255,255,0.06)\",\n borderRadius: 4,\n }}\n />\n ))}\n </div>\n </div>\n );\n }\n\n // Empty state\n if (!access) {\n return (\n <div\n className={classNames(\"zendir-access-card\", \"empty\", className)}\n role=\"article\"\n aria-label=\"No access data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n ...(tokens.colors.border.cardStyleDashed ?? {}),\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.lg,\n textAlign: \"center\",\n color: tokens.colors.text.tertiary,\n }}\n >\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n style={{ opacity: 0.5, marginBottom: 8 }}\n >\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\" />\n </svg>\n <p style={{ margin: 0, fontSize: tokens.typography.body[2].fontSize }}>\n {groundStationName}: No access data\n </p>\n </div>\n );\n }\n\n // Compact view - shows key access info in a single row\n if (compact && !expanded) {\n return (\n <article\n className={classNames(\"zendir-access-card\", \"compact\", className)}\n {...handlers}\n aria-label={`Access: ${groundStationName} (compact)`}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n ...(useGlassMode\n ? glassContainerStyle\n : {\n backgroundColor: cardBg,\n ...cardGlass,\n ...(tokens.colors.border.cardStyle ?? {}),\n }),\n borderRadius: tokens.borderRadius.lg,\n padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.primary,\n fontSize: tokens.typography.fontSize.sm,\n cursor: \"pointer\",\n transition: `all ${transitionDuration} ease-out`,\n transform: \"scale(1)\",\n }}\n onMouseEnter={(e) => {\n handlers.onMouseEnter();\n if (!prefersReducedMotion) {\n (e.currentTarget as HTMLElement).style.transform = \"scale(1.01)\";\n (e.currentTarget as HTMLElement).style.boxShadow =\n `0 4px 12px ${statusColor}20`;\n }\n }}\n onMouseLeave={(e) => {\n handlers.onMouseLeave();\n (e.currentTarget as HTMLElement).style.transform = \"scale(1)\";\n (e.currentTarget as HTMLElement).style.boxShadow = \"\";\n }}\n >\n {/* Glass gradient overlay for bold/minimal themes */}\n {useGlassMode && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background:\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\n pointerEvents: \"none\",\n zIndex: 0,\n }}\n />\n )}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: tokens.spacing.md,\n position: \"relative\",\n zIndex: 1,\n }}\n >\n {/* Left side: Status indicator + Name + Accent line */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n flex: 1,\n minWidth: 0,\n }}\n >\n <div\n style={{\n width: 10,\n height: 10,\n borderRadius: \"50%\",\n backgroundColor: statusColor,\n boxShadow: isAccessible ? `0 0 6px ${statusColor}` : \"none\",\n flexShrink: 0,\n }}\n />\n <span\n style={{\n fontWeight: tokens.typography.fontWeight.medium,\n color: useGlassMode ? glassAccentColor : undefined,\n textShadow: useGlassMode\n ? `0 0 16px ${glassAccentMuted}`\n : undefined,\n }}\n >\n {groundStationName.split(\" \")[0]}\n </span>\n {useGlassMode && (\n <div\n style={{\n flex: 1,\n height: isBoldVariant ? \"2px\" : \"1px\",\n minWidth: 20,\n background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`,\n boxShadow: isBoldVariant\n ? `0 0 8px ${glassAccentMuted}`\n : undefined,\n }}\n />\n )}\n </div>\n\n {/* Right side: Status badge + Signal strength + Pin */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n flexShrink: 0,\n }}\n >\n <span\n style={{\n color: statusColor,\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n }}\n >\n {isAccessible ? \"AOS\" : \"LOS\"}\n </span>\n {access.signalStrength !== undefined && (\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\n <Icon\n name=\"antenna\"\n size={12}\n color={tokens.colors.text.secondary}\n />\n <span\n style={{\n fontVariantNumeric: \"tabular-nums\",\n fontFamily: tokens.typography.fontFamily.mono,\n fontSize: tokens.typography.fontSize.xs,\n }}\n >\n {safeNumber(access.signalStrength, 0)}%\n </span>\n </div>\n )}\n {isPinned && (\n <Icon\n name=\"lock\"\n size={12}\n color={tokens.colors.accent.primary}\n />\n )}\n </div>\n </div>\n </article>\n );\n }\n\n const labelStyle: React.CSSProperties = {\n color: tokens.colors.text.secondary, // WCAG AA compliant - 4.5:1 contrast\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n };\n\n const valueStyle: React.CSSProperties = {\n color: tokens.colors.text.primary,\n fontWeight: tokens.typography.fontWeight.medium,\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: \"tabular-nums\",\n marginTop: 2,\n };\n\n return (\n <article\n className={classNames(\"zendir-access-card\", className)}\n aria-label={`${spacecraftName ?? \"Spacecraft\"} access to ${groundStationName}`}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n ...(useGlassMode\n ? glassContainerStyle\n : {\n backgroundColor: cardBg,\n ...cardGlass,\n ...(tokens.colors.border.cardStyle ?? {}),\n }),\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.primary,\n fontSize: tokens.typography.fontSize.sm,\n }}\n >\n {/* Glass gradient overlay for bold/minimal themes */}\n {useGlassMode && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background:\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\n pointerEvents: \"none\",\n zIndex: 0,\n }}\n />\n )}\n\n {/* Unified Card Header - handles all theme variants */}\n <CardHeader\n icon=\"antenna-transmit\"\n title={groundStationName}\n subtitle={spacecraftName}\n status={statusLevel}\n badge={isAccessible ? \"Link\" : \"No Link\"}\n badgeColor={statusColor}\n />\n\n {/* Access Metrics */}\n <section\n style={{\n paddingTop: tokens.spacing.md,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n marginBottom: tokens.spacing.md,\n }}\n aria-label=\"Access metrics\"\n >\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(2, 1fr)\",\n gap: tokens.spacing.sm,\n }}\n >\n <div>\n <span style={labelStyle}>Elevation</span>\n <div\n style={{\n ...valueStyle,\n color:\n (access.elevation ?? 0) > 0\n ? tokens.colors.status.normal\n : tokens.colors.status.off,\n }}\n >\n {formatDegrees(access.elevation)}\n </div>\n </div>\n <div>\n <span style={labelStyle}>Azimuth</span>\n <div style={valueStyle}>{formatDegrees(access.azimuth)}</div>\n </div>\n <div>\n <span style={labelStyle}>Range</span>\n <div style={valueStyle}>{safeNumber(access.slantRange, 0)} km</div>\n </div>\n <div>\n <span style={labelStyle}>Signal</span>\n <div style={{ ...valueStyle, color: getStatusColor(signalStatus) }}>\n {safeNumber(access.signalStrength, 0, \"--\")}%\n </div>\n </div>\n </div>\n </section>\n\n {/* Link Budget */}\n {access.linkBudget && isAccessible && (\n <section\n style={{\n paddingTop: tokens.spacing.md,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n marginBottom: tokens.spacing.md,\n }}\n aria-label=\"Link budget\"\n >\n <h4\n style={{\n margin: `0 0 ${tokens.spacing.sm} 0`,\n ...labelStyle,\n }}\n >\n Link Budget\n </h4>\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(3, 1fr)\",\n gap: tokens.spacing.sm,\n }}\n >\n <div>\n <span style={labelStyle}>Rx Power</span>\n <div style={valueStyle}>\n {formatDecibels(access.linkBudget.receivedPower)}m\n </div>\n </div>\n <div>\n <span style={labelStyle}>SNR</span>\n <div style={valueStyle}>\n {formatDecibels(access.linkBudget.snr)}\n </div>\n </div>\n <div>\n <span style={labelStyle}>Data Rate</span>\n <div\n style={{\n ...valueStyle,\n color: safeAccentText(tokens.colors.accent.primary),\n }}\n >\n {formatDataRate(access.linkBudget.dataRate)}\n </div>\n </div>\n </div>\n </section>\n )}\n\n {/* Upcoming Windows */}\n {upcomingWindows.length > 0 && (\n <section aria-label=\"Upcoming passes\">\n <h4\n style={{\n margin: `0 0 ${tokens.spacing.sm} 0`,\n ...labelStyle,\n }}\n >\n Upcoming Passes\n </h4>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 4 }}>\n {upcomingWindows.slice(0, 3).map((window, idx) => (\n <div\n key={idx}\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n padding: tokens.spacing.sm,\n backgroundColor: tokens.colors.background.base,\n borderRadius: tokens.borderRadius.sm,\n }}\n >\n <div>\n <div\n style={{\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n fontFamily: tokens.typography.fontFamily.mono,\n }}\n >\n {formatTime(String(window.startTime ?? window.aos), false)}\n </div>\n <div\n style={{\n fontSize: tokens.typography.fontSize.xxs,\n color: tokens.colors.text.tertiary,\n }}\n >\n {formatDuration(window.duration ?? 0)}\n </div>\n </div>\n <div\n style={{\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.status.normal,\n fontFamily: tokens.typography.fontFamily.mono,\n }}\n >\n {safeNumber(window.maxElevation, 0)}° max\n </div>\n </div>\n ))}\n </div>\n </section>\n )}\n </article>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"AccessCard.js","names":[],"sources":["../../../src/react/cards/AccessCard.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - AccessCard Component\r\n *\r\n * Enterprise-grade access/link status card between spacecraft and ground station.\r\n *\r\n * AstroUXDS Compliance:\r\n * - Status colors used semantically for link/signal status\r\n * - Normal (green) = accessible, Off (grey) = no contact\r\n * - Signal strength uses status gradient (normal → caution → serious → critical)\r\n * - Zendir accent colors for decorative elements\r\n * - Tabular numbers for time/data display\r\n *\r\n * Features:\r\n * - Full null-safety with graceful fallbacks\r\n * - WCAG 2.1 AA accessibility\r\n * - Link budget display\r\n * - Upcoming pass windows\r\n * - Loading and empty states\r\n */\r\n\r\nimport React, { memo, useMemo } from \"react\";\r\nimport type { AccessData, AccessWindow } from \"../types\";\r\nimport { useTheme } from \"../theme\";\r\nimport { Icon } from \"../core/display/Icon\";\r\nimport { CardHeader } from \"../core/display/CardHeader\";\r\nimport { useCompactMode } from \"../hooks\";\r\nimport {\r\n safeNumber,\r\n formatDuration,\r\n formatTime,\r\n formatDataRate,\r\n formatDecibels,\r\n formatDegrees,\r\n classNames,\r\n getStatusColor,\r\n safeAccentText,\r\n type StatusLevel,\r\n} from \"../utils\";\r\n\r\nexport interface AccessCardProps {\r\n /** Current access data */\r\n access?: AccessData;\r\n /** Ground station name */\r\n groundStationName: string;\r\n /** Spacecraft name */\r\n spacecraftName?: string;\r\n /** Next access windows */\r\n upcomingWindows?: AccessWindow[];\r\n /** Loading state */\r\n loading?: boolean;\r\n /** Custom className */\r\n className?: string;\r\n /** Enable compact mode - shows condensed view that expands on hover/click */\r\n compact?: boolean;\r\n /** Start expanded when in compact mode (pinned state) */\r\n defaultExpanded?: boolean;\r\n /** Callback when pin state changes in compact mode */\r\n onPinChange?: (isPinned: boolean) => void;\r\n}\r\n\r\n/**\r\n * AccessCard - Displays spacecraft-ground station link status\r\n *\r\n * @example\r\n * ```tsx\r\n * <AccessCard\r\n * access={accessData}\r\n * groundStationName=\"Goldstone\"\r\n * spacecraftName=\"ISS\"\r\n * upcomingWindows={windows}\r\n * />\r\n * ```\r\n */\r\nexport const AccessCard = memo(function AccessCard({\r\n access,\r\n groundStationName,\r\n spacecraftName,\r\n upcomingWindows = [],\r\n loading = false,\r\n className = \"\",\r\n compact = false,\r\n defaultExpanded = false,\r\n onPinChange,\r\n}: AccessCardProps): React.ReactElement {\r\n const { tokens, theme, prefersReducedMotion } = useTheme();\r\n const isTransparentTheme =\r\n theme === \"transparent\" ||\r\n theme === \"transparent-bold\" ||\r\n theme === \"transparent-minimal\";\r\n const isBoldVariant = theme === \"transparent-bold\";\r\n const isMinimalVariant = theme === \"transparent-minimal\";\r\n const useGlassMode = isBoldVariant || isMinimalVariant;\r\n\r\n // Glass accent colors for bold/minimal themes (matching Container/AstroChart)\r\n const glassAccentColor = tokens.colors.accent.primary;\r\n const glassAccentMuted = `${glassAccentColor}66`;\r\n\r\n // Use transparent background with blur for transparent themes (matching Timeline)\r\n const cardBg = isTransparentTheme\r\n ? \"transparent\"\r\n : tokens.colors.background.surface;\r\n const cardGlass = isTransparentTheme\r\n ? {\r\n backdropFilter: \"blur(12px)\" as const,\r\n WebkitBackdropFilter: \"blur(12px)\" as const,\r\n }\r\n : {};\r\n\r\n // Glass mode container style (matching Container/AstroChart for bold/minimal)\r\n const glassContainerStyle: React.CSSProperties = useGlassMode\r\n ? {\r\n backgroundColor: \"rgba(10, 15, 25, 0.35)\",\r\n backdropFilter: \"blur(12px)\",\r\n WebkitBackdropFilter: \"blur(12px)\",\r\n border: `1px solid ${glassAccentMuted}`,\r\n borderTop: isBoldVariant\r\n ? `2px solid ${glassAccentColor}`\r\n : `1px solid ${glassAccentColor}`,\r\n }\r\n : {};\r\n\r\n // Compact mode state management\r\n const { expanded, isPinned, handlers, transitionDuration } = useCompactMode({\r\n compact,\r\n defaultExpanded,\r\n onPinChange,\r\n });\r\n\r\n // Computed status\r\n const isAccessible = access?.isAccessible ?? false;\r\n const statusLevel: StatusLevel = isAccessible ? \"normal\" : \"off\";\r\n const statusColor = getStatusColor(statusLevel);\r\n\r\n const signalStatus = useMemo((): StatusLevel => {\r\n const signal = access?.signalStrength;\r\n if (signal === undefined || signal === null) return \"off\";\r\n if (signal > 70) return \"normal\";\r\n if (signal > 40) return \"caution\";\r\n if (signal > 20) return \"serious\";\r\n return \"critical\";\r\n }, [access?.signalStrength]);\r\n\r\n // Loading state\r\n if (loading) {\r\n return (\r\n <div\r\n className={classNames(\"zendir-access-card\", \"loading\", className)}\r\n role=\"article\"\r\n aria-busy=\"true\"\r\n aria-label=\"Loading access data\"\r\n style={{\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...(tokens.colors.border.cardStyle ?? {}),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: tokens.spacing.md,\r\n minHeight: 180,\r\n }}\r\n >\r\n <div\r\n style={{\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n marginBottom: 16,\r\n }}\r\n >\r\n <div\r\n style={{\r\n height: 24,\r\n width: \"40%\",\r\n backgroundColor: \"rgba(255,255,255,0.1)\",\r\n borderRadius: 4,\r\n }}\r\n />\r\n <div\r\n style={{\r\n height: 24,\r\n width: 60,\r\n backgroundColor: \"rgba(255,255,255,0.1)\",\r\n borderRadius: 4,\r\n }}\r\n />\r\n </div>\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(2, 1fr)\",\r\n gap: 12,\r\n }}\r\n >\r\n {[1, 2, 3, 4].map((i) => (\r\n <div\r\n key={i}\r\n style={{\r\n height: 40,\r\n backgroundColor: \"rgba(255,255,255,0.06)\",\r\n borderRadius: 4,\r\n }}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Empty state\r\n if (!access) {\r\n return (\r\n <div\r\n className={classNames(\"zendir-access-card\", \"empty\", className)}\r\n role=\"article\"\r\n aria-label=\"No access data\"\r\n style={{\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...(tokens.colors.border.cardStyleDashed ?? {}),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: tokens.spacing.lg,\r\n textAlign: \"center\",\r\n color: tokens.colors.text.tertiary,\r\n }}\r\n >\r\n <svg\r\n width=\"32\"\r\n height=\"32\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"currentColor\"\r\n style={{ opacity: 0.5, marginBottom: 8 }}\r\n >\r\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\" />\r\n </svg>\r\n <p style={{ margin: 0, fontSize: tokens.typography.body[2].fontSize }}>\r\n {groundStationName}: No access data\r\n </p>\r\n </div>\r\n );\r\n }\r\n\r\n // Compact view - shows key access info in a single row\r\n if (compact && !expanded) {\r\n return (\r\n <article\r\n className={classNames(\"zendir-access-card\", \"compact\", className)}\r\n {...handlers}\r\n aria-label={`Access: ${groundStationName} (compact)`}\r\n style={{\r\n position: \"relative\",\r\n overflow: \"hidden\",\r\n ...(useGlassMode\r\n ? glassContainerStyle\r\n : {\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...(tokens.colors.border.cardStyle ?? {}),\r\n }),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n color: tokens.colors.text.primary,\r\n fontSize: tokens.typography.fontSize.sm,\r\n cursor: \"pointer\",\r\n transition: `all ${transitionDuration} ease-out`,\r\n transform: \"scale(1)\",\r\n }}\r\n onMouseEnter={(e) => {\r\n handlers.onMouseEnter();\r\n if (!prefersReducedMotion) {\r\n (e.currentTarget as HTMLElement).style.transform = \"scale(1.01)\";\r\n (e.currentTarget as HTMLElement).style.boxShadow =\r\n `0 4px 12px ${statusColor}20`;\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n handlers.onMouseLeave();\r\n (e.currentTarget as HTMLElement).style.transform = \"scale(1)\";\r\n (e.currentTarget as HTMLElement).style.boxShadow = \"\";\r\n }}\r\n >\r\n {/* Glass gradient overlay for bold/minimal themes */}\r\n {useGlassMode && (\r\n <div\r\n style={{\r\n position: \"absolute\",\r\n inset: 0,\r\n background:\r\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\r\n pointerEvents: \"none\",\r\n zIndex: 0,\r\n }}\r\n />\r\n )}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"space-between\",\r\n gap: tokens.spacing.md,\r\n position: \"relative\",\r\n zIndex: 1,\r\n }}\r\n >\r\n {/* Left side: Status indicator + Name + Accent line */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n flex: 1,\r\n minWidth: 0,\r\n }}\r\n >\r\n <div\r\n style={{\r\n width: 10,\r\n height: 10,\r\n borderRadius: \"50%\",\r\n backgroundColor: statusColor,\r\n boxShadow: isAccessible ? `0 0 6px ${statusColor}` : \"none\",\r\n flexShrink: 0,\r\n }}\r\n />\r\n <span\r\n style={{\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n color: useGlassMode ? glassAccentColor : undefined,\r\n textShadow: useGlassMode\r\n ? `0 0 16px ${glassAccentMuted}`\r\n : undefined,\r\n }}\r\n >\r\n {groundStationName.split(\" \")[0]}\r\n </span>\r\n {useGlassMode && (\r\n <div\r\n style={{\r\n flex: 1,\r\n height: isBoldVariant ? \"2px\" : \"1px\",\r\n minWidth: 20,\r\n background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`,\r\n boxShadow: isBoldVariant\r\n ? `0 0 8px ${glassAccentMuted}`\r\n : undefined,\r\n }}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Right side: Status badge + Signal strength + Pin */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n flexShrink: 0,\r\n }}\r\n >\r\n <span\r\n style={{\r\n color: statusColor,\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n {isAccessible ? \"AOS\" : \"LOS\"}\r\n </span>\r\n {access.signalStrength !== undefined && (\r\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 4 }}>\r\n <Icon\r\n name=\"antenna\"\r\n size={12}\r\n color={tokens.colors.text.secondary}\r\n />\r\n <span\r\n style={{\r\n fontVariantNumeric: \"tabular-nums\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontSize: tokens.typography.fontSize.xs,\r\n }}\r\n >\r\n {safeNumber(access.signalStrength, 0)}%\r\n </span>\r\n </div>\r\n )}\r\n {isPinned && (\r\n <Icon\r\n name=\"lock\"\r\n size={12}\r\n color={tokens.colors.accent.primary}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n </article>\r\n );\r\n }\r\n\r\n const labelStyle: React.CSSProperties = {\r\n color: tokens.colors.text.secondary, // WCAG AA compliant - 4.5:1 contrast\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n };\r\n\r\n const valueStyle: React.CSSProperties = {\r\n color: tokens.colors.text.primary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontVariantNumeric: \"tabular-nums\",\r\n marginTop: 2,\r\n };\r\n\r\n return (\r\n <article\r\n className={classNames(\"zendir-access-card\", className)}\r\n aria-label={`${spacecraftName ?? \"Spacecraft\"} access to ${groundStationName}`}\r\n style={{\r\n position: \"relative\",\r\n overflow: \"hidden\",\r\n ...(useGlassMode\r\n ? glassContainerStyle\r\n : {\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...(tokens.colors.border.cardStyle ?? {}),\r\n }),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: tokens.spacing.md,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n color: tokens.colors.text.primary,\r\n fontSize: tokens.typography.fontSize.sm,\r\n }}\r\n >\r\n {/* Glass gradient overlay for bold/minimal themes */}\r\n {useGlassMode && (\r\n <div\r\n style={{\r\n position: \"absolute\",\r\n inset: 0,\r\n background:\r\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\r\n pointerEvents: \"none\",\r\n zIndex: 0,\r\n }}\r\n />\r\n )}\r\n\r\n {/* Unified Card Header - handles all theme variants */}\r\n <CardHeader\r\n icon=\"antenna-transmit\"\r\n title={groundStationName}\r\n subtitle={spacecraftName}\r\n status={statusLevel}\r\n badge={isAccessible ? \"Link\" : \"No Link\"}\r\n badgeColor={statusColor}\r\n />\r\n\r\n {/* Access Metrics */}\r\n <section\r\n style={{\r\n paddingTop: tokens.spacing.md,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n marginBottom: tokens.spacing.md,\r\n }}\r\n aria-label=\"Access metrics\"\r\n >\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(2, 1fr)\",\r\n gap: tokens.spacing.sm,\r\n }}\r\n >\r\n <div>\r\n <span style={labelStyle}>Elevation</span>\r\n <div\r\n style={{\r\n ...valueStyle,\r\n color:\r\n (access.elevation ?? 0) > 0\r\n ? tokens.colors.status.normal\r\n : tokens.colors.status.off,\r\n }}\r\n >\r\n {formatDegrees(access.elevation)}\r\n </div>\r\n </div>\r\n <div>\r\n <span style={labelStyle}>Azimuth</span>\r\n <div style={valueStyle}>{formatDegrees(access.azimuth)}</div>\r\n </div>\r\n <div>\r\n <span style={labelStyle}>Range</span>\r\n <div style={valueStyle}>{safeNumber(access.slantRange, 0)} km</div>\r\n </div>\r\n <div>\r\n <span style={labelStyle}>Signal</span>\r\n <div style={{ ...valueStyle, color: getStatusColor(signalStatus) }}>\r\n {safeNumber(access.signalStrength, 0, \"--\")}%\r\n </div>\r\n </div>\r\n </div>\r\n </section>\r\n\r\n {/* Link Budget */}\r\n {access.linkBudget && isAccessible && (\r\n <section\r\n style={{\r\n paddingTop: tokens.spacing.md,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n marginBottom: tokens.spacing.md,\r\n }}\r\n aria-label=\"Link budget\"\r\n >\r\n <h4\r\n style={{\r\n margin: `0 0 ${tokens.spacing.sm} 0`,\r\n ...labelStyle,\r\n }}\r\n >\r\n Link Budget\r\n </h4>\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(3, 1fr)\",\r\n gap: tokens.spacing.sm,\r\n }}\r\n >\r\n <div>\r\n <span style={labelStyle}>Rx Power</span>\r\n <div style={valueStyle}>\r\n {formatDecibels(access.linkBudget.receivedPower)}m\r\n </div>\r\n </div>\r\n <div>\r\n <span style={labelStyle}>SNR</span>\r\n <div style={valueStyle}>\r\n {formatDecibels(access.linkBudget.snr)}\r\n </div>\r\n </div>\r\n <div>\r\n <span style={labelStyle}>Data Rate</span>\r\n <div\r\n style={{\r\n ...valueStyle,\r\n color: safeAccentText(tokens.colors.accent.primary),\r\n }}\r\n >\r\n {formatDataRate(access.linkBudget.dataRate)}\r\n </div>\r\n </div>\r\n </div>\r\n </section>\r\n )}\r\n\r\n {/* Upcoming Windows */}\r\n {upcomingWindows.length > 0 && (\r\n <section aria-label=\"Upcoming passes\">\r\n <h4\r\n style={{\r\n margin: `0 0 ${tokens.spacing.sm} 0`,\r\n ...labelStyle,\r\n }}\r\n >\r\n Upcoming Passes\r\n </h4>\r\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 4 }}>\r\n {upcomingWindows.slice(0, 3).map((window, idx) => (\r\n <div\r\n key={idx}\r\n style={{\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n alignItems: \"center\",\r\n padding: tokens.spacing.sm,\r\n backgroundColor: tokens.colors.background.base,\r\n borderRadius: tokens.borderRadius.sm,\r\n }}\r\n >\r\n <div>\r\n <div\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n }}\r\n >\r\n {formatTime(String(window.startTime ?? window.aos), false)}\r\n </div>\r\n <div\r\n style={{\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.tertiary,\r\n }}\r\n >\r\n {formatDuration(window.duration ?? 0)}\r\n </div>\r\n </div>\r\n <div\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.status.normal,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n }}\r\n >\r\n {safeNumber(window.maxElevation, 0)}° max\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n </section>\r\n )}\r\n </article>\r\n );\r\n});\r\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"OrbitCard.js","names":[],"sources":["../../../src/react/cards/OrbitCard.tsx"],"sourcesContent":["/**\n * @zendir/ui - OrbitCard Component\n *\n * Enterprise-grade orbital parameters display card.\n *\n * AstroUXDS Compliance:\n * - Orbit type colors use Zendir-Astro data viz palette (categorical, not status)\n * - Tabular numbers for orbital data display\n * - Sentence-case labels per Tier 3 compliance\n *\n * Features:\n * - Full null-safety with graceful fallbacks\n * - WCAG 2.1 AA accessibility\n * - Computed orbital parameters (period, velocity)\n * - Orbit type classification with Zendir-branded color coding\n * - Loading and empty states\n */\n\nimport React, { memo, useMemo } from \"react\";\nimport type { SpacecraftPosition } from \"../types\";\nimport { estimateOrbitalPeriod, estimateOrbitalVelocity } from \"../types\";\nimport { useTheme } from \"../theme\";\nimport { Icon } from \"../core/display/Icon\";\nimport { AstroIcon } from \"../core/display/AstroIcon\";\nimport { CardHeader } from \"../core/display/CardHeader\";\nimport { useCompactMode } from \"../hooks\";\nimport {\n formatAltitude,\n formatVelocity,\n formatDuration,\n formatCoordinate,\n formatDegrees,\n formatTime,\n classNames,\n safeAccentText,\n} from \"../utils\";\n\nexport interface OrbitCardProps {\n /** Spacecraft position data */\n spacecraft?: SpacecraftPosition;\n /** Show computed orbital parameters (period, velocity) */\n showComputed?: boolean;\n /** Loading state */\n loading?: boolean;\n /** Custom className */\n className?: string;\n /** Enable compact mode - shows condensed view that expands on hover/click */\n compact?: boolean;\n /** Start expanded when in compact mode (pinned state) */\n defaultExpanded?: boolean;\n /** Callback when pin state changes in compact mode */\n onPinChange?: (isPinned: boolean) => void;\n}\n\n/**\n * Orbit type information with color and description\n */\ninterface OrbitTypeInfo {\n color: string;\n description: string;\n}\n\n/**\n * Get orbit type info with Zendir-branded colors\n * Uses AstroUXDS data visualization palette for orbit classification\n */\nfunction getOrbitTypeInfo(orbitType: string | undefined): OrbitTypeInfo {\n // Orbit type colors using Zendir-Astro palette\n // Non-status colors since orbit type is categorical, not status\n const types: Record<string, OrbitTypeInfo> = {\n LEO: { color: \"#3E3CFF\", description: \"Low Earth Orbit (200-2,000 km)\" }, // Zendir Electric\n MEO: {\n color: \"#3548C0\",\n description: \"Medium Earth Orbit (2,000-35,786 km)\",\n }, // Zendir Prussian Blue Light\n GEO: { color: \"#9D70FF\", description: \"Geostationary Orbit (~35,786 km)\" }, // Zendir Purple\n HEO: { color: \"#1B2DA0\", description: \"Highly Elliptical Orbit\" }, // Zendir Prussian Blue\n SSO: { color: \"#B48DFF\", description: \"Sun-Synchronous Orbit\" }, // Zendir Purple Light\n POLAR: { color: \"#6B69FF\", description: \"Polar Orbit\" }, // Zendir Electric Light\n MOLNIYA: { color: \"#C9A8FF\", description: \"Molniya Orbit (12h period)\" }, // Zendir Purple Lighter\n };\n\n return (\n types[orbitType?.toUpperCase() ?? \"\"] ?? {\n color: \"#a4abb6\",\n description: \"Unknown orbit type\",\n }\n );\n}\n\n/**\n * OrbitCard - Displays spacecraft orbital parameters\n *\n * @example\n * ```tsx\n * <OrbitCard\n * spacecraft={spacecraftData}\n * showComputed\n * />\n * ```\n */\nexport const OrbitCard = memo(function OrbitCard({\n spacecraft,\n showComputed = true,\n loading = false,\n className = \"\",\n compact = false,\n defaultExpanded = false,\n onPinChange,\n}: OrbitCardProps): React.ReactElement {\n const { tokens, theme, prefersReducedMotion } = useTheme();\n const isTransparentTheme =\n theme === \"transparent\" ||\n theme === \"transparent-bold\" ||\n theme === \"transparent-minimal\";\n const isBoldVariant = theme === \"transparent-bold\";\n const isMinimalVariant = theme === \"transparent-minimal\";\n const useGlassMode = isBoldVariant || isMinimalVariant;\n\n // Glass accent colors for bold/minimal themes (matching Container/AstroChart)\n const glassAccentColor = tokens.colors.accent.primary;\n const glassAccentMuted = `${glassAccentColor}66`;\n\n // Use transparent background with blur for transparent themes (matching Timeline)\n const cardBg = isTransparentTheme\n ? \"transparent\"\n : tokens.colors.background.surface;\n const cardGlass = isTransparentTheme\n ? {\n backdropFilter: \"blur(12px)\" as const,\n WebkitBackdropFilter: \"blur(12px)\" as const,\n }\n : {};\n\n // Glass mode container style (matching Container/AstroChart for bold/minimal)\n const glassContainerStyle: React.CSSProperties = useGlassMode\n ? {\n backgroundColor: \"rgba(10, 15, 25, 0.35)\",\n backdropFilter: \"blur(12px)\",\n WebkitBackdropFilter: \"blur(12px)\",\n border: `1px solid ${glassAccentMuted}`,\n borderTop: isBoldVariant\n ? `2px solid ${glassAccentColor}`\n : `1px solid ${glassAccentColor}`,\n }\n : {};\n\n // Compact mode state management\n const { expanded, isPinned, handlers, transitionDuration } = useCompactMode({\n compact,\n defaultExpanded,\n onPinChange,\n });\n\n // Computed orbital parameters\n const orbitInfo = useMemo(\n () => getOrbitTypeInfo(spacecraft?.orbitType),\n [spacecraft?.orbitType],\n );\n\n const computedPeriod = useMemo(() => {\n if (!spacecraft?.altitude) return null;\n try {\n return estimateOrbitalPeriod(spacecraft.altitude);\n } catch {\n return null;\n }\n }, [spacecraft?.altitude]);\n\n const computedVelocity = useMemo(() => {\n if (!spacecraft?.altitude) return null;\n try {\n return estimateOrbitalVelocity(spacecraft.altitude);\n } catch {\n return null;\n }\n }, [spacecraft?.altitude]);\n\n // Loading state\n if (loading) {\n return (\n <div\n className={classNames(\"zendir-orbit-card\", \"loading\", className)}\n role=\"article\"\n aria-busy=\"true\"\n aria-label=\"Loading orbit data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n ...(tokens.colors.border.cardStyle ?? {}),\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n minHeight: 200,\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n marginBottom: 20,\n }}\n >\n <div\n style={{\n width: 40,\n height: 40,\n borderRadius: 8,\n backgroundColor: \"rgba(255,255,255,0.1)\",\n }}\n />\n <div style={{ flex: 1 }}>\n <div\n style={{\n height: 18,\n width: \"50%\",\n backgroundColor: \"rgba(255,255,255,0.1)\",\n borderRadius: 4,\n }}\n />\n <div\n style={{\n height: 12,\n width: \"70%\",\n backgroundColor: \"rgba(255,255,255,0.06)\",\n borderRadius: 4,\n marginTop: 6,\n }}\n />\n </div>\n </div>\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(2, 1fr)\",\n gap: 16,\n }}\n >\n {[1, 2, 3, 4].map((i) => (\n <div key={i}>\n <div\n style={{\n height: 10,\n width: \"40%\",\n backgroundColor: \"rgba(255,255,255,0.06)\",\n borderRadius: 2,\n }}\n />\n <div\n style={{\n height: 20,\n width: \"60%\",\n backgroundColor: \"rgba(255,255,255,0.1)\",\n borderRadius: 4,\n marginTop: 4,\n }}\n />\n </div>\n ))}\n </div>\n </div>\n );\n }\n\n // Empty state\n if (!spacecraft) {\n return (\n <div\n className={classNames(\"zendir-orbit-card\", \"empty\", className)}\n role=\"article\"\n aria-label=\"No orbit data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n ...(tokens.colors.border.cardStyleDashed ?? {}),\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.lg,\n textAlign: \"center\",\n color: tokens.colors.text.tertiary,\n }}\n >\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n style={{ opacity: 0.5, marginBottom: 8 }}\n >\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z\" />\n <ellipse\n cx=\"12\"\n cy=\"12\"\n rx=\"10\"\n ry=\"4\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1\"\n strokeDasharray=\"3,3\"\n />\n </svg>\n <p style={{ margin: 0, fontSize: tokens.typography.body[2].fontSize }}>\n No orbit data available\n </p>\n </div>\n );\n }\n\n // Compact view - shows key orbit info in a single row\n if (compact && !expanded) {\n return (\n <article\n className={classNames(\"zendir-orbit-card\", \"compact\", className)}\n {...handlers}\n aria-label={`Orbit: ${spacecraft.orbitType ?? \"Unknown\"} (compact)`}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n ...(useGlassMode\n ? glassContainerStyle\n : {\n backgroundColor: cardBg,\n ...cardGlass,\n ...(tokens.colors.border.cardStyle ?? {}),\n }),\n borderRadius: tokens.borderRadius.lg,\n padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.primary,\n fontSize: tokens.typography.fontSize.sm,\n cursor: \"pointer\",\n transition: `all ${transitionDuration} ease-out`,\n transform: \"scale(1)\",\n }}\n onMouseEnter={(e) => {\n handlers.onMouseEnter();\n if (!prefersReducedMotion) {\n (e.currentTarget as HTMLElement).style.transform = \"scale(1.01)\";\n (e.currentTarget as HTMLElement).style.boxShadow =\n `0 4px 12px ${orbitInfo.color}20`;\n }\n }}\n onMouseLeave={(e) => {\n handlers.onMouseLeave();\n (e.currentTarget as HTMLElement).style.transform = \"scale(1)\";\n (e.currentTarget as HTMLElement).style.boxShadow = \"\";\n }}\n >\n {/* Glass gradient overlay for bold/minimal themes */}\n {useGlassMode && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background:\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\n pointerEvents: \"none\",\n zIndex: 0,\n }}\n />\n )}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n gap: tokens.spacing.md,\n position: \"relative\",\n zIndex: 1,\n }}\n >\n {/* Left side: Icon + Title + Accent line */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n flex: 1,\n minWidth: 0,\n }}\n >\n <AstroIcon name=\"360\" size={16} color={orbitInfo.color} />\n <span\n style={{\n fontWeight: tokens.typography.fontWeight.medium,\n color: useGlassMode ? glassAccentColor : undefined,\n textShadow: useGlassMode\n ? `0 0 16px ${glassAccentMuted}`\n : undefined,\n }}\n >\n Orbit\n </span>\n {useGlassMode && (\n <div\n style={{\n flex: 1,\n height: isBoldVariant ? \"2px\" : \"1px\",\n minWidth: 20,\n background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`,\n boxShadow: isBoldVariant\n ? `0 0 8px ${glassAccentMuted}`\n : undefined,\n }}\n />\n )}\n </div>\n\n {/* Right side: Orbit badge + Altitude + Pin */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n flexShrink: 0,\n }}\n >\n <span\n style={{\n backgroundColor: `${orbitInfo.color}20`,\n color: orbitInfo.color,\n padding: `2px 6px`,\n borderRadius: tokens.borderRadius.sm,\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n }}\n >\n {spacecraft.orbitType ?? \"—\"}\n </span>\n <span\n style={{\n fontVariantNumeric: \"tabular-nums\",\n fontFamily: tokens.typography.fontFamily.mono,\n fontSize: tokens.typography.fontSize.xs,\n }}\n >\n {formatAltitude(spacecraft.altitude)}\n </span>\n {isPinned && (\n <Icon\n name=\"lock\"\n size={12}\n color={tokens.colors.accent.primary}\n />\n )}\n </div>\n </div>\n </article>\n );\n }\n\n const labelStyle: React.CSSProperties = {\n color: tokens.colors.text.secondary, // WCAG AA compliant - 4.5:1 contrast\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n };\n\n const valueStyle: React.CSSProperties = {\n color: tokens.colors.text.primary,\n fontWeight: tokens.typography.fontWeight.medium,\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: \"tabular-nums\",\n fontSize: tokens.typography.fontSize.md,\n marginTop: 2,\n };\n\n return (\n <article\n className={classNames(\n \"zendir-orbit-card\",\n compact ? \"expanded\" : \"\",\n className,\n )}\n {...(compact ? handlers : {})}\n role={compact ? handlers.role : \"article\"}\n tabIndex={compact ? handlers.tabIndex : undefined}\n aria-expanded={compact ? handlers[\"aria-expanded\"] : undefined}\n aria-label={`Orbit data for ${spacecraft.name ?? spacecraft.id}`}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n ...(useGlassMode\n ? glassContainerStyle\n : {\n backgroundColor: cardBg,\n ...cardGlass,\n ...(tokens.colors.border.cardStyle ?? {}),\n }),\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n fontFamily: tokens.typography.fontFamily.primary,\n cursor: compact ? \"pointer\" : undefined,\n transition: compact ? `all ${transitionDuration} ease-out` : undefined,\n color: tokens.colors.text.primary,\n fontSize: tokens.typography.fontSize.sm,\n }}\n >\n {/* Glass gradient overlay for bold/minimal themes */}\n {useGlassMode && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background:\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\n pointerEvents: \"none\",\n zIndex: 0,\n }}\n />\n )}\n\n {/* Unified Card Header - handles all theme variants */}\n {/* OrbitCard uses categorical colors (orbit type), not status colors */}\n <CardHeader\n icon=\"360\"\n title={spacecraft.name ?? spacecraft.id ?? \"Unknown\"}\n subtitle={orbitInfo.description}\n badge={spacecraft.orbitType ?? \"ORBIT\"}\n badgeColor={orbitInfo.color}\n iconColor={orbitInfo.color}\n hideStatusIndicator\n />\n\n {/* Orbital Parameters */}\n <section aria-label=\"Orbital parameters\">\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(2, 1fr)\",\n gap: tokens.spacing.md,\n }}\n >\n <div>\n <span style={labelStyle}>Altitude</span>\n <div\n style={{\n ...valueStyle,\n color: safeAccentText(tokens.colors.accent.primary),\n }}\n >\n {formatAltitude(spacecraft.altitude)}\n </div>\n </div>\n <div>\n <span style={labelStyle}>Velocity</span>\n <div style={valueStyle}>\n {spacecraft.velocity\n ? formatVelocity(spacecraft.velocity)\n : computedVelocity\n ? formatVelocity(computedVelocity)\n : \"-- km/s\"}\n </div>\n </div>\n {spacecraft.inclination !== undefined && (\n <div>\n <span style={labelStyle}>Inclination</span>\n <div style={valueStyle}>\n {formatDegrees(spacecraft.inclination)}\n </div>\n </div>\n )}\n {showComputed && computedPeriod !== null && (\n <div>\n <span style={labelStyle}>Period</span>\n <div style={valueStyle}>{formatDuration(computedPeriod)}</div>\n </div>\n )}\n </div>\n </section>\n\n {/* Current Position */}\n <section\n style={{\n marginTop: tokens.spacing.lg,\n paddingTop: tokens.spacing.lg,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n }}\n aria-label=\"Current position\"\n >\n <h4\n style={{\n margin: `0 0 ${tokens.spacing.sm} 0`,\n ...labelStyle,\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n }}\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z\" />\n </svg>\n Current Position\n </h4>\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(2, 1fr)\",\n gap: tokens.spacing.md,\n }}\n >\n <div>\n <span style={labelStyle}>Latitude</span>\n <div style={valueStyle}>\n {formatCoordinate(spacecraft.latitude, \"lat\")}\n </div>\n </div>\n <div>\n <span style={labelStyle}>Longitude</span>\n <div style={valueStyle}>\n {formatCoordinate(spacecraft.longitude, \"lon\")}\n </div>\n </div>\n </div>\n </section>\n\n {/* Timestamp */}\n {spacecraft.timestamp && (\n <footer\n style={{\n marginTop: tokens.spacing.md,\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n textAlign: \"right\",\n }}\n >\n <time dateTime={spacecraft.timestamp}>\n {formatTime(spacecraft.timestamp)} UTC\n </time>\n </footer>\n )}\n </article>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"OrbitCard.js","names":[],"sources":["../../../src/react/cards/OrbitCard.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - OrbitCard Component\r\n *\r\n * Enterprise-grade orbital parameters display card.\r\n *\r\n * AstroUXDS Compliance:\r\n * - Orbit type colors use Zendir-Astro data viz palette (categorical, not status)\r\n * - Tabular numbers for orbital data display\r\n * - Sentence-case labels per Tier 3 compliance\r\n *\r\n * Features:\r\n * - Full null-safety with graceful fallbacks\r\n * - WCAG 2.1 AA accessibility\r\n * - Computed orbital parameters (period, velocity)\r\n * - Orbit type classification with Zendir-branded color coding\r\n * - Loading and empty states\r\n */\r\n\r\nimport React, { memo, useMemo } from \"react\";\r\nimport type { SpacecraftPosition } from \"../types\";\r\nimport { estimateOrbitalPeriod, estimateOrbitalVelocity } from \"../types\";\r\nimport { useTheme } from \"../theme\";\r\nimport { Icon } from \"../core/display/Icon\";\r\nimport { AstroIcon } from \"../core/display/AstroIcon\";\r\nimport { CardHeader } from \"../core/display/CardHeader\";\r\nimport { useCompactMode } from \"../hooks\";\r\nimport {\r\n formatAltitude,\r\n formatVelocity,\r\n formatDuration,\r\n formatCoordinate,\r\n formatDegrees,\r\n formatTime,\r\n classNames,\r\n safeAccentText,\r\n} from \"../utils\";\r\n\r\nexport interface OrbitCardProps {\r\n /** Spacecraft position data */\r\n spacecraft?: SpacecraftPosition;\r\n /** Show computed orbital parameters (period, velocity) */\r\n showComputed?: boolean;\r\n /** Loading state */\r\n loading?: boolean;\r\n /** Custom className */\r\n className?: string;\r\n /** Enable compact mode - shows condensed view that expands on hover/click */\r\n compact?: boolean;\r\n /** Start expanded when in compact mode (pinned state) */\r\n defaultExpanded?: boolean;\r\n /** Callback when pin state changes in compact mode */\r\n onPinChange?: (isPinned: boolean) => void;\r\n}\r\n\r\n/**\r\n * Orbit type information with color and description\r\n */\r\ninterface OrbitTypeInfo {\r\n color: string;\r\n description: string;\r\n}\r\n\r\n/**\r\n * Get orbit type info with Zendir-branded colors\r\n * Uses AstroUXDS data visualization palette for orbit classification\r\n */\r\nfunction getOrbitTypeInfo(orbitType: string | undefined): OrbitTypeInfo {\r\n // Orbit type colors using Zendir-Astro palette\r\n // Non-status colors since orbit type is categorical, not status\r\n const types: Record<string, OrbitTypeInfo> = {\r\n LEO: { color: \"#3E3CFF\", description: \"Low Earth Orbit (200-2,000 km)\" }, // Zendir Electric\r\n MEO: {\r\n color: \"#3548C0\",\r\n description: \"Medium Earth Orbit (2,000-35,786 km)\",\r\n }, // Zendir Prussian Blue Light\r\n GEO: { color: \"#9D70FF\", description: \"Geostationary Orbit (~35,786 km)\" }, // Zendir Purple\r\n HEO: { color: \"#1B2DA0\", description: \"Highly Elliptical Orbit\" }, // Zendir Prussian Blue\r\n SSO: { color: \"#B48DFF\", description: \"Sun-Synchronous Orbit\" }, // Zendir Purple Light\r\n POLAR: { color: \"#6B69FF\", description: \"Polar Orbit\" }, // Zendir Electric Light\r\n MOLNIYA: { color: \"#C9A8FF\", description: \"Molniya Orbit (12h period)\" }, // Zendir Purple Lighter\r\n };\r\n\r\n return (\r\n types[orbitType?.toUpperCase() ?? \"\"] ?? {\r\n color: \"#a4abb6\",\r\n description: \"Unknown orbit type\",\r\n }\r\n );\r\n}\r\n\r\n/**\r\n * OrbitCard - Displays spacecraft orbital parameters\r\n *\r\n * @example\r\n * ```tsx\r\n * <OrbitCard\r\n * spacecraft={spacecraftData}\r\n * showComputed\r\n * />\r\n * ```\r\n */\r\nexport const OrbitCard = memo(function OrbitCard({\r\n spacecraft,\r\n showComputed = true,\r\n loading = false,\r\n className = \"\",\r\n compact = false,\r\n defaultExpanded = false,\r\n onPinChange,\r\n}: OrbitCardProps): React.ReactElement {\r\n const { tokens, theme, prefersReducedMotion } = useTheme();\r\n const isTransparentTheme =\r\n theme === \"transparent\" ||\r\n theme === \"transparent-bold\" ||\r\n theme === \"transparent-minimal\";\r\n const isBoldVariant = theme === \"transparent-bold\";\r\n const isMinimalVariant = theme === \"transparent-minimal\";\r\n const useGlassMode = isBoldVariant || isMinimalVariant;\r\n\r\n // Glass accent colors for bold/minimal themes (matching Container/AstroChart)\r\n const glassAccentColor = tokens.colors.accent.primary;\r\n const glassAccentMuted = `${glassAccentColor}66`;\r\n\r\n // Use transparent background with blur for transparent themes (matching Timeline)\r\n const cardBg = isTransparentTheme\r\n ? \"transparent\"\r\n : tokens.colors.background.surface;\r\n const cardGlass = isTransparentTheme\r\n ? {\r\n backdropFilter: \"blur(12px)\" as const,\r\n WebkitBackdropFilter: \"blur(12px)\" as const,\r\n }\r\n : {};\r\n\r\n // Glass mode container style (matching Container/AstroChart for bold/minimal)\r\n const glassContainerStyle: React.CSSProperties = useGlassMode\r\n ? {\r\n backgroundColor: \"rgba(10, 15, 25, 0.35)\",\r\n backdropFilter: \"blur(12px)\",\r\n WebkitBackdropFilter: \"blur(12px)\",\r\n border: `1px solid ${glassAccentMuted}`,\r\n borderTop: isBoldVariant\r\n ? `2px solid ${glassAccentColor}`\r\n : `1px solid ${glassAccentColor}`,\r\n }\r\n : {};\r\n\r\n // Compact mode state management\r\n const { expanded, isPinned, handlers, transitionDuration } = useCompactMode({\r\n compact,\r\n defaultExpanded,\r\n onPinChange,\r\n });\r\n\r\n // Computed orbital parameters\r\n const orbitInfo = useMemo(\r\n () => getOrbitTypeInfo(spacecraft?.orbitType),\r\n [spacecraft?.orbitType],\r\n );\r\n\r\n const computedPeriod = useMemo(() => {\r\n if (!spacecraft?.altitude) return null;\r\n try {\r\n return estimateOrbitalPeriod(spacecraft.altitude);\r\n } catch {\r\n return null;\r\n }\r\n }, [spacecraft?.altitude]);\r\n\r\n const computedVelocity = useMemo(() => {\r\n if (!spacecraft?.altitude) return null;\r\n try {\r\n return estimateOrbitalVelocity(spacecraft.altitude);\r\n } catch {\r\n return null;\r\n }\r\n }, [spacecraft?.altitude]);\r\n\r\n // Loading state\r\n if (loading) {\r\n return (\r\n <div\r\n className={classNames(\"zendir-orbit-card\", \"loading\", className)}\r\n role=\"article\"\r\n aria-busy=\"true\"\r\n aria-label=\"Loading orbit data\"\r\n style={{\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...(tokens.colors.border.cardStyle ?? {}),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: tokens.spacing.md,\r\n minHeight: 200,\r\n }}\r\n >\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 12,\r\n marginBottom: 20,\r\n }}\r\n >\r\n <div\r\n style={{\r\n width: 40,\r\n height: 40,\r\n borderRadius: 8,\r\n backgroundColor: \"rgba(255,255,255,0.1)\",\r\n }}\r\n />\r\n <div style={{ flex: 1 }}>\r\n <div\r\n style={{\r\n height: 18,\r\n width: \"50%\",\r\n backgroundColor: \"rgba(255,255,255,0.1)\",\r\n borderRadius: 4,\r\n }}\r\n />\r\n <div\r\n style={{\r\n height: 12,\r\n width: \"70%\",\r\n backgroundColor: \"rgba(255,255,255,0.06)\",\r\n borderRadius: 4,\r\n marginTop: 6,\r\n }}\r\n />\r\n </div>\r\n </div>\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(2, 1fr)\",\r\n gap: 16,\r\n }}\r\n >\r\n {[1, 2, 3, 4].map((i) => (\r\n <div key={i}>\r\n <div\r\n style={{\r\n height: 10,\r\n width: \"40%\",\r\n backgroundColor: \"rgba(255,255,255,0.06)\",\r\n borderRadius: 2,\r\n }}\r\n />\r\n <div\r\n style={{\r\n height: 20,\r\n width: \"60%\",\r\n backgroundColor: \"rgba(255,255,255,0.1)\",\r\n borderRadius: 4,\r\n marginTop: 4,\r\n }}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n // Empty state\r\n if (!spacecraft) {\r\n return (\r\n <div\r\n className={classNames(\"zendir-orbit-card\", \"empty\", className)}\r\n role=\"article\"\r\n aria-label=\"No orbit data\"\r\n style={{\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...(tokens.colors.border.cardStyleDashed ?? {}),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: tokens.spacing.lg,\r\n textAlign: \"center\",\r\n color: tokens.colors.text.tertiary,\r\n }}\r\n >\r\n <svg\r\n width=\"32\"\r\n height=\"32\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"currentColor\"\r\n style={{ opacity: 0.5, marginBottom: 8 }}\r\n >\r\n <path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z\" />\r\n <ellipse\r\n cx=\"12\"\r\n cy=\"12\"\r\n rx=\"10\"\r\n ry=\"4\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1\"\r\n strokeDasharray=\"3,3\"\r\n />\r\n </svg>\r\n <p style={{ margin: 0, fontSize: tokens.typography.body[2].fontSize }}>\r\n No orbit data available\r\n </p>\r\n </div>\r\n );\r\n }\r\n\r\n // Compact view - shows key orbit info in a single row\r\n if (compact && !expanded) {\r\n return (\r\n <article\r\n className={classNames(\"zendir-orbit-card\", \"compact\", className)}\r\n {...handlers}\r\n aria-label={`Orbit: ${spacecraft.orbitType ?? \"Unknown\"} (compact)`}\r\n style={{\r\n position: \"relative\",\r\n overflow: \"hidden\",\r\n ...(useGlassMode\r\n ? glassContainerStyle\r\n : {\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...(tokens.colors.border.cardStyle ?? {}),\r\n }),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.md}`,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n color: tokens.colors.text.primary,\r\n fontSize: tokens.typography.fontSize.sm,\r\n cursor: \"pointer\",\r\n transition: `all ${transitionDuration} ease-out`,\r\n transform: \"scale(1)\",\r\n }}\r\n onMouseEnter={(e) => {\r\n handlers.onMouseEnter();\r\n if (!prefersReducedMotion) {\r\n (e.currentTarget as HTMLElement).style.transform = \"scale(1.01)\";\r\n (e.currentTarget as HTMLElement).style.boxShadow =\r\n `0 4px 12px ${orbitInfo.color}20`;\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n handlers.onMouseLeave();\r\n (e.currentTarget as HTMLElement).style.transform = \"scale(1)\";\r\n (e.currentTarget as HTMLElement).style.boxShadow = \"\";\r\n }}\r\n >\r\n {/* Glass gradient overlay for bold/minimal themes */}\r\n {useGlassMode && (\r\n <div\r\n style={{\r\n position: \"absolute\",\r\n inset: 0,\r\n background:\r\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\r\n pointerEvents: \"none\",\r\n zIndex: 0,\r\n }}\r\n />\r\n )}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"space-between\",\r\n gap: tokens.spacing.md,\r\n position: \"relative\",\r\n zIndex: 1,\r\n }}\r\n >\r\n {/* Left side: Icon + Title + Accent line */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n flex: 1,\r\n minWidth: 0,\r\n }}\r\n >\r\n <AstroIcon name=\"360\" size={16} color={orbitInfo.color} />\r\n <span\r\n style={{\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n color: useGlassMode ? glassAccentColor : undefined,\r\n textShadow: useGlassMode\r\n ? `0 0 16px ${glassAccentMuted}`\r\n : undefined,\r\n }}\r\n >\r\n Orbit\r\n </span>\r\n {useGlassMode && (\r\n <div\r\n style={{\r\n flex: 1,\r\n height: isBoldVariant ? \"2px\" : \"1px\",\r\n minWidth: 20,\r\n background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`,\r\n boxShadow: isBoldVariant\r\n ? `0 0 8px ${glassAccentMuted}`\r\n : undefined,\r\n }}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Right side: Orbit badge + Altitude + Pin */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n flexShrink: 0,\r\n }}\r\n >\r\n <span\r\n style={{\r\n backgroundColor: `${orbitInfo.color}20`,\r\n color: orbitInfo.color,\r\n padding: `2px 6px`,\r\n borderRadius: tokens.borderRadius.sm,\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n {spacecraft.orbitType ?? \"—\"}\r\n </span>\r\n <span\r\n style={{\r\n fontVariantNumeric: \"tabular-nums\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontSize: tokens.typography.fontSize.xs,\r\n }}\r\n >\r\n {formatAltitude(spacecraft.altitude)}\r\n </span>\r\n {isPinned && (\r\n <Icon\r\n name=\"lock\"\r\n size={12}\r\n color={tokens.colors.accent.primary}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n </article>\r\n );\r\n }\r\n\r\n const labelStyle: React.CSSProperties = {\r\n color: tokens.colors.text.secondary, // WCAG AA compliant - 4.5:1 contrast\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n };\r\n\r\n const valueStyle: React.CSSProperties = {\r\n color: tokens.colors.text.primary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontVariantNumeric: \"tabular-nums\",\r\n fontSize: tokens.typography.fontSize.md,\r\n marginTop: 2,\r\n };\r\n\r\n return (\r\n <article\r\n className={classNames(\r\n \"zendir-orbit-card\",\r\n compact ? \"expanded\" : \"\",\r\n className,\r\n )}\r\n {...(compact ? handlers : {})}\r\n role={compact ? handlers.role : \"article\"}\r\n tabIndex={compact ? handlers.tabIndex : undefined}\r\n aria-expanded={compact ? handlers[\"aria-expanded\"] : undefined}\r\n aria-label={`Orbit data for ${spacecraft.name ?? spacecraft.id}`}\r\n style={{\r\n position: \"relative\",\r\n overflow: \"hidden\",\r\n ...(useGlassMode\r\n ? glassContainerStyle\r\n : {\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...(tokens.colors.border.cardStyle ?? {}),\r\n }),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: tokens.spacing.md,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n cursor: compact ? \"pointer\" : undefined,\r\n transition: compact ? `all ${transitionDuration} ease-out` : undefined,\r\n color: tokens.colors.text.primary,\r\n fontSize: tokens.typography.fontSize.sm,\r\n }}\r\n >\r\n {/* Glass gradient overlay for bold/minimal themes */}\r\n {useGlassMode && (\r\n <div\r\n style={{\r\n position: \"absolute\",\r\n inset: 0,\r\n background:\r\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\r\n pointerEvents: \"none\",\r\n zIndex: 0,\r\n }}\r\n />\r\n )}\r\n\r\n {/* Unified Card Header - handles all theme variants */}\r\n {/* OrbitCard uses categorical colors (orbit type), not status colors */}\r\n <CardHeader\r\n icon=\"360\"\r\n title={spacecraft.name ?? spacecraft.id ?? \"Unknown\"}\r\n subtitle={orbitInfo.description}\r\n badge={spacecraft.orbitType ?? \"ORBIT\"}\r\n badgeColor={orbitInfo.color}\r\n iconColor={orbitInfo.color}\r\n hideStatusIndicator\r\n />\r\n\r\n {/* Orbital Parameters */}\r\n <section aria-label=\"Orbital parameters\">\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(2, 1fr)\",\r\n gap: tokens.spacing.md,\r\n }}\r\n >\r\n <div>\r\n <span style={labelStyle}>Altitude</span>\r\n <div\r\n style={{\r\n ...valueStyle,\r\n color: safeAccentText(tokens.colors.accent.primary),\r\n }}\r\n >\r\n {formatAltitude(spacecraft.altitude)}\r\n </div>\r\n </div>\r\n <div>\r\n <span style={labelStyle}>Velocity</span>\r\n <div style={valueStyle}>\r\n {spacecraft.velocity\r\n ? formatVelocity(spacecraft.velocity)\r\n : computedVelocity\r\n ? formatVelocity(computedVelocity)\r\n : \"-- km/s\"}\r\n </div>\r\n </div>\r\n {spacecraft.inclination !== undefined && (\r\n <div>\r\n <span style={labelStyle}>Inclination</span>\r\n <div style={valueStyle}>\r\n {formatDegrees(spacecraft.inclination)}\r\n </div>\r\n </div>\r\n )}\r\n {showComputed && computedPeriod !== null && (\r\n <div>\r\n <span style={labelStyle}>Period</span>\r\n <div style={valueStyle}>{formatDuration(computedPeriod)}</div>\r\n </div>\r\n )}\r\n </div>\r\n </section>\r\n\r\n {/* Current Position */}\r\n <section\r\n style={{\r\n marginTop: tokens.spacing.lg,\r\n paddingTop: tokens.spacing.lg,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n }}\r\n aria-label=\"Current position\"\r\n >\r\n <h4\r\n style={{\r\n margin: `0 0 ${tokens.spacing.sm} 0`,\r\n ...labelStyle,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n }}\r\n >\r\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\r\n <path d=\"M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z\" />\r\n </svg>\r\n Current Position\r\n </h4>\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(2, 1fr)\",\r\n gap: tokens.spacing.md,\r\n }}\r\n >\r\n <div>\r\n <span style={labelStyle}>Latitude</span>\r\n <div style={valueStyle}>\r\n {formatCoordinate(spacecraft.latitude, \"lat\")}\r\n </div>\r\n </div>\r\n <div>\r\n <span style={labelStyle}>Longitude</span>\r\n <div style={valueStyle}>\r\n {formatCoordinate(spacecraft.longitude, \"lon\")}\r\n </div>\r\n </div>\r\n </div>\r\n </section>\r\n\r\n {/* Timestamp */}\r\n {spacecraft.timestamp && (\r\n <footer\r\n style={{\r\n marginTop: tokens.spacing.md,\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n <time dateTime={spacecraft.timestamp}>\r\n {formatTime(spacecraft.timestamp)} UTC\r\n </time>\r\n </footer>\r\n )}\r\n </article>\r\n );\r\n});\r\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SpacecraftCard.js","names":[],"sources":["../../../src/react/cards/SpacecraftCard.tsx"],"sourcesContent":["/**\n * @zendir/ui - SpacecraftCard Component\n *\n * Enterprise-grade spacecraft information card.\n *\n * AstroUXDS Compliance:\n * - Status colors used for health/operational status only\n * - Orbit type uses Zendir-Astro data viz colors (categorical)\n * - Zendir accent colors for interactive elements\n * - Tabular numbers with fontVariantNumeric for data\n * - Sentence-case labels per Tier 3 compliance\n *\n * Features:\n * - Full null-safety with graceful fallbacks\n * - WCAG 2.1 AA accessibility\n * - Keyboard navigation\n * - Smooth animations with reduced-motion support\n * - Loading skeleton state\n * - Error boundary support\n * - Real SDK integration via optional client prop\n */\n\nimport React, { memo, useCallback, useMemo } from \"react\";\nimport type { SpacecraftPosition, TelemetryData } from \"../types\";\nimport { useTheme } from \"../theme\";\nimport { Icon, type IconName } from \"../core/display/Icon\";\nimport { CardHeader } from \"../core/display/CardHeader\";\nimport { HeaderIconWithStatus } from \"../core/display/HeaderIconWithStatus\";\nimport { useCompactMode } from \"../hooks\";\nimport { useCardBorderStyle } from \"../context/DisplaySettingsContext\";\n\n// ZendirClient is optional - only used when SDK is installed\ntype ZendirClient = any;\nimport {\n safeNumber,\n formatCoordinate,\n formatAltitude,\n formatVelocity,\n formatPercentage,\n formatTime,\n getStatusColor,\n classNames,\n safeAccentText,\n type StatusLevel,\n} from \"../utils\";\n\nexport interface SpacecraftCardProps {\n /** Spacecraft position data (for direct data mode) */\n spacecraft?: SpacecraftPosition;\n /** Optional telemetry data */\n telemetry?: TelemetryData;\n /** Show expanded orbit info */\n showOrbit?: boolean;\n /** Show telemetry summary */\n showTelemetry?: boolean;\n /** Loading state */\n loading?: boolean;\n /** Click handler */\n onClick?: (spacecraft: SpacecraftPosition) => void;\n /** Custom className */\n className?: string;\n /** Connected mode: SDK client */\n client?: ZendirClient;\n /** Connected mode: Spacecraft ID to fetch */\n spacecraftId?: string;\n /** Enable compact mode - shows condensed view that expands on hover/click */\n compact?: boolean;\n /** Start expanded when in compact mode (pinned state) */\n defaultExpanded?: boolean;\n /** Callback when pin state changes in compact mode */\n onPinChange?: (isPinned: boolean) => void;\n}\n\n/**\n * Get orbit type color based on orbit classification\n * Uses Zendir-Astro palette for categorical (non-status) classification\n */\nfunction getOrbitTypeColor(\n orbitType: string | undefined,\n accentColor: string,\n): string {\n // Orbit type colors using pure Zendir brand palette\n // These are categorical colors, not status colors\n const colors: Record<string, string> = {\n LEO: \"#3E3CFF\", // Zendir Electric - Low Earth Orbit\n MEO: \"#3548C0\", // Zendir Prussian Blue Light - Medium Earth Orbit\n GEO: \"#9D70FF\", // Zendir Purple - Geostationary\n HEO: \"#1B2DA0\", // Zendir Prussian Blue - Highly Elliptical\n SSO: \"#B48DFF\", // Zendir Purple Light - Sun-Synchronous\n POLAR: \"#6B69FF\", // Zendir Electric Light - Polar\n };\n return colors[orbitType?.toUpperCase() ?? \"\"] ?? accentColor;\n}\n\n/**\n * Derive health status from spacecraft or telemetry\n * Prefers telemetry.health.status, falls back to spacecraft.status\n */\nfunction deriveHealthStatus(\n spacecraftStatus: StatusLevel | undefined,\n telemetryStatus: string | undefined,\n): StatusLevel {\n // Prefer telemetry if available, but also validate it's a proper StatusLevel\n if (telemetryStatus) {\n const validStatuses: StatusLevel[] = [\n \"off\",\n \"standby\",\n \"normal\",\n \"caution\",\n \"serious\",\n \"critical\",\n ];\n const normalized = telemetryStatus.toLowerCase();\n if (validStatuses.includes(normalized as StatusLevel)) {\n return normalized as StatusLevel;\n }\n // Legacy mapping for backwards compatibility\n switch (normalized) {\n case \"healthy\":\n case \"nominal\":\n case \"operational\":\n return \"normal\";\n case \"warning\":\n case \"degraded\":\n return \"caution\";\n case \"failed\":\n case \"error\":\n return \"critical\";\n case \"idle\":\n return \"standby\";\n }\n }\n // Use spacecraft.status directly (already typed as StatusLevel)\n return spacecraftStatus ?? \"off\";\n}\n\n/**\n * SpacecraftCard - Displays spacecraft position and status information\n *\n * @example\n * ```tsx\n * // Direct data mode\n * <SpacecraftCard\n * spacecraft={spacecraftData}\n * telemetry={telemetryData}\n * showOrbit\n * showTelemetry\n * onClick={() => {}}\n * />\n *\n * // Connected mode (auto-fetches via SDK)\n * <SpacecraftCard\n * client={zendirClient}\n * spacecraftId=\"iss-25544\"\n * showTelemetry\n * />\n * ```\n */\nexport const SpacecraftCard = memo(function SpacecraftCard({\n spacecraft,\n telemetry,\n showOrbit = false,\n showTelemetry = false,\n loading = false,\n onClick,\n className = \"\",\n compact = false,\n defaultExpanded = false,\n onPinChange,\n}: SpacecraftCardProps): React.ReactElement {\n const { tokens, theme, prefersReducedMotion } = useTheme();\n const isTransparentTheme =\n theme === \"transparent\" ||\n theme === \"transparent-bold\" ||\n theme === \"transparent-minimal\";\n const isBoldVariant = theme === \"transparent-bold\";\n const isMinimalVariant = theme === \"transparent-minimal\";\n const useGlassMode = isBoldVariant || isMinimalVariant;\n\n // Glass accent colors for bold/minimal themes (matching Container/AstroChart)\n const glassAccentColor = tokens.colors.accent.primary;\n const glassAccentMuted = `${glassAccentColor}66`;\n\n // WCAG AA safe accent for use as foreground text on dark backgrounds\n const accentTextColor = useMemo(\n () => safeAccentText(tokens.colors.accent.primary),\n [tokens.colors.accent.primary],\n );\n\n // Use transparent background with blur for transparent themes (matching Timeline)\n const cardBg = isTransparentTheme\n ? \"transparent\"\n : tokens.colors.background.surface;\n const cardGlass = isTransparentTheme\n ? {\n backdropFilter: \"blur(12px)\" as const,\n WebkitBackdropFilter: \"blur(12px)\" as const,\n }\n : {};\n // Get card border style based on accentBorders setting\n const cardBorderStyle = useCardBorderStyle(tokens, isTransparentTheme);\n\n // Glass mode container style (matching Container/AstroChart for bold/minimal)\n const glassContainerStyle: React.CSSProperties = useGlassMode\n ? {\n backgroundColor: \"rgba(10, 15, 25, 0.35)\",\n backdropFilter: \"blur(12px)\",\n WebkitBackdropFilter: \"blur(12px)\",\n border: `1px solid ${glassAccentMuted}`,\n borderTop: isBoldVariant\n ? `2px solid ${glassAccentColor}`\n : `1px solid ${glassAccentColor}`,\n }\n : {};\n\n // Compact mode state management\n const {\n expanded,\n isPinned,\n isHovered: _isHovered,\n handlers: compactHandlers,\n transitionDuration: _compactTransition,\n } = useCompactMode({\n compact,\n defaultExpanded,\n onPinChange,\n });\n\n // Smooth animation timing\n const animationDuration = prefersReducedMotion ? 0 : 250;\n const animationEasing = \"cubic-bezier(0.4, 0, 0.2, 1)\";\n\n // Memoized click handler\n const _handleClick = useCallback(() => {\n if (onClick && spacecraft) {\n onClick(spacecraft);\n }\n }, [onClick, spacecraft]);\n\n // Keyboard handler for accessibility\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (onClick && spacecraft && (e.key === \"Enter\" || e.key === \" \")) {\n e.preventDefault();\n onClick(spacecraft);\n }\n },\n [onClick, spacecraft],\n );\n\n // Memoized computed values\n const orbitColor = useMemo(\n () =>\n getOrbitTypeColor(spacecraft?.orbitType, tokens.colors.accent.primary),\n [spacecraft?.orbitType, tokens.colors.accent.primary],\n );\n\n const healthStatus = useMemo(\n () => deriveHealthStatus(spacecraft?.status, telemetry?.health?.status),\n [spacecraft?.status, telemetry?.health?.status],\n );\n\n const statusColor = useMemo(\n () => getStatusColor(healthStatus),\n [healthStatus],\n );\n\n // Animation duration (respects reduced motion)\n const transitionDuration = prefersReducedMotion ? \"0ms\" : \"200ms\";\n\n // Combined click handler for compact mode and onClick (must be before early returns)\n const combinedClickHandler = useCallback(() => {\n if (compact) {\n compactHandlers.onClick();\n }\n if (onClick && spacecraft) {\n onClick(spacecraft);\n }\n }, [compact, compactHandlers, onClick, spacecraft]);\n\n // Loading state\n if (loading) {\n return (\n <div\n className={classNames(\"zendir-spacecraft-card\", \"loading\", className)}\n role=\"article\"\n aria-busy=\"true\"\n aria-label=\"Loading spacecraft data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n ...cardBorderStyle,\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n minHeight: 180,\n }}\n >\n {/* Loading skeleton */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 12,\n marginBottom: 16,\n }}\n >\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n backgroundColor: \"rgba(255,255,255,0.1)\",\n animation: \"pulse 1.5s ease-in-out infinite\",\n }}\n />\n <div style={{ flex: 1 }}>\n <div\n style={{\n height: 16,\n width: \"60%\",\n backgroundColor: \"rgba(255,255,255,0.1)\",\n borderRadius: 4,\n animation: \"pulse 1.5s ease-in-out infinite\",\n }}\n />\n </div>\n </div>\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(2, 1fr)\",\n gap: 12,\n }}\n >\n {[1, 2, 3, 4].map((i) => (\n <div key={i}>\n <div\n style={{\n height: 10,\n width: \"40%\",\n backgroundColor: \"rgba(255,255,255,0.08)\",\n borderRadius: 2,\n marginBottom: 4,\n }}\n />\n <div\n style={{\n height: 14,\n width: \"70%\",\n backgroundColor: \"rgba(255,255,255,0.1)\",\n borderRadius: 2,\n }}\n />\n </div>\n ))}\n </div>\n <style>{`\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n `}</style>\n </div>\n );\n }\n\n // Empty state\n if (!spacecraft) {\n return (\n <div\n className={classNames(\"zendir-spacecraft-card\", \"empty\", className)}\n role=\"article\"\n aria-label=\"No spacecraft data\"\n style={{\n backgroundColor: cardBg,\n ...cardGlass,\n ...(tokens.colors.border.cardStyleDashed ?? {}),\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.lg,\n textAlign: \"center\",\n color: tokens.colors.text.tertiary,\n }}\n >\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n style={{ marginBottom: 8, opacity: 0.5 }}\n >\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n <p style={{ margin: 0, fontSize: tokens.typography.body[2].fontSize }}>\n No spacecraft data available\n </p>\n </div>\n );\n }\n\n // Compact view - shows key info in a single row\n // Compact metric item component for consistent styling\n const CompactMetric = ({\n icon,\n label,\n value,\n color,\n }: {\n icon: IconName;\n label: string;\n value: string | number;\n color?: string;\n }) => (\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 3,\n padding: `2px 0`,\n }}\n >\n <Icon\n name={icon}\n size={12}\n color={color ?? tokens.colors.text.secondary}\n />\n <span\n style={{\n fontSize: tokens.typography.fontSize.micro, // 0.5625rem / 9px (AstroUXDS micro)\n fontWeight: tokens.typography.fontWeight.medium,\n fontFamily: tokens.typography.fontFamily.primary, // Public Sans → Roboto fallback → system stack\n color: tokens.colors.text.tertiary,\n textTransform: \"uppercase\",\n minWidth: 8,\n }}\n >\n {label.charAt(0)}\n </span>\n <span\n style={{\n fontVariantNumeric: \"tabular-nums\",\n fontFamily: tokens.typography.fontFamily.mono,\n fontSize: tokens.typography.fontSize.xs,\n color: color ?? tokens.colors.text.primary,\n fontWeight: tokens.typography.fontWeight.medium,\n }}\n >\n {value}\n </span>\n </div>\n );\n\n // Compact view content - reusable for rendering\n const renderCompactContent = () => {\n const power = telemetry?.subsystems?.power ?? telemetry?.power;\n const batteryLevel = power?.batteryLevel;\n const batteryStatusLocal =\n batteryLevel !== undefined\n ? batteryLevel > 50\n ? \"normal\"\n : batteryLevel > 20\n ? \"caution\"\n : \"critical\"\n : \"off\";\n\n // Status color for header icon\n const statusColor = getStatusColor(healthStatus);\n\n return (\n <>\n {/* Header: Icon (status colored) → Status symbol → Name → Badges */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: tokens.spacing.xs,\n paddingBottom: tokens.spacing.xs,\n borderBottom: useGlassMode\n ? \"none\"\n : `1px solid ${tokens.colors.border.muted}`,\n position: \"relative\",\n zIndex: 1,\n }}\n >\n {/* Left side: Icon + Name + Accent line */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.xs,\n flex: 1,\n minWidth: 0,\n }}\n >\n {/* Icon with status badge - MonitoringIcon pattern */}\n <HeaderIconWithStatus\n icon=\"satellite-transmit\"\n size={18}\n status={healthStatus}\n statusColor={statusColor}\n />\n {/* Name - accent color for glass mode */}\n <span\n style={{\n fontWeight: tokens.typography.fontWeight.semibold,\n fontSize: tokens.typography.fontSize.sm,\n fontFamily: tokens.typography.fontFamily.primary,\n color: useGlassMode ? glassAccentColor : undefined,\n textShadow: useGlassMode\n ? `0 0 16px ${glassAccentMuted}`\n : undefined,\n whiteSpace: \"nowrap\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n }}\n >\n {(spacecraft.name ?? spacecraft.id ?? \"Unknown\").split(\" \")[0]}\n </span>\n {/* Accent line for glass mode */}\n {useGlassMode && (\n <div\n style={{\n flex: 1,\n height: isBoldVariant ? \"2px\" : \"1px\",\n minWidth: 20,\n background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`,\n boxShadow: isBoldVariant\n ? `0 0 8px ${glassAccentMuted}`\n : undefined,\n }}\n />\n )}\n </div>\n\n {/* Right side: Orbit type badge + Pin */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.xs,\n flexShrink: 0,\n }}\n >\n {/* Orbit type badge */}\n <span\n style={{\n backgroundColor: `${orbitColor}20`,\n color: orbitColor,\n padding: `1px 6px`,\n borderRadius: tokens.borderRadius.sm,\n fontSize: tokens.typography.fontSize.xxs, // 0.625rem / 10px (AstroUXDS compact)\n fontWeight: tokens.typography.fontWeight.medium,\n fontFamily: tokens.typography.fontFamily.primary,\n }}\n >\n {spacecraft.orbitType ?? \"—\"}\n </span>\n {/* Pin badge */}\n {isPinned && (\n <Icon\n name=\"lock\"\n size={10}\n color={tokens.colors.accent.primary}\n />\n )}\n </div>\n </div>\n\n {/* Metrics grid - 3 columns */}\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(3, 1fr)\",\n gap: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\n }}\n >\n {/* Position metrics */}\n <CompactMetric\n icon=\"location\"\n label=\"Latitude\"\n value={formatCoordinate(spacecraft.latitude, \"lat\")}\n />\n <CompactMetric\n icon=\"location\"\n label=\"Longitude\"\n value={formatCoordinate(spacecraft.longitude, \"lon\")}\n />\n <CompactMetric\n icon=\"orbit\"\n label=\"Altitude\"\n value={formatAltitude(spacecraft.altitude)}\n color={orbitColor}\n />\n\n {/* Velocity */}\n {spacecraft.velocity !== undefined && (\n <CompactMetric\n icon=\"rocket\"\n label=\"Velocity\"\n value={formatVelocity(spacecraft.velocity)}\n />\n )}\n\n {/* Telemetry data if available */}\n {batteryLevel !== undefined && (\n <CompactMetric\n icon=\"battery\"\n label=\"Battery\"\n value={formatPercentage(batteryLevel)}\n color={getStatusColor(batteryStatusLocal as StatusLevel)}\n />\n )}\n\n {/* Inclination if available */}\n {spacecraft.inclination !== undefined && (\n <CompactMetric\n icon=\"orbit\"\n label=\"Inclination\"\n value={`${safeNumber(spacecraft.inclination, 1)}°`}\n />\n )}\n </div>\n </>\n );\n };\n\n // Compact mode with in-place expansion - cards push each other\n if (compact) {\n return (\n <article\n className={classNames(\n \"zendir-spacecraft-card\",\n \"compact\",\n expanded ? \"expanded\" : \"\",\n className,\n )}\n {...compactHandlers}\n aria-label={`Spacecraft: ${spacecraft.name ?? spacecraft.id}${expanded ? \"\" : \" (compact)\"}`}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n // Use glass container style for bold/minimal themes\n ...(useGlassMode\n ? glassContainerStyle\n : {\n backgroundColor: cardBg,\n ...cardGlass,\n ...cardBorderStyle,\n }),\n borderRadius: tokens.borderRadius.lg,\n padding: expanded ? tokens.spacing.md : tokens.spacing.sm,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.primary,\n fontSize: expanded\n ? tokens.typography.fontSize.base\n : tokens.typography.fontSize.sm,\n cursor: \"pointer\",\n transition: `all ${animationDuration}ms ${animationEasing}`,\n boxShadow: expanded\n ? `0 12px 40px rgba(0,0,0,0.4), 0 0 0 1px ${orbitColor}30`\n : \"none\",\n zIndex: expanded ? 50 : 1,\n }}\n >\n {/* Glass gradient overlay for bold/minimal themes */}\n {useGlassMode && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background:\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\n pointerEvents: \"none\",\n zIndex: 0,\n }}\n />\n )}\n {expanded ? (\n // Full expanded content\n <>\n {/* Full expanded header - matches MonitoringIcon layout pattern */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n marginBottom: tokens.spacing.md,\n }}\n >\n {/* Icon with status badge - MonitoringIcon pattern */}\n <HeaderIconWithStatus\n icon=\"satellite-transmit\"\n size={24}\n status={healthStatus}\n />\n <div style={{ flex: 1, minWidth: 0 }}>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\n <h3\n style={{\n margin: 0,\n fontSize: tokens.typography.fontSize.md,\n fontWeight: tokens.typography.fontWeight.semibold,\n lineHeight: 1.2,\n }}\n >\n {spacecraft.name ?? spacecraft.id}\n </h3>\n {isPinned && (\n <Icon\n name=\"lock\"\n size={12}\n color={tokens.colors.accent.primary}\n />\n )}\n </div>\n {spacecraft.id && spacecraft.name && (\n <span\n style={{\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n }}\n >\n {spacecraft.id}\n </span>\n )}\n </div>\n <span\n style={{\n backgroundColor: `${orbitColor}20`,\n color: orbitColor,\n padding: `4px 8px`,\n borderRadius: tokens.borderRadius.sm,\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n flexShrink: 0,\n }}\n >\n {spacecraft.orbitType ?? \"Unknown\"}\n </span>\n </div>\n\n {/* Position Grid */}\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(2, 1fr)\",\n gap: tokens.spacing.sm,\n marginBottom: tokens.spacing.md,\n }}\n >\n <div>\n <span\n style={{\n display: \"block\",\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n marginBottom: 2,\n }}\n >\n Latitude\n </span>\n <span\n style={{\n fontSize: tokens.typography.fontSize.md,\n fontWeight: tokens.typography.fontWeight.medium,\n fontVariantNumeric: \"tabular-nums\",\n fontFamily: tokens.typography.fontFamily.mono,\n }}\n >\n {formatCoordinate(spacecraft.latitude, \"lat\")}\n </span>\n </div>\n <div>\n <span\n style={{\n display: \"block\",\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n marginBottom: 2,\n }}\n >\n Longitude\n </span>\n <span\n style={{\n fontSize: tokens.typography.fontSize.md,\n fontWeight: tokens.typography.fontWeight.medium,\n fontVariantNumeric: \"tabular-nums\",\n fontFamily: tokens.typography.fontFamily.mono,\n }}\n >\n {formatCoordinate(spacecraft.longitude, \"lon\")}\n </span>\n </div>\n <div>\n <span\n style={{\n display: \"block\",\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n marginBottom: 2,\n }}\n >\n Altitude\n </span>\n <span\n style={{\n fontSize: tokens.typography.fontSize.md,\n fontWeight: tokens.typography.fontWeight.medium,\n fontVariantNumeric: \"tabular-nums\",\n fontFamily: tokens.typography.fontFamily.mono,\n color: orbitColor,\n }}\n >\n {formatAltitude(spacecraft.altitude)}\n </span>\n </div>\n <div>\n <span\n style={{\n display: \"block\",\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n marginBottom: 2,\n }}\n >\n Velocity\n </span>\n <span\n style={{\n fontSize: tokens.typography.fontSize.md,\n fontWeight: tokens.typography.fontWeight.medium,\n fontVariantNumeric: \"tabular-nums\",\n fontFamily: tokens.typography.fontFamily.mono,\n }}\n >\n {formatVelocity(spacecraft.velocity)}\n </span>\n </div>\n </div>\n\n {/* Timestamp */}\n {spacecraft.timestamp && (\n <time\n dateTime={spacecraft.timestamp}\n style={{\n display: \"block\",\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n fontVariantNumeric: \"tabular-nums\",\n }}\n >\n {formatTime(spacecraft.timestamp)}\n </time>\n )}\n </>\n ) : (\n // Compact content\n renderCompactContent()\n )}\n </article>\n );\n }\n\n return (\n <article\n className={classNames(\n \"zendir-spacecraft-card\",\n compact ? \"expanded\" : \"\",\n className,\n )}\n onClick={compact || onClick ? combinedClickHandler : undefined}\n onKeyDown={onClick ? handleKeyDown : compactHandlers.onKeyDown}\n tabIndex={onClick || compact ? 0 : undefined}\n role={compact ? compactHandlers.role : \"article\"}\n aria-expanded={compact ? compactHandlers[\"aria-expanded\"] : undefined}\n aria-label={`Spacecraft: ${spacecraft.name ?? spacecraft.id}`}\n style={{\n position: \"relative\",\n overflow: \"hidden\",\n ...(useGlassMode\n ? glassContainerStyle\n : {\n backgroundColor: cardBg,\n ...cardGlass,\n ...cardBorderStyle,\n }),\n borderRadius: tokens.borderRadius.lg,\n padding: tokens.spacing.md,\n fontFamily: tokens.typography.fontFamily.primary,\n color: tokens.colors.text.primary,\n cursor: onClick || compact ? \"pointer\" : \"default\",\n transition: `all ${transitionDuration} ease-out`,\n outline: \"none\",\n }}\n onMouseEnter={(e) => {\n if (compact) compactHandlers.onMouseEnter();\n if (onClick) {\n e.currentTarget.style.borderColor = tokens.colors.border.focus;\n e.currentTarget.style.boxShadow = tokens.shadows.md;\n e.currentTarget.style.transform = prefersReducedMotion\n ? \"none\"\n : \"translateY(-2px)\";\n }\n }}\n onMouseLeave={(e) => {\n if (compact) compactHandlers.onMouseLeave();\n if (onClick) {\n e.currentTarget.style.borderColor = tokens.colors.border.muted;\n e.currentTarget.style.boxShadow = \"none\";\n e.currentTarget.style.transform = \"none\";\n }\n }}\n onFocus={(e) => {\n e.currentTarget.style.outline = `2px solid ${tokens.colors.border.focus}`;\n e.currentTarget.style.outlineOffset = \"2px\";\n }}\n onBlur={(e) => {\n e.currentTarget.style.outline = \"none\";\n }}\n >\n {/* Glass gradient overlay for bold/minimal themes */}\n {useGlassMode && (\n <div\n style={{\n position: \"absolute\",\n inset: 0,\n background:\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\n pointerEvents: \"none\",\n zIndex: 0,\n }}\n />\n )}\n\n {/* Unified Card Header - handles all theme variants */}\n <CardHeader\n icon=\"satellite-transmit\"\n title={spacecraft.name ?? spacecraft.id ?? \"Unknown\"}\n subtitle={spacecraft.id && spacecraft.name ? spacecraft.id : undefined}\n status={healthStatus}\n badge={spacecraft.orbitType ?? \"Unknown\"}\n badgeColor={orbitColor}\n isPinned={compact && isPinned}\n />\n\n {/* Position Data Grid */}\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(2, 1fr)\",\n gap: tokens.spacing.sm,\n }}\n >\n <DataCell\n label=\"Latitude\"\n value={formatCoordinate(spacecraft.latitude, \"lat\")}\n tokens={tokens}\n highlightColor={accentTextColor}\n />\n <DataCell\n label=\"Longitude\"\n value={formatCoordinate(spacecraft.longitude, \"lon\")}\n tokens={tokens}\n highlightColor={accentTextColor}\n />\n <DataCell\n label=\"Altitude\"\n value={formatAltitude(spacecraft.altitude)}\n highlight\n tokens={tokens}\n highlightColor={accentTextColor}\n />\n <DataCell\n label=\"Velocity\"\n value={formatVelocity(spacecraft.velocity)}\n tokens={tokens}\n highlightColor={accentTextColor}\n />\n </div>\n\n {/* Orbit Info (Optional) */}\n {showOrbit && spacecraft.inclination !== undefined && (\n <div\n style={{\n marginTop: tokens.spacing.md,\n paddingTop: tokens.spacing.md,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n }}\n >\n <DataCell\n label=\"Inclination\"\n value={`${safeNumber(spacecraft.inclination, 1)}°`}\n inline\n tokens={tokens}\n />\n </div>\n )}\n\n {/* Telemetry Summary (Optional) */}\n {showTelemetry && telemetry && (\n <div\n style={{\n marginTop: tokens.spacing.md,\n paddingTop: tokens.spacing.md,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n }}\n >\n {/* Health Status */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: tokens.spacing.sm,\n marginBottom: tokens.spacing.sm,\n }}\n >\n <span\n aria-hidden=\"true\"\n style={{\n width: 10,\n height: 10,\n borderRadius: \"50%\",\n backgroundColor: statusColor,\n boxShadow: `0 0 8px ${statusColor}60`,\n }}\n />\n <span\n style={{\n fontSize: tokens.typography.fontSize.xs,\n fontWeight: tokens.typography.fontWeight.medium,\n color: statusColor,\n textTransform: \"capitalize\",\n }}\n >\n {telemetry.health?.status ?? \"Unknown\"}\n </span>\n </div>\n\n {/* Battery Progress */}\n {telemetry.power?.batteryLevel !== undefined && (\n <div>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n marginBottom: 4,\n fontSize: tokens.typography.fontSize.xs,\n }}\n >\n <span style={{ color: tokens.colors.text.tertiary }}>\n Battery\n </span>\n <span\n style={{\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: \"tabular-nums\",\n }}\n >\n {formatPercentage(telemetry.power.batteryLevel, false, 0)}\n </span>\n </div>\n <div\n style={{\n height: 4,\n backgroundColor: tokens.colors.border.muted,\n borderRadius: 2,\n overflow: \"hidden\",\n }}\n >\n <div\n role=\"progressbar\"\n aria-valuenow={telemetry.power.batteryLevel}\n aria-valuemin={0}\n aria-valuemax={100}\n aria-label=\"Battery level\"\n style={{\n height: \"100%\",\n width: `${Math.min(100, Math.max(0, telemetry.power.batteryLevel))}%`,\n backgroundColor:\n telemetry.power.batteryLevel > 30\n ? tokens.colors.status.normal\n : tokens.colors.status.critical,\n borderRadius: 2,\n transition: `width ${transitionDuration} ease-out`,\n }}\n />\n </div>\n </div>\n )}\n </div>\n )}\n\n {/* Timestamp Footer */}\n {spacecraft.timestamp && (\n <footer\n style={{\n marginTop: tokens.spacing.md,\n paddingTop: tokens.spacing.sm,\n borderTop: `1px solid ${tokens.colors.border.muted}`,\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.tertiary,\n textAlign: \"right\",\n }}\n >\n <time dateTime={spacecraft.timestamp}>\n {formatTime(spacecraft.timestamp)} UTC\n </time>\n </footer>\n )}\n </article>\n );\n});\n\n// ============================================================================\n// Helper Components\n// ============================================================================\n\ninterface DataCellProps {\n label: string;\n value: string;\n highlight?: boolean;\n inline?: boolean;\n tokens: ReturnType<typeof useTheme>[\"tokens\"];\n /** WCAG AA safe highlight color (computed via safeAccentText) */\n highlightColor?: string;\n}\n\nconst DataCell = memo(function DataCell({\n label,\n value,\n highlight = false,\n inline = false,\n tokens,\n highlightColor,\n}: DataCellProps): React.ReactElement {\n if (inline) {\n return (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.secondary, // WCAG AA compliant\n fontWeight: tokens.typography.fontWeight.medium,\n }}\n >\n {label}\n </span>\n <span\n style={{\n fontSize: tokens.typography.fontSize.sm,\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: \"tabular-nums\",\n color: tokens.colors.text.primary,\n }}\n >\n {value}\n </span>\n </div>\n );\n }\n\n return (\n <div>\n <span\n style={{\n display: \"block\",\n fontSize: tokens.typography.fontSize.xs,\n color: tokens.colors.text.secondary, // WCAG AA compliant\n fontWeight: tokens.typography.fontWeight.medium,\n marginBottom: 2,\n }}\n >\n {label}\n </span>\n <span\n style={{\n display: \"block\",\n fontSize: tokens.typography.fontSize.sm,\n fontFamily: tokens.typography.fontFamily.mono,\n fontVariantNumeric: \"tabular-nums\",\n color: highlight\n ? (highlightColor ?? safeAccentText(tokens.colors.accent.primary))\n : tokens.colors.text.primary,\n fontWeight: tokens.typography.fontWeight.medium,\n }}\n >\n {value}\n </span>\n </div>\n );\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"SpacecraftCard.js","names":[],"sources":["../../../src/react/cards/SpacecraftCard.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - SpacecraftCard Component\r\n *\r\n * Enterprise-grade spacecraft information card.\r\n *\r\n * AstroUXDS Compliance:\r\n * - Status colors used for health/operational status only\r\n * - Orbit type uses Zendir-Astro data viz colors (categorical)\r\n * - Zendir accent colors for interactive elements\r\n * - Tabular numbers with fontVariantNumeric for data\r\n * - Sentence-case labels per Tier 3 compliance\r\n *\r\n * Features:\r\n * - Full null-safety with graceful fallbacks\r\n * - WCAG 2.1 AA accessibility\r\n * - Keyboard navigation\r\n * - Smooth animations with reduced-motion support\r\n * - Loading skeleton state\r\n * - Error boundary support\r\n * - Real SDK integration via optional client prop\r\n */\r\n\r\nimport React, { memo, useCallback, useMemo } from \"react\";\r\nimport type { SpacecraftPosition, TelemetryData } from \"../types\";\r\nimport { useTheme } from \"../theme\";\r\nimport { Icon, type IconName } from \"../core/display/Icon\";\r\nimport { CardHeader } from \"../core/display/CardHeader\";\r\nimport { HeaderIconWithStatus } from \"../core/display/HeaderIconWithStatus\";\r\nimport { useCompactMode } from \"../hooks\";\r\nimport { useCardBorderStyle } from \"../context/DisplaySettingsContext\";\r\n\r\n// ZendirClient is optional - only used when SDK is installed\r\ntype ZendirClient = any;\r\nimport {\r\n safeNumber,\r\n formatCoordinate,\r\n formatAltitude,\r\n formatVelocity,\r\n formatPercentage,\r\n formatTime,\r\n getStatusColor,\r\n classNames,\r\n safeAccentText,\r\n type StatusLevel,\r\n} from \"../utils\";\r\n\r\nexport interface SpacecraftCardProps {\r\n /** Spacecraft position data (for direct data mode) */\r\n spacecraft?: SpacecraftPosition;\r\n /** Optional telemetry data */\r\n telemetry?: TelemetryData;\r\n /** Show expanded orbit info */\r\n showOrbit?: boolean;\r\n /** Show telemetry summary */\r\n showTelemetry?: boolean;\r\n /** Loading state */\r\n loading?: boolean;\r\n /** Click handler */\r\n onClick?: (spacecraft: SpacecraftPosition) => void;\r\n /** Custom className */\r\n className?: string;\r\n /** Connected mode: SDK client */\r\n client?: ZendirClient;\r\n /** Connected mode: Spacecraft ID to fetch */\r\n spacecraftId?: string;\r\n /** Enable compact mode - shows condensed view that expands on hover/click */\r\n compact?: boolean;\r\n /** Start expanded when in compact mode (pinned state) */\r\n defaultExpanded?: boolean;\r\n /** Callback when pin state changes in compact mode */\r\n onPinChange?: (isPinned: boolean) => void;\r\n}\r\n\r\n/**\r\n * Get orbit type color based on orbit classification\r\n * Uses Zendir-Astro palette for categorical (non-status) classification\r\n */\r\nfunction getOrbitTypeColor(\r\n orbitType: string | undefined,\r\n accentColor: string,\r\n): string {\r\n // Orbit type colors using pure Zendir brand palette\r\n // These are categorical colors, not status colors\r\n const colors: Record<string, string> = {\r\n LEO: \"#3E3CFF\", // Zendir Electric - Low Earth Orbit\r\n MEO: \"#3548C0\", // Zendir Prussian Blue Light - Medium Earth Orbit\r\n GEO: \"#9D70FF\", // Zendir Purple - Geostationary\r\n HEO: \"#1B2DA0\", // Zendir Prussian Blue - Highly Elliptical\r\n SSO: \"#B48DFF\", // Zendir Purple Light - Sun-Synchronous\r\n POLAR: \"#6B69FF\", // Zendir Electric Light - Polar\r\n };\r\n return colors[orbitType?.toUpperCase() ?? \"\"] ?? accentColor;\r\n}\r\n\r\n/**\r\n * Derive health status from spacecraft or telemetry\r\n * Prefers telemetry.health.status, falls back to spacecraft.status\r\n */\r\nfunction deriveHealthStatus(\r\n spacecraftStatus: StatusLevel | undefined,\r\n telemetryStatus: string | undefined,\r\n): StatusLevel {\r\n // Prefer telemetry if available, but also validate it's a proper StatusLevel\r\n if (telemetryStatus) {\r\n const validStatuses: StatusLevel[] = [\r\n \"off\",\r\n \"standby\",\r\n \"normal\",\r\n \"caution\",\r\n \"serious\",\r\n \"critical\",\r\n ];\r\n const normalized = telemetryStatus.toLowerCase();\r\n if (validStatuses.includes(normalized as StatusLevel)) {\r\n return normalized as StatusLevel;\r\n }\r\n // Legacy mapping for backwards compatibility\r\n switch (normalized) {\r\n case \"healthy\":\r\n case \"nominal\":\r\n case \"operational\":\r\n return \"normal\";\r\n case \"warning\":\r\n case \"degraded\":\r\n return \"caution\";\r\n case \"failed\":\r\n case \"error\":\r\n return \"critical\";\r\n case \"idle\":\r\n return \"standby\";\r\n }\r\n }\r\n // Use spacecraft.status directly (already typed as StatusLevel)\r\n return spacecraftStatus ?? \"off\";\r\n}\r\n\r\n/**\r\n * SpacecraftCard - Displays spacecraft position and status information\r\n *\r\n * @example\r\n * ```tsx\r\n * // Direct data mode\r\n * <SpacecraftCard\r\n * spacecraft={spacecraftData}\r\n * telemetry={telemetryData}\r\n * showOrbit\r\n * showTelemetry\r\n * onClick={() => {}}\r\n * />\r\n *\r\n * // Connected mode (auto-fetches via SDK)\r\n * <SpacecraftCard\r\n * client={zendirClient}\r\n * spacecraftId=\"iss-25544\"\r\n * showTelemetry\r\n * />\r\n * ```\r\n */\r\nexport const SpacecraftCard = memo(function SpacecraftCard({\r\n spacecraft,\r\n telemetry,\r\n showOrbit = false,\r\n showTelemetry = false,\r\n loading = false,\r\n onClick,\r\n className = \"\",\r\n compact = false,\r\n defaultExpanded = false,\r\n onPinChange,\r\n}: SpacecraftCardProps): React.ReactElement {\r\n const { tokens, theme, prefersReducedMotion } = useTheme();\r\n const isTransparentTheme =\r\n theme === \"transparent\" ||\r\n theme === \"transparent-bold\" ||\r\n theme === \"transparent-minimal\";\r\n const isBoldVariant = theme === \"transparent-bold\";\r\n const isMinimalVariant = theme === \"transparent-minimal\";\r\n const useGlassMode = isBoldVariant || isMinimalVariant;\r\n\r\n // Glass accent colors for bold/minimal themes (matching Container/AstroChart)\r\n const glassAccentColor = tokens.colors.accent.primary;\r\n const glassAccentMuted = `${glassAccentColor}66`;\r\n\r\n // WCAG AA safe accent for use as foreground text on dark backgrounds\r\n const accentTextColor = useMemo(\r\n () => safeAccentText(tokens.colors.accent.primary),\r\n [tokens.colors.accent.primary],\r\n );\r\n\r\n // Use transparent background with blur for transparent themes (matching Timeline)\r\n const cardBg = isTransparentTheme\r\n ? \"transparent\"\r\n : tokens.colors.background.surface;\r\n const cardGlass = isTransparentTheme\r\n ? {\r\n backdropFilter: \"blur(12px)\" as const,\r\n WebkitBackdropFilter: \"blur(12px)\" as const,\r\n }\r\n : {};\r\n // Get card border style based on accentBorders setting\r\n const cardBorderStyle = useCardBorderStyle(tokens, isTransparentTheme);\r\n\r\n // Glass mode container style (matching Container/AstroChart for bold/minimal)\r\n const glassContainerStyle: React.CSSProperties = useGlassMode\r\n ? {\r\n backgroundColor: \"rgba(10, 15, 25, 0.35)\",\r\n backdropFilter: \"blur(12px)\",\r\n WebkitBackdropFilter: \"blur(12px)\",\r\n border: `1px solid ${glassAccentMuted}`,\r\n borderTop: isBoldVariant\r\n ? `2px solid ${glassAccentColor}`\r\n : `1px solid ${glassAccentColor}`,\r\n }\r\n : {};\r\n\r\n // Compact mode state management\r\n const {\r\n expanded,\r\n isPinned,\r\n isHovered: _isHovered,\r\n handlers: compactHandlers,\r\n transitionDuration: _compactTransition,\r\n } = useCompactMode({\r\n compact,\r\n defaultExpanded,\r\n onPinChange,\r\n });\r\n\r\n // Smooth animation timing\r\n const animationDuration = prefersReducedMotion ? 0 : 250;\r\n const animationEasing = \"cubic-bezier(0.4, 0, 0.2, 1)\";\r\n\r\n // Memoized click handler\r\n const _handleClick = useCallback(() => {\r\n if (onClick && spacecraft) {\r\n onClick(spacecraft);\r\n }\r\n }, [onClick, spacecraft]);\r\n\r\n // Keyboard handler for accessibility\r\n const handleKeyDown = useCallback(\r\n (e: React.KeyboardEvent) => {\r\n if (onClick && spacecraft && (e.key === \"Enter\" || e.key === \" \")) {\r\n e.preventDefault();\r\n onClick(spacecraft);\r\n }\r\n },\r\n [onClick, spacecraft],\r\n );\r\n\r\n // Memoized computed values\r\n const orbitColor = useMemo(\r\n () =>\r\n getOrbitTypeColor(spacecraft?.orbitType, tokens.colors.accent.primary),\r\n [spacecraft?.orbitType, tokens.colors.accent.primary],\r\n );\r\n\r\n const healthStatus = useMemo(\r\n () => deriveHealthStatus(spacecraft?.status, telemetry?.health?.status),\r\n [spacecraft?.status, telemetry?.health?.status],\r\n );\r\n\r\n const statusColor = useMemo(\r\n () => getStatusColor(healthStatus),\r\n [healthStatus],\r\n );\r\n\r\n // Animation duration (respects reduced motion)\r\n const transitionDuration = prefersReducedMotion ? \"0ms\" : \"200ms\";\r\n\r\n // Combined click handler for compact mode and onClick (must be before early returns)\r\n const combinedClickHandler = useCallback(() => {\r\n if (compact) {\r\n compactHandlers.onClick();\r\n }\r\n if (onClick && spacecraft) {\r\n onClick(spacecraft);\r\n }\r\n }, [compact, compactHandlers, onClick, spacecraft]);\r\n\r\n // Loading state\r\n if (loading) {\r\n return (\r\n <div\r\n className={classNames(\"zendir-spacecraft-card\", \"loading\", className)}\r\n role=\"article\"\r\n aria-busy=\"true\"\r\n aria-label=\"Loading spacecraft data\"\r\n style={{\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...cardBorderStyle,\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: tokens.spacing.md,\r\n minHeight: 180,\r\n }}\r\n >\r\n {/* Loading skeleton */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 12,\r\n marginBottom: 16,\r\n }}\r\n >\r\n <div\r\n style={{\r\n width: 32,\r\n height: 32,\r\n borderRadius: \"50%\",\r\n backgroundColor: \"rgba(255,255,255,0.1)\",\r\n animation: \"pulse 1.5s ease-in-out infinite\",\r\n }}\r\n />\r\n <div style={{ flex: 1 }}>\r\n <div\r\n style={{\r\n height: 16,\r\n width: \"60%\",\r\n backgroundColor: \"rgba(255,255,255,0.1)\",\r\n borderRadius: 4,\r\n animation: \"pulse 1.5s ease-in-out infinite\",\r\n }}\r\n />\r\n </div>\r\n </div>\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(2, 1fr)\",\r\n gap: 12,\r\n }}\r\n >\r\n {[1, 2, 3, 4].map((i) => (\r\n <div key={i}>\r\n <div\r\n style={{\r\n height: 10,\r\n width: \"40%\",\r\n backgroundColor: \"rgba(255,255,255,0.08)\",\r\n borderRadius: 2,\r\n marginBottom: 4,\r\n }}\r\n />\r\n <div\r\n style={{\r\n height: 14,\r\n width: \"70%\",\r\n backgroundColor: \"rgba(255,255,255,0.1)\",\r\n borderRadius: 2,\r\n }}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n <style>{`\r\n @keyframes pulse {\r\n 0%, 100% { opacity: 1; }\r\n 50% { opacity: 0.5; }\r\n }\r\n `}</style>\r\n </div>\r\n );\r\n }\r\n\r\n // Empty state\r\n if (!spacecraft) {\r\n return (\r\n <div\r\n className={classNames(\"zendir-spacecraft-card\", \"empty\", className)}\r\n role=\"article\"\r\n aria-label=\"No spacecraft data\"\r\n style={{\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...(tokens.colors.border.cardStyleDashed ?? {}),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: tokens.spacing.lg,\r\n textAlign: \"center\",\r\n color: tokens.colors.text.tertiary,\r\n }}\r\n >\r\n <svg\r\n width=\"32\"\r\n height=\"32\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"1.5\"\r\n style={{ marginBottom: 8, opacity: 0.5 }}\r\n >\r\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\r\n </svg>\r\n <p style={{ margin: 0, fontSize: tokens.typography.body[2].fontSize }}>\r\n No spacecraft data available\r\n </p>\r\n </div>\r\n );\r\n }\r\n\r\n // Compact view - shows key info in a single row\r\n // Compact metric item component for consistent styling\r\n const CompactMetric = ({\r\n icon,\r\n label,\r\n value,\r\n color,\r\n }: {\r\n icon: IconName;\r\n label: string;\r\n value: string | number;\r\n color?: string;\r\n }) => (\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 3,\r\n padding: `2px 0`,\r\n }}\r\n >\r\n <Icon\r\n name={icon}\r\n size={12}\r\n color={color ?? tokens.colors.text.secondary}\r\n />\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.micro, // 0.5625rem / 9px (AstroUXDS micro)\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: tokens.typography.fontFamily.primary, // Public Sans → Roboto fallback → system stack\r\n color: tokens.colors.text.tertiary,\r\n textTransform: \"uppercase\",\r\n minWidth: 8,\r\n }}\r\n >\r\n {label.charAt(0)}\r\n </span>\r\n <span\r\n style={{\r\n fontVariantNumeric: \"tabular-nums\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: color ?? tokens.colors.text.primary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n {value}\r\n </span>\r\n </div>\r\n );\r\n\r\n // Compact view content - reusable for rendering\r\n const renderCompactContent = () => {\r\n const power = telemetry?.subsystems?.power ?? telemetry?.power;\r\n const batteryLevel = power?.batteryLevel;\r\n const batteryStatusLocal =\r\n batteryLevel !== undefined\r\n ? batteryLevel > 50\r\n ? \"normal\"\r\n : batteryLevel > 20\r\n ? \"caution\"\r\n : \"critical\"\r\n : \"off\";\r\n\r\n // Status color for header icon\r\n const statusColor = getStatusColor(healthStatus);\r\n\r\n return (\r\n <>\r\n {/* Header: Icon (status colored) → Status symbol → Name → Badges */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"space-between\",\r\n marginBottom: tokens.spacing.xs,\r\n paddingBottom: tokens.spacing.xs,\r\n borderBottom: useGlassMode\r\n ? \"none\"\r\n : `1px solid ${tokens.colors.border.muted}`,\r\n position: \"relative\",\r\n zIndex: 1,\r\n }}\r\n >\r\n {/* Left side: Icon + Name + Accent line */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.xs,\r\n flex: 1,\r\n minWidth: 0,\r\n }}\r\n >\r\n {/* Icon with status badge - MonitoringIcon pattern */}\r\n <HeaderIconWithStatus\r\n icon=\"satellite-transmit\"\r\n size={18}\r\n status={healthStatus}\r\n statusColor={statusColor}\r\n />\r\n {/* Name - accent color for glass mode */}\r\n <span\r\n style={{\r\n fontWeight: tokens.typography.fontWeight.semibold,\r\n fontSize: tokens.typography.fontSize.sm,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n color: useGlassMode ? glassAccentColor : undefined,\r\n textShadow: useGlassMode\r\n ? `0 0 16px ${glassAccentMuted}`\r\n : undefined,\r\n whiteSpace: \"nowrap\",\r\n overflow: \"hidden\",\r\n textOverflow: \"ellipsis\",\r\n }}\r\n >\r\n {(spacecraft.name ?? spacecraft.id ?? \"Unknown\").split(\" \")[0]}\r\n </span>\r\n {/* Accent line for glass mode */}\r\n {useGlassMode && (\r\n <div\r\n style={{\r\n flex: 1,\r\n height: isBoldVariant ? \"2px\" : \"1px\",\r\n minWidth: 20,\r\n background: `linear-gradient(90deg, ${glassAccentColor} 0%, ${glassAccentMuted} 60%, transparent 100%)`,\r\n boxShadow: isBoldVariant\r\n ? `0 0 8px ${glassAccentMuted}`\r\n : undefined,\r\n }}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Right side: Orbit type badge + Pin */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.xs,\r\n flexShrink: 0,\r\n }}\r\n >\r\n {/* Orbit type badge */}\r\n <span\r\n style={{\r\n backgroundColor: `${orbitColor}20`,\r\n color: orbitColor,\r\n padding: `1px 6px`,\r\n borderRadius: tokens.borderRadius.sm,\r\n fontSize: tokens.typography.fontSize.xxs, // 0.625rem / 10px (AstroUXDS compact)\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n }}\r\n >\r\n {spacecraft.orbitType ?? \"—\"}\r\n </span>\r\n {/* Pin badge */}\r\n {isPinned && (\r\n <Icon\r\n name=\"lock\"\r\n size={10}\r\n color={tokens.colors.accent.primary}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Metrics grid - 3 columns */}\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(3, 1fr)\",\r\n gap: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n }}\r\n >\r\n {/* Position metrics */}\r\n <CompactMetric\r\n icon=\"location\"\r\n label=\"Latitude\"\r\n value={formatCoordinate(spacecraft.latitude, \"lat\")}\r\n />\r\n <CompactMetric\r\n icon=\"location\"\r\n label=\"Longitude\"\r\n value={formatCoordinate(spacecraft.longitude, \"lon\")}\r\n />\r\n <CompactMetric\r\n icon=\"orbit\"\r\n label=\"Altitude\"\r\n value={formatAltitude(spacecraft.altitude)}\r\n color={orbitColor}\r\n />\r\n\r\n {/* Velocity */}\r\n {spacecraft.velocity !== undefined && (\r\n <CompactMetric\r\n icon=\"rocket\"\r\n label=\"Velocity\"\r\n value={formatVelocity(spacecraft.velocity)}\r\n />\r\n )}\r\n\r\n {/* Telemetry data if available */}\r\n {batteryLevel !== undefined && (\r\n <CompactMetric\r\n icon=\"battery\"\r\n label=\"Battery\"\r\n value={formatPercentage(batteryLevel)}\r\n color={getStatusColor(batteryStatusLocal as StatusLevel)}\r\n />\r\n )}\r\n\r\n {/* Inclination if available */}\r\n {spacecraft.inclination !== undefined && (\r\n <CompactMetric\r\n icon=\"orbit\"\r\n label=\"Inclination\"\r\n value={`${safeNumber(spacecraft.inclination, 1)}°`}\r\n />\r\n )}\r\n </div>\r\n </>\r\n );\r\n };\r\n\r\n // Compact mode with in-place expansion - cards push each other\r\n if (compact) {\r\n return (\r\n <article\r\n className={classNames(\r\n \"zendir-spacecraft-card\",\r\n \"compact\",\r\n expanded ? \"expanded\" : \"\",\r\n className,\r\n )}\r\n {...compactHandlers}\r\n aria-label={`Spacecraft: ${spacecraft.name ?? spacecraft.id}${expanded ? \"\" : \" (compact)\"}`}\r\n style={{\r\n position: \"relative\",\r\n overflow: \"hidden\",\r\n // Use glass container style for bold/minimal themes\r\n ...(useGlassMode\r\n ? glassContainerStyle\r\n : {\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...cardBorderStyle,\r\n }),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: expanded ? tokens.spacing.md : tokens.spacing.sm,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n color: tokens.colors.text.primary,\r\n fontSize: expanded\r\n ? tokens.typography.fontSize.base\r\n : tokens.typography.fontSize.sm,\r\n cursor: \"pointer\",\r\n transition: `all ${animationDuration}ms ${animationEasing}`,\r\n boxShadow: expanded\r\n ? `0 12px 40px rgba(0,0,0,0.4), 0 0 0 1px ${orbitColor}30`\r\n : \"none\",\r\n zIndex: expanded ? 50 : 1,\r\n }}\r\n >\r\n {/* Glass gradient overlay for bold/minimal themes */}\r\n {useGlassMode && (\r\n <div\r\n style={{\r\n position: \"absolute\",\r\n inset: 0,\r\n background:\r\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\r\n pointerEvents: \"none\",\r\n zIndex: 0,\r\n }}\r\n />\r\n )}\r\n {expanded ? (\r\n // Full expanded content\r\n <>\r\n {/* Full expanded header - matches MonitoringIcon layout pattern */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n marginBottom: tokens.spacing.md,\r\n }}\r\n >\r\n {/* Icon with status badge - MonitoringIcon pattern */}\r\n <HeaderIconWithStatus\r\n icon=\"satellite-transmit\"\r\n size={24}\r\n status={healthStatus}\r\n />\r\n <div style={{ flex: 1, minWidth: 0 }}>\r\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6 }}>\r\n <h3\r\n style={{\r\n margin: 0,\r\n fontSize: tokens.typography.fontSize.md,\r\n fontWeight: tokens.typography.fontWeight.semibold,\r\n lineHeight: 1.2,\r\n }}\r\n >\r\n {spacecraft.name ?? spacecraft.id}\r\n </h3>\r\n {isPinned && (\r\n <Icon\r\n name=\"lock\"\r\n size={12}\r\n color={tokens.colors.accent.primary}\r\n />\r\n )}\r\n </div>\r\n {spacecraft.id && spacecraft.name && (\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n }}\r\n >\r\n {spacecraft.id}\r\n </span>\r\n )}\r\n </div>\r\n <span\r\n style={{\r\n backgroundColor: `${orbitColor}20`,\r\n color: orbitColor,\r\n padding: `4px 8px`,\r\n borderRadius: tokens.borderRadius.sm,\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n flexShrink: 0,\r\n }}\r\n >\r\n {spacecraft.orbitType ?? \"Unknown\"}\r\n </span>\r\n </div>\r\n\r\n {/* Position Grid */}\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(2, 1fr)\",\r\n gap: tokens.spacing.sm,\r\n marginBottom: tokens.spacing.md,\r\n }}\r\n >\r\n <div>\r\n <span\r\n style={{\r\n display: \"block\",\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n marginBottom: 2,\r\n }}\r\n >\r\n Latitude\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.md,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontVariantNumeric: \"tabular-nums\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n }}\r\n >\r\n {formatCoordinate(spacecraft.latitude, \"lat\")}\r\n </span>\r\n </div>\r\n <div>\r\n <span\r\n style={{\r\n display: \"block\",\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n marginBottom: 2,\r\n }}\r\n >\r\n Longitude\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.md,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontVariantNumeric: \"tabular-nums\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n }}\r\n >\r\n {formatCoordinate(spacecraft.longitude, \"lon\")}\r\n </span>\r\n </div>\r\n <div>\r\n <span\r\n style={{\r\n display: \"block\",\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n marginBottom: 2,\r\n }}\r\n >\r\n Altitude\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.md,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontVariantNumeric: \"tabular-nums\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n color: orbitColor,\r\n }}\r\n >\r\n {formatAltitude(spacecraft.altitude)}\r\n </span>\r\n </div>\r\n <div>\r\n <span\r\n style={{\r\n display: \"block\",\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n marginBottom: 2,\r\n }}\r\n >\r\n Velocity\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.md,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontVariantNumeric: \"tabular-nums\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n }}\r\n >\r\n {formatVelocity(spacecraft.velocity)}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {/* Timestamp */}\r\n {spacecraft.timestamp && (\r\n <time\r\n dateTime={spacecraft.timestamp}\r\n style={{\r\n display: \"block\",\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n fontVariantNumeric: \"tabular-nums\",\r\n }}\r\n >\r\n {formatTime(spacecraft.timestamp)}\r\n </time>\r\n )}\r\n </>\r\n ) : (\r\n // Compact content\r\n renderCompactContent()\r\n )}\r\n </article>\r\n );\r\n }\r\n\r\n return (\r\n <article\r\n className={classNames(\r\n \"zendir-spacecraft-card\",\r\n compact ? \"expanded\" : \"\",\r\n className,\r\n )}\r\n onClick={compact || onClick ? combinedClickHandler : undefined}\r\n onKeyDown={onClick ? handleKeyDown : compactHandlers.onKeyDown}\r\n tabIndex={onClick || compact ? 0 : undefined}\r\n role={compact ? compactHandlers.role : \"article\"}\r\n aria-expanded={compact ? compactHandlers[\"aria-expanded\"] : undefined}\r\n aria-label={`Spacecraft: ${spacecraft.name ?? spacecraft.id}`}\r\n style={{\r\n position: \"relative\",\r\n overflow: \"hidden\",\r\n ...(useGlassMode\r\n ? glassContainerStyle\r\n : {\r\n backgroundColor: cardBg,\r\n ...cardGlass,\r\n ...cardBorderStyle,\r\n }),\r\n borderRadius: tokens.borderRadius.lg,\r\n padding: tokens.spacing.md,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n color: tokens.colors.text.primary,\r\n cursor: onClick || compact ? \"pointer\" : \"default\",\r\n transition: `all ${transitionDuration} ease-out`,\r\n outline: \"none\",\r\n }}\r\n onMouseEnter={(e) => {\r\n if (compact) compactHandlers.onMouseEnter();\r\n if (onClick) {\r\n e.currentTarget.style.borderColor = tokens.colors.border.focus;\r\n e.currentTarget.style.boxShadow = tokens.shadows.md;\r\n e.currentTarget.style.transform = prefersReducedMotion\r\n ? \"none\"\r\n : \"translateY(-2px)\";\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (compact) compactHandlers.onMouseLeave();\r\n if (onClick) {\r\n e.currentTarget.style.borderColor = tokens.colors.border.muted;\r\n e.currentTarget.style.boxShadow = \"none\";\r\n e.currentTarget.style.transform = \"none\";\r\n }\r\n }}\r\n onFocus={(e) => {\r\n e.currentTarget.style.outline = `2px solid ${tokens.colors.border.focus}`;\r\n e.currentTarget.style.outlineOffset = \"2px\";\r\n }}\r\n onBlur={(e) => {\r\n e.currentTarget.style.outline = \"none\";\r\n }}\r\n >\r\n {/* Glass gradient overlay for bold/minimal themes */}\r\n {useGlassMode && (\r\n <div\r\n style={{\r\n position: \"absolute\",\r\n inset: 0,\r\n background:\r\n \"linear-gradient(135deg, rgba(255,255,255,0.03) 0%, transparent 50%, rgba(0,0,0,0.1) 100%)\",\r\n pointerEvents: \"none\",\r\n zIndex: 0,\r\n }}\r\n />\r\n )}\r\n\r\n {/* Unified Card Header - handles all theme variants */}\r\n <CardHeader\r\n icon=\"satellite-transmit\"\r\n title={spacecraft.name ?? spacecraft.id ?? \"Unknown\"}\r\n subtitle={spacecraft.id && spacecraft.name ? spacecraft.id : undefined}\r\n status={healthStatus}\r\n badge={spacecraft.orbitType ?? \"Unknown\"}\r\n badgeColor={orbitColor}\r\n isPinned={compact && isPinned}\r\n />\r\n\r\n {/* Position Data Grid */}\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"repeat(2, 1fr)\",\r\n gap: tokens.spacing.sm,\r\n }}\r\n >\r\n <DataCell\r\n label=\"Latitude\"\r\n value={formatCoordinate(spacecraft.latitude, \"lat\")}\r\n tokens={tokens}\r\n highlightColor={accentTextColor}\r\n />\r\n <DataCell\r\n label=\"Longitude\"\r\n value={formatCoordinate(spacecraft.longitude, \"lon\")}\r\n tokens={tokens}\r\n highlightColor={accentTextColor}\r\n />\r\n <DataCell\r\n label=\"Altitude\"\r\n value={formatAltitude(spacecraft.altitude)}\r\n highlight\r\n tokens={tokens}\r\n highlightColor={accentTextColor}\r\n />\r\n <DataCell\r\n label=\"Velocity\"\r\n value={formatVelocity(spacecraft.velocity)}\r\n tokens={tokens}\r\n highlightColor={accentTextColor}\r\n />\r\n </div>\r\n\r\n {/* Orbit Info (Optional) */}\r\n {showOrbit && spacecraft.inclination !== undefined && (\r\n <div\r\n style={{\r\n marginTop: tokens.spacing.md,\r\n paddingTop: tokens.spacing.md,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n }}\r\n >\r\n <DataCell\r\n label=\"Inclination\"\r\n value={`${safeNumber(spacecraft.inclination, 1)}°`}\r\n inline\r\n tokens={tokens}\r\n />\r\n </div>\r\n )}\r\n\r\n {/* Telemetry Summary (Optional) */}\r\n {showTelemetry && telemetry && (\r\n <div\r\n style={{\r\n marginTop: tokens.spacing.md,\r\n paddingTop: tokens.spacing.md,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n }}\r\n >\r\n {/* Health Status */}\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n marginBottom: tokens.spacing.sm,\r\n }}\r\n >\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n width: 10,\r\n height: 10,\r\n borderRadius: \"50%\",\r\n backgroundColor: statusColor,\r\n boxShadow: `0 0 8px ${statusColor}60`,\r\n }}\r\n />\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n color: statusColor,\r\n textTransform: \"capitalize\",\r\n }}\r\n >\r\n {telemetry.health?.status ?? \"Unknown\"}\r\n </span>\r\n </div>\r\n\r\n {/* Battery Progress */}\r\n {telemetry.power?.batteryLevel !== undefined && (\r\n <div>\r\n <div\r\n style={{\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n marginBottom: 4,\r\n fontSize: tokens.typography.fontSize.xs,\r\n }}\r\n >\r\n <span style={{ color: tokens.colors.text.tertiary }}>\r\n Battery\r\n </span>\r\n <span\r\n style={{\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontVariantNumeric: \"tabular-nums\",\r\n }}\r\n >\r\n {formatPercentage(telemetry.power.batteryLevel, false, 0)}\r\n </span>\r\n </div>\r\n <div\r\n style={{\r\n height: 4,\r\n backgroundColor: tokens.colors.border.muted,\r\n borderRadius: 2,\r\n overflow: \"hidden\",\r\n }}\r\n >\r\n <div\r\n role=\"progressbar\"\r\n aria-valuenow={telemetry.power.batteryLevel}\r\n aria-valuemin={0}\r\n aria-valuemax={100}\r\n aria-label=\"Battery level\"\r\n style={{\r\n height: \"100%\",\r\n width: `${Math.min(100, Math.max(0, telemetry.power.batteryLevel))}%`,\r\n backgroundColor:\r\n telemetry.power.batteryLevel > 30\r\n ? tokens.colors.status.normal\r\n : tokens.colors.status.critical,\r\n borderRadius: 2,\r\n transition: `width ${transitionDuration} ease-out`,\r\n }}\r\n />\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Timestamp Footer */}\r\n {spacecraft.timestamp && (\r\n <footer\r\n style={{\r\n marginTop: tokens.spacing.md,\r\n paddingTop: tokens.spacing.sm,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.tertiary,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n <time dateTime={spacecraft.timestamp}>\r\n {formatTime(spacecraft.timestamp)} UTC\r\n </time>\r\n </footer>\r\n )}\r\n </article>\r\n );\r\n});\r\n\r\n// ============================================================================\r\n// Helper Components\r\n// ============================================================================\r\n\r\ninterface DataCellProps {\r\n label: string;\r\n value: string;\r\n highlight?: boolean;\r\n inline?: boolean;\r\n tokens: ReturnType<typeof useTheme>[\"tokens\"];\r\n /** WCAG AA safe highlight color (computed via safeAccentText) */\r\n highlightColor?: string;\r\n}\r\n\r\nconst DataCell = memo(function DataCell({\r\n label,\r\n value,\r\n highlight = false,\r\n inline = false,\r\n tokens,\r\n highlightColor,\r\n}: DataCellProps): React.ReactElement {\r\n if (inline) {\r\n return (\r\n <div\r\n style={{\r\n display: \"flex\",\r\n justifyContent: \"space-between\",\r\n alignItems: \"center\",\r\n }}\r\n >\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.secondary, // WCAG AA compliant\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n {label}\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontVariantNumeric: \"tabular-nums\",\r\n color: tokens.colors.text.primary,\r\n }}\r\n >\r\n {value}\r\n </span>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div>\r\n <span\r\n style={{\r\n display: \"block\",\r\n fontSize: tokens.typography.fontSize.xs,\r\n color: tokens.colors.text.secondary, // WCAG AA compliant\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n marginBottom: 2,\r\n }}\r\n >\r\n {label}\r\n </span>\r\n <span\r\n style={{\r\n display: \"block\",\r\n fontSize: tokens.typography.fontSize.sm,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontVariantNumeric: \"tabular-nums\",\r\n color: highlight\r\n ? (highlightColor ?? safeAccentText(tokens.colors.accent.primary))\r\n : tokens.colors.text.primary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n {value}\r\n </span>\r\n </div>\r\n );\r\n});\r\n"],"mappings":"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"}