Merge remote-tracking branch 'next' into v2.3

pull/4499/head
tangjinzhou 2021-08-09 20:59:46 +08:00
commit 6dfb2e5184
55 changed files with 1176 additions and 913 deletions

View File

@ -10,7 +10,7 @@ jobs:
steps:
- name: Need Reproduce
if: github.event.label.name == '🤔 Need Reproduce'
uses: actions-cool/issues-helper@v1
uses: actions-cool/issues-helper@v1.2
with:
actions: 'create-comment'
issue-number: ${{ github.event.issue.number }}
@ -21,7 +21,7 @@ jobs:
- name: help wanted
if: github.event.label.name == 'help wanted'
uses: actions-cool/issues-helper@v1
uses: actions-cool/issues-helper@v1.2
with:
actions: 'create-comment'
issue-number: ${{ github.event.issue.number }}
@ -29,3 +29,15 @@ jobs:
Hello @${{ github.event.issue.user.login }}. We totally like your proposal/feedback, welcome to send us a Pull Request for it. Please send your Pull Request to proper branch, fill the Pull Request Template here, provide changelog/TypeScript/documentation/test cases if needed and make sure CI passed, we will review it soon. We appreciate your effort in advance and looking forward to your contribution!
你好 @${{ github.event.issue.user.login }},我们完全同意你的提议/反馈,欢迎直接在此仓库创建一个 Pull Request 来解决这个问题。请将 Pull Request 发到正确的分支,务必填写 Pull Request 内的预设模板,提供改动所需相应的 changelog、TypeScript 定义、测试用例、文档等,并确保 CI 通过,我们会尽快进行 Review提前感谢和期待您的贡献。
- name: Usage
if: github.event.label.name == 'Usage'
uses: actions-cool/issues-helper@v1.2
with:
actions: 'create-comment, close-issue'
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}, we use GitHub issues to trace bugs or discuss plans of Ant Design Vue. So, please don't ask usage questions here. You can try to open a new discussion in [antdv discussions](https://github.com/vueComponent/ant-design-vue/discussions), select `Q&A` to ask questions, also can ask questions on [Stack Overflow](http://stackoverflow.com/questions/) or [Segment Fault](https://segmentfault.com).
你好 @${{ github.event.issue.user.login }}Ant Design Vue Issue 板块是用于 bug 反馈与需求讨论的地方。请勿询问如何使用的问题,你可以试着在 [antdv discussions](https://github.com/vueComponent/ant-design-vue/discussions) 新开一个 discussion选择 `Q&A` 类别进行提问,也可以在 [Stack Overflow](http://stackoverflow.com/questions/) 或者 [Segment Fault](https://segmentfault.com/) 中提问。

20
.github/workflows/pr-labeled.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: PR Labeled
on:
pull_request_target:
types: [labeled]
jobs:
reply:
runs-on: ubuntu-latest
steps:
- name: Usage
if: github.event.label.name == 'Usage'
uses: actions-cool/issues-helper@v1.2
with:
actions: 'create-comment, close-issue'
issue-number: ${{ github.event.pull_request.number }}
body: |
Hello @${{ github.event.pull_request.user.login }}, we use GitHub PR to build and perfect of Ant Design Vue. So, please don't ask usage questions here. You can try to open a new discussion in [antdv discussions](https://github.com/vueComponent/ant-design-vue/discussions), select `Q&A` to ask questions, also can ask questions on [Stack Overflow](http://stackoverflow.com/questions/) or [Segment Fault](https://segmentfault.com).
你好 @${{ github.event.pull_request.user.login }}Ant Design Vue PR 是用于建设、完善项目的地方。请勿询问如何使用的问题,你可以试着在 [antdv discussions](https://github.com/vueComponent/ant-design-vue/discussions) 新开一个 discussion选择 `Q&A` 类别进行提问,也可以在 [Stack Overflow](http://stackoverflow.com/questions/) 或者 [Segment Fault](https://segmentfault.com/) 中提问。

View File

@ -10,6 +10,20 @@
---
## 2.2.3
`2021-08-07`
- 🌟 Use `position: sticky` for the fixed column of `Table` to improve performance and solve the problem of misalignment in some scenes [38569c](https://github.com/vueComponent/ant-design-vue/commit/38569c28c7eb4eaa34f2cc096982daea901062d4)
- 🌟 `Collapse` supports number type key [#4405](https://github.com/vueComponent/ant-design-vue/issues/4405)
- 🌟 Optimize the flickering problem of `Tabs` when selected under windows [#4241](https://github.com/vueComponent/ant-design-vue/issues/4241)
- 🌟 `InputPassword` supports global setting prefixCls [#4430](https://github.com/vueComponent/ant-design-vue/issues/4430)
- 🐞 Fix `Select` cannot scroll issue [#4396](https://github.com/vueComponent/ant-design-vue/issues/4396)
- 🐞 Fix `Badge` error reporting under ssr [#4384](https://github.com/vueComponent/ant-design-vue/issues/4384)
- 🐞 Fix the issue of invalid data fields in `Form` [#4435](https://github.com/vueComponent/ant-design-vue/issues/4435)
- 🐞 Fix an error when the child element of `FormItem` is a native label [#4383](https://github.com/vueComponent/ant-design-vue/issues/4383)
- 🐞 Fix the error when `TreeSelect` customize title through slot [#4459](https://github.com/vueComponent/ant-design-vue/issues/4459)
## 2.2.2
`2021-07-11`

View File

@ -10,6 +10,20 @@
---
## 2.2.3
`2021-08-07`
- 🌟 `Table` 固定列使用 `position: sticky` 提升性能,解决部分场景不对齐问题 [38569c](https://github.com/vueComponent/ant-design-vue/commit/38569c28c7eb4eaa34f2cc096982daea901062d4)
- 🌟 `Collapse` 支持 number 类型 key [#4405](https://github.com/vueComponent/ant-design-vue/issues/4405)
- 🌟 优化 `Tabs` 在 windows 下选中时闪动问题 [#4241](https://github.com/vueComponent/ant-design-vue/issues/4241)
- 🌟 `InputPassword` 支持全局设置 prefixCls [#4430](https://github.com/vueComponent/ant-design-vue/issues/4430)
- 🐞 修复 `Select` 无法滚动问题 [#4396](https://github.com/vueComponent/ant-design-vue/issues/4396)
- 🐞 修复 `Badge` 在 ssr 下报错问题 [#4384](https://github.com/vueComponent/ant-design-vue/issues/4384)
- 🐞 修复 `Form` 多出无效数据字段问题 [#4435](https://github.com/vueComponent/ant-design-vue/issues/4435)
- 🐞 修复 `FormItem` 子元素是原生标签时报错问题 [#4383](https://github.com/vueComponent/ant-design-vue/issues/4383)
- 🐞 修复 `TreeSelect` 通过 slot 自定义 title 时报错问题 [#4459](https://github.com/vueComponent/ant-design-vue/issues/4459)
## 2.2.2
`2021-07-11`

View File

@ -0,0 +1,41 @@
import type { Ref } from 'vue';
import { onBeforeUnmount, ref } from 'vue';
import wrapperRaf from '../raf';
export type Updater<State> = (prev: State) => State;
/**
* Execute code before next frame but async
*/
export function useLayoutState<State>(
defaultState: State,
): [Ref<State>, (updater: Updater<State>) => void] {
const stateRef = ref(defaultState);
let tempState = stateRef.value;
let updateBatchRef = [];
const rafRef = ref();
function setFrameState(updater: Updater<State>) {
wrapperRaf.cancel(rafRef.value);
updateBatchRef.push(updater);
rafRef.value = wrapperRaf(() => {
const prevBatch = updateBatchRef;
// const prevState = stateRef.value;
updateBatchRef = [];
prevBatch.forEach(batchUpdater => {
tempState = batchUpdater(tempState);
});
// if (tempState !== stateRef.value) {
stateRef.value = tempState;
// }
});
}
onBeforeUnmount(() => {
wrapperRaf.cancel(rafRef.value);
});
return [stateRef as Ref<State>, setFrameState];
}

View File

@ -15,7 +15,7 @@ const eventsName = `onCopy onCut onPaste onCompositionend onCompositionstart onC
onKeypress onKeyup onFocus onBlur onChange onInput onSubmit onClick onContextmenu onDoubleclick onDblclick
onDrag onDragend onDragenter onDragexit onDragleave onDragover onDragstart onDrop onMousedown
onMouseenter onMouseleave onMousemove onMouseout onMouseover onMouseup onSelect onTouchcancel
onTouchend onTouchmove onTouchstart onScroll onWheel onAbort onCanplay onCanplaythrough
onTouchend onTouchmove onTouchstart onTouchstartPassive onTouchmovePassive onScroll onWheel onAbort onCanplay onCanplaythrough
onDurationchange onEmptied onEncrypted onEnded onError onLoadeddata onLoadedmetadata
onLoadstart onPause onPlay onPlaying onProgress onRatechange onSeeked onSeeking onStalled onSuspend onTimeupdate onVolumechange onWaiting onLoad onError`;

View File

@ -339,9 +339,10 @@ export function isEmptyContent(c) {
export function isEmptyElement(c) {
return (
c.type === Comment ||
(c.type === Fragment && c.children.length === 0) ||
(c.type === Text && c.children.trim() === '')
c &&
(c.type === Comment ||
(c.type === Fragment && c.children.length === 0) ||
(c.type === Text && c.children.trim() === ''))
);
}

View File

@ -1,6 +1,5 @@
import type { App, PropType, VNodeChild, Plugin } from 'vue';
export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
// https://stackoverflow.com/questions/46176165/ways-to-get-string-literal-type-of-array-values-without-enum-overhead
export const tuple = <T extends string[]>(...args: T) => args;

View File

@ -114,7 +114,7 @@ export default defineComponent({
[`${prefixCls.value}-count-sm`]: props.size === 'small',
[`${prefixCls.value}-multiple-words`]:
!isDotRef.value && displayCount.value && displayCount.value.toString().length > 1,
[`${prefixCls.value}-status-${status}`]: !!status,
[`${prefixCls.value}-status-${props.status}`]: !!props.status,
[`${prefixCls.value}-status-${props.color}`]: isPresetColor(props.color),
}));

View File

@ -5,7 +5,7 @@ import { flattenChildren, getPropsSlot } from '../_util/props-util';
import warning from '../_util/warning';
import BreadcrumbItem from './BreadcrumbItem';
import Menu from '../menu';
import type { Omit, VueNode } from '../_util/type';
import type { VueNode } from '../_util/type';
import useConfigInject from '../_util/hooks/useConfigInject';
export interface Route {

View File

@ -1,4 +1,5 @@
import type { PropType, ExtractPropTypes, ComputedRef } from 'vue';
import { watch } from 'vue';
import { defineComponent, computed, nextTick, ref, watchEffect, onBeforeUnmount } from 'vue';
import cloneDeep from 'lodash-es/cloneDeep';
import PropTypes from '../_util/vue-types';
@ -271,16 +272,31 @@ export default defineComponent({
clearValidate,
resetField,
});
formContext.addField(eventKey, {
fieldValue,
fieldId,
let registered = false;
watch(
fieldName,
resetField,
clearValidate,
namePath,
validateRules,
rules: rulesRef,
});
val => {
if (val) {
if (!registered) {
registered = true;
formContext.addField(eventKey, {
fieldValue,
fieldId,
fieldName,
resetField,
clearValidate,
namePath,
validateRules,
rules: rulesRef,
});
}
} else {
registered = false;
formContext.removeField(eventKey);
}
},
{ immediate: true },
);
onBeforeUnmount(() => {
formContext.removeField(eventKey);
});
@ -306,7 +322,7 @@ export default defineComponent({
const children = flattenChildren(slots.default?.());
let firstChildren = children[0];
if (fieldName.value && props.autoLink && isValidElement(firstChildren)) {
const originalEvents = firstChildren.props;
const originalEvents = firstChildren.props || {};
const originalBlur = originalEvents.onBlur;
const originalChange = originalEvents.onChange;
firstChildren = cloneElement(firstChildren, {

View File

@ -108,9 +108,9 @@ function useForm(
resetFields: (newValues?: Props) => void;
validate: <T = any>(names?: namesType, option?: validateOptions) => Promise<T>;
validateField: (
name?: string,
value?: any,
rules?: [Record<string, unknown>],
name: string,
value: any,
rules: Record<string, unknown>[],
option?: validateOptions,
) => Promise<RuleError[]>;
mergeValidateInfo: (items: ValidateInfo | ValidateInfo[]) => ValidateInfo;
@ -236,8 +236,8 @@ function useForm(
const validateField = (
name: string,
value: any,
rules: any,
option: validateOptions,
rules: Record<string, unknown>[],
option: validateOptions = {},
): Promise<RuleError[]> => {
const promise = validateRules(
[name],

View File

@ -7,7 +7,8 @@ import EyeInvisibleOutlined from '@ant-design/icons-vue/EyeInvisibleOutlined';
import inputProps from './inputProps';
import PropTypes from '../_util/vue-types';
import BaseMixin from '../_util/BaseMixin';
import { defineComponent } from 'vue';
import { defineComponent, inject } from 'vue';
import { defaultConfigProvider } from '../config-provider';
const ActionMap = {
click: 'onClick',
@ -20,8 +21,8 @@ export default defineComponent({
inheritAttrs: false,
props: {
...inputProps,
prefixCls: PropTypes.string.def('ant-input-password'),
inputPrefixCls: PropTypes.string.def('ant-input'),
prefixCls: PropTypes.string,
inputPrefixCls: PropTypes.string,
action: PropTypes.string.def('click'),
visibilityToggle: PropTypes.looseBool.def(true),
iconRender: PropTypes.func.def((visible: boolean) =>
@ -31,6 +32,7 @@ export default defineComponent({
setup() {
return {
input: null,
configProvider: inject('configProvider', defaultConfigProvider),
};
},
data() {
@ -56,8 +58,8 @@ export default defineComponent({
visible: !this.visible,
});
},
getIcon() {
const { prefixCls, action } = this.$props;
getIcon(prefixCls) {
const { action } = this.$props;
const iconTrigger = ActionMap[action] || '';
const iconRender = this.$slots.iconRender || this.$props.iconRender;
const icon = iconRender(this.visible);
@ -81,8 +83,8 @@ export default defineComponent({
},
render() {
const {
prefixCls,
inputPrefixCls,
prefixCls: customizePrefixCls,
inputPrefixCls: customizeInputPrefixCls,
size,
suffix,
action,
@ -91,7 +93,12 @@ export default defineComponent({
...restProps
} = getOptionProps(this);
const { class: className } = this.$attrs;
const suffixIcon = visibilityToggle && this.getIcon();
const getPrefixCls = this.configProvider.getPrefixCls;
const inputPrefixCls = getPrefixCls('input', customizeInputPrefixCls);
const prefixCls = getPrefixCls('input-password', customizePrefixCls);
const suffixIcon = visibilityToggle && this.getIcon(prefixCls);
const inputClassName = classNames(prefixCls, className, {
[`${prefixCls}-${size}`]: !!size,
});

View File

@ -1,6 +1,7 @@
import { computed, defineComponent, ref, watch } from 'vue';
import Transition from '../../_util/transition';
import { useInjectMenu, MenuContextProvider } from './hooks/useMenuContext';
import type { MenuMode } from './interface';
import SubMenuList from './SubMenuList';
export default defineComponent({
@ -12,7 +13,7 @@ export default defineComponent({
keyPath: Array,
},
setup(props, { slots }) {
const fixedMode = computed(() => 'inline');
const fixedMode = computed<MenuMode>(() => 'inline');
const { motion, mode, defaultMotions } = useInjectMenu();
const sameModeRef = computed(() => mode.value === fixedMode.value);
const destroy = ref(!sameModeRef.value);
@ -43,12 +44,7 @@ export default defineComponent({
return null;
}
return (
<MenuContextProvider
props={{
mode: fixedMode,
locked: !sameModeRef.value,
}}
>
<MenuContextProvider mode={fixedMode.value}>
<Transition {...mergedMotion.value}>
<SubMenuList
v-show={mergedOpen.value}

View File

@ -367,13 +367,13 @@ export default defineComponent({
siderCollapsed,
defaultMotions: computed(() => (isMounted.value ? defaultMotions : null)),
motion: computed(() => (isMounted.value ? props.motion : null)),
overflowDisabled: computed(() => undefined),
overflowDisabled: ref(undefined),
onOpenChange: onInternalOpenChange,
onItemClick: onInternalClick,
registerMenuInfo,
unRegisterMenuInfo,
selectedSubMenuEventKeys,
isRootMenu: true,
isRootMenu: ref(true),
expandIcon: props.expandIcon || slots.expandIcon,
});
return () => {
@ -391,7 +391,7 @@ export default defineComponent({
// Always wrap provider to avoid sub node re-mount
<MenuContextProvider
key={child.key}
props={{ overflowDisabled: computed(() => index > lastVisibleIndex.value) }}
overflowDisabled={index > lastVisibleIndex.value}
>
{child}
</MenuContextProvider>

View File

@ -80,7 +80,7 @@ export default defineComponent({
)}
stretch={mode === 'horizontal' ? 'minWidth' : null}
getPopupContainer={
isRootMenu ? getPopupContainer.value : triggerNode => triggerNode.parentNode
isRootMenu.value ? getPopupContainer.value : triggerNode => triggerNode.parentNode
}
builtinPlacements={placement.value}
popupPlacement={popupPlacement.value}

View File

@ -268,12 +268,7 @@ export default defineComponent({
onVisibleChange={onPopupVisibleChange}
v-slots={{
popup: ({ visible }) => (
<MenuContextProvider
props={{
mode: subMenuTriggerModeRef,
isRootMenu: false,
}}
>
<MenuContextProvider mode={subMenuTriggerModeRef.value} isRootMenu={false}>
<Transition {...mergedMotion.value}>
<SubMenuList v-show={visible} id={popupId} ref={popupRef}>
{slots.default?.()}
@ -292,7 +287,7 @@ export default defineComponent({
titleNode = <PopupTrigger>{titleNode}</PopupTrigger>;
}
return (
<MenuContextProvider props={{ mode: renderMode }}>
<MenuContextProvider mode={renderMode.value}>
<Overflow.Item
component="li"
{...attrs}

View File

@ -1,6 +1,6 @@
import type { Key } from '../../../_util/type';
import type { ComputedRef, CSSProperties, InjectionKey, Ref, UnwrapRef } from 'vue';
import { defineComponent, inject, provide } from 'vue';
import type { ComputedRef, CSSProperties, InjectionKey, PropType, Ref, UnwrapRef } from 'vue';
import { defineComponent, inject, provide, toRef } from 'vue';
import type {
BuiltinPlacements,
MenuClickEventHandler,
@ -19,7 +19,7 @@ export interface StoreMenuInfo {
parentKeys: ComputedRef<Key[]>;
}
export interface MenuContextProps {
isRootMenu: boolean;
isRootMenu: Ref<boolean>;
store: Ref<Record<string, UnwrapRef<StoreMenuInfo>>>;
registerMenuInfo: (key: string, info: StoreMenuInfo) => void;
@ -31,8 +31,6 @@ export interface MenuContextProps {
selectedSubMenuEventKeys: Ref<string[]>;
rtl?: ComputedRef<boolean>;
locked?: Ref<boolean>;
inlineCollapsed: Ref<boolean>;
antdMenuTheme?: ComputedRef<MenuTheme>;
@ -44,7 +42,7 @@ export interface MenuContextProps {
// // Disabled
disabled?: ComputedRef<boolean>;
// // Used for overflow only. Prevent hidden node trigger open
overflowDisabled?: ComputedRef<boolean>;
overflowDisabled?: Ref<boolean>;
// // Active
activeKeys: Ref<Key[]>;
@ -108,10 +106,25 @@ const MenuContextProvider = defineComponent({
name: 'MenuContextProvider',
inheritAttrs: false,
props: {
props: Object,
mode: { type: String as PropType<MenuMode>, default: undefined },
overflowDisabled: { type: Boolean, default: undefined },
isRootMenu: { type: Boolean, default: undefined },
},
setup(props, { slots }) {
useProvideMenu({ ...useInjectMenu(), ...props.props });
const menuContext = useInjectMenu();
const newContext = { ...menuContext };
// 确保传入的属性不会动态增删
// 不需要 watch 变化
if (props.mode !== undefined) {
newContext.mode = toRef(props, 'mode');
}
if (props.isRootMenu !== undefined) {
newContext.isRootMenu = toRef(props, 'isRootMenu');
}
if (props.overflowDisabled !== undefined) {
newContext.overflowDisabled = toRef(props, 'overflowDisabled');
}
useProvideMenu(newContext);
return () => slots.default?.();
},
});

View File

@ -1,6 +1,4 @@
import { defineComponent, onBeforeUnmount, onMounted, onUpdated, ref } from 'vue';
import moment from 'moment';
import interopDefault from '../_util/interopDefault';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import Statistic, { statisticProps } from './Statistic';
import type { countdownValueType, FormatConfig } from './utils';
@ -9,7 +7,7 @@ import { formatCountdown as formatCD } from './utils';
const REFRESH_INTERVAL = 1000 / 30;
function getTime(value?: countdownValueType) {
return interopDefault(moment)(value).valueOf();
return new Date(value as any).getTime();
}
export default defineComponent({

View File

@ -12,11 +12,11 @@ exports[`Table.pagination renders pagination correctly 1`] = `
<div class="ant-table-body">
<table class="">
<colgroup>
<col>
<col data-key="name">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class="ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="0" colspan="1" colend="0" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
@ -40,8 +40,6 @@ exports[`Table.pagination renders pagination correctly 1`] = `
</div>
<!---->
<!---->
<!---->
<!---->
</div>
</div>
<ul unselectable="unselectable" class="ant-pagination my-page ant-table-pagination">

View File

@ -13,19 +13,19 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
<div class="ant-table-body">
<table class="">
<colgroup>
<col class="ant-table-selection-col">
<col>
<col data-key="selection-column" class="ant-table-selection-col">
<col data-key="name">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class="ant-table-fixed-columns-in-body ant-table-selection-column"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title"><div class="ant-table-selection"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<th colstart="0" colspan="1" colend="0" rowspan="1" class="ant-table-selection-column"><span class="ant-table-header-column"><div><span class="ant-table-column-title"><div class="ant-table-selection"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label>
<!---->
</div></span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class="ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="1" colspan="1" colend="1" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
@ -33,7 +33,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
</thead>
<tbody class="ant-table-tbody">
<tr class="ant-table-row ant-table-row-level-0" data-row-key="0">
<td class="ant-table-fixed-columns-in-body ant-table-selection-column">
<td class="ant-table-selection-column">
<!---->
<!----><span><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label></span>
@ -44,7 +44,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
</td>
</tr>
<tr class="ant-table-row ant-table-row-level-0" data-row-key="1">
<td class="ant-table-fixed-columns-in-body ant-table-selection-column">
<td class="ant-table-selection-column">
<!---->
<!----><span><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label></span>
@ -55,7 +55,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
</td>
</tr>
<tr class="ant-table-row ant-table-row-level-0" data-row-key="2">
<td class="ant-table-fixed-columns-in-body ant-table-selection-column">
<td class="ant-table-selection-column">
<!---->
<!----><span><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label></span>
@ -66,7 +66,7 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
</td>
</tr>
<tr class="ant-table-row ant-table-row-level-0" data-row-key="3">
<td class="ant-table-fixed-columns-in-body ant-table-selection-column">
<td class="ant-table-selection-column">
<!---->
<!----><span><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label></span>
@ -82,62 +82,8 @@ exports[`Table.rowSelection fix selection column on the left 1`] = `
<!---->
<!---->
</div>
<div class="ant-table-fixed-left">
<!---->
<div class="ant-table-body-outer">
<div class="ant-table-body-inner">
<table class="ant-table-fixed">
<colgroup>
<col class="ant-table-selection-col">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class="ant-table-selection-column ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title"><div class="ant-table-selection"><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label>
<!---->
</div></span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
</tr>
</thead>
<tbody class="ant-table-tbody">
<tr class="ant-table-row ant-table-row-level-0" data-row-key="0">
<td class="ant-table-selection-column">
<!---->
<!----><span><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label></span>
</td>
</tr>
<tr class="ant-table-row ant-table-row-level-0" data-row-key="1">
<td class="ant-table-selection-column">
<!---->
<!----><span><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label></span>
</td>
</tr>
<tr class="ant-table-row ant-table-row-level-0" data-row-key="2">
<td class="ant-table-selection-column">
<!---->
<!----><span><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label></span>
</td>
</tr>
<tr class="ant-table-row ant-table-row-level-0" data-row-key="3">
<td class="ant-table-selection-column">
<!---->
<!----><span><label class="ant-checkbox-wrapper"><span class="ant-checkbox"><input type="checkbox" class="ant-checkbox-input"><span class="ant-checkbox-inner"></span></span>
<!----></label></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<!---->
</div>
</div>
<ul unselectable="unselectable" 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>

View File

@ -3,7 +3,7 @@
exports[`Table.sorter renders sorter icon correctly 1`] = `
<thead class="ant-table-thead">
<tr>
<th class="ant-table-column-has-actions ant-table-column-has-sorters ant-table-row-cell-last"><span class="ant-table-header-column"><div class="ant-table-column-sorters"><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><div title="Sort" class="ant-table-column-sorter-inner ant-table-column-sorter-inner-full"><span role="img" aria-label="caret-up" class="anticon anticon-caret-up ant-table-column-sorter-up off"><svg focusable="false" class="" data-icon="caret-up" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"></path></svg></span><span role="img" aria-label="caret-down" class="anticon anticon-caret-down ant-table-column-sorter-down off"><svg focusable="false" class="" data-icon="caret-down" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"></path></svg></span></div></span></div></span>
<th colstart="0" colspan="1" colend="0" rowspan="1" class="ant-table-column-has-actions ant-table-column-has-sorters"><span class="ant-table-header-column"><div class="ant-table-column-sorters"><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><div title="Sort" class="ant-table-column-sorter-inner ant-table-column-sorter-inner-full"><span role="img" aria-label="caret-up" class="anticon anticon-caret-up ant-table-column-sorter-up off"><svg focusable="false" class="" data-icon="caret-up" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M858.9 689L530.5 308.2c-9.4-10.9-27.5-10.9-37 0L165.1 689c-12.2 14.2-1.2 35 18.5 35h656.8c19.7 0 30.7-20.8 18.5-35z"></path></svg></span><span role="img" aria-label="caret-down" class="anticon anticon-caret-down ant-table-column-sorter-down off"><svg focusable="false" class="" data-icon="caret-down" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="0 0 1024 1024"><path d="M840.4 300H183.6c-19.7 0-30.7 20.8-18.5 35l328.4 380.8c9.4 10.9 27.5 10.9 37 0L858.9 335c12.2-14.2 1.2-35-18.5-35z"></path></svg></span></div></span></div></span>
<!---->
</th>
</tr>

View File

@ -12,16 +12,16 @@ exports[`Table align column should not override cell style 1`] = `
<div class="ant-table-body">
<table class="">
<colgroup>
<col>
<col>
<col data-key="name">
<col data-key="age">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="0" colspan="1" colend="0" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th style="text-align: center;" class="ant-table-align-center ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Age</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="1" colspan="1" colend="1" rowspan="1" style="text-align: center;" class="ant-table-align-center"><span class="ant-table-header-column"><div><span class="ant-table-column-title">Age</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
@ -55,8 +55,6 @@ exports[`Table align column should not override cell style 1`] = `
</div>
<!---->
<!---->
<!---->
<!---->
</div>
</div>
<ul unselectable="unselectable" class="ant-pagination ant-table-pagination">
@ -83,27 +81,27 @@ exports[`Table renders JSX correctly 1`] = `
<div class="ant-table-body">
<table class="">
<colgroup>
<col>
<col>
<col>
<col data-key="firstName">
<col data-key="lastName">
<col data-key="age">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th colspan="2" class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="0" hassubcolumns="true" colspan="2" colend="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Name</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th rowspan="2" class="ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Age</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="2" rowspan="2" colspan="1" colend="2" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Age</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
</tr>
<tr>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">First Name</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="0" colspan="1" colend="0" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">First Name</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Last Name</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="1" colspan="1" colend="1" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Last Name</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
@ -143,8 +141,6 @@ exports[`Table renders JSX correctly 1`] = `
</div>
<!---->
<!---->
<!---->
<!---->
</div>
</div>
</div>

View File

@ -12,45 +12,45 @@ exports[`Table renders empty table 1`] = `
<div class="ant-table-body">
<table class="">
<colgroup>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col data-key="1">
<col data-key="2">
<col data-key="3">
<col data-key="4">
<col data-key="5">
<col data-key="6">
<col data-key="7">
<col data-key="8">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 1</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="0" colspan="1" colend="0" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 1</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 2</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="1" colspan="1" colend="1" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 2</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 3</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="2" colspan="1" colend="2" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 3</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 4</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="3" colspan="1" colend="3" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 4</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 5</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="4" colspan="1" colend="4" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 5</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 6</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="5" colspan="1" colend="5" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 6</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 7</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="6" colspan="1" colend="6" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 7</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
<th class="ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 8</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="7" colspan="1" colend="7" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 8</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
</tr>
@ -74,8 +74,6 @@ exports[`Table renders empty table 1`] = `
</div>
</div>
<!---->
<!---->
<!---->
</div>
</div>
</div>
@ -95,45 +93,45 @@ exports[`Table renders empty table with custom emptyText 1`] = `
<div class="ant-table-body">
<table class="">
<colgroup>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col data-key="1">
<col data-key="2">
<col data-key="3">
<col data-key="4">
<col data-key="5">
<col data-key="6">
<col data-key="7">
<col data-key="8">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 1</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="0" colspan="1" colend="0" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 1</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 2</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="1" colspan="1" colend="1" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 2</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 3</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="2" colspan="1" colend="2" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 3</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 4</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="3" colspan="1" colend="3" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 4</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 5</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="4" colspan="1" colend="4" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 5</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 6</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="5" colspan="1" colend="5" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 6</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 7</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="6" colspan="1" colend="6" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 7</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
<th class="ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 8</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="7" colspan="1" colend="7" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 8</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
</tr>
@ -143,8 +141,6 @@ exports[`Table renders empty table with custom emptyText 1`] = `
</div>
<div class="ant-table-placeholder">custom empty text </div>
<!---->
<!---->
<!---->
</div>
</div>
</div>
@ -165,58 +161,58 @@ exports[`Table renders empty table with fixed columns 1`] = `
<div class="ant-table-body">
<table class="">
<colgroup>
<col style="width: 100px; min-width: 100px;">
<col style="width: 100px; min-width: 100px;">
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col style="width: 100px; min-width: 100px;">
<col data-key="name" style="width: 100px; min-width: 100px;">
<col data-key="age" style="width: 100px; min-width: 100px;">
<col data-key="1">
<col data-key="2">
<col data-key="3">
<col data-key="4">
<col data-key="5">
<col data-key="6">
<col data-key="7">
<col data-key="8">
<col data-key="address" style="width: 100px; min-width: 100px;">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class="ant-table-fixed-columns-in-body ant-table-row-cell-break-word"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Full Name</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="0" colspan="1" colend="0" rowspan="1" class="ant-table-row-cell-break-word"><span class="ant-table-header-column"><div><span class="ant-table-column-title">Full Name</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class="ant-table-fixed-columns-in-body ant-table-row-cell-break-word"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Age</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="1" colspan="1" colend="1" rowspan="1" class="ant-table-row-cell-break-word"><span class="ant-table-header-column"><div><span class="ant-table-column-title">Age</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 1</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="2" colspan="1" colend="2" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 1</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 2</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="3" colspan="1" colend="3" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 2</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 3</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="4" colspan="1" colend="4" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 3</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 4</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="5" colspan="1" colend="5" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 4</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 5</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="6" colspan="1" colend="6" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 5</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 6</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="7" colspan="1" colend="7" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 6</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 7</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="8" colspan="1" colend="8" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 7</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 8</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="9" colspan="1" colend="9" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 8</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
<th class="ant-table-fixed-columns-in-body ant-table-row-cell-break-word ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Action</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="10" colspan="1" colend="10" rowspan="1" class="ant-table-row-cell-break-word"><span class="ant-table-header-column"><div><span class="ant-table-column-title">Action</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
</tr>
@ -241,53 +237,6 @@ exports[`Table renders empty table with fixed columns 1`] = `
</div>
<!---->
</div>
<div class="ant-table-fixed-left">
<!---->
<div class="ant-table-body-outer">
<div class="ant-table-body-inner">
<table class="ant-table-fixed" style="width: 200px;">
<colgroup>
<col style="width: 100px; min-width: 100px;">
<col style="width: 100px; min-width: 100px;">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class="ant-table-row-cell-break-word"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Full Name</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class="ant-table-row-cell-break-word ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Age</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
</tr>
</thead>
<tbody class="ant-table-tbody"></tbody>
</table>
</div>
</div>
</div>
<div class="ant-table-fixed-right">
<!---->
<div class="ant-table-body-outer">
<div class="ant-table-body-inner">
<table class="ant-table-fixed" style="width: 100px;">
<colgroup>
<col style="width: 100px; min-width: 100px;">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class="ant-table-row-cell-break-word ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Action</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
</tr>
</thead>
<tbody class="ant-table-tbody"></tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
@ -311,45 +260,45 @@ exports[`Table renders empty table without emptyText when loading 1`] = `
<div class="ant-table-body">
<table class="">
<colgroup>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col>
<col data-key="1">
<col data-key="2">
<col data-key="3">
<col data-key="4">
<col data-key="5">
<col data-key="6">
<col data-key="7">
<col data-key="8">
</colgroup>
<thead class="ant-table-thead">
<tr>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 1</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="0" colspan="1" colend="0" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 1</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 2</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="1" colspan="1" colend="1" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 2</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 3</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="2" colspan="1" colend="2" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 3</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 4</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="3" colspan="1" colend="3" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 4</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 5</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="4" colspan="1" colend="4" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 5</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 6</span><span class="ant-table-column-sorter"><!----></span>
<th colstart="5" colspan="1" colend="5" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 6</span><span class="ant-table-column-sorter"><!----></span>
</div></span>
<!---->
</th>
<th class=""><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 7</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="6" colspan="1" colend="6" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 7</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
<th class="ant-table-row-cell-last"><span class="ant-table-header-column"><div class=""><span class="ant-table-column-title">Column 8</span><span class="ant-table-column-sorter"><!----></span></div></span>
<th colstart="7" colspan="1" colend="7" rowspan="1" class=""><span class="ant-table-header-column"><div><span class="ant-table-column-title">Column 8</span><span class="ant-table-column-sorter"><!----></span></div></span>
<!---->
</th>
</tr>
@ -373,8 +322,6 @@ exports[`Table renders empty table without emptyText when loading 1`] = `
</div>
</div>
<!---->
<!---->
<!---->
</div>
</div>
</div>

View File

@ -1,7 +1,6 @@
import { reactive, defineComponent, nextTick, computed, watch } from 'vue';
import FilterFilled from '@ant-design/icons-vue/FilterFilled';
import Menu, { SubMenu, MenuItem } from '../menu';
import closest from '../_util/dom-closest';
import classNames from '../_util/classNames';
import shallowequal from '../_util/shallowequal';
import Dropdown from '../dropdown';
@ -9,7 +8,7 @@ import Checkbox from '../checkbox';
import Radio from '../radio';
import FilterDropdownMenuWrapper from './FilterDropdownMenuWrapper';
import { FilterMenuProps } from './interface';
import { isValidElement, findDOMNode } from '../_util/props-util';
import { isValidElement } from '../_util/props-util';
import initDefaultProps from '../_util/props-util/initDefaultProps';
import { cloneElement } from '../_util/vnode';
import BaseMixin2 from '../_util/BaseMixin2';
@ -67,33 +66,9 @@ export default defineComponent({
// );
return state;
},
mounted() {
const { column } = this;
nextTick(() => {
this.setNeverShown(column);
});
},
updated() {
const { column } = this;
nextTick(() => {
this.setNeverShown(column);
});
},
methods: {
getDropdownVisible() {
return this.neverShown ? false : this.sVisible;
},
setNeverShown(column) {
const rootNode = findDOMNode(this);
const filterBelongToScrollBody = !!closest(rootNode, `.ant-table-scroll`);
if (filterBelongToScrollBody) {
// When fixed column have filters, there will be two dropdown menus
// Filter dropdown menu inside scroll body should never be shown
// To fix https://github.com/ant-design/ant-design/issues/5010 and
// https://github.com/ant-design/ant-design/issues/7909
this.neverShown = !!column.fixed;
}
return !!this.sVisible;
},
setSelectedKeys({ selectedKeys }) {

View File

@ -615,15 +615,6 @@
overflow-x: hidden;
table {
min-width: 100%;
// https://github.com/ant-design/ant-design/issues/14545
// https://github.com/ant-design/ant-design/issues/19491
.@{table-prefix-cls}-fixed-columns-in-body:not([colspan]) {
color: transparent;
& > * {
visibility: hidden;
}
}
}
}
@ -776,6 +767,96 @@
&-row[class*='@{table-prefix-cls}-row-level-0'] .@{table-prefix-cls}-selection-column > span {
display: inline-block;
}
// ============================ Fixed =============================
&-cell-fix-left,
&-cell-fix-right {
position: -webkit-sticky !important;
position: sticky !important;
z-index: @zindex-table-fixed;
background: @table-bg;
}
&-cell-fix-left-first::after,
&-cell-fix-left-last::after {
position: absolute;
top: 0;
right: 0;
bottom: -1px;
width: 30px;
transform: translateX(100%);
transition: box-shadow 0.3s;
content: '';
pointer-events: none;
}
&-cell-fix-right-first::after,
&-cell-fix-right-last::after {
position: absolute;
top: 0;
bottom: -1px;
left: 0;
width: 30px;
transform: translateX(-100%);
transition: box-shadow 0.3s;
content: '';
pointer-events: none;
}
.@{table-prefix-cls}-container {
&::before,
&::after {
position: absolute;
top: 0;
bottom: 0;
z-index: 1;
width: 30px;
transition: box-shadow 0.3s;
content: '';
pointer-events: none;
}
&::before {
left: 0;
}
&::after {
right: 0;
}
}
&-ping-left {
&:not(.@{table-prefix-cls}-has-fix-left) .@{table-prefix-cls}-container {
position: relative;
&::before {
box-shadow: inset 10px 0 8px -8px darken(@shadow-color, 5%);
}
}
.@{table-prefix-cls}-cell-fix-left-first::after,
.@{table-prefix-cls}-cell-fix-left-last::after {
box-shadow: inset 10px 0 8px -8px darken(@shadow-color, 5%);
}
.@{table-prefix-cls}-cell-fix-left-last::before {
background-color: transparent !important;
}
}
&-ping-right {
&:not(.@{table-prefix-cls}-has-fix-right) .@{table-prefix-cls}-container {
position: relative;
&::after {
box-shadow: inset -10px 0 8px -8px darken(@shadow-color, 5%);
}
}
.@{table-prefix-cls}-cell-fix-right-first::after,
.@{table-prefix-cls}-cell-fix-right-last::after {
box-shadow: inset -10px 0 8px -8px darken(@shadow-color, 5%);
}
}
}
.@{table-prefix-cls}-filter-dropdown,

View File

@ -212,7 +212,10 @@
&-active {
color: @tabs-highlight-color;
font-weight: 500;
// https://github.com/vueComponent/ant-design-vue/issues/4241
// Remove font-weight to keep pace with antd (#4241)
text-shadow: 0 0 0.25px currentColor;
// font-weight: 500;
}
&-disabled {

View File

@ -93,10 +93,10 @@ const TreeSelect = defineComponent({
let newLabel = typeof label === 'function' ? label() : label;
let newTitle = typeof title === 'function' ? title() : title;
if (!newLabel && slots.label && $slots[slots.label]) {
newLabel = <>{$slots.label(item)}</>;
newLabel = <>{$slots[slots.label](item)}</>;
}
if (!newTitle && slots.title && $slots[slots.title]) {
newTitle = <>{$slots.title(item)}</>;
newTitle = <>{$slots[slots.title](item)}</>;
}
const treeNodeProps = {
...item,

View File

@ -35,7 +35,7 @@ exports[`Upload List handle error 2`] = `
exports[`Upload List should be uploading when upload a file 1`] = `<span><div class="ant-upload ant-upload-select ant-upload-select-text"><span role="button" tabindex="0" class="ant-upload"><input type="file" accept="" style="display: none;"><button>upload</button></span></div><span tag="div" class="ant-upload-list ant-upload-list-text"></span></span>`;
exports[`Upload List should non-image format file preview 1`] = `
<span class=""><div class="ant-upload ant-upload-select ant-upload-select-picture"><!----></div><div class="ant-upload-list ant-upload-list-picture"><div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/aaa.zip" target="_blank" rel="noopener noreferrer"><span role="img" aria-label="file" class="anticon anticon-file ant-upload-list-item-icon"><svg focusable="false" class="" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494z"></path></svg></span></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="not-image" href="https://cdn.xxx.com/aaa.zip">not-image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
<span><div class="ant-upload ant-upload-select ant-upload-select-picture"><!----></div><div class="ant-upload-list ant-upload-list-picture"><div class=""><span><div class="ant-upload-list-item ant-upload-list-item-done ant-upload-list-item-list-type-picture"><div class="ant-upload-list-item-info"><span><a class="ant-upload-list-item-thumbnail" href="https://cdn.xxx.com/aaa.zip" target="_blank" rel="noopener noreferrer"><span role="img" aria-label="file" class="anticon anticon-file ant-upload-list-item-icon"><svg focusable="false" class="" data-icon="file" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M854.6 288.6L639.4 73.4c-6-6-14.1-9.4-22.6-9.4H192c-17.7 0-32 14.3-32 32v832c0 17.7 14.3 32 32 32h640c17.7 0 32-14.3 32-32V311.3c0-8.5-3.4-16.7-9.4-22.7zM790.2 326H602V137.8L790.2 326zm1.8 562H232V136h302v216a42 42 0 0042 42h216v494z"></path></svg></span></a><a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name ant-upload-list-item-name-icon-count-1" title="not-image" href="https://cdn.xxx.com/aaa.zip">not-image</a><span class="ant-upload-list-item-card-actions picture"><!----><a title="Remove file"><span title="Remove file" tabindex="-1" role="img" aria-label="delete" class="anticon anticon-delete"><svg focusable="false" class="" data-icon="delete" width="1em" height="1em" fill="currentColor" aria-hidden="true" viewBox="64 64 896 896"><path d="M360 184h-8c4.4 0 8-3.6 8-8v8h304v-8c0 4.4 3.6 8 8 8h-8v72h72v-80c0-35.3-28.7-64-64-64H352c-35.3 0-64 28.7-64 64v80h72v-72zm504 72H160c-17.7 0-32 14.3-32 32v32c0 4.4 3.6 8 8 8h60.4l24.7 523c1.6 34.1 29.8 61 63.9 61h454c34.2 0 62.3-26.8 63.9-61l24.7-523H888c4.4 0 8-3.6 8-8v-32c0-17.7-14.3-32-32-32zM731.3 840H292.7l-24.2-512h487l-24.2 512z"></path></svg></span></a></span></span></div>
<!---->
<!---->
</div></span></div>

View File

@ -15,7 +15,9 @@ import { defineComponent } from 'vue';
function _toArray(activeKey) {
let currentActiveKey = activeKey;
if (!Array.isArray(currentActiveKey)) {
currentActiveKey = currentActiveKey ? [currentActiveKey] : [];
const activeKeyType = typeof currentActiveKey;
currentActiveKey =
activeKeyType === 'number' || activeKeyType === 'string' ? [currentActiveKey] : [];
}
return currentActiveKey.map(key => String(key));
}
@ -76,7 +78,7 @@ export default defineComponent({
const { prefixCls, accordion, destroyInactivePanel, expandIcon } = this.$props;
// If there is no key provide, use the panel order as default key
const key = child.key || String(index);
const key = String(child.key ?? index);
const { header, headerClass, disabled } = getPropsData(child);
let isActive = false;

View File

@ -439,6 +439,15 @@ const Drawer = defineComponent({
onKeydown: open && keyboard ? this.onKeyDown : noop,
style: { ...wrapStyle, ...style },
};
// 跑用例用
const touchEvents = {
[supportsPassive ? 'onTouchstartPassive' : 'onTouchstart']: open
? this.removeStartHandler
: noop,
[supportsPassive ? 'onTouchmovePassive' : 'onTouchmove']: open
? this.removeMoveHandler
: noop,
};
return (
<div
ref={c => {
@ -475,8 +484,7 @@ const Drawer = defineComponent({
ref={c => {
this.contentDom = c;
}}
onTouchstart={open ? this.removeStartHandler : noop} // 跑用例用
onTouchmove={open ? this.removeMoveHandler : noop} // 跑用例用
{...touchEvents}
>
{children}
</div>

View File

@ -6,6 +6,7 @@ import classNames from '../../_util/classNames';
import KeyCode from '../../_util/KeyCode';
import InputHandler from './InputHandler';
import { defineComponent } from 'vue';
import supportsPassive from '../../_util/supportsPassive';
function preventDefault(e) {
e.preventDefault();
@ -699,11 +700,13 @@ export default defineComponent({
let downEvents;
if (useTouch) {
upEvents = {
onTouchstart: editable && !upDisabledClass && this.up,
[supportsPassive ? 'onTouchstartPassive' : 'onTouchstart']:
editable && !upDisabledClass && this.up,
onTouchend: this.stop,
};
downEvents = {
onTouchstart: editable && !downDisabledClass && this.down,
[supportsPassive ? 'onTouchstartPassive' : 'onTouchstart']:
editable && !downDisabledClass && this.down,
onTouchend: this.stop,
};
} else {

View File

@ -5,6 +5,7 @@ import warning from '../../_util/warning';
import BaseMixin from '../../_util/BaseMixin';
import { ITouchProps } from './PropTypes';
import { defineComponent } from 'vue';
import supportsPassive from '../../_util/supportsPassive';
export default defineComponent({
name: 'TouchFeedback',
@ -76,8 +77,8 @@ export default defineComponent({
const events = disabled
? undefined
: {
onTouchstart: this.onTouchStart,
onTouchmove: this.onTouchMove,
[supportsPassive ? 'onTouchstartPassive' : 'onTouchstart']: this.onTouchStart,
[supportsPassive ? 'onTouchmovePassive' : 'onTouchmove']: this.onTouchMove,
onTouchend: this.onTouchEnd,
onTouchcancel: this.onTouchCancel,
onMousedown: this.onMouseDown,

View File

@ -22,7 +22,9 @@ export const mentionsProps = {
placement: PropTypes.oneOf(PlaceMent),
character: PropTypes.any,
characterRender: PropTypes.func,
filterOption: PropTypes.func,
filterOption: {
type: [Boolean, Function] as PropType<typeof defaultFilterOption | false>,
},
validateSearch: PropTypes.func,
getPopupContainer: {
type: Function as PropType<() => HTMLElement>,

View File

@ -23,6 +23,7 @@ import {
import Track from './track';
import Dots from './dots';
import { PrevArrow, NextArrow } from './arrows';
import supportsPassive from '../../_util/supportsPassive';
function noop() {}
@ -694,8 +695,11 @@ export default {
onMousemove: this.dragging && touchMove ? this.swipeMove : noop,
onMouseup: touchMove ? this.swipeEnd : noop,
onMouseleave: this.dragging && touchMove ? this.swipeEnd : noop,
onTouchstart: touchMove ? this.swipeStart : noop,
onTouchmove: this.dragging && touchMove ? this.swipeMove : noop,
[supportsPassive ? 'onTouchstartPassive' : 'onTouchstart']: touchMove
? this.swipeStart
: noop,
[supportsPassive ? 'onTouchmovePassive' : 'onTouchmove']:
this.dragging && touchMove ? this.swipeMove : noop,
onTouchend: touchMove ? this.swipeEnd : noop,
onTouchcancel: this.dragging && touchMove ? this.swipeEnd : noop,
onKeydown: this.accessibility ? this.keyHandler : noop,

View File

@ -1,3 +1,4 @@
import supportsPassive from '../../../_util/supportsPassive';
import classNames from '../../../_util/classNames';
import { isValidElement } from '../../../_util/props-util';
@ -51,13 +52,16 @@ const Marks = (_, { attrs }) => {
const style = vertical ? bottomStyle : leftStyle;
const markStyle = markPointIsObject ? { ...style, ...markPoint.style } : style;
const touchEvents = {
[supportsPassive ? 'onTouchstartPassive' : 'onTouchstart']: e => onClickLabel(e, point),
};
return (
<span
class={markClassName}
style={markStyle}
key={point}
onMousedown={e => onClickLabel(e, point)}
onTouchstart={e => onClickLabel(e, point)}
{...touchEvents}
>
{markLabel}
</span>

View File

@ -9,6 +9,7 @@ import Marks from './Marks';
import Handle from '../Handle';
import * as utils from '../utils';
import BaseMixin from '../../../_util/BaseMixin';
import supportsPassive from '../../../_util/supportsPassive';
function noop() {}
@ -295,13 +296,18 @@ export default function createSlider(Component) {
class: `${prefixCls}-mark`,
onClickLabel: disabled ? noop : this.onClickMarkLabel,
};
const touchEvents = {
[supportsPassive ? 'onTouchstartPassive' : 'onTouchstart']: disabled
? noop
: this.onTouchStart,
};
return (
<div
id={id}
ref={this.saveSlider}
tabindex="-1"
class={sliderClassName}
onTouchstart={disabled ? noop : this.onTouchStart}
{...touchEvents}
onMousedown={disabled ? noop : this.onMouseDown}
onMouseup={disabled ? noop : this.onMouseUp}
onKeydown={disabled ? noop : this.onKeyDown}

View File

@ -27,15 +27,10 @@ const BaseTable = {
},
methods: {
getColumns(cols) {
const { columns = [], fixed } = this.$props;
const { table } = this;
const { prefixCls } = table.$props;
const { columns = [] } = this.$props;
return (cols || columns).map(column => ({
...column,
className:
!!column.fixed && !fixed
? classNames(`${prefixCls}-fixed-columns-in-body`, column.className, column.class)
: classNames(column.className, column.class),
className: classNames(column.className, column.class),
}));
},
handleRowHover(isHover, key) {
@ -44,7 +39,6 @@ const BaseTable = {
renderRows(renderData, indent, ancestorKeys = []) {
const {
columnManager,
sComponents: components,
prefixCls,
childrenColumnName,
@ -57,6 +51,7 @@ const BaseTable = {
onRowMouseLeave = noop,
rowRef,
} = { ...this.table.$attrs, ...this.table.$props, ...this.table.$data };
const { columnManager } = this.store;
const { getRowKey, fixed, expander, isAnyColumnsFixed } = this;
const rows = [];
@ -68,17 +63,17 @@ const BaseTable = {
typeof rowClassName === 'string' ? rowClassName : rowClassName(record, i, indent);
const onHoverProps = {};
if (columnManager.isAnyColumnsFixed()) {
if (columnManager.isAnyColumnsFixed) {
onHoverProps.onHover = this.handleRowHover;
}
let leafColumns;
if (fixed === 'left') {
leafColumns = columnManager.leftLeafColumns();
leafColumns = columnManager.leftLeafColumns;
} else if (fixed === 'right') {
leafColumns = columnManager.rightLeafColumns();
leafColumns = columnManager.rightLeafColumns;
} else {
leafColumns = this.getColumns(columnManager.leafColumns());
leafColumns = this.getColumns(columnManager.leafColumns);
}
const rowPrefixCls = `${prefixCls}-row`;

View File

@ -1,6 +1,7 @@
import { inject } from 'vue';
import PropTypes from '../../_util/vue-types';
import { INTERNAL_COL_DEFINE } from './utils';
import ResizeObserver from '../../vc-resize-observer';
export default {
name: 'ColGroup',
@ -12,11 +13,12 @@ export default {
setup() {
return {
table: inject('table', {}),
store: inject('table-store', () => ({})),
};
},
render() {
const { fixed, table } = this;
const { prefixCls, expandIconAsCell, columnManager } = table;
const { prefixCls, expandIconAsCell, onColumnResize } = table;
let cols = [];
@ -25,19 +27,32 @@ export default {
}
let leafColumns;
const { columnManager } = this.store;
if (fixed === 'left') {
leafColumns = columnManager.leftLeafColumns();
leafColumns = columnManager.leftLeafColumns;
} else if (fixed === 'right') {
leafColumns = columnManager.rightLeafColumns();
leafColumns = columnManager.rightLeafColumns;
} else {
leafColumns = columnManager.leafColumns();
leafColumns = columnManager.leafColumns;
}
cols = cols.concat(
leafColumns.map(({ key, dataIndex, width, [INTERNAL_COL_DEFINE]: additionalProps }) => {
const mergedKey = key !== undefined ? key : dataIndex;
const w = typeof width === 'number' ? `${width}px` : width;
return <col key={mergedKey} style={{ width: w, minWidth: w }} {...additionalProps} />;
return (
<ResizeObserver
onResize={({ offsetWidth }) => {
onColumnResize(mergedKey, offsetWidth);
}}
>
<col
data-key={mergedKey}
key={mergedKey}
style={{ width: w, minWidth: w }}
{...additionalProps}
/>
</ResizeObserver>
);
}),
);
return <colgroup>{cols}</colgroup>;

View File

@ -1,116 +0,0 @@
import { toRaw } from 'vue';
export default class ColumnManager {
constructor(columns) {
this.columns = toRaw(columns);
this._cached = {};
}
isAnyColumnsFixed() {
return this._cache('isAnyColumnsFixed', () => this.columns.some(column => !!column.fixed));
}
isAnyColumnsLeftFixed() {
return this._cache('isAnyColumnsLeftFixed', () =>
this.columns.some(column => column.fixed === 'left' || column.fixed === true),
);
}
isAnyColumnsRightFixed() {
return this._cache('isAnyColumnsRightFixed', () =>
this.columns.some(column => column.fixed === 'right'),
);
}
leftColumns() {
return this._cache('leftColumns', () =>
this.groupedColumns().filter(column => column.fixed === 'left' || column.fixed === true),
);
}
rightColumns() {
return this._cache('rightColumns', () =>
this.groupedColumns().filter(column => column.fixed === 'right'),
);
}
leafColumns() {
return this._cache('leafColumns', () => this._leafColumns(this.columns));
}
leftLeafColumns() {
return this._cache('leftLeafColumns', () => this._leafColumns(this.leftColumns()));
}
rightLeafColumns() {
return this._cache('rightLeafColumns', () => this._leafColumns(this.rightColumns()));
}
// add appropriate rowspan and colspan to column
groupedColumns() {
return this._cache('groupedColumns', () => {
const _groupColumns = (columns, currentRow = 0, parentColumn = {}, rows = []) => {
// track how many rows we got
rows[currentRow] = rows[currentRow] || [];
const grouped = [];
const setRowSpan = column => {
const rowSpan = rows.length - currentRow;
if (
column &&
!column.children && // parent columns are supposed to be one row
rowSpan > 1 &&
(!column.rowSpan || column.rowSpan < rowSpan)
) {
column.rowSpan = rowSpan;
}
};
columns.forEach((column, index) => {
const newColumn = { ...column };
rows[currentRow].push(newColumn);
parentColumn.colSpan = parentColumn.colSpan || 0;
if (newColumn.children && newColumn.children.length > 0) {
newColumn.children = _groupColumns(newColumn.children, currentRow + 1, newColumn, rows);
parentColumn.colSpan += newColumn.colSpan;
} else {
parentColumn.colSpan += 1;
}
// update rowspan to all same row columns
for (let i = 0; i < rows[currentRow].length - 1; i += 1) {
setRowSpan(rows[currentRow][i]);
}
// last column, update rowspan immediately
if (index + 1 === columns.length) {
setRowSpan(newColumn);
}
grouped.push(newColumn);
});
return grouped;
};
return _groupColumns(this.columns);
});
}
reset(columns) {
this.columns = toRaw(columns);
this._cached = {};
}
_cache(name, fn) {
if (name in this._cached) {
return this._cached[name];
}
this._cached[name] = fn();
return this._cached[name];
}
_leafColumns(columns) {
const leafColumns = [];
columns.forEach(column => {
if (!column.children) {
leafColumns.push(column);
} else {
leafColumns.push(...this._leafColumns(column.children));
}
});
return leafColumns;
}
}

View File

@ -147,11 +147,11 @@ const ExpandableTable = {
};
let colCount;
if (fixed === 'left') {
colCount = this.columnManager.leftLeafColumns().length;
colCount = this.columnManager.leftLeafColumns.value.length;
} else if (fixed === 'right') {
colCount = this.columnManager.rightLeafColumns().length;
colCount = this.columnManager.rightLeafColumns.value.length;
} else {
colCount = this.columnManager.leafColumns().length;
colCount = this.columnManager.leafColumns.value.length;
}
const columns = [
{

View File

@ -1,19 +1,34 @@
/* eslint-disable camelcase */
import { provide, markRaw, defineComponent, nextTick, reactive } from 'vue';
import {
provide,
markRaw,
defineComponent,
nextTick,
reactive,
computed,
ref,
onUpdated,
onMounted,
toRef,
} from 'vue';
import shallowequal from '../../_util/shallowequal';
import merge from 'lodash-es/merge';
import classes from '../../_util/component-classes';
import classNames from '../../_util/classNames';
import PropTypes from '../../_util/vue-types';
import { debounce, getDataAndAriaProps } from './utils';
import { debounce, getColumnsKey, getDataAndAriaProps, validateValue } from './utils';
import warning from '../../_util/warning';
import addEventListener from '../../vc-util/Dom/addEventListener';
import ColumnManager from './ColumnManager';
import HeadTable from './HeadTable';
import BodyTable from './BodyTable';
import ExpandableTable from './ExpandableTable';
import { initDefaultProps, getOptionProps } from '../../_util/props-util';
import BaseMixin from '../../_util/BaseMixin';
import { useLayoutState } from '../../_util/hooks/useLayoutState';
import useColumnManager from './useColumnManager';
import useStickyOffsets from './useStickyOffsets';
import { getCellFixedInfo } from './fixUtil';
import ResizeObserver from '../../vc-resize-observer';
export default defineComponent({
name: 'Table',
@ -84,23 +99,76 @@ export default defineComponent({
customHeaderRow: () => {},
},
),
setup() {
setup(props) {
const columnManager = useColumnManager(toRef(props, 'columns'));
const colsKeys = computed(() => getColumnsKey(columnManager.leafColumns.value));
const [colsWidths, updateColsWidths] = useLayoutState(new Map());
const pureColWidths = computed(() =>
colsKeys.value.map(columnKey => colsWidths.value.get(columnKey)),
);
const stickyOffsets = useStickyOffsets(pureColWidths, columnManager.leafColumns);
const onColumnResize = (columnKey, width) => {
updateColsWidths(widths => {
if (widths.get(columnKey) !== width) {
const newWidths = new Map(widths);
newWidths.set(columnKey, width);
return newWidths;
}
return widths;
});
};
const fixedInfoList = computed(() =>
columnManager.leafColumns.value.map((_, colIndex) =>
getCellFixedInfo(colIndex, colIndex, columnManager.leafColumns.value, stickyOffsets.value),
),
);
const store = reactive({
currentHoverKey: null,
fixedColumnsHeadRowsHeight: [],
fixedColumnsBodyRowsHeight: {},
expandedRowsHeight: {},
expandedRowKeys: [],
columnManager,
fixedInfoList,
stickyOffsets,
});
provide('table-store', store);
const bodyRef = ref();
const pingedLeft = ref(false);
const pingedRight = ref(false);
const horizonScroll = computed(() => props.scroll && validateValue(props.scroll.x));
const onScroll = currentTarget => {
const { scrollWidth, clientWidth, scrollLeft } = currentTarget;
pingedLeft.value = scrollLeft > 0;
pingedRight.value = scrollLeft < scrollWidth - clientWidth;
};
onUpdated(() => {
nextTick(() => {
horizonScroll.value && onScroll(bodyRef.value.$el);
});
});
onMounted(() => {
nextTick(() => {
horizonScroll.value && onScroll(bodyRef.value.$el);
});
});
const onFullTableResize = () => {
horizonScroll.value && onScroll(bodyRef.value.$el);
};
return {
bodyRef,
store,
onColumnResize,
columnManager,
onScroll,
pingedLeft,
pingedRight,
onFullTableResize,
};
},
data() {
this.preData = [...this.data];
return {
columnManager: markRaw(new ColumnManager(this.columns)),
sComponents: markRaw(
merge(
{
@ -145,11 +213,6 @@ export default defineComponent({
this.components,
);
},
columns(val) {
if (val) {
this.columnManager.reset(val);
}
},
dataLen(val, preVal) {
if ((val === 0 || preVal === 0) && this.hasScrollX()) {
nextTick(() => {
@ -160,21 +223,6 @@ export default defineComponent({
},
created() {
provide('table', this);
// ['rowClick', 'rowDoubleclick', 'rowContextmenu', 'rowMouseenter', 'rowMouseleave'].forEach(
// name => {
// warning(
// getListeners(this)[name] === undefined,
// `${name} is deprecated, please use customRow instead.`,
// );
// },
// );
// warning(
// this.getBodyWrapper === undefined,
// 'getBodyWrapper is deprecated, please use custom components instead.',
// );
// this.columnManager = new ColumnManager(this.columns, this.$slots.default)
this.setScrollPosition('left');
@ -183,7 +231,7 @@ export default defineComponent({
mounted() {
this.$nextTick(() => {
if (this.columnManager.isAnyColumnsFixed()) {
if (this.columnManager.isAnyColumnsFixed.value) {
this.handleWindowResize();
this.resizeEvent = addEventListener(window, 'resize', this.debouncedWindowResize);
}
@ -199,7 +247,7 @@ export default defineComponent({
updated() {
this.$nextTick(() => {
if (this.columnManager.isAnyColumnsFixed()) {
if (this.columnManager.isAnyColumnsFixed.value) {
this.handleWindowResize();
if (!this.resizeEvent) {
this.resizeEvent = addEventListener(window, 'resize', this.debouncedWindowResize);
@ -383,8 +431,8 @@ export default defineComponent({
// Remember last scrollTop for scroll direction detecting.
this.lastScrollTop = target.scrollTop;
},
handleBodyScroll(e) {
this.onScroll(e.target);
this.handleBodyScrollLeft(e);
this.handleBodyScrollTop(e);
},
@ -432,28 +480,34 @@ export default defineComponent({
},
renderMainTable() {
const { scroll, prefixCls } = this;
const isAnyColumnsFixed = this.columnManager.isAnyColumnsFixed();
const isAnyColumnsFixed = this.columnManager.isAnyColumnsFixed.value;
const scrollable = isAnyColumnsFixed || scroll.x || scroll.y;
const table = [
this.renderTable({
columns: this.columnManager.groupedColumns(),
columns: this.columnManager.groupedColumns.value,
isAnyColumnsFixed,
}),
this.renderEmptyText(),
this.renderFooter(),
];
return scrollable ? <div class={`${prefixCls}-scroll`}>{table}</div> : table;
return scrollable ? (
<ResizeObserver onResize={this.onFullTableResize}>
<div class={`${prefixCls}-scroll`}>{table}</div>
</ResizeObserver>
) : (
table
);
},
renderLeftFixedTable() {
const { prefixCls } = this;
return (
<div class={`${prefixCls}-fixed-left`}>
<div key="left" class={`${prefixCls}-fixed-left`}>
{this.renderTable({
columns: this.columnManager.leftColumns(),
columns: this.columnManager.leftColumns.value,
fixed: 'left',
})}
</div>
@ -465,7 +519,7 @@ export default defineComponent({
return (
<div class={`${prefixCls}-fixed-right`}>
{this.renderTable({
columns: this.columnManager.rightColumns(),
columns: this.columnManager.rightColumns.value,
fixed: 'right',
})}
</div>
@ -499,6 +553,7 @@ export default defineComponent({
handleBodyScroll={this.handleBodyScroll}
expander={this.expander}
isAnyColumnsFixed={isAnyColumnsFixed}
ref="bodyRef"
/>
);
@ -548,10 +603,9 @@ export default defineComponent({
this.scrollPosition === 'both',
[`${prefixCls}-scroll-position-${this.scrollPosition}`]: this.scrollPosition !== 'both',
[`${prefixCls}-layout-fixed`]: this.isTableLayoutFixed(),
[`${prefixCls}-ping-left`]: this.pingedLeft,
[`${prefixCls}-ping-right`]: this.pingedRight,
});
const hasLeftFixed = columnManager.isAnyColumnsLeftFixed();
const hasRightFixed = columnManager.isAnyColumnsRightFixed();
const dataAndAriaProps = getDataAndAriaProps(props);
const expandableTableProps = {
...props,
@ -573,11 +627,7 @@ export default defineComponent({
{...dataAndAriaProps}
>
{this.renderTitle()}
<div class={`${prefixCls}-content`}>
{this.renderMainTable()}
{hasLeftFixed && this.renderLeftFixedTable()}
{hasRightFixed && this.renderRightFixedTable()}
</div>
<div class={`${prefixCls}-content`}>{this.renderMainTable()}</div>
</div>
);
},

View File

@ -22,10 +22,12 @@ export default {
column: PropTypes.object,
expandIcon: PropTypes.any,
component: PropTypes.any,
colIndex: PropTypes.number,
},
setup() {
return {
table: inject('table', {}),
store: inject('table-store', {}),
};
},
methods: {
@ -51,8 +53,24 @@ export default {
column,
component: BodyCell,
} = this;
const fixedInfoList = this.store.fixedInfoList || [];
const fixedInfo = fixedInfoList[this.colIndex];
const { fixLeft, fixRight, firstFixLeft, lastFixLeft, firstFixRight, lastFixRight } = fixedInfo;
// ====================== Fixed =======================
const fixedStyle = {};
const isFixLeft = typeof fixLeft === 'number';
const isFixRight = typeof fixRight === 'number';
if (isFixLeft) {
fixedStyle.position = 'sticky';
fixedStyle.left = `${fixLeft}px`;
}
if (isFixRight) {
fixedStyle.position = 'sticky';
fixedStyle.right = `${fixRight}px`;
}
const { dataIndex, customRender, className = '' } = column;
const { transformCellText } = this.table;
const { transformCellText, prefixCls: rootPrefixCls } = this.table;
// We should return undefined if no dataIndex is specified, but in order to
// be compatible with object-path's behavior, we return the record object instead.
let text;
@ -110,6 +128,12 @@ export default {
//
// https://github.com/ant-design/ant-design/issues/13825#issuecomment-449889241
[`${prefixCls}-cell-break-word`]: !!column.width,
[`${rootPrefixCls}-cell-fix-left`]: isFixLeft,
[`${rootPrefixCls}-cell-fix-left-first`]: firstFixLeft,
[`${rootPrefixCls}-cell-fix-left-last`]: lastFixLeft,
[`${rootPrefixCls}-cell-fix-right`]: isFixRight,
[`${rootPrefixCls}-cell-fix-right-first`]: firstFixRight,
[`${rootPrefixCls}-cell-fix-right-last`]: lastFixRight,
});
if (column.ellipsis) {
@ -124,7 +148,11 @@ export default {
}
return (
<BodyCell class={cellClassName} {...tdProps}>
<BodyCell
class={cellClassName}
{...tdProps}
{...{ style: { ...(tdProps.style || {}), ...fixedStyle } }}
>
{indentText}
{expandIcon}
{toRaw(text)}

View File

@ -1,44 +1,70 @@
import { inject } from 'vue';
import { computed, inject } from 'vue';
import PropTypes from '../../_util/vue-types';
import TableHeaderRow from './TableHeaderRow';
function getHeaderRows({ columns = [], currentRow = 0, rows = [], isLast = true }) {
rows = rows || [];
rows[currentRow] = rows[currentRow] || [];
function parseHeaderRows(rootColumns) {
const rows = [];
columns.forEach((column, i) => {
if (column.rowSpan && rows.length < column.rowSpan) {
while (rows.length < column.rowSpan) {
rows.push([]);
function fillRowCells(columns, colIndex, rowIndex = 0) {
// Init rows
rows[rowIndex] = rows[rowIndex] || [];
let currentColIndex = colIndex;
const colSpans = columns.filter(Boolean).map(column => {
const cell = {
key: column.key,
className: column.className || column.class || '',
children: column.title,
column,
colStart: currentColIndex,
};
let colSpan = 1;
const subColumns = column.children;
if (subColumns && subColumns.length > 0) {
colSpan = fillRowCells(subColumns, currentColIndex, rowIndex + 1).reduce(
(total, count) => total + count,
0,
);
cell.hasSubColumns = true;
}
}
const cellIsLast = isLast && i === columns.length - 1;
const cell = {
key: column.key,
className: column.className || column.class || '',
children: column.title,
isLast: cellIsLast,
column,
};
if (column.children) {
getHeaderRows({
columns: column.children,
currentRow: currentRow + 1,
rows,
isLast: cellIsLast,
});
}
if ('colSpan' in column) {
cell.colSpan = column.colSpan;
}
if ('rowSpan' in column) {
cell.rowSpan = column.rowSpan;
}
if (cell.colSpan !== 0) {
rows[currentRow].push(cell);
}
});
return rows.filter(row => row.length > 0);
if ('colSpan' in column) {
({ colSpan } = column);
}
if ('rowSpan' in column) {
cell.rowSpan = column.rowSpan;
}
cell.colSpan = colSpan;
cell.colEnd = cell.colStart + colSpan - 1;
rows[rowIndex].push(cell);
currentColIndex += colSpan;
return colSpan;
});
return colSpans;
}
// Generate `rows` cell data
fillRowCells(rootColumns, 0);
// Handle `rowSpan`
const rowCount = rows.length;
for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
rows[rowIndex].forEach(cell => {
if (!('rowSpan' in cell) && !cell.hasSubColumns) {
// eslint-disable-next-line no-param-reassign
cell.rowSpan = rowCount - rowIndex;
}
});
}
return rows;
}
export default {
@ -49,22 +75,21 @@ export default {
columns: PropTypes.array.isRequired,
expander: PropTypes.object.isRequired,
},
setup() {
setup(props) {
return {
table: inject('table', {}),
rows: computed(() => parseHeaderRows(props.columns)),
};
},
render() {
const { sComponents: components, prefixCls, showHeader, customHeaderRow } = this.table;
const { expander, columns, fixed } = this;
const { expander, columns, fixed, rows } = this;
if (!showHeader) {
return null;
}
const rows = getHeaderRows({ columns });
expander.renderExpandIndentCell(rows, fixed);
const HeaderWrapper = components.header.wrapper;

View File

@ -1,6 +1,7 @@
import classNames from '../../_util/classNames';
import PropTypes from '../../_util/vue-types';
import { computed, inject } from 'vue';
import { getCellFixedInfo } from './fixUtil';
const TableHeaderRow = {
name: 'TableHeaderRow',
@ -35,6 +36,7 @@ const TableHeaderRow = {
}
return null;
}),
store,
};
},
render() {
@ -50,21 +52,44 @@ const TableHeaderRow = {
if (style.height === null) {
delete style.height;
}
const { stickyOffsets, columnManager } = this.store;
return (
<HeaderRow {...rowProps} style={style}>
{row.map((cell, i) => {
const { column, isLast, children, className, ...cellProps } = cell;
const fixedInfo = getCellFixedInfo(
cell.colStart,
cell.colEnd,
columnManager.leafColumns,
stickyOffsets,
);
const customProps = column.customHeaderCell ? column.customHeaderCell(column) : {};
const headerCellProps = {
...cellProps,
...customProps,
key: column.key || column.dataIndex || i,
};
if (headerCellProps.colSpan === 0) {
return null;
}
if (column.align) {
headerCellProps.style = { ...customProps.style, textAlign: column.align };
}
// ====================== Fixed =======================
const { fixLeft, fixRight, firstFixLeft, lastFixLeft, firstFixRight, lastFixRight } =
fixedInfo;
const fixedStyle = {};
const isFixLeft = typeof fixLeft === 'number';
const isFixRight = typeof fixRight === 'number';
if (isFixLeft) {
fixedStyle.position = 'sticky';
fixedStyle.left = `${fixLeft}px`;
}
if (isFixRight) {
fixedStyle.position = 'sticky';
fixedStyle.right = `${fixRight}px`;
}
headerCellProps.class = classNames(
customProps.class,
customProps.className,
@ -75,9 +100,15 @@ const TableHeaderRow = {
[`${prefixCls}-row-cell-ellipsis`]: !!column.ellipsis,
[`${prefixCls}-row-cell-break-word`]: !!column.width,
[`${prefixCls}-row-cell-last`]: isLast,
[`${prefixCls}-cell-fix-left`]: isFixLeft,
[`${prefixCls}-cell-fix-left-first`]: firstFixLeft,
[`${prefixCls}-cell-fix-left-last`]: lastFixLeft,
[`${prefixCls}-cell-fix-right`]: isFixRight,
[`${prefixCls}-cell-fix-right-first`]: firstFixRight,
[`${prefixCls}-cell-fix-right-last`]: lastFixRight,
},
);
headerCellProps.style = { ...(headerCellProps.style || {}), ...fixedStyle };
if (typeof HeaderCell === 'function') {
return HeaderCell(headerCellProps, children);
}

View File

@ -250,6 +250,7 @@ const TableRow = {
indentSize={indentSize}
indent={indent}
index={index}
colIndex={i}
column={column}
key={column.key || column.dataIndex}
expandIcon={hasExpandIcon(i) && renderExpandIcon()}

View File

@ -0,0 +1,73 @@
export interface StickyOffsets {
left: readonly number[];
right: readonly number[];
isSticky?: boolean;
}
export type FixedType = 'left' | 'right' | boolean;
export interface FixedInfo {
fixLeft: number | false;
fixRight: number | false;
lastFixLeft: boolean;
firstFixRight: boolean;
// For Rtl Direction
lastFixRight: boolean;
firstFixLeft: boolean;
isSticky: boolean;
}
export function getCellFixedInfo(
colStart: number,
colEnd: number,
columns: readonly { fixed?: FixedType }[],
stickyOffsets: StickyOffsets,
direction: 'ltr' | 'rtl',
): FixedInfo {
const startColumn = columns[colStart] || {};
const endColumn = columns[colEnd] || {};
let fixLeft: number;
let fixRight: number;
if (startColumn.fixed === 'left') {
fixLeft = stickyOffsets.left[colStart];
} else if (endColumn.fixed === 'right') {
fixRight = stickyOffsets.right[colEnd];
}
let lastFixLeft = false;
let firstFixRight = false;
let lastFixRight = false;
let firstFixLeft = false;
const nextColumn = columns[colEnd + 1];
const prevColumn = columns[colStart - 1];
if (direction === 'rtl') {
if (fixLeft !== undefined) {
const prevFixLeft = prevColumn && prevColumn.fixed === 'left';
firstFixLeft = !prevFixLeft;
} else if (fixRight !== undefined) {
const nextFixRight = nextColumn && nextColumn.fixed === 'right';
lastFixRight = !nextFixRight;
}
} else if (fixLeft !== undefined) {
const nextFixLeft = nextColumn && nextColumn.fixed === 'left';
lastFixLeft = !nextFixLeft;
} else if (fixRight !== undefined) {
const prevFixRight = prevColumn && prevColumn.fixed === 'right';
firstFixRight = !prevFixRight;
}
return {
fixLeft,
fixRight,
lastFixLeft,
firstFixRight,
lastFixRight,
firstFixLeft,
isSticky: stickyOffsets.isSticky,
};
}

View File

@ -0,0 +1,101 @@
import { computed } from 'vue';
export default function useColumnManager(columns) {
const _leafColumns = (cls, fixed = false) => {
const leafColumns = [];
cls.forEach(column => {
column.fixed = fixed || column.fixed;
if (!column.children) {
leafColumns.push(column);
} else {
leafColumns.push(..._leafColumns(column.children, column.fixed));
}
});
return leafColumns;
};
// add appropriate rowspan and colspan to column
const groupedColumns = computed(() => {
const _groupColumns = (cls, currentRow = 0, parentColumn = {}, rows = [], fixed = false) => {
// track how many rows we got
rows[currentRow] = rows[currentRow] || [];
const grouped = [];
const setRowSpan = column => {
const rowSpan = rows.length - currentRow;
if (
column &&
!column.children && // parent columns.value are supposed to be one row
rowSpan > 1 &&
(!column.rowSpan || column.rowSpan < rowSpan)
) {
column.rowSpan = rowSpan;
}
};
cls.forEach((column, index) => {
const newColumn = { ...column };
newColumn.fixed = fixed || column.fixed;
rows[currentRow].push(newColumn);
parentColumn.colSpan = parentColumn.colSpan || 0;
if (newColumn.children && newColumn.children.length > 0) {
newColumn.children = _groupColumns(
newColumn.children,
currentRow + 1,
newColumn,
rows,
newColumn.fixed,
);
parentColumn.colSpan += newColumn.colSpan;
} else {
parentColumn.colSpan += 1;
}
// update rowspan to all same row columns.value
for (let i = 0; i < rows[currentRow].length - 1; i += 1) {
setRowSpan(rows[currentRow][i]);
}
// last column, update rowspan immediately
if (index + 1 === cls.length) {
setRowSpan(newColumn);
}
grouped.push(newColumn);
});
return grouped;
};
return _groupColumns(columns.value);
});
const isAnyColumnsFixed = computed(() => columns.value.some(column => !!column.fixed));
const isAnyColumnsLeftFixed = computed(() =>
columns.value.some(column => column.fixed === 'left' || column.fixed === true),
);
const isAnyColumnsRightFixed = computed(() =>
columns.value.some(column => column.fixed === 'right'),
);
const leftColumns = computed(() =>
groupedColumns.value.filter(column => column.fixed === 'left' || column.fixed === true),
);
const rightColumns = computed(() => {
return groupedColumns.value.filter(column => column.fixed === 'right');
});
const leafColumns = computed(() => {
return _leafColumns(columns.value);
});
const leftLeafColumns = computed(() => _leafColumns(leftColumns.value));
const rightLeafColumns = computed(() => _leafColumns(rightColumns.value));
return {
groupedColumns,
isAnyColumnsFixed,
isAnyColumnsLeftFixed,
isAnyColumnsRightFixed,
leftColumns,
rightColumns,
leafColumns,
leftLeafColumns,
rightLeafColumns,
};
}

View File

@ -0,0 +1,43 @@
import { ref, watch } from 'vue';
/**
* Get sticky column offset width
*/
function useStickyOffsets(colWidths, columns) {
const stickyOffsets = ref({
left: [],
right: [],
});
const columnCount = ref();
watch(
columns,
() => {
columnCount.value = columns.value.length;
},
{ immediate: true },
);
watch([colWidths, columnCount], () => {
const leftOffsets = [];
const rightOffsets = [];
let left = 0;
let right = 0;
for (let start = 0; start < columnCount.value; start += 1) {
// Left offset
leftOffsets[start] = left;
left += colWidths.value[start] || 0;
// Right offset
const end = columnCount.value - start - 1;
rightOffsets[end] = right;
right += colWidths.value[end] || 0;
}
stickyOffsets.value = {
left: leftOffsets,
right: rightOffsets,
};
});
return stickyOffsets;
}
export default useStickyOffsets;

View File

@ -98,3 +98,19 @@ export function getDataAndAriaProps(props) {
return memo;
}, {});
}
export function getColumnsKey(columns) {
const columnKeys = [];
columns.forEach(column => {
const { key, dataIndex } = column || {};
columnKeys.push(key !== undefined ? key : dataIndex);
});
return columnKeys;
}
export function validateValue(val) {
return val !== null && val !== undefined;
}

View File

@ -12,7 +12,6 @@ export default function toArray(children: any[], option: Option = {}): any[] {
if ((child === undefined || child === null) && !option.keepEmpty) {
return;
}
debugger;
if (Array.isArray(child)) {
ret = ret.concat(toArray(child));
} else if (isFragment(child) && child.props) {

View File

@ -145,74 +145,76 @@ const List = defineComponent({
watch(
[inVirtual, useVirtual, () => state.scrollTop, mergedData, heights, () => props.height],
() => {
if (!useVirtual.value) {
calRes.value = {
scrollHeight: undefined,
start: 0,
end: mergedData.value.length - 1,
offset: undefined,
};
return;
}
// Always use virtual scroll bar in avoid shaking
if (!inVirtual.value) {
calRes.value = {
scrollHeight: fillerInnerRef.value?.offsetHeight || 0,
start: 0,
end: mergedData.value.length - 1,
offset: undefined,
};
return;
}
let itemTop = 0;
let startIndex: number | undefined;
let startOffset: number | undefined;
let endIndex: number | undefined;
const dataLen = mergedData.value.length;
const data = mergedData.value;
for (let i = 0; i < dataLen; i += 1) {
const item = data[i];
const key = getKey(item);
const cacheHeight = heights[key];
const currentItemBottom =
itemTop + (cacheHeight === undefined ? props.itemHeight! : cacheHeight);
if (currentItemBottom >= state.scrollTop && startIndex === undefined) {
startIndex = i;
startOffset = itemTop;
nextTick(() => {
if (!useVirtual.value) {
calRes.value = {
scrollHeight: undefined,
start: 0,
end: mergedData.value.length - 1,
offset: undefined,
};
return;
}
// Check item bottom in the range. We will render additional one item for motion usage
if (currentItemBottom > state.scrollTop + props.height! && endIndex === undefined) {
endIndex = i;
// Always use virtual scroll bar in avoid shaking
if (!inVirtual.value) {
calRes.value = {
scrollHeight: fillerInnerRef.value?.offsetHeight || 0,
start: 0,
end: mergedData.value.length - 1,
offset: undefined,
};
return;
}
itemTop = currentItemBottom;
}
let itemTop = 0;
let startIndex: number | undefined;
let startOffset: number | undefined;
let endIndex: number | undefined;
const dataLen = mergedData.value.length;
const data = mergedData.value;
for (let i = 0; i < dataLen; i += 1) {
const item = data[i];
const key = getKey(item);
// Fallback to normal if not match. This code should never reach
/* istanbul ignore next */
if (startIndex === undefined) {
startIndex = 0;
startOffset = 0;
}
if (endIndex === undefined) {
endIndex = dataLen - 1;
}
const cacheHeight = heights[key];
const currentItemBottom =
itemTop + (cacheHeight === undefined ? props.itemHeight! : cacheHeight);
// Give cache to improve scroll experience
endIndex = Math.min(endIndex + 1, dataLen);
calRes.value = {
scrollHeight: itemTop,
start: startIndex,
end: endIndex,
offset: startOffset,
};
if (currentItemBottom >= state.scrollTop && startIndex === undefined) {
startIndex = i;
startOffset = itemTop;
}
// Check item bottom in the range. We will render additional one item for motion usage
if (currentItemBottom > state.scrollTop + props.height! && endIndex === undefined) {
endIndex = i;
}
itemTop = currentItemBottom;
}
// Fallback to normal if not match. This code should never reach
/* istanbul ignore next */
if (startIndex === undefined) {
startIndex = 0;
startOffset = 0;
}
if (endIndex === undefined) {
endIndex = dataLen - 1;
}
// Give cache to improve scroll experience
endIndex = Math.min(endIndex + 1, dataLen);
calRes.value = {
scrollHeight: itemTop,
start: startIndex,
end: endIndex,
offset: startOffset,
};
});
},
{ immediate: true },
{ immediate: true, flush: 'post' },
);
// =============================== In Range ===============================

View File

@ -1,6 +1,6 @@
{
"name": "ant-design-vue",
"version": "2.2.2",
"version": "2.2.3",
"title": "Ant Design Vue",
"description": "An enterprise-class UI design language and Vue-based implementation",
"keywords": [
@ -185,7 +185,7 @@
"vue-clipboard2": "0.3.1",
"vue-draggable-resizable": "^2.1.0",
"vue-eslint-parser": "^7.0.0",
"vue-i18n": "^9.0.0-alpha.11",
"vue-i18n": "^9.1.7",
"vue-infinite-scroll": "^2.0.2",
"vue-jest": "^5.0.0-alpha.3",
"vue-loader": "^16.1.1",

2
v2-doc

@ -1 +1 @@
Subproject commit 57c08127bf0e3e826b03f845df3e1332820964e5
Subproject commit d571ad4bf772cfc372511dc1dedf07981dc56ae8