@mskcc/carbon-react
Version:
Carbon react components for the MSKCC DSM
369 lines (356 loc) • 13.1 kB
JavaScript
/**
* MSKCC 2021, 2024
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var _rollupPluginBabelHelpers = require('../../_virtual/_rollupPluginBabelHelpers.js');
var cx = require('classnames');
var PropTypes = require('prop-types');
var React = require('react');
var Select = require('../Select/Select.js');
require('../Select/Select.Skeleton.js');
var SelectItem = require('../SelectItem/SelectItem.js');
var array = require('../../tools/array.js');
var useId = require('../../internal/useId.js');
var usePrefix = require('../../internal/usePrefix.js');
var IconButton = require('../IconButton/IconButton.js');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var cx__default = /*#__PURE__*/_interopDefaultLegacy(cx);
var PropTypes__default = /*#__PURE__*/_interopDefaultLegacy(PropTypes);
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
function mapPageSizesToObject(sizes) {
return sizes.map(size => typeof size === 'number' ? {
text: String(size),
value: size
} : size);
}
function renderSelectItems(total) {
let counter = 1;
const itemArr = [];
while (counter <= total) {
itemArr.push( /*#__PURE__*/React__default["default"].createElement(SelectItem["default"], {
key: counter,
value: counter,
text: String(counter)
}));
counter++;
}
return itemArr;
}
function getPageSize(pageSizes, pageSize) {
if (pageSize) {
const hasSize = pageSizes.find(size => {
return pageSize === size.value;
});
if (hasSize) {
return pageSize;
}
}
return pageSizes[0].value;
}
const Pagination = /*#__PURE__*/React__default["default"].forwardRef(function Pagination(_ref, ref) {
let {
backwardText = 'Previous page',
className: customClassName,
disabled = false,
forwardText = 'Next page',
id,
isLastPage = false,
itemText = (min, max) => `${min}–${max} items`,
itemRangeText = (min, max, total) => `${min}–${max} of ${total} items`,
itemsPerPageText = 'Items per page:',
onChange,
pageNumberText: _pageNumberText = 'Page Number',
pageRangeText = (_current, total) => `of ${total} ${total === 1 ? 'page' : 'pages'}`,
page: controlledPage = 1,
pageInputDisabled,
pageSize: controlledPageSize,
pageSizeInputDisabled,
pageSizes: controlledPageSizes,
pageText = (page, pagesUnknown) => `page ${pagesUnknown ? '' : page}`,
pagesUnknown = false,
size = 'md',
totalItems = 0,
...rest
} = _ref;
const prefix = usePrefix.usePrefix();
const inputId = useId.useFallbackId(id);
const backBtnRef = React.useRef(null);
const forwardBtnRef = React.useRef(null);
// const [pageSizes, setPageSizes] = useState<
// { text: string; value: number }[]
// >([]);
const [pageSizes, setPageSizes] = React.useState(() => {
return mapPageSizesToObject(controlledPageSizes);
});
const [prevPageSizes, setPrevPageSizes] = React.useState(controlledPageSizes);
const [page, setPage] = React.useState(controlledPage);
const [prevControlledPage, setPrevControlledPage] = React.useState(controlledPage);
const [pageSize, setPageSize] = React.useState(() => {
return getPageSize(pageSizes, controlledPageSize);
});
const [prevControlledPageSize, setPrevControlledPageSize] = React.useState(controlledPageSize);
const className = cx__default["default"](`${prefix}--pagination`, customClassName, {
[`${prefix}--pagination--${size}`]: size
});
// useEffect(() => {
// const newPageSizes = mapPageSizesToObject(controlledPageSizes);
// setPageSizes(newPageSizes);
// setPageSize(getPageSize(newPageSizes, controlledPageSize));
// }, [controlledPageSizes, controlledPageSize]);
const totalPages = Math.max(Math.ceil(totalItems / pageSize), 1);
const backButtonDisabled = disabled || page === 1;
const backButtonClasses = cx__default["default"]('msk-pagination--button', 'msk-pagination--button-backward', {
// [`${prefix}--pagination__button`]: false,
// [`${prefix}--pagination__button--backward`]: false,
[`${prefix}--pagination__button--no-index`]: backButtonDisabled
});
const forwardButtonDisabled = disabled || page === totalPages;
const forwardButtonClasses = cx__default["default"]('msk-pagination--button', 'msk-pagination--button-forward', {
// [`${prefix}--pagination__button`]: false,
// [`${prefix}--pagination__button--forward`]: false,
[`${prefix}--pagination__button--no-index`]: forwardButtonDisabled
});
const selectItems = renderSelectItems(totalPages);
// Sync state with props
if (controlledPage !== prevControlledPage) {
setPage(controlledPage);
setPrevControlledPage(controlledPage);
}
if (controlledPageSize !== prevControlledPageSize) {
setPageSize(getPageSize(pageSizes, controlledPageSize));
setPrevControlledPageSize(controlledPageSize);
}
if (!array.equals(controlledPageSizes, prevPageSizes)) {
const pageSizes = mapPageSizesToObject(controlledPageSizes);
const hasPageSize = pageSizes.find(size => {
return size.value === pageSize;
});
// Reset page to 1 if the current pageSize is not included in the new page
// sizes
if (!hasPageSize) {
setPage(1);
}
setPageSizes(pageSizes);
setPrevPageSizes(controlledPageSizes);
}
function handleSizeChange(event) {
const pageSize = Number(event.target.value);
const changes = {
pageSize,
page: 1
};
setPage(changes.page);
setPageSize(changes.pageSize);
if (onChange) {
onChange(changes);
}
}
function handlePageInputChange(event) {
const page = Number(event.target.value);
if (page > 0 && page <= Math.max(Math.ceil(totalItems / pageSize), 1)) {
setPage(page);
if (onChange) {
onChange({
page,
pageSize
});
}
}
}
function changePage(newPage) {
if (newPage > 0 && newPage <= Math.max(Math.ceil(totalItems / pageSize), 1)) {
setPage(newPage);
if (onChange) {
onChange({
page: newPage,
pageSize
});
}
}
}
function handlePageInputKeyDown(event) {
if (event.key === 'Enter') {
const selectElement = event.target;
const selectedValue = Number(selectElement.value);
changePage(selectedValue);
}
}
function incrementPage() {
const nextPage = page + 1;
setPage(nextPage);
if (nextPage === totalPages) {
backBtnRef.current?.focus();
}
if (onChange) {
onChange({
page: nextPage,
pageSize,
backBtnRef
});
}
}
function decrementPage() {
const nextPage = page - 1;
setPage(nextPage);
if (nextPage === 1) {
forwardBtnRef.current?.focus();
}
if (onChange) {
onChange({
page: nextPage,
pageSize,
forwardBtnRef
});
}
}
return /*#__PURE__*/React__default["default"].createElement("div", _rollupPluginBabelHelpers["extends"]({
className: className,
ref: ref
}, rest), /*#__PURE__*/React__default["default"].createElement("div", {
className: `${prefix}--pagination__left`
}, /*#__PURE__*/React__default["default"].createElement("label", {
id: `${prefix}-pagination-select-${inputId}-count-label`,
className: `${prefix}--pagination__text`,
htmlFor: `${prefix}-pagination-select-${inputId}`
}, itemsPerPageText), /*#__PURE__*/React__default["default"].createElement(Select["default"], {
id: `${prefix}-pagination-select-${inputId}`,
className: `${prefix}--select__item-count`,
labelText: "",
hideLabel: true,
noLabel: true,
inline: true,
onChange: handleSizeChange,
disabled: pageSizeInputDisabled || disabled,
value: pageSize
}, pageSizes.map(sizeObj => /*#__PURE__*/React__default["default"].createElement(SelectItem["default"], {
key: sizeObj.value,
value: sizeObj.value,
text: String(sizeObj.text)
}))), /*#__PURE__*/React__default["default"].createElement("span", {
className: `${prefix}--pagination__text ${prefix}--pagination__items-count`
}, pagesUnknown ? itemText(pageSize * (page - 1) + 1, page * pageSize) : itemRangeText(Math.min(pageSize * (page - 1) + 1, totalItems), Math.min(page * pageSize, totalItems), totalItems))), /*#__PURE__*/React__default["default"].createElement("div", {
className: `${prefix}--pagination__right`
}, pagesUnknown ? /*#__PURE__*/React__default["default"].createElement("span", {
className: `${prefix}--pagination__text ${prefix}--pagination__page-text`
}, pagesUnknown ? pageText(page, pagesUnknown) : pageRangeText(page, totalPages)) : null, /*#__PURE__*/React__default["default"].createElement(Select["default"], {
id: `${prefix}-pagination-select-${inputId}-right`,
className: `msk-select--page-number`,
labelText: `Page number, of ${totalPages} pages`,
inline: true,
hideLabel: true,
onChange: handlePageInputChange,
onKeyDown: handlePageInputKeyDown,
value: page,
disabled: pageInputDisabled || disabled
}, selectItems), pagesUnknown ? null : /*#__PURE__*/React__default["default"].createElement("span", {
className: `${prefix}--pagination__text`
}, pagesUnknown ? pageText(page, pagesUnknown) : pageRangeText(page, totalPages)), /*#__PURE__*/React__default["default"].createElement("div", {
className: `${prefix}--pagination__control-buttons`
}, /*#__PURE__*/React__default["default"].createElement(IconButton.IconButton, {
align: "top",
disabled: backButtonDisabled,
kind: "ghost",
className: backButtonClasses,
label: backwardText,
onClick: decrementPage,
ref: backBtnRef
}, "arrow_left"), /*#__PURE__*/React__default["default"].createElement(IconButton.IconButton, {
align: "top-right",
disabled: forwardButtonDisabled || isLastPage,
kind: "ghost",
className: forwardButtonClasses,
label: forwardText,
onClick: incrementPage,
ref: forwardBtnRef
}, "arrow_right"))));
});
Pagination.propTypes = {
/**
* The description for the backward icon.
*/
backwardText: PropTypes__default["default"].string,
/**
* The CSS class names.
*/
className: PropTypes__default["default"].string,
/**
* `true` if the backward/forward buttons, as well as the page select elements, should be disabled.
*/
disabled: PropTypes__default["default"].bool,
/**
* The description for the forward icon.
*/
forwardText: PropTypes__default["default"].string,
/**
* The unique ID of this component instance.
*/
id: PropTypes__default["default"].oneOfType([PropTypes__default["default"].string, PropTypes__default["default"].number]),
// TODO: remove when v9 is deprecated
/**
* `true` if the current page should be the last page.
*/
isLastPage: PropTypes__default["default"].bool,
/**
* The function returning a translatable text showing where the current page is,
* in a manner of the range of items.
*/
itemRangeText: PropTypes__default["default"].func,
/**
* A variant of `itemRangeText`, used if the total number of items is unknown.
*/
itemText: PropTypes__default["default"].func,
/**
* The translatable text indicating the number of items per page.
*/
itemsPerPageText: PropTypes__default["default"].string,
/**
* The callback function called when the current page changes.
*/
onChange: PropTypes__default["default"].func,
/**
* The current page.
*/
page: PropTypes__default["default"].number,
/**
* `true` if the select box to change the page should be disabled.
*/
pageInputDisabled: PropTypes__default["default"].bool,
pageNumberText: PropTypes__default["default"].string,
/**
* A function returning PII showing where the current page is.
*/
pageRangeText: PropTypes__default["default"].func,
/**
* The number dictating how many items a page contains.
*/
pageSize: PropTypes__default["default"].number,
/**
* `true` if the select box to change the items per page should be disabled.
*/
pageSizeInputDisabled: PropTypes__default["default"].bool,
/**
* The choices for `pageSize`.
*/
pageSizes: PropTypes__default["default"].oneOfType([PropTypes__default["default"].arrayOf(PropTypes__default["default"].number.isRequired), PropTypes__default["default"].arrayOf(PropTypes__default["default"].shape({
text: PropTypes__default["default"].string.isRequired,
value: PropTypes__default["default"].number.isRequired
}).isRequired)]).isRequired,
/**
* The translatable text showing the current page.
*/
pageText: PropTypes__default["default"].func,
/**
* `true` if the total number of items is unknown.
*/
pagesUnknown: PropTypes__default["default"].bool,
/**
* Specify the size of the Pagination.
*/
size: PropTypes__default["default"].oneOf(['sm', 'md', 'lg']),
/**
* The total number of items.
*/
totalItems: PropTypes__default["default"].number
};
exports["default"] = Pagination;