import { html, useState, useEffect } from './core.js';
export const Card = ({ title, right, children }) => html`
${title && html`
${title}
${right}
`}
${children}
`;
export const Stat = ({ label, value, sub, tone }) => html`
${label}
${value}
${sub && html`${sub}
`}
`;
export const Dot = ({ tone = 'idle', live }) => html`
`;
export const Pill = ({ tone, children }) => html`${children}`;
export const Bar = ({ value, max, tone }) => {
const width = max > 0 ? Math.min(100, (Number(value) / Number(max)) * 100) : 0;
return html`
`;
};
export const Skeleton = ({ rows = 3 }) => html`
${Array.from({ length: rows }, (_, i) => html`
`)}
`;
export const Empty = ({ children }) => html`${children}
`;
export function Toast({ toast }) {
const [shown, setShown] = useState(toast);
useEffect(() => {
setShown(toast);
if (!toast) return undefined;
const timer = setTimeout(() => setShown(null), toast.sticky ? 12000 : 4500);
return () => clearTimeout(timer);
}, [toast]);
if (!shown) return null;
return html`${shown.message}
`;
}
// Anything that changes production asks twice. The second click is a different
// button label so muscle memory cannot carry you through both.
export function Confirm({ label, confirmLabel, onConfirm, danger, disabled, busy }) {
const [armed, setArmed] = useState(false);
useEffect(() => {
if (!armed) return undefined;
const timer = setTimeout(() => setArmed(false), 5000);
return () => clearTimeout(timer);
}, [armed]);
if (busy) return html``;
if (!armed) {
return html``;
}
return html`
`;
}