Files
star-erp/resources/js/Components/shared/Pagination.tsx

99 lines
4.1 KiB
TypeScript
Raw Normal View History

2025-12-30 15:03:19 +08:00
import { Link } from "@inertiajs/react";
import { ChevronLeft, ChevronRight } from "lucide-react";
import { cn } from "@/lib/utils";
interface PaginationProps {
links: {
url: string | null;
label: string;
active: boolean;
}[];
className?: string;
}
export default function Pagination({ links, className }: PaginationProps) {
// 如果只有一頁,不顯示分頁
if (links.length <= 3) return null;
return (
<div className={cn("flex flex-wrap justify-center gap-1", className)}>
{links.map((link, key) => {
// 處理特殊標籤
let label = link.label;
if (label.includes("&laquo;")) label = "Previous";
if (label.includes("&raquo;")) label = "Next";
const isPrevious = label === "Previous";
const isNext = label === "Next";
const activeIndex = links.findIndex(l => l.active);
// Tablet/Mobile visibility logic (< md):
// Show: Previous, Next, Active, and up to 2 neighbors (Total ~5 numeric pages)
// Hide others on small screens (hidden md:flex)
// User requested: "small than 800... display 5 pages"
const isVisibleOnTablet =
isPrevious ||
isNext ||
link.active ||
key === activeIndex - 1 ||
key === activeIndex + 1 ||
key === activeIndex - 2 ||
key === activeIndex + 2;
const baseClasses = cn(
isVisibleOnTablet ? "flex" : "hidden md:flex",
"h-9 items-center justify-center rounded-md border px-3 text-sm"
);
2025-12-30 15:03:19 +08:00
// 如果是 Previous/Next 但沒有 URL則不渲染或者渲染為 disabled
if ((isPrevious || isNext) && !link.url) {
return (
<div
key={key}
className={cn(
baseClasses,
"border-input bg-transparent text-muted-foreground opacity-50 cursor-not-allowed",
2025-12-30 15:03:19 +08:00
isPrevious || isNext ? "px-2" : ""
)}
>
{isPrevious && <ChevronLeft className="h-4 w-4" />}
{isNext && <ChevronRight className="h-4 w-4" />}
{!isPrevious && !isNext && <span dangerouslySetInnerHTML={{ __html: link.label }} />}
</div>
);
}
return link.url ? (
<Link
key={key}
href={link.url}
preserveScroll
className={cn(
baseClasses,
"transition-colors hover:bg-accent hover:text-accent-foreground",
2025-12-30 15:03:19 +08:00
link.active
? "border-primary bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground"
: "border-input bg-transparent text-foreground",
isPrevious || isNext ? "px-2" : ""
)}
>
{isPrevious && <ChevronLeft className="h-4 w-4" />}
{isNext && <ChevronRight className="h-4 w-4" />}
{!isPrevious && !isNext && <span dangerouslySetInnerHTML={{ __html: link.label }} />}
</Link>
) : (
<div
key={key}
className={cn(
baseClasses,
"border-input bg-transparent text-foreground"
)}
2025-12-30 15:03:19 +08:00
>
<span dangerouslySetInnerHTML={{ __html: link.label }} />
</div>
);
})}
</div>
);
}