glide-design-system
Version:
Glide design system is an open-source React component library. It offers numerous benefits that make them essential tools for design and development teams.
290 lines (276 loc) • 9.27 kB
JavaScript
import React, { useState, useEffect } from "react";
import "./pagination.css";
import PropTypes from "prop-types";
/**
* A pagination component
*
* @param {function} onChange - Callback function when a page is changed.
* @param {number} page - Current active page.
* @param {number} count - Total number of pages.
* @param {string} color - Background color for active page.
* @param {string} className - custom class for styles
*/
export const Pagination = ({
onChange,
page,
count,
color,
className,
containerClass,
style,
}) => {
const [lastElement, setLastElement] = useState(false);
const [more, setMore] = useState(false);
const [pages, setPages] = useState(page);
const [renderCounter, setRenderCounter] = useState(
count > 10 ? [1, 2, 3, 4, 5, 6] : [1, 2, 3]
);
useEffect(() => {
setRenderCounter(count > 10 ? [1, 2, 3, 4, 5, 6] : [1, 2, 3, 4]);
}, [count]);
return (
<div
className={`paginationParentContainer ${
containerClass ? containerClass : ""
}`}
>
<div
id="previous-page"
className={`paginationChildContainer ${className ? className : ""}`}
style={{ ...style }}
onClick={() => {
// this if conditions for morethan a 10 pages
if (count > 10) {
setPages(page - 1);
if (page < 7) {
setLastElement(false);
setMore(false);
setRenderCounter([1, 2, 3, 4, 5, 6]);
}
}
onChange &&
(count || count !== 0) &&
page - 1 > 0 &&
onChange(page - 1);
}}
>
<span className="material-symbols-outlined paginationIcon">
chevron_left
</span>
</div>
{count <= 10 && (
<div style={{ display: "flex" }}>
{Array.from({ length: count ? count : 0 })?.map((_, i) => {
return (
<div
key={i}
id={`page-${i}`}
data-testid={`page-${i}`}
onClick={() => onChange && onChange(i + 1)}
className={`paginationChildContainer ${
className ? className : ""
}`}
style={{
backgroundColor:
i + 1 === page ? (color ? color : "#0a5b99") : "#ffffff",
color: i + 1 === page ? "#ffffff" : "#333333",
...style,
}}
>
<div className="pageCount">{i + 1}</div>
</div>
);
})}
</div>
)}
{/* if the page has more than a 10 pages it will be nvoke */}
{count > 10 && (
<div
style={{
display: "flex",
}}
>
<div
id={`page-1`}
onClick={() => {
setMore(false);
setRenderCounter([1, 2, 3, 4, 5, 6]);
onChange && onChange(1);
}}
className={`paginationChildContainer ${className ? className : ""}`}
style={{
backgroundColor: page === 1 ? "#0a5b99" : "#ffffff",
color: page === 1 ? "white" : "",
}}
>
{/* this div contains 1 st page default */}
<div className="pageCount">{1}</div>
</div>
{renderCounter.map((i) => {
return (
<div
key={i}
id={`page-${i}`}
data-testid={`page-${i}`}
onClick={() => {
setRenderCounter(count > 10 ? [1, 2, 3, 4, 5, 6] : [1, 2, 3]);
onChange && onChange(i + 1);
if (pages >= 4) {
setLastElement(false);
setMore(false);
}
}}
className={`paginationChildContainer ${
className ? className : ""
}`}
style={{
backgroundColor:
i + 1 === page ? (color ? color : "#0a5b99") : "#ffffff",
color: i + 1 === page ? "#ffffff" : "#333333",
...style,
}}
>
<div className="pageCount">{i + 1}</div>
</div>
);
})}
{pages < count - 2 && more && page >= 5 && (
<>
{/*This area responsible for If the user reaches a page beyond the seventh, this div invokes, and the closest three pages to the current page will be shows */}
<div style={{ marginRight: "5px" }}>....</div>
<div
id={`page-${page - 2}`}
style={{
backgroundColor: page - 2 === pages ? "#0a5b99" : "#ffffff",
color: page - 2 === pages ? "white" : "",
}}
onClick={() => {
onChange && onChange(page - 2);
}}
className={`paginationChildContainer ${
className ? className : ""
}`}
>
<div className="pageCount">{page - 2}</div>
</div>
<div
id={`page-${page - 1}`}
style={{
backgroundColor: page - 1 === pages ? "#0a5b99" : "#ffffff",
color: page - 1 === pages ? "white" : "",
}}
onClick={() => {
onChange && onChange(page - 1);
}}
className={`paginationChildContainer ${
className ? className : ""
}`}
>
<div className="pageCount">{page - 1}</div>
</div>
<div
id={`page-${page}`}
style={{
backgroundColor: "#0a5b99",
color: "white",
}}
onClick={() => {
onChange && onChange(page);
}}
className={`paginationChildContainer ${
className ? className : ""
}`}
>
<div className="pageCount">{page}</div>
</div>
</>
)}
<div style={{ marginRight: "5px" }}>....</div>
{/*This area responsible for If the user reaches a last page this div invokes, and the last three pages will be shows */}
{pages >= count - 2 && lastElement && (
<div style={{ display: "flex" }}>
<div
id={`page-${count - 2}`}
onClick={() => {
setLastElement(true);
onChange && onChange(count - 2);
}}
style={{
backgroundColor: page === count - 2 ? "#0a5b99" : "#ffffff",
color: page === count - 2 ? "white" : "",
}}
className={`paginationChildContainer ${
className ? className : ""
}`}
>
<div className="pageCount">{count - 2}</div>
</div>
<div
id={`page-${count - 1}`}
style={{
backgroundColor: page === count - 1 ? "#0a5b99" : "#ffffff",
color: page === count - 1 ? "white" : "",
}}
onClick={() => {
onChange && onChange(count - 1);
}}
className={`paginationChildContainer ${
className ? className : ""
}`}
>
<div className="pageCount">{count - 1}</div>
</div>
</div>
)}
{/* this div contains last page by default */}
<div
id={`page-${count}`}
style={{
backgroundColor: page === count ? "#0a5b99" : "#ffffff",
color: page === count ? "white" : "",
}}
onClick={() => {
setMore(true);
setLastElement(true);
setPages(count);
setRenderCounter([1]);
onChange && onChange(count);
}}
className={`paginationChildContainer ${className ? className : ""}`}
>
<div className="pageCount">{count}</div>
</div>
</div>
)}
<div
id="next-page"
className={`paginationChildContainer ${className ? className : ""}`}
style={{ ...style }}
onClick={() => {
if (count > 10) {
setPages(page + 1);
if (page >= 7) {
setLastElement(true);
setMore(true);
setRenderCounter([1]);
}
}
onChange &&
(count || count !== 0) &&
page + 1 <= count &&
onChange(page + 1);
}}
>
<span className="material-symbols-outlined paginationIcon">
chevron_right
</span>
</div>
</div>
);
};
Pagination.propTypes = {
onChange: PropTypes.func,
count: PropTypes.number,
page: PropTypes.number,
color: PropTypes.string,
};