-
Notifications
You must be signed in to change notification settings - Fork 3
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 #31 from cobaltinc/park/PRE-1707
Pagination 컴포넌트 추가
- Loading branch information
Showing
8 changed files
with
317 additions
and
0 deletions.
There are no files selected for viewing
18 changes: 18 additions & 0 deletions
18
packages/co-design-core/src/components/Pagination/Bullet.tsx
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,18 @@ | ||
import React from 'react'; | ||
|
||
interface BulletProps { | ||
className?: string; | ||
circleClassName?: string; | ||
} | ||
|
||
const Bullet = ({ circleClassName, ...props }: BulletProps) => { | ||
return ( | ||
<div {...props}> | ||
{[0, 1, 2].map((_, index) => ( | ||
<div key={index} className={circleClassName} /> | ||
))} | ||
</div> | ||
); | ||
}; | ||
|
||
export default Bullet; |
74 changes: 74 additions & 0 deletions
74
packages/co-design-core/src/components/Pagination/Pagination.style.ts
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,74 @@ | ||
import { createStyles } from '@co-design/styles'; | ||
|
||
export default createStyles((theme) => ({ | ||
root: { | ||
display: 'inline-flex', | ||
alignItems: 'center', | ||
}, | ||
page: { | ||
display: 'inline-block', | ||
minWidth: '32px', | ||
height: '32px', | ||
padding: '7px 11.5px', | ||
textAlign: 'center', | ||
fontSize: '14px', | ||
lineHeight: '20px', | ||
verticalAlign: 'middle', | ||
color: '#171b24', | ||
boxSizing: 'border-box', | ||
marginRight: '8px', | ||
cursor: 'pointer', | ||
'@media (max-width: 500px)': { | ||
minWidth: '24px', | ||
height: '24px', | ||
padding: '2px 4px', | ||
}, | ||
'&:last-of-type': { | ||
marginRight: '0px', | ||
}, | ||
'&:hover': { | ||
backgroundColor: 'rgba(35, 40, 48, 0.12)', | ||
}, | ||
}, | ||
active: { | ||
backgroundColor: theme.palettes.gray[9], | ||
color: 'white', | ||
'&:hover': { | ||
backgroundColor: theme.palettes.gray[9], | ||
}, | ||
}, | ||
arrow: { | ||
display: 'inline-block', | ||
width: '32px', | ||
height: '32px', | ||
verticalAlign: 'middle', | ||
'&:first-of-type': { | ||
marginRight: '8px', | ||
}, | ||
'&:last-of-type': { | ||
marginLeft: '8px', | ||
}, | ||
}, | ||
disabled: { | ||
pointerEvents: 'none', | ||
cursor: 'not-allowed', | ||
}, | ||
bullet: { | ||
marginRight: '4px', | ||
'@media (max-width: 500px)': { | ||
width: '24px', | ||
height: '24px', | ||
}, | ||
}, | ||
circle: { | ||
display: 'inline-block', | ||
width: '3px', | ||
height: '3px', | ||
borderRadius: '50%', | ||
marginRight: '4px', | ||
backgroundColor: '#171b24', | ||
'&:last-of-type': { | ||
marginRight: '0px', | ||
}, | ||
}, | ||
})); |
146 changes: 146 additions & 0 deletions
146
packages/co-design-core/src/components/Pagination/Pagination.tsx
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,146 @@ | ||
import React, { useState } from 'react'; | ||
import { View } from '../View'; | ||
import { IconButton } from '../IconButton'; | ||
import ChevronLeft from './icons/ChevronLeft'; | ||
import ChevronRight from './icons/ChevronRight'; | ||
import useStyles from './Pagination.style'; | ||
import { ClassNames, CoComponentProps } from '@co-design/styles'; | ||
import Bullet from './Bullet'; | ||
|
||
export type PaginationStylesNames = ClassNames<typeof useStyles>; | ||
|
||
export interface PaginationProps extends CoComponentProps<PaginationStylesNames>, Omit<React.ComponentPropsWithoutRef<'div'>, 'onChange'> { | ||
/** Pagination 의 초기 Active Page 를 설정합니다. */ | ||
activePage?: number; | ||
|
||
/** Pagination 의 한 페이지당 보여줄 아이템의 개수를 설정합니다. */ | ||
itemsCountPerView?: number; | ||
|
||
/** Pagination 의 전체 아이템의 개수를 설정합니다. */ | ||
totalItemsCount: number; | ||
|
||
/** 첫 페이지를 유지하여 보여주고 선택할 수 있도록 설정합니다. */ | ||
showFirst?: boolean; | ||
|
||
/** 마지막 페이지를 유지하여 보여주고 선택할 수 있도록 설정합니다. */ | ||
showLast?: boolean; | ||
|
||
/** Pagination 의 페이지를 변경했을 때 발생할 이벤트를 설정합니다. */ | ||
onChange?(page: number): void; | ||
} | ||
|
||
export const Pagination = ({ | ||
activePage = 1, | ||
itemsCountPerView = 10, | ||
totalItemsCount, | ||
showFirst = true, | ||
showLast = true, | ||
onChange, | ||
className = '', | ||
style, | ||
co, | ||
overrideStyles, | ||
...props | ||
}: PaginationProps) => { | ||
const [currentPage, setCurrentPage] = useState(activePage); | ||
const { cx, classes } = useStyles(null, { | ||
overrideStyles, | ||
name: 'Pagination', | ||
}); | ||
|
||
const totalPage = Math.ceil(totalItemsCount / itemsCountPerView); | ||
let pages = []; | ||
|
||
if (totalPage <= 5) { | ||
pages = Array(totalPage) | ||
.fill(0) | ||
.map((_, index) => index + 1); | ||
} else if (currentPage < 3) { | ||
pages = [1, 2, 3, 4, 5]; | ||
} else if (totalPage - 2 < currentPage) { | ||
pages = [totalPage - 4, totalPage - 3, totalPage - 2, totalPage - 1, totalPage]; | ||
} else { | ||
pages = [currentPage - 2, currentPage - 1, currentPage, currentPage + 1, currentPage + 2]; | ||
} | ||
|
||
const handleChangePage = (page: number) => { | ||
onChange?.(page); | ||
setCurrentPage(page); | ||
}; | ||
|
||
const handlePrevPage = () => { | ||
if (currentPage > 1) { | ||
onChange?.(currentPage - 1); | ||
setCurrentPage(currentPage - 1); | ||
} | ||
}; | ||
|
||
const handleNextPage = () => { | ||
if (currentPage < totalPage) { | ||
onChange?.(currentPage + 1); | ||
setCurrentPage(currentPage + 1); | ||
} | ||
}; | ||
|
||
return ( | ||
<View className={classes.root} style={style} co={co} {...props}> | ||
<IconButton | ||
color="gray" | ||
variant="text" | ||
className={cx(classes.arrow, { [classes.disabled]: currentPage === 1 })} | ||
onClick={handlePrevPage} | ||
overrideStyles={{ | ||
text: { | ||
'&:not(:disabled):hover': { | ||
borderRadius: 0, | ||
}, | ||
}, | ||
}} | ||
> | ||
<ChevronLeft color={currentPage === 1 ? '#D5DADF' : '#171B24'} /> | ||
</IconButton> | ||
|
||
{currentPage > 3 && totalPage > pages.length && showFirst ? ( | ||
<> | ||
<div className={cx(classes.page, { [classes.active]: 1 === currentPage })} onClick={() => handleChangePage(1)}> | ||
1 | ||
</div> | ||
<Bullet className={classes.bullet} circleClassName={classes.circle} /> | ||
</> | ||
) : null} | ||
|
||
{pages.map((index) => ( | ||
<div className={cx(classes.page, { [classes.active]: index === currentPage })} key={index} onClick={() => handleChangePage(index)}> | ||
{index} | ||
</div> | ||
))} | ||
|
||
{totalPage - 2 > currentPage && totalPage > pages.length && showLast ? ( | ||
<> | ||
<Bullet className={classes.bullet} circleClassName={classes.circle} /> | ||
<div className={cx(classes.page, { [classes.active]: totalPage === currentPage })} onClick={() => handleChangePage(totalPage)}> | ||
{totalPage} | ||
</div> | ||
</> | ||
) : null} | ||
|
||
<IconButton | ||
color="gray" | ||
variant="text" | ||
className={cx(classes.arrow, { [classes.disabled]: currentPage === totalPage })} | ||
onClick={handleNextPage} | ||
overrideStyles={{ | ||
text: { | ||
'&:not(:disabled):hover': { | ||
borderRadius: 0, | ||
}, | ||
}, | ||
}} | ||
> | ||
<ChevronRight color={currentPage === totalPage ? '#D5DADF' : '#171B24'} /> | ||
</IconButton> | ||
</View> | ||
); | ||
}; | ||
|
||
Pagination.displayName = '@co-design/core/Pagination'; |
9 changes: 9 additions & 0 deletions
9
packages/co-design-core/src/components/Pagination/icons/ChevronLeft.tsx
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,9 @@ | ||
import React, { SVGProps } from 'react'; | ||
|
||
const ChevronLeft = (props: SVGProps<SVGSVGElement>) => ( | ||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}> | ||
<path fillRule="evenodd" clipRule="evenodd" d="M15.41 16.59L10.83 12L15.41 7.41L14 6L8 12L14 18L15.41 16.59Z" fill="#5D636D" /> | ||
</svg> | ||
); | ||
|
||
export default ChevronLeft; |
14 changes: 14 additions & 0 deletions
14
packages/co-design-core/src/components/Pagination/icons/ChevronRight.tsx
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,14 @@ | ||
import React, { SVGProps } from 'react'; | ||
|
||
const ChevronRight = (props: SVGProps<SVGSVGElement>) => ( | ||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}> | ||
<path | ||
fillRule="evenodd" | ||
clipRule="evenodd" | ||
d="M8.58984 16.59L13.1698 12L8.58984 7.41L9.99984 6L15.9998 12L9.99984 18L8.58984 16.59Z" | ||
fill="#5D636D" | ||
/> | ||
</svg> | ||
); | ||
|
||
export default ChevronRight; |
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,2 @@ | ||
export { Pagination } from './Pagination'; | ||
export type { PaginationProps } from './Pagination'; |
53 changes: 53 additions & 0 deletions
53
packages/co-design-core/src/components/Pagination/stories/Pagination.stories.tsx
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,53 @@ | ||
import React from 'react'; | ||
import { Pagination } from '../Pagination'; | ||
import { Meta, StoryObj } from '@storybook/react'; | ||
|
||
type Story = StoryObj<typeof Pagination>; | ||
|
||
export default { | ||
title: '@co-design/core/Pagination', | ||
component: Pagination, | ||
argTypes: { | ||
activePage: { | ||
control: { | ||
type: 'number', | ||
}, | ||
}, | ||
itemsCountPerView: { | ||
control: { | ||
type: 'number', | ||
}, | ||
}, | ||
totalItemsCount: { | ||
control: { | ||
type: 'number', | ||
}, | ||
}, | ||
showFirst: { | ||
control: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
showLast: { | ||
control: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
}, | ||
args: { | ||
activePage: 1, | ||
itemsCountPerView: 10, | ||
totalItemsCount: 120, | ||
showFirst: true, | ||
showLast: true, | ||
}, | ||
} as Meta<typeof Pagination>; | ||
|
||
export const Default: Story = {}; | ||
|
||
export const NoShowBullet: Story = { | ||
args: { | ||
showFirst: false, | ||
showLast: false, | ||
}, | ||
}; |
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