codev / src /components /LogoV2 /Feed.tsx
chenbhao's picture
feat: keep only color
d8a167e
Raw
History Blame Contribute Delete
3.02 kB
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 (
<Box flexDirection="column" width={actualWidth}>
<Text bold color="clawd_body">
{title}
</Text>
{customContent ? (
<>
{customContent.content}
{footer && (
<Text dimColor italic>
{truncate(footer, actualWidth)}
</Text>
)}
</>
) : lines.length === 0 && emptyMessage ? (
<Text dimColor>{truncate(emptyMessage, actualWidth)}</Text>
) : (
<>
{lines.map((line, index) => {
const textWidth = Math.max(
10,
actualWidth -
(maxTimestampWidth > 0 ? maxTimestampWidth + gap.length : 0),
)
return (
<Text key={index}>
{maxTimestampWidth > 0 && (
<>
<Text dimColor>
{(line.timestamp || '').padEnd(maxTimestampWidth)}
</Text>
{gap}
</>
)}
<Text>{truncate(line.text, textWidth)}</Text>
</Text>
)
})}
{footer && (
<Text dimColor italic>
{truncate(footer, actualWidth)}
</Text>
)}
</>
)}
</Box>
)
}