/* ============================================================ components.jsx — UI primitives for the instrument. Status is always shape + text + color, never color alone. Exports to window. ============================================================ */ (function () { // ---- layout --------------------------------------------- function Card({ tone = "surface", pad = 16, children, style, className = "", ...rest }) { const bg = tone === "sunken" ? "var(--bg-sunken)" : tone === "raised" ? "var(--surface-raised)" : "var(--surface)"; return (
{children}
); } function Row({ children, gap = 8, align = "center", justify = "flex-start", wrap = false, style }) { return
{children}
; } function Label({ children, style }) { return {children}; } // ---- status mark (shape-coded, a11y safe) ---------------- // good ▸ ring · attn ▸ caret-up · acute ▸ bang · within ▸ dash · low ▸ hollow function StatusMark({ status = "within", size = 14 }) { const c = { good: "var(--good)", attn: "var(--attn)", acute: "var(--acute)", within: "var(--ink-3)", lowconf: "var(--ink-4)" }[status]; const s = size; if (status === "acute") return ( ); if (status === "attn") return ( ); if (status === "good") return ( ); if (status === "lowconf") return ( ); return ; } // ---- confidence meter (signal bars) ---------------------- function ConfidenceMeter({ level = "high", pct, showText = true, size = 1 }) { const fill = { high: 3, medium: 2, low: 1 }[level]; const col = level === "low" ? "var(--ink-4)" : level === "medium" ? "var(--ink-2)" : "var(--good)"; const bw = 3.5 * size, gap = 2 * size; return ( {[0, 1, 2].map((i) => ( ))} {showText && } ); } // ---- chip ------------------------------------------------ function Chip({ tone = "neutral", children, style, mono = true }) { const map = { neutral: ["var(--surface-2)", "var(--ink-2)", "var(--line)"], good: ["var(--good-soft)", "var(--good-ink)", "var(--good-line)"], attn: ["var(--attn-soft)", "var(--attn-ink)", "var(--attn-line)"], acute: ["var(--acute-soft)", "var(--acute-ink)", "var(--acute-line)"], }; const [bg, fg, bd] = map[tone] || map.neutral; return ( {children} ); } // ---- delta tag (vs baseline) ----------------------------- function Delta({ children, tone = "neutral" }) { const col = tone === "good" ? "var(--good-ink)" : tone === "attn" ? "var(--attn-ink)" : "var(--ink-3)"; return {children}; } // ---- big numeric readout --------------------------------- function Readout({ value, unit, band, size = 64, status, color }) { const col = color || (status ? { good: "var(--good)", attn: "var(--attn)", acute: "var(--acute)" }[status] : "var(--ink)") || "var(--ink)"; return ( {value} {band != null && ±{band}} {unit && {unit}} ); } // ---- tier header ----------------------------------------- function TierHeader({ tier, title, count, note }) { const accent = { acute: "var(--acute)", subacute: "var(--attn)", chronic: "var(--ink-3)", wellness: "var(--good)" }[tier] || "var(--ink-3)"; return ( {count != null && } {note && } ); } // ---- caveat block (clinical humility) -------------------- function Caveat({ children, action, tone = "neutral" }) { const bd = tone === "acute" ? "var(--acute-line)" : tone === "attn" ? "var(--attn-line)" : "var(--line)"; return (
{children} {action && ( )}
); } // ---- section divider label ------------------------------- function SubLabel({ children, right }) { return ( {right && } ); } // ---- icon (minimal line glyphs) -------------------------- function Icon({ name, size = 20, color = "currentColor", stroke = 1.6 }) { const p = { fill: "none", stroke: color, strokeWidth: stroke, strokeLinecap: "round", strokeLinejoin: "round" }; const paths = { home: <>, heart: <>, moon: <>, trend: <>, clinical: <>, sun: <>{[0, 45, 90, 135, 180, 225, 270, 315].map((a) => { const r = a * Math.PI / 180; return ; })}, back: <>, gap: <>, }; return {paths[name]}; } Object.assign(window, { Card, Row, Label, StatusMark, ConfidenceMeter, Chip, Delta, Readout, TierHeader, Caveat, SubLabel, Icon }); })();