import { useMemo, useState } from "react"; import { Box, Text } from "../../../../ui"; import { TextAttributes } from "../../../../ui"; import { ExternalLinkText } from "../../../../components/ui"; import { InlineTickerBadge } from "../../../../components/ticker/badge"; import type { InlineTickerCatalogEntry } from "../../../../state/hooks/inline-tickers"; import { blendHex, colors } from "../../../../theme/colors"; import type { ChatUserSummary } from "../../../../api-client"; import { tokenizeInlineContent, type InlineContentToken } from "../../../../utils/inline-content-tokenizer"; import { chatBadgeTextWidth } from "../layout"; export function ResponsiveTickerBadgeText({ text = "", tokens: providedTokens, prewrapped = false, catalog, textColor, openTicker, userByUsername, onUserHover, onUserHoverEnd, }: { text?: string; tokens?: readonly InlineContentToken[]; prewrapped?: boolean; catalog: Record; textColor: string; openTicker: (symbol: string) => void; userByUsername?: Map; onUserHover?: (user: ChatUserSummary) => void; onUserHoverEnd?: () => void; }) { const [hoveredSymbol, setHoveredSymbol] = useState(null); const tokens = useMemo(() => providedTokens ?? tokenizeInlineContent(text), [providedTokens, text]); const renderTextToken = (value: string, tokenIndex: number) => { if (!value) return null; return ( {value} ); }; const renderUsernameToken = (username: string, value: string, tokenIndex: number) => { const user = userByUsername?.get(username.toLowerCase()) ?? null; return ( { if (user) onUserHover?.(user); }} onMouseOut={() => { if (user) onUserHoverEnd?.(); }} > {value} ); }; return ( {tokens.map((token, index) => { if (token.kind === "text") { return renderTextToken(token.value, index); } if (token.kind === "link") { return ( ); } if (token.kind === "username") { return renderUsernameToken(token.username, token.value, index); } const entry = catalog[token.symbol]; if (!entry || entry.status === "missing") { return {token.value}; } // Pre-wrapped lines reserved this width for the chip; it never outgrows it. const maxTextWidth = prewrapped ? chatBadgeTextWidth(token.symbol, entry) : undefined; return ( setHoveredSymbol(token.symbol)} onHoverEnd={() => { setHoveredSymbol((current) => (current === token.symbol ? null : current)); }} onOpen={openTicker} /> ); })} ); }