mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 20:49:53 +08:00
feat: Responsive table columns (#23298)
This commit is contained in:
parent
7935651899
commit
f09686d3df
@ -3,14 +3,17 @@ import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import RcTable from 'rc-table';
|
||||
import { TableProps as RcTableProps, INTERNAL_HOOKS } from 'rc-table/lib/Table';
|
||||
import { convertChildrenToColumns } from 'rc-table/lib/hooks/useColumns';
|
||||
import Spin, { SpinProps } from '../spin';
|
||||
import Pagination, { PaginationConfig } from '../pagination';
|
||||
import { ConfigContext } from '../config-provider/context';
|
||||
import usePagination, { DEFAULT_PAGE_SIZE, getPaginationParam } from './hooks/usePagination';
|
||||
import useLazyKVMap from './hooks/useLazyKVMap';
|
||||
import { Breakpoint } from '../_util/responsiveObserve';
|
||||
import {
|
||||
TableRowSelection,
|
||||
GetRowKey,
|
||||
ColumnType,
|
||||
ColumnsType,
|
||||
TableCurrentDataSource,
|
||||
SorterResult,
|
||||
@ -33,6 +36,7 @@ import SizeContext, { SizeType } from '../config-provider/SizeContext';
|
||||
import Column from './Column';
|
||||
import ColumnGroup from './ColumnGroup';
|
||||
import warning from '../_util/warning';
|
||||
import useBreakpoint from '../grid/hooks/useBreakpoint';
|
||||
|
||||
export { ColumnsType, TablePaginationConfig };
|
||||
|
||||
@ -113,7 +117,17 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
|
||||
showSorterTooltip = true,
|
||||
} = props;
|
||||
|
||||
const tableProps = omit(props, ['className', 'style']) as TableProps<RecordType>;
|
||||
const screens = useBreakpoint();
|
||||
const mergedColumns = React.useMemo(() => {
|
||||
const matched = new Set(Object.keys(screens).filter((m: Breakpoint) => screens[m]));
|
||||
|
||||
return (columns || convertChildrenToColumns(children)).filter(
|
||||
(c: ColumnType<RecordType>) =>
|
||||
!c.responsive || c.responsive.some((r: Breakpoint) => matched.has(r)),
|
||||
);
|
||||
}, [children, columns, screens]);
|
||||
|
||||
const tableProps = omit(props, ['className', 'style', 'columns']) as TableProps<RecordType>;
|
||||
|
||||
const size = React.useContext(SizeContext);
|
||||
const { locale: contextLocale = defaultLocale, renderEmpty, direction } = React.useContext(
|
||||
@ -222,8 +236,7 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
|
||||
};
|
||||
const [transformSorterColumns, sortStates, sorterTitleProps, getSorters] = useSorter<RecordType>({
|
||||
prefixCls,
|
||||
columns,
|
||||
children,
|
||||
mergedColumns,
|
||||
onSorterChange,
|
||||
sortDirections: sortDirections || ['ascend', 'descend'],
|
||||
tableLocale,
|
||||
@ -255,8 +268,7 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
|
||||
prefixCls,
|
||||
locale: tableLocale,
|
||||
dropdownPrefixCls,
|
||||
columns,
|
||||
children,
|
||||
mergedColumns,
|
||||
onFilterChange,
|
||||
getPopupContainer,
|
||||
});
|
||||
@ -313,8 +325,7 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
|
||||
return mergedData;
|
||||
}
|
||||
|
||||
const currentPageData = mergedData.slice((current - 1) * pageSize, current * pageSize);
|
||||
return currentPageData;
|
||||
return mergedData.slice((current - 1) * pageSize, current * pageSize);
|
||||
}, [
|
||||
!!pagination,
|
||||
mergedData,
|
||||
@ -439,6 +450,7 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
|
||||
{topPaginationNode}
|
||||
<RcTable<RecordType>
|
||||
{...tableProps}
|
||||
columns={mergedColumns}
|
||||
direction={direction}
|
||||
expandable={mergedExpandable}
|
||||
prefixCls={prefixCls}
|
||||
|
@ -11541,6 +11541,141 @@ exports[`renders ./components/table/demo/resizable-column.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/table/demo/responsive.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-table-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-nested-loading"
|
||||
>
|
||||
<div
|
||||
class="ant-spin-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table"
|
||||
>
|
||||
<div
|
||||
class="ant-table-container"
|
||||
>
|
||||
<div
|
||||
class="ant-table-content"
|
||||
>
|
||||
<table
|
||||
style="table-layout:auto"
|
||||
>
|
||||
<colgroup />
|
||||
<thead
|
||||
class="ant-table-thead"
|
||||
>
|
||||
<tr>
|
||||
<th
|
||||
class="ant-table-cell"
|
||||
>
|
||||
Name (all screens)
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody
|
||||
class="ant-table-tbody"
|
||||
>
|
||||
<tr
|
||||
class="ant-table-row ant-table-row-level-0"
|
||||
data-row-key="1"
|
||||
>
|
||||
<td
|
||||
class="ant-table-cell"
|
||||
>
|
||||
<a>
|
||||
John Brown
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
class="ant-pagination ant-table-pagination ant-table-pagination-right"
|
||||
unselectable="unselectable"
|
||||
>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-prev ant-pagination-disabled"
|
||||
title="Previous Page"
|
||||
>
|
||||
<a
|
||||
class="ant-pagination-item-link"
|
||||
disabled=""
|
||||
>
|
||||
<span
|
||||
aria-label="left"
|
||||
class="anticon anticon-left"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="left"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<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"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class="ant-pagination-item ant-pagination-item-1 ant-pagination-item-active"
|
||||
tabindex="0"
|
||||
title="1"
|
||||
>
|
||||
<a>
|
||||
1
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
aria-disabled="true"
|
||||
class="ant-pagination-next ant-pagination-disabled"
|
||||
title="Next Page"
|
||||
>
|
||||
<a
|
||||
class="ant-pagination-item-link"
|
||||
disabled=""
|
||||
>
|
||||
<span
|
||||
aria-label="right"
|
||||
class="anticon anticon-right"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
data-icon="right"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/table/demo/row-selection.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
|
50
components/table/demo/responsive.md
Normal file
50
components/table/demo/responsive.md
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
order: 31
|
||||
title:
|
||||
zh-CN: 响应式
|
||||
en-US: Responsive
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
响应式配置列的展示。
|
||||
|
||||
## en-US
|
||||
|
||||
Responsive columns.
|
||||
|
||||
```jsx
|
||||
import { Table } from 'antd';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: 'Name (all screens)',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
render: text => <a>{text}</a>,
|
||||
},
|
||||
{
|
||||
title: 'Age (medium screen or bigger)',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
responsive: ['md'],
|
||||
},
|
||||
{
|
||||
title: 'Address (large screen or bigger)',
|
||||
dataIndex: 'address',
|
||||
key: 'address',
|
||||
responsive: ['lg'],
|
||||
},
|
||||
];
|
||||
|
||||
const data = [
|
||||
{
|
||||
key: '1',
|
||||
name: 'John Brown',
|
||||
age: 32,
|
||||
address: 'New York No. 1 Lake Park',
|
||||
},
|
||||
];
|
||||
|
||||
ReactDOM.render(<Table columns={columns} dataSource={data} />, mountNode);
|
||||
```
|
@ -1,5 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import { convertChildrenToColumns } from 'rc-table/lib/hooks/useColumns';
|
||||
import {
|
||||
TransformColumns,
|
||||
ColumnsType,
|
||||
@ -162,8 +161,7 @@ export function getFilterData<RecordType>(
|
||||
interface FilterConfig<RecordType> {
|
||||
prefixCls: string;
|
||||
dropdownPrefixCls: string;
|
||||
columns?: ColumnsType<RecordType>;
|
||||
children?: React.ReactNode;
|
||||
mergedColumns: ColumnsType<RecordType>;
|
||||
locale: TableLocale;
|
||||
onFilterChange: (
|
||||
filters: Record<string, Key[] | null>,
|
||||
@ -175,8 +173,7 @@ interface FilterConfig<RecordType> {
|
||||
function useFilter<RecordType>({
|
||||
prefixCls,
|
||||
dropdownPrefixCls,
|
||||
columns,
|
||||
children,
|
||||
mergedColumns,
|
||||
onFilterChange,
|
||||
getPopupContainer,
|
||||
locale: tableLocale,
|
||||
@ -185,10 +182,6 @@ function useFilter<RecordType>({
|
||||
FilterState<RecordType>[],
|
||||
() => Record<string, Key[] | null>,
|
||||
] {
|
||||
const mergedColumns = React.useMemo(() => {
|
||||
return columns || convertChildrenToColumns(children);
|
||||
}, [children, columns]);
|
||||
|
||||
const [filterStates, setFilterStates] = React.useState<FilterState<RecordType>[]>(
|
||||
collectFilterStates(mergedColumns, true),
|
||||
);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { convertChildrenToColumns } from 'rc-table/lib/hooks/useColumns';
|
||||
import CaretDownOutlined from '@ant-design/icons/CaretDownOutlined';
|
||||
import CaretUpOutlined from '@ant-design/icons/CaretUpOutlined';
|
||||
import {
|
||||
@ -300,8 +299,7 @@ export function getSortData<RecordType>(
|
||||
|
||||
interface SorterConfig<RecordType> {
|
||||
prefixCls: string;
|
||||
columns?: ColumnsType<RecordType>;
|
||||
children?: React.ReactNode;
|
||||
mergedColumns: ColumnsType<RecordType>;
|
||||
onSorterChange: (
|
||||
sorterResult: SorterResult<RecordType> | SorterResult<RecordType>[],
|
||||
sortStates: SortState<RecordType>[],
|
||||
@ -313,8 +311,7 @@ interface SorterConfig<RecordType> {
|
||||
|
||||
export default function useFilterSorter<RecordType>({
|
||||
prefixCls,
|
||||
columns,
|
||||
children,
|
||||
mergedColumns,
|
||||
onSorterChange,
|
||||
sortDirections,
|
||||
tableLocale,
|
||||
@ -325,10 +322,6 @@ export default function useFilterSorter<RecordType>({
|
||||
ColumnTitleProps<RecordType>,
|
||||
() => SorterResult<RecordType> | SorterResult<RecordType>[],
|
||||
] {
|
||||
const mergedColumns = React.useMemo(() => {
|
||||
return columns || convertChildrenToColumns(children);
|
||||
}, [children, columns]);
|
||||
|
||||
const [sortStates, setSortStates] = React.useState<SortState<RecordType>[]>(
|
||||
collectSortStates(mergedColumns, true),
|
||||
);
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
} from 'rc-table/lib/interface';
|
||||
import { CheckboxProps } from '../checkbox';
|
||||
import { PaginationConfig } from '../pagination';
|
||||
import { Breakpoint } from '../_util/responsiveObserve';
|
||||
|
||||
export { GetRowKey, ExpandableConfig };
|
||||
|
||||
@ -95,6 +96,9 @@ export interface ColumnType<RecordType> extends RcColumnType<RecordType> {
|
||||
onFilter?: (value: string | number | boolean, record: RecordType) => boolean;
|
||||
filterDropdownVisible?: boolean;
|
||||
onFilterDropdownVisibleChange?: (visible: boolean) => void;
|
||||
|
||||
// Responsive
|
||||
responsive?: Breakpoint[];
|
||||
}
|
||||
|
||||
export interface ColumnGroupType<RecordType> extends Omit<ColumnType<RecordType>, 'dataIndex'> {
|
||||
|
@ -3,6 +3,7 @@ import './index.less';
|
||||
|
||||
// style dependencies
|
||||
// deps-lint-skip: menu
|
||||
// deps-lint-skip: grid
|
||||
import '../../button/style';
|
||||
import '../../empty/style';
|
||||
import '../../radio/style';
|
||||
|
Loading…
Reference in New Issue
Block a user