diff --git a/src/Options.tsx b/src/Options.tsx index aa570dc0..3f9c1efd 100644 --- a/src/Options.tsx +++ b/src/Options.tsx @@ -1,5 +1,6 @@ import { KeyCode } from '@rc-component/util'; import React from 'react'; +import isEnterOrSpaceKey from './isEnterOrSpaceKey'; import type { PaginationLocale } from './interface'; export type SizeChangerRender = (info: { @@ -91,6 +92,17 @@ const Options: React.FC = (props) => { } }; + const preventInnerKeyDown = (e: React.KeyboardEvent) => { + if (disabled && isEnterOrSpaceKey(e)) { + e.preventDefault(); + } + }; + + const unfocusableWhenDisabled = (node: React.ReactNode) => + disabled && React.isValidElement>(node) + ? React.cloneElement(node, { tabIndex: -1 }) + : node; + const getPageSizeOptions = () => { if ( pageSizeOptions.some( @@ -150,8 +162,8 @@ const Options: React.FC = (props) => { {locale.jump_to_confirm} ) : ( - - {goButton} + + {unfocusableWhenDisabled(goButton)} ); } diff --git a/src/Pager.tsx b/src/Pager.tsx index 5a512afd..3e2d09a5 100644 --- a/src/Pager.tsx +++ b/src/Pager.tsx @@ -11,6 +11,7 @@ export interface PagerProps extends Pick { className?: string; style?: React.CSSProperties; showTitle: boolean; + disabled?: boolean; onClick?: (page: number) => void; onKeyPress?: ( e: React.KeyboardEvent, @@ -28,6 +29,7 @@ const Pager: React.FC = (props) => { className, style, showTitle, + disabled, onClick, onKeyPress, itemRender, @@ -59,21 +61,26 @@ const Pager: React.FC = (props) => { {page} , ); + const pagerContent = + disabled && React.isValidElement>(pager) + ? React.cloneElement(pager, { tabIndex: -1 }) + : pager; const pagerLabel = `${pageLabel} ${page}`.trim(); - return pager ? ( + return pagerContent ? (
  • - {pager} + {pagerContent}
  • ) : null; }; diff --git a/src/Pagination.tsx b/src/Pagination.tsx index 2ca06bd8..5a98a205 100644 --- a/src/Pagination.tsx +++ b/src/Pagination.tsx @@ -296,7 +296,7 @@ const Pagination: React.FC = (props) => { ), ); return React.isValidElement(prevButton) - ? React.cloneElement(prevButton, { disabled: !hasPrev }) + ? React.cloneElement(prevButton, { disabled: !hasPrev || disabled }) : prevButton; } @@ -312,7 +312,7 @@ const Pagination: React.FC = (props) => { ), ); return React.isValidElement(nextButton) - ? React.cloneElement(nextButton, { disabled: !hasNext }) + ? React.cloneElement(nextButton, { disabled: !hasNext || disabled }) : nextButton; } @@ -322,6 +322,28 @@ const Pagination: React.FC = (props) => { } } + function preventInnerDefault(event: React.MouseEvent) { + if (disabled) { + event.preventDefault(); + } + } + + function preventInnerKeyDown(event: React.KeyboardEvent) { + if (disabled && isEnterOrSpaceKey(event)) { + event.preventDefault(); + } + } + + function withUnfocusable(node: React.ReactNode) { + if ( + disabled && + React.isValidElement>(node) + ) { + return React.cloneElement(node, { tabIndex: -1 }); + } + return node; + } + let jumpPrev: React.ReactElement = null; const dataOrAriaAttributeProps = pickAttrs(props, { @@ -360,6 +382,7 @@ const Pagination: React.FC = (props) => { page: -1, className: paginationClassNames?.item, style: styles?.item, + disabled, }; const prevPage = current - 1 > 0 ? current - 1 : 0; @@ -377,14 +400,23 @@ const Pagination: React.FC = (props) => { if (goButton) { if (typeof goButton === 'boolean') { gotoButton = ( - ); } else { gotoButton = ( - - {goButton} + + {withUnfocusable(goButton)} ); } @@ -476,7 +508,7 @@ const Pagination: React.FC = (props) => {
  • = (props) => { })} role="button" aria-label={prevItemTitle} + aria-disabled={disabled || undefined} > - {jumpPrevContent} + {withUnfocusable(jumpPrevContent)}
  • ) : null; @@ -493,7 +526,7 @@ const Pagination: React.FC = (props) => {
  • = (props) => { })} role="button" aria-label={nextItemTitle} + aria-disabled={disabled || undefined} > - {jumpNextContent} + {withUnfocusable(jumpNextContent)}
  • ) : null; } @@ -570,7 +604,7 @@ const Pagination: React.FC = (props) => { let prev = renderPrev(prevPage); if (isReactRenderable(prev)) { - const prevDisabled = !hasPrev || !allPages; + const prevDisabled = !hasPrev || !allPages || !!disabled; prev = (
  • = (props) => { role="button" aria-label={locale.prev_page} > - {prev} + {withUnfocusable(prev)}
  • ); } let next = renderNext(nextPage); if (isReactRenderable(next)) { - let nextDisabled: boolean, nextTabIndex: number | null; - - if (simple) { - nextDisabled = !hasNext; - nextTabIndex = hasPrev ? 0 : null; - } else { - nextDisabled = !hasNext || !allPages; - nextTabIndex = nextDisabled ? null : 0; - } + const nextDisabled = !hasNext || !allPages || !!disabled; next = (
  • = (props) => { role="button" aria-label={locale.next_page} > - {next} + {withUnfocusable(next)}
  • ); } @@ -632,7 +658,9 @@ const Pagination: React.FC = (props) => { className={cls} style={style} ref={paginationRef} + onClick={preventInnerDefault} {...dataOrAriaAttributeProps} + aria-disabled={disabled || undefined} > {totalText} {prev} diff --git a/tests/__snapshots__/demo.test.tsx.snap b/tests/__snapshots__/demo.test.tsx.snap index 2b1ffd7e..11058e3c 100644 --- a/tests/__snapshots__/demo.test.tsx.snap +++ b/tests/__snapshots__/demo.test.tsx.snap @@ -2135,28 +2135,29 @@ exports[`Example jumper 1`] = ` 禁用