Phase 0: monorepo skeleton (hub, live-map, api, packages, infra, CI)
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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')}`;
|
||||
}
|
||||
Reference in New Issue
Block a user