@grafana/ui
Version:
Grafana Components Library
1 lines • 9.99 kB
Source Map (JSON)
{"version":3,"file":"Pagination.mjs","sources":["../../../../src/components/Pagination/Pagination.tsx"],"sourcesContent":["import { css, cx } from '@emotion/css';\nimport { useMemo, type JSX } from 'react';\n\nimport { t } from '@grafana/i18n';\n\nimport { useStyles2 } from '../../themes/ThemeContext';\nimport { Button } from '../Button/Button';\nimport { Icon } from '../Icon/Icon';\n\nexport interface Props {\n /** The current page index being shown. */\n currentPage: number;\n /** Number of total pages. */\n numberOfPages: number;\n /** Callback function for fetching the selected page. */\n onNavigate: (toPage: number) => void;\n /** When set to true and the pagination result is only one page it will not render the pagination at all. */\n hideWhenSinglePage?: boolean;\n /** Small version only shows the current page and the navigation buttons. */\n showSmallVersion?: boolean;\n className?: string;\n /** If we are using cursor based pagination, disable next page button when we have no cursor */\n hasNextPage?: boolean;\n}\n\n/**\n * Component used for rendering a page selector below paginated content.\n *\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/navigation-pagination--docs\n */\nexport const Pagination = ({\n currentPage,\n numberOfPages,\n onNavigate,\n hideWhenSinglePage,\n showSmallVersion,\n className,\n hasNextPage,\n}: Props) => {\n const styles = useStyles2(getStyles);\n const pageLengthToCondense = showSmallVersion ? 1 : 8;\n\n const pageButtons = useMemo(() => {\n const pages = [...new Array(numberOfPages).keys()];\n\n const condensePages = numberOfPages > pageLengthToCondense;\n const getListItem = (page: number, isCurrentPage: boolean) => {\n const variant = isCurrentPage ? 'primary' : 'secondary';\n return (\n <li key={page} className={styles.item}>\n <Button\n aria-current={isCurrentPage ? 'page' : undefined}\n size=\"sm\"\n variant={variant}\n onClick={() => onNavigate(page)}\n >\n {page}\n </Button>\n </li>\n );\n };\n\n return pages.reduce<JSX.Element[]>((pagesToRender, pageIndex) => {\n const page = pageIndex + 1;\n const isCurrentPage = page === currentPage;\n\n // The indexes at which to start and stop condensing pages\n const lowerBoundIndex = pageLengthToCondense;\n const upperBoundIndex = numberOfPages - pageLengthToCondense + 1;\n // When the indexes overlap one another this number is negative\n const differenceOfBounds = upperBoundIndex - lowerBoundIndex;\n\n const isFirstOrLastPage = page === 1 || page === numberOfPages;\n // This handles when the lowerBoundIndex < currentPage < upperBoundIndex\n const currentPageIsBetweenBounds =\n differenceOfBounds > -1 && currentPage >= lowerBoundIndex && currentPage <= upperBoundIndex;\n\n // Show ellipsis after that many pages\n const ellipsisOffset = showSmallVersion ? 1 : 3;\n\n // The offset to show more pages when currentPageIsBetweenBounds\n const pageOffset = showSmallVersion ? 0 : 2;\n\n if (condensePages) {\n if (\n isFirstOrLastPage ||\n (currentPage < lowerBoundIndex && page < lowerBoundIndex) ||\n (differenceOfBounds >= 0 && currentPage > upperBoundIndex && page > upperBoundIndex) ||\n (differenceOfBounds < 0 && currentPage >= lowerBoundIndex && page > upperBoundIndex) ||\n (currentPageIsBetweenBounds && page >= currentPage - pageOffset && page <= currentPage + pageOffset)\n ) {\n // Renders a button for the page\n pagesToRender.push(getListItem(page, isCurrentPage));\n } else if (\n (page === lowerBoundIndex && currentPage < lowerBoundIndex) ||\n (page === upperBoundIndex && currentPage > upperBoundIndex) ||\n (currentPageIsBetweenBounds &&\n (page === currentPage - ellipsisOffset || page === currentPage + ellipsisOffset))\n ) {\n // Renders and ellipsis to represent condensed pages\n pagesToRender.push(\n <li key={page} className={styles.item}>\n <Icon className={styles.ellipsis} name=\"ellipsis-v\" data-testid=\"pagination-ellipsis-icon\" />\n </li>\n );\n }\n } else {\n pagesToRender.push(getListItem(page, isCurrentPage));\n }\n return pagesToRender;\n }, []);\n }, [currentPage, numberOfPages, onNavigate, pageLengthToCondense, showSmallVersion, styles.ellipsis, styles.item]);\n\n if (hideWhenSinglePage && numberOfPages <= 1) {\n return null;\n }\n\n const previousPageLabel = t('grafana-ui.pagination.previous-page', 'previous page');\n const nextPageLabel = t('grafana-ui.pagination.next-page', 'next page');\n\n return (\n <div className={cx(styles.container, className)} role=\"navigation\">\n <ol>\n <li className={styles.item}>\n <Button\n aria-label={previousPageLabel}\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => onNavigate(currentPage - 1)}\n disabled={currentPage === 1}\n >\n <Icon name=\"angle-left\" />\n </Button>\n </li>\n {pageButtons}\n {pageButtons.length === 0 && <li className={styles.item}>{currentPage}</li>}\n <li className={styles.item}>\n <Button\n aria-label={nextPageLabel}\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => onNavigate(currentPage + 1)}\n disabled={hasNextPage === false || currentPage === numberOfPages}\n >\n <Icon name=\"angle-right\" />\n </Button>\n </li>\n </ol>\n </div>\n );\n};\n\nconst getStyles = () => {\n return {\n container: css({\n float: 'right',\n }),\n item: css({\n display: 'inline-block',\n paddingLeft: '10px',\n marginBottom: '5px',\n }),\n ellipsis: css({\n transform: 'rotate(90deg)',\n }),\n };\n};\n"],"names":[],"mappings":"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"}