45 lines
1.3 KiB
TypeScript
45 lines
1.3 KiB
TypeScript
'use client'
|
|
|
|
import { SEQUENCE_SLOTS, PUBLIC_SLOT_CAP } from '@/lib/clusterMock'
|
|
|
|
type Props = {
|
|
used: number
|
|
size?: 'sm' | 'lg'
|
|
showCap?: boolean
|
|
}
|
|
|
|
/**
|
|
* The signature element. Eight discrete cells, one per vLLM sequence slot.
|
|
* Cells past PUBLIC_SLOT_CAP are operator headroom and read as reserved.
|
|
*/
|
|
export function SlotMeter({ used, size = 'sm', showCap = false }: Props) {
|
|
const cell = size === 'lg' ? 'h-6 w-3' : 'h-3 w-[7px]'
|
|
|
|
return (
|
|
<div className="flex items-center gap-2">
|
|
<div className="flex gap-[3px]" role="img" aria-label={`${used} of ${SEQUENCE_SLOTS} sequence slots in use`}>
|
|
{Array.from({ length: SEQUENCE_SLOTS }, (_, i) => {
|
|
const reserved = i >= PUBLIC_SLOT_CAP
|
|
const active = i < used
|
|
return (
|
|
<span
|
|
key={i}
|
|
className={[
|
|
cell,
|
|
'rounded-[1px] transition-colors duration-500',
|
|
active ? 'bg-lamp' : reserved ? 'bg-wire' : 'bg-wire-lit/40',
|
|
reserved && !active ? 'opacity-50' : '',
|
|
].join(' ')}
|
|
/>
|
|
)
|
|
})}
|
|
</div>
|
|
{showCap && (
|
|
<span className="font-data text-[10px] uppercase tracking-widest text-dim">
|
|
{used}/{PUBLIC_SLOT_CAP} public · {SEQUENCE_SLOTS} total
|
|
</span>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|