index.tsx 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import clsx from "clsx";
  2. import usePagination, {
  3. UsePaginationItem,
  4. UsePaginationProps,
  5. } from "libs/hooks/usePagination";
  6. import PaginationItem, { PaginationItemProps } from "./PaginationItem";
  7. import styles from "./index.module.scss";
  8. import { forwardRef } from "react";
  9. export interface PaginationProps extends UsePaginationProps {
  10. className?: string;
  11. /**
  12. * Accepts a function which returns a string value that provides a user-friendly name for the current page.
  13. * This is important for screen reader users.
  14. *
  15. * For localization purposes, you can use the provided [translations](/material-ui/guides/localization/).
  16. * @param {string} type The link or button type to format ('page' | 'first' | 'last' | 'next' | 'previous'). Defaults to 'page'.
  17. * @param {number} page The page number to format.
  18. * @param {bool} selected If true, the current page is selected.
  19. * @returns {string}
  20. */
  21. getItemAriaLabel?: typeof defaultGetAriaLabel;
  22. /**
  23. * Render the item.
  24. * @param {UsePaginationItem} params The props to spread on a PaginationItem.
  25. * @returns {ReactNode}
  26. * @default (item) => <PaginationItem {...item} />
  27. */
  28. renderItem?: (params: UsePaginationItem) => React.ReactNode;
  29. }
  30. function defaultGetAriaLabel(
  31. type: UsePaginationItem["type"],
  32. page: number | null,
  33. selected: boolean
  34. ) {
  35. if (type === "page") {
  36. return `${selected ? "" : "Go to "}page ${page}`;
  37. }
  38. return `Go to ${type} page`;
  39. }
  40. const Pagination = forwardRef<HTMLDivElement, PaginationProps>(
  41. function Pagination(props, ref) {
  42. const {
  43. boundaryCount = 1,
  44. className,
  45. count = 1,
  46. defaultPage = 1,
  47. disabled = false,
  48. getItemAriaLabel = defaultGetAriaLabel,
  49. hideNextButton = false,
  50. hidePrevButton = false,
  51. onChange,
  52. renderItem = (item: PaginationItemProps) => <PaginationItem {...item} />,
  53. ...other
  54. } = props;
  55. const { items } = usePagination({ ...props, componentName: "Pagination" });
  56. return (
  57. <nav
  58. aria-label="pagination navigation"
  59. className={clsx(styles.pages, className)}
  60. ref={ref}
  61. {...other}
  62. >
  63. <ul className={styles.inner}>
  64. {items.map((item, index) => (
  65. <li key={index}>
  66. {renderItem({
  67. ...item,
  68. "aria-label": getItemAriaLabel(
  69. item.type,
  70. item.page,
  71. item.selected
  72. ),
  73. })}
  74. </li>
  75. ))}
  76. </ul>
  77. </nav>
  78. );
  79. }
  80. );
  81. export default Pagination;