import { type CSSProperties } from 'react'; import type { ActiveBuff } from '../game/types'; import { BUFF_META } from './buffMeta'; interface BuffStatusStripProps { buffs: ActiveBuff[]; nowMs: number; } const rowStyle: CSSProperties = { display: 'flex', gap: 4, flexWrap: 'wrap', alignItems: 'center', width: '100%', maxWidth: '100%', minWidth: 0, pointerEvents: 'none', }; const chipStyle: CSSProperties = { display: 'inline-flex', alignItems: 'center', gap: 3, padding: '2px 6px', borderRadius: 6, fontSize: 10, fontWeight: 700, color: '#fff', textShadow: '0 1px 2px rgba(0,0,0,0.85)', flexShrink: 0, }; function liveRemainingMs(buff: ActiveBuff, nowMs: number): number { if (buff.expiresAtMs != null) { return Math.max(0, buff.expiresAtMs - nowMs); } return Math.max(0, buff.remainingMs); } /** Read-only active buff indicators (no activation controls). */ export function BuffStatusStrip({ buffs, nowMs }: BuffStatusStripProps) { const live = buffs .map((b) => ({ ...b, remainingMs: liveRemainingMs(b, nowMs) })) .filter((b) => b.remainingMs > 0); if (live.length === 0) return null; return (
{live.map((buff) => { const meta = BUFF_META[buff.type]; if (!meta) return null; const sec = Math.ceil(buff.remainingMs / 1000); const justApplied = buff.durationMs > 0 && buff.remainingMs / buff.durationMs > 0.8; const style: CSSProperties = { ...chipStyle, backgroundColor: `${meta.color}44`, border: `1px solid ${meta.color}aa`, animation: justApplied ? 'buff-status-pulse 0.55s ease-out' : undefined, }; return ( {meta.icon} {sec}s ); })}
); }