@carbon/react
Version:
React components for the Carbon Design System
197 lines (193 loc) • 7.16 kB
JavaScript
/**
* Copyright IBM Corp. 2016, 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
import { extends as _extends } from '../../../_virtual/_rollupPluginBabelHelpers.js';
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import { CaretLeft, CaretRight } from '@carbon/icons-react';
import Select from '../../Select/Select.js';
import '../../Select/Select.Skeleton.js';
import SelectItem from '../../SelectItem/SelectItem.js';
import { IconButton } from '../../IconButton/index.js';
import { usePrefix } from '../../../internal/usePrefix.js';
var _CaretLeft, _CaretRight;
function Pagination({
backwardText = 'Previous page',
children = undefined,
className = null,
disabled = false,
forwardText = 'Next page',
id = 1,
initialPage = 1,
itemsPerPageText = 'Items per page:',
itemRangeText = (min, max, total) => `${min}–${max} of ${total} items`,
itemText = (min, max) => `${min}–${max} items`,
onChange,
pageRangeText = (current, total) => `${current} of ${total} pages`,
pageSize = 10,
pageSizes = undefined,
pageText = page => `page ${page}`,
pagesUnknown = false,
totalItems = undefined,
...other
}) {
const [currentPage, setCurrentPage] = useState(initialPage);
const [currentPageSize, setCurrentPageSize] = useState(pageSize);
const prefix = usePrefix();
const totalPages = totalItems ? Math.max(Math.ceil(totalItems / currentPageSize), 1) : undefined;
const backButtonDisabled = disabled || currentPage === 1;
const forwardButtonDisabled = disabled || currentPage === totalPages;
function onSetPage(newPage) {
setCurrentPage(Number(newPage));
}
function incrementPage() {
const page = currentPage + 1;
setCurrentPage(page);
onChange({
page,
pageSize: currentPageSize
});
}
function decrementPage() {
const page = currentPage - 1;
setCurrentPage(page);
onChange({
page,
pageSize: currentPageSize
});
}
const namespace = `${prefix}--unstable-pagination`;
return /*#__PURE__*/React.createElement("section", _extends({
className: cx(namespace, className)
}, other), /*#__PURE__*/React.createElement("div", {
className: `${namespace}__left`
}, pageSizes && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("label", {
id: `${namespace}__page-sizer__counter-${id}`,
className: `${namespace}__text`,
htmlFor: `${namespace}__page-sizer__input-${id}`
}, itemsPerPageText), /*#__PURE__*/React.createElement(Select, {
id: `${namespace}__page-sizer__input-${id}`,
className: `${namespace}__page-sizer`,
labelText: "",
hideLabel: true,
noLabel: true,
inline: true,
onChange: event => setCurrentPageSize(Number(event.target.value)),
value: currentPageSize
}, pageSizes.map(size => /*#__PURE__*/React.createElement(SelectItem, {
key: size,
value: size,
text: String(size)
})))), /*#__PURE__*/React.createElement("span", {
className: `${namespace}__text`
}, totalItems && !pagesUnknown && itemRangeText(Math.min(currentPageSize * (currentPage - 1) + 1, totalItems), Math.min(currentPage * currentPageSize, totalItems), totalItems), totalItems && pagesUnknown && itemText(currentPageSize * (currentPage - 1) + 1, currentPage * currentPageSize), !totalItems && itemText(currentPageSize * (currentPage - 1) + 1, currentPage * currentPageSize))), /*#__PURE__*/React.createElement("div", {
className: `${namespace}__right`
}, children && totalItems && children({
currentPage,
currentPageSize,
onSetPage,
totalPages
}), children && totalItems && !pagesUnknown && /*#__PURE__*/React.createElement("span", {
className: `${namespace}__text`
}, pageRangeText('', totalPages)), children && !totalItems && /*#__PURE__*/React.createElement("span", {
className: `${namespace}__text`
}, pageText(currentPage)), !children && /*#__PURE__*/React.createElement("span", {
className: `${namespace}__text`
}, !totalItems ? pageText(currentPage) : pageRangeText(currentPage, totalPages)), /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(IconButton, {
align: "top",
disabled: backButtonDisabled,
kind: "ghost",
className: cx(`${namespace}__button`, `${namespace}__button--backward`, {
[`${namespace}__button--no-index`]: backButtonDisabled
}),
label: backwardText,
onClick: () => decrementPage()
}, _CaretLeft || (_CaretLeft = /*#__PURE__*/React.createElement(CaretLeft, null))), /*#__PURE__*/React.createElement(IconButton, {
align: "top-right",
disabled: forwardButtonDisabled,
kind: "ghost",
className: cx(`${namespace}__button`, `${namespace}__button--forward`, {
[`${namespace}__button--no-index`]: forwardButtonDisabled
}),
label: forwardText,
onClick: () => incrementPage()
}, _CaretRight || (_CaretRight = /*#__PURE__*/React.createElement(CaretRight, null))))));
}
Pagination.propTypes = {
/**
* The description for the backward icon.
*/
backwardText: PropTypes.string,
/**
* The children of the pagination component.
*/
children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
/**
* Extra classes to add.
*/
className: PropTypes.string,
/**
* `true` if the backward/forward buttons should be disabled.
*/
disabled: PropTypes.bool,
/**
* The description for the forward icon.
*/
forwardText: PropTypes.string,
/** The unique ID of this component instance. */
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
/**
* The initial active page when the component is first mounted.
*/
initialPage: PropTypes.number,
/**
* The function returning a translatable text showing where the current page is,
* in a manner of the range of items.
*/
itemRangeText: PropTypes.func,
/**
* A variant of `itemRangeText`, used if the total number of items is unknown.
*/
itemText: PropTypes.func,
/**
* The translatable text indicating the number of items per page.
*/
itemsPerPageText: PropTypes.string,
/**
* The callback function called when the current page changes.
*/
onChange: PropTypes.func,
/**
* The function returning a translatable text showing where the current page is,
* in a manner of the total number of pages.
*/
pageRangeText: PropTypes.func,
/**
* The number dictating how many items a page contains.
*/
pageSize: PropTypes.number,
/**
* The choices for `pageSize`.
*/
pageSizes: PropTypes.arrayOf(PropTypes.number),
/**
* The translatable text showing the current page.
*/
pageText: PropTypes.func,
/**
* `true` if total number of pages is unknown.
*/
pagesUnknown: PropTypes.bool,
/**
* The total number of items.
* You need to provide total items to calculate total page,
* which is required by a child like the `PageSelector`
* to know how many pages to display.
*/
totalItems: PropTypes.number
};
export { Pagination as default };