import { Box, Text } from "ink";
import { Spinner } from "@inkjs/ui";
import { UnifiedProjectItem } from "./UnifiedProjectItem.tsx";
import { ColumnHeader, ColumnSeparator } from "./ColumnHeader.tsx";
import { useStore, useFilteredUnifiedRepos } from "../state/store.tsx";
interface ProjectListProps {
height?: number;
}
export function ProjectList({ height = 20 }: ProjectListProps) {
const { state } = useStore();
const { cursorIndex, selectedIndices, isLoading, sortBy, sortDirection } = state;
const filteredRepos = useFilteredUnifiedRepos();
if (isLoading) {
return (
);
}
if (filteredRepos.length === 0) {
return (
{/* Always show headers */}
No repositories found
{state.filterText && (
Try a different filter
)}
{state.viewMode === "github" && !state.githubRepos.length && (
<>
{state.githubError ? (
GitHub error: {state.githubError}
) : (
Set GITHUB_TOKEN to see GitHub repos
)}
>
)}
);
}
// Reserve space for header (2 lines: header + separator)
const listHeight = height - 2;
// Calculate visible range with scroll offset
const visibleCount = Math.min(listHeight, filteredRepos.length);
let startIndex = Math.max(0, cursorIndex - Math.floor(visibleCount / 2));
// Adjust if we're near the end
if (startIndex + visibleCount > filteredRepos.length) {
startIndex = Math.max(0, filteredRepos.length - visibleCount);
}
const visibleRepos = filteredRepos.slice(startIndex, startIndex + visibleCount);
return (
{/* Persistent column headers */}
{/* Repository list */}
{visibleRepos.map((repo, idx) => {
const realIndex = startIndex + idx;
return (
);
})}
{/* Scroll indicator at bottom */}
{startIndex + visibleCount < filteredRepos.length && (
↓ {filteredRepos.length - startIndex - visibleCount} more below
)}
);
}