UNPKG

@hypothesis/frontend-shared

Version:

Shared components, styles and utilities for Hypothesis projects

162 lines 5.82 kB
var _jsxFileName = "/home/runner/work/frontend-shared/frontend-shared/src/components/navigation/Pagination.tsx"; import classnames from 'classnames'; import { paginationItems } from '../../util/pagination'; import { ArrowLeftIcon, ArrowRightIcon } from '../icons'; import Button from '../input/Button'; import { jsxDEV as _jsxDEV } from "preact/jsx-dev-runtime"; function NavigationButton({ children, invisible = false, pressed = false, onClick, title }) { return _jsxDEV(Button, { classes: classnames('px-3.5 py-2.5 gap-x-1', 'font-semibold rounded', // These colors are the same as the "dark" variant of IconButton 'text-grey-7 enabled:hover:text-grey-9 enabled:hover:bg-grey-3', 'disabled:text-grey-5 aria-pressed:bg-grey-3 aria-expanded:bg-grey-3', // Disabled navigation buttons are rendered as invisible and disabled // rather than removed so that the overall width of the component and // positions of child controls doesn't change too much when navigating // between pages. invisible && 'invisible'), disabled: invisible, onClick: onClick, pressed: pressed, size: "custom", title: title, variant: "custom", children: children }, void 0, false, { fileName: _jsxFileName, lineNumber: 24, columnNumber: 5 }, this); } /** * Render controls for navigating between pages in a paginated list of items. * * Buttons corresponding to nearby pages are shown on wider screens; for narrow * screens only Prev and Next buttons are shown. */ export default function Pagination({ currentPage, onChangePage, totalPages }) { // Pages are 1-indexed const hasNextPage = currentPage < totalPages; const hasPreviousPage = currentPage > 1; const pageNumbers = paginationItems(currentPage, totalPages); const changePageTo = (pageNumber, element) => { onChangePage(pageNumber); // Because changing pagination page doesn't reload the page (as it would // in a "traditional" HTML context), the clicked-upon navigation button // will awkwardly retain focus unless it is actively removed. // TODO: Evaluate this for a11y issues element.blur(); }; return _jsxDEV("div", { className: "flex items-center text-md select-none", "data-testid": "pagination-navigation", children: [_jsxDEV("div", { className: "mr-2", children: _jsxDEV(NavigationButton, { invisible: !hasPreviousPage, title: "Go to previous page", onClick: e => changePageTo(currentPage - 1, e.target), children: [_jsxDEV(ArrowLeftIcon, {}, void 0, false, { fileName: _jsxFileName, lineNumber: 100, columnNumber: 11 }, this), "prev"] }, void 0, true, { fileName: _jsxFileName, lineNumber: 95, columnNumber: 9 }, this) }, void 0, false, { fileName: _jsxFileName, lineNumber: 94, columnNumber: 7 }, this), _jsxDEV("ul", { className: classnames( // Where there's enough horizontal space, // lay out page navigation buttons horizontally between prev/next: // | prevPage | numberedPages | nextPage // // e.g. // | [<- prev] | [2] ... [5] [6] [7] ... [10] | [next ->] | // // These page buttons are hidden on narrow screens 'hidden', // For slightly wider screens, they are shown in a horizontal row 'md:flex md:items-center md:justify-center md:gap-x-2', // when visible, this element should stretch to fill available space 'md:grow'), children: pageNumbers.map((page, idx) => _jsxDEV("li", { children: page === null ? // Indicator for elided pages. Should be approximately the same // width as a small page number. This reduces the variation of // the component's width as the current page is advanced. // // Navigation buttons have `px-3.5`. This uses `px-3` since // an ellipsis is slightly wider than a digit. _jsxDEV("div", { className: "px-3 text-center", "data-testid": "pagination-gap", children: "\u2026" }, void 0, false, { fileName: _jsxFileName, lineNumber: 130, columnNumber: 15 }, this) : _jsxDEV(NavigationButton, { title: `Go to page ${page}`, pressed: page === currentPage, onClick: e => changePageTo(page, e.target), children: page.toString() }, `page-${idx}`, false, { fileName: _jsxFileName, lineNumber: 134, columnNumber: 15 }, this) }, idx, false, { fileName: _jsxFileName, lineNumber: 122, columnNumber: 11 }, this)) }, void 0, false, { fileName: _jsxFileName, lineNumber: 104, columnNumber: 7 }, this), _jsxDEV("div", { className: classnames('ml-2 flex justify-end', // When page buttons are not shown, this element should grow to fill // available space. But when page buttons are shown, it should not. 'grow md:grow-0'), children: _jsxDEV(NavigationButton, { invisible: !hasNextPage, title: "Go to next page", onClick: e => changePageTo(currentPage + 1, e.target), children: ["next", _jsxDEV(ArrowRightIcon, {}, void 0, false, { fileName: _jsxFileName, lineNumber: 160, columnNumber: 11 }, this)] }, void 0, true, { fileName: _jsxFileName, lineNumber: 154, columnNumber: 9 }, this) }, void 0, false, { fileName: _jsxFileName, lineNumber: 146, columnNumber: 7 }, this)] }, void 0, true, { fileName: _jsxFileName, lineNumber: 90, columnNumber: 5 }, this); } //# sourceMappingURL=Pagination.js.map