// components.jsx — primitive component library for the control panel.
// Style only with classes + tokens from base.css. No inline hex colors.
// Exposes (on window): Button, IconButton, Card, StatCard, PageHeader, Field,
// Input, Textarea, Select, Switch, Checkbox, SegmentedControl, Badge, Tabs,
// Modal, ToastProvider, useToast, EmptyState, Skeleton, Spinner, CopyButton,
// SecretField, KeyValue, CodeBlock, Sparkline, AreaChart, BarChart,
// ErrorBoundary, CommandPalette
(() => {
const { useState, useEffect, useRef, useMemo, useCallback, useContext } = React;
const Icon = window.Icon;
const fmtCount = window.fmtCount;
let uidCounter = 0;
const nextUid = (prefix) => prefix + "-" + (++uidCounter);
const cx = (...parts) => parts.filter(Boolean).join(" ");
const TONE_COLORS = {
accent: "var(--accent)",
success: "var(--success)",
warning: "var(--warning)",
danger: "var(--danger)",
info: "var(--info)",
neutral: "var(--text-3)",
};
const toneColor = (tone) => TONE_COLORS[tone] || TONE_COLORS.accent;
/* ────────────────────────────────────────────
Buttons
──────────────────────────────────────────── */
function Button({ variant = "secondary", size = "md", loading = false, icon, block, className, children, disabled, type = "button", ...props }) {
return (
);
}
function IconButton({ icon, label, size = 15, bordered, className, ...props }) {
return (
);
}
/* ────────────────────────────────────────────
Card + StatCard + PageHeader
──────────────────────────────────────────── */
function Card({ title, description, actions, footer, flush, className, children }) {
return (
{(title || description || actions) && (
{title &&
{title}
}
{description &&
{description}
}
{actions && {actions}
}
)}
{children}
{footer && }
);
}
// delta: number → formatted as a % delta with tone inferred from sign,
// string → rendered as-is (pass deltaTone to color it).
function StatCard({ label, value, delta, deltaTone, sub, spark, sparkTone = "accent", loading, className }) {
let deltaNode = null;
if (delta != null && delta !== "") {
let text = delta;
let tone = deltaTone;
if (typeof delta === "number") {
text = window.fmtDelta(delta, "%");
if (!tone) tone = delta > 0 ? "success" : delta < 0 ? "danger" : "neutral";
}
deltaNode = {text};
}
return (
{label}
{deltaNode}
{loading ? : {value}}
{spark && spark.length > 0 && }
{sub &&
{sub}
}
);
}
function PageHeader({ title, description, actions, children }) {
return (
{title}
{description &&
{description}
}
{actions &&
{actions}
}
{children}
);
}
/* ────────────────────────────────────────────
Form controls
──────────────────────────────────────────── */
function Field({ label, hint, error, htmlFor, mono, className, children }) {
return (
{label &&
}
{children}
{hint && !error &&
{hint}
}
{error && (
{error}
)}
);
}
const Input = React.forwardRef(function Input({ className, mono, invalid, ...props }, ref) {
return (
);
});
const Textarea = React.forwardRef(function Textarea({ className, mono, invalid, ...props }, ref) {
return (
);
});
// options: ["a", "b"] or [{value, label, disabled}] — or pass