Files
usa/src/components/NewsTicker.tsx
2026-03-02 16:29:11 +08:00

57 lines
2.1 KiB
TypeScript

import { useMemo } from 'react'
import type { SituationUpdate, ConflictEvent } from '@/data/mockData'
import { processTickerText } from '@/utils/tickerText'
interface NewsTickerProps {
updates?: SituationUpdate[]
conflictEvents?: ConflictEvent[]
className?: string
}
export function NewsTicker({ updates = [], conflictEvents = [], className = '' }: NewsTickerProps) {
const items = useMemo(() => {
const list: { id: string; text: string }[] = []
for (const e of conflictEvents || []) {
const text = processTickerText(e.title || '')
if (text) list.push({ id: `ev-${e.event_id}`, text })
}
for (const u of updates || []) {
const text = processTickerText(u.summary || '')
if (text) list.push({ id: `up-${u.id}`, text })
}
return list.slice(0, 30)
}, [updates, conflictEvents])
const baseCls = 'flex items-center overflow-hidden'
const defaultCls = 'border-b border-military-border/50 bg-military-panel/60 py-1.5'
const wrapperCls = className ? `${baseCls} ${className}` : `${baseCls} ${defaultCls}`
if (items.length === 0) {
return (
<div className={wrapperCls}>
<span className="shrink-0 pr-2 text-[10px] uppercase text-military-text-secondary"></span>
<span className="text-[11px] text-military-text-secondary"></span>
</div>
)
}
const content = items.map((i) => i.text).join(' ◆ ')
const duration = Math.max(180, Math.min(480, content.length * 0.8))
return (
<div className={wrapperCls}>
<span className="shrink-0 pr-2 text-[10px] font-medium uppercase tracking-wider text-cyan-400"></span>
<div className="min-w-0 flex-1 overflow-hidden">
<div
className="inline-flex whitespace-nowrap text-[11px] text-military-text-secondary"
style={{ animation: `ticker ${duration}s linear infinite` }}
>
<span className="px-2">{content}</span>
<span className="px-2 text-cyan-400/60"></span>
<span className="px-2">{content}</span>
</div>
</div>
</div>
)
}