@zendir/ui 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +0 -169
- package/dist/index.js.map +1 -1
- package/dist/react/context/DisplaySettingsContext.js +0 -12
- package/dist/react/context/DisplaySettingsContext.js.map +1 -1
- package/dist/react/core/AstroIcon.js +1 -816
- package/dist/react/core/AstroIcon.js.map +1 -1
- package/dist/react/core/index.d.ts +0 -1
- package/dist/react/index.d.ts +2 -42
- package/dist/react/utils/index.js +0 -8
- package/dist/react/utils/index.js.map +1 -1
- package/dist/react.js +0 -169
- package/dist/react.js.map +1 -1
- package/package.json +1 -1
- package/dist/react/3d/EarthViewer.js +0 -836
- package/dist/react/3d/EarthViewer.js.map +0 -1
- package/dist/react/3d/SolarSystemViewer.js +0 -372
- package/dist/react/3d/SolarSystemViewer.js.map +0 -1
- package/dist/react/3d/ZenSpace3D.js +0 -1253
- package/dist/react/3d/ZenSpace3D.js.map +0 -1
- package/dist/react/3d/ZenSpace3DCesium.js +0 -186
- package/dist/react/3d/ZenSpace3DCesium.js.map +0 -1
- package/dist/react/3d/ZenSpace3DShaders.js +0 -94
- package/dist/react/3d/ZenSpace3DShaders.js.map +0 -1
- package/dist/react/3d/ZenSpace3DUtils.js +0 -213
- package/dist/react/3d/ZenSpace3DUtils.js.map +0 -1
- package/dist/react/3d/threeLoader.js +0 -18
- package/dist/react/3d/threeLoader.js.map +0 -1
- package/dist/react/cards/AccessCard.js +0 -410
- package/dist/react/cards/AccessCard.js.map +0 -1
- package/dist/react/cards/OrbitCard.js +0 -372
- package/dist/react/cards/OrbitCard.js.map +0 -1
- package/dist/react/cards/SpacecraftCard.js +0 -941
- package/dist/react/cards/SpacecraftCard.js.map +0 -1
- package/dist/react/cards/TelemetryCard.js +0 -742
- package/dist/react/cards/TelemetryCard.js.map +0 -1
- package/dist/react/cards/TelemetryStreamCard.js +0 -309
- package/dist/react/cards/TelemetryStreamCard.js.map +0 -1
- package/dist/react/charts/GroundTrackMap.js +0 -1123
- package/dist/react/charts/GroundTrackMap.js.map +0 -1
- package/dist/react/charts/GroundTrackMapLeaflet.js +0 -571
- package/dist/react/charts/GroundTrackMapLeaflet.js.map +0 -1
- package/dist/react/charts/groundTrackMapLeafletTiles.js +0 -11
- package/dist/react/charts/groundTrackMapLeafletTiles.js.map +0 -1
- package/dist/react/charts/groundTrackMapLeafletUtils.js +0 -109
- package/dist/react/charts/groundTrackMapLeafletUtils.js.map +0 -1
- package/dist/react/charts/unified/AstroChart.js +0 -1405
- package/dist/react/charts/unified/AstroChart.js.map +0 -1
- package/dist/react/charts/unified/PowerOverviewChart.js +0 -488
- package/dist/react/charts/unified/PowerOverviewChart.js.map +0 -1
- package/dist/react/charts/unified/domain.js +0 -3168
- package/dist/react/charts/unified/domain.js.map +0 -1
- package/dist/react/charts/unified/generators.js +0 -518
- package/dist/react/charts/unified/generators.js.map +0 -1
- package/dist/react/charts/unified/presets.js +0 -999
- package/dist/react/charts/unified/presets.js.map +0 -1
- package/dist/react/charts/unified/sync.js +0 -219
- package/dist/react/charts/unified/sync.js.map +0 -1
- package/dist/react/charts/unified/theme.js +0 -562
- package/dist/react/charts/unified/theme.js.map +0 -1
- package/dist/react/charts/unified/useChartStream.js +0 -226
- package/dist/react/charts/unified/useChartStream.js.map +0 -1
- package/dist/react/chatgpt/AppCard.js +0 -306
- package/dist/react/chatgpt/AppCard.js.map +0 -1
- package/dist/react/chatgpt/index.js +0 -166
- package/dist/react/chatgpt/index.js.map +0 -1
- package/dist/react/hooks/useSpacecraftPosition.js +0 -89
- package/dist/react/hooks/useSpacecraftPosition.js.map +0 -1
- package/dist/react/hooks/useTelemetry.js +0 -73
- package/dist/react/hooks/useTelemetry.js.map +0 -1
- package/dist/react/hooks/useZendirSession.js +0 -148
- package/dist/react/hooks/useZendirSession.js.map +0 -1
- package/dist/react/visualizations/EclipseTimerCard.js +0 -250
- package/dist/react/visualizations/EclipseTimerCard.js.map +0 -1
- package/dist/react/visualizations/LinkBudgetCard.js +0 -444
- package/dist/react/visualizations/LinkBudgetCard.js.map +0 -1
- package/dist/react/visualizations/NavBallCard.js +0 -243
- package/dist/react/visualizations/NavBallCard.js.map +0 -1
- package/dist/react/visualizations/PropulsionCard.js +0 -298
- package/dist/react/visualizations/PropulsionCard.js.map +0 -1
- package/dist/react/visualizations/SensorFootprintCard.js +0 -326
- package/dist/react/visualizations/SensorFootprintCard.js.map +0 -1
- package/dist/react/visualizations/ThermalHeatmapCard.js +0 -372
- package/dist/react/visualizations/ThermalHeatmapCard.js.map +0 -1
- package/dist/shaders/atmosphere.frag.js +0 -5
- package/dist/shaders/atmosphere.frag.js.map +0 -1
- package/dist/shaders/atmosphere.vert.js +0 -5
- package/dist/shaders/atmosphere.vert.js.map +0 -1
- package/dist/shaders/stars.frag.js +0 -5
- package/dist/shaders/stars.frag.js.map +0 -1
- package/dist/shaders/stars.vert.js +0 -5
- package/dist/shaders/stars.vert.js.map +0 -1
- package/dist/style.css +0 -143
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/react/utils/index.ts"],"sourcesContent":["/**\n * @zendir/ui - Enterprise Utility Functions\n * \n * Shared utilities for null-safety, formatting, and defensive coding.\n * These utilities ensure components never crash due to undefined data.\n */\n\n// ============================================================================\n// NULL SAFETY UTILITIES\n// ============================================================================\n\n/**\n * Safely access a value with a fallback for null/undefined\n * @example withNullSafety(data?.temperature, 0) // Returns 0 if undefined\n */\nexport function withNullSafety<T>(value: T | null | undefined, fallback: T): T {\n return value ?? fallback;\n}\n\n/**\n * Safely format a number, returning '--' if undefined\n * @example safeNumber(data?.value, 2) // \"123.45\" or \"--\"\n */\nexport function safeNumber(\n value: number | null | undefined,\n decimals: number = 2,\n fallback: string = '--'\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return fallback;\n }\n return value.toFixed(decimals);\n}\n\n/**\n * Check if value is a valid finite number\n */\nexport function isValidNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\n// ============================================================================\n// NUMBER FORMATTING\n// ============================================================================\n\nexport interface FormatNumberOptions {\n decimals?: number;\n locale?: string;\n notation?: 'standard' | 'scientific' | 'engineering' | 'compact';\n unit?: string;\n signDisplay?: 'auto' | 'never' | 'always' | 'exceptZero';\n}\n\n/**\n * Format a number with locale-aware formatting and optional unit\n * @example formatNumber(1234567, { notation: 'compact' }) // \"1.2M\"\n */\nexport function formatNumber(\n value: number | null | undefined,\n options: FormatNumberOptions = {}\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '--';\n }\n\n const {\n decimals = 2,\n locale = 'en-US',\n notation = 'standard',\n unit,\n signDisplay = 'auto',\n } = options;\n\n try {\n const formatted = new Intl.NumberFormat(locale, {\n notation,\n minimumFractionDigits: notation === 'compact' ? 0 : decimals,\n maximumFractionDigits: decimals,\n signDisplay,\n }).format(value);\n\n return unit ? `${formatted} ${unit}` : formatted;\n } catch {\n return value.toFixed(decimals);\n }\n}\n\n/**\n * Format a number with tabular (monospace) digits for alignment\n * Uses font-feature-settings: 'tnum' 1\n */\nexport function formatTabular(\n value: number | null | undefined,\n decimals: number = 2\n): string {\n return safeNumber(value, decimals);\n}\n\n// ============================================================================\n// UNIT-AWARE FORMATTING\n// ============================================================================\n\n/**\n * Format temperature with unit conversion\n * @example formatTemperature(25) // \"25.0°C\"\n * @example formatTemperature(25, 'fahrenheit') // \"77.0°F\"\n */\nexport function formatTemperature(\n celsius: number | null | undefined,\n unit: 'celsius' | 'fahrenheit' | 'kelvin' = 'celsius',\n decimals: number = 1\n): string {\n if (celsius === null || celsius === undefined || !Number.isFinite(celsius)) {\n return '--°C';\n }\n\n switch (unit) {\n case 'fahrenheit':\n return `${((celsius * 9) / 5 + 32).toFixed(decimals)}°F`;\n case 'kelvin':\n return `${(celsius + 273.15).toFixed(decimals)}K`;\n default:\n return `${celsius.toFixed(decimals)}°C`;\n }\n}\n\n/**\n * Format data rate with automatic unit scaling\n * @example formatDataRate(1500000) // \"1.50 Mbps\"\n */\nexport function formatDataRate(bitsPerSecond: number | null | undefined): string {\n if (bitsPerSecond === null || bitsPerSecond === undefined || !Number.isFinite(bitsPerSecond)) {\n return '-- bps';\n }\n\n const units = ['bps', 'Kbps', 'Mbps', 'Gbps', 'Tbps'];\n let unitIndex = 0;\n let value = bitsPerSecond;\n\n while (value >= 1000 && unitIndex < units.length - 1) {\n value /= 1000;\n unitIndex++;\n }\n\n return `${value.toFixed(2)} ${units[unitIndex]}`;\n}\n\n/**\n * Format distance with automatic unit scaling\n * @example formatDistance(1500) // \"1.50 km\"\n */\nexport function formatDistance(meters: number | null | undefined): string {\n if (meters === null || meters === undefined || !Number.isFinite(meters)) {\n return '-- m';\n }\n\n if (meters >= 1_000_000) {\n return `${(meters / 1_000_000).toFixed(2)} Mm`;\n } else if (meters >= 1_000) {\n return `${(meters / 1_000).toFixed(2)} km`;\n } else if (meters < 1) {\n return `${(meters * 100).toFixed(1)} cm`;\n }\n return `${meters.toFixed(1)} m`;\n}\n\n/**\n * Format altitude (always in km for space ops)\n * @example formatAltitude(418.2) // \"418.2 km\"\n */\nexport function formatAltitude(km: number | null | undefined): string {\n if (km === null || km === undefined || !Number.isFinite(km)) {\n return '-- km';\n }\n return `${km.toFixed(1)} km`;\n}\n\n/**\n * Format velocity\n * @example formatVelocity(7.66) // \"7.66 km/s\"\n */\nexport function formatVelocity(kmPerSec: number | null | undefined): string {\n if (kmPerSec === null || kmPerSec === undefined || !Number.isFinite(kmPerSec)) {\n return '-- km/s';\n }\n return `${kmPerSec.toFixed(2)} km/s`;\n}\n\n/**\n * Format percentage with bounds checking\n * @example formatPercentage(0.856) // \"85.6%\"\n * @example formatPercentage(85.6, false) // \"85.6%\" (already percentage)\n */\nexport function formatPercentage(\n value: number | null | undefined,\n isDecimal: boolean = false,\n decimals: number = 1\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '--%';\n }\n\n const percentage = isDecimal ? value * 100 : value;\n return `${percentage.toFixed(decimals)}%`;\n}\n\n/**\n * Format power (watts) with auto-scaling\n * @example formatPower(1500) // \"1.50 kW\"\n */\nexport function formatPower(watts: number | null | undefined): string {\n if (watts === null || watts === undefined || !Number.isFinite(watts)) {\n return '-- W';\n }\n\n if (Math.abs(watts) >= 1_000_000) {\n return `${(watts / 1_000_000).toFixed(2)} MW`;\n } else if (Math.abs(watts) >= 1_000) {\n return `${(watts / 1_000).toFixed(2)} kW`;\n } else if (Math.abs(watts) < 1) {\n return `${(watts * 1000).toFixed(1)} mW`;\n }\n return `${watts.toFixed(1)} W`;\n}\n\n/**\n * Format frequency (Hz) with auto-scaling\n * @example formatFrequency(2400000000) // \"2.40 GHz\"\n */\nexport function formatFrequency(hz: number | null | undefined): string {\n if (hz === null || hz === undefined || !Number.isFinite(hz)) {\n return '-- Hz';\n }\n\n if (hz >= 1_000_000_000) {\n return `${(hz / 1_000_000_000).toFixed(2)} GHz`;\n } else if (hz >= 1_000_000) {\n return `${(hz / 1_000_000).toFixed(2)} MHz`;\n } else if (hz >= 1_000) {\n return `${(hz / 1_000).toFixed(2)} kHz`;\n }\n return `${hz.toFixed(0)} Hz`;\n}\n\n// ============================================================================\n// TIME FORMATTING\n// ============================================================================\n\n/**\n * Format duration in human-readable form\n * @example formatDuration(3661) // \"1h 1m 1s\"\n */\nexport function formatDuration(seconds: number | null | undefined): string {\n if (seconds === null || seconds === undefined || !Number.isFinite(seconds)) {\n return '--:--';\n }\n\n const absSeconds = Math.abs(seconds);\n const sign = seconds < 0 ? '-' : '';\n\n if (absSeconds < 60) {\n return `${sign}${absSeconds.toFixed(0)}s`;\n } else if (absSeconds < 3600) {\n const mins = Math.floor(absSeconds / 60);\n const secs = Math.floor(absSeconds % 60);\n return `${sign}${mins}m ${secs}s`;\n } else if (absSeconds < 86400) {\n const hours = Math.floor(absSeconds / 3600);\n const mins = Math.floor((absSeconds % 3600) / 60);\n return `${sign}${hours}h ${mins}m`;\n } else {\n const days = Math.floor(absSeconds / 86400);\n const hours = Math.floor((absSeconds % 86400) / 3600);\n return `${sign}${days}d ${hours}h`;\n }\n}\n\n/**\n * Format countdown timer (supports negative values for past events)\n * @example formatCountdown(125) // \"T-02:05\"\n * @example formatCountdown(-60) // \"T+01:00\"\n */\nexport function formatCountdown(seconds: number | null | undefined): string {\n if (seconds === null || seconds === undefined || !Number.isFinite(seconds)) {\n return 'T--:--';\n }\n\n const prefix = seconds >= 0 ? 'T-' : 'T+';\n const absSeconds = Math.abs(seconds);\n\n if (absSeconds >= 3600) {\n const hours = Math.floor(absSeconds / 3600);\n const mins = Math.floor((absSeconds % 3600) / 60);\n const secs = Math.floor(absSeconds % 60);\n return `${prefix}${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n }\n\n const mins = Math.floor(absSeconds / 60);\n const secs = Math.floor(absSeconds % 60);\n return `${prefix}${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n}\n\n/**\n * Format UTC timestamp\n * @example formatUTC(new Date()) // \"2026-01-27 14:30:00Z\"\n */\nexport function formatUTC(date: Date | string | null | undefined): string {\n if (!date) return '--:--:-- UTC';\n\n try {\n const d = typeof date === 'string' ? new Date(date) : date;\n if (isNaN(d.getTime())) return '--:--:-- UTC';\n\n return d.toISOString().replace('T', ' ').slice(0, 19) + 'Z';\n } catch {\n return '--:--:-- UTC';\n }\n}\n\n/**\n * Format time only (HH:MM:SS)\n * @example formatTime(new Date()) // \"14:30:00\"\n */\nexport function formatTime(date: Date | string | null | undefined, includeSeconds = true): string {\n if (!date) return includeSeconds ? '--:--:--' : '--:--';\n\n try {\n const d = typeof date === 'string' ? new Date(date) : date;\n if (isNaN(d.getTime())) return includeSeconds ? '--:--:--' : '--:--';\n\n const hours = d.getUTCHours().toString().padStart(2, '0');\n const mins = d.getUTCMinutes().toString().padStart(2, '0');\n const secs = d.getUTCSeconds().toString().padStart(2, '0');\n\n return includeSeconds ? `${hours}:${mins}:${secs}` : `${hours}:${mins}`;\n } catch {\n return includeSeconds ? '--:--:--' : '--:--';\n }\n}\n\n// ============================================================================\n// COORDINATE FORMATTING\n// ============================================================================\n\n/**\n * Format latitude/longitude\n * @example formatCoordinate(32.4, 'lat') // \"32.40° N\"\n * @example formatCoordinate(-117.2, 'lon') // \"117.20° W\"\n */\nexport function formatCoordinate(\n value: number | null | undefined,\n type: 'lat' | 'lon'\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '--°';\n }\n\n const absValue = Math.abs(value);\n let direction: string;\n\n if (type === 'lat') {\n direction = value >= 0 ? 'N' : 'S';\n } else {\n direction = value >= 0 ? 'E' : 'W';\n }\n\n return `${absValue.toFixed(2)}° ${direction}`;\n}\n\n/**\n * Format lat/lon pair\n * @example formatLatLon(32.4, -117.2) // \"32.40° N, 117.20° W\"\n */\nexport function formatLatLon(\n lat: number | null | undefined,\n lon: number | null | undefined\n): string {\n return `${formatCoordinate(lat, 'lat')}, ${formatCoordinate(lon, 'lon')}`;\n}\n\n// ============================================================================\n// ANGLE FORMATTING\n// ============================================================================\n\n/**\n * Format angle in degrees\n * @example formatDegrees(45.5) // \"45.5°\"\n */\nexport function formatDegrees(\n value: number | null | undefined,\n decimals: number = 1\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '--°';\n }\n return `${value.toFixed(decimals)}°`;\n}\n\n/**\n * Format decibels\n * @example formatDecibels(3.5) // \"3.5 dB\"\n */\nexport function formatDecibels(\n value: number | null | undefined,\n decimals: number = 1\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '-- dB';\n }\n return `${value.toFixed(decimals)} dB`;\n}\n\n// ============================================================================\n// VALUE UTILITIES\n// ============================================================================\n\n/**\n * Clamp a value between min and max\n * @example clamp(150, 0, 100) // 100\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Linear interpolation\n * @example lerp(0, 100, 0.5) // 50\n */\nexport function lerp(start: number, end: number, t: number): number {\n return start + (end - start) * clamp(t, 0, 1);\n}\n\n/**\n * Map a value from one range to another\n * @example mapRange(50, 0, 100, 0, 1) // 0.5\n */\nexport function mapRange(\n value: number,\n inMin: number,\n inMax: number,\n outMin: number,\n outMax: number\n): number {\n const t = (value - inMin) / (inMax - inMin);\n return lerp(outMin, outMax, t);\n}\n\n// ============================================================================\n// STATUS UTILITIES\n// ============================================================================\n\nexport type StatusLevel = 'off' | 'standby' | 'normal' | 'caution' | 'serious' | 'critical';\n\n/**\n * Astro UX Design System status colors\n * These match the official Astro status semantics\n */\nexport const STATUS_COLORS: Record<StatusLevel, string> = {\n off: '#a4abb6',\n standby: '#2dccff',\n normal: '#56f000',\n caution: '#fce83a',\n serious: '#ffb302',\n critical: '#ff3838',\n};\n\n/**\n * Get status color from level\n * @example getStatusColor('normal') // '#56f000'\n */\nexport function getStatusColor(status: StatusLevel | null | undefined): string {\n return STATUS_COLORS[status ?? 'off'];\n}\n\n/**\n * Derive status for battery specifically (low is bad)\n * @example deriveBatteryStatus(25) // 'caution'\n */\nexport function deriveBatteryStatus(level: number | undefined | null): StatusLevel {\n if (level === undefined || level === null) return 'off';\n if (level <= 10) return 'critical';\n if (level <= 20) return 'serious';\n if (level <= 30) return 'caution';\n return 'normal';\n}\n\n/**\n * Determine status level from a value and thresholds\n * @example getStatusFromValue(85, { critical: 20, serious: 40, caution: 60, normal: 80 }) // 'normal'\n */\nexport function getStatusFromValue(\n value: number | null | undefined,\n thresholds: {\n critical?: number;\n serious?: number;\n caution?: number;\n normal?: number;\n },\n higherIsBetter: boolean = true\n): StatusLevel {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return 'off';\n }\n\n const { critical = 10, serious = 25, caution = 50, normal = 75 } = thresholds;\n\n if (higherIsBetter) {\n if (value <= critical) return 'critical';\n if (value <= serious) return 'serious';\n if (value <= caution) return 'caution';\n if (value <= normal) return 'standby';\n return 'normal';\n } else {\n if (value >= critical) return 'critical';\n if (value >= serious) return 'serious';\n if (value >= caution) return 'caution';\n if (value >= normal) return 'standby';\n return 'normal';\n }\n}\n\n// ============================================================================\n// STATUS NORMALIZATION\n// ============================================================================\n\n/**\n * Domain status terms that map to UI StatusLevel\n * This handles common backend/sensor terminology\n */\nconst STATUS_MAPPING: Record<string, StatusLevel> = {\n // → 'off'\n 'off': 'off',\n 'disabled': 'off',\n 'inactive': 'off',\n 'offline': 'off',\n 'unknown': 'off',\n 'null': 'off',\n 'none': 'off',\n \n // → 'standby'\n 'standby': 'standby',\n 'idle': 'standby',\n 'waiting': 'standby',\n 'ready': 'standby',\n 'pending': 'standby',\n 'queued': 'standby',\n \n // → 'normal'\n 'normal': 'normal',\n 'nominal': 'normal',\n 'healthy': 'normal',\n 'ok': 'normal',\n 'good': 'normal',\n 'success': 'normal',\n 'operational': 'normal',\n 'active': 'normal',\n 'online': 'normal',\n 'connected': 'normal',\n 'stable': 'normal',\n 'transmitting': 'normal',\n 'receiving': 'normal',\n \n // → 'caution'\n 'caution': 'caution',\n 'warning': 'caution',\n 'degraded': 'caution',\n 'elevated': 'caution',\n 'alert': 'caution',\n 'attention': 'caution',\n 'limited': 'caution',\n \n // → 'serious'\n 'serious': 'serious',\n 'unstable': 'serious',\n 'danger': 'serious',\n 'severe': 'serious',\n \n // → 'critical'\n 'critical': 'critical',\n 'error': 'critical',\n 'failed': 'critical',\n 'failure': 'critical',\n 'emergency': 'critical',\n 'fault': 'critical',\n 'alarm': 'critical',\n};\n\n/**\n * Normalize any status string to the 6-level StatusLevel system\n * \n * @param status - Any status string from domain/backend\n * @param defaultStatus - Fallback if status is not recognized (default: 'off')\n * @returns StatusLevel\n * \n * @example\n * ```typescript\n * normalizeStatus('degraded') // 'caution'\n * normalizeStatus('nominal') // 'normal'\n * normalizeStatus('transmitting') // 'normal'\n * normalizeStatus('warning') // 'caution'\n * normalizeStatus('error') // 'critical'\n * normalizeStatus(undefined) // 'off'\n * ```\n */\nexport function normalizeStatus(\n status: string | undefined | null,\n defaultStatus: StatusLevel = 'off'\n): StatusLevel {\n if (!status) return defaultStatus;\n \n const normalized = status.toLowerCase().trim();\n return STATUS_MAPPING[normalized] ?? defaultStatus;\n}\n\n/**\n * Check if a string is a valid StatusLevel\n */\nexport function isStatusLevel(value: string): value is StatusLevel {\n return ['off', 'standby', 'normal', 'caution', 'serious', 'critical'].includes(value);\n}\n\n/**\n * Get the severity order of a status (higher = more severe)\n * Useful for sorting or finding worst status\n */\nexport function getStatusSeverity(status: StatusLevel): number {\n const order: Record<StatusLevel, number> = {\n off: 0,\n standby: 1,\n normal: 2,\n caution: 3,\n serious: 4,\n critical: 5,\n };\n return order[status];\n}\n\n/**\n * Get the worst (most severe) status from an array\n * \n * @example\n * ```typescript\n * getWorstStatus(['normal', 'caution', 'normal']) // 'caution'\n * getWorstStatus(['normal', 'critical', 'caution']) // 'critical'\n * ```\n */\nexport function getWorstStatus(statuses: StatusLevel[]): StatusLevel {\n if (statuses.length === 0) return 'off';\n return statuses.reduce((worst, current) => \n getStatusSeverity(current) > getStatusSeverity(worst) ? current : worst\n );\n}\n\n// ============================================================================\n// COLOR UTILITIES\n// ============================================================================\n\n/**\n * Safely add alpha to any CSS color string.\n * Handles hex (#RRGGBB → #RRGGBBAA), rgb(), and rgba() formats.\n *\n * Avoids the common bug of appending a hex alpha string to an rgba() color,\n * which produces invalid CSS (e.g. \"rgba(15, 20, 35, 0.85)80\").\n *\n * @param color - CSS color string (hex, rgb, or rgba)\n * @param alpha - Alpha value 0–1\n * @returns Valid CSS color string with alpha applied\n *\n * @example\n * addAlpha('#1b2d3e', 0.5) // '#1b2d3e80'\n * addAlpha('rgba(15, 20, 35, 0.85)', 0.5) // 'rgba(15, 20, 35, 0.5)'\n * addAlpha('rgb(15, 20, 35)', 0.031) // 'rgba(15, 20, 35, 0.031)'\n */\nexport function addAlpha(color: string, alpha: number): string {\n if (!color) return color;\n const a = Math.max(0, Math.min(1, alpha));\n if (color.startsWith('rgba(')) {\n return color.replace(/,\\s*[\\d.]+\\)\\s*$/, `, ${a})`);\n }\n if (color.startsWith('rgb(')) {\n return color.replace(/^rgb\\(/, 'rgba(').replace(/\\)\\s*$/, `, ${a})`);\n }\n if (color.startsWith('#')) {\n const hexA = Math.round(a * 255).toString(16).padStart(2, '0');\n return `${color}${hexA}`;\n }\n return color;\n}\n\n// ============================================================================\n// COMPONENT STYLE UTILITIES\n// ============================================================================\n\n/**\n * Merge class names, filtering out falsy values\n * @example classNames('base', isActive && 'active', className) // \"base active custom\"\n */\nexport function classNames(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n\n/**\n * Generate CSS for tabular numbers (monospace digits)\n */\nexport const tabularNumsStyle: React.CSSProperties = {\n fontVariantNumeric: 'tabular-nums',\n fontFeatureSettings: '\"tnum\" 1',\n};\n\n/**\n * CSS transition presets\n */\nexport const transitions = {\n fast: 'all 150ms ease-out',\n normal: 'all 250ms ease-out',\n slow: 'all 400ms ease-out',\n spring: 'all 300ms cubic-bezier(0.34, 1.56, 0.64, 1)',\n} as const;\n\n/**\n * Focus ring styles for accessibility\n */\nexport const focusRingStyle: React.CSSProperties = {\n outline: '2px solid #4dc3ff',\n outlineOffset: '2px',\n};\n\n/**\n * Compute a WCAG AA safe version of an accent color for use as foreground text\n * on dark backgrounds. If the accent already passes 4.5:1 contrast on typical\n * dark surfaces (L ≈ 0.01), returns it unchanged. Otherwise lightens toward\n * white until the minimum contrast is met.\n *\n * @example safeAccentText('#8b5cf6') // '#a885f8' — lightened to pass 4.5:1\n */\nexport function safeAccentText(accent: string): string {\n const hex = accent.replace('#', '');\n if (hex.length < 6) return accent;\n\n const r = parseInt(hex.slice(0, 2), 16) / 255;\n const g = parseInt(hex.slice(2, 4), 16) / 255;\n const b = parseInt(hex.slice(4, 6), 16) / 255;\n const toLinear = (c: number) =>\n c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n const L = 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);\n\n // Threshold: on a dark surface with L≈0.01 we need text L ≥ 0.22 for 4.5:1\n if (L >= 0.22) return accent;\n\n // Lighten by mixing 25% toward white — reaches ~5.5:1 on typical dark bgs\n const mix = 0.25;\n const lr = Math.min(255, Math.round((r + (1 - r) * mix) * 255));\n const lg = Math.min(255, Math.round((g + (1 - g) * mix) * 255));\n const lb = Math.min(255, Math.round((b + (1 - b) * mix) * 255));\n return `#${lr.toString(16).padStart(2, '0')}${lg.toString(16).padStart(2, '0')}${lb.toString(16).padStart(2, '0')}`;\n}\n"],"names":["mins","secs"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/react/utils/index.ts"],"sourcesContent":["/**\n * @zendir/ui - Enterprise Utility Functions\n * \n * Shared utilities for null-safety, formatting, and defensive coding.\n * These utilities ensure components never crash due to undefined data.\n */\n\n// ============================================================================\n// NULL SAFETY UTILITIES\n// ============================================================================\n\n/**\n * Safely access a value with a fallback for null/undefined\n * @example withNullSafety(data?.temperature, 0) // Returns 0 if undefined\n */\nexport function withNullSafety<T>(value: T | null | undefined, fallback: T): T {\n return value ?? fallback;\n}\n\n/**\n * Safely format a number, returning '--' if undefined\n * @example safeNumber(data?.value, 2) // \"123.45\" or \"--\"\n */\nexport function safeNumber(\n value: number | null | undefined,\n decimals: number = 2,\n fallback: string = '--'\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return fallback;\n }\n return value.toFixed(decimals);\n}\n\n/**\n * Check if value is a valid finite number\n */\nexport function isValidNumber(value: unknown): value is number {\n return typeof value === 'number' && Number.isFinite(value);\n}\n\n// ============================================================================\n// NUMBER FORMATTING\n// ============================================================================\n\nexport interface FormatNumberOptions {\n decimals?: number;\n locale?: string;\n notation?: 'standard' | 'scientific' | 'engineering' | 'compact';\n unit?: string;\n signDisplay?: 'auto' | 'never' | 'always' | 'exceptZero';\n}\n\n/**\n * Format a number with locale-aware formatting and optional unit\n * @example formatNumber(1234567, { notation: 'compact' }) // \"1.2M\"\n */\nexport function formatNumber(\n value: number | null | undefined,\n options: FormatNumberOptions = {}\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '--';\n }\n\n const {\n decimals = 2,\n locale = 'en-US',\n notation = 'standard',\n unit,\n signDisplay = 'auto',\n } = options;\n\n try {\n const formatted = new Intl.NumberFormat(locale, {\n notation,\n minimumFractionDigits: notation === 'compact' ? 0 : decimals,\n maximumFractionDigits: decimals,\n signDisplay,\n }).format(value);\n\n return unit ? `${formatted} ${unit}` : formatted;\n } catch {\n return value.toFixed(decimals);\n }\n}\n\n/**\n * Format a number with tabular (monospace) digits for alignment\n * Uses font-feature-settings: 'tnum' 1\n */\nexport function formatTabular(\n value: number | null | undefined,\n decimals: number = 2\n): string {\n return safeNumber(value, decimals);\n}\n\n// ============================================================================\n// UNIT-AWARE FORMATTING\n// ============================================================================\n\n/**\n * Format temperature with unit conversion\n * @example formatTemperature(25) // \"25.0°C\"\n * @example formatTemperature(25, 'fahrenheit') // \"77.0°F\"\n */\nexport function formatTemperature(\n celsius: number | null | undefined,\n unit: 'celsius' | 'fahrenheit' | 'kelvin' = 'celsius',\n decimals: number = 1\n): string {\n if (celsius === null || celsius === undefined || !Number.isFinite(celsius)) {\n return '--°C';\n }\n\n switch (unit) {\n case 'fahrenheit':\n return `${((celsius * 9) / 5 + 32).toFixed(decimals)}°F`;\n case 'kelvin':\n return `${(celsius + 273.15).toFixed(decimals)}K`;\n default:\n return `${celsius.toFixed(decimals)}°C`;\n }\n}\n\n/**\n * Format data rate with automatic unit scaling\n * @example formatDataRate(1500000) // \"1.50 Mbps\"\n */\nexport function formatDataRate(bitsPerSecond: number | null | undefined): string {\n if (bitsPerSecond === null || bitsPerSecond === undefined || !Number.isFinite(bitsPerSecond)) {\n return '-- bps';\n }\n\n const units = ['bps', 'Kbps', 'Mbps', 'Gbps', 'Tbps'];\n let unitIndex = 0;\n let value = bitsPerSecond;\n\n while (value >= 1000 && unitIndex < units.length - 1) {\n value /= 1000;\n unitIndex++;\n }\n\n return `${value.toFixed(2)} ${units[unitIndex]}`;\n}\n\n/**\n * Format distance with automatic unit scaling\n * @example formatDistance(1500) // \"1.50 km\"\n */\nexport function formatDistance(meters: number | null | undefined): string {\n if (meters === null || meters === undefined || !Number.isFinite(meters)) {\n return '-- m';\n }\n\n if (meters >= 1_000_000) {\n return `${(meters / 1_000_000).toFixed(2)} Mm`;\n } else if (meters >= 1_000) {\n return `${(meters / 1_000).toFixed(2)} km`;\n } else if (meters < 1) {\n return `${(meters * 100).toFixed(1)} cm`;\n }\n return `${meters.toFixed(1)} m`;\n}\n\n/**\n * Format altitude (always in km for space ops)\n * @example formatAltitude(418.2) // \"418.2 km\"\n */\nexport function formatAltitude(km: number | null | undefined): string {\n if (km === null || km === undefined || !Number.isFinite(km)) {\n return '-- km';\n }\n return `${km.toFixed(1)} km`;\n}\n\n/**\n * Format velocity\n * @example formatVelocity(7.66) // \"7.66 km/s\"\n */\nexport function formatVelocity(kmPerSec: number | null | undefined): string {\n if (kmPerSec === null || kmPerSec === undefined || !Number.isFinite(kmPerSec)) {\n return '-- km/s';\n }\n return `${kmPerSec.toFixed(2)} km/s`;\n}\n\n/**\n * Format percentage with bounds checking\n * @example formatPercentage(0.856) // \"85.6%\"\n * @example formatPercentage(85.6, false) // \"85.6%\" (already percentage)\n */\nexport function formatPercentage(\n value: number | null | undefined,\n isDecimal: boolean = false,\n decimals: number = 1\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '--%';\n }\n\n const percentage = isDecimal ? value * 100 : value;\n return `${percentage.toFixed(decimals)}%`;\n}\n\n/**\n * Format power (watts) with auto-scaling\n * @example formatPower(1500) // \"1.50 kW\"\n */\nexport function formatPower(watts: number | null | undefined): string {\n if (watts === null || watts === undefined || !Number.isFinite(watts)) {\n return '-- W';\n }\n\n if (Math.abs(watts) >= 1_000_000) {\n return `${(watts / 1_000_000).toFixed(2)} MW`;\n } else if (Math.abs(watts) >= 1_000) {\n return `${(watts / 1_000).toFixed(2)} kW`;\n } else if (Math.abs(watts) < 1) {\n return `${(watts * 1000).toFixed(1)} mW`;\n }\n return `${watts.toFixed(1)} W`;\n}\n\n/**\n * Format frequency (Hz) with auto-scaling\n * @example formatFrequency(2400000000) // \"2.40 GHz\"\n */\nexport function formatFrequency(hz: number | null | undefined): string {\n if (hz === null || hz === undefined || !Number.isFinite(hz)) {\n return '-- Hz';\n }\n\n if (hz >= 1_000_000_000) {\n return `${(hz / 1_000_000_000).toFixed(2)} GHz`;\n } else if (hz >= 1_000_000) {\n return `${(hz / 1_000_000).toFixed(2)} MHz`;\n } else if (hz >= 1_000) {\n return `${(hz / 1_000).toFixed(2)} kHz`;\n }\n return `${hz.toFixed(0)} Hz`;\n}\n\n// ============================================================================\n// TIME FORMATTING\n// ============================================================================\n\n/**\n * Format duration in human-readable form\n * @example formatDuration(3661) // \"1h 1m 1s\"\n */\nexport function formatDuration(seconds: number | null | undefined): string {\n if (seconds === null || seconds === undefined || !Number.isFinite(seconds)) {\n return '--:--';\n }\n\n const absSeconds = Math.abs(seconds);\n const sign = seconds < 0 ? '-' : '';\n\n if (absSeconds < 60) {\n return `${sign}${absSeconds.toFixed(0)}s`;\n } else if (absSeconds < 3600) {\n const mins = Math.floor(absSeconds / 60);\n const secs = Math.floor(absSeconds % 60);\n return `${sign}${mins}m ${secs}s`;\n } else if (absSeconds < 86400) {\n const hours = Math.floor(absSeconds / 3600);\n const mins = Math.floor((absSeconds % 3600) / 60);\n return `${sign}${hours}h ${mins}m`;\n } else {\n const days = Math.floor(absSeconds / 86400);\n const hours = Math.floor((absSeconds % 86400) / 3600);\n return `${sign}${days}d ${hours}h`;\n }\n}\n\n/**\n * Format countdown timer (supports negative values for past events)\n * @example formatCountdown(125) // \"T-02:05\"\n * @example formatCountdown(-60) // \"T+01:00\"\n */\nexport function formatCountdown(seconds: number | null | undefined): string {\n if (seconds === null || seconds === undefined || !Number.isFinite(seconds)) {\n return 'T--:--';\n }\n\n const prefix = seconds >= 0 ? 'T-' : 'T+';\n const absSeconds = Math.abs(seconds);\n\n if (absSeconds >= 3600) {\n const hours = Math.floor(absSeconds / 3600);\n const mins = Math.floor((absSeconds % 3600) / 60);\n const secs = Math.floor(absSeconds % 60);\n return `${prefix}${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n }\n\n const mins = Math.floor(absSeconds / 60);\n const secs = Math.floor(absSeconds % 60);\n return `${prefix}${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n}\n\n/**\n * Format UTC timestamp\n * @example formatUTC(new Date()) // \"2026-01-27 14:30:00Z\"\n */\nexport function formatUTC(date: Date | string | null | undefined): string {\n if (!date) return '--:--:-- UTC';\n\n try {\n const d = typeof date === 'string' ? new Date(date) : date;\n if (isNaN(d.getTime())) return '--:--:-- UTC';\n\n return d.toISOString().replace('T', ' ').slice(0, 19) + 'Z';\n } catch {\n return '--:--:-- UTC';\n }\n}\n\n/**\n * Format time only (HH:MM:SS)\n * @example formatTime(new Date()) // \"14:30:00\"\n */\nexport function formatTime(date: Date | string | null | undefined, includeSeconds = true): string {\n if (!date) return includeSeconds ? '--:--:--' : '--:--';\n\n try {\n const d = typeof date === 'string' ? new Date(date) : date;\n if (isNaN(d.getTime())) return includeSeconds ? '--:--:--' : '--:--';\n\n const hours = d.getUTCHours().toString().padStart(2, '0');\n const mins = d.getUTCMinutes().toString().padStart(2, '0');\n const secs = d.getUTCSeconds().toString().padStart(2, '0');\n\n return includeSeconds ? `${hours}:${mins}:${secs}` : `${hours}:${mins}`;\n } catch {\n return includeSeconds ? '--:--:--' : '--:--';\n }\n}\n\n// ============================================================================\n// COORDINATE FORMATTING\n// ============================================================================\n\n/**\n * Format latitude/longitude\n * @example formatCoordinate(32.4, 'lat') // \"32.40° N\"\n * @example formatCoordinate(-117.2, 'lon') // \"117.20° W\"\n */\nexport function formatCoordinate(\n value: number | null | undefined,\n type: 'lat' | 'lon'\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '--°';\n }\n\n const absValue = Math.abs(value);\n let direction: string;\n\n if (type === 'lat') {\n direction = value >= 0 ? 'N' : 'S';\n } else {\n direction = value >= 0 ? 'E' : 'W';\n }\n\n return `${absValue.toFixed(2)}° ${direction}`;\n}\n\n/**\n * Format lat/lon pair\n * @example formatLatLon(32.4, -117.2) // \"32.40° N, 117.20° W\"\n */\nexport function formatLatLon(\n lat: number | null | undefined,\n lon: number | null | undefined\n): string {\n return `${formatCoordinate(lat, 'lat')}, ${formatCoordinate(lon, 'lon')}`;\n}\n\n// ============================================================================\n// ANGLE FORMATTING\n// ============================================================================\n\n/**\n * Format angle in degrees\n * @example formatDegrees(45.5) // \"45.5°\"\n */\nexport function formatDegrees(\n value: number | null | undefined,\n decimals: number = 1\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '--°';\n }\n return `${value.toFixed(decimals)}°`;\n}\n\n/**\n * Format decibels\n * @example formatDecibels(3.5) // \"3.5 dB\"\n */\nexport function formatDecibels(\n value: number | null | undefined,\n decimals: number = 1\n): string {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return '-- dB';\n }\n return `${value.toFixed(decimals)} dB`;\n}\n\n// ============================================================================\n// VALUE UTILITIES\n// ============================================================================\n\n/**\n * Clamp a value between min and max\n * @example clamp(150, 0, 100) // 100\n */\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/**\n * Linear interpolation\n * @example lerp(0, 100, 0.5) // 50\n */\nexport function lerp(start: number, end: number, t: number): number {\n return start + (end - start) * clamp(t, 0, 1);\n}\n\n/**\n * Map a value from one range to another\n * @example mapRange(50, 0, 100, 0, 1) // 0.5\n */\nexport function mapRange(\n value: number,\n inMin: number,\n inMax: number,\n outMin: number,\n outMax: number\n): number {\n const t = (value - inMin) / (inMax - inMin);\n return lerp(outMin, outMax, t);\n}\n\n// ============================================================================\n// STATUS UTILITIES\n// ============================================================================\n\nexport type StatusLevel = 'off' | 'standby' | 'normal' | 'caution' | 'serious' | 'critical';\n\n/**\n * Astro UX Design System status colors\n * These match the official Astro status semantics\n */\nexport const STATUS_COLORS: Record<StatusLevel, string> = {\n off: '#a4abb6',\n standby: '#2dccff',\n normal: '#56f000',\n caution: '#fce83a',\n serious: '#ffb302',\n critical: '#ff3838',\n};\n\n/**\n * Get status color from level\n * @example getStatusColor('normal') // '#56f000'\n */\nexport function getStatusColor(status: StatusLevel | null | undefined): string {\n return STATUS_COLORS[status ?? 'off'];\n}\n\n/**\n * Derive status for battery specifically (low is bad)\n * @example deriveBatteryStatus(25) // 'caution'\n */\nexport function deriveBatteryStatus(level: number | undefined | null): StatusLevel {\n if (level === undefined || level === null) return 'off';\n if (level <= 10) return 'critical';\n if (level <= 20) return 'serious';\n if (level <= 30) return 'caution';\n return 'normal';\n}\n\n/**\n * Determine status level from a value and thresholds\n * @example getStatusFromValue(85, { critical: 20, serious: 40, caution: 60, normal: 80 }) // 'normal'\n */\nexport function getStatusFromValue(\n value: number | null | undefined,\n thresholds: {\n critical?: number;\n serious?: number;\n caution?: number;\n normal?: number;\n },\n higherIsBetter: boolean = true\n): StatusLevel {\n if (value === null || value === undefined || !Number.isFinite(value)) {\n return 'off';\n }\n\n const { critical = 10, serious = 25, caution = 50, normal = 75 } = thresholds;\n\n if (higherIsBetter) {\n if (value <= critical) return 'critical';\n if (value <= serious) return 'serious';\n if (value <= caution) return 'caution';\n if (value <= normal) return 'standby';\n return 'normal';\n } else {\n if (value >= critical) return 'critical';\n if (value >= serious) return 'serious';\n if (value >= caution) return 'caution';\n if (value >= normal) return 'standby';\n return 'normal';\n }\n}\n\n// ============================================================================\n// STATUS NORMALIZATION\n// ============================================================================\n\n/**\n * Domain status terms that map to UI StatusLevel\n * This handles common backend/sensor terminology\n */\nconst STATUS_MAPPING: Record<string, StatusLevel> = {\n // → 'off'\n 'off': 'off',\n 'disabled': 'off',\n 'inactive': 'off',\n 'offline': 'off',\n 'unknown': 'off',\n 'null': 'off',\n 'none': 'off',\n \n // → 'standby'\n 'standby': 'standby',\n 'idle': 'standby',\n 'waiting': 'standby',\n 'ready': 'standby',\n 'pending': 'standby',\n 'queued': 'standby',\n \n // → 'normal'\n 'normal': 'normal',\n 'nominal': 'normal',\n 'healthy': 'normal',\n 'ok': 'normal',\n 'good': 'normal',\n 'success': 'normal',\n 'operational': 'normal',\n 'active': 'normal',\n 'online': 'normal',\n 'connected': 'normal',\n 'stable': 'normal',\n 'transmitting': 'normal',\n 'receiving': 'normal',\n \n // → 'caution'\n 'caution': 'caution',\n 'warning': 'caution',\n 'degraded': 'caution',\n 'elevated': 'caution',\n 'alert': 'caution',\n 'attention': 'caution',\n 'limited': 'caution',\n \n // → 'serious'\n 'serious': 'serious',\n 'unstable': 'serious',\n 'danger': 'serious',\n 'severe': 'serious',\n \n // → 'critical'\n 'critical': 'critical',\n 'error': 'critical',\n 'failed': 'critical',\n 'failure': 'critical',\n 'emergency': 'critical',\n 'fault': 'critical',\n 'alarm': 'critical',\n};\n\n/**\n * Normalize any status string to the 6-level StatusLevel system\n * \n * @param status - Any status string from domain/backend\n * @param defaultStatus - Fallback if status is not recognized (default: 'off')\n * @returns StatusLevel\n * \n * @example\n * ```typescript\n * normalizeStatus('degraded') // 'caution'\n * normalizeStatus('nominal') // 'normal'\n * normalizeStatus('transmitting') // 'normal'\n * normalizeStatus('warning') // 'caution'\n * normalizeStatus('error') // 'critical'\n * normalizeStatus(undefined) // 'off'\n * ```\n */\nexport function normalizeStatus(\n status: string | undefined | null,\n defaultStatus: StatusLevel = 'off'\n): StatusLevel {\n if (!status) return defaultStatus;\n \n const normalized = status.toLowerCase().trim();\n return STATUS_MAPPING[normalized] ?? defaultStatus;\n}\n\n/**\n * Check if a string is a valid StatusLevel\n */\nexport function isStatusLevel(value: string): value is StatusLevel {\n return ['off', 'standby', 'normal', 'caution', 'serious', 'critical'].includes(value);\n}\n\n/**\n * Get the severity order of a status (higher = more severe)\n * Useful for sorting or finding worst status\n */\nexport function getStatusSeverity(status: StatusLevel): number {\n const order: Record<StatusLevel, number> = {\n off: 0,\n standby: 1,\n normal: 2,\n caution: 3,\n serious: 4,\n critical: 5,\n };\n return order[status];\n}\n\n/**\n * Get the worst (most severe) status from an array\n * \n * @example\n * ```typescript\n * getWorstStatus(['normal', 'caution', 'normal']) // 'caution'\n * getWorstStatus(['normal', 'critical', 'caution']) // 'critical'\n * ```\n */\nexport function getWorstStatus(statuses: StatusLevel[]): StatusLevel {\n if (statuses.length === 0) return 'off';\n return statuses.reduce((worst, current) => \n getStatusSeverity(current) > getStatusSeverity(worst) ? current : worst\n );\n}\n\n// ============================================================================\n// COLOR UTILITIES\n// ============================================================================\n\n/**\n * Safely add alpha to any CSS color string.\n * Handles hex (#RRGGBB → #RRGGBBAA), rgb(), and rgba() formats.\n *\n * Avoids the common bug of appending a hex alpha string to an rgba() color,\n * which produces invalid CSS (e.g. \"rgba(15, 20, 35, 0.85)80\").\n *\n * @param color - CSS color string (hex, rgb, or rgba)\n * @param alpha - Alpha value 0–1\n * @returns Valid CSS color string with alpha applied\n *\n * @example\n * addAlpha('#1b2d3e', 0.5) // '#1b2d3e80'\n * addAlpha('rgba(15, 20, 35, 0.85)', 0.5) // 'rgba(15, 20, 35, 0.5)'\n * addAlpha('rgb(15, 20, 35)', 0.031) // 'rgba(15, 20, 35, 0.031)'\n */\nexport function addAlpha(color: string, alpha: number): string {\n if (!color) return color;\n const a = Math.max(0, Math.min(1, alpha));\n if (color.startsWith('rgba(')) {\n return color.replace(/,\\s*[\\d.]+\\)\\s*$/, `, ${a})`);\n }\n if (color.startsWith('rgb(')) {\n return color.replace(/^rgb\\(/, 'rgba(').replace(/\\)\\s*$/, `, ${a})`);\n }\n if (color.startsWith('#')) {\n const hexA = Math.round(a * 255).toString(16).padStart(2, '0');\n return `${color}${hexA}`;\n }\n return color;\n}\n\n// ============================================================================\n// COMPONENT STYLE UTILITIES\n// ============================================================================\n\n/**\n * Merge class names, filtering out falsy values\n * @example classNames('base', isActive && 'active', className) // \"base active custom\"\n */\nexport function classNames(...classes: (string | boolean | undefined | null)[]): string {\n return classes.filter(Boolean).join(' ');\n}\n\n/**\n * Generate CSS for tabular numbers (monospace digits)\n */\nexport const tabularNumsStyle: React.CSSProperties = {\n fontVariantNumeric: 'tabular-nums',\n fontFeatureSettings: '\"tnum\" 1',\n};\n\n/**\n * CSS transition presets\n */\nexport const transitions = {\n fast: 'all 150ms ease-out',\n normal: 'all 250ms ease-out',\n slow: 'all 400ms ease-out',\n spring: 'all 300ms cubic-bezier(0.34, 1.56, 0.64, 1)',\n} as const;\n\n/**\n * Focus ring styles for accessibility\n */\nexport const focusRingStyle: React.CSSProperties = {\n outline: '2px solid #4dc3ff',\n outlineOffset: '2px',\n};\n\n/**\n * Compute a WCAG AA safe version of an accent color for use as foreground text\n * on dark backgrounds. If the accent already passes 4.5:1 contrast on typical\n * dark surfaces (L ≈ 0.01), returns it unchanged. Otherwise lightens toward\n * white until the minimum contrast is met.\n *\n * @example safeAccentText('#8b5cf6') // '#a885f8' — lightened to pass 4.5:1\n */\nexport function safeAccentText(accent: string): string {\n const hex = accent.replace('#', '');\n if (hex.length < 6) return accent;\n\n const r = parseInt(hex.slice(0, 2), 16) / 255;\n const g = parseInt(hex.slice(2, 4), 16) / 255;\n const b = parseInt(hex.slice(4, 6), 16) / 255;\n const toLinear = (c: number) =>\n c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);\n const L = 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);\n\n // Threshold: on a dark surface with L≈0.01 we need text L ≥ 0.22 for 4.5:1\n if (L >= 0.22) return accent;\n\n // Lighten by mixing 25% toward white — reaches ~5.5:1 on typical dark bgs\n const mix = 0.25;\n const lr = Math.min(255, Math.round((r + (1 - r) * mix) * 255));\n const lg = Math.min(255, Math.round((g + (1 - g) * mix) * 255));\n const lb = Math.min(255, Math.round((b + (1 - b) * mix) * 255));\n return `#${lr.toString(16).padStart(2, '0')}${lg.toString(16).padStart(2, '0')}${lb.toString(16).padStart(2, '0')}`;\n}\n"],"names":["mins","secs"],"mappings":"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"}
|
package/dist/react.js
CHANGED
|
@@ -1,33 +1,10 @@
|
|
|
1
1
|
import { ErrorBoundary, withErrorBoundary } from "./react/shared/ErrorBoundary.js";
|
|
2
2
|
import { Skeleton3D, SkeletonBox, SkeletonCard, SkeletonChart, SkeletonCircle, SkeletonText } from "./react/shared/Skeleton.js";
|
|
3
3
|
import { STATUS_COLORS, addAlpha, clamp, classNames, focusRingStyle, formatAltitude, formatCoordinate, formatCountdown, formatDataRate, formatDecibels, formatDegrees, formatDistance, formatDuration, formatFrequency, formatLatLon, formatNumber, formatPercentage, formatPower, formatTabular, formatTemperature, formatTime, formatUTC, formatVelocity, getStatusColor, getStatusFromValue, getStatusSeverity, getWorstStatus, isStatusLevel, isValidNumber, lerp, mapRange, normalizeStatus, safeAccentText, safeNumber, tabularNumsStyle, transitions, withNullSafety } from "./react/utils/index.js";
|
|
4
|
-
import { SpacecraftCard } from "./react/cards/SpacecraftCard.js";
|
|
5
|
-
import { TelemetryCard } from "./react/cards/TelemetryCard.js";
|
|
6
|
-
import { AccessCard } from "./react/cards/AccessCard.js";
|
|
7
|
-
import { OrbitCard } from "./react/cards/OrbitCard.js";
|
|
8
|
-
import { TelemetryStreamCard } from "./react/cards/TelemetryStreamCard.js";
|
|
9
|
-
import { EclipseTimerCard } from "./react/visualizations/EclipseTimerCard.js";
|
|
10
|
-
import { NavBallCard } from "./react/visualizations/NavBallCard.js";
|
|
11
|
-
import { LinkBudgetCard } from "./react/visualizations/LinkBudgetCard.js";
|
|
12
|
-
import { ThermalHeatmapCard } from "./react/visualizations/ThermalHeatmapCard.js";
|
|
13
|
-
import { PropulsionCard } from "./react/visualizations/PropulsionCard.js";
|
|
14
|
-
import { SensorFootprintCard } from "./react/visualizations/SensorFootprintCard.js";
|
|
15
|
-
import { EarthViewer } from "./react/3d/EarthViewer.js";
|
|
16
|
-
import { SolarSystemViewer } from "./react/3d/SolarSystemViewer.js";
|
|
17
|
-
import { useZendirSession } from "./react/hooks/useZendirSession.js";
|
|
18
|
-
import { useTelemetry } from "./react/hooks/useTelemetry.js";
|
|
19
|
-
import { useSpacecraftPosition } from "./react/hooks/useSpacecraftPosition.js";
|
|
20
4
|
import { useCompactMode } from "./react/hooks/useCompactMode.js";
|
|
21
|
-
import { isInChatGPT, useCallTool, useChatGPTTheme, useDisplayMode, useIntrinsicHeight, useLocale, useMaxHeight, useOpenAiGlobal, useOpenExternal, useSendMessage, useToolInput, useToolOutput, useWidgetState } from "./react/chatgpt/index.js";
|
|
22
|
-
import { AppCard, ChatGPTCard } from "./react/chatgpt/AppCard.js";
|
|
23
5
|
import { PLANETS, auToKm, estimateOrbitalPeriod, estimateOrbitalVelocity, getPlanet, normalizePlanetName } from "./react/types.js";
|
|
24
|
-
import { ASTRO_DATA_VIZ_COLORS, STATUS_COLORS as STATUS_COLORS2, calculateAxisBounds, createAreaGradient, createAstroEChartsTheme, formatTimeLabel, formatValueWithUnit, getSeriesColor } from "./react/charts/unified/theme.js";
|
|
25
|
-
import { ASTRO_ICON_NAMES, AstroIcon, getAllIconNames, getAstroIconNames, getIconAliases, isAstroIconsAvailable, isIconAlias, preloadAstroIcons } from "./react/core/AstroIcon.js";
|
|
26
6
|
import { ActivityPlanner } from "./react/core/ActivityPlanner.js";
|
|
27
|
-
import { AntennaPattern3DChart, AttitudeChart, AttitudeHistory3DChart, Bar3DChart, ConjunctionAssessment3DChart, ConjunctionChart, ConstellationCoverageChart, ContactWindowChart, DopplerTrackChart, EclipseTimelineChart, HeliocentricOrbitPlot, LaunchCorridor3DChart, Lines3DChart, LinkBudgetChart, LinkMarginChart, ManeuverBudgetChart, OrbitChart, PowerChart, RoseDiagram, Scatter3DChart, SpectrumChart, SphericalRadar3DChart, SubsystemGauge, Surface3DChart, ThermalHeatmapChart, TransferOrbit3DChart, WaterfallChart } from "./react/charts/unified/domain.js";
|
|
28
7
|
import { AppBar } from "./react/core/AppBar.js";
|
|
29
|
-
import { AreaChart, BarChart, BubbleChart, CandlestickChart, DonutChart, DualAxisChart, GaugeChart, GraphChart, HeatmapChart, HistogramChart, LineChart, ParallelChart, PieChart, RadarChart, SankeyChart, ScatterChart, StackedAreaChart, StackedBarChart, SunburstChart, TimeSeriesChart, TreemapChart } from "./react/charts/unified/presets.js";
|
|
30
|
-
import { AstroChart } from "./react/charts/unified/AstroChart.js";
|
|
31
8
|
import { BREAKPOINTS, useBreakpoint } from "./react/core/layout/useBreakpoint.js";
|
|
32
9
|
import { Badge } from "./react/core/Badge.js";
|
|
33
10
|
import { Body1, Body2, Body3, Compact, DataText, Display1, Display2, FONT_FAMILY_MONO, FONT_FAMILY_PRIMARY, FONT_WEIGHTS, H1, H2, H3, H4, H5, H6, Label, Micro, Mono, Typography } from "./react/core/Typography.js";
|
|
@@ -51,13 +28,11 @@ import { DataValue, DataValueGroup } from "./react/core/DataValue.js";
|
|
|
51
28
|
import { Dialog } from "./react/core/Dialog.js";
|
|
52
29
|
import { DisplaySettingsProvider, GLASS_TINTS, PRESET_COLORS, getEffectiveCompactMode, useDisplaySettings, useDisplaySettingsOptional } from "./react/context/DisplaySettingsContext.js";
|
|
53
30
|
import { Divider } from "./react/core/layout/Divider.js";
|
|
54
|
-
import { EARTH_RADIUS_KM, KM_TO_SCENE, SCENE_EARTH_RADIUS, calculateVisibilityConeGeometry, cartesianToLatLonAlt, generateHexGrid, generateOrbitPath, latLonAltToCartesian, parseTLE, propagateSGP4Simple, propagateSatellite } from "./react/3d/ZenSpace3DUtils.js";
|
|
55
31
|
import { FileExplorer } from "./react/core/FileExplorer.js";
|
|
56
32
|
import { Flex } from "./react/core/layout/Flex.js";
|
|
57
33
|
import { GLASS_COLOR_OVERLAYS, GlassCard } from "./react/core/GlassCard.js";
|
|
58
34
|
import { GlobalStatusBar } from "./react/astro/GlobalStatusBar.js";
|
|
59
35
|
import { Grid } from "./react/core/layout/Grid.js";
|
|
60
|
-
import { GroundTrackMap } from "./react/charts/GroundTrackMap.js";
|
|
61
36
|
import { HStack, Stack, VStack } from "./react/core/layout/Stack.js";
|
|
62
37
|
import { HeaderIconWithStatus } from "./react/core/HeaderIconWithStatus.js";
|
|
63
38
|
import { HexViewer, REGION_BORDER_COLORS, REGION_COLORS } from "./react/core/HexViewer.js";
|
|
@@ -77,7 +52,6 @@ import { NumberInput } from "./react/core/NumberInput.js";
|
|
|
77
52
|
import { PacketViewer } from "./react/core/PacketViewer.js";
|
|
78
53
|
import { Pagination } from "./react/core/Pagination.js";
|
|
79
54
|
import { PinInput } from "./react/core/PinInput.js";
|
|
80
|
-
import { PowerOverviewChart, generateSamplePowerData } from "./react/charts/unified/PowerOverviewChart.js";
|
|
81
55
|
import { Progress } from "./react/astro/Progress.js";
|
|
82
56
|
import { Select } from "./react/core/Select.js";
|
|
83
57
|
import { SideNav } from "./react/core/SideNav.js";
|
|
@@ -90,50 +64,28 @@ import { UnifiedTimeline } from "./react/astro/UnifiedTimeline.js";
|
|
|
90
64
|
import { ToastProvider, useToast, useToastManager } from "./react/core/Toast.js";
|
|
91
65
|
import { Toggle } from "./react/core/Toggle.js";
|
|
92
66
|
import { Tooltip } from "./react/core/Tooltip.js";
|
|
93
|
-
import { ZenSpace3D } from "./react/3d/ZenSpace3D.js";
|
|
94
|
-
import { ZenSpace3DCesium } from "./react/3d/ZenSpace3DCesium.js";
|
|
95
|
-
import { atmosphereFragmentShader, atmosphereVertexShader, starsFragmentShader, starsVertexShader } from "./react/3d/ZenSpace3DShaders.js";
|
|
96
|
-
import { dispatchToGroup, exportGroupAsCSV, exportGroupAsImages, getGroupCharts, hideGroupTooltip, resetGroupZoom, showGroupTooltip, syncZoomRange, useChartSync } from "./react/charts/unified/sync.js";
|
|
97
|
-
import { generateAttitudeData, generateConjunctionEvents, generateConstellationCoverage, generateContactWindows, generateDopplerData, generateEclipseTimeline, generateHeliocentricOrbits, generatePowerData, generateSpectrum, generateWaterfallData } from "./react/charts/unified/generators.js";
|
|
98
67
|
import { resolveResponsive, resolveSpacing } from "./react/core/layout/responsive.js";
|
|
99
|
-
import { useChartStream, useWebSocketStream } from "./react/charts/unified/useChartStream.js";
|
|
100
68
|
export {
|
|
101
|
-
ASTRO_DATA_VIZ_COLORS,
|
|
102
|
-
ASTRO_ICON_NAMES,
|
|
103
|
-
AccessCard,
|
|
104
69
|
ActivityPlanner,
|
|
105
|
-
AntennaPattern3DChart,
|
|
106
70
|
AppBar,
|
|
107
|
-
AppCard,
|
|
108
|
-
AreaChart,
|
|
109
|
-
AstroChart,
|
|
110
|
-
AstroIcon,
|
|
111
|
-
AttitudeChart,
|
|
112
|
-
AttitudeHistory3DChart,
|
|
113
71
|
BREAKPOINTS,
|
|
114
72
|
Badge,
|
|
115
|
-
Bar3DChart,
|
|
116
|
-
BarChart,
|
|
117
73
|
Body1,
|
|
118
74
|
Body2,
|
|
119
75
|
Body3,
|
|
120
76
|
Box,
|
|
121
|
-
BubbleChart,
|
|
122
77
|
Button,
|
|
123
78
|
CARD_ACCENT_COLORS,
|
|
124
79
|
CATEGORY_ICONS,
|
|
125
80
|
CATEGORY_LABELS,
|
|
126
|
-
STATUS_COLORS2 as CHART_STATUS_COLORS,
|
|
127
81
|
CHAT_RESPONSE_JSON_PROMPT,
|
|
128
82
|
CHAT_RESPONSE_MCP_TOOL,
|
|
129
83
|
CHAT_RESPONSE_TOOL_SCHEMA,
|
|
130
84
|
CHAT_RESPONSE_YAML_PROMPT,
|
|
131
85
|
CHAT_STATUS_RULES_PROMPT,
|
|
132
|
-
CandlestickChart,
|
|
133
86
|
CardAccentProvider,
|
|
134
87
|
CardHeader,
|
|
135
88
|
Center,
|
|
136
|
-
ChatGPTCard,
|
|
137
89
|
ChatPanel,
|
|
138
90
|
Checkbox,
|
|
139
91
|
ClassificationBanner,
|
|
@@ -142,11 +94,7 @@ export {
|
|
|
142
94
|
Compact,
|
|
143
95
|
ConfirmDialog,
|
|
144
96
|
ConfirmProvider,
|
|
145
|
-
ConjunctionAssessment3DChart,
|
|
146
|
-
ConjunctionChart,
|
|
147
97
|
ConnectionForm,
|
|
148
|
-
ConstellationCoverageChart,
|
|
149
|
-
ContactWindowChart,
|
|
150
98
|
Container,
|
|
151
99
|
CopyButton,
|
|
152
100
|
DataTable,
|
|
@@ -159,13 +107,6 @@ export {
|
|
|
159
107
|
Display2,
|
|
160
108
|
DisplaySettingsProvider,
|
|
161
109
|
Divider,
|
|
162
|
-
DonutChart,
|
|
163
|
-
DopplerTrackChart,
|
|
164
|
-
DualAxisChart,
|
|
165
|
-
EARTH_RADIUS_KM,
|
|
166
|
-
EarthViewer,
|
|
167
|
-
EclipseTimelineChart,
|
|
168
|
-
EclipseTimerCard,
|
|
169
110
|
ErrorBoundary,
|
|
170
111
|
FONT_FAMILY_MONO,
|
|
171
112
|
FONT_FAMILY_PRIMARY,
|
|
@@ -174,12 +115,9 @@ export {
|
|
|
174
115
|
Flex,
|
|
175
116
|
GLASS_COLOR_OVERLAYS,
|
|
176
117
|
GLASS_TINTS,
|
|
177
|
-
GaugeChart,
|
|
178
118
|
GlassCard,
|
|
179
119
|
GlobalStatusBar,
|
|
180
|
-
GraphChart,
|
|
181
120
|
Grid,
|
|
182
|
-
GroundTrackMap,
|
|
183
121
|
H1,
|
|
184
122
|
H2,
|
|
185
123
|
H3,
|
|
@@ -188,24 +126,13 @@ export {
|
|
|
188
126
|
H6,
|
|
189
127
|
HStack,
|
|
190
128
|
HeaderIconWithStatus,
|
|
191
|
-
HeatmapChart,
|
|
192
|
-
HeliocentricOrbitPlot,
|
|
193
129
|
HexViewer,
|
|
194
|
-
HistogramChart,
|
|
195
130
|
Icon,
|
|
196
131
|
ImageGallery,
|
|
197
132
|
Input,
|
|
198
|
-
KM_TO_SCENE,
|
|
199
133
|
Label,
|
|
200
|
-
LaunchCorridor3DChart,
|
|
201
134
|
LimitsBar,
|
|
202
|
-
LineChart,
|
|
203
|
-
Lines3DChart,
|
|
204
|
-
LinkBudgetCard,
|
|
205
|
-
LinkBudgetChart,
|
|
206
|
-
LinkMarginChart,
|
|
207
135
|
LogViewer,
|
|
208
|
-
ManeuverBudgetChart,
|
|
209
136
|
Menu,
|
|
210
137
|
MessageStream,
|
|
211
138
|
Micro,
|
|
@@ -214,36 +141,21 @@ export {
|
|
|
214
141
|
MissionClock,
|
|
215
142
|
MonitoringIcon,
|
|
216
143
|
Mono,
|
|
217
|
-
NavBallCard,
|
|
218
144
|
Notification,
|
|
219
145
|
NumberInput,
|
|
220
|
-
OrbitCard,
|
|
221
|
-
OrbitChart,
|
|
222
146
|
PLANETS,
|
|
223
147
|
PRESET_COLORS,
|
|
224
148
|
PROPERTY_PRESETS,
|
|
225
149
|
PacketViewer,
|
|
226
150
|
Pagination,
|
|
227
|
-
ParallelChart,
|
|
228
|
-
PieChart,
|
|
229
151
|
PinInput,
|
|
230
152
|
Popover,
|
|
231
|
-
PowerChart,
|
|
232
|
-
PowerOverviewChart,
|
|
233
153
|
Progress,
|
|
234
|
-
PropulsionCard,
|
|
235
154
|
REGION_BORDER_COLORS,
|
|
236
155
|
REGION_COLORS,
|
|
237
|
-
RadarChart,
|
|
238
|
-
RoseDiagram,
|
|
239
|
-
SCENE_EARTH_RADIUS,
|
|
240
156
|
SPACE_SYSTEM_COLORS,
|
|
241
157
|
STATUS_COLORS,
|
|
242
|
-
SankeyChart,
|
|
243
|
-
Scatter3DChart,
|
|
244
|
-
ScatterChart,
|
|
245
158
|
Select,
|
|
246
|
-
SensorFootprintCard,
|
|
247
159
|
SideNav,
|
|
248
160
|
SidePanel,
|
|
249
161
|
SimulationControls,
|
|
@@ -254,56 +166,27 @@ export {
|
|
|
254
166
|
SkeletonChart,
|
|
255
167
|
SkeletonCircle,
|
|
256
168
|
SkeletonText,
|
|
257
|
-
SolarSystemViewer,
|
|
258
|
-
SpacecraftCard,
|
|
259
169
|
Spacer,
|
|
260
|
-
SpectrumChart,
|
|
261
|
-
SphericalRadar3DChart,
|
|
262
170
|
Stack,
|
|
263
|
-
StackedAreaChart,
|
|
264
|
-
StackedBarChart,
|
|
265
171
|
StatusIndicator,
|
|
266
|
-
SubsystemGauge,
|
|
267
|
-
SunburstChart,
|
|
268
|
-
Surface3DChart,
|
|
269
172
|
Tabs,
|
|
270
|
-
TelemetryCard,
|
|
271
|
-
TelemetryStreamCard,
|
|
272
173
|
ThemeProvider,
|
|
273
|
-
ThermalHeatmapCard,
|
|
274
|
-
ThermalHeatmapChart,
|
|
275
|
-
TimeSeriesChart,
|
|
276
174
|
UnifiedTimeline as Timeline,
|
|
277
175
|
ToastProvider,
|
|
278
176
|
Toggle,
|
|
279
177
|
Tooltip,
|
|
280
|
-
TransferOrbit3DChart,
|
|
281
|
-
TreemapChart,
|
|
282
178
|
Typography,
|
|
283
179
|
VStack,
|
|
284
|
-
WaterfallChart,
|
|
285
|
-
ZenSpace3D,
|
|
286
|
-
ZenSpace3DCesium,
|
|
287
180
|
addAlpha,
|
|
288
|
-
atmosphereFragmentShader,
|
|
289
|
-
atmosphereVertexShader,
|
|
290
181
|
auToKm,
|
|
291
|
-
calculateAxisBounds,
|
|
292
|
-
calculateVisibilityConeGeometry,
|
|
293
|
-
cartesianToLatLonAlt,
|
|
294
182
|
clamp,
|
|
295
183
|
classNames,
|
|
296
|
-
createAreaGradient,
|
|
297
|
-
createAstroEChartsTheme,
|
|
298
184
|
createChatResponseParser,
|
|
299
185
|
createPropertyConfig,
|
|
300
186
|
deriveBatteryStatus,
|
|
301
187
|
deriveStatus,
|
|
302
|
-
dispatchToGroup,
|
|
303
188
|
estimateOrbitalPeriod,
|
|
304
189
|
estimateOrbitalVelocity,
|
|
305
|
-
exportGroupAsCSV,
|
|
306
|
-
exportGroupAsImages,
|
|
307
190
|
focusRingStyle,
|
|
308
191
|
formatAltitude,
|
|
309
192
|
formatCoordinate,
|
|
@@ -323,98 +206,46 @@ export {
|
|
|
323
206
|
formatTabular,
|
|
324
207
|
formatTemperature,
|
|
325
208
|
formatTime,
|
|
326
|
-
formatTimeLabel,
|
|
327
209
|
formatUTC,
|
|
328
|
-
formatValueWithUnit,
|
|
329
210
|
formatVelocity,
|
|
330
|
-
generateAttitudeData,
|
|
331
|
-
generateConjunctionEvents,
|
|
332
|
-
generateConstellationCoverage,
|
|
333
|
-
generateContactWindows,
|
|
334
|
-
generateDopplerData,
|
|
335
|
-
generateEclipseTimeline,
|
|
336
|
-
generateHeliocentricOrbits,
|
|
337
|
-
generateHexGrid,
|
|
338
|
-
generateOrbitPath,
|
|
339
|
-
generatePowerData,
|
|
340
|
-
generateSamplePowerData,
|
|
341
|
-
generateSpectrum,
|
|
342
|
-
generateWaterfallData,
|
|
343
211
|
getAccentColorOptions,
|
|
344
|
-
getAllIconNames,
|
|
345
|
-
getAstroIconNames,
|
|
346
212
|
getEffectiveCompactMode,
|
|
347
|
-
getGroupCharts,
|
|
348
|
-
getIconAliases,
|
|
349
213
|
getIconNames,
|
|
350
214
|
getPlanet,
|
|
351
215
|
getPropertiesByCategory,
|
|
352
216
|
getPropertyConfig,
|
|
353
|
-
getSeriesColor,
|
|
354
217
|
getStatusColor,
|
|
355
218
|
getStatusFromValue,
|
|
356
219
|
getStatusSeverity,
|
|
357
220
|
getSystemAccentColor,
|
|
358
221
|
getWorstStatus,
|
|
359
|
-
hideGroupTooltip,
|
|
360
|
-
isAstroIconsAvailable,
|
|
361
|
-
isIconAlias,
|
|
362
|
-
isInChatGPT,
|
|
363
222
|
isStatusLevel,
|
|
364
223
|
isValidIconName,
|
|
365
224
|
isValidNumber,
|
|
366
|
-
latLonAltToCartesian,
|
|
367
225
|
lerp,
|
|
368
226
|
mapRange,
|
|
369
227
|
normalizePlanetName,
|
|
370
228
|
normalizeStatus,
|
|
371
229
|
parseChatResponse,
|
|
372
230
|
parseMcpToolResult,
|
|
373
|
-
parseTLE,
|
|
374
|
-
preloadAstroIcons,
|
|
375
|
-
propagateSGP4Simple,
|
|
376
|
-
propagateSatellite,
|
|
377
|
-
resetGroupZoom,
|
|
378
231
|
resolveResponsive,
|
|
379
232
|
resolveSpacing,
|
|
380
233
|
safeAccentText,
|
|
381
234
|
safeNumber,
|
|
382
|
-
showGroupTooltip,
|
|
383
|
-
starsFragmentShader,
|
|
384
|
-
starsVertexShader,
|
|
385
|
-
syncZoomRange,
|
|
386
235
|
tabularNumsStyle,
|
|
387
236
|
transitions,
|
|
388
237
|
useBreakpoint,
|
|
389
|
-
useCallTool,
|
|
390
238
|
useCardAccent,
|
|
391
|
-
useChartStream,
|
|
392
|
-
useChartSync,
|
|
393
|
-
useChatGPTTheme,
|
|
394
239
|
useCompactMode,
|
|
395
240
|
useConfirm,
|
|
396
241
|
useCopyToClipboard,
|
|
397
|
-
useDisplayMode,
|
|
398
242
|
useDisplaySettings,
|
|
399
243
|
useDisplaySettingsOptional,
|
|
400
|
-
useIntrinsicHeight,
|
|
401
|
-
useLocale,
|
|
402
|
-
useMaxHeight,
|
|
403
|
-
useOpenAiGlobal,
|
|
404
|
-
useOpenExternal,
|
|
405
244
|
useScrollbarStyles,
|
|
406
|
-
useSendMessage,
|
|
407
|
-
useSpacecraftPosition,
|
|
408
|
-
useTelemetry,
|
|
409
245
|
useTheme,
|
|
410
246
|
useThemeTokens,
|
|
411
247
|
useToast,
|
|
412
248
|
useToastManager,
|
|
413
|
-
useToolInput,
|
|
414
|
-
useToolOutput,
|
|
415
|
-
useWebSocketStream,
|
|
416
|
-
useWidgetState,
|
|
417
|
-
useZendirSession,
|
|
418
249
|
withErrorBoundary,
|
|
419
250
|
withNullSafety
|
|
420
251
|
};
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"react.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|