commonux2
Version:
A collection of styled components for use in ABB projects, designed for React and Next.js. It features TypeScript support, integrates Lucide icons, and is built on Radix primitives with Tailwind CSS.
112 lines (111 loc) • 6.54 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import * as React from "react";
import { useState, useEffect } from "react";
import { ChevronLeftIcon, ChevronRightIcon, ChevronsLeftIcon, ChevronsRightIcon, } from "lucide-react";
import { Button } from "../button";
import { Input } from "../input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "../select";
import { cn } from "../../lib/utils";
const page_limits = [5, 10, 50, 100];
export function Pagination({ totalData, initialItemsPerPage = 10, onPageChange, currentPage: givenPageNo, pageLimits = page_limits, }) {
const [currentPage, setCurrentPage] = useState(givenPageNo !== null && givenPageNo !== void 0 ? givenPageNo : 1);
const [itemsPerPage, setItemsPerPage] = useState(initialItemsPerPage);
const [manualPageChange, setManualPageChange] = useState(false);
const [isValidJump, setIsValidJump] = useState(true);
const [jumpInput, setJumpInput] = useState(currentPage);
const totalPages = Math.ceil(totalData / itemsPerPage);
const handlePageChange = (page) => {
if (page !== currentPage && page >= 1 && page <= totalPages) {
setCurrentPage(page);
setManualPageChange(true);
setJumpInput(page);
}
};
const handleItemsPerPageChange = (value) => {
if (!isNaN(value) && value > 0) {
setItemsPerPage(value);
setManualPageChange(true);
setCurrentPage(1);
}
};
const handleJumpToPage = (value) => {
if (value > totalPages || !value) {
setIsValidJump(false);
return;
}
else
setIsValidJump(true);
handlePageChange(value);
};
useEffect(() => {
if (manualPageChange) {
onPageChange({
currentPage,
pageOffset: (currentPage - 1) * itemsPerPage,
itemsPerPage,
});
setManualPageChange(false);
}
}, [currentPage, itemsPerPage, manualPageChange, onPageChange]);
return (React.createElement("div", { className: "flex flex-col gap-2 px-2 mt-6" },
React.createElement("div", { className: "flex flex-wrap items-center justify-between gap-2" },
React.createElement("div", { className: "flex items-center space-x-2" },
React.createElement(Select, { defaultValue: itemsPerPage.toString(), onValueChange: (val) => handleItemsPerPageChange(+val) },
React.createElement(SelectTrigger, { className: "w-16 h-6 pr-2 text-[12.5px] font-medium border-2 rounded-sm" },
React.createElement(SelectValue, { placeholder: "Theme" })),
React.createElement(SelectContent, null, pageLimits.map((item) => (React.createElement(SelectItem, { className: "text-sm", key: item, value: item.toString() }, item))))),
React.createElement("span", { className: "text-sm font-medium text-muted-foreground" }, "Records per page")),
React.createElement("div", { className: "flex flex-wrap items-center space-x-2.5 space-y-2.5" },
React.createElement("div", { className: "flex items-center space-x-2" },
React.createElement("span", { className: "text-sm font-medium text-muted-foreground" }, "Jump to page"),
React.createElement(Input, { type: "number", value: jumpInput !== null && jumpInput !== void 0 ? jumpInput : 1, onKeyDown: (e) => e.keyCode == 13 && handleJumpToPage(jumpInput), onChange: (e) => setJumpInput(e.target.valueAsNumber), className: cn("w-16 h-6 text-xs font-medium rounded-sm", !isValidJump && "border-destructive") })),
React.createElement("div", { className: "flex items-center gap-1.5 !mt-0" },
React.createElement(PaginationButton, { disabled: currentPage == 1, onClick: () => handlePageChange(1) },
React.createElement(ChevronsLeftIcon, { className: "w-4 h-4" })),
React.createElement(PaginationButton, { disabled: currentPage == 1, onClick: () => handlePageChange(currentPage - 1) },
React.createElement(ChevronLeftIcon, { className: "w-4 h-4" })),
generatePageNumbers(currentPage, totalPages).map((page, index) => page === "..." ? (React.createElement(PaginationElipse, { key: index })) : (React.createElement(PaginationButton, { key: index, isActive: page === currentPage, onClick: () => handlePageChange(page) }, page))),
React.createElement(PaginationButton, { disabled: currentPage == totalPages, onClick: () => handlePageChange(currentPage + 1) },
React.createElement(ChevronRightIcon, { className: "w-4 h-4" })),
React.createElement(PaginationButton, { disabled: currentPage == totalPages, onClick: () => handlePageChange(totalPages) },
React.createElement(ChevronsRightIcon, { className: "w-4 h-4" })))))));
}
function PaginationButton(_a) {
var { className, isActive = false } = _a, props = __rest(_a, ["className", "isActive"]);
return (React.createElement(Button, Object.assign({ size: "icon", variant: "ghost", className: cn("rounded-full hover:bg-gray-300 h-7 w-7 font-medium", className, isActive && "!bg-gray-300") }, props)));
}
function PaginationElipse() {
return React.createElement("span", { className: "px-0.5 -mt-2" }, "...");
}
function generatePageNumbers(currentPage, totalPages) {
const delta = 1;
const range = [];
const rangeWithDots = [];
for (let i = Math.max(2, currentPage - delta); i <= Math.min(totalPages - 1, currentPage + delta); i++) {
range.push(i);
}
if (currentPage - delta > 2) {
rangeWithDots.push(1, "...");
}
else {
rangeWithDots.push(1);
}
rangeWithDots.push(...range);
if (currentPage + delta < totalPages - 1) {
rangeWithDots.push("...", totalPages);
}
else if (totalPages > 1) {
rangeWithDots.push(totalPages);
}
return rangeWithDots;
}