Skip to content

Instantly share code, notes, and snippets.

@anymaniax
Created June 11, 2019 12:00
Show Gist options
  • Save anymaniax/c1aa3d66ca629112fa0c43a863290d07 to your computer and use it in GitHub Desktop.
Save anymaniax/c1aa3d66ca629112fa0c43a863290d07 to your computer and use it in GitHub Desktop.
import React, {Fragment} from 'react'
import PropTypes from 'prop-types'
import {range} from 'ramda'
import styled from 'styled-components'
import {FromLeftToCenter} from '../../styled/Text.style'
import {colors} from '../../../styles/colors'
import {fontSize} from '../../../styles/mixins'
const DEFAULT_MAX_PAGINATION = 5
const ButtonText = styled.button`
background: none;
${fontSize(14)};
color: ${props => (props.available ? colors.grey100 : colors.grey40)};
padding: ${props =>
props.Left ? '0 16px 0 0 ' : props.Right ? '0 0 0 16px' : '0'};
pointer-events: ${props => (props.available ? 'auto' : 'none')};
`
const PaginationBox = styled.div`
margin-top: 24px;
display: inline-block;
box-shadow: 0 2px 4px 0 rgba(18, 19, 18, 0.09);
background: white;
padding: 2px 5px 4px 5px;
border-radius: 20px;
`
const PaginationButton = styled.button`
margin: 1px 1px;
border-radius: 50%;
color: ${props => (props.isActive ? colors.white : colors.grey90)};
${fontSize(16)};
background: ${props => (props.isActive ? colors.blue20 : 'none')};
padding: 4px ${props => (props.number > 9 ? '7.03' : '11.5')}px;
&:first-of-type {
margin: 1px 1px 1px 0;
}
&:last-of-type {
margin: 1px 0 1px 1px;
}
`
const PaginationContainer = styled.div`
width: ${props =>
props.width && Number.isInteger(props.width) ? props.width : 100}%;
margin: 0 auto 64px auto;
`
const getRange = (selectedPage, pages) => {
const maxPagination = DEFAULT_MAX_PAGINATION
const total = pages + 1
const halfOfMax = Math.floor(maxPagination / 2)
if (pages <= maxPagination) {
return range(1, total)
} else {
if (selectedPage <= halfOfMax) {
return range(1, maxPagination + 1)
} else if (selectedPage + halfOfMax >= pages) {
return range(total - maxPagination, total)
} else {
return range(selectedPage - halfOfMax, selectedPage + halfOfMax + 1)
}
}
}
const propTypes = {
pages: PropTypes.number,
selectedPage: PropTypes.number,
setPage: PropTypes.func.isRequired,
width: PropTypes.number,
}
export const Pagination = ({pages, selectedPage, setPage, width}) =>
pages > 1 ? (
<PaginationContainer width={width}>
<FromLeftToCenter paddingBottom={64} paddingBottomMobile={32}>
<Fragment>
<ButtonText
available={selectedPage > 1}
Left
onClick={() => setPage(1)}
>
First
</ButtonText>
<ButtonText
available={selectedPage > 1}
Left
onClick={() => setPage(selectedPage - 1)}
>
Previous
</ButtonText>
</Fragment>
<PaginationBox>
{getRange(selectedPage, pages).map(number => (
<PaginationButton
key={number}
number={number}
onClick={() => setPage(number)}
isActive={number === selectedPage}
>
{number}
</PaginationButton>
))}
</PaginationBox>
<Fragment>
<ButtonText
available={selectedPage < pages}
Right
onClick={() => setPage(selectedPage + 1)}
>
Next
</ButtonText>
<ButtonText
available={selectedPage < pages}
Right
onClick={() => setPage(pages)}
>
Last
</ButtonText>
</Fragment>
</FromLeftToCenter>
</PaginationContainer>
) : null
Pagination.propTypes = propTypes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment