UNPKG

@hitachivantara/uikit-react-core

Version:

Core React components for the NEXT Design System.

209 lines (208 loc) 7.8 kB
import { jsxs, jsx, Fragment } from "react/jsx-runtime"; import { forwardRef, useState, useCallback, useEffect } from "react"; import { useTheme, useMediaQuery } from "@mui/material"; import { useDefaultProps, clamp } from "@hitachivantara/uikit-react-utils"; import { useLabels } from "../hooks/useLabels.js"; import { HvIcon } from "../icons.js"; import { setId } from "../utils/setId.js"; import { useClasses } from "./Pagination.styles.js"; import { staticClasses } from "./Pagination.styles.js"; import HvSelect, { Option } from "./Select.js"; import { HvTypography } from "../Typography/Typography.js"; import { HvIconButton } from "../IconButton/IconButton.js"; import { HvInput } from "../Input/Input.js"; const defaultPageSizeOptions = [5, 10, 20, 25, 50, 100]; const DEFAULT_LABELS = { /** The show label. */ pageSizePrev: "Show", /** Indicate the units of the page size selection. */ pageSizeEntryName: "rows", /** Used for the aria-label of the selection of number of unit.s */ pageSizeSelectorDescription: "Select how many to display", /** Separator of current page and total pages. */ pagesSeparator: "/", /** Title of button `firstPage`. @deprecated Use `firstPage` instead. */ paginationFirstPageTitle: "First page", /** Title of button `previousPage`. @deprecated Use `previousPage` instead. */ paginationPreviousPageTitle: "Previous page", /** Title of button `nextPage`. @deprecated Use `nextPage` instead. */ paginationNextPageTitle: "Next page", /** Title of button `lastPage`. @deprecated Use `lastPage` instead. */ paginationLastPageTitle: "Last page", /** Aria-label passed to the page input. */ paginationInputLabel: "Current page", /** Label of the first page button */ firstPage: "First Page", /** Label of the previous page button */ previousPage: "Previous Page", /** Label of the next page button */ nextPage: "Next Page", /** Label of the last page button */ lastPage: "Last Page" }; const HvPagination = forwardRef(function HvPagination2(props, ref) { const { classes: classesProp, className, id, pages = 1, page = 0, showPageSizeOptions = true, pageSizeOptions = defaultPageSizeOptions, pageSize = defaultPageSizeOptions[1], showPageJump = true, canPrevious = false, canNext = false, onPageChange, onPageSizeChange, labels: labelsProp, showPageProps, navigationProps, currentPageInputProps, ...others } = useDefaultProps("HvPagination", props); const { classes, cx } = useClasses(classesProp); const labels = useLabels(DEFAULT_LABELS, labelsProp); const muiTheme = useTheme(); const isXsDown = useMediaQuery(muiTheme.breakpoints.down("xs")); const [pageInput, setPageInput] = useState(page); const changePage = useCallback( (newPage) => { const safePage = Number.isNaN(newPage) ? page : clamp(newPage, pages - 1); onPageChange?.(safePage); setPageInput(safePage); }, [page, pages, onPageChange] ); useEffect(() => { if (page >= pages && pages > 0) { changePage(page); } }, [changePage, page, pages]); useEffect(() => { setPageInput(page); }, [page]); const renderPageJump = () => /* @__PURE__ */ jsx("div", { className: classes.pageJump, children: /* @__PURE__ */ jsx( HvInput, { id: setId(id, "currentPage"), labels, inputProps: { "aria-label": labels?.paginationInputLabel, // We really want the native number input type: "number" }, classes: { root: classes?.pageSizeInputContainer, input: classes?.pageSizeInput, inputRoot: classes?.pageSizeInputRoot }, value: String(pageInput + 1), onChange: (event, value) => setPageInput(Number(value) - 1), onBlur: (evt, value) => changePage(Math.round(Number(value)) - 1), onEnter: (evt, value) => changePage(Math.round(Number(value)) - 1), disabled: pageSize === 0, disableClear: true, ...currentPageInputProps } ) }); return /* @__PURE__ */ jsxs("div", { ref, id, className: cx(classes.root, className), ...others, children: [ /* @__PURE__ */ jsx("div", { className: classes.pageSizeOptions, ...showPageProps, children: showPageSizeOptions && /* @__PURE__ */ jsxs(Fragment, { children: [ !isXsDown && /* @__PURE__ */ jsx( HvTypography, { component: "span", className: classes?.pageSizeTextContainer, children: labels?.pageSizePrev } ), /* @__PURE__ */ jsx( HvSelect, { id: setId(id, "pageSize"), disabled: pageSize === 0, className: classes.pageSizeOptionsSelect, "aria-label": labels?.pageSizeSelectorDescription, onChange: (_, val) => onPageSizeChange?.(val), value: pageSize, classes: { header: classes.pageSizeHeader, root: classes.pageSizeRoot }, children: pageSizeOptions.map((option) => /* @__PURE__ */ jsx(Option, { value: option, children: option }, option)) } ), !isXsDown && /* @__PURE__ */ jsx( HvTypography, { component: "span", className: classes.pageSizeTextContainer, children: labels?.pageSizeEntryName } ) ] }) }), /* @__PURE__ */ jsxs("div", { className: classes.pageNavigator, ...navigationProps, children: [ /* @__PURE__ */ jsx( HvIconButton, { id: setId(id, "firstPage-button"), className: classes.iconContainer, disabled: !canPrevious, onClick: () => changePage(0), title: labels?.firstPage || labels?.paginationFirstPageTitle, children: /* @__PURE__ */ jsx(HvIcon, { name: "Start", className: classes.icon, size: "xs" }) } ), /* @__PURE__ */ jsx( HvIconButton, { id: setId(id, "previousPage-button"), className: classes.iconContainer, disabled: !canPrevious, onClick: () => changePage(page - 1), title: labels?.previousPage || labels?.paginationPreviousPageTitle, children: /* @__PURE__ */ jsx(HvIcon, { name: "Backwards", className: classes.icon, size: "xs" }) } ), /* @__PURE__ */ jsxs("div", { className: classes.pageInfo, children: [ showPageJump ? renderPageJump() : /* @__PURE__ */ jsx(HvTypography, { variant: "caption2", component: "span", children: `${page + 1}` }), /* @__PURE__ */ jsx(HvTypography, { component: "span", children: `${labels?.pagesSeparator} ` }), /* @__PURE__ */ jsx( HvTypography, { component: "span", id: setId(id, "totalPages"), className: classes.totalPagesTextContainer, children: pages } ) ] }), /* @__PURE__ */ jsx( HvIconButton, { id: setId(id, "nextPage-button"), className: classes.iconContainer, disabled: !canNext, onClick: () => changePage(page + 1), title: labels?.nextPage || labels?.paginationNextPageTitle, children: /* @__PURE__ */ jsx(HvIcon, { name: "Forwards", className: classes.icon, size: "xs" }) } ), /* @__PURE__ */ jsx( HvIconButton, { id: setId(id, "lastPage-button"), className: classes.iconContainer, disabled: !canNext, onClick: () => changePage(pages - 1), title: labels?.lastPage || labels?.paginationLastPageTitle, children: /* @__PURE__ */ jsx(HvIcon, { name: "End", className: classes.icon, size: "xs" }) } ) ] }) ] }); }); export { HvPagination, staticClasses as paginationClasses };