import { ColorStyle } from '@repay/cactus-theme' import PropTypes from 'prop-types' import React, { ReactElement, useContext } from 'react' import styled from 'styled-components' import { margin, MarginProps } from 'styled-system' import { keyDownAsClick } from '../helpers/a11y' import { border, fontSize } from '../helpers/theme' import { DataGridContext } from './helpers' export interface PageSizeSelectProps extends MarginProps { pageSize?: number initialPageSize?: number makePageSizeLabel?: (pageSize: number) => string pageSizeSelectLabel?: React.ReactChild pageSizeOptions: number[] } const defaultPageSizeLabel = (pageSize: number): string => `View ${pageSize} rows per page` const PageSizeSelect = (props: PageSizeSelectProps): ReactElement => { const { pageState, updatePageState } = useContext(DataGridContext) const { pageSizeSelectLabel, pageSizeOptions, makePageSizeLabel = defaultPageSizeLabel, initialPageSize = 1, pageSize: currentPageSize = pageState.pageSize || initialPageSize, ...rest } = props React.useEffect(() => { updatePageState({ pageSize: currentPageSize }) }, [currentPageSize]) // eslint-disable-line react-hooks/exhaustive-deps return ( {pageSizeSelectLabel || 'View'}
    {pageSizeOptions?.map((pageSize): ReactElement => { const isCurrentPageSize = currentPageSize === pageSize return (
  1. updatePageState({ pageSize }, true)} onKeyDown={keyDownAsClick} tabIndex={isCurrentPageSize ? undefined : 0} aria-label={makePageSizeLabel(pageSize)} > {pageSize}
  2. ) })}
) } const StyledPageSizeSelect = styled.div` display: inline-box; ${margin} span { margin-right: 8px; } .page-options-list { display: inline-flex; flex-wrap: nowrap; list-style: none; margin: 0; padding: 0; } .page-option { min-width: 15px; height: 24px; text-align: center; background: none; appearance: none; padding: 2px 8px; display: block; border-left: ${(p): string => border(p.theme, 'lightContrast')}; &:last-child { border-right: ${(p): string => border(p.theme, 'lightContrast')}; } &, a { color: ${(p): string => p.theme.colors.darkestContrast}; ${(p): string => fontSize(p.theme, 'small')}; line-height: 18px; text-decoration: none; } a { cursor: pointer; padding: 3px; vertical-align: middle; line-height: 18px; display: block; border-radius: 8px; text-decoration: none; color: inherit; &:hover { color: ${(p): string => p.theme.colors.callToAction}; } &:active, &:focus { // Re-stated to prevent a small shift when the button is clicked in Firefox padding: 3px; outline: none; ${(p): ColorStyle => p.theme.colorStyles.callToAction}; } &[aria-selected='true'] { ${(p): ColorStyle => p.theme.colorStyles.base}; } } } ` PageSizeSelect.defaultProps = { makePageSizeLabel: defaultPageSizeLabel, } PageSizeSelect.propTypes = { makePageSizeLabel: PropTypes.func, pageSizeSelectLabel: PropTypes.node, pageSizeOptions: PropTypes.arrayOf(PropTypes.number), } PageSizeSelect.displayName = 'PageSizeSelect' export default PageSizeSelect