import React, { CSSProperties, Children, isValidElement, ReactElement, useMemo, useCallback, useState, HTMLAttributes } from 'react' import RcPagination from 'rc-pagination' import cns from 'classnames' import { usePrefix, useLangData } from '../ConfigProvider' import { LeftThinIcon, MoreIcon, RightThinIcon } from '../icons' import { Select, SelectOption } from '../Select' import { useUpdate } from '../utils/hooks' export type PaginationProps = { /** * 默认当前页 * * @default 0 */ defaultCurrent?: number /** * 当前页,从 0 开始 */ current?: number total?: number /** * 每页显示的数量 */ pageSize?: number /** * @default 10 */ defaultPageSize?: number /** * 是否显示 page size 选择器 */ showSizeChanger?: boolean /** 页码或 pageSize 改变的回调,参数是改变后的页码及每页条数 */ onChange?(page: number, pageSize: number): void /** * 是否显示"跳转到" */ showQuickJumper?: boolean /** 自定义样式名 */ className?: string /** 自定义样式 */ style?: CSSProperties /** * 根元素的 html 属性 */ rootHtmlProps?: HTMLAttributes } export default function Pagination(props: PaginationProps) { const { onChange, pageSize, current, defaultCurrent = 0, defaultPageSize = 10, rootHtmlProps, className, style, ...rest } = props const prefix = usePrefix('pagination') const [innerCurrent, setInnerCurrent] = useState((current ?? defaultCurrent) + 1) const [innerPageSize, setInnerPageSize] = useState(pageSize ?? defaultPageSize) useUpdate(() => { if (current != null) { setInnerCurrent(current + 1) } if (pageSize != null) { setInnerPageSize(pageSize) } }, [current, pageSize]) const handleChange = useCallback((nextPage: number, nextPageSize: number) => { if (current == null) { setInnerCurrent(nextPage) } if (pageSize == null) { setInnerPageSize(nextPageSize) } onChange?.(nextPage - 1, nextPageSize) }, [current, onChange, pageSize]) // eslint-disable-next-line @typescript-eslint/naming-convention const renderSizeChanger: { Option?: any, (selectProps: SelectComponentProps): JSX.Element } = useMemo( () => { function handleSizeChange(nextPageSize: number) { handleChange(innerCurrent, nextPageSize) } // eslint-disable-next-line no-underscore-dangle function _renderSizeChanger(selectProps: SelectComponentProps) { return } // https://github.com/react-component/pagination/blob/0bbe863da2b1b69d048ff47604619bb65b6db611/src/Options.jsx#L110 // eg: {value: "10", children: "10 条/页"} _renderSizeChanger.Option = (optionProps: { value: string, children: string }) => optionProps return _renderSizeChanger }, [handleChange, innerCurrent] ) const langData = useLangData('pagination') return ( } nextIcon={} jumpPrevIcon={} jumpNextIcon={} pageSize={innerPageSize} // 去掉 rc 默认带的 a 标签 itemRender={(page, type, elm) => (type === 'page' ? page : elm)} onChange={handleChange} current={innerCurrent} className={cns(className, rootHtmlProps?.className)} style={{ ...style, ...rootHtmlProps?.style }} locale={langData} {...rest} /> ) } type SelectComponentProps = { // {value: "10", children: "10 条/页"} children?: ReactElement<{ value: string, children: string }> value: string } function SizeChanger(props: SelectComponentProps & { onSizeChange?(size: number): void }) { const { value, onSizeChange, children } = props const options = Children.map(children, child => { if (!isValidElement(child)) { return child } return {child.props.children} }) return ( ) }