77 lines
2.2 KiB
Svelte
77 lines
2.2 KiB
Svelte
<script lang="ts">
|
|
import type { BlockSummary } from "../types";
|
|
import { formatTokens, formatCountdown, formatPct } from "../format";
|
|
|
|
let {
|
|
block,
|
|
cap,
|
|
nowSeconds,
|
|
}: {
|
|
block: BlockSummary | null;
|
|
cap: number;
|
|
/** Locally-decremented countdown so we don't IPC just to tick the clock. */
|
|
nowSeconds: number;
|
|
} = $props();
|
|
|
|
// Geometry.
|
|
const SIZE = 140;
|
|
const STROKE = 12;
|
|
const R = (SIZE - STROKE) / 2;
|
|
const C = 2 * Math.PI * R;
|
|
|
|
let pct = $derived(block && cap > 0 ? Math.min(1, block.total_tokens / cap) : 0);
|
|
let dash = $derived(C * pct);
|
|
let color = $derived(
|
|
pct > 0.95 ? "var(--danger)" : pct > 0.8 ? "var(--warn)" : "var(--accent)",
|
|
);
|
|
let pulse = $derived(pct > 0.9);
|
|
</script>
|
|
|
|
<div class="wrap">
|
|
<svg width={SIZE} height={SIZE} viewBox={`0 0 ${SIZE} ${SIZE}`}>
|
|
<!-- track -->
|
|
<circle
|
|
cx={SIZE / 2}
|
|
cy={SIZE / 2}
|
|
r={R}
|
|
fill="none"
|
|
stroke="var(--border)"
|
|
stroke-width={STROKE}
|
|
/>
|
|
<!-- progress -->
|
|
<circle
|
|
cx={SIZE / 2}
|
|
cy={SIZE / 2}
|
|
r={R}
|
|
fill="none"
|
|
stroke={color}
|
|
stroke-width={STROKE}
|
|
stroke-linecap="round"
|
|
stroke-dasharray={`${dash} ${C}`}
|
|
transform={`rotate(-90 ${SIZE / 2} ${SIZE / 2})`}
|
|
class:pulse
|
|
/>
|
|
<text x={SIZE / 2} y={SIZE / 2 - 6} text-anchor="middle" class="big">
|
|
{block ? formatTokens(block.total_tokens) : "—"}
|
|
</text>
|
|
<text x={SIZE / 2} y={SIZE / 2 + 12} text-anchor="middle" class="small">
|
|
{block ? formatPct(block.total_tokens, cap) : ""}
|
|
</text>
|
|
<text x={SIZE / 2} y={SIZE / 2 + 30} text-anchor="middle" class="countdown">
|
|
{block ? formatCountdown(nowSeconds) : "no activity"}
|
|
</text>
|
|
</svg>
|
|
</div>
|
|
|
|
<style>
|
|
.wrap { display: flex; justify-content: center; padding: 14px 0 6px; }
|
|
text { fill: var(--fg); font-family: inherit; }
|
|
text.big { font-size: 22px; font-weight: 600; }
|
|
text.small { font-size: 11px; fill: var(--fg-dim); }
|
|
text.countdown { font-size: 11px; fill: var(--fg-dim); font-variant-numeric: tabular-nums; }
|
|
.pulse { animation: pulse 1.6s ease-in-out infinite; }
|
|
@keyframes pulse {
|
|
0%, 100% { opacity: 1; }
|
|
50% { opacity: 0.55; }
|
|
}
|
|
</style>
|