mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 09:26:06 +08:00
feat: List grid support more column count (#23630)
* list grid * 🎬 update demo/useBreakpoint.md * List grid support all number * refactor object entries * docs: update List grid API * ✅ fix snapshot * fix ci * use max-width instead of flex %
This commit is contained in:
parent
2da7e29198
commit
053497724d
@ -1227,14 +1227,4 @@ exports[`renders ./components/grid/demo/sort.md correctly 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/grid/demo/useBreakpoint.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-row"
|
||||
>
|
||||
<div
|
||||
class="ant-col"
|
||||
>
|
||||
Current break point:
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
exports[`renders ./components/grid/demo/useBreakpoint.md correctly 1`] = `null`;
|
||||
|
@ -12,23 +12,23 @@ title: useBreakpoint Hook
|
||||
Use `useBreakpoint` Hook povide personalized layout.
|
||||
|
||||
```jsx
|
||||
import { Row, Col, Grid } from 'antd';
|
||||
import { Grid, Tag } from 'antd';
|
||||
|
||||
const { useBreakpoint } = Grid;
|
||||
|
||||
function UseBreakpointDemo() {
|
||||
const screens = useBreakpoint();
|
||||
|
||||
return (
|
||||
<Row>
|
||||
<Col>
|
||||
Current break point:
|
||||
{Object.entries(screens)
|
||||
.filter(screen => !!screen[1])
|
||||
.map(screen => screen[0])
|
||||
.join(' ')}
|
||||
</Col>
|
||||
</Row>
|
||||
<>
|
||||
Current break point:{' '}
|
||||
{Object.entries(screens)
|
||||
.filter(screen => !!screen[1])
|
||||
.map(screen => (
|
||||
<Tag color="blue" key={screen[0]}>
|
||||
{screen[0]}
|
||||
</Tag>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { ListGridType, ColumnType, ListContext } from './index';
|
||||
import { ListGridType, ListContext } from './index';
|
||||
import { Col } from '../grid';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import { cloneElement } from '../_util/reactNode';
|
||||
@ -14,6 +14,7 @@ export interface ListItemProps extends React.HTMLAttributes<HTMLDivElement> {
|
||||
extra?: React.ReactNode;
|
||||
actions?: React.ReactNode[];
|
||||
grid?: ListGridType;
|
||||
colStyle?: React.CSSProperties;
|
||||
}
|
||||
|
||||
export interface ListItemMetaProps {
|
||||
@ -54,10 +55,6 @@ export const Meta: React.FC<ListItemMetaProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
function getGrid(grid: ListGridType, t: ColumnType) {
|
||||
return grid[t] && Math.floor(24 / grid[t]!);
|
||||
}
|
||||
|
||||
export interface ListItemTypeProps extends React.FC<ListItemProps> {
|
||||
Meta: typeof Meta;
|
||||
}
|
||||
@ -85,7 +82,15 @@ const Item: ListItemTypeProps = props => {
|
||||
return !isItemContainsTextNodeAndNotSingular();
|
||||
};
|
||||
|
||||
const { prefixCls: customizePrefixCls, children, actions, extra, className, ...others } = props;
|
||||
const {
|
||||
prefixCls: customizePrefixCls,
|
||||
children,
|
||||
actions,
|
||||
extra,
|
||||
className,
|
||||
colStyle,
|
||||
...others
|
||||
} = props;
|
||||
const prefixCls = getPrefixCls('list', customizePrefixCls);
|
||||
const actionsContent = actions && actions.length > 0 && (
|
||||
<ul className={`${prefixCls}-item-action`} key="actions">
|
||||
@ -98,9 +103,9 @@ const Item: ListItemTypeProps = props => {
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
const Tag = grid ? 'div' : 'li';
|
||||
const Element = grid ? 'div' : 'li';
|
||||
const itemChildren = (
|
||||
<Tag
|
||||
<Element
|
||||
{...(others as any)} // `li` element `onCopy` prop args is not same as `div`
|
||||
className={classNames(`${prefixCls}-item`, className, {
|
||||
[`${prefixCls}-item-no-flex`]: !isFlexMode(),
|
||||
@ -117,19 +122,11 @@ const Item: ListItemTypeProps = props => {
|
||||
</div>,
|
||||
]
|
||||
: [children, actionsContent, cloneElement(extra, { key: 'extra' })]}
|
||||
</Tag>
|
||||
</Element>
|
||||
);
|
||||
|
||||
return grid ? (
|
||||
<Col
|
||||
span={getGrid(grid, 'column')}
|
||||
xs={getGrid(grid, 'xs')}
|
||||
sm={getGrid(grid, 'sm')}
|
||||
md={getGrid(grid, 'md')}
|
||||
lg={getGrid(grid, 'lg')}
|
||||
xl={getGrid(grid, 'xl')}
|
||||
xxl={getGrid(grid, 'xxl')}
|
||||
>
|
||||
<Col flex={1} style={colStyle}>
|
||||
{itemChildren}
|
||||
</Col>
|
||||
) : (
|
||||
|
@ -182,8 +182,8 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
style="margin-left:-8px;margin-right:-8px"
|
||||
>
|
||||
<div
|
||||
class="ant-col ant-col-6"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;width:25%;max-width:25%;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
@ -213,8 +213,8 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-col-6"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;width:25%;max-width:25%;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
@ -244,8 +244,8 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-col-6"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;width:25%;max-width:25%;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
@ -275,8 +275,8 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-col-6"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;width:25%;max-width:25%;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
@ -451,8 +451,8 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
style="margin-left:-8px;margin-right:-8px"
|
||||
>
|
||||
<div
|
||||
class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
@ -482,8 +482,8 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
@ -513,8 +513,8 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
@ -544,8 +544,8 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
@ -575,8 +575,8 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
@ -606,8 +606,8 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col ant-col-xs-24 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4 ant-col-xxl-8"
|
||||
style="padding-left:8px;padding-right:8px"
|
||||
class="ant-col"
|
||||
style="padding-left:8px;padding-right:8px;flex:1 1 auto"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
|
@ -44,16 +44,16 @@ More about pagination, please check [`Pagination`](/components/pagination/).
|
||||
|
||||
### List grid props
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| column | column of grid, [optional number](https://github.com/ant-design/ant-design/blob/a7f17b4cdebbca07b3b9ce5698de61e772d46237/components/list/index.tsx#L16) | number | - | |
|
||||
| gutter | spacing between grid | number | 0 | |
|
||||
| xs | `<576px` column of grid | number | - | |
|
||||
| sm | `≥576px` column of grid | number | - | |
|
||||
| md | `≥768px` column of grid | number | - | |
|
||||
| lg | `≥992px` column of grid | number | - | |
|
||||
| xl | `≥1200px` column of grid | number | - | |
|
||||
| xxl | `≥1600px` column of grid | number | - | |
|
||||
| Property | Description | Type | Default | Version |
|
||||
| -------- | ------------------------ | ------ | ------- | ------- |
|
||||
| column | column of grid | number | - | |
|
||||
| gutter | spacing between grid | number | 0 | |
|
||||
| xs | `<576px` column of grid | number | - | |
|
||||
| sm | `≥576px` column of grid | number | - | |
|
||||
| md | `≥768px` column of grid | number | - | |
|
||||
| lg | `≥992px` column of grid | number | - | |
|
||||
| xl | `≥1200px` column of grid | number | - | |
|
||||
| xxl | `≥1600px` column of grid | number | - | |
|
||||
|
||||
### List.Item
|
||||
|
||||
|
@ -2,16 +2,16 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'omit.js';
|
||||
import Spin, { SpinProps } from '../spin';
|
||||
import useBreakpoint from '../grid/hooks/useBreakpoint';
|
||||
import { Breakpoint, responsiveArray } from '../_util/responsiveObserve';
|
||||
import { RenderEmptyHandler, ConfigContext } from '../config-provider';
|
||||
|
||||
import Pagination, { PaginationConfig } from '../pagination';
|
||||
import { Row } from '../grid';
|
||||
|
||||
import Item from './Item';
|
||||
|
||||
export { ListItemProps, ListItemMetaProps } from './Item';
|
||||
|
||||
export type ColumnCount = 1 | 2 | 3 | 4 | 6 | 8 | 12 | 24;
|
||||
export type ColumnCount = number;
|
||||
|
||||
export type ColumnType = 'gutter' | 'column' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
|
||||
|
||||
@ -218,20 +218,40 @@ function List<T>({ pagination, ...props }: ListProps<T>) {
|
||||
}
|
||||
}
|
||||
|
||||
let childrenContent;
|
||||
childrenContent = isLoading && <div style={{ minHeight: 53 }} />;
|
||||
const screens = useBreakpoint();
|
||||
const currentBreakpoint = React.useMemo(() => {
|
||||
for (let i = 0; i < responsiveArray.length; i += 1) {
|
||||
const breakpoint: Breakpoint = responsiveArray[i];
|
||||
if (screens[breakpoint]) {
|
||||
return breakpoint;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}, [screens]);
|
||||
|
||||
const colStyle = React.useMemo(() => {
|
||||
if (!grid) {
|
||||
return undefined;
|
||||
}
|
||||
const columnCount =
|
||||
currentBreakpoint && grid[currentBreakpoint] ? grid[currentBreakpoint] : grid.column;
|
||||
if (columnCount) {
|
||||
return {
|
||||
width: `${100 / columnCount}%`,
|
||||
maxWidth: `${100 / columnCount}%`,
|
||||
};
|
||||
}
|
||||
}, [grid?.column, currentBreakpoint]);
|
||||
|
||||
let childrenContent = isLoading && <div style={{ minHeight: 53 }} />;
|
||||
if (splitDataSource.length > 0) {
|
||||
const items = splitDataSource.map((item: any, index: number) => renderItem(item, index));
|
||||
|
||||
const childrenList: Array<React.ReactNode> = [];
|
||||
React.Children.forEach(items, (child: any, index) => {
|
||||
childrenList.push(
|
||||
React.cloneElement(child, {
|
||||
key: keys[index],
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
const childrenList = React.Children.map(items, (child: any, index) =>
|
||||
React.cloneElement(child, {
|
||||
key: keys[index],
|
||||
colStyle,
|
||||
}),
|
||||
);
|
||||
childrenContent = grid ? (
|
||||
<Row gutter={grid.gutter}>{childrenList}</Row>
|
||||
) : (
|
||||
|
@ -44,16 +44,16 @@ cols: 1
|
||||
|
||||
### List grid props
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| column | 列数,[可选值](https://github.com/ant-design/ant-design/blob/a7f17b4cdebbca07b3b9ce5698de61e772d46237/components/list/index.tsx#L16) | number | - | |
|
||||
| gutter | 栅格间隔 | number | 0 | |
|
||||
| xs | `<576px` 展示的列数 | number | - | |
|
||||
| sm | `≥576px` 展示的列数 | number | - | |
|
||||
| md | `≥768px` 展示的列数 | number | - | |
|
||||
| lg | `≥992px` 展示的列数 | number | - | |
|
||||
| xl | `≥1200px` 展示的列数 | number | - | |
|
||||
| xxl | `≥1600px` 展示的列数 | number | - | |
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| ------ | -------------------- | ------ | ------ | ---- |
|
||||
| column | 列数 | number | - | |
|
||||
| gutter | 栅格间隔 | number | 0 | |
|
||||
| xs | `<576px` 展示的列数 | number | - | |
|
||||
| sm | `≥576px` 展示的列数 | number | - | |
|
||||
| md | `≥768px` 展示的列数 | number | - | |
|
||||
| lg | `≥992px` 展示的列数 | number | - | |
|
||||
| xl | `≥1200px` 展示的列数 | number | - | |
|
||||
| xxl | `≥1600px` 展示的列数 | number | - | |
|
||||
|
||||
### List.Item
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user