forked from opentiny/tiny-vue
feat(pager): [pager] add simplest pager to adaptive x-design (#2126)
* feat(pager): [pager] add simplest pager to adaptive x-design * feat(pager): [pager] add simplest pager to adaptive x-design
This commit is contained in:
parent
ecedc485e3
commit
5bce345e3b
|
@ -92,10 +92,10 @@ export default {
|
|||
},
|
||||
{
|
||||
name: 'mode',
|
||||
type: "'number' | 'simple' | 'complete' | 'fixed'",
|
||||
type: "'number' | 'simple' | 'complete' | 'fixed' | 'simplest'",
|
||||
defaultValue: '',
|
||||
desc: {
|
||||
'zh-CN': '设置分页组件显示模式,此属性优先级大于 layout',
|
||||
'zh-CN': '设置分页组件显示模式,此属性优先级大于 layout, 3.19.0新增simplest',
|
||||
'en-US': 'Set the display mode of pagination components, which takes priority over layout'
|
||||
},
|
||||
mode: ['pc'],
|
||||
|
|
|
@ -12,8 +12,8 @@ test('禁用和尺寸', async ({ page }) => {
|
|||
const next = pager.locator('.tiny-pager__btn-next')
|
||||
|
||||
await demo.locator('.tiny-switch').click()
|
||||
await expect(sizeChange).toHaveCSS('color', 'rgb(138, 142, 153)')
|
||||
await expect(sizeChange).toHaveCSS('border-top-color', 'rgba(0, 0, 0, 0)')
|
||||
await expect(sizeChange).toHaveCSS('color', 'rgb(194, 194, 194)')
|
||||
await expect(sizeChange).toHaveCSS('border-top-color', 'rgb(219, 219, 219)')
|
||||
await expect(prev).toBeDisabled()
|
||||
await expect(next).toBeDisabled()
|
||||
await expect(pageItem.first()).toHaveCSS('cursor', 'not-allowed')
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<tiny-radio-button label="simple"></tiny-radio-button>
|
||||
<tiny-radio-button label="complete"></tiny-radio-button>
|
||||
<tiny-radio-button label="fixed"></tiny-radio-button>
|
||||
<tiny-radio-button label="simplest"></tiny-radio-button>
|
||||
</tiny-radio-group>
|
||||
<tiny-pager :mode="mode" :total="100"></tiny-pager>
|
||||
</div>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<tiny-radio-button label="simple"></tiny-radio-button>
|
||||
<tiny-radio-button label="complete"></tiny-radio-button>
|
||||
<tiny-radio-button label="fixed"></tiny-radio-button>
|
||||
<tiny-radio-button label="simplest"></tiny-radio-button>
|
||||
</tiny-radio-group>
|
||||
<tiny-pager :mode="mode" :total="100"></tiny-pager>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
export default {
|
||||
state: {
|
||||
pageSizeText: '',
|
||||
align: 'right',
|
||||
totalFixedLeft: true
|
||||
align: 'right'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ export const computedInternalLayout =
|
|||
props.mode === 'simple' && (layout = 'sizes, total, prev, current, next')
|
||||
props.mode === 'complete' && (layout = 'sizes, total, prev, pager, next, jumper')
|
||||
props.mode === 'fixed' && (layout = 'prev,pager,next')
|
||||
props.mode === 'simplest' && (layout = 'total, prev, simplest-pager, next')
|
||||
} else if ((!props.mode && props.layout) || (props.mode && props.layout)) {
|
||||
layout = props.layout
|
||||
} else {
|
||||
|
@ -67,6 +68,25 @@ export const computedInternalPageCount =
|
|||
return null
|
||||
}
|
||||
|
||||
export const computedSimplestPagerOption =
|
||||
({ props, state }: Pick<IPagerRenderlessParams, 'props' | 'state'>) =>
|
||||
(): Array<{ value: number; label: string }> => {
|
||||
const itemSizes = Math.max(1, Math.ceil(props.total / state.internalPageSize))
|
||||
return Array.from({ length: itemSizes }).map((item, index) => ({
|
||||
value: index + 1,
|
||||
label: `${index + 1}/${itemSizes}`
|
||||
}))
|
||||
}
|
||||
|
||||
export const computedSimplestPagerWidth =
|
||||
({ state }: Pick<IPagerRenderlessParams, 'state'>) =>
|
||||
(): number => {
|
||||
const baseWidth = 60
|
||||
const num = String(state.internalCurrentPage).length + String(state.simplestPagerOption.length).length
|
||||
// 输入框长度 = 基本宽度加数字长度
|
||||
return baseWidth + num * 8
|
||||
}
|
||||
|
||||
export const handleJumperFocus =
|
||||
({ state }: Pick<IPagerRenderlessParams, 'state'>) =>
|
||||
(e: Event): void => {
|
||||
|
|
|
@ -10,6 +10,8 @@ import {
|
|||
computedInternalLayout,
|
||||
computedTotalText,
|
||||
computedInternalPageCount,
|
||||
computedSimplestPagerOption,
|
||||
computedSimplestPagerWidth,
|
||||
handleJumperFocus,
|
||||
handleSizeChange,
|
||||
handleJumperInput,
|
||||
|
@ -83,6 +85,8 @@ export const renderless = (
|
|||
internalTotal: props.total,
|
||||
jumperValue: '1',
|
||||
jumperBackup: '1',
|
||||
simplestPagerOption: computed(() => api.computedSimplestPagerOption()),
|
||||
simplestPagerWidth: computed(() => api.computedSimplestPagerWidth()),
|
||||
showPager: computed(() => api.computedShowPager()),
|
||||
internalLayout: computed(() => api.computedInternalLayout()),
|
||||
totalText: computed(() => api.computedTotalText()),
|
||||
|
@ -90,7 +94,9 @@ export const renderless = (
|
|||
showJumperSufix: designConfig?.state?.showJumperSufix ?? true,
|
||||
align: props.align || designConfig?.state?.align || 'left',
|
||||
totalI18n: designConfig?.state?.totalI18n || 'totals',
|
||||
totalFixedLeft: props.totalFixedLeft ?? designConfig?.state?.totalFixedLeft ?? false,
|
||||
totalFixedLeft: computed(
|
||||
() => props.totalFixedLeft ?? designConfig?.state?.totalFixedLeft ?? props.mode !== 'simplest' ?? true
|
||||
),
|
||||
pageSizeText: props.pageSizeText ?? designConfig?.state?.pageSizeText
|
||||
})
|
||||
|
||||
|
@ -100,6 +106,8 @@ export const renderless = (
|
|||
computedInternalLayout: computedInternalLayout({ props }),
|
||||
computedTotalText: computedTotalText({ props, t }),
|
||||
computedInternalPageCount: computedInternalPageCount({ props, state }),
|
||||
computedSimplestPagerOption: computedSimplestPagerOption({ props, state }),
|
||||
computedSimplestPagerWidth: computedSimplestPagerWidth({ state }),
|
||||
getValidCurrentPage: getValidCurrentPage({ state }),
|
||||
handleJumperFocus: handleJumperFocus({ state }),
|
||||
handleSizeChange: handleSizeChange({ props, state, api, emit, vm }),
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
// 小型选择器尾部图标距离输入框的垂直距离
|
||||
--ti-select-input-icon-top-small: var(--ti-common-space-4x);
|
||||
// 迷你型选择器尾部图标距离输入框的垂直距离
|
||||
--ti-select-input-icon-top-mini: var(--ti-common-space-4x);
|
||||
--ti-select-input-icon-top-mini: var(--ti-common-space-3x);
|
||||
// 选择器输入框尾部图标的颜色
|
||||
--ti-select-input-caret-icon-color: var(--ti-common-color-icon-normal);
|
||||
// 选择器输入框尾部图标悬浮时的颜色
|
||||
|
|
|
@ -132,9 +132,6 @@
|
|||
.@{pager-prefix-cls}__total-loading {
|
||||
width: 30px;
|
||||
}
|
||||
.tiny-loading__spinner {
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&__goto {
|
||||
|
@ -169,9 +166,11 @@
|
|||
border: 1px solid var(--ti-pager-primary-border-color);
|
||||
box-shadow: 0 0 0 rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
&[disabled] {
|
||||
color: var(--ti-pager-disabled-text-color);
|
||||
border-color: var(--ti-pager-disabled-border-color);
|
||||
border-color: var(--ti-pager-select-disabled-border-color);
|
||||
background: var(--ti-pager-select-disabled-bg-color);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
@ -182,6 +181,7 @@
|
|||
padding-left: var(--ti-pager-normal-text-padding-left);
|
||||
margin-right: 8px;
|
||||
line-height: var(--ti-pager-input-height);
|
||||
|
||||
&-sufix {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
@ -210,10 +210,12 @@
|
|||
background 0.3s;
|
||||
outline: 0;
|
||||
.user-select(none);
|
||||
|
||||
&:hover {
|
||||
border: 1px solid var(--ti-pager-goto-btn-border-hover-color);
|
||||
color: var(--ti-pager-goto-btn-text-hover-color);
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
color: var(--ti-pager-disabled-text-color);
|
||||
border-color: var(--ti-pager-disabled-border-color);
|
||||
|
@ -316,11 +318,12 @@
|
|||
.list-item {
|
||||
min-height: var(--ti-pager-poplist-item-min-height);
|
||||
padding: 0 8px;
|
||||
line-height: 30px;
|
||||
line-height: var(--ti-pager-poplist-item-min-height);
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
@ -512,8 +515,8 @@
|
|||
.@{pager-prefix-cls}__page-size {
|
||||
color: var(--ti-pager-disabled-text-color);
|
||||
cursor: not-allowed;
|
||||
border-color: var(--ti-pager-disabled-border-color);
|
||||
background-color: var(--ti-base-color-bg-1);
|
||||
border-color: var(--ti-pager-select-disabled-border-color);
|
||||
background: var(--ti-pager-select-disabled-bg-color);
|
||||
}
|
||||
|
||||
.@{pager-prefix-cls}__page-size-btn {
|
||||
|
@ -528,6 +531,20 @@
|
|||
color: var(--ti-pager-disabled-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
&__simplest-pager-popover {
|
||||
.component-css-vars-pager();
|
||||
|
||||
.tiny-option-label {
|
||||
text-align: center;
|
||||
font-family: var(--ti-pager-number-font-family);
|
||||
}
|
||||
|
||||
.tiny-option.selected {
|
||||
color: var(--ti-pager-poplist-item-selected-text-color);
|
||||
background: var(--ti-pager-poplist-item-selected-bg-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
|
|
@ -22,7 +22,6 @@ export const tinyPagerOldTheme = {
|
|||
'ti-pager-prev-padding-left': '6px',
|
||||
'ti-pager-goto-btn-text-hover-color': 'var(--ti-common-color-text-highlight, #526ecc)',
|
||||
'ti-pager-poplist-item-min-height': '30px',
|
||||
'ti-pager-pop-body-margin-top': '4px',
|
||||
'ti-pager-poplist-item-selected-bg-color': 'var(--ti-common-color-selected-background, #5e7ce0)',
|
||||
'ti-pager-poplist-item-hover-text-color': 'var(--ti-common-color-text-highlight, #526ecc)',
|
||||
'ti-pager-poplist-item-hover-bg-color': 'var(--ti-common-color-hover-background, #f2f5fc)',
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
// 分页页码选中项文字色
|
||||
--ti-pager-active-font-color: var(--ti-common-color-text-primary);
|
||||
// 分页页码选中项背景色
|
||||
--ti-pager-active-bg-color: #F5F5F5;
|
||||
--ti-pager-active-bg-color: #f5f5f5;
|
||||
// 自定义上下页按钮文本色
|
||||
--ti-pager-primary-text-color: var(--ti-common-color-text-link, #526ecc);
|
||||
// 分页跳转输入框激活颜色
|
||||
|
@ -31,6 +31,10 @@
|
|||
--ti-pager-disabled-text-color: var(--ti-common-color-text-disabled, #adb0b8);
|
||||
// 分页禁用状态下边框颜色
|
||||
--ti-pager-disabled-border-color: transparent;
|
||||
// 分页禁用选择框边框颜色
|
||||
--ti-pager-select-disabled-border-color: #dbdbdb;
|
||||
// 分页禁用选择框背景颜色
|
||||
--ti-pager-select-disabled-bg-color: var(--ti-common-color-bg-disabled);
|
||||
|
||||
// 分页输入框和选项框边框色
|
||||
--ti-pager-input-border-color: var(--ti-common-color-line-normal);
|
||||
|
@ -85,11 +89,11 @@
|
|||
--ti-pager-li-item-hover-font-weight: var(--ti-common-font-weight-6);
|
||||
|
||||
// 分页项默认悬浮背景色
|
||||
--ti-pager-poplist-item-hover-bg-color: #F5F5F5;
|
||||
--ti-pager-poplist-item-hover-bg-color: #f5f5f5;
|
||||
// 分页下拉框项|列表项悬浮文本色
|
||||
--ti-pager-poplist-item-hover-text-color: var(--ti-common-color-text-primary);
|
||||
// 分页下拉框选中项默认背景色
|
||||
--ti-pager-poplist-item-selected-bg-color: #F5F5F5;
|
||||
--ti-pager-poplist-item-selected-bg-color: #f5f5f5;
|
||||
// 分页下拉框项选中字体颜色
|
||||
--ti-pager-poplist-item-selected-text-color: var(--ti-common-color-selected-text-color, #fff);
|
||||
// 分页页码项默认悬浮边框色
|
||||
|
@ -99,7 +103,7 @@
|
|||
// 分页下拉框顶部外边距
|
||||
--ti-pager-pop-body-margin-top: var(--ti-common-space-base);
|
||||
// 分页下拉项最小高度
|
||||
--ti-pager-poplist-item-min-height: var(--ti-common-line-height-6);
|
||||
--ti-pager-poplist-item-min-height: 32px;
|
||||
|
||||
// 分页下一页文字禁用色
|
||||
--ti-pager-prev-next-text-color-disabled: var(--ti-common-color-text-disabled, #adb0b8);
|
||||
|
|
|
@ -1,37 +1,35 @@
|
|||
{
|
||||
"name": "@opentiny/vue-base-select",
|
||||
"type": "module",
|
||||
"version": "3.18.0",
|
||||
"description": "",
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"main": "lib/index.js",
|
||||
"module": "index.ts",
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@opentiny-internal/vue-test-utils": "workspace:*",
|
||||
"vitest": "^0.31.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm -w build:ui $npm_package_name",
|
||||
"//postversion": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentiny/vue-renderless": "workspace:~",
|
||||
"@opentiny/vue-common": "workspace:~",
|
||||
"@opentiny/vue-locale": "workspace:~",
|
||||
"@opentiny/vue-tag": "workspace:~",
|
||||
"@opentiny/vue-input": "workspace:~",
|
||||
"@opentiny/vue-option": "workspace:~",
|
||||
"@opentiny/vue-scrollbar": "workspace:~",
|
||||
"@opentiny/vue-icon": "workspace:~",
|
||||
"@opentiny/vue-select-dropdown": "workspace:~",
|
||||
"@opentiny/vue-grid": "workspace:~",
|
||||
"@opentiny/vue-tree": "workspace:~",
|
||||
"@opentiny/vue-tooltip": "workspace:~",
|
||||
"@opentiny/vue-filter-box": "workspace:~",
|
||||
"@opentiny/vue-button": "workspace:~",
|
||||
"@opentiny/vue-checkbox": "workspace:~",
|
||||
"@opentiny/vue-theme": "workspace:~",
|
||||
"@opentiny/vue-common": "workspace:~",
|
||||
"@opentiny/vue-filter-box": "workspace:~",
|
||||
"@opentiny/vue-icon": "workspace:~",
|
||||
"@opentiny/vue-input": "workspace:~",
|
||||
"@opentiny/vue-locale": "workspace:~",
|
||||
"@opentiny/vue-option": "workspace:~",
|
||||
"@opentiny/vue-recycle-scroller": "workspace:~",
|
||||
"@opentiny/vue-button": "workspace:~"
|
||||
"@opentiny/vue-renderless": "workspace:~",
|
||||
"@opentiny/vue-scrollbar": "workspace:~",
|
||||
"@opentiny/vue-select-dropdown": "workspace:~",
|
||||
"@opentiny/vue-tag": "workspace:~",
|
||||
"@opentiny/vue-theme": "workspace:~",
|
||||
"@opentiny/vue-tooltip": "workspace:~"
|
||||
},
|
||||
"license": "MIT"
|
||||
"devDependencies": {
|
||||
"@opentiny-internal/vue-test-utils": "workspace:*",
|
||||
"vitest": "^0.31.0"
|
||||
}
|
||||
}
|
|
@ -540,8 +540,6 @@ import {
|
|||
IconEllipsis,
|
||||
IconChevronUp
|
||||
} from '@opentiny/vue-icon'
|
||||
import Grid from '@opentiny/vue-grid'
|
||||
import Tree from '@opentiny/vue-tree'
|
||||
import TinyTooltip from '@opentiny/vue-tooltip'
|
||||
import FilterBox from '@opentiny/vue-filter-box'
|
||||
import RecycleScroller from '@opentiny/vue-recycle-scroller'
|
||||
|
@ -593,8 +591,6 @@ export default defineComponent({
|
|||
TinyTag,
|
||||
TinyInput,
|
||||
TinyOption,
|
||||
TinyGrid: Grid,
|
||||
TinyTree: Tree,
|
||||
TinyButton,
|
||||
IconClose: IconClose(),
|
||||
TinyScrollbar,
|
||||
|
|
|
@ -1,27 +1,28 @@
|
|||
{
|
||||
"name": "@opentiny/vue-pager",
|
||||
"type": "module",
|
||||
"version": "3.18.0",
|
||||
"description": "",
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"main": "lib/index.js",
|
||||
"module": "index.ts",
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"@opentiny-internal/vue-test-utils": "workspace:*",
|
||||
"vitest": "^0.31.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm -w build:ui $npm_package_name",
|
||||
"//postversion": "pnpm build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@opentiny/vue-renderless": "workspace:~",
|
||||
"@opentiny/vue-base-select": "workspace:~",
|
||||
"@opentiny/vue-common": "workspace:~",
|
||||
"@opentiny/vue-icon": "workspace:~",
|
||||
"@opentiny/vue-popover": "workspace:~",
|
||||
"@opentiny/vue-pager-item": "workspace:~",
|
||||
"@opentiny/vue-loading": "workspace:~",
|
||||
"@opentiny/vue-theme": "workspace:~",
|
||||
"@opentiny/vue-common": "workspace:~"
|
||||
"@opentiny/vue-pager-item": "workspace:~",
|
||||
"@opentiny/vue-popover": "workspace:~",
|
||||
"@opentiny/vue-renderless": "workspace:~",
|
||||
"@opentiny/vue-theme": "workspace:~"
|
||||
},
|
||||
"license": "MIT"
|
||||
"devDependencies": {
|
||||
"@opentiny-internal/vue-test-utils": "workspace:*",
|
||||
"vitest": "^0.31.0"
|
||||
}
|
||||
}
|
|
@ -69,6 +69,20 @@
|
|||
@before-page-change="beforePagerChangeHandler"
|
||||
></pager>
|
||||
|
||||
<!-- simplest-pager-item -->
|
||||
<tiny-base-select
|
||||
v-else-if="item === 'simplest-pager'"
|
||||
:style="{ width: state.simplestPagerWidth + 'px' }"
|
||||
:size="size"
|
||||
:key="'simplest-pager' + index"
|
||||
v-model="state.internalCurrentPage"
|
||||
:disabled="disabled"
|
||||
:options="state.simplestPagerOption"
|
||||
popper-class="tiny-pager__simplest-pager-popover"
|
||||
:optimization="state.simplestPagerOption.length > 30"
|
||||
@change="handleCurrentChange"
|
||||
></tiny-base-select>
|
||||
|
||||
<!-- next -->
|
||||
<button
|
||||
v-else-if="item === 'next'"
|
||||
|
@ -156,6 +170,7 @@
|
|||
|
||||
<script lang="tsx">
|
||||
import Pager from '@opentiny/vue-pager-item'
|
||||
import TinyBaseSelect from '@opentiny/vue-base-select'
|
||||
import Popover from '@opentiny/vue-popover'
|
||||
import Loading from '@opentiny/vue-loading'
|
||||
import { $prefix, setup, defineComponent, props } from '@opentiny/vue-common'
|
||||
|
@ -200,6 +215,7 @@ export default defineComponent({
|
|||
},
|
||||
components: {
|
||||
TinyPopover: Popover,
|
||||
TinyBaseSelect,
|
||||
ChevronLeft: iconChevronLeft(),
|
||||
ChevronRight: iconChevronRight(),
|
||||
TriangleDown: iconTriangleDown(),
|
||||
|
|
Loading…
Reference in New Issue