feat: Space add wrap (#27910)

* feat: Space add wrap

* improve

* fix

* Update index.tsx

* change doc

* change docs

* change docs

* 😂

* improve

* change doc

* improve code

* Update Item.tsx
This commit is contained in:
Tom Xu 2020-11-27 13:40:40 +08:00 committed by GitHub
parent d86c8c857e
commit 94f2ae9e87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 369 additions and 26 deletions

View File

@ -1,46 +1,44 @@
import * as React from 'react';
import { LastIndexContext } from '.';
import { SizeType } from '../config-provider/SizeContext';
const spaceSize = {
small: 8,
middle: 16,
large: 24,
};
import { SpaceContext } from '.';
export interface ItemProps {
className: string;
children: React.ReactNode;
index: number;
direction?: 'horizontal' | 'vertical';
size?: SizeType | number;
marginDirection: 'marginLeft' | 'marginRight';
split?: string | React.ReactNode;
wrap?: boolean;
}
export default function Item({
className,
direction,
index,
size,
marginDirection,
children,
split,
wrap,
}: ItemProps) {
const latestIndex = React.useContext(LastIndexContext);
const { horizontalSize, verticalSize, latestIndex } = React.useContext(SpaceContext);
let style: React.CSSProperties = {};
if (direction === 'vertical') {
if (index < latestIndex) {
style = { marginBottom: horizontalSize / (split ? 2 : 1) };
}
} else {
style = {
...(index < latestIndex && { [marginDirection]: horizontalSize / (split ? 2 : 1) }),
...(wrap && { paddingBottom: verticalSize }),
};
}
if (children === null || children === undefined) {
return null;
}
const style =
index >= latestIndex
? {}
: {
[direction === 'vertical' ? 'marginBottom' : marginDirection]:
((typeof size === 'string' ? spaceSize[size] : size) ?? 0) / (split ? 2 : 1),
};
return (
<>
<div className={className} style={style}>

View File

@ -657,3 +657,271 @@ exports[`renders ./components/space/demo/vertical.md correctly 1`] = `
</div>
</div>
`;
exports[`renders ./components/space/demo/wrap.md correctly 1`] = `
<div
class="ant-space ant-space-horizontal ant-space-align-center"
style="flex-wrap:wrap;margin-bottom:-16px"
>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="margin-right:8px;padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
<div
class="ant-space-item"
style="padding-bottom:16px"
>
<button
class="ant-btn"
type="button"
>
<span>
Button
</span>
</button>
</div>
</div>
`;

View File

@ -0,0 +1,31 @@
---
order: 98
title:
zh-CN: 自动换行
en-US: Wrap
---
## zh-CN
自动换行。
## en-US
Auto wrap line.
```jsx
import { Space, Button } from 'antd';
const Demo = () => {
return (
<Space size={[8, 16]} wrap>
{new Array(20).fill(null).map((_, index) => (
// eslint-disable-next-line react/no-array-index-key
<Button key={index}>Button</Button>
))}
</Space>
);
};
ReactDOM.render(<Demo />, mountNode);
```

View File

@ -18,5 +18,10 @@ Avoid components clinging together and set a unified space.
| --- | --- | --- | --- | --- |
| align | Align items | `start` \| `end` \|`center` \|`baseline` | - | 4.2.0 |
| direction | The space direction | `vertical` \| `horizontal` | `horizontal` | 4.1.0 |
| size | The space size | `small` \| `middle` \| `large` \| number | `small` | 4.1.0 |
| size | The space size | [Size](#Size) \| [Size\[\]](#Size) | `small` | 4.1.0 \| Array: 4.9.0 |
| split | Set split | ReactNode | - | 4.7.0 |
| wrap | Auto wrap line, when `horizontal` effective | boolean | false | 4.9.0 |
### Size
`'small' | 'middle' | 'large' | number`

View File

@ -5,17 +5,34 @@ import { ConfigContext } from '../config-provider';
import { SizeType } from '../config-provider/SizeContext';
import Item from './Item';
export const LastIndexContext = React.createContext(0);
export const SpaceContext = React.createContext({
latestIndex: 0,
horizontalSize: 0,
verticalSize: 0,
});
export type SpaceSize = SizeType | number;
export interface SpaceProps {
prefixCls?: string;
className?: string;
style?: React.CSSProperties;
size?: SizeType | number;
size?: SpaceSize | [SpaceSize, SpaceSize];
direction?: 'horizontal' | 'vertical';
// No `stretch` since many components do not support that.
align?: 'start' | 'end' | 'center' | 'baseline';
split?: React.ReactNode;
wrap?: boolean;
}
const spaceSize = {
small: 8,
middle: 16,
large: 24,
};
function getNumberSize(size: SpaceSize) {
return typeof size === 'string' ? spaceSize[size] : size || 0;
}
const Space: React.FC<SpaceProps> = props => {
@ -29,9 +46,19 @@ const Space: React.FC<SpaceProps> = props => {
direction = 'horizontal',
prefixCls: customizePrefixCls,
split,
style,
wrap = false,
...otherProps
} = props;
const [horizontalSize, verticalSize] = React.useMemo(
() =>
((Array.isArray(size) ? size : [size, size]) as [SpaceSize, SpaceSize]).map(item =>
getNumberSize(item),
),
[size],
);
const childNodes = toArray(children, { keepEmpty: true });
if (childNodes.length === 0) {
@ -67,10 +94,10 @@ const Space: React.FC<SpaceProps> = props => {
className={itemClassName}
key={`${itemClassName}-${i}`}
direction={direction}
size={size}
index={i}
marginDirection={marginDirection}
split={split}
wrap={wrap}
>
{child}
</Item>
@ -79,8 +106,17 @@ const Space: React.FC<SpaceProps> = props => {
});
return (
<div className={cn} {...otherProps}>
<LastIndexContext.Provider value={latestIndex}>{nodes}</LastIndexContext.Provider>
<div
className={cn}
style={{
...(wrap && { flexWrap: 'wrap', marginBottom: -verticalSize }),
...style,
}}
{...otherProps}
>
<SpaceContext.Provider value={{ horizontalSize, verticalSize, latestIndex }}>
{nodes}
</SpaceContext.Provider>
</div>
);
};

View File

@ -22,5 +22,10 @@ cover: https://gw.alipayobjects.com/zos/antfincdn/wc6%263gJ0Y8/Space.svg
| --- | --- | --- | --- | --- |
| align | 对齐方式 | `start` \| `end` \|`center` \|`baseline` | - | 4.2.0 |
| direction | 间距方向 | `vertical` \| `horizontal` | `horizontal` | 4.1.0 |
| size | 间距大小 | `small` \| `middle` \| `large` \| number | `small` | 4.1.0 |
| size | 间距大小 | [Size](#Size) \| [Size\[\]](#Size) | `small` | 4.1.0 \| Array: 4.9.0 |
| split | 设置拆分 | ReactNode | - | 4.7.0 |
| wrap | 是否自动换行,仅在 `horizontal` 时有效 | boolean | false | 4.9.0 |
### Size
`'small' | 'middle' | 'large' | number`