UNPKG

@equinor/eds-core-react

Version:

The React implementation of the Equinor Design System

152 lines (147 loc) 5.69 kB
import { forwardRef, useState } from 'react'; import styled from 'styled-components'; import { useIsMounted, useIsomorphicLayoutEffect } from '@equinor/eds-utils'; import { Button } from '../Button/index.js'; import { Icon } from '../Icon/index.js'; import { PaginationItem } from './PaginationItem.js'; import { pagination } from './Pagination.tokens.js'; import { chevron_left, chevron_right, more_horizontal } from '@equinor/eds-icons'; import { PaginationControl } from './paginationControl.js'; import { jsx, jsxs } from 'react/jsx-runtime'; import { Typography } from '../Typography/Typography.js'; const icons = { chevron_left, chevron_right, more_horizontal }; Icon.add(icons); const Navigation = styled.nav.withConfig({ displayName: "Pagination__Navigation", componentId: "sc-13cpp3o-0" })(["display:flex;justify-content:space-between;align-items:center;flex-wrap:nowrap;margin-left:", ";"], ({ $withItemIndicator }) => $withItemIndicator ? pagination.spacings.left : 0); const OrderedList = styled.ol.withConfig({ displayName: "Pagination__OrderedList", componentId: "sc-13cpp3o-1" })(["list-style:none;margin:0;padding:0;display:grid;grid-gap:", ";grid-auto-flow:column;"], pagination.spacings.left); const ListItem = styled.li.withConfig({ displayName: "Pagination__ListItem", componentId: "sc-13cpp3o-2" })(["display:inline-grid;"]); const StyledIcon = styled(Icon).withConfig({ displayName: "Pagination__StyledIcon", componentId: "sc-13cpp3o-3" })(["align-self:center;justify-self:center;fill:", ";"], pagination.entities.icon.typography.color); const FlexContainer = styled.div.withConfig({ displayName: "Pagination__FlexContainer", componentId: "sc-13cpp3o-4" })(["display:flex;justify-content:space-between;flex-wrap:nowrap;align-items:center;"]); const Text = styled(Typography).withConfig({ displayName: "Pagination__Text", componentId: "sc-13cpp3o-5" })(["white-space:nowrap;"]); function getAriaLabel(page, selected) { return `${selected === page ? 'Current page, ' : 'Go to '}page ${page}`; } const Pagination = /*#__PURE__*/forwardRef(function Pagination({ totalItems, defaultPage = 1, withItemIndicator, itemsPerPage = 10, onChange, ...rest }, ref) { const pages = Math.ceil(totalItems / itemsPerPage); // Total page numbers const columns = pages < 5 ? pages + 2 : 7; // Total pages to display on the control + 2: < and > const [activePage, setActivePage] = useState(defaultPage); const currentItemFirst = activePage === 1 ? 1 : activePage * itemsPerPage - itemsPerPage + 1; // First number of range of items at current page const currentItemLast = activePage === pages ? totalItems : activePage * itemsPerPage; // Last number of range of items at current page const onPageChange = (event, page) => { page && setActivePage(page); if (event && onChange) { // Callback for provided onChange func onChange(event, page); } else { return undefined; } }; const isMounted = useIsMounted(); const items = PaginationControl(pages, activePage); useIsomorphicLayoutEffect(() => { if (isMounted) { setActivePage(1); onChange?.(null, 1); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [itemsPerPage]); const props = { ref, $withItemIndicator: withItemIndicator, ...rest }; const pagination = /*#__PURE__*/jsx(Navigation, { "aria-label": "pagination", ...props, children: /*#__PURE__*/jsxs(OrderedList, { style: { gridTemplateColumns: `repeat(${columns}, 48px)` }, children: [/*#__PURE__*/jsx(ListItem, { children: /*#__PURE__*/jsx(Button, { variant: "ghost_icon", onClick: activePage > 1 ? event => { onPageChange(event, activePage - 1); } : undefined, disabled: activePage === 1, "aria-label": "Go to previous page", children: /*#__PURE__*/jsx(Icon, { name: "chevron_left" }) }) }, "previous"), items.length > 0 ? items.map((page, index) => page !== 'ELLIPSIS' ? /*#__PURE__*/jsx(ListItem // eslint-disable-next-line react/no-array-index-key , { children: /*#__PURE__*/jsx(PaginationItem, { "aria-label": getAriaLabel(page, activePage), "aria-current": activePage, $page: page, selected: page === activePage, onClick: event => { onPageChange(event, page); } }) }, `list-item ${index}`) : /*#__PURE__*/jsx(ListItem // eslint-disable-next-line react/no-array-index-key , { children: /*#__PURE__*/jsx(StyledIcon, { name: "more_horizontal", "aria-label": "Ellipsis of pages" }) }, `ellipsis-${index}`)) : undefined, /*#__PURE__*/jsx(ListItem, { children: /*#__PURE__*/jsx(Button, { variant: "ghost_icon", onClick: activePage < pages ? event => { onPageChange(event, activePage + 1); } : undefined, "aria-label": "Go to next page", disabled: activePage === pages, children: /*#__PURE__*/jsx(Icon, { name: "chevron_right" }) }) }, "next")] }) }); return withItemIndicator ? /*#__PURE__*/jsxs(FlexContainer, { children: [/*#__PURE__*/jsx(Text, { children: currentItemFirst !== currentItemLast ? `${currentItemFirst} ${' - '} ${currentItemLast} ${' of '} ${totalItems} ${' items'}` : `${currentItemFirst} ${' of '} ${totalItems} ${' items'}` }), pagination] }) : pagination; }); export { Pagination };