refactor: pagination

pull/4606/head
tangjinzhou 2021-08-29 17:05:23 +08:00
parent d7b63dc4a0
commit e5275f742c
86 changed files with 864 additions and 1151 deletions

View File

@ -0,0 +1,10 @@
function firstNotUndefined<T>(arr: T[] = []): T {
for (let i = 0, len = arr.length; i < len; i++) {
if (arr[i] !== undefined) {
return arr[i];
}
}
return undefined;
}
export default firstNotUndefined;

View File

@ -42,7 +42,7 @@ const parseStyleText = (cssText = '', camel) => {
};
const hasProp = (instance, prop) => {
return prop in getOptionProps(instance);
return instance[prop] !== undefined;
};
// 重构后直接使用 hasProp 替换
const slotHasProp = (slot, prop) => {
@ -386,6 +386,9 @@ export function mergeProps() {
}
function isValidElement(element) {
if (Array.isArray(element) && element.length === 1) {
element = element[0];
}
return element && element.__v_isVNode && typeof element.type !== 'symbol'; // remove text node
}

View File

@ -1,4 +1,4 @@
import type { VNodeTypes, PropType, ComputedRef } from 'vue';
import type { VNodeTypes, PropType, ComputedRef, Ref } from 'vue';
import { unref } from 'vue';
import { inject, defineComponent, computed } from 'vue';
import PropTypes from '../_util/vue-types';
@ -68,6 +68,7 @@ type LocaleComponent = keyof Locale;
export function useLocaleReceiver<T extends LocaleComponent>(
componentName: T,
defaultLocale?: Locale[T] | Function | ComputedRef<Locale[T] | Function>,
propsLocale?: Ref<Locale[T]>,
): [ComputedRef<Locale[T]>] {
const localeData = inject<LocaleReceiverContext>('localeData', {} as LocaleReceiverContext);
const componentLocale = computed<Locale[T]>(() => {
@ -79,6 +80,7 @@ export function useLocaleReceiver<T extends LocaleComponent>(
return {
...(typeof locale === 'function' ? (locale as Function)() : locale),
...(localeFromContext || {}),
...(unref(propsLocale) || {}),
};
});
return [componentLocale];

View File

@ -1,18 +1,18 @@
import { defineComponent } from 'vue';
import VcSelect, { selectProps } from '../select';
import { getOptionProps, getSlot } from '../_util/props-util';
export default defineComponent({
inheritAttrs: false,
props: selectProps(),
Option: VcSelect.Option,
render() {
const selectOptionsProps = getOptionProps(this);
const selelctProps: any = {
...selectOptionsProps,
size: 'small',
...this.$attrs,
setup(props, { attrs, slots }) {
return () => {
const selelctProps: any = {
...props,
size: 'small',
...attrs,
};
return <VcSelect {...selelctProps} v-slots={slots}></VcSelect>;
};
return <VcSelect {...selelctProps}>{getSlot(this)}</VcSelect>;
},
});

View File

@ -1,5 +1,6 @@
import type { ExtractPropTypes } from 'vue';
import { defineComponent, inject } from 'vue';
import { computed, toRef } from 'vue';
import { defineComponent } from 'vue';
import LeftOutlined from '@ant-design/icons-vue/LeftOutlined';
import RightOutlined from '@ant-design/icons-vue/RightOutlined';
import DoubleLeftOutlined from '@ant-design/icons-vue/DoubleLeftOutlined';
@ -8,12 +9,11 @@ import { tuple } from '../_util/type';
import PropTypes, { withUndefined } from '../_util/vue-types';
import VcSelect from '../select';
import MiniSelect from './MiniSelect';
import LocaleReceiver from '../locale-provider/LocaleReceiver';
import { getOptionProps } from '../_util/props-util';
import { useLocaleReceiver } from '../locale-provider/LocaleReceiver';
import VcPagination from '../vc-pagination';
import enUS from '../vc-pagination/locale/en_US';
import { defaultConfigProvider } from '../config-provider';
import classNames from '../_util/classNames';
import useConfigInject from '../_util/hooks/useConfigInject';
export const paginationProps = () => ({
total: PropTypes.number,
@ -55,90 +55,83 @@ export type PaginationLocale = any;
export default defineComponent({
name: 'APagination',
inheritAttrs: false,
props: {
...paginationProps(),
},
props: paginationProps(),
emits: ['change', 'showSizeChange', 'update:current', 'update:pageSize'],
setup() {
return {
configProvider: inject('configProvider', defaultConfigProvider),
};
},
methods: {
getIconsProps(prefixCls: string) {
const prevIcon = (
<a class={`${prefixCls}-item-link`}>
setup(props, { slots, attrs }) {
const { prefixCls, configProvider, direction } = useConfigInject('pagination', props);
const selectPrefixCls = computed(() =>
configProvider.getPrefixCls('select', props.selectPrefixCls),
);
const [locale] = useLocaleReceiver('Pagination', enUS, toRef(props, 'locale'));
const getIconsProps = (pre: string) => {
const ellipsis = <span class={`${pre}-item-ellipsis`}></span>;
let prevIcon = (
<button class={`${pre}-item-link`} type="button" tabindex={-1}>
<LeftOutlined />
</a>
</button>
);
const nextIcon = (
<a class={`${prefixCls}-item-link`}>
let nextIcon = (
<button class={`${pre}-item-link`} type="button" tabindex={-1}>
<RightOutlined />
</a>
</button>
);
const jumpPrevIcon = (
<a class={`${prefixCls}-item-link`}>
let jumpPrevIcon = (
<a class={`${pre}-item-link`}>
{/* You can use transition effects in the container :) */}
<div class={`${prefixCls}-item-container`}>
<DoubleLeftOutlined class={`${prefixCls}-item-link-icon`} />
<span class={`${prefixCls}-item-ellipsis`}></span>
<div class={`${pre}-item-container`}>
<DoubleLeftOutlined class={`${pre}-item-link-icon`} />
{ellipsis}
</div>
</a>
);
const jumpNextIcon = (
<a class={`${prefixCls}-item-link`}>
let jumpNextIcon = (
<a class={`${pre}-item-link`}>
{/* You can use transition effects in the container :) */}
<div class={`${prefixCls}-item-container`}>
<DoubleRightOutlined class={`${prefixCls}-item-link-icon`} />
<span class={`${prefixCls}-item-ellipsis`}></span>
<div class={`${pre}-item-container`}>
<DoubleRightOutlined class={`${pre}-item-link-icon`} />
{ellipsis}
</div>
</a>
);
// change arrows direction in right-to-left direction
if (direction.value === 'rtl') {
[prevIcon, nextIcon] = [nextIcon, prevIcon];
[jumpPrevIcon, jumpNextIcon] = [jumpNextIcon, jumpPrevIcon];
}
return {
prevIcon,
nextIcon,
jumpPrevIcon,
jumpNextIcon,
};
},
renderPagination(contextLocale: object) {
};
return () => {
const {
prefixCls: customizePrefixCls,
selectPrefixCls: customizeSelectPrefixCls,
buildOptionText,
size,
locale: customLocale,
itemRender = slots.itemRender,
buildOptionText = slots.buildOptionText,
...restProps
} = getOptionProps(this);
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('pagination', customizePrefixCls);
const selectPrefixCls = getPrefixCls('select', customizeSelectPrefixCls);
} = props;
const isSmall = size === 'small';
const paginationProps = {
prefixCls,
selectPrefixCls,
...restProps,
...this.getIconsProps(prefixCls),
...getIconsProps(prefixCls.value),
prefixCls: prefixCls.value,
selectPrefixCls: selectPrefixCls.value,
selectComponentClass: isSmall ? MiniSelect : VcSelect,
locale: { ...contextLocale, ...customLocale },
buildOptionText: buildOptionText || this.$slots.buildOptionText,
...this.$attrs,
class: classNames({ mini: isSmall }, this.$attrs.class),
itemRender: this.itemRender || this.$slots.itemRender,
locale: locale.value,
buildOptionText,
...attrs,
class: classNames(
{ mini: isSmall, [`${prefixCls.value}-rtl`]: direction.value === 'rtl' },
attrs.class,
),
itemRender,
};
return <VcPagination {...paginationProps} />;
},
},
render() {
return (
<LocaleReceiver
componentName="Pagination"
defaultLocale={enUS}
children={this.renderPagination}
/>
);
};
},
});

View File

@ -59,7 +59,7 @@
}
}
&:focus,
&:focus-visible,
&:hover {
border-color: @primary-color;
transition: all 0.3s;
@ -77,12 +77,12 @@
color: @primary-color;
}
&:focus,
&:focus-visible,
&:hover {
border-color: @primary-5;
}
&:focus a,
&:focus-visible a,
&:hover a {
color: @primary-5;
}
@ -96,9 +96,8 @@
position: relative;
.@{pagination-prefix-cls}-item-link-icon {
.iconfont-size-under-12px(12px);
color: @primary-color;
font-size: @font-size-sm;
letter-spacing: -1px;
opacity: 0;
transition: all 0.2s;
@ -120,6 +119,7 @@
display: block;
margin: auto;
color: @disabled-color;
font-family: Arial, Helvetica, sans-serif;
letter-spacing: 2px;
text-align: center;
text-indent: 0.13em;
@ -128,7 +128,7 @@
}
}
&:focus,
&:focus-visible,
&:hover {
.@{pagination-prefix-cls}-item-link-icon {
opacity: 1;
@ -164,20 +164,24 @@
&-prev,
&-next {
font-family: Arial, Helvetica, sans-serif;
outline: 0;
a {
button {
color: @text-color;
cursor: pointer;
user-select: none;
}
&:hover a {
&:hover button {
border-color: @primary-5;
}
.@{pagination-prefix-cls}-item-link {
display: block;
width: 100%;
height: 100%;
padding: 0;
font-size: 12px;
text-align: center;
background-color: @pagination-item-link-bg;
@ -187,7 +191,7 @@
transition: all 0.3s;
}
&:focus .@{pagination-prefix-cls}-item-link,
&:focus-visible .@{pagination-prefix-cls}-item-link,
&:hover .@{pagination-prefix-cls}-item-link {
color: @primary-color;
border-color: @primary-color;
@ -197,9 +201,8 @@
&-disabled {
&,
&:hover,
&:focus {
&:focus-visible {
cursor: not-allowed;
a,
.@{pagination-prefix-cls}-item-link {
color: @disabled-color;
border-color: @border-color-base;
@ -217,15 +220,23 @@
margin-left: 16px;
vertical-align: middle;
// IE11 css hack. `*::-ms-backdrop,` is a must have
@media all and (-ms-high-contrast: none) {
*::-ms-backdrop,
& {
vertical-align: top;
}
}
&-size-changer.@{ant-prefix}-select {
display: inline-block;
width: auto;
margin-right: 8px;
}
&-quick-jumper {
display: inline-block;
height: @input-height-base;
margin-left: @margin-xs;
line-height: @input-height-base;
vertical-align: top;
@ -233,6 +244,7 @@
.input();
width: 50px;
height: @input-height-base;
margin: 0 8px;
}
}
@ -245,6 +257,7 @@
vertical-align: top;
.@{pagination-prefix-cls}-item-link {
height: @pagination-item-size-sm;
background-color: transparent;
border: 0;
&::after {
height: @pagination-item-size-sm;
@ -273,6 +286,13 @@
&:hover {
border-color: @primary-color;
}
&[disabled] {
color: @disabled-color;
background: @disabled-bg;
border-color: @border-color-base;
cursor: not-allowed;
}
}
}
@ -321,6 +341,11 @@
&.mini &-options {
margin-left: 2px;
&-size-changer {
top: @pagination-mini-options-size-changer-top;
}
&-quick-jumper {
height: @pagination-item-size-sm;
line-height: @pagination-item-size-sm;
@ -329,6 +354,7 @@
.input-sm();
width: 44px;
height: @input-height-sm;
}
}
}
@ -359,27 +385,25 @@
}
.@{pagination-prefix-cls}-item-link {
&,
&:hover,
&:focus {
color: @text-color-secondary;
background: @disabled-bg;
border-color: @border-color-base;
cursor: not-allowed;
color: @disabled-color;
background: @disabled-bg;
border-color: @border-color-base;
cursor: not-allowed;
.@{pagination-prefix-cls}-simple& {
background: transparent;
}
}
.@{pagination-prefix-cls}-jump-prev,
.@{pagination-prefix-cls}-jump-next {
&:focus,
&:hover {
.@{pagination-prefix-cls}-item-link-icon {
opacity: 0;
}
.@{pagination-prefix-cls}-item-ellipsis {
opacity: 1;
}
}
.@{pagination-prefix-cls}-item-link-icon {
opacity: 0;
}
.@{pagination-prefix-cls}-item-ellipsis {
opacity: 1;
}
.@{pagination-prefix-cls}-simple-pager {
color: @disabled-color;
}
}
}
@ -398,3 +422,5 @@
display: none;
}
}
@import './rtl';

View File

@ -2,4 +2,5 @@ import '../../style/index.less';
import './index.less';
// style dependencies
// deps-lint-skip: grid
import '../../select/style';

View File

@ -0,0 +1,55 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@import '../../input/style/mixin';
@pagination-prefix-cls: ~'@{ant-prefix}-pagination';
.@{pagination-prefix-cls}-rtl {
.@{pagination-prefix-cls}-total-text {
margin-right: 0;
margin-left: 8px;
}
.@{pagination-prefix-cls}-item,
.@{pagination-prefix-cls}-prev,
.@{pagination-prefix-cls}-jump-prev,
.@{pagination-prefix-cls}-jump-next {
margin-right: 0;
margin-left: 8px;
}
.@{pagination-prefix-cls}-slash {
margin: 0 5px 0 10px;
}
.@{pagination-prefix-cls}-options {
margin-right: 16px;
margin-left: 0;
.@{pagination-prefix-cls}-options-size-changer.@{ant-prefix}-select {
margin-right: 0;
margin-left: 8px;
}
.@{pagination-prefix-cls}-options-quick-jumper {
margin-left: 0;
}
}
&.@{pagination-prefix-cls}-simple {
.@{pagination-prefix-cls}-simple-pager {
margin-right: 0;
margin-left: 8px;
input {
margin-right: 0;
margin-left: 8px;
}
}
}
&.@{pagination-prefix-cls}.mini .@{pagination-prefix-cls}-options {
margin-right: 2px;
margin-left: 0;
}
}

View File

@ -716,15 +716,16 @@
// Pagination
// ---
@pagination-item-bg: @component-background;
@pagination-item-size: 32px;
@pagination-item-size: @height-base;
@pagination-item-size-sm: 24px;
@pagination-font-family: Arial;
@pagination-font-family: @font-family;
@pagination-font-weight-active: 500;
@pagination-item-bg-active: @component-background;
@pagination-item-link-bg: @component-background;
@pagination-item-disabled-color-active: @white;
@pagination-item-disabled-bg-active: darken(@disabled-bg, 10%);
@pagination-item-input-bg: @component-background;
@pagination-mini-options-size-changer-top: 0px;
// PageHeader
// ---

View File

@ -42,12 +42,12 @@ exports[`Table.pagination renders pagination correctly 1`] = `
<!---->
</div>
</div>
<ul unselectable="unselectable" class="ant-pagination my-page ant-table-pagination">
<ul unselectable="on" class="ant-pagination my-page ant-table-pagination">
<!---->
<li title="Previous Page" class="ant-pagination-disabled ant-pagination-prev" aria-disabled="true"><a class="ant-pagination-item-link"><span role="img" aria-label="left" class="anticon anticon-left"><svg focusable="false" class="" data-icon="left" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></svg></span></a></li>
<li title="1" tabindex="0" class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"><a>1</a></li>
<li title="2" tabindex="0" class="ant-pagination-item ant-pagination-item-2"><a>2</a></li>
<li title="Next Page" tabindex="0" class=" ant-pagination-next" aria-disabled="false"><a class="ant-pagination-item-link"><span role="img" aria-label="right" class="anticon anticon-right"><svg focusable="false" class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span></a></li>
<li title="Previous Page" class="ant-pagination-prev ant-pagination-disabled" aria-disabled="true"><button class="ant-pagination-item-link" type="button" tabindex="-1" disabled=""><span role="img" aria-label="left" class="anticon anticon-left"><svg focusable="false" class="" data-icon="left" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></svg></span></button></li>
<li title="1" tabindex="0" class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"><a rel="nofollow">1</a></li>
<li title="2" tabindex="0" class="ant-pagination-item ant-pagination-item-2"><a rel="nofollow">2</a></li>
<li title="Next Page" tabindex="0" class="ant-pagination-next" aria-disabled="false"><button class="ant-pagination-item-link" type="button" tabindex="-1"><span role="img" aria-label="right" class="anticon anticon-right"><svg focusable="false" class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span></button></li>
<!---->
</ul>
</div>

View File

@ -84,11 +84,11 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
</div>
</div>
</div>
<ul unselectable="unselectable" class="ant-pagination ant-table-pagination">
<ul unselectable="on" class="ant-pagination ant-table-pagination">
<!---->
<li title="Previous Page" class="ant-pagination-disabled ant-pagination-prev" aria-disabled="true"><a class="ant-pagination-item-link"><span role="img" aria-label="left" class="anticon anticon-left"><svg focusable="false" class="" data-icon="left" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></svg></span></a></li>
<li title="1" tabindex="0" class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"><a>1</a></li>
<li title="Next Page" class="ant-pagination-disabled ant-pagination-next" aria-disabled="true"><a class="ant-pagination-item-link"><span role="img" aria-label="right" class="anticon anticon-right"><svg focusable="false" class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span></a></li>
<li title="Previous Page" class="ant-pagination-prev ant-pagination-disabled" aria-disabled="true"><button class="ant-pagination-item-link" type="button" tabindex="-1" disabled=""><span role="img" aria-label="left" class="anticon anticon-left"><svg focusable="false" class="" data-icon="left" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></svg></span></button></li>
<li title="1" tabindex="0" class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"><a rel="nofollow">1</a></li>
<li title="Next Page" class="ant-pagination-next ant-pagination-disabled" aria-disabled="true"><button class="ant-pagination-item-link" type="button" tabindex="-1" disabled=""><span role="img" aria-label="right" class="anticon anticon-right"><svg focusable="false" class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span></button></li>
<!---->
</ul>
</div>

View File

@ -57,11 +57,11 @@ exports[`Table align column should not override cell style 1`] = `
<!---->
</div>
</div>
<ul unselectable="unselectable" class="ant-pagination ant-table-pagination">
<ul unselectable="on" class="ant-pagination ant-table-pagination">
<!---->
<li title="Previous Page" class="ant-pagination-disabled ant-pagination-prev" aria-disabled="true"><a class="ant-pagination-item-link"><span role="img" aria-label="left" class="anticon anticon-left"><svg focusable="false" class="" data-icon="left" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></svg></span></a></li>
<li title="1" tabindex="0" class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"><a>1</a></li>
<li title="Next Page" class="ant-pagination-disabled ant-pagination-next" aria-disabled="true"><a class="ant-pagination-item-link"><span role="img" aria-label="right" class="anticon anticon-right"><svg focusable="false" class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span></a></li>
<li title="Previous Page" class="ant-pagination-prev ant-pagination-disabled" aria-disabled="true"><button class="ant-pagination-item-link" type="button" tabindex="-1" disabled=""><span role="img" aria-label="left" class="anticon anticon-left"><svg focusable="false" class="" data-icon="left" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"></path></svg></span></button></li>
<li title="1" tabindex="0" class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"><a rel="nofollow">1</a></li>
<li title="Next Page" class="ant-pagination-next ant-pagination-disabled" aria-disabled="true"><button class="ant-pagination-item-link" type="button" tabindex="-1" disabled=""><span role="img" aria-label="right" class="anticon anticon-right"><svg focusable="false" class="" data-icon="right" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"></path></svg></span></button></li>
<!---->
</ul>
</div>

View File

@ -1,185 +0,0 @@
import PropTypes from '../_util/vue-types';
import KEYCODE from './KeyCode';
import BaseMixin from '../_util/BaseMixin';
import { withDirectives } from 'vue';
import antInput from '../_util/antInputDirective';
export default {
mixins: [BaseMixin],
props: {
disabled: PropTypes.looseBool,
changeSize: PropTypes.func,
quickGo: PropTypes.func,
selectComponentClass: PropTypes.any,
current: PropTypes.number,
pageSizeOptions: PropTypes.array.def(['10', '20', '50', '100']),
pageSize: PropTypes.number,
buildOptionText: PropTypes.func,
locale: PropTypes.object,
rootPrefixCls: PropTypes.string,
selectPrefixCls: PropTypes.string,
goButton: PropTypes.any,
},
data() {
return {
goInputText: '',
};
},
methods: {
getValidValue() {
const { goInputText } = this;
return !goInputText || isNaN(goInputText) ? undefined : Number(goInputText);
},
defaultBuildOptionText(opt) {
return `${opt.value} ${this.locale.items_per_page}`;
},
handleChange(e) {
const { value, composing } = e.target;
if (e.isComposing || composing || this.goInputText === value) return;
this.setState({
goInputText: value,
});
},
handleBlur(e) {
const { goButton, quickGo, rootPrefixCls } = this.$props;
const { goInputText } = this.$data;
if (goButton || goInputText === '') {
return;
}
this.setState({
goInputText: '',
});
if (
e.relatedTarget &&
(e.relatedTarget.className.indexOf(`${rootPrefixCls}-item-link`) >= 0 ||
e.relatedTarget.className.indexOf(`${rootPrefixCls}-item`) >= 0)
) {
return;
}
quickGo(this.getValidValue());
},
go(e) {
const { goInputText } = this;
if (goInputText === '') {
return;
}
if (e.keyCode === KEYCODE.ENTER || e.type === 'click') {
// https://github.com/vueComponent/ant-design-vue/issues/1316
this.quickGo(this.getValidValue());
this.setState({
goInputText: '',
});
}
},
getPageSizeOptions() {
const { pageSize, pageSizeOptions } = this.$props;
if (pageSizeOptions.some(option => option.toString() === pageSize.toString())) {
return pageSizeOptions;
}
return pageSizeOptions.concat([pageSize.toString()]).sort((a, b) => {
// eslint-disable-next-line no-restricted-globals
const numberA = isNaN(Number(a)) ? 0 : Number(a);
// eslint-disable-next-line no-restricted-globals
const numberB = isNaN(Number(b)) ? 0 : Number(b);
return numberA - numberB;
});
},
},
render() {
const {
rootPrefixCls,
locale,
changeSize,
quickGo,
goButton,
selectComponentClass: Select,
defaultBuildOptionText,
selectPrefixCls,
pageSize,
goInputText,
disabled,
} = this;
const prefixCls = `${rootPrefixCls}-options`;
let changeSelect = null;
let goInput = null;
let gotoButton = null;
if (!changeSize && !quickGo) {
return null;
}
const pageSizeOptions = this.getPageSizeOptions();
if (changeSize && Select) {
const buildOptionText = this.buildOptionText || defaultBuildOptionText;
const options = pageSizeOptions.map((opt, i) => (
<Select.Option key={i} value={opt}>
{buildOptionText({ value: opt })}
</Select.Option>
));
changeSelect = (
<Select
disabled={disabled}
prefixCls={selectPrefixCls}
showSearch={false}
class={`${prefixCls}-size-changer`}
optionLabelProp="children"
value={(pageSize || pageSizeOptions[0]).toString()}
onChange={value => this.changeSize(Number(value))}
getPopupContainer={triggerNode => triggerNode.parentNode}
>
{options}
</Select>
);
}
if (quickGo) {
if (goButton) {
gotoButton =
typeof goButton === 'boolean' ? (
<button
type="button"
onClick={this.go}
onKeyup={this.go}
disabled={disabled}
class={`${prefixCls}-quick-jumper-button`}
>
{locale.jump_to_confirm}
</button>
) : (
<span onClick={this.go} onKeyup={this.go}>
{goButton}
</span>
);
}
goInput = (
<div class={`${prefixCls}-quick-jumper`}>
{locale.jump_to}
{withDirectives(
<input
disabled={disabled}
type="text"
value={goInputText}
onInput={this.handleChange}
onChange={this.handleChange}
onKeyup={this.go}
onBlur={this.handleBlur}
/>,
[[antInput]],
)}
{locale.page}
{gotoButton}
</div>
);
}
return (
<li class={`${prefixCls}`}>
{changeSelect}
{goInput}
</li>
);
},
};

View File

@ -0,0 +1,175 @@
import PropTypes from '../_util/vue-types';
import KEYCODE from './KeyCode';
import { computed, defineComponent, ref, withDirectives } from 'vue';
import antInput from '../_util/antInputDirective';
import type { EventHandler } from '../_util/EventInterface';
export default defineComponent({
props: {
disabled: PropTypes.looseBool,
changeSize: PropTypes.func,
quickGo: PropTypes.func,
selectComponentClass: PropTypes.any,
current: PropTypes.number,
pageSizeOptions: PropTypes.array.def(['10', '20', '50', '100']),
pageSize: PropTypes.number,
buildOptionText: PropTypes.func,
locale: PropTypes.object,
rootPrefixCls: PropTypes.string,
selectPrefixCls: PropTypes.string,
goButton: PropTypes.any,
},
setup(props) {
const goInputText = ref('');
const validValue = computed(() => {
return !goInputText.value || isNaN(goInputText.value as any)
? undefined
: Number(goInputText.value);
});
const defaultBuildOptionText = opt => {
return `${opt.value} ${props.locale.items_per_page}`;
};
const handleChange: EventHandler = e => {
const { value, composing } = e.target;
if (e.isComposing || composing || goInputText.value === value) return;
goInputText.value = value;
};
const handleBlur: EventHandler = e => {
const { goButton, quickGo, rootPrefixCls } = props;
if (goButton || goInputText.value === '') {
return;
}
if (
e.relatedTarget &&
(e.relatedTarget.className.indexOf(`${rootPrefixCls}-item-link`) >= 0 ||
e.relatedTarget.className.indexOf(`${rootPrefixCls}-item`) >= 0)
) {
goInputText.value = '';
return;
} else {
quickGo(validValue.value);
goInputText.value = '';
}
};
const go: EventHandler = e => {
if (goInputText.value === '') {
return;
}
if (e.keyCode === KEYCODE.ENTER || e.type === 'click') {
// https://github.com/vueComponent/ant-design-vue/issues/1316
props.quickGo(validValue.value);
goInputText.value = '';
}
};
const pageSizeOptions = computed(() => {
const { pageSize, pageSizeOptions } = props;
if (pageSizeOptions.some(option => option.toString() === pageSize.toString())) {
return pageSizeOptions;
}
return pageSizeOptions.concat([pageSize.toString()]).sort((a, b) => {
// eslint-disable-next-line no-restricted-globals
const numberA = isNaN(Number(a)) ? 0 : Number(a);
// eslint-disable-next-line no-restricted-globals
const numberB = isNaN(Number(b)) ? 0 : Number(b);
return numberA - numberB;
});
});
return () => {
const {
rootPrefixCls,
locale,
changeSize,
quickGo,
goButton,
selectComponentClass: Select,
selectPrefixCls,
pageSize,
disabled,
} = props;
const prefixCls = `${rootPrefixCls}-options`;
let changeSelect = null;
let goInput = null;
let gotoButton = null;
if (!changeSize && !quickGo) {
return null;
}
if (changeSize && Select) {
const buildOptionText = props.buildOptionText || defaultBuildOptionText;
const options = pageSizeOptions.value.map((opt, i) => (
<Select.Option key={i} value={opt}>
{buildOptionText({ value: opt })}
</Select.Option>
));
changeSelect = (
<Select
disabled={disabled}
prefixCls={selectPrefixCls}
showSearch={false}
class={`${prefixCls}-size-changer`}
optionLabelProp="children"
value={(pageSize || pageSizeOptions.value[0]).toString()}
onChange={value => changeSize(Number(value))}
getPopupContainer={triggerNode => triggerNode.parentNode}
>
{options}
</Select>
);
}
if (quickGo) {
if (goButton) {
gotoButton =
typeof goButton === 'boolean' ? (
<button
type="button"
onClick={go}
onKeyup={go}
disabled={disabled}
class={`${prefixCls}-quick-jumper-button`}
>
{locale.jump_to_confirm}
</button>
) : (
<span onClick={go} onKeyup={go}>
{goButton}
</span>
);
}
goInput = (
<div class={`${prefixCls}-quick-jumper`}>
{locale.jump_to}
{withDirectives(
<input
disabled={disabled}
type="text"
value={goInputText.value}
onInput={handleChange}
onChange={handleChange}
onKeyup={go}
onBlur={handleBlur}
/>,
[[antInput]],
)}
{locale.page}
{gotoButton}
</div>
);
}
return (
<li class={`${prefixCls}`}>
{changeSelect}
{goInput}
</li>
);
};
},
});

View File

@ -1,60 +0,0 @@
import PropTypes from '../_util/vue-types';
import classNames from '../_util/classNames';
import BaseMixin from '../_util/BaseMixin';
export default {
name: 'Pager',
mixins: [BaseMixin],
inheritAttrs: false,
props: {
rootPrefixCls: PropTypes.string,
page: PropTypes.number,
active: PropTypes.looseBool,
last: PropTypes.looseBool,
locale: PropTypes.object,
showTitle: PropTypes.looseBool,
itemRender: {
type: Function,
default: () => {},
},
},
methods: {
handleClick() {
this.__emit('click', this.page);
},
handleKeyPress(event) {
this.__emit('keypress', event, this.handleClick, this.page);
},
},
render() {
const { class: _cls, style } = this.$attrs;
const props = this.$props;
const prefixCls = `${props.rootPrefixCls}-item`;
const cls = classNames(
prefixCls,
`${prefixCls}-${props.page}`,
{
[`${prefixCls}-active`]: props.active,
[`${prefixCls}-disabled`]: !props.page,
},
_cls,
);
return (
<li
onClick={this.handleClick}
onKeypress={this.handleKeyPress}
title={this.showTitle ? this.page : null}
tabindex="0"
class={cls}
style={style}
>
{this.itemRender({
page: this.page,
type: 'page',
originalElement: <a rel="nofollow">{this.page}</a>,
})}
</li>
);
},
};

View File

@ -0,0 +1,60 @@
import PropTypes from '../_util/vue-types';
import classNames from '../_util/classNames';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Pager',
inheritAttrs: false,
props: {
rootPrefixCls: PropTypes.string,
page: PropTypes.number,
active: PropTypes.looseBool,
last: PropTypes.looseBool,
locale: PropTypes.object,
showTitle: PropTypes.looseBool,
itemRender: {
type: Function,
default: () => {},
},
},
eimt: ['click', 'keypress'],
setup(props, { emit, attrs }) {
const handleClick = () => {
emit('click', props.page);
};
const handleKeyPress = (event: KeyboardEvent) => {
emit('keypress', event, handleClick, props.page);
};
return () => {
const { showTitle, page, itemRender } = props;
const { class: _cls, style } = attrs;
const prefixCls = `${props.rootPrefixCls}-item`;
const cls = classNames(
prefixCls,
`${prefixCls}-${props.page}`,
{
[`${prefixCls}-active`]: props.active,
[`${prefixCls}-disabled`]: !props.page,
},
_cls,
);
return (
<li
onClick={handleClick}
onKeypress={handleKeyPress}
title={showTitle ? String(page) : null}
tabindex="0"
class={cls}
style={style}
>
{itemRender({
page,
type: 'page',
originalElement: <a rel="nofollow">{page}</a>,
})}
</li>
);
};
},
});

View File

@ -1,12 +1,6 @@
import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin';
import {
hasProp,
getOptionProps,
getComponent,
splitAttrs,
isValidElement,
} from '../_util/props-util';
import { hasProp, getComponent, splitAttrs, isValidElement } from '../_util/props-util';
import Pager from './Pager';
import Options from './Options';
import LOCALE from './locale/zh_CN';
@ -15,8 +9,7 @@ import classNames from '../_util/classNames';
import { defineComponent, withDirectives } from 'vue';
import antInput from '../_util/antInputDirective';
import { cloneElement } from '../_util/vnode';
function noop() {}
import firstNotUndefined from '../_util/firstNotUndefined';
//
function isInteger(value) {
@ -53,7 +46,7 @@ export default defineComponent({
showPrevNextJumpers: PropTypes.looseBool.def(true),
showQuickJumper: PropTypes.oneOfType([PropTypes.looseBool, PropTypes.object]).def(false),
showTitle: PropTypes.looseBool.def(true),
pageSizeOptions: PropTypes.arrayOf(PropTypes.string),
pageSizeOptions: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])),
buildOptionText: PropTypes.func,
showTotal: PropTypes.func,
simple: PropTypes.looseBool,
@ -66,23 +59,10 @@ export default defineComponent({
totalBoundaryShowSizeChanger: PropTypes.number.def(50),
},
data() {
const props = getOptionProps(this);
const hasOnChange = this.onChange !== noop;
const hasCurrent = 'current' in props;
if (hasCurrent && !hasOnChange) {
console.warn(
'Warning: You provided a `current` prop to a Pagination component without an `onChange` handler. This will render a read-only component.',
); // eslint-disable-line
}
let current = this.defaultCurrent;
if ('current' in props) {
current = this.current;
}
const props = this.$props;
let current = firstNotUndefined([this.current, this.defaultCurrent]);
let pageSize = this.defaultPageSize;
if ('pageSize' in props) {
pageSize = this.pageSize;
}
const pageSize = firstNotUndefined([this.pageSize, this.defaultPageSize]);
current = Math.min(current, calculatePage(pageSize, undefined, props));
@ -100,7 +80,7 @@ export default defineComponent({
});
},
pageSize(val) {
const newState = {};
const newState: any = {};
let current = this.stateCurrent;
const newCurrent = calculatePage(val, this.$data, this.$props);
current = current > newCurrent ? newCurrent : current;
@ -111,7 +91,7 @@ export default defineComponent({
newState.statePageSize = val;
this.setState(newState);
},
stateCurrent(val, oldValue) {
stateCurrent(_val, oldValue) {
// When current page change, fix focused style of prev item
// A hacky solution of https://github.com/ant-design/ant-design/issues/8948
this.$nextTick(() => {
@ -126,7 +106,7 @@ export default defineComponent({
});
},
total() {
const newState = {};
const newState: any = {};
const newCurrent = calculatePage(this.pageSize, this.$data, this.$props);
if (hasProp(this, 'current')) {
const current = Math.min(this.current, newCurrent);
@ -332,7 +312,9 @@ export default defineComponent({
originalElement: this.getItemIcon('prevIcon', 'prev page'),
});
const disabled = !this.hasPrev();
return isValidElement(prevButton) ? cloneElement(prevButton, { disabled }) : prevButton;
return isValidElement(prevButton)
? cloneElement(prevButton, disabled ? { disabled } : {})
: prevButton;
},
renderNext(nextPage) {
@ -343,7 +325,9 @@ export default defineComponent({
originalElement: this.getItemIcon('nextIcon', 'next page'),
});
const disabled = !this.hasNext();
return isValidElement(nextButton) ? cloneElement(nextButton, { disabled }) : nextButton;
return isValidElement(nextButton)
? cloneElement(nextButton, disabled ? { disabled } : {})
: nextButton;
},
},
render() {
@ -646,7 +630,7 @@ export default defineComponent({
const buildOptionText = this.buildOptionText || this.$slots.buildOptionText;
return (
<ul
unselectable="unselectable"
unselectable="on"
ref="paginationNode"
{...restAttrs}
class={classNames(

View File

@ -1,352 +0,0 @@
@prefixClass: rc-pagination;
.@{prefixClass} {
font-size: 12px;
font-family: 'Arial';
user-select: none;
padding: 0;
> li {
list-style: none;
}
&-total-text {
float: left;
height: 30px;
line-height: 30px;
list-style: none;
padding: 0;
margin: 0 8px 0 0;
}
&:after {
content: ' ';
display: block;
height: 0;
clear: both;
overflow: hidden;
visibility: hidden;
}
&-item {
cursor: pointer;
border-radius: 6px;
min-width: 28px;
height: 28px;
line-height: 28px;
text-align: center;
list-style: none;
float: left;
border: 1px solid #d9d9d9;
background-color: #fff;
margin-right: 8px;
a {
text-decoration: none;
color: #666;
}
&:hover {
border-color: #2db7f5;
a {
color: #2db7f5;
}
}
&-disabled {
cursor: not-allowed;
&:hover {
border-color: #d9d9d9;
a {
color: #d9d9d9;
}
}
}
&-active {
background-color: #2db7f5;
border-color: #2db7f5;
a {
color: #fff;
}
&:hover {
a {
color: #fff;
}
}
}
}
&-jump-prev,
&-jump-next {
&:after {
content: '•••';
display: block;
letter-spacing: 2px;
color: #ccc;
font-size: 12px;
margin-top: 1px;
}
&:hover {
&:after {
color: #2db7f5;
}
}
}
&-jump-prev {
&:hover {
&:after {
content: '«';
}
}
}
&-jump-next {
&:hover {
&:after {
content: '»';
}
}
}
&-jump-prev-custom-icon,
&-jump-next-custom-icon {
position: relative;
&:after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
transition: all 0.2s;
content: '•••';
opacity: 1;
display: block;
letter-spacing: 2px;
color: #ccc;
font-size: 12px;
margin-top: 1px;
}
.custom-icon-jump-prev,
.custom-icon-jump-next {
opacity: 0;
transition: all 0.2s;
}
&:hover {
&:after {
opacity: 0;
color: #ccc;
}
.custom-icon-jump-prev,
.custom-icon-jump-next {
opacity: 1;
color: #2db7f5;
}
}
}
&-prev,
&-jump-prev,
&-jump-next {
margin-right: 8px;
}
&-prev,
&-next,
&-jump-prev,
&-jump-next {
cursor: pointer;
color: #666;
font-size: 10px;
border-radius: 6px;
list-style: none;
min-width: 28px;
height: 28px;
line-height: 28px;
float: left;
text-align: center;
}
&-prev {
a {
&:after {
content: '';
display: block;
}
}
}
&-next {
a {
&:after {
content: '';
display: block;
}
}
}
&-prev,
&-next {
border: 1px solid #d9d9d9;
font-size: 18px;
a {
color: #666;
&:after {
margin-top: -1px;
}
}
}
&-disabled {
cursor: not-allowed;
a {
color: #ccc;
}
}
&-options {
float: left;
margin-left: 15px;
&-size-changer {
float: left;
width: 80px;
}
&-quick-jumper {
float: left;
margin-left: 16px;
height: 28px;
line-height: 28px;
input {
margin: 0 8px;
box-sizing: border-box;
background-color: #fff;
border-radius: 6px;
border: 1px solid #d9d9d9;
outline: none;
padding: 3px 12px;
width: 50px;
height: 28px;
&:hover {
border-color: #2db7f5;
}
}
button {
display: inline-block;
margin: 0 8px;
font-weight: 500;
text-align: center;
touch-action: manipulation;
cursor: pointer;
background-image: none;
border: 1px solid transparent;
white-space: nowrap;
padding: 0 15px;
font-size: 12px;
border-radius: 6px;
height: 28px;
user-select: none;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
position: relative;
color: rgba(0, 0, 0, 0.65);
background-color: #fff;
border-color: #d9d9d9;
&:hover,
&:active,
&:focus {
color: #2db7f5;
background-color: #fff;
border-color: #2db7f5;
}
}
}
}
&-simple {
.@{prefixClass}-prev,
.@{prefixClass}-next {
border: none;
height: 24px;
line-height: 24px;
margin: 0;
font-size: 18px;
}
.@{prefixClass}-simple-pager {
float: left;
margin-right: 8px;
list-style: none;
.@{prefixClass}-slash {
margin: 0 10px;
}
input {
margin: 0 8px;
box-sizing: border-box;
background-color: #fff;
border-radius: 6px;
border: 1px solid #d9d9d9;
outline: none;
padding: 5px 8px;
min-height: 20px;
&:hover {
border-color: #2db7f5;
}
}
button {
display: inline-block;
margin: 0 8px;
font-weight: 500;
text-align: center;
touch-action: manipulation;
cursor: pointer;
background-image: none;
border: 1px solid transparent;
white-space: nowrap;
padding: 0 8px;
font-size: 12px;
border-radius: 6px;
height: 26px;
user-select: none;
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
position: relative;
color: rgba(0, 0, 0, 0.65);
background-color: #fff;
border-color: #d9d9d9;
&:hover,
&:active,
&:focus {
color: #2db7f5;
background-color: #fff;
border-color: #2db7f5;
}
}
}
}
}
@media only screen and (max-width: 1024px) {
.@{prefixClass}-item {
&-after-jump-prev,
&-before-jump-next {
display: none;
}
}
}