import * as React from 'react' import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon, } from 'lucide-react' import { cn } from '@/lib/utils' import { Button, buttonVariants } from '@/components/ui/button' function Pagination({ className, ...props }: React.ComponentProps<'nav'>) { return ( <nav role="navigation" aria-label="pagination" data-slot="pagination" className={cn('mx-auto flex w-full justify-center', className)} {...props} /> ) } function PaginationContent({ className, ...props }: React.ComponentProps<'ul'>) { return ( <ul data-slot="pagination-content" className={cn('flex flex-row items-center gap-1', className)} {...props} /> ) } function PaginationItem({ ...props }: React.ComponentProps<'li'>) { return <li data-slot="pagination-item" {...props} /> } type PaginationLinkProps = { isActive?: boolean isDisabled?: boolean } & Pick<React.ComponentProps<typeof Button>, 'size'> & React.ComponentProps<'a'> function PaginationLink({ className, isActive, isDisabled, size = 'icon', ...props }: PaginationLinkProps) { return ( <a aria-current={isActive ? 'page' : undefined} data-slot="pagination-link" data-active={isActive} data-disabled={isDisabled} className={cn( buttonVariants({ variant: isActive ? 'outline' : 'ghost', size, }), isDisabled && 'pointer-events-none opacity-50', className, )} {...props} /> ) } function PaginationPrevious({ className, isDisabled, ...props }: React.ComponentProps<typeof PaginationLink>) { return ( <PaginationLink aria-label="Go to previous page" size="default" className={cn('gap-1 px-2.5 sm:pl-2.5', className)} isDisabled={isDisabled} {...props} > <ChevronLeftIcon /> <span className="hidden sm:block">Previous</span> </PaginationLink> ) } function PaginationNext({ className, isDisabled, ...props }: React.ComponentProps<typeof PaginationLink>) { return ( <PaginationLink aria-label="Go to next page" size="default" className={cn('gap-1 px-2.5 sm:pr-2.5', className)} isDisabled={isDisabled} {...props} > <span className="hidden sm:block">Next</span> <ChevronRightIcon /> </PaginationLink> ) } function PaginationEllipsis({ className, ...props }: React.ComponentProps<'span'>) { return ( <span aria-hidden data-slot="pagination-ellipsis" className={cn('flex size-9 items-center justify-center', className)} {...props} > <MoreHorizontalIcon className="size-4" /> <span className="sr-only">More pages</span> </span> ) } const PaginationComponent: React.FC<PaginationProps> = ({ currentPage, totalPages, baseUrl, }) => { const pages = Array.from({ length: totalPages }, (_, i) => i + 1) const getPageUrl = (page: number) => { if (page === 1) return baseUrl return `${baseUrl}${page}` } return ( <Pagination> <PaginationContent className="flex-wrap"> <PaginationItem> <PaginationPrevious href={currentPage > 1 ? getPageUrl(currentPage - 1) : undefined} isDisabled={currentPage === 1} /> </PaginationItem> {pages.map((page) => ( <PaginationItem key={page}> <PaginationLink href={getPageUrl(page)} isActive={page === currentPage} > {page} </PaginationLink> </PaginationItem> ))} {totalPages > 5 && ( <PaginationItem> <PaginationEllipsis /> </PaginationItem> )} <PaginationItem> <PaginationNext href={currentPage < totalPages ? getPageUrl(currentPage + 1) : undefined} isDisabled={currentPage === totalPages} /> </PaginationItem> </PaginationContent> </Pagination> ) } interface PaginationProps { currentPage: number totalPages: number baseUrl: string } export default PaginationComponent export { Pagination, PaginationContent, PaginationLink, PaginationItem, PaginationPrevious, PaginationNext, PaginationEllipsis, }