Files
KSP-MissionControl/packages/ui/src/index.ts
T

65 lines
2.0 KiB
TypeScript

/**
* Shared UI primitives used by both hub and live-map frontends.
* Keep this package dependency-free (no Tailwind, no MUI) — apps
* style with their own CSS / framework.
*/
import { type ReactNode } from 'react';
export function Pill({ children, tone = 'neutral' }: { children: ReactNode; tone?: 'neutral' | 'success' | 'warn' | 'danger' }) {
const colorMap = {
neutral: 'var(--pill-neutral, #ddd)',
success: 'var(--pill-success, #2c5)',
warn: 'var(--pill-warn, #fa3)',
danger: 'var(--pill-danger, #e44)',
} as const;
return (
<span
style={{
display: 'inline-block',
padding: '0.125rem 0.5rem',
borderRadius: 999,
background: colorMap[tone],
color: 'white',
fontSize: '0.75rem',
fontWeight: 600,
letterSpacing: '0.02em',
}}
>
{children}
</span>
);
}
export function Card({ children, title }: { children: ReactNode; title?: string }) {
return (
<section
style={{
border: '1px solid var(--card-border, #333)',
borderRadius: 8,
padding: '1rem',
background: 'var(--card-bg, rgba(255,255,255,0.03))',
}}
>
{title && (
<h3 style={{ margin: '0 0 0.5rem', fontSize: '1rem', fontWeight: 600 }}>{title}</h3>
)}
{children}
</section>
);
}
export function formatUtAsKspDate(ut: number): string {
// KSP year 1 day 1 00:00:00 is UT=0. A KSP day is 6 hours, a year is 426 days.
const KSP_DAY_SECONDS = 6 * 3600;
const KSP_YEAR_DAYS = 426;
const totalDays = ut / KSP_DAY_SECONDS;
const year = Math.floor(totalDays / KSP_YEAR_DAYS) + 1;
const day = (Math.floor(totalDays) % KSP_YEAR_DAYS) + 1;
const secondsInDay = ut % KSP_DAY_SECONDS;
const hour = Math.floor(secondsInDay / 3600);
const minute = Math.floor((secondsInDay % 3600) / 60);
const second = Math.floor(secondsInDay % 60);
return `Y${year} D${day} ${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}:${String(second).padStart(2, '0')}`;
}