import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious, } from '@/components/ui/pagination'; import { RAGFlowSelect, RAGFlowSelectOptionType } from '@/components/ui/select'; import { cn } from '@/lib/utils'; import { useCallback, useEffect, useMemo, useState } from 'react'; export type RAGFlowPaginationType = { showQuickJumper?: boolean; onChange?(page: number, pageSize: number): void; total?: number; current?: number; pageSize?: number; showSizeChanger?: boolean; }; export function RAGFlowPagination({ current = 1, pageSize = 10, total = 0, onChange, showSizeChanger = true, }: RAGFlowPaginationType) { const [currentPage, setCurrentPage] = useState(1); const [currentPageSize, setCurrentPageSize] = useState('10'); const sizeChangerOptions: RAGFlowSelectOptionType[] = useMemo(() => { return [10, 20, 50, 100].map((x) => ({ label: {x} / page, value: x.toString(), })); }, []); const pages = useMemo(() => { const num = Math.ceil(total / pageSize); return new Array(num).fill(0).map((_, idx) => idx + 1); }, [pageSize, total]); const changePage = useCallback( (page: number) => { onChange?.(page, Number(currentPageSize)); }, [currentPageSize, onChange], ); const handlePreviousPageChange = useCallback(() => { setCurrentPage((page) => { const previousPage = page - 1; if (previousPage > 0) { changePage(previousPage); return previousPage; } changePage(page); return page; }); }, [changePage]); const handlePageChange = useCallback( (page: number) => () => { changePage(page); setCurrentPage(page); }, [changePage], ); const handleNextPageChange = useCallback(() => { setCurrentPage((page) => { const nextPage = page + 1; if (nextPage <= pages.length) { changePage(nextPage); return nextPage; } changePage(page); return page; }); }, [changePage, pages.length]); const handlePageSizeChange = useCallback( (size: string) => { onChange?.(currentPage, Number(size)); setCurrentPageSize(size); }, [currentPage, onChange], ); useEffect(() => { setCurrentPage(current); }, [current]); useEffect(() => { setCurrentPageSize(pageSize.toString()); }, [pageSize]); // Generates an array of page numbers to display const displayedPages = useMemo(() => { const totalPages = pages.length; const maxDisplayedPages = 5; if (totalPages <= maxDisplayedPages) { return pages; } const left = Math.max(2, currentPage - 2); const right = Math.min(totalPages - 1, currentPage + 2); const newPages = []; newPages.push(1); if (left > 2) { newPages.push(-1); // Indicates an ellipsis } for (let i = left; i <= right; i++) { newPages.push(i); } if (right < totalPages - 1) { newPages.push(-1); } if (totalPages > 1) { newPages.push(totalPages); } return newPages; }, [pages, currentPage]); return (
Total {total} {displayedPages.map((page, index) => page === -1 ? ( ) : ( {page} ), )} {showSizeChanger && ( )}
); }