import * as React from 'react' import { stringWidth } from '../../ink/stringWidth.js' import { Box, Text } from '../../ink.js' 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)} )} )} ) }