refactor:table (#6267)

* refactor:table

* docs:update & refactor: table type

---------

Co-authored-by: tangjinzhou <415800467@qq.com>
pull/6269/head^2
果冻橙 2023-02-16 07:44:48 +08:00 committed by GitHub
parent c1ed77f67a
commit 8472c25633
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 1634 additions and 1337 deletions

View File

@ -37,7 +37,8 @@ import './time-picker/style';
import './calendar/style'; import './calendar/style';
// import './date-picker/style'; // import './date-picker/style';
// import './slider/style'; // import './slider/style';
import './table/style'; // import './table/style';
// import './progress/style'; // import './progress/style';
// import './timeline/style'; // import './timeline/style';
// import './input-number/style'; // import './input-number/style';

View File

@ -34,7 +34,7 @@ import scrollTo from '../_util/scrollTo';
import defaultLocale from '../locale/en_US'; import defaultLocale from '../locale/en_US';
import type { SizeType } from '../config-provider'; import type { SizeType } from '../config-provider';
import devWarning from '../vc-util/devWarning'; import devWarning from '../vc-util/devWarning';
import type { CSSProperties, PropType } from 'vue'; import type { CSSProperties } from 'vue';
import { nextTick, reactive, ref, computed, defineComponent, toRef, watchEffect, watch } from 'vue'; import { nextTick, reactive, ref, computed, defineComponent, toRef, watchEffect, watch } from 'vue';
import type { DefaultRecordType } from '../vc-table/interface'; import type { DefaultRecordType } from '../vc-table/interface';
import useBreakpoint from '../_util/hooks/useBreakpoint'; import useBreakpoint from '../_util/hooks/useBreakpoint';
@ -47,6 +47,17 @@ import { useProvideSlots, useProvideTableContext } from './context';
import type { ContextSlots } from './context'; import type { ContextSlots } from './context';
import useColumns from './hooks/useColumns'; import useColumns from './hooks/useColumns';
import { convertChildrenToColumns } from './util'; import { convertChildrenToColumns } from './util';
import {
stringType,
booleanType,
arrayType,
someType,
functionType,
objectType,
} from '../_util/type';
// CSSINJS
import useStyle from './style';
export type { ColumnsType, TablePaginationConfig }; export type { ColumnsType, TablePaginationConfig };
@ -107,128 +118,68 @@ export interface TableProps<RecordType = DefaultRecordType>
export const tableProps = () => { export const tableProps = () => {
return { return {
prefixCls: { type: String as PropType<string>, default: undefined }, prefixCls: stringType<string>(),
columns: { type: Array as PropType<ColumnsType>, default: undefined }, columns: arrayType<ColumnsType>(),
rowKey: { type: [String, Function] as PropType<TableProps['rowKey']>, default: undefined }, rowKey: someType<TableProps['rowKey']>([String, Function]),
tableLayout: { type: String as PropType<TableProps['tableLayout']>, default: undefined }, tableLayout: stringType<TableProps['tableLayout']>(),
rowClassName: { rowClassName: someType<TableProps['rowClassName']>([String, Function]),
type: [String, Function] as PropType<TableProps['rowClassName']>, title: functionType<TableProps['title']>(),
default: undefined, footer: functionType<TableProps['footer']>(),
}, id: stringType<TableProps['id']>(),
title: { type: Function as PropType<TableProps['title']>, default: undefined }, showHeader: booleanType(),
footer: { type: Function as PropType<TableProps['footer']>, default: undefined }, components: objectType<TableProps['components']>(),
id: { type: String as PropType<TableProps['id']>, default: undefined }, customRow: functionType<TableProps['customRow']>(),
showHeader: { type: Boolean as PropType<TableProps['showHeader']>, default: undefined }, customHeaderRow: functionType<TableProps['customHeaderRow']>(),
components: { type: Object as PropType<TableProps['components']>, default: undefined }, direction: stringType<TableProps['direction']>(),
customRow: { type: Function as PropType<TableProps['customRow']>, default: undefined }, expandFixed: someType<TableProps['expandFixed']>([Boolean, String]),
customHeaderRow: { expandColumnWidth: Number,
type: Function as PropType<TableProps['customHeaderRow']>, expandedRowKeys: arrayType<TableProps['expandedRowKeys']>(),
default: undefined, defaultExpandedRowKeys: arrayType<TableProps['defaultExpandedRowKeys']>(),
}, expandedRowRender: functionType<TableProps['expandedRowRender']>(),
direction: { type: String as PropType<TableProps['direction']>, default: undefined }, expandRowByClick: booleanType(),
expandFixed: { expandIcon: functionType<TableProps['expandIcon']>(),
type: [Boolean, String] as PropType<TableProps['expandFixed']>, onExpand: functionType<TableProps['onExpand']>(),
default: undefined, onExpandedRowsChange: functionType<TableProps['onExpandedRowsChange']>(),
}, 'onUpdate:expandedRowKeys': functionType<TableProps['onExpandedRowsChange']>(),
expandColumnWidth: { defaultExpandAllRows: booleanType(),
type: Number as PropType<TableProps['expandColumnWidth']>, indentSize: Number,
default: undefined,
},
expandedRowKeys: {
type: Array as PropType<TableProps['expandedRowKeys']>,
default: undefined as TableProps['expandedRowKeys'],
},
defaultExpandedRowKeys: {
type: Array as PropType<TableProps['defaultExpandedRowKeys']>,
default: undefined as TableProps['defaultExpandedRowKeys'],
},
expandedRowRender: {
type: Function as PropType<TableProps['expandedRowRender']>,
default: undefined,
},
expandRowByClick: {
type: Boolean as PropType<TableProps['expandRowByClick']>,
default: undefined,
},
expandIcon: { type: Function as PropType<TableProps['expandIcon']>, default: undefined },
onExpand: { type: Function as PropType<TableProps['onExpand']>, default: undefined },
onExpandedRowsChange: {
type: Function as PropType<TableProps['onExpandedRowsChange']>,
default: undefined,
},
'onUpdate:expandedRowKeys': {
type: Function as PropType<TableProps['onExpandedRowsChange']>,
default: undefined,
},
defaultExpandAllRows: {
type: Boolean as PropType<TableProps['defaultExpandAllRows']>,
default: undefined,
},
indentSize: { type: Number as PropType<TableProps['indentSize']>, default: undefined },
/** @deprecated Please use `EXPAND_COLUMN` in `columns` directly */ /** @deprecated Please use `EXPAND_COLUMN` in `columns` directly */
expandIconColumnIndex: { expandIconColumnIndex: Number,
type: Number as PropType<TableProps['expandIconColumnIndex']>, showExpandColumn: booleanType(),
default: undefined, expandedRowClassName: functionType<TableProps['expandedRowClassName']>(),
}, childrenColumnName: stringType<TableProps['childrenColumnName']>(),
showExpandColumn: { type: Boolean, default: undefined }, rowExpandable: functionType<TableProps['rowExpandable']>(),
expandedRowClassName: { sticky: someType<TableProps['sticky']>([Boolean, Object]),
type: Function as PropType<TableProps['expandedRowClassName']>,
default: undefined,
},
childrenColumnName: {
type: String as PropType<TableProps['childrenColumnName']>,
default: undefined,
},
rowExpandable: { type: Function as PropType<TableProps['rowExpandable']>, default: undefined },
sticky: { type: [Boolean, Object] as PropType<TableProps['sticky']>, default: undefined },
dropdownPrefixCls: String, dropdownPrefixCls: String,
dataSource: { type: Array as PropType<RcTableProps['data']>, default: undefined }, dataSource: arrayType<RcTableProps['data']>(),
pagination: { pagination: someType<false | TablePaginationConfig>([Boolean, Object]),
type: [Boolean, Object] as PropType<false | TablePaginationConfig>, loading: someType<boolean | SpinProps>([Boolean, Object]),
default: undefined, size: stringType<SizeType>(),
}, bordered: booleanType(),
loading: { type: [Boolean, Object] as PropType<boolean | SpinProps>, default: undefined }, locale: objectType<TableLocale>(),
size: { type: String as PropType<SizeType>, default: undefined },
bordered: Boolean,
locale: { type: Object as PropType<TableLocale>, default: undefined },
onChange: { onChange:
type: Function as PropType< functionType<
( (
pagination: TablePaginationConfig, pagination: TablePaginationConfig,
filters: Record<string, FilterValue | null>, filters: Record<string, FilterValue | null>,
sorter: SorterResult | SorterResult[], sorter: SorterResult | SorterResult[],
extra: TableCurrentDataSource, extra: TableCurrentDataSource,
) => void ) => void
>, >(),
default: undefined, onResizeColumn: functionType<(w: number, col: ColumnType) => void>(),
}, rowSelection: objectType<TableRowSelection>(),
onResizeColumn: { getPopupContainer: functionType<GetPopupContainer>(),
type: Function as PropType<(w: number, col: ColumnType) => void>, scroll: objectType<
default: undefined, RcTableProps['scroll'] & {
}, scrollToFirstRowOnChange?: boolean;
rowSelection: { type: Object as PropType<TableRowSelection>, default: undefined }, }
getPopupContainer: { type: Function as PropType<GetPopupContainer>, default: undefined }, >(),
scroll: { sortDirections: arrayType<SortOrder[]>(),
type: Object as PropType< showSorterTooltip: someType<boolean | TooltipProps>([Boolean, Object], true),
RcTableProps['scroll'] & { contextSlots: objectType<ContextSlots>(),
scrollToFirstRowOnChange?: boolean; transformCellText: functionType<TableProps['transformCellText']>(),
}
>,
default: undefined,
},
sortDirections: { type: Array as PropType<SortOrder[]>, default: undefined },
showSorterTooltip: {
type: [Boolean, Object] as PropType<boolean | TooltipProps>,
default: true,
},
contextSlots: {
type: Object as PropType<ContextSlots>,
},
transformCellText: {
type: Function as PropType<TableProps['transformCellText']>,
},
}; };
}; };
@ -287,6 +238,10 @@ const InteralTable = defineComponent<
prefixCls, prefixCls,
configProvider, configProvider,
} = useConfigInject('table', props); } = useConfigInject('table', props);
// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
const transformCellText = computed( const transformCellText = computed(
() => props.transformCellText || configProvider.transformCellText?.value, () => props.transformCellText || configProvider.transformCellText?.value,
); );
@ -637,9 +592,10 @@ const InteralTable = defineComponent<
[`${prefixCls.value}-wrapper-rtl`]: direction.value === 'rtl', [`${prefixCls.value}-wrapper-rtl`]: direction.value === 'rtl',
}, },
attrs.class, attrs.class,
hashId.value,
); );
const tableProps = omit(props, ['columns']); const tableProps = omit(props, ['columns']);
return ( return wrapSSR(
<div class={wrapperClassNames} style={attrs.style as CSSProperties}> <div class={wrapperClassNames} style={attrs.style as CSSProperties}>
<Spin spinning={false} {...spinProps}> <Spin spinning={false} {...spinProps}>
{topPaginationNode} {topPaginationNode}
@ -677,7 +633,7 @@ const InteralTable = defineComponent<
/> />
{bottomPaginationNode} {bottomPaginationNode}
</Spin> </Spin>
</div> </div>,
); );
}; };
}, },

