UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

125 lines (120 loc) 6.27 kB
import React from 'react'; import styled from 'styled-components'; import Box from '../Box/Box.js'; import { get } from '../constants.js'; import sx from '../sx.js'; import { buildPaginationModel, buildComponentData } from './model.js'; import { viewportRanges } from '../hooks/useResponsiveValue.js'; import { toggleStyledComponent } from '../internal/utils/toggleStyledComponent.js'; import '../FeatureFlags/FeatureFlags.js'; import { useFeatureFlag } from '../FeatureFlags/useFeatureFlag.js'; import '../FeatureFlags/DefaultFeatureFlags.js'; import { clsx } from 'clsx'; import classes from './Pagination.module.css.js'; function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); } const CSS_MODULES_FEATURE_FLAG = 'primer_react_css_modules_staff'; const getViewportRangesToHidePages = showPages => { if (showPages && typeof showPages !== 'boolean') { return Object.keys(showPages).filter(key => !showPages[key]); } if (showPages) { return []; } else { return Object.keys(viewportRanges); } }; const Page = toggleStyledComponent(CSS_MODULES_FEATURE_FLAG, 'a', styled.a.withConfig({ displayName: "Pagination__Page", componentId: "sc-cp45c9-0" })(["display:inline-block;min-width:32px;height:32px;padding:0.5rem calc((2rem - 1.25rem) / 2);font-style:normal;line-height:1;color:", ";text-align:center;white-space:nowrap;vertical-align:middle;cursor:pointer;user-select:none;text-decoration:none;margin-right:", ";&:last-child{margin-right:0;}background-color:transparent;border-radius:", ";transition:background-color 0.2s cubic-bezier(0.3,0,0.5,1);&:hover,&:focus{text-decoration:none;background-color:", ";outline:0;transition-duration:0.1s;}&:focus-visible{outline:2px solid ", ";outline-offset:-2px;}&:active{border-color:", ";}&[rel='prev'],&[rel='next']{color:", ";}&[aria-current],&[aria-current]:hover{color:", ";background-color:", ";border-color:transparent;}&[aria-current]:focus-visible{outline:2px solid ", ";outline-offset:-2px;box-shadow:inset 0 0 0 3px ", ";}&[aria-hidden],&[aria-hidden]:hover,&[role='presentation'],&[role='presentation']:hover{color:", ";cursor:default;background-color:transparent;}@supports (clip-path:polygon(50% 0,100% 50%,50% 100%)){&[rel='prev']::before,&[rel='next']::after{display:inline-block;width:16px;height:16px;vertical-align:text-bottom;content:'';background-color:currentColor;}&[rel='prev']::before{margin-right:", ";clip-path:polygon( 9.8px 12.8px,8.7px 12.8px,4.5px 8.5px,4.5px 7.5px,8.7px 3.2px,9.8px 4.3px,6.1px 8px,9.8px 11.7px,9.8px 12.8px );}&[rel='next']::after{margin-left:", ";clip-path:polygon( 6.2px 3.2px,7.3px 3.2px,11.5px 7.5px,11.5px 8.5px,7.3px 12.8px,6.2px 11.7px,9.9px 8px,6.2px 4.3px,6.2px 3.2px );}}"], get('colors.fg.default'), get('space.1'), get('radii.2'), get('colors.actionListItem.default.hoverBg'), get('colors.accent.emphasis'), get('colors.border.muted'), get('colors.accent.fg'), get('colors.fg.onEmphasis'), get('colors.accent.emphasis'), get('colors.accent.emphasis'), get('colors.fg.onEmphasis'), get('colors.primer.fg.disabled'), get('space.1'), get('space.1'))); function usePaginationPages({ theme, pageCount, currentPage, onPageChange, hrefBuilder, marginPageCount, showPages, surroundingPageCount }) { const pageChange = React.useCallback(n => e => onPageChange(e, n), [onPageChange]); const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG); const model = React.useMemo(() => { return buildPaginationModel(pageCount, currentPage, !!showPages, marginPageCount, surroundingPageCount); }, [pageCount, currentPage, showPages, marginPageCount, surroundingPageCount]); const children = React.useMemo(() => { return model.map(page => { const { props, key, content } = buildComponentData(page, hrefBuilder, pageChange(page.num)); return /*#__PURE__*/React.createElement(Page, _extends({}, props, { key: key, theme: theme, className: clsx(enabled && classes.Page) }), content); }); }, [model, hrefBuilder, pageChange, theme, enabled]); return children; } const PaginationContainer = toggleStyledComponent(CSS_MODULES_FEATURE_FLAG, 'nav', styled.nav.withConfig({ displayName: "Pagination__PaginationContainer", componentId: "sc-cp45c9-1" })(["margin-top:20px;margin-bottom:15px;text-align:center;", " ", ";"], // Hides pages based on the viewport range passed to `showPages` Object.keys(viewportRanges).map(viewportRangeKey => { return ` @media (${viewportRanges[viewportRangeKey]}) { .TablePaginationSteps[data-hidden-viewport-ranges*='${viewportRangeKey}'] > *:not(:first-child):not(:last-child) { display: none; } .TablePaginationSteps[data-hidden-viewport-ranges*='${viewportRangeKey}'] > *:first-child { margin-inline-end: 0; } .TablePaginationSteps[data-hidden-viewport-ranges*='${viewportRangeKey}'] > *:last-child { margin-inline-start: 0; } } `; }).join(''), sx)); function Pagination({ theme, pageCount, currentPage, onPageChange = noop, hrefBuilder = defaultHrefBuilder, marginPageCount = 1, showPages = true, surroundingPageCount = 2, ...rest }) { const pageElements = usePaginationPages({ theme, pageCount, currentPage, onPageChange, hrefBuilder, marginPageCount, showPages, surroundingPageCount }); const enabled = useFeatureFlag(CSS_MODULES_FEATURE_FLAG); return /*#__PURE__*/React.createElement(PaginationContainer, _extends({ className: clsx(enabled && classes.PaginationContainer), "aria-label": "Pagination" }, rest, { theme: theme }), /*#__PURE__*/React.createElement(Box, { display: "inline-block", theme: theme, className: classes.TablePaginationSteps, "data-hidden-viewport-ranges": getViewportRangesToHidePages(showPages).join(' ') }, pageElements)); } Pagination.displayName = "Pagination"; function defaultHrefBuilder(pageNum) { return `#${pageNum}`; } function noop() {} export { Pagination as default };