-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from toptal/picas-36-initial-components-pagina…
…tion Add Pagination component
- Loading branch information
Showing
10 changed files
with
523 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
export default { | ||
root: { | ||
display: 'inline-block', | ||
|
||
'& Button': { | ||
margin: '0', | ||
'&:first-child': { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* global alert */ | ||
|
||
import React from 'react' | ||
import { storiesOf } from '@storybook/react' | ||
|
||
import StoryTeller from '../../.storybook/StoryTeller' | ||
import Pagination from './' | ||
import Spacer from '../Spacer' | ||
|
||
const stories = storiesOf('Pagination', module) | ||
|
||
const teller = new StoryTeller( | ||
'Pagination', | ||
'Component which allows navigating long data lists' | ||
) | ||
const chapter = teller.addChapter() | ||
|
||
chapter | ||
.addSection('Pagination', 'variations', () => ( | ||
<div> | ||
<Pagination | ||
activePage={1} | ||
onPageChange={page => { | ||
alert('Page change...' + page) | ||
}} | ||
totalPages={10} | ||
/> | ||
<Spacer bottom={2} /> | ||
<Pagination | ||
activePage={9} | ||
onPageChange={page => { | ||
alert('Page change...' + page) | ||
}} | ||
totalPages={10} | ||
/> | ||
<Spacer bottom={2} /> | ||
<Pagination | ||
activePage={5} | ||
onPageChange={page => { | ||
alert('Page change...' + page) | ||
}} | ||
totalPages={10} | ||
/> | ||
<Spacer bottom={2} /> | ||
<Pagination | ||
activePage={10} | ||
onPageChange={page => { | ||
alert('Page change...' + page) | ||
}} | ||
totalPages={10} | ||
/> | ||
</div> | ||
)) | ||
.addSection('Pagination', 'disabled', () => ( | ||
<div> | ||
<Pagination | ||
activePage={1} | ||
disabled | ||
onPageChange={page => { | ||
alert('Page change...' + page) | ||
}} | ||
totalPages={10} | ||
/> | ||
</div> | ||
)) | ||
|
||
stories.addWithChapters('Pagination', teller.toStory()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
|
||
import Button from '../Button' | ||
import { getRange, ELLIPSIS, FIRST_PAGE, ONE_PAGE } from './range-utils' | ||
|
||
const NAVIGATION = { | ||
FIRST: 'FIRST', | ||
LAST: 'LAST', | ||
PREVIOUS: 'PREVIOUS', | ||
NEXT: 'NEXT' | ||
} | ||
const SIBLING_COUNT = 3 | ||
|
||
class Pagination extends React.PureComponent { | ||
static propTypes = { | ||
activePage: PropTypes.number.isRequired, | ||
disabled: PropTypes.bool, | ||
onPageChange: PropTypes.func.isRequired, | ||
totalPages: PropTypes.number.isRequired | ||
} | ||
|
||
static defaultProps = { | ||
disabled: false | ||
} | ||
|
||
handleChange (navigation) { | ||
const { onPageChange, totalPages, activePage } = this.props | ||
let page | ||
|
||
switch (navigation) { | ||
case NAVIGATION.FIRST: | ||
page = FIRST_PAGE | ||
break | ||
case NAVIGATION.PREVIOUS: | ||
page = activePage - ONE_PAGE | ||
break | ||
case NAVIGATION.NEXT: | ||
page = activePage + ONE_PAGE | ||
break | ||
case NAVIGATION.LAST: | ||
page = totalPages | ||
break | ||
default: | ||
page = navigation | ||
} | ||
|
||
onPageChange(page) | ||
} | ||
|
||
isFirstActive = activePage => activePage === 1 | ||
isLastActive = (activePage, totalPages) => activePage === totalPages | ||
|
||
renderRange () { | ||
const { totalPages, activePage, disabled } = this.props | ||
|
||
const range = getRange({ | ||
activePage, | ||
totalPages, | ||
siblingCount: SIBLING_COUNT | ||
}) | ||
|
||
return range.map((pageItemLabel, index) => { | ||
return ( | ||
<Button | ||
color={activePage === pageItemLabel ? 'primary' : undefined} | ||
disabled={pageItemLabel === ELLIPSIS || disabled} | ||
key={pageItemLabel + index} // eslint-disable-line react/no-array-index-key | ||
onClick={() => this.handleChange(pageItemLabel)} | ||
variant={activePage === pageItemLabel ? 'contained' : 'outlined'} | ||
> | ||
{pageItemLabel} | ||
</Button> | ||
) | ||
}) | ||
} | ||
|
||
render () { | ||
const { activePage, totalPages, disabled } = this.props | ||
const isFirstActive = this.isFirstActive(activePage) | ||
const isLastActive = this.isLastActive(activePage, totalPages) | ||
|
||
return ( | ||
<Button.Group> | ||
<Button | ||
color='default' | ||
disabled={isFirstActive || disabled} | ||
onClick={() => this.handleChange(NAVIGATION.FIRST)} | ||
variant='outlined' | ||
> | ||
« | ||
</Button> | ||
<Button | ||
color='default' | ||
disabled={isFirstActive || disabled} | ||
onClick={() => this.handleChange(NAVIGATION.PREVIOUS)} | ||
variant='outlined' | ||
> | ||
⟨ | ||
</Button> | ||
|
||
{this.renderRange()} | ||
|
||
<Button | ||
color='default' | ||
disabled={isLastActive || disabled} | ||
onClick={() => this.handleChange(NAVIGATION.NEXT)} | ||
variant='outlined' | ||
> | ||
⟩ | ||
</Button> | ||
<Button | ||
color='default' | ||
disabled={isLastActive || disabled} | ||
onClick={() => this.handleChange(NAVIGATION.LAST)} | ||
variant='outlined' | ||
> | ||
» | ||
</Button> | ||
</Button.Group> | ||
) | ||
} | ||
} | ||
|
||
export default Pagination |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`renders default 1`] = ` | ||
<div> | ||
<div | ||
class="ButtonGroup-root" | ||
> | ||
<button | ||
class="MuiButtonBase-root MuiButton-root Button-root MuiButton-outlined Button-outlined" | ||
tabindex="0" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
> | ||
« | ||
</div> | ||
</span> | ||
<span | ||
class="MuiTouchRipple-root" | ||
/> | ||
</button> | ||
<button | ||
class="MuiButtonBase-root MuiButton-root Button-root MuiButton-outlined Button-outlined" | ||
tabindex="0" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
> | ||
⟨ | ||
</div> | ||
</span> | ||
<span | ||
class="MuiTouchRipple-root" | ||
/> | ||
</button> | ||
<button | ||
class="MuiButtonBase-root MuiButton-root Button-containedPrimary Button-root MuiButton-contained Button-contained MuiButton-containedPrimary Button-containedPrimary MuiButton-raised MuiButton-raisedPrimary" | ||
tabindex="0" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
/> | ||
</span> | ||
<span | ||
class="MuiTouchRipple-root" | ||
/> | ||
</button> | ||
<button | ||
class="MuiButtonBase-root MuiButtonBase-disabled MuiButton-root Button-root MuiButton-outlined Button-outlined MuiButton-disabled" | ||
disabled="" | ||
tabindex="-1" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
> | ||
⟩ | ||
</div> | ||
</span> | ||
</button> | ||
<button | ||
class="MuiButtonBase-root MuiButtonBase-disabled MuiButton-root Button-root MuiButton-outlined Button-outlined MuiButton-disabled" | ||
disabled="" | ||
tabindex="-1" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
> | ||
» | ||
</div> | ||
</span> | ||
</button> | ||
</div> | ||
</div> | ||
`; | ||
|
||
exports[`renders disabled 1`] = ` | ||
<div> | ||
<div | ||
class="ButtonGroup-root" | ||
> | ||
<button | ||
class="MuiButtonBase-root MuiButton-root Button-root MuiButton-outlined Button-outlined" | ||
tabindex="0" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
> | ||
« | ||
</div> | ||
</span> | ||
<span | ||
class="MuiTouchRipple-root" | ||
/> | ||
</button> | ||
<button | ||
class="MuiButtonBase-root MuiButton-root Button-root MuiButton-outlined Button-outlined" | ||
tabindex="0" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
> | ||
⟨ | ||
</div> | ||
</span> | ||
<span | ||
class="MuiTouchRipple-root" | ||
/> | ||
</button> | ||
<button | ||
class="MuiButtonBase-root MuiButton-root Button-containedPrimary Button-root MuiButton-contained Button-contained MuiButton-containedPrimary Button-containedPrimary MuiButton-raised MuiButton-raisedPrimary" | ||
tabindex="0" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
/> | ||
</span> | ||
<span | ||
class="MuiTouchRipple-root" | ||
/> | ||
</button> | ||
<button | ||
class="MuiButtonBase-root MuiButtonBase-disabled MuiButton-root Button-root MuiButton-outlined Button-outlined MuiButton-disabled" | ||
disabled="" | ||
tabindex="-1" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
> | ||
⟩ | ||
</div> | ||
</span> | ||
</button> | ||
<button | ||
class="MuiButtonBase-root MuiButtonBase-disabled MuiButton-root Button-root MuiButton-outlined Button-outlined MuiButton-disabled" | ||
disabled="" | ||
tabindex="-1" | ||
type="button" | ||
> | ||
<span | ||
class="MuiButton-label" | ||
> | ||
<div | ||
class="Button-children" | ||
> | ||
» | ||
</div> | ||
</span> | ||
</button> | ||
</div> | ||
</div> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './Pagination' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { getRange, ELLIPSIS, FIRST_PAGE, ONE_PAGE } from './range-utils' |
Oops, something went wrong.