// ── components.js — shared UI primitives ───────────────── // // One-stop helpers for the repeating bar / pill / chart-header // patterns across pages. Renderers return HTML strings — callers // inject via innerHTML and wire events on the resulting DOM. import { escapeHTML } from './utils.js'; // ── Bar primitives ─────────────────────────────────────── // barTrack — just the percentage bar (no label/count head). // value: numeric value to display // max: ceiling for percentage; 0/falsy means 0% // fwClass: optional framework slug (openclaw, claude-code, hermes, …) // — applied as fw- on the fill for color // size: 'xs' | 'sm' | 'md' | 'lg' (default 'md') // modifier: extra class on the fill (e.g. 'model', 'input', 'output') export function barTrack({ value = 0, max = 0, fwClass = '', size = 'md', modifier = '' } = {}) { const pct = max > 0 ? Math.min(100, (value / max) * 100).toFixed(1) : '0'; const fillClasses = ['am-bar-fill']; if (fwClass) fillClasses.push('fw-' + fwClass); if (modifier) fillClasses.push(modifier); return `
`; } // barRow — head (name + count) plus track. // countDisplay overrides the rendered count text (e.g. "238" vs "238 events"). export function barRow({ name = '', count = 0, countDisplay, max = 0, fwClass = '', size = 'sm', modifier = '' } = {}) { const display = countDisplay != null ? countDisplay : count; return `
${escapeHTML(String(name))} ${escapeHTML(String(display))}
${barTrack({ value: count, max, fwClass, size, modifier })}
`; } // barRankList — ranked list of barRows wrapped in