Skip to content

Instantly share code, notes, and snippets.

@talum
Last active October 28, 2019 15:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save talum/8d0df3c3fb0d91edf161943f65d9ef6c to your computer and use it in GitHub Desktop.
Save talum/8d0df3c3fb0d91edf161943f65d9ef6c to your computer and use it in GitHub Desktop.
pagination
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import Button from 'lib/shared-react-components/buttons/Button'
export default class Ellipsis extends PureComponent {
render () {
if (!this.props.visible) return null
return (
<Button
classes='button button--color-blue-inverted button--corners-tight
button--height-small button--width-xxsmall'
disabled
label='...'
/>
)
}
}
Ellipsis.defaultProps = {
visible: false
}
Ellipsis.propTypes = {
visible: PropTypes.bool
}
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import Button from 'lib/shared-react-components/buttons/Button'
export default class NextPage extends PureComponent {
clickHandler = () => {
const newPage = this.props.currentPage + 1
return this.props.handleClick(newPage)
}
render () {
const { currentPage, lastPage } = this.props
return (
<Button
classes='button button--color-blue-inverted button--corners-tight button--height-small'
disabled={currentPage === lastPage}
handleClick={this.clickHandler}
label='Next'
/>
)
}
}
NextPage.propTypes = {
handleClick: PropTypes.func.isRequired,
currentPage: PropTypes.number.isRequired,
lastPage: PropTypes.number.isRequired
}
import React, { Component } from 'react'
export default class NoPagination extends Component {
shouldComponentUpdate () { return false }
render () {
return (
<div className='module'>
<div className='flex-grid flex-grid--center-x'>
<div className='flex-grid__item'>
You&#39;ve reached the end of the list.
</div>
</div>
</div>
)
}
}
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Button from 'lib/shared-react-components/buttons/Button'
class PageNumber extends Component {
shouldComponentUpdate ({ active, lastPage }) {
return (
active !== this.props.active
|| lastPage !== this.props.lastPage
)
}
clickHandler = () => this.props.handleClick(this.props.pageNumber)
render () {
const { active, pageNumber } = this.props
return (
<Button
active={active}
classes={`button ${active ? 'button--color-blue' : 'button--color-blue-inverted'}
button--corners-tight button--height-small button--width-xxsmall`}
handleClick={this.clickHandler}
label={`${pageNumber}`}
/>
)
}
}
PageNumber.propTypes = {
active: PropTypes.bool.isRequired,
handleClick: PropTypes.func.isRequired,
lastPage: PropTypes.number.isRequired,
pageNumber: PropTypes.number.isRequired
}
export default PageNumber
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import Ellipsis from 'lib/shared-react-components/pagination/Ellipsis'
import NextPage from 'lib/shared-react-components/pagination/NextPage'
import NoPagination from 'lib/shared-react-components/pagination/NoPagination'
import PageNumber from 'lib/shared-react-components/pagination/PageNumber'
import PreviousPage from 'lib/shared-react-components/pagination/PreviousPage'
export default class Pagination extends PureComponent {
render () {
const { changePage, currentPage, lastPage } = this.props
if (!currentPage) return null
if (lastPage <= 1) return <NoPagination />
let middlePageNumbers
if (lastPage > 6) {
switch (true) {
case (currentPage - 1) < 3:
middlePageNumbers = [2, 3, 4]
break
case (lastPage - currentPage) < 3:
middlePageNumbers = [lastPage - 3, lastPage - 2, lastPage - 1]
break
default:
middlePageNumbers = [currentPage - 1, currentPage, currentPage + 1]
break
}
} else {
const pageRange = [...Array(lastPage).keys()]
middlePageNumbers = pageRange.slice(2)
}
return (
<div className='module module--margin-bottom-large'>
<div className='flex-grid flex-grid--center-x'>
<div className='flex-grid__item'>
<PreviousPage
currentPage={currentPage}
handleClick={changePage}
/>
</div>
<div className='flex-grid'>
<div className='flex-grid__item'>
<PageNumber
active={currentPage === 1}
handleClick={changePage}
pageNumber={1}
lastPage={lastPage}
/>
</div>
<div className='flex-grid__item'>
<Ellipsis visible={lastPage > 6 && currentPage > 3} />
</div>
{
middlePageNumbers.map(pageNumber => (
<div className='flex-grid__item' key={pageNumber}>
<PageNumber
active={currentPage === pageNumber}
handleClick={changePage}
pageNumber={pageNumber}
lastPage={lastPage}
/>
</div>
))
}
<div className='flex-grid__item'>
<Ellipsis visible={lastPage > 6 && (lastPage - currentPage) > 2} />
</div>
<div className='flex-grid__item'>
<PageNumber
active={currentPage === lastPage}
handleClick={changePage}
pageNumber={lastPage}
lastPage={lastPage}
/>
</div>
</div>
<div className='flex-grid__item'>
<NextPage
handleClick={changePage}
currentPage={currentPage}
lastPage={lastPage}
/>
</div>
</div>
</div>
)
}
}
Pagination.propTypes = {
changePage: PropTypes.func.isRequired,
currentPage: PropTypes.number.isRequired,
lastPage: PropTypes.number.isRequired
}
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Button from 'lib/shared-react-components/buttons/Button'
export default class PreviousPage extends Component {
shouldComponentUpdate ({ currentPage }) {
return currentPage !== this.props.currentPage
}
clickHandler = () => {
const newPage = this.props.currentPage - 1
return this.props.handleClick(newPage)
}
render () {
const { currentPage } = this.props
return (
<Button
classes='button button--color-blue-inverted button--corners-tight button--height-small'
disabled={currentPage === 1}
handleClick={this.clickHandler}
label='Prev'
/>
)
}
}
PreviousPage.propTypes = {
handleClick: PropTypes.func.isRequired,
currentPage: PropTypes.number.isRequired
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment