UNPKG

@resourge/react-pagination

Version:

`react-pagination` is a small, highly customizable, component to render the pagination.

247 lines (239 loc) 6.58 kB
/** * 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