UNPKG

lucid-ui

Version:

A UI component library from AppNexus.

136 lines (135 loc) 6.33 kB
import _ from 'lodash'; import React from 'react'; import PropTypes from 'react-peek/prop-types'; import { lucidClassNames } from '../../util/style-helpers'; import * as reducers from './Paginator.reducers'; import selectors from './Paginator.selectors'; import { SingleSelectDumb as SingleSelect, } from '../SingleSelect/SingleSelect'; import TextField from '../TextField/TextField'; import { Button } from '../Button/Button'; import ArrowIcon from '../Icon/ArrowIcon/ArrowIcon'; import { buildModernHybridComponent } from '../../util/state-management'; const cx = lucidClassNames.bind('&-Paginator'); const { arrayOf, bool, func, number, object, oneOfType, shape, string, } = PropTypes; const { Option } = SingleSelect; const defaultProps = { hasPageSizeSelector: false, isDisabled: false, objectLabel: 'Object', onPageSelect: _.noop, selectedPageIndex: 0, selectedPageSizeIndex: 0, showTotalObjects: false, totalCount: null, totalPages: undefined, pageSizeOptions: [10, 50, 100], SingleSelect: { ...SingleSelect.defaultProps, selectedIndex: 0, }, TextField: TextField.defaultProps, }; class Paginator extends React.Component { constructor() { super(...arguments); this.handleTextFieldChange = (pageNum, { props, event, }) => { const { onPageSelect, selectedPageIndex, totalPages } = this.props; const parsedPageNum = _.parseInt(pageNum); if (_.isNaN(parsedPageNum)) { return onPageSelect(selectedPageIndex, totalPages, { props, event }); } return onPageSelect(parsedPageNum - 1, totalPages, { props, event }); }; } render() { const { className, hasPageSizeSelector, isDisabled, objectLabel, objectLabelPlural, onPageSelect, onPageSizeSelect, pageSizeOptions, selectedPageIndex, selectedPageSizeIndex, showTotalObjects, totalPages, totalCount, style, SingleSelect: singleSelectProps, TextField: textFieldProps, } = this.props; return (React.createElement("div", { style: style, className: cx('&', className) }, showTotalObjects && _.isNumber(totalCount) && (React.createElement("div", { className: cx('&-total-count') }, _.isFunction(showTotalObjects) ? showTotalObjects(totalCount) : totalCount.toLocaleString(), ' ', totalCount === 1 ? objectLabel : objectLabelPlural || `${objectLabel}s`)), hasPageSizeSelector ? (React.createElement("div", { className: cx('&-page-size-container') }, React.createElement("span", { className: cx('&-rows-per-page-label') }, "Rows per page:"), React.createElement(SingleSelect, Object.assign({}, singleSelectProps, { hasReset: false, isInvisible: true, isSelectionHighlighted: false, isDisabled: isDisabled, selectedIndex: selectedPageSizeIndex, onSelect: onPageSizeSelect }), _.map(pageSizeOptions, option => (React.createElement(Option, { key: option }, option)))))) : null, React.createElement(Button, { onClick: _.partial(onPageSelect, selectedPageIndex - 1, totalPages), isDisabled: isDisabled || selectedPageIndex === 0, kind: 'invisible', hasOnlyIcon: true }, React.createElement(ArrowIcon, { direction: 'left' })), React.createElement(TextField, Object.assign({ lazyLevel: 100 }, textFieldProps, { onBlur: this.handleTextFieldChange, onSubmit: this.handleTextFieldChange, isDisabled: isDisabled, value: selectedPageIndex + 1 })), !_.isNil(totalPages) && React.createElement("span", null, "of ", totalPages.toLocaleString()), React.createElement(Button, { kind: 'invisible', onClick: _.partial(onPageSelect, selectedPageIndex + 1, totalPages), isDisabled: isDisabled || selectedPageIndex === totalPages - 1, hasOnlyIcon: true }, React.createElement(ArrowIcon, { direction: 'right' })))); } } Paginator.displayName = 'Paginator'; Paginator.peek = { description: ` A paginator that has an optional page size selector. `, categories: ['navigation'], madeFrom: ['ArrowIcon', 'TextField', 'Button', 'SingleSelect'], }; Paginator.reducers = reducers; Paginator.selectors = selectors; Paginator.defaultProps = defaultProps; Paginator.propTypes = { className: string ` Appended to the component-specific class names set on the root elements. `, style: object ` Styles that are passed through to root element. `, isDisabled: bool ` Disables the Paginator from being clicked or focused. `, hasPageSizeSelector: bool ` Whether to show the page size selector. `, selectedPageIndex: number ` 0-indexed currently selected page number. `, selectedPageSizeIndex: number ` Currently selected page size option index. `, SingleSelect: shape(SingleSelect.propTypes) ` Object of SingleSelect props which are passed thru to the underlying SingleSelect component for the page size selector. `, showTotalObjects: oneOfType([bool, func]) ` Show total count of objects. `, objectLabel: string ` Label when showTotalObjects is true with 1 or fewer objects. `, objectLabelPlural: string ` Label when showTotalObjects is true with more than 1 objects. `, totalPages: number ` Number to display in \`of \${totalPages}\`, calculated from \`totalPages\` and selected page size by default. `, totalCount: number ` Total number of items across all pages. `, pageSizeOptions: arrayOf(number) ` Array of numbers representing page size options. `, TextField: shape(TextField.propTypes) ` Object of TextField props which are passed thru to the underlying TextField component. `, onPageSelect: func ` Called when a page is selected. Has the signature \`(pageIndex, totalPages, {props, event}) => {}\` where pageIndex is a number. `, onPageSizeSelect: func ` Called when a page size is selected. Has the signature \`(pageSizeIndex, {props, event}) => {}\` where pageSizeIndex is a number. `, }; export default buildModernHybridComponent(Paginator, { reducers, selectors }); export { Paginator as PaginatorDumb };