View File

@ -1,19 +1,19 @@
import type { PropType } from 'vue';
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import SearchOutlined from '@ant-design/icons-vue/SearchOutlined'; import SearchOutlined from '@ant-design/icons-vue/SearchOutlined';
import type { FilterSearchType, TableLocale } from '../../interface'; import type { FilterSearchType, TableLocale } from '../../interface';
import Input from '../../../input'; import Input from '../../../input';
import { stringType, someType, functionType, objectType } from '../../../_util/type';
export default defineComponent({ export default defineComponent({
compatConfig: { MODE: 3 }, compatConfig: { MODE: 3 },
name: 'FilterSearch', name: 'FilterSearch',
inheritAttrs: false, inheritAttrs: false,
props: { props: {
value: String, value: stringType(),
onChange: Function as PropType<(e: InputEvent) => void>, onChange: functionType<(e: InputEvent) => void>(),
filterSearch: [Boolean, Function] as PropType<FilterSearchType>, filterSearch: someType<FilterSearchType>([Boolean, Function]),
tablePrefixCls: String, tablePrefixCls: stringType(),
locale: { type: Object as PropType<TableLocale>, default: undefined as TableLocale }, locale: objectType<TableLocale>(),
}, },
setup(props) { setup(props) {
return () => { return () => {

View File

@ -3,7 +3,7 @@ category: Components
cols: 1 cols: 1
type: Data Display type: Data Display
title: Table title: Table
cover: https://gw.alipayobjects.com/zos/alicdn/f-SbcX2Lx/Table.svg cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*3yz3QqMlShYAAAAAAAAAAAAADrJ8AQ/original
--- ---
A table displays rows of data. A table displays rows of data.

View File

@ -4,7 +4,7 @@ cols: 1
type: 数据展示 type: 数据展示
title: Table title: Table
subtitle: 表格 subtitle: 表格
cover: https://gw.alipayobjects.com/zos/alicdn/f-SbcX2Lx/Table.svg cover: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*3yz3QqMlShYAAAAAAAAAAAAADrJ8AQ/original
--- ---
展示行列数据。 展示行列数据。

View File

@ -1,136 +0,0 @@
@import './size';
@import (reference) '../../style/themes/index';
@table-prefix-cls: ~'@{ant-prefix}-table';
@table-border: @border-width-base @border-style-base @table-border-color;
.@{table-prefix-cls}.@{table-prefix-cls}-bordered {
// ============================ Title =============================
> .@{table-prefix-cls}-title {
border: @table-border;
border-bottom: 0;
}
> .@{table-prefix-cls}-container {
// ============================ Content ============================
border-left: @table-border;
> .@{table-prefix-cls}-content,
> .@{table-prefix-cls}-header,
> .@{table-prefix-cls}-body,
> .@{table-prefix-cls}-summary {
> table {
// ============================= Cell =============================
> thead > tr > th,
> tbody > tr > td,
> tfoot > tr > th,
> tfoot > tr > td {
border-right: @table-border;
}
// ============================ Header ============================
> thead {
> tr:not(:last-child) > th {
border-bottom: @border-width-base @border-style-base @table-border-color;
}
> tr > th {
&::before {
background-color: transparent !important;
}
}
}
// Fixed right should provides additional border
> thead > tr,
> tbody > tr,
> tfoot > tr {
> .@{table-prefix-cls}-cell-fix-right-first::after {
border-right: @table-border;
}
}
}
// ========================== Expandable ==========================
> table > tbody > tr > td {
> .@{table-prefix-cls}-expanded-row-fixed {
margin: -@table-padding-vertical (-@table-padding-horizontal - @border-width-base);
&::after {
position: absolute;
top: 0;
right: @border-width-base;
bottom: 0;
border-right: @table-border;
content: '';
}
}
}
}
> .@{table-prefix-cls}-content,
> .@{table-prefix-cls}-header {
> table {
border-top: @table-border;
}
}
}
&.@{table-prefix-cls}-scroll-horizontal {
> .@{table-prefix-cls}-container > .@{table-prefix-cls}-body {
> table > tbody {
> tr.@{table-prefix-cls}-expanded-row,
> tr.@{table-prefix-cls}-placeholder {
> td {
border-right: 0;
}
}
}
}
}
// Size related
&.@{table-prefix-cls}-middle {
> .@{table-prefix-cls}-container {
> .@{table-prefix-cls}-content,
> .@{table-prefix-cls}-body {
> table > tbody > tr > td {
> .@{table-prefix-cls}-expanded-row-fixed {
margin: -@table-padding-vertical-md (-@table-padding-horizontal-md - @border-width-base);
}
}
}
}
}
&.@{table-prefix-cls}-small {
> .@{table-prefix-cls}-container {
> .@{table-prefix-cls}-content,
> .@{table-prefix-cls}-body {
> table > tbody > tr > td {
> .@{table-prefix-cls}-expanded-row-fixed {
margin: -@table-padding-vertical-sm (-@table-padding-horizontal-sm - @border-width-base);
}
}
}
}
}
// ============================ Footer ============================
> .@{table-prefix-cls}-footer {
border: @table-border;
border-top: 0;
}
}
.@{table-prefix-cls}-cell {
// ============================ Nested ============================
.@{table-prefix-cls}-container:first-child {
// :first-child to avoid the case when bordered and title is set
border-top: 0;
}
// https://github.com/ant-design/ant-design/issues/35577
&-scrollbar:not([rowspan]) {
box-shadow: 0 @border-width-base 0 @border-width-base @table-header-bg;
}
}

View File

@ -0,0 +1,159 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genBorderedStyle: GenerateStyle<TableToken, CSSObject> = token => {
const { componentCls } = token;
const tableBorder = `${token.lineWidth}px ${token.lineType} ${token.tableBorderColor}`;
const getSizeBorderStyle = (
size: 'small' | 'middle',
paddingVertical: number,
paddingHorizontal: number,
) => ({
[`&${componentCls}-${size}`]: {
[`> ${componentCls}-container`]: {
[`> ${componentCls}-content, > ${componentCls}-body`]: {
'> table > tbody > tr > td': {
[`> ${componentCls}-expanded-row-fixed`]: {
margin: `-${paddingVertical}px -${paddingHorizontal + token.lineWidth}px`,
},
},
},
},
},
});
return {
[`${componentCls}-wrapper`]: {
[`${componentCls}${componentCls}-bordered`]: {
// ============================ Title =============================
[`> ${componentCls}-title`]: {
border: tableBorder,
borderBottom: 0,
},
// ============================ Content ============================
[`> ${componentCls}-container`]: {
borderInlineStart: tableBorder,
[`
> ${componentCls}-content,
> ${componentCls}-header,
> ${componentCls}-body,
> ${componentCls}-summary
`]: {
'> table': {
// ============================= Cell =============================
[`
> thead > tr > th,
> tbody > tr > td,
> tfoot > tr > th,
> tfoot > tr > td
`]: {
borderInlineEnd: tableBorder,
},
// ============================ Header ============================
'> thead': {
'> tr:not(:last-child) > th': {
borderBottom: tableBorder,
},
'> tr > th::before': {
backgroundColor: 'transparent !important',
},
},
// Fixed right should provides additional border
[`
> thead > tr,
> tbody > tr,
> tfoot > tr
`]: {
[`> ${componentCls}-cell-fix-right-first::after`]: {
borderInlineEnd: tableBorder,
},
},
// ========================== Expandable ==========================
'> tbody > tr > td': {
[`> ${componentCls}-expanded-row-fixed`]: {
margin: `-${token.tablePaddingVertical}px -${
token.tablePaddingHorizontal + token.lineWidth
}px`,
'&::after': {
position: 'absolute',
top: 0,
insetInlineEnd: token.lineWidth,
bottom: 0,
borderInlineEnd: tableBorder,
content: '""',
},
},
},
},
},
[`
> ${componentCls}-content,
> ${componentCls}-header
`]: {
'> table': {
borderTop: tableBorder,
},
},
},
// ============================ Scroll ============================
[`&${componentCls}-scroll-horizontal`]: {
[`> ${componentCls}-container > ${componentCls}-body`]: {
'> table > tbody': {
[`
> tr${componentCls}-expanded-row,
> tr${componentCls}-placeholder
`]: {
'> td': {
borderInlineEnd: 0,
},
},
},
},
},
// ============================ Size ============================
...getSizeBorderStyle(
'middle',
token.tablePaddingVerticalMiddle,
token.tablePaddingHorizontalMiddle,
),
...getSizeBorderStyle(
'small',
token.tablePaddingVerticalSmall,
token.tablePaddingHorizontalSmall,
),
// ============================ Footer ============================
[`> ${componentCls}-footer`]: {
border: tableBorder,
borderTop: 0,
},
},
// ============================ Nested ============================
[`${componentCls}-cell`]: {
[`${componentCls}-container:first-child`]: {
// :first-child to avoid the case when bordered and title is set
borderTop: 0,
},
// https://github.com/ant-design/ant-design/issues/35577
'&-scrollbar:not([rowspan])': {
boxShadow: `0 ${token.lineWidth}px 0 ${token.lineWidth}px ${token.tableHeaderBg}`,
},
},
},
};
};
export default genBorderedStyle;

View File

@ -0,0 +1,37 @@
import type { CSSObject } from '../../_util/cssinjs';
import { textEllipsis } from '../../_style';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genEllipsisStyle: GenerateStyle<TableToken, CSSObject> = token => {
const { componentCls } = token;
return {
[`${componentCls}-wrapper`]: {
[`${componentCls}-cell-ellipsis`]: {
...textEllipsis,
wordBreak: 'keep-all',
// Fixed first or last should special process
[`
&${componentCls}-cell-fix-left-last,
&${componentCls}-cell-fix-right-first
`]: {
overflow: 'visible',
[`${componentCls}-cell-content`]: {
display: 'block',
overflow: 'hidden',
textOverflow: 'ellipsis',
},
},
[`${componentCls}-column-title`]: {
overflow: 'hidden',
textOverflow: 'ellipsis',
wordBreak: 'keep-all',
},
},
},
};
};
export default genEllipsisStyle;

View File

@ -0,0 +1,22 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
// ========================= Placeholder ==========================
const genEmptyStyle: GenerateStyle<TableToken, CSSObject> = token => {
const { componentCls } = token;
return {
[`${componentCls}-wrapper`]: {
[`${componentCls}-tbody > tr${componentCls}-placeholder`]: {
textAlign: 'center',
color: token.colorTextDisabled,
'&:hover > td': {
background: token.colorBgContainer,
},
},
},
};
};
export default genEmptyStyle;

View File

@ -0,0 +1,152 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
import { operationUnit } from '../../_style';
const genExpandStyle: GenerateStyle<TableToken, CSSObject> = token => {
const {
componentCls,
antCls,
controlInteractiveSize: checkboxSize,
motionDurationSlow,
lineWidth,
paddingXS,
lineType,
tableBorderColor,
tableExpandIconBg,
tableExpandColumnWidth,
borderRadius,
fontSize,
fontSizeSM,
lineHeight,
tablePaddingVertical,
tablePaddingHorizontal,
tableExpandedRowBg,
paddingXXS,
} = token;
const halfInnerSize = checkboxSize / 2 - lineWidth;
// must be odd number, unless it cannot align center
const expandIconSize = halfInnerSize * 2 + lineWidth * 3;
const tableBorder = `${lineWidth}px ${lineType} ${tableBorderColor}`;
const expandIconLineOffset = paddingXXS - lineWidth;
return {
[`${componentCls}-wrapper`]: {
[`${componentCls}-expand-icon-col`]: {
width: tableExpandColumnWidth,
},
[`${componentCls}-row-expand-icon-cell`]: {
textAlign: 'center',
[`${componentCls}-row-expand-icon`]: {
display: 'inline-flex',
float: 'none',
verticalAlign: 'sub',
},
},
[`${componentCls}-row-indent`]: {
height: 1,
float: 'left',
},
[`${componentCls}-row-expand-icon`]: {
...operationUnit(token),
position: 'relative',
float: 'left',
boxSizing: 'border-box',
width: expandIconSize,
height: expandIconSize,
padding: 0,
color: 'inherit',
lineHeight: `${expandIconSize}px`,
background: tableExpandIconBg,
border: tableBorder,
borderRadius,
transform: `scale(${checkboxSize / expandIconSize})`,
transition: `all ${motionDurationSlow}`,
userSelect: 'none',
[`&:focus, &:hover, &:active`]: {
borderColor: 'currentcolor',
},
[`&::before, &::after`]: {
position: 'absolute',
background: 'currentcolor',
transition: `transform ${motionDurationSlow} ease-out`,
content: '""',
},
'&::before': {
top: halfInnerSize,
insetInlineEnd: expandIconLineOffset,
insetInlineStart: expandIconLineOffset,
height: lineWidth,
},
'&::after': {
top: expandIconLineOffset,
bottom: expandIconLineOffset,
insetInlineStart: halfInnerSize,
width: lineWidth,
transform: 'rotate(90deg)',
},
// Motion effect
'&-collapsed::before': {
transform: 'rotate(-180deg)',
},
'&-collapsed::after': {
transform: 'rotate(0deg)',
},
'&-spaced': {
'&::before, &::after': {
display: 'none',
content: 'none',
},
background: 'transparent',
border: 0,
visibility: 'hidden',
},
},
[`${componentCls}-row-indent + ${componentCls}-row-expand-icon`]: {
marginTop:
(fontSize * lineHeight - lineWidth * 3) / 2 -
Math.ceil((fontSizeSM * 1.4 - lineWidth * 3) / 2),
marginInlineEnd: paddingXS,
},
[`tr${componentCls}-expanded-row`]: {
'&, &:hover': {
'> td': {
background: tableExpandedRowBg,
},
},
// https://github.com/ant-design/ant-design/issues/25573
[`${antCls}-descriptions-view`]: {
display: 'flex',
table: {
flex: 'auto',
width: 'auto',
},
},
},
// With fixed
[`${componentCls}-expanded-row-fixed`]: {
position: 'relative',
margin: `-${tablePaddingVertical}px -${tablePaddingHorizontal}px`,
padding: `${tablePaddingVertical}px ${tablePaddingHorizontal}px`,
},
},
};
};
export default genExpandStyle;

View File

@ -0,0 +1,172 @@
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
import { resetComponent } from '../../_style';
const genFilterStyle: GenerateStyle<TableToken> = token => {
const {
componentCls,
antCls,
iconCls,
tableFilterDropdownWidth,
tableFilterDropdownSearchWidth,
paddingXXS,
paddingXS,
colorText,
lineWidth,
lineType,
tableBorderColor,
tableHeaderIconColor,
fontSizeSM,
tablePaddingHorizontal,
borderRadius,
motionDurationSlow,
colorTextDescription,
colorPrimary,
tableHeaderFilterActiveBg,
colorTextDisabled,
tableFilterDropdownBg,
tableFilterDropdownHeight,
controlItemBgHover,
controlItemBgActive,
boxShadowSecondary,
} = token;
const dropdownPrefixCls = `${antCls}-dropdown`;
const tableFilterDropdownPrefixCls = `${componentCls}-filter-dropdown`;
const treePrefixCls = `${antCls}-tree`;
const tableBorder = `${lineWidth}px ${lineType} ${tableBorderColor}`;
return [
{
[`${componentCls}-wrapper`]: {
[`${componentCls}-filter-column`]: {
display: 'flex',
justifyContent: 'space-between',
},
[`${componentCls}-filter-trigger`]: {
position: 'relative',
display: 'flex',
alignItems: 'center',
marginBlock: -paddingXXS,
marginInline: `${paddingXXS}px ${-tablePaddingHorizontal / 2}px`,
padding: `0 ${paddingXXS}px`,
color: tableHeaderIconColor,
fontSize: fontSizeSM,
borderRadius,
cursor: 'pointer',
transition: `all ${motionDurationSlow}`,
'&:hover': {
color: colorTextDescription,
background: tableHeaderFilterActiveBg,
},
'&.active': {
color: colorPrimary,
},
},
},
},
{
// Dropdown
[`${antCls}-dropdown`]: {
[tableFilterDropdownPrefixCls]: {
...resetComponent(token),
minWidth: tableFilterDropdownWidth,
backgroundColor: tableFilterDropdownBg,
borderRadius,
boxShadow: boxShadowSecondary,
// Reset menu
[`${dropdownPrefixCls}-menu`]: {
// https://github.com/ant-design/ant-design/issues/4916
// https://github.com/ant-design/ant-design/issues/19542
maxHeight: tableFilterDropdownHeight,
overflowX: 'hidden',
border: 0,
boxShadow: 'none',
'&:empty::after': {
display: 'block',
padding: `${paddingXS}px 0`,
color: colorTextDisabled,
fontSize: fontSizeSM,
textAlign: 'center',
content: '"Not Found"',
},
},
[`${tableFilterDropdownPrefixCls}-tree`]: {
paddingBlock: `${paddingXS}px 0`,
paddingInline: paddingXS,
[treePrefixCls]: {
padding: 0,
},
[`${treePrefixCls}-treenode ${treePrefixCls}-node-content-wrapper:hover`]: {
backgroundColor: controlItemBgHover,
},
[`${treePrefixCls}-treenode-checkbox-checked ${treePrefixCls}-node-content-wrapper`]: {
'&, &:hover': {
backgroundColor: controlItemBgActive,
},
},
},
[`${tableFilterDropdownPrefixCls}-search`]: {
padding: paddingXS,
borderBottom: tableBorder,
'&-input': {
input: {
minWidth: tableFilterDropdownSearchWidth,
},
[iconCls]: {
color: colorTextDisabled,
},
},
},
[`${tableFilterDropdownPrefixCls}-checkall`]: {
width: '100%',
marginBottom: paddingXXS,
marginInlineStart: paddingXXS,
},
// Operation
[`${tableFilterDropdownPrefixCls}-btns`]: {
display: 'flex',
justifyContent: 'space-between',
padding: `${paddingXS - lineWidth}px ${paddingXS}px`,
overflow: 'hidden',
backgroundColor: 'inherit',
borderTop: tableBorder,
},
},
},
},
// Dropdown Menu & SubMenu
{
// submenu of table filter dropdown
[`${antCls}-dropdown ${tableFilterDropdownPrefixCls}, ${tableFilterDropdownPrefixCls}-submenu`]:
{
// Checkbox
[`${antCls}-checkbox-wrapper + span`]: {
paddingInlineStart: paddingXS,
color: colorText,
},
[`> ul`]: {
maxHeight: 'calc(100vh - 130px)',
overflowX: 'hidden',
overflowY: 'auto',
},
},
},
];
};
export default genFilterStyle;

View File

@ -0,0 +1,132 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genFixedStyle: GenerateStyle<TableToken, CSSObject> = token => {
const {
componentCls,
lineWidth,
colorSplit,
motionDurationSlow,
zIndexTableFixed,
tableBg,
zIndexTableSticky,
} = token;
const shadowColor = colorSplit;
// Follow style is magic of shadow which should not follow token:
return {
[`${componentCls}-wrapper`]: {
[`
${componentCls}-cell-fix-left,
${componentCls}-cell-fix-right
`]: {
position: 'sticky !important' as 'sticky',
zIndex: zIndexTableFixed,
background: tableBg,
},
[`
${componentCls}-cell-fix-left-first::after,
${componentCls}-cell-fix-left-last::after
`]: {
position: 'absolute',
top: 0,
right: {
_skip_check_: true,
value: 0,
},
bottom: -lineWidth,
width: 30,
transform: 'translateX(100%)',
transition: `box-shadow ${motionDurationSlow}`,
content: '""',
pointerEvents: 'none',
},
[`${componentCls}-cell-fix-left-all::after`]: {
display: 'none',
},
[`
${componentCls}-cell-fix-right-first::after,
${componentCls}-cell-fix-right-last::after
`]: {
position: 'absolute',
top: 0,
bottom: -lineWidth,
left: {
_skip_check_: true,
value: 0,
},
width: 30,
transform: 'translateX(-100%)',
transition: `box-shadow ${motionDurationSlow}`,
content: '""',
pointerEvents: 'none',
},
[`${componentCls}-container`]: {
'&::before, &::after': {
position: 'absolute',
top: 0,
bottom: 0,
zIndex: zIndexTableSticky + 1,
width: 30,
transition: `box-shadow ${motionDurationSlow}`,
content: '""',
pointerEvents: 'none',
},
'&::before': {
insetInlineStart: 0,
},
'&::after': {
insetInlineEnd: 0,
},
},
[`${componentCls}-ping-left`]: {
[`&:not(${componentCls}-has-fix-left) ${componentCls}-container`]: {
position: 'relative',
'&::before': {
boxShadow: `inset 10px 0 8px -8px ${shadowColor}`,
},
},
[`
${componentCls}-cell-fix-left-first::after,
${componentCls}-cell-fix-left-last::after
`]: {
boxShadow: `inset 10px 0 8px -8px ${shadowColor}`,
},
[`${componentCls}-cell-fix-left-last::before`]: {
backgroundColor: 'transparent !important',
},
},
[`${componentCls}-ping-right`]: {
[`&:not(${componentCls}-has-fix-right) ${componentCls}-container`]: {
position: 'relative',
'&::after': {
boxShadow: `inset -10px 0 8px -8px ${shadowColor}`,
},
},
[`
${componentCls}-cell-fix-right-first::after,
${componentCls}-cell-fix-right-last::after
`]: {
boxShadow: `inset -10px 0 8px -8px ${shadowColor}`,
},
},
},
};
};
export default genFixedStyle;

View File

@ -1,754 +0,0 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@import './size';
@import './bordered';
@table-prefix-cls: ~'@{ant-prefix}-table';
@tree-prefix-cls: ~'@{ant-prefix}-tree';
@dropdown-prefix-cls: ~'@{ant-prefix}-dropdown';
@descriptions-prefix-cls: ~'@{ant-prefix}-descriptions';
@table-header-icon-color: #bfbfbf;
@table-header-icon-color-hover: darken(@table-header-icon-color, 10%);
@table-sticky-zindex: calc(@zindex-table-fixed + 1);
@table-sticky-scroll-bar-active-bg: fade(@table-sticky-scroll-bar-bg, 80%);
@table-filter-dropdown-max-height: 264px;
.@{table-prefix-cls}-wrapper {
clear: both;
max-width: 100%;
.clearfix();
}
.@{table-prefix-cls} {
.reset-component();
position: relative;
font-size: @table-font-size;
background: @table-bg;
border-radius: @table-border-radius-base;
// https://github.com/ant-design/ant-design/issues/17611
table {
width: 100%;
text-align: left;
border-radius: @table-border-radius-base @table-border-radius-base 0 0;
border-collapse: separate;
border-spacing: 0;
}
// ============================= Cell =============================
&-thead > tr > th,
&-tbody > tr > td,
tfoot > tr > th,
tfoot > tr > td {
position: relative;
padding: @table-padding-vertical @table-padding-horizontal;
overflow-wrap: break-word;
}
&-cell-ellipsis {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
word-break: keep-all;
// Fixed first or last should special process
&.@{table-prefix-cls}-cell-fix-left-last,
&.@{table-prefix-cls}-cell-fix-right-first {
overflow: visible;
.@{table-prefix-cls}-cell-content {
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
}
.@{table-prefix-cls}-column-title {
overflow: hidden;
text-overflow: ellipsis;
word-break: keep-all;
}
}
// ============================ Title =============================
&-title {
padding: @table-padding-vertical @table-padding-horizontal;
}
// ============================ Footer ============================
&-footer {
padding: @table-padding-vertical @table-padding-horizontal;
color: @table-footer-color;
background: @table-footer-bg;
}
// ============================ Header ============================
&-thead {
> tr {
> th {
position: relative;
color: @table-header-color;
font-weight: 500;
text-align: left;
background: @table-header-bg;
border-bottom: @border-width-base @border-style-base @table-border-color;
transition: background 0.3s ease;
&[colspan]:not([colspan='1']) {
text-align: center;
}
&:not(:last-child):not(.@{table-prefix-cls}-selection-column):not(.@{table-prefix-cls}-row-expand-icon-cell):not([colspan])::before {
position: absolute;
top: 50%;
right: 0;
width: 1px;
height: 1.6em;
background-color: @table-header-cell-split-color;
transform: translateY(-50%);
transition: background-color 0.3s;
content: '';
}
}
}
> tr:not(:last-child) > th {
&[colspan] {
border-bottom: 0;
}
}
}
// ============================= Body =============================
&-tbody {
> tr {
> td {
border-bottom: @border-width-base @border-style-base @table-border-color;
transition: background 0.3s;
// ========================= Nest Table ===========================
> .@{table-prefix-cls}-wrapper:only-child,
> .@{table-prefix-cls}-expanded-row-fixed > .@{table-prefix-cls}-wrapper:only-child {
.@{table-prefix-cls} {
margin: -@table-padding-vertical -@table-padding-horizontal -@table-padding-vertical (@table-padding-horizontal +
ceil(@font-size-sm * 1.4));
&-tbody > tr:last-child > td {
border-bottom: 0;
&:first-child,
&:last-child {
border-radius: 0;
}
}
}
}
}
&.@{table-prefix-cls}-row:hover > td,
> td.@{table-prefix-cls}-cell-row-hover {
background: @table-row-hover-bg;
}
&.@{table-prefix-cls}-row-selected {
> td {
background: @table-selected-row-bg;
border-color: rgba(0, 0, 0, 0.03);
}
&:hover {
> td {
background: @table-selected-row-hover-bg;
}
}
}
}
}
// =========================== Summary ============================
&-summary {
position: relative;
z-index: @zindex-table-fixed;
background: @table-bg;
div& {
box-shadow: 0 -@border-width-base 0 @table-border-color;
}
> tr {
> th,
> td {
border-bottom: @border-width-base @border-style-base @table-border-color;
}
}
}
// ========================== Pagination ==========================
&-pagination.@{ant-prefix}-pagination {
margin: 16px 0;
}
&-pagination {
display: flex;
flex-wrap: wrap;
row-gap: @padding-xs;
> * {
flex: none;
}
&-left {
justify-content: flex-start;
}
&-center {
justify-content: center;
}
&-right {
justify-content: flex-end;
}
}
// ================================================================
// = Function =
// ================================================================
// ============================ Sorter ============================
&-thead th.@{table-prefix-cls}-column-has-sorters {
outline: none;
cursor: pointer;
transition: all 0.3s;
&:hover {
background: @table-header-sort-active-bg;
&::before {
background-color: transparent !important;
}
}
&:focus-visible {
color: @primary-color;
}
// https://github.com/ant-design/ant-design/issues/30969
&.@{table-prefix-cls}-cell-fix-left:hover,
&.@{table-prefix-cls}-cell-fix-right:hover {
background: @table-fixed-header-sort-active-bg;
}
}
&-thead th.@{table-prefix-cls}-column-sort {
background: @table-header-sort-bg;
&::before {
background-color: transparent !important;
}
}
td&-column-sort {
background: @table-body-sort-bg;
}
&-column-title {
position: relative;
z-index: 1;
flex: 1;
}
&-column-sorters {
display: flex;
flex: auto;
align-items: center;
justify-content: space-between;
&::after {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
}
}
&-column-sorter {
margin-left: 4px;
color: @table-header-icon-color;
font-size: 0;
transition: color 0.3s;
&-inner {
display: inline-flex;
flex-direction: column;
align-items: center;
}
&-up,
&-down {
font-size: 11px;
&.active {
color: @primary-color;
}
}
&-up + &-down {
margin-top: -0.3em;
}
}
&-column-sorters:hover &-column-sorter {
color: darken(@table-header-icon-color, 10%);
}
// ============================ Filter ============================
&-filter-column {
display: flex;
justify-content: space-between;
}
&-filter-trigger {
position: relative;
display: flex;
align-items: center;
margin: -4px (-@table-padding-horizontal / 2) -4px 4px;
padding: 0 4px;
color: @table-header-icon-color;
font-size: @font-size-sm;
border-radius: @border-radius-base;
cursor: pointer;
transition: all 0.3s;
&:hover {
color: @text-color-secondary;
background: @table-header-filter-active-bg;
}
&.active {
color: @primary-color;
}
}
// Dropdown
&-filter-dropdown {
.reset-component();
min-width: 120px;
background-color: @table-filter-dropdown-bg;
border-radius: @border-radius-base;
box-shadow: @box-shadow-base;
// Reset menu
.@{dropdown-prefix-cls}-menu {
// https://github.com/ant-design/ant-design/issues/4916
// https://github.com/ant-design/ant-design/issues/19542
max-height: @table-filter-dropdown-max-height;
overflow-x: hidden;
border: 0;
box-shadow: none;
&:empty::after {
display: block;
padding: 8px 0;
color: @disabled-color;
font-size: @font-size-sm;
text-align: center;
content: 'Not Found';
}
}
&-tree {
padding: 8px 8px 0;
.@{tree-prefix-cls}-treenode .@{tree-prefix-cls}-node-content-wrapper:hover {
background-color: @tree-node-hover-bg;
}
.@{tree-prefix-cls}-treenode-checkbox-checked .@{tree-prefix-cls}-node-content-wrapper {
&,
&:hover {
background-color: @tree-node-selected-bg;
}
}
}
&-search {
padding: 8px;
border-bottom: @border-width-base @border-color-split @border-style-base;
&-input {
input {
min-width: 140px;
}
.@{iconfont-css-prefix} {
color: @disabled-color;
}
}
}
&-checkall {
width: 100%;
margin-bottom: 4px;
margin-left: 4px;
}
&-submenu > ul {
max-height: calc(100vh - 130px);
overflow-x: hidden;
overflow-y: auto;
}
// Checkbox
&,
&-submenu {
.@{ant-prefix}-checkbox-wrapper + span {
padding-left: 8px;
}
}
// Operation
&-btns {
display: flex;
justify-content: space-between;
padding: 7px 8px;
overflow: hidden;
background-color: @table-filter-btns-bg;
border-top: @border-width-base @border-style-base @table-border-color;
}
}
// ========================== Selections ==========================
&-selection-col {
width: @table-selection-column-width;
}
&-bordered &-selection-col {
width: @table-selection-column-width + 18px;
}
table tr th&-selection-column,
table tr td&-selection-column {
padding-right: @padding-xs;
padding-left: @padding-xs;
text-align: center;
.@{ant-prefix}-radio-wrapper {
margin-right: 0;
}
}
table tr th&-selection-column&-cell-fix-left {
z-index: 3;
}
table tr th&-selection-column::after {
background-color: transparent !important;
}
&-selection {
position: relative;
display: inline-flex;
flex-direction: column;
&-extra {
position: absolute;
top: 0;
z-index: 1;
cursor: pointer;
transition: all 0.3s;
margin-inline-start: 100%;
padding-inline-start: (@table-padding-horizontal / 4);
.@{iconfont-css-prefix} {
color: @table-header-icon-color;
font-size: 10px;
&:hover {
color: @table-header-icon-color-hover;
}
}
}
}
// ========================== Expandable ==========================
&-expand-icon-col {
width: 48px;
}
&-row-expand-icon-cell {
text-align: center;
}
&-row-indent {
float: left;
height: 1px;
}
&-row-expand-icon {
.operation-unit();
position: relative;
display: inline-flex;
float: left;
box-sizing: border-box;
width: @expand-icon-size;
height: @expand-icon-size;
padding: 0;
color: inherit;
line-height: ceil(((@font-size-sm * 1.4 - @border-width-base * 3) / 2)) * 2 + @border-width-base *
3;
background: @table-expand-icon-bg;
border: @border-width-base @border-style-base @table-border-color;
border-radius: @border-radius-base;
outline: none;
transform: scale((unit(@checkbox-size) / unit(@expand-icon-size)));
transition: all 0.3s;
user-select: none;
@expand-icon-size: ceil(((@font-size-sm * 1.4 - @border-width-base * 3) / 2)) * 2 +
@border-width-base * 3;
&:focus,
&:hover,
&:active {
border-color: currentcolor;
}
&::before,
&::after {
position: absolute;
background: currentcolor;
transition: transform 0.3s ease-out;
content: '';
}
&::before {
top: ceil(((@font-size-sm * 1.4 - @border-width-base * 3) / 2));
right: 3px;
left: 3px;
height: @border-width-base;
}
&::after {
top: 3px;
bottom: 3px;
left: ceil(((@font-size-sm * 1.4 - @border-width-base * 3) / 2));
width: @border-width-base;
transform: rotate(90deg);
}
// Motion effect
&-collapsed::before {
transform: rotate(-180deg);
}
&-collapsed::after {
transform: rotate(0deg);
}
&-spaced {
&::before,
&::after {
display: none;
content: none;
}
background: transparent;
border: 0;
visibility: hidden;
}
.@{table-prefix-cls}-row-indent + & {
margin-top: ((@font-size-base * @line-height-base - @border-width-base * 3) / 2) -
ceil(((@font-size-sm * 1.4 - @border-width-base * 3) / 2));
margin-right: @padding-xs;
}
}
tr&-expanded-row {
&,
&:hover {
> td {
background: @table-expanded-row-bg;
}
}
// https://github.com/ant-design/ant-design/issues/25573
.@{descriptions-prefix-cls}-view {
display: flex;
table {
flex: auto;
width: auto;
}
}
}
// With fixed
.@{table-prefix-cls}-expanded-row-fixed {
position: relative;
margin: -@table-padding-vertical -@table-padding-horizontal;
padding: @table-padding-vertical @table-padding-horizontal;
}
// ========================= Placeholder ==========================
&-tbody > tr&-placeholder {
text-align: center;
.@{table-prefix-cls}-empty & {
color: @disabled-color;
}
&:hover {
> td {
background: @component-background;
}
}
}
// ============================ Fixed =============================
&-cell-fix-left,
&-cell-fix-right {
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: @zindex-table-fixed;
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%);
}
}
&-sticky {
&-holder {
position: sticky;
z-index: @table-sticky-zindex;
background: @component-background;
}
&-scroll {
position: sticky;
bottom: 0;
z-index: @table-sticky-zindex;
display: flex;
align-items: center;
background: lighten(@table-border-color, 80%);
border-top: 1px solid @table-border-color;
opacity: 0.6;
&:hover {
transform-origin: center bottom;
}
&-bar {
height: 8px;
background-color: @table-sticky-scroll-bar-bg;
border-radius: @table-sticky-scroll-bar-radius;
&:hover {
background-color: @table-sticky-scroll-bar-active-bg;
}
&-active {
background-color: @table-sticky-scroll-bar-active-bg;
}
}
}
}
}
@media all and (-ms-high-contrast: none) {
.@{table-prefix-cls} {
&-ping-left {
.@{table-prefix-cls}-cell-fix-left-last::after {
box-shadow: none !important;
}
}
&-ping-right {
.@{table-prefix-cls}-cell-fix-right-first::after {
box-shadow: none !important;
}
}
}
}
@import './radius';
@import './rtl';

View File

@ -0,0 +1,409 @@
import type { CSSObject } from '../../_util/cssinjs';
import { TinyColor } from '@ctrl/tinycolor';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import genBorderedStyle from './bordered';
import genEllipsisStyle from './ellipsis';
import genEmptyStyle from './empty';
import genExpandStyle from './expand';
import genFilterStyle from './filter';
import genFixedStyle from './fixed';
import genPaginationStyle from './pagination';
import genRadiusStyle from './radius';
import genRtlStyle from './rtl';
import genSelectionStyle from './selection';
import genSizeStyle from './size';
import genSorterStyle from './sorter';
import genStickyStyle from './sticky';
import genSummaryStyle from './summary';
import { clearFix, resetComponent } from '../../_style';
export interface ComponentToken {}
export interface TableToken extends FullToken<'Table'> {
tableFontSize: number;
tableBg: string;
tableRadius: number;
tablePaddingHorizontal: number;
tablePaddingVertical: number;
tablePaddingHorizontalMiddle: number;
tablePaddingVerticalMiddle: number;
tablePaddingHorizontalSmall: number;
tablePaddingVerticalSmall: number;
tableBorderColor: string;
tableHeaderTextColor: string;
tableHeaderBg: string;
tableFooterTextColor: string;
tableFooterBg: string;
tableHeaderCellSplitColor: string;
tableHeaderSortBg: string;
tableHeaderSortHoverBg: string;
tableHeaderIconColor: string;
tableHeaderIconColorHover: string;
tableBodySortBg: string;
tableFixedHeaderSortActiveBg: string;
tableHeaderFilterActiveBg: string;
tableFilterDropdownBg: string;
tableFilterDropdownHeight: number;
tableRowHoverBg: string;
tableSelectedRowBg: string;
tableSelectedRowHoverBg: string;
tableFontSizeMiddle: number;
tableFontSizeSmall: number;
tableSelectionColumnWidth: number;
tableExpandIconBg: string;
tableExpandColumnWidth: number;
tableExpandedRowBg: string;
tableFilterDropdownWidth: number;
tableFilterDropdownSearchWidth: number;
// Z-Index
zIndexTableFixed: number;
zIndexTableSticky: number;
// Virtual Scroll Bar
tableScrollThumbSize: number;
tableScrollThumbBg: string;
tableScrollThumbBgHover: string;
tableScrollBg: string;
}
const genTableStyle: GenerateStyle<TableToken, CSSObject> = token => {
const {
componentCls,
fontWeightStrong,
tablePaddingVertical,
tablePaddingHorizontal,
lineWidth,
lineType,
tableBorderColor,
tableFontSize,
tableBg,
tableRadius,
tableHeaderTextColor,
motionDurationMid,
tableHeaderBg,
tableHeaderCellSplitColor,
tableRowHoverBg,
tableSelectedRowBg,
tableSelectedRowHoverBg,
tableFooterTextColor,
tableFooterBg,
paddingContentVerticalLG,
wireframe,
} = token;
const tableBorder = `${lineWidth}px ${lineType} ${tableBorderColor}`;
return {
[`${componentCls}-wrapper`]: {
clear: 'both',
maxWidth: '100%',
...clearFix(),
[componentCls]: {
...resetComponent(token),
fontSize: tableFontSize,
background: tableBg,
borderRadius: `${tableRadius}px ${tableRadius}px 0 0`,
},
// https://github.com/ant-design/ant-design/issues/17611
table: {
width: '100%',
textAlign: 'start',
borderRadius: `${tableRadius}px ${tableRadius}px 0 0`,
borderCollapse: 'separate',
borderSpacing: 0,
},
// ============================= Cell =============================
[`
${componentCls}-thead > tr > th,
${componentCls}-tbody > tr > td,
tfoot > tr > th,
tfoot > tr > td
`]: {
position: 'relative',
padding: `${paddingContentVerticalLG}px ${tablePaddingHorizontal}px`,
overflowWrap: 'break-word',
},
// ============================ Title =============================
[`${componentCls}-title`]: {
padding: `${tablePaddingVertical}px ${tablePaddingHorizontal}px`,
},
// ============================ Header ============================
[`${componentCls}-thead`]: {
[`
> tr > th,
> tr > td
`]: {
position: 'relative',
color: tableHeaderTextColor,
fontWeight: fontWeightStrong,
textAlign: 'start',
background: tableHeaderBg,
borderBottom: tableBorder,
transition: `background ${motionDurationMid} ease`,
"&[colspan]:not([colspan='1'])": {
textAlign: 'center',
},
[`&:not(:last-child):not(${componentCls}-selection-column):not(${componentCls}-row-expand-icon-cell):not([colspan])::before`]:
{
position: 'absolute',
top: '50%',
insetInlineEnd: 0,
width: 1,
height: '1.6em',
backgroundColor: tableHeaderCellSplitColor,
transform: 'translateY(-50%)',
transition: `background-color ${motionDurationMid}`,
content: '""',
},
},
'> tr:not(:last-child) > th[colspan]': {
borderBottom: 0,
},
},
// ============================ Body ============================
// Borderless Table has unique hover style, which would be implemented with `borderTop`.
[`${componentCls}:not(${componentCls}-bordered)`]: {
[`${componentCls}-tbody`]: {
'> tr': {
'> td': {
borderTop: tableBorder,
borderBottom: 'transparent',
},
'&:last-child > td': {
borderBottom: tableBorder,
},
[`&:first-child > td,
&${componentCls}-measure-row + tr > td`]: {
borderTop: 'none',
borderTopColor: 'transparent',
},
},
},
},
// Bordered Table remains simple `borderBottom`.
// Ref issue: https://github.com/ant-design/ant-design/issues/38724
[`${componentCls}${componentCls}-bordered`]: {
[`${componentCls}-tbody`]: {
'> tr': {
'> td': {
borderBottom: tableBorder,
},
},
},
},
[`${componentCls}-tbody`]: {
'> tr': {
'> td': {
transition: `background ${motionDurationMid}, border-color ${motionDurationMid}`,
// ========================= Nest Table ===========================
[`
> ${componentCls}-wrapper:only-child,
> ${componentCls}-expanded-row-fixed > ${componentCls}-wrapper:only-child
`]: {
[componentCls]: {
marginBlock: `-${tablePaddingVertical}px`,
marginInline: `${
token.tableExpandColumnWidth - tablePaddingHorizontal
}px -${tablePaddingHorizontal}px`,
[`${componentCls}-tbody > tr:last-child > td`]: {
borderBottom: 0,
'&:first-child, &:last-child': {
borderRadius: 0,
},
},
},
},
},
[`
&${componentCls}-row:hover > td,
> td${componentCls}-cell-row-hover
`]: {
background: tableRowHoverBg,
},
[`&${componentCls}-row-selected`]: {
'> td': {
background: tableSelectedRowBg,
},
'&:hover > td': {
background: tableSelectedRowHoverBg,
},
},
},
},
[`${componentCls}:not(${componentCls}-bordered) ${componentCls}-tbody > tr`]: wireframe
? undefined
: {
[`&${componentCls}-row:hover, &${componentCls}-row${componentCls}-row-selected`]: {
[`+ tr${componentCls}-row > td`]: {
borderTopColor: 'transparent',
},
},
[`&${componentCls}-row:last-child:hover > td,
&${componentCls}-row${componentCls}-row-selected:last-child > td`]: {
borderBottomColor: 'transparent',
},
[`
&${componentCls}-row:hover > td,
> td${componentCls}-cell-row-hover,
&${componentCls}-row${componentCls}-row-selected > td
`]: {
borderTopColor: 'transparent',
'&:first-child': {
borderStartStartRadius: tableRadius,
borderEndStartRadius: tableRadius,
},
'&:last-child': {
borderStartEndRadius: tableRadius,
borderEndEndRadius: tableRadius,
},
},
},
// ============================ Footer ============================
[`${componentCls}-footer`]: {
padding: `${tablePaddingVertical}px ${tablePaddingHorizontal}px`,
color: tableFooterTextColor,
background: tableFooterBg,
},
},
};
};
// ============================== Export ==============================
export default genComponentStyleHook('Table', token => {
const {
controlItemBgActive,
controlItemBgActiveHover,
colorTextPlaceholder,
colorTextHeading,
colorSplit,
colorBorderSecondary,
fontSize,
padding,
paddingXS,
paddingSM,
controlHeight,
colorFillAlter,
colorIcon,
colorIconHover,
opacityLoading,
colorBgContainer,
borderRadiusLG,
colorFillContent,
colorFillSecondary,
controlInteractiveSize: checkboxSize,
} = token;
const baseColorAction = new TinyColor(colorIcon);
const baseColorActionHover = new TinyColor(colorIconHover);
const tableSelectedRowBg = controlItemBgActive;
const zIndexTableFixed: number = 2;
const colorFillSecondarySolid = new TinyColor(colorFillSecondary)
.onBackground(colorBgContainer)
.toHexString();
const colorFillContentSolid = new TinyColor(colorFillContent)
.onBackground(colorBgContainer)
.toHexString();
const colorFillAlterSolid = new TinyColor(colorFillAlter)
.onBackground(colorBgContainer)
.toHexString();
const tableToken = mergeToken<TableToken>(token, {
tableFontSize: fontSize,
tableBg: colorBgContainer,
tableRadius: borderRadiusLG,
tablePaddingVertical: padding,
tablePaddingHorizontal: padding,
tablePaddingVerticalMiddle: paddingSM,
tablePaddingHorizontalMiddle: paddingXS,
tablePaddingVerticalSmall: paddingXS,
tablePaddingHorizontalSmall: paddingXS,
tableBorderColor: colorBorderSecondary,
tableHeaderTextColor: colorTextHeading,
tableHeaderBg: colorFillAlterSolid,
tableFooterTextColor: colorTextHeading,
tableFooterBg: colorFillAlterSolid,
tableHeaderCellSplitColor: colorBorderSecondary,
tableHeaderSortBg: colorFillSecondarySolid,
tableHeaderSortHoverBg: colorFillContentSolid,
tableHeaderIconColor: baseColorAction
.clone()
.setAlpha(baseColorAction.getAlpha() * opacityLoading)
.toRgbString(),
tableHeaderIconColorHover: baseColorActionHover
.clone()
.setAlpha(baseColorActionHover.getAlpha() * opacityLoading)
.toRgbString(),
tableBodySortBg: colorFillAlterSolid,
tableFixedHeaderSortActiveBg: colorFillSecondarySolid,
tableHeaderFilterActiveBg: colorFillContent,
tableFilterDropdownBg: colorBgContainer,
tableRowHoverBg: colorFillAlterSolid,
tableSelectedRowBg,
tableSelectedRowHoverBg: controlItemBgActiveHover,
zIndexTableFixed,
zIndexTableSticky: zIndexTableFixed + 1,
tableFontSizeMiddle: fontSize,
tableFontSizeSmall: fontSize,
tableSelectionColumnWidth: controlHeight,
tableExpandIconBg: colorBgContainer,
tableExpandColumnWidth: checkboxSize + 2 * token.padding,
tableExpandedRowBg: colorFillAlter,
// Dropdown
tableFilterDropdownWidth: 120,
tableFilterDropdownHeight: 264,
tableFilterDropdownSearchWidth: 140,
// Virtual Scroll Bar
tableScrollThumbSize: 8, // Mac scroll bar size
tableScrollThumbBg: colorTextPlaceholder,
tableScrollThumbBgHover: colorTextHeading,
tableScrollBg: colorSplit,
});
return [
genTableStyle(tableToken),
genPaginationStyle(tableToken),
genSummaryStyle(tableToken),
genSorterStyle(tableToken),
genFilterStyle(tableToken),
genBorderedStyle(tableToken),
genRadiusStyle(tableToken),
genExpandStyle(tableToken),
genSummaryStyle(tableToken),
genEmptyStyle(tableToken),
genSelectionStyle(tableToken),
genFixedStyle(tableToken),
genStickyStyle(tableToken),
genEllipsisStyle(tableToken),
genSizeStyle(tableToken),
genRtlStyle(tableToken),
];
});

View File

@ -1,16 +0,0 @@
import '../../style/index.less';
import './index.less';
// style dependencies
// deps-lint-skip: menu
// deps-lint-skip: grid
import '../../button/style';
import '../../empty/style';
import '../../radio/style';
import '../../checkbox/style';
import '../../dropdown/style';
import '../../spin/style';
import '../../pagination/style';
import '../../tooltip/style';
import '../../input/style';
import '../../tree/style';

View File

@ -0,0 +1,39 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genPaginationStyle: GenerateStyle<TableToken, CSSObject> = token => {
const { componentCls, antCls } = token;
return {
[`${componentCls}-wrapper`]: {
// ========================== Pagination ==========================
[`${componentCls}-pagination${antCls}-pagination`]: {
margin: `${token.margin}px 0`,
},
[`${componentCls}-pagination`]: {
display: 'flex',
flexWrap: 'wrap',
rowGap: token.paddingXS,
'> *': {
flex: 'none',
},
'&-left': {
justifyContent: 'flex-start',
},
'&-center': {
justifyContent: 'center',
},
'&-right': {
justifyContent: 'flex-end',
},
},
},
};
};
export default genPaginationStyle;

View File

@ -1,45 +0,0 @@
// ================================================================
// = Border Radio =
// ================================================================
.@{table-prefix-cls} {
/* title + table */
&-title {
border-radius: @table-border-radius-base @table-border-radius-base 0 0;
}
&-title + &-container {
border-top-left-radius: 0;
border-top-right-radius: 0;
table > thead > tr:first-child {
th:first-child {
border-radius: 0;
}
th:last-child {
border-radius: 0;
}
}
}
/* table */
&-container {
border-top-left-radius: @table-border-radius-base;
border-top-right-radius: @table-border-radius-base;
table > thead > tr:first-child {
th:first-child {
border-top-left-radius: @table-border-radius-base;
}
th:last-child {
border-top-right-radius: @table-border-radius-base;
}
}
}
/* table + footer */
&-footer {
border-radius: 0 0 @table-border-radius-base @table-border-radius-base;
}
}

View File

@ -0,0 +1,57 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genRadiusStyle: GenerateStyle<TableToken, CSSObject> = token => {
const { componentCls, tableRadius } = token;
return {
[`${componentCls}-wrapper`]: {
[componentCls]: {
// https://github.com/ant-design/ant-design/issues/39115#issuecomment-1362314574
[`${componentCls}-title, ${componentCls}-header`]: {
borderRadius: `${tableRadius}px ${tableRadius}px 0 0`,
},
[`${componentCls}-title + ${componentCls}-container`]: {
borderStartStartRadius: 0,
borderStartEndRadius: 0,
table: {
borderRadius: 0,
'> thead > tr:first-child': {
'th:first-child': {
borderRadius: 0,
},
'th:last-child': {
borderRadius: 0,
},
},
},
},
'&-container': {
borderStartStartRadius: tableRadius,
borderStartEndRadius: tableRadius,
'table > thead > tr:first-child': {
'> *:first-child': {
borderStartStartRadius: tableRadius,
},
'> *:last-child': {
borderStartEndRadius: tableRadius,
},
},
},
'&-footer': {
borderRadius: `0 0 ${tableRadius}px ${tableRadius}px`,
},
},
},
};
};
export default genRadiusStyle;

View File

@ -1,41 +0,0 @@
.@{table-prefix-cls}-resize-handle {
position: absolute;
top: 0;
height: 100% !important;
bottom: 0;
left: auto !important;
right: -8px;
cursor: col-resize;
touch-action: none;
user-select: auto;
width: 16px;
z-index: 1;
&-line {
display: block;
width: 1px;
margin-left: 7px;
height: 100% !important;
background-color: @primary-color;
opacity: 0;
}
&:hover &-line {
opacity: 1;
}
}
.@{table-prefix-cls}-resize-handle.dragging {
overflow: hidden;
.@{table-prefix-cls}-resize-handle-line {
opacity: 1;
}
&:before {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
content: ' ';
width: 200vw;
transform: translateX(-50%);
opacity: 0;
}
}

View File

@ -1,168 +0,0 @@
@import '../../style/themes/index';
@import '../../style/mixins/index';
@table-prefix-cls: ~'@{ant-prefix}-table';
@table-wrapepr-cls: ~'@{table-prefix-cls}-wrapper';
@table-wrapepr-rtl-cls: ~'@{table-prefix-cls}-wrapper-rtl';
.@{table-prefix-cls}-wrapper {
&-rtl {
direction: rtl;
}
}
.@{table-prefix-cls} {
&-rtl {
direction: rtl;
}
table {
.@{table-wrapepr-rtl-cls} & {
text-align: right;
}
}
// ============================ Header ============================
&-thead {
> tr {
> th {
&[colspan]:not([colspan='1']) {
.@{table-wrapepr-rtl-cls} & {
text-align: center;
}
}
&:not(:last-child):not(.@{table-prefix-cls}-selection-column):not(.@{table-prefix-cls}-row-expand-icon-cell):not([colspan])::before {
.@{table-wrapepr-rtl-cls} & {
right: auto;
left: 0;
}
}
.@{table-wrapepr-rtl-cls} & {
text-align: right;
}
}
}
}
// ============================= Body =============================
&-tbody {
> tr {
// ========================= Nest Table ===========================
.@{table-prefix-cls}-wrapper:only-child {
.@{table-prefix-cls}.@{table-prefix-cls}-rtl {
margin: -@table-padding-vertical (@table-padding-horizontal + ceil(@font-size-sm * 1.4)) -@table-padding-vertical -@table-padding-horizontal;
}
}
}
}
// ========================== Pagination ==========================
&-pagination {
&-left {
.@{table-wrapepr-cls}.@{table-wrapepr-rtl-cls} & {
justify-content: flex-end;
}
}
&-right {
.@{table-wrapepr-cls}.@{table-wrapepr-rtl-cls} & {
justify-content: flex-start;
}
}
}
// ================================================================
// = Function =
// ================================================================
// ============================ Sorter ============================
&-column-sorter {
.@{table-wrapepr-rtl-cls} & {
margin-right: 4px;
margin-left: 0;
}
}
// ============================ Filter ============================
&-filter-column-title {
.@{table-wrapepr-rtl-cls} & {
padding: @table-padding-vertical @table-padding-horizontal @table-padding-vertical 2.3em;
}
}
&-thead tr th.@{table-prefix-cls}-column-has-sorters {
.@{table-prefix-cls}-filter-column-title {
.@{table-prefix-cls}-rtl & {
padding: 0 0 0 2.3em;
}
}
}
&-filter-trigger {
.@{table-wrapepr-rtl-cls} & {
margin: -4px 4px -4px (-@table-padding-horizontal / 2);
}
}
// Dropdown
&-filter-dropdown {
// Checkbox
&,
&-submenu {
.@{ant-prefix}-checkbox-wrapper + span {
.@{ant-prefix}-dropdown-rtl &,
.@{ant-prefix}-dropdown-menu-submenu-rtl& {
padding-right: 8px;
padding-left: 0;
}
}
}
}
// ========================== Selections ==========================
&-selection {
.@{table-wrapepr-rtl-cls} & {
text-align: center;
}
}
// ========================== Expandable ==========================
&-row-indent {
.@{table-wrapepr-rtl-cls} & {
float: right;
}
}
&-row-expand-icon {
.@{table-wrapepr-rtl-cls} & {
float: right;
}
.@{table-prefix-cls}-row-indent + & {
.@{table-wrapepr-rtl-cls} & {
margin-right: 0;
margin-left: @padding-xs;
}
}
&::after {
.@{table-wrapepr-rtl-cls} & {
transform: rotate(-90deg);
}
}
&-collapsed::before {
.@{table-wrapepr-rtl-cls} & {
transform: rotate(180deg);
}
}
&-collapsed::after {
.@{table-wrapepr-rtl-cls} & {
transform: rotate(0deg);
}
}
}
}

View File

@ -0,0 +1,39 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genStyle: GenerateStyle<TableToken, CSSObject> = token => {
const { componentCls } = token;
return {
[`${componentCls}-wrapper-rtl`]: {
direction: 'rtl',
table: {
direction: 'rtl',
},
[`${componentCls}-pagination-left`]: {
justifyContent: 'flex-end',
},
[`${componentCls}-pagination-right`]: {
justifyContent: 'flex-start',
},
[`${componentCls}-row-expand-icon`]: {
'&::after': {
transform: 'rotate(-90deg)',
},
'&-collapsed::before': {
transform: 'rotate(180deg)',
},
'&-collapsed::after': {
transform: 'rotate(0deg)',
},
},
},
};
};
export default genStyle;

View File

@ -0,0 +1,76 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genSelectionStyle: GenerateStyle<TableToken, CSSObject> = token => {
const {
componentCls,
antCls,
iconCls,
fontSizeIcon,
paddingXS,
tableHeaderIconColor,
tableHeaderIconColorHover,
} = token;
return {
[`${componentCls}-wrapper`]: {
// ========================== Selections ==========================
[`${componentCls}-selection-col`]: {
width: token.tableSelectionColumnWidth,
},
[`${componentCls}-bordered ${componentCls}-selection-col`]: {
width: token.tableSelectionColumnWidth + paddingXS * 2,
},
[`
table tr th${componentCls}-selection-column,
table tr td${componentCls}-selection-column
`]: {
paddingInlineEnd: token.paddingXS,
paddingInlineStart: token.paddingXS,
textAlign: 'center',
[`${antCls}-radio-wrapper`]: {
marginInlineEnd: 0,
},
},
[`table tr th${componentCls}-selection-column${componentCls}-cell-fix-left`]: {
zIndex: token.zIndexTableFixed + 1,
},
[`table tr th${componentCls}-selection-column::after`]: {
backgroundColor: 'transparent !important',
},
[`${componentCls}-selection`]: {
position: 'relative',
display: 'inline-flex',
flexDirection: 'column',
},
[`${componentCls}-selection-extra`]: {
position: 'absolute',
top: 0,
zIndex: 1,
cursor: 'pointer',
transition: `all ${token.motionDurationSlow}`,
marginInlineStart: '100%',
paddingInlineStart: `${token.tablePaddingHorizontal / 4}px`,
[iconCls]: {
color: tableHeaderIconColor,
fontSize: fontSizeIcon,
verticalAlign: 'baseline',
'&:hover': {
color: tableHeaderIconColorHover,
},
},
},
},
};
};
export default genSelectionStyle;

View File

@ -1,51 +0,0 @@
@import (reference) '../../style/themes/index';
@table-prefix-cls: ~'@{ant-prefix}-table';
.table-size(@size, @padding-vertical, @padding-horizontal, @font-size) {
.@{table-prefix-cls}.@{table-prefix-cls}-@{size} {
font-size: @font-size;
.@{table-prefix-cls}-title,
.@{table-prefix-cls}-footer,
.@{table-prefix-cls}-thead > tr > th,
.@{table-prefix-cls}-tbody > tr > td,
tfoot > tr > th,
tfoot > tr > td {
padding: @padding-vertical @padding-horizontal;
}
.@{table-prefix-cls}-filter-trigger {
margin-right: -(@padding-horizontal / 2);
}
.@{table-prefix-cls}-expanded-row-fixed {
margin: -@padding-vertical -@padding-horizontal;
}
.@{table-prefix-cls}-tbody {
// ========================= Nest Table ===========================
.@{table-prefix-cls}-wrapper:only-child {
.@{table-prefix-cls} {
margin: -@padding-vertical -@padding-horizontal -@padding-vertical (@padding-horizontal +
ceil((@font-size-sm * 1.4)));
}
}
}
// https://github.com/ant-design/ant-design/issues/35167
.@{table-prefix-cls}-selection-column {
padding-inline-start: (@padding-horizontal / 4);
}
}
}
// ================================================================
// = Middle =
// ================================================================
.table-size(~'middle', @table-padding-vertical-md, @table-padding-horizontal-md, @table-font-size-md);
// ================================================================
// = Small =
// ================================================================
.table-size(~'small', @table-padding-vertical-sm, @table-padding-horizontal-sm, @table-font-size-sm);

View File

@ -0,0 +1,68 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genSizeStyle: GenerateStyle<TableToken, CSSObject> = token => {
const { componentCls } = token;
const getSizeStyle = (
size: 'small' | 'middle',
paddingVertical: number,
paddingHorizontal: number,
fontSize: number,
) => ({
[`${componentCls}${componentCls}-${size}`]: {
fontSize,
[`
${componentCls}-title,
${componentCls}-footer,
${componentCls}-thead > tr > th,
${componentCls}-tbody > tr > td,
tfoot > tr > th,
tfoot > tr > td
`]: {
padding: `${paddingVertical}px ${paddingHorizontal}px`,
},
[`${componentCls}-filter-trigger`]: {
marginInlineEnd: `-${paddingHorizontal / 2}px`,
},
[`${componentCls}-expanded-row-fixed`]: {
margin: `-${paddingVertical}px -${paddingHorizontal}px`,
},
[`${componentCls}-tbody`]: {
// ========================= Nest Table ===========================
[`${componentCls}-wrapper:only-child ${componentCls}`]: {
marginBlock: `-${paddingVertical}px`,
marginInline: `${
token.tableExpandColumnWidth - paddingHorizontal
}px -${paddingHorizontal}px`,
},
},
// https://github.com/ant-design/ant-design/issues/35167
[`${componentCls}-selection-column`]: {
paddingInlineStart: `${paddingHorizontal / 4}px`,
},
},
});
return {
[`${componentCls}-wrapper`]: {
...getSizeStyle(
'middle',
token.tablePaddingVerticalMiddle,
token.tablePaddingHorizontalMiddle,
token.tableFontSizeMiddle,
),
...getSizeStyle(
'small',
token.tablePaddingVerticalSmall,
token.tablePaddingHorizontalSmall,
token.tableFontSizeSmall,
),
},
};
};
export default genSizeStyle;

View File

@ -0,0 +1,101 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genSorterStyle: GenerateStyle<TableToken, CSSObject> = token => {
const { componentCls, marginXXS, fontSizeIcon, tableHeaderIconColor, tableHeaderIconColorHover } =
token;
return {
[`${componentCls}-wrapper`]: {
[`${componentCls}-thead th${componentCls}-column-has-sorters`]: {
outline: 'none',
cursor: 'pointer',
transition: `all ${token.motionDurationSlow}`,
'&:hover': {
background: token.tableHeaderSortHoverBg,
'&::before': {
backgroundColor: 'transparent !important',
},
},
'&:focus-visible': {
color: token.colorPrimary,
},
// https://github.com/ant-design/ant-design/issues/30969
[`
&${componentCls}-cell-fix-left:hover,
&${componentCls}-cell-fix-right:hover
`]: {
background: token.tableFixedHeaderSortActiveBg,
},
},
[`${componentCls}-thead th${componentCls}-column-sort`]: {
background: token.tableHeaderSortBg,
'&::before': {
backgroundColor: 'transparent !important',
},
},
[`td${componentCls}-column-sort`]: {
background: token.tableBodySortBg,
},
[`${componentCls}-column-title`]: {
position: 'relative',
zIndex: 1,
flex: 1,
},
[`${componentCls}-column-sorters`]: {
display: 'flex',
flex: 'auto',
alignItems: 'center',
justifyContent: 'space-between',
'&::after': {
position: 'absolute',
inset: 0,
width: '100%',
height: '100%',
content: '""',
},
},
[`${componentCls}-column-sorter`]: {
marginInlineStart: marginXXS,
color: tableHeaderIconColor,
fontSize: 0,
transition: `color ${token.motionDurationSlow}`,
'&-inner': {
display: 'inline-flex',
flexDirection: 'column',
alignItems: 'center',
},
'&-up, &-down': {
fontSize: fontSizeIcon,
'&.active': {
color: token.colorPrimary,
},
},
[`${componentCls}-column-sorter-up + ${componentCls}-column-sorter-down`]: {
marginTop: '-0.3em',
},
},
[`${componentCls}-column-sorters:hover ${componentCls}-column-sorter`]: {
color: tableHeaderIconColorHover,
},
},
};
};
export default genSorterStyle;

View File

@ -0,0 +1,59 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genStickyStyle: GenerateStyle<TableToken, CSSObject> = token => {
const {
componentCls,
opacityLoading,
tableScrollThumbBg,
tableScrollThumbBgHover,
tableScrollThumbSize,
tableScrollBg,
zIndexTableSticky,
} = token;
const tableBorder = `${token.lineWidth}px ${token.lineType} ${token.tableBorderColor}`;
return {
[`${componentCls}-wrapper`]: {
[`${componentCls}-sticky`]: {
'&-holder': {
position: 'sticky',
zIndex: zIndexTableSticky,
background: token.colorBgContainer,
},
'&-scroll': {
position: 'sticky',
bottom: 0,
height: `${tableScrollThumbSize}px !important`,
zIndex: zIndexTableSticky,
display: 'flex',
alignItems: 'center',
background: tableScrollBg,
borderTop: tableBorder,
opacity: opacityLoading,
'&:hover': {
transformOrigin: 'center bottom',
},
// fake scrollbar style of sticky
'&-bar': {
height: tableScrollThumbSize,
backgroundColor: tableScrollThumbBg,
borderRadius: 100,
transition: `all ${token.motionDurationSlow}, transform none`,
position: 'absolute',
bottom: 0,
'&:hover, &-active': {
backgroundColor: tableScrollThumbBgHover,
},
},
},
},
},
};
};
export default genStickyStyle;

View File

@ -0,0 +1,29 @@
import type { CSSObject } from '../../_util/cssinjs';
import type { GenerateStyle } from '../../theme/internal';
import type { TableToken } from './index';
const genSummaryStyle: GenerateStyle<TableToken, CSSObject> = token => {
const { componentCls, lineWidth, tableBorderColor } = token;
const tableBorder = `${lineWidth}px ${token.lineType} ${tableBorderColor}`;
return {
[`${componentCls}-wrapper`]: {
[`${componentCls}-summary`]: {
position: 'relative',
zIndex: token.zIndexTableFixed,
background: token.tableBg,
'> tr': {
'> th, > td': {
borderBottom: tableBorder,
},
},
},
[`div${componentCls}-summary`]: {
boxShadow: `0 -${lineWidth}px 0 ${tableBorderColor}`,
},
},
};
};
export default genSummaryStyle;

View File

@ -37,7 +37,7 @@ import type { ComponentToken as SliderComponentToken } from '../../slider/style'
import type { ComponentToken as SpaceComponentToken } from '../../space/style'; import type { ComponentToken as SpaceComponentToken } from '../../space/style';
import type { ComponentToken as SpinComponentToken } from '../../spin/style'; import type { ComponentToken as SpinComponentToken } from '../../spin/style';
import type { ComponentToken as StepsComponentToken } from '../../steps/style'; import type { ComponentToken as StepsComponentToken } from '../../steps/style';
// import type { ComponentToken as TableComponentToken } from '../../table/style'; import type { ComponentToken as TableComponentToken } from '../../table/style';
// import type { ComponentToken as TabsComponentToken } from '../../tabs/style'; // import type { ComponentToken as TabsComponentToken } from '../../tabs/style';
import type { ComponentToken as TagComponentToken } from '../../tag/style'; import type { ComponentToken as TagComponentToken } from '../../tag/style';
import type { ComponentToken as TimelineComponentToken } from '../../timeline/style'; import type { ComponentToken as TimelineComponentToken } from '../../timeline/style';
@ -109,7 +109,7 @@ export interface ComponentTokenMap {
Message?: MessageComponentToken; Message?: MessageComponentToken;
Upload?: UploadComponentToken; Upload?: UploadComponentToken;
Tooltip?: TooltipComponentToken; Tooltip?: TooltipComponentToken;
// Table?: TableComponentToken; Table?: TableComponentToken;
Space?: SpaceComponentToken; Space?: SpaceComponentToken;
Progress?: ProgressComponentToken; Progress?: ProgressComponentToken;
// Tour?: TourComponentToken; // Tour?: TourComponentToken;