import * as React from 'react'; import { Box, Text, stringWidth } from '@anthropic/ink'; import { truncate } from '../../utils/format.js'; export type FeedLine = { text: string; timestamp?: string; }; export type FeedConfig = { title: string; lines: FeedLine[]; footer?: string; emptyMessage?: string; customContent?: { content: React.ReactNode; width: number }; }; type FeedProps = { config: FeedConfig; actualWidth: number; }; export function calculateFeedWidth(config: FeedConfig): number { const { title, lines, footer, emptyMessage, customContent } = config; let maxWidth = stringWidth(title); if (customContent !== undefined) { maxWidth = Math.max(maxWidth, customContent.width); } else if (lines.length === 0 && emptyMessage) { maxWidth = Math.max(maxWidth, stringWidth(emptyMessage)); } else { const gap = ' '; const maxTimestampWidth = Math.max(0, ...lines.map(line => (line.timestamp ? stringWidth(line.timestamp) : 0))); for (const line of lines) { const timestampWidth = maxTimestampWidth > 0 ? maxTimestampWidth : 0; const lineWidth = stringWidth(line.text) + (timestampWidth > 0 ? timestampWidth + gap.length : 0); maxWidth = Math.max(maxWidth, lineWidth); } } if (footer) { maxWidth = Math.max(maxWidth, stringWidth(footer)); } return maxWidth; } export function Feed({ config, actualWidth }: FeedProps): React.ReactNode { const { title, lines, footer, emptyMessage, customContent } = config; const gap = ' '; const maxTimestampWidth = Math.max(0, ...lines.map(line => (line.timestamp ? stringWidth(line.timestamp) : 0))); return ( {title} {customContent ? ( <> {customContent.content} {footer && ( {truncate(footer, actualWidth)} )} ) : lines.length === 0 && emptyMessage ? ( {truncate(emptyMessage, actualWidth)} ) : ( <> {lines.map((line, index) => { const textWidth = Math.max(10, actualWidth - (maxTimestampWidth > 0 ? maxTimestampWidth + gap.length : 0)); return ( {maxTimestampWidth > 0 && ( <> {(line.timestamp || '').padEnd(maxTimestampWidth)} {gap} )} {truncate(line.text, textWidth)} ); })} {footer && ( {truncate(footer, actualWidth)} )} )} ); }