UNPKG

react-responsive-pagination

Version:
132 lines (131 loc) 5.91 kB
import React, { memo, useEffect } from 'react'; import PropTypes from 'prop-types'; import { usePaginationItems } from "./hooks/usePaginationItems.js"; import { defaultLabelBehaviour } from "./labelBehaviour.js"; import { incRenderCount } from "./debug.js"; export * from "./narrowBehaviour.js"; export * from "./presets.js"; export * from "./labelBehaviour.js"; /** * @public */ const ResponsivePaginationComponent = memo(ResponsivePagination); export default ResponsivePaginationComponent; function ResponsivePagination(props) { incRenderCount(); if (process.env.NODE_ENV !== 'production') { checkLegacyProps(props); } const { current, total, onPageChange: handlePageChange, maxWidth, narrowBehaviour, className, containerClassName, extraClassName = 'justify-content-center', pageItemClassName = 'page-item', pageLinkClassName = 'page-link', activeItemClassName = 'active', inactiveItemClassName = '', disabledItemClassName = 'disabled', navClassName, previousClassName, nextClassName, classMerge = defaultClassMerge, previousLabel, nextLabel, ariaPreviousLabel, ariaNextLabel, ariaPageLabel, renderNav = 'anchor-disabled-span', ariaCurrentAttr = true, linkHref = 'hash', labelBehaviour: getLabel = defaultLabelBehaviour, } = props; const { visible, items, ref, clearCache } = usePaginationItems(current, total, { handlePageChange, previousLabel, nextLabel, ariaPreviousLabel, ariaNextLabel, ariaPageLabel, ariaCurrentAttr, linkHref, maxWidth, omitNav: ['none', false].includes(renderNav), narrowBehaviour, }); useEffect(() => { return () => clearCache(); }, [ clearCache, className, containerClassName, pageItemClassName, pageLinkClassName, activeItemClassName, inactiveItemClassName, disabledItemClassName, navClassName, previousClassName, nextClassName, classMerge, ]); if (items.length === 0) return null; function getContainerClassName() { if (className !== undefined) { return className; } else if (containerClassName !== undefined) { return containerClassName; } else if (extraClassName) { return `pagination ${extraClassName}`; } else { return 'pagination'; } } function getListItemClassName(item) { return classNames(classMerge, [ pageItemClassName, item.gotoPage === undefined ? disabledItemClassName : item.active ? activeItemClassName : inactiveItemClassName, item.type === 'next' && (nextClassName ?? navClassName), item.type === 'previous' && (previousClassName ?? navClassName), ]); } return (React.createElement("ul", { className: getContainerClassName(), ref: ref, ...(!visible && { style: { visibility: 'hidden' } }) }, items.map(item => (React.createElement("li", { key: item.key, className: getListItemClassName(item), ...item.listItemProps }, item.type === 'previous' || item.type === 'next' ? (renderNav === 'button' ? (React.createElement("button", { className: pageLinkClassName, ...item.buttonProps }, getLabel(item))) : item.gotoPage !== undefined || renderNav === 'anchor' ? (React.createElement("a", { className: pageLinkClassName, ...item.anchorProps }, getLabel(item))) : (React.createElement("span", { className: pageLinkClassName, ...item.spanAsAnchorProps }, getLabel(item)))) : item.type === 'ellipsis' ? (React.createElement("span", { className: pageLinkClassName }, getLabel(item))) : (React.createElement("a", { className: pageLinkClassName, ...item.anchorProps }, getLabel(item)))))))); } function classNames(classMerge, names) { return classMerge(names.filter((name) => Boolean(name))); } const defaultClassMerge = (classNames) => classNames.join(' '); ResponsivePagination.propTypes = { current: PropTypes.number.isRequired, total: PropTypes.number.isRequired, onPageChange: PropTypes.func.isRequired, maxWidth: PropTypes.number, narrowBehaviour: PropTypes.func, className: PropTypes.string, containerClassName: PropTypes.string, extraClassName: PropTypes.string, pageItemClassName: PropTypes.string, pageLinkClassName: PropTypes.string, activeItemClassName: PropTypes.string, inactiveItemClassName: PropTypes.string, disabledItemClassName: PropTypes.string, disabledLinkClassName: PropTypes.string, navClassName: PropTypes.string, previousClassName: PropTypes.string, nextClassName: PropTypes.string, classMerge: PropTypes.func, previousLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), nextLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), ariaPreviousLabel: PropTypes.string, ariaNextLabel: PropTypes.string, ariaPageLabel: PropTypes.func, renderNav: PropTypes.oneOfType([ PropTypes.bool, PropTypes.oneOf(['none', 'anchor', 'anchor-disabled-span', 'button']), ]), ariaCurrentAttr: PropTypes.bool, linkHref: PropTypes.oneOfType([ PropTypes.func, PropTypes.oneOf(['hash', 'omit']), ]), labelBehaviour: PropTypes.func, }; const legacyUsageWarnings = []; function checkLegacyProps(props) { for (const legacyProp of [ 'srOnlyClassName', 'a11yActiveLabel', 'narrowStrategy', ]) { if (props[legacyProp] !== undefined && !legacyUsageWarnings.includes(legacyProp)) { console.warn(`react-responsive-pagination: '${legacyProp}' prop no longer supported, please see migration guide: https://react-responsive-pagination.elantha.com/migration`); legacyUsageWarnings.push(legacyProp); } } }