| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 | import React from 'react'import clsx from 'clsx'import usePagination from './hook'import type {  ButtonProps,  IPagination,  IPaginationProps,  PageButtonProps,} from './type'const defaultState: IPagination = {  currentPage: 0,  setCurrentPage: () => {},  truncableText: '...',  truncableClassName: '',  pages: [],  hasPreviousPage: false,  hasNextPage: false,  previousPages: [],  isPreviousTruncable: false,  middlePages: [],  isNextTruncable: false,  nextPages: [],}const PaginationContext: React.Context<IPagination> = React.createContext<IPagination>(defaultState)export const PrevButton = ({  className,  children,  dataTestId,  as = <button />,  ...buttonProps}: ButtonProps) => {  const pagination = React.useContext(PaginationContext)  const previous = () => {    if (pagination.currentPage + 1 > 1)      pagination.setCurrentPage(pagination.currentPage - 1)  }  const disabled = pagination.currentPage === 0  return (    <as.type      {...buttonProps}      {...as.props}      className={clsx(className, as.props.className)}      onClick={() => previous()}      tabIndex={disabled ? '-1' : 0}      disabled={disabled}      data-testid={dataTestId}      onKeyPress={(event: React.KeyboardEvent) => {        event.preventDefault()        if (event.key === 'Enter' && !disabled)          previous()      }}    >      {as.props.children ?? children}    </as.type>  )}export const NextButton = ({  className,  children,  dataTestId,  as = <button />,  ...buttonProps}: ButtonProps) => {  const pagination = React.useContext(PaginationContext)  const next = () => {    if (pagination.currentPage + 1 < pagination.pages.length)      pagination.setCurrentPage(pagination.currentPage + 1)  }  const disabled = pagination.currentPage === pagination.pages.length - 1  return (    <as.type      {...buttonProps}      {...as.props}      className={clsx(className, as.props.className)}      onClick={() => next()}      tabIndex={disabled ? '-1' : 0}      disabled={disabled}      data-testid={dataTestId}      onKeyPress={(event: React.KeyboardEvent) => {        event.preventDefault()        if (event.key === 'Enter' && !disabled)          next()      }}    >      {as.props.children ?? children}    </as.type>  )}type ITruncableElementProps = {  prev?: boolean}const TruncableElement = ({ prev }: ITruncableElementProps) => {  const pagination: IPagination = React.useContext(PaginationContext)  const {    isPreviousTruncable,    isNextTruncable,    truncableText,    truncableClassName,  } = pagination  return ((isPreviousTruncable && prev === true) || (isNextTruncable && !prev))    ? (      <li className={truncableClassName || undefined}>{truncableText}</li>    )    : null}export const PageButton = ({  as = <a />,  className,  dataTestIdActive,  dataTestIdInactive,  activeClassName,  inactiveClassName,  renderExtraProps,}: PageButtonProps) => {  const pagination: IPagination = React.useContext(PaginationContext)  const renderPageButton = (page: number) => (    <li key={page}>      <as.type        data-testid={          clsx({            [`${dataTestIdActive}`]:              dataTestIdActive && pagination.currentPage + 1 === page,            [`${dataTestIdInactive}-${page}`]:              dataTestIdActive && pagination.currentPage + 1 !== page,          }) || undefined        }        tabIndex={0}        onKeyPress={(event: React.KeyboardEvent) => {          if (event.key === 'Enter')            pagination.setCurrentPage(page - 1)        }}        onClick={() => pagination.setCurrentPage(page - 1)}        className={clsx(          className,          pagination.currentPage + 1 === page            ? activeClassName            : inactiveClassName,        )}        {...as.props}        {...(renderExtraProps ? renderExtraProps(page) : {})}      >        {page}      </as.type>    </li>  )  return (    <>      {pagination.previousPages.map(renderPageButton)}      <TruncableElement prev />      {pagination.middlePages.map(renderPageButton)}      <TruncableElement />      {pagination.nextPages.map(renderPageButton)}    </>  )}export const Pagination = ({  dataTestId,  ...paginationProps}: IPaginationProps & { dataTestId?: string }) => {  const pagination = usePagination(paginationProps)  return (    <PaginationContext.Provider value={pagination}>      <div className={paginationProps.className} data-testid={dataTestId}>        {paginationProps.children}      </div>    </PaginationContext.Provider>  )}Pagination.PrevButton = PrevButtonPagination.NextButton = NextButtonPagination.PageButton = PageButton
 |