import JWPaginate from 'jw-paginate' import React from 'react' import { styled } from '@styled-components' import { Box, BoxProps } from '../../atoms/box/index.js' import { Button, ButtonProps } from '../../atoms/button/index.js' import { Icon } from '../../atoms/icon/index.js' import { cssClass } from '../../utils/css-class.js' const MIN_PAGES_FOR_FIRST_PAGE_BUTTON = 3 const FIRST_PAGE = 1 /** * @alias PaginationProps * @memberof Pagination */ export type PaginationProps = { /** * Current page */ page: number; /** * Items per page */ perPage: number; /** * Total number of items */ total: number; /** * location. You can pass window.location or the location object * given by ReactRouter */ location?: Location; /** * Triggers when user clicks any of the button */ onChange: (pageNumber: number) => void; } const PaginationButton = (props: ButtonProps) => ({ size: 'icon' as const, variant: props.variant || 'text' as const }) // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore const PaginationLink: any = styled(Button).attrs(PaginationButton)` min-width: 28px; height: 28px; line-height: 12px; padding: 3px 6px; text-align: center; ` PaginationLink.defaultProps = { className: cssClass('PaginationLink'), } const PaginationWrapper = styled(Box)` display: inline-block; padding: 2px; border: 1px solid ${({ theme }) => theme.colors.border}; & > :hover { text-decoration: none; } & > :first-child { border-right: 1px solid ${({ theme }) => theme.colors.border}; } & > :last-child { border-left: 1px solid ${({ theme }) => theme.colors.border}; } ` /** * @classdesc * * * * Pagination component * * ### Usage * * ```javascript * import { Pagination, PaginationProps } from '@adminjs/design-system' * ``` * * @component * @subcategory Molecules * @hideconstructor * @see PaginationProps * @see {@link https://storybook.adminjs.co/?path=/story/designsystem-molecules-pagination--default Storybook} * @example * const location = { search: ''} * return ( * * alert(`clicked ${item}`)} * /> * * ) * @section design-system */ const Pagination: React.FC = (props) => { const { total, page, perPage, onChange, ...rest } = props const currentPage = page || FIRST_PAGE const paginate = JWPaginate(total, currentPage, perPage) const isFirstPage = currentPage === paginate.startPage const isLastPage = currentPage === paginate.endPage const prevPage = isFirstPage ? currentPage : currentPage - 1 const nextPage = isLastPage ? currentPage : currentPage + 1 if (paginate.totalPages === FIRST_PAGE || total === 0) { return null } return ( { total >= MIN_PAGES_FOR_FIRST_PAGE_BUTTON ? ( (!isFirstPage ? onChange(FIRST_PAGE) : undefined)} > ) : null } (!isFirstPage ? onChange(prevPage) : undefined)} > {paginate.pages.map((p) => ( onChange(p)} variant={p === currentPage ? 'contained' : 'text'} className={cssClass('PaginationLink', p === currentPage ? 'current' : '')} data-testid={`page-${p}`} > {p} ))} (!isLastPage ? onChange(nextPage) : undefined)} > { total >= MIN_PAGES_FOR_FIRST_PAGE_BUTTON ? ( (!isLastPage ? onChange(paginate.totalPages) : undefined)} > ) : null } ) } Pagination.displayName = 'Pagination' export { Pagination } export default Pagination