@douyinfe/semi-ui
Version:
A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.
480 lines (478 loc) • 17.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _noop2 = _interopRequireDefault(require("lodash/noop"));
var _react = _interopRequireDefault(require("react"));
var _classnames = _interopRequireDefault(require("classnames"));
var _propTypes = _interopRequireDefault(require("prop-types"));
var _reactWindow = require("react-window");
var _foundation = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/pagination/foundation"));
var _constants = require("@douyinfe/semi-foundation/lib/cjs/pagination/constants");
require("@douyinfe/semi-foundation/lib/cjs/pagination/pagination.css");
var _constants2 = require("@douyinfe/semi-foundation/lib/cjs/popover/constants");
var _semiIcons = require("@douyinfe/semi-icons");
var _warning = _interopRequireDefault(require("@douyinfe/semi-foundation/lib/cjs/utils/warning"));
var _context = _interopRequireDefault(require("../configProvider/context"));
var _localeConsumer = _interopRequireDefault(require("../locale/localeConsumer"));
var _index = _interopRequireDefault(require("../select/index"));
var _index2 = _interopRequireDefault(require("../inputNumber/index"));
var _baseComponent = _interopRequireDefault(require("../_base/baseComponent"));
var _index3 = _interopRequireDefault(require("../popover/index"));
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
var __rest = void 0 && (void 0).__rest || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
}
return t;
};
/* eslint-disable jsx-a11y/no-noninteractive-element-to-interactive-role */
const prefixCls = _constants.cssClasses.PREFIX;
const {
Option
} = _index.default;
class Pagination extends _baseComponent.default {
constructor(props) {
super(props);
const total = props.total;
const pageSize = props.pageSize || props.pageSizeOpts[0] || _constants.numbers.DEFAULT_PAGE_SIZE; // Use pageSize first, use the first of pageSizeOpts when not, use the default value when none
const shouldFillAllNumber = props.size === 'small' && props.hoverShowPageSelect && !props.disabled;
this.state = {
total,
showTotal: props.showTotal,
currentPage: props.currentPage || props.defaultCurrentPage,
pageSize,
pageList: [],
prevDisabled: false,
nextDisabled: false,
restLeftPageList: [],
restRightPageList: [],
quickJumpPage: '',
allPageNumbers: shouldFillAllNumber ? Array.from({
length: Math.ceil(total / pageSize)
}, (v, i) => i + 1) : [] // only need to count in smallPage mode, when props.size = small
};
this.foundation = new _foundation.default(this.adapter);
this.renderDefaultPage = this.renderDefaultPage.bind(this);
this.renderSmallPage = this.renderSmallPage.bind(this);
(0, _warning.default)(Boolean(props.showSizeChanger && props.hideOnSinglePage), '[Semi Pagination] You should not use showSizeChanger and hideOnSinglePage in ths same time. At this time, hideOnSinglePage no longer takes effect, otherwise there may be a problem that the switch entry disappears');
}
get adapter() {
return Object.assign(Object.assign({}, super.adapter), {
setPageList: pageListState => {
const {
pageList,
restLeftPageList,
restRightPageList
} = pageListState;
this.setState({
pageList,
restLeftPageList,
restRightPageList
});
},
setDisabled: (prevIsDisabled, nextIsDisabled) => {
this.setState({
prevDisabled: prevIsDisabled,
nextDisabled: nextIsDisabled
});
},
updateTotal: total => this.setState({
total
}),
updatePageSize: pageSize => this.setState({
pageSize
}),
updateQuickJumpPage: quickJumpPage => this.setState({
quickJumpPage
}),
updateAllPageNumbers: allPageNumbers => this.setState({
allPageNumbers
}),
setCurrentPage: pageIndex => {
this.setState({
currentPage: pageIndex
});
},
registerKeyDownHandler: handler => {
document.addEventListener('keydown', handler);
},
unregisterKeyDownHandler: handler => {
document.removeEventListener('keydown', handler);
},
notifyPageChange: pageIndex => {
this.props.onPageChange(pageIndex);
},
notifyPageSizeChange: pageSize => {
this.props.onPageSizeChange(pageSize);
},
notifyChange: (pageIndex, pageSize) => {
this.props.onChange(pageIndex, pageSize);
}
});
}
componentDidMount() {
this.foundation.init();
}
componentWillUnmount() {
this.foundation.destroy();
}
componentDidUpdate(prevProps) {
const pagerProps = {
currentPage: this.props.currentPage,
total: this.props.total,
pageSize: this.props.pageSize
};
let pagerHasChanged = false;
let allPageNumberNeedUpdate = false;
if (prevProps.currentPage !== this.props.currentPage) {
pagerHasChanged = true;
// this.foundation.updatePage(this.props.currentPage);
}
if (prevProps.total !== this.props.total) {
pagerHasChanged = true;
allPageNumberNeedUpdate = true;
}
if (prevProps.pageSize !== this.props.pageSize) {
pagerHasChanged = true;
allPageNumberNeedUpdate = true;
}
if (pagerHasChanged) {
this.foundation.updatePage(pagerProps.currentPage, pagerProps.total, pagerProps.pageSize);
}
if (allPageNumberNeedUpdate) {
this.foundation.updateAllPageNumbers(pagerProps.total, pagerProps.pageSize);
}
}
renderPrevBtn() {
const {
prevText,
disabled
} = this.props;
const {
prevDisabled
} = this.state;
const isDisabled = prevDisabled || disabled;
const preClassName = (0, _classnames.default)({
[`${prefixCls}-item`]: true,
[`${prefixCls}-prev`]: true,
[`${prefixCls}-item-disabled`]: isDisabled
});
return /*#__PURE__*/_react.default.createElement("li", {
role: "button",
"aria-disabled": isDisabled ? true : false,
"aria-label": "Previous",
onClick: e => !isDisabled && this.foundation.goPrev(e),
className: preClassName,
"x-semi-prop": "prevText"
}, prevText || /*#__PURE__*/_react.default.createElement(_semiIcons.IconChevronLeft, {
size: "large"
}));
}
renderNextBtn() {
const {
nextText,
disabled
} = this.props;
const {
nextDisabled
} = this.state;
const isDisabled = nextDisabled || disabled;
const nextClassName = (0, _classnames.default)({
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-disabled`]: isDisabled,
[`${prefixCls}-next`]: true
});
return /*#__PURE__*/_react.default.createElement("li", {
role: "button",
"aria-disabled": isDisabled ? true : false,
"aria-label": "Next",
onClick: e => !isDisabled && this.foundation.goNext(e),
className: nextClassName,
"x-semi-prop": "nextText"
}, nextText || /*#__PURE__*/_react.default.createElement(_semiIcons.IconChevronRight, {
size: "large"
}));
}
renderPageSizeSwitch(locale) {
// rtl modify the default position
const {
direction
} = this.context;
const defaultPopoverPosition = direction === 'rtl' ? 'bottomRight' : 'bottomLeft';
const {
showSizeChanger,
popoverPosition = defaultPopoverPosition,
disabled,
popoverZIndex
} = this.props;
const {
pageSize
} = this.state;
const switchCls = (0, _classnames.default)(`${prefixCls}-switch`);
if (!showSizeChanger) {
return null;
}
const newPageSizeOpts = this.foundation.pageSizeInOpts();
const pageSizeToken = locale.pageSize;
// Display pageSize in a specific language format order
const options = newPageSizeOpts.map(size => (/*#__PURE__*/_react.default.createElement(Option, {
value: size,
key: size
}, /*#__PURE__*/_react.default.createElement("span", null, pageSizeToken.replace('${pageSize}', size.toString())))));
return /*#__PURE__*/_react.default.createElement("div", {
className: switchCls
}, /*#__PURE__*/_react.default.createElement(_index.default, {
"aria-label": "Page size selector",
disabled: disabled,
onChange: newPageSize => this.foundation.changePageSize(newPageSize),
value: pageSize,
key: pageSize + pageSizeToken,
position: popoverPosition || 'bottomRight',
clickToHide: true,
zIndex: popoverZIndex,
dropdownClassName: `${prefixCls}-select-dropdown`
}, options));
}
renderQuickJump(locale) {
const {
showQuickJumper,
disabled
} = this.props;
const {
quickJumpPage,
total,
pageSize
} = this.state;
if (!showQuickJumper) {
return null;
}
const totalPageNum = this.foundation._getTotalPageNumber(total, pageSize);
const isDisabled = totalPageNum === 1 || disabled;
const quickJumpCls = (0, _classnames.default)({
[`${prefixCls}-quickjump`]: true,
[`${prefixCls}-quickjump-disabled`]: isDisabled
});
return /*#__PURE__*/_react.default.createElement("div", {
className: quickJumpCls
}, /*#__PURE__*/_react.default.createElement("span", null, locale.jumpTo), /*#__PURE__*/_react.default.createElement(_index2.default, {
value: quickJumpPage,
className: `${prefixCls}-quickjump-input-number`,
hideButtons: true,
disabled: isDisabled,
onBlur: e => this.foundation.handleQuickJumpBlur(),
onEnterPress: e => this.foundation.handleQuickJumpEnterPress(e.target.value),
onChange: v => this.foundation.handleQuickJumpNumberChange(v)
}), /*#__PURE__*/_react.default.createElement("span", null, locale.page));
}
renderPageList() {
const {
pageList,
currentPage,
restLeftPageList,
restRightPageList
} = this.state;
const {
popoverPosition,
popoverZIndex,
disabled
} = this.props;
return pageList.map((page, i) => {
const pageListClassName = (0, _classnames.default)(`${prefixCls}-item`, {
[`${prefixCls}-item-active`]: currentPage === page,
[`${prefixCls}-item-all-disabled`]: disabled,
[`${prefixCls}-item-all-disabled-active`]: currentPage === page && disabled
// [`${prefixCls}-item-rest-opening`]: (i < 3 && isLeftRestHover && page ==='...') || (i > 3 && isRightRestHover && page === '...')
});
const pageEl = /*#__PURE__*/_react.default.createElement("li", {
key: `${page}${i}`,
onClick: () => !disabled && this.foundation.goPage(page, i),
className: pageListClassName,
"aria-label": page === '...' ? 'More' : `Page ${page}`,
"aria-current": currentPage === page ? "page" : false
}, page);
if (page === '...' && !disabled) {
let content;
i < 3 ? content = restLeftPageList : content = restRightPageList;
return /*#__PURE__*/_react.default.createElement(_index3.default, {
rePosKey: this.props.currentPage,
trigger: "hover",
// onVisibleChange={visible=>this.handleRestHover(visible, i < 3 ? 'left' : 'right')}
content: this.renderRestPageList(content),
key: `${page}${i}`,
position: popoverPosition,
zIndex: popoverZIndex
}, pageEl);
}
return pageEl;
});
}
renderRestPageList(restList) {
// The number of pages may be tens of thousands, here is virtualized with the help of react-window
const {
direction
} = this.context;
const className = (0, _classnames.default)(`${prefixCls}-rest-item`);
const count = restList.length;
const row = item => {
const {
index,
style
} = item;
const page = restList[index];
return /*#__PURE__*/_react.default.createElement("div", {
role: "listitem",
key: `${page}${index}`,
className: className,
onClick: () => this.foundation.goPage(page, index),
style: style,
"aria-label": `${page}`
}, page);
};
const itemHeight = 32;
const listHeight = count >= 5 ? itemHeight * 5 : itemHeight * count;
return (
/*#__PURE__*/
// @ts-ignore skip type check cause react-window not update with @types/react 18
_react.default.createElement(_reactWindow.FixedSizeList, {
className: `${prefixCls}-rest-list`,
itemData: restList,
itemSize: itemHeight,
width: 78,
itemCount: count,
height: listHeight,
style: {
direction
}
}, row)
);
}
renderSmallPageSelect(content) {
const allPageNumbers = this.state.allPageNumbers;
const pageList = this.renderRestPageList(allPageNumbers);
return /*#__PURE__*/_react.default.createElement(_index3.default, {
content: pageList
}, content);
}
renderSmallPage(locale) {
const _a = this.props,
{
className,
style,
hideOnSinglePage,
hoverShowPageSelect,
showSizeChanger,
disabled
} = _a,
rest = __rest(_a, ["className", "style", "hideOnSinglePage", "hoverShowPageSelect", "showSizeChanger", "disabled"]);
const paginationCls = (0, _classnames.default)(`${prefixCls}-small`, prefixCls, className, {
[`${prefixCls}-disabled`]: disabled
});
const {
currentPage,
total,
pageSize
} = this.state;
const totalPageNum = Math.ceil(total / pageSize);
if (totalPageNum < 2 && hideOnSinglePage && !showSizeChanger) {
return null;
}
const pageCls = (0, _classnames.default)({
[`${prefixCls}-item`]: true,
[`${prefixCls}-item-small`]: true,
[`${prefixCls}-item-all-disabled`]: disabled
});
const content = /*#__PURE__*/_react.default.createElement("div", {
className: pageCls
}, currentPage, "/", totalPageNum, " ");
return /*#__PURE__*/_react.default.createElement("div", Object.assign({
className: paginationCls,
style: style
}, this.getDataAttr(rest)), this.renderPrevBtn(), hoverShowPageSelect && !disabled ? this.renderSmallPageSelect(content) : content, this.renderNextBtn(), this.renderQuickJump(locale));
}
renderDefaultPage(locale) {
const {
total,
pageSize
} = this.state;
const _a = this.props,
{
showTotal,
className,
style,
hideOnSinglePage,
showSizeChanger,
disabled
} = _a,
rest = __rest(_a, ["showTotal", "className", "style", "hideOnSinglePage", "showSizeChanger", "disabled"]);
const paginationCls = (0, _classnames.default)(className, `${prefixCls}`, {
[`${prefixCls}-disabled`]: disabled
});
const showTotalCls = `${prefixCls}-total`;
const totalPageNum = Math.ceil(total / pageSize);
if (totalPageNum < 2 && hideOnSinglePage && !showSizeChanger) {
return null;
}
const totalNum = Math.ceil(total / pageSize);
const totalToken = locale.total.replace('${total}', totalNum.toString());
return /*#__PURE__*/_react.default.createElement("ul", Object.assign({
className: paginationCls,
style: style
}, this.getDataAttr(rest)), showTotal ? (/*#__PURE__*/_react.default.createElement("span", {
className: showTotalCls
}, totalToken)) : null, this.renderPrevBtn(), this.renderPageList(), this.renderNextBtn(), this.renderPageSizeSwitch(locale), this.renderQuickJump(locale));
}
render() {
const {
size
} = this.props;
return /*#__PURE__*/_react.default.createElement(_localeConsumer.default, {
componentName: "Pagination"
}, locale => size === 'small' ? this.renderSmallPage(locale) : this.renderDefaultPage(locale));
}
}
exports.default = Pagination;
Pagination.contextType = _context.default;
Pagination.propTypes = {
total: _propTypes.default.number,
showTotal: _propTypes.default.bool,
pageSize: _propTypes.default.number,
pageSizeOpts: _propTypes.default.array,
size: _propTypes.default.string,
currentPage: _propTypes.default.number,
defaultCurrentPage: _propTypes.default.number,
onPageChange: _propTypes.default.func,
onPageSizeChange: _propTypes.default.func,
onChange: _propTypes.default.func,
prevText: _propTypes.default.node,
nextText: _propTypes.default.node,
showSizeChanger: _propTypes.default.bool,
popoverZIndex: _propTypes.default.number,
popoverPosition: _propTypes.default.string,
style: _propTypes.default.object,
className: _propTypes.default.string,
hideOnSinglePage: _propTypes.default.bool,
hoverShowPageSelect: _propTypes.default.bool,
showQuickJumper: _propTypes.default.bool,
disabled: _propTypes.default.bool
};
Pagination.defaultProps = {
total: 1,
popoverZIndex: _constants2.numbers.DEFAULT_Z_INDEX,
showTotal: false,
pageSize: null,
pageSizeOpts: _constants.numbers.PAGE_SIZE_OPTION,
defaultCurrentPage: 1,
size: 'default',
onPageChange: _noop2.default,
onPageSizeChange: _noop2.default,
onChange: _noop2.default,
showSizeChanger: false,
className: '',
hideOnSinglePage: false,
showQuickJumper: false,
disabled: false
};