125 lines
2.8 KiB
TypeScript
125 lines
2.8 KiB
TypeScript
import {
|
|
ChevronLeftIcon,
|
|
ChevronRightIcon,
|
|
MoreHorizontalIcon,
|
|
} from "lucide-react";
|
|
import type * as React from "react";
|
|
import { cn } from "./utils";
|
|
|
|
const baseClasses =
|
|
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50";
|
|
|
|
function Pagination({ className, ...props }: React.ComponentProps<"nav">) {
|
|
return (
|
|
<nav
|
|
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;
|
|
} & React.ComponentProps<"a">;
|
|
|
|
function PaginationLink({
|
|
className,
|
|
isActive,
|
|
...props
|
|
}: PaginationLinkProps) {
|
|
return (
|
|
<a
|
|
aria-current={isActive ? "page" : undefined}
|
|
data-slot="pagination-link"
|
|
data-active={isActive}
|
|
className={cn(
|
|
baseClasses,
|
|
isActive
|
|
? "border border-input bg-background hover:bg-accent hover:text-accent-foreground" // outline variant styles
|
|
: "hover:bg-accent hover:text-accent-foreground", // ghost variant styles
|
|
"size-8 p-0", // Default size for icon buttons
|
|
className,
|
|
)}
|
|
{...props}
|
|
/>
|
|
);
|
|
}
|
|
|
|
function PaginationPrevious({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<typeof PaginationLink>) {
|
|
return (
|
|
<PaginationLink
|
|
aria-label="Go to previous page"
|
|
className={cn("gap-1 px-2.5 sm:pl-2.5", className)}
|
|
{...props}
|
|
>
|
|
<ChevronLeftIcon />
|
|
<span className="hidden sm:block">Previous</span>
|
|
</PaginationLink>
|
|
);
|
|
}
|
|
|
|
function PaginationNext({
|
|
className,
|
|
...props
|
|
}: React.ComponentProps<typeof PaginationLink>) {
|
|
return (
|
|
<PaginationLink
|
|
aria-label="Go to next page"
|
|
className={cn("gap-1 px-2.5 sm:pr-2.5", className)}
|
|
{...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>
|
|
);
|
|
}
|
|
|
|
export {
|
|
Pagination,
|
|
PaginationContent,
|
|
PaginationLink,
|
|
PaginationItem,
|
|
PaginationPrevious,
|
|
PaginationNext,
|
|
PaginationEllipsis,
|
|
};
|