mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-12 12:25:16 +08:00
refactor(pagination): ts
This commit is contained in:
parent
825f85e33d
commit
fb9211efd7
@ -1,4 +1,5 @@
|
||||
/* istanbul ignore file */
|
||||
export { default as NInput } from './src/Input'
|
||||
export type { InputRef } from './src/Input'
|
||||
export { default as NInputGroup } from './src/InputGroup'
|
||||
export { default as NInputGroupLabel } from './src/InputGroupLabel'
|
||||
|
@ -23,6 +23,11 @@ import { inputLight } from '../styles'
|
||||
import type { InputTheme } from '../styles'
|
||||
import style from './styles/input.cssr'
|
||||
|
||||
export interface InputRef {
|
||||
blur: () => void
|
||||
focus: () => void
|
||||
}
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Input',
|
||||
props: {
|
||||
|
@ -1 +0,0 @@
|
||||
export { default as NPagination } from './src/Pagination.vue'
|
1
src/pagination/index.ts
Normal file
1
src/pagination/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { default as NPagination } from './src/Pagination'
|
504
src/pagination/src/Pagination.tsx
Normal file
504
src/pagination/src/Pagination.tsx
Normal file
@ -0,0 +1,504 @@
|
||||
import {
|
||||
h,
|
||||
nextTick,
|
||||
computed,
|
||||
ref,
|
||||
toRef,
|
||||
watch,
|
||||
defineComponent,
|
||||
PropType,
|
||||
CSSProperties
|
||||
} from 'vue'
|
||||
import { useCompitable, useMergedState } from 'vooks'
|
||||
import { NSelect } from '../../select'
|
||||
import { InputRef, NInput } from '../../input'
|
||||
import { NBaseIcon } from '../../_base'
|
||||
import {
|
||||
FastForwardIcon,
|
||||
FastBackwardIcon,
|
||||
BackwardIcon,
|
||||
ForwardIcon,
|
||||
MoreIcon
|
||||
} from '../../_base/icons'
|
||||
import { useLocale, useTheme } from '../../_mixins'
|
||||
import type { ThemeProps } from '../../_mixins'
|
||||
import { paginationLight, PaginationTheme } from '../styles'
|
||||
import { pageItems } from './utils'
|
||||
import type { PageItem } from './utils'
|
||||
import style from './styles/index.cssr'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Pagination',
|
||||
props: {
|
||||
...(useTheme.props as ThemeProps<PaginationTheme>),
|
||||
page: {
|
||||
type: Number,
|
||||
required: undefined
|
||||
},
|
||||
defaultPage: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
pageCount: {
|
||||
type: Number,
|
||||
validator: (value: any) => {
|
||||
return Number.isInteger(value) && value > 0
|
||||
},
|
||||
default: undefined
|
||||
},
|
||||
defaultPageCount: {
|
||||
type: Number,
|
||||
validator: (value: any) => {
|
||||
return Number.isInteger(value) && value > 0
|
||||
},
|
||||
default: 1
|
||||
},
|
||||
showSizePicker: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: undefined
|
||||
},
|
||||
defaultPageSize: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
pageSizes: {
|
||||
type: Array as PropType<number[]>,
|
||||
default: () => []
|
||||
},
|
||||
showQuickJumper: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
pageSlot: {
|
||||
type: Number,
|
||||
default: 9
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
'onUpdate:page': {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
'onUpdate:pageSize': {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
// deprecated
|
||||
onPageSizeChange: {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
onChange: {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
total: {
|
||||
type: Number,
|
||||
validator: (value: any) => {
|
||||
return Number.isInteger(value) && value > 0
|
||||
},
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
const themeRef = useTheme(
|
||||
'Pagination',
|
||||
'Pagination',
|
||||
style,
|
||||
paginationLight,
|
||||
props
|
||||
)
|
||||
const { locale } = useLocale('Pagination')
|
||||
const selfRef = ref<HTMLElement | null>(null)
|
||||
const jumperRef = ref<InputRef | null>(null)
|
||||
const compitablePageCountRef = useCompitable(props, ['total', 'pageCount'])
|
||||
const jumperValueRef = ref('')
|
||||
const uncontrolledPageRef = ref(props.defaultPage)
|
||||
const uncontrolledPageSizeRef = ref(props.defaultPageSize)
|
||||
const mergedPageRef = useMergedState(
|
||||
toRef(props, 'page'),
|
||||
uncontrolledPageRef
|
||||
)
|
||||
const mergedPageSizeRef = useMergedState(
|
||||
toRef(props, 'pageSize'),
|
||||
uncontrolledPageSizeRef
|
||||
)
|
||||
const showFastForwardRef = ref(false)
|
||||
const showFastBackwardRef = ref(false)
|
||||
const transitionDisabledRef = ref(false)
|
||||
|
||||
const pageSizeOptionsRef = computed(() => {
|
||||
const suffix = locale.value.selectionSuffix
|
||||
return props.pageSizes.map((size) => ({
|
||||
label: `${size} / ${suffix}`,
|
||||
value: size
|
||||
}))
|
||||
})
|
||||
// unstable feature
|
||||
const inputSizeRef = computed<'small'>(() => {
|
||||
// const { unstableConfig } = this.$naive
|
||||
// const size = unstableConfig?.Pagination?.inputSize
|
||||
// if (size) {
|
||||
// return size
|
||||
// }
|
||||
return 'small'
|
||||
})
|
||||
|
||||
const disableTransitionOneTick = (): void => {
|
||||
transitionDisabledRef.value = true
|
||||
void nextTick(() => {
|
||||
void selfRef.value?.offsetWidth
|
||||
transitionDisabledRef.value = false
|
||||
})
|
||||
}
|
||||
watch(mergedPageRef, disableTransitionOneTick)
|
||||
function doUpdatePage (page: number): void {
|
||||
if (page === mergedPageRef.value) return
|
||||
const { 'onUpdate:page': onUpdatePage, onChange } = props
|
||||
if (onUpdatePage) onUpdatePage(page)
|
||||
// deprecated
|
||||
if (onChange) onChange(page)
|
||||
}
|
||||
function doUpdatePageSize (pageSize: number): void {
|
||||
if (pageSize === mergedPageSizeRef.value) return
|
||||
const { 'onUpdate:pageSize': onUpdatePageSize, onPageSizeChange } = props
|
||||
if (onUpdatePageSize) onUpdatePageSize(pageSize)
|
||||
// deprecated
|
||||
if (onPageSizeChange) onPageSizeChange(pageSize)
|
||||
}
|
||||
function forward (): void {
|
||||
if (props.disabled) return
|
||||
const page = Math.min(
|
||||
mergedPageRef.value + 1,
|
||||
compitablePageCountRef.value
|
||||
)
|
||||
doUpdatePage(page)
|
||||
}
|
||||
function backward (): void {
|
||||
if (props.disabled) return
|
||||
const page = Math.max(mergedPageRef.value - 1, 1)
|
||||
doUpdatePage(page)
|
||||
}
|
||||
function fastForward (): void {
|
||||
if (props.disabled) return
|
||||
const page = Math.min(
|
||||
mergedPageRef.value + (props.pageSlot - 4),
|
||||
compitablePageCountRef.value
|
||||
)
|
||||
doUpdatePage(page)
|
||||
}
|
||||
function fastBackward (): void {
|
||||
if (props.disabled) return
|
||||
const page = Math.max(mergedPageRef.value - (props.pageSlot - 4), 1)
|
||||
doUpdatePage(page)
|
||||
}
|
||||
function handleSizePickerChange (value: number): void {
|
||||
doUpdatePageSize(value)
|
||||
}
|
||||
function handleQuickJumperKeyUp (e: KeyboardEvent): void {
|
||||
if (e.code === 'Enter') {
|
||||
const page = parseInt(jumperValueRef.value)
|
||||
if (
|
||||
!Number.isNaN(page) &&
|
||||
page >= 1 &&
|
||||
page <= compitablePageCountRef.value
|
||||
) {
|
||||
doUpdatePage(page)
|
||||
jumperValueRef.value = ''
|
||||
jumperRef.value?.blur()
|
||||
}
|
||||
}
|
||||
}
|
||||
function handlePageItemClick (pageItem: PageItem): void {
|
||||
if (props.disabled) return
|
||||
switch (pageItem.type) {
|
||||
case 'page':
|
||||
doUpdatePage(pageItem.label)
|
||||
break
|
||||
case 'fastBackward':
|
||||
fastBackward()
|
||||
break
|
||||
case 'fastForward':
|
||||
fastForward()
|
||||
break
|
||||
}
|
||||
}
|
||||
function handlePageItemMouseEnter (pageItem: PageItem): void {
|
||||
if (props.disabled) return
|
||||
switch (pageItem.type) {
|
||||
default:
|
||||
return
|
||||
case 'fastBackward':
|
||||
showFastBackwardRef.value = true
|
||||
break
|
||||
case 'fastForward':
|
||||
showFastForwardRef.value = true
|
||||
break
|
||||
}
|
||||
disableTransitionOneTick()
|
||||
}
|
||||
function handlePageItemMouseLeave (pageItem: PageItem): void {
|
||||
if (props.disabled) return
|
||||
switch (pageItem.type) {
|
||||
default:
|
||||
return
|
||||
case 'fastBackward':
|
||||
showFastBackwardRef.value = false
|
||||
break
|
||||
case 'fastForward':
|
||||
showFastForwardRef.value = false
|
||||
break
|
||||
}
|
||||
disableTransitionOneTick()
|
||||
}
|
||||
function handleJumperInput (value: string): void {
|
||||
jumperValueRef.value = value
|
||||
}
|
||||
return {
|
||||
locale,
|
||||
selfRef,
|
||||
jumperRef,
|
||||
mergedPage: mergedPageRef,
|
||||
showFastBackward: showFastBackwardRef,
|
||||
showFastForward: showFastForwardRef,
|
||||
compitablePageCount: compitablePageCountRef,
|
||||
pageItems: computed(() =>
|
||||
pageItems(
|
||||
mergedPageRef.value,
|
||||
compitablePageCountRef.value,
|
||||
props.pageSlot
|
||||
)
|
||||
),
|
||||
jumperValue: jumperValueRef,
|
||||
pageSizeOptions: pageSizeOptionsRef,
|
||||
inputSize: inputSizeRef,
|
||||
transitionDisabled: transitionDisabledRef,
|
||||
mergedTheme: themeRef,
|
||||
handleJumperInput,
|
||||
handleBackwardClick: backward,
|
||||
handleForwardClick: forward,
|
||||
handlePageItemClick,
|
||||
handleSizePickerChange,
|
||||
handleQuickJumperKeyUp,
|
||||
handlePageItemMouseEnter,
|
||||
handlePageItemMouseLeave,
|
||||
cssVars: computed(() => {
|
||||
const {
|
||||
self: {
|
||||
itemSize,
|
||||
itemPadding,
|
||||
itemMargin,
|
||||
inputWidth,
|
||||
selectWidth,
|
||||
inputMargin,
|
||||
selectMargin,
|
||||
buttonBorder,
|
||||
buttonBorderHover,
|
||||
buttonBorderPressed,
|
||||
buttonIconColor,
|
||||
buttonIconColorHover,
|
||||
buttonIconColorPressed,
|
||||
buttonIconSize,
|
||||
itemTextColor,
|
||||
itemTextColorHover,
|
||||
itemTextColorPressed,
|
||||
itemTextColorActive,
|
||||
itemTextColorDisabled,
|
||||
itemColor,
|
||||
itemColorHover,
|
||||
itemColorPressed,
|
||||
itemColorActive,
|
||||
itemColorDisabled,
|
||||
itemBorder,
|
||||
itemBorderHover,
|
||||
itemBorderPressed,
|
||||
itemBorderActive,
|
||||
itemBorderDisabled,
|
||||
itemBorderRadius,
|
||||
itemFontSize,
|
||||
jumperFontSize,
|
||||
jumperTextColor,
|
||||
jumperTextColorDisabled
|
||||
},
|
||||
common: { cubicBezierEaseInOut }
|
||||
} = themeRef.value
|
||||
return {
|
||||
'--item-font-size': itemFontSize,
|
||||
'--select-width': selectWidth,
|
||||
'--select-margin': selectMargin,
|
||||
'--input-width': inputWidth,
|
||||
'--input-margin': inputMargin,
|
||||
'--item-size': itemSize,
|
||||
'--item-text-color': itemTextColor,
|
||||
'--item-text-color-disabled': itemTextColorDisabled,
|
||||
'--item-text-color-hover': itemTextColorHover,
|
||||
'--item-text-color-active': itemTextColorActive,
|
||||
'--item-text-color-pressed': itemTextColorPressed,
|
||||
'--item-color': itemColor,
|
||||
'--item-color-hover': itemColorHover,
|
||||
'--item-color-disabled': itemColorDisabled,
|
||||
'--item-color-active': itemColorActive,
|
||||
'--item-color-pressed': itemColorPressed,
|
||||
'--item-border': itemBorder,
|
||||
'--item-border-hover': itemBorderHover,
|
||||
'--item-border-disabled': itemBorderDisabled,
|
||||
'--item-border-active': itemBorderActive,
|
||||
'--item-border-pressed': itemBorderPressed,
|
||||
'--item-padding': itemPadding,
|
||||
'--item-border-radius': itemBorderRadius,
|
||||
'--bezier': cubicBezierEaseInOut,
|
||||
'--jumper-font-size': jumperFontSize,
|
||||
'--jumper-text-color': jumperTextColor,
|
||||
'--jumper-text-color-disabled': jumperTextColorDisabled,
|
||||
'--item-margin': itemMargin,
|
||||
'--buttoNBaseIcon-size': buttonIconSize,
|
||||
'--buttoNBaseIcon-color': buttonIconColor,
|
||||
'--buttoNBaseIcon-color-hover': buttonIconColorHover,
|
||||
'--buttoNBaseIcon-color-pressed': buttonIconColorPressed,
|
||||
'--button-border': buttonBorder,
|
||||
'--button-border-hover': buttonBorderHover,
|
||||
'--button-border-pressed': buttonBorderPressed
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const {
|
||||
transitionDisabled,
|
||||
disabled,
|
||||
cssVars,
|
||||
mergedPage,
|
||||
compitablePageCount,
|
||||
pageItems,
|
||||
showFastBackward,
|
||||
showFastForward,
|
||||
showSizePicker,
|
||||
showQuickJumper,
|
||||
mergedTheme,
|
||||
locale,
|
||||
inputSize,
|
||||
pageSize,
|
||||
pageSizeOptions,
|
||||
jumperValue,
|
||||
handleJumperInput,
|
||||
handleSizePickerChange,
|
||||
handleBackwardClick,
|
||||
handlePageItemClick,
|
||||
handlePageItemMouseEnter,
|
||||
handlePageItemMouseLeave,
|
||||
handleForwardClick,
|
||||
handleQuickJumperKeyUp
|
||||
} = this
|
||||
return (
|
||||
<div
|
||||
ref="selfRef"
|
||||
class={[
|
||||
'n-pagination',
|
||||
{
|
||||
'n-pagination--transition-disabled': transitionDisabled,
|
||||
'n-pagination--disabled': disabled
|
||||
}
|
||||
]}
|
||||
style={cssVars as CSSProperties}
|
||||
>
|
||||
<div
|
||||
class={[
|
||||
'n-pagination-item n-pagination-item--button',
|
||||
{
|
||||
'n-pagination-item--disabled':
|
||||
mergedPage <= 1 || mergedPage > compitablePageCount || disabled
|
||||
}
|
||||
]}
|
||||
onClick={handleBackwardClick}
|
||||
>
|
||||
<NBaseIcon>{{ default: () => <BackwardIcon /> }}</NBaseIcon>
|
||||
</div>
|
||||
{pageItems.map((pageItem, index) => {
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
class={[
|
||||
'n-pagination-item',
|
||||
{
|
||||
'n-pagination-item--active': pageItem.active,
|
||||
'n-pagination-item--disabled': disabled
|
||||
}
|
||||
]}
|
||||
onClick={() => handlePageItemClick(pageItem)}
|
||||
onMouseenter={() => handlePageItemMouseEnter(pageItem)}
|
||||
onMouseleave={() => handlePageItemMouseLeave(pageItem)}
|
||||
>
|
||||
{pageItem.type === 'page' ? pageItem.label : null}
|
||||
{pageItem.type === 'fastBackward' ? (
|
||||
showFastBackward ? (
|
||||
<NBaseIcon>
|
||||
{{ default: () => <FastBackwardIcon /> }}
|
||||
</NBaseIcon>
|
||||
) : (
|
||||
<NBaseIcon>{{ default: () => <MoreIcon /> }}</NBaseIcon>
|
||||
)
|
||||
) : null}
|
||||
{pageItem.type === 'fastForward' ? (
|
||||
showFastForward ? (
|
||||
<NBaseIcon>
|
||||
{{ default: () => <FastForwardIcon /> }}
|
||||
</NBaseIcon>
|
||||
) : (
|
||||
<NBaseIcon>{{ default: () => <MoreIcon /> }}</NBaseIcon>
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
<div
|
||||
class={[
|
||||
'n-pagination-item n-pagination-item--button',
|
||||
{
|
||||
'n-pagination-item--disabled':
|
||||
mergedPage < 1 || mergedPage >= compitablePageCount || disabled
|
||||
}
|
||||
]}
|
||||
onClick={handleForwardClick}
|
||||
>
|
||||
<NBaseIcon>{{ default: () => <ForwardIcon /> }}</NBaseIcon>
|
||||
</div>
|
||||
{showSizePicker ? (
|
||||
<NSelect
|
||||
size={inputSize}
|
||||
placeholder=""
|
||||
options={pageSizeOptions}
|
||||
value={pageSize}
|
||||
disabled={disabled}
|
||||
unstableTheme={mergedTheme.peers.Select}
|
||||
unstableThemeOverrides={mergedTheme.overrides.Select}
|
||||
onUpdateValue={handleSizePickerChange as any}
|
||||
/>
|
||||
) : null}
|
||||
{showQuickJumper ? (
|
||||
<div class="n-pagination-quick-jumper">
|
||||
{locale.goto}
|
||||
<NInput
|
||||
ref="jumperRef"
|
||||
value={jumperValue}
|
||||
onInput={handleJumperInput}
|
||||
size={inputSize}
|
||||
placeholder=""
|
||||
disabled={disabled}
|
||||
unstableTheme={mergedTheme.peers.Input}
|
||||
unstableThemeOverrides={mergedTheme.overrides.Input}
|
||||
onKeyup={handleQuickJumperKeyUp}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
})
|
@ -1,465 +0,0 @@
|
||||
<template>
|
||||
<div
|
||||
ref="selfRef"
|
||||
class="n-pagination"
|
||||
:class="{
|
||||
'n-pagination--transition-disabled': transitionDisabled,
|
||||
'n-pagination--disabled': disabled
|
||||
}"
|
||||
:style="cssVars"
|
||||
>
|
||||
<div
|
||||
class="n-pagination-item n-pagination-item--button"
|
||||
:class="{
|
||||
'n-pagination-item--disabled':
|
||||
page <= 1 || page > compitablePageCount || disabled
|
||||
}"
|
||||
@click="handleBackwardClick"
|
||||
>
|
||||
<n-base-icon>
|
||||
<backward-icon />
|
||||
</n-base-icon>
|
||||
</div>
|
||||
<div
|
||||
v-for="(pageItem, index) in pageItems"
|
||||
:key="index"
|
||||
class="n-pagination-item"
|
||||
:class="{
|
||||
'n-pagination-item--active': pageItem.active,
|
||||
'n-pagination-item--disabled': disabled
|
||||
}"
|
||||
@click="handlePageItemClick(pageItem)"
|
||||
@mouseenter="handlePageItemMouseEnter(pageItem)"
|
||||
@mouseleave="handlePageItemMouseLeave(pageItem)"
|
||||
>
|
||||
<template v-if="pageItem.type === 'page'">
|
||||
{{ pageItem.label }}
|
||||
</template>
|
||||
<template v-if="pageItem.type === 'fastBackward'">
|
||||
<n-base-icon v-if="showFastBackward">
|
||||
<fast-backward-icon />
|
||||
</n-base-icon>
|
||||
<n-base-icon v-else>
|
||||
<more-icon />
|
||||
</n-base-icon>
|
||||
</template>
|
||||
<template v-if="pageItem.type === 'fastForward'">
|
||||
<n-base-icon v-if="showFastForward">
|
||||
<fast-forward-icon />
|
||||
</n-base-icon>
|
||||
<n-base-icon v-else>
|
||||
<more-icon />
|
||||
</n-base-icon>
|
||||
</template>
|
||||
</div>
|
||||
<div
|
||||
class="n-pagination-item n-pagination-item--button"
|
||||
:class="{
|
||||
'n-pagination-item--disabled':
|
||||
page < 1 || page >= compitablePageCount || disabled
|
||||
}"
|
||||
@click="handleForwardClick"
|
||||
>
|
||||
<n-base-icon>
|
||||
<forward-icon />
|
||||
</n-base-icon>
|
||||
</div>
|
||||
<n-select
|
||||
v-if="showSizePicker"
|
||||
:size="inputSize"
|
||||
placeholder=""
|
||||
:options="pageSizeOptions"
|
||||
:value="pageSize"
|
||||
:disabled="disabled"
|
||||
:unstable-theme="mergedTheme.peers.Select"
|
||||
:unstable-theme-overrides="mergedTheme.overrides.Select"
|
||||
@update:value="handleSizePickerChange"
|
||||
/>
|
||||
<div v-if="showQuickJumper" class="n-pagination-quick-jumper">
|
||||
{{ locale.goto }}
|
||||
<n-input
|
||||
v-model:value="jumperValue"
|
||||
:size="inputSize"
|
||||
placeholder=""
|
||||
:disabled="disabled"
|
||||
:unstable-theme="mergedTheme.peers.Input"
|
||||
:unstable-theme-overrides="mergedTheme.overrides.Input"
|
||||
@keyup="handleQuickJumperKeyUp"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { nextTick, computed, ref, toRef, watch } from 'vue'
|
||||
import { useCompitable, useMergedState } from 'vooks'
|
||||
import { NSelect } from '../../select'
|
||||
import { NInput } from '../../input'
|
||||
import { NBaseIcon } from '../../_base'
|
||||
import {
|
||||
FastForwardIcon,
|
||||
FastBackwardIcon,
|
||||
BackwardIcon,
|
||||
ForwardIcon,
|
||||
MoreIcon
|
||||
} from '../../_base/icons'
|
||||
import { useLocale, useTheme } from '../../_mixins'
|
||||
import { paginationLight } from '../styles'
|
||||
import { pageItems } from './utils'
|
||||
import style from './styles/index.cssr.js'
|
||||
|
||||
function useMethods (
|
||||
props,
|
||||
{
|
||||
showFastForwardRef,
|
||||
showFastBackwardRef,
|
||||
mergedPageRef,
|
||||
mergedPageSizeRef,
|
||||
compitablePageCountRef,
|
||||
jumperValueRef,
|
||||
disableTransitionOneTick
|
||||
}
|
||||
) {
|
||||
function doUpdatePage (page) {
|
||||
if (page === mergedPageRef.value) return
|
||||
const { 'onUpdate:page': onUpdatePage, onChange } = props
|
||||
if (onUpdatePage) onUpdatePage(page)
|
||||
// deprecated
|
||||
if (onChange) onChange(page)
|
||||
}
|
||||
function doUpdatePageSize (pageSize) {
|
||||
if (pageSize === mergedPageSizeRef.value) return
|
||||
const { 'onUpdate:pageSize': onUpdatePageSize, onPageSizeChange } = this
|
||||
if (onUpdatePageSize) onUpdatePageSize(pageSize)
|
||||
// deprecated
|
||||
if (onPageSizeChange) onPageSizeChange(pageSize)
|
||||
}
|
||||
function forward () {
|
||||
if (props.disabled) return
|
||||
const page = Math.min(mergedPageRef.value + 1, compitablePageCountRef.value)
|
||||
doUpdatePage(page)
|
||||
}
|
||||
function backward () {
|
||||
if (props.disabled) return
|
||||
const page = Math.max(mergedPageRef.value - 1, 1)
|
||||
doUpdatePage(page)
|
||||
}
|
||||
function fastForward () {
|
||||
if (props.disabled) return
|
||||
const page = Math.min(
|
||||
mergedPageRef.value + (props.pageSlot - 4),
|
||||
compitablePageCountRef.value
|
||||
)
|
||||
doUpdatePage(page)
|
||||
}
|
||||
function fastBackward () {
|
||||
if (props.disabled) return
|
||||
const page = Math.max(mergedPageRef.value - (props.pageSlot - 4), 1)
|
||||
doUpdatePage(page)
|
||||
}
|
||||
function handleSizePickerChange (value) {
|
||||
doUpdatePageSize(value)
|
||||
}
|
||||
function handleQuickJumperKeyUp (e) {
|
||||
if (e.code === 'Enter') {
|
||||
const page = parseInt(jumperValueRef.value)
|
||||
if (
|
||||
!Number.isNaN(page) &&
|
||||
page >= 1 &&
|
||||
page <= compitablePageCountRef.value
|
||||
) {
|
||||
doUpdatePage(page)
|
||||
jumperValueRef.value = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
function handlePageItemClick (pageItem) {
|
||||
if (props.disabled) return
|
||||
switch (pageItem.type) {
|
||||
case 'page':
|
||||
doUpdatePage(pageItem.label)
|
||||
break
|
||||
case 'fastBackward':
|
||||
fastBackward()
|
||||
break
|
||||
case 'fastForward':
|
||||
fastForward()
|
||||
break
|
||||
}
|
||||
}
|
||||
function handlePageItemMouseEnter (pageItem) {
|
||||
if (props.disabled) return
|
||||
switch (pageItem.type) {
|
||||
default:
|
||||
return
|
||||
case 'fastBackward':
|
||||
showFastBackwardRef.value = true
|
||||
break
|
||||
case 'fastForward':
|
||||
showFastForwardRef.value = true
|
||||
break
|
||||
}
|
||||
disableTransitionOneTick()
|
||||
}
|
||||
function handlePageItemMouseLeave (pageItem) {
|
||||
if (props.disabled) return
|
||||
switch (pageItem.type) {
|
||||
default:
|
||||
return
|
||||
case 'fastBackward':
|
||||
showFastBackwardRef.value = false
|
||||
break
|
||||
case 'fastForward':
|
||||
showFastForwardRef.value = false
|
||||
break
|
||||
}
|
||||
disableTransitionOneTick()
|
||||
}
|
||||
return {
|
||||
handleBackwardClick: backward,
|
||||
handleForwardClick: forward,
|
||||
handlePageItemClick,
|
||||
handleSizePickerChange,
|
||||
handleQuickJumperKeyUp,
|
||||
handlePageItemMouseEnter,
|
||||
handlePageItemMouseLeave
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'Pagination',
|
||||
components: {
|
||||
NSelect,
|
||||
NInput,
|
||||
NBaseIcon,
|
||||
BackwardIcon,
|
||||
ForwardIcon,
|
||||
MoreIcon,
|
||||
FastForwardIcon,
|
||||
FastBackwardIcon
|
||||
},
|
||||
props: {
|
||||
...useTheme.props,
|
||||
page: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
pageCount: {
|
||||
validator (value) {
|
||||
return Number.isInteger(value) && value > 0
|
||||
},
|
||||
default: undefined
|
||||
},
|
||||
defaultPageCount: {
|
||||
validator (value) {
|
||||
return Number.isInteger(value) && value > 0
|
||||
},
|
||||
default: 1
|
||||
},
|
||||
showSizePicker: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: undefined
|
||||
},
|
||||
defaultPageSize: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
pageSizes: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
showQuickJumper: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
pageSlot: {
|
||||
type: Number,
|
||||
default: 9
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
'onUpdate:page': {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
'onUpdate:pageSize': {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
// deprecated
|
||||
onPageSizeChange: {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
onChange: {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
total: {
|
||||
validator (value) {
|
||||
return Number.isInteger(value) && value > 0
|
||||
},
|
||||
default: undefined
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
const themeRef = useTheme(
|
||||
'Pagination',
|
||||
'Pagination',
|
||||
style,
|
||||
paginationLight,
|
||||
props
|
||||
)
|
||||
const selfRef = ref(null)
|
||||
const compitablePageCountRef = useCompitable(props, ['total', 'pageCount'])
|
||||
const jumperValueRef = ref('')
|
||||
const uncontrolledPageRef = ref(props.defaultPage)
|
||||
const uncontrolledPageSizeRef = ref(props.defaultPageSize)
|
||||
const mergedPageRef = useMergedState(
|
||||
toRef(props, 'page'),
|
||||
uncontrolledPageRef
|
||||
)
|
||||
const mergedPageSizeRef = useMergedState(
|
||||
toRef(props, 'pageSize'),
|
||||
uncontrolledPageSizeRef
|
||||
)
|
||||
const showFastForwardRef = ref(false)
|
||||
const showFastBackwardRef = ref(false)
|
||||
const transitionDisabledRef = ref(false)
|
||||
const disableTransitionOneTick = () => {
|
||||
transitionDisabledRef.value = true
|
||||
nextTick(() => {
|
||||
void selfRef.value.offsetWidth
|
||||
transitionDisabledRef.value = false
|
||||
})
|
||||
}
|
||||
watch(mergedPageRef, disableTransitionOneTick)
|
||||
return {
|
||||
...useLocale('Pagination'),
|
||||
...useMethods(props, {
|
||||
showFastForwardRef,
|
||||
showFastBackwardRef,
|
||||
mergedPageRef,
|
||||
mergedPageSizeRef,
|
||||
compitablePageCountRef,
|
||||
jumperValueRef,
|
||||
disableTransitionOneTick
|
||||
}),
|
||||
selfRef,
|
||||
showFastBackward: showFastBackwardRef,
|
||||
showFastForward: showFastForwardRef,
|
||||
compitablePageCount: compitablePageCountRef,
|
||||
pageItems: computed(() =>
|
||||
pageItems(props.page, compitablePageCountRef.value, props.pageSlot)
|
||||
),
|
||||
jumperValue: jumperValueRef,
|
||||
transitionDisabled: transitionDisabledRef,
|
||||
mergedTheme: themeRef,
|
||||
cssVars: computed(() => {
|
||||
const {
|
||||
self: {
|
||||
itemSize,
|
||||
itemPadding,
|
||||
itemMargin,
|
||||
inputWidth,
|
||||
selectWidth,
|
||||
inputMargin,
|
||||
selectMargin,
|
||||
buttonBorder,
|
||||
buttonBorderHover,
|
||||
buttonBorderPressed,
|
||||
buttonIconColor,
|
||||
buttonIconColorHover,
|
||||
buttonIconColorPressed,
|
||||
buttonIconSize,
|
||||
itemTextColor,
|
||||
itemTextColorHover,
|
||||
itemTextColorPressed,
|
||||
itemTextColorActive,
|
||||
itemTextColorDisabled,
|
||||
itemColor,
|
||||
itemColorHover,
|
||||
itemColorPressed,
|
||||
itemColorActive,
|
||||
itemColorDisabled,
|
||||
itemBorder,
|
||||
itemBorderHover,
|
||||
itemBorderPressed,
|
||||
itemBorderActive,
|
||||
itemBorderDisabled,
|
||||
itemBorderRadius,
|
||||
itemFontSize,
|
||||
jumperFontSize,
|
||||
jumperTextColor,
|
||||
jumperTextColorDisabled
|
||||
},
|
||||
common: { cubicBezierEaseInOut }
|
||||
} = themeRef.value
|
||||
return {
|
||||
'--item-font-size': itemFontSize,
|
||||
'--select-width': selectWidth,
|
||||
'--select-margin': selectMargin,
|
||||
'--input-width': inputWidth,
|
||||
'--input-margin': inputMargin,
|
||||
'--item-size': itemSize,
|
||||
'--item-text-color': itemTextColor,
|
||||
'--item-text-color-disabled': itemTextColorDisabled,
|
||||
'--item-text-color-hover': itemTextColorHover,
|
||||
'--item-text-color-active': itemTextColorActive,
|
||||
'--item-text-color-pressed': itemTextColorPressed,
|
||||
'--item-color': itemColor,
|
||||
'--item-color-hover': itemColorHover,
|
||||
'--item-color-disabled': itemColorDisabled,
|
||||
'--item-color-active': itemColorActive,
|
||||
'--item-color-pressed': itemColorPressed,
|
||||
'--item-border': itemBorder,
|
||||
'--item-border-hover': itemBorderHover,
|
||||
'--item-border-disabled': itemBorderDisabled,
|
||||
'--item-border-active': itemBorderActive,
|
||||
'--item-border-pressed': itemBorderPressed,
|
||||
'--item-padding': itemPadding,
|
||||
'--item-border-radius': itemBorderRadius,
|
||||
'--bezier': cubicBezierEaseInOut,
|
||||
'--jumper-font-size': jumperFontSize,
|
||||
'--jumper-text-color': jumperTextColor,
|
||||
'--jumper-text-color-disabled': jumperTextColorDisabled,
|
||||
'--item-margin': itemMargin,
|
||||
'--button-base-icon-size': buttonIconSize,
|
||||
'--button-base-icon-color': buttonIconColor,
|
||||
'--button-base-icon-color-hover': buttonIconColorHover,
|
||||
'--button-base-icon-color-pressed': buttonIconColorPressed,
|
||||
'--button-border': buttonBorder,
|
||||
'--button-border-hover': buttonBorderHover,
|
||||
'--button-border-pressed': buttonBorderPressed
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
pageSizeOptions () {
|
||||
const suffix = this.locale.selectionSuffix
|
||||
return this.pageSizes.map((size) => ({
|
||||
label: `${size} / ${suffix}`,
|
||||
value: size
|
||||
}))
|
||||
},
|
||||
// unstable feature
|
||||
inputSize () {
|
||||
const { unstableConfig } = this.$naive
|
||||
const size = unstableConfig?.Pagination?.inputSize
|
||||
if (size) {
|
||||
return size
|
||||
}
|
||||
return 'small'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,4 +1,4 @@
|
||||
import { cB, c, cE, cM, cNotM } from '../../../_utils/cssr'
|
||||
import { cB, c, cM, cNotM } from '../../../_utils/cssr'
|
||||
|
||||
// vars:
|
||||
// --item-font-size
|
||||
@ -58,16 +58,7 @@ export default cB('pagination', `
|
||||
cB('input', `
|
||||
margin: var(--input-margin);
|
||||
width: var(--input-width);
|
||||
`, [
|
||||
cE('placeholder', {
|
||||
left: '6px',
|
||||
right: '6px'
|
||||
}),
|
||||
c('input', `
|
||||
padding-left: 6px;
|
||||
padding-right: 6px;
|
||||
`)
|
||||
])
|
||||
`)
|
||||
]),
|
||||
cB('pagination-item', `
|
||||
position: relative;
|
@ -1,9 +1,8 @@
|
||||
/**
|
||||
*
|
||||
* @param {number} currentPage
|
||||
* @param {number} pageCount
|
||||
*/
|
||||
function pagesToShow (currentPage, pageCount, pageSlot = 9) {
|
||||
function pagesToShow (
|
||||
currentPage: number,
|
||||
pageCount: number,
|
||||
pageSlot: number = 9
|
||||
): number[] {
|
||||
if (pageCount === 1) return [1]
|
||||
if (pageCount === 2) return [1, 2]
|
||||
const firstPage = 1
|
||||
@ -47,18 +46,32 @@ function pagesToShow (currentPage, pageCount, pageSlot = 9) {
|
||||
return items
|
||||
}
|
||||
|
||||
function mapPagesToPageItems (pages, currentPage) {
|
||||
export type PageItem =
|
||||
| {
|
||||
type: 'fastBackward' | 'fastForward'
|
||||
label: string
|
||||
active: false
|
||||
}
|
||||
| {
|
||||
type: 'page'
|
||||
label: number
|
||||
active: boolean
|
||||
}
|
||||
|
||||
function mapPagesToPageItems (pages: number[], currentPage: number): PageItem[] {
|
||||
return pages.map((page) => {
|
||||
switch (page) {
|
||||
case -2:
|
||||
return {
|
||||
type: 'fastBackward',
|
||||
label: 'fastBackward'
|
||||
label: 'fastBackward',
|
||||
active: false
|
||||
}
|
||||
case -1:
|
||||
return {
|
||||
type: 'fastForward',
|
||||
label: 'fastForward'
|
||||
label: 'fastForward',
|
||||
active: false
|
||||
}
|
||||
default:
|
||||
if (page === currentPage) {
|
||||
@ -78,10 +91,13 @@ function mapPagesToPageItems (pages, currentPage) {
|
||||
})
|
||||
}
|
||||
|
||||
function pageItems (currentPage, pageCount, pageSlot) {
|
||||
function pageItems (
|
||||
currentPage: number,
|
||||
pageCount: number,
|
||||
pageSlot: number
|
||||
): PageItem[] {
|
||||
const pages = pagesToShow(currentPage, pageCount, pageSlot)
|
||||
const items = mapPagesToPageItems(pages, currentPage)
|
||||
return items
|
||||
return mapPagesToPageItems(pages, currentPage)
|
||||
}
|
||||
|
||||
export { pagesToShow, mapPagesToPageItems, pageItems }
|
@ -2,9 +2,10 @@ import { changeColor } from 'seemly'
|
||||
import { selectDark } from '../../select/styles'
|
||||
import { inputDark } from '../../input/styles'
|
||||
import { commonDark } from '../../_styles/new-common'
|
||||
import commonVariables from './_common.js'
|
||||
import commonVariables from './_common'
|
||||
import type { PaginationTheme } from './light'
|
||||
|
||||
export default {
|
||||
const paginationDark: PaginationTheme = {
|
||||
name: 'Pagination',
|
||||
common: commonDark,
|
||||
peers: {
|
||||
@ -25,7 +26,7 @@ export default {
|
||||
fontSize
|
||||
} = vars
|
||||
const borderColor = changeColor(primaryColor, {
|
||||
alpha: opacity3
|
||||
alpha: Number(opacity3)
|
||||
})
|
||||
return {
|
||||
...commonVariables,
|
||||
@ -60,3 +61,5 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default paginationDark
|
@ -1,2 +0,0 @@
|
||||
export { default as paginationDark } from './dark.js'
|
||||
export { default as paginationLight } from './light.js'
|
3
src/pagination/styles/index.ts
Normal file
3
src/pagination/styles/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export { default as paginationDark } from './dark'
|
||||
export { default as paginationLight } from './light'
|
||||
export type { PaginationTheme, PaginationThemeVars } from './light'
|
@ -1,58 +0,0 @@
|
||||
import { selectLight } from '../../select/styles'
|
||||
import { inputLight } from '../../input/styles'
|
||||
import { commonLight } from '../../_styles/new-common'
|
||||
import commonVariables from './_common.js'
|
||||
|
||||
export default {
|
||||
name: 'Pagination',
|
||||
common: commonLight,
|
||||
peers: {
|
||||
Select: selectLight,
|
||||
Input: inputLight
|
||||
},
|
||||
self (vars) {
|
||||
const {
|
||||
textColor2,
|
||||
primaryColor,
|
||||
primaryColorHover,
|
||||
primaryColorPressed,
|
||||
inputColorDisabled,
|
||||
textColorDisabled,
|
||||
borderColor,
|
||||
borderRadius,
|
||||
fontSize
|
||||
} = vars
|
||||
|
||||
return {
|
||||
...commonVariables,
|
||||
buttonColor: 'transparent',
|
||||
buttonColorHover: 'transparent',
|
||||
buttonColorPressed: 'transparent',
|
||||
buttonBorder: `1px solid ${borderColor}`,
|
||||
buttonBorderHover: `1px solid ${borderColor}`,
|
||||
buttonBorderPressed: `1px solid ${borderColor}`,
|
||||
buttonIconColor: textColor2,
|
||||
buttonIconColorHover: textColor2,
|
||||
buttonIconColorPressed: textColor2,
|
||||
itemTextColor: textColor2,
|
||||
itemTextColorHover: primaryColorHover,
|
||||
itemTextColorPressed: primaryColorPressed,
|
||||
itemTextColorActive: primaryColor,
|
||||
itemTextColorDisabled: textColorDisabled,
|
||||
itemColor: 'transparent',
|
||||
itemColorHover: 'transparent',
|
||||
itemColorPressed: 'transparent',
|
||||
itemColorActive: 'transparent',
|
||||
itemColorDisabled: inputColorDisabled,
|
||||
itemBorder: '1px solid transparent',
|
||||
itemBorderHover: '1px solid transparent',
|
||||
itemBorderPressed: '1px solid transparent',
|
||||
itemBorderActive: `1px solid ${primaryColor}`,
|
||||
itemBorderDisabled: `1px solid ${borderColor}`,
|
||||
itemBorderRadius: borderRadius,
|
||||
itemFontSize: fontSize,
|
||||
jumperTextColor: textColor2,
|
||||
jumperTextColorDisabled: textColorDisabled
|
||||
}
|
||||
}
|
||||
}
|
66
src/pagination/styles/light.ts
Normal file
66
src/pagination/styles/light.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { selectLight } from '../../select/styles'
|
||||
import { inputLight } from '../../input/styles'
|
||||
import { commonLight, ThemeCommonVars } from '../../_styles/new-common'
|
||||
import commonVariables from './_common'
|
||||
import { createTheme } from '../../_mixins'
|
||||
|
||||
const self = (vars: ThemeCommonVars) => {
|
||||
const {
|
||||
textColor2,
|
||||
primaryColor,
|
||||
primaryColorHover,
|
||||
primaryColorPressed,
|
||||
inputColorDisabled,
|
||||
textColorDisabled,
|
||||
borderColor,
|
||||
borderRadius,
|
||||
fontSize
|
||||
} = vars
|
||||
|
||||
return {
|
||||
...commonVariables,
|
||||
buttonColor: 'transparent',
|
||||
buttonColorHover: 'transparent',
|
||||
buttonColorPressed: 'transparent',
|
||||
buttonBorder: `1px solid ${borderColor}`,
|
||||
buttonBorderHover: `1px solid ${borderColor}`,
|
||||
buttonBorderPressed: `1px solid ${borderColor}`,
|
||||
buttonIconColor: textColor2,
|
||||
buttonIconColorHover: textColor2,
|
||||
buttonIconColorPressed: textColor2,
|
||||
itemTextColor: textColor2,
|
||||
itemTextColorHover: primaryColorHover,
|
||||
itemTextColorPressed: primaryColorPressed,
|
||||
itemTextColorActive: primaryColor,
|
||||
itemTextColorDisabled: textColorDisabled,
|
||||
itemColor: 'transparent',
|
||||
itemColorHover: 'transparent',
|
||||
itemColorPressed: 'transparent',
|
||||
itemColorActive: 'transparent',
|
||||
itemColorDisabled: inputColorDisabled,
|
||||
itemBorder: '1px solid transparent',
|
||||
itemBorderHover: '1px solid transparent',
|
||||
itemBorderPressed: '1px solid transparent',
|
||||
itemBorderActive: `1px solid ${primaryColor}`,
|
||||
itemBorderDisabled: `1px solid ${borderColor}`,
|
||||
itemBorderRadius: borderRadius,
|
||||
itemFontSize: fontSize,
|
||||
jumperTextColor: textColor2,
|
||||
jumperTextColorDisabled: textColorDisabled
|
||||
}
|
||||
}
|
||||
|
||||
export type PaginationThemeVars = ReturnType<typeof self>
|
||||
|
||||
const paginationLight = createTheme({
|
||||
name: 'Pagination',
|
||||
common: commonLight,
|
||||
peers: {
|
||||
Select: selectLight,
|
||||
Input: inputLight
|
||||
},
|
||||
self
|
||||
})
|
||||
|
||||
export default paginationLight
|
||||
export type PaginationTheme = typeof paginationLight
|
@ -144,6 +144,13 @@ export default defineComponent({
|
||||
>,
|
||||
default: undefined
|
||||
},
|
||||
// for jsx
|
||||
onUpdateValue: {
|
||||
type: [Function, Array] as PropType<
|
||||
MaybeArray<(value: string | number | null) => void> | undefined
|
||||
>,
|
||||
default: undefined
|
||||
},
|
||||
onBlur: {
|
||||
type: [Function, Array] as PropType<
|
||||
MaybeArray<(e: FocusEvent) => void> | undefined
|
||||
@ -315,10 +322,15 @@ export default defineComponent({
|
||||
function doUpdateValue (
|
||||
value: string | number | Array<string | number> | null
|
||||
): void {
|
||||
const { onChange, 'onUpdate:value': onUpdateValue } = props
|
||||
const {
|
||||
onChange,
|
||||
'onUpdate:value': _onUpdateValue,
|
||||
onUpdateValue
|
||||
} = props
|
||||
const { nTriggerFormChange, nTriggerFormInput } = formItem
|
||||
if (onChange) call(onChange, value)
|
||||
if (onUpdateValue) call(onUpdateValue, value)
|
||||
if (_onUpdateValue) call(_onUpdateValue, value)
|
||||
uncontrolledValueRef.value = value
|
||||
nTriggerFormChange()
|
||||
nTriggerFormInput()
|
||||
|
Loading…
Reference in New Issue
Block a user