@alifd/next
Version:
A configurable component library for web built on React.
753 lines (638 loc) • 26.2 kB
JavaScript
'use strict';
exports.__esModule = true;
var _objectWithoutProperties2 = require('babel-runtime/helpers/objectWithoutProperties');
var _objectWithoutProperties3 = _interopRequireDefault(_objectWithoutProperties2);
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck');
var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
var _possibleConstructorReturn2 = require('babel-runtime/helpers/possibleConstructorReturn');
var _possibleConstructorReturn3 = _interopRequireDefault(_possibleConstructorReturn2);
var _inherits2 = require('babel-runtime/helpers/inherits');
var _inherits3 = _interopRequireDefault(_inherits2);
var _class, _temp;
var _react = require('react');
var _react2 = _interopRequireDefault(_react);
var _propTypes = require('prop-types');
var _propTypes2 = _interopRequireDefault(_propTypes);
var _reactLifecyclesCompat = require('react-lifecycles-compat');
var _classnames = require('classnames');
var _classnames2 = _interopRequireDefault(_classnames);
var _configProvider = require('../config-provider');
var _configProvider2 = _interopRequireDefault(_configProvider);
var _icon = require('../icon');
var _icon2 = _interopRequireDefault(_icon);
var _button = require('../button');
var _button2 = _interopRequireDefault(_button);
var _input = require('../input');
var _input2 = _interopRequireDefault(_input);
var _select = require('../select');
var _select2 = _interopRequireDefault(_select);
var _util = require('../util');
var _zhCn = require('../locale/zh-cn.js');
var _zhCn2 = _interopRequireDefault(_zhCn);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var Option = _select2.default.Option;
var noop = function noop() {};
function correctCurrent(currentPage, total, currentPageSize) {
var totalPage = getTotalPage(total, currentPageSize);
return currentPage > totalPage ? totalPage : currentPage;
}
function getTotalPage(total, currentPageSize) {
var totalPage = Math.ceil(total / currentPageSize);
return totalPage <= 0 ? 1 : totalPage;
}
/**
* Pagination
*/
var Pagination = (_temp = _class = function (_Component) {
(0, _inherits3.default)(Pagination, _Component);
function Pagination(props, context) {
(0, _classCallCheck3.default)(this, Pagination);
var _this = (0, _possibleConstructorReturn3.default)(this, _Component.call(this, props, context));
_this.handleJump = function (e) {
var total = _this.props.total;
var _this$state = _this.state,
current = _this$state.current,
currentPageSize = _this$state.currentPageSize,
inputValue = _this$state.inputValue;
var totalPage = getTotalPage(total, currentPageSize);
var value = parseInt(inputValue, 10);
if (isNaN(value)) {
value = '';
} else if (value < 1) {
value = 1;
} else if (value > totalPage) {
value = totalPage;
}
if (value && value !== current) {
_this.onPageItemClick(value, e);
}
_this.setState({
inputValue: ''
});
};
_this.state = {
current: props.defaultCurrent || 1,
currentPageSize: 0,
inputValue: ''
};
return _this;
}
Pagination.getDerivedStateFromProps = function getDerivedStateFromProps(props, state) {
var current = props.current,
total = props.total,
pageSize = props.pageSize;
var st = {};
var newCurrent = correctCurrent(current || state.current, total, pageSize);
if (state.current !== newCurrent) {
st.current = newCurrent;
}
if (state.currentPageSize !== pageSize) {
st.currentPageSize = pageSize;
}
return st;
};
Pagination.prototype.onPageItemClick = function onPageItemClick(page, e) {
if (!('current' in this.props)) {
this.setState({
current: page
});
}
this.props.onChange(page, e);
};
Pagination.prototype.onInputChange = function onInputChange(value) {
this.setState({
inputValue: value
});
};
Pagination.prototype.onSelectSize = function onSelectSize(pageSize) {
var newState = {
currentPageSize: pageSize
};
var totalPage = getTotalPage(this.props.total, pageSize);
if (this.state.current > totalPage) {
newState.current = totalPage;
}
this.setState(newState);
this.props.onPageSizeChange(pageSize);
};
Pagination.prototype.renderPageTotal = function renderPageTotal() {
var _props = this.props,
prefix = _props.prefix,
total = _props.total,
totalRender = _props.totalRender;
var _state = this.state,
currentPageSize = _state.currentPageSize,
current = _state.current;
var range = [(current - 1) * currentPageSize + 1, current * currentPageSize];
return _react2.default.createElement(
'div',
{ className: prefix + 'pagination-total' },
totalRender(total, range)
);
};
Pagination.prototype.renderPageItem = function renderPageItem(index) {
var _cx;
var _props2 = this.props,
prefix = _props2.prefix,
size = _props2.size,
link = _props2.link,
pageNumberRender = _props2.pageNumberRender,
total = _props2.total,
pageSize = _props2.pageSize,
locale = _props2.locale;
var current = this.state.current;
var totalPage = getTotalPage(total, pageSize);
var isCurrent = parseInt(index, 10) === current;
var props = {
size: size,
className: (0, _classnames2.default)((_cx = {}, _cx[prefix + 'pagination-item'] = true, _cx[prefix + 'current'] = isCurrent, _cx)),
onClick: isCurrent ? noop : this.onPageItemClick.bind(this, index)
};
if (link) {
props.component = 'a';
props.href = link.replace('{page}', index);
}
return _react2.default.createElement(
_button2.default,
(0, _extends3.default)({
'aria-label': _util.str.template(locale.total, {
current: index,
total: totalPage
})
}, props, {
key: index
}),
pageNumberRender(index)
);
};
Pagination.prototype.renderPageFirst = function renderPageFirst(current) {
var _cx2;
var _props3 = this.props,
prefix = _props3.prefix,
size = _props3.size,
shape = _props3.shape,
locale = _props3.locale;
var isFirst = current <= 1;
var props = {
disabled: isFirst,
size: size,
className: (0, _classnames2.default)((_cx2 = {}, _cx2[prefix + 'pagination-item'] = true, _cx2[prefix + 'prev'] = true, _cx2)),
onClick: this.onPageItemClick.bind(this, current - 1)
};
var icon = _react2.default.createElement(_icon2.default, { type: 'arrow-left', className: prefix + 'pagination-icon-prev' });
return _react2.default.createElement(
_button2.default,
(0, _extends3.default)({}, props, { 'aria-label': _util.str.template(locale.labelPrev, { current: current }) }),
icon,
shape === 'arrow-only' || shape === 'arrow-prev-only' || shape === 'no-border' ? '' : locale.prev
);
};
Pagination.prototype.renderPageLast = function renderPageLast(current, totalPage) {
var _cx3;
var _props4 = this.props,
prefix = _props4.prefix,
size = _props4.size,
shape = _props4.shape,
locale = _props4.locale;
var isLast = current >= totalPage;
var props = {
disabled: isLast,
size: size,
className: (0, _classnames2.default)((_cx3 = {}, _cx3[prefix + 'pagination-item'] = true, _cx3[prefix + 'next'] = true, _cx3)),
onClick: this.onPageItemClick.bind(this, current + 1)
};
var icon = _react2.default.createElement(_icon2.default, { type: 'arrow-right', className: prefix + 'pagination-icon-next' });
return _react2.default.createElement(
_button2.default,
(0, _extends3.default)({}, props, { 'aria-label': _util.str.template(locale.labelNext, { current: current }) }),
shape === 'arrow-only' || shape === 'no-border' ? '' : locale.next,
icon
);
};
Pagination.prototype.renderPageEllipsis = function renderPageEllipsis(idx) {
var prefix = this.props.prefix;
return _react2.default.createElement(_icon2.default, {
className: prefix + 'pagination-ellipsis ' + prefix + 'pagination-icon-ellipsis',
type: 'ellipsis',
key: 'ellipsis-' + idx
});
};
Pagination.prototype.renderPageJump = function renderPageJump() {
var _this2 = this;
var _props5 = this.props,
prefix = _props5.prefix,
size = _props5.size,
locale = _props5.locale;
var inputValue = this.state.inputValue;
/* eslint-disable react/jsx-key */
return [_react2.default.createElement(
'span',
{ className: prefix + 'pagination-jump-text' },
locale.goTo
), _react2.default.createElement(_input2.default, {
className: prefix + 'pagination-jump-input',
type: 'text',
'aria-label': locale.inputAriaLabel,
size: size,
value: inputValue,
onChange: this.onInputChange.bind(this),
onKeyDown: function onKeyDown(e) {
if (e.keyCode === _util.KEYCODE.ENTER) {
_this2.handleJump(e);
}
}
}), _react2.default.createElement(
'span',
{ className: prefix + 'pagination-jump-text' },
locale.page
), _react2.default.createElement(
_button2.default,
{ className: prefix + 'pagination-jump-go', size: size, onClick: this.handleJump },
locale.go
)];
/* eslint-enable react/jsx-key */
};
Pagination.prototype.renderPageDisplay = function renderPageDisplay(current, totalPage) {
var _props6 = this.props,
prefix = _props6.prefix,
pageNumberRender = _props6.pageNumberRender;
return _react2.default.createElement(
'span',
{ className: prefix + 'pagination-display' },
_react2.default.createElement(
'em',
null,
pageNumberRender(current)
),
'/',
pageNumberRender(totalPage)
);
};
Pagination.prototype.renderPageList = function renderPageList(current, totalPage) {
var _props7 = this.props,
prefix = _props7.prefix,
pageShowCount = _props7.pageShowCount;
var pages = [];
if (totalPage <= pageShowCount) {
for (var i = 1; i <= totalPage; i++) {
pages.push(this.renderPageItem(i));
}
} else {
// 除去第一页,最后一页以及当前页,剩下的页数
var othersCount = pageShowCount - 3;
var halfCount = parseInt(othersCount / 2, 10);
var start = void 0,
end = void 0;
pages.push(this.renderPageItem(1));
start = current - halfCount;
end = current + halfCount;
if (start <= 1) {
start = 2;
end = start + othersCount;
}
if (start > 2) {
pages.push(this.renderPageEllipsis(1));
}
if (end >= totalPage - 1) {
end = totalPage - 1;
start = totalPage - 1 - othersCount;
}
for (var j = start; j <= end; j++) {
pages.push(this.renderPageItem(j));
}
if (end < totalPage - 1) {
pages.push(this.renderPageEllipsis(2));
}
pages.push(this.renderPageItem(totalPage));
}
return _react2.default.createElement(
'div',
{ className: prefix + 'pagination-list' },
pages
);
};
Pagination.prototype.renderPageSizeSelector = function renderPageSizeSelector() {
var _props8 = this.props,
prefix = _props8.prefix,
pageSizeSelector = _props8.pageSizeSelector,
locale = _props8.locale;
var pageSizeSpan = _react2.default.createElement(
'span',
{ className: prefix + 'pagination-size-selector-title' },
locale.pageSize
);
switch (pageSizeSelector) {
case 'filter':
return _react2.default.createElement(
'div',
{ className: prefix + 'pagination-size-selector' },
pageSizeSpan,
this.renderPageSizeFilter()
);
case 'dropdown':
return _react2.default.createElement(
'div',
{ className: prefix + 'pagination-size-selector' },
pageSizeSpan,
this.renderPageSizeDropdown()
);
default:
return null;
}
};
Pagination.prototype.renderPageSizeFilter = function renderPageSizeFilter() {
var _this3 = this;
var _props9 = this.props,
prefix = _props9.prefix,
size = _props9.size,
pageSizeList = _props9.pageSizeList;
var currentPageSize = this.state.currentPageSize;
return _react2.default.createElement(
'div',
{ className: prefix + 'pagination-size-selector-filter' },
pageSizeList.map(function (item, index) {
var _cx4;
var label = void 0;
var pageSize = void 0;
if (item.value) {
// {label: '', value: 5}
label = item.label;
pageSize = item.value;
} else {
// number
label = pageSize = item;
}
var classes = (0, _classnames2.default)((_cx4 = {}, _cx4[prefix + 'pagination-size-selector-btn'] = true, _cx4[prefix + 'current'] = pageSize === currentPageSize, _cx4));
return _react2.default.createElement(
_button2.default,
{
key: index,
text: true,
size: size,
className: classes,
onClick: pageSize !== currentPageSize ? _this3.onSelectSize.bind(_this3, pageSize) : null
},
label
);
})
);
};
Pagination.prototype.renderPageSizeDropdown = function renderPageSizeDropdown() {
var _props10 = this.props,
prefix = _props10.prefix,
size = _props10.size,
pageSizeList = _props10.pageSizeList,
locale = _props10.locale,
popupProps = _props10.popupProps,
selectProps = _props10.selectProps;
var currentPageSize = this.state.currentPageSize;
return _react2.default.createElement(
_select2.default,
(0, _extends3.default)({
className: prefix + 'pagination-size-selector-dropdown',
popupClassName: prefix + 'pagination-size-selector-popup',
popupProps: popupProps,
'aria-label': locale.selectAriaLabel,
autoWidth: false,
size: size,
value: currentPageSize,
onChange: this.onSelectSize.bind(this)
}, selectProps),
pageSizeList.map(function (item, index) {
var label = void 0;
var pageSize = void 0;
if (item.value) {
// {label: '', value: 5}
label = item.label;
pageSize = item.value;
} else {
// number
label = pageSize = item;
}
return _react2.default.createElement(
Option,
{ key: index, value: pageSize },
label
);
})
);
};
Pagination.prototype.render = function render() {
var _cx5,
_this4 = this;
/* eslint-disable no-unused-vars */
var _props11 = this.props,
prefix = _props11.prefix,
pure = _props11.pure,
rtl = _props11.rtl,
device = _props11.device,
paginationType = _props11.type,
size = _props11.size,
shape = _props11.shape,
className = _props11.className,
total = _props11.total,
totalRender = _props11.totalRender,
pageSize = _props11.pageSize,
pageSizeSelector = _props11.pageSizeSelector,
pageSizeList = _props11.pageSizeList,
pageSizePosition = _props11.pageSizePosition,
useFloatLayout = _props11.useFloatLayout,
onPageSizeChange = _props11.onPageSizeChange,
hideOnlyOnePage = _props11.hideOnlyOnePage,
showJump = _props11.showJump,
locale = _props11.locale,
current = _props11.current,
defaultCurrent = _props11.defaultCurrent,
pageShowCount = _props11.pageShowCount,
pageNumberRender = _props11.pageNumberRender,
link = _props11.link,
onChange = _props11.onChange,
popupProps = _props11.popupProps,
selectProps = _props11.selectProps,
others = (0, _objectWithoutProperties3.default)(_props11, ['prefix', 'pure', 'rtl', 'device', 'type', 'size', 'shape', 'className', 'total', 'totalRender', 'pageSize', 'pageSizeSelector', 'pageSizeList', 'pageSizePosition', 'useFloatLayout', 'onPageSizeChange', 'hideOnlyOnePage', 'showJump', 'locale', 'current', 'defaultCurrent', 'pageShowCount', 'pageNumberRender', 'link', 'onChange', 'popupProps', 'selectProps']);
/* eslint-enable */
var _state2 = this.state,
currentPage = _state2.current,
currentPageSize = _state2.currentPageSize;
var totalPage = getTotalPage(total, currentPageSize);
var pageFirst = this.renderPageFirst(currentPage);
var pageLast = this.renderPageLast(currentPage, totalPage);
var sizeSelector = this.renderPageSizeSelector();
var isStart = pageSizePosition === 'start';
var type = paginationType;
if (device === 'phone' && type === 'normal') {
type = 'simple';
}
var classes = (0, _classnames2.default)((_cx5 = {}, _cx5[prefix + 'pagination'] = true, _cx5['' + prefix + size] = size, _cx5['' + prefix + type] = type, _cx5['' + prefix + shape] = shape, _cx5[prefix + 'start'] = !!pageSizeSelector && isStart && useFloatLayout, _cx5[prefix + 'end'] = !!pageSizeSelector && !isStart && useFloatLayout, _cx5[prefix + 'hide'] = totalPage <= 1 && hideOnlyOnePage, _cx5[className] = !!className, _cx5));
if (rtl) {
others.dir = 'rtl';
}
var buildComponent = function buildComponent() {
for (var _len = arguments.length, coms = Array(_len), _key = 0; _key < _len; _key++) {
coms[_key] = arguments[_key];
}
return _react2.default.createElement(
'div',
(0, _extends3.default)({ className: classes }, _util.obj.pickOthers(Object.keys(Pagination.propTypes), others)),
isStart && sizeSelector,
totalRender ? _this4.renderPageTotal() : null,
_react2.default.createElement(
'div',
{ className: prefix + 'pagination-pages' },
coms.map(function (com, index) {
return com && _react2.default.cloneElement(com, { key: index });
})
),
!isStart && sizeSelector
);
};
switch (type) {
case 'mini':
return buildComponent(pageFirst, pageLast);
case 'simple':
{
var pageDisplay = this.renderPageDisplay(currentPage, totalPage);
return buildComponent(pageFirst, pageDisplay, pageLast);
}
case 'normal':
{
var pageList = this.renderPageList(currentPage, totalPage);
var _pageDisplay = showJump && total > pageSize * pageShowCount ? this.renderPageDisplay(currentPage, totalPage) : null;
var pageJump = showJump && total > pageSize * pageShowCount ? this.renderPageJump(currentPage, totalPage) : null;
return buildComponent.apply(undefined, [pageFirst, pageList, pageLast, _pageDisplay].concat(pageJump));
}
default:
return null;
}
};
return Pagination;
}(_react.Component), _class.propTypes = (0, _extends3.default)({}, _configProvider2.default.propTypes, {
prefix: _propTypes2.default.string,
pure: _propTypes2.default.bool,
rtl: _propTypes2.default.bool,
device: _propTypes2.default.oneOf(['desktop', 'tablet', 'phone']),
className: _propTypes2.default.string,
/**
* 自定义国际化文案对象
*/
locale: _propTypes2.default.object,
/**
* 分页组件类型
*/
type: _propTypes2.default.oneOf(['normal', 'simple', 'mini']),
/**
* 前进后退按钮样式
*/
shape: _propTypes2.default.oneOf(['normal', 'arrow-only', 'arrow-prev-only', 'no-border']),
/**
* 分页组件大小
*/
size: _propTypes2.default.oneOf(['small', 'medium', 'large']),
/**
* (受控)当前页码
*/
current: _propTypes2.default.number,
/**
* (非受控)初始页码
*/
defaultCurrent: _propTypes2.default.number,
/**
* 页码发生改变时的回调函数
* @param {Number} current 改变后的页码数
* @param {Object} e 点击事件对象
*/
onChange: _propTypes2.default.func,
/**
* 总记录数
*/
total: _propTypes2.default.number,
/**
* 总数的渲染函数
* @param {Number} total 总数
* @param {Array} range 当前数据在总数中的区间
*/
totalRender: _propTypes2.default.func,
/**
* 页码显示的数量,更多的使用...代替
*/
pageShowCount: _propTypes2.default.number,
/**
* 一页中的记录数
*/
pageSize: _propTypes2.default.number,
/**
* 每页显示选择器类型
*/
pageSizeSelector: _propTypes2.default.oneOf([false, 'filter', 'dropdown']),
/**
* 每页显示选择器可选值
*/
pageSizeList: _propTypes2.default.oneOfType([_propTypes2.default.arrayOf(_propTypes2.default.number), _propTypes2.default.arrayOf(_propTypes2.default.shape({
label: _propTypes2.default.string,
value: _propTypes2.default.number
}))]),
/**
* 自定义页码渲染函数,函数作用于页码button以及当前页/总页数的数字渲染
* @param {Number} index 分页的页码,从1开始
* @return {ReactNode} 返回渲染结果
*/
pageNumberRender: _propTypes2.default.func,
/**
* 每页显示选择器在组件中的位置
*/
pageSizePosition: _propTypes2.default.oneOf(['start', 'end']),
/**
* 存在每页显示选择器时是否使用浮动布局
*/
useFloatLayout: _propTypes2.default.bool,
/**
* 每页显示记录数量改变时的回调函数
* @param {Number} pageSize 改变后的每页显示记录数
*/
onPageSizeChange: _propTypes2.default.func,
/**
* 当分页数为1时,是否隐藏分页器
*/
hideOnlyOnePage: _propTypes2.default.bool,
/**
* type 设置为 normal 时,在页码数超过5页后,会显示跳转输入框与按钮,当设置 showJump 为 false 时,不再显示该跳转区域
*/
showJump: _propTypes2.default.bool,
/**
* 设置页码按钮的跳转链接,它的值为一个包含 {page} 的模版字符串,如:https://www.taobao.com/{page}
*/
link: _propTypes2.default.string,
/**
* 弹层组件属性,透传给Popup
*/
popupProps: _propTypes2.default.object,
selectProps: _propTypes2.default.object
}), _class.defaultProps = {
prefix: 'next-',
pure: false,
rtl: false,
locale: _zhCn2.default.Pagination,
type: 'normal',
shape: 'normal',
size: 'medium',
defaultCurrent: 1,
onChange: noop,
pageSize: 10,
pageSizeSelector: false,
pageSizeList: [5, 10, 20],
pageSizePosition: 'start',
onPageSizeChange: noop,
useFloatLayout: false,
total: 100,
pageShowCount: 5,
hideOnlyOnePage: false,
showJump: true,
pageNumberRender: function pageNumberRender(index) {
return index;
}
}, _temp);
Pagination.displayName = 'Pagination';
exports.default = _configProvider2.default.config((0, _reactLifecyclesCompat.polyfill)(Pagination));
module.exports = exports['default'];