SPB Git forge

spb/market-atlas

Public
12commits 1branches 0releases
1.1 MBsize
maindefault branch
10 days agolast push
TypeScript 96.7% SQL 1.6% CSS 0.8% JavaScript 0.5%
1.4 KB · 34 lines tsx
Raw Blame History
1"use client";23import { useMemo } from "react";4import { EventRow } from "./event-row";5import { cx } from "@/lib/format";6import { useLiveEvents, useMarketStream } from "@/lib/stream";7import type { MarketEvent } from "@/lib/types";89/** Initial events (SSR) merged with events arriving on `events:*` (or a narrower channel). */10export function LiveEvents({ initial, channel = "events:*", max = 40, dense, className, types }: { initial: MarketEvent[]; channel?: string; max?: number; dense?: boolean; className?: string; types?: string[] }) {11  useMarketStream([channel]);12  const live = useLiveEvents(max);13  const merged = useMemo(() => {14    const seen = new Set<string>();15    const out: MarketEvent[] = [];16    for (const e of [...live, ...initial]) {17      if (seen.has(e.id)) continue;18      if (types && !types.includes(e.type)) continue;19      seen.add(e.id);20      out.push(e);21      if (out.length >= max) break;22    }23    return out;24  }, [live, initial, max, types]);25  if (!merged.length) return <div className={cx("rounded-md border border-dashed border-rule px-4 py-8 text-center text-sm text-ink-3", className)}>No events yet — the feed fills as sources emit changes.</div>;26  return (27    <ul className={cx("rounded-md border border-rule bg-surface px-3", className)}>28      {merged.map((e) => (29        <EventRow key={e.id} e={e} dense={dense} />30      ))}31    </ul>32  );33}34