89 lines
2.4 KiB
TypeScript
89 lines
2.4 KiB
TypeScript
|
||
|
||
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
||
import { Box } from './primitives/Box';
|
||
import { Button } from './Button';
|
||
import { Icon } from './Icon';
|
||
import { Stack } from './primitives/Stack';
|
||
import { Text } from './Text';
|
||
|
||
interface PaginationProps {
|
||
currentPage: number;
|
||
totalPages: number;
|
||
totalItems: number;
|
||
itemsPerPage: number;
|
||
onPageChange: (page: number) => void;
|
||
}
|
||
|
||
export function Pagination({
|
||
currentPage,
|
||
totalPages,
|
||
totalItems,
|
||
itemsPerPage,
|
||
onPageChange,
|
||
}: PaginationProps) {
|
||
if (totalPages <= 1) return null;
|
||
|
||
const startItem = ((currentPage - 1) * itemsPerPage) + 1;
|
||
const endItem = Math.min(currentPage * itemsPerPage, totalItems);
|
||
|
||
const getPageNumbers = () => {
|
||
if (totalPages <= 5) {
|
||
return Array.from({ length: totalPages }, (_, i) => i + 1);
|
||
}
|
||
|
||
if (currentPage <= 3) {
|
||
return [1, 2, 3, 4, 5];
|
||
}
|
||
|
||
if (currentPage >= totalPages - 2) {
|
||
return [totalPages - 4, totalPages - 3, totalPages - 2, totalPages - 1, totalPages];
|
||
}
|
||
|
||
return [currentPage - 2, currentPage - 1, currentPage, currentPage + 1, currentPage + 2];
|
||
};
|
||
|
||
return (
|
||
<Box display="flex" alignItems="center" justifyContent="between" pt={4}>
|
||
<Text size="sm" color="text-gray-500">
|
||
Showing {startItem}–{endItem} of {totalItems}
|
||
</Text>
|
||
|
||
<Stack direction="row" align="center" gap={2}>
|
||
<Button
|
||
variant="secondary"
|
||
onClick={() => onPageChange(Math.max(1, currentPage - 1))}
|
||
disabled={currentPage === 1}
|
||
size="sm"
|
||
icon={<Icon icon={ChevronLeft} size={5} />}
|
||
>
|
||
<Box as="span" className="sr-only">Previous</Box>
|
||
</Button>
|
||
|
||
<Stack direction="row" align="center" gap={1}>
|
||
{getPageNumbers().map(pageNum => (
|
||
<Button
|
||
key={pageNum}
|
||
variant={currentPage === pageNum ? 'primary' : 'ghost'}
|
||
onClick={() => onPageChange(pageNum)}
|
||
className="w-10 h-10 p-0"
|
||
>
|
||
{pageNum}
|
||
</Button>
|
||
))}
|
||
</Stack>
|
||
|
||
<Button
|
||
variant="secondary"
|
||
onClick={() => onPageChange(Math.min(totalPages, currentPage + 1))}
|
||
disabled={currentPage === totalPages}
|
||
size="sm"
|
||
icon={<Icon icon={ChevronRight} size={5} />}
|
||
>
|
||
<Box as="span" className="sr-only">Next</Box>
|
||
</Button>
|
||
</Stack>
|
||
</Box>
|
||
);
|
||
}
|