wix-style-react
Version:
wix-style-react
191 lines • 9.83 kB
JavaScript
import * as React from 'react';
import { st, classes } from './PaginationCore.st.css';
import { DataHooks } from './constants';
import { calculateWidth, getId, measureAndSetRootMinWidth } from './utils';
import { PageStrip } from './PageStrip';
import { filterDataProps } from '../../utils/propsUtils';
const upperCaseFirst = (str) => str[0].toUpperCase() + str.slice(1);
class PaginationCore extends React.Component {
constructor() {
super(...arguments);
this.getMaxPagesToShow = () => {
if (this.props.maxPagesToShow) {
return this.props.maxPagesToShow;
}
if (this.props.responsive) {
return 20;
}
return 7;
};
this.state = {
pageInputValue: String(this.props.currentPage),
pageInputHasError: false,
};
this.handlePageInputChange = (e) => {
this.setState({
pageInputValue: e.target.value,
pageInputHasError: false,
});
};
this.handlePageInputKeyDown = (event) => {
// Enter
if (event.key === 'Enter') {
const page = Number(this.state.pageInputValue);
if (page !== this.props.currentPage) {
if (1 <= page && page <= this.props.totalPages) {
this.props.onChange && this.props.onChange({ event, page });
}
else {
this.setState({ pageInputHasError: true });
}
}
}
};
this.handlePageInputBlur = () => {
this.setState({
pageInputValue: String(this.props.currentPage),
pageInputHasError: false,
});
};
this.handlePageClick = (event, page) => {
this.props.onChange && this.props.onChange({ event, page });
};
this.handlePageKeyDown = (event, page) => {
// Enter or Space
if (event.key === 'Enter' || event.key === 'Space') {
this.props.onChange && this.props.onChange({ event, page });
}
};
}
updateRootMinWidth() {
this.rootNode &&
this.props.paginationMode &&
measureAndSetRootMinWidth(this.rootNode, this.props.paginationMode, this.props.id);
}
componentDidMount() {
this.props.updateResponsiveLayout && this.updateRootMinWidth();
}
componentDidUpdate() {
this.props.updateResponsiveLayout && this.updateRootMinWidth();
}
getId(elementName = '') {
return getId(this.props.id, elementName);
}
renderPageStrip() {
return (React.createElement(PageStrip, { id: this.props.id, totalPages: this.props.totalPages || 0, currentPage: this.props.currentPage || 0, maxPagesToShow: this.getMaxPagesToShow() || 0, showFirstPage: !!this.props.showFirstPage, showLastPage: !!this.props.showLastPage, responsive: !!this.props.responsive, pageUrl: this.props.pageUrl, gapLabel: this.props.gapLabel || '', onPageClick: this.handlePageClick, onPageKeyDown: this.handlePageKeyDown, updateResponsiveLayout: this.props.updateResponsiveLayout, disabled: !!this.props.disabled }));
}
renderPages() {
switch (this.props.paginationMode) {
case "input" /* PaginationCoreMode.Input */:
return this.renderPageForm();
case "compact" /* PaginationCoreMode.Compact */:
return this.renderPageCompact();
case "pages" /* PaginationCoreMode.Pages */:
default:
return this.renderPageStrip();
}
}
renderPageCompact() {
return (React.createElement("div", { "data-hook": DataHooks.pageCompact, id: this.getId('pageCompact'), className: classes.compact },
React.createElement("span", { id: this.getId('currentPage'), "data-hook": DataHooks.currentPage }, this.props.currentPage),
React.createElement("span", { id: this.getId('slash'), className: classes.slash, "data-hook": DataHooks.slashLabel }, this.props.slashLabel),
React.createElement("span", { id: this.getId('totalPages'), "data-hook": DataHooks.totalPages }, this.props.totalPages)));
}
renderPageForm() {
return (React.createElement("div", { "data-hook": DataHooks.pageForm, id: this.getId('pageForm'), className: classes.pageForm, dir: "ltr" },
React.createElement("input", { id: this.getId('pageInput'), "data-hook": DataHooks.pageInput, type: "number", className: classes.pageInput, min: 1, max: this.props.totalPages, value: this.state.pageInputValue, disabled: this.props.disabled, onChange: this.handlePageInputChange, onKeyDown: this.handlePageInputKeyDown, "aria-label": 'Page number, select a number between 1 and ' +
this.props.totalPages, onBlur: this.handlePageInputBlur, style: { width: calculateWidth(this.props.totalPages) } }),
this.props.showInputModeTotalPages && [
React.createElement("span", { key: "slash", id: this.getId('slash'), className: classes.slash }, this.props.slashLabel),
React.createElement("span", { key: "total-pages", id: this.getId('totalPages'), "data-hook": DataHooks.totalPages, className: classes.totalPages }, this.props.totalPages),
]));
}
renderEmptyButton(type) {
let btnClass = '';
switch (type) {
case "previous" /* ButtonType.Prev */: {
btnClass = classes.emptyButtonPrevious;
break;
}
case "next" /* ButtonType.Next */: {
btnClass = classes.emptyButtonNext;
break;
}
default:
}
return (React.createElement("div", { "data-hook": DataHooks[type], className: st(classes.emptyButton, btnClass) }));
}
renderNavButton(type) {
const { currentPage, totalPages, pageUrl } = this.props;
const disabled = this.props.disabled ||
((type === "first" /* ButtonType.First */ || type === "previous" /* ButtonType.Prev */) &&
(currentPage || 0) <= 1) ||
((type === "last" /* ButtonType.Last */ || type === "next" /* ButtonType.Next */) &&
(currentPage || 0) >= totalPages);
const [btnClass, label, page] = {
["previous" /* ButtonType.Prev */]: [
classes.navButtonPrevious,
this.props.previousLabel,
(currentPage || 0) - 1,
],
["next" /* ButtonType.Next */]: [
classes.navButtonNext,
this.props.nextLabel,
(currentPage || 0) + 1,
],
["first" /* ButtonType.First */]: [classes.navButtonFirst, this.props.firstLabel, 1],
["last" /* ButtonType.Last */]: [
classes.navButtonLast,
this.props.lastLabel,
totalPages,
],
}[type];
return (React.createElement("a", { "data-hook": DataHooks[type], id: this.getId('navButton' + upperCaseFirst(type)), className: st(classes.navButton, { disabled }, btnClass), "aria-label": upperCaseFirst(type) + ' Page', "aria-disabled": disabled, tabIndex: disabled || pageUrl ? undefined : 0, onClick: disabled ? undefined : event => this.handlePageClick(event, page), onKeyDown: disabled ? undefined : event => this.handlePageKeyDown(event, page), href: !disabled && pageUrl ? pageUrl(page) : undefined }, label));
}
UNSAFE_componentWillReceiveProps(nextProps) {
this.setState({
pageInputValue: String(nextProps.currentPage),
pageInputHasError: false,
});
}
render() {
const { disabled, showFirstLastNavButtons, showNextLabel, showPreviousLabel, width, style: inlineStyle, } = this.props;
const styleStates = {
disabled,
error: this.state.pageInputHasError,
};
return (React.createElement("nav", { ref: el => (this.rootNode = el), id: this.getId(''), "aria-label": "PaginationCore Navigation", "aria-disabled": disabled, dir: this.props.rtl ? 'rtl' : undefined, onClick: this.props.onClick, onDoubleClick: this.props.onDoubleClick, onMouseEnter: this.props.onMouseEnter, onMouseLeave: this.props.onMouseLeave, style: inlineStyle || { width }, className: st(classes.root, styleStates, this.props.className), ...filterDataProps(this.props) },
showFirstLastNavButtons && this.renderNavButton("first" /* ButtonType.First */),
showPreviousLabel
? this.renderNavButton("previous" /* ButtonType.Prev */)
: this.renderEmptyButton("previous" /* ButtonType.Prev */),
this.renderPages(),
showNextLabel
? this.renderNavButton("next" /* ButtonType.Next */)
: this.renderEmptyButton("next" /* ButtonType.Next */),
showFirstLastNavButtons && this.renderNavButton("last" /* ButtonType.Last */)));
}
}
PaginationCore.displayName = 'PaginationCore';
PaginationCore.defaultProps = {
currentPage: 1,
showFirstLastNavButtons: false,
showFirstPage: false,
showLastPage: false,
showNextLabel: true,
showPreviousLabel: true,
responsive: false,
paginationMode: 'pages',
showInputModeTotalPages: false,
disabled: false,
// dir="rtl" automatically flips the direction of less-than and more-than signs.
// If we decide to use different labels we need to add conditional logic.
firstLabel: '<<',
lastLabel: '>>',
previousLabel: '<',
nextLabel: '>',
gapLabel: '...',
slashLabel: '\u00A0/\u00A0',
};
export default PaginationCore;
//# sourceMappingURL=PaginationCore.js.map