67 lines
1.6 KiB
TypeScript
67 lines
1.6 KiB
TypeScript
"use client";
|
|
|
|
import { Badge } from "@/components/ui/badge";
|
|
import type { HeadlineNode } from "@/app/actions";
|
|
import { KeywordHighlighter } from "./keyword-highlighter";
|
|
|
|
interface HeadlineTreeProps {
|
|
headlines: HeadlineNode[];
|
|
keyword?: string | null;
|
|
}
|
|
|
|
const HeadlineNodeDisplay = ({
|
|
node,
|
|
level,
|
|
keyword,
|
|
}: {
|
|
node: HeadlineNode;
|
|
level: number;
|
|
keyword?: string | null;
|
|
}) => {
|
|
return (
|
|
<>
|
|
<div
|
|
className="flex items-center gap-3 py-2.5 pr-4 border-t"
|
|
style={{ paddingLeft: `${16 + level * 24}px` }}
|
|
>
|
|
<Badge
|
|
variant="secondary"
|
|
className="uppercase w-12 flex-shrink-0 justify-center font-mono"
|
|
>
|
|
{node.tag}
|
|
</Badge>
|
|
<p className="font-medium flex-grow text-foreground">
|
|
<KeywordHighlighter text={node.text} keyword={keyword} />
|
|
</p>
|
|
<p className="text-sm text-muted-foreground flex-shrink-0 w-10 text-right">
|
|
{node.length}
|
|
</p>
|
|
</div>
|
|
{node.children?.map((child, index) => (
|
|
<HeadlineNodeDisplay
|
|
key={index}
|
|
node={child}
|
|
level={level + 1}
|
|
keyword={keyword}
|
|
/>
|
|
))}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export function HeadlineTree({ headlines, keyword }: HeadlineTreeProps) {
|
|
return (
|
|
<div className="w-full rounded-lg overflow-hidden">
|
|
<div className="-mt-px">
|
|
{headlines.map((headline, index) => (
|
|
<HeadlineNodeDisplay
|
|
key={index}
|
|
node={headline}
|
|
level={0}
|
|
keyword={keyword}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
} |