Phase 0: monorepo skeleton (hub, live-map, api, packages, infra, CI)

This commit is contained in:
Mavis
2026-06-02 15:47:28 +00:00
commit 7b19c54943
59 changed files with 2391 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
{
"name": "@kerbal-rt/ui",
"version": "0.1.0",
"private": true,
"description": "Shared React components for hub + live-map",
"type": "module",
"main": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts"
},
"scripts": {
"typecheck": "tsc --noEmit",
"lint": "echo 'no linter yet'",
"test": "echo 'no tests yet'",
"build": "tsc"
},
"peerDependencies": {
"react": "^18.3.0",
"react-dom": "^18.3.0"
},
"devDependencies": {
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"typescript": "^5.6.2"
}
}
+64
View File
@@ -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')}`;
}
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"jsx": "react-jsx"
},
"include": ["src/**/*"]
}