import { useBridge, useData, usePublish, type PanelRef } from '@jaspers-ai/sdk' import './styles.css' interface Article { id: string published: string | null title: string | null publisher: string | null author: string | null url: string | null summary: string | null tickers: string | null insights: string | null sentiment: string | null sentiment_ticker: string | null sentiment_reasoning: string | null [field: string]: unknown } interface State { tickers?: string[] limit?: number } const when = (s: string | null) => (s ? new Date(s).toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' }) : '') const tone = (s: string | null) => (s === 'positive' ? 'mv-up' : s === 'negative' ? 'mv-down' : '') export function NewsView({ panel }: { panel: PanelRef }) { const state = useData(`workspaces/${panel.workspaceId}/panels/${panel.id}/state`) as State | undefined if (state === undefined) return

Loading…

const tickers = (state.tickers ?? ['AAPL']).map((t) => t.trim().toUpperCase()).filter(Boolean) return } function List({ panel, tickers, limit }: { panel: PanelRef; tickers: string[]; limit: number }) { const bridge = useBridge() const { data, error, loading, refetch } = useData('massive/news', { tickers, limit }) const rows = (data ?? []) as Article[] usePublish(panel, { tickers, count: rows.length, latest: rows[0]?.title ?? null, error: error ?? null }) return (
News · {tickers.join(', ') || 'all'}
{error ?

{error}

: null} {!data && !error ?

Loading…

: null} {data && !rows.length ?

No articles.

: null}
) }