Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Type pagination #15399

Merged
merged 10 commits into from
Mar 14, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ import cx from 'classnames';
import SkeletonText from '../SkeletonText';
import { usePrefix } from '../../internal/usePrefix';

function PaginationSkeleton({ className, ...rest }) {
export interface PaginationSkeletonProps
extends React.HTMLAttributes<HTMLDivElement> {
/**
* Specify an optional className to add.
*/
className?: string;
}

function PaginationSkeleton({ className, ...rest }: PaginationSkeletonProps) {
const prefix = usePrefix();
return (
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,124 @@ import { useFallbackId } from '../../internal/useId';
import { usePrefix } from '../../internal/usePrefix';
import { IconButton } from '../IconButton';

type ExcludedAttributes = 'id' | 'onChange';

export interface PaginationPageSize {
text: string;
value: string;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completely appreciate this is still a draft, but just to flag in the case it's helpful, based on this (and its display in the docs);

pageSizes: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.number),
PropTypes.arrayOf(
PropTypes.shape({
text: PropTypes.string,
value: PropTypes.number,
})
),
]).isRequired,

This might need to be a number

Suggested change
value: string;
value: number;

}

export interface PaginationProps
extends Omit<React.HTMLAttributes<HTMLDivElement>, ExcludedAttributes> {
/**
* The description for the backward icon.
*/
backwardText?: string;

/**
* The CSS class names.
*/
className?: string;

/**
* `true` if the backward/forward buttons, as well as the page select elements, should be disabled.
*/
disabled?: boolean;

/**
* The description for the forward icon.
*/
forwardText?: string;

/**
* The unique ID of this component instance.
*/
id?: string | number;

// TODO: remove when v9 is deprecated
/**
* `true` if the current page should be the last page.
*/
isLastPage?: boolean;

/**
* The function returning a translatable text showing where the current page is,
* in a manner of the range of items.
*/
itemRangeText?: (min: number, max: number, total: number) => string;

/**
* A variant of `itemRangeText`, used if the total number of items is unknown.
*/
itemText?: (min: number, max: number) => string;

/**
* The translatable text indicating the number of items per page.
*/
itemsPerPageText?: string;

/**
* The callback function called when the current page changes.
*/
onChange?: (data: {
page: number;
pageSize: number;
ref?: React.RefObject<any>;
}) => void;

/**
* The current page.
*/
page?: number;

/**
* `true` if the select box to change the page should be disabled.
*/
pageInputDisabled?: boolean;

pageNumberText?: string;

/**
* A function returning PII showing where the current page is.
*/
pageRangeText?: (current: number, total: number) => string;

/**
* The number dictating how many items a page contains.
*/
pageSize?: number;

/**
* `true` if the select box to change the items per page should be disabled.
*/
pageSizeInputDisabled?: boolean;

/**
* The choices for `pageSize`.
*/
pageSizes: number[] | PaginationPageSize[];

/**
* The translatable text showing the current page.
*/
pageText?: (page: number, pagesUnknown?: boolean) => string;

/**
* `true` if the total number of items is unknown.
*/
pagesUnknown?: boolean;

/**
* Specify the size of the Pagination.
*/
size?: 'sm' | 'md' | 'lg';

/**
* The total number of items.
*/
totalItems?: number;
}

function mapPageSizesToObject(sizes) {
return typeof sizes[0] === 'object' && sizes[0] !== null
? sizes
Expand All @@ -24,7 +142,7 @@ function mapPageSizesToObject(sizes) {

function renderSelectItems(total) {
let counter = 1;
let itemArr = [];
const itemArr: React.ReactNode[] = [];
while (counter <= total) {
itemArr.push(
<SelectItem key={counter} value={counter} text={String(counter)} />
Expand All @@ -50,7 +168,7 @@ function getPageSize(pageSizes, pageSize) {
const Pagination = React.forwardRef(function Pagination(
{
backwardText = 'Previous page',
className: customClassName,
className: customClassName = '',
disabled = false,
forwardText = 'Next page',
id,
Expand All @@ -70,15 +188,15 @@ const Pagination = React.forwardRef(function Pagination(
pageText = (page, pagesUnknown) => `page ${pagesUnknown ? '' : page}`,
pagesUnknown = false,
size = 'md',
totalItems,
totalItems = 1,
...rest
},
ref
}: PaginationProps,
ref: React.Ref<HTMLDivElement>
) {
const prefix = usePrefix();
const inputId = useFallbackId(id);
const backBtnRef = useRef(null);
const forwardBtnRef = useRef(null);
const inputId = useFallbackId(id?.toString());
const backBtnRef = useRef<HTMLButtonElement>(null);
const forwardBtnRef = useRef<HTMLButtonElement>(null);
const [pageSizes, setPageSizes] = useState(() => {
return mapPageSizesToObject(controlledPageSizes);
});
Expand Down Expand Up @@ -178,15 +296,15 @@ const Pagination = React.forwardRef(function Pagination(
// the icon button becomes disabled and the focus shifts to `main`
// this presents an a11y problem for keyboard & screen reader users
// instead, we want the focus to shift to the other pagination btn
if (nextPage === totalPages) {
if (nextPage === totalPages && backBtnRef?.current) {
backBtnRef.current.focus();
}

if (onChange) {
onChange({
page: nextPage,
pageSize,
backBtnRef,
ref: backBtnRef,
});
}
}
Expand All @@ -199,15 +317,15 @@ const Pagination = React.forwardRef(function Pagination(
// the icon button becomes disabled and the focus shifts to `main`
// this presents an a11y problem for keyboard & screen reader users
// instead, we want the focus to shift to the other pagination btn
if (nextPage === 1) {
if (nextPage === 1 && forwardBtnRef?.current) {
forwardBtnRef.current.focus();
}

if (onChange) {
onChange({
page: nextPage,
pageSize,
forwardBtnRef,
ref: forwardBtnRef,
});
}
}
Expand Down Expand Up @@ -391,7 +509,7 @@ Pagination.propTypes = {
PropTypes.arrayOf(PropTypes.number),
PropTypes.arrayOf(
PropTypes.shape({
text: PropTypes.text,
text: PropTypes.string,
value: PropTypes.number,
})
),
Expand Down