/* global React */ const { useState, useEffect, useRef, useMemo } = React; // ============================================================ // LOGO — 3 rotated nested squares = vibration wave + precision // ============================================================ function Logo({ size = 20, color = "currentColor" }) { return ( ); } function Wordmark({ showTagline = true }) { return (
Vibranium
{showTagline && (
Obserwator wibracji
)}
); } // ============================================================ // STATUS — colorblind-safe via SHAPE (● = ok, ▲ = warn, ■ = alarm) // ============================================================ const STATUS_META = { ok: { color: "var(--ok)", weak: "var(--ok-weak)", border: "var(--ok-border)", label: "OK", shape: "circle" }, warn: { color: "var(--warn)", weak: "var(--warn-weak)", border: "var(--warn-border)", label: "Ostrzeżenie", shape: "triangle" }, alarm: { color: "var(--alarm)", weak: "var(--alarm-weak)", border: "var(--alarm-border)", label: "Alarm", shape: "square" }, idle: { color: "var(--fg-subtle)", weak: "var(--bg-sunken)", border: "var(--border)", label: "Brak", shape: "dash" }, }; function StatusGlyph({ status, size = 10 }) { const meta = STATUS_META[status] || STATUS_META.idle; const s = size; if (meta.shape === "circle") { return ; } if (meta.shape === "triangle") { return ; } if (meta.shape === "square") { return ; } return ; } function StatusBadge({ status, label, size = "md" }) { const meta = STATUS_META[status] || STATUS_META.idle; const pad = size === "sm" ? "2px 6px" : "3px 8px"; const fs = size === "sm" ? 10 : 11; return ( {label ?? meta.label} ); } // ============================================================ // BUTTON // ============================================================ function Button({ variant = "default", size = "md", children, icon, onClick, style, disabled }) { const sizes = { sm: { padding: "4px 10px", fontSize: 11, height: 24 }, md: { padding: "6px 12px", fontSize: 12, height: 28 }, lg: { padding: "8px 16px", fontSize: 13, height: 34 }, }; const variants = { default: { background: "var(--surface)", color: "var(--fg)", border: "1px solid var(--border-strong)" }, primary: { background: "var(--fg)", color: "var(--bg)", border: "1px solid var(--fg)" }, ghost: { background: "transparent", color: "var(--fg)", border: "1px solid transparent" }, accent: { background: "var(--accent)", color: "var(--accent-fg)", border: "1px solid var(--accent)" }, danger: { background: "var(--alarm-weak)", color: "var(--alarm)", border: "1px solid var(--alarm-border)" }, }; return ( ); } // ============================================================ // ICONS — thin, monoline, lucide-inspired but minimal // ============================================================ const Ic = { search: (p) => , refresh: (p) => , download: (p) => , upload: (p) => , mail: (p) => , edit: (p) => , eye: (p) => , plus: (p) => , chevronRight: (p) => , chevronDown: (p) => , chevronLeft: (p) => , arrowUp: (p) => , arrowDown: (p) => , dashboard: (p) => , measure: (p) => , chart: (p) => , config: (p) => , computer: (p) => , moon: (p) => , sun: (p) => , file: (p) => , wrench: (p) => , }; // ============================================================ // INPUT // ============================================================ function Input({ icon, placeholder, value, onChange, style }) { return (
{icon &&
{icon}
}
); } // ============================================================ // CARD // ============================================================ function Card({ children, style, pad = true, elev = false }) { return (
{children}
); } // ============================================================ // STAT CARD // ============================================================ function StatCard({ label, value, unit, trend, trendValue, status, note, style }) { const trendColor = trend === "up" ? "var(--alarm)" : trend === "down" ? "var(--ok)" : "var(--fg-muted)"; return (
{label}
{status && }
{value}
{unit &&
{unit}
}
{(trend || note) && (
{trend === "up" && } {trend === "down" && } {trendValue} {note && {note}}
)}
); } // ============================================================ // BREADCRUMB // ============================================================ function Breadcrumb({ items }) { return (
{items.map((it, i) => ( {i > 0 && } {it.label} ))}
); } Object.assign(window, { Logo, Wordmark, StatusGlyph, StatusBadge, STATUS_META, Button, Input, Card, StatCard, Breadcrumb, Ic, });