@resourge/react-pagination
Version:
`react-pagination` is a small, highly customizable, component to render the pagination.
247 lines (239 loc) • 6.58 kB
JavaScript
/**
* react-pagination v1.2.0
*
* Copyright (c) resourge.
*
* This source code is licensed under the MIT license found in the
* LICENSE.md file in the root directory of this source tree.
*
* @license MIT
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@emotion/css')) :
typeof define === 'function' && define.amd ? define(['exports', 'react', '@emotion/css'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.ReactPagination = {}, global.React, global.emotionCss));
})(this, (function (exports, React, css) { 'use strict';
const getMinMaxPage = (page, displayRange, totalPage) => {
const diff = Math.floor(displayRange / 2);
let minPage = Math.max(0, page - diff);
let maxPage = Math.min(totalPage - 1, page + diff);
if (minPage < 0) {
maxPage = totalPage > displayRange ? displayRange - 1 : totalPage;
}
if (maxPage >= totalPage) {
minPage = totalPage - displayRange;
if (maxPage < displayRange) {
minPage = 0;
}
}
return {
minPage,
maxPage
};
};
/**
* Method to generate an array of "pages"
* @param config {@link PaginationConfig}
* @returns an array containing the "pages"
*/
const pagination = ({
page,
totalPages,
displayRange = 5,
disabled = false,
onPageChange,
firstLabel,
previousLabel,
nextLabel,
lastLabel
}) => {
const {
minPage,
maxPage
} = getMinMaxPage(page <= totalPages ? page : 0, displayRange, totalPages);
const createPage = (label, type, page) => label ? {
label: typeof label === 'function' ? label() : label,
type,
page,
disabled: disabled || page < 0 || page >= totalPages,
onClick: () => {
onPageChange(page);
}
} : null;
return [createPage(firstLabel, 'firstPage', 0), createPage(previousLabel, 'previousPage', page - 1), ...Array.from({
length: maxPage - minPage + 1
}, (_, i) => {
const p = minPage + i;
return {
label: p + 1,
page: p,
type: 'page',
disabled,
selected: page === p,
onClick: () => {
onPageChange(p);
}
};
}), createPage(nextLabel, 'nextPage', page + 1), createPage(lastLabel, 'lastPage', totalPages - 1)].filter(Boolean);
};
/**
* Hook to generate an array of "pages"
* @param props {@link UsePaginationProps}
* @returns an array containing the "pages"
*/
const usePagination = props => {
var _props$onPageChange;
const onPageChange = (_props$onPageChange = props.onPageChange) != null ? _props$onPageChange : () => {};
const onPageChangeRef = React.useRef(onPageChange);
onPageChangeRef.current = onPageChange;
return React.useMemo(() => pagination({
...props,
onPageChange: page => {
onPageChangeRef.current(page);
},
firstLabel: props.renderFirst,
previousLabel: props.renderPrevious,
nextLabel: props.renderNext,
lastLabel: props.renderLast
// eslint-disable-next-line react-hooks/exhaustive-deps
}), [props.page, props.totalPages, props.disabled]);
};
const PrimaryColor = '#2E3641';
const DisableColor = '#D0D0D0';
const pageItemLinkSelectedDisabled = {
backgroundColor: DisableColor,
color: 'white'
};
const pageItemDisabled = ({
selected
}) => ({
cursor: 'not-allowed',
border: `2px solid ${DisableColor}`,
color: DisableColor,
'& > *': {
cursor: 'not-allowed',
opacity: 0.5
},
...(selected ? pageItemLinkSelectedDisabled : {})
});
const DefaultUlCss = {
listStyle: 'none',
display: 'flex',
alignItems: 'center',
gap: '0.75rem',
padding: 0
};
const DefaultACss = _ => ({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
color: 'inherit',
width: '1.875rem',
height: '1.875rem'
});
const DefaultLiCss = ({
disabled,
selected
}) => ({
cursor: 'pointer',
borderRadius: '5px',
border: `2px solid ${PrimaryColor}`,
color: PrimaryColor,
'& > *': {
color: PrimaryColor
},
...(disabled ? pageItemDisabled({
selected
}) : {}),
'&:hover': {
backgroundColor: 'rgba(46,54,65, 0.15)',
color: PrimaryColor
},
...(selected ? {
backgroundColor: PrimaryColor,
color: 'white',
'& > *': {
color: 'white'
},
'&:hover': {
opacity: 0.75
}
} : {})
});
const PageItem = ({
href,
children,
onClick,
disabled,
selected,
customStyles
}) => {
const cssProps = {
disabled,
selected
};
const defaultLiCss = DefaultLiCss(cssProps);
const defaultACss = DefaultACss();
const liCss = customStyles && customStyles.li ? customStyles.li(defaultLiCss, cssProps) : defaultLiCss;
const aCss = customStyles && customStyles.a ? customStyles.a(defaultACss, cssProps) : defaultACss;
return /*#__PURE__*/React.createElement("li", {
"aria-label": typeof children === 'number' ? `Page ${children}` : undefined,
className: css.css(liCss),
role: 'navigation'
}, /*#__PURE__*/React.createElement("a", {
className: css.css(aCss),
href: href,
rel: "noreferrer",
target: "_blank",
onClick: event => {
if (event.ctrlKey || event.metaKey) {
return;
}
event.preventDefault();
event.stopPropagation();
if (!disabled) {
onClick && onClick();
}
}
}, children));
};
/* eslint-disable @typescript-eslint/prefer-nullish-coalescing */
/**
* Pagination component
*/
const Pagination = ({
className,
page,
totalPages = 1,
getHref,
customStyles,
...usePaginationProps
}) => {
const pages = usePagination({
page,
totalPages,
...usePaginationProps
});
const ulCss = customStyles && customStyles.ul ? customStyles.ul(DefaultUlCss) : DefaultUlCss;
return /*#__PURE__*/React.createElement("ul", {
className: `${css.css(ulCss)}${className ? ` ${className}` : ''}`
}, pages.map(({
label,
page,
disabled,
selected,
onClick
}, index) => /*#__PURE__*/React.createElement(PageItem, {
key: `pagination_page_item_${index}`,
customStyles: customStyles,
disabled: disabled,
href: getHref && getHref(page),
selected: selected,
onClick: onClick
}, label)));
};
exports.Pagination = Pagination;
exports.pagination = pagination;
exports.usePagination = usePagination;
}));
//# sourceMappingURL=react-pagination.development.js.map