import type { PropType , CSSProperties } from 'vue' ; import { computed , defineComponent , inject , reactive , ref , toRefs , watch , } from 'vue' ; import type { Data , EmitType } from '../_utils/types' ; import { getPrefixCls } from '../_utils/global-config' ; import { Size } from '../_utils/constant' ; import Pager from './page-item.vue' ; import StepPager from './page-item-step.vue' ; import EllipsisPager from './page-item-ellipsis.vue' ; import PageJumper from './page-jumper.vue' ; import PageOptions from './page-options.vue' ; import { useI18n } from '../locale' ; import { isNumber } from '../_utils/is' ; import type { PageItemType } from './interface' ; import { SelectProps } from '../select' ; import { configProviderInjectionKey } from '../config-provider/context' ; export default defineComponent ( { name : 'Pagination' , props : { zh en total : { type : Number , required : true } , zh en vModel current : Number , zh en defaultCurrent : { type : Number , default : 1 } , zh en vModel pageSize : Number , zh en defaultPageSize : { type : Number , default : 10 } , zh en disabled : { type : Boolean , default : false } , zh en hideOnSinglePage : { type : Boolean , default : false } , zh en simple : { type : Boolean , default : false } , zh en showTotal : { type : Boolean , default : false } , zh en showMore : { type : Boolean , default : false } , zh en showJumper : { type : Boolean , default : false } , zh en showPageSize : { type : Boolean , default : false } , zh en pageSizeOptions : { type : Array as PropType < number [ ] > , default : ( ) => [ 10 , 20 , 30 , 40 , 50 ] } , zh en pageSizeProps : { type : Object as PropType < SelectProps > } , zh en values defaultValue size : { type : String as PropType < Size > , default : ( ) => inject ( configProviderInjectionKey , undefined ) ?. size ?? 'medium' } , zh en pageItemStyle : { type : Object as PropType < CSSProperties > } , zh en activePageItemStyle : { type : Object as PropType < CSSProperties > } , zh en baseSize : { type : Number , default : 6 } , zh en bufferSize : { type : Number , default : 2 } , onChange : { type : [ Function , Array ] as PropType < EmitType < ( value : number ) => void > > } , onPageSizeChange : { type : [ Function , Array ] as PropType < EmitType < ( value : number ) => void > > } } , emits : [ 'update:current' , 'update:pageSize' , 'change' , 'pageSizeChange' , ] , zh en version slot binding zh en version slot binding zh en version slot zh en version slot binding setup ( props , { emit , slots } ) { const prefixCls = getPrefixCls ( 'pagination' ) ; const { t } = useI18n ( ) ; const { disabled , pageItemStyle , activePageItemStyle } = toRefs ( props ) ; const _current = ref ( props . defaultCurrent ) ; const _pageSize = ref ( props . defaultPageSize ) ; const computedCurrent = computed ( ( ) => props . current ?? _current . value ) ; const computedPageSize = computed ( ( ) => props . pageSize ?? _pageSize . value ) ; const pages = computed ( ( ) => Math . ceil ( props . total / computedPageSize . value ) ) ; const handleClick = ( page ) => { if ( page !== computedCurrent . value && isNumber ( page ) && ! props . disabled ) { _current . value = page ; emit ( 'update:current' , page ) ; emit ( 'change' , page ) ; } } ; const handlePageSizeChange = ( pageSize ) => { _pageSize . value = pageSize ; emit ( 'update:pageSize' , pageSize ) ; emit ( 'pageSizeChange' , pageSize ) ; } ; const pagerProps = reactive ( { current : computedCurrent , pages , disabled , style : pageItemStyle , activeStyle : activePageItemStyle , onClick : handleClick } ) ; const getPageItemElement = ( type , props = { } ) => { if ( type === 'more' ) { return ( < EllipsisPager v - slots = { { default : slots [ 'page-item-ellipsis' ] } } { ... props } { ... pagerProps } / > ) ; } if ( type === 'previous' ) { return ( < StepPager v - slots = { { default : slots [ 'page-item-step' ] } } type = "previous" { ... props } { ... pagerProps } />); } if ( type === 'next' ) { return ( < StepPager v - slots = { { default : slots [ 'page-item-step' ] } } type = "next" { ... props } { ... pagerProps } />); } return ( < Pager v - slots = { { default : slots [ 'page-item' ] } } { ... props } { ... pagerProps } />); } ; const pageList = computed ( ( ) => { const pageList = [ ] ; if ( pages . value < props . baseSize + props . bufferSize * 2 ) { for ( let i = 1 ; i <= pages . value ; i ++ ) { pageList . push ( getPageItemElement ( 'page' , { key : i , pageNumber : i } ) ) ; } } else { let left = 1 ; let right = pages . value ; let hasLeftEllipsis = false ; let hasRightEllipsis = false ; if ( computedCurrent . value > 2 + props . bufferSize ) { hasLeftEllipsis = true ; left = Math . min ( computedCurrent . value - props . bufferSize , pages . value - 2 * props . bufferSize ) ; } if ( computedCurrent . value < pages . value - ( props . bufferSize + 1 ) ) { hasRightEllipsis = true ; right = Math . max ( computedCurrent . value + props . bufferSize , 2 * props . bufferSize + 1 ) ; } if ( hasLeftEllipsis ) { pageList . push ( getPageItemElement ( 'page' , { key : 1 , pageNumber : 1 } ) ) ; pageList . push ( getPageItemElement ( 'more' , { key : 'left-ellipsis-pager' , step : - ( props . bufferSize * 2 + 1 ) } ) ) ; } for ( let i = left ; i <= right ; i ++ ) { pageList . push ( getPageItemElement ( 'page' , { key : i , pageNumber : i } ) ) ; } if ( hasRightEllipsis ) { pageList . push ( getPageItemElement ( 'more' , { key : 'right-ellipsis-pager' , step : props . bufferSize * 2 + 1 } ) ) ; pageList . push ( getPageItemElement ( 'page' , { key : pages . value , pageNumber : pages . value } ) ) ; } } return pageList ; } ) ; const renderPager = ( ) => { if ( props . simple ) { return ( < span class = { `${ prefixCls }-simple` } > { getPageItemElement ( 'previous' , { simple : true } ) } < PageJumper disabled = { props . disabled } current = { computedCurrent . value } pages = { pages . value } simple onChange = { handleClick } / > { getPageItemElement ( 'next' , { simple : true } ) } < /span>); } return ( < ul class = { `${ prefixCls }-list` } > { getPageItemElement ( 'previous' , { simple : true } ) } { pageList . value } { props . showMore && getPageItemElement ( 'more' , { key : 'more' , step : props . bufferSize * 2 + 1 } ) } { getPageItemElement ( 'next' , { simple : true } ) } < /ul>); } ; watch ( computedPageSize , ( ) => { if ( computedCurrent . value !== 1 ) { _current . value = 1 ; emit ( 'update:current' , 1 ) ; emit ( 'change' , 1 ) ; } } ) ; const cls = computed ( ( ) => [ prefixCls , `${ prefixCls }-size-${ props . size }` , { [ `${ prefixCls }-simple` ] : props . simple , [ `${ prefixCls }-disabled` ] : props . disabled } , ] ) ; return ( ) => { if ( props . hideOnSinglePage && pages . value <= 1 ) { return null ; } return ( < div class = { cls . value } > { props . showTotal && ( < span class = { `${ prefixCls }-total` } > { slots . total ?. ( { total : props . total } ) ?? t ( 'pagination.total' , props . total ) } < /span>)} { renderPager ( ) } { props . showPageSize && ( < PageOptions disabled = { props . disabled } sizeOptions = { props . pageSizeOptions } pageSize = { computedPageSize . value } size = { props . size } onChange = { handlePageSizeChange } selectProps = { props . pageSizeProps } / > ) } { ! props . simple && props . showJumper && ( < PageJumper disabled = { props . disabled } current = { computedCurrent . value } pages = { pages . value } size = { props . size } onChange = { handleClick } / > ) } < /div>); } ; } } ) ;