|
1 | 1 | import classNames from 'classnames'; |
2 | | -import { forwardRef, type ComponentPropsWithoutRef } from 'react'; |
3 | | -import { ArrowLeftIcon, ArrowRightIcon } from '#components/content-presentation/index.js'; |
4 | | -import { type AsElementLink } from '#util/types/LinkTypes.js'; |
| 2 | +import { Children, forwardRef, type ComponentPropsWithoutRef } from 'react'; |
| 3 | +import { PaginationItem, PaginationLink } from './components/index.js'; |
| 4 | +import { childIsOfComponentType } from '#util/types/TypeGuards.js'; |
5 | 5 |
|
6 | | -export interface PaginationLinkProps extends AsElementLink<HTMLAnchorElement> { |
7 | | - previous?: boolean; |
8 | | - next?: boolean; |
9 | | -} |
| 6 | +export type PaginationProps = ComponentPropsWithoutRef<'nav'>; |
| 7 | + |
| 8 | +const PaginationComponent = forwardRef<HTMLElement, PaginationProps>( |
| 9 | + ({ className, children, 'aria-label': ariaLabel = 'Pagination', ...rest }, forwardedRef) => { |
| 10 | + const items = Children.toArray(children); |
| 11 | + |
| 12 | + // Filter previous and next links |
| 13 | + const links = items.filter((child) => childIsOfComponentType(child, PaginationLink)); |
| 14 | + const linkPrevious = links.find(({ props }) => props.previous); |
| 15 | + const linkNext = links.find(({ props }) => props.next); |
| 16 | + |
| 17 | + // Filter numbered list items |
| 18 | + const listItems = items.filter((child) => childIsOfComponentType(child, PaginationItem)); |
| 19 | + const listItemsNumbered = listItems.filter(({ props }) => props.number || props.ellipsis); |
10 | 20 |
|
11 | | -export const PaginationLink = forwardRef<HTMLAnchorElement, PaginationLinkProps>( |
12 | | - ({ className, children, asElement: Element = 'a', previous, next, ...rest }, forwardedRef) => ( |
13 | | - <li |
14 | | - className={classNames( |
15 | | - { 'nhsuk-pagination-item--previous': previous }, |
16 | | - { 'nhsuk-pagination-item--next': next }, |
17 | | - )} |
18 | | - > |
19 | | - <Element |
| 21 | + return ( |
| 22 | + <nav |
20 | 23 | className={classNames( |
21 | | - 'nhsuk-pagination__link', |
22 | | - { 'nhsuk-pagination__link--prev': previous }, |
23 | | - { 'nhsuk-pagination__link--next': next }, |
| 24 | + 'nhsuk-pagination', |
| 25 | + { 'nhsuk-pagination--numbered': listItemsNumbered.length }, |
24 | 26 | className, |
25 | 27 | )} |
| 28 | + role="navigation" |
| 29 | + aria-label={ariaLabel} |
26 | 30 | ref={forwardedRef} |
27 | 31 | {...rest} |
28 | 32 | > |
29 | | - <span className="nhsuk-pagination__title"> |
30 | | - {previous ? 'Previous' : null} |
31 | | - {next ? 'Next' : null} |
32 | | - </span> |
33 | | - <span className="nhsuk-u-visually-hidden">:</span> |
34 | | - <span className="nhsuk-pagination__page">{children}</span> |
35 | | - {previous ? <ArrowLeftIcon /> : null} |
36 | | - {next ? <ArrowRightIcon /> : null} |
37 | | - </Element> |
38 | | - </li> |
39 | | - ), |
40 | | -); |
41 | | - |
42 | | -export type PaginationProps = ComponentPropsWithoutRef<'nav'>; |
43 | | - |
44 | | -const PaginationComponent = forwardRef<HTMLElement, PaginationProps>( |
45 | | - ({ className, children, 'aria-label': ariaLabel = 'Pagination', ...rest }, forwardedRef) => ( |
46 | | - <nav |
47 | | - className={classNames('nhsuk-pagination', className)} |
48 | | - role="navigation" |
49 | | - aria-label={ariaLabel} |
50 | | - ref={forwardedRef} |
51 | | - {...rest} |
52 | | - > |
53 | | - <ul className="nhsuk-list nhsuk-pagination__list">{children}</ul> |
54 | | - </nav> |
55 | | - ), |
| 33 | + {linkPrevious} |
| 34 | + <ul |
| 35 | + className={ |
| 36 | + listItemsNumbered.length |
| 37 | + ? 'nhsuk-pagination__list' // Standard pagination list class |
| 38 | + : 'nhsuk-list nhsuk-pagination__list' // Legacy pagination list class |
| 39 | + } |
| 40 | + > |
| 41 | + {listItems} |
| 42 | + </ul> |
| 43 | + {linkNext} |
| 44 | + </nav> |
| 45 | + ); |
| 46 | + }, |
56 | 47 | ); |
57 | 48 |
|
58 | 49 | PaginationComponent.displayName = 'Pagination'; |
59 | | -PaginationLink.displayName = 'Pagination.Link'; |
60 | 50 |
|
61 | 51 | export const Pagination = Object.assign(PaginationComponent, { |
| 52 | + Item: PaginationItem, |
62 | 53 | Link: PaginationLink, |
63 | 54 | }); |
0 commit comments