0889ee9117
feat(hooks): add useLiveStream generic WebSocket hook - supports websocket/sse/polling transports - exponential backoff reconnect with jitter - circular buffer with configurable size - typed filter callback per use case - manual disconnect + reconnect + error state feat(hooks): add useLiveMetrics derived hook - sliding time-window cut - moving average (configurable window) - current / avg / min / max / ratePerSecond - zero allocations per tick (memoized) feat(charts): add LiveMetricChart molecule (Recharts) - line + area variants, grid + tooltip - moving-average overlay (dashed) - ConnectionStatus atom in header - status bar + compact mode - 100% responsive, GPU via SVG ViewBox feat(atoms): add ConnectionStatus indicator - 5 states: disconnected/connecting/connected/reconnecting/error - animated pulse, JetBrains Mono, pill style - exported helpers: formatLatency / formatBytes docs(pkg): bump v0.1.0 → v0.2.0, add recharts peerDep
112 lines
4.8 KiB
JavaScript
Executable File
112 lines
4.8 KiB
JavaScript
Executable File
import {
|
|
cn
|
|
} from "../chunk-RL4ANBQD.mjs";
|
|
|
|
// src/components/index.tsx
|
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
var variantStyles = {
|
|
primary: "bg-indigo-600 text-white hover:bg-indigo-700 active:bg-indigo-800 disabled:bg-indigo-300",
|
|
secondary: "border border-gray-300 text-gray-700 bg-white hover:bg-gray-50 active:bg-gray-100",
|
|
ghost: "text-gray-600 hover:bg-gray-100 active:bg-gray-200",
|
|
danger: "bg-red-600 text-white hover:bg-red-700 active:bg-red-800",
|
|
success: "bg-emerald-600 text-white hover:bg-emerald-700 active:bg-emerald-800"
|
|
};
|
|
var sizeStyles = {
|
|
sm: "px-2.5 py-1 text-xs rounded",
|
|
md: "px-4 py-2 text-sm rounded-md",
|
|
lg: "px-6 py-3 text-base rounded-lg"
|
|
};
|
|
function Button({
|
|
className,
|
|
variant = "primary",
|
|
size = "md",
|
|
loading,
|
|
leftIcon,
|
|
rightIcon,
|
|
children,
|
|
disabled,
|
|
...rest
|
|
}) {
|
|
return /* @__PURE__ */ jsxs(
|
|
"button",
|
|
{
|
|
className: cn(
|
|
"inline-flex items-center justify-center gap-2 font-medium transition-colors",
|
|
"focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2",
|
|
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
variantStyles[variant],
|
|
sizeStyles[size],
|
|
className
|
|
),
|
|
disabled: disabled || loading,
|
|
...rest,
|
|
children: [
|
|
loading ? /* @__PURE__ */ jsx(Spinner, { size: 16 }) : leftIcon ?? null,
|
|
children,
|
|
!loading && rightIcon
|
|
]
|
|
}
|
|
);
|
|
}
|
|
function Input({ className, label, error, hint, id, ...rest }) {
|
|
const inputId = id ?? label?.toLowerCase().replace(/\s+/g, "-");
|
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
label && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "text-sm font-medium text-gray-700", children: label }),
|
|
/* @__PURE__ */ jsx(
|
|
"input",
|
|
{
|
|
id: inputId,
|
|
className: cn(
|
|
"w-full rounded-md border border-gray-300 px-3 py-2 text-sm",
|
|
"placeholder:text-gray-400",
|
|
"focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500",
|
|
"disabled:bg-gray-100 disabled:cursor-not-allowed",
|
|
error && "border-red-500 focus:ring-red-500 focus:border-red-500",
|
|
className
|
|
),
|
|
...rest
|
|
}
|
|
),
|
|
error && /* @__PURE__ */ jsx("span", { className: "text-xs text-red-500", children: error }),
|
|
hint && !error && /* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400", children: hint })
|
|
] });
|
|
}
|
|
var alertStyles = {
|
|
info: { container: "bg-blue-50 border-blue-200 text-blue-800", icon: "\u2139\uFE0F" },
|
|
success: { container: "bg-emerald-50 border-emerald-200 text-emerald-800", icon: "\u2705" },
|
|
warning: { container: "bg-amber-50 border-amber-200 text-amber-800", icon: "\u26A0\uFE0F" },
|
|
error: { container: "bg-red-50 border-red-200 text-red-800", icon: "\u274C" }
|
|
};
|
|
function Alert({ variant = "info", title, children, onClose }) {
|
|
const s = alertStyles[variant];
|
|
return /* @__PURE__ */ jsxs("div", { className: cn("flex items-start gap-2 rounded-lg border px-4 py-3", s.container), children: [
|
|
/* @__PURE__ */ jsx("span", { className: "text-base leading-none", children: s.icon }),
|
|
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
title && /* @__PURE__ */ jsx("p", { className: "font-semibold text-sm", children: title }),
|
|
/* @__PURE__ */ jsx("p", { className: "text-sm", children })
|
|
] }),
|
|
onClose && /* @__PURE__ */ jsx("button", { onClick: onClose, className: "ml-auto text-lg leading-none opacity-50 hover:opacity-100", children: "\xD7" })
|
|
] });
|
|
}
|
|
var Card = ({ className, children, ...rest }) => /* @__PURE__ */ jsx("div", { className: cn("rounded-xl border border-gray-200 bg-white shadow-sm", className), ...rest, children });
|
|
var CardHeader = ({ className, children, ...rest }) => /* @__PURE__ */ jsx("div", { className: cn("px-5 py-4 border-b border-gray-100", className), ...rest, children });
|
|
var CardTitle = ({ children }) => /* @__PURE__ */ jsx("h3", { className: "font-semibold text-gray-900 text-base", children });
|
|
var CardBody = ({ className, children, ...rest }) => /* @__PURE__ */ jsx("div", { className: cn("px-5 py-4", className), ...rest, children });
|
|
function Spinner({ size = 16, className = "" }) {
|
|
return /* @__PURE__ */ jsxs("svg", { className: cn("animate-spin", className), width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: [
|
|
/* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
/* @__PURE__ */ jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })
|
|
] });
|
|
}
|
|
export {
|
|
Alert,
|
|
Button,
|
|
Card,
|
|
CardBody,
|
|
CardHeader,
|
|
CardTitle,
|
|
Input,
|
|
Spinner,
|
|
cn
|
|
};
|
|
//# sourceMappingURL=index.mjs.map
